📄 weapon.cpp
字号:
(
Event *ev
)
{
Ammo *ammo;
int amount;
amount = ammo_clip_size - ammo_in_clip;
assert( owner );
if ( owner && owner->isClient() && !UnlimitedAmmo() )
{
if ( ammotype.length() )
{
ammo = ( Ammo * )owner->FindItem( ammotype.c_str() );
if ( ammo )
{
if ( ammo->Amount() < amount )
amount = ammo->Amount();
if ( !ammo->Use( amount ) )
{
amount = 0;
}
}
SetAmmoAmount( amount + ammo_in_clip );
}
}
else
{
SetAmmoAmount( ammo_clip_size );
}
ForceIdle();
if ( owner )
{
owner->ProcessEvent( EV_Sentient_WeaponReady );
}
}
qboolean Weapon::ForceReload
(
void
)
{
if ( weaponstate != WEAPON_READY )
return false;
if ( level.cinematic && owner && owner->isClient() )
{
return false;
}
// do a reload if the ammo in clip is not full,
// and there is some ammo available out of clip
if (
( ammo_clip_size != ammo_in_clip ) &&
( AmmoAvailable() > 0 )
)
{
weaponstate = WEAPON_RELOADING;
if ( ( owner ) && ( owner->flags & FL_SILENCER ) && ( silenced ) )
RandomAnimate( "silreload", EV_Weapon_DoneReloading );
else
RandomAnimate( "reload", EV_Weapon_DoneReloading );
return true;
}
return false;
}
qboolean Weapon::CheckReload
(
void
)
{
if ( weaponstate != WEAPON_READY )
return false;
if ( level.cinematic && owner && owner->isClient() )
{
return false;
}
if ( ammo_clip_size && !ammo_in_clip && HasAmmo() )
{
weaponstate = WEAPON_RELOADING;
if ( ( owner ) && ( owner->flags & FL_SILENCER ) && ( silenced ) )
RandomAnimate( "silreload", EV_Weapon_DoneReloading );
else
RandomAnimate( "reload", EV_Weapon_DoneReloading );
return true;
}
return false;
}
void Weapon::Idle
(
Event *ev
)
{
if ( ammo_clip_size && ( !ammo_in_clip || level.time > last_attack_time + 2 ) )
{
if (CheckReload())
return;
}
ForceIdle();
}
void Weapon::FinishAttack
(
Event *ev
)
{
attack_finished = level.time;
}
void Weapon::NextAttack
(
double rate
)
{
attack_finished = level.time + (float)rate;
}
float Weapon::GetMaxRange
(
void
)
{
return maxrange;
}
float Weapon::GetMinRange
(
void
)
{
return minrange;
}
float Weapon::GetProjectileSpeed
(
void
)
{
return projectilespeed;
}
void Weapon::SetMaxRangeEvent
(
Event *ev
)
{
maxrange = ev->GetFloat( 1 );
}
void Weapon::SetMinRangeEvent
(
Event *ev
)
{
minrange = ev->GetFloat( 1 );
}
void Weapon::SetProjectileSpeedEvent
(
Event *ev
)
{
projectilespeed = ev->GetFloat( 1 );
}
void Weapon::NotDroppableEvent
(
Event *ev
)
{
notdroppable = true;
}
void Weapon::SetMaxRange
(
float val
)
{
maxrange = val;
}
void Weapon::SetMinRange
(
float val
)
{
minrange = val;
}
void Weapon::SetProjectileSpeed
(
float val
)
{
projectilespeed = val;
}
void Weapon::EventMuzzleFlash
(
Event *ev
)
{
if ( !owner )
{
return;
}
SpawnTempDlight
(
owner->worldorigin,
ev->GetFloat( 1 ),
ev->GetFloat( 2 ),
ev->GetFloat( 3 ),
ev->GetFloat( 4 ),
ev->GetFloat( 5 ),
ev->GetFloat( 6 )
);
}
void Weapon::MuzzleFlash
(
float r,
float g,
float b,
float radius,
float decay,
float life
)
{
if ( !owner )
{
return;
}
SpawnTempDlight
(
owner->worldorigin,
r,
g,
b,
radius,
decay,
life
);
}
void Weapon::BulletHole
(
trace_t *trace
)
{
Entity *hole;
Vector norm,norm2;
Entity *hit;
hit = trace->ent->entity;
if ( !hit )
{
return;
}
if ( trace->surface &&
( trace->surface->flags & SURF_NODRAW ) )
return;
if ( hit->hidden() )
return;
// FIXME: Make Bullet holes client side.
if ( deathmatch->value )
return;
hole = new Entity;
hole->setMoveType( MOVETYPE_PUSH );
hole->setSolidType( SOLID_NOT );
hole->setModel( "sprites/bullethole.spr" );
hole->setSize( "0 0 0", "0 0 0" );
norm = trace->plane.normal;
norm2.x = -norm.x;
norm2.y = -norm.y;
norm2.z = norm.z;
hole->angles = norm2.toAngles();
hole->setAngles( hole->angles );
hole->setOrigin( Vector( trace->endpos ) + ( norm * 0.2 ) ) ;
if ( ( trace->ent->solid == SOLID_BSP ) && ( hit != world ) )
{
hole->bind( hit );
}
queueBulletHoles.Enqueue(hole);
numBulletHoles++;
if (numBulletHoles > sv_maxbulletholes->value)
{
// Fade one out of the list.
Entity *fadehole;
fadehole = (Entity *) queueBulletHoles.Dequeue();
fadehole->ProcessEvent(EV_Remove);
numBulletHoles--;
}
}
EXPORT_FROM_DLL void Weapon::WeaponSound
(
Event *ev
)
{
Event *e;
// Broadcasting a sound can be time consuming. Only do it once in a while on really fast guns.
if ( nextweaponsoundtime > level.time )
{
if ( owner )
{
owner->BroadcastSound( ev, CHAN_WEAPON, NullEvent, 0 );
}
else
{
BroadcastSound( ev, CHAN_WEAPON, EV_HeardWeapon, 0 );
}
return;
}
if ( owner )
{
e = new Event( ev );
owner->ProcessEvent( e );
}
else
{
Item::WeaponSound( ev );
}
// give us some breathing room
nextweaponsoundtime = level.time + 0.4;
}
qboolean Weapon::Removable
(
void
)
{
if (
( ( int )( dmflags->value ) & DF_WEAPONS_STAY ) &&
!( spawnflags & ( DROPPED_ITEM | DROPPED_PLAYER_ITEM ) )
)
return false;
else
return true;
}
qboolean Weapon::Pickupable
(
Entity *other
)
{
Sentient *sen;
if ( !other->isSubclassOf( Sentient ) )
{
return false;
}
else if ( !other->isClient() )
{
return false;
}
sen = ( Sentient * )other;
//FIXME
// This should be in player
// Mutants can't pickup weapons
if ( other->flags & (FL_MUTANT|FL_SP_MUTANT) )
{
return false;
}
// If we have the weapon and weapons stay, then don't pick it up
if ( ( ( int )( dmflags->value ) & DF_WEAPONS_STAY ) && !( spawnflags & ( DROPPED_ITEM | DROPPED_PLAYER_ITEM ) ) )
{
Weapon *weapon;
weapon = ( Weapon * )sen->FindItem( getClassname() );
if ( weapon )
return false;
}
return true;
}
qboolean Weapon::AutoChange
(
void
)
{
return true;
}
int Weapon::ClipAmmo
(
void
)
{
if (ammo_clip_size)
return ammo_in_clip;
else
return -1;
}
void Weapon::ProcessWeaponCommandsEvent
(
Event *ev
)
{
int index;
index = ev->GetInteger( 1 );
ProcessInitCommands( index );
}
void Weapon::SetKick
(
Event *ev
)
{
kick = ev->GetInteger( 1 );
}
void Weapon::SecondaryUse
(
Event *ev
)
{
if ( !dualmode )
return;
// Switch to the secondary mode of the weapon
if (weaponstate != WEAPON_READY)
return;
weaponstate = WEAPON_CHANGING;
if (weaponmode == PRIMARY)
{
RandomAnimate( "primary2secondary", EV_Weapon_SecondaryMode );
weaponmode = SECONDARY;
}
else
{
RandomAnimate( "secondary2primary", EV_Weapon_PrimaryMode );
weaponmode = PRIMARY;
}
}
void Weapon::PrimaryMode
(
Event *ev
)
{
RandomAnimate( "primaryidle", EV_Weapon_Idle );
weaponstate = WEAPON_READY;
ammotype = primary_ammo_type;
}
void Weapon::SecondaryMode
(
Event *ev
)
{
RandomAnimate( "secondaryidle", EV_Weapon_Idle );
weaponstate = WEAPON_READY;
ammotype = secondary_ammo_type;
}
void Weapon::SetActionLevelIncrement
(
Event *ev
)
{
action_level_increment = ev->GetInteger( 1 );
}
int Weapon::ActionLevelIncrement
(
void
)
{
return action_level_increment;
}
qboolean Weapon::IsDroppable
(
void
)
{
if ( notdroppable || !worldmodel.length() )
{
return false;
}
else
{
return true;
}
}
qboolean Weapon::IsSilenced
(
void
)
{
return silenced;
}
void Weapon::Raise
(
Event *ev
)
{
weaponstate = WEAPON_HOLSTERED;
ReadyWeapon();
}
void Weapon::PutAwayAndRaise
(
Event *ev
)
{
weaponstate = WEAPON_LOWERING;
if ( deathmatch->value && ( ( int )dmflags->value & DF_FAST_WEAPONS ) )
{
ProcessEvent( EV_Weapon_DoneRaising );
return;
}
RandomAnimate( "putaway", EV_Weapon_Raise );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -