📄 weapon.cpp
字号:
// handles most cases
weapontype = WEAPON_2HANDED_HI;
// start off unattached
attached = false;
// maximum effective firing distance (for AI)
maxrange = 8192 * 2; // FIXME grr... magic number...
// minimum safe firing distance (for AI)
minrange = 0;
// speed of the projectile (0 == infinite speed)
projectilespeed = 0;
// default action_level_increment
action_level_increment = 2;
}
Weapon::~Weapon()
{
DetachGun();
}
void Weapon::CreateSpawnArgs
(
void
)
{
Item::CreateSpawnArgs();
G_SetIntArg( "ammo_in_clip", ammo_in_clip );
G_SetIntArg( "silenced", silenced );
G_SetIntArg( "weaponmode", weaponmode );
}
int Weapon::Rank
(
void
)
{
return rank;
}
int Weapon::Order
(
void
)
{
return order;
}
void Weapon::SetRank
(
int order,
int rank
)
{
this->order = order;
this->rank = rank;
}
void Weapon::SetType
(
weapontype_t type
)
{
weapontype = type;
}
weapontype_t Weapon::GetType
(
void
)
{
return weapontype;
}
void Weapon::SetAmmo
(
const char *type,
int amount,
int startamount
)
{
if ( type )
{
ammotype = type;
primary_ammo_type = type;
}
else
{
ammotype = "";
primary_ammo_type = "";
}
ammorequired = amount;
startammo = startamount;
}
void Weapon::SetSecondaryAmmo
(
const char *type,
int amount,
int startamount
)
{
if ( type )
{
secondary_ammo_type = type;
}
else
{
secondary_ammo_type = "";
}
secondary_ammorequired = amount;
}
void Weapon::SetAmmoAmount
(
int amount
)
{
if ( ammo_clip_size )
ammo_in_clip = amount;
}
void Weapon::UseAmmo
(
int amount
)
{
if ( ammo_clip_size )
{
ammo_in_clip -= amount;
if (ammo_in_clip < 0)
{
warning("UseAmmo","Used more ammo than in clip.\n");
ammo_in_clip = 0;
}
}
else
{
Ammo * ammo;
assert( owner );
if ( owner && owner->isClient() && !UnlimitedAmmo() )
{
if ( ammotype.length() )
{
ammo = ( Ammo * )owner->FindItem( ammotype.c_str() );
if ( weaponmode == PRIMARY )
{
if ( !ammo || !ammo->Use( ammorequired ) )
{
SetAmmoAmount( 0 );
return;
}
}
else
{
if ( !ammo || !ammo->Use( secondary_ammorequired ) )
{
SetAmmoAmount( 0 );
return;
}
}
SetAmmoAmount( ammo->Amount() );
}
}
}
}
Vector Weapon::MuzzleOffset
(
void
)
{
vec3_t trans[ 3 ];
vec3_t orient;
int groupindex;
int tri_num;
Vector offset = vec_zero;
int useanim;
int useframe;
// get the bone information
if ( ( !edict->s.gunmodelindex ) || ( owner && owner->isClient() ) )
{
if ( gi.GetBoneInfo( edict->s.modelindex, "barrel", &groupindex, &tri_num, orient ) )
{
if ( aimanim == -1 )
{
useanim = edict->s.anim;
useframe = edict->s.frame;
}
else
{
useanim = aimanim;
useframe = aimframe;
}
if ( gi.GetBoneTransform( edict->s.modelindex, groupindex, tri_num, orient, useanim, useframe,
edict->s.scale, trans, offset.vec3() ) )
{
//
// we scale the pos by 0.3 because of RF_DEPTHHACK
//
offset *= 0.3f;
if ( owner && owner->isClient() )
{
switch( owner->client->pers.hand )
{
case LEFT_HANDED:
offset[ 1 ] *= -1.0f;
break;
case CENTER_HANDED:
offset[ 1 ] = 0;
break;
}
}
}
}
}
//
// if it is a non-client, than get the information from the world model of the gun
//
else if ( gi.GetBoneInfo( edict->s.gunmodelindex, "barrel", &groupindex, &tri_num, orient ) )
{
gi.GetBoneTransform( edict->s.gunmodelindex, groupindex, tri_num, orient, 0, 0,
edict->s.scale, trans, offset.vec3() );
}
// Gun doesn't have a barrel, so search the owner for a barrel bone
else if ( owner && gi.GetBoneInfo( owner->edict->s.modelindex,
"barrel",
&groupindex,
&tri_num,
orient ) )
{
gi.GetBoneTransform( owner->edict->s.modelindex,
groupindex,
tri_num,
orient,
owner->edict->s.anim,
owner->edict->s.frame,
owner->edict->s.scale,
trans,
offset.vec3() );
}
return offset;
}
void Weapon::GetMuzzlePosition
(
Vector *position,
Vector *forward,
Vector *right,
Vector *up
)
{
Vector offset;
Vector f, r, u;
Vector pos;
Vector end;
Vector dir;
Vector gunpos;
trace_t trace;
assert( owner );
// technically, we should never not have an owner when firing.
if ( !owner )
{
return;
}
//
// get the position of the owners gun bone
//
gunpos = owner->GunPosition();
pos = gunpos;
owner->GetGunOrientation( pos, &f, &r, &u );
// get the bone information
offset = MuzzleOffset();
pos += f * offset[ 0 ];
pos -= r * offset[ 1 ];
pos += u * offset[ 2 ];
// prevent the creature from firing through walls
trace = G_Trace( gunpos, vec_zero, vec_zero, pos, owner, MASK_PROJECTILE, "Weapon::GetMuzzlePosition" );
if ( ( trace.fraction < 1 ) || ( trace.startsolid ) || ( trace.allsolid ) )
{
pos = gunpos;
pos -= r * offset[ 1 ];
pos += u * offset[ 2 ];
}
//
// calculate where this projectile is going to hit
//
end = gunpos + f*2048;
trace = G_FullTrace( gunpos, vec_zero, vec_zero, end, 10, owner, MASK_SHOT, "Weapon::GetMuzzlePosition" );
dir = trace.endpos - pos;
dir.normalize();
if ( dir*f < 0.707 )
dir = f;
if ( position )
{
*position = pos;
}
if ( forward )
{
*forward = dir;
}
if ( right )
{
*right = r;
}
if ( up )
{
*up = u;
}
}
void Weapon::SetAmmoClipSize
(
Event * ev
)
{
ammo_clip_size = ev->GetInteger( 1 );
}
void Weapon::SetModels
(
const char *world,
const char *view
)
{
Event *ev;
assert( view );
viewmodel = view;
modelIndex( view );
if ( world )
{
worldmodel = world;
modelIndex( world );
}
else
{
worldmodel = "";
}
if ( owner )
{
setModel( viewmodel );
}
else if ( worldmodel.length() )
{
setModel( worldmodel );
}
else
{
setModel( viewmodel );
}
if ( worldmodel.length() )
{
ev = new Event( EV_Weapon_ProcessModelCommands );
ev->AddInteger( modelIndex( worldmodel.c_str() ) );
PostEvent( ev, 0 );
}
ev = new Event( EV_Weapon_ProcessModelCommands );
ev->AddInteger( modelIndex( viewmodel.c_str() ) );
PostEvent( ev, 0 );
}
void Weapon::SetAimAnim
(
Event *ev
)
{
str anim;
anim = ev->GetString( 1 );
aimanim = gi.Anim_NumForName( edict->s.modelindex, anim.c_str() );
aimframe = ev->GetInteger( 2 );
}
void Weapon::SetOwner
(
Sentient *ent
)
{
assert( ent );
if ( !ent )
{
// return to avoid any buggy behaviour
return;
}
Item::SetOwner( ent );
setOrigin( vec_zero );
setAngles( vec_zero );
if ( !viewmodel.length() )
{
error( "setOwner", "Weapon without viewmodel set" );
}
setModel( viewmodel );
if ( ent->isClient() && ammotype.length() && startammo && !G_GetSpawnArg( "savegame" ) )
{
ent->giveItem( ammotype.c_str(), startammo );
}
}
int Weapon::AmmoAvailable
(
void
)
{
Ammo *ammo;
if ( owner )
{
if ( ammotype.length() )
{
ammo = ( Ammo * )owner->FindItem( ammotype.c_str() );
if ( ammo )
{
return ammo->Amount();
}
}
}
return 0;
}
qboolean Weapon::UnlimitedAmmo
(
void
)
{
if ( !owner )
{
return false;
}
if ( !owner->isClient() || ( owner->flags & FL_GODMODE ) || DM_FLAG( DF_INFINITE_AMMO ) )
{
return true;
}
#ifdef SIN_ARCADE
if ( !sv_infinitebullets || !sv_infiniterockets || !sv_infiniteplasma || !sv_infinitespears || !sv_infinitesniper )
{
sv_infinitebullets = gameVars.CreateVariable( "infinitebullets", 0 );
sv_infiniterockets = gameVars.CreateVariable( "infiniterockets", 0 );
sv_infiniteplasma = gameVars.CreateVariable( "infiniteplasma", 0 );
sv_infinitespears = gameVars.CreateVariable( "infinitespears", 0 );
sv_infinitesniper = gameVars.CreateVariable( "infinitesniper", 0 );
}
if ( sv_infinitebullets->intValue() && ( ( !Q_strncasecmp( ammotype.c_str(), "bullet", 6 ) && ( ammotype != "BulletPulse" ) &&
( ammotype != "BulletSniper" ) ) || ( ammotype == "ShotgunClip" ) ) )
{
return true;
}
if ( sv_infiniterockets->intValue() && ( ammotype == "Rockets" ) )
{
return true;
}
if ( sv_infiniteplasma->intValue() && ( ammotype == "BulletPulse" ) )
{
return true;
}
if ( sv_infinitesniper->intValue() && ( ammotype == "BulletSniper" ) )
{
return true;
}
if ( sv_infinitespears->intValue() && ( ammotype == "Spears" ) )
{
return true;
}
#endif
return false;
}
qboolean Weapon::HasAmmo
(
void
)
{
if ( !owner )
{
return false;
}
if ( UnlimitedAmmo() )
{
return true;
}
if ( weaponmode == PRIMARY )
{
if ( ( ammo_clip_size && ammo_in_clip >= ammorequired ) || AmmoAvailable() >= ammorequired )
{
return true;
}
}
else
{
if ( ( ammo_clip_size && ammo_in_clip >= secondary_ammorequired ) || AmmoAvailable() >= secondary_ammorequired )
{
return true;
}
}
return false;
}
qboolean Weapon::HasAmmoInClip
(
void
)
{
if ( ammo_clip_size )
{
if ( weaponmode == PRIMARY )
{
if ( ammo_in_clip >= ammorequired )
{
return true;
}
}
else
{
if ( ammo_in_clip >= secondary_ammorequired )
{
return true;
}
}
}
else
{
return HasAmmo();
}
return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -