Update ropes

This commit is contained in:
Roman Chistokhodov 2019-08-01 18:17:29 +03:00
parent eb086db702
commit 6cb150f7f1
5 changed files with 2130 additions and 223 deletions

View File

@ -188,6 +188,10 @@ set (SVDLL_SOURCES
../pm_shared/pm_math.c
../pm_shared/pm_shared.c
)
if(NOT MSVC)
set_source_files_properties(gearbox/ropes.cpp PROPERTIES COMPILE_FLAGS -O0)
endif()
include_directories (. wpn_shared ../common ../engine ../pm_shared ../game_shared ../public gearbox)

File diff suppressed because it is too large Load Diff

311
dlls/gearbox/ropes.h Normal file
View File

@ -0,0 +1,311 @@
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#ifndef ROPES_H
#define ROPES_H
class CRopeSegment;
class CRopeSample;
struct RopeSampleData;
struct Spring;
#define MAX_SEGMENTS 63
#define MAX_SAMPLES 64
#define MAX_TEMP_SAMPLES 5
/**
* A rope with a number of segments.
* Uses an RK4 integrator with dampened springs to simulate rope physics.
*/
class CRope : public CBaseDelay
{
public:
CRope();
virtual void KeyValue( KeyValueData* pkvd );
virtual void Precache();
virtual void Spawn();
void Think();
void Touch( CBaseEntity* pOther );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
/**
* Initializes the rope simulation data.
*/
void InitializeRopeSim();
/**
* Initializes the springs.
* @param uiNumSprings Number of springs to create.
*/
void InitializeSprings( const size_t uiNumSprings );
/**
* Runs simulation on the samples.
*/
void RunSimOnSamples();
/**
* Computes forces on the given sample list.
* @param pSystem List of sample data. m_NumSamples Elements large.
*/
void ComputeForces( RopeSampleData* pSystem );
/**
* Computes forces on the given sample list.
* @param pSystem List of samples. m_NumSamples Elements large.
*/
void ComputeForces( CRopeSample** ppSystem );
/**
* Computes forces for the given sample data.
* @param data Sample data.
*/
void ComputeSampleForce( RopeSampleData& data );
/**
* Computes spring force for the given sample datas.
* @param first First sample.
* @param second Second sample.
* @param spring Spring.
*/
void ComputeSpringForce( RopeSampleData& first, RopeSampleData& second, const Spring& spring );
/**
* Runs RK4 integration.
* @param flDeltaTime Delta between previous and current time.
* @param ppSampleSource Previous sample state.
* @param ppSampleTarget Next sample state.
*/
void RK4Integrate( const float flDeltaTime, CRopeSample** ppSampleSource, CRopeSample** ppSampleTarget );
/**
* Traces model positions and angles and corrects them.
* @param ppPrimarySegs Visible segments.
* @param ppHiddenSegs hidden segments.
*/
void TraceModels( CRopeSegment** ppPrimarySegs, CRopeSegment** ppHiddenSegs );
/**
* Traces model positions and angles, makes visible segments visible and hidden segments hidden.
*/
void SetRopeSegments( const size_t uiNumSegments,
CRopeSegment** ppPrimarySegs, CRopeSegment** ppHiddenSegs );
/**
* Moves the attached object up.
* @param flDeltaTime Time between previous and current movement.
* @return true if the object is still on the rope, false otherwise.
*/
bool MoveUp( const float flDeltaTime );
/**
* Moves the attached object down.
* @param flDeltaTime Time between previous and current movement.
* @return true if the object is still on the rope, false otherwise.
*/
bool MoveDown( const float flDeltaTime );
/**
* @return The attached object's velocity.
*/
Vector GetAttachedObjectsVelocity() const;
/**
* Applies force from the player. Only applies if there is currently an object attached to the rope.
* @param vecForce Force.
*/
void ApplyForceFromPlayer( const Vector& vecForce );
/**
* Applies force to a specific segment.
* @param vecForce Force.
* @param uiSegment Segment index.
*/
void ApplyForceToSegment( const Vector& vecForce, const size_t uiSegment );
/**
* Attached an object to the given segment.
*/
void AttachObjectToSegment( CRopeSegment* pSegment );
/**
* Detaches an attached object.
*/
void DetachObject();
/**
* @return Whether an object is attached.
*/
bool IsObjectAttached() const { return mObjectAttached; }
/**
* @return Whether this rope allows attachments.
*/
bool IsAcceptingAttachment() const;
/**
* @return The number of segments.
*/
size_t GetNumSegments() const { return m_iSegments; }
/**
* @return The segments.
*/
CRopeSegment** GetSegments() { return seg; }
/**
* @return The alternative segments.
*/
CRopeSegment** GetAltSegments() { return altseg; }
/**
* @return The toggle value.
*/
bool GetToggleValue() const { return m_bToggle; }
/**
* @return Whether this rope is allowed to make sounds.
*/
bool IsSoundAllowed() const { return m_bMakeSound; }
/**
* Sets whether this rope is allowed to make sounds.
*/
void SetSoundAllowed( const bool bAllowed )
{
m_bMakeSound = bAllowed;
}
/**
* @return Whether this rope should creak.
*/
bool ShouldCreak() const;
/**
* Plays a creak sound.
*/
void Creak();
/**
* @return The body model name.
*/
string_t GetBodyModel() const { return mBodyModel; }
/**
* @return The ending model name.
*/
string_t GetEndingModel() const { return mEndingModel; }
/**
* @return Segment length for the given segment.
*/
float GetSegmentLength( size_t uiSegmentIndex ) const;
/**
* @return Total rope length.
*/
float GetRopeLength() const;
/**
* @return The rope's origin.
*/
Vector GetRopeOrigin() const;
/**
* @return Whether the given segment index is valid.
*/
bool IsValidSegmentIndex( const size_t uiSegment ) const;
/**
* @return The origin of the given segment.
*/
Vector GetSegmentOrigin( const size_t uiSegment ) const;
/**
* @return The attachment point of the given segment.
*/
Vector GetSegmentAttachmentPoint( const size_t uiSegment ) const;
/**
* @param pSegment Segment.
* Sets the attached object segment.
*/
void SetAttachedObjectsSegment( CRopeSegment* pSegment );
/**
* @param uiSegmentIndex Segment index.
* @return The segment direction normal from its origin.
*/
Vector GetSegmentDirFromOrigin( const size_t uiSegmentIndex ) const;
/**
* @return The attached object position.
*/
Vector GetAttachedObjectsPosition() const;
private:
size_t m_iSegments;
CRopeSegment* seg[ MAX_SEGMENTS ];
CRopeSegment* altseg[ MAX_SEGMENTS ];
bool m_bToggle;
bool m_InitialDeltaTime;
float mLastTime;
Vector m_LastEndPos;
Vector m_Gravity;
float m_HookConstant;
float m_SpringDampning;
CRopeSample* m_CurrentSys[ MAX_SAMPLES ];
CRopeSample* m_TargetSys[ MAX_SAMPLES ];
RopeSampleData* m_TempSys[ MAX_TEMP_SAMPLES ];
size_t m_NumSamples;
Spring* m_Spring;
size_t m_SpringCnt;
bool mSpringsInitialized;
int m_BeamOffset;
bool mObjectAttached;
size_t mAttachedObjectsSegment;
float mAttachedObjectsOffset;
float detachTime;
string_t mBodyModel;
string_t mEndingModel;
int mDisallowPlayerAttachment;
bool m_bMakeSound;
};
#endif //ROPES_H

View File

@ -120,6 +120,7 @@ TYPEDESCRIPTION CBasePlayer::m_playerSaveData[] =
DEFINE_FIELD( CBasePlayer, m_iFOV, FIELD_INTEGER ),
DEFINE_FIELD(CBasePlayer, m_fInXen, FIELD_BOOLEAN),
DEFINE_FIELD(CBasePlayer, m_pRope, FIELD_CLASSPTR),
//DEFINE_FIELD( CBasePlayer, m_fDeadTime, FIELD_FLOAT ), // only used in multiplayer games
//DEFINE_FIELD( CBasePlayer, m_fGameHUDInitialized, FIELD_INTEGER ), // only used in multiplayer games
@ -1880,6 +1881,135 @@ void CBasePlayer::PreThink( void )
else
pev->flags &= ~FL_ONTRAIN;
//We're on a rope. - Solokiller
if( (m_afPhysicsFlags & PFLAG_ONROPE) && m_pRope )
{
pev->velocity = g_vecZero;
Vector vecAttachPos = m_pRope->GetAttachedObjectsPosition();
pev->origin = vecAttachPos;
Vector vecForce;
/*
//This causes sideways acceleration that doesn't occur in Op4. - Solokiller
if( pev->button & IN_DUCK )
{
vecForce.x = gpGlobals->v_right.x;
vecForce.y = gpGlobals->v_right.y;
vecForce.z = 0;
m_pRope->ApplyForceFromPlayer( vecForce );
}
if( pev->button & IN_JUMP )
{
vecForce.x = -gpGlobals->v_right.x;
vecForce.y = -gpGlobals->v_right.y;
vecForce.z = 0;
m_pRope->ApplyForceFromPlayer( vecForce );
}
*/
//Determine if any force should be applied to the rope, or if we should move around. - Solokiller
if( pev->button & ( IN_BACK | IN_FORWARD ) )
{
if( ( gpGlobals->v_forward.x * gpGlobals->v_forward.x +
gpGlobals->v_forward.y * gpGlobals->v_forward.y -
gpGlobals->v_forward.z * gpGlobals->v_forward.z ) <= 0.0 )
{
if( m_bIsClimbing )
{
const float flDelta = gpGlobals->time - m_flLastClimbTime;
m_flLastClimbTime = gpGlobals->time;
if( pev->button & IN_FORWARD )
{
if( gpGlobals->v_forward.z < 0.0 )
{
if( !m_pRope->MoveDown( flDelta ) )
{
//Let go of the rope, detach. - Solokiller
pev->movetype = MOVETYPE_WALK;
pev->solid = SOLID_SLIDEBOX;
m_afPhysicsFlags &= ~PFLAG_ONROPE;
m_pRope->DetachObject();
m_pRope = NULL;
m_bIsClimbing = false;
}
}
else
{
m_pRope->MoveUp( flDelta );
}
}
if( pev->button & IN_BACK )
{
if( gpGlobals->v_forward.z < 0.0 )
{
m_pRope->MoveUp( flDelta );
}
else if( !m_pRope->MoveDown( flDelta ) )
{
//Let go of the rope, detach. - Solokiller
pev->movetype = MOVETYPE_WALK;
pev->solid = SOLID_SLIDEBOX;
m_afPhysicsFlags &= ~PFLAG_ONROPE;
m_pRope->DetachObject();
m_pRope = NULL;
m_bIsClimbing = false;
}
}
}
else
{
m_bIsClimbing = true;
m_flLastClimbTime = gpGlobals->time;
}
}
else
{
vecForce.x = gpGlobals->v_forward.x;
vecForce.y = gpGlobals->v_forward.y;
vecForce.z = 0.0;
if( pev->button & IN_BACK )
{
vecForce.x = -gpGlobals->v_forward.x;
vecForce.y = -gpGlobals->v_forward.y;
vecForce.z = 0;
}
m_pRope->ApplyForceFromPlayer( vecForce );
m_bIsClimbing = false;
}
}
else
{
m_bIsClimbing = false;
}
if( m_afButtonPressed & IN_JUMP )
{
//We've jumped off the rope, give us some momentum - Solokiller
pev->movetype = MOVETYPE_WALK;
pev->solid = SOLID_SLIDEBOX;
this->m_afPhysicsFlags &= ~PFLAG_ONROPE;
Vector vecDir = gpGlobals->v_up * 165.0 + gpGlobals->v_forward * 150.0;
Vector vecVelocity = m_pRope->GetAttachedObjectsVelocity() * 2;
vecVelocity = vecVelocity.Normalize();
vecVelocity = vecVelocity * 200;
pev->velocity = vecVelocity + vecDir;
m_pRope->DetachObject();
m_pRope = NULL;
m_bIsClimbing = false;
}
return;
}
// Train speed control
if( m_afPhysicsFlags & PFLAG_ONTRAIN )
{

View File

@ -17,6 +17,7 @@
#define PLAYER_H
#include "pm_materials.h"
#include "ropes.h"
#define PLAYER_FATAL_FALL_SPEED 1024// approx 60 feet
#define PLAYER_MAX_SAFE_FALL_SPEED 580// approx 20 feet
@ -37,6 +38,8 @@
#define PFLAG_LATCHING ( 1<<6 ) // Player is latching to a target
#define PFLAG_ATTACHED ( 1<<7 ) // Player is attached by a barnacle tongue tip
#define PFLAG_ONROPE ( 1<<8 )
//
// generic player
//
@ -374,6 +377,28 @@ public:
void Service_Grapple( void );
bool m_bSentBhopcap; // If false, the player just joined and needs a bhopcap message.
bool m_bIsClimbing;
float m_flLastClimbTime;
CRope *m_pRope;
BOOL IsOnRope()
{
return ( m_afPhysicsFlags & PFLAG_ONROPE ) != 0;
}
void SetRope( CBaseEntity *pRope )
{
m_pRope = (CRope*)pRope;
}
void SetOnRopeState( bool onRope )
{
if( onRope )
m_afPhysicsFlags |= PFLAG_ONROPE;
else
m_afPhysicsFlags &= ~PFLAG_ONROPE;
}
CRope* GetRope() { return m_pRope; }
};
#define AUTOAIM_2DEGREES 0.0348994967025