Add modified source code in game directory (part 3)

This commit is contained in:
LegendGuard 2023-07-26 13:25:23 +02:00 committed by GitHub
parent e2d9b1df6a
commit b6b8a04ab2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 551 additions and 109 deletions

View file

@ -55,6 +55,8 @@ const idEventDef EV_Explode( "<explode>", NULL );
const idEventDef EV_Fizzle( "<fizzle>", NULL );
const idEventDef EV_RadiusDamage( "<radiusdmg>", "e" );
const idEventDef EV_GetProjectileState( "getProjectileState", NULL, 'd' );
// HEXEN : Zeroth
const idEventDef EV_Launch( "Launch", "vvvfff" );
CLASS_DECLARATION( idEntity, idProjectile )
EVENT( EV_Explode, idProjectile::Event_Explode )
@ -62,6 +64,8 @@ CLASS_DECLARATION( idEntity, idProjectile )
EVENT( EV_Touch, idProjectile::Event_Touch )
EVENT( EV_RadiusDamage, idProjectile::Event_RadiusDamage )
EVENT( EV_GetProjectileState, idProjectile::Event_GetProjectileState )
// HEXEN : Zeroth
EVENT( EV_Launch, idProjectile::Event_Launch )
END_CLASS
/*
@ -296,6 +300,12 @@ void idProjectile::Launch( const idVec3 &start, const idVec3 &dir, const idVec3
idMat3 axis;
int contents;
int clipMask;
// HEXEN : Zeroth
bool randomDirection;
idVec3 newDir;
bool randomVelocity;
float randomAngular;
idVec2 fuse_random;
// allow characters to throw projectiles during cinematics, but not the player
if ( owner.GetEntity() && !owner.GetEntity()->IsType( idPlayer::Type ) ) {
@ -309,12 +319,47 @@ void idProjectile::Launch( const idVec3 &start, const idVec3 &dir, const idVec3
spawnArgs.GetVector( "velocity", "0 0 0", velocity );
// HEXEN : Zeroth
randomDirection = spawnArgs.GetBool( "random_direction" );
randomVelocity = spawnArgs.GetBool( "random_velocity" );
// HEXEN : Zeroth
if ( randomVelocity ) {
velocity.x *= gameLocal.random.RandomFloat() + 0.5f;
velocity.y *= gameLocal.random.RandomFloat() + 0.5f;
velocity.z *= gameLocal.random.RandomFloat() + 0.5f;
}
// HEXEN : Zeroth
if ( randomDirection ) {
newDir.x = gameLocal.random.RandomInt( 360 ) - 180;
newDir.y = gameLocal.random.RandomInt( 360 ) - 180;
newDir.z = gameLocal.random.RandomInt( 360 ) - 180;
newDir.Normalize();
velocity = velocity.Length() * newDir;
}
speed = velocity.Length() * launchPower;
damagePower = dmgPower;
spawnArgs.GetAngles( "angular_velocity", "0 0 0", angular_velocity );
// HEXEN : Zeroth
randomAngular = spawnArgs.GetFloat( "random_angular_velocity" );
// HEXEN : Zeroth
if ( randomAngular != 0.0f ) {
angular_velocity.yaw += gameLocal.random.RandomInt( randomAngular );
angular_velocity.pitch += gameLocal.random.RandomInt( randomAngular );
angular_velocity.roll += gameLocal.random.RandomInt( randomAngular );
}
//
// // HEXEN : Zeroth
// SetAngles( idAngles( gameLocal.random.RandomInt( 360 * 2 ) - 360,
// gameLocal.random.RandomInt( 360 * 2 ) - 360,
// gameLocal.random.RandomInt( 360 * 2 ) - 360 ) );
linear_friction = spawnArgs.GetFloat( "linear_friction" );
angular_friction = spawnArgs.GetFloat( "angular_friction" );
contact_friction = spawnArgs.GetFloat( "contact_friction" );
@ -323,6 +368,12 @@ void idProjectile::Launch( const idVec3 &start, const idVec3 &dir, const idVec3
gravity = spawnArgs.GetFloat( "gravity" );
fuse = spawnArgs.GetFloat( "fuse" );
// HEXEN : Zeroth
fuse_random = spawnArgs.GetVec2( "fuse_random" );
if ( fuse_random.y > 0.0f ) {
fuse = gameLocal.random.CRandomFloat() * fuse_random.y + fuse_random.x;
}
projectileFlags.detonate_on_world = spawnArgs.GetBool( "detonate_on_world" );
projectileFlags.detonate_on_actor = spawnArgs.GetBool( "detonate_on_actor" );
projectileFlags.randomShaderSpin = spawnArgs.GetBool( "random_shader_spin" );
@ -377,8 +428,15 @@ void idProjectile::Launch( const idVec3 &start, const idVec3 &dir, const idVec3
physicsObj.SetGravity( gravVec * gravity );
physicsObj.SetContents( contents );
physicsObj.SetClipMask( clipMask );
physicsObj.SetLinearVelocity( axis[ 2 ] * speed + pushVelocity );
physicsObj.SetAngularVelocity( angular_velocity.ToAngularVelocity() * axis );
if ( spawnArgs.GetBool( "override_launch" ) ) {
physicsObj.SetLinearVelocity( velocity );
physicsObj.SetAngularVelocity( angular_velocity.ToAngularVelocity() );
} else {
physicsObj.SetLinearVelocity( axis[ 2 ] * speed + pushVelocity );
physicsObj.SetAngularVelocity( angular_velocity.ToAngularVelocity() * axis );
}
physicsObj.SetOrigin( start );
physicsObj.SetAxis( axis );
@ -586,7 +644,7 @@ bool idProjectile::Collide( const trace_t &collision, const idVec3 &velocity ) {
}
if ( damageDefName[0] != '\0' ) {
ent->Damage( this, owner.GetEntity(), dir, damageDefName, damageScale, CLIPMODEL_ID_TO_JOINT_HANDLE( collision.c.id ) );
ent->Damage( this, owner.GetEntity(), dir, damageDefName, damageScale, CLIPMODEL_ID_TO_JOINT_HANDLE( collision.c.id ), idVec3( collision.c.point ) );
ignore = ent;
}
}
@ -1539,7 +1597,7 @@ void idSoulCubeMissile::KillTarget( const idVec3 &dir ) {
if ( ( act->health > 0 ) && ownerEnt && ownerEnt->IsType( idPlayer::Type ) && ( ownerEnt->health > 0 ) && !act->spawnArgs.GetBool( "boss" ) ) {
static_cast<idPlayer *>( ownerEnt )->GiveHealthPool( act->health );
}
act->Damage( this, owner.GetEntity(), dir, spawnArgs.GetString( "def_damage" ), 1.0f, INVALID_JOINT );
act->Damage( this, owner.GetEntity(), dir, spawnArgs.GetString( "def_damage" ), 1.0f, INVALID_JOINT, idVec3( 0, 0, 0 ) );
act->GetAFPhysics()->SetTimeScale( 0.25 );
StartSound( "snd_explode", SND_CHANNEL_BODY, 0, false, NULL );
}
@ -1821,7 +1879,7 @@ void idBFGProjectile::Think( void ) {
if ( damageFreq && *(const char *)damageFreq && beamTargets[i].target.GetEntity() && beamTargets[i].target.GetEntity()->CanDamage( GetPhysics()->GetOrigin(), org ) ) {
org = beamTargets[i].target.GetEntity()->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
org.Normalize();
beamTargets[i].target.GetEntity()->Damage( this, owner.GetEntity(), org, damageFreq, ( damagePower ) ? damagePower : 1.0f, INVALID_JOINT );
beamTargets[i].target.GetEntity()->Damage( this, owner.GetEntity(), org, damageFreq, ( damagePower ) ? damagePower : 1.0f, INVALID_JOINT, idVec3( 0, 0, 0 ) );
} else {
beamTargets[i].renderEntity.shaderParms[ SHADERPARM_RED ] =
beamTargets[i].renderEntity.shaderParms[ SHADERPARM_GREEN ] =
@ -2020,7 +2078,7 @@ void idBFGProjectile::Explode( const trace_t &collision, idEntity *ignore ) {
if ( damage[0] && ( beamTargets[i].target.GetEntity()->entityNumber > gameLocal.numClients - 1 ) ) {
dir = beamTargets[i].target.GetEntity()->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
dir.Normalize();
beamTargets[i].target.GetEntity()->Damage( this, ownerEnt, dir, damage, damageScale, ( collision.c.id < 0 ) ? CLIPMODEL_ID_TO_JOINT_HANDLE( collision.c.id ) : INVALID_JOINT );
beamTargets[i].target.GetEntity()->Damage( this, ownerEnt, dir, damage, damageScale, ( collision.c.id < 0 ) ? CLIPMODEL_ID_TO_JOINT_HANDLE( collision.c.id ) : INVALID_JOINT, idVec3( collision.c.point ) );
}
}
@ -2067,6 +2125,8 @@ void idDebris::Spawn( void ) {
owner = NULL;
smokeFly = NULL;
smokeFlyTime = 0;
// HEXEN : Zeroth
randomPosInBounds = false;
}
/*
@ -2156,6 +2216,15 @@ void idDebris::Launch( void ) {
bool randomVelocity;
idMat3 axis;
// HEXEN : Zeroth
bool randomDirection;
bool randomPosition;
float direction_from_spawner;
idVec3 newDir;
idVec3 originBeforeAdjust;
float randomAngular;
idVec2 fuse_random;
renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
spawnArgs.GetVector( "velocity", "0 0 0", velocity );
@ -2170,6 +2239,18 @@ void idDebris::Launch( void ) {
fuse = spawnArgs.GetFloat( "fuse" );
randomVelocity = spawnArgs.GetBool ( "random_velocity" );
// HEXEN : Zeroth
randomPosition = spawnArgs.GetBool( "random_pos_in_spawner" );
randomDirection = spawnArgs.GetBool( "random_direction" );
direction_from_spawner = spawnArgs.GetFloat( "direction_from_spawner" );
randomAngular = spawnArgs.GetFloat( "random_angular_velocity" );
fuse_random = spawnArgs.GetVec2( "fuse_random" );
// HEXEN : Zeroth
if ( fuse_random.y > 0.0f ) {
fuse = gameLocal.random.CRandomFloat() * fuse_random.y + fuse_random.x;
}
if ( mass <= 0 ) {
gameLocal.Error( "Invalid mass on '%s'\n", GetEntityDefName() );
}
@ -2180,6 +2261,60 @@ void idDebris::Launch( void ) {
velocity.z *= gameLocal.random.RandomFloat() + 0.5f;
}
// HEXEN : Zeroth
if ( randomDirection ) {
newDir.x = gameLocal.random.RandomInt( 360 ) - 180;
newDir.y = gameLocal.random.RandomInt( 360 ) - 180;
newDir.z = gameLocal.random.RandomInt( 360 ) - 180;
newDir.Normalize();
velocity = velocity.Length() * newDir;
}
if ( randomPosition && randomPosInBounds ) {
// set origin to random position inside moveable's bounds
newDir.x = gameLocal.random.RandomFloat() * ( randomPosEnt->GetPhysics()->GetBounds()[1].x - randomPosEnt->GetPhysics()->GetBounds()[0].x );
newDir.x += randomPosEnt->GetPhysics()->GetBounds()[0].x;
newDir.y = gameLocal.random.RandomFloat() * ( randomPosEnt->GetPhysics()->GetBounds()[1].y - randomPosEnt->GetPhysics()->GetBounds()[0].y );
newDir.y += randomPosEnt->GetPhysics()->GetBounds()[0].y;
newDir.z = gameLocal.random.RandomFloat() * ( randomPosEnt->GetPhysics()->GetBounds()[1].z - randomPosEnt->GetPhysics()->GetBounds()[0].z );
newDir.z += randomPosEnt->GetPhysics()->GetBounds()[0].z;
newDir *= randomPosEnt->GetPhysics()->GetClipModel()->GetAxis();
newDir += randomPosEnt->GetPhysics()->GetOrigin();
GetPhysics()->SetOrigin( newDir );
// overrides "randomDirection"
if ( direction_from_spawner != 0 ) {
newDir = GetPhysics()->GetOrigin() - originBeforeAdjust;
newDir.Normalize();
velocity += direction_from_spawner * newDir;
// get center of bounds on moveable
newDir = randomPosEnt->GetPhysics()->GetBounds()[1] + randomPosEnt->GetPhysics()->GetBounds()[0];
newDir *= randomPosEnt->GetPhysics()->GetClipModel()->GetAxis();
// get vector from moveable's center to debris' origin
newDir = randomPosEnt->GetPhysics()->GetOrigin() - newDir;
newDir.Normalize();
// set velocity in that direction
velocity = velocity.Length() * newDir;
}
}
// HEXEN : Zeroth
if ( randomAngular != 0.0f ) {
angular_velocity.yaw += gameLocal.random.RandomInt( randomAngular );
angular_velocity.pitch += gameLocal.random.RandomInt( randomAngular );
angular_velocity.roll += gameLocal.random.RandomInt( randomAngular );
}
// HEXEN : Zeroth - why shoulnt the angles ever be not random ?
SetAngles( idAngles( gameLocal.random.RandomInt( 360 * 2 ) - 360,
gameLocal.random.RandomInt( 360 * 2 ) - 360,
gameLocal.random.RandomInt( 360 * 2 ) - 360 ) );
if ( health ) {
fl.takedamage = true;
}
@ -2216,8 +2351,28 @@ void idDebris::Launch( void ) {
}
physicsObj.SetBouncyness( bounce );
physicsObj.SetGravity( gravVec * gravity );
physicsObj.SetContents( 0 );
physicsObj.SetClipMask( MASK_SOLID | CONTENTS_MOVEABLECLIP );
if ( spawnArgs.GetBool ( "hascontents" ) ) {
if ( spawnArgs.GetFloat( "mass", "10", mass ) ) {
physicsObj.SetMass( mass );
}
if ( spawnArgs.GetBool( "noimpact" ) || spawnArgs.GetBool( "notPushable" )/** || IsType( idWood::Type )**/ ) { // HEXEN : Zeroth, added idWood
physicsObj.DisableImpact();
}
if ( spawnArgs.GetBool( "nonsolid" ) ) {
physicsObj.SetContents( CONTENTS_CORPSE | CONTENTS_RENDERMODEL );
physicsObj.SetClipMask( MASK_SOLID | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
} else {
physicsObj.SetContents( CONTENTS_SOLID );
physicsObj.SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
}
} else {
physicsObj.SetContents( 0 );
physicsObj.SetClipMask( MASK_SOLID | CONTENTS_MOVEABLECLIP );
}
physicsObj.SetLinearVelocity( axis[ 0 ] * velocity[ 0 ] + axis[ 1 ] * velocity[ 1 ] + axis[ 2 ] * velocity[ 2 ] );
physicsObj.SetAngularVelocity( angular_velocity.ToAngularVelocity() * axis );
physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
@ -2394,3 +2549,13 @@ idDebris::Event_Fizzle
void idDebris::Event_Fizzle( void ) {
Fizzle();
}
/*
================
Zeroth
idProjectile::Event_Launch
================
*/
void idProjectile::Event_Launch( const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity, const float timeSinceFire, const float launchPower, const float dmgPower ) {
Launch( start, dir, pushVelocity, timeSinceFire, launchPower, dmgPower );
}

View file

@ -33,6 +33,8 @@ If you have questions concerning this license or the applicable additional terms
#include "physics/Force_Constant.h"
#include "Entity.h"
#include "Moveable.h"
/*
===============================================================================
@ -124,13 +126,20 @@ protected:
private:
bool netSyncPhysics;
// HEXEN : Zeroth: changed to protected
protected:
void AddDefaultDamageEffect( const trace_t &collision, const idVec3 &velocity );
private:
void Event_Explode( void );
void Event_Fizzle( void );
void Event_RadiusDamage( idEntity *ignore );
void Event_Touch( idEntity *other, trace_t *trace );
void Event_GetProjectileState( void );
// HEXEN : Zeroth
private:
void Event_Launch( const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity, const float timeSinceFire, const float launchPower, const float dmgPower );
};
class idGuidedProjectile : public idProjectile {
@ -268,6 +277,10 @@ private:
void Event_Explode( void );
void Event_Fizzle( void );
public:
bool randomPosInBounds;
idMoveable *randomPosEnt;
};
#endif /* !__GAME_PROJECTILE_H__ */

View file

@ -1420,3 +1420,36 @@ void idPVS::ReadPVS( const pvsHandle_t handle, const idBitMsg &msg ) {
}
#endif
/*
================
Zeroth
idPVS::CheckAreasForPortalSky
================
*/
bool idPVS::CheckAreasForPortalSky( const pvsHandle_t handle, const idVec3 &origin ) {
int j, sourceArea;
if ( handle.i < 0 || handle.i >= MAX_CURRENT_PVS || handle.h != currentPVS[handle.i].handle.h ) {
return false;
}
sourceArea = gameRenderWorld->PointInArea( origin );
if ( sourceArea == -1 ) {
return false;
}
for ( j = 0; j < numAreas; j++ ) {
if ( !( currentPVS[ handle.i ].pvs[ j>>3 ] & ( 1 << ( j&7 ) ) ) ) {
continue;
}
if ( gameRenderWorld->CheckAreaForPortalSky( j ) ) {
return true;
}
}
return false;
}

View file

@ -97,6 +97,8 @@ public:
void ReadPVS( const pvsHandle_t handle, const idBitMsg &msg );
#endif
bool CheckAreasForPortalSky( const pvsHandle_t handle, const idVec3 &origin ); // HEXEN : Zeroth
private:
int numAreas;
int numPortals;

View file

@ -128,6 +128,14 @@ void idSound::Spawn( void ) {
} else {
timerOn = false;
}
// HEXEN : Zeroth
// ****** thanks SnoopJeDi ( http://www.doom3world.org/phpbb2/viewtopic.php?f=56&t=12469&p=214427#p214427 )
if ( spawnArgs.GetBool( "s_music" ) ) { //SnoopJeDi
gameLocal.musicSpeakers.Append( entityNumber );
}
// ******
}
/*
@ -260,6 +268,7 @@ idSound::DoSound
*/
void idSound::DoSound( bool play ) {
if ( play ) {
s_music_vol.SetModified(); // Zeroth: sometimes triggered speakers like to ignore that they're supposed to be faded
StartSoundShader( refSound.shader, SND_CHANNEL_ANY, refSound.parms.soundShaderFlags, true, &playingUntilTime );
playingUntilTime += gameLocal.time;
} else {

View file

@ -147,7 +147,7 @@ void idTarget_Damage::Event_Activate( idEntity *activator ) {
for( i = 0; i < targets.Num(); i++ ) {
ent = targets[ i ].GetEntity();
if ( ent ) {
ent->Damage( this, this, vec3_origin, damage, 1.0f, INVALID_JOINT );
ent->Damage( this, this, vec3_origin, damage, 1.0f, INVALID_JOINT, idVec3( 0, 0, 0 ) );
}
}
}
@ -195,6 +195,8 @@ idTarget_EndLevel::Event_Activate
*/
void idTarget_EndLevel::Event_Activate( idEntity *activator ) {
idStr nextMap;
idStr spawnPoint;
idStr endEoCRelease;
if ( spawnArgs.GetBool( "endOfGame" ) ) {
cvarSystem->SetCVarBool( "g_nightmare", true );
@ -207,6 +209,10 @@ void idTarget_EndLevel::Event_Activate( idEntity *activator ) {
return;
}
// HEXEN : Zeroth
spawnArgs.GetString( "spawnPoint", "", spawnPoint );
gameLocal.SetLocalPlayerSpawnPoint( spawnPoint );
if ( spawnArgs.GetInt( "devmap", "0" ) ) {
gameLocal.sessionCommand = "devmap "; // only for special demos
} else {

View file

@ -66,6 +66,9 @@ protected:
void Event_Enable( void );
void Event_Disable( void );
// void check_gravity();
void eoc_Check_Automap( idEntity *activator ); // HEXEN : Zeroth
const function_t * scriptFunction;
};
@ -195,6 +198,8 @@ public:
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void SetCount( int c ) { count = c; };
void SetGoal( int c ) { goal = c; };
void Spawn( void );
@ -230,10 +235,22 @@ public:
private:
bool on;
float delay;
int nextTime;
idList<idDict> nextTime;
void Event_Touch( idEntity *other, trace_t *trace );
void Event_Toggle( idEntity *activator );
// HEXEN : Zeroth
private:
bool dontTripby_LocalPlayer;
bool limitEntityType;
bool tripby_idPlayer;
bool tripby_idAI;
bool tripby_idMoveable;
bool tripby_idItem;
bool tripby_idActor;
bool tripby_idProjectile;
bool tripby_LocalPlayer;
};
@ -285,6 +302,36 @@ private:
idClipModel * clipModel;
void Event_Trigger( idEntity *activator );
// HEXEN : Zeroth - for trigger_enter
private:
bool onEntrance;
idList<idStr> touchingEntities;
idList<bool> flagEntities;
idList<int> resistTimeEntities;
// HEXEN : Zeroth - for limit entity types
private:
bool dontTripby_LocalPlayer;
bool limitEntityType;
bool tripby_idPlayer;
bool tripby_idAI;
bool tripby_idMoveable;
bool tripby_idItem;
bool tripby_idActor;
bool tripby_idProjectile;
// HEXEN : Zeroth - for trigger_hurtmulti
private:
bool hurtmulti;
// HEXEN : Zeroth - primarily for trigger_hurtmulti
private:
float delay;
// HEXEN : Zeroth - for trigger_hurtmulti
private:
idList<idDict> nextTime; // HEXEN : Zeroth. changed to idlist. not really useful anymore.
};
#endif /* !__GAME_TRIGGER_H__ */

View file

@ -52,8 +52,8 @@ const idEventDef EV_Weapon_Clear( "<clear>" );
const idEventDef EV_Weapon_GetOwner( "getOwner", NULL, 'e' );
const idEventDef EV_Weapon_Next( "nextWeapon" );
const idEventDef EV_Weapon_State( "weaponState", "sd" );
const idEventDef EV_Weapon_UseAmmo( "useAmmo", "d" );
const idEventDef EV_Weapon_AddToClip( "addToClip", "d" );
const idEventDef EV_Weapon_UseAmmo( "useAmmo", "f" );
const idEventDef EV_Weapon_AddToClip( "addToClip", "f" );
const idEventDef EV_Weapon_AmmoInClip( "ammoInClip", NULL, 'f' );
const idEventDef EV_Weapon_AmmoAvailable( "ammoAvailable", NULL, 'f' );
const idEventDef EV_Weapon_TotalAmmoCount( "totalAmmoCount", NULL, 'f' );
@ -321,10 +321,10 @@ void idWeapon::Save( idSaveGame *savefile ) const {
savefile->WriteVec3( muzzle_kick_offset );
savefile->WriteInt( ammoType );
savefile->WriteInt( ammoRequired );
savefile->WriteInt( clipSize );
savefile->WriteInt( ammoClip );
savefile->WriteInt( lowAmmo );
savefile->WriteFloat( ammoRequired );
savefile->WriteFloat( clipSize );
savefile->WriteFloat( ammoClip );
savefile->WriteFloat( lowAmmo );
savefile->WriteBool( powerAmmo );
// savegames <= 17
@ -374,8 +374,12 @@ void idWeapon::Save( idSaveGame *savefile ) const {
savefile->WriteFloat( weaponOffsetScale );
savefile->WriteBool( allowDrop );
savefile->WriteObject( projectileEnt );
// HEXEN : Zeroth
savefile->WriteInt( projectileEnts.Num() );
for ( int i = 0; i < projectileEnts.Num(); i++ ) {
savefile->WriteObject( projectileEnts[i] );
}
}
/*
@ -395,6 +399,7 @@ void idWeapon::Restore( idRestoreGame *savefile ) {
// Re-link script fields
WEAPON_ATTACK.LinkTo( scriptObject, "WEAPON_ATTACK" );
WEAPON_ATTACK2.LinkTo( scriptObject, "WEAPON_ATTACK2" ); // HEXEN : Zeroth
WEAPON_RELOAD.LinkTo( scriptObject, "WEAPON_RELOAD" );
WEAPON_NETRELOAD.LinkTo( scriptObject, "WEAPON_NETRELOAD" );
WEAPON_NETENDRELOAD.LinkTo( scriptObject, "WEAPON_NETENDRELOAD" );
@ -474,10 +479,10 @@ void idWeapon::Restore( idRestoreGame *savefile ) {
savefile->ReadVec3( muzzle_kick_offset );
savefile->ReadInt( (int &)ammoType );
savefile->ReadInt( ammoRequired );
savefile->ReadInt( clipSize );
savefile->ReadInt( ammoClip );
savefile->ReadInt( lowAmmo );
savefile->ReadFloat( ammoRequired );
savefile->ReadFloat( clipSize );
savefile->ReadFloat( ammoClip );
savefile->ReadFloat( lowAmmo );
savefile->ReadBool( powerAmmo );
// savegame versions <= 17
@ -528,7 +533,15 @@ void idWeapon::Restore( idRestoreGame *savefile ) {
savefile->ReadFloat( weaponOffsetScale );
savefile->ReadBool( allowDrop );
savefile->ReadObject( reinterpret_cast<idClass *&>( projectileEnt ) );
// HEXEN : Zeroth
int projs;
idEntity *proj;
savefile->ReadInt( projs );
for ( int i = 0; i < projs; i++ ) {
savefile->ReadObject( reinterpret_cast<idClass *&>( proj ) );
projectileEnts.Append( proj );
}
}
/***********************************************************************
@ -549,6 +562,7 @@ void idWeapon::Clear( void ) {
scriptObject.Free();
WEAPON_ATTACK.Unlink();
WEAPON_ATTACK2.Unlink(); // HEXEN : Zeroth
WEAPON_RELOAD.Unlink();
WEAPON_NETRELOAD.Unlink();
WEAPON_NETENDRELOAD.Unlink();
@ -706,7 +720,10 @@ void idWeapon::Clear( void ) {
sndHum = NULL;
isLinked = false;
projectileEnt = NULL;
// HEXEN : Zeroth
projectileEnts.Clear();
//projectileEnt = NULL;
isFiring = false;
}
@ -762,7 +779,7 @@ void idWeapon::InitWorldModel( const idDeclEntityDef *def ) {
idWeapon::GetWeaponDef
================
*/
void idWeapon::GetWeaponDef( const char *objectname, int ammoinclip ) {
void idWeapon::GetWeaponDef( const char *objectname, float ammoinclip ) {
const char *shader;
const char *objectType;
const char *vmodel;
@ -770,7 +787,7 @@ void idWeapon::GetWeaponDef( const char *objectname, int ammoinclip ) {
const char *projectileName;
const char *brassDefName;
const char *smokeName;
int ammoAvail;
float ammoAvail;
Clear();
@ -783,9 +800,9 @@ void idWeapon::GetWeaponDef( const char *objectname, int ammoinclip ) {
weaponDef = gameLocal.FindEntityDef( objectname );
ammoType = GetAmmoNumForName( weaponDef->dict.GetString( "ammoType" ) );
ammoRequired = weaponDef->dict.GetInt( "ammoRequired" );
clipSize = weaponDef->dict.GetInt( "clipSize" );
lowAmmo = weaponDef->dict.GetInt( "lowAmmo" );
ammoRequired = weaponDef->dict.GetFloat( "ammoRequired" );
clipSize = weaponDef->dict.GetFloat( "clipSize" );
lowAmmo = weaponDef->dict.GetFloat( "lowAmmo" );
icon = weaponDef->dict.GetString( "icon" );
silent_fire = weaponDef->dict.GetBool( "silent_fire" );
@ -844,7 +861,13 @@ void idWeapon::GetWeaponDef( const char *objectname, int ammoinclip ) {
}
// find some joints in the model for locating effects
barrelJointView = animator.GetJointHandle( "barrel" );
// HEXEN : Zeroth
if ( !weaponDef->dict.FindKey( "barrelJointName" ) ) {
barrelJointView = animator.GetJointHandle( "barrel" );
} else {
barrelJointView = animator.GetJointHandle( weaponDef->dict.GetString( "barrelJointName" ) );
}
flashJointView = animator.GetJointHandle( "flash" );
ejectJointView = animator.GetJointHandle( "eject" );
guiLightJointView = animator.GetJointHandle( "guiLight" );
@ -992,6 +1015,7 @@ void idWeapon::GetWeaponDef( const char *objectname, int ammoinclip ) {
}
WEAPON_ATTACK.LinkTo( scriptObject, "WEAPON_ATTACK" );
WEAPON_ATTACK2.LinkTo( scriptObject, "WEAPON_ATTACK2" ); // HEXEN : Zeroth
WEAPON_RELOAD.LinkTo( scriptObject, "WEAPON_RELOAD" );
WEAPON_NETRELOAD.LinkTo( scriptObject, "WEAPON_NETRELOAD" );
WEAPON_NETENDRELOAD.LinkTo( scriptObject, "WEAPON_NETENDRELOAD" );
@ -1062,8 +1086,8 @@ void idWeapon::UpdateGUI( void ) {
}
}
int inclip = AmmoInClip();
int ammoamount = AmmoAvailable();
float inclip = AmmoInClip();
float ammoamount = AmmoAvailable();
if ( ammoamount < 0 ) {
// show infinite ammo
@ -1071,9 +1095,9 @@ void idWeapon::UpdateGUI( void ) {
} else {
// show remaining ammo
renderEntity.gui[ 0 ]->SetStateString( "player_totalammo", va( "%i", ammoamount - inclip) );
renderEntity.gui[ 0 ]->SetStateString( "player_ammo", ClipSize() ? va( "%i", inclip ) : "--" );
renderEntity.gui[ 0 ]->SetStateString( "player_clips", ClipSize() ? va("%i", ammoamount / ClipSize()) : "--" );
renderEntity.gui[ 0 ]->SetStateString( "player_allammo", va( "%i/%i", inclip, ammoamount - inclip ) );
renderEntity.gui[ 0 ]->SetStateString( "player_ammo", ClipSize() ? va( "%f", inclip ) : "--" );
renderEntity.gui[ 0 ]->SetStateString( "player_clips", ClipSize() ? va("%f", ammoamount / ClipSize()) : "--" );
renderEntity.gui[ 0 ]->SetStateString( "player_allammo", va( "%f/%f", inclip, ammoamount - inclip ) );
}
renderEntity.gui[ 0 ]->SetStateBool( "player_ammo_empty", ( ammoamount == 0 ) );
renderEntity.gui[ 0 ]->SetStateBool( "player_clip_empty", ( inclip == 0 ) );
@ -1414,6 +1438,29 @@ void idWeapon::BeginAttack( void ) {
WEAPON_ATTACK = true;
}
/*
================
Zeroth
idWeapon::BeginAttack2
================
*/
void idWeapon::BeginAttack2( void ) {
if ( status != WP_OUTOFAMMO ) {
lastAttack = gameLocal.time;
}
if ( !isLinked ) {
return;
}
if ( !WEAPON_ATTACK2 ) {
if ( sndHum ) {
StopSound( SND_CHANNEL_BODY, false );
}
}
WEAPON_ATTACK2 = true;
}
/*
================
idWeapon::EndAttack
@ -1431,6 +1478,24 @@ void idWeapon::EndAttack( void ) {
}
}
/*
================
Zeroth
idWeapon::EndAttack2
================
*/
void idWeapon::EndAttack2( void ) {
if ( !WEAPON_ATTACK2.IsLinked() ) {
return;
}
if ( WEAPON_ATTACK2 ) {
WEAPON_ATTACK2 = false;
if ( sndHum ) {
StartSoundShader( sndHum, SND_CHANNEL_BODY, 0, false, NULL );
}
}
}
/*
================
idWeapon::isReady
@ -1490,12 +1555,16 @@ idWeapon::WeaponStolen
*/
void idWeapon::WeaponStolen( void ) {
assert( !gameLocal.isClient );
if ( projectileEnt ) {
if ( projectileEnts.Num() ) {
if ( isLinked ) {
SetState( "WeaponStolen", 0 );
thread->Execute();
}
projectileEnt = NULL;
// HEXEN : Zeroth
for ( int i = 0; i < projectileEnts.Num(); i++ ) {
projectileEnts[ i ] = NULL;
}
}
// set to holstered so we can switch weapons right away
@ -2016,6 +2085,7 @@ void idWeapon::EnterCinematic( void ) {
thread->Execute();
WEAPON_ATTACK = false;
WEAPON_ATTACK2 = false; // HEXEN : Zeroth
WEAPON_RELOAD = false;
WEAPON_NETRELOAD = false;
WEAPON_NETENDRELOAD = false;
@ -2029,6 +2099,25 @@ void idWeapon::EnterCinematic( void ) {
LowerWeapon();
}
/*
================
Zeroth
idWeapon::EnterCinematic
================
*/
void idWeapon::eoc_UnstickAllButtons( void ) {
if ( isLinked ) {
WEAPON_ATTACK = false;
WEAPON_ATTACK2 = false;
WEAPON_RELOAD = false;
WEAPON_NETRELOAD = false;
WEAPON_NETENDRELOAD = false;
WEAPON_NETFIRING = false;
WEAPON_RAISEWEAPON = false;
WEAPON_LOWERWEAPON = false;
}
}
/*
================
idWeapon::ExitCinematic
@ -2191,20 +2280,63 @@ const char *idWeapon::GetAmmoPickupNameForNum( ammo_t ammonum ) {
idWeapon::AmmoAvailable
================
*/
int idWeapon::AmmoAvailable( void ) const {
float idWeapon::AmmoAvailable( void ) const {
if ( owner ) {
owner->inventory.DoCombinedMana(); // HEXEN : Zeroth
return owner->inventory.HasAmmo( ammoType, ammoRequired );
} else {
return 0;
}
}
/*
================
Zeroth
idWeapon::BlueManaAvailable
================
*/
//int idWeapon::BlueManaAvailable( void ) const {
// if ( owner ) {
// return owner->inventory.HasAmmo( GetAmmoNumForName("ammo_bluemana"), 1 );
// } else {
// return 0;
// }
//}
/*
================
Zeroth
idWeapon::GreenManaAvailable
================
*/
//int idWeapon::GreenManaAvailable( void ) const {
// if ( owner ) {
// return owner->inventory.HasAmmo( GetAmmoNumForName("ammo_greenmana"), 1 );
/// } else {
// return 0;
// }
//}
/*
================
Zeroth
idWeapon::CombinedManaAvailable
================
*/
//int idWeapon::CombinedManaAvailable( void ) const {
// if ( owner ) {
// return owner->inventory.HasAmmo( GetAmmoNumForName("ammo_combinedmana"), 1 );
// } else {
// return 0;
// }
//}
/*
================
idWeapon::AmmoInClip
================
*/
int idWeapon::AmmoInClip( void ) const {
float idWeapon::AmmoInClip( void ) const {
return ammoClip;
}
@ -2231,7 +2363,7 @@ ammo_t idWeapon::GetAmmoType( void ) const {
idWeapon::ClipSize
================
*/
int idWeapon::ClipSize( void ) const {
float idWeapon::ClipSize( void ) const {
return clipSize;
}
@ -2240,7 +2372,7 @@ int idWeapon::ClipSize( void ) const {
idWeapon::LowAmmo
================
*/
int idWeapon::LowAmmo() const {
float idWeapon::LowAmmo() const {
return lowAmmo;
}
@ -2249,7 +2381,7 @@ int idWeapon::LowAmmo() const {
idWeapon::AmmoRequired
================
*/
int idWeapon::AmmoRequired( void ) const {
float idWeapon::AmmoRequired( void ) const {
return ammoRequired;
}
@ -2466,7 +2598,7 @@ void idWeapon::Event_WeaponLowering( void ) {
idWeapon::Event_UseAmmo
===============
*/
void idWeapon::Event_UseAmmo( int amount ) {
void idWeapon::Event_UseAmmo( float amount ) {
if ( gameLocal.isClient ) {
return;
}
@ -2485,8 +2617,8 @@ void idWeapon::Event_UseAmmo( int amount ) {
idWeapon::Event_AddToClip
===============
*/
void idWeapon::Event_AddToClip( int amount ) {
int ammoAvail;
void idWeapon::Event_AddToClip( float amount ) {
float ammoAvail;
if ( gameLocal.isClient ) {
return;
@ -2509,7 +2641,7 @@ idWeapon::Event_AmmoInClip
===============
*/
void idWeapon::Event_AmmoInClip( void ) {
int ammo = AmmoInClip();
float ammo = AmmoInClip();
idThread::ReturnFloat( ammo );
}
@ -2519,7 +2651,7 @@ idWeapon::Event_AmmoAvailable
===============
*/
void idWeapon::Event_AmmoAvailable( void ) {
int ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
float ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
idThread::ReturnFloat( ammoAvail );
}
@ -2529,7 +2661,7 @@ idWeapon::Event_TotalAmmoCount
===============
*/
void idWeapon::Event_TotalAmmoCount( void ) {
int ammoAvail = owner->inventory.HasAmmo( ammoType, 1 );
float ammoAvail = owner->inventory.HasAmmo( ammoType, 1 );
idThread::ReturnFloat( ammoAvail );
}
@ -2779,14 +2911,16 @@ idWeapon::Event_CreateProjectile
*/
void idWeapon::Event_CreateProjectile( void ) {
if ( !gameLocal.isClient ) {
projectileEnt = NULL;
gameLocal.SpawnEntityDef( projectileDict, &projectileEnt, false );
if ( projectileEnt ) {
projectileEnt->SetOrigin( GetPhysics()->GetOrigin() );
projectileEnt->Bind( owner, false );
projectileEnt->Hide();
// HEXEN : Zeroth
projectileEnts.Append( &idEntity() );
int pnum = projectileEnts.Num() - 1;
gameLocal.SpawnEntityDef( projectileDict, &(projectileEnts[pnum]), false );
if ( projectileEnts[pnum] ) {
projectileEnts[pnum]->SetOrigin( GetPhysics()->GetOrigin() );
projectileEnts[pnum]->Bind( owner, false );
projectileEnts[pnum]->Hide();
}
idThread::ReturnEntity( projectileEnt );
idThread::ReturnEntity( projectileEnts[pnum] );
} else {
idThread::ReturnEntity( NULL );
}
@ -2800,7 +2934,7 @@ idWeapon::Event_LaunchProjectiles
void idWeapon::Event_LaunchProjectiles( int num_projectiles, float spread, float fuseOffset, float launchPower, float dmgPower ) {
idProjectile *proj;
idEntity *ent;
int i;
int i, c;
idVec3 dir;
float ang;
float spin;
@ -2824,7 +2958,7 @@ void idWeapon::Event_LaunchProjectiles( int num_projectiles, float spread, float
if ( !gameLocal.isClient ) {
// check if we're out of ammo or the clip is empty
int ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
float ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
if ( !ammoAvail || ( ( clipSize != 0 ) && ( ammoClip <= 0 ) ) ) {
return;
}
@ -2914,49 +3048,78 @@ void idWeapon::Event_LaunchProjectiles( int num_projectiles, float spread, float
dir = playerViewAxis[ 0 ] + playerViewAxis[ 2 ] * ( ang * idMath::Sin( spin ) ) - playerViewAxis[ 1 ] * ( ang * idMath::Cos( spin ) );
dir.Normalize();
if ( projectileEnt ) {
ent = projectileEnt;
ent->Show();
ent->Unbind();
projectileEnt = NULL;
// HEXEN : Zeroth
//Z.TODO: this could be simplified, but for now it works.
c = projectileEnts.Num();
if ( c ) {
for ( ; c > 0; c-- ) {
ent = projectileEnts[ c - 1 ];
ent->Show();
ent->Unbind();
if ( !ent || !ent->IsType( idProjectile::Type ) ) {
const char *projectileName = weaponDef->dict.GetString( "def_projectile" );
gameLocal.Error( "'%s' is not an idProjectile", projectileName );
}
if ( projectileDict.GetBool( "net_instanthit" ) ) {
// don't synchronize this on top of the already predicted effect
ent->fl.networkSync = false;
}
proj = static_cast<idProjectile *>(ent);
proj->Create( owner, muzzleOrigin, dir );
projBounds = proj->GetPhysics()->GetBounds().Rotate( proj->GetPhysics()->GetAxis() );
// make sure the projectile starts inside the bounding box of the owner
if ( i == 0 ) {
muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
if ( ( ownerBounds - projBounds).RayIntersection( muzzle_pos, playerViewAxis[ 0 ], distance ) ) {
start = muzzle_pos + distance * playerViewAxis[ 0 ];
} else {
start = ownerBounds.GetCenter();
}
gameLocal.clip.Translation( tr, start, muzzle_pos, proj->GetPhysics()->GetClipModel(), proj->GetPhysics()->GetClipModel()->GetAxis(), MASK_SHOT_RENDERMODEL, owner );
muzzle_pos = tr.endpos;
}
proj->Launch( muzzle_pos, dir, pushVelocity, fuseOffset, launchPower, dmgPower );
projectileEnts.RemoveIndex( c - 1 );
}
} else {
gameLocal.SpawnEntityDef( projectileDict, &ent, false );
}
if ( !ent || !ent->IsType( idProjectile::Type ) ) {
const char *projectileName = weaponDef->dict.GetString( "def_projectile" );
gameLocal.Error( "'%s' is not an idProjectile", projectileName );
}
if ( projectileDict.GetBool( "net_instanthit" ) ) {
// don't synchronize this on top of the already predicted effect
ent->fl.networkSync = false;
}
proj = static_cast<idProjectile *>(ent);
proj->Create( owner, muzzleOrigin, dir );
projBounds = proj->GetPhysics()->GetBounds().Rotate( proj->GetPhysics()->GetAxis() );
// make sure the projectile starts inside the bounding box of the owner
if ( i == 0 ) {
muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
// DG: sometimes the assertion in idBounds::operator-(const idBounds&) triggers
// (would get bounding box with negative volume)
// => check that before doing ownerBounds - projBounds (equivalent to the check in the assertion)
idVec3 obDiff = ownerBounds[1] - ownerBounds[0];
idVec3 pbDiff = projBounds[1] - projBounds[0];
bool boundsSubLegal = obDiff.x > pbDiff.x && obDiff.y > pbDiff.y && obDiff.z > pbDiff.z;
if ( boundsSubLegal && ( ownerBounds - projBounds ).RayIntersection( muzzle_pos, playerViewAxis[0], distance ) ) {
start = muzzle_pos + distance * playerViewAxis[0];
} else {
start = ownerBounds.GetCenter();
if ( !ent || !ent->IsType( idProjectile::Type ) ) {
const char *projectileName = weaponDef->dict.GetString( "def_projectile" );
gameLocal.Error( "'%s' is not an idProjectile", projectileName );
}
gameLocal.clip.Translation( tr, start, muzzle_pos, proj->GetPhysics()->GetClipModel(), proj->GetPhysics()->GetClipModel()->GetAxis(), MASK_SHOT_RENDERMODEL, owner );
muzzle_pos = tr.endpos;
}
proj->Launch( muzzle_pos, dir, pushVelocity, fuseOffset, launchPower, dmgPower );
if ( projectileDict.GetBool( "net_instanthit" ) ) {
// don't synchronize this on top of the already predicted effect
ent->fl.networkSync = false;
}
proj = static_cast<idProjectile *>(ent);
proj->Create( owner, muzzleOrigin, dir );
projBounds = proj->GetPhysics()->GetBounds().Rotate( proj->GetPhysics()->GetAxis() );
// make sure the projectile starts inside the bounding box of the owner
if ( i == 0 ) {
muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
if ( ( ownerBounds - projBounds).RayIntersection( muzzle_pos, playerViewAxis[0], distance ) ) {
start = muzzle_pos + distance * playerViewAxis[0];
} else {
start = ownerBounds.GetCenter();
}
gameLocal.clip.Translation( tr, start, muzzle_pos, proj->GetPhysics()->GetClipModel(), proj->GetPhysics()->GetClipModel()->GetAxis(), MASK_SHOT_RENDERMODEL, owner );
muzzle_pos = tr.endpos;
}
proj->Launch( muzzle_pos, dir, pushVelocity, fuseOffset, launchPower, dmgPower );
}
}
// toss the brass
@ -3033,7 +3196,7 @@ void idWeapon::Event_Melee( void ) {
idVec3 kickDir, globalKickDir;
meleeDef->dict.GetVector( "kickDir", "0 0 0", kickDir );
globalKickDir = muzzleAxis * kickDir;
ent->Damage( owner, owner, globalKickDir, meleeDefName, owner->PowerUpModifier( MELEE_DAMAGE ), tr.c.id );
ent->Damage( owner, owner, globalKickDir, meleeDefName, owner->PowerUpModifier( MELEE_DAMAGE ), tr.c.id, tr.c.point );
hit = true;
}
@ -3057,7 +3220,7 @@ void idWeapon::Event_Melee( void ) {
// start impact sound based on material type
hitSound = meleeDef->dict.GetString( va( "snd_%s", materialType ) );
if ( *hitSound == '\0' ) {
hitSound = meleeDef->dict.GetString( "snd_metal" );
hitSound = meleeDef->dict.GetString( "snd_hit" );
}
if ( gameLocal.time > nextStrikeFx ) {

View file

@ -82,7 +82,7 @@ public:
// Weapon definition management
void Clear( void );
void GetWeaponDef( const char *objectname, int ammoinclip );
void GetWeaponDef( const char *objectname, float ammoinclip );
bool IsLinked( void );
bool IsWorldModelReady( void );
@ -109,6 +109,8 @@ public:
void OwnerDied( void );
void BeginAttack( void );
void EndAttack( void );
void BeginAttack2( void ); // HEXEN : Zeroth
void EndAttack2( void ); // HEXEN : Zeroth
bool IsReady( void ) const;
bool IsReloading( void ) const;
bool IsHolstered( void ) const;
@ -123,6 +125,7 @@ public:
void SetState( const char *statename, int blendFrames );
void UpdateScript( void );
void EnterCinematic( void );
void eoc_UnstickAllButtons( void ); // HEXEN : Zeroth
void ExitCinematic( void );
void NetCatchup( void );
@ -138,12 +141,12 @@ public:
static const char *GetAmmoNameForNum( ammo_t ammonum );
static const char *GetAmmoPickupNameForNum( ammo_t ammonum );
ammo_t GetAmmoType( void ) const;
int AmmoAvailable( void ) const;
int AmmoInClip( void ) const;
float AmmoAvailable( void ) const;
float AmmoInClip( void ) const;
void ResetAmmoClip( void );
int ClipSize( void ) const;
int LowAmmo( void ) const;
int AmmoRequired( void ) const;
float ClipSize( void ) const;
float LowAmmo( void ) const;
float AmmoRequired( void ) const;
virtual void WriteToSnapshot( idBitMsgDelta &msg ) const;
virtual void ReadFromSnapshot( const idBitMsgDelta &msg );
@ -161,6 +164,7 @@ public:
private:
// script control
idScriptBool WEAPON_ATTACK;
idScriptBool WEAPON_ATTACK2; // HEXEN : Zeroth
idScriptBool WEAPON_RELOAD;
idScriptBool WEAPON_NETRELOAD;
idScriptBool WEAPON_NETENDRELOAD;
@ -176,7 +180,7 @@ private:
bool isLinked;
// precreated projectile
idEntity *projectileEnt;
idList<idEntity *> projectileEnts; // HEXEN : Zeroth. turned into an idList.
idPlayer * owner;
idEntityPtr<idAnimatedEntity> worldModel;
@ -250,10 +254,10 @@ private:
// ammo management
ammo_t ammoType;
int ammoRequired; // amount of ammo to use each shot. 0 means weapon doesn't need ammo.
int clipSize; // 0 means no reload
int ammoClip;
int lowAmmo; // if ammo in clip hits this threshold, snd_
float ammoRequired; // amount of ammo to use each shot. 0 means weapon doesn't need ammo.
float clipSize; // 0 means no reload
float ammoClip;
float lowAmmo; // if ammo in clip hits this threshold, snd_
bool powerAmmo; // true if the clip reduction is a factor of the power setting when
// a projectile is launched
// mp client
@ -326,8 +330,8 @@ private:
void Event_WeaponHolstered( void );
void Event_WeaponRising( void );
void Event_WeaponLowering( void );
void Event_UseAmmo( int amount );
void Event_AddToClip( int amount );
void Event_UseAmmo( float amount );
void Event_AddToClip( float amount );
void Event_AmmoInClip( void );
void Event_AmmoAvailable( void );
void Event_TotalAmmoCount( void );