📄 weapon.cpp
字号:
}
void Weapon::ForceState
(
weaponstate_t state
)
{
weaponstate = state;
}
qboolean Weapon::AttackDone
(
void
)
{
return ( attack_finished <= level.time );
}
qboolean Weapon::ReadyToFire
(
void
)
{
return ( weaponstate == WEAPON_READY ) && AttackDone();
}
qboolean Weapon::ReadyToChange
(
void
)
{
return ( weaponstate == WEAPON_READY );
}
qboolean Weapon::ReadyToUse
(
void
)
{
return true;
}
qboolean Weapon::ChangingWeapons
(
void
)
{
return ( weaponstate == WEAPON_LOWERING ) || ( weaponstate == WEAPON_RAISING );
}
qboolean Weapon::WeaponRaising
(
void
)
{
return ( weaponstate == WEAPON_RAISING );
}
qboolean Weapon::WeaponPuttingAway
(
void
)
{
return ( weaponstate == WEAPON_LOWERING );
}
qboolean Weapon::Reloading
(
void
)
{
return ( weaponstate == WEAPON_RELOADING );
}
void Weapon::PutAway
(
void
)
{
if ( weaponstate != WEAPON_READY )
{
return;
}
weaponstate = WEAPON_LOWERING;
if ( !HasAnim( "putaway" ) || ( deathmatch->value && ( ( int )dmflags->value & DF_FAST_WEAPONS ) ) )
{
ProcessEvent( EV_Weapon_DoneLowering );
return;
}
if ( dualmode )
{
if ( weaponmode == PRIMARY )
RandomAnimate( "primaryputaway", EV_Weapon_DoneLowering );
else
RandomAnimate( "secondaryputaway", EV_Weapon_DoneLowering );
}
else
if ( ( owner ) && ( owner->flags & FL_SILENCER ) && ( silenced ) )
RandomAnimate( "silputaway", EV_Weapon_DoneLowering );
else
RandomAnimate( "putaway", EV_Weapon_DoneLowering );
//weaponmode = PRIMARY;
}
void Weapon::ReadyWeapon
(
void
)
{
str animname;
if ( weaponstate != WEAPON_HOLSTERED )
{
return;
}
weaponstate = WEAPON_RAISING;
AttachGun();
if ( ( owner ) && ( owner->flags & FL_SILENCER ) && ( silenced ) )
animname = "silready";
else
{
if ( weaponmode == SECONDARY )
animname = "secondaryready";
else
animname = "ready";
}
if ( !HasAnim( animname.c_str() ) || ( deathmatch->value && ( ( int )dmflags->value & DF_FAST_WEAPONS ) ) )
{
ProcessEvent( EV_Weapon_DoneRaising );
return;
}
RandomAnimate( animname.c_str(), EV_Weapon_DoneRaising );
}
void Weapon::DetachFromOwner
(
void
)
{
StopAnimating();
DetachGun();
weaponstate = WEAPON_HOLSTERED;
}
void Weapon::AttachToOwner
(
void
)
{
AttachGun();
ForceIdle();
}
qboolean Weapon::Drop
(
void
)
{
float radius;
Vector temp;
if ( !owner )
{
return false;
}
if ( !IsDroppable() )
{
return false;
}
DetachGun();
const gravityaxis_t &grav = gravity_axis[ gravaxis ];
temp[ grav.z ] = 40 * grav.sign;
if ( owner )
{
setOrigin( owner->worldorigin + temp );
}
else
{
setOrigin( worldorigin + temp );
}
setModel( worldmodel );
// hack to fix the bounds when the gun is dropped
//
// once dropped reset the rotated bounds
//
flags |= FL_ROTATEDBOUNDS;
gi.CalculateBounds( edict->s.modelindex, edict->s.scale, mins.vec3(), maxs.vec3() );
radius = ( mins - maxs ).length() * 0.25f;
mins.x = mins.y = -radius;
maxs.x = maxs.y = radius;
setSize( mins, maxs );
StopAnimating();
edict->s.frame = 0;
edict->s.anim = 0;
// drop the weapon
PlaceItem();
if ( owner )
{
temp[ grav.x ] = G_CRandom( 50 );
temp[ grav.y ] = G_CRandom( 50 );
temp[ grav.z ] = 100 * grav.sign;
velocity = owner->velocity * 0.5 + temp;
setAngles( owner->angles );
}
avelocity = Vector( 0, G_CRandom( 360 ), 0 );
if ( owner && owner->isClient() )
{
spawnflags |= DROPPED_PLAYER_ITEM;
if ( ammo_clip_size )
startammo = ammo_in_clip;
else
startammo = 0;
// If owner is dead, put all his ammo of that type in the gun.
if ( owner->deadflag )
{
startammo = AmmoAvailable();
}
}
else
{
spawnflags |= DROPPED_ITEM;
if ( ammo_clip_size && ammo_in_clip )
startammo = ammo_in_clip;
else
startammo >>= 2;
if ( startammo == 0 )
{
startammo = 1;
}
}
// Wait some time before the last owner can pickup this weapon
last_owner = owner;
last_owner_trigger_time = level.time + 2.5f;
// Cancel reloading events
CancelEventsOfType( EV_Weapon_DoneReloading );
// Remove this from the owner's item list
if ( owner )
{
owner->RemoveItem( this );
}
owner = NULL;
// Fade out dropped weapons, to keep down the clutter
PostEvent( EV_FadeOut, 30 );
return true;
}
void Weapon::Fire
(
void
)
{
if ( !ReadyToFire() )
{
return;
}
if ( !HasAmmoInClip() )
{
CheckReload();
return;
}
if ( weaponmode == PRIMARY )
UseAmmo( ammorequired );
else
UseAmmo( secondary_ammorequired );
weaponstate = WEAPON_FIRING;
CancelEventsOfType( EV_Weapon_DoneFiring );
// this is just a precaution that we can re-trigger
NextAttack( 5 );
if ( dualmode )
{
if ( weaponmode == PRIMARY )
{
RandomAnimate( "primaryfire", EV_Weapon_DoneFiring );
}
else
{
RandomAnimate( "secondaryfire", EV_Weapon_DoneFiring );
}
}
else
{
if ( ( owner ) && ( owner->flags & FL_SILENCER ) && ( silenced ) )
RandomAnimate( "silfire", EV_Weapon_DoneFiring );
else
RandomAnimate( "fire", EV_Weapon_DoneFiring );
}
last_attack_time = level.time;
}
//**********************************************************************************/
//
// Non-public Weapon functions
//
//**********************************************************************************/
void Weapon::DetachGun
(
void
)
{
if ( attached )
{
RandomGlobalSound("null_sound", 1, CHAN_WEAPONIDLE );
attached = false;
detach();
hideModel();
edict->s.gunmodelindex = 0;
edict->s.gunanim = 0;
edict->s.gunframe = 0;
edict->s.effects &= ~EF_SMOOTHANGLES;
}
}
//
// attach and detach the gun from the owner
//
void Weapon::AttachGun
(
void
)
{
int groupindex;
int tri_num;
Vector orient;
if ( !owner )
{
return;
}
if (attached)
DetachGun();
if ( gi.GetBoneInfo( owner->edict->s.modelindex, "gun", &groupindex, &tri_num, orient.vec3() ) )
{
attached = true;
attach( owner->entnum, groupindex, tri_num, orient );
showModel();
setOrigin( vec_zero );
edict->s.gunmodelindex = modelIndex( worldmodel.c_str() );
if ( edict->s.gunmodelindex )
{
edict->s.gunanim = gi.Anim_Random( edict->s.gunmodelindex, "idle" );
if ( edict->s.gunanim < 0 )
edict->s.gunanim = 0;
edict->s.gunframe = 0;
}
else
{
edict->s.gunanim = 0;
edict->s.gunframe = 0;
}
edict->s.effects |= EF_SMOOTHANGLES;
}
else
{
gi.dprintf( "attach failed\n" );
}
}
void Weapon::PickupWeapon
(
Event *ev
)
{
Sentient *sen;
Entity *other;
Weapon *weapon;
Weapon *current;
qboolean hasweapon;
qboolean giveammo;
Ammo *ammo;
other = ev->GetEntity( 1 );
assert( other );
if ( !other->isSubclassOf( Sentient ) )
{
return;
}
sen = ( Sentient * )other;
// If this is the last owner, check to see if he can pick it up
if ( ( sen == last_owner ) && ( level.time < last_owner_trigger_time ) )
{
return;
}
hasweapon = sen->HasItem( getClassname() );
giveammo = ( sen->isClient() && ammotype.length() && startammo );
// if he already has the weapon, don't pick it up if he doesn't need the ammo
if ( hasweapon )
{
if ( !giveammo )
{
return;
}
// check if he needs the ammo
ammo = ( Ammo * )sen->FindItem( ammotype.c_str() );
if ( ammo && ( ammo->Amount() >= ammo->MaxAmount() ) )
{
// doesn't need the ammo or the weapon, so return.
return;
}
}
weapon = ( Weapon * )ItemPickup( other );
if ( !weapon )
{
// Item Pickup failed, so don't give ammo either.
return;
}
//
// once picked up we don't want rotated bounds
//
flags &= ~FL_ROTATEDBOUNDS;
//FIXME
// Sentient should probably handle this when itempickup is called
// Check if we should switch his weapon
current = sen->CurrentWeapon();
if ( !hasweapon && current && ( current != weapon ) && ( current->AutoChange() ) &&
( ( current->Rank() < weapon->Rank() ) || ( !current->HasAmmo() && weapon->HasAmmo() ) ) )
{
sen->ChangeWeapon( weapon );
}
// check if we should give him ammo
if ( giveammo )
{
sen->giveItem( ammotype.c_str(), startammo );
}
}
void Weapon::ForceIdle
(
void
)
{
weaponstate = WEAPON_READY;
if ( dualmode )
{
if ( weaponmode == PRIMARY )
RandomAnimate( "primaryidle", EV_Weapon_Idle );
else
RandomAnimate( "secondaryidle", EV_Weapon_Idle );
}
else
{
if ( owner && ( owner->flags & FL_SILENCER ) && ( silenced ) )
RandomAnimate( "silidle", EV_Weapon_Idle );
else
RandomAnimate( "idle", EV_Weapon_Idle );
}
}
void Weapon::DoneLowering
(
Event *ev
)
{
weaponstate = WEAPON_HOLSTERED;
DetachGun();
if ( owner )
{
owner->ProcessEvent( EV_Sentient_WeaponPutAway );
}
StopAnimating();
}
void Weapon::DoneRaising
(
Event *ev
)
{
weaponstate = WEAPON_READY;
if ( !ForceReload() )
{
ForceIdle();
}
if ( !owner )
{
PostEvent( EV_Remove, 0 );
return;
}
// Set the ammo type
if (weaponmode == PRIMARY)
{
ammotype = primary_ammo_type;
}
else if ( weaponmode == SECONDARY )
{
ammotype = secondary_ammo_type;
}
if ( owner )
owner->ProcessEvent( EV_Sentient_WeaponReady );
}
void Weapon::DoneFiring
(
Event *ev
)
{
if ( !CheckReload() )
{
ForceIdle();
}
if ( owner )
{
owner->ProcessEvent( EV_Sentient_WeaponDoneFiring );
}
}
void Weapon::DoneReloading
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -