Scientist Hunt: Add some basic logic for the insanity mode. This adds

sh_insanity (cvar). Also fixed some shared Half-Life ish stuff with
blood, trigger_hurt entities... too tired to list
This commit is contained in:
Marco Cawthorne 2020-04-30 05:58:17 +02:00
parent 5ce957bb20
commit 9ea07752f8
19 changed files with 197 additions and 18 deletions

View File

@ -4,6 +4,7 @@
#define CSQC
#define CLIENT
#define VALVE
#define CLASSIC_VGUI
#includelist
../../shared/fteextensions.qc
@ -35,7 +36,7 @@
../../shared/valve/animations.c
../../shared/scihunt/player.cpp
../player.c
../../shared/valve/pmove.c
../../shared/scihunt/pmove.c
../../shared/pmove.c
../valve/predict.c
../predict.c

View File

@ -4,6 +4,7 @@
#define CSQC
#define CLIENT
#define VALVE
#define CLASSIC_VGUI
#includelist
../../shared/fteextensions.qc

View File

@ -55,6 +55,11 @@ void worldspawn::SpawnKey(string strField, string strKey)
g_ambientsound = spawn(env_soundscape);
g_ambientsound.m_iShader = Sound_Precache(strKey);
break;
#ifdef HHDEATH
case "_bgm":
localcmd(sprintf("music sound/bgm/%s.mp3\n", strKey));
break;
#endif
case "hdr_iris_minvalue":
g_flHDRIrisMinValue = stof(strKey);
cvar_set("r_hdr_irisadaptation_minvalue", ftos(g_flHDRIrisMinValue));

View File

@ -419,5 +419,4 @@ void
CBaseMonster::CBaseMonster(void)
{
CBaseEntity::CBaseEntity();
Respawn();
}

View File

@ -132,7 +132,7 @@ CBaseTrigger::InitBrushTrigger(void)
{
SetModel(m_oldModel);
movetype = MOVETYPE_NONE;
solid = SOLID_BSPTRIGGER;
solid = SOLID_TRIGGER;
SetRenderMode(RM_TRIGGER);
}

View File

@ -61,10 +61,8 @@ trigger_hurt::Trigger(void)
} else {
dprint(sprintf("trigger_hurt::^3Trigger: %s activated\n",
m_strTargetName));
solid = SOLID_BSPTRIGGER;
InitBrushTrigger();
touch = Touch;
setmodel (this, m_oldModel);
self.movetype = MOVETYPE_NONE;
}
}
@ -118,20 +116,25 @@ void
trigger_hurt::Respawn(void)
{
/* reset */
m_flNextDmg = 0.5f;
m_flNextTrigger = 0.0f;
if (spawnflags & SF_HURT_OFF) {
solid = SOLID_NOT;
touch = __NULL__;
} else {
InitBrushTrigger();
touch = Touch;
}
}
void
trigger_hurt::trigger_hurt(void)
{
/* defaults */
m_iDamage = 15;
m_flNextDmg = 0.5f;
CBaseEntity::CBaseEntity();
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "dmg":
@ -146,6 +149,4 @@ trigger_hurt::trigger_hurt(void)
break;
}
}
CBaseEntity::CBaseEntity();
}

View File

@ -95,5 +95,4 @@ trigger_multiple::trigger_multiple(void)
break;
}
}
InitBrushTrigger();
}

View File

@ -151,8 +151,7 @@ hostage_entity::Death(int iHitBody)
WarnAllies();
if (style != MONSTER_DEAD) {
frame = HOSA_DIE_SIMPLE + floor(random(0, 6));
style = MONSTER_DEAD;
SetFrame(HOSA_DIE_SIMPLE + floor(random(0, 6)));
}
/* now mark our state as 'dead' */

View File

@ -14,13 +14,39 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sh_insanity = 10;
var int autocvar_sv_playerkeepalive = TRUE;
void
SHMultiplayerRules::PlayerDeath(player pl)
{
weaponbox_spawn(pl);
/* obituary networking */
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_OBITUARY);
if (g_dmg_eAttacker.netname)
WriteString(MSG_MULTICAST, g_dmg_eAttacker.netname);
else
WriteString(MSG_MULTICAST, g_dmg_eAttacker.classname);
WriteString(MSG_MULTICAST, pl.netname);
WriteByte(MSG_MULTICAST, g_dmg_iWeapon);
WriteByte(MSG_MULTICAST, 0);
msg_entity = world;
multicast([0,0,0], MULTICAST_ALL);
/* death-counter */
pl.deaths++;
forceinfokey(pl, "*deaths", ftos(pl.deaths));
/* update score-counter */
if (pl.flags & FL_CLIENT || pl.flags & FL_MONSTER)
if (g_dmg_eAttacker.flags & FL_CLIENT) {
if (pl == g_dmg_eAttacker)
g_dmg_eAttacker.frags--;
else
g_dmg_eAttacker.frags++;
}
pl.movetype = MOVETYPE_NONE;
pl.solid = SOLID_NOT;
pl.takedamage = DAMAGE_NO;
@ -286,6 +312,17 @@ SHMultiplayerRules::PlayerPostFrame(player pl)
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
pl.sh_insaneactive = bound(0.0f, pl.sh_insaneactive - frametime, pl.sh_insaneactive);
if (pl.sh_insaneactive > 0.0f)
pl.flags |= FL_RESERVED1;
else {
if (pl.flags & FL_RESERVED1) {
bprint(PRINT_CHAT, sprintf("%s is no longer insane!\n", pl.netname));
}
pl.flags &= ~FL_RESERVED1;
}
}
void
@ -327,4 +364,42 @@ void
SHMultiplayerRules::PlayerKill(player pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}
void
SHMultiplayerRules::ScientistKill(player pl, entity sci)
{
/* obituary networking */
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_OBITUARY);
WriteString(MSG_MULTICAST, pl.netname);
WriteString(MSG_MULTICAST, sci.netname);
WriteByte(MSG_MULTICAST, g_dmg_iWeapon);
WriteByte(MSG_MULTICAST, 0);
msg_entity = world;
multicast([0,0,0], MULTICAST_ALL);
pl.frags++;
/*if (g_weapons[g_dmg_iWeapon].slot != 0)
return;*/
/* if this is our first kill in a while, or in the timer... */
if (pl.sh_insanecount == 0 || pl.sh_insanetime > time) {
pl.sh_insanecount++;
} else {
pl.sh_insanecount = 0;
}
if (pl.sh_insanecount >= autocvar_sh_insanity) {
if (pl.sh_insaneactive <= 0.0f)
bprint(PRINT_CHAT, sprintf("%s is going insane!\n", pl.netname));
pl.sh_insaneactive += 3.0f;
if (pl.sh_insaneactive > 60)
pl.sh_insaneactive = 60;
}
/* timer gets touched every time */
pl.sh_insanetime = time + 2.0f;
}

View File

@ -25,6 +25,7 @@ class SHMultiplayerRules:CGameRules
virtual void(player) PlayerKill;
virtual void(player) PlayerDeath;
virtual void(player) PlayerPostFrame;
virtual void(player, entity) ScientistKill;
virtual void(player) LevelDecodeParms;
virtual void(player) LevelChangeParms;

View File

@ -515,6 +515,14 @@ void monster_scientist::Physics(void)
} else {
m_iFlags -= (flags & SCIF_FALLING);
}
/* support for think/nextthink */
if (think && nextthink > 0.0f) {
if (nextthink < time) {
nextthink = 0.0f;
think();
}
}
}
void monster_scientist::touch(void)
@ -582,6 +590,11 @@ void monster_scientist::Death(int iHitBody)
return;
}
SHMultiplayerRules rules = (SHMultiplayerRules)g_grMode;
if (g_dmg_eAttacker.flags & FL_CLIENT)
rules.ScientistKill((player)g_dmg_eAttacker, (entity)this);
int r;
r = floor(random(0,sci_snddie.length));
Speak(sci_snddie[r]);

View File

@ -68,7 +68,7 @@ monster_scientist.cpp
../../shared/valve/fx_spark.c
../valve/player.c
../../shared/valve/pmove.c
../../shared/scihunt/pmove.c
../../shared/pmove.c
../valve/spectator.c
../../shared/scihunt/items.h

View File

@ -109,7 +109,7 @@ void
monster_alien_controller::Respawn(void)
{
CBaseMonster::Respawn();
frame = CON_IDLE;
SetFrame(CON_IDLE);
}
void

View File

@ -97,6 +97,8 @@ void monster_scientist_dead::Respawn(void)
default:
SetFrame(DSCIA_LYING1);
}
droptofloor();
}
void monster_scientist_dead::monster_scientist_dead(void)

View File

@ -116,5 +116,9 @@ class player:CBaseEntity
int old_a_ammo2;
int old_a_ammo3;
int voted;
int sh_insanecount;
float sh_insanetime;
float sh_insaneactive;
#endif
};

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <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.
*/
#define PHY_JUMP_CHAINWINDOW 0.5
#define PHY_JUMP_CHAIN 100
#define PHY_JUMP_CHAINDECAY 50
.float waterlevel;
.float watertype;
float GamePMove_Maxspeed(player target)
{
if (target.flags & FL_RESERVED1)
return (target.flags & FL_CROUCHING) ? 135 : 500;
else
return (target.flags & FL_CROUCHING) ? 135 : 270;
}
void GamePMove_Fall(player target, float impactspeed)
{
if (impactspeed > 580) {
#ifdef SERVER
float fFallDamage = (impactspeed - 580) * (100 / (1024 - 580));
Damage_Apply(self, world, fFallDamage, 0, DMG_FALL);
Sound_Play(self, CHAN_AUTO, "player.fall");
#endif
}
}
void GamePMove_Jump(player target)
{
float flJumptimeDelta;
float flChainBonus;
if (target.waterlevel >= 2) {
if (target.watertype == CONTENT_WATER) {
target.velocity[2] = 100;
} else if (target.watertype == CONTENT_SLIME) {
target.velocity[2] = 80;
} else {
target.velocity[2] = 50;
}
} else {
/* Half-Life: Longjump module */
#ifdef VALVE
if (target.flags & FL_CROUCHING && target.g_items & 0x00008000i) {
target.velocity = v_forward * 512;
target.velocity[2] += 100;
}
#endif
target.velocity[2] += 240;
}
if (target.jumptime > 0) {
flJumptimeDelta = 0 - (target.jumptime - PHY_JUMP_CHAINWINDOW);
flChainBonus = PHY_JUMP_CHAIN - (((PHY_JUMP_CHAINWINDOW - (PHY_JUMP_CHAINWINDOW - flJumptimeDelta)) * 2) * PHY_JUMP_CHAINDECAY);
target.velocity[2] += flChainBonus;
}
target.jumptime = PHY_JUMP_CHAINWINDOW;
}

View File

@ -55,7 +55,7 @@ FX_Blood(vector pos, vector color)
eBlood.maxframe = modelframecount(eBlood.modelindex);
eBlood.loops = 0;
eBlood.scale = 1.0f;
eBlood.colormod = color;
eBlood.m_vecRenderColor = color;
eBlood.framerate = 20;
eBlood.nextthink = time + 0.05f;
@ -69,7 +69,7 @@ FX_Blood(vector pos, vector color)
ePart.drawmask = MASK_ENGINE;
ePart.maxframe = modelframecount(ePart.modelindex);
ePart.loops = 0;
ePart.colormod = color;
ePart.m_vecRenderColor = color;
ePart.framerate = 15;
ePart.nextthink = time + 0.1f;
ePart.velocity = randomvec() * 64;

View File

@ -66,6 +66,7 @@ FX_Impact(int iType, vector vecPos, vector vNormal)
}
switch (iType) {
case IMPACT_MELEE:
case IMPACT_EXPLOSION:
break;
case IMPACT_GLASS:

View File

@ -101,7 +101,12 @@ w_crowbar_primary(void)
Weapons_MakeVectors();
src = pl.origin + pl.view_ofs;
/* make sure we can gib corpses */
int oldhitcontents = self.hitcontentsmaski;
self.hitcontentsmaski = CONTENTBITS_POINTSOLID | CONTENTBIT_CORPSE;
traceline(src, src + (v_forward * 32), FALSE, pl);
self.hitcontentsmaski = oldhitcontents;
if (trace_fraction >= 1.0) {
pl.w_attack_next = 0.5f;