Implement functionality of the various powerups, except for rendering.

This commit is contained in:
Marco Cawthorne 2023-04-16 09:49:38 -07:00
parent 32902116be
commit 621b93171f
Signed by: eukara
GPG key ID: CE2032F0A2882A22
16 changed files with 249 additions and 12 deletions

19
src/server/defs.h Normal file
View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "gamerules.h"
#include "../../../valve/src/server/items.h"
#include "../../../valve/src/server/flashlight.h"

63
src/server/gamerules.h Normal file
View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class HLGameRules:NSGameRules
{
virtual void DamageApply(entity, entity, float, int, damageType_t);
virtual void PlayerConnect(NSClientPlayer);
virtual void PlayerDisconnect(NSClientPlayer);
virtual void PlayerKill(NSClientPlayer);
virtual void PlayerPostFrame(NSClientPlayer);
virtual void LevelDecodeParms(NSClientPlayer);
virtual void LevelChangeParms(NSClientPlayer);
virtual void LevelNewParms(void);
virtual bool IsMultiplayer(void);
virtual bool ImpulseCommand(NSClient, float);
};
class HLSingleplayerRules:HLGameRules
{
/* client */
virtual void(NSClientPlayer) PlayerSpawn;
virtual void(NSClientPlayer) PlayerDeath;
virtual bool(void) IsMultiplayer;
virtual bool ImpulseCommand(NSClient, float);
};
class HLMultiplayerRules:HLGameRules
{
int m_iIntermission;
int m_iIntermissionTime;
string m_strTeamList;
void(void) HLMultiplayerRules;
virtual void(void) FrameStart;
virtual void(void) CheckRules;
virtual bool(void) MonstersSpawn;
/* client */
virtual void(NSClientPlayer) PlayerSpawn;
virtual void(NSClientPlayer) PlayerDeath;
virtual bool(NSClientPlayer, string) ConsoleCommand;
virtual bool(void) IsMultiplayer;
virtual bool(void) IsTeamplay;
virtual void(void) InitPostEnts;
virtual bool PlayerRequestRespawn(NSClientPlayer);
};

View file

@ -20,6 +20,36 @@ HLGameRules::IsMultiplayer(void)
return false; return false;
} }
void
HLGameRules::DamageApply(entity t, entity c, float dmg, int w, damageType_t type)
{
player targetPlayer;
player causingPlayer;
/* handle Quad Damage */
if (c.classname == "player") {
causingPlayer = (player)c;
if (causingPlayer.HasQuadDamage())
dmg *= 4.0f;
}
if (t.classname == "player") {
targetPlayer = (player)t;
/* handle Invulnerability */
if (targetPlayer.HasInvulnerability())
return;
/* handle Enviro Suit */
if (type == DMG_BURN || type == DMG_ACID)
if (targetPlayer.HasEnviroSuit())
return;
}
super::DamageApply(t, c, dmg, w, type);
}
void void
HLGameRules::LevelDecodeParms(NSClientPlayer pp) HLGameRules::LevelDecodeParms(NSClientPlayer pp)
{ {

View file

@ -17,6 +17,8 @@
class item_artifact:NSRenderableEntity class item_artifact:NSRenderableEntity
{ {
float m_respawnTime; float m_respawnTime;
int m_itemID;
float m_usageTime;
void(void) item_artifact; void(void) item_artifact;
@ -36,6 +38,22 @@ item_artifact::Touch(entity eToucher)
Sound_Play(eToucher, CHAN_ITEM, noise); Sound_Play(eToucher, CHAN_ITEM, noise);
Logging_Pickup(eToucher, this, __NULL__); Logging_Pickup(eToucher, this, __NULL__);
if (m_itemID == ITEM_QUAD) {
pl.m_quadFinishTime = time + 30.0f;
} else if (m_itemID == ITEM_INVIS) {
pl.m_invisFinishTime = time + 30.0f;
} else if (m_itemID == ITEM_INVULN) {
pl.m_invulnFinishTime = time + 30.0f;
} else if (m_itemID == ITEM_ENVIROSUIT) {
pl.m_enviroFinishTime = time + 30.0f;
}
pl.g_items |= m_itemID;
pl.SetRenderMode(GetRenderMode());
pl.SetRenderFX(GetRenderFX());
pl.SetRenderColor(GetRenderColor());
pl.SetRenderAmt(GetRenderAmt());
/* TODO: if deathmatch is 4 and player invincible, don't pick up */ /* TODO: if deathmatch is 4 and player invincible, don't pick up */
if (cvar("deathmatch") == 0 || cvar("deathmatch") == 2) { if (cvar("deathmatch") == 0 || cvar("deathmatch") == 2) {
Destroy(); Destroy();
@ -78,6 +96,7 @@ item_artifact::item_artifact(void)
{ {
m_oldModel = model; m_oldModel = model;
m_respawnTime = 60.0f; m_respawnTime = 60.0f;
m_itemID = 0i;
} }
/*QUAKED item_artifact_envirosuit (0 0 0.8) (-16 -16 0) (16 16 32) /*QUAKED item_artifact_envirosuit (0 0 0.8) (-16 -16 0) (16 16 32)
@ -112,6 +131,7 @@ item_artifact_envirosuit::Touch(entity eToucher)
if (eToucher.classname != "player") if (eToucher.classname != "player")
return; return;
m_itemID = ITEM_ENVIROSUIT;
super::Touch(eToucher); super::Touch(eToucher);
} }
@ -160,6 +180,7 @@ item_artifact_invisibility::Touch(entity eToucher)
return; return;
m_respawnTime = 5 * 60.0f; m_respawnTime = 5 * 60.0f;
m_itemID = ITEM_INVIS;
super::Touch(eToucher); super::Touch(eToucher);
} }
@ -207,6 +228,7 @@ item_artifact_invulnerability::Touch(entity eToucher)
return; return;
m_respawnTime = 5 * 60.0f; m_respawnTime = 5 * 60.0f;
m_itemID = ITEM_INVULN;
super::Touch(eToucher); super::Touch(eToucher);
} }
@ -242,6 +264,7 @@ void
item_artifact_super_damage::Spawned(void) item_artifact_super_damage::Spawned(void)
{ {
super::Spawned(); super::Spawned();
Sound_Precache("item_artifact_super_damage.attack");
SetRenderFX(RFX_GLOWSHELL); SetRenderFX(RFX_GLOWSHELL);
SetRenderColor([0.5, 0.5, 1.0]); SetRenderColor([0.5, 0.5, 1.0]);
SetRenderAmt(0.45f); SetRenderAmt(0.45f);
@ -253,5 +276,6 @@ item_artifact_super_damage::Touch(entity eToucher)
if (eToucher.classname != "player") if (eToucher.classname != "player")
return; return;
m_itemID = ITEM_QUAD;
super::Touch(eToucher); super::Touch(eToucher);
} }

View file

@ -15,7 +15,7 @@
../../../src/gs-entbase/server.src ../../../src/gs-entbase/server.src
../../../src/gs-entbase/shared.src ../../../src/gs-entbase/shared.src
../../../valve/src/server/defs.h defs.h
../shared/include.src ../shared/include.src

View file

@ -32,10 +32,10 @@
#define ITEM_SUIT 0x00004000i #define ITEM_SUIT 0x00004000i
#define ITEM_LONGJUMP 0x00008000i #define ITEM_LONGJUMP 0x00008000i
#define ITEM_UNUSED17 0x00010000i #define ITEM_QUAD 0x00010000i
#define ITEM_UNUSED18 0x00020000i #define ITEM_INVIS 0x00020000i
#define ITEM_UNUSED19 0x00040000i #define ITEM_INVULN 0x00040000i
#define ITEM_UNUSED20 0x00080000i #define ITEM_ENVIROSUIT 0x00080000i
#define ITEM_UNUSED21 0x00100000i #define ITEM_UNUSED21 0x00100000i
#define ITEM_UNUSED22 0x00200000i #define ITEM_UNUSED22 0x00200000i
#define ITEM_UNUSED23 0x00400000i #define ITEM_UNUSED23 0x00400000i

View file

@ -14,6 +14,8 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "items.h"
#ifdef CLIENT #ifdef CLIENT
/* Here's a list of bone names that we are aware of on HL player models. /* Here's a list of bone names that we are aware of on HL player models.
Usually we'd use skeletalobjects to share the same skeleton/anim with Usually we'd use skeletalobjects to share the same skeleton/anim with
@ -132,6 +134,13 @@ class player:NSClientPlayer
PREDICTED_FLOAT_N(ammo_rockets) PREDICTED_FLOAT_N(ammo_rockets)
PREDICTED_FLOAT_N(ammo_cells) PREDICTED_FLOAT_N(ammo_cells)
#ifdef SERVER
float m_quadFinishTime;
float m_invisFinishTime;
float m_invulnFinishTime;
float m_enviroFinishTime;
#endif
virtual void Physics_Jump(void); virtual void Physics_Jump(void);
virtual void UpdatePlayerAnimation(float); virtual void UpdatePlayerAnimation(float);
@ -150,6 +159,11 @@ class player:NSClientPlayer
virtual void Save(float); virtual void Save(float);
virtual void Restore(string,string); virtual void Restore(string,string);
#endif #endif
nonvirtual bool HasQuadDamage(void);
nonvirtual bool HasInvisibility(void);
nonvirtual bool HasInvulnerability(void);
nonvirtual bool HasEnviroSuit(void);
}; };
void Animation_PlayerUpdate(player); void Animation_PlayerUpdate(player);
@ -449,6 +463,33 @@ player::EvaluateEntity(void)
EVALUATE_FIELD(ammo_nails, PLAYER_AMMO1) EVALUATE_FIELD(ammo_nails, PLAYER_AMMO1)
EVALUATE_FIELD(ammo_rockets, PLAYER_AMMO1) EVALUATE_FIELD(ammo_rockets, PLAYER_AMMO1)
EVALUATE_FIELD(ammo_cells, PLAYER_AMMO1) EVALUATE_FIELD(ammo_cells, PLAYER_AMMO1)
if (g_items & ITEM_QUAD) {
if (m_quadFinishTime < time) {
g_items &= ~ITEM_QUAD;
}
}
if (g_items & ITEM_INVIS) {
if (m_invisFinishTime < time) {
g_items &= ~ITEM_INVIS;
}
}
if (g_items & ITEM_INVULN) {
if (m_invulnFinishTime < time) {
g_items &= ~ITEM_INVULN;
}
}
if (g_items & ITEM_ENVIROSUIT) {
if (m_enviroFinishTime < time) {
}
g_items &= ~ITEM_ENVIROSUIT;
}
} }
/* /*
@ -488,6 +529,30 @@ player::SendEntity(entity ePEnt, float flChanged)
} }
#endif #endif
bool
player::HasQuadDamage(void)
{
return g_items & ITEM_QUAD ? true : false;
}
bool
player::HasInvisibility(void)
{
return g_items & ITEM_INVIS ? true : false;
}
bool
player::HasInvulnerability(void)
{
return g_items & ITEM_INVULN ? true : false;
}
bool
player::HasEnviroSuit(void)
{
return g_items & ITEM_ENVIROSUIT ? true : false;
}
void void
player::player(void) player::player(void)
{ {

View file

@ -93,6 +93,10 @@ w_crowbar_primary(player pl)
Animation_PlayerTop(pl, (pl.flags & FL_CROUCHING) ? ANIM_CR_SHOOTCROWBAR : ANIM_SHOOTCROWBAR, 0.41f); Animation_PlayerTop(pl, (pl.flags & FL_CROUCHING) ? ANIM_CR_SHOOTCROWBAR : ANIM_SHOOTCROWBAR, 0.41f);
#ifdef SERVER #ifdef SERVER
if (pl.HasQuadDamage()) {
Sound_Play(pl, CHAN_ITEM, "item_artifact_super_damage.attack");
}
Sound_Play(pl, CHAN_WEAPON, "weapon_crowbar.swing"); Sound_Play(pl, CHAN_WEAPON, "weapon_crowbar.swing");
if (trace_fraction >= 1.0) { if (trace_fraction >= 1.0) {

View file

@ -154,6 +154,10 @@ w_grenadelauncher_primary(player pl)
/* fire the actual projectile (on the server) */ /* fire the actual projectile (on the server) */
#ifdef SERVER #ifdef SERVER
if (pl.HasQuadDamage()) {
Sound_Play(pl, CHAN_ITEM, "item_artifact_super_damage.attack");
}
w_grenadelauncher_shootnade(pl); w_grenadelauncher_shootnade(pl);
#endif #endif

View file

@ -131,6 +131,9 @@ w_lightning_primary(player pl)
} }
} }
if (pl.HasQuadDamage()) {
Sound_Play(pl, CHAN_ITEM, "item_artifact_super_damage.attack");
}
Sound_Play(pl, CHAN_WEAPON, "weapon_lightning.start"); Sound_Play(pl, CHAN_WEAPON, "weapon_lightning.start");
#endif #endif

View file

@ -138,6 +138,10 @@ w_nailgun_primary(player pl)
nail.angles = vectoangles(nail.velocity); nail.angles = vectoangles(nail.velocity);
} }
if (pl.HasQuadDamage()) {
Sound_Play(pl, CHAN_ITEM, "item_artifact_super_damage.attack");
}
Sound_Play(pl, CHAN_WEAPON, "weapon_nailgun.shoot"); Sound_Play(pl, CHAN_WEAPON, "weapon_nailgun.shoot");
#endif #endif

View file

@ -138,6 +138,10 @@ w_rocketlauncher_primary(player pl)
setsize(rocket, [0,0,0], [0,0,0]); setsize(rocket, [0,0,0], [0,0,0]);
Sound_Play(pl, CHAN_WEAPON, "weapon_rocketlauncher.shoot"); Sound_Play(pl, CHAN_WEAPON, "weapon_rocketlauncher.shoot");
if (pl.HasQuadDamage()) {
Sound_Play(pl, CHAN_ITEM, "item_artifact_super_damage.attack");
}
#endif #endif
} }

View file

@ -133,6 +133,10 @@ w_shotgun_primary(player pl)
/* Singleplayer is more accurate */ /* Singleplayer is more accurate */
TraceAttack_FireBulletsWithDecal(6, pl.origin + pl.view_ofs, Skill_GetValue("plr_shotgun", 4), [0.1,0.1], WEAPON_SHOTGUN, "Impact.BigShot"); TraceAttack_FireBulletsWithDecal(6, pl.origin + pl.view_ofs, Skill_GetValue("plr_shotgun", 4), [0.1,0.1], WEAPON_SHOTGUN, "Impact.BigShot");
Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.shoot"); Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.shoot");
if (pl.HasQuadDamage()) {
Sound_Play(pl, CHAN_ITEM, "item_artifact_super_damage.attack");
}
#else #else
//View_AddEvent(w_shotgun_ejectshell, 0.25f); //View_AddEvent(w_shotgun_ejectshell, 0.25f);
#endif #endif

View file

@ -140,6 +140,10 @@ w_supernailgun_primary(player pl)
} }
Sound_Play(pl, CHAN_WEAPON, "weapon_supernailgun.shoot"); Sound_Play(pl, CHAN_WEAPON, "weapon_supernailgun.shoot");
if (pl.HasQuadDamage()) {
Sound_Play(pl, CHAN_ITEM, "item_artifact_super_damage.attack");
}
#endif #endif
pl.w_attack_next = 0.085f; pl.w_attack_next = 0.085f;

View file

@ -151,6 +151,10 @@ w_supershotgun_primary(player pl)
#else #else
TraceAttack_FireBulletsWithDecal(14, pl.origin + pl.view_ofs, Skill_GetValue("plr_supershotgun", 4), [0.14,0.08], WEAPON_SUPERSHOTGUN, "Impact.BigShot"); TraceAttack_FireBulletsWithDecal(14, pl.origin + pl.view_ofs, Skill_GetValue("plr_supershotgun", 4), [0.14,0.08], WEAPON_SUPERSHOTGUN, "Impact.BigShot");
Sound_Play(pl, CHAN_WEAPON, "weapon_supershotgun.shoot"); Sound_Play(pl, CHAN_WEAPON, "weapon_supershotgun.shoot");
if (pl.HasQuadDamage()) {
Sound_Play(pl, CHAN_ITEM, "item_artifact_super_damage.attack");
}
#endif #endif
Weapons_ViewPunchAngle(pl, [-2,0,0]); Weapons_ViewPunchAngle(pl, [-2,0,0]);

View file

@ -54,6 +54,11 @@ item_artifact_super_damage.pickup
sample items/damage.wav sample items/damage.wav
} }
item_artifact_super_damage.attack
{
sample items/damage3.wav
}
dmc_item.respawn dmc_item.respawn
{ {
sample items/itembk2.wav sample items/itembk2.wav