Commit 34a3efba authored by D-AIRY's avatar D-AIRY

Added CBaseCharacter middleclass; Weapon fire spread calculation

parent 1a9ee0dd
......@@ -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
......
......@@ -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" />
......
......@@ -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
#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);
}
/******************************************************
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
//! @}
......@@ -30,3 +30,8 @@ SXbaseItem::SXbaseItem(EntityManager * pMgr):
m_bPickable(true)
{
}
float SXbaseItem::getWeight()
{
return(m_iInvWeight);
}
......@@ -32,6 +32,10 @@ public:
int m_iInvStackMaxSize; //!< Максимальное количество итемов в стеке
float m_iInvWeight; //!< Масса объекта
bool m_bPickable; //!< Можно ли поднять объект
//! Масса объекта
virtual float getWeight();
};
#endif
......
......@@ -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);
}
......@@ -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
......@@ -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);
}
......@@ -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
......@@ -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;