NSWeapon: - add "chargeTime" key
rework state machine in NSWeapon reload timing separation in NSWeapon
This commit is contained in:
parent
c3f527d5e5
commit
21b68d1938
6 changed files with 305 additions and 182 deletions
|
@ -142,6 +142,7 @@ private:
|
|||
|
||||
PREDICTED_FLOAT(w_attack_next)
|
||||
PREDICTED_FLOAT(w_idle_next)
|
||||
PREDICTED_FLOAT(w_reload_next)
|
||||
PREDICTED_FLOAT(teleport_time)
|
||||
PREDICTED_FLOAT(weapontime)
|
||||
PREDICTED_FLOAT(m_flStamina)
|
||||
|
|
|
@ -250,11 +250,9 @@ NSClientPlayer::ProcessInput(void)
|
|||
|
||||
/* weapon system */
|
||||
if (input_buttons & INPUT_SECONDARY) {
|
||||
m_activeWeapon._WeaponStartedFiring();
|
||||
m_activeWeapon.SecondaryAttack();
|
||||
m_activeWeapon._SecondaryAttack();
|
||||
} else if (input_buttons & INPUT_PRIMARY) {
|
||||
m_activeWeapon._WeaponStartedFiring();
|
||||
m_activeWeapon.PrimaryAttack();
|
||||
m_activeWeapon._PrimaryAttack();
|
||||
} else if (input_buttons & INPUT_RELOAD) {
|
||||
m_activeWeapon.Reload();
|
||||
} else {
|
||||
|
@ -734,6 +732,7 @@ NSClientPlayer::ReceiveEntity(float new, float flChanged)
|
|||
READENTITY_FLOAT(weapontime, PLAYER_TIMINGS)
|
||||
READENTITY_FLOAT(w_attack_next, PLAYER_TIMINGS)
|
||||
READENTITY_FLOAT(w_idle_next, PLAYER_TIMINGS)
|
||||
READENTITY_FLOAT(w_reload_next, PLAYER_TIMINGS)
|
||||
READENTITY_ENTNUM(vehicle_entnum, PLAYER_VEHICLE)
|
||||
READENTITY_BYTE(spec_ent, PLAYER_SPECTATE)
|
||||
READENTITY_BYTE(spec_mode, PLAYER_SPECTATE)
|
||||
|
@ -825,6 +824,7 @@ NSClientPlayer::PredictPreFrame(void)
|
|||
SAVE_STATE(weapontime)
|
||||
SAVE_STATE(w_attack_next)
|
||||
SAVE_STATE(w_idle_next)
|
||||
SAVE_STATE(w_reload_next)
|
||||
SAVE_STATE(vehicle_entnum)
|
||||
SAVE_STATE(spec_ent)
|
||||
SAVE_STATE(spec_mode)
|
||||
|
@ -878,6 +878,7 @@ NSClientPlayer::PredictPostFrame(void)
|
|||
ROLL_BACK(weapontime)
|
||||
ROLL_BACK(w_attack_next)
|
||||
ROLL_BACK(w_idle_next)
|
||||
ROLL_BACK(w_reload_next)
|
||||
ROLL_BACK(vehicle_entnum)
|
||||
ROLL_BACK(spec_ent)
|
||||
ROLL_BACK(spec_mode)
|
||||
|
@ -929,6 +930,7 @@ NSClientPlayer::Save(float handle)
|
|||
SaveFloat(handle, "pmove_flags", pmove_flags);
|
||||
SaveFloat(handle, "w_attack_next", w_attack_next);
|
||||
SaveFloat(handle, "w_idle_next", w_idle_next);
|
||||
SaveFloat(handle, "w_reload_next", w_reload_next);
|
||||
SaveFloat(handle, "teleport_time", teleport_time);
|
||||
SaveFloat(handle, "m_flStamina", m_flStamina);
|
||||
SaveInt(handle, "weaponframe", weaponframe);
|
||||
|
@ -1000,6 +1002,9 @@ NSClientPlayer::Restore(string strKey, string strValue)
|
|||
case "w_idle_next":
|
||||
w_idle_next = ReadFloat(strValue);
|
||||
break;
|
||||
case "w_reload_next":
|
||||
w_reload_next = ReadFloat(strValue);
|
||||
break;
|
||||
case "teleport_time":
|
||||
teleport_time = ReadFloat(strValue);
|
||||
break;
|
||||
|
@ -1255,6 +1260,7 @@ NSClientPlayer::EvaluateEntity(void)
|
|||
EVALUATE_FIELD(weapontime, PLAYER_TIMINGS)
|
||||
EVALUATE_FIELD(w_attack_next, PLAYER_TIMINGS)
|
||||
EVALUATE_FIELD(w_idle_next, PLAYER_TIMINGS)
|
||||
EVALUATE_FIELD(w_reload_next, PLAYER_TIMINGS)
|
||||
EVALUATE_FIELD(vehicle, PLAYER_VEHICLE)
|
||||
EVALUATE_FIELD(spec_ent, PLAYER_SPECTATE)
|
||||
EVALUATE_FIELD(spec_mode, PLAYER_SPECTATE)
|
||||
|
@ -1344,6 +1350,7 @@ NSClientPlayer::SendEntity(entity ePEnt, float flChanged)
|
|||
SENDENTITY_FLOAT(weapontime, PLAYER_TIMINGS)
|
||||
SENDENTITY_FLOAT(w_attack_next, PLAYER_TIMINGS)
|
||||
SENDENTITY_FLOAT(w_idle_next, PLAYER_TIMINGS)
|
||||
SENDENTITY_FLOAT(w_reload_next, PLAYER_TIMINGS)
|
||||
SENDENTITY_ENTITY(vehicle, PLAYER_VEHICLE)
|
||||
SENDENTITY_BYTE(spec_ent, PLAYER_SPECTATE)
|
||||
SENDENTITY_BYTE(spec_mode, PLAYER_SPECTATE)
|
||||
|
|
|
@ -853,12 +853,15 @@ void
|
|||
EFX_UpdateListener(NSView playerView)
|
||||
{
|
||||
static NSSoundScape lastScape;
|
||||
vector vecPlayer;
|
||||
vector camPos = playerView.GetCameraOrigin();
|
||||
vector camAngle = playerView.GetCameraAngle();
|
||||
NSSoundScape bestScape = __NULL__;
|
||||
|
||||
vecPlayer = playerView.GetCameraOrigin();
|
||||
makevectors(playerView.GetCameraAngle());
|
||||
SetListener(vecPlayer, v_forward, v_right, v_up, 12);
|
||||
if (lastScape) {
|
||||
SetListener(camPos, anglesToForward(camAngle), anglesToRight(camAngle), anglesToUp(camAngle), 12);
|
||||
} else {
|
||||
SetListener(camPos, anglesToForward(camAngle), anglesToRight(camAngle), anglesToUp(camAngle), 0);
|
||||
}
|
||||
|
||||
if (autocvar_s_al_use_reverb == false) {
|
||||
return;
|
||||
|
@ -869,12 +872,12 @@ EFX_UpdateListener(NSView playerView)
|
|||
NSSoundScape scape = (NSSoundScape)e;
|
||||
|
||||
other = world;
|
||||
traceline(scape.origin, vecPlayer, MOVE_OTHERONLY, scape);
|
||||
traceline(scape.origin, camPos, MOVE_OTHERONLY, scape);
|
||||
if (trace_fraction < 1.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float dist = vlen(e.origin - vecPlayer);
|
||||
float dist = vlen(e.origin - camPos);
|
||||
if (dist > scape.m_radius) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -44,8 +44,22 @@ typedef enum
|
|||
WEAPONSTATE_RELOAD_START,
|
||||
WEAPONSTATE_RELOAD,
|
||||
WEAPONSTATE_RELOAD_END,
|
||||
WEAPONSTATE_CHARGING,
|
||||
WEAPONSTATE_FIRELOOP,
|
||||
WEAPONSTATE_RELEASED
|
||||
} nsweapon_state_t;
|
||||
|
||||
string nsweapon_state_s[] =
|
||||
{
|
||||
"WEAPONSTATE_IDLE",
|
||||
"WEAPONSTATE_RELOAD_START",
|
||||
"WEAPONSTATE_RELOAD",
|
||||
"WEAPONSTATE_RELOAD_END",
|
||||
"WEAPONSTATE_CHARGING",
|
||||
"WEAPONSTATE_FIRELOOP",
|
||||
"WEAPONSTATE_RELEASED"
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WEPEVENT_FIRED,
|
||||
|
@ -63,9 +77,6 @@ related keys get forwarded only to items of this class.
|
|||
- "targetname" : Name
|
||||
|
||||
- "weapon_scriptobject" : mapC progs with the weapon code within.
|
||||
- "ammoType" : name of the ammo type def entry which the gun uses
|
||||
- "ammoRequired" : set to 1 if we require ammo.
|
||||
- "ammoPerShot" : Amount of ammo to deduct per shot.
|
||||
- "clipSize" : maximum clip size
|
||||
- "mtr_flashShader" : muzzleflash material to Use.
|
||||
- "model_flash" : muzzleflash model/sprite to use.
|
||||
|
@ -79,6 +90,25 @@ related keys get forwarded only to items of this class.
|
|||
- "continuousSmoke" : whether the particle effect is continous
|
||||
- "clipSizeDefault" : CUSTOM: Default clip size on pickup.
|
||||
|
||||
## Attack related keys
|
||||
- "def_onFire" : Def to spawn when the weapon is fired.
|
||||
- "def_onRelease" : Def to spawn when the weapon has been released.
|
||||
|
||||
## Ammo management related keys
|
||||
- "ammoType" : name of the ammo type def entry which the weapon uses
|
||||
- "ammoRequired" : set to 1 if we require ammo.
|
||||
- "ammoPerShot" : Amount of ammo to deduct per successful shot.
|
||||
|
||||
### Charging/Overcharging
|
||||
For an overcharge effect, spawn a self-destructive explosion on "def_onFire", and rely on "def_onRelease"
|
||||
for delivering a lethal charge to other enemies.
|
||||
- "chargeTime" : Amount of time the weapon has to charge before "def_onFire" is spawned.
|
||||
|
||||
### Overheating weapons
|
||||
Overheating of the weapon is done when both keys are set.
|
||||
- "overheatLength" : Time in which it takes for the weapon to cool down.
|
||||
- "overheatPerShot" : Time added against "overheat_length" when a shot is fired.
|
||||
|
||||
@ingroup baseclass
|
||||
*/
|
||||
class
|
||||
|
@ -111,7 +141,7 @@ public:
|
|||
virtual bool IsWeapon(void);
|
||||
virtual bool HasReserveAmmo(void);
|
||||
|
||||
/** Overridable: Called when we switch to this weapon */
|
||||
/** Overridable: Called when we switch to this weapon from another. */
|
||||
virtual void Draw(void);
|
||||
/** Overridable: Called when we are about to switch to another weapon */
|
||||
virtual void Holster(void);
|
||||
|
@ -121,8 +151,10 @@ public:
|
|||
virtual void SecondaryAttack(void);
|
||||
/** Overridable: On +reload execution. */
|
||||
virtual void Reload(void);
|
||||
/** Overridable: When no buttons are held. */
|
||||
/** Overridable: When no buttons are held, or you forcefully want to stop firing. */
|
||||
virtual void Release(void);
|
||||
/** Overridable: When the weapon is supposed to be doing something on its own. */
|
||||
virtual void Idle(void);
|
||||
/** Overridable: When the HUD is requested to be drawn. */
|
||||
virtual void UpdateGUI(void);
|
||||
|
||||
|
@ -130,11 +162,18 @@ public:
|
|||
nonvirtual void SetWorldModel(string);
|
||||
nonvirtual void SetPlayerModel(string);
|
||||
nonvirtual void SetWeaponFrame(float);
|
||||
nonvirtual void PlaySound(string, bool);
|
||||
|
||||
/* state */
|
||||
nonvirtual void SetWeaponState(nsweapon_state_t);
|
||||
nonvirtual nsweapon_state_t GetWeaponState(void);
|
||||
|
||||
virtual void SetAttackNext(float);
|
||||
virtual void SetReloadNext(float);
|
||||
virtual void SetIdleNext(float);
|
||||
virtual bool CanFire(void);
|
||||
virtual bool CanIdle(void);
|
||||
virtual bool CanReload(void);
|
||||
virtual bool UseAmmo(string);
|
||||
|
||||
/** Overridable: Called once when the weapon started firing. */
|
||||
|
@ -172,6 +211,8 @@ private:
|
|||
nonvirtual void _CacheWeaponDefVariables(void);
|
||||
nonvirtual void _WeaponStartedFiring(void);
|
||||
nonvirtual void _WeaponStoppedFiring(void);
|
||||
nonvirtual void _PrimaryAttack(void);
|
||||
nonvirtual void _SecondaryAttack(void);
|
||||
|
||||
#ifdef SERVER
|
||||
nonvirtual void _ReloadFinished(void);
|
||||
|
@ -230,6 +271,7 @@ private:
|
|||
bool m_fiSemiAuto;
|
||||
string m_fiSndFireLoop;
|
||||
float m_flReloadSpeed;
|
||||
float m_fiChargeTime;
|
||||
|
||||
NETWORKED_INT(m_iClip)
|
||||
NETWORKED_INT(m_iClipSize)
|
||||
|
|
|
@ -64,6 +64,26 @@ NSWeapon::RemovedFromInventory(void)
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
NSWeapon::SetWeaponState(nsweapon_state_t newState)
|
||||
{
|
||||
if (m_dState == newState) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_dState = newState;
|
||||
|
||||
#ifdef SERVER
|
||||
printf("State changed to %s\n", nsweapon_state_s[newState]);
|
||||
#endif
|
||||
}
|
||||
|
||||
nsweapon_state_t
|
||||
NSWeapon::GetWeaponState(void)
|
||||
{
|
||||
return (m_dState);
|
||||
}
|
||||
|
||||
void
|
||||
NSWeapon::UpdateFireInfoCache(void)
|
||||
{
|
||||
|
@ -77,10 +97,14 @@ NSWeapon::UpdateFireInfoCache(void)
|
|||
m_fiAmmoType = ammoNumForName(GetSubDefString(m_strLastFireInfo, "ammoType"));
|
||||
m_fiAmmoRequired = GetSubDefBool(m_strLastFireInfo, "ammoRequired");
|
||||
m_fiFireRate = GetSubDefFloat(m_strLastFireInfo, "fireRate");
|
||||
m_fiOnFire = GetSubDefString(m_strLastFireInfo, "def_onFire");
|
||||
m_fiOnRelease = GetSubDefString(m_strLastFireInfo, "def_onRelease");
|
||||
m_fiSemiAuto = GetSubDefBool(m_strLastFireInfo, "semiAuto");
|
||||
|
||||
/* defs to spawn */
|
||||
m_fiOnFire = GetSubDefString(m_strLastFireInfo, "def_onFire");
|
||||
m_fiOnRelease = GetSubDefString(m_strLastFireInfo, "def_onRelease");
|
||||
m_fiChargeTime = GetSubDefFloat(m_strLastFireInfo, "chargeTime");
|
||||
|
||||
/* when -1.0 we'll pull it from the animation. */
|
||||
if (reloadSpeed != "") {
|
||||
m_flReloadSpeed = stof(reloadSpeed);
|
||||
} else {
|
||||
|
@ -96,10 +120,11 @@ NSWeapon::UpdateFireInfoCache(void)
|
|||
#endif
|
||||
|
||||
/* validate */
|
||||
if (ammoPerShot != __NULL__)
|
||||
if (ammoPerShot != __NULL__) {
|
||||
m_fiAmmoPerShot = (int)stoi(ammoPerShot);
|
||||
else
|
||||
} else {
|
||||
m_fiAmmoPerShot = 1i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -184,59 +209,6 @@ NSWeapon::SpawnKey(string keyName, string setValue)
|
|||
case "continuousSmoke":
|
||||
m_bSmokeContinous = ReadBool(setValue);
|
||||
break;
|
||||
|
||||
case "actAltFire":
|
||||
case "actAltFireLast":
|
||||
case "actDraw":
|
||||
case "actDrawEmpty":
|
||||
case "actFire":
|
||||
case "actFireLast":
|
||||
case "actHolster":
|
||||
case "actHolsterEmpty":
|
||||
case "actLoop":
|
||||
case "actIdle":
|
||||
case "actIdleEmpty":
|
||||
case "actMeleeHit":
|
||||
case "actMeleeMiss":
|
||||
case "actPull":
|
||||
case "actReload":
|
||||
case "actReloadEmpty":
|
||||
case "actReloadEnd":
|
||||
case "actReloadStart":
|
||||
case "actThrow":
|
||||
case "ammoRequired":
|
||||
case "ammoPerShot":
|
||||
case "def_altFireInfo":
|
||||
case "def_damage_inhand":
|
||||
case "def_explode_inhand":
|
||||
case "def_fireInfo":
|
||||
case "def_melee":
|
||||
case "def_plant":
|
||||
case "def_projectile":
|
||||
case "detonateOnFire":
|
||||
case "fireRate":
|
||||
case "hudSlot":
|
||||
case "hudSlotPos":
|
||||
case "inv_name":
|
||||
case "meleeRateHit":
|
||||
case "meleeRateMiss":
|
||||
case "melee_distance":
|
||||
case "primed_fuse":
|
||||
case "punchAngle":
|
||||
case "powerAmmo":
|
||||
case "removeOnEmpty":
|
||||
case "silent_fire":
|
||||
case "snd_altfire":
|
||||
case "snd_empty":
|
||||
case "snd_fire":
|
||||
case "snd_reload":
|
||||
case "snd_reload_start":
|
||||
case "snd_reload_end":
|
||||
case "weight":
|
||||
case "trigger_delay":
|
||||
case "zoomFov":
|
||||
break;
|
||||
|
||||
default:
|
||||
super::SpawnKey(keyName, setValue);
|
||||
break;
|
||||
|
@ -585,7 +557,6 @@ NSWeapon::_CacheWeaponDefVariables(void)
|
|||
|
||||
muzzleModel = GetSubDefString(m_primaryFireInfo, "model_flash");
|
||||
m_muzzleModelIndex = getmodelindex(muzzleModel, false);
|
||||
m_flTriggerDelay = GetSubDefFloat(m_primaryFireInfo, "trigger_delay");
|
||||
m_flPrimedFuse = GetDefFloat("primed_fuse");
|
||||
m_flZoomFOV = GetDefFloat("zoomFov") / 90;
|
||||
m_bPowerAmmo = GetDefBool("powerAmmo");
|
||||
|
@ -748,6 +719,12 @@ NSWeapon::FiredWeaponAttack(string fireInfo)
|
|||
{
|
||||
NSClientPlayer ourOwner = (NSClientPlayer)GetOwner();
|
||||
ourOwner.AttackByDef(fireInfo, false);
|
||||
SetWeaponState(WEAPONSTATE_IDLE);
|
||||
|
||||
/* prevent release from firing it again */
|
||||
if (m_bPowerAmmo) {
|
||||
m_fiWillRelease = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -755,6 +732,7 @@ NSWeapon::ReleasedWeaponAttack(string fireInfo)
|
|||
{
|
||||
NSClientPlayer ourOwner = (NSClientPlayer)GetOwner();
|
||||
ourOwner.AttackByDef(fireInfo, true);
|
||||
SetWeaponState(WEAPONSTATE_RELEASED);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -768,7 +746,7 @@ NSWeapon::Attack(string fireInfo)
|
|||
ourOwner.gflags |= GF_SEMI_TOGGLED;
|
||||
}
|
||||
|
||||
/* satchels, pipe bombs, etc. */
|
||||
/* no real attack, detonate named satchels, pipe bombs, etc. */
|
||||
if (m_fiDetonateOnFire != __NULL__) {
|
||||
if (DetonateDef(m_fiDetonateOnFire) == true) {
|
||||
SetWeaponFrame(GetSubDefAct(fireInfo, "actDetonate"));
|
||||
|
@ -789,6 +767,8 @@ NSWeapon::Attack(string fireInfo)
|
|||
NSError("Will release.");
|
||||
}
|
||||
|
||||
/* melee attacks go through their own routine because we have to test
|
||||
against objects and walls and if we can even hit them. */
|
||||
if (m_meleeDef != "") {
|
||||
vector eyePos = ourOwner.GetEyePos();
|
||||
vector eyeAngles = ourOwner.v_angle;
|
||||
|
@ -818,7 +798,7 @@ NSWeapon::Attack(string fireInfo)
|
|||
SetIdleNext(meleeRate + 1.0f);
|
||||
|
||||
#ifdef SERVER
|
||||
Sound_Play(ourOwner, CHAN_WEAPON, GetSubDefString(m_meleeDef, "snd_miss"));
|
||||
PlaySound(GetSubDefString(m_meleeDef, "snd_miss"), false);
|
||||
|
||||
if (trace_fraction >= 1.0) {
|
||||
return;
|
||||
|
@ -837,10 +817,10 @@ NSWeapon::Attack(string fireInfo)
|
|||
//Damage_Apply(trace_ent, ourOwner, meleeDamage, 0, DMG_BLUNT);
|
||||
|
||||
if (hitEnt.iBleeds) {
|
||||
Sound_Play(ourOwner, CHAN_WEAPON, GetSubDefString(m_meleeDef, "snd_flesh"));
|
||||
PlaySound(GetSubDefString(m_meleeDef, "snd_flesh"), false);
|
||||
}
|
||||
} else {
|
||||
Sound_Play(ourOwner, CHAN_WEAPON, GetSubDefString(m_meleeDef, "snd_hit"));
|
||||
PlaySound(GetSubDefString(m_meleeDef, "snd_hit"), false);
|
||||
DecalGroups_Place("Impact.Shot", hitLoc + (anglesToForward(eyeAngles) * -2));
|
||||
}
|
||||
#endif
|
||||
|
@ -866,18 +846,19 @@ NSWeapon::Attack(string fireInfo)
|
|||
return;
|
||||
}
|
||||
|
||||
/* this weapon has a timed delay before something shoots out. */
|
||||
if (m_flTriggerDelay > 0.0f) {
|
||||
if (ourOwner.vv_flags & VFL_PRIMEDFUSE) {
|
||||
Release();
|
||||
/* this weapon has a delay before something shoots out. */
|
||||
if (m_fiChargeTime > 0.0f) {
|
||||
/* we haven't yet tried firing while charging */
|
||||
if (GetWeaponState() != WEAPONSTATE_CHARGING) {
|
||||
shotAnim = GetSubDefAct(fireInfo, "actDelay");
|
||||
SetAttackNext(m_fiChargeTime);
|
||||
|
||||
/* mark as charging, play loop anim in Idle() next */
|
||||
SetIdleNext(frameduration(m_viewModel, shotAnim));
|
||||
SetWeaponFrame(shotAnim);
|
||||
SetWeaponState(WEAPONSTATE_CHARGING);
|
||||
return;
|
||||
}
|
||||
shotAnim = GetSubDefAct(fireInfo, "actDelay");
|
||||
SetAttackNext(m_flTriggerDelay);
|
||||
SetWeaponFrame(shotAnim);
|
||||
ourOwner.vv_flags |= VFL_PRIMEDFUSE;
|
||||
//ourOwner.gflags |= GF_SEMI_TOGGLED;
|
||||
return;
|
||||
}
|
||||
|
||||
ourOwner.punchangle += m_fiPunchAngle;
|
||||
|
@ -912,10 +893,43 @@ NSWeapon::Attack(string fireInfo)
|
|||
m_bFiring = true;
|
||||
}
|
||||
|
||||
void
|
||||
NSWeapon::_PrimaryAttack(void)
|
||||
{
|
||||
SwitchFireInfo(m_primaryFireInfo);
|
||||
_WeaponStartedFiring();
|
||||
PrimaryAttack();
|
||||
}
|
||||
|
||||
void
|
||||
NSWeapon::_SecondaryAttack(void)
|
||||
{
|
||||
SwitchFireInfo(m_secondaryFireInfo);
|
||||
_WeaponStartedFiring();
|
||||
SecondaryAttack();
|
||||
}
|
||||
|
||||
void
|
||||
NSWeapon::PlaySound(string soundDef, bool clientOnly)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (clientOnly) {
|
||||
Sound_Play(owner, CHAN_WEAPON, soundDef);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SERVER
|
||||
if (!clientOnly) {
|
||||
Sound_Play(owner, CHAN_WEAPON, soundDef);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
NSWeapon::PrimaryAttack(void)
|
||||
{
|
||||
NSClientPlayer ourOwner = (NSClientPlayer)GetOwner();
|
||||
|
||||
if (CanFire() == false) {
|
||||
if (!(ourOwner.gflags & GF_SEMI_TOGGLED)) {
|
||||
Release();
|
||||
|
@ -924,10 +938,99 @@ NSWeapon::PrimaryAttack(void)
|
|||
return;
|
||||
}
|
||||
|
||||
SwitchFireInfo(m_primaryFireInfo);
|
||||
Attack(m_primaryFireInfo);
|
||||
}
|
||||
|
||||
void
|
||||
NSWeapon::Idle(void)
|
||||
{
|
||||
NSClientPlayer ourOwner = (NSClientPlayer)GetOwner();
|
||||
float idleAnim = 0;
|
||||
|
||||
if (CanIdle() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* handle shotgun style reloads */
|
||||
switch (m_dState) {
|
||||
case WEAPONSTATE_RELOAD_START:
|
||||
idleAnim = GetDefAct("actReloadStart");
|
||||
SetWeaponState(WEAPONSTATE_RELOAD);
|
||||
PlaySound(GetDefString("snd_reload_start"), false);
|
||||
break;
|
||||
case WEAPONSTATE_RELOAD:
|
||||
float reloadTime;
|
||||
idleAnim = GetDefAct("actReload");
|
||||
m_iClip++;
|
||||
ourOwner.UseAmmo(m_primaryAmmoType, 1);
|
||||
|
||||
if (HasReserveAmmo() == false || m_iClip >= m_iClipSize) {
|
||||
SetWeaponState(WEAPONSTATE_RELOAD_END);
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
PlaySound(GetDefString("snd_reload"), false);
|
||||
#endif
|
||||
|
||||
if (m_flReloadSpeed == -1.0f) {
|
||||
reloadTime = frameduration(m_viewModel, idleAnim);
|
||||
} else {
|
||||
reloadTime = m_flReloadSpeed;
|
||||
}
|
||||
|
||||
SetWeaponFrame(idleAnim);
|
||||
SetIdleNext(reloadTime);
|
||||
return;
|
||||
break;
|
||||
case WEAPONSTATE_RELOAD_END:
|
||||
idleAnim = GetDefAct("actReloadEnd");
|
||||
SetWeaponState(WEAPONSTATE_IDLE);
|
||||
#ifdef SERVER
|
||||
PlaySound(GetDefString("snd_reload_end"), false);
|
||||
#endif
|
||||
break;
|
||||
case WEAPONSTATE_FIRELOOP:
|
||||
idleAnim = GetDefAct("actLoop");
|
||||
break;
|
||||
case WEAPONSTATE_CHARGING:
|
||||
idleAnim = GetDefAct("actLoop");
|
||||
break;
|
||||
case WEAPONSTATE_RELEASED:
|
||||
//breakpoint();
|
||||
idleAnim = GetDefAct("actRelease");
|
||||
SetWeaponState(WEAPONSTATE_IDLE);
|
||||
break;
|
||||
case WEAPONSTATE_IDLE:
|
||||
default:
|
||||
if (!m_iMode) {
|
||||
if (m_iClipSize > 0 && m_iClip == 0) {
|
||||
idleAnim = GetDefAct("actIdleEmpty");
|
||||
|
||||
/* this will mess with us otherwise */
|
||||
if (!idleAnim)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!idleAnim)
|
||||
idleAnim = GetDefAct("actIdle");
|
||||
} else {
|
||||
if (m_iClipSize > 0 && m_iClip == 0) {
|
||||
idleAnim = GetDefAct("actAltIdleEmpty");
|
||||
|
||||
/* this will mess with us otherwise */
|
||||
if (!idleAnim)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!idleAnim)
|
||||
idleAnim = GetDefAct("actAltIdle");
|
||||
}
|
||||
}
|
||||
|
||||
SetWeaponFrame(idleAnim);
|
||||
SetIdleNext(frameduration(m_viewModel, idleAnim));
|
||||
}
|
||||
|
||||
void
|
||||
NSWeapon::SecondaryAttack(void)
|
||||
{
|
||||
|
@ -945,9 +1048,9 @@ NSWeapon::SecondaryAttack(void)
|
|||
|
||||
#ifdef SERVER
|
||||
if (ourOwner.viewzoom == 1.0) {
|
||||
Sound_Play(ourOwner, CHAN_WEAPON, GetDefString("snd_lower_scope"));
|
||||
PlaySound(GetDefString("snd_lower_scope"), false);
|
||||
} else {
|
||||
Sound_Play(ourOwner, CHAN_WEAPON, GetDefString("snd_raise_scope"));
|
||||
PlaySound(GetDefString("snd_raise_scope"), false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -961,10 +1064,12 @@ NSWeapon::SecondaryAttack(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (CanFire() == false)
|
||||
/* don't run any further logic */
|
||||
if (CanFire() == false) {
|
||||
Idle();
|
||||
return;
|
||||
}
|
||||
|
||||
SwitchFireInfo(m_secondaryFireInfo);
|
||||
Attack(m_secondaryFireInfo);
|
||||
}
|
||||
|
||||
|
@ -978,8 +1083,9 @@ NSWeapon::_ReloadFinished(void)
|
|||
ammoToDeduct = m_iClipSize - m_iClip;
|
||||
|
||||
/* not enough ammo. assign whatever is left. */
|
||||
if (ourOwner.HasAmmo(m_primaryAmmoType, ammoToDeduct) == false)
|
||||
if (ourOwner.HasAmmo(m_primaryAmmoType, ammoToDeduct) == false) {
|
||||
ammoToDeduct = ourOwner.m_iAmmoTypes[m_primaryAmmoType];
|
||||
}
|
||||
|
||||
m_iClip = m_iClipSize;
|
||||
ourOwner.UseAmmo(m_primaryAmmoType, ammoToDeduct);
|
||||
|
@ -990,7 +1096,6 @@ void
|
|||
NSWeapon::Reload(void)
|
||||
{
|
||||
NSClientPlayer ourOwner = (NSClientPlayer)GetOwner();
|
||||
string fireInfo;
|
||||
float reloadAnimation = 0;
|
||||
float reloadTime;
|
||||
string ammoType;
|
||||
|
@ -1008,17 +1113,11 @@ NSWeapon::Reload(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (CanFire() == false) {
|
||||
if (CanReload() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
fireInfo = m_strLastFireInfo;
|
||||
|
||||
/* fall back to main weapon def */
|
||||
if (!fireInfo)
|
||||
fireInfo = classname;
|
||||
|
||||
ammoType = GetSubDefString(fireInfo, "ammoType");
|
||||
ammoType = GetSubDefString(m_strLastFireInfo, "ammoType");
|
||||
ammoTypeID = ammoNumForName(ammoType);
|
||||
|
||||
if (m_iClip == m_iClipSize) {
|
||||
|
@ -1032,7 +1131,7 @@ NSWeapon::Reload(void)
|
|||
|
||||
/* we have a start-reload, so this is a shotgun styled weapon reload */
|
||||
if (reloadStartAct) {
|
||||
m_dState = WEAPONSTATE_RELOAD_START;
|
||||
SetWeaponState(WEAPONSTATE_RELOAD_START);
|
||||
Release();
|
||||
return;
|
||||
}
|
||||
|
@ -1061,13 +1160,9 @@ NSWeapon::Reload(void)
|
|||
reloadTime = m_flReloadSpeed;
|
||||
}
|
||||
|
||||
PlaySound(GetDefString("snd_reload"), false);
|
||||
|
||||
#ifdef SERVER
|
||||
string soundDef = GetDefString("snd_reload");
|
||||
|
||||
if (soundDef) {
|
||||
ourOwner.StartSoundDef(soundDef, CHAN_WEAPON, true);
|
||||
}
|
||||
|
||||
ScheduleThink(_ReloadFinished, reloadTime - 0.1f);
|
||||
#endif
|
||||
|
||||
|
@ -1106,6 +1201,19 @@ NSWeapon::_WeaponStartedFiring(void)
|
|||
|
||||
/* hasn't been fired yet. */
|
||||
if (!(owner.vv_flags & VFL_FIRING)) {
|
||||
float actFireStart = GetSubDefAct(m_strLastFireInfo, "actFireStart");
|
||||
|
||||
#ifdef SERVER
|
||||
printf("actFireStart %d %S\n", actFireStart, m_strLastFireInfo);
|
||||
#endif
|
||||
|
||||
if (actFireStart) {
|
||||
SetWeaponFrame(actFireStart);
|
||||
SetAttackNext(frameduration(m_viewModel, actFireStart));
|
||||
SetIdleNext(frameduration(m_viewModel, actFireStart));
|
||||
SetWeaponState(WEAPONSTATE_FIRELOOP);
|
||||
}
|
||||
|
||||
WeaponStartedFiring();
|
||||
}
|
||||
|
||||
|
@ -1121,6 +1229,19 @@ NSWeapon::_WeaponStoppedFiring(void)
|
|||
|
||||
/* was still registed as firing */
|
||||
if (owner.vv_flags & VFL_FIRING) {
|
||||
float actFireStop = GetSubDefAct(m_strLastFireInfo, "actFireStop");
|
||||
|
||||
#ifdef SERVER
|
||||
printf("actFireStop %d %S\n", actFireStop, m_strLastFireInfo);
|
||||
#endif
|
||||
|
||||
if (actFireStop) {
|
||||
SetWeaponFrame(actFireStop);
|
||||
SetAttackNext(frameduration(m_viewModel, actFireStop));
|
||||
SetIdleNext(frameduration(m_viewModel, actFireStop));
|
||||
SetWeaponState(WEAPONSTATE_RELEASED);
|
||||
}
|
||||
|
||||
WeaponStoppedFiring();
|
||||
}
|
||||
|
||||
|
@ -1189,10 +1310,6 @@ NSWeapon::Release(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (CanIdle() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_bFiring = false;
|
||||
|
||||
if (ourOwner.vv_flags & VFL_REDRAW) {
|
||||
|
@ -1201,75 +1318,7 @@ NSWeapon::Release(void)
|
|||
return;
|
||||
}
|
||||
|
||||
/* handle shotgun style reloads */
|
||||
switch (m_dState) {
|
||||
case WEAPONSTATE_RELOAD_START:
|
||||
idleAnim = GetDefAct("actReloadStart");
|
||||
m_dState = WEAPONSTATE_RELOAD;
|
||||
#ifdef SERVER
|
||||
Sound_Play(ourOwner, CHAN_WEAPON, GetDefString("snd_reload_start"));
|
||||
#endif
|
||||
break;
|
||||
case WEAPONSTATE_RELOAD:
|
||||
float reloadTime;
|
||||
idleAnim = GetDefAct("actReload");
|
||||
m_iClip++;
|
||||
ourOwner.UseAmmo(m_primaryAmmoType, 1);
|
||||
|
||||
if (HasReserveAmmo() == false || m_iClip >= m_iClipSize) {
|
||||
m_dState = WEAPONSTATE_RELOAD_END;
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
Sound_Play(ourOwner, CHAN_WEAPON, GetDefString("snd_reload"));
|
||||
#endif
|
||||
|
||||
if (m_flReloadSpeed == -1.0f) {
|
||||
reloadTime = frameduration(m_viewModel, idleAnim);
|
||||
} else {
|
||||
reloadTime = m_flReloadSpeed;
|
||||
}
|
||||
|
||||
SetWeaponFrame(idleAnim);
|
||||
SetIdleNext(reloadTime);
|
||||
return;
|
||||
break;
|
||||
case WEAPONSTATE_RELOAD_END:
|
||||
idleAnim = GetDefAct("actReloadEnd");
|
||||
m_dState = WEAPONSTATE_IDLE;
|
||||
#ifdef SERVER
|
||||
Sound_Play(ourOwner, CHAN_WEAPON, GetDefString("snd_reload_end"));
|
||||
#endif
|
||||
break;
|
||||
case WEAPONSTATE_IDLE:
|
||||
default:
|
||||
if (!m_iMode) {
|
||||
if (m_iClipSize > 0 && m_iClip == 0) {
|
||||
idleAnim = GetDefAct("actIdleEmpty");
|
||||
|
||||
/* this will mess with us otherwise */
|
||||
if (!idleAnim)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!idleAnim)
|
||||
idleAnim = GetDefAct("actIdle");
|
||||
} else {
|
||||
if (m_iClipSize > 0 && m_iClip == 0) {
|
||||
idleAnim = GetDefAct("actAltIdleEmpty");
|
||||
|
||||
/* this will mess with us otherwise */
|
||||
if (!idleAnim)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!idleAnim)
|
||||
idleAnim = GetDefAct("actAltIdle");
|
||||
}
|
||||
}
|
||||
|
||||
SetWeaponFrame(idleAnim);
|
||||
SetIdleNext(frameduration(m_viewModel, idleAnim));
|
||||
Idle();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1332,6 +1381,14 @@ NSWeapon::SetAttackNext(float newDelay)
|
|||
{
|
||||
NSClientPlayer ourOwner = (NSClientPlayer)GetOwner();
|
||||
ourOwner.w_attack_next = newDelay;
|
||||
SetReloadNext(newDelay);
|
||||
}
|
||||
|
||||
void
|
||||
NSWeapon::SetReloadNext(float newDelay)
|
||||
{
|
||||
NSClientPlayer ourOwner = (NSClientPlayer)GetOwner();
|
||||
ourOwner.w_reload_next = newDelay;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1369,6 +1426,18 @@ NSWeapon::CanFire(void)
|
|||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
NSWeapon::CanReload(void)
|
||||
{
|
||||
NSClientPlayer ourOwner = (NSClientPlayer)GetOwner();
|
||||
|
||||
if (ourOwner.w_reload_next > 0.0f) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* required because we might need to look it up inside the
|
||||
info for the primary attack mode. */
|
||||
static string
|
||||
|
|
|
@ -514,6 +514,7 @@ NSClientPlayer::Physics_InputPostMove(void)
|
|||
float punch;
|
||||
/* timers, these are predicted and shared across client and server */
|
||||
w_attack_next = max(0, w_attack_next - input_timelength);
|
||||
w_reload_next = max(0, w_reload_next - input_timelength);
|
||||
w_idle_next = max(0, w_idle_next - input_timelength);
|
||||
weapontime += input_timelength;
|
||||
|
||||
|
|
Loading…
Reference in a new issue