From 34a3efba0d5f1995510ad36df60b8185bd03b5d4 Mon Sep 17 00:00:00 2001 From: D-AIRY <admin@ds-servers.com> Date: Tue, 2 Jan 2018 20:41:15 +0300 Subject: [PATCH] Added CBaseCharacter middleclass; Weapon fire spread calculation --- build/gamesource/config/entities/classes.ent | 6 +- proj/sxgame/vs2013/sxgame.vcxproj | 2 + proj/sxgame/vs2013/sxgame.vcxproj.filters | 54 ++-- source/game/CBaseCharacter.cpp | 246 +++++++++++++++++++ source/game/CBaseCharacter.h | 106 ++++++++ source/game/SXbaseItem.cpp | 5 + source/game/SXbaseItem.h | 4 + source/game/SXbaseTool.cpp | 13 +- source/game/SXbaseTool.h | 9 + source/game/SXbaseWeapon.cpp | 85 ++++++- source/game/SXbaseWeapon.h | 39 +++ source/game/SXplayer.cpp | 153 +----------- source/game/SXplayer.h | 66 +---- source/game/crosshair.cpp | 13 +- 14 files changed, 570 insertions(+), 231 deletions(-) create mode 100644 source/game/CBaseCharacter.cpp create mode 100644 source/game/CBaseCharacter.h diff --git a/build/gamesource/config/entities/classes.ent b/build/gamesource/config/entities/classes.ent index b0b7cf2c7..8b2422ed1 100644 --- a/build/gamesource/config/entities/classes.ent +++ b/build/gamesource/config/entities/classes.ent @@ -51,6 +51,10 @@ single_speed = 40; выст/мин burst_speed = 100; выст/мин effective_distance = 650 + +;разброс +spread_base = 0.33 ;угол (в градусах) базовой дисперсии оружия (оружия, зажатого в тисках) + ; Боевая скорострельность (одиночными): 40 выст/мин ; Боевая скорострельность (очередями): 100 выст/мин ; Дальность, до которой сохраняется убойное действие пули: 1350 м @@ -80,8 +84,6 @@ durability = 350000 durability_return_min = 0.7 ; при ремонте: durability_return_max = 0.9 ; durability_max = durability_max * rand(durability_return_min, durability_return_max) -;разброс -fire_dispersion_base = 0.33 ;угол (в градусах) базовой дисперсии оружия (оружия, зажатого в тисках) ;отдача cam_return = 0 diff --git a/proj/sxgame/vs2013/sxgame.vcxproj b/proj/sxgame/vs2013/sxgame.vcxproj index a0ebed554..e33751a9b 100644 --- a/proj/sxgame/vs2013/sxgame.vcxproj +++ b/proj/sxgame/vs2013/sxgame.vcxproj @@ -97,6 +97,7 @@ <ClCompile Include="..\..\..\source\game\BaseSilencer.cpp" /> <ClCompile Include="..\..\..\source\game\BaseWeaponAddon.cpp" /> <ClCompile Include="..\..\..\source\game\BaseTrigger.cpp" /> + <ClCompile Include="..\..\..\source\game\CBaseCharacter.cpp" /> <ClCompile Include="..\..\..\source\game\crosshair.cpp" /> <ClCompile Include="..\..\..\source\game\CrosshairManager.cpp" /> <ClCompile Include="..\..\..\source\game\EntityFactory.cpp" /> @@ -133,6 +134,7 @@ <ClInclude Include="..\..\..\source\game\BaseSilencer.h" /> <ClInclude Include="..\..\..\source\game\BaseWeaponAddon.h" /> <ClInclude Include="..\..\..\source\game\BaseTrigger.h" /> + <ClInclude Include="..\..\..\source\game\CBaseCharacter.h" /> <ClInclude Include="..\..\..\source\game\crosshair.h" /> <ClInclude Include="..\..\..\source\game\CrosshairManager.h" /> <ClInclude Include="..\..\..\source\game\EntityFactory.h" /> diff --git a/proj/sxgame/vs2013/sxgame.vcxproj.filters b/proj/sxgame/vs2013/sxgame.vcxproj.filters index 55022f88c..144db71d3 100644 --- a/proj/sxgame/vs2013/sxgame.vcxproj.filters +++ b/proj/sxgame/vs2013/sxgame.vcxproj.filters @@ -49,6 +49,18 @@ <Filter Include="Source Files\ents\triggers"> <UniqueIdentifier>{a19af9a9-9698-4f6e-94fc-fc12afaa10a2}</UniqueIdentifier> </Filter> + <Filter Include="Header Files\ents\characters"> + <UniqueIdentifier>{dd25ca33-fbd9-40fb-878e-4d2f1531565f}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files\ents\characters\npc"> + <UniqueIdentifier>{befd7b49-c663-45c4-87cf-9d481da7fb90}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files\ents\characters"> + <UniqueIdentifier>{9a873af0-2663-4675-9e2e-ce30a5bfc8ea}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files\ents\characters\npc"> + <UniqueIdentifier>{474c6cbf-9b16-4a74-876b-edd6fc116cbc}</UniqueIdentifier> + </Filter> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\..\source\game\sxgame_dll.cpp"> @@ -75,9 +87,6 @@ <ClCompile Include="..\..\..\source\game\SXplayerSpawn.cpp"> <Filter>Source Files\ents</Filter> </ClCompile> - <ClCompile Include="..\..\..\source\game\SXplayer.cpp"> - <Filter>Source Files\ents</Filter> - </ClCompile> <ClCompile Include="..\..\..\source\game\SXpointCamera.cpp"> <Filter>Source Files\ents</Filter> </ClCompile> @@ -111,12 +120,6 @@ <ClCompile Include="..\..\..\source\game\SXbaseWeapon.cpp"> <Filter>Source Files\ents\items\tools</Filter> </ClCompile> - <ClCompile Include="..\..\..\source\game\NPCBase.cpp"> - <Filter>Source Files\ents</Filter> - </ClCompile> - <ClCompile Include="..\..\..\source\game\NPCZombie.cpp"> - <Filter>Source Files\ents</Filter> - </ClCompile> <ClCompile Include="..\..\..\source\game\LightDirectional.cpp"> <Filter>Source Files\ents</Filter> </ClCompile> @@ -153,6 +156,18 @@ <ClCompile Include="..\..\..\source\game\SXbaseSupply.cpp"> <Filter>Source Files\ents\items</Filter> </ClCompile> + <ClCompile Include="..\..\..\source\game\NPCZombie.cpp"> + <Filter>Source Files\ents\characters\npc</Filter> + </ClCompile> + <ClCompile Include="..\..\..\source\game\NPCBase.cpp"> + <Filter>Source Files\ents\characters</Filter> + </ClCompile> + <ClCompile Include="..\..\..\source\game\SXplayer.cpp"> + <Filter>Source Files\ents\characters</Filter> + </ClCompile> + <ClCompile Include="..\..\..\source\game\CBaseCharacter.cpp"> + <Filter>Source Files\ents\characters</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\..\source\game\sxgame.h"> @@ -167,9 +182,6 @@ <ClInclude Include="..\..\..\source\game\SXbaseAnimating.h"> <Filter>Header Files\ents</Filter> </ClInclude> - <ClInclude Include="..\..\..\source\game\SXplayer.h"> - <Filter>Header Files\ents</Filter> - </ClInclude> <ClInclude Include="..\..\..\source\game\SXpointEntity.h"> <Filter>Header Files\ents</Filter> </ClInclude> @@ -221,12 +233,6 @@ <ClInclude Include="..\..\..\source\game\SXbaseWeapon.h"> <Filter>Header Files\ents\items\tools</Filter> </ClInclude> - <ClInclude Include="..\..\..\source\game\NPCBase.h"> - <Filter>Header Files\ents</Filter> - </ClInclude> - <ClInclude Include="..\..\..\source\game\NPCZombie.h"> - <Filter>Header Files\ents</Filter> - </ClInclude> <ClInclude Include="..\..\..\source\game\LightDirectional.h"> <Filter>Header Files\ents</Filter> </ClInclude> @@ -263,5 +269,17 @@ <ClInclude Include="..\..\..\source\game\SXbaseSupply.h"> <Filter>Header Files\ents\items</Filter> </ClInclude> + <ClInclude Include="..\..\..\source\game\SXplayer.h"> + <Filter>Header Files\ents\characters</Filter> + </ClInclude> + <ClInclude Include="..\..\..\source\game\NPCBase.h"> + <Filter>Header Files\ents\characters</Filter> + </ClInclude> + <ClInclude Include="..\..\..\source\game\NPCZombie.h"> + <Filter>Header Files\ents\characters\npc</Filter> + </ClInclude> + <ClInclude Include="..\..\..\source\game\CBaseCharacter.h"> + <Filter>Header Files\ents\characters</Filter> + </ClInclude> </ItemGroup> </Project> \ No newline at end of file diff --git a/source/game/CBaseCharacter.cpp b/source/game/CBaseCharacter.cpp new file mode 100644 index 000000000..9fc3897da --- /dev/null +++ b/source/game/CBaseCharacter.cpp @@ -0,0 +1,246 @@ + +#include "CBaseCharacter.h" +#include "GameData.h" +#include "SXbaseTool.h" +#include "SXbaseWeapon.h" + +/*! \skydocent base_character +������� ����� ��������� +*/ + +BEGIN_PROPTABLE(CBaseCharacter) + // empty +END_PROPTABLE() + +REGISTER_ENTITY_NOLISTING(CBaseCharacter, base_character); + +class btKinematicClosestNotMeRayResultCallback: public btCollisionWorld::ClosestRayResultCallback +{ +public: + btKinematicClosestNotMeRayResultCallback(btCollisionObject* me, const btVector3& rayFromWorld, const btVector3& rayToWorld): btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld) + { + m_me = me; + m_shapeInfo = {-1, -1}; + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) + { + if(rayResult.m_collisionObject == m_me) + return 1.0; + if(rayResult.m_localShapeInfo) + { + m_shapeInfo = *rayResult.m_localShapeInfo; + } + return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); + } + btCollisionWorld::LocalShapeInfo m_shapeInfo; +protected: + btCollisionObject* m_me; +}; + +CBaseCharacter::CBaseCharacter(EntityManager * pMgr): + BaseClass(pMgr), + m_uMoveDir(PM_OBSERVER), + m_vPitchYawRoll(float3_t(0, 0, 0)), + m_pActiveTool(NULL), + m_fCurrentSpread(0.0f) +{ + btTransform startTransform; + startTransform.setIdentity(); + startTransform.setOrigin(F3_BTVEC(m_vPosition)); + //startTransform.setOrigin(btVector3(0, 12, 10)); + + m_pGhostObject = new btPairCachingGhostObject(); + m_pGhostObject->setWorldTransform(startTransform); + //sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback()); + m_pCollideShape = new btCapsuleShape(0.4f, 1.0f); + m_pGhostObject->setCollisionShape(m_pCollideShape); + m_pGhostObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT); + m_pGhostObject->setUserPointer(this); + + btScalar stepHeight = 0.4f; + m_pCharacter = new btKinematicCharacterController(m_pGhostObject, (btConvexShape*)m_pCollideShape, stepHeight, btVector3(0.0f, 1.0f, 0.0f)); + m_pCharacter->setMaxJumpHeight(0.60f); + m_pCharacter->setJumpSpeed(3.50f); + //m_pCharacter->setJumpSpeed(3.5f); + m_pCharacter->setGravity(btVector3(0, -10.0f, 0)); + //m_pCharacter->setGravity(1.0f); + m_pCharacter->setFallSpeed(300.0f); + //m_pCharacter->setFallSpeed(30.0f); + + SXPhysics_GetDynWorld()->addCollisionObject(m_pGhostObject, btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::DebrisFilter); + + m_pGhostObject->setCollisionFlags(m_pGhostObject->getCollisionFlags() | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT); + + SXPhysics_GetDynWorld()->addAction(m_pCharacter); + + + m_flashlight = (CLightDirectional*)CREATE_ENTITY("light_directional", m_pMgr); + //m_flashlight->SetPos(GetPos() + float3(0.f, 0.1f, 0.f)); + m_flashlight->SetPos(GetPos() + float3(0.f, 0.2f, 0.1f)); + m_flashlight->SetOrient(GetOrient() * SMQuaternion(SM_PIDIV2, 'x')); + m_flashlight->SetParent(this); + m_flashlight->setDist(20.f); + m_flashlight->setAngle(SMToRadian(60)); + m_flashlight->setColor(float3(3.5, 3.5, 3.5)); + //m_flashlight->setShadowType(-1); + m_flashlight->setShadowType(1); + + m_idTaskSpread = SET_INTERVAL(updateSpread, 1.0f / 30.0f); +} + +CBaseCharacter::~CBaseCharacter() +{ + CLEAR_INTERVAL(m_idTaskSpread); + REMOVE_ENTITY(m_flashlight); +} + + +void CBaseCharacter::Attack(BOOL state) +{ + if(m_uMoveDir & PM_OBSERVER) + { + return; + } + if(m_pActiveTool) + { + m_pActiveTool->PrimaryAction(state); + } +} + +void CBaseCharacter::Attack2(BOOL state) +{ + if(m_uMoveDir & PM_OBSERVER) + { + return; + } + if(m_pActiveTool) + { + m_pActiveTool->SecondaryAction(state); + } +} + +void CBaseCharacter::Reload() +{ + if(m_uMoveDir & PM_OBSERVER) + { + return; + } + if(m_pActiveTool) + { + m_pActiveTool->Reload(); + } +} + +void CBaseCharacter::ToggleFlashlight() +{ + m_flashlight->toggleEnable(); +} + +void CBaseCharacter::nextFireMode() +{ + if(m_uMoveDir & PM_OBSERVER) + { + return; + } + if(m_pActiveTool) + { + //@FIXME: Add correct call + //m_pActiveTool->nextFireMode(); + } +} + +bool CBaseCharacter::onGround() +{ + return(m_pCharacter->onGround()); +} + +void CBaseCharacter::playFootstepsSound() +{ + if(!(m_uMoveDir & PM_OBSERVER)) + { + if(onGround()) + { + float3 start = GetPos(), + end = start + float3(0.0f, -2.0f, 0.0f); + btKinematicClosestNotMeRayResultCallback cb(m_pGhostObject, F3_BTVEC(start), F3_BTVEC(end)); + SXPhysics_GetDynWorld()->rayTest(F3_BTVEC(start), F3_BTVEC(end), cb); + + if(cb.hasHit() && cb.m_shapeInfo.m_shapePart == 0 && cb.m_shapeInfo.m_triangleIndex >= 0) + { + MTLTYPE_PHYSIC type = (MTLTYPE_PHYSIC)SXPhysics_GetMtlType(cb.m_collisionObject, &cb.m_shapeInfo); + g_pGameData->playFootstepSound(type, BTVEC_F3(cb.m_hitPointWorld)); + } + } + } +} + +float CBaseCharacter::getMomentSpread() +{ + if(!m_pActiveTool || !m_pActiveTool->isWeapon()) + { + return(0.0f); + } + + SXbaseWeapon *pWpn = (SXbaseWeapon*)m_pActiveTool; + + float fBaseSpread = pWpn->getBaseSpread(); + + const float fIdleSpreadBase = 1.0f, fIdleSpreadMult = pWpn->getSpreadCoeff(SPREAD_COEFF_IDLE), // ���� + fCrouchSpreadBase = 1.0f, fCrouchSpreadMult = pWpn->getSpreadCoeff(SPREAD_COEFF_CROUCH), // ���������� + fLaySpreadBase = 1.0f, fLaySpreadMult = pWpn->getSpreadCoeff(SPREAD_COEFF_CRAWL), // ���� + + fWalkSpreadBase = 1.0f, fWalkSpreadMult = pWpn->getSpreadCoeff(SPREAD_COEFF_WALK), // � ������ + fRunSpreadBase = 1.0f, fRunSpreadMult = pWpn->getSpreadCoeff(SPREAD_COEFF_RUN), // � ���� + fAirborneSpreadBase = 1.0f, fAirborneSpreadMult = pWpn->getSpreadCoeff(SPREAD_COEFF_AIRBORNE), // � ������ + fConditionSpreadBase = 1.0f, fConditionSpreadMult = pWpn->getSpreadCoeff(SPREAD_COEFF_CONDITION), // ��������� ������ + fArmSpreadBase = 1.0f, fArmSpreadMult = pWpn->getSpreadCoeff(SPREAD_COEFF_ARM), // ��������� ��� + fIronSightSpreadBase = 1.0f, fIronSightSpreadMult = pWpn->getSpreadCoeff(SPREAD_COEFF_IRONSIGHT); // � ������������ + + + + float fMomentSpread = fBaseSpread * + (fIdleSpreadBase + (!(m_uMoveDir & (PM_CROUCH | PM_CRAWL)) ? fIdleSpreadMult : 0.0f)) * + (fWalkSpreadBase + (((m_uMoveDir & (PM_FORWARD | PM_BACKWARD | PM_LEFT | PM_RIGHT)) && !(m_uMoveDir & PM_RUN)) ? fWalkSpreadMult : 0.0f)) * + (fCrouchSpreadBase + ((m_uMoveDir & PM_CROUCH) ? fCrouchSpreadMult : 0.0f)) * + (fRunSpreadBase + ((m_uMoveDir & PM_RUN) ? fRunSpreadMult : 0.0f)) * + (fLaySpreadBase + ((m_uMoveDir & PM_CRAWL) ? fLaySpreadMult : 0.0f)) * + (fAirborneSpreadBase + (!onGround() ? fAirborneSpreadMult : 0.0f)) * + (fConditionSpreadBase + (fConditionSpreadMult * (1.0f - pWpn->getCondition()))) * + // (fArmSpreadBase + (fArmSpreadMult * (1.0f - getArmCondition()))) * + (fIronSightSpreadBase + (pWpn->isIronSight() ? fIronSightSpreadMult : 0.0f)) + ; + + //printf("%5.3f => %5.3f\n", fMomentSpread, fBaseSpread); + if(fMomentSpread < fBaseSpread) + { + fMomentSpread = fBaseSpread; + } + return(fMomentSpread); +} + +void CBaseCharacter::updateSpread(float dt) +{ + float fMomentSpread = getMomentSpread(); + float fWeaponMass = m_pActiveTool ? m_pActiveTool->getWeight() : 0.0f; + //printf("%5.3f => %5.3f\n", fMomentSpread, m_fCurrentSpread); + if(m_fCurrentSpread < fMomentSpread) + { + m_fCurrentSpread += fMomentSpread * (3.0f * dt); + } + else + { + float fDivider = 5.0f; + float fCoeff = (3.0f * dt) * (fDivider / (fWeaponMass + (fDivider / 0.9f)) + 0.1f); + if(fCoeff > 1.0f) + { + fCoeff = 1.0f; + } + m_fCurrentSpread -= (m_fCurrentSpread - fMomentSpread) * fCoeff; + } +} + +float CBaseCharacter::getCurrentSpread() +{ + return(m_fCurrentSpread); +} diff --git a/source/game/CBaseCharacter.h b/source/game/CBaseCharacter.h new file mode 100644 index 000000000..8070cc03f --- /dev/null +++ b/source/game/CBaseCharacter.h @@ -0,0 +1,106 @@ + +/****************************************************** +Copyright � Vitaliy Buturlin, Evgeny Danilovich, 2017 +See the license in LICENSE +******************************************************/ + +/*! +\file +������� ����� ��������� +*/ + +/*! \ingroup cbaseanimating +@{ +*/ + +#ifndef _CBaseCharacter_H_ +#define _CBaseCharacter_H_ + +#include "SXbaseAnimating.h" +#include "LightDirectional.h" + +class SXbaseTool; + +//! ���� �������� ������ +enum PLAYER_MOVE +{ + PM_NONE = 0, + PM_FORWARD = 0x01, //!< ������ + PM_BACKWARD = 0x02, //!< ����� + PM_LEFT = 0x04, //!< ����� + PM_RIGHT = 0x08, //!< ������ + PM_CROUCH = 0x10, //!< �������� + PM_JUMP = 0x20, //!< �������� + PM_RUN = 0x40, //!< ������ + PM_CRAWL = 0x80, //!< ������ + PM_OBSERVER = 0x100, //!< ����������� + + PM_STOP = 0xFFFF +}; + +//! ����� ������ \ingroup cbaseanimating +class CBaseCharacter: public SXbaseAnimating +{ + DECLARE_CLASS(CBaseCharacter, SXbaseAnimating); + DECLARE_PROPTABLE(); +public: + CBaseCharacter(EntityManager * pMgr); + ~CBaseCharacter(); + + //! ���������/������������� ��������� ����� + void Attack(BOOL state); + //! ���������/������������� ��������� ����� + void Attack2(BOOL state); + //! ��������� ����������� ��������� ������ + void Reload(); + //! ��������/��������� ������ + void ToggleFlashlight(); + //! ����������� ����� �������� ��������� ������ + void nextFireMode(); + + //! ��������� �� ����� �� ����� + bool onGround(); + + //! ������������� ���� ����� � ������ ��������� �� ������� ����� ����� + void playFootstepsSound(); + + + //! �������� ������������ ��� �������� ������ ����������� �������� (� ������ �������� ��������) + float getCurrentSpread(); + +protected: + //! ������� + CLightDirectional* m_flashlight; + + //! ������� �������� + UINT m_uMoveDir; + + //! ������� ���������� � ����� + SXbaseTool * m_pActiveTool; + + //! ��� ������ @{ + btCollisionShape * m_pCollideShape; + btRigidBody * m_pRigidBody; + btPairCachingGhostObject * m_pGhostObject; + btKinematicCharacterController * m_pCharacter; + //! @} + + //! ���� �������� ������ + float3_t m_vPitchYawRoll; + + //! ���������� �������� ������������ �������� + float getMomentSpread(); + + //! ������ ���������� �������� + ID m_idTaskSpread; + + //! ��������� �������� �������� + virtual void updateSpread(float dt); + + //! ����������� �������� �������� + float m_fCurrentSpread; +}; + +#endif + +//! @} diff --git a/source/game/SXbaseItem.cpp b/source/game/SXbaseItem.cpp index 2374bca2d..78e585bd6 100644 --- a/source/game/SXbaseItem.cpp +++ b/source/game/SXbaseItem.cpp @@ -30,3 +30,8 @@ SXbaseItem::SXbaseItem(EntityManager * pMgr): m_bPickable(true) { } + +float SXbaseItem::getWeight() +{ + return(m_iInvWeight); +} diff --git a/source/game/SXbaseItem.h b/source/game/SXbaseItem.h index c0ce2ecd9..a6a8a1f88 100644 --- a/source/game/SXbaseItem.h +++ b/source/game/SXbaseItem.h @@ -32,6 +32,10 @@ public: int m_iInvStackMaxSize; //!< Максимальное количество итемов в стеке float m_iInvWeight; //!< Масса объекта bool m_bPickable; //!< Можно ли поднять объект + + + //! Масса объекта + virtual float getWeight(); }; #endif diff --git a/source/game/SXbaseTool.cpp b/source/game/SXbaseTool.cpp index 9b7ce26c3..50aa20e32 100644 --- a/source/game/SXbaseTool.cpp +++ b/source/game/SXbaseTool.cpp @@ -59,7 +59,8 @@ SXbaseTool::SXbaseTool(EntityManager * pMgr): m_iSoundAction2(-1), m_iMuzzleFlash(-1), m_iMuzzleFlash2(-1), - m_fMaxDistance(1000.0f) + m_fMaxDistance(1000.0f), + m_bIsWeapon(false) { m_bInvStackable = false; @@ -267,3 +268,13 @@ void SXbaseTool::_Rezoom() ((SXplayer*)m_pOwner)->GetCamera()->GetCamera()->SetFOV(SMToRadian(vlerp(*r_default_fov, *r_default_fov - 10.0f, m_fZoomProgress))); } } + +bool SXbaseTool::isWeapon() const +{ + return(m_bIsWeapon); +} + +float SXbaseTool::getCondition() const +{ + return(1.0f); +} diff --git a/source/game/SXbaseTool.h b/source/game/SXbaseTool.h index 4a34d6f65..3fa7ffcd3 100644 --- a/source/game/SXbaseTool.h +++ b/source/game/SXbaseTool.h @@ -58,6 +58,12 @@ public: void SetParent(SXbaseEntity * pEnt, int attachment = -1); + //! Этот инструмент - оружие + bool isWeapon() const; + + //! Состояние: 1 - целое; 0 - сломанное + float getCondition() const; + protected: bool m_bInPrimaryAction; @@ -105,6 +111,9 @@ protected: const char * m_szUsableAmmos; float m_fMaxDistance; + + //! Этот инструмент - оружие + bool m_bIsWeapon; }; #endif diff --git a/source/game/SXbaseWeapon.cpp b/source/game/SXbaseWeapon.cpp index f68fc039f..d8000cbcb 100644 --- a/source/game/SXbaseWeapon.cpp +++ b/source/game/SXbaseWeapon.cpp @@ -51,6 +51,28 @@ BEGIN_PROPTABLE(SXbaseWeapon) DEFINE_FIELD_INT(m_iCapacity, PDFF_NOEDIT | PDFF_NOEXPORT, "capacity", "", EDITOR_NONE) //! Текущая загрузка без учета магазина DEFINE_FIELD_INT(m_iCurrentLoad, PDFF_NOEDIT, "current_load", "", EDITOR_NONE) + + + //! угол (в градусах) базовой дисперсии оружия (оружия, зажатого в тисках) + DEFINE_FIELD_FLOAT(m_fBaseSpread, PDFF_NOEDIT | PDFF_NOEXPORT, "spread_base", "", EDITOR_NONE) + //! коэффициент разброса в стоя + DEFINE_FIELD_FLOAT(m_fSpreadIdle, PDFF_NOEDIT | PDFF_NOEXPORT, "spread_idle", "", EDITOR_NONE) + //! коэффициент разброса пригнувшись + DEFINE_FIELD_FLOAT(m_fSpreadCrouch, PDFF_NOEDIT | PDFF_NOEXPORT, "spread_crouch", "", EDITOR_NONE) + //! коэффициент разброса лежа + DEFINE_FIELD_FLOAT(m_fSpreadCrawl, PDFF_NOEDIT | PDFF_NOEXPORT, "spread_crawl", "", EDITOR_NONE) + //! коэффициент разброса в ходьбе + DEFINE_FIELD_FLOAT(m_fSpreadWalk, PDFF_NOEDIT | PDFF_NOEXPORT, "spread_walk", "", EDITOR_NONE) + //! коэффициент разброса в беге + DEFINE_FIELD_FLOAT(m_fSpreadRun, PDFF_NOEDIT | PDFF_NOEXPORT, "spread_run", "", EDITOR_NONE) + //! коэффициент разброса в полете (прыжок) + DEFINE_FIELD_FLOAT(m_fSpreadAirborne, PDFF_NOEDIT | PDFF_NOEXPORT, "spread_airborne", "", EDITOR_NONE) + //! коэффициент разброса от состояния оружия + DEFINE_FIELD_FLOAT(m_fSpreadCondition, PDFF_NOEDIT | PDFF_NOEXPORT, "spread_condition", "", EDITOR_NONE) + //! коэффициент разброса от состояния рук + DEFINE_FIELD_FLOAT(m_fSpreadArm, PDFF_NOEDIT | PDFF_NOEXPORT, "spread_arm", "", EDITOR_NONE) + //! коэффициент разброса в прицеливании + DEFINE_FIELD_FLOAT(m_fSpreadIronSight, PDFF_NOEDIT | PDFF_NOEXPORT, "spread_ironsight", "", EDITOR_NONE) END_PROPTABLE() REGISTER_ENTITY_NOLISTING(SXbaseWeapon, base_weapon); @@ -72,8 +94,21 @@ SXbaseWeapon::SXbaseWeapon(EntityManager * pMgr): m_idSndSwitch(-1), m_iCapacity(1), - m_iCurrentLoad(0) -{} + m_iCurrentLoad(0), + + m_fBaseSpread(0.33f), + m_fSpreadIdle(0.01f), + m_fSpreadCrouch(0.007f), + m_fSpreadCrawl(0.001f), + m_fSpreadWalk(1.0f), + m_fSpreadRun(4.0f), + m_fSpreadAirborne(5.0f), + m_fSpreadCondition(3.0f), + m_fSpreadArm(3.0f), + m_fSpreadIronSight(-0.8f) +{ + m_bIsWeapon = true; +} void SXbaseWeapon::OnPostLoad() { @@ -254,3 +289,49 @@ bool SXbaseWeapon::canShoot() { return(m_iCurrentLoad > 0 || (m_pMag && m_pMag->getLoad() > 0)); } + +float SXbaseWeapon::getWeight() +{ + return(m_iInvWeight + + (m_pHandle ? m_pHandle->getWeight() : 0.0f) + + (m_pScope ? m_pScope->getWeight() : 0.0f) + + (m_pMag ? m_pMag->getWeight() : 0.0f) + + (m_pSilencer ? m_pSilencer->getWeight() : 0.0f) + ); +} + +float SXbaseWeapon::getBaseSpread() const +{ + return(m_fBaseSpread); +} + +bool SXbaseWeapon::isIronSight() const +{ + return(m_iZoomable && m_bInSecondaryAction); +} + +float SXbaseWeapon::getSpreadCoeff(SPREAD_COEFF what) const +{ + switch(what) + { + case SPREAD_COEFF_IDLE: + return(m_fSpreadIdle); + case SPREAD_COEFF_CROUCH: + return(m_fSpreadCrouch); + case SPREAD_COEFF_CRAWL: + return(m_fSpreadCrawl); + case SPREAD_COEFF_WALK: + return(m_fSpreadWalk); + case SPREAD_COEFF_RUN: + return(m_fSpreadRun); + case SPREAD_COEFF_AIRBORNE: + return(m_fSpreadAirborne); + case SPREAD_COEFF_CONDITION: + return(m_fSpreadCondition); + case SPREAD_COEFF_ARM: + return(m_fSpreadArm); + case SPREAD_COEFF_IRONSIGHT: + return(m_fSpreadIronSight); + } + return(1.0f); +} diff --git a/source/game/SXbaseWeapon.h b/source/game/SXbaseWeapon.h index 7f46533db..8f8ecfe3f 100644 --- a/source/game/SXbaseWeapon.h +++ b/source/game/SXbaseWeapon.h @@ -28,6 +28,20 @@ enum FIRE_MODE }; #define FIRE_MODE_COUNT 3 +//! Идентификаторы для получения коэффициентов разброса +enum SPREAD_COEFF +{ + SPREAD_COEFF_IDLE, //!< стоя + SPREAD_COEFF_CROUCH, //!< пригувшись + SPREAD_COEFF_CRAWL, //!< лежа + SPREAD_COEFF_WALK, //!< в ходьбе + SPREAD_COEFF_RUN, //!< в беге + SPREAD_COEFF_AIRBORNE, //!< в прыжке + SPREAD_COEFF_CONDITION, //!< состояние оружия + SPREAD_COEFF_ARM, //!< состояние рук + SPREAD_COEFF_IRONSIGHT, //!< в прицеливании +}; + /*! Оружие \ingroup cbaseitem */ @@ -50,6 +64,19 @@ public: bool canShoot(); + //! Масса объекта + float getWeight(); + + + //! угол (в градусах) базовой дисперсии оружия (оружия, зажатого в тисках) + float getBaseSpread() const; + + //! в прицеливании + bool isIronSight() const; + + //! Коэффициент разброса + float getSpreadCoeff(SPREAD_COEFF what) const; + protected: // Compatible addons @@ -94,6 +121,18 @@ protected: // Without mag int m_iCapacity; int m_iCurrentLoad; + + // Spread + float m_fBaseSpread; + float m_fSpreadIdle; + float m_fSpreadCrouch; + float m_fSpreadCrawl; + float m_fSpreadWalk; + float m_fSpreadRun; + float m_fSpreadAirborne; + float m_fSpreadCondition; + float m_fSpreadArm; + float m_fSpreadIronSight; }; #endif diff --git a/source/game/SXplayer.cpp b/source/game/SXplayer.cpp index 40a8d7bc9..76e7fdf34 100644 --- a/source/game/SXplayer.cpp +++ b/source/game/SXplayer.cpp @@ -17,40 +17,13 @@ END_PROPTABLE() REGISTER_ENTITY(SXplayer, player); -class btKinematicClosestNotMeRayResultCallback: public btCollisionWorld::ClosestRayResultCallback -{ -public: - btKinematicClosestNotMeRayResultCallback(btCollisionObject* me, const btVector3& rayFromWorld, const btVector3& rayToWorld): btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld) - { - m_me = me; - m_shapeInfo = {-1, -1}; - } - - virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) - { - if(rayResult.m_collisionObject == m_me) - return 1.0; - if(rayResult.m_localShapeInfo) - { - m_shapeInfo = *rayResult.m_localShapeInfo; - } - return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); - } - btCollisionWorld::LocalShapeInfo m_shapeInfo; -protected: - btCollisionObject* m_me; -}; - SXplayer::SXplayer(EntityManager * pMgr): BaseClass(pMgr), - m_uMoveDir(PM_OBSERVER), - m_vPitchYawRoll(float3_t(0, 0, 0)), m_canJump(true), m_fViewbobStep(0.0f), m_fViewbobY(0.0f), m_fViewbobStrafe(float3_t(0, 0, 0)), m_vWpnShakeAngles(float3_t(0.0f, 0.0f, 0.0f)), - m_pActiveTool(NULL), m_iDSM(DSM_NONE) { m_pCamera = (SXpointCamera*)CREATE_ENTITY("point_camera", pMgr); @@ -58,38 +31,7 @@ SXplayer::SXplayer(EntityManager * pMgr): m_iUpdIval = SET_INTERVAL(UpdateInput, 0); - btTransform startTransform; - startTransform.setIdentity(); - startTransform.setOrigin(F3_BTVEC(m_vPosition)); - //startTransform.setOrigin(btVector3(0, 12, 10)); - m_pGhostObject = new btPairCachingGhostObject(); - m_pGhostObject->setWorldTransform(startTransform); - //sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback()); - m_pCollideShape = new btCapsuleShape(0.4f, 1.0f); - m_pGhostObject->setCollisionShape(m_pCollideShape); - m_pGhostObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT); - m_pGhostObject->setUserPointer(this); - - btScalar stepHeight = 0.4f; - m_pCharacter = new btKinematicCharacterController(m_pGhostObject, (btConvexShape*)m_pCollideShape, stepHeight, btVector3(0.0f, 1.0f, 0.0f)); - m_pCharacter->setMaxJumpHeight(0.60f); - m_pCharacter->setJumpSpeed(3.50f); - //m_pCharacter->setJumpSpeed(3.5f); - m_pCharacter->setGravity(btVector3(0, -10.0f, 0)); - //m_pCharacter->setGravity(1.0f); - m_pCharacter->setFallSpeed(300.0f); - //m_pCharacter->setFallSpeed(30.0f); - - SXPhysics_GetDynWorld()->addCollisionObject(m_pGhostObject, btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::DebrisFilter); - - m_pGhostObject->setCollisionFlags(m_pGhostObject->getCollisionFlags() | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT); - - SXPhysics_GetDynWorld()->addAction(m_pCharacter); - - - -/* m_pActiveTool = (SXbaseTool*)CREATE_ENTITY("weapon_ak74", m_pMgr); m_pActiveTool->SetOwner(this); m_pActiveTool->AttachHands(); @@ -97,19 +39,6 @@ SXplayer::SXplayer(EntityManager * pMgr): m_pActiveTool->SetPos(GetPos() + float3(1.0f, 0.0f, 1.0f)); m_pActiveTool->SetOrient(GetOrient()); m_pActiveTool->SetParent(this); - */ - - - m_flashlight = (CLightDirectional*)CREATE_ENTITY("light_directional", m_pMgr); - //m_flashlight->SetPos(GetPos() + float3(0.f, 0.1f, 0.f)); - m_flashlight->SetPos(GetPos() + float3(0.f, 0.2f, 0.1f)); - m_flashlight->SetOrient(GetOrient() * SMQuaternion(SM_PIDIV2, 'x')); - m_flashlight->SetParent(this); - m_flashlight->setDist(20.f); - m_flashlight->setAngle(SMToRadian(60)); - m_flashlight->setColor(float3(3.5, 3.5, 3.5)); - //m_flashlight->setShadowType(-1); - m_flashlight->setShadowType(1); m_idQuadCurr = -1; @@ -123,26 +52,6 @@ SXplayer::~SXplayer() REMOVE_ENTITY(m_pCamera); } -void SXplayer::playFootstepsSound() -{ - if(!(m_uMoveDir & PM_OBSERVER)) - { - if(onGround()) - { - float3 start = GetPos(), - end = start + float3(0.0f, -2.0f, 0.0f); - btKinematicClosestNotMeRayResultCallback cb(m_pGhostObject, F3_BTVEC(start), F3_BTVEC(end)); - SXPhysics_GetDynWorld()->rayTest(F3_BTVEC(start), F3_BTVEC(end), cb); - - if(cb.hasHit() && cb.m_shapeInfo.m_shapePart == 0 && cb.m_shapeInfo.m_triangleIndex >= 0) - { - MTLTYPE_PHYSIC type = (MTLTYPE_PHYSIC)SXPhysics_GetMtlType(cb.m_collisionObject, &cb.m_shapeInfo); - g_pGameData->playFootstepSound(type, BTVEC_F3(cb.m_hitPointWorld)); - } - } - } -} - void SXplayer::UpdateInput(float dt) { int x, y; @@ -436,60 +345,6 @@ void SXplayer::SetPos(const float3 & pos) m_pGhostObject->getWorldTransform().setOrigin(F3_BTVEC(pos)); } -void SXplayer::Attack(BOOL state) -{ - if(m_uMoveDir & PM_OBSERVER) - { - return; - } - if(m_pActiveTool) - { - m_pActiveTool->PrimaryAction(state); - } -} - -void SXplayer::Attack2(BOOL state) -{ - if(m_uMoveDir & PM_OBSERVER) - { - return; - } - if(m_pActiveTool) - { - m_pActiveTool->SecondaryAction(state); - } -} - -void SXplayer::Reload() -{ - if(m_uMoveDir & PM_OBSERVER) - { - return; - } - if(m_pActiveTool) - { - m_pActiveTool->Reload(); - } -} - -void SXplayer::ToggleFlashlight() -{ - m_flashlight->toggleEnable(); -} - -void SXplayer::nextFireMode() -{ - if(m_uMoveDir & PM_OBSERVER) - { - return; - } - if(m_pActiveTool) - { - //@FIXME: Add correct call - //m_pActiveTool->nextFireMode(); - } -} - void SXplayer::_ccmd_slot_on(int argc, const char ** argv) { if(argc != 2) @@ -530,7 +385,11 @@ float3_t & SXplayer::GetWeaponDeltaAngles() return(m_vWpnShakeAngles); } -bool SXplayer::onGround() +void SXplayer::updateSpread(float dt) { - return(m_pCharacter->onGround()); + BaseClass::updateSpread(dt); + if(m_pCrosshair) + { + m_pCrosshair->SetSize(getCurrentSpread() * 0.1f); + } } diff --git a/source/game/SXplayer.h b/source/game/SXplayer.h index 1abb17615..d0812e233 100644 --- a/source/game/SXplayer.h +++ b/source/game/SXplayer.h @@ -16,34 +16,14 @@ See the license in LICENSE #ifndef _SXplayer_H_ #define _SXplayer_H_ -#include "SXbaseAnimating.h" +#include "CBaseCharacter.h" #include "SXpointCamera.h" -#include "LightDirectional.h" #include "crosshair.h" -//! Типы движения игрока -enum PLAYER_MOVE -{ - PM_NONE = 0, - PM_FORWARD = 0x01, //!< вперед - PM_BACKWARD = 0x02, //!< назад - PM_LEFT = 0x04, //!< влево - PM_RIGHT = 0x08, //!< вправо - PM_CROUCH = 0x10, //!< присесть - PM_JUMP = 0x20, //!< прыгнуть - PM_RUN = 0x40, //!< бежать - PM_CRAWL = 0x80, //!< лежать - PM_OBSERVER = 0x100, //!< наблюдатель - - PM_STOP = 0xFFFF -}; - -class SXbaseTool; - //! Класс игрока \ingroup cbaseanimating -class SXplayer: public SXbaseAnimating +class SXplayer: public CBaseCharacter { - DECLARE_CLASS(SXplayer, SXbaseAnimating); + DECLARE_CLASS(SXplayer, CBaseCharacter); DECLARE_PROPTABLE(); public: SXplayer(EntityManager * pMgr); @@ -73,18 +53,7 @@ public: //! Устанавливает положение в мире void SetPos(const float3 & pos); - - //! Запускает/останавливает первичную атаку - void Attack(BOOL state); - //! Запускает/останавливает вторичную атаку - void Attack2(BOOL state); - //! Запускает перезарядку активного оружия - void Reload(); - //! Включает/выключает фонарь - void ToggleFlashlight(); - //! Переключает режим стрельбы активного оружия - void nextFireMode(); - + /*! Возаращает мировую позицию для модели оружия \note Устарело? */ @@ -99,37 +68,13 @@ public: //! Получает объект перекрестия Crosshair * GetCrosshair(); - //! Находится ли игрок на земле - bool onGround(); - - //! Воспроизводит звук шагов с учетом материала на котором стоит игрок - void playFootstepsSound(); - protected: - //! Фонарик - CLightDirectional* m_flashlight; //! Камера SXpointCamera * m_pCamera; - //! Текущее движение - UINT m_uMoveDir; - //! ID интервала обновления ID m_iUpdIval; - //! Углы вращения игрока - float3_t m_vPitchYawRoll; - - //! Для физики @{ - btCollisionShape * m_pCollideShape; - btRigidBody * m_pRigidBody; - btPairCachingGhostObject * m_pGhostObject; - btKinematicCharacterController * m_pCharacter; - //! @} - - //! Текущий инструмент в руках - SXbaseTool * m_pActiveTool; - //! Может ли прыгать bool m_canJump; @@ -146,6 +91,9 @@ protected: Crosshair * m_pCrosshair; ID m_idQuadCurr; //!< текущий квад аи сетки на котором стоит игрок + + //! Обновляет разброса значение + virtual void updateSpread(float dt); }; #endif diff --git a/source/game/crosshair.cpp b/source/game/crosshair.cpp index aa3abddf4..77d9950a9 100644 --- a/source/game/crosshair.cpp +++ b/source/game/crosshair.cpp @@ -67,8 +67,8 @@ void Crosshair::Update() static const int *r_win_height = GET_PCVAR_INT("r_win_height"); //build new buffer - float fScreenWidth = *r_win_width; - float fScreenHeight = *r_win_height; + float fScreenWidth = (float)*r_win_width; + float fScreenHeight = (float)*r_win_height; float fTexWidth = m_f2TexSize.x; float fTexHeight = m_f2TexSize.y; float fXradius = fTexWidth / fScreenWidth * 0.5f; @@ -359,6 +359,15 @@ void Crosshair::Render() SGCore_ShaderUnBind(); m_pDev->SetTexture(0, m_pTexture); m_pDev->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE); + + // Использовать альфа-канал в качестве источника альфа-компонент + m_pDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + m_pDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + + // Устанавливаем коэффициенты смешивания таким образом, + // чтобы альфа-компонента определяла прозрачность + m_pDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + m_pDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); //m_pDev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC); //m_pDev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); -- GitLab