Add func_tank, func_tankmortar and generally faff about with input code.

This commit is contained in:
Marco Cawthorne 2020-09-04 21:28:06 +02:00
parent 3ca223b673
commit 50ccbf4b9a
27 changed files with 892 additions and 13 deletions

View File

@ -80,7 +80,5 @@ CSQC_Parse_Damage(float save, float take, vector abs_pos)
pSeat->m_flDamageAlpha = 1.0f;
}
//View_AddPunchAngle([take,0,0]);
return TRUE;
}

View File

@ -257,7 +257,6 @@ CSQC_UpdateView(float w, float h, float focus)
setproperty(VF_CL_VIEWANGLES, view_angles);
setproperty(VF_ANGLES, view_angles);
} else {
pSeat->m_vecCameraOrigin = [0,0,0];
if (pl.health) {
if (autocvar_cl_thirdperson == TRUE) {
makevectors(view_angles);
@ -273,7 +272,10 @@ CSQC_UpdateView(float w, float h, float focus)
}
if (g_iIntermission) {
view_angles = pSeat->m_vecCameraAngle + [sin(time), sin(time * 2)] * 5;
view_angles = pSeat->m_vecCameraAngle;
view_angles += [sin(time), sin(time * 2)] * 5;
setproperty(VF_ORIGIN, pSeat->m_vecCameraOrigin);
setproperty(VF_CL_VIEWANGLES, view_angles);
}
setproperty(VF_ANGLES, view_angles + pl.punchangle);
}
@ -492,9 +494,27 @@ CSQC_Parse_Event(void)
switch (fHeader) {
case EV_INTERMISSION:
int cam;
vector pos, ang;
cam = (int)readbyte();
if (cam) {
ang[0] = readfloat();
ang[1] = readfloat();
ang[2] = readfloat();
pos[0] = readcoord();
pos[1] = readcoord();
pos[2] = readcoord();
} else {
pos = getproperty(VF_ORIGIN);
ang = getproperty(VF_ANGLES);
}
pSeat->m_vecCameraOrigin = pos;
pSeat->m_vecCameraAngle = ang;
g_iIntermission = TRUE;
pSeat->m_vecCameraOrigin = getproperty(VF_ORIGIN);
pSeat->m_vecCameraAngle = getproperty(VF_ANGLES);
break;
case EV_MUSICTRACK:
Music_ParseTrack();

View File

@ -14,6 +14,7 @@ server/basephysics.cpp
server/basevehicle.cpp
server/info_null.cpp
server/info_notnull.cpp
server/info_intermission.cpp
server/button_target.cpp
server/ambient_generic.cpp
server/cycler.cpp
@ -42,6 +43,9 @@ server/func_train.cpp
server/func_guntarget.cpp
server/func_tracktrain.cpp
server/func_tracktraincontrols.cpp
server/func_tank.cpp
server/func_tankmortar.cpp
server/func_tankcontrols.cpp
server/func_pushable.cpp
server/func_wall.cpp
server/func_wall_toggle.cpp

View File

@ -24,8 +24,15 @@ class CBaseVehicle:CBaseTrigger
virtual void(void) PlayerAlign;
virtual void(base_player) PlayerEnter;
virtual void(base_player) PlayerLeave;
virtual void() PlayerInput;
};
void
CBaseVehicle::PlayerInput(void)
{
}
void
CBaseVehicle::PlayerAlign(void)
{
@ -56,6 +63,7 @@ CBaseVehicle::PlayerEnter(base_player pl)
m_vecPlayerPos[2] = dotproduct(offs, v_up);
pl.movetype = MOVETYPE_NOCLIP;
m_eDriver = (entity)pl;
pl.vehicle = this;
}
void
@ -63,6 +71,7 @@ CBaseVehicle::PlayerLeave(base_player pl)
{
pl.movetype = MOVETYPE_WALK;
pl.flags &= ~FL_FROZEN;
pl.vehicle = __NULL__;
m_eDriver = __NULL__;
}

View File

@ -0,0 +1,261 @@
/*
* 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.
*/
/*QUAKED func_tank (0 .5 .8) ? FNCTANK_ACTIVE x x x FNCTANK_DIRECTONLY FNCTANK_CONTROLLABLE
"targetname" Name
"yawrate" The speed of the left/right movement of the gun.
"yawrange" Range of left/right movement in degrees.
"pitchrate" The speed of the up/down movement of the gun.
"pitchrange" Range of up/down movement in degrees.
"barrel" Distance from origin to barrel tip in units.
"barrely" Horizontal distance origin to the center of the barrel tip.
"barrelz" Vertical distance origin to the center of the barrel tip.
"firerate" Number of bullets fired per second.
"bullet_damage" Damage each fired bullet does.
"firespread" Accuracy of the gun. 0 is best, 4 is worst.
"persistance" Time in seconds for how long an NPC might continue shooting.
"minRange" Minimum range the target can be at for an NPC to fire.
"maxRange" Maximum range the target can be at for an NPC to fire.
"spritesmoke" Sprite to spawn for 'smoke' when the entity is fired.
"spriteflash" Sprite to spawn for a 'muzzleflash' when the entity is fired.
"spritescale" Scale multiplier for both smoke and flash sprites.
"rotatesound" Sound file to play in a loop while barrel is rotating.
Description:
A mountable tank gun turret type entity. A player (or NPC) can interact with
it and shoot it. It's in the same family as the func_tankmortar entity, the
difference being that this shoots bullets and not mortar blasts.
Notes:
I don't like the sprite stuff tacked on at all because of the extra networking
involved and because it's so awfully GoldSrc specific.
Eventually I need to design a more generic routine that allows people to just
refer to materials with the appropriate blend-modes instead of hardcoding that
some random sprites needs to be treated additive.
Trivia:
This entity was introduced in Half-Life (1998).
*/
/* TODO: Implement these */
enumflags
{
FNCTANK_ACTIVE,
FNCTANK_UNUSED1,
FNCTANK_UNUSED2,
FNCTANK_UNUSED3,
FNCTANK_DIRECTONLY,
FNCTANK_CONTROLLABLE
};
class func_tank:CBaseVehicle
{
/* attributes */
float m_flYawRate; /* TODO */
float m_flYawRange; /* TODO */
float m_flPitchRate; /* TODO */
float m_flPitchRange; /* TODO */
vector m_vecTipPos;
float m_flFireRate;
int m_iDamage;
vector m_vecSpread; /* TODO: Needs checking */
string m_strSpriteSmoke;
string m_strSpriteFlash;
float m_flSpriteScale;
string m_strSndRotate; /* TODO */
float m_flPersistance; /* TODO */
float m_flMinRange; /* TODO */
float m_flMaxRange; /* TODO */
float m_flFireTime;
void(void) func_tank;
virtual void(void) customphysics;
virtual void(void) PlayerInput;
virtual void(void) Respawn;
virtual void(vector) SpriteSmoke;
virtual void(vector) SpriteFlash;
};
void
func_tank::SpriteSmoke(vector org)
{
static void Die(void) {
remove(self);
}
if (!m_strSpriteSmoke)
return;
entity smoke = spawn();
setmodel(smoke, m_strSpriteSmoke);
setorigin(smoke, org);
smoke.think = Die;
smoke.nextthink = time + 0.1f;
}
void
func_tank::SpriteFlash(vector org)
{
static void Die(void) {
remove(self);
}
if (!m_strSpriteFlash)
return;
entity smoke = spawn();
setmodel(smoke, m_strSpriteFlash);
setorigin(smoke, org);
smoke.think = Die;
smoke.nextthink = time + 0.1f;
}
void
func_tank::customphysics(void)
{
if (m_eDriver && m_eDriver.health <= 0)
PlayerLeave(m_eDriver);
if (m_eDriver) {
vector endorg;
makevectors(m_eDriver.v_angle);
endorg = v_forward * 4086;
angles = vectoangles(endorg - origin);
if (vlen(m_eDriver.origin - origin) > 128)
PlayerLeave(m_eDriver);
}
}
void
func_tank_shootsingle(entity shooter, vector org, vector spread, int damg)
{
entity oldself = self;
self = shooter;
TraceAttack_FireBullets(1, org, damg, spread, 0);
self = oldself;
}
void
func_tank::PlayerInput(void)
{
if (m_flFireTime < time)
if (input_buttons & INPUT_BUTTON0) {
vector spos;
/* barrel tip offset */
makevectors(angles);
spos = origin + v_forward * m_vecTipPos[0];
spos += v_right * m_vecTipPos[1];
spos += v_up * m_vecTipPos[2];
CBaseTrigger::UseTargets(this, TRIG_ON);
func_tank_shootsingle(m_eDriver, spos, m_vecSpread, m_iDamage);
m_flFireTime = time + m_flFireRate;
SpriteSmoke(spos);
SpriteFlash(spos);
/* disable actual weapon fire */
input_buttons = 0;
}
input_buttons &= ~INPUT_BUTTON0;
}
void
func_tank::Respawn(void)
{
SetMovetype(MOVETYPE_PUSH);
SetSolid(SOLID_BSP);
SetModel(m_oldModel);
SetOrigin(m_oldOrigin);
SetAngles(m_oldAngle);
if (m_eDriver)
PlayerLeave(m_eDriver);
}
void
func_tank::func_tank(void)
{
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "yawrate":
m_flYawRate = stof(argv(i+1));
break;
case "yawrange":
m_flYawRange = stof(argv(i+1));
break;
case "pitchrate":
m_flPitchRate = stof(argv(i+1));
break;
case "pitchrange":
m_flPitchRange = stof(argv(i+1));
break;
case "barrel":
m_vecTipPos[0] = stof(argv(i+1));
break;
case "barrely":
m_vecTipPos[1] = stof(argv(i+1));
break;
case "barrelz":
m_vecTipPos[2] = stof(argv(i+1));
break;
case "firerate":
m_flFireRate = 1.0f / stof(argv(i+1));
break;
case "bullet_damage":
m_iDamage = stoi(argv(i+1));
break;
case "firespread":
m_vecSpread = [0.25, 0.25, 0] * stof(argv(i+1));
break;
case "persistance":
m_flPersistance = stof(argv(i+1));
break;
case "minRange":
m_flMinRange = stof(argv(i+1));
break;
case "maxRange":
m_flMaxRange = stof(argv(i+1));
break;
case "spritesmoke":
m_strSpriteSmoke = argv(i+1);
break;
case "spriteflash":
m_strSpriteFlash = argv(i+1);
break;
case "spritescale":
m_flSpriteScale = stof(argv(i+1));
break;
case "rotatesound":
m_strSndRotate = argv(i+1);
break;
default:
break;
}
}
if (m_strSpriteFlash)
precache_model(m_strSpriteFlash);
if (m_strSpriteSmoke)
precache_model(m_strSpriteSmoke);
CBaseVehicle::CBaseVehicle();
}

View File

@ -0,0 +1,68 @@
/*
* 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.
*/
/*QUAKED func_tankcontrols (0 .5 .8) ?
"targetname" Name
*/
class func_tankcontrols:CBaseTrigger
{
void(void) func_tankcontrols;
virtual void(void) PlayerUse;
virtual void(void) Respawn;
};
void
func_tankcontrols::PlayerUse(void)
{
entity f;
CBaseVehicle tank;
if (!(eActivator.flags & FL_CLIENT)) {
return;
}
for (f = world; (f = find(f, CBaseEntity::m_strTargetName, m_strTarget));) {
/* we found the right entity */
if (f.classname == "func_tank" || f.classname == "func_tankmortar") {
tank = (CBaseVehicle)f;
}
}
if (tank) {
if (!tank.m_eDriver)
tank.PlayerEnter(eActivator);
else if (tank.m_eDriver == eActivator)
tank.PlayerLeave(eActivator);
}
}
void
func_tankcontrols::Respawn(void)
{
SetMovetype(MOVETYPE_PUSH);
SetSolid(SOLID_BSP);
SetModel(m_oldModel);
SetOrigin(m_oldOrigin);
SetRenderMode(RM_TRIGGER);
}
void
func_tankcontrols::func_tankcontrols(void)
{
CBaseTrigger::CBaseTrigger();
}

View File

@ -0,0 +1,274 @@
/*
* 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.
*/
/*QUAKED func_tankmortar (0 .5 .8) ?
"targetname" Name
"yawrate" The speed of the left/right movement of the mortar.
"yawrange" Range of left/right movement in degrees.
"pitchrate" The speed of the up/down movement of the mortar.
"pitchrange" Range of up/down movement in degrees.
"barrel" Distance from origin to barrel tip in units.
"barrely" Horizontal distance origin to the center of the barrel tip.
"barrelz" Vertical distance origin to the center of the barrel tip.
"firerate" Number of bullets fired per second.
"iMagnitude" Power of each explosion.
"firespread" Accuracy of the mortar. 0 is best, 4 is worst.
"persistance" Time in seconds for how long an NPC might continue shooting.
"minRange" Minimum range the target can be at for an NPC to fire.
"maxRange" Maximum range the target can be at for an NPC to fire.
"spritesmoke" Sprite to spawn for 'smoke' when the entity is fired.
"spriteflash" Sprite to spawn for a 'muzzleflash' when the entity is fired.
"spritescale" Scale multiplier for both smoke and flash sprites.
"rotatesound" Sound file to play in a loop while barrel is rotating.
Description:
A mountable tank mortar turret type entity. A player (or NPC) can interact with
it and shoot it. It's in the same family as the func_tank entity, the
difference being that this shoots mortar blasts and not bullets.
Notes:
I don't like the sprite stuff tacked on at all because of the extra networking
involved and because it's so awfully GoldSrc specific.
Eventually I need to design a more generic routine that allows people to just
refer to materials with the appropriate blend-modes instead of hardcoding that
some random sprites needs to be treated additive.
Trivia:
This entity was introduced in Half-Life (1998).
*/
/* TODO: Implement these */
enumflags
{
FNCTANK_ACTIVE,
FNCTANK_UNUSED1,
FNCTANK_UNUSED2,
FNCTANK_UNUSED3,
FNCTANK_DIRECTONLY,
FNCTANK_CONTROLLABLE
};
class func_tankmortar:CBaseVehicle
{
/* attributes */
float m_flYawRate;
float m_flYawRange; /* TODO */
float m_flPitchRate;
float m_flPitchRange; /* TODO */
vector m_vecTipPos;
float m_flFireRate;
int m_iDamage;
vector m_vecSpread; /* TODO: Needs checking */
string m_strSpriteSmoke;
string m_strSpriteFlash;
float m_flSpriteScale;
string m_strSndRotate; /* TODO */
float m_flPersistance; /* TODO */
float m_flMinRange; /* TODO */
float m_flMaxRange; /* TODO */
float m_flFireTime;
void(void) func_tankmortar;
virtual void(void) customphysics;
virtual void(void) PlayerInput;
virtual void(void) Respawn;
virtual void(vector) SpriteSmoke;
virtual void(vector) SpriteFlash;
};
void
func_tankmortar::SpriteSmoke(vector org)
{
static void Die(void) {
remove(self);
}
if (!m_strSpriteSmoke)
return;
entity smoke = spawn();
setmodel(smoke, m_strSpriteSmoke);
setorigin(smoke, org);
smoke.think = Die;
smoke.nextthink = time + 0.1f;
smoke.effects = EF_FLAG2;
smoke.scale = m_flSpriteScale;
}
void
func_tankmortar::SpriteFlash(vector org)
{
static void Die(void) {
remove(self);
}
if (!m_strSpriteFlash)
return;
entity smoke = spawn();
setmodel(smoke, m_strSpriteFlash);
setorigin(smoke, org);
smoke.think = Die;
smoke.nextthink = time + 0.1f;
smoke.effects = EF_FLAG2;
smoke.scale = m_flSpriteScale;
}
void
func_tankmortar::customphysics(void)
{
if (m_eDriver && m_eDriver.health <= 0)
PlayerLeave(m_eDriver);
if (m_eDriver) {
vector wantang, endang;
vector aimorg;
makevectors(m_eDriver.v_angle);
aimorg = m_eDriver.origin + v_forward * 4086;
/* lerp */
makevectors(vectoangles(aimorg - origin));
wantang = v_forward;
makevectors(angles);
endang[0] = Math_Lerp(v_forward[0], wantang[0], frametime);
endang[1] = Math_Lerp(v_forward[1], wantang[1], frametime);
endang[2] = Math_Lerp(v_forward[2], wantang[2], frametime);
angles = vectoangles(endang);
m_eDriver.flags |= FL_FROZEN;
}
}
void
func_tankmortar::PlayerInput(void)
{
if (m_flFireTime < time)
if (input_buttons & INPUT_BUTTON0) {
vector spos;
vector dir;
float dmg;
/* barrel tip offset */
makevectors(angles);
spos = origin + (v_forward * m_vecTipPos[0]);
spos += v_right * m_vecTipPos[1];
spos += v_up * m_vecTipPos[2];
/* spread */
dir = v_forward;
dir += random(-1,1) * m_vecSpread[0] * v_right;
dir += random(-1,1) * m_vecSpread[1] * v_up;
traceline(spos, spos + (dir * 4096), MOVE_NORMAL, this);
dmg = (float)m_iDamage;
Damage_Radius(trace_endpos, m_eDriver, dmg, dmg * 2.5f, TRUE, 0);
/* fx */
FX_Explosion(trace_endpos);
SpriteSmoke(spos);
SpriteFlash(spos);
CBaseTrigger::UseTargets(this, TRIG_ON);
m_flFireTime = time + m_flFireRate;
}
input_buttons &= ~INPUT_BUTTON0;
}
void
func_tankmortar::Respawn(void)
{
SetMovetype(MOVETYPE_PUSH);
SetSolid(SOLID_BSP);
SetModel(m_oldModel);
SetOrigin(m_oldOrigin);
SetAngles(m_oldAngle);
if (m_eDriver)
PlayerLeave(m_eDriver);
}
void
func_tankmortar::func_tankmortar(void)
{
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "yawrate":
m_flYawRate = stof(argv(i+1)) * 0.01f;
break;
case "yawrange":
m_flYawRange = stof(argv(i+1));
break;
case "pitchrate":
m_flPitchRate = stof(argv(i+1)) * 0.01f;
break;
case "pitchrange":
m_flPitchRange = stof(argv(i+1));
break;
case "barrel":
m_vecTipPos[0] = stof(argv(i+1));
break;
case "barrely":
m_vecTipPos[1] = stof(argv(i+1));
break;
case "barrelz":
m_vecTipPos[2] = stof(argv(i+1));
break;
case "firerate":
m_flFireRate = 1.0f / stof(argv(i+1));
break;
case "iMagnitude":
m_iDamage = stoi(argv(i+1));
break;
case "firespread":
m_vecSpread = [0.10, 0.10, 0] * stof(argv(i+1));
break;
case "persistance":
m_flPersistance = stof(argv(i+1));
break;
case "minRange":
m_flMinRange = stof(argv(i+1));
break;
case "maxRange":
m_flMaxRange = stof(argv(i+1));
break;
case "spritesmoke":
m_strSpriteSmoke = argv(i+1);
break;
case "spriteflash":
m_strSpriteFlash = argv(i+1);
break;
case "spritescale":
m_flSpriteScale = stof(argv(i+1));
break;
case "rotatesound":
m_strSndRotate = argv(i+1);
break;
default:
break;
}
}
if (m_strSpriteFlash)
precache_model(m_strSpriteFlash);
if (m_strSpriteSmoke)
precache_model(m_strSpriteSmoke);
CBaseVehicle::CBaseVehicle();
}

View File

@ -483,7 +483,6 @@ func_vehicle::Respawn(void)
SetModel(m_oldModel);
SetOrigin(m_oldOrigin);
SetAngles(m_oldAngle);
owner = m_eDriver = __NULL__;
think = Realign;
nextthink = time + 0.1f;
@ -492,6 +491,9 @@ func_vehicle::Respawn(void)
m_wlBL.velocity =
m_wlBR.velocity =
velocity = [0,0,0];
if (m_eDriver)
PlayerLeave(m_eDriver);
}
void

View File

@ -0,0 +1,39 @@
/*
* 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.
*/
/*QUAKED info_intermission (1 0 0) (-8 -8 -8) (8 8 8)
"targetname" Name
"targetname" Target entity to aim towards
An entity that's used to create an 'Intermission' camera.
Some mods use this while displaying the final scores, once a timelimit
is hit etc.
When Intermission is active, the players camera will be teleported here
and angles towards the aim target.
*/
class info_intermission:CBaseTrigger
{
void(void) info_intermission;
};
void
info_intermission::info_intermission(void)
{
CBaseTrigger::CBaseTrigger();
}

View File

@ -58,6 +58,9 @@ multi_manager::Trigger(entity act, int state)
CBaseTrigger::UseTargets(wow.m_eActivator, TRIG_TOGGLE);
}
if (GetMaster() == FALSE)
return;
m_iValue = TRUE;
/* If not multi-threaded, we have to watch out 'til all triggers are done. */

View File

@ -17,6 +17,7 @@
CLASSEXPORT(info_node, info_notnull)
CLASSEXPORT(info_target, info_notnull)
CLASSEXPORT(env_sound, info_null)
CLASSEXPORT(info_intermission, info_null)
void
env_glow(void)

View File

@ -315,7 +315,7 @@ menu_customgame_init(void)
customgame_sbMods.SetItemheight(29);
customgame_sbMods.SetHeight(289);
customgame_sbMods.SetCallback(customgame_sbmods_changed);
customgame_sbMods.SetMax(gameinfo_count-1); /* don't show our current game */
customgame_sbMods.SetMax(gameinfo_count-1);
Widget_Add(fn_customgame, customgame_sbMods);
}

View File

@ -89,6 +89,7 @@ up_toggleinstall(void)
pkgid = up_lbUpdates.GetSelected();
switch (updates[pkgid].installed) {
case "":
case "rem":
localcmd(sprintf("pkg add %s\n", updates[pkgid].name));
updates[pkgid].installed = "pending";

View File

@ -45,7 +45,7 @@ void Player_UseDown(void)
makevectors(self.v_angle);
vSource = self.origin + self.view_ofs;
traceline (vSource, vSource + (v_forward * 64), FALSE, self);
traceline (vSource, vSource + (v_forward * 64), MOVE_EVERYTHING, self);
if (trace_ent.PlayerUse) {
self.gflags &= ~GF_USE_RELEASED;

View File

@ -24,6 +24,7 @@
#include "flashlight.h"
#include "weapons.h"
#include "plugins.h"
#include "vehicles.h"
#define CLASSEXPORT(classname,classa) void classname(void) { spawnfunc_##classa(); }

View File

@ -118,12 +118,57 @@ CGameRules::IntermissionStart(void)
m_iIntermission = TRUE;
m_flIntermissionTime = time + 5.0f;
}
void
CGameRules::IntermissionCycle(void)
{
static CBaseEntity cam;
CBaseEntity targ;
if (!m_iIntermission)
return;
if (time < m_flIntermissionCycle)
return;
/* make the clients aware */
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_INTERMISSION);
cam = (CBaseEntity)find(cam, ::classname, "info_intermission");
if (cam) {
targ = (CBaseEntity)find(world, CBaseEntity::m_strTargetName, cam.m_strTarget);
if (targ) {
vector foo;
foo = vectoangles(targ.origin - cam.origin);
WriteByte(MSG_MULTICAST, 1);
WriteFloat(MSG_MULTICAST, foo[0]);
WriteFloat(MSG_MULTICAST, foo[1]);
WriteFloat(MSG_MULTICAST, foo[2]);
WriteCoord(MSG_MULTICAST, cam.origin[0]);
WriteCoord(MSG_MULTICAST, cam.origin[1]);
WriteCoord(MSG_MULTICAST, cam.origin[2]);
}
for (entity pl = world; (pl = find(pl, ::classname, "player"));) {
setorigin(pl, cam.origin);
}
} else {
WriteByte(MSG_MULTICAST, 0);
}
msg_entity = world;
multicast([0,0,0], MULTICAST_ALL);
if (!cam)
m_flIntermissionCycle = 0.0f;
else
m_flIntermissionCycle = time + 5.0f;
}
void
@ -131,6 +176,7 @@ CGameRules::IntermissionEnd(void)
{
if (!m_iIntermission)
return;
if (time < m_flIntermissionTime)
return;

View File

@ -18,6 +18,7 @@ class CGameRules
{
int m_iIntermission;
float m_flIntermissionTime;
float m_flIntermissionCycle;
void() CGameRules;
@ -45,6 +46,7 @@ class CGameRules
/* end of a game */
virtual void(void) IntermissionStart;
virtual void(void) IntermissionCycle;
virtual void(void) IntermissionEnd;
/* spectator */

View File

@ -14,5 +14,6 @@ footsteps.c
flashlight.c
vote.c
weapons.c
vehicles.c
entry.c
#endlist

View File

@ -0,0 +1,59 @@
/*
* 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.
*/
class hologram_damage:CBaseNPC
{
void(void) hologram_damage;
virtual void(void) Respawn;
};
void
hologram_damage::Respawn(void)
{
//SetRenderMode(RM_ADDITIVE);
}
void
hologram_damage::hologram_damage(void)
{
int mdltype;
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
switch (argv(i)) {
case "creaturetype":
mdltype = stoi(argv(i+1));
break;
default:
break;
}
}
switch (mdltype) {
case 1:
model = "models/tube.mdl";
break;
case 2:
model = "models/raptor.mdl";
break;
default:
model = "models/beak.mdl";
}
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
CBaseNPC::CBaseNPC();
}

View File

@ -0,0 +1,28 @@
/*
* 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.
*/
class monster_trainingbot:CBaseNPC
{
void(void) monster_trainingbot;
};
void monster_trainingbot::monster_trainingbot(void)
{
model = "models/gunmantrooper.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
CBaseNPC::CBaseNPC();
}

View File

@ -19,6 +19,15 @@
../valve/defs.h
../rewolf/gunman_cycler.cpp
../rewolf/hologram_damage.cpp
../rewolf/monster_human_bandit.cpp
../rewolf/monster_human_chopper.cpp
../rewolf/monster_human_demoman.cpp
../rewolf/monster_human_gunman.cpp
../rewolf/monster_human_unarmed.cpp
../rewolf/monster_trainingbot.cpp
../valve/player.c
../valve/spectator.c

View File

@ -21,6 +21,8 @@ HLMultiplayerRules::FrameStart(void)
if (time >= (cvar("mp_timelimit") * 60)) {
IntermissionStart();
}
IntermissionCycle();
}
void

View File

@ -35,17 +35,17 @@ Player_UseDown
*/
void Player_UseDown(void)
{
vector vecSrc;
if (self.health <= 0) {
return;
} else if (!(self.gflags & GF_USE_RELEASED)) {
return;
}
vector vSource;
makevectors(self.v_angle);
vSource = self.origin + self.view_ofs;
traceline (vSource, vSource + (v_forward * 64), FALSE, self);
vecSrc = self.origin + self.view_ofs;
traceline(vecSrc, vecSrc + (v_forward * 64), MOVE_NORMAL, self);
if (trace_ent.PlayerUse) {
self.gflags &= ~GF_USE_RELEASED;

26
src/server/vehicles.c Normal file
View File

@ -0,0 +1,26 @@
/*
* 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.
*/
void
Vehicle_Input(void)
{
player pl = (player)self;
if (pl.vehicle) {
CBaseVehicle veh = (CBaseVehicle)pl.vehicle;
veh.PlayerInput();
}
};

17
src/server/vehicles.h Normal file
View File

@ -0,0 +1,17 @@
/*
* 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.
*/
void Vehicle_Input(void);

View File

@ -33,6 +33,9 @@ class base_player
/* any mods that use hooks */
entity hook;
/* vehicle info */
entity vehicle;
#ifdef CLIENT
/* Prediction */
vector net_origin;

View File

@ -795,6 +795,11 @@ PMove_Run(void)
pl.punchangle[1] *= punch;
pl.punchangle[2] *= punch;
/* allow vehicles to prevent weapon logic from happening */
#ifdef SERVER
Vehicle_Input();
#endif
/* weapon/item logic of what the player controls */
Game_Input();
}