📄 weapon_brickbat.cpp
字号:
//=========== (C) Copyright 2000 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: This is the brickbat weapon
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "NPCEvent.h"
#include "basehlcombatweapon.h"
#include "basecombatcharacter.h"
#include "AI_BaseNPC.h"
#include "AI_Memory.h"
#include "player.h"
#include "gamerules.h" // For g_pGameRules
#include "weapon_brickbat.h"
#include "grenade_brickbat.h"
#include "ammodef.h"
#include "in_buttons.h"
#include "game.h"
#include "IEffects.h"
#include "vstdlib/random.h"
#include "baseviewmodel.h"
#include "movevars_shared.h"
extern ConVar sk_npc_dmg_brickbat;
extern ConVar sk_plr_dmg_brickbat;
struct BrickbatAmmo_s
{
const char *m_sClassName;
int m_nAmmoType;
int m_nMaxCarry;
const char *m_sViewModel;
const char *m_sWorldModel;
};
BrickbatAmmo_s BrickBatAmmoArray[NUM_BRICKBAT_AMMO_TYPES] =
{
{ "grenade_rockbb", BRICKBAT_ROCK, 5, "models/weapons/v_bb_bottle.mdl", "models/props_junk/Rock001a.mdl" },
{ "grenade_beerbottle", BRICKBAT_BOTTLE, 3, "models/weapons/v_bb_bottle.mdl", "models/weapons/w_bb_bottle.mdl" },
{ "grenade_crematorhead", BRICKBAT_CREMATORHEAD, 1, "models/weapons/v_bb_crematorhead.mdl", "models/cremator_head.mdl" },
};
IMPLEMENT_SERVERCLASS_ST(CWeaponBrickbat, DT_WeaponBrickbat)
END_SEND_TABLE()
//LINK_ENTITY_TO_CLASS( weapon_brickbat, CWeaponBrickbat );
//PRECACHE_WEAPON_REGISTER(weapon_brickbat);
acttable_t CWeaponBrickbat::m_acttable[] =
{
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_THROW, true },
};
IMPLEMENT_ACTTABLE(CWeaponBrickbat);
BEGIN_DATADESC( CWeaponBrickbat )
DEFINE_FIELD( CWeaponBrickbat, m_bNeedDraw, FIELD_BOOLEAN ),
DEFINE_FIELD( CWeaponBrickbat, m_bNeedThrow, FIELD_BOOLEAN ),
DEFINE_FIELD( CWeaponBrickbat, m_iThrowBits, FIELD_INTEGER ),
DEFINE_FIELD( CWeaponBrickbat, m_fNextThrowCheck, FIELD_TIME ),
DEFINE_FIELD( CWeaponBrickbat, m_vecTossVelocity, FIELD_VECTOR ),
DEFINE_ARRAY( CWeaponBrickbat, m_nAmmoCount, FIELD_INTEGER, NUM_BRICKBAT_AMMO_TYPES ),
DEFINE_KEYFIELD( CWeaponBrickbat, m_iCurrentAmmoType, FIELD_INTEGER, "BrickbatType" ),
// Function Pointers
DEFINE_FUNCTION( CWeaponBrickbat, BrickbatTouch ),
END_DATADESC()
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CWeaponBrickbat::Precache( void )
{
for (int i=0;i<ARRAYSIZE(BrickBatAmmoArray);i++)
{
engine->PrecacheModel(BrickBatAmmoArray[i].m_sWorldModel);
engine->PrecacheModel(BrickBatAmmoArray[i].m_sViewModel);
}
UTIL_PrecacheOther("grenade_molotov");
BaseClass::Precache();
}
void CWeaponBrickbat::Spawn( void )
{
m_bNeedDraw = true;
m_bNeedThrow = false;
for (int i=0;i<NUM_BRICKBAT_AMMO_TYPES;i++)
{
m_nAmmoCount[i] = 0;
}
// Call base class first
BaseClass::Spawn();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CWeaponBrickbat::GetViewModel( int viewmodelindex /*=0*/ )
{
return BrickBatAmmoArray[m_iCurrentAmmoType].m_sViewModel;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CWeaponBrickbat::GetWorldModel( void )
{
return BrickBatAmmoArray[m_iCurrentAmmoType].m_sWorldModel;
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
bool CWeaponBrickbat::Deploy( void )
{
SetModel( GetViewModel() );
m_bNeedDraw = false;
m_bNeedThrow = false;
return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_VM_DRAW, (char*)GetAnimPrefix() );
}
//------------------------------------------------------------------------------
// Purpose : Override to use brickbats pickup touch function
// Input :
// Output :
//------------------------------------------------------------------------------
void CWeaponBrickbat::SetPickupTouch( void )
{
SetTouch( BrickbatTouch );
}
//------------------------------------------------------------------------------
// Purpose : Override base class so can be picked up with physics gun
// Input :
// Output :
//------------------------------------------------------------------------------
void CWeaponBrickbat::SetObjectCollisionBox( void )
{
BaseClass::BaseClass::SetObjectCollisionBox();
}
//-----------------------------------------------------------------------------
// Purpose: Override so give correct ammo
// Input : pOther - the entity that touched me
// Output :
//-----------------------------------------------------------------------------
void CWeaponBrickbat::BrickbatTouch( CBaseEntity *pOther )
{
// ---------------------------------------------------
// First give weapon to touching entity if allowed
// Skip ammo given portion by setting clips to zero
// and handle ammo giving here
// ---------------------------------------------------
BaseClass::DefaultTouch(pOther);
//FIXME: This ammo handling code is a bit bogus, need a real solution if brickbats are going to live
/*
// ----------------------------------------------------
// Give brickbat ammo if touching client
// ----------------------------------------------------
if (pOther->GetFlags() & FL_CLIENT)
{
CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pOther );
// Exit if game rules say I can't have any more of this ammo type.
if ( g_pGameRules->CanHaveAmmo( pBCC, m_iPrimaryAmmoType ) == false )
return;
// ------------------------------------------------
// If already owned weapon of this type remove me
// ------------------------------------------------
CWeaponBrickbat* oldWeapon = (CWeaponBrickbat*)pBCC->Weapon_OwnsThisType( GetClassname() );
// Remove physics object if is one
VPhysicsDestroyObject();
if ( ( oldWeapon != NULL ) && ( oldWeapon != this ) )
{
// Only pick up if not at max ammo amount
if (oldWeapon->m_nAmmoCount[m_iCurrentAmmoType] < BrickBatAmmoArray[m_iCurrentAmmoType].m_nMaxCarry)
{
oldWeapon->m_nAmmoCount[m_iCurrentAmmoType]++;
pBCC->GiveAmmo( 1, oldWeapon->m_iPrimaryAmmoType );
UTIL_Remove( this );
}
}
else
{
// Only pick up if not at max ammo amount
if (m_nAmmoCount[m_iCurrentAmmoType] < BrickBatAmmoArray[m_iCurrentAmmoType].m_nMaxCarry)
{
m_nAmmoCount[m_iCurrentAmmoType]++;
pBCC->GiveAmmo( 1, m_iPrimaryAmmoType );
SetThink (NULL);
}
}
// -----------------------------------------------------
// Switch to this weapon if the only weapon I own
// -----------------------------------------------------
if (!pBCC->GetActiveWeapon() && pBCC->GetActiveWeapon() != this)
{
pBCC->Weapon_Switch(oldWeapon);
}
}
*/
}
//-----------------------------------------------------------------------------
// Purpose: Gets event from anim stream and throws the object
// Input :
// Output :
//-----------------------------------------------------------------------------
void CWeaponBrickbat::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator )
{
switch( pEvent->event )
{
case EVENT_WEAPON_THROW:
{
CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer();
if (!pNPC)
{
return;
}
Vector vec_target = pNPC->GetEnemyLKP();
// -----------------------------------------------------
// Get position of throw
// -----------------------------------------------------
// If owner has a hand, set position to the hand bone position
Vector launchPos;
int iBIndex = pNPC->LookupBone("Bip01 R Hand");
if (iBIndex != -1) {
Vector origin;
QAngle angles;
pNPC->GetBonePosition( iBIndex, launchPos, angles);
}
// Otherwise just set to in front of the owner
else {
Vector vFacingDir = pNPC->BodyDirection2D( );
vFacingDir = vFacingDir * 60.0;
launchPos = pNPC->GetLocalOrigin()+vFacingDir;
}
ThrowBrickbat( launchPos, m_vecTossVelocity, sk_npc_dmg_brickbat.GetFloat());
// Drop the weapon and remove as no more ammo
pNPC->Weapon_Drop( this );
UTIL_Remove( this );
}
break;
default:
BaseClass::Operator_HandleAnimEvent( pEvent, pOperator );
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
bool CWeaponBrickbat::ObjectInWay( void )
{
CBaseCombatCharacter *pOwner = GetOwner();
if (!pOwner)
{
return false;
}
Vector vecSrc = pOwner->Weapon_ShootPosition( );
Vector vecAiming = pOwner->BodyDirection2D( );
trace_t tr;
Vector vecEnd = vecSrc + (vecAiming * 32);
UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
if (tr.fraction < 1.0)
{
// Don't block on a living creature
if (tr.m_pEnt)
{
CBaseEntity *pEntity = tr.m_pEnt;
CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity );
if (pBCC)
{
return false;
}
}
return true;
}
else
{
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose: Override to allow throw w/o LOS
// Input :
// Output :
//-----------------------------------------------------------------------------
bool CWeaponBrickbat::WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos,bool bSetConditions)
{
// <<TODO>> should test if can throw from present location here...
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Override to check throw
// Input :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -