Newer
Older
/***********************************************************
Copyright © Vitaliy Buturlin, Evgeny Danilovich, 2017, 2018
See the license in LICENSE
***********************************************************/
#include <decals/sxdecals.h>
/*! \skydocent base_tool
Базовый класс для инструмента (в т.ч оружие). То, что игрок может взять в руки и использовать
*/
DEFINE_FIELD_FLOAT(m_fReloadTime, PDFF_NOEDIT | PDFF_NOEXPORT, "reload_time", "", EDITOR_NONE)
DEFINE_FIELD_FLOAT(m_fZoomTime, PDFF_NOEDIT | PDFF_NOEXPORT, "zoom_time", "", EDITOR_NONE)
DEFINE_FIELD_VECTOR(m_vSlotPos, PDFF_NOEDIT | PDFF_NOEXPORT, "slot_offset", "", EDITOR_NONE)
DEFINE_FIELD_ANGLES(m_qSlotRot, PDFF_NOEDIT | PDFF_NOEXPORT, "slot_rotation", "", EDITOR_NONE)
DEFINE_FIELD_VECTOR(m_vSlotPosAim, PDFF_NOEDIT | PDFF_NOEXPORT, "slot_offset_aim", "", EDITOR_NONE)
DEFINE_FIELD_ANGLES(m_qSlotRotAim, PDFF_NOEDIT | PDFF_NOEXPORT, "slot_rotation_aim", "", EDITOR_NONE)
//! Смещение визуальной модели при приближении к стене
DEFINE_FIELD_VECTOR(m_vSlotPosClose, PDFF_NOEDIT | PDFF_NOEXPORT, "slot_offset_close", "", EDITOR_NONE)
//! Вращение визуальной модели при приближении к стене
DEFINE_FIELD_ANGLES(m_qSlotRotClose, PDFF_NOEDIT | PDFF_NOEXPORT, "slot_rotation_close", "", EDITOR_NONE)
//! Расстояние от центра модели до кончика ствола
DEFINE_FIELD_FLOAT(m_fCenterLength, PDFF_NOEDIT | PDFF_NOEXPORT, "center_length", "", EDITOR_NONE)
DEFINE_FIELD_INT(m_iZoomable, PDFF_NOEDIT | PDFF_NOEXPORT, "zoomable", "", EDITOR_NONE)
DEFINE_FIELD_STRING(m_szPrimaryActionSound, PDFF_NOEDIT | PDFF_NOEXPORT, "action1_sound", "", EDITOR_NONE)
DEFINE_FIELD_STRING(m_szSecondaryActionSound, PDFF_NOEDIT | PDFF_NOEXPORT, "action2_sound", "", EDITOR_NONE)
DEFINE_FIELD_STRING(m_szPrimaryActionMuzzleflash, PDFF_NOEDIT | PDFF_NOEXPORT, "action1_muzzle", "", EDITOR_NONE)
DEFINE_FIELD_STRING(m_szSecondaryActionMuzzleflash, PDFF_NOEDIT | PDFF_NOEXPORT, "action2_muzzle", "", EDITOR_NONE)
DEFINE_FIELD_FLOAT(m_fMaxDistance, PDFF_NOEDIT | PDFF_NOEXPORT, "max_distance", "", EDITOR_NONE)
DEFINE_FIELD_STRING(m_szUsableAmmos, PDFF_NOEDIT | PDFF_NOEXPORT, "ammos", "", EDITOR_NONE)
//! Класс заряженного в данный момент припаса
DEFINE_FIELD_STRING(m_szLoadedAmmo, PDFF_NOEDIT | PDFF_NOEXPORT, "loaded_ammo", "", EDITOR_NONE)
REGISTER_ENTITY_NOLISTING(CBaseTool, base_tool);
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;
};
CBaseTool::CBaseTool(CEntityManager * pMgr):
BaseClass(pMgr),
m_bInPrimaryAction(false),
m_bInSecondaryAction(false),
m_bWorldModel(false),
m_bCanUse(true),
m_fZoomTime(0.0f),
m_iZoomable(1),
m_iSoundAction1(-1),
m_iSoundAction2(-1),
m_iMuzzleFlash(-1),
m_iMuzzleFlash2(-1),
m_fMaxDistance(1000.0f),
m_iIvalUpdate = SET_INTERVAL(_update, 0);
Byurrrer
committed
m_iSoundAction1 = SSCore_SndCreate3dInst(m_szPrimaryActionSound, SX_SOUND_CHANNEL_GAME, 100);
Byurrrer
committed
m_iSoundAction2 = SSCore_SndCreate3dInst(m_szSecondaryActionSound, SX_SOUND_CHANNEL_GAME, 100);
}
if(m_szPrimaryActionMuzzleflash[0])
{
m_iMuzzleFlash = SPE_EffectInstanceByName(m_szPrimaryActionMuzzleflash);
}
if(m_szSecondaryActionMuzzleflash[0])
{
m_iMuzzleFlash2 = SPE_EffectInstanceByName(m_szSecondaryActionMuzzleflash);
}
}
void CBaseTool::setNextUse(float time)
void CBaseTool::primaryAction(BOOL st)
SPE_EffectSetEnable(m_iMuzzleFlash, true);
Byurrrer
committed
SSCore_SndInstancePlay3d(m_iSoundAction1, false, false, &getPos());
float3 start = getPos();
float3 dir = m_pParent->getOrient() * float3(0.0f, 0.0f, 1.0f);
btCollisionWorld::ClosestRayResultCallback cb(F3_BTVEC(start), F3_BTVEC(end));
SPhysics_GetDynWorld()->rayTest(F3_BTVEC(start), F3_BTVEC(end), cb);
if(cb.hasHit())
{
//shoot decal
SXDecals_ShootDecal(DECAL_TYPE_CONCRETE, BTVEC_F3(cb.m_hitPointWorld), BTVEC_F3(cb.m_hitNormalWorld));
Byurrrer
committed
SPE_EffectPlayByName("fire", &BTVEC_F3(cb.m_hitPointWorld), &BTVEC_F3(cb.m_hitNormalWorld));
if(!cb.m_collisionObject->isStaticOrKinematicObject())
{
((btRigidBody*)cb.m_collisionObject)->applyCentralImpulse(F3_BTVEC(dir * 10.0f));
cb.m_collisionObject->activate();
}
}
void CBaseTool::secondaryAction(BOOL st)
((CPlayer*)m_pOwner)->getCrosshair()->enable(!st);
void CBaseTool::setIsWorldModel(bool b)
setNextUse(m_fReloadTime);
playAnimation("reload");
void CBaseTool::dbgMove(int dir, float dy)
case DSM_LEN:
m_fCenterLength += dy;
break;
printf(COLOR_GREEN "slot_offset = " COLOR_LGREEN "%f %f %f\n"
COLOR_GREEN "slot_rotation = " COLOR_LGREEN "%f %f %f %f\n"
COLOR_GREEN "center_length = " COLOR_LGREEN "%f\n" COLOR_RESET
, m_qSlotRotResult.x, m_qSlotRotResult.y, m_qSlotRotResult.z, m_qSlotRotResult.w
, m_fCenterLength);
if(m_pOwner)
{
float3_t ang = ((CPlayer*)m_pOwner)->getWeaponDeltaAngles();
m_vOffsetOrient = m_qSlotRotResult * SMQuaternion(ang.x, 'x') * SMQuaternion(ang.y, 'y') * SMQuaternion(ang.z, 'z');
}
else
{
m_vOffsetOrient = m_qSlotRotResult;
}
Byurrrer
committed
{
float3 pos = m_pModel->asAnimatedModel()->getBoneTransformPos(m_pModel->asAnimatedModel()->getBoneId("muzzle_rifle1"));
SPE_EffectSetPos(m_iMuzzleFlash, &pos);
SPE_EffectSetRotQ(m_iMuzzleFlash, m_vOrientation);
Byurrrer
committed
}
if(m_inventoryMode == IIM_EQUIPPED && m_fCenterLength > 0.4f /* player capsule radius */)
{
// raycast towards to check if
float3 start = m_pParent->getPos();
float3 dir = m_pParent->getOrient() * float3(0.0f, 0.0f, 1.0f);
float3 end = start + dir * m_fCenterLength;
btKinematicClosestNotMeRayResultCallback cb(((CBaseCharacter*)m_pOwner)->getBtCollisionObject(), F3_BTVEC(start), F3_BTVEC(end));
SPhysics_GetDynWorld()->rayTest(F3_BTVEC(start), F3_BTVEC(end), cb);
m_isClose = cb.hasHit();
}
bool needRezoom = false;
float speed = 1.0f / m_fZoomTime;
if(m_bInSecondaryAction && m_iZoomable)
if(m_fZoomProgress > 1.0f)
{
m_fZoomProgress = 1.0f;
}
if(m_fZoomProgress < 0.0f)
{
m_fZoomProgress = 0.0f;
}
needRezoom = true;
}
}
if(m_isClose)
{
if(m_fCloseProgress < 1.0f)
{
m_fCloseProgress += dt * speed;
if(m_fCloseProgress > 1.0f)
{
m_fCloseProgress = 1.0f;
}
needRezoom = true;
else
{
if(m_fCloseProgress > 0.0f)
{
m_fCloseProgress -= dt * speed;
if(m_fCloseProgress < 0.0f)
{
m_fCloseProgress = 0.0f;
}
needRezoom = true;
}
}
if(needRezoom)
{
_rezoom();
}
void CBaseTool::setParent(CBaseEntity * pEnt, int attachment)
BaseClass::setParent(pEnt, attachment);
const float * r_default_fov = GET_PCVAR_FLOAT("r_default_fov");
m_vSlotPosResult = (float3)vlerp(vlerp(m_vSlotPos, m_vSlotPosClose, m_fCloseProgress), m_vSlotPosAim, m_fZoomProgress);
m_qSlotRotResult = SMquaternionSlerp(SMquaternionSlerp(m_qSlotRot, m_qSlotRotClose, m_fCloseProgress), m_qSlotRotAim, m_fZoomProgress);
if(m_pOwner && m_pOwner->getClassName() && !fstrcmp(m_pOwner->getClassName(), "player"))
((CPlayer*)m_pOwner)->getCamera()->getCamera()->setFOV(SMToRadian(vlerp(*r_default_fov, *r_default_fov - 10.0f, m_fZoomProgress)));
{
return(m_bIsWeapon);
}
float CBaseTool::getCondition() const
{
return(1.0f);
}
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
CBaseSupply *CBaseTool::getAmmo() const
{
return(m_pLoadedAmmo);
}
void CBaseTool::chargeAmmo(CBaseSupply *pAmmo)
{
if(!pAmmo || !isValidAmmo(pAmmo))
{
return;
}
if(getAmmo())
{
uncharge();
}
m_pLoadedAmmo = pAmmo;
m_pLoadedAmmo->setParent(this);
_setStrVal(&m_szLoadedAmmo, m_pLoadedAmmo->getClassName());
}
void CBaseTool::uncharge()
{
if(!getAmmo())
{
return;
}
_setStrVal(&m_szLoadedAmmo, "");
m_pLoadedAmmo->setParent(NULL);
//getOwner()->getInventory()->put(getAmmo());
m_pLoadedAmmo = NULL;
}
bool CBaseTool::isValidAmmo(CBaseSupply *pAmmo)
{
const char * str = strstr(m_szUsableAmmos, pAmmo->getClassName());
if(str)
{
char chr = str[strlen(pAmmo->getClassName())];
return(chr == ',' || chr == 0);
}
return(false);
}
float CBaseTool::getMaxDistance() const
{
return(m_fMaxDistance);
}
void CBaseTool::stopAction()
{
}