Skip to content
BaseTool.cpp 7.67 KiB
Newer Older

/***********************************************************
Copyright © Vitaliy Buturlin, Evgeny Danilovich, 2017, 2018
See the license in LICENSE
***********************************************************/

#include "BaseTool.h"
D-AIRY's avatar
D-AIRY committed
#include <particles/sxparticles.h>
#include "Player.h"
D-AIRY's avatar
D-AIRY committed
/*! \skydocent base_tool
Базовый класс для инструмента (в т.ч оружие). То, что игрок может взять в руки и использовать
*/


BEGIN_PROPTABLE(CBaseTool)
D-AIRY's avatar
D-AIRY committed
	//! Время перезарядки, с
	DEFINE_FIELD_FLOAT(m_fReloadTime, PDFF_NOEDIT | PDFF_NOEXPORT, "reload_time", "", EDITOR_NONE)
D-AIRY's avatar
D-AIRY committed
	//! Время прицеливания, с
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_FLOAT(m_fZoomTime, PDFF_NOEDIT | PDFF_NOEXPORT, "zoom_time", "", EDITOR_NONE)
D-AIRY's avatar
D-AIRY committed
	//! Смещение визуальной модели
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_VECTOR(m_vSlotPos, PDFF_NOEDIT | PDFF_NOEXPORT, "slot_offset", "", EDITOR_NONE)
D-AIRY's avatar
D-AIRY committed
	//! Вращение визуальной модели
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_ANGLES(m_qSlotRot, PDFF_NOEDIT | PDFF_NOEXPORT, "slot_rotation", "", EDITOR_NONE)
D-AIRY's avatar
D-AIRY committed
	//! Смещение визуальной модели в прицеливании
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_VECTOR(m_vSlotPosAim, PDFF_NOEDIT | PDFF_NOEXPORT, "slot_offset_aim", "", EDITOR_NONE)
D-AIRY's avatar
D-AIRY committed
	//! Вращение визуальной модели в прицеливании
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_ANGLES(m_qSlotRotAim, PDFF_NOEDIT | PDFF_NOEXPORT, "slot_rotation_aim", "", EDITOR_NONE)
D-AIRY's avatar
D-AIRY committed
	
D-AIRY's avatar
D-AIRY committed
	//! Разрешить прицеливание
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_INT(m_iZoomable, PDFF_NOEDIT | PDFF_NOEXPORT, "zoomable", "", EDITOR_NONE)

D-AIRY's avatar
D-AIRY committed
	//! Звук первичного действия
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_STRING(m_szPrimaryActionSound, PDFF_NOEDIT | PDFF_NOEXPORT, "action1_sound", "", EDITOR_NONE)
D-AIRY's avatar
D-AIRY committed
	//! Звук вторичного действия
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_STRING(m_szSecondaryActionSound, PDFF_NOEDIT | PDFF_NOEXPORT, "action2_sound", "", EDITOR_NONE)
D-AIRY's avatar
D-AIRY committed
	//! Эффект первичного действия
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_STRING(m_szPrimaryActionMuzzleflash, PDFF_NOEDIT | PDFF_NOEXPORT, "action1_muzzle", "", EDITOR_NONE)
D-AIRY's avatar
D-AIRY committed
	//! Эффект вторичного действия
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_STRING(m_szSecondaryActionMuzzleflash, PDFF_NOEDIT | PDFF_NOEXPORT, "action2_muzzle", "", EDITOR_NONE)
	
D-AIRY's avatar
D-AIRY committed
	//! Максимальная дальность
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_FLOAT(m_fMaxDistance, PDFF_NOEDIT | PDFF_NOEXPORT, "max_distance", "", EDITOR_NONE)
D-AIRY's avatar
D-AIRY committed
	//! Подходящие типы припасов, классы, через запятую
D-AIRY's avatar
D-AIRY committed
	DEFINE_FIELD_STRING(m_szUsableAmmos, PDFF_NOEDIT | PDFF_NOEXPORT, "ammos", "", EDITOR_NONE)

END_PROPTABLE()

REGISTER_ENTITY_NOLISTING(CBaseTool, base_tool);
CBaseTool::CBaseTool(CEntityManager * pMgr):
	BaseClass(pMgr),
	m_bInPrimaryAction(false),
	m_bInSecondaryAction(false),
	m_bWorldModel(false),
	m_bCanUse(true),
	m_fZoomTime(0.0f),
D-AIRY's avatar
D-AIRY committed
	m_fReloadTime(0.0f),
D-AIRY's avatar
D-AIRY committed
	m_fZoomProgress(0.0f),
	m_iZoomable(1),
	m_iSoundAction1(-1),
	m_iSoundAction2(-1),
	m_iMuzzleFlash(-1),
	m_iMuzzleFlash2(-1),
	m_fMaxDistance(1000.0f),
	m_bIsWeapon(false)
{
	m_bInvStackable = false;
	m_iIvalUpdate = SET_INTERVAL(_update, 0);
CBaseTool::~CBaseTool()
D-AIRY's avatar
D-AIRY committed
{
	CLEAR_INTERVAL(m_iIvalUpdate);
void CBaseTool::onPostLoad()
D-AIRY's avatar
D-AIRY committed
{
	BaseClass::onPostLoad();
D-AIRY's avatar
D-AIRY committed

	if(m_szPrimaryActionSound[0])
	{
		m_iSoundAction1 = SSCore_SndCreate3dInst(m_szPrimaryActionSound, false, 0, 100);
	}
	if(m_szSecondaryActionSound[0])
	{
		m_iSoundAction2 = SSCore_SndCreate3dInst(m_szSecondaryActionSound, false, 0, 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)
{
	m_bCanUse = false;
	SET_TIMEOUT(_allowUse, time);
bool CBaseTool::canUse()
{
	return(m_bCanUse);
}

void CBaseTool::primaryAction(BOOL st)
{
	m_bInPrimaryAction = st != FALSE;
D-AIRY's avatar
D-AIRY committed
	if(st)
	{
		playAnimation("shoot1");
D-AIRY's avatar
D-AIRY committed
		if(ID_VALID(m_iMuzzleFlash))
		{
			SPE_EffectEnableSet(m_iMuzzleFlash, true);
		}
		if(ID_VALID(m_iSoundAction1))
		{
			SSCore_SndInstancePlay3d(m_iSoundAction1, &getPos());
D-AIRY's avatar
D-AIRY committed
		}

		//((CPlayer*)m_pOwner)->is
		float3 start = getPos();
		float3 dir = m_pParent->getOrient() * float3(0.0f, 0.0f, 1.0f);
D-AIRY's avatar
D-AIRY committed
		float3 end = start + dir * m_fMaxDistance;
		btCollisionWorld::ClosestRayResultCallback cb(F3_BTVEC(start), F3_BTVEC(end));
		SXPhysics_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));
			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();
			}
		}
D-AIRY's avatar
D-AIRY committed
	}
void CBaseTool::secondaryAction(BOOL st)
{
	m_bInSecondaryAction = st != FALSE;
D-AIRY's avatar
D-AIRY committed
	if(m_iZoomable)
	{
		((CPlayer*)m_pOwner)->getCrosshair()->enable(!st);
D-AIRY's avatar
D-AIRY committed
	}
void CBaseTool::setIsWorldModel(bool b)
{
	m_bWorldModel = b;
}

void CBaseTool::reload()
	if(canUse())
		setNextUse(m_fReloadTime);
		playAnimation("reload");
void CBaseTool::attachHands()
D-AIRY's avatar
D-AIRY committed
{
	if(m_pAnimPlayer)
	{
		m_pAnimPlayer->addModel("models/weapons/hands.dse");
		m_pAnimPlayer->assembly();
void CBaseTool::dbgMove(int dir, float dy)
D-AIRY's avatar
D-AIRY committed
{
	switch(dir)
	{
	case DSM_POS_X:
		m_vOffsetPos.x += dy;
		break;
	case DSM_POS_Y:
		m_vOffsetPos.y += dy;
		break;
	case DSM_POS_Z:
		m_vOffsetPos.z += dy;
		break;
	case DSM_ROT_X:
D-AIRY's avatar
D-AIRY committed
		m_qSlotRotResult = m_qSlotRotResult * SMQuaternion(dy, 'x');
D-AIRY's avatar
D-AIRY committed
		break;
	case DSM_ROT_Y:
D-AIRY's avatar
D-AIRY committed
		m_qSlotRotResult = m_qSlotRotResult * SMQuaternion(dy, 'y');
D-AIRY's avatar
D-AIRY committed
		break;
	case DSM_ROT_Z:
D-AIRY's avatar
D-AIRY committed
		m_qSlotRotResult = m_qSlotRotResult * SMQuaternion(dy, 'z');
D-AIRY's avatar
D-AIRY committed
		break;

	case DSM_PRINT:
		printf(COLOR_GREEN "offset: " COLOR_LGREEN "%f %f %f\n"
			COLOR_GREEN "orient: " COLOR_LGREEN "%f %f %f %f\n" COLOR_RESET
			, m_vOffsetPos.x, m_vOffsetPos.y, m_vOffsetPos.z
D-AIRY's avatar
D-AIRY committed
			, m_qSlotRotResult.x, m_qSlotRotResult.y, m_qSlotRotResult.z, m_qSlotRotResult.w);
void CBaseTool::onSync()
D-AIRY's avatar
D-AIRY committed
{
	float3_t ang = ((CPlayer*)m_pOwner)->getWeaponDeltaAngles();
D-AIRY's avatar
D-AIRY committed
	m_vOffsetOrient = m_qSlotRotResult * SMQuaternion(ang.x, 'x') * SMQuaternion(ang.y, 'y') * SMQuaternion(ang.z, 'z');
	BaseClass::onSync();
	if(m_pAnimPlayer)
D-AIRY's avatar
D-AIRY committed
		//SPE_EffectPlayByID
		float3 pos = m_pAnimPlayer->getBoneTransformPos(m_pAnimPlayer->getBone("muzzle_rifle1"));
		//pos = m_vOrientation * float3(0, 0, 1);
		SPE_EffectRotSetQ(m_iMuzzleFlash, m_vOrientation);
void CBaseTool::_update(float dt)
D-AIRY's avatar
D-AIRY committed
{
D-AIRY's avatar
D-AIRY committed
	float speed = 1.0f / m_fZoomTime;
	if(m_bInSecondaryAction && m_iZoomable)
D-AIRY's avatar
D-AIRY committed
	{
		if(m_fZoomProgress < 1.0f)
		{
D-AIRY's avatar
D-AIRY committed
			m_fZoomProgress += dt * speed;
D-AIRY's avatar
D-AIRY committed
			if(m_fZoomProgress > 1.0f)
			{
				m_fZoomProgress = 1.0f;
			}
D-AIRY's avatar
D-AIRY committed
		}
	}
	else
	{
		if(m_fZoomProgress > 0.0f)
		{
D-AIRY's avatar
D-AIRY committed
			m_fZoomProgress -= dt * speed;
D-AIRY's avatar
D-AIRY committed
			if(m_fZoomProgress < 0.0f)
			{
				m_fZoomProgress = 0.0f;
			}
void CBaseTool::setParent(CBaseEntity * pEnt, int attachment)
D-AIRY's avatar
D-AIRY committed
{
	BaseClass::setParent(pEnt, attachment);
void CBaseTool::_rezoom()
D-AIRY's avatar
D-AIRY committed
{
	const float * r_default_fov = GET_PCVAR_FLOAT("r_default_fov");
D-AIRY's avatar
D-AIRY committed
	m_vOffsetPos = (float3)vlerp(m_vSlotPos, m_vSlotPosAim, m_fZoomProgress);
D-AIRY's avatar
D-AIRY committed
	//m_vWpnShakeAngles
	m_qSlotRotResult = SMquaternionSlerp(m_qSlotRot, m_qSlotRotAim, m_fZoomProgress);
	if(m_pOwner)
	{
		((CPlayer*)m_pOwner)->getCamera()->getCamera()->setFOV(SMToRadian(vlerp(*r_default_fov, *r_default_fov - 10.0f, m_fZoomProgress)));
D-AIRY's avatar
D-AIRY committed
}
bool CBaseTool::isWeapon() const
float CBaseTool::getCondition() const