From a41398253651d8fd4764e5ac8c12aa19378955ae Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 4 Aug 2020 23:58:00 -0300 Subject: [PATCH 001/144] First pass cleanup of Attachable header and cpp. Some TODOs to deal with still. Minor naming change in HDFirearm to make it match. --- Entities/Attachable.cpp | 1005 +++++++++++++------------------------ Entities/Attachable.h | 1047 ++++++++++++++------------------------- Entities/HDFirearm.h | 2 +- 3 files changed, 733 insertions(+), 1321 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 14b00f67f..057726375 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -1,674 +1,369 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// File: Attachable.cpp -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Source file for the Attachable class. -// Project: Retro Terrain Engine -// Author(s): Daniel Tabar -// data@datarealms.com -// http://www.datarealms.com - - -////////////////////////////////////////////////////////////////////////////////////////// -// Inclusions of header files - #include "Attachable.h" #include "AtomGroup.h" #include "PresetMan.h" #include "MovableMan.h" #include "AEmitter.h" #include "Actor.h" -#include "ConsoleMan.h" namespace RTE { -ConcreteClassInfo(Attachable, MOSRotating, 0) - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Clear -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Clears all the member variables of this Attachable, effectively -// resetting the members of this abstraction level only. - -void Attachable::Clear() -{ - m_pParent = 0; - m_ParentOffset.Reset(); - m_JointStrength = 10; - m_JointStiffness = 1.0; - m_pBreakWound = 0; - m_JointOffset.Reset(); - m_JointPos.Reset(); - m_RotTarget.Reset(); - m_AtomSubgroupID = -1; - m_DrawAfterParent = true; - m_DamageCount = 0; - m_OnlyLinForces = false; - m_InheritsRotAngle = true; - m_CanCollideWithTerrainWhenAttached = false; - m_IsCollidingWithTerrainWhileAttached = false; - m_DeleteWithParent = false; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes the MOSParticle object ready for use. - -int Attachable::Create() -{ - if (MOSRotating::Create() < 0) - return -1; - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Creates a Attachable to be identical to another, by deep copy. - -int Attachable::Create(const Attachable &reference) -{ - MOSRotating::Create(reference); - - m_pParent = reference.m_pParent; - m_ParentOffset = reference.m_ParentOffset; - m_JointStrength = reference.m_JointStrength; - m_JointStiffness = reference.m_JointStiffness; - m_pBreakWound = reference.m_pBreakWound; - m_JointOffset = reference.m_JointOffset; - m_JointPos = reference.m_JointPos; - m_RotTarget = reference.m_RotTarget; - m_AtomSubgroupID = reference.m_AtomSubgroupID; - m_DrawAfterParent = reference.m_DrawAfterParent; - m_DamageCount = reference.m_DamageCount; - m_OnlyLinForces = reference.m_OnlyLinForces; - m_InheritsRotAngle = reference.m_InheritsRotAngle; - m_CanCollideWithTerrainWhenAttached = reference.m_CanCollideWithTerrainWhenAttached; - m_DeleteWithParent = reference.m_DeleteWithParent; - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: ReadProperty -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Reads a property value from a reader stream. If the name isn't -// recognized by this class, then ReadProperty of the parent class -// is called. If the property isn't recognized by any of the base classes, -// false is returned, and the reader's position is untouched. - -int Attachable::ReadProperty(std::string propName, Reader &reader) -{ - if (propName == "ParentOffset") - reader >> m_ParentOffset; - else if (propName == "JointStrength" || propName == "Strength") - reader >> m_JointStrength; - else if (propName == "JointStiffness" || propName == "Stiffness") - reader >> m_JointStiffness; - else if (propName == "BreakWound") - m_pBreakWound = dynamic_cast(g_PresetMan.GetEntityPreset(reader)); - else if (propName == "JointOffset") - reader >> m_JointOffset; - else if (propName == "InheritsRotAngle") - reader >> m_InheritsRotAngle; - else if (propName == "DrawAfterParent") - reader >> m_DrawAfterParent; - else if (propName == "CollidesWithTerrainWhenAttached") - reader >> m_CanCollideWithTerrainWhenAttached; - else if (propName == "DeleteWithParent") - reader >> m_DeleteWithParent; - else - return MOSRotating::ReadProperty(propName, reader); - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Save -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Saves the complete state of this Attachable with a Writer for -// later recreation with Create(Reader &reader); - -int Attachable::Save(Writer &writer) const -{ - MOSRotating::Save(writer); - - writer.NewProperty("ParentOffset"); - writer << m_ParentOffset; - writer.NewProperty("JointStrength"); - writer << m_JointStrength; - writer.NewProperty("JointStiffness"); - writer << m_JointStiffness; - writer.NewProperty("BreakWound"); - writer << m_pBreakWound; - writer.NewProperty("JointOffset"); - writer << m_JointOffset; - writer.NewProperty("InheritsRotAngle"); - writer << m_InheritsRotAngle; - writer.NewProperty("DrawAfterParent"); - writer << m_DrawAfterParent; - writer.NewProperty("CollidesWithTerrainWhenAttached"); - writer << m_CanCollideWithTerrainWhenAttached; - writer.NewProperty("DeleteWithParent"); - writer << m_DeleteWithParent; - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Destroy -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Destroys and resets (through Clear()) the Attachable object. - -void Attachable::Destroy(bool notInherited) -{ - - if (!notInherited) - MOSRotating::Destroy(); - Clear(); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: CollideAtPoint -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Calculates the collision response when another MO's Atom collides with -// this MO's physical representation. The effects will be applied -// directly to this MO, and also represented in the passed in HitData. - -bool Attachable::CollideAtPoint(HitData &hd) -{ - return MOSRotating::CollideAtPoint(hd); -/* - // See if the impact created a force enough to detach from parent. - if (m_pParent && hd.ResImpulse[HITEE].GetMagnitude() > m_JointStrength) { - m_pParent->AddAbsImpulseForce(Vector(hd.ResImpulse[HITEE]).SetMagnitude(m_JointStrength), m_JointPos); - - Detach(); - } - else { - - } -*/ -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: ParticlePenetration -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Determines whether a particle which has hit this MO will penetrate, -// and if so, whether it gets lodged or exits on the other side of this -// MO. Appropriate effects will be determined and applied ONLY IF there -// was penetration! If not, nothing will be affected. - -bool Attachable::ParticlePenetration(HitData &hd) -{ - bool penetrated = MOSRotating::ParticlePenetration(hd); - - // Add damage points if MO is set to damage actors - if (hd.Body[HITOR]->DamageOnCollision() != 0) - AddDamage(hd.Body[HITOR]->DamageOnCollision()); - - // If penetrated, propogate an alarm up to the root parent, if it's an actor - if (penetrated && m_pParent) - { - // Add damage points if MO is set to damage actors on penetration - if (hd.Body[HITOR]->DamageOnPenetration() != 0) - AddDamage(hd.Body[HITOR]->DamageOnPenetration()); - - Actor *pParentActor = dynamic_cast(GetRootParent()); - if (pParentActor) - { - // Move the alarm point out a bit from the body so the reaction is better -// Vector extruded(g_SceneMan.ShortestDistance(pParentActor->GetPos(), hd.HitPoint)); - Vector extruded(hd.HitVel[HITOR]); - extruded.SetMagnitude(pParentActor->GetHeight()); - extruded = m_Pos - extruded; - g_SceneMan.WrapPosition(extruded); - pParentActor->AlarmPoint(extruded); - } - } - - return penetrated; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. - -void Attachable::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { - m_pParent ? m_pParent->RemoveAttachable(this) : Detach(); - MOSRotating::GibThis(impactImpulse, internalBlast, pIgnoreMO); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Attach -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Attaches this Attachable to a host MOSprite - -void Attachable::Attach(MOSRotating *pParent) -{ - m_pParent = pParent; - - // Adopt the team of parent - if (pParent) - { - m_Team = pParent->GetTeam(); - } - - // Reset the attachables timers so things that have been sitting in inventory don't make backed up emissions - ResetAllTimers(); - - if (m_pParent != NULL && GetRootParent()->HasEverBeenAddedToMovableMan()) { - RunScriptedFunctionInAppropriateScripts("OnAttach", false, false, {m_pParent}); - } -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Detach -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Detaches this Attachable from its host MOSprite - -void Attachable::Detach() -{ - if (m_pParent) - { - // Attempt to remove any atoms of this that may have been added to the parent's AtomGroup before detaching - m_pParent->GetAtomGroup()->RemoveAtoms(m_AtomSubgroupID); - } - - m_Team = -1; - MOSRotating *temporaryParent = m_pParent; - m_pParent = 0; - // Since it's no longer atteched it should belong to itself - m_RootMOID = m_MOID; + ConcreteClassInfo(Attachable, MOSRotating, 0) + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::Clear() { + m_Parent = 0; + m_ParentOffset.Reset(); + m_DrawAfterParent = true; + m_DeleteWithParent = false; + + m_JointStrength = 10; + m_JointStiffness = 1.0; + m_JointOffset.Reset(); + m_JointPos.Reset(); + + m_OnlyLinearForces = false; + + m_DamageCount = 0; + m_BreakWound = 0; + + m_InheritsRotAngle = true; + m_RotTarget.Reset(); + + m_AtomSubgroupID = -1; + m_CanCollideWithTerrainWhenAttached = false; + m_IsCollidingWithTerrainWhileAttached = false; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Attachable::Create(const Attachable &reference) { + MOSRotating::Create(reference); + + m_Parent = reference.m_Parent; + m_ParentOffset = reference.m_ParentOffset; + m_DrawAfterParent = reference.m_DrawAfterParent; + m_DeleteWithParent = reference.m_DeleteWithParent; + + m_JointStrength = reference.m_JointStrength; + m_JointStiffness = reference.m_JointStiffness; + m_JointOffset = reference.m_JointOffset; + m_JointPos = reference.m_JointPos; + + m_OnlyLinearForces = reference.m_OnlyLinearForces; + + m_DamageCount = reference.m_DamageCount; + m_BreakWound = reference.m_BreakWound; + + m_InheritsRotAngle = reference.m_InheritsRotAngle; + m_RotTarget = reference.m_RotTarget; + + m_AtomSubgroupID = reference.m_AtomSubgroupID; + m_CanCollideWithTerrainWhenAttached = reference.m_CanCollideWithTerrainWhenAttached; + m_IsCollidingWithTerrainWhileAttached = reference.m_IsCollidingWithTerrainWhileAttached; + + return 0; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Attachable::ReadProperty(std::string propName, Reader &reader) { + if (propName == "ParentOffset") { + reader >> m_ParentOffset; + } else if (propName == "DrawAfterParent") { + reader >> m_DrawAfterParent; + } else if (propName == "DeleteWithParent") { + reader >> m_DeleteWithParent; + } else if (propName == "JointStrength" || propName == "Strength") { + reader >> m_JointStrength; + } else if (propName == "JointStiffness" || propName == "Stiffness") { + reader >> m_JointStiffness; + } else if (propName == "JointOffset") { + reader >> m_JointOffset; + } else if (propName == "BreakWound") { + m_BreakWound = dynamic_cast(g_PresetMan.GetEntityPreset(reader)); + } else if (propName == "InheritsRotAngle") { + reader >> m_InheritsRotAngle; + } else if (propName == "CollidesWithTerrainWhenAttached") { + reader >> m_CanCollideWithTerrainWhenAttached; + } else { + return MOSRotating::ReadProperty(propName, reader); + } + + return 0; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Attachable::Save(Writer &writer) const { + MOSRotating::Save(writer); + + writer.NewProperty("ParentOffset"); + writer << m_ParentOffset; + writer.NewProperty("DrawAfterParent"); + writer << m_DrawAfterParent; + writer.NewProperty("DeleteWithParent"); + writer << m_DeleteWithParent; + + writer.NewProperty("JointStrength"); + writer << m_JointStrength; + writer.NewProperty("JointStiffness"); + writer << m_JointStiffness; + writer.NewProperty("JointOffset"); + writer << m_JointOffset; + + writer.NewProperty("BreakWound"); + writer << m_BreakWound; + + writer.NewProperty("InheritsRotAngle"); + writer << m_InheritsRotAngle; + writer.NewProperty("CollidesWithTerrainWhenAttached"); + writer << m_CanCollideWithTerrainWhenAttached; + + return 0; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + bool Attachable::TransferJointForces(Vector &jointForces) { + if (!m_Parent) { + return false; + } + + Vector forces; + for (const std::pair &force : m_Forces) { + forces += force.first; + } + m_Forces.clear(); + + jointForces += forces; + return true; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + bool Attachable::TransferJointImpulses(Vector &jointImpulses) { + if (!m_Parent) { + return false; + } + + Vector impulseForces; + for (const std::pair &impulseForce : m_ImpulseForces) { + impulseForces += impulseForce.first; + } + impulseForces *= m_JointStiffness; + + if (impulseForces.GetMagnitude() > m_JointStrength) { + impulseForces.SetMagnitude(m_JointStrength); + jointImpulses += impulseForces; + if (m_BreakWound) { + AEmitter *breakWound = dynamic_cast(m_BreakWound->Clone()); + if (breakWound) { + breakWound->SetEmitAngle(m_JointOffset.GetAbsRadAngle()); + AddWound(breakWound, m_JointOffset, false); + breakWound = 0; + } + } + m_Parent->RemoveAttachable(this); + g_MovableMan.AddParticle(this); + return false; + } + + for (const std::pair &impulseForce : m_ImpulseForces) { + if (!impulseForce.second.IsZero()) { + // Rough explanation of what this is doing: + // The first part is getting the Dot/Scalar product of the perpendicular of the offset vector for the force onto the force vector itself (dot product is the amount two vectors are pointing in the same direction). + // The second part is dividing that Dot product by the moment of inertia, i.e. the torque needed to make it turn. All of this is multiplied by 1 - JointStiffness, because max stiffness joints transfer all force to parents and min stiffness transfer none. + m_AngularVel += (impulseForce.second.GetPerpendicular().Dot(impulseForce.first) / m_pAtomGroup->GetMomentOfInertia()) * (1.0F - m_JointStiffness); + } + } + m_ImpulseForces.clear(); + + jointImpulses += impulseForces; + return true; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + float Attachable::CollectDamage() { + float totalDamage = m_DamageCount; + m_DamageCount = 0; + + for (AEmitter *wound : m_Wounds) { + totalDamage += wound->CollectDamage(); + } + return totalDamage * m_DamageMultiplier; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::EnableTerrainCollisions(bool enable) { + if (IsAttached() && CanCollideWithTerrainWhenAttached()) { + if (!IsCollidingWithTerrainWhileAttached() && enable) { + m_Parent->GetAtomGroup()->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), GetParentOffset() - GetJointOffset()); + SetIsCollidingWithTerrainWhileAttached(true); + } else if (IsCollidingWithTerrainWhileAttached() && !enable) { + m_Parent->GetAtomGroup()->RemoveAtoms(GetAtomSubgroupID()); + SetIsCollidingWithTerrainWhileAttached(false); + } + } else if (IsAttached() && !CanCollideWithTerrainWhenAttached()) { + if (enable || !enable) { + g_ConsoleMan.PrintString("ERROR: Tried to toggle collisions for attachable that was not set to collide when initially created!"); + } + } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::Attach(MOSRotating *newParent) { + if (newParent != nullptr) { + m_Parent = newParent; + m_Team = m_Parent->GetTeam(); + + //TODO see if this is reasonable. Seems like inventory swapping should do this cleanup internally. Also note that it used to be done regardless of newParent existing but I changed that, might be bad? + // Timers are reset here as a precaution, so that if something was sitting in an inventory, it doesn't cause backed up emissions. + ResetAllTimers(); + + if (GetRootParent()->HasEverBeenAddedToMovableMan()) { + RunScriptedFunctionInAppropriateScripts("OnAttach", false, false, {m_Parent}); + } + } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::Detach() { + if (m_Parent) { + m_Parent->GetAtomGroup()->RemoveAtoms(m_AtomSubgroupID); + } + + m_Team = -1; + MOSRotating *temporaryParent = m_Parent; + m_Parent = 0; + m_RootMOID = m_MOID; + //TODO I don't think we need these at all? They're basically duplicates, and I think the m_MOID = g_NoMOID is backwards anyway??? #if defined DEBUG_BUILD || defined MIN_DEBUG_BUILD - RTEAssert(m_RootMOID == g_NoMOID || (m_RootMOID >= 0 && m_RootMOID < g_MovableMan.GetMOIDCount()), "MOID out of bounds!"); - RTEAssert(m_MOID == g_NoMOID || (m_MOID >= 0 && m_MOID < g_MovableMan.GetMOIDCount()), "MOID out of bounds!"); + RTEAssert(m_RootMOID == g_NoMOID || (m_RootMOID >= 0 && m_RootMOID < g_MovableMan.GetMOIDCount()), "MOID out of bounds!"); + RTEAssert(m_MOID == g_NoMOID || (m_MOID >= 0 && m_MOID < g_MovableMan.GetMOIDCount()), "MOID out of bounds!"); #endif - m_RestTimer.Reset(); - - if (temporaryParent != NULL && temporaryParent->GetRootParent()->HasEverBeenAddedToMovableMan()) { - RunScriptedFunctionInAppropriateScripts("OnDetach", false, false, {temporaryParent}); - } -} - - -/// -/// Turns on/off this Attachable's collisions, by adding/removing its atoms to/from its parent's AtomGroup. -/// -/// Adds this Attachable's atoms to the parent's AtomGroup if true, removes them if false. -void Attachable::EnableTerrainCollisions(bool enable) -{ - if (IsAttached() && CanCollideWithTerrainWhenAttached()) - { - if (!IsCollidingWithTerrainWhileAttached() && enable) - { - m_pParent->GetAtomGroup()->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), GetParentOffset() - GetJointOffset()); - SetIsCollidingWithTerrainWhileAttached(true); + m_RestTimer.Reset(); + + if (temporaryParent != nullptr && temporaryParent->GetRootParent()->HasEverBeenAddedToMovableMan()) { + RunScriptedFunctionInAppropriateScripts("OnDetach", false, false, {temporaryParent}); + } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + bool Attachable::CollideAtPoint(HitData &hd) { + return MOSRotating::CollideAtPoint(hd); + //TODO potentially make this happen, I guess the concepts are handled in MOSR::ApplyAttachableForces, which seems weird. If I don't implement, remove this whole override method cause it's otherwise unused. + /* + // See if the impact created a force enough to detach from parent. + if (m_pParent && hd.ResImpulse[HITEE].GetMagnitude() > m_JointStrength) { + m_pParent->AddAbsImpulseForce(Vector(hd.ResImpulse[HITEE]).SetMagnitude(m_JointStrength), m_JointPos); + + Detach(); + } + else { + + } + */ + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + bool Attachable::ParticlePenetration(HitData &hd) { + bool penetrated = MOSRotating::ParticlePenetration(hd); + + if (hd.Body[HITOR]->DamageOnCollision() != 0) { + AddDamage(hd.Body[HITOR]->DamageOnCollision()); } - else if (IsCollidingWithTerrainWhileAttached() && !enable) - { - m_pParent->GetAtomGroup()->RemoveAtoms(GetAtomSubgroupID()); - SetIsCollidingWithTerrainWhileAttached(false); + + if (penetrated && m_Parent) { + if (hd.Body[HITOR]->DamageOnPenetration() != 0) { + AddDamage(hd.Body[HITOR]->DamageOnPenetration()); + } + + // If the parent is an actor, generate an alarm point for them, moving it slightly away from the body (in the direction they got hit from) to get a good reaction. + Actor *parentAsActor = dynamic_cast(GetRootParent()); + if (parentAsActor) { + Vector extruded(hd.HitVel[HITOR]); + extruded.SetMagnitude(parentAsActor->GetHeight()); + extruded = m_Pos - extruded; + g_SceneMan.WrapPosition(extruded); + parentAsActor->AlarmPoint(extruded); + } } + + return penetrated; } - else if (IsAttached() && !CanCollideWithTerrainWhenAttached()) - { - if (enable || !enable) - { - g_ConsoleMan.PrintString("ERROR: Tried to toggle collisions for attachable that was not set to collide when initially created!"); + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + //TODO change impactImpulse to a const reference Vector + void Attachable::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { + if (m_Parent) { + m_Parent->RemoveAttachable(this); + } else { + Detach(); } + MOSRotating::GibThis(impactImpulse, internalBlast, pIgnoreMO); } -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: TransferJointForces -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Bundles up all the accumulated forces of this Attachable and calcs -// how they transfer to the joint, and therefore to the parent. - -bool Attachable::TransferJointForces(Vector &jointForces) -{ - // Exit trivially if not attahced to anything - if (!m_pParent) - return false; - - Vector forces; - // Add up all the forces - for (deque >::iterator fItr = m_Forces.begin(); - fItr != m_Forces.end(); ++fItr) - forces += fItr->first; - - // Joint held up, so act accordingly -// TODO: Maybe not do this here, we might need the forces for other stuff?") - // Clear out forces after we've bundled them up. - m_Forces.clear(); - - jointForces += forces; - return true; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: TransferJointImpulses -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Bundles up all the accumulated impulses of this Attachable and calcs -// how they transfer to the joint, and therefore to the parent. - -bool Attachable::TransferJointImpulses(Vector &jointImpulses) -{ - // Exit trivially if not attahced to anything - if (!m_pParent) - return false; - - Vector impulses; - // Add up the impulses - for (deque >::iterator iItr = m_ImpulseForces.begin(); iItr != m_ImpulseForces.end(); ++iItr) - impulses += iItr->first; - - // Factor in the stiffness, or lack thereof - impulses *= m_JointStiffness; - - // Check if joint breaks and act accordingly - if (impulses.GetMagnitude() > m_JointStrength) - { - impulses.SetMagnitude(m_JointStrength); - jointImpulses += impulses; -/* - float deltaTime = g_TimerMan.GetDeltaTimeSecs(); - m_ImpulseForces.push_back(make_pair(-impulses, m_JointOffset)); - for (iItr = m_ImpulseForces.begin(); iItr != m_ImpulseForces.end(); ++iItr) - { - // Impulse force application to the transformational velocity of this MO. - // Don't timescale these because they're already in kg * m/s (as opposed to kg * m/s^2). - m_Vel += iItr->first / m_Mass; - // Impulse force application to the rotational velocity of this MO. - if (!(*iItr).second.IsZero()) - m_AngularVel += iItr->second.GetPerpendicular().Dot(iItr->first) / - m_pAtomGroup->GetMomentOfInertia(); - } -*/ - if (m_pBreakWound) - { - // Add velocity and wound before detaching. - // The forces should be applied to this' vel next round when detached - AEmitter *pWound = dynamic_cast(m_pBreakWound->Clone()); - if (pWound) - { - pWound->SetEmitAngle(m_JointOffset.GetAbsRadAngle()); - AddWound(pWound, m_JointOffset, false); - pWound = 0; - } - } - - if (m_pParent) - { - m_pParent->RemoveAttachable(this); - } - else - { - Detach(); - } - g_MovableMan.AddParticle(this); - return false; - } - - //////////////////////////////////////////// - // Joint held up, so act accordingly - - // Apply the rotational effects of all the impulses accumulated. - for (deque >::iterator iItr = m_ImpulseForces.begin(); iItr != m_ImpulseForces.end(); ++iItr) - { - // Impulse force application to the rotational velocity of this MO. - if (!(*iItr).second.IsZero()) - m_AngularVel += ((*iItr).second.GetPerpendicular().Dot((*iItr).first) / - m_pAtomGroup->GetMomentOfInertia()) * (1.0 - m_JointStiffness); - } -// TODO: Maybe not do this here, we might need the forces for other stuff?") - // Clear out forces after we've bundled them up. - m_ImpulseForces.clear(); - - jointImpulses += impulses; - return true; -} - -/* -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: PostTravel -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Does stuff that needs to be done after Update(). Always call after -// calling Update. - -void Attachable::PostTravel() -{ - MOSRotating::PostTravel(); -} -*/ - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: CollectDamage -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the number of damage points this Attachable has sustained and -// should cause its parent. Calling this will reset the damage count. -// This should normally be called AFTER Update() to get the correct -// damage for a given frame. - -float Attachable::CollectDamage() -{ - float totalDamage = m_DamageCount; - m_DamageCount = 0; - - for (list::iterator itr = m_Wounds.begin(); itr != m_Wounds.end(); ++itr) - totalDamage += (*itr)->CollectDamage(); - - return totalDamage * m_DamageMultiplier; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: RemoveWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds and returns damage caoused by this wounds. -// Head multiplier is not used. - -int Attachable::RemoveWounds(int amount) -{ - return MOSRotating::RemoveWounds(amount) * m_DamageMultiplier; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Update -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Updates this Attachable. Supposed to be done every frame. - -void Attachable::Update() -{ - if (!m_pParent) { -// This doesn't work so well, sinking problems -// m_DeepCheck = true; - m_JointPos = m_Pos + RotateOffset(m_JointOffset); - } - else { - // Save previous position and velocities before moving - m_PrevPos = m_Pos; - m_PrevVel = m_Vel; - // Attached, so get all metrics from parent and apply -// m_HFlipped = m_pParent->IsHFlipped(); not flexible enough - if (!m_JointPos.IsZero()) - m_Pos = m_JointPos - RotateOffset(m_JointOffset); - else - m_Pos = m_pParent->GetPos() - RotateOffset(m_JointOffset); -// m_Rotation = m_pParent->GetRotMatrix(); - m_Vel = m_pParent->GetVel(); -// m_AngularVel = m_pParent->GetAngularVel(); - m_Team = m_pParent->GetTeam(); -/* - /////////////////////////////////////// - // Rotation spring calc - // Get the rotation in radians. - float springDelta = m_Rotation.GetRadAngle() - m_RotTarget.GetRadAngle(); - // Eliminate full rotations - while (fabs(springDelta) > c_TwoPI) { - springDelta -= springDelta > 0 ? c_TwoPI : -c_TwoPI; - } - // Eliminate rotations over half a turn -// if (fabs(springDelta) > c_PI) -// springDelta = (springDelta > 0 ? -c_PI : c_PI) + (springDelta - (springDelta > 0 ? c_PI : -c_PI)); - // Break the spring if close to target angle. - if (fabs(springDelta) > 0.1) - m_AngularVel -= springDelta * fabs(springDelta);// * m_JointStiffness; - else if (fabs(m_AngularVel) > 0.1) - m_AngularVel *= 0.5; -// m_Rotation += springDelta * m_JointStiffness; - -// m_AngularVel -= springDelta * m_JointStiffness; - - // Apply the rotational velocity - float deltaTime = g_TimerMan.GetDeltaTimeSecs(); -// m_Rotation += m_AngularVel * deltaTime; -*/ - - m_DeepCheck = false; - } - - MOSRotating::Update(); - - // If we're attached to something, MoveableMan doesn't own us, and therefore isn't calling our ScriptUpdate (and our parent isn't calling it either), so we should here - if (m_pParent != NULL && GetRootParent()->HasEverBeenAddedToMovableMan()) { UpdateScripts(); } -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this Attachable's current graphical representation to a -// BITMAP of choice. - -void Attachable::Draw(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode, - bool onlyPhysical) const -{ - MOSRotating::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - -/* - Vector spritePos(m_Pos.GetFloored() - targetPos); - - // If attached to something, rotate about the joint, - // otherwise rotate about the center of mass -// if (m_pParent) -// spritePos += m_JointOffset; - - if (m_Recoiled) - spritePos += m_RecoilOffset; - - if (m_HFlipped) { - if (!m_pTempBitmapB) { - m_pTempBitmapB = new BITMAP(); - m_pTempBitmapB->Create(g_FrameMan.GetScreen(), - m_aSprite->GetTile()->GetBlockWidth(), - m_aSprite->GetTile()->GetBlockHeight(), - CDXMEM_SYSTEMONLY); - } - m_pTempBitmapB->Fill(g_MaskColor); - m_pTempBitmapB->SetColorKey(g_MaskColor); - m_aSprite->SetPos(0, 0); - - if (mode != g_DrawColor) { - if (!m_pTempBitmapA) { - m_pTempBitmapA = new BITMAP(); - m_pTempBitmapA->Create(g_FrameMan.GetScreen(), - m_aSprite->GetTile()->GetBlockWidth(), - m_aSprite->GetTile()->GetBlockHeight(), - CDXMEM_SYSTEMONLY); - } - m_pTempBitmapA->Fill(g_MaskColor); - m_pTempBitmapA->SetColorKey(g_MaskColor); - - if (mode == g_DrawMaterial) - DrawMaterial(m_aSprite, m_pTempBitmapA, GetSettleMaterial()); - else if (mode == g_DrawAir) - DrawMaterial(m_aSprite, m_pTempBitmapA, g_MaterialAir); - else if (mode == g_DrawMask) - DrawMaterial(m_aSprite, m_pTempBitmapA, g_MaskColor); - else if (mode == g_DrawMOID) - DrawMaterial(m_aSprite, m_pTempBitmapA, m_MOID); - else - RTEAbort("Unknown draw mode selected in Attachable:Draw()!"); - - m_pTempBitmapA->DrawTransHFlip(m_pTempBitmapB, 0, 0); - } - else - m_aSprite->Draw(m_pTempBitmapB, 0, 0, CDXBLT_TRANSHFLIP); - - Vector newSpriteCent(m_SpriteCenter); - newSpriteCent.m_X = -newSpriteCent.m_X; - newSpriteCent.RadRotate(m_Rotation); - spritePos += newSpriteCent; - - // Hack to correct shitty cdx rotozoom - spritePos.m_X += 2.0; - - // This guy wants the center of the sprite, not the top left corner like Draw(). - m_pTempBitmapB->DrawTransRotoZoom(pTargetBitmap, - spritePos.m_X, - spritePos.m_Y, - m_pTempBitmapB->GetClipRect(), - m_Rotation, - m_Scale); - } - else { - spritePos += m_SpriteOffset; - spritePos += (m_SpriteCenter * m_Rotation - m_SpriteCenter); - // Hack to correct shitty cdx rotozoom - spritePos.m_X += 1.0; - - m_aSprite->SetPos(spritePos.m_X, spritePos.m_Y); - - if (mode == g_DrawMaterial) - DrawMaterialRotoZoomed(m_aSprite, pTargetBitmap, GetSettleMaterial()); - else if (mode == g_DrawAir) - DrawMaterialRotoZoomed(m_aSprite, pTargetBitmap, g_MaterialAir); - else if (mode == g_DrawMask) - DrawMaterialRotoZoomed(m_aSprite, pTargetBitmap, g_MaskColor); - else if (mode == g_DrawMOID) - DrawMaterialRotoZoomed(m_aSprite, pTargetBitmap, m_MOID); - else - m_aSprite->Draw(pTargetBitmap, 0, 0, CDXBLT_TRANSROTOZOOM); - } - -// TODO: Clean up the drawing hierarchy!#@!") - // Finally draw all the attached emitters, and only if the mode is g_DrawColor - if (mode == g_DrawColor || mode == g_DrawMaterial) { - for (list::iterator itr = m_Wounds.begin(); itr != m_Wounds.end(); ++itr) - (*itr)->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } -*/ -/* -#ifdef DEBUG_BUILD - pTargetBitmap->Lock(); - pTargetBitmap->PutPixel(m_Pos.GetFloorIntX() - targetPos.m_X, - m_Pos.GetFloorIntY() - targetPos.m_Y, - 64); - pTargetBitmap->UnLock(); -#endif -*/ -} -} // namespace RTE \ No newline at end of file +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::Update() { + if (!m_Parent) { + //TODO right now parents are responsible for setting JointPos. The only one that seems to do much with this is Leg, everything else looks much the same. I'd rather attachables do this internally cause that makes way more sense. Will take some cleanup though. + m_JointPos = m_Pos + RotateOffset(m_JointOffset); + } else { + m_PrevPos = m_Pos; + m_PrevVel = m_Vel; + + if (!m_JointPos.IsZero()) { + m_Pos = m_JointPos - RotateOffset(m_JointOffset); + } else { + m_Pos = m_Parent->GetPos() - RotateOffset(m_JointOffset); + } + m_Vel = m_Parent->GetVel(); + m_Team = m_Parent->GetTeam(); + + //TODO RotAngle should be set here based on whether or not this InheritsRotAngle. It's currently done by MOSR which is dumdum. Alternatively, see below. + + //TODO m_RotTarget is handled here, the idea is to use spring concepts instead of just setting RotAngle. Either fix it, or delete it and the header stuff for it. + /* + float springDelta = m_Rotation.GetRadAngle() - m_RotTarget.GetRadAngle(); + // Eliminate full rotations + while (fabs(springDelta) > c_TwoPI) { + springDelta -= springDelta > 0 ? c_TwoPI : -c_TwoPI; + } + // Eliminate rotations over half a turn + //if (fabs(springDelta) > c_PI) { + // springDelta = (springDelta > 0 ? -c_PI : c_PI) + (springDelta - (springDelta > 0 ? c_PI : -c_PI)); + //} + + // Break the spring if close to target angle. + if (fabs(springDelta) > 0.1) { + m_AngularVel -= springDelta * fabs(springDelta);// * m_JointStiffness; + } else if (fabs(m_AngularVel) > 0.1) { + m_AngularVel *= 0.5; + } + //m_Rotation += springDelta * m_JointStiffness; + //m_AngularVel -= springDelta * m_JointStiffness; + + // Apply the rotational velocity + //m_Rotation += m_AngularVel * g_TimerMan.GetDeltaTimeSecs(); + */ + + m_DeepCheck = false; + } + + MOSRotating::Update(); + + // If we're attached to something, MovableMan doesn't own us, and therefore isn't calling our UpdateScripts method (and neither is our parent), so we should here. + if (m_Parent != nullptr && GetRootParent()->HasEverBeenAddedToMovableMan()) { UpdateScripts(); } + } +} \ No newline at end of file diff --git a/Entities/Attachable.h b/Entities/Attachable.h index bfd8a041e..afa07a6ad 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -1,674 +1,391 @@ #ifndef _RTEATTACHABLE_ #define _RTEATTACHABLE_ -////////////////////////////////////////////////////////////////////////////////////////// -// File: Attachable.h -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Header file for the Attachable class. -// Project: Retro Terrain Engine -// Author(s): Daniel Tabar -// data@datarealms.com -// http://www.datarealms.com - - -////////////////////////////////////////////////////////////////////////////////////////// -// Inclusions of header files - #include "MOSRotating.h" -namespace RTE -{ - -class AEmitter; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Class: Attachable -////////////////////////////////////////////////////////////////////////////////////////// -// Description: An articulated, detachable part of an Actor's body. -// Parent(s): MOSRotating. -// Class history: 05/30/2002 Attachable created. - -class Attachable: - public MOSRotating -{ - - -////////////////////////////////////////////////////////////////////////////////////////// -// Public member variable, method and friend function declarations - -public: - - -// Concrete allocation and cloning definitions -EntityAllocation(Attachable) -AddScriptFunctionNames(MOSRotating, "OnAttach", "OnDetach") -SerializableOverrideMethods -ClassInfoGetters - -////////////////////////////////////////////////////////////////////////////////////////// -// Constructor: Attachable -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Constructor method used to instantiate a Attachable object in system -// memory. Create() should be called before using the object. -// Arguments: None. - - Attachable() { Clear(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Destructor: ~Attachable -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Destructor method used to clean up a Attachable object before deletion -// from system memory. -// Arguments: None. - - virtual ~Attachable() { Destroy(true); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes the Attachable object ready for use. -// Arguments: None. -// Return value: An error return value signaling sucess or any particular failure. -// Anything below 0 is an error signal. - - virtual int Create(); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Creates a Attachable to be identical to another, by deep copy. -// Arguments: A reference to the Attachable to deep copy. -// Return value: An error return value signaling sucess or any particular failure. -// Anything below 0 is an error signal. - - int Create(const Attachable &reference); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Reset -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Resets the entire Attachable, including its inherited members, to their -// default settings or values. -// Arguments: None. -// Return value: None. - - virtual void Reset() { Clear(); MOSRotating::Reset(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Destroy -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Destroys and resets (through Clear()) the SceneLayer object. -// Arguments: Whether to only destroy the members defined in this derived class, or -// to destroy all inherited members also. -// Return value: None. - - virtual void Destroy(bool notInherited = false); +namespace RTE { + class AEmitter; /// - /// Gets the MO which is the parent of this Attachable. + /// An articulated, detachable part of an Actor's body. /// - /// A pointer to the parent of this Attachable. - MovableObject * GetParent() override { return m_pParent; } - - /// - /// Gets the MO which is the parent of this Attachable. - /// - /// A pointer to the parent of this Attachable. - const MovableObject * GetParent() const override { return m_pParent; } - - /// - /// Gets the MO which is the ultimate root parent of this Attachable and its parent. - /// - /// A pointer to the highest root parent of this Attachable. - MovableObject * GetRootParent() override { return m_pParent ? m_pParent->GetRootParent() : this; } - - /// - /// Gets the MO which is the ultimate root parent of this Attachable and its parent. - /// - /// A pointer to the highest root parent of this Attachable. - const MovableObject * GetRootParent() const override { return m_pParent ? m_pParent->GetRootParent() : this; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetParentOffset -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the stored offset between this Attachable's parent's Pos and the -// joint position. This should be maintained by the parent. -// Arguments: None. -// Return value: A const reference Vector describing the offset from the parent's pos -// to the joint point. - - virtual const Vector & GetParentOffset() const { return m_ParentOffset; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetJointOffset -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the offset to the joint (the point around which this Attachable -// and its parent hinge) from this Attachable's center of mass/origin. -// Arguments: None. -// Return value: A const reference Vector describing the offset of the joint relative -// to the this Attachable's origin/center of mass position. - - virtual const Vector & GetJointOffset() const { return m_JointOffset; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetJointOffset -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the offset to the joint (the point around which this Attachable -// and its parent hinge) from this Attachable's center of mass/origin. -// Arguments: Vector describing the offset of the joint relative -// to the this Attachable's origin/center of mass position. -// Return value: None. - - virtual void SetJointOffset(Vector offset) { m_JointOffset = offset; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetJointStrength -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the amount of impulse force the joint of this Attachable can -// handle before breaking. -// Arguments: None. -// Return value: A float with the max tolerated impulse force in kg * m/s. - - float GetJointStrength() const { return m_JointStrength; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetJointStiffness -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the normalized stiffness scalar of the join of this Attachable. -// Arguments: None. -// Return value: A float between 0 and 1.0. 1.0 means 100% of all forces imposed on this -// attachable will be transferred through the joint to the parent. 0.5 -// means 50%, and so on. - - float GetJointStiffness() const { return m_JointStiffness; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetBreakWound -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the AEmitter that represents the wound created when this -// Attachable gets detached from its parent. -// Arguments: None. -// Return value: A const pointer to the break wound AEmitter. - - const AEmitter * GetBreakWound() const { return m_pBreakWound; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetRotTarget -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the target rotation that this Attachable should be striving to -// match its real rotation with, if it is attached. The joint stiffness -// will determine how strong the scalar spring is between the current -// rotation and the target set here. -// Arguments: None. -// Return value: A float for the current target angle in radians. - - float GetRotTarget() const { return m_RotTarget.GetRadAngle(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetAtomSubgroupID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the subgroup ID of this' Atoms. -// Arguments: None. -// Return value: The the subgroup ID of this' Atoms. - - long int GetAtomSubgroupID() const { return m_AtomSubgroupID; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetOnlyLinearForces -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this AEmitter only cares about linear forces that it -// creates through emissions, ie no torquing due to the parent offset. -// Arguments: None. -// Return value: Whether only using linear forces or not. - - bool GetOnlyLinearForces() const { return m_OnlyLinForces; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetParentOffset -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the stored offset between this Attachable's parent's Pos and the -// joint position. This should be maintained by the parent. -// Arguments: A const reference to the new parent offset. -// Return value: None. - - void SetParentOffset(const Vector &newParOff) { m_ParentOffset = newParOff; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetJointPos -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the position of this Attachable by defining where the joint is. -// Upon Update(), this will be translated into what the actual position -// of the Attachable origin/center of mass is, depending on its set -// rotational angle and joint offset. -// Arguments: A const reference to the new joint position to set the position with. -// Return value: None. - - void SetJointPos(const Vector &newJointPos) { m_JointPos = newJointPos; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetJointStrength -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the amount of impulse force the joint of this Attachable can -// handle before breaking. -// Arguments: A float with the max tolerated impulse force in kg * m/s. -// Return value: None. - - void SetJointStrength(float newJointStrength) { m_JointStrength = newJointStrength; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetJointStiffness -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the normalized stiffness scalar of the join of this Attachable. -// Arguments: A float between 0 and 1.0. 1.0 means 100% of all forces imposed on this -// attachable will be transferred through the joint to the parent. 0.5 -// means 50%, and so on. -// Return value: None. - - void SetJointStiffness(float newJointStiff) { m_JointStiffness = newJointStiff; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetRotTarget -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the target rotation that this Attachable should be striving to -// match its real rotation with, if it is attached. The joint stiffness -// will determine how strong the scalar spring is between the current -// rotation and the target set here. -// Arguments: A float for the new target angle in radians. -// Return value: None. - - void SetRotTarget(float newRotTarget) { m_RotTarget.SetRadAngle(newRotTarget); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetAtomSubgroupID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the subgroup ID of this' Atoms -// Arguments: The new subgroup id of this' Atoms -// Return value: None. - - void SetAtomSubgroupID(long int newID = 0) { m_AtomSubgroupID = newID; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetOnlyLinearForces -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets whether this AEmitter should only care about linear forces that it -// creates through emissions, ie no torquing due to the parent offset. -// Arguments: Whether only use linear forces or not. -// Return value: None. - - void SetOnlyLinearForces(bool linOnly) { m_OnlyLinForces = linOnly; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: IsAttached -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this Attachable is attached to an MOSprite or not. -// Arguments: None. -// Return value: Whether it's attached or not. - - bool IsAttached() const { return m_pParent != 0; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: IsAttachedTo -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this Attachable is attached to a specific actor or -// not. -// Arguments: A pointer to which MOSprite you want to check if this is attached to. -// Return value: Whether it's attached or not. - - bool IsAttachedTo(const MOSprite *pparent) const { return m_pParent == pparent; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: IsDrawnAfterParent -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this Attachable is to be drawn after (in front of) or -// before (behind) the parent. -// Arguments: None. -// Return value: Whether it's to be drawn after parent or not. - - virtual bool IsDrawnAfterParent() const { return m_DrawAfterParent; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: CollideAtPoint -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Calculates the collision response when another MO's Atom collides with -// this MO's physical representation. The effects will be applied -// directly to this MO, and also represented in the passed in HitData. -// Arguments: Reference to the HitData struct which describes the collision. This -// will be modified to represent the results of the collision. -// Return value: Whether the collision has been deemed valid. If false, then disregard -// any impulses in the Hitdata. - - virtual bool CollideAtPoint(HitData &hitData); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: ParticlePenetration -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Determines whether a particle which has hit this MO will penetrate, -// and if so, whether it gets lodged or exits on the other side of this -// MO. Appropriate effects will be determined and applied ONLY IF there -// was penetration! If not, nothing will be affected. -// Arguments: The HitData describing the collision in detail, the impulses have to -// have been filled out! -// Return value: Whether the particle managed to penetrate into this MO or not. If -// somehting but a MOPixel or MOSParticle is being passed in as hitor, -// false will trivially be returned here. - - virtual bool ParticlePenetration(HitData &hd); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - virtual void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Attach -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Attaches this Attachable to a host MOSprite -// Arguments: Pointer to the MOSprite to attach to. Ownership is NOT transferred! -// Return value: None. - - virtual void Attach(MOSRotating *pParent); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Attach -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Attaches this Attachable to a host MOSprite -// Arguments: Pointer to the MOSprite to attach to. Ownership is NOT transferred! -// The offset from the parent's Pos to the joint position. -// Return value: None. - - virtual void Attach(MOSRotating *pParent, const Vector &parOffset) { Attach(pParent); m_ParentOffset = parOffset; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Detach -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Detaches this Attachable from its host MOSprite -// Arguments: None. -// Return value: None. - - virtual void Detach(); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: TransferJointForces -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Bundles up all the accumulated forces of this Attachable and calcs -// how they transfer to the joint, and therefore to the parent. -// Arguments: A vector that will have with the forces affecting the joint ADDED to it. -// Return value: If the accumulated forces exceed the strength of the joint, the -// attachable will only fill out the forces up to the strength threshold -// and then detach itself and return false, and the parent should react -// accordingly in that case (null out pointers to the Attachable). - - bool TransferJointForces(Vector &jointForces); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: TransferJointImpulses -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Bundles up all the accumulated impulses of this Attachable and calcs -// how they transfer to the joint, and therefore to the parent. -// Arguments: A vector that will have with the imps affecting the joint ADDED to it. -// Return value: If the accumulated impulses exceed the strength of the joint, the -// attachable will only fill out the impulses up to the strength threshold -// and then detach itself and return false, and the parent should react -// accordingly in that case (null out pointers to the Attachable). - - bool TransferJointImpulses(Vector &jointImpulses); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: CollectDamage -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the amount of damage points this Attachable has sustained and -// should cause its parent. Calling this will reset the damage count. -// This should normally be called AFTER Update() to get the correct -// damage for a given frame. -// Arguments: None. -// Return value: A float with the damage points accumulated since the last time -// this method was called. - - virtual float CollectDamage(); - -/* -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: PostTravel -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Does stuff that needs to be done after Update(). Always call after -// calling Update. -// Arguments: None. -// Return value: None. - - virtual void PostTravel(); -*/ - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Update -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Updates this MovableObject. Supposed to be done every frame. -// Arguments: None. -// Return value: None. - - virtual void Update(); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this Attachable's current graphical representation to a -// BITMAP of choice. -// Arguments: A pointer to a BITMAP to draw on. -// The absolute position of the target bitmap's upper left corner in the Scene. -// In which mode to draw in. See the DrawMode enumeration for the modes. -// Whether to not draw any extra 'ghost' items of this MovableObject, -// indicator arrows or hovering HUD text and so on. -// Return value: None. - - virtual void Draw(BITMAP *pTargetBitmap, - const Vector &targetPos = Vector(), - DrawMode mode = g_DrawColor, - bool onlyPhysical = false) const; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: RemoveWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds. -// Arguments: Amount of wounds to remove. -// Return value: Amount of damage, caused by these wounds. - - virtual int RemoveWounds(int amount); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: AddDamage -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Adds specified number of damage points to this attachable. -// Arguments: Amount of damage to add. -// Return value: None. - - virtual void AddDamage(float amount) { m_DamageCount += amount; }; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: InheritsRotAngle -////////////////////////////////////////////////////////////////////////////////////////// -// Description: If true (default old behavior) the parent MOSRotating resets attachables or emitters RotAngle every frame. False to avoid that. -// Arguments: None. -// Return value: Whether parent MOSRotating should change this RotAngle to match it's own during MOSRotating::Update - - virtual bool InheritsRotAngle() const { return m_InheritsRotAngle; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetInheritsRotAngle -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets Whether parent MOSRotating should change this RotAngle to match it's own during MOSRotating::Update. -// Arguments: Whether to inherit RotAngle or not. -// Return value: None. - - virtual void SetInheritsRotAngle(bool inherit) { m_InheritsRotAngle = inherit; } - - - /// - /// Whether this attachable is capable of having terrain collisions enabled/disabled when attached to a parent. - /// - /// If true, can have terrain collisions enabled/disabled when attached. - virtual bool CanCollideWithTerrainWhenAttached() const { return m_CanCollideWithTerrainWhenAttached; } - - - /// - /// Sets whether this attachable is capable of having terrain collisions enabled/disabled when attached to a parent. - /// - /// Whether this attachable can have terrain collisions enabled/disabled when attached. - virtual void SetCanCollideWithTerrainWhenAttached(bool canCollide) { m_CanCollideWithTerrainWhenAttached = canCollide; } - - - /// - /// Whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. - /// - /// If true, terrain collisions while attached are enabled and atoms are present in parent AtomGroup. - virtual bool IsCollidingWithTerrainWhileAttached() const { return m_IsCollidingWithTerrainWhileAttached; } - - - /// - /// Sets whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. - /// - /// Whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. - virtual void SetIsCollidingWithTerrainWhileAttached(bool isColliding) { m_IsCollidingWithTerrainWhileAttached = isColliding; } - - - /// - /// Turns on/off this Attachable's terrain collisions while it is attached by adding/removing its atoms to/from its parent AtomGroup. - /// - virtual void EnableTerrainCollisions(bool enable); - - - /// - /// Gets whether this attachable is marked be deleted along with it's parent when it's being deleted or not. - /// - /// Whether this attachable is marked to be deleted along with it's parent or not. - bool ToDeleteWithParent() const { return m_DeleteWithParent; } - -////////////////////////////////////////////////////////////////////////////////////////// -// Protected member variable and method declarations - -protected: - - // Member variables - static Entity::ClassInfo m_sClass; - // Pointer to the MOSRotating this attachable is attached to. - MOSRotating *m_pParent; - // The offset from the PARENT's Pos to the joint point this Attachable is attached. - Vector m_ParentOffset; - // The amount of impulse force needed on this to deatch it from the host Actor. In kg * m/s - float m_JointStrength; - - // The normalized joint stiffness scalar. 1.0 = all forces are trasferred - // to parent through joint. 0.5 = half are. - float m_JointStiffness; - - // The wound this Attachable will cause when it breaks from its parent. - const AEmitter *m_pBreakWound; - - // The offset to the joint (the point around which this Attachable and its - // parent hinge) from its center of mass/origin. - Vector m_JointOffset; - // The absolute position of the joint that the parent sets upon Update() if this - // Attachable is attached to it. This position is used to determine the actual - // position/center of mass of this Attachable on its Update(), using the JointOff - // and RotAngle of this attachable. - Vector m_JointPos; - - // This is the desired rotation of this Attachable, the angle that the attachable - // is striving to achieve through angle springs. - Matrix m_RotTarget; - - // The Atom ID's this' atoms will have when attached and added to a parent's AtomGroup - long int m_AtomSubgroupID; - - // Whether to draw this Attachable after (in front of) or before (behind) the parent. - bool m_DrawAfterParent; - - // The number of damage points that this Attachable has accumulated since the - // last time CollectDamage() was called. - float m_DamageCount; - - // Whether to only record linear forces, ie no torquing due to the parent offset - bool m_OnlyLinForces; - - // If true inherits Parent's rot angle, which is set MOSRotating::Update. Default is true to maintain maybe awkward but default behavior - bool m_InheritsRotAngle; - - // Whether this attachable is capable of having terrain collisions enabled/disabled when attached to a parent. - bool m_CanCollideWithTerrainWhenAttached; - - // Whether this attachable currently has terrain collisions enabled while it's attached to a parent. - bool m_IsCollidingWithTerrainWhileAttached; - - bool m_DeleteWithParent; //!< Whether this attachable is marked to be deleted along with it's parent when it's being deleted or not. - - -////////////////////////////////////////////////////////////////////////////////////////// -// Private member variable and method declarations - -private: - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Clear -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Clears all the member variables of this Attachable, effectively -// resetting the members of this abstraction level only. -// Arguments: None. -// Return value: None. - - void Clear(); - - - // Disallow the use of some implicit methods. - Attachable(const Attachable &reference); - Attachable& operator=(const Attachable &rhs); - -}; - -} // namespace RTE - -#endif // File \ No newline at end of file + class Attachable : public MOSRotating { + + public: + + EntityAllocation(Attachable) + AddScriptFunctionNames(MOSRotating, "OnAttach", "OnDetach") + SerializableOverrideMethods + ClassInfoGetters + + +#pragma region Creation + /// + /// Constructor method used to instantiate a Attachable object in system memory. Create() should be called before using the object. + /// + Attachable() { Clear(); } + + /// + /// Creates a Attachable to be identical to another, by deep copy. + /// + /// A reference to the Attachable to deep copy. + /// An error return value signaling sucess or any particular failure. Anything below 0 is an error signal. + int Create(const Attachable &reference); +#pragma endregion + +#pragma region Destruction + /// + /// Destructor method used to clean up a Attachable object before deletion from system memory. + /// + ~Attachable() override { Destroy(true); } + + /// + /// Destroys and resets (through Clear()) the Attachable object. + /// + /// Whether to only destroy the members defined in this derived class, or to destroy all inherited members also. + void Destroy(bool notInherited = false) override { if (!notInherited) { MOSRotating::Destroy(); } Clear(); } + + /// + /// Resets the entire Attachable, including its inherited members, to their default settings or values. + /// + void Reset() override { Clear(); MOSRotating::Reset(); } +#pragma endregion + +#pragma region Parent Getters and Setters + /// + /// Gets the MO which is the parent of this Attachable. + /// + /// A pointer to the parent of this Attachable. + MovableObject *GetParent() override { return m_Parent; } + + /// + /// Gets the MO which is the parent of this Attachable. + /// + /// A pointer to the parent of this Attachable. + const MovableObject *GetParent() const override { return m_Parent; } + + /// + /// Gets the MO which is the ultimate root parent of this Attachable and its parent. + /// + /// A pointer to the highest root parent of this Attachable. + MovableObject *GetRootParent() override { return m_Parent ? m_Parent->GetRootParent() : this; } + + /// + /// Gets the MO which is the ultimate root parent of this Attachable and its parent. + /// + /// A pointer to the highest root parent of this Attachable. + const MovableObject *GetRootParent() const override { return m_Parent ? m_Parent->GetRootParent() : this; } + + /// + /// Gets the stored offset between this Attachable's parent's position and the joint position. This should be maintained by the parent. + /// + /// A const reference Vector describing the offset from the parent's position to the joint position. + const Vector &GetParentOffset() const { return m_ParentOffset; } + + /// + /// Sets the stored offset between this Attachable's parent's Pos and the joint position. This should be maintained by the parent. + /// + /// A const reference to the new parent offset. + void SetParentOffset(const Vector &newParentOffset) { m_ParentOffset = newParentOffset; } + + /// + /// Indicates whether this Attachable is to be drawn after (in front of) or before (behind) the parent. + /// + /// Whether it's to be drawn after parent or not. + virtual bool IsDrawnAfterParent() const { return m_DrawAfterParent; } + + /// + /// Gets whether this attachable should be deleted automatically when its parent is being deleted or not. + /// + /// Whether this attachable is marked to be deleted along with it's parent or not. + bool ShouldDeleteWithParent() const { return m_DeleteWithParent; } +#pragma endregion + +#pragma region Joint Getters and Setters + /// + /// Gets the amount of impulse force the joint of this Attachable can handle before breaking. + /// + /// A float with the max tolerated impulse force in kg * m/s. + float GetJointStrength() const { return m_JointStrength; } + + /// + /// Sets the amount of impulse force the joint of this Attachable can handle before breaking. + /// + /// A float describing the max tolerated impulse force in Newtons (kg * m/s). + void SetJointStrength(float jointStrength) { m_JointStrength = jointStrength; } + + /// + /// Gets the stiffness scalar of the joint of this Attachable, normalized between 0 and 1.0. + /// 1.0 means impulse forces on this attachable will be transferred to the parent with 100% strength, 0 means they will not transfer at all. + /// + /// The normalized stiffness scalar of this Attachable's joint. + float GetJointStiffness() const { return m_JointStiffness; } + + /// + /// Sets the stiffness scalar of the joint of this Attachable, normalized between 0 and 1.0. + /// 1.0 means impulse forces on this attachable will be transferred to the parent with 100% strength, 0 means they will not transfer at all. + /// + /// A float describing the normalized stiffness scalar of this Attachable's joint. It will automatically be limited between 0 and 1.0. + void SetJointStiffness(float jointStiffness) { m_JointStiffness = Limit(jointStiffness, 1, 0); } + + /// + /// Gets the offset of the joint (the point around which this Attachable and its parent hinge) from this Attachable's center of mass/origin. + /// + /// A const reference Vector describing the offset of the joint relative to this Attachable's origin/center of mass position. + const Vector &GetJointOffset() const { return m_JointOffset; } + + /// + /// Sets the offset of the joint (the point around which this Attachable and its parent hinge) from this Attachable's center of mass/origin. + /// + /// A Vector describing the offset of the joint relative to the this Attachable's origin/center of mass position. + void SetJointOffset(Vector offset) { m_JointOffset = offset; } + + /// + /// Sets the position of this Attachable by defining where the joint is. + /// Upon Update(), this will be translated into what the actual position of the Attachable origin/center of mass is, depending on its set rotational angle and joint offset. + /// + /// A const reference to the new joint position to set the position with. + void SetJointPos(const Vector &jointPos) { m_JointPos = jointPos; } +#pragma endregion + +#pragma region Force Managment + /// + /// Indicates whether this Attachable only cares about linear forces that it creates through emissions, ie no torquing due to the parent offset. + /// + /// Whether this is only using linear forces or not. + bool GetOnlyLinearForces() const { return m_OnlyLinearForces; } + + /// + /// Sets whether this AEmitter should only care about linear forces that it creates through emissions, ie no torquing due to the parent offset. + /// + /// Whether to only use linear forces or not. + void SetOnlyLinearForces(bool onlyLinearForces) { m_OnlyLinearForces = onlyLinearForces; } + + /// + /// Bundles up all the accumulated forces of this Attachable and calculates how they transfer to the joint, and therefore to the parent. + /// + /// A vector that will have the forces affecting the joint ADDED to it. + /// + /// If the accumulated forces exceed the strength of the joint, the attachable will only fill out the forces up to the strength threshold and then detach itself and return false. + /// The parent should react accordingly in that case, by nulling out pointers to the Attachable. + /// + bool TransferJointForces(Vector &jointForces); + + /// + /// Bundles up all the accumulated impulse forces of this Attachable and calculates how they transfer to the joint, and therefore to the parent. + /// + /// A vector that will have with the impulse forces affecting the joint ADDED to it. + /// + /// If the accumulated impulse forces exceed the strength of the joint, the attachable will only fill out the forces up to the strength threshold and then detach itself and return false. + /// The parent should react accordingly in that case, by nulling out pointers to the Attachable. + /// + bool TransferJointImpulses(Vector &jointImpulses); +#pragma endregion + +#pragma region Damage and Wound Management + /// + /// Adds the specified number of damage points to this attachable. + /// + /// The amount of damage to add. + void AddDamage(float damageAmount) { m_DamageCount += damageAmount; } + + /// + /// Gets the amount of damage points this Attachable has sustained and should cause its parent, then resets the damage count. + /// This should normally be called AFTER Update() to get the correct damage for a given frame. + /// + /// A float with the damage points accumulated since the last time this method was called. + float CollectDamage(); + + /// + /// Gets the AEmitter that represents the wound created when this Attachable gets detached from its parent, if it's set as Vital. OWNERSHIP IS NOT TRANSFERRED! + /// + /// A const pointer to the break wound AEmitter. + const AEmitter *GetBreakWound() const { return m_BreakWound; } + + /// + /// Sets the AEmitter that represents the wound created when this Attachable gets detached from its parent, if it's set as Vital. OWNERSHIP IS NOT TRANSFERRED! + /// + /// + void SetBreakWound(const AEmitter *breakWound) { m_BreakWound = breakWound; } //TODO I added this for consistency but do we want it? Maybe should have a string version that does the presetman lookup, cause we need to have a working pointer to the breakwound. +#pragma endregion + +#pragma region Rotation Getters and Setters + /// + /// Gets whether or not this Attachable inherits its RotAngle from its parent, i.e. whether it has its RotAngle reset to match its parent every frame, if attached. + /// + /// Whether or not this Attachable inherits its RotAngle from its parent. + bool InheritsRotAngle() const { return m_InheritsRotAngle; } + + /// + /// Sets whether or not this Attachable inherits its RotAngle from its parent, i.e. whether it has its RotAngle reset to match its parent every frame, if attached. + /// + /// Whether or not to inherit its parent's RotAngle. + void SetInheritsRotAngle(bool inheritsRotAngle) { m_InheritsRotAngle = inheritsRotAngle; } + + /// + /// Gets the target rotation that this Attachable should be striving to match its real rotation with, if it is attached. + /// The joint stiffness will determine how strong the scalar spring is between the current rotation and the target set here. + /// + /// A float for the current target angle in radians. + float GetRotTarget() const { return m_RotTarget.GetRadAngle(); } + + /// + /// Sets the target rotation angle in radians that this Attachable should be striving to match its real rotation with, if it is attached. + /// The joint stiffness will determine how strong the scalar spring is between the current rotation and the target set here. + /// + /// A float describing the target angle in radians. + void SetRotTarget(float rotRadAngle) { m_RotTarget.SetRadAngle(rotRadAngle); } +#pragma endregion + +#pragma region Collision Management + /// + /// Gets the subgroup ID of this' Atoms. + /// + /// The subgroup ID of this' Atoms. + long int GetAtomSubgroupID() const { return m_AtomSubgroupID; } + + /// + /// Sets the subgroup ID of this' Atoms + /// + /// A long int describing the new subgroup id of this' Atoms. + void SetAtomSubgroupID(long int subgroupID = 0) { m_AtomSubgroupID = subgroupID; } + + /// + /// Whether this attachable is capable of having terrain collisions enabled/disabled when attached to a parent. + /// + /// If true, can have terrain collisions enabled/disabled when attached. + virtual bool CanCollideWithTerrainWhenAttached() const { return m_CanCollideWithTerrainWhenAttached; } + + /// + /// Sets whether this attachable is capable of having terrain collisions enabled/disabled when attached to a parent. + /// + /// Whether this attachable can have terrain collisions enabled/disabled when attached. + virtual void SetCanCollideWithTerrainWhenAttached(bool canCollide) { m_CanCollideWithTerrainWhenAttached = canCollide; } + + /// + /// Whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. + /// + /// If true, terrain collisions while attached are enabled and atoms are present in parent AtomGroup. + virtual bool IsCollidingWithTerrainWhileAttached() const { return m_IsCollidingWithTerrainWhileAttached; } + + /// + /// Sets whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. + /// + /// Whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. + virtual void SetIsCollidingWithTerrainWhileAttached(bool isColliding) { m_IsCollidingWithTerrainWhileAttached = isColliding; } + + /// + /// Turns on/off this Attachable's terrain collisions while it is attached by adding/removing its atoms to/from its parent AtomGroup. + /// + /// Whether or not to add or remove this Attachable's atoms to/from the parent's AtomGroup. + virtual void EnableTerrainCollisions(bool enable); +#pragma endregion + +#pragma region Attachment Managment + /// + /// Indicates whether this Attachable is attached to an MOSRotating parent or not. + /// + /// Whether it's attached or not. + bool IsAttached() const { return m_Parent != nullptr; } + + /// + /// Indicates whether this Attachable is attached to the specified MOSRotating or not. + /// + /// A pointer to which MOSRotating you want to check for. + /// Whether it's attached or not. + bool IsAttachedTo(const MOSRotating *parentToCheck) const { return m_Parent == parentToCheck; } + + /// + /// Attaches this Attachable to a new parent MOSRotating. + /// + /// A pointer to the MOSRotating to attach to. Ownership is NOT transferred! + virtual void Attach(MOSRotating *newParent); + + /// + /// Attaches this Attachable to a new parent MOSRotating, with the specified parent offset. + /// + /// A pointer to the MOSRotating to attach to. Ownership is NOT transferred! + /// The offset from the parent's Pos to the joint Pos. + void Attach(MOSRotating *newParent, const Vector &parentOffset) { Attach(newParent); m_ParentOffset = parentOffset; } + + /// + /// Detaches this Attachable from its host MOSprite + /// + virtual void Detach(); +#pragma endregion + +#pragma region Override Methods + /// + /// Calculates the collision response when another MO's Atom collides with this MO's physical representation. + /// The effects will be applied directly to this MO, and also represented in the passed in HitData. + /// + /// Reference to the HitData struct which describes the collision. This will be modified to represent the results of the collision. + /// Whether the collision has been deemed valid. If false, then disregard any impulses in the Hitdata. + bool CollideAtPoint(HitData &hitData) override; + + /// + /// Determines whether a particle which has hit this MO will penetrate, and if so, whether it gets lodged or exits on the other side of this MO. + /// Appropriate effects will be determined and applied ONLY IF there was penetration! If not, nothing will be affected. + /// + /// The HitData describing the collision in detail, the impulses have to have been filled out! + /// + /// Whether the particle managed to penetrate into this MO or not. + /// If something other than an MOPixel or MOSParticle is being passed in as the hitor, false will trivially be returned here. + /// + bool ParticlePenetration(HitData &hitData) override; + + /// + /// Gibs this, effectively destroying it and creating gibs in its place. + /// + /// The impulse (kg * m/s) of the impact causing the gibbing to happen. + /// The internal blast impulse which will push the gibs away from the center. + /// A pointer to an MO which the gibs shuold not be colliding with! + void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *MOToIgnore = 0) override; + + /// + /// Updates this Attachable. Supposed to be done every frame. + /// + void Update() override; +#pragma endregion + //TODO This is crap but MOSR needs to account for damage multiplier + virtual int RemoveWounds(int amount) { return MOSRotating::RemoveWounds(amount) * m_DamageMultiplier; } + + private: + + static Entity::ClassInfo m_sClass; //!< ClassInfo for this class. + + MOSRotating *m_Parent; //!< Pointer to the MOSRotating this attachable is attached to. + Vector m_ParentOffset; //!< The offset from the parent's Pos to the joint point this Attachable is attached with. + bool m_DrawAfterParent; //!< Whether to draw this Attachable after (in front of) or before (behind) the parent. + bool m_DeleteWithParent; //!< Whether this attachable should be deleted when its parent is set ToDelete. + + float m_JointStrength; //!< The amount of impulse force needed on this to deatch it from the host Actor, in kg * m/s. + float m_JointStiffness; //!< The normalized joint stiffness scalar. 1.0 means impulse forces on this attachable will be transferred to the parent with 100% strength, 0 means they will not transfer at all. + Vector m_JointOffset; //!< The offset to the joint (the point around which this Attachable and its parent hinge) from its center of mass/origin. + Vector m_JointPos; //!< The absolute position of the joint that the parent sets upon Update() if this Attachable is attached to it. + + bool m_OnlyLinearForces; //!< Whether to only record linear forces, ie no torquing due to the parent offset. + + float m_DamageCount; //!< The number of damage points that this Attachable has accumulated since the last time CollectDamage() was called. + const AEmitter *m_BreakWound; //!< The wound this Attachable will cause when it breaks from its parent. + + bool m_InheritsRotAngle; //!< Whether this Attachable should inherit its parent's RotAngle. + Matrix m_RotTarget; //!< The desired rotation of this Attachable, the angle it's trying to achieve through angle springs. + + long int m_AtomSubgroupID; //!< The Atom IDs this' atoms will have when attached and added to a parent's AtomGroup. + bool m_CanCollideWithTerrainWhenAttached; //!< Whether this attachable is capable of having terrain collisions enabled/disabled when attached to a parent. + bool m_IsCollidingWithTerrainWhileAttached; //!< Whether this attachable currently has terrain collisions enabled while it's attached to a parent. + + /// + /// Clears all the member variables of this Attachable, effectively resetting the members of this abstraction level only. + /// + void Clear(); + + // Disallow the use of some implicit methods. + Attachable(const Attachable &reference) {} + Attachable &operator=(const Attachable &rhs) {} + }; + +} +#endif \ No newline at end of file diff --git a/Entities/HDFirearm.h b/Entities/HDFirearm.h index 6fbcbad36..7da70e29e 100644 --- a/Entities/HDFirearm.h +++ b/Entities/HDFirearm.h @@ -453,7 +453,7 @@ ClassInfoGetters // Arguments: Pointer to the MOSprite to attach to. Ownership is NOT transferred! // Return value: None. - virtual void Attach(MOSRotating *pParent) { HeldDevice::Attach(pParent); m_Reloading = false; m_ReloadTmr.Reset(); } + virtual void Attach(MOSRotating *newParent) { HeldDevice::Attach(newParent); m_Reloading = false; m_ReloadTmr.Reset(); } ////////////////////////////////////////////////////////////////////////////////////////// From 5361c54a006070f9ae3eb573c12d036741b3339b Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 6 Aug 2020 01:44:53 -0300 Subject: [PATCH 002/144] Added Attachable member variables for transferring damage to parent and having separate break wounds for the attachable and the parent. Mostly not implemented yet though. Cleaned up terrain collision handling so there's only one member variable m_CollidesWithTerrainWhileAttached, and a helper method to organize parent atoms. Cleaned up various junk code and unused RotTarget since it didn't work/wasn't used and doesn't really make sense IMO. Removed Attach and Detach, now SetParent does what they did. It's protected access since it should only really be used by MOSRotating (which is now a Friend class of Attachable) --- CHANGELOG.md | 7 ++ Entities/Attachable.cpp | 174 +++++++++++++++------------------------ Entities/Attachable.h | 157 +++++++++++++++-------------------- Entities/MOSRotating.cpp | 47 +++++------ Managers/LuaMan.cpp | 21 +++-- 5 files changed, 172 insertions(+), 234 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96ed82c93..0503475e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - New shortcut `ALT + W` to generate a detailed 140x55px mini `WorldDump` to be used for scene previews. No relying on `SceneEditor`, stretches over whole image, no ugly cyan bunkers, no actors or glows and has sky gradient. +- New INI and Lua (R/W) properties for Attachables: + `TransfersDamageToParent = 0/1`. If enabled, the Attachable will act like hardcoded ones and transfer damage to its parent. For Attachables attached to other Attachables, the parent Attachable (and any of its parents, etc.) must have this enabled for it to work. + `ParentBreakWound = AEmitter...`. Use this to optionally define different BreakWounds for the Attachable and its parent. Matches BreakWound by default for ease of use. + `BreakWound` is also now R/W accessible to Lua. + ### Changed - Lua error reporting has been improved so script errors will always show filename and line number. @@ -139,6 +144,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Removed `MOSParticle` property `Framerate` and lua bindings. `MOSParticle` animation is now handled with `SpriteAnimMode` like everything else. +- Removed `Attachable` Lua write capability for `AtomSubGroupID` as changing this can cause all kinds of problems, and `RotTarget` as this didn't actually work. + *** ## [0.1.0 pre-release 2][0.1.0-pre2] - 2020/05/08 diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 057726375..078021c1d 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -15,6 +15,7 @@ namespace RTE { m_Parent = 0; m_ParentOffset.Reset(); m_DrawAfterParent = true; + m_TransfersDamageToParent = false; m_DeleteWithParent = false; m_JointStrength = 10; @@ -26,13 +27,12 @@ namespace RTE { m_DamageCount = 0; m_BreakWound = 0; + m_ParentBreakWound = 0; m_InheritsRotAngle = true; - m_RotTarget.Reset(); m_AtomSubgroupID = -1; - m_CanCollideWithTerrainWhenAttached = false; - m_IsCollidingWithTerrainWhileAttached = false; + m_CollidesWithTerrainWhileAttached = false; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -43,6 +43,7 @@ namespace RTE { m_Parent = reference.m_Parent; m_ParentOffset = reference.m_ParentOffset; m_DrawAfterParent = reference.m_DrawAfterParent; + m_TransfersDamageToParent = reference.m_TransfersDamageToParent; m_DeleteWithParent = reference.m_DeleteWithParent; m_JointStrength = reference.m_JointStrength; @@ -54,13 +55,12 @@ namespace RTE { m_DamageCount = reference.m_DamageCount; m_BreakWound = reference.m_BreakWound; + m_ParentBreakWound = reference.m_ParentBreakWound; m_InheritsRotAngle = reference.m_InheritsRotAngle; - m_RotTarget = reference.m_RotTarget; m_AtomSubgroupID = reference.m_AtomSubgroupID; - m_CanCollideWithTerrainWhenAttached = reference.m_CanCollideWithTerrainWhenAttached; - m_IsCollidingWithTerrainWhileAttached = reference.m_IsCollidingWithTerrainWhileAttached; + m_CollidesWithTerrainWhileAttached = reference.m_CollidesWithTerrainWhileAttached; return 0; } @@ -72,6 +72,8 @@ namespace RTE { reader >> m_ParentOffset; } else if (propName == "DrawAfterParent") { reader >> m_DrawAfterParent; + } else if (propName == "TransfersDamageToParent") { + reader >> m_TransfersDamageToParent; } else if (propName == "DeleteWithParent") { reader >> m_DeleteWithParent; } else if (propName == "JointStrength" || propName == "Strength") { @@ -82,10 +84,13 @@ namespace RTE { reader >> m_JointOffset; } else if (propName == "BreakWound") { m_BreakWound = dynamic_cast(g_PresetMan.GetEntityPreset(reader)); + if (!m_ParentBreakWound) { m_ParentBreakWound = m_BreakWound; } + } else if (propName == "ParentBreakWound") { + m_ParentBreakWound = dynamic_cast(g_PresetMan.GetEntityPreset(reader)); } else if (propName == "InheritsRotAngle") { reader >> m_InheritsRotAngle; } else if (propName == "CollidesWithTerrainWhenAttached") { - reader >> m_CanCollideWithTerrainWhenAttached; + reader >> m_CollidesWithTerrainWhileAttached; } else { return MOSRotating::ReadProperty(propName, reader); } @@ -102,6 +107,8 @@ namespace RTE { writer << m_ParentOffset; writer.NewProperty("DrawAfterParent"); writer << m_DrawAfterParent; + writer.NewProperty("TransfersDamageToParent"); + writer << m_TransfersDamageToParent; writer.NewProperty("DeleteWithParent"); writer << m_DeleteWithParent; @@ -114,11 +121,13 @@ namespace RTE { writer.NewProperty("BreakWound"); writer << m_BreakWound; + writer.NewProperty("ParentBreakWound"); + writer << m_ParentBreakWound; writer.NewProperty("InheritsRotAngle"); writer << m_InheritsRotAngle; - writer.NewProperty("CollidesWithTerrainWhenAttached"); - writer << m_CanCollideWithTerrainWhenAttached; + writer.NewProperty("CollidesWithTerrainWhileAttached"); + writer << m_CollidesWithTerrainWhileAttached; return 0; } @@ -197,82 +206,13 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Attachable::EnableTerrainCollisions(bool enable) { - if (IsAttached() && CanCollideWithTerrainWhenAttached()) { - if (!IsCollidingWithTerrainWhileAttached() && enable) { - m_Parent->GetAtomGroup()->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), GetParentOffset() - GetJointOffset()); - SetIsCollidingWithTerrainWhileAttached(true); - } else if (IsCollidingWithTerrainWhileAttached() && !enable) { - m_Parent->GetAtomGroup()->RemoveAtoms(GetAtomSubgroupID()); - SetIsCollidingWithTerrainWhileAttached(false); - } - } else if (IsAttached() && !CanCollideWithTerrainWhenAttached()) { - if (enable || !enable) { - g_ConsoleMan.PrintString("ERROR: Tried to toggle collisions for attachable that was not set to collide when initially created!"); - } + void Attachable::SetCollidesWithTerrainWhileAttached(bool collidesWithTerrainWhileAttached) { + if (m_CollidesWithTerrainWhileAttached != collidesWithTerrainWhileAttached) { + OrganizeAtomsInParent(collidesWithTerrainWhileAttached); + m_CollidesWithTerrainWhileAttached = collidesWithTerrainWhileAttached; } } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - void Attachable::Attach(MOSRotating *newParent) { - if (newParent != nullptr) { - m_Parent = newParent; - m_Team = m_Parent->GetTeam(); - - //TODO see if this is reasonable. Seems like inventory swapping should do this cleanup internally. Also note that it used to be done regardless of newParent existing but I changed that, might be bad? - // Timers are reset here as a precaution, so that if something was sitting in an inventory, it doesn't cause backed up emissions. - ResetAllTimers(); - - if (GetRootParent()->HasEverBeenAddedToMovableMan()) { - RunScriptedFunctionInAppropriateScripts("OnAttach", false, false, {m_Parent}); - } - } - } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - void Attachable::Detach() { - if (m_Parent) { - m_Parent->GetAtomGroup()->RemoveAtoms(m_AtomSubgroupID); - } - - m_Team = -1; - MOSRotating *temporaryParent = m_Parent; - m_Parent = 0; - m_RootMOID = m_MOID; - - //TODO I don't think we need these at all? They're basically duplicates, and I think the m_MOID = g_NoMOID is backwards anyway??? -#if defined DEBUG_BUILD || defined MIN_DEBUG_BUILD - RTEAssert(m_RootMOID == g_NoMOID || (m_RootMOID >= 0 && m_RootMOID < g_MovableMan.GetMOIDCount()), "MOID out of bounds!"); - RTEAssert(m_MOID == g_NoMOID || (m_MOID >= 0 && m_MOID < g_MovableMan.GetMOIDCount()), "MOID out of bounds!"); -#endif - - m_RestTimer.Reset(); - - if (temporaryParent != nullptr && temporaryParent->GetRootParent()->HasEverBeenAddedToMovableMan()) { - RunScriptedFunctionInAppropriateScripts("OnDetach", false, false, {temporaryParent}); - } - } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - bool Attachable::CollideAtPoint(HitData &hd) { - return MOSRotating::CollideAtPoint(hd); - //TODO potentially make this happen, I guess the concepts are handled in MOSR::ApplyAttachableForces, which seems weird. If I don't implement, remove this whole override method cause it's otherwise unused. - /* - // See if the impact created a force enough to detach from parent. - if (m_pParent && hd.ResImpulse[HITEE].GetMagnitude() > m_JointStrength) { - m_pParent->AddAbsImpulseForce(Vector(hd.ResImpulse[HITEE]).SetMagnitude(m_JointStrength), m_JointPos); - - Detach(); - } - else { - - } - */ - } - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Attachable::ParticlePenetration(HitData &hd) { @@ -308,7 +248,7 @@ namespace RTE { if (m_Parent) { m_Parent->RemoveAttachable(this); } else { - Detach(); + SetParent(nullptr); } MOSRotating::GibThis(impactImpulse, internalBlast, pIgnoreMO); } @@ -333,31 +273,6 @@ namespace RTE { //TODO RotAngle should be set here based on whether or not this InheritsRotAngle. It's currently done by MOSR which is dumdum. Alternatively, see below. - //TODO m_RotTarget is handled here, the idea is to use spring concepts instead of just setting RotAngle. Either fix it, or delete it and the header stuff for it. - /* - float springDelta = m_Rotation.GetRadAngle() - m_RotTarget.GetRadAngle(); - // Eliminate full rotations - while (fabs(springDelta) > c_TwoPI) { - springDelta -= springDelta > 0 ? c_TwoPI : -c_TwoPI; - } - // Eliminate rotations over half a turn - //if (fabs(springDelta) > c_PI) { - // springDelta = (springDelta > 0 ? -c_PI : c_PI) + (springDelta - (springDelta > 0 ? c_PI : -c_PI)); - //} - - // Break the spring if close to target angle. - if (fabs(springDelta) > 0.1) { - m_AngularVel -= springDelta * fabs(springDelta);// * m_JointStiffness; - } else if (fabs(m_AngularVel) > 0.1) { - m_AngularVel *= 0.5; - } - //m_Rotation += springDelta * m_JointStiffness; - //m_AngularVel -= springDelta * m_JointStiffness; - - // Apply the rotational velocity - //m_Rotation += m_AngularVel * g_TimerMan.GetDeltaTimeSecs(); - */ - m_DeepCheck = false; } @@ -366,4 +281,47 @@ namespace RTE { // If we're attached to something, MovableMan doesn't own us, and therefore isn't calling our UpdateScripts method (and neither is our parent), so we should here. if (m_Parent != nullptr && GetRootParent()->HasEverBeenAddedToMovableMan()) { UpdateScripts(); } } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::SetParent(MOSRotating *newParent) { + if (newParent == m_Parent) { + return; + } + + m_Team = newParent ? newParent->GetTeam() : -1; + MOSRotating *parentToUseForScriptCall = newParent ? newParent : m_Parent; + + if (newParent) { + //TODO see if this is reasonable. Seems like inventory swapping should do this cleanup internally. Also note that it used to be done regardless of newParent existing (i.e. any time Attach was called) but I changed that, might be bad? + + // Timers are reset here as a precaution, so that if something was sitting in an inventory, it doesn't cause backed up emissions. + ResetAllTimers(); + + m_Parent = newParent; + OrganizeAtomsInParent(newParent != nullptr); + } else { + m_RootMOID = m_MOID; + m_RestTimer.Reset(); + + OrganizeAtomsInParent(newParent != nullptr); + m_Parent = newParent; + } + + if (parentToUseForScriptCall && parentToUseForScriptCall->GetRootParent()->HasEverBeenAddedToMovableMan()) { + RunScriptedFunctionInAppropriateScripts(newParent ? "OnAttach" : "OnDetach", false, false, {parentToUseForScriptCall}); + } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::OrganizeAtomsInParent(bool addToParent) { + if (IsAttached()) { + if (addToParent) { + m_Parent->GetAtomGroup()->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), GetParentOffset() - GetJointOffset()); + } else { + m_Parent->GetAtomGroup()->RemoveAtoms(GetAtomSubgroupID()); + } + } + } } \ No newline at end of file diff --git a/Entities/Attachable.h b/Entities/Attachable.h index afa07a6ad..346888806 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -11,6 +11,7 @@ namespace RTE { /// An articulated, detachable part of an Actor's body. /// class Attachable : public MOSRotating { + friend class MOSRotating; public: @@ -65,6 +66,19 @@ namespace RTE { /// A pointer to the parent of this Attachable. const MovableObject *GetParent() const override { return m_Parent; } + /// + /// Indicates whether this Attachable is attached to an MOSRotating parent or not. + /// + /// Whether it's attached or not. + bool IsAttached() const { return m_Parent != nullptr; } + + /// + /// Indicates whether this Attachable is attached to the specified MOSRotating or not. + /// + /// A pointer to which MOSRotating you want to check for. + /// Whether it's attached or not. + bool IsAttachedTo(const MOSRotating *parentToCheck) const { return m_Parent == parentToCheck; } + /// /// Gets the MO which is the ultimate root parent of this Attachable and its parent. /// @@ -86,20 +100,32 @@ namespace RTE { /// /// Sets the stored offset between this Attachable's parent's Pos and the joint position. This should be maintained by the parent. /// - /// A const reference to the new parent offset. + /// A const reference to the new parent offset. void SetParentOffset(const Vector &newParentOffset) { m_ParentOffset = newParentOffset; } /// - /// Indicates whether this Attachable is to be drawn after (in front of) or before (behind) the parent. + /// Gets whether this Attachable is to be drawn after (in front of) or before (behind) the parent. + /// + /// Whether this Attachable is to be drawn after its parent or not. + bool IsDrawnAfterParent() const override { return m_DrawAfterParent; } + + /// + /// Gets whether this Attachable will collect its damage and transfer it to its parent if attached. Transferred damage accounts for the Attachable's damage multiplier. /// - /// Whether it's to be drawn after parent or not. - virtual bool IsDrawnAfterParent() const { return m_DrawAfterParent; } + /// Whether this Attachable will transfer damage to its parent or not. + bool GetTransfersDamageToParent() const { return m_TransfersDamageToParent; } /// - /// Gets whether this attachable should be deleted automatically when its parent is being deleted or not. + /// Sets whether this Attachable will collect its damage and transfer it to its parent if attached. Transferred damage accounts for the Attachable's damage multiplier. + /// + /// Whether this Attachable should transfer damage to its parent. + void SetTransfersDamageToParent(bool transfersDamageToParent) { m_TransfersDamageToParent = transfersDamageToParent; } + + /// + /// Gets whether this attachable will be deleted automatically when its parent is being deleted or not. /// /// Whether this attachable is marked to be deleted along with it's parent or not. - bool ShouldDeleteWithParent() const { return m_DeleteWithParent; } + bool ToDeleteWithParent() const { return m_DeleteWithParent; } #pragma endregion #pragma region Joint Getters and Setters @@ -198,16 +224,28 @@ namespace RTE { float CollectDamage(); /// - /// Gets the AEmitter that represents the wound created when this Attachable gets detached from its parent, if it's set as Vital. OWNERSHIP IS NOT TRANSFERRED! + /// Gets the AEmitter that represents the wound added to this Attachable when it gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! /// /// A const pointer to the break wound AEmitter. const AEmitter *GetBreakWound() const { return m_BreakWound; } /// - /// Sets the AEmitter that represents the wound created when this Attachable gets detached from its parent, if it's set as Vital. OWNERSHIP IS NOT TRANSFERRED! + /// Sets the AEmitter that represents the wound added to this Attachable when it gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! /// - /// + /// The AEmitter to use for this Attachable's breakwound. void SetBreakWound(const AEmitter *breakWound) { m_BreakWound = breakWound; } //TODO I added this for consistency but do we want it? Maybe should have a string version that does the presetman lookup, cause we need to have a working pointer to the breakwound. + + /// + /// Gets the AEmitter that represents the wound added to this Attachable's parent when this Attachable gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! + /// + /// A const pointer to the parent break wound AEmitter. + const AEmitter *GetParentBreakWound() const { return m_ParentBreakWound; } + + /// + /// Sets the AEmitter that represents the wound added to this Attachable's parent when this Attachable gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! + /// + /// The AEmitter to use for the parent's breakwound. + void SetParentBreakWound(const AEmitter *breakWound) { m_ParentBreakWound = breakWound; } #pragma endregion #pragma region Rotation Getters and Setters @@ -222,20 +260,6 @@ namespace RTE { /// /// Whether or not to inherit its parent's RotAngle. void SetInheritsRotAngle(bool inheritsRotAngle) { m_InheritsRotAngle = inheritsRotAngle; } - - /// - /// Gets the target rotation that this Attachable should be striving to match its real rotation with, if it is attached. - /// The joint stiffness will determine how strong the scalar spring is between the current rotation and the target set here. - /// - /// A float for the current target angle in radians. - float GetRotTarget() const { return m_RotTarget.GetRadAngle(); } - - /// - /// Sets the target rotation angle in radians that this Attachable should be striving to match its real rotation with, if it is attached. - /// The joint stiffness will determine how strong the scalar spring is between the current rotation and the target set here. - /// - /// A float describing the target angle in radians. - void SetRotTarget(float rotRadAngle) { m_RotTarget.SetRadAngle(rotRadAngle); } #pragma endregion #pragma region Collision Management @@ -251,79 +275,20 @@ namespace RTE { /// A long int describing the new subgroup id of this' Atoms. void SetAtomSubgroupID(long int subgroupID = 0) { m_AtomSubgroupID = subgroupID; } - /// - /// Whether this attachable is capable of having terrain collisions enabled/disabled when attached to a parent. - /// - /// If true, can have terrain collisions enabled/disabled when attached. - virtual bool CanCollideWithTerrainWhenAttached() const { return m_CanCollideWithTerrainWhenAttached; } - - /// - /// Sets whether this attachable is capable of having terrain collisions enabled/disabled when attached to a parent. - /// - /// Whether this attachable can have terrain collisions enabled/disabled when attached. - virtual void SetCanCollideWithTerrainWhenAttached(bool canCollide) { m_CanCollideWithTerrainWhenAttached = canCollide; } - /// /// Whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. /// /// If true, terrain collisions while attached are enabled and atoms are present in parent AtomGroup. - virtual bool IsCollidingWithTerrainWhileAttached() const { return m_IsCollidingWithTerrainWhileAttached; } + bool GetCollidesWithTerrainWhileAttached() const { return m_CollidesWithTerrainWhileAttached; } /// /// Sets whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. /// - /// Whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. - virtual void SetIsCollidingWithTerrainWhileAttached(bool isColliding) { m_IsCollidingWithTerrainWhileAttached = isColliding; } - - /// - /// Turns on/off this Attachable's terrain collisions while it is attached by adding/removing its atoms to/from its parent AtomGroup. - /// - /// Whether or not to add or remove this Attachable's atoms to/from the parent's AtomGroup. - virtual void EnableTerrainCollisions(bool enable); -#pragma endregion - -#pragma region Attachment Managment - /// - /// Indicates whether this Attachable is attached to an MOSRotating parent or not. - /// - /// Whether it's attached or not. - bool IsAttached() const { return m_Parent != nullptr; } - - /// - /// Indicates whether this Attachable is attached to the specified MOSRotating or not. - /// - /// A pointer to which MOSRotating you want to check for. - /// Whether it's attached or not. - bool IsAttachedTo(const MOSRotating *parentToCheck) const { return m_Parent == parentToCheck; } - - /// - /// Attaches this Attachable to a new parent MOSRotating. - /// - /// A pointer to the MOSRotating to attach to. Ownership is NOT transferred! - virtual void Attach(MOSRotating *newParent); - - /// - /// Attaches this Attachable to a new parent MOSRotating, with the specified parent offset. - /// - /// A pointer to the MOSRotating to attach to. Ownership is NOT transferred! - /// The offset from the parent's Pos to the joint Pos. - void Attach(MOSRotating *newParent, const Vector &parentOffset) { Attach(newParent); m_ParentOffset = parentOffset; } - - /// - /// Detaches this Attachable from its host MOSprite - /// - virtual void Detach(); + /// Whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. + void SetCollidesWithTerrainWhileAttached(bool collidesWithTerrainWhileAttached); #pragma endregion #pragma region Override Methods - /// - /// Calculates the collision response when another MO's Atom collides with this MO's physical representation. - /// The effects will be applied directly to this MO, and also represented in the passed in HitData. - /// - /// Reference to the HitData struct which describes the collision. This will be modified to represent the results of the collision. - /// Whether the collision has been deemed valid. If false, then disregard any impulses in the Hitdata. - bool CollideAtPoint(HitData &hitData) override; - /// /// Determines whether a particle which has hit this MO will penetrate, and if so, whether it gets lodged or exits on the other side of this MO. /// Appropriate effects will be determined and applied ONLY IF there was penetration! If not, nothing will be affected. @@ -351,6 +316,14 @@ namespace RTE { //TODO This is crap but MOSR needs to account for damage multiplier virtual int RemoveWounds(int amount) { return MOSRotating::RemoveWounds(amount) * m_DamageMultiplier; } + protected: + + /// + /// Attaches this Attachable to a new parent MOSRotating, safely detaching from its old parent first if there is one. + /// + /// A pointer to the MOSRotating to attach to. Ownership is NOT transferred! + void SetParent(MOSRotating *newParent); + private: static Entity::ClassInfo m_sClass; //!< ClassInfo for this class. @@ -358,6 +331,7 @@ namespace RTE { MOSRotating *m_Parent; //!< Pointer to the MOSRotating this attachable is attached to. Vector m_ParentOffset; //!< The offset from the parent's Pos to the joint point this Attachable is attached with. bool m_DrawAfterParent; //!< Whether to draw this Attachable after (in front of) or before (behind) the parent. + bool m_TransfersDamageToParent; // + /// Turns on/off this Attachable's terrain collisions while it is attached by adding/removing its atoms to/from its parent AtomGroup. + /// + /// Whether to add this Attachable's atoms to the parent's AtomGroup or remove them. + void OrganizeAtomsInParent(bool addToParent); /// /// Clears all the member variables of this Attachable, effectively resetting the members of this abstraction level only. diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 21bb2ab69..73e9643d1 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -432,22 +432,18 @@ int MOSRotating::Save(Writer &writer) const /// /// The wound AEmitter to add /// The vector to set as the wound AEmitter's parent offset -void MOSRotating::AddWound(AEmitter *pWound, const Vector & parentOffsetToSet, bool checkGibWoundLimit) -{ - if (pWound) - { - if (checkGibWoundLimit && !ToDelete() && m_GibWoundLimit && m_Wounds.size() + 1 > m_GibWoundLimit) - { +void MOSRotating::AddWound(AEmitter *pWound, const Vector & parentOffsetToSet, bool checkGibWoundLimit) { + if (pWound) { + if (checkGibWoundLimit && !ToDelete() && m_GibWoundLimit && m_Wounds.size() + 1 > m_GibWoundLimit) { // Indicate blast in opposite direction of emission // TODO: don't hardcode here, get some data from the emitter Vector blast(-5, 0); blast.RadRotate(pWound->GetEmitAngle()); GibThis(blast); return; - } - else - { - pWound->Attach(this, parentOffsetToSet); + } else { + pWound->SetParentOffset(parentOffsetToSet); + pWound->SetParent(this); m_Wounds.push_back(pWound); } } @@ -1667,22 +1663,15 @@ void MOSRotating::AddAttachable(Attachable *pAttachable, bool isHardcodedAttacha /// The Attachable to add. /// The vector to set as the Attachable's parent offset. /// Whether or not the Attachable should be treated as hardcoded. -void MOSRotating::AddAttachable(Attachable *pAttachable, const Vector & parentOffsetToSet, bool isHardcodedAttachable) -{ - if (pAttachable) - { - pAttachable->Attach(this, parentOffsetToSet); +void MOSRotating::AddAttachable(Attachable *pAttachable, const Vector & parentOffsetToSet, bool isHardcodedAttachable) { + if (pAttachable) { + pAttachable->SetParentOffset(parentOffsetToSet); + pAttachable->SetParent(this); // Set the attachable's subgroup ID to it's Unique ID to avoid any possible conflicts when adding atoms to parent group. pAttachable->SetAtomSubgroupID(pAttachable->GetUniqueID()); - if (pAttachable->CanCollideWithTerrainWhenAttached()) - { - pAttachable->EnableTerrainCollisions(true); - } - - if (!isHardcodedAttachable) - { + if (!isHardcodedAttachable) { m_Attachables.push_back(pAttachable); } m_AllAttachables.push_back(pAttachable); @@ -1719,7 +1708,11 @@ bool MOSRotating::RemoveAttachable(Attachable *pAttachable) { if (m_AllAttachables.size() > 0) { m_AllAttachables.remove(pAttachable); } - pAttachable->ToDeleteWithParent() ? pAttachable->SetToDelete() : pAttachable->Detach(); + if (pAttachable->ToDeleteWithParent()) { + pAttachable->SetToDelete(); + } else { + pAttachable->SetParent(nullptr); + } return true; } return false; @@ -1730,14 +1723,12 @@ bool MOSRotating::RemoveAttachable(Attachable *pAttachable) { /// Either detaches or deletes all of this MOSRotating's attachables /// /// Whether to detach or delete the attachables. Setting this to true deletes them, setting it to false detaches them -void MOSRotating::DetachOrDestroyAll(bool destroy) -{ - for (list::const_iterator aItr = m_AllAttachables.begin(); aItr != m_AllAttachables.end(); ++aItr) - { +void MOSRotating::DetachOrDestroyAll(bool destroy) { + for (list::const_iterator aItr = m_AllAttachables.begin(); aItr != m_AllAttachables.end(); ++aItr) { if (destroy) delete (*aItr); else - (*aItr)->Detach(); + (*aItr)->SetParent(nullptr); } m_AllAttachables.clear(); diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 46e595485..d60573c71 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -779,22 +779,25 @@ int LuaMan::Create() .def_readonly("Wounds", &MOSRotating::m_Wounds, return_stl_iterator), CONCRETELUABINDING(Attachable, MOSRotating) - .property("ParentOffset", &Attachable::GetParentOffset, &Attachable::SetParentOffset) - .property("JointOffset", &Attachable::GetJointOffset, &Attachable::SetJointOffset) - .property("JointStiffness", &Attachable::GetJointStiffness, &Attachable::SetJointStiffness) - .property("JointStrength", &Attachable::GetJointStrength, &Attachable::SetJointStrength) - .property("RotTarget", &Attachable::GetRotTarget, &Attachable::SetRotTarget) - .property("AtomSubgroupID", &Attachable::GetAtomSubgroupID, &Attachable::SetAtomSubgroupID) - .property("OnlyLinearForces", &Attachable::GetOnlyLinearForces, &Attachable::SetOnlyLinearForces) .def("IsAttached", &Attachable::IsAttached) .def("IsAttachedTo", &Attachable::IsAttachedTo) + .property("ParentOffset", &Attachable::GetParentOffset, &Attachable::SetParentOffset) .def("IsDrawnAfterParent", &Attachable::IsDrawnAfterParent) + .property("TransfersDamageToParent", &Attachable::GetTransfersDamageToParent, &Attachable::SetTransfersDamageToParent) + .property("JointStrength", &Attachable::GetJointStrength, &Attachable::SetJointStrength) + .property("JointStiffness", &Attachable::GetJointStiffness, &Attachable::SetJointStiffness) + .property("JointOffset", &Attachable::GetJointOffset, &Attachable::SetJointOffset) + .property("OnlyLinearForces", &Attachable::GetOnlyLinearForces, &Attachable::SetOnlyLinearForces) .def("TransferJointForces", &Attachable::TransferJointForces) .def("TransferJointImpulses", &Attachable::TransferJointImpulses) .def("CollectDamage", &Attachable::CollectDamage) + .def("GetBreakWound", &Attachable::GetBreakWound) + .def("SetBreakWound", &Attachable::SetBreakWound) + .def("GetParentBreakWound", &Attachable::GetParentBreakWound) + .def("SetParentBreakWound", &Attachable::SetParentBreakWound) .property("InheritsRotAngle", &Attachable::InheritsRotAngle, &Attachable::SetInheritsRotAngle) - .property("IsCollidingWithTerrainWhileAttached", &Attachable::IsCollidingWithTerrainWhileAttached) - .def("EnableTerrainCollisions", &Attachable::EnableTerrainCollisions), + .property("AtomSubgroupID", &Attachable::GetAtomSubgroupID) + .property("CollidesWithTerrainWhileAttached", &Attachable::GetCollidesWithTerrainWhileAttached, &Attachable::SetCollidesWithTerrainWhileAttached), ABSTRACTLUABINDING(Emission, Entity) .property("ParticlesPerMinute", &Emission::GetRate, &Emission::SetRate) From c0ed2f438f96e85fbe56e8082ca6c96bb1119001 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 11 Aug 2020 01:56:36 -0300 Subject: [PATCH 003/144] Cleaned up Attachable handling so all attachables sit in one list, added template function and unordered_set to clean up hardcoded attachable handling while still avoiding duplicates Removed the m_DamageMultiplierRedefined flag and used -1 to define default instead Fixed various method comments and other minor stuff --- Entities/MOSRotating.cpp | 153 +++++++++++---------------------------- Entities/MOSRotating.h | 69 +++++++++++------- Managers/LuaMan.cpp | 2 +- 3 files changed, 88 insertions(+), 136 deletions(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 73e9643d1..839103d08 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -62,7 +62,6 @@ void MOSRotating::Clear() m_RecoilOffset.Reset(); m_Wounds.clear(); m_Attachables.clear(); - m_AllAttachables.clear(); m_Gibs.clear(); m_GibImpulseLimit = 0; m_GibWoundLimit = 0; @@ -73,8 +72,7 @@ void MOSRotating::Clear() m_pTempBitmap = 0; m_pTempBitmapS = 0; m_LoudnessOnGib = 1; - m_DamageMultiplier = 1; - m_DamageMultiplierRedefined = false; + m_DamageMultiplier = -1; m_StringValueMap.clear(); m_NumberValueMap.clear(); m_ObjectValueMap.clear(); @@ -91,6 +89,8 @@ int MOSRotating::Create() if (MOSprite::Create() < 0) return -1; + if (m_DamageMultiplier < 0.0F) { m_DamageMultiplier = 1; } + if (m_pAtomGroup && m_pAtomGroup->AutoGenerate()/* && m_pAtomGroup->GetAtomCount() == 0*/) m_pAtomGroup->Create(this); else if (m_pAtomGroup) @@ -197,7 +197,7 @@ int MOSRotating::Create(ContentFile spriteFile, const unsigned long lifetime) { MOSprite::Create(spriteFile, frameCount, mass, position, velocity, lifetime); - + if (m_DamageMultiplier < 0.0F) { m_DamageMultiplier = 1; } return 0; } @@ -238,28 +238,20 @@ int MOSRotating::Create(const MOSRotating &reference) m_RecoilOffset = reference.m_RecoilOffset; // Wound emitter copies - AEmitter *pWound = 0; - for (list::const_iterator itr = reference.m_Wounds.begin(); itr != reference.m_Wounds.end(); ++itr) - { - pWound = dynamic_cast((*itr)->Clone()); - AddWound(pWound, pWound->GetParentOffset()); - pWound = 0; + for (AEmitter *wound : reference.m_Wounds) { + AddWound(dynamic_cast(wound), wound->GetParentOffset()); } // Attachable copies - m_AllAttachables.clear(); - Attachable *pAttachable = 0; - for (list::const_iterator aItr = reference.m_Attachables.begin(); aItr != reference.m_Attachables.end(); ++aItr) - { - pAttachable = dynamic_cast((*aItr)->Clone()); - AddAttachable(pAttachable, pAttachable->GetParentOffset()); - pAttachable = 0; + for (const Attachable *attachable : reference.m_Attachables) { + if (m_AlreadyCopiedAttachableUniqueIDs.find(attachable->GetUniqueID()) != m_AlreadyCopiedAttachableUniqueIDs.end()) { + AddAttachable(dynamic_cast(attachable->Clone())); + } } // Gib copies - for (list::const_iterator gItr = reference.m_Gibs.begin(); gItr != reference.m_Gibs.end(); ++gItr) - { - m_Gibs.push_back(*gItr); + for (const Gib &gib : reference.m_Gibs) { + m_Gibs.push_back(gib); } m_StringValueMap = reference.m_StringValueMap; @@ -273,7 +265,6 @@ int MOSRotating::Create(const MOSRotating &reference) m_LoudnessOnGib = reference.m_LoudnessOnGib; m_DamageMultiplier = reference.m_DamageMultiplier; - m_DamageMultiplierRedefined = reference.m_DamageMultiplierRedefined; /* Allocated in lazy fashion as needed when drawing flipped if (!m_pFlipBitmap && m_aSprite[0]) @@ -346,7 +337,6 @@ int MOSRotating::ReadProperty(std::string propName, Reader &reader) reader >> m_LoudnessOnGib; else if (propName == "DamageMultiplier") { reader >> m_DamageMultiplier; - m_DamageMultiplierRedefined = true; } else if (propName == "AddCustomValue") { ReadCustomValueProperty(reader); } else @@ -1050,7 +1040,6 @@ void MOSRotating::GibThis(Vector impactImpulse, float internalBlast, MovableObje } // Clear the attachables list, all the attachables ownership have been handed to the movableman m_Attachables.clear(); - m_AllAttachables.clear(); // Play the gib sound m_GibSound.Play(m_Pos); @@ -1618,122 +1607,68 @@ void MOSRotating::UpdateChildMOIDs(vector &MOIDIndex, MOSprite::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Attaches the passed in Attachable and adds it to the list of attachables, not changing its parent offset and not treating it as hardcoded. -/// -/// The Attachable to attach. -void MOSRotating::AddAttachable(Attachable *pAttachable) -{ - if (pAttachable) - { - AddAttachable(pAttachable, pAttachable->GetParentOffset()); +void MOSRotating::AddAttachable(Attachable *attachable) { + if (attachable) { + AddAttachable(attachable, attachable->GetParentOffset()); } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Attaches the passed in Attachable and adds it to the list of attachables, changing its parent offset to the passed in Vector but not treating it as hardcoded. -/// -/// The Attachable to add. -/// The vector to set as the Attachable's parent offset. -void MOSRotating::AddAttachable(Attachable *pAttachable, const Vector& parentOffsetToSet) -{ - AddAttachable(pAttachable, parentOffsetToSet, false); -} - - -/// -/// Attaches the passed in Attachable and adds it to the list of attachables, not changing its parent offset but treating it as hardcoded depending on the passed in boolean. -/// -/// The Attachable to add. -/// Whether or not the Attachable should be treated as hardcoded. -void MOSRotating::AddAttachable(Attachable *pAttachable, bool isHardcodedAttachable) -{ - if (pAttachable) - { - AddAttachable(pAttachable, pAttachable->GetParentOffset(), isHardcodedAttachable); - } -} - - -/// -/// Attaches the passed in Attachable and adds it to the list of attachables, changing its parent offset to the passed in Vector and treating it as hardcoded depending on the passed in boolean. -/// -/// The Attachable to add. -/// The vector to set as the Attachable's parent offset. -/// Whether or not the Attachable should be treated as hardcoded. -void MOSRotating::AddAttachable(Attachable *pAttachable, const Vector & parentOffsetToSet, bool isHardcodedAttachable) { - if (pAttachable) { - pAttachable->SetParentOffset(parentOffsetToSet); - pAttachable->SetParent(this); +void MOSRotating::AddAttachable(Attachable *attachable, const Vector& parentOffsetToSet) { + if (attachable) { + attachable->SetParentOffset(parentOffsetToSet); + attachable->SetParent(this); // Set the attachable's subgroup ID to it's Unique ID to avoid any possible conflicts when adding atoms to parent group. - pAttachable->SetAtomSubgroupID(pAttachable->GetUniqueID()); - - if (!isHardcodedAttachable) { - m_Attachables.push_back(pAttachable); - } - m_AllAttachables.push_back(pAttachable); + attachable->SetAtomSubgroupID(attachable->GetUniqueID()); + m_Attachables.push_back(attachable); } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Detaches the Attachable corresponding to the passed in UniqueId, and removes it from the appropriate attachable lists -/// -/// The UniqueId of the the attachable to remove -/// False if the attachable is invalid, otherwise true -bool MOSRotating::RemoveAttachable(long attachableUniqueId) -{ - MovableObject *attachableAsMovableObject = g_MovableMan.FindObjectByUniqueID(attachableUniqueId); - if (attachableAsMovableObject) - { +bool MOSRotating::RemoveAttachable(long attachableUniqueID) { + MovableObject *attachableAsMovableObject = g_MovableMan.FindObjectByUniqueID(attachableUniqueID); + if (attachableAsMovableObject) { return RemoveAttachable((Attachable *)attachableAsMovableObject); } return false; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Detaches the passed in Attachable and removes it from the appropriate attachable lists -/// -/// The attachable to remove -/// False if the attachable is invalid, otherwise true -bool MOSRotating::RemoveAttachable(Attachable *pAttachable) { - if (pAttachable) { +bool MOSRotating::RemoveAttachable(Attachable *attachable) { + if (attachable) { if (m_Attachables.size() > 0) { - m_Attachables.remove(pAttachable); + m_Attachables.remove(attachable); } - if (m_AllAttachables.size() > 0) { - m_AllAttachables.remove(pAttachable); - } - if (pAttachable->ToDeleteWithParent()) { - pAttachable->SetToDelete(); + if (attachable->ToDeleteWithParent()) { + attachable->SetToDelete(); } else { - pAttachable->SetParent(nullptr); + attachable->SetParent(nullptr); } return true; } return false; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Either detaches or deletes all of this MOSRotating's attachables -/// -/// Whether to detach or delete the attachables. Setting this to true deletes them, setting it to false detaches them void MOSRotating::DetachOrDestroyAll(bool destroy) { - for (list::const_iterator aItr = m_AllAttachables.begin(); aItr != m_AllAttachables.end(); ++aItr) { - if (destroy) - delete (*aItr); - else - (*aItr)->SetParent(nullptr); - } - - m_AllAttachables.clear(); + for (Attachable *attachable : m_Attachables) { + if (destroy) { + delete attachable; + } else { + attachable->SetParent(nullptr); + } + } + m_Attachables.clear(); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetMOIDs diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 0c154caf7..c6973edaf 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -425,19 +425,38 @@ ClassInfoGetters virtual void ApplyImpulses(); + /// + /// Adds the passed in Attachable the list of attachables and sets its parent to this MOSRotating. + /// + /// The Attachable to add. + void AddAttachable(Attachable *attachable); - void AddAttachable(Attachable *pAttachable); - - void AddAttachable(Attachable *pAttachable, const Vector& parentOffsetToSet); - - void AddAttachable(Attachable *pAttachable, bool isHardcodedAttachable); - - void AddAttachable(Attachable *pAttachable, const Vector& parentOffsetToSet, bool isHardcodedAttachable); + /// + /// Attaches the passed in Attachable and adds it to the list of attachables, changing its parent offset to the passed in Vector but not treating it as hardcoded. + /// Adds the passed in Attachable the list of attachables, changes its parent offset to the passed in Vector, and sets its parent to this MOSRotating. + /// + /// The Attachable to add. + /// The Vector to set as the Attachable's parent offset. + void AddAttachable(Attachable *attachable, const Vector& parentOffsetToSet); - bool RemoveAttachable(long attachableUniqueId); + /// + /// Detaches the Attachable corresponding to the passed in UniqueID, and removes it from the appropriate attachable lists. + /// + /// The UniqueID of the the attachable to remove. + /// False if the attachable is invalid, otherwise true. + bool RemoveAttachable(long attachableUniqueID); - bool RemoveAttachable(Attachable *pAttachable); + /// + /// Detaches the passed in Attachable and removes it from the appropriate attachable lists. + /// + /// The attachable to remove. + /// False if the attachable is invalid, otherwise true. + bool RemoveAttachable(Attachable *attachable); + /// + /// Either detaches or deletes all of this MOSRotating's attachables. + /// + /// Whether to detach or delete the attachables. Setting this to true deletes them, setting it to false detaches them. void DetachOrDestroyAll(bool destroy); @@ -772,16 +791,6 @@ ClassInfoGetters virtual float GetDamageMultiplier() const { return m_DamageMultiplier; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: IsDamageMultiplierRedefined -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether the damage multiplier was altered in the .INI definition. -// If not, CC will apply default values during actor construction. -// Arguments: None. -// Return value: Current multiplier value. - - virtual bool IsDamageMultiplierRedefined() const { return m_DamageMultiplierRedefined; } - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetTravelImpulse @@ -808,6 +817,17 @@ ClassInfoGetters protected: + /// + /// To be called during Create(reference): + /// Clones a hardcoded attachable, setting the appropriate member variable, and calling AddAttachable. + /// Also adds the reference attachable's UniqueID to the std::unordered_set of already copied attachable unique IDs so it doesn't get duplicated. + /// + /// The relevant hardcoded attachable belonging to the reference object being cloned. + /// A std::function containing the setter for the given hardcoded attachable. Aside from setting the relevant member variable, this setter should call AddAttachable. + template void CloneHardcodedAttachable(Attachable *referenceAttachable, T hardcodedAttachableSetter) { + m_AlreadyCopiedAttachableUniqueIDs.insert(referenceAttachable->GetUniqueID()); + hardcodedAttachableSetter(*this, dynamic_cast(referenceAttachable->Clone())); + } ////////////////////////////////////////////////////////////////////////////////////////// // Method: ApplyAttachableForces @@ -869,12 +889,11 @@ ClassInfoGetters Vector m_RecoilForce; // The vector that the recoil offsets the sprite when m_Recoiled is true. Vector m_RecoilOffset; - // The list of wound AEmitters currently attached to this MOSRotating, and owned here as well + // The list of wound AEmitters currently attached to this MOSRotating, and owned here as well. std::list m_Wounds; - // The list of general Attachables currently attached and Owned by this. + // The list of Attachables currently attached and Owned by this. std::list m_Attachables; - // The list of all Attachables, including both hardcoded attachables and those added through ini or lua - std::list m_AllAttachables; + std::unordered_set m_AlreadyCopiedAttachableUniqueIDs; // m_Gibs; // The amount of impulse force required to gib this, in kg * (m/s). 0 means no limit @@ -894,10 +913,8 @@ ClassInfoGetters // Map to store any object pointers std::map m_ObjectValueMap; - // Damage mutliplier for this attachable + // Damage multiplier for this attachable float m_DamageMultiplier; - // Whether damage multiplier for this attachable was redefined in .ini - bool m_DamageMultiplierRedefined; // Intermediary drawing bitmap used to flip rotating bitmaps. Owned! BITMAP *m_pFlipBitmap; diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index d60573c71..ac1e88eab 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -775,7 +775,7 @@ int LuaMan::Create() .def("AddEmitter", (void (MOSRotating::*)(Attachable *attachableToAdd, const Vector &parentOffset))&MOSRotating::AddAttachable, adopt(_2)) .def("RemoveEmitter", (bool (MOSRotating::*)(Attachable *attachableToRemove))&MOSRotating::RemoveAttachable) .def("RemoveEmitter", (bool (MOSRotating::*)(long uniqueIDOfAttachableToRemove))&MOSRotating::RemoveAttachable) - .def_readonly("Attachables", &MOSRotating::m_AllAttachables, return_stl_iterator) + .def_readonly("Attachables", &MOSRotating::m_Attachables, return_stl_iterator) .def_readonly("Wounds", &MOSRotating::m_Wounds, return_stl_iterator), CONCRETELUABINDING(Attachable, MOSRotating) From 2d9d0e1c63643b9d752b4be3142f81dd4083e468 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 11 Aug 2020 02:14:30 -0300 Subject: [PATCH 004/144] Added setters for hardcoded attachables to ACrab and used them during clone create. Made hardcoded attachables get set to transfer damage in INI, this property can be unset with lua. Cleaned up and slightly renamed getters for ACrab hardcoded attachables. Made lua bindings for them read/write (property name hasn't changed to match renamed getters) Generally cleaned up ACrab clone Create and ReadProperty --- Entities/ACrab.cpp | 205 ++++++++++++++++++++++++-------------------- Entities/ACrab.h | 112 ++++++++++++++---------- Managers/LuaMan.cpp | 12 +-- 3 files changed, 185 insertions(+), 144 deletions(-) diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 6ee06b78d..afbabc4fb 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -161,50 +161,19 @@ int ACrab::Create(BITMAP *pSprite, ////////////////////////////////////////////////////////////////////////////////////////// // Description: Creates a ACrab to be identical to another, by deep copy. -int ACrab::Create(const ACrab &reference) -{ - Actor::Create(reference); - - if (reference.m_pTurret) - { - m_pTurret = dynamic_cast(reference.m_pTurret->Clone()); - m_pTurret->SetCanCollideWithTerrainWhenAttached(true); - AddAttachable(m_pTurret, true); - } +int ACrab::Create(const ACrab &reference) { + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pTurret, ACrab::SetTurret); } + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pJetpack, ACrab::SetJetpack); } + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pLFGLeg, ACrab::SetLeftFGLeg); } + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pRFGLeg, ACrab::SetRightFGLeg); } + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pLBGLeg, ACrab::SetLeftBGLeg); } + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pRBGLeg, ACrab::SetRightBGLeg); } - if (reference.m_pJetpack) - { - m_pJetpack = dynamic_cast(reference.m_pJetpack->Clone()); - AddAttachable(m_pJetpack, true); - } + Actor::Create(reference); m_JetTimeTotal = reference.m_JetTimeTotal; m_JetTimeLeft = reference.m_JetTimeLeft; - if (reference.m_pLFGLeg) - { - m_pLFGLeg = dynamic_cast(reference.m_pLFGLeg->Clone()); - AddAttachable(m_pLFGLeg, true); - } - - if (reference.m_pLBGLeg) - { - m_pLBGLeg = dynamic_cast(reference.m_pLBGLeg->Clone()); - AddAttachable(m_pLBGLeg, true); - } - - if (reference.m_pRFGLeg) - { - m_pRFGLeg = dynamic_cast(reference.m_pRFGLeg->Clone()); - AddAttachable(m_pRFGLeg, true); - } - - if (reference.m_pRBGLeg) - { - m_pRBGLeg = dynamic_cast(reference.m_pRBGLeg->Clone()); - AddAttachable(m_pRBGLeg, true); - } - m_pLFGFootGroup = dynamic_cast(reference.m_pLFGFootGroup->Clone()); m_pLFGFootGroup->SetOwner(this); m_pLBGFootGroup = dynamic_cast(reference.m_pLBGFootGroup->Clone()); @@ -218,10 +187,8 @@ int ACrab::Create(const ACrab &reference) m_MoveState = reference.m_MoveState; - for (int side = 0; side < SIDECOUNT; ++side) - { - for (int i = 0; i < MOVEMENTSTATECOUNT; ++i) - { + for (int side = 0; side < SIDECOUNT; ++side) { + for (int i = 0; i < MOVEMENTSTATECOUNT; ++i) { m_Paths[side][FGROUND][i].Create(reference.m_Paths[side][FGROUND][i]); m_Paths[side][BGROUND][i].Create(reference.m_Paths[side][BGROUND][i]); } @@ -255,52 +222,43 @@ int ACrab::Create(const ACrab &reference) int ACrab::ReadProperty(std::string propName, Reader &reader) { - if (propName == "Turret") - { + if (propName == "Turret") { delete m_pTurret; m_pTurret = new Turret; reader >> m_pTurret; - if (!m_pTurret->IsDamageMultiplierRedefined()) - m_pTurret->SetDamageMultiplier(5); - } - else if (propName == "Jetpack") - { + m_pTurret->SetTransfersDamageToParent(true); + if (m_pTurret->GetDamageMultiplier() < 0.0F) { + m_pTurret->SetDamageMultiplier(5); + } + } else if (propName == "Jetpack") { delete m_pJetpack; m_pJetpack = new AEmitter; reader >> m_pJetpack; - } - else if (propName == "JumpTime") - { + m_pJetpack->SetTransfersDamageToParent(true); + } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; - // Convert to ms m_JetTimeTotal *= 1000; - } - else if (propName == "LFGLeg") - { + } else if (propName == "LFGLeg") { delete m_pLFGLeg; m_pLFGLeg = new Leg; reader >> m_pLFGLeg; - } - else if (propName == "LBGLeg") - { + m_pLFGLeg->SetTransfersDamageToParent(true); + } else if (propName == "LBGLeg") { delete m_pLBGLeg; m_pLBGLeg = new Leg; reader >> m_pLBGLeg; - } - else if (propName == "RFGLeg") - { + m_pLBGLeg->SetTransfersDamageToParent(true); + } else if (propName == "RFGLeg") { delete m_pRFGLeg; m_pRFGLeg = new Leg; reader >> m_pRFGLeg; - } - else if (propName == "RBGLeg") - { + m_pRFGLeg->SetTransfersDamageToParent(true); + } else if (propName == "RBGLeg") { delete m_pRBGLeg; m_pRBGLeg = new Leg; reader >> m_pRBGLeg; - } - else if (propName == "LFootGroup") - { + m_pRBGLeg->SetTransfersDamageToParent(true); + } else if (propName == "LFootGroup") { delete m_pLFGFootGroup; delete m_pLBGFootGroup; m_pLFGFootGroup = new AtomGroup(); @@ -309,9 +267,7 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) m_pLBGFootGroup->Create(*m_pLFGFootGroup); m_pLFGFootGroup->SetOwner(this); m_pLBGFootGroup->SetOwner(this); - } - else if (propName == "RFootGroup") - { + } else if (propName == "RFootGroup") { delete m_pRFGFootGroup; delete m_pRBGFootGroup; m_pRFGFootGroup = new AtomGroup(); @@ -320,27 +276,27 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) m_pRBGFootGroup->Create(*m_pRFGFootGroup); m_pRFGFootGroup->SetOwner(this); m_pRBGFootGroup->SetOwner(this); - } - else if (propName == "StrideSound") + } else if (propName == "StrideSound") { reader >> m_StrideSound; - else if (propName == "LStandLimbPath") + } else if (propName == "LStandLimbPath") { reader >> m_Paths[LEFTSIDE][FGROUND][STAND]; - else if (propName == "LWalkLimbPath") + } else if (propName == "LWalkLimbPath") { reader >> m_Paths[LEFTSIDE][FGROUND][WALK]; - else if (propName == "LDislodgeLimbPath") + } else if (propName == "LDislodgeLimbPath") { reader >> m_Paths[LEFTSIDE][FGROUND][DISLODGE]; - else if (propName == "RStandLimbPath") + } else if (propName == "RStandLimbPath") { reader >> m_Paths[RIGHTSIDE][FGROUND][STAND]; - else if (propName == "RWalkLimbPath") + } else if (propName == "RWalkLimbPath") { reader >> m_Paths[RIGHTSIDE][FGROUND][WALK]; - else if (propName == "RDislodgeLimbPath") + } else if (propName == "RDislodgeLimbPath") { reader >> m_Paths[RIGHTSIDE][FGROUND][DISLODGE]; - else if (propName == "AimRangeUpperLimit") + } else if (propName == "AimRangeUpperLimit") { reader >> m_AimRangeUpperLimit; - else if (propName == "AimRangeLowerLimit") + } else if (propName == "AimRangeLowerLimit") { reader >> m_AimRangeLowerLimit; - else + } else { return Actor::ReadProperty(propName, reader); + } return 0; } @@ -537,6 +493,63 @@ Vector ACrab::GetEyePos() const return m_Pos; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ACrab::SetLeftFGLeg(Attachable *newLeg) { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pLFGLeg); + m_pLFGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ACrab::SetLeftBGLeg(Attachable *newLeg) { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pLBGLeg); + m_pLBGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void ACrab::SetRightFGLeg(Attachable *newLeg) { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pRFGLeg); + m_pRFGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void ACrab::SetRightBGLeg(Attachable *newLeg) { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pRBGLeg); + m_pRBGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void ACrab::SetJetpack(Attachable *newJetpack) { + AEmitter *castedNewJetpack = dynamic_cast(newJetpack); + if (castedNewJetpack) { + RemoveAttachable(m_pJetpack); + m_pJetpack = castedNewJetpack; + AddAttachable(castedNewJetpack); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: SetID @@ -709,22 +722,28 @@ bool ACrab::HandlePieCommand(int pieSliceIndex) return false; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual Method: GetTurret -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns any attached turret. - -Attachable * ACrab::GetTurret() const -{ - if (m_pTurret && m_pTurret->IsAttached()) - { +Attachable * ACrab::GetTurret() const { + if (m_pTurret && m_pTurret->IsAttached()) { return dynamic_cast(m_pTurret); } - return 0; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ACrab::SetTurret(Attachable *newTurret) { + Turret *castedNewTurret = dynamic_cast(newTurret); + if (castedNewTurret) { + RemoveAttachable(m_pTurret); + m_pTurret = castedNewTurret; + AddAttachable(castedNewTurret); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// // Virtual Method: GetEquippedItem diff --git a/Entities/ACrab.h b/Entities/ACrab.h index 4966f2a58..6cd7a3789 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -198,44 +198,53 @@ ClassInfoGetters virtual Vector GetEyePos() const; -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetLFGLeg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the left FG Leg as an Attachable. This is for Lua binding mostly. -// Arguments: None. -// Return value: A pointer to the Leg Attachable. Ownership is NOT transferred! - - Attachable * GetLFGLeg() const { return (Attachable *)m_pLFGLeg; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetLBGLeg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the left BG Leg as an Attachable. This is for Lua binding mostly. -// Arguments: None. -// Return value: A pointer to the Leg Attachable. Ownership is NOT transferred! - - Attachable * GetLBGLeg() const { return (Attachable *)m_pLBGLeg; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetRFGLeg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the right FG Leg as an Attachable. This is for Lua binding mostly. -// Arguments: None. -// Return value: A pointer to the Leg Attachable. Ownership is NOT transferred! - - Attachable * GetRFGLeg() const { return (Attachable *)m_pRFGLeg; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetLFGLeg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the right BG Leg as an Attachable. This is for Lua binding mostly. -// Arguments: None. -// Return value: A pointer to the Leg Attachable. Ownership is NOT transferred! - - Attachable * GetRBGLeg() const { return (Attachable *)m_pRBGLeg; } + /// + /// Gets the left FG Leg as an Attachable. + /// + /// A pointer to the Leg Attachable. Ownership is NOT transferred! + Attachable * GetLeftFGLeg() const { return dynamic_cast(m_pLFGLeg); } + + /// + /// Sets the left foreground leg for this Crab. Ownership IS transferred! + /// + /// The new leg to use. + void SetLeftFGLeg(Attachable *newLeg); + + /// + /// Gets the left BG Leg as an Attachable. + /// + /// A pointer to the Leg Attachable. Ownership is NOT transferred! + Attachable * GetLeftBGLeg() const { return dynamic_cast(m_pLBGLeg); } + + /// + /// Sets the left background leg for this Crab. Ownership IS transferred! + /// + /// The new leg to use. + void SetLeftBGLeg(Attachable *newLeg); + + /// + /// Gets the right FG Leg as an Attachable. + /// + /// A pointer to the Leg Attachable. Ownership is NOT transferred! + Attachable * GetRightFGLeg() const { return dynamic_cast(m_pRFGLeg); } + + /// + /// Sets the right foreground leg for this Crab. Ownership IS transferred! + /// + /// The new leg to use. + void SetRightFGLeg(Attachable *newLeg); + + /// + /// Gets the right BG Leg as an Attachable. + /// + /// A pointer to the Leg Attachable. Ownership is NOT transferred! + Attachable *GetRightBGLeg() const { return dynamic_cast(m_pRBGLeg); } + + /// + /// Sets the right background leg for this Crab. Ownership IS transferred! + /// + /// The new leg to use. + void SetRightBGLeg(Attachable *newLeg); ////////////////////////////////////////////////////////////////////////////////////////// @@ -245,8 +254,18 @@ ClassInfoGetters // Arguments: None. // Return value: A pointer to jetpack emitter. Ownership is NOT transferred! + /// + /// Gets the jetpack emitter for this Crab. + /// + /// A pointer to the jetpack emitter. Ownership is NOT transferred! AEmitter * GetJetpack() const { return (AEmitter *)m_pJetpack; } + /// + /// Sets the jetpack for this Crab. Ownership IS Transferred! + /// + /// The new jetpack to use. + void SetJetpack(Attachable *newJetpack); + ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetJetTimeTotal @@ -349,14 +368,17 @@ ClassInfoGetters virtual bool HandlePieCommand(int pieSliceIndex); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual Method: GetEquippedItem -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns any equipped turret. -// Arguments: None. -// Return value: A pointer to an attachable. + /// + /// Gets the turret of this Crab. + /// + /// A pointer to the Crab's turret. Ownership is NOT transferred! + Attachable * GetTurret() const; - virtual Attachable * GetTurret() const; + /// + /// Sets the turret for this Crab. Ownership IS transferred! + /// + /// The new turret to use. + void SetTurret(Attachable *newTurret); ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index ac1e88eab..f94fdfc57 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1149,12 +1149,12 @@ int LuaMan::Create() value("LANDJUMP", 5) ] .def(constructor<>()) - .property("Turret", &ACrab::GetTurret) - .property("LFGLeg", &ACrab::GetLFGLeg) - .property("LBGLeg", &ACrab::GetLBGLeg) - .property("RFGLeg", &ACrab::GetRFGLeg) - .property("RBGLeg", &ACrab::GetRBGLeg) - .property("Jetpack", &ACrab::GetJetpack) + .property("Turret", &ACrab::GetTurret, &ACrab::SetTurret) + .property("LFGLeg", &ACrab::GetLeftFGLeg, &ACrab::SetLeftFGLeg) + .property("LBGLeg", &ACrab::GetLeftBGLeg, &ACrab::SetLeftBGLeg) + .property("RFGLeg", &ACrab::GetRightFGLeg, &ACrab::SetRightFGLeg) + .property("RBGLeg", &ACrab::GetRightBGLeg, &ACrab::SetRightBGLeg) + .property("Jetpack", &ACrab::GetJetpack, &ACrab::SetJetpack) .property("JetTimeTotal", &ACrab::GetJetTimeTotal, &ACrab::SetJetTimeTotal) .property("JetTimeLeft", &ACrab::GetJetTimeLeft) .property("EquippedItem", &ACrab::GetEquippedItem) From bebf0834612eb0896e0868f1cbc9903273117e13 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 11 Aug 2020 02:40:57 -0300 Subject: [PATCH 005/144] Added setters for hardcoded attachables to ACDropShip and used them during clone create. Made hardcoded attachables get set to transfer damage in INI, this property can be unset with lua. Cleaned up and slightly renamed getters for ACDropShip hardcoded attachables. Made lua bindings for them read/write (property name hasn't changed to match renamed getters) Generally cleaned up ACDropShip clone Create and ReadProperty Added TODOs to ACrab and ACDropShip to rename some member variables when they're cleaned up --- Entities/ACDropShip.cpp | 146 ++++++++++++++++++++++------------------ Entities/ACDropShip.h | 130 +++++++++++++++++++---------------- Entities/ACrab.h | 1 + 3 files changed, 154 insertions(+), 123 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 3b0ce2f88..b9c576f54 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -71,47 +71,18 @@ int ACDropShip::Create() ////////////////////////////////////////////////////////////////////////////////////////// // Description: Creates a ACDropShip to be identical to another, by deep copy. -int ACDropShip::Create(const ACDropShip &reference) -{ +int ACDropShip::Create(const ACDropShip &reference) { + if (reference.m_pRThruster) { CloneHardcodedAttachable(reference.m_pRThruster, ACDropShip::SetRightThruster); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLThruster, ACDropShip::SetLeftThruster); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pURThruster, ACDropShip::SetURightThruster); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pULThruster, ACDropShip::SetULeftThruster); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pRHatch, ACDropShip::SetRightHatch); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLHatch, ACDropShip::SetLeftHatch); } + ACraft::Create(reference); m_pBodyAG = dynamic_cast(reference.m_pBodyAG->Clone()); m_pBodyAG->SetOwner(this); - - if (reference.m_pRThruster) - { - m_pRThruster = dynamic_cast(reference.m_pRThruster->Clone()); - m_pRThruster->SetCanCollideWithTerrainWhenAttached(true); - AddAttachable(m_pRThruster, true); - } - if (reference.m_pLThruster) - { - m_pLThruster = dynamic_cast(reference.m_pLThruster->Clone()); - m_pLThruster->SetCanCollideWithTerrainWhenAttached(true); - AddAttachable(m_pLThruster, true); - } - if (reference.m_pURThruster) - { - m_pURThruster = dynamic_cast(reference.m_pURThruster->Clone()); - AddAttachable(m_pURThruster, true); - } - if (reference.m_pULThruster) - { - m_pULThruster = dynamic_cast(reference.m_pULThruster->Clone()); - AddAttachable(m_pULThruster, true); - } - if (reference.m_pRHatch) - { - m_pRHatch = dynamic_cast(reference.m_pRHatch->Clone()); - m_pRHatch->SetCanCollideWithTerrainWhenAttached(true); - AddAttachable(m_pRHatch, true); - } - if (reference.m_pLHatch) - { - m_pLHatch = dynamic_cast(reference.m_pLHatch->Clone()); - m_pLHatch->SetCanCollideWithTerrainWhenAttached(true); - AddAttachable(m_pLHatch, true); - } m_HatchSwingRange = reference.m_HatchSwingRange; m_HatchOpeness = reference.m_HatchOpeness; @@ -134,56 +105,50 @@ int ACDropShip::Create(const ACDropShip &reference) // is called. If the property isn't recognized by any of the base classes, // false is returned, and the reader's position is untouched. -int ACDropShip::ReadProperty(std::string propName, Reader &reader) -{ - if (propName == "RThruster") - { +int ACDropShip::ReadProperty(std::string propName, Reader &reader) { + if (propName == "RThruster") { delete m_pRThruster; m_pRThruster = new AEmitter; + m_pRThruster->SetTransfersDamageToParent(true); reader >> m_pRThruster; - } - else if (propName == "LThruster") - { + } else if (propName == "LThruster") { delete m_pLThruster; m_pLThruster = new AEmitter; reader >> m_pLThruster; - } - else if (propName == "URThruster") - { + m_pLThruster->SetTransfersDamageToParent(true); + } else if (propName == "URThruster") { delete m_pURThruster; m_pURThruster = new AEmitter; reader >> m_pURThruster; - } - else if (propName == "ULThruster") - { + m_pURThruster->SetTransfersDamageToParent(true); + } else if (propName == "ULThruster") { delete m_pULThruster; m_pULThruster = new AEmitter; reader >> m_pULThruster; - } - else if (propName == "RHatchDoor") - { + m_pULThruster->SetTransfersDamageToParent(true); + } else if (propName == "RHatchDoor") { delete m_pRHatch; m_pRHatch = new Attachable; reader >> m_pRHatch; - } - else if (propName == "LHatchDoor") - { + m_pRHatch->SetTransfersDamageToParent(true); + } else if (propName == "LHatchDoor") { delete m_pLHatch; m_pLHatch = new Attachable; reader >> m_pLHatch; - } - else if (propName == "HatchDoorSwingRange") + m_pLHatch->SetTransfersDamageToParent(true); + } else if (propName == "HatchDoorSwingRange") { reader >> m_HatchSwingRange; - else if (propName == "AutoStabilize") + } else if (propName == "AutoStabilize") { reader >> m_AutoStabilize; - else if (propName == "ScuttleIfFlippedTime") + } else if (propName == "ScuttleIfFlippedTime") { reader >> m_ScuttleIfFlippedTime; - else if (propName == "MaxEngineAngle") - reader >> m_MaxEngineAngle; - else if (propName == "LateralControlSpeed") - reader >> m_LateralControlSpeed; - else + } else if (propName == "MaxEngineAngle") { + reader >> m_MaxEngineAngle; + } else if (propName == "LateralControlSpeed") { + reader >> m_LateralControlSpeed; + } else { return ACraft::ReadProperty(propName, reader); + } return 0; } @@ -982,28 +947,55 @@ void ACDropShip::Update() */ } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Method: ResetEmissionTimers ////////////////////////////////////////////////////////////////////////////////////////// // Description: Reset the timers of all emissions so they will start/stop at the // correct relative offsets from now. +void ACDropShip::SetRightThruster(Attachable *newThruster) { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pRThruster); + m_pRThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } +} void ACDropShip::ResetEmissionTimers() { if (m_pRThruster && m_pRThruster->IsAttached()) m_pRThruster->ResetEmissionTimers(); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (m_pLThruster && m_pLThruster->IsAttached()) m_pLThruster->ResetEmissionTimers(); +void ACDropShip::SetLeftThruster(Attachable *newThruster) { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pLThruster); + m_pLThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } +} if (m_pURThruster && m_pURThruster->IsAttached()) m_pURThruster->ResetEmissionTimers(); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (m_pULThruster && m_pULThruster->IsAttached()) m_pULThruster->ResetEmissionTimers(); +void ACDropShip::SetURightThruster(Attachable *newThruster) { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pURThruster); + m_pURThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Method: RemoveAnyRandomWounds @@ -1013,6 +1005,14 @@ void ACDropShip::ResetEmissionTimers() int ACDropShip::RemoveAnyRandomWounds(int amount) { float damage = 0; +void ACDropShip::SetULeftThruster(Attachable *newThruster) { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pULThruster); + m_pULThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } +} for (int i = 0; i < amount; i++) { @@ -1038,10 +1038,18 @@ int ACDropShip::RemoveAnyRandomWounds(int amount) MOSRotating * part = bodyParts[partIndex]; damage += part->RemoveWounds(1); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// return damage; +void ACDropShip::SetLeftHatch(Attachable *newHatch) { + if (newHatch) { + RemoveAttachable(m_pLHatch); + m_pLHatch = newHatch; + AddAttachable(newHatch); + } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetTotalWoundCount @@ -1051,6 +1059,13 @@ int ACDropShip::RemoveAnyRandomWounds(int amount) int ACDropShip::GetTotalWoundCount() const { int count = ACraft::GetWoundCount(); +void ACDropShip::SetRightHatch(Attachable *newHatch) { + if (newHatch) { + RemoveAttachable(m_pLHatch); + m_pRHatch = newHatch; + AddAttachable(newHatch); + } +} if (m_pRHatch) count += m_pRHatch->GetWoundCount(); @@ -1060,6 +1075,7 @@ int ACDropShip::GetTotalWoundCount() const count += m_pRThruster->GetWoundCount(); if (m_pLThruster) count += m_pLThruster->GetWoundCount(); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// return count; } diff --git a/Entities/ACDropShip.h b/Entities/ACDropShip.h index 9b04e444e..1c5cacabb 100644 --- a/Entities/ACDropShip.h +++ b/Entities/ACDropShip.h @@ -266,64 +266,77 @@ ClassInfoGetters virtual int GetMaxPassengers() const { return m_MaxPassengers > -1 ? m_MaxPassengers : 4; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetRThruster -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the right side engine. -// Arguments: None. -// Return value: An AEmitter pointer. - - AEmitter * GetRThruster() const { return m_pRThruster; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetLThruster -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the left side engine. -// Arguments: None. -// Return value: An AEmitter pointer. - - AEmitter * GetLThruster() const { return m_pLThruster; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetURThruster -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the right side secondary thruster. -// Arguments: None. -// Return value: An AEmitter pointer. - - AEmitter * GetURThruster() const { return m_pURThruster; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetULThruster -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the left side secondary thruster. -// Arguments: None. -// Return value: An AEmitter pointer. - - AEmitter * GetULThruster() const { return m_pULThruster; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetLHatch -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the left side hatch. -// Arguments: None. -// Return value: An Attachable pointer. - - Attachable * GetLHatch() const { return m_pLHatch; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetRHatch -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the right side hatch. -// Arguments: None. -// Return value: An Attachable pointer. - - Attachable * GetRHatch() const { return m_pRHatch; } + /// + /// Gets the right side thruster of this ACDropship. + /// + /// A pointer to the right side thruster of this ACDropship. Ownership is NOT transferred. + AEmitter *GetRightThruster() const { return m_pRThruster; } + + /// + /// Sets the right side thruster for this ACDropship. + /// + /// The new thruster to use. + void SetRightThruster(Attachable *newThruster); + + /// + /// Gets the left side thruster of this ACDropship. + /// + /// A pointer to the left side thruster of this ACDropship. Ownership is NOT transferred. + AEmitter *GetLeftThruster() const { return m_pLThruster; } + + /// + /// Sets the left side thruster for this ACDropship. + /// + /// The new thruster to use. + void SetLeftThruster(Attachable *newThruster); + + /// + /// Gets the right side secondary thruster of this ACDropship. + /// + /// A pointer to the right side secondary thruster of this ACDropship. Ownership is NOT transferred. + AEmitter *GetURightThruster() const { return m_pURThruster; } + + /// + /// Sets the right side secondary thruster for this ACDropship. + /// + /// The new thruster to use. + void SetURightThruster(Attachable *newThruster); + + /// + /// Gets the left side secondary thruster of this ACDropship. + /// + /// A pointer to the left side secondary thruster of this ACDropship. Ownership is NOT transferred. + AEmitter *GetULeftThruster() const { return m_pULThruster; } + + /// + /// Sets the left side secondary thruster for this ACDropship. + /// + /// The new thruster to use. + void SetULeftThruster(Attachable *newThruster); + + /// + /// Gets the left side hatch of this ACDropship. + /// + /// A pointer to the left side hatch of this ACDropship. Ownership is NOT transferred. + Attachable *GetLeftHatch() const { return m_pLHatch; } + + /// + /// Sets the left side hatch for this ACDropship. + /// + /// The new hatch to use. + void SetLeftHatch(Attachable *newHatch); + + /// + /// Gets the right side hatch of this ACDropship. + /// + /// A pointer to the right side hatch of this ACDropship. Ownership is NOT transferred. + Attachable *GetRightHatch() const { return m_pRHatch; } + + /// + /// Sets the right side hatch for this ACDropship. + /// + /// The new hatch to use. + void SetRightHatch(Attachable *newHatch); ////////////////////////////////////////////////////////////////////////////////////////// @@ -453,6 +466,7 @@ ClassInfoGetters // Body AtomGroups. AtomGroup *m_pBodyAG; // Thruster emitters. + //TODO when this class is cleaned up, these and their getters and setters should probably be renamed (I'd argue the lua bindings should be broken to match but that's debatable). L and R should be Left and Right and they should probably be Primary and Secondary. AEmitter *m_pRThruster; AEmitter *m_pLThruster; AEmitter *m_pURThruster; diff --git a/Entities/ACrab.h b/Entities/ACrab.h index 6cd7a3789..635d0a81d 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -686,6 +686,7 @@ ClassInfoGetters // Turret which can be mounted with a weapon Turret *m_pTurret; + //TODO when this class is cleaned up these legs and footgroups should probably be renamed. L and R should be expanded to Left and Right. I think FG and BG can stay as is cause they're everywhere. // Left Foreground leg. Leg *m_pLFGLeg; // Left Background leg. From ee1d23547837463f7054e128635754d79201cd75 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 11 Aug 2020 02:46:17 -0300 Subject: [PATCH 006/144] Reworked up wound checking and removal. Now it's all handled by MOSR and it can recursively deal with wounds from damage transferring or non damage transferring attachables. This applies to getting wounds, getting wound limits and removing wounds. Cleaned up MOSRotating::AddWound and completely got rid of RemoveAnyRandomWounds, GetTotalWoundCount and GetTotalWoundLimit since they're all handled better by these changes (note, ACDropship.cpp looks a little weird in git diff here for some reason) Modified lua bindings to match the new wound stuff --- Entities/ACDropShip.cpp | 94 +++++--------------------------- Entities/ACDropShip.h | 29 ---------- Entities/ACRocket.cpp | 76 -------------------------- Entities/ACRocket.h | 29 ---------- Entities/ACrab.cpp | 91 ------------------------------- Entities/ACrab.h | 29 ---------- Entities/ADoor.cpp | 20 ------- Entities/ADoor.h | 7 --- Entities/AHuman.cpp | 92 -------------------------------- Entities/AHuman.h | 28 ---------- Entities/Actor.cpp | 29 ---------- Entities/Actor.h | 28 ---------- Entities/MOSRotating.cpp | 112 ++++++++++++++++++++++++++++++--------- Entities/MOSRotating.h | 55 ++++++++++++------- Managers/LuaMan.cpp | 10 ++-- 15 files changed, 144 insertions(+), 585 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index b9c576f54..3b9d16364 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -949,11 +949,6 @@ void ACDropShip::Update() ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Method: ResetEmissionTimers -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Reset the timers of all emissions so they will start/stop at the -// correct relative offsets from now. void ACDropShip::SetRightThruster(Attachable *newThruster) { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { @@ -963,14 +958,8 @@ void ACDropShip::SetRightThruster(Attachable *newThruster) { } } -void ACDropShip::ResetEmissionTimers() -{ - if (m_pRThruster && m_pRThruster->IsAttached()) - m_pRThruster->ResetEmissionTimers(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (m_pLThruster && m_pLThruster->IsAttached()) - m_pLThruster->ResetEmissionTimers(); void ACDropShip::SetLeftThruster(Attachable *newThruster) { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { @@ -980,12 +969,8 @@ void ACDropShip::SetLeftThruster(Attachable *newThruster) { } } - if (m_pURThruster && m_pURThruster->IsAttached()) - m_pURThruster->ResetEmissionTimers(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (m_pULThruster && m_pULThruster->IsAttached()) - m_pULThruster->ResetEmissionTimers(); void ACDropShip::SetURightThruster(Attachable *newThruster) { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { @@ -997,14 +982,6 @@ void ACDropShip::SetURightThruster(Attachable *newThruster) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Method: RemoveAnyRandomWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds from the actor and all standard attachables. - -int ACDropShip::RemoveAnyRandomWounds(int amount) -{ - float damage = 0; void ACDropShip::SetULeftThruster(Attachable *newThruster) { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { @@ -1014,33 +991,8 @@ void ACDropShip::SetULeftThruster(Attachable *newThruster) { } } - for (int i = 0; i < amount; i++) - { - // Fill the list of damaged bodyparts - std::vector bodyParts; - if (GetWoundCount() > 0) - bodyParts.push_back(this); - - if (m_pRHatch && m_pRHatch->GetWoundCount()) - bodyParts.push_back(m_pRHatch); - if (m_pLHatch && m_pLHatch->GetWoundCount()) - bodyParts.push_back(m_pLHatch); - if (m_pRThruster && m_pRThruster->GetWoundCount()) - bodyParts.push_back(m_pRThruster); - if (m_pLThruster && m_pLThruster->GetWoundCount()) - bodyParts.push_back(m_pLThruster); - - // Stop removing wounds if there are not any left - if (bodyParts.size() == 0) - break; - - int partIndex = RangeRand(0, bodyParts.size() - 1); - MOSRotating * part = bodyParts[partIndex]; - damage += part->RemoveWounds(1); - } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - return damage; void ACDropShip::SetLeftHatch(Attachable *newHatch) { if (newHatch) { RemoveAttachable(m_pLHatch); @@ -1051,14 +1003,6 @@ void ACDropShip::SetLeftHatch(Attachable *newHatch) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound count of this actor and all vital attachables. - -int ACDropShip::GetTotalWoundCount() const -{ - int count = ACraft::GetWoundCount(); void ACDropShip::SetRightHatch(Attachable *newHatch) { if (newHatch) { RemoveAttachable(m_pLHatch); @@ -1067,38 +1011,28 @@ void ACDropShip::SetRightHatch(Attachable *newHatch) { } } - if (m_pRHatch) - count += m_pRHatch->GetWoundCount(); - if (m_pLHatch) - count += m_pLHatch->GetWoundCount(); - if (m_pRThruster) - count += m_pRThruster->GetWoundCount(); - if (m_pLThruster) - count += m_pLThruster->GetWoundCount(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - return count; -} ////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundLimit +// Method: ResetEmissionTimers ////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound limit of this actor and all vital attachables. +// Description: Reset the timers of all emissions so they will start/stop at the +// correct relative offsets from now. + +void ACDropShip::ResetEmissionTimers() +{ + if (m_pRThruster && m_pRThruster->IsAttached()) + m_pRThruster->ResetEmissionTimers(); -int ACDropShip::GetTotalWoundLimit() const -{ - int count = ACraft::GetGibWoundLimit(); + if (m_pLThruster && m_pLThruster->IsAttached()) + m_pLThruster->ResetEmissionTimers(); - if (m_pRHatch) - count += m_pRHatch->GetGibWoundLimit(); - if (m_pLHatch) - count += m_pLHatch->GetGibWoundLimit(); - if (m_pRThruster) - count += m_pRThruster->GetGibWoundLimit(); - if (m_pLThruster) - count += m_pLThruster->GetGibWoundLimit(); + if (m_pURThruster && m_pURThruster->IsAttached()) + m_pURThruster->ResetEmissionTimers(); - return count; + if (m_pULThruster && m_pULThruster->IsAttached()) + m_pULThruster->ResetEmissionTimers(); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACDropShip.h b/Entities/ACDropShip.h index 1c5cacabb..9a198de64 100644 --- a/Entities/ACDropShip.h +++ b/Entities/ACDropShip.h @@ -350,35 +350,6 @@ ClassInfoGetters virtual void ResetEmissionTimers(); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound count of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total number of wounds of this actor. - - virtual int GetTotalWoundCount() const; - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound limit of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total wound limit of this actor. - - virtual int GetTotalWoundLimit() const; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: RemoveAnyRandomWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds from the actor and all standard attachables. -// Arguments: Amount of wounds to remove. -// Return value: Damage taken from removed wounds. - - virtual int RemoveAnyRandomWounds(int amount); - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetMOIDs ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 32449aebe..04198e134 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -1110,82 +1110,6 @@ void ACRocket::ResetEmissionTimers() } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: RemoveAnyRandomWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds from the actor and all standard attachables. - -int ACRocket::RemoveAnyRandomWounds(int amount) -{ - float damage = 0; - - for (int i = 0; i < amount; i++) - { - // Fill the list of damaged bodyparts - std::vector bodyParts; - if (GetWoundCount() > 0) - bodyParts.push_back(this); - - if (m_pRLeg && m_pRLeg->GetWoundCount()) - bodyParts.push_back(m_pRLeg); - if (m_pLLeg && m_pLLeg->GetWoundCount()) - bodyParts.push_back(m_pLLeg); - - // Stop removing wounds if there are not any left - if (bodyParts.size() == 0) - break; - - int partIndex = RangeRand(0, bodyParts.size() - 1); - MOSRotating * part = bodyParts[partIndex]; - damage += part->RemoveWounds(1); - } - - return damage; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound count of this actor and all vital attachables. - -int ACRocket::GetTotalWoundCount() const -{ - int count = ACraft::GetWoundCount(); - -// if (m_pMThruster) -// count += m_pMThruster->GetWoundCount(); - if (m_pRLeg) - count += m_pRLeg->GetWoundCount(); - if (m_pLLeg) - count += m_pLLeg->GetWoundCount(); -// if (m_pCapsule) -// count += m_pCapsule->GetWoundCount(); - - return count; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound limit of this actor and all vital attachables. - -int ACRocket::GetTotalWoundLimit() const -{ - int count = ACraft::GetGibWoundLimit(); - -// if (m_pMThruster) -// count += m_pMThruster->GetGibWoundLimit(); - if (m_pRLeg) - count += m_pRLeg->GetGibWoundLimit(); - if (m_pLLeg) - count += m_pLLeg->GetGibWoundLimit(); -// if (m_pCapsule) -// count += m_pCapsule->GetGibWoundLimit(); - - return count; -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACRocket.h b/Entities/ACRocket.h index ce5fe033f..403fd0258 100644 --- a/Entities/ACRocket.h +++ b/Entities/ACRocket.h @@ -230,26 +230,6 @@ ClassInfoGetters virtual void ResetEmissionTimers(); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound count of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total number of wounds of this actor. - - virtual int GetTotalWoundCount() const; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound limit of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total wound limit of this actor. - - virtual int GetTotalWoundLimit() const; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw ////////////////////////////////////////////////////////////////////////////////////////// @@ -279,15 +259,6 @@ ClassInfoGetters virtual int GetMaxPassengers() const { return m_MaxPassengers > -1 ? m_MaxPassengers : 2; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: RemoveAnyRandomWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds from the actor and all standard attachables. -// Arguments: Amount of wounds to remove. -// Return value: Damage taken from removed wounds. - - virtual int RemoveAnyRandomWounds(int amount); - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetMOIDs diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index afbabc4fb..eb1a1e45c 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -3011,97 +3011,6 @@ void ACrab::GetMOIDs(std::vector &MOIDs) const Actor::GetMOIDs(MOIDs); } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: RemoveAnyRandomWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds from the actor and all standard attachables. - -int ACrab::RemoveAnyRandomWounds(int amount) -{ - float damage = 0; - - for (int i = 0; i < amount; i++) - { - // Fill the list of damaged bodyparts - std::vector bodyParts; - if (GetWoundCount() > 0) - bodyParts.push_back(this); - - if (m_pLBGLeg && m_pLBGLeg->GetWoundCount()) - bodyParts.push_back(m_pLBGLeg); - if (m_pRBGLeg && m_pRBGLeg->GetWoundCount()) - bodyParts.push_back(m_pRBGLeg); - if (m_pJetpack && m_pJetpack->GetWoundCount()) - bodyParts.push_back(m_pJetpack); - if (m_pLFGLeg && m_pLFGLeg->GetWoundCount()) - bodyParts.push_back(m_pLFGLeg); - if (m_pRFGLeg && m_pRFGLeg->GetWoundCount()) - bodyParts.push_back(m_pRFGLeg); - if (m_pTurret && m_pTurret->GetWoundCount()) - bodyParts.push_back(m_pTurret); - - // Stop removing wounds if there are not any left - if (bodyParts.size() == 0) - break; - - int partIndex = RangeRand(0, bodyParts.size() - 1); - MOSRotating * part = bodyParts[partIndex]; - damage += part->RemoveWounds(1); - } - - return damage; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound count of this actor and all vital attachables. - -int ACrab::GetTotalWoundCount() const -{ - int count = Actor::GetWoundCount(); - - if (m_pLBGLeg) - count += m_pLBGLeg->GetWoundCount(); - if (m_pRBGLeg) - count += m_pRBGLeg->GetWoundCount(); - if (m_pJetpack) - count += m_pJetpack->GetWoundCount(); - if (m_pLFGLeg) - count += m_pLFGLeg->GetWoundCount(); - if (m_pRFGLeg) - count += m_pRFGLeg->GetWoundCount(); - if (m_pTurret) - count += m_pTurret->GetWoundCount(); - - return count; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound limit of this actor and all vital attachables. - -int ACrab::GetTotalWoundLimit() const -{ - int count = Actor::GetGibWoundLimit(); - - if (m_pLBGLeg) - count += m_pLBGLeg->GetGibWoundLimit(); - if (m_pRBGLeg) - count += m_pRBGLeg->GetGibWoundLimit(); - if (m_pJetpack) - count += m_pJetpack->GetGibWoundLimit(); - if (m_pLFGLeg) - count += m_pLFGLeg->GetGibWoundLimit(); - if (m_pRFGLeg) - count += m_pRFGLeg->GetGibWoundLimit(); - if (m_pTurret) - count += m_pTurret->GetGibWoundLimit(); - - return count; -} - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACrab.h b/Entities/ACrab.h index 635d0a81d..e73efa498 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -546,25 +546,6 @@ ClassInfoGetters virtual void Update(); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound count of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total number of wounds of this actor. - - virtual int GetTotalWoundCount() const; - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound limit of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total wound limit of this actor. - - virtual int GetTotalWoundLimit() const; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw ////////////////////////////////////////////////////////////////////////////////////////// @@ -597,16 +578,6 @@ ClassInfoGetters virtual void DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), int whichScreen = 0, bool playerControlled = false); -////////////////////////////////////////////////////////////////////////////////////////// -// Method: RemoveAnyRandomWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds from the actor and all standard attachables. -// Arguments: Amount of wounds to remove. -// Return value: Damage taken from removed wounds. - - virtual int RemoveAnyRandomWounds(int amount); - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetMOIDs ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index c1149dcf5..a2e5678ff 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -283,26 +283,6 @@ namespace RTE { m_DoorMaterialTempErased = enable; } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - int ADoor::RemoveAnyRandomWounds(int amount) { - float damage = 0; - for (int i = 0; i < amount; i++) { - std::vector woundedBodyParts; - if (GetWoundCount() > 0) { woundedBodyParts.push_back(this); } - if (m_Door && m_Door->GetWoundCount()) { woundedBodyParts.push_back(m_Door); } - - if (woundedBodyParts.size() == 0) { - return damage; - } - - int partIndex = RangeRand(0, woundedBodyParts.size() - 1); - MOSRotating *part = woundedBodyParts[partIndex]; - damage += part->RemoveWounds(1); - } - return damage; - } - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ADoor::GibThis(Vector impactImpulse, float internalBlast, MovableObject *ignoreMO) { diff --git a/Entities/ADoor.h b/Entities/ADoor.h index 74ff30c02..38b7b2388 100644 --- a/Entities/ADoor.h +++ b/Entities/ADoor.h @@ -141,13 +141,6 @@ namespace RTE { #pragma endregion #pragma region Virtual Override Methods - /// - /// Removes a specified amount of wounds from the actor and all standard attachables. - /// - /// Amount of wounds to remove. - /// Damage taken from removed wounds. - virtual int RemoveAnyRandomWounds(int amount); - /// /// Gibs this, effectively destroying it and creating multiple gibs or pieces in its place. /// diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 01a5174b0..6fab99ec5 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -4472,98 +4472,6 @@ void AHuman::DrawThrowingReticule(BITMAP *pTargetBitmap, const Vector &targetPos } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: RemoveAnyRandomWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds from the actor and all standard attachables. - -int AHuman::RemoveAnyRandomWounds(int amount) -{ - float damage = 0; - - for (int i = 0; i < amount; i++) - { - // Fill the list of damaged bodyparts - std::vector bodyParts; - if (GetWoundCount() > 0) - bodyParts.push_back(this); - - if (m_pBGLeg && m_pBGLeg->GetWoundCount()) - bodyParts.push_back(m_pBGLeg); - if (m_pBGArm && m_pBGArm->GetWoundCount()) - bodyParts.push_back(m_pBGArm); - if (m_pJetpack && m_pJetpack->GetWoundCount()) - bodyParts.push_back(m_pJetpack); - if (m_pHead && m_pHead->GetWoundCount()) - bodyParts.push_back(m_pHead); - if (m_pFGLeg && m_pFGLeg->GetWoundCount()) - bodyParts.push_back(m_pFGLeg); - if (m_pFGArm && m_pFGArm->GetWoundCount()) - bodyParts.push_back(m_pFGArm); - - // Stop removing wounds if there are not any left - if (bodyParts.size() == 0) - break; - - int partIndex = RangeRand(0, bodyParts.size() - 1); - MOSRotating * part = bodyParts[partIndex]; - damage += part->RemoveWounds(1); - } - - return damage; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound count of this actor and all vital attachables. - -int AHuman::GetTotalWoundCount() const -{ - int count = Actor::GetTotalWoundCount(); - - if (m_pBGLeg) - count += m_pBGLeg->GetWoundCount(); - if (m_pBGArm) - count += m_pBGArm->GetWoundCount(); - if (m_pJetpack) - count += m_pJetpack->GetWoundCount(); - if (m_pHead) - count += m_pHead->GetWoundCount(); - if (m_pFGLeg) - count += m_pFGLeg->GetWoundCount(); - if (m_pFGArm) - count += m_pFGArm->GetWoundCount(); - - return count; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound limit of this actor and all vital attachables. - -int AHuman::GetTotalWoundLimit() const -{ - int count = Actor::GetGibWoundLimit(); - - if (m_pBGLeg) - count += m_pBGLeg->GetGibWoundLimit(); - if (m_pBGArm) - count += m_pBGArm->GetGibWoundLimit(); - if (m_pJetpack) - count += m_pJetpack->GetGibWoundLimit(); - if (m_pHead) - count += m_pHead->GetGibWoundLimit(); - if (m_pFGLeg) - count += m_pFGLeg->GetGibWoundLimit(); - if (m_pFGArm) - count += m_pFGArm->GetGibWoundLimit(); - - return count; -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: UpdateChildMOIDs ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 38baa6ea2..468a13230 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -799,34 +799,6 @@ ClassInfoGetters virtual bool IsOnScenePoint(Vector &scenePoint) const; - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: RemoveAnyRandomWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds from the actor and all standard attachables. -// Arguments: Amount of wounds to remove. -// Return value: Damage taken from removed wounds. - - virtual int RemoveAnyRandomWounds(int amount); - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound count of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total number of wounds of this actor. - - virtual int GetTotalWoundCount() const; - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound limit of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total wound limit of this actor. - - virtual int GetTotalWoundLimit() const; - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: ResetAllTimers ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index 0e16903bd..c02d06717 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -1364,35 +1364,6 @@ void Actor::UpdateAI() } } - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: RemoveAnyRandomWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds from the actor and all standard attachables. - -int Actor::RemoveAnyRandomWounds(int amount) -{ - float damage = 0; - - for (int i = 0; i < amount; i++) - { - // Fill the list of damaged bodyparts - std::vector bodyParts; - if (GetWoundCount() > 0) - bodyParts.push_back(this); - - // Stop removing wounds if there are not any left - if (bodyParts.size() == 0) - break; - - int partIndex = RangeRand(0, bodyParts.size() - 1); - MOSRotating * part = bodyParts[partIndex]; - damage += part->RemoveWounds(1); - } - - return damage; -} - ////////////////////////////////////////////////////////////////////////////////////////// // Method: VerifyMOIDs ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Actor.h b/Entities/Actor.h index c367ca1ce..bdea7d1c3 100644 --- a/Entities/Actor.h +++ b/Entities/Actor.h @@ -253,15 +253,6 @@ ClassInfoGetters void SetMaxHealth(int newValue) { m_MaxHealth = newValue; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: RemoveAnyRandomWounds -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Removes a specified amount of wounds from the actor and all standard attachables. -// Arguments: Amount of wounds to remove. -// Return value: Damage taken from removed wounds. - - virtual int RemoveAnyRandomWounds(int amount); - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetAimDistance ////////////////////////////////////////////////////////////////////////////////////////// @@ -1171,25 +1162,6 @@ ClassInfoGetters virtual unsigned int GetDeploymentID() const { return m_DeploymentID; } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound count of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total number of wounds of this actor. - - virtual int GetTotalWoundCount() const { return this->GetWoundCount(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound limit of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total wound limit of this actor. - - virtual int GetTotalWoundLimit() const { return this->m_GibWoundLimit; } - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetSightDistance diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 839103d08..03db41e3d 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -422,49 +422,111 @@ int MOSRotating::Save(Writer &writer) const /// /// The wound AEmitter to add /// The vector to set as the wound AEmitter's parent offset -void MOSRotating::AddWound(AEmitter *pWound, const Vector & parentOffsetToSet, bool checkGibWoundLimit) { - if (pWound) { +void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit) { + if (woundToAdd) { if (checkGibWoundLimit && !ToDelete() && m_GibWoundLimit && m_Wounds.size() + 1 > m_GibWoundLimit) { // Indicate blast in opposite direction of emission // TODO: don't hardcode here, get some data from the emitter Vector blast(-5, 0); - blast.RadRotate(pWound->GetEmitAngle()); + blast.RadRotate(woundToAdd->GetEmitAngle()); GibThis(blast); return; } else { - pWound->SetParentOffset(parentOffsetToSet); - pWound->SetParent(this); - m_Wounds.push_back(pWound); + woundToAdd->SetParentOffset(parentOffsetToSet); + woundToAdd->SetParent(this); + m_Wounds.push_back(woundToAdd); } } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// -/// Removes a specified amount of wounds and returns damage caused by this wounds. Head multiplier is not used. -/// -/// Amount of wounds to remove. -/// Amount of damage caused by these wounds. -int MOSRotating::RemoveWounds(int amount) -{ - int deleted = 0; - float damage = 0; +int MOSRotating::GetGibWoundLimit(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const { + int gibWoundLimit = m_GibWoundLimit; + if (includeDamageTransferringAttachables || includeNonDamageTransferringAttachables) { + for (const Attachable *attachable : m_Attachables) { + if (includeDamageTransferringAttachables && attachable->GetTransfersDamageToParent()) { + gibWoundLimit += attachable->GetGibWoundLimit(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables); + } else if (includeNonDamageTransferringAttachables && !attachable->GetTransfersDamageToParent()) { + gibWoundLimit += attachable->GetGibWoundLimit(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables); + } + } + } + return gibWoundLimit; +} - for (list::iterator itr = m_Wounds.begin(); itr != m_Wounds.end();) - { - damage += (*itr)->GetBurstDamage(); - delete (*itr); - (*itr) = 0; - itr = m_Wounds.erase(itr); - deleted++; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (deleted >= amount) - break; - } +int MOSRotating::GetWoundCount(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const { + int woundCount = m_Wounds.size(); + if (includeDamageTransferringAttachables || includeNonDamageTransferringAttachables) { + for (const Attachable *attachable : m_Attachables) { + if (includeDamageTransferringAttachables && attachable->GetTransfersDamageToParent()) { + woundCount += attachable->GetWoundCount(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables); + } else if (includeNonDamageTransferringAttachables && !attachable->GetTransfersDamageToParent()) { + woundCount += attachable->GetWoundCount(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables); + } + } + } + return woundCount; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) { + float damage = 0; + int woundCount = GetWoundCount(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables); + + std::vector> woundedParts; + if (woundCount > 0) { woundedParts.push_back({this, woundCount}); } + for (Attachable *attachable : m_Attachables) { + bool attachableSatisfiesWoundRemovalCriteria = (includeDamageTransferringAttachables && attachable->GetTransfersDamageToParent()) || (includeNonDamageTransferringAttachables && !attachable->GetTransfersDamageToParent()); + if (attachableSatisfiesWoundRemovalCriteria && attachable->GetWoundCount(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables) > 0) { + woundedParts.push_back({attachable, attachable->GetWoundCount(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables)}); + } + } + + if (woundedParts.empty()) { + return damage; + } + + /// + /// Internal lambda function to remove the first wound emitter from this MOSRotating. + /// + auto removeFirstWoundEmitter = [this]() { + if (m_Wounds.size() == 0) { + return 0.0F; + } + float woundDamage = m_Wounds.front()->GetBurstDamage(); + m_Wounds.pop_front(); + return woundDamage; + }; + + for (int i = 0; i < numberOfWoundsToRemove; i++) { + if (woundedParts.size() == 0) { + break; + } + + int woundedPartIndex = static_cast(RangeRand(0.0F, static_cast(woundedParts.size() - 1))); + MOSRotating *woundedPart = woundedParts[woundedPartIndex].first; + if (woundedPart == this) { + damage += removeFirstWoundEmitter() * GetDamageMultiplier(); + } else { + Attachable *woundedPartAsAttachable = dynamic_cast(woundedPart); + if (woundedPartAsAttachable) { + damage += woundedPartAsAttachable->RemoveWounds(1, includeDamageTransferringAttachables, includeNonDamageTransferringAttachables) * (woundedPartAsAttachable->GetTransfersDamageToParent() ? woundedPartAsAttachable->GetDamageMultiplier() : 0); + } + } + if (woundedParts[woundedPartIndex].second-- <= 0) { + woundedParts.erase(woundedParts.begin() + woundedPartIndex); + } + } return damage; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// // Method: Destroy ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index c6973edaf..a65bef218 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -629,32 +629,51 @@ ClassInfoGetters virtual void SetGibWoundLimit(int newLimit) { m_GibWoundLimit = newLimit; } + /// + /// Gets the gib wound limit for this MOSRotating, optionally recursively adding the gib wound limit of damaging and/or non-damaging attachables and any of their such attachables, and so on. + /// + /// Whether to add wound limits of attachables that transfer damage to their parent (this MOSRotating). + /// Whether to add wound limits of attachables that do not transfer damage to their parent (this MOSRotating). + /// The wound limit of this MOSRotating and, optionally, its attachables. + int GetGibWoundLimit(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const; + + /// + /// Gets the number of wounds directly attached to this MOSRotating. + /// The number of wounds on this MOSRotating. + /// + int GetWoundCount() const { return GetWoundCount(false, false); } + + /// + /// Gets the number of wounds attached to this MOSRotating, optionally recursively including wounds on damaging and/or non-damaging attachables and any of their such attachables, and so on. + /// Whether to count wounds from attachables that transfer damage to their parent (this MOSRotating). + /// Whether to count wounds from attachables that do not transfer damage to their parent (this MOSRotating). + /// The number of wounds on this MOSRotating and, optionally, its attachables. + /// + int GetWoundCount(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const; /// /// Attaches the passed in wound AEmitter and adds it to the list of wounds, changing its parent offset to the passed in Vector. /// /// The wound AEmitter to add /// The vector to set as the wound AEmitter's parent offset - virtual void AddWound(AEmitter *pWound, const Vector& parentOffsetToSet, bool checkGibWoundLimit = true); - + void AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit = true); - /// - /// Removes a specified amount of wounds and returns damage caused by these wounds. Head multiplier is not used. - /// - /// Amount of wounds to remove. - /// Amount of damage caused by these wounds. - virtual int RemoveWounds(int amount); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns the amount of wound attached to this. -// Arguments: Key to retrieve value. -// Return value: Wound amount. - - virtual int GetWoundCount() const { return m_Wounds.size(); }; + /// + /// Removes a specified number of wounds and returns damage caused by these wounds. Head multiplier is not used. + /// + /// The number of wounds that should be removed. + /// The amount of damage caused by these wounds. + float RemoveWounds(int numberOfWoundsToRemove) { return RemoveWounds(numberOfWoundsToRemove, true, false); } + /// + /// Removes a specified number of wounds and returns damage caused by these wounds. Head multiplier is not used. + /// Optionally only removes wounds that affect health directly. + /// + /// The number of wounds that should be removed. + /// Whether to remove wounds from attachables that transfer damage to their parent (this MOSRotating). + /// Whether to remove wounds from attachables that do not transfer damage to their parent (this MOSRotating). + /// The amount of damage caused by the removed wounds. + float RemoveWounds(int numberOfWoundsToRemove, bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables); ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetStringValue diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index f94fdfc57..c59c78563 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -751,8 +751,13 @@ int LuaMan::Create() .def("MoveOutOfTerrain", &MOSRotating::MoveOutOfTerrain) .def("ApplyForces", &MOSRotating::ApplyForces) .def("ApplyImpulses", &MOSRotating::ApplyImpulses) + .def("GetGibWoundLimit", (int (MOSRotating:: *)()) &MOSRotating::GetGibWoundLimit) + .def("GetGibWoundLimit", (int (MOSRotating:: *)(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables)) &MOSRotating::GetGibWoundLimit) + .def("GetWoundCount", (int (MOSRotating:: *)()) &MOSRotating::GetWoundCount) + .def("GetWoundCount", (int (MOSRotating:: *)(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables)) &MOSRotating::GetWoundCount) .def("AddWound", &MOSRotating::AddWound, adopt(_2)) - .def("RemoveWounds", &MOSRotating::RemoveWounds) + .def("RemoveWounds", (int (MOSRotating:: *)(int numberOfWoundsToRemove)) &MOSRotating::RemoveWounds) + .def("RemoveWounds", (int (MOSRotating:: *)(int numberOfWoundsToRemove, bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables)) &MOSRotating::RemoveWounds) .def("IsOnScenePoint", &MOSRotating::IsOnScenePoint) .def("EraseFromTerrain", &MOSRotating::EraseFromTerrain) .def("GetStringValue", &MOSRotating::GetStringValue) @@ -955,9 +960,6 @@ int LuaMan::Create() .def("GetAlarmPoint", &Actor::GetAlarmPoint) .property("AimDistance", &Actor::GetAimDistance, &Actor::SetAimDistance) .property("SightDistance", &Actor::GetSightDistance, &Actor::SetSightDistance) - .property("TotalWoundCount", &Actor::GetTotalWoundCount) - .property("TotalWoundLimit", &Actor::GetTotalWoundLimit) - .def("RemoveAnyRandomWounds", &Actor::RemoveAnyRandomWounds) .property("DeathSound", &Actor::GetDeathSound, &Actor::SetDeathSound), CONCRETELUABINDING(ADoor, Actor) From cf5f4269f70f9fb62b17756b34590968c88eced2 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 11 Aug 2020 02:47:55 -0300 Subject: [PATCH 007/144] Followup to c0ed2f4 forgot to include damage multiplier handling for AHuman head Also fixing some incorrect comments in Attachable.h --- Entities/AHuman.cpp | 5 +++-- Entities/Attachable.h | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 6fab99ec5..4b8aed856 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -232,8 +232,9 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) delete m_pHead; m_pHead = new Attachable; reader >> m_pHead; - if (!m_pHead->IsDamageMultiplierRedefined()) - m_pHead->SetDamageMultiplier(5); + if (!m_pHead->GetDamageMultiplier() < 0) { + m_pHead->SetDamageMultiplier(5); + } } else if (propName == "Jetpack") { diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 346888806..b2e43448a 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -319,10 +319,10 @@ namespace RTE { protected: /// - /// Attaches this Attachable to a new parent MOSRotating, safely detaching from its old parent first if there is one. + /// Sets this Attachable's parent MOSRotating, and also sets its Team based on its parent and, if the Attachable is set to collide, adds/removes Atoms to its new/old parent. /// - /// A pointer to the MOSRotating to attach to. Ownership is NOT transferred! - void SetParent(MOSRotating *newParent); + /// A pointer to the MOSRotating to set as the new parent. Ownership is NOT transferred! + virtual void SetParent(MOSRotating *newParent); private: From be5bf22d822418ea62b2e8584301a92d474bf0ca Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 11 Aug 2020 02:48:57 -0300 Subject: [PATCH 008/144] Followup to ee1d235, removed RemoveWounds override from Attachable since its damage multiplier handling is now accounted for in MOSRotating --- Entities/Attachable.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Entities/Attachable.h b/Entities/Attachable.h index b2e43448a..751cbbb11 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -313,8 +313,6 @@ namespace RTE { /// void Update() override; #pragma endregion - //TODO This is crap but MOSR needs to account for damage multiplier - virtual int RemoveWounds(int amount) { return MOSRotating::RemoveWounds(amount) * m_DamageMultiplier; } protected: From 652c265b10e045ee56b95b73ad039737202a682b Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 11 Aug 2020 02:50:25 -0300 Subject: [PATCH 009/144] Followup to 5361c54 fixed leftover Attach and Detach in HDFirearm, SetParent override now deals with reloading like they did --- Entities/HDFirearm.h | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/Entities/HDFirearm.h b/Entities/HDFirearm.h index 7da70e29e..29bb85e96 100644 --- a/Entities/HDFirearm.h +++ b/Entities/HDFirearm.h @@ -444,26 +444,6 @@ ClassInfoGetters // Return value: None. virtual void SetID(const MOID newID); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Attach -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Attaches this Attachable to a host MOSprite -// Arguments: Pointer to the MOSprite to attach to. Ownership is NOT transferred! -// Return value: None. - - virtual void Attach(MOSRotating *newParent) { HeldDevice::Attach(newParent); m_Reloading = false; m_ReloadTmr.Reset(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Detach -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Detaches this Attachable from its host MOSprite -// Arguments: None. -// Return value: None. - - virtual void Detach() { HeldDevice::Detach(); m_Activated = m_Reloading = false; m_ReloadTmr.Reset(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -746,6 +726,13 @@ ClassInfoGetters virtual void GetMOIDs(std::vector &MOIDs) const; + /// + /// Sets this HDFirearm's parent MOSRotating, and also sets its Team based on its parent and, if the Attachable is set to collide, adds/removes Atoms to its new/old parent. + /// Additionally, sets this Attachable as not reloading, and resets its reload timer. + /// + /// A pointer to the MOSRotating to set as the new parent. Ownership is NOT transferred! + void SetParent(MOSRotating *newParent) override { HeldDevice::SetParent(newParent); m_Reloading = false; m_ReloadTmr.Reset(); } + // Member variables. static Entity::ClassInfo m_sClass; From 66012e78e99917aae90abb9a354df8b8b0d5c20e Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 11 Aug 2020 02:51:30 -0300 Subject: [PATCH 010/144] A couple random commits - fixing readability on error when sound is fucked up Fixed bad spacing in AudioMan.h --- Managers/AudioMan.h | 2 +- System/ContentFile.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Managers/AudioMan.h b/Managers/AudioMan.h index de43ef13d..07f75cb6a 100644 --- a/Managers/AudioMan.h +++ b/Managers/AudioMan.h @@ -494,7 +494,7 @@ namespace RTE { // Disallow the use of some implicit methods. AudioMan(const AudioMan &reference) {} - AudioMan & operator=(const AudioMan &rhs) {} + AudioMan &operator=(const AudioMan &rhs) {} }; } #endif \ No newline at end of file diff --git a/System/ContentFile.cpp b/System/ContentFile.cpp index 3b5248aa8..a5998b256 100644 --- a/System/ContentFile.cpp +++ b/System/ContentFile.cpp @@ -252,7 +252,7 @@ namespace RTE { FMOD_RESULT result = g_AudioMan.GetAudioSystem()->createSound(rawData, FMOD_OPENMEMORY | FMOD_3D, &soundInfo, &returnSample); if (result != FMOD_OK) { - errorMessage = "Unable to create sound because of FMOD error " + std::string(FMOD_ErrorString(result)) + ". Path and name was: "; + errorMessage = "Unable to create sound because of FMOD error:\n" + std::string(FMOD_ErrorString(result)) + "\nPath and name was: "; if (abortGameForInvalidSound) { RTEAbort(errorMessage + "\n\n" + m_DataPath); } g_ConsoleMan.PrintString("ERROR: " + errorMessage + m_DataPath); return returnSample; From 177066e36452dd949dd2983a5d3200056ee859e0 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 13 Aug 2020 20:53:23 -0300 Subject: [PATCH 011/144] Removed accidentally skipped old GetJetpack comment in ACrab.h Added clear for m_AlreadyCopiedAttachableUniqueIDs in MOSRotating --- Entities/ACrab.h | 8 -------- Entities/MOSRotating.cpp | 1 + 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Entities/ACrab.h b/Entities/ACrab.h index 260ea5227..6b64f5c8e 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -215,14 +215,6 @@ class ACrab : /// The new leg to use. void SetRightBGLeg(Attachable *newLeg); - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetJetpack -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the jetpack as an emitter. This is for Lua binding mostly. -// Arguments: None. -// Return value: A pointer to jetpack emitter. Ownership is NOT transferred! - /// /// Gets the jetpack emitter for this Crab. /// diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index d2d824aa4..cf8b2d448 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -62,6 +62,7 @@ void MOSRotating::Clear() m_RecoilOffset.Reset(); m_Wounds.clear(); m_Attachables.clear(); + m_AlreadyCopiedAttachableUniqueIDs.clear(); m_Gibs.clear(); m_GibImpulseLimit = 0; m_GibWoundLimit = 0; From 63fe5d674c786df33661e6a1b1150e1ad8fb1cf6 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 13 Aug 2020 21:01:25 -0300 Subject: [PATCH 012/144] Removed accidentally skipped GetTotalWoundCount and GetTotalWoundLimit from ACraft Added and used setters (and for legs, getters) for ACRocket hardcoded attachables, and made them all transfer damage to parent Fixed and added lua bindings for ACDropship and ACRocket hardcoded attachable getting and setting --- Entities/ACRocket.cpp | 174 ++++++++++++++++++++++++------------------ Entities/ACRocket.h | 132 ++++++++++++++++++++------------ Entities/ACraft.h | 19 ----- Managers/LuaMan.cpp | 24 +++--- 4 files changed, 197 insertions(+), 152 deletions(-) diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 6c591dcbd..cee022f9a 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -91,19 +91,16 @@ int ACRocket::Create() ////////////////////////////////////////////////////////////////////////////////////////// // Description: Creates a ACRocket to be identical to another, by deep copy. -int ACRocket::Create(const ACRocket &reference) -{ - ACraft::Create(reference); +int ACRocket::Create(const ACRocket &reference) { + if (reference.m_pRLeg) { CloneHardcodedAttachable(reference.m_pRLeg, ACRocket::SetRightLeg); } + if (reference.m_pLLeg) { CloneHardcodedAttachable(reference.m_pLLeg, ACRocket::SetLeftLeg); } + if (reference.m_pMThruster) { CloneHardcodedAttachable(reference.m_pMThruster, ACRocket::SetMainThruster); } + if (reference.m_pRThruster) { CloneHardcodedAttachable(reference.m_pRThruster, ACRocket::SetRightThruster); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLThruster, ACRocket::SetLeftThruster); } + if (reference.m_pURThruster) { CloneHardcodedAttachable(reference.m_pURThruster, ACRocket::SetURightThruster); } + if (reference.m_pULThruster) { CloneHardcodedAttachable(reference.m_pULThruster, ACRocket::SetULeftThruster); } - if (reference.m_pRLeg) { - m_pRLeg = dynamic_cast(reference.m_pRLeg->Clone()); - AddAttachable(m_pRLeg, true); - } - - if (reference.m_pLLeg) { - m_pLLeg = dynamic_cast(reference.m_pLLeg->Clone()); - AddAttachable(m_pLLeg, true); - } + ACraft::Create(reference); m_pBodyAG = dynamic_cast(reference.m_pBodyAG->Clone()); m_pBodyAG->SetOwner(this); @@ -119,32 +116,6 @@ int ACRocket::Create(const ACRocket &reference) m_pLFootGroup->SetOwner(this); } - if (reference.m_pMThruster) - { - m_pMThruster = dynamic_cast(reference.m_pMThruster->Clone()); - AddAttachable(m_pMThruster, true); - } - if (reference.m_pRThruster) - { - m_pRThruster = dynamic_cast(reference.m_pRThruster->Clone()); - AddAttachable(m_pRThruster, true); - } - if (reference.m_pLThruster) - { - m_pLThruster = dynamic_cast(reference.m_pLThruster->Clone()); - AddAttachable(m_pLThruster, true); - } - if (reference.m_pURThruster) - { - m_pURThruster = dynamic_cast(reference.m_pURThruster->Clone()); - AddAttachable(m_pURThruster, true); - } - if (reference.m_pULThruster) - { - m_pULThruster = dynamic_cast(reference.m_pULThruster->Clone()); - AddAttachable(m_pULThruster, true); - } - m_GearState = reference.m_GearState; for (int i = 0; i < GearStateCount; ++i) { @@ -166,77 +137,66 @@ int ACRocket::Create(const ACRocket &reference) // is called. If the property isn't recognized by any of the base classes, // false is returned, and the reader's position is untouched. -int ACRocket::ReadProperty(std::string propName, Reader &reader) -{ - if (propName == "RLeg") - { +int ACRocket::ReadProperty(std::string propName, Reader &reader) { + if (propName == "RLeg") { delete m_pRLeg; m_pRLeg = new Leg; reader >> m_pRLeg; - } - else if (propName == "LLeg") - { + m_pRLeg->SetTransfersDamageToParent(true); + } else if (propName == "LLeg") { delete m_pLLeg; m_pLLeg = new Leg; reader >> m_pLLeg; m_pLLeg->SetHFlipped(true); - } - else if (propName == "RFootGroup") - { + m_pLLeg->SetTransfersDamageToParent(true); + } else if (propName == "RFootGroup") { delete m_pRFootGroup; m_pRFootGroup = new AtomGroup(); reader >> m_pRFootGroup; m_pRFootGroup->SetOwner(this); - } - else if (propName == "LFootGroup") - { + } else if (propName == "LFootGroup") { delete m_pLFootGroup; m_pLFootGroup = new AtomGroup(); reader >> m_pLFootGroup; m_pLFootGroup->SetOwner(this); - } - else if (propName == "MThruster") - { + } else if (propName == "MThruster"){ delete m_pMThruster; m_pMThruster = new AEmitter; reader >> m_pMThruster; - } - else if (propName == "RThruster") - { + m_pMThruster->SetTransfersDamageToParent(true); + } else if (propName == "RThruster") { delete m_pRThruster; m_pRThruster = new AEmitter; reader >> m_pRThruster; - } - else if (propName == "LThruster") - { + m_pRThruster->SetTransfersDamageToParent(true); + } else if (propName == "LThruster") { delete m_pLThruster; m_pLThruster = new AEmitter; reader >> m_pLThruster; - } - else if (propName == "URThruster") - { + m_pLThruster->SetTransfersDamageToParent(true); + } else if (propName == "URThruster") { delete m_pURThruster; m_pURThruster = new AEmitter; reader >> m_pURThruster; - } - else if (propName == "ULThruster") - { + m_pURThruster->SetTransfersDamageToParent(true); + } else if (propName == "ULThruster") { delete m_pULThruster; m_pULThruster = new AEmitter; reader >> m_pULThruster; - } - else if (propName == "RaisedGearLimbPath") + m_pULThruster->SetTransfersDamageToParent(true); + } else if (propName == "RaisedGearLimbPath") { reader >> m_Paths[RIGHT][RAISED]; - else if (propName == "LoweredGearLimbPath") + } else if (propName == "LoweredGearLimbPath") { reader >> m_Paths[RIGHT][LOWERED]; - else if (propName == "LoweringGearLimbPath") + } else if (propName == "LoweringGearLimbPath") { reader >> m_Paths[RIGHT][LOWERING]; - else if (propName == "RaisingGearLimbPath") + } else if (propName == "RaisingGearLimbPath") { reader >> m_Paths[RIGHT][RAISING]; - else if (propName == "ScuttleIfFlippedTime") + } else if (propName == "ScuttleIfFlippedTime") { reader >> m_ScuttleIfFlippedTime; - else + } else { return ACraft::ReadProperty(propName, reader); + } return 0; } @@ -1084,6 +1044,74 @@ void ACRocket::GetMOIDs(std::vector &MOIDs) const ACraft::GetMOIDs(MOIDs); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ACRocket::SetRightLeg(Attachable *newLeg) { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pRLeg); + m_pRLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ACRocket::SetLeftLeg(Attachable *newLeg) { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pLLeg); + m_pLLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ACRocket::SetRightThruster(Attachable *newThruster) { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pRThruster); + m_pRThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ACRocket::SetLeftThruster(Attachable *newThruster) { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pLThruster); + m_pLThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ACRocket::SetURightThruster(Attachable *newThruster) { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pURThruster); + m_pURThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ACRocket::SetULeftThruster(Attachable *newThruster) { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pULThruster); + m_pULThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// // Method: ResetEmissionTimers diff --git a/Entities/ACRocket.h b/Entities/ACRocket.h index f4bdea314..bfe3464c3 100644 --- a/Entities/ACRocket.h +++ b/Entities/ACRocket.h @@ -239,55 +239,89 @@ ClassInfoGetters void GetMOIDs(std::vector &MOIDs) const override; - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetMThruster -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the main thruster. -// Arguments: None. -// Return value: An AEmitter pointer. - - AEmitter * GetMThruster() const { return m_pMThruster; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetRThruster -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the right thruster. -// Arguments: None. -// Return value: An AEmitter pointer. - - AEmitter * GetRThruster() const { return m_pRThruster; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetLThruster -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the left thruster. -// Arguments: None. -// Return value: An AEmitter pointer. - - AEmitter * GetLThruster() const { return m_pLThruster; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetURThruster -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the right side secondary thruster. -// Arguments: None. -// Return value: An AEmitter pointer. - - AEmitter * GetURThruster() const { return m_pURThruster; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetULThruster -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the left side secondary thruster. -// Arguments: None. -// Return value: An AEmitter pointer. - - AEmitter * GetULThruster() const { return m_pULThruster; } + /// + /// Gets the right leg of this ACRocket. + /// + /// A pointer to the right leg of this ACRocket. Ownership is NOT transferred. + Leg *GetRightLeg() const { return m_pRLeg; } + + /// + /// Sets the right leg for this ACRocket. + /// + /// The new leg to use. + void SetRightLeg(Attachable *newLeg); + + /// + /// Gets the left leg of this ACRocket. + /// + /// A pointer to the left leg of this ACRocket. Ownership is NOT transferred. + Leg *GetLeftLeg() const { return m_pLLeg; } + + /// + /// Sets the left leg for this ACRocket. + /// + /// The new leg to use. + void SetLeftLeg(Attachable *newLeg); + + /// + /// Gets the main thruster of this ACRocket. + /// + /// A pointer to the main thruster of this ACRocket. Ownership is NOT transferred. + AEmitter *GetMainThruster() const { return m_pMThruster; } + + /// + /// Sets the main thruster for this ACRocket. + /// + /// The new thruster to use. + void SetMainThruster(Attachable *newThruster); + + /// + /// Gets the right side thruster of this ACRocket. + /// + /// A pointer to the right side thruster of this ACRocket. Ownership is NOT transferred. + AEmitter *GetRightThruster() const { return m_pRThruster; } + + /// + /// Sets the right side thruster for this ACRocket. + /// + /// The new thruster to use. + void SetRightThruster(Attachable *newThruster); + + /// + /// Gets the left side thruster of this ACRocket. + /// + /// A pointer to the left side thruster of this ACRocket. Ownership is NOT transferred. + AEmitter *GetLeftThruster() const { return m_pLThruster; } + + /// + /// Sets the left side thruster for this ACRocket. + /// + /// The new thruster to use. + void SetLeftThruster(Attachable *newThruster); + + /// + /// Gets the right side secondary thruster of this ACRocket. + /// + /// A pointer to the right side secondary thruster of this ACRocket. Ownership is NOT transferred. + AEmitter *GetURightThruster() const { return m_pURThruster; } + + /// + /// Sets the right side secondary thruster for this ACRocket. + /// + /// The new thruster to use. + void SetURightThruster(Attachable *newThruster); + + /// + /// Gets the left side secondary thruster of this ACRocket. + /// + /// A pointer to the left side secondary thruster of this ACRocket. Ownership is NOT transferred. + AEmitter *GetULeftThruster() const { return m_pULThruster; } + + /// + /// Sets the left side secondary thruster for this ACRocket. + /// + /// The new thruster to use. + void SetULeftThruster(Attachable *newThruster); ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACraft.h b/Entities/ACraft.h index 0cd511bd3..7f0133db5 100644 --- a/Entities/ACraft.h +++ b/Entities/ACraft.h @@ -569,25 +569,6 @@ enum virtual void SetMaxPassengers(int max) { m_MaxPassengers = max; } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundCount -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound count of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total number of wounds of this actor. - - int GetTotalWoundCount() const override { return Actor::GetTotalWoundCount(); } - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetTotalWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns total wound limit of this actor and all vital attachables. -// Arguments: None. -// Return value: Returns total wound limit of this actor. - - int GetTotalWoundLimit() const override { return Actor::GetTotalWoundLimit(); }; - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetDeliveryDelayMultiplier ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 7ec1171a0..131243b21 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1217,12 +1217,12 @@ int LuaMan::Create() .property("DeliveryDelayMultiplier", &ACraft::GetDeliveryDelayMultiplier), CONCRETELUABINDING(ACDropShip, ACraft) - .property("RightEngine", &ACDropShip::GetRThruster) - .property("LeftEngine", &ACDropShip::GetLThruster) - .property("RightThruster", &ACDropShip::GetURThruster) - .property("LeftThruster", &ACDropShip::GetULThruster) - .property("LeftHatch", &ACDropShip::GetLHatch) - .property("RightHatch", &ACDropShip::GetRHatch) + .property("RightEngine", &ACDropShip::GetRightThruster, &ACDropShip::SetRightThruster) + .property("LeftEngine", &ACDropShip::GetLeftThruster, &ACDropShip::SetLeftThruster) + .property("RightThruster", &ACDropShip::GetURightThruster, &ACDropShip::SetURightThruster) + .property("LeftThruster", &ACDropShip::GetULeftThruster, &ACDropShip::SetULeftThruster) + .property("LeftHatch", &ACDropShip::GetLeftHatch, &ACDropShip::SetLeftHatch) + .property("RightHatch", &ACDropShip::GetRightHatch, &ACDropShip::SetRightHatch) .property("MaxEngineAngle", &ACDropShip::GetMaxEngineAngle, &ACDropShip::SetMaxEngineAngle) .property("LateralControlSpeed", &ACDropShip::GetLateralControlSpeed, &ACDropShip::SetLateralControlSpeed) .property("LateralControl", &ACDropShip::GetLateralControl) @@ -1238,11 +1238,13 @@ int LuaMan::Create() value("RAISING", 3 /*ACRocket::LandingGearState::RAISING*/), value("GearStateCount", 4 /*ACRocket::LandingGearState::GearStateCount*/) ] - .property("MainEngine", &ACRocket::GetMThruster) - .property("LeftEngine", &ACRocket::GetLThruster) - .property("RightEngine", &ACRocket::GetRThruster) - .property("LeftThruster", &ACRocket::GetULThruster) - .property("RightThruster", &ACRocket::GetURThruster) + .property("RightLeg", &ACRocket::GetRightLeg, &ACRocket::SetRightLeg) + .property("LeftLeg", &ACRocket::GetLeftLeg, &ACRocket::SetLeftLeg) + .property("MainEngine", &ACRocket::GetMainThruster, &ACRocket::SetMainThruster) + .property("LeftEngine", &ACRocket::GetLeftThruster, &ACRocket::SetLeftThruster) + .property("RightEngine", &ACRocket::GetRightThruster, &ACRocket::SetRightThruster) + .property("LeftThruster", &ACRocket::GetULeftThruster, &ACRocket::SetULeftThruster) + .property("RightThruster", &ACRocket::GetURightThruster, &ACRocket::SetURightThruster) .property("GearState", &ACRocket::GetGearState), CONCRETELUABINDING(HeldDevice, Attachable) From 2d4998ae1d68be284961f9a9d35a67b8c2d45108 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 13 Aug 2020 21:03:15 -0300 Subject: [PATCH 013/144] Followup to 63fe5d6, added missing setter for SetMainThruster --- Entities/ACRocket.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index cee022f9a..5419a51a7 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -1068,6 +1068,17 @@ void ACRocket::SetLeftLeg(Attachable *newLeg) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void ACRocket::SetMainThruster(Attachable *newThruster) { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pMThruster); + m_pMThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ACRocket::SetRightThruster(Attachable *newThruster) { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { From 9850343e219bd37e26f9ac5f3df8a923d2215d0e Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 15 Aug 2020 12:04:25 -0300 Subject: [PATCH 014/144] Added setter for ADoor door Attachable and used it in Create. Added lua binding for it. --- Entities/ADoor.cpp | 18 +++++++++++++----- Entities/ADoor.h | 8 +++++++- Managers/LuaMan.cpp | 2 +- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index 316a37b61..721423484 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -45,6 +45,9 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int ADoor::Create(const ADoor &reference) { + if (reference.m_Door) { CloneHardcodedAttachable(reference.m_Door, ADoor::SetDoor); } + //TODO this was setting door parent offset to my closed offset, which is super weird. Test that doors are still cool. Old code was AddAttachable(m_Door, m_ClosedOffset, true); + Actor::Create(reference); m_InitialSpriteAnimDuration = reference.m_SpriteAnimDuration; @@ -54,11 +57,6 @@ namespace RTE { } m_SensorInterval = reference.m_SensorInterval; - if (reference.m_Door) { - m_Door = dynamic_cast(reference.m_Door->Clone()); - AddAttachable(m_Door, m_ClosedOffset, true); - } - // Set the initial door state to the opposite of default so it'll move to default when spawned and draw the door material layer. m_DoorState = reference.m_ClosedByDefault ? OPEN : CLOSED; @@ -200,6 +198,16 @@ namespace RTE { Clear(); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void ADoor::SetDoor(Attachable *newDoor) { + if (newDoor) { + RemoveAttachable(m_Door); + m_Door = newDoor; + AddAttachable(newDoor); + } + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float ADoor::GetMass() const { diff --git a/Entities/ADoor.h b/Entities/ADoor.h index 71858dbcc..8b0a2c7c1 100644 --- a/Entities/ADoor.h +++ b/Entities/ADoor.h @@ -71,7 +71,13 @@ namespace RTE { /// Gets the moving door Attachable of this ADoor /// /// A pointer to the door Attachable of this. Ownership is NOT transferred! - Attachable * GetDoor() const { return m_Door; } + Attachable *GetDoor() const { return m_Door; } + + /// + /// Sets the moving door Attachable for this ADoor. + /// + /// The new moving door attachable to use. + void SetDoor(Attachable *newDoor); /// /// Gets the current state of the door. diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 131243b21..6de95b265 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -985,7 +985,7 @@ int LuaMan::Create() value("CLOSING", ADoor::DoorState::CLOSING), value("STOPPED", ADoor::DoorState::STOPPED) ] - .property("Door", &ADoor::GetDoor) + .property("Door", &ADoor::GetDoor, &ADoor::SetDoor) .def("GetDoorState", &ADoor::GetDoorState) .def("OpenDoor", &ADoor::OpenDoor) .def("CloseDoor", &ADoor::CloseDoor) From 356919abd5a4e6402cd308cb2199e840855553b1 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 16 Aug 2020 23:39:52 -0300 Subject: [PATCH 015/144] Cleaned up hardcoded attachable getters for AHuman and added setters and lua bindings for them. Set TransfersDamageToParent property for relevant AHuman hardcoded attachables. Also cleaned up GetHeadBitmap while I was there Reorganized ACrab hardcoded attachable setters slightly and fixed some method comments. Also moved GetTurret into the cpp --- Entities/ACrab.cpp | 59 ++++++------- Entities/ACrab.h | 89 ++++++++++---------- Entities/AHuman.cpp | 198 ++++++++++++++++++++++++-------------------- Entities/AHuman.h | 115 +++++++++++++------------ Managers/LuaMan.cpp | 14 ++-- 5 files changed, 245 insertions(+), 230 deletions(-) diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index a080e6af0..f3bdea1ee 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -495,6 +495,28 @@ Vector ACrab::GetEyePos() const ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void ACrab::SetTurret(Attachable *newTurret) { + Turret *castedNewTurret = dynamic_cast(newTurret); + if (castedNewTurret) { + RemoveAttachable(m_pTurret); + m_pTurret = castedNewTurret; + AddAttachable(castedNewTurret); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void ACrab::SetJetpack(Attachable *newJetpack) { + AEmitter *castedNewJetpack = dynamic_cast(newJetpack); + if (castedNewJetpack) { + RemoveAttachable(m_pJetpack); + m_pJetpack = castedNewJetpack; + AddAttachable(castedNewJetpack); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ACrab::SetLeftFGLeg(Attachable *newLeg) { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { @@ -517,7 +539,7 @@ void ACrab::SetLeftBGLeg(Attachable *newLeg) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline void ACrab::SetRightFGLeg(Attachable *newLeg) { +void ACrab::SetRightFGLeg(Attachable *newLeg) { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { RemoveAttachable(m_pRFGLeg); @@ -528,7 +550,7 @@ inline void ACrab::SetRightFGLeg(Attachable *newLeg) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline void ACrab::SetRightBGLeg(Attachable *newLeg) { +void ACrab::SetRightBGLeg(Attachable *newLeg) { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { RemoveAttachable(m_pRBGLeg); @@ -539,17 +561,6 @@ inline void ACrab::SetRightBGLeg(Attachable *newLeg) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -inline void ACrab::SetJetpack(Attachable *newJetpack) { - AEmitter *castedNewJetpack = dynamic_cast(newJetpack); - if (castedNewJetpack) { - RemoveAttachable(m_pJetpack); - m_pJetpack = castedNewJetpack; - AddAttachable(castedNewJetpack); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: SetID @@ -722,28 +733,6 @@ bool ACrab::HandlePieCommand(int pieSliceIndex) return false; } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -Attachable * ACrab::GetTurret() const { - if (m_pTurret && m_pTurret->IsAttached()) { - return dynamic_cast(m_pTurret); - } - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void ACrab::SetTurret(Attachable *newTurret) { - Turret *castedNewTurret = dynamic_cast(newTurret); - if (castedNewTurret) { - RemoveAttachable(m_pTurret); - m_pTurret = castedNewTurret; - AddAttachable(castedNewTurret); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual Method: GetEquippedItem diff --git a/Entities/ACrab.h b/Entities/ACrab.h index 6b64f5c8e..ce97620b6 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -167,66 +167,78 @@ class ACrab : Vector GetEyePos() const override; + /// + /// Gets the Turret of this Crab. + /// + /// A pointer to the Crab's Turret. Ownership is NOT transferred! + Attachable *GetTurret() const { return (m_pTurret && m_pTurret->IsAttached()) ? dynamic_cast(m_pTurret) : nullptr; } + + /// + /// Sets the turret for this Crab. Ownership IS transferred! + /// + /// The new turret to use. + void SetTurret(Attachable *newTurret); + + /// + /// Gets the jetpack of this ACrab. + /// + /// A pointer to the jetpack of this ACrab. Ownership is NOT transferred! + AEmitter *GetJetpack() const { return m_pJetpack; } + + /// + /// Sets the jetpack for this ACrab. Ownership IS Transferred! + /// + /// The new jetpack to use. + void SetJetpack(Attachable *newJetpack); + /// - /// Gets the left FG Leg as an Attachable. + /// Gets the left foreground Leg of this ACrab. /// - /// A pointer to the Leg Attachable. Ownership is NOT transferred! - Attachable * GetLeftFGLeg() const { return dynamic_cast(m_pLFGLeg); } + /// A pointer to the left foreground Leg of this ACrab. Ownership is NOT transferred! + Attachable *GetLeftFGLeg() const { return static_cast(m_pLFGLeg); } /// - /// Sets the left foreground leg for this Crab. Ownership IS transferred! + /// Sets the left foreground Leg for this ACrab. Ownership IS transferred! /// - /// The new leg to use. + /// The new Leg to use. void SetLeftFGLeg(Attachable *newLeg); /// - /// Gets the left BG Leg as an Attachable. + /// Gets the left background Leg of this ACrab. /// - /// A pointer to the Leg Attachable. Ownership is NOT transferred! - Attachable * GetLeftBGLeg() const { return dynamic_cast(m_pLBGLeg); } + /// A pointer to the left background Leg of this ACrab. Ownership is NOT transferred! + Attachable *GetLeftBGLeg() const { return static_cast(m_pLBGLeg); } /// - /// Sets the left background leg for this Crab. Ownership IS transferred! + /// Sets the left background Leg for this ACrab. Ownership IS transferred! /// - /// The new leg to use. + /// The new Leg to use. void SetLeftBGLeg(Attachable *newLeg); /// - /// Gets the right FG Leg as an Attachable. + /// Gets the right foreground Leg of this ACrab. /// - /// A pointer to the Leg Attachable. Ownership is NOT transferred! - Attachable * GetRightFGLeg() const { return dynamic_cast(m_pRFGLeg); } + /// A pointer to the right foreground Leg of this ACrab. Ownership is NOT transferred! + Attachable *GetRightFGLeg() const { return static_cast(m_pRFGLeg); } /// - /// Sets the right foreground leg for this Crab. Ownership IS transferred! + /// Sets the right foreground Leg for this ACrab. Ownership IS transferred! /// - /// The new leg to use. + /// The new Leg to use. void SetRightFGLeg(Attachable *newLeg); /// - /// Gets the right BG Leg as an Attachable. + /// Gets the right BG Leg of this ACrab. /// - /// A pointer to the Leg Attachable. Ownership is NOT transferred! - Attachable *GetRightBGLeg() const { return dynamic_cast(m_pRBGLeg); } + /// A pointer to the right background Leg of this ACrab. Ownership is NOT transferred! + Attachable *GetRightBGLeg() const { return static_cast(m_pRBGLeg); } /// - /// Sets the right background leg for this Crab. Ownership IS transferred! + /// Sets the right background Leg for this ACrab. Ownership IS transferred! /// - /// The new leg to use. + /// The new Leg to use. void SetRightBGLeg(Attachable *newLeg); - /// - /// Gets the jetpack emitter for this Crab. - /// - /// A pointer to the jetpack emitter. Ownership is NOT transferred! - AEmitter * GetJetpack() const { return (AEmitter *)m_pJetpack; } - - /// - /// Sets the jetpack for this Crab. Ownership IS Transferred! - /// - /// The new jetpack to use. - void SetJetpack(Attachable *newJetpack); - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetJetTimeTotal @@ -303,19 +315,6 @@ class ACrab : bool HandlePieCommand(int pieSliceIndex) override; - /// - /// Gets the turret of this Crab. - /// - /// A pointer to the Crab's turret. Ownership is NOT transferred! - Attachable * GetTurret() const; - - /// - /// Sets the turret for this Crab. Ownership IS transferred! - /// - /// The new turret to use. - void SetTurret(Attachable *newTurret); - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetEquippedItem ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 45f92774c..9ab8637e2 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -137,46 +137,19 @@ int AHuman::Create() ////////////////////////////////////////////////////////////////////////////////////////// // Description: Creates a AHuman to be identical to another, by deep copy. -int AHuman::Create(const AHuman &reference) -{ +int AHuman::Create(const AHuman &reference) { + if (reference.m_pHead) { CloneHardcodedAttachable(reference.m_pHead, AHuman::SetHead); } + if (reference.m_pJetpack) { CloneHardcodedAttachable(reference.m_pJetpack, AHuman::SetJetpack); } + if (reference.m_pFGArm) { CloneHardcodedAttachable(reference.m_pFGArm, AHuman::SetFGArm); } + if (reference.m_pBGArm) { CloneHardcodedAttachable(reference.m_pBGArm, AHuman::SetBGArm); } + if (reference.m_pFGLeg) { CloneHardcodedAttachable(reference.m_pFGLeg, AHuman::SetFGLeg); } + if (reference.m_pBGLeg) { CloneHardcodedAttachable(reference.m_pBGLeg, AHuman::SetBGLeg); } Actor::Create(reference); m_ThrowPrepTime = reference.m_ThrowPrepTime; - - if (reference.m_pHead) { - m_pHead = dynamic_cast(reference.m_pHead->Clone()); - m_pHead->SetCanCollideWithTerrainWhenAttached(true); - AddAttachable(m_pHead, true); - } - - if (reference.m_pJetpack) { - m_pJetpack = dynamic_cast(reference.m_pJetpack->Clone()); - AddAttachable(m_pJetpack, true); - } - m_JetTimeTotal = reference.m_JetTimeTotal; m_JetTimeLeft = reference.m_JetTimeLeft; - if (reference.m_pFGArm) { - m_pFGArm = dynamic_cast(reference.m_pFGArm->Clone()); - AddAttachable(m_pFGArm, true); - } - - if (reference.m_pBGArm) { - m_pBGArm = dynamic_cast(reference.m_pBGArm->Clone()); - AddAttachable(m_pBGArm, true); - } - - if (reference.m_pFGLeg) { - m_pFGLeg = dynamic_cast(reference.m_pFGLeg->Clone()); - AddAttachable(m_pFGLeg, true); - } - - if (reference.m_pBGLeg) { - m_pBGLeg = dynamic_cast(reference.m_pBGLeg->Clone()); - AddAttachable(m_pBGLeg, true); - } - m_pFGHandGroup = dynamic_cast(reference.m_pFGHandGroup->Clone()); m_pFGHandGroup->SetOwner(this); m_pBGHandGroup = dynamic_cast(reference.m_pBGHandGroup->Clone()); @@ -192,8 +165,7 @@ int AHuman::Create(const AHuman &reference) m_MoveState = reference.m_MoveState; m_ProneState = reference.m_ProneState; - for (int i = 0; i < MOVEMENTSTATECOUNT; ++i) - { + for (int i = 0; i < MOVEMENTSTATECOUNT; ++i) { m_Paths[FGROUND][i].Create(reference.m_Paths[FGROUND][i]); m_Paths[BGROUND][i].Create(reference.m_Paths[BGROUND][i]); } @@ -223,57 +195,46 @@ int AHuman::Create(const AHuman &reference) // is called. If the property isn't recognized by any of the base classes, // false is returned, and the reader's position is untouched. -int AHuman::ReadProperty(std::string propName, Reader &reader) -{ - if (propName == "ThrowPrepTime") - reader >> m_ThrowPrepTime; - else if (propName == "Head") - { +int AHuman::ReadProperty(std::string propName, Reader &reader) { + if (propName == "ThrowPrepTime") { + reader >> m_ThrowPrepTime; + } else if (propName == "Head") { delete m_pHead; m_pHead = new Attachable; reader >> m_pHead; - if (!m_pHead->GetDamageMultiplier() < 0) { + if (m_pHead->GetDamageMultiplier() >= 0.0F) { m_pHead->SetDamageMultiplier(5); } - } - else if (propName == "Jetpack") - { + m_pHead->SetTransfersDamageToParent(true); + } else if (propName == "Jetpack") { delete m_pJetpack; m_pJetpack = new AEmitter; reader >> m_pJetpack; - } - else if (propName == "JumpTime") - { + } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; // Convert to ms m_JetTimeTotal *= 1000; - } - else if (propName == "FGArm") - { + } else if (propName == "FGArm") { delete m_pFGArm; m_pFGArm = new Arm; reader >> m_pFGArm; - } - else if (propName == "BGArm") - { + m_pFGArm->SetTransfersDamageToParent(true); + } else if (propName == "BGArm") { delete m_pBGArm; m_pBGArm = new Arm; reader >> m_pBGArm; - } - else if (propName == "FGLeg") - { + m_pBGArm->SetTransfersDamageToParent(true); + } else if (propName == "FGLeg") { delete m_pFGLeg; m_pFGLeg = new Leg; reader >> m_pFGLeg; - } - else if (propName == "BGLeg") - { + m_pFGLeg->SetTransfersDamageToParent(true); + } else if (propName == "BGLeg") { delete m_pBGLeg; m_pBGLeg = new Leg; reader >> m_pBGLeg; - } - else if (propName == "HandGroup") - { + m_pBGLeg->SetTransfersDamageToParent(true); + } else if (propName == "HandGroup") { delete m_pFGHandGroup; delete m_pBGHandGroup; m_pFGHandGroup = new AtomGroup(); @@ -282,43 +243,39 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) m_pBGHandGroup->Create(*m_pFGHandGroup); m_pFGHandGroup->SetOwner(this); m_pBGHandGroup->SetOwner(this); - } - else if (propName == "FGFootGroup") - { + } else if (propName == "FGFootGroup") { delete m_pFGFootGroup; m_pFGFootGroup = new AtomGroup(); reader >> m_pFGFootGroup; m_pFGFootGroup->SetOwner(this); - } - else if (propName == "BGFootGroup") - { + } else if (propName == "BGFootGroup") { delete m_pBGFootGroup; m_pBGFootGroup = new AtomGroup(); reader >> m_pBGFootGroup; m_pBGFootGroup->SetOwner(this); - } - else if (propName == "StrideSound") + } else if (propName == "StrideSound") { reader >> m_StrideSound; - else if (propName == "StandLimbPath") + } else if (propName == "StandLimbPath") { reader >> m_Paths[FGROUND][STAND]; - else if (propName == "StandLimbPathBG") + } else if (propName == "StandLimbPathBG") { reader >> m_Paths[BGROUND][STAND]; - else if (propName == "WalkLimbPath") + } else if (propName == "WalkLimbPath") { reader >> m_Paths[FGROUND][WALK]; - else if (propName == "CrouchLimbPath") + } else if (propName == "CrouchLimbPath") { reader >> m_Paths[FGROUND][CROUCH]; - else if (propName == "CrawlLimbPath") + } else if (propName == "CrawlLimbPath") { reader >> m_Paths[FGROUND][CRAWL]; - else if (propName == "ArmCrawlLimbPath") + } else if (propName == "ArmCrawlLimbPath") { reader >> m_Paths[FGROUND][ARMCRAWL]; - else if (propName == "ClimbLimbPath") + } else if (propName == "ClimbLimbPath") { reader >> m_Paths[FGROUND][CLIMB]; - else if (propName == "JumpLimbPath") + } else if (propName == "JumpLimbPath") { reader >> m_Paths[FGROUND][JUMP]; - else if (propName == "DislodgeLimbPath") + } else if (propName == "DislodgeLimbPath") { reader >> m_Paths[FGROUND][DISLODGE]; - else + } else { return Actor::ReadProperty(propName, reader); + } return 0; } @@ -518,20 +475,79 @@ Vector AHuman::GetEyePos() const return m_Pos; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetHeadBitmap -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the sprite representing the head of this. +void AHuman::SetHead(Attachable *newHead) { + if (newHead) { + RemoveAttachable(m_pHead); + m_pHead = newHead; + AddAttachable(newHead); + } +} -BITMAP * AHuman::GetHeadBitmap() const -{ - if (m_pHead && m_pHead->IsAttached()) - return m_pHead->GetSpriteFrame(0); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - return 0; +void AHuman::SetJetpack(Attachable *newJetpack) { + AEmitter *castedNewJetpack = dynamic_cast(newJetpack); + if (castedNewJetpack) { + RemoveAttachable(m_pJetpack); + m_pJetpack = castedNewJetpack; + AddAttachable(castedNewJetpack); + } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void AHuman::SetFGArm(Attachable *newArm) { + Arm *castedNewArm = dynamic_cast(newArm); + if (castedNewArm) { + RemoveAttachable(m_pFGArm); + m_pFGArm = castedNewArm; + AddAttachable(castedNewArm); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void AHuman::SetBGArm(Attachable *newArm) { + Arm *castedNewArm = dynamic_cast(newArm); + if (castedNewArm) { + RemoveAttachable(m_pBGArm); + m_pBGArm = castedNewArm; + AddAttachable(castedNewArm); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void AHuman::SetFGLeg(Attachable *newLeg) { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pFGLeg); + m_pFGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void AHuman::SetBGLeg(Attachable *newLeg) { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pBGLeg); + m_pBGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +BITMAP *AHuman::GetHeadBitmap() const { + return (m_pHead && m_pHead->IsAttached()) ? m_pHead->GetSpriteFrame(0) : nullptr; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: SetID diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 21efd10b4..78b286c9f 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -244,78 +244,89 @@ ClassInfoGetters Vector GetEyePos() const override; -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetHead -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the head Attachable -// Arguments: None. -// Return value: A pointer to the head Attachable of this. Ownership is NOT transferred! + /// + /// Gets the head of this AHuman. + /// + /// A pointer to the head of this AHuman. Ownership is NOT transferred. + Attachable *GetHead() const { return m_pHead; } - Attachable * GetHead() const { return m_pHead; } + /// + /// Sets the head for this AHuman. + /// + /// The new head to use. + void SetHead(Attachable *newHead); + /// + /// Gets the jetpack of this AHuman. + /// + /// A pointer to the jetpack of this AHuman. Ownership is NOT transferred. + AEmitter *GetJetpack() const { return m_pJetpack; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetFGArm -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the FG Arm as an Attachable. This is for Lua binding mostly. -// Arguments: None. -// Return value: A pointer to the FG Arm Attachable of this. Ownership is NOT transferred! + /// + /// Sets the jetpack for this AHuman. + /// + /// The new jetpack to use. + void SetJetpack(Attachable *newJetpack); - Attachable * GetFGArm() const { return (Attachable *)m_pFGArm; } + /// + /// Gets the foreground Arm of this AHuman. + /// + /// A pointer to the foreground Arm of this AHuman. Ownership is NOT transferred. + Attachable *GetFGArm() const { return static_cast(m_pFGArm); } + /// + /// Sets the foreground Arm for this AHuman. + /// + /// The new Arm to use. + void SetFGArm(Attachable *newArm); -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetBGArm -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the BG Arm as an Attachable. This is for Lua binding mostly. -// Arguments: None. -// Return value: A pointer to the BG Arm Attachable of this. Ownership is NOT transferred! + /// + /// Gets the background arm of this AHuman. + /// + /// A pointer to the background arm of this AHuman. Ownership is NOT transferred. + Attachable *GetBGArm() const { return static_cast(m_pBGArm); } - Attachable * GetBGArm() const { return (Attachable *)m_pBGArm; } + /// + /// Sets the background Arm for this AHuman. + /// + /// The new Arm to use. + void SetBGArm(Attachable *newArm); + /// + /// Gets the foreground Leg of this AHuman. + /// + /// A pointer to the foreground Leg of this AHuman. Ownership is NOT transferred. + Attachable *GetFGLeg() const { return static_cast(m_pFGLeg); } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetFGLeg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the FG Leg as an Attachable. This is for Lua binding mostly. -// Arguments: None. -// Return value: A pointer to the FG Leg Attachable of this. Ownership is NOT transferred! + /// + /// Sets the foreground Leg for this AHuman. + /// + /// The new Leg to use. + void SetFGLeg(Attachable *newLeg); - Attachable * GetFGLeg() const { return (Attachable *)m_pFGLeg; } + /// + /// Gets the background leg of this AHuman. + /// + /// A pointer to the background leg of this AHuman. Ownership is NOT transferred. + Attachable *GetBGLeg() const { return static_cast(m_pBGLeg); } + /// + /// Sets the background Leg for this AHuman. + /// + /// The new Leg to use. + void SetBGLeg(Attachable *newLeg); /// /// Gets the FG foot attachable of this. /// /// A pointer to the FG foot attachable of this. Ownership is NOT transferred! - Attachable * GetFGFoot() const { if (m_pFGLeg) { return m_pFGLeg->GetFoot(); } else { return nullptr; } } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetBGLeg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the BG Leg as an Attachable. This is for Lua binding mostly. -// Arguments: None. -// Return value: A pointer to the BG Leg Attachable of this. Ownership is NOT transferred! - - Attachable * GetBGLeg() const { return (Attachable *)m_pBGLeg; } - + Attachable *GetFGFoot() const { return m_pFGLeg ? m_pFGLeg->GetFoot() : nullptr; } /// /// Gets the BG foot attachable of this. /// /// A pointer to the BG foot attachable of this. Ownership is NOT transferred! - Attachable * GetBGFoot() const { if (m_pBGLeg) { return m_pBGLeg->GetFoot(); } else { return nullptr; } } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetJetpack -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the jetpack as an emitter. This is for Lua binding mostly. -// Arguments: None. -// Return value: A pointer to jetpack emitter. Ownership is NOT transferred! - - AEmitter * GetJetpack() const { return (AEmitter *)m_pJetpack; } + Attachable *GetBGFoot() const { return m_pBGLeg ? m_pBGLeg->GetFoot() : nullptr; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -326,7 +337,7 @@ ClassInfoGetters // Return value: A pointer to the bitmap of with the head of this. Ownership is NOT // transferred! - BITMAP * GetHeadBitmap() const; + BITMAP *GetHeadBitmap() const; ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 6de95b265..b614ed4a2 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1067,14 +1067,14 @@ int LuaMan::Create() value("LANDJUMP", 5 /*AHuman::JumpState::LANDJUMP*/) ] .def(constructor<>()) - .property("Head", &AHuman::GetHead) - .property("FGArm", &AHuman::GetFGArm) - .property("BGArm", &AHuman::GetBGArm) - .property("FGLeg", &AHuman::GetFGLeg) + .property("Head", &AHuman::GetHead, &AHuman::SetHead) + .property("Jetpack", &AHuman::GetJetpack, &AHuman::SetJetpack) + .property("FGArm", &AHuman::GetFGArm, &AHuman::SetFGArm) + .property("BGArm", &AHuman::GetBGArm, &AHuman::SetBGArm) + .property("FGLeg", &AHuman::GetFGLeg, &AHuman::SetFGLeg) + .property("BGLeg", &AHuman::GetBGLeg, &AHuman::SetBGLeg) .property("FGFoot", &AHuman::GetFGFoot) - .property("BGLeg", &AHuman::GetBGLeg) .property("BGFoot", &AHuman::GetBGFoot) - .property("Jetpack", &AHuman::GetJetpack) .property("JetTimeTotal", &AHuman::GetJetTimeTotal, &AHuman::SetJetTimeTotal) .property("JetTimeLeft", &AHuman::GetJetTimeLeft, &AHuman::SetJetTimeLeft) .property("ThrowPrepTime", &AHuman::GetThrowPrepTime, &AHuman::SetThrowPrepTime) @@ -1159,11 +1159,11 @@ int LuaMan::Create() ] .def(constructor<>()) .property("Turret", &ACrab::GetTurret, &ACrab::SetTurret) + .property("Jetpack", &ACrab::GetJetpack, &ACrab::SetJetpack) .property("LFGLeg", &ACrab::GetLeftFGLeg, &ACrab::SetLeftFGLeg) .property("LBGLeg", &ACrab::GetLeftBGLeg, &ACrab::SetLeftBGLeg) .property("RFGLeg", &ACrab::GetRightFGLeg, &ACrab::SetRightFGLeg) .property("RBGLeg", &ACrab::GetRightBGLeg, &ACrab::SetRightBGLeg) - .property("Jetpack", &ACrab::GetJetpack, &ACrab::SetJetpack) .property("JetTimeTotal", &ACrab::GetJetTimeTotal, &ACrab::SetJetTimeTotal) .property("JetTimeLeft", &ACrab::GetJetTimeLeft) .property("EquippedItem", &ACrab::GetEquippedItem) From 63b17a25434e8ba16bf9ed9c406e351ee5f4ec63 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 18 Aug 2020 00:05:59 -0300 Subject: [PATCH 016/144] . Fixed CloneHardcodedAttachable calls in ACDropship, ACRocket, ADoor, ACrab, AHuman so they cast the member function to std::function Moved ACrab::GetTurret back into cpp file cause I'd need to include Turret in the header otherwise. Also cleaned up some comments and included Leg in ACrab.h Included Arm in AHuman --- Entities/ACDropShip.cpp | 12 ++++++------ Entities/ACRocket.cpp | 14 +++++++------- Entities/ACrab.cpp | 19 +++++++++++++------ Entities/ACrab.h | 12 ++++++------ Entities/ADoor.cpp | 2 +- Entities/AHuman.cpp | 12 ++++++------ Entities/AHuman.h | 3 +-- 7 files changed, 40 insertions(+), 34 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 4da8c0cbb..e54dbed6d 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -72,12 +72,12 @@ int ACDropShip::Create() // Description: Creates a ACDropShip to be identical to another, by deep copy. int ACDropShip::Create(const ACDropShip &reference) { - if (reference.m_pRThruster) { CloneHardcodedAttachable(reference.m_pRThruster, ACDropShip::SetRightThruster); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLThruster, ACDropShip::SetLeftThruster); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pURThruster, ACDropShip::SetURightThruster); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pULThruster, ACDropShip::SetULeftThruster); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pRHatch, ACDropShip::SetRightHatch); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLHatch, ACDropShip::SetLeftHatch); } + if (reference.m_pRThruster) { CloneHardcodedAttachable(reference.m_pRThruster, this, static_cast>(&ACDropShip::SetRightThruster)); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLThruster, this, static_cast>(&ACDropShip::SetLeftThruster)); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pURThruster, this, static_cast>(&ACDropShip::SetURightThruster)); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pULThruster, this, static_cast>(&ACDropShip::SetULeftThruster)); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pRHatch, this, static_cast>(&ACDropShip::SetRightHatch)); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLHatch, this, static_cast>(&ACDropShip::SetLeftHatch)); } ACraft::Create(reference); diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 5419a51a7..8cb8777a1 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -92,13 +92,13 @@ int ACRocket::Create() // Description: Creates a ACRocket to be identical to another, by deep copy. int ACRocket::Create(const ACRocket &reference) { - if (reference.m_pRLeg) { CloneHardcodedAttachable(reference.m_pRLeg, ACRocket::SetRightLeg); } - if (reference.m_pLLeg) { CloneHardcodedAttachable(reference.m_pLLeg, ACRocket::SetLeftLeg); } - if (reference.m_pMThruster) { CloneHardcodedAttachable(reference.m_pMThruster, ACRocket::SetMainThruster); } - if (reference.m_pRThruster) { CloneHardcodedAttachable(reference.m_pRThruster, ACRocket::SetRightThruster); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLThruster, ACRocket::SetLeftThruster); } - if (reference.m_pURThruster) { CloneHardcodedAttachable(reference.m_pURThruster, ACRocket::SetURightThruster); } - if (reference.m_pULThruster) { CloneHardcodedAttachable(reference.m_pULThruster, ACRocket::SetULeftThruster); } + if (reference.m_pRLeg) { CloneHardcodedAttachable(reference.m_pRLeg, this, static_cast>(&ACRocket::SetRightLeg)); } + if (reference.m_pLLeg) { CloneHardcodedAttachable(reference.m_pLLeg, this, static_cast>(&ACRocket::SetLeftLeg)); } + if (reference.m_pMThruster) { CloneHardcodedAttachable(reference.m_pMThruster, this, static_cast>(&ACRocket::SetMainThruster)); } + if (reference.m_pRThruster) { CloneHardcodedAttachable(reference.m_pRThruster, this, static_cast>(&ACRocket::SetRightThruster)); } + if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLThruster, this, static_cast>(&ACRocket::SetLeftThruster)); } + if (reference.m_pURThruster) { CloneHardcodedAttachable(reference.m_pURThruster, this, static_cast>(&ACRocket::SetURightThruster)); } + if (reference.m_pULThruster) { CloneHardcodedAttachable(reference.m_pULThruster, this, static_cast>(&ACRocket::SetULeftThruster)); } ACraft::Create(reference); diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index f3bdea1ee..f547436be 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -162,12 +162,15 @@ int ACrab::Create(BITMAP *pSprite, // Description: Creates a ACrab to be identical to another, by deep copy. int ACrab::Create(const ACrab &reference) { - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pTurret, ACrab::SetTurret); } - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pJetpack, ACrab::SetJetpack); } - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pLFGLeg, ACrab::SetLeftFGLeg); } - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pRFGLeg, ACrab::SetRightFGLeg); } - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pLBGLeg, ACrab::SetLeftBGLeg); } - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pRBGLeg, ACrab::SetRightBGLeg); } + //if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pTurret, std::bind(&ACrab::SetTurret, this, dynamic_cast(reference.m_pTurret->Clone()))); } + + + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pTurret, this, static_cast>(&ACrab::SetTurret)); } + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pJetpack, this, static_cast>(&ACrab::SetJetpack)); } + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pLFGLeg, this, static_cast>(&ACrab::SetLeftFGLeg)); } + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pRFGLeg, this, static_cast>(&ACrab::SetRightFGLeg)); } + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pLBGLeg, this, static_cast>(&ACrab::SetLeftBGLeg)); } + if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pRBGLeg, this, static_cast>(&ACrab::SetRightBGLeg)); } Actor::Create(reference); @@ -493,6 +496,10 @@ Vector ACrab::GetEyePos() const return m_Pos; } +Attachable *ACrab::GetTurret() const { + return (m_pTurret && m_pTurret->IsAttached()) ? dynamic_cast(m_pTurret) : nullptr; +} + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACrab::SetTurret(Attachable *newTurret) { diff --git a/Entities/ACrab.h b/Entities/ACrab.h index ce97620b6..fec00053f 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -16,6 +16,7 @@ #include "Actor.h" #include "LimbPath.h" +#include "Leg.h" struct BITMAP; @@ -24,7 +25,6 @@ namespace RTE class Attachable; class Turret; -class Leg; class AEmitter; //class LimbPath; @@ -168,15 +168,15 @@ class ACrab : /// - /// Gets the Turret of this Crab. + /// Gets the Turret of this ACrab. /// - /// A pointer to the Crab's Turret. Ownership is NOT transferred! - Attachable *GetTurret() const { return (m_pTurret && m_pTurret->IsAttached()) ? dynamic_cast(m_pTurret) : nullptr; } + /// A pointer to Turret of this ACrab. Ownership is NOT transferred! + Attachable *GetTurret() const; /// - /// Sets the turret for this Crab. Ownership IS transferred! + /// Sets the Turret for this ACrab. Ownership IS transferred! /// - /// The new turret to use. + /// The new Turret to use. void SetTurret(Attachable *newTurret); /// diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index 721423484..88e260243 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -45,7 +45,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int ADoor::Create(const ADoor &reference) { - if (reference.m_Door) { CloneHardcodedAttachable(reference.m_Door, ADoor::SetDoor); } + if (reference.m_Door) { CloneHardcodedAttachable(reference.m_Door, this, static_cast>(&ADoor::SetDoor)); } //TODO this was setting door parent offset to my closed offset, which is super weird. Test that doors are still cool. Old code was AddAttachable(m_Door, m_ClosedOffset, true); Actor::Create(reference); diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 9ab8637e2..ea5766fbc 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -138,12 +138,12 @@ int AHuman::Create() // Description: Creates a AHuman to be identical to another, by deep copy. int AHuman::Create(const AHuman &reference) { - if (reference.m_pHead) { CloneHardcodedAttachable(reference.m_pHead, AHuman::SetHead); } - if (reference.m_pJetpack) { CloneHardcodedAttachable(reference.m_pJetpack, AHuman::SetJetpack); } - if (reference.m_pFGArm) { CloneHardcodedAttachable(reference.m_pFGArm, AHuman::SetFGArm); } - if (reference.m_pBGArm) { CloneHardcodedAttachable(reference.m_pBGArm, AHuman::SetBGArm); } - if (reference.m_pFGLeg) { CloneHardcodedAttachable(reference.m_pFGLeg, AHuman::SetFGLeg); } - if (reference.m_pBGLeg) { CloneHardcodedAttachable(reference.m_pBGLeg, AHuman::SetBGLeg); } + if (reference.m_pHead) { CloneHardcodedAttachable(reference.m_pHead, this, static_cast>(&AHuman::SetHead)); } + if (reference.m_pJetpack) { CloneHardcodedAttachable(reference.m_pJetpack, this, static_cast>(&AHuman::SetJetpack)); } + if (reference.m_pFGArm) { CloneHardcodedAttachable(reference.m_pFGArm, this, static_cast>(&AHuman::SetFGArm)); } + if (reference.m_pBGArm) { CloneHardcodedAttachable(reference.m_pBGArm, this, static_cast>(&AHuman::SetBGArm)); } + if (reference.m_pFGLeg) { CloneHardcodedAttachable(reference.m_pFGLeg, this, static_cast>(&AHuman::SetFGLeg)); } + if (reference.m_pBGLeg) { CloneHardcodedAttachable(reference.m_pBGLeg, this, static_cast>(&AHuman::SetBGLeg)); } Actor::Create(reference); m_ThrowPrepTime = reference.m_ThrowPrepTime; diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 78b286c9f..f8d92ff9d 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -15,6 +15,7 @@ // Inclusions of header files #include "Actor.h" +#include "Arm.h" #include "Leg.h" #include "LimbPath.h" @@ -24,8 +25,6 @@ namespace RTE { class Attachable; -class Arm; -class Leg; class AEmitter; //class LimbPath; From ed056e041d84f6215fd4b3304ced9c438a856d9c Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 18 Aug 2020 00:11:20 -0300 Subject: [PATCH 017/144] Added safety check to Attachable::OrganizeAtomsInParent and made member variables protected cause it's easier Removed AEmitter Create that does nothing. Cleaned up some improper float definitions in AEmitter Clear, added Flash setter and used it, fixed use of Attach in ReadProperty, removed deletion of Flash in destroy, fixed variable name to match change from attachable Added luabinding to get and set AEmitter flash --- Entities/AEmitter.cpp | 59 +++++++++++++++++------------------------ Entities/AEmitter.h | 11 -------- Entities/Attachable.cpp | 2 +- Entities/Attachable.h | 4 +-- Managers/LuaMan.cpp | 1 + 5 files changed, 28 insertions(+), 49 deletions(-) diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index 6fb0a0576..746f89b10 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -55,25 +55,11 @@ void AEmitter::Clear() m_EmitDamage = 0; m_LastEmitTmr.Reset(); m_pFlash = 0; - m_FlashScale = 1.0f; - m_AvgBurstImpulse = -1.0f; - m_AvgImpulse = -1.0f; + m_FlashScale = 1.0F; + m_AvgBurstImpulse = -1.0F; + m_AvgImpulse = -1.0F; m_FlashOnlyOnBurst = true; - m_LoudnessOnEmit = 1.0f; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes the Emission object ready for use. - -int AEmitter::Create() -{ - if (Attachable::Create() < 0) - return -1; - - return 0; + m_LoudnessOnEmit = 1.0F; } @@ -82,12 +68,13 @@ int AEmitter::Create() ////////////////////////////////////////////////////////////////////////////////////////// // Description: Creates a AEmitter to be identical to another, by deep copy. -int AEmitter::Create(const AEmitter &reference) -{ +int AEmitter::Create(const AEmitter &reference) { + if (reference.m_pFlash) { CloneHardcodedAttachable(reference.m_pFlash, this, static_cast>(&AEmitter::SetFlash)); } Attachable::Create(reference); - for (list::const_iterator itr = reference.m_EmissionList.begin(); itr != reference.m_EmissionList.end(); ++itr) + for (list::const_iterator itr = reference.m_EmissionList.begin(); itr != reference.m_EmissionList.end(); ++itr) { m_EmissionList.push_back(dynamic_cast((*itr)->Clone())); + } m_EmissionSound = reference.m_EmissionSound; m_BurstSound = reference.m_BurstSound; @@ -107,12 +94,6 @@ int AEmitter::Create(const AEmitter &reference) m_EmitAngle = reference.m_EmitAngle; m_EmissionOffset = reference.m_EmissionOffset; m_EmitDamage = reference.m_EmitDamage; - if (reference.m_pFlash) - { - m_pFlash = dynamic_cast(reference.m_pFlash->Clone()); - if (m_pFlash) - m_pFlash->Attach(this); - } m_FlashScale = reference.m_FlashScale; m_FlashOnlyOnBurst = reference.m_FlashOnlyOnBurst; m_LoudnessOnEmit = reference.m_LoudnessOnEmit; @@ -192,11 +173,9 @@ int AEmitter::ReadProperty(std::string propName, Reader &reader) else if (propName == "Flash") { const Entity *pObj = g_PresetMan.GetEntityPreset(reader); - if (pObj) - { + if (pObj) { m_pFlash = dynamic_cast(pObj->Clone()); - if (m_pFlash) - m_pFlash->Attach(this); + AddAttachable(m_pFlash); } } else if (propName == "FlashScale") @@ -299,8 +278,6 @@ void AEmitter::Destroy(bool notInherited) m_EmissionSound.Stop(); // m_BurstSound.Stop(); - delete m_pFlash; - if (!notInherited) Attachable::Destroy(); Clear(); @@ -409,6 +386,18 @@ void AEmitter::GibThis(Vector impactImpulse, float internalBlast, MovableObject } */ +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void AEmitter::SetFlash(Attachable *newFlash) { + if (newFlash) { + RemoveAttachable(m_pFlash); + m_pFlash = newFlash; + AddAttachable(newFlash); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Update ////////////////////////////////////////////////////////////////////////////////////////// @@ -563,8 +552,8 @@ void AEmitter::Update() m_LastEmitTmr.Reset(); // Apply recoil/push effects, scaled by the joint stiffness - if (m_pParent && !m_OnlyLinForces) - m_pParent->AddAbsImpulseForce(pushImpulses * m_JointStiffness, m_Pos + m_JointOffset); + if (m_Parent && !m_OnlyLinearForces) + m_Parent->AddAbsImpulseForce(pushImpulses * m_JointStiffness, m_Pos + m_JointOffset); else m_ImpulseForces.push_back(make_pair(pushImpulses * m_JointStiffness, Vector())); diff --git a/Entities/AEmitter.h b/Entities/AEmitter.h index 629c16bb5..36883b1e2 100644 --- a/Entities/AEmitter.h +++ b/Entities/AEmitter.h @@ -65,17 +65,6 @@ ClassInfoGetters ~AEmitter() override { Destroy(true); } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes the AEmitter object ready for use. -// Arguments: None. -// Return value: An error return value signaling sucess or any particular failure. -// Anything below 0 is an error signal. - - int Create() override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: Create ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 078021c1d..645752965 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -316,7 +316,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Attachable::OrganizeAtomsInParent(bool addToParent) { - if (IsAttached()) { + if (IsAttached() && m_Parent->GetAtomGroup()) { if (addToParent) { m_Parent->GetAtomGroup()->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), GetParentOffset() - GetJointOffset()); } else { diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 751cbbb11..fafb43119 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -322,8 +322,6 @@ namespace RTE { /// A pointer to the MOSRotating to set as the new parent. Ownership is NOT transferred! virtual void SetParent(MOSRotating *newParent); - private: - static Entity::ClassInfo m_sClass; //!< ClassInfo for this class. MOSRotating *m_Parent; //!< Pointer to the MOSRotating this attachable is attached to. @@ -348,6 +346,8 @@ namespace RTE { long int m_AtomSubgroupID; //!< The Atom IDs this' atoms will have when attached and added to a parent's AtomGroup. bool m_CollidesWithTerrainWhileAttached; //!< Whether this attachable currently has terrain collisions enabled while it's attached to a parent. + private: + /// /// Turns on/off this Attachable's terrain collisions while it is attached by adding/removing its atoms to/from its parent AtomGroup. /// diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index b614ed4a2..328e561ff 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -850,6 +850,7 @@ int LuaMan::Create() .property("EmitterDamageMultiplier", &AEmitter::GetEmitterDamageMultiplier, &AEmitter::SetEmitterDamageMultiplier) .property("EmitCountLimit", &AEmitter::GetEmitCountLimit, &AEmitter::SetEmitCountLimit) .property("EmitDamage", &AEmitter::GetEmitDamage, &AEmitter::SetEmitDamage) + .property("Flash", &AEmitter::GetFlash, &AEmitter::SetFlash) .property("FlashScale", &AEmitter::GetFlashScale, &AEmitter::SetFlashScale) .def("GetEmitVector", &AEmitter::GetEmitVector) .def("GetRecoilVector", &AEmitter::GetRecoilVector) From 23e350a5da800c4b8287e4c984c5445da691a6df Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 18 Aug 2020 00:18:16 -0300 Subject: [PATCH 018/144] Forgot to stage the header last commit Added and used HDFirearm Magazine and Flash setters, changed Flash Attach to AddAttachable and did AddAttachable for magazine in ReadProperty Got rid of Flash and Magazine deletion in Destroy, since they're handled by MOSR destroy Cleaned up variable names and changed Detach and Attach to RemoveAttachable and AddAttachable in SetNextMagazineName and Update --- Entities/AEmitter.h | 12 ++++++++ Entities/HDFirearm.cpp | 64 ++++++++++++++++++++++-------------------- Entities/HDFirearm.h | 29 ++++++++++++++----- 3 files changed, 68 insertions(+), 37 deletions(-) diff --git a/Entities/AEmitter.h b/Entities/AEmitter.h index 36883b1e2..88f03d9d7 100644 --- a/Entities/AEmitter.h +++ b/Entities/AEmitter.h @@ -305,6 +305,18 @@ ClassInfoGetters void SetBurstSpacing(const float spacing) { m_BurstSpacing = spacing; } + /// + /// Gets the flash of this AEmitter. + /// + /// A pointer to the AEmitter's flash. Ownership is NOT transferred! + Attachable *GetFlash() const { return m_pFlash; } + + /// + /// Sets the flash for this AEmitter. Ownership IS transferred! + /// + /// The new flash to use. + void SetFlash(Attachable *newFlash); + ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetFlashScale ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index 68a8c92f5..8264acf40 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -95,22 +95,12 @@ int HDFirearm::Create() ////////////////////////////////////////////////////////////////////////////////////////// // Description: Creates a HDFirearm to be identical to another, by deep copy. -int HDFirearm::Create(const HDFirearm &reference) -{ +int HDFirearm::Create(const HDFirearm &reference) { + if (reference.m_pMagazine) { CloneHardcodedAttachable(reference.m_pMagazine, this, static_cast>(&HDFirearm::SetMagazine)); } + if (reference.m_pFlash) { CloneHardcodedAttachable(reference.m_pFlash, this, static_cast>(&HDFirearm::SetFlash)); } HeldDevice::Create(reference); m_pMagazineReference = reference.m_pMagazineReference; - - if (reference.m_pMagazine) - { - m_pMagazine = dynamic_cast(reference.m_pMagazine->Clone()); - AddAttachable(m_pMagazine, m_pMagazine->GetParentOffset(), true); - } - if (reference.m_pFlash) - { - m_pFlash = dynamic_cast(reference.m_pFlash->Clone()); - m_pFlash->Attach(this, m_pFlash->GetParentOffset()); - } m_FireSound = reference.m_FireSound; m_ActiveSound = reference.m_ActiveSound; m_DeactivationSound = reference.m_DeactivationSound; @@ -161,6 +151,7 @@ int HDFirearm::ReadProperty(std::string propName, Reader &reader) delete m_pMagazine; m_pMagazine = dynamic_cast(m_pMagazineReference->Clone()); + if (m_pMagazine) { AddAttachable(m_pMagazine); } } } else if (propName == "Flash") @@ -169,8 +160,7 @@ int HDFirearm::ReadProperty(std::string propName, Reader &reader) if (pObj) { m_pFlash = dynamic_cast(pObj->Clone()); - if (m_pFlash) - m_pFlash->Attach(this); + if (m_pFlash) { AddAttachable(m_pFlash); } } } else if (propName == "FireSound") @@ -310,8 +300,6 @@ int HDFirearm::Save(Writer &writer) const void HDFirearm::Destroy(bool notInherited) { - delete m_pMagazine; - delete m_pFlash; m_FireSound.Stop(); m_ActiveSound.Stop(); m_DeactivationSound.Stop(); @@ -333,12 +321,28 @@ float HDFirearm::GetMass() const return m_pMagazine ? m_Mass + m_pMagazine->GetMass() : m_Mass; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetNextMagazineName -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the Preset name of the next Magazine that will be loaded into -// this gun. This changes all future mags that will be reloaded. +void HDFirearm::SetMagazine(Attachable *newMagazine) { + Magazine *castedNewMagazine= dynamic_cast(newMagazine); + if (castedNewMagazine) { + RemoveAttachable(m_pMagazine); + m_pMagazine = castedNewMagazine; + AddAttachable(castedNewMagazine); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void HDFirearm::SetFlash(Attachable *newFlash) { + if (newFlash) { + RemoveAttachable(m_pFlash); + m_pFlash = newFlash; + AddAttachable(newFlash); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool HDFirearm::SetNextMagazineName(string magName) { @@ -618,7 +622,7 @@ void HDFirearm::Reload() { m_pMagazine->SetVel(m_Vel + Vector(m_HFlipped ? -3 : 3, 0.3)); m_pMagazine->SetAngularVel(6 + (-6 * PosRand())); - m_pMagazine->Detach(); + RemoveAttachable(m_pMagazine); // Whether the magazine is ok to release into scene if (m_pMagazine->IsDiscardable()) g_MovableMan.AddParticle(m_pMagazine); @@ -761,9 +765,9 @@ void HDFirearm::Update() int player = -1; Controller * pController = 0; - if (m_pParent) + if (m_Parent) { - Actor * pActor = dynamic_cast(m_pParent); + Actor * pActor = dynamic_cast(m_Parent); if (pActor) { pController = pActor->GetController(); @@ -815,7 +819,7 @@ void HDFirearm::Update() Attachable *pAttachable = dynamic_cast(pParticle); if (pAttachable) { - pAttachable->Detach(); + dynamic_cast(pAttachable->GetParent())->RemoveAttachable(pAttachable); // Activate if it is some kind of grenade or whatnot. ThrownDevice *pTD = dynamic_cast(pAttachable); if (pTD) @@ -920,7 +924,7 @@ void HDFirearm::Update() m_pMagazine = dynamic_cast(m_pMagazineReference->Clone()); if (m_pMagazine) { - m_pMagazine->Attach(this); + AddAttachable(m_pMagazine); m_ReloadEndSound.Play(m_Pos); m_ActivationTimer.Reset(); @@ -963,8 +967,8 @@ void HDFirearm::Update() } // TODO: This is broken, revise") - if (m_pParent) - m_pParent->SetRecoil(m_RecoilForce, m_RecoilOffset, m_Recoiled); + if (m_Parent) + m_Parent->SetRecoil(m_RecoilForce, m_RecoilOffset, m_Recoiled); else m_ImpulseForces.push_back(make_pair(m_RecoilForce, m_RecoilOffset)); @@ -1157,7 +1161,7 @@ void HDFirearm::DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos, int whic HeldDevice::DrawHUD(pTargetBitmap, targetPos, whichScreen); // Don't bother if the aim distance is really short, or not held - if (!m_pParent || m_SharpAim < 0.15) + if (!m_Parent || m_SharpAim < 0.15) return; float sharpLength = m_MaxSharpLength * m_SharpAim; diff --git a/Entities/HDFirearm.h b/Entities/HDFirearm.h index e92041bfd..d9db583d0 100644 --- a/Entities/HDFirearm.h +++ b/Entities/HDFirearm.h @@ -142,14 +142,29 @@ ClassInfoGetters void SetRateOfFire(int newRate) { m_RateOfFire = newRate; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetMagazine -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the currently attached Magazine, if any. -// Arguments: None. -// Return value: The Magazine, if any is attached. + /// + /// Gets the Magazine of this HDFirearm. + /// + /// A pointer to Magazine of this HDFirearm. Ownership is NOT transferred! + Magazine *GetMagazine() const { return m_pMagazine; } - Magazine * GetMagazine() const { return m_pMagazine; } + /// + /// Sets the Magazine for this HDFirearm. Ownership IS transferred! + /// + /// The new Magazine to use. + void SetMagazine(Attachable *newMagazine); + + /// + /// Gets the flash of this HDFirearm. + /// + /// A pointer to flash of this HDFirearm. Ownership is NOT transferred! + Attachable *GetFlash() const { return m_pFlash; } + + /// + /// Sets the flash for this HDFirearm. Ownership IS transferred! + /// + /// The new flash to use. + void SetFlash(Attachable *newFlash); ////////////////////////////////////////////////////////////////////////////////////////// From 16c5c5031ba82e86731ae3577400a6664dfb3ada Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 18 Aug 2020 00:21:33 -0300 Subject: [PATCH 019/144] Added lua setter binding for HDFirearm magazine that I'd forgotten to commit. We may not actually want this though, we'll see Cleaned up HeldDevice variable names and such --- Entities/HeldDevice.cpp | 8 ++++---- Managers/LuaMan.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index f40a8018f..4a81d5ac8 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -57,7 +57,7 @@ void HeldDevice::Clear() int HeldDevice::Create() { - if (Attachable::Create() < 0) + if (MOSRotating::Create() < 0) return -1; // Set MO Type. @@ -371,7 +371,7 @@ void HeldDevice::Update() Attachable::Update(); // Remove loose items that have completely disappeared into the terrain, unless they're pinned - if (!m_pParent && m_PinStrength <= 0 && m_RestTimer.IsPastSimMS(20000) && m_CanBeSquished && m_pAtomGroup->RatioInTerrain() > 0.9) + if (!m_Parent && m_PinStrength <= 0 && m_RestTimer.IsPastSimMS(20000) && m_CanBeSquished && m_pAtomGroup->RatioInTerrain() > 0.9) GibThis(); if (m_Activated) @@ -389,7 +389,7 @@ void HeldDevice::Update() } } - if (!m_pParent) { + if (!m_Parent) { } else { @@ -457,7 +457,7 @@ void HeldDevice::DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos, int whi Attachable::DrawHUD(pTargetBitmap, targetPos, whichScreen); - if (!m_pParent) + if (!m_Parent) { // Only draw if the team viewing this has seen the space where this is located int viewingTeam = g_ActivityMan.GetActivity()->GetTeamOfPlayer(g_ActivityMan.GetActivity()->PlayerOfScreen(whichScreen)); diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 328e561ff..ba6475d80 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1299,7 +1299,7 @@ int LuaMan::Create() .property("RateOfFire", &HDFirearm::GetRateOfFire, &HDFirearm::SetRateOfFire) .property("FullAuto", &HDFirearm::IsFullAuto, &HDFirearm::SetFullAuto) .property("RoundInMagCount", &HDFirearm::GetRoundInMagCount) - .property("Magazine", &HDFirearm::GetMagazine) + .property("Magazine", &HDFirearm::GetMagazine, &HDFirearm::SetMagazine) .property("ActivationDelay", &HDFirearm::GetActivationDelay, &HDFirearm::SetActivationDelay) .property("DeactivationDelay", &HDFirearm::GetDeactivationDelay, &HDFirearm::SetDeactivationDelay) .property("ReloadTime", &HDFirearm::GetReloadTime, &HDFirearm::SetReloadTime) From 6a918a58e6beeb5f019e13fbd9f34a537fd30f30 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 18 Aug 2020 00:24:26 -0300 Subject: [PATCH 020/144] Added and used Setter for Arm heldMO. There was already one, but it took an MO and needs to be refactored sometime, this one just wraps it Changed various uses of Attach and Detach to AddAttachable and RemoveAttachable in Arm. Cleaned up variable names and deletion of attachable in Destroy --- Entities/Arm.cpp | 43 ++++++++++++++++--------------------------- Entities/Arm.h | 7 +++++++ 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index ea9ed6ae2..7c7d83160 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -62,17 +62,10 @@ int Arm::Create() ////////////////////////////////////////////////////////////////////////////////////////// // Description: Creates a Arm to be identical to another, by deep copy. -int Arm::Create(const Arm &reference) -{ +int Arm::Create(const Arm &reference) { + if (reference.m_pHeldMO) { CloneHardcodedAttachable(dynamic_cast(reference.m_pHeldMO), this, static_cast>((void (Arm:: *)(Attachable *newHeldMO)) &Arm::SetHeldMO)); } Attachable::Create(reference); - if (reference.m_pHeldMO) { - m_pHeldMO = dynamic_cast(reference.m_pHeldMO->Clone()); - if (m_pHeldMO->IsDevice()) - dynamic_cast(m_pHeldMO)->Attach(this, - dynamic_cast(m_pHeldMO)->GetParentOffset()); - } - m_HandFile = reference.m_HandFile; m_pHand = m_HandFile.GetAsBitmap(); RTEAssert(m_pHand, "Failed to load hand bitmap in Arm::Create") @@ -104,8 +97,7 @@ int Arm::ReadProperty(std::string propName, Reader &reader) if (pEntity) { m_pHeldMO = dynamic_cast(pEntity->Clone()); - if (m_pHeldMO->IsDevice()) - dynamic_cast(m_pHeldMO)->Attach(this, dynamic_cast(m_pHeldMO)->GetParentOffset()); + if (m_pHeldMO->IsDevice()) { AddAttachable(dynamic_cast(m_pHeldMO)); } } pEntity = 0; } @@ -230,7 +222,7 @@ void Arm::SetHeldMO(MovableObject *newHeldMO) // TODO: NEED TO REWORK THIS TO WORK WITH THROWNDEVICES!! if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && dynamic_cast(m_pHeldMO)->IsAttachedTo(this)) { HeldDevice *pHeldDev = dynamic_cast(m_pHeldMO); - pHeldDev->Detach(); + if (pHeldDev->IsAttached()) { dynamic_cast(pHeldDev->GetParent())->RemoveAttachable(pHeldDev); } // TODO: Refine throwing force to dropped device here?") pHeldDev->SetVel(Vector(10 * PosRand(), -15 * PosRand())); pHeldDev->SetAngularVel(-10 * PosRand()); @@ -240,9 +232,9 @@ void Arm::SetHeldMO(MovableObject *newHeldMO) if (newHeldMO && (newHeldMO->IsHeldDevice() || newHeldMO->IsThrownDevice())) { Attachable *pNewDev = dynamic_cast(newHeldMO); - pNewDev->Detach(); + if (pNewDev->IsAttached()) { dynamic_cast(pNewDev->GetParent())->RemoveAttachable(pNewDev); } g_MovableMan.RemoveMO(pNewDev); - pNewDev->Attach(this, pNewDev->GetParentOffset()); + AddAttachable(pNewDev); pNewDev->SetTeam(m_Team); pNewDev = 0; } @@ -271,7 +263,7 @@ MovableObject * Arm::ReleaseHeldMO() { // Once detached may have incorrect ID value. Detach will take care m_RootID. New ID will be assigned on next frame. m_pHeldMO->SetID(g_NoMOID); - dynamic_cast(m_pHeldMO)->Detach(); + RemoveAttachable(dynamic_cast(m_pHeldMO)); } } m_pHeldMO = 0; @@ -291,7 +283,7 @@ MovableObject * Arm::DropEverything() MovableObject *pReturnMO = m_pHeldMO; if (m_pHeldMO && m_pHeldMO->IsDevice()) { - dynamic_cast(m_pHeldMO)->Detach(); + RemoveAttachable(dynamic_cast(m_pHeldMO)); g_MovableMan.AddItem(m_pHeldMO); } else if (m_pHeldMO) @@ -312,13 +304,11 @@ MovableObject * Arm::DropEverything() MovableObject * Arm::SwapHeldMO(MovableObject *newMO) { MovableObject *oldMO = m_pHeldMO; - if (oldMO && oldMO->IsDevice()) - dynamic_cast(oldMO)->Detach(); + if (m_pHeldMO && m_pHeldMO->IsDevice()) { RemoveAttachable(dynamic_cast(m_pHeldMO)); } m_pHeldMO = newMO; if (newMO && newMO->IsDevice()) { - dynamic_cast(newMO)->Attach(this, - dynamic_cast(newMO)->GetParentOffset()); + AddAttachable(dynamic_cast(newMO)); } return oldMO; @@ -424,13 +414,12 @@ void Arm::Update() // Update basic metrics from parent. Attachable::Update(); - if (!m_pParent) { + if (!m_Parent) { // When arm is detached, let go of whatever it is holding if (m_pHeldMO) { m_pHeldMO->SetVel(m_Vel + Vector(-10 * PosRand(), -15 * PosRand())); m_pHeldMO->SetAngularVel(-7); - if (m_pHeldMO->IsDevice()) - dynamic_cast(m_pHeldMO)->Detach(); + if (m_pHeldMO->IsDevice()) { RemoveAttachable(dynamic_cast(m_pHeldMO)); } g_MovableMan.AddItem(m_pHeldMO); m_pHeldMO = 0; } @@ -482,7 +471,7 @@ void Arm::Update() pHeldDev->SetRotAngle(m_Rotation.GetRadAngle()); pHeldDev->Update(); if (pHeldDev->IsRecoiled()) - m_pParent->AddImpulseForce(pHeldDev->GetRecoilForce()); + m_Parent->AddImpulseForce(pHeldDev->GetRecoilForce()); else m_Recoiled = false; @@ -492,7 +481,7 @@ void Arm::Update() if (!m_JointPos.IsZero()) m_Pos = m_JointPos - RotateOffset(m_JointOffset); else - m_Pos = m_pParent->GetPos() - RotateOffset(m_JointOffset); + m_Pos = m_Parent->GetPos() - RotateOffset(m_JointOffset); // Apply forces and detach if necessary // OBSERVE the memeber pointer is what gets set to 0!$@#$@ @@ -539,7 +528,7 @@ void Arm::Update() if (!m_JointPos.IsZero()) m_Pos = m_JointPos - RotateOffset(m_JointOffset); else - m_Pos = m_pParent->GetPos() - RotateOffset(m_JointOffset); + m_Pos = m_Parent->GetPos() - RotateOffset(m_JointOffset); // If holding something other than a FireArm, then update it if (m_pHeldMO) @@ -629,7 +618,7 @@ void Arm::Draw(BITMAP *pTargetBitmap, if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && m_pHeldMO->IsDrawnAfterParent()) m_pHeldMO->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (!onlyPhysical && mode == g_DrawColor && (m_pHeldMO || !m_pParent)) + if (!onlyPhysical && mode == g_DrawColor && (m_pHeldMO || !m_Parent)) DrawHand(pTargetBitmap, targetPos, mode); if (m_pHeldMO && ((!m_pHeldMO->IsHeldDevice() && !m_pHeldMO->IsThrownDevice()) || m_pHeldMO->IsDrawnAfterParent())) diff --git a/Entities/Arm.h b/Entities/Arm.h index b2a1e4542..64c5c091e 100644 --- a/Entities/Arm.h +++ b/Entities/Arm.h @@ -196,6 +196,13 @@ ClassInfoGetters void SetID(const MOID newID) override; + /// + /// Replaces the MovableObject currently held by this arm with a new one. Ownership IS transferred. + /// The currently held MovableObject (if there is one) will be dropped and become a detached MovableObject. + /// This is primarily used to support clone Create. At some point this should be refactored so Arm can only hold HeldDevices or Attachables anyway. + /// + /// A pointer to the new MovableObject to hold. Ownership IS transferred. + void SetHeldMO(Attachable *newHeldMO) { SetHeldMO(dynamic_cast(newHeldMO)); } ////////////////////////////////////////////////////////////////////////////////////////// // Method: SetHeldMO From a01bebd560fa7a3252debfca61215d7e84f36ba0 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 18 Aug 2020 00:28:04 -0300 Subject: [PATCH 021/144] Added setter in leg for foot and used it Cleaned up leg Create, variable names, foot deletion, added as attachable during read property Forgot to save removing heldMO deletion in Arm before committing before Added lua foot setter property binding --- Entities/Arm.cpp | 1 - Entities/Leg.cpp | 25 ++++++++++++++++--------- Entities/Leg.h | 10 ++++++++-- Managers/LuaMan.cpp | 2 +- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 7c7d83160..a3764c6b5 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -157,7 +157,6 @@ void Arm::Destroy(bool notInherited) { // g_MovableMan.RemoveEntityPreset(this); - delete m_pHeldMO; // Not owned by this // destroy_bitmap(m_pHand); diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index dae6aa2bb..a96a5ccff 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -50,7 +50,7 @@ void Leg::Clear() int Leg::Create() { - if (Attachable::Create() < 0) + if (MOSRotating::Create() < 0) return -1; // Make sure the contracted offset is the one closer to the joint @@ -73,14 +73,10 @@ int Leg::Create() ////////////////////////////////////////////////////////////////////////////////////////// // Description: Creates a Leg to be identical to another, by deep copy. -int Leg::Create(const Leg &reference) -{ +int Leg::Create(const Leg &reference) { + if (reference.m_pFoot) { CloneHardcodedAttachable(reference.m_pFoot, this, static_cast>(&Leg::SetFoot)); } Attachable::Create(reference); - if (reference.m_pFoot) { - m_pFoot = dynamic_cast(reference.m_pFoot->Clone()); - AddAttachable(m_pFoot, true); - } m_ContractedOffset = reference.m_ContractedOffset; m_ExtendedOffset = reference.m_ExtendedOffset; m_MinExtension = reference.m_MinExtension; @@ -112,6 +108,7 @@ int Leg::ReadProperty(std::string propName, Reader &reader) if (pObj) { m_pFoot = dynamic_cast(pObj->Clone()); + AddAttachable(m_pFoot); } } else if (propName == "ContractedOffset") @@ -182,7 +179,6 @@ int Leg::Save(Writer &writer) const void Leg::Destroy(bool notInherited) { - delete m_pFoot; if (!notInherited) Attachable::Destroy(); Clear(); @@ -288,7 +284,7 @@ void Leg::Update() // Update basic metrics from parent. Attachable::Update(); - if (!m_pParent) + if (!m_Parent) { if (m_pFoot) { @@ -413,6 +409,17 @@ void Leg::GetMOIDs(std::vector &MOIDs) const Attachable::GetMOIDs(MOIDs); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Leg::SetFoot(Attachable *newFoot) { + if (newFoot) { + RemoveAttachable(m_pFoot); + m_pFoot = newFoot; + AddAttachable(newFoot); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw diff --git a/Entities/Leg.h b/Entities/Leg.h index 30dc02ce2..b88d4d3ab 100644 --- a/Entities/Leg.h +++ b/Entities/Leg.h @@ -244,11 +244,17 @@ ClassInfoGetters /// - /// Gets the foot Attachable of this. + /// Gets the foot of this Leg. /// - /// A pointer to the foot Attachable of this. Ownership is NOT transferred! + /// A pointer to foot of this Leg. Ownership is NOT transferred! Attachable * GetFoot() const { return m_pFoot; } + /// + /// Sets the foot for this Leg. Ownership IS transferred! + /// + /// The new foot to use. + void SetFoot(Attachable *newFoot); + ////////////////////////////////////////////////////////////////////////////////////////// // Protected member variable and method declarations diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index ba6475d80..f6293516c 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -998,7 +998,7 @@ int LuaMan::Create() .property("HandPos", &Arm::GetHandPos, &Arm::SetHandPos), ABSTRACTLUABINDING(Leg, Attachable) - .property("Foot", &Leg::GetFoot), + .property("Foot", &Leg::GetFoot, &Leg::SetFoot), CONCRETELUABINDING(AHuman, Actor) // These are all private/protected so they can't be bound, need to consider making them public. From 3ec4d50f71a13338cb3b8d2c432ce0ad16659ee0 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 18 Aug 2020 00:41:48 -0300 Subject: [PATCH 022/144] Cleaned up Magazine Create, fixed MOSR CloneHardcodedAttachable template function Fixed lua bindings for mosr wound to use const, matching method definitions --- Entities/MOSRotating.h | 5 +++-- Entities/Magazine.cpp | 2 +- Managers/LuaMan.cpp | 16 ++++++++-------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 2f1ee1285..8ee5393bd 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -788,10 +788,11 @@ ClassInfoGetters /// Also adds the reference attachable's UniqueID to the std::unordered_set of already copied attachable unique IDs so it doesn't get duplicated. /// /// The relevant hardcoded attachable belonging to the reference object being cloned. + /// A pointer to the object which the setter should be run on. Normally would be this, sent from the child class so types work properly. /// A std::function containing the setter for the given hardcoded attachable. Aside from setting the relevant member variable, this setter should call AddAttachable. - template void CloneHardcodedAttachable(Attachable *referenceAttachable, T hardcodedAttachableSetter) { + template void CloneHardcodedAttachable(Attachable *referenceAttachable, T objectToRunSetterOn, U hardcodedAttachableSetter) { m_AlreadyCopiedAttachableUniqueIDs.insert(referenceAttachable->GetUniqueID()); - hardcodedAttachableSetter(*this, dynamic_cast(referenceAttachable->Clone())); + hardcodedAttachableSetter(*objectToRunSetterOn, dynamic_cast(referenceAttachable->Clone())); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Magazine.cpp b/Entities/Magazine.cpp index 00a0d24bf..23f4233f9 100644 --- a/Entities/Magazine.cpp +++ b/Entities/Magazine.cpp @@ -48,7 +48,7 @@ void Magazine::Clear() int Magazine::Create() { - if (Attachable::Create() < 0) + if (MOSRotating::Create() < 0) return -1; // Read projectile properties for AI aim caluculations diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index f6293516c..771e5fe5e 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -759,10 +759,10 @@ int LuaMan::Create() .property("RecoilForce", &MOSRotating::GetRecoilForce) .property("RecoilOffset", &MOSRotating::GetRecoilOffset) .property("TravelImpulse", &MOSRotating::GetTravelImpulse, &MOSRotating::SetTravelImpulse) - .property("GibWoundLimit", &MOSRotating::GetGibWoundLimit, &MOSRotating::SetGibWoundLimit) + .property("GibWoundLimit", (int (MOSRotating:: *)() const) &MOSRotating::GetGibWoundLimit, &MOSRotating::SetGibWoundLimit) .property("GibImpulseLimit", &MOSRotating::GetGibImpulseLimit, &MOSRotating::SetGibImpulseLimit) .property("DamageMultiplier", &MOSRotating::GetDamageMultiplier, &MOSRotating::SetDamageMultiplier) - .property("WoundCount", &MOSRotating::GetWoundCount) + .property("WoundCount", (int (MOSRotating:: *)() const) &MOSRotating::GetWoundCount) .def("AddRecoil", &MOSRotating::AddRecoil) .def("SetRecoil", &MOSRotating::SetRecoil) .def("IsRecoiled", &MOSRotating::IsRecoiled) @@ -774,13 +774,13 @@ int LuaMan::Create() .def("MoveOutOfTerrain", &MOSRotating::MoveOutOfTerrain) .def("ApplyForces", &MOSRotating::ApplyForces) .def("ApplyImpulses", &MOSRotating::ApplyImpulses) - .def("GetGibWoundLimit", (int (MOSRotating:: *)()) &MOSRotating::GetGibWoundLimit) - .def("GetGibWoundLimit", (int (MOSRotating:: *)(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables)) &MOSRotating::GetGibWoundLimit) - .def("GetWoundCount", (int (MOSRotating:: *)()) &MOSRotating::GetWoundCount) - .def("GetWoundCount", (int (MOSRotating:: *)(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables)) &MOSRotating::GetWoundCount) + .def("GetGibWoundLimit", (int (MOSRotating:: *)() const) &MOSRotating::GetGibWoundLimit) + .def("GetGibWoundLimit", (int (MOSRotating:: *)(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const) &MOSRotating::GetGibWoundLimit) + .def("GetWoundCount", (int (MOSRotating:: *)() const) &MOSRotating::GetWoundCount) + .def("GetWoundCount", (int (MOSRotating:: *)(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const) &MOSRotating::GetWoundCount) .def("AddWound", &MOSRotating::AddWound, adopt(_2)) - .def("RemoveWounds", (int (MOSRotating:: *)(int numberOfWoundsToRemove)) &MOSRotating::RemoveWounds) - .def("RemoveWounds", (int (MOSRotating:: *)(int numberOfWoundsToRemove, bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables)) &MOSRotating::RemoveWounds) + .def("RemoveWounds", (float (MOSRotating:: *)(int numberOfWoundsToRemove)) &MOSRotating::RemoveWounds) + .def("RemoveWounds", (float (MOSRotating:: *)(int numberOfWoundsToRemove, bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables)) &MOSRotating::RemoveWounds) .def("IsOnScenePoint", &MOSRotating::IsOnScenePoint) .def("EraseFromTerrain", &MOSRotating::EraseFromTerrain) .def("GetStringValue", &MOSRotating::GetStringValue) From ace863200d79ce5b759030730d0acfc783f9fb4b Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 18 Aug 2020 00:47:34 -0300 Subject: [PATCH 023/144] Cleaned up variable names, use of attach and detach, deletion of attachables during destroy in Turret Added setter for mounted MO and used it Added luabinding for turret getter and setter --- Entities/Turret.cpp | 43 +++++++++++++------------------------------ Entities/Turret.h | 7 +++++++ Managers/LuaMan.cpp | 3 ++- 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index d627b8cd5..2f8c63aa7 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -52,17 +52,10 @@ int Turret::Create() ////////////////////////////////////////////////////////////////////////////////////////// // Description: Creates a Turret to be identical to another, by deep copy. -int Turret::Create(const Turret &reference) -{ +int Turret::Create(const Turret &reference) { + if (reference.m_pMountedMO && reference.m_pMountedMO->IsDevice()) { CloneHardcodedAttachable(dynamic_cast(reference.m_pMountedMO), this, static_cast>((void (Turret:: *)(Attachable * newMountedMO)) & Turret::SetMountedMO)); } Attachable::Create(reference); - if (reference.m_pMountedMO) { - m_pMountedMO = dynamic_cast(reference.m_pMountedMO->Clone()); - if (m_pMountedMO->IsDevice()) - dynamic_cast(m_pMountedMO)->Attach(this, - dynamic_cast(m_pMountedMO)->GetParentOffset()); - } - m_MountedRotOffset = reference.m_MountedRotOffset; return 0; @@ -79,14 +72,11 @@ int Turret::Create(const Turret &reference) int Turret::ReadProperty(std::string propName, Reader &reader) { - if (propName == "MountedMO") - { + if (propName == "MountedMO") { const Entity *pEntity = g_PresetMan.GetEntityPreset(reader); - if (pEntity) - { + if (pEntity) { m_pMountedMO = dynamic_cast(pEntity->Clone()); - if (m_pMountedMO->IsDevice()) - dynamic_cast(m_pMountedMO)->Attach(this, dynamic_cast(m_pMountedMO)->GetParentOffset()); + if (m_pMountedMO->IsDevice()) { AddAttachable(dynamic_cast(m_pMountedMO)); } } pEntity = 0; } @@ -123,8 +113,6 @@ void Turret::Destroy(bool notInherited) { // g_MovableMan.RemoveEntityPreset(this); - delete m_pMountedMO; - if (!notInherited) Attachable::Destroy(); Clear(); @@ -185,7 +173,7 @@ void Turret::SetMountedMO(MovableObject *newHeldMO) { if (m_pMountedMO && m_pMountedMO->IsHeldDevice() && dynamic_cast(m_pMountedMO)->IsAttachedTo(this)) { HeldDevice *pHeldDev = dynamic_cast(m_pMountedMO); - pHeldDev->Detach(); + RemoveAttachable(pHeldDev); // TODO: Refine throwing force to dropped device here?") pHeldDev->SetVel(Vector(10 * PosRand(), -15 * PosRand())); pHeldDev->SetAngularVel(-10 * PosRand()); @@ -195,9 +183,9 @@ void Turret::SetMountedMO(MovableObject *newHeldMO) if (newHeldMO && newHeldMO->IsHeldDevice()) { HeldDevice *pNewDev = dynamic_cast(newHeldMO); - pNewDev->Detach(); + dynamic_cast(pNewDev->GetParent())->RemoveAttachable(pNewDev); g_MovableMan.RemoveMO(pNewDev); - pNewDev->Attach(this, pNewDev->GetParentOffset()); + AddAttachable(pNewDev); pNewDev = 0; } m_pMountedMO = newHeldMO; @@ -216,8 +204,7 @@ void Turret::SetMountedMO(MovableObject *newHeldMO) MovableObject * Turret::ReleaseMountedMO() { MovableObject *pReturnMO = m_pMountedMO; - if (m_pMountedMO && m_pMountedMO->IsDevice()) - dynamic_cast(m_pMountedMO)->Detach(); + if (m_pMountedMO && m_pMountedMO->IsDevice()) { RemoveAttachable(dynamic_cast(m_pMountedMO)); } m_pMountedMO = 0; return pReturnMO; } @@ -235,7 +222,7 @@ MovableObject * Turret::DropEverything() MovableObject *pReturnMO = m_pMountedMO; if (m_pMountedMO && m_pMountedMO->IsDevice()) { - dynamic_cast(m_pMountedMO)->Detach(); + RemoveAttachable(dynamic_cast(m_pMountedMO)); g_MovableMan.AddItem(m_pMountedMO); } else if (m_pMountedMO) @@ -256,14 +243,10 @@ MovableObject * Turret::DropEverything() MovableObject * Turret::SwapMountedMO(MovableObject *newMO) { MovableObject *oldMO = m_pMountedMO; - if (oldMO && oldMO->IsDevice()) - dynamic_cast(oldMO)->Detach(); + if (m_pMountedMO && m_pMountedMO->IsDevice()) { RemoveAttachable(dynamic_cast(m_pMountedMO)); } m_pMountedMO = newMO; - if (newMO && newMO->IsDevice()) { - dynamic_cast(newMO)->Attach(this, - dynamic_cast(newMO)->GetParentOffset()); - } + if (newMO && newMO->IsDevice()) { AddAttachable(dynamic_cast(newMO)); } return oldMO; } @@ -291,7 +274,7 @@ void Turret::Update() // Update basic metrics from parent. Attachable::Update(); - if (!m_pParent) + if (!m_Parent) { if (m_pMountedMO) { diff --git a/Entities/Turret.h b/Entities/Turret.h index 714cdeb4a..0ead6caac 100644 --- a/Entities/Turret.h +++ b/Entities/Turret.h @@ -177,6 +177,13 @@ ClassInfoGetters void SetID(const MOID newID) override; + /// + /// Replaces the MovableObject currently held by this Turret with a new one. Ownership IS transferred. + /// The currently held MovableObject (if there is one) will be dropped and become a detached MovableObject. + /// This is primarily used to support clone Create. At some point this should be refactored so Turret can only hold HeldDevices or Attachables anyway. + /// + /// A pointer to the new MovableObject to hold. Ownership IS transferred. + void SetMountedMO(Attachable *newMountedMO) { SetMountedMO(static_cast(newMountedMO)); } ////////////////////////////////////////////////////////////////////////////////////////// // Method: SetMountedMO diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 771e5fe5e..ed89a0712 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1182,7 +1182,8 @@ int LuaMan::Create() .def("GetLimbPathSpeed", &ACrab::GetLimbPathSpeed) .def("SetLimbPathSpeed", &ACrab::SetLimbPathSpeed), - ABSTRACTLUABINDING(Turret, Attachable), + CONCRETELUABINDING(Turret, Attachable) + .property("MountedMO", &Turret::GetMountedMO, (void (Turret:: *)(Attachable *newMountedMO)) &Turret::SetMountedMO), ABSTRACTLUABINDING(ACraft, Actor) .enum_("HatchState")[ From 55e42dc4c9fe6f36eb49c35a7b0dfc31797a21bc Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 19 Aug 2020 00:09:55 -0300 Subject: [PATCH 024/144] Fixed copy paste screwup in ACrab Fixed deleting hardcoded attachables in ACrab, ACDropship, ACRocket, ADoor, AHuman --- Entities/ACDropShip.cpp | 6 ------ Entities/ACRocket.cpp | 8 -------- Entities/ACrab.cpp | 19 +++++-------------- Entities/ADoor.cpp | 1 - Entities/AHuman.cpp | 6 ------ 5 files changed, 5 insertions(+), 35 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index e54dbed6d..d34e9c2f2 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -199,12 +199,6 @@ int ACDropShip::Save(Writer &writer) const void ACDropShip::Destroy(bool notInherited) { delete m_pBodyAG; - delete m_pRThruster; - delete m_pLThruster; - delete m_pURThruster; - delete m_pULThruster; - delete m_pRHatch; - delete m_pLHatch; if (!notInherited) ACraft::Destroy(); diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 8cb8777a1..39adaaaee 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -252,17 +252,9 @@ int ACRocket::Save(Writer &writer) const void ACRocket::Destroy(bool notInherited) { - delete m_pRLeg; - delete m_pLLeg; delete m_pBodyAG; delete m_pRFootGroup; delete m_pLFootGroup; - - delete m_pMThruster; - delete m_pRThruster; - delete m_pLThruster; - delete m_pURThruster; - delete m_pULThruster; // for (deque::iterator itr = m_WalkPaths.begin(); // itr != m_WalkPaths.end(); ++itr) diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index f547436be..ef076de75 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -162,15 +162,12 @@ int ACrab::Create(BITMAP *pSprite, // Description: Creates a ACrab to be identical to another, by deep copy. int ACrab::Create(const ACrab &reference) { - //if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pTurret, std::bind(&ACrab::SetTurret, this, dynamic_cast(reference.m_pTurret->Clone()))); } - - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pTurret, this, static_cast>(&ACrab::SetTurret)); } - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pJetpack, this, static_cast>(&ACrab::SetJetpack)); } - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pLFGLeg, this, static_cast>(&ACrab::SetLeftFGLeg)); } - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pRFGLeg, this, static_cast>(&ACrab::SetRightFGLeg)); } - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pLBGLeg, this, static_cast>(&ACrab::SetLeftBGLeg)); } - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pRBGLeg, this, static_cast>(&ACrab::SetRightBGLeg)); } + if (reference.m_pJetpack) { CloneHardcodedAttachable(reference.m_pJetpack, this, static_cast>(&ACrab::SetJetpack)); } + if (reference.m_pLFGLeg) { CloneHardcodedAttachable(reference.m_pLFGLeg, this, static_cast>(&ACrab::SetLeftFGLeg)); } + if (reference.m_pRFGLeg) { CloneHardcodedAttachable(reference.m_pRFGLeg, this, static_cast>(&ACrab::SetRightFGLeg)); } + if (reference.m_pLBGLeg) { CloneHardcodedAttachable(reference.m_pLBGLeg, this, static_cast>(&ACrab::SetLeftBGLeg)); } + if (reference.m_pRBGLeg) { CloneHardcodedAttachable(reference.m_pRBGLeg, this, static_cast>(&ACrab::SetRightBGLeg)); } Actor::Create(reference); @@ -411,12 +408,6 @@ int ACrab::Save(ostream &stream) const void ACrab::Destroy(bool notInherited) { - delete m_pTurret; - delete m_pLFGLeg; - delete m_pLBGLeg; - delete m_pRFGLeg; - delete m_pRBGLeg; - delete m_pJetpack; delete m_pLFGFootGroup; delete m_pLBGFootGroup; delete m_pRFGFootGroup; diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index 88e260243..df82682e3 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -189,7 +189,6 @@ namespace RTE { m_DoorMoveSound.Stop(); m_DoorDirectionChangeSound.Stop(); m_DoorMoveEndSound.Stop(); - delete m_Door; if (!notInherited) { Actor::Destroy(); } for (ADSensor &sensor : m_Sensors) { diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index ea5766fbc..dcb4d37dc 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -347,12 +347,6 @@ int AHuman::Save(Writer &writer) const void AHuman::Destroy(bool notInherited) { - delete m_pBGLeg; - delete m_pFGLeg; - delete m_pBGArm; - delete m_pFGArm; - delete m_pJetpack; - delete m_pHead; delete m_pBGHandGroup; delete m_pFGFootGroup; delete m_pBGFootGroup; From 2be90ce42463136aded85f438bb794f319cb9986 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 21 Aug 2020 21:02:29 -0300 Subject: [PATCH 025/144] Fixed add attachable during read property on AEmitter, Arm, Leg, Turret. Also cleaned up ReadProperty in these Fixed missing IsAttachahed check in Turret Fixed backwards equality check in MOSR attachable copying --- Entities/AEmitter.cpp | 71 ++++++++++++++++-------------------- Entities/Arm.cpp | 26 ++++++-------- Entities/HDFirearm.cpp | 78 ++++++++++++++++------------------------ Entities/Leg.cpp | 32 ++++++----------- Entities/MOSRotating.cpp | 2 +- Entities/Turret.cpp | 10 +++--- 6 files changed, 87 insertions(+), 132 deletions(-) diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index 746f89b10..af3faa148 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -110,82 +110,73 @@ int AEmitter::Create(const AEmitter &reference) { // is called. If the property isn't recognized by any of the base classes, // false is returned, and the reader's position is untouched. -int AEmitter::ReadProperty(std::string propName, Reader &reader) -{ - if (propName == "AddEmission") - { +int AEmitter::ReadProperty(std::string propName, Reader &reader) { + if (propName == "AddEmission") { Emission * emission = new Emission(); reader >> *emission; m_EmissionList.push_back(emission); - } - else if (propName == "EmissionSound") + } else if (propName == "EmissionSound") { reader >> m_EmissionSound; - else if (propName == "BurstSound") + } else if (propName == "BurstSound") { reader >> m_BurstSound; - else if (propName == "EndSound") + } else if (propName == "EndSound") { reader >> m_EndSound; - else if (propName == "EmissionEnabled") + } else if (propName == "EmissionEnabled") { reader >> m_EmitEnabled; - else if (propName == "EmissionCount") + } else if (propName == "EmissionCount") { reader >> m_EmitCount; - else if (propName == "EmissionCountLimit") + } else if (propName == "EmissionCountLimit") { reader >> m_EmitCountLimit; - else if (propName == "ParticlesPerMinute") - { + } else if (propName == "ParticlesPerMinute") { float ppm; reader >> ppm; // Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility - for (list::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr) + for (list::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr) { (*eItr)->m_PPM = ppm / m_EmissionList.size(); - } - else if (propName == "MinThrottleRange") + } + } else if (propName == "MinThrottleRange") { reader >> m_MinThrottleRange; - else if (propName == "MaxThrottleRange") + } else if (propName == "MaxThrottleRange") { reader >> m_MaxThrottleRange; - else if (propName == "Throttle") + } else if (propName == "Throttle") { reader >> m_Throttle; - else if (propName == "EmissionsIgnoreThis") + } else if (propName == "EmissionsIgnoreThis") { reader >> m_EmissionsIgnoreThis; - else if (propName == "BurstSize") - { + } else if (propName == "BurstSize") { int burstSize; reader >> burstSize; // Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility - for (list::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr) + for (list::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr) { (*eItr)->m_BurstSize = ceilf((float)burstSize / (float)m_EmissionList.size()); - } - else if (propName == "BurstScale") + } + } else if (propName == "BurstScale") { reader >> m_BurstScale; - else if (propName == "BurstDamage") + } else if (propName == "BurstDamage") { reader >> m_BurstDamage; - else if (propName == "EmitterDamageMultiplier") + } else if (propName == "EmitterDamageMultiplier") { reader >> m_EmitterDamageMultiplier; - else if (propName == "BurstSpacing") + } else if (propName == "BurstSpacing") { reader >> m_BurstSpacing; - else if (propName == "BurstTriggered") + } else if (propName == "BurstTriggered") { reader >> m_BurstTriggered; - else if (propName == "EmissionAngle") + } else if (propName == "EmissionAngle") { reader >> m_EmitAngle; - else if (propName == "EmissionOffset") + } else if (propName == "EmissionOffset") { reader >> m_EmissionOffset; - else if (propName == "EmissionDamage") + } else if (propName == "EmissionDamage") { reader >> m_EmitDamage; - else if (propName == "Flash") - { + } else if (propName == "Flash") { const Entity *pObj = g_PresetMan.GetEntityPreset(reader); if (pObj) { m_pFlash = dynamic_cast(pObj->Clone()); - AddAttachable(m_pFlash); } - } - else if (propName == "FlashScale") + } else if (propName == "FlashScale") { reader >> m_FlashScale; - else if (propName == "FlashOnlyOnBurst") + } else if (propName == "FlashOnlyOnBurst") { reader >> m_FlashOnlyOnBurst; - else if (propName == "LoudnessOnEmit") + } else if (propName == "LoudnessOnEmit") { reader >> m_LoudnessOnEmit; - else - { + } else { return Attachable::ReadProperty(propName, reader); } diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index a3764c6b5..063b7573c 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -88,34 +88,28 @@ int Arm::Create(const Arm &reference) { // is called. If the property isn't recognized by any of the base classes, // false is returned, and the reader's position is untouched. -int Arm::ReadProperty(std::string propName, Reader &reader) -{ - if (propName == "HeldDevice") - { +int Arm::ReadProperty(std::string propName, Reader &reader) { + if (propName == "HeldDevice") { const Entity *pEntity; pEntity = g_PresetMan.GetEntityPreset(reader); - if (pEntity) - { + if (pEntity) { m_pHeldMO = dynamic_cast(pEntity->Clone()); - if (m_pHeldMO->IsDevice()) { AddAttachable(dynamic_cast(m_pHeldMO)); } } pEntity = 0; - } - else if (propName == "Hand") - { + } else if (propName == "Hand") { reader >> m_HandFile; m_pHand = m_HandFile.GetAsBitmap(); - } - else if (propName == "MaxLength") + } else if (propName == "MaxLength") { reader >> m_MaxLength; - else if (propName == "IdleOffset") + } else if (propName == "IdleOffset") { reader >> m_IdleOffset; - else if (propName == "WillIdle") + } else if (propName == "WillIdle") { reader >> m_WillIdle; - else if (propName == "MoveSpeed") + } else if (propName == "MoveSpeed") { reader >> m_MoveSpeed; - else + } else { return Attachable::ReadProperty(propName, reader); + } return 0; } diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index 8264acf40..ff23afe26 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -140,91 +140,73 @@ int HDFirearm::Create(const HDFirearm &reference) { // is called. If the property isn't recognized by any of the base classes, // false is returned, and the reader's position is untouched. -int HDFirearm::ReadProperty(std::string propName, Reader &reader) -{ - if (propName == "Magazine") - { +int HDFirearm::ReadProperty(std::string propName, Reader &reader) { + if (propName == "Magazine") { const Entity *pObj = g_PresetMan.GetEntityPreset(reader); - if (pObj) - { + if (pObj) { m_pMagazineReference = dynamic_cast(pObj); - delete m_pMagazine; m_pMagazine = dynamic_cast(m_pMagazineReference->Clone()); - if (m_pMagazine) { AddAttachable(m_pMagazine); } } - } - else if (propName == "Flash") - { + } else if (propName == "Flash") { const Entity *pObj = g_PresetMan.GetEntityPreset(reader); - if (pObj) - { + if (pObj) { + delete m_pFlash; m_pFlash = dynamic_cast(pObj->Clone()); - if (m_pFlash) { AddAttachable(m_pFlash); } } - } - else if (propName == "FireSound") + } else if (propName == "FireSound") { reader >> m_FireSound; - else if (propName == "ActiveSound") { + } else if (propName == "ActiveSound") { reader >> m_ActiveSound; m_ActiveSound.SetAffectedByGlobalPitch(false); //Active sound (i.e. weapon spinup) modifies its pitch, so it has to account for global pitch on its own. - } else if (propName == "DeactivationSound") + } else if (propName == "DeactivationSound") { reader >> m_DeactivationSound; - else if (propName == "EmptySound") + } else if (propName == "EmptySound") { reader >> m_EmptySound; - else if (propName == "ReloadStartSound") + } else if (propName == "ReloadStartSound") { reader >> m_ReloadStartSound; - else if (propName == "ReloadEndSound") + } else if (propName == "ReloadEndSound") { reader >> m_ReloadEndSound; - else if (propName == "RateOfFire") + } else if (propName == "RateOfFire") { reader >> m_RateOfFire; - else if (propName == "ActivationDelay") + } else if (propName == "ActivationDelay") { reader >> m_ActivationDelay; - else if (propName == "DeactivationDelay") + } else if (propName == "DeactivationDelay") { reader >> m_DeactivationDelay; - else if (propName == "ReloadTime") + } else if (propName == "ReloadTime") { reader >> m_ReloadTime; - else if (propName == "FullAuto") + } else if (propName == "FullAuto") { reader >> m_FullAuto; - else if (propName == "FireIgnoresThis") + } else if (propName == "FireIgnoresThis") { reader >> m_FireIgnoresThis; - else if (propName == "RecoilTransmission") + } else if (propName == "RecoilTransmission") { reader >> m_RecoilTransmission; - else if (propName == "IsAnimatedManually") + } else if (propName == "IsAnimatedManually") { reader >> m_IsAnimatedManually; - else if (propName == "ShakeRange") - { + } else if (propName == "ShakeRange") { reader >> m_ShakeRange; m_ShakeRange /= 2; - } - else if (propName == "SharpShakeRange") - { + } else if (propName == "SharpShakeRange") { reader >> m_SharpShakeRange; m_SharpShakeRange /= 2; - } - else if (propName == "NoSupportFactor") + } else if (propName == "NoSupportFactor") { reader >> m_NoSupportFactor; - else if (propName == "ParticleSpreadRange") - { + } else if (propName == "ParticleSpreadRange") { reader >> m_ParticleSpreadRange; m_ParticleSpreadRange /= 2; - } - else if (propName == "ShellSpreadRange") - { + } else if (propName == "ShellSpreadRange") { reader >> m_ShellSpreadRange; m_ShellSpreadRange /= 2; - } - else if (propName == "ShellAngVelRange") - { + } else if (propName == "ShellAngVelRange") { reader >> m_ShellAngVelRange; m_ShellAngVelRange /= 2; - } - else if (propName == "MuzzleOffset") + } else if (propName == "MuzzleOffset") { reader >> m_MuzzleOff; - else if (propName == "EjectionOffset") + } else if (propName == "EjectionOffset") { reader >> m_EjectOff; - else + } else { return HeldDevice::ReadProperty(propName, reader); + } return 0; } diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index a96a5ccff..46a2b44ff 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -100,29 +100,19 @@ int Leg::Create(const Leg &reference) { // is called. If the property isn't recognized by any of the base classes, // false is returned, and the reader's position is untouched. -int Leg::ReadProperty(std::string propName, Reader &reader) -{ - if (propName == "Foot") - { +int Leg::ReadProperty(std::string propName, Reader &reader) { + if (propName == "Foot") { const Entity *pObj = g_PresetMan.GetEntityPreset(reader); - if (pObj) - { + if (pObj) { m_pFoot = dynamic_cast(pObj->Clone()); - AddAttachable(m_pFoot); } - } - else if (propName == "ContractedOffset") - { + } else if (propName == "ContractedOffset") { reader >> m_ContractedOffset; m_MinExtension = m_ContractedOffset.GetMagnitude(); - } - else if (propName == "ExtendedOffset") - { + } else if (propName == "ExtendedOffset") { reader >> m_ExtendedOffset; m_MaxExtension = m_ExtendedOffset.GetMagnitude(); - } - else if (propName == "MaxLength") - { + } else if (propName == "MaxLength") { // For backward compatibiltiy with before float maxLength; reader >> maxLength; @@ -131,15 +121,15 @@ int Leg::ReadProperty(std::string propName, Reader &reader) m_ContractedOffset.SetXY(m_MinExtension, 0); m_MaxExtension = maxLength; m_ExtendedOffset.SetXY(m_MaxExtension, 0); - } - else if (propName == "IdleOffset") + } else if (propName == "IdleOffset") { reader >> m_IdleOffset; - else if (propName == "WillIdle") + } else if (propName == "WillIdle") { reader >> m_WillIdle; - else if (propName == "MoveSpeed") + } else if (propName == "MoveSpeed") { reader >> m_MoveSpeed; - else + } else { return Attachable::ReadProperty(propName, reader); + } return 0; } diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index cf8b2d448..8d9736e92 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -245,7 +245,7 @@ int MOSRotating::Create(const MOSRotating &reference) // Attachable copies for (const Attachable *attachable : reference.m_Attachables) { - if (m_AlreadyCopiedAttachableUniqueIDs.find(attachable->GetUniqueID()) != m_AlreadyCopiedAttachableUniqueIDs.end()) { + if (m_AlreadyCopiedAttachableUniqueIDs.find(attachable->GetUniqueID()) == m_AlreadyCopiedAttachableUniqueIDs.end()) { AddAttachable(dynamic_cast(attachable->Clone())); } } diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index 2f8c63aa7..6c9ea24a0 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -70,18 +70,16 @@ int Turret::Create(const Turret &reference) { // is called. If the property isn't recognized by any of the base classes, // false is returned, and the reader's position is untouched. -int Turret::ReadProperty(std::string propName, Reader &reader) -{ +int Turret::ReadProperty(std::string propName, Reader &reader) { if (propName == "MountedMO") { const Entity *pEntity = g_PresetMan.GetEntityPreset(reader); if (pEntity) { m_pMountedMO = dynamic_cast(pEntity->Clone()); - if (m_pMountedMO->IsDevice()) { AddAttachable(dynamic_cast(m_pMountedMO)); } } pEntity = 0; - } - else + } else { return Attachable::ReadProperty(propName, reader); + } return 0; } @@ -183,7 +181,7 @@ void Turret::SetMountedMO(MovableObject *newHeldMO) if (newHeldMO && newHeldMO->IsHeldDevice()) { HeldDevice *pNewDev = dynamic_cast(newHeldMO); - dynamic_cast(pNewDev->GetParent())->RemoveAttachable(pNewDev); + if (pNewDev->IsAttached()) { dynamic_cast(pNewDev->GetParent())->RemoveAttachable(pNewDev); } g_MovableMan.RemoveMO(pNewDev); AddAttachable(pNewDev); pNewDev = 0; From 3deb98b8752b61f92fc0e609ab1a7cbe76f7a29b Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 22 Aug 2020 00:06:24 -0300 Subject: [PATCH 026/144] Cleanup Turret - fix and clean methods, reorganize, change MountedMO to MountedDevice cause having it as an MO was incredibly stupid Set aside some of the stuff that needs cleaning up in Turret for a future commit. Did clean up some stuff (e.g. attachable update) though. Fixed ACrab and LuaMan to match changes in Turret Cleaned up a few comments in Attachable header --- Entities/ACrab.cpp | 63 +++--- Entities/Attachable.h | 5 +- Entities/Turret.cpp | 488 ++++++++++------------------------------ Entities/Turret.h | 501 +++++++++++------------------------------- Managers/LuaMan.cpp | 2 +- 5 files changed, 287 insertions(+), 772 deletions(-) diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index ef076de75..a00710f5d 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -481,12 +481,14 @@ Vector ACrab::GetCPUPos() const Vector ACrab::GetEyePos() const { - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->GetMountedMO()) - return m_pTurret->GetMountedMO()->GetPos(); + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) + return m_pTurret->GetMountedDevice()->GetPos(); return m_Pos; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Attachable *ACrab::GetTurret() const { return (m_pTurret && m_pTurret->IsAttached()) ? dynamic_cast(m_pTurret) : nullptr; } @@ -686,7 +688,7 @@ bool ACrab::AddPieMenuSlices(PieMenuGUI *pPieMenu) Actor::AddPieMenuSlices(pPieMenu); // Add any custom slices from a currently held device - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) m_pTurret->GetMountedDevice()->AddPieMenuSlices(pPieMenu); return true; @@ -739,9 +741,9 @@ bool ACrab::HandlePieCommand(int pieSliceIndex) MovableObject * ACrab::GetEquippedItem() const { - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsSomethingMounted()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { - return m_pTurret->GetMountedMO(); + return m_pTurret->GetMountedDevice(); } return 0; @@ -756,9 +758,9 @@ MovableObject * ACrab::GetEquippedItem() const bool ACrab::FirearmIsReady() const { - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsSomethingMounted()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { - HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedMO()); + HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedDevice()); if (pWeapon && pWeapon->GetRoundInMagCount() != 0) return true; } @@ -774,9 +776,9 @@ bool ACrab::FirearmIsReady() const bool ACrab::FirearmIsEmpty() const { - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { - HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedMO()); + HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedDevice()); if (pWeapon && pWeapon->GetRoundInMagCount() == 0) return true; } @@ -792,9 +794,9 @@ bool ACrab::FirearmIsEmpty() const bool ACrab::FirearmNeedsReload() const { - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { - HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedMO()); + HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedDevice()); if (pWeapon && pWeapon->NeedsReloading()) return true; } @@ -810,9 +812,9 @@ bool ACrab::FirearmNeedsReload() const bool ACrab::FirearmIsSemiAuto() const { - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { - HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedMO()); + HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedDevice()); return pWeapon && !pWeapon->IsFullAuto(); } return false; @@ -828,9 +830,9 @@ bool ACrab::FirearmIsSemiAuto() const void ACrab::ReloadFirearm() { - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { - HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedMO()); + HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedDevice()); if (pWeapon) pWeapon->Reload(); } @@ -846,9 +848,9 @@ void ACrab::ReloadFirearm() int ACrab::FirearmActivationDelay() const { // Check if the currently held device is already the desired type - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { - HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedMO()); + HDFirearm *pWeapon = dynamic_cast(m_pTurret->GetMountedDevice()); if (pWeapon) return pWeapon->GetActivationDelay(); } @@ -879,7 +881,7 @@ bool ACrab::IsWithinRange(Vector &point) const float range = m_AimDistance; // Add the sharp range of the equipped weapon - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { range += m_pTurret->GetMountedDevice()->GetSharpLength() * m_SharpAimProgress; } @@ -905,7 +907,7 @@ bool ACrab::Look(float FOVSpread, float range) Vector aimPos = GetCPUPos(); // If aiming down the barrel, look through that - if (m_Controller.IsState(AIM_SHARP) && m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_Controller.IsState(AIM_SHARP) && m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { aimPos = m_pTurret->GetMountedDevice()->GetPos(); aimDistance += m_pTurret->GetMountedDevice()->GetSharpLength(); @@ -947,7 +949,7 @@ MovableObject * ACrab::LookForMOs(float FOVSpread, unsigned char ignoreMaterial, float aimDistance = m_AimDistance + g_FrameMan.GetPlayerScreenWidth() * 0.51; // Set the length of the look vector // If aiming down the barrel, look through that - if (m_Controller.IsState(AIM_SHARP) && m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_Controller.IsState(AIM_SHARP) && m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { aimPos = m_pTurret->GetMountedDevice()->GetPos(); aimDistance += m_pTurret->GetMountedDevice()->GetSharpLength(); @@ -2461,17 +2463,14 @@ void ACrab::Update() //////////////////////////////////// // Fire/Activate held devices - if (m_pTurret && m_pTurret->IsAttached()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { // Activate held device, if a device is held. - if (m_pTurret->IsHeldDeviceMounted()) - { - m_pTurret->GetMountedDevice()->SetSharpAim(m_SharpAimProgress); - if (m_Controller.IsState(WEAPON_FIRE)) - m_pTurret->GetMountedDevice()->Activate(); - else - m_pTurret->GetMountedDevice()->Deactivate(); - } + m_pTurret->GetMountedDevice()->SetSharpAim(m_SharpAimProgress); + if (m_Controller.IsState(WEAPON_FIRE)) + m_pTurret->GetMountedDevice()->Activate(); + else + m_pTurret->GetMountedDevice()->Deactivate(); } // Controller disabled @@ -2726,7 +2725,7 @@ void ACrab::Update() // Reset this each frame m_SharpAimMaxedOut = false; - if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) { float maxLength = m_pTurret->GetMountedDevice()->GetSharpLength(); @@ -2772,7 +2771,7 @@ void ACrab::Update() m_pTurret->SetHFlipped(m_HFlipped); m_pTurret->SetJointPos(m_Pos + m_pTurret->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); m_pTurret->SetRotAngle(m_Rotation.GetRadAngle()); - m_pTurret->SetMountedRotOffset((m_HFlipped ? -m_AimAngle : m_AimAngle) - m_Rotation.GetRadAngle()); + m_pTurret->SetMountedDeviceRotOffset((m_HFlipped ? -m_AimAngle : m_AimAngle) - m_Rotation.GetRadAngle()); m_pTurret->Update(); // Update the Atoms' offsets in the parent group // Matrix atomRot(FacingAngle(m_pTurret->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); @@ -3104,7 +3103,7 @@ void ACrab::DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos, int whichScr // Player AI drawing // Device aiming reticule - if (m_Controller.IsState(AIM_SHARP) && m_pTurret && m_pTurret->IsAttached() && m_pTurret->IsHeldDeviceMounted()) + if (m_Controller.IsState(AIM_SHARP) && m_pTurret && m_pTurret->IsAttached() && m_pTurret->HasMountedDevice()) m_pTurret->GetMountedDevice()->DrawHUD(pTargetBitmap, targetPos, whichScreen, m_Controller.IsPlayerControlled()); ////////////////////////////////////// diff --git a/Entities/Attachable.h b/Entities/Attachable.h index fafb43119..f8fe11167 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -20,7 +20,6 @@ namespace RTE { SerializableOverrideMethods ClassInfoGetters - #pragma region Creation /// /// Constructor method used to instantiate a Attachable object in system memory. Create() should be called before using the object. @@ -37,7 +36,7 @@ namespace RTE { #pragma region Destruction /// - /// Destructor method used to clean up a Attachable object before deletion from system memory. + /// Destructor method used to clean up an Attachable object before deletion from system memory. /// ~Attachable() override { Destroy(true); } @@ -305,7 +304,7 @@ namespace RTE { /// /// The impulse (kg * m/s) of the impact causing the gibbing to happen. /// The internal blast impulse which will push the gibs away from the center. - /// A pointer to an MO which the gibs shuold not be colliding with! + /// A pointer to an MO which the gibs should not be colliding with! void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *MOToIgnore = 0) override; /// diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index 6c9ea24a0..2182931c3 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -1,376 +1,128 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// File: Turret.cpp -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Source file for the Turret class. -// Project: Retro Terrain Engine -// Author(s): Daniel Tabar -// data@datarealms.com -// http://www.datarealms.com - - -////////////////////////////////////////////////////////////////////////////////////////// -// Inclusions of header files - #include "Turret.h" -#include "HeldDevice.h" #include "PresetMan.h" namespace RTE { -ConcreteClassInfo(Turret, Attachable, 20) - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Clear -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Clears all the member variables of this Turret, effectively -// resetting the members of this abstraction level only. - -void Turret::Clear() -{ - m_pMountedMO = 0; - m_MountedRotOffset = 0; -} - -/* -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes the Round object ready for use. - -int Turret::Create() -{ - if (Attachable::Create() < 0) - return -1; - - return 0; -} -*/ - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Creates a Turret to be identical to another, by deep copy. - -int Turret::Create(const Turret &reference) { - if (reference.m_pMountedMO && reference.m_pMountedMO->IsDevice()) { CloneHardcodedAttachable(dynamic_cast(reference.m_pMountedMO), this, static_cast>((void (Turret:: *)(Attachable * newMountedMO)) & Turret::SetMountedMO)); } - Attachable::Create(reference); - - m_MountedRotOffset = reference.m_MountedRotOffset; - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: ReadProperty -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Reads a property value from a reader stream. If the name isn't -// recognized by this class, then ReadProperty of the parent class -// is called. If the property isn't recognized by any of the base classes, -// false is returned, and the reader's position is untouched. - -int Turret::ReadProperty(std::string propName, Reader &reader) { - if (propName == "MountedMO") { - const Entity *pEntity = g_PresetMan.GetEntityPreset(reader); - if (pEntity) { - m_pMountedMO = dynamic_cast(pEntity->Clone()); - } - pEntity = 0; - } else { - return Attachable::ReadProperty(propName, reader); - } - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Save -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Saves the complete state of this Turret with a Writer for -// later recreation with Create(Reader &reader); - -int Turret::Save(Writer &writer) const -{ - Attachable::Save(writer); - - writer.NewProperty("MountedMO"); - writer << m_pMountedMO; - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Destroy -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Destroys and resets (through Clear()) the Turret object. - -void Turret::Destroy(bool notInherited) -{ -// g_MovableMan.RemoveEntityPreset(this); - - if (!notInherited) - Attachable::Destroy(); - Clear(); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this Turret, including the mass of any device it -// may be holding. - -float Turret::GetMass() const -{ - return m_Mass + (m_pMountedMO ? m_pMountedMO->GetMass() : 0); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetMountedDevice -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the HeldDevice currently held by this Turret, IF the thing held is -// a HeldDevice, that is. Ownership is NOT transferred. -// Arguments: None. -// Return value: A pointer to the currently held HeldDevice. 0 is returned if no -// HeldDevice is currently held (even though an MO may be held). - -HeldDevice * Turret::GetMountedDevice() const -{ - HeldDevice *pRetDev = 0; - if (m_pMountedMO && m_pMountedMO->IsHeldDevice()) - pRetDev = dynamic_cast(m_pMountedMO); - return pRetDev; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. - -void Turret::SetID(const MOID newID) -{ - MovableObject::SetID(newID); - if (m_pMountedMO) - m_pMountedMO->SetID(newID); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetMountedMO -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Replaces the MovableObject currently held by this Turret with a new -// one. Ownership IS transferred. The currently held MovableObject -// (if there is one) will be dropped and become a detached MovableObject, - -void Turret::SetMountedMO(MovableObject *newHeldMO) -{ - if (m_pMountedMO && m_pMountedMO->IsHeldDevice() && dynamic_cast(m_pMountedMO)->IsAttachedTo(this)) { - HeldDevice *pHeldDev = dynamic_cast(m_pMountedMO); - RemoveAttachable(pHeldDev); -// TODO: Refine throwing force to dropped device here?") - pHeldDev->SetVel(Vector(10 * PosRand(), -15 * PosRand())); - pHeldDev->SetAngularVel(-10 * PosRand()); - g_MovableMan.AddItem(pHeldDev); - m_pMountedMO = pHeldDev = 0; - } - - if (newHeldMO && newHeldMO->IsHeldDevice()) { - HeldDevice *pNewDev = dynamic_cast(newHeldMO); - if (pNewDev->IsAttached()) { dynamic_cast(pNewDev->GetParent())->RemoveAttachable(pNewDev); } - g_MovableMan.RemoveMO(pNewDev); - AddAttachable(pNewDev); - pNewDev = 0; - } - m_pMountedMO = newHeldMO; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: ReleaseMountedMO -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this arm let go of the HeldDevice currently held. Ownership IS -// transferred! -// Arguments: None. -// Return value: A pointer to the up to this point held HeldDevice. 0 is returned if no -// HeldDevice is currently held. Ownership IS transferred! - -MovableObject * Turret::ReleaseMountedMO() -{ - MovableObject *pReturnMO = m_pMountedMO; - if (m_pMountedMO && m_pMountedMO->IsDevice()) { RemoveAttachable(dynamic_cast(m_pMountedMO)); } - m_pMountedMO = 0; - return pReturnMO; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: DropEverything -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this arm let go of anyhthing it holds and give it to the -// MovableMan. Ownership is transferred to MovableMan. -// Arguments: None. - -MovableObject * Turret::DropEverything() -{ - MovableObject *pReturnMO = m_pMountedMO; - - if (m_pMountedMO && m_pMountedMO->IsDevice()) { - RemoveAttachable(dynamic_cast(m_pMountedMO)); - g_MovableMan.AddItem(m_pMountedMO); - } - else if (m_pMountedMO) - g_MovableMan.AddParticle(m_pMountedMO); - - m_pMountedMO = 0; - - return pReturnMO; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SwapMountedMO -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Replaces the MovableObject currently held by this Turret with a new -// one, and returns the replaced one. Ownership IS transferred both ways. - -MovableObject * Turret::SwapMountedMO(MovableObject *newMO) -{ - MovableObject *oldMO = m_pMountedMO; - if (m_pMountedMO && m_pMountedMO->IsDevice()) { RemoveAttachable(dynamic_cast(m_pMountedMO)); } - - m_pMountedMO = newMO; - if (newMO && newMO->IsDevice()) { AddAttachable(dynamic_cast(newMO)); } - - return oldMO; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. - -void Turret::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) -{ - Attachable::GibThis(impactImpulse, internalBlast, pIgnoreMO); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Update -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Updates this Turret. Supposed to be done every frame. - -void Turret::Update() -{ - // Update basic metrics from parent. - Attachable::Update(); - - if (!m_Parent) - { - if (m_pMountedMO) - { -/* - m_pMountedMO->SetVel(m_Vel + Vector(-10 * PosRand(), -15 * PosRand())); - m_pMountedMO->SetAngularVel(-7); - if (m_pMountedMO->IsDevice()) - dynamic_cast(m_pMountedMO)->Detach(); - g_MovableMan.AddItem(m_pMountedMO); - m_pMountedMO = 0; -*/ - HeldDevice *pHeldDev = dynamic_cast(m_pMountedMO); - if (pHeldDev && pHeldDev->IsHeldDevice()) - { - pHeldDev->SetJointPos(m_Pos + pHeldDev->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - pHeldDev->SetRotAngle(m_Rotation.GetRadAngle() + m_MountedRotOffset); - pHeldDev->Update(); - } - } - } - else - { - // Attached, so act like it - - // If a device is held, update it and arm configuration accordingly. - HeldDevice *pHeldDev = dynamic_cast(m_pMountedMO); - if (m_pMountedMO && m_pMountedMO->IsHeldDevice() && pHeldDev) - { - pHeldDev->SetHFlipped(m_HFlipped); - - pHeldDev->SetJointPos(m_Pos + pHeldDev->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - pHeldDev->SetRotAngle(m_Rotation.GetRadAngle() + m_MountedRotOffset); - pHeldDev->Update(); -// Looks strange -// if (pHeldDev->IsRecoiled()) -// m_pParent->AddImpulseForce(pHeldDev->GetRecoilForce()); -// else - m_Recoiled = false; - - // Apply forces and detach if necessary - // OBSERVE the memeber pointer is what gets set to 0!$@#$@ - if (!ApplyAttachableForces(pHeldDev)) - m_pMountedMO = 0; - } - } -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. - -void Turret::UpdateChildMOIDs(vector &MOIDIndex, - MOID rootMOID, - bool makeNewMOID) -{ - if (m_pMountedMO && m_pMountedMO->GetsHitByMOs()) - m_pMountedMO->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - - Attachable::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - -void Turret::GetMOIDs(std::vector &MOIDs) const -{ - if (m_pMountedMO && m_pMountedMO->GetsHitByMOs()) - m_pMountedMO->GetMOIDs(MOIDs); - - Attachable::GetMOIDs(MOIDs); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this Turret's current graphical representation to a -// BITMAP of choice. - -void Turret::Draw(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode, - bool onlyPhysical) const -{ - if (m_pMountedMO && !m_pMountedMO->IsDrawnAfterParent()) - m_pMountedMO->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + ConcreteClassInfo(Turret, Attachable, 20) - Attachable::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (m_pMountedMO && m_pMountedMO->IsDrawnAfterParent()) - m_pMountedMO->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); -} + void Turret::Clear() { + m_MountedDevice = 0; + m_MountedDeviceRotOffset = 0; + } -} // namespace RTE \ No newline at end of file +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Turret::Create(const Turret &reference) { + if (reference.m_MountedDevice && reference.m_MountedDevice->IsDevice()) { CloneHardcodedAttachable(dynamic_cast(reference.m_MountedDevice), this, static_cast>((void (Turret:: *)(Attachable * newMountedMO)) & Turret::SetMountedDevice)); } + Attachable::Create(reference); + + m_MountedDeviceRotOffset = reference.m_MountedDeviceRotOffset; + + return 0; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Turret::ReadProperty(std::string propName, Reader &reader) { + if (propName == "MountedMO") { + const Entity *pEntity = g_PresetMan.GetEntityPreset(reader); + if (pEntity) { + m_MountedDevice = dynamic_cast(pEntity->Clone()); + } + pEntity = 0; + } else { + return Attachable::ReadProperty(propName, reader); + } + + return 0; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Turret::Save(Writer &writer) const { + Attachable::Save(writer); + + writer.NewProperty("MountedMO"); + writer << m_MountedDevice; + + return 0; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Turret::SetMountedDevice(HeldDevice *newMountedDevice) { + DropMountedDevice(); + + if (newMountedDevice) { + if (newMountedDevice->IsAttached()) { dynamic_cast(newMountedDevice->GetParent())->RemoveAttachable(newMountedDevice); } + g_MovableMan.RemoveMO(newMountedDevice); + AddAttachable(newMountedDevice); + } + m_MountedDevice = newMountedDevice; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + HeldDevice *Turret::ReleaseMountedDevice() { + HeldDevice *previouslyMountedDevice = m_MountedDevice; + if (m_MountedDevice) { RemoveAttachable(m_MountedDevice); } + m_MountedDevice = 0; + return previouslyMountedDevice; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + HeldDevice *Turret::DropMountedDevice() { + HeldDevice *previouslyMountedDevice = ReleaseMountedDevice(); + + if (previouslyMountedDevice) { + g_MovableMan.AddItem(previouslyMountedDevice); + } + + return previouslyMountedDevice; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Turret::Update() { + if (m_MountedDevice) { + m_MountedDevice->SetJointPos(m_Pos + m_MountedDevice->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); + m_MountedDevice->SetRotAngle(m_Rotation.GetRadAngle() + m_MountedDeviceRotOffset); + if (m_Parent) { + //if (m_MountedDevice->IsRecoiled()) { + // m_Parent->AddImpulseForce(m_MountedDevice->GetRecoilForce()); + //} else { + m_Recoiled = false; + //} + } + } + + Attachable::Update(); + //TODO consider expanding the stuff used in clone create to allow for clearing hardcoded attachables (might be as simple as updating unique id entries and calling things accordingly) + if (std::find(m_Attachables.begin(), m_Attachables.end(), m_MountedDevice) == m_Attachables.end()) { m_MountedDevice = nullptr; } + } + + //TODO KILL KILL KILL + float Turret::GetMass() const { + return m_Mass + (m_MountedDevice ? m_MountedDevice->GetMass() : 0); + } + void Turret::SetID(const MOID newID) { + MovableObject::SetID(newID); + if (m_MountedDevice) + m_MountedDevice->SetID(newID); + } + void Turret::GetMOIDs(std::vector &MOIDs) const { + if (m_MountedDevice && m_MountedDevice->GetsHitByMOs()) + m_MountedDevice->GetMOIDs(MOIDs); + + Attachable::GetMOIDs(MOIDs); + } + void Turret::UpdateChildMOIDs(vector &MOIDIndex, MOID rootMOID, bool makeNewMOID) { + if (m_MountedDevice && m_MountedDevice->GetsHitByMOs()) + m_MountedDevice->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); + + Attachable::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); + } +} \ No newline at end of file diff --git a/Entities/Turret.h b/Entities/Turret.h index 0ead6caac..9a63c4d50 100644 --- a/Entities/Turret.h +++ b/Entities/Turret.h @@ -1,371 +1,136 @@ #ifndef _RTETURRET_ #define _RTETURRET_ -////////////////////////////////////////////////////////////////////////////////////////// -// File: Turret.h -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Header file for the Turret class. -// Project: Retro Terrain Engine -// Author(s): Daniel Tabar -// data@datarealms.com -// http://www.datarealms.com - - -////////////////////////////////////////////////////////////////////////////////////////// -// Inclusions of header files - -#include "Attachable.h" - -namespace RTE -{ - -class HeldDevice; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Class: Turret -////////////////////////////////////////////////////////////////////////////////////////// -// Description: A detatchable turret pod that can hold HeldDevices (weapons, tools) -// Parent(s): Attachable. -// Class history: 10/24/2007 Turret created. - -class Turret: - public Attachable -{ - - -////////////////////////////////////////////////////////////////////////////////////////// -// Public member variable, method and friend function declarations - -public: - - -// Concrete allocation and cloning definitions -EntityAllocation(Turret) -SerializableOverrideMethods -ClassInfoGetters - - -////////////////////////////////////////////////////////////////////////////////////////// -// Constructor: Turret -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Constructor method used to instantiate a Turret object in system -// memory. Create() should be called before using the object. -// Arguments: None. - - Turret() { Clear(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Destructor: ~Turret -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Destructor method used to clean up a Turret object before deletion -// from system memory. -// Arguments: None. - - ~Turret() override { Destroy(true); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Creates a Turret to be identical to another, by deep copy. -// Arguments: A reference to the Turret to deep copy. -// Return value: An error return value signaling sucess or any particular failure. -// Anything below 0 is an error signal. - - int Create(const Turret &reference); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Reset -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Resets the entire Turret, including its inherited members, to their -// default settings or values. -// Arguments: None. -// Return value: None. - - void Reset() override { Clear(); Attachable::Reset(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Destroy -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Destroys and resets (through Clear()) the SceneLayer object. -// Arguments: Whether to only destroy the members defined in this derived class, or -// to destroy all inherited members also. -// Return value: None. - - void Destroy(bool notInherited = false) override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this Turret, including the mass of any device it -// may be holding. -// Arguments: None. -// Return value: A float describing the mass value in Kilograms (kg). - - float GetMass() const override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetMountedDevice -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the HeldDevice currently held by this Turret, IF the thing held is -// a HeldDevice, that is. Ownership is NOT transferred. -// Arguments: None. -// Return value: A pointer to the currently held HeldDevice. 0 is returned if no -// HeldDevice is currently held (even though an MO may be held). - - HeldDevice * GetMountedDevice() const; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: IsDeviceMounted -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether a device is being held or not. Faster than using -// GetMountedDevice() for the purpose. -// Arguments: None. -// Return value: A bool indicating whether any device is held by this Turret. - - bool IsDeviceMounted() const { return m_pMountedMO && m_pMountedMO->IsDevice(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: IsHeldDeviceMounted -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether a HeldDevice is held or not. Faster than using -// GetMountedDevice() for the purpose. -// Arguments: None. -// Return value: A bool indicating whether a HeldDevice is held by this Turret. - - bool IsHeldDeviceMounted() const { return m_pMountedMO && m_pMountedMO->IsHeldDevice(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: IsThrownDeviceMounted -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether a ThrownDevice is held or not. Faster than using -// GetMountedDevice() for the purpose. -// Arguments: None. -// Return value: A bool indicating whether a ThrownDevice is held by this Turret. - - bool IsThrownDeviceMounted() const { return m_pMountedMO && m_pMountedMO->IsThrownDevice(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetMountedMO -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the MovableObject currently held by this Turret. Ownership is NOT -// transferred. -// Arguments: None. -// Return value: A pointer to the currently held MovableObject. 0 is returned if no -// MovableObject is currently held. - - MovableObject * GetMountedMO() const { return m_pMountedMO; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. -// Arguments: A MOID specifying the MOID that this MovableObject is -// assigned for this frame. -// Return value: None. - - void SetID(const MOID newID) override; - - /// - /// Replaces the MovableObject currently held by this Turret with a new one. Ownership IS transferred. - /// The currently held MovableObject (if there is one) will be dropped and become a detached MovableObject. - /// This is primarily used to support clone Create. At some point this should be refactored so Turret can only hold HeldDevices or Attachables anyway. - /// - /// A pointer to the new MovableObject to hold. Ownership IS transferred. - void SetMountedMO(Attachable *newMountedMO) { SetMountedMO(static_cast(newMountedMO)); } - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetMountedMO -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Replaces the MovableObject currently held by this Turret with a new -// one. Ownership IS transferred. The currently held MovableObject -// (if there is one) will be dropped and become a detached MovableObject, -// Arguments: A pointer to the new MovableObject to hold. Ownership IS transferred. -// Return value: None. - - void SetMountedMO(MovableObject *newHeldMO); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: ReleaseMountedMO -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this arm let go of the MovableObject currently held. Ownership -// IS transferred! -// Arguments: None. -// Return value: A pointer to the up to this point held MovableObject. 0 is returned -// if no MovableObject is currently held. Ownership IS transferred! - - MovableObject * ReleaseMountedMO(); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: DropEverything -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this arm let go of anyhthing it holds and give it to the -// MovableMan. Ownership is transferred to MovableMan. -// Arguments: None. -// Return value: A pointer to the up to this point held anything. 0 is returned if -// nothing is currently held. Ownership is NOT transferred, but given -// to MovableMan. - - MovableObject * DropEverything(); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SwapMountedMO -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Replaces the MovableObject currently held by this Turret with a new -// one, and returns the replaced one. Ownership IS transferred both ways. -// Arguments: A pointer to the new MovableObject to hold. Ownership IS transferred. -// Return value: A pointer to the previously held MO. Ownership IS transferred. - - MovableObject * SwapMountedMO(MovableObject *newMO); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: IsDeviceMounted -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this Turret is holding a HeldDevice or not. -// Arguments: None. -// Return value: Whether this Turret is holding a HeldDevice or not. - - bool IsDeviceMounted() { return m_pMountedMO && m_pMountedMO->IsDevice(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: IsSomethingMounted -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this Turret is holding an MO or not. -// Arguments: None. -// Return value: Whether this Turret is holding anyhting. - - bool IsSomethingMounted() { return m_pMountedMO != 0; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetMountedRotOffset -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the current rotational offset of the mounted device from the rest -// of the turret -// Arguments: The new offset angle in radians, relative from the rest of the turret. -// Return value: None. - - void SetMountedRotOffset(float newOffsetAngle) { m_MountedRotOffset = newOffsetAngle; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Update -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Updates this MovableObject. Supposed to be done every frame. -// Arguments: None. -// Return value: None. - - void Update() override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this Turret's current graphical representation to a -// BITMAP of choice. -// Arguments: A pointer to a BITMAP to draw on. -// The absolute position of the target bitmap's upper left corner in the Scene. -// In which mode to draw in. See the DrawMode enumeration for the modes. -// Whether to not draw any extra 'ghost' items of this MovableObject, -// indicator arrows or hovering HUD text and so on. -// Return value: None. - - void Draw(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; - - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - - void GetMOIDs(std::vector &MOIDs) const override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Protected member variable and method declarations - -protected: - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame, -// and then finally draws its and its childrens' MOID silhouette onto a -// BITMAP of choice. -// Arguments: The MOID index to register itself and its children in. -// The MOID of the root MO of this MO, ie the highest parent of this MO. -// 0 means that this MO is the root, ie it is owned by MovableMan. -// Whether this MO should make a new MOID to use for itself, or to use -// the same as the last one in the index (presumably its parent), -// Return value: None. - - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; - - - // Member variables - static Entity::ClassInfo m_sClass; - // The MovableObject held, updated and held by this Turret, if any. - MovableObject *m_pMountedMO; - // The relative offset in angle (radians) of the mounted device from this' rotation - float m_MountedRotOffset; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Private member variable and method declarations - -private: - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Clear -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Clears all the member variables of this Turret, effectively -// resetting the members of this abstraction level only. -// Arguments: None. -// Return value: None. - - void Clear(); - - - // Disallow the use of some implicit methods. - Turret(const Turret &reference) {} - Turret & operator=(const Turret &rhs) {} - -}; - -} // namespace RTE - -#endif // File \ No newline at end of file +#include "HeldDevice.h" + +namespace RTE { + + class HeldDevice; + + /// + /// A detatchable turret pod that can hold HeldDevices. + /// + class Turret : public Attachable { + + public: + + EntityAllocation(Turret) + SerializableOverrideMethods + ClassInfoGetters + +#pragma region Creation + /// + /// Constructor method used to instantiate a Turret object in system memory. Create() should be called before using the object. + /// + Turret() { Clear(); } + + /// + /// Creates a Turret to be identical to another, by deep copy. + /// + /// A reference to the Turret to deep copy. + /// An error return value signaling sucess or any particular failure. Anything below 0 is an error signal. + int Create(const Turret &reference); +#pragma endregion + +#pragma region Destruction + /// + /// Destructor method used to clean up a Turret object before deletion from system memory. + /// + ~Turret() override { Destroy(true); } + + /// + /// Destroys and resets (through Clear()) the Turret object. + /// + /// Whether to only destroy the members defined in this derived class, or to destroy all inherited members also. + void Destroy(bool notInherited = false) override { if (!notInherited) { Attachable::Destroy(); } Clear(); } + + /// + /// Resets the entire Turret, including its inherited members, to their default settings or values. + /// + void Reset() override { Clear(); Attachable::Reset(); } +#pragma endregion + +#pragma region Getters and Setters + /// + /// Indicates whether a HeldDevice is mounted or not. + /// + /// Whether or not a HeldDevice is mounted on this Turret. + bool HasMountedDevice() const { return m_MountedDevice != nullptr; } + + /// + /// Gets the mounted HeldDevice of this Turret. + /// + /// A pointer to mounted HeldDevice of this Turret. Ownership is NOT transferred! + HeldDevice * GetMountedDevice() const { return m_MountedDevice; } + + /// + /// Sets the mounted HeldDevice for this Turret. Ownership IS transferred! + /// The currently mounted HeldDevice (if there is one) will be dropped and added to MovableMan. + /// + /// The new HeldDevice to use. + void SetMountedDevice(HeldDevice *newMountedDevice); + + /// + /// Indicates whether a ThrownDevice is mounted or not. + /// + /// Whether or not a ThrownDevice is mounted on this Turret. + bool IsThrownDeviceMounted() const { return m_MountedDevice && m_MountedDevice->IsThrownDevice(); } + + /// + /// Sets the current rotational offset of the mounted HeldDevice from the rest of the Turret. + /// + /// The new offset angle in radians, relative from the rest of the turret. + void SetMountedDeviceRotOffset(float newOffsetAngle) { m_MountedDeviceRotOffset = newOffsetAngle; } +#pragma endregion + +#pragma region Mounted Device Management + /// + /// Makes this Turret unmount its mounted HeldDevice. Ownership IS transferred! + /// + /// A pointer to the previously mounted HeldDevice. Ownership IS transferred! + HeldDevice * ReleaseMountedDevice(); + + /// + /// Makes this Turret unmount its mounted HeldDevice and give it to MovableMan. Ownership IS transferred to MovableMan. + /// + /// A pointer to the previously mounted HeldDevice. Ownership IS transferred to MovableMan. + HeldDevice *DropMountedDevice(); +#pragma endregion + +#pragma region Override Methods + /// + /// Updates this MovableObject. Supposed to be done every frame. + /// + void Update() override; +#pragma endregion + + + //These die soon + float GetMass() const override; + void SetID(const MOID newID) override; + void GetMOIDs(std::vector &MOIDs) const override; + + protected: + + //This dies soon + void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; + + + static Entity::ClassInfo m_sClass; //!< ClassInfo for this class. + + HeldDevice *m_MountedDevice; // + /// Clears all the member variables of this Turret, effectively resetting the members of this abstraction level only. + /// + void Clear(); + + // Disallow the use of some implicit methods. + Turret(const Turret &reference) {} + Turret &operator=(const Turret &rhs) {} + }; +} +#endif \ No newline at end of file diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index ed89a0712..66c47ba98 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1183,7 +1183,7 @@ int LuaMan::Create() .def("SetLimbPathSpeed", &ACrab::SetLimbPathSpeed), CONCRETELUABINDING(Turret, Attachable) - .property("MountedMO", &Turret::GetMountedMO, (void (Turret:: *)(Attachable *newMountedMO)) &Turret::SetMountedMO), + .property("MountedDevice", &Turret::GetMountedDevice, (void (Turret:: *)(Attachable *newMountedMO)) &Turret::SetMountedDevice), ABSTRACTLUABINDING(ACraft, Actor) .enum_("HatchState")[ From 59f710f07c7a836e61e0890d98e2060f08e4d383 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 22 Aug 2020 22:27:52 -0300 Subject: [PATCH 027/144] Prepped to have MOSR handle attachable behaviour in GetMass, SetID, GetMOIDs, IsOnScenePoint, UpdateChildMOIDs, GibThis and Draw Cleaned up RegMOID in MO so it's not totally stupid when makeNewMOID is false Changed SetID to SetAsNoID cause that's all it was used for, and directly setting ID like this fucks up collisions with attachables --- Entities/MOSRotating.cpp | 154 +++++++++++-------------------------- Entities/MOSRotating.h | 44 +++++------ Entities/MovableObject.cpp | 22 ++---- Entities/MovableObject.h | 13 +--- Managers/MovableMan.cpp | 6 +- 5 files changed, 80 insertions(+), 159 deletions(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 8d9736e92..9f8d13259 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -554,23 +554,29 @@ void MOSRotating::Destroy(bool notInherited) Clear(); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this ACDropShip, including the mass of its -// currently attached body parts and inventory. - -float MOSRotating::GetMass() const -{ +float MOSRotating::GetMass() const { float totalMass = MOSprite::GetMass(); + for (const Attachable *attachable : m_Attachables) { + totalMass += attachable->GetMass(); + } + for (const AEmitter *wound : m_Wounds) { + totalMass += wound->GetMass(); + } + return totalMass; +} - for (list::const_iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ++aItr) - totalMass += (*aItr)->GetMass(); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - return totalMass; +void MOSRotating::SetAsNoID() { + MovableObject::SetAsNoID(); + for (Attachable *attachable : m_Attachables) { + attachable->SetAsNoID(); + } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetMaterial @@ -1254,84 +1260,32 @@ void MOSRotating::RestDetection() m_PrevAngVel = m_AngularVel; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: IsOnScenePoint -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this' current graphical representation overlaps -// a point in absolute scene coordinates. - -bool MOSRotating::IsOnScenePoint(Vector &scenePoint) const -{ - if (!m_aSprite[m_Frame]) +bool MOSRotating::IsOnScenePoint(Vector &scenePoint) const { + if (!m_aSprite[m_Frame]) { return false; -// TODO: TAKE CARE OF WRAPPING -/* - // Take care of wrapping situations - bitmapPos = m_Pos + m_BitmapOffset; - Vector aScenePoint[4]; - aScenePoint[0] = scenePoint; - int passes = 1; - - // See if need to double draw this across the scene seam if we're being drawn onto a scenewide bitmap - if (targetPos.IsZero()) - { - if (g_SceneMan.SceneWrapsX()) - { - if (bitmapPos.m_X < m_pFGColor->w) - { - aScenePoint[passes] = aScenePoint[0]; - aScenePoint[passes].m_X += g_SceneMan.GetSceneWidth(); - passes++; - } - else if (aScenePoint[0].m_X > pTargetBitmap->w - m_pFGColor->w) - { - aScenePoint[passes] = aScenePoint[0]; - aScenePoint[passes].m_X -= g_SceneMan.GetSceneWidth(); - passes++; - } - } - if (g_SceneMan.SceneWrapsY()) - { - - } } - // Check all the passes needed - for (int i = 0; i < passes; ++i) - { - if (IsWithinBox(aScenePoint[i], m_Pos + m_BitmapOffset, m_pFGColor->w, m_pFGColor->h)) - { - if (getpixel(m_pFGColor, aScenePoint[i].m_X, aScenePoint[i].m_Y) != g_MaskColor || - (m_pBGColor && getpixel(m_pBGColor, aScenePoint[i].m_X, aScenePoint[i].m_Y) != g_MaskColor) || - (m_pMaterial && getpixel(m_pMaterial, aScenePoint[i].m_X, aScenePoint[i].m_Y) != g_MaterialAir)) - return true; - } - } -*/ - if (WithinBox(scenePoint, m_Pos.m_X - m_MaxRadius, m_Pos.m_Y - m_MaxRadius, m_Pos.m_X + m_MaxRadius, m_Pos.m_Y + m_MaxRadius)) - { - // Get scene point in object's relative space + if (WithinBox(scenePoint, m_Pos.m_X - m_MaxRadius, m_Pos.m_Y - m_MaxRadius, m_Pos.m_X + m_MaxRadius, m_Pos.m_Y + m_MaxRadius)) { Vector spritePoint = scenePoint - m_Pos; - // Rotate it back to correspond with the unrotated bitmap spritePoint = UnRotateOffset(spritePoint); - // Check for overlap on the local rotated relative point. subtract spriteoffset to get into sprite bitmap's space - int pixel = getpixel(m_aSprite[m_Frame], spritePoint.m_X - m_SpriteOffset.m_X, spritePoint.m_Y - m_SpriteOffset.m_Y); - // Check that it isn't outside the bitmap, and not of the key color - if (pixel != -1 && pixel != g_MaskColor) - return true; + int pixel = getpixel(m_aSprite[m_Frame], static_cast(spritePoint.m_X - m_SpriteOffset.m_X), static_cast(spritePoint.m_Y - m_SpriteOffset.m_Y)); + if (pixel != -1 && pixel != g_MaskColor) { + return true; + } } - // Check the attachables too, backward since the latter ones tend to be larger, and therefore more likeyl to be on the point - for (list::const_reverse_iterator aItr = m_Attachables.rbegin(); aItr != m_Attachables.rend(); ++aItr) - { - if ((*aItr)->IsOnScenePoint(scenePoint)) + for (const Attachable *attachable : m_Attachables) { + if (attachable->IsOnScenePoint(scenePoint)) { return true; + } } return false; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: EraseFromTerrain @@ -1648,26 +1602,18 @@ bool MOSRotating::DrawMOIDIfOverlapping(MovableObject *pOverlapMO) return false; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. +//TODO This should just be defined in MOSR instead of having an empty definition in MO. MOSR would need to override UpdateMOID accordingly, but this would clean things up a little. +void MOSRotating::UpdateChildMOIDs(vector &MOIDIndex, MOID rootMOID, bool makeNewMOID) { + MOSprite::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); -void MOSRotating::UpdateChildMOIDs(vector &MOIDIndex, - MOID rootMOID, - bool makeNewMOID) -{ - // Register all the eligible attachables - for (list::iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ++aItr) - { -// TODO: Which should it be, don't register at all, or register as same as parent?? - if ((*aItr)->GetsHitByMOs()) - (*aItr)->UpdateMOID(MOIDIndex, m_RootMOID, (*aItr)->GetsHitByMOs()); + for (Attachable *attachable : m_Attachables) { + // Anything that doesn't get hit by MOs doesn't need an ID, since that's only actually used for collision stuff. + if (attachable->GetsHitByMOs()) { + attachable->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); + } } - - MOSprite::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1733,23 +1679,17 @@ void MOSRotating::DetachOrDestroyAll(bool destroy) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - -void MOSRotating::GetMOIDs(std::vector &MOIDs) const -{ - // Get MOIDs all the eligible attachables - for (list::const_iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ++aItr) - (*aItr)->GetMOIDs(MOIDs); - - // Get self MOID - MOSprite::GetMOIDs(MOIDs); +void MOSRotating::GetMOIDs(std::vector &MOIDs) const { + MOSprite::GetMOIDs(MOIDs); + for (const Attachable *attachable : m_Attachables) { + if (attachable->GetsHitByMOs()) { + attachable->GetMOIDs(MOIDs); + } + } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 8ee5393bd..3f6a35986 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -136,16 +136,22 @@ ClassInfoGetters void Destroy(bool notInherited = false) override; + /// + /// Gets the mass value of this MOSRotating, including the mass of all its Attachables and their Attachables and so on. + /// + /// The mass of this MOSRotating and all Attachables in Kilograms (kg). + float GetMass() const override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this ACDropShip, including the mass of its -// currently attached body parts and inventory. -// Arguments: None. -// Return value: A float describing the mass value in Kilograms (kg). + /// + /// Gets the MOIDs of this MOSRotating and all its Attachables and Wounds, putting them into the MOIDs vector. + /// + /// The vector that will store all the MOIDs of this MOSRotating. + void GetMOIDs(std::vector &MOIDs) const override; - float GetMass() const override; + /// + /// Sets the MOID of this MOSRotating and any Attachables on it to be g_NoMOID (255) for this frame. + /// + void SetAsNoID() override; ////////////////////////////////////////////////////////////////////////////////////////// @@ -433,14 +439,11 @@ ClassInfoGetters void RestDetection() override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: IsOnScenePoint -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this' current graphical representation overlaps -// a point in absolute scene coordinates. -// Arguments: The point in absolute scene coordinates. -// Return value: Whether this' graphical rep overlaps the scene point. - + /// + /// Indicates whether this MOSRotating's current graphical representation, including its Attachables, overlaps a point in absolute scene coordinates. + /// + /// The point in absolute scene coordinates to check for overlap with. + /// Whether or not this MOSRotating's graphical representation overlaps the given scene point. bool IsOnScenePoint(Vector &scenePoint) const override; @@ -729,15 +732,6 @@ ClassInfoGetters bool ObjectValueExists(std::string key); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - - void GetMOIDs(std::vector &MOIDs) const override; - ////////////////////////////////////////////////////////////////////////////////////////// // Method: SetDamageMultiplier ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/MovableObject.cpp b/Entities/MovableObject.cpp index ade2ae6d7..98af1b46a 100644 --- a/Entities/MovableObject.cpp +++ b/Entities/MovableObject.cpp @@ -1025,27 +1025,19 @@ void MovableObject::GetMOIDs(std::vector &MOIDs) const // itself and its children for this frame. // BITMAP of choice. -void MovableObject::RegMOID(vector &MOIDIndex, - MOID rootMOID, - bool makeNewMOID) -{ - // Make a new MOID for itself - if (makeNewMOID) - { - // Skip g_NoMOID item - if (MOIDIndex.size() == g_NoMOID) - MOIDIndex.push_back(0); +void MovableObject::RegMOID(vector &MOIDIndex, MOID rootMOID, bool makeNewMOID) { + if (!makeNewMOID && GetParent()) { + m_MOID = GetParent()->GetID(); + } else { + if (MOIDIndex.size() == g_NoMOID) { + MOIDIndex.push_back(0); + } m_MOID = MOIDIndex.size(); MOIDIndex.push_back(this); } - // Use the parent's MOID instead (the two are considered the same MO) - else - m_MOID = MOIDIndex.size() - 1; - // Assign the root MOID m_RootMOID = (rootMOID == g_NoMOID ? m_MOID : rootMOID); - } } // namespace RTE \ No newline at end of file diff --git a/Entities/MovableObject.h b/Entities/MovableObject.h index acafb6413..99eeb6d9a 100644 --- a/Entities/MovableObject.h +++ b/Entities/MovableObject.h @@ -778,15 +778,10 @@ friend class Atom; void SetAge(double newAge = 0) { m_AgeTimer.SetElapsedSimTimeMS(newAge); } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. -// Arguments: An int specifying the MOID that this MovableObject is -// assigned for this frame. -// Return value: None. - - virtual void SetID(const MOID newID) { m_MOID = newID; } + /// + /// Sets the MOID of this MovableObject to be g_NoMOID (255) for this frame. + /// + virtual void SetAsNoID() { m_MOID = g_NoMOID; } /// /// Sets this object as having been added to MovableMan. Should only really be done in MovableMan::AddObject. diff --git a/Managers/MovableMan.cpp b/Managers/MovableMan.cpp index ec4286a1d..475b19680 100644 --- a/Managers/MovableMan.cpp +++ b/Managers/MovableMan.cpp @@ -2121,7 +2121,7 @@ void MovableMan::UpdateDrawMOIDs(BITMAP *pTargetBitmap) currentMOID = m_MOIDIndex.size(); } else - m_Actors[i]->SetID(g_NoMOID); + m_Actors[i]->SetAsNoID(); } for (i = 0; i < iCount; ++i) { @@ -2132,7 +2132,7 @@ void MovableMan::UpdateDrawMOIDs(BITMAP *pTargetBitmap) currentMOID = m_MOIDIndex.size(); } else - m_Items[i]->SetID(g_NoMOID); + m_Items[i]->SetAsNoID(); } for (i = 0; i < parCount; ++i) { @@ -2143,7 +2143,7 @@ void MovableMan::UpdateDrawMOIDs(BITMAP *pTargetBitmap) currentMOID = m_MOIDIndex.size(); } else - m_Particles[i]->SetID(g_NoMOID); + m_Particles[i]->SetAsNoID(); } } From 3599697fae1698050cc854095fdddaf48a4a46c4 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 22 Aug 2020 22:28:29 -0300 Subject: [PATCH 028/144] Cleaned up turret use of mosr handled methods --- Entities/Turret.cpp | 24 +----------------------- Entities/Turret.h | 6 ------ 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index 2182931c3..3d6c8edc0 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -100,29 +100,7 @@ namespace RTE { } Attachable::Update(); - //TODO consider expanding the stuff used in clone create to allow for clearing hardcoded attachables (might be as simple as updating unique id entries and calling things accordingly) + //TODO consider expanding the stuff used in clone create to allow for clearing hardcoded attachables members (might be as simple as updating unique id entries and calling things accordingly) if (std::find(m_Attachables.begin(), m_Attachables.end(), m_MountedDevice) == m_Attachables.end()) { m_MountedDevice = nullptr; } } - - //TODO KILL KILL KILL - float Turret::GetMass() const { - return m_Mass + (m_MountedDevice ? m_MountedDevice->GetMass() : 0); - } - void Turret::SetID(const MOID newID) { - MovableObject::SetID(newID); - if (m_MountedDevice) - m_MountedDevice->SetID(newID); - } - void Turret::GetMOIDs(std::vector &MOIDs) const { - if (m_MountedDevice && m_MountedDevice->GetsHitByMOs()) - m_MountedDevice->GetMOIDs(MOIDs); - - Attachable::GetMOIDs(MOIDs); - } - void Turret::UpdateChildMOIDs(vector &MOIDIndex, MOID rootMOID, bool makeNewMOID) { - if (m_MountedDevice && m_MountedDevice->GetsHitByMOs()) - m_MountedDevice->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - - Attachable::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); - } } \ No newline at end of file diff --git a/Entities/Turret.h b/Entities/Turret.h index 9a63c4d50..743bec717 100644 --- a/Entities/Turret.h +++ b/Entities/Turret.h @@ -104,12 +104,6 @@ namespace RTE { void Update() override; #pragma endregion - - //These die soon - float GetMass() const override; - void SetID(const MOID newID) override; - void GetMOIDs(std::vector &MOIDs) const override; - protected: //This dies soon From bb1651226028009911ae128ced342b870ce4a3b0 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 7 Sep 2020 18:21:33 -0300 Subject: [PATCH 029/144] Cleaned up Leg and renamed various methods, updated rocket, human and crab to use renamed methods --- Entities/ACRocket.cpp | 12 +- Entities/ACrab.cpp | 8 +- Entities/AHuman.cpp | 4 +- Entities/Leg.cpp | 671 ++++++++++++++---------------------------- Entities/Leg.h | 484 +++++++++--------------------- 5 files changed, 383 insertions(+), 796 deletions(-) diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 39adaaaee..ccf49a6ea 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -834,11 +834,11 @@ void ACRocket::Update() m_pRLeg->SetJointPos(m_Pos + m_pRLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); /* Obsolete if (!m_pMThruster->IsEmitting()) - m_pRLeg->ReachToward(m_Pos + Vector(18, 40) * m_Rotation); + m_pRLeg->SetTargetOffset(m_Pos + Vector(18, 40) * m_Rotation); else - m_pRLeg->ReachToward(m_Pos + Vector(13, 40) * m_Rotation); + m_pRLeg->SetTargetOffset(m_Pos + Vector(13, 40) * m_Rotation); */ - m_pRLeg->ReachToward(m_pRFootGroup->GetLimbPos(m_HFlipped)); + m_pRLeg->SetTargetOffset(m_pRFootGroup->GetLimbPos(m_HFlipped)); m_pRLeg->Update(); m_Health -= m_pRLeg->CollectDamage(); } @@ -848,11 +848,11 @@ void ACRocket::Update() m_pLLeg->SetJointPos(m_Pos + m_pLLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); /* Obsolete if (!m_pMThruster->IsEmitting()) - m_pLLeg->ReachToward(m_Pos + Vector(-18, 40) * m_Rotation); + m_pLLeg->SetTargetOffset(m_Pos + Vector(-18, 40) * m_Rotation); else - m_pLLeg->ReachToward(m_Pos + Vector(-13, 40) * m_Rotation); + m_pLLeg->SetTargetOffset(m_Pos + Vector(-13, 40) * m_Rotation); */ - m_pLLeg->ReachToward(m_pLFootGroup->GetLimbPos(!m_HFlipped)); + m_pLLeg->SetTargetOffset(m_pLFootGroup->GetLimbPos(!m_HFlipped)); m_pLLeg->Update(); m_Health -= m_pLLeg->CollectDamage(); } diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index a00710f5d..eeaaa50c6 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -2798,7 +2798,7 @@ void ACrab::Update() m_pLFGLeg->SetJointPos(m_Pos + m_pLFGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pLFGLeg->EnableIdle(m_Status != UNSTABLE); - m_pLFGLeg->ReachToward(m_pLFGFootGroup->GetLimbPos(m_HFlipped)); + m_pLFGLeg->SetTargetOffset(m_pLFGFootGroup->GetLimbPos(m_HFlipped)); m_pLFGLeg->Update(); m_Health -= m_pLFGLeg->CollectDamage(); } @@ -2811,7 +2811,7 @@ void ACrab::Update() m_pLBGLeg->SetJointPos(m_Pos + m_pLBGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pLBGLeg->EnableIdle(m_Status != UNSTABLE); - m_pLBGLeg->ReachToward(m_pLBGFootGroup->GetLimbPos(m_HFlipped)); + m_pLBGLeg->SetTargetOffset(m_pLBGFootGroup->GetLimbPos(m_HFlipped)); m_pLBGLeg->Update(); m_Health -= m_pLBGLeg->CollectDamage(); } @@ -2821,7 +2821,7 @@ void ACrab::Update() m_pRFGLeg->SetHFlipped(m_HFlipped); m_pRFGLeg->SetJointPos(m_Pos + m_pRFGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pRFGLeg->EnableIdle(m_Status != UNSTABLE); - m_pRFGLeg->ReachToward(m_pRFGFootGroup->GetLimbPos(m_HFlipped)); + m_pRFGLeg->SetTargetOffset(m_pRFGFootGroup->GetLimbPos(m_HFlipped)); m_pRFGLeg->Update(); m_Health -= m_pRFGLeg->CollectDamage(); } @@ -2832,7 +2832,7 @@ void ACrab::Update() m_pRBGLeg->SetJointPos(m_Pos + m_pRBGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pRBGLeg->EnableIdle(m_Status != UNSTABLE); - m_pRBGLeg->ReachToward(m_pRBGFootGroup->GetLimbPos(m_HFlipped)); + m_pRBGLeg->SetTargetOffset(m_pRBGFootGroup->GetLimbPos(m_HFlipped)); m_pRBGLeg->Update(); m_Health -= m_pRBGLeg->CollectDamage(); } diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index dcb4d37dc..769f7ee06 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -4147,7 +4147,7 @@ void AHuman::Update() m_pFGLeg->SetJointPos(m_Pos + m_pFGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pFGLeg->EnableIdle(m_ProneState == NOTPRONE && m_Status != UNSTABLE); // if (!m_ArmClimbing[FGROUND]) - m_pFGLeg->ReachToward(m_pFGFootGroup->GetLimbPos(m_HFlipped)); + m_pFGLeg->SetTargetOffset(m_pFGFootGroup->GetLimbPos(m_HFlipped)); m_pFGLeg->Update(); m_Health -= m_pFGLeg->CollectDamage(); } @@ -4159,7 +4159,7 @@ void AHuman::Update() // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pBGLeg->EnableIdle(m_ProneState == NOTPRONE && m_Status != UNSTABLE); // if (!m_ArmClimbing[BGROUND]) - m_pBGLeg->ReachToward(m_pBGFootGroup->GetLimbPos(m_HFlipped)); + m_pBGLeg->SetTargetOffset(m_pBGFootGroup->GetLimbPos(m_HFlipped)); m_pBGLeg->Update(); m_Health -= m_pBGLeg->CollectDamage(); } diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index 46a2b44ff..feecf2e36 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -1,456 +1,237 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// File: Leg.cpp -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Source file for the Leg class. -// Project: Retro Terrain Engine -// Author(s): Daniel Tabar -// data@datarealms.com -// http://www.datarealms.com - - -////////////////////////////////////////////////////////////////////////////////////////// -// Inclusions of header files - #include "Leg.h" #include "PresetMan.h" namespace RTE { -ConcreteClassInfo(Leg, Attachable, 50) - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Clear -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Clears all the member variables of this Leg, effectively -// resetting the members of this abstraction level only. - -void Leg::Clear() -{ -// m_AnkleOffset.Reset(); - m_pFoot = 0; - m_ContractedOffset.Reset(); - m_ExtendedOffset.Reset(); - m_MinExtension = 0; - m_MaxExtension = 0; - m_CurrentNormalizedExtension = 0; - m_AnkleOffset.Reset(); - m_TargetOffset.Reset(); - m_IdleOffset.Reset(); - m_MoveSpeed = 0; - m_WillIdle = false; - m_DidReach = false; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes the Round object ready for use. - -int Leg::Create() -{ - if (MOSRotating::Create() < 0) - return -1; - - // Make sure the contracted offset is the one closer to the joint - if (m_ContractedOffset.GetMagnitude() > m_ExtendedOffset.GetMagnitude()) - { - Vector tempOffset = m_ContractedOffset; - m_ContractedOffset = m_ExtendedOffset; - m_ExtendedOffset = tempOffset; - } - - m_MinExtension = m_ContractedOffset.GetMagnitude(); - m_MaxExtension = m_ExtendedOffset.GetMagnitude(); - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Creates a Leg to be identical to another, by deep copy. - -int Leg::Create(const Leg &reference) { - if (reference.m_pFoot) { CloneHardcodedAttachable(reference.m_pFoot, this, static_cast>(&Leg::SetFoot)); } - Attachable::Create(reference); - - m_ContractedOffset = reference.m_ContractedOffset; - m_ExtendedOffset = reference.m_ExtendedOffset; - m_MinExtension = reference.m_MinExtension; - m_MaxExtension = reference.m_MaxExtension; - m_CurrentNormalizedExtension = reference.m_CurrentNormalizedExtension; - m_AnkleOffset = reference.m_AnkleOffset; - m_TargetOffset = reference.m_TargetOffset; - m_IdleOffset = reference.m_IdleOffset; - m_WillIdle = reference.m_WillIdle; - m_MoveSpeed = reference.m_MoveSpeed; - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: ReadProperty -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Reads a property value from a reader stream. If the name isn't -// recognized by this class, then ReadProperty of the parent class -// is called. If the property isn't recognized by any of the base classes, -// false is returned, and the reader's position is untouched. - -int Leg::ReadProperty(std::string propName, Reader &reader) { - if (propName == "Foot") { - const Entity *pObj = g_PresetMan.GetEntityPreset(reader); - if (pObj) { - m_pFoot = dynamic_cast(pObj->Clone()); - } - } else if (propName == "ContractedOffset") { - reader >> m_ContractedOffset; - m_MinExtension = m_ContractedOffset.GetMagnitude(); - } else if (propName == "ExtendedOffset") { - reader >> m_ExtendedOffset; - m_MaxExtension = m_ExtendedOffset.GetMagnitude(); - } else if (propName == "MaxLength") { - // For backward compatibiltiy with before - float maxLength; - reader >> maxLength; - - m_MinExtension = maxLength / 2; - m_ContractedOffset.SetXY(m_MinExtension, 0); - m_MaxExtension = maxLength; - m_ExtendedOffset.SetXY(m_MaxExtension, 0); - } else if (propName == "IdleOffset") { - reader >> m_IdleOffset; - } else if (propName == "WillIdle") { - reader >> m_WillIdle; - } else if (propName == "MoveSpeed") { - reader >> m_MoveSpeed; - } else { - return Attachable::ReadProperty(propName, reader); - } - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Save -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Saves the complete state of this Leg with a Writer for -// later recreation with Create(Reader &reader); - -int Leg::Save(Writer &writer) const -{ - Attachable::Save(writer); - - writer.NewProperty("Foot"); - writer << m_pFoot; - writer.NewProperty("ContractedOffset"); - writer << m_ContractedOffset; - writer.NewProperty("ExtendedOffset"); - writer << m_ExtendedOffset; - writer.NewProperty("IdleOffset"); - writer << m_IdleOffset; - writer.NewProperty("WillIdle"); - writer << m_WillIdle; - writer.NewProperty("MoveSpeed"); - writer << m_MoveSpeed; - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Destroy -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Destroys and resets (through Clear()) the Leg object. - -void Leg::Destroy(bool notInherited) -{ - if (!notInherited) - Attachable::Destroy(); - Clear(); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. - -void Leg::SetID(const MOID newID) -{ - MovableObject::SetID(newID); - if (m_pFoot) - m_pFoot->SetID(newID); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: ReachToward -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Rotates the leg so that it reaches after a point in scene coordinates. - -void Leg::ReachToward(const Vector &scenePoint) -{ - m_TargetOffset = scenePoint; -/* - if (m_HFlipped) { - m_Pos.m_X -= m_ParentOffset.m_X; - m_Pos.m_Y += m_ParentOffset.m_Y; - } - else - m_Pos += m_ParentOffset; - - Vector reachVec(m_TargetOffset - m_Pos); - return reachVec.GetMagnitude() <= m_MaxExtension && - reachVec.GetMagnitude() >= (m_MaxExtension / 2); -*/ -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: BendLeg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Bends the leg to the appropriate position depending on the ankle -// offset. - -void Leg::BendLeg() -{ - if (m_FrameCount == 1) - { - m_Frame = 0; - return; - } - - // Set correct frame for leg bend. - float range = m_MaxExtension - m_MinExtension; - m_CurrentNormalizedExtension = (m_AnkleOffset.GetMagnitude() - (m_MaxExtension - range)) / range; - - if (m_CurrentNormalizedExtension < 0) - m_CurrentNormalizedExtension = 0; - else if (m_CurrentNormalizedExtension > 1.0) - m_CurrentNormalizedExtension = 1.0; - - m_Frame = floorf(m_CurrentNormalizedExtension * m_FrameCount); - - // Clamp - if (m_Frame >= m_FrameCount) - m_Frame = m_FrameCount - 1; - - RTEAssert(m_Frame >= 0 && m_Frame < m_FrameCount, "Frame is out of bounds!"); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. - -void Leg::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) -{ - // Detach foot and let loose - if (m_pFoot) - { - RemoveAttachable(m_pFoot); - g_MovableMan.AddParticle(m_pFoot); - m_pFoot = 0; - } - - Attachable::GibThis(impactImpulse, internalBlast, pIgnoreMO); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Update -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Updates this Leg. Supposed to be done every frame. - -void Leg::Update() -{ - // Update basic metrics from parent. - Attachable::Update(); - - if (!m_Parent) - { - if (m_pFoot) - { - m_AnkleOffset.SetXY(m_MaxExtension * 0.60, 0); - m_AnkleOffset.RadRotate((m_HFlipped ? c_PI : 0) + m_Rotation.GetRadAngle()); - BendLeg(); - m_pFoot->SetJointPos(m_JointPos.GetFloored() + m_AnkleOffset); - m_pFoot->SetRotAngle(m_Rotation.GetRadAngle() + c_PI / 2); - m_pFoot->Update(); - } - } - else - { - // Attached, so act like it - - Vector target = g_SceneMan.ShortestDistance(m_JointPos, m_TargetOffset);// m_Pos + RotateOffset(m_JointOffset)); - // Check if target is within leg's length. - if (target.GetMagnitude() <= m_MaxExtension && target.m_Y >= -3/* && target.GetFloored() != m_AnkleOffset.GetFloored()*/) - { - Vector moveVec(target - m_AnkleOffset); - m_AnkleOffset += moveVec * m_MoveSpeed; - m_DidReach = true; - } - else /*if (m_IdleOffset.GetXFlipped(m_HFlipped).GetFloored() != m_AnkleOffset.GetFloored())*/ - { - if (target.m_Y < -3 && m_WillIdle) - { - Vector moveVec(m_IdleOffset.GetXFlipped(m_HFlipped) - m_AnkleOffset); - m_AnkleOffset += moveVec * m_MoveSpeed; -// m_AnkleOffset = m_IdleOffset.GetXFlipped(m_HFlipped); - } - else - m_AnkleOffset = target; - m_DidReach = false; - } - - // Cap foot distance to what the Leg allows - ConstrainFoot(); - - // Set the basic rotation - m_Rotation = (m_HFlipped ? c_PI : 0) + m_AnkleOffset.GetAbsRadAngle(); - - // Apply the extra rotation needed to line up the sprite with the leg extension line - - // Get normalized scalar for how much of the difference in angle between the contracted and extrended offsets should be applied - // EaseOut is used to get the sine effect needed - float extraRotationRatio = (EaseOut(m_MinExtension, m_MaxExtension, m_CurrentNormalizedExtension) - m_MinExtension) / (m_MaxExtension - m_MinExtension); - // The contracted offset's inverse angle is the base for the rotation correction - float extraRotation = -(m_ContractedOffset.GetAbsRadAngle()); - // Get the actual amount of extra rotation correction needed from the ratio, somewhere on the arc between contracted and extended angles - // This is negative because it's a correction, the bitmap needs to rotate back to align the ankle with where it's supposed to be in the sprite - extraRotation -= (m_ExtendedOffset.GetAbsRadAngle() - m_ContractedOffset.GetAbsRadAngle()) * extraRotationRatio; - // Apply the extra rotation - m_Rotation.SetRadAngle(m_Rotation.GetRadAngle() + (m_HFlipped ? -extraRotation : extraRotation)); - -// Don't apply state changes to BITMAP anywhere else than Draw(). -// m_aSprite->SetAngle(m_Rotation); -// m_aSprite->SetScale(m_Scale); - - BendLeg(); - - if (m_pFoot) - { - m_pFoot->SetHFlipped(m_HFlipped); -// Vector rotatedOff(m_pFoot->GetParentOffset()); -// if (m_HFlipped) -// rotatedOff.m_X = -rotatedOff.m_X; -// rotatedOff.RadRotate(m_Rotation); -// m_pFoot->SetPos(m_Pos + rotatedOff.GetFloored()); -// m_pFoot->SetJointPos(m_Pos.GetFloored() + RotateOffset(m_JointOffset) + m_AnkleOffset); - m_pFoot->SetJointPos(m_JointPos + m_AnkleOffset); - if (!m_HFlipped && target.m_X < -10 || - m_HFlipped && target.m_X > 10) { - m_pFoot->SetFrame(3); - } - else if (!m_HFlipped && target.m_X < -6 || - m_HFlipped && target.m_X > 6) { - m_pFoot->SetFrame(2); - m_pFoot->SetRotAngle(0); - } - else if (!m_HFlipped && target.m_X > 6 || - m_HFlipped && target.m_X < -6) { - m_pFoot->SetFrame(1); - m_pFoot->SetRotAngle(0); -// m_pFoot->SetRotAngle(m_Rotation + (m_HFlipped ? -c_HalfPI : c_HalfPI)); - } - else { - m_pFoot->SetFrame(0); - m_pFoot->SetRotAngle(0.0); - } - m_pFoot->Update(); - } - } -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. - -void Leg::UpdateChildMOIDs(vector &MOIDIndex, - MOID rootMOID, - bool makeNewMOID) -{ -// if (m_pFoot) -// m_pFoot->UpdateMOID(MOIDIndex, false); - - Attachable::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - -void Leg::GetMOIDs(std::vector &MOIDs) const -{ - Attachable::GetMOIDs(MOIDs); -} + ConcreteClassInfo(Leg, Attachable, 50) + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + //TODO Organize these + void Leg::Clear() { + m_Foot = 0; + m_ContractedOffset.Reset(); + m_ExtendedOffset.Reset(); + m_MinExtension = 0; + m_MaxExtension = 0; + m_CurrentNormalizedExtension = 0; + m_TargetOffset.Reset(); + m_IdleOffset.Reset(); + m_CurrentAnkleOffset.Reset(); + m_WillIdle = false; + m_MoveSpeed = 0; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Leg::Create() { + if (MOSRotating::Create() < 0) { + return -1; + } + + if (m_ContractedOffset.GetMagnitude() > m_ExtendedOffset.GetMagnitude()) { + std::swap(m_ContractedOffset, m_ExtendedOffset); //TODO dunno if this'll work, swapping if needed so contracted always < extended + } + + m_MinExtension = m_ContractedOffset.GetMagnitude(); + m_MaxExtension = m_ExtendedOffset.GetMagnitude(); + + return 0; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Leg::Create(const Leg &reference) { + if (reference.m_Foot) { CloneHardcodedAttachable(reference.m_Foot, this, static_cast>(&Leg::SetFoot)); } + Attachable::Create(reference); + + m_ContractedOffset = reference.m_ContractedOffset; + m_ExtendedOffset = reference.m_ExtendedOffset; + m_MinExtension = reference.m_MinExtension; + m_MaxExtension = reference.m_MaxExtension; + m_CurrentNormalizedExtension = reference.m_CurrentNormalizedExtension; + m_TargetOffset = reference.m_TargetOffset; + m_IdleOffset = reference.m_IdleOffset; + m_CurrentAnkleOffset = reference.m_CurrentAnkleOffset; + m_WillIdle = reference.m_WillIdle; + m_MoveSpeed = reference.m_MoveSpeed; + + return 0; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Leg::ReadProperty(std::string propName, Reader &reader) { + if (propName == "Foot") { + const Entity *pObj = g_PresetMan.GetEntityPreset(reader); + if (pObj) { + m_Foot = dynamic_cast(pObj->Clone()); + } + } else if (propName == "ContractedOffset") { + reader >> m_ContractedOffset; + m_MinExtension = m_ContractedOffset.GetMagnitude(); + } else if (propName == "ExtendedOffset") { + reader >> m_ExtendedOffset; + m_MaxExtension = m_ExtendedOffset.GetMagnitude(); + } else if (propName == "MaxLength") { + //TODO Get rid of this, it's used only for rocket leg I think + float maxLength; + reader >> maxLength; + + m_MinExtension = maxLength / 2; + m_ContractedOffset.SetXY(m_MinExtension, 0); + m_MaxExtension = maxLength; + m_ExtendedOffset.SetXY(m_MaxExtension, 0); + } else if (propName == "IdleOffset") { + reader >> m_IdleOffset; + } else if (propName == "WillIdle") { + reader >> m_WillIdle; + } else if (propName == "MoveSpeed") { + reader >> m_MoveSpeed; + } else { + return Attachable::ReadProperty(propName, reader); + } + + return 0; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Leg::Save(Writer &writer) const { + Attachable::Save(writer); + + writer.NewProperty("Foot"); + writer << m_Foot; + writer.NewProperty("ContractedOffset"); + writer << m_ContractedOffset; + writer.NewProperty("ExtendedOffset"); + writer << m_ExtendedOffset; + writer.NewProperty("IdleOffset"); + writer << m_IdleOffset; + writer.NewProperty("WillIdle"); + writer << m_WillIdle; + writer.NewProperty("MoveSpeed"); + writer << m_MoveSpeed; + + return 0; + } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void Leg::SetFoot(Attachable *newFoot) { - if (newFoot) { - RemoveAttachable(m_pFoot); - m_pFoot = newFoot; - AddAttachable(newFoot); - } -} + void Leg::SetFoot(Attachable *newFoot) { + if (newFoot) { + RemoveAttachable(m_Foot); + m_Foot = newFoot; + AddAttachable(newFoot); + } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Leg::Update() { + Attachable::Update(); + + UpdateCurrentAnkleOffset(); + + UpdateLegRotation(); + + UpdateFrameAndNormalizedExtension(); + + UpdateFootFrameJointPositionAndRotation(); + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Leg::UpdateCurrentAnkleOffset() { + if (IsAttached()) { + Vector targetPosition = g_SceneMan.ShortestDistance(m_JointPos, m_TargetOffset, g_SceneMan.SceneWrapsX()); + if (m_WillIdle && targetPosition.m_Y < -3) { + targetPosition = m_IdleOffset.GetXFlipped(m_HFlipped); + } + + //TODO DELETE IF NEVER TRIGGERED ELSE INTEGRATE + if (targetPosition.GetMagnitude() > m_MaxExtension) { + int a = 0; + } + + Vector distanceToTargetPosition(targetPosition - m_CurrentAnkleOffset); + distanceToTargetPosition.SetMagnitude(std::min(distanceToTargetPosition.GetMagnitude(), m_MaxExtension)); + m_CurrentAnkleOffset += distanceToTargetPosition * m_MoveSpeed; + + //TODO DELETE IF NEVER TRIGGERED ELSE INTEGRATE BETTER + if (m_CurrentAnkleOffset.GetMagnitude() > m_MaxExtension) { + m_CurrentAnkleOffset.SetMagnitude(m_MaxExtension); + } else if (m_CurrentAnkleOffset.GetMagnitude() < m_MinExtension) { + m_CurrentAnkleOffset.SetMagnitude(m_MinExtension + 0.1F); + } + } else { + m_CurrentAnkleOffset.SetXY(m_MaxExtension * 0.60F, 0); + m_CurrentAnkleOffset.RadRotate((m_HFlipped ? c_PI : 0) + m_Rotation.GetRadAngle()); + } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Leg::UpdateLegRotation() { + if (IsAttached()) { + m_Rotation = m_CurrentAnkleOffset.GetAbsRadAngle() + (m_HFlipped ? c_PI : 0); + + // Get normalized scalar for how much of the difference in angle between the contracted and extrended offsets should be applied. EaseOut is used to get the sine effect needed + float extraRotationRatio = (EaseOut(m_MinExtension, m_MaxExtension, m_CurrentNormalizedExtension) - m_MinExtension) / (m_MaxExtension - m_MinExtension); + + // The contracted offset's inverse angle is the base for the rotation correction + float extraRotation = -(m_ContractedOffset.GetAbsRadAngle()); + + // Get the actual amount of extra rotation correction needed from the ratio, somewhere on the arc between contracted and extended angles. + // This is negative because it's a correction, the bitmap needs to rotate back to align the ankle with where it's supposed to be in the sprite + extraRotation -= (m_ExtendedOffset.GetAbsRadAngle() - m_ContractedOffset.GetAbsRadAngle()) * extraRotationRatio; + + m_Rotation.SetRadAngle(m_Rotation.GetRadAngle() + extraRotation * static_cast(GetFlipFactor())); + } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Leg::UpdateFrameAndNormalizedExtension() { + if (m_FrameCount == 1) { + m_Frame = 0; + return; + } + + //TODO Test out the math here and with frame setting stuff, I don't trust/understand this and I wonder if we can maybe change the frame stuff to build the clamping in + float extensionRange = m_MaxExtension - m_MinExtension; + m_CurrentNormalizedExtension = (m_CurrentAnkleOffset.GetMagnitude() - (m_MaxExtension - extensionRange)) / extensionRange; + Clamp(m_CurrentNormalizedExtension, 1.0F, 0.0F); + + m_Frame = std::min(m_FrameCount - 1, static_cast(floorf(m_CurrentNormalizedExtension * static_cast(m_FrameCount)))); + } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this Leg's current graphical representation to a -// BITMAP of choice. - -void Leg::Draw(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode, - bool onlyPhysical) const -{ - if (m_pFoot && mode != g_DrawMOID && !m_pFoot->IsDrawnAfterParent()) - m_pFoot->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - Attachable::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (m_pFoot && mode != g_DrawMOID && m_pFoot->IsDrawnAfterParent()) - m_pFoot->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: ConstrainFoot -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes sure the foot distance is constrained between the mix and max -// extension of this Leg. - -bool Leg::ConstrainFoot() -{ - if (m_AnkleOffset.GetMagnitude() > m_MaxExtension) - { - m_AnkleOffset.SetMagnitude(m_MaxExtension); - return false; - } - else if (m_AnkleOffset.GetMagnitude() < m_MinExtension) { - m_AnkleOffset.SetMagnitude(m_MinExtension + 0.1); - return true; - } - else - return true; -} - -} // namespace RTE \ No newline at end of file + void Leg::UpdateFootFrameJointPositionAndRotation() { + if (m_Foot) { + m_Foot->SetJointPos(m_JointPos + m_CurrentAnkleOffset); //TODO parentoffset for feet is left at (0,0). It may be able to be used here (need to understand how rotation is done right now!) so jointpos stuff can live in Attachable entirely. + + if (IsAttached()) { + //TODO I wonder if we could use m_CurrentAnkleOffset for this instead? + float targetHorizontalDistanceAccountingForFlipping = g_SceneMan.ShortestDistance(m_JointPos, m_TargetOffset, g_SceneMan.SceneWrapsX()).m_X * static_cast(GetFlipFactor()); + if (targetHorizontalDistanceAccountingForFlipping < -10) { + m_Foot->SetFrame(3); + //TODO this should probably be setting rotangle to 0 too, check if it's changing at any point in time and if not, unify + } else if (targetHorizontalDistanceAccountingForFlipping < -6) { + m_Foot->SetFrame(2); + m_Foot->SetRotAngle(0.0F); + } else if (targetHorizontalDistanceAccountingForFlipping > 6) { + m_Foot->SetFrame(1); + m_Foot->SetRotAngle(0.0F); + } else { + m_Foot->SetFrame(0); + m_Foot->SetRotAngle(0.0F); + } + } else { + m_Foot->SetRotAngle(m_Rotation.GetRadAngle() + c_PI / 2); + } + //m_Foot->Update(); //TODO this may need reorganizing + } + } +} \ No newline at end of file diff --git a/Entities/Leg.h b/Entities/Leg.h index b88d4d3ab..ef12beaae 100644 --- a/Entities/Leg.h +++ b/Entities/Leg.h @@ -1,348 +1,154 @@ #ifndef _RTELEG_ #define _RTELEG_ -////////////////////////////////////////////////////////////////////////////////////////// -// File: Leg.h -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Header file for the Leg class. -// Project: Retro Terrain Engine -// Author(s): Daniel Tabar -// data@datarealms.com -// http://www.datarealms.com - - -////////////////////////////////////////////////////////////////////////////////////////// -// Inclusions of header files - #include "Attachable.h" -namespace RTE -{ - -class HeldDevice; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Class: Leg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: A detatchable leg that will be controlled by LimbPath:s. -// Parent(s): Attachable. -// Class history: 05/30/2002 Leg created. - -class Leg: - public Attachable -{ - -////////////////////////////////////////////////////////////////////////////////////////// -// Public member variable, method and friend function declarations - -public: - - -// Concrete allocation and cloning definitions -EntityAllocation(Leg) -SerializableOverrideMethods -ClassInfoGetters - -////////////////////////////////////////////////////////////////////////////////////////// -// Constructor: Leg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Constructor method used to instantiate a Leg object in system -// memory. Create() should be called before using the object. -// Arguments: None. - - Leg() { Clear(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Destructor: ~Leg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Destructor method used to clean up a Leg object before deletion -// from system memory. -// Arguments: None. - - ~Leg() override { Destroy(true); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes the Leg object ready for use. -// Arguments: None. -// Return value: An error return value signaling sucess or any particular failure. -// Anything below 0 is an error signal. - - int Create() override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Create -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Creates a Leg to be identical to another, by deep copy. -// Arguments: A reference to the Leg to deep copy. -// Return value: An error return value signaling sucess or any particular failure. -// Anything below 0 is an error signal. - - int Create(const Leg &reference); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Reset -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Resets the entire Leg, including its inherited members, to their -// default settings or values. -// Arguments: None. -// Return value: None. - - void Reset() override { Clear(); Attachable::Reset(); } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Destroy -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Destroys and resets (through Clear()) the SceneLayer object. -// Arguments: Whether to only destroy the members defined in this derived class, or -// to destroy all inherited members also. -// Return value: None. - - void Destroy(bool notInherited = false) override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetAnklePos -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the position of the ankle of this Leg as an absolute scene coord. -// Arguments: None. -// Return value: Vector with the current absolute scene ankle position. - - Vector GetAnklePos() { return m_Pos + m_AnkleOffset; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetMaxLength -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the max length this leg can reach from its socket to the foot. -// Arguments: None. -// Return value: The max length of reach, in pixels, of this leg. - - float GetMaxLength() const { return m_MaxExtension; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. -// Arguments: A MOID specifying the MOID that this MovableObject is -// assigned for this frame. -// Return value: None. - - void SetID(const MOID newID) override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetIdleOffset -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the offset from the position of this Leg to which its foot will -// go when not holding a device and not able to reach a certain target. -// Arguments: Vector with the new idle offset relative to the position of this Leg. -// Return value: None. - - void SetIdleOffset(const Vector &newIdleOffset) { m_IdleOffset = newIdleOffset; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: EnableIdle -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets this to go into idle offset mode if the target appears to be above -// the joint of the leg. -// Arguments: Whetehr to enable the idling if the target is above the joint -// Return value: None. - - void EnableIdle(bool idle = true) { m_WillIdle = idle; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: ReachToward -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Rotates the leg so that it reaches after a point in scene coordinates. -// Must be called AFTER SetPos for this frame if the return value is to -// be accurate. -// Arguments: The point to reach after. If (0, 0), reaching is deactivated. -// Return value: None. - - void ReachToward(const Vector &scenePoint); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: DidReach -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this Leg actually reached the reach target last -// Update(). -// Arguments: None. -// Return value: Whether.the Leg was able to actually reach the point or not. - - bool DidReach() { return m_DidReach; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: BendLeg -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Bends the leg to the appropriate position depending on the ankle -// offset. -// Arguments: None. -// Return value: None. - - void BendLeg(); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Update -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Updates this MovableObject. Supposed to be done every frame. -// Arguments: None. -// Return value: None. - - void Update() override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this Leg's current graphical representation to a -// BITMAP of choice. -// Arguments: A pointer to a BITMAP to draw on. -// The absolute position of the target bitmap's upper left corner in the Scene. -// In which mode to draw in. See the DrawMode enumeration for the modes. -// Whether to not draw any extra 'ghost' items of this MovableObject, -// indicator arrows or hovering HUD text and so on. -// Return value: None. - - void Draw(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - - void GetMOIDs(std::vector &MOIDs) const override; +namespace RTE { + class HeldDevice; /// - /// Gets the foot of this Leg. + /// A detatchable leg that will be controlled by LimbPaths. /// - /// A pointer to foot of this Leg. Ownership is NOT transferred! - Attachable * GetFoot() const { return m_pFoot; } - - /// - /// Sets the foot for this Leg. Ownership IS transferred! - /// - /// The new foot to use. - void SetFoot(Attachable *newFoot); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Protected member variable and method declarations - -protected: - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: ConstrainFoot -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes sure the foot distance is constrained between the mix and max -// extension of this Leg. -// Arguments: None. -// Return value: Whether.the Foot already was within the reach range of this Leg or not. - - bool ConstrainFoot(); - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. -// Arguments: The MOID index to register itself and its children in. -// The MOID of the root MO of this MO, ie the highest parent of this MO. -// 0 means that this MO is the root, ie it is owned by MovableMan. -// Whether this MO should make a new MOID to use for itself, or to use -// the same as the last one in the index (presumably its parent), -// Return value: None. - - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; - - - // Member variables - static Entity::ClassInfo m_sClass; -// // The location of the 'foot' in relation to the MovableObject::m_Pos -// Vector m_FootPos; - // The foot attachable. - Attachable *m_pFoot; - // The offset from the joint where the ankle contracts to in the sprite - Vector m_ContractedOffset; - // The offset from the joint where the ankle extends to in the sprite - Vector m_ExtendedOffset; - // Precalculated min and max extensions of the leg (from the joint) based ont he contracted and extended offsets - float m_MinExtension; - float m_MaxExtension; - // normalized scalar of where the ankle offset's magnitude is between the min and max extensions - float m_CurrentNormalizedExtension; - // Current offset from the joint to the ankle where the foot should be - Vector m_AnkleOffset; - // The target offset that this Leg's foot is reaching after. - // If (0, 0), the Leg is currently not reaching after anything. - Vector m_TargetOffset; - // The target offset from m_Pos that this Leg's foot is reaching after when - // not reaching for or holding anything else. - Vector m_IdleOffset; - // How fast the leg moves to a reach target, - // on a scale from 0.0 (frozen) to 1.0 (instantly there). - float m_MoveSpeed; - // Whether this will go to idle position if the target is above the joint - bool m_WillIdle; - // Whether this Leg reaached the reach target last Update. - bool m_DidReach; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Private member variable and method declarations - -private: - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: Clear -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Clears all the member variables of this Leg, effectively -// resetting the members of this abstraction level only. -// Arguments: None. -// Return value: None. - - void Clear(); - - - // Disallow the use of some implicit methods. - Leg(const Leg &reference) {} - Leg & operator=(const Leg &rhs) {} - -}; - -} // namespace RTE - -#endif // File \ No newline at end of file + class Leg : public Attachable { + + public: + EntityAllocation(Leg) + SerializableOverrideMethods + ClassInfoGetters + +#pragma region Creation + /// + /// Constructor method used to instantiate a Leg object in system memory. Create() should be called before using the object. + /// + Leg() { Clear(); } + + /// + /// Makes the Leg object ready for use. + /// + /// An error return value signaling sucess or any particular failure. Anything below 0 is an error signal. + int Create() override; + + /// + /// Creates a Leg to be identical to another, by deep copy. + /// + /// A reference to the Leg to deep copy. + /// An error return value signaling sucess or any particular failure. Anything below 0 is an error signal. + int Create(const Leg &reference); +#pragma endregion + +#pragma region Destruction + /// + /// Destructor method used to clean up a Leg object before deletion from system memory. + /// + ~Leg() override { Destroy(true); } + + /// + /// Destroys and resets (through Clear()) the Leg object. + /// + /// Whether to only destroy the members defined in this derived class, or to destroy all inherited members also. + void Destroy(bool notInherited = false) override { if (!notInherited) { Attachable::Destroy(); } Clear(); } + + /// + /// Resets the entire Leg, including its inherited members, to their default settings or values. + /// + void Reset() override { Clear(); Attachable::Reset(); } +#pragma endregion + +#pragma region Getters and Setters + /// + /// Gets the foot of this Leg. + /// + /// A pointer to foot of this Leg. Ownership is NOT transferred! + Attachable *GetFoot() const { return m_Foot; } + + /// + /// Sets the foot for this Leg. Ownership IS transferred! + /// + /// The new foot to use. + void SetFoot(Attachable *newFoot); + + /// + /// Gets the max length this Leg can reach from its socket to the foot. + /// + /// The max length of reach, in pixels, of this Leg. + float GetMaxLength() const { return m_MaxExtension; } + + //TODO I think this is in absolute scene coordinates actually, since it works based off of joint pos not joint offset. Look into this and update accordingly. Also look at the member variable, the (0, 0) thing seems wrong. + /// + /// Sets the point the Leg should move towards, in relative coordinates. + /// + /// The offset the Leg should move towards. + void SetTargetOffset(const Vector &targetOffset) { m_TargetOffset = targetOffset; } + + /// + /// Sets this to go into idle offset mode if the target appears to be above the joint of the Leg. + /// + /// Whether to enable idling if the target offset is above the joint. + void EnableIdle(bool idle = true) { m_WillIdle = idle; } +#pragma endregion + + /// + /// Updates this Leg. Supposed to be done every frame. + /// + void Update() override; + + protected: + + static Entity::ClassInfo m_sClass; //!< ClassInfo for this class. + + Attachable *m_Foot; //!< Pointer to the foot attachable of this Leg. + + Vector m_ContractedOffset; //!< The offset from the joint where the ankle contracts to in the sprite. + Vector m_ExtendedOffset; //!< The offset from the joint where the ankle extends to in the sprite. + + float m_MinExtension; //!< Precalculated min extension of the Leg (from the joint) based on the contracted offset. + float m_MaxExtension; //!< Precalculated max extension of the Leg (from the joint) based on the extended offset. + float m_CurrentNormalizedExtension; //!< Normalized scalar of where the ankle offset's magnitude is between the min and max extensions + + Vector m_TargetOffset; //!< The target offset that this Leg's foot is moving towards. If (0, 0), the Leg will not try towards anything. + Vector m_IdleOffset; //!< The target offset from m_Pos that this Leg's foot is reaching towards when not reaching for or anything else. + + Vector m_CurrentAnkleOffset; //!< Current offset from the joint to the ankle where the foot should be. + + bool m_WillIdle; //!< Whether the Leg will go to idle position if the target is above the joint. + float m_MoveSpeed; //!< How fast the Leg moves to a reach target, 0 means it doesn't and 1 means it moves instantly. + + private: + + /// + /// Updates the current ankle offset for this Leg. Should only be called from Update. + /// If the Leg is attached, the current ankle offset is based on the target offset and move speed, and whether the Leg should idle or not, otherwise it puts it in a reasonable position. + /// + void UpdateCurrentAnkleOffset(); + + /// + /// Updates the rotation of the Leg. Should only be called from Update. + /// If the Leg is attached, this applies extra rotation to line up the Leg's sprite with its extension line, otherwise it does nothing. + /// + void UpdateLegRotation(); + + /// + /// Sets the Leg's frame to the appropriate one based on its current extension, and updates the normalized extension value. Should only be called from Update. + /// Works the same whether attached or not. + /// + void UpdateFrameAndNormalizedExtension(); + + /// + /// Updates the frame, joint position and rotation of the Leg's foot Attachable. Should only be called from Update. + /// If the Leg is attached, the rotation and frame depend on the target offset, otherwise the rotation is set to be perpendicular to the Leg. + /// The joint position is always updated to include the current ankle offset so the foot Attachable stays in the appropriate position. + /// + void UpdateFootFrameJointPositionAndRotation(); + + /// + /// Clears all the member variables of this Leg, effectively resetting the members of this abstraction level only. + /// + void Clear(); + + // Disallow the use of some implicit methods. + Leg(const Leg &reference) {} + Leg &operator=(const Leg &rhs) {} + }; +} +#endif \ No newline at end of file From b5f9c578dc2ad1a7a7e5f99bf260f1cfd40d6dca Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 8 Sep 2020 00:56:05 -0300 Subject: [PATCH 030/144] Added Attachable flag for whether the attachable should be drawn normally by its parent, or if it requires some special handling (e.g. AEmitter flash). Used this in AEmitter and HDFirearm Used this flag to determine attachable drawing in MOSR and also cleaned up MOSR Update and Draw a little bit Also cleaned up AEmitter and HDFirearm, and some minor typos in Attachable Cleaned up Turret too --- Entities/AEmitter.cpp | 17 +-------- Entities/AEmitter.h | 13 ------- Entities/Attachable.cpp | 2 + Entities/Attachable.h | 21 ++++++++-- Entities/HDFirearm.cpp | 82 +++++----------------------------------- Entities/HDFirearm.h | 46 ---------------------- Entities/MOSRotating.cpp | 75 ++++++++++++++---------------------- 7 files changed, 59 insertions(+), 197 deletions(-) diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index af3faa148..4a2ede845 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -169,6 +169,7 @@ int AEmitter::ReadProperty(std::string propName, Reader &reader) { const Entity *pObj = g_PresetMan.GetEntityPreset(reader); if (pObj) { m_pFlash = dynamic_cast(pObj->Clone()); + m_pFlash->SetDrawnNormallyByParent(false); } } else if (propName == "FlashScale") { reader >> m_FlashScale; @@ -361,22 +362,6 @@ float AEmitter::EstimateImpulse(bool burst) return m_AvgImpulse * throttleFactor; } - -/* -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. - -void AEmitter::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) -{ - - - Attachable::GibThis(impactImpulse, internalBlast, pIgnoreMO); -} -*/ - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AEmitter::SetFlash(Attachable *newFlash) { diff --git a/Entities/AEmitter.h b/Entities/AEmitter.h index 88f03d9d7..552cc81c4 100644 --- a/Entities/AEmitter.h +++ b/Entities/AEmitter.h @@ -450,19 +450,6 @@ ClassInfoGetters void ResetAllTimers() override { Attachable::ResetAllTimers(); m_BurstTimer.Reset(); m_LastEmitTmr.Reset(); } -/* -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; -*/ ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Update diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 645752965..caf05af74 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -15,6 +15,7 @@ namespace RTE { m_Parent = 0; m_ParentOffset.Reset(); m_DrawAfterParent = true; + m_DrawnNormallyByParent = true; m_TransfersDamageToParent = false; m_DeleteWithParent = false; @@ -43,6 +44,7 @@ namespace RTE { m_Parent = reference.m_Parent; m_ParentOffset = reference.m_ParentOffset; m_DrawAfterParent = reference.m_DrawAfterParent; + m_DrawnNormallyByParent = reference.m_DrawnNormallyByParent; m_TransfersDamageToParent = reference.m_TransfersDamageToParent; m_DeleteWithParent = reference.m_DeleteWithParent; diff --git a/Entities/Attachable.h b/Entities/Attachable.h index f8fe11167..fb896f03c 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -108,6 +108,20 @@ namespace RTE { /// Whether this Attachable is to be drawn after its parent or not. bool IsDrawnAfterParent() const override { return m_DrawAfterParent; } + /// + /// Gets whether this Attachable should be drawn normally by its parent. + /// Some attachables (e.g. AEmitter flashes) require custom handling for when they should or shouldn't draw, to be done by the specific parent class. + /// + /// Whether this Attachable should be drawn normally by its parent. + bool IsDrawnNormallyByParent() const { return m_DrawnNormallyByParent; } + + /// + /// Sets whether this Attachable should be drawn normally by its parent. + /// Some attachables (e.g. AEmitter flashes) require custom handling for when they should or shouldn't draw, to be done by the specific parent class. + /// + /// Whether this Attachable should be drawn normally by its parent. + void SetDrawnNormallyByParent(bool drawnNormallyByParent) { m_DrawnNormallyByParent = drawnNormallyByParent; } + /// /// Gets whether this Attachable will collect its damage and transfer it to its parent if attached. Transferred damage accounts for the Attachable's damage multiplier. /// @@ -121,9 +135,9 @@ namespace RTE { void SetTransfersDamageToParent(bool transfersDamageToParent) { m_TransfersDamageToParent = transfersDamageToParent; } /// - /// Gets whether this attachable will be deleted automatically when its parent is being deleted or not. + /// Gets whether this Attachable will be deleted automatically when its parent is being deleted or not. /// - /// Whether this attachable is marked to be deleted along with it's parent or not. + /// Whether this Attachable is marked to be deleted along with it's parent or not. bool ToDeleteWithParent() const { return m_DeleteWithParent; } #pragma endregion @@ -326,8 +340,9 @@ namespace RTE { MOSRotating *m_Parent; //!< Pointer to the MOSRotating this attachable is attached to. Vector m_ParentOffset; //!< The offset from the parent's Pos to the joint point this Attachable is attached with. bool m_DrawAfterParent; //!< Whether to draw this Attachable after (in front of) or before (behind) the parent. + bool m_DrawnNormallyByParent; //!< Whether this Attachable will be be drawn normally when attached, or will require special handling by some non-MOSR parent type. bool m_TransfersDamageToParent; //(pObj->Clone()); + m_pFlash->SetDrawnNormallyByParent(false); } } else if (propName == "FireSound") { reader >> m_FireSound; @@ -291,18 +292,6 @@ void HDFirearm::Destroy(bool notInherited) Clear(); } - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this HDFirearm, including the mass of Magazine -// may have inserted. - -float HDFirearm::GetMass() const -{ - return m_pMagazine ? m_Mass + m_pMagazine->GetMass() : m_Mass; -} - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void HDFirearm::SetMagazine(Attachable *newMagazine) { @@ -522,19 +511,6 @@ void HDFirearm::RestDetection() } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. - -void HDFirearm::SetID(const MOID newID) -{ - MovableObject::SetID(newID); - if (m_pMagazine) - m_pMagazine->SetID(newID); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Activate ////////////////////////////////////////////////////////////////////////////////////////// @@ -1040,39 +1016,6 @@ void HDFirearm::Update() } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. - -void HDFirearm::UpdateChildMOIDs(vector &MOIDIndex, - MOID rootMOID, - bool makeNewMOID) -{ - if (m_pMagazine && m_pMagazine->GetsHitByMOs()) - m_pMagazine->UpdateMOID(MOIDIndex, m_RootMOID, false); - - HeldDevice::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - -void HDFirearm::GetMOIDs(std::vector &MOIDs) const -{ - if (m_pMagazine && m_pMagazine->GetsHitByMOs()) - m_pMagazine->GetMOIDs(MOIDs); - - HeldDevice::GetMOIDs(MOIDs); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: EstimateDigStrenght ////////////////////////////////////////////////////////////////////////////////////////// @@ -1093,32 +1036,25 @@ float HDFirearm::EstimateDigStrenght() // Description: Draws this HDFirearm's current graphical representation to a // BITMAP of choice. -void HDFirearm::Draw(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode, - bool onlyPhysical) const -{ - if (m_pMagazine && !m_pMagazine->IsDrawnAfterParent()) - m_pMagazine->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (m_pFlash && m_FireFrame && !m_pFlash->IsDrawnAfterParent() && mode == g_DrawColor && !onlyPhysical) +void HDFirearm::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { + if (m_pFlash && m_FireFrame && !m_pFlash->IsDrawnAfterParent() && mode == g_DrawColor && !onlyPhysical) { m_pFlash->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + } HeldDevice::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pMagazine && m_pMagazine->IsDrawnAfterParent()) - m_pMagazine->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (m_pFlash && m_FireFrame && m_pFlash->IsDrawnAfterParent() && mode == g_DrawColor && !onlyPhysical) + if (m_pFlash && m_FireFrame && m_pFlash->IsDrawnAfterParent() && mode == g_DrawColor && !onlyPhysical) { m_pFlash->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + } // Fudge the muzzle pos forward a little bit so the glow aligns nicely Vector muzzlePos = m_MuzzleOff; muzzlePos.m_X += 4; muzzlePos = m_Pos + RotateOffset(muzzlePos); // Set the screen flash effect to draw at the final post processing stage - if (m_FireFrame && m_pFlash && m_pFlash->GetScreenEffect() && mode == g_DrawColor && !onlyPhysical && !g_SceneMan.ObscuredPoint(muzzlePos)) - g_PostProcessMan.RegisterPostEffect(muzzlePos, m_pFlash->GetScreenEffect(), m_pFlash->GetScreenEffectHash(), 55 + 200 * PosRand(), m_pFlash->GetEffectRotAngle()); + if (m_FireFrame && m_pFlash && m_pFlash->GetScreenEffect() && mode == g_DrawColor && !onlyPhysical && !g_SceneMan.ObscuredPoint(muzzlePos)) { + g_PostProcessMan.RegisterPostEffect(muzzlePos, m_pFlash->GetScreenEffect(), m_pFlash->GetScreenEffectHash(), 55 + 200 * PosRand(), m_pFlash->GetEffectRotAngle()); + } } diff --git a/Entities/HDFirearm.h b/Entities/HDFirearm.h index d9db583d0..4a514bd08 100644 --- a/Entities/HDFirearm.h +++ b/Entities/HDFirearm.h @@ -109,17 +109,6 @@ ClassInfoGetters void Destroy(bool notInherited = false) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this HDFirearm, including the mass of Magazine -// may have inserted. -// Arguments: None. -// Return value: A float describing the mass value in Kilograms (kg). - - float GetMass() const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetRateOfFire ////////////////////////////////////////////////////////////////////////////////////////// @@ -439,17 +428,6 @@ ClassInfoGetters void SetMuzzleOffset(Vector newOffset) override { m_MuzzleOff = newOffset; } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. -// Arguments: An moid specifying the MOID that this MovableObject is -// assigned for this frame. -// Return value: None. - - void SetID(const MOID newID) override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: ResetAllTimers ////////////////////////////////////////////////////////////////////////////////////////// @@ -701,30 +679,6 @@ ClassInfoGetters protected: -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. -// Arguments: The MOID index to register itself and its children in. -// The MOID of the root MO of this MO, ie the highest parent of this MO. -// 0 means that this MO is the root, ie it is owned by MovableMan. -// Whether this MO should make a new MOID to use for itself, or to use -// the same as the last one in the index (presumably its parent), -// Return value: None. - - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - - void GetMOIDs(std::vector &MOIDs) const override; - /// /// Sets this HDFirearm's parent MOSRotating, and also sets its Team based on its parent and, if the Attachable is set to collide, adds/removes Atoms to its new/old parent. /// Additionally, sets this Attachable as not reloading, and resets its reload timer. diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 9f8d13259..5f278d35d 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1060,8 +1060,6 @@ void MOSRotating::GibThis(Vector impactImpulse, float internalBlast, MovableObje for (list::iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ) //NOTE: No increment to handle RemoveAttachable removing the object { RTEAssert((*aItr), "Broken Attachable!"); - if (!(*aItr)) - continue; // Get handy handle to the object we're putting pAttachable = *aItr; @@ -1526,30 +1524,17 @@ void MOSRotating::Update() } // Update all the attached wound emitters - for (list::iterator itr = m_Wounds.begin(); - itr != m_Wounds.end(); ++itr) - { - if ((*itr)) - { - (*itr)->SetJointPos(m_Pos + RotateOffset((*itr)->GetParentOffset())); - if ((*itr)->InheritsRotAngle()) - (*itr)->SetRotAngle(m_Rotation.GetRadAngle()); -// (*itr)->SetEmitAngle(m_Rotation); - (*itr)->Update(); - } - else - RTEAbort("Broken emitter!!"); + for (AEmitter *wound : m_Wounds) { + RTEAssert(wound, "Broken wound AEmitter"); + wound->SetJointPos(m_Pos + RotateOffset(wound->GetParentOffset())); + wound->Update(); } // Update all the attachables Attachable *pAttachable = 0; - for (list::iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ) // NOTE NO INCCREMENT! - { - RTEAssert((*aItr), "Broken Attachable!"); - if (!(*aItr)) - continue; - + for (list::iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ) { pAttachable = *aItr; + RTEAssert(pAttachable, "Broken Attachable!"); ++aItr; pAttachable->SetHFlipped(m_HFlipped); @@ -1797,24 +1782,22 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, } } - // Draw all the attached wound emitters, and only if the mode is g_DrawColor and not onlyphysical // Only draw attachables and emitters which are not drawn after parent, so we draw them before - if (mode == g_DrawColor || (!onlyPhysical && mode == g_DrawMaterial)) - { - for (list::const_iterator itr = m_Wounds.begin(); itr != m_Wounds.end(); ++itr) - { - if (!(*itr)->IsDrawnAfterParent()) - (*itr)->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } + if (mode == g_DrawColor || (!onlyPhysical && mode == g_DrawMaterial)) { + for (const AEmitter *woundToDraw : m_Wounds) { + if (!woundToDraw->IsDrawnAfterParent()) { + woundToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + } + } } // Draw all the attached attachables - for (list::const_iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ++aItr) - { - if (!(*aItr)->IsDrawnAfterParent()) - (*aItr)->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } + for (const Attachable *attachableToDraw : m_Attachables) { + if (!attachableToDraw->IsDrawnAfterParent() && attachableToDraw->IsDrawnNormallyByParent()) { + attachableToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + } + } ////////////////// @@ -1923,21 +1906,21 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, } // Draw all the attached wound emitters, and only if the mode is g_DrawColor and not onlyphysical - if (mode == g_DrawColor || (!onlyPhysical && mode == g_DrawMaterial)) - { - for (list::const_iterator itr = m_Wounds.begin(); itr != m_Wounds.end(); ++itr) - { - if ((*itr)->IsDrawnAfterParent()) - (*itr)->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } + // Only draw attachables and emitters which are not drawn after parent, so we draw them before + if (mode == g_DrawColor || (!onlyPhysical && mode == g_DrawMaterial)) { + for (const AEmitter *woundToDraw : m_Wounds) { + if (woundToDraw->IsDrawnAfterParent()) { + woundToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + } + } } // Draw all the attached attachables - for (list::const_iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ++aItr) - { - if ((*aItr)->IsDrawnAfterParent()) - (*aItr)->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } + for (const Attachable *attachableToDraw : m_Attachables) { + if (attachableToDraw->IsDrawnAfterParent() && attachableToDraw->IsDrawnNormallyByParent()) { + attachableToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + } + } } From c9b81ffa8e24e02d46f65e63055d03a0ed696993 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 8 Sep 2020 01:19:22 -0300 Subject: [PATCH 031/144] Cleaned up no longer needed methods in ACDropship, ACRocket, ACrab, and made their Draw methods only exist in debug/do debug stuff Cleaned up AHuman and made its Draw method only draw the bg arm's hand and do debug stuff --- Entities/ACDropShip.cpp | 154 ++------------------------------------ Entities/ACDropShip.h | 59 +-------------- Entities/ACRocket.cpp | 149 ++----------------------------------- Entities/ACRocket.h | 47 +----------- Entities/ACrab.cpp | 161 ++-------------------------------------- Entities/ACrab.h | 59 +-------------- Entities/AHuman.cpp | 161 +++------------------------------------- Entities/AHuman.h | 57 -------------- 8 files changed, 37 insertions(+), 810 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index d34e9c2f2..e4965edc4 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -206,29 +206,6 @@ void ACDropShip::Destroy(bool notInherited) } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this ACDropShip, including the mass of its -// currently attached body parts and inventory. - -float ACDropShip::GetMass() const -{ - float totalMass = ACraft::GetMass(); - - if (m_pRThruster) - totalMass += m_pRThruster->GetMass(); - if (m_pLThruster) - totalMass += m_pLThruster->GetMass(); - if (m_pRHatch) - totalMass += m_pRHatch->GetMass(); - if (m_pLHatch) - totalMass += m_pLHatch->GetMass(); - - return totalMass; -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetAltitude ////////////////////////////////////////////////////////////////////////////////////////// @@ -314,25 +291,6 @@ MOID ACDropShip::DetectObstacle(float distance) return false; } - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. - -void ACDropShip::SetID(const MOID newID) -{ - MovableObject::SetID(newID); - if (m_pRThruster) - m_pRThruster->SetID(newID); - if (m_pLThruster) - m_pLThruster->SetID(newID); - if (m_pRHatch) - m_pRHatch->SetID(newID); - if (m_pLHatch) - m_pLHatch->SetID(newID); -} - /* ////////////////////////////////////////////////////////////////////////////////////////// // Method: OnBounce @@ -423,22 +381,6 @@ void ACDropShip::GibThis(Vector impactImpulse, float internalBlast, MovableObjec } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: IsOnScenePoint -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this' current graphical representation overlaps -// a point in absolute scene coordinates. - -bool ACDropShip::IsOnScenePoint(Vector &scenePoint) const -{ - return ((m_pLThruster && m_pLThruster->IsOnScenePoint(scenePoint)) || - (m_pRThruster && m_pRThruster->IsOnScenePoint(scenePoint)) || - MOSRotating::IsOnScenePoint(scenePoint) || - (m_pLHatch && m_pLHatch->IsOnScenePoint(scenePoint)) || - (m_pRHatch && m_pRHatch->IsOnScenePoint(scenePoint))); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: UpdateAI ////////////////////////////////////////////////////////////////////////////////////////// @@ -1029,103 +971,21 @@ void ACDropShip::ResetEmissionTimers() m_pULThruster->ResetEmissionTimers(); } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. - -void ACDropShip::UpdateChildMOIDs(vector &MOIDIndex, - MOID rootMOID, - bool makeNewMOID) -{ - if (m_pRHatch) - m_pRHatch->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pLHatch) - m_pLHatch->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pRThruster) - m_pRThruster->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pLThruster) - m_pLThruster->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - - ACraft::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - -void ACDropShip::GetMOIDs(std::vector &MOIDs) const -{ - if (m_pRHatch) - m_pRHatch->GetMOIDs(MOIDs); - if (m_pLHatch) - m_pLHatch->GetMOIDs(MOIDs); - if (m_pRThruster) - m_pRThruster->GetMOIDs(MOIDs); - if (m_pLThruster) - m_pLThruster->GetMOIDs(MOIDs); - - ACraft::GetMOIDs(MOIDs); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this ACDropShip's current graphical representation to a -// BITMAP of choice. - -void ACDropShip::Draw(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode, - bool onlyPhysical) const -{ - if (m_pRHatch) - m_pRHatch->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pLHatch) - m_pLHatch->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (m_pRThruster && !m_pRThruster->IsDrawnAfterParent()) - m_pRThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pLThruster && !m_pLThruster->IsDrawnAfterParent()) - m_pLThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef DEBUG_BUILD +void ACDropShip::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { ACraft::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pRThruster && m_pRThruster->IsDrawnAfterParent()) - m_pRThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pLThruster && m_pLThruster->IsDrawnAfterParent()) - m_pLThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (mode == g_DrawColor || mode == g_DrawMaterial) - { - if (m_pURThruster) - m_pURThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pULThruster) - m_pULThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } - - if (mode == g_DrawColor) - { -#ifdef DEBUG_BUILD + if (mode == g_DrawColor) { acquire_bitmap(pTargetBitmap); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), - floorf(m_Pos.m_Y), - 64); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), - floorf(m_Pos.m_Y), - 64); + putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); + putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); release_bitmap(pTargetBitmap); m_pAtomGroup->Draw(pTargetBitmap, targetPos, false, 122); // m_pDeepGroup->Draw(pTargetBitmap, targetPos, false, 13); -#endif } } - +#endif } // namespace RTE \ No newline at end of file diff --git a/Entities/ACDropShip.h b/Entities/ACDropShip.h index 9e7a8aabf..2485633c5 100644 --- a/Entities/ACDropShip.h +++ b/Entities/ACDropShip.h @@ -109,17 +109,6 @@ ClassInfoGetters void Destroy(bool notInherited = false) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this ACDropShip, including the mass of its -// currently attached body parts and inventory. -// Arguments: None. -// Return value: A float describing the mass value in Kilograms (kg). - - float GetMass() const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetAltitude ////////////////////////////////////////////////////////////////////////////////////////// @@ -143,17 +132,6 @@ ClassInfoGetters MOID DetectObstacle(float distance); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. -// Arguments: A moid specifying the MOID that this MovableObject is -// assigned for this frame. -// Return value: None. - - void SetID(const MOID newID) override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: AutoStabilizing ////////////////////////////////////////////////////////////////////////////////////////// @@ -178,17 +156,6 @@ ClassInfoGetters void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: IsOnScenePoint -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this' current graphical representation overlaps -// a point in absolute scene coordinates. -// Arguments: The point in absolute scene coordinates. -// Return value: Whether this' graphical rep overlaps the scene point. - - bool IsOnScenePoint(Vector &scenePoint) const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: UpdateAI ////////////////////////////////////////////////////////////////////////////////////////// @@ -210,6 +177,7 @@ ClassInfoGetters void Update() override; +#ifdef DEBUG_BUILD ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw ////////////////////////////////////////////////////////////////////////////////////////// @@ -223,6 +191,7 @@ ClassInfoGetters // Return value: None. void Draw(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; +#endif ////////////////////////////////////////////////////////////////////////////////////////// @@ -321,16 +290,6 @@ ClassInfoGetters void ResetEmissionTimers() override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - - void GetMOIDs(std::vector &MOIDs) const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetMaxEngineAngle ////////////////////////////////////////////////////////////////////////////////////////// @@ -386,20 +345,6 @@ ClassInfoGetters protected: -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. -// Arguments: The MOID index to register itself and its children in. -// The MOID of the root MO of this MO, ie the highest parent of this MO. -// 0 means that this MO is the root, ie it is owned by MovableMan. -// Whether this MO should make a new MOID to use for itself, or to use -// the same as the last one in the index (presumably its parent), -// Return value: None. - - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; - // Member variables static Entity::ClassInfo m_sClass; diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index ccf49a6ea..9f5d41de6 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -266,27 +266,6 @@ void ACRocket::Destroy(bool notInherited) } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this ACRocket, including the mass of its -// currently attached body parts and inventory. - -float ACRocket::GetMass() const -{ - float totalMass = ACraft::GetMass(); -// if (m_pCapsule) -// totalMass += m_pCapsule->GetMass(); - if (m_pRLeg) - totalMass += m_pRLeg->GetMass(); - if (m_pLLeg) - totalMass += m_pLLeg->GetMass(); - if (m_pMThruster) - totalMass += m_pMThruster->GetMass(); - return totalMass; -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetAltitude ////////////////////////////////////////////////////////////////////////////////////////// @@ -305,25 +284,6 @@ float ACRocket::GetAltitude(int max, int accuracy) return g_SceneMan.FindAltitude(pos, max, accuracy); } - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. - -void ACRocket::SetID(const MOID newID) -{ - MovableObject::SetID(newID); -// if (m_pCapsule) -// m_pCapsule->SetID(newID); - if (m_pRLeg) - m_pRLeg->SetID(newID); - if (m_pLLeg) - m_pLLeg->SetID(newID); - if (m_pMThruster) - m_pMThruster->SetID(newID); -} - /* ////////////////////////////////////////////////////////////////////////////////////////// // Method: OnBounce @@ -999,43 +959,6 @@ void ACRocket::Update() } } - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. - -void ACRocket::UpdateChildMOIDs(vector &MOIDIndex, - MOID rootMOID, - bool makeNewMOID) -{ - if (m_pRLeg) - m_pRLeg->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pLLeg) - m_pLLeg->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - - ACraft::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - -void ACRocket::GetMOIDs(std::vector &MOIDs) const -{ - if (m_pRLeg) - m_pRLeg->GetMOIDs(MOIDs); - if (m_pLLeg) - m_pLLeg->GetMOIDs(MOIDs); - - ACraft::GetMOIDs(MOIDs); -} - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACRocket::SetRightLeg(Attachable *newLeg) { @@ -1140,82 +1063,24 @@ void ACRocket::ResetEmissionTimers() m_pULThruster->ResetEmissionTimers(); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this ACRocket's current graphical representation to a -// BITMAP of choice. - -void ACRocket::Draw(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode, - bool onlyPhysical) const -{ - if (m_pMThruster && !m_pMThruster->IsDrawnAfterParent() && (mode == g_DrawColor || mode == g_DrawMaterial)) - m_pMThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (m_pRLeg && !m_pRLeg->IsDrawnAfterParent()) - m_pRLeg->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pLLeg && !m_pLLeg->IsDrawnAfterParent()) - m_pLLeg->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (mode == g_DrawColor || mode == g_DrawMaterial) { - if (m_pRThruster && !m_pRThruster->IsDrawnAfterParent()) - m_pRThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pLThruster && !m_pLThruster->IsDrawnAfterParent()) - m_pLThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pURThruster && !m_pURThruster->IsDrawnAfterParent()) - m_pURThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pULThruster && !m_pULThruster->IsDrawnAfterParent()) - m_pULThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } - +#ifdef DEBUG_BUILD +void ACRocket::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { ACraft::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pMThruster && m_pMThruster->IsDrawnAfterParent() && (mode == g_DrawColor || mode == g_DrawMaterial)) - m_pMThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (m_pRLeg && m_pRLeg->IsDrawnAfterParent()) - m_pRLeg->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pLLeg && m_pLLeg->IsDrawnAfterParent()) - m_pLLeg->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (mode == g_DrawColor || mode == g_DrawMaterial) { - if (m_pRThruster && m_pRThruster->IsDrawnAfterParent()) - m_pRThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pLThruster && m_pLThruster->IsDrawnAfterParent()) - m_pLThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pURThruster && m_pURThruster->IsDrawnAfterParent()) - m_pURThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pULThruster && m_pULThruster->IsDrawnAfterParent()) - m_pULThruster->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } -/* - if (m_pCapsule) - m_pCapsule->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); -*/ if (mode == g_DrawColor) { -#ifdef DEBUG_BUILD acquire_bitmap(pTargetBitmap); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), - floorf(m_Pos.m_Y), - 64); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), - floorf(m_Pos.m_Y), - 64); + putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); + putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); release_bitmap(pTargetBitmap); + m_pAtomGroup->Draw(pTargetBitmap, targetPos, false, 122); m_pRFootGroup->Draw(pTargetBitmap, targetPos, true, 13); m_pLFootGroup->Draw(pTargetBitmap, targetPos, true, 13); -// m_pAtomGroup->Draw(pTargetBitmap, targetPos, false, 122); // m_pDeepGroup->Draw(pTargetBitmap, targetPos, false, 13); -#endif -// m_pAtomGroup->Draw(pTargetBitmap, targetPos, false); -// m_pFGFootGroup->Draw(pTargetBitmap, targetPos, true); -// m_pBGFootGroup->Draw(pTargetBitmap, targetPos, true); -// m_pBGHandGroup->Draw(pTargetBitmap, targetPos, true); } } +#endif } // namespace RTE diff --git a/Entities/ACRocket.h b/Entities/ACRocket.h index bfe3464c3..b3ddfc1da 100644 --- a/Entities/ACRocket.h +++ b/Entities/ACRocket.h @@ -124,17 +124,6 @@ ClassInfoGetters void Destroy(bool notInherited = false) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this ACRocket, including the mass of its -// currently attached body parts and inventory. -// Arguments: None. -// Return value: A float describing the mass value in Kilograms (kg). - - float GetMass() const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetAltitude ////////////////////////////////////////////////////////////////////////////////////////// @@ -148,17 +137,6 @@ ClassInfoGetters float GetAltitude(int max = 0, int accuracy = 0) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. -// Arguments: A MOID specifying the MOID that this MovableObject is -// assigned for this frame. -// Return value: None. - - void SetID(const MOID newID) override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GibThis ////////////////////////////////////////////////////////////////////////////////////////// @@ -204,6 +182,7 @@ ClassInfoGetters void ResetEmissionTimers() override; +#ifdef DEBUG_BUILD ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw ////////////////////////////////////////////////////////////////////////////////////////// @@ -217,6 +196,7 @@ ClassInfoGetters // Return value: None. void Draw(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; +#endif ////////////////////////////////////////////////////////////////////////////////////////// @@ -230,15 +210,6 @@ ClassInfoGetters int GetMaxPassengers() const override { return m_MaxPassengers > -1 ? m_MaxPassengers : 2; } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - - void GetMOIDs(std::vector &MOIDs) const override; - /// /// Gets the right leg of this ACRocket. /// @@ -339,20 +310,6 @@ ClassInfoGetters protected: -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. -// Arguments: The MOID index to register itself and its children in. -// The MOID of the root MO of this MO, ie the highest parent of this MO. -// 0 means that this MO is the root, ie it is owned by MovableMan. -// Whether this MO should make a new MOID to use for itself, or to use -// the same as the last one in the index (presumably its parent), -// Return value: None. - - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; - // Member variables static Entity::ClassInfo m_sClass; diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index eeaaa50c6..14df53589 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -421,29 +421,6 @@ void ACrab::Destroy(bool notInherited) Clear(); } - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this ACrab, including the mass of its -// currently attached body parts and inventory. - -float ACrab::GetMass() const -{ - float totalMass = Actor::GetMass(); - if (m_pTurret) - totalMass += m_pTurret->GetMass(); - if (m_pLFGLeg) - totalMass += m_pLFGLeg->GetMass(); - if (m_pLBGLeg) - totalMass += m_pLBGLeg->GetMass(); - if (m_pRFGLeg) - totalMass += m_pRFGLeg->GetMass(); - if (m_pRBGLeg) - totalMass += m_pRBGLeg->GetMass(); - return totalMass; -} - /* ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetTotalValue @@ -562,27 +539,6 @@ void ACrab::SetRightBGLeg(Attachable *newLeg) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. - -void ACrab::SetID(const MOID newID) -{ - MovableObject::SetID(newID); - if (m_pTurret) - m_pTurret->SetID(newID); - if (m_pLFGLeg) - m_pLFGLeg->SetID(newID); - if (m_pLBGLeg) - m_pLBGLeg->SetID(newID); - if (m_pRFGLeg) - m_pRFGLeg->SetID(newID); - if (m_pRBGLeg) - m_pRBGLeg->SetID(newID); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: CollideAtPoint ////////////////////////////////////////////////////////////////////////////////////////// @@ -1041,24 +997,6 @@ void ACrab::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pI } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: IsOnScenePoint -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this' current graphical representation overlaps -// a point in absolute scene coordinates. - -bool ACrab::IsOnScenePoint(Vector &scenePoint) const -{ - return ((m_pTurret && m_pTurret->IsOnScenePoint(scenePoint)) || - (m_pLFGLeg && m_pLFGLeg->IsOnScenePoint(scenePoint)) || - (m_pRFGLeg && m_pRFGLeg->IsOnScenePoint(scenePoint)) || - Actor::IsOnScenePoint(scenePoint) || - (m_pJetpack && m_pJetpack->IsOnScenePoint(scenePoint)) || - (m_pLBGLeg && m_pLBGLeg->IsOnScenePoint(scenePoint)) || - (m_pRBGLeg && m_pRBGLeg->IsOnScenePoint(scenePoint))); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: UpdateMovePath ////////////////////////////////////////////////////////////////////////////////////////// @@ -2945,101 +2883,16 @@ void ACrab::Update() } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. - -void ACrab::UpdateChildMOIDs(vector &MOIDIndex, - MOID rootMOID, - bool makeNewMOID) -{ - if (m_pLBGLeg) - m_pLBGLeg->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pRBGLeg) - m_pRBGLeg->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pJetpack) - m_pJetpack->UpdateMOID(MOIDIndex, m_RootMOID, false); - if (m_pLFGLeg) - m_pLFGLeg->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pRFGLeg) - m_pRFGLeg->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pTurret) - m_pTurret->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - - Actor::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - -void ACrab::GetMOIDs(std::vector &MOIDs) const -{ - if (m_pLBGLeg) - m_pLBGLeg->GetMOIDs(MOIDs); - if (m_pRBGLeg) - m_pRBGLeg->GetMOIDs(MOIDs); - if (m_pJetpack) - m_pJetpack->GetMOIDs(MOIDs); - if (m_pLFGLeg) - m_pLFGLeg->GetMOIDs(MOIDs); - if (m_pRFGLeg) - m_pRFGLeg->GetMOIDs(MOIDs); - if (m_pTurret) - m_pTurret->GetMOIDs(MOIDs); - - Actor::GetMOIDs(MOIDs); -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this ACrab's current graphical representation to a -// BITMAP of choice. - -void ACrab::Draw(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode, - bool onlyPhysical) const -{ - // Override color drawing with flash, if requested. - DrawMode realMode = (mode == g_DrawColor && m_FlashWhiteMS) ? g_DrawWhite : mode; - - if (m_pLBGLeg) - m_pLBGLeg->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - if (m_pRBGLeg) - m_pRBGLeg->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - if (m_pJetpack) - m_pJetpack->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - if (m_pTurret && !m_pTurret->IsDrawnAfterParent()) - m_pTurret->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef DEBUG_BUILD +void ACrab::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { Actor::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pTurret && m_pTurret->IsDrawnAfterParent()) - m_pTurret->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - if (m_pRFGLeg) - m_pRFGLeg->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - if (m_pLFGLeg) - m_pLFGLeg->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - -#ifdef DEBUG_BUILD -// if (mode == g_DrawDebug) - if (mode == g_DrawColor && !onlyPhysical) - { + if (mode == g_DrawColor && !onlyPhysical) { acquire_bitmap(pTargetBitmap); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), - floorf(m_Pos.m_Y), - 64); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), - floorf(m_Pos.m_Y), - 64); + putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); + putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); release_bitmap(pTargetBitmap); m_pAtomGroup->Draw(pTargetBitmap, targetPos, false, 122); @@ -3048,8 +2901,8 @@ void ACrab::Draw(BITMAP *pTargetBitmap, m_pRFGFootGroup->Draw(pTargetBitmap, targetPos, true, 13); m_pRBGFootGroup->Draw(pTargetBitmap, targetPos, true, 13); } -#endif } +#endif ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACrab.h b/Entities/ACrab.h index fec00053f..1023213ac 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -136,17 +136,6 @@ class ACrab : void Destroy(bool notInherited = false) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this ACrab, including the mass of its -// currently attached body parts and inventory. -// Arguments: None. -// Return value: A float describing the mass value in Kilograms (kg). - - float GetMass() const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetGoldCarried ////////////////////////////////////////////////////////////////////////////////////////// @@ -268,17 +257,6 @@ class ACrab : float GetJetTimeLeft() const { return m_JetTimeLeft; } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. -// Arguments: A MOID specifying the MOID that this MovableObject is -// assigned for this frame. -// Return value: None. - - void SetID(const MOID newID) override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: CollideAtPoint ////////////////////////////////////////////////////////////////////////////////////////// @@ -438,17 +416,6 @@ int FirearmActivationDelay() const; void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: IsOnScenePoint -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this' current graphical representation overlaps -// a point in absolute scene coordinates. -// Arguments: The point in absolute scene coordinates. -// Return value: Whether this' graphical rep overlaps the scene point. - - bool IsOnScenePoint(Vector &scenePoint) const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: UpdateMovePath ////////////////////////////////////////////////////////////////////////////////////////// @@ -480,6 +447,7 @@ int FirearmActivationDelay() const; void Update() override; +#ifdef DEBUG_BUILD ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw ////////////////////////////////////////////////////////////////////////////////////////// @@ -493,6 +461,7 @@ int FirearmActivationDelay() const; // Return value: None. void Draw(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; +#endif ////////////////////////////////////////////////////////////////////////////////////////// @@ -509,16 +478,6 @@ int FirearmActivationDelay() const; void DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), int whichScreen = 0, bool playerControlled = false) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - - void GetMOIDs(std::vector &MOIDs) const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetLimbPathSpeed ////////////////////////////////////////////////////////////////////////////////////////// @@ -566,20 +525,6 @@ int FirearmActivationDelay() const; protected: -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. -// Arguments: The MOID index to register itself and its children in. -// The MOID of the root MO of this MO, ie the highest parent of this MO. -// 0 means that this MO is the root, ie it is owned by MovableMan. -// Whether this MO should make a new MOID to use for itself, or to use -// the same as the last one in the index (presumably its parent), -// Return value: None. - - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; - // Member variables static Entity::ClassInfo m_sClass; diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 769f7ee06..c3f2d39cb 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -219,11 +219,13 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { m_pFGArm = new Arm; reader >> m_pFGArm; m_pFGArm->SetTransfersDamageToParent(true); + m_pFGArm->SetDrawnAfterParent(true); } else if (propName == "BGArm") { delete m_pBGArm; m_pBGArm = new Arm; reader >> m_pBGArm; m_pBGArm->SetTransfersDamageToParent(true); + m_pBGArm->SetDrawnAfterParent(false); } else if (propName == "FGLeg") { delete m_pFGLeg; m_pFGLeg = new Leg; @@ -360,29 +362,6 @@ void AHuman::Destroy(bool notInherited) } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this AHuman, including the mass of its -// currently attached body parts and inventory. - -float AHuman::GetMass() const -{ - float totalMass = Actor::GetMass(); - if (m_pHead) - totalMass += m_pHead->GetMass(); - if (m_pFGArm) - totalMass += m_pFGArm->GetMass(); - if (m_pBGArm) - totalMass += m_pBGArm->GetMass(); - if (m_pFGLeg) - totalMass += m_pFGLeg->GetMass(); - if (m_pBGLeg) - totalMass += m_pBGLeg->GetMass(); - return totalMass; -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetTotalValue ////////////////////////////////////////////////////////////////////////////////////////// @@ -543,27 +522,6 @@ BITMAP *AHuman::GetHeadBitmap() const { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. - -void AHuman::SetID(const MOID newID) -{ - MovableObject::SetID(newID); - if (m_pHead) - m_pHead->SetID(newID); - if (m_pFGArm) - m_pFGArm->SetID(newID); - if (m_pBGArm) - m_pBGArm->SetID(newID); - if (m_pFGLeg) - m_pFGLeg->SetID(newID); - if (m_pBGLeg) - m_pBGLeg->SetID(newID); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: CollideAtPoint ////////////////////////////////////////////////////////////////////////////////////////// @@ -1718,24 +1676,6 @@ void AHuman::GibThis(Vector impactImpulse, float internalBlast, MovableObject *p } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: IsOnScenePoint -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this' current graphical representation overlaps -// a point in absolute scene coordinates. - -bool AHuman::IsOnScenePoint(Vector &scenePoint) const -{ - return ((m_pFGArm && m_pFGArm->IsOnScenePoint(scenePoint)) || - (m_pFGLeg && m_pFGLeg->IsOnScenePoint(scenePoint)) || - (m_pHead && m_pHead->IsOnScenePoint(scenePoint)) || - Actor::IsOnScenePoint(scenePoint) || - (m_pJetpack && m_pJetpack->IsOnScenePoint(scenePoint)) || - (m_pBGArm && m_pBGArm->IsOnScenePoint(scenePoint)) || - (m_pBGLeg && m_pBGLeg->IsOnScenePoint(scenePoint))); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: ResetAllTimers ////////////////////////////////////////////////////////////////////////////////////////// @@ -4486,99 +4426,23 @@ void AHuman::DrawThrowingReticule(BITMAP *pTargetBitmap, const Vector &targetPos release_bitmap(pTargetBitmap); } - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame - -void AHuman::UpdateChildMOIDs(vector &MOIDIndex, - MOID rootMOID, - bool makeNewMOID) -{ - if (m_pBGLeg) - m_pBGLeg->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pBGArm) - m_pBGArm->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pJetpack) - m_pJetpack->UpdateMOID(MOIDIndex, m_RootMOID, false); - if (m_pHead) - m_pHead->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pFGLeg) - m_pFGLeg->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - if (m_pFGArm) - m_pFGArm->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - - Actor::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - -void AHuman::GetMOIDs(std::vector &MOIDs) const -{ - if (m_pBGLeg) - m_pBGLeg->GetMOIDs(MOIDs); - if (m_pBGArm) - m_pBGArm->GetMOIDs(MOIDs); - if (m_pJetpack) - m_pJetpack->GetMOIDs(MOIDs); - if (m_pHead) - m_pHead->GetMOIDs(MOIDs); - if (m_pFGLeg) - m_pFGLeg->GetMOIDs(MOIDs); - if (m_pFGArm) - m_pFGArm->GetMOIDs(MOIDs); - - Actor::GetMOIDs(MOIDs); -} - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw ////////////////////////////////////////////////////////////////////////////////////////// // Description: Draws this AHuman's current graphical representation to a // BITMAP of choice. -void AHuman::Draw(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode, - bool onlyPhysical) const -{ - // Override color drawing with flash, if requested. +void AHuman::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { DrawMode realMode = (mode == g_DrawColor && m_FlashWhiteMS) ? g_DrawWhite : mode; - if (m_pBGLeg) - m_pBGLeg->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - if (m_pBGArm) - m_pBGArm->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - if (m_pJetpack) - m_pJetpack->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - if (m_pHead && !m_pHead->IsDrawnAfterParent()) - m_pHead->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - Actor::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (m_pHead && m_pHead->IsDrawnAfterParent()) - m_pHead->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - if (m_pFGLeg) - m_pFGLeg->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - if (m_pFGArm) - { - m_pFGArm->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); - // Draw background Arm's hand after the HeldDevice of FGArm is drawn. - if (!onlyPhysical && mode == g_DrawColor && (m_pBGArm && m_pBGArm->DidReach() && m_pFGArm->HoldsHeldDevice() && !m_pFGArm->HoldsThrownDevice() && !m_pFGArm->GetHeldDevice()->IsReloading() && !m_pFGArm->GetHeldDevice()->IsShield())) - m_pBGArm->DrawHand(pTargetBitmap, targetPos, realMode); + // Draw background Arm's hand after the HeldDevice of FGArm is drawn if the FGArm is holding a weapon. + if (m_pFGArm && m_pBGArm && !onlyPhysical && mode == g_DrawColor && m_pBGArm->DidReach() && m_pFGArm->HoldsHeldDevice() && !m_pFGArm->HoldsThrownDevice() && !m_pFGArm->GetHeldDevice()->IsReloading() && !m_pFGArm->GetHeldDevice()->IsShield()) { + m_pBGArm->DrawHand(pTargetBitmap, targetPos, realMode); } #ifdef DEBUG_BUILD - if (mode == g_DrawDebug) - { + if (mode == g_DrawDebug) { // Limbpath debug drawing m_Paths[m_HFlipped][WALK].Draw(pTargetBitmap, targetPos, 122); m_Paths[m_HFlipped][CRAWL].Draw(pTargetBitmap, targetPos, 122); @@ -4586,15 +4450,10 @@ void AHuman::Draw(BITMAP *pTargetBitmap, m_Paths[m_HFlipped][CLIMB].Draw(pTargetBitmap, targetPos, 165); } - if (mode == g_DrawColor && !onlyPhysical) - { + if (mode == g_DrawColor && !onlyPhysical) { acquire_bitmap(pTargetBitmap); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), - floorf(m_Pos.m_Y), - 64); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), - floorf(m_Pos.m_Y), - 64); + putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); + putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); release_bitmap(pTargetBitmap); // m_pAtomGroup->Draw(pTargetBitmap, targetPos, false, 122); diff --git a/Entities/AHuman.h b/Entities/AHuman.h index f8d92ff9d..8c209811d 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -157,17 +157,6 @@ ClassInfoGetters void Destroy(bool notInherited = false) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this AHuman, including the mass of its -// currently attached body parts and inventory. -// Arguments: None. -// Return value: A float describing the mass value in Kilograms (kg). - - float GetMass() const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetGoldCarried ////////////////////////////////////////////////////////////////////////////////////////// @@ -379,17 +368,6 @@ ClassInfoGetters void SetJetTimeLeft(float newValue) { m_JetTimeLeft = newValue < m_JetTimeTotal ? newValue : m_JetTimeTotal; } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. -// Arguments: A moid specifying the MOID that this MovableObject is -// assigned for this frame. -// Return value: None. - - void SetID(const MOID newID) override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: CollideAtPoint ////////////////////////////////////////////////////////////////////////////////////////// @@ -746,17 +724,6 @@ ClassInfoGetters BITMAP * GetGraphicalIcon() override { return GetHeadBitmap(); } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: IsOnScenePoint -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Indicates whether this' current graphical representation overlaps -// a point in absolute scene coordinates. -// Arguments: The point in absolute scene coordinates. -// Return value: Whether this' graphical rep overlaps the scene point. - - bool IsOnScenePoint(Vector &scenePoint) const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: ResetAllTimers ////////////////////////////////////////////////////////////////////////////////////////// @@ -836,16 +803,6 @@ ClassInfoGetters void DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), int whichScreen = 0, bool playerControlled = false) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - - void GetMOIDs(std::vector &MOIDs) const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetLimbPathSpeed ////////////////////////////////////////////////////////////////////////////////////////// @@ -905,20 +862,6 @@ ClassInfoGetters protected: -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. -// Arguments: The MOID index to register itself and its children in. -// The MOID of the root MO of this MO, ie the highest parent of this MO. -// 0 means that this MO is the root, ie it is owned by MovableMan. -// Whether this MO should make a new MOID to use for itself, or to use -// the same as the last one in the index (presumably its parent), -// Return value: None. - - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; - ////////////////////////////////////////////////////////////////////////////////////////// // Method: ChunkGold From e0a32999349c76967a77e29e9bfa6e76e527f89c Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 8 Sep 2020 01:22:05 -0300 Subject: [PATCH 032/144] Cleaned up uneeded methods from ACraft, ADoor, Arm Fixed missing rename in Arm and made DrawHand support flashing white (though it technically doesn't draw white properly while flipped) Cleaned up leftovers in Turret.h --- Entities/ACraft.cpp | 15 ------ Entities/ACraft.h | 39 --------------- Entities/ADoor.cpp | 54 -------------------- Entities/ADoor.h | 42 ---------------- Entities/Arm.cpp | 118 ++++++++++---------------------------------- Entities/Arm.h | 47 ------------------ Entities/Turret.h | 8 +-- 7 files changed, 28 insertions(+), 295 deletions(-) diff --git a/Entities/ACraft.cpp b/Entities/ACraft.cpp index 0ddd91684..4be928bbf 100644 --- a/Entities/ACraft.cpp +++ b/Entities/ACraft.cpp @@ -951,21 +951,6 @@ void ACraft::Update() } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this ACraft's current graphical representation to a -// BITMAP of choice. - -void ACraft::Draw(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode, - bool onlyPhysical) const -{ - Actor::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: DrawHUD ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACraft.h b/Entities/ACraft.h index 7f0133db5..825a9f87f 100644 --- a/Entities/ACraft.h +++ b/Entities/ACraft.h @@ -516,21 +516,6 @@ enum void Update() override; -////////////////////////////////////////////////////////////////////////////////////////// -// Pure v. method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this ACraft's current graphical representation to a -// BITMAP of choice. -// Arguments: A pointer to a BITMAP to draw on. -// The absolute position of the target bitmap's upper left corner in the Scene. -// In which mode to draw in. See the DrawMode enumeration for the modes. -// Whether to not draw any extra 'ghost' items of this MovableObject, -// indicator arrows or hovering HUD text and so on. -// Return value: None. - - void Draw(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: DrawHUD ////////////////////////////////////////////////////////////////////////////////////////// @@ -596,32 +581,8 @@ enum protected: - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. -// Arguments: The MOID index to register itself and its children in. -// The MOID of the root MO of this MO, ie the highest parent of this MO. -// 0 means that this MO is the root, ie it is owned by MovableMan. -// Whether this MO should make a new MOID to use for itself, or to use -// the same as the last one in the index (presumably its parent), -// Return value: None. - - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override { Actor::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); } - void SetAttachableVelocitiesForGibbing(Attachable* pAttachable, Vector impactImpulse, float internalBlast); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - - void GetMOIDs(std::vector &MOIDs) const override { Actor::GetMOIDs(MOIDs); } - // Member variables static Entity::ClassInfo m_sClass; // Current movement state. diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index df82682e3..47a266493 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -207,34 +207,6 @@ namespace RTE { } } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - float ADoor::GetMass() const { - float totalMass = Actor::GetMass(); - if (m_Door) { totalMass += m_Door->GetMass(); } - return totalMass; - } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - void ADoor::GetMOIDs(std::vector &MOIDs) const { - if (m_Door) { m_Door->GetMOIDs(MOIDs); } - Actor::GetMOIDs(MOIDs); - } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - void ADoor::SetID(const MOID newID) { - Actor::SetID(newID); - if (m_Door) { m_Door->SetID(newID); } - } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - bool ADoor::IsOnScenePoint(Vector &scenePoint) const { - return ((m_Door && m_Door->IsOnScenePoint(scenePoint)) || Actor::IsOnScenePoint(scenePoint)); - } - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ADoor::DrawDoorMaterial() { @@ -306,13 +278,6 @@ namespace RTE { Actor::GibThis(impactImpulse, internalBlast, ignoreMO); } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - void ADoor::UpdateChildMOIDs(vector &MOIDIndex, MOID rootMOID, bool makeNewMOID) { - if (m_Door) { m_Door->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); } - Actor::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); - } - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ADoor::OpenDoor() { @@ -504,25 +469,6 @@ namespace RTE { m_Door->Update(); } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - void ADoor::Draw(BITMAP *targetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { - // Override color drawing with flash, if requested. - DrawMode realMode = (mode == g_DrawColor && m_FlashWhiteMS) ? g_DrawWhite : mode; - - if (m_Door && m_Door->IsAttached()) { - if (!m_Door->IsDrawnAfterParent()) { - m_Door->Draw(targetBitmap, targetPos, realMode, onlyPhysical); - Actor::Draw(targetBitmap, targetPos, mode, onlyPhysical); - } else { - Actor::Draw(targetBitmap, targetPos, mode, onlyPhysical); - m_Door->Draw(targetBitmap, targetPos, realMode, onlyPhysical); - } - } else { - Actor::Draw(targetBitmap, targetPos, mode, onlyPhysical); - } - } - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ADoor::DrawHUD(BITMAP *targetBitmap, const Vector &targetPos, int whichScreen, bool playerControlled) { diff --git a/Entities/ADoor.h b/Entities/ADoor.h index 8b0a2c7c1..1589566b3 100644 --- a/Entities/ADoor.h +++ b/Entities/ADoor.h @@ -85,24 +85,6 @@ namespace RTE { /// The current state of this ADoor. See the DoorState enum. DoorState GetDoorState() const { return m_DoorState; } - /// - /// Gets the mass value of this ADoor, including the mass of its currently attached parts. - /// - /// A float describing the mass value in Kilograms (kg). - float GetMass() const override; - - /// - /// Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector to store MOIDs. - /// - /// - void GetMOIDs(std::vector &MOIDs) const override; - - /// - /// Sets the MOID of this ADoor for this frame. - /// - /// A MOID specifying the MOID that this ADoor is assigned for this frame. - void SetID(const MOID newID) override; - /// /// Sets whether this ADoor closes (or opens) after a while by default. /// @@ -114,13 +96,6 @@ namespace RTE { /// /// Whether a player can control this at all. bool IsControllable() const override { return false; } - - /// - /// Indicates whether this' current graphical representation overlaps a point in absolute scene coordinates. - /// - /// The point in absolute scene coordinates. - /// Whether this' graphical representation overlaps the scene point. - bool IsOnScenePoint(Vector &scenePoint) const override; #pragma endregion #pragma region Concrete Methods @@ -160,15 +135,6 @@ namespace RTE { /// void Update() override; - /// - /// Draws this ADoor's current graphical representation to a BITMAP of choice. - /// - /// A pointer to a BITMAP to draw on. - /// The absolute position of the target bitmap's upper left corner in the Scene. - /// Which mode to draw in. See the DrawMode enumeration for the modes. - /// Whether to not draw any extra 'ghost' items of this ADoor, indicator arrows or hovering HUD text and so on. - void Draw(BITMAP *targetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; - /// /// Draws this ADoor's current graphical HUD overlay representation to a BITMAP of choice. /// @@ -244,14 +210,6 @@ namespace RTE { /// void SharedDoorControls(); - /// - /// Makes this MO register itself and all its attached children in the MOID register and get IDs for itself and its children for this frame. - /// - /// The MOID index to register itself and its children in. - /// The MOID of the root MO of this MO, ie the highest parent of this MO. 0 means that this MO is the root, ie it is owned by MovableMan. - /// Whether this MO should make a new MOID to use for itself, or to use the same as the last one in the index (presumably its parent), - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; - /// /// Draws the material under the position of the door attachable, to create terrain collision detection for the doors. /// diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 063b7573c..3b6af74d0 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -160,18 +160,6 @@ void Arm::Destroy(bool notInherited) } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this Arm, including the mass of any device it -// may be holding. - -float Arm::GetMass() const -{ - return m_Mass + (m_pHeldMO ? m_pHeldMO->GetMass() : 0); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetHeldDevice ////////////////////////////////////////////////////////////////////////////////////////// @@ -190,19 +178,6 @@ HeldDevice * Arm::GetHeldDevice() const } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. - -void Arm::SetID(const MOID newID) -{ - MovableObject::SetID(newID); - if (m_pHeldMO) - m_pHeldMO->SetID(newID); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: SetHeldMO ////////////////////////////////////////////////////////////////////////////////////////// @@ -255,7 +230,7 @@ MovableObject * Arm::ReleaseHeldMO() if (m_pHeldMO->IsDevice()) { // Once detached may have incorrect ID value. Detach will take care m_RootID. New ID will be assigned on next frame. - m_pHeldMO->SetID(g_NoMOID); + m_pHeldMO->SetAsNoID(); RemoveAttachable(dynamic_cast(m_pHeldMO)); } } @@ -556,66 +531,22 @@ void Arm::Update() } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. - -void Arm::UpdateChildMOIDs(vector &MOIDIndex, - MOID rootMOID, - bool makeNewMOID) -{ - if (m_pHeldMO && m_pHeldMO->GetsHitByMOs()) - m_pHeldMO->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - - Attachable::UpdateChildMOIDs(MOIDIndex, m_RootMOID, makeNewMOID); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - -void Arm::GetMOIDs(std::vector &MOIDs) const -{ - if (m_pHeldMO) - m_pHeldMO->GetMOIDs(MOIDs); - - Attachable::GetMOIDs(MOIDs); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw ////////////////////////////////////////////////////////////////////////////////////////// // Description: Draws this Arm's current graphical representation to a // BITMAP of choice. -void Arm::Draw(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode, - bool onlyPhysical) const -{ - if (m_pHeldMO && !m_pHeldMO->IsDrawnAfterParent()) - m_pHeldMO->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - +void Arm::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { Attachable::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (!onlyPhysical && mode == g_DrawColor && (!m_DidReach && !m_pHeldMO)) - DrawHand(pTargetBitmap, targetPos, mode); - - if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && m_pHeldMO->IsDrawnAfterParent()) - m_pHeldMO->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (!onlyPhysical && mode == g_DrawColor && (m_pHeldMO || !m_Parent)) - DrawHand(pTargetBitmap, targetPos, mode); - - if (m_pHeldMO && ((!m_pHeldMO->IsHeldDevice() && !m_pHeldMO->IsThrownDevice()) || m_pHeldMO->IsDrawnAfterParent())) - m_pHeldMO->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + if (m_pHeldMO || (!m_pHeldMO && !m_DidReach) || !m_Parent) { + if (!onlyPhysical && (mode == g_DrawColor || mode == g_DrawWhite)) { + DrawHand(pTargetBitmap, targetPos, mode); + } + if (m_pHeldMO && m_pHeldMO->IsDrawnAfterParent()) { + m_pHeldMO->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + } + } } @@ -625,22 +556,25 @@ void Arm::Draw(BITMAP *pTargetBitmap, // Description: Draws this Arm's hand's graphical representation to a BITMAP of // choice. -void Arm::DrawHand(BITMAP *pTargetBitmap, - const Vector &targetPos, - DrawMode mode) const -{ - - Vector handPos(m_JointPos + - m_HandOffset + - (m_Recoiled ? m_RecoilOffset : Vector()) - - targetPos); +void Arm::DrawHand(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode) const { + Vector handPos(m_JointPos + m_HandOffset + (m_Recoiled ? m_RecoilOffset : Vector()) - targetPos); handPos.m_X -= (m_pHand->w / 2) + 1; handPos.m_Y -= (m_pHand->h / 2) + 1; - if (!m_HFlipped) - draw_sprite(pTargetBitmap, m_pHand, handPos.GetRoundIntX(), handPos.GetRoundIntY()); - else - draw_sprite_h_flip(pTargetBitmap, m_pHand, handPos.GetRoundIntX(), handPos.GetRoundIntY()); + if (!m_HFlipped) { + if (mode == g_DrawWhite) { + draw_character_ex(pTargetBitmap, m_pHand, handPos.GetRoundIntX(), handPos.GetRoundIntY(), g_WhiteColor, -1); + } else { + draw_sprite(pTargetBitmap, m_pHand, handPos.GetRoundIntX(), handPos.GetRoundIntY()); + } + } else { + //TODO this won't draw flipped. It should draw onto a temp bitmap and then draw that flipped. Maybe it can reuse a temp bitmap from MOSR, maybe not? + if (mode == g_DrawWhite) { + draw_character_ex(pTargetBitmap, m_pHand, handPos.GetRoundIntX(), handPos.GetRoundIntY(), g_WhiteColor, -1); + } else { + draw_sprite_h_flip(pTargetBitmap, m_pHand, handPos.GetRoundIntX(), handPos.GetRoundIntY()); + } + } } } // namespace RTE \ No newline at end of file diff --git a/Entities/Arm.h b/Entities/Arm.h index 64c5c091e..048ec26f8 100644 --- a/Entities/Arm.h +++ b/Entities/Arm.h @@ -98,17 +98,6 @@ ClassInfoGetters void Destroy(bool notInherited = false) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this Arm, including the mass of any device it -// may be holding. -// Arguments: None. -// Return value: A float describing the mass value in Kilograms (kg). - - float GetMass() const override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetHandPos ////////////////////////////////////////////////////////////////////////////////////////// @@ -185,17 +174,6 @@ ClassInfoGetters float GetMaxLength() const { return m_MaxLength; } - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: SetID -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the MOID of this MovableObject for this frame. -// Arguments: A moid specifying the MOID that this MovableObject is -// assigned for this frame. -// Return value: None. - - void SetID(const MOID newID) override; - /// /// Replaces the MovableObject currently held by this arm with a new one. Ownership IS transferred. /// The currently held MovableObject (if there is one) will be dropped and become a detached MovableObject. @@ -413,16 +391,6 @@ ClassInfoGetters void DrawHand(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor) const; - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Puts all MOIDs associated with this MO and all it's descendants into MOIDs vector -// Arguments: Vector to store MOIDs -// Return value: None. - - void GetMOIDs(std::vector &MOIDs) const override; - ////////////////////////////////////////////////////////////////////////////////////////// // Protected member variable and method declarations @@ -440,21 +408,6 @@ ClassInfoGetters bool ConstrainHand(); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: UpdateChildMOIDs -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes this MO register itself and all its attached children in the -// MOID register and get ID:s for itself and its children for this frame. -// Arguments: The MOID index to register itself and its children in. -// The MOID of the root MO of this MO, ie the highest parent of this MO. -// 0 means that this MO is the root, ie it is owned by MovableMan. -// Whether this MO should make a new MOID to use for itself, or to use -// the same as the last one in the index (presumably its parent), -// Return value: None. - - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; - - // Member variables static Entity::ClassInfo m_sClass; // // The location of the 'hand' in relation to the MovableObject::m_Pos diff --git a/Entities/Turret.h b/Entities/Turret.h index 743bec717..7963fedd8 100644 --- a/Entities/Turret.h +++ b/Entities/Turret.h @@ -106,14 +106,10 @@ namespace RTE { protected: - //This dies soon - void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; - - static Entity::ClassInfo m_sClass; //!< ClassInfo for this class. - HeldDevice *m_MountedDevice; // Date: Tue, 8 Sep 2020 01:24:34 -0300 Subject: [PATCH 033/144] Added setter for DrawnAfterParent and fixed a bit of comments in Attachable (this was used in AHuman changes that were accidentally committed in c9b81ff) --- Entities/Attachable.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Entities/Attachable.h b/Entities/Attachable.h index fb896f03c..757caf28a 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -103,11 +103,17 @@ namespace RTE { void SetParentOffset(const Vector &newParentOffset) { m_ParentOffset = newParentOffset; } /// - /// Gets whether this Attachable is to be drawn after (in front of) or before (behind) the parent. + /// Gets whether this Attachable is to be drawn after (in front of) or before (behind) its parent. /// /// Whether this Attachable is to be drawn after its parent or not. bool IsDrawnAfterParent() const override { return m_DrawAfterParent; } + /// + /// Sets whether this Attachabe is to be drawn after (in front of) or before (behind) its parent. + /// + /// Whether this Attachable is to be drawn after its parent. + void SetDrawnAfterParent(bool drawAfterParent) { m_DrawAfterParent = drawAfterParent; } + /// /// Gets whether this Attachable should be drawn normally by its parent. /// Some attachables (e.g. AEmitter flashes) require custom handling for when they should or shouldn't draw, to be done by the specific parent class. From fcc75159b256d677f0ce514c4e5acf8bb443ada6 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 8 Sep 2020 18:50:16 -0300 Subject: [PATCH 034/144] Finished work on Leg - solved all TODOs, fixed bugs, cleaned up code, renamed methods, cleaned up comments etc. Fixed ACrab, ACRocket and AHuman to deal with renamed Leg methods --- Entities/ACRocket.cpp | 12 ++--- Entities/ACrab.cpp | 8 +-- Entities/AHuman.cpp | 4 +- Entities/Leg.cpp | 116 +++++++++++++++++++----------------------- Entities/Leg.h | 40 ++++++++------- 5 files changed, 86 insertions(+), 94 deletions(-) diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 9f5d41de6..f60a2bbf8 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -794,11 +794,11 @@ void ACRocket::Update() m_pRLeg->SetJointPos(m_Pos + m_pRLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); /* Obsolete if (!m_pMThruster->IsEmitting()) - m_pRLeg->SetTargetOffset(m_Pos + Vector(18, 40) * m_Rotation); + m_pRLeg->SetTargetPosition(m_Pos + Vector(18, 40) * m_Rotation); else - m_pRLeg->SetTargetOffset(m_Pos + Vector(13, 40) * m_Rotation); + m_pRLeg->SetTargetPosition(m_Pos + Vector(13, 40) * m_Rotation); */ - m_pRLeg->SetTargetOffset(m_pRFootGroup->GetLimbPos(m_HFlipped)); + m_pRLeg->SetTargetPosition(m_pRFootGroup->GetLimbPos(m_HFlipped)); m_pRLeg->Update(); m_Health -= m_pRLeg->CollectDamage(); } @@ -808,11 +808,11 @@ void ACRocket::Update() m_pLLeg->SetJointPos(m_Pos + m_pLLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); /* Obsolete if (!m_pMThruster->IsEmitting()) - m_pLLeg->SetTargetOffset(m_Pos + Vector(-18, 40) * m_Rotation); + m_pLLeg->SetTargetPosition(m_Pos + Vector(-18, 40) * m_Rotation); else - m_pLLeg->SetTargetOffset(m_Pos + Vector(-13, 40) * m_Rotation); + m_pLLeg->SetTargetPosition(m_Pos + Vector(-13, 40) * m_Rotation); */ - m_pLLeg->SetTargetOffset(m_pLFootGroup->GetLimbPos(!m_HFlipped)); + m_pLLeg->SetTargetPosition(m_pLFootGroup->GetLimbPos(!m_HFlipped)); m_pLLeg->Update(); m_Health -= m_pLLeg->CollectDamage(); } diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 14df53589..4f48450d2 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -2736,7 +2736,7 @@ void ACrab::Update() m_pLFGLeg->SetJointPos(m_Pos + m_pLFGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pLFGLeg->EnableIdle(m_Status != UNSTABLE); - m_pLFGLeg->SetTargetOffset(m_pLFGFootGroup->GetLimbPos(m_HFlipped)); + m_pLFGLeg->SetTargetPosition(m_pLFGFootGroup->GetLimbPos(m_HFlipped)); m_pLFGLeg->Update(); m_Health -= m_pLFGLeg->CollectDamage(); } @@ -2749,7 +2749,7 @@ void ACrab::Update() m_pLBGLeg->SetJointPos(m_Pos + m_pLBGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pLBGLeg->EnableIdle(m_Status != UNSTABLE); - m_pLBGLeg->SetTargetOffset(m_pLBGFootGroup->GetLimbPos(m_HFlipped)); + m_pLBGLeg->SetTargetPosition(m_pLBGFootGroup->GetLimbPos(m_HFlipped)); m_pLBGLeg->Update(); m_Health -= m_pLBGLeg->CollectDamage(); } @@ -2759,7 +2759,7 @@ void ACrab::Update() m_pRFGLeg->SetHFlipped(m_HFlipped); m_pRFGLeg->SetJointPos(m_Pos + m_pRFGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pRFGLeg->EnableIdle(m_Status != UNSTABLE); - m_pRFGLeg->SetTargetOffset(m_pRFGFootGroup->GetLimbPos(m_HFlipped)); + m_pRFGLeg->SetTargetPosition(m_pRFGFootGroup->GetLimbPos(m_HFlipped)); m_pRFGLeg->Update(); m_Health -= m_pRFGLeg->CollectDamage(); } @@ -2770,7 +2770,7 @@ void ACrab::Update() m_pRBGLeg->SetJointPos(m_Pos + m_pRBGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pRBGLeg->EnableIdle(m_Status != UNSTABLE); - m_pRBGLeg->SetTargetOffset(m_pRBGFootGroup->GetLimbPos(m_HFlipped)); + m_pRBGLeg->SetTargetPosition(m_pRBGFootGroup->GetLimbPos(m_HFlipped)); m_pRBGLeg->Update(); m_Health -= m_pRBGLeg->CollectDamage(); } diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index c3f2d39cb..f6aed732d 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -4087,7 +4087,7 @@ void AHuman::Update() m_pFGLeg->SetJointPos(m_Pos + m_pFGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pFGLeg->EnableIdle(m_ProneState == NOTPRONE && m_Status != UNSTABLE); // if (!m_ArmClimbing[FGROUND]) - m_pFGLeg->SetTargetOffset(m_pFGFootGroup->GetLimbPos(m_HFlipped)); + m_pFGLeg->SetTargetPosition(m_pFGFootGroup->GetLimbPos(m_HFlipped)); m_pFGLeg->Update(); m_Health -= m_pFGLeg->CollectDamage(); } @@ -4099,7 +4099,7 @@ void AHuman::Update() // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise m_pBGLeg->EnableIdle(m_ProneState == NOTPRONE && m_Status != UNSTABLE); // if (!m_ArmClimbing[BGROUND]) - m_pBGLeg->SetTargetOffset(m_pBGFootGroup->GetLimbPos(m_HFlipped)); + m_pBGLeg->SetTargetPosition(m_pBGFootGroup->GetLimbPos(m_HFlipped)); m_pBGLeg->Update(); m_Health -= m_pBGLeg->CollectDamage(); } diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index feecf2e36..d41cdcac1 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -7,17 +7,21 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //TODO Organize these void Leg::Clear() { m_Foot = 0; + m_ContractedOffset.Reset(); m_ExtendedOffset.Reset(); + m_MinExtension = 0; m_MaxExtension = 0; m_CurrentNormalizedExtension = 0; - m_TargetOffset.Reset(); + + m_TargetPosition.Reset(); m_IdleOffset.Reset(); + m_CurrentAnkleOffset.Reset(); + m_WillIdle = false; m_MoveSpeed = 0; } @@ -29,8 +33,11 @@ namespace RTE { return -1; } + // Ensure Legs don't get flagged as inheriting RotAngle, since they never do and always set their RotAngle for themselves. + m_InheritsRotAngle = false; + if (m_ContractedOffset.GetMagnitude() > m_ExtendedOffset.GetMagnitude()) { - std::swap(m_ContractedOffset, m_ExtendedOffset); //TODO dunno if this'll work, swapping if needed so contracted always < extended + std::swap(m_ContractedOffset, m_ExtendedOffset); } m_MinExtension = m_ContractedOffset.GetMagnitude(); @@ -47,12 +54,16 @@ namespace RTE { m_ContractedOffset = reference.m_ContractedOffset; m_ExtendedOffset = reference.m_ExtendedOffset; + m_MinExtension = reference.m_MinExtension; m_MaxExtension = reference.m_MaxExtension; m_CurrentNormalizedExtension = reference.m_CurrentNormalizedExtension; - m_TargetOffset = reference.m_TargetOffset; + + m_TargetPosition = reference.m_TargetPosition; m_IdleOffset = reference.m_IdleOffset; + m_CurrentAnkleOffset = reference.m_CurrentAnkleOffset; + m_WillIdle = reference.m_WillIdle; m_MoveSpeed = reference.m_MoveSpeed; @@ -63,9 +74,11 @@ namespace RTE { int Leg::ReadProperty(std::string propName, Reader &reader) { if (propName == "Foot") { - const Entity *pObj = g_PresetMan.GetEntityPreset(reader); - if (pObj) { - m_Foot = dynamic_cast(pObj->Clone()); + delete m_Foot; + const Entity *footEntity = g_PresetMan.GetEntityPreset(reader); + if (footEntity) { + m_Foot = dynamic_cast(footEntity->Clone()); + m_Foot->SetInheritsRotAngle(false); // Foot RotAngles are handled specially by Leg. } } else if (propName == "ContractedOffset") { reader >> m_ContractedOffset; @@ -73,15 +86,6 @@ namespace RTE { } else if (propName == "ExtendedOffset") { reader >> m_ExtendedOffset; m_MaxExtension = m_ExtendedOffset.GetMagnitude(); - } else if (propName == "MaxLength") { - //TODO Get rid of this, it's used only for rocket leg I think - float maxLength; - reader >> maxLength; - - m_MinExtension = maxLength / 2; - m_ContractedOffset.SetXY(m_MinExtension, 0); - m_MaxExtension = maxLength; - m_ExtendedOffset.SetXY(m_MaxExtension, 0); } else if (propName == "IdleOffset") { reader >> m_IdleOffset; } else if (propName == "WillIdle") { @@ -129,45 +133,41 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Leg::Update() { - Attachable::Update(); + UpdateCurrentAnkleOffsetAndFootParentOffset(); - UpdateCurrentAnkleOffset(); + Attachable::Update(); UpdateLegRotation(); - UpdateFrameAndNormalizedExtension(); + UpdateLegFrameAndNormalizedExtension(); - UpdateFootFrameJointPositionAndRotation(); + UpdateFootFrameAndRotation(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Leg::UpdateCurrentAnkleOffset() { + void Leg::UpdateCurrentAnkleOffsetAndFootParentOffset() { if (IsAttached()) { - Vector targetPosition = g_SceneMan.ShortestDistance(m_JointPos, m_TargetOffset, g_SceneMan.SceneWrapsX()); - if (m_WillIdle && targetPosition.m_Y < -3) { - targetPosition = m_IdleOffset.GetXFlipped(m_HFlipped); + Vector targetOffset = g_SceneMan.ShortestDistance(m_JointPos, m_TargetPosition, g_SceneMan.SceneWrapsX()); + if (m_WillIdle && targetOffset.m_Y < -3) { + targetOffset = m_IdleOffset.GetXFlipped(m_HFlipped); } - //TODO DELETE IF NEVER TRIGGERED ELSE INTEGRATE - if (targetPosition.GetMagnitude() > m_MaxExtension) { - int a = 0; - } - - Vector distanceToTargetPosition(targetPosition - m_CurrentAnkleOffset); - distanceToTargetPosition.SetMagnitude(std::min(distanceToTargetPosition.GetMagnitude(), m_MaxExtension)); - m_CurrentAnkleOffset += distanceToTargetPosition * m_MoveSpeed; - - //TODO DELETE IF NEVER TRIGGERED ELSE INTEGRATE BETTER - if (m_CurrentAnkleOffset.GetMagnitude() > m_MaxExtension) { - m_CurrentAnkleOffset.SetMagnitude(m_MaxExtension); - } else if (m_CurrentAnkleOffset.GetMagnitude() < m_MinExtension) { - m_CurrentAnkleOffset.SetMagnitude(m_MinExtension + 0.1F); - } + Vector distanceFromTargetOffsetToAnkleOffset(targetOffset - m_CurrentAnkleOffset); + m_CurrentAnkleOffset += distanceFromTargetOffsetToAnkleOffset * m_MoveSpeed; + m_CurrentAnkleOffset.ClampMagnitude(m_MaxExtension, m_MinExtension + 0.1F); } else { m_CurrentAnkleOffset.SetXY(m_MaxExtension * 0.60F, 0); m_CurrentAnkleOffset.RadRotate((m_HFlipped ? c_PI : 0) + m_Rotation.GetRadAngle()); } + + if (m_Foot) { + // In order to keep the ankle in the right place, we need to convert its offset to work as the ParentOffset for the foot. The Foot will then use this to set its JointPos when it's updated. + // Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. + Vector ankleOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_CurrentAnkleOffset; + ankleOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); + m_Foot->SetParentOffset(ankleOffsetAsParentOffset); + } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -176,14 +176,14 @@ namespace RTE { if (IsAttached()) { m_Rotation = m_CurrentAnkleOffset.GetAbsRadAngle() + (m_HFlipped ? c_PI : 0); - // Get normalized scalar for how much of the difference in angle between the contracted and extrended offsets should be applied. EaseOut is used to get the sine effect needed + // Get a normalized scalar for where the Leg should be rotated to between the contracted and extended offsets. EaseOut is used to get the sine effect needed. float extraRotationRatio = (EaseOut(m_MinExtension, m_MaxExtension, m_CurrentNormalizedExtension) - m_MinExtension) / (m_MaxExtension - m_MinExtension); - // The contracted offset's inverse angle is the base for the rotation correction + // The contracted offset's inverse angle is the base for the rotation correction. float extraRotation = -(m_ContractedOffset.GetAbsRadAngle()); // Get the actual amount of extra rotation correction needed from the ratio, somewhere on the arc between contracted and extended angles. - // This is negative because it's a correction, the bitmap needs to rotate back to align the ankle with where it's supposed to be in the sprite + // This is negative because it's a correction, the bitmap needs to rotate back to align the ankle with where it's supposed to be in the sprite. extraRotation -= (m_ExtendedOffset.GetAbsRadAngle() - m_ContractedOffset.GetAbsRadAngle()) * extraRotationRatio; m_Rotation.SetRadAngle(m_Rotation.GetRadAngle() + extraRotation * static_cast(GetFlipFactor())); @@ -192,46 +192,34 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Leg::UpdateFrameAndNormalizedExtension() { + void Leg::UpdateLegFrameAndNormalizedExtension() { if (m_FrameCount == 1) { m_Frame = 0; - return; + } else { + m_CurrentNormalizedExtension = Limit((m_CurrentAnkleOffset.GetMagnitude() - m_MinExtension) / (m_MaxExtension - m_MinExtension), 1.0F, 0.0F); + m_Frame = std::min(m_FrameCount - 1, static_cast(floorf(m_CurrentNormalizedExtension * static_cast(m_FrameCount)))); } - - //TODO Test out the math here and with frame setting stuff, I don't trust/understand this and I wonder if we can maybe change the frame stuff to build the clamping in - float extensionRange = m_MaxExtension - m_MinExtension; - m_CurrentNormalizedExtension = (m_CurrentAnkleOffset.GetMagnitude() - (m_MaxExtension - extensionRange)) / extensionRange; - Clamp(m_CurrentNormalizedExtension, 1.0F, 0.0F); - - m_Frame = std::min(m_FrameCount - 1, static_cast(floorf(m_CurrentNormalizedExtension * static_cast(m_FrameCount)))); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Leg::UpdateFootFrameJointPositionAndRotation() { + void Leg::UpdateFootFrameAndRotation() { if (m_Foot) { - m_Foot->SetJointPos(m_JointPos + m_CurrentAnkleOffset); //TODO parentoffset for feet is left at (0,0). It may be able to be used here (need to understand how rotation is done right now!) so jointpos stuff can live in Attachable entirely. - if (IsAttached()) { - //TODO I wonder if we could use m_CurrentAnkleOffset for this instead? - float targetHorizontalDistanceAccountingForFlipping = g_SceneMan.ShortestDistance(m_JointPos, m_TargetOffset, g_SceneMan.SceneWrapsX()).m_X * static_cast(GetFlipFactor()); - if (targetHorizontalDistanceAccountingForFlipping < -10) { + float ankleOffsetHorizontalDistanceAccountingForFlipping = m_CurrentAnkleOffset.GetXFlipped(m_HFlipped).GetX(); + if (ankleOffsetHorizontalDistanceAccountingForFlipping < -10) { m_Foot->SetFrame(3); - //TODO this should probably be setting rotangle to 0 too, check if it's changing at any point in time and if not, unify - } else if (targetHorizontalDistanceAccountingForFlipping < -6) { + } else if (ankleOffsetHorizontalDistanceAccountingForFlipping < -6) { m_Foot->SetFrame(2); - m_Foot->SetRotAngle(0.0F); - } else if (targetHorizontalDistanceAccountingForFlipping > 6) { + } else if (ankleOffsetHorizontalDistanceAccountingForFlipping > 6) { m_Foot->SetFrame(1); - m_Foot->SetRotAngle(0.0F); } else { m_Foot->SetFrame(0); - m_Foot->SetRotAngle(0.0F); } + m_Foot->SetRotAngle(0.0F); } else { m_Foot->SetRotAngle(m_Rotation.GetRadAngle() + c_PI / 2); } - //m_Foot->Update(); //TODO this may need reorganizing } } } \ No newline at end of file diff --git a/Entities/Leg.h b/Entities/Leg.h index ef12beaae..cca07fd6f 100644 --- a/Entities/Leg.h +++ b/Entities/Leg.h @@ -8,7 +8,7 @@ namespace RTE { class HeldDevice; /// - /// A detatchable leg that will be controlled by LimbPaths. + /// A detatchable Leg that will be controlled by LimbPaths. /// class Leg : public Attachable { @@ -69,20 +69,25 @@ namespace RTE { void SetFoot(Attachable *newFoot); /// - /// Gets the max length this Leg can reach from its socket to the foot. + /// Gets the min length this of Leg, the minimum allowed length from its joint to its ankle's position. /// - /// The max length of reach, in pixels, of this Leg. + /// The min length, in pixels, of this Leg. + float GetMinLength() const { return m_MinExtension; } + + /// + /// Gets the max length this Leg, the maximum allowed length from its joint to its ankle's position. + /// + /// The max length, in pixels, of this Leg. float GetMaxLength() const { return m_MaxExtension; } - //TODO I think this is in absolute scene coordinates actually, since it works based off of joint pos not joint offset. Look into this and update accordingly. Also look at the member variable, the (0, 0) thing seems wrong. /// - /// Sets the point the Leg should move towards, in relative coordinates. + /// Sets the position this Leg should move towards, in absolute coordinates. /// - /// The offset the Leg should move towards. - void SetTargetOffset(const Vector &targetOffset) { m_TargetOffset = targetOffset; } + /// The position the Leg should move towards. + void SetTargetPosition(const Vector &targetPosition) { m_TargetPosition = targetPosition; } /// - /// Sets this to go into idle offset mode if the target appears to be above the joint of the Leg. + /// Sets whether this Leg will go into idle offset mode if the target appears to be above the joint of the Leg. /// /// Whether to enable idling if the target offset is above the joint. void EnableIdle(bool idle = true) { m_WillIdle = idle; } @@ -106,21 +111,21 @@ namespace RTE { float m_MaxExtension; //!< Precalculated max extension of the Leg (from the joint) based on the extended offset. float m_CurrentNormalizedExtension; //!< Normalized scalar of where the ankle offset's magnitude is between the min and max extensions - Vector m_TargetOffset; //!< The target offset that this Leg's foot is moving towards. If (0, 0), the Leg will not try towards anything. - Vector m_IdleOffset; //!< The target offset from m_Pos that this Leg's foot is reaching towards when not reaching for or anything else. + Vector m_TargetPosition; //!< The absolute position that this Leg's foot is moving towards. + Vector m_IdleOffset; //!< The target offset from m_Pos that this Leg's foot is moving towards when allowed to idle and the target position is not acceptable. Vector m_CurrentAnkleOffset; //!< Current offset from the joint to the ankle where the foot should be. - bool m_WillIdle; //!< Whether the Leg will go to idle position if the target is above the joint. + bool m_WillIdle; //!< Whether the Leg will go to idle position if the target position is above the Leg's joint position. float m_MoveSpeed; //!< How fast the Leg moves to a reach target, 0 means it doesn't and 1 means it moves instantly. private: /// - /// Updates the current ankle offset for this Leg. Should only be called from Update. + /// Updates the current ankle offset for this Leg, and sets the foot's parent offset to match up with it. Should only be called from Update. /// If the Leg is attached, the current ankle offset is based on the target offset and move speed, and whether the Leg should idle or not, otherwise it puts it in a reasonable position. /// - void UpdateCurrentAnkleOffset(); + void UpdateCurrentAnkleOffsetAndFootParentOffset(); /// /// Updates the rotation of the Leg. Should only be called from Update. @@ -132,14 +137,13 @@ namespace RTE { /// Sets the Leg's frame to the appropriate one based on its current extension, and updates the normalized extension value. Should only be called from Update. /// Works the same whether attached or not. /// - void UpdateFrameAndNormalizedExtension(); + void UpdateLegFrameAndNormalizedExtension(); /// - /// Updates the frame, joint position and rotation of the Leg's foot Attachable. Should only be called from Update. - /// If the Leg is attached, the rotation and frame depend on the target offset, otherwise the rotation is set to be perpendicular to the Leg. - /// The joint position is always updated to include the current ankle offset so the foot Attachable stays in the appropriate position. + /// Updates the frame and rotation of the Leg's foot Attachable. Should only be called from Update. + /// If the Leg is attached, the foot's rotation and frame depend on the ankle offset, otherwise the foot's rotation is set to be perpendicular to the Leg's rotation. /// - void UpdateFootFrameJointPositionAndRotation(); + void UpdateFootFrameAndRotation(); /// /// Clears all the member variables of this Leg, effectively resetting the members of this abstraction level only. From 37c3a510e8bf70c120924a02e5da663586982aa5 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 8 Sep 2020 18:54:00 -0300 Subject: [PATCH 035/144] Added ClampMagnitude method to Vector that does what it says on the box Added luabinding for ClampMagnitude --- Managers/LuaMan.cpp | 1 + System/Vector.cpp | 16 ++++++++++++++++ System/Vector.h | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 66c47ba98..85a9d0613 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -505,6 +505,7 @@ int LuaMan::Create() .property("AbsRadAngle", &Vector::GetAbsRadAngle) .property("AbsDegAngle", &Vector::GetAbsDegAngle) .def("CapMagnitude", &Vector::CapMagnitude) + .def("ClampMagnitude", &Vector::ClampMagnitude) .def("FlipX", &Vector::FlipX) .def("FlipY", &Vector::FlipY) .def("IsZero", &Vector::IsZero) diff --git a/System/Vector.cpp b/System/Vector.cpp index 45f204002..dfc37d8ac 100644 --- a/System/Vector.cpp +++ b/System/Vector.cpp @@ -49,6 +49,22 @@ namespace RTE { return *this; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Vector & Vector::ClampMagnitude(float upperLimit, float lowerLimit) { + if (upperLimit < lowerLimit) { + std::swap(upperLimit, lowerLimit); + } + if (upperLimit == 0 && lowerLimit == 0) { + Reset(); + } else if (GetMagnitude() > upperLimit) { + SetMagnitude(upperLimit); + } else if (GetMagnitude() < lowerLimit) { + SetMagnitude(lowerLimit); + } + return *this; + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float Vector::GetAbsRadAngle() const { diff --git a/System/Vector.h b/System/Vector.h index 2bca7a3a6..e4ff6ac22 100644 --- a/System/Vector.h +++ b/System/Vector.h @@ -203,6 +203,14 @@ namespace RTE { /// A reference to this after the change. Vector & CapMagnitude(float capMag); + /// + /// Clamps the magnitude of this Vector between the upper and lower limits, and keeps its angle intact. + /// + /// A float value that defines the upper limit for the magnitude. + /// A float value that defines the lower limit for the magnitude. + /// A reference to this after the change. + Vector & ClampMagnitude(float upperMagnitudeLimit, float lowerMagnitudeLimit); + /// /// Returns a Vector that has the same direction as this but with a magnitude of 1.0. /// From f3635b75c8d5a24b9c135bc6c6b40d27cfb30397 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 9 Sep 2020 00:13:02 -0300 Subject: [PATCH 036/144] Changed GibThis to use a const Vector reference for impactImpulse Cleaned up a bit of leftover questionable code in Attachable that I'd needed to test Cleaned up some header comments in MOSR and cleaned up MOSR update --- Entities/Attachable.cpp | 15 +++---- Entities/Attachable.h | 2 +- Entities/MOSRotating.cpp | 46 ++++++------------- Entities/MOSRotating.h | 96 ++++++++++++++++++---------------------- 4 files changed, 61 insertions(+), 98 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index caf05af74..e6784e22b 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -245,8 +245,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //TODO change impactImpulse to a const reference Vector - void Attachable::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { + void Attachable::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { if (m_Parent) { m_Parent->RemoveAttachable(this); } else { @@ -259,21 +258,17 @@ namespace RTE { void Attachable::Update() { if (!m_Parent) { - //TODO right now parents are responsible for setting JointPos. The only one that seems to do much with this is Leg, everything else looks much the same. I'd rather attachables do this internally cause that makes way more sense. Will take some cleanup though. m_JointPos = m_Pos + RotateOffset(m_JointOffset); } else { m_PrevPos = m_Pos; m_PrevVel = m_Vel; - if (!m_JointPos.IsZero()) { - m_Pos = m_JointPos - RotateOffset(m_JointOffset); - } else { - m_Pos = m_Parent->GetPos() - RotateOffset(m_JointOffset); - } + m_JointPos = m_Parent->GetPos() + m_Parent->RotateOffset(GetParentOffset()); + m_Pos = m_JointPos - RotateOffset(m_JointOffset); m_Vel = m_Parent->GetVel(); m_Team = m_Parent->GetTeam(); - - //TODO RotAngle should be set here based on whether or not this InheritsRotAngle. It's currently done by MOSR which is dumdum. Alternatively, see below. + m_HFlipped = m_Parent->IsHFlipped(); + if (InheritsRotAngle()) { SetRotAngle(m_Parent->GetRotAngle()); } m_DeepCheck = false; } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 757caf28a..5a8afc575 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -325,7 +325,7 @@ namespace RTE { /// The impulse (kg * m/s) of the impact causing the gibbing to happen. /// The internal blast impulse which will push the gibs away from the center. /// A pointer to an MO which the gibs should not be colliding with! - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *MOToIgnore = 0) override; + void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *MOToIgnore = 0) override; /// /// Updates this Attachable. Supposed to be done every frame. diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 5f278d35d..360265448 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -966,7 +966,7 @@ bool MOSRotating::ParticlePenetration(HitData &hd) // Description: Gibs this, effectively destroying it and creating multiple gibs or // pieces in its place. -void MOSRotating::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) +void MOSRotating::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { // Can't, or is already gibbed, so don't do anything if (m_MissionCritical || m_ToDelete) @@ -1494,66 +1494,46 @@ void MOSRotating::PostTravel() ////////////////////////////////////////////////////////////////////////////////////////// // Description: Updates this MOSRotating. Supposed to be done every frame. -void MOSRotating::Update() -{ - -#if defined DEBUG_BUILD || defined MIN_DEBUG_BUILD +void MOSRotating::Update() { RTEAssert(m_MOID == g_NoMOID || (m_MOID >= 0 && m_MOID < g_MovableMan.GetMOIDCount()), "MOID out of bounds!"); -#endif MOSprite::Update(); - if (m_InheritEffectRotAngle) - m_EffectRotAngle = m_Rotation.GetRadAngle(); - - // Align the orienatation with the velocity vector, if any - if (m_OrientToVel > 0 && m_Vel.GetLargest() > 5.0) - { - // Clamp - if (m_OrientToVel > 1.0) - m_OrientToVel = 1.0; + if (m_InheritEffectRotAngle) { + m_EffectRotAngle = m_Rotation.GetRadAngle(); + } - // Velocity influence - float velInfluence = m_OrientToVel < 1.0 ? m_Vel.GetMagnitude() / 100 : 1.0f; - if (velInfluence > 1.0) - velInfluence = 1.0; + if (m_OrientToVel > 0 && m_Vel.GetLargest() > 5.0) { + Clamp(m_OrientToVel, 1.0F, 0.0F); - // Figure the difference in current velocity vector and + float velInfluence = Limit(m_OrientToVel < 1.0 ? m_Vel.GetMagnitude() / 100 : 1.0F, 1.0F, 0.0F); float radsToGo = m_Rotation.GetRadAngleTo(m_Vel.GetAbsRadAngle()); m_Rotation += (radsToGo * m_OrientToVel * velInfluence); } - // Update all the attached wound emitters for (AEmitter *wound : m_Wounds) { RTEAssert(wound, "Broken wound AEmitter"); - wound->SetJointPos(m_Pos + RotateOffset(wound->GetParentOffset())); wound->Update(); } - // Update all the attachables Attachable *pAttachable = 0; for (list::iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ) { pAttachable = *aItr; RTEAssert(pAttachable, "Broken Attachable!"); ++aItr; - pAttachable->SetHFlipped(m_HFlipped); - pAttachable->SetJointPos(m_Pos + RotateOffset((pAttachable)->GetParentOffset())); - if (pAttachable->InheritsRotAngle()) - { - pAttachable->SetRotAngle(m_Rotation.GetRadAngle()); - } pAttachable->Update(); ApplyAttachableForces(pAttachable); } - // Create intermediate flipping bitmap if there isn't one yet - if (m_HFlipped && !m_pFlipBitmap && m_aSprite[0]) + // Create intermediate flipping bitmaps if they don't exist + if (m_HFlipped && !m_pFlipBitmap && m_aSprite[0]) { m_pFlipBitmap = create_bitmap_ex(8, m_aSprite[0]->w, m_aSprite[0]->h); - - if (m_HFlipped && !m_pFlipBitmapS && m_aSprite[0]) + } + if (m_HFlipped && !m_pFlipBitmapS && m_aSprite[0]) { m_pFlipBitmapS = create_bitmap_ex(c_MOIDLayerBitDepth, m_aSprite[0]->w, m_aSprite[0]->h); + } } diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 3f6a35986..5be3b18dc 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -340,7 +340,7 @@ ClassInfoGetters // A pointer to an MO which the gibs shuold not be colliding with! // Return value: None. - virtual void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0); + virtual void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0); ////////////////////////////////////////////////////////////////////////////////////////// @@ -381,14 +381,14 @@ ClassInfoGetters void ApplyImpulses() override; /// - /// Adds the passed in Attachable the list of attachables and sets its parent to this MOSRotating. + /// Adds the passed in Attachable the list of Attachables and sets its parent to this MOSRotating. /// /// The Attachable to add. void AddAttachable(Attachable *attachable); /// - /// Attaches the passed in Attachable and adds it to the list of attachables, changing its parent offset to the passed in Vector but not treating it as hardcoded. - /// Adds the passed in Attachable the list of attachables, changes its parent offset to the passed in Vector, and sets its parent to this MOSRotating. + /// Attaches the passed in Attachable and adds it to the list of Attachables, changing its parent offset to the passed in Vector but not treating it as hardcoded. + /// Adds the passed in Attachable the list of Attachables, changes its parent offset to the passed in Vector, and sets its parent to this MOSRotating. /// /// The Attachable to add. /// The Vector to set as the Attachable's parent offset. @@ -409,9 +409,9 @@ ClassInfoGetters bool RemoveAttachable(Attachable *attachable); /// - /// Either detaches or deletes all of this MOSRotating's attachables. + /// Either detaches or deletes all of this MOSRotating's Attachables. /// - /// Whether to detach or delete the attachables. Setting this to true deletes them, setting it to false detaches them. + /// Whether to detach or delete the Attachables. Setting this to true deletes them, setting it to false detaches them. void DetachOrDestroyAll(bool destroy); @@ -539,64 +539,52 @@ ClassInfoGetters void Draw(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetGibWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Return wound limit for this object. -// Arguments: None. -// Return value: Wound limit of the object. - - int GetGibWoundLimit() const { return m_GibWoundLimit; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetGibImpulseLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Set new impulse limit. -// Arguments: New impulse limit. -// Return value: None. - - void SetGibImpulseLimit(int newLimit) { m_GibImpulseLimit = newLimit; } - - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetGibImpulseLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Return impulse limit for this object. -// Arguments: None. -// Return value: Impulse limit of the object. - - int GetGibImpulseLimit() const { return m_GibImpulseLimit; } - + /// + /// Gets the gib impulse limit for this MOSRotating, i.e. the amount of impulse force required in a frame to gib this MOSRotating. + /// + /// The gib impulse limit of this MOSRotating. + int GetGibImpulseLimit() const { return m_GibImpulseLimit; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetGibWoundLimit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Set new wound limit, current wounds are not affected. -// Arguments: New wound limit. -// Return value: None. + /// + /// Sets the gib impulse limit for this MOSRotating, i.e. the amount of impulse force required in a frame to gib this MOSRotating. + /// + /// The new gib impulse limit to use. + void SetGibImpulseLimit(int newGibImpulseLimit) { m_GibImpulseLimit = newGibImpulseLimit; } - void SetGibWoundLimit(int newLimit) { m_GibWoundLimit = newLimit; } + /// + /// Gets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. + /// Includes Attachables that transfer damage to this MOSRotating. + /// + /// + int GetGibWoundLimit() const { return GetGibWoundLimit(true, false); } /// - /// Gets the gib wound limit for this MOSRotating, optionally recursively adding the gib wound limit of damaging and/or non-damaging attachables and any of their such attachables, and so on. + /// Gets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. + /// Optionally recursively adds the gib wound limits of damaging and/or non-damaging Attachables and any of their such Attachables. /// - /// Whether to add wound limits of attachables that transfer damage to their parent (this MOSRotating). - /// Whether to add wound limits of attachables that do not transfer damage to their parent (this MOSRotating). - /// The wound limit of this MOSRotating and, optionally, its attachables. + /// Whether to add wound limits of Attachables that transfer damage to their parent (this MOSRotating). + /// Whether to add wound limits of Attachables that do not transfer damage to their parent (this MOSRotating). + /// The wound limit of this MOSRotating and, optionally, its Attachables. int GetGibWoundLimit(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const; + /// + /// Sets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. + /// This will not directly trigger gibbing, even if the limit is lower than the current number of wounds. + /// + /// The new gib wound limit to use. + void SetGibWoundLimit(int newGibWoundLimit) { m_GibWoundLimit = newGibWoundLimit; } + /// /// Gets the number of wounds directly attached to this MOSRotating. /// The number of wounds on this MOSRotating. /// - int GetWoundCount() const { return GetWoundCount(false, false); } + int GetWoundCount() const { return GetWoundCount(true, false); } /// - /// Gets the number of wounds attached to this MOSRotating, optionally recursively including wounds on damaging and/or non-damaging attachables and any of their such attachables, and so on. - /// Whether to count wounds from attachables that transfer damage to their parent (this MOSRotating). - /// Whether to count wounds from attachables that do not transfer damage to their parent (this MOSRotating). - /// The number of wounds on this MOSRotating and, optionally, its attachables. + /// Gets the number of wounds attached to this MOSRotating, optionally recursively including wounds on damaging and/or non-damaging Attachables and any of their such Attachables, and so on. + /// Whether to count wounds from Attachables that transfer damage to their parent (this MOSRotating). + /// Whether to count wounds from Attachables that do not transfer damage to their parent (this MOSRotating). + /// The number of wounds on this MOSRotating and, optionally, its Attachables. /// int GetWoundCount(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const; @@ -619,8 +607,8 @@ ClassInfoGetters /// Optionally only removes wounds that affect health directly. /// /// The number of wounds that should be removed. - /// Whether to remove wounds from attachables that transfer damage to their parent (this MOSRotating). - /// Whether to remove wounds from attachables that do not transfer damage to their parent (this MOSRotating). + /// Whether to remove wounds from Attachables that transfer damage to their parent (this MOSRotating). + /// Whether to remove wounds from Attachables that do not transfer damage to their parent (this MOSRotating). /// The amount of damage caused by the removed wounds. float RemoveWounds(int numberOfWoundsToRemove, bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables); @@ -851,7 +839,7 @@ ClassInfoGetters std::list m_Wounds; // The list of Attachables currently attached and Owned by this. std::list m_Attachables; - std::unordered_set m_AlreadyCopiedAttachableUniqueIDs; // m_AlreadyCopiedAttachableUniqueIDs; // m_Gibs; // The amount of impulse force required to gib this, in kg * (m/s). 0 means no limit From b636b3bd9feb55d4a06a79e44f88e0e10a0de594 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 9 Sep 2020 00:17:41 -0300 Subject: [PATCH 037/144] Forgot to commit these just now, changed GibThis implementers to use new method signature Forgot to commit this earlier, made hands now get drawn in drawtrans mode (i.e. placement during scene edit mode) --- Entities/ACDropShip.cpp | 2 +- Entities/ACDropShip.h | 2 +- Entities/ACRocket.cpp | 2 +- Entities/ACRocket.h | 2 +- Entities/ACrab.cpp | 2 +- Entities/ACrab.h | 2 +- Entities/ADoor.cpp | 2 +- Entities/ADoor.h | 2 +- Entities/AHuman.cpp | 2 +- Entities/AHuman.h | 2 +- Entities/Actor.cpp | 2 +- Entities/Actor.h | 2 +- Entities/Arm.cpp | 5 ++--- Entities/Arm.h | 2 +- 14 files changed, 15 insertions(+), 16 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index e4965edc4..7fb3a8a4b 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -324,7 +324,7 @@ bool ACDropShip::OnSink(const Vector &pos) // Description: Gibs this, effectively destroying it and creating multiple gibs or // pieces in its place. -void ACDropShip::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) +void ACDropShip::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { // TODO: maybe make hardcoded attachables gib if their gib list isn't empty // Detach all limbs and let loose diff --git a/Entities/ACDropShip.h b/Entities/ACDropShip.h index 2485633c5..826b8429b 100644 --- a/Entities/ACDropShip.h +++ b/Entities/ACDropShip.h @@ -153,7 +153,7 @@ ClassInfoGetters // A pointer to an MO which the gibs shuold not be colliding with! // Return value: None. - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; + void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index f60a2bbf8..09ad9306a 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -316,7 +316,7 @@ bool ACRocket::OnSink(const Vector &pos) // Description: Gibs this, effectively destroying it and creating multiple gibs or // pieces in its place. -void ACRocket::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) +void ACRocket::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { // TODO: maybe make hardcoded attachables gib if their gib list isn't empty // Detach all limbs and let loose diff --git a/Entities/ACRocket.h b/Entities/ACRocket.h index b3ddfc1da..0a8f2d182 100644 --- a/Entities/ACRocket.h +++ b/Entities/ACRocket.h @@ -147,7 +147,7 @@ ClassInfoGetters // A pointer to an MO which the gibs shuold not be colliding with! // Return value: None. - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; + void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 4f48450d2..11f70d514 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -941,7 +941,7 @@ MovableObject * ACrab::LookForMOs(float FOVSpread, unsigned char ignoreMaterial, // Description: Gibs this, effectively destroying it and creating multiple gibs or // pieces in its place. -void ACrab::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) +void ACrab::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { // Detach all limbs and let loose if (m_pTurret && m_pTurret->IsAttached()) diff --git a/Entities/ACrab.h b/Entities/ACrab.h index 1023213ac..61daccba4 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -413,7 +413,7 @@ int FirearmActivationDelay() const; // A pointer to an MO which the gibs shuold not be colliding with! // Return value: None. - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; + void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index 47a266493..28b4c93eb 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -264,7 +264,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void ADoor::GibThis(Vector impactImpulse, float internalBlast, MovableObject *ignoreMO) { + void ADoor::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *ignoreMO) { if (m_Door && m_Door->IsAttached()) { EraseDoorMaterial(); m_Door->DeepCheck(true); diff --git a/Entities/ADoor.h b/Entities/ADoor.h index 1589566b3..396344d56 100644 --- a/Entities/ADoor.h +++ b/Entities/ADoor.h @@ -128,7 +128,7 @@ namespace RTE { /// The impulse (kg * m/s) of the impact causing the gibbing to happen. /// The internal blast impulse which will push the gibs away from the center. /// A pointer to an MO which the gibs should not be colliding with! - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *ignoreMO = 0) override; + void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *ignoreMO = 0) override; /// /// Updates this ADoor. Supposed to be done every frame. diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index f6aed732d..2496ae74e 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -1620,7 +1620,7 @@ MovableObject * AHuman::LookForMOs(float FOVSpread, unsigned char ignoreMaterial // Description: Gibs this, effectively destroying it and creating multiple gibs or // pieces in its place. -void AHuman::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) +void AHuman::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { // Detach all limbs and let loose if (m_pHead && m_pHead->IsAttached()) diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 8c209811d..6eae5c113 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -709,7 +709,7 @@ ClassInfoGetters // A pointer to an MO which the gibs shuold not be colliding with! // Return value: None. - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; + void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index b8f1cadf0..574259257 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -973,7 +973,7 @@ void Actor::DropAllInventory() // Description: Gibs this, effectively destroying it and creating multiple gibs or // pieces in its place. -void Actor::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) +void Actor::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { // Play death sound // TODO: Don't attenuate since death is pretty important.. maybe only make this happen for teh brains diff --git a/Entities/Actor.h b/Entities/Actor.h index 7729fb6d9..8d3ba633f 100644 --- a/Entities/Actor.h +++ b/Entities/Actor.h @@ -991,7 +991,7 @@ ClassInfoGetters // A pointer to an MO which the gibs shuold not be colliding with! // Return value: None. - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; + void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 3b6af74d0..456a5eb04 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -365,8 +365,7 @@ bool Arm::ConstrainHand() // Description: Gibs this, effectively destroying it and creating multiple gibs or // pieces in its place. -void Arm::GibThis(Vector impactImpulse, float internalBlast, MovableObject *pIgnoreMO) -{ +void Arm::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { DropEverything(); Attachable::GibThis(impactImpulse, internalBlast, pIgnoreMO); } @@ -540,7 +539,7 @@ void Arm::Update() void Arm::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { Attachable::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); if (m_pHeldMO || (!m_pHeldMO && !m_DidReach) || !m_Parent) { - if (!onlyPhysical && (mode == g_DrawColor || mode == g_DrawWhite)) { + if (!onlyPhysical && (mode == g_DrawColor || mode == g_DrawWhite || mode == g_DrawTrans)) { DrawHand(pTargetBitmap, targetPos, mode); } if (m_pHeldMO && m_pHeldMO->IsDrawnAfterParent()) { diff --git a/Entities/Arm.h b/Entities/Arm.h index 048ec26f8..61cc8e082 100644 --- a/Entities/Arm.h +++ b/Entities/Arm.h @@ -351,7 +351,7 @@ ClassInfoGetters // A pointer to an MO which the gibs shuold not be colliding with! // Return value: None. - void GibThis(Vector impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; + void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; ////////////////////////////////////////////////////////////////////////////////////////// From edd26aa6b18ecdd776f27ad7c25198b971f2a583 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 11 Sep 2020 01:39:39 -0300 Subject: [PATCH 038/144] Removed TransfersDamageToParent from Attachable, just using MOSRotating::DamageMultiplier now. Added flag for whether this was set in INI so hardcoded Attachables can properly modify it as needed. Added Attachable InheritsHFlipped which can be 0 (no inheritance), 1 (inherit directly) or any other number, though 2 is recommended (inherit reversed). Could be split into 2 variables, but I figured this was cleaner, if a little weird. Didn't wanna use -1 since we often use that to mean default value. Changed wound handling stuff to allow for searching for wounds that have a positive damage multipliers, a negative damage multiplier or no damage multiplier, so it can be more fine-grained --- Entities/Attachable.cpp | 30 ++++++++++++--------- Entities/Attachable.h | 40 ++++++++++++++------------- Entities/MOSRotating.cpp | 56 +++++++++++++++++++++----------------- Entities/MOSRotating.h | 58 +++++++++++++++++++++++++--------------- 4 files changed, 106 insertions(+), 78 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index e6784e22b..c3dd87aaa 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -16,7 +16,6 @@ namespace RTE { m_ParentOffset.Reset(); m_DrawAfterParent = true; m_DrawnNormallyByParent = true; - m_TransfersDamageToParent = false; m_DeleteWithParent = false; m_JointStrength = 10; @@ -30,6 +29,7 @@ namespace RTE { m_BreakWound = 0; m_ParentBreakWound = 0; + m_InheritsHFlipped = 1; m_InheritsRotAngle = true; m_AtomSubgroupID = -1; @@ -45,7 +45,6 @@ namespace RTE { m_ParentOffset = reference.m_ParentOffset; m_DrawAfterParent = reference.m_DrawAfterParent; m_DrawnNormallyByParent = reference.m_DrawnNormallyByParent; - m_TransfersDamageToParent = reference.m_TransfersDamageToParent; m_DeleteWithParent = reference.m_DeleteWithParent; m_JointStrength = reference.m_JointStrength; @@ -59,6 +58,7 @@ namespace RTE { m_BreakWound = reference.m_BreakWound; m_ParentBreakWound = reference.m_ParentBreakWound; + m_InheritsHFlipped = reference.m_InheritsHFlipped; m_InheritsRotAngle = reference.m_InheritsRotAngle; m_AtomSubgroupID = reference.m_AtomSubgroupID; @@ -74,8 +74,6 @@ namespace RTE { reader >> m_ParentOffset; } else if (propName == "DrawAfterParent") { reader >> m_DrawAfterParent; - } else if (propName == "TransfersDamageToParent") { - reader >> m_TransfersDamageToParent; } else if (propName == "DeleteWithParent") { reader >> m_DeleteWithParent; } else if (propName == "JointStrength" || propName == "Strength") { @@ -89,6 +87,9 @@ namespace RTE { if (!m_ParentBreakWound) { m_ParentBreakWound = m_BreakWound; } } else if (propName == "ParentBreakWound") { m_ParentBreakWound = dynamic_cast(g_PresetMan.GetEntityPreset(reader)); + } else if (propName == "InheritsHFlipped") { + reader >> m_InheritsHFlipped; + if (m_InheritsHFlipped != 0 && m_InheritsHFlipped != 1) { m_InheritsHFlipped = 2; } } else if (propName == "InheritsRotAngle") { reader >> m_InheritsRotAngle; } else if (propName == "CollidesWithTerrainWhenAttached") { @@ -109,8 +110,6 @@ namespace RTE { writer << m_ParentOffset; writer.NewProperty("DrawAfterParent"); writer << m_DrawAfterParent; - writer.NewProperty("TransfersDamageToParent"); - writer << m_TransfersDamageToParent; writer.NewProperty("DeleteWithParent"); writer << m_DeleteWithParent; @@ -126,8 +125,12 @@ namespace RTE { writer.NewProperty("ParentBreakWound"); writer << m_ParentBreakWound; + writer.NewProperty("InheritsHFlipped"); + if (m_InheritsHFlipped != 0 && m_InheritsHFlipped != 1) { m_InheritsHFlipped = 2; } + writer << m_InheritsHFlipped; writer.NewProperty("InheritsRotAngle"); writer << m_InheritsRotAngle; + writer.NewProperty("CollidesWithTerrainWhileAttached"); writer << m_CollidesWithTerrainWhileAttached; @@ -197,13 +200,16 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float Attachable::CollectDamage() { - float totalDamage = m_DamageCount; - m_DamageCount = 0; + if (m_DamageMultiplier > 0) { + float totalDamage = m_DamageCount; + m_DamageCount = 0; - for (AEmitter *wound : m_Wounds) { - totalDamage += wound->CollectDamage(); + for (AEmitter *wound : m_Wounds) { + totalDamage += wound->CollectDamage(); + } + return totalDamage * m_DamageMultiplier; } - return totalDamage * m_DamageMultiplier; + return 0; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -267,7 +273,7 @@ namespace RTE { m_Pos = m_JointPos - RotateOffset(m_JointOffset); m_Vel = m_Parent->GetVel(); m_Team = m_Parent->GetTeam(); - m_HFlipped = m_Parent->IsHFlipped(); + if (InheritsHFlipped() != 0) { m_HFlipped = m_InheritsHFlipped == 1 ? m_Parent->IsHFlipped() : !m_Parent->IsHFlipped(); } if (InheritsRotAngle()) { SetRotAngle(m_Parent->GetRotAngle()); } m_DeepCheck = false; diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 5a8afc575..7ca328b47 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -128,18 +128,6 @@ namespace RTE { /// Whether this Attachable should be drawn normally by its parent. void SetDrawnNormallyByParent(bool drawnNormallyByParent) { m_DrawnNormallyByParent = drawnNormallyByParent; } - /// - /// Gets whether this Attachable will collect its damage and transfer it to its parent if attached. Transferred damage accounts for the Attachable's damage multiplier. - /// - /// Whether this Attachable will transfer damage to its parent or not. - bool GetTransfersDamageToParent() const { return m_TransfersDamageToParent; } - - /// - /// Sets whether this Attachable will collect its damage and transfer it to its parent if attached. Transferred damage accounts for the Attachable's damage multiplier. - /// - /// Whether this Attachable should transfer damage to its parent. - void SetTransfersDamageToParent(bool transfersDamageToParent) { m_TransfersDamageToParent = transfersDamageToParent; } - /// /// Gets whether this Attachable will be deleted automatically when its parent is being deleted or not. /// @@ -236,10 +224,10 @@ namespace RTE { void AddDamage(float damageAmount) { m_DamageCount += damageAmount; } /// - /// Gets the amount of damage points this Attachable has sustained and should cause its parent, then resets the damage count. - /// This should normally be called AFTER Update() to get the correct damage for a given frame. + /// Calculates the amount of damage this Attachable has sustained since the last time this method was called and returns it, modified by the Attachable's damage multiplier. + /// This should normally be called AFTER updating this Attachable in order to get the correct damage for a given frame. /// - /// A float with the damage points accumulated since the last time this method was called. + /// A float with the damage accumulated, multiplied by the Attachable's damage multiplier, since the last time this method was called. float CollectDamage(); /// @@ -267,11 +255,25 @@ namespace RTE { void SetParentBreakWound(const AEmitter *breakWound) { m_ParentBreakWound = breakWound; } #pragma endregion -#pragma region Rotation Getters and Setters +#pragma region Inherited Value Getters and Setters + /// + /// Gets whether or not this Attachable inherits its parent's HFlipped value, i.e. whether it has its HFlipped value reset to match/reverse its parent's every frame, if attached. + /// 0 means no inheritance, 1 means inheritance, any other value means reversed inheritance (i.e. if the parent's HFlipped value is true, this Attachable's HFlipped value will be false). + /// + /// Whether or not this Attachable inherits its parent's HFlipped value. + int InheritsHFlipped() const { return m_InheritsHFlipped; } + + /// + /// Sets whether or not this Attachable inherits its parent's HFlipped value, i.e. whether it has its HFlipped value reset to match/reverse its parent's every frame, if attached. + /// 0 means no inheritance, 1 means inheritance, any other value means reversed inheritance (i.e. if the parent's HFlipped value is true, this Attachable's HFlipped value will be false). + /// + /// Whether or not to inherit its parent's HFlipped value. + void SetInheritsHFlipped(int inheritsHFlipped) { m_InheritsHFlipped = inheritsHFlipped; } + /// /// Gets whether or not this Attachable inherits its RotAngle from its parent, i.e. whether it has its RotAngle reset to match its parent every frame, if attached. /// - /// Whether or not this Attachable inherits its RotAngle from its parent. + /// Whether or not this Attachable inherits its parent's RotAngle. bool InheritsRotAngle() const { return m_InheritsRotAngle; } /// @@ -347,7 +349,6 @@ namespace RTE { Vector m_ParentOffset; //!< The offset from the parent's Pos to the joint point this Attachable is attached with. bool m_DrawAfterParent; //!< Whether to draw this Attachable after (in front of) or before (behind) the parent. bool m_DrawnNormallyByParent; //!< Whether this Attachable will be be drawn normally when attached, or will require special handling by some non-MOSR parent type. - bool m_TransfersDamageToParent; //AutoGenerate()/* && m_pAtomGroup->GetAtomCount() == 0*/) m_pAtomGroup->Create(this); else if (m_pAtomGroup) @@ -198,7 +197,6 @@ int MOSRotating::Create(ContentFile spriteFile, const unsigned long lifetime) { MOSprite::Create(spriteFile, frameCount, mass, position, velocity, lifetime); - if (m_DamageMultiplier < 0.0F) { m_DamageMultiplier = 1; } return 0; } @@ -266,6 +264,7 @@ int MOSRotating::Create(const MOSRotating &reference) m_LoudnessOnGib = reference.m_LoudnessOnGib; m_DamageMultiplier = reference.m_DamageMultiplier; + m_DamageMultiplierSetInINI = reference.m_DamageMultiplierSetInINI; /* Allocated in lazy fashion as needed when drawing flipped if (!m_pFlipBitmap && m_aSprite[0]) @@ -338,6 +337,7 @@ int MOSRotating::ReadProperty(std::string propName, Reader &reader) reader >> m_LoudnessOnGib; else if (propName == "DamageMultiplier") { reader >> m_DamageMultiplier; + m_DamageMultiplierSetInINI = true; } else if (propName == "AddCustomValue") { ReadCustomValueProperty(reader); } else @@ -442,14 +442,16 @@ void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int MOSRotating::GetGibWoundLimit(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const { +int MOSRotating::GetGibWoundLimit(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const { int gibWoundLimit = m_GibWoundLimit; - if (includeDamageTransferringAttachables || includeNonDamageTransferringAttachables) { + if (includeAttachablesWithAPositiveDamageMultiplier || includeAttachablesWithANegativeDamageMultiplier || includeAttachablesWithNoDamageMultiplier) { for (const Attachable *attachable : m_Attachables) { - if (includeDamageTransferringAttachables && attachable->GetTransfersDamageToParent()) { - gibWoundLimit += attachable->GetGibWoundLimit(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables); - } else if (includeNonDamageTransferringAttachables && !attachable->GetTransfersDamageToParent()) { - gibWoundLimit += attachable->GetGibWoundLimit(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables); + bool attachableSatisfiesConditions = (includeAttachablesWithAPositiveDamageMultiplier && attachable->GetDamageMultiplier() > 0) || + (includeAttachablesWithANegativeDamageMultiplier && attachable->GetDamageMultiplier() < 0) || + (includeAttachablesWithNoDamageMultiplier && attachable->GetDamageMultiplier() == 0); + + if (attachableSatisfiesConditions) { + gibWoundLimit += attachable->GetGibWoundLimit(includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); } } } @@ -458,14 +460,16 @@ int MOSRotating::GetGibWoundLimit(bool includeDamageTransferringAttachables, boo ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int MOSRotating::GetWoundCount(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const { +int MOSRotating::GetWoundCount(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const { int woundCount = m_Wounds.size(); - if (includeDamageTransferringAttachables || includeNonDamageTransferringAttachables) { + if (includeAttachablesWithAPositiveDamageMultiplier || includeAttachablesWithANegativeDamageMultiplier || includeAttachablesWithNoDamageMultiplier) { for (const Attachable *attachable : m_Attachables) { - if (includeDamageTransferringAttachables && attachable->GetTransfersDamageToParent()) { - woundCount += attachable->GetWoundCount(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables); - } else if (includeNonDamageTransferringAttachables && !attachable->GetTransfersDamageToParent()) { - woundCount += attachable->GetWoundCount(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables); + bool attachableSatisfiesConditions = (includeAttachablesWithAPositiveDamageMultiplier && attachable->GetDamageMultiplier() > 0) || + (includeAttachablesWithANegativeDamageMultiplier && attachable->GetDamageMultiplier() < 0) || + (includeAttachablesWithNoDamageMultiplier && attachable->GetDamageMultiplier() == 0); + + if (attachableSatisfiesConditions) { + woundCount += attachable->GetWoundCount(includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); } } } @@ -474,16 +478,21 @@ int MOSRotating::GetWoundCount(bool includeDamageTransferringAttachables, bool i ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) { +float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) { float damage = 0; - int woundCount = GetWoundCount(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables); + int woundCount = GetWoundCount(includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); std::vector> woundedParts; if (woundCount > 0) { woundedParts.push_back({this, woundCount}); } + for (Attachable *attachable : m_Attachables) { - bool attachableSatisfiesWoundRemovalCriteria = (includeDamageTransferringAttachables && attachable->GetTransfersDamageToParent()) || (includeNonDamageTransferringAttachables && !attachable->GetTransfersDamageToParent()); - if (attachableSatisfiesWoundRemovalCriteria && attachable->GetWoundCount(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables) > 0) { - woundedParts.push_back({attachable, attachable->GetWoundCount(includeDamageTransferringAttachables, includeNonDamageTransferringAttachables)}); + bool attachableSatisfiesConditions = (includeAttachablesWithAPositiveDamageMultiplier && attachable->GetDamageMultiplier() > 0) || + (includeAttachablesWithANegativeDamageMultiplier && attachable->GetDamageMultiplier() < 0) || + (includeAttachablesWithNoDamageMultiplier && attachable->GetDamageMultiplier() == 0); + int attachableWoundCount = attachable->GetWoundCount(includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); + + if (attachableSatisfiesConditions && attachableWoundCount > 0) { + woundedParts.push_back({attachable, attachableWoundCount}); } } @@ -513,10 +522,7 @@ float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeDamageTr if (woundedPart == this) { damage += removeFirstWoundEmitter() * GetDamageMultiplier(); } else { - Attachable *woundedPartAsAttachable = dynamic_cast(woundedPart); - if (woundedPartAsAttachable) { - damage += woundedPartAsAttachable->RemoveWounds(1, includeDamageTransferringAttachables, includeNonDamageTransferringAttachables) * (woundedPartAsAttachable->GetTransfersDamageToParent() ? woundedPartAsAttachable->GetDamageMultiplier() : 0); - } + damage += woundedPart->RemoveWounds(1, includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier) * woundedPart->GetDamageMultiplier(); } if (woundedParts[woundedPartIndex].second-- <= 0) { woundedParts.erase(woundedParts.begin() + woundedPartIndex); diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 5be3b18dc..0c53e1533 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -553,19 +553,20 @@ ClassInfoGetters /// /// Gets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. - /// Includes Attachables that transfer damage to this MOSRotating. + /// Includes any Attachables (and their Attachables, etc.) that have a positive damage multiplier. /// /// - int GetGibWoundLimit() const { return GetGibWoundLimit(true, false); } + int GetGibWoundLimit() const { return GetGibWoundLimit(true, false, false); } /// /// Gets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. - /// Optionally recursively adds the gib wound limits of damaging and/or non-damaging Attachables and any of their such Attachables. + /// Optionally adds the gib wound limits of Attachables (and their Attachables, etc.) that match the conditions set by the provided parameters. /// - /// Whether to add wound limits of Attachables that transfer damage to their parent (this MOSRotating). - /// Whether to add wound limits of Attachables that do not transfer damage to their parent (this MOSRotating). + /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. /// The wound limit of this MOSRotating and, optionally, its Attachables. - int GetGibWoundLimit(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const; + int GetGibWoundLimit(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const; /// /// Sets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. @@ -575,42 +576,48 @@ ClassInfoGetters void SetGibWoundLimit(int newGibWoundLimit) { m_GibWoundLimit = newGibWoundLimit; } /// - /// Gets the number of wounds directly attached to this MOSRotating. + /// Gets the number of wounds attached to this MOSRotating. + /// Includes any Attachables (and their Attachables, etc.) that have a positive damage multiplier. /// The number of wounds on this MOSRotating. /// - int GetWoundCount() const { return GetWoundCount(true, false); } + int GetWoundCount() const { return GetWoundCount(true, false, false); } /// - /// Gets the number of wounds attached to this MOSRotating, optionally recursively including wounds on damaging and/or non-damaging Attachables and any of their such Attachables, and so on. - /// Whether to count wounds from Attachables that transfer damage to their parent (this MOSRotating). - /// Whether to count wounds from Attachables that do not transfer damage to their parent (this MOSRotating). + /// Gets the number of wounds attached to this MOSRotating. + /// Optionally adds the wound counts of Attachables (and their Attachables, etc.) that match the conditions set by the provided parameters. + /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. /// The number of wounds on this MOSRotating and, optionally, its Attachables. /// - int GetWoundCount(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const; + int GetWoundCount(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const; /// /// Attaches the passed in wound AEmitter and adds it to the list of wounds, changing its parent offset to the passed in Vector. /// - /// The wound AEmitter to add - /// The vector to set as the wound AEmitter's parent offset + /// The wound AEmitter to add. + /// The vector to set as the wound AEmitter's parent offset<./param> + /// Whether to gib this MOSRotating if adding this wound raises its wound count past its gib wound limit. void AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit = true); /// - /// Removes a specified number of wounds and returns damage caused by these wounds. Head multiplier is not used. + /// Removes a specified number of wounds, including and returns damage caused by these wounds. + /// Includes any Attachables (and their Attachables, etc.) that have a positive damage multiplier. /// /// The number of wounds that should be removed. - /// The amount of damage caused by these wounds. - float RemoveWounds(int numberOfWoundsToRemove) { return RemoveWounds(numberOfWoundsToRemove, true, false); } + /// The amount of damage caused by these wounds, taking damage multipliers into account. + float RemoveWounds(int numberOfWoundsToRemove) { return RemoveWounds(numberOfWoundsToRemove, true, false, false); } /// /// Removes a specified number of wounds and returns damage caused by these wounds. Head multiplier is not used. - /// Optionally only removes wounds that affect health directly. + /// Optionally adds removes wounds from Attachables (and their Attachables, etc.) that match the conditions set by the provided parameters. /// /// The number of wounds that should be removed. - /// Whether to remove wounds from Attachables that transfer damage to their parent (this MOSRotating). - /// Whether to remove wounds from Attachables that do not transfer damage to their parent (this MOSRotating). - /// The amount of damage caused by the removed wounds. - float RemoveWounds(int numberOfWoundsToRemove, bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables); + /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. + /// The amount of damage caused by these wounds, taking damage multipliers into account. + float RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier); ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetStringValue @@ -738,6 +745,12 @@ ClassInfoGetters float GetDamageMultiplier() const { return m_DamageMultiplier; } + /// + /// Gets whether the damage multiplier was set in this MOSRotating's INI definition. Used to determine whether to set the damage multiplier for hardcoded Attachables when reading them in from INI. + /// + /// Whether the damage multiplier was set in this MOSRotating's INI definition. + bool GetDamageMultiplierSetInINI() const { return m_DamageMultiplierSetInINI; } + ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetTravelImpulse @@ -861,6 +874,7 @@ ClassInfoGetters // Damage multiplier for this attachable float m_DamageMultiplier; + bool m_DamageMultiplierSetInINI; //!< Whether or not the damage multiplier was set in INI for this MOSRotating. // Intermediary drawing bitmap used to flip rotating bitmaps. Owned! BITMAP *m_pFlipBitmap; From 583b4aa78a5a131ce1444fb75f7949511ca22dcc Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 11 Sep 2020 02:16:54 -0300 Subject: [PATCH 039/144] Cleaned up ACrab and AHuman damage handling and Attachable updating so they only do stuff specific to the special Attachable types Made it so Actor collects damage from all attachables and applies it to health. Also fixed Attachable::CollectDamage a bit Made Arm automatically not inherit rot angle, just like Leg --- Entities/ACrab.cpp | 136 ++++++---------------- Entities/AHuman.cpp | 247 +++++++++++++++------------------------- Entities/Actor.cpp | 11 +- Entities/Arm.cpp | 15 ++- Entities/Arm.h | 6 + Entities/Attachable.cpp | 5 +- 6 files changed, 149 insertions(+), 271 deletions(-) diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 11f70d514..6bc0bf8a5 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -226,15 +226,13 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) delete m_pTurret; m_pTurret = new Turret; reader >> m_pTurret; - m_pTurret->SetTransfersDamageToParent(true); - if (m_pTurret->GetDamageMultiplier() < 0.0F) { - m_pTurret->SetDamageMultiplier(5); - } + if (!m_pTurret->GetDamageMultiplierSetInINI()) { m_pTurret->SetDamageMultiplier(5.0F); } } else if (propName == "Jetpack") { delete m_pJetpack; m_pJetpack = new AEmitter; reader >> m_pJetpack; - m_pJetpack->SetTransfersDamageToParent(true); + if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } + m_pJetpack->SetOnlyLinearForces(true); } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; m_JetTimeTotal *= 1000; @@ -242,22 +240,24 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) delete m_pLFGLeg; m_pLFGLeg = new Leg; reader >> m_pLFGLeg; - m_pLFGLeg->SetTransfersDamageToParent(true); + if (!m_pLFGLeg->GetDamageMultiplierSetInINI()) { m_pLFGLeg->SetDamageMultiplier(1.0F); } + m_pLFGLeg->SetInheritsHFlipped(2); } else if (propName == "LBGLeg") { delete m_pLBGLeg; m_pLBGLeg = new Leg; reader >> m_pLBGLeg; - m_pLBGLeg->SetTransfersDamageToParent(true); + if (!m_pLBGLeg->GetDamageMultiplierSetInINI()) { m_pLBGLeg->SetDamageMultiplier(1.0F); } + m_pLBGLeg->SetInheritsHFlipped(2); } else if (propName == "RFGLeg") { delete m_pRFGLeg; m_pRFGLeg = new Leg; reader >> m_pRFGLeg; - m_pRFGLeg->SetTransfersDamageToParent(true); + if (!m_pRFGLeg->GetDamageMultiplierSetInINI()) { m_pRFGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "RBGLeg") { delete m_pRBGLeg; m_pRBGLeg = new Leg; reader >> m_pRBGLeg; - m_pRBGLeg->SetTransfersDamageToParent(true); + if (!m_pRBGLeg->GetDamageMultiplierSetInINI()) { m_pRBGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "LFootGroup") { delete m_pLFGFootGroup; delete m_pLBGFootGroup; @@ -2646,13 +2646,36 @@ void ACrab::Update() } } + if (m_pTurret && m_pTurret->IsAttached()) { + m_pTurret->SetMountedDeviceRotOffset((m_AimAngle * static_cast(GetFlipFactor())) - m_Rotation.GetRadAngle()); + } + + if (m_pLFGLeg && m_pLFGLeg->IsAttached()) { + m_pLFGLeg->EnableIdle(m_Status != UNSTABLE); + m_pLFGLeg->SetTargetPosition(m_pLFGFootGroup->GetLimbPos(m_HFlipped)); + } + + if (m_pLBGLeg && m_pLBGLeg->IsAttached()) { + m_pLBGLeg->EnableIdle(m_Status != UNSTABLE); + m_pLBGLeg->SetTargetPosition(m_pLBGFootGroup->GetLimbPos(m_HFlipped)); + } + + if (m_pRFGLeg && m_pRFGLeg->IsAttached()) { + m_pRFGLeg->EnableIdle(m_Status != UNSTABLE); + m_pRFGLeg->SetTargetPosition(m_pRFGFootGroup->GetLimbPos(m_HFlipped)); + } + + if (m_pRBGLeg && m_pRBGLeg->IsAttached()) { + m_pRBGLeg->EnableIdle(m_Status != UNSTABLE); + m_pRBGLeg->SetTargetPosition(m_pRBGFootGroup->GetLimbPos(m_HFlipped)); + } + + ///////////////////////////////////////////////// // Update MovableObject, adds on the forces etc // NOTE: this also updates the controller, so any setstates of it will be wiped! - Actor::Update(); - //////////////////////////////////// // Update viewpoint @@ -2700,97 +2723,6 @@ void ACrab::Update() if (m_Vel.GetMagnitude() > 10.0) m_ViewPoint += m_Vel * 6; - - ///////////////////////////////// - // Update Attachable:s - - if (m_pTurret && m_pTurret->IsAttached()) - { - m_pTurret->SetHFlipped(m_HFlipped); - m_pTurret->SetJointPos(m_Pos + m_pTurret->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - m_pTurret->SetRotAngle(m_Rotation.GetRadAngle()); - m_pTurret->SetMountedDeviceRotOffset((m_HFlipped ? -m_AimAngle : m_AimAngle) - m_Rotation.GetRadAngle()); - m_pTurret->Update(); - // Update the Atoms' offsets in the parent group -// Matrix atomRot(FacingAngle(m_pTurret->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); -// m_pAtomGroup->UpdateSubAtoms(m_pTurret->GetAtomSubgroupID(), m_pTurret->GetParentOffset() - (m_pTurret->GetJointOffset() * atomRot), atomRot); - - m_Health -= m_pTurret->CollectDamage();// * 5; - } - - if (m_pJetpack && m_pJetpack->IsAttached()) - { - m_pJetpack->SetHFlipped(m_HFlipped); - m_pJetpack->SetJointPos(m_Pos + m_pJetpack->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - m_pJetpack->SetRotAngle(m_Rotation.GetRadAngle()); - m_pJetpack->SetOnlyLinearForces(true); - m_pJetpack->Update(); -// m_Health -= m_pJetpack->CollectDamage() * 10; - } - - if (m_pLFGLeg && m_pLFGLeg->IsAttached()) - { - // Left legs always flipped the other way - m_pLFGLeg->SetHFlipped(!m_HFlipped); - // Don't flip the parent offset though, that's probably done in the ini - m_pLFGLeg->SetJointPos(m_Pos + m_pLFGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise - m_pLFGLeg->EnableIdle(m_Status != UNSTABLE); - m_pLFGLeg->SetTargetPosition(m_pLFGFootGroup->GetLimbPos(m_HFlipped)); - m_pLFGLeg->Update(); - m_Health -= m_pLFGLeg->CollectDamage(); - } - - if (m_pLBGLeg && m_pLBGLeg->IsAttached()) - { - // Left legs always flipped the other way - m_pLBGLeg->SetHFlipped(!m_HFlipped); - // Don't flip the parent offset though, that's probably done in the ini - m_pLBGLeg->SetJointPos(m_Pos + m_pLBGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise - m_pLBGLeg->EnableIdle(m_Status != UNSTABLE); - m_pLBGLeg->SetTargetPosition(m_pLBGFootGroup->GetLimbPos(m_HFlipped)); - m_pLBGLeg->Update(); - m_Health -= m_pLBGLeg->CollectDamage(); - } - - if (m_pRFGLeg && m_pRFGLeg->IsAttached()) - { - m_pRFGLeg->SetHFlipped(m_HFlipped); - m_pRFGLeg->SetJointPos(m_Pos + m_pRFGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise - m_pRFGLeg->EnableIdle(m_Status != UNSTABLE); - m_pRFGLeg->SetTargetPosition(m_pRFGFootGroup->GetLimbPos(m_HFlipped)); - m_pRFGLeg->Update(); - m_Health -= m_pRFGLeg->CollectDamage(); - } - - if (m_pRBGLeg && m_pRBGLeg->IsAttached()) - { - m_pRBGLeg->SetHFlipped(m_HFlipped); - m_pRBGLeg->SetJointPos(m_Pos + m_pRBGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise - m_pRBGLeg->EnableIdle(m_Status != UNSTABLE); - m_pRBGLeg->SetTargetPosition(m_pRBGFootGroup->GetLimbPos(m_HFlipped)); - m_pRBGLeg->Update(); - m_Health -= m_pRBGLeg->CollectDamage(); - } - - ///////////////////////////// - // Apply forces transferred from the attachables and - // add detachment wounds to this if applicable - - if (!ApplyAttachableForces(m_pTurret)) - m_pTurret = 0; - if (!ApplyAttachableForces(m_pJetpack)) - m_pJetpack = 0; - if (!ApplyAttachableForces(m_pLFGLeg)) - m_pLFGLeg = 0; - if (!ApplyAttachableForces(m_pLBGLeg)) - m_pLBGLeg = 0; - if (!ApplyAttachableForces(m_pRFGLeg)) - m_pRFGLeg = 0; - if (!ApplyAttachableForces(m_pRBGLeg)) - m_pRBGLeg = 0; /* Done by pie menu now, see HandlePieCommand() //////////////////////////////////////// // AI mode setting diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 2496ae74e..a33911d42 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -202,14 +202,14 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { delete m_pHead; m_pHead = new Attachable; reader >> m_pHead; - if (m_pHead->GetDamageMultiplier() >= 0.0F) { - m_pHead->SetDamageMultiplier(5); - } - m_pHead->SetTransfersDamageToParent(true); + if (!m_pHead->GetDamageMultiplierSetInINI()) { m_pHead->SetDamageMultiplier(5.0F); } + m_pHead->SetInheritsRotAngle(false); } else if (propName == "Jetpack") { delete m_pJetpack; m_pJetpack = new AEmitter; reader >> m_pJetpack; + if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } + m_pJetpack->SetOnlyLinearForces(true); } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; // Convert to ms @@ -218,24 +218,24 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { delete m_pFGArm; m_pFGArm = new Arm; reader >> m_pFGArm; - m_pFGArm->SetTransfersDamageToParent(true); + if (!m_pFGArm->GetDamageMultiplierSetInINI()) { m_pFGArm->SetDamageMultiplier(1.0F); } m_pFGArm->SetDrawnAfterParent(true); } else if (propName == "BGArm") { delete m_pBGArm; m_pBGArm = new Arm; reader >> m_pBGArm; - m_pBGArm->SetTransfersDamageToParent(true); + if (!m_pBGArm->GetDamageMultiplierSetInINI()) { m_pBGArm->SetDamageMultiplier(1.0F); } m_pBGArm->SetDrawnAfterParent(false); } else if (propName == "FGLeg") { delete m_pFGLeg; m_pFGLeg = new Leg; reader >> m_pFGLeg; - m_pFGLeg->SetTransfersDamageToParent(true); + if (!m_pFGLeg->GetDamageMultiplierSetInINI()) { m_pFGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "BGLeg") { delete m_pBGLeg; m_pBGLeg = new Leg; reader >> m_pBGLeg; - m_pBGLeg->SetTransfersDamageToParent(true); + if (!m_pBGLeg->GetDamageMultiplierSetInINI()) { m_pBGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "HandGroup") { delete m_pFGHandGroup; delete m_pBGHandGroup; @@ -3980,70 +3980,22 @@ void AHuman::Update() } } - ///////////////////////////////////////////////// - // Update MovableObject, adds on the forces etc - // NOTE: this also updates the controller, so any setstates of it will be wiped! - Actor::Update(); - - //////////////////////////////////// - // Update viewpoint - // Set viewpoint based on how we are aiming etc. - Vector aimSight(m_AimDistance, 0); - Matrix aimMatrix(m_HFlipped ? -m_AimAngle : m_AimAngle); - aimMatrix.SetXFlipped(m_HFlipped); - // Reset this each frame - m_SharpAimMaxedOut = false; - if (m_pFGArm && m_pFGArm->IsAttached() && m_pFGArm->HoldsHeldDevice()) - { - float maxLength = m_pFGArm->GetHeldDevice()->GetSharpLength(); - // Use a non-terrain check ray to cap the magnitude, so we can't see into objects etc - if (m_SharpAimProgress > 0) - { - Vector notUsed; - Vector sharpAimVector(maxLength, 0); - sharpAimVector *= aimMatrix; - // See how far along the sharp aim vector there is opaque air -// float result = g_SceneMan.CastNotMaterialRay(m_pFGArm->GetHeldDevice()->GetMuzzlePos(), sharpAimVector, g_MaterialAir, 5); - float result = g_SceneMan.CastObstacleRay(m_pFGArm->GetHeldDevice()->GetMuzzlePos(), sharpAimVector, notUsed, notUsed, GetRootID(), g_MaterialAir, 5); - // If we didn't find anything but air before the sharpdistance, then don't alter the sharp distance - if (result >= 0 && result < (maxLength * m_SharpAimProgress)) - { - m_SharpAimProgress = result / maxLength; - m_SharpAimMaxedOut = true; - } - } - // Indicate maxed outedness if we really are, too - if (m_SharpAimProgress > 0.9) - m_SharpAimMaxedOut = true; -// sharpDistance *= m_Controller.GetAnalogAim().GetMagnitude(); - aimSight.m_X += maxLength * m_SharpAimProgress; - } - // Rotate the aiming spot vector and add it to the view point - aimSight *= aimMatrix; - m_ViewPoint = m_Pos.GetFloored() + aimSight; - // Add velocity also so the viewpoint moves ahead at high speeds - if (m_Vel.GetMagnitude() > 10.0) - m_ViewPoint += m_Vel * 6; ///////////////////////////////// // Update Attachable:s - if (m_pHead && m_pHead->IsAttached()) - { - m_pHead->SetHFlipped(m_HFlipped); - m_pHead->SetJointPos(m_Pos + m_pHead->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); + if (m_pHead && m_pHead->IsAttached()) { float toRotate = 0; // Only rotate the head to match the aim angle if body is stable and upright - if (m_Status == STABLE && fabs(m_Rotation.GetRadAngle()) < (c_HalfPI + c_QuarterPI)) - { + if (m_Status == STABLE && fabs(m_Rotation.GetRadAngle()) < (c_HalfPI + c_QuarterPI)) { toRotate = m_pHead->GetRotMatrix().GetRadAngleTo((m_HFlipped ? -m_AimAngle : m_AimAngle) * 0.7 + m_Rotation.GetRadAngle() * 0.2); toRotate *= 0.15; } @@ -4055,154 +4007,133 @@ void AHuman::Update() // toRotate *= 0.10; // } // Make head just keep rotating loosely with the body if unstable or upside down - else - { + else { toRotate = m_pHead->GetRotMatrix().GetRadAngleTo(m_Rotation.GetRadAngle()); - toRotate *= 0.10; + toRotate *= 0.10F; } // Now actually rotate by the amount calculated above - m_pHead->SetRotAngle(m_pHead->GetRotMatrix().GetRadAngle() + toRotate); + m_pHead->SetRotAngle(m_pHead->GetRotAngle() + toRotate); - m_pHead->Update(); // Update the Atoms' offsets in the parent group Matrix headAtomRot(FacingAngle(m_pHead->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); m_pAtomGroup->UpdateSubAtoms(m_pHead->GetAtomSubgroupID(), m_pHead->GetParentOffset() - (m_pHead->GetJointOffset() * headAtomRot), headAtomRot); - - m_Health -= m_pHead->CollectDamage();// * 5; // This is done in CollectDamage via m_DamageMultiplier now. - } - - if (m_pJetpack && m_pJetpack->IsAttached()) - { - m_pJetpack->SetHFlipped(m_HFlipped); - m_pJetpack->SetJointPos(m_Pos + m_pJetpack->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - m_pJetpack->SetRotAngle(m_Rotation.GetRadAngle()); - m_pJetpack->SetOnlyLinearForces(true); - m_pJetpack->Update(); -// m_Health -= m_pJetpack->CollectDamage() * 10; } - if (m_pFGLeg && m_pFGLeg->IsAttached()) - { - m_pFGLeg->SetHFlipped(m_HFlipped); - m_pFGLeg->SetJointPos(m_Pos + m_pFGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise + if (m_pFGLeg && m_pFGLeg->IsAttached()) { m_pFGLeg->EnableIdle(m_ProneState == NOTPRONE && m_Status != UNSTABLE); -// if (!m_ArmClimbing[FGROUND]) - m_pFGLeg->SetTargetPosition(m_pFGFootGroup->GetLimbPos(m_HFlipped)); - m_pFGLeg->Update(); - m_Health -= m_pFGLeg->CollectDamage(); + m_pFGLeg->SetTargetPosition(m_pFGFootGroup->GetLimbPos(m_HFlipped)); } - if (m_pBGLeg && m_pBGLeg->IsAttached()) - { - m_pBGLeg->SetHFlipped(m_HFlipped); - m_pBGLeg->SetJointPos(m_Pos + m_pBGLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - // Only have the leg go to idle position if the limb target is over the joint and if we're firing the jetpack... looks retarded otherwise + if (m_pBGLeg && m_pBGLeg->IsAttached()) { m_pBGLeg->EnableIdle(m_ProneState == NOTPRONE && m_Status != UNSTABLE); -// if (!m_ArmClimbing[BGROUND]) - m_pBGLeg->SetTargetPosition(m_pBGFootGroup->GetLimbPos(m_HFlipped)); - m_pBGLeg->Update(); - m_Health -= m_pBGLeg->CollectDamage(); + m_pBGLeg->SetTargetPosition(m_pBGFootGroup->GetLimbPos(m_HFlipped)); } - if (m_pFGArm && m_pFGArm->IsAttached()) - { - m_pFGArm->SetHFlipped(m_HFlipped); - m_pFGArm->SetJointPos(m_Pos + m_pFGArm->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); + if (m_pFGArm && m_pFGArm->IsAttached()) { + m_pFGArm->SetRotAngle(m_AimAngle * static_cast(GetFlipFactor())); m_pFGArm->SetRotAngle(m_HFlipped ? (-m_AimAngle/* + -m_Rotation*/) : (m_AimAngle/* + m_Rotation*/)); -// m_pFGArm->SetRotTarget(m_HFlipped ? (-m_AimAngle/* + -m_Rotation*/) : (m_AimAngle/* + m_Rotation*/)); - if (m_Status == STABLE) - { - if (m_ArmClimbing[FGROUND]) - { + if (m_Status == STABLE) { + if (m_ArmClimbing[FGROUND]) { // Can't climb with anything in the arm? - // UnequipBGArm(); + //UnequipBGArm(); m_pFGArm->ReachToward(m_pFGHandGroup->GetLimbPos(m_HFlipped)); - } - // This will likely make the arm idle since the target will be out of range - else if (!m_pFGArm->IsReaching()) + } else if (!m_pFGArm->IsReaching()) { + // This will likely make the arm idle since the target will be out of range m_pFGArm->Reach(m_pFGHandGroup->GetLimbPos(m_HFlipped)); - } - // Unstable, so just drop the arm limply - else + } + } else { + // Unstable, so just drop the arm limply m_pFGArm->ReachToward(m_pFGHandGroup->GetLimbPos(m_HFlipped)); - - m_pFGArm->Update(); - m_Health -= m_pFGArm->CollectDamage(); + } } - if (m_pBGArm && m_pBGArm->IsAttached()) - { - m_pBGArm->SetHFlipped(m_HFlipped); - m_pBGArm->SetJointPos(m_Pos + m_pBGArm->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - if (m_Status == STABLE) - { - if (m_ArmClimbing[BGROUND]) - { + if (m_pBGArm && m_pBGArm->IsAttached()) { + if (m_Status == STABLE) { + if (m_ArmClimbing[BGROUND]) { // Can't climb with the shield UnequipBGArm(); m_pBGArm->ReachToward(m_pBGHandGroup->GetLimbPos(m_HFlipped)); - m_pBGArm->Update(); - } - else if (m_pFGArm && m_pFGArm->IsAttached() && m_pFGArm->HoldsHeldDevice() && !m_pBGArm->HoldsHeldDevice()) - { + } else if (m_pFGArm && m_pFGArm->IsAttached() && m_pFGArm->HoldsHeldDevice() && !m_pBGArm->HoldsHeldDevice()) { // Re-equip shield in BG arm after climbing EquipShieldInBGArm(); m_pBGArm->Reach(m_pFGArm->GetHeldDevice()->GetSupportPos()); - // m_pBGArm->ReachToward(m_Pos + m_WalkPaths.front()->GetCurrentPos()); - m_pBGArm->Update(); + // m_pBGArm->ReachToward(m_Pos + m_WalkPaths.front()->GetCurrentPos()); // BGArm does reach to support the device held by FGArm. - if (m_pBGArm->DidReach()) - { + if (m_pBGArm->DidReach()) { m_pFGArm->GetHeldDevice()->SetSupported(true); - m_pBGArm->SetRecoil(m_pFGArm->GetHeldDevice()->GetRecoilForce(), - m_pFGArm->GetHeldDevice()->GetRecoilOffset(), - m_pFGArm->GetHeldDevice()->IsRecoiled()); - } - // BGArm did not reach to support the device. - else - { + m_pBGArm->SetRecoil(m_pFGArm->GetHeldDevice()->GetRecoilForce(), m_pFGArm->GetHeldDevice()->GetRecoilOffset(), m_pFGArm->GetHeldDevice()->IsRecoiled()); + } else { + // BGArm did not reach to support the device. m_pFGArm->GetHeldDevice()->SetSupported(false); m_pBGArm->SetRecoil(Vector(), Vector(), false); } - } - else - { + } else { // Re-equip shield in BG arm after climbing EquipShieldInBGArm(); // This will likely make the arm idle since the target will be out of range m_pBGArm->Reach(m_pFGHandGroup->GetLimbPos(m_HFlipped)); m_pBGArm->SetRotAngle(m_HFlipped ? (-m_AimAngle + -m_Rotation.GetRadAngle()) : (m_AimAngle + m_Rotation.GetRadAngle())); - m_pBGArm->Update(); } + } else { + // Unstable, so just drop the arm limply + m_pBGArm->ReachToward(m_pBGHandGroup->GetLimbPos(m_HFlipped)); } - // Unstable, so just drop the arm limply - else + } + + ///////////////////////////////////////////////// + // Update MovableObject, adds on the forces etc + // NOTE: this also updates the controller, so any setstates of it will be wiped! + Actor::Update(); + + //////////////////////////////////// + // Update viewpoint + + // Set viewpoint based on how we are aiming etc. + Vector aimSight(m_AimDistance, 0); + Matrix aimMatrix(m_HFlipped ? -m_AimAngle : m_AimAngle); + aimMatrix.SetXFlipped(m_HFlipped); + // Reset this each frame + m_SharpAimMaxedOut = false; + + if (m_pFGArm && m_pFGArm->IsAttached() && m_pFGArm->HoldsHeldDevice()) + { + float maxLength = m_pFGArm->GetHeldDevice()->GetSharpLength(); + + // Use a non-terrain check ray to cap the magnitude, so we can't see into objects etc + if (m_SharpAimProgress > 0) { - m_pBGArm->ReachToward(m_pBGHandGroup->GetLimbPos(m_HFlipped)); - m_pBGArm->Update(); + Vector notUsed; + Vector sharpAimVector(maxLength, 0); + sharpAimVector *= aimMatrix; + + // See how far along the sharp aim vector there is opaque air +// float result = g_SceneMan.CastNotMaterialRay(m_pFGArm->GetHeldDevice()->GetMuzzlePos(), sharpAimVector, g_MaterialAir, 5); + float result = g_SceneMan.CastObstacleRay(m_pFGArm->GetHeldDevice()->GetMuzzlePos(), sharpAimVector, notUsed, notUsed, GetRootID(), g_MaterialAir, 5); + // If we didn't find anything but air before the sharpdistance, then don't alter the sharp distance + if (result >= 0 && result < (maxLength * m_SharpAimProgress)) + { + m_SharpAimProgress = result / maxLength; + m_SharpAimMaxedOut = true; + } } + // Indicate maxed outedness if we really are, too + if (m_SharpAimProgress > 0.9) + m_SharpAimMaxedOut = true; - m_Health -= m_pBGArm->CollectDamage(); +// sharpDistance *= m_Controller.GetAnalogAim().GetMagnitude(); + aimSight.m_X += maxLength * m_SharpAimProgress; } - ///////////////////////////// - // Apply forces transferred from the attachables and - // add detachment wounds to this if applicable + // Rotate the aiming spot vector and add it to the view point + aimSight *= aimMatrix; + m_ViewPoint = m_Pos.GetFloored() + aimSight; + + // Add velocity also so the viewpoint moves ahead at high speeds + if (m_Vel.GetMagnitude() > 10.0) + m_ViewPoint += m_Vel * 6; - if (!ApplyAttachableForces(m_pHead)) - m_pHead = 0; - if (!ApplyAttachableForces(m_pJetpack)) - m_pJetpack = 0; - if (!ApplyAttachableForces(m_pFGArm, true)) - m_pFGArm = 0; - if (!ApplyAttachableForces(m_pBGArm, true)) - m_pBGArm = 0; - if (!ApplyAttachableForces(m_pFGLeg, true)) - m_pFGLeg = 0; - if (!ApplyAttachableForces(m_pBGLeg, true)) - m_pBGLeg = 0; /* Done by pie menu now, see HandlePieCommand() //////////////////////////////////////// // AI mode setting diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index 574259257..7a610d6fb 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -1464,10 +1464,13 @@ void Actor::Update() } ///////////////////////////////////// - // Detract damage caused by wounds from health - - for (list::iterator itr = m_Wounds.begin(); itr != m_Wounds.end(); ++itr) - m_Health -= (*itr)->CollectDamage() * m_DamageMultiplier; //Actors must apply DamageMultiplier effects to their main MO by themselves + // Take damage from wounds and wounds on Attachables + for (AEmitter *wound : m_Wounds) { + m_Health -= wound->CollectDamage() * m_DamageMultiplier; + } + for (Attachable *attachable : m_Attachables) { + m_Health -= attachable->CollectDamage(); + } ///////////////////////////////////////////// // Take damage from large hits during travel diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 456a5eb04..2daf4e504 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -42,20 +42,23 @@ void Arm::Clear() m_DidReach = false; } -/* + ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Create ////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes the Round object ready for use. +// Description: Makes the Arm object ready for use. -int Arm::Create() -{ - if (Attachable::Create() < 0) +int Arm::Create() { + if (MOSRotating::Create() < 0) { return -1; + } + + // Ensure Arms don't get flagged as inheriting RotAngle, since they never do and always set their RotAngle for themselves. + m_InheritsRotAngle = false; return 0; } -*/ + ////////////////////////////////////////////////////////////////////////////////////////// // Method: Create diff --git a/Entities/Arm.h b/Entities/Arm.h index 61cc8e082..083222f28 100644 --- a/Entities/Arm.h +++ b/Entities/Arm.h @@ -65,6 +65,12 @@ ClassInfoGetters ~Arm() override { Destroy(true); } + /// + /// Makes the Arm object ready for use. + /// + /// An error return value signaling sucess or any particular failure. Anything below 0 is an error signal. + int Create() override; + ////////////////////////////////////////////////////////////////////////////////////////// // Method: Create ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index c3dd87aaa..72b5aaa43 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -200,13 +200,16 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float Attachable::CollectDamage() { - if (m_DamageMultiplier > 0) { + if (m_DamageMultiplier != 0) { float totalDamage = m_DamageCount; m_DamageCount = 0; for (AEmitter *wound : m_Wounds) { totalDamage += wound->CollectDamage(); } + for (Attachable *attachable : m_Attachables) { + totalDamage += attachable->CollectDamage(); + } return totalDamage * m_DamageMultiplier; } return 0; From 4f44c8bf605a7ee45a2ea7f463c469362af4d762 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 11 Sep 2020 03:02:48 -0300 Subject: [PATCH 040/144] Cleaned up ACRocket and ACDropship attachable updating, damage transferring and force application so it's now done through MOSR Cleaned up some crud in ACrab and AHuman cpp --- Entities/ACDropShip.cpp | 148 +++++++++++++--------------------------- Entities/ACRocket.cpp | 95 ++++++-------------------- Entities/ACrab.cpp | 2 + Entities/AHuman.cpp | 12 +--- 4 files changed, 69 insertions(+), 188 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 7fb3a8a4b..3e094d3df 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -37,7 +37,6 @@ void ACDropShip::Clear() m_pULThruster = 0; m_pRHatch = 0; m_pLHatch = 0; -// TODO: don't hardcode m_HatchSwingRange.SetDegAngle(90); m_HatchOpeness = 0; m_LateralControl = 0; @@ -109,33 +108,37 @@ int ACDropShip::ReadProperty(std::string propName, Reader &reader) { if (propName == "RThruster") { delete m_pRThruster; m_pRThruster = new AEmitter; - m_pRThruster->SetTransfersDamageToParent(true); reader >> m_pRThruster; + if (!m_pRThruster->GetDamageMultiplierSetInINI()) { m_pRThruster->SetDamageMultiplier(1.0F); } + m_pRThruster->SetInheritsRotAngle(false); } else if (propName == "LThruster") { delete m_pLThruster; m_pLThruster = new AEmitter; reader >> m_pLThruster; - m_pLThruster->SetTransfersDamageToParent(true); + if (!m_pLThruster->GetDamageMultiplierSetInINI()) { m_pLThruster->SetDamageMultiplier(1.0F); } + m_pLThruster->SetInheritsRotAngle(false); } else if (propName == "URThruster") { delete m_pURThruster; m_pURThruster = new AEmitter; reader >> m_pURThruster; - m_pURThruster->SetTransfersDamageToParent(true); + if (!m_pURThruster->GetDamageMultiplierSetInINI()) { m_pURThruster->SetDamageMultiplier(1.0F); } } else if (propName == "ULThruster") { delete m_pULThruster; m_pULThruster = new AEmitter; reader >> m_pULThruster; - m_pULThruster->SetTransfersDamageToParent(true); + if (!m_pULThruster->GetDamageMultiplierSetInINI()) { m_pULThruster->SetDamageMultiplier(1.0F); } } else if (propName == "RHatchDoor") { delete m_pRHatch; m_pRHatch = new Attachable; reader >> m_pRHatch; - m_pRHatch->SetTransfersDamageToParent(true); + if (!m_pRHatch->GetDamageMultiplierSetInINI()) { m_pRHatch->SetDamageMultiplier(1.0F); } + m_pRHatch->SetInheritsRotAngle(false); } else if (propName == "LHatchDoor") { delete m_pLHatch; m_pLHatch = new Attachable; reader >> m_pLHatch; - m_pLHatch->SetTransfersDamageToParent(true); + if (!m_pLHatch->GetDamageMultiplierSetInINI()) { m_pLHatch->SetDamageMultiplier(1.0F); } + m_pLHatch->SetInheritsRotAngle(false); } else if (propName == "HatchDoorSwingRange") { reader >> m_HatchSwingRange; } else if (propName == "AutoStabilize") { @@ -530,8 +533,6 @@ void ACDropShip::UpdateAI() void ACDropShip::Update() { - float mass = GetMass(); - ///////////////////////////////// // Controller update and handling @@ -687,134 +688,79 @@ void ACDropShip::Update() } } - ///////////////////////////////////////////////// - // Update MovableObject, adds on the forces etc, updated viewpoint - - ACraft::Update(); - - - ///////////////////////////////// - // Update Attachable:s - -// TODO: don't hardcode the 20 deg tilt range! - Matrix engineRot = 0; - // Clamp engine rotation to within +-20 of body rotation - if (m_Rotation.GetDegAngle() > m_MaxEngineAngle) - engineRot.SetDegAngle(m_Rotation.GetDegAngle() - m_MaxEngineAngle); - else if (m_Rotation.GetDegAngle() < -m_MaxEngineAngle) - engineRot.SetDegAngle(m_Rotation.GetDegAngle() + m_MaxEngineAngle); - // Lateral control application - else - engineRot.SetDegAngle(m_MaxEngineAngle * m_LateralControl); + ///////////////////////////////// + // Manage Attachable:s + Matrix engineRot = 0; + if (m_Rotation.GetDegAngle() > m_MaxEngineAngle) { + engineRot.SetDegAngle(m_Rotation.GetDegAngle() - m_MaxEngineAngle); + } else if (m_Rotation.GetDegAngle() < -m_MaxEngineAngle) { + engineRot.SetDegAngle(m_Rotation.GetDegAngle() + m_MaxEngineAngle); + } else { + // Lateral control application + engineRot.SetDegAngle(m_MaxEngineAngle * m_LateralControl); + } - if (m_pRThruster && m_pRThruster->IsAttached()) - { + if (m_pRThruster && m_pRThruster->IsAttached()) { m_pRThruster->SetRotAngle(engineRot.GetRadAngle()); - m_pRThruster->SetJointPos(m_Pos + m_pRThruster->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - m_pRThruster->Update(); // Update the Atoms' offsets in the parent group Matrix atomRot(FacingAngle(m_pRThruster->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); m_pAtomGroup->UpdateSubAtoms(m_pRThruster->GetAtomSubgroupID(), m_pRThruster->GetParentOffset() - (m_pRThruster->GetJointOffset() * atomRot), atomRot); - - m_Health -= m_pRThruster->CollectDamage(); } - if (m_pLThruster && m_pLThruster->IsAttached()) - { + if (m_pLThruster && m_pLThruster->IsAttached()) { m_pLThruster->SetRotAngle(engineRot.GetRadAngle()); - m_pLThruster->SetJointPos(m_Pos + m_pLThruster->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - m_pLThruster->Update(); // Update the Atoms' offsets in the parent group Matrix atomRot(FacingAngle(m_pLThruster->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); m_pAtomGroup->UpdateSubAtoms(m_pLThruster->GetAtomSubgroupID(), m_pLThruster->GetParentOffset() - (m_pLThruster->GetJointOffset() * atomRot), atomRot); - - m_Health -= m_pLThruster->CollectDamage(); } // Auto balancing with the up thrusters - - if (m_pURThruster && m_pURThruster->IsAttached() && m_pULThruster && m_pULThruster->IsAttached()) - { - if (m_AutoStabilize) - { + if (m_pURThruster && m_pURThruster->IsAttached() && m_pULThruster && m_pULThruster->IsAttached()) { + if (m_AutoStabilize) { // Use a PD-controller for balance - float change = 0.9 * m_AngularVel + 0.8 * m_Rotation.GetRadAngle(); - if (change > 0.2) - { - if (!m_pURThruster->IsEmitting()) + float change = 0.9F * m_AngularVel + 0.8F * m_Rotation.GetRadAngle(); + if (change > 0.2F) { + if (!m_pURThruster->IsEmitting()) { m_pURThruster->TriggerBurst(); + } m_pURThruster->EnableEmission(true); - } - else + } else { m_pURThruster->EnableEmission(false); + } - if (change < -0.2) - { - if (!m_pULThruster->IsEmitting()) + if (change < -0.2F) { + if (!m_pULThruster->IsEmitting()) { m_pULThruster->TriggerBurst(); + } m_pULThruster->EnableEmission(true); - } - else + } else { m_pULThruster->EnableEmission(false); + } } - - m_pURThruster->SetRotAngle(m_Rotation.GetRadAngle()); - m_pURThruster->SetJointPos(m_Pos + m_pURThruster->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - m_pURThruster->Update(); - - m_pULThruster->SetRotAngle(m_Rotation.GetRadAngle()); - m_pULThruster->SetJointPos(m_Pos + m_pULThruster->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - m_pULThruster->Update(); } // Hatch door pieces - - if (m_pRHatch && m_pRHatch->IsAttached()) - { + if (m_pRHatch && m_pRHatch->IsAttached()) { m_pRHatch->SetRotAngle(m_Rotation.GetRadAngle() + m_HatchSwingRange.GetRadAngle() * m_HatchOpeness); - m_pRHatch->SetJointPos(m_Pos + m_pRHatch->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - m_pRHatch->Update(); - - // Update the Atoms' offsets in the parent group - Matrix atomRot(FacingAngle(m_pRHatch->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); - m_pAtomGroup->UpdateSubAtoms(m_pRHatch->GetAtomSubgroupID(), m_pRHatch->GetParentOffset() - (m_pRHatch->GetJointOffset() * atomRot), atomRot); - m_Health -= m_pRHatch->CollectDamage(); + // Update the Atoms' offsets in the parent group + Matrix atomRot(FacingAngle(m_pRHatch->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); + m_pAtomGroup->UpdateSubAtoms(m_pRHatch->GetAtomSubgroupID(), m_pRHatch->GetParentOffset() - (m_pRHatch->GetJointOffset() * atomRot), atomRot); } - if (m_pLHatch && m_pLHatch->IsAttached()) - { + if (m_pLHatch && m_pLHatch->IsAttached()) { m_pLHatch->SetRotAngle(m_Rotation.GetRadAngle() - m_HatchSwingRange.GetRadAngle() * m_HatchOpeness); - m_pLHatch->SetJointPos(m_Pos + m_pLHatch->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - m_pLHatch->Update(); - - // Update the Atoms' offsets in the parent group - Matrix atomRot(FacingAngle(m_pLHatch->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); - m_pAtomGroup->UpdateSubAtoms(m_pLHatch->GetAtomSubgroupID(), m_pLHatch->GetParentOffset() - (m_pLHatch->GetJointOffset() * atomRot), atomRot); - m_Health -= m_pLHatch->CollectDamage(); + // Update the Atoms' offsets in the parent group + Matrix atomRot(FacingAngle(m_pLHatch->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); + m_pAtomGroup->UpdateSubAtoms(m_pLHatch->GetAtomSubgroupID(), m_pLHatch->GetParentOffset() - (m_pLHatch->GetJointOffset() * atomRot), atomRot); } - /////////////////////////////////////////////////////////// - // Apply forces transferred from the attachables and - // add detachment wounds to this if applicable - - if (!ApplyAttachableForces(m_pRHatch)) - m_pRHatch = 0; - if (!ApplyAttachableForces(m_pLHatch)) - m_pLHatch = 0; - if (!ApplyAttachableForces(m_pRThruster)) - m_pRThruster = 0; - if (!ApplyAttachableForces(m_pLThruster)) - m_pLThruster = 0; - if (!ApplyAttachableForces(m_pURThruster)) - m_pURThruster = 0; - if (!ApplyAttachableForces(m_pULThruster)) - m_pULThruster = 0; - -// TODO: add hatch damage here + ///////////////////////////////////////////////// + // Update MovableObject, adds on the forces etc, updated viewpoint + ACraft::Update(); /////////////////////////////////// // Explosion logic diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 09ad9306a..2ea1ec3ac 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -142,13 +142,13 @@ int ACRocket::ReadProperty(std::string propName, Reader &reader) { delete m_pRLeg; m_pRLeg = new Leg; reader >> m_pRLeg; - m_pRLeg->SetTransfersDamageToParent(true); + if (!m_pRLeg->GetDamageMultiplierSetInINI()) { m_pRLeg->SetDamageMultiplier(1.0F); } } else if (propName == "LLeg") { delete m_pLLeg; m_pLLeg = new Leg; reader >> m_pLLeg; - m_pLLeg->SetHFlipped(true); - m_pLLeg->SetTransfersDamageToParent(true); + m_pLLeg->SetInheritsHFlipped(2); + if (!m_pLLeg->GetDamageMultiplierSetInINI()) { m_pLLeg->SetDamageMultiplier(1.0F); } } else if (propName == "RFootGroup") { delete m_pRFootGroup; m_pRFootGroup = new AtomGroup(); @@ -163,27 +163,31 @@ int ACRocket::ReadProperty(std::string propName, Reader &reader) { delete m_pMThruster; m_pMThruster = new AEmitter; reader >> m_pMThruster; - m_pMThruster->SetTransfersDamageToParent(true); + if (!m_pMThruster->GetDamageMultiplierSetInINI()) { m_pMThruster->SetDamageMultiplier(1.0F); } } else if (propName == "RThruster") { delete m_pRThruster; m_pRThruster = new AEmitter; reader >> m_pRThruster; - m_pRThruster->SetTransfersDamageToParent(true); + if (!m_pRThruster->GetDamageMultiplierSetInINI()) { m_pRThruster->SetDamageMultiplier(1.0F); } + m_pRThruster->SetInheritsRotAngle(false); } else if (propName == "LThruster") { delete m_pLThruster; m_pLThruster = new AEmitter; reader >> m_pLThruster; - m_pLThruster->SetTransfersDamageToParent(true); + if (!m_pLThruster->GetDamageMultiplierSetInINI()) { m_pLThruster->SetDamageMultiplier(1.0F); } + m_pLThruster->SetInheritsRotAngle(false); } else if (propName == "URThruster") { delete m_pURThruster; m_pURThruster = new AEmitter; reader >> m_pURThruster; - m_pURThruster->SetTransfersDamageToParent(true); + if (!m_pURThruster->GetDamageMultiplierSetInINI()) { m_pURThruster->SetDamageMultiplier(1.0F); } + m_pURThruster->SetInheritsRotAngle(false); } else if (propName == "ULThruster") { delete m_pULThruster; m_pULThruster = new AEmitter; reader >> m_pULThruster; - m_pULThruster->SetTransfersDamageToParent(true); + if (!m_pULThruster->GetDamageMultiplierSetInINI()) { m_pULThruster->SetDamageMultiplier(1.0F); } + m_pULThruster->SetInheritsRotAngle(false); } else if (propName == "RaisedGearLimbPath") { reader >> m_Paths[RIGHT][RAISED]; } else if (propName == "LoweredGearLimbPath") { @@ -559,7 +563,6 @@ void ACRocket::UpdateAI() void ACRocket::Update() { - float mass = GetMass(); float deltaTime = g_TimerMan.GetDeltaTimeSecs(); // Look/aim update, make the scanner point aftward if the rocket is falling @@ -772,101 +775,41 @@ void ACRocket::Update() m_GearState = LOWERED; } - ///////////////////////////////////////////////// - // Update MovableObject, adds on the forces etc, updated viewpoint - - ACraft::Update(); - ///////////////////////////////// - // Update Attachable:s -/* - if (m_pCapsule && m_pCapsule->IsAttached()) - { - m_pCapsule->SetJointPos(m_Pos + m_pCapsule->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); - m_pCapsule->SetRotAngle(m_Rotation); - m_pCapsule->Update(); - m_Health -= m_pCapsule->CollectDamage(); - } -*/ - if (m_pRLeg && m_pRLeg->IsAttached()) - { - m_pRLeg->SetJointPos(m_Pos + m_pRLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); -/* Obsolete - if (!m_pMThruster->IsEmitting()) - m_pRLeg->SetTargetPosition(m_Pos + Vector(18, 40) * m_Rotation); - else - m_pRLeg->SetTargetPosition(m_Pos + Vector(13, 40) * m_Rotation); -*/ + // Manage Attachable:s + if (m_pRLeg && m_pRLeg->IsAttached()) { m_pRLeg->SetTargetPosition(m_pRFootGroup->GetLimbPos(m_HFlipped)); - m_pRLeg->Update(); - m_Health -= m_pRLeg->CollectDamage(); } - if (m_pLLeg && m_pLLeg->IsAttached()) - { - m_pLLeg->SetJointPos(m_Pos + m_pLLeg->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); -/* Obsolete - if (!m_pMThruster->IsEmitting()) - m_pLLeg->SetTargetPosition(m_Pos + Vector(-18, 40) * m_Rotation); - else - m_pLLeg->SetTargetPosition(m_Pos + Vector(-13, 40) * m_Rotation); -*/ + if (m_pLLeg && m_pLLeg->IsAttached()) { m_pLLeg->SetTargetPosition(m_pLFootGroup->GetLimbPos(!m_HFlipped)); - m_pLLeg->Update(); - m_Health -= m_pLLeg->CollectDamage(); } - // Apply forces transferred from the attachables and - // add detachment wounds to this if applicable - -// if (!ApplyAttachableForces(m_pCapsule)) -// m_pCapsule = 0; - if (!ApplyAttachableForces(m_pRLeg)) - m_pRLeg = 0; - if (!ApplyAttachableForces(m_pLLeg)) - m_pLLeg = 0; - if (m_pMThruster) { - m_pMThruster->SetJointPos(m_Pos + RotateOffset(m_pMThruster->GetParentOffset())); -// m_pMThruster->SetVel(m_Vel); m_pMThruster->SetRotAngle(m_Rotation.GetRadAngle() - c_HalfPI); -// m_pMThruster->SetEmitAngle(m_Rotation - c_HalfPI); - m_pMThruster->Update(); } if (m_pRThruster) { - m_pRThruster->SetJointPos(m_Pos + RotateOffset(m_pRThruster->GetParentOffset())); - m_pRThruster->SetVel(m_Vel); m_pRThruster->SetRotAngle(m_Rotation.GetRadAngle() + c_EighthPI); -// m_pRThruster->SetEmitAngle(m_Rotation); - m_pRThruster->Update(); } if (m_pLThruster) { - m_pLThruster->SetJointPos(m_Pos + RotateOffset(m_pLThruster->GetParentOffset())); - m_pLThruster->SetVel(m_Vel); m_pLThruster->SetRotAngle(m_Rotation.GetRadAngle() + c_PI - c_EighthPI); -// m_pLThruster->SetEmitAngle(m_Rotation + c_PI); - m_pLThruster->Update(); } if (m_pURThruster) { - m_pURThruster->SetJointPos(m_Pos + RotateOffset(m_pURThruster->GetParentOffset())); - m_pURThruster->SetVel(m_Vel); m_pURThruster->SetRotAngle(m_Rotation.GetRadAngle() + c_HalfPI - c_QuarterPI / 2); -// m_pURThruster->SetEmitAngle(-c_QuarterPI / 2); - m_pURThruster->Update(); } if (m_pULThruster) { - m_pULThruster->SetJointPos(m_Pos + RotateOffset(m_pULThruster->GetParentOffset())); - m_pULThruster->SetVel(m_Vel); m_pULThruster->SetRotAngle(m_Rotation.GetRadAngle() + c_HalfPI + c_QuarterPI / 2); -// m_pULThruster->SetEmitAngle(c_QuarterPI / 2); - m_pULThruster->Update(); } + ///////////////////////////////////////////////// + // Update MovableObject, adds on the forces etc, updated viewpoint + ACraft::Update(); + /////////////////////////////////// // Explosion logic diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 6bc0bf8a5..9148cc379 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -2646,6 +2646,8 @@ void ACrab::Update() } } + ///////////////////////////////// + // Manage Attachable:s if (m_pTurret && m_pTurret->IsAttached()) { m_pTurret->SetMountedDeviceRotOffset((m_AimAngle * static_cast(GetFlipFactor())) - m_Rotation.GetRadAngle()); } diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index a33911d42..57df99512 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -3980,18 +3980,8 @@ void AHuman::Update() } } - - - - - - - - - ///////////////////////////////// - // Update Attachable:s - + // Manage Attachable:s if (m_pHead && m_pHead->IsAttached()) { float toRotate = 0; // Only rotate the head to match the aim angle if body is stable and upright From a31288e0e220d96a7b23c60faf290adc551b4bf1 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 11 Sep 2020 03:33:22 -0300 Subject: [PATCH 041/144] Fixed lua bindings to use appropriate policies for setters and getters as properties, cleaned up Turret MountedDevice lua binding Updated lua bindings for wound management that I'd forgotten to commit before and cleaned up some leftovers and unwanted stuff, and added a binding for InheritsHFlipped Added necessary AHuman methods to support lua bindings for setting feet directly from AHuman and cleaned up some method comments --- Entities/AHuman.h | 24 ++++++++++---- Managers/LuaMan.cpp | 77 ++++++++++++++++++++++----------------------- 2 files changed, 56 insertions(+), 45 deletions(-) diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 6eae5c113..054a1d1d5 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -293,9 +293,9 @@ ClassInfoGetters void SetFGLeg(Attachable *newLeg); /// - /// Gets the background leg of this AHuman. + /// Gets the background Leg of this AHuman. /// - /// A pointer to the background leg of this AHuman. Ownership is NOT transferred. + /// A pointer to the background Leg of this AHuman. Ownership is NOT transferred. Attachable *GetBGLeg() const { return static_cast(m_pBGLeg); } /// @@ -305,17 +305,29 @@ ClassInfoGetters void SetBGLeg(Attachable *newLeg); /// - /// Gets the FG foot attachable of this. + /// Gets the foot Attachable of this AHuman's foreground Leg. /// - /// A pointer to the FG foot attachable of this. Ownership is NOT transferred! + /// A pointer to the foot Attachable of this AHuman's foreground Leg. Ownership is NOT transferred! Attachable *GetFGFoot() const { return m_pFGLeg ? m_pFGLeg->GetFoot() : nullptr; } + /// + /// Sets the foot Attachable of this AHuman's foreground Leg. + /// + /// The new foot for this AHuman's foreground Leg to use. + void SetFGFoot(Attachable *newFoot) { if (m_pFGLeg && m_pFGLeg->IsAttached()) { m_pFGLeg->SetFoot(newFoot); } } + /// - /// Gets the BG foot attachable of this. + /// Gets the foot Attachable of this AHuman's background Leg. /// - /// A pointer to the BG foot attachable of this. Ownership is NOT transferred! + /// A pointer to the foot Attachable of this AHuman's background Leg. Ownership is NOT transferred! Attachable *GetBGFoot() const { return m_pBGLeg ? m_pBGLeg->GetFoot() : nullptr; } + /// + /// Sets the foot Attachable of this AHuman's background Leg. + /// + /// The new foot for this AHuman's background Leg to use. + void SetBGFoot(Attachable *newFoot) { if (m_pBGLeg && m_pBGLeg->IsAttached()) { m_pBGLeg->SetFoot(newFoot); } } + ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetHeadBitmap diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 85a9d0613..a9adc530d 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -52,6 +52,7 @@ // LuaBind #include "luabind/luabind.hpp" #include "luabind/operator.hpp" +#include "luabind/copy_policy.hpp" #include "luabind/adopt_policy.hpp" #include "luabind/out_value_policy.hpp" #include "luabind/iterator_policy.hpp" @@ -776,12 +777,12 @@ int LuaMan::Create() .def("ApplyForces", &MOSRotating::ApplyForces) .def("ApplyImpulses", &MOSRotating::ApplyImpulses) .def("GetGibWoundLimit", (int (MOSRotating:: *)() const) &MOSRotating::GetGibWoundLimit) - .def("GetGibWoundLimit", (int (MOSRotating:: *)(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const) &MOSRotating::GetGibWoundLimit) + .def("GetGibWoundLimit", (int (MOSRotating:: *)(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const) &MOSRotating::GetGibWoundLimit) .def("GetWoundCount", (int (MOSRotating:: *)() const) &MOSRotating::GetWoundCount) - .def("GetWoundCount", (int (MOSRotating:: *)(bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables) const) &MOSRotating::GetWoundCount) + .def("GetWoundCount", (int (MOSRotating:: *)(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const) &MOSRotating::GetWoundCount) .def("AddWound", &MOSRotating::AddWound, adopt(_2)) .def("RemoveWounds", (float (MOSRotating:: *)(int numberOfWoundsToRemove)) &MOSRotating::RemoveWounds) - .def("RemoveWounds", (float (MOSRotating:: *)(int numberOfWoundsToRemove, bool includeDamageTransferringAttachables, bool includeNonDamageTransferringAttachables)) &MOSRotating::RemoveWounds) + .def("RemoveWounds", (float (MOSRotating:: *)(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier)) &MOSRotating::RemoveWounds) .def("IsOnScenePoint", &MOSRotating::IsOnScenePoint) .def("EraseFromTerrain", &MOSRotating::EraseFromTerrain) .def("GetStringValue", &MOSRotating::GetStringValue) @@ -812,18 +813,15 @@ int LuaMan::Create() .def("IsAttachedTo", &Attachable::IsAttachedTo) .property("ParentOffset", &Attachable::GetParentOffset, &Attachable::SetParentOffset) .def("IsDrawnAfterParent", &Attachable::IsDrawnAfterParent) - .property("TransfersDamageToParent", &Attachable::GetTransfersDamageToParent, &Attachable::SetTransfersDamageToParent) .property("JointStrength", &Attachable::GetJointStrength, &Attachable::SetJointStrength) .property("JointStiffness", &Attachable::GetJointStiffness, &Attachable::SetJointStiffness) .property("JointOffset", &Attachable::GetJointOffset, &Attachable::SetJointOffset) .property("OnlyLinearForces", &Attachable::GetOnlyLinearForces, &Attachable::SetOnlyLinearForces) .def("TransferJointForces", &Attachable::TransferJointForces) .def("TransferJointImpulses", &Attachable::TransferJointImpulses) - .def("CollectDamage", &Attachable::CollectDamage) - .def("GetBreakWound", &Attachable::GetBreakWound) - .def("SetBreakWound", &Attachable::SetBreakWound) - .def("GetParentBreakWound", &Attachable::GetParentBreakWound) - .def("SetParentBreakWound", &Attachable::SetParentBreakWound) + .property("BreakWound", &Attachable::GetBreakWound, &Attachable::SetBreakWound, copy(result), adopt(_2)) + .property("ParentBreakWound", &Attachable::GetParentBreakWound, &Attachable::SetParentBreakWound, copy(result), adopt(_2)) + .property("InheritsHFlipped", &Attachable::InheritsHFlipped, &Attachable::SetInheritsHFlipped) .property("InheritsRotAngle", &Attachable::InheritsRotAngle, &Attachable::SetInheritsRotAngle) .property("AtomSubgroupID", &Attachable::GetAtomSubgroupID) .property("CollidesWithTerrainWhileAttached", &Attachable::GetCollidesWithTerrainWhileAttached, &Attachable::SetCollidesWithTerrainWhileAttached), @@ -851,7 +849,7 @@ int LuaMan::Create() .property("EmitterDamageMultiplier", &AEmitter::GetEmitterDamageMultiplier, &AEmitter::SetEmitterDamageMultiplier) .property("EmitCountLimit", &AEmitter::GetEmitCountLimit, &AEmitter::SetEmitCountLimit) .property("EmitDamage", &AEmitter::GetEmitDamage, &AEmitter::SetEmitDamage) - .property("Flash", &AEmitter::GetFlash, &AEmitter::SetFlash) + .property("Flash", &AEmitter::GetFlash, &AEmitter::SetFlash, copy(result), adopt(_2)) .property("FlashScale", &AEmitter::GetFlashScale, &AEmitter::SetFlashScale) .def("GetEmitVector", &AEmitter::GetEmitVector) .def("GetRecoilVector", &AEmitter::GetRecoilVector) @@ -987,7 +985,7 @@ int LuaMan::Create() value("CLOSING", ADoor::DoorState::CLOSING), value("STOPPED", ADoor::DoorState::STOPPED) ] - .property("Door", &ADoor::GetDoor, &ADoor::SetDoor) + .property("Door", &ADoor::GetDoor, &ADoor::SetDoor, copy(result), adopt(_2)) .def("GetDoorState", &ADoor::GetDoorState) .def("OpenDoor", &ADoor::OpenDoor) .def("CloseDoor", &ADoor::CloseDoor) @@ -999,7 +997,7 @@ int LuaMan::Create() .property("HandPos", &Arm::GetHandPos, &Arm::SetHandPos), ABSTRACTLUABINDING(Leg, Attachable) - .property("Foot", &Leg::GetFoot, &Leg::SetFoot), + .property("Foot", &Leg::GetFoot, &Leg::SetFoot, copy(result), adopt(_2)), CONCRETELUABINDING(AHuman, Actor) // These are all private/protected so they can't be bound, need to consider making them public. @@ -1071,12 +1069,12 @@ int LuaMan::Create() .def(constructor<>()) .property("Head", &AHuman::GetHead, &AHuman::SetHead) .property("Jetpack", &AHuman::GetJetpack, &AHuman::SetJetpack) - .property("FGArm", &AHuman::GetFGArm, &AHuman::SetFGArm) - .property("BGArm", &AHuman::GetBGArm, &AHuman::SetBGArm) - .property("FGLeg", &AHuman::GetFGLeg, &AHuman::SetFGLeg) - .property("BGLeg", &AHuman::GetBGLeg, &AHuman::SetBGLeg) - .property("FGFoot", &AHuman::GetFGFoot) - .property("BGFoot", &AHuman::GetBGFoot) + .property("FGArm", &AHuman::GetFGArm, &AHuman::SetFGArm, copy(result), adopt(_2)) + .property("BGArm", &AHuman::GetBGArm, &AHuman::SetBGArm, copy(result), adopt(_2)) + .property("FGLeg", &AHuman::GetFGLeg, &AHuman::SetFGLeg, copy(result), adopt(_2)) + .property("BGLeg", &AHuman::GetBGLeg, &AHuman::SetBGLeg, copy(result), adopt(_2)) + .property("FGFoot", &AHuman::GetFGFoot, &AHuman::SetFGFoot, copy(result), adopt(_2)) + .property("BGFoot", &AHuman::GetBGFoot, &AHuman::SetBGFoot, copy(result), adopt(_2)) .property("JetTimeTotal", &AHuman::GetJetTimeTotal, &AHuman::SetJetTimeTotal) .property("JetTimeLeft", &AHuman::GetJetTimeLeft, &AHuman::SetJetTimeLeft) .property("ThrowPrepTime", &AHuman::GetThrowPrepTime, &AHuman::SetThrowPrepTime) @@ -1160,12 +1158,12 @@ int LuaMan::Create() value("LANDJUMP", 5 /*ACrab::JumpState::LANDJUMP*/) ] .def(constructor<>()) - .property("Turret", &ACrab::GetTurret, &ACrab::SetTurret) - .property("Jetpack", &ACrab::GetJetpack, &ACrab::SetJetpack) - .property("LFGLeg", &ACrab::GetLeftFGLeg, &ACrab::SetLeftFGLeg) - .property("LBGLeg", &ACrab::GetLeftBGLeg, &ACrab::SetLeftBGLeg) - .property("RFGLeg", &ACrab::GetRightFGLeg, &ACrab::SetRightFGLeg) - .property("RBGLeg", &ACrab::GetRightBGLeg, &ACrab::SetRightBGLeg) + .property("Turret", &ACrab::GetTurret, &ACrab::SetTurret, copy(result), adopt(_2)) + .property("Jetpack", &ACrab::GetJetpack, &ACrab::SetJetpack, copy(result), adopt(_2)) + .property("LFGLeg", &ACrab::GetLeftFGLeg, &ACrab::SetLeftFGLeg, copy(result), adopt(_2)) + .property("LBGLeg", &ACrab::GetLeftBGLeg, &ACrab::SetLeftBGLeg, copy(result), adopt(_2)) + .property("RFGLeg", &ACrab::GetRightFGLeg, &ACrab::SetRightFGLeg, copy(result), adopt(_2)) + .property("RBGLeg", &ACrab::GetRightBGLeg, &ACrab::SetRightBGLeg, copy(result), adopt(_2)) .property("JetTimeTotal", &ACrab::GetJetTimeTotal, &ACrab::SetJetTimeTotal) .property("JetTimeLeft", &ACrab::GetJetTimeLeft) .property("EquippedItem", &ACrab::GetEquippedItem) @@ -1184,7 +1182,7 @@ int LuaMan::Create() .def("SetLimbPathSpeed", &ACrab::SetLimbPathSpeed), CONCRETELUABINDING(Turret, Attachable) - .property("MountedDevice", &Turret::GetMountedDevice, (void (Turret:: *)(Attachable *newMountedMO)) &Turret::SetMountedDevice), + .property("MountedDevice", &Turret::GetMountedDevice, &Turret::SetMountedDevice, copy(result), adopt(_2)), ABSTRACTLUABINDING(ACraft, Actor) .enum_("HatchState")[ @@ -1220,12 +1218,12 @@ int LuaMan::Create() .property("DeliveryDelayMultiplier", &ACraft::GetDeliveryDelayMultiplier), CONCRETELUABINDING(ACDropShip, ACraft) - .property("RightEngine", &ACDropShip::GetRightThruster, &ACDropShip::SetRightThruster) - .property("LeftEngine", &ACDropShip::GetLeftThruster, &ACDropShip::SetLeftThruster) - .property("RightThruster", &ACDropShip::GetURightThruster, &ACDropShip::SetURightThruster) - .property("LeftThruster", &ACDropShip::GetULeftThruster, &ACDropShip::SetULeftThruster) - .property("LeftHatch", &ACDropShip::GetLeftHatch, &ACDropShip::SetLeftHatch) - .property("RightHatch", &ACDropShip::GetRightHatch, &ACDropShip::SetRightHatch) + .property("RightEngine", &ACDropShip::GetRightThruster, &ACDropShip::SetRightThruster, copy(result), adopt(_2)) + .property("LeftEngine", &ACDropShip::GetLeftThruster, &ACDropShip::SetLeftThruster, copy(result), adopt(_2)) + .property("RightThruster", &ACDropShip::GetURightThruster, &ACDropShip::SetURightThruster, copy(result), adopt(_2)) + .property("LeftThruster", &ACDropShip::GetULeftThruster, &ACDropShip::SetULeftThruster, copy(result), adopt(_2)) + .property("RightHatch", &ACDropShip::GetRightHatch, &ACDropShip::SetRightHatch, copy(result), adopt(_2)) + .property("LeftHatch", &ACDropShip::GetLeftHatch, &ACDropShip::SetLeftHatch, copy(result), adopt(_2)) .property("MaxEngineAngle", &ACDropShip::GetMaxEngineAngle, &ACDropShip::SetMaxEngineAngle) .property("LateralControlSpeed", &ACDropShip::GetLateralControlSpeed, &ACDropShip::SetLateralControlSpeed) .property("LateralControl", &ACDropShip::GetLateralControl) @@ -1241,13 +1239,13 @@ int LuaMan::Create() value("RAISING", 3 /*ACRocket::LandingGearState::RAISING*/), value("GearStateCount", 4 /*ACRocket::LandingGearState::GearStateCount*/) ] - .property("RightLeg", &ACRocket::GetRightLeg, &ACRocket::SetRightLeg) - .property("LeftLeg", &ACRocket::GetLeftLeg, &ACRocket::SetLeftLeg) - .property("MainEngine", &ACRocket::GetMainThruster, &ACRocket::SetMainThruster) - .property("LeftEngine", &ACRocket::GetLeftThruster, &ACRocket::SetLeftThruster) - .property("RightEngine", &ACRocket::GetRightThruster, &ACRocket::SetRightThruster) - .property("LeftThruster", &ACRocket::GetULeftThruster, &ACRocket::SetULeftThruster) - .property("RightThruster", &ACRocket::GetURightThruster, &ACRocket::SetURightThruster) + .property("RightLeg", &ACRocket::GetRightLeg, &ACRocket::SetRightLeg, copy(result), adopt(_2)) + .property("LeftLeg", &ACRocket::GetLeftLeg, &ACRocket::SetLeftLeg, copy(result), adopt(_2)) + .property("MainEngine", &ACRocket::GetMainThruster, &ACRocket::SetMainThruster, copy(result), adopt(_2)) + .property("LeftEngine", &ACRocket::GetLeftThruster, &ACRocket::SetLeftThruster, copy(result), adopt(_2)) + .property("RightEngine", &ACRocket::GetRightThruster, &ACRocket::SetRightThruster, copy(result), adopt(_2)) + .property("LeftThruster", &ACRocket::GetULeftThruster, &ACRocket::SetULeftThruster, copy(result), adopt(_2)) + .property("RightThruster", &ACRocket::GetURightThruster, &ACRocket::SetURightThruster, copy(result), adopt(_2)) .property("GearState", &ACRocket::GetGearState), CONCRETELUABINDING(HeldDevice, Attachable) @@ -1301,7 +1299,8 @@ int LuaMan::Create() .property("RateOfFire", &HDFirearm::GetRateOfFire, &HDFirearm::SetRateOfFire) .property("FullAuto", &HDFirearm::IsFullAuto, &HDFirearm::SetFullAuto) .property("RoundInMagCount", &HDFirearm::GetRoundInMagCount) - .property("Magazine", &HDFirearm::GetMagazine, &HDFirearm::SetMagazine) + .property("Magazine", &HDFirearm::GetMagazine, &HDFirearm::SetMagazine, copy(result), adopt(_2)) + .property("Flash", &HDFirearm::GetFlash, &HDFirearm::SetFlash, copy(result), adopt(_2)) .property("ActivationDelay", &HDFirearm::GetActivationDelay, &HDFirearm::SetActivationDelay) .property("DeactivationDelay", &HDFirearm::GetDeactivationDelay, &HDFirearm::SetDeactivationDelay) .property("ReloadTime", &HDFirearm::GetReloadTime, &HDFirearm::SetReloadTime) From ec47823797c3cc70917ed2ff5b50a0a0c75208ff Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 11 Sep 2020 03:44:05 -0300 Subject: [PATCH 042/144] A bit of cleanup on Turret to match up with jointpos changes and rename the MountedMO property to MountedDevice. Also some cleanup --- Entities/Turret.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index 3d6c8edc0..2cb1f400f 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -26,12 +26,13 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int Turret::ReadProperty(std::string propName, Reader &reader) { - if (propName == "MountedMO") { - const Entity *pEntity = g_PresetMan.GetEntityPreset(reader); - if (pEntity) { - m_MountedDevice = dynamic_cast(pEntity->Clone()); + if (propName == "MountedDevice") { + const Entity *entity = g_PresetMan.GetEntityPreset(reader); + if (entity) { + m_MountedDevice = dynamic_cast(entity->Clone()); + m_MountedDevice->SetInheritsRotAngle(false); } - pEntity = 0; + entity = 0; } else { return Attachable::ReadProperty(propName, reader); } @@ -44,7 +45,7 @@ namespace RTE { int Turret::Save(Writer &writer) const { Attachable::Save(writer); - writer.NewProperty("MountedMO"); + writer.NewProperty("MountedDevice"); writer << m_MountedDevice; return 0; @@ -88,7 +89,6 @@ namespace RTE { void Turret::Update() { if (m_MountedDevice) { - m_MountedDevice->SetJointPos(m_Pos + m_MountedDevice->GetParentOffset().GetXFlipped(m_HFlipped) * m_Rotation); m_MountedDevice->SetRotAngle(m_Rotation.GetRadAngle() + m_MountedDeviceRotOffset); if (m_Parent) { //if (m_MountedDevice->IsRecoiled()) { From 0301396db1ac4ad5c4b2a1cb6f44c31dd3a8b76b Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 14 Sep 2020 23:15:08 -0300 Subject: [PATCH 043/144] Made ADoor, AEmitter, Arm and HDFirearm work with new attachable handling Renamed ADoor::UpdateDoorAttachable to UpdateDoorAttachableActions since it doesn't actually update the door attachable anymore --- Entities/ADoor.cpp | 23 ++++++++++--------- Entities/ADoor.h | 2 +- Entities/AEmitter.cpp | 35 ++++++++++------------------- Entities/Arm.cpp | 50 ++++++++++++++++++------------------------ Entities/HDFirearm.cpp | 12 +--------- Entities/Leg.cpp | 4 ++-- 6 files changed, 48 insertions(+), 78 deletions(-) diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index 28b4c93eb..5d763c7a0 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -86,6 +86,7 @@ namespace RTE { delete m_Door; m_Door = new Attachable; reader >> m_Door; + m_Door->SetInheritsRotAngle(false); m_DoorMaterialID = m_Door->GetMaterial()->GetIndex(); } else if (propName == "OpenOffset") { reader >> m_OpenOffset; @@ -349,14 +350,15 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ADoor::Update() { - Actor::Update(); if (m_Door && m_Door->IsAttached()) { if (m_DoorState != STOPPED && m_SensorTimer.IsPastSimMS(m_SensorInterval)) { UpdateSensors(); } - UpdateDoorAttachable(); + UpdateDoorAttachableActions(); } - if (m_Door && !ApplyAttachableForces(m_Door)) { + Actor::Update(); + + if (m_Door) { EraseDoorMaterial(); m_Door = 0; // Start the spinning out of control animation for the motor, start it slow @@ -412,14 +414,12 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void ADoor::UpdateDoorAttachable() { + void ADoor::UpdateDoorAttachableActions() { Vector startOffset; Vector endOffset; float startAngle; float endAngle; - m_Door->SetHFlipped(m_HFlipped); - if (m_DoorState == OPEN || m_DoorState == OPENING) { startOffset = m_ClosedOffset; endOffset = m_OpenOffset; @@ -433,16 +433,16 @@ namespace RTE { } if (m_DoorState == OPEN || m_DoorState == CLOSED) { - m_Door->SetJointPos(m_Pos + endOffset.GetXFlipped(m_HFlipped) * m_Rotation); - m_Door->SetRotAngle(m_Rotation.GetRadAngle() + (endAngle * GetFlipFactor())); + m_Door->SetParentOffset(endOffset); + m_Door->SetRotAngle(m_Rotation.GetRadAngle() + (endAngle * static_cast(GetFlipFactor()))); } else if (m_DoorState == OPENING || m_DoorState == CLOSING) { if (!m_DoorMoveSound.IsBeingPlayed()) { m_DoorMoveSound.Play(m_Pos); } if (m_DoorMoveTimer.IsPastSimMS(m_DoorMoveTime)) { m_ResetToDefaultStateTimer.Reset(); - m_Door->SetJointPos(m_Pos + endOffset.GetXFlipped(m_HFlipped) * m_Rotation); - m_Door->SetRotAngle(m_Rotation.GetRadAngle() + (endAngle * GetFlipFactor())); + m_Door->SetParentOffset(endOffset); + m_Door->SetRotAngle(m_Rotation.GetRadAngle() + (endAngle * static_cast(GetFlipFactor()))); m_DoorMoveSound.Stop(); m_DoorMoveEndSound.Play(m_Pos); @@ -459,14 +459,13 @@ namespace RTE { // TODO: Make this work across rotation 0. Probably the best solution would be to setup an angle LERP that properly handles the 2PI border and +- angles. float updatedAngle = LERP(0, m_DoorMoveTime, startAngle, endAngle, m_DoorMoveTimer.GetElapsedSimTimeMS()); - m_Door->SetJointPos(m_Pos + updatedOffset.GetXFlipped(m_HFlipped) * m_Rotation); + m_Door->SetParentOffset(updatedOffset); m_Door->SetRotAngle(m_Rotation.GetRadAngle() + (updatedAngle * GetFlipFactor())); // Clear away any terrain debris when the door is moving but only after a short delay so it doesn't take a chunk out of the ground if (m_DoorMoveTimer.IsPastSimMS(50)) { m_Door->DeepCheck(true); } } } - m_Door->Update(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ADoor.h b/Entities/ADoor.h index 396344d56..3c34ab47a 100644 --- a/Entities/ADoor.h +++ b/Entities/ADoor.h @@ -202,7 +202,7 @@ namespace RTE { /// /// Updates the door attachable position and movement based on the current state of this ADoor. This is called from Update(). /// - void UpdateDoorAttachable(); + void UpdateDoorAttachableActions(); #pragma endregion /// diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index 4a2ede845..66faf141a 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -170,6 +170,7 @@ int AEmitter::ReadProperty(std::string propName, Reader &reader) { if (pObj) { m_pFlash = dynamic_cast(pObj->Clone()); m_pFlash->SetDrawnNormallyByParent(false); + m_pFlash->SetInheritsRotAngle(false); } } else if (propName == "FlashScale") { reader >> m_FlashScale; @@ -390,6 +391,17 @@ void AEmitter::Update() m_Frame = 0; } + // Update and show flash if there is one + if (m_pFlash && (!m_FlashOnlyOnBurst || m_BurstTriggered)) { + m_pFlash->SetParentOffset(m_EmissionOffset); + if (m_EmitEnabled && !m_WasEmitting) { + // Don't set the flipping for the flash because that is wasting resources when drawing, just handle the flipping of the rotation here. + m_pFlash->SetRotAngle(m_HFlipped ? c_PI + m_Rotation.GetRadAngle() - m_EmitAngle.GetRadAngle() : m_Rotation.GetRadAngle() + m_EmitAngle.GetRadAngle()); + m_pFlash->SetScale(m_FlashScale); + m_pFlash->SetNextFrame(); + } + } + Attachable::Update(); if (m_EmitEnabled) @@ -533,21 +545,6 @@ void AEmitter::Update() else m_ImpulseForces.push_back(make_pair(pushImpulses * m_JointStiffness, Vector())); - // Update and show flash if there is one - if (m_pFlash && (!m_FlashOnlyOnBurst || m_BurstTriggered)) { - if (!m_EmissionOffset.IsZero()) - m_pFlash->SetJointPos(m_Pos + RotateOffset(m_EmissionOffset)/* + (m_MuzzleOff.GetXFlipped(m_HFlipped) * m_Rotation)*/); - else - m_pFlash->SetJointPos(m_Pos/* + (m_MuzzleOff.GetXFlipped(m_HFlipped) * m_Rotation)*/); - // Don't set the flipping for the flash because that is wasting resources when drawing, - // just handle the flipping of the rotation here. - m_pFlash->SetRotAngle(m_HFlipped ? c_PI + m_Rotation.GetRadAngle() - m_EmitAngle.GetRadAngle() : m_Rotation.GetRadAngle() + m_EmitAngle.GetRadAngle()); -// m_pFlash->SetFrame(floorf((m_pFlash->GetFrameCount()/* - 1*/) * PosRand() - 0.001)); - m_pFlash->SetScale(m_FlashScale); - m_pFlash->SetNextFrame(); - m_pFlash->Update(); - } - // Count the the damage caused by the emissions, and only if we're not bursting if (!m_BurstTriggered) m_DamageCount += (float)emissions * m_EmitDamage * m_EmitterDamageMultiplier; @@ -568,14 +565,6 @@ void AEmitter::Update() // Do stuff to stop emission else { - // Fix for when emitter is not emitting the flash is drawn on the wrong position - if (m_pFlash) { - if (!m_EmissionOffset.IsZero()) - m_pFlash->SetJointPos(m_Pos + RotateOffset(m_EmissionOffset)/* + (m_MuzzleOff.GetXFlipped(m_HFlipped) * m_Rotation)*/); - else - m_pFlash->SetJointPos(m_Pos/* + (m_MuzzleOff.GetXFlipped(m_HFlipped) * m_Rotation)*/); - } - if (m_WasEmitting) { m_EmissionSound.Stop(); diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 2daf4e504..3fd6ea529 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -379,9 +379,9 @@ void Arm::GibThis(const Vector &impactImpulse, float internalBlast, MovableObjec ////////////////////////////////////////////////////////////////////////////////////////// // Description: Updates this Arm. Supposed to be done every frame. -void Arm::Update() -{ - // Update basic metrics from parent. +void Arm::Update() { + + Attachable::Update(); if (!m_Parent) { @@ -396,8 +396,7 @@ void Arm::Update() // Update hand m_HandOffset.SetXY(m_MaxLength * 0.65, 0); m_HandOffset.RadRotate((m_HFlipped ? c_PI : 0) + m_Rotation.GetRadAngle()); - } - else { + } else { // Attached, so act like it // If a Firearm or Shield device is held, but not a throwable, update it and arm configuration accordingly. @@ -437,9 +436,13 @@ void Arm::Update() ConstrainHand(); float handAngle = m_HandOffset.GetAbsRadAngle(); - pHeldDev->SetJointPos(m_JointPos + m_HandOffset); - pHeldDev->SetRotAngle(m_Rotation.GetRadAngle()); - pHeldDev->Update(); + + // In order to keep the HeldDevice in the right place, we need to convert its offset (the hand offset) to work as the ParentOffset for the HeldDevice. + // The HeldDevice will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. + Vector handOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_HandOffset; + handOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); + pHeldDev->SetParentOffset(handOffsetAsParentOffset); + if (pHeldDev->IsRecoiled()) m_Parent->AddImpulseForce(pHeldDev->GetRecoilForce()); else @@ -448,15 +451,8 @@ void Arm::Update() m_Rotation = (m_HFlipped ? c_PI : 0) + handAngle; // Redo the positioning of the arm now since the rotation has changed and RotateOffset will return different results - if (!m_JointPos.IsZero()) - m_Pos = m_JointPos - RotateOffset(m_JointOffset); - else - m_Pos = m_Parent->GetPos() - RotateOffset(m_JointOffset); + m_Pos = m_JointPos - RotateOffset(m_JointOffset); - // Apply forces and detach if necessary - // OBSERVE the memeber pointer is what gets set to 0!$@#$@ - if (!ApplyAttachableForces(pHeldDev)) - m_pHeldMO = 0; // If it blew up or whatever, releaes it from hand and put into scene so it'll be cleaned up properly if (m_pHeldMO && m_pHeldMO->IsSetToDelete()) g_MovableMan.AddItem(ReleaseHeldMO()); @@ -495,22 +491,18 @@ void Arm::Update() m_Rotation = (m_HFlipped ? c_PI : 0) + m_HandOffset.GetAbsRadAngle(); // Redo the positioning of the arm now since the rotation has changed and RotateOffset will return different results - if (!m_JointPos.IsZero()) - m_Pos = m_JointPos - RotateOffset(m_JointOffset); - else - m_Pos = m_Parent->GetPos() - RotateOffset(m_JointOffset); + m_Pos = m_JointPos - RotateOffset(m_JointOffset); // If holding something other than a FireArm, then update it - if (m_pHeldMO) - { + if (m_pHeldMO) { Attachable *pHeldDev = dynamic_cast(m_pHeldMO); - if (pHeldDev) - pHeldDev->SetJointPos(m_JointPos + m_HandOffset); - else - m_pHeldMO->SetPos(m_JointPos + m_HandOffset); - m_pHeldMO->SetHFlipped(m_HFlipped); - m_pHeldMO->SetRotAngle(m_Rotation.GetRadAngle()); - m_pHeldMO->Update(); + + // In order to keep the HeldDevice in the right place, we need to convert its offset (the hand offset) to work as the ParentOffset for the HeldDevice. + // The HeldDevice will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. + Vector handOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_HandOffset; + handOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); + pHeldDev->SetParentOffset(handOffsetAsParentOffset); + // If it blew up or whatever, releaes it from hand and put into scene so it'll be cleaned up properly if (m_pHeldMO->IsSetToDelete()) g_MovableMan.AddItem(ReleaseHeldMO()); diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index b7b11aeb5..dc9f063ec 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -939,11 +939,8 @@ void HDFirearm::Update() // Display gun flame frame. if (m_pFlash) { - m_pFlash->SetHFlipped(m_HFlipped); - m_pFlash->SetJointPos(m_Pos + (m_MuzzleOff.GetXFlipped(m_HFlipped) * m_Rotation)); - m_pFlash->SetRotAngle(m_Rotation.GetRadAngle()); + m_pFlash->SetParentOffset(m_MuzzleOff); m_pFlash->SetFrame(floorf((m_pFlash->GetFrameCount()/* - 1*/) * PosRand() - 0.001)); - m_pFlash->Update(); } // Play firing sound @@ -1001,17 +998,10 @@ void HDFirearm::Update() // Update fitted Magazine. if (m_pMagazine) { - m_pMagazine->SetHFlipped(m_HFlipped); - m_pMagazine->SetJointPos(m_Pos + RotateOffset(m_pMagazine->GetParentOffset())); - m_pMagazine->SetRotAngle(m_Rotation.GetRadAngle()); - m_pMagazine->Update(); // Recoil offset has to be applied after the Update or it'll get reset within the update m_pMagazine->SetRecoil(m_RecoilForce, m_RecoilOffset, m_Recoiled); } - if (!ApplyAttachableForces(m_pMagazine)) - m_pMagazine = 0; - m_FiredLastFrame = m_FireFrame; } diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index d41cdcac1..ed90f5a6d 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -162,8 +162,8 @@ namespace RTE { } if (m_Foot) { - // In order to keep the ankle in the right place, we need to convert its offset to work as the ParentOffset for the foot. The Foot will then use this to set its JointPos when it's updated. - // Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. + // In order to keep the foot in the right place, we need to convert its offset (the ankle offstet) to work as the ParentOffset for the foot. + // The foot will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. Vector ankleOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_CurrentAnkleOffset; ankleOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); m_Foot->SetParentOffset(ankleOffsetAsParentOffset); From feb480d53fe32b8dfd4aa2dd60d2ae35be502a8c Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 14 Sep 2020 23:28:40 -0300 Subject: [PATCH 044/144] Renamed DeleteWithParent to DeleteWhenRemovedFromParent since this more accurately describes what it does. Added setter for this and used it for flashes Added Create() for Attachable and made that set its subgroup ID. Subgroup ID is no longer copied by clone create Removed Attachable SetJointPos since that's now done internally, made attachables collide with terrain while attached by default, made breakwound setters not const cause that was screwing with lua bindings Added RemoveAttachable with boolean flags to add the removed attachable to movableman and to add breakwounds to the parent and attachable. Renamed ApplyAttachableForces to TransferForcesFromAttachable and cleaned it up Made AddAttachable safely remove MOs from MovableMan so there's no issues there Misc fixes and stuff in Attachable and MOSRotating --- Entities/AEmitter.cpp | 1 + Entities/Arm.cpp | 1 - Entities/Attachable.cpp | 93 +++++++++-------- Entities/Attachable.h | 35 ++++--- Entities/HDFirearm.cpp | 1 + Entities/MOSRotating.cpp | 212 +++++++++++++++++---------------------- Entities/MOSRotating.h | 62 +++++++----- 7 files changed, 203 insertions(+), 202 deletions(-) diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index 66faf141a..ec0061ad4 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -171,6 +171,7 @@ int AEmitter::ReadProperty(std::string propName, Reader &reader) { m_pFlash = dynamic_cast(pObj->Clone()); m_pFlash->SetDrawnNormallyByParent(false); m_pFlash->SetInheritsRotAngle(false); + m_pFlash->SetDeleteWhenRemovedFromParent(true); } } else if (propName == "FlashScale") { reader >> m_FlashScale; diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 3fd6ea529..e60ca3205 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -204,7 +204,6 @@ void Arm::SetHeldMO(MovableObject *newHeldMO) if (newHeldMO && (newHeldMO->IsHeldDevice() || newHeldMO->IsThrownDevice())) { Attachable *pNewDev = dynamic_cast(newHeldMO); if (pNewDev->IsAttached()) { dynamic_cast(pNewDev->GetParent())->RemoveAttachable(pNewDev); } - g_MovableMan.RemoveMO(pNewDev); AddAttachable(pNewDev); pNewDev->SetTeam(m_Team); pNewDev = 0; diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 72b5aaa43..77ea81201 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -16,7 +16,7 @@ namespace RTE { m_ParentOffset.Reset(); m_DrawAfterParent = true; m_DrawnNormallyByParent = true; - m_DeleteWithParent = false; + m_DeleteWhenRemovedFromParent = false; m_JointStrength = 10; m_JointStiffness = 1.0; @@ -33,7 +33,17 @@ namespace RTE { m_InheritsRotAngle = true; m_AtomSubgroupID = -1; - m_CollidesWithTerrainWhileAttached = false; + m_CollidesWithTerrainWhileAttached = true; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int Attachable::Create() { + MOSRotating::Create(); + + m_AtomSubgroupID = GetUniqueID(); + + return 0; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -45,7 +55,7 @@ namespace RTE { m_ParentOffset = reference.m_ParentOffset; m_DrawAfterParent = reference.m_DrawAfterParent; m_DrawnNormallyByParent = reference.m_DrawnNormallyByParent; - m_DeleteWithParent = reference.m_DeleteWithParent; + m_DeleteWhenRemovedFromParent = reference.m_DeleteWhenRemovedFromParent; m_JointStrength = reference.m_JointStrength; m_JointStiffness = reference.m_JointStiffness; @@ -61,7 +71,6 @@ namespace RTE { m_InheritsHFlipped = reference.m_InheritsHFlipped; m_InheritsRotAngle = reference.m_InheritsRotAngle; - m_AtomSubgroupID = reference.m_AtomSubgroupID; m_CollidesWithTerrainWhileAttached = reference.m_CollidesWithTerrainWhileAttached; return 0; @@ -74,8 +83,8 @@ namespace RTE { reader >> m_ParentOffset; } else if (propName == "DrawAfterParent") { reader >> m_DrawAfterParent; - } else if (propName == "DeleteWithParent") { - reader >> m_DeleteWithParent; + } else if (propName == "DeleteWhenRemovedFromParent" || propName == "DeleteWithParent") { + reader >> m_DeleteWhenRemovedFromParent; } else if (propName == "JointStrength" || propName == "Strength") { reader >> m_JointStrength; } else if (propName == "JointStiffness" || propName == "Stiffness") { @@ -110,8 +119,8 @@ namespace RTE { writer << m_ParentOffset; writer.NewProperty("DrawAfterParent"); writer << m_DrawAfterParent; - writer.NewProperty("DeleteWithParent"); - writer << m_DeleteWithParent; + writer.NewProperty("DeleteWhenRemovedFromParent"); + writer << m_DeleteWhenRemovedFromParent; writer.NewProperty("JointStrength"); writer << m_JointStrength; @@ -126,8 +135,7 @@ namespace RTE { writer << m_ParentBreakWound; writer.NewProperty("InheritsHFlipped"); - if (m_InheritsHFlipped != 0 && m_InheritsHFlipped != 1) { m_InheritsHFlipped = 2; } - writer << m_InheritsHFlipped; + writer << ((m_InheritsHFlipped == 0 || m_InheritsHFlipped == 1) ? m_InheritsHFlipped : 2); writer.NewProperty("InheritsRotAngle"); writer << m_InheritsRotAngle; @@ -144,13 +152,13 @@ namespace RTE { return false; } - Vector forces; + Vector totalForce; for (const std::pair &force : m_Forces) { - forces += force.first; + totalForce += force.first; } - m_Forces.clear(); - jointForces += forces; + jointForces += totalForce; + m_Forces.clear(); return true; } @@ -161,39 +169,35 @@ namespace RTE { return false; } - Vector impulseForces; + Vector totalImpulseForce; for (const std::pair &impulseForce : m_ImpulseForces) { - impulseForces += impulseForce.first; + totalImpulseForce += impulseForce.first; } - impulseForces *= m_JointStiffness; - - if (impulseForces.GetMagnitude() > m_JointStrength) { - impulseForces.SetMagnitude(m_JointStrength); - jointImpulses += impulseForces; - if (m_BreakWound) { - AEmitter *breakWound = dynamic_cast(m_BreakWound->Clone()); - if (breakWound) { - breakWound->SetEmitAngle(m_JointOffset.GetAbsRadAngle()); - AddWound(breakWound, m_JointOffset, false); - breakWound = 0; - } - } - m_Parent->RemoveAttachable(this); - g_MovableMan.AddParticle(this); + + if (m_GibImpulseLimit > 0 && totalImpulseForce.GetMagnitude() > m_GibImpulseLimit) { + jointImpulses += (totalImpulseForce.SetMagnitude(totalImpulseForce.GetMagnitude() - m_GibImpulseLimit)) * m_JointStiffness; + GibThis(); + return false; + } else if (m_JointStrength > 0 && totalImpulseForce.GetMagnitude() > m_JointStrength) { + jointImpulses += (totalImpulseForce.SetMagnitude(totalImpulseForce.GetMagnitude() - m_JointStiffness)) * m_JointStiffness; + m_Parent->RemoveAttachable(this, true, true); return false; + } else { + jointImpulses += totalImpulseForce * m_JointStiffness; } - for (const std::pair &impulseForce : m_ImpulseForces) { - if (!impulseForce.second.IsZero()) { - // Rough explanation of what this is doing: - // The first part is getting the Dot/Scalar product of the perpendicular of the offset vector for the force onto the force vector itself (dot product is the amount two vectors are pointing in the same direction). - // The second part is dividing that Dot product by the moment of inertia, i.e. the torque needed to make it turn. All of this is multiplied by 1 - JointStiffness, because max stiffness joints transfer all force to parents and min stiffness transfer none. - m_AngularVel += (impulseForce.second.GetPerpendicular().Dot(impulseForce.first) / m_pAtomGroup->GetMomentOfInertia()) * (1.0F - m_JointStiffness); + // Rough explanation of what this is doing: + // The first part is getting the Dot/Scalar product of the perpendicular of the offset vector for the force onto the force vector itself (dot product is the amount two vectors are pointing in the same direction). + // The second part is dividing that Dot product by the moment of inertia, i.e. the torque needed to make it turn. All of this is multiplied by 1 - JointStiffness, because max stiffness joints transfer all force to parents and min stiffness transfer none. + if (!m_InheritsRotAngle) { + for (const std::pair &impulseForce : m_ImpulseForces) { + if (!impulseForce.second.IsZero()) { + m_AngularVel += (impulseForce.second.GetPerpendicular().Dot(impulseForce.first) / m_pAtomGroup->GetMomentOfInertia()) * (1.0F - m_JointStiffness); + } } } - m_ImpulseForces.clear(); - jointImpulses += impulseForces; + m_ImpulseForces.clear(); return true; } @@ -255,8 +259,9 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Attachable::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { + m_ToDelete = true; // Necessary to avoid oddities with breakwounds if (m_Parent) { - m_Parent->RemoveAttachable(this); + m_Parent->RemoveAttachable(this, true, true); } else { SetParent(nullptr); } @@ -279,6 +284,14 @@ namespace RTE { if (InheritsHFlipped() != 0) { m_HFlipped = m_InheritsHFlipped == 1 ? m_Parent->IsHFlipped() : !m_Parent->IsHFlipped(); } if (InheritsRotAngle()) { SetRotAngle(m_Parent->GetRotAngle()); } + if (m_CollidesWithTerrainWhileAttached) { + float facingAngle = (m_HFlipped ? c_PI : 0) + GetRotAngle() * static_cast(GetFlipFactor()); + float parentFacingAngle = (m_Parent->IsHFlipped() ? c_PI : 0) + m_Parent->GetRotAngle() * static_cast(m_Parent->GetFlipFactor()); + + Matrix atomRot(facingAngle - parentFacingAngle); + m_pAtomGroup->UpdateSubAtoms(GetAtomSubgroupID(), GetParentOffset() - (GetJointOffset() * atomRot), atomRot); + } + m_DeepCheck = false; } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 7ca328b47..adc159797 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -27,10 +27,16 @@ namespace RTE { Attachable() { Clear(); } /// - /// Creates a Attachable to be identical to another, by deep copy. + /// Makes the Attachable object ready for use. + /// + /// An error return value signaling success or any particular failure. Anything below 0 is an error signal. + int Create(); + + /// + /// Creates an Attachable to be identical to another, by deep copy. /// /// A reference to the Attachable to deep copy. - /// An error return value signaling sucess or any particular failure. Anything below 0 is an error signal. + /// An error return value signaling success or any particular failure. Anything below 0 is an error signal. int Create(const Attachable &reference); #pragma endregion @@ -129,10 +135,16 @@ namespace RTE { void SetDrawnNormallyByParent(bool drawnNormallyByParent) { m_DrawnNormallyByParent = drawnNormallyByParent; } /// - /// Gets whether this Attachable will be deleted automatically when its parent is being deleted or not. + /// Gets whether this Attachable will be deleted when it's removed from its parent. Has no effect until the Attachable is added to a parent. /// - /// Whether this Attachable is marked to be deleted along with it's parent or not. - bool ToDeleteWithParent() const { return m_DeleteWithParent; } + /// Whether this Attachable is marked to be deleted when it's removed from its parent or not. + bool GetDeleteWhenRemovedFromParent() const { return m_DeleteWhenRemovedFromParent; } + + /// + /// Sets whether this Attachable will be deleted when it's removed from its parent. + /// + /// Whether this Attachable should be deleted when it's removed from its parent. + void SetDeleteWhenRemovedFromParent(bool deleteWhenRemovedFromParent) { m_DeleteWhenRemovedFromParent = deleteWhenRemovedFromParent; } #pragma endregion #pragma region Joint Getters and Setters @@ -173,13 +185,6 @@ namespace RTE { /// /// A Vector describing the offset of the joint relative to the this Attachable's origin/center of mass position. void SetJointOffset(Vector offset) { m_JointOffset = offset; } - - /// - /// Sets the position of this Attachable by defining where the joint is. - /// Upon Update(), this will be translated into what the actual position of the Attachable origin/center of mass is, depending on its set rotational angle and joint offset. - /// - /// A const reference to the new joint position to set the position with. - void SetJointPos(const Vector &jointPos) { m_JointPos = jointPos; } #pragma endregion #pragma region Force Managment @@ -240,7 +245,7 @@ namespace RTE { /// Sets the AEmitter that represents the wound added to this Attachable when it gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! /// /// The AEmitter to use for this Attachable's breakwound. - void SetBreakWound(const AEmitter *breakWound) { m_BreakWound = breakWound; } //TODO I added this for consistency but do we want it? Maybe should have a string version that does the presetman lookup, cause we need to have a working pointer to the breakwound. + void SetBreakWound(AEmitter *breakWound) { m_BreakWound = breakWound; } //TODO I added this for consistency but do we want it? Maybe should have a string version that does the presetman lookup, cause we need to have a working pointer to the breakwound. /// /// Gets the AEmitter that represents the wound added to this Attachable's parent when this Attachable gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! @@ -252,7 +257,7 @@ namespace RTE { /// Sets the AEmitter that represents the wound added to this Attachable's parent when this Attachable gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! /// /// The AEmitter to use for the parent's breakwound. - void SetParentBreakWound(const AEmitter *breakWound) { m_ParentBreakWound = breakWound; } + void SetParentBreakWound(AEmitter *breakWound) { m_ParentBreakWound = breakWound; } #pragma endregion #pragma region Inherited Value Getters and Setters @@ -349,7 +354,7 @@ namespace RTE { Vector m_ParentOffset; //!< The offset from the parent's Pos to the joint point this Attachable is attached with. bool m_DrawAfterParent; //!< Whether to draw this Attachable after (in front of) or before (behind) the parent. bool m_DrawnNormallyByParent; //!< Whether this Attachable will be be drawn normally when attached, or will require special handling by some non-MOSR parent type. - bool m_DeleteWithParent; //!< Whether this Attachable should be deleted when its parent is set ToDelete. + bool m_DeleteWhenRemovedFromParent; //!< Whether this Attachable should be deleted when it's removed from its parent. float m_JointStrength; //!< The amount of impulse force needed on this to deatch it from the host Actor, in kg * m/s. float m_JointStiffness; //!< The normalized joint stiffness scalar. 1.0 means impulse forces on this attachable will be transferred to the parent with 100% strength, 0 means they will not transfer at all. diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index dc9f063ec..8d1ccd2c5 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -154,6 +154,7 @@ int HDFirearm::ReadProperty(std::string propName, Reader &reader) { delete m_pFlash; m_pFlash = dynamic_cast(pObj->Clone()); m_pFlash->SetDrawnNormallyByParent(false); + m_pFlash->SetDeleteWhenRemovedFromParent(true); } } else if (propName == "FireSound") { reader >> m_FireSound; diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index f7cf43585..0565ef46a 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -417,29 +417,6 @@ int MOSRotating::Save(Writer &writer) const return 0; } - -/// -/// Attaches the passed in wound AEmitter and adds it to the list of wounds, changing its parent offset to the passed in Vector. -/// -/// The wound AEmitter to add -/// The vector to set as the wound AEmitter's parent offset -void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit) { - if (woundToAdd) { - if (checkGibWoundLimit && !ToDelete() && m_GibWoundLimit && m_Wounds.size() + 1 > m_GibWoundLimit) { - // Indicate blast in opposite direction of emission - // TODO: don't hardcode here, get some data from the emitter - Vector blast(-5, 0); - blast.RadRotate(woundToAdd->GetEmitAngle()); - GibThis(blast); - return; - } else { - woundToAdd->SetParentOffset(parentOffsetToSet); - woundToAdd->SetParent(this); - m_Wounds.push_back(woundToAdd); - } - } -} - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int MOSRotating::GetGibWoundLimit(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const { @@ -478,6 +455,25 @@ int MOSRotating::GetWoundCount(bool includeAttachablesWithAPositiveDamageMultipl ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit) { + if (woundToAdd) { + if (checkGibWoundLimit && !ToDelete() && m_GibWoundLimit && m_Wounds.size() + 1 > m_GibWoundLimit) { + // Indicate blast in opposite direction of emission + // TODO: don't hardcode here, get some data from the emitter + Vector blast(-5, 0); + blast.RadRotate(woundToAdd->GetEmitAngle()); + GibThis(blast); + return; + } else { + woundToAdd->SetParentOffset(parentOffsetToSet); + woundToAdd->SetParent(this); + m_Wounds.push_back(woundToAdd); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) { float damage = 0; int woundCount = GetWoundCount(includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); @@ -522,7 +518,7 @@ float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachab if (woundedPart == this) { damage += removeFirstWoundEmitter() * GetDamageMultiplier(); } else { - damage += woundedPart->RemoveWounds(1, includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier) * woundedPart->GetDamageMultiplier(); + damage += woundedPart->RemoveWounds(1, includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); } if (woundedParts[woundedPartIndex].second-- <= 0) { woundedParts.erase(woundedParts.begin() + woundedPartIndex); @@ -1512,9 +1508,9 @@ void MOSRotating::Update() { if (m_OrientToVel > 0 && m_Vel.GetLargest() > 5.0) { Clamp(m_OrientToVel, 1.0F, 0.0F); - float velInfluence = Limit(m_OrientToVel < 1.0 ? m_Vel.GetMagnitude() / 100 : 1.0F, 1.0F, 0.0F); + float velInfluence = Limit(m_OrientToVel < 1.0 ? m_Vel.GetMagnitude() / 100.0F : 1.0F, 1.0F, 0.0F); float radsToGo = m_Rotation.GetRadAngleTo(m_Vel.GetAbsRadAngle()); - m_Rotation += (radsToGo * m_OrientToVel * velInfluence); + m_Rotation += radsToGo * m_OrientToVel * velInfluence; } for (AEmitter *wound : m_Wounds) { @@ -1522,15 +1518,15 @@ void MOSRotating::Update() { wound->Update(); } - Attachable *pAttachable = 0; - for (list::iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ) { - pAttachable = *aItr; - RTEAssert(pAttachable, "Broken Attachable!"); - ++aItr; + Attachable *attachable = 0; + for (list::iterator attachableIterator = m_Attachables.begin(); attachableIterator != m_Attachables.end(); ) { + attachable = *attachableIterator; + RTEAssert(attachable, "Broken Attachable!"); + ++attachableIterator; - pAttachable->Update(); + attachable->Update(); - ApplyAttachableForces(pAttachable); + TransferForcesFromAttachable(attachable); } // Create intermediate flipping bitmaps if they don't exist @@ -1599,40 +1595,60 @@ void MOSRotating::AddAttachable(Attachable *attachable) { void MOSRotating::AddAttachable(Attachable *attachable, const Vector& parentOffsetToSet) { if (attachable) { + if (g_MovableMan.ValidMO(attachable)) { g_MovableMan.RemoveMO(attachable); } attachable->SetParentOffset(parentOffsetToSet); attachable->SetParent(this); - - // Set the attachable's subgroup ID to it's Unique ID to avoid any possible conflicts when adding atoms to parent group. - attachable->SetAtomSubgroupID(attachable->GetUniqueID()); m_Attachables.push_back(attachable); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool MOSRotating::RemoveAttachable(long attachableUniqueID) { - MovableObject *attachableAsMovableObject = g_MovableMan.FindObjectByUniqueID(attachableUniqueID); - if (attachableAsMovableObject) { - return RemoveAttachable((Attachable *)attachableAsMovableObject); - } - return false; +bool MOSRotating::RemoveAttachable(long attachableUniqueID, bool addToMovableMan, bool addBreakWounds) { + MovableObject *attachableAsMovableObject = g_MovableMan.FindObjectByUniqueID(attachableUniqueID); + if (attachableAsMovableObject) { + return RemoveAttachable(dynamic_cast(attachableAsMovableObject), addToMovableMan, addBreakWounds); + } + return false; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool MOSRotating::RemoveAttachable(Attachable *attachable) { - if (attachable) { - if (m_Attachables.size() > 0) { - m_Attachables.remove(attachable); - } - if (attachable->ToDeleteWithParent()) { - attachable->SetToDelete(); - } else { - attachable->SetParent(nullptr); + +bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, bool addBreakWounds) { + if (!attachable) { + return false; + } + RTEAssert(!attachable->IsAttached() || attachable->IsAttachedTo(this), "Tried to transfer forces from another parent's (" + attachable->GetParent()->GetModuleAndPresetName() + ") Attachable (" + attachable->GetModuleAndPresetName() + "), this should never happen!"); + if (!attachable->IsAttached()) { + int a = 0; + } + + if (m_Attachables.size() > 0) { m_Attachables.remove(attachable); } + attachable->SetParent(nullptr); + + if (attachable->GetDeleteWhenRemovedFromParent()) { attachable->SetToDelete(); } + if (addToMovableMan || attachable->IsSetToDelete()) { g_MovableMan.AddMO(attachable); } + + if (addBreakWounds) { + if (!m_ToDelete && attachable->GetParentBreakWound()) { + AEmitter *parentBreakWound = dynamic_cast(attachable->GetParentBreakWound()->Clone()); + if (parentBreakWound) { + parentBreakWound->SetEmitAngle((attachable->GetParentOffset() * m_Rotation).GetAbsRadAngle()); + AddWound(parentBreakWound, attachable->GetParentOffset(), false); + parentBreakWound = nullptr; + } } - return true; - } - return false; + if (!attachable->IsSetToDelete() && attachable->GetBreakWound()) { + AEmitter *childBreakWound = dynamic_cast(attachable->GetBreakWound()->Clone()); + if (childBreakWound) { + childBreakWound->SetEmitAngle(attachable->GetJointOffset().GetAbsRadAngle()); + attachable->AddWound(childBreakWound, attachable->GetJointOffset()); + childBreakWound = nullptr; + } + } + } + return true; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1903,80 +1919,38 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, // Draw all the attached attachables for (const Attachable *attachableToDraw : m_Attachables) { - if (attachableToDraw->IsDrawnAfterParent() && attachableToDraw->IsDrawnNormallyByParent()) { + if (attachableToDraw->IsDrawnAfterParent() && attachableToDraw->IsDrawnNormallyByParent() && (!onlyPhysical || attachableToDraw->GetCollidesWithTerrainWhileAttached())) { attachableToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Method: ApplyAttachableForces -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Does the joint force transfer stuff for an attachable. Convencinece -// method. If this returns false, it means the attachable has been knocked -// off and has been passed to MovableMan. In either case, if false is -// returned just set the pointer to 0 and be done with it. - -bool MOSRotating::ApplyAttachableForces(Attachable *pAttachable, bool isCritical) -{ - bool intact = true; - Vector forces, impulses; - - if (pAttachable) - { - // If the attahcable is set to be deleted (probably by it having been gibbed), do so - // Note that is done regardless of whether it's attached anymore or not - if (pAttachable->IsSetToDelete()) - { - intact = false; - RemoveAttachable(pAttachable); - // If set to delete, then add to the movableman, and it'll delete it when it's safe to! - g_MovableMan.AddParticle(pAttachable); - } - // If still attached, see what forces are being transferred to this, and if they attachable can withstand them. - // If they rip the thing off, it will add itself to the Movableman, transferring ownership. - else if (pAttachable->IsAttached()) - { - pAttachable->PostTravel(); - intact = pAttachable->TransferJointForces(forces); - intact = intact && pAttachable->TransferJointImpulses(impulses); - - if (!forces.IsZero()) - AddForce(forces, pAttachable->GetOnlyLinearForces() ? Vector() : pAttachable->GetParentOffset() * m_Rotation); - if (!impulses.IsZero()) - AddImpulseForce(impulses, pAttachable->GetOnlyLinearForces() ? Vector() : pAttachable->GetParentOffset() * m_Rotation); - } - // If not attached, then we're not intact - else - intact = false; - - // If the attachable was ripped off or gibbed, handle it - if (!intact) - { - // Get and attach the wound to this if the attachable has one and it was ripped off or gibbed - if (pAttachable->GetBreakWound()) - { - AEmitter *pWound = dynamic_cast(pAttachable->GetBreakWound()->Clone()); - if (pWound) - { - pWound->SetEmitAngle((pAttachable->GetParentOffset() * m_Rotation).GetAbsRadAngle()); - if (isCritical && !IsInGroup("Brains")) - { - pWound->SetEmitCountLimit(1000000); - pWound->SetEmitDamage(0.5); - pWound->SetBurstDamage(35); - } - // IMPORTANT to pass false here so the added wound doesn't potentially gib this and cause the Attachables list to get f'd up while we're iterating through it in MOSRotating::Update! - AddWound(pWound, pAttachable->GetParentOffset(), false); - pWound = 0; - } +bool MOSRotating::TransferForcesFromAttachable(Attachable *attachable) { + RTEAssert(attachable->IsAttached(), "Tried to transfer forces from Attachable (" + attachable->GetModuleAndPresetName() + ") with no parent, this should never happen!"); + RTEAssert(attachable->IsAttachedTo(this), "Tried to transfer forces from another parent's (" + attachable->GetParent()->GetModuleAndPresetName() + ") Attachable (" + attachable->GetModuleAndPresetName() + "), this should never happen!"); + bool intact = false; + if (attachable) { + if (attachable->IsSetToDelete()) { + RemoveAttachable(attachable, true, true); + } else if (attachable->IsAttached()) { + attachable->PostTravel(); + Vector forces; + Vector impulses; + intact = attachable->TransferJointForces(forces) && attachable->TransferJointImpulses(impulses); + + if (!forces.IsZero()) { + AddForce(forces, attachable->GetOnlyLinearForces() ? Vector() : attachable->GetParentOffset() * m_Rotation); } + if (!impulses.IsZero()) { + AddImpulseForce(impulses, attachable->GetOnlyLinearForces() ? Vector() : attachable->GetParentOffset() * m_Rotation); + } + if (!intact) { RemoveAttachable(attachable, true, true); } + } else { + RemoveAttachable(attachable); } } - else - intact = false; - return intact; } diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 0c53e1533..2ccf0b28a 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -395,18 +395,36 @@ ClassInfoGetters void AddAttachable(Attachable *attachable, const Vector& parentOffsetToSet); /// - /// Detaches the Attachable corresponding to the passed in UniqueID, and removes it from the appropriate attachable lists. + /// Detaches the Attachable corresponding to the passed in UniqueID, and removes it from the appropriate Attachable lists. Does not add it to MovableMan or add break wounds. /// - /// The UniqueID of the the attachable to remove. - /// False if the attachable is invalid, otherwise true. - bool RemoveAttachable(long attachableUniqueID); + /// The UniqueID of the the Attachable to remove. + /// False if the Attachable is invalid, otherwise true. + bool RemoveAttachable(long attachableUniqueID) { return RemoveAttachable(attachableUniqueID, false, false); } /// - /// Detaches the passed in Attachable and removes it from the appropriate attachable lists. + /// Detaches the Attachable corresponding to the passed in UniqueID, and removes it from the appropriate Attachable lists. Optionally adds it to MovableMan and/or adds break wounds. /// - /// The attachable to remove. - /// False if the attachable is invalid, otherwise true. - bool RemoveAttachable(Attachable *attachable); + /// The UniqueID of the the Attachable to remove. + /// Whether or not to add the Attacahble to MovableMan once it has been removed. + /// Whether or not to add break wounds to the Attachable and this MOSRotating. + /// False if the Attachable is invalid, otherwise true. + bool RemoveAttachable(long attachableUniqueID, bool addToMovableMan, bool addBreakWounds); + + /// + /// Detaches the passed in Attachable and removes it from the appropriate Attachable lists. Does not add it to MovableMan or add break wounds. + /// + /// The Attachable to remove. + /// False if the Attachable is invalid, otherwise true. + bool RemoveAttachable(Attachable *attachable) { return RemoveAttachable(attachable, false, false); } + + /// + /// Detaches the passed in Attachable and removes it from the appropriate Attachable lists. Optionally adds it to MovableMan and/or adds break wounds. + /// + /// The Attachable to remove. + /// Whether or not to add the Attachable to MovableMan once it has been removed. + /// Whether or not to add break wounds to the Attachable and this MOSRotating. + /// False if the Attachable is invalid, otherwise true. + bool RemoveAttachable(Attachable *attachable, bool addToMovableMan, bool addBreakWounds); /// /// Either detaches or deletes all of this MOSRotating's Attachables. @@ -596,9 +614,9 @@ ClassInfoGetters /// Attaches the passed in wound AEmitter and adds it to the list of wounds, changing its parent offset to the passed in Vector. /// /// The wound AEmitter to add. - /// The vector to set as the wound AEmitter's parent offset<./param> - /// Whether to gib this MOSRotating if adding this wound raises its wound count past its gib wound limit. - void AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit = true); + /// The vector to set as the wound AEmitter's parent offset. + /// Whether to gib this MOSRotating if adding this wound raises its wound count past its gib wound limit. Defaults to true. + void AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit = true); /// /// Removes a specified number of wounds, including and returns damage caused by these wounds. @@ -790,22 +808,12 @@ ClassInfoGetters hardcodedAttachableSetter(*objectToRunSetterOn, dynamic_cast(referenceAttachable->Clone())); } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: ApplyAttachableForces -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Does the joint force transfer stuff for an attachable. Convencinece -// method. If this returns false, it means the attachable has been knocked -// off and has been passed to MovableMan OR deleted. In either case, -// if false is returned just set the pointer to 0 and be done with it. -// Arguments: A pointer to the attachable to mess with. Ownership isn't transferred, -// but if the return is false, then the object has been deleted! -// If isCritical is true, then if attachable is gibbed created break wound -// emits indefenitely to guarantee actor's death. -// Return value: Whether or not the joint held up to the forces and impulses which had -// accumulated on the Attachable during this Update(). If false, the passed -// in instance is now deleted and invalid! - - bool ApplyAttachableForces(Attachable *pAttachable, bool isCritical = false); + /// + /// Transfers forces and impulse forces from the given Attachable to this MOSRotating or removed the Attachable if needed. + /// + /// A pointer to the Attachable to apply forces from. Ownership is NOT transferred! + /// Whether or not the Attachable has been removed, in which case it'll usually be passed to MovableMan or deleted. + bool TransferForcesFromAttachable(Attachable *attachable); ////////////////////////////////////////////////////////////////////////////////////////// From cdb0f7647bdd37ded9946e18890fc9631cceb52c Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 14 Sep 2020 23:31:16 -0300 Subject: [PATCH 045/144] Made MovableMan::AddMO also add Items if the MO is a held device, changed Attachable include to HeldDevice Cleaning up a couple class Attachable lines in headers that we don't need anymore cause Attachable is included further up the chain Updated luaman to match changes, also fixed attachable setter properties so they adopt properly from lua stack and removed some definitions that shouldn't be there Got rid of atom stuff in ACDropship, it's been moved to Attachable --- Entities/ACDropShip.cpp | 8 ----- Entities/ACrab.h | 2 -- Entities/AHuman.h | 2 -- Managers/LuaMan.cpp | 70 ++++++++++++++++++++--------------------- Managers/MovableMan.cpp | 18 +++++------ 5 files changed, 44 insertions(+), 56 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 3e094d3df..39fd46494 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -744,18 +744,10 @@ void ACDropShip::Update() // Hatch door pieces if (m_pRHatch && m_pRHatch->IsAttached()) { m_pRHatch->SetRotAngle(m_Rotation.GetRadAngle() + m_HatchSwingRange.GetRadAngle() * m_HatchOpeness); - - // Update the Atoms' offsets in the parent group - Matrix atomRot(FacingAngle(m_pRHatch->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); - m_pAtomGroup->UpdateSubAtoms(m_pRHatch->GetAtomSubgroupID(), m_pRHatch->GetParentOffset() - (m_pRHatch->GetJointOffset() * atomRot), atomRot); } if (m_pLHatch && m_pLHatch->IsAttached()) { m_pLHatch->SetRotAngle(m_Rotation.GetRadAngle() - m_HatchSwingRange.GetRadAngle() * m_HatchOpeness); - - // Update the Atoms' offsets in the parent group - Matrix atomRot(FacingAngle(m_pLHatch->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); - m_pAtomGroup->UpdateSubAtoms(m_pLHatch->GetAtomSubgroupID(), m_pLHatch->GetParentOffset() - (m_pLHatch->GetJointOffset() * atomRot), atomRot); } ///////////////////////////////////////////////// diff --git a/Entities/ACrab.h b/Entities/ACrab.h index 61daccba4..f3169bb6b 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -23,10 +23,8 @@ struct BITMAP; namespace RTE { -class Attachable; class Turret; class AEmitter; -//class LimbPath; ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 054a1d1d5..208613fb3 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -24,9 +24,7 @@ struct BITMAP; namespace RTE { -class Attachable; class AEmitter; -//class LimbPath; ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index a9adc530d..21960490f 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -774,8 +774,6 @@ int LuaMan::Create() // Free function bound as member function to emulate default variables .def("GibThis", &GibThis) .def("MoveOutOfTerrain", &MOSRotating::MoveOutOfTerrain) - .def("ApplyForces", &MOSRotating::ApplyForces) - .def("ApplyImpulses", &MOSRotating::ApplyImpulses) .def("GetGibWoundLimit", (int (MOSRotating:: *)() const) &MOSRotating::GetGibWoundLimit) .def("GetGibWoundLimit", (int (MOSRotating:: *)(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const) &MOSRotating::GetGibWoundLimit) .def("GetWoundCount", (int (MOSRotating:: *)() const) &MOSRotating::GetWoundCount) @@ -800,7 +798,9 @@ int LuaMan::Create() .def("AddAttachable", (void (MOSRotating::*)(Attachable *attachableToAdd))&MOSRotating::AddAttachable, adopt(_2)) .def("AddAttachable", (void (MOSRotating::*)(Attachable *attachableToAdd, const Vector &parentOffset))&MOSRotating::AddAttachable, adopt(_2)) .def("RemoveAttachable", (bool (MOSRotating::*)(Attachable *attachableToRemove))&MOSRotating::RemoveAttachable) + .def("RemoveAttachable", (bool (MOSRotating:: *)(Attachable *attachableToRemove, bool addToMovableMan, bool addBreakWounds)) &MOSRotating::RemoveAttachable) .def("RemoveAttachable", (bool (MOSRotating::*)(long uniqueIDOfAttachableToRemove))&MOSRotating::RemoveAttachable) + .def("RemoveAttachable", (bool (MOSRotating:: *)(long uniqueIDOfAttachableToRemove, bool addToMovableMan, bool addBreakWounds)) &MOSRotating::RemoveAttachable) .def("AddEmitter", (void (MOSRotating::*)(Attachable *attachableToAdd))&MOSRotating::AddAttachable, adopt(_2)) .def("AddEmitter", (void (MOSRotating::*)(Attachable *attachableToAdd, const Vector &parentOffset))&MOSRotating::AddAttachable, adopt(_2)) .def("RemoveEmitter", (bool (MOSRotating::*)(Attachable *attachableToRemove))&MOSRotating::RemoveAttachable) @@ -819,8 +819,8 @@ int LuaMan::Create() .property("OnlyLinearForces", &Attachable::GetOnlyLinearForces, &Attachable::SetOnlyLinearForces) .def("TransferJointForces", &Attachable::TransferJointForces) .def("TransferJointImpulses", &Attachable::TransferJointImpulses) - .property("BreakWound", &Attachable::GetBreakWound, &Attachable::SetBreakWound, copy(result), adopt(_2)) - .property("ParentBreakWound", &Attachable::GetParentBreakWound, &Attachable::SetParentBreakWound, copy(result), adopt(_2)) + .property("BreakWound", &Attachable::GetBreakWound, &Attachable::SetBreakWound, detail::null_type(), adopt(_2)) + .property("ParentBreakWound", &Attachable::GetParentBreakWound, &Attachable::SetParentBreakWound, detail::null_type(), adopt(_2)) .property("InheritsHFlipped", &Attachable::InheritsHFlipped, &Attachable::SetInheritsHFlipped) .property("InheritsRotAngle", &Attachable::InheritsRotAngle, &Attachable::SetInheritsRotAngle) .property("AtomSubgroupID", &Attachable::GetAtomSubgroupID) @@ -849,7 +849,7 @@ int LuaMan::Create() .property("EmitterDamageMultiplier", &AEmitter::GetEmitterDamageMultiplier, &AEmitter::SetEmitterDamageMultiplier) .property("EmitCountLimit", &AEmitter::GetEmitCountLimit, &AEmitter::SetEmitCountLimit) .property("EmitDamage", &AEmitter::GetEmitDamage, &AEmitter::SetEmitDamage) - .property("Flash", &AEmitter::GetFlash, &AEmitter::SetFlash, copy(result), adopt(_2)) + .property("Flash", &AEmitter::GetFlash, &AEmitter::SetFlash, detail::null_type(), adopt(_2)) .property("FlashScale", &AEmitter::GetFlashScale, &AEmitter::SetFlashScale) .def("GetEmitVector", &AEmitter::GetEmitVector) .def("GetRecoilVector", &AEmitter::GetRecoilVector) @@ -985,7 +985,7 @@ int LuaMan::Create() value("CLOSING", ADoor::DoorState::CLOSING), value("STOPPED", ADoor::DoorState::STOPPED) ] - .property("Door", &ADoor::GetDoor, &ADoor::SetDoor, copy(result), adopt(_2)) + .property("Door", &ADoor::GetDoor, &ADoor::SetDoor, detail::null_type(), adopt(_2)) .def("GetDoorState", &ADoor::GetDoorState) .def("OpenDoor", &ADoor::OpenDoor) .def("CloseDoor", &ADoor::CloseDoor) @@ -997,7 +997,7 @@ int LuaMan::Create() .property("HandPos", &Arm::GetHandPos, &Arm::SetHandPos), ABSTRACTLUABINDING(Leg, Attachable) - .property("Foot", &Leg::GetFoot, &Leg::SetFoot, copy(result), adopt(_2)), + .property("Foot", &Leg::GetFoot, &Leg::SetFoot, detail::null_type(), adopt(_2)), CONCRETELUABINDING(AHuman, Actor) // These are all private/protected so they can't be bound, need to consider making them public. @@ -1069,12 +1069,12 @@ int LuaMan::Create() .def(constructor<>()) .property("Head", &AHuman::GetHead, &AHuman::SetHead) .property("Jetpack", &AHuman::GetJetpack, &AHuman::SetJetpack) - .property("FGArm", &AHuman::GetFGArm, &AHuman::SetFGArm, copy(result), adopt(_2)) - .property("BGArm", &AHuman::GetBGArm, &AHuman::SetBGArm, copy(result), adopt(_2)) - .property("FGLeg", &AHuman::GetFGLeg, &AHuman::SetFGLeg, copy(result), adopt(_2)) - .property("BGLeg", &AHuman::GetBGLeg, &AHuman::SetBGLeg, copy(result), adopt(_2)) - .property("FGFoot", &AHuman::GetFGFoot, &AHuman::SetFGFoot, copy(result), adopt(_2)) - .property("BGFoot", &AHuman::GetBGFoot, &AHuman::SetBGFoot, copy(result), adopt(_2)) + .property("FGArm", &AHuman::GetFGArm, &AHuman::SetFGArm, detail::null_type(), adopt(_2)) + .property("BGArm", &AHuman::GetBGArm, &AHuman::SetBGArm, detail::null_type(), adopt(_2)) + .property("FGLeg", &AHuman::GetFGLeg, &AHuman::SetFGLeg, detail::null_type(), adopt(_2)) + .property("BGLeg", &AHuman::GetBGLeg, &AHuman::SetBGLeg, detail::null_type(), adopt(_2)) + .property("FGFoot", &AHuman::GetFGFoot, &AHuman::SetFGFoot, detail::null_type(), adopt(_2)) + .property("BGFoot", &AHuman::GetBGFoot, &AHuman::SetBGFoot, detail::null_type(), adopt(_2)) .property("JetTimeTotal", &AHuman::GetJetTimeTotal, &AHuman::SetJetTimeTotal) .property("JetTimeLeft", &AHuman::GetJetTimeLeft, &AHuman::SetJetTimeLeft) .property("ThrowPrepTime", &AHuman::GetThrowPrepTime, &AHuman::SetThrowPrepTime) @@ -1158,12 +1158,12 @@ int LuaMan::Create() value("LANDJUMP", 5 /*ACrab::JumpState::LANDJUMP*/) ] .def(constructor<>()) - .property("Turret", &ACrab::GetTurret, &ACrab::SetTurret, copy(result), adopt(_2)) - .property("Jetpack", &ACrab::GetJetpack, &ACrab::SetJetpack, copy(result), adopt(_2)) - .property("LFGLeg", &ACrab::GetLeftFGLeg, &ACrab::SetLeftFGLeg, copy(result), adopt(_2)) - .property("LBGLeg", &ACrab::GetLeftBGLeg, &ACrab::SetLeftBGLeg, copy(result), adopt(_2)) - .property("RFGLeg", &ACrab::GetRightFGLeg, &ACrab::SetRightFGLeg, copy(result), adopt(_2)) - .property("RBGLeg", &ACrab::GetRightBGLeg, &ACrab::SetRightBGLeg, copy(result), adopt(_2)) + .property("Turret", &ACrab::GetTurret, &ACrab::SetTurret, detail::null_type(), adopt(_2)) + .property("Jetpack", &ACrab::GetJetpack, &ACrab::SetJetpack, detail::null_type(), adopt(_2)) + .property("LFGLeg", &ACrab::GetLeftFGLeg, &ACrab::SetLeftFGLeg, detail::null_type(), adopt(_2)) + .property("LBGLeg", &ACrab::GetLeftBGLeg, &ACrab::SetLeftBGLeg, detail::null_type(), adopt(_2)) + .property("RFGLeg", &ACrab::GetRightFGLeg, &ACrab::SetRightFGLeg, detail::null_type(), adopt(_2)) + .property("RBGLeg", &ACrab::GetRightBGLeg, &ACrab::SetRightBGLeg, detail::null_type(), adopt(_2)) .property("JetTimeTotal", &ACrab::GetJetTimeTotal, &ACrab::SetJetTimeTotal) .property("JetTimeLeft", &ACrab::GetJetTimeLeft) .property("EquippedItem", &ACrab::GetEquippedItem) @@ -1182,7 +1182,7 @@ int LuaMan::Create() .def("SetLimbPathSpeed", &ACrab::SetLimbPathSpeed), CONCRETELUABINDING(Turret, Attachable) - .property("MountedDevice", &Turret::GetMountedDevice, &Turret::SetMountedDevice, copy(result), adopt(_2)), + .property("MountedDevice", &Turret::GetMountedDevice, &Turret::SetMountedDevice, detail::null_type(), adopt(_2)), ABSTRACTLUABINDING(ACraft, Actor) .enum_("HatchState")[ @@ -1218,12 +1218,12 @@ int LuaMan::Create() .property("DeliveryDelayMultiplier", &ACraft::GetDeliveryDelayMultiplier), CONCRETELUABINDING(ACDropShip, ACraft) - .property("RightEngine", &ACDropShip::GetRightThruster, &ACDropShip::SetRightThruster, copy(result), adopt(_2)) - .property("LeftEngine", &ACDropShip::GetLeftThruster, &ACDropShip::SetLeftThruster, copy(result), adopt(_2)) - .property("RightThruster", &ACDropShip::GetURightThruster, &ACDropShip::SetURightThruster, copy(result), adopt(_2)) - .property("LeftThruster", &ACDropShip::GetULeftThruster, &ACDropShip::SetULeftThruster, copy(result), adopt(_2)) - .property("RightHatch", &ACDropShip::GetRightHatch, &ACDropShip::SetRightHatch, copy(result), adopt(_2)) - .property("LeftHatch", &ACDropShip::GetLeftHatch, &ACDropShip::SetLeftHatch, copy(result), adopt(_2)) + .property("RightEngine", &ACDropShip::GetRightThruster, &ACDropShip::SetRightThruster, detail::null_type(), adopt(_2)) + .property("LeftEngine", &ACDropShip::GetLeftThruster, &ACDropShip::SetLeftThruster, detail::null_type(), adopt(_2)) + .property("RightThruster", &ACDropShip::GetURightThruster, &ACDropShip::SetURightThruster, detail::null_type(), adopt(_2)) + .property("LeftThruster", &ACDropShip::GetULeftThruster, &ACDropShip::SetULeftThruster, detail::null_type(), adopt(_2)) + .property("RightHatch", &ACDropShip::GetRightHatch, &ACDropShip::SetRightHatch, detail::null_type(), adopt(_2)) + .property("LeftHatch", &ACDropShip::GetLeftHatch, &ACDropShip::SetLeftHatch, detail::null_type(), adopt(_2)) .property("MaxEngineAngle", &ACDropShip::GetMaxEngineAngle, &ACDropShip::SetMaxEngineAngle) .property("LateralControlSpeed", &ACDropShip::GetLateralControlSpeed, &ACDropShip::SetLateralControlSpeed) .property("LateralControl", &ACDropShip::GetLateralControl) @@ -1239,13 +1239,13 @@ int LuaMan::Create() value("RAISING", 3 /*ACRocket::LandingGearState::RAISING*/), value("GearStateCount", 4 /*ACRocket::LandingGearState::GearStateCount*/) ] - .property("RightLeg", &ACRocket::GetRightLeg, &ACRocket::SetRightLeg, copy(result), adopt(_2)) - .property("LeftLeg", &ACRocket::GetLeftLeg, &ACRocket::SetLeftLeg, copy(result), adopt(_2)) - .property("MainEngine", &ACRocket::GetMainThruster, &ACRocket::SetMainThruster, copy(result), adopt(_2)) - .property("LeftEngine", &ACRocket::GetLeftThruster, &ACRocket::SetLeftThruster, copy(result), adopt(_2)) - .property("RightEngine", &ACRocket::GetRightThruster, &ACRocket::SetRightThruster, copy(result), adopt(_2)) - .property("LeftThruster", &ACRocket::GetULeftThruster, &ACRocket::SetULeftThruster, copy(result), adopt(_2)) - .property("RightThruster", &ACRocket::GetURightThruster, &ACRocket::SetURightThruster, copy(result), adopt(_2)) + .property("RightLeg", &ACRocket::GetRightLeg, &ACRocket::SetRightLeg, detail::null_type(), adopt(_2)) + .property("LeftLeg", &ACRocket::GetLeftLeg, &ACRocket::SetLeftLeg, detail::null_type(), adopt(_2)) + .property("MainEngine", &ACRocket::GetMainThruster, &ACRocket::SetMainThruster, detail::null_type(), adopt(_2)) + .property("LeftEngine", &ACRocket::GetLeftThruster, &ACRocket::SetLeftThruster, detail::null_type(), adopt(_2)) + .property("RightEngine", &ACRocket::GetRightThruster, &ACRocket::SetRightThruster, detail::null_type(), adopt(_2)) + .property("LeftThruster", &ACRocket::GetULeftThruster, &ACRocket::SetULeftThruster, detail::null_type(), adopt(_2)) + .property("RightThruster", &ACRocket::GetURightThruster, &ACRocket::SetURightThruster, detail::null_type(), adopt(_2)) .property("GearState", &ACRocket::GetGearState), CONCRETELUABINDING(HeldDevice, Attachable) @@ -1299,8 +1299,8 @@ int LuaMan::Create() .property("RateOfFire", &HDFirearm::GetRateOfFire, &HDFirearm::SetRateOfFire) .property("FullAuto", &HDFirearm::IsFullAuto, &HDFirearm::SetFullAuto) .property("RoundInMagCount", &HDFirearm::GetRoundInMagCount) - .property("Magazine", &HDFirearm::GetMagazine, &HDFirearm::SetMagazine, copy(result), adopt(_2)) - .property("Flash", &HDFirearm::GetFlash, &HDFirearm::SetFlash, copy(result), adopt(_2)) + .property("Magazine", &HDFirearm::GetMagazine, &HDFirearm::SetMagazine, detail::null_type(), adopt(_2)) + .property("Flash", &HDFirearm::GetFlash, &HDFirearm::SetFlash, detail::null_type(), adopt(_2)) .property("ActivationDelay", &HDFirearm::GetActivationDelay, &HDFirearm::SetActivationDelay) .property("DeactivationDelay", &HDFirearm::GetDeactivationDelay, &HDFirearm::SetDeactivationDelay) .property("ReloadTime", &HDFirearm::GetReloadTime, &HDFirearm::SetReloadTime) diff --git a/Managers/MovableMan.cpp b/Managers/MovableMan.cpp index 475b19680..964f07dc5 100644 --- a/Managers/MovableMan.cpp +++ b/Managers/MovableMan.cpp @@ -17,7 +17,7 @@ #include "PresetMan.h" #include "AHuman.h" #include "MOPixel.h" -#include "Attachable.h" +#include "HeldDevice.h" #include "SLTerrain.h" #include "Controller.h" #include "AtomGroup.h" @@ -786,21 +786,21 @@ Actor * MovableMan::GetUnassignedBrain(int team) const // best way to add it is. E.g. if it's an Actor, it will be added as such. // Ownership IS transferred! -bool MovableMan::AddMO(MovableObject *pMOToAdd) -{ - if (!pMOToAdd) +bool MovableMan::AddMO(MovableObject *pMOToAdd) { + if (!pMOToAdd) { return false; + } pMOToAdd->SetAsAddedToMovableMan(); // Find out what kind it is and apply accordingly - if (Actor *pActor = dynamic_cast(pMOToAdd)) - { + if (Actor *pActor = dynamic_cast(pMOToAdd)) { AddActor(pActor); return true; - } - else - { + } else if (HeldDevice *pHeldDevice = dynamic_cast(pMOToAdd)) { + AddItem(pHeldDevice); + return true; + } else { AddParticle(pMOToAdd); return true; } From 92c40225279535cc3964d241bcb4aa3aa60f08e2 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 16 Sep 2020 03:47:48 -0300 Subject: [PATCH 046/144] Changed hardcoded attachable handling to put lambda functions in a map on MOSR so that they can later be used to unset hardcoded attachable pointers when needed Changed the already copied attachables unique IDs unordered_set to an unordered_map HardcodedAttachableUniqueIDsAndSetters and used this to store hardcoded attachable setters Changed the process of MOSR::Create(reference) so once hardcoded attachables are copied over, they sit in the map instead of the reference's versions, making it useable for unsetting hardcoded attachable pointers Cleaned up a bit of attachable removal so it's more correct about deleting the attachable being removed or adding it to MovableMan, and also so it unsets hardcoded attachable pointers where relevant. Cleaned up unused extra methods in Turret that RemoveAttachable can handle nicely, made it better align with everything else and also did a bit of cleanup in MOSR Fixed a mistake in ACDropship with hatches, fixed a mistake in ACRocket with main thruster inheriting rotation, fixed a mistake in Emitter which was screwing up flash Updated objects with hardcoded attachables accordingly. Also, by necessity, made it so objects read in will add and remove hardcoded attachables to/from their attachable list, with all the handling that comes along with that. --- Entities/ACDropShip.cpp | 102 ++++++++++++++++++---------- Entities/ACRocket.cpp | 141 +++++++++++++++++++++++++-------------- Entities/ACrab.cpp | 120 +++++++++++++++++++++------------ Entities/ADoor.cpp | 10 ++- Entities/AEmitter.cpp | 25 ++++--- Entities/AHuman.cpp | 110 +++++++++++++++++++----------- Entities/Arm.cpp | 55 ++++++++------- Entities/HDFirearm.cpp | 43 +++++++----- Entities/Leg.cpp | 12 ++-- Entities/MOSRotating.cpp | 30 ++++++--- Entities/MOSRotating.h | 15 +---- Entities/Turret.cpp | 53 +++++---------- Entities/Turret.h | 16 +---- 13 files changed, 435 insertions(+), 297 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 39fd46494..b1e39c1cd 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -71,12 +71,12 @@ int ACDropShip::Create() // Description: Creates a ACDropShip to be identical to another, by deep copy. int ACDropShip::Create(const ACDropShip &reference) { - if (reference.m_pRThruster) { CloneHardcodedAttachable(reference.m_pRThruster, this, static_cast>(&ACDropShip::SetRightThruster)); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLThruster, this, static_cast>(&ACDropShip::SetLeftThruster)); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pURThruster, this, static_cast>(&ACDropShip::SetURightThruster)); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pULThruster, this, static_cast>(&ACDropShip::SetULeftThruster)); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pRHatch, this, static_cast>(&ACDropShip::SetRightHatch)); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLHatch, this, static_cast>(&ACDropShip::SetLeftHatch)); } + if (reference.m_pRThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightThruster(attachable); }}); } + if (reference.m_pLThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftThruster(attachable); }}); } + if (reference.m_pURThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pURThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetURightThruster(attachable); }}); } + if (reference.m_pULThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pULThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetULeftThruster(attachable); }}); } + if (reference.m_pRHatch) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightHatch(attachable); }}); } + if (reference.m_pLHatch) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftHatch(attachable); }}); } ACraft::Create(reference); @@ -106,37 +106,43 @@ int ACDropShip::Create(const ACDropShip &reference) { int ACDropShip::ReadProperty(std::string propName, Reader &reader) { if (propName == "RThruster") { - delete m_pRThruster; + RemoveAttachable(m_pRThruster); m_pRThruster = new AEmitter; reader >> m_pRThruster; + AddAttachable(m_pRThruster); if (!m_pRThruster->GetDamageMultiplierSetInINI()) { m_pRThruster->SetDamageMultiplier(1.0F); } m_pRThruster->SetInheritsRotAngle(false); } else if (propName == "LThruster") { - delete m_pLThruster; + RemoveAttachable(m_pLThruster); m_pLThruster = new AEmitter; reader >> m_pLThruster; + AddAttachable(m_pLThruster); if (!m_pLThruster->GetDamageMultiplierSetInINI()) { m_pLThruster->SetDamageMultiplier(1.0F); } m_pLThruster->SetInheritsRotAngle(false); } else if (propName == "URThruster") { - delete m_pURThruster; + RemoveAttachable(m_pURThruster); m_pURThruster = new AEmitter; reader >> m_pURThruster; + AddAttachable(m_pURThruster); if (!m_pURThruster->GetDamageMultiplierSetInINI()) { m_pURThruster->SetDamageMultiplier(1.0F); } } else if (propName == "ULThruster") { - delete m_pULThruster; + RemoveAttachable(m_pULThruster); m_pULThruster = new AEmitter; reader >> m_pULThruster; + AddAttachable(m_pULThruster); if (!m_pULThruster->GetDamageMultiplierSetInINI()) { m_pULThruster->SetDamageMultiplier(1.0F); } } else if (propName == "RHatchDoor") { - delete m_pRHatch; + RemoveAttachable(m_pRHatch); m_pRHatch = new Attachable; reader >> m_pRHatch; + AddAttachable(m_pRHatch); if (!m_pRHatch->GetDamageMultiplierSetInINI()) { m_pRHatch->SetDamageMultiplier(1.0F); } m_pRHatch->SetInheritsRotAngle(false); } else if (propName == "LHatchDoor") { - delete m_pLHatch; + RemoveAttachable(m_pLHatch); m_pLHatch = new Attachable; reader >> m_pLHatch; + AddAttachable(m_pLHatch); if (!m_pLHatch->GetDamageMultiplierSetInINI()) { m_pLHatch->SetDamageMultiplier(1.0F); } m_pLHatch->SetInheritsRotAngle(false); } else if (propName == "HatchDoorSwingRange") { @@ -824,51 +830,74 @@ void ACDropShip::Update() ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACDropShip::SetRightThruster(Attachable *newThruster) { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - RemoveAttachable(m_pRThruster); - m_pRThruster = castedNewThruster; - AddAttachable(castedNewThruster); + if (newThruster == nullptr) { + if (m_pRThruster && m_pRThruster->IsAttachedTo(this)) { RemoveAttachable(m_pRThruster); } + m_pRThruster = nullptr; + } else { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pRThruster); + m_pRThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACDropShip::SetLeftThruster(Attachable *newThruster) { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - RemoveAttachable(m_pLThruster); - m_pLThruster = castedNewThruster; - AddAttachable(castedNewThruster); + if (newThruster == nullptr) { + if (m_pLThruster && m_pLThruster->IsAttachedTo(this)) { RemoveAttachable(m_pLThruster); } + m_pLThruster = nullptr; + } else { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pLThruster); + m_pLThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACDropShip::SetURightThruster(Attachable *newThruster) { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - RemoveAttachable(m_pURThruster); - m_pURThruster = castedNewThruster; - AddAttachable(castedNewThruster); + if (newThruster == nullptr) { + if (m_pURThruster && m_pURThruster->IsAttachedTo(this)) { RemoveAttachable(m_pURThruster); } + m_pURThruster = nullptr; + } else { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pURThruster); + m_pURThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACDropShip::SetULeftThruster(Attachable *newThruster) { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - RemoveAttachable(m_pULThruster); - m_pULThruster = castedNewThruster; - AddAttachable(castedNewThruster); + if (newThruster == nullptr) { + if (m_pULThruster && m_pULThruster->IsAttachedTo(this)) { RemoveAttachable(m_pULThruster); } + m_pULThruster = nullptr; + } else { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pULThruster); + m_pULThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACDropShip::SetLeftHatch(Attachable *newHatch) { - if (newHatch) { + if (newHatch == nullptr) { + if (m_pLHatch && m_pLHatch->IsAttachedTo(this)) { RemoveAttachable(m_pLHatch); } + m_pLHatch = nullptr; + } else { RemoveAttachable(m_pLHatch); m_pLHatch = newHatch; AddAttachable(newHatch); @@ -878,8 +907,11 @@ void ACDropShip::SetLeftHatch(Attachable *newHatch) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACDropShip::SetRightHatch(Attachable *newHatch) { - if (newHatch) { - RemoveAttachable(m_pLHatch); + if (newHatch == nullptr) { + if (m_pRHatch && m_pRHatch->IsAttachedTo(this)) { RemoveAttachable(m_pRHatch); } + m_pRHatch = nullptr; + } else { + RemoveAttachable(m_pRHatch); m_pRHatch = newHatch; AddAttachable(newHatch); } diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 2ea1ec3ac..62f15dac1 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -92,13 +92,13 @@ int ACRocket::Create() // Description: Creates a ACRocket to be identical to another, by deep copy. int ACRocket::Create(const ACRocket &reference) { - if (reference.m_pRLeg) { CloneHardcodedAttachable(reference.m_pRLeg, this, static_cast>(&ACRocket::SetRightLeg)); } - if (reference.m_pLLeg) { CloneHardcodedAttachable(reference.m_pLLeg, this, static_cast>(&ACRocket::SetLeftLeg)); } - if (reference.m_pMThruster) { CloneHardcodedAttachable(reference.m_pMThruster, this, static_cast>(&ACRocket::SetMainThruster)); } - if (reference.m_pRThruster) { CloneHardcodedAttachable(reference.m_pRThruster, this, static_cast>(&ACRocket::SetRightThruster)); } - if (reference.m_pLThruster) { CloneHardcodedAttachable(reference.m_pLThruster, this, static_cast>(&ACRocket::SetLeftThruster)); } - if (reference.m_pURThruster) { CloneHardcodedAttachable(reference.m_pURThruster, this, static_cast>(&ACRocket::SetURightThruster)); } - if (reference.m_pULThruster) { CloneHardcodedAttachable(reference.m_pULThruster, this, static_cast>(&ACRocket::SetULeftThruster)); } + if (reference.m_pRLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightLeg(attachable); }}); } + if (reference.m_pLLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftLeg(attachable); }}); } + if (reference.m_pMThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pMThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMainThruster(attachable); }}); } + if (reference.m_pRThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightThruster(attachable); }}); } + if (reference.m_pLThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftThruster(attachable); }}); } + if (reference.m_pURThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pURThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetURightThruster(attachable); }}); } + if (reference.m_pULThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pULThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetULeftThruster(attachable); }}); } ACraft::Create(reference); @@ -139,14 +139,16 @@ int ACRocket::Create(const ACRocket &reference) { int ACRocket::ReadProperty(std::string propName, Reader &reader) { if (propName == "RLeg") { - delete m_pRLeg; + RemoveAttachable(m_pRLeg); m_pRLeg = new Leg; reader >> m_pRLeg; + AddAttachable(m_pRLeg); if (!m_pRLeg->GetDamageMultiplierSetInINI()) { m_pRLeg->SetDamageMultiplier(1.0F); } } else if (propName == "LLeg") { - delete m_pLLeg; + RemoveAttachable(m_pLLeg); m_pLLeg = new Leg; reader >> m_pLLeg; + AddAttachable(m_pLLeg); m_pLLeg->SetInheritsHFlipped(2); if (!m_pLLeg->GetDamageMultiplierSetInINI()) { m_pLLeg->SetDamageMultiplier(1.0F); } } else if (propName == "RFootGroup") { @@ -160,32 +162,38 @@ int ACRocket::ReadProperty(std::string propName, Reader &reader) { reader >> m_pLFootGroup; m_pLFootGroup->SetOwner(this); } else if (propName == "MThruster"){ - delete m_pMThruster; + RemoveAttachable(m_pMThruster); m_pMThruster = new AEmitter; reader >> m_pMThruster; + AddAttachable(m_pMThruster); if (!m_pMThruster->GetDamageMultiplierSetInINI()) { m_pMThruster->SetDamageMultiplier(1.0F); } + m_pMThruster->SetInheritsRotAngle(false); } else if (propName == "RThruster") { - delete m_pRThruster; + RemoveAttachable(m_pRThruster); m_pRThruster = new AEmitter; reader >> m_pRThruster; + AddAttachable(m_pRThruster); if (!m_pRThruster->GetDamageMultiplierSetInINI()) { m_pRThruster->SetDamageMultiplier(1.0F); } m_pRThruster->SetInheritsRotAngle(false); } else if (propName == "LThruster") { - delete m_pLThruster; + RemoveAttachable(m_pLThruster); m_pLThruster = new AEmitter; reader >> m_pLThruster; + AddAttachable(m_pLThruster); if (!m_pLThruster->GetDamageMultiplierSetInINI()) { m_pLThruster->SetDamageMultiplier(1.0F); } m_pLThruster->SetInheritsRotAngle(false); } else if (propName == "URThruster") { - delete m_pURThruster; + RemoveAttachable(m_pURThruster); m_pURThruster = new AEmitter; reader >> m_pURThruster; + AddAttachable(m_pURThruster); if (!m_pURThruster->GetDamageMultiplierSetInINI()) { m_pURThruster->SetDamageMultiplier(1.0F); } m_pURThruster->SetInheritsRotAngle(false); } else if (propName == "ULThruster") { - delete m_pULThruster; + RemoveAttachable(m_pULThruster); m_pULThruster = new AEmitter; reader >> m_pULThruster; + AddAttachable(m_pULThruster); if (!m_pULThruster->GetDamageMultiplierSetInINI()) { m_pULThruster->SetDamageMultiplier(1.0F); } m_pULThruster->SetInheritsRotAngle(false); } else if (propName == "RaisedGearLimbPath") { @@ -905,77 +913,112 @@ void ACRocket::Update() ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACRocket::SetRightLeg(Attachable *newLeg) { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - RemoveAttachable(m_pRLeg); - m_pRLeg = castedNewLeg; - AddAttachable(castedNewLeg); + if (newLeg == nullptr) { + if (m_pRLeg && m_pRLeg->IsAttachedTo(this)) { RemoveAttachable(m_pRLeg); } + m_pRLeg = nullptr; + } else { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pRLeg); + m_pRLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACRocket::SetLeftLeg(Attachable *newLeg) { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - RemoveAttachable(m_pLLeg); - m_pLLeg = castedNewLeg; - AddAttachable(castedNewLeg); + if (newLeg == nullptr) { + if (m_pLLeg && m_pLLeg->IsAttachedTo(this)) { RemoveAttachable(m_pLLeg); } + m_pLLeg = nullptr; + } else { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pLLeg); + m_pLLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACRocket::SetMainThruster(Attachable *newThruster) { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - RemoveAttachable(m_pMThruster); - m_pMThruster = castedNewThruster; - AddAttachable(castedNewThruster); + if (newThruster == nullptr) { + if (m_pMThruster && m_pMThruster->IsAttachedTo(this)) { RemoveAttachable(m_pMThruster); } + m_pMThruster = nullptr; + } else { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pMThruster); + m_pMThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACRocket::SetRightThruster(Attachable *newThruster) { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - RemoveAttachable(m_pRThruster); - m_pRThruster = castedNewThruster; - AddAttachable(castedNewThruster); + if (newThruster == nullptr) { + if (m_pRThruster && m_pRThruster->IsAttachedTo(this)) { RemoveAttachable(m_pRThruster); } + m_pRThruster = nullptr; + } else { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pRThruster); + m_pRThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACRocket::SetLeftThruster(Attachable *newThruster) { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - RemoveAttachable(m_pLThruster); - m_pLThruster = castedNewThruster; - AddAttachable(castedNewThruster); + if (newThruster == nullptr) { + if (m_pLThruster && m_pLThruster->IsAttachedTo(this)) { RemoveAttachable(m_pLThruster); } + m_pLThruster = nullptr; + } else { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pLThruster); + m_pLThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACRocket::SetURightThruster(Attachable *newThruster) { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - RemoveAttachable(m_pURThruster); - m_pURThruster = castedNewThruster; - AddAttachable(castedNewThruster); + if (newThruster == nullptr) { + if (m_pURThruster && m_pURThruster->IsAttachedTo(this)) { RemoveAttachable(m_pURThruster); } + m_pURThruster = nullptr; + } else { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pURThruster); + m_pURThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACRocket::SetULeftThruster(Attachable *newThruster) { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - RemoveAttachable(m_pULThruster); - m_pULThruster = castedNewThruster; - AddAttachable(castedNewThruster); + if (newThruster == nullptr) { + if (m_pULThruster && m_pULThruster->IsAttachedTo(this)) { RemoveAttachable(m_pULThruster); } + m_pULThruster = nullptr; + } else { + AEmitter *castedNewThruster = dynamic_cast(newThruster); + if (castedNewThruster) { + RemoveAttachable(m_pULThruster); + m_pULThruster = castedNewThruster; + AddAttachable(castedNewThruster); + } } } diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 9148cc379..bb5fe037e 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -162,12 +162,12 @@ int ACrab::Create(BITMAP *pSprite, // Description: Creates a ACrab to be identical to another, by deep copy. int ACrab::Create(const ACrab &reference) { - if (reference.m_pTurret) { CloneHardcodedAttachable(reference.m_pTurret, this, static_cast>(&ACrab::SetTurret)); } - if (reference.m_pJetpack) { CloneHardcodedAttachable(reference.m_pJetpack, this, static_cast>(&ACrab::SetJetpack)); } - if (reference.m_pLFGLeg) { CloneHardcodedAttachable(reference.m_pLFGLeg, this, static_cast>(&ACrab::SetLeftFGLeg)); } - if (reference.m_pRFGLeg) { CloneHardcodedAttachable(reference.m_pRFGLeg, this, static_cast>(&ACrab::SetRightFGLeg)); } - if (reference.m_pLBGLeg) { CloneHardcodedAttachable(reference.m_pLBGLeg, this, static_cast>(&ACrab::SetLeftBGLeg)); } - if (reference.m_pRBGLeg) { CloneHardcodedAttachable(reference.m_pRBGLeg, this, static_cast>(&ACrab::SetRightBGLeg)); } + if (reference.m_pTurret) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pTurret->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetTurret(attachable); }}); } + if (reference.m_pJetpack) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetJetpack(attachable); }}); } + if (reference.m_pLFGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLFGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftFGLeg(attachable); }}); } + if (reference.m_pRFGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRFGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightFGLeg(attachable); }}); } + if (reference.m_pLBGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLBGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftBGLeg(attachable); }}); } + if (reference.m_pRBGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRBGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightBGLeg(attachable); }}); } Actor::Create(reference); @@ -223,40 +223,46 @@ int ACrab::Create(const ACrab &reference) { int ACrab::ReadProperty(std::string propName, Reader &reader) { if (propName == "Turret") { - delete m_pTurret; + RemoveAttachable(m_pTurret); m_pTurret = new Turret; reader >> m_pTurret; + AddAttachable(m_pTurret); if (!m_pTurret->GetDamageMultiplierSetInINI()) { m_pTurret->SetDamageMultiplier(5.0F); } } else if (propName == "Jetpack") { - delete m_pJetpack; + RemoveAttachable(m_pJetpack); m_pJetpack = new AEmitter; reader >> m_pJetpack; + AddAttachable(m_pJetpack); if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } m_pJetpack->SetOnlyLinearForces(true); } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; m_JetTimeTotal *= 1000; } else if (propName == "LFGLeg") { - delete m_pLFGLeg; + RemoveAttachable(m_pLFGLeg); m_pLFGLeg = new Leg; reader >> m_pLFGLeg; + AddAttachable(m_pLFGLeg); if (!m_pLFGLeg->GetDamageMultiplierSetInINI()) { m_pLFGLeg->SetDamageMultiplier(1.0F); } m_pLFGLeg->SetInheritsHFlipped(2); } else if (propName == "LBGLeg") { - delete m_pLBGLeg; + RemoveAttachable(m_pLBGLeg); m_pLBGLeg = new Leg; reader >> m_pLBGLeg; + AddAttachable(m_pLBGLeg); if (!m_pLBGLeg->GetDamageMultiplierSetInINI()) { m_pLBGLeg->SetDamageMultiplier(1.0F); } m_pLBGLeg->SetInheritsHFlipped(2); } else if (propName == "RFGLeg") { - delete m_pRFGLeg; + RemoveAttachable(m_pRFGLeg); m_pRFGLeg = new Leg; reader >> m_pRFGLeg; + AddAttachable(m_pRFGLeg); if (!m_pRFGLeg->GetDamageMultiplierSetInINI()) { m_pRFGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "RBGLeg") { - delete m_pRBGLeg; + RemoveAttachable(m_pRBGLeg); m_pRBGLeg = new Leg; reader >> m_pRBGLeg; + AddAttachable(m_pRBGLeg); if (!m_pRBGLeg->GetDamageMultiplierSetInINI()) { m_pRBGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "LFootGroup") { delete m_pLFGFootGroup; @@ -473,66 +479,96 @@ Attachable *ACrab::GetTurret() const { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACrab::SetTurret(Attachable *newTurret) { - Turret *castedNewTurret = dynamic_cast(newTurret); - if (castedNewTurret) { - RemoveAttachable(m_pTurret); - m_pTurret = castedNewTurret; - AddAttachable(castedNewTurret); + if (newTurret == nullptr) { + if (m_pTurret && m_pTurret->IsAttachedTo(this)) { RemoveAttachable(m_pTurret); } + m_pTurret = nullptr; + } else { + Turret *castedNewTurret = dynamic_cast(newTurret); + if (castedNewTurret) { + RemoveAttachable(m_pTurret); + m_pTurret = castedNewTurret; + AddAttachable(castedNewTurret); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACrab::SetJetpack(Attachable *newJetpack) { - AEmitter *castedNewJetpack = dynamic_cast(newJetpack); - if (castedNewJetpack) { - RemoveAttachable(m_pJetpack); - m_pJetpack = castedNewJetpack; - AddAttachable(castedNewJetpack); + if (newJetpack == nullptr) { + if (m_pJetpack && m_pJetpack->IsAttachedTo(this)) { RemoveAttachable(m_pJetpack); } + m_pJetpack = nullptr; + } else { + AEmitter *castedNewJetpack = dynamic_cast(newJetpack); + if (castedNewJetpack) { + RemoveAttachable(m_pJetpack); + m_pJetpack = castedNewJetpack; + AddAttachable(castedNewJetpack); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACrab::SetLeftFGLeg(Attachable *newLeg) { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - RemoveAttachable(m_pLFGLeg); - m_pLFGLeg = castedNewLeg; - AddAttachable(castedNewLeg); + if (newLeg == nullptr) { + if (m_pLFGLeg && m_pLFGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pLFGLeg); } + m_pLFGLeg = nullptr; + } else { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pLFGLeg); + m_pLFGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACrab::SetLeftBGLeg(Attachable *newLeg) { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - RemoveAttachable(m_pLBGLeg); - m_pLBGLeg = castedNewLeg; - AddAttachable(castedNewLeg); + if (newLeg == nullptr) { + if (m_pLBGLeg && m_pLBGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pLBGLeg); } + m_pLBGLeg = nullptr; + } else { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pLBGLeg); + m_pLBGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACrab::SetRightFGLeg(Attachable *newLeg) { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - RemoveAttachable(m_pRFGLeg); - m_pRFGLeg = castedNewLeg; - AddAttachable(castedNewLeg); + if (newLeg == nullptr) { + if (m_pRFGLeg && m_pRFGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pRFGLeg); } + m_pRFGLeg = nullptr; + } else { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pRFGLeg); + m_pRFGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ACrab::SetRightBGLeg(Attachable *newLeg) { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - RemoveAttachable(m_pRBGLeg); - m_pRBGLeg = castedNewLeg; - AddAttachable(castedNewLeg); + if (newLeg == nullptr) { + if (m_pRBGLeg && m_pRBGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pRBGLeg); } + m_pRBGLeg = nullptr; + } else { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pRBGLeg); + m_pRBGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } } } diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index 5d763c7a0..a58893199 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -45,7 +45,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int ADoor::Create(const ADoor &reference) { - if (reference.m_Door) { CloneHardcodedAttachable(reference.m_Door, this, static_cast>(&ADoor::SetDoor)); } + if (reference.m_Door) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_Door->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetDoor(attachable); }}); } //TODO this was setting door parent offset to my closed offset, which is super weird. Test that doors are still cool. Old code was AddAttachable(m_Door, m_ClosedOffset, true); Actor::Create(reference); @@ -83,9 +83,10 @@ namespace RTE { int ADoor::ReadProperty(std::string propName, Reader &reader) { if (propName == "Door") { - delete m_Door; + RemoveAttachable(m_Door); m_Door = new Attachable; reader >> m_Door; + AddAttachable(m_Door); m_Door->SetInheritsRotAngle(false); m_DoorMaterialID = m_Door->GetMaterial()->GetIndex(); } else if (propName == "OpenOffset") { @@ -201,7 +202,10 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ADoor::SetDoor(Attachable *newDoor) { - if (newDoor) { + if (newDoor == nullptr) { + if (m_Door && m_Door->IsAttachedTo(this)) { RemoveAttachable(m_Door); } + m_Door = nullptr; + } else { RemoveAttachable(m_Door); m_Door = newDoor; AddAttachable(newDoor); diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index ec0061ad4..9dc399fcf 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -69,7 +69,7 @@ void AEmitter::Clear() // Description: Creates a AEmitter to be identical to another, by deep copy. int AEmitter::Create(const AEmitter &reference) { - if (reference.m_pFlash) { CloneHardcodedAttachable(reference.m_pFlash, this, static_cast>(&AEmitter::SetFlash)); } + if (reference.m_pFlash) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFlash(attachable); }}); } Attachable::Create(reference); for (list::const_iterator itr = reference.m_EmissionList.begin(); itr != reference.m_EmissionList.end(); ++itr) { @@ -166,9 +166,11 @@ int AEmitter::ReadProperty(std::string propName, Reader &reader) { } else if (propName == "EmissionDamage") { reader >> m_EmitDamage; } else if (propName == "Flash") { - const Entity *pObj = g_PresetMan.GetEntityPreset(reader); - if (pObj) { - m_pFlash = dynamic_cast(pObj->Clone()); + RemoveAttachable(m_pFlash); + const Entity *flashEntity = g_PresetMan.GetEntityPreset(reader); + if (flashEntity) { + m_pFlash = dynamic_cast(flashEntity->Clone()); + AddAttachable(m_pFlash); m_pFlash->SetDrawnNormallyByParent(false); m_pFlash->SetInheritsRotAngle(false); m_pFlash->SetDeleteWhenRemovedFromParent(true); @@ -367,7 +369,10 @@ float AEmitter::EstimateImpulse(bool burst) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AEmitter::SetFlash(Attachable *newFlash) { - if (newFlash) { + if (newFlash == nullptr) { + if (m_pFlash && m_pFlash->IsAttachedTo(this)) { RemoveAttachable(m_pFlash); } + m_pFlash = nullptr; + } else { RemoveAttachable(m_pFlash); m_pFlash = newFlash; AddAttachable(newFlash); @@ -395,12 +400,10 @@ void AEmitter::Update() // Update and show flash if there is one if (m_pFlash && (!m_FlashOnlyOnBurst || m_BurstTriggered)) { m_pFlash->SetParentOffset(m_EmissionOffset); - if (m_EmitEnabled && !m_WasEmitting) { - // Don't set the flipping for the flash because that is wasting resources when drawing, just handle the flipping of the rotation here. - m_pFlash->SetRotAngle(m_HFlipped ? c_PI + m_Rotation.GetRadAngle() - m_EmitAngle.GetRadAngle() : m_Rotation.GetRadAngle() + m_EmitAngle.GetRadAngle()); - m_pFlash->SetScale(m_FlashScale); - m_pFlash->SetNextFrame(); - } + // Don't set the flipping for the flash because that is wasting resources when drawing, just handle the flipping of the rotation here. + m_pFlash->SetRotAngle(m_HFlipped ? c_PI + m_Rotation.GetRadAngle() - m_EmitAngle.GetRadAngle() : m_Rotation.GetRadAngle() + m_EmitAngle.GetRadAngle()); + m_pFlash->SetScale(m_FlashScale); + m_pFlash->SetNextFrame(); } Attachable::Update(); diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 57df99512..fd228469f 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -138,12 +138,12 @@ int AHuman::Create() // Description: Creates a AHuman to be identical to another, by deep copy. int AHuman::Create(const AHuman &reference) { - if (reference.m_pHead) { CloneHardcodedAttachable(reference.m_pHead, this, static_cast>(&AHuman::SetHead)); } - if (reference.m_pJetpack) { CloneHardcodedAttachable(reference.m_pJetpack, this, static_cast>(&AHuman::SetJetpack)); } - if (reference.m_pFGArm) { CloneHardcodedAttachable(reference.m_pFGArm, this, static_cast>(&AHuman::SetFGArm)); } - if (reference.m_pBGArm) { CloneHardcodedAttachable(reference.m_pBGArm, this, static_cast>(&AHuman::SetBGArm)); } - if (reference.m_pFGLeg) { CloneHardcodedAttachable(reference.m_pFGLeg, this, static_cast>(&AHuman::SetFGLeg)); } - if (reference.m_pBGLeg) { CloneHardcodedAttachable(reference.m_pBGLeg, this, static_cast>(&AHuman::SetBGLeg)); } + if (reference.m_pHead) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pHead->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetHead(attachable); }}); } + if (reference.m_pJetpack) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetJetpack(attachable); }}); } + if (reference.m_pFGArm) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pFGArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFGArm(attachable); }}); } + if (reference.m_pBGArm) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pBGArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetBGArm(attachable); }}); } + if (reference.m_pFGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pFGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFGLeg(attachable); }}); } + if (reference.m_pBGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pBGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetBGLeg(attachable); }}); } Actor::Create(reference); m_ThrowPrepTime = reference.m_ThrowPrepTime; @@ -199,15 +199,17 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { if (propName == "ThrowPrepTime") { reader >> m_ThrowPrepTime; } else if (propName == "Head") { - delete m_pHead; + RemoveAttachable(m_pHead); m_pHead = new Attachable; reader >> m_pHead; + AddAttachable(m_pHead); if (!m_pHead->GetDamageMultiplierSetInINI()) { m_pHead->SetDamageMultiplier(5.0F); } m_pHead->SetInheritsRotAngle(false); } else if (propName == "Jetpack") { - delete m_pJetpack; + RemoveAttachable(m_pJetpack); m_pJetpack = new AEmitter; reader >> m_pJetpack; + AddAttachable(m_pJetpack); if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } m_pJetpack->SetOnlyLinearForces(true); } else if (propName == "JumpTime") { @@ -215,26 +217,30 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { // Convert to ms m_JetTimeTotal *= 1000; } else if (propName == "FGArm") { - delete m_pFGArm; + RemoveAttachable(m_pFGArm); m_pFGArm = new Arm; reader >> m_pFGArm; + AddAttachable(m_pFGArm); if (!m_pFGArm->GetDamageMultiplierSetInINI()) { m_pFGArm->SetDamageMultiplier(1.0F); } m_pFGArm->SetDrawnAfterParent(true); } else if (propName == "BGArm") { - delete m_pBGArm; + RemoveAttachable(m_pBGArm); m_pBGArm = new Arm; reader >> m_pBGArm; + AddAttachable(m_pBGArm); if (!m_pBGArm->GetDamageMultiplierSetInINI()) { m_pBGArm->SetDamageMultiplier(1.0F); } m_pBGArm->SetDrawnAfterParent(false); } else if (propName == "FGLeg") { - delete m_pFGLeg; + RemoveAttachable(m_pFGLeg); m_pFGLeg = new Leg; reader >> m_pFGLeg; + AddAttachable(m_pFGLeg); if (!m_pFGLeg->GetDamageMultiplierSetInINI()) { m_pFGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "BGLeg") { - delete m_pBGLeg; + RemoveAttachable(m_pBGLeg); m_pBGLeg = new Leg; reader >> m_pBGLeg; + AddAttachable(m_pBGLeg); if (!m_pBGLeg->GetDamageMultiplierSetInINI()) { m_pBGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "HandGroup") { delete m_pFGHandGroup; @@ -451,7 +457,10 @@ Vector AHuman::GetEyePos() const ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AHuman::SetHead(Attachable *newHead) { - if (newHead) { + if (newHead == nullptr) { + if (m_pHead && m_pHead->IsAttachedTo(this)) { RemoveAttachable(m_pHead); } + m_pHead = nullptr; + } else { RemoveAttachable(m_pHead); m_pHead = newHead; AddAttachable(newHead); @@ -461,55 +470,80 @@ void AHuman::SetHead(Attachable *newHead) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AHuman::SetJetpack(Attachable *newJetpack) { - AEmitter *castedNewJetpack = dynamic_cast(newJetpack); - if (castedNewJetpack) { - RemoveAttachable(m_pJetpack); - m_pJetpack = castedNewJetpack; - AddAttachable(castedNewJetpack); + if (newJetpack == nullptr) { + if (m_pJetpack && m_pJetpack->IsAttachedTo(this)) { RemoveAttachable(m_pJetpack); } + m_pJetpack = nullptr; + } else { + AEmitter *castedNewJetpack = dynamic_cast(newJetpack); + if (castedNewJetpack) { + RemoveAttachable(m_pJetpack); + m_pJetpack = castedNewJetpack; + AddAttachable(castedNewJetpack); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AHuman::SetFGArm(Attachable *newArm) { - Arm *castedNewArm = dynamic_cast(newArm); - if (castedNewArm) { - RemoveAttachable(m_pFGArm); - m_pFGArm = castedNewArm; - AddAttachable(castedNewArm); + if (newArm == nullptr) { + if (m_pFGArm && m_pFGArm->IsAttachedTo(this)) { RemoveAttachable(m_pFGArm); } + m_pFGArm = nullptr; + } else { + Arm *castedNewArm = dynamic_cast(newArm); + if (castedNewArm) { + RemoveAttachable(m_pFGArm); + m_pFGArm = castedNewArm; + AddAttachable(castedNewArm); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AHuman::SetBGArm(Attachable *newArm) { - Arm *castedNewArm = dynamic_cast(newArm); - if (castedNewArm) { - RemoveAttachable(m_pBGArm); - m_pBGArm = castedNewArm; - AddAttachable(castedNewArm); + if (newArm == nullptr) { + if (m_pBGArm && m_pBGArm->IsAttachedTo(this)) { RemoveAttachable(m_pBGArm); } + m_pBGArm = nullptr; + } else { + Arm *castedNewArm = dynamic_cast(newArm); + if (castedNewArm) { + RemoveAttachable(m_pBGArm); + m_pBGArm = castedNewArm; + AddAttachable(castedNewArm); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AHuman::SetFGLeg(Attachable *newLeg) { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - RemoveAttachable(m_pFGLeg); - m_pFGLeg = castedNewLeg; - AddAttachable(castedNewLeg); + if (newLeg == nullptr) { + if (m_pFGLeg && m_pFGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pFGLeg); } + m_pFGLeg = nullptr; + } else { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pFGLeg); + m_pFGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void AHuman::SetBGLeg(Attachable *newLeg) { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - RemoveAttachable(m_pBGLeg); - m_pBGLeg = castedNewLeg; - AddAttachable(castedNewLeg); + if (newLeg == nullptr) { + if (m_pBGLeg && m_pBGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pBGLeg); } + m_pBGLeg = nullptr; + } else { + Leg *castedNewLeg = dynamic_cast(newLeg); + if (castedNewLeg) { + RemoveAttachable(m_pBGLeg); + m_pBGLeg = castedNewLeg; + AddAttachable(castedNewLeg); + } } } diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index e60ca3205..cbb334720 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -66,7 +66,7 @@ int Arm::Create() { // Description: Creates a Arm to be identical to another, by deep copy. int Arm::Create(const Arm &reference) { - if (reference.m_pHeldMO) { CloneHardcodedAttachable(dynamic_cast(reference.m_pHeldMO), this, static_cast>((void (Arm:: *)(Attachable *newHeldMO)) &Arm::SetHeldMO)); } + if (reference.m_pHeldMO) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pHeldMO->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetHeldMO(attachable); }}); } Attachable::Create(reference); m_HandFile = reference.m_HandFile; @@ -93,12 +93,12 @@ int Arm::Create(const Arm &reference) { int Arm::ReadProperty(std::string propName, Reader &reader) { if (propName == "HeldDevice") { - const Entity *pEntity; - pEntity = g_PresetMan.GetEntityPreset(reader); - if (pEntity) { - m_pHeldMO = dynamic_cast(pEntity->Clone()); + RemoveAttachable(dynamic_cast(m_pHeldMO)); + const Entity *heldDeviceEntity = g_PresetMan.GetEntityPreset(reader); + if (heldDeviceEntity) { + m_pHeldMO = dynamic_cast(heldDeviceEntity->Clone()); + AddAttachable(dynamic_cast(m_pHeldMO)); } - pEntity = 0; } else if (propName == "Hand") { reader >> m_HandFile; m_pHand = m_HandFile.GetAsBitmap(); @@ -188,27 +188,32 @@ HeldDevice * Arm::GetHeldDevice() const // one. Ownership IS transferred. The currently held MovableObject // (if there is one) will be dropped and become a detached MovableObject, -void Arm::SetHeldMO(MovableObject *newHeldMO) -{ -// TODO: NEED TO REWORK THIS TO WORK WITH THROWNDEVICES!! - if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && dynamic_cast(m_pHeldMO)->IsAttachedTo(this)) { - HeldDevice *pHeldDev = dynamic_cast(m_pHeldMO); - if (pHeldDev->IsAttached()) { dynamic_cast(pHeldDev->GetParent())->RemoveAttachable(pHeldDev); } -// TODO: Refine throwing force to dropped device here?") - pHeldDev->SetVel(Vector(10 * PosRand(), -15 * PosRand())); - pHeldDev->SetAngularVel(-10 * PosRand()); - g_MovableMan.AddItem(pHeldDev); - m_pHeldMO = pHeldDev = 0; - } +void Arm::SetHeldMO(MovableObject *newHeldMO) { + if (newHeldMO == nullptr) { + Attachable *heldMOAsAttachable = dynamic_cast(m_pHeldMO); + if (m_pHeldMO && heldMOAsAttachable && heldMOAsAttachable->IsAttachedTo(this)) { RemoveAttachable(heldMOAsAttachable); } + m_pHeldMO = nullptr; + } else { + //TODO All this needs cleaning up, it should work just like all other hardcoded attachable setters and rely on RemoveAttachable to add it to MovableMan, etc. + if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && dynamic_cast(m_pHeldMO)->IsAttachedTo(this)) { + HeldDevice *pHeldDev = dynamic_cast(m_pHeldMO); + if (pHeldDev->IsAttached()) { dynamic_cast(pHeldDev->GetParent())->RemoveAttachable(pHeldDev); } + // TODO: Refine throwing force to dropped device here?") + pHeldDev->SetVel(Vector(10 * PosRand(), -15 * PosRand())); + pHeldDev->SetAngularVel(-10 * PosRand()); + g_MovableMan.AddItem(pHeldDev); + m_pHeldMO = pHeldDev = 0; + } - if (newHeldMO && (newHeldMO->IsHeldDevice() || newHeldMO->IsThrownDevice())) { - Attachable *pNewDev = dynamic_cast(newHeldMO); - if (pNewDev->IsAttached()) { dynamic_cast(pNewDev->GetParent())->RemoveAttachable(pNewDev); } - AddAttachable(pNewDev); - pNewDev->SetTeam(m_Team); - pNewDev = 0; + if (newHeldMO && (newHeldMO->IsHeldDevice() || newHeldMO->IsThrownDevice())) { + Attachable *pNewDev = dynamic_cast(newHeldMO); + if (pNewDev->IsAttached()) { dynamic_cast(pNewDev->GetParent())->RemoveAttachable(pNewDev); } + AddAttachable(pNewDev); + pNewDev->SetTeam(m_Team); + pNewDev = 0; + } + m_pHeldMO = newHeldMO; } - m_pHeldMO = newHeldMO; } diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index 8d1ccd2c5..371d53ffa 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -96,8 +96,8 @@ int HDFirearm::Create() // Description: Creates a HDFirearm to be identical to another, by deep copy. int HDFirearm::Create(const HDFirearm &reference) { - if (reference.m_pMagazine) { CloneHardcodedAttachable(reference.m_pMagazine, this, static_cast>(&HDFirearm::SetMagazine)); } - if (reference.m_pFlash) { CloneHardcodedAttachable(reference.m_pFlash, this, static_cast>(&HDFirearm::SetFlash)); } + if (reference.m_pMagazine) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pMagazine->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMagazine(attachable); }}); } + if (reference.m_pFlash) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFlash(attachable); }}); } HeldDevice::Create(reference); m_pMagazineReference = reference.m_pMagazineReference; @@ -142,17 +142,18 @@ int HDFirearm::Create(const HDFirearm &reference) { int HDFirearm::ReadProperty(std::string propName, Reader &reader) { if (propName == "Magazine") { - const Entity *pObj = g_PresetMan.GetEntityPreset(reader); - if (pObj) { - m_pMagazineReference = dynamic_cast(pObj); - delete m_pMagazine; - m_pMagazine = dynamic_cast(m_pMagazineReference->Clone()); + RemoveAttachable(m_pMagazine); + const Entity *magazineEntity = g_PresetMan.GetEntityPreset(reader); + if (magazineEntity) { + m_pMagazine = dynamic_cast(magazineEntity->Clone()); + AddAttachable(m_pMagazine); } } else if (propName == "Flash") { - const Entity *pObj = g_PresetMan.GetEntityPreset(reader); - if (pObj) { - delete m_pFlash; - m_pFlash = dynamic_cast(pObj->Clone()); + RemoveAttachable(m_pFlash); + const Entity *flashEntity = g_PresetMan.GetEntityPreset(reader); + if (flashEntity) { + m_pFlash = dynamic_cast(flashEntity->Clone()); + AddAttachable(m_pFlash); m_pFlash->SetDrawnNormallyByParent(false); m_pFlash->SetDeleteWhenRemovedFromParent(true); } @@ -296,18 +297,26 @@ void HDFirearm::Destroy(bool notInherited) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void HDFirearm::SetMagazine(Attachable *newMagazine) { - Magazine *castedNewMagazine= dynamic_cast(newMagazine); - if (castedNewMagazine) { - RemoveAttachable(m_pMagazine); - m_pMagazine = castedNewMagazine; - AddAttachable(castedNewMagazine); + if (newMagazine == nullptr) { + if (m_pMagazine && m_pMagazine->IsAttachedTo(this)) { RemoveAttachable(m_pMagazine); } + m_pMagazine = nullptr; + } else { + Magazine *castedNewMagazine = dynamic_cast(newMagazine); + if (castedNewMagazine) { + RemoveAttachable(m_pMagazine); + m_pMagazine = castedNewMagazine; + AddAttachable(castedNewMagazine); + } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void HDFirearm::SetFlash(Attachable *newFlash) { - if (newFlash) { + if (newFlash == nullptr) { + if (m_pFlash && m_pFlash->IsAttachedTo(this)) { RemoveAttachable(m_pFlash); } + m_pFlash = nullptr; + } else { RemoveAttachable(m_pFlash); m_pFlash = newFlash; AddAttachable(newFlash); diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index ed90f5a6d..90a8809d0 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -49,7 +49,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int Leg::Create(const Leg &reference) { - if (reference.m_Foot) { CloneHardcodedAttachable(reference.m_Foot, this, static_cast>(&Leg::SetFoot)); } + if (reference.m_Foot) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_Foot->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFoot(attachable); }}); } Attachable::Create(reference); m_ContractedOffset = reference.m_ContractedOffset; @@ -74,11 +74,12 @@ namespace RTE { int Leg::ReadProperty(std::string propName, Reader &reader) { if (propName == "Foot") { - delete m_Foot; + RemoveAttachable(m_Foot); const Entity *footEntity = g_PresetMan.GetEntityPreset(reader); if (footEntity) { m_Foot = dynamic_cast(footEntity->Clone()); - m_Foot->SetInheritsRotAngle(false); // Foot RotAngles are handled specially by Leg. + AddAttachable(m_Foot); + m_Foot->SetInheritsRotAngle(false); } } else if (propName == "ContractedOffset") { reader >> m_ContractedOffset; @@ -123,7 +124,10 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Leg::SetFoot(Attachable *newFoot) { - if (newFoot) { + if (newFoot == nullptr) { + if (m_Foot && m_Foot->IsAttachedTo(this)) { RemoveAttachable(m_Foot); } + m_Foot = nullptr; + } else { RemoveAttachable(m_Foot); m_Foot = newFoot; AddAttachable(newFoot); diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 0565ef46a..f16b65178 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -62,7 +62,7 @@ void MOSRotating::Clear() m_RecoilOffset.Reset(); m_Wounds.clear(); m_Attachables.clear(); - m_AlreadyCopiedAttachableUniqueIDs.clear(); + m_HardcodedAttachableUniqueIDsAndSetters.clear(); m_Gibs.clear(); m_GibImpulseLimit = 0; m_GibWoundLimit = 0; @@ -242,9 +242,18 @@ int MOSRotating::Create(const MOSRotating &reference) } // Attachable copies - for (const Attachable *attachable : reference.m_Attachables) { - if (m_AlreadyCopiedAttachableUniqueIDs.find(attachable->GetUniqueID()) == m_AlreadyCopiedAttachableUniqueIDs.end()) { - AddAttachable(dynamic_cast(attachable->Clone())); + Attachable *newAttachable; + for (const Attachable *referenceAttachable : reference.m_Attachables) { + newAttachable = dynamic_cast(referenceAttachable->Clone()); + newAttachable->m_Parent = nullptr; + + std::unordered_map>::iterator hardcodedAttachableMapEntry = m_HardcodedAttachableUniqueIDsAndSetters.find(referenceAttachable->GetUniqueID()); + if (hardcodedAttachableMapEntry != m_HardcodedAttachableUniqueIDsAndSetters.end()) { + (*hardcodedAttachableMapEntry).second(this, newAttachable); + m_HardcodedAttachableUniqueIDsAndSetters.insert({newAttachable->GetUniqueID(), hardcodedAttachableMapEntry->second}); + m_HardcodedAttachableUniqueIDsAndSetters.erase(hardcodedAttachableMapEntry); + } else { + AddAttachable(newAttachable); } } @@ -1619,7 +1628,7 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, if (!attachable) { return false; } - RTEAssert(!attachable->IsAttached() || attachable->IsAttachedTo(this), "Tried to transfer forces from another parent's (" + attachable->GetParent()->GetModuleAndPresetName() + ") Attachable (" + attachable->GetModuleAndPresetName() + "), this should never happen!"); + RTEAssert(!attachable->IsAttached() || attachable->IsAttachedTo(this), "Tried to remove attachable that was attached to another parent (" + (attachable->GetParent() ? attachable->GetParent()->GetModuleAndPresetName() : "ERROR") + ") Attachable (" + attachable->GetModuleAndPresetName() + "), this should never happen!"); if (!attachable->IsAttached()) { int a = 0; } @@ -1627,8 +1636,8 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, if (m_Attachables.size() > 0) { m_Attachables.remove(attachable); } attachable->SetParent(nullptr); - if (attachable->GetDeleteWhenRemovedFromParent()) { attachable->SetToDelete(); } - if (addToMovableMan || attachable->IsSetToDelete()) { g_MovableMan.AddMO(attachable); } + std::unordered_map>::iterator hardcodedAttachableMapEntry = m_HardcodedAttachableUniqueIDsAndSetters.find(attachable->GetUniqueID()); + if (hardcodedAttachableMapEntry != m_HardcodedAttachableUniqueIDsAndSetters.end()) { hardcodedAttachableMapEntry->second(this, nullptr); } if (addBreakWounds) { if (!m_ToDelete && attachable->GetParentBreakWound()) { @@ -1648,6 +1657,11 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, } } } + if (!addToMovableMan || attachable->GetDeleteWhenRemovedFromParent()) { + delete attachable; + } else if (addToMovableMan || attachable->IsSetToDelete()) { + g_MovableMan.AddMO(attachable); + } return true; } @@ -1919,7 +1933,7 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, // Draw all the attached attachables for (const Attachable *attachableToDraw : m_Attachables) { - if (attachableToDraw->IsDrawnAfterParent() && attachableToDraw->IsDrawnNormallyByParent() && (!onlyPhysical || attachableToDraw->GetCollidesWithTerrainWhileAttached())) { + if (attachableToDraw->IsDrawnAfterParent() && attachableToDraw->IsDrawnNormallyByParent()) { attachableToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } } diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 2ccf0b28a..0617cc4d9 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -795,19 +795,6 @@ ClassInfoGetters protected: - /// - /// To be called during Create(reference): - /// Clones a hardcoded attachable, setting the appropriate member variable, and calling AddAttachable. - /// Also adds the reference attachable's UniqueID to the std::unordered_set of already copied attachable unique IDs so it doesn't get duplicated. - /// - /// The relevant hardcoded attachable belonging to the reference object being cloned. - /// A pointer to the object which the setter should be run on. Normally would be this, sent from the child class so types work properly. - /// A std::function containing the setter for the given hardcoded attachable. Aside from setting the relevant member variable, this setter should call AddAttachable. - template void CloneHardcodedAttachable(Attachable *referenceAttachable, T objectToRunSetterOn, U hardcodedAttachableSetter) { - m_AlreadyCopiedAttachableUniqueIDs.insert(referenceAttachable->GetUniqueID()); - hardcodedAttachableSetter(*objectToRunSetterOn, dynamic_cast(referenceAttachable->Clone())); - } - /// /// Transfers forces and impulse forces from the given Attachable to this MOSRotating or removed the Attachable if needed. /// @@ -860,7 +847,7 @@ ClassInfoGetters std::list m_Wounds; // The list of Attachables currently attached and Owned by this. std::list m_Attachables; - std::unordered_set m_AlreadyCopiedAttachableUniqueIDs; //> m_HardcodedAttachableUniqueIDsAndSetters; // m_Gibs; // The amount of impulse force required to gib this, in kg * (m/s). 0 means no limit diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index 2cb1f400f..b5bb770db 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -15,7 +15,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int Turret::Create(const Turret &reference) { - if (reference.m_MountedDevice && reference.m_MountedDevice->IsDevice()) { CloneHardcodedAttachable(dynamic_cast(reference.m_MountedDevice), this, static_cast>((void (Turret:: *)(Attachable * newMountedMO)) & Turret::SetMountedDevice)); } + if (reference.m_MountedDevice) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_MountedDevice->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMountedDevice(attachable); }}); } Attachable::Create(reference); m_MountedDeviceRotOffset = reference.m_MountedDeviceRotOffset; @@ -27,12 +27,13 @@ namespace RTE { int Turret::ReadProperty(std::string propName, Reader &reader) { if (propName == "MountedDevice") { - const Entity *entity = g_PresetMan.GetEntityPreset(reader); - if (entity) { - m_MountedDevice = dynamic_cast(entity->Clone()); + RemoveAttachable(m_MountedDevice); + const Entity *mountedDeviceEntity = g_PresetMan.GetEntityPreset(reader); + if (mountedDeviceEntity) { + m_MountedDevice = dynamic_cast(mountedDeviceEntity->Clone()); + AddAttachable(m_MountedDevice); m_MountedDevice->SetInheritsRotAngle(false); } - entity = 0; } else { return Attachable::ReadProperty(propName, reader); } @@ -53,36 +54,18 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Turret::SetMountedDevice(HeldDevice *newMountedDevice) { - DropMountedDevice(); - - if (newMountedDevice) { - if (newMountedDevice->IsAttached()) { dynamic_cast(newMountedDevice->GetParent())->RemoveAttachable(newMountedDevice); } - g_MovableMan.RemoveMO(newMountedDevice); - AddAttachable(newMountedDevice); - } - m_MountedDevice = newMountedDevice; - } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - HeldDevice *Turret::ReleaseMountedDevice() { - HeldDevice *previouslyMountedDevice = m_MountedDevice; - if (m_MountedDevice) { RemoveAttachable(m_MountedDevice); } - m_MountedDevice = 0; - return previouslyMountedDevice; - } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - HeldDevice *Turret::DropMountedDevice() { - HeldDevice *previouslyMountedDevice = ReleaseMountedDevice(); - - if (previouslyMountedDevice) { - g_MovableMan.AddItem(previouslyMountedDevice); + void Turret::SetMountedDevice(Attachable *newMountedDevice) { + if (newMountedDevice == nullptr) { + if (m_MountedDevice && m_MountedDevice->IsAttachedTo(this)) { RemoveAttachable(m_MountedDevice); } + m_MountedDevice = nullptr; + } else { + HeldDevice *castedNewMountedDevice = dynamic_cast(newMountedDevice); + if (castedNewMountedDevice) { + RemoveAttachable(m_MountedDevice); + m_MountedDevice = castedNewMountedDevice; + AddAttachable(castedNewMountedDevice); + } } - - return previouslyMountedDevice; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -100,7 +83,5 @@ namespace RTE { } Attachable::Update(); - //TODO consider expanding the stuff used in clone create to allow for clearing hardcoded attachables members (might be as simple as updating unique id entries and calling things accordingly) - if (std::find(m_Attachables.begin(), m_Attachables.end(), m_MountedDevice) == m_Attachables.end()) { m_MountedDevice = nullptr; } } } \ No newline at end of file diff --git a/Entities/Turret.h b/Entities/Turret.h index 7963fedd8..8124954b3 100644 --- a/Entities/Turret.h +++ b/Entities/Turret.h @@ -68,7 +68,7 @@ namespace RTE { /// The currently mounted HeldDevice (if there is one) will be dropped and added to MovableMan. /// /// The new HeldDevice to use. - void SetMountedDevice(HeldDevice *newMountedDevice); + void SetMountedDevice(Attachable *newMountedDevice); /// /// Indicates whether a ThrownDevice is mounted or not. @@ -83,20 +83,6 @@ namespace RTE { void SetMountedDeviceRotOffset(float newOffsetAngle) { m_MountedDeviceRotOffset = newOffsetAngle; } #pragma endregion -#pragma region Mounted Device Management - /// - /// Makes this Turret unmount its mounted HeldDevice. Ownership IS transferred! - /// - /// A pointer to the previously mounted HeldDevice. Ownership IS transferred! - HeldDevice * ReleaseMountedDevice(); - - /// - /// Makes this Turret unmount its mounted HeldDevice and give it to MovableMan. Ownership IS transferred to MovableMan. - /// - /// A pointer to the previously mounted HeldDevice. Ownership IS transferred to MovableMan. - HeldDevice *DropMountedDevice(); -#pragma endregion - #pragma region Override Methods /// /// Updates this MovableObject. Supposed to be done every frame. From 970dbcd66bf5692a376ce444a8068e5a4dcb3fbb Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 16 Sep 2020 19:09:11 -0300 Subject: [PATCH 047/144] Added Attachable InheritedRotAngleOffset property, added INI setters (one for degrees and one for rads) for it and lua getter and setter for it Added RTETools DegreesToRadians and RadiansToDegrees methods (to support this InheritedRotAngleOffset stuff) Made hardcoded attachables that can use InheritedRotAngleOffset use it instead of their parents having to handle it Cleaned up some leftover hardcoded attachable atom updating in AHuman and ACDropship Made AHuman bgleg not be drawn after parent so its foot draws before the fgleg's foot Killed off undesirable lua functions TransferJointForces and TransferJointImpulses, and renamed lua property bindings for ACrab legs to spell out Left and Right --- Entities/ACDropShip.cpp | 8 -------- Entities/ACRocket.cpp | 30 +++++------------------------- Entities/AHuman.cpp | 5 +---- Entities/Attachable.cpp | 10 +++++++++- Entities/Attachable.h | 13 +++++++++++++ Managers/LuaMan.cpp | 11 +++++------ System/RTETools.h | 14 ++++++++++++++ 7 files changed, 47 insertions(+), 44 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index b1e39c1cd..28e260e75 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -708,18 +708,10 @@ void ACDropShip::Update() if (m_pRThruster && m_pRThruster->IsAttached()) { m_pRThruster->SetRotAngle(engineRot.GetRadAngle()); - - // Update the Atoms' offsets in the parent group - Matrix atomRot(FacingAngle(m_pRThruster->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); - m_pAtomGroup->UpdateSubAtoms(m_pRThruster->GetAtomSubgroupID(), m_pRThruster->GetParentOffset() - (m_pRThruster->GetJointOffset() * atomRot), atomRot); } if (m_pLThruster && m_pLThruster->IsAttached()) { m_pLThruster->SetRotAngle(engineRot.GetRadAngle()); - - // Update the Atoms' offsets in the parent group - Matrix atomRot(FacingAngle(m_pLThruster->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); - m_pAtomGroup->UpdateSubAtoms(m_pLThruster->GetAtomSubgroupID(), m_pLThruster->GetParentOffset() - (m_pLThruster->GetJointOffset() * atomRot), atomRot); } // Auto balancing with the up thrusters diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 62f15dac1..c10bd4e5d 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -167,35 +167,35 @@ int ACRocket::ReadProperty(std::string propName, Reader &reader) { reader >> m_pMThruster; AddAttachable(m_pMThruster); if (!m_pMThruster->GetDamageMultiplierSetInINI()) { m_pMThruster->SetDamageMultiplier(1.0F); } - m_pMThruster->SetInheritsRotAngle(false); + m_pMThruster->SetInheritedRotAngleOffset(-c_HalfPI); } else if (propName == "RThruster") { RemoveAttachable(m_pRThruster); m_pRThruster = new AEmitter; reader >> m_pRThruster; AddAttachable(m_pRThruster); if (!m_pRThruster->GetDamageMultiplierSetInINI()) { m_pRThruster->SetDamageMultiplier(1.0F); } - m_pRThruster->SetInheritsRotAngle(false); + m_pRThruster->SetInheritedRotAngleOffset(c_EighthPI); } else if (propName == "LThruster") { RemoveAttachable(m_pLThruster); m_pLThruster = new AEmitter; reader >> m_pLThruster; AddAttachable(m_pLThruster); if (!m_pLThruster->GetDamageMultiplierSetInINI()) { m_pLThruster->SetDamageMultiplier(1.0F); } - m_pLThruster->SetInheritsRotAngle(false); + m_pLThruster->SetInheritedRotAngleOffset(c_PI - c_EighthPI); } else if (propName == "URThruster") { RemoveAttachable(m_pURThruster); m_pURThruster = new AEmitter; reader >> m_pURThruster; AddAttachable(m_pURThruster); if (!m_pURThruster->GetDamageMultiplierSetInINI()) { m_pURThruster->SetDamageMultiplier(1.0F); } - m_pURThruster->SetInheritsRotAngle(false); + m_pURThruster->SetInheritedRotAngleOffset(c_HalfPI - c_EighthPI); } else if (propName == "ULThruster") { RemoveAttachable(m_pULThruster); m_pULThruster = new AEmitter; reader >> m_pULThruster; AddAttachable(m_pULThruster); if (!m_pULThruster->GetDamageMultiplierSetInINI()) { m_pULThruster->SetDamageMultiplier(1.0F); } - m_pULThruster->SetInheritsRotAngle(false); + m_pULThruster->SetInheritedRotAngleOffset(c_HalfPI + c_EighthPI); } else if (propName == "RaisedGearLimbPath") { reader >> m_Paths[RIGHT][RAISED]; } else if (propName == "LoweredGearLimbPath") { @@ -794,26 +794,6 @@ void ACRocket::Update() m_pLLeg->SetTargetPosition(m_pLFootGroup->GetLimbPos(!m_HFlipped)); } - if (m_pMThruster) { - m_pMThruster->SetRotAngle(m_Rotation.GetRadAngle() - c_HalfPI); - } - - if (m_pRThruster) { - m_pRThruster->SetRotAngle(m_Rotation.GetRadAngle() + c_EighthPI); - } - - if (m_pLThruster) { - m_pLThruster->SetRotAngle(m_Rotation.GetRadAngle() + c_PI - c_EighthPI); - } - - if (m_pURThruster) { - m_pURThruster->SetRotAngle(m_Rotation.GetRadAngle() + c_HalfPI - c_QuarterPI / 2); - } - - if (m_pULThruster) { - m_pULThruster->SetRotAngle(m_Rotation.GetRadAngle() + c_HalfPI + c_QuarterPI / 2); - } - ///////////////////////////////////////////////// // Update MovableObject, adds on the forces etc, updated viewpoint ACraft::Update(); diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index fd228469f..5182d5c32 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -242,6 +242,7 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { reader >> m_pBGLeg; AddAttachable(m_pBGLeg); if (!m_pBGLeg->GetDamageMultiplierSetInINI()) { m_pBGLeg->SetDamageMultiplier(1.0F); } + m_pBGLeg->SetDrawnAfterParent(false); } else if (propName == "HandGroup") { delete m_pFGHandGroup; delete m_pBGHandGroup; @@ -4037,10 +4038,6 @@ void AHuman::Update() } // Now actually rotate by the amount calculated above m_pHead->SetRotAngle(m_pHead->GetRotAngle() + toRotate); - - // Update the Atoms' offsets in the parent group - Matrix headAtomRot(FacingAngle(m_pHead->GetRotMatrix().GetRadAngle()) - FacingAngle(m_Rotation.GetRadAngle())); - m_pAtomGroup->UpdateSubAtoms(m_pHead->GetAtomSubgroupID(), m_pHead->GetParentOffset() - (m_pHead->GetJointOffset() * headAtomRot), headAtomRot); } if (m_pFGLeg && m_pFGLeg->IsAttached()) { diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 77ea81201..379a1b2bc 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -31,6 +31,7 @@ namespace RTE { m_InheritsHFlipped = 1; m_InheritsRotAngle = true; + m_InheritedRotAngleOffset = 0; m_AtomSubgroupID = -1; m_CollidesWithTerrainWhileAttached = true; @@ -70,6 +71,7 @@ namespace RTE { m_InheritsHFlipped = reference.m_InheritsHFlipped; m_InheritsRotAngle = reference.m_InheritsRotAngle; + m_InheritedRotAngleOffset = reference.m_InheritedRotAngleOffset; m_CollidesWithTerrainWhileAttached = reference.m_CollidesWithTerrainWhileAttached; @@ -101,6 +103,10 @@ namespace RTE { if (m_InheritsHFlipped != 0 && m_InheritsHFlipped != 1) { m_InheritsHFlipped = 2; } } else if (propName == "InheritsRotAngle") { reader >> m_InheritsRotAngle; + } else if (propName == "InheritedRotAngleRadOffset" || propName == "InheritedRotAngleOffset") { + reader >> m_InheritedRotAngleOffset; + } else if (propName == "InheritedRotAngleDegOffset") { + m_InheritedRotAngleOffset = DegreesToRadians(std::stof(reader.ReadPropValue())); } else if (propName == "CollidesWithTerrainWhenAttached") { reader >> m_CollidesWithTerrainWhileAttached; } else { @@ -138,6 +144,8 @@ namespace RTE { writer << ((m_InheritsHFlipped == 0 || m_InheritsHFlipped == 1) ? m_InheritsHFlipped : 2); writer.NewProperty("InheritsRotAngle"); writer << m_InheritsRotAngle; + writer.NewProperty("InheritedRotAngleOffset"); + writer << m_InheritedRotAngleOffset; writer.NewProperty("CollidesWithTerrainWhileAttached"); writer << m_CollidesWithTerrainWhileAttached; @@ -282,7 +290,7 @@ namespace RTE { m_Vel = m_Parent->GetVel(); m_Team = m_Parent->GetTeam(); if (InheritsHFlipped() != 0) { m_HFlipped = m_InheritsHFlipped == 1 ? m_Parent->IsHFlipped() : !m_Parent->IsHFlipped(); } - if (InheritsRotAngle()) { SetRotAngle(m_Parent->GetRotAngle()); } + if (InheritsRotAngle()) { SetRotAngle(m_Parent->GetRotAngle() + m_InheritedRotAngleOffset); } if (m_CollidesWithTerrainWhileAttached) { float facingAngle = (m_HFlipped ? c_PI : 0) + GetRotAngle() * static_cast(GetFlipFactor()); diff --git a/Entities/Attachable.h b/Entities/Attachable.h index adc159797..522067798 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -286,6 +286,18 @@ namespace RTE { /// /// Whether or not to inherit its parent's RotAngle. void SetInheritsRotAngle(bool inheritsRotAngle) { m_InheritsRotAngle = inheritsRotAngle; } + + /// + /// Gets the offset of this Attachable's rotation angle from its parent. Only actually applied if the Attachable is set to inherit its parent's rotation angle. + /// + /// This Attachable's inherited rotation angle offset. + bool GetInheritedRotAngleOffset() const { return m_InheritedRotAngleOffset; } + + /// + /// Sets the offset of this Attachable's rotation angle from its parent. Only actually applied if the Attachable is set to inherit its parent's rotation angle. + /// + /// Thee new rotation angle offset for this Attachable. + void SetInheritedRotAngleOffset(float inheritedRotAngleOffset) { m_InheritedRotAngleOffset = inheritedRotAngleOffset; } #pragma endregion #pragma region Collision Management @@ -369,6 +381,7 @@ namespace RTE { int m_InheritsHFlipped; //!< Whether this Attachable should inherit its parent's HFlipped. Defaults to true. bool m_InheritsRotAngle; //!< Whether this Attachable should inherit its parent's RotAngle. Defaults to true. + float m_InheritedRotAngleOffset; //!< The offset by which this Attachable should be rotated when it's set to inherit its parent's rotation angle. Defaults to 0. long int m_AtomSubgroupID; //!< The Atom IDs this' atoms will have when attached and added to a parent's AtomGroup. bool m_CollidesWithTerrainWhileAttached; //!< Whether this attachable currently has terrain collisions enabled while it's attached to a parent. diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 21960490f..58705c479 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -817,12 +817,11 @@ int LuaMan::Create() .property("JointStiffness", &Attachable::GetJointStiffness, &Attachable::SetJointStiffness) .property("JointOffset", &Attachable::GetJointOffset, &Attachable::SetJointOffset) .property("OnlyLinearForces", &Attachable::GetOnlyLinearForces, &Attachable::SetOnlyLinearForces) - .def("TransferJointForces", &Attachable::TransferJointForces) - .def("TransferJointImpulses", &Attachable::TransferJointImpulses) .property("BreakWound", &Attachable::GetBreakWound, &Attachable::SetBreakWound, detail::null_type(), adopt(_2)) .property("ParentBreakWound", &Attachable::GetParentBreakWound, &Attachable::SetParentBreakWound, detail::null_type(), adopt(_2)) .property("InheritsHFlipped", &Attachable::InheritsHFlipped, &Attachable::SetInheritsHFlipped) .property("InheritsRotAngle", &Attachable::InheritsRotAngle, &Attachable::SetInheritsRotAngle) + .property("InheritedRotAngleOffset", &Attachable::GetInheritedRotAngleOffset, &Attachable::SetInheritedRotAngleOffset) .property("AtomSubgroupID", &Attachable::GetAtomSubgroupID) .property("CollidesWithTerrainWhileAttached", &Attachable::GetCollidesWithTerrainWhileAttached, &Attachable::SetCollidesWithTerrainWhileAttached), @@ -1160,10 +1159,10 @@ int LuaMan::Create() .def(constructor<>()) .property("Turret", &ACrab::GetTurret, &ACrab::SetTurret, detail::null_type(), adopt(_2)) .property("Jetpack", &ACrab::GetJetpack, &ACrab::SetJetpack, detail::null_type(), adopt(_2)) - .property("LFGLeg", &ACrab::GetLeftFGLeg, &ACrab::SetLeftFGLeg, detail::null_type(), adopt(_2)) - .property("LBGLeg", &ACrab::GetLeftBGLeg, &ACrab::SetLeftBGLeg, detail::null_type(), adopt(_2)) - .property("RFGLeg", &ACrab::GetRightFGLeg, &ACrab::SetRightFGLeg, detail::null_type(), adopt(_2)) - .property("RBGLeg", &ACrab::GetRightBGLeg, &ACrab::SetRightBGLeg, detail::null_type(), adopt(_2)) + .property("LeftFGLeg", &ACrab::GetLeftFGLeg, &ACrab::SetLeftFGLeg, detail::null_type(), adopt(_2)) + .property("LeftBGLeg", &ACrab::GetLeftBGLeg, &ACrab::SetLeftBGLeg, detail::null_type(), adopt(_2)) + .property("RightFGLeg", &ACrab::GetRightFGLeg, &ACrab::SetRightFGLeg, detail::null_type(), adopt(_2)) + .property("RightBGLeg", &ACrab::GetRightBGLeg, &ACrab::SetRightBGLeg, detail::null_type(), adopt(_2)) .property("JetTimeTotal", &ACrab::GetJetTimeTotal, &ACrab::SetJetTimeTotal) .property("JetTimeLeft", &ACrab::GetJetTimeLeft) .property("EquippedItem", &ACrab::GetEquippedItem) diff --git a/System/RTETools.h b/System/RTETools.h index 7de590cc0..b9358ec92 100644 --- a/System/RTETools.h +++ b/System/RTETools.h @@ -162,6 +162,20 @@ namespace RTE { /// The angle value to correct. In degrees. /// A float with the represented angle as full rotations being 256. float GetAllegroAngle(float angleDegrees); + + /// + /// Returns the given angle converted from degrees to radians. + /// + /// The angle in degrees to be converted. + /// The converted angle in radians. + float DegreesToRadians(float angleInDegrees) { return angleInDegrees / c_PI * 180.0F; } + + /// + /// Returns the given angle converted from radians to degrees. + /// + /// The angle in radians to be converted. + /// The converted angle in degrees. + float RadiansToDegrees(float angleInRadians) { return angleInRadians / 180.0F * c_PI; } #pragma endregion #pragma region Misc From ec2f526ec1af925796fad8de8d00347eb8a97539 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 16 Sep 2020 21:15:04 -0300 Subject: [PATCH 048/144] Renamed OnlyLinearForces to ApplyTransferredForcesAtOffset and reversed its meaning, so it more clearly describes what the heck it does. Added INI handling for this and updated things accordingly in classes that used it. Tweaked AEmitter force handling with this, we'll see how it goes --- Entities/ACrab.cpp | 2 +- Entities/AEmitter.cpp | 7 ++----- Entities/AHuman.cpp | 2 +- Entities/Attachable.cpp | 12 +++++++----- Entities/Attachable.h | 28 ++++++++++++++-------------- Entities/MOSRotating.cpp | 4 ++-- Managers/LuaMan.cpp | 2 +- 7 files changed, 28 insertions(+), 29 deletions(-) diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index bb5fe037e..857e20737 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -234,7 +234,7 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) reader >> m_pJetpack; AddAttachable(m_pJetpack); if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } - m_pJetpack->SetOnlyLinearForces(true); + m_pJetpack->SetApplyTransferredForcesAtOffset(false); } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; m_JetTimeTotal *= 1000; diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index 9dc399fcf..f256cd765 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -543,11 +543,8 @@ void AEmitter::Update() } m_LastEmitTmr.Reset(); - // Apply recoil/push effects, scaled by the joint stiffness - if (m_Parent && !m_OnlyLinearForces) - m_Parent->AddAbsImpulseForce(pushImpulses * m_JointStiffness, m_Pos + m_JointOffset); - else - m_ImpulseForces.push_back(make_pair(pushImpulses * m_JointStiffness, Vector())); + // Apply recoil/push effects. Joint stiffness will take effect when these are transferred to the parent. + m_ImpulseForces.push_back({pushImpulses, Vector()}); // Count the the damage caused by the emissions, and only if we're not bursting if (!m_BurstTriggered) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 5182d5c32..63128df25 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -211,7 +211,7 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { reader >> m_pJetpack; AddAttachable(m_pJetpack); if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } - m_pJetpack->SetOnlyLinearForces(true); + m_pJetpack->SetApplyTransferredForcesAtOffset(false); } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; // Convert to ms diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 379a1b2bc..0e60f3c17 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -17,14 +17,13 @@ namespace RTE { m_DrawAfterParent = true; m_DrawnNormallyByParent = true; m_DeleteWhenRemovedFromParent = false; + m_ApplyTransferredForcesAtOffset = true; m_JointStrength = 10; m_JointStiffness = 1.0; m_JointOffset.Reset(); m_JointPos.Reset(); - m_OnlyLinearForces = false; - m_DamageCount = 0; m_BreakWound = 0; m_ParentBreakWound = 0; @@ -57,14 +56,13 @@ namespace RTE { m_DrawAfterParent = reference.m_DrawAfterParent; m_DrawnNormallyByParent = reference.m_DrawnNormallyByParent; m_DeleteWhenRemovedFromParent = reference.m_DeleteWhenRemovedFromParent; + m_ApplyTransferredForcesAtOffset = reference.m_ApplyTransferredForcesAtOffset; m_JointStrength = reference.m_JointStrength; m_JointStiffness = reference.m_JointStiffness; m_JointOffset = reference.m_JointOffset; m_JointPos = reference.m_JointPos; - m_OnlyLinearForces = reference.m_OnlyLinearForces; - m_DamageCount = reference.m_DamageCount; m_BreakWound = reference.m_BreakWound; m_ParentBreakWound = reference.m_ParentBreakWound; @@ -85,8 +83,10 @@ namespace RTE { reader >> m_ParentOffset; } else if (propName == "DrawAfterParent") { reader >> m_DrawAfterParent; - } else if (propName == "DeleteWhenRemovedFromParent" || propName == "DeleteWithParent") { + } else if (propName == "DeleteWhenRemovedFromParent") { reader >> m_DeleteWhenRemovedFromParent; + } else if (propName == "ApplyTransferredForcesAtOffset") { + reader >> m_ApplyTransferredForcesAtOffset; } else if (propName == "JointStrength" || propName == "Strength") { reader >> m_JointStrength; } else if (propName == "JointStiffness" || propName == "Stiffness") { @@ -127,6 +127,8 @@ namespace RTE { writer << m_DrawAfterParent; writer.NewProperty("DeleteWhenRemovedFromParent"); writer << m_DeleteWhenRemovedFromParent; + writer.NewProperty("ApplyTransferredForcesAtOffset"); + writer << m_ApplyTransferredForcesAtOffset; writer.NewProperty("JointStrength"); writer << m_JointStrength; diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 522067798..e34cb5c76 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -145,6 +145,18 @@ namespace RTE { /// /// Whether this Attachable should be deleted when it's removed from its parent. void SetDeleteWhenRemovedFromParent(bool deleteWhenRemovedFromParent) { m_DeleteWhenRemovedFromParent = deleteWhenRemovedFromParent; } + + /// + /// Gets whether forces transferred from this Attachable should be applied at its parent's offset (rotated to match the parent) where they will produce torque, or directly at its parent's position. + /// + /// Whether forces transferred from this Attachable should be applied at an offset. + bool GetApplyTransferredForcesAtOffset() const { return m_ApplyTransferredForcesAtOffset; } + + /// + /// Sets whether forces transferred from this Attachable should be applied at its parent's offset (rotated to match the parent) where they will produce torque, or directly at its parent's position. + /// + /// Whether forces transferred from this Attachable should be applied at an offset. + void SetApplyTransferredForcesAtOffset(bool appliesTransferredForcesAtOffset) { m_ApplyTransferredForcesAtOffset = appliesTransferredForcesAtOffset; } #pragma endregion #pragma region Joint Getters and Setters @@ -187,19 +199,7 @@ namespace RTE { void SetJointOffset(Vector offset) { m_JointOffset = offset; } #pragma endregion -#pragma region Force Managment - /// - /// Indicates whether this Attachable only cares about linear forces that it creates through emissions, ie no torquing due to the parent offset. - /// - /// Whether this is only using linear forces or not. - bool GetOnlyLinearForces() const { return m_OnlyLinearForces; } - - /// - /// Sets whether this AEmitter should only care about linear forces that it creates through emissions, ie no torquing due to the parent offset. - /// - /// Whether to only use linear forces or not. - void SetOnlyLinearForces(bool onlyLinearForces) { m_OnlyLinearForces = onlyLinearForces; } - +#pragma region Force Transferral /// /// Bundles up all the accumulated forces of this Attachable and calculates how they transfer to the joint, and therefore to the parent. /// @@ -367,13 +367,13 @@ namespace RTE { bool m_DrawAfterParent; //!< Whether to draw this Attachable after (in front of) or before (behind) the parent. bool m_DrawnNormallyByParent; //!< Whether this Attachable will be be drawn normally when attached, or will require special handling by some non-MOSR parent type. bool m_DeleteWhenRemovedFromParent; //!< Whether this Attachable should be deleted when it's removed from its parent. + bool m_ApplyTransferredForcesAtOffset; //!< Whether forces transferred from this Attachable should be applied at the rotated parent offset (which will produce torque), or directly at the parent's position. Mostly useful to make jetpacks and similar emitters viable. float m_JointStrength; //!< The amount of impulse force needed on this to deatch it from the host Actor, in kg * m/s. float m_JointStiffness; //!< The normalized joint stiffness scalar. 1.0 means impulse forces on this attachable will be transferred to the parent with 100% strength, 0 means they will not transfer at all. Vector m_JointOffset; //!< The offset to the joint (the point around which this Attachable and its parent hinge) from its center of mass/origin. Vector m_JointPos; //!< The absolute position of the joint that the parent sets upon Update() if this Attachable is attached to it. - bool m_OnlyLinearForces; //!< Whether to only record linear forces, ie no torquing due to the parent offset. float m_DamageCount; //!< The number of damage points that this Attachable has accumulated since the last time CollectDamage() was called. const AEmitter *m_BreakWound; //!< The wound this Attachable will receive when it breaks from its parent. diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index f16b65178..803f74a80 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1955,10 +1955,10 @@ bool MOSRotating::TransferForcesFromAttachable(Attachable *attachable) { intact = attachable->TransferJointForces(forces) && attachable->TransferJointImpulses(impulses); if (!forces.IsZero()) { - AddForce(forces, attachable->GetOnlyLinearForces() ? Vector() : attachable->GetParentOffset() * m_Rotation); + AddForce(forces, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation : Vector()); } if (!impulses.IsZero()) { - AddImpulseForce(impulses, attachable->GetOnlyLinearForces() ? Vector() : attachable->GetParentOffset() * m_Rotation); + AddImpulseForce(impulses, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation : Vector()); } if (!intact) { RemoveAttachable(attachable, true, true); } } else { diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 58705c479..f08e80e08 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -816,7 +816,7 @@ int LuaMan::Create() .property("JointStrength", &Attachable::GetJointStrength, &Attachable::SetJointStrength) .property("JointStiffness", &Attachable::GetJointStiffness, &Attachable::SetJointStiffness) .property("JointOffset", &Attachable::GetJointOffset, &Attachable::SetJointOffset) - .property("OnlyLinearForces", &Attachable::GetOnlyLinearForces, &Attachable::SetOnlyLinearForces) + .property("ApplyTransferredForcesAtOffset", &Attachable::GetApplyTransferredForcesAtOffset, &Attachable::SetApplyTransferredForcesAtOffset) .property("BreakWound", &Attachable::GetBreakWound, &Attachable::SetBreakWound, detail::null_type(), adopt(_2)) .property("ParentBreakWound", &Attachable::GetParentBreakWound, &Attachable::SetParentBreakWound, detail::null_type(), adopt(_2)) .property("InheritsHFlipped", &Attachable::InheritsHFlipped, &Attachable::SetInheritsHFlipped) From 5f3f37ffe5d1a74cd7417c23c7d4e6c2e71e70a6 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 19 Sep 2020 01:09:11 -0300 Subject: [PATCH 049/144] Added new MOSRotating property for affecting gibbing - GibBlast Strength Added new Attachable properties for affecting gibbing - GibWithParentChance and ParentGibBlastStrengthMultiplier Made Gib GetParticlePreset method const since it returns a const pointer --- Entities/Attachable.cpp | 10 ++++++++++ Entities/Attachable.h | 30 +++++++++++++++++++++++++++++- Entities/Gib.h | 2 +- Entities/MOSRotating.cpp | 6 +++++- Entities/MOSRotating.h | 15 ++++++++++++++- 5 files changed, 59 insertions(+), 4 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 0e60f3c17..005c82ece 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -19,6 +19,9 @@ namespace RTE { m_DeleteWhenRemovedFromParent = false; m_ApplyTransferredForcesAtOffset = true; + m_GibWithParentChance = 0; + m_ParentGibBlastStrengthMultiplier = 1; + m_JointStrength = 10; m_JointStiffness = 1.0; m_JointOffset.Reset(); @@ -58,6 +61,9 @@ namespace RTE { m_DeleteWhenRemovedFromParent = reference.m_DeleteWhenRemovedFromParent; m_ApplyTransferredForcesAtOffset = reference.m_ApplyTransferredForcesAtOffset; + m_GibWithParentChance = reference.m_GibWithParentChance; + m_ParentGibBlastStrengthMultiplier = reference.m_ParentGibBlastStrengthMultiplier; + m_JointStrength = reference.m_JointStrength; m_JointStiffness = reference.m_JointStiffness; m_JointOffset = reference.m_JointOffset; @@ -87,6 +93,10 @@ namespace RTE { reader >> m_DeleteWhenRemovedFromParent; } else if (propName == "ApplyTransferredForcesAtOffset") { reader >> m_ApplyTransferredForcesAtOffset; + } else if (propName == "GibWithParentChance") { + reader >> m_GibWithParentChance; + } else if (propName == "ParentGibBlastStrengthMultiplier") { + reader >> m_ParentGibBlastStrengthMultiplier; } else if (propName == "JointStrength" || propName == "Strength") { reader >> m_JointStrength; } else if (propName == "JointStiffness" || propName == "Stiffness") { diff --git a/Entities/Attachable.h b/Entities/Attachable.h index e34cb5c76..246535916 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -159,6 +159,32 @@ namespace RTE { void SetApplyTransferredForcesAtOffset(bool appliesTransferredForcesAtOffset) { m_ApplyTransferredForcesAtOffset = appliesTransferredForcesAtOffset; } #pragma endregion +#pragma region Parent Gib Handling Getters and Setters + /// + /// Gets the percentage chance that this Attachable will gib when its parent does. 0 means never, 1 means always. + /// + /// A float with the percentage chance this Attachable will gib when its parent gibs. + float GetGibWithParentChance() const { return m_GibWithParentChance; } + + /// + /// Sets the percentage chance that this Attachable will gib when its parent does. 0 means never, 1 means always. + /// + /// A float describing the percentage chance this Attachable will gib when its parent gibs. + void SetGibWithParentChance(float gibWithParentChance) { m_GibWithParentChance = gibWithParentChance; } + + /// + /// Gets the multiplier this Attacahble will apply to its parent's gib blast strength when the parent gibs. + /// + /// A float with the gib blast strength multiplier of this Attachable. + float GetParentGibBlastStrengthMultiplier() const { return m_ParentGibBlastStrengthMultiplier; } + + /// + /// Sets the multiplier this Attacahble will apply to its parent's gib blast strength when the parent gibs. + /// + /// A float describing the gib blast strength multiplier of this Attachable. + void SetParentGibBlastStrengthMultiplier(float parentGibBlastStrengthMultiplier) { m_ParentGibBlastStrengthMultiplier = parentGibBlastStrengthMultiplier; } +#pragma endregion + #pragma region Joint Getters and Setters /// /// Gets the amount of impulse force the joint of this Attachable can handle before breaking. @@ -369,12 +395,14 @@ namespace RTE { bool m_DeleteWhenRemovedFromParent; //!< Whether this Attachable should be deleted when it's removed from its parent. bool m_ApplyTransferredForcesAtOffset; //!< Whether forces transferred from this Attachable should be applied at the rotated parent offset (which will produce torque), or directly at the parent's position. Mostly useful to make jetpacks and similar emitters viable. + float m_GibWithParentChance; //!< The percentage chance that this Attachable will gib when its parent does. 0 means never, 1 means always. + float m_ParentGibBlastStrengthMultiplier; //!< The multiplier this Attacahble will apply to its parent's gib blast strength when the parent gibs. + float m_JointStrength; //!< The amount of impulse force needed on this to deatch it from the host Actor, in kg * m/s. float m_JointStiffness; //!< The normalized joint stiffness scalar. 1.0 means impulse forces on this attachable will be transferred to the parent with 100% strength, 0 means they will not transfer at all. Vector m_JointOffset; //!< The offset to the joint (the point around which this Attachable and its parent hinge) from its center of mass/origin. Vector m_JointPos; //!< The absolute position of the joint that the parent sets upon Update() if this Attachable is attached to it. - float m_DamageCount; //!< The number of damage points that this Attachable has accumulated since the last time CollectDamage() was called. const AEmitter *m_BreakWound; //!< The wound this Attachable will receive when it breaks from its parent. const AEmitter *m_ParentBreakWound; //!< The wound this Attachable's parent will receive when the Attachable breaks from its parent. diff --git a/Entities/Gib.h b/Entities/Gib.h index 76eaa8127..73d0aac5c 100644 --- a/Entities/Gib.h +++ b/Entities/Gib.h @@ -49,7 +49,7 @@ namespace RTE { /// Gets the reference particle to be used as a Gib. Ownership is NOT transferred! /// /// A pointer to the particle to be used as a Gib. - const MovableObject * GetParticlePreset() { return m_GibParticle; } + const MovableObject * GetParticlePreset() const { return m_GibParticle; } /// /// Gets the spawn offset of this Gib from the parent's position. diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 803f74a80..9d5623249 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -66,6 +66,7 @@ void MOSRotating::Clear() m_Gibs.clear(); m_GibImpulseLimit = 0; m_GibWoundLimit = 0; + m_GibBlastStrength = 10.0F; m_GibSound.Reset(); m_EffectOnGib = true; m_pFlipBitmap = 0; @@ -268,6 +269,7 @@ int MOSRotating::Create(const MOSRotating &reference) m_GibImpulseLimit = reference.m_GibImpulseLimit; m_GibWoundLimit = reference.m_GibWoundLimit; + m_GibBlastStrength = reference.m_GibBlastStrength; m_GibSound = reference.m_GibSound; m_EffectOnGib = reference.m_EffectOnGib; m_LoudnessOnGib = reference.m_LoudnessOnGib; @@ -338,7 +340,9 @@ int MOSRotating::ReadProperty(std::string propName, Reader &reader) reader >> m_GibImpulseLimit; else if (propName == "GibWoundLimit" || propName == "WoundLimit") reader >> m_GibWoundLimit; - else if (propName == "GibSound") + else if (propName == "GibBlastStrength") { + reader >> m_GibBlastStrength; + } else if (propName == "GibSound") reader >> m_GibSound; else if (propName == "EffectOnGib") reader >> m_EffectOnGib; diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 0617cc4d9..7bbd744fa 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -593,6 +593,18 @@ ClassInfoGetters /// The new gib wound limit to use. void SetGibWoundLimit(int newGibWoundLimit) { m_GibWoundLimit = newGibWoundLimit; } + /// + /// Gets the gib blast strength this MOSRotating, i.e. the strength with which Gibs and Attachables will be launched when this MOSRotating is gibbed. + /// + /// The gib blast strength of this MOSRotating. + int GetGibBlastStrength() const { return m_GibBlastStrength; } + + /// + /// Sets the gib blast strength this MOSRotating, i.e. the strength with which Gibs and Attachables will be launched when this MOSRotating is gibbed. + /// + /// The new gib blast strength to use. + void SetGibBlastStrength(int newGibBlastStrength) { m_GibBlastStrength = newGibBlastStrength; } + /// /// Gets the number of wounds attached to this MOSRotating. /// Includes any Attachables (and their Attachables, etc.) that have a positive damage multiplier. @@ -847,13 +859,14 @@ ClassInfoGetters std::list m_Wounds; // The list of Attachables currently attached and Owned by this. std::list m_Attachables; - std::unordered_map> m_HardcodedAttachableUniqueIDsAndSetters; //> m_HardcodedAttachableUniqueIDsAndSetters; //!< An unordered map of Unique IDs to setter lambda functions, used to properly set member pointers for hardcoded Attachables (i.e. head, legs, etc.) when cloning. // The list of Gib:s this will create when gibbed std::list m_Gibs; // The amount of impulse force required to gib this, in kg * (m/s). 0 means no limit float m_GibImpulseLimit; // The number of wound emitters allowed before this gets gibbed. 0 means this can't get gibbed int m_GibWoundLimit; + float m_GibBlastStrength; //!< The strength with which Gibs and Attachables will get launched when this MOSRotating is gibbed. // Gib sound effect SoundContainer m_GibSound; // Whether to flash effect on gib From eaedcc18a55f6221decf8b308111347fa6e206d0 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 19 Sep 2020 01:17:01 -0300 Subject: [PATCH 050/144] Used new Attachable and MOSRotating properties to simplify gibbing and make it more consistent. Also broke it down into separate functions for handling gibs and attachables --- Entities/MOSRotating.cpp | 224 ++++++++++++++------------------------- Entities/MOSRotating.h | 32 ++++-- 2 files changed, 98 insertions(+), 158 deletions(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 9d5623249..c72169d22 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -974,173 +974,103 @@ bool MOSRotating::ParticlePenetration(HitData &hd) return false; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. - -void MOSRotating::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) -{ - // Can't, or is already gibbed, so don't do anything - if (m_MissionCritical || m_ToDelete) +void MOSRotating::GibThis(const Vector &impactImpulse, MovableObject *movableObjectToIgnore) { + if (m_MissionCritical || m_ToDelete) { return; + } - MovableObject *pGib = 0; - float velMin, velRange, spread, angularVel; - Vector gibROffset, gibVel; - for (list::iterator gItr = m_Gibs.begin(); gItr != m_Gibs.end(); ++gItr) - { - // Throwing out gibs - for (int i = 0; i < (*gItr).GetCount(); ++i) - { - // Make a copy after the preset particle - // THIS IS A TIME SINK, takes up the vast bulk of time of GibThis - { - // Create gibs - pGib = dynamic_cast((*gItr).GetParticlePreset()->Clone()); - } - - // Generate the velocities procedurally - if ((*gItr).GetMinVelocity() == 0 && (*gItr).GetMaxVelocity() == 0) - { - velMin = internalBlast / pGib->GetMass(); - velRange = 10.0f; - } - // Use the ones defined already - else - { - velMin = (*gItr).GetMinVelocity(); - velRange = (*gItr).GetMaxVelocity() - (*gItr).GetMinVelocity(); - } - spread = (*gItr).GetSpread(); - gibROffset = RotateOffset((*gItr).GetOffset()); - // Put variation on the lifetime, if it's not set to be endless - if (pGib->GetLifetime() != 0) - pGib->SetLifetime(pGib->GetLifetime() * (1.0 + ((*gItr).GetLifeVariation() * NormalRand()))); - // Set up its position and velocity according to the parameters of this AEmitter. - pGib->SetPos(m_Pos + gibROffset/*Vector(m_Pos.m_X + 5 * NormalRand(), m_Pos.m_Y + 5 * NormalRand())*/); - pGib->SetRotAngle(m_Rotation.GetRadAngle() + pGib->GetRotMatrix().GetRadAngle()); - // Rotational angle - pGib->SetAngularVel((pGib->GetAngularVel() * 0.35) + (pGib->GetAngularVel() * 0.65 / pGib->GetMass()) * PosRand()); - // Make it rotate away in the appropriate direction depending on which side of the object it is on - // If the object is far to the relft or right of the center, make it always rotate outwards to some degree - if (gibROffset.m_X > m_aSprite[0]->w / 3) - { - float offCenterRatio = gibROffset.m_X / (m_aSprite[0]->w / 2); - angularVel = fabs(pGib->GetAngularVel() * 0.5); - angularVel += fabs(pGib->GetAngularVel() * 0.5 * offCenterRatio); - pGib->SetAngularVel(angularVel * (gibROffset.m_X > 0 ? -1 : 1)); - } - // Gib is too close to center to always make it rotate in one direction, so give it a baseline rotation and then randomize - else - { - pGib->SetAngularVel((pGib->GetAngularVel() * 0.5 + pGib->GetAngularVel() * PosRand()) * (NormalRand() > 0 ? 1 : -1)); - } - -// TODO: Optimize making the random angles!") - { - // Pretty much always zero - gibVel = gibROffset; - if (gibVel.IsZero()) - gibVel.SetXY(velMin + velRange * PosRand(), 0); - else - gibVel.SetMagnitude(velMin + velRange * PosRand()); - gibVel.RadRotate(impactImpulse.GetAbsRadAngle() + spread * NormalRand()); -// Don't! the offset was already rotated! -// gibVel = RotateOffset(gibVel); - // Distribute any impact implse out over all the gibs -// gibVel += (impactImpulse / m_Gibs.size()) / pGib->GetMass(); - } + CreateGibsWhenGibbing(impactImpulse, movableObjectToIgnore); - // Only add the velocity of the parent if it's suppposed to - if ((*gItr).InheritsVelocity()) - pGib->SetVel(m_Vel + gibVel); - else - pGib->SetVel(gibVel); + RemoveAttachablesWhenGibbing(impactImpulse, movableObjectToIgnore); - // Set the gib to not hit a specific MO - if (pIgnoreMO) - pGib->SetWhichMOToNotHit(pIgnoreMO); + m_GibSound.Play(m_Pos); - // Add the gib to the scene - g_MovableMan.AddParticle(pGib); - pGib = 0; - } + if (m_pScreenEffect && m_EffectOnGib && (m_EffectAlwaysShows || !g_SceneMan.ObscuredPoint(m_Pos.GetFloorIntX(), m_Pos.GetFloorIntY()))) { + g_PostProcessMan.RegisterPostEffect(m_Pos, m_pScreenEffect, m_ScreenEffectHash, 255, m_EffectRotAngle); } - // Throw out all the attachables - Attachable *pAttachable = 0; - for (list::iterator aItr = m_Attachables.begin(); aItr != m_Attachables.end(); ) //NOTE: No increment to handle RemoveAttachable removing the object - { - RTEAssert((*aItr), "Broken Attachable!"); + if (m_LoudnessOnGib > 0) { + g_MovableMan.RegisterAlarmEvent(AlarmEvent(m_Pos, m_Team, m_LoudnessOnGib)); + } - // Get handy handle to the object we're putting - pAttachable = *aItr; + m_ToDelete = true; +} - // TODO: Rework this whole system - // Generate the velocities procedurally - velMin = internalBlast / (1 + pAttachable->GetMass()); - velRange = 10.0f; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Rotational angle velocity - pAttachable->SetAngularVel((pAttachable->GetAngularVel() * 0.35) + (pAttachable->GetAngularVel() * 0.65 / pAttachable->GetMass()) * PosRand()); - // Make it rotate away in the appropriate direction depending on which side of the object it is on - // If the object is far to the relft or right of the center, make it always rotate outwards to some degree - if (pAttachable->GetParentOffset().m_X > m_aSprite[0]->w / 3) - { - float offCenterRatio = pAttachable->GetParentOffset().m_X / (m_aSprite[0]->w / 2); - angularVel = fabs(pAttachable->GetAngularVel() * 0.5); - angularVel += fabs(pAttachable->GetAngularVel() * 0.5 * offCenterRatio); - pAttachable->SetAngularVel(angularVel * (pAttachable->GetParentOffset().m_X > 0 ? -1 : 1)); - } - // Gib is too close to center to always make it rotate in one direction, so give it a baseline rotation and then randomize - else - { - pAttachable->SetAngularVel((pAttachable->GetAngularVel() * 0.5 + pAttachable->GetAngularVel() * PosRand()) * (NormalRand() > 0 ? 1 : -1)); +void MOSRotating::CreateGibsWhenGibbing(const Vector &impactImpulse, MovableObject *movableObjectToIgnore) { + for (const Gib &gibSettingsObject : m_Gibs) { + if (gibSettingsObject.GetCount() == 0) { + continue; } + MovableObject *gibParticleClone = dynamic_cast(gibSettingsObject.GetParticlePreset()->Clone()); + gibParticleClone->SetRotAngle(GetRotAngle() + gibParticleClone->GetRotAngle()); + Vector rotatedGibOffset = RotateOffset(gibSettingsObject.GetOffset()); + gibParticleClone->SetPos(m_Pos + rotatedGibOffset); + + float minVelocity = (gibSettingsObject.GetMinVelocity() == 0 && gibSettingsObject.GetMaxVelocity() == 0) ? m_GibBlastStrength / gibParticleClone->GetMass() : gibSettingsObject.GetMinVelocity(); + float velocityRange = (gibSettingsObject.GetMinVelocity() == 0 && gibSettingsObject.GetMaxVelocity() == 0) ? 10.0F : gibSettingsObject.GetMaxVelocity() - gibSettingsObject.GetMinVelocity(); + for (int i = 0; i < gibSettingsObject.GetCount(); i++) { + if (i > 0) { gibParticleClone = dynamic_cast(gibParticleClone->Clone()); } + + if (gibParticleClone->GetLifetime() != 0) { gibParticleClone->SetLifetime(gibParticleClone->GetLifetime() * static_cast((1.0F + gibSettingsObject.GetLifeVariation() * NormalRand()/*RandomNormalNum()*/))); } + + gibParticleClone->SetAngularVel((gibParticleClone->GetAngularVel() * 0.35F) + (gibParticleClone->GetAngularVel() * 0.65F / gibParticleClone->GetMass()) * PosRand()/*RandomNum()*/); + if (rotatedGibOffset.GetRoundIntX() > m_aSprite[0]->w / 3) { + float offCenterRatio = rotatedGibOffset.m_X / (static_cast(m_aSprite[0]->w) / 2.0F); + float angularVel = fabs(gibParticleClone->GetAngularVel() * 0.5F) + fabs(gibParticleClone->GetAngularVel() * 0.5F * offCenterRatio); + gibParticleClone->SetAngularVel(angularVel * (rotatedGibOffset.m_X > 0 ? -1 : 1)); + } else { + gibParticleClone->SetAngularVel((gibParticleClone->GetAngularVel() * 0.5F + (gibParticleClone->GetAngularVel() * PosRand()/*RandomNum()*/)) * (NormalRand()/*RandomNormalNum()*/ > 0.0F ? 1.0F : -1.0F)); + } -// TODO: Optimize making the random angles!") - gibVel = pAttachable->GetParentOffset(); - if (gibVel.IsZero()) - gibVel.SetXY(velMin + velRange * PosRand(), 0); - else - gibVel.SetMagnitude(velMin + velRange * PosRand()); - gibVel.RadRotate(impactImpulse.GetAbsRadAngle()); - pAttachable->SetVel(m_Vel + gibVel); - - // Set the gib to not hit a specific MO - if (pIgnoreMO) - pAttachable->SetWhichMOToNotHit(pIgnoreMO); - - // Safely remove attachable and add it to the scene - ++aItr; - RemoveAttachable(pAttachable); - g_MovableMan.AddParticle(pAttachable); - pAttachable = 0; - } - // Clear the attachables list, all the attachables ownership have been handed to the movableman - m_Attachables.clear(); + Vector gibVelocity = rotatedGibOffset.SetMagnitude(minVelocity + (velocityRange * PosRand())).RadRotate(impactImpulse.GetAbsRadAngle() + gibSettingsObject.GetSpread() + NormalRand()); + //Vector gibVelocity = rotatedGibOffset.SetMagnitude(minVelocity + RandomNum(0.0F, velocityRange)).RadRotate(impactImpulse.GetAbsRadAngle() + gib.GetSpread() + RandomNormalNum()); + gibParticleClone->SetVel(gibVelocity + (gibSettingsObject.InheritsVelocity() ? m_Vel : Vector())); - // Play the gib sound - m_GibSound.Play(m_Pos); + if (movableObjectToIgnore) { + gibParticleClone->SetWhichMOToNotHit(movableObjectToIgnore); + } - // Flash post effect if it is defined - if (m_pScreenEffect && m_EffectOnGib && (m_EffectAlwaysShows || !g_SceneMan.ObscuredPoint(m_Pos.GetFloorIntX(), m_Pos.GetFloorIntY()))) - { - // Set the screen effect to draw at the final post processing stage - g_PostProcessMan.RegisterPostEffect(m_Pos, m_pScreenEffect, m_ScreenEffectHash, 255, m_EffectRotAngle); + g_MovableMan.AddParticle(gibParticleClone); + } } +} - // Things breaking apart makes alarming noises! - if (m_LoudnessOnGib > 0) - g_MovableMan.RegisterAlarmEvent(AlarmEvent(m_Pos, m_Team, m_LoudnessOnGib)); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Mark this for deletion! - m_ToDelete = true; +void MOSRotating::RemoveAttachablesWhenGibbing(const Vector &impactImpulse, MovableObject *movableObjectToIgnore) { + Attachable *attachable; + for (list::iterator attachableIterator = m_Attachables.begin(); attachableIterator != m_Attachables.end();) { + RTEAssert((*attachableIterator), "Broken Attachable!"); + attachable = *attachableIterator; + + if (PosRand()/*RandomNum()*/ < attachable->GetGibWithParentChance()) { + ++attachableIterator; + attachable->GibThis(); + continue; + } + + if (!attachable->GetDeleteWhenRemovedFromParent()) { + float attachableGibBlastStrength = (attachable->GetParentGibBlastStrengthMultiplier() == 0 ? 1 : attachable->GetParentGibBlastStrengthMultiplier() * m_GibBlastStrength) / (1 + attachable->GetMass()); + attachable->SetAngularVel((attachable->GetAngularVel() * 0.5F) + (attachable->GetAngularVel() * 0.5F * attachableGibBlastStrength * NormalRand()/*RandomNormalNum()*/)); + Vector gibBlastVel = Vector(attachable->GetParentOffset()).SetMagnitude(attachableGibBlastStrength * 0.5 + (attachableGibBlastStrength * PosRand()/*RandomNum()*/)); + attachable->SetVel(m_Vel + gibBlastVel + impactImpulse); + + if (movableObjectToIgnore) { + attachable->SetWhichMOToNotHit(movableObjectToIgnore); + } + } + + ++attachableIterator; + RemoveAttachable(attachable, true, true); + } + m_Attachables.clear(); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: MoveOutOfTerrain diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 7bbd744fa..da90376f7 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -330,17 +330,13 @@ ClassInfoGetters virtual bool ParticlePenetration(HitData &hd); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - virtual void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0); + /// + /// Destroys this MOSRotating and creates its specified Gibs in its place with appropriate velocities. + /// Any Attachables are removed and also given appropriate velocities. + /// + /// The impulse (kg * m/s) of the impact causing the gibbing to happen. + /// A pointer to an MO which the Gibs and Attachables should not be colliding with. + virtual void GibThis(const Vector &impactImpulse = Vector(), MovableObject *movableObjectToIgnore = nullptr); ////////////////////////////////////////////////////////////////////////////////////////// @@ -829,6 +825,20 @@ ClassInfoGetters void UpdateChildMOIDs(std::vector &MOIDIndex, MOID rootMOID = g_NoMOID, bool makeNewMOID = true) override; + /// + /// Creates the particles specified by this MOSRotating's list of Gibs and adds them to MovableMan with appropriately randomized velocities, based on this MOSRotating's gib blast strength. + /// + /// The impulse (kg * m/s) of the impact that caused the gibbing to happen. + /// A pointer to an MO which the Attachables should not be colliding with. + void CreateGibsWhenGibbing(const Vector &impactImpulse, MovableObject *movableObjectToIgnore); + + /// + /// Removes all Attachables from this MOSR, deleting them or adding them to MovableMan as appropriate, and giving them randomized velocities based on their properties and this MOSRotating's gib blast strength. + /// + /// The impulse (kg * m/s) of the impact that caused the gibbing to happen. + /// A pointer to an MO which the Attachables should not be colliding with. + void RemoveAttachablesWhenGibbing(const Vector &impactImpulse, MovableObject *movableObjectToIgnore); + // Member variables static Entity::ClassInfo m_sClass; // float m_Torque; // In kg * r/s^2 (Newtons). From 0649a55d7fd7fc16f6bdd398acc657acf5900c19 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 19 Sep 2020 02:03:30 -0300 Subject: [PATCH 051/144] Deleted GibThis method in ACrab, AHuman, ACRocket, ACDropship, Deleted no longer needed ACraft::SetAttachableVelocitiesForGibbing Fixed up Actor and ADoor and Attachable GibThis methods to match with changes Tweaked some settings so various objects gib appropriately --- Entities/ACDropShip.cpp | 64 +------------------------------------ Entities/ACDropShip.h | 13 -------- Entities/ACRocket.cpp | 71 +---------------------------------------- Entities/ACRocket.h | 13 -------- Entities/ACrab.cpp | 63 +----------------------------------- Entities/ACrab.h | 13 -------- Entities/ACraft.cpp | 15 --------- Entities/ACraft.h | 2 -- Entities/ADoor.cpp | 11 ++----- Entities/ADoor.h | 8 ++--- Entities/AHuman.cpp | 63 +----------------------------------- Entities/AHuman.h | 13 -------- Entities/Actor.cpp | 10 +++--- Entities/Actor.h | 18 ++++------- Entities/Arm.cpp | 12 ------- Entities/Arm.h | 13 -------- Entities/Attachable.cpp | 6 ++-- Entities/Attachable.h | 8 ++--- Entities/HDFirearm.cpp | 1 + Entities/HeldDevice.cpp | 3 ++ Entities/Leg.cpp | 1 + Entities/Turret.cpp | 1 + 22 files changed, 36 insertions(+), 386 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 28e260e75..6420f8f97 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -327,68 +327,6 @@ bool ACDropShip::OnSink(const Vector &pos) } */ -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. - -void ACDropShip::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) -{ - // TODO: maybe make hardcoded attachables gib if their gib list isn't empty - // Detach all limbs and let loose - if (m_pRThruster && m_pRThruster->IsAttached()) - { - RemoveAttachable(m_pRThruster); - SetAttachableVelocitiesForGibbing(m_pRThruster, impactImpulse, internalBlast); - m_pRThruster->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pRThruster); - m_pRThruster = 0; - } - if (m_pLThruster && m_pLThruster->IsAttached()) - { - RemoveAttachable(m_pLThruster); - SetAttachableVelocitiesForGibbing(m_pLThruster, impactImpulse, internalBlast); - m_pLThruster->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pLThruster); - m_pLThruster = 0; - } - if (m_pRHatch && m_pRHatch->IsAttached()) - { - RemoveAttachable(m_pRHatch); - SetAttachableVelocitiesForGibbing(m_pRHatch, impactImpulse, internalBlast); - m_pRHatch->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pRHatch); - m_pRHatch = 0; - } - if (m_pLHatch && m_pLHatch->IsAttached()) - { - RemoveAttachable(m_pLHatch); - SetAttachableVelocitiesForGibbing(m_pLHatch, impactImpulse, internalBlast); - m_pLHatch->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pLHatch); - m_pLHatch = 0; - } - if (m_pURThruster && m_pURThruster->IsAttached()) - { - RemoveAttachable(m_pURThruster); - SetAttachableVelocitiesForGibbing(m_pURThruster, impactImpulse, internalBlast); - m_pURThruster->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pURThruster); - m_pURThruster = 0; - } - if (m_pULThruster && m_pULThruster->IsAttached()) - { - RemoveAttachable(m_pULThruster); - SetAttachableVelocitiesForGibbing(m_pULThruster, impactImpulse, internalBlast); - m_pULThruster->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pULThruster); - m_pULThruster = 0; - } - - Actor::GibThis(impactImpulse, internalBlast, pIgnoreMO); -} - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: UpdateAI @@ -756,7 +694,7 @@ void ACDropShip::Update() // Explosion logic if (m_Status == DEAD) - GibThis(Vector(), 50); + GibThis(); //////////////////////////////////////// // Balance stuff diff --git a/Entities/ACDropShip.h b/Entities/ACDropShip.h index 826b8429b..b631a8f35 100644 --- a/Entities/ACDropShip.h +++ b/Entities/ACDropShip.h @@ -143,19 +143,6 @@ ClassInfoGetters bool AutoStabilizing() override { return true; } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: UpdateAI ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index c10bd4e5d..9286e9b5b 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -322,75 +322,6 @@ bool ACRocket::OnSink(const Vector &pos) return false; } */ -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. - -void ACRocket::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) -{ - // TODO: maybe make hardcoded attachables gib if their gib list isn't empty - // Detach all limbs and let loose - if (m_pRLeg && m_pRLeg->IsAttached()) - { - RemoveAttachable(m_pRLeg); - SetAttachableVelocitiesForGibbing(m_pRLeg, impactImpulse, internalBlast); - m_pRLeg->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pRLeg); - m_pRLeg = 0; - } - if (m_pLLeg && m_pLLeg->IsAttached()) - { - RemoveAttachable(m_pLLeg); - SetAttachableVelocitiesForGibbing(m_pLLeg, impactImpulse, internalBlast); - m_pLLeg->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pLLeg); - m_pLLeg = 0; - } - if (m_pMThruster && m_pMThruster->IsAttached()) - { - RemoveAttachable(m_pMThruster); - SetAttachableVelocitiesForGibbing(m_pMThruster, impactImpulse, internalBlast); - m_pMThruster->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pMThruster); - m_pMThruster = 0; - } - if (m_pRThruster && m_pRThruster->IsAttached()) - { - RemoveAttachable(m_pRThruster); - SetAttachableVelocitiesForGibbing(m_pRThruster, impactImpulse, internalBlast); - m_pRThruster->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pRThruster); - m_pRThruster = 0; - } - if (m_pLThruster && m_pLThruster->IsAttached()) - { - RemoveAttachable(m_pLThruster); - SetAttachableVelocitiesForGibbing(m_pLThruster, impactImpulse, internalBlast); - m_pLThruster->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pLThruster); - m_pLThruster = 0; - } - if (m_pURThruster && m_pURThruster->IsAttached()) - { - RemoveAttachable(m_pURThruster); - SetAttachableVelocitiesForGibbing(m_pURThruster, impactImpulse, internalBlast); - m_pURThruster->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pURThruster); - m_pURThruster = 0; - } - if (m_pULThruster && m_pULThruster->IsAttached()) - { - RemoveAttachable(m_pULThruster); - SetAttachableVelocitiesForGibbing(m_pULThruster, impactImpulse, internalBlast); - m_pULThruster->SetToGetHitByMOs(false); - g_MovableMan.AddParticle(m_pULThruster); - m_pULThruster = 0; - } - - Actor::GibThis(impactImpulse, internalBlast, pIgnoreMO); -} ////////////////////////////////////////////////////////////////////////////////////////// @@ -802,7 +733,7 @@ void ACRocket::Update() // Explosion logic if (m_Status == DEAD) - GibThis(Vector(), 50); + GibThis(); //////////////////////////////////////// // Balance stuff diff --git a/Entities/ACRocket.h b/Entities/ACRocket.h index 0a8f2d182..41b222664 100644 --- a/Entities/ACRocket.h +++ b/Entities/ACRocket.h @@ -137,19 +137,6 @@ ClassInfoGetters float GetAltitude(int max = 0, int accuracy = 0) override; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: UpdateAI ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 857e20737..a6db999f0 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -235,6 +235,7 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) AddAttachable(m_pJetpack); if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } m_pJetpack->SetApplyTransferredForcesAtOffset(false); + m_pJetpack->SetDeleteWhenRemovedFromParent(true); } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; m_JetTimeTotal *= 1000; @@ -971,68 +972,6 @@ MovableObject * ACrab::LookForMOs(float FOVSpread, unsigned char ignoreMaterial, } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. - -void ACrab::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) -{ - // Detach all limbs and let loose - if (m_pTurret && m_pTurret->IsAttached()) - { - RemoveAttachable(m_pTurret); - m_pTurret->SetVel(m_Vel + m_pTurret->GetParentOffset() * PosRand()); - m_pTurret->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_pTurret); - m_pTurret = 0; - } - if (m_pJetpack && m_pJetpack->IsAttached()) - { - // Jetpacks are really nothing, so just delete them safely - RemoveAttachable(m_pJetpack); - m_pJetpack->SetToDelete(true); - g_MovableMan.AddParticle(m_pJetpack); - m_pJetpack = 0; - } - if (m_pLFGLeg && m_pLFGLeg->IsAttached()) - { - RemoveAttachable(m_pLFGLeg); - m_pLFGLeg->SetVel(m_Vel + m_pLFGLeg->GetParentOffset() * PosRand()); - m_pLFGLeg->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_pLFGLeg); - m_pLFGLeg = 0; - } - if (m_pLBGLeg && m_pLBGLeg->IsAttached()) - { - RemoveAttachable(m_pLBGLeg); - m_pLBGLeg->SetVel(m_Vel + m_pLBGLeg->GetParentOffset() * PosRand()); - m_pLBGLeg->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_pLBGLeg); - m_pLBGLeg = 0; - } - if (m_pRFGLeg && m_pRFGLeg->IsAttached()) - { - RemoveAttachable(m_pRFGLeg); - m_pRFGLeg->SetVel(m_Vel + m_pRFGLeg->GetParentOffset() * PosRand()); - m_pRFGLeg->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_pRFGLeg); - m_pRFGLeg = 0; - } - if (m_pRBGLeg && m_pRBGLeg->IsAttached()) - { - RemoveAttachable(m_pRBGLeg); - m_pRBGLeg->SetVel(m_Vel + m_pRBGLeg->GetParentOffset() * PosRand()); - m_pRBGLeg->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_pRBGLeg); - m_pRBGLeg = 0; - } - - Actor::GibThis(impactImpulse, internalBlast, pIgnoreMO); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: UpdateMovePath ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACrab.h b/Entities/ACrab.h index f3169bb6b..3fcea49ae 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -401,19 +401,6 @@ int FirearmActivationDelay() const; MovableObject * LookForMOs(float FOVSpread = 45, unsigned char ignoreMaterial = 0, bool ignoreAllTerrain = false); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: UpdateMovePath ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACraft.cpp b/Entities/ACraft.cpp index 4be928bbf..85425e0b1 100644 --- a/Entities/ACraft.cpp +++ b/Entities/ACraft.cpp @@ -1076,19 +1076,4 @@ void ACraft::DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos, int whichSc } } -/// -/// Helper method to remove code duplication in ACDropship and ACRocket gibbing -/// -/// The attachable to set velocities for -/// The impactImpulse passed in from GibThis -/// The internalBlast passed in from GibThis -void ACraft::SetAttachableVelocitiesForGibbing(Attachable * pAttachable, Vector impactImpulse, float internalBlast) -{ - Vector newVel(pAttachable->GetPos() - m_Pos); - newVel.SetMagnitude(internalBlast); - newVel += m_Vel + impactImpulse; - pAttachable->SetVel(newVel); - pAttachable->SetAngularVel(NormalRand()); -} - } // namespace RTE \ No newline at end of file diff --git a/Entities/ACraft.h b/Entities/ACraft.h index 825a9f87f..d3b017b19 100644 --- a/Entities/ACraft.h +++ b/Entities/ACraft.h @@ -581,8 +581,6 @@ enum protected: - void SetAttachableVelocitiesForGibbing(Attachable* pAttachable, Vector impactImpulse, float internalBlast); - // Member variables static Entity::ClassInfo m_sClass; // Current movement state. diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index a58893199..9ac6015da 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -269,18 +269,13 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void ADoor::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *ignoreMO) { + void ADoor::GibThis(const Vector &impactImpulse, MovableObject *movableObjectToIgnore) { if (m_Door && m_Door->IsAttached()) { EraseDoorMaterial(); m_Door->DeepCheck(true); m_Door->SetPinStrength(0); - m_Door->SetVel(m_Vel + m_Door->GetParentOffset() * PosRand()); - m_Door->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_Door); - RemoveAttachable(m_Door); - m_Door = 0; } - Actor::GibThis(impactImpulse, internalBlast, ignoreMO); + Actor::GibThis(impactImpulse, movableObjectToIgnore); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -384,7 +379,7 @@ namespace RTE { m_Health -= 0.4F; } - if (m_Status == DEAD) { GibThis(Vector(), 50); } + if (m_Status == DEAD) { GibThis(); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ADoor.h b/Entities/ADoor.h index 3c34ab47a..fbb8e0fe9 100644 --- a/Entities/ADoor.h +++ b/Entities/ADoor.h @@ -123,12 +123,12 @@ namespace RTE { #pragma region Virtual Override Methods /// - /// Gibs this, effectively destroying it and creating multiple gibs or pieces in its place. + /// Destroys this ADoor and creates its specified Gibs in its place with appropriate velocities. + /// Any Attachables are removed and also given appropriate velocities. /// /// The impulse (kg * m/s) of the impact causing the gibbing to happen. - /// The internal blast impulse which will push the gibs away from the center. - /// A pointer to an MO which the gibs should not be colliding with! - void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *ignoreMO = 0) override; + /// A pointer to an MO which the Gibs and Attachables should not be colliding with. + void GibThis(const Vector &impactImpulse = Vector(), MovableObject *movableObjectToIgnore = nullptr) override; /// /// Updates this ADoor. Supposed to be done every frame. diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 63128df25..84aced79b 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -212,6 +212,7 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { AddAttachable(m_pJetpack); if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } m_pJetpack->SetApplyTransferredForcesAtOffset(false); + m_pJetpack->SetDeleteWhenRemovedFromParent(true); } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; // Convert to ms @@ -1649,68 +1650,6 @@ MovableObject * AHuman::LookForMOs(float FOVSpread, unsigned char ignoreMaterial } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. - -void AHuman::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) -{ - // Detach all limbs and let loose - if (m_pHead && m_pHead->IsAttached()) - { - RemoveAttachable(m_pHead); - m_pHead->SetVel(m_Vel + m_pHead->GetParentOffset() * PosRand()); - m_pHead->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_pHead); - m_pHead = 0; - } - if (m_pJetpack && m_pJetpack->IsAttached()) - { - // Jetpacks are really nothing, so just delete them safely - RemoveAttachable(m_pJetpack); - m_pJetpack->SetToDelete(true); - g_MovableMan.AddParticle(m_pJetpack); - m_pJetpack = 0; - } - if (m_pFGArm && m_pFGArm->IsAttached()) - { - RemoveAttachable(m_pFGArm); - m_pFGArm->SetVel(m_Vel + m_pFGArm->GetParentOffset() * PosRand()); - m_pFGArm->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_pFGArm); - m_pFGArm = 0; - } - if (m_pBGArm && m_pBGArm->IsAttached()) - { - RemoveAttachable(m_pBGArm); - m_pBGArm->SetVel(m_Vel + m_pBGArm->GetParentOffset() * PosRand()); - m_pBGArm->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_pBGArm); - m_pBGArm = 0; - } - if (m_pFGLeg && m_pFGLeg->IsAttached()) - { - RemoveAttachable(m_pFGLeg); - m_pFGLeg->SetVel(m_Vel + m_pFGLeg->GetParentOffset() * PosRand()); - m_pFGLeg->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_pFGLeg); - m_pFGLeg = 0; - } - if (m_pBGLeg && m_pBGLeg->IsAttached()) - { - RemoveAttachable(m_pBGLeg); - m_pBGLeg->SetVel(m_Vel + m_pBGLeg->GetParentOffset() * PosRand()); - m_pBGLeg->SetAngularVel(NormalRand()); - g_MovableMan.AddParticle(m_pBGLeg); - m_pBGLeg = 0; - } - - Actor::GibThis(impactImpulse, internalBlast, pIgnoreMO); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: ResetAllTimers ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 208613fb3..5b9c0cf30 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -709,19 +709,6 @@ ClassInfoGetters MovableObject * LookForMOs(float FOVSpread = 45, unsigned char ignoreMaterial = 0, bool ignoreAllTerrain = false); -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetGraphicalIcon ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index 7a610d6fb..03e508f38 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -973,14 +973,14 @@ void Actor::DropAllInventory() // Description: Gibs this, effectively destroying it and creating multiple gibs or // pieces in its place. -void Actor::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) +void Actor::GibThis(const Vector &impactImpulse, MovableObject *movableObjectToIgnore) { // Play death sound // TODO: Don't attenuate since death is pretty important.. maybe only make this happen for teh brains m_DeathSound.Play(m_Pos); // Gib all the regular gibs - MOSRotating::GibThis(impactImpulse, internalBlast, pIgnoreMO); + MOSRotating::GibThis(impactImpulse, movableObjectToIgnore); if (g_SettingsMan.EnableCrabBombs()) { unsigned short crabCount = 0; @@ -1007,7 +1007,7 @@ void Actor::GibThis(const Vector &impactImpulse, float internalBlast, MovableObj pObject = *gItr; // Generate the velocities procedurally - velMin = internalBlast / pObject->GetMass(); + velMin = m_GibBlastStrength / pObject->GetMass(); velRange = 10.0f; // Randomize the offset from center to be within the original object @@ -1048,8 +1048,8 @@ void Actor::GibThis(const Vector &impactImpulse, float internalBlast, MovableObj pObject->ResetAllTimers(); // Set the gib to not hit a specific MO - if (pIgnoreMO) - pObject->SetWhichMOToNotHit(pIgnoreMO); + if (movableObjectToIgnore) + pObject->SetWhichMOToNotHit(movableObjectToIgnore); // Detect whether we're dealing with a passenger and add it as Actor instead if (pPassenger = dynamic_cast(pObject)) diff --git a/Entities/Actor.h b/Entities/Actor.h index 8d3ba633f..934e8a619 100644 --- a/Entities/Actor.h +++ b/Entities/Actor.h @@ -981,17 +981,13 @@ ClassInfoGetters void DrawWaypoints(bool drawWaypoints = true) { m_DrawWaypoints = drawWaypoints; } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; + /// + /// Destroys this MOSRotating and creates its specified Gibs in its place with appropriate velocities. + /// Any Attachables are removed and also given appropriate velocities. + /// + /// The impulse (kg * m/s) of the impact causing the gibbing to happen. + /// A pointer to an MO which the Gibs and Attachables should not be colliding with. + void GibThis(const Vector &impactImpulse = Vector(), MovableObject *movableObjectToIgnore = nullptr) override; ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index cbb334720..a1a605a2f 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -366,18 +366,6 @@ bool Arm::ConstrainHand() } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. - -void Arm::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { - DropEverything(); - Attachable::GibThis(impactImpulse, internalBlast, pIgnoreMO); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Update ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Arm.h b/Entities/Arm.h index 083222f28..c88732e39 100644 --- a/Entities/Arm.h +++ b/Entities/Arm.h @@ -347,19 +347,6 @@ ClassInfoGetters bool HoldsSomething() { return m_pHeldMO != 0; } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GibThis -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gibs this, effectively destroying it and creating multiple gibs or -// pieces in its place. -// Arguments: The impulse (kg * m/s) of the impact causing the gibbing to happen. -// The internal blast impulse which will push the gibs away from the center. -// A pointer to an MO which the gibs shuold not be colliding with! -// Return value: None. - - void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *pIgnoreMO = 0) override; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Update ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 005c82ece..85f8b3975 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -278,14 +278,14 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Attachable::GibThis(const Vector &impactImpulse, float internalBlast, MovableObject *pIgnoreMO) { - m_ToDelete = true; // Necessary to avoid oddities with breakwounds + void Attachable::GibThis(const Vector &impactImpulse, MovableObject *movableObjectToIgnore) { + m_ToDelete = true; // Note: ToDelete must be set to true ahead of time to avoid oddities with breakwounds if (m_Parent) { m_Parent->RemoveAttachable(this, true, true); } else { SetParent(nullptr); } - MOSRotating::GibThis(impactImpulse, internalBlast, pIgnoreMO); + MOSRotating::GibThis(impactImpulse, movableObjectToIgnore); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 246535916..e07ffb693 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -365,12 +365,12 @@ namespace RTE { bool ParticlePenetration(HitData &hitData) override; /// - /// Gibs this, effectively destroying it and creating gibs in its place. + /// Destroys this Attachable and creates its specified Gibs in its place with appropriate velocities. + /// Any Attachables are removed and also given appropriate velocities. /// /// The impulse (kg * m/s) of the impact causing the gibbing to happen. - /// The internal blast impulse which will push the gibs away from the center. - /// A pointer to an MO which the gibs should not be colliding with! - void GibThis(const Vector &impactImpulse = Vector(), float internalBlast = 10, MovableObject *MOToIgnore = 0) override; + /// A pointer to an MO which the Gibs and Attachables should not be colliding with. + virtual void GibThis(const Vector &impactImpulse = Vector(), MovableObject *movableObjectToIgnore = nullptr); /// /// Updates this Attachable. Supposed to be done every frame. diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index 371d53ffa..3218bd4a4 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -148,6 +148,7 @@ int HDFirearm::ReadProperty(std::string propName, Reader &reader) { m_pMagazine = dynamic_cast(magazineEntity->Clone()); AddAttachable(m_pMagazine); } + m_pMagazine->SetDeleteWhenRemovedFromParent(true); } else if (propName == "Flash") { RemoveAttachable(m_pFlash); const Entity *flashEntity = g_PresetMan.GetEntityPreset(reader); diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index 4a81d5ac8..1f7204eee 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -92,6 +92,9 @@ int HeldDevice::Create() else m_Loudness = 1.0; } + + // Make it so held devices are dropped when their parent gibs + m_ParentGibBlastStrengthMultiplier = 0.0F; // All HeldDevice:s by default avoid hitting and getting physically hit by AtomGoups when they are at rest m_IgnoresAGHitsWhenSlowerThan = 1.0; diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index 90a8809d0..fa685294c 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -80,6 +80,7 @@ namespace RTE { m_Foot = dynamic_cast(footEntity->Clone()); AddAttachable(m_Foot); m_Foot->SetInheritsRotAngle(false); + m_Foot->SetParentGibBlastStrengthMultiplier(0.0F); } } else if (propName == "ContractedOffset") { reader >> m_ContractedOffset; diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index b5bb770db..699d544a0 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -33,6 +33,7 @@ namespace RTE { m_MountedDevice = dynamic_cast(mountedDeviceEntity->Clone()); AddAttachable(m_MountedDevice); m_MountedDevice->SetInheritsRotAngle(false); + m_MountedDevice->SetDeleteWhenRemovedFromParent(true); } } else { return Attachable::ReadProperty(propName, reader); From 45b0f853dfa0564fa8a8fdbcb6b7bd6afb56692f Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 19 Sep 2020 03:15:57 -0300 Subject: [PATCH 052/144] Fixed DegreesToRadians and RadiansToDegrees so they're defined in the cpp file rather than the header cause RTETools isn't a class (oops) Added lua bindings for these functions --- Managers/LuaMan.cpp | 2 ++ System/RTETools.cpp | 8 ++++++++ System/RTETools.h | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index f08e80e08..75f26a6bd 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -2137,6 +2137,8 @@ int LuaMan::Create() def("GetMPP", &GetMPP), def("GetPPL", &GetPPL), def("GetLPP", &GetLPP), + def("DegreesToRadians", &DegreesToRadians), + def("RadiansToDegrees", &RadiansToDegrees), class_("InputDevice") .enum_("InputDevice")[ diff --git a/System/RTETools.cpp b/System/RTETools.cpp index 06d5f6b77..6bbab5e3c 100644 --- a/System/RTETools.cpp +++ b/System/RTETools.cpp @@ -134,6 +134,14 @@ namespace RTE { float GetAllegroAngle(float angleDegrees) { return (angleDegrees / 360) * 256; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + float DegreesToRadians(float angleInDegrees) { return angleInDegrees / c_PI * 180.0F; } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + float RadiansToDegrees(float angleInRadians) { return angleInRadians / 180.0F * c_PI; } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OpenBrowserToURL(std::string goToURL) { diff --git a/System/RTETools.h b/System/RTETools.h index b9358ec92..fd209acee 100644 --- a/System/RTETools.h +++ b/System/RTETools.h @@ -168,14 +168,14 @@ namespace RTE { /// /// The angle in degrees to be converted. /// The converted angle in radians. - float DegreesToRadians(float angleInDegrees) { return angleInDegrees / c_PI * 180.0F; } + float DegreesToRadians(float angleInDegrees); /// /// Returns the given angle converted from radians to degrees. /// /// The angle in radians to be converted. /// The converted angle in degrees. - float RadiansToDegrees(float angleInRadians) { return angleInRadians / 180.0F * c_PI; } + float RadiansToDegrees(float angleInRadians); #pragma endregion #pragma region Misc From c5429025fbe151f956fa5cb5fae4de49c50805cb Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 19 Sep 2020 04:53:16 -0300 Subject: [PATCH 053/144] Fixed a little bug in ADoor and removed a TODO that seems fine Fixed a removing setting magazine reference and a bug with magazine replacement when reloading in HDFirearm. Also fixed magazine deleting when removed Removed DegreesToRadians and RadiansToDegrees lua bindings, maxim reminded me that lua already has that built in Fixed some deletion ordering bugs in Attachable and some gib creation issues in MOSRotating GibThis --- Entities/ADoor.cpp | 4 +--- Entities/Attachable.cpp | 6 ++---- Entities/HDFirearm.cpp | 9 ++------- Entities/MOSRotating.cpp | 22 +++++++++++++++------- Managers/LuaMan.cpp | 2 -- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index 9ac6015da..e08b115d1 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -46,7 +46,6 @@ namespace RTE { int ADoor::Create(const ADoor &reference) { if (reference.m_Door) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_Door->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetDoor(attachable); }}); } - //TODO this was setting door parent offset to my closed offset, which is super weird. Test that doors are still cool. Old code was AddAttachable(m_Door, m_ClosedOffset, true); Actor::Create(reference); @@ -357,9 +356,8 @@ namespace RTE { Actor::Update(); - if (m_Door) { + if (!m_Door) { EraseDoorMaterial(); - m_Door = 0; // Start the spinning out of control animation for the motor, start it slow m_SpriteAnimDuration *= 4; } diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 85f8b3975..cebb424c3 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -199,8 +199,7 @@ namespace RTE { GibThis(); return false; } else if (m_JointStrength > 0 && totalImpulseForce.GetMagnitude() > m_JointStrength) { - jointImpulses += (totalImpulseForce.SetMagnitude(totalImpulseForce.GetMagnitude() - m_JointStiffness)) * m_JointStiffness; - m_Parent->RemoveAttachable(this, true, true); + jointImpulses += (totalImpulseForce.SetMagnitude(totalImpulseForce.GetMagnitude() - m_JointStrength)) * m_JointStiffness; return false; } else { jointImpulses += totalImpulseForce * m_JointStiffness; @@ -279,13 +278,12 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Attachable::GibThis(const Vector &impactImpulse, MovableObject *movableObjectToIgnore) { - m_ToDelete = true; // Note: ToDelete must be set to true ahead of time to avoid oddities with breakwounds + MOSRotating::GibThis(impactImpulse, movableObjectToIgnore); if (m_Parent) { m_Parent->RemoveAttachable(this, true, true); } else { SetParent(nullptr); } - MOSRotating::GibThis(impactImpulse, movableObjectToIgnore); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index 3218bd4a4..b3461b408 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -145,10 +145,10 @@ int HDFirearm::ReadProperty(std::string propName, Reader &reader) { RemoveAttachable(m_pMagazine); const Entity *magazineEntity = g_PresetMan.GetEntityPreset(reader); if (magazineEntity) { + m_pMagazineReference = dynamic_cast(magazineEntity); m_pMagazine = dynamic_cast(magazineEntity->Clone()); AddAttachable(m_pMagazine); } - m_pMagazine->SetDeleteWhenRemovedFromParent(true); } else if (propName == "Flash") { RemoveAttachable(m_pFlash); const Entity *flashEntity = g_PresetMan.GetEntityPreset(reader); @@ -591,12 +591,7 @@ void HDFirearm::Reload() { m_pMagazine->SetVel(m_Vel + Vector(m_HFlipped ? -3 : 3, 0.3)); m_pMagazine->SetAngularVel(6 + (-6 * PosRand())); - RemoveAttachable(m_pMagazine); - // Whether the magazine is ok to release into scene - if (m_pMagazine->IsDiscardable()) - g_MovableMan.AddParticle(m_pMagazine); - else - delete m_pMagazine; + RemoveAttachable(m_pMagazine, m_pMagazine->IsDiscardable(), false); m_pMagazine = 0; } diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index c72169d22..fbab0cf02 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1006,17 +1006,24 @@ void MOSRotating::CreateGibsWhenGibbing(const Vector &impactImpulse, MovableObje continue; } MovableObject *gibParticleClone = dynamic_cast(gibSettingsObject.GetParticlePreset()->Clone()); - gibParticleClone->SetRotAngle(GetRotAngle() + gibParticleClone->GetRotAngle()); - Vector rotatedGibOffset = RotateOffset(gibSettingsObject.GetOffset()); - gibParticleClone->SetPos(m_Pos + rotatedGibOffset); - float minVelocity = (gibSettingsObject.GetMinVelocity() == 0 && gibSettingsObject.GetMaxVelocity() == 0) ? m_GibBlastStrength / gibParticleClone->GetMass() : gibSettingsObject.GetMinVelocity(); - float velocityRange = (gibSettingsObject.GetMinVelocity() == 0 && gibSettingsObject.GetMaxVelocity() == 0) ? 10.0F : gibSettingsObject.GetMaxVelocity() - gibSettingsObject.GetMinVelocity(); + float minVelocity = gibSettingsObject.GetMinVelocity(); + float velocityRange = gibSettingsObject.GetMaxVelocity() - gibSettingsObject.GetMinVelocity(); + if (gibSettingsObject.GetMinVelocity() == 0 && gibSettingsObject.GetMaxVelocity() == 0) { + minVelocity = m_GibBlastStrength / gibParticleClone->GetMass(); + velocityRange = 10.0F; + } + Vector rotatedGibOffset = RotateOffset(gibSettingsObject.GetOffset()); for (int i = 0; i < gibSettingsObject.GetCount(); i++) { - if (i > 0) { gibParticleClone = dynamic_cast(gibParticleClone->Clone()); } + if (i > 0) { + gibParticleClone = dynamic_cast(gibSettingsObject.GetParticlePreset()->Clone()); + } - if (gibParticleClone->GetLifetime() != 0) { gibParticleClone->SetLifetime(gibParticleClone->GetLifetime() * static_cast((1.0F + gibSettingsObject.GetLifeVariation() * NormalRand()/*RandomNormalNum()*/))); } + if (gibParticleClone->GetLifetime() != 0) { + gibParticleClone->SetLifetime(static_cast(static_cast(gibParticleClone->GetLifetime()) * (1.0F + (gibSettingsObject.GetLifeVariation() * NormalRand()/*RandomNormalNum()*/)))); + } + gibParticleClone->SetRotAngle(GetRotAngle() + gibParticleClone->GetRotAngle()); gibParticleClone->SetAngularVel((gibParticleClone->GetAngularVel() * 0.35F) + (gibParticleClone->GetAngularVel() * 0.65F / gibParticleClone->GetMass()) * PosRand()/*RandomNum()*/); if (rotatedGibOffset.GetRoundIntX() > m_aSprite[0]->w / 3) { float offCenterRatio = rotatedGibOffset.m_X / (static_cast(m_aSprite[0]->w) / 2.0F); @@ -1026,6 +1033,7 @@ void MOSRotating::CreateGibsWhenGibbing(const Vector &impactImpulse, MovableObje gibParticleClone->SetAngularVel((gibParticleClone->GetAngularVel() * 0.5F + (gibParticleClone->GetAngularVel() * PosRand()/*RandomNum()*/)) * (NormalRand()/*RandomNormalNum()*/ > 0.0F ? 1.0F : -1.0F)); } + gibParticleClone->SetPos(m_Pos + rotatedGibOffset); Vector gibVelocity = rotatedGibOffset.SetMagnitude(minVelocity + (velocityRange * PosRand())).RadRotate(impactImpulse.GetAbsRadAngle() + gibSettingsObject.GetSpread() + NormalRand()); //Vector gibVelocity = rotatedGibOffset.SetMagnitude(minVelocity + RandomNum(0.0F, velocityRange)).RadRotate(impactImpulse.GetAbsRadAngle() + gib.GetSpread() + RandomNormalNum()); gibParticleClone->SetVel(gibVelocity + (gibSettingsObject.InheritsVelocity() ? m_Vel : Vector())); diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 75f26a6bd..f08e80e08 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -2137,8 +2137,6 @@ int LuaMan::Create() def("GetMPP", &GetMPP), def("GetPPL", &GetPPL), def("GetLPP", &GetLPP), - def("DegreesToRadians", &DegreesToRadians), - def("RadiansToDegrees", &RadiansToDegrees), class_("InputDevice") .enum_("InputDevice")[ From 25cfb70a0e896cd0e39f0a43917323778ed65b3c Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 19 Sep 2020 04:54:52 -0300 Subject: [PATCH 054/144] Added handling to fix draw order problems in ACrab and AHuman. Also solves the longstanding draw order issues in AHuman --- Entities/ACrab.cpp | 10 ++++++++++ Entities/AHuman.cpp | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index a6db999f0..1b9e7a73f 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -100,6 +100,16 @@ int ACrab::Create() if (Actor::Create() < 0) return -1; + if (m_IsOriginalPreset) { + Attachable *orderedAttachables[] = {m_pLBGLeg, m_pRBGLeg, m_pJetpack, m_pTurret, m_pLFGLeg, m_pRFGLeg}; + std::list attachablesCopy = m_Attachables; + m_Attachables.clear(); + std::copy_if(std::begin(orderedAttachables), std::end(orderedAttachables), std::back_inserter(m_Attachables), [](const Attachable *attachable) { return attachable != nullptr; }); + std::copy_if(attachablesCopy.begin(), attachablesCopy.end(), std::back_inserter(m_Attachables), [this](const Attachable *attachable) { + return (std::find(m_Attachables.begin(), m_Attachables.end(), attachable) == m_Attachables.end()); + }); + } + // Create the background paths copied from the foreground ones which were already read in for (int side = 0; side < SIDECOUNT; ++side) { diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 84aced79b..a85ebd524 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -104,6 +104,16 @@ int AHuman::Create() if (Actor::Create() < 0) return -1; + if (m_IsOriginalPreset) { + Attachable *orderedAttachables[] = {m_pBGArm, m_pBGLeg, m_pHead, m_pJetpack, m_pFGLeg, m_pFGArm}; + std::list attachablesCopy = m_Attachables; + m_Attachables.clear(); + std::copy_if(std::begin(orderedAttachables), std::end(orderedAttachables), std::back_inserter(m_Attachables), [](const Attachable *attachable) { return attachable != nullptr; }); + std::copy_if(attachablesCopy.begin(), attachablesCopy.end(), std::back_inserter(m_Attachables), [this](const Attachable *attachable) { + return (std::find(m_Attachables.begin(), m_Attachables.end(), attachable) == m_Attachables.end()); + }); + } + // Make the limb paths for the background limbs for (int i = 0; i < MOVEMENTSTATECOUNT; ++i) { From 010b2cad5514f25383ad9ec096554958539f6f71 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 19 Sep 2020 21:52:43 -0300 Subject: [PATCH 055/144] Added some reasonable checks before organizing atoms in parents for attadhables and made the passed in bool less obfuscated Made it so HeldDevices can never be set to delete when removed from their parent Added a missing safety check when firing grenades from HDFirearms Fixed some bad logic when removing attachables --- Entities/Attachable.cpp | 4 ++-- Entities/HDFirearm.cpp | 4 +++- Entities/HeldDevice.cpp | 5 ++++- Entities/HeldDevice.h | 6 ++++++ Entities/MOSRotating.cpp | 2 +- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index cebb424c3..c06e6c1a8 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -336,12 +336,12 @@ namespace RTE { ResetAllTimers(); m_Parent = newParent; - OrganizeAtomsInParent(newParent != nullptr); + if (m_CollidesWithTerrainWhileAttached) { OrganizeAtomsInParent(true); } } else { m_RootMOID = m_MOID; m_RestTimer.Reset(); - OrganizeAtomsInParent(newParent != nullptr); + if (m_CollidesWithTerrainWhileAttached) { OrganizeAtomsInParent(false); } m_Parent = newParent; } diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index b3461b408..bb7e34d87 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -783,7 +783,9 @@ void HDFirearm::Update() Attachable *pAttachable = dynamic_cast(pParticle); if (pAttachable) { - dynamic_cast(pAttachable->GetParent())->RemoveAttachable(pAttachable); + if (pAttachable->IsAttached()) { + dynamic_cast(pAttachable->GetParent())->RemoveAttachable(pAttachable); + } // Activate if it is some kind of grenade or whatnot. ThrownDevice *pTD = dynamic_cast(pAttachable); if (pTD) diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index 1f7204eee..1f90ee8fd 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -93,8 +93,11 @@ int HeldDevice::Create() m_Loudness = 1.0; } - // Make it so held devices are dropped when their parent gibs + // Make it so held devices are dropped gently when their parent gibs m_ParentGibBlastStrengthMultiplier = 0.0F; + + // Make it so users can't accidentally set this to true for HeldDevices, since it'll cause crashes when swapping inventory items around. + m_DeleteWhenRemovedFromParent = false; // All HeldDevice:s by default avoid hitting and getting physically hit by AtomGoups when they are at rest m_IgnoresAGHitsWhenSlowerThan = 1.0; diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index 12b90cd52..5aaef6d2a 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -530,6 +530,12 @@ ClassInfoGetters /// void ResetAllTimers() override { Attachable::ResetAllTimers(); m_ActivationTimer.Reset(); } + /// + /// Override to ensure that HeldDevices and their children can NOT be set to delete when removed from their parent as that causes problems when swapping inventory items around. + /// + /// Whether this Attachable should be deleted when it's removed from its parent. + void SetDeleteWhenRemovedFromParent(bool deleteWhenRemovedFromParent) final { m_DeleteWhenRemovedFromParent = false; } + ////////////////////////////////////////////////////////////////////////////////////////// // Protected member variable and method declarations diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index fbab0cf02..727ec4f93 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1599,7 +1599,7 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, } } } - if (!addToMovableMan || attachable->GetDeleteWhenRemovedFromParent()) { + if (!attachable->IsSetToDelete() && attachable->GetDeleteWhenRemovedFromParent()) { delete attachable; } else if (addToMovableMan || attachable->IsSetToDelete()) { g_MovableMan.AddMO(attachable); From 3c09e790ca606abab1741e683c110e1e1820e329 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 20 Sep 2020 00:42:35 -0300 Subject: [PATCH 056/144] Changed (once again) how hardcoded attachable setup is done, so that setting a new hardcoded attachable updates the unique ID - setter function map properly Readded set of reference hardcoded attachable unique IDs to facilitate this. It's now totally separate from the actual hardcoded attachable unique id - setter function map Modified ACrab, AHuman, ACDropship, ACRocket, ADoor, AEmitter, Arm, Turret, Leg, HDFirearm to account for these changes This change means that attachable ordering can be handled directly in an object's copy Create, so need to have special attachable ordering fixes in AHuman and ACrab Also cleaned up MOSR Create(reference) cause why not, and made it not unset attachables' parents cause Attachable does that now Missed making Attachabe::SetDeleteWhenRemovedFromParent virtual, also made Attachable cloning not copy parent cause that causes trouble and doesn't make sense anyway --- Entities/ACDropShip.cpp | 57 ++++++++++++++++++++++++++++------------ Entities/ACRocket.cpp | 42 ++++++++++++++++++++++++----- Entities/ACrab.cpp | 48 +++++++++++++++++++++------------ Entities/ADoor.cpp | 6 ++++- Entities/AEmitter.cpp | 6 ++++- Entities/AHuman.cpp | 47 ++++++++++++++++++++++----------- Entities/Arm.cpp | 19 ++++++++------ Entities/Attachable.cpp | 1 - Entities/Attachable.h | 2 +- Entities/HDFirearm.cpp | 12 +++++++-- Entities/Leg.cpp | 6 ++++- Entities/MOSRotating.cpp | 51 ++++++++++++++--------------------- Entities/MOSRotating.h | 3 ++- Entities/Turret.cpp | 6 ++++- 14 files changed, 201 insertions(+), 105 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 6420f8f97..b642aad61 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -71,13 +71,30 @@ int ACDropShip::Create() // Description: Creates a ACDropShip to be identical to another, by deep copy. int ACDropShip::Create(const ACDropShip &reference) { - if (reference.m_pRThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightThruster(attachable); }}); } - if (reference.m_pLThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftThruster(attachable); }}); } - if (reference.m_pURThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pURThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetURightThruster(attachable); }}); } - if (reference.m_pULThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pULThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetULeftThruster(attachable); }}); } - if (reference.m_pRHatch) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightHatch(attachable); }}); } - if (reference.m_pLHatch) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftHatch(attachable); }}); } - + if (reference.m_pRThruster) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRThruster->GetUniqueID()); + SetRightThruster(dynamic_cast(reference.m_pRThruster->Clone())); + } + if (reference.m_pLThruster) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLThruster->GetUniqueID()); + SetLeftThruster(dynamic_cast(reference.m_pLThruster->Clone())); + } + if (reference.m_pURThruster) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pURThruster->GetUniqueID()); + SetURightThruster(dynamic_cast(reference.m_pURThruster->Clone())); + } + if (reference.m_pULThruster) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pULThruster->GetUniqueID()); + SetULeftThruster(dynamic_cast(reference.m_pULThruster->Clone())); + } + if (reference.m_pRHatch) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRHatch->GetUniqueID()); + SetRightHatch(dynamic_cast(reference.m_pRHatch->Clone())); + } + if (reference.m_pLHatch) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLHatch->GetUniqueID()); + SetLeftHatch(dynamic_cast(reference.m_pLHatch->Clone())); + } ACraft::Create(reference); m_pBodyAG = dynamic_cast(reference.m_pBodyAG->Clone()); @@ -769,6 +786,7 @@ void ACDropShip::SetRightThruster(Attachable *newThruster) { RemoveAttachable(m_pRThruster); m_pRThruster = castedNewThruster; AddAttachable(castedNewThruster); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightThruster(attachable); }}); } } } @@ -785,6 +803,7 @@ void ACDropShip::SetLeftThruster(Attachable *newThruster) { RemoveAttachable(m_pLThruster); m_pLThruster = castedNewThruster; AddAttachable(castedNewThruster); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftThruster(attachable); }}); } } } @@ -801,6 +820,7 @@ void ACDropShip::SetURightThruster(Attachable *newThruster) { RemoveAttachable(m_pURThruster); m_pURThruster = castedNewThruster; AddAttachable(castedNewThruster); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetURightThruster(attachable); }}); } } } @@ -817,33 +837,36 @@ void ACDropShip::SetULeftThruster(Attachable *newThruster) { RemoveAttachable(m_pULThruster); m_pULThruster = castedNewThruster; AddAttachable(castedNewThruster); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetULeftThruster(attachable); }}); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACDropShip::SetLeftHatch(Attachable *newHatch) { +void ACDropShip::SetRightHatch(Attachable *newHatch) { if (newHatch == nullptr) { - if (m_pLHatch && m_pLHatch->IsAttachedTo(this)) { RemoveAttachable(m_pLHatch); } - m_pLHatch = nullptr; + if (m_pRHatch && m_pRHatch->IsAttachedTo(this)) { RemoveAttachable(m_pRHatch); } + m_pRHatch = nullptr; } else { - RemoveAttachable(m_pLHatch); - m_pLHatch = newHatch; + RemoveAttachable(m_pRHatch); + m_pRHatch = newHatch; AddAttachable(newHatch); + m_HardcodedAttachableUniqueIDsAndSetters.insert({newHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightHatch(attachable); }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACDropShip::SetRightHatch(Attachable *newHatch) { +void ACDropShip::SetLeftHatch(Attachable *newHatch) { if (newHatch == nullptr) { - if (m_pRHatch && m_pRHatch->IsAttachedTo(this)) { RemoveAttachable(m_pRHatch); } - m_pRHatch = nullptr; + if (m_pLHatch && m_pLHatch->IsAttachedTo(this)) { RemoveAttachable(m_pLHatch); } + m_pLHatch = nullptr; } else { - RemoveAttachable(m_pRHatch); - m_pRHatch = newHatch; + RemoveAttachable(m_pLHatch); + m_pLHatch = newHatch; AddAttachable(newHatch); + m_HardcodedAttachableUniqueIDsAndSetters.insert({newHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftHatch(attachable); }}); } } diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 9286e9b5b..14e2ccf0b 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -92,13 +92,34 @@ int ACRocket::Create() // Description: Creates a ACRocket to be identical to another, by deep copy. int ACRocket::Create(const ACRocket &reference) { - if (reference.m_pRLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightLeg(attachable); }}); } - if (reference.m_pLLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftLeg(attachable); }}); } - if (reference.m_pMThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pMThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMainThruster(attachable); }}); } - if (reference.m_pRThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightThruster(attachable); }}); } - if (reference.m_pLThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftThruster(attachable); }}); } - if (reference.m_pURThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pURThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetURightThruster(attachable); }}); } - if (reference.m_pULThruster) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pULThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetULeftThruster(attachable); }}); } + if (reference.m_pRLeg) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRLeg->GetUniqueID()); + SetRightLeg(dynamic_cast(reference.m_pRLeg->Clone())); + } + if (reference.m_pLLeg) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLLeg->GetUniqueID()); + SetLeftLeg(dynamic_cast(reference.m_pLLeg->Clone())); + } + if (reference.m_pMThruster) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pMThruster->GetUniqueID()); + SetMainThruster(dynamic_cast(reference.m_pMThruster->Clone())); + } + if (reference.m_pRThruster) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRThruster->GetUniqueID()); + SetRightThruster(dynamic_cast(reference.m_pRThruster->Clone())); + } + if (reference.m_pLThruster) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLThruster->GetUniqueID()); + SetLeftThruster(dynamic_cast(reference.m_pLThruster->Clone())); + } + if (reference.m_pURThruster) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pURThruster->GetUniqueID()); + SetURightThruster(dynamic_cast(reference.m_pURThruster->Clone())); + } + if (reference.m_pULThruster) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pULThruster->GetUniqueID()); + SetULeftThruster(dynamic_cast(reference.m_pULThruster->Clone())); + } ACraft::Create(reference); @@ -833,6 +854,7 @@ void ACRocket::SetRightLeg(Attachable *newLeg) { RemoveAttachable(m_pRLeg); m_pRLeg = castedNewLeg; AddAttachable(castedNewLeg); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightLeg(attachable); }}); } } } @@ -849,6 +871,7 @@ void ACRocket::SetLeftLeg(Attachable *newLeg) { RemoveAttachable(m_pLLeg); m_pLLeg = castedNewLeg; AddAttachable(castedNewLeg); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftLeg(attachable); }}); } } } @@ -865,6 +888,7 @@ void ACRocket::SetMainThruster(Attachable *newThruster) { RemoveAttachable(m_pMThruster); m_pMThruster = castedNewThruster; AddAttachable(castedNewThruster); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMainThruster(attachable); }}); } } } @@ -881,6 +905,7 @@ void ACRocket::SetRightThruster(Attachable *newThruster) { RemoveAttachable(m_pRThruster); m_pRThruster = castedNewThruster; AddAttachable(castedNewThruster); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightThruster(attachable); }}); } } } @@ -897,6 +922,7 @@ void ACRocket::SetLeftThruster(Attachable *newThruster) { RemoveAttachable(m_pLThruster); m_pLThruster = castedNewThruster; AddAttachable(castedNewThruster); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftThruster(attachable); }}); } } } @@ -913,6 +939,7 @@ void ACRocket::SetURightThruster(Attachable *newThruster) { RemoveAttachable(m_pURThruster); m_pURThruster = castedNewThruster; AddAttachable(castedNewThruster); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetURightThruster(attachable); }}); } } } @@ -929,6 +956,7 @@ void ACRocket::SetULeftThruster(Attachable *newThruster) { RemoveAttachable(m_pULThruster); m_pULThruster = castedNewThruster; AddAttachable(castedNewThruster); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetULeftThruster(attachable); }}); } } } diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 1b9e7a73f..83eddf682 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -100,16 +100,6 @@ int ACrab::Create() if (Actor::Create() < 0) return -1; - if (m_IsOriginalPreset) { - Attachable *orderedAttachables[] = {m_pLBGLeg, m_pRBGLeg, m_pJetpack, m_pTurret, m_pLFGLeg, m_pRFGLeg}; - std::list attachablesCopy = m_Attachables; - m_Attachables.clear(); - std::copy_if(std::begin(orderedAttachables), std::end(orderedAttachables), std::back_inserter(m_Attachables), [](const Attachable *attachable) { return attachable != nullptr; }); - std::copy_if(attachablesCopy.begin(), attachablesCopy.end(), std::back_inserter(m_Attachables), [this](const Attachable *attachable) { - return (std::find(m_Attachables.begin(), m_Attachables.end(), attachable) == m_Attachables.end()); - }); - } - // Create the background paths copied from the foreground ones which were already read in for (int side = 0; side < SIDECOUNT; ++side) { @@ -172,13 +162,31 @@ int ACrab::Create(BITMAP *pSprite, // Description: Creates a ACrab to be identical to another, by deep copy. int ACrab::Create(const ACrab &reference) { - if (reference.m_pTurret) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pTurret->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetTurret(attachable); }}); } - if (reference.m_pJetpack) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetJetpack(attachable); }}); } - if (reference.m_pLFGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLFGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftFGLeg(attachable); }}); } - if (reference.m_pRFGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRFGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightFGLeg(attachable); }}); } - if (reference.m_pLBGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pLBGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftBGLeg(attachable); }}); } - if (reference.m_pRBGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pRBGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightBGLeg(attachable); }}); } - + //Note - hardcoded attachable copying is organized based on desired draw order here. + if (reference.m_pLBGLeg) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLBGLeg->GetUniqueID()); + SetLeftBGLeg(dynamic_cast(reference.m_pLBGLeg->Clone())); + } + if (reference.m_pRBGLeg) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRBGLeg->GetUniqueID()); + SetRightBGLeg(dynamic_cast(reference.m_pRBGLeg->Clone())); + } + if (reference.m_pJetpack) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pJetpack->GetUniqueID()); + SetJetpack(dynamic_cast(reference.m_pJetpack->Clone())); + } + if (reference.m_pTurret) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pTurret->GetUniqueID()); + SetTurret(dynamic_cast(reference.m_pTurret->Clone())); + } + if (reference.m_pLFGLeg) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLFGLeg->GetUniqueID()); + SetLeftFGLeg(dynamic_cast(reference.m_pLFGLeg->Clone())); + } + if (reference.m_pRFGLeg) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRFGLeg->GetUniqueID()); + SetRightFGLeg(dynamic_cast(reference.m_pRFGLeg->Clone())); + } Actor::Create(reference); m_JetTimeTotal = reference.m_JetTimeTotal; @@ -499,6 +507,7 @@ void ACrab::SetTurret(Attachable *newTurret) { RemoveAttachable(m_pTurret); m_pTurret = castedNewTurret; AddAttachable(castedNewTurret); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewTurret->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetTurret(attachable); }}); } } } @@ -515,6 +524,7 @@ void ACrab::SetJetpack(Attachable *newJetpack) { RemoveAttachable(m_pJetpack); m_pJetpack = castedNewJetpack; AddAttachable(castedNewJetpack); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetJetpack(attachable); }}); } } } @@ -531,6 +541,7 @@ void ACrab::SetLeftFGLeg(Attachable *newLeg) { RemoveAttachable(m_pLFGLeg); m_pLFGLeg = castedNewLeg; AddAttachable(castedNewLeg); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftFGLeg(attachable); }}); } } } @@ -547,6 +558,7 @@ void ACrab::SetLeftBGLeg(Attachable *newLeg) { RemoveAttachable(m_pLBGLeg); m_pLBGLeg = castedNewLeg; AddAttachable(castedNewLeg); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftBGLeg(attachable); }}); } } } @@ -563,6 +575,7 @@ void ACrab::SetRightFGLeg(Attachable *newLeg) { RemoveAttachable(m_pRFGLeg); m_pRFGLeg = castedNewLeg; AddAttachable(castedNewLeg); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightFGLeg(attachable); }}); } } } @@ -579,6 +592,7 @@ void ACrab::SetRightBGLeg(Attachable *newLeg) { RemoveAttachable(m_pRBGLeg); m_pRBGLeg = castedNewLeg; AddAttachable(castedNewLeg); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightBGLeg(attachable); }}); } } } diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index e08b115d1..bfafb18b9 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -45,7 +45,10 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int ADoor::Create(const ADoor &reference) { - if (reference.m_Door) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_Door->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetDoor(attachable); }}); } + if (reference.m_Door) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_Door->GetUniqueID()); + SetDoor(dynamic_cast(reference.m_Door->Clone())); + } Actor::Create(reference); @@ -208,6 +211,7 @@ namespace RTE { RemoveAttachable(m_Door); m_Door = newDoor; AddAttachable(newDoor); + m_HardcodedAttachableUniqueIDsAndSetters.insert({newDoor->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetDoor(attachable); }}); } } diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index f256cd765..41e70d0dd 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -69,7 +69,10 @@ void AEmitter::Clear() // Description: Creates a AEmitter to be identical to another, by deep copy. int AEmitter::Create(const AEmitter &reference) { - if (reference.m_pFlash) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFlash(attachable); }}); } + if (reference.m_pFlash) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pFlash->GetUniqueID()); + SetFlash(dynamic_cast(reference.m_pFlash->Clone())); + } Attachable::Create(reference); for (list::const_iterator itr = reference.m_EmissionList.begin(); itr != reference.m_EmissionList.end(); ++itr) { @@ -376,6 +379,7 @@ void AEmitter::SetFlash(Attachable *newFlash) { RemoveAttachable(m_pFlash); m_pFlash = newFlash; AddAttachable(newFlash); + m_HardcodedAttachableUniqueIDsAndSetters.insert({newFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFlash(attachable); }}); } } diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index a85ebd524..b76c3b91b 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -104,16 +104,6 @@ int AHuman::Create() if (Actor::Create() < 0) return -1; - if (m_IsOriginalPreset) { - Attachable *orderedAttachables[] = {m_pBGArm, m_pBGLeg, m_pHead, m_pJetpack, m_pFGLeg, m_pFGArm}; - std::list attachablesCopy = m_Attachables; - m_Attachables.clear(); - std::copy_if(std::begin(orderedAttachables), std::end(orderedAttachables), std::back_inserter(m_Attachables), [](const Attachable *attachable) { return attachable != nullptr; }); - std::copy_if(attachablesCopy.begin(), attachablesCopy.end(), std::back_inserter(m_Attachables), [this](const Attachable *attachable) { - return (std::find(m_Attachables.begin(), m_Attachables.end(), attachable) == m_Attachables.end()); - }); - } - // Make the limb paths for the background limbs for (int i = 0; i < MOVEMENTSTATECOUNT; ++i) { @@ -148,12 +138,31 @@ int AHuman::Create() // Description: Creates a AHuman to be identical to another, by deep copy. int AHuman::Create(const AHuman &reference) { - if (reference.m_pHead) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pHead->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetHead(attachable); }}); } - if (reference.m_pJetpack) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetJetpack(attachable); }}); } - if (reference.m_pFGArm) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pFGArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFGArm(attachable); }}); } - if (reference.m_pBGArm) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pBGArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetBGArm(attachable); }}); } - if (reference.m_pFGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pFGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFGLeg(attachable); }}); } - if (reference.m_pBGLeg) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pBGLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetBGLeg(attachable); }}); } + //Note - hardcoded attachable copying is organized based on desired draw order here. + if (reference.m_pBGArm) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pBGArm->GetUniqueID()); + SetBGArm(dynamic_cast(reference.m_pBGArm->Clone())); + } + if (reference.m_pBGLeg) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pBGLeg->GetUniqueID()); + SetBGLeg(dynamic_cast(reference.m_pBGLeg->Clone())); + } + if (reference.m_pJetpack) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pJetpack->GetUniqueID()); + SetJetpack(dynamic_cast(reference.m_pJetpack->Clone())); + } + if (reference.m_pHead) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pHead->GetUniqueID()); + SetHead(dynamic_cast(reference.m_pHead->Clone())); + } + if (reference.m_pFGLeg) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pFGLeg->GetUniqueID()); + SetFGLeg(dynamic_cast(reference.m_pFGLeg->Clone())); + } + if (reference.m_pFGArm) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pFGArm->GetUniqueID()); + SetFGArm(dynamic_cast(reference.m_pFGArm->Clone())); + } Actor::Create(reference); m_ThrowPrepTime = reference.m_ThrowPrepTime; @@ -476,6 +485,7 @@ void AHuman::SetHead(Attachable *newHead) { RemoveAttachable(m_pHead); m_pHead = newHead; AddAttachable(newHead); + m_HardcodedAttachableUniqueIDsAndSetters.insert({newHead->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetHead(attachable); }}); } } @@ -491,6 +501,7 @@ void AHuman::SetJetpack(Attachable *newJetpack) { RemoveAttachable(m_pJetpack); m_pJetpack = castedNewJetpack; AddAttachable(castedNewJetpack); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetJetpack(attachable); }}); } } } @@ -507,6 +518,7 @@ void AHuman::SetFGArm(Attachable *newArm) { RemoveAttachable(m_pFGArm); m_pFGArm = castedNewArm; AddAttachable(castedNewArm); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFGArm(attachable); }}); } } } @@ -523,6 +535,7 @@ void AHuman::SetBGArm(Attachable *newArm) { RemoveAttachable(m_pBGArm); m_pBGArm = castedNewArm; AddAttachable(castedNewArm); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetBGArm(attachable); }}); } } } @@ -539,6 +552,7 @@ void AHuman::SetFGLeg(Attachable *newLeg) { RemoveAttachable(m_pFGLeg); m_pFGLeg = castedNewLeg; AddAttachable(castedNewLeg); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFGLeg(attachable); }}); } } } @@ -555,6 +569,7 @@ void AHuman::SetBGLeg(Attachable *newLeg) { RemoveAttachable(m_pBGLeg); m_pBGLeg = castedNewLeg; AddAttachable(castedNewLeg); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetBGLeg(attachable); }}); } } } diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index a1a605a2f..c0e869c3c 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -66,7 +66,10 @@ int Arm::Create() { // Description: Creates a Arm to be identical to another, by deep copy. int Arm::Create(const Arm &reference) { - if (reference.m_pHeldMO) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pHeldMO->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetHeldMO(attachable); }}); } + if (reference.m_pHeldMO) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pHeldMO->GetUniqueID()); + SetHeldMO(dynamic_cast(reference.m_pHeldMO->Clone())); + } Attachable::Create(reference); m_HandFile = reference.m_HandFile; @@ -196,21 +199,21 @@ void Arm::SetHeldMO(MovableObject *newHeldMO) { } else { //TODO All this needs cleaning up, it should work just like all other hardcoded attachable setters and rely on RemoveAttachable to add it to MovableMan, etc. if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && dynamic_cast(m_pHeldMO)->IsAttachedTo(this)) { - HeldDevice *pHeldDev = dynamic_cast(m_pHeldMO); - if (pHeldDev->IsAttached()) { dynamic_cast(pHeldDev->GetParent())->RemoveAttachable(pHeldDev); } + HeldDevice *oldHeldDevice = dynamic_cast(m_pHeldMO); + if (oldHeldDevice->IsAttached()) { dynamic_cast(oldHeldDevice->GetParent())->RemoveAttachable(oldHeldDevice, true, false); } // TODO: Refine throwing force to dropped device here?") pHeldDev->SetVel(Vector(10 * PosRand(), -15 * PosRand())); pHeldDev->SetAngularVel(-10 * PosRand()); g_MovableMan.AddItem(pHeldDev); m_pHeldMO = pHeldDev = 0; + m_pHeldMO = nullptr; } if (newHeldMO && (newHeldMO->IsHeldDevice() || newHeldMO->IsThrownDevice())) { - Attachable *pNewDev = dynamic_cast(newHeldMO); - if (pNewDev->IsAttached()) { dynamic_cast(pNewDev->GetParent())->RemoveAttachable(pNewDev); } - AddAttachable(pNewDev); - pNewDev->SetTeam(m_Team); - pNewDev = 0; + Attachable *newHeldDevice = dynamic_cast(newHeldMO); + if (newHeldDevice->IsAttached()) { dynamic_cast(newHeldDevice->GetParent())->RemoveAttachable(newHeldDevice); } + AddAttachable(newHeldDevice); + m_HardcodedAttachableUniqueIDsAndSetters.insert({newHeldDevice->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetHeldMO(attachable); }}); } m_pHeldMO = newHeldMO; } diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index c06e6c1a8..8d9d45e58 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -54,7 +54,6 @@ namespace RTE { int Attachable::Create(const Attachable &reference) { MOSRotating::Create(reference); - m_Parent = reference.m_Parent; m_ParentOffset = reference.m_ParentOffset; m_DrawAfterParent = reference.m_DrawAfterParent; m_DrawnNormallyByParent = reference.m_DrawnNormallyByParent; diff --git a/Entities/Attachable.h b/Entities/Attachable.h index e07ffb693..d438eb04e 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -144,7 +144,7 @@ namespace RTE { /// Sets whether this Attachable will be deleted when it's removed from its parent. /// /// Whether this Attachable should be deleted when it's removed from its parent. - void SetDeleteWhenRemovedFromParent(bool deleteWhenRemovedFromParent) { m_DeleteWhenRemovedFromParent = deleteWhenRemovedFromParent; } + virtual void SetDeleteWhenRemovedFromParent(bool deleteWhenRemovedFromParent) { m_DeleteWhenRemovedFromParent = deleteWhenRemovedFromParent; } /// /// Gets whether forces transferred from this Attachable should be applied at its parent's offset (rotated to match the parent) where they will produce torque, or directly at its parent's position. diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index bb7e34d87..ae7d8514b 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -96,8 +96,14 @@ int HDFirearm::Create() // Description: Creates a HDFirearm to be identical to another, by deep copy. int HDFirearm::Create(const HDFirearm &reference) { - if (reference.m_pMagazine) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pMagazine->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMagazine(attachable); }}); } - if (reference.m_pFlash) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_pFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFlash(attachable); }}); } + if (reference.m_pMagazine) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pMagazine->GetUniqueID()); + SetMagazine(dynamic_cast(reference.m_pMagazine->Clone())); + } + if (reference.m_pFlash) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pFlash->GetUniqueID()); + SetFlash(dynamic_cast(reference.m_pFlash->Clone())); + } HeldDevice::Create(reference); m_pMagazineReference = reference.m_pMagazineReference; @@ -307,6 +313,7 @@ void HDFirearm::SetMagazine(Attachable *newMagazine) { RemoveAttachable(m_pMagazine); m_pMagazine = castedNewMagazine; AddAttachable(castedNewMagazine); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewMagazine->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMagazine(attachable); }}); } } } @@ -321,6 +328,7 @@ void HDFirearm::SetFlash(Attachable *newFlash) { RemoveAttachable(m_pFlash); m_pFlash = newFlash; AddAttachable(newFlash); + m_HardcodedAttachableUniqueIDsAndSetters.insert({newFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFlash(attachable); }}); } } diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index fa685294c..42955d134 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -49,7 +49,10 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int Leg::Create(const Leg &reference) { - if (reference.m_Foot) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_Foot->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFoot(attachable); }}); } + if (reference.m_Foot) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_Foot->GetUniqueID()); + SetFoot(dynamic_cast(reference.m_Foot->Clone())); + } Attachable::Create(reference); m_ContractedOffset = reference.m_ContractedOffset; @@ -132,6 +135,7 @@ namespace RTE { RemoveAttachable(m_Foot); m_Foot = newFoot; AddAttachable(newFoot); + m_HardcodedAttachableUniqueIDsAndSetters.insert({newFoot->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFoot(attachable); }}); } } diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 727ec4f93..cfc54d378 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -62,6 +62,7 @@ void MOSRotating::Clear() m_RecoilOffset.Reset(); m_Wounds.clear(); m_Attachables.clear(); + m_ReferenceHardcodedAttachableUniqueIDs.clear(); m_HardcodedAttachableUniqueIDsAndSetters.clear(); m_Gibs.clear(); m_GibImpulseLimit = 0; @@ -207,26 +208,21 @@ int MOSRotating::Create(ContentFile spriteFile, ////////////////////////////////////////////////////////////////////////////////////////// // Description: Creates a MOSRotating to be identical to another, by deep copy. -int MOSRotating::Create(const MOSRotating &reference) -{ +int MOSRotating::Create(const MOSRotating &reference) { MOSprite::Create(reference); - if (!reference.m_pAtomGroup) + if (!reference.m_pAtomGroup) { return -1; + } - { - // THESE ATOMGROUP COPYING ARE A TIME SINK! - m_pAtomGroup = new AtomGroup(); - m_pAtomGroup->Create(*reference.m_pAtomGroup, true); - if (m_pAtomGroup) - m_pAtomGroup->SetOwner(this); + // THESE ATOMGROUP COPYING ARE A TIME SINK! + m_pAtomGroup = new AtomGroup(); + m_pAtomGroup->Create(*reference.m_pAtomGroup, true); + if (m_pAtomGroup) { m_pAtomGroup->SetOwner(this); } - if (reference.m_pDeepGroup) - { - m_pDeepGroup = dynamic_cast(reference.m_pDeepGroup->Clone()); - if (m_pDeepGroup) - m_pDeepGroup->SetOwner(this); - } + if (reference.m_pDeepGroup) { + m_pDeepGroup = dynamic_cast(reference.m_pDeepGroup->Clone()); + if (m_pDeepGroup) { m_pDeepGroup->SetOwner(this); } } m_DeepCheck = reference.m_DeepCheck; @@ -237,28 +233,18 @@ int MOSRotating::Create(const MOSRotating &reference) m_RecoilForce = reference.m_RecoilForce; m_RecoilOffset = reference.m_RecoilOffset; - // Wound emitter copies - for (AEmitter *wound : reference.m_Wounds) { - AddWound(dynamic_cast(wound), wound->GetParentOffset()); + for (const AEmitter *wound : reference.m_Wounds) { + AddWound(dynamic_cast(wound->Clone()), wound->GetParentOffset(), false); } - // Attachable copies - Attachable *newAttachable; for (const Attachable *referenceAttachable : reference.m_Attachables) { - newAttachable = dynamic_cast(referenceAttachable->Clone()); - newAttachable->m_Parent = nullptr; - - std::unordered_map>::iterator hardcodedAttachableMapEntry = m_HardcodedAttachableUniqueIDsAndSetters.find(referenceAttachable->GetUniqueID()); - if (hardcodedAttachableMapEntry != m_HardcodedAttachableUniqueIDsAndSetters.end()) { - (*hardcodedAttachableMapEntry).second(this, newAttachable); - m_HardcodedAttachableUniqueIDsAndSetters.insert({newAttachable->GetUniqueID(), hardcodedAttachableMapEntry->second}); - m_HardcodedAttachableUniqueIDsAndSetters.erase(hardcodedAttachableMapEntry); - } else { + if (m_ReferenceHardcodedAttachableUniqueIDs.find(referenceAttachable->GetUniqueID()) == m_ReferenceHardcodedAttachableUniqueIDs.end()) { + Attachable *newAttachable = dynamic_cast(referenceAttachable->Clone()); AddAttachable(newAttachable); } } + m_ReferenceHardcodedAttachableUniqueIDs.clear(); - // Gib copies for (const Gib &gib : reference.m_Gibs) { m_Gibs.push_back(gib); } @@ -1579,7 +1565,10 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, attachable->SetParent(nullptr); std::unordered_map>::iterator hardcodedAttachableMapEntry = m_HardcodedAttachableUniqueIDsAndSetters.find(attachable->GetUniqueID()); - if (hardcodedAttachableMapEntry != m_HardcodedAttachableUniqueIDsAndSetters.end()) { hardcodedAttachableMapEntry->second(this, nullptr); } + if (hardcodedAttachableMapEntry != m_HardcodedAttachableUniqueIDsAndSetters.end()) { + hardcodedAttachableMapEntry->second(this, nullptr); + m_HardcodedAttachableUniqueIDsAndSetters.erase(hardcodedAttachableMapEntry); + } if (addBreakWounds) { if (!m_ToDelete && attachable->GetParentBreakWound()) { diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index da90376f7..756e9ae49 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -869,7 +869,8 @@ ClassInfoGetters std::list m_Wounds; // The list of Attachables currently attached and Owned by this. std::list m_Attachables; - std::unordered_map> m_HardcodedAttachableUniqueIDsAndSetters; //!< An unordered map of Unique IDs to setter lambda functions, used to properly set member pointers for hardcoded Attachables (i.e. head, legs, etc.) when cloning. + std::unordered_set m_ReferenceHardcodedAttachableUniqueIDs; //!< An unordered set is filled with the Unique IDs of all of the reference object's hardcoded Attachables when using the copy Create. + std::unordered_map> m_HardcodedAttachableUniqueIDsAndSetters; //!< An unordered map of Unique IDs to setter lambda functions, used to call the appropriate hardcoded Attachable setter when a hardcoded Attachable is removed. // The list of Gib:s this will create when gibbed std::list m_Gibs; // The amount of impulse force required to gib this, in kg * (m/s). 0 means no limit diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index 699d544a0..7551b914f 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -15,7 +15,10 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int Turret::Create(const Turret &reference) { - if (reference.m_MountedDevice) { m_HardcodedAttachableUniqueIDsAndSetters.insert({reference.m_MountedDevice->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMountedDevice(attachable); }}); } + if (reference.m_MountedDevice) { + m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_MountedDevice->GetUniqueID()); + SetMountedDevice(dynamic_cast(reference.m_MountedDevice->Clone())); + } Attachable::Create(reference); m_MountedDeviceRotOffset = reference.m_MountedDeviceRotOffset; @@ -65,6 +68,7 @@ namespace RTE { RemoveAttachable(m_MountedDevice); m_MountedDevice = castedNewMountedDevice; AddAttachable(castedNewMountedDevice); + m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewMountedDevice->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMountedDevice(attachable); }}); } } } From d5000a1a5de89d66f11f78280ea8386634f574f0 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 20 Sep 2020 04:01:02 -0300 Subject: [PATCH 057/144] Fixed a longstanding bug wherein forces transferred from Attachables weren't accounting for distances being in meters; quite a big deal, really. Added some extra safety checking to RemoveAttachable and an RTEAbort for bizarre situations when transferring forces from attachables Added early return to Attachable force transferral to save some calculations, and made it so force transferred is the gib impulse limit or joint strength, as it was before, since that's more correct than what I had changed it to Cleaned up some Attachable header comments --- Entities/Attachable.cpp | 11 +++++++++-- Entities/Attachable.h | 18 ++++++++---------- Entities/MOSRotating.cpp | 14 +++++--------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 8d9d45e58..b9cf3c0ac 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -170,6 +170,9 @@ namespace RTE { if (!m_Parent) { return false; } + if (m_Forces.empty()) { + return true; + } Vector totalForce; for (const std::pair &force : m_Forces) { @@ -187,6 +190,9 @@ namespace RTE { if (!m_Parent) { return false; } + if (m_ImpulseForces.empty()) { + return true; + } Vector totalImpulseForce; for (const std::pair &impulseForce : m_ImpulseForces) { @@ -194,11 +200,12 @@ namespace RTE { } if (m_GibImpulseLimit > 0 && totalImpulseForce.GetMagnitude() > m_GibImpulseLimit) { - jointImpulses += (totalImpulseForce.SetMagnitude(totalImpulseForce.GetMagnitude() - m_GibImpulseLimit)) * m_JointStiffness; + jointImpulses += (totalImpulseForce.SetMagnitude(m_GibImpulseLimit)) * m_JointStiffness; GibThis(); return false; } else if (m_JointStrength > 0 && totalImpulseForce.GetMagnitude() > m_JointStrength) { - jointImpulses += (totalImpulseForce.SetMagnitude(totalImpulseForce.GetMagnitude() - m_JointStrength)) * m_JointStiffness; + jointImpulses += (totalImpulseForce.SetMagnitude(m_JointStrength)) * m_JointStiffness; + m_Parent->RemoveAttachable(this, true, true); return false; } else { jointImpulses += totalImpulseForce * m_JointStiffness; diff --git a/Entities/Attachable.h b/Entities/Attachable.h index d438eb04e..b4b2e943b 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -173,7 +173,7 @@ namespace RTE { void SetGibWithParentChance(float gibWithParentChance) { m_GibWithParentChance = gibWithParentChance; } /// - /// Gets the multiplier this Attacahble will apply to its parent's gib blast strength when the parent gibs. + /// Gets the multiplier this Attachable will apply to its parent's gib blast strength when the parent gibs. /// /// A float with the gib blast strength multiplier of this Attachable. float GetParentGibBlastStrengthMultiplier() const { return m_ParentGibBlastStrengthMultiplier; } @@ -228,22 +228,20 @@ namespace RTE { #pragma region Force Transferral /// /// Bundles up all the accumulated forces of this Attachable and calculates how they transfer to the joint, and therefore to the parent. + /// If the accumulated forces exceed the joint strength of this Attachable, the jointForces Vector will be filled to the limit and false will be returned. + /// Additionally, in this case, the Attachable will remove itself from its parent. /// /// A vector that will have the forces affecting the joint ADDED to it. - /// - /// If the accumulated forces exceed the strength of the joint, the attachable will only fill out the forces up to the strength threshold and then detach itself and return false. - /// The parent should react accordingly in that case, by nulling out pointers to the Attachable. - /// + /// False if the Attachable has no parent or its accumulated forces are greater than its joint strength, otherwise true. bool TransferJointForces(Vector &jointForces); /// /// Bundles up all the accumulated impulse forces of this Attachable and calculates how they transfer to the joint, and therefore to the parent. + /// If the accumulated impulse forces exceed the joint strength or gib impulse limit of this Attachable, the jointImpulses Vector will be filled up to that limit and false will be returned. + /// Additionally, in this case, the Attachable will remove itself from its parent and gib itself if appropriate. /// - /// A vector that will have with the impulse forces affecting the joint ADDED to it. - /// - /// If the accumulated impulse forces exceed the strength of the joint, the attachable will only fill out the forces up to the strength threshold and then detach itself and return false. - /// The parent should react accordingly in that case, by nulling out pointers to the Attachable. - /// + /// A vector that will have the impulse forces affecting the joint ADDED to it. + /// False if the Attachable has no parent or its accumulated forces are greater than its joint strength or gib impulse limit, otherwise true. bool TransferJointImpulses(Vector &jointImpulses); #pragma endregion diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index cfc54d378..835aa6ab2 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1553,13 +1553,10 @@ bool MOSRotating::RemoveAttachable(long attachableUniqueID, bool addToMovableMan bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, bool addBreakWounds) { - if (!attachable) { + if (!attachable || !attachable->IsAttached()) { return false; } - RTEAssert(!attachable->IsAttached() || attachable->IsAttachedTo(this), "Tried to remove attachable that was attached to another parent (" + (attachable->GetParent() ? attachable->GetParent()->GetModuleAndPresetName() : "ERROR") + ") Attachable (" + attachable->GetModuleAndPresetName() + "), this should never happen!"); - if (!attachable->IsAttached()) { - int a = 0; - } + RTEAssert(attachable->IsAttachedTo(this), "Tried to remove attachable that was attached to another parent (" + (attachable->GetParent() ? attachable->GetParent()->GetModuleAndPresetName() : "ERROR") + ") Attachable (" + attachable->GetModuleAndPresetName() + "), this should never happen!"); if (m_Attachables.size() > 0) { m_Attachables.remove(attachable); } attachable->SetParent(nullptr); @@ -1886,14 +1883,13 @@ bool MOSRotating::TransferForcesFromAttachable(Attachable *attachable) { intact = attachable->TransferJointForces(forces) && attachable->TransferJointImpulses(impulses); if (!forces.IsZero()) { - AddForce(forces, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation : Vector()); + AddForce(forces, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation * c_MPP : Vector()); } if (!impulses.IsZero()) { - AddImpulseForce(impulses, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation : Vector()); + AddImpulseForce(impulses, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation * c_MPP : Vector()); } - if (!intact) { RemoveAttachable(attachable, true, true); } } else { - RemoveAttachable(attachable); + RTEAbort("Tried to transfer forces from a Non-Attached, Non-Deleting Attachable " + attachable->GetModuleAndPresetName() + ". This should never happen!"); } } return intact; From bb6f4cbe46147563a6ec5bf7a9e9b54f7533d5f7 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 20 Sep 2020 23:36:23 -0300 Subject: [PATCH 058/144] Added GripStrength property to Arm and GripStrengthMultiplier property to HeldDevice Made TransferJointImpulses virtual and added override parameter handling to it to support more functionality. Uses this to override it in HeldDevice so it uses GripStrength and GripStrengthMultiplier. Made HDFirearm recoil transmission INI and Lua setters actually just set JointStiffness Modified lua bindings to match these changes --- Entities/Arm.cpp | 6 ++++++ Entities/Arm.h | 13 +++++++++++++ Entities/Attachable.cpp | 17 ++++++++++------- Entities/Attachable.h | 5 ++++- Entities/HDFirearm.cpp | 8 +++----- Entities/HDFirearm.h | 23 ----------------------- Entities/HeldDevice.cpp | 28 +++++++++++++++++++++++++++- Entities/HeldDevice.h | 28 ++++++++++++++++++++++++++++ Entities/Turret.cpp | 12 +----------- Managers/LuaMan.cpp | 4 +++- 10 files changed, 95 insertions(+), 49 deletions(-) diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index c0e869c3c..19fc0925f 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -31,6 +31,7 @@ void Arm::Clear() { // m_HandOffset.Reset(); m_pHeldMO = 0; + m_GripStrength = 0; m_HandFile.Reset(); m_pHand = 0; m_MaxLength = 0; @@ -72,6 +73,7 @@ int Arm::Create(const Arm &reference) { } Attachable::Create(reference); + m_GripStrength = reference.m_GripStrength; m_HandFile = reference.m_HandFile; m_pHand = m_HandFile.GetAsBitmap(); RTEAssert(m_pHand, "Failed to load hand bitmap in Arm::Create") @@ -102,6 +104,8 @@ int Arm::ReadProperty(std::string propName, Reader &reader) { m_pHeldMO = dynamic_cast(heldDeviceEntity->Clone()); AddAttachable(dynamic_cast(m_pHeldMO)); } + } else if (propName == "GripStrength") { + reader >> m_GripStrength; } else if (propName == "Hand") { reader >> m_HandFile; m_pHand = m_HandFile.GetAsBitmap(); @@ -133,6 +137,8 @@ int Arm::Save(Writer &writer) const writer.NewProperty("HeldDevice"); writer << m_pHeldMO; + writer.NewProperty("GripStrength"); + writer << m_GripStrength; writer.NewProperty("HandGroup"); writer << m_HandFile; writer.NewProperty("MaxLength"); diff --git a/Entities/Arm.h b/Entities/Arm.h index c88732e39..4e96749fb 100644 --- a/Entities/Arm.h +++ b/Entities/Arm.h @@ -170,6 +170,18 @@ ClassInfoGetters MovableObject * GetHeldMO() const { return m_pHeldMO; } + /// + /// Gets the the strength with which this Arm will grip its HeldDevice. + /// + /// The grip strength of this Arm. + float GetGripStrength() const { return m_GripStrength; } + + /// + /// Sets the strength with which this Arm will grip its HeldDevice. + /// + /// The new grip strength for this Arm to use. + void SetGripStrength(float newGripStrength) { m_GripStrength = newGripStrength; } + ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetMaxLength @@ -409,6 +421,7 @@ ClassInfoGetters MovableObject *m_pHeldMO; // Whether or not this arm is currently supporting something held in another hand bool m_Supporting; + float m_GripStrength; //!< The strength with which this Arm will grip its HeldDevice. Effectively supercedes the HeldDevice's JointStrength. // The file containing the hand bitmap. ContentFile m_HandFile; // The small bitmap holding the hand bitmap. diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index b9cf3c0ac..aabbc22ef 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -186,29 +186,32 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool Attachable::TransferJointImpulses(Vector &jointImpulses) { + bool Attachable::TransferJointImpulses(Vector &jointImpulses, float jointStiffnessOverride, float jointStrengthOverride, float gibImpulseLimitOverride) { if (!m_Parent) { return false; } if (m_ImpulseForces.empty()) { return true; } + jointStiffnessOverride = jointStiffnessOverride > 0 ? jointStiffnessOverride : m_JointStiffness; + jointStrengthOverride = jointStrengthOverride > 0 ? jointStrengthOverride : m_JointStrength; + gibImpulseLimitOverride = gibImpulseLimitOverride > 0 ? gibImpulseLimitOverride : m_GibImpulseLimit; Vector totalImpulseForce; for (const std::pair &impulseForce : m_ImpulseForces) { totalImpulseForce += impulseForce.first; } - if (m_GibImpulseLimit > 0 && totalImpulseForce.GetMagnitude() > m_GibImpulseLimit) { - jointImpulses += (totalImpulseForce.SetMagnitude(m_GibImpulseLimit)) * m_JointStiffness; + if (gibImpulseLimitOverride > 0 && totalImpulseForce.GetMagnitude() > gibImpulseLimitOverride) { + jointImpulses += (totalImpulseForce.SetMagnitude(gibImpulseLimitOverride)) * jointStiffnessOverride; GibThis(); return false; - } else if (m_JointStrength > 0 && totalImpulseForce.GetMagnitude() > m_JointStrength) { - jointImpulses += (totalImpulseForce.SetMagnitude(m_JointStrength)) * m_JointStiffness; + } else if (jointStrengthOverride > 0 && totalImpulseForce.GetMagnitude() > jointStrengthOverride) { + jointImpulses += (totalImpulseForce.SetMagnitude(jointStrengthOverride)) * jointStiffnessOverride; m_Parent->RemoveAttachable(this, true, true); return false; } else { - jointImpulses += totalImpulseForce * m_JointStiffness; + jointImpulses += totalImpulseForce * jointStiffnessOverride; } // Rough explanation of what this is doing: @@ -217,7 +220,7 @@ namespace RTE { if (!m_InheritsRotAngle) { for (const std::pair &impulseForce : m_ImpulseForces) { if (!impulseForce.second.IsZero()) { - m_AngularVel += (impulseForce.second.GetPerpendicular().Dot(impulseForce.first) / m_pAtomGroup->GetMomentOfInertia()) * (1.0F - m_JointStiffness); + m_AngularVel += (impulseForce.second.GetPerpendicular().Dot(impulseForce.first) / m_pAtomGroup->GetMomentOfInertia()) * (1.0F - jointStiffnessOverride); } } } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index b4b2e943b..6eafe75c9 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -241,8 +241,11 @@ namespace RTE { /// Additionally, in this case, the Attachable will remove itself from its parent and gib itself if appropriate. /// /// A vector that will have the impulse forces affecting the joint ADDED to it. + /// An optional override for the Attachable's joint stiffness for this function call. Primarily used to allow subclasses to perform special behaviour. + /// An optional override for the Attachable's joint strength for this function call. Primarily used to allow subclasses to perform special behaviour. + /// An optional override for the Attachable's gib impulse limit for this function call. Primarily used to allow subclasses to perform special behaviour. /// False if the Attachable has no parent or its accumulated forces are greater than its joint strength or gib impulse limit, otherwise true. - bool TransferJointImpulses(Vector &jointImpulses); + virtual bool TransferJointImpulses(Vector &jointImpulses, float jointStiffnessOverride = -1, float jointStrengthOverride = -1, float gibImpulseLimitOverride = -1); #pragma endregion #pragma region Damage and Wound Management diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index ae7d8514b..f618cee57 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -49,7 +49,6 @@ void HDFirearm::Clear() m_ReloadTime = 0; m_FullAuto = false; m_FireIgnoresThis = true; - m_RecoilTransmission = 1.0; m_ShakeRange = 0; m_SharpShakeRange = 0; m_NoSupportFactor = 0; @@ -121,7 +120,6 @@ int HDFirearm::Create(const HDFirearm &reference) { m_ReloadTime = reference.m_ReloadTime; m_FullAuto = reference.m_FullAuto; m_FireIgnoresThis = reference.m_FireIgnoresThis; - m_RecoilTransmission = reference.m_RecoilTransmission; m_ShakeRange = reference.m_ShakeRange; m_SharpShakeRange = reference.m_SharpShakeRange; m_NoSupportFactor = reference.m_NoSupportFactor; @@ -190,7 +188,7 @@ int HDFirearm::ReadProperty(std::string propName, Reader &reader) { } else if (propName == "FireIgnoresThis") { reader >> m_FireIgnoresThis; } else if (propName == "RecoilTransmission") { - reader >> m_RecoilTransmission; + reader >> m_JointStiffness; } else if (propName == "IsAnimatedManually") { reader >> m_IsAnimatedManually; } else if (propName == "ShakeRange") { @@ -261,7 +259,7 @@ int HDFirearm::Save(Writer &writer) const writer.NewProperty("FireIgnoresThis"); writer << m_FireIgnoresThis; writer.NewProperty("RecoilTransmission"); - writer << m_RecoilTransmission; + writer << m_JointStiffness; writer.NewProperty("IsAnimatedManually"); writer << m_IsAnimatedManually; writer.NewProperty("ShakeRange"); @@ -931,7 +929,7 @@ void HDFirearm::Update() // Set up the recoil force and shake offsets if (m_Recoiled) { - m_RecoilForce.SetXY(totalFireForce * m_RecoilTransmission, 0); + m_RecoilForce.SetXY(totalFireForce * m_JointStiffness, 0); m_RecoilForce = RotateOffset(m_RecoilForce); m_RecoilForce = -m_RecoilForce; diff --git a/Entities/HDFirearm.h b/Entities/HDFirearm.h index 4a514bd08..f56b167df 100644 --- a/Entities/HDFirearm.h +++ b/Entities/HDFirearm.h @@ -653,27 +653,6 @@ ClassInfoGetters void SetAnimatedManually(bool newValue) { m_IsAnimatedManually = newValue; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetRecoilTransmission -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets the calar of how much of the fire recoil force is transmitted to -// who/whatever is holding this weapon -// Arguments: New transmission value. -// Return value: None. - - void SetRecoilTransmission(float recoilTransmission) { m_RecoilTransmission = recoilTransmission; } - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetRecoilTransmission -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Returns the calar of how much of the fire recoil force is transmitted to -// who/whatever is holding this weapon -// Arguments: None. -// Return value: Transmission value. - - float GetRecoilTransmission() const { return m_RecoilTransmission; } - - ////////////////////////////////////////////////////////////////////////////////////////// // Protected member variable and method declarations @@ -727,8 +706,6 @@ ClassInfoGetters // Whether particles fired from this HDFirearm will ignore hits with itself, // and the root parent of this HDFirearm, regardless if they are set to hit MOs. bool m_FireIgnoresThis; - // Scalar of how much of the fire recoil force is transmitted to who/whatever is holding this weapon - float m_RecoilTransmission; // Timer for timing how long ago the last round was fired. Timer m_LastFireTmr; diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index 1f90ee8fd..20ecfab58 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -14,6 +14,7 @@ #include "HeldDevice.h" #include "MovableMan.h" #include "AtomGroup.h" +#include "Arm.h" #include "GUI/GUI.h" #include "GUI/AllegroBitmap.h" @@ -44,6 +45,7 @@ void HeldDevice::Clear() m_MaxSharpLength = 0; m_Supported = false; m_SupportOffset.Reset(); + m_GripStrengthMultiplier = 1.0; m_BlinkTimer.Reset(); m_PieSlices.clear(); m_Loudness = -1; @@ -131,6 +133,7 @@ int HeldDevice::Create(const HeldDevice &reference) m_StanceOffset = reference.m_StanceOffset; m_SharpStanceOffset = reference.m_SharpStanceOffset; m_SupportOffset = reference.m_SupportOffset; + m_GripStrengthMultiplier = reference.m_GripStrengthMultiplier; m_SharpAim = reference.m_SharpAim; m_MaxSharpLength = reference.m_MaxSharpLength; @@ -166,7 +169,9 @@ int HeldDevice::ReadProperty(std::string propName, Reader &reader) reader >> m_SharpStanceOffset; else if (propName == "SupportOffset") reader >> m_SupportOffset; - else if (propName == "SharpLength") + else if (propName == "GripStrengthMultiplier") { + reader >> m_GripStrengthMultiplier; + } else if (propName == "SharpLength") reader >> m_MaxSharpLength; else if (propName == "Loudness") reader >> m_Loudness; @@ -207,6 +212,8 @@ int HeldDevice::Save(Writer &writer) const writer << m_SharpStanceOffset; writer.NewProperty("SupportOffset"); writer << m_SupportOffset; + writer.NewProperty("GripStrengthMultiplier"); + writer << m_GripStrengthMultiplier; writer.NewProperty("SharpLength"); writer << m_MaxSharpLength; writer.NewProperty("Loudness"); @@ -353,6 +360,25 @@ bool HeldDevice::OnMOHit(MovableObject *pOtherMO) return false; } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool HeldDevice::TransferJointImpulses(Vector &jointImpulses, float jointStiffnessOverride, float jointStrengthOverride, float gibImpulseLimitOverride) { + if (!m_Parent) { + return false; + } + if (m_ImpulseForces.empty()) { + return true; + } + const Arm *parentAsArm = dynamic_cast(m_Parent); + if (parentAsArm && parentAsArm->GetGripStrength() > 0 && jointStrengthOverride < 0) { + jointStrengthOverride = parentAsArm->GetGripStrength() * m_GripStrengthMultiplier; + } + Attachable::TransferJointImpulses(jointImpulses, jointStiffnessOverride, jointStrengthOverride, gibImpulseLimitOverride); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /* ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Travel diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index 5aaef6d2a..048bc0cdc 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -282,6 +282,19 @@ ClassInfoGetters void SetSupportOffset(Vector newOffset) { m_SupportOffset = newOffset; } + /// + /// Gets the multiplier for how well this HeldDevice can be gripped by Arms. + /// + /// The grip strength multiplier for this HeldDevice. + float GetGripStrengthMultiplier() { return m_GripStrengthMultiplier; } + + /// + /// Sets the multiplier for how well this HeldDevice can be gripped by Arms. + /// + /// The new grip strength multiplier for this HeldDevice. + void SetGripStrengthMultiplier(float gripStrengthMultiplier) { m_GripStrengthMultiplier = gripStrengthMultiplier; } + + ////////////////////////////////////////////////////////////////////////////////////////// // Method: SetSharpAim ////////////////////////////////////////////////////////////////////////////////////////// @@ -536,6 +549,20 @@ ClassInfoGetters /// Whether this Attachable should be deleted when it's removed from its parent. void SetDeleteWhenRemovedFromParent(bool deleteWhenRemovedFromParent) final { m_DeleteWhenRemovedFromParent = false; } +#pragma region Force Transferral + /// + /// Bundles up all the accumulated impulse forces of this Attachable and calculates how they transfer to the joint, and therefore to the parent. + /// If the accumulated impulse forces exceed the joint strength or gib impulse limit of this Attachable, the jointImpulses Vector will be filled up to that limit and false will be returned. + /// Additionally, in this case, the Attachable will remove itself from its parent and gib itself if appropriate. + /// + /// A vector that will have the impulse forces affecting the joint ADDED to it. + /// An optional override for the Attachable's joint stiffness for this function call. Primarily used to allow subclasses to perform special behaviour. + /// An optional override for the Attachable's joint strength for this function call. Primarily used to allow subclasses to perform special behaviour. + /// An optional override for the Attachable's gib impulse limit for this function call. Primarily used to allow subclasses to perform special behaviour. + /// False if the Attachable has no parent or its accumulated forces are greater than its joint strength or gib impulse limit, otherwise true. + bool TransferJointImpulses(Vector &jointImpulses, float jointStiffnessOverride = -1, float jointStrengthOverride = -1, float gibImpulseLimitOverride = -1) override; +#pragma endregion + ////////////////////////////////////////////////////////////////////////////////////////// // Protected member variable and method declarations @@ -568,6 +595,7 @@ ClassInfoGetters float m_MaxSharpLength; // If this HeldDevice is currently being supported by a second hand. bool m_Supported; + float m_GripStrengthMultiplier; //!< The multiplier for how well this HeldDevice can be gripped by Arms. // Blink timer for the icon Timer m_BlinkTimer; // Extra pie menu options that this should add to any actor who holds this device diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index 7551b914f..b40ae35f0 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -76,17 +76,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Turret::Update() { - if (m_MountedDevice) { - m_MountedDevice->SetRotAngle(m_Rotation.GetRadAngle() + m_MountedDeviceRotOffset); - if (m_Parent) { - //if (m_MountedDevice->IsRecoiled()) { - // m_Parent->AddImpulseForce(m_MountedDevice->GetRecoilForce()); - //} else { - m_Recoiled = false; - //} - } - } - Attachable::Update(); + if (m_MountedDevice) { m_MountedDevice->SetRotAngle(m_Rotation.GetRadAngle() + m_MountedDeviceRotOffset); } } } \ No newline at end of file diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index f08e80e08..a396f2dd4 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -993,6 +993,7 @@ int LuaMan::Create() ABSTRACTLUABINDING(Arm, Attachable) .property("IdleOffset", &Arm::GetIdleOffset, &Arm::SetIdleOffset) + .property("GripStrength", &Arm::GetGripStrength, &Arm::SetGripStrength) .property("HandPos", &Arm::GetHandPos, &Arm::SetHandPos), ABSTRACTLUABINDING(Leg, Attachable) @@ -1272,6 +1273,7 @@ int LuaMan::Create() .def("IsFull", &HeldDevice::IsFull) .property("SharpLength", &HeldDevice::GetSharpLength, &HeldDevice::SetSharpLength) .property("SupportOffset", &HeldDevice::GetSupportOffset, &HeldDevice::SetSupportOffset) + .property("GripStrengthMultiplier", &HeldDevice::GetGripStrengthMultiplier, &HeldDevice::SetGripStrengthMultiplier) .def("SetSupported", &HeldDevice::SetSupported), CONCRETELUABINDING(Magazine, Attachable) @@ -1318,7 +1320,7 @@ int LuaMan::Create() .def("CompareTrajectories", &HDFirearm::CompareTrajectories) .def("SetNextMagazineName", &HDFirearm::SetNextMagazineName) .property("IsAnimatedManually", &HDFirearm::IsAnimatedManually, &HDFirearm::SetAnimatedManually) - .property("RecoilTransmission", &HDFirearm::GetRecoilTransmission, &HDFirearm::SetRecoilTransmission), + .property("RecoilTransmission", &HDFirearm::GetJointStiffness, &HDFirearm::SetJointStiffness), CONCRETELUABINDING(ThrownDevice, HeldDevice) .property("MinThrowVel", &ThrownDevice::GetMinThrowVel, &ThrownDevice::SetMinThrowVel) From 78d004b72f4ef8062fa108908f90cdc0e9021680 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 29 Sep 2020 01:01:15 -0300 Subject: [PATCH 059/144] Cleaned up AG Drawing in Draw so MOSR Draw does it automatically for any MOSRs that are their own parent. AG drawing already won't draw non-terrain-colliding attachables so it works well. Fixed leg and arm terrain collisions Fixed AHuman FGArm drawing behind non-hardcoded attachables like chestplates, it now draws above all of its AHuman's attachables Fixed SetWhichMOToNotHit so it applies to attachables on MOSRs and their attachables and so on. Added GetWhichMOToNotHit and appropriate lua binding --- Entities/ACDropShip.h | 17 ----------------- Entities/ACRocket.cpp | 7 ------- Entities/ACrab.cpp | 6 ------ Entities/AHuman.cpp | 17 +++++++---------- Entities/Arm.cpp | 3 +++ Entities/Leg.cpp | 3 +++ Entities/MOSRotating.cpp | 13 +++++++++++++ Entities/MOSRotating.h | 7 +++++++ Entities/MovableObject.h | 21 +++++++++++---------- Managers/LuaMan.cpp | 1 + 10 files changed, 45 insertions(+), 50 deletions(-) diff --git a/Entities/ACDropShip.h b/Entities/ACDropShip.h index b631a8f35..05922abbf 100644 --- a/Entities/ACDropShip.h +++ b/Entities/ACDropShip.h @@ -164,23 +164,6 @@ ClassInfoGetters void Update() override; -#ifdef DEBUG_BUILD -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this ACDropShip's current graphical representation to a -// BITMAP of choice. -// Arguments: A pointer to a BITMAP to draw on. -// The absolute position of the target bitmap's upper left corner in the Scene. -// In which mode to draw in. See the DrawMode enumeration for the modes. -// Whether to not draw any extra 'ghost' items of this MovableObject, -// indicator arrows or hovering HUD text and so on. -// Return value: None. - - void Draw(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; -#endif - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetMaxPassengers ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 14e2ccf0b..edffbd1ae 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -995,15 +995,8 @@ void ACRocket::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mod ACraft::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); if (mode == g_DrawColor) { - acquire_bitmap(pTargetBitmap); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); - release_bitmap(pTargetBitmap); - - m_pAtomGroup->Draw(pTargetBitmap, targetPos, false, 122); m_pRFootGroup->Draw(pTargetBitmap, targetPos, true, 13); m_pLFootGroup->Draw(pTargetBitmap, targetPos, true, 13); -// m_pDeepGroup->Draw(pTargetBitmap, targetPos, false, 13); } } #endif diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 83eddf682..75472d141 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -2823,12 +2823,6 @@ void ACrab::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, Actor::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); if (mode == g_DrawColor && !onlyPhysical) { - acquire_bitmap(pTargetBitmap); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); - release_bitmap(pTargetBitmap); - - m_pAtomGroup->Draw(pTargetBitmap, targetPos, false, 122); m_pLFGFootGroup->Draw(pTargetBitmap, targetPos, true, 13); m_pLBGFootGroup->Draw(pTargetBitmap, targetPos, true, 13); m_pRFGFootGroup->Draw(pTargetBitmap, targetPos, true, 13); diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index b76c3b91b..659fd89ac 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -104,6 +104,12 @@ int AHuman::Create() if (Actor::Create() < 0) return -1; + // Cheat to make sure the FG Arm is always at the end of the Attachables list so it draws last. + if (m_pFGArm) { + m_Attachables.erase(std::find(m_Attachables.begin(), m_Attachables.end(), m_pFGArm)); + m_Attachables.push_back(m_pFGArm); + } + // Make the limb paths for the background limbs for (int i = 0; i < MOVEMENTSTATECOUNT; ++i) { @@ -4349,30 +4355,21 @@ void AHuman::DrawThrowingReticule(BITMAP *pTargetBitmap, const Vector &targetPos // BITMAP of choice. void AHuman::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { - DrawMode realMode = (mode == g_DrawColor && m_FlashWhiteMS) ? g_DrawWhite : mode; - Actor::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); // Draw background Arm's hand after the HeldDevice of FGArm is drawn if the FGArm is holding a weapon. + DrawMode realMode = (mode == g_DrawColor && m_FlashWhiteMS) ? g_DrawWhite : mode; if (m_pFGArm && m_pBGArm && !onlyPhysical && mode == g_DrawColor && m_pBGArm->DidReach() && m_pFGArm->HoldsHeldDevice() && !m_pFGArm->HoldsThrownDevice() && !m_pFGArm->GetHeldDevice()->IsReloading() && !m_pFGArm->GetHeldDevice()->IsShield()) { m_pBGArm->DrawHand(pTargetBitmap, targetPos, realMode); } #ifdef DEBUG_BUILD if (mode == g_DrawDebug) { - // Limbpath debug drawing m_Paths[m_HFlipped][WALK].Draw(pTargetBitmap, targetPos, 122); m_Paths[m_HFlipped][CRAWL].Draw(pTargetBitmap, targetPos, 122); m_Paths[m_HFlipped][ARMCRAWL].Draw(pTargetBitmap, targetPos, 13); m_Paths[m_HFlipped][CLIMB].Draw(pTargetBitmap, targetPos, 165); } - if (mode == g_DrawColor && !onlyPhysical) { - acquire_bitmap(pTargetBitmap); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); - release_bitmap(pTargetBitmap); - -// m_pAtomGroup->Draw(pTargetBitmap, targetPos, false, 122); m_pFGFootGroup->Draw(pTargetBitmap, targetPos, true, 13); m_pBGFootGroup->Draw(pTargetBitmap, targetPos, true, 13); m_pFGHandGroup->Draw(pTargetBitmap, targetPos, true, 13); diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 19fc0925f..d0d1da68d 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -57,6 +57,9 @@ int Arm::Create() { // Ensure Arms don't get flagged as inheriting RotAngle, since they never do and always set their RotAngle for themselves. m_InheritsRotAngle = false; + // Ensure Arms don't collide with terrain when attached since their expansion/contraction is frame based so atom group doesn't know how to account for it. + SetCollidesWithTerrainWhileAttached(false); + return 0; } diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index 42955d134..6123e6bb6 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -36,6 +36,9 @@ namespace RTE { // Ensure Legs don't get flagged as inheriting RotAngle, since they never do and always set their RotAngle for themselves. m_InheritsRotAngle = false; + // Ensure Legs don't collide with terrain when attached since their expansion/contraction is frame based so atom group doesn't know how to account for it. + SetCollidesWithTerrainWhileAttached(false); + if (m_ContractedOffset.GetMagnitude() > m_ExtendedOffset.GetMagnitude()) { std::swap(m_ContractedOffset, m_ExtendedOffset); } diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 835aa6ab2..220072e76 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1619,6 +1619,12 @@ void MOSRotating::GetMOIDs(std::vector &MOIDs) const { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void MOSRotating::SetWhichMOToNotHit(MovableObject *moToNotHit, float forHowLong) { + MOSprite::SetWhichMOToNotHit(moToNotHit, forHowLong); + for (Attachable *attachable : m_Attachables) { attachable->SetWhichMOToNotHit(moToNotHit, forHowLong); } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: Draw @@ -1865,6 +1871,13 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, attachableToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } } + +#ifdef DEBUG_BUILD + if (mode == g_DrawColor && !onlyPhysical && m_pAtomGroup && GetRootParent() == this) { + m_pAtomGroup->Draw(pTargetBitmap, targetPos, false, 122); + //m_pDeepGroup->Draw(pTargetBitmap, targetPos, false, 13); + } +#endif } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 756e9ae49..fd3eb803c 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -153,6 +153,13 @@ ClassInfoGetters /// void SetAsNoID() override; + /// + /// Sets this MOSRotating to not hit a specific other MO and all its children even though MO hitting is enabled on this MOSRotating. + /// + /// A pointer to the MO to not be hitting. 0 means don't ignore anyhting. Ownership is NOT transferred! + /// How long, in seconds, to ignore the specified MO. A negative number means forever. + void SetWhichMOToNotHit(MovableObject *moToNotHit = 0, float forHowLong = -1) override; + ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetAtomGroup diff --git a/Entities/MovableObject.h b/Entities/MovableObject.h index 99eeb6d9a..e986059e4 100644 --- a/Entities/MovableObject.h +++ b/Entities/MovableObject.h @@ -822,17 +822,18 @@ friend class Atom; void SetToGetHitByMOs(bool getHitByMOs = true) { m_GetsHitByMOs = getHitByMOs; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: SetWhichMOToNotHit -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Sets this MO to not hit a specific other MO and all its children even -// though MO hitting is enabled on this MovableObject -// Arguments: A pointer to the MO to not be hitting. 0 means don't ignore anyhting. -// Ownership is not transferred! -// For how long, in S, to ignore the above. Negative number means forever. -// Return value: None. + /// + /// Gets the MO this MO is set not to hit even when MO hitting is enabled on this MO. + /// + /// The MO this MO is set not to hit. + const MovableObject *GetWhichMOToNotHit() const { return m_pMOToNotHit; } - void SetWhichMOToNotHit(MovableObject *moToNotHit = 0, float forHowLong = -1) { m_pMOToNotHit = moToNotHit; m_MOIgnoreTimer.Reset(); m_MOIgnoreTimer.SetSimTimeLimitS(forHowLong); } + /// + /// Sets this MO to not hit a specific other MO and all its children even when MO hitting is enabled on this MO. + /// + /// A pointer to the MO to not be hitting. 0 means don't ignore anyhting. Ownership is NOT transferred! + /// How long, in seconds, to ignore the specified MO. A negative number means forever. + virtual void SetWhichMOToNotHit(MovableObject *moToNotHit = 0, float forHowLong = -1) { m_pMOToNotHit = moToNotHit; m_MOIgnoreTimer.Reset(); m_MOIgnoreTimer.SetSimTimeLimitS(forHowLong); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index a396f2dd4..bf23fa27e 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -651,6 +651,7 @@ int LuaMan::Create() .property("IgnoresTeamHits", &MovableObject::IgnoresTeamHits, &MovableObject::SetIgnoresTeamHits) .property("IgnoresWhichTeam", &MovableObject::IgnoresWhichTeam) .property("IgnoreTerrain", &MovableObject::IgnoreTerrain, &MovableObject::SetIgnoreTerrain) + .def("GetWhichMOToNotHit", &MovableObject::GetWhichMOToNotHit) .def("SetWhichMOToNotHit", &MovableObject::SetWhichMOToNotHit) .property("ToSettle", &MovableObject::ToSettle, &MovableObject::SetToSettle) .property("ToDelete", &MovableObject::ToDelete, &MovableObject::SetToDelete) From 99575077eccc26b6a4ff106873159e55a9daa58c Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 29 Sep 2020 01:01:29 -0300 Subject: [PATCH 060/144] Missed a section --- Entities/ACDropShip.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index b642aad61..daa17c3bd 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -893,22 +893,4 @@ void ACDropShip::ResetEmissionTimers() if (m_pULThruster && m_pULThruster->IsAttached()) m_pULThruster->ResetEmissionTimers(); } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#ifdef DEBUG_BUILD -void ACDropShip::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { - ACraft::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - - if (mode == g_DrawColor) { - acquire_bitmap(pTargetBitmap); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); - putpixel(pTargetBitmap, floorf(m_Pos.m_X), floorf(m_Pos.m_Y), 64); - release_bitmap(pTargetBitmap); - - m_pAtomGroup->Draw(pTargetBitmap, targetPos, false, 122); -// m_pDeepGroup->Draw(pTargetBitmap, targetPos, false, 13); - } -} -#endif } // namespace RTE \ No newline at end of file From cda75d39a58a64c10c0ad0dac7d69fa1ce0e4d59 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 29 Sep 2020 01:10:36 -0300 Subject: [PATCH 061/144] Cleaned up recoil handling from HDs so it works better. It's hard to notice with current force values, but it seems decent. Actors will be set to unstable fall over if weapons are removed by forces Forgot a line that cleans up m_pMOToNotHit in attachables who had it set by their parent and are then removed. This makes them willing to hit that MO again. Also cleaned up some equipped item setting in Arm --- Entities/Arm.cpp | 12 ++---------- Entities/Attachable.cpp | 1 + Entities/HDFirearm.cpp | 6 +----- Entities/HeldDevice.cpp | 15 ++++++++++++--- Entities/HeldDevice.h | 2 +- Entities/Turret.cpp | 4 +++- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index d0d1da68d..3591aaf17 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -206,15 +206,10 @@ void Arm::SetHeldMO(MovableObject *newHeldMO) { if (m_pHeldMO && heldMOAsAttachable && heldMOAsAttachable->IsAttachedTo(this)) { RemoveAttachable(heldMOAsAttachable); } m_pHeldMO = nullptr; } else { - //TODO All this needs cleaning up, it should work just like all other hardcoded attachable setters and rely on RemoveAttachable to add it to MovableMan, etc. + //TODO All this needs cleaning up, this should do the basics, some other method should be responsible for replacing held things if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && dynamic_cast(m_pHeldMO)->IsAttachedTo(this)) { HeldDevice *oldHeldDevice = dynamic_cast(m_pHeldMO); if (oldHeldDevice->IsAttached()) { dynamic_cast(oldHeldDevice->GetParent())->RemoveAttachable(oldHeldDevice, true, false); } - // TODO: Refine throwing force to dropped device here?") - pHeldDev->SetVel(Vector(10 * PosRand(), -15 * PosRand())); - pHeldDev->SetAngularVel(-10 * PosRand()); - g_MovableMan.AddItem(pHeldDev); - m_pHeldMO = pHeldDev = 0; m_pHeldMO = nullptr; } @@ -447,10 +442,7 @@ void Arm::Update() { handOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); pHeldDev->SetParentOffset(handOffsetAsParentOffset); - if (pHeldDev->IsRecoiled()) - m_Parent->AddImpulseForce(pHeldDev->GetRecoilForce()); - else - m_Recoiled = false; + m_Recoiled = pHeldDev->IsRecoiled(); m_Rotation = (m_HFlipped ? c_PI : 0) + handAngle; diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index aabbc22ef..a1b40ef4d 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -349,6 +349,7 @@ namespace RTE { } else { m_RootMOID = m_MOID; m_RestTimer.Reset(); + if (m_pMOToNotHit && m_Parent && m_Parent->GetWhichMOToNotHit() == m_pMOToNotHit) { m_pMOToNotHit = nullptr; } if (m_CollidesWithTerrainWhileAttached) { OrganizeAtomsInParent(false); } m_Parent = newParent; diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index f618cee57..62581c027 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -938,11 +938,7 @@ void HDFirearm::Update() m_RecoilOffset.SetMagnitude(1.25); } -// TODO: This is broken, revise") - if (m_Parent) - m_Parent->SetRecoil(m_RecoilForce, m_RecoilOffset, m_Recoiled); - else - m_ImpulseForces.push_back(make_pair(m_RecoilForce, m_RecoilOffset)); + AddImpulseForce(m_RecoilForce, m_RecoilOffset); // Display gun animation if (!m_IsAnimatedManually) diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index 20ecfab58..b5fabae23 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -15,6 +15,7 @@ #include "MovableMan.h" #include "AtomGroup.h" #include "Arm.h" +#include "Actor.h" #include "GUI/GUI.h" #include "GUI/AllegroBitmap.h" @@ -364,17 +365,25 @@ bool HeldDevice::OnMOHit(MovableObject *pOtherMO) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool HeldDevice::TransferJointImpulses(Vector &jointImpulses, float jointStiffnessOverride, float jointStrengthOverride, float gibImpulseLimitOverride) { - if (!m_Parent) { + MovableObject *parent = m_Parent; + if (!parent) { return false; } if (m_ImpulseForces.empty()) { return true; } - const Arm *parentAsArm = dynamic_cast(m_Parent); + const Arm *parentAsArm = dynamic_cast(parent); if (parentAsArm && parentAsArm->GetGripStrength() > 0 && jointStrengthOverride < 0) { jointStrengthOverride = parentAsArm->GetGripStrength() * m_GripStrengthMultiplier; } - Attachable::TransferJointImpulses(jointImpulses, jointStiffnessOverride, jointStrengthOverride, gibImpulseLimitOverride); + bool intact = Attachable::TransferJointImpulses(jointImpulses, jointStiffnessOverride, jointStrengthOverride, gibImpulseLimitOverride); + if (!intact) { + Actor *rootParentAsActor = dynamic_cast(parent->GetRootParent()); + if (rootParentAsActor && rootParentAsActor->GetStatus() == Actor::STABLE) { + rootParentAsActor->SetStatus(Actor::UNSTABLE); + } + } + return intact; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index 048bc0cdc..d7f828eb3 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -286,7 +286,7 @@ ClassInfoGetters /// Gets the multiplier for how well this HeldDevice can be gripped by Arms. /// /// The grip strength multiplier for this HeldDevice. - float GetGripStrengthMultiplier() { return m_GripStrengthMultiplier; } + float GetGripStrengthMultiplier() const { return m_GripStrengthMultiplier; } /// /// Sets the multiplier for how well this HeldDevice can be gripped by Arms. diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index b40ae35f0..e1d6c4b66 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -37,6 +37,8 @@ namespace RTE { AddAttachable(m_MountedDevice); m_MountedDevice->SetInheritsRotAngle(false); m_MountedDevice->SetDeleteWhenRemovedFromParent(true); + //Force weapons mounted on turrets to never be removed due to forces. This doesn't affect them gibbing from hitting their impulse limits though. + m_MountedDevice->SetJointStrength(0.0F); } } else { return Attachable::ReadProperty(propName, reader); @@ -76,7 +78,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Turret::Update() { - Attachable::Update(); if (m_MountedDevice) { m_MountedDevice->SetRotAngle(m_Rotation.GetRadAngle() + m_MountedDeviceRotOffset); } + Attachable::Update(); } } \ No newline at end of file From b3acae08b6554282d82642c70650056863f067d0 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 5 Oct 2020 23:26:18 -0300 Subject: [PATCH 062/144] Fixed Attachable terrain collision handling so it properly adds atoms with the proper subgroup ID, and updates them only when appropriate Fixed travel handling of MOToNotHit in MOPixel, MOSParticle and MOSRotating so it doesn't rely on sequentially ordered IDs and instead uses GetMOIDs so it's safer. Fixed AEmitter's flash and HDFirearm's flash and magazine and Leg's Foot colliding with terrain while attached Removed HeldDevice override DeleteWhenRemovedFromParent. It was making Crab Turret HDFirearms not delete, and would generally not be good to force like that. This can have some messy side-effects if a HeldDevice is set to delete when removed though, cause swapping weapons and stuff will delete it. Probably need to add an extra property on HD that allows for selective overriding of this. Renamed and cleaned up some stuff --- Entities/AEmitter.cpp | 1 + Entities/Attachable.cpp | 59 ++++++++++++++++++++++++++++++++-------- Entities/Attachable.h | 15 +++++++--- Entities/HDFirearm.cpp | 2 ++ Entities/HeldDevice.h | 6 ---- Entities/Leg.cpp | 3 +- Entities/MOPixel.cpp | 8 +++--- Entities/MOSParticle.cpp | 8 +++--- Entities/MOSRotating.cpp | 12 ++++---- Entities/Magazine.cpp | 2 +- 10 files changed, 78 insertions(+), 38 deletions(-) diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index 41e70d0dd..d47f665ee 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -177,6 +177,7 @@ int AEmitter::ReadProperty(std::string propName, Reader &reader) { m_pFlash->SetDrawnNormallyByParent(false); m_pFlash->SetInheritsRotAngle(false); m_pFlash->SetDeleteWhenRemovedFromParent(true); + m_pFlash->SetCollidesWithTerrainWhileAttached(false); } } else if (propName == "FlashScale") { reader >> m_FlashScale; diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index a1b40ef4d..69599c7dc 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -78,6 +78,8 @@ namespace RTE { m_CollidesWithTerrainWhileAttached = reference.m_CollidesWithTerrainWhileAttached; + m_AtomSubgroupID = GetUniqueID(); + return 0; } @@ -251,7 +253,7 @@ namespace RTE { void Attachable::SetCollidesWithTerrainWhileAttached(bool collidesWithTerrainWhileAttached) { if (m_CollidesWithTerrainWhileAttached != collidesWithTerrainWhileAttached) { - OrganizeAtomsInParent(collidesWithTerrainWhileAttached); + AddOrRemoveAtomsFromRootParentAtomGroup(collidesWithTerrainWhileAttached); m_CollidesWithTerrainWhileAttached = collidesWithTerrainWhileAttached; } } @@ -311,12 +313,21 @@ namespace RTE { if (InheritsHFlipped() != 0) { m_HFlipped = m_InheritsHFlipped == 1 ? m_Parent->IsHFlipped() : !m_Parent->IsHFlipped(); } if (InheritsRotAngle()) { SetRotAngle(m_Parent->GetRotAngle() + m_InheritedRotAngleOffset); } - if (m_CollidesWithTerrainWhileAttached) { + MOSRotating *rootParentAsMOSR = dynamic_cast(GetRootParent()); + if (rootParentAsMOSR && m_CollidesWithTerrainWhileAttached) { + // This safety check exists to ensure the parent's AtomGroup contains this Attachable's Atoms in a subgroup. Hardcoded Attachables need this in order to work, since they're cloned before their parent's AtomGroup exists. + if (!rootParentAsMOSR->GetAtomGroup()->ContainsSubGroup(m_AtomSubgroupID)) { AddOrRemoveAtomsFromRootParentAtomGroup(true); } + float facingAngle = (m_HFlipped ? c_PI : 0) + GetRotAngle() * static_cast(GetFlipFactor()); float parentFacingAngle = (m_Parent->IsHFlipped() ? c_PI : 0) + m_Parent->GetRotAngle() * static_cast(m_Parent->GetFlipFactor()); - Matrix atomRot(facingAngle - parentFacingAngle); - m_pAtomGroup->UpdateSubAtoms(GetAtomSubgroupID(), GetParentOffset() - (GetJointOffset() * atomRot), atomRot); + if (!InheritsRotAngle()) { + Matrix atomRotationForSubgroup(facingAngle - parentFacingAngle); + Vector atomOffsetForSubgroup; + CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); + atomOffsetForSubgroup += GetJointOffset() - (GetJointOffset() * atomRotationForSubgroup); + rootParentAsMOSR->GetAtomGroup()->UpdateSubAtoms(GetAtomSubgroupID(), atomOffsetForSubgroup, atomRotationForSubgroup); + } } m_DeepCheck = false; @@ -345,14 +356,20 @@ namespace RTE { ResetAllTimers(); m_Parent = newParent; - if (m_CollidesWithTerrainWhileAttached) { OrganizeAtomsInParent(true); } + if (m_CollidesWithTerrainWhileAttached) { AddOrRemoveAtomsFromRootParentAtomGroup(true); } } else { m_RootMOID = m_MOID; m_RestTimer.Reset(); if (m_pMOToNotHit && m_Parent && m_Parent->GetWhichMOToNotHit() == m_pMOToNotHit) { m_pMOToNotHit = nullptr; } - if (m_CollidesWithTerrainWhileAttached) { OrganizeAtomsInParent(false); } + if (m_CollidesWithTerrainWhileAttached) { AddOrRemoveAtomsFromRootParentAtomGroup(false); } + for (Attachable *attachable : m_Attachables) { + if (attachable->GetCollidesWithTerrainWhileAttached()) { attachable->AddOrRemoveAtomsFromRootParentAtomGroup(false); } + } m_Parent = newParent; + for (Attachable *attachable : m_Attachables) { + if (attachable->GetCollidesWithTerrainWhileAttached()) { attachable->AddOrRemoveAtomsFromRootParentAtomGroup(true); } + } } if (parentToUseForScriptCall && parentToUseForScriptCall->GetRootParent()->HasEverBeenAddedToMovableMan()) { @@ -362,12 +379,30 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Attachable::OrganizeAtomsInParent(bool addToParent) { - if (IsAttached() && m_Parent->GetAtomGroup()) { - if (addToParent) { - m_Parent->GetAtomGroup()->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), GetParentOffset() - GetJointOffset()); - } else { - m_Parent->GetAtomGroup()->RemoveAtoms(GetAtomSubgroupID()); + void Attachable::CalculateAtomOffsetForSubgroup(Vector &atomOffsetForSubgroup) const { + if (m_Parent) { + const Attachable *parentAsAttachable = dynamic_cast(m_Parent); + if (parentAsAttachable) { + parentAsAttachable->CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); + } + atomOffsetForSubgroup += GetParentOffset() - GetJointOffset(); + } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::AddOrRemoveAtomsFromRootParentAtomGroup(bool addAtoms) { + MOSRotating *rootParentAsMOSR = dynamic_cast(GetRootParent()); + if (rootParentAsMOSR && IsAttached()) { + AtomGroup *rootParentAtomGroup = rootParentAsMOSR->GetAtomGroup(); + if (rootParentAtomGroup) { + if (addAtoms && !rootParentAtomGroup->ContainsSubGroup(GetAtomSubgroupID())) { + Vector atomOffsetForSubgroup; + CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); + rootParentAsMOSR->GetAtomGroup()->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), atomOffsetForSubgroup); + } else if (!addAtoms && rootParentAtomGroup->ContainsSubGroup(GetAtomSubgroupID())) { + rootParentAsMOSR->GetAtomGroup()->RemoveAtoms(GetAtomSubgroupID()); + } } } } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 6eafe75c9..46623eb93 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -210,7 +210,7 @@ namespace RTE { /// 1.0 means impulse forces on this attachable will be transferred to the parent with 100% strength, 0 means they will not transfer at all. /// /// A float describing the normalized stiffness scalar of this Attachable's joint. It will automatically be limited between 0 and 1.0. - void SetJointStiffness(float jointStiffness) { m_JointStiffness = Limit(jointStiffness, 1, 0); } + void SetJointStiffness(float jointStiffness) { m_JointStiffness = Limit(jointStiffness, 1.0F, 0.0F); } /// /// Gets the offset of the joint (the point around which this Attachable and its parent hinge) from this Attachable's center of mass/origin. @@ -418,10 +418,17 @@ namespace RTE { private: /// - /// Turns on/off this Attachable's terrain collisions while it is attached by adding/removing its atoms to/from its parent AtomGroup. + /// Calculates the offset this Attachable's Atoms should be given when added to its root parent's AtomGroup as a subgroup, and fills the passed in Vector with it. + /// If the Attachable's parent is the root parent, the Vector is not modified, as the calculated offset is (0, 0). /// - /// Whether to add this Attachable's atoms to the parent's AtomGroup or remove them. - void OrganizeAtomsInParent(bool addToParent); + /// A reference to the Vector that will be filled in with the offset this Attachable's Atoms should use when added to their root parent's AtomGroup as a subgroup. + void CalculateAtomOffsetForSubgroup(Vector &atomOffsetForSubgroup) const; + + /// + /// Turns on/off this Attachable's terrain collisions while it is attached by adding/removing its Atoms to/from its root parent's AtomGroup. + /// + /// Whether to add this Attachable's Atoms to the root parent's AtomGroup or remove them. + void AddOrRemoveAtomsFromRootParentAtomGroup(bool addAtoms); /// /// Clears all the member variables of this Attachable, effectively resetting the members of this abstraction level only. diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index 62581c027..8b92e3fc9 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -152,6 +152,7 @@ int HDFirearm::ReadProperty(std::string propName, Reader &reader) { m_pMagazineReference = dynamic_cast(magazineEntity); m_pMagazine = dynamic_cast(magazineEntity->Clone()); AddAttachable(m_pMagazine); + m_pMagazine->SetCollidesWithTerrainWhileAttached(false); } } else if (propName == "Flash") { RemoveAttachable(m_pFlash); @@ -161,6 +162,7 @@ int HDFirearm::ReadProperty(std::string propName, Reader &reader) { AddAttachable(m_pFlash); m_pFlash->SetDrawnNormallyByParent(false); m_pFlash->SetDeleteWhenRemovedFromParent(true); + m_pFlash->SetCollidesWithTerrainWhileAttached(false); } } else if (propName == "FireSound") { reader >> m_FireSound; diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index d7f828eb3..aadb6883d 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -543,12 +543,6 @@ ClassInfoGetters /// void ResetAllTimers() override { Attachable::ResetAllTimers(); m_ActivationTimer.Reset(); } - /// - /// Override to ensure that HeldDevices and their children can NOT be set to delete when removed from their parent as that causes problems when swapping inventory items around. - /// - /// Whether this Attachable should be deleted when it's removed from its parent. - void SetDeleteWhenRemovedFromParent(bool deleteWhenRemovedFromParent) final { m_DeleteWhenRemovedFromParent = false; } - #pragma region Force Transferral /// /// Bundles up all the accumulated impulse forces of this Attachable and calculates how they transfer to the joint, and therefore to the parent. diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index 6123e6bb6..7fa5b7722 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -87,6 +87,7 @@ namespace RTE { AddAttachable(m_Foot); m_Foot->SetInheritsRotAngle(false); m_Foot->SetParentGibBlastStrengthMultiplier(0.0F); + m_Foot->SetCollidesWithTerrainWhileAttached(false); } } else if (propName == "ContractedOffset") { reader >> m_ContractedOffset; @@ -209,7 +210,7 @@ namespace RTE { m_Frame = 0; } else { m_CurrentNormalizedExtension = Limit((m_CurrentAnkleOffset.GetMagnitude() - m_MinExtension) / (m_MaxExtension - m_MinExtension), 1.0F, 0.0F); - m_Frame = std::min(m_FrameCount - 1, static_cast(floorf(m_CurrentNormalizedExtension * static_cast(m_FrameCount)))); + m_Frame = std::min(m_FrameCount - 1, static_cast(std::floorf(m_CurrentNormalizedExtension * static_cast(m_FrameCount)))); } } diff --git a/Entities/MOPixel.cpp b/Entities/MOPixel.cpp index e2b635c8e..9f76bc9c3 100644 --- a/Entities/MOPixel.cpp +++ b/Entities/MOPixel.cpp @@ -143,10 +143,10 @@ namespace RTE { // Set the atom to ignore a certain MO, if set and applicable. if (m_HitsMOs && m_pMOToNotHit && g_MovableMan.ValidMO(m_pMOToNotHit) && !m_MOIgnoreTimer.IsPastSimTimeLimit()) { - MOID root = m_pMOToNotHit->GetID(); - int footprint = m_pMOToNotHit->GetMOIDFootprint(); - for (int i = 0; i < footprint; ++i) { - m_Atom->AddMOIDToIgnore(root + i); + std::vector MOIDsNotToHit; + m_pMOToNotHit->GetMOIDs(MOIDsNotToHit); + for (const MOID &MOIDNotToHit : MOIDsNotToHit) { + m_Atom->AddMOIDToIgnore(MOIDNotToHit); } } // Do static particle bounce calculations. diff --git a/Entities/MOSParticle.cpp b/Entities/MOSParticle.cpp index 48407f8da..8efc9fac2 100644 --- a/Entities/MOSParticle.cpp +++ b/Entities/MOSParticle.cpp @@ -111,10 +111,10 @@ namespace RTE { // Set the atom to ignore a certain MO, if set and applicable. if (m_HitsMOs && m_pMOToNotHit && g_MovableMan.ValidMO(m_pMOToNotHit) && !m_MOIgnoreTimer.IsPastSimTimeLimit()) { - MOID root = m_pMOToNotHit->GetID(); - int footprint = m_pMOToNotHit->GetMOIDFootprint(); - for (int i = 0; i < footprint; ++i) { - m_Atom->AddMOIDToIgnore(root + i); + std::vector MOIDsNotToHit; + m_pMOToNotHit->GetMOIDs(MOIDsNotToHit); + for (const MOID &MOIDNotToHit : MOIDsNotToHit) { + m_Atom->AddMOIDToIgnore(MOIDNotToHit); } } // Do static particle bounce calculations. diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 220072e76..0af2e4bd4 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1380,12 +1380,12 @@ void MOSRotating::Travel() } // Set the atom to ignore a certain MO, if set and applicable. - if (m_HitsMOs && m_pMOToNotHit && g_MovableMan.ValidMO(m_pMOToNotHit) && !m_MOIgnoreTimer.IsPastSimTimeLimit()) - { - MOID root = m_pMOToNotHit->GetID(); - int footprint = m_pMOToNotHit->GetMOIDFootprint(); - for (int i = 0; i < footprint; ++i) - m_pAtomGroup->AddMOIDToIgnore(root + i); + if (m_HitsMOs && m_pMOToNotHit && g_MovableMan.ValidMO(m_pMOToNotHit) && !m_MOIgnoreTimer.IsPastSimTimeLimit()) { + std::vector MOIDsNotToHit; + m_pMOToNotHit->GetMOIDs(MOIDsNotToHit); + for (const MOID &MOIDNotToHit : MOIDsNotToHit) { + m_pAtomGroup->AddMOIDToIgnore(MOIDNotToHit); + } } ///////////////////////////////// diff --git a/Entities/Magazine.cpp b/Entities/Magazine.cpp index 23f4233f9..00a0d24bf 100644 --- a/Entities/Magazine.cpp +++ b/Entities/Magazine.cpp @@ -48,7 +48,7 @@ void Magazine::Clear() int Magazine::Create() { - if (MOSRotating::Create() < 0) + if (Attachable::Create() < 0) return -1; // Read projectile properties for AI aim caluculations From adb49e412fa23e02ebe466ab7a089fc9fee53289 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 6 Oct 2020 01:04:26 -0300 Subject: [PATCH 063/144] Made GetMass more efficient for MOSRs. Instead of having to get each attachable and wound's mass (and in turn their attachables' masses) each call, it stores the mass of each attachable when adding them and removes it when removing them To support this change to GetMass, attachables are now responsible for telling their parent when their mass has changed because of their own wounds or attachables. Cleaned up some comments in MOSR and cleaned up Attachable a little Cleaned up some leftover cruft in TDExplosive Renamed DetachOrDestroyAll to RemoveOrDestroyAllAttachables and fixed it so it uses an iterator for loop again and won't cause crashes. Would be nice to just delete it since it's only used for fuggin hats --- Entities/AHuman.cpp | 2 +- Entities/Attachable.cpp | 57 ++++++++++++++++++++++++++++++++++------ Entities/Attachable.h | 41 +++++++++++++++++++++++++++++ Entities/MOSRotating.cpp | 29 +++++++++----------- Entities/MOSRotating.h | 41 +++++++++++++++++------------ Entities/TDExplosive.cpp | 33 +++++++++++------------ Entities/TDExplosive.h | 6 +++++ 7 files changed, 150 insertions(+), 59 deletions(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 659fd89ac..b93196c26 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -3068,7 +3068,7 @@ void AHuman::Update() Attachable *pNewHat = dynamic_cast(preset->Clone()); if (pNewHat) { - m_pHead->DetachOrDestroyAll(true); + m_pHead->RemoveOrDestroyAllAttachables(true); m_pHead->AddAttachable(pNewHat, pNewHat->GetParentOffset()); } } diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 69599c7dc..4d8a67523 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -325,11 +325,11 @@ namespace RTE { Matrix atomRotationForSubgroup(facingAngle - parentFacingAngle); Vector atomOffsetForSubgroup; CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); + // Note: This line looks weird because CalculateAtomOffsetForSubgroup already adds JointOffset to the value, so we have to subtract it and added its rotated value instead. atomOffsetForSubgroup += GetJointOffset() - (GetJointOffset() * atomRotationForSubgroup); rootParentAsMOSR->GetAtomGroup()->UpdateSubAtoms(GetAtomSubgroupID(), atomOffsetForSubgroup, atomRotationForSubgroup); } } - m_DeepCheck = false; } @@ -339,27 +339,68 @@ namespace RTE { if (m_Parent != nullptr && GetRootParent()->HasEverBeenAddedToMovableMan()) { UpdateScripts(); } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::SetMass(const float newMass) { + float previousMassForUpdatingParent = m_Parent ? GetMass() : 0.0F; + MovableObject::SetMass(newMass); + if (m_Parent) { m_Parent->UpdateAttachableAndWoundMass(previousMassForUpdatingParent, GetMass()); } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::AddAttachable(Attachable *attachable, const Vector &parentOffsetToSet) { + float previousMassForUpdatingParent = m_Parent ? GetMass() : 0.0F; + MOSRotating::AddAttachable(attachable, parentOffsetToSet); + if (m_Parent) { m_Parent->UpdateAttachableAndWoundMass(previousMassForUpdatingParent, GetMass()); } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + bool Attachable::RemoveAttachable(Attachable *attachable, bool addToMovableMan, bool addBreakWounds) { + float previousMassForUpdatingParent = m_Parent ? GetMass() : 0.0F; + bool result = MOSRotating::RemoveAttachable(attachable, addToMovableMan, addBreakWounds); + if (m_Parent) { m_Parent->UpdateAttachableAndWoundMass(previousMassForUpdatingParent, GetMass()); } + return result; + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit) { + float previousMassForUpdatingParent = m_Parent ? GetMass() : 0.0F; + MOSRotating::AddWound(woundToAdd, parentOffsetToSet, checkGibWoundLimit); + if (m_Parent) { m_Parent->UpdateAttachableAndWoundMass(previousMassForUpdatingParent, GetMass()); } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + float Attachable::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) { + float previousMassForUpdatingParent = m_Parent ? GetMass() : 0.0F; + float result = MOSRotating::RemoveWounds(numberOfWoundsToRemove, includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); + if (m_Parent) { m_Parent->UpdateAttachableAndWoundMass(previousMassForUpdatingParent, GetMass()); } + return result; + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Attachable::SetParent(MOSRotating *newParent) { if (newParent == m_Parent) { return; } - - m_Team = newParent ? newParent->GetTeam() : -1; MOSRotating *parentToUseForScriptCall = newParent ? newParent : m_Parent; + + //TODO Get rid of the need for calling ResetAllTimers, if something like inventory swapping needs timers reset it should do it itself! This blanket handling probably has side-effects. + // Timers are reset here as a precaution, so that if something was sitting in an inventory, it doesn't cause backed up emissions. + ResetAllTimers(); if (newParent) { - //TODO see if this is reasonable. Seems like inventory swapping should do this cleanup internally. Also note that it used to be done regardless of newParent existing (i.e. any time Attach was called) but I changed that, might be bad? - - // Timers are reset here as a precaution, so that if something was sitting in an inventory, it doesn't cause backed up emissions. - ResetAllTimers(); - m_Parent = newParent; + m_Team = newParent->GetTeam(); if (m_CollidesWithTerrainWhileAttached) { AddOrRemoveAtomsFromRootParentAtomGroup(true); } } else { m_RootMOID = m_MOID; m_RestTimer.Reset(); + m_Team = -1; if (m_pMOToNotHit && m_Parent && m_Parent->GetWhichMOToNotHit() == m_pMOToNotHit) { m_pMOToNotHit = nullptr; } if (m_CollidesWithTerrainWhileAttached) { AddOrRemoveAtomsFromRootParentAtomGroup(false); } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 46623eb93..7de7e4fff 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -377,6 +377,47 @@ namespace RTE { /// Updates this Attachable. Supposed to be done every frame. /// void Update() override; + + /// + /// Sets the mass of this Attachable. + /// + /// A float specifying the new mass value in Kilograms (kg). + void SetMass(const float newMass) final; + + /// + /// Adds the passed in Attachable the list of Attachables, changes its parent offset to the passed in Vector, and sets its parent to this MOSRotating. + /// + /// The Attachable to add. + /// The Vector to set as the Attachable's parent offset. + void AddAttachable(Attachable *attachable, const Vector &parentOffsetToSet) final; + + /// + /// Removes the passed in Attachable and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. + /// + /// The Attachable to remove. + /// Whether or not to add the Attachable to MovableMan once it has been removed. + /// Whether or not to add break wounds to the Attachable and this MOSRotating. + /// False if the Attachable is invalid, otherwise true. + bool RemoveAttachable(Attachable *attachable, bool addToMovableMan, bool addBreakWounds) final; + + /// + /// Adds the passed in wound AEmitter to the list of wounds and changes its parent offset to the passed in Vector. + /// + /// The wound AEmitter to add. + /// The vector to set as the wound AEmitter's parent offset. + /// Whether to gib this MOSRotating if adding this wound raises its wound count past its gib wound limit. Defaults to true. + void AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit = true) final; + + /// + /// Removes the specified number of wounds from this MOSRotating, and returns damage caused by these removed wounds. + /// Optionally removes wounds from Attachables (and their Attachables, etc.) that match the conditions set by the provided inclusion parameters. + /// + /// The number of wounds that should be removed. + /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. + /// The amount of damage caused by these wounds, taking damage multipliers into account. + float RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) override; #pragma endregion protected: diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 0af2e4bd4..5c29c4751 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -64,6 +64,7 @@ void MOSRotating::Clear() m_Attachables.clear(); m_ReferenceHardcodedAttachableUniqueIDs.clear(); m_HardcodedAttachableUniqueIDsAndSetters.clear(); + m_AttachableAndWoundMass = 0.0F; m_Gibs.clear(); m_GibImpulseLimit = 0; m_GibWoundLimit = 0; @@ -466,6 +467,7 @@ void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet } else { woundToAdd->SetParentOffset(parentOffsetToSet); woundToAdd->SetParent(this); + m_AttachableAndWoundMass += woundToAdd->GetMass(); m_Wounds.push_back(woundToAdd); } } @@ -503,6 +505,7 @@ float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachab return 0.0F; } float woundDamage = m_Wounds.front()->GetBurstDamage(); + m_AttachableAndWoundMass -= m_Wounds.front()->GetMass(); m_Wounds.pop_front(); return woundDamage; }; @@ -557,19 +560,6 @@ void MOSRotating::Destroy(bool notInherited) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float MOSRotating::GetMass() const { - float totalMass = MOSprite::GetMass(); - for (const Attachable *attachable : m_Attachables) { - totalMass += attachable->GetMass(); - } - for (const AEmitter *wound : m_Wounds) { - totalMass += wound->GetMass(); - } - return totalMass; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void MOSRotating::SetAsNoID() { MovableObject::SetAsNoID(); for (Attachable *attachable : m_Attachables) { @@ -1535,6 +1525,7 @@ void MOSRotating::AddAttachable(Attachable *attachable, const Vector& parentOffs if (g_MovableMan.ValidMO(attachable)) { g_MovableMan.RemoveMO(attachable); } attachable->SetParentOffset(parentOffsetToSet); attachable->SetParent(this); + m_AttachableAndWoundMass += attachable->GetMass(); m_Attachables.push_back(attachable); } } @@ -1560,6 +1551,7 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, if (m_Attachables.size() > 0) { m_Attachables.remove(attachable); } attachable->SetParent(nullptr); + m_AttachableAndWoundMass -= attachable->GetMass(); std::unordered_map>::iterator hardcodedAttachableMapEntry = m_HardcodedAttachableUniqueIDsAndSetters.find(attachable->GetUniqueID()); if (hardcodedAttachableMapEntry != m_HardcodedAttachableUniqueIDsAndSetters.end()) { @@ -1595,12 +1587,17 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void MOSRotating::DetachOrDestroyAll(bool destroy) { - for (Attachable *attachable : m_Attachables) { +void MOSRotating::RemoveOrDestroyAllAttachables(bool destroy) { + Attachable *attachable; + for (list::iterator attachableIterator = m_Attachables.begin(); attachableIterator != m_Attachables.end(); ) { + attachable = *attachableIterator; + RTEAssert(attachable, "Broken Attachable!"); + ++attachableIterator; + if (destroy) { delete attachable; } else { - attachable->SetParent(nullptr); + RemoveAttachable(attachable); } } m_Attachables.clear(); diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index fd3eb803c..7a7431410 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -140,7 +140,14 @@ ClassInfoGetters /// Gets the mass value of this MOSRotating, including the mass of all its Attachables and their Attachables and so on. /// /// The mass of this MOSRotating and all Attachables in Kilograms (kg). - float GetMass() const override; + float GetMass() const override { return MOSprite::GetMass() + m_AttachableAndWoundMass; } + + /// + /// Updates the total mass of Attachables and wounds for this MOSRotating, intended to be used when Attachables' masses get modified. Simply subtracts the old mass and adds the new one. + /// + /// The mass the Attachable or wound had before its mass was modified. + /// The up-to-date mass of the Attachable or wound after its mass was modified. + void UpdateAttachableAndWoundMass(float oldAttachableOrWoundMass, float newAttachableOrWoundMass) { m_AttachableAndWoundMass += newAttachableOrWoundMass - oldAttachableOrWoundMass; } /// /// Gets the MOIDs of this MOSRotating and all its Attachables and Wounds, putting them into the MOIDs vector. @@ -390,22 +397,21 @@ ClassInfoGetters void AddAttachable(Attachable *attachable); /// - /// Attaches the passed in Attachable and adds it to the list of Attachables, changing its parent offset to the passed in Vector but not treating it as hardcoded. /// Adds the passed in Attachable the list of Attachables, changes its parent offset to the passed in Vector, and sets its parent to this MOSRotating. /// /// The Attachable to add. /// The Vector to set as the Attachable's parent offset. - void AddAttachable(Attachable *attachable, const Vector& parentOffsetToSet); + virtual void AddAttachable(Attachable *attachable, const Vector& parentOffsetToSet); /// - /// Detaches the Attachable corresponding to the passed in UniqueID, and removes it from the appropriate Attachable lists. Does not add it to MovableMan or add break wounds. + /// Removes the Attachable corresponding to the passed in UniqueID and sets its parent to nullptr. Does not add it to MovableMan or add break wounds. /// /// The UniqueID of the the Attachable to remove. /// False if the Attachable is invalid, otherwise true. bool RemoveAttachable(long attachableUniqueID) { return RemoveAttachable(attachableUniqueID, false, false); } /// - /// Detaches the Attachable corresponding to the passed in UniqueID, and removes it from the appropriate Attachable lists. Optionally adds it to MovableMan and/or adds break wounds. + /// Removes the Attachable corresponding to the passed in UniqueID and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. /// /// The UniqueID of the the Attachable to remove. /// Whether or not to add the Attacahble to MovableMan once it has been removed. @@ -414,26 +420,26 @@ ClassInfoGetters bool RemoveAttachable(long attachableUniqueID, bool addToMovableMan, bool addBreakWounds); /// - /// Detaches the passed in Attachable and removes it from the appropriate Attachable lists. Does not add it to MovableMan or add break wounds. + /// Removes the passed in Attachable and sets its parent to nullptr. Does not add it to MovableMan or add break wounds. /// /// The Attachable to remove. /// False if the Attachable is invalid, otherwise true. bool RemoveAttachable(Attachable *attachable) { return RemoveAttachable(attachable, false, false); } /// - /// Detaches the passed in Attachable and removes it from the appropriate Attachable lists. Optionally adds it to MovableMan and/or adds break wounds. + /// Removes the passed in Attachable and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. /// /// The Attachable to remove. /// Whether or not to add the Attachable to MovableMan once it has been removed. /// Whether or not to add break wounds to the Attachable and this MOSRotating. /// False if the Attachable is invalid, otherwise true. - bool RemoveAttachable(Attachable *attachable, bool addToMovableMan, bool addBreakWounds); + virtual bool RemoveAttachable(Attachable *attachable, bool addToMovableMan, bool addBreakWounds); /// - /// Either detaches or deletes all of this MOSRotating's Attachables. + /// Either removes or deletes all of this MOSRotating's Attachables. /// - /// Whether to detach or delete the Attachables. Setting this to true deletes them, setting it to false detaches them. - void DetachOrDestroyAll(bool destroy); + /// Whether to remove or delete the Attachables. Setting this to true deletes them, setting it to false removes them. + void RemoveOrDestroyAllAttachables(bool destroy); ////////////////////////////////////////////////////////////////////////////////////////// @@ -626,15 +632,15 @@ ClassInfoGetters int GetWoundCount(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const; /// - /// Attaches the passed in wound AEmitter and adds it to the list of wounds, changing its parent offset to the passed in Vector. + /// Adds the passed in wound AEmitter to the list of wounds and changes its parent offset to the passed in Vector. /// /// The wound AEmitter to add. /// The vector to set as the wound AEmitter's parent offset. /// Whether to gib this MOSRotating if adding this wound raises its wound count past its gib wound limit. Defaults to true. - void AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit = true); + virtual void AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit = true); /// - /// Removes a specified number of wounds, including and returns damage caused by these wounds. + /// Removes the specified number of wounds from this MOSRotating, and returns damage caused by these removed wounds. /// Includes any Attachables (and their Attachables, etc.) that have a positive damage multiplier. /// /// The number of wounds that should be removed. @@ -642,15 +648,15 @@ ClassInfoGetters float RemoveWounds(int numberOfWoundsToRemove) { return RemoveWounds(numberOfWoundsToRemove, true, false, false); } /// - /// Removes a specified number of wounds and returns damage caused by these wounds. Head multiplier is not used. - /// Optionally adds removes wounds from Attachables (and their Attachables, etc.) that match the conditions set by the provided parameters. + /// Removes the specified number of wounds from this MOSRotating, and returns damage caused by these removed wounds. + /// Optionally removes wounds from Attachables (and their Attachables, etc.) that match the conditions set by the provided inclusion parameters. /// /// The number of wounds that should be removed. /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. /// The amount of damage caused by these wounds, taking damage multipliers into account. - float RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier); + virtual float RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier); ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetStringValue @@ -878,6 +884,7 @@ ClassInfoGetters std::list m_Attachables; std::unordered_set m_ReferenceHardcodedAttachableUniqueIDs; //!< An unordered set is filled with the Unique IDs of all of the reference object's hardcoded Attachables when using the copy Create. std::unordered_map> m_HardcodedAttachableUniqueIDsAndSetters; //!< An unordered map of Unique IDs to setter lambda functions, used to call the appropriate hardcoded Attachable setter when a hardcoded Attachable is removed. + float m_AttachableAndWoundMass; //!< The mass of all Attachables and wounds on this MOSRotating. Used in combination with its actual mass and any other affecting factors to get its total mass. // The list of Gib:s this will create when gibbed std::list m_Gibs; // The amount of impulse force required to gib this, in kg * (m/s). 0 means no limit diff --git a/Entities/TDExplosive.cpp b/Entities/TDExplosive.cpp index 5a98a8b46..74e6d2885 100644 --- a/Entities/TDExplosive.cpp +++ b/Entities/TDExplosive.cpp @@ -12,15 +12,23 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - int TDExplosive::Create(const TDExplosive &reference) { - ThrownDevice::Create(reference); + int TDExplosive::Create() { + if (ThrownDevice::Create() < 0) { + return -1; + } - m_IsAnimatedManually = reference.m_IsAnimatedManually; + if (IsInGroup("Bombs - Payloads")) { m_HUDVisible = false; } - // All Explosives should hit against other objects etc, like grenades flying and hitting actors etc EXCEPT when they are laying on the ground etc - m_IgnoresAGHitsWhenSlowerThan = 1.0F; + return 0; + } - if (IsInGroup("Bombs - Payloads")) { m_HUDVisible = false; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + int TDExplosive::Create(const TDExplosive &reference) { + if (ThrownDevice::Create(reference) < 0) { + return -1; + } + m_IsAnimatedManually = reference.m_IsAnimatedManually; return 0; } @@ -54,25 +62,16 @@ namespace RTE { ThrownDevice::Update(); if (m_Activated) { - // If not animated manually, play 'fuse lit' animation m_SpriteAnimMode = !m_IsAnimatedManually ? ALWAYSLOOP : NOANIM; m_RestTimer.Reset(); m_ToSettle = false; } - // Blow up if the activation timer has reached the trigger delay limit - if (m_Activated && m_ActivationTimer.GetElapsedSimTimeMS() >= m_TriggerDelay) { - m_Activated = false; - GibThis(); - } + if (m_Activated && m_ActivationTimer.GetElapsedSimTimeMS() >= m_TriggerDelay) { GibThis(); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void TDExplosive::DrawHUD(BITMAP *targetBitmap, const Vector &targetPos, int whichScreen, bool playerControlled) { - if (!m_HUDVisible) { - return; - } - // Only draw the pickup HUD if not activated - if (!m_Activated) { ThrownDevice::DrawHUD(targetBitmap, targetPos, whichScreen); } + if (m_HUDVisible && !m_Activated) { ThrownDevice::DrawHUD(targetBitmap, targetPos, whichScreen); } } } \ No newline at end of file diff --git a/Entities/TDExplosive.h b/Entities/TDExplosive.h index 6065172f0..03f2cb0be 100644 --- a/Entities/TDExplosive.h +++ b/Entities/TDExplosive.h @@ -22,6 +22,12 @@ namespace RTE { /// TDExplosive() { Clear(); } + /// + /// Makes the TDExplosive object ready for use. + /// + /// An error return value signaling success or any particular failure. Anything below 0 is an error signal. + int Create() override; + /// /// Creates a TDExplosive to be identical to another, by deep copy. /// From 0267459ca458fda7b370df56d9b86a7df1c8690c Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 6 Oct 2020 01:54:06 -0300 Subject: [PATCH 064/144] Added override methods for overloads of add and remove Attachable and remove wounds. cpp is fucking dumb so this is needed to prevent hiding other unrelated overloads Trimmed off all the comments for these since apparently Doxygen should be smort when there's no comments and use the preceding class' comments. Unfortunately seems to be no way to make VS smort like this for cpp. --- Entities/Attachable.h | 46 ++++++++++++++---------------------------- Entities/MOSRotating.h | 10 ++++----- 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 7de7e4fff..a253227d1 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -377,46 +377,30 @@ namespace RTE { /// Updates this Attachable. Supposed to be done every frame. /// void Update() override; +#pragma endregion - /// - /// Sets the mass of this Attachable. - /// - /// A float specifying the new mass value in Kilograms (kg). +#pragma region Override Methods for Handling Mass + /* + NOTE: Method comments are left blank here so Doxygen will treat them as inherited. Unfortunately there's no way to make VS do this for C++ (inheritdoc tag doesn't work). + */ void SetMass(const float newMass) final; - /// - /// Adds the passed in Attachable the list of Attachables, changes its parent offset to the passed in Vector, and sets its parent to this MOSRotating. - /// - /// The Attachable to add. - /// The Vector to set as the Attachable's parent offset. + void AddAttachable(Attachable *attachable) final { MOSRotating::AddAttachable(attachable); } + void AddAttachable(Attachable *attachable, const Vector &parentOffsetToSet) final; - /// - /// Removes the passed in Attachable and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. - /// - /// The Attachable to remove. - /// Whether or not to add the Attachable to MovableMan once it has been removed. - /// Whether or not to add break wounds to the Attachable and this MOSRotating. - /// False if the Attachable is invalid, otherwise true. + bool RemoveAttachable(long attachableUniqueID) final { return MOSRotating::RemoveAttachable(attachableUniqueID); } + + bool RemoveAttachable(long attachableUniqueID, bool addToMovableMan, bool addBreakWounds) final { return MOSRotating::RemoveAttachable(attachableUniqueID, addToMovableMan, addBreakWounds); } + + bool RemoveAttachable(Attachable *attachable) final { return MOSRotating::RemoveAttachable(attachable); } + bool RemoveAttachable(Attachable *attachable, bool addToMovableMan, bool addBreakWounds) final; - /// - /// Adds the passed in wound AEmitter to the list of wounds and changes its parent offset to the passed in Vector. - /// - /// The wound AEmitter to add. - /// The vector to set as the wound AEmitter's parent offset. - /// Whether to gib this MOSRotating if adding this wound raises its wound count past its gib wound limit. Defaults to true. void AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit = true) final; - /// - /// Removes the specified number of wounds from this MOSRotating, and returns damage caused by these removed wounds. - /// Optionally removes wounds from Attachables (and their Attachables, etc.) that match the conditions set by the provided inclusion parameters. - /// - /// The number of wounds that should be removed. - /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. - /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. - /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. - /// The amount of damage caused by these wounds, taking damage multipliers into account. + float RemoveWounds(int numberOfWoundsToRemove) final { return MOSRotating::RemoveWounds(numberOfWoundsToRemove); } + float RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) override; #pragma endregion diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 7a7431410..149f8bfec 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -394,7 +394,7 @@ ClassInfoGetters /// Adds the passed in Attachable the list of Attachables and sets its parent to this MOSRotating. /// /// The Attachable to add. - void AddAttachable(Attachable *attachable); + virtual void AddAttachable(Attachable *attachable); /// /// Adds the passed in Attachable the list of Attachables, changes its parent offset to the passed in Vector, and sets its parent to this MOSRotating. @@ -408,7 +408,7 @@ ClassInfoGetters /// /// The UniqueID of the the Attachable to remove. /// False if the Attachable is invalid, otherwise true. - bool RemoveAttachable(long attachableUniqueID) { return RemoveAttachable(attachableUniqueID, false, false); } + virtual bool RemoveAttachable(long attachableUniqueID) { return RemoveAttachable(attachableUniqueID, false, false); } /// /// Removes the Attachable corresponding to the passed in UniqueID and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. @@ -417,14 +417,14 @@ ClassInfoGetters /// Whether or not to add the Attacahble to MovableMan once it has been removed. /// Whether or not to add break wounds to the Attachable and this MOSRotating. /// False if the Attachable is invalid, otherwise true. - bool RemoveAttachable(long attachableUniqueID, bool addToMovableMan, bool addBreakWounds); + virtual bool RemoveAttachable(long attachableUniqueID, bool addToMovableMan, bool addBreakWounds); /// /// Removes the passed in Attachable and sets its parent to nullptr. Does not add it to MovableMan or add break wounds. /// /// The Attachable to remove. /// False if the Attachable is invalid, otherwise true. - bool RemoveAttachable(Attachable *attachable) { return RemoveAttachable(attachable, false, false); } + virtual bool RemoveAttachable(Attachable *attachable) { return RemoveAttachable(attachable, false, false); } /// /// Removes the passed in Attachable and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. @@ -645,7 +645,7 @@ ClassInfoGetters /// /// The number of wounds that should be removed. /// The amount of damage caused by these wounds, taking damage multipliers into account. - float RemoveWounds(int numberOfWoundsToRemove) { return RemoveWounds(numberOfWoundsToRemove, true, false, false); } + virtual float RemoveWounds(int numberOfWoundsToRemove) { return RemoveWounds(numberOfWoundsToRemove, true, false, false); } /// /// Removes the specified number of wounds from this MOSRotating, and returns damage caused by these removed wounds. From 786d02f8e8cb935a73d2e252bc84e86046ee1426 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 6 Oct 2020 02:06:49 -0300 Subject: [PATCH 065/144] Chucking in a TODO and an experimental Assert. I think the assert might punish lua modders though, so maybe it should be removed in future, but it's a nice safety note right now cause if it ever gets triggered that's bad Dealing with a lua binding problem caused by Arm being garbage still --- Entities/AHuman.cpp | 1 + Entities/MOSRotating.cpp | 1 + Managers/LuaMan.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index b93196c26..502e1042a 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -4356,6 +4356,7 @@ void AHuman::DrawThrowingReticule(BITMAP *pTargetBitmap, const Vector &targetPos void AHuman::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { Actor::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + //TODO simplify this complex if check when arm is cleaned up like turret so all it can hold are HeldDevices and children // Draw background Arm's hand after the HeldDevice of FGArm is drawn if the FGArm is holding a weapon. DrawMode realMode = (mode == g_DrawColor && m_FlashWhiteMS) ? g_DrawWhite : mode; if (m_pFGArm && m_pBGArm && !onlyPhysical && mode == g_DrawColor && m_pBGArm->DidReach() && m_pFGArm->HoldsHeldDevice() && !m_pFGArm->HoldsThrownDevice() && !m_pFGArm->GetHeldDevice()->IsReloading() && !m_pFGArm->GetHeldDevice()->IsShield()) { diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 5c29c4751..6c7fd9240 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1522,6 +1522,7 @@ void MOSRotating::AddAttachable(Attachable *attachable) { void MOSRotating::AddAttachable(Attachable *attachable, const Vector& parentOffsetToSet) { if (attachable) { + RTEAssert(!attachable->IsAttached(), "Tried to add Attachable " + attachable->GetModuleAndPresetName() + " but it already has a parent, " + (attachable->GetParent() ? attachable->GetParent()->GetModuleAndPresetName() : "ERROR") + "."); if (g_MovableMan.ValidMO(attachable)) { g_MovableMan.RemoveMO(attachable); } attachable->SetParentOffset(parentOffsetToSet); attachable->SetParent(this); diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index bf23fa27e..d7e659900 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -993,6 +993,7 @@ int LuaMan::Create() .def("SetClosedByDefault", &ADoor::SetClosedByDefault), ABSTRACTLUABINDING(Arm, Attachable) + .property("HeldDevice", &Arm::GetHeldMO) .property("IdleOffset", &Arm::GetIdleOffset, &Arm::SetIdleOffset) .property("GripStrength", &Arm::GetGripStrength, &Arm::SetGripStrength) .property("HandPos", &Arm::GetHandPos, &Arm::SetHandPos), From b08c1b15900744700c01616afe028eaaab13b76c Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 6 Oct 2020 03:07:45 -0300 Subject: [PATCH 066/144] Sneaking in a couple little code quality improvements - AEmitter read property iterating for stuff is now a range for loop and Attachable Atom addition/removal uses the pre-existing variable for the parent atomgroup instead of getting it again --- Entities/AEmitter.cpp | 12 ++++-------- Entities/Attachable.cpp | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index af6895652..f4ee79257 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -133,10 +133,8 @@ int AEmitter::ReadProperty(std::string propName, Reader &reader) { } else if (propName == "ParticlesPerMinute") { float ppm; reader >> ppm; - // Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility - for (list::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr) { - (*eItr)->m_PPM = ppm / m_EmissionList.size(); - } + // Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility. + for (Emission *emission : m_EmissionList) { emission->m_PPM = ppm; } } else if (propName == "MinThrottleRange") { reader >> m_MinThrottleRange; } else if (propName == "MaxThrottleRange") { @@ -148,10 +146,8 @@ int AEmitter::ReadProperty(std::string propName, Reader &reader) { } else if (propName == "BurstSize") { int burstSize; reader >> burstSize; - // Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility - for (list::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr) { - (*eItr)->m_BurstSize = ceilf((float)burstSize / (float)m_EmissionList.size()); - } + // Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility. + for (Emission *emission : m_EmissionList) { emission->m_BurstSize = std::ceil(static_cast(burstSize) / static_cast(m_EmissionList.size())); } } else if (propName == "BurstScale") { reader >> m_BurstScale; } else if (propName == "BurstDamage") { diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 0fb2598df..b8bf6a24b 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -440,9 +440,9 @@ namespace RTE { if (addAtoms && !rootParentAtomGroup->ContainsSubGroup(GetAtomSubgroupID())) { Vector atomOffsetForSubgroup; CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); - rootParentAsMOSR->GetAtomGroup()->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), atomOffsetForSubgroup); + rootParentAtomGroup->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), atomOffsetForSubgroup); } else if (!addAtoms && rootParentAtomGroup->ContainsSubGroup(GetAtomSubgroupID())) { - rootParentAsMOSR->GetAtomGroup()->RemoveAtoms(GetAtomSubgroupID()); + rootParentAtomGroup->RemoveAtoms(GetAtomSubgroupID()); } } } From 11129a95df7739e9999d67459d2e57f2f17cd888 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 6 Oct 2020 18:08:04 -0300 Subject: [PATCH 067/144] Cleaned up some comments, added ini support in ACrab for spelled out versions of leg stuff (e.g. LeftFGLeg instead of LFGLeg) --- Entities/ACrab.cpp | 24 ++++++++++++------------ Entities/Attachable.cpp | 2 +- Entities/Attachable.h | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index d98eae4c4..07e3e04cb 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -257,33 +257,33 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; m_JetTimeTotal *= 1000; - } else if (propName == "LFGLeg") { + } else if (propName == "LFGLeg" || propName == "LeftFGLeg") { RemoveAttachable(m_pLFGLeg); m_pLFGLeg = new Leg; reader >> m_pLFGLeg; AddAttachable(m_pLFGLeg); if (!m_pLFGLeg->GetDamageMultiplierSetInINI()) { m_pLFGLeg->SetDamageMultiplier(1.0F); } m_pLFGLeg->SetInheritsHFlipped(2); - } else if (propName == "LBGLeg") { + } else if (propName == "LBGLeg" || propName == "LeftFGLeg") { RemoveAttachable(m_pLBGLeg); m_pLBGLeg = new Leg; reader >> m_pLBGLeg; AddAttachable(m_pLBGLeg); if (!m_pLBGLeg->GetDamageMultiplierSetInINI()) { m_pLBGLeg->SetDamageMultiplier(1.0F); } m_pLBGLeg->SetInheritsHFlipped(2); - } else if (propName == "RFGLeg") { + } else if (propName == "RFGLeg" || propName == "LeftFGLeg") { RemoveAttachable(m_pRFGLeg); m_pRFGLeg = new Leg; reader >> m_pRFGLeg; AddAttachable(m_pRFGLeg); if (!m_pRFGLeg->GetDamageMultiplierSetInINI()) { m_pRFGLeg->SetDamageMultiplier(1.0F); } - } else if (propName == "RBGLeg") { + } else if (propName == "RBGLeg" || propName == "LeftFGLeg") { RemoveAttachable(m_pRBGLeg); m_pRBGLeg = new Leg; reader >> m_pRBGLeg; AddAttachable(m_pRBGLeg); if (!m_pRBGLeg->GetDamageMultiplierSetInINI()) { m_pRBGLeg->SetDamageMultiplier(1.0F); } - } else if (propName == "LFootGroup") { + } else if (propName == "LFootGroup" || propName == "LeftFootGroup") { delete m_pLFGFootGroup; delete m_pLBGFootGroup; m_pLFGFootGroup = new AtomGroup(); @@ -292,7 +292,7 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) m_pLBGFootGroup->Create(*m_pLFGFootGroup); m_pLFGFootGroup->SetOwner(this); m_pLBGFootGroup->SetOwner(this); - } else if (propName == "RFootGroup") { + } else if (propName == "RFootGroup" || propName == "RightFootGroup") { delete m_pRFGFootGroup; delete m_pRBGFootGroup; m_pRFGFootGroup = new AtomGroup(); @@ -303,17 +303,17 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) m_pRBGFootGroup->SetOwner(this); } else if (propName == "StrideSound") { reader >> m_StrideSound; - } else if (propName == "LStandLimbPath") { + } else if (propName == "LStandLimbPath" || propName == "LeftStandLimbPath") { reader >> m_Paths[LEFTSIDE][FGROUND][STAND]; - } else if (propName == "LWalkLimbPath") { + } else if (propName == "LWalkLimbPath" || propName == "LeftWalkLimbPath") { reader >> m_Paths[LEFTSIDE][FGROUND][WALK]; - } else if (propName == "LDislodgeLimbPath") { + } else if (propName == "LDislodgeLimbPath" || propName == "LeftDislodgeLimbPath") { reader >> m_Paths[LEFTSIDE][FGROUND][DISLODGE]; - } else if (propName == "RStandLimbPath") { + } else if (propName == "RStandLimbPath" || propName == "RightStandLimbPath") { reader >> m_Paths[RIGHTSIDE][FGROUND][STAND]; - } else if (propName == "RWalkLimbPath") { + } else if (propName == "RWalkLimbPath" || propName == "RightWalkLimbPath") { reader >> m_Paths[RIGHTSIDE][FGROUND][WALK]; - } else if (propName == "RDislodgeLimbPath") { + } else if (propName == "RDislodgeLimbPath" || propName == "RightDislodgeLimbPath") { reader >> m_Paths[RIGHTSIDE][FGROUND][DISLODGE]; } else if (propName == "AimRangeUpperLimit") { reader >> m_AimRangeUpperLimit; diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index b8bf6a24b..6d7c4f7f8 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -315,7 +315,7 @@ namespace RTE { MOSRotating *rootParentAsMOSR = dynamic_cast(GetRootParent()); if (rootParentAsMOSR && m_CollidesWithTerrainWhileAttached) { - // This safety check exists to ensure the parent's AtomGroup contains this Attachable's Atoms in a subgroup. Hardcoded Attachables need this in order to work, since they're cloned before their parent's AtomGroup exists. + // Note: This safety check exists to ensure the parent's AtomGroup contains this Attachable's Atoms in a subgroup. Hardcoded Attachables need this in order to work, since they're cloned before their parent's AtomGroup exists. if (!rootParentAsMOSR->GetAtomGroup()->ContainsSubGroup(m_AtomSubgroupID)) { AddOrRemoveAtomsFromRootParentAtomGroup(true); } float facingAngle = (m_HFlipped ? c_PI : 0) + GetRotAngle() * static_cast(GetFlipFactor()); diff --git a/Entities/Attachable.h b/Entities/Attachable.h index a253227d1..196f5311d 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -424,7 +424,7 @@ namespace RTE { float m_GibWithParentChance; //!< The percentage chance that this Attachable will gib when its parent does. 0 means never, 1 means always. float m_ParentGibBlastStrengthMultiplier; //!< The multiplier this Attacahble will apply to its parent's gib blast strength when the parent gibs. - float m_JointStrength; //!< The amount of impulse force needed on this to deatch it from the host Actor, in kg * m/s. + float m_JointStrength; //!< The amount of impulse force needed on this to deatch it from the host Actor, in kg * m/s. A value of 0 means the join is infinitely strong and will never break naturally. float m_JointStiffness; //!< The normalized joint stiffness scalar. 1.0 means impulse forces on this attachable will be transferred to the parent with 100% strength, 0 means they will not transfer at all. Vector m_JointOffset; //!< The offset to the joint (the point around which this Attachable and its parent hinge) from its center of mass/origin. Vector m_JointPos; //!< The absolute position of the joint that the parent sets upon Update() if this Attachable is attached to it. From 129369613b20f7eea62deaac1991b68d0f0009bb Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 6 Oct 2020 18:10:41 -0300 Subject: [PATCH 068/144] Updated changelog with a myriad of things --- CHANGELOG.md | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdbf45ea5..5ac9ec610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -144,6 +144,35 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Exposed PEmitter to lua. Bindings are identical to AEmitter's bindings, except that damage-related bindings don't exist for PEmitter. +- Added Lua (R/W) properties for all hardcoded Attachables. You can now set them on the fly to be created objects of the relevant type. Note that trying to set things inappropriately (e.g. setting an HDFirearm as something's Leg) will probably crash the game; that's your problem to deal with. + You can read and write the following properties: + AHuman - `Head, Jetpack, FGArm, BGArm, FGLeg, BGLeg, FGFoot, BGFoot` + ACrab - `Turret, Jetpack, LeftFGLeg, LeftBGLeg, RightFGLeg, RightBGLeg` + ACDropship - `RightEngine, LeftEngine, RightThruster, LeftThruster, RightHatch, LeftHatch` + ACRocket - `RightLeg, LeftLeg, MainEngine, LeftEngine, RightEngine, LeftThruster, RightThruster` + ADoor - `Door` + Turret - `MountedDevice` + Leg - `Foot` + HDFirearm - `Magazine, Flash` + AEmitter - `Flash` + +- Added `Vector:ClampMagnitude(upperLimit, lowerLimit)` Lua function that lets you limit a Vector's upper and lower magnitude. + +- Added `MOSRotating GibBlastStrength` INI and Lua (R/W) property. This lets you define how much force created `Gibs` and any `Attachables` will get launched when the MOSRotating gibs. + +- New INI and Lua (R/W) properties for Attachables: + `ParentBreakWound = AEmitter...` allows you to optionally define different BreakWounds for the `Attachable` and its parent. By default it matches `BreakWound` for ease of use.ma + `InheritsHFlipped = 0/1/2` allows you to define whether the `Attachable` will inherit its parent's HFlipped value or not. 0 means no inheritance, 1 means normal inheritance, 2 means reversed inheritance (technically any value other than 0 or 1 will act as reversed inheritance). Defaults to 1 to preserve normal behaviour. + `InheritedRotAngleRadOffset = angle` and `InheritedRotAngleDegOffset = angle` allow you specify an offset to keep an `Attachable's` rotation at when `InheritsRotAngle` is set to true. In Lua there's only `InheritedRotAngleOffset` which takes/returns radians, to avoid confusion. For example, `InheritedRotAngleDegOffset = 90` would make the Attachable always face perpendicular to its parent. Does nothing if the `Attachable's` `InheritsRotAngle` is set to false or the `Attachable` has no parent. + `GibWithParentChance = 0 - 1` allows you to specify whether this `Attachable` should be gibbed when its parent does and what the chance of that happening is. 0 means never, 1 means always. + `ParentGibBlastStrengthMultiplier = number` allows you to specify the multiplier this `Attachable` will apply to its parent's gib blast strength when the parent gibs. Usually this would be a positive number, but it doesn't have to be. + +- New INI and Lua (R/W) `Arm` property `GripStrength`. This effectively replaces the `JointStrength` of the held `HeldDevice`, allowing `Arms` to control how tightly equipment is held. + +- New INI and Lua (R/W) `HeldDevice` property `GripStrengthMultiplier`. This allows `HeldDevices` to multiply the `GripStrength` of their `Arms` to support them being more or less easy to hold. + +- New Lua `MovableObject` function `GetWhichMOToNotHit`. This provides access to the MO that has been set to not be hit by `SetWhichMOToNotHit`. + ### Changed - Codebase now uses the C++17 standard. @@ -238,6 +267,46 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Scenes with a PresetName containing the strings "Test", "Editor" and "Tutorial" are no longer excluded from the scenarios screen and from the metagame. +- Hands will now draw in transparent drawing mode, i.e. editing menu. + +- `AHuman` background `Leg` will no longer draw in front of the `AHuman`. The real result of this is that the background foot will no longer draw in front of the foregroundone. + +- Everything draws better when flashing white, including crafts which used to be terrible at it. + +- Reworked Attachable managment + `DamageMultiplier` on `Attachables` now works as expected, all `Attachables` can now transfer damage to their root parent. This will travel up chains of `Attachables`, as long as every `Attachable` in the chain has a non-zero DamageMultiplier (yes, negative numbers are supported if you wanna be weird, have fun). + `Attachable` terrain collision has been reworked so that it can be changed simply by setting `CollidesWithTerrainWhileAttached = true/false` in INI or Lua. Also, `Attachables` attached to other `Attachables` will now collide with terrain properly. + `BreakWounds` on `Attachables` now gets added to both the `Attachable` and the parent when the `Attachable` is broken off. If `ParentBreakWound` is defined, the parent will use this instead of the regular `BreakWound`. + +- `Attachable.BreakWound` now has R/W access in Lua. + +- `Attachable.DeleteWithParent` is now `Attachable.DeleteWhenRemovedFromParent`, since this more accurately describes what it does. + +- `Attachable.OnlyLinearForces` has been renamed to `Attachable.ApplyTransferredForcesAtOffset` and its effect has been reversed, so something that checked `OnlyLinearForces == true` would now check `ApplyTransferredForcesAtOffset == false`, since this makes more sense to use. + +- `Arms` and `Legs` on `AHumans` will no longer bleed out indefinitely. If you want this to happen, adjust their `BreakWound` or `ParentBreakWound` accordingly. + +- Reworked wound management + Wound management is now always done with `MOSRotating` functions, instead of requiring different ones for `Actors`. This means TotalWoundCount and RemoveAnyRandomWounds no longer exist. + You can get all wounds with `GetWounds`, get the wound count with `GetWoundCount` (or using the pre-existing WoundCount property), get the gib wound limit with `GetGibWoundLimit` (or using the pre-existing GibWoundLimit property), and remove wounds with `RemoveWounds`. + All of these functions have two variants, one lets you just specify any normal arguments (e.g. number of wounds to remove), the other lets you also specify whether you want to include `Attachables` with a positive `DamageMultiplier` (i.e. `Attachables` that damage their parent), `Attachables` with a negative `DamageMultiplier` (i.e. `Attachables` that heal their parent) or `Attachables` with no `DamageMultiplier` (i.e. `Attachables` that don't affect their parent). + Without any arguments, these functions will only include `Attachables` with a positive `DamageMultiplier` in their counting calculations. The property variants (e.g. mosr.WoundCount) also behave this way. + Note that this process is recursive, so if an `Attachable` that satisfies the conditions has `Attachables` that also satisfy the conditions, their wounds will be included in the results. + +- Renamed `Turret` INI property `MountedMO` to `MountedDevice` to better match the new reality that `Turrets` can only mount `HeldDevices` and their child classes. + +- Renamed `ACrab` `LFGLeg`, `LBGLeg`, `RFGLeg` and `RBGLeg` Lua properties to `LeftFGLeg`, `LeftBGLeg`, `RightFGLeg`, `RightBGLeg` respectively, to be more consistent with other naming. + For the time being, the INI properties (as well as the ones for setting `FootGroups` and `LimbPaths`) support both single letter and written out versions (i.e. `LStandLimbPath` and `LeftStandLimbPath` are both supported). This single letter versions will probably be deprecated over time. + +- `MovableMan:AddMO` will now add to `HeldDevices` (or any child class) to its `Items` collection, making it able to provide the functionality of `AddParticle`, `AddActor` and `AddItem`. + +- Changed and cleaned up how gibbing works and how it affects `Attachables`. In particular, limbs will better inherit velocity during gibbing and things are more customizable. See `Attachable` properties for more details. + As an added bonus, `Attachables` on `ACDropShips` and `ACRockets` can now be shot down when the craft gibs; fight back against the baleful dropship engines! + +- Improved native recoil handling! Guns transfer recoil to arms/turrets, which transfer it to AHumans/ACrabs, all of it properly accounts for joint strengths (or grip strengths) and offsets at every step. ([Issue #7](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/issues/7) and [Issue #8](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/issues/8)). + +- Due to the nature of various `Attachable` and force transferral changes, AEmitters seem to apply far more force now, so `DropShip` engines may need higher `JointStrengths` and `GibImpulseLimits`, otherwise they may break off or gib during normal use. + ### Fixed - Fix crash when returning to `MetaGame` scenario screen after activity end. @@ -260,6 +329,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - The "woosh" sound played when switching actors from a distance will now take scene wrapping into account. Additionally, attempting to switch to previous or next actor with only one actor will play the more correct "error" sound. +- `MovableObject:SetWhichMOToNotHit` will now work properly for Attachables. They will also not hit the relevant MO. When they're removed, Attachables will check if they have the same MO for this value and, if so, unset it so they can hit that MO. + +- Craft sucking up objects now works properly again. + +- Getting the `Mass` of an `MOSRotating` has now been made more efficient. Additionally, `Attachables` of `Attachables` will now be included in Mass, so some things have gotten a lot heavier (e.g. Dummy Dreadnought). + +- The moment of inertia of `AtomGroups` now updates when the mass or Atoms change, meaning losing `Attachables` or changing mass will properly affect how rotational forces apply to MOSRotatings. + ### Removed - Removed the ability to remove scripts from objects with Lua. This is no longer needed cause of code efficiency increases. @@ -278,6 +355,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Removed `Attachable` Lua write capability for `AtomSubGroupID` as changing this can cause all kinds of problems, and `RotTarget` as this didn't actually work. +- Removed `MaxLength` property from `Leg`, since it was a mostly unused leftover caused by Leg being originally copied from Arm, and was actually a fake setting that just set other properties. To replace it, set the following: + ``` + ContractedOffset = Vector + X = //Old MaxLength/2 + Y = 0 + ExtendedOffset = Vector + X = //Old MaxLength + Y = 0 + ``` + +- Removed `Attachable.RotTarget` from Lua and INI. The property never worked and no longer exists. + +- Removed `Attachable:CollectDamage`, `Attachable:TransferJointForces` and `Attachable:TransferJointImpulses` Lua function definitions. These are internal functions that should never have been exposed to Lua. + +- Removed `MOSRotating:ApplyForces` and `MOSRotating:ApplyImpulses` Lua functions. These are both internal functions that should never have been exposed to Lua. + *** ## [0.1.0 pre-release 2][0.1.0-pre2] - 2020/05/08 From 16717f9b9723d33028605533307ac077afccfcbd Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 19 Oct 2020 02:06:03 -0300 Subject: [PATCH 069/144] Added limit to healing from attachables with negative damage multipliers, so you can't go past max health --- Entities/Actor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index 50fd495b5..4115d3df9 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -1464,13 +1464,14 @@ void Actor::Update() } ///////////////////////////////////// - // Take damage from wounds and wounds on Attachables + // Take damage/heal from wounds and wounds on Attachables for (AEmitter *wound : m_Wounds) { m_Health -= wound->CollectDamage() * m_DamageMultiplier; } for (Attachable *attachable : m_Attachables) { m_Health -= attachable->CollectDamage(); } + m_Health = std::min(m_MaxHealth, m_Health); ///////////////////////////////////////////// // Take damage from large hits during travel From 70c873932a014f9e558218d346f2042476b6db9c Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 19 Oct 2020 02:06:56 -0300 Subject: [PATCH 070/144] Whoops, changed order of min call with healing and forgot to stage it --- Entities/Actor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index 4115d3df9..23d66e776 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -1471,7 +1471,7 @@ void Actor::Update() for (Attachable *attachable : m_Attachables) { m_Health -= attachable->CollectDamage(); } - m_Health = std::min(m_MaxHealth, m_Health); + m_Health = std::min(m_Health, m_MaxHealth); ///////////////////////////////////////////// // Take damage from large hits during travel From b85bbd05ea7c86cefb1a91e05d9621036d536354 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 19 Oct 2020 02:13:59 -0300 Subject: [PATCH 071/144] PR review Fixed typo in Actor Fixed a for loop in AEmitter Fixed an extra RotAngle setting in AHuman Fixed various cruft, unused line, drawing with rounded ints instead of floored ints and typo in Arm Fixed unnecessary SetParent call and typo in Attachable Added TODO for efficiency, changed to std::clamp, fixed some assert text, added some more safety stuff in MOSRotating Fixed dumdum mistake in RTETools Fixed typos and changed some text in Changelog --- CHANGELOG.md | 6 +++--- Entities/AEmitter.cpp | 4 ++-- Entities/AHuman.cpp | 1 - Entities/Actor.cpp | 2 +- Entities/Arm.cpp | 15 ++++++--------- Entities/Attachable.cpp | 8 ++------ Entities/MOSRotating.cpp | 13 ++++++++----- System/RTETools.cpp | 4 ++-- 8 files changed, 24 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ac9ec610..6ff656732 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -269,12 +269,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Hands will now draw in transparent drawing mode, i.e. editing menu. -- `AHuman` background `Leg` will no longer draw in front of the `AHuman`. The real result of this is that the background foot will no longer draw in front of the foregroundone. +- `AHuman` background `Leg` will no longer draw in front of the `AHuman`. The real result of this is that the background foot will no longer draw in front of the foreground one. - Everything draws better when flashing white, including crafts which used to be terrible at it. - Reworked Attachable managment - `DamageMultiplier` on `Attachables` now works as expected, all `Attachables` can now transfer damage to their root parent. This will travel up chains of `Attachables`, as long as every `Attachable` in the chain has a non-zero DamageMultiplier (yes, negative numbers are supported if you wanna be weird, have fun). + `DamageMultiplier` on `Attachables` now works as expected, all `Attachables` can now transfer damage to their root parent. This will travel up chains of `Attachables`, as long as every `Attachable` in the chain has a non-zero DamageMultiplier (yes, negative numbers are supported if you wanna have healing instead of damage or weirdness with chaining negative multipliers). `Attachable` terrain collision has been reworked so that it can be changed simply by setting `CollidesWithTerrainWhileAttached = true/false` in INI or Lua. Also, `Attachables` attached to other `Attachables` will now collide with terrain properly. `BreakWounds` on `Attachables` now gets added to both the `Attachable` and the parent when the `Attachable` is broken off. If `ParentBreakWound` is defined, the parent will use this instead of the regular `BreakWound`. @@ -298,7 +298,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Renamed `ACrab` `LFGLeg`, `LBGLeg`, `RFGLeg` and `RBGLeg` Lua properties to `LeftFGLeg`, `LeftBGLeg`, `RightFGLeg`, `RightBGLeg` respectively, to be more consistent with other naming. For the time being, the INI properties (as well as the ones for setting `FootGroups` and `LimbPaths`) support both single letter and written out versions (i.e. `LStandLimbPath` and `LeftStandLimbPath` are both supported). This single letter versions will probably be deprecated over time. -- `MovableMan:AddMO` will now add to `HeldDevices` (or any child class) to its `Items` collection, making it able to provide the functionality of `AddParticle`, `AddActor` and `AddItem`. +- `MovableMan:AddMO` will now add `HeldDevices` (or any child class of `HeldDevice`) to its `Items` collection, making it able to provide the functionality of `AddParticle`, `AddActor` and `AddItem`. - Changed and cleaned up how gibbing works and how it affects `Attachables`. In particular, limbs will better inherit velocity during gibbing and things are more customizable. See `Attachable` properties for more details. As an added bonus, `Attachables` on `ACDropShips` and `ACRockets` can now be shot down when the craft gibs; fight back against the baleful dropship engines! diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index f4ee79257..d997c1c1a 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -75,8 +75,8 @@ int AEmitter::Create(const AEmitter &reference) { } Attachable::Create(reference); - for (list::const_iterator itr = reference.m_EmissionList.begin(); itr != reference.m_EmissionList.end(); ++itr) { - m_EmissionList.push_back(dynamic_cast((*itr)->Clone())); + for (const Emission *referenceEmission : reference.m_EmissionList) { + m_EmissionList.push_back(dynamic_cast(referenceEmission->Clone())); } m_EmissionSound = reference.m_EmissionSound; diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 210317cdf..dda5a4c2a 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -3983,7 +3983,6 @@ void AHuman::Update() if (m_pFGArm && m_pFGArm->IsAttached()) { m_pFGArm->SetRotAngle(m_AimAngle * static_cast(GetFlipFactor())); - m_pFGArm->SetRotAngle(m_HFlipped ? (-m_AimAngle/* + -m_Rotation*/) : (m_AimAngle/* + m_Rotation*/)); if (m_Status == STABLE) { if (m_ArmClimbing[FGROUND]) { diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index 23d66e776..df923139e 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -1008,7 +1008,7 @@ void Actor::GibThis(const Vector &impactImpulse, MovableObject *movableObjectToI // Generate the velocities procedurally velMin = m_GibBlastStrength / pObject->GetMass(); - velRange = 10.0f; + velRange = 10.0F; // Randomize the offset from center to be within the original object gibROffset.SetXY(m_MaxRadius * 0.35F * RandomNormalNum(), m_MaxRadius * 0.35F * RandomNormalNum()); diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index b6ca4feef..634c8be5c 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -202,17 +202,16 @@ HeldDevice * Arm::GetHeldDevice() const void Arm::SetHeldMO(MovableObject *newHeldMO) { if (newHeldMO == nullptr) { Attachable *heldMOAsAttachable = dynamic_cast(m_pHeldMO); - if (m_pHeldMO && heldMOAsAttachable && heldMOAsAttachable->IsAttachedTo(this)) { RemoveAttachable(heldMOAsAttachable); } + if (heldMOAsAttachable && heldMOAsAttachable->IsAttachedTo(this)) { RemoveAttachable(heldMOAsAttachable); } m_pHeldMO = nullptr; } else { //TODO All this needs cleaning up, this should do the basics, some other method should be responsible for replacing held things if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && dynamic_cast(m_pHeldMO)->IsAttachedTo(this)) { - HeldDevice *oldHeldDevice = dynamic_cast(m_pHeldMO); - if (oldHeldDevice->IsAttached()) { dynamic_cast(oldHeldDevice->GetParent())->RemoveAttachable(oldHeldDevice, true, false); } + RemoveAttachable(dynamic_cast(m_pHeldMO), true, false); m_pHeldMO = nullptr; } - if (newHeldMO && (newHeldMO->IsHeldDevice() || newHeldMO->IsThrownDevice())) { + if (newHeldMO->IsHeldDevice()) { Attachable *newHeldDevice = dynamic_cast(newHeldMO); if (newHeldDevice->IsAttached()) { dynamic_cast(newHeldDevice->GetParent())->RemoveAttachable(newHeldDevice); } AddAttachable(newHeldDevice); @@ -433,8 +432,6 @@ void Arm::Update() { // Make sure the weapon cannot be extended beyond the reach of the arm. ConstrainHand(); - float handAngle = m_HandOffset.GetAbsRadAngle(); - // In order to keep the HeldDevice in the right place, we need to convert its offset (the hand offset) to work as the ParentOffset for the HeldDevice. // The HeldDevice will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. Vector handOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_HandOffset; @@ -497,7 +494,7 @@ void Arm::Update() { handOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); pHeldDev->SetParentOffset(handOffsetAsParentOffset); - // If it blew up or whatever, releaes it from hand and put into scene so it'll be cleaned up properly + // If it blew up or whatever, release it from hand and put into scene so it'll be cleaned up properly if (m_pHeldMO->IsSetToDelete()) g_MovableMan.AddItem(ReleaseHeldMO()); } @@ -557,9 +554,9 @@ void Arm::DrawHand(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode } else { //TODO this won't draw flipped. It should draw onto a temp bitmap and then draw that flipped. Maybe it can reuse a temp bitmap from MOSR, maybe not? if (mode == g_DrawWhite) { - draw_character_ex(pTargetBitmap, m_pHand, handPos.GetRoundIntX(), handPos.GetRoundIntY(), g_WhiteColor, -1); + draw_character_ex(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntX(), g_WhiteColor, -1); } else { - draw_sprite_h_flip(pTargetBitmap, m_pHand, handPos.GetRoundIntX(), handPos.GetRoundIntY()); + draw_sprite_h_flip(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntX()); } } } diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 6d7c4f7f8..38d86754f 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -290,11 +290,7 @@ namespace RTE { void Attachable::GibThis(const Vector &impactImpulse, MovableObject *movableObjectToIgnore) { MOSRotating::GibThis(impactImpulse, movableObjectToIgnore); - if (m_Parent) { - m_Parent->RemoveAttachable(this, true, true); - } else { - SetParent(nullptr); - } + if (m_Parent) { m_Parent->RemoveAttachable(this, true, true); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -325,7 +321,7 @@ namespace RTE { Matrix atomRotationForSubgroup(facingAngle - parentFacingAngle); Vector atomOffsetForSubgroup; CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); - // Note: This line looks weird because CalculateAtomOffsetForSubgroup already adds JointOffset to the value, so we have to subtract it and added its rotated value instead. + // Note: This line looks weird because CalculateAtomOffsetForSubgroup already adds JointOffset to the value, so we have to subtract it and add its rotated value instead. atomOffsetForSubgroup += GetJointOffset() - (GetJointOffset() * atomRotationForSubgroup); rootParentAsMOSR->GetAtomGroup()->UpdateSubAtoms(GetAtomSubgroupID(), atomOffsetForSubgroup, atomRotationForSubgroup); } diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index b791689dc..e3cdbf73f 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -520,6 +520,7 @@ float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachab if (woundedPart == this) { damage += removeFirstWoundEmitter() * GetDamageMultiplier(); } else { + //TODO This is less efficient than it should be. We already collected all wounded parts and their wounds above, we should pass that in (make another function overload) instead of collecting everything again. It might be wise to use a tree for this purpose. damage += woundedPart->RemoveWounds(1, includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); } if (woundedParts[woundedPartIndex].second-- <= 0) { @@ -1432,9 +1433,9 @@ void MOSRotating::Update() { } if (m_OrientToVel > 0 && m_Vel.GetLargest() > 5.0) { - Clamp(m_OrientToVel, 1.0F, 0.0F); + m_OrientToVel = std::clamp(m_OrientToVel, 0.0F, 1.0F); - float velInfluence = Limit(m_OrientToVel < 1.0 ? m_Vel.GetMagnitude() / 100.0F : 1.0F, 1.0F, 0.0F); + float velInfluence = std::clamp(m_OrientToVel < 1.0 ? m_Vel.GetMagnitude() / 100.0F : 1.0F, 0.0F, 1.0F); float radsToGo = m_Rotation.GetRadAngleTo(m_Vel.GetAbsRadAngle()); m_Rotation += radsToGo * m_OrientToVel * velInfluence; } @@ -1547,7 +1548,7 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, if (!attachable || !attachable->IsAttached()) { return false; } - RTEAssert(attachable->IsAttachedTo(this), "Tried to remove attachable that was attached to another parent (" + (attachable->GetParent() ? attachable->GetParent()->GetModuleAndPresetName() : "ERROR") + ") Attachable (" + attachable->GetModuleAndPresetName() + "), this should never happen!"); + RTEAssert(attachable->IsAttachedTo(this), "Tried to remove Attachable " + attachable->GetModuleAndPresetName() + " from presumed parent " + GetModuleAndPresetName() + ", but it had a different parent (" + (attachable->GetParent() ? attachable->GetParent()->GetModuleAndPresetName() : "ERROR") + "). This should never happen!"); if (m_Attachables.size() > 0) { m_Attachables.remove(attachable); } attachable->SetParent(nullptr); @@ -1581,6 +1582,8 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, delete attachable; } else if (addToMovableMan || attachable->IsSetToDelete()) { g_MovableMan.AddMO(attachable); + } else { + RTEAbort("Tried to remove Attachable " + attachable->GetModuleAndPresetName() + " from parent " + GetModuleAndPresetName() + " but it was not set to delete, or be added to MovableMan, or delete when removed from parent. This should never happen."); } return true; } @@ -1880,10 +1883,10 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool MOSRotating::TransferForcesFromAttachable(Attachable *attachable) { - RTEAssert(attachable->IsAttached(), "Tried to transfer forces from Attachable (" + attachable->GetModuleAndPresetName() + ") with no parent, this should never happen!"); - RTEAssert(attachable->IsAttachedTo(this), "Tried to transfer forces from another parent's (" + attachable->GetParent()->GetModuleAndPresetName() + ") Attachable (" + attachable->GetModuleAndPresetName() + "), this should never happen!"); bool intact = false; if (attachable) { + RTEAssert(attachable->IsAttached(), "Tried to transfer forces from Attachable (" + attachable->GetModuleAndPresetName() + ") with no parent, this should never happen!"); + RTEAssert(attachable->IsAttachedTo(this), "Tried to transfer forces from another parent's (" + attachable->GetParent()->GetModuleAndPresetName() + ") Attachable (" + attachable->GetModuleAndPresetName() + "), this should never happen!"); if (attachable->IsSetToDelete()) { RemoveAttachable(attachable, true, true); } else if (attachable->IsAttached()) { diff --git a/System/RTETools.cpp b/System/RTETools.cpp index 5f4dc0ed8..72c14e3ff 100644 --- a/System/RTETools.cpp +++ b/System/RTETools.cpp @@ -136,11 +136,11 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - float DegreesToRadians(float angleInDegrees) { return angleInDegrees / c_PI * 180.0F; } + float DegreesToRadians(float angleInDegrees) { return angleInDegrees / 180.0F * c_PI; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - float RadiansToDegrees(float angleInRadians) { return angleInRadians / 180.0F * c_PI; } + float RadiansToDegrees(float angleInRadians) { return angleInRadians / c_PI * 180.0F; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// From 4ce5a2a35a7939dd19becd83d0cc53de0f0b10be Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 23 Oct 2020 00:15:47 -0300 Subject: [PATCH 072/144] Review comments Changed IsAttachedTo safety/efficiency checks when setting hardcoded attachables to IsAttached, so if they're attached to something else the game will appropriately error out. Fixed positions on hand drawing for Arm so it uses floor int everywhere, and doesn't accidentally have X in both places AddedFixed comment in Attachable about changing atom offsets for subgroups, and added TODO about it Added TODO in MOSR to make deletion more consistent --- Entities/ACDropShip.cpp | 24 ++++++++++++------------ Entities/ACRocket.cpp | 28 ++++++++++++++-------------- Entities/ACrab.cpp | 24 ++++++++++++------------ Entities/ADoor.cpp | 4 ++-- Entities/AEmitter.cpp | 4 ++-- Entities/AHuman.cpp | 24 ++++++++++++------------ Entities/Arm.cpp | 12 ++++++------ Entities/Attachable.cpp | 3 ++- Entities/HDFirearm.cpp | 8 ++++---- Entities/Leg.cpp | 4 ++-- Entities/MOSRotating.cpp | 1 + Entities/Turret.cpp | 4 ++-- 12 files changed, 71 insertions(+), 69 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 99b36c575..81e8b27b9 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -778,12 +778,12 @@ void ACDropShip::Update() void ACDropShip::SetRightThruster(Attachable *newThruster) { if (newThruster == nullptr) { - if (m_pRThruster && m_pRThruster->IsAttachedTo(this)) { RemoveAttachable(m_pRThruster); } + if (m_pRThruster && m_pRThruster->IsAttached()) { RemoveAttachable(m_pRThruster); } m_pRThruster = nullptr; } else { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { - RemoveAttachable(m_pRThruster); + if (m_pRThruster && m_pRThruster->IsAttached()) { RemoveAttachable(m_pRThruster); } m_pRThruster = castedNewThruster; AddAttachable(castedNewThruster); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightThruster(attachable); }}); @@ -795,12 +795,12 @@ void ACDropShip::SetRightThruster(Attachable *newThruster) { void ACDropShip::SetLeftThruster(Attachable *newThruster) { if (newThruster == nullptr) { - if (m_pLThruster && m_pLThruster->IsAttachedTo(this)) { RemoveAttachable(m_pLThruster); } + if (m_pLThruster && m_pLThruster->IsAttached()) { RemoveAttachable(m_pLThruster); } m_pLThruster = nullptr; } else { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { - RemoveAttachable(m_pLThruster); + if (m_pLThruster && m_pLThruster->IsAttached()) { RemoveAttachable(m_pLThruster); } m_pLThruster = castedNewThruster; AddAttachable(castedNewThruster); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftThruster(attachable); }}); @@ -812,12 +812,12 @@ void ACDropShip::SetLeftThruster(Attachable *newThruster) { void ACDropShip::SetURightThruster(Attachable *newThruster) { if (newThruster == nullptr) { - if (m_pURThruster && m_pURThruster->IsAttachedTo(this)) { RemoveAttachable(m_pURThruster); } + if (m_pURThruster && m_pURThruster->IsAttached()) { RemoveAttachable(m_pURThruster); } m_pURThruster = nullptr; } else { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { - RemoveAttachable(m_pURThruster); + if (m_pURThruster && m_pURThruster->IsAttached()) { RemoveAttachable(m_pURThruster); } m_pURThruster = castedNewThruster; AddAttachable(castedNewThruster); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetURightThruster(attachable); }}); @@ -829,12 +829,12 @@ void ACDropShip::SetURightThruster(Attachable *newThruster) { void ACDropShip::SetULeftThruster(Attachable *newThruster) { if (newThruster == nullptr) { - if (m_pULThruster && m_pULThruster->IsAttachedTo(this)) { RemoveAttachable(m_pULThruster); } + if (m_pULThruster && m_pULThruster->IsAttached()) { RemoveAttachable(m_pULThruster); } m_pULThruster = nullptr; } else { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { - RemoveAttachable(m_pULThruster); + if (m_pULThruster && m_pULThruster->IsAttached()) { RemoveAttachable(m_pULThruster); } m_pULThruster = castedNewThruster; AddAttachable(castedNewThruster); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetULeftThruster(attachable); }}); @@ -846,10 +846,10 @@ void ACDropShip::SetULeftThruster(Attachable *newThruster) { void ACDropShip::SetRightHatch(Attachable *newHatch) { if (newHatch == nullptr) { - if (m_pRHatch && m_pRHatch->IsAttachedTo(this)) { RemoveAttachable(m_pRHatch); } + if (m_pRHatch && m_pRHatch->IsAttached()) { RemoveAttachable(m_pRHatch); } m_pRHatch = nullptr; } else { - RemoveAttachable(m_pRHatch); + if (m_pRHatch && m_pRHatch->IsAttached()) { RemoveAttachable(m_pRHatch); } m_pRHatch = newHatch; AddAttachable(newHatch); m_HardcodedAttachableUniqueIDsAndSetters.insert({newHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightHatch(attachable); }}); @@ -860,10 +860,10 @@ void ACDropShip::SetRightHatch(Attachable *newHatch) { void ACDropShip::SetLeftHatch(Attachable *newHatch) { if (newHatch == nullptr) { - if (m_pLHatch && m_pLHatch->IsAttachedTo(this)) { RemoveAttachable(m_pLHatch); } + if (m_pLHatch && m_pLHatch->IsAttached()) { RemoveAttachable(m_pLHatch); } m_pLHatch = nullptr; } else { - RemoveAttachable(m_pLHatch); + if (m_pLHatch && m_pLHatch->IsAttached()) { RemoveAttachable(m_pLHatch); } m_pLHatch = newHatch; AddAttachable(newHatch); m_HardcodedAttachableUniqueIDsAndSetters.insert({newHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftHatch(attachable); }}); diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 8883c0a1d..591623cb1 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -845,12 +845,12 @@ void ACRocket::Update() void ACRocket::SetRightLeg(Attachable *newLeg) { if (newLeg == nullptr) { - if (m_pRLeg && m_pRLeg->IsAttachedTo(this)) { RemoveAttachable(m_pRLeg); } + if (m_pRLeg && m_pRLeg->IsAttached()) { RemoveAttachable(m_pRLeg); } m_pRLeg = nullptr; } else { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { - RemoveAttachable(m_pRLeg); + if (m_pRLeg && m_pRLeg->IsAttached()) { RemoveAttachable(m_pRLeg); } m_pRLeg = castedNewLeg; AddAttachable(castedNewLeg); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightLeg(attachable); }}); @@ -862,12 +862,12 @@ void ACRocket::SetRightLeg(Attachable *newLeg) { void ACRocket::SetLeftLeg(Attachable *newLeg) { if (newLeg == nullptr) { - if (m_pLLeg && m_pLLeg->IsAttachedTo(this)) { RemoveAttachable(m_pLLeg); } + if (m_pLLeg && m_pLLeg->IsAttached()) { RemoveAttachable(m_pLLeg); } m_pLLeg = nullptr; } else { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { - RemoveAttachable(m_pLLeg); + if (m_pLLeg && m_pLLeg->IsAttached()) { RemoveAttachable(m_pLLeg); } m_pLLeg = castedNewLeg; AddAttachable(castedNewLeg); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftLeg(attachable); }}); @@ -879,12 +879,12 @@ void ACRocket::SetLeftLeg(Attachable *newLeg) { void ACRocket::SetMainThruster(Attachable *newThruster) { if (newThruster == nullptr) { - if (m_pMThruster && m_pMThruster->IsAttachedTo(this)) { RemoveAttachable(m_pMThruster); } + if (m_pMThruster && m_pMThruster->IsAttached()) { RemoveAttachable(m_pMThruster); } m_pMThruster = nullptr; } else { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { - RemoveAttachable(m_pMThruster); + if (m_pMThruster && m_pMThruster->IsAttached()) { RemoveAttachable(m_pMThruster); } m_pMThruster = castedNewThruster; AddAttachable(castedNewThruster); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMainThruster(attachable); }}); @@ -896,12 +896,12 @@ void ACRocket::SetMainThruster(Attachable *newThruster) { void ACRocket::SetRightThruster(Attachable *newThruster) { if (newThruster == nullptr) { - if (m_pRThruster && m_pRThruster->IsAttachedTo(this)) { RemoveAttachable(m_pRThruster); } + if (m_pRThruster && m_pRThruster->IsAttached()) { RemoveAttachable(m_pRThruster); } m_pRThruster = nullptr; } else { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { - RemoveAttachable(m_pRThruster); + if (m_pRThruster && m_pRThruster->IsAttached()) { RemoveAttachable(m_pRThruster); } m_pRThruster = castedNewThruster; AddAttachable(castedNewThruster); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightThruster(attachable); }}); @@ -913,12 +913,12 @@ void ACRocket::SetRightThruster(Attachable *newThruster) { void ACRocket::SetLeftThruster(Attachable *newThruster) { if (newThruster == nullptr) { - if (m_pLThruster && m_pLThruster->IsAttachedTo(this)) { RemoveAttachable(m_pLThruster); } + if (m_pLThruster && m_pLThruster->IsAttached()) { RemoveAttachable(m_pLThruster); } m_pLThruster = nullptr; } else { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { - RemoveAttachable(m_pLThruster); + if (m_pLThruster && m_pLThruster->IsAttached()) { RemoveAttachable(m_pLThruster); } m_pLThruster = castedNewThruster; AddAttachable(castedNewThruster); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftThruster(attachable); }}); @@ -930,12 +930,12 @@ void ACRocket::SetLeftThruster(Attachable *newThruster) { void ACRocket::SetURightThruster(Attachable *newThruster) { if (newThruster == nullptr) { - if (m_pURThruster && m_pURThruster->IsAttachedTo(this)) { RemoveAttachable(m_pURThruster); } + if (m_pURThruster && m_pURThruster->IsAttached()) { RemoveAttachable(m_pURThruster); } m_pURThruster = nullptr; } else { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { - RemoveAttachable(m_pURThruster); + if (m_pURThruster && m_pURThruster->IsAttached()) { RemoveAttachable(m_pURThruster); } m_pURThruster = castedNewThruster; AddAttachable(castedNewThruster); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetURightThruster(attachable); }}); @@ -947,12 +947,12 @@ void ACRocket::SetURightThruster(Attachable *newThruster) { void ACRocket::SetULeftThruster(Attachable *newThruster) { if (newThruster == nullptr) { - if (m_pULThruster && m_pULThruster->IsAttachedTo(this)) { RemoveAttachable(m_pULThruster); } + if (m_pULThruster && m_pULThruster->IsAttached()) { RemoveAttachable(m_pULThruster); } m_pULThruster = nullptr; } else { AEmitter *castedNewThruster = dynamic_cast(newThruster); if (castedNewThruster) { - RemoveAttachable(m_pULThruster); + if (m_pULThruster && m_pULThruster->IsAttached()) { RemoveAttachable(m_pULThruster); } m_pULThruster = castedNewThruster; AddAttachable(castedNewThruster); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetULeftThruster(attachable); }}); diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 07e3e04cb..10dd6afe9 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -499,12 +499,12 @@ Attachable *ACrab::GetTurret() const { void ACrab::SetTurret(Attachable *newTurret) { if (newTurret == nullptr) { - if (m_pTurret && m_pTurret->IsAttachedTo(this)) { RemoveAttachable(m_pTurret); } + if (m_pTurret && m_pTurret->IsAttached()) { RemoveAttachable(m_pTurret); } m_pTurret = nullptr; } else { Turret *castedNewTurret = dynamic_cast(newTurret); if (castedNewTurret) { - RemoveAttachable(m_pTurret); + if (m_pTurret && m_pTurret->IsAttached()) { RemoveAttachable(m_pTurret); } m_pTurret = castedNewTurret; AddAttachable(castedNewTurret); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewTurret->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetTurret(attachable); }}); @@ -516,12 +516,12 @@ void ACrab::SetTurret(Attachable *newTurret) { void ACrab::SetJetpack(Attachable *newJetpack) { if (newJetpack == nullptr) { - if (m_pJetpack && m_pJetpack->IsAttachedTo(this)) { RemoveAttachable(m_pJetpack); } + if (m_pJetpack && m_pJetpack->IsAttached()) { RemoveAttachable(m_pJetpack); } m_pJetpack = nullptr; } else { AEmitter *castedNewJetpack = dynamic_cast(newJetpack); if (castedNewJetpack) { - RemoveAttachable(m_pJetpack); + if (m_pJetpack && m_pJetpack->IsAttached()) { RemoveAttachable(m_pJetpack); } m_pJetpack = castedNewJetpack; AddAttachable(castedNewJetpack); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetJetpack(attachable); }}); @@ -533,12 +533,12 @@ void ACrab::SetJetpack(Attachable *newJetpack) { void ACrab::SetLeftFGLeg(Attachable *newLeg) { if (newLeg == nullptr) { - if (m_pLFGLeg && m_pLFGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pLFGLeg); } + if (m_pLFGLeg && m_pLFGLeg->IsAttached()) { RemoveAttachable(m_pLFGLeg); } m_pLFGLeg = nullptr; } else { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { - RemoveAttachable(m_pLFGLeg); + if (m_pLFGLeg && m_pLFGLeg->IsAttached()) { RemoveAttachable(m_pLFGLeg); } m_pLFGLeg = castedNewLeg; AddAttachable(castedNewLeg); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftFGLeg(attachable); }}); @@ -550,12 +550,12 @@ void ACrab::SetLeftFGLeg(Attachable *newLeg) { void ACrab::SetLeftBGLeg(Attachable *newLeg) { if (newLeg == nullptr) { - if (m_pLBGLeg && m_pLBGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pLBGLeg); } + if (m_pLBGLeg && m_pLBGLeg->IsAttached()) { RemoveAttachable(m_pLBGLeg); } m_pLBGLeg = nullptr; } else { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { - RemoveAttachable(m_pLBGLeg); + if (m_pLBGLeg && m_pLBGLeg->IsAttached()) { RemoveAttachable(m_pLBGLeg); } m_pLBGLeg = castedNewLeg; AddAttachable(castedNewLeg); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftBGLeg(attachable); }}); @@ -567,12 +567,12 @@ void ACrab::SetLeftBGLeg(Attachable *newLeg) { void ACrab::SetRightFGLeg(Attachable *newLeg) { if (newLeg == nullptr) { - if (m_pRFGLeg && m_pRFGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pRFGLeg); } + if (m_pRFGLeg && m_pRFGLeg->IsAttached()) { RemoveAttachable(m_pRFGLeg); } m_pRFGLeg = nullptr; } else { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { - RemoveAttachable(m_pRFGLeg); + if (m_pRFGLeg && m_pRFGLeg->IsAttached()) { RemoveAttachable(m_pRFGLeg); } m_pRFGLeg = castedNewLeg; AddAttachable(castedNewLeg); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightFGLeg(attachable); }}); @@ -584,12 +584,12 @@ void ACrab::SetRightFGLeg(Attachable *newLeg) { void ACrab::SetRightBGLeg(Attachable *newLeg) { if (newLeg == nullptr) { - if (m_pRBGLeg && m_pRBGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pRBGLeg); } + if (m_pRBGLeg && m_pRBGLeg->IsAttached()) { RemoveAttachable(m_pRBGLeg); } m_pRBGLeg = nullptr; } else { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { - RemoveAttachable(m_pRBGLeg); + if (m_pRBGLeg && m_pRBGLeg->IsAttached()) { RemoveAttachable(m_pRBGLeg); } m_pRBGLeg = castedNewLeg; AddAttachable(castedNewLeg); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightBGLeg(attachable); }}); diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index bfafb18b9..6609efccc 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -205,10 +205,10 @@ namespace RTE { void ADoor::SetDoor(Attachable *newDoor) { if (newDoor == nullptr) { - if (m_Door && m_Door->IsAttachedTo(this)) { RemoveAttachable(m_Door); } + if (m_Door && m_Door->IsAttached()) { RemoveAttachable(m_Door); } m_Door = nullptr; } else { - RemoveAttachable(m_Door); + if (m_Door && m_Door->IsAttached()) { RemoveAttachable(m_Door); } m_Door = newDoor; AddAttachable(newDoor); m_HardcodedAttachableUniqueIDsAndSetters.insert({newDoor->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetDoor(attachable); }}); diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index d997c1c1a..0033f783d 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -370,10 +370,10 @@ float AEmitter::EstimateImpulse(bool burst) void AEmitter::SetFlash(Attachable *newFlash) { if (newFlash == nullptr) { - if (m_pFlash && m_pFlash->IsAttachedTo(this)) { RemoveAttachable(m_pFlash); } + if (m_pFlash && m_pFlash->IsAttached()) { RemoveAttachable(m_pFlash); } m_pFlash = nullptr; } else { - RemoveAttachable(m_pFlash); + if (m_pFlash && m_pFlash->IsAttached()) { RemoveAttachable(m_pFlash); } m_pFlash = newFlash; AddAttachable(newFlash); m_HardcodedAttachableUniqueIDsAndSetters.insert({newFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFlash(attachable); }}); diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index dda5a4c2a..4a2a6419c 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -486,10 +486,10 @@ Vector AHuman::GetEyePos() const void AHuman::SetHead(Attachable *newHead) { if (newHead == nullptr) { - if (m_pHead && m_pHead->IsAttachedTo(this)) { RemoveAttachable(m_pHead); } + if (m_pHead && m_pHead->IsAttached()) { RemoveAttachable(m_pHead); } m_pHead = nullptr; } else { - RemoveAttachable(m_pHead); + if (m_pHead && m_pHead->IsAttached()) { RemoveAttachable(m_pHead); } m_pHead = newHead; AddAttachable(newHead); m_HardcodedAttachableUniqueIDsAndSetters.insert({newHead->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetHead(attachable); }}); @@ -500,12 +500,12 @@ void AHuman::SetHead(Attachable *newHead) { void AHuman::SetJetpack(Attachable *newJetpack) { if (newJetpack == nullptr) { - if (m_pJetpack && m_pJetpack->IsAttachedTo(this)) { RemoveAttachable(m_pJetpack); } + if (m_pJetpack && m_pJetpack->IsAttached()) { RemoveAttachable(m_pJetpack); } m_pJetpack = nullptr; } else { AEmitter *castedNewJetpack = dynamic_cast(newJetpack); if (castedNewJetpack) { - RemoveAttachable(m_pJetpack); + if (m_pJetpack && m_pJetpack->IsAttached()) { RemoveAttachable(m_pJetpack); } m_pJetpack = castedNewJetpack; AddAttachable(castedNewJetpack); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetJetpack(attachable); }}); @@ -517,12 +517,12 @@ void AHuman::SetJetpack(Attachable *newJetpack) { void AHuman::SetFGArm(Attachable *newArm) { if (newArm == nullptr) { - if (m_pFGArm && m_pFGArm->IsAttachedTo(this)) { RemoveAttachable(m_pFGArm); } + if (m_pFGArm && m_pFGArm->IsAttached()) { RemoveAttachable(m_pFGArm); } m_pFGArm = nullptr; } else { Arm *castedNewArm = dynamic_cast(newArm); if (castedNewArm) { - RemoveAttachable(m_pFGArm); + if (m_pFGArm && m_pFGArm->IsAttached()) { RemoveAttachable(m_pFGArm); } m_pFGArm = castedNewArm; AddAttachable(castedNewArm); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFGArm(attachable); }}); @@ -534,12 +534,12 @@ void AHuman::SetFGArm(Attachable *newArm) { void AHuman::SetBGArm(Attachable *newArm) { if (newArm == nullptr) { - if (m_pBGArm && m_pBGArm->IsAttachedTo(this)) { RemoveAttachable(m_pBGArm); } + if (m_pBGArm && m_pBGArm->IsAttached()) { RemoveAttachable(m_pBGArm); } m_pBGArm = nullptr; } else { Arm *castedNewArm = dynamic_cast(newArm); if (castedNewArm) { - RemoveAttachable(m_pBGArm); + if (m_pBGArm && m_pBGArm->IsAttached()) { RemoveAttachable(m_pBGArm); } m_pBGArm = castedNewArm; AddAttachable(castedNewArm); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetBGArm(attachable); }}); @@ -551,12 +551,12 @@ void AHuman::SetBGArm(Attachable *newArm) { void AHuman::SetFGLeg(Attachable *newLeg) { if (newLeg == nullptr) { - if (m_pFGLeg && m_pFGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pFGLeg); } + if (m_pFGLeg && m_pFGLeg->IsAttached()) { RemoveAttachable(m_pFGLeg); } m_pFGLeg = nullptr; } else { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { - RemoveAttachable(m_pFGLeg); + if (m_pFGLeg && m_pFGLeg->IsAttached()) { RemoveAttachable(m_pFGLeg); } m_pFGLeg = castedNewLeg; AddAttachable(castedNewLeg); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFGLeg(attachable); }}); @@ -568,12 +568,12 @@ void AHuman::SetFGLeg(Attachable *newLeg) { void AHuman::SetBGLeg(Attachable *newLeg) { if (newLeg == nullptr) { - if (m_pBGLeg && m_pBGLeg->IsAttachedTo(this)) { RemoveAttachable(m_pBGLeg); } + if (m_pBGLeg && m_pBGLeg->IsAttached()) { RemoveAttachable(m_pBGLeg); } m_pBGLeg = nullptr; } else { Leg *castedNewLeg = dynamic_cast(newLeg); if (castedNewLeg) { - RemoveAttachable(m_pBGLeg); + if (m_pBGLeg && m_pBGLeg->IsAttached()) { RemoveAttachable(m_pBGLeg); } m_pBGLeg = castedNewLeg; AddAttachable(castedNewLeg); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetBGLeg(attachable); }}); diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 634c8be5c..8cde98915 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -202,11 +202,11 @@ HeldDevice * Arm::GetHeldDevice() const void Arm::SetHeldMO(MovableObject *newHeldMO) { if (newHeldMO == nullptr) { Attachable *heldMOAsAttachable = dynamic_cast(m_pHeldMO); - if (heldMOAsAttachable && heldMOAsAttachable->IsAttachedTo(this)) { RemoveAttachable(heldMOAsAttachable); } + if (heldMOAsAttachable && heldMOAsAttachable->IsAttached()) { RemoveAttachable(heldMOAsAttachable); } m_pHeldMO = nullptr; } else { //TODO All this needs cleaning up, this should do the basics, some other method should be responsible for replacing held things - if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && dynamic_cast(m_pHeldMO)->IsAttachedTo(this)) { + if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && dynamic_cast(m_pHeldMO)->IsAttached())) { RemoveAttachable(dynamic_cast(m_pHeldMO), true, false); m_pHeldMO = nullptr; } @@ -547,16 +547,16 @@ void Arm::DrawHand(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode if (!m_HFlipped) { if (mode == g_DrawWhite) { - draw_character_ex(pTargetBitmap, m_pHand, handPos.GetRoundIntX(), handPos.GetRoundIntY(), g_WhiteColor, -1); + draw_character_ex(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY(), g_WhiteColor, -1); } else { - draw_sprite(pTargetBitmap, m_pHand, handPos.GetRoundIntX(), handPos.GetRoundIntY()); + draw_sprite(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY()); } } else { //TODO this won't draw flipped. It should draw onto a temp bitmap and then draw that flipped. Maybe it can reuse a temp bitmap from MOSR, maybe not? if (mode == g_DrawWhite) { - draw_character_ex(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntX(), g_WhiteColor, -1); + draw_character_ex(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY(), g_WhiteColor, -1); } else { - draw_sprite_h_flip(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntX()); + draw_sprite_h_flip(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY()); } } } diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 38d86754f..05a386f44 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -321,7 +321,8 @@ namespace RTE { Matrix atomRotationForSubgroup(facingAngle - parentFacingAngle); Vector atomOffsetForSubgroup; CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); - // Note: This line looks weird because CalculateAtomOffsetForSubgroup already adds JointOffset to the value, so we have to subtract it and add its rotated value instead. + //TODO CalculateAtomOffsetForSubgroup should just return the rotated value. This means AtomGroup::AddAtoms needs to be modified to exect this rotated value instead of doing rotation internally. Alternatively, UpdateSubAtoms should expect unrotated atom offsets and deal with things interally, either way, it should be consistent. + // Note: This line looks weird because CalculateAtomOffsetForSubgroup already subtracts JointOffset from the value, so we have to re-add it and then subtract its rotated value instead. atomOffsetForSubgroup += GetJointOffset() - (GetJointOffset() * atomRotationForSubgroup); rootParentAsMOSR->GetAtomGroup()->UpdateSubAtoms(GetAtomSubgroupID(), atomOffsetForSubgroup, atomRotationForSubgroup); } diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index 22aae753c..675c112f8 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -305,12 +305,12 @@ void HDFirearm::Destroy(bool notInherited) void HDFirearm::SetMagazine(Attachable *newMagazine) { if (newMagazine == nullptr) { - if (m_pMagazine && m_pMagazine->IsAttachedTo(this)) { RemoveAttachable(m_pMagazine); } + if (m_pMagazine && m_pMagazine->IsAttached()) { RemoveAttachable(m_pMagazine); } m_pMagazine = nullptr; } else { Magazine *castedNewMagazine = dynamic_cast(newMagazine); if (castedNewMagazine) { - RemoveAttachable(m_pMagazine); + if (m_pMagazine && m_pMagazine->IsAttached()) { RemoveAttachable(m_pMagazine); } m_pMagazine = castedNewMagazine; AddAttachable(castedNewMagazine); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewMagazine->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMagazine(attachable); }}); @@ -322,10 +322,10 @@ void HDFirearm::SetMagazine(Attachable *newMagazine) { void HDFirearm::SetFlash(Attachable *newFlash) { if (newFlash == nullptr) { - if (m_pFlash && m_pFlash->IsAttachedTo(this)) { RemoveAttachable(m_pFlash); } + if (m_pFlash && m_pFlash->IsAttached()) { RemoveAttachable(m_pFlash); } m_pFlash = nullptr; } else { - RemoveAttachable(m_pFlash); + if (m_pFlash && m_pFlash->IsAttached()) { RemoveAttachable(m_pFlash); } m_pFlash = newFlash; AddAttachable(newFlash); m_HardcodedAttachableUniqueIDsAndSetters.insert({newFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFlash(attachable); }}); diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index 1fd1ee5d3..b981b61f9 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -133,10 +133,10 @@ namespace RTE { void Leg::SetFoot(Attachable *newFoot) { if (newFoot == nullptr) { - if (m_Foot && m_Foot->IsAttachedTo(this)) { RemoveAttachable(m_Foot); } + if (m_Foot && m_Foot->IsAttached()) { RemoveAttachable(m_Foot); } m_Foot = nullptr; } else { - RemoveAttachable(m_Foot); + if (m_Foot && m_Foot->IsAttached()) { RemoveAttachable(m_Foot); } m_Foot = newFoot; AddAttachable(newFoot); m_HardcodedAttachableUniqueIDsAndSetters.insert({newFoot->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFoot(attachable); }}); diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index e3cdbf73f..89a4804a3 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1578,6 +1578,7 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, } } } + //TODO Deletion should be made more consistent. Once other code is cleaned up and we can safely delete right away if the Attachable IsSetToDelete, we should do that. Alternatively we could add to MovableMan and let that take care of it in both deletion cases, but I think that may be a waste. Would need to investigate. if (!attachable->IsSetToDelete() && attachable->GetDeleteWhenRemovedFromParent()) { delete attachable; } else if (addToMovableMan || attachable->IsSetToDelete()) { diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index e1d6c4b66..6255bf4ff 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -62,12 +62,12 @@ namespace RTE { void Turret::SetMountedDevice(Attachable *newMountedDevice) { if (newMountedDevice == nullptr) { - if (m_MountedDevice && m_MountedDevice->IsAttachedTo(this)) { RemoveAttachable(m_MountedDevice); } + if (m_MountedDevice && m_MountedDevice->IsAttached()) { RemoveAttachable(m_MountedDevice); } m_MountedDevice = nullptr; } else { HeldDevice *castedNewMountedDevice = dynamic_cast(newMountedDevice); if (castedNewMountedDevice) { - RemoveAttachable(m_MountedDevice); + if (m_MountedDevice && m_MountedDevice->IsAttached()) { RemoveAttachable(m_MountedDevice); } m_MountedDevice = castedNewMountedDevice; AddAttachable(castedNewMountedDevice); m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewMountedDevice->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMountedDevice(attachable); }}); From 34ff1fea2eb2fa874de0a25632d8d6d92daadbbb Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 23 Oct 2020 00:29:44 -0300 Subject: [PATCH 073/144] Added necessary AtomGroup changes to make everything work. --- Entities/AtomGroup.cpp | 9 +++++++-- Entities/AtomGroup.h | 11 ++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Entities/AtomGroup.cpp b/Entities/AtomGroup.cpp index 606fcb512..594f780ad 100644 --- a/Entities/AtomGroup.cpp +++ b/Entities/AtomGroup.cpp @@ -202,10 +202,12 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// float AtomGroup::GetMomentOfInertia() { - if (m_MomentOfInertia == 0.0F) { + float currentOwnerMass = m_OwnerMOSR->GetMass(); + if (m_MomentOfInertia == 0.0F || std::abs(m_StoredOwnerMass - currentOwnerMass) >= (m_StoredOwnerMass / 10.0F)) { RTEAssert(m_OwnerMOSR, "Tried to calculate moment of inertia for an AtomGroup with no parent!"); - float distMass = m_OwnerMOSR->GetMass() / static_cast(m_Atoms.size()); + m_StoredOwnerMass = currentOwnerMass; + float distMass = m_StoredOwnerMass / static_cast(m_Atoms.size()); float radius = 0.0F; for (const Atom *atom : m_Atoms) { radius = atom->GetOffset().GetMagnitude() * c_MPP; @@ -229,9 +231,11 @@ namespace RTE { atomToAdd->SetSubID(subgroupID); atomToAdd->SetOffset(offset + (atomToAdd->GetOriginalOffset() * offsetRotation)); atomToAdd->SetOwner(m_OwnerMOSR); + atomToAdd->SetIgnoreMOIDsByGroup(&m_IgnoreMOIDs); m_Atoms.push_back(atomToAdd); m_SubGroups.at(subgroupID).push_back(atomToAdd); } + if (!atomList.empty()) { m_MomentOfInertia = 0.0F; } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -253,6 +257,7 @@ namespace RTE { } } m_SubGroups.erase(removeID); + if (removedAny) { m_MomentOfInertia = 0.0F; } return removedAny; } diff --git a/Entities/AtomGroup.h b/Entities/AtomGroup.h index 50795d8f4..29618ca3c 100644 --- a/Entities/AtomGroup.h +++ b/Entities/AtomGroup.h @@ -179,10 +179,11 @@ namespace RTE { #pragma region Atom Management /// /// Adds a new Atom into the internal list that makes up this AtomGroup. Ownership of the Atom IS transferred! + /// Note, this resets the moment of inertia, which then has to be recalculated. /// /// A pointer to an Atom that will pushed onto the end of the list. Ownership IS transferred! /// The subgroup ID that the new Atom will have within the group. - void AddAtom(Atom *newAtom, long subgroupID = 0) { newAtom->SetSubID(subgroupID); m_Atoms.push_back(newAtom); } + void AddAtom(Atom *newAtom, long subgroupID = 0) { newAtom->SetSubID(subgroupID); m_Atoms.push_back(newAtom); m_MomentOfInertia = 0.0F; } /// /// Adds a list of new Atoms to the internal list that makes up this AtomGroup. Ownership of all Atoms in the list IS NOT transferred! @@ -200,6 +201,13 @@ namespace RTE { /// Whether any Atoms of that subgroup ID were found and removed. bool RemoveAtoms(long removeID); + /// + /// Gets whether the AtomGroup contains a subgroup with the given subgroupID. + /// + /// The subgroupID to check for. + /// Whether this AtomGroup contains a subgroup with the given subgroupID. + bool ContainsSubGroup(long int subgroupID) { return m_SubGroups.count(subgroupID) != 0; } + /// /// Updates the offsets of a subgroup of Atoms in this AtomGroup. This allows repositioning a subgroup to match the position and rotation of the graphical representation of it's owner MOSR. /// @@ -351,6 +359,7 @@ namespace RTE { std::unordered_map> m_SubGroups; //!< Sub groupings of Atoms. Points to Atoms owned in m_Atoms. Not owned. MOSRotating *m_OwnerMOSR; //!< The owner of this AtomGroup. The owner is obviously not owned by this AtomGroup. + float m_StoredOwnerMass; //!< The stored mass for the owner MOSR. Used to figure out when the moment of inertia needs to be recalculated due to significant mass changes. const Material *m_Material; //!< Material of this AtomGroup. bool m_AutoGenerate; //!< Whether the Atoms in this AtomGroup were automatically generated based on a sprite, or manually defined. From 108f7fcdc9724b222983aa28a3867aa3f6b27eda Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 23 Oct 2020 00:44:49 -0300 Subject: [PATCH 074/144] Oops --- Entities/Arm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 8cde98915..388b26946 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -206,7 +206,7 @@ void Arm::SetHeldMO(MovableObject *newHeldMO) { m_pHeldMO = nullptr; } else { //TODO All this needs cleaning up, this should do the basics, some other method should be responsible for replacing held things - if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && dynamic_cast(m_pHeldMO)->IsAttached())) { + if (m_pHeldMO && m_pHeldMO->IsHeldDevice() && dynamic_cast(m_pHeldMO)->IsAttached()) { RemoveAttachable(dynamic_cast(m_pHeldMO), true, false); m_pHeldMO = nullptr; } From 5b8f240d4ff290f3560f7f48f329f3c4869470e7 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 23 Oct 2020 12:45:01 -0300 Subject: [PATCH 075/144] "Fixed" always triggering abort when removing attachable (commented it out for now and deleted attachable to avoid memory leak, will need to ocme back to this) --- Entities/MOSRotating.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index a93b87c4d..ddf723524 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1584,7 +1584,8 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, } else if (addToMovableMan || attachable->IsSetToDelete()) { g_MovableMan.AddMO(attachable); } else { - RTEAbort("Tried to remove Attachable " + attachable->GetModuleAndPresetName() + " from parent " + GetModuleAndPresetName() + " but it was not set to delete, or be added to MovableMan, or delete when removed from parent. This should never happen."); + delete attachable; + //RTEAbort("Tried to remove Attachable " + attachable->GetModuleAndPresetName() + " from parent " + GetModuleAndPresetName() + " but it was not set to delete, or be added to MovableMan, or delete when removed from parent. This should never happen."); } return true; } From b679e35800feb0bf1ad3e44ce2cfe1848e2df6e6 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 23 Oct 2020 20:26:48 -0300 Subject: [PATCH 076/144] Fixed crashes and potential crashes Changed RemoveAttachable deletion handling so attachables are always added to MovableMan if they're getting deleted, but can also not be deleted or added to MovableMan so things can utilize them. I didn't realize it, for the previous version to work safely the MOID layer would have to be cleared and redrawn after deleting the attachable in order to avoid screwups. This option is definitely cheaper. Also changed a size() check to an empty() check (thanks sonarlint for catching it) Added special luaman handling for removing attachables so that modder mistakes can't cause memory leaks (i.e. they will always either delete or get added to MovableMan). Modified comments and added a TODO to MOSR header to make RemoveAttachable return the attachable removed and hand over ownership. When this is done it will avoid some mess we currently have. It should be done as part of Arm cleanup. --- Entities/MOSRotating.cpp | 13 +++---------- Entities/MOSRotating.h | 3 +++ Managers/LuaMan.cpp | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index ddf723524..3861906e2 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1550,7 +1550,7 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, } RTEAssert(attachable->IsAttachedTo(this), "Tried to remove Attachable " + attachable->GetModuleAndPresetName() + " from presumed parent " + GetModuleAndPresetName() + ", but it had a different parent (" + (attachable->GetParent() ? attachable->GetParent()->GetModuleAndPresetName() : "ERROR") + "). This should never happen!"); - if (m_Attachables.size() > 0) { m_Attachables.remove(attachable); } + if (!m_Attachables.empty()) { m_Attachables.remove(attachable); } attachable->SetParent(nullptr); m_AttachableAndWoundMass -= attachable->GetMass(); @@ -1578,15 +1578,8 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, } } } - //TODO Deletion should be made more consistent. Once other code is cleaned up and we can safely delete right away if the Attachable IsSetToDelete, we should do that. Alternatively we could add to MovableMan and let that take care of it in both deletion cases, but I think that may be a waste. Would need to investigate. - if (!attachable->IsSetToDelete() && attachable->GetDeleteWhenRemovedFromParent()) { - delete attachable; - } else if (addToMovableMan || attachable->IsSetToDelete()) { - g_MovableMan.AddMO(attachable); - } else { - delete attachable; - //RTEAbort("Tried to remove Attachable " + attachable->GetModuleAndPresetName() + " from parent " + GetModuleAndPresetName() + " but it was not set to delete, or be added to MovableMan, or delete when removed from parent. This should never happen."); - } + if (attachable->GetDeleteWhenRemovedFromParent()) { attachable->SetToDelete(); } + if (addToMovableMan || attachable->IsSetToDelete()) { g_MovableMan.AddMO(attachable); } return true; } diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 149f8bfec..fc5c65d22 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -403,6 +403,7 @@ ClassInfoGetters /// The Vector to set as the Attachable's parent offset. virtual void AddAttachable(Attachable *attachable, const Vector& parentOffsetToSet); + //TODO All RemoveAttachable methods should return the removed attachable (if it's not deleted) so there's no potential memory leaks or other safety problems. Very little cares about whether this actually succeeded or failed anyway, so returning a boolean here is kind of pointless. This should probably be done as part of Arm cleanup. /// /// Removes the Attachable corresponding to the passed in UniqueID and sets its parent to nullptr. Does not add it to MovableMan or add break wounds. /// @@ -412,6 +413,7 @@ ClassInfoGetters /// /// Removes the Attachable corresponding to the passed in UniqueID and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. + /// If the Attachable is not set to delete or delete when removed from its parent, and addToMovableMan is false, the caller must hang onto a pointer to the Attachable ahead of time to avoid memory leaks. /// /// The UniqueID of the the Attachable to remove. /// Whether or not to add the Attacahble to MovableMan once it has been removed. @@ -428,6 +430,7 @@ ClassInfoGetters /// /// Removes the passed in Attachable and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. + /// If the Attachable is not set to delete or delete when removed from its parent, and addToMovableMan is false, the caller must hang onto a pointer to the Attachable ahead of time to avoid memory leaks. /// /// The Attachable to remove. /// Whether or not to add the Attachable to MovableMan once it has been removed. diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 3566a3b80..8d729bf4a 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -381,6 +381,30 @@ void AddParticle(MovableMan &This, MovableObject *pParticle) double NormalRand() { return RandomNormalNum(); } double PosRand() { return RandomNum(); } +/* +These methods are needed to specially handling removing attachables with Lua in order to avoid memory leaks. They have silly names cause luabind otherwise makes it difficult to pass values to them properly. +Eventually RemoveAttachable should return the removed attachable, making this whole thing no longer unsafe and these methods unnecessary (there's a TODO in MOSRotating.h for it). +*/ +bool RemoveAttachableLuaSafe4(MOSRotating *luaSelfObject, Attachable *attachable, bool addToMovableMan, bool addBreakWounds) { + if (!addToMovableMan && !attachable->IsSetToDelete()) { + attachable->SetToDelete(); + } + return luaSelfObject->RemoveAttachable(attachable, addToMovableMan, addBreakWounds); +} +bool RemoveAttachableLuaSafe3(MOSRotating *luaSelfObject, Attachable *attachable) { + return RemoveAttachableLuaSafe4(luaSelfObject, attachable, false, false); +} +bool RemoveAttachableLuaSafe2(MOSRotating *luaSelfObject, long attachableUniqueID, bool addToMovableMan, bool addBreakWounds) { + MovableObject *attachableAsMovableObject = g_MovableMan.FindObjectByUniqueID(attachableUniqueID); + if (attachableAsMovableObject) { + return RemoveAttachableLuaSafe4(luaSelfObject, dynamic_cast(attachableAsMovableObject), addToMovableMan, addBreakWounds); + } + return false; +} +bool RemoveAttachableLuaSafe1(MOSRotating *luaSelfObject, long attachableUniqueID) { + return RemoveAttachableLuaSafe2(luaSelfObject, attachableUniqueID, false, false); +} + /* ////////////////////////////////////////////////////////////////////////////////////////// // Wrapper for the GAScripted so we can derive new classes from it purely in lua: @@ -788,10 +812,16 @@ int LuaMan::Create() { .def("ObjectValueExists", &MOSRotating::ObjectValueExists) .def("AddAttachable", (void (MOSRotating::*)(Attachable *attachableToAdd))&MOSRotating::AddAttachable, adopt(_2)) .def("AddAttachable", (void (MOSRotating::*)(Attachable *attachableToAdd, const Vector &parentOffset))&MOSRotating::AddAttachable, adopt(_2)) + .def("RemoveAttachable", &RemoveAttachableLuaSafe1) + .def("RemoveAttachable", &RemoveAttachableLuaSafe2) + .def("RemoveAttachable", &RemoveAttachableLuaSafe3) + .def("RemoveAttachable", &RemoveAttachableLuaSafe4) + /* + .def("RemoveAttachable", (bool (MOSRotating:: *)(long uniqueIDOfAttachableToRemove)) &MOSRotating::RemoveAttachable) + .def("RemoveAttachable", (bool (MOSRotating:: *)(long uniqueIDOfAttachableToRemove, bool addToMovableMan, bool addBreakWounds)) &MOSRotating::RemoveAttachable) .def("RemoveAttachable", (bool (MOSRotating::*)(Attachable *attachableToRemove))&MOSRotating::RemoveAttachable) .def("RemoveAttachable", (bool (MOSRotating:: *)(Attachable *attachableToRemove, bool addToMovableMan, bool addBreakWounds)) &MOSRotating::RemoveAttachable) - .def("RemoveAttachable", (bool (MOSRotating::*)(long uniqueIDOfAttachableToRemove))&MOSRotating::RemoveAttachable) - .def("RemoveAttachable", (bool (MOSRotating:: *)(long uniqueIDOfAttachableToRemove, bool addToMovableMan, bool addBreakWounds)) &MOSRotating::RemoveAttachable) + */ .def("AddEmitter", (void (MOSRotating::*)(Attachable *attachableToAdd))&MOSRotating::AddAttachable, adopt(_2)) .def("AddEmitter", (void (MOSRotating::*)(Attachable *attachableToAdd, const Vector &parentOffset))&MOSRotating::AddAttachable, adopt(_2)) .def("RemoveEmitter", (bool (MOSRotating::*)(Attachable *attachableToRemove))&MOSRotating::RemoveAttachable) From ca8399ee4f815e753ff4b00050087337f156f78f Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 23 Oct 2020 20:45:56 -0300 Subject: [PATCH 077/144] Turns out setting hardcoded attachables wasn't broken at all, I just screwed up and forgot to put an adoption policy on the thing I was testing with :( --- Managers/LuaMan.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 8d729bf4a..cce0c3873 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1107,8 +1107,8 @@ int LuaMan::Create() { value("LANDJUMP", 5 /*AHuman::JumpState::LANDJUMP*/) ] .def(constructor<>()) - .property("Head", &AHuman::GetHead, &AHuman::SetHead) - .property("Jetpack", &AHuman::GetJetpack, &AHuman::SetJetpack) + .property("Head", &AHuman::GetHead, &AHuman::SetHead, detail::null_type(), adopt(_2)) + .property("Jetpack", &AHuman::GetJetpack, &AHuman::SetJetpack, detail::null_type(), adopt(_2)) .property("FGArm", &AHuman::GetFGArm, &AHuman::SetFGArm, detail::null_type(), adopt(_2)) .property("BGArm", &AHuman::GetBGArm, &AHuman::SetBGArm, detail::null_type(), adopt(_2)) .property("FGLeg", &AHuman::GetFGLeg, &AHuman::SetFGLeg, detail::null_type(), adopt(_2)) From 5b31253c1fef826276c7904a7a70bd1cc142d7ea Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 24 Oct 2020 01:36:48 -0300 Subject: [PATCH 078/144] Removed extra MovableMan AddItem calls in Arm The two calling ReleaseHeldMO crashed the game cause the item was being added twice, and the other ones were unsafe cause under the right circumstances the item may still be added twice. --- Entities/Arm.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 388b26946..131678625 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -263,8 +263,7 @@ MovableObject * Arm::DropEverything() MovableObject *pReturnMO = m_pHeldMO; if (m_pHeldMO && m_pHeldMO->IsDevice()) { - RemoveAttachable(dynamic_cast(m_pHeldMO)); - g_MovableMan.AddItem(m_pHeldMO); + RemoveAttachable(dynamic_cast(m_pHeldMO), true, false); } else if (m_pHeldMO) g_MovableMan.AddParticle(m_pHeldMO); @@ -386,8 +385,7 @@ void Arm::Update() { if (m_pHeldMO) { m_pHeldMO->SetVel(m_Vel + Vector(-RandomNum(0.0F, 10.0F), -RandomNum(0.0F, 15.0F))); m_pHeldMO->SetAngularVel(-7); - if (m_pHeldMO->IsDevice()) { RemoveAttachable(dynamic_cast(m_pHeldMO)); } - g_MovableMan.AddItem(m_pHeldMO); + if (m_pHeldMO->IsDevice()) { RemoveAttachable(dynamic_cast(m_pHeldMO), true, false); } m_pHeldMO = 0; } // Update hand @@ -447,7 +445,7 @@ void Arm::Update() { // If it blew up or whatever, releaes it from hand and put into scene so it'll be cleaned up properly if (m_pHeldMO && m_pHeldMO->IsSetToDelete()) - g_MovableMan.AddItem(ReleaseHeldMO()); + ReleaseHeldMO(); } // Adjust rotation and hand distance if reaching toward something. else @@ -496,7 +494,7 @@ void Arm::Update() { // If it blew up or whatever, release it from hand and put into scene so it'll be cleaned up properly if (m_pHeldMO->IsSetToDelete()) - g_MovableMan.AddItem(ReleaseHeldMO()); + ReleaseHeldMO(); } } From e4bc466d15153caaede56340a8a85a5f09a97bca Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 24 Oct 2020 17:08:30 -0300 Subject: [PATCH 079/144] Added safe handling to HDFirearm so there's no potential memory leaks from non-discardable magazines Fiddled with attachable handling so if the attachable was gibbing during its update (e.g. TDEs) things won't crash. Also moved handling of attachables that are SetToDelete outside of force transferral to deal with this, and cleaned it up a little --- Entities/HDFirearm.cpp | 1 + Entities/MOSRotating.cpp | 33 ++++++++++++++++----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index 675c112f8..f52f5ca0c 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -599,6 +599,7 @@ void HDFirearm::Reload() { m_pMagazine->SetVel(m_Vel + Vector(m_HFlipped ? -3 : 3, 0.3)); m_pMagazine->SetAngularVel(6.0F + (-RandomNum(0.0F, 6.0F))); + if (m_pMagazine->IsDiscardable()) { m_pMagazine->SetToDelete(); } RemoveAttachable(m_pMagazine, m_pMagazine->IsDiscardable(), false); m_pMagazine = 0; } diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 3861906e2..6b5f95286 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1453,7 +1453,11 @@ void MOSRotating::Update() { attachable->Update(); - TransferForcesFromAttachable(attachable); + if (attachable->IsAttachedTo(this) && attachable->IsSetToDelete()) { + RemoveAttachable(attachable, true, false); + } else if (!attachable->IsSetToDelete()) { + TransferForcesFromAttachable(attachable); + } } // Create intermediate flipping bitmaps if they don't exist @@ -1882,22 +1886,17 @@ bool MOSRotating::TransferForcesFromAttachable(Attachable *attachable) { if (attachable) { RTEAssert(attachable->IsAttached(), "Tried to transfer forces from Attachable (" + attachable->GetModuleAndPresetName() + ") with no parent, this should never happen!"); RTEAssert(attachable->IsAttachedTo(this), "Tried to transfer forces from another parent's (" + attachable->GetParent()->GetModuleAndPresetName() + ") Attachable (" + attachable->GetModuleAndPresetName() + "), this should never happen!"); - if (attachable->IsSetToDelete()) { - RemoveAttachable(attachable, true, true); - } else if (attachable->IsAttached()) { - attachable->PostTravel(); - Vector forces; - Vector impulses; - intact = attachable->TransferJointForces(forces) && attachable->TransferJointImpulses(impulses); - - if (!forces.IsZero()) { - AddForce(forces, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation * c_MPP : Vector()); - } - if (!impulses.IsZero()) { - AddImpulseForce(impulses, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation * c_MPP : Vector()); - } - } else { - RTEAbort("Tried to transfer forces from a Non-Attached, Non-Deleting Attachable " + attachable->GetModuleAndPresetName() + ". This should never happen!"); + + attachable->PostTravel(); + Vector forces; + Vector impulses; + intact = attachable->TransferJointForces(forces) && attachable->TransferJointImpulses(impulses); + + if (!forces.IsZero()) { + AddForce(forces, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation * c_MPP : Vector()); + } + if (!impulses.IsZero()) { + AddImpulseForce(impulses, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation * c_MPP : Vector()); } } return intact; From fe0a46421feddeb693a0af23b5fe153f971e57a8 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 25 Oct 2020 18:42:35 -0300 Subject: [PATCH 080/144] Review Comments AHuman - Delete FGHandGroup, clean up Destroy, change fabs to std::fabs, add Fs to floats Arm - Set HeldMO = nullptr instead of 0 in Clear, use Attachable::Create instead of MOSR::Create in Create Attachable - Make Create() override (thanks sonarlint) HDFirearm - Oneline code HeldDevice - Fix Fs for floats, use Attachable::Create instead of MOSR::Create in Create, change comment spelling in header Leg - Use Attachable::Create instead of MOSR::Create in Create, fix typos and added missing regions in header MOSR cpp - Cleanup and oneline various code, change size == 0 to empty, remove weird unneeded if check when creating gibs, change fabs to std::fabs and list to std::list, add Fs to floats MOSR h - Change MOSprite::GetMass to MO::GetMass, change moToNotHit = 0 to nullptr and change method comment to match, clean up comments and typos and spacing, change ints to floats in method definitions, add dino fact MO - Oneline code, change moToNotHit = 0 to nullptr in header and change method comment to match Turret - Change MountedDevice = 0 to nullptr in Clear and fixed typos in header LuaMan - Trim down lengthy argument names for wound stuff so it's more readable here Vector - Oneline code --- Entities/AHuman.cpp | 16 +++---- Entities/Arm.cpp | 4 +- Entities/Attachable.h | 2 +- Entities/HDFirearm.cpp | 4 +- Entities/HeldDevice.cpp | 6 +-- Entities/HeldDevice.h | 6 +-- Entities/Leg.cpp | 2 +- Entities/Leg.h | 12 +++-- Entities/MOSRotating.cpp | 94 ++++++++++++-------------------------- Entities/MOSRotating.h | 29 ++++++------ Entities/MovableObject.cpp | 4 +- Entities/MovableObject.h | 4 +- Entities/Turret.cpp | 2 +- Entities/Turret.h | 4 +- Managers/LuaMan.cpp | 6 +-- System/Vector.cpp | 4 +- 16 files changed, 77 insertions(+), 122 deletions(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 4a2a6419c..c04316eef 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -380,17 +380,13 @@ int AHuman::Save(Writer &writer) const ////////////////////////////////////////////////////////////////////////////////////////// // Description: Destroys and resets (through Clear()) the AHuman object. -void AHuman::Destroy(bool notInherited) -{ +void AHuman::Destroy(bool notInherited) { + delete m_pFGHandGroup; delete m_pBGHandGroup; delete m_pFGFootGroup; delete m_pBGFootGroup; -// for (deque::iterator itr = m_WalkPaths.begin(); -// itr != m_WalkPaths.end(); ++itr) -// delete *itr; - if (!notInherited) - Actor::Destroy(); + if (!notInherited) { Actor::Destroy(); } Clear(); } @@ -3951,9 +3947,9 @@ void AHuman::Update() if (m_pHead && m_pHead->IsAttached()) { float toRotate = 0; // Only rotate the head to match the aim angle if body is stable and upright - if (m_Status == STABLE && fabs(m_Rotation.GetRadAngle()) < (c_HalfPI + c_QuarterPI)) { - toRotate = m_pHead->GetRotMatrix().GetRadAngleTo((m_HFlipped ? -m_AimAngle : m_AimAngle) * 0.7 + m_Rotation.GetRadAngle() * 0.2); - toRotate *= 0.15; + if (m_Status == STABLE && std::fabs(m_Rotation.GetRadAngle()) < (c_HalfPI + c_QuarterPI)) { + toRotate = m_pHead->GetRotMatrix().GetRadAngleTo((m_HFlipped ? -m_AimAngle : m_AimAngle) * 0.7F + m_Rotation.GetRadAngle() * 0.2F); + toRotate *= 0.15F; } // If dying upright, make head slump forward or back depending on body lean // TODO: Doesn't work too well, but probably could diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 131678625..f3a3b7901 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -29,7 +29,7 @@ ConcreteClassInfo(Arm, Attachable, 50) void Arm::Clear() { - m_pHeldMO = 0; + m_pHeldMO = nullptr; m_GripStrength = 0; m_HandFile.Reset(); m_pHand = 0; @@ -49,7 +49,7 @@ void Arm::Clear() // Description: Makes the Arm object ready for use. int Arm::Create() { - if (MOSRotating::Create() < 0) { + if (Attachable::Create() < 0) { return -1; } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 196f5311d..f076af092 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -30,7 +30,7 @@ namespace RTE { /// Makes the Attachable object ready for use. /// /// An error return value signaling success or any particular failure. Anything below 0 is an error signal. - int Create(); + int Create() override; /// /// Creates an Attachable to be identical to another, by deep copy. diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index f52f5ca0c..8da1c48c8 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -792,9 +792,7 @@ void HDFirearm::Update() Attachable *pAttachable = dynamic_cast(pParticle); if (pAttachable) { - if (pAttachable->IsAttached()) { - dynamic_cast(pAttachable->GetParent())->RemoveAttachable(pAttachable); - } + if (pAttachable->IsAttached()) { dynamic_cast(pAttachable->GetParent())->RemoveAttachable(pAttachable); } // Activate if it is some kind of grenade or whatnot. ThrownDevice *pTD = dynamic_cast(pAttachable); if (pTD) diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index b15c4e393..472fbc9da 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -42,11 +42,11 @@ void HeldDevice::Clear() m_DualWieldable = false; m_StanceOffset.Reset(); m_SharpStanceOffset.Reset(); - m_SharpAim = 0.0f; + m_SharpAim = 0.0F; m_MaxSharpLength = 0; m_Supported = false; m_SupportOffset.Reset(); - m_GripStrengthMultiplier = 1.0; + m_GripStrengthMultiplier = 1.0F; m_BlinkTimer.Reset(); m_PieSlices.clear(); m_Loudness = -1; @@ -60,7 +60,7 @@ void HeldDevice::Clear() int HeldDevice::Create() { - if (MOSRotating::Create() < 0) + if (Attachable::Create() < 0) return -1; // Set MO Type. diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index aadb6883d..0faa1b1cf 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -550,9 +550,9 @@ ClassInfoGetters /// Additionally, in this case, the Attachable will remove itself from its parent and gib itself if appropriate. /// /// A vector that will have the impulse forces affecting the joint ADDED to it. - /// An optional override for the Attachable's joint stiffness for this function call. Primarily used to allow subclasses to perform special behaviour. - /// An optional override for the Attachable's joint strength for this function call. Primarily used to allow subclasses to perform special behaviour. - /// An optional override for the Attachable's gib impulse limit for this function call. Primarily used to allow subclasses to perform special behaviour. + /// An optional override for the Attachable's joint stiffness for this function call. Primarily used to allow subclasses to perform special behavior. + /// An optional override for the Attachable's joint strength for this function call. Primarily used to allow subclasses to perform special behavior. + /// An optional override for the Attachable's gib impulse limit for this function call. Primarily used to allow subclasses to perform special behavior. /// False if the Attachable has no parent or its accumulated forces are greater than its joint strength or gib impulse limit, otherwise true. bool TransferJointImpulses(Vector &jointImpulses, float jointStiffnessOverride = -1, float jointStrengthOverride = -1, float gibImpulseLimitOverride = -1) override; #pragma endregion diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index b981b61f9..717666c5e 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -29,7 +29,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int Leg::Create() { - if (MOSRotating::Create() < 0) { + if (Attachable::Create() < 0) { return -1; } diff --git a/Entities/Leg.h b/Entities/Leg.h index cca07fd6f..9cab33030 100644 --- a/Entities/Leg.h +++ b/Entities/Leg.h @@ -8,7 +8,7 @@ namespace RTE { class HeldDevice; /// - /// A detatchable Leg that will be controlled by LimbPaths. + /// A detachable Leg that will be controlled by LimbPaths. /// class Leg : public Attachable { @@ -26,14 +26,14 @@ namespace RTE { /// /// Makes the Leg object ready for use. /// - /// An error return value signaling sucess or any particular failure. Anything below 0 is an error signal. + /// An error return value signaling success or any particular failure. Anything below 0 is an error signal. int Create() override; /// /// Creates a Leg to be identical to another, by deep copy. /// /// A reference to the Leg to deep copy. - /// An error return value signaling sucess or any particular failure. Anything below 0 is an error signal. + /// An error return value signaling success or any particular failure. Anything below 0 is an error signal. int Create(const Leg &reference); #pragma endregion @@ -93,10 +93,12 @@ namespace RTE { void EnableIdle(bool idle = true) { m_WillIdle = idle; } #pragma endregion +#pragma region Override Methods /// /// Updates this Leg. Supposed to be done every frame. /// void Update() override; +#pragma endregion protected: @@ -109,7 +111,7 @@ namespace RTE { float m_MinExtension; //!< Precalculated min extension of the Leg (from the joint) based on the contracted offset. float m_MaxExtension; //!< Precalculated max extension of the Leg (from the joint) based on the extended offset. - float m_CurrentNormalizedExtension; //!< Normalized scalar of where the ankle offset's magnitude is between the min and max extensions + float m_CurrentNormalizedExtension; //!< Normalized scalar of where the ankle offset's magnitude is between the min and max extensions. Vector m_TargetPosition; //!< The absolute position that this Leg's foot is moving towards. Vector m_IdleOffset; //!< The target offset from m_Pos that this Leg's foot is moving towards when allowed to idle and the target position is not acceptable. @@ -121,6 +123,7 @@ namespace RTE { private: +#pragma region Update Breakdown /// /// Updates the current ankle offset for this Leg, and sets the foot's parent offset to match up with it. Should only be called from Update. /// If the Leg is attached, the current ankle offset is based on the target offset and move speed, and whether the Leg should idle or not, otherwise it puts it in a reasonable position. @@ -144,6 +147,7 @@ namespace RTE { /// If the Leg is attached, the foot's rotation and frame depend on the ankle offset, otherwise the foot's rotation is set to be perpendicular to the Leg's rotation. /// void UpdateFootFrameAndRotation(); +#pragma endregion /// /// Clears all the member variables of this Leg, effectively resetting the members of this abstraction level only. diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 6b5f95286..b84b0b563 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -240,8 +240,7 @@ int MOSRotating::Create(const MOSRotating &reference) { for (const Attachable *referenceAttachable : reference.m_Attachables) { if (m_ReferenceHardcodedAttachableUniqueIDs.find(referenceAttachable->GetUniqueID()) == m_ReferenceHardcodedAttachableUniqueIDs.end()) { - Attachable *newAttachable = dynamic_cast(referenceAttachable->Clone()); - AddAttachable(newAttachable); + AddAttachable(dynamic_cast(referenceAttachable->Clone())); } } m_ReferenceHardcodedAttachableUniqueIDs.clear(); @@ -488,9 +487,7 @@ float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachab (includeAttachablesWithNoDamageMultiplier && attachable->GetDamageMultiplier() == 0); int attachableWoundCount = attachable->GetWoundCount(includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); - if (attachableSatisfiesConditions && attachableWoundCount > 0) { - woundedParts.push_back({attachable, attachableWoundCount}); - } + if (attachableSatisfiesConditions && attachableWoundCount > 0) { woundedParts.push_back({attachable, attachableWoundCount}); } } if (woundedParts.empty()) { @@ -501,7 +498,7 @@ float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachab /// Internal lambda function to remove the first wound emitter from this MOSRotating. /// auto removeFirstWoundEmitter = [this]() { - if (m_Wounds.size() == 0) { + if (m_Wounds.empty()) { return 0.0F; } float woundDamage = m_Wounds.front()->GetBurstDamage(); @@ -511,7 +508,7 @@ float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachab }; for (int i = 0; i < numberOfWoundsToRemove; i++) { - if (woundedParts.size() == 0) { + if (woundedParts.empty()) { break; } @@ -523,9 +520,7 @@ float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachab //TODO This is less efficient than it should be. We already collected all wounded parts and their wounds above, we should pass that in (make another function overload) instead of collecting everything again. It might be wise to use a tree for this purpose. damage += woundedPart->RemoveWounds(1, includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); } - if (woundedParts[woundedPartIndex].second-- <= 0) { - woundedParts.erase(woundedParts.begin() + woundedPartIndex); - } + if (woundedParts[woundedPartIndex].second-- <= 0) { woundedParts.erase(woundedParts.begin() + woundedPartIndex); } } return damage; @@ -968,9 +963,7 @@ void MOSRotating::GibThis(const Vector &impactImpulse, MovableObject *movableObj g_PostProcessMan.RegisterPostEffect(m_Pos, m_pScreenEffect, m_ScreenEffectHash, 255, m_EffectRotAngle); } - if (m_LoudnessOnGib > 0) { - g_MovableMan.RegisterAlarmEvent(AlarmEvent(m_Pos, m_Team, m_LoudnessOnGib)); - } + if (m_LoudnessOnGib > 0) { g_MovableMan.RegisterAlarmEvent(AlarmEvent(m_Pos, m_Team, m_LoudnessOnGib)); } m_ToDelete = true; } @@ -992,9 +985,7 @@ void MOSRotating::CreateGibsWhenGibbing(const Vector &impactImpulse, MovableObje } Vector rotatedGibOffset = RotateOffset(gibSettingsObject.GetOffset()); for (int i = 0; i < gibSettingsObject.GetCount(); i++) { - if (i > 0) { - gibParticleClone = dynamic_cast(gibSettingsObject.GetParticlePreset()->Clone()); - } + gibParticleClone = dynamic_cast(gibSettingsObject.GetParticlePreset()->Clone()); if (gibParticleClone->GetLifetime() != 0) { gibParticleClone->SetLifetime(static_cast(static_cast(gibParticleClone->GetLifetime()) * (1.0F + (gibSettingsObject.GetLifeVariation() * RandomNormalNum())))); @@ -1004,7 +995,7 @@ void MOSRotating::CreateGibsWhenGibbing(const Vector &impactImpulse, MovableObje gibParticleClone->SetAngularVel((gibParticleClone->GetAngularVel() * 0.35F) + (gibParticleClone->GetAngularVel() * 0.65F / gibParticleClone->GetMass()) * RandomNum()); if (rotatedGibOffset.GetRoundIntX() > m_aSprite[0]->w / 3) { float offCenterRatio = rotatedGibOffset.m_X / (static_cast(m_aSprite[0]->w) / 2.0F); - float angularVel = fabs(gibParticleClone->GetAngularVel() * 0.5F) + fabs(gibParticleClone->GetAngularVel() * 0.5F * offCenterRatio); + float angularVel = fabs(gibParticleClone->GetAngularVel() * 0.5F) + std::fabs(gibParticleClone->GetAngularVel() * 0.5F * offCenterRatio); gibParticleClone->SetAngularVel(angularVel * (rotatedGibOffset.m_X > 0 ? -1 : 1)); } else { gibParticleClone->SetAngularVel((gibParticleClone->GetAngularVel() * 0.5F + (gibParticleClone->GetAngularVel() * RandomNum())) * (RandomNormalNum() > 0.0F ? 1.0F : -1.0F)); @@ -1014,9 +1005,7 @@ void MOSRotating::CreateGibsWhenGibbing(const Vector &impactImpulse, MovableObje Vector gibVelocity = rotatedGibOffset.SetMagnitude(minVelocity + RandomNum(0.0F, velocityRange)).RadRotate(impactImpulse.GetAbsRadAngle() + gibSettingsObject.GetSpread() + RandomNormalNum()); gibParticleClone->SetVel(gibVelocity + (gibSettingsObject.InheritsVelocity() ? m_Vel : Vector())); - if (movableObjectToIgnore) { - gibParticleClone->SetWhichMOToNotHit(movableObjectToIgnore); - } + if (movableObjectToIgnore) { gibParticleClone->SetWhichMOToNotHit(movableObjectToIgnore); } g_MovableMan.AddParticle(gibParticleClone); } @@ -1027,7 +1016,7 @@ void MOSRotating::CreateGibsWhenGibbing(const Vector &impactImpulse, MovableObje void MOSRotating::RemoveAttachablesWhenGibbing(const Vector &impactImpulse, MovableObject *movableObjectToIgnore) { Attachable *attachable; - for (list::iterator attachableIterator = m_Attachables.begin(); attachableIterator != m_Attachables.end();) { + for (std::list::iterator attachableIterator = m_Attachables.begin(); attachableIterator != m_Attachables.end();) { RTEAssert((*attachableIterator), "Broken Attachable!"); attachable = *attachableIterator; @@ -1040,12 +1029,10 @@ void MOSRotating::RemoveAttachablesWhenGibbing(const Vector &impactImpulse, Mova if (!attachable->GetDeleteWhenRemovedFromParent()) { float attachableGibBlastStrength = (attachable->GetParentGibBlastStrengthMultiplier() == 0 ? 1 : attachable->GetParentGibBlastStrengthMultiplier() * m_GibBlastStrength) / (1 + attachable->GetMass()); attachable->SetAngularVel((attachable->GetAngularVel() * 0.5F) + (attachable->GetAngularVel() * 0.5F * attachableGibBlastStrength * RandomNormalNum())); - Vector gibBlastVel = Vector(attachable->GetParentOffset()).SetMagnitude(attachableGibBlastStrength * 0.5 + (attachableGibBlastStrength * RandomNum())); + Vector gibBlastVel = Vector(attachable->GetParentOffset()).SetMagnitude(attachableGibBlastStrength * 0.5F + (attachableGibBlastStrength * RandomNum())); attachable->SetVel(m_Vel + gibBlastVel + impactImpulse); - if (movableObjectToIgnore) { - attachable->SetWhichMOToNotHit(movableObjectToIgnore); - } + if (movableObjectToIgnore) { attachable->SetWhichMOToNotHit(movableObjectToIgnore); } } ++attachableIterator; @@ -1428,14 +1415,12 @@ void MOSRotating::Update() { MOSprite::Update(); - if (m_InheritEffectRotAngle) { - m_EffectRotAngle = m_Rotation.GetRadAngle(); - } + if (m_InheritEffectRotAngle) { m_EffectRotAngle = m_Rotation.GetRadAngle(); } - if (m_OrientToVel > 0 && m_Vel.GetLargest() > 5.0) { + if (m_OrientToVel > 0 && m_Vel.GetLargest() > 5.0F) { m_OrientToVel = std::clamp(m_OrientToVel, 0.0F, 1.0F); - float velInfluence = std::clamp(m_OrientToVel < 1.0 ? m_Vel.GetMagnitude() / 100.0F : 1.0F, 0.0F, 1.0F); + float velInfluence = std::clamp(m_OrientToVel < 1.0F ? m_Vel.GetMagnitude() / 100.0F : 1.0F, 0.0F, 1.0F); float radsToGo = m_Rotation.GetRadAngleTo(m_Vel.GetAbsRadAngle()); m_Rotation += radsToGo * m_OrientToVel * velInfluence; } @@ -1446,7 +1431,7 @@ void MOSRotating::Update() { } Attachable *attachable = 0; - for (list::iterator attachableIterator = m_Attachables.begin(); attachableIterator != m_Attachables.end(); ) { + for (std::list::iterator attachableIterator = m_Attachables.begin(); attachableIterator != m_Attachables.end(); ) { attachable = *attachableIterator; RTEAssert(attachable, "Broken Attachable!"); ++attachableIterator; @@ -1460,13 +1445,8 @@ void MOSRotating::Update() { } } - // Create intermediate flipping bitmaps if they don't exist - if (m_HFlipped && !m_pFlipBitmap && m_aSprite[0]) { - m_pFlipBitmap = create_bitmap_ex(8, m_aSprite[0]->w, m_aSprite[0]->h); - } - if (m_HFlipped && !m_pFlipBitmapS && m_aSprite[0]) { - m_pFlipBitmapS = create_bitmap_ex(c_MOIDLayerBitDepth, m_aSprite[0]->w, m_aSprite[0]->h); - } + if (m_HFlipped && !m_pFlipBitmap && m_aSprite[0]) { m_pFlipBitmap = create_bitmap_ex(8, m_aSprite[0]->w, m_aSprite[0]->h); } + if (m_HFlipped && !m_pFlipBitmapS && m_aSprite[0]) { m_pFlipBitmapS = create_bitmap_ex(c_MOIDLayerBitDepth, m_aSprite[0]->w, m_aSprite[0]->h); } } @@ -1508,18 +1488,14 @@ void MOSRotating::UpdateChildMOIDs(vector &MOIDIndex, MOID root for (Attachable *attachable : m_Attachables) { // Anything that doesn't get hit by MOs doesn't need an ID, since that's only actually used for collision stuff. - if (attachable->GetsHitByMOs()) { - attachable->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); - } + if (attachable->GetsHitByMOs()) { attachable->UpdateMOID(MOIDIndex, m_RootMOID, makeNewMOID); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void MOSRotating::AddAttachable(Attachable *attachable) { - if (attachable) { - AddAttachable(attachable, attachable->GetParentOffset()); - } + if (attachable) { AddAttachable(attachable, attachable->GetParentOffset()); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1591,7 +1567,7 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, void MOSRotating::RemoveOrDestroyAllAttachables(bool destroy) { Attachable *attachable; - for (list::iterator attachableIterator = m_Attachables.begin(); attachableIterator != m_Attachables.end(); ) { + for (std::list::iterator attachableIterator = m_Attachables.begin(); attachableIterator != m_Attachables.end(); ) { attachable = *attachableIterator; RTEAssert(attachable, "Broken Attachable!"); ++attachableIterator; @@ -1610,9 +1586,7 @@ void MOSRotating::RemoveOrDestroyAllAttachables(bool destroy) { void MOSRotating::GetMOIDs(std::vector &MOIDs) const { MOSprite::GetMOIDs(MOIDs); for (const Attachable *attachable : m_Attachables) { - if (attachable->GetsHitByMOs()) { - attachable->GetMOIDs(MOIDs); - } + if (attachable->GetsHitByMOs()) { attachable->GetMOIDs(MOIDs); } } } @@ -1735,17 +1709,13 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, // Only draw attachables and emitters which are not drawn after parent, so we draw them before if (mode == g_DrawColor || (!onlyPhysical && mode == g_DrawMaterial)) { for (const AEmitter *woundToDraw : m_Wounds) { - if (!woundToDraw->IsDrawnAfterParent()) { - woundToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } + if (!woundToDraw->IsDrawnAfterParent()) { woundToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } } } // Draw all the attached attachables for (const Attachable *attachableToDraw : m_Attachables) { - if (!attachableToDraw->IsDrawnAfterParent() && attachableToDraw->IsDrawnNormallyByParent()) { - attachableToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } + if (!attachableToDraw->IsDrawnAfterParent() && attachableToDraw->IsDrawnNormallyByParent()) { attachableToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } } @@ -1858,17 +1828,13 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, // Only draw attachables and emitters which are not drawn after parent, so we draw them before if (mode == g_DrawColor || (!onlyPhysical && mode == g_DrawMaterial)) { for (const AEmitter *woundToDraw : m_Wounds) { - if (woundToDraw->IsDrawnAfterParent()) { - woundToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } + if (woundToDraw->IsDrawnAfterParent()) { woundToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } } } // Draw all the attached attachables for (const Attachable *attachableToDraw : m_Attachables) { - if (attachableToDraw->IsDrawnAfterParent() && attachableToDraw->IsDrawnNormallyByParent()) { - attachableToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } + if (attachableToDraw->IsDrawnAfterParent() && attachableToDraw->IsDrawnNormallyByParent()) { attachableToDraw->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } } #ifdef DEBUG_BUILD @@ -1892,12 +1858,8 @@ bool MOSRotating::TransferForcesFromAttachable(Attachable *attachable) { Vector impulses; intact = attachable->TransferJointForces(forces) && attachable->TransferJointImpulses(impulses); - if (!forces.IsZero()) { - AddForce(forces, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation * c_MPP : Vector()); - } - if (!impulses.IsZero()) { - AddImpulseForce(impulses, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation * c_MPP : Vector()); - } + if (!forces.IsZero()) { AddForce(forces, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation * c_MPP : Vector()); } + if (!impulses.IsZero()) { AddImpulseForce(impulses, attachable->GetApplyTransferredForcesAtOffset() ? attachable->GetParentOffset() * m_Rotation * c_MPP : Vector()); } } return intact; } diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index fc5c65d22..0424694a2 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -140,7 +140,7 @@ ClassInfoGetters /// Gets the mass value of this MOSRotating, including the mass of all its Attachables and their Attachables and so on. /// /// The mass of this MOSRotating and all Attachables in Kilograms (kg). - float GetMass() const override { return MOSprite::GetMass() + m_AttachableAndWoundMass; } + float GetMass() const override { return MovableObject::GetMass() + m_AttachableAndWoundMass; } /// /// Updates the total mass of Attachables and wounds for this MOSRotating, intended to be used when Attachables' masses get modified. Simply subtracts the old mass and adds the new one. @@ -163,9 +163,9 @@ ClassInfoGetters /// /// Sets this MOSRotating to not hit a specific other MO and all its children even though MO hitting is enabled on this MOSRotating. /// - /// A pointer to the MO to not be hitting. 0 means don't ignore anyhting. Ownership is NOT transferred! + /// A pointer to the MO to not be hitting. Null pointer means don't ignore anything. Ownership is NOT transferred! /// How long, in seconds, to ignore the specified MO. A negative number means forever. - void SetWhichMOToNotHit(MovableObject *moToNotHit = 0, float forHowLong = -1) override; + void SetWhichMOToNotHit(MovableObject *moToNotHit = nullptr, float forHowLong = -1) override; ////////////////////////////////////////////////////////////////////////////////////////// @@ -345,8 +345,7 @@ ClassInfoGetters /// - /// Destroys this MOSRotating and creates its specified Gibs in its place with appropriate velocities. - /// Any Attachables are removed and also given appropriate velocities. + /// Destroys this MOSRotating and creates its specified Gibs in its place with appropriate velocities. Any Attachables are removed and also given appropriate velocities. /// /// The impulse (kg * m/s) of the impact causing the gibbing to happen. /// A pointer to an MO which the Gibs and Attachables should not be colliding with. @@ -401,13 +400,13 @@ ClassInfoGetters /// /// The Attachable to add. /// The Vector to set as the Attachable's parent offset. - virtual void AddAttachable(Attachable *attachable, const Vector& parentOffsetToSet); + virtual void AddAttachable(Attachable *attachable, const Vector &parentOffsetToSet); - //TODO All RemoveAttachable methods should return the removed attachable (if it's not deleted) so there's no potential memory leaks or other safety problems. Very little cares about whether this actually succeeded or failed anyway, so returning a boolean here is kind of pointless. This should probably be done as part of Arm cleanup. + //TODO All RemoveAttachable methods should return the removed attachable (if it's not deleted) so there's no potential memory leaks or other safety problems. Very little cares about whether this actually succeeded or failed anyway, so returning a boolean here is kind of pointless. This should probably be done as part of Arm cleanup. Also, worth noting, dinosaurs are/were neat. /// /// Removes the Attachable corresponding to the passed in UniqueID and sets its parent to nullptr. Does not add it to MovableMan or add break wounds. /// - /// The UniqueID of the the Attachable to remove. + /// The UniqueID of the Attachable to remove. /// False if the Attachable is invalid, otherwise true. virtual bool RemoveAttachable(long attachableUniqueID) { return RemoveAttachable(attachableUniqueID, false, false); } @@ -415,8 +414,8 @@ ClassInfoGetters /// Removes the Attachable corresponding to the passed in UniqueID and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. /// If the Attachable is not set to delete or delete when removed from its parent, and addToMovableMan is false, the caller must hang onto a pointer to the Attachable ahead of time to avoid memory leaks. /// - /// The UniqueID of the the Attachable to remove. - /// Whether or not to add the Attacahble to MovableMan once it has been removed. + /// The UniqueID of the Attachable to remove. + /// Whether or not to add the Attachable to MovableMan once it has been removed. /// Whether or not to add break wounds to the Attachable and this MOSRotating. /// False if the Attachable is invalid, otherwise true. virtual bool RemoveAttachable(long attachableUniqueID, bool addToMovableMan, bool addBreakWounds); @@ -573,13 +572,13 @@ ClassInfoGetters /// Gets the gib impulse limit for this MOSRotating, i.e. the amount of impulse force required in a frame to gib this MOSRotating. /// /// The gib impulse limit of this MOSRotating. - int GetGibImpulseLimit() const { return m_GibImpulseLimit; } + float GetGibImpulseLimit() const { return m_GibImpulseLimit; } /// /// Sets the gib impulse limit for this MOSRotating, i.e. the amount of impulse force required in a frame to gib this MOSRotating. /// /// The new gib impulse limit to use. - void SetGibImpulseLimit(int newGibImpulseLimit) { m_GibImpulseLimit = newGibImpulseLimit; } + void SetGibImpulseLimit(float newGibImpulseLimit) { m_GibImpulseLimit = newGibImpulseLimit; } /// /// Gets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. @@ -609,13 +608,13 @@ ClassInfoGetters /// Gets the gib blast strength this MOSRotating, i.e. the strength with which Gibs and Attachables will be launched when this MOSRotating is gibbed. /// /// The gib blast strength of this MOSRotating. - int GetGibBlastStrength() const { return m_GibBlastStrength; } + float GetGibBlastStrength() const { return m_GibBlastStrength; } /// /// Sets the gib blast strength this MOSRotating, i.e. the strength with which Gibs and Attachables will be launched when this MOSRotating is gibbed. /// /// The new gib blast strength to use. - void SetGibBlastStrength(int newGibBlastStrength) { m_GibBlastStrength = newGibBlastStrength; } + void SetGibBlastStrength(float newGibBlastStrength) { m_GibBlastStrength = newGibBlastStrength; } /// /// Gets the number of wounds attached to this MOSRotating. @@ -820,7 +819,7 @@ ClassInfoGetters protected: /// - /// Transfers forces and impulse forces from the given Attachable to this MOSRotating or removed the Attachable if needed. + /// Transfers forces and impulse forces from the given Attachable to this MOSRotating or remove the Attachable if needed. /// /// A pointer to the Attachable to apply forces from. Ownership is NOT transferred! /// Whether or not the Attachable has been removed, in which case it'll usually be passed to MovableMan or deleted. diff --git a/Entities/MovableObject.cpp b/Entities/MovableObject.cpp index 050609092..9d6612d8f 100644 --- a/Entities/MovableObject.cpp +++ b/Entities/MovableObject.cpp @@ -1029,9 +1029,7 @@ void MovableObject::RegMOID(vector &MOIDIndex, MOID rootMOID, b if (!makeNewMOID && GetParent()) { m_MOID = GetParent()->GetID(); } else { - if (MOIDIndex.size() == g_NoMOID) { - MOIDIndex.push_back(0); - } + if (MOIDIndex.size() == g_NoMOID) { MOIDIndex.push_back(0); } m_MOID = MOIDIndex.size(); MOIDIndex.push_back(this); diff --git a/Entities/MovableObject.h b/Entities/MovableObject.h index e986059e4..01b84099f 100644 --- a/Entities/MovableObject.h +++ b/Entities/MovableObject.h @@ -831,9 +831,9 @@ friend class Atom; /// /// Sets this MO to not hit a specific other MO and all its children even when MO hitting is enabled on this MO. /// - /// A pointer to the MO to not be hitting. 0 means don't ignore anyhting. Ownership is NOT transferred! + /// A pointer to the MO to not be hitting. Null pointer means don't ignore anyhting. Ownership is NOT transferred! /// How long, in seconds, to ignore the specified MO. A negative number means forever. - virtual void SetWhichMOToNotHit(MovableObject *moToNotHit = 0, float forHowLong = -1) { m_pMOToNotHit = moToNotHit; m_MOIgnoreTimer.Reset(); m_MOIgnoreTimer.SetSimTimeLimitS(forHowLong); } + virtual void SetWhichMOToNotHit(MovableObject *moToNotHit = nullptr, float forHowLong = -1) { m_pMOToNotHit = moToNotHit; m_MOIgnoreTimer.Reset(); m_MOIgnoreTimer.SetSimTimeLimitS(forHowLong); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index 6255bf4ff..bcf7036c3 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -8,7 +8,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Turret::Clear() { - m_MountedDevice = 0; + m_MountedDevice = nullptr; m_MountedDeviceRotOffset = 0; } diff --git a/Entities/Turret.h b/Entities/Turret.h index 8124954b3..c86c15ccc 100644 --- a/Entities/Turret.h +++ b/Entities/Turret.h @@ -8,7 +8,7 @@ namespace RTE { class HeldDevice; /// - /// A detatchable turret pod that can hold HeldDevices. + /// A detachable turret pod that can hold HeldDevices. /// class Turret : public Attachable { @@ -28,7 +28,7 @@ namespace RTE { /// Creates a Turret to be identical to another, by deep copy. /// /// A reference to the Turret to deep copy. - /// An error return value signaling sucess or any particular failure. Anything below 0 is an error signal. + /// An error return value signaling success or any particular failure. Anything below 0 is an error signal. int Create(const Turret &reference); #pragma endregion diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index cce0c3873..8877524bb 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -790,12 +790,12 @@ int LuaMan::Create() { .def("GibThis", &GibThis) .def("MoveOutOfTerrain", &MOSRotating::MoveOutOfTerrain) .def("GetGibWoundLimit", (int (MOSRotating:: *)() const) &MOSRotating::GetGibWoundLimit) - .def("GetGibWoundLimit", (int (MOSRotating:: *)(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const) &MOSRotating::GetGibWoundLimit) + .def("GetGibWoundLimit", (int (MOSRotating:: *)(bool positiveDamage, bool negativeDamage, bool noDamage) const) &MOSRotating::GetGibWoundLimit) .def("GetWoundCount", (int (MOSRotating:: *)() const) &MOSRotating::GetWoundCount) - .def("GetWoundCount", (int (MOSRotating:: *)(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const) &MOSRotating::GetWoundCount) + .def("GetWoundCount", (int (MOSRotating:: *)(bool positiveDamage, bool negativeDamage, bool noDamage) const) &MOSRotating::GetWoundCount) .def("AddWound", &MOSRotating::AddWound, adopt(_2)) .def("RemoveWounds", (float (MOSRotating:: *)(int numberOfWoundsToRemove)) &MOSRotating::RemoveWounds) - .def("RemoveWounds", (float (MOSRotating:: *)(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier)) &MOSRotating::RemoveWounds) + .def("RemoveWounds", (float (MOSRotating:: *)(int numberOfWoundsToRemove, bool positiveDamage, bool negativeDamage, bool noDamage)) &MOSRotating::RemoveWounds) .def("IsOnScenePoint", &MOSRotating::IsOnScenePoint) .def("EraseFromTerrain", &MOSRotating::EraseFromTerrain) .def("GetStringValue", &MOSRotating::GetStringValue) diff --git a/System/Vector.cpp b/System/Vector.cpp index 5d0a10b52..50be397f2 100644 --- a/System/Vector.cpp +++ b/System/Vector.cpp @@ -54,9 +54,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Vector & Vector::ClampMagnitude(float upperLimit, float lowerLimit) { - if (upperLimit < lowerLimit) { - std::swap(upperLimit, lowerLimit); - } + if (upperLimit < lowerLimit) { std::swap(upperLimit, lowerLimit); } if (upperLimit == 0 && lowerLimit == 0) { Reset(); } else if (GetMagnitude() > upperLimit) { From cd7b85260fcb955a8a6015192bdf6cd4e5577140 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 25 Oct 2020 23:58:10 -0300 Subject: [PATCH 081/144] Review Changes Changed Type *Method to Type * Method in ACDropship, ACrab, ACRocket, ADoor, AEmitter, AHuman, Attachable, HDFirearm, Leg and MovableObject Moved ACrab::GetTurret into header and simplified it so it's normal Changed SetJointOffset to take a const Vector & and Breakwound Setters to take const AEmitter *s in Attachable (thanks sonarlint) --- Entities/ACDropShip.h | 12 ++++++------ Entities/ACRocket.h | 14 +++++++------- Entities/ACrab.cpp | 6 ------ Entities/ACrab.h | 12 ++++++------ Entities/ADoor.h | 2 +- Entities/AEmitter.h | 2 +- Entities/AHuman.h | 16 ++++++++-------- Entities/Attachable.h | 20 ++++++++++---------- Entities/HDFirearm.h | 4 ++-- Entities/Leg.h | 2 +- Entities/MovableObject.h | 2 +- 11 files changed, 43 insertions(+), 49 deletions(-) diff --git a/Entities/ACDropShip.h b/Entities/ACDropShip.h index 05922abbf..3a1f6a567 100644 --- a/Entities/ACDropShip.h +++ b/Entities/ACDropShip.h @@ -180,7 +180,7 @@ ClassInfoGetters /// Gets the right side thruster of this ACDropship. /// /// A pointer to the right side thruster of this ACDropship. Ownership is NOT transferred. - AEmitter *GetRightThruster() const { return m_pRThruster; } + AEmitter * GetRightThruster() const { return m_pRThruster; } /// /// Sets the right side thruster for this ACDropship. @@ -192,7 +192,7 @@ ClassInfoGetters /// Gets the left side thruster of this ACDropship. /// /// A pointer to the left side thruster of this ACDropship. Ownership is NOT transferred. - AEmitter *GetLeftThruster() const { return m_pLThruster; } + AEmitter * GetLeftThruster() const { return m_pLThruster; } /// /// Sets the left side thruster for this ACDropship. @@ -204,7 +204,7 @@ ClassInfoGetters /// Gets the right side secondary thruster of this ACDropship. /// /// A pointer to the right side secondary thruster of this ACDropship. Ownership is NOT transferred. - AEmitter *GetURightThruster() const { return m_pURThruster; } + AEmitter * GetURightThruster() const { return m_pURThruster; } /// /// Sets the right side secondary thruster for this ACDropship. @@ -216,7 +216,7 @@ ClassInfoGetters /// Gets the left side secondary thruster of this ACDropship. /// /// A pointer to the left side secondary thruster of this ACDropship. Ownership is NOT transferred. - AEmitter *GetULeftThruster() const { return m_pULThruster; } + AEmitter * GetULeftThruster() const { return m_pULThruster; } /// /// Sets the left side secondary thruster for this ACDropship. @@ -228,7 +228,7 @@ ClassInfoGetters /// Gets the left side hatch of this ACDropship. /// /// A pointer to the left side hatch of this ACDropship. Ownership is NOT transferred. - Attachable *GetLeftHatch() const { return m_pLHatch; } + Attachable * GetLeftHatch() const { return m_pLHatch; } /// /// Sets the left side hatch for this ACDropship. @@ -240,7 +240,7 @@ ClassInfoGetters /// Gets the right side hatch of this ACDropship. /// /// A pointer to the right side hatch of this ACDropship. Ownership is NOT transferred. - Attachable *GetRightHatch() const { return m_pRHatch; } + Attachable * GetRightHatch() const { return m_pRHatch; } /// /// Sets the right side hatch for this ACDropship. diff --git a/Entities/ACRocket.h b/Entities/ACRocket.h index 41b222664..a03b4fe83 100644 --- a/Entities/ACRocket.h +++ b/Entities/ACRocket.h @@ -201,7 +201,7 @@ ClassInfoGetters /// Gets the right leg of this ACRocket. /// /// A pointer to the right leg of this ACRocket. Ownership is NOT transferred. - Leg *GetRightLeg() const { return m_pRLeg; } + Leg * GetRightLeg() const { return m_pRLeg; } /// /// Sets the right leg for this ACRocket. @@ -213,7 +213,7 @@ ClassInfoGetters /// Gets the left leg of this ACRocket. /// /// A pointer to the left leg of this ACRocket. Ownership is NOT transferred. - Leg *GetLeftLeg() const { return m_pLLeg; } + Leg * GetLeftLeg() const { return m_pLLeg; } /// /// Sets the left leg for this ACRocket. @@ -225,7 +225,7 @@ ClassInfoGetters /// Gets the main thruster of this ACRocket. /// /// A pointer to the main thruster of this ACRocket. Ownership is NOT transferred. - AEmitter *GetMainThruster() const { return m_pMThruster; } + AEmitter * GetMainThruster() const { return m_pMThruster; } /// /// Sets the main thruster for this ACRocket. @@ -237,7 +237,7 @@ ClassInfoGetters /// Gets the right side thruster of this ACRocket. /// /// A pointer to the right side thruster of this ACRocket. Ownership is NOT transferred. - AEmitter *GetRightThruster() const { return m_pRThruster; } + AEmitter * GetRightThruster() const { return m_pRThruster; } /// /// Sets the right side thruster for this ACRocket. @@ -249,7 +249,7 @@ ClassInfoGetters /// Gets the left side thruster of this ACRocket. /// /// A pointer to the left side thruster of this ACRocket. Ownership is NOT transferred. - AEmitter *GetLeftThruster() const { return m_pLThruster; } + AEmitter * GetLeftThruster() const { return m_pLThruster; } /// /// Sets the left side thruster for this ACRocket. @@ -261,7 +261,7 @@ ClassInfoGetters /// Gets the right side secondary thruster of this ACRocket. /// /// A pointer to the right side secondary thruster of this ACRocket. Ownership is NOT transferred. - AEmitter *GetURightThruster() const { return m_pURThruster; } + AEmitter * GetURightThruster() const { return m_pURThruster; } /// /// Sets the right side secondary thruster for this ACRocket. @@ -273,7 +273,7 @@ ClassInfoGetters /// Gets the left side secondary thruster of this ACRocket. /// /// A pointer to the left side secondary thruster of this ACRocket. Ownership is NOT transferred. - AEmitter *GetULeftThruster() const { return m_pULThruster; } + AEmitter * GetULeftThruster() const { return m_pULThruster; } /// /// Sets the left side secondary thruster for this ACRocket. diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 10dd6afe9..31f1d66ce 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -491,12 +491,6 @@ Vector ACrab::GetEyePos() const ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -Attachable *ACrab::GetTurret() const { - return (m_pTurret && m_pTurret->IsAttached()) ? dynamic_cast(m_pTurret) : nullptr; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void ACrab::SetTurret(Attachable *newTurret) { if (newTurret == nullptr) { if (m_pTurret && m_pTurret->IsAttached()) { RemoveAttachable(m_pTurret); } diff --git a/Entities/ACrab.h b/Entities/ACrab.h index 3fcea49ae..fbd6d67ad 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -158,7 +158,7 @@ class ACrab : /// Gets the Turret of this ACrab. /// /// A pointer to Turret of this ACrab. Ownership is NOT transferred! - Attachable *GetTurret() const; + Turret * GetTurret() const { return m_pTurret; } /// /// Sets the Turret for this ACrab. Ownership IS transferred! @@ -170,7 +170,7 @@ class ACrab : /// Gets the jetpack of this ACrab. /// /// A pointer to the jetpack of this ACrab. Ownership is NOT transferred! - AEmitter *GetJetpack() const { return m_pJetpack; } + AEmitter * GetJetpack() const { return m_pJetpack; } /// /// Sets the jetpack for this ACrab. Ownership IS Transferred! @@ -182,7 +182,7 @@ class ACrab : /// Gets the left foreground Leg of this ACrab. /// /// A pointer to the left foreground Leg of this ACrab. Ownership is NOT transferred! - Attachable *GetLeftFGLeg() const { return static_cast(m_pLFGLeg); } + Leg * GetLeftFGLeg() const { return m_pLFGLeg; } /// /// Sets the left foreground Leg for this ACrab. Ownership IS transferred! @@ -194,7 +194,7 @@ class ACrab : /// Gets the left background Leg of this ACrab. /// /// A pointer to the left background Leg of this ACrab. Ownership is NOT transferred! - Attachable *GetLeftBGLeg() const { return static_cast(m_pLBGLeg); } + Leg * GetLeftBGLeg() const { m_pLBGLeg; } /// /// Sets the left background Leg for this ACrab. Ownership IS transferred! @@ -206,7 +206,7 @@ class ACrab : /// Gets the right foreground Leg of this ACrab. /// /// A pointer to the right foreground Leg of this ACrab. Ownership is NOT transferred! - Attachable *GetRightFGLeg() const { return static_cast(m_pRFGLeg); } + Leg * GetRightFGLeg() const { return m_pRFGLeg; } /// /// Sets the right foreground Leg for this ACrab. Ownership IS transferred! @@ -218,7 +218,7 @@ class ACrab : /// Gets the right BG Leg of this ACrab. /// /// A pointer to the right background Leg of this ACrab. Ownership is NOT transferred! - Attachable *GetRightBGLeg() const { return static_cast(m_pRBGLeg); } + Leg * GetRightBGLeg() const { return m_pRBGLeg; } /// /// Sets the right background Leg for this ACrab. Ownership IS transferred! diff --git a/Entities/ADoor.h b/Entities/ADoor.h index fbb8e0fe9..31c14e65f 100644 --- a/Entities/ADoor.h +++ b/Entities/ADoor.h @@ -71,7 +71,7 @@ namespace RTE { /// Gets the moving door Attachable of this ADoor /// /// A pointer to the door Attachable of this. Ownership is NOT transferred! - Attachable *GetDoor() const { return m_Door; } + Attachable * GetDoor() const { return m_Door; } /// /// Sets the moving door Attachable for this ADoor. diff --git a/Entities/AEmitter.h b/Entities/AEmitter.h index 552cc81c4..98e91859a 100644 --- a/Entities/AEmitter.h +++ b/Entities/AEmitter.h @@ -309,7 +309,7 @@ ClassInfoGetters /// Gets the flash of this AEmitter. /// /// A pointer to the AEmitter's flash. Ownership is NOT transferred! - Attachable *GetFlash() const { return m_pFlash; } + Attachable * GetFlash() const { return m_pFlash; } /// /// Sets the flash for this AEmitter. Ownership IS transferred! diff --git a/Entities/AHuman.h b/Entities/AHuman.h index ecfd31a9e..d0f47db5a 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -234,7 +234,7 @@ ClassInfoGetters /// Gets the head of this AHuman. /// /// A pointer to the head of this AHuman. Ownership is NOT transferred. - Attachable *GetHead() const { return m_pHead; } + Attachable * GetHead() const { return m_pHead; } /// /// Sets the head for this AHuman. @@ -246,7 +246,7 @@ ClassInfoGetters /// Gets the jetpack of this AHuman. /// /// A pointer to the jetpack of this AHuman. Ownership is NOT transferred. - AEmitter *GetJetpack() const { return m_pJetpack; } + AEmitter * GetJetpack() const { return m_pJetpack; } /// /// Sets the jetpack for this AHuman. @@ -258,7 +258,7 @@ ClassInfoGetters /// Gets the foreground Arm of this AHuman. /// /// A pointer to the foreground Arm of this AHuman. Ownership is NOT transferred. - Attachable *GetFGArm() const { return static_cast(m_pFGArm); } + Attachable * GetFGArm() const { return static_cast(m_pFGArm); } /// /// Sets the foreground Arm for this AHuman. @@ -270,7 +270,7 @@ ClassInfoGetters /// Gets the background arm of this AHuman. /// /// A pointer to the background arm of this AHuman. Ownership is NOT transferred. - Attachable *GetBGArm() const { return static_cast(m_pBGArm); } + Attachable * GetBGArm() const { return static_cast(m_pBGArm); } /// /// Sets the background Arm for this AHuman. @@ -282,7 +282,7 @@ ClassInfoGetters /// Gets the foreground Leg of this AHuman. /// /// A pointer to the foreground Leg of this AHuman. Ownership is NOT transferred. - Attachable *GetFGLeg() const { return static_cast(m_pFGLeg); } + Attachable * GetFGLeg() const { return static_cast(m_pFGLeg); } /// /// Sets the foreground Leg for this AHuman. @@ -294,7 +294,7 @@ ClassInfoGetters /// Gets the background Leg of this AHuman. /// /// A pointer to the background Leg of this AHuman. Ownership is NOT transferred. - Attachable *GetBGLeg() const { return static_cast(m_pBGLeg); } + Attachable * GetBGLeg() const { return static_cast(m_pBGLeg); } /// /// Sets the background Leg for this AHuman. @@ -306,7 +306,7 @@ ClassInfoGetters /// Gets the foot Attachable of this AHuman's foreground Leg. /// /// A pointer to the foot Attachable of this AHuman's foreground Leg. Ownership is NOT transferred! - Attachable *GetFGFoot() const { return m_pFGLeg ? m_pFGLeg->GetFoot() : nullptr; } + Attachable * GetFGFoot() const { return m_pFGLeg ? m_pFGLeg->GetFoot() : nullptr; } /// /// Sets the foot Attachable of this AHuman's foreground Leg. @@ -318,7 +318,7 @@ ClassInfoGetters /// Gets the foot Attachable of this AHuman's background Leg. /// /// A pointer to the foot Attachable of this AHuman's background Leg. Ownership is NOT transferred! - Attachable *GetBGFoot() const { return m_pBGLeg ? m_pBGLeg->GetFoot() : nullptr; } + Attachable * GetBGFoot() const { return m_pBGLeg ? m_pBGLeg->GetFoot() : nullptr; } /// /// Sets the foot Attachable of this AHuman's background Leg. diff --git a/Entities/Attachable.h b/Entities/Attachable.h index f076af092..31e693080 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -63,13 +63,13 @@ namespace RTE { /// Gets the MO which is the parent of this Attachable. /// /// A pointer to the parent of this Attachable. - MovableObject *GetParent() override { return m_Parent; } + MovableObject * GetParent() override { return m_Parent; } /// /// Gets the MO which is the parent of this Attachable. /// /// A pointer to the parent of this Attachable. - const MovableObject *GetParent() const override { return m_Parent; } + const MovableObject * GetParent() const override { return m_Parent; } /// /// Indicates whether this Attachable is attached to an MOSRotating parent or not. @@ -88,19 +88,19 @@ namespace RTE { /// Gets the MO which is the ultimate root parent of this Attachable and its parent. /// /// A pointer to the highest root parent of this Attachable. - MovableObject *GetRootParent() override { return m_Parent ? m_Parent->GetRootParent() : this; } + MovableObject * GetRootParent() override { return m_Parent ? m_Parent->GetRootParent() : this; } /// /// Gets the MO which is the ultimate root parent of this Attachable and its parent. /// /// A pointer to the highest root parent of this Attachable. - const MovableObject *GetRootParent() const override { return m_Parent ? m_Parent->GetRootParent() : this; } + const MovableObject * GetRootParent() const override { return m_Parent ? m_Parent->GetRootParent() : this; } /// /// Gets the stored offset between this Attachable's parent's position and the joint position. This should be maintained by the parent. /// /// A const reference Vector describing the offset from the parent's position to the joint position. - const Vector &GetParentOffset() const { return m_ParentOffset; } + const Vector & GetParentOffset() const { return m_ParentOffset; } /// /// Sets the stored offset between this Attachable's parent's Pos and the joint position. This should be maintained by the parent. @@ -222,7 +222,7 @@ namespace RTE { /// Sets the offset of the joint (the point around which this Attachable and its parent hinge) from this Attachable's center of mass/origin. /// /// A Vector describing the offset of the joint relative to the this Attachable's origin/center of mass position. - void SetJointOffset(Vector offset) { m_JointOffset = offset; } + void SetJointOffset(const Vector &offset) { m_JointOffset = offset; } #pragma endregion #pragma region Force Transferral @@ -266,25 +266,25 @@ namespace RTE { /// Gets the AEmitter that represents the wound added to this Attachable when it gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! /// /// A const pointer to the break wound AEmitter. - const AEmitter *GetBreakWound() const { return m_BreakWound; } + const AEmitter * GetBreakWound() const { return m_BreakWound; } /// /// Sets the AEmitter that represents the wound added to this Attachable when it gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! /// /// The AEmitter to use for this Attachable's breakwound. - void SetBreakWound(AEmitter *breakWound) { m_BreakWound = breakWound; } //TODO I added this for consistency but do we want it? Maybe should have a string version that does the presetman lookup, cause we need to have a working pointer to the breakwound. + void SetBreakWound(const AEmitter *breakWound) { m_BreakWound = breakWound; } //TODO I added this for consistency but do we want it? Maybe should have a string version that does the presetman lookup, cause we need to have a working pointer to the breakwound. /// /// Gets the AEmitter that represents the wound added to this Attachable's parent when this Attachable gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! /// /// A const pointer to the parent break wound AEmitter. - const AEmitter *GetParentBreakWound() const { return m_ParentBreakWound; } + const AEmitter * GetParentBreakWound() const { return m_ParentBreakWound; } /// /// Sets the AEmitter that represents the wound added to this Attachable's parent when this Attachable gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! /// /// The AEmitter to use for the parent's breakwound. - void SetParentBreakWound(AEmitter *breakWound) { m_ParentBreakWound = breakWound; } + void SetParentBreakWound(const AEmitter *breakWound) { m_ParentBreakWound = breakWound; } #pragma endregion #pragma region Inherited Value Getters and Setters diff --git a/Entities/HDFirearm.h b/Entities/HDFirearm.h index f56b167df..14b72358d 100644 --- a/Entities/HDFirearm.h +++ b/Entities/HDFirearm.h @@ -135,7 +135,7 @@ ClassInfoGetters /// Gets the Magazine of this HDFirearm. /// /// A pointer to Magazine of this HDFirearm. Ownership is NOT transferred! - Magazine *GetMagazine() const { return m_pMagazine; } + Magazine * GetMagazine() const { return m_pMagazine; } /// /// Sets the Magazine for this HDFirearm. Ownership IS transferred! @@ -147,7 +147,7 @@ ClassInfoGetters /// Gets the flash of this HDFirearm. /// /// A pointer to flash of this HDFirearm. Ownership is NOT transferred! - Attachable *GetFlash() const { return m_pFlash; } + Attachable * GetFlash() const { return m_pFlash; } /// /// Sets the flash for this HDFirearm. Ownership IS transferred! diff --git a/Entities/Leg.h b/Entities/Leg.h index 9cab33030..32ab8bf3e 100644 --- a/Entities/Leg.h +++ b/Entities/Leg.h @@ -60,7 +60,7 @@ namespace RTE { /// Gets the foot of this Leg. /// /// A pointer to foot of this Leg. Ownership is NOT transferred! - Attachable *GetFoot() const { return m_Foot; } + Attachable * GetFoot() const { return m_Foot; } /// /// Sets the foot for this Leg. Ownership IS transferred! diff --git a/Entities/MovableObject.h b/Entities/MovableObject.h index 01b84099f..a7c44f49d 100644 --- a/Entities/MovableObject.h +++ b/Entities/MovableObject.h @@ -826,7 +826,7 @@ friend class Atom; /// Gets the MO this MO is set not to hit even when MO hitting is enabled on this MO. /// /// The MO this MO is set not to hit. - const MovableObject *GetWhichMOToNotHit() const { return m_pMOToNotHit; } + const MovableObject * GetWhichMOToNotHit() const { return m_pMOToNotHit; } /// /// Sets this MO to not hit a specific other MO and all its children even when MO hitting is enabled on this MO. From fe85e83ebb6ec73d32e179f21367e9c44e959bae Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 26 Oct 2020 00:16:32 -0300 Subject: [PATCH 082/144] Renamed wordy includeAttachablesWithAXDamageMultiplier to the slightly less wordy includeXDamageAttachables --- Entities/MOSRotating.cpp | 38 +++++++++++++++++++------------------- Entities/MOSRotating.h | 24 ++++++++++++------------ 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index b84b0b563..181e8b00d 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -418,16 +418,16 @@ int MOSRotating::Save(Writer &writer) const ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int MOSRotating::GetGibWoundLimit(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const { +int MOSRotating::GetGibWoundLimit(bool includePositiveDamageAttachables, bool includeNegativeDamageAttachables, bool includeNoDamageAttachables) const { int gibWoundLimit = m_GibWoundLimit; - if (includeAttachablesWithAPositiveDamageMultiplier || includeAttachablesWithANegativeDamageMultiplier || includeAttachablesWithNoDamageMultiplier) { + if (includePositiveDamageAttachables || includeNegativeDamageAttachables || includeNoDamageAttachables) { for (const Attachable *attachable : m_Attachables) { - bool attachableSatisfiesConditions = (includeAttachablesWithAPositiveDamageMultiplier && attachable->GetDamageMultiplier() > 0) || - (includeAttachablesWithANegativeDamageMultiplier && attachable->GetDamageMultiplier() < 0) || - (includeAttachablesWithNoDamageMultiplier && attachable->GetDamageMultiplier() == 0); + bool attachableSatisfiesConditions = (includePositiveDamageAttachables && attachable->GetDamageMultiplier() > 0) || + (includeNegativeDamageAttachables && attachable->GetDamageMultiplier() < 0) || + (includeNoDamageAttachables && attachable->GetDamageMultiplier() == 0); if (attachableSatisfiesConditions) { - gibWoundLimit += attachable->GetGibWoundLimit(includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); + gibWoundLimit += attachable->GetGibWoundLimit(includePositiveDamageAttachables, includeNegativeDamageAttachables, includeNoDamageAttachables); } } } @@ -436,16 +436,16 @@ int MOSRotating::GetGibWoundLimit(bool includeAttachablesWithAPositiveDamageMult ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int MOSRotating::GetWoundCount(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const { +int MOSRotating::GetWoundCount(bool includePositiveDamageAttachables, bool includeNegativeDamageAttachables, bool includeNoDamageAttachables) const { int woundCount = m_Wounds.size(); - if (includeAttachablesWithAPositiveDamageMultiplier || includeAttachablesWithANegativeDamageMultiplier || includeAttachablesWithNoDamageMultiplier) { + if (includePositiveDamageAttachables || includeNegativeDamageAttachables || includeNoDamageAttachables) { for (const Attachable *attachable : m_Attachables) { - bool attachableSatisfiesConditions = (includeAttachablesWithAPositiveDamageMultiplier && attachable->GetDamageMultiplier() > 0) || - (includeAttachablesWithANegativeDamageMultiplier && attachable->GetDamageMultiplier() < 0) || - (includeAttachablesWithNoDamageMultiplier && attachable->GetDamageMultiplier() == 0); + bool attachableSatisfiesConditions = (includePositiveDamageAttachables && attachable->GetDamageMultiplier() > 0) || + (includeNegativeDamageAttachables && attachable->GetDamageMultiplier() < 0) || + (includeNoDamageAttachables && attachable->GetDamageMultiplier() == 0); if (attachableSatisfiesConditions) { - woundCount += attachable->GetWoundCount(includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); + woundCount += attachable->GetWoundCount(includePositiveDamageAttachables, includeNegativeDamageAttachables, includeNoDamageAttachables); } } } @@ -474,18 +474,18 @@ void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) { +float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includePositiveDamageAttachables, bool includeNegativeDamageAttachables, bool includeNoDamageAttachables) { float damage = 0; - int woundCount = GetWoundCount(includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); + int woundCount = GetWoundCount(includePositiveDamageAttachables, includeNegativeDamageAttachables, includeNoDamageAttachables); std::vector> woundedParts; if (woundCount > 0) { woundedParts.push_back({this, woundCount}); } for (Attachable *attachable : m_Attachables) { - bool attachableSatisfiesConditions = (includeAttachablesWithAPositiveDamageMultiplier && attachable->GetDamageMultiplier() > 0) || - (includeAttachablesWithANegativeDamageMultiplier && attachable->GetDamageMultiplier() < 0) || - (includeAttachablesWithNoDamageMultiplier && attachable->GetDamageMultiplier() == 0); - int attachableWoundCount = attachable->GetWoundCount(includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); + bool attachableSatisfiesConditions = (includePositiveDamageAttachables && attachable->GetDamageMultiplier() > 0) || + (includeNegativeDamageAttachables && attachable->GetDamageMultiplier() < 0) || + (includeNoDamageAttachables && attachable->GetDamageMultiplier() == 0); + int attachableWoundCount = attachable->GetWoundCount(includePositiveDamageAttachables, includeNegativeDamageAttachables, includeNoDamageAttachables); if (attachableSatisfiesConditions && attachableWoundCount > 0) { woundedParts.push_back({attachable, attachableWoundCount}); } } @@ -518,7 +518,7 @@ float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includeAttachab damage += removeFirstWoundEmitter() * GetDamageMultiplier(); } else { //TODO This is less efficient than it should be. We already collected all wounded parts and their wounds above, we should pass that in (make another function overload) instead of collecting everything again. It might be wise to use a tree for this purpose. - damage += woundedPart->RemoveWounds(1, includeAttachablesWithAPositiveDamageMultiplier, includeAttachablesWithANegativeDamageMultiplier, includeAttachablesWithNoDamageMultiplier); + damage += woundedPart->RemoveWounds(1, includePositiveDamageAttachables, includeNegativeDamageAttachables, includeNoDamageAttachables); } if (woundedParts[woundedPartIndex].second-- <= 0) { woundedParts.erase(woundedParts.begin() + woundedPartIndex); } } diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 0424694a2..7ec1b3763 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -591,11 +591,11 @@ ClassInfoGetters /// Gets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. /// Optionally adds the gib wound limits of Attachables (and their Attachables, etc.) that match the conditions set by the provided parameters. /// - /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. - /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. - /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. /// The wound limit of this MOSRotating and, optionally, its Attachables. - int GetGibWoundLimit(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const; + int GetGibWoundLimit(bool includePositiveDamageAttachables, bool includeNegativeDamageAttachables, bool includeNoDamageAttachables) const; /// /// Sets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. @@ -626,12 +626,12 @@ ClassInfoGetters /// /// Gets the number of wounds attached to this MOSRotating. /// Optionally adds the wound counts of Attachables (and their Attachables, etc.) that match the conditions set by the provided parameters. - /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. - /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. - /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. /// The number of wounds on this MOSRotating and, optionally, its Attachables. /// - int GetWoundCount(bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) const; + int GetWoundCount(bool includePositiveDamageAttachables, bool includeNegativeDamageAttachables, bool includeNoDamageAttachables) const; /// /// Adds the passed in wound AEmitter to the list of wounds and changes its parent offset to the passed in Vector. @@ -654,11 +654,11 @@ ClassInfoGetters /// Optionally removes wounds from Attachables (and their Attachables, etc.) that match the conditions set by the provided inclusion parameters. /// /// The number of wounds that should be removed. - /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. - /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. - /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this MOSRotating) when wounded. + /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this MOSRotating) when wounded. /// The amount of damage caused by these wounds, taking damage multipliers into account. - virtual float RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier); + virtual float RemoveWounds(int numberOfWoundsToRemove, bool includePositiveDamageAttachables, bool includeNegativeDamageAttachables, bool includeNoDamageAttachables); ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetStringValue From 1db9cd88a6abb7c8f5a0228cb05b0658edcf605f Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 26 Oct 2020 00:22:51 -0300 Subject: [PATCH 083/144] Changed ContainsSubGroup to long instead of long int, and made it const --- Entities/AtomGroup.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Entities/AtomGroup.h b/Entities/AtomGroup.h index 29618ca3c..c0abeab54 100644 --- a/Entities/AtomGroup.h +++ b/Entities/AtomGroup.h @@ -206,7 +206,7 @@ namespace RTE { /// /// The subgroupID to check for. /// Whether this AtomGroup contains a subgroup with the given subgroupID. - bool ContainsSubGroup(long int subgroupID) { return m_SubGroups.count(subgroupID) != 0; } + bool ContainsSubGroup(long subgroupID) const { return m_SubGroups.count(subgroupID) != 0; } /// /// Updates the offsets of a subgroup of Atoms in this AtomGroup. This allows repositioning a subgroup to match the position and rotation of the graphical representation of it's owner MOSR. From 097c7c62722126c477ec031c9866935e737897d6 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 26 Oct 2020 19:07:02 -0300 Subject: [PATCH 084/144] Fixed build problems - forgot to return in ACrab, had to un-const some setter params for luabind to be okay with things --- Entities/ACrab.h | 2 +- Entities/Attachable.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Entities/ACrab.h b/Entities/ACrab.h index fbd6d67ad..c2df526ef 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -194,7 +194,7 @@ class ACrab : /// Gets the left background Leg of this ACrab. /// /// A pointer to the left background Leg of this ACrab. Ownership is NOT transferred! - Leg * GetLeftBGLeg() const { m_pLBGLeg; } + Leg * GetLeftBGLeg() const { return m_pLBGLeg; } /// /// Sets the left background Leg for this ACrab. Ownership IS transferred! diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 31e693080..777466b37 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -272,7 +272,7 @@ namespace RTE { /// Sets the AEmitter that represents the wound added to this Attachable when it gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! /// /// The AEmitter to use for this Attachable's breakwound. - void SetBreakWound(const AEmitter *breakWound) { m_BreakWound = breakWound; } //TODO I added this for consistency but do we want it? Maybe should have a string version that does the presetman lookup, cause we need to have a working pointer to the breakwound. + void SetBreakWound(AEmitter *breakWound) { m_BreakWound = breakWound; } /// /// Gets the AEmitter that represents the wound added to this Attachable's parent when this Attachable gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! @@ -284,7 +284,7 @@ namespace RTE { /// Sets the AEmitter that represents the wound added to this Attachable's parent when this Attachable gets detached from its parent. OWNERSHIP IS NOT TRANSFERRED! /// /// The AEmitter to use for the parent's breakwound. - void SetParentBreakWound(const AEmitter *breakWound) { m_ParentBreakWound = breakWound; } + void SetParentBreakWound(AEmitter *breakWound) { m_ParentBreakWound = breakWound; } #pragma endregion #pragma region Inherited Value Getters and Setters From 94e84e37860a25e8689428808cf83ac32cea83d1 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 1 Nov 2020 17:37:31 -0400 Subject: [PATCH 085/144] Review Comments Made jetpacks not delete when removed from their parent Moved Magazine terrain collision setting from HDFirearm::ReadProperty to Magazine::Create so it can be overriden by INI. Also fixed a missing ! in discardable checks Made MOSR::GetGibWoundLimit no argument version return just the MOSR's GibWoundLimit and tweaked changelog accordingly --- CHANGELOG.md | 2 +- Entities/AHuman.cpp | 1 - Entities/HDFirearm.cpp | 3 +-- Entities/MOSRotating.h | 5 ++--- Entities/Magazine.cpp | 2 ++ 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ff656732..ee5c30bb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -290,7 +290,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), Wound management is now always done with `MOSRotating` functions, instead of requiring different ones for `Actors`. This means TotalWoundCount and RemoveAnyRandomWounds no longer exist. You can get all wounds with `GetWounds`, get the wound count with `GetWoundCount` (or using the pre-existing WoundCount property), get the gib wound limit with `GetGibWoundLimit` (or using the pre-existing GibWoundLimit property), and remove wounds with `RemoveWounds`. All of these functions have two variants, one lets you just specify any normal arguments (e.g. number of wounds to remove), the other lets you also specify whether you want to include `Attachables` with a positive `DamageMultiplier` (i.e. `Attachables` that damage their parent), `Attachables` with a negative `DamageMultiplier` (i.e. `Attachables` that heal their parent) or `Attachables` with no `DamageMultiplier` (i.e. `Attachables` that don't affect their parent). - Without any arguments, these functions will only include `Attachables` with a positive `DamageMultiplier` in their counting calculations. The property variants (e.g. mosr.WoundCount) also behave this way. + Without any arguments, `GetWoundCount` and `RemoveWounds` will only include `Attachables` with a positive `DamageMultiplier` in their counting calculations, and `GetGibWoundLimit` will not include any `Attachables` in its counting calculations. The property variants (e.g. mosr.WoundCount) behave the same way as the no-argument versions. Note that this process is recursive, so if an `Attachable` that satisfies the conditions has `Attachables` that also satisfy the conditions, their wounds will be included in the results. - Renamed `Turret` INI property `MountedMO` to `MountedDevice` to better match the new reality that `Turrets` can only mount `HeldDevices` and their child classes. diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index c04316eef..bbdbd32b3 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -237,7 +237,6 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { AddAttachable(m_pJetpack); if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } m_pJetpack->SetApplyTransferredForcesAtOffset(false); - m_pJetpack->SetDeleteWhenRemovedFromParent(true); } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; // Convert to ms diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index 8da1c48c8..d41096152 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -152,7 +152,6 @@ int HDFirearm::ReadProperty(std::string propName, Reader &reader) { m_pMagazineReference = dynamic_cast(magazineEntity); m_pMagazine = dynamic_cast(magazineEntity->Clone()); AddAttachable(m_pMagazine); - m_pMagazine->SetCollidesWithTerrainWhileAttached(false); } } else if (propName == "Flash") { RemoveAttachable(m_pFlash); @@ -599,7 +598,7 @@ void HDFirearm::Reload() { m_pMagazine->SetVel(m_Vel + Vector(m_HFlipped ? -3 : 3, 0.3)); m_pMagazine->SetAngularVel(6.0F + (-RandomNum(0.0F, 6.0F))); - if (m_pMagazine->IsDiscardable()) { m_pMagazine->SetToDelete(); } + if (!m_pMagazine->IsDiscardable()) { m_pMagazine->SetToDelete(); } RemoveAttachable(m_pMagazine, m_pMagazine->IsDiscardable(), false); m_pMagazine = 0; } diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 7ec1b3763..3e44e27e2 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -581,11 +581,10 @@ ClassInfoGetters void SetGibImpulseLimit(float newGibImpulseLimit) { m_GibImpulseLimit = newGibImpulseLimit; } /// - /// Gets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. - /// Includes any Attachables (and their Attachables, etc.) that have a positive damage multiplier. + /// Gets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. Does not include any Attachables. /// /// - int GetGibWoundLimit() const { return GetGibWoundLimit(true, false, false); } + int GetGibWoundLimit() const { return GetGibWoundLimit(false, false, false); } /// /// Gets the gib wound limit for this MOSRotating, i.e. the total number of wounds required to gib this MOSRotating. diff --git a/Entities/Magazine.cpp b/Entities/Magazine.cpp index 00a0d24bf..221a56ed0 100644 --- a/Entities/Magazine.cpp +++ b/Entities/Magazine.cpp @@ -50,6 +50,8 @@ int Magazine::Create() { if (Attachable::Create() < 0) return -1; + + SetCollidesWithTerrainWhileAttached(false); // Read projectile properties for AI aim caluculations const Round * pNextRound = GetNextRound(); From 71976ac00182d4e83b97d4fca95c9d2adf7ac42e Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 1 Nov 2020 17:52:35 -0400 Subject: [PATCH 086/144] Added pickup limitation handling to HeldDevice Used pickup limitations to determine when AHumans can pick things up Used pickup limitations to make it so turret mounted devices will not be pickupable Added lua bindings and changelog entries for pickup limitations Added changelog entry for pickup limitations --- CHANGELOG.md | 18 ++++++++++++++++++ Entities/AHuman.cpp | 7 +++---- Entities/HeldDevice.cpp | 41 +++++++++++++++++++++++++++++++++++++++-- Entities/HeldDevice.h | 37 +++++++++++++++++++++++++++++++++++++ Entities/Turret.cpp | 2 +- Managers/LuaMan.cpp | 5 +++++ 6 files changed, 103 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee5c30bb4..ef239dda6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -173,6 +173,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - New Lua `MovableObject` function `GetWhichMOToNotHit`. This provides access to the MO that has been set to not be hit by `SetWhichMOToNotHit`. +- Added `HeldDevice` handling to limit which `Actor(s)` can pick it up. Note that pickup limitations are all done by PresetName, so you can not use this to specify specific `Actors` (yet). + The INI definition looks like this: + ``` + PickupableBy = PickupableByEntries + AddActorEntry = First Actor PresetName Here + AddActorEntry = Second Actor PresetName Here + // Alternatively, you can set it to never be pickupable with + NoActorsCanPickThisUp = 1 + ``` + The Lua properties and functions are as follows: + ``` + heldDevice.HasPickupLimitations; --(R) Whether or not this HeldDevice has any limitations affecting whether it can be picked up. + heldDevice.NoActorsCanPickThisUp --(R/W) Whether this HeldDevice is/should be pickupable by any Actors. + heldDevice:ActorCanPickThisUp(actor) -- Whether or not a given Actor can pick up this HeldDevice. + heldDevice:AddActorWhoCanPickThisUp(actor) -- Allows the given Actor (and any others with the same PresetName) to pick up this HeldDevice. + heldDevice:RemoveActorWhoCanPickThisUp(actor) -- Disallows the given Actor (and any others with the same PresetName) from picking up this HeldDevice. + ``` + ### Changed - Codebase now uses the C++17 standard. diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index bbdbd32b3..98c220d32 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -3467,7 +3467,7 @@ void AHuman::Update() // Set the grenade or whatever to ignore hits with same team pMO->SetTeam(m_Team); pMO->SetIgnoresTeamHits(true); - g_MovableMan.AddItem(pMO); + g_MovableMan.AddMO(pMO); } else { if (pMO->IsGold()) { m_GoldInInventoryChunk = 0; @@ -3524,7 +3524,7 @@ void AHuman::Update() pMO->SetVel(tossVec.GetXFlipped(m_HFlipped) * m_Rotation); pMO->SetAngularVel(5.0F * RandomNormalNum()); if (pMO->IsDevice()) { - g_MovableMan.AddItem(pMO); + g_MovableMan.AddMO(pMO); } else { if (pMO->IsGold()) { m_GoldInInventoryChunk = 0; @@ -3559,8 +3559,7 @@ void AHuman::Update() } // Item currently set to be within reach has expired or is now out of range - if (m_pItemInReach && (!g_MovableMan.IsDevice(m_pItemInReach) || (m_pItemInReach->GetPos() - m_Pos).GetMagnitude() > reach)) - { + if (m_pItemInReach && (m_pItemInReach->GetNoActorsCanPickThisUp() || (m_pItemInReach->HasPickupLimitations() && !m_pItemInReach->ActorCanPickThisUp(GetPresetName())) || !g_MovableMan.IsDevice(m_pItemInReach) || (m_pItemInReach->GetPos() - m_Pos).GetMagnitude() > reach)) { m_pItemInReach = 0; m_PieNeedsUpdate = true; } diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index 472fbc9da..dda756536 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -46,6 +46,7 @@ void HeldDevice::Clear() m_MaxSharpLength = 0; m_Supported = false; m_SupportOffset.Reset(); + m_ActorsWhoCanPickThisUp.clear(); m_GripStrengthMultiplier = 1.0F; m_BlinkTimer.Reset(); m_PieSlices.clear(); @@ -134,6 +135,9 @@ int HeldDevice::Create(const HeldDevice &reference) m_StanceOffset = reference.m_StanceOffset; m_SharpStanceOffset = reference.m_SharpStanceOffset; m_SupportOffset = reference.m_SupportOffset; + for (std::string referenceActorWhoCanPickThisUp : reference.m_ActorsWhoCanPickThisUp) { + m_ActorsWhoCanPickThisUp.insert(referenceActorWhoCanPickThisUp); + } m_GripStrengthMultiplier = reference.m_GripStrengthMultiplier; m_SharpAim = reference.m_SharpAim; @@ -170,7 +174,29 @@ int HeldDevice::ReadProperty(std::string propName, Reader &reader) reader >> m_SharpStanceOffset; else if (propName == "SupportOffset") reader >> m_SupportOffset; - else if (propName == "GripStrengthMultiplier") { + else if (propName == "PickupableBy") { + std::string pickupableByValue = reader.ReadPropValue(); + if (pickupableByValue == "PickupableByEntries") { + while (reader.NextProperty()) { + std::string pickupableByEntryType = reader.ReadPropName(); + if (pickupableByEntryType == "AddActorEntry") { + m_ActorsWhoCanPickThisUp.insert(reader.ReadPropValue()); + } else if (pickupableByEntryType == "AddGroupEntry ") { + reader.ReportError("AddGroupEntry is not yet supported."); + } else if (pickupableByEntryType == "AddDataModuleEntry ") { + reader.ReportError("AddDataModuleEntry is not yet supported."); + } else { + break; + } + } + } else { + m_ActorsWhoCanPickThisUp.insert(pickupableByValue); + } + } else if (propName == "NoActorsCanPickThisUp") { + bool noActorsCanPickThisUp; + reader >> noActorsCanPickThisUp; + SetNoActorsCanPickThisUp(noActorsCanPickThisUp); + } else if (propName == "GripStrengthMultiplier") { reader >> m_GripStrengthMultiplier; } else if (propName == "SharpLength") reader >> m_MaxSharpLength; @@ -259,6 +285,17 @@ Vector HeldDevice::GetStanceOffset() const return m_StanceOffset.GetXFlipped(m_HFlipped); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void HeldDevice::SetNoActorsCanPickThisUp(bool noActors) { + if (noActors) { + AddActorWhoCanPickThisUp("|-NONE-|"); + } else { + RemoveActorWhoCanPickThisUp("|-NONE-|"); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetSupportPos @@ -498,7 +535,7 @@ void HeldDevice::DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos, int whi Attachable::DrawHUD(pTargetBitmap, targetPos, whichScreen); - if (!m_Parent) + if (!m_Parent && !GetNoActorsCanPickThisUp()) { // Only draw if the team viewing this has seen the space where this is located int viewingTeam = g_ActivityMan.GetActivity()->GetTeamOfPlayer(g_ActivityMan.GetActivity()->PlayerOfScreen(whichScreen)); diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index 0faa1b1cf..ac5f47d95 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -281,6 +281,42 @@ ClassInfoGetters void SetSupportOffset(Vector newOffset) { m_SupportOffset = newOffset; } + /// + /// Gets whether this HeldDevice has any limitations on who can pick it up. + /// + /// Whether this HeldDevice has any limitations on who can pick it up. + bool HasPickupLimitations() const { return !m_ActorsWhoCanPickThisUp.empty(); } + + /// + /// Gets whether no Actors (or child classes) can pick up this HeldDevice. + /// + /// Whether no Actors (or child classes) can pick up this HeldDevice. + bool GetNoActorsCanPickThisUp() const { return m_ActorsWhoCanPickThisUp.find("NONE") != m_ActorsWhoCanPickThisUp.end(); } + + /// + /// Sets whether no Actors (or child classes) can pick up this HeldDevice. + /// + /// Whether no Actors (or child classes) should be able to pick up this HeldDevice. True means none will be able to, false means any other limitations will apply normally. + void SetNoActorsCanPickThisUp(bool noActors); + + /// + /// Checks whether Actors with the given PresetName can pick up this HeldDevice. + /// + /// The PresetName of the Actor to check. Ownership is NOT transferred. + /// Whether Actors with the given PresetName can pick up this HeldDevice. + bool ActorCanPickThisUp(const std::string &actorPresetName) { return m_ActorsWhoCanPickThisUp.find(actorPresetName) != m_ActorsWhoCanPickThisUp.end(); } + + /// + /// Allow any Actors (or child classes) with the given PresetName to pick up this HeldDevice, as long as it's not set so no Actors can pick it up. + /// + /// The PresetName of an Actor who should be able to pick up this HeldDevice. + void AddActorWhoCanPickThisUp(const std::string &actorPresetName) { m_ActorsWhoCanPickThisUp.insert(actorPresetName); } + + /// + /// Remove allowance for any Actors (or child classes) with the given PresetName from picking up this HeldDevice. Note that if no specific Actors are allowed to pick this HeldDevice up, all Actors will be allowed to do so unless it's set so no Actors can pick it up. + /// + /// The PresetName of an Actor who should no longer be able to pick up this HeldDevice. + void RemoveActorWhoCanPickThisUp(const std::string &actorPresetName) { m_ActorsWhoCanPickThisUp.erase(m_ActorsWhoCanPickThisUp.find(actorPresetName)); } /// /// Gets the multiplier for how well this HeldDevice can be gripped by Arms. @@ -589,6 +625,7 @@ ClassInfoGetters float m_MaxSharpLength; // If this HeldDevice is currently being supported by a second hand. bool m_Supported; + std::unordered_set m_ActorsWhoCanPickThisUp; //!< The unordered set of Actors (and appropriate subclasses) who can pick up this held device if it's dropped. An empty set means any Actors can pick it up, a "NONE" entry means none can pick it up. float m_GripStrengthMultiplier; //!< The multiplier for how well this HeldDevice can be gripped by Arms. // Blink timer for the icon Timer m_BlinkTimer; diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index bcf7036c3..c6c2450d0 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -36,7 +36,7 @@ namespace RTE { m_MountedDevice = dynamic_cast(mountedDeviceEntity->Clone()); AddAttachable(m_MountedDevice); m_MountedDevice->SetInheritsRotAngle(false); - m_MountedDevice->SetDeleteWhenRemovedFromParent(true); + m_MountedDevice->SetNoActorsCanPickThisUp(true); //Force weapons mounted on turrets to never be removed due to forces. This doesn't affect them gibbing from hitting their impulse limits though. m_MountedDevice->SetJointStrength(0.0F); } diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 8877524bb..107b2fb4b 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1313,6 +1313,11 @@ int LuaMan::Create() { .def("IsFull", &HeldDevice::IsFull) .property("SharpLength", &HeldDevice::GetSharpLength, &HeldDevice::SetSharpLength) .property("SupportOffset", &HeldDevice::GetSupportOffset, &HeldDevice::SetSupportOffset) + .property("HasPickupLimitations", &HeldDevice::HasPickupLimitations) + .property("NoActorsCanPickThisUp", &HeldDevice::GetNoActorsCanPickThisUp, &HeldDevice::SetNoActorsCanPickThisUp) + .def("ActorCanPickThisUp", &HeldDevice::ActorCanPickThisUp) + .def("AddActorWhoCanPickThisUp", &HeldDevice::AddActorWhoCanPickThisUp) + .def("RemoveActorWhoCanPickThisUp", &HeldDevice::RemoveActorWhoCanPickThisUp) .property("GripStrengthMultiplier", &HeldDevice::GetGripStrengthMultiplier, &HeldDevice::SetGripStrengthMultiplier) .def("SetSupported", &HeldDevice::SetSupported), From 2c0fe51852026de562456928daa7903388b6289b Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 2 Nov 2020 12:38:39 -0400 Subject: [PATCH 087/144] Added GetIndividualMass and GetInventoryMass to MOSR and Actor Tweaked some comments and cleaned up code a little Added lua property bindings for these mass methods and updated changelog accordingly --- CHANGELOG.md | 4 ++++ Entities/Actor.cpp | 22 ++++++++-------------- Entities/Actor.h | 19 ++++++++++--------- Entities/MOSRotating.h | 10 ++++++++-- Managers/LuaMan.cpp | 2 ++ 5 files changed, 32 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef239dda6..e9171bccf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -190,6 +190,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), heldDevice:AddActorWhoCanPickThisUp(actor) -- Allows the given Actor (and any others with the same PresetName) to pick up this HeldDevice. heldDevice:RemoveActorWhoCanPickThisUp(actor) -- Disallows the given Actor (and any others with the same PresetName) from picking up this HeldDevice. ``` + +- Added `MOSRotating` Lua (R) property `IndividualMass`. This provides access to the `MOSRotating's` actual mass value, not including any `Attachables` or inventory items. Note that the normal `Mass` property is still used to set the `MOSRotating's` mass. + +- Added `Actor` Lua (R) property `InventoryMass`. This provides access to the mass of the `Actor's` inventory separate from the `Actor's` actual mass. ### Changed diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index df923139e..1afa5ec5c 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -506,22 +506,16 @@ int Actor::LoadScript(std::string const &scriptPath, bool loadAsEnabledScript) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this Actor, including the mass of its -// currently attached body parts and inventory. - -float Actor::GetMass() const -{ - float totalMass = MOSRotating::GetMass(); - for (deque::const_iterator itr = m_Inventory.begin(); itr != m_Inventory.end(); ++itr) - totalMass += (*itr)->GetMass(); - totalMass += m_GoldCarried * g_SceneMan.GetKgPerOz(); - return totalMass; +float Actor::GetInventoryMass() const { + float inventoryMass = 0.0F; + for (const MovableObject *inventoryItem : m_Inventory) { + inventoryMass += inventoryItem->GetMass(); + } + return inventoryMass; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// // Method: IsPlayerControlled diff --git a/Entities/Actor.h b/Entities/Actor.h index 8c4cf3d0d..3d478ec8c 100644 --- a/Entities/Actor.h +++ b/Entities/Actor.h @@ -147,16 +147,17 @@ ClassInfoGetters /// An error return value signaling success or any particular failure. Anything below 0 is an error signal. int LoadScript(std::string const &scriptPath, bool loadAsEnabledScript = false) override; + /// + /// Gets the mass of this Actor's inventory. Does not include any equipped item (for actor subtypes that have that). + /// + /// The mass of this Actor's inventory. + float GetInventoryMass() const; -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: GetMass -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the mass value of this Actor, including the mass of its -// currently attached body parts and inventory. -// Arguments: None. -// Return value: A float describing the mass value in Kilograms (kg). - - float GetMass() const override; + /// + /// Gets the mass of this Actor, including the mass of its Attachables, wounds and inventory. + /// + /// The mass of this Actor, its inventory and all its Attachables and wounds in Kilograms (kg). + float GetMass() const override { return MOSRotating::GetMass() + GetInventoryMass() + (m_GoldCarried * g_SceneMan.GetKgPerOz()); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 3e44e27e2..05e76224d 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -137,9 +137,15 @@ ClassInfoGetters void Destroy(bool notInherited = false) override; /// - /// Gets the mass value of this MOSRotating, including the mass of all its Attachables and their Attachables and so on. + /// Gets the mass value of this MOSRotating, not including any Attachables or wounds. /// - /// The mass of this MOSRotating and all Attachables in Kilograms (kg). + /// The mass of this MOSRotating. + float GetIndividualMass() const { return MovableObject::GetMass(); } + + /// + /// Gets the mass value of this MOSRotating, including the mass of all its Attachables and wounds, and their Attachables and so on. + /// + /// The mass of this MOSRotating and all of its Attachables and wounds in Kilograms (kg). float GetMass() const override { return MovableObject::GetMass() + m_AttachableAndWoundMass; } /// diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 107b2fb4b..39def9b47 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -773,6 +773,7 @@ int LuaMan::Create() { CONCRETELUABINDING(MOSRotating, MOSprite) /*.property("Material", &MOSRotating::GetMaterial)*/ + .property("IndividualMass", &MOSRotating::GetIndividualMass) .property("RecoilForce", &MOSRotating::GetRecoilForce) .property("RecoilOffset", &MOSRotating::GetRecoilOffset) .property("TravelImpulse", &MOSRotating::GetTravelImpulse, &MOSRotating::SetTravelImpulse) @@ -963,6 +964,7 @@ int LuaMan::Create() { .property("Status", &Actor::GetStatus, &Actor::SetStatus) .property("Health", &Actor::GetHealth, &Actor::SetHealth) .property("MaxHealth", &Actor::GetMaxHealth, &Actor::SetMaxHealth) + .property("InventoryMass", &Actor::GetInventoryMass) .property("GoldCarried", &Actor::GetGoldCarried, &Actor::SetGoldCarried) .property("AimRange", &Actor::GetAimRange, &Actor::SetAimRange) .def("GetAimAngle", &Actor::GetAimAngle) From f352a48a6edc9269c23dd77f5c26515d81b87670 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 4 Nov 2020 14:09:37 -0400 Subject: [PATCH 088/144] Added const for no pickups and used it to fix a dumb bug I made --- Entities/HeldDevice.cpp | 5 +++-- Entities/HeldDevice.h | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index dda756536..51e1fccdd 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -25,6 +25,7 @@ namespace RTE { ConcreteClassInfo(HeldDevice, Attachable, 50) +const std::string HeldDevice::c_NoPickupString = "|-NONE-|"; ////////////////////////////////////////////////////////////////////////////////////////// // Method: Clear @@ -289,9 +290,9 @@ Vector HeldDevice::GetStanceOffset() const void HeldDevice::SetNoActorsCanPickThisUp(bool noActors) { if (noActors) { - AddActorWhoCanPickThisUp("|-NONE-|"); + AddActorWhoCanPickThisUp(c_NoPickupString); } else { - RemoveActorWhoCanPickThisUp("|-NONE-|"); + RemoveActorWhoCanPickThisUp(c_NoPickupString); } } diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index ac5f47d95..48d6cb19e 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -291,7 +291,7 @@ ClassInfoGetters /// Gets whether no Actors (or child classes) can pick up this HeldDevice. /// /// Whether no Actors (or child classes) can pick up this HeldDevice. - bool GetNoActorsCanPickThisUp() const { return m_ActorsWhoCanPickThisUp.find("NONE") != m_ActorsWhoCanPickThisUp.end(); } + bool GetNoActorsCanPickThisUp() const { return m_ActorsWhoCanPickThisUp.find(c_NoPickupString) != m_ActorsWhoCanPickThisUp.end(); } /// /// Sets whether no Actors (or child classes) can pick up this HeldDevice. @@ -599,6 +599,8 @@ ClassInfoGetters protected: + static const std::string c_NoPickupString; //!< Static string for adding a no allowed pickups entry. + // Member variables static Entity::ClassInfo m_sClass; // Indicates what kind of held device this is, see the HeldDeviceType enum @@ -625,7 +627,7 @@ ClassInfoGetters float m_MaxSharpLength; // If this HeldDevice is currently being supported by a second hand. bool m_Supported; - std::unordered_set m_ActorsWhoCanPickThisUp; //!< The unordered set of Actors (and appropriate subclasses) who can pick up this held device if it's dropped. An empty set means any Actors can pick it up, a "NONE" entry means none can pick it up. + std::unordered_set m_ActorsWhoCanPickThisUp; //!< The unordered set of Actors (and appropriate subclasses) who can pick up this held device if it's dropped. An empty set means any Actors can pick it up, a c_NoPickupString entry means none can pick it up. float m_GripStrengthMultiplier; //!< The multiplier for how well this HeldDevice can be gripped by Arms. // Blink timer for the icon Timer m_BlinkTimer; From 1126c38085a34bfc96a46eabb15cd1a511c61a11 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 4 Nov 2020 22:22:28 -0400 Subject: [PATCH 089/144] Review comments (sort of), pulled some simpler update stuff that had been split into methods back into Leg::Update --- Entities/Leg.cpp | 38 ++++++++++++++++---------------------- Entities/Leg.h | 10 ++-------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index 717666c5e..826f8ac5f 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -146,20 +146,33 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Leg::Update() { - UpdateCurrentAnkleOffsetAndFootParentOffset(); + UpdateCurrentAnkleOffset(); + + if (m_Foot) { + // In order to keep the foot in the right place, we need to convert its offset (the ankle offstet) to work as the ParentOffset for the foot. + // The foot will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. + Vector ankleOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_CurrentAnkleOffset; + ankleOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); + m_Foot->SetParentOffset(ankleOffsetAsParentOffset); + } Attachable::Update(); UpdateLegRotation(); - UpdateLegFrameAndNormalizedExtension(); + if (m_FrameCount == 1) { + m_Frame = 0; + } else { + m_CurrentNormalizedExtension = Limit((m_CurrentAnkleOffset.GetMagnitude() - m_MinExtension) / (m_MaxExtension - m_MinExtension), 1.0F, 0.0F); + m_Frame = std::min(m_FrameCount - 1, static_cast(std::floor(m_CurrentNormalizedExtension * static_cast(m_FrameCount)))); + } UpdateFootFrameAndRotation(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Leg::UpdateCurrentAnkleOffsetAndFootParentOffset() { + void Leg::UpdateCurrentAnkleOffset() { if (IsAttached()) { Vector targetOffset = g_SceneMan.ShortestDistance(m_JointPos, m_TargetPosition, g_SceneMan.SceneWrapsX()); if (m_WillIdle && targetOffset.m_Y < -3) { @@ -173,14 +186,6 @@ namespace RTE { m_CurrentAnkleOffset.SetXY(m_MaxExtension * 0.60F, 0); m_CurrentAnkleOffset.RadRotate((m_HFlipped ? c_PI : 0) + m_Rotation.GetRadAngle()); } - - if (m_Foot) { - // In order to keep the foot in the right place, we need to convert its offset (the ankle offstet) to work as the ParentOffset for the foot. - // The foot will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. - Vector ankleOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_CurrentAnkleOffset; - ankleOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); - m_Foot->SetParentOffset(ankleOffsetAsParentOffset); - } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -203,17 +208,6 @@ namespace RTE { } } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - void Leg::UpdateLegFrameAndNormalizedExtension() { - if (m_FrameCount == 1) { - m_Frame = 0; - } else { - m_CurrentNormalizedExtension = Limit((m_CurrentAnkleOffset.GetMagnitude() - m_MinExtension) / (m_MaxExtension - m_MinExtension), 1.0F, 0.0F); - m_Frame = std::min(m_FrameCount - 1, static_cast(std::floor(m_CurrentNormalizedExtension * static_cast(m_FrameCount)))); - } - } - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Leg::UpdateFootFrameAndRotation() { diff --git a/Entities/Leg.h b/Entities/Leg.h index 32ab8bf3e..6b6e9de84 100644 --- a/Entities/Leg.h +++ b/Entities/Leg.h @@ -125,10 +125,10 @@ namespace RTE { #pragma region Update Breakdown /// - /// Updates the current ankle offset for this Leg, and sets the foot's parent offset to match up with it. Should only be called from Update. + /// Updates the current ankle offset for this Leg. Should only be called from Update. /// If the Leg is attached, the current ankle offset is based on the target offset and move speed, and whether the Leg should idle or not, otherwise it puts it in a reasonable position. /// - void UpdateCurrentAnkleOffsetAndFootParentOffset(); + void UpdateCurrentAnkleOffset(); /// /// Updates the rotation of the Leg. Should only be called from Update. @@ -136,12 +136,6 @@ namespace RTE { /// void UpdateLegRotation(); - /// - /// Sets the Leg's frame to the appropriate one based on its current extension, and updates the normalized extension value. Should only be called from Update. - /// Works the same whether attached or not. - /// - void UpdateLegFrameAndNormalizedExtension(); - /// /// Updates the frame and rotation of the Leg's foot Attachable. Should only be called from Update. /// If the Leg is attached, the foot's rotation and frame depend on the ankle offset, otherwise the foot's rotation is set to be perpendicular to the Leg's rotation. From 5a067c30dafc0e9291589d157a610e966d3f6977 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 4 Nov 2020 23:16:57 -0400 Subject: [PATCH 090/144] Fixed emitters being way too strong. Turns out I was an absolute dumdum Fixed HDFirearms firing after being blasted out of your hands --- Entities/AEmitter.cpp | 2 +- Entities/HDFirearm.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index 0033f783d..d0aad73b8 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -134,7 +134,7 @@ int AEmitter::ReadProperty(std::string propName, Reader &reader) { float ppm; reader >> ppm; // Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility. - for (Emission *emission : m_EmissionList) { emission->m_PPM = ppm; } + for (Emission *emission : m_EmissionList) { emission->m_PPM = ppm / static_cast(m_EmissionList.size()); } } else if (propName == "MinThrottleRange") { reader >> m_MinThrottleRange; } else if (propName == "MaxThrottleRange") { diff --git a/Entities/HDFirearm.h b/Entities/HDFirearm.h index 14b72358d..de0f184d2 100644 --- a/Entities/HDFirearm.h +++ b/Entities/HDFirearm.h @@ -663,7 +663,7 @@ ClassInfoGetters /// Additionally, sets this Attachable as not reloading, and resets its reload timer. /// /// A pointer to the MOSRotating to set as the new parent. Ownership is NOT transferred! - void SetParent(MOSRotating *newParent) override { HeldDevice::SetParent(newParent); m_Reloading = false; m_ReloadTmr.Reset(); } + void SetParent(MOSRotating *newParent) override { HeldDevice::SetParent(newParent); Deactivate(); m_Reloading = false; m_ReloadTmr.Reset(); } // Member variables. static Entity::ClassInfo m_sClass; From dbb863597c740cc4ae25e5a849d438f6f2b59485 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 6 Nov 2020 23:23:01 -0400 Subject: [PATCH 091/144] Review Comment Changed hardcoded attachable setters to take in their most derived type (i.e. Leg, Arm, etc.) instead of Attachable where applicable. Casting is now done in the lambda instead of the main function, so the main function is inherently a little safer Changed formatting of all hardcoded attachable setters to be more consistent Cleaned up some comments in HDFirearm.h Changed lua bindings for Arm and Leg to concrete so they can be created, and added clone entries for them (and emission) --- Entities/ACDropShip.cpp | 90 +++++++++++++++----------- Entities/ACDropShip.h | 8 +-- Entities/ACRocket.cpp | 139 ++++++++++++++++++++++------------------ Entities/ACRocket.h | 28 ++++---- Entities/ACrab.cpp | 120 ++++++++++++++++++---------------- Entities/ACrab.h | 12 ++-- Entities/ADoor.cpp | 5 +- Entities/AEmitter.cpp | 5 +- Entities/AHuman.cpp | 105 +++++++++++++++++------------- Entities/AHuman.h | 20 +++--- Entities/Arm.cpp | 5 +- Entities/HDFirearm.cpp | 25 +++++--- Entities/HDFirearm.h | 8 +-- Entities/Leg.cpp | 5 +- Entities/Turret.cpp | 20 +++--- Entities/Turret.h | 2 +- Managers/LuaMan.cpp | 9 ++- 17 files changed, 341 insertions(+), 265 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 81e8b27b9..3e08279c7 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -73,19 +73,19 @@ int ACDropShip::Create() int ACDropShip::Create(const ACDropShip &reference) { if (reference.m_pRThruster) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRThruster->GetUniqueID()); - SetRightThruster(dynamic_cast(reference.m_pRThruster->Clone())); + SetRightThruster(dynamic_cast(reference.m_pRThruster->Clone())); } if (reference.m_pLThruster) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLThruster->GetUniqueID()); - SetLeftThruster(dynamic_cast(reference.m_pLThruster->Clone())); + SetLeftThruster(dynamic_cast(reference.m_pLThruster->Clone())); } if (reference.m_pURThruster) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pURThruster->GetUniqueID()); - SetURightThruster(dynamic_cast(reference.m_pURThruster->Clone())); + SetURightThruster(dynamic_cast(reference.m_pURThruster->Clone())); } if (reference.m_pULThruster) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pULThruster->GetUniqueID()); - SetULeftThruster(dynamic_cast(reference.m_pULThruster->Clone())); + SetULeftThruster(dynamic_cast(reference.m_pULThruster->Clone())); } if (reference.m_pRHatch) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRHatch->GetUniqueID()); @@ -776,69 +776,77 @@ void ACDropShip::Update() ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACDropShip::SetRightThruster(Attachable *newThruster) { +void ACDropShip::SetRightThruster(AEmitter *newThruster) { if (newThruster == nullptr) { if (m_pRThruster && m_pRThruster->IsAttached()) { RemoveAttachable(m_pRThruster); } m_pRThruster = nullptr; } else { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - if (m_pRThruster && m_pRThruster->IsAttached()) { RemoveAttachable(m_pRThruster); } - m_pRThruster = castedNewThruster; - AddAttachable(castedNewThruster); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightThruster(attachable); }}); - } + if (m_pRThruster && m_pRThruster->IsAttached()) { RemoveAttachable(m_pRThruster); } + m_pRThruster = newThruster; + AddAttachable(newThruster); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetRightThruster"); + dynamic_cast(parent)->SetRightThruster(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACDropShip::SetLeftThruster(Attachable *newThruster) { +void ACDropShip::SetLeftThruster(AEmitter *newThruster) { if (newThruster == nullptr) { if (m_pLThruster && m_pLThruster->IsAttached()) { RemoveAttachable(m_pLThruster); } m_pLThruster = nullptr; } else { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - if (m_pLThruster && m_pLThruster->IsAttached()) { RemoveAttachable(m_pLThruster); } - m_pLThruster = castedNewThruster; - AddAttachable(castedNewThruster); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftThruster(attachable); }}); - } + if (m_pLThruster && m_pLThruster->IsAttached()) { RemoveAttachable(m_pLThruster); } + m_pLThruster = newThruster; + AddAttachable(newThruster); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetLeftThruster"); + dynamic_cast(parent)->SetLeftThruster(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACDropShip::SetURightThruster(Attachable *newThruster) { +void ACDropShip::SetURightThruster(AEmitter *newThruster) { if (newThruster == nullptr) { if (m_pURThruster && m_pURThruster->IsAttached()) { RemoveAttachable(m_pURThruster); } m_pURThruster = nullptr; } else { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - if (m_pURThruster && m_pURThruster->IsAttached()) { RemoveAttachable(m_pURThruster); } - m_pURThruster = castedNewThruster; - AddAttachable(castedNewThruster); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetURightThruster(attachable); }}); - } + if (m_pURThruster && m_pURThruster->IsAttached()) { RemoveAttachable(m_pURThruster); } + m_pURThruster = newThruster; + AddAttachable(newThruster); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetURightThruster"); + dynamic_cast(parent)->SetURightThruster(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACDropShip::SetULeftThruster(Attachable *newThruster) { +void ACDropShip::SetULeftThruster(AEmitter *newThruster) { if (newThruster == nullptr) { if (m_pULThruster && m_pULThruster->IsAttached()) { RemoveAttachable(m_pULThruster); } m_pULThruster = nullptr; } else { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - if (m_pULThruster && m_pULThruster->IsAttached()) { RemoveAttachable(m_pULThruster); } - m_pULThruster = castedNewThruster; - AddAttachable(castedNewThruster); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetULeftThruster(attachable); }}); - } + if (m_pULThruster && m_pULThruster->IsAttached()) { RemoveAttachable(m_pULThruster); } + m_pULThruster = newThruster; + AddAttachable(newThruster); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetULeftThruster"); + dynamic_cast(parent)->SetULeftThruster(castedAttachable); + }}); } } @@ -852,7 +860,10 @@ void ACDropShip::SetRightHatch(Attachable *newHatch) { if (m_pRHatch && m_pRHatch->IsAttached()) { RemoveAttachable(m_pRHatch); } m_pRHatch = newHatch; AddAttachable(newHatch); - m_HardcodedAttachableUniqueIDsAndSetters.insert({newHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightHatch(attachable); }}); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + dynamic_cast(parent)->SetRightHatch(attachable); + }}); } } @@ -866,7 +877,10 @@ void ACDropShip::SetLeftHatch(Attachable *newHatch) { if (m_pLHatch && m_pLHatch->IsAttached()) { RemoveAttachable(m_pLHatch); } m_pLHatch = newHatch; AddAttachable(newHatch); - m_HardcodedAttachableUniqueIDsAndSetters.insert({newHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftHatch(attachable); }}); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newHatch->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + dynamic_cast(parent)->SetLeftHatch(attachable); + }}); } } diff --git a/Entities/ACDropShip.h b/Entities/ACDropShip.h index 3a1f6a567..53ce54055 100644 --- a/Entities/ACDropShip.h +++ b/Entities/ACDropShip.h @@ -186,7 +186,7 @@ ClassInfoGetters /// Sets the right side thruster for this ACDropship. /// /// The new thruster to use. - void SetRightThruster(Attachable *newThruster); + void SetRightThruster(AEmitter *newThruster); /// /// Gets the left side thruster of this ACDropship. @@ -198,7 +198,7 @@ ClassInfoGetters /// Sets the left side thruster for this ACDropship. /// /// The new thruster to use. - void SetLeftThruster(Attachable *newThruster); + void SetLeftThruster(AEmitter *newThruster); /// /// Gets the right side secondary thruster of this ACDropship. @@ -210,7 +210,7 @@ ClassInfoGetters /// Sets the right side secondary thruster for this ACDropship. /// /// The new thruster to use. - void SetURightThruster(Attachable *newThruster); + void SetURightThruster(AEmitter *newThruster); /// /// Gets the left side secondary thruster of this ACDropship. @@ -222,7 +222,7 @@ ClassInfoGetters /// Sets the left side secondary thruster for this ACDropship. /// /// The new thruster to use. - void SetULeftThruster(Attachable *newThruster); + void SetULeftThruster(AEmitter *newThruster); /// /// Gets the left side hatch of this ACDropship. diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 591623cb1..417587de0 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -94,31 +94,31 @@ int ACRocket::Create() int ACRocket::Create(const ACRocket &reference) { if (reference.m_pRLeg) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRLeg->GetUniqueID()); - SetRightLeg(dynamic_cast(reference.m_pRLeg->Clone())); + SetRightLeg(dynamic_cast(reference.m_pRLeg->Clone())); } if (reference.m_pLLeg) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLLeg->GetUniqueID()); - SetLeftLeg(dynamic_cast(reference.m_pLLeg->Clone())); + SetLeftLeg(dynamic_cast(reference.m_pLLeg->Clone())); } if (reference.m_pMThruster) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pMThruster->GetUniqueID()); - SetMainThruster(dynamic_cast(reference.m_pMThruster->Clone())); + SetMainThruster(dynamic_cast(reference.m_pMThruster->Clone())); } if (reference.m_pRThruster) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRThruster->GetUniqueID()); - SetRightThruster(dynamic_cast(reference.m_pRThruster->Clone())); + SetRightThruster(dynamic_cast(reference.m_pRThruster->Clone())); } if (reference.m_pLThruster) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLThruster->GetUniqueID()); - SetLeftThruster(dynamic_cast(reference.m_pLThruster->Clone())); + SetLeftThruster(dynamic_cast(reference.m_pLThruster->Clone())); } if (reference.m_pURThruster) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pURThruster->GetUniqueID()); - SetURightThruster(dynamic_cast(reference.m_pURThruster->Clone())); + SetURightThruster(dynamic_cast(reference.m_pURThruster->Clone())); } if (reference.m_pULThruster) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pULThruster->GetUniqueID()); - SetULeftThruster(dynamic_cast(reference.m_pULThruster->Clone())); + SetULeftThruster(dynamic_cast(reference.m_pULThruster->Clone())); } ACraft::Create(reference); @@ -843,120 +843,133 @@ void ACRocket::Update() ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACRocket::SetRightLeg(Attachable *newLeg) { +void ACRocket::SetRightLeg(Leg *newLeg) { if (newLeg == nullptr) { if (m_pRLeg && m_pRLeg->IsAttached()) { RemoveAttachable(m_pRLeg); } m_pRLeg = nullptr; } else { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - if (m_pRLeg && m_pRLeg->IsAttached()) { RemoveAttachable(m_pRLeg); } - m_pRLeg = castedNewLeg; - AddAttachable(castedNewLeg); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightLeg(attachable); }}); - } + if (m_pRLeg && m_pRLeg->IsAttached()) { RemoveAttachable(m_pRLeg); } + m_pRLeg = newLeg; + AddAttachable(newLeg); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Leg *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetRightLeg"); + dynamic_cast(parent)->SetRightLeg(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACRocket::SetLeftLeg(Attachable *newLeg) { +void ACRocket::SetLeftLeg(Leg *newLeg) { if (newLeg == nullptr) { if (m_pLLeg && m_pLLeg->IsAttached()) { RemoveAttachable(m_pLLeg); } m_pLLeg = nullptr; } else { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - if (m_pLLeg && m_pLLeg->IsAttached()) { RemoveAttachable(m_pLLeg); } - m_pLLeg = castedNewLeg; - AddAttachable(castedNewLeg); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftLeg(attachable); }}); - } + if (m_pLLeg && m_pLLeg->IsAttached()) { RemoveAttachable(m_pLLeg); } + m_pLLeg = newLeg; + AddAttachable(newLeg); + m_HardcodedAttachableUniqueIDsAndSetters.insert({newLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Leg *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetLeftLeg"); + dynamic_cast(parent)->SetLeftLeg(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACRocket::SetMainThruster(Attachable *newThruster) { +void ACRocket::SetMainThruster(AEmitter *newThruster) { if (newThruster == nullptr) { if (m_pMThruster && m_pMThruster->IsAttached()) { RemoveAttachable(m_pMThruster); } m_pMThruster = nullptr; } else { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - if (m_pMThruster && m_pMThruster->IsAttached()) { RemoveAttachable(m_pMThruster); } - m_pMThruster = castedNewThruster; - AddAttachable(castedNewThruster); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMainThruster(attachable); }}); - } + if (m_pMThruster && m_pMThruster->IsAttached()) { RemoveAttachable(m_pMThruster); } + m_pMThruster = newThruster; + AddAttachable(newThruster); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetMainThruster"); + dynamic_cast(parent)->SetMainThruster(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACRocket::SetRightThruster(Attachable *newThruster) { +void ACRocket::SetRightThruster(AEmitter *newThruster) { if (newThruster == nullptr) { if (m_pRThruster && m_pRThruster->IsAttached()) { RemoveAttachable(m_pRThruster); } m_pRThruster = nullptr; } else { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - if (m_pRThruster && m_pRThruster->IsAttached()) { RemoveAttachable(m_pRThruster); } - m_pRThruster = castedNewThruster; - AddAttachable(castedNewThruster); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightThruster(attachable); }}); - } + if (m_pRThruster && m_pRThruster->IsAttached()) { RemoveAttachable(m_pRThruster); } + m_pRThruster = newThruster; + AddAttachable(newThruster); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetRightThruster"); + dynamic_cast(parent)->SetRightThruster(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACRocket::SetLeftThruster(Attachable *newThruster) { +void ACRocket::SetLeftThruster(AEmitter *newThruster) { if (newThruster == nullptr) { if (m_pLThruster && m_pLThruster->IsAttached()) { RemoveAttachable(m_pLThruster); } m_pLThruster = nullptr; } else { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - if (m_pLThruster && m_pLThruster->IsAttached()) { RemoveAttachable(m_pLThruster); } - m_pLThruster = castedNewThruster; - AddAttachable(castedNewThruster); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftThruster(attachable); }}); - } + if (m_pLThruster && m_pLThruster->IsAttached()) { RemoveAttachable(m_pLThruster); } + m_pLThruster = newThruster; + AddAttachable(newThruster); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetLeftThruster"); + dynamic_cast(parent)->SetLeftThruster(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACRocket::SetURightThruster(Attachable *newThruster) { +void ACRocket::SetURightThruster(AEmitter *newThruster) { if (newThruster == nullptr) { if (m_pURThruster && m_pURThruster->IsAttached()) { RemoveAttachable(m_pURThruster); } m_pURThruster = nullptr; } else { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - if (m_pURThruster && m_pURThruster->IsAttached()) { RemoveAttachable(m_pURThruster); } - m_pURThruster = castedNewThruster; - AddAttachable(castedNewThruster); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetURightThruster(attachable); }}); - } + if (m_pURThruster && m_pURThruster->IsAttached()) { RemoveAttachable(m_pURThruster); } + m_pURThruster = newThruster; + AddAttachable(newThruster); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetURightThruster"); + dynamic_cast(parent)->SetURightThruster(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACRocket::SetULeftThruster(Attachable *newThruster) { +void ACRocket::SetULeftThruster(AEmitter *newThruster) { if (newThruster == nullptr) { if (m_pULThruster && m_pULThruster->IsAttached()) { RemoveAttachable(m_pULThruster); } m_pULThruster = nullptr; } else { - AEmitter *castedNewThruster = dynamic_cast(newThruster); - if (castedNewThruster) { - if (m_pULThruster && m_pULThruster->IsAttached()) { RemoveAttachable(m_pULThruster); } - m_pULThruster = castedNewThruster; - AddAttachable(castedNewThruster); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetULeftThruster(attachable); }}); - } + if (m_pULThruster && m_pULThruster->IsAttached()) { RemoveAttachable(m_pULThruster); } + m_pULThruster = newThruster; + AddAttachable(newThruster); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newThruster->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetULeftThruster"); + dynamic_cast(parent)->SetULeftThruster(castedAttachable); + }}); } } diff --git a/Entities/ACRocket.h b/Entities/ACRocket.h index a03b4fe83..f9b330026 100644 --- a/Entities/ACRocket.h +++ b/Entities/ACRocket.h @@ -200,26 +200,26 @@ ClassInfoGetters /// /// Gets the right leg of this ACRocket. /// - /// A pointer to the right leg of this ACRocket. Ownership is NOT transferred. + /// A pointer to the right Leg of this ACRocket. Ownership is NOT transferred. Leg * GetRightLeg() const { return m_pRLeg; } /// - /// Sets the right leg for this ACRocket. + /// Sets the right Leg for this ACRocket. /// - /// The new leg to use. - void SetRightLeg(Attachable *newLeg); + /// The new Leg to use. + void SetRightLeg(Leg *newLeg); /// - /// Gets the left leg of this ACRocket. + /// Gets the left Leg of this ACRocket. /// - /// A pointer to the left leg of this ACRocket. Ownership is NOT transferred. + /// A pointer to the left Leg of this ACRocket. Ownership is NOT transferred. Leg * GetLeftLeg() const { return m_pLLeg; } /// - /// Sets the left leg for this ACRocket. + /// Sets the left Leg for this ACRocket. /// - /// The new leg to use. - void SetLeftLeg(Attachable *newLeg); + /// The new Leg to use. + void SetLeftLeg(Leg *newLeg); /// /// Gets the main thruster of this ACRocket. @@ -231,7 +231,7 @@ ClassInfoGetters /// Sets the main thruster for this ACRocket. /// /// The new thruster to use. - void SetMainThruster(Attachable *newThruster); + void SetMainThruster(AEmitter *newThruster); /// /// Gets the right side thruster of this ACRocket. @@ -243,7 +243,7 @@ ClassInfoGetters /// Sets the right side thruster for this ACRocket. /// /// The new thruster to use. - void SetRightThruster(Attachable *newThruster); + void SetRightThruster(AEmitter *newThruster); /// /// Gets the left side thruster of this ACRocket. @@ -255,7 +255,7 @@ ClassInfoGetters /// Sets the left side thruster for this ACRocket. /// /// The new thruster to use. - void SetLeftThruster(Attachable *newThruster); + void SetLeftThruster(AEmitter *newThruster); /// /// Gets the right side secondary thruster of this ACRocket. @@ -267,7 +267,7 @@ ClassInfoGetters /// Sets the right side secondary thruster for this ACRocket. /// /// The new thruster to use. - void SetURightThruster(Attachable *newThruster); + void SetURightThruster(AEmitter *newThruster); /// /// Gets the left side secondary thruster of this ACRocket. @@ -279,7 +279,7 @@ ClassInfoGetters /// Sets the left side secondary thruster for this ACRocket. /// /// The new thruster to use. - void SetULeftThruster(Attachable *newThruster); + void SetULeftThruster(AEmitter *newThruster); ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 31f1d66ce..c1b805c45 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -165,27 +165,27 @@ int ACrab::Create(const ACrab &reference) { //Note - hardcoded attachable copying is organized based on desired draw order here. if (reference.m_pLBGLeg) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLBGLeg->GetUniqueID()); - SetLeftBGLeg(dynamic_cast(reference.m_pLBGLeg->Clone())); + SetLeftBGLeg(dynamic_cast(reference.m_pLBGLeg->Clone())); } if (reference.m_pRBGLeg) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRBGLeg->GetUniqueID()); - SetRightBGLeg(dynamic_cast(reference.m_pRBGLeg->Clone())); + SetRightBGLeg(dynamic_cast(reference.m_pRBGLeg->Clone())); } if (reference.m_pJetpack) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pJetpack->GetUniqueID()); - SetJetpack(dynamic_cast(reference.m_pJetpack->Clone())); + SetJetpack(dynamic_cast(reference.m_pJetpack->Clone())); } if (reference.m_pTurret) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pTurret->GetUniqueID()); - SetTurret(dynamic_cast(reference.m_pTurret->Clone())); + SetTurret(dynamic_cast(reference.m_pTurret->Clone())); } if (reference.m_pLFGLeg) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pLFGLeg->GetUniqueID()); - SetLeftFGLeg(dynamic_cast(reference.m_pLFGLeg->Clone())); + SetLeftFGLeg(dynamic_cast(reference.m_pLFGLeg->Clone())); } if (reference.m_pRFGLeg) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pRFGLeg->GetUniqueID()); - SetRightFGLeg(dynamic_cast(reference.m_pRFGLeg->Clone())); + SetRightFGLeg(dynamic_cast(reference.m_pRFGLeg->Clone())); } Actor::Create(reference); @@ -491,103 +491,115 @@ Vector ACrab::GetEyePos() const ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACrab::SetTurret(Attachable *newTurret) { +void ACrab::SetTurret(Turret *newTurret) { if (newTurret == nullptr) { if (m_pTurret && m_pTurret->IsAttached()) { RemoveAttachable(m_pTurret); } m_pTurret = nullptr; } else { - Turret *castedNewTurret = dynamic_cast(newTurret); - if (castedNewTurret) { - if (m_pTurret && m_pTurret->IsAttached()) { RemoveAttachable(m_pTurret); } - m_pTurret = castedNewTurret; - AddAttachable(castedNewTurret); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewTurret->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetTurret(attachable); }}); - } + if (m_pTurret && m_pTurret->IsAttached()) { RemoveAttachable(m_pTurret); } + m_pTurret = newTurret; + AddAttachable(newTurret); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newTurret->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Turret *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetTurret"); + dynamic_cast(parent)->SetTurret(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACrab::SetJetpack(Attachable *newJetpack) { +void ACrab::SetJetpack(AEmitter *newJetpack) { if (newJetpack == nullptr) { if (m_pJetpack && m_pJetpack->IsAttached()) { RemoveAttachable(m_pJetpack); } m_pJetpack = nullptr; } else { - AEmitter *castedNewJetpack = dynamic_cast(newJetpack); - if (castedNewJetpack) { - if (m_pJetpack && m_pJetpack->IsAttached()) { RemoveAttachable(m_pJetpack); } - m_pJetpack = castedNewJetpack; - AddAttachable(castedNewJetpack); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetJetpack(attachable); }}); - } + if (m_pJetpack && m_pJetpack->IsAttached()) { RemoveAttachable(m_pJetpack); } + m_pJetpack = newJetpack; + AddAttachable(newJetpack); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetJetpack"); + dynamic_cast(parent)->SetJetpack(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACrab::SetLeftFGLeg(Attachable *newLeg) { +void ACrab::SetLeftFGLeg(Leg *newLeg) { if (newLeg == nullptr) { if (m_pLFGLeg && m_pLFGLeg->IsAttached()) { RemoveAttachable(m_pLFGLeg); } m_pLFGLeg = nullptr; } else { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - if (m_pLFGLeg && m_pLFGLeg->IsAttached()) { RemoveAttachable(m_pLFGLeg); } - m_pLFGLeg = castedNewLeg; - AddAttachable(castedNewLeg); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftFGLeg(attachable); }}); - } + if (m_pLFGLeg && m_pLFGLeg->IsAttached()) { RemoveAttachable(m_pLFGLeg); } + m_pLFGLeg = newLeg; + AddAttachable(newLeg); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Leg *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetLeftFGLeg"); + dynamic_cast(parent)->SetLeftFGLeg(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACrab::SetLeftBGLeg(Attachable *newLeg) { +void ACrab::SetLeftBGLeg(Leg *newLeg) { if (newLeg == nullptr) { if (m_pLBGLeg && m_pLBGLeg->IsAttached()) { RemoveAttachable(m_pLBGLeg); } m_pLBGLeg = nullptr; } else { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - if (m_pLBGLeg && m_pLBGLeg->IsAttached()) { RemoveAttachable(m_pLBGLeg); } - m_pLBGLeg = castedNewLeg; - AddAttachable(castedNewLeg); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetLeftBGLeg(attachable); }}); - } + if (m_pLBGLeg && m_pLBGLeg->IsAttached()) { RemoveAttachable(m_pLBGLeg); } + m_pLBGLeg = newLeg; + AddAttachable(newLeg); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Leg *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetLeftBGLeg"); + dynamic_cast(parent)->SetLeftBGLeg(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACrab::SetRightFGLeg(Attachable *newLeg) { +void ACrab::SetRightFGLeg(Leg *newLeg) { if (newLeg == nullptr) { if (m_pRFGLeg && m_pRFGLeg->IsAttached()) { RemoveAttachable(m_pRFGLeg); } m_pRFGLeg = nullptr; } else { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - if (m_pRFGLeg && m_pRFGLeg->IsAttached()) { RemoveAttachable(m_pRFGLeg); } - m_pRFGLeg = castedNewLeg; - AddAttachable(castedNewLeg); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightFGLeg(attachable); }}); - } + if (m_pRFGLeg && m_pRFGLeg->IsAttached()) { RemoveAttachable(m_pRFGLeg); } + m_pRFGLeg = newLeg; + AddAttachable(newLeg); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Leg *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetRightFGLeg"); + dynamic_cast(parent)->SetRightFGLeg(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void ACrab::SetRightBGLeg(Attachable *newLeg) { +void ACrab::SetRightBGLeg(Leg *newLeg) { if (newLeg == nullptr) { if (m_pRBGLeg && m_pRBGLeg->IsAttached()) { RemoveAttachable(m_pRBGLeg); } m_pRBGLeg = nullptr; } else { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - if (m_pRBGLeg && m_pRBGLeg->IsAttached()) { RemoveAttachable(m_pRBGLeg); } - m_pRBGLeg = castedNewLeg; - AddAttachable(castedNewLeg); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetRightBGLeg(attachable); }}); - } + if (m_pRBGLeg && m_pRBGLeg->IsAttached()) { RemoveAttachable(m_pRBGLeg); } + m_pRBGLeg = newLeg; + AddAttachable(newLeg); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Leg *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetRightBGLeg"); + dynamic_cast(parent)->SetRightBGLeg(castedAttachable); + }}); } } diff --git a/Entities/ACrab.h b/Entities/ACrab.h index c2df526ef..0ae53503b 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -164,7 +164,7 @@ class ACrab : /// Sets the Turret for this ACrab. Ownership IS transferred! /// /// The new Turret to use. - void SetTurret(Attachable *newTurret); + void SetTurret(Turret *newTurret); /// /// Gets the jetpack of this ACrab. @@ -176,7 +176,7 @@ class ACrab : /// Sets the jetpack for this ACrab. Ownership IS Transferred! /// /// The new jetpack to use. - void SetJetpack(Attachable *newJetpack); + void SetJetpack(AEmitter *newJetpack); /// /// Gets the left foreground Leg of this ACrab. @@ -188,7 +188,7 @@ class ACrab : /// Sets the left foreground Leg for this ACrab. Ownership IS transferred! /// /// The new Leg to use. - void SetLeftFGLeg(Attachable *newLeg); + void SetLeftFGLeg(Leg *newLeg); /// /// Gets the left background Leg of this ACrab. @@ -200,7 +200,7 @@ class ACrab : /// Sets the left background Leg for this ACrab. Ownership IS transferred! /// /// The new Leg to use. - void SetLeftBGLeg(Attachable *newLeg); + void SetLeftBGLeg(Leg *newLeg); /// /// Gets the right foreground Leg of this ACrab. @@ -212,7 +212,7 @@ class ACrab : /// Sets the right foreground Leg for this ACrab. Ownership IS transferred! /// /// The new Leg to use. - void SetRightFGLeg(Attachable *newLeg); + void SetRightFGLeg(Leg *newLeg); /// /// Gets the right BG Leg of this ACrab. @@ -224,7 +224,7 @@ class ACrab : /// Sets the right background Leg for this ACrab. Ownership IS transferred! /// /// The new Leg to use. - void SetRightBGLeg(Attachable *newLeg); + void SetRightBGLeg(Leg *newLeg); ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/ADoor.cpp b/Entities/ADoor.cpp index 6609efccc..16460b240 100644 --- a/Entities/ADoor.cpp +++ b/Entities/ADoor.cpp @@ -211,7 +211,10 @@ namespace RTE { if (m_Door && m_Door->IsAttached()) { RemoveAttachable(m_Door); } m_Door = newDoor; AddAttachable(newDoor); - m_HardcodedAttachableUniqueIDsAndSetters.insert({newDoor->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetDoor(attachable); }}); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newDoor->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + dynamic_cast(parent)->SetDoor(attachable); + }}); } } diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index d0aad73b8..934ac06d4 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -376,7 +376,10 @@ void AEmitter::SetFlash(Attachable *newFlash) { if (m_pFlash && m_pFlash->IsAttached()) { RemoveAttachable(m_pFlash); } m_pFlash = newFlash; AddAttachable(newFlash); - m_HardcodedAttachableUniqueIDsAndSetters.insert({newFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFlash(attachable); }}); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + dynamic_cast(parent)->SetFlash(attachable); + }}); } } diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 98c220d32..2fb18ba6f 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -147,15 +147,15 @@ int AHuman::Create(const AHuman &reference) { //Note - hardcoded attachable copying is organized based on desired draw order here. if (reference.m_pBGArm) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pBGArm->GetUniqueID()); - SetBGArm(dynamic_cast(reference.m_pBGArm->Clone())); + SetBGArm(dynamic_cast(reference.m_pBGArm->Clone())); } if (reference.m_pBGLeg) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pBGLeg->GetUniqueID()); - SetBGLeg(dynamic_cast(reference.m_pBGLeg->Clone())); + SetBGLeg(dynamic_cast(reference.m_pBGLeg->Clone())); } if (reference.m_pJetpack) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pJetpack->GetUniqueID()); - SetJetpack(dynamic_cast(reference.m_pJetpack->Clone())); + SetJetpack(dynamic_cast(reference.m_pJetpack->Clone())); } if (reference.m_pHead) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pHead->GetUniqueID()); @@ -163,11 +163,11 @@ int AHuman::Create(const AHuman &reference) { } if (reference.m_pFGLeg) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pFGLeg->GetUniqueID()); - SetFGLeg(dynamic_cast(reference.m_pFGLeg->Clone())); + SetFGLeg(dynamic_cast(reference.m_pFGLeg->Clone())); } if (reference.m_pFGArm) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pFGArm->GetUniqueID()); - SetFGArm(dynamic_cast(reference.m_pFGArm->Clone())); + SetFGArm(dynamic_cast(reference.m_pFGArm->Clone())); } Actor::Create(reference); @@ -487,92 +487,105 @@ void AHuman::SetHead(Attachable *newHead) { if (m_pHead && m_pHead->IsAttached()) { RemoveAttachable(m_pHead); } m_pHead = newHead; AddAttachable(newHead); - m_HardcodedAttachableUniqueIDsAndSetters.insert({newHead->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetHead(attachable); }}); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newHead->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + dynamic_cast(parent)->SetHead(attachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AHuman::SetJetpack(Attachable *newJetpack) { +void AHuman::SetJetpack(AEmitter *newJetpack) { if (newJetpack == nullptr) { if (m_pJetpack && m_pJetpack->IsAttached()) { RemoveAttachable(m_pJetpack); } m_pJetpack = nullptr; } else { - AEmitter *castedNewJetpack = dynamic_cast(newJetpack); - if (castedNewJetpack) { - if (m_pJetpack && m_pJetpack->IsAttached()) { RemoveAttachable(m_pJetpack); } - m_pJetpack = castedNewJetpack; - AddAttachable(castedNewJetpack); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetJetpack(attachable); }}); - } + if (m_pJetpack && m_pJetpack->IsAttached()) { RemoveAttachable(m_pJetpack); } + m_pJetpack = newJetpack; + AddAttachable(newJetpack); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newJetpack->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + AEmitter *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetJetpack"); + dynamic_cast(parent)->SetJetpack(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AHuman::SetFGArm(Attachable *newArm) { +void AHuman::SetFGArm(Arm *newArm) { if (newArm == nullptr) { if (m_pFGArm && m_pFGArm->IsAttached()) { RemoveAttachable(m_pFGArm); } m_pFGArm = nullptr; } else { - Arm *castedNewArm = dynamic_cast(newArm); - if (castedNewArm) { - if (m_pFGArm && m_pFGArm->IsAttached()) { RemoveAttachable(m_pFGArm); } - m_pFGArm = castedNewArm; - AddAttachable(castedNewArm); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFGArm(attachable); }}); - } + if (m_pFGArm && m_pFGArm->IsAttached()) { RemoveAttachable(m_pFGArm); } + m_pFGArm = newArm; + AddAttachable(newArm); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Arm *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetJetpack"); + dynamic_cast(parent)->SetFGArm(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AHuman::SetBGArm(Attachable *newArm) { +void AHuman::SetBGArm(Arm *newArm) { if (newArm == nullptr) { if (m_pBGArm && m_pBGArm->IsAttached()) { RemoveAttachable(m_pBGArm); } m_pBGArm = nullptr; } else { - Arm *castedNewArm = dynamic_cast(newArm); - if (castedNewArm) { - if (m_pBGArm && m_pBGArm->IsAttached()) { RemoveAttachable(m_pBGArm); } - m_pBGArm = castedNewArm; - AddAttachable(castedNewArm); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetBGArm(attachable); }}); - } + if (m_pBGArm && m_pBGArm->IsAttached()) { RemoveAttachable(m_pBGArm); } + m_pBGArm = newArm; + AddAttachable(newArm); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Arm *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetBGArm"); + dynamic_cast(parent)->SetBGArm(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AHuman::SetFGLeg(Attachable *newLeg) { +void AHuman::SetFGLeg(Leg *newLeg) { if (newLeg == nullptr) { if (m_pFGLeg && m_pFGLeg->IsAttached()) { RemoveAttachable(m_pFGLeg); } m_pFGLeg = nullptr; } else { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - if (m_pFGLeg && m_pFGLeg->IsAttached()) { RemoveAttachable(m_pFGLeg); } - m_pFGLeg = castedNewLeg; - AddAttachable(castedNewLeg); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFGLeg(attachable); }}); - } + if (m_pFGLeg && m_pFGLeg->IsAttached()) { RemoveAttachable(m_pFGLeg); } + m_pFGLeg = newLeg; + AddAttachable(newLeg); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Leg *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetFGLeg"); + dynamic_cast(parent)->SetFGLeg(castedAttachable); + }}); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void AHuman::SetBGLeg(Attachable *newLeg) { +void AHuman::SetBGLeg(Leg *newLeg) { if (newLeg == nullptr) { if (m_pBGLeg && m_pBGLeg->IsAttached()) { RemoveAttachable(m_pBGLeg); } m_pBGLeg = nullptr; } else { - Leg *castedNewLeg = dynamic_cast(newLeg); - if (castedNewLeg) { - if (m_pBGLeg && m_pBGLeg->IsAttached()) { RemoveAttachable(m_pBGLeg); } - m_pBGLeg = castedNewLeg; - AddAttachable(castedNewLeg); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetBGLeg(attachable); }}); - } + if (m_pBGLeg && m_pBGLeg->IsAttached()) { RemoveAttachable(m_pBGLeg); } + m_pBGLeg = newLeg; + AddAttachable(newLeg); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newLeg->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Leg *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetBGLeg"); + dynamic_cast(parent)->SetBGLeg(castedAttachable); + }}); } } diff --git a/Entities/AHuman.h b/Entities/AHuman.h index d0f47db5a..8b68658b8 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -251,56 +251,56 @@ ClassInfoGetters /// /// Sets the jetpack for this AHuman. /// - /// The new jetpack to use. - void SetJetpack(Attachable *newJetpack); + /// The new jetpack to use. + void SetJetpack(AEmitter *newJetpack); /// /// Gets the foreground Arm of this AHuman. /// /// A pointer to the foreground Arm of this AHuman. Ownership is NOT transferred. - Attachable * GetFGArm() const { return static_cast(m_pFGArm); } + Arm * GetFGArm() const { return m_pFGArm; } /// /// Sets the foreground Arm for this AHuman. /// /// The new Arm to use. - void SetFGArm(Attachable *newArm); + void SetFGArm(Arm *newArm); /// /// Gets the background arm of this AHuman. /// /// A pointer to the background arm of this AHuman. Ownership is NOT transferred. - Attachable * GetBGArm() const { return static_cast(m_pBGArm); } + Arm * GetBGArm() const { return m_pBGArm; } /// /// Sets the background Arm for this AHuman. /// /// The new Arm to use. - void SetBGArm(Attachable *newArm); + void SetBGArm(Arm *newArm); /// /// Gets the foreground Leg of this AHuman. /// /// A pointer to the foreground Leg of this AHuman. Ownership is NOT transferred. - Attachable * GetFGLeg() const { return static_cast(m_pFGLeg); } + Leg * GetFGLeg() const { return m_pFGLeg; } /// /// Sets the foreground Leg for this AHuman. /// /// The new Leg to use. - void SetFGLeg(Attachable *newLeg); + void SetFGLeg(Leg *newLeg); /// /// Gets the background Leg of this AHuman. /// /// A pointer to the background Leg of this AHuman. Ownership is NOT transferred. - Attachable * GetBGLeg() const { return static_cast(m_pBGLeg); } + Leg * GetBGLeg() const { return m_pBGLeg; } /// /// Sets the background Leg for this AHuman. /// /// The new Leg to use. - void SetBGLeg(Attachable *newLeg); + void SetBGLeg(Leg *newLeg); /// /// Gets the foot Attachable of this AHuman's foreground Leg. diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index f3a3b7901..f97811618 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -215,7 +215,10 @@ void Arm::SetHeldMO(MovableObject *newHeldMO) { Attachable *newHeldDevice = dynamic_cast(newHeldMO); if (newHeldDevice->IsAttached()) { dynamic_cast(newHeldDevice->GetParent())->RemoveAttachable(newHeldDevice); } AddAttachable(newHeldDevice); - m_HardcodedAttachableUniqueIDsAndSetters.insert({newHeldDevice->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetHeldMO(attachable); }}); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newHeldDevice->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + dynamic_cast(parent)->SetHeldMO(attachable); + }}); } m_pHeldMO = newHeldMO; } diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index d41096152..b88d9f706 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -97,7 +97,7 @@ int HDFirearm::Create() int HDFirearm::Create(const HDFirearm &reference) { if (reference.m_pMagazine) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pMagazine->GetUniqueID()); - SetMagazine(dynamic_cast(reference.m_pMagazine->Clone())); + SetMagazine(dynamic_cast(reference.m_pMagazine->Clone())); } if (reference.m_pFlash) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_pFlash->GetUniqueID()); @@ -302,18 +302,20 @@ void HDFirearm::Destroy(bool notInherited) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void HDFirearm::SetMagazine(Attachable *newMagazine) { +void HDFirearm::SetMagazine(Magazine *newMagazine) { if (newMagazine == nullptr) { if (m_pMagazine && m_pMagazine->IsAttached()) { RemoveAttachable(m_pMagazine); } m_pMagazine = nullptr; } else { - Magazine *castedNewMagazine = dynamic_cast(newMagazine); - if (castedNewMagazine) { - if (m_pMagazine && m_pMagazine->IsAttached()) { RemoveAttachable(m_pMagazine); } - m_pMagazine = castedNewMagazine; - AddAttachable(castedNewMagazine); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewMagazine->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMagazine(attachable); }}); - } + if (m_pMagazine && m_pMagazine->IsAttached()) { RemoveAttachable(m_pMagazine); } + m_pMagazine = newMagazine; + AddAttachable(newMagazine); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newMagazine->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + Magazine *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetMagazine"); + dynamic_cast(parent)->SetMagazine(castedAttachable); + }}); } } @@ -327,7 +329,10 @@ void HDFirearm::SetFlash(Attachable *newFlash) { if (m_pFlash && m_pFlash->IsAttached()) { RemoveAttachable(m_pFlash); } m_pFlash = newFlash; AddAttachable(newFlash); - m_HardcodedAttachableUniqueIDsAndSetters.insert({newFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFlash(attachable); }}); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newFlash->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + dynamic_cast(parent)->SetFlash(attachable); + }}); } } diff --git a/Entities/HDFirearm.h b/Entities/HDFirearm.h index de0f184d2..15d536ce6 100644 --- a/Entities/HDFirearm.h +++ b/Entities/HDFirearm.h @@ -140,8 +140,8 @@ ClassInfoGetters /// /// Sets the Magazine for this HDFirearm. Ownership IS transferred! /// - /// The new Magazine to use. - void SetMagazine(Attachable *newMagazine); + /// The new Magazine to use. + void SetMagazine(Magazine *newMagazine); /// /// Gets the flash of this HDFirearm. @@ -659,8 +659,8 @@ ClassInfoGetters protected: /// - /// Sets this HDFirearm's parent MOSRotating, and also sets its Team based on its parent and, if the Attachable is set to collide, adds/removes Atoms to its new/old parent. - /// Additionally, sets this Attachable as not reloading, and resets its reload timer. + /// Sets this Attachable's parent MOSRotating, and also sets its Team based on its parent and, if the Attachable is set to collide, adds/removes Atoms to its new/old parent. + /// Additionally, sets this HDFirearm as not firing or reloading, and resets its reload timer. /// /// A pointer to the MOSRotating to set as the new parent. Ownership is NOT transferred! void SetParent(MOSRotating *newParent) override { HeldDevice::SetParent(newParent); Deactivate(); m_Reloading = false; m_ReloadTmr.Reset(); } diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index 826f8ac5f..58a51588d 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -139,7 +139,10 @@ namespace RTE { if (m_Foot && m_Foot->IsAttached()) { RemoveAttachable(m_Foot); } m_Foot = newFoot; AddAttachable(newFoot); - m_HardcodedAttachableUniqueIDsAndSetters.insert({newFoot->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetFoot(attachable); }}); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newFoot->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + dynamic_cast(parent)->SetFoot(attachable); + }}); } } diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index c6c2450d0..2a6005622 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -17,7 +17,7 @@ namespace RTE { int Turret::Create(const Turret &reference) { if (reference.m_MountedDevice) { m_ReferenceHardcodedAttachableUniqueIDs.insert(reference.m_MountedDevice->GetUniqueID()); - SetMountedDevice(dynamic_cast(reference.m_MountedDevice->Clone())); + SetMountedDevice(dynamic_cast(reference.m_MountedDevice->Clone())); } Attachable::Create(reference); @@ -60,18 +60,20 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - void Turret::SetMountedDevice(Attachable *newMountedDevice) { + void Turret::SetMountedDevice(HeldDevice *newMountedDevice) { if (newMountedDevice == nullptr) { if (m_MountedDevice && m_MountedDevice->IsAttached()) { RemoveAttachable(m_MountedDevice); } m_MountedDevice = nullptr; } else { - HeldDevice *castedNewMountedDevice = dynamic_cast(newMountedDevice); - if (castedNewMountedDevice) { - if (m_MountedDevice && m_MountedDevice->IsAttached()) { RemoveAttachable(m_MountedDevice); } - m_MountedDevice = castedNewMountedDevice; - AddAttachable(castedNewMountedDevice); - m_HardcodedAttachableUniqueIDsAndSetters.insert({castedNewMountedDevice->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { dynamic_cast(parent)->SetMountedDevice(attachable); }}); - } + if (m_MountedDevice && m_MountedDevice->IsAttached()) { RemoveAttachable(m_MountedDevice); } + m_MountedDevice = newMountedDevice; + AddAttachable(newMountedDevice); + + m_HardcodedAttachableUniqueIDsAndSetters.insert({newMountedDevice->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { + HeldDevice *castedAttachable = dynamic_cast(attachable); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetMountedDevice"); + dynamic_cast(parent)->SetMountedDevice(castedAttachable); + }}); } } diff --git a/Entities/Turret.h b/Entities/Turret.h index c86c15ccc..ae857ee5d 100644 --- a/Entities/Turret.h +++ b/Entities/Turret.h @@ -68,7 +68,7 @@ namespace RTE { /// The currently mounted HeldDevice (if there is one) will be dropped and added to MovableMan. /// /// The new HeldDevice to use. - void SetMountedDevice(Attachable *newMountedDevice); + void SetMountedDevice(HeldDevice *newMountedDevice); /// /// Indicates whether a ThrownDevice is mounted or not. diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 39def9b47..5cfb95579 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -188,6 +188,8 @@ struct enum_wrapper { // These are expanded by the preprocessor to all the different cloning function definitions. LUAENTITYCREATE(Attachable) +LUAENTITYCREATE(Arm) +LUAENTITYCREATE(Leg) LUAENTITYCREATE(AEmitter) LUAENTITYCREATE(Turret) LUAENTITYCREATE(Actor) @@ -233,6 +235,9 @@ LUAENTITYCLONE(Entity) LUAENTITYCLONE(SceneObject) LUAENTITYCLONE(MovableObject) LUAENTITYCLONE(Attachable) +LUAENTITYCLONE(Arm) +LUAENTITYCLONE(Leg) +LUAENTITYCLONE(Emission) LUAENTITYCLONE(AEmitter) LUAENTITYCLONE(Turret) LUAENTITYCLONE(Actor) @@ -1032,13 +1037,13 @@ int LuaMan::Create() { .def("StopDoor", &ADoor::StopDoor) .def("SetClosedByDefault", &ADoor::SetClosedByDefault), - ABSTRACTLUABINDING(Arm, Attachable) + CONCRETELUABINDING(Arm, Attachable) .property("HeldDevice", &Arm::GetHeldMO) .property("IdleOffset", &Arm::GetIdleOffset, &Arm::SetIdleOffset) .property("GripStrength", &Arm::GetGripStrength, &Arm::SetGripStrength) .property("HandPos", &Arm::GetHandPos, &Arm::SetHandPos), - ABSTRACTLUABINDING(Leg, Attachable) + CONCRETELUABINDING(Leg, Attachable) .property("Foot", &Leg::GetFoot, &Leg::SetFoot, detail::null_type(), adopt(_2)), CONCRETELUABINDING(AHuman, Actor) From f6d125967988491a87dc13f940b0e543babd3d75 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 6 Nov 2020 23:24:30 -0400 Subject: [PATCH 092/144] Review comments - replaced INI NoActorsCanPickThisUp with adding an actor entry of none, None or NONE --- CHANGELOG.md | 3 +-- Entities/HeldDevice.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9171bccf..8d4917b10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -179,8 +179,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), PickupableBy = PickupableByEntries AddActorEntry = First Actor PresetName Here AddActorEntry = Second Actor PresetName Here - // Alternatively, you can set it to never be pickupable with - NoActorsCanPickThisUp = 1 + AddActorEntry = None //This sets it to never be pickupable ``` The Lua properties and functions are as follows: ``` diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index 51e1fccdd..6b4298100 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -181,7 +181,12 @@ int HeldDevice::ReadProperty(std::string propName, Reader &reader) while (reader.NextProperty()) { std::string pickupableByEntryType = reader.ReadPropName(); if (pickupableByEntryType == "AddActorEntry") { - m_ActorsWhoCanPickThisUp.insert(reader.ReadPropValue()); + std::string actorEntryValue = reader.ReadPropValue(); + if (actorEntryValue == "none" || actorEntryValue == "None" || actorEntryValue == "NONE") { + m_ActorsWhoCanPickThisUp.insert(c_NoPickupString); + } else { + m_ActorsWhoCanPickThisUp.insert(actorEntryValue); + } } else if (pickupableByEntryType == "AddGroupEntry ") { reader.ReportError("AddGroupEntry is not yet supported."); } else if (pickupableByEntryType == "AddDataModuleEntry ") { @@ -193,10 +198,6 @@ int HeldDevice::ReadProperty(std::string propName, Reader &reader) } else { m_ActorsWhoCanPickThisUp.insert(pickupableByValue); } - } else if (propName == "NoActorsCanPickThisUp") { - bool noActorsCanPickThisUp; - reader >> noActorsCanPickThisUp; - SetNoActorsCanPickThisUp(noActorsCanPickThisUp); } else if (propName == "GripStrengthMultiplier") { reader >> m_GripStrengthMultiplier; } else if (propName == "SharpLength") From 503b5e8574e830f93caa40ddd4f52cb2df07b44a Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 6 Nov 2020 23:25:31 -0400 Subject: [PATCH 093/144] Changed variable name (and comments) for TransferJointImpulses in Attachable and HeldDevice --- Entities/Attachable.cpp | 20 ++++++++++---------- Entities/Attachable.h | 8 ++++---- Entities/HeldDevice.cpp | 8 ++++---- Entities/HeldDevice.h | 16 ++++++++-------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 05a386f44..dacca3a91 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -188,32 +188,32 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - bool Attachable::TransferJointImpulses(Vector &jointImpulses, float jointStiffnessOverride, float jointStrengthOverride, float gibImpulseLimitOverride) { + bool Attachable::TransferJointImpulses(Vector &jointImpulses, float jointStiffnessValueToUse, float jointStrengthValueToUse, float gibImpulseLimitValueToUse) { if (!m_Parent) { return false; } if (m_ImpulseForces.empty()) { return true; } - jointStiffnessOverride = jointStiffnessOverride > 0 ? jointStiffnessOverride : m_JointStiffness; - jointStrengthOverride = jointStrengthOverride > 0 ? jointStrengthOverride : m_JointStrength; - gibImpulseLimitOverride = gibImpulseLimitOverride > 0 ? gibImpulseLimitOverride : m_GibImpulseLimit; + jointStiffnessValueToUse = jointStiffnessValueToUse > 0 ? jointStiffnessValueToUse : m_JointStiffness; + jointStrengthValueToUse = jointStrengthValueToUse > 0 ? jointStrengthValueToUse : m_JointStrength; + gibImpulseLimitValueToUse = gibImpulseLimitValueToUse > 0 ? gibImpulseLimitValueToUse : m_GibImpulseLimit; Vector totalImpulseForce; for (const std::pair &impulseForce : m_ImpulseForces) { totalImpulseForce += impulseForce.first; } - if (gibImpulseLimitOverride > 0 && totalImpulseForce.GetMagnitude() > gibImpulseLimitOverride) { - jointImpulses += (totalImpulseForce.SetMagnitude(gibImpulseLimitOverride)) * jointStiffnessOverride; + if (gibImpulseLimitValueToUse > 0 && totalImpulseForce.GetMagnitude() > gibImpulseLimitValueToUse) { + jointImpulses += (totalImpulseForce.SetMagnitude(gibImpulseLimitValueToUse)) * jointStiffnessValueToUse; GibThis(); return false; - } else if (jointStrengthOverride > 0 && totalImpulseForce.GetMagnitude() > jointStrengthOverride) { - jointImpulses += (totalImpulseForce.SetMagnitude(jointStrengthOverride)) * jointStiffnessOverride; + } else if (jointStrengthValueToUse > 0 && totalImpulseForce.GetMagnitude() > jointStrengthValueToUse) { + jointImpulses += (totalImpulseForce.SetMagnitude(jointStrengthValueToUse)) * jointStiffnessValueToUse; m_Parent->RemoveAttachable(this, true, true); return false; } else { - jointImpulses += totalImpulseForce * jointStiffnessOverride; + jointImpulses += totalImpulseForce * jointStiffnessValueToUse; } // Rough explanation of what this is doing: @@ -222,7 +222,7 @@ namespace RTE { if (!m_InheritsRotAngle) { for (const std::pair &impulseForce : m_ImpulseForces) { if (!impulseForce.second.IsZero()) { - m_AngularVel += (impulseForce.second.GetPerpendicular().Dot(impulseForce.first) / m_pAtomGroup->GetMomentOfInertia()) * (1.0F - jointStiffnessOverride); + m_AngularVel += (impulseForce.second.GetPerpendicular().Dot(impulseForce.first) / m_pAtomGroup->GetMomentOfInertia()) * (1.0F - jointStiffnessValueToUse); } } } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 777466b37..25ccb3526 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -241,11 +241,11 @@ namespace RTE { /// Additionally, in this case, the Attachable will remove itself from its parent and gib itself if appropriate. /// /// A vector that will have the impulse forces affecting the joint ADDED to it. - /// An optional override for the Attachable's joint stiffness for this function call. Primarily used to allow subclasses to perform special behaviour. - /// An optional override for the Attachable's joint strength for this function call. Primarily used to allow subclasses to perform special behaviour. - /// An optional override for the Attachable's gib impulse limit for this function call. Primarily used to allow subclasses to perform special behaviour. + /// An optional override for the Attachable's joint stiffness for this function call. Primarily used to allow subclasses to perform special behaviour. + /// An optional override for the Attachable's joint strength for this function call. Primarily used to allow subclasses to perform special behaviour. + /// An optional override for the Attachable's gib impulse limit for this function call. Primarily used to allow subclasses to perform special behaviour. /// False if the Attachable has no parent or its accumulated forces are greater than its joint strength or gib impulse limit, otherwise true. - virtual bool TransferJointImpulses(Vector &jointImpulses, float jointStiffnessOverride = -1, float jointStrengthOverride = -1, float gibImpulseLimitOverride = -1); + virtual bool TransferJointImpulses(Vector &jointImpulses, float jointStiffnessValueToUse = -1, float jointStrengthValueToUse = -1, float gibImpulseLimitValueToUse = -1); #pragma endregion #pragma region Damage and Wound Management diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index 6b4298100..d56de8f7c 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -403,7 +403,7 @@ bool HeldDevice::OnMOHit(MovableObject *pOtherMO) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool HeldDevice::TransferJointImpulses(Vector &jointImpulses, float jointStiffnessOverride, float jointStrengthOverride, float gibImpulseLimitOverride) { +bool HeldDevice::TransferJointImpulses(Vector &jointImpulses, float jointStiffnessValueToUse, float jointStrengthValueToUse, float gibImpulseLimitValueToUse) { MovableObject *parent = m_Parent; if (!parent) { return false; @@ -412,10 +412,10 @@ bool HeldDevice::TransferJointImpulses(Vector &jointImpulses, float jointStiffne return true; } const Arm *parentAsArm = dynamic_cast(parent); - if (parentAsArm && parentAsArm->GetGripStrength() > 0 && jointStrengthOverride < 0) { - jointStrengthOverride = parentAsArm->GetGripStrength() * m_GripStrengthMultiplier; + if (parentAsArm && parentAsArm->GetGripStrength() > 0 && jointStrengthValueToUse < 0) { + jointStrengthValueToUse = parentAsArm->GetGripStrength() * m_GripStrengthMultiplier; } - bool intact = Attachable::TransferJointImpulses(jointImpulses, jointStiffnessOverride, jointStrengthOverride, gibImpulseLimitOverride); + bool intact = Attachable::TransferJointImpulses(jointImpulses, jointStiffnessValueToUse, jointStrengthValueToUse, gibImpulseLimitValueToUse); if (!intact) { Actor *rootParentAsActor = dynamic_cast(parent->GetRootParent()); if (rootParentAsActor && rootParentAsActor->GetStatus() == Actor::STABLE) { diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index 48d6cb19e..9b442b2fd 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -581,16 +581,16 @@ ClassInfoGetters #pragma region Force Transferral /// - /// Bundles up all the accumulated impulse forces of this Attachable and calculates how they transfer to the joint, and therefore to the parent. - /// If the accumulated impulse forces exceed the joint strength or gib impulse limit of this Attachable, the jointImpulses Vector will be filled up to that limit and false will be returned. - /// Additionally, in this case, the Attachable will remove itself from its parent and gib itself if appropriate. + /// Bundles up all the accumulated impulse forces of this HeldDevice and calculates how they transfer to the joint, and therefore to the parent. + /// If the accumulated impulse forces exceed the joint strength or gib impulse limit of this HeldDevice, the jointImpulses Vector will be filled up to that limit and false will be returned. + /// Additionally, in this case, the HeldDevice will remove itself from its parent, destabilizing said parent if it's an Actor, and gib itself if appropriate. /// /// A vector that will have the impulse forces affecting the joint ADDED to it. - /// An optional override for the Attachable's joint stiffness for this function call. Primarily used to allow subclasses to perform special behavior. - /// An optional override for the Attachable's joint strength for this function call. Primarily used to allow subclasses to perform special behavior. - /// An optional override for the Attachable's gib impulse limit for this function call. Primarily used to allow subclasses to perform special behavior. - /// False if the Attachable has no parent or its accumulated forces are greater than its joint strength or gib impulse limit, otherwise true. - bool TransferJointImpulses(Vector &jointImpulses, float jointStiffnessOverride = -1, float jointStrengthOverride = -1, float gibImpulseLimitOverride = -1) override; + /// An optional override for the HeldDevice's joint stiffness for this function call. Primarily used to allow subclasses to perform special behavior. + /// An optional override for the HeldDevice's joint strength for this function call. Primarily used to allow subclasses to perform special behavior. + /// An optional override for the HeldDevice's gib impulse limit for this function call. Primarily used to allow subclasses to perform special behavior. + /// False if the HeldDevice has no parent or its accumulated forces are greater than its joint strength or gib impulse limit, otherwise true. + bool TransferJointImpulses(Vector &jointImpulses, float jointStiffnessValueToUse = -1, float jointStrengthValueToUse = -1, float gibImpulseLimitValueToUse = -1) override; #pragma endregion From 310a57bad46ab9940fa1bf732a3e747bafdd5142 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 12 Nov 2020 23:38:02 -0400 Subject: [PATCH 094/144] Fixed a couple screwups with gib generation (thanks 4zK) One where I had a + instead of a * and one where I handled velocities for gibs with no offset incorrectly --- Entities/MOSRotating.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 181e8b00d..149b5254d 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1002,7 +1002,8 @@ void MOSRotating::CreateGibsWhenGibbing(const Vector &impactImpulse, MovableObje } gibParticleClone->SetPos(m_Pos + rotatedGibOffset); - Vector gibVelocity = rotatedGibOffset.SetMagnitude(minVelocity + RandomNum(0.0F, velocityRange)).RadRotate(impactImpulse.GetAbsRadAngle() + gibSettingsObject.GetSpread() + RandomNormalNum()); + Vector gibVelocity = rotatedGibOffset.IsZero() ? Vector(minVelocity + RandomNum(0.0F, velocityRange), 0.0F) : rotatedGibOffset.SetMagnitude(minVelocity + RandomNum(0.0F, velocityRange)); + gibVelocity.RadRotate(impactImpulse.GetAbsRadAngle() + (gibSettingsObject.GetSpread() * RandomNormalNum())); gibParticleClone->SetVel(gibVelocity + (gibSettingsObject.InheritsVelocity() ? m_Vel : Vector())); if (movableObjectToIgnore) { gibParticleClone->SetWhichMOToNotHit(movableObjectToIgnore); } From 248d770dc1d4aee18f2c03f0caaabd4d8912e371 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 13 Nov 2020 02:29:11 -0400 Subject: [PATCH 095/144] PR Review Comments and Discussion Changed AddMO to AddItem in AHuman Onelined stuff in Arm Fixed missing float (and long) specifiers and onelined stuff in Attachable.cpp Fixed typos and screwups in Attachable.h Renamed CurrentNormalizedExtension and CurrentAnkleOffset to not have Current, fixed typos, onelined things in Leg.cpp and Leg.h. Also changed a use of Limit to std::clamp in Leg.cpp Tweaked some comments in MOSR.h --- Entities/AHuman.cpp | 4 +- Entities/Arm.cpp | 8 +-- Entities/Attachable.cpp | 30 +++++------- Entities/Attachable.h | 105 +++++++++++++++++++++++++++++++--------- Entities/Leg.cpp | 40 +++++++-------- Entities/Leg.h | 4 +- Entities/MOSRotating.h | 4 +- 7 files changed, 119 insertions(+), 76 deletions(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 2fb18ba6f..1c174b045 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -3480,7 +3480,7 @@ void AHuman::Update() // Set the grenade or whatever to ignore hits with same team pMO->SetTeam(m_Team); pMO->SetIgnoresTeamHits(true); - g_MovableMan.AddMO(pMO); + g_MovableMan.AddItem(pMO); } else { if (pMO->IsGold()) { m_GoldInInventoryChunk = 0; @@ -3537,7 +3537,7 @@ void AHuman::Update() pMO->SetVel(tossVec.GetXFlipped(m_HFlipped) * m_Rotation); pMO->SetAngularVel(5.0F * RandomNormalNum()); if (pMO->IsDevice()) { - g_MovableMan.AddMO(pMO); + g_MovableMan.AddItem(pMO); } else { if (pMO->IsGold()) { m_GoldInInventoryChunk = 0; diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index f97811618..41d83a7d0 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -525,12 +525,8 @@ void Arm::Update() { void Arm::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { Attachable::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); if (m_pHeldMO || (!m_pHeldMO && !m_DidReach) || !m_Parent) { - if (!onlyPhysical && (mode == g_DrawColor || mode == g_DrawWhite || mode == g_DrawTrans)) { - DrawHand(pTargetBitmap, targetPos, mode); - } - if (m_pHeldMO && m_pHeldMO->IsDrawnAfterParent()) { - m_pHeldMO->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - } + if (!onlyPhysical && (mode == g_DrawColor || mode == g_DrawWhite || mode == g_DrawTrans)) { DrawHand(pTargetBitmap, targetPos, mode); } + if (m_pHeldMO && m_pHeldMO->IsDrawnAfterParent()) { m_pHeldMO->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } } } diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index dacca3a91..3424a231f 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -12,30 +12,30 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Attachable::Clear() { - m_Parent = 0; + m_Parent = nullptr; m_ParentOffset.Reset(); m_DrawAfterParent = true; m_DrawnNormallyByParent = true; m_DeleteWhenRemovedFromParent = false; m_ApplyTransferredForcesAtOffset = true; - m_GibWithParentChance = 0; + m_GibWithParentChance = 0.0F; m_ParentGibBlastStrengthMultiplier = 1; - m_JointStrength = 10; - m_JointStiffness = 1.0; + m_JointStrength = 10.0F; + m_JointStiffness = 1.0F; m_JointOffset.Reset(); m_JointPos.Reset(); - m_DamageCount = 0; - m_BreakWound = 0; - m_ParentBreakWound = 0; + m_DamageCount = 0.0F; + m_BreakWound = nullptr; + m_ParentBreakWound = nullptr; m_InheritsHFlipped = 1; m_InheritsRotAngle = true; - m_InheritedRotAngleOffset = 0; + m_InheritedRotAngleOffset = 0.0F; - m_AtomSubgroupID = -1; + m_AtomSubgroupID = -1L; m_CollidesWithTerrainWhileAttached = true; } @@ -263,14 +263,10 @@ namespace RTE { bool Attachable::ParticlePenetration(HitData &hd) { bool penetrated = MOSRotating::ParticlePenetration(hd); - if (hd.Body[HITOR]->DamageOnCollision() != 0) { - AddDamage(hd.Body[HITOR]->DamageOnCollision()); - } + if (hd.Body[HITOR]->DamageOnCollision() != 0) { AddDamage(hd.Body[HITOR]->DamageOnCollision()); } if (penetrated && m_Parent) { - if (hd.Body[HITOR]->DamageOnPenetration() != 0) { - AddDamage(hd.Body[HITOR]->DamageOnPenetration()); - } + if (hd.Body[HITOR]->DamageOnPenetration() != 0) { AddDamage(hd.Body[HITOR]->DamageOnPenetration()); } // If the parent is an actor, generate an alarm point for them, moving it slightly away from the body (in the direction they got hit from) to get a good reaction. Actor *parentAsActor = dynamic_cast(GetRootParent()); @@ -420,9 +416,7 @@ namespace RTE { void Attachable::CalculateAtomOffsetForSubgroup(Vector &atomOffsetForSubgroup) const { if (m_Parent) { const Attachable *parentAsAttachable = dynamic_cast(m_Parent); - if (parentAsAttachable) { - parentAsAttachable->CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); - } + if (parentAsAttachable) { parentAsAttachable->CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); } atomOffsetForSubgroup += GetParentOffset() - GetJointOffset(); } } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 25ccb3526..c23ab75fd 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -115,7 +115,7 @@ namespace RTE { bool IsDrawnAfterParent() const override { return m_DrawAfterParent; } /// - /// Sets whether this Attachabe is to be drawn after (in front of) or before (behind) its parent. + /// Sets whether this Attachable is to be drawn after (in front of) or before (behind) its parent. /// /// Whether this Attachable is to be drawn after its parent. void SetDrawnAfterParent(bool drawAfterParent) { m_DrawAfterParent = drawAfterParent; } @@ -179,7 +179,7 @@ namespace RTE { float GetParentGibBlastStrengthMultiplier() const { return m_ParentGibBlastStrengthMultiplier; } /// - /// Sets the multiplier this Attacahble will apply to its parent's gib blast strength when the parent gibs. + /// Sets the multiplier this Attachable will apply to its parent's gib blast strength when the parent gibs. /// /// A float describing the gib blast strength multiplier of this Attachable. void SetParentGibBlastStrengthMultiplier(float parentGibBlastStrengthMultiplier) { m_ParentGibBlastStrengthMultiplier = parentGibBlastStrengthMultiplier; } @@ -216,7 +216,7 @@ namespace RTE { /// Gets the offset of the joint (the point around which this Attachable and its parent hinge) from this Attachable's center of mass/origin. /// /// A const reference Vector describing the offset of the joint relative to this Attachable's origin/center of mass position. - const Vector &GetJointOffset() const { return m_JointOffset; } + const Vector & GetJointOffset() const { return m_JointOffset; } /// /// Sets the offset of the joint (the point around which this Attachable and its parent hinge) from this Attachable's center of mass/origin. @@ -241,9 +241,9 @@ namespace RTE { /// Additionally, in this case, the Attachable will remove itself from its parent and gib itself if appropriate. /// /// A vector that will have the impulse forces affecting the joint ADDED to it. - /// An optional override for the Attachable's joint stiffness for this function call. Primarily used to allow subclasses to perform special behaviour. - /// An optional override for the Attachable's joint strength for this function call. Primarily used to allow subclasses to perform special behaviour. - /// An optional override for the Attachable's gib impulse limit for this function call. Primarily used to allow subclasses to perform special behaviour. + /// An optional override for the Attachable's joint stiffness for this function call. Primarily used to allow subclasses to perform special behavior. + /// An optional override for the Attachable's joint strength for this function call. Primarily used to allow subclasses to perform special behavior. + /// An optional override for the Attachable's gib impulse limit for this function call. Primarily used to allow subclasses to perform special behavior. /// False if the Attachable has no parent or its accumulated forces are greater than its joint strength or gib impulse limit, otherwise true. virtual bool TransferJointImpulses(Vector &jointImpulses, float jointStiffnessValueToUse = -1, float jointStrengthValueToUse = -1, float gibImpulseLimitValueToUse = -1); #pragma endregion @@ -318,7 +318,7 @@ namespace RTE { /// Gets the offset of this Attachable's rotation angle from its parent. Only actually applied if the Attachable is set to inherit its parent's rotation angle. /// /// This Attachable's inherited rotation angle offset. - bool GetInheritedRotAngleOffset() const { return m_InheritedRotAngleOffset; } + float GetInheritedRotAngleOffset() const { return m_InheritedRotAngleOffset; } /// /// Sets the offset of this Attachable's rotation angle from its parent. Only actually applied if the Attachable is set to inherit its parent's rotation angle. @@ -332,13 +332,13 @@ namespace RTE { /// Gets the subgroup ID of this' Atoms. /// /// The subgroup ID of this' Atoms. - long int GetAtomSubgroupID() const { return m_AtomSubgroupID; } + long GetAtomSubgroupID() const { return m_AtomSubgroupID; } /// /// Sets the subgroup ID of this' Atoms /// - /// A long int describing the new subgroup id of this' Atoms. - void SetAtomSubgroupID(long int subgroupID = 0) { m_AtomSubgroupID = subgroupID; } + /// A long describing the new subgroup id of this' Atoms. + void SetAtomSubgroupID(long subgroupID = 0) { m_AtomSubgroupID = subgroupID; } /// /// Whether this attachable currently has terrain collisions enabled and it's atoms are present in the parent AtomGroup. @@ -380,51 +380,102 @@ namespace RTE { #pragma endregion #pragma region Override Methods for Handling Mass - /* - NOTE: Method comments are left blank here so Doxygen will treat them as inherited. Unfortunately there's no way to make VS do this for C++ (inheritdoc tag doesn't work). - */ + /// + /// Sets the mass of this Attachable. + /// + /// A float specifying the new mass value in Kilograms (kg). void SetMass(const float newMass) final; + /// + /// Adds the passed in Attachable the list of Attachables and sets its parent to this Attachable. + /// + /// The Attachable to add. void AddAttachable(Attachable *attachable) final { MOSRotating::AddAttachable(attachable); } + /// + /// Adds the passed in Attachable the list of Attachables, changes its parent offset to the passed in Vector, and sets its parent to this Attachable. + /// + /// The Attachable to add. + /// The Vector to set as the Attachable's parent offset. void AddAttachable(Attachable *attachable, const Vector &parentOffsetToSet) final; + /// + /// Removes the Attachable corresponding to the passed in UniqueID and sets its parent to nullptr. Does not add it to MovableMan or add break wounds. + /// + /// The UniqueID of the Attachable to remove. + /// False if the Attachable is invalid, otherwise true. bool RemoveAttachable(long attachableUniqueID) final { return MOSRotating::RemoveAttachable(attachableUniqueID); } + /// + /// Removes the Attachable corresponding to the passed in UniqueID and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. + /// If the Attachable is not set to delete or delete when removed from its parent, and addToMovableMan is false, the caller must hang onto a pointer to the Attachable ahead of time to avoid memory leaks. + /// + /// The UniqueID of the Attachable to remove. + /// Whether or not to add the Attachable to MovableMan once it has been removed. + /// Whether or not to add break wounds to the removed Attachable and this Attachable. + /// False if the Attachable is invalid, otherwise true. bool RemoveAttachable(long attachableUniqueID, bool addToMovableMan, bool addBreakWounds) final { return MOSRotating::RemoveAttachable(attachableUniqueID, addToMovableMan, addBreakWounds); } + /// + /// Removes the passed in Attachable and sets its parent to nullptr. Does not add it to MovableMan or add break wounds. + /// + /// The Attachable to remove. + /// False if the Attachable is invalid, otherwise true. bool RemoveAttachable(Attachable *attachable) final { return MOSRotating::RemoveAttachable(attachable); } + /// + /// Removes the passed in Attachable and sets its parent to nullptr. Optionally adds it to MovableMan and/or adds break wounds. + /// If the Attachable is not set to delete or delete when removed from its parent, and addToMovableMan is false, the caller must hang onto a pointer to the Attachable ahead of time to avoid memory leaks. + /// + /// The Attachable to remove. + /// Whether or not to add the Attachable to MovableMan once it has been removed. + /// Whether or not to add break wounds to the removed Attachable and this Attachable. + /// False if the Attachable is invalid, otherwise true. bool RemoveAttachable(Attachable *attachable, bool addToMovableMan, bool addBreakWounds) final; + /// + /// Adds the passed in wound AEmitter to the list of wounds and changes its parent offset to the passed in Vector. + /// + /// The wound AEmitter to add. + /// The vector to set as the wound AEmitter's parent offset. + /// Whether to gib this Attachable if adding this wound raises its wound count past its gib wound limit. Defaults to true. void AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet, bool checkGibWoundLimit = true) final; + /// + /// Removes the specified number of wounds from this Attachable, and returns damage caused by these removed wounds. + /// Includes any Attachables (and their Attachables, etc.) that have a positive damage multiplier. + /// + /// The number of wounds that should be removed. + /// The amount of damage caused by these wounds, taking damage multipliers into account. float RemoveWounds(int numberOfWoundsToRemove) final { return MOSRotating::RemoveWounds(numberOfWoundsToRemove); } + /// + /// Removes the specified number of wounds from this Attachable, and returns damage caused by these removed wounds. + /// Optionally removes wounds from Attachables (and their Attachables, etc.) that match the conditions set by the provided inclusion parameters. + /// + /// The number of wounds that should be removed. + /// Whether to count wounds from Attachables that have a positive damage multiplier, i.e. those that damage their parent (this Attachable) when wounded. + /// Whether to count wounds from Attachables that have a negative damage multiplier, i.e. those that heal their parent (this Attachable) when wounded. + /// Whether to count wounds from Attachables that a zero damage multiplier, i.e. those that do not affect their parent (this Attachable) when wounded. + /// The amount of damage caused by these wounds, taking damage multipliers into account. float RemoveWounds(int numberOfWoundsToRemove, bool includeAttachablesWithAPositiveDamageMultiplier, bool includeAttachablesWithANegativeDamageMultiplier, bool includeAttachablesWithNoDamageMultiplier) override; #pragma endregion protected: - /// - /// Sets this Attachable's parent MOSRotating, and also sets its Team based on its parent and, if the Attachable is set to collide, adds/removes Atoms to its new/old parent. - /// - /// A pointer to the MOSRotating to set as the new parent. Ownership is NOT transferred! - virtual void SetParent(MOSRotating *newParent); - static Entity::ClassInfo m_sClass; //!< ClassInfo for this class. MOSRotating *m_Parent; //!< Pointer to the MOSRotating this attachable is attached to. Vector m_ParentOffset; //!< The offset from the parent's Pos to the joint point this Attachable is attached with. bool m_DrawAfterParent; //!< Whether to draw this Attachable after (in front of) or before (behind) the parent. - bool m_DrawnNormallyByParent; //!< Whether this Attachable will be be drawn normally when attached, or will require special handling by some non-MOSR parent type. + bool m_DrawnNormallyByParent; //!< Whether this Attachable will be drawn normally when attached, or will require special handling by some non-MOSR parent type. bool m_DeleteWhenRemovedFromParent; //!< Whether this Attachable should be deleted when it's removed from its parent. bool m_ApplyTransferredForcesAtOffset; //!< Whether forces transferred from this Attachable should be applied at the rotated parent offset (which will produce torque), or directly at the parent's position. Mostly useful to make jetpacks and similar emitters viable. float m_GibWithParentChance; //!< The percentage chance that this Attachable will gib when its parent does. 0 means never, 1 means always. - float m_ParentGibBlastStrengthMultiplier; //!< The multiplier this Attacahble will apply to its parent's gib blast strength when the parent gibs. + float m_ParentGibBlastStrengthMultiplier; //!< The multiplier this Attachable will apply to its parent's gib blast strength when the parent gibs. - float m_JointStrength; //!< The amount of impulse force needed on this to deatch it from the host Actor, in kg * m/s. A value of 0 means the join is infinitely strong and will never break naturally. + float m_JointStrength; //!< The amount of impulse force needed on this to detach it from the host Actor, in kg * m/s. A value of 0 means the join is infinitely strong and will never break naturally. float m_JointStiffness; //!< The normalized joint stiffness scalar. 1.0 means impulse forces on this attachable will be transferred to the parent with 100% strength, 0 means they will not transfer at all. Vector m_JointOffset; //!< The offset to the joint (the point around which this Attachable and its parent hinge) from its center of mass/origin. Vector m_JointPos; //!< The absolute position of the joint that the parent sets upon Update() if this Attachable is attached to it. @@ -433,13 +484,19 @@ namespace RTE { const AEmitter *m_BreakWound; //!< The wound this Attachable will receive when it breaks from its parent. const AEmitter *m_ParentBreakWound; //!< The wound this Attachable's parent will receive when the Attachable breaks from its parent. - int m_InheritsHFlipped; //!< Whether this Attachable should inherit its parent's HFlipped. Defaults to true. + int m_InheritsHFlipped; //!< Whether this Attachable should inherit its parent's HFlipped. Defaults to 1 (normal inheritance). bool m_InheritsRotAngle; //!< Whether this Attachable should inherit its parent's RotAngle. Defaults to true. float m_InheritedRotAngleOffset; //!< The offset by which this Attachable should be rotated when it's set to inherit its parent's rotation angle. Defaults to 0. - long int m_AtomSubgroupID; //!< The Atom IDs this' atoms will have when attached and added to a parent's AtomGroup. + long m_AtomSubgroupID; //!< The Atom IDs this' atoms will have when attached and added to a parent's AtomGroup. bool m_CollidesWithTerrainWhileAttached; //!< Whether this attachable currently has terrain collisions enabled while it's attached to a parent. + /// + /// Sets this Attachable's parent MOSRotating, and also sets its Team based on its parent and, if the Attachable is set to collide, adds/removes Atoms to its new/old parent. + /// + /// A pointer to the MOSRotating to set as the new parent. Ownership is NOT transferred! + virtual void SetParent(MOSRotating *newParent); + private: /// diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index 58a51588d..425f64e3d 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -15,12 +15,12 @@ namespace RTE { m_MinExtension = 0; m_MaxExtension = 0; - m_CurrentNormalizedExtension = 0; + m_NormalizedExtension = 0; m_TargetPosition.Reset(); m_IdleOffset.Reset(); - m_CurrentAnkleOffset.Reset(); + m_AnkleOffset.Reset(); m_WillIdle = false; m_MoveSpeed = 0; @@ -39,9 +39,7 @@ namespace RTE { // Ensure Legs don't collide with terrain when attached since their expansion/contraction is frame based so atom group doesn't know how to account for it. SetCollidesWithTerrainWhileAttached(false); - if (m_ContractedOffset.GetMagnitude() > m_ExtendedOffset.GetMagnitude()) { - std::swap(m_ContractedOffset, m_ExtendedOffset); - } + if (m_ContractedOffset.GetMagnitude() > m_ExtendedOffset.GetMagnitude()) { std::swap(m_ContractedOffset, m_ExtendedOffset); } m_MinExtension = m_ContractedOffset.GetMagnitude(); m_MaxExtension = m_ExtendedOffset.GetMagnitude(); @@ -63,12 +61,12 @@ namespace RTE { m_MinExtension = reference.m_MinExtension; m_MaxExtension = reference.m_MaxExtension; - m_CurrentNormalizedExtension = reference.m_CurrentNormalizedExtension; + m_NormalizedExtension = reference.m_NormalizedExtension; m_TargetPosition = reference.m_TargetPosition; m_IdleOffset = reference.m_IdleOffset; - m_CurrentAnkleOffset = reference.m_CurrentAnkleOffset; + m_AnkleOffset = reference.m_AnkleOffset; m_WillIdle = reference.m_WillIdle; m_MoveSpeed = reference.m_MoveSpeed; @@ -152,9 +150,9 @@ namespace RTE { UpdateCurrentAnkleOffset(); if (m_Foot) { - // In order to keep the foot in the right place, we need to convert its offset (the ankle offstet) to work as the ParentOffset for the foot. + // In order to keep the foot in the right place, we need to convert its offset (the ankle offset) to work as the ParentOffset for the foot. // The foot will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. - Vector ankleOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_CurrentAnkleOffset; + Vector ankleOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_AnkleOffset; ankleOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); m_Foot->SetParentOffset(ankleOffsetAsParentOffset); } @@ -166,8 +164,8 @@ namespace RTE { if (m_FrameCount == 1) { m_Frame = 0; } else { - m_CurrentNormalizedExtension = Limit((m_CurrentAnkleOffset.GetMagnitude() - m_MinExtension) / (m_MaxExtension - m_MinExtension), 1.0F, 0.0F); - m_Frame = std::min(m_FrameCount - 1, static_cast(std::floor(m_CurrentNormalizedExtension * static_cast(m_FrameCount)))); + m_NormalizedExtension = std::clamp((m_AnkleOffset.GetMagnitude() - m_MinExtension) / (m_MaxExtension - m_MinExtension), 0.0F, 1.0F); + m_Frame = std::min(m_FrameCount - 1, static_cast(std::floor(m_NormalizedExtension * static_cast(m_FrameCount)))); } UpdateFootFrameAndRotation(); @@ -178,16 +176,14 @@ namespace RTE { void Leg::UpdateCurrentAnkleOffset() { if (IsAttached()) { Vector targetOffset = g_SceneMan.ShortestDistance(m_JointPos, m_TargetPosition, g_SceneMan.SceneWrapsX()); - if (m_WillIdle && targetOffset.m_Y < -3) { - targetOffset = m_IdleOffset.GetXFlipped(m_HFlipped); - } + if (m_WillIdle && targetOffset.m_Y < -3) { targetOffset = m_IdleOffset.GetXFlipped(m_HFlipped); } - Vector distanceFromTargetOffsetToAnkleOffset(targetOffset - m_CurrentAnkleOffset); - m_CurrentAnkleOffset += distanceFromTargetOffsetToAnkleOffset * m_MoveSpeed; - m_CurrentAnkleOffset.ClampMagnitude(m_MaxExtension, m_MinExtension + 0.1F); + Vector distanceFromTargetOffsetToAnkleOffset(targetOffset - m_AnkleOffset); + m_AnkleOffset += distanceFromTargetOffsetToAnkleOffset * m_MoveSpeed; + m_AnkleOffset.ClampMagnitude(m_MaxExtension, m_MinExtension + 0.1F); } else { - m_CurrentAnkleOffset.SetXY(m_MaxExtension * 0.60F, 0); - m_CurrentAnkleOffset.RadRotate((m_HFlipped ? c_PI : 0) + m_Rotation.GetRadAngle()); + m_AnkleOffset.SetXY(m_MaxExtension * 0.60F, 0); + m_AnkleOffset.RadRotate((m_HFlipped ? c_PI : 0) + m_Rotation.GetRadAngle()); } } @@ -195,10 +191,10 @@ namespace RTE { void Leg::UpdateLegRotation() { if (IsAttached()) { - m_Rotation = m_CurrentAnkleOffset.GetAbsRadAngle() + (m_HFlipped ? c_PI : 0); + m_Rotation = m_AnkleOffset.GetAbsRadAngle() + (m_HFlipped ? c_PI : 0); // Get a normalized scalar for where the Leg should be rotated to between the contracted and extended offsets. EaseOut is used to get the sine effect needed. - float extraRotationRatio = (EaseOut(m_MinExtension, m_MaxExtension, m_CurrentNormalizedExtension) - m_MinExtension) / (m_MaxExtension - m_MinExtension); + float extraRotationRatio = (EaseOut(m_MinExtension, m_MaxExtension, m_NormalizedExtension) - m_MinExtension) / (m_MaxExtension - m_MinExtension); // The contracted offset's inverse angle is the base for the rotation correction. float extraRotation = -(m_ContractedOffset.GetAbsRadAngle()); @@ -216,7 +212,7 @@ namespace RTE { void Leg::UpdateFootFrameAndRotation() { if (m_Foot) { if (IsAttached()) { - float ankleOffsetHorizontalDistanceAccountingForFlipping = m_CurrentAnkleOffset.GetXFlipped(m_HFlipped).GetX(); + float ankleOffsetHorizontalDistanceAccountingForFlipping = m_AnkleOffset.GetXFlipped(m_HFlipped).GetX(); if (ankleOffsetHorizontalDistanceAccountingForFlipping < -10) { m_Foot->SetFrame(3); } else if (ankleOffsetHorizontalDistanceAccountingForFlipping < -6) { diff --git a/Entities/Leg.h b/Entities/Leg.h index 6b6e9de84..dcdb50343 100644 --- a/Entities/Leg.h +++ b/Entities/Leg.h @@ -111,12 +111,12 @@ namespace RTE { float m_MinExtension; //!< Precalculated min extension of the Leg (from the joint) based on the contracted offset. float m_MaxExtension; //!< Precalculated max extension of the Leg (from the joint) based on the extended offset. - float m_CurrentNormalizedExtension; //!< Normalized scalar of where the ankle offset's magnitude is between the min and max extensions. + float m_NormalizedExtension; //!< Normalized scalar of where the ankle offset's magnitude is between the min and max extensions. Vector m_TargetPosition; //!< The absolute position that this Leg's foot is moving towards. Vector m_IdleOffset; //!< The target offset from m_Pos that this Leg's foot is moving towards when allowed to idle and the target position is not acceptable. - Vector m_CurrentAnkleOffset; //!< Current offset from the joint to the ankle where the foot should be. + Vector m_AnkleOffset; //!< Current offset from the joint to the ankle where the foot should be. bool m_WillIdle; //!< Whether the Leg will go to idle position if the target position is above the Leg's joint position. float m_MoveSpeed; //!< How fast the Leg moves to a reach target, 0 means it doesn't and 1 means it moves instantly. diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index 05e76224d..a25e6aebb 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -422,7 +422,7 @@ ClassInfoGetters /// /// The UniqueID of the Attachable to remove. /// Whether or not to add the Attachable to MovableMan once it has been removed. - /// Whether or not to add break wounds to the Attachable and this MOSRotating. + /// Whether or not to add break wounds to the removed Attachable and this MOSRotating. /// False if the Attachable is invalid, otherwise true. virtual bool RemoveAttachable(long attachableUniqueID, bool addToMovableMan, bool addBreakWounds); @@ -439,7 +439,7 @@ ClassInfoGetters /// /// The Attachable to remove. /// Whether or not to add the Attachable to MovableMan once it has been removed. - /// Whether or not to add break wounds to the Attachable and this MOSRotating. + /// Whether or not to add break wounds to the removed Attachable and this MOSRotating. /// False if the Attachable is invalid, otherwise true. virtual bool RemoveAttachable(Attachable *attachable, bool addToMovableMan, bool addBreakWounds); From 53da816164ca0f910c3866230b051578e66e4d61 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 13 Nov 2020 02:33:44 -0400 Subject: [PATCH 096/144] PR review changes Changed various stuff around pickupable limitations and fixed AHuman.cpp and Turret.cpp to match up. so it's better named and more future-ready Fixed typos in changelog and updated it to match up with renaming of pickupable stuff --- CHANGELOG.md | 23 +++++++++++----------- Entities/AHuman.cpp | 2 +- Entities/HeldDevice.cpp | 33 +++++++++++++++----------------- Entities/HeldDevice.h | 42 +++++++++++++++++++++-------------------- Entities/Turret.cpp | 2 +- Managers/LuaMan.cpp | 8 ++++---- 6 files changed, 55 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d4917b10..dbf2b5fbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -161,7 +161,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Added `MOSRotating GibBlastStrength` INI and Lua (R/W) property. This lets you define how much force created `Gibs` and any `Attachables` will get launched when the MOSRotating gibs. - New INI and Lua (R/W) properties for Attachables: - `ParentBreakWound = AEmitter...` allows you to optionally define different BreakWounds for the `Attachable` and its parent. By default it matches `BreakWound` for ease of use.ma + `ParentBreakWound = AEmitter...` allows you to optionally define different BreakWounds for the `Attachable` and its parent. By default it matches `BreakWound` for ease of use. `InheritsHFlipped = 0/1/2` allows you to define whether the `Attachable` will inherit its parent's HFlipped value or not. 0 means no inheritance, 1 means normal inheritance, 2 means reversed inheritance (technically any value other than 0 or 1 will act as reversed inheritance). Defaults to 1 to preserve normal behaviour. `InheritedRotAngleRadOffset = angle` and `InheritedRotAngleDegOffset = angle` allow you specify an offset to keep an `Attachable's` rotation at when `InheritsRotAngle` is set to true. In Lua there's only `InheritedRotAngleOffset` which takes/returns radians, to avoid confusion. For example, `InheritedRotAngleDegOffset = 90` would make the Attachable always face perpendicular to its parent. Does nothing if the `Attachable's` `InheritsRotAngle` is set to false or the `Attachable` has no parent. `GibWithParentChance = 0 - 1` allows you to specify whether this `Attachable` should be gibbed when its parent does and what the chance of that happening is. 0 means never, 1 means always. @@ -173,21 +173,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - New Lua `MovableObject` function `GetWhichMOToNotHit`. This provides access to the MO that has been set to not be hit by `SetWhichMOToNotHit`. -- Added `HeldDevice` handling to limit which `Actor(s)` can pick it up. Note that pickup limitations are all done by PresetName, so you can not use this to specify specific `Actors` (yet). +- Added `HeldDevice` handling to limit which `Actor(s)` can pick it up. Note that pickup limitations are all done by PresetName, so you can not use this to precisely specify individual `Actors`. The INI definition looks like this: ``` PickupableBy = PickupableByEntries - AddActorEntry = First Actor PresetName Here - AddActorEntry = Second Actor PresetName Here - AddActorEntry = None //This sets it to never be pickupable + AddPresetNameEntry = First Actor PresetName Here + AddPresetNameEntry = Second Actor PresetName Here + //Alternatively, if you want this not to be pickupable + PickupableBy = None ``` The Lua properties and functions are as follows: ``` heldDevice.HasPickupLimitations; --(R) Whether or not this HeldDevice has any limitations affecting whether it can be picked up. - heldDevice.NoActorsCanPickThisUp --(R/W) Whether this HeldDevice is/should be pickupable by any Actors. - heldDevice:ActorCanPickThisUp(actor) -- Whether or not a given Actor can pick up this HeldDevice. - heldDevice:AddActorWhoCanPickThisUp(actor) -- Allows the given Actor (and any others with the same PresetName) to pick up this HeldDevice. - heldDevice:RemoveActorWhoCanPickThisUp(actor) -- Disallows the given Actor (and any others with the same PresetName) from picking up this HeldDevice. + heldDevice.UnPickupable --(R/W) Whether this HeldDevice is/should be pickupable. + heldDevice:IsPickupableBy(actor) -- Whether or not a given Actor can pick up this HeldDevice. + heldDevice:AddPickupableByPresetName(presetName) -- Allows Actors with the given PresetName to pick up this HeldDevice. + heldDevice:RemovePickupableByPresetName(presetName) -- Disallows Actors with the given PresetNames from picking up this HeldDevice (as long as there are other pickup limitations). ``` - Added `MOSRotating` Lua (R) property `IndividualMass`. This provides access to the `MOSRotating's` actual mass value, not including any `Attachables` or inventory items. Note that the normal `Mass` property is still used to set the `MOSRotating's` mass. @@ -292,7 +293,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - `AHuman` background `Leg` will no longer draw in front of the `AHuman`. The real result of this is that the background foot will no longer draw in front of the foreground one. -- Everything draws better when flashing white, including crafts which used to be terrible at it. +- Everything draws better when flashing white, including craft which used to be terrible at it. - Reworked Attachable managment `DamageMultiplier` on `Attachables` now works as expected, all `Attachables` can now transfer damage to their root parent. This will travel up chains of `Attachables`, as long as every `Attachable` in the chain has a non-zero DamageMultiplier (yes, negative numbers are supported if you wanna have healing instead of damage or weirdness with chaining negative multipliers). @@ -354,7 +355,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Craft sucking up objects now works properly again. -- Getting the `Mass` of an `MOSRotating` has now been made more efficient. Additionally, `Attachables` of `Attachables` will now be included in Mass, so some things have gotten a lot heavier (e.g. Dummy Dreadnought). +- Getting the `Mass` of a `MOSRotating` has now been made more efficient. Additionally, `Attachables` of `Attachables` will now be included in Mass, so some things have gotten a lot heavier (e.g. Dummy Dreadnought). - The moment of inertia of `AtomGroups` now updates when the mass or Atoms change, meaning losing `Attachables` or changing mass will properly affect how rotational forces apply to MOSRotatings. diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 1c174b045..b89676375 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -3572,7 +3572,7 @@ void AHuman::Update() } // Item currently set to be within reach has expired or is now out of range - if (m_pItemInReach && (m_pItemInReach->GetNoActorsCanPickThisUp() || (m_pItemInReach->HasPickupLimitations() && !m_pItemInReach->ActorCanPickThisUp(GetPresetName())) || !g_MovableMan.IsDevice(m_pItemInReach) || (m_pItemInReach->GetPos() - m_Pos).GetMagnitude() > reach)) { + if (m_pItemInReach && (m_pItemInReach->IsUnPickupable() || (m_pItemInReach->HasPickupLimitations() && !m_pItemInReach->IsPickupableBy(this)) || !g_MovableMan.IsDevice(m_pItemInReach) || (m_pItemInReach->GetPos() - m_Pos).GetMagnitude() > reach)) { m_pItemInReach = 0; m_PieNeedsUpdate = true; } diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index d56de8f7c..4c6a94662 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -47,7 +47,7 @@ void HeldDevice::Clear() m_MaxSharpLength = 0; m_Supported = false; m_SupportOffset.Reset(); - m_ActorsWhoCanPickThisUp.clear(); + m_PickupableByPresetNames.clear(); m_GripStrengthMultiplier = 1.0F; m_BlinkTimer.Reset(); m_PieSlices.clear(); @@ -136,8 +136,8 @@ int HeldDevice::Create(const HeldDevice &reference) m_StanceOffset = reference.m_StanceOffset; m_SharpStanceOffset = reference.m_SharpStanceOffset; m_SupportOffset = reference.m_SupportOffset; - for (std::string referenceActorWhoCanPickThisUp : reference.m_ActorsWhoCanPickThisUp) { - m_ActorsWhoCanPickThisUp.insert(referenceActorWhoCanPickThisUp); + for (std::string referenceActorWhoCanPickThisUp : reference.m_PickupableByPresetNames) { + m_PickupableByPresetNames.insert(referenceActorWhoCanPickThisUp); } m_GripStrengthMultiplier = reference.m_GripStrengthMultiplier; @@ -180,14 +180,11 @@ int HeldDevice::ReadProperty(std::string propName, Reader &reader) if (pickupableByValue == "PickupableByEntries") { while (reader.NextProperty()) { std::string pickupableByEntryType = reader.ReadPropName(); - if (pickupableByEntryType == "AddActorEntry") { - std::string actorEntryValue = reader.ReadPropValue(); - if (actorEntryValue == "none" || actorEntryValue == "None" || actorEntryValue == "NONE") { - m_ActorsWhoCanPickThisUp.insert(c_NoPickupString); - } else { - m_ActorsWhoCanPickThisUp.insert(actorEntryValue); - } - } else if (pickupableByEntryType == "AddGroupEntry ") { + if (pickupableByEntryType == "AddPresetNameEntry") { + m_PickupableByPresetNames.insert(reader.ReadPropValue()); + } else if (pickupableByEntryType == "AddClassNameEntry ") { + reader.ReportError("AddClassNameEntry is not yet supported."); + } else if (pickupableByEntryType == "AddGroupEntry") { reader.ReportError("AddGroupEntry is not yet supported."); } else if (pickupableByEntryType == "AddDataModuleEntry ") { reader.ReportError("AddDataModuleEntry is not yet supported."); @@ -195,8 +192,8 @@ int HeldDevice::ReadProperty(std::string propName, Reader &reader) break; } } - } else { - m_ActorsWhoCanPickThisUp.insert(pickupableByValue); + } else if (pickupableByValue == "None") { + SetUnPickupable(true); } } else if (propName == "GripStrengthMultiplier") { reader >> m_GripStrengthMultiplier; @@ -289,11 +286,11 @@ Vector HeldDevice::GetStanceOffset() const ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void HeldDevice::SetNoActorsCanPickThisUp(bool noActors) { - if (noActors) { - AddActorWhoCanPickThisUp(c_NoPickupString); +void HeldDevice::SetUnPickupable(bool unpickupable) { + if (unpickupable) { + AddPickupableByPresetName(c_NoPickupString); } else { - RemoveActorWhoCanPickThisUp(c_NoPickupString); + RemovePickupableByPresetName(c_NoPickupString); } } @@ -537,7 +534,7 @@ void HeldDevice::DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos, int whi Attachable::DrawHUD(pTargetBitmap, targetPos, whichScreen); - if (!m_Parent && !GetNoActorsCanPickThisUp()) + if (!m_Parent && !IsUnPickupable()) { // Only draw if the team viewing this has seen the space where this is located int viewingTeam = g_ActivityMan.GetActivity()->GetTeamOfPlayer(g_ActivityMan.GetActivity()->PlayerOfScreen(whichScreen)); diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index 9b442b2fd..7892cfb34 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -15,6 +15,7 @@ // Inclusions of header files #include "Attachable.h" +#include "Actor.h" #include "PieMenuGUI.h" namespace RTE @@ -282,41 +283,42 @@ ClassInfoGetters void SetSupportOffset(Vector newOffset) { m_SupportOffset = newOffset; } /// - /// Gets whether this HeldDevice has any limitations on who can pick it up. + /// Gets whether this HeldDevice has any limitations on what can pick it up. /// - /// Whether this HeldDevice has any limitations on who can pick it up. - bool HasPickupLimitations() const { return !m_ActorsWhoCanPickThisUp.empty(); } + /// Whether this HeldDevice has any limitations on what can pick it up. + bool HasPickupLimitations() const { return IsUnPickupable() || !m_PickupableByPresetNames.empty(); } /// - /// Gets whether no Actors (or child classes) can pick up this HeldDevice. + /// Gets whether this HeldDevice cannot be picked up at all. /// - /// Whether no Actors (or child classes) can pick up this HeldDevice. - bool GetNoActorsCanPickThisUp() const { return m_ActorsWhoCanPickThisUp.find(c_NoPickupString) != m_ActorsWhoCanPickThisUp.end(); } + /// Whether this HeldDevice cannot be picked up at all. + bool IsUnPickupable() const { return m_PickupableByPresetNames.find(c_NoPickupString) != m_PickupableByPresetNames.end(); } /// - /// Sets whether no Actors (or child classes) can pick up this HeldDevice. + /// Sets whether this HeldDevice cannot be picked up at all. /// - /// Whether no Actors (or child classes) should be able to pick up this HeldDevice. True means none will be able to, false means any other limitations will apply normally. - void SetNoActorsCanPickThisUp(bool noActors); + /// Whether this HeldDevice cannot be picked up at all. True means it cannot, false means any other limitations will apply normally. + void SetUnPickupable(bool unpickupable); /// - /// Checks whether Actors with the given PresetName can pick up this HeldDevice. + /// Checks whether the given Actor can pick up this HeldDevice. /// - /// The PresetName of the Actor to check. Ownership is NOT transferred. - /// Whether Actors with the given PresetName can pick up this HeldDevice. - bool ActorCanPickThisUp(const std::string &actorPresetName) { return m_ActorsWhoCanPickThisUp.find(actorPresetName) != m_ActorsWhoCanPickThisUp.end(); } + /// The Actor to check. Ownership is NOT transferred. + /// Whether the given Actor can pick up this HeldDevice. + bool IsPickupableBy(const Actor *actor) const { return !HasPickupLimitations() || m_PickupableByPresetNames.find(actor->GetPresetName()) != m_PickupableByPresetNames.end(); } /// - /// Allow any Actors (or child classes) with the given PresetName to pick up this HeldDevice, as long as it's not set so no Actors can pick it up. + /// Specify that objects with the given PresetName can pick up this HeldDevice. /// - /// The PresetName of an Actor who should be able to pick up this HeldDevice. - void AddActorWhoCanPickThisUp(const std::string &actorPresetName) { m_ActorsWhoCanPickThisUp.insert(actorPresetName); } + /// The PresetName of an object that should be able to pick up this HeldDevice. + void AddPickupableByPresetName(const std::string &presetName) { SetUnPickupable(false); m_PickupableByPresetNames.insert(presetName); } /// - /// Remove allowance for any Actors (or child classes) with the given PresetName from picking up this HeldDevice. Note that if no specific Actors are allowed to pick this HeldDevice up, all Actors will be allowed to do so unless it's set so no Actors can pick it up. + /// Remove allowance for objects with the given PresetName to pick up this HeldDevice. + /// Note that if the last allowance is removed, the HeldDevice will no longer have pickup limitations, rather than setting itself as unpickupable. /// - /// The PresetName of an Actor who should no longer be able to pick up this HeldDevice. - void RemoveActorWhoCanPickThisUp(const std::string &actorPresetName) { m_ActorsWhoCanPickThisUp.erase(m_ActorsWhoCanPickThisUp.find(actorPresetName)); } + /// The PresetName of an object that should no longer be able to pick up this HeldDevice. + void RemovePickupableByPresetName(const std::string &actorPresetName) { m_PickupableByPresetNames.erase(m_PickupableByPresetNames.find(actorPresetName)); } /// /// Gets the multiplier for how well this HeldDevice can be gripped by Arms. @@ -627,7 +629,7 @@ ClassInfoGetters float m_MaxSharpLength; // If this HeldDevice is currently being supported by a second hand. bool m_Supported; - std::unordered_set m_ActorsWhoCanPickThisUp; //!< The unordered set of Actors (and appropriate subclasses) who can pick up this held device if it's dropped. An empty set means any Actors can pick it up, a c_NoPickupString entry means none can pick it up. + std::unordered_set m_PickupableByPresetNames; //!< The unordered set of PresetNames that can pick up this HeldDevice if it's dropped. An empty set means there are no PresetName limitations. float m_GripStrengthMultiplier; //!< The multiplier for how well this HeldDevice can be gripped by Arms. // Blink timer for the icon Timer m_BlinkTimer; diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index 2a6005622..f7324ab0d 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -36,7 +36,7 @@ namespace RTE { m_MountedDevice = dynamic_cast(mountedDeviceEntity->Clone()); AddAttachable(m_MountedDevice); m_MountedDevice->SetInheritsRotAngle(false); - m_MountedDevice->SetNoActorsCanPickThisUp(true); + m_MountedDevice->SetUnPickupable(true); //Force weapons mounted on turrets to never be removed due to forces. This doesn't affect them gibbing from hitting their impulse limits though. m_MountedDevice->SetJointStrength(0.0F); } diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 5cfb95579..923b9cf4a 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1321,10 +1321,10 @@ int LuaMan::Create() { .property("SharpLength", &HeldDevice::GetSharpLength, &HeldDevice::SetSharpLength) .property("SupportOffset", &HeldDevice::GetSupportOffset, &HeldDevice::SetSupportOffset) .property("HasPickupLimitations", &HeldDevice::HasPickupLimitations) - .property("NoActorsCanPickThisUp", &HeldDevice::GetNoActorsCanPickThisUp, &HeldDevice::SetNoActorsCanPickThisUp) - .def("ActorCanPickThisUp", &HeldDevice::ActorCanPickThisUp) - .def("AddActorWhoCanPickThisUp", &HeldDevice::AddActorWhoCanPickThisUp) - .def("RemoveActorWhoCanPickThisUp", &HeldDevice::RemoveActorWhoCanPickThisUp) + .property("UnPickupable", &HeldDevice::IsUnPickupable, &HeldDevice::SetUnPickupable) + .def("IsPickupableBy", &HeldDevice::IsPickupableBy) + .def("AddPickupableByPresetName", &HeldDevice::AddPickupableByPresetName) + .def("RemovePickupableByPresetName", &HeldDevice::RemovePickupableByPresetName) .property("GripStrengthMultiplier", &HeldDevice::GetGripStrengthMultiplier, &HeldDevice::SetGripStrengthMultiplier) .def("SetSupported", &HeldDevice::SetSupported), From 7fdaf52ac84b802d339fe320d87c092a49237dfa Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 13 Nov 2020 10:29:02 -0400 Subject: [PATCH 097/144] Whoops, fixed a li'l crash --- Entities/HeldDevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index 7892cfb34..b1edffcd9 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -318,7 +318,7 @@ ClassInfoGetters /// Note that if the last allowance is removed, the HeldDevice will no longer have pickup limitations, rather than setting itself as unpickupable. /// /// The PresetName of an object that should no longer be able to pick up this HeldDevice. - void RemovePickupableByPresetName(const std::string &actorPresetName) { m_PickupableByPresetNames.erase(m_PickupableByPresetNames.find(actorPresetName)); } + void RemovePickupableByPresetName(const std::string &actorPresetName) { std::unordered_set::iterator pickupableByPresetNameEntry = m_PickupableByPresetNames.find(actorPresetName); if (pickupableByPresetNameEntry != m_PickupableByPresetNames.end()) { m_PickupableByPresetNames.erase(pickupableByPresetNameEntry); } } /// /// Gets the multiplier for how well this HeldDevice can be gripped by Arms. From f860debe8349325172a0646fde3ba96b488037c7 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 13 Nov 2020 11:27:46 -0400 Subject: [PATCH 098/144] Changed nonpickupable to use a boolean so it doesn't weirdly crash (still bizarre that it does but w/e) --- Entities/HeldDevice.cpp | 15 ++------------- Entities/HeldDevice.h | 9 ++++----- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index 4c6a94662..6747b38e7 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -25,8 +25,6 @@ namespace RTE { ConcreteClassInfo(HeldDevice, Attachable, 50) -const std::string HeldDevice::c_NoPickupString = "|-NONE-|"; - ////////////////////////////////////////////////////////////////////////////////////////// // Method: Clear ////////////////////////////////////////////////////////////////////////////////////////// @@ -47,6 +45,7 @@ void HeldDevice::Clear() m_MaxSharpLength = 0; m_Supported = false; m_SupportOffset.Reset(); + m_IsUnPickupable = false; m_PickupableByPresetNames.clear(); m_GripStrengthMultiplier = 1.0F; m_BlinkTimer.Reset(); @@ -136,6 +135,7 @@ int HeldDevice::Create(const HeldDevice &reference) m_StanceOffset = reference.m_StanceOffset; m_SharpStanceOffset = reference.m_SharpStanceOffset; m_SupportOffset = reference.m_SupportOffset; + m_IsUnPickupable = reference.m_IsUnPickupable; for (std::string referenceActorWhoCanPickThisUp : reference.m_PickupableByPresetNames) { m_PickupableByPresetNames.insert(referenceActorWhoCanPickThisUp); } @@ -284,17 +284,6 @@ Vector HeldDevice::GetStanceOffset() const return m_StanceOffset.GetXFlipped(m_HFlipped); } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void HeldDevice::SetUnPickupable(bool unpickupable) { - if (unpickupable) { - AddPickupableByPresetName(c_NoPickupString); - } else { - RemovePickupableByPresetName(c_NoPickupString); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetSupportPos diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index b1edffcd9..510d7fc2b 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -292,13 +292,13 @@ ClassInfoGetters /// Gets whether this HeldDevice cannot be picked up at all. /// /// Whether this HeldDevice cannot be picked up at all. - bool IsUnPickupable() const { return m_PickupableByPresetNames.find(c_NoPickupString) != m_PickupableByPresetNames.end(); } + bool IsUnPickupable() const { return m_IsUnPickupable; } /// /// Sets whether this HeldDevice cannot be picked up at all. /// - /// Whether this HeldDevice cannot be picked up at all. True means it cannot, false means any other limitations will apply normally. - void SetUnPickupable(bool unpickupable); + /// Whether this HeldDevice cannot be picked up at all. True means it cannot, false means any other limitations will apply normally. + void SetUnPickupable(bool shouldBeUnPickupable) { m_IsUnPickupable = shouldBeUnPickupable; } /// /// Checks whether the given Actor can pick up this HeldDevice. @@ -601,8 +601,6 @@ ClassInfoGetters protected: - static const std::string c_NoPickupString; //!< Static string for adding a no allowed pickups entry. - // Member variables static Entity::ClassInfo m_sClass; // Indicates what kind of held device this is, see the HeldDeviceType enum @@ -629,6 +627,7 @@ ClassInfoGetters float m_MaxSharpLength; // If this HeldDevice is currently being supported by a second hand. bool m_Supported; + bool m_IsUnPickupable; //!< Whether or not this HeldDevice should be able to be picked up at all. std::unordered_set m_PickupableByPresetNames; //!< The unordered set of PresetNames that can pick up this HeldDevice if it's dropped. An empty set means there are no PresetName limitations. float m_GripStrengthMultiplier; //!< The multiplier for how well this HeldDevice can be gripped by Arms. // Blink timer for the icon From fed49f3864f16fdb813afa18e082b30a0b4c89a0 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 21 Nov 2020 16:30:44 -0400 Subject: [PATCH 099/144] Swap InheritsHFlip to be -1 for reverse instead of 2 and modified changelog accordingly Fixed magazine terrain collision default setting so it no longer overwrites INI values --- CHANGELOG.md | 2 +- Entities/ACRocket.cpp | 2 +- Entities/ACrab.cpp | 4 ++-- Entities/Attachable.cpp | 2 +- Entities/Attachable.h | 4 ++-- Entities/Magazine.cpp | 5 +++-- Entities/Magazine.h | 2 +- 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbf2b5fbd..0f27f8808 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -162,7 +162,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - New INI and Lua (R/W) properties for Attachables: `ParentBreakWound = AEmitter...` allows you to optionally define different BreakWounds for the `Attachable` and its parent. By default it matches `BreakWound` for ease of use. - `InheritsHFlipped = 0/1/2` allows you to define whether the `Attachable` will inherit its parent's HFlipped value or not. 0 means no inheritance, 1 means normal inheritance, 2 means reversed inheritance (technically any value other than 0 or 1 will act as reversed inheritance). Defaults to 1 to preserve normal behaviour. + `InheritsHFlipped = -1/0/1` allows you to define whether the `Attachable` will inherit its parent's HFlipped value or not. -1 means reversed inheritance (i.e. if the parent's HFlipped value is true, this Attachable's HFlipped value will be false), 0 means no inheritance, 1 means normal inheritance. Defaults to 1 to preserve normal behaviour. `InheritedRotAngleRadOffset = angle` and `InheritedRotAngleDegOffset = angle` allow you specify an offset to keep an `Attachable's` rotation at when `InheritsRotAngle` is set to true. In Lua there's only `InheritedRotAngleOffset` which takes/returns radians, to avoid confusion. For example, `InheritedRotAngleDegOffset = 90` would make the Attachable always face perpendicular to its parent. Does nothing if the `Attachable's` `InheritsRotAngle` is set to false or the `Attachable` has no parent. `GibWithParentChance = 0 - 1` allows you to specify whether this `Attachable` should be gibbed when its parent does and what the chance of that happening is. 0 means never, 1 means always. `ParentGibBlastStrengthMultiplier = number` allows you to specify the multiplier this `Attachable` will apply to its parent's gib blast strength when the parent gibs. Usually this would be a positive number, but it doesn't have to be. diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 417587de0..038511650 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -170,7 +170,7 @@ int ACRocket::ReadProperty(std::string propName, Reader &reader) { m_pLLeg = new Leg; reader >> m_pLLeg; AddAttachable(m_pLLeg); - m_pLLeg->SetInheritsHFlipped(2); + m_pLLeg->SetInheritsHFlipped(-1); if (!m_pLLeg->GetDamageMultiplierSetInINI()) { m_pLLeg->SetDamageMultiplier(1.0F); } } else if (propName == "RFootGroup") { delete m_pRFootGroup; diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index c1b805c45..0833a14f0 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -263,14 +263,14 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) reader >> m_pLFGLeg; AddAttachable(m_pLFGLeg); if (!m_pLFGLeg->GetDamageMultiplierSetInINI()) { m_pLFGLeg->SetDamageMultiplier(1.0F); } - m_pLFGLeg->SetInheritsHFlipped(2); + m_pLFGLeg->SetInheritsHFlipped(-1); } else if (propName == "LBGLeg" || propName == "LeftFGLeg") { RemoveAttachable(m_pLBGLeg); m_pLBGLeg = new Leg; reader >> m_pLBGLeg; AddAttachable(m_pLBGLeg); if (!m_pLBGLeg->GetDamageMultiplierSetInINI()) { m_pLBGLeg->SetDamageMultiplier(1.0F); } - m_pLBGLeg->SetInheritsHFlipped(2); + m_pLBGLeg->SetInheritsHFlipped(-1); } else if (propName == "RFGLeg" || propName == "LeftFGLeg") { RemoveAttachable(m_pRFGLeg); m_pRFGLeg = new Leg; diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 3424a231f..3ee5c5b5c 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -111,7 +111,7 @@ namespace RTE { m_ParentBreakWound = dynamic_cast(g_PresetMan.GetEntityPreset(reader)); } else if (propName == "InheritsHFlipped") { reader >> m_InheritsHFlipped; - if (m_InheritsHFlipped != 0 && m_InheritsHFlipped != 1) { m_InheritsHFlipped = 2; } + if (m_InheritsHFlipped != 0 && m_InheritsHFlipped != 1) { m_InheritsHFlipped = -1; } } else if (propName == "InheritsRotAngle") { reader >> m_InheritsRotAngle; } else if (propName == "InheritedRotAngleRadOffset" || propName == "InheritedRotAngleOffset") { diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 27cbec0d4..461e8d7cf 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -290,14 +290,14 @@ namespace RTE { #pragma region Inherited Value Getters and Setters /// /// Gets whether or not this Attachable inherits its parent's HFlipped value, i.e. whether it has its HFlipped value reset to match/reverse its parent's every frame, if attached. - /// 0 means no inheritance, 1 means inheritance, any other value means reversed inheritance (i.e. if the parent's HFlipped value is true, this Attachable's HFlipped value will be false). + /// -1 (or technically any value that's not 0 or 1) means reversed inheritance (i.e. if the parent's HFlipped value is true, this Attachable's HFlipped value will be false), 0 means no inheritance, 1 means normal inheritance. /// /// Whether or not this Attachable inherits its parent's HFlipped value. int InheritsHFlipped() const { return m_InheritsHFlipped; } /// /// Sets whether or not this Attachable inherits its parent's HFlipped value, i.e. whether it has its HFlipped value reset to match/reverse its parent's every frame, if attached. - /// 0 means no inheritance, 1 means inheritance, any other value means reversed inheritance (i.e. if the parent's HFlipped value is true, this Attachable's HFlipped value will be false). + /// -1 (or technically any value that's not 0 or 1) means reversed inheritance (i.e. if the parent's HFlipped value is true, this Attachable's HFlipped value will be false), 0 means no inheritance, 1 means normal inheritance. /// /// Whether or not to inherit its parent's HFlipped value. void SetInheritsHFlipped(int inheritsHFlipped) { m_InheritsHFlipped = inheritsHFlipped; } diff --git a/Entities/Magazine.cpp b/Entities/Magazine.cpp index 221a56ed0..5101ce6cf 100644 --- a/Entities/Magazine.cpp +++ b/Entities/Magazine.cpp @@ -38,6 +38,9 @@ void Magazine::Clear() m_AIAimMaxDistance = -1; m_AIAimPenetration = 0; m_AIBlastRadius = -1; + + // NOTE: This special override of a parent class member variable avoids needing an extra variable to avoid overwriting INI values. + m_CollidesWithTerrainWhileAttached = false; } @@ -50,8 +53,6 @@ int Magazine::Create() { if (Attachable::Create() < 0) return -1; - - SetCollidesWithTerrainWhileAttached(false); // Read projectile properties for AI aim caluculations const Round * pNextRound = GetNextRound(); diff --git a/Entities/Magazine.h b/Entities/Magazine.h index a756304aa..daf3e17c7 100644 --- a/Entities/Magazine.h +++ b/Entities/Magazine.h @@ -94,7 +94,7 @@ ClassInfoGetters // Arguments: None. // Return value: None. - void Reset() override { Clear(); Attachable::Reset(); } + void Reset() override { Clear(); Attachable::Reset(); m_CollidesWithTerrainWhileAttached = false; } ////////////////////////////////////////////////////////////////////////////////////////// From b4c7a712f0f2858630899e15f69eedd1375e8732 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 21 Nov 2020 16:32:22 -0400 Subject: [PATCH 100/144] Moved FacingAngle from Actor to MOSprite so it can be used more widely --- Entities/Actor.cpp | 13 ------------- Entities/Actor.h | 12 ------------ Entities/MOSprite.h | 7 +++++++ 3 files changed, 7 insertions(+), 25 deletions(-) diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index 788d78581..c91bf978e 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -736,19 +736,6 @@ void Actor::RestDetection() } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: FacingAngle -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Adjusts an absolute aiming angle based on whether this Actor is facing -// left or right. - -float Actor::FacingAngle(float angle) const -{ - return (m_HFlipped ? c_PI : 0) + (angle * (m_HFlipped ? -1 : 1)); -// return (angle * m_HFlipped ? -1 : 1); -} - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: AddPieMenuSlices ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Actor.h b/Entities/Actor.h index 768e77107..1abc117fc 100644 --- a/Entities/Actor.h +++ b/Entities/Actor.h @@ -588,18 +588,6 @@ ClassInfoGetters bool IsDead() const { return m_Status == DEAD; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: FacingAngle -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Adjusts an absolute aiming angle based on wether this Actor is facing -// left or right. -// Arguments: The input angle in radians. -// Return value: The output angle in radians, which will be unaltered if this Actor is -// facing right. - - float FacingAngle(float angle) const; - - ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: PieNeedsUpdate ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/MOSprite.h b/Entities/MOSprite.h index f16255667..b9f64dd98 100644 --- a/Entities/MOSprite.h +++ b/Entities/MOSprite.h @@ -453,6 +453,13 @@ class MOSprite: Vector UnRotateOffset(const Vector &offset) const; + /// + /// Adjusts an absolute angle based on wether this MOSprite is flipped. + /// + /// The input angle in radians. + /// The output angle in radians, which will be unaltered if this MOSprite is not flipped. + float FacingAngle(float angle) const { return (m_HFlipped ? c_PI : 0) + (angle * static_cast(GetFlipFactor())); } + ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: SetEntryWound From ad6c6056f5c526e04568258cb950ff14781f9a3b Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 21 Nov 2020 16:33:29 -0400 Subject: [PATCH 101/144] Sort of fixed attachable atom group updating so it'll happen whenever the attachable's rot angle changes, relative to its root parent Got rid of recursive CalculateAtomOffsetForSubgroup in favour of just getting shortest distance to root parent --- Entities/Attachable.cpp | 44 +++++++++++++++-------------------------- Entities/Attachable.h | 9 ++------- 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 3ee5c5b5c..7afde1dc2 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -37,6 +37,8 @@ namespace RTE { m_AtomSubgroupID = -1L; m_CollidesWithTerrainWhileAttached = true; + + m_PrevRotAngleOffset = 0.0F; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -76,9 +78,10 @@ namespace RTE { m_InheritsRotAngle = reference.m_InheritsRotAngle; m_InheritedRotAngleOffset = reference.m_InheritedRotAngleOffset; + m_AtomSubgroupID = GetUniqueID(); m_CollidesWithTerrainWhileAttached = reference.m_CollidesWithTerrainWhileAttached; - m_AtomSubgroupID = GetUniqueID(); + m_PrevRotAngleOffset = reference.m_PrevRotAngleOffset; return 0; } @@ -295,35 +298,30 @@ namespace RTE { if (!m_Parent) { m_JointPos = m_Pos + RotateOffset(m_JointOffset); } else { - m_PrevPos = m_Pos; - m_PrevVel = m_Vel; - m_JointPos = m_Parent->GetPos() + m_Parent->RotateOffset(GetParentOffset()); m_Pos = m_JointPos - RotateOffset(m_JointOffset); m_Vel = m_Parent->GetVel(); m_Team = m_Parent->GetTeam(); if (InheritsHFlipped() != 0) { m_HFlipped = m_InheritsHFlipped == 1 ? m_Parent->IsHFlipped() : !m_Parent->IsHFlipped(); } - if (InheritsRotAngle()) { SetRotAngle(m_Parent->GetRotAngle() + m_InheritedRotAngleOffset); } + if (InheritsRotAngle()) { SetRotAngle(m_Parent->GetRotAngle() + m_InheritedRotAngleOffset * static_cast(m_Parent->GetFlipFactor())); } MOSRotating *rootParentAsMOSR = dynamic_cast(GetRootParent()); + float currentRotAngleOffset = (GetRotAngle() * static_cast(GetFlipFactor())) - rootParentAsMOSR->GetRotAngle(); if (rootParentAsMOSR && m_CollidesWithTerrainWhileAttached) { // Note: This safety check exists to ensure the parent's AtomGroup contains this Attachable's Atoms in a subgroup. Hardcoded Attachables need this in order to work, since they're cloned before their parent's AtomGroup exists. if (!rootParentAsMOSR->GetAtomGroup()->ContainsSubGroup(m_AtomSubgroupID)) { AddOrRemoveAtomsFromRootParentAtomGroup(true); } - float facingAngle = (m_HFlipped ? c_PI : 0) + GetRotAngle() * static_cast(GetFlipFactor()); - float parentFacingAngle = (m_Parent->IsHFlipped() ? c_PI : 0) + m_Parent->GetRotAngle() * static_cast(m_Parent->GetFlipFactor()); - - if (!InheritsRotAngle()) { - Matrix atomRotationForSubgroup(facingAngle - parentFacingAngle); - Vector atomOffsetForSubgroup; - CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); - //TODO CalculateAtomOffsetForSubgroup should just return the rotated value. This means AtomGroup::AddAtoms needs to be modified to exect this rotated value instead of doing rotation internally. Alternatively, UpdateSubAtoms should expect unrotated atom offsets and deal with things interally, either way, it should be consistent. - // Note: This line looks weird because CalculateAtomOffsetForSubgroup already subtracts JointOffset from the value, so we have to re-add it and then subtract its rotated value instead. - atomOffsetForSubgroup += GetJointOffset() - (GetJointOffset() * atomRotationForSubgroup); + if (std::abs(currentRotAngleOffset - m_PrevRotAngleOffset) > 0.01745F) { // Update for 1 degree differences + Matrix atomRotationForSubgroup(rootParentAsMOSR->FacingAngle(GetRotAngle()) - rootParentAsMOSR->FacingAngle(rootParentAsMOSR->GetRotAngle())); + Vector atomOffsetForSubgroup = g_SceneMan.ShortestDistance(rootParentAsMOSR->GetPos(), m_Pos, g_SceneMan.SceneWrapsX()); rootParentAsMOSR->GetAtomGroup()->UpdateSubAtoms(GetAtomSubgroupID(), atomOffsetForSubgroup, atomRotationForSubgroup); } } m_DeepCheck = false; + + m_PrevPos = m_Pos; + m_PrevVel = m_Vel; + m_PrevRotAngleOffset = currentRotAngleOffset; } MOSRotating::Update(); @@ -411,16 +409,6 @@ namespace RTE { } } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - void Attachable::CalculateAtomOffsetForSubgroup(Vector &atomOffsetForSubgroup) const { - if (m_Parent) { - const Attachable *parentAsAttachable = dynamic_cast(m_Parent); - if (parentAsAttachable) { parentAsAttachable->CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); } - atomOffsetForSubgroup += GetParentOffset() - GetJointOffset(); - } - } - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Attachable::AddOrRemoveAtomsFromRootParentAtomGroup(bool addAtoms) { @@ -429,9 +417,9 @@ namespace RTE { AtomGroup *rootParentAtomGroup = rootParentAsMOSR->GetAtomGroup(); if (rootParentAtomGroup) { if (addAtoms && !rootParentAtomGroup->ContainsSubGroup(GetAtomSubgroupID())) { - Vector atomOffsetForSubgroup; - CalculateAtomOffsetForSubgroup(atomOffsetForSubgroup); - rootParentAtomGroup->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), atomOffsetForSubgroup); + Vector atomOffsetForSubgroup = g_SceneMan.ShortestDistance(rootParentAsMOSR->GetPos(), m_Pos, g_SceneMan.SceneWrapsX()); + Matrix atomRotationForSubgroup(rootParentAsMOSR->FacingAngle(GetRotAngle()) - rootParentAsMOSR->FacingAngle(rootParentAsMOSR->GetRotAngle())); + rootParentAtomGroup->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), atomOffsetForSubgroup, atomRotationForSubgroup); } else if (!addAtoms && rootParentAtomGroup->ContainsSubGroup(GetAtomSubgroupID())) { rootParentAtomGroup->RemoveAtoms(GetAtomSubgroupID()); } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 461e8d7cf..b1db35a8e 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -491,6 +491,8 @@ namespace RTE { long m_AtomSubgroupID; //!< The Atom IDs this' atoms will have when attached and added to a parent's AtomGroup. bool m_CollidesWithTerrainWhileAttached; //!< Whether this attachable currently has terrain collisions enabled while it's attached to a parent. + float m_PrevRotAngleOffset; //!< The previous frame's difference between this Attachable's RotAngle and it's root parent's RotAngle. + /// /// Sets this Attachable's parent MOSRotating, and also sets its Team based on its parent and, if the Attachable is set to collide, adds/removes Atoms to its new/old parent. /// @@ -499,13 +501,6 @@ namespace RTE { private: - /// - /// Calculates the offset this Attachable's Atoms should be given when added to its root parent's AtomGroup as a subgroup, and fills the passed in Vector with it. - /// If the Attachable's parent is the root parent, the Vector is not modified, as the calculated offset is (0, 0). - /// - /// A reference to the Vector that will be filled in with the offset this Attachable's Atoms should use when added to their root parent's AtomGroup as a subgroup. - void CalculateAtomOffsetForSubgroup(Vector &atomOffsetForSubgroup) const; - /// /// Turns on/off this Attachable's terrain collisions while it is attached by adding/removing its Atoms to/from its root parent's AtomGroup. /// From 2f4101c5c0dc428d31bd0ec1a0c8596ce0cb0c8a Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 21 Nov 2020 16:34:53 -0400 Subject: [PATCH 102/144] LuaMan and changelog FacingAngle update --- CHANGELOG.md | 2 ++ Managers/LuaMan.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f27f8808..6c53c1e70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -329,6 +329,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Due to the nature of various `Attachable` and force transferral changes, AEmitters seem to apply far more force now, so `DropShip` engines may need higher `JointStrengths` and `GibImpulseLimits`, otherwise they may break off or gib during normal use. +- The `FacingAngle` function has been moved from `Actor` to `MOSprite` so it can be used more widely. + ### Fixed - Fix crash when returning to `MetaGame` scenario screen after activity end. diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 923b9cf4a..22f0c77ff 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -767,6 +767,7 @@ int LuaMan::Create() { .def("IsOnScenePoint", &MOSprite::IsOnScenePoint) .def("RotateOffset", &MOSprite::RotateOffset) .def("UnRotateOffset", &MOSprite::UnRotateOffset) + .def("FacingAngle", &MOSprite::FacingAngle) .def("GetSpriteWidth", &MOSprite::GetSpriteWidth) .def("GetSpriteHeight", &MOSprite::GetSpriteHeight) .def("SetEntryWound", &MOSprite::SetEntryWound) @@ -984,7 +985,6 @@ int LuaMan::Create() { .def("AddHealth", &Actor::AddHealth) .def("IsStatus", &Actor::IsStatus) .def("IsDead", &Actor::IsDead) - .def("FacingAngle", &Actor::FacingAngle) .property("AIMode", &Actor::GetAIMode, &Actor::SetAIMode) .property("DeploymentID", &Actor::GetDeploymentID) .property("PassengerSlots", &Actor::GetPassengerSlots, &Actor::SetPassengerSlots) From 8b7762164ac5ab51fd95890f5538d61ab3a6f49d Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 23 Nov 2020 12:25:06 -0400 Subject: [PATCH 103/144] Added flipping when determining atomOffsetForSubgroup in Attachable, so it's not wonky when facing left. --- Entities/Attachable.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 7afde1dc2..8206f5907 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -314,6 +314,7 @@ namespace RTE { if (std::abs(currentRotAngleOffset - m_PrevRotAngleOffset) > 0.01745F) { // Update for 1 degree differences Matrix atomRotationForSubgroup(rootParentAsMOSR->FacingAngle(GetRotAngle()) - rootParentAsMOSR->FacingAngle(rootParentAsMOSR->GetRotAngle())); Vector atomOffsetForSubgroup = g_SceneMan.ShortestDistance(rootParentAsMOSR->GetPos(), m_Pos, g_SceneMan.SceneWrapsX()); + atomOffsetForSubgroup.FlipX(rootParentAsMOSR->IsHFlipped()); rootParentAsMOSR->GetAtomGroup()->UpdateSubAtoms(GetAtomSubgroupID(), atomOffsetForSubgroup, atomRotationForSubgroup); } } @@ -418,6 +419,7 @@ namespace RTE { if (rootParentAtomGroup) { if (addAtoms && !rootParentAtomGroup->ContainsSubGroup(GetAtomSubgroupID())) { Vector atomOffsetForSubgroup = g_SceneMan.ShortestDistance(rootParentAsMOSR->GetPos(), m_Pos, g_SceneMan.SceneWrapsX()); + atomOffsetForSubgroup.FlipX(rootParentAsMOSR->IsHFlipped()); Matrix atomRotationForSubgroup(rootParentAsMOSR->FacingAngle(GetRotAngle()) - rootParentAsMOSR->FacingAngle(rootParentAsMOSR->GetRotAngle())); rootParentAtomGroup->AddAtoms(GetAtomGroup()->GetAtomList(), GetAtomSubgroupID(), atomOffsetForSubgroup, atomRotationForSubgroup); } else if (!addAtoms && rootParentAtomGroup->ContainsSubGroup(GetAtomSubgroupID())) { From 201ab7fe07a30291b85031560db652df32d4b925 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 26 Nov 2020 16:14:49 -0400 Subject: [PATCH 104/144] Review comment - moved RemovePickupableByPresetName into cpp file and multilined it --- Entities/HeldDevice.cpp | 8 ++++++++ Entities/HeldDevice.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Entities/HeldDevice.cpp b/Entities/HeldDevice.cpp index 6747b38e7..905545c0c 100644 --- a/Entities/HeldDevice.cpp +++ b/Entities/HeldDevice.cpp @@ -313,6 +313,14 @@ Vector HeldDevice::GetMagazinePos() const return m_Pos; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void HeldDevice::RemovePickupableByPresetName(const std::string &actorPresetName) { + std::unordered_set::iterator pickupableByPresetNameEntry = m_PickupableByPresetNames.find(actorPresetName); + if (pickupableByPresetNameEntry != m_PickupableByPresetNames.end()) { m_PickupableByPresetNames.erase(pickupableByPresetNameEntry); } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: AddPieMenuSlices diff --git a/Entities/HeldDevice.h b/Entities/HeldDevice.h index 300164d52..2250e7402 100644 --- a/Entities/HeldDevice.h +++ b/Entities/HeldDevice.h @@ -318,7 +318,7 @@ ClassInfoGetters /// Note that if the last allowance is removed, the HeldDevice will no longer have pickup limitations, rather than setting itself as unpickupable. /// /// The PresetName of an object that should no longer be able to pick up this HeldDevice. - void RemovePickupableByPresetName(const std::string &actorPresetName) { std::unordered_set::iterator pickupableByPresetNameEntry = m_PickupableByPresetNames.find(actorPresetName); if (pickupableByPresetNameEntry != m_PickupableByPresetNames.end()) { m_PickupableByPresetNames.erase(pickupableByPresetNameEntry); } } + void RemovePickupableByPresetName(const std::string &actorPresetName); /// /// Gets the multiplier for how well this HeldDevice can be gripped by Arms. From 0a00c141077a3f2f3fa857c7793fdf31013b04b3 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 3 Dec 2020 03:47:12 -0400 Subject: [PATCH 105/144] Fixed atom subgroup rotation problems, they should rotate properly now, fingers crossed --- Entities/Attachable.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 8206f5907..a61dea578 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -314,7 +314,8 @@ namespace RTE { if (std::abs(currentRotAngleOffset - m_PrevRotAngleOffset) > 0.01745F) { // Update for 1 degree differences Matrix atomRotationForSubgroup(rootParentAsMOSR->FacingAngle(GetRotAngle()) - rootParentAsMOSR->FacingAngle(rootParentAsMOSR->GetRotAngle())); Vector atomOffsetForSubgroup = g_SceneMan.ShortestDistance(rootParentAsMOSR->GetPos(), m_Pos, g_SceneMan.SceneWrapsX()); - atomOffsetForSubgroup.FlipX(rootParentAsMOSR->IsHFlipped()); + atomOffsetForSubgroup.FlipX(rootParentAsMOSR->IsHFlipped()); //TODO consolidate this into the line above once this returns the vector + atomOffsetForSubgroup /= Matrix(rootParentAsMOSR->GetRotAngle() * rootParentAsMOSR->GetFlipFactor()); rootParentAsMOSR->GetAtomGroup()->UpdateSubAtoms(GetAtomSubgroupID(), atomOffsetForSubgroup, atomRotationForSubgroup); } } From 4f50af23392ee291c03b0a8981198692f555b650 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 4 Dec 2020 01:57:34 -0400 Subject: [PATCH 106/144] Fixed forces removing/gibbing attachables too easily Added backwards little backwards compatibility/safety check to keep attachables with low gib impulse limits from being too flimsy (it now uses the joint strength if that's the larger value) --- Entities/Attachable.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index a61dea578..c746429e0 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -201,22 +201,24 @@ namespace RTE { jointStiffnessValueToUse = jointStiffnessValueToUse > 0 ? jointStiffnessValueToUse : m_JointStiffness; jointStrengthValueToUse = jointStrengthValueToUse > 0 ? jointStrengthValueToUse : m_JointStrength; gibImpulseLimitValueToUse = gibImpulseLimitValueToUse > 0 ? gibImpulseLimitValueToUse : m_GibImpulseLimit; + if (gibImpulseLimitValueToUse > 0) { gibImpulseLimitValueToUse = std::max(gibImpulseLimitValueToUse, jointStrengthValueToUse); } Vector totalImpulseForce; for (const std::pair &impulseForce : m_ImpulseForces) { totalImpulseForce += impulseForce.first; } + totalImpulseForce *= jointStiffnessValueToUse; if (gibImpulseLimitValueToUse > 0 && totalImpulseForce.GetMagnitude() > gibImpulseLimitValueToUse) { - jointImpulses += (totalImpulseForce.SetMagnitude(gibImpulseLimitValueToUse)) * jointStiffnessValueToUse; + jointImpulses += totalImpulseForce.SetMagnitude(gibImpulseLimitValueToUse); GibThis(); return false; } else if (jointStrengthValueToUse > 0 && totalImpulseForce.GetMagnitude() > jointStrengthValueToUse) { - jointImpulses += (totalImpulseForce.SetMagnitude(jointStrengthValueToUse)) * jointStiffnessValueToUse; + jointImpulses += totalImpulseForce.SetMagnitude(jointStrengthValueToUse); m_Parent->RemoveAttachable(this, true, true); return false; } else { - jointImpulses += totalImpulseForce * jointStiffnessValueToUse; + jointImpulses += totalImpulseForce; } // Rough explanation of what this is doing: From 47611e605db19e2786361932e5988e6d40fb92e5 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 4 Dec 2020 01:58:41 -0400 Subject: [PATCH 107/144] Changelog update --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 402119ea6..05989207c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -328,7 +328,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Improved native recoil handling! Guns transfer recoil to arms/turrets, which transfer it to AHumans/ACrabs, all of it properly accounts for joint strengths (or grip strengths) and offsets at every step. ([Issue #7](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/issues/7) and [Issue #8](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/issues/8)). -- Due to the nature of various `Attachable` and force transferral changes, AEmitters seem to apply far more force now, so `DropShip` engines may need higher `JointStrengths` and `GibImpulseLimits`, otherwise they may break off or gib during normal use. +- `Attachables` now use their `GibImpulseLimit` as well as their `JointStrength` when determining whether they should be detached by strong forces. To maintain backwards compatibility, if the `GibImpulseLimit` is less than the `JointStrength`, the `JointStrength` will be used instead for this purpose. - The `FacingAngle` function has been moved from `Actor` to `MOSprite` so it can be used more widely. From a3c54c2ce267aebfdff1dd2a0a2371234ac4bfb3 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 18 Jan 2021 20:41:51 -0400 Subject: [PATCH 108/144] Made parent breakwound not automatically copy breakwound to fix weird actor flying on death. If you want a parent breakwound, you'll have to specify it, and probably make sure its emissions don't move the emitter. --- Entities/Attachable.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index c746429e0..2bd8e83c2 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -109,7 +109,6 @@ namespace RTE { reader >> m_JointOffset; } else if (propName == "BreakWound") { m_BreakWound = dynamic_cast(g_PresetMan.GetEntityPreset(reader)); - if (!m_ParentBreakWound) { m_ParentBreakWound = m_BreakWound; } } else if (propName == "ParentBreakWound") { m_ParentBreakWound = dynamic_cast(g_PresetMan.GetEntityPreset(reader)); } else if (propName == "InheritsHFlipped") { From 667bba8be496f8b76f182c75b59ce0a43a0b98df Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 18 Jan 2021 20:59:02 -0400 Subject: [PATCH 109/144] Update CHANGELOG.md Update changelog to correct previous description of parent breakwound handling and fix a few things --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de3448a1e..5f8d0542a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -130,8 +130,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ``` - New INI and Lua (R/W) properties for Attachables: - `TransfersDamageToParent = 0/1`. If enabled, the Attachable will act like hardcoded ones and transfer damage to its parent. For Attachables attached to other Attachables, the parent Attachable (and any of its parents, etc.) must have this enabled for it to work. - `ParentBreakWound = AEmitter...`. Use this to optionally define different BreakWounds for the Attachable and its parent. Matches BreakWound by default for ease of use. + `TransfersDamageToParent = 0/1`. If enabled, the Attachable will act like hardcoded ones and transfer damage to its parent. For `Attachables` attached to other `Attachables`, the parent `Attachable` (and any of its parents, etc.) must have this enabled for it to affect the root parent. + `ParentBreakWound = AEmitter...`. Use this to define a BreakWound that will be applied to the `Attachable's` parent when the `Attachable` is removed. `BreakWound` is also now R/W accessible to Lua. - Added log for non-fatal loading errors. This log will show image files that have been loaded with incorrect extensions (has no side effects but should be addressed) and audio files that failed loading entirely and will not be audible. From a764312de2b6470354ff7a8233edd2ce7ab0fbe4 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 21 Jan 2021 01:37:30 -0400 Subject: [PATCH 110/144] Added and used method to get impulses on an object. Also made AddImpulseForce use list initializer instead of make_pair cause I was there. Made attachable's update their positions as soon as they're given a new parent, avoiding wonky issues with atom positions and moment of inertia Made aemitter impulses only get added if they're non-zero. --- Entities/AEmitter.cpp | 2 +- Entities/Attachable.cpp | 2 ++ Entities/MovableObject.h | 7 ++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index 934ac06d4..0f0e57cc5 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -548,7 +548,7 @@ void AEmitter::Update() m_LastEmitTmr.Reset(); // Apply recoil/push effects. Joint stiffness will take effect when these are transferred to the parent. - m_ImpulseForces.push_back({pushImpulses, Vector()}); + if (!pushImpulses.IsZero()) { AddImpulseForce(pushImpulses); } // Count the the damage caused by the emissions, and only if we're not bursting if (!m_BurstTriggered) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 2bd8e83c2..85454fd49 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -390,6 +390,8 @@ namespace RTE { if (newParent) { m_Parent = newParent; m_Team = newParent->GetTeam(); + m_JointPos = m_Parent->GetPos() + m_Parent->RotateOffset(GetParentOffset()); + m_Pos = m_JointPos - RotateOffset(m_JointOffset); if (m_CollidesWithTerrainWhileAttached) { AddOrRemoveAtomsFromRootParentAtomGroup(true); } } else { m_RootMOID = m_MOID; diff --git a/Entities/MovableObject.h b/Entities/MovableObject.h index a7a50f5c4..546c9f853 100644 --- a/Entities/MovableObject.h +++ b/Entities/MovableObject.h @@ -1095,7 +1095,7 @@ friend class Atom; RTEAssert(offset.GetLargest() < 5000, "HUEG IMPULSE FORCE OFFSET"); #endif - m_ImpulseForces.push_back(std::make_pair(impulse, offset)); + m_ImpulseForces.push_back({impulse, offset}); } @@ -1427,6 +1427,11 @@ friend class Atom; void SetForceOffset(int n, Vector v) { if (n > 0 && n < m_Forces.size()) m_Forces[n].second = v; } + /// + /// Gets the pairs of impulse forces and their offsets that have to be applied. + /// + /// A constant reference to the deque of impulses for this MovableObject. + const std::deque > &GetImpulses() { return m_ImpulseForces; } ////////////////////////////////////////////////////////////////////////////////////////// // Virtual method: GetImpulsesCount() From b207c5ee65acefa607f648d71bc5b156a573db82 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 21 Jan 2021 01:42:04 -0400 Subject: [PATCH 111/144] Made wounds never collide with terrain while attached Cleaned up potential minor memory leak from wounds not being deleted when they're removed by lua callers Made wounds support lifetime and ToDelete = true, providing a few new ways to interact with them, a bit of minor cleanup --- Entities/MOSRotating.cpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 60f5eef74..457aff893 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -464,6 +464,7 @@ void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet GibThis(blast); return; } else { + woundToAdd->SetCollidesWithTerrainWhileAttached(false); woundToAdd->SetParentOffset(parentOffsetToSet); woundToAdd->SetParent(this); m_AttachableAndWoundMass += woundToAdd->GetMass(); @@ -502,8 +503,10 @@ float MOSRotating::RemoveWounds(int numberOfWoundsToRemove, bool includePositive return 0.0F; } float woundDamage = m_Wounds.front()->GetBurstDamage(); - m_AttachableAndWoundMass -= m_Wounds.front()->GetMass(); + AEmitter *wound = m_Wounds.front(); + m_AttachableAndWoundMass -= wound->GetMass(); m_Wounds.pop_front(); + delete wound; return woundDamage; }; @@ -1428,12 +1431,31 @@ void MOSRotating::Update() { m_Rotation += radsToGo * m_OrientToVel * velInfluence; } - for (AEmitter *wound : m_Wounds) { - RTEAssert(wound, "Broken wound AEmitter"); + AEmitter *wound = nullptr; + for (std::list::iterator woundIterator = m_Wounds.begin(); woundIterator != m_Wounds.end(); ) { + wound = *woundIterator; + RTEAssert(wound && wound->IsAttachedTo(this), "Broken wound AEmitter"); + ++woundIterator; wound->Update(); + + if (wound->IsSetToDelete() || (wound->GetLifetime() > 0 && wound->GetAge() > wound->GetLifetime())) { + m_Wounds.remove(wound); + m_AttachableAndWoundMass -= wound->GetMass(); + delete wound; + } else { + Vector totalImpulseForce; + for (const std::pair &impulseForce : wound->GetImpulses()) { + totalImpulseForce += impulseForce.first; + } + totalImpulseForce *= wound->GetJointStiffness(); + + if (!totalImpulseForce.IsZero()) { AddImpulseForce(totalImpulseForce, wound->GetApplyTransferredForcesAtOffset() ? wound->GetParentOffset() * m_Rotation * c_MPP : Vector()); } + + wound->ClearImpulseForces(); + } } - Attachable *attachable = 0; + Attachable *attachable = nullptr; for (std::list::iterator attachableIterator = m_Attachables.begin(); attachableIterator != m_Attachables.end(); ) { attachable = *attachableIterator; RTEAssert(attachable, "Broken Attachable!"); From de87115035908016f759ed58052be67641c9b19f Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 21 Jan 2021 20:44:16 -0400 Subject: [PATCH 112/144] Undid changelog changes in branch to make for easier merge --- CHANGELOG.md | 126 +-------------------------------------------------- 1 file changed, 1 insertion(+), 125 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f8d0542a..afb9c6c39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -128,11 +128,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), PrimitiveMan:DrawEllipseFillPrimitive(Vector pos, short horizRadius, short vertRadius, color) PrimitiveMan:DrawEllipseFillPrimitive(player, Vector pos, horizRadius, vertRadius, color) ``` - -- New INI and Lua (R/W) properties for Attachables: - `TransfersDamageToParent = 0/1`. If enabled, the Attachable will act like hardcoded ones and transfer damage to its parent. For `Attachables` attached to other `Attachables`, the parent `Attachable` (and any of its parents, etc.) must have this enabled for it to affect the root parent. - `ParentBreakWound = AEmitter...`. Use this to define a BreakWound that will be applied to the `Attachable's` parent when the `Attachable` is removed. - `BreakWound` is also now R/W accessible to Lua. - Added log for non-fatal loading errors. This log will show image files that have been loaded with incorrect extensions (has no side effects but should be addressed) and audio files that failed loading entirely and will not be audible. If errors are present the console will be forced open to notify the player (only when loading into main menu). @@ -146,57 +141,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - `FLAC` audio files can now be loaded through lua and ini. -- Added Lua (R/W) properties for all hardcoded Attachables. You can now set them on the fly to be created objects of the relevant type. Note that trying to set things inappropriately (e.g. setting an HDFirearm as something's Leg) will probably crash the game; that's your problem to deal with. - You can read and write the following properties: - AHuman - `Head, Jetpack, FGArm, BGArm, FGLeg, BGLeg, FGFoot, BGFoot` - ACrab - `Turret, Jetpack, LeftFGLeg, LeftBGLeg, RightFGLeg, RightBGLeg` - ACDropship - `RightEngine, LeftEngine, RightThruster, LeftThruster, RightHatch, LeftHatch` - ACRocket - `RightLeg, LeftLeg, MainEngine, LeftEngine, RightEngine, LeftThruster, RightThruster` - ADoor - `Door` - Turret - `MountedDevice` - Leg - `Foot` - HDFirearm - `Magazine, Flash` - AEmitter - `Flash` - -- Added `Vector:ClampMagnitude(upperLimit, lowerLimit)` Lua function that lets you limit a Vector's upper and lower magnitude. - -- Added `MOSRotating GibBlastStrength` INI and Lua (R/W) property. This lets you define how much force created `Gibs` and any `Attachables` will get launched when the MOSRotating gibs. - -- New INI and Lua (R/W) properties for Attachables: - `ParentBreakWound = AEmitter...` allows you to optionally define different BreakWounds for the `Attachable` and its parent. By default it matches `BreakWound` for ease of use. - `InheritsHFlipped = -1/0/1` allows you to define whether the `Attachable` will inherit its parent's HFlipped value or not. -1 means reversed inheritance (i.e. if the parent's HFlipped value is true, this Attachable's HFlipped value will be false), 0 means no inheritance, 1 means normal inheritance. Defaults to 1 to preserve normal behaviour. - `InheritedRotAngleRadOffset = angle` and `InheritedRotAngleDegOffset = angle` allow you specify an offset to keep an `Attachable's` rotation at when `InheritsRotAngle` is set to true. In Lua there's only `InheritedRotAngleOffset` which takes/returns radians, to avoid confusion. For example, `InheritedRotAngleDegOffset = 90` would make the Attachable always face perpendicular to its parent. Does nothing if the `Attachable's` `InheritsRotAngle` is set to false or the `Attachable` has no parent. - `GibWithParentChance = 0 - 1` allows you to specify whether this `Attachable` should be gibbed when its parent does and what the chance of that happening is. 0 means never, 1 means always. - `ParentGibBlastStrengthMultiplier = number` allows you to specify the multiplier this `Attachable` will apply to its parent's gib blast strength when the parent gibs. Usually this would be a positive number, but it doesn't have to be. - -- New INI and Lua (R/W) `Arm` property `GripStrength`. This effectively replaces the `JointStrength` of the held `HeldDevice`, allowing `Arms` to control how tightly equipment is held. - -- New INI and Lua (R/W) `HeldDevice` property `GripStrengthMultiplier`. This allows `HeldDevices` to multiply the `GripStrength` of their `Arms` to support them being more or less easy to hold. - -- New Lua `MovableObject` function `GetWhichMOToNotHit`. This provides access to the MO that has been set to not be hit by `SetWhichMOToNotHit`. - -- Added `HeldDevice` handling to limit which `Actor(s)` can pick it up. Note that pickup limitations are all done by PresetName, so you can not use this to precisely specify individual `Actors`. - The INI definition looks like this: - ``` - PickupableBy = PickupableByEntries - AddPresetNameEntry = First Actor PresetName Here - AddPresetNameEntry = Second Actor PresetName Here - //Alternatively, if you want this not to be pickupable - PickupableBy = None - ``` - The Lua properties and functions are as follows: - ``` - heldDevice.HasPickupLimitations; --(R) Whether or not this HeldDevice has any limitations affecting whether it can be picked up. - heldDevice.UnPickupable --(R/W) Whether this HeldDevice is/should be pickupable. - heldDevice:IsPickupableBy(actor) -- Whether or not a given Actor can pick up this HeldDevice. - heldDevice:AddPickupableByPresetName(presetName) -- Allows Actors with the given PresetName to pick up this HeldDevice. - heldDevice:RemovePickupableByPresetName(presetName) -- Disallows Actors with the given PresetNames from picking up this HeldDevice (as long as there are other pickup limitations). - ``` - -- Added `MOSRotating` Lua (R) property `IndividualMass`. This provides access to the `MOSRotating's` actual mass value, not including any `Attachables` or inventory items. Note that the normal `Mass` property is still used to set the `MOSRotating's` mass. - -- Added `Actor` Lua (R) property `InventoryMass`. This provides access to the mass of the `Actor's` inventory separate from the `Actor's` actual mass. - - Added new lua `Vector` functions: `GetRadRotated(angle)` and `GetDegRotated(angle)`. They return a rotated copy of the vector without modifying it. ### Changed @@ -292,50 +236,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - `Scenes` with a `PresetName` containing the strings "Test", "Editor" and "Tutorial" are no longer excluded from the scenarios screen and from the MetaGame. -- Hands will now draw in transparent drawing mode, i.e. editing menu. - -- `AHuman` background `Leg` will no longer draw in front of the `AHuman`. The real result of this is that the background foot will no longer draw in front of the foreground one. - -- Everything draws better when flashing white, including craft which used to be terrible at it. - -- Reworked Attachable managment - `DamageMultiplier` on `Attachables` now works as expected, all `Attachables` can now transfer damage to their root parent. This will travel up chains of `Attachables`, as long as every `Attachable` in the chain has a non-zero DamageMultiplier (yes, negative numbers are supported if you wanna have healing instead of damage or weirdness with chaining negative multipliers). - `Attachable` terrain collision has been reworked so that it can be changed simply by setting `CollidesWithTerrainWhileAttached = true/false` in INI or Lua. Also, `Attachables` attached to other `Attachables` will now collide with terrain properly. - `BreakWounds` on `Attachables` now gets added to both the `Attachable` and the parent when the `Attachable` is broken off. If `ParentBreakWound` is defined, the parent will use this instead of the regular `BreakWound`. - -- `Attachable.BreakWound` now has R/W access in Lua. - -- `Attachable.DeleteWithParent` is now `Attachable.DeleteWhenRemovedFromParent`, since this more accurately describes what it does. - -- `Attachable.OnlyLinearForces` has been renamed to `Attachable.ApplyTransferredForcesAtOffset` and its effect has been reversed, so something that checked `OnlyLinearForces == true` would now check `ApplyTransferredForcesAtOffset == false`, since this makes more sense to use. - -- `Arms` and `Legs` on `AHumans` will no longer bleed out indefinitely. If you want this to happen, adjust their `BreakWound` or `ParentBreakWound` accordingly. - -- Reworked wound management - Wound management is now always done with `MOSRotating` functions, instead of requiring different ones for `Actors`. This means TotalWoundCount and RemoveAnyRandomWounds no longer exist. - You can get all wounds with `GetWounds`, get the wound count with `GetWoundCount` (or using the pre-existing WoundCount property), get the gib wound limit with `GetGibWoundLimit` (or using the pre-existing GibWoundLimit property), and remove wounds with `RemoveWounds`. - All of these functions have two variants, one lets you just specify any normal arguments (e.g. number of wounds to remove), the other lets you also specify whether you want to include `Attachables` with a positive `DamageMultiplier` (i.e. `Attachables` that damage their parent), `Attachables` with a negative `DamageMultiplier` (i.e. `Attachables` that heal their parent) or `Attachables` with no `DamageMultiplier` (i.e. `Attachables` that don't affect their parent). - Without any arguments, `GetWoundCount` and `RemoveWounds` will only include `Attachables` with a positive `DamageMultiplier` in their counting calculations, and `GetGibWoundLimit` will not include any `Attachables` in its counting calculations. The property variants (e.g. mosr.WoundCount) behave the same way as the no-argument versions. - Note that this process is recursive, so if an `Attachable` that satisfies the conditions has `Attachables` that also satisfy the conditions, their wounds will be included in the results. - -- Renamed `Turret` INI property `MountedMO` to `MountedDevice` to better match the new reality that `Turrets` can only mount `HeldDevices` and their child classes. - -- Renamed `ACrab` `LFGLeg`, `LBGLeg`, `RFGLeg` and `RBGLeg` Lua properties to `LeftFGLeg`, `LeftBGLeg`, `RightFGLeg`, `RightBGLeg` respectively, to be more consistent with other naming. - For the time being, the INI properties (as well as the ones for setting `FootGroups` and `LimbPaths`) support both single letter and written out versions (i.e. `LStandLimbPath` and `LeftStandLimbPath` are both supported). This single letter versions will probably be deprecated over time. - -- `MovableMan:AddMO` will now add `HeldDevices` (or any child class of `HeldDevice`) to its `Items` collection, making it able to provide the functionality of `AddParticle`, `AddActor` and `AddItem`. - -- Changed and cleaned up how gibbing works and how it affects `Attachables`. In particular, limbs will better inherit velocity during gibbing and things are more customizable. See `Attachable` properties for more details. - As an added bonus, `Attachables` on `ACDropShips` and `ACRockets` can now be shot down when the craft gibs; fight back against the baleful dropship engines! - -- Improved native recoil handling! Guns transfer recoil to arms/turrets, which transfer it to AHumans/ACrabs, all of it properly accounts for joint strengths (or grip strengths) and offsets at every step. ([Issue #7](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/issues/7) and [Issue #8](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/issues/8)). - -- `Attachables` now use their `GibImpulseLimit` as well as their `JointStrength` when determining whether they should be detached by strong forces. To maintain backwards compatibility, if the `GibImpulseLimit` is less than the `JointStrength`, the `JointStrength` will be used instead for this purpose. - -- The `FacingAngle` function has been moved from `Actor` to `MOSprite` so it can be used more widely. - -- Pressing escape at the options, mod manager, game editors and credits screens no longer quits the game. - ### Fixed - Fix crash when returning to `MetaGame` scenario screen after activity end. @@ -358,13 +258,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - The "woosh" sound played when switching actors from a distance will now take scene wrapping into account. Additionally, attempting to switch to previous or next actor with only one actor will play the more correct "error" sound. -- `MovableObject:SetWhichMOToNotHit` will now work properly for Attachables. They will also not hit the relevant MO. When they're removed, Attachables will check if they have the same MO for this value and, if so, unset it so they can hit that MO. - -- Craft sucking up objects now works properly again. - -- Getting the `Mass` of a `MOSRotating` has now been made more efficient. Additionally, `Attachables` of `Attachables` will now be included in Mass, so some things have gotten a lot heavier (e.g. Dummy Dreadnought). - -- The moment of inertia of `AtomGroups` now updates when the mass or Atoms change, meaning losing `Attachables` or changing mass will properly affect how rotational forces apply to MOSRotatings. +- Pressing escape at the options, mod manager, game editors and credits screens no longer quits the game. ### Removed @@ -382,24 +276,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Removed `Activity` property `FundsOfTeam#`, use `Team#Funds` instead. -- Removed `Attachable` Lua write capability for `AtomSubGroupID` as changing this can cause all kinds of problems, and `RotTarget` as this didn't actually work. - -- Removed `MaxLength` property from `Leg`, since it was a mostly unused leftover caused by Leg being originally copied from Arm, and was actually a fake setting that just set other properties. To replace it, set the following: - ``` - ContractedOffset = Vector - X = //Old MaxLength/2 - Y = 0 - ExtendedOffset = Vector - X = //Old MaxLength - Y = 0 - ``` - -- Removed `Attachable.RotTarget` from Lua and INI. The property never worked and no longer exists. - -- Removed `Attachable:CollectDamage`, `Attachable:TransferJointForces` and `Attachable:TransferJointImpulses` Lua function definitions. These are internal functions that should never have been exposed to Lua. - -- Removed `MOSRotating:ApplyForces` and `MOSRotating:ApplyImpulses` Lua functions. These are both internal functions that should never have been exposed to Lua. - *** ## [0.1.0 pre-release 2][0.1.0-pre2] - 2020/05/08 From 6891880cf1edcdc56c7059c65beb3c2d918b12b6 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 21 Jan 2021 21:01:18 -0400 Subject: [PATCH 113/144] Readded changelog updates --- CHANGELOG.md | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32f7f7d56..9e6aba9de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,14 +10,142 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Executable can be compiled as 64bit. +- New INI and Lua (R/W) properties for Attachables: + `TransfersDamageToParent = 0/1`. If enabled, the Attachable will act like hardcoded ones and transfer damage to its parent. For `Attachables` attached to other `Attachables`, the parent `Attachable` (and any of its parents, etc.) must have this enabled for it to affect the root parent. + `ParentBreakWound = AEmitter...`. Use this to define a BreakWound that will be applied to the `Attachable's` parent when the `Attachable` is removed. + `BreakWound` is also now R/W accessible to Lua. + +- Added Lua (R/W) properties for all hardcoded Attachables. You can now set them on the fly to be created objects of the relevant type. Note that trying to set things inappropriately (e.g. setting an HDFirearm as something's Leg) will probably crash the game; that's your problem to deal with. + You can read and write the following properties: + AHuman - `Head, Jetpack, FGArm, BGArm, FGLeg, BGLeg, FGFoot, BGFoot` + ACrab - `Turret, Jetpack, LeftFGLeg, LeftBGLeg, RightFGLeg, RightBGLeg` + ACDropship - `RightEngine, LeftEngine, RightThruster, LeftThruster, RightHatch, LeftHatch` + ACRocket - `RightLeg, LeftLeg, MainEngine, LeftEngine, RightEngine, LeftThruster, RightThruster` + ADoor - `Door` + Turret - `MountedDevice` + Leg - `Foot` + HDFirearm - `Magazine, Flash` + AEmitter - `Flash` + +- Added `Vector:ClampMagnitude(upperLimit, lowerLimit)` Lua function that lets you limit a Vector's upper and lower magnitude. + +- Added `MOSRotating GibBlastStrength` INI and Lua (R/W) property. This lets you define how much force created `Gibs` and any `Attachables` will get launched when the MOSRotating gibs. + +- New INI and Lua (R/W) properties for Attachables: + `ParentBreakWound = AEmitter...` allows you to optionally define different BreakWounds for the `Attachable` and its parent. By default it matches `BreakWound` for ease of use. + `InheritsHFlipped = -1/0/1` allows you to define whether the `Attachable` will inherit its parent's HFlipped value or not. -1 means reversed inheritance (i.e. if the parent's HFlipped value is true, this Attachable's HFlipped value will be false), 0 means no inheritance, 1 means normal inheritance. Defaults to 1 to preserve normal behaviour. + `InheritedRotAngleRadOffset = angle` and `InheritedRotAngleDegOffset = angle` allow you specify an offset to keep an `Attachable's` rotation at when `InheritsRotAngle` is set to true. In Lua there's only `InheritedRotAngleOffset` which takes/returns radians, to avoid confusion. For example, `InheritedRotAngleDegOffset = 90` would make the Attachable always face perpendicular to its parent. Does nothing if the `Attachable's` `InheritsRotAngle` is set to false or the `Attachable` has no parent. + `GibWithParentChance = 0 - 1` allows you to specify whether this `Attachable` should be gibbed when its parent does and what the chance of that happening is. 0 means never, 1 means always. + `ParentGibBlastStrengthMultiplier = number` allows you to specify the multiplier this `Attachable` will apply to its parent's gib blast strength when the parent gibs. Usually this would be a positive number, but it doesn't have to be. + +- New INI and Lua (R/W) `Arm` property `GripStrength`. This effectively replaces the `JointStrength` of the held `HeldDevice`, allowing `Arms` to control how tightly equipment is held. + +- New INI and Lua (R/W) `HeldDevice` property `GripStrengthMultiplier`. This allows `HeldDevices` to multiply the `GripStrength` of their `Arms` to support them being more or less easy to hold. + +- New Lua `MovableObject` function `GetWhichMOToNotHit`. This provides access to the MO that has been set to not be hit by `SetWhichMOToNotHit`. + +- Added `HeldDevice` handling to limit which `Actor(s)` can pick it up. Note that pickup limitations are all done by PresetName, so you can not use this to precisely specify individual `Actors`. + The INI definition looks like this: + ``` + PickupableBy = PickupableByEntries + AddPresetNameEntry = First Actor PresetName Here + AddPresetNameEntry = Second Actor PresetName Here + //Alternatively, if you want this not to be pickupable + PickupableBy = None + ``` + The Lua properties and functions are as follows: + ``` + heldDevice.HasPickupLimitations; --(R) Whether or not this HeldDevice has any limitations affecting whether it can be picked up. + heldDevice.UnPickupable --(R/W) Whether this HeldDevice is/should be pickupable. + heldDevice:IsPickupableBy(actor) -- Whether or not a given Actor can pick up this HeldDevice. + heldDevice:AddPickupableByPresetName(presetName) -- Allows Actors with the given PresetName to pick up this HeldDevice. + heldDevice:RemovePickupableByPresetName(presetName) -- Disallows Actors with the given PresetNames from picking up this HeldDevice (as long as there are other pickup limitations). + ``` + +- Added `MOSRotating` Lua (R) property `IndividualMass`. This provides access to the `MOSRotating's` actual mass value, not including any `Attachables` or inventory items. Note that the normal `Mass` property is still used to set the `MOSRotating's` mass. + +- Added `Actor` Lua (R) property `InventoryMass`. This provides access to the mass of the `Actor's` inventory separate from the `Actor's` actual mass. + ### Changed +- Hands will now draw in transparent drawing mode, i.e. editing menu. + +- `AHuman` background `Leg` will no longer draw in front of the `AHuman`. The real result of this is that the background foot will no longer draw in front of the foreground one. + +- Everything draws better when flashing white, including craft which used to be terrible at it. + +- Reworked Attachable managment + `DamageMultiplier` on `Attachables` now works as expected, all `Attachables` can now transfer damage to their root parent. This will travel up chains of `Attachables`, as long as every `Attachable` in the chain has a non-zero DamageMultiplier (yes, negative numbers are supported if you wanna have healing instead of damage or weirdness with chaining negative multipliers). + `Attachable` terrain collision has been reworked so that it can be changed simply by setting `CollidesWithTerrainWhileAttached = true/false` in INI or Lua. Also, `Attachables` attached to other `Attachables` will now collide with terrain properly. + `BreakWounds` on `Attachables` now gets added to both the `Attachable` and the parent when the `Attachable` is broken off. If `ParentBreakWound` is defined, the parent will use this instead of the regular `BreakWound`. + +- `Attachable.BreakWound` now has R/W access in Lua. + +- `Attachable.DeleteWithParent` is now `Attachable.DeleteWhenRemovedFromParent`, since this more accurately describes what it does. + +- `Attachable.OnlyLinearForces` has been renamed to `Attachable.ApplyTransferredForcesAtOffset` and its effect has been reversed, so something that checked `OnlyLinearForces == true` would now check `ApplyTransferredForcesAtOffset == false`, since this makes more sense to use. + +- `Arms` and `Legs` on `AHumans` will no longer bleed out indefinitely. If you want this to happen, adjust their `BreakWound` or `ParentBreakWound` accordingly. + +- Reworked wound management + Wound management is now always done with `MOSRotating` functions, instead of requiring different ones for `Actors`. This means TotalWoundCount and RemoveAnyRandomWounds no longer exist. + You can get all wounds with `GetWounds`, get the wound count with `GetWoundCount` (or using the pre-existing WoundCount property), get the gib wound limit with `GetGibWoundLimit` (or using the pre-existing GibWoundLimit property), and remove wounds with `RemoveWounds`. + All of these functions have two variants, one lets you just specify any normal arguments (e.g. number of wounds to remove), the other lets you also specify whether you want to include `Attachables` with a positive `DamageMultiplier` (i.e. `Attachables` that damage their parent), `Attachables` with a negative `DamageMultiplier` (i.e. `Attachables` that heal their parent) or `Attachables` with no `DamageMultiplier` (i.e. `Attachables` that don't affect their parent). + Without any arguments, `GetWoundCount` and `RemoveWounds` will only include `Attachables` with a positive `DamageMultiplier` in their counting calculations, and `GetGibWoundLimit` will not include any `Attachables` in its counting calculations. The property variants (e.g. mosr.WoundCount) behave the same way as the no-argument versions. + Note that this process is recursive, so if an `Attachable` that satisfies the conditions has `Attachables` that also satisfy the conditions, their wounds will be included in the results. + +- Renamed `Turret` INI property `MountedMO` to `MountedDevice` to better match the new reality that `Turrets` can only mount `HeldDevices` and their child classes. + +- Renamed `ACrab` `LFGLeg`, `LBGLeg`, `RFGLeg` and `RBGLeg` Lua properties to `LeftFGLeg`, `LeftBGLeg`, `RightFGLeg`, `RightBGLeg` respectively, to be more consistent with other naming. + For the time being, the INI properties (as well as the ones for setting `FootGroups` and `LimbPaths`) support both single letter and written out versions (i.e. `LStandLimbPath` and `LeftStandLimbPath` are both supported). This single letter versions will probably be deprecated over time. + +- `MovableMan:AddMO` will now add `HeldDevices` (or any child class of `HeldDevice`) to its `Items` collection, making it able to provide the functionality of `AddParticle`, `AddActor` and `AddItem`. + +- Changed and cleaned up how gibbing works and how it affects `Attachables`. In particular, limbs will better inherit velocity during gibbing and things are more customizable. See `Attachable` properties for more details. + As an added bonus, `Attachables` on `ACDropShips` and `ACRockets` can now be shot down when the craft gibs; fight back against the baleful dropship engines! + +- Improved native recoil handling! Guns transfer recoil to arms/turrets, which transfer it to AHumans/ACrabs, all of it properly accounts for joint strengths (or grip strengths) and offsets at every step. ([Issue #7](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/issues/7) and [Issue #8](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/issues/8)). + +- `Attachables` now use their `GibImpulseLimit` as well as their `JointStrength` when determining whether they should be detached by strong forces. To maintain backwards compatibility, if the `GibImpulseLimit` is less than the `JointStrength`, the `JointStrength` will be used instead for this purpose. + +- The `FacingAngle` function has been moved from `Actor` to `MOSprite` so it can be used more widely. + +- Lifetime and ToDelete now work on wounds, giving modders more control over them. + +- Pressing escape at the options, mod manager, game editors and credits screens no longer quits the game. + - Pressing escape when a buy menu is open now closes it instead of pausing the game. ### Fixed +- `MovableObject:SetWhichMOToNotHit` will now work properly for Attachables. They will also not hit the relevant MO. When they're removed, Attachables will check if they have the same MO for this value and, if so, unset it so they can hit that MO. + +- Craft sucking up objects now works properly again. + +- Getting the `Mass` of a `MOSRotating` has now been made more efficient. Additionally, `Attachables` of `Attachables` will now be included in Mass, so some things have gotten a lot heavier (e.g. Dummy Dreadnought). + +- The moment of inertia of `AtomGroups` now updates when the mass or Atoms change, meaning losing `Attachables` or changing mass will properly affect how rotational forces apply to MOSRotatings. + ### Removed +- Removed `Attachable` Lua write capability for `AtomSubGroupID` as changing this can cause all kinds of problems, and `RotTarget` as this didn't actually work. + +- Removed `MaxLength` property from `Leg`, since it was a mostly unused leftover caused by Leg being originally copied from Arm, and was actually a fake setting that just set other properties. To replace it, set the following: + ``` + ContractedOffset = Vector + X = //Old MaxLength/2 + Y = 0 + ExtendedOffset = Vector + X = //Old MaxLength + Y = 0 + ``` + +- Removed `Attachable.RotTarget` from Lua and INI. The property never worked and no longer exists. + +- Removed `Attachable:CollectDamage`, `Attachable:TransferJointForces` and `Attachable:TransferJointImpulses` Lua function definitions. These are internal functions that should never have been exposed to Lua. + +- Removed `MOSRotating:ApplyForces` and `MOSRotating:ApplyImpulses` Lua functions. These are both internal functions that should never have been exposed to Lua. + *** ## [0.1.0 pre-release 3.0][0.1.0-pre3.0] - 2020/12/25 @@ -311,8 +439,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - The "woosh" sound played when switching actors from a distance will now take scene wrapping into account. Additionally, attempting to switch to previous or next actor with only one actor will play the more correct "error" sound. -- Pressing escape at the options, mod manager, game editors and credits screens no longer quits the game. - - `HDFirearm` INI property `DeactivationSound` now works properly instead of constantly playing. - Gold mining sound has been set to restart its playback everytime it's played, making it way less annoying. It's still pretty wonky, but it's better. From 13734c3c8b29bf4ede86d070d80cdea7048c6886 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 21 Jan 2021 21:04:01 -0400 Subject: [PATCH 114/144] Fix previous changelog change a bit so the line I moved is correctly in pre3 not unreleased --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e6aba9de..3256fc6f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -112,8 +112,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Lifetime and ToDelete now work on wounds, giving modders more control over them. -- Pressing escape at the options, mod manager, game editors and credits screens no longer quits the game. - - Pressing escape when a buy menu is open now closes it instead of pausing the game. ### Fixed @@ -417,6 +415,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - `AddSound` and `SelectNextSoundSet` Lua bindings have been moved from `SoundContainer` to `SoundSet`. The latter has been renamed and the former have been trimmed down slightly since some complexity is no longer needed. Their speciifcs are mentioned in the `Added` section. +- Pressing escape at the options, mod manager, game editors and credits screens no longer quits the game. + ### Fixed - Fix crash when returning to `MetaGame` scenario screen after activity end. From 8b0125bad027b6e7f78b8f60d34de0d6e79b9a07 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 25 Jan 2021 23:44:41 -0400 Subject: [PATCH 115/144] Partially cleaned up Arm.h, and renamed a bit of stuff, also broke update out into sub-methods Cleaned up Arm.cpp Update so it's not a mess and will work properly with attachable changes. Also cleaned up various misc stuff in Arm.cpp Fixed FGArm draw order in AHuman by making it not draw normally, to avoid any oddities Tiny cleanup in Leg.cpp --- Entities/AHuman.cpp | 5 + Entities/Arm.cpp | 256 +++++++++++++------------------------------- Entities/Arm.h | 47 ++++---- Entities/Leg.cpp | 2 +- 4 files changed, 107 insertions(+), 203 deletions(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index b89676375..bd6c197f5 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -248,6 +248,7 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { AddAttachable(m_pFGArm); if (!m_pFGArm->GetDamageMultiplierSetInINI()) { m_pFGArm->SetDamageMultiplier(1.0F); } m_pFGArm->SetDrawnAfterParent(true); + m_pFGArm->SetDrawnNormallyByParent(false); } else if (propName == "BGArm") { RemoveAttachable(m_pBGArm); m_pBGArm = new Arm; @@ -4309,6 +4310,10 @@ void AHuman::DrawThrowingReticule(BITMAP *pTargetBitmap, const Vector &targetPos void AHuman::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { Actor::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + + // Note: For some reason the ordering of the attachables list can get messed up. The most important thing here is that the FGArm is on top of everything else. + if (m_pFGArm) { m_pFGArm->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } + //TODO simplify this complex if check when arm is cleaned up like turret so all it can hold are HeldDevices and children // Draw background Arm's hand after the HeldDevice of FGArm is drawn if the FGArm is holding a weapon. DrawMode realMode = (mode == g_DrawColor && m_FlashWhiteMS) ? g_DrawWhite : mode; diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 41d83a7d0..6a914bc92 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -32,10 +32,10 @@ void Arm::Clear() m_pHeldMO = nullptr; m_GripStrength = 0; m_HandFile.Reset(); - m_pHand = 0; + m_pHand = nullptr; m_MaxLength = 0; m_HandOffset.Reset(); - m_TargetPoint.Reset(); + m_TargetPosition.Reset(); m_IdleOffset.Reset(); m_MoveSpeed = 0; m_WillIdle = true; @@ -82,7 +82,7 @@ int Arm::Create(const Arm &reference) { m_MaxLength = reference.m_MaxLength; m_HandOffset = reference.m_HandOffset; - m_TargetPoint = reference.m_TargetPoint; + m_TargetPosition = reference.m_TargetPosition; m_IdleOffset = reference.m_IdleOffset; m_MoveSpeed = reference.m_MoveSpeed; @@ -249,7 +249,7 @@ MovableObject * Arm::ReleaseHeldMO() RemoveAttachable(dynamic_cast(m_pHeldMO)); } } - m_pHeldMO = 0; + m_pHeldMO = nullptr; return pReturnMO; } @@ -307,7 +307,7 @@ MovableObject * Arm::SwapHeldMO(MovableObject *newMO) void Arm::Reach(const Vector &scenePoint) { - m_TargetPoint = scenePoint; + m_TargetPosition = scenePoint; m_WillIdle = true; /* if (m_HFlipped) { @@ -317,7 +317,7 @@ void Arm::Reach(const Vector &scenePoint) else m_Pos += m_ParentOffset; - Vector reachVec(m_TargetPoint - m_Pos); + Vector reachVec(m_TargetPosition - m_Pos); return reachVec.GetMagnitude() <= m_MaxLength && reachVec.GetMagnitude() >= (m_MaxLength / 2); */ @@ -334,7 +334,7 @@ void Arm::Reach(const Vector &scenePoint) void Arm::ReachToward(const Vector &scenePoint) { - m_TargetPoint = scenePoint; + m_TargetPosition = scenePoint; m_WillIdle = false; /* if (m_HFlipped) { @@ -344,216 +344,112 @@ void Arm::ReachToward(const Vector &scenePoint) else m_Pos += m_ParentOffset; - Vector reachVec(m_TargetPoint - m_Pos); + Vector reachVec(m_TargetPosition - m_Pos); return reachVec.GetMagnitude() <= m_MaxLength && reachVec.GetMagnitude() >= (m_MaxLength / 2); */ } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Method: ConstrainHand -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Makes sure the hand distance is constrained between the max length of -// this Arm and half the max length. +void Arm::Update() { + if (!IsAttached()) { RemoveAttachable(dynamic_cast(m_pHeldMO), true, false); } -bool Arm::ConstrainHand() -{ - float halfMax = m_MaxLength / 2; - if (m_HandOffset.GetMagnitude() > m_MaxLength) { - m_HandOffset.SetMagnitude(m_MaxLength); - return false; - } - else if (m_HandOffset.GetMagnitude() < halfMax) { - m_HandOffset.SetMagnitude(halfMax + 0.1); - return true; - } - else - return true; -} + UpdateCurrentHandOffset(); + if (m_pHeldMO) { + // In order to keep the HeldDevice in the right place, we need to convert its offset (the hand offset) to work as the ParentOffset for the HeldDevice. + // The HeldDevice will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. + Vector handOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_HandOffset; + handOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); + dynamic_cast(m_pHeldMO)->SetParentOffset(handOffsetAsParentOffset); + } -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Update -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Updates this Arm. Supposed to be done every frame. + Attachable::Update(); -void Arm::Update() { + if (IsAttached()) { + if (dynamic_cast(m_pHeldMO)) { m_Recoiled = dynamic_cast(m_pHeldMO)->IsRecoiled(); } + // Need to manually specify the rotation here so the arm moves with its hand. Need to specify the position because the rotation has changed and RotateOffset will return different results. + m_Rotation = m_HandOffset.GetAbsRadAngle() + (m_HFlipped ? c_PI : 0); + m_Pos = m_JointPos - RotateOffset(m_JointOffset); + } - Attachable::Update(); + UpdateArmFrame(); +} - if (!m_Parent) { - // When arm is detached, let go of whatever it is holding - if (m_pHeldMO) { - m_pHeldMO->SetVel(m_Vel + Vector(-RandomNum(0.0F, 10.0F), -RandomNum(0.0F, 15.0F))); - m_pHeldMO->SetAngularVel(-7); - if (m_pHeldMO->IsDevice()) { RemoveAttachable(dynamic_cast(m_pHeldMO), true, false); } - m_pHeldMO = 0; - } - // Update hand - m_HandOffset.SetXY(m_MaxLength * 0.65, 0); - m_HandOffset.RadRotate((m_HFlipped ? c_PI : 0) + m_Rotation.GetRadAngle()); - } else { - // Attached, so act like it - - // If a Firearm or Shield device is held, but not a throwable, update it and arm configuration accordingly. - HeldDevice *pHeldDev = dynamic_cast(m_pHeldMO); - if (pHeldDev && !dynamic_cast(m_pHeldMO)) - { - // Indicate that the arm wasn't reaching for anything this frame. - m_DidReach = false; - pHeldDev->SetHFlipped(m_HFlipped); - - Vector handTarget(pHeldDev->GetStanceOffset()); - handTarget *= m_Rotation/* + m_pParent->GetRotMatrix()*/; - // handTarget.RadRotate(m_pParent->GetRotMatrix()); - - // Predict where the new muzzle position will be if we don't try to clear the muzzle of terrain - Vector newMuzzlePos = (m_JointPos + handTarget) - RotateOffset(pHeldDev->GetJointOffset()) + RotateOffset(pHeldDev->GetMuzzleOffset()); - // Adjust the hand offset back if necessary so that the weapon's muzzle doesn't poke into terrain - Vector midToMuzzle(pHeldDev->GetRadius(), 0); - midToMuzzle = RotateOffset(midToMuzzle); - - // Figure out where the back butt of the device will be without adjustment +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Arm::UpdateCurrentHandOffset() { + if (IsAttached()) { + Vector targetOffset; + if (m_pHeldMO && !dynamic_cast(m_pHeldMO)) { + const HeldDevice *heldDevice = dynamic_cast(m_pHeldMO); + targetOffset = heldDevice->GetStanceOffset() * m_Rotation; + + // In order to keep the held device from clipping through terrain, we need to determine where its muzzle position will be, and use that to figure out where its midpoint will be, as well as the distance between the two. + Vector newMuzzlePos = (m_JointPos + targetOffset) - RotateOffset(heldDevice->GetJointOffset()) + RotateOffset(heldDevice->GetMuzzleOffset()); + Vector midToMuzzle = RotateOffset({heldDevice->GetRadius(), 0}); Vector midOfDevice = newMuzzlePos - midToMuzzle; - // Trace from the back toward the muzzle, finding first pixel of impassable hardness - Vector freeMuzzlePos; - g_SceneMan.CastStrengthRay(midOfDevice, midToMuzzle, 5, freeMuzzlePos, 0, false); - Vector muzzleAdjustment = g_SceneMan.ShortestDistance(newMuzzlePos, freeMuzzlePos); - // Only apply if it's large enough - if (muzzleAdjustment.GetMagnitude() > 2.0F) - handTarget += muzzleAdjustment; - - // Interpolate the hand offset to the hand target - handTarget -= m_HandOffset; - m_HandOffset += handTarget * m_MoveSpeed; - - // Make sure the weapon cannot be extended beyond the reach of the arm. - ConstrainHand(); - - // In order to keep the HeldDevice in the right place, we need to convert its offset (the hand offset) to work as the ParentOffset for the HeldDevice. - // The HeldDevice will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. - Vector handOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_HandOffset; - handOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); - pHeldDev->SetParentOffset(handOffsetAsParentOffset); - - m_Recoiled = pHeldDev->IsRecoiled(); - - m_Rotation = (m_HFlipped ? c_PI : 0) + m_HandOffset.GetAbsRadAngle(); - - // Redo the positioning of the arm now since the rotation has changed and RotateOffset will return different results - m_Pos = m_JointPos - RotateOffset(m_JointOffset); - - // If it blew up or whatever, releaes it from hand and put into scene so it'll be cleaned up properly - if (m_pHeldMO && m_pHeldMO->IsSetToDelete()) - ReleaseHeldMO(); - } - // Adjust rotation and hand distance if reaching toward something. - else - { - // Not reaching toward anything - if (m_TargetPoint.IsZero()) - { - Vector moveVec(m_IdleOffset.GetXFlipped(m_HFlipped) - m_HandOffset); - m_HandOffset += moveVec * m_MoveSpeed; - m_DidReach = false; - } - else - { - Vector handTarget = g_SceneMan.ShortestDistance(m_JointPos, m_TargetPoint); - - // Check if handTarget is within arm's length. - if (handTarget.GetMagnitude() <= m_MaxLength || !m_WillIdle/* && handTarget.GetFloored() != m_HandOffset.GetFloored()*/) - { - Vector moveVec(handTarget - m_HandOffset); - m_HandOffset += moveVec * m_MoveSpeed; - m_DidReach = m_WillIdle; - } - else /*if (m_IdleOffset.GetXFlipped(m_HFlipped).GetFloored() != m_HandOffset.GetFloored())*/ - { - Vector moveVec(m_IdleOffset.GetXFlipped(m_HFlipped) - m_HandOffset); - m_HandOffset += moveVec * m_MoveSpeed; - m_DidReach = false; - } - } - // Cap hand distance to what the Arm allows - ConstrainHand(); - m_Rotation = (m_HFlipped ? c_PI : 0) + m_HandOffset.GetAbsRadAngle(); - - // Redo the positioning of the arm now since the rotation has changed and RotateOffset will return different results - m_Pos = m_JointPos - RotateOffset(m_JointOffset); - - // If holding something other than a FireArm, then update it - if (m_pHeldMO) { - Attachable *pHeldDev = dynamic_cast(m_pHeldMO); - - // In order to keep the HeldDevice in the right place, we need to convert its offset (the hand offset) to work as the ParentOffset for the HeldDevice. - // The HeldDevice will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. - Vector handOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_HandOffset; - handOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); - pHeldDev->SetParentOffset(handOffsetAsParentOffset); - - // If it blew up or whatever, release it from hand and put into scene so it'll be cleaned up properly - if (m_pHeldMO->IsSetToDelete()) - ReleaseHeldMO(); - } + Vector terrainOrMuzzlePosition; + g_SceneMan.CastStrengthRay(midOfDevice, midToMuzzle, 5, terrainOrMuzzlePosition, 0, false); + targetOffset += g_SceneMan.ShortestDistance(newMuzzlePos, terrainOrMuzzlePosition, g_SceneMan.SceneWrapsX()); + } else { + targetOffset = m_TargetPosition.IsZero() ? m_IdleOffset.GetXFlipped(m_HFlipped) : g_SceneMan.ShortestDistance(m_JointPos, m_TargetPosition, g_SceneMan.SceneWrapsX()); + if (m_WillIdle && !m_TargetPosition.IsZero() && targetOffset.GetMagnitude() > m_MaxLength) { targetOffset = m_IdleOffset.GetXFlipped(m_HFlipped); } } - - // Set correct frame for arm bend. - float halfMax = m_MaxLength / 2.0F; - int newFrame = static_cast(((m_HandOffset.GetMagnitude()- halfMax) / halfMax) * static_cast(m_FrameCount)); - if (newFrame < 0) { - newFrame = 0; - } - RTEAssert(newFrame <= m_FrameCount, "Arm frame is out of bounds for "+ GetClassName()+": "+ GetPresetName() + "."); - if (newFrame == m_FrameCount) { - --newFrame; - } - m_Frame = newFrame; + Vector distanceFromTargetOffsetToHandOffset(targetOffset - m_HandOffset); + m_HandOffset += distanceFromTargetOffsetToHandOffset * m_MoveSpeed; + m_HandOffset.ClampMagnitude(m_MaxLength, m_MaxLength / 2 + 0.1F); + } else { + m_HandOffset.SetXY(m_MaxLength * 0.65F, 0); + m_HandOffset.RadRotate((m_HFlipped ? c_PI : 0) + m_Rotation.GetRadAngle()); } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Draw -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this Arm's current graphical representation to a -// BITMAP of choice. +void Arm::UpdateArmFrame() { + if (IsAttached()) { + float halfMax = m_MaxLength / 2.0F; + //TODO this should be replaced with floor I think. If I remember right, casting float to int always rounds to 0, which should function the same but is harder to remember than clearly flooring it. + int newFrame = static_cast(((m_HandOffset.GetMagnitude() - halfMax) / halfMax) * static_cast(m_FrameCount)); + RTEAssert(newFrame <= m_FrameCount, "Arm frame is out of bounds for " + GetClassName() + ": " + GetPresetName() + "."); + m_Frame = std::clamp(static_cast(newFrame), 0U, m_FrameCount - 1); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Arm::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { Attachable::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); - if (m_pHeldMO || (!m_pHeldMO && !m_DidReach) || !m_Parent) { - if (!onlyPhysical && (mode == g_DrawColor || mode == g_DrawWhite || mode == g_DrawTrans)) { DrawHand(pTargetBitmap, targetPos, mode); } + + if (!onlyPhysical && (mode == g_DrawColor || mode == g_DrawWhite || mode == g_DrawTrans) && (!m_Parent || m_pHeldMO || (!m_pHeldMO && !m_DidReach))) { + DrawHand(pTargetBitmap, targetPos, mode); if (m_pHeldMO && m_pHeldMO->IsDrawnAfterParent()) { m_pHeldMO->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: DrawHand -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this Arm's hand's graphical representation to a BITMAP of -// choice. - -void Arm::DrawHand(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode) const { +void Arm::DrawHand(BITMAP *targetBitmap, const Vector &targetPos, DrawMode mode) const { Vector handPos(m_JointPos + m_HandOffset + (m_Recoiled ? m_RecoilOffset : Vector()) - targetPos); - handPos.m_X -= (m_pHand->w / 2) + 1; - handPos.m_Y -= (m_pHand->h / 2) + 1; + handPos.m_X -= static_cast((m_pHand->w / 2) + 1); + handPos.m_Y -= static_cast((m_pHand->h / 2) + 1); if (!m_HFlipped) { if (mode == g_DrawWhite) { - draw_character_ex(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY(), g_WhiteColor, -1); + draw_character_ex(targetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY(), g_WhiteColor, -1); } else { - draw_sprite(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY()); + draw_sprite(targetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY()); } } else { - //TODO this won't draw flipped. It should draw onto a temp bitmap and then draw that flipped. Maybe it can reuse a temp bitmap from MOSR, maybe not? + //TODO this draw_character_ex won't draw flipped. It should draw onto a temp bitmap and then draw that flipped. Maybe it can reuse a temp bitmap from MOSR, maybe not? if (mode == g_DrawWhite) { - draw_character_ex(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY(), g_WhiteColor, -1); + draw_character_ex(targetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY(), g_WhiteColor, -1); } else { - draw_sprite_h_flip(pTargetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY()); + draw_sprite_h_flip(targetBitmap, m_pHand, handPos.GetFloorIntX(), handPos.GetFloorIntY()); } } } diff --git a/Entities/Arm.h b/Entities/Arm.h index 236c637f2..9f1c1e266 100644 --- a/Entities/Arm.h +++ b/Entities/Arm.h @@ -314,7 +314,7 @@ ClassInfoGetters // Arguments: None. // Return value: Whether this Arm is holding anyhting. - bool IsReaching() { return !m_TargetPoint.IsZero(); } + bool IsReaching() { return !m_TargetPosition.IsZero(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -358,14 +358,9 @@ ClassInfoGetters bool HoldsSomething() { return m_pHeldMO != 0; } - -////////////////////////////////////////////////////////////////////////////////////////// -// Virtual method: Update -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Updates this MovableObject. Supposed to be done every frame. -// Arguments: None. -// Return value: None. - + /// + /// Updates this Arm. Supposed to be done every frame. + /// void Update() override; @@ -383,18 +378,13 @@ ClassInfoGetters void Draw(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; - -////////////////////////////////////////////////////////////////////////////////////////// -// Method: DrawHand -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Draws this Arm's hand's graphical representation to a BITMAP of -// choice. -// Arguments: A pointer to a BITMAP to draw on. -// The absolute position of the target bitmap's upper left corner in the Scene. -// In which mode to draw in. See the DrawMode enumeration for the modes. -// Return value: None. - - void DrawHand(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor) const; + /// + /// Draws this Arm's hand's graphical representation to a BITMAP of choice. + /// + /// A pointer to a BITMAP to draw on. + /// The absolute position of the target bitmap's upper left corner in the Scene. + /// Which mode to draw in. See the DrawMode enumeration for available modes. + void DrawHand(BITMAP *targetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor) const; ////////////////////////////////////////////////////////////////////////////////////////// // Protected member variable and method declarations @@ -432,7 +422,7 @@ ClassInfoGetters Vector m_HandOffset; // The target position that this Arm's hand is reaching after. // If (0, 0), the Arm is currently not reaching after anything. - Vector m_TargetPoint; + Vector m_TargetPosition; // The target offset relative to m_JointPos that this Arm's hand is moving to while not reaching for or doing anything else. Vector m_IdleOffset; // How fast the arm moves to a reach target, @@ -450,6 +440,19 @@ ClassInfoGetters private: +#pragma region Update Breakdown + /// + /// Updates the current hand offset for this Arm. Should only be called from Update. + /// If the Arm is attached, the current hand offset is based on the target offset and move speed, and whether the Arm should idle or not, otherwise it puts it in a reasonable position. + /// + void UpdateCurrentHandOffset(); + + /// + /// Updates the frame for this Arm. Should only be called from Update. + /// + void UpdateArmFrame(); +#pragma endregion + ////////////////////////////////////////////////////////////////////////////////////////// // Method: Clear ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index 425f64e3d..7bbb80e70 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -8,7 +8,7 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Leg::Clear() { - m_Foot = 0; + m_Foot = nullptr; m_ContractedOffset.Reset(); m_ExtendedOffset.Reset(); From 551528676b7cf1781bb66eeca0054e371a2a691d Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 29 Jan 2021 22:49:39 -0400 Subject: [PATCH 116/144] Flash didn't get flipped in the past to save on drawing resources or something, this change keeps that in place. --- Entities/AEmitter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Entities/AEmitter.cpp b/Entities/AEmitter.cpp index 0f0e57cc5..d51acf7da 100644 --- a/Entities/AEmitter.cpp +++ b/Entities/AEmitter.cpp @@ -172,6 +172,7 @@ int AEmitter::ReadProperty(std::string propName, Reader &reader) { AddAttachable(m_pFlash); m_pFlash->SetDrawnNormallyByParent(false); m_pFlash->SetInheritsRotAngle(false); + m_pFlash->SetInheritsHFlipped(0); m_pFlash->SetDeleteWhenRemovedFromParent(true); m_pFlash->SetCollidesWithTerrainWhileAttached(false); } From 34ceb4529dc2393373a6b3cd75dd97367b4b0842 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 30 Jan 2021 02:34:53 -0400 Subject: [PATCH 117/144] Probably fix guns' bullets hitting their parents when said guns get knocked out of hands due to forces --- Entities/HDFirearm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Entities/HDFirearm.cpp b/Entities/HDFirearm.cpp index 0e9e90278..b4b3e49e5 100644 --- a/Entities/HDFirearm.cpp +++ b/Entities/HDFirearm.cpp @@ -822,7 +822,7 @@ void HDFirearm::Update() // Set the fired particle to not hit this HeldDevice's parent, if applicable if (m_FireIgnoresThis) - pParticle->SetWhichMOToNotHit(pRootParent, 1.0f); + pParticle->SetWhichMOToNotHit(this, 1.0f); // Set the team so alarm events that happen if these gib won't freak out the guy firing pParticle->SetTeam(m_Team); From 779b7ae648bc6a824cda0c254f7b96248ea988b6 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 1 Feb 2021 13:39:30 -0400 Subject: [PATCH 118/144] Minor cleanup in Arm heldMO handling Make adding wounds default to damage multiplier of 1 if it's not defined in ini --- Entities/Arm.cpp | 5 +++-- Entities/MOSRotating.cpp | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 6a914bc92..1a4859c93 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -357,12 +357,13 @@ void Arm::Update() { UpdateCurrentHandOffset(); - if (m_pHeldMO) { + HeldDevice *heldDevice = m_pHeldMO ? dynamic_cast(m_pHeldMO) : nullptr; + if (heldDevice) { // In order to keep the HeldDevice in the right place, we need to convert its offset (the hand offset) to work as the ParentOffset for the HeldDevice. // The HeldDevice will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. Vector handOffsetAsParentOffset = RotateOffset(m_JointOffset) + m_HandOffset; handOffsetAsParentOffset.RadRotate(-m_Rotation.GetRadAngle()).FlipX(m_HFlipped); - dynamic_cast(m_pHeldMO)->SetParentOffset(handOffsetAsParentOffset); + heldDevice->SetParentOffset(handOffsetAsParentOffset); } Attachable::Update(); diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 457aff893..808b87ead 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -464,6 +464,7 @@ void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet GibThis(blast); return; } else { + if (!woundToAdd->GetDamageMultiplierSetInINI() && woundToAdd->GetDamageMultiplier() == 0.0F) { woundToAdd->SetDamageMultiplier(1.0F); } woundToAdd->SetCollidesWithTerrainWhileAttached(false); woundToAdd->SetParentOffset(parentOffsetToSet); woundToAdd->SetParent(this); From 2e53b3ca52d24f5a97039fc5e862259923b06fc8 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 1 Feb 2021 14:01:18 -0400 Subject: [PATCH 119/144] made it so particle wound damage multiplier actually multiplies wound's existing damage multiplier, instead of overwriting it --- Entities/MOSRotating.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 808b87ead..822af19c0 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -896,7 +896,7 @@ bool MOSRotating::ParticlePenetration(HitData &hd) // Add entry wound AEmitter to actor where the particle penetrated. AEmitter *pEntryWound = dynamic_cast(m_pEntryWound->Clone()); pEntryWound->SetEmitAngle(dir.GetXFlipped(m_HFlipped).GetAbsRadAngle() + c_PI); - pEntryWound->SetDamageMultiplier(hd.Body[HITOR]->WoundDamageMultiplier()); + pEntryWound->SetDamageMultiplier(pEntryWound->GetDamageMultiplier() * hd.Body[HITOR]->WoundDamageMultiplier()); // Adjust position so that it looks like the hole is actually *on* the Hitee. entryPos[dom] += increment[dom] * (pEntryWound->GetSpriteFrame()->w / 2); AddWound(pEntryWound, entryPos + m_SpriteOffset); @@ -915,7 +915,7 @@ bool MOSRotating::ParticlePenetration(HitData &hd) // Adjust position so that it looks like the hole is actually *on* the Hitee. exitPos[dom] -= increment[dom] * (pExitWound->GetSpriteFrame()->w / 2); pExitWound->SetEmitAngle(dir.GetXFlipped(m_HFlipped).GetAbsRadAngle()); - pExitWound->SetDamageMultiplier(hd.Body[HITOR]->WoundDamageMultiplier()); + pExitWound->SetDamageMultiplier(pExitWound->GetDamageMultiplier() * hd.Body[HITOR]->WoundDamageMultiplier()); AddWound(pExitWound, exitPos + m_SpriteOffset); pExitWound = 0; } From c35f4495692c5a5452b53351573a02cd786e22c4 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 1 Feb 2021 14:49:01 -0400 Subject: [PATCH 120/144] Fix damage multiplier setting on wounds so it works properly in collision wound creation and breakwound creation --- Entities/MOSRotating.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 822af19c0..5dce79a68 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -464,7 +464,6 @@ void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet GibThis(blast); return; } else { - if (!woundToAdd->GetDamageMultiplierSetInINI() && woundToAdd->GetDamageMultiplier() == 0.0F) { woundToAdd->SetDamageMultiplier(1.0F); } woundToAdd->SetCollidesWithTerrainWhileAttached(false); woundToAdd->SetParentOffset(parentOffsetToSet); woundToAdd->SetParent(this); @@ -896,7 +895,8 @@ bool MOSRotating::ParticlePenetration(HitData &hd) // Add entry wound AEmitter to actor where the particle penetrated. AEmitter *pEntryWound = dynamic_cast(m_pEntryWound->Clone()); pEntryWound->SetEmitAngle(dir.GetXFlipped(m_HFlipped).GetAbsRadAngle() + c_PI); - pEntryWound->SetDamageMultiplier(pEntryWound->GetDamageMultiplier() * hd.Body[HITOR]->WoundDamageMultiplier()); + float damageMultiplier = pEntryWound->GetDamageMultiplierSetInINI() ? pEntryWound->GetDamageMultiplier() : 1.0F; + pEntryWound->SetDamageMultiplier(damageMultiplier * hd.Body[HITOR]->WoundDamageMultiplier()); // Adjust position so that it looks like the hole is actually *on* the Hitee. entryPos[dom] += increment[dom] * (pEntryWound->GetSpriteFrame()->w / 2); AddWound(pEntryWound, entryPos + m_SpriteOffset); @@ -915,7 +915,8 @@ bool MOSRotating::ParticlePenetration(HitData &hd) // Adjust position so that it looks like the hole is actually *on* the Hitee. exitPos[dom] -= increment[dom] * (pExitWound->GetSpriteFrame()->w / 2); pExitWound->SetEmitAngle(dir.GetXFlipped(m_HFlipped).GetAbsRadAngle()); - pExitWound->SetDamageMultiplier(pExitWound->GetDamageMultiplier() * hd.Body[HITOR]->WoundDamageMultiplier()); + float damageMultiplier = pExitWound->GetDamageMultiplierSetInINI() ? pExitWound->GetDamageMultiplier() : 1.0F; + pExitWound->SetDamageMultiplier(damageMultiplier * hd.Body[HITOR]->WoundDamageMultiplier()); AddWound(pExitWound, exitPos + m_SpriteOffset); pExitWound = 0; } @@ -1571,6 +1572,7 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, AEmitter *parentBreakWound = dynamic_cast(attachable->GetParentBreakWound()->Clone()); if (parentBreakWound) { parentBreakWound->SetEmitAngle((attachable->GetParentOffset() * m_Rotation).GetAbsRadAngle()); + if (!parentBreakWound->GetDamageMultiplierSetInINI()) { parentBreakWound->SetDamageMultiplier(1.0F); } AddWound(parentBreakWound, attachable->GetParentOffset(), false); parentBreakWound = nullptr; } @@ -1579,6 +1581,7 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, AEmitter *childBreakWound = dynamic_cast(attachable->GetBreakWound()->Clone()); if (childBreakWound) { childBreakWound->SetEmitAngle(attachable->GetJointOffset().GetAbsRadAngle()); + if (!childBreakWound->GetDamageMultiplierSetInINI()) { childBreakWound->SetDamageMultiplier(1.0F); } attachable->AddWound(childBreakWound, attachable->GetJointOffset()); childBreakWound = nullptr; } From ac592bf2d76d0b05a7a07ba57e327b0cc696c7c7 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 1 Feb 2021 15:28:48 -0400 Subject: [PATCH 121/144] Quick test to see if this fixes wound flipping? --- Entities/MOSRotating.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 5dce79a68..3b9bd4fde 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -466,6 +466,7 @@ void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet } else { woundToAdd->SetCollidesWithTerrainWhileAttached(false); woundToAdd->SetParentOffset(parentOffsetToSet); + woundToAdd->SetInheritsHFlipped(false); woundToAdd->SetParent(this); m_AttachableAndWoundMass += woundToAdd->GetMass(); m_Wounds.push_back(woundToAdd); From 79201114cf0a140cd232a140723c0abde172e268 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 1 Feb 2021 16:06:02 -0400 Subject: [PATCH 122/144] Make actor damage multiplier default to 1 so people don't have to add extra ini boilerplate --- Entities/Actor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index c91bf978e..25900885d 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -135,6 +135,8 @@ void Actor::Clear() m_StuckTimer.Reset(); m_FallTimer.Reset(); m_DigStrength = 1; + + m_DamageMultiplier = 1.0F; } From decda47455a41762df3e50d6f3ce4a66e5f19ace Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 1 Feb 2021 17:29:03 -0400 Subject: [PATCH 123/144] Added LimbPath EndSegCount that defines that count beyond which the corresponding footgroup should be disabled. The name sucks but this all needs renaming anyway. --- Entities/ACrab.cpp | 23 +++++++++++++++++++++++ Entities/ACrab.h | 4 ++++ Entities/AHuman.cpp | 13 +++++++++++++ Entities/AHuman.h | 2 ++ Entities/LimbPath.cpp | 9 +++++++-- Entities/LimbPath.h | 16 ++++++++++++---- 6 files changed, 61 insertions(+), 6 deletions(-) diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index 0833a14f0..cc7b01293 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -46,9 +46,13 @@ void ACrab::Clear() m_pRFGLeg = 0; m_pRBGLeg = 0; m_pLFGFootGroup = 0; + m_BackupLFGFootGroup = nullptr; m_pLBGFootGroup = 0; + m_BackupLBGFootGroup = nullptr; m_pRFGFootGroup = 0; + m_BackupRFGFootGroup = nullptr; m_pRBGFootGroup = 0; + m_BackupRBGFootGroup = nullptr; m_StrideSound.Reset(); m_pJetpack = 0; m_JetTimeTotal = 0.0; @@ -110,6 +114,11 @@ int ACrab::Create() } } + m_BackupLFGFootGroup = new AtomGroup; + m_BackupLBGFootGroup = new AtomGroup; + m_BackupRFGFootGroup = new AtomGroup; + m_BackupRBGFootGroup = new AtomGroup; + // Initalize the jump time left m_JetTimeLeft = m_JetTimeTotal; @@ -194,12 +203,20 @@ int ACrab::Create(const ACrab &reference) { m_pLFGFootGroup = dynamic_cast(reference.m_pLFGFootGroup->Clone()); m_pLFGFootGroup->SetOwner(this); + m_BackupLFGFootGroup = dynamic_cast(reference.m_BackupLFGFootGroup->Clone()); + m_BackupLFGFootGroup->SetOwner(this); m_pLBGFootGroup = dynamic_cast(reference.m_pLBGFootGroup->Clone()); m_pLBGFootGroup->SetOwner(this); + m_BackupLBGFootGroup = dynamic_cast(reference.m_BackupLBGFootGroup->Clone()); + m_BackupLBGFootGroup->SetOwner(this); m_pRFGFootGroup = dynamic_cast(reference.m_pRFGFootGroup->Clone()); m_pRFGFootGroup->SetOwner(this); + m_BackupRFGFootGroup = dynamic_cast(reference.m_BackupRFGFootGroup->Clone()); + m_BackupRFGFootGroup->SetOwner(this); m_pRBGFootGroup = dynamic_cast(reference.m_pRBGFootGroup->Clone()); m_pRBGFootGroup->SetOwner(this); + m_BackupRBGFootGroup = dynamic_cast(reference.m_BackupRBGFootGroup->Clone()); + m_BackupRBGFootGroup->SetOwner(this); m_StrideSound = reference.m_StrideSound; @@ -2433,6 +2450,12 @@ void ACrab::Update() if (m_Status == STABLE) { + // This exists to support disabling foot collisions if the limbpath has that flag set. + if ((m_pLFGFootGroup->GetAtomCount() == 0 && m_BackupLFGFootGroup->GetAtomCount() > 0) != m_Paths[LEFTSIDE][FGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pLFGFootGroup, m_BackupLFGFootGroup); } + if ((m_pLBGFootGroup->GetAtomCount() == 0 && m_BackupLBGFootGroup->GetAtomCount() > 0) != m_Paths[LEFTSIDE][BGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pLBGFootGroup, m_BackupLBGFootGroup); } + if ((m_pRFGFootGroup->GetAtomCount() == 0 && m_BackupRFGFootGroup->GetAtomCount() > 0) != m_Paths[RIGHTSIDE][FGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pRFGFootGroup, m_BackupRFGFootGroup); } + if ((m_pRBGFootGroup->GetAtomCount() == 0 && m_BackupRBGFootGroup->GetAtomCount() > 0) != m_Paths[RIGHTSIDE][BGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pRBGFootGroup, m_BackupRBGFootGroup); } + // WALKING if (m_MoveState == WALK) { diff --git a/Entities/ACrab.h b/Entities/ACrab.h index 676f61164..47c91bba6 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -527,9 +527,13 @@ int FirearmActivationDelay() const; Leg *m_pRBGLeg; // Limb AtomGroups. AtomGroup *m_pLFGFootGroup; + AtomGroup *m_BackupLFGFootGroup; AtomGroup *m_pLBGFootGroup; + AtomGroup *m_BackupLBGFootGroup; AtomGroup *m_pRFGFootGroup; + AtomGroup *m_BackupRFGFootGroup; AtomGroup *m_pRBGFootGroup; + AtomGroup *m_BackupRBGFootGroup; // The sound of the actor taking a step (think robot servo) SoundContainer m_StrideSound; // Jetpack booster. diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index bd6c197f5..be31e4e17 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -51,7 +51,9 @@ void AHuman::Clear() m_pFGHandGroup = 0; m_pBGHandGroup = 0; m_pFGFootGroup = 0; + m_BackupFGFootGroup = nullptr; m_pBGFootGroup = 0; + m_BackupBGFootGroup = nullptr; m_StrideSound.Reset(); m_ArmsState = WEAPON_READY; m_MoveState = STAND; @@ -121,6 +123,9 @@ int AHuman::Create() } } + m_BackupFGFootGroup = new AtomGroup; + m_BackupBGFootGroup = new AtomGroup; + // If empty-handed, equip first thing in inventory if (m_pFGArm && m_pFGArm->IsAttached() && !m_pFGArm->GetHeldMO()) { @@ -181,8 +186,12 @@ int AHuman::Create(const AHuman &reference) { m_pBGHandGroup->SetOwner(this); m_pFGFootGroup = dynamic_cast(reference.m_pFGFootGroup->Clone()); m_pFGFootGroup->SetOwner(this); + m_BackupFGFootGroup = dynamic_cast(reference.m_BackupFGFootGroup->Clone()); + m_BackupFGFootGroup->SetOwner(this); m_pBGFootGroup = dynamic_cast(reference.m_pBGFootGroup->Clone()); m_pBGFootGroup->SetOwner(this); + m_BackupBGFootGroup = dynamic_cast(reference.m_BackupBGFootGroup->Clone()); + m_BackupBGFootGroup->SetOwner(this); m_StrideSound = reference.m_StrideSound; @@ -3608,6 +3617,10 @@ void AHuman::Update() if (m_Status == STABLE && m_MoveState != NOMOVE) { + // This exists to support disabling foot collisions if the limbpath has that flag set. + if ((m_pFGFootGroup->GetAtomCount() == 0 && m_BackupFGFootGroup->GetAtomCount() > 0) != m_Paths[FGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pFGFootGroup, m_BackupFGFootGroup); } + if ((m_pBGFootGroup->GetAtomCount() == 0 && m_BackupBGFootGroup->GetAtomCount() > 0) != m_Paths[BGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pBGFootGroup, m_BackupBGFootGroup); } + // WALKING, OR WE ARE JETPACKING AND STUCK if (m_MoveState == WALK || (m_MoveState == JUMP && m_Vel.GetLargest() < 1.0)) { diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 8d49b3081..0e3427b9c 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -900,7 +900,9 @@ ClassInfoGetters AtomGroup *m_pFGHandGroup; AtomGroup *m_pBGHandGroup; AtomGroup *m_pFGFootGroup; + AtomGroup *m_BackupFGFootGroup; AtomGroup *m_pBGFootGroup; + AtomGroup *m_BackupBGFootGroup; // The sound of the actor taking a step (think robot servo) SoundContainer m_StrideSound; // Jetpack booster. diff --git a/Entities/LimbPath.cpp b/Entities/LimbPath.cpp index 3ed325cf4..7c1e52dc0 100644 --- a/Entities/LimbPath.cpp +++ b/Entities/LimbPath.cpp @@ -32,6 +32,7 @@ void LimbPath::Clear() m_StartSegCount = 0; m_Segments.clear(); // m_CurrentSegment = 0; + m_FootCollisionsDisabledSegment = -1; m_SegProgress = 0.0; for (int i = 0; i < SPEEDCOUNT; ++i) m_TravelSpeed[i] = 0.0; @@ -120,6 +121,8 @@ int LimbPath::Create(const LimbPath &reference) else m_CurrentSegment = m_Segments.end(); + m_FootCollisionsDisabledSegment = reference.m_FootCollisionsDisabledSegment; + m_SegProgress = reference.m_SegProgress; for (int i = 0; i < SPEEDCOUNT; ++i) m_TravelSpeed[i] = reference.m_TravelSpeed[i]; @@ -158,6 +161,8 @@ int LimbPath::ReadProperty(std::string propName, Reader &reader) m_TotalLength += segment.GetMagnitude(); if (m_Segments.size() >= m_StartSegCount) m_RegularLength += segment.GetMagnitude(); + } else if (propName == "EndSegCount") { + reader >> m_FootCollisionsDisabledSegment; } else if (propName == "SlowTravelSpeed") { @@ -417,7 +422,7 @@ void LimbPath::ReportProgress(const Vector &limbPos) // Description: Gets a value representing the total progress that has been made on // this entire path. If the path has ended, 0.0 is returned. -float LimbPath::GetTotalProgress() +float LimbPath::GetTotalProgress() const { if (m_Ended || IsStaticPoint()) return 0.0; @@ -439,7 +444,7 @@ float LimbPath::GetTotalProgress() // If progress has not been made past the starting segments, < 0 will // be returned. If the path has ended, 0.0 is returned. -float LimbPath::GetRegularProgress() +float LimbPath::GetRegularProgress() const { if (m_Ended || IsStaticPoint()) return 0.0; diff --git a/Entities/LimbPath.h b/Entities/LimbPath.h index e7ba324d1..3cba4f667 100644 --- a/Entities/LimbPath.h +++ b/Entities/LimbPath.h @@ -171,6 +171,12 @@ ClassInfoGetters // const Vector const * GetSegArray() const { return m_aSegments; } + /// + /// Gets whether or not foot collisions should be disabled, i.e. the limbpath's progress is greater than the FootCollisionsDisabledSegment value. + /// + /// Whether or not foot collisions should be disabled for this limbpath at its current progress. + bool FootCollisionsShouldBeDisabled() const { return m_FootCollisionsDisabledSegment >= 0 && m_FootCollisionsDisabledSegment <= static_cast(std::floorf(GetRegularProgress() * static_cast(GetSegCount()))); } + ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetSegProgress @@ -343,7 +349,7 @@ ClassInfoGetters // Return value: A float indicating the total progress made on the entire path, from // 0.0 to 1.0. If the path has ended, 0.0 is returned. - float GetTotalProgress(); + float GetTotalProgress() const; ////////////////////////////////////////////////////////////////////////////////////////// @@ -357,7 +363,7 @@ ClassInfoGetters // Return value: A float indicating the total progress made on the regular path, from // 0.0 to 1.0. If the path has ended, 0.0 is returned. - float GetRegularProgress(); + float GetRegularProgress() const; ////////////////////////////////////////////////////////////////////////////////////////// @@ -573,7 +579,7 @@ ClassInfoGetters // Arguments: None. // Return value: Whether this has been Create:ed yet. - bool IsInitialized() { return !m_Start.IsZero() || !m_Segments.empty(); } + bool IsInitialized() const { return !m_Start.IsZero() || !m_Segments.empty(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -585,7 +591,7 @@ ClassInfoGetters // Arguments: None. // Return value: None. - bool IsStaticPoint() { return m_Segments.empty(); } + bool IsStaticPoint() const { return m_Segments.empty(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -622,6 +628,8 @@ ClassInfoGetters // The iterator to the segment of the path that the limb ended up on the end of std::deque::iterator m_CurrentSegment; + int m_FootCollisionsDisabledSegment; //!< The segment after which foot collisions will be disabled for this limbpath, if it's for legs. + // Normalized measure of how far the limb has progressed toward the // current segment's target. 0.0 means its farther away than the // magnitude of the entire segment. 0.5 means it's half the mag of the segment From 63265a39172ded92fad751e215b50b31fd153493 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 2 Feb 2021 11:19:07 -0400 Subject: [PATCH 124/144] Fiddle with limbpath endsegcount so it counts back from the end for consistency --- Entities/LimbPath.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Entities/LimbPath.h b/Entities/LimbPath.h index 3cba4f667..15ad405ed 100644 --- a/Entities/LimbPath.h +++ b/Entities/LimbPath.h @@ -175,7 +175,7 @@ ClassInfoGetters /// Gets whether or not foot collisions should be disabled, i.e. the limbpath's progress is greater than the FootCollisionsDisabledSegment value. /// /// Whether or not foot collisions should be disabled for this limbpath at its current progress. - bool FootCollisionsShouldBeDisabled() const { return m_FootCollisionsDisabledSegment >= 0 && m_FootCollisionsDisabledSegment <= static_cast(std::floorf(GetRegularProgress() * static_cast(GetSegCount()))); } + bool FootCollisionsShouldBeDisabled() const { return m_FootCollisionsDisabledSegment >= 0 && (GetSegCount() - static_cast(std::floorf(GetRegularProgress() * static_cast(GetSegCount())))) <= m_FootCollisionsDisabledSegment; } ////////////////////////////////////////////////////////////////////////////////////////// From fa54a05f465f67f5e838735bc3e1d6fdac9fed90 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Tue, 2 Feb 2021 13:45:11 -0400 Subject: [PATCH 125/144] Changes to hopefully make limbpath endsegcount work better Added AtomGroup::RemoveAllAtoms and LimbPath::GetCurrentSegmentNumber, which do what one would expect --- Entities/AHuman.cpp | 21 ++++++++++++++++----- Entities/AtomGroup.h | 5 +++++ Entities/LimbPath.cpp | 15 +++++++++++++++ Entities/LimbPath.h | 8 +++++++- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index be31e4e17..182b128b2 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -123,9 +123,6 @@ int AHuman::Create() } } - m_BackupFGFootGroup = new AtomGroup; - m_BackupBGFootGroup = new AtomGroup; - // If empty-handed, equip first thing in inventory if (m_pFGArm && m_pFGArm->IsAttached() && !m_pFGArm->GetHeldMO()) { @@ -188,10 +185,12 @@ int AHuman::Create(const AHuman &reference) { m_pFGFootGroup->SetOwner(this); m_BackupFGFootGroup = dynamic_cast(reference.m_BackupFGFootGroup->Clone()); m_BackupFGFootGroup->SetOwner(this); + m_BackupFGFootGroup->SetLimbPos(reference.m_BackupFGFootGroup->GetLimbPos()); m_pBGFootGroup = dynamic_cast(reference.m_pBGFootGroup->Clone()); m_pBGFootGroup->SetOwner(this); m_BackupBGFootGroup = dynamic_cast(reference.m_BackupBGFootGroup->Clone()); m_BackupBGFootGroup->SetOwner(this); + m_BackupBGFootGroup->SetLimbPos(reference.m_BackupBGFootGroup->GetLimbPos()); m_StrideSound = reference.m_StrideSound; @@ -292,11 +291,17 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { m_pFGFootGroup = new AtomGroup(); reader >> m_pFGFootGroup; m_pFGFootGroup->SetOwner(this); + m_BackupFGFootGroup = new AtomGroup(*m_pFGFootGroup); + m_BackupFGFootGroup->RemoveAllAtoms(); + m_BackupFGFootGroup->SetLimbPos(m_pFGFootGroup->GetLimbPos()); } else if (propName == "BGFootGroup") { delete m_pBGFootGroup; m_pBGFootGroup = new AtomGroup(); reader >> m_pBGFootGroup; m_pBGFootGroup->SetOwner(this); + m_BackupBGFootGroup = new AtomGroup(*m_pBGFootGroup); + m_BackupBGFootGroup->RemoveAllAtoms(); + m_BackupBGFootGroup->SetLimbPos(m_pBGFootGroup->GetLimbPos()); } else if (propName == "StrideSound") { reader >> m_StrideSound; } else if (propName == "StandLimbPath") { @@ -3618,8 +3623,14 @@ void AHuman::Update() if (m_Status == STABLE && m_MoveState != NOMOVE) { // This exists to support disabling foot collisions if the limbpath has that flag set. - if ((m_pFGFootGroup->GetAtomCount() == 0 && m_BackupFGFootGroup->GetAtomCount() > 0) != m_Paths[FGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pFGFootGroup, m_BackupFGFootGroup); } - if ((m_pBGFootGroup->GetAtomCount() == 0 && m_BackupBGFootGroup->GetAtomCount() > 0) != m_Paths[BGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pBGFootGroup, m_BackupBGFootGroup); } + if ((m_pFGFootGroup->GetAtomCount() == 0 && m_BackupFGFootGroup->GetAtomCount() > 0) != m_Paths[FGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { + m_BackupFGFootGroup->SetLimbPos(m_pFGFootGroup->GetLimbPos()); + std::swap(m_pFGFootGroup, m_BackupFGFootGroup); + } + if ((m_pBGFootGroup->GetAtomCount() == 0 && m_BackupBGFootGroup->GetAtomCount() > 0) != m_Paths[BGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { + m_BackupBGFootGroup->SetLimbPos(m_pBGFootGroup->GetLimbPos()); + std::swap(m_pBGFootGroup, m_BackupBGFootGroup); + } // WALKING, OR WE ARE JETPACKING AND STUCK if (m_MoveState == WALK || (m_MoveState == JUMP && m_Vel.GetLargest() < 1.0)) diff --git a/Entities/AtomGroup.h b/Entities/AtomGroup.h index c0abeab54..6635281ba 100644 --- a/Entities/AtomGroup.h +++ b/Entities/AtomGroup.h @@ -201,6 +201,11 @@ namespace RTE { /// Whether any Atoms of that subgroup ID were found and removed. bool RemoveAtoms(long removeID); + /// + /// Removes all atoms in this AtomGroup, leaving it empty of Atoms. + /// + void RemoveAllAtoms() { m_Atoms.clear(); m_SubGroups.clear(); m_MomentOfInertia = 0.0F; m_StoredOwnerMass = 0.0F; } + /// /// Gets whether the AtomGroup contains a subgroup with the given subgroupID. /// diff --git a/Entities/LimbPath.cpp b/Entities/LimbPath.cpp index 7c1e52dc0..efde4a0c5 100644 --- a/Entities/LimbPath.cpp +++ b/Entities/LimbPath.cpp @@ -458,6 +458,21 @@ float LimbPath::GetRegularProgress() const } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int LimbPath::GetCurrentSegmentNumber() const { + int progress = 0; + if (!m_Ended && !IsStaticPoint()) { + for (deque::const_iterator itr = m_Segments.begin(); itr != m_CurrentSegment; ++itr) { + progress++; + } + } + return progress; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////////////////// // Method: SetSpeed ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/LimbPath.h b/Entities/LimbPath.h index 15ad405ed..aebee384f 100644 --- a/Entities/LimbPath.h +++ b/Entities/LimbPath.h @@ -175,7 +175,7 @@ ClassInfoGetters /// Gets whether or not foot collisions should be disabled, i.e. the limbpath's progress is greater than the FootCollisionsDisabledSegment value. /// /// Whether or not foot collisions should be disabled for this limbpath at its current progress. - bool FootCollisionsShouldBeDisabled() const { return m_FootCollisionsDisabledSegment >= 0 && (GetSegCount() - static_cast(std::floorf(GetRegularProgress() * static_cast(GetSegCount())))) <= m_FootCollisionsDisabledSegment; } + bool FootCollisionsShouldBeDisabled() const { return m_FootCollisionsDisabledSegment >= 0 && GetSegCount() - GetCurrentSegmentNumber() <= m_FootCollisionsDisabledSegment; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -365,6 +365,12 @@ ClassInfoGetters float GetRegularProgress() const; + /// + /// Gets the current segment as a number, rather than an iterator. + /// + /// The current segment as a number. + int GetCurrentSegmentNumber() const; + ////////////////////////////////////////////////////////////////////////////////////////// // Method: SetSegments From c9f347b170c77eb610ca7fca6e2d790696a5d2c5 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 3 Feb 2021 01:27:32 -0400 Subject: [PATCH 126/144] Added AHuman INI property CrouchLimbPathBG Added name to AHuman FGROUND and BGROUND enum to match lua binding Added AHuman GetLimbPath method that lets you get a limbpath by passing in its layer and movement state Added LimbPath start offset setter and cleaned up getter, and added method to get a segment by its index Used these AHuman and LimbPath methods to add appropriate lua bindings --- Entities/AHuman.cpp | 2 ++ Entities/AHuman.h | 11 ++++++++++- Entities/LimbPath.h | 33 ++++++++++++++++----------------- Managers/LuaMan.cpp | 6 ++++++ 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 182b128b2..df7d8c06d 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -312,6 +312,8 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { reader >> m_Paths[FGROUND][WALK]; } else if (propName == "CrouchLimbPath") { reader >> m_Paths[FGROUND][CROUCH]; + } else if (propName == "CrouchLimbPathBG") { + reader >> m_Paths[BGROUND][CROUCH]; } else if (propName == "CrawlLimbPath") { reader >> m_Paths[FGROUND][CRAWL]; } else if (propName == "ArmCrawlLimbPath") { diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 0e3427b9c..353656d07 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -73,7 +73,7 @@ enum ProneState PRONESTATECOUNT }; -enum +enum Layer { FGROUND = 0, BGROUND @@ -800,6 +800,15 @@ ClassInfoGetters void DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), int whichScreen = 0, bool playerControlled = false) override; + /// + /// Gets the LimbPath corresponding to the passed in Layer and MovementState values. + /// + /// Whether to get foreground or background LimbPath. + /// Which movement state to get the LimbPath for. + /// The LimbPath corresponding to the passed in Layer and MovementState values. + LimbPath * GetLimbPath(Layer foregroundBackground, MovementState movementState) { return &m_Paths[foregroundBackground][movementState]; } + + ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetLimbPathSpeed ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/LimbPath.h b/Entities/LimbPath.h index aebee384f..90f46eeaa 100644 --- a/Entities/LimbPath.h +++ b/Entities/LimbPath.h @@ -139,16 +139,17 @@ ClassInfoGetters void Destroy(bool notInherited = false) override; + /// + /// Gets the coordinates where the limb should start at the start of the LimbPath cycle, relative to the owning AtomGroup's local origin. + /// + /// A Vector with the start position. + const Vector & GetStartOffset() const { return m_Start; } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetStartOffset -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the coordinates where the limb should start at the start of the -// LimbPath cycle, relative to the owning AtomGroup's local origin. -// Arguments: None. -// Return value: A Vector with the start position. - - Vector GetStartOffset() const { return m_Start; } + /// + /// Sets the coordinates where the limb should start at the start of the LimbPath cycle, relative to the owning AtomGroup's local origin. + /// + /// A Vector with the new start offset. + void SetStartOffset(const Vector &newStartOffset) { m_Start = newStartOffset; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -162,14 +163,12 @@ ClassInfoGetters unsigned int GetSegCount() const { return m_Segments.size(); } -////////////////////////////////////////////////////////////////////////////////////////// -// Method: GetSegments -////////////////////////////////////////////////////////////////////////////////////////// -// Description: Gets the array of 'waypoints' or segments of this LimbPath. -// Arguments: None. -// Return value: An array of Vectors defining the path of this LimbPath. - -// const Vector const * GetSegArray() const { return m_aSegments; } + /// + /// Gets a pointer to the segment at the given index. Ownership is NOT transferred. + /// + /// The index of the segment to get. + /// A pointer to the segment at the given index. Ownership is NOT transferred. + Vector *GetSegment(int segmentIndex) { if (segmentIndex >= 0 && segmentIndex < m_Segments.size()) { return &m_Segments.at(segmentIndex); } return nullptr;} /// /// Gets whether or not foot collisions should be disabled, i.e. the limbpath's progress is greater than the FootCollisionsDisabledSegment value. diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 1d52f396e..7f50c0432 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -648,6 +648,11 @@ int LuaMan::Create() { .def("AddSound", (void (SoundSet:: *)(std::string const &soundFilePath, const Vector &offset, float minimumAudibleDistance, float attenuationStartDistance)) &SoundSet::AddSound) .def("AddSoundSet", &SoundSet::AddSoundSet), + class_("LimbPath") + .property("StartOffset", &LimbPath::GetStartOffset, &LimbPath::SetStartOffset) + .property("SegmentCount", &LimbPath::GetSegCount) + .def("GetSegment", &LimbPath::GetSegment), + ABSTRACTLUABINDING(SceneObject, Entity) .property("Pos", &SceneObject::GetPos, &SceneObject::SetPos) .property("HFlipped", &SceneObject::IsHFlipped, &SceneObject::SetHFlipped) @@ -1178,6 +1183,7 @@ int LuaMan::Create() { .def("LookForGold", &AHuman::LookForGold) .def("LookForMOs", &AHuman::LookForMOs) .def("IsOnScenePoint", &AHuman::IsOnScenePoint) + .def("GetLimbPath", &AHuman::GetLimbPath) .property("LimbPathPushForce", &AHuman::GetLimbPathPushForce, &AHuman::SetLimbPathPushForce) .def("GetLimbPathSpeed", &AHuman::GetLimbPathSpeed) .def("SetLimbPathSpeed", &AHuman::SetLimbPathSpeed), From 525326296956f72724489b4f01fcd98c58d5832e Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 3 Feb 2021 01:43:59 -0400 Subject: [PATCH 127/144] Cleaned up ACrab backup footgroup handling to match AHuman's and tweaked things slightly in both so it's cleaner --- Entities/ACrab.cpp | 35 ++++++++++++++++++++++++++--------- Entities/AHuman.cpp | 2 -- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index cc7b01293..df6034f6a 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -114,11 +114,6 @@ int ACrab::Create() } } - m_BackupLFGFootGroup = new AtomGroup; - m_BackupLBGFootGroup = new AtomGroup; - m_BackupRFGFootGroup = new AtomGroup; - m_BackupRBGFootGroup = new AtomGroup; - // Initalize the jump time left m_JetTimeLeft = m_JetTimeTotal; @@ -205,18 +200,22 @@ int ACrab::Create(const ACrab &reference) { m_pLFGFootGroup->SetOwner(this); m_BackupLFGFootGroup = dynamic_cast(reference.m_BackupLFGFootGroup->Clone()); m_BackupLFGFootGroup->SetOwner(this); + m_BackupLFGFootGroup->SetLimbPos(reference.m_BackupLFGFootGroup->GetLimbPos()); m_pLBGFootGroup = dynamic_cast(reference.m_pLBGFootGroup->Clone()); m_pLBGFootGroup->SetOwner(this); m_BackupLBGFootGroup = dynamic_cast(reference.m_BackupLBGFootGroup->Clone()); m_BackupLBGFootGroup->SetOwner(this); + m_BackupLBGFootGroup->SetLimbPos(reference.m_BackupLBGFootGroup->GetLimbPos()); m_pRFGFootGroup = dynamic_cast(reference.m_pRFGFootGroup->Clone()); m_pRFGFootGroup->SetOwner(this); m_BackupRFGFootGroup = dynamic_cast(reference.m_BackupRFGFootGroup->Clone()); m_BackupRFGFootGroup->SetOwner(this); + m_BackupRFGFootGroup->SetLimbPos(reference.m_BackupRFGFootGroup->GetLimbPos()); m_pRBGFootGroup = dynamic_cast(reference.m_pRBGFootGroup->Clone()); m_pRBGFootGroup->SetOwner(this); m_BackupRBGFootGroup = dynamic_cast(reference.m_BackupRBGFootGroup->Clone()); m_BackupRBGFootGroup->SetOwner(this); + m_BackupRBGFootGroup->SetLimbPos(reference.m_BackupRBGFootGroup->GetLimbPos()); m_StrideSound = reference.m_StrideSound; @@ -309,6 +308,9 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) m_pLBGFootGroup->Create(*m_pLFGFootGroup); m_pLFGFootGroup->SetOwner(this); m_pLBGFootGroup->SetOwner(this); + m_BackupLFGFootGroup = new AtomGroup(*m_pLFGFootGroup); + m_BackupLFGFootGroup->RemoveAllAtoms(); + m_BackupLBGFootGroup = new AtomGroup(*m_BackupLFGFootGroup); } else if (propName == "RFootGroup" || propName == "RightFootGroup") { delete m_pRFGFootGroup; delete m_pRBGFootGroup; @@ -318,6 +320,9 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) m_pRBGFootGroup->Create(*m_pRFGFootGroup); m_pRFGFootGroup->SetOwner(this); m_pRBGFootGroup->SetOwner(this); + m_BackupRFGFootGroup = new AtomGroup(*m_pRFGFootGroup); + m_BackupRFGFootGroup->RemoveAllAtoms(); + m_BackupRBGFootGroup = new AtomGroup(*m_BackupRFGFootGroup); } else if (propName == "StrideSound") { reader >> m_StrideSound; } else if (propName == "LStandLimbPath" || propName == "LeftStandLimbPath") { @@ -2451,10 +2456,22 @@ void ACrab::Update() if (m_Status == STABLE) { // This exists to support disabling foot collisions if the limbpath has that flag set. - if ((m_pLFGFootGroup->GetAtomCount() == 0 && m_BackupLFGFootGroup->GetAtomCount() > 0) != m_Paths[LEFTSIDE][FGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pLFGFootGroup, m_BackupLFGFootGroup); } - if ((m_pLBGFootGroup->GetAtomCount() == 0 && m_BackupLBGFootGroup->GetAtomCount() > 0) != m_Paths[LEFTSIDE][BGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pLBGFootGroup, m_BackupLBGFootGroup); } - if ((m_pRFGFootGroup->GetAtomCount() == 0 && m_BackupRFGFootGroup->GetAtomCount() > 0) != m_Paths[RIGHTSIDE][FGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pRFGFootGroup, m_BackupRFGFootGroup); } - if ((m_pRBGFootGroup->GetAtomCount() == 0 && m_BackupRBGFootGroup->GetAtomCount() > 0) != m_Paths[RIGHTSIDE][BGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { std::swap(m_pRBGFootGroup, m_BackupRBGFootGroup); } + if ((m_pLFGFootGroup->GetAtomCount() == 0 && m_BackupLFGFootGroup->GetAtomCount() > 0) != m_Paths[LEFTSIDE][FGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { + m_BackupLFGFootGroup->SetLimbPos(m_pLFGFootGroup->GetLimbPos()); + std::swap(m_pLFGFootGroup, m_BackupLFGFootGroup); + } + if ((m_pLBGFootGroup->GetAtomCount() == 0 && m_BackupLBGFootGroup->GetAtomCount() > 0) != m_Paths[LEFTSIDE][BGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { + m_BackupLBGFootGroup->SetLimbPos(m_pLBGFootGroup->GetLimbPos()); + std::swap(m_pLBGFootGroup, m_BackupLBGFootGroup); + } + if ((m_pRFGFootGroup->GetAtomCount() == 0 && m_BackupRFGFootGroup->GetAtomCount() > 0) != m_Paths[RIGHTSIDE][FGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { + m_BackupRFGFootGroup->SetLimbPos(m_pRFGFootGroup->GetLimbPos()); + std::swap(m_pRFGFootGroup, m_BackupRFGFootGroup); + } + if ((m_pRBGFootGroup->GetAtomCount() == 0 && m_BackupRBGFootGroup->GetAtomCount() > 0) != m_Paths[RIGHTSIDE][BGROUND][m_MoveState].FootCollisionsShouldBeDisabled()) { + m_BackupRBGFootGroup->SetLimbPos(m_pRBGFootGroup->GetLimbPos()); + std::swap(m_pRBGFootGroup, m_BackupRBGFootGroup); + } // WALKING if (m_MoveState == WALK) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index df7d8c06d..b7a501996 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -293,7 +293,6 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { m_pFGFootGroup->SetOwner(this); m_BackupFGFootGroup = new AtomGroup(*m_pFGFootGroup); m_BackupFGFootGroup->RemoveAllAtoms(); - m_BackupFGFootGroup->SetLimbPos(m_pFGFootGroup->GetLimbPos()); } else if (propName == "BGFootGroup") { delete m_pBGFootGroup; m_pBGFootGroup = new AtomGroup(); @@ -301,7 +300,6 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { m_pBGFootGroup->SetOwner(this); m_BackupBGFootGroup = new AtomGroup(*m_pBGFootGroup); m_BackupBGFootGroup->RemoveAllAtoms(); - m_BackupBGFootGroup->SetLimbPos(m_pBGFootGroup->GetLimbPos()); } else if (propName == "StrideSound") { reader >> m_StrideSound; } else if (propName == "StandLimbPath") { From c8e5f73541447bcc42102e91d63c815768598384 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 3 Feb 2021 01:44:50 -0400 Subject: [PATCH 128/144] Added GetLimbPath for ACrab and added names for Side and Layer enums Added lua binding for acrab getlimbpath Cleaned up variable names and comments for ahuman getlimbpath --- Entities/ACrab.h | 14 ++++++++++++-- Entities/AHuman.h | 4 ++-- Managers/LuaMan.cpp | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Entities/ACrab.h b/Entities/ACrab.h index 47c91bba6..b6100ff53 100644 --- a/Entities/ACrab.h +++ b/Entities/ACrab.h @@ -46,13 +46,13 @@ class ACrab : MOVEMENTSTATECOUNT }; - enum { + enum Side { LEFTSIDE = 0, RIGHTSIDE, SIDECOUNT }; - enum { + enum Layer { FGROUND = 0, BGROUND, LAYERCOUNT @@ -463,6 +463,16 @@ int FirearmActivationDelay() const; void DrawHUD(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), int whichScreen = 0, bool playerControlled = false) override; + /// + /// Gets the LimbPath corresponding to the passed in Side, Layer and MovementState values. + /// + /// Whether to get the left or right side. + /// Whether to get foreground or background LimbPath. + /// Which movement state to get the LimbPath for. + /// The LimbPath corresponding to the passed in Layer and MovementState values. + LimbPath *GetLimbPath(Side side, Layer layer, MovementState movementState) { return &m_Paths[side][layer][movementState]; } + + ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetLimbPathSpeed ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 353656d07..62ce2d44f 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -803,10 +803,10 @@ ClassInfoGetters /// /// Gets the LimbPath corresponding to the passed in Layer and MovementState values. /// - /// Whether to get foreground or background LimbPath. + /// Whether to get foreground or background LimbPath. /// Which movement state to get the LimbPath for. /// The LimbPath corresponding to the passed in Layer and MovementState values. - LimbPath * GetLimbPath(Layer foregroundBackground, MovementState movementState) { return &m_Paths[foregroundBackground][movementState]; } + LimbPath * GetLimbPath(Layer layer, MovementState movementState) { return &m_Paths[layer][movementState]; } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index 7f50c0432..d83475a8d 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1260,6 +1260,7 @@ int LuaMan::Create() { .def("Look", &ACrab::Look) .def("LookForMOs", &ACrab::LookForMOs) .def("IsOnScenePoint", &ACrab::IsOnScenePoint) + .def("GetLimbPath", &ACrab::GetLimbPath) .property("LimbPathPushForce", &ACrab::GetLimbPathPushForce, &ACrab::SetLimbPathPushForce) .def("GetLimbPathSpeed", &ACrab::GetLimbPathSpeed) .def("SetLimbPathSpeed", &ACrab::SetLimbPathSpeed), From fc06ae7479a2b95ae7bae555a59f3fd32781f7a4 Mon Sep 17 00:00:00 2001 From: fourZK Date: Wed, 3 Feb 2021 18:44:04 +0200 Subject: [PATCH 129/144] Added unique rotation target for when crouching but still --- Entities/AHuman.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index b7a501996..524fadad9 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -4215,13 +4215,26 @@ void AHuman::Update() } } // Upright body posture - else - { - // Break the spring if close to target angle. - if (fabs(rot) > 0.1) - m_AngularVel -= rot * 0.5;//fabs(rot); - else if (fabs(m_AngularVel) > 0.3) - m_AngularVel *= 0.5; + else + { + // Hunch slightly if crouching but still + if (m_MoveState == CROUCH) + { + float rotTarget = m_HFlipped ? c_QuarterPI : -c_QuarterPI; + float rotDiff = rot - rotTarget; + if (fabs(rotDiff) > 0.1) + m_AngularVel -= rotDiff * 0.5; + else if (fabs(m_AngularVel) > 0.3) + m_AngularVel *= 0.5; + } + else + { + if (fabs(rot) > 0.1) + m_AngularVel -= rot * 0.5; + // Break the spring if close to target angle. + else if (fabs(m_AngularVel) > 0.3) + m_AngularVel *= 0.5; + } } } // Keel over From 7707f0fa6e2ca2ad580ef651390599de0458ee05 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 5 Feb 2021 01:28:52 -0400 Subject: [PATCH 130/144] Add AHuman m_RotAngleTargets for setting desired rot angles for differnt movement states Added ini properties for setting rot angle targets. These are the only ones that work currently Added lua bindings for getting and setting ahuman RotAngleTarget --- Entities/AHuman.cpp | 34 ++++++++++++++++------------------ Entities/AHuman.h | 15 +++++++++++++++ Managers/LuaMan.cpp | 4 +++- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 524fadad9..e3a587585 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -64,6 +64,7 @@ void AHuman::Clear() m_Paths[BGROUND][i].Reset(); m_Paths[FGROUND][i].Terminate(); m_Paths[BGROUND][i].Terminate(); + m_RotAngleTargets[i] = 0.0F; } m_Aiming = false; m_ArmClimbing[FGROUND] = false; @@ -201,6 +202,7 @@ int AHuman::Create(const AHuman &reference) { for (int i = 0; i < MOVEMENTSTATECOUNT; ++i) { m_Paths[FGROUND][i].Create(reference.m_Paths[FGROUND][i]); m_Paths[BGROUND][i].Create(reference.m_Paths[BGROUND][i]); + m_RotAngleTargets[i] = reference.m_RotAngleTargets[i]; } m_GoldInInventoryChunk = reference.m_GoldInInventoryChunk; @@ -322,6 +324,14 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { reader >> m_Paths[FGROUND][JUMP]; } else if (propName == "DislodgeLimbPath") { reader >> m_Paths[FGROUND][DISLODGE]; + } else if (propName == "StandRotAngleTarget") { + reader >> m_RotAngleTargets[STAND]; + } else if (propName == "WalkRotAngleTarget") { + reader >> m_RotAngleTargets[WALK]; + } else if (propName == "CrouchRotAngleTarget") { + reader >> m_RotAngleTargets[CROUCH]; + } else if (propName == "JumpRotAngleTarget") { + reader >> m_RotAngleTargets[JUMP]; } else { return Actor::ReadProperty(propName, reader); } @@ -4217,24 +4227,12 @@ void AHuman::Update() // Upright body posture else { - // Hunch slightly if crouching but still - if (m_MoveState == CROUCH) - { - float rotTarget = m_HFlipped ? c_QuarterPI : -c_QuarterPI; - float rotDiff = rot - rotTarget; - if (fabs(rotDiff) > 0.1) - m_AngularVel -= rotDiff * 0.5; - else if (fabs(m_AngularVel) > 0.3) - m_AngularVel *= 0.5; - } - else - { - if (fabs(rot) > 0.1) - m_AngularVel -= rot * 0.5; - // Break the spring if close to target angle. - else if (fabs(m_AngularVel) > 0.3) - m_AngularVel *= 0.5; - } + float rotDiff = rot - (GetRotAngleTarget(m_MoveState) * GetFlipFactor()); + if (fabs(rotDiff) > 0.1F) { + m_AngularVel -= rotDiff * 0.5F; + } else if (fabs(m_AngularVel) > 0.3F) { + m_AngularVel *= 0.5F; + } } } // Keel over diff --git a/Entities/AHuman.h b/Entities/AHuman.h index 62ce2d44f..6df16f708 100644 --- a/Entities/AHuman.h +++ b/Entities/AHuman.h @@ -850,6 +850,20 @@ ClassInfoGetters void SetLimbPathPushForce(float force); + /// + /// Gets the target rot angle for the given MovementState. + /// + /// The MovementState to get the rot angle target for. + /// The target rot angle for the given MovementState. + float GetRotAngleTarget(MovementState movementState) { return m_RotAngleTargets.at(movementState); } + + /// + /// Sets the target rot angle for the given MovementState. + /// + /// The MovementState to get the rot angle target for. + /// The new rot angle target to use. + void SetRotAngleTarget(MovementState movementState, float newRotAngleTarget) { m_RotAngleTargets.at(movementState) = newRotAngleTarget; } + /// /// Gets the duration it takes this AHuman to fully charge a throw. /// @@ -935,6 +949,7 @@ ClassInfoGetters // Limb paths for different movement states. // [0] is for the foreground limbs, and [1] is for BG. LimbPath m_Paths[2][MOVEMENTSTATECOUNT]; + std::array m_RotAngleTargets; //!< An array of rot angle targets for different movement states. // Whether was aiming during the last frame too. bool m_Aiming; // Whether the BG Arm is helping with locomotion or not. diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index d83475a8d..c7965eb4e 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -1186,7 +1186,9 @@ int LuaMan::Create() { .def("GetLimbPath", &AHuman::GetLimbPath) .property("LimbPathPushForce", &AHuman::GetLimbPathPushForce, &AHuman::SetLimbPathPushForce) .def("GetLimbPathSpeed", &AHuman::GetLimbPathSpeed) - .def("SetLimbPathSpeed", &AHuman::SetLimbPathSpeed), + .def("SetLimbPathSpeed", &AHuman::SetLimbPathSpeed) + .def("GetRotAngleTarget", &AHuman::GetRotAngleTarget) + .def("SetRotAngleTarget", &AHuman::SetRotAngleTarget), CONCRETELUABINDING(ACrab, Actor) // These are all private/protected so they can't be bound, need to consider making them public. From 0b6b6b9925d0a8b613b1a92eef43c65f46aba68a Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 5 Feb 2021 02:10:03 -0400 Subject: [PATCH 131/144] Fixed mass handling so changing mass on attachables of attachables will propagate it back up through the chain and to the top level parent. Also made attachable setmass do nothing if the new mass is the same as the current, for efficiency purposes --- Entities/Attachable.cpp | 13 ++++++++++++- Entities/Attachable.h | 7 +++++++ Entities/MOSRotating.h | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index 85454fd49..e8b1e3cfc 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -336,8 +336,19 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Attachable::SetMass(const float newMass) { + float currentMass = GetMass(); + if (newMass != currentMass) { + float previousMassForUpdatingParent = m_Parent ? currentMass : 0.0F; + MovableObject::SetMass(newMass); + if (m_Parent) { m_Parent->UpdateAttachableAndWoundMass(previousMassForUpdatingParent, GetMass()); } + } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::UpdateAttachableAndWoundMass(float oldAttachableOrWoundMass, float newAttachableOrWoundMass) { float previousMassForUpdatingParent = m_Parent ? GetMass() : 0.0F; - MovableObject::SetMass(newMass); + MOSRotating::UpdateAttachableAndWoundMass(oldAttachableOrWoundMass, newAttachableOrWoundMass); if (m_Parent) { m_Parent->UpdateAttachableAndWoundMass(previousMassForUpdatingParent, GetMass()); } } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index b1db35a8e..f709b4b2b 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -386,6 +386,13 @@ namespace RTE { /// A float specifying the new mass value in Kilograms (kg). void SetMass(const float newMass) final; + /// + /// Updates the total mass of Attachables and wounds for this Attachable, intended to be used when Attachables' masses get modified. Simply subtracts the old mass and adds the new one. + /// + /// The mass the Attachable or wound had before its mass was modified. + /// The up-to-date mass of the Attachable or wound after its mass was modified. + void UpdateAttachableAndWoundMass(float oldAttachableOrWoundMass, float newAttachableOrWoundMass) final; + /// /// Adds the passed in Attachable the list of Attachables and sets its parent to this Attachable. /// diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index ce5b94fdd..bea16ba10 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -153,7 +153,7 @@ ClassInfoGetters /// /// The mass the Attachable or wound had before its mass was modified. /// The up-to-date mass of the Attachable or wound after its mass was modified. - void UpdateAttachableAndWoundMass(float oldAttachableOrWoundMass, float newAttachableOrWoundMass) { m_AttachableAndWoundMass += newAttachableOrWoundMass - oldAttachableOrWoundMass; } + virtual void UpdateAttachableAndWoundMass(float oldAttachableOrWoundMass, float newAttachableOrWoundMass) { m_AttachableAndWoundMass += newAttachableOrWoundMass - oldAttachableOrWoundMass; } /// /// Gets the MOIDs of this MOSRotating and all its Attachables and Wounds, putting them into the MOIDs vector. From bb7e740f2871a3a57315d40328089f9d170bd947 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 5 Feb 2021 02:16:07 -0400 Subject: [PATCH 132/144] Made Turret MountedMO always draw at the end if it's set to draw after parent. It actually double draws, which is a waste, but that'll be fixed in the future sometime. --- Entities/Turret.cpp | 8 ++++++++ Entities/Turret.h | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/Entities/Turret.cpp b/Entities/Turret.cpp index f7324ab0d..a9fa64285 100644 --- a/Entities/Turret.cpp +++ b/Entities/Turret.cpp @@ -83,4 +83,12 @@ namespace RTE { if (m_MountedDevice) { m_MountedDevice->SetRotAngle(m_Rotation.GetRadAngle() + m_MountedDeviceRotOffset); } Attachable::Update(); } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Turret::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { + Attachable::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + //TODO replace this with a relative draw order property or something that lets you organize attachable drawing so it doesn't need special hardcoding crap. Use this for ahuman limbs and arm held mo if possible. + if (m_MountedDevice && m_MountedDevice->IsDrawnAfterParent()) { m_MountedDevice->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } + } } \ No newline at end of file diff --git a/Entities/Turret.h b/Entities/Turret.h index fdf4616de..f4386f7e4 100644 --- a/Entities/Turret.h +++ b/Entities/Turret.h @@ -88,6 +88,15 @@ namespace RTE { /// Updates this MovableObject. Supposed to be done every frame. /// void Update() override; + + /// + /// Draws this Turret's current graphical representation to a BITMAP of choice. + /// + /// A pointer to a BITMAP to draw on. + /// The absolute position of the target bitmap's upper left corner in the Scene. + /// In which mode to draw in. See the DrawMode enumeration for the modes. + /// Whether to not draw any extra 'ghost' items of this MovableObject, indicator arrows or hovering HUD text and so on. + void Draw(BITMAP *pTargetBitmap, const Vector &targetPos = Vector(), DrawMode mode = g_DrawColor, bool onlyPhysical = false) const override; #pragma endregion protected: From f3d6c2d229867fbf396d301d52eb766dc20effaf Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 5 Feb 2021 21:19:57 -0400 Subject: [PATCH 133/144] Fixed Arm update so TDs aren't wonky. Also clean up some logic so it's generally clearer what's going on in here --- Entities/Arm.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 1a4859c93..0e0334e6e 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -358,6 +358,11 @@ void Arm::Update() { UpdateCurrentHandOffset(); HeldDevice *heldDevice = m_pHeldMO ? dynamic_cast(m_pHeldMO) : nullptr; + const ThrownDevice *thrownDevice = heldDevice ? dynamic_cast(heldDevice) : nullptr; + + // HeldDevices need to use the aim angle for their positioning and rotating, while ThrownDevices need to aim and position themselves based on the hand offset, so this done here for TDs and below for HDs. + if (thrownDevice) { m_Rotation = m_HandOffset.GetAbsRadAngle() + (m_HFlipped ? c_PI : 0); } + if (heldDevice) { // In order to keep the HeldDevice in the right place, we need to convert its offset (the hand offset) to work as the ParentOffset for the HeldDevice. // The HeldDevice will then use this to set its JointPos when it's updated. Unfortunately UnRotateOffset doesn't work for this, since it's Vector/Matrix division, which isn't commutative. @@ -368,10 +373,9 @@ void Arm::Update() { Attachable::Update(); - if (IsAttached()) { - if (dynamic_cast(m_pHeldMO)) { m_Recoiled = dynamic_cast(m_pHeldMO)->IsRecoiled(); } + m_Recoiled = heldDevice && heldDevice->IsRecoiled(); - // Need to manually specify the rotation here so the arm moves with its hand. Need to specify the position because the rotation has changed and RotateOffset will return different results. + if (!thrownDevice) { m_Rotation = m_HandOffset.GetAbsRadAngle() + (m_HFlipped ? c_PI : 0); m_Pos = m_JointPos - RotateOffset(m_JointOffset); } @@ -397,9 +401,14 @@ void Arm::UpdateCurrentHandOffset() { g_SceneMan.CastStrengthRay(midOfDevice, midToMuzzle, 5, terrainOrMuzzlePosition, 0, false); targetOffset += g_SceneMan.ShortestDistance(newMuzzlePos, terrainOrMuzzlePosition, g_SceneMan.SceneWrapsX()); } else { - targetOffset = m_TargetPosition.IsZero() ? m_IdleOffset.GetXFlipped(m_HFlipped) : g_SceneMan.ShortestDistance(m_JointPos, m_TargetPosition, g_SceneMan.SceneWrapsX()); - if (m_WillIdle && !m_TargetPosition.IsZero() && targetOffset.GetMagnitude() > m_MaxLength) { targetOffset = m_IdleOffset.GetXFlipped(m_HFlipped); } + if (m_TargetPosition.IsZero()) { + targetOffset = m_IdleOffset.GetXFlipped(m_HFlipped); + } else { + targetOffset = g_SceneMan.ShortestDistance(m_JointPos, m_TargetPosition, g_SceneMan.SceneWrapsX()); + if (m_WillIdle && targetOffset.GetMagnitude() > m_MaxLength) { targetOffset = m_IdleOffset.GetXFlipped(m_HFlipped); } + } } + Vector distanceFromTargetOffsetToHandOffset(targetOffset - m_HandOffset); m_HandOffset += distanceFromTargetOffsetToHandOffset * m_MoveSpeed; m_HandOffset.ClampMagnitude(m_MaxLength, m_MaxLength / 2 + 0.1F); From 6cde16b0b1ff194dee9fcba5cf0ac69430911279 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Fri, 5 Feb 2021 22:00:00 -0400 Subject: [PATCH 134/144] Renamed DamageMultiplierSetInIni to HasNoSetDamageMultiplier, and reversed its use. Used this to ensure that wounds added will cleanly have a 1.0 damage multiplier if they don't have one set, either by lua or ini Corrected the various actor subclasses that force damage multipliers on their hardcoded attachables --- Entities/ACDropShip.cpp | 12 ++++++------ Entities/ACRocket.cpp | 14 +++++++------- Entities/ACrab.cpp | 12 ++++++------ Entities/AHuman.cpp | 12 ++++++------ Entities/MOSRotating.cpp | 13 ++++++------- Entities/MOSRotating.h | 13 ++++++------- 6 files changed, 37 insertions(+), 39 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 3e08279c7..a05de7901 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -127,40 +127,40 @@ int ACDropShip::ReadProperty(std::string propName, Reader &reader) { m_pRThruster = new AEmitter; reader >> m_pRThruster; AddAttachable(m_pRThruster); - if (!m_pRThruster->GetDamageMultiplierSetInINI()) { m_pRThruster->SetDamageMultiplier(1.0F); } + if (m_pRThruster->HasNoSetDamageMultiplier()) { m_pRThruster->SetDamageMultiplier(1.0F); } m_pRThruster->SetInheritsRotAngle(false); } else if (propName == "LThruster") { RemoveAttachable(m_pLThruster); m_pLThruster = new AEmitter; reader >> m_pLThruster; AddAttachable(m_pLThruster); - if (!m_pLThruster->GetDamageMultiplierSetInINI()) { m_pLThruster->SetDamageMultiplier(1.0F); } + if (m_pLThruster->HasNoSetDamageMultiplier()) { m_pLThruster->SetDamageMultiplier(1.0F); } m_pLThruster->SetInheritsRotAngle(false); } else if (propName == "URThruster") { RemoveAttachable(m_pURThruster); m_pURThruster = new AEmitter; reader >> m_pURThruster; AddAttachable(m_pURThruster); - if (!m_pURThruster->GetDamageMultiplierSetInINI()) { m_pURThruster->SetDamageMultiplier(1.0F); } + if (m_pURThruster->HasNoSetDamageMultiplier()) { m_pURThruster->SetDamageMultiplier(1.0F); } } else if (propName == "ULThruster") { RemoveAttachable(m_pULThruster); m_pULThruster = new AEmitter; reader >> m_pULThruster; AddAttachable(m_pULThruster); - if (!m_pULThruster->GetDamageMultiplierSetInINI()) { m_pULThruster->SetDamageMultiplier(1.0F); } + if (m_pULThruster->HasNoSetDamageMultiplier()) { m_pULThruster->SetDamageMultiplier(1.0F); } } else if (propName == "RHatchDoor") { RemoveAttachable(m_pRHatch); m_pRHatch = new Attachable; reader >> m_pRHatch; AddAttachable(m_pRHatch); - if (!m_pRHatch->GetDamageMultiplierSetInINI()) { m_pRHatch->SetDamageMultiplier(1.0F); } + if (m_pRHatch->HasNoSetDamageMultiplier()) { m_pRHatch->SetDamageMultiplier(1.0F); } m_pRHatch->SetInheritsRotAngle(false); } else if (propName == "LHatchDoor") { RemoveAttachable(m_pLHatch); m_pLHatch = new Attachable; reader >> m_pLHatch; AddAttachable(m_pLHatch); - if (!m_pLHatch->GetDamageMultiplierSetInINI()) { m_pLHatch->SetDamageMultiplier(1.0F); } + if (m_pLHatch->HasNoSetDamageMultiplier()) { m_pLHatch->SetDamageMultiplier(1.0F); } m_pLHatch->SetInheritsRotAngle(false); } else if (propName == "HatchDoorSwingRange") { reader >> m_HatchSwingRange; diff --git a/Entities/ACRocket.cpp b/Entities/ACRocket.cpp index 038511650..77bc56de4 100644 --- a/Entities/ACRocket.cpp +++ b/Entities/ACRocket.cpp @@ -164,14 +164,14 @@ int ACRocket::ReadProperty(std::string propName, Reader &reader) { m_pRLeg = new Leg; reader >> m_pRLeg; AddAttachable(m_pRLeg); - if (!m_pRLeg->GetDamageMultiplierSetInINI()) { m_pRLeg->SetDamageMultiplier(1.0F); } + if (m_pRLeg->HasNoSetDamageMultiplier()) { m_pRLeg->SetDamageMultiplier(1.0F); } } else if (propName == "LLeg") { RemoveAttachable(m_pLLeg); m_pLLeg = new Leg; reader >> m_pLLeg; AddAttachable(m_pLLeg); m_pLLeg->SetInheritsHFlipped(-1); - if (!m_pLLeg->GetDamageMultiplierSetInINI()) { m_pLLeg->SetDamageMultiplier(1.0F); } + if (m_pLLeg->HasNoSetDamageMultiplier()) { m_pLLeg->SetDamageMultiplier(1.0F); } } else if (propName == "RFootGroup") { delete m_pRFootGroup; m_pRFootGroup = new AtomGroup(); @@ -187,35 +187,35 @@ int ACRocket::ReadProperty(std::string propName, Reader &reader) { m_pMThruster = new AEmitter; reader >> m_pMThruster; AddAttachable(m_pMThruster); - if (!m_pMThruster->GetDamageMultiplierSetInINI()) { m_pMThruster->SetDamageMultiplier(1.0F); } + if (m_pMThruster->HasNoSetDamageMultiplier()) { m_pMThruster->SetDamageMultiplier(1.0F); } m_pMThruster->SetInheritedRotAngleOffset(-c_HalfPI); } else if (propName == "RThruster") { RemoveAttachable(m_pRThruster); m_pRThruster = new AEmitter; reader >> m_pRThruster; AddAttachable(m_pRThruster); - if (!m_pRThruster->GetDamageMultiplierSetInINI()) { m_pRThruster->SetDamageMultiplier(1.0F); } + if (m_pRThruster->HasNoSetDamageMultiplier()) { m_pRThruster->SetDamageMultiplier(1.0F); } m_pRThruster->SetInheritedRotAngleOffset(c_EighthPI); } else if (propName == "LThruster") { RemoveAttachable(m_pLThruster); m_pLThruster = new AEmitter; reader >> m_pLThruster; AddAttachable(m_pLThruster); - if (!m_pLThruster->GetDamageMultiplierSetInINI()) { m_pLThruster->SetDamageMultiplier(1.0F); } + if (m_pLThruster->HasNoSetDamageMultiplier()) { m_pLThruster->SetDamageMultiplier(1.0F); } m_pLThruster->SetInheritedRotAngleOffset(c_PI - c_EighthPI); } else if (propName == "URThruster") { RemoveAttachable(m_pURThruster); m_pURThruster = new AEmitter; reader >> m_pURThruster; AddAttachable(m_pURThruster); - if (!m_pURThruster->GetDamageMultiplierSetInINI()) { m_pURThruster->SetDamageMultiplier(1.0F); } + if (m_pURThruster->HasNoSetDamageMultiplier()) { m_pURThruster->SetDamageMultiplier(1.0F); } m_pURThruster->SetInheritedRotAngleOffset(c_HalfPI - c_EighthPI); } else if (propName == "ULThruster") { RemoveAttachable(m_pULThruster); m_pULThruster = new AEmitter; reader >> m_pULThruster; AddAttachable(m_pULThruster); - if (!m_pULThruster->GetDamageMultiplierSetInINI()) { m_pULThruster->SetDamageMultiplier(1.0F); } + if (m_pULThruster->HasNoSetDamageMultiplier()) { m_pULThruster->SetDamageMultiplier(1.0F); } m_pULThruster->SetInheritedRotAngleOffset(c_HalfPI + c_EighthPI); } else if (propName == "RaisedGearLimbPath") { reader >> m_Paths[RIGHT][RAISED]; diff --git a/Entities/ACrab.cpp b/Entities/ACrab.cpp index df6034f6a..993eac03a 100644 --- a/Entities/ACrab.cpp +++ b/Entities/ACrab.cpp @@ -261,13 +261,13 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) m_pTurret = new Turret; reader >> m_pTurret; AddAttachable(m_pTurret); - if (!m_pTurret->GetDamageMultiplierSetInINI()) { m_pTurret->SetDamageMultiplier(5.0F); } + if (m_pTurret->HasNoSetDamageMultiplier()) { m_pTurret->SetDamageMultiplier(5.0F); } } else if (propName == "Jetpack") { RemoveAttachable(m_pJetpack); m_pJetpack = new AEmitter; reader >> m_pJetpack; AddAttachable(m_pJetpack); - if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } + if (m_pJetpack->HasNoSetDamageMultiplier()) { m_pJetpack->SetDamageMultiplier(0.0F); } m_pJetpack->SetApplyTransferredForcesAtOffset(false); m_pJetpack->SetDeleteWhenRemovedFromParent(true); } else if (propName == "JumpTime") { @@ -278,27 +278,27 @@ int ACrab::ReadProperty(std::string propName, Reader &reader) m_pLFGLeg = new Leg; reader >> m_pLFGLeg; AddAttachable(m_pLFGLeg); - if (!m_pLFGLeg->GetDamageMultiplierSetInINI()) { m_pLFGLeg->SetDamageMultiplier(1.0F); } + if (m_pLFGLeg->HasNoSetDamageMultiplier()) { m_pLFGLeg->SetDamageMultiplier(1.0F); } m_pLFGLeg->SetInheritsHFlipped(-1); } else if (propName == "LBGLeg" || propName == "LeftFGLeg") { RemoveAttachable(m_pLBGLeg); m_pLBGLeg = new Leg; reader >> m_pLBGLeg; AddAttachable(m_pLBGLeg); - if (!m_pLBGLeg->GetDamageMultiplierSetInINI()) { m_pLBGLeg->SetDamageMultiplier(1.0F); } + if (m_pLBGLeg->HasNoSetDamageMultiplier()) { m_pLBGLeg->SetDamageMultiplier(1.0F); } m_pLBGLeg->SetInheritsHFlipped(-1); } else if (propName == "RFGLeg" || propName == "LeftFGLeg") { RemoveAttachable(m_pRFGLeg); m_pRFGLeg = new Leg; reader >> m_pRFGLeg; AddAttachable(m_pRFGLeg); - if (!m_pRFGLeg->GetDamageMultiplierSetInINI()) { m_pRFGLeg->SetDamageMultiplier(1.0F); } + if (m_pRFGLeg->HasNoSetDamageMultiplier()) { m_pRFGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "RBGLeg" || propName == "LeftFGLeg") { RemoveAttachable(m_pRBGLeg); m_pRBGLeg = new Leg; reader >> m_pRBGLeg; AddAttachable(m_pRBGLeg); - if (!m_pRBGLeg->GetDamageMultiplierSetInINI()) { m_pRBGLeg->SetDamageMultiplier(1.0F); } + if (m_pRBGLeg->HasNoSetDamageMultiplier()) { m_pRBGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "LFootGroup" || propName == "LeftFootGroup") { delete m_pLFGFootGroup; delete m_pLBGFootGroup; diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index e3a587585..894c1344b 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -238,14 +238,14 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { m_pHead = new Attachable; reader >> m_pHead; AddAttachable(m_pHead); - if (!m_pHead->GetDamageMultiplierSetInINI()) { m_pHead->SetDamageMultiplier(5.0F); } + if (m_pHead->HasNoSetDamageMultiplier()) { m_pHead->SetDamageMultiplier(5.0F); } m_pHead->SetInheritsRotAngle(false); } else if (propName == "Jetpack") { RemoveAttachable(m_pJetpack); m_pJetpack = new AEmitter; reader >> m_pJetpack; AddAttachable(m_pJetpack); - if (!m_pJetpack->GetDamageMultiplierSetInINI()) { m_pJetpack->SetDamageMultiplier(0.0F); } + if (m_pJetpack->HasNoSetDamageMultiplier()) { m_pJetpack->SetDamageMultiplier(0.0F); } m_pJetpack->SetApplyTransferredForcesAtOffset(false); } else if (propName == "JumpTime") { reader >> m_JetTimeTotal; @@ -256,7 +256,7 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { m_pFGArm = new Arm; reader >> m_pFGArm; AddAttachable(m_pFGArm); - if (!m_pFGArm->GetDamageMultiplierSetInINI()) { m_pFGArm->SetDamageMultiplier(1.0F); } + if (m_pFGArm->HasNoSetDamageMultiplier()) { m_pFGArm->SetDamageMultiplier(1.0F); } m_pFGArm->SetDrawnAfterParent(true); m_pFGArm->SetDrawnNormallyByParent(false); } else if (propName == "BGArm") { @@ -264,20 +264,20 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { m_pBGArm = new Arm; reader >> m_pBGArm; AddAttachable(m_pBGArm); - if (!m_pBGArm->GetDamageMultiplierSetInINI()) { m_pBGArm->SetDamageMultiplier(1.0F); } + if (m_pBGArm->HasNoSetDamageMultiplier()) { m_pBGArm->SetDamageMultiplier(1.0F); } m_pBGArm->SetDrawnAfterParent(false); } else if (propName == "FGLeg") { RemoveAttachable(m_pFGLeg); m_pFGLeg = new Leg; reader >> m_pFGLeg; AddAttachable(m_pFGLeg); - if (!m_pFGLeg->GetDamageMultiplierSetInINI()) { m_pFGLeg->SetDamageMultiplier(1.0F); } + if (m_pFGLeg->HasNoSetDamageMultiplier()) { m_pFGLeg->SetDamageMultiplier(1.0F); } } else if (propName == "BGLeg") { RemoveAttachable(m_pBGLeg); m_pBGLeg = new Leg; reader >> m_pBGLeg; AddAttachable(m_pBGLeg); - if (!m_pBGLeg->GetDamageMultiplierSetInINI()) { m_pBGLeg->SetDamageMultiplier(1.0F); } + if (m_pBGLeg->HasNoSetDamageMultiplier()) { m_pBGLeg->SetDamageMultiplier(1.0F); } m_pBGLeg->SetDrawnAfterParent(false); } else if (propName == "HandGroup") { delete m_pFGHandGroup; diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 3b9bd4fde..26dd379d5 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -77,7 +77,7 @@ void MOSRotating::Clear() m_pTempBitmapS = 0; m_LoudnessOnGib = 1; m_DamageMultiplier = 0; - m_DamageMultiplierSetInINI = false; + m_NoSetDamageMultiplier = true; m_StringValueMap.clear(); m_NumberValueMap.clear(); m_ObjectValueMap.clear(); @@ -261,7 +261,7 @@ int MOSRotating::Create(const MOSRotating &reference) { m_LoudnessOnGib = reference.m_LoudnessOnGib; m_DamageMultiplier = reference.m_DamageMultiplier; - m_DamageMultiplierSetInINI = reference.m_DamageMultiplierSetInINI; + m_NoSetDamageMultiplier = reference.m_NoSetDamageMultiplier; /* Allocated in lazy fashion as needed when drawing flipped if (!m_pFlipBitmap && m_aSprite[0]) @@ -336,7 +336,7 @@ int MOSRotating::ReadProperty(std::string propName, Reader &reader) reader >> m_LoudnessOnGib; else if (propName == "DamageMultiplier") { reader >> m_DamageMultiplier; - m_DamageMultiplierSetInINI = true; + m_NoSetDamageMultiplier = false; } else if (propName == "AddCustomValue") { ReadCustomValueProperty(reader); } else @@ -468,6 +468,7 @@ void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet woundToAdd->SetParentOffset(parentOffsetToSet); woundToAdd->SetInheritsHFlipped(false); woundToAdd->SetParent(this); + if (woundToAdd->HasNoSetDamageMultiplier()) { woundToAdd->SetDamageMultiplier(1.0F); } m_AttachableAndWoundMass += woundToAdd->GetMass(); m_Wounds.push_back(woundToAdd); } @@ -896,7 +897,7 @@ bool MOSRotating::ParticlePenetration(HitData &hd) // Add entry wound AEmitter to actor where the particle penetrated. AEmitter *pEntryWound = dynamic_cast(m_pEntryWound->Clone()); pEntryWound->SetEmitAngle(dir.GetXFlipped(m_HFlipped).GetAbsRadAngle() + c_PI); - float damageMultiplier = pEntryWound->GetDamageMultiplierSetInINI() ? pEntryWound->GetDamageMultiplier() : 1.0F; + float damageMultiplier = pEntryWound->HasNoSetDamageMultiplier() ? 1.0F : pEntryWound->GetDamageMultiplier(); pEntryWound->SetDamageMultiplier(damageMultiplier * hd.Body[HITOR]->WoundDamageMultiplier()); // Adjust position so that it looks like the hole is actually *on* the Hitee. entryPos[dom] += increment[dom] * (pEntryWound->GetSpriteFrame()->w / 2); @@ -916,7 +917,7 @@ bool MOSRotating::ParticlePenetration(HitData &hd) // Adjust position so that it looks like the hole is actually *on* the Hitee. exitPos[dom] -= increment[dom] * (pExitWound->GetSpriteFrame()->w / 2); pExitWound->SetEmitAngle(dir.GetXFlipped(m_HFlipped).GetAbsRadAngle()); - float damageMultiplier = pExitWound->GetDamageMultiplierSetInINI() ? pExitWound->GetDamageMultiplier() : 1.0F; + float damageMultiplier = pExitWound->HasNoSetDamageMultiplier() ? 1.0F : pExitWound->GetDamageMultiplier(); pExitWound->SetDamageMultiplier(damageMultiplier * hd.Body[HITOR]->WoundDamageMultiplier()); AddWound(pExitWound, exitPos + m_SpriteOffset); pExitWound = 0; @@ -1573,7 +1574,6 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, AEmitter *parentBreakWound = dynamic_cast(attachable->GetParentBreakWound()->Clone()); if (parentBreakWound) { parentBreakWound->SetEmitAngle((attachable->GetParentOffset() * m_Rotation).GetAbsRadAngle()); - if (!parentBreakWound->GetDamageMultiplierSetInINI()) { parentBreakWound->SetDamageMultiplier(1.0F); } AddWound(parentBreakWound, attachable->GetParentOffset(), false); parentBreakWound = nullptr; } @@ -1582,7 +1582,6 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, AEmitter *childBreakWound = dynamic_cast(attachable->GetBreakWound()->Clone()); if (childBreakWound) { childBreakWound->SetEmitAngle(attachable->GetJointOffset().GetAbsRadAngle()); - if (!childBreakWound->GetDamageMultiplierSetInINI()) { childBreakWound->SetDamageMultiplier(1.0F); } attachable->AddWound(childBreakWound, attachable->GetJointOffset()); childBreakWound = nullptr; } diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index bea16ba10..a66f6abe8 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -780,7 +780,7 @@ ClassInfoGetters // Arguments: New multiplier value. // Return value: None. - void SetDamageMultiplier(float newValue) { m_DamageMultiplier = newValue; } + void SetDamageMultiplier(float newValue) { m_DamageMultiplier = newValue; m_NoSetDamageMultiplier = false; } ////////////////////////////////////////////////////////////////////////////////////////// // Method: GetDamageMultiplier @@ -792,10 +792,10 @@ ClassInfoGetters float GetDamageMultiplier() const { return m_DamageMultiplier; } /// - /// Gets whether the damage multiplier was set in this MOSRotating's INI definition. Used to determine whether to set the damage multiplier for hardcoded Attachables when reading them in from INI. + /// Gets whether the damage multiplier for this MOSRotating has been directly set, or is at its default value. /// - /// Whether the damage multiplier was set in this MOSRotating's INI definition. - bool GetDamageMultiplierSetInINI() const { return m_DamageMultiplierSetInINI; } + /// Whether the damage multiplier for this MOSRotating has been set. + bool HasNoSetDamageMultiplier() const { return m_NoSetDamageMultiplier; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -912,9 +912,8 @@ ClassInfoGetters // Map to store any object pointers std::map m_ObjectValueMap; - // Damage multiplier for this attachable - float m_DamageMultiplier; - bool m_DamageMultiplierSetInINI; //!< Whether or not the damage multiplier was set in INI for this MOSRotating. + float m_DamageMultiplier; //!< Damage multiplier for this MOSRotating. + bool m_NoSetDamageMultiplier; //!< Whether or not the damage multiplier for this MOSRotating was set. // Intermediary drawing bitmap used to flip rotating bitmaps. Owned! BITMAP *m_pFlipBitmap; From a79a06fc1d3165dfa062dea40946b14796056a94 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sat, 6 Feb 2021 13:29:35 -0400 Subject: [PATCH 135/144] Fixed AHuman FGArm not drawing white. --- Entities/AHuman.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 894c1344b..f7a0419e3 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -4346,12 +4346,12 @@ void AHuman::DrawThrowingReticule(BITMAP *pTargetBitmap, const Vector &targetPos void AHuman::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, bool onlyPhysical) const { Actor::Draw(pTargetBitmap, targetPos, mode, onlyPhysical); + DrawMode realMode = (mode == g_DrawColor && m_FlashWhiteMS) ? g_DrawWhite : mode; // Note: For some reason the ordering of the attachables list can get messed up. The most important thing here is that the FGArm is on top of everything else. - if (m_pFGArm) { m_pFGArm->Draw(pTargetBitmap, targetPos, mode, onlyPhysical); } + if (m_pFGArm) { m_pFGArm->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); } //TODO simplify this complex if check when arm is cleaned up like turret so all it can hold are HeldDevices and children // Draw background Arm's hand after the HeldDevice of FGArm is drawn if the FGArm is holding a weapon. - DrawMode realMode = (mode == g_DrawColor && m_FlashWhiteMS) ? g_DrawWhite : mode; if (m_pFGArm && m_pBGArm && !onlyPhysical && mode == g_DrawColor && m_pBGArm->DidReach() && m_pFGArm->HoldsHeldDevice() && !m_pFGArm->HoldsThrownDevice() && !m_pFGArm->GetHeldDevice()->IsReloading() && !m_pFGArm->GetHeldDevice()->IsShield()) { m_pBGArm->DrawHand(pTargetBitmap, targetPos, realMode); } From 89044b06ca1c329d33be39c7e883f81b89b0caee Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 7 Feb 2021 02:05:09 -0400 Subject: [PATCH 136/144] Changed MOSprite Radius to SpriteRadius to clearly distinguish between it and radius that includes attachables. Same thing with diameter Added MOSRotating method GetIndividualRadius that returns sprite radius, and made it override GetRadius with one that uses attachable distance and radius to determine the true radius. Same thing with diameter Added MOSRotating radius handling when adding or removing attachables and supporting method for it Made Attachable parent and joint offset setters update position and joint position right away, and update parent radius if applicable. To handle luabind being a pain, parent and joint offsets are also stored and checked against, in order to properly update parent radius as needed Cleaned up things that use radius and diameter to either use sprite radius/diameter or getradius/diameter based on what I think makes sense. Also minor cleanup of data forgetting to account for scene wrapping :ju: Cleaned up TODO is SLTerrain for using Diameter since GetDiameter should now work --- Entities/ACDropShip.cpp | 2 ++ Entities/Actor.cpp | 4 +-- Entities/AtomGroup.cpp | 4 +-- Entities/Attachable.cpp | 48 +++++++++++++++++++++++++------ Entities/Attachable.h | 13 +++++++-- Entities/MOSRotating.cpp | 61 +++++++++++++++++++++++++++------------- Entities/MOSRotating.h | 32 +++++++++++++++++++++ Entities/MOSprite.cpp | 18 ++++++------ Entities/MOSprite.h | 14 ++++----- Entities/MovableObject.h | 2 +- Entities/SLTerrain.cpp | 3 +- Managers/LuaMan.cpp | 2 ++ 12 files changed, 150 insertions(+), 53 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index a05de7901..5959d7b74 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -379,6 +379,7 @@ void ACDropShip::UpdateAI() // Check for something in the way of our descent, and hover to the side to avoid it MOID detected = g_NoMOID; + //TODO since GetRadius includes attachables, this could probably be lessened. Maybe could just use GetDiameter directly. if ((detected = DetectObstacle(GetRadius() * 4)) != g_NoMOID) { // Only check other craft in the way @@ -444,6 +445,7 @@ void ACDropShip::UpdateAI() // Check for something in the way of our ascent, and hover to the side to avoid it MOID detected = g_NoMOID; + //TODO since GetRadius includes attachables, this could probably be lessened. Maybe could just use GetDiameter directly. if ((detected = DetectObstacle(GetRadius() * 4)) != g_NoMOID) { // Only check other craft in the way diff --git a/Entities/Actor.cpp b/Entities/Actor.cpp index 25900885d..f39ec3c2c 100644 --- a/Entities/Actor.cpp +++ b/Entities/Actor.cpp @@ -892,7 +892,7 @@ void Actor::DropAllInventory() velRange = 10.0F; // Randomize the offset from center to be within the original object - gibROffset.SetXY(m_MaxRadius * 0.35F * RandomNormalNum(), m_MaxRadius * 0.35F * RandomNormalNum()); + gibROffset.SetXY(m_SpriteRadius * 0.35F * RandomNormalNum(), m_SpriteRadius * 0.35F * RandomNormalNum()); // Set up its position and velocity according to the parameters of this AEmitter. pObject->SetPos(m_Pos + gibROffset/*Vector(m_Pos.m_X + 5 * NormalRand(), m_Pos.m_Y + 5 * NormalRand())*/); pObject->SetRotAngle(m_Rotation.GetRadAngle() + pObject->GetRotMatrix().GetRadAngle()); @@ -994,7 +994,7 @@ void Actor::GibThis(const Vector &impactImpulse, MovableObject *movableObjectToI velRange = 10.0F; // Randomize the offset from center to be within the original object - gibROffset.SetXY(m_MaxRadius * 0.35F * RandomNormalNum(), m_MaxRadius * 0.35F * RandomNormalNum()); + gibROffset.SetXY(m_SpriteRadius * 0.35F * RandomNormalNum(), m_SpriteRadius * 0.35F * RandomNormalNum()); // Set up its position and velocity according to the parameters of this AEmitter. pObject->SetPos(m_Pos + gibROffset/*Vector(m_Pos.m_X + 5 * NormalRand(), m_Pos.m_Y + 5 * NormalRand())*/); pObject->SetRotAngle(m_Rotation.GetRadAngle() + pObject->GetRotMatrix().GetRadAngle()); diff --git a/Entities/AtomGroup.cpp b/Entities/AtomGroup.cpp index 036b4492d..9ec7ff11c 100644 --- a/Entities/AtomGroup.cpp +++ b/Entities/AtomGroup.cpp @@ -1361,7 +1361,7 @@ namespace RTE { } // If the exit vector is too large, then avoid the jarring jump and report that we didn't make it out - if (totalExitVector.GetMagnitude() > m_OwnerMOSR->GetRadius()) { + if (totalExitVector.GetMagnitude() > m_OwnerMOSR->GetIndividualRadius()) { return false; } @@ -1489,7 +1489,7 @@ namespace RTE { } // Now actually apply the exit vectors to both, but only if the jump isn't too jarring - if (thisExit.GetMagnitude() < m_OwnerMOSR->GetRadius()) { position += thisExit; } + if (thisExit.GetMagnitude() < m_OwnerMOSR->GetIndividualRadius()) { position += thisExit; } if (!intersectedExit.IsZero() && intersectedExit.GetMagnitude() < intersectedMO->GetRadius()) { intersectedMO->SetPos(intersectedMO->GetPos() + intersectedExit); } if (m_OwnerMOSR->CanBeSquished() && RatioInTerrain() > 0.75F) /* && totalExitVector.GetMagnitude() > m_OwnerMOSR->GetDiameter()) */ { diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index e8b1e3cfc..a13fe0845 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -168,6 +168,28 @@ namespace RTE { return 0; } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::SetParentOffset(const Vector &newParentOffset) { + bool offsetsAreDifferent = (m_ParentOffset - newParentOffset).GetMagnitude() > 0.1F; + m_ParentOffset = newParentOffset; + if (offsetsAreDifferent) { + UpdatePositionAndJointPositionBasedOnOffsets(); + if (m_Parent) { m_Parent->HandlePotentialRadiusAffectingAttachable(this); } + } + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::SetJointOffset(const Vector &newJointOffset) { + bool offsetsAreDifferent = (m_JointOffset - newJointOffset).GetMagnitude() > 0.1F; + m_JointOffset = newJointOffset; + if (offsetsAreDifferent) { + UpdatePositionAndJointPositionBasedOnOffsets(); + if (m_Parent) { m_Parent->HandlePotentialRadiusAffectingAttachable(this); } + } + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Attachable::TransferJointForces(Vector &jointForces) { @@ -296,11 +318,9 @@ namespace RTE { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Attachable::Update() { - if (!m_Parent) { - m_JointPos = m_Pos + RotateOffset(m_JointOffset); - } else { - m_JointPos = m_Parent->GetPos() + m_Parent->RotateOffset(GetParentOffset()); - m_Pos = m_JointPos - RotateOffset(m_JointOffset); + if (m_Parent) { + UpdatePositionAndJointPositionBasedOnOffsets(); + if ((m_ParentOffset - m_PrevParentOffset).GetMagnitude() > 0.1F || (m_JointOffset - m_PrevJointOffset).GetMagnitude() > 0.1F) { m_Parent->HandlePotentialRadiusAffectingAttachable(this); } m_Vel = m_Parent->GetVel(); m_Team = m_Parent->GetTeam(); if (InheritsHFlipped() != 0) { m_HFlipped = m_InheritsHFlipped == 1 ? m_Parent->IsHFlipped() : !m_Parent->IsHFlipped(); } @@ -321,9 +341,6 @@ namespace RTE { } } m_DeepCheck = false; - - m_PrevPos = m_Pos; - m_PrevVel = m_Vel; m_PrevRotAngleOffset = currentRotAngleOffset; } @@ -331,6 +348,11 @@ namespace RTE { // If we're attached to something, MovableMan doesn't own us, and therefore isn't calling our UpdateScripts method (and neither is our parent), so we should here. if (m_Parent != nullptr && GetRootParent()->HasEverBeenAddedToMovableMan()) { UpdateScripts(); } + + m_PrevPos = m_Pos; + m_PrevVel = m_Vel; + m_PrevParentOffset = m_ParentOffset; + m_PrevJointOffset = m_JointOffset; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -425,6 +447,16 @@ namespace RTE { } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void Attachable::UpdatePositionAndJointPositionBasedOnOffsets() { + if (m_Parent) { + m_JointPos = m_Parent->GetPos() + m_Parent->RotateOffset(GetParentOffset()); m_Pos = m_JointPos - RotateOffset(m_JointOffset); + } else { + m_JointPos = m_Pos + RotateOffset(m_JointOffset); + } + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Attachable::AddOrRemoveAtomsFromRootParentAtomGroup(bool addAtoms) { diff --git a/Entities/Attachable.h b/Entities/Attachable.h index f709b4b2b..53c62511f 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -106,7 +106,7 @@ namespace RTE { /// Sets the stored offset between this Attachable's parent's Pos and the joint position. This should be maintained by the parent. /// /// A const reference to the new parent offset. - void SetParentOffset(const Vector &newParentOffset) { m_ParentOffset = newParentOffset; } + void SetParentOffset(const Vector &newParentOffset); /// /// Gets whether this Attachable is to be drawn after (in front of) or before (behind) its parent. @@ -221,8 +221,8 @@ namespace RTE { /// /// Sets the offset of the joint (the point around which this Attachable and its parent hinge) from this Attachable's center of mass/origin. /// - /// A Vector describing the offset of the joint relative to the this Attachable's origin/center of mass position. - void SetJointOffset(const Vector &offset) { m_JointOffset = offset; } + /// A Vector describing the offset of the joint relative to the this Attachable's origin/center of mass position. + void SetJointOffset(const Vector &newJointOffset); #pragma endregion #pragma region Force Transferral @@ -498,6 +498,8 @@ namespace RTE { long m_AtomSubgroupID; //!< The Atom IDs this' atoms will have when attached and added to a parent's AtomGroup. bool m_CollidesWithTerrainWhileAttached; //!< Whether this attachable currently has terrain collisions enabled while it's attached to a parent. + Vector m_PrevParentOffset; //!< The previous frame's parent offset. + Vector m_PrevJointOffset; //!< The previous frame's joint offset. float m_PrevRotAngleOffset; //!< The previous frame's difference between this Attachable's RotAngle and it's root parent's RotAngle. /// @@ -508,6 +510,11 @@ namespace RTE { private: + /// + /// Updates the position of this Attachable based on its parent offset and joint offset. Used during update and when something sets these offsets through setters. + /// + void UpdatePositionAndJointPositionBasedOnOffsets(); + /// /// Turns on/off this Attachable's terrain collisions while it is attached by adding/removing its Atoms to/from its root parent's AtomGroup. /// diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 26dd379d5..e8aa083c6 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -64,6 +64,8 @@ void MOSRotating::Clear() m_Attachables.clear(); m_ReferenceHardcodedAttachableUniqueIDs.clear(); m_HardcodedAttachableUniqueIDsAndSetters.clear(); + m_RadiusAffectingAttachable = nullptr; + m_FarthestAttachableDistanceAndRadius = 0.0F; m_AttachableAndWoundMass = 0.0F; m_Gibs.clear(); m_GibImpulseLimit = 0; @@ -111,8 +113,8 @@ int MOSRotating::Create() // Now done in MOSprite::Create, based on the sprite // Calc radius based on the atomgroup -// m_MaxRadius = m_pAtomGroup->CalculateMaxRadius() + 4; -// m_MaxDiameter = m_MaxRadius * 2; +// m_SpriteRadius = m_pAtomGroup->CalculateMaxRadius() + 4; +// m_MaxDiameter = m_SpriteRadius * 2; /* Allocated in lazy fashion as needed when drawing flipped if (!m_pFlipBitmap && m_aSprite[0]) @@ -152,27 +154,27 @@ int MOSRotating::Create() m_spTempBitmapS512 = create_bitmap_ex(c_MOIDLayerBitDepth, 512, 512); // Choose an appropriate size for this' diameter - if (m_MaxDiameter >= 256) + if (m_SpriteDiameter >= 256) { m_pTempBitmap = m_spTempBitmap512; m_pTempBitmapS = m_spTempBitmapS512; } - else if (m_MaxDiameter >= 128) + else if (m_SpriteDiameter >= 128) { m_pTempBitmap = m_spTempBitmap256; m_pTempBitmapS = m_spTempBitmapS256; } - else if (m_MaxDiameter >= 64) + else if (m_SpriteDiameter >= 64) { m_pTempBitmap = m_spTempBitmap128; m_pTempBitmapS = m_spTempBitmapS128; } - else if (m_MaxDiameter >= 32) + else if (m_SpriteDiameter >= 32) { m_pTempBitmap = m_spTempBitmap64; m_pTempBitmapS = m_spTempBitmapS64; } - else if (m_MaxDiameter >= 16) + else if (m_SpriteDiameter >= 16) { m_pTempBitmap = m_spTempBitmap32; m_pTempBitmapS = m_spTempBitmapS32; @@ -1166,16 +1168,17 @@ void MOSRotating::RestDetection() if (fabs(m_Rotation.GetRadAngle() - m_PrevRotation.GetRadAngle()) >= 0.01) m_RestTimer.Reset(); - // If we seem to be about to settle, make sure we're not flying in the air still + // If we seem to be about to settle, make sure we're not flying in the air still. + // Note that this uses sprite radius to avoid possibly settling when it shouldn't (e.g. if there's a lopsided attachable enlarging the radius, using GetRadius might make it settle in the air). if (m_ToSettle || IsAtRest()) { - if (g_SceneMan.OverAltitude(m_Pos, m_MaxRadius + 4, 3)) + if (g_SceneMan.OverAltitude(m_Pos, m_SpriteRadius + 4, 3)) { m_RestTimer.Reset(); m_ToSettle = false; } // TODO: REMOVE -// bool KUK = g_SceneMan.OverAltitude(m_Pos, m_MaxRadius + 4, 3); +// bool KUK = g_SceneMan.OverAltitude(m_Pos, m_SpriteRadius + 4, 3); } m_PrevRotation = m_Rotation; @@ -1189,7 +1192,8 @@ bool MOSRotating::IsOnScenePoint(Vector &scenePoint) const { return false; } - if (WithinBox(scenePoint, m_Pos.m_X - m_MaxRadius, m_Pos.m_Y - m_MaxRadius, m_Pos.m_X + m_MaxRadius, m_Pos.m_Y + m_MaxRadius)) { + //TODO this should really use GetRadius() instead of sprite radius, then check attachable's sprites directly here. It'd save some computation but I didn't wanna deal with it. + if (WithinBox(scenePoint, m_Pos.m_X - m_SpriteRadius, m_Pos.m_Y - m_SpriteRadius, m_Pos.m_X + m_SpriteRadius, m_Pos.m_Y + m_SpriteRadius)) { Vector spritePoint = scenePoint - m_Pos; spritePoint = UnRotateOffset(spritePoint); int pixel = getpixel(m_aSprite[m_Frame], static_cast(spritePoint.m_X - m_SpriteOffset.m_X), static_cast(spritePoint.m_Y - m_SpriteOffset.m_Y)); @@ -1489,7 +1493,7 @@ bool MOSRotating::DrawMOIDIfOverlapping(MovableObject *pOverlapMO) { if (pOverlapMO != this && m_GetsHitByMOs) { - float combinedRadii = m_MaxRadius + pOverlapMO->GetRadius(); + float combinedRadii = GetRadius() + pOverlapMO->GetRadius(); Vector otherPos = pOverlapMO->GetPos(); // Quick check @@ -1497,8 +1501,7 @@ bool MOSRotating::DrawMOIDIfOverlapping(MovableObject *pOverlapMO) return false; // Check if the offset is within the combined radii of the two object, and therefore might be overlapping - Vector offset = otherPos - m_Pos; - if (offset.GetMagnitude() < combinedRadii) + if (g_SceneMan.ShortestDistance(m_Pos, otherPos, g_SceneMan.SceneWrapsX()).GetMagnitude() < combinedRadii) { // They may be overlapping, so draw the MOID rep of this to the MOID layer Draw(g_SceneMan.GetMOIDBitmap(), Vector(), g_DrawMOID, true); @@ -1536,7 +1539,8 @@ void MOSRotating::AddAttachable(Attachable *attachable, const Vector& parentOffs attachable->SetParentOffset(parentOffsetToSet); attachable->SetParent(this); m_AttachableAndWoundMass += attachable->GetMass(); - m_Attachables.push_back(attachable); + HandlePotentialRadiusAffectingAttachable(attachable); + m_Attachables.push_back(attachable); } } @@ -1589,6 +1593,13 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, } if (attachable->GetDeleteWhenRemovedFromParent()) { attachable->SetToDelete(); } if (addToMovableMan || attachable->IsSetToDelete()) { g_MovableMan.AddMO(attachable); } + + if (attachable == m_RadiusAffectingAttachable) { + m_RadiusAffectingAttachable = nullptr; + m_FarthestAttachableDistanceAndRadius = 0; + std::for_each(m_Attachables.begin(), m_Attachables.end(), [this](const Attachable *attachableToCheck) { HandlePotentialRadiusAffectingAttachable(attachableToCheck); }); + } + return true; } @@ -1703,13 +1714,13 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, // See if need to double draw this across the scene seam if we're being drawn onto a scenewide bitmap if (targetPos.IsZero() && m_WrapDoubleDraw) { - if (spritePos.m_X < m_MaxDiameter) + if (spritePos.m_X < m_SpriteDiameter) { aDrawPos[passes] = spritePos; aDrawPos[passes].m_X += pTargetBitmap->w; passes++; } - else if (spritePos.m_X > pTargetBitmap->w - m_MaxDiameter) + else if (spritePos.m_X > pTargetBitmap->w - m_SpriteDiameter) { aDrawPos[passes] = spritePos; aDrawPos[passes].m_X -= pTargetBitmap->w; @@ -1800,7 +1811,7 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, // Register potential MOID drawing if (mode == g_DrawMOID) - g_SceneMan.RegisterMOIDDrawing(aDrawPos[i].GetFloored(), m_MaxRadius + 2); + g_SceneMan.RegisterMOIDDrawing(aDrawPos[i].GetFloored(), m_SpriteRadius + 2); } } } @@ -1848,7 +1859,7 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, // Register potential MOID drawing if (mode == g_DrawMOID) - g_SceneMan.RegisterMOIDDrawing(aDrawPos[i].GetFloored(), m_MaxRadius + 2); + g_SceneMan.RegisterMOIDDrawing(aDrawPos[i].GetFloored(), m_SpriteRadius + 2); } } } @@ -1874,6 +1885,18 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, #endif } +void MOSRotating::HandlePotentialRadiusAffectingAttachable(const Attachable *attachable) { + float distanceAndRadiusFromParent = g_SceneMan.ShortestDistance(m_Pos, attachable->m_Pos, g_SceneMan.SceneWrapsX()).GetMagnitude() + attachable->GetRadius(); + if (attachable == m_RadiusAffectingAttachable && distanceAndRadiusFromParent < m_FarthestAttachableDistanceAndRadius && m_Attachables.size() > 1) { + m_FarthestAttachableDistanceAndRadius = 0; + m_RadiusAffectingAttachable = nullptr; + std::for_each(m_Attachables.begin(), m_Attachables.end(), [this](const Attachable *attachableToCheck) { HandlePotentialRadiusAffectingAttachable(attachableToCheck); }); + } else if (distanceAndRadiusFromParent > m_FarthestAttachableDistanceAndRadius) { + m_FarthestAttachableDistanceAndRadius = distanceAndRadiusFromParent; + m_RadiusAffectingAttachable = attachable; + } +} + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool MOSRotating::TransferForcesFromAttachable(Attachable *attachable) { diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index a66f6abe8..b7e2516e9 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -136,6 +136,36 @@ ClassInfoGetters void Destroy(bool notInherited = false) override; + /// + /// Gets the radius of this MOSRotating, not including any Attachables. + /// + /// + float GetIndividualRadius() const { return m_SpriteRadius; } + + /// + /// Gets the radius of this MOSRotating, including any Attachables. + /// + /// The radius of this MOSRotating, including any Attachables. + float GetRadius() const override { return std::max(m_SpriteRadius, m_FarthestAttachableDistanceAndRadius); } + + /// + /// Gets the diameter of this MOSRotating, not including any Attachables. + /// + /// + float GetIndividualDiameter() const { return m_SpriteDiameter; } + + /// + /// Gets the diameter of this MOSRotating, including any Attachables. + /// + /// The diameter of this MOSRotating, including any Attachables. + float GetDiameter() const override { return GetRadius() * 2.0F; } + + /// + /// Checks if this Attachable should affect radius and, handles it if it should. + /// + /// The Attachable to check. + void HandlePotentialRadiusAffectingAttachable(const Attachable *attachable); + /// /// Gets the mass value of this MOSRotating, not including any Attachables or wounds. /// @@ -891,6 +921,8 @@ ClassInfoGetters std::list m_Attachables; std::unordered_set m_ReferenceHardcodedAttachableUniqueIDs; //!< An unordered set is filled with the Unique IDs of all of the reference object's hardcoded Attachables when using the copy Create. std::unordered_map> m_HardcodedAttachableUniqueIDsAndSetters; //!< An unordered map of Unique IDs to setter lambda functions, used to call the appropriate hardcoded Attachable setter when a hardcoded Attachable is removed. + const Attachable *m_RadiusAffectingAttachable; //!< A pointer to the Attachable that is currently affecting the radius. Used for some efficiency benefits. + float m_FarthestAttachableDistanceAndRadius; //!< The distance + radius of the radius affecting Attachable. float m_AttachableAndWoundMass; //!< The mass of all Attachables and wounds on this MOSRotating. Used in combination with its actual mass and any other affecting factors to get its total mass. // The list of Gib:s this will create when gibbed std::list m_Gibs; diff --git a/Entities/MOSprite.cpp b/Entities/MOSprite.cpp index 22a55383e..da8360172 100644 --- a/Entities/MOSprite.cpp +++ b/Entities/MOSprite.cpp @@ -38,8 +38,8 @@ void MOSprite::Clear() m_SpriteAnimTimer.Reset(); m_SpriteAnimIsReversingFrames = false; m_HFlipped = false; - m_MaxRadius = 1; - m_MaxDiameter = 2; + m_SpriteRadius = 1.0F; + m_SpriteDiameter = 2.0F; m_Rotation.Reset(); m_PrevRotation.Reset(); m_AngularVel = 0; @@ -76,8 +76,8 @@ int MOSprite::Create() // Calc maximum dimensions from the Pos, based on the sprite float maxX = MAX(fabs(m_SpriteOffset.m_X), fabs(m_aSprite[0]->w + m_SpriteOffset.m_X)); float maxY = MAX(fabs(m_SpriteOffset.m_Y), fabs(m_aSprite[0]->h + m_SpriteOffset.m_Y)); - m_MaxRadius = sqrt((float)(maxX * maxX) + (maxY * maxY)); - m_MaxDiameter = m_MaxRadius * 2; + m_SpriteRadius = sqrt((float)(maxX * maxX) + (maxY * maxY)); + m_SpriteDiameter = m_SpriteRadius * 2.0F; } else return -1; @@ -111,8 +111,8 @@ int MOSprite::Create(ContentFile spriteFile, // Calc maximum dimensions from the Pos, based on the sprite float maxX = MAX(fabs(m_SpriteOffset.m_X), fabs(m_aSprite[0]->w + m_SpriteOffset.m_X)); float maxY = MAX(fabs(m_SpriteOffset.m_Y), fabs(m_aSprite[0]->h + m_SpriteOffset.m_Y)); - m_MaxRadius = sqrt((float)(maxX * maxX) + (maxY * maxY)); - m_MaxDiameter = m_MaxRadius * 2; + m_SpriteRadius = sqrt((float)(maxX * maxX) + (maxY * maxY)); + m_SpriteDiameter = m_SpriteRadius * 2.0F; return 0; } @@ -147,8 +147,8 @@ int MOSprite::Create(const MOSprite &reference) m_SpriteAnimMode = reference.m_SpriteAnimMode; m_SpriteAnimDuration = reference.m_SpriteAnimDuration; m_HFlipped = reference.m_HFlipped; - m_MaxRadius = reference.m_MaxRadius; - m_MaxDiameter = reference.m_MaxDiameter; + m_SpriteRadius = reference.m_SpriteRadius; + m_SpriteDiameter = reference.m_SpriteDiameter; m_Rotation = reference.m_Rotation; m_AngularVel = reference.m_AngularVel; @@ -407,7 +407,7 @@ bool MOSprite::IsOnScenePoint(Vector &scenePoint) const } } */ - if (WithinBox(scenePoint, m_Pos.m_X - m_MaxRadius, m_Pos.m_Y - m_MaxRadius, m_Pos.m_X + m_MaxRadius, m_Pos.m_Y + m_MaxRadius)) + if (WithinBox(scenePoint, m_Pos.m_X - m_SpriteRadius, m_Pos.m_Y - m_SpriteRadius, m_Pos.m_X + m_SpriteRadius, m_Pos.m_Y + m_SpriteRadius)) { // Get scene point in object's relative space Vector spritePoint = scenePoint - m_Pos; diff --git a/Entities/MOSprite.h b/Entities/MOSprite.h index b9f64dd98..bd65f8842 100644 --- a/Entities/MOSprite.h +++ b/Entities/MOSprite.h @@ -147,7 +147,7 @@ class MOSprite: // Arguments: None. // Return value: The radius from its center to the edge of its graphical representation. - float GetRadius() const override { return m_MaxRadius; } + float GetRadius() const override { return m_SpriteRadius; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -157,7 +157,7 @@ class MOSprite: // Arguments: None. // Return value: The largest diameter across its graphical representation. - float GetDiameter() const override { return m_MaxDiameter; } + float GetDiameter() const override { return m_SpriteDiameter; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -167,7 +167,7 @@ class MOSprite: // Arguments: None. // Return value: A Vector with the absolute position of this' HUD stack top point. - Vector GetAboveHUDPos() const override { return m_Pos + Vector(0, -m_MaxRadius); } + Vector GetAboveHUDPos() const override { return m_Pos + Vector(0, -GetRadius()); } // TODO: Improve this one! Really crappy fit ////////////////////////////////////////////////////////////////////////////////////////// @@ -180,7 +180,7 @@ class MOSprite: // Return value: A Box which is guaranteed to contain this. Does nto take wrapping into // account, and parts of this box may be out of bounds! - Box GetBoundingBox() const { return Box(m_Pos + Vector(-m_MaxRadius, -m_MaxRadius), m_MaxDiameter, m_MaxDiameter); } + Box GetBoundingBox() const { return Box(m_Pos + Vector(-GetRadius(), -GetRadius()), GetDiameter(), GetDiameter()); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -404,7 +404,7 @@ class MOSprite: // Arguments: None. // Return value: Whether this is either moving or rotating too fast. - bool IsTooFast() const override { return m_Vel.GetLargest() > 500.0f || fabs(m_AngularVel) > (2000.0f / (m_MaxRadius + 1.0f)); } + bool IsTooFast() const override { return m_Vel.GetLargest() > 500.0f || fabs(m_AngularVel) > (2000.0f / (GetRadius() + 1.0f)); } //bool IsTooFast() const override { return m_Vel.GetLargest() > 500 || fabs(m_AngularVel) > 100.0f; } @@ -585,8 +585,8 @@ class MOSprite: // Whether flipped horizontally or not. bool m_HFlipped; // The precalculated maximum possible radius and diameter of this, in pixels - float m_MaxRadius; - float m_MaxDiameter; + float m_SpriteRadius; + float m_SpriteDiameter; // A counter to count the oscillations in rotation, in order to detect settling. int m_AngOscillations; // Whether to disable the settle material ID when this gets drawn as material diff --git a/Entities/MovableObject.h b/Entities/MovableObject.h index 546c9f853..0c70f839f 100644 --- a/Entities/MovableObject.h +++ b/Entities/MovableObject.h @@ -327,7 +327,7 @@ friend class Atom; // Arguments: None. // Return value: The largest diameter across its graphical representation. - virtual float GetDiameter() const { return 2.0f; } + virtual float GetDiameter() const { return 2.0F; } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/SLTerrain.cpp b/Entities/SLTerrain.cpp index 31f55b1cd..9ccc9fa87 100644 --- a/Entities/SLTerrain.cpp +++ b/Entities/SLTerrain.cpp @@ -1103,8 +1103,7 @@ void SLTerrain::ApplyMovableObject(MovableObject *pMObject) // Temporary bitmap holder, doesn't own BITMAP *pSprite = pMOSprite->GetSpriteFrame(); -// TODO: Make the diameter more accurate.. now we have to double it because it's not taking into account anything attached to the MO - float diameter = pMOSprite->GetDiameter() * 2; + float diameter = pMOSprite->GetDiameter(); // Choose an appropriate size if (diameter >= 256) pTempBitmap = m_spTempBitmap512; diff --git a/Managers/LuaMan.cpp b/Managers/LuaMan.cpp index c7965eb4e..1be34f8dc 100644 --- a/Managers/LuaMan.cpp +++ b/Managers/LuaMan.cpp @@ -814,6 +814,8 @@ int LuaMan::Create() { CONCRETELUABINDING(MOSRotating, MOSprite) /*.property("Material", &MOSRotating::GetMaterial)*/ + .property("IndividualRadius", &MOSRotating::GetIndividualRadius) + .property("IndividualDiameter", &MOSRotating::GetIndividualDiameter) .property("IndividualMass", &MOSRotating::GetIndividualMass) .property("RecoilForce", &MOSRotating::GetRecoilForce) .property("RecoilOffset", &MOSRotating::GetRecoilOffset) From ce5491b13778963d41635827cc881aca8faea3ab Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 7 Feb 2021 02:32:23 -0400 Subject: [PATCH 137/144] Update changelog with most recent set of work --- CHANGELOG.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba2025123..26392bba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Added `Actor` Lua (R) property `InventoryMass`. This provides access to the mass of the `Actor's` inventory separate from the `Actor's` actual mass. +- Added `LimbPath` INI property `EndSegCount`, which allows you to specify a segment after which the owning `Actor's` foot will not collide with terrain. This lets you add extra visual-only frames to your `LimbPaths`. + +- Added `AHuman` INI property `CrouchLimbPathBG` to allow you to specify a different `LimbPath` for the background leg while crouching. + +- Added `AHuman` INI properties `StandRotAngleTarget`, `WalkRotAngleTarget`, `CrouchRotAngleTarget` and `JumpRotAngleTarget` that let you define the rot angle the body should aim towards when in the corresponding `MovementState`. + +- Added `AHuman` Lua methods `GetRotAngleTarget(movementState)` and `SetRotAngleTarget(movementState, newRotAngleTarget)` that allow you to get and set rot angle targets for `MovementStates`. Note that only the `MovementStates` mentioned above will actually work. + +- `LimbPaths` are now Lua accessible for `ACrabs` and `AHumans`. You can use `GetLimbPath(Layer, MovementState)` for `AHumans` and `GetLimbPath(Side, Layer, MovementState)` for `ACrabs`. + `LimbPaths` have the following properties: + `limbPath.StartOffset` (R/W) - the start offset for the `LimbPath`. Also defines its position if it has no actual path. + `limbPath.SegmentCount` (R) - the number of segments in the `LimbPath`. + `limbPath:GetSegment(segmentIndex)` - Gets the segment Vector for the given segment index. You can use this to modify `LimbPaths`. + ### Changed - Hands will now draw in transparent drawing mode, i.e. editing menu. @@ -75,7 +89,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Everything draws better when flashing white, including craft which used to be terrible at it. - Reworked Attachable managment - `DamageMultiplier` on `Attachables` now works as expected, all `Attachables` can now transfer damage to their root parent. This will travel up chains of `Attachables`, as long as every `Attachable` in the chain has a non-zero DamageMultiplier (yes, negative numbers are supported if you wanna have healing instead of damage or weirdness with chaining negative multipliers). + `DamageMultiplier` on `Attachables` now works as expected, all `Attachables` can now transfer damage to their root parent. This will travel up chains of `Attachables`, as long as every `Attachable` in the chain has a non-zero DamageMultiplier (yes, negative numbers are supported if you wanna have healing instead of damage or weirdness with chaining negative multipliers). Note that the default `DamageMultiplier` for `Attachables` is 0, so you have to set it if you want it. Also note that wounds will default this value to 1 instead of 0. `Attachable` terrain collision has been reworked so that it can be changed simply by setting `CollidesWithTerrainWhileAttached = true/false` in INI or Lua. Also, `Attachables` attached to other `Attachables` will now collide with terrain properly. `BreakWounds` on `Attachables` now gets added to both the `Attachable` and the parent when the `Attachable` is broken off. If `ParentBreakWound` is defined, the parent will use this instead of the regular `BreakWound`. @@ -128,6 +142,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - The moment of inertia of `AtomGroups` now updates when the mass or Atoms change, meaning losing `Attachables` or changing mass will properly affect how rotational forces apply to MOSRotatings. +- `WoundDamageMultipliers` on projectiles will now properly stack with wounds' `DamageMultiplier`. Prior to this, if you set the `DamageMultiplier` of a wound on some object, it'd be overwritten by the hitting projectile's `WoundDamageMultiplier`. Now they multiply together properly. + +- `Radius` and `Diameter` now account for `Attachables` on objects that can have them. If you want just the `Radius` or `Diameter` of the object, use `IndividualRadius` and `IndividualDiameter` (only available for `MOSRotating` and subclasses). This means that `Radius` and `Diameter` will now give you a good estimation of an object's total size. + - Fixed various audio bugs that were in Pre3, and fixed clicking noise on sounds that played far away. The game should sound way better now! - Mobile sounds (i.e. generally things that aren't GUI related) will now pause and resume when you pause and resume your activity. From 5cfafddc971a874b2c935fe975e94516a877fd7e Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 7 Feb 2021 12:30:17 -0400 Subject: [PATCH 138/144] Make ahuman head draw after other attachables if set to draw after parent. Bit of manual draw order fiddling to keep things unchanged --- Entities/AHuman.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index f7a0419e3..6a3dde371 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -239,6 +239,7 @@ int AHuman::ReadProperty(std::string propName, Reader &reader) { reader >> m_pHead; AddAttachable(m_pHead); if (m_pHead->HasNoSetDamageMultiplier()) { m_pHead->SetDamageMultiplier(5.0F); } + if (m_pHead->IsDrawnAfterParent()) { m_pHead->SetDrawnNormallyByParent(false); } m_pHead->SetInheritsRotAngle(false); } else if (propName == "Jetpack") { RemoveAttachable(m_pJetpack); @@ -4348,6 +4349,7 @@ void AHuman::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode, DrawMode realMode = (mode == g_DrawColor && m_FlashWhiteMS) ? g_DrawWhite : mode; // Note: For some reason the ordering of the attachables list can get messed up. The most important thing here is that the FGArm is on top of everything else. + if (m_pHead && m_pHead->IsDrawnAfterParent()) { m_pHead->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); } if (m_pFGArm) { m_pFGArm->Draw(pTargetBitmap, targetPos, realMode, onlyPhysical); } //TODO simplify this complex if check when arm is cleaned up like turret so all it can hold are HeldDevices and children From befe0e97c6604ba7e8ba27d6428b586ad5f11d22 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 7 Feb 2021 20:32:36 -0400 Subject: [PATCH 139/144] Attachables that are set to delete will apply breakwounds to their parent --- Entities/MOSRotating.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index e8aa083c6..4d81d4434 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -1472,7 +1472,7 @@ void MOSRotating::Update() { attachable->Update(); if (attachable->IsAttachedTo(this) && attachable->IsSetToDelete()) { - RemoveAttachable(attachable, true, false); + RemoveAttachable(attachable, true, true); } else if (!attachable->IsSetToDelete()) { TransferForcesFromAttachable(attachable); } From cc93d8bf64a1e2ba44f1ffa841a34d9bc7d2ed16 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 8 Feb 2021 21:02:59 -0400 Subject: [PATCH 140/144] Fixed radius handling edge cases Radius calc will now not include flashes on hdfirearms or emitters Radius recalc will proliferate up through parents, so the full object chain can recalc as needed Radius recalc will work properly when handling the radius affecting attachable after its distance and radius has decreased, and it's the only attachable on its parent --- Entities/Attachable.cpp | 10 ++++++++++ Entities/Attachable.h | 9 ++++++++- Entities/MOSRotating.cpp | 25 ++++++++++++++++++++----- Entities/MOSRotating.h | 5 +++-- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index a13fe0845..b42db1f3e 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -315,6 +315,16 @@ namespace RTE { if (m_Parent) { m_Parent->RemoveAttachable(this, true, true); } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + bool Attachable::HandlePotentialRadiusAffectingAttachable(const Attachable *attachable) { + if (MOSRotating::HandlePotentialRadiusAffectingAttachable(attachable)) { + if (IsAttached()) { m_Parent->HandlePotentialRadiusAffectingAttachable(this); } + return true; + } + return false; + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Attachable::Update() { diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 53c62511f..5547fbd1c 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -371,7 +371,14 @@ namespace RTE { /// /// The impulse (kg * m/s) of the impact causing the gibbing to happen. /// A pointer to an MO which the Gibs and Attachables should not be colliding with. - virtual void GibThis(const Vector &impactImpulse = Vector(), MovableObject *movableObjectToIgnore = nullptr); + void GibThis(const Vector &impactImpulse = Vector(), MovableObject *movableObjectToIgnore = nullptr) override; + + /// + /// Checks if the given Attachable should affect radius, and handles it if it should. + /// + /// The Attachable to check. + /// Whether the radius affecting Attachable changed as a result of this call. + bool HandlePotentialRadiusAffectingAttachable(const Attachable *attachable) override; /// /// Updates this Attachable. Supposed to be done every frame. diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 4d81d4434..648c55705 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -19,6 +19,7 @@ #include "MOSParticle.h" #include "AEmitter.h" #include "Attachable.h" +#include "HDFirearm.h" #include "RTEError.h" @@ -1598,6 +1599,11 @@ bool MOSRotating::RemoveAttachable(Attachable *attachable, bool addToMovableMan, m_RadiusAffectingAttachable = nullptr; m_FarthestAttachableDistanceAndRadius = 0; std::for_each(m_Attachables.begin(), m_Attachables.end(), [this](const Attachable *attachableToCheck) { HandlePotentialRadiusAffectingAttachable(attachableToCheck); }); + + Attachable *thisAsAttachable = dynamic_cast(this); + if (thisAsAttachable && m_Attachables.empty() && thisAsAttachable->IsAttached()) { + thisAsAttachable->m_Parent->HandlePotentialRadiusAffectingAttachable(thisAsAttachable); + } } return true; @@ -1885,16 +1891,25 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, #endif } -void MOSRotating::HandlePotentialRadiusAffectingAttachable(const Attachable *attachable) { +bool MOSRotating::HandlePotentialRadiusAffectingAttachable(const Attachable *attachable) { + const HDFirearm *thisAsFirearm = dynamic_cast(this); + const AEmitter *thisAsEmitter = dynamic_cast(this); + if ((thisAsFirearm && attachable == thisAsFirearm->GetFlash()) || (thisAsEmitter && attachable == thisAsEmitter->GetFlash())) { + return false; + } float distanceAndRadiusFromParent = g_SceneMan.ShortestDistance(m_Pos, attachable->m_Pos, g_SceneMan.SceneWrapsX()).GetMagnitude() + attachable->GetRadius(); - if (attachable == m_RadiusAffectingAttachable && distanceAndRadiusFromParent < m_FarthestAttachableDistanceAndRadius && m_Attachables.size() > 1) { - m_FarthestAttachableDistanceAndRadius = 0; - m_RadiusAffectingAttachable = nullptr; - std::for_each(m_Attachables.begin(), m_Attachables.end(), [this](const Attachable *attachableToCheck) { HandlePotentialRadiusAffectingAttachable(attachableToCheck); }); + if (attachable == m_RadiusAffectingAttachable && distanceAndRadiusFromParent < m_FarthestAttachableDistanceAndRadius) { + m_FarthestAttachableDistanceAndRadius = distanceAndRadiusFromParent; + if (m_Attachables.size() > 1) { + std::for_each(m_Attachables.begin(), m_Attachables.end(), [this](const Attachable *attachableToCheck) { HandlePotentialRadiusAffectingAttachable(attachableToCheck); }); + } + return true; } else if (distanceAndRadiusFromParent > m_FarthestAttachableDistanceAndRadius) { m_FarthestAttachableDistanceAndRadius = distanceAndRadiusFromParent; m_RadiusAffectingAttachable = attachable; + return true; } + return false; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Entities/MOSRotating.h b/Entities/MOSRotating.h index b7e2516e9..3186bdae5 100644 --- a/Entities/MOSRotating.h +++ b/Entities/MOSRotating.h @@ -161,10 +161,11 @@ ClassInfoGetters float GetDiameter() const override { return GetRadius() * 2.0F; } /// - /// Checks if this Attachable should affect radius and, handles it if it should. + /// Checks if the given Attachable should affect radius, and handles it if it should. /// /// The Attachable to check. - void HandlePotentialRadiusAffectingAttachable(const Attachable *attachable); + /// Whether the radius affecting Attachable changed as a result of this call. + virtual bool HandlePotentialRadiusAffectingAttachable(const Attachable *attachable); /// /// Gets the mass value of this MOSRotating, not including any Attachables or wounds. From 3ecaf734596337fa43485f5c5ece905ee123c8f8 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Mon, 8 Feb 2021 21:42:53 -0400 Subject: [PATCH 141/144] Added angular vel cleaning for arms, legs and dropship engines when attached, to prevent them from quietly growing giant angular vels and blowing up cause they're considered too fast Rejiggered arm rot angle setting logic a bit so it better fits what was there before. I don't think it actually makes a difference, but might as well be correct with it --- Entities/ACDropShip.cpp | 2 ++ Entities/Arm.cpp | 10 +++++++--- Entities/Attachable.cpp | 5 ++++- Entities/Leg.cpp | 1 + 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Entities/ACDropShip.cpp b/Entities/ACDropShip.cpp index 5959d7b74..305d0800b 100644 --- a/Entities/ACDropShip.cpp +++ b/Entities/ACDropShip.cpp @@ -665,10 +665,12 @@ void ACDropShip::Update() if (m_pRThruster && m_pRThruster->IsAttached()) { m_pRThruster->SetRotAngle(engineRot.GetRadAngle()); + m_pRThruster->SetAngularVel(0.0F); } if (m_pLThruster && m_pLThruster->IsAttached()) { m_pLThruster->SetRotAngle(engineRot.GetRadAngle()); + m_pLThruster->SetAngularVel(0.0F); } // Auto balancing with the up thrusters diff --git a/Entities/Arm.cpp b/Entities/Arm.cpp index 0e0334e6e..5ec5587d1 100644 --- a/Entities/Arm.cpp +++ b/Entities/Arm.cpp @@ -353,7 +353,11 @@ void Arm::ReachToward(const Vector &scenePoint) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Arm::Update() { - if (!IsAttached()) { RemoveAttachable(dynamic_cast(m_pHeldMO), true, false); } + if (!IsAttached()) { + RemoveAttachable(dynamic_cast(m_pHeldMO), true, false); + } else { + m_AngularVel = 0.0F; + } UpdateCurrentHandOffset(); @@ -361,7 +365,7 @@ void Arm::Update() { const ThrownDevice *thrownDevice = heldDevice ? dynamic_cast(heldDevice) : nullptr; // HeldDevices need to use the aim angle for their positioning and rotating, while ThrownDevices need to aim and position themselves based on the hand offset, so this done here for TDs and below for HDs. - if (thrownDevice) { m_Rotation = m_HandOffset.GetAbsRadAngle() + (m_HFlipped ? c_PI : 0); } + if (thrownDevice || !heldDevice) { m_Rotation = m_HandOffset.GetAbsRadAngle() + (m_HFlipped ? c_PI : 0); } if (heldDevice) { // In order to keep the HeldDevice in the right place, we need to convert its offset (the hand offset) to work as the ParentOffset for the HeldDevice. @@ -375,7 +379,7 @@ void Arm::Update() { m_Recoiled = heldDevice && heldDevice->IsRecoiled(); - if (!thrownDevice) { + if (heldDevice && !thrownDevice) { m_Rotation = m_HandOffset.GetAbsRadAngle() + (m_HFlipped ? c_PI : 0); m_Pos = m_JointPos - RotateOffset(m_JointOffset); } diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index b42db1f3e..e5e25808b 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -334,7 +334,10 @@ namespace RTE { m_Vel = m_Parent->GetVel(); m_Team = m_Parent->GetTeam(); if (InheritsHFlipped() != 0) { m_HFlipped = m_InheritsHFlipped == 1 ? m_Parent->IsHFlipped() : !m_Parent->IsHFlipped(); } - if (InheritsRotAngle()) { SetRotAngle(m_Parent->GetRotAngle() + m_InheritedRotAngleOffset * static_cast(m_Parent->GetFlipFactor())); } + if (InheritsRotAngle()) { + SetRotAngle(m_Parent->GetRotAngle() + m_InheritedRotAngleOffset * static_cast(m_Parent->GetFlipFactor())); + m_AngularVel = 0.0F; + } MOSRotating *rootParentAsMOSR = dynamic_cast(GetRootParent()); float currentRotAngleOffset = (GetRotAngle() * static_cast(GetFlipFactor())) - rootParentAsMOSR->GetRotAngle(); diff --git a/Entities/Leg.cpp b/Entities/Leg.cpp index 7bbb80e70..60d072566 100644 --- a/Entities/Leg.cpp +++ b/Entities/Leg.cpp @@ -204,6 +204,7 @@ namespace RTE { extraRotation -= (m_ExtendedOffset.GetAbsRadAngle() - m_ContractedOffset.GetAbsRadAngle()) * extraRotationRatio; m_Rotation.SetRadAngle(m_Rotation.GetRadAngle() + extraRotation * static_cast(GetFlipFactor())); + m_AngularVel = 0.0F; } } From 4a3e625b3dbd2535a0f2c59be63e19ca80f47bd5 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Wed, 10 Feb 2021 02:10:51 -0400 Subject: [PATCH 142/144] Fix some edge case bugs in radius handling by re-simplifying parent offset setting, so it's all handled in the update check. Simplified check for changed parent offset to just be vector equality and clenaed up a bit of stuff --- Entities/Attachable.cpp | 30 ++++-------------------------- Entities/Attachable.h | 4 ++-- 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index e5e25808b..c309d7c9b 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -168,28 +168,6 @@ namespace RTE { return 0; } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - void Attachable::SetParentOffset(const Vector &newParentOffset) { - bool offsetsAreDifferent = (m_ParentOffset - newParentOffset).GetMagnitude() > 0.1F; - m_ParentOffset = newParentOffset; - if (offsetsAreDifferent) { - UpdatePositionAndJointPositionBasedOnOffsets(); - if (m_Parent) { m_Parent->HandlePotentialRadiusAffectingAttachable(this); } - } - } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - void Attachable::SetJointOffset(const Vector &newJointOffset) { - bool offsetsAreDifferent = (m_JointOffset - newJointOffset).GetMagnitude() > 0.1F; - m_JointOffset = newJointOffset; - if (offsetsAreDifferent) { - UpdatePositionAndJointPositionBasedOnOffsets(); - if (m_Parent) { m_Parent->HandlePotentialRadiusAffectingAttachable(this); } - } - } - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool Attachable::TransferJointForces(Vector &jointForces) { @@ -330,7 +308,7 @@ namespace RTE { void Attachable::Update() { if (m_Parent) { UpdatePositionAndJointPositionBasedOnOffsets(); - if ((m_ParentOffset - m_PrevParentOffset).GetMagnitude() > 0.1F || (m_JointOffset - m_PrevJointOffset).GetMagnitude() > 0.1F) { m_Parent->HandlePotentialRadiusAffectingAttachable(this); } + if (m_ParentOffset != m_PrevParentOffset || m_JointOffset != m_PrevJointOffset) { m_Parent->HandlePotentialRadiusAffectingAttachable(this); } m_Vel = m_Parent->GetVel(); m_Team = m_Parent->GetTeam(); if (InheritsHFlipped() != 0) { m_HFlipped = m_InheritsHFlipped == 1 ? m_Parent->IsHFlipped() : !m_Parent->IsHFlipped(); } @@ -436,8 +414,7 @@ namespace RTE { if (newParent) { m_Parent = newParent; m_Team = newParent->GetTeam(); - m_JointPos = m_Parent->GetPos() + m_Parent->RotateOffset(GetParentOffset()); - m_Pos = m_JointPos - RotateOffset(m_JointOffset); + UpdatePositionAndJointPositionBasedOnOffsets(); if (m_CollidesWithTerrainWhileAttached) { AddOrRemoveAtomsFromRootParentAtomGroup(true); } } else { m_RootMOID = m_MOID; @@ -464,7 +441,8 @@ namespace RTE { void Attachable::UpdatePositionAndJointPositionBasedOnOffsets() { if (m_Parent) { - m_JointPos = m_Parent->GetPos() + m_Parent->RotateOffset(GetParentOffset()); m_Pos = m_JointPos - RotateOffset(m_JointOffset); + m_JointPos = m_Parent->GetPos() + m_Parent->RotateOffset(GetParentOffset()); + m_Pos = m_JointPos - RotateOffset(m_JointOffset); } else { m_JointPos = m_Pos + RotateOffset(m_JointOffset); } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index 5547fbd1c..de4b4837e 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -106,7 +106,7 @@ namespace RTE { /// Sets the stored offset between this Attachable's parent's Pos and the joint position. This should be maintained by the parent. /// /// A const reference to the new parent offset. - void SetParentOffset(const Vector &newParentOffset); + void SetParentOffset(const Vector &newParentOffset) { m_ParentOffset = newParentOffset; } /// /// Gets whether this Attachable is to be drawn after (in front of) or before (behind) its parent. @@ -222,7 +222,7 @@ namespace RTE { /// Sets the offset of the joint (the point around which this Attachable and its parent hinge) from this Attachable's center of mass/origin. /// /// A Vector describing the offset of the joint relative to the this Attachable's origin/center of mass position. - void SetJointOffset(const Vector &newJointOffset); + void SetJointOffset(const Vector &newJointOffset) { m_JointOffset = newJointOffset; } #pragma endregion #pragma region Force Transferral From 1088fb147e49e498eecf4da6dc10c0d839abd87d Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Thu, 11 Feb 2021 12:02:35 -0400 Subject: [PATCH 143/144] Fixed wounds being included in radius due by adding and using a stopgap IsWound flag Fix a typo in AHuman method comment --- Entities/AHuman.cpp | 2 +- Entities/Attachable.cpp | 5 +++++ Entities/Attachable.h | 17 +++++++++++++++++ Entities/MOSRotating.cpp | 4 ++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Entities/AHuman.cpp b/Entities/AHuman.cpp index 6a3dde371..491296bf8 100644 --- a/Entities/AHuman.cpp +++ b/Entities/AHuman.cpp @@ -552,7 +552,7 @@ void AHuman::SetFGArm(Arm *newArm) { m_HardcodedAttachableUniqueIDsAndSetters.insert({newArm->GetUniqueID(), [](MOSRotating *parent, Attachable *attachable) { Arm *castedAttachable = dynamic_cast(attachable); - RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetJetpack"); + RTEAssert(!attachable || castedAttachable, "Tried to pass incorrect Attachable subtype " + (attachable ? attachable->GetClassName() : "") + " to SetFGArm"); dynamic_cast(parent)->SetFGArm(castedAttachable); }}); } diff --git a/Entities/Attachable.cpp b/Entities/Attachable.cpp index c309d7c9b..c405a0b36 100644 --- a/Entities/Attachable.cpp +++ b/Entities/Attachable.cpp @@ -22,6 +22,8 @@ namespace RTE { m_GibWithParentChance = 0.0F; m_ParentGibBlastStrengthMultiplier = 1; + m_IsWound = false; + m_JointStrength = 10.0F; m_JointStiffness = 1.0F; m_JointOffset.Reset(); @@ -65,6 +67,8 @@ namespace RTE { m_GibWithParentChance = reference.m_GibWithParentChance; m_ParentGibBlastStrengthMultiplier = reference.m_ParentGibBlastStrengthMultiplier; + m_IsWound = reference.m_IsWound; + m_JointStrength = reference.m_JointStrength; m_JointStiffness = reference.m_JointStiffness; m_JointOffset = reference.m_JointOffset; @@ -420,6 +424,7 @@ namespace RTE { m_RootMOID = m_MOID; m_RestTimer.Reset(); m_Team = -1; + m_IsWound = false; if (m_pMOToNotHit && m_Parent && m_Parent->GetWhichMOToNotHit() == m_pMOToNotHit) { m_pMOToNotHit = nullptr; } if (m_CollidesWithTerrainWhileAttached) { AddOrRemoveAtomsFromRootParentAtomGroup(false); } diff --git a/Entities/Attachable.h b/Entities/Attachable.h index de4b4837e..0d255c635 100644 --- a/Entities/Attachable.h +++ b/Entities/Attachable.h @@ -185,6 +185,20 @@ namespace RTE { void SetParentGibBlastStrengthMultiplier(float parentGibBlastStrengthMultiplier) { m_ParentGibBlastStrengthMultiplier = parentGibBlastStrengthMultiplier; } #pragma endregion +#pragma region Temporary Handling for Wounds, to be Replaced by a Wound Object in Future + /// + /// Gets whether or not this Attachable is a wound, as determined by its parent MOSR. + /// + /// Whether or not this Attachable is a wound. + bool IsWound() const { return m_IsWound; } + + /// + /// Sets whether or not this Attachable is a wound, to be done by its parent MOSR. + /// + /// Whether or not this Attachable should be a wound. + void SetIsWound(bool isWound) { m_IsWound = isWound; } +#pragma endregion + #pragma region Joint Getters and Setters /// /// Gets the amount of impulse force the joint of this Attachable can handle before breaking. @@ -489,6 +503,9 @@ namespace RTE { float m_GibWithParentChance; //!< The percentage chance that this Attachable will gib when its parent does. 0 means never, 1 means always. float m_ParentGibBlastStrengthMultiplier; //!< The multiplier this Attachable will apply to its parent's gib blast strength when the parent gibs. + //TODO This is a stopgap for a dedicated Wound class, that would be helpful to simplify things like this and default damage multiplier handling. + bool m_IsWound; //!< Whether or not this Attachable has been added as a wound. Only set and applied for Attachables with parents. + float m_JointStrength; //!< The amount of impulse force needed on this to detach it from the host Actor, in kg * m/s. A value of 0 means the join is infinitely strong and will never break naturally. float m_JointStiffness; //!< The normalized joint stiffness scalar. 1.0 means impulse forces on this attachable will be transferred to the parent with 100% strength, 0 means they will not transfer at all. Vector m_JointOffset; //!< The offset to the joint (the point around which this Attachable and its parent hinge) from its center of mass/origin. diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 648c55705..0dd59a390 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -471,6 +471,7 @@ void MOSRotating::AddWound(AEmitter *woundToAdd, const Vector &parentOffsetToSet woundToAdd->SetParentOffset(parentOffsetToSet); woundToAdd->SetInheritsHFlipped(false); woundToAdd->SetParent(this); + woundToAdd->SetIsWound(true); if (woundToAdd->HasNoSetDamageMultiplier()) { woundToAdd->SetDamageMultiplier(1.0F); } m_AttachableAndWoundMass += woundToAdd->GetMass(); m_Wounds.push_back(woundToAdd); @@ -1892,6 +1893,9 @@ void MOSRotating::Draw(BITMAP *pTargetBitmap, } bool MOSRotating::HandlePotentialRadiusAffectingAttachable(const Attachable *attachable) { + if (!attachable->IsAttachedTo(this) && !attachable->IsWound()) { + return false; + } const HDFirearm *thisAsFirearm = dynamic_cast(this); const AEmitter *thisAsEmitter = dynamic_cast(this); if ((thisAsFirearm && attachable == thisAsFirearm->GetFlash()) || (thisAsEmitter && attachable == thisAsEmitter->GetFlash())) { From 782a1de5adf6ca698f771f96acc24b836634d6c8 Mon Sep 17 00:00:00 2001 From: Gareth YR Date: Sun, 14 Feb 2021 20:03:38 -0400 Subject: [PATCH 144/144] Cleanup some junk comments as requested in review. Oneline something that was ugly multilined --- Entities/MOSRotating.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Entities/MOSRotating.cpp b/Entities/MOSRotating.cpp index 0dd59a390..13e69078b 100644 --- a/Entities/MOSRotating.cpp +++ b/Entities/MOSRotating.cpp @@ -107,16 +107,9 @@ int MOSRotating::Create() else if (m_pDeepGroup) m_pDeepGroup->SetOwner(this); - // Set up the sprite center Vector. - m_SpriteCenter.SetXY(m_aSprite[m_Frame]->w / 2, - m_aSprite[m_Frame]->h / 2); + m_SpriteCenter.SetXY(m_aSprite[m_Frame]->w / 2, m_aSprite[m_Frame]->h / 2); m_SpriteCenter += m_SpriteOffset; -// Now done in MOSprite::Create, based on the sprite - // Calc radius based on the atomgroup -// m_SpriteRadius = m_pAtomGroup->CalculateMaxRadius() + 4; -// m_MaxDiameter = m_SpriteRadius * 2; - /* Allocated in lazy fashion as needed when drawing flipped if (!m_pFlipBitmap && m_aSprite[0]) m_pFlipBitmap = create_bitmap_ex(8, m_aSprite[0]->w, m_aSprite[0]->h); @@ -1179,8 +1172,6 @@ void MOSRotating::RestDetection() m_RestTimer.Reset(); m_ToSettle = false; } -// TODO: REMOVE -// bool KUK = g_SceneMan.OverAltitude(m_Pos, m_SpriteRadius + 4, 3); } m_PrevRotation = m_Rotation;