djcev.com

//

Git Repos / fte_dogmode / commit f4c96ea

Commit: f4c96eaf4b4fa9f434c30ffd7ebc480b01ac7e8b
Parent: 5b4a9d6f6aeb8222378215d455ccec45d498795a
Author: Cameron Vanderzanden, 2023-11-20 21:12
Committer: Cameron Vanderzanden, 2023-11-20 21:12

Commit Message

changes to movement, build environment, file reorg

Lot of changes here. Major new features include walljumping, +speed
becoming +walk when always run is on (when cl_run is 0), better
+moveup / +movedown handling, restored some support for vanilla
physics (pm_standardphysics 1), inlined some functions in
PM_WalkAccelerate, and so on.

Extended support for Quake 3 entities to include all armors (I think),
more health, most ammo types, and most weapons.

Reorganized triggers.qc and various stray triggers in other files
into individual files in the triggers/ directory. Changed indentation
and formatting of those files to match what I've been writing so far.
I plan to do the same for func_, items_, weapons_, and so on, within
reason.

This is a lot of changes so I'm sure there's something I'm forgetting
in here.

Change List

Diff .gitignore

diff --git a/.gitignore b/.gitignore
index 4ab1c40..bc1fac7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*.dat
*.lno
*.swp
+assets
qc/fteextensions.qc

Return to the top of this page or return to the overview of this repo.

Diff Makefile

diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..5f7e146
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+INSTALLDIR=/z/games/Quake/dog
+
+all:
+ make client
+ make server
+
+install:
+ make client-install
+ make server-install
+
+client:
+ cd qc/csqc && $(MAKE)
+
+client-install:
+ cp csprogs.dat $(INSTALLDIR)/csprogs.dat
+ cp csprogs.lno $(INSTALLDIR)/csprogs.lno
+
+server:
+ cd qc && $(MAKE)
+
+server-install:
+ cp progs.dat $(INSTALLDIR)/progs.dat
+ cp progs.lno $(INSTALLDIR)/progs.lno
+

Return to the top of this page or return to the overview of this repo.

Diff autoexec.cfg

diff --git a/autoexec.cfg b/autoexec.cfg
index d7796bc..e46d21f 100644
--- a/autoexec.cfg
+++ b/autoexec.cfg
@@ -1,2 +1,4 @@
+cl_run 0
pm_airstep 1
+pm_walljump 1
sv_bigcoords 1

Return to the top of this page or return to the overview of this repo.

Diff build.sh

diff --git a/build.sh b/build.sh
deleted file mode 100755
index f905f62..0000000
--- a/build.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-FTEQCC=/z/games/Quake/engines/fteqcc/fteqcc64
-SRCDIR=/z/work/cvanderz/fte_dogmode
-CLIENTQCDIR=$SRCDIR/qc/csqc
-SERVERQCDIR=$SRCDIR/qc
-
-cd $CLIENTQCDIR
-$FTEQCC -Wall -O2 csqc_progs.src
-cd $SERVERQCDIR
-$FTEQCC -Wall -O2 progs.src

Return to the top of this page or return to the overview of this repo.

Diff qc/Makefile

diff --git a/qc/Makefile b/qc/Makefile
new file mode 100644
index 0000000..6059f23
--- /dev/null
+++ b/qc/Makefile
@@ -0,0 +1,5 @@
+CC=fteqcc64
+CCOPTS=-Wall -O2
+
+all:
+ $(CC) $(CCOPTS) progs.src

Return to the top of this page or return to the overview of this repo.

Diff qc/client.qc

diff --git a/qc/client.qc b/qc/client.qc
index 605d26d..282a524 100644
--- a/qc/client.qc
+++ b/qc/client.qc
@@ -565,6 +565,14 @@ void() PlayerDeathThink =
};

//======================================================================
+// PlayerClimb -- johnfitz
+//----------------------------------------------------------------------
+void() PlayerClimb =
+{
+ self.velocity = '0 0 160';
+}
+
+//======================================================================
// PlayerJump
//----------------------------------------------------------------------
void() PlayerJump =
@@ -572,22 +580,18 @@ void() PlayerJump =
if (self.flags & FL_WATERJUMP)
return;

- if (self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_NOCLIP)
- return;
-
if (self.waterlevel >= 2)
{
- // pmove code predicts this
- // if (self.watertype == CONTENT_WATER)
- // self.velocity_z = 100;
- // else if (self.watertype == CONTENT_SLIME)
- // self.velocity_z = 80;
- // else
- // self.velocity_z = 50;
-
- if (self.swim_flag < time)
+ if (self.watertype == CONTENT_WATER)
+ self.velocity_z = 100;
+ else if (self.watertype == CONTENT_SLIME)
+ self.velocity_z = 80;
+ else
+ self.velocity_z = 50;
+
+ // play swiming sound
+ if (self.swim_flag < time)
{
- // play swimming sound
self.swim_flag = time + 1;
if (random() < 0.5)
sound (self, CHAN_BODY, "misc/water1.wav",
@@ -596,32 +600,29 @@ void() PlayerJump =
sound (self, CHAN_BODY, "misc/water2.wav",
1, ATTN_NORM);
}
-
- return;
- }
-
- if (!(self.flags & FL_ONGROUND))
- {
- dprint ("PlayerJump: player is not on ground, returning\n");
return;
}

- if (!(self.flags & FL_JUMPRELEASED))
+ // refactoring from Copper -- dumptruck_ds
+ if (self.movetype != MOVETYPE_NOCLIP)
{
+ if (!(self.flags & FL_ONGROUND))
+ return;
// don't pogo stick
- dprint ("PlayerJump: player is holding jump, returning\n");
- return;
+ if ( !(self.flags & FL_JUMPRELEASED) )
+ return;
+ // player jumping sound (h00rt)
+ sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
}

- self.flags &= ~FL_JUMPRELEASED;
- // self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
+ self.flags = self.flags - (self.flags & FL_JUMPRELEASED);

- // don't stairwalk (not yet anyway)
- self.flags &= ~FL_ONGROUND;
+ // don't stairwalk
+ self.flags = self.flags - FL_ONGROUND;

self.button2 = 0;
- // player jumping sound
- sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
+ // sound (self, CHAN_AUTO, "player/plyrjmp8.wav", 1, ATTN_NORM);
+ self.velocity_z = self.velocity_z + 270;
};

//======================================================================
@@ -725,11 +726,52 @@ void() WaterMove =
};

//======================================================================
+// CheckWaterJump
+//----------------------------------------------------------------------
+void() CheckWaterJump =
+{
+ // from Copper -- dumptruck_ds
+ if (self.movetype == MOVETYPE_NOCLIP)
+ return;
+
+ local vector start, end;
+
+ // check for a jump-out-of-water
+ makevectors (self.angles);
+ start = self.origin;
+ start_z = start_z + 8;
+ v_forward_z = 0;
+ normalize (v_forward);
+ end = start + v_forward * 24;
+ traceline (start, end, TRUE, self);
+ if (trace_fraction < 1)
+ {
+ // solid at waist
+ start_z = start_z + self.maxs_z - 8;
+ end = start + v_forward * 24;
+ self.movedir = trace_plane_normal * -50;
+ traceline (start, end, TRUE, self);
+ if (trace_fraction == 1)
+ {
+ // open at eye level
+ self.flags = self.flags | FL_WATERJUMP;
+ self.velocity_z = 225;
+ self.flags -= self.flags & FL_JUMPRELEASED;
+ // safety net
+ self.teleport_time = time + 2; // safety net
+ return;
+ }
+ }
+};
+
+//======================================================================
// PlayerPreThink
// Called every frame before physics are run
//======================================================================
void() PlayerPreThink =
{
+ local float do_ladder_physics = FALSE;
+
if (intermission_running)
{
// otherwise a button could be missed between the think tics
@@ -745,7 +787,29 @@ void() PlayerPreThink =
return;
}

- self.gravity = self.wantedgravity;
+ // note that this code block is here, before the tests which check
+ // whether the player is dead, so that the player's gravity will be
+ // correctly updated even if they e.g. fell off a ladder because
+ // they died -- iw
+ if (autocvar(pm_standardphysics, FALSE))
+ {
+ if (self.pmove_flags & PMF_ONLADDER)
+ {
+ do_ladder_physics = TRUE;
+ // not zero, because zero means "default"
+ self.gravity = 0.0000001;
+ self.pmove_flags &= ~PMF_ONLADDER;
+ }
+ else
+ {
+ do_ladder_physics = FALSE;
+ self.gravity = self.wantedgravity;
+ }
+ }
+ else
+ {
+ self.gravity = self.wantedgravity;
+ }

// If just spawned in, try to recover previous fog values from
// own client entity, if any
@@ -758,6 +822,11 @@ void() PlayerPreThink =
CheckRules ();
WaterMove ();

+ // Run legacy CheckWaterJump if we're doing standard physics -- CEV
+ if (autocvar(pm_standardphysics, FALSE))
+ if (self.waterlevel == 2)
+ CheckWaterJump ();
+
if (self.deadflag >= DEAD_DEAD)
{
PlayerDeathThink ();
@@ -769,30 +838,49 @@ void() PlayerPreThink =
return;

// johnfitz ladder conditions, added from Rubicon2 -- dumptruck_ds
- /* TODO CEV
- if (do_ladder_physics)
+ if (autocvar(pm_standardphysics, FALSE))
{
- if (self.button2)
+ if (do_ladder_physics)
{
- // no ladder footsteps for now
- if (time > self.ladder_step_finished)
+ if (self.button2)
{
- r = random();
- if (r > 0.66)
- sound (self, CHAN_BODY, "ladder/metal1.wav", 0.5, ATTN_NORM);
- else if (r > 0.33)
- sound (self, CHAN_BODY, "ladder/metal2.wav", 0.5, ATTN_NORM);
- else
- sound (self, CHAN_BODY, "ladder/metal3.wav", 0.5, ATTN_NORM);
- self.ladder_step_finished = time + 0.3;
+ PlayerClimb ();
+ /*
+ // no ladder footsteps for now
+ if (time > self.ladder_step_finished)
+ {
+ r = random();
+ if (r > 0.66)
+ sound (self, CHAN_BODY,
+ "ladder/metal1.wav",
+ 0.5, ATTN_NORM);
+ else if (r > 0.33)
+ sound (self, CHAN_BODY,
+ "ladder/metal2.wav",
+ 0.5, ATTN_NORM);
+ else
+ sound (self, CHAN_BODY,
+ "ladder/metal3.wav",
+ 0.5, ATTN_NORM);
+ self.ladder_step_finished = time + 0.3;
+ }
+ */
+ }
+ else
+ {
+ self.flags = self.flags | FL_JUMPRELEASED;
+ self.velocity = 0.9 * self.velocity;
+ self.velocity_z = 0;
}
}
else
{
- self.flags = self.flags | FL_JUMPRELEASED;
+ if (self.button2)
+ PlayerJump ();
+ else
+ self.flags = self.flags | FL_JUMPRELEASED;
}
}
- */

// teleporters can force a non-moving pause time
if (time < self.pausetime)
@@ -806,9 +894,12 @@ void() PlayerPreThink =
}

// from copper -- dumptruck_ds
- if (self.movetype == MOVETYPE_NOCLIP)
+ if (autocvar(pm_standardphysics, FALSE))
{
- self.flags = self.flags | FL_FLY;
+ if (self.movetype == MOVETYPE_NOCLIP)
+ {
+ self.flags = self.flags | FL_FLY;
+ }
}

// TODO CEV
@@ -977,12 +1068,6 @@ void() CheckPowerups =
//======================================================================
void() PlayerPostThink =
{
- // from Copper -- dumptruck_ds
- if (self.movetype != MOVETYPE_NOCLIP)
- {
- self.flags = not(self.flags, FL_FLY);
- }
-
// TODO CEV
self.SendFlags = 0xffffff;

@@ -1033,6 +1118,12 @@ void() PlayerPostThink =
}

CheckPowerups ();
+
+ // from Copper -- dumptruck_ds
+ if (autocvar(pm_standardphysics, FALSE))
+ if (self.movetype != MOVETYPE_NOCLIP)
+ // self.flags = not(self.flags, FL_FLY);
+ self.flags &= ~FL_FLY;
};

//======================================================================

Return to the top of this page or return to the overview of this repo.

Diff qc/compat_quake3.qc

diff --git a/qc/compat_quake3.qc b/qc/compat_quake3.qc
index 67f6035..05b38d3 100644
--- a/qc/compat_quake3.qc
+++ b/qc/compat_quake3.qc
@@ -2,40 +2,113 @@
// Quake 3 compatibility entrypoints / functions
//==============================================================================

+void() item_armor1;
void() item_armor2;
void() item_armorInv;
+void() item_cells;
+void() item_health;
void() item_health_vial;
+void() item_rockets;
+void() item_shells;
+void() item_spikes;
+void() weapon_supernailgun;
void() info_teleport_destination;

//======================================================================
// Quake 3 armor item support -- CEV
//----------------------------------------------------------------------

+// Green Armor -- CEV
+//----------------------------------------------------------------------
+void() spawnfunc_item_armor_jacket =
+{
+ self.classname = "item_armor1";
+ item_armor1 ();
+};
+
// Yellow Armor -- CEV
-void() item_armor_combat =
+//----------------------------------------------------------------------
+void() spawnfunc_item_armor_combat =
{
- item_armor2();
+ self.classname = "item_armor2";
+ item_armor2 ();
};

// Red Armor -- CEV
-void() item_armor_body =
+//----------------------------------------------------------------------
+void() spawnfunc_item_armor_body =
{
- item_armorInv();
+ self.classname = "item_armorInv";
+ item_armorInv ();
};

//======================================================================
// Quake 3 health item support -- CEV
//----------------------------------------------------------------------

-void() item_health_small =
+//----------------------------------------------------------------------
+void() spawnfunc_item_health_mega =
+{
+ self.classname = "item_health";
+ self.spawnflags |= 2;
+ item_health ();
+};
+
+//----------------------------------------------------------------------
+void() spawnfunc_item_health_small =
{
+ self.classname = "item_health_vial";
item_health_vial ();
};

//======================================================================
+// Quake 3 ammo & weapons -- CEV
+//----------------------------------------------------------------------
+void() spawnfunc_ammo_cells =
+{
+ self.classname = "item_spikes";
+ item_spikes ();
+};
+
+//----------------------------------------------------------------------
+void() spawnfunc_ammo_grenades =
+{
+ self.classname = "item_rockets";
+ item_rockets ();
+};
+
+//----------------------------------------------------------------------
+void() spawnfunc_ammo_lightning =
+{
+ self.classname = "item_cells";
+ item_cells ();
+};
+
+//----------------------------------------------------------------------
+void() spawnfunc_ammo_rockets =
+{
+ self.classname = "item_rockets";
+ item_rockets ();
+};
+
+//----------------------------------------------------------------------
+void() spawnfunc_ammo_shells =
+{
+ self.classname = "item_shells";
+ item_shells ();
+};
+
+//----------------------------------------------------------------------
+void() weapon_plasmagun =
+{
+ self.classname = "weapon_supernailgun";
+ weapon_supernailgun ();
+};
+
+//======================================================================
// Quake 3 push target entities -- CEV
//----------------------------------------------------------------------
-void() target_push =
+void() spawnfunc_target_push =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit ())
@@ -50,27 +123,31 @@ void() target_push =
};

//----------------------------------------------------------------------
-void() target_position =
+void() spawnfunc_target_position =
{
- target_push ();
+ self.classname = "target_push";
+ spawnfunc_target_push ();
};

//======================================================================
// Quake 3 Teleporter targets -- CEV
//----------------------------------------------------------------------
-void() misc_teleporter_dest =
+void() spawnfunc_misc_teleporter_dest =
{
+ self.classname = "info_teleport_destination";
info_teleport_destination ();
};

//----------------------------------------------------------------------
-void() misc_teleporter_destination =
+void() spawnfunc_misc_teleporter_destination =
{
+ self.classname = "info_teleport_destination";
info_teleport_destination ();
};

//----------------------------------------------------------------------
-void() target_teleporter =
+void() spawnfunc_target_teleporter =
{
+ self.classname = "info_teleport_destination";
info_teleport_destination ();
};

Return to the top of this page or return to the overview of this repo.

Diff qc/csqc/Makefile

diff --git a/qc/csqc/Makefile b/qc/csqc/Makefile
new file mode 100644
index 0000000..28788fc
--- /dev/null
+++ b/qc/csqc/Makefile
@@ -0,0 +1,5 @@
+CC=fteqcc64
+CCOPTS=-Wall -O2
+
+all:
+ $(CC) $(CCOPTS) csqc_progs.src

Return to the top of this page or return to the overview of this repo.

Diff qc/csqc/csqc_entrypoints.qc

diff --git a/qc/csqc/csqc_entrypoints.qc b/qc/csqc/csqc_entrypoints.qc
index f6d838e..02fa6e9 100644
--- a/qc/csqc/csqc_entrypoints.qc
+++ b/qc/csqc/csqc_entrypoints.qc
@@ -184,7 +184,7 @@ float CSQC_Parse_TempEntity()
handled = FALSE;
teid = ReadByte ();

- switch(teid)
+ switch (teid)
{
case 6:
eid = readentitynum ();
@@ -196,7 +196,7 @@ float CSQC_Parse_TempEntity()
end_z = ReadCoord ();
// pointparticles (
// particleeffectnum("TE_LIGHTNING2"),
- // pos, end, 1);
+ // pos, end, 1);
if (player_local)
te_lightning2 (player_local, pos, end);
else

Return to the top of this page or return to the overview of this repo.

Diff qc/defs_builtins.qc

diff --git a/qc/defs_builtins.qc b/qc/defs_builtins.qc
index 26958d2..c961148 100644
--- a/qc/defs_builtins.qc
+++ b/qc/defs_builtins.qc
@@ -97,6 +97,9 @@ float(float angle) cos = #61;
// Part of DP_QC_SINCOSSQRTPOW
float(float value) sqrt = #62;

+// Part of DP_QC_ETOS
+string(entity ent) etos = #65;
+
void(float step) movetogoal = #67;
string(string s) precache_file = #68; // no effect except for -copy
void(entity e) makestatic = #69;

Return to the top of this page or return to the overview of this repo.

Diff qc/defs_misc.qc

diff --git a/qc/defs_misc.qc b/qc/defs_misc.qc
index f6d10c7..0ae68d9 100644
--- a/qc/defs_misc.qc
+++ b/qc/defs_misc.qc
@@ -514,8 +514,6 @@ void() SUB_UsePain; // dumptruck_ds
.float keep_ammo; // dumptruck_ds
.float berserk; // dumptruck_ds
nosave float *world_sounds; // via Spike fun times! nosave=noclobber
-void() trigger_changemusic; // dumptruck_ds
-void() onlookat_touch; // dumptruck_ds

// Drake Cutscenes -- Borrowed from Zerstorer.
.string script; // dhm - denotes which script to read.
@@ -533,15 +531,6 @@ float mindex_inviso; // Invisible (null sprite)
.string null_string; // Replace 'string_null' with
// 'world.null_string'. null string,
// nothing should be held here.
-// from Custents
-// variable for healing trigger
-.float heal_timer;
-.float heal_amount;
-.float health_max;
-// Constants for the healing trigger
-float HEAL_START_ON = 1;
-float HEAL_PLAYER_ONLY = 2;
-float HEAL_MONSTER_ONLY = 4;

// Custom Monster Sounds START -- dumptruck_ds
.string snd_death;
@@ -604,14 +593,6 @@ nosave float gamestarted;
.float last_setstate_frame = light_lev;
.entity last_setstate = aiment;

-// 1998-07-03 hurt_touch fix by Robert Field start
-//
-// triggers.qc
-//
-.float hurt_together_time;
-.float hurt_nextthink;
-// 1998-07-03 hurt_touch fix by Robert Field end
-
float I_AM_TURRET = 262144; // dumptruck_ds
.void() th_turret;

@@ -677,7 +658,3 @@ void(entity client, float density, vector color) csf_set;
// of the SendEntity method.
.float SendFlags;
#endif
-
-// TESTING TODO CEV
-.float light_level;
-

Return to the top of this page or return to the overview of this repo.

Diff qc/hip_rotate.qc

diff --git a/qc/hip_rotate.qc b/qc/hip_rotate.qc
index 2f74ff9..b3e73be 100644
--- a/qc/hip_rotate.qc
+++ b/qc/hip_rotate.qc
@@ -223,20 +223,6 @@ void() LinkRotateTargets =
}
};

-void( entity ent, float amount ) hurt_setdamage =
- {
- ent.dmg = amount;
- if ( !amount )
- {
- ent.solid = SOLID_NOT;
- }
- else
- {
- ent.solid = SOLID_TRIGGER;
- }
- ent.nextthink = -1;
- };
-
void( float amount ) SetDamageOnTargets =
{
local entity ent;

Return to the top of this page or return to the overview of this repo.

Diff qc/hip_trig.qc

diff --git a/qc/hip_trig.qc b/qc/hip_trig.qc
deleted file mode 100644
index f8a3dec..0000000
--- a/qc/hip_trig.qc
+++ /dev/null
@@ -1,238 +0,0 @@
-//Selections from hiptrig.qc NOT the entire file
-
-/* Trigger QuickC program
- By Jim Dose' 12/2/96
- Copyright (c)1996 Hipnotic Interactive, Inc.
- All rights reserved.
- Do not distribute.
-*/
-
-float USE_SILV_KEY = 8;
-float USE_GOLD_KEY = 16;
-
-/*
-================
-keytrigger_unlock
-
-Perform the actions which should be performed when self is successfully
-unlocked with a key.
-
-This function exists so that it can be passed as an argument to the new
-keylock_try_to_unlock function. This code was previously part of the
-keytrigger_use function. -- iw
-================
-*/
-void() keytrigger_unlock =
-{
- // we can't just remove (self) here, because this is a touch function
- // called while C code is looping through area links...
- self.touch = SUB_Null;
- self.use = SUB_Null;
- self.nextthink = time + 0.1;
- self.think = SUB_Remove;
- self.message = "";
-
- SUB_UseTargets();
-};
-
-void() keytrigger_use =
-{
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
- if (self.attack_finished > time)
- return;
-
- self.attack_finished = time + 2;
- keylock_try_to_unlock (activator, self.message, keytrigger_unlock);
-};
-
-void() keytrigger_touch =
-{
- activator = other;
- keytrigger_use();
-};
-
-/*QUAKED trigger_usekey (0 .5 0) ? X X X USE_SILV_KEY USE_GOLD_KEY X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-
-Variable sized single use trigger that requires a key to trigger targets. Must be targeted at one or more entities.
-
-"cnt" if 1, leave a used key in the player's inventory (0 default).
-"keyname" if set, this is the keyname of the item_key_custom which unlocks this entity.
-"message" is printed when the trigger is touched without having the right key.
-"noise1" sound file for the "key required" sound (default is per worldtype).
-"noise2" sound file for the "key used" sound (default is per worldtype).
-*/
-
-void() trigger_usekey =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
-// the keylock_* functions use self.noise3 and self.noise4 internally,
-// but trigger_usekey doesn't use the self.noise1 or self.noise2 fields
-// for anything, so we allow the mapper to specify custom sound files by
-// setting self.noise1 and self.noise2, but we move those values into
-// self.noise3 and self.noise4 -- iw
- self.noise3 = self.noise1;
- self.noise4 = self.noise2;
- self.noise1 = "";
- self.noise2 = "";
-
- keylock_init ();
-
- if (self.spawnflags & USE_SILV_KEY) {//dumptruck_ds
- keylock_set_silver_key ();
-
- if (self.keyname != "") {
- self.netname = self.keyname;
- self.keyname = "";
- }
- }
- if (self.spawnflags & USE_GOLD_KEY) {//dumptruck_ds
- keylock_set_gold_key ();
-
- if (self.keyname != "") {
- self.netname = self.keyname;
- self.keyname = "";
- }
- }
-
-// support for item_key_custom -- iw
- if (self.keyname != "")
- {
- keylock_set_custom_key (self.keyname);
- self.keyname = ""; // this should not be referenced again
- }
-
- if (!keylock_has_key_set ())
- {
- objerror ("no key specified!");
- return;
- }
-
- self.use = keytrigger_use;
- self.touch = keytrigger_touch;
-
- InitTrigger ();
- SUB_CheckWaiting();
-};
-
-// void() remove_touch =
-// {
-// if (other.flags & self.cnt)
-// return;
-// other.touch = SUB_Null;
-// other.model = "";
-// remove(self);
-// };
-//
-// /*QUAKED trigger_remove (.5 .5 .5) ? ignoremonsters ignoreplayers
-// Variable sized trigger that removes the thing
-// that touches it. Does not affect monsters or
-// players.
-// */
-// void() trigger_remove =
-// {
-// if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
-// return;
-//
-// self.cnt = FL_CLIENT|FL_MONSTER;
-// if (self.spawnflags & 1)
-// self.cnt = self.cnt - FL_MONSTER;
-// if (self.spawnflags & 2)
-// self.cnt = self.cnt - FL_CLIENT;
-// InitTrigger ();
-// self.touch = remove_touch;
-// };
-
-/*
-==============================================================================
-
-trigger_setgravity
-
-==============================================================================
-*/
-float DT_GRAVTOFF = 8; // trigger will start off
-
-void() grav_toggle = //dumptruck_ds based on hipnotic blocker_use
-{
- if (self.estate != STATE_ACTIVE)
- self.estate = STATE_ACTIVE;
- else
- self.estate = STATE_INACTIVE;
-
-};
-
-void() trigger_gravity_touch =
-{
- // from Copper -- dumptruck_ds
- // if (!CheckValidTouch()) return;
-
- if (self.estate != STATE_ACTIVE) return;
-
- local float grav;
-
-// This is commented out so that the changing gravity will
-// affect everything, if you don't want to use all affecting
-// gravity changes, then uncomment these two lines.
-// if (other.classname != "player")
-// return;
-
- if (self.gravity == -1)
- grav = 1;
- else
- grav = self.gravity;
-
- // the player's gravity is now managed in PlayerPreThink(), however
- // other entities don't have special gravity management, so their
- // gravity is still set directly -- iw
- if (other.classname == "player")
- other.wantedgravity = grav;
- else
- other.gravity = grav;
-};
-
-/*QUAKED trigger_setgravity (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-set the gravity of a player
-
-"gravity" what to set the players gravity to
- - 0 (default) normal gravity
- - 1 no gravity
- - 2 almost no gravity
- - 10 is a good setting
- - ...
- - 101 normal gravity
- - 102 slightly higher gravity
- - ...
- - 1000 very high gravity
-
- NOTE: the amount of gravity can only be changed by touching another
- trigger_setgravity with a different setting. The gravity key defaults to 0
- which is normal gravity. Lower numbers (e.g. 25) equal lower gravity. Setting
- 100 is normal gravity. Numbers above 100 will make the player “heavier”, i.e.
- harder to jump. If you want multiple trigger setgravity triggers in one room or
- area, make sure the brushes are not touching each other. This can cause the
- triggers not to work properly.
-
-*/
-void() trigger_setgravity =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- InitTrigger ();
-
- self.use = grav_toggle; // dumptruck_ds
- self.touch = trigger_gravity_touch;
-
- if ( self.spawnflags & DT_GRAVTOFF ) //dumptruck_ds
- self.estate = STATE_INACTIVE;
-
- if (!self.gravity)
- self.gravity = -1;
- else
- self.gravity = ((self.gravity - 1) / 100);
-
- SUB_CheckWaiting();
-};

Return to the top of this page or return to the overview of this repo.

Diff qc/intermission.qc

diff --git a/qc/intermission.qc b/qc/intermission.qc
index 33b8565..89fb64f 100644
--- a/qc/intermission.qc
+++ b/qc/intermission.qc
@@ -263,136 +263,3 @@ void() IntermissionThink =

ExitIntermission ();
};
-
-void() execute_changelevel =
-{
- used_exit = self;
- local entity pos;
-
- intermission_running = 1;
-
-// enforce a wait time before allowing changelevel
- if (deathmatch)
- intermission_exittime = time + 5;
- else
- intermission_exittime = time + 2;
-
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 3);
- WriteByte (MSG_ALL, 3);
-
- pos = FindIntermission ();
-
- other = find (world, classname, "player");
- while (other != world)
- {
- other.view_ofs = '0 0 0';
- other.angles = other.v_angle = pos.mangle;
- other.fixangle = TRUE; // turn this way immediately
- other.nextthink = time + 0.5;
- other.takedamage = DAMAGE_NO;
- other.solid = SOLID_NOT;
- other.movetype = MOVETYPE_NONE;
- other.modelindex = 0;
- setorigin (other, pos.origin);
- other = find (other, classname, "player");
- fog_setFromEnt(other, pos);
- }
- // Drake -- dumptruck_ds
- if (cutscene)
- { // If player was in a cutscene when the level ended, restore viewsize.
- pos = find (world, classname, "camera");
- if (pos)
- {
- local string val;
-
- val = ftos (pos.cnt);
- cvar_set ("viewsize", val);
- }
- }
-
- WriteByte (MSG_ALL, SVC_INTERMISSION);
-};
-
-
-void() changelevel_touch =
-{
- if (self.estate != STATE_ACTIVE) return;
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
- if ((cvar("noexit") == 1) || ((cvar("noexit") == 2) && (mapname != "start")))
- {
- T_Damage (other, self, self, 50000);
- return;
- }
-
- if (coop || deathmatch)
- {
- bprint (other.netname);
- bprint (" exited the level\n");
- }
-
- nextmap = self.map;
-
- SUB_UseTargets ();
- if ( (self.spawnflags & 16) && (deathmatch == 0) ) //use info_player_start2 -- dumptruck_ds
- {
- sigil_touch2();
- }
-
- if ( (self.spawnflags & 1) && (deathmatch == 0) )
- { // NO_INTERMISSION
- GotoNextMap();
- return;
- }
-
-
- self.touch = SUB_Null;
-
-// we can't move people right now, because touch functions are called
-// in the middle of C movement code, so set a think time to do it
- self.think = execute_changelevel;
- self.nextthink = time + 0.1;
-};
-
-void() dt_exit_toggle = //dumptruck_ds based on hipnotic blocker_use
-{
- if (self.estate != STATE_ACTIVE)
- {
- self.is_waiting = 0;
- self.estate = STATE_ACTIVE;
- }
- else
- {
- self.is_waiting = 1;
- self.estate = STATE_INACTIVE;
- }
-};
-
-
-float DT_EXITOFF = 8;
-/*QUAKED trigger_changelevel (0.5 0.5 0.5) ? NO_INTERMISSION X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-
-When the player touches this, he gets sent to the map listed in the "map" variable. Unless the NO_INTERMISSION flag is set, the view will go to the info_intermission spot and display stats.
-*/
-void() trigger_changelevel =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (self.spawnflags & DT_EXITOFF) //dumptruck_ds
- {
- self.is_waiting = 1;
- }
- SUB_CheckWaiting();
-
- self.use = dt_exit_toggle;
- if (!self.map)
- objerror ("changelevel trigger doesn't have map");
-
-
- InitTrigger ();
- self.flags = self.flags | FL_NOCENTERPRINT;
- self.touch = changelevel_touch;
-};

Return to the top of this page or return to the overview of this repo.

Diff qc/plats.qc

diff --git a/qc/plats.qc b/qc/plats.qc
index 022041b..650c375 100644
--- a/qc/plats.qc
+++ b/qc/plats.qc
@@ -348,7 +348,7 @@ void() train_next = {
destang = displ = '0 0 0';

targ = find(world, targetname, self.target);
-
+
if (!targ || self.target == "")
objerror("train_next: no next target");

Return to the top of this page or return to the overview of this repo.

Diff qc/pmove.qc

diff --git a/qc/pmove.qc b/qc/pmove.qc
index 7743253..83d3953 100644
--- a/qc/pmove.qc
+++ b/qc/pmove.qc
@@ -3,13 +3,11 @@
//==============================================================================

// TODO CEV: crouching
-// TODO CEV: re-implement PM_WallJump
-// TODO CEV: try again to simplify the makevectors setup?

-// globals managed by FTEQW
+// globals managed by FTEQW, from fteextensions.qc -- CEV
float input_buttons;
// float input_impulse;
-float input_timelength; // from fteextensions.qc -- CEV
+float input_timelength;
vector input_angles; // +x = DOWN
vector input_movevalues;

@@ -23,54 +21,64 @@ vector input_movevalues;
.float groundboost_timer; // time to apply low friction -- CEV
.void() customphysics;

-// pmove constants
-// It's definitely possible to rework these as cvars -- CEV
-const float PM_AIRACCEL = 7.5f; // 10 in Q1; now 8
-const float PM_AIRACCELQ3 = 0.75f; // 1.0 in Q3 ?; now 0.8
+// pmove constants; it's defnitely possible to rework these as cvars -- CEV
+// acceleration & friction
+const float PM_AIRACCEL = 7.5f; // 10 in Q1; now 7.5
+const float PM_AIRACCELQ3 = 0.75f; // 1.0 in Q3 ?; now 0.75
const float PM_AIRACCELFWD = 1.5f; // 1 feels close to Q3 / CPM
const float PM_AIRACCELBACK = 5.0f; // Air stop speed in Q3?
const float PM_AIRACCELTURN = 100.0f; // affects +fwd style turning radius
-const float PM_BOOSTACCEL = 12.0f; // 12 is fast, 10 is enough
-const float PM_BOOSTFRICTION = 4.0f; // Q1 friction (4) is plenty low
+const float PM_BOOSTACCEL = 12.0f; // ground boost accel; 10 is enough
+const float PM_BOOSTFRICTION = 4.0f; // ground boost friction; 4 is Q1
const float PM_GROUNDACCEL = 15.0f; // 10 is normal, 15 is CPM
const float PM_GROUNDFRICTION = 8.0f; // 4 for Q1, 6 for Q3, 8 for CPM
const vector PM_GROUNDDIST_V = '0 0 1'; // distance for ground check
-const float PM_GRAVITY = 800.0f; // unless sv_gravity, scaled by .gravity
-const float PM_OVERCLIP = 1.0f; // Quake3's OVERCLIP is 1.001f
-const float PM_STEPHEIGHT = 18.0f; // 18 for Q1, 22 for later games?
-const vector PM_WALLDIST_V = '0 0 40'; // min. distance from ground for wj
const float PM_WATERACCEL = 10.0f; // water acceleration
const float PM_WATERFRICTION = 4.0f; // friction in water

-const float PM_JUMPSPEED = 270.0f; // standard jump Z velocity; 90 * 3
-const float PM_DOUBLEJUMPSPEED = 360.0f;// 270 * 1.5 in CPM?; 360 = 90 * 4
-const float PM_TELEJUMPSPEED = 360.0f; // same as DOUBLEJUMPSPEED
-const float PM_WALLJUMPFORCE = 90.0f; // amount of push away from wall
-const float PM_WALLJUMPSPEED = 270.0f; // upward vel for walljumps
+// horizontal speeds (mostly)
+const float PM_CROUCHSPEED = 120.0f; // ???
const float PM_MAXSPEED = 320.0f; // 320 always
const float PM_MAXAIRSPEED = 30.0f; // 30 for Q1 air control
+const float PM_RUNSPEED = 400.0f; // run speed override
const float PM_STOPSPEED = 100.0f;
+const float PM_TELEEXITSPEED = 400.0f; // exit teleporters at this speed
+const float PM_WALKSPEED = 200.0f; // walk speed override
const float PM_WATERMAXSPEED = 224.0f; // 320 * 0.7
const float PM_WATERSINKSPEED = 60.0f;

+// vertical speeds (mostly)
+const float PM_GRAVITY = 800.0f; // unless sv_gravity, scaled by .gravity
+const float PM_JUMPSPEED = 270.0f; // standard jump Z velocity; 90 * 3
+const float PM_DOUBLEJUMPSPEED = 360.0f;// 270 * 1.5 in CPM; 360 here
+const float PM_STAIRJUMPSPEED = 360.0f; // 360 = 90 * 4
+const float PM_TELEJUMPSPEED = 360.0f; // same as STAIRJUMPSPEED
+const float PM_WALLJUMPFORCE = 90.0f; // 90 * 2; push away from wall
+const float PM_WALLJUMPLIMIT = -180.f; // no walljump if Z vel below this
+const float PM_WALLJUMPSPEED = 270.0f; // 225 = 90 * 2.5; wall jump
+const float PM_WALLJUMPDOUBLE = 360.0f; // 315 = 90 * 3.5; wall doublejump
+
+// timing
const float PM_DOUBLEJUMP_WINDOW = 0.4f;// 2 jumps in this time is a double
const float PM_GROUNDBOOST_WINDOW = 0.4f;// groundboost duration
const float PM_TELEJUMP_WINDOW = 0.4f; // duration to perform a telejump
-const float PM_WALLJUMP_WINDOW = 0.2f; // duration between walljumps
+const float PM_WALLJUMP_WINDOW = 0.25f; // duration between walljumps
const float PM_WALLCLIP_WINDOW = 0.25f; //

+// misc
+const float PM_OVERCLIP = 1.0f; // Quake3's OVERCLIP is 1.001f
+const float PM_STEPHEIGHT = 18.0f; // 18 for Q1, 22 for later games?
const vector PM_TELEDROP = '0 0 -64'; // drop teleporter exit to floor if
// floor is within this distance
-const float PM_TELEEXITSPEED = 400.0f; // exit teleporters at this speed
-
// water level
const int WATERLEVEL_NONE = 0;
const int WATERLEVEL_FEET = 1;
const int WATERLEVEL_WAIST = 2;
const int WATERLEVEL_EYES = 3;

-// from Nexuiz; less precise than theirs, but this should be fine. -- CEV
-const float RAD2DEG = 57.295779;
+//
+const vector CROUCHED_MINS = '-16 -16 -18';// VEC_HULL_MIN is '-16 -16 -24'
+const vector CROUCHED_MAXS = '16 16 18';// VEC_HULL_MAX is '16 16 32'

// pmove_flags
enumflags
@@ -79,10 +87,13 @@ enumflags
PMF_STARTGROUND, // entity started the move on ground
PMF_ONLADDER, // entity is on a ladder
PMF_INWATER, // entity is in water
+ PMF_CROUCH_HELD, // player is holding the crouch key
+ PMF_CROUCHED, // entity is crouching
PMF_JUMP_HELD, // player is holding the jump key
PMF_DOUBLEJUMPED, // entity has doublejumped
- PMF_WALLJUMP, // entity has walljumped
- PMF_WATERJUMP // entity has waterjumped
+ PMF_WALLJUMPED, // entity has walljumped
+ PMF_WATERJUMPED, // entity has waterjumped
+ PMF_PRE_MOVE // hint that origin hasn't updated yet
};

// prototypes
@@ -96,13 +107,29 @@ void(vector wishvel, float wishspeed, float accel, float move_time)
PM_AirAccelerate;
void(vector wishdir, float wishspeed, float move_time) PM_AirControl;
void() PM_Jump;
-// TODO CEV void(vector checkdir) PM_WallJump;
-void(float premove, float move_time) PM_WalkAccelerate;
-void(float move_time) PM_SwimAccelerate;
-void(float scale, float move_time) PM_NoClipAccelerate;
+void() PM_WallJump;
+void(vector wishvel, float move_time) PM_WalkAccelerate;
+void(vector wishvel, float move_time) PM_SwimAccelerate;
+void(vector wishvel, float scale, float move_time) PM_NoClipAccelerate;
void(float move_time) PM_ManageTimers;
void(entity target) PM_Move;

+#ifdef SSQC
+//======================================================================
+// SV_RunClientCommand -- server-side movement entrypoint -- CEV
+//----------------------------------------------------------------------
+void() SV_RunClientCommand =
+{
+ // should match the one used by csqc.
+ if (autocvar(pm_standardphysics, FALSE))
+ // for testing -- CEV
+ runstandardplayerphysics (self);
+ else
+ // for real
+ PM_Move (self);
+};
+#endif
+
//======================================================================
// PM_Nudge
// from the GPL2 CSQCTest code that comes with FTEQW; is called often
@@ -257,7 +284,7 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
// but this solves more interactions (ztndm3) -- CEV
local float roof_fraction = trace_fraction;
local vector roof_plane = trace_plane_normal;
-
+
// second: move forward
stepsize = trace_endpos_z - self.origin_z;
end = trace_endpos + (self.velocity * time_left);
@@ -265,8 +292,16 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
tracebox (trace_endpos, self.mins, self.maxs, end,
FALSE, self);

+ // save trace_ent if it has a touch function
+ if (trace_ent && trace_ent.touch != __NULL__)
+ touched_ent = trace_ent;
+
if (trace_fraction >= 1.0f)
{
+ // storing another vector, disappointed in
+ // myself -- CEV
+ local vector fwd_plane = trace_plane_normal;
+
// forward move didn't hit anything
// third: move down
end = trace_endpos;
@@ -278,21 +313,30 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
trace_plane_normal_z > 0.7f)
{
// good ground, accept the move
- if (roof_fraction < 1.0f)
+ if (roof_fraction < 1.0f &&
+ roof_plane != fwd_plane &&
+ roof_plane != plane)
{
- // we hit the ceiling, store
- // its plane as prev_plane so
- // we'll clip to it below -- CEV
- prev_plane2 = plane;
- prev_plane = roof_plane;
+ // do a simple clipvel to the
+ // roof plane right now -- CEV
+ self.velocity -= roof_plane *
+ (self.velocity *
+ roof_plane);
}

stepsize = trace_endpos_z -
self.origin_z;
self.origin = trace_endpos;
time_left -= time_left * trace_fraction;
+
+ prev_plane2 = __NULL__;
+ prev_plane = fwd_plane;
plane = trace_plane_normal;
- touched_ent = trace_ent;
+
+ if (trace_ent &&
+ trace_ent.touch != __NULL__)
+ touched_ent = trace_ent;
+
// don't attempt to step again
dostep = FALSE;
}
@@ -304,44 +348,40 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
stepsize = 0;
}
}
- else if (trace_plane_normal_z == 0)
+ else if (trace_plane_normal != plane)
{
- // raised forward move hit something
- // so clip to it. solves issues with
- // complex movement on stairs. note
- // that we're not updating origin.
- // -- CEV
- if (roof_fraction < 1.0f)
+ // raised forward move hit something different
+ // than the initial move so clip velocity to
+ // it. solves issues with weird ceilings and
+ // complex movement on stairs. note that we're
+ // not updating origin. -- CEV
+ prev_plane2 = __NULL__;
+ prev_plane = __NULL__;
+ time_left -= time_left * trace_fraction;
+ stepsize = 0;
+
+ if (roof_fraction < 1.0f &&
+ roof_plane != trace_plane_normal)
{
- // save ceiling for later if we hit it
- prev_plane2 = plane;
+ // save the roof plane & fwd plane
prev_plane = roof_plane;
+ plane = trace_plane_normal;
+ }
+ else if (roof_plane == trace_plane_normal)
+ {
+ // roof plane is fwd plane, so save
+ // first and fwd plane
+ prev_plane = plane;
+ plane = trace_plane_normal;
+ }
+ else
+ {
+ // only save fwd plane
+ plane = trace_plane_normal;
}
-
- // stepsize = 0;
- stepsize = trace_endpos_z - self.origin_z;
- time_left -= time_left * trace_fraction;
- plane = trace_plane_normal;
- // save trace_ent if it has a touch function
- if (trace_ent && trace_ent.touch != __NULL__)
- touched_ent = trace_ent;
}
}

- // clip velocity to the saved plane
- // inline PM_Rebound aka PM_ClipVelocity -- CEV
- backoff = self.velocity * plane;
-
- if (backoff < 0)
- backoff *= PM_OVERCLIP;
- else
- if (sticky)
- backoff /= PM_OVERCLIP;
- else
- backoff *= -0.001;
-
- self.velocity -= plane * backoff;
-
// need to do the ground check & touch the saved ent before
// we might stop the loop early -- CEV
if (plane_z > 0.7)
@@ -374,6 +414,20 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
self = orig_self;
}

+ // clip velocity to the saved plane
+ // inline PM_Rebound aka PM_ClipVelocity -- CEV
+ backoff = self.velocity * plane;
+
+ if (backoff < 0)
+ backoff *= PM_OVERCLIP;
+ else
+ if (sticky)
+ backoff /= PM_OVERCLIP;
+ else
+ backoff *= -0.001;
+
+ self.velocity -= plane * backoff;
+
// if velocity interacts with prev_plane then clip to it.
// I'm duplicating a little code here (ClipVelocity),
// hopefully the audience will forgive me. -- CEV
@@ -489,6 +543,8 @@ void() PM_CategorizePosition =
// noclip is never on ground
self.groundentity = __NULL__;
self.groundnormal = __NULL__;
+ self.pmove_flags &= ~PMF_DOUBLEJUMPED;
+ self.pmove_flags &= ~PMF_WALLJUMPED;
self.pmove_flags &= ~PMF_ONGROUND;
self.flags &= ~FL_ONGROUND;
}
@@ -500,41 +556,29 @@ void() PM_CategorizePosition =
// do a trace to check for ground
tracebox (self.origin, self.mins, self.maxs,
self.origin - PM_GROUNDDIST_V, FALSE, self);
- // only onground if we hit it, it faces upwards,
- // and we're actually moving towards it
- // if (trace_fraction < 1 &&
- // trace_plane_normal_z > 0.7 &&
- // self.velocity * trace_plane_normal < 0.01)
- if (trace_fraction < 1 && trace_plane_normal_z > 0.7)
+ // only onground if we hit it & it faces upwards
+ if (trace_fraction < 1.0f && trace_plane_normal_z > 0.7f)
{
// on ground
self.groundentity = trace_ent;
self.groundnormal = trace_plane_normal;
+ self.flags |= FL_ONGROUND;
+ self.pmove_flags |= PMF_ONGROUND;
+ self.pmove_flags &= ~PMF_WALLJUMPED;
}
else
{
+ // not on ground
self.groundentity = __NULL__;
self.groundnormal = __NULL__;
+ self.flags &= ~FL_ONGROUND;
+ self.pmove_flags &= ~PMF_ONGROUND;
}
}

- // assume we're on ground if we have a groundnormal field -- CEV
- if (self.groundnormal != __NULL__)
- {
- // on ground
- self.flags |= FL_ONGROUND;
- self.pmove_flags |= PMF_ONGROUND;
- self.pmove_flags &= ~PMF_WALLJUMP;
- }
- else
- {
- // not on ground
- self.flags &= ~FL_ONGROUND;
- self.pmove_flags &= ~PMF_ONGROUND;
- }
-
// check water levels
- point = [self.origin_x, self.origin_y, self.origin_z + self.mins_z + 1];
+ point = self.origin;
+ point_z = self.origin_z + self.mins_z + 1;
contents = pointcontents (point);
if (contents < CONTENT_SOLID)
{
@@ -560,13 +604,14 @@ void() PM_CategorizePosition =
}

// can't be waterjumping if we're on ground
- if (self.pmove_flags & PMF_WATERJUMP &&
- (!self.waterlevel || self.pmove_flags & PMF_ONGROUND))
+ if (self.pmove_flags & PMF_WATERJUMPED &&
+ (self.waterlevel == WATERLEVEL_NONE ||
+ self.pmove_flags & PMF_ONGROUND))
{
#ifdef SSQC
dprint ("PM_CategorizePosition: clearing FL_WATERJUMP\n");
#endif
- self.pmove_flags &= ~PMF_WATERJUMP;
+ self.pmove_flags &= ~PMF_WATERJUMPED;
self.flags &= ~FL_WATERJUMP;
}
};
@@ -670,11 +715,13 @@ void(vector wishdir, float wishspeed, float move_time) PM_AirControl =
self.velocity_z = zspeed;
};

+//======================================================================
+// PM_Jump
//----------------------------------------------------------------------
void() PM_Jump =
{
// are we already waterjumping, or is jump being held?
- if (self.pmove_flags & PMF_WATERJUMP ||
+ if (self.pmove_flags & PMF_WATERJUMPED ||
self.pmove_flags & PMF_JUMP_HELD)
return;

@@ -717,7 +764,7 @@ void() PM_Jump =
self.velocity_z));
#endif
// don't do additive stairjumps on flat ground -- CEV
- self.velocity_z = PM_DOUBLEJUMPSPEED;
+ self.velocity_z = PM_STAIRJUMPSPEED;
}
else
{
@@ -766,125 +813,148 @@ void() PM_Jump =
self.groundboost_timer = PM_GROUNDBOOST_WINDOW;
};

+//======================================================================
+// PM_WallJump
//----------------------------------------------------------------------
-/* TODO CEV this needs to be reworked.
-void(vector checkdir) PM_WallJump =
+void() PM_WallJump =
{
- // is our upward speed greater than walljump speed?
- if (self.velocity_z > PM_WALLJUMPSPEED)
- return;
-
- // are we already waterjumping?
- if (self.pmove_flags & PMF_WATERJUMP)
+ // are we in water, already waterjumping, already walljumping,
+ // or is jump being held?
+ if (self.waterlevel > WATERLEVEL_NONE ||
+ self.pmove_flags & PMF_WATERJUMPED ||
+ self.pmove_flags & PMF_JUMP_HELD ||
+ self.pmove_flags & PMF_WALLJUMPED)
return;

- // are we already walljumping?
- if (self.pmove_flags & PMF_WALLJUMP)
+ // mandatory interval between jump and walljump
+ if (self.doublejump_timer > (PM_DOUBLEJUMP_WINDOW - PM_WALLJUMP_WINDOW))
return;

- // are we noclipping?
- if (self.movetype == MOVETYPE_NOCLIP)
+ if (self.velocity_z < PM_WALLJUMPLIMIT)
+ // falling too fast to walljump
+ // TODO CEV it would be a good idea to include a sound here.
return;

- // don't pogo
- if (self.pmove_flags & PMF_JUMP_HELD)
- return;
+ // start at STEPHEIGHT + 1 to try and clear any steps -- CEV
+ local vector start, end;
+ start = end = self.origin;
+ start_z += PM_STEPHEIGHT + 1;

- // don't walljump if within 32 units of ground
- tracebox (self.origin, self.mins, self.maxs,
- self.origin - PM_WALLDIST_V, FALSE, self);
- if (trace_fraction < 1) return;
+ for (int i = 0; i < 4; i++)
+ {
+ // I've borrowed a little logic from Quake Champions Classic
+ // here, shoutout to RhapsodyInGeek, check out their good work
+ // https://github.com/RhapsodyInGeek/Quake-Champions-Classic
+ // v_forward and v_right should still correspond to the
+ // makevectors call from PM_Move -- CEV
+ if (i < 2)
+ if (input_movevalues_x == 0)
+ continue;
+ else
+ end = v_forward * 10;
+ if (i > 1)
+ if (input_movevalues_y == 0)
+ continue;
+ else
+ end = v_right * 10;
+ if (i == 1 || i == 3)
+ end = end - end * 2;
+
+ end = start + end;
+
+ // this ends up firing *a lot* when hopping through a map
+ // normally, unfortunately. traceline may be better here -- CEV
+ tracebox (start, self.mins, self.maxs, end, TRUE, self);
+
+ // in order: we hit something, that something is vaguely
+ // vertical, we hit it at a speed greater than -90, and
+ // that something is within 20 (units?) -- CEV
+ if (trace_fraction < 1.0f &&
+ trace_plane_normal_z < 0.2f &&
+ trace_plane_normal_z >= 0 &&
+ self.velocity * trace_plane_normal >= -90 &&
+ vlen(self.origin - trace_endpos) <= 20)
+ {
+ self.pmove_flags |= PMF_WALLJUMPED;
+ break;
+ }
+ }

- tracebox (self.origin, self.mins, self.maxs,
- self.origin + self.velocity * 100, FALSE, self);
- if (trace_fraction < 1 && trace_plane_normal_z < 0.2 &&
- (vlen(self.origin - trace_endpos) < 10))
+ if (self.pmove_flags & PMF_WALLJUMPED)
{
- #ifdef SSQC
- dprint (sprintf("PM_WallJump: walljump dist %g\n",
- vlen(self.origin - trace_endpos)));
- #endif
- // player jumping sound
- #ifdef SSQC
- sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
- #endif
- // modify X and Y velocity
+ // bounce off the wall plane -- CEV
self.velocity_x += trace_plane_normal_x * PM_WALLJUMPFORCE;
self.velocity_y += trace_plane_normal_y * PM_WALLJUMPFORCE;
- // now modify Z
+
+ // zero out negative Z, quarter positive Z -- CEV
+ if (self.velocity_z < 0)
+ self.velocity_z = 0;
+ else if (self.velocity_z > 0)
+ self.velocity_z *= 0.25;
+
if (self.doublejump_timer > 0)
{
- self.velocity_z += PM_DOUBLEJUMPSPEED;
+ #ifdef SSQC
+ dprint ("PM_WallJump: wall double ");
+ #endif
+ self.velocity_z += PM_WALLJUMPDOUBLE;
}
- else if (self.velocity_z < (PM_WALLJUMPSPEED / 0.5))
- self.velocity_z = PM_WALLJUMPSPEED;
else
+ {
+ #ifdef SSQC
+ dprint ("PM_WallJump: walljump ");
+ #endif
self.velocity_z += PM_WALLJUMPSPEED;
- // set walljump flag
- self.pmove_flags |= PMF_WALLJUMP;
- // clear misc flags & ground fields
+ }
+
+ #ifdef SSQC
+ dprint (sprintf("dist %g, normalspeed %g\n",
+ vlen(self.origin - trace_endpos),
+ self.velocity * trace_plane_normal));
+ #endif
+
+ // manage flags & fields; PMF_WALLJUMPED is already set -- CEV
self.pmove_flags |= PMF_JUMP_HELD;
+ self.doublejump_timer = PM_DOUBLEJUMP_WINDOW;
+
+ // server-side stuff
+ #ifdef SSQC
self.button2 = 0;
- self.groundnormal = __NULL__;
- self.groundentity = __NULL__;
+ sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
+ #endif
}
};
-*/

//======================================================================
// PM_WalkAccelerate
-//
-// Handle acceleration for MOVETYPE_WALK entities (players).
-// Modifies velocity. -- CEV
+// Handle accel & friction for MOVETYPE_WALK entities (players). -- CEV
//----------------------------------------------------------------------
-void(float premove, float move_time) PM_WalkAccelerate =
+void(vector wishvel, float move_time) PM_WalkAccelerate =
{
- vector wishvel, wishdir;
- float accel, friction, wishspeed, wishyaw;
-
- accel = friction = wishyaw = 0;
+ vector wishdir;
+ float accel, friction, newspeed, speed, temp, wishspeed;

- // only yaw matters here -- CEV
- makevectors ([0, input_angles_y, 0]);
+ accel = friction = 0;

- wishvel = v_forward * input_movevalues_x;
- wishvel += v_right * input_movevalues_y;
- wishvel += v_up * input_movevalues_z;
wishspeed = vlen (wishvel);
wishdir = normalize (wishvel);

if (wishspeed > PM_MAXSPEED)
wishspeed = PM_MAXSPEED;

- // calculate the difference between the yaw angle the user
- // is requesting to move and the yaw angle we're currently
- // moving in. inspired by Slide mod; might be slow -- CEV
- wishyaw = vectoyaw (wishvel) - vectoyaw (self.velocity);
-
- // limit wishyaw to a range of 0-180 (roughly) -- CEV
- if (wishyaw < 0)
- wishyaw = wishyaw + 360;
- if (wishyaw >= 180)
- wishyaw = fabs (wishyaw - 360);
-
- /*
- #ifdef SSQC
- dprint (sprintf("PM_WalkAccelerate: wishyaw %g\n",
- RAD2DEG * atan2 (vectoyaw(wishvel), vectoyaw(self.velocity))));
- #endif
- */
-
- if (premove)
+ if (self.pmove_flags & PMF_PRE_MOVE)
{
if (self.pmove_flags & PMF_ONLADDER)
{
// ladder physics
// these currently stutter in high ping (or low netfps)
// situations because we rely on touch()ing the ladder
- // trigger to set PMF_ONLADDER -- TODO CEV
+ // trigger to set PMF_ONLADDER and the client doesn't
+ // know about the trigger brush yet -- TODO CEV
self.velocity = 0.75 * self.velocity;

- if (input_buttons & 2 || input_movevalues_z > 0)
+ if (input_buttons & 2 || self.button2 > 0 ||
+ input_movevalues_z > 0)
{
// PlayerClimb -- johnfitz
self.velocity_z = 160;
@@ -905,7 +975,8 @@ void(float premove, float move_time) PM_WalkAccelerate =
}
else
{
- if (input_buttons & 2 || self.button2)
+ if (input_buttons & 2 || self.button2 > 0 ||
+ input_movevalues_z > 0)
{
// +jump was pressed
if (self.pmove_flags & PMF_ONGROUND)
@@ -913,9 +984,11 @@ void(float premove, float move_time) PM_WalkAccelerate =
// normal jump
PM_Jump ();
}
- // TODO CEV
- // else
- // PM_WallJump (right);
+ else if (autocvar(pm_walljump, FALSE))
+ {
+ // borrow FTE's pm_walljump cvar -- CEV
+ PM_WallJump ();
+ }
}
else
{
@@ -945,66 +1018,119 @@ void(float premove, float move_time) PM_WalkAccelerate =
accel = PM_GROUNDACCEL;
friction = PM_GROUNDFRICTION;
}
+ }
+ else if (input_movevalues_x == 0)
+ {
+ // Q1 air accel when requesting sideways movement in the air
+ // flag a check below with this -1 -- CEV
+ accel = -1;
+ }
+ else
+ {
+ if (input_movevalues_y == 0)
+ {
+ // Painkiller style air control
+ if (input_movevalues_x < 0)
+ // we're slowing down
+ accel = PM_AIRACCELBACK;
+ else
+ // we're gaining speed
+ accel = PM_AIRACCELFWD;

- /* testing something out here -- TODO CEV
- if (!input_movevalues_x && self.teleport_time <= (time - 0.1) &&
- self.groundboost_timer > 0 &&
- (wishyaw > 75 && wishyaw < 105))
+ // borrow the friction var to flag a conditional below
+ friction = -1;
+ }
+ else
{
- // if we're onground, haven't just exited a teleporter,
- // are within the boost timer, and are holding left
- // or right then redirect left/right velocity into
- // forward velocity to prevent sudden changes of
- // direction while jumping up stairs -- CEV
- wishvel = v_forward * fabs(input_movevalues_y * 1.2f);
- wishvel += v_right * (input_movevalues_y * 0.05f);
- wishvel += v_up * input_movevalues_z;
- #ifdef SSQC
- dprint ("PM_WalkAccelerate: altering wishvel\n");
- #endif
- wishspeed = vlen (wishvel);
- wishdir = normalize (wishvel);
+ // we're in the air and the player is requesting both
+ // forward/back and sideways movement, so pick the Q3
+ // air accel value -- CEV
+ accel = PM_AIRACCELQ3;
}
- */
}
- else if (input_movevalues_x && input_movevalues_y)
+
+ // I've duplicated a fair amount of code below, inlining the various
+ // acceleration functions to hopefully improve performance -- CEV
+
+ // apply friction (ground or otherwise)
+ if (friction > 0)
{
- // we're in the air and the player is requesting both
- // forward/back and sideways movement, so pick the Q3
- // air accel value -- CEV
- accel = PM_AIRACCELQ3;
+ // inline PM_Friction
+ speed = vlen (self.velocity);
+
+ if (speed < 1)
+ {
+ self.velocity = '0 0 0';
+ }
+ else
+ {
+ // calculate what their new speed should be
+ temp = speed < PM_STOPSPEED ? PM_STOPSPEED : speed;
+ newspeed = speed - temp * friction * move_time;
+
+ // and slow them
+ if (newspeed < 0)
+ newspeed = 0;
+
+ self.velocity = self.velocity * (newspeed / speed);
+ }
}
- else if ((wishyaw > 45 && wishyaw < 135) ||
- vlen ([self.velocity_x, self.velocity_y, 0]) <
- (PM_MAXAIRSPEED - 1))
+
+ if (accel == -1)
{
- // Q1 air control when requesting movement within 45 to
- // 135 degrees of current movement -- CEV
- PM_AirAccelerate (wishvel, wishspeed, PM_AIRACCEL, move_time);
+ // Quake 1 sideways air acceleration; inline PM_AirAccelerate
+ wishvel_z = 0;
+ temp = vlen (wishvel);
+ wishvel = normalize (wishvel);
+ if (temp > PM_MAXAIRSPEED)
+ temp = PM_MAXAIRSPEED;
+ speed = self.velocity * wishvel;
+ speed = temp - speed;
+
+ if (speed > 0)
+ {
+ newspeed = PM_AIRACCEL * move_time * wishspeed;
+ if (newspeed > speed)
+ newspeed = speed;
+ self.velocity += newspeed * wishvel;
+ }
}
- else
+ else if (accel > 0)
{
- if (wishyaw >= 135)
- // we're slowing down
- accel = PM_AIRACCELBACK;
- else
- // we're gaining speed
- accel = PM_AIRACCELFWD;
+ // ground & Quake 3 style acceleration; inline PM_Accelerate
+ speed = wishspeed - (self.velocity * wishdir);

- // borrow the local friction var to flag a conditional below
- friction = -1;
+ if (speed > 0)
+ {
+ newspeed = accel * move_time * wishspeed;
+ if (newspeed > speed)
+ newspeed = speed;
+
+ self.velocity += newspeed * wishdir;
+ }
}

- if (friction > 0)
- PM_Friction (friction, move_time);
+ // CPM & PK-style air control, needs to happen after PM_Accelerate
+ if (friction == -1)
+ {
+ // inline PM_AirControl
+ temp = self.velocity_z;
+ self.velocity_z = 0;
+
+ speed = vlen (self.velocity);
+ self.velocity = normalize (self.velocity);

- if (accel > 0)
- PM_Accelerate (wishdir, wishspeed, accel, move_time);
+ if ((self.velocity * wishdir) > 0)
+ {
+ self.velocity = normalize (self.velocity * speed +
+ wishdir * PM_AIRACCELTURN);
+ }

- if (friction < 0)
- PM_AirControl (wishdir, wishspeed, move_time);
+ self.velocity *= speed;
+ self.velocity_z = temp;
+ }

- if (!premove)
+ if (!(self.pmove_flags & PMF_PRE_MOVE))
self.pmove_flags &= ~PMF_STARTGROUND;
};

@@ -1012,73 +1138,70 @@ void(float premove, float move_time) PM_WalkAccelerate =
// PM_SwimAccelerate
// Largely copied from id Software's WaterMove. Works like NoClipAccelerate.
//----------------------------------------------------------------------
-void(float move_time) PM_SwimAccelerate =
+void(vector wishvel, float move_time) PM_SwimAccelerate =
{
- vector wishvel;
float wishspeed;

- makevectors (input_angles);
-
- wishvel = v_forward * input_movevalues_x;
- wishvel += v_right * input_movevalues_y;
- wishvel += v_up * input_movevalues_z;
-
- // CheckWaterJump
- if (self.waterlevel == WATERLEVEL_WAIST)
+ if (self.pmove_flags & PMF_PRE_MOVE)
{
- local vector start, end;
-
- start = self.origin;
- start_z = start_z + 8;
- // use wishvel instead of v_forward -- CEV
- end = [wishvel_x, wishvel_y, 0];
- end = normalize (end);
- traceline (start, (start + end * 24), TRUE, self);
-
- if (trace_fraction < 1)
+ // CheckWaterJump
+ if (self.waterlevel == WATERLEVEL_WAIST)
{
- // solid at the waist
- start_z = start_z + self.maxs_z - 8;
- self.movedir = trace_plane_normal * -50;
+ local vector start, end;
+
+ start = self.origin;
+ start_z = start_z + 8;
+ // use wishvel instead of v_forward -- CEV
+ end = [wishvel_x, wishvel_y, 0];
+ end = normalize (end);
traceline (start, (start + end * 24), TRUE, self);

- if (trace_fraction == 1)
+ if (trace_fraction < 1)
{
- // open at eye level
- self.flags |= FL_WATERJUMP;
- self.pmove_flags |= PMF_WATERJUMP;
- self.flags &= ~FL_JUMPRELEASED;
- self.pmove_flags &= ~PMF_JUMP_HELD;
- // Z velocity was 225
- self.velocity_z = PM_JUMPSPEED;
- // safety net
- self.teleport_time = time + 2;
+ // solid at the waist
+ start_z = start_z + self.maxs_z - 8;
+ self.movedir = trace_plane_normal * -50;
+ traceline (start, (start + end * 24),
+ TRUE, self);
+
+ if (trace_fraction == 1)
+ {
+ // open at eye level
+ self.flags |= FL_WATERJUMP;
+ self.pmove_flags |= PMF_WATERJUMPED;
+ self.flags &= ~FL_JUMPRELEASED;
+ self.pmove_flags &= ~PMF_JUMP_HELD;
+ // Z velocity was 225
+ self.velocity_z = PM_JUMPSPEED;
+ // safety net
+ self.teleport_time = time + 2;
+ }
}
}
- }

- #ifdef SSQC
- // functionality copied into pmove from client.qc -- CEV
- if (self.waterlevel >= WATERLEVEL_WAIST)
- {
- if (self.swim_flag < time)
+ #ifdef SSQC
+ // functionality copied into pmove from client.qc -- CEV
+ if (self.waterlevel >= WATERLEVEL_WAIST)
{
- // play swimming sound
- self.swim_flag = time + 1;
- if (random() < 0.5)
- sound (self, CHAN_BODY, "misc/water1.wav",
- 1, ATTN_NORM);
- else
- sound (self, CHAN_BODY, "misc/water2.wav",
- 1, ATTN_NORM);
+ if (self.swim_flag < time)
+ {
+ // play swimming sound
+ self.swim_flag = time + 1;
+ if (random() < 0.5)
+ sound (self, CHAN_BODY,
+ "misc/water1.wav", 1,ATTN_NORM);
+ else
+ sound (self, CHAN_BODY,
+ "misc/water2.wav", 1,ATTN_NORM);
+ }
}
+ #endif
}
- #endif

- if (input_buttons & 2 && !(self.pmove_flags & PMF_WATERJUMP))
+ if (input_buttons & 2 && !(self.pmove_flags & PMF_WATERJUMPED))
// smartjump
wishvel_z = max (PM_MAXSPEED, wishvel_z);
- else if (!input_movevalues)
+ else if (input_movevalues == '0 0 0')
// drift towards bottom -- CEV
wishvel_z -= PM_WATERSINKSPEED;

@@ -1088,7 +1211,7 @@ void(float move_time) PM_SwimAccelerate =
wishvel = normalize (wishvel);

// water friction; reuse PM_Friction with a special constant -- CEV
- if (!(self.pmove_flags & PMF_WATERJUMP))
+ if (!(self.pmove_flags & PMF_WATERJUMPED))
PM_Friction (PM_WATERFRICTION, move_time);

// accelerate; reuse PM_Accelerate with a special constant -- CEV
@@ -1101,17 +1224,10 @@ void(float move_time) PM_SwimAccelerate =
// Basic acceleration for flying / noclipping players. Not suitable for
// swimming. -- CEV
//----------------------------------------------------------------------
-void(float scale, float move_time) PM_NoClipAccelerate =
+void(vector wishvel, float scale, float move_time) PM_NoClipAccelerate =
{
- vector wishvel;
float wishspeed;

- makevectors (input_angles);
-
- wishvel = v_forward * input_movevalues_x;
- wishvel += v_right * input_movevalues_y;
- wishvel += v_up * input_movevalues_z;
-
// smartjump
if (input_buttons & 2)
wishvel_z = max (PM_MAXSPEED, wishvel_z);
@@ -1132,7 +1248,9 @@ void(float move_time) PM_ManageTimers =
self.doublejump_timer = 0;

if (self.doublejump_timer == 0)
+ {
self.pmove_flags &= ~PMF_DOUBLEJUMPED;
+ }

if (self.groundboost_timer > 0 && move_time > 0)
self.groundboost_timer -= move_time;
@@ -1145,12 +1263,13 @@ void(float move_time) PM_ManageTimers =
//----------------------------------------------------------------------
void(entity target) PM_Move =
{
- entity oldself;
-
if (input_timelength <= 0)
// don't process partial frames -- CEV
return;

+ vector wishvel;
+ entity oldself;
+
oldself = self;
self = target;

@@ -1160,10 +1279,46 @@ void(entity target) PM_Move =
if (!autocvar(sv_bigcoords, FALSE))
PM_Nudge ();

+ // rework user input, copying something like QuakeSpasm's always run
+ // feature here. This turns the +speed button into a hold-to-walk
+ // button when cl_run is 0 (when FTE's always run setting is on).
+ // -- CEV
+ if (autocvar(cl_run, FALSE) == FALSE)
+ {
+ // local float s = 0;
+ for (int i = 0; i < 3; i++)
+ {
+ // this works, it's just commented out to stop calling
+ // autocvar quite so many times. to re-enable change
+ // the check against "PM_RUNSPEED" below to "s" -- CEV
+ /*
+ if (i == 0)
+ s = autocvar (cl_forwardspeed, PM_RUNSPEED);
+ else if (i == 1)
+ s = autocvar (cl_sidespeed, PM_RUNSPEED);
+ else if (i == 2)
+ s = autocvar (cl_upspeed, PM_RUNSPEED);
+ */
+
+ if (fabs(input_movevalues[i]) > PM_RUNSPEED)
+ input_movevalues[i] = PM_WALKSPEED *
+ (input_movevalues[i] /
+ fabs(input_movevalues[i]));
+ // Don't need this, it's already PM_RUNSPEED -- CEV
+ /*
+ else if (input_movevalues[i] != 0)
+ input_movevalues[i] = PM_RUNSPEED *
+ (input_movevalues[i] /
+ fabs(input_movevalues[i]));
+ */
+ }
+ }
+
// TODO CEV this is the wrong place to clear PMF_JUMP_HELD
- if (!(input_buttons & 2))
+ if (!(input_buttons & 2) || self.button2 == 0)
self.pmove_flags &= ~PMF_JUMP_HELD;

+ // figure out the properties of the player's position, then clear timers
PM_CategorizePosition ();
PM_ManageTimers (0);

@@ -1175,6 +1330,9 @@ void(entity target) PM_Move =
doskim = FALSE;
sticky = FALSE;

+ // signal acceleration functions that we're pre-move
+ self.pmove_flags |= PMF_PRE_MOVE;
+
// split the acceleration in two to reduce
// framerate dependence. -- CEV
if (self.waterlevel >= WATERLEVEL_WAIST)
@@ -1184,40 +1342,57 @@ void(entity target) PM_Move =
dogravity = FALSE;
doskim = FALSE;
sticky = FALSE;
+
+ // figure out wishvel -- CEV
+ makevectors (input_angles);
+ wishvel = v_forward * input_movevalues_x;
+ wishvel += v_right * input_movevalues_y;
+ wishvel += v_up * input_movevalues_z;
+
// swim acceleration
- PM_SwimAccelerate (input_timelength * 0.5f);
+ PM_SwimAccelerate (wishvel,
+ input_timelength * 0.5f);
}
else
{
- PM_WalkAccelerate (TRUE,
+ // only yaw matters here -- CEV
+ makevectors ([0, input_angles_y, 0]);
+ wishvel = v_forward * input_movevalues_x;
+ wishvel += v_right * input_movevalues_y;
+ // don't need wishvel_z -- CEV
+ // wishvel += v_up * input_movevalues_z;
+
+ PM_WalkAccelerate (wishvel,
input_timelength * 0.5f);

// WalkAccelerate calls Jump which might
// alter pmove_flags, so do our feature
// checks afterwards -- CEV
- if (self.doublejump_timer > 0 &&
- !(self.pmove_flags & PMF_DOUBLEJUMPED))
+ if (self.doublejump_timer <= 0 ||
+ self.pmove_flags & PMF_DOUBLEJUMPED ||
+ self.pmove_flags & PMF_WALLJUMPED)
+ // don't stick to the floor
+ sticky = FALSE;
+ else
// we've jumped & haven't doublejumped,
// so do sticky steps -- CEV
sticky = TRUE;
- else
- // otherwise nostick -- CEV
- sticky = FALSE;

// apply gravity only when in the air or on
// a ramp -- CEV
if (self.groundnormal &&
self.groundnormal_z < 1.0f)
dogravity = TRUE;
- else if (!(self.pmove_flags & PMF_ONGROUND))
- dogravity = TRUE;
- else
+ else if (self.pmove_flags & PMF_ONGROUND)
dogravity = FALSE;
+ else
+ dogravity = TRUE;

// skim / wallclipping checks -- CEV
if (self.doublejump_timer >
(PM_DOUBLEJUMP_WINDOW -
PM_WALLCLIP_WINDOW) &&
+ !(self.pmove_flags & PMF_WALLJUMPED) &&
self.teleport_time <= (time - 0.1))
doskim = TRUE;

@@ -1236,11 +1411,15 @@ void(entity target) PM_Move =
// Do the move. Bounce, Rock, Skate, Roll -- CEV
PM_DanceMove (dogravity, sticky, TRUE, doskim);

+ // signal accel functions we're post-move
+ self.pmove_flags &= ~PMF_PRE_MOVE;
+
// second pass at acceleration
if (self.waterlevel >= WATERLEVEL_WAIST)
- PM_SwimAccelerate (input_timelength * 0.5f);
+ PM_SwimAccelerate (wishvel,
+ input_timelength * 0.5f);
else
- PM_WalkAccelerate (FALSE,
+ PM_WalkAccelerate (wishvel,
input_timelength * 0.5f);

// timers (part 2) -- CEV
@@ -1253,17 +1432,29 @@ void(entity target) PM_Move =
break;

case MOVETYPE_FLY:
- // split the acceleration in two to reduce
- // framerate dependence. -- CEV
- PM_NoClipAccelerate (1.0f, input_timelength * 0.5f);
+ // split acceleration in two to reduce framerate
+ // dependence. -- CEV
+ makevectors (input_angles);
+ wishvel = v_forward * input_movevalues_x;
+ wishvel += v_right * input_movevalues_y;
+ wishvel += v_up * input_movevalues_z;
+
+ PM_NoClipAccelerate (wishvel, 1.0f,
+ input_timelength * 0.5f);
PM_DanceMove (FALSE, TRUE, TRUE, FALSE);
- PM_NoClipAccelerate (1.0f, input_timelength * 0.5f);
+ PM_NoClipAccelerate (wishvel, 1.0f,
+ input_timelength * 0.5f);
break;

case MOVETYPE_NOCLIP:
// noclip is a debugging feature, no need to
// worry about acceleration consistency. -- CEV
- PM_NoClipAccelerate (1.0f, input_timelength);
+ makevectors (input_angles);
+ wishvel = v_forward * input_movevalues_x;
+ wishvel += v_right * input_movevalues_y;
+ wishvel += v_up * input_movevalues_z;
+
+ PM_NoClipAccelerate (wishvel, 1.0f, input_timelength);
// we're noclipping so update origin directly -- CEV
self.origin += self.velocity * input_timelength;
break;

Return to the top of this page or return to the overview of this repo.

Diff qc/progs.src

diff --git a/qc/progs.src b/qc/progs.src
index cbc2056..8647d24 100644
--- a/qc/progs.src
+++ b/qc/progs.src
@@ -6,6 +6,9 @@
#define SSQC

#includelist
+//----------------------------------------------------------------------
+// defs
+//----------------------------------------------------------------------
defs_globalvars.qc // globalvars_t
defs_entvars.qc // entvars_t
defs_builtins.qc // builtin functions (& overrides)
@@ -29,27 +32,54 @@ weapons.qc
world.qc
intermission.qc
pmove.qc // QC player movement code -- CEV
-sv_runclient.qc // hook into SV_RunClientCommand FTE extension -- CEV
client.qc
cutscene.qc // Drake version -- dumptruck_ds
player.qc
keylock.qc // common code for entities unlockable with keys
doors.qc
buttons.qc
-triggers.qc // added trigger_push_custom based on Hipnotic
+
+//----------------------------------------------------------------------
+// func
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+// triggers
+//----------------------------------------------------------------------
+triggers/changelevel.qc //
+triggers/changemusic.qc //
+triggers/changetarget.qc//
+triggers/counter.qc //
+triggers/filter.qc //
triggers/heal.qc // trigger_heal (was in dtmisc.qc) -- CEV
+triggers/hurt.qc //
triggers/ladder.qc // ladders (from rubicon2) -- CEV
+triggers/look.qc //
+triggers/misc.qc // was triggers.qc -- CEV
+triggers/monsterface.qc //
+triggers/monsterjump.qc //
+triggers/onlyregistered.qc//
triggers/push.qc // wind/push brushes, jumppads -- CEV
+triggers/remove.qc // was in hip_trig.qc; currently commented out -- CEV
+triggers/secret.qc //
+triggers/setgravity.qc // was in hip_trig.qc
+triggers/setskill.qc //
triggers/shake.qc // triggerable shake from Zer cutscenes; was dtquake.qc
+triggers/take_weapon.qc //
triggers/teleport.qc // was in triggers.qc -- CEV
triggers/textstory.qc // textstory (was in misc.qc) -- CEV
+triggers/usekey.qc // was in hip_trig.qc -- CEV
+triggers/void.qc //
+
plats.qc
misc.qc
lights.qc // c0burn's excellent switchable lights
fog.qc // fog triggers
cshift.qc // background color shift controller

+//----------------------------------------------------------------------
// monsters
+//----------------------------------------------------------------------
monsters.qc // modified by dumptruck_ds from Preach's
// spawning tutorial | fish count fixed
monsters/boss.qc
@@ -77,7 +107,6 @@ misc_model.qc // Code by Joshua Skelton
hip_count.qc // Hipnotic counter
hip_part.qc // Hipnotic particlefield and func_togglewall
hip_rotate.qc // from Hipnotic thanks RennyC
-hip_trig.qc // Hipnotic triggers qc
doe_elbutton.qc // Rogue elevator code
doe_ltrail.qc // from DOE lightnin.qc
doe_plats.qc // Rogue MP newplats.qc

Return to the top of this page or return to the overview of this repo.

Diff qc/subs.qc

diff --git a/qc/subs.qc b/qc/subs.qc
index 91343f3..06eb3fa 100644
--- a/qc/subs.qc
+++ b/qc/subs.qc
@@ -711,7 +711,6 @@ float() CheckValidTouch =
return FALSE;
return TRUE;
}
-float(float a, float b) not = { return a - (a & b); } // fix not issue in client.qc - Copper -- dumptruck_ds

void() SUB_EndWaiting = {
self.is_waiting = 0;

Return to the top of this page or return to the overview of this repo.

Diff qc/sv_runclient.qc

diff --git a/qc/sv_runclient.qc b/qc/sv_runclient.qc
deleted file mode 100644
index 19686d2..0000000
--- a/qc/sv_runclient.qc
+++ /dev/null
@@ -1,12 +0,0 @@
-void(entity ent) PM_Move;
-
-void() SV_RunClientCommand =
-{
- // should match the one used by csqc.
- if (autocvar(pm_standardphysics, FALSE))
- // for testing -- CEV
- runstandardplayerphysics (self);
- else
- // for real
- PM_Move (self);
-};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers.qc

diff --git a/qc/triggers.qc b/qc/triggers.qc
deleted file mode 100644
index fc10495..0000000
--- a/qc/triggers.qc
+++ /dev/null
@@ -1,1177 +0,0 @@
-//==============================================================================
-// TRIGGERS.QC
-//==============================================================================
-
-// entity s;
-
-void() trigger_reactivate =
-{
- self.solid = SOLID_TRIGGER;
-};
-
-//=============================================================================
-
-float SPAWNFLAG_NOMESSAGE = 1;
-float SPAWNFLAG_NOTOUCH = 1;
-float SPAWNFLAG_TURNS_OFF = 2; //used for Wait for retrigger spawnflag
-
-// the wait time has passed, so set back up for another activation
-void() multi_wait =
-{
- if (self.max_health)
- {
- self.health = self.max_health;
- self.takedamage = DAMAGE_YES;
- self.solid = SOLID_BBOX;
- }
-};
-
-
-// the trigger was just touched/killed/used
-// self.enemy should be set to the activator so it can be held through a delay
-// so wait for the delay time before firing
-void() multi_trigger =
-{
- if (self.nextthink > time)
- {
- return; // allready been triggered
- }
-
- if (self.classname == "trigger_secret")
- {
- if (self.enemy.classname != "player")
- return;
- if (cutscene)
- return; // Don't activate in cutscene mode
- found_secrets = found_secrets + 1;
- WriteByte (MSG_ALL, SVC_FOUNDSECRET);
- }
-
- if (self.noise != "")
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
-
-// don't trigger again until reset
- self.takedamage = DAMAGE_NO;
-
- activator = self.enemy;
-
- SUB_UseTargets();
-
- if (self.wait > 0)
- {
- self.think = multi_wait;
- self.nextthink = time + self.wait;
- if (self.spawnflags & SPAWNFLAG_TURNS_OFF)
- {
- self.is_waiting = 1;
- SUB_CheckWaiting();
- }
- }
- else
- { // we can't just remove (self) here, because this is a touch function
- // called wheil C code is looping through area links...
- self.touch = SUB_Null;
- self.nextthink = time + 0.1;
- self.think = SUB_Remove;
- }
-};
-
-void() multi_killed = //dumptruck_ds
-{
- if (self.estate != STATE_ACTIVE) // Supa, restore health and do nothing if we're still waiting to be activated
- {
- self.health = self.max_health; // nyah nyah~!
- self.takedamage = DAMAGE_YES;
- self.solid = SOLID_BBOX;
-
- return;
- }
-
- self.enemy = damage_attacker;
- multi_trigger();
-};
-
-void() multi_use = //dumptruck_ds
-{
- self.enemy = activator;
- multi_trigger();
-};
-
-void() multi_touch = //dumptruck_ds
-{
-
- if (other.classname != "player")
- return;
-
- // from Copper -- dumptruck_ds
- if (other.movetype == MOVETYPE_NOCLIP)
- return;
-
- if (self.estate != STATE_ACTIVE)
- return;
-
-// if the trigger has an angles field, check player's facing direction
- if (self.movedir != '0 0 0')
- {
- makevectors (other.angles);
- if (v_forward * self.movedir < 0)
- return; // not facing the right way
- }
-
- self.enemy = other;
- multi_trigger ();
-};
-
-/*QUAKED trigger_multiple (.5 .5 .5) ? notouch WAIT_FOR_RETRIGGER X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-
-Variable sized repeatable trigger. Must be targeted at one or more entities. If "health" is set, the trigger must be killed to activate each time.
-If "WAIT_FOR_RETRIGGER" is set, it must be triggered by another entity before it can trigger again.
-If "delay" is set, the trigger waits some time after activating before firing.
-"wait" : Seconds between triggerings. (.2 default)
-If notouch is set, the trigger is only fired by other entities, not by touching.
-NOTOUCH has been obsoleted by trigger_relay!
-sounds
-1) secret
-2) beep beep
-3) large switch
-set "message" to text string
-"is_waiting" : If set to 1, this trigger will do nothing until another trigger activates it
-*/
-void() trigger_multiple =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (self.sounds == 1)
- {
- precache_sound ("misc/secret.wav");
- self.noise = "misc/secret.wav";
- }
- else if (self.sounds == 2)
- {
- precache_sound ("misc/talk.wav");
- self.noise = "misc/talk.wav";
- }
- else if (self.sounds == 3)
- {
- precache_sound ("misc/trigger1.wav");
- self.noise = "misc/trigger1.wav";
- }
-
- if (!self.wait)
- {
- self.wait = 0.2;
- }
- else if (self.wait < 0 && (self.spawnflags & SPAWNFLAG_TURNS_OFF))
- {
- objerror("Wait for retrigger and negative wait don't make sense");
- }
- self.use = multi_use;
-
- InitTrigger ();
-
- if (self.health)
- {
- if (self.spawnflags & SPAWNFLAG_NOTOUCH)
- objerror ("health and notouch don't make sense\n");
- self.max_health = self.health;
- self.th_die = multi_killed;
- self.takedamage = DAMAGE_YES;
- self.solid = SOLID_BBOX;
- setorigin (self, self.origin); // make sure it links into the world
- }
- else
- {
- if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
- {
- self.touch = multi_touch;
- }
- }
-
- SUB_CheckWaiting();
-};
-
-
-/*QUAKED trigger_once (.5 .5 .5) ? notouch X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-
-Variable sized trigger. Triggers once, then removes itself. You must set the key "target" to the name of another object in the level that has a matching
-"targetname". If "health" is set, the trigger must be killed to activate.
-If notouch is set, the trigger is only fired by other entities, not by touching.
-if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
-if "angle" is set, the trigger will only fire when someone is facing the direction of the angle. Use "360" for an angle of 0.
-sounds
-1) secret
-2) beep beep
-3) large switch
-set "message" to text string
-*/
-void() trigger_once =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.wait = -1;
- trigger_multiple();
-};
-
-//=============================================================================
-
-/*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-This fixed size trigger cannot be touched, it can only be fired by other events. It can contain killtargets, targets, delays, and messages.
-*/
-void() trigger_relay =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.use = SUB_UseTargets;
-};
-
-
-//=============================================================================
-
-/*QUAKED trigger_secret (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-secret counter trigger
-sounds
-1) secret
-2) beep beep
-set "message" to text string
-*/
-void() trigger_secret =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- total_secrets = total_secrets + 1;
- self.wait = -1;
- if (!self.message)
- self.message = "You found a secret area!";
- if (!self.sounds)
- self.sounds = 1;
-
- if (self.sounds == 1)
- {
- precache_sound ("misc/secret.wav");
- self.noise = "misc/secret.wav";
- }
- else if (self.sounds == 2)
- {
- precache_sound ("misc/talk.wav");
- self.noise = "misc/talk.wav";
- }
-
- trigger_multiple ();
-};
-
-//=============================================================================
-
-
-void() counter_use =
-{
- if (self.estate != STATE_ACTIVE) return;
-
- self.count = self.count - 1;
- if (self.count < 0)
- return;
-
- if (self.count != 0)
- {
- if (activator.classname == "player"
- && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
- {
- if (self.count >= 4)
- centerprint (activator, "There are more to go...");
- else if (self.count == 3)
- centerprint (activator, "Only 3 more to go...");
- else if (self.count == 2)
- centerprint (activator, "Only 2 more to go...");
- else
- centerprint (activator, "Only 1 more to go...");
- }
- return;
- }
-
- if (activator.classname == "player"
- && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
- centerprint(activator, "Sequence completed!");
- self.enemy = activator;
- multi_trigger ();
-};
-
-/*QUAKED trigger_counter (.5 .5 .5) ? nomessage X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-
-Acts as an intermediary for an action that takes multiple inputs.
-
-If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
-
-After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
-*/
-void() trigger_counter =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.wait = -1;
- if (!self.count)
- self.count = 2;
-
- self.use = counter_use;
-};
-
-/*
-==============================================================================
-
-trigger_setskill
-
-==============================================================================
-*/
-
-void() trigger_skill_touch =
-{
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
- cvar_set ("skill", self.message);
-};
-
-/*QUAKED trigger_setskill (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-sets skill level to the value of "message".
-Only used on start map.
-*/
-void() trigger_setskill =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- InitTrigger ();
- self.touch = trigger_skill_touch;
-
- SUB_CheckWaiting();
-};
-
-
-/*
-==============================================================================
-
-ONLY REGISTERED TRIGGERS
-
-==============================================================================
-*/
-
-void() trigger_onlyregistered_touch =
-{
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
- if (self.attack_finished > time)
- return;
-
- self.attack_finished = time + 2;
- if (cvar("registered"))
- {
- self.message = "";
- SUB_UseTargets ();
- remove (self);
- }
- else
- {
- if (self.message != "")
- {
- centerprint (other, self.message);
- sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
- }
- }
-};
-
-/*QUAKED trigger_onlyregistered (.5 .5 .5) ?
-Only fires if playing the registered version, otherwise prints the message
-*/
-void() trigger_onlyregistered =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- precache_sound ("misc/talk.wav");
- InitTrigger ();
- self.touch = trigger_onlyregistered_touch;
-
- SUB_CheckWaiting();
-};
-
-//============================================================================
-
-// 1998-07-03 hurt_touch fix by Robert Field start
-/*
-void() hurt_on =
-{
- self.solid = SOLID_TRIGGER;
- self.nextthink = -1;
-};
-*/
-// 1998-07-03 hurt_touch fix by Robert Field end
-
-void() hurt_touch =
-{
-
- if (self.estate != STATE_ACTIVE) return;
-
- // from Copper -- dumptruck_ds
- if (other.movetype == MOVETYPE_NOCLIP)
- return;
-
- if (other.takedamage && self.nextthink < time)
- {
-// 1998-07-03 hurt_touch fix by Robert Field start
-// self.solid = SOLID_NOT;
- if (time != self.hurt_together_time)
- if (time < self.hurt_nextthink)
- return;
-// 1998-07-03 hurt_touch fix by Robert Field end
- T_Damage (other, self, self, self.dmg);
-// 1998-07-03 hurt_touch fix by Robert Field start
-// self.think = hurt_on;
-// self.nextthink = time + 1;
- self.hurt_together_time = time;
- self.hurt_nextthink = time + 1;
-// 1998-07-03 hurt_touch fix by Robert Field end
- }
- return;
-};
-
-/*QUAKED trigger_hurt (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-Any object touching this will be hurt
-set dmg to damage amount
-defalt dmg = 5
-*/
-void() trigger_hurt =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- InitTrigger ();
- self.touch = hurt_touch;
- if (!self.dmg)
- self.dmg = 5;
-
- SUB_CheckWaiting();
-};
-
-//This is necros' trigger_void from Lost Chapters pack, modified by dumptruck_ds
-
-float MONSTER_SAFE = 1;
-float PLAYER_SAFE = 2;
-
-void() trigger_void_touch =
-{
- if (self.estate != STATE_ACTIVE) return;
-
- if (other.movetype == MOVETYPE_NOCLIP) // from Copper -- dumptruck_ds
- return FALSE;
-
- if (self.spawnflags & MONSTER_SAFE && other.flags & FL_MONSTER) return; //ignore monsters
- if (self.spawnflags & PLAYER_SAFE && other.flags & FL_CLIENT) return; // ignore players
-
- if (other.takedamage)
- {
- other.invincible_finished = 0; // kills even with Pentagram, this took forever to figure out!! -- dumptruck_ds
- T_Damage (other, self, self, other.health + 1000 /*, DTH_TRIGGER_VOID, 1, 1*/);
-
- if (other.flags & FL_MONSTER)
- remove(other);
- }
-
- if (other.classname == "gib" ||
- other.classname == "grenade" ||
- other.classname == "spike" ||
- other.classname == "missile")
- remove(other);
-
- if (other.flags & FL_ITEM)
- remove(other);
-
- force_retouch = 2;
-};
-
-/*QUAKED trigger_void (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-Use this for a 'void' area. removes monsters, gibs, ammo, etc... also kills player.
-*/
-void() trigger_void =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- InitTrigger ();
- self.touch = trigger_void_touch;
-
- SUB_CheckWaiting();
-};
-
-/*==============================================================================
-GIVE AND TAKE STUFF (WIP)
-
-This is Axe only at the moment. Need to research removing all weapons.
-==============================================================================*/
-
-void() take_weapon_use = //thanks to ShanJaq and Spike for their help on this.
-
-{
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
- if (!(other.flags & FL_CLIENT))
- return;
-
- {
- multi_trigger();
- other.items &= ~IT_SHOTGUN;
- other.currentammo = !other.ammo_shells;
- other.ammo_shells = !other.ammo_shells;
- other.items = other.items - ( other.items & IT_SHELLS);
- W_SetCurrentAmmo();
- W_BestWeapon();
- }
-};
-/*QUAKED trigger_take_weapon (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-
-Removes shotgun upon touch. You can also set "reset_items" in the worldspawn entity to accomplish an axe only start.
-*/
-void() trigger_take_weapon =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.wait = -1;
- trigger_multiple();
- self.touch = take_weapon_use;
-
- SUB_CheckWaiting();
-};
-
-void(float newtrack) changemusic =
-{
- *world_sounds = newtrack; //changing the field via a pointer
- //world.sounds has now been changed via our pointer, newly connecting players (like those connecting after the game is loaded) will get sent the new cd track's number.
-
- //let everyone currently on the server know.
- WriteByte(MSG_ALL, SVC_CDTRACK);
- WriteByte(MSG_ALL, newtrack); //initial track
- WriteByte(MSG_ALL, newtrack); //looped track... should generally be set the same as the initial track as most engines ignore it entirely so it might as well be sane for those that care.
-};
-
-//thanks to jleww via changemusic.rar --dumptruck_ds
-
-void() trigger_changemusic_touch =
-{
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
- if (!(other.flags & FL_CLIENT))
- {
- return;
- }
- changemusic(self.sounds);
- self.touch = SUB_Null;
- self.nextthink = (time + 0.1);
- self.think = SUB_Remove;
-};
-/*QUAKED trigger_changemusic (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-A trigger brush that changes the currently playing music track. The number of the track to play goes in the sounds key (just like worldspawn). */
-void() trigger_changemusic =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
- if (!self.sounds)
- {
- objerror("ERROR: trigger_changemusic needs valid track number in sounds field");
- return;
- }
- InitTrigger();
- self.touch = trigger_changemusic_touch;
-
- SUB_CheckWaiting();
-};
-
-void() trigger_cdtrack_use = //point entity version uses count for music track number for backwards compatibly in Adoria mod -- dumptruck_ds
-{
- changemusic(self.count);
-};
-/*QUAKED trigger_cdtrack (.7 .7 .7) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-A point entity that changes the currently playing music track when triggered. The number of the track to play goes in the count key. e.g. 32 for track32.ogg See manual trigger_changemusic for more information on formats and more.
-
-NOTE: the track number uses the count key here but trigger_changemusic uses the sound key for the same info.
-*/
-void() trigger_cdtrack =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
- if (!self.count)
- {
- objerror("ERROR: trigger_cdtrack needs valid track number in count field");
- return;
- }
- InitTrigger();
- self.use = trigger_cdtrack_use;
-};
-///////////////////////////////////////////////////////////////
-//trigger_look (a.k.a. trigger_onlookat from NullPointPaladin!)
-///////////////////////////////////////////////////////////////
-void() onlookat_touch =
-{
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
- if (self.nextthink > time)
- {
- return; // allready been triggered
- }
-
- //added player view offset to make this more accurate to the player crosshairs
- local vector player_offset;
- player_offset = other.origin + other.view_ofs;
-
- makevectors(other.v_angle);
-
- //using speed to determine the reach of the trace
- if(!self.speed)
- self.speed = 500;
- traceline(player_offset, (player_offset + (v_forward * self.speed)), FALSE, other);
-
- if ((trace_ent.targetname == self.target))
- {
- // Play message if available
- if (self.message != "")
- {
- centerprint (other, self.message);
- }
- self.use = multi_trigger;
- SUB_UseTargets();
-
- if (self.noise != "")
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- else
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
-
- // added wait
- if (self.wait > 0)
- {
- self.think = multi_wait;
- self.nextthink = time + self.wait;
- }
- else
- { // we can't just remove (self) here, because this is a touch function
- // called wheil C code is looping through area links...
- self.touch = SUB_Null;
- self.nextthink = time + 0.1;
- self.think = SUB_Remove;
- }
- }
-};
-/*QUAKED trigger_look (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-This will trigger when a player is within the brush trigger and looks directly at a target entity.
-Use the first target key for the "looked at entity" and use the subsequent targets (2-4) to trigger other events.
-
-speed = Distance from player to search for trigger, adjust if the target is too far from the trigger (default 500 units)
-wait = Time between re-triggering (default 0)
-sounds = 0-3 are standard Quake trigger choices, 4 allows a custom sound, requires a path set in noise1 key
-noise1 = Path to custom sound. Use with sounds key set to 4 (e.g. fish/bite.wav)
-
-See manual for complete details. See pd_cutscenes sample map for example
-*/
-void() trigger_look =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- //play all the sounds available for a normal trigger
- if (self.sounds == 0)
- {
- precache_sound ("misc/null.wav");
- self.noise = "misc/null.wav";
- }
- else if (self.sounds == 1)
- {
- precache_sound ("misc/secret.wav");
- self.noise = "misc/secret.wav";
- }
- else if (self.sounds == 2)
- {
- precache_sound ("misc/talk.wav");
- self.noise = "misc/talk.wav";
- }
- else if (self.sounds == 3)
- {
- precache_sound ("misc/trigger1.wav");
- self.noise = "misc/trigger1.wav";
- }
- else if (self.sounds == 4)
- {
- if (!self.noise1) //dumptruck_ds
- {
- objerror ("no soundfile set in noise1!\n");
- remove(self);
- return;
- }
- else
- precache_sound (self.noise1);
- self.noise = self.noise1;
- }
-
- InitTrigger();
- self.touch = onlookat_touch;
-
- SUB_CheckWaiting();
-};
-
-void() trigger_target_change_use =
-{
- if (self.estate != STATE_ACTIVE) return;
-
- for (entity e = world; (e = find(e, targetname, self.target)); )
- {
- if (!self.cnt || self.cnt == 1)
- {
- e.target = self.message;
- }
- else if (self.cnt == 2)
- {
- e.target2 = self.message;
- }
- else if (self.cnt == 3)
- {
- e.target3 = self.message;
- }
- else if (self.cnt == 4)
- {
- e.target4 = self.message;
- }
- }
-};
-
-
-/*QUAKED trigger_changetarget (.5 .5 .5) ?
-Changes an entity's target field
-
-target = entity to change
-message = new value for target field
-cnt = target field to change, null defaults to target
-
-*/
-void() trigger_changetarget =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.use = trigger_target_change_use;
-};
-
-
-
-
-/*
-=============================================================
-
-target_setstate
-
-=============================================================
-*/
-float SETSTATE_STARTOFF = 1;
-float SETSTATE_CLOSEALLDOORS = 2;
-float SETSTATE_DONTRESETBUTTON = 4;
-
-float(entity e) entity_get_state = {
- if(e.classname == "func_door") return e.owner.estate;
- else return e.estate;
-};
-
-void(entity e, float state, float flags) entity_set_state = {
- float closealldoors;
-
- if(e.classname == "func_button") {
- if (state == STATE_ACTIVE) button_unlock(e, flags & SETSTATE_DONTRESETBUTTON);
- else button_lock(e);
- }
- else if(e.classname == "func_door") {
- if (flags & SETSTATE_CLOSEALLDOORS) closealldoors = 1;
-
- if (state == STATE_ACTIVE) door_estate_unlock(e, closealldoors);
- else door_estate_lock(e, closealldoors);
- }
- else e.estate = state;
-
- if (e.is_waiting > 0 && state == STATE_ACTIVE) {
- SUB_CallAsSelf(SUB_EndWaiting, e);
- }
-
- //if (e.touch && e.touch != SUB_Null) {
- // force_retouch = 2;
- //}
-};
-
-void(string matchstring, .string matchfield, float state, float flags) target_setstate_set_target = {
- local entity t;
-
- t = find (world, matchfield, matchstring);
- while (t != world) {
- if(state == -1){
- if(entity_get_state(t) == STATE_ACTIVE) entity_set_state(t, STATE_INACTIVE, flags);
- else entity_set_state(t, STATE_ACTIVE, flags);
- }
- else entity_set_state(t, state, flags);
-
- t = find (t, matchfield, matchstring);
- }
-};
-
-void(float state) target_setstate_set_alltargets = {
- if (self.target && self.target != "") {
- target_setstate_set_target(self.target, targetname, state, self.spawnflags);
- target_setstate_set_target(self.target, targetname2, state, self.spawnflags);
- target_setstate_set_target(self.target, targetname3, state, self.spawnflags);
- target_setstate_set_target(self.target, targetname4, state, self.spawnflags);
- }
- if (self.target2 && self.target2 != "") {
- target_setstate_set_target(self.target2, targetname, state, self.spawnflags);
- target_setstate_set_target(self.target2, targetname2, state, self.spawnflags);
- target_setstate_set_target(self.target2, targetname3, state, self.spawnflags);
- target_setstate_set_target(self.target2, targetname4, state, self.spawnflags);
- }
- if (self.target3 && self.target3 != "") {
- target_setstate_set_target(self.target3, targetname, state, self.spawnflags);
- target_setstate_set_target(self.target3, targetname2, state, self.spawnflags);
- target_setstate_set_target(self.target3, targetname3, state, self.spawnflags);
- target_setstate_set_target(self.target3, targetname4, state, self.spawnflags);
- }
- if (self.target4 && self.target4 != "") {
- target_setstate_set_target(self.target4, targetname, state, self.spawnflags);
- target_setstate_set_target(self.target4, targetname2, state, self.spawnflags);
- target_setstate_set_target(self.target4, targetname3, state, self.spawnflags);
- target_setstate_set_target(self.target4, targetname4, state, self.spawnflags);
- }
-};
-
-void() target_setstate_use = {
- local float state;
-
- if (self.style == 1) state = STATE_ACTIVE;
- else if (self.style == 2) state = STATE_INACTIVE;
- else state = -1;
-
- target_setstate_set_alltargets(state);
-
-};
-
-void() target_setstate_startoff_think = {
- target_setstate_set_alltargets(STATE_INACTIVE);
-};
-
-void() target_setstate = {
- self.use = target_setstate_use;
-
- if(self.spawnflags & SETSTATE_STARTOFF) {
- // wait a bit while doors finish being set up
- self.think = target_setstate_startoff_think;
- self.nextthink = time + 0.2;
- }
-};
-
-
-
-
-/*
-=============================================================
-
-trigger_filter
-
-=============================================================
-*/
-
-
-float FILTER_FIELD_STATE = 0;
-float FILTER_FIELD_HEALTH = 1;
-float FILTER_FIELD_WEAPON = 2;
-float FILTER_FIELD_FLAGS = 3;
-float FILTER_FIELD_SPAWNFLAGS = 4;
-float FILTER_FIELD_CLASSNAME = 5;
-float FILTER_FIELD_ESTATE = 6;
-float FILTER_FIELD_TARGETNAME = 8;
-float FILTER_FIELD_ITEMS = 10;
-float FILTER_FIELD_COUNT = 11;
-float FILTER_FIELD_CNT = 12;
-float FILTER_FIELD_TYPE = 13;
-
-
-float FILTER_FIELDTYPE_FLOAT = 0;
-float FILTER_FIELDTYPE_STRING = 1;
-float FILTER_FIELDTYPE_FLAG = 2;
-
-float FILTER_OP_EQUALS = 0;
-float FILTER_OP_LT = 1;
-float FILTER_OP_LTE = 2;
-float FILTER_OP_GT = 3;
-float FILTER_OP_GTE = 4;
-float FILTER_OP_BITMASK_AND = 5;
-float FILTER_OP_BITMASK_OR = 6;
-
-void() trigger_filter_use = {
- self.state = 0;
-
- if (self.estate != STATE_ACTIVE) return;
-
- entity targ;
- float targfloat;
- string targstring;
-
- float fieldtype, op, result;
-
- if (self.include != "") {
- targ = find(world, targetname, self.include);
- if (!targ) targ = find(world, targetname2, self.include);
- if (!targ) return;
- }
- else
- targ = activator;
-
- op = self.weapon;
-
- switch (self.style) {
- case FILTER_FIELD_STATE:
- fieldtype = FILTER_FIELDTYPE_FLOAT;
- targfloat = targ.state;
- break;
-
- case FILTER_FIELD_ESTATE:
- fieldtype = FILTER_FIELDTYPE_FLOAT;
- targfloat = targ.estate;
- break;
-
- case FILTER_FIELD_HEALTH:
- fieldtype = FILTER_FIELDTYPE_FLOAT;
- targfloat = targ.health;
- break;
-
- case FILTER_FIELD_COUNT:
- fieldtype = FILTER_FIELDTYPE_FLOAT;
- targfloat = targ.count;
- break;
-
- case FILTER_FIELD_CNT:
- fieldtype = FILTER_FIELDTYPE_FLOAT;
- targfloat = targ.cnt;
- break;
-
- case FILTER_FIELD_WEAPON:
- fieldtype = FILTER_FIELDTYPE_FLOAT;
- targfloat = targ.weapon;
- break;
-
- case FILTER_FIELD_FLAGS:
- fieldtype = FILTER_FIELDTYPE_FLAG;
- targfloat = targ.flags;
- break;
-
- case FILTER_FIELD_SPAWNFLAGS:
- fieldtype = FILTER_FIELDTYPE_FLAG;
- targfloat = targ.spawnflags;
- break;
-
- case FILTER_FIELD_ITEMS:
- fieldtype = FILTER_FIELDTYPE_FLAG;
- targfloat = targ.items;
- break;
-
- case FILTER_FIELD_CLASSNAME:
- fieldtype = FILTER_FIELDTYPE_STRING;
- targstring = targ.classname;
- break;
-
- case FILTER_FIELD_TARGETNAME:
- fieldtype = FILTER_FIELDTYPE_STRING;
- targstring = targ.targetname;
- break;
-
- case FILTER_FIELD_TYPE:
- fieldtype = FILTER_FIELDTYPE_STRING;
- targstring = targ.type;
- break;
- }
-
- if (fieldtype == FILTER_FIELDTYPE_FLOAT) {
- if (op == FILTER_OP_EQUALS) {if (targfloat == self.count) result = 1;}
- else if (op == FILTER_OP_LT) {if (targfloat < self.count) result = 1;}
- else if (op == FILTER_OP_LTE) {if (targfloat <= self.count) result = 1;}
- else if (op == FILTER_OP_GT) {if (targfloat > self.count) result = 1;}
- else if (op == FILTER_OP_GTE) {if (targfloat >= self.count) result = 1;}
- else if (op == FILTER_OP_BITMASK_AND) {if (targfloat & self.count) result = 1;}
- else if (op == FILTER_OP_BITMASK_OR) {if (targfloat | self.count) result = 1;}
- else {if (targfloat == self.count) result = 1;}
- }
- else if (fieldtype == FILTER_FIELDTYPE_FLAG) {
- if (op == FILTER_OP_EQUALS) {if (targfloat == self.aflag) result = 1;}
- else if (op == FILTER_OP_BITMASK_AND) {if (targfloat & self.aflag) result = 1;}
- else if (op == FILTER_OP_BITMASK_OR) {if (targfloat | self.aflag) result = 1;}
- else {if (targfloat == self.aflag) result = 1;}
- }
- else if (fieldtype == FILTER_FIELDTYPE_STRING) {
-
- if (targstring == self.type) result = 1;
- }
- else {
- objerror ("invalid fieldtype");
- return;
- }
-
- if (self.spawnflags & 1) result = 1 - result; // negate
-
- if (result) {
- self.state = 1;
-
- if (self.spawnflags & 2 && activator.owner) activator = activator.owner; // relay activator as owner
-
- SUB_UseTargets();
- if (other.classname == "trigger_everything" && other.spawnflags & 1) {
- if (other.wait) other.attack_finished = time + other.wait;
- }
-
- }
-};
-
-void() trigger_filter = {
- self.use = trigger_filter_use;
-
-};
-
-
-/*
-=============================================================
-
-trigger_everything
-
-=============================================================
-*/
-
-void() trigger_everything_touch = {
- if (self.estate != STATE_ACTIVE) return;
-
- if (time < self.attack_finished) return;
-
- activator = other;
-
- SUB_UseSpecificTarget(self.target, targetname);
-
- if (self.wait)
- if (!(self.spawnflags & 1)) self.attack_finished = time + self.wait;
-
-};
-
-void() trigger_everything = {
- InitTrigger();
-
- self.touch = trigger_everything_touch;
- SUB_CheckWaiting();
-};
-
-
-/*
-=============================================================
-
-target_setcount
-
-=============================================================
-*/
-
-void(string name, .string fld) target_setcount_set = {
- local entity t;
-
- t = find(world, fld, name);
-
- while (t) {
- if (self.style == 1)
- t.count += self.count;
- else
- t.count = self.count;
-
- t = find(t, fld, name);
- }
-};
-
-void() target_setcount_use = {
- if (self.target && self.target != "") {
- target_setcount_set(self.target, targetname);
- target_setcount_set(self.target, targetname2);
- target_setcount_set(self.target, targetname3);
- target_setcount_set(self.target, targetname4);
- }
- if (self.target2 && self.target2 != "") {
- target_setcount_set(self.target2, targetname);
- target_setcount_set(self.target2, targetname2);
- target_setcount_set(self.target2, targetname3);
- target_setcount_set(self.target2, targetname4);
- }
- if (self.target3 && self.target3 != "") {
- target_setcount_set(self.target3, targetname);
- target_setcount_set(self.target3, targetname2);
- target_setcount_set(self.target3, targetname3);
- target_setcount_set(self.target3, targetname4);
- }
- if (self.target4 && self.target4 != "") {
- target_setcount_set(self.target4, targetname);
- target_setcount_set(self.target4, targetname2);
- target_setcount_set(self.target4, targetname3);
- target_setcount_set(self.target4, targetname4);
- }
-
- if (self.spawnflags & 1) {
- if (self.style == 1)
- activator.count += activator.count;
- else
- activator.count = activator.count;
- }
-};
-
-void() target_setcount = {
- self.use = target_setcount_use;
-
-};
-
-void() trigger_monsterface_touch =
-{
- // only affect ground monsters
- if ( other.flags & (FL_MONSTER | FL_FLY | FL_SWIM) != FL_MONSTER )
- return;
-
- if (!visibleToOther(other.enemy)) { // enemy is hidden
- other.t_length = time + self.wait + 0.2; // don't dodge around, just go straight
- other.ideal_yaw = self.angles_y; // face where I want
- }
-}
-
-void() trigger_monsterface_init =
-{
- self.solid = SOLID_TRIGGER;
- setmodel (self, self.model); // set size and link into world
- self.movetype = MOVETYPE_NONE;
- self.modelindex = 0;
- self.model = "";
-
- if (self.angles == '0 0 0')
- self.angles = '0 360 0';
-
- self.touch = trigger_monsterface_touch;
-}
-
-/*QUAKED trigger_monsterface (.5 .0 .5)
-Running monsters that do not see their target and touch this will face in the direction of the trigger's angle instead of the unseen target.
-Use this trigger to make monsters leave their sniping spot and execute complex maneuvers.
-
-Keys:
-"angle" absolute angle in which the monster should face
-"targetname" entity name
-"wait" time to wait between retriggers
-*/
-void() trigger_monsterface =
-{
- if (SUB_Inhibit())
- return;
-
- trigger_monsterface_init();
- // InitTrigger();
-}

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/changelevel.qc

diff --git a/qc/triggers/changelevel.qc b/qc/triggers/changelevel.qc
new file mode 100644
index 0000000..2540298
--- /dev/null
+++ b/qc/triggers/changelevel.qc
@@ -0,0 +1,149 @@
+//==============================================================================
+// trigger_changelevel
+//==============================================================================
+
+const float DT_EXITOFF = 8;
+
+//----------------------------------------------------------------------
+void() execute_changelevel =
+{
+ used_exit = self;
+ local entity pos;
+
+ intermission_running = 1;
+
+ // enforce a wait time before allowing changelevel
+ if (deathmatch)
+ intermission_exittime = time + 5;
+ else
+ intermission_exittime = time + 2;
+
+ WriteByte (MSG_ALL, SVC_CDTRACK);
+ WriteByte (MSG_ALL, 3);
+ WriteByte (MSG_ALL, 3);
+
+ pos = FindIntermission ();
+
+ other = find (world, classname, "player");
+ while (other != world)
+ {
+ other.view_ofs = '0 0 0';
+ other.angles = other.v_angle = pos.mangle;
+ // turn this way immediately
+ other.fixangle = TRUE;
+ other.nextthink = time + 0.5;
+ other.takedamage = DAMAGE_NO;
+ other.solid = SOLID_NOT;
+ other.movetype = MOVETYPE_NONE;
+ other.modelindex = 0;
+ setorigin (other, pos.origin);
+ other = find (other, classname, "player");
+ fog_setFromEnt (other, pos);
+ }
+
+ // Drake -- dumptruck_ds
+ if (cutscene)
+ {
+ // If player was in a cutscene when the level ended,
+ // restore viewsize.
+ pos = find (world, classname, "camera");
+ if (pos)
+ {
+ local string val;
+
+ val = ftos (pos.cnt);
+ cvar_set ("viewsize", val);
+ }
+ }
+
+ WriteByte (MSG_ALL, SVC_INTERMISSION);
+};
+
+//----------------------------------------------------------------------
+void() changelevel_touch =
+{
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ if ((cvar("noexit") == 1) || ((cvar("noexit") == 2) &&
+ (mapname != "start")))
+ {
+ T_Damage (other, self, self, 50000);
+ return;
+ }
+
+ if (coop || deathmatch)
+ {
+ bprint (other.netname);
+ bprint (" exited the level\n");
+ }
+
+ nextmap = self.map;
+ SUB_UseTargets ();
+
+ if ((self.spawnflags & 16) && (deathmatch == 0))
+ {
+ // use info_player_start2 -- dumptruck_ds
+ sigil_touch2 ();
+ }
+
+ if ((self.spawnflags & 1) && (deathmatch == 0))
+ {
+ // NO_INTERMISSION
+ GotoNextMap ();
+ return;
+ }
+
+ self.touch = SUB_Null;
+
+ // we can't move people right now, because touch functions are called
+ // in the middle of C movement code, so set a think time to do it
+ self.think = execute_changelevel;
+ self.nextthink = time + 0.1;
+};
+
+//----------------------------------------------------------------------
+// dumptruck_ds based on hipnotic blocker_use
+//----------------------------------------------------------------------
+void() dt_exit_toggle =
+{
+ if (self.estate != STATE_ACTIVE)
+ {
+ self.is_waiting = 0;
+ self.estate = STATE_ACTIVE;
+ }
+ else
+ {
+ self.is_waiting = 1;
+ self.estate = STATE_INACTIVE;
+ }
+};
+
+/*QUAKED trigger_changelevel (0.5 0.5 0.5) ? NO_INTERMISSION X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+
+When the player touches this, he gets sent to the map listed in the "map" variable. Unless the NO_INTERMISSION flag is set, the view will go to the info_intermission spot and display stats.
+*/
+void() trigger_changelevel =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ // dumptruck_ds
+ if (self.spawnflags & DT_EXITOFF)
+ self.is_waiting = 1;
+
+ SUB_CheckWaiting ();
+ self.use = dt_exit_toggle;
+
+ if (!self.map)
+ objerror ("changelevel trigger doesn't have map");
+
+ InitTrigger ();
+ self.flags = self.flags | FL_NOCENTERPRINT;
+ self.touch = changelevel_touch;
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/changemusic.qc

diff --git a/qc/triggers/changemusic.qc b/qc/triggers/changemusic.qc
new file mode 100644
index 0000000..0aec200
--- /dev/null
+++ b/qc/triggers/changemusic.qc
@@ -0,0 +1,94 @@
+//==============================================================================
+// trigger_changemusic, trigger_cdtrack
+//==============================================================================
+
+void(float newtrack) changemusic =
+{
+ // changing the field via a pointer
+ *world_sounds = newtrack;
+
+ // world.sounds has now been changed via our pointer, newly connecting
+ // players (like those connecting after the game is loaded) will get
+ // sent the new cd track's number.
+
+ // let everyone currently on the server know.
+ WriteByte(MSG_ALL, SVC_CDTRACK);
+ // initial track
+ WriteByte(MSG_ALL, newtrack);
+ // looped track... should generally be set the same as the initial
+ // track as most engines ignore it entirely so it might as well be
+ // same for those that care.
+ WriteByte(MSG_ALL, newtrack);
+};
+
+// thanks to jleww via changemusic.rar --dumptruck_ds
+void() trigger_changemusic_touch =
+{
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ if (!(other.flags & FL_CLIENT))
+ return;
+
+ changemusic (self.sounds);
+ self.touch = SUB_Null;
+ self.nextthink = (time + 0.1);
+ self.think = SUB_Remove;
+};
+
+/*QUAKED trigger_changemusic (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+A trigger brush that changes the currently playing music track. The number of the track to play goes in the sounds key (just like worldspawn). */
+void() trigger_changemusic =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.sounds)
+ {
+ // splitting the error string up, FTEQCC does implicit
+ // string concatenation -- CEV
+ objerror ("ERROR: trigger_changemusic needs valid track"
+ " number in sounds field");
+ return;
+ }
+
+ InitTrigger ();
+ self.touch = trigger_changemusic_touch;
+
+ SUB_CheckWaiting ();
+};
+
+
+// point entity version uses count for music track number for backwards
+// compatibly in Adoria mod -- dumptruck_ds
+void() trigger_cdtrack_use =
+{
+ changemusic (self.count);
+};
+
+/*QUAKED trigger_cdtrack (.7 .7 .7) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+A point entity that changes the currently playing music track when triggered. The number of the track to play goes in the count key. e.g. 32 for track32.ogg See manual trigger_changemusic for more information on formats and more.
+
+NOTE: the track number uses the count key here but trigger_changemusic uses the sound key for the same info.
+*/
+void() trigger_cdtrack =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.count)
+ {
+ // splitting the error string up, FTEQCC does implicit
+ // string concatenation -- CEV
+ objerror ("ERROR: trigger_cdtrack needs valid track number"
+ " in count field");
+ return;
+ }
+
+ InitTrigger ();
+ self.use = trigger_cdtrack_use;
+};
+

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/changetarget.qc

diff --git a/qc/triggers/changetarget.qc b/qc/triggers/changetarget.qc
new file mode 100644
index 0000000..2cf1557
--- /dev/null
+++ b/qc/triggers/changetarget.qc
@@ -0,0 +1,38 @@
+//==============================================================================
+// trigger_changetarget
+//==============================================================================
+
+void() trigger_target_change_use =
+{
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ for (entity e = world; (e = find (e, targetname, self.target)); )
+ {
+ if (!self.cnt || self.cnt == 1)
+ e.target = self.message;
+ else if (self.cnt == 2)
+ e.target2 = self.message;
+ else if (self.cnt == 3)
+ e.target3 = self.message;
+ else if (self.cnt == 4)
+ e.target4 = self.message;
+ }
+};
+
+/*QUAKED trigger_changetarget (.5 .5 .5) ?
+Changes an entity's target field
+
+target = entity to change
+message = new value for target field
+cnt = target field to change, null defaults to target
+
+*/
+void() trigger_changetarget =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.use = trigger_target_change_use;
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/counter.qc

diff --git a/qc/triggers/counter.qc b/qc/triggers/counter.qc
new file mode 100644
index 0000000..b0efb8b
--- /dev/null
+++ b/qc/triggers/counter.qc
@@ -0,0 +1,63 @@
+//==============================================================================
+// trigger_counter
+//==============================================================================
+
+//----------------------------------------------------------------------
+void() counter_use =
+{
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ self.count = self.count - 1;
+ if (self.count < 0)
+ return;
+
+ if (self.count != 0)
+ {
+ if (activator.classname == "player" &&
+ (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
+ {
+ if (self.count >= 4)
+ centerprint (activator, "There are more "
+ "to go...");
+ else if (self.count == 3)
+ centerprint (activator, "Only 3 more to go...");
+ else if (self.count == 2)
+ centerprint (activator, "Only 2 more to go...");
+ else
+ centerprint (activator, "Only 1 more to go...");
+ }
+ return;
+ }
+
+ if (activator.classname == "player" &&
+ (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
+ {
+ centerprint(activator, "Sequence completed!");
+ }
+
+ self.enemy = activator;
+ multi_trigger ();
+};
+
+/*QUAKED trigger_counter (.5 .5 .5) ? nomessage X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+
+Acts as an intermediary for an action that takes multiple inputs.
+
+If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
+
+After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
+*/
+void() trigger_counter =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.wait = -1;
+
+ if (!self.count)
+ self.count = 2;
+
+ self.use = counter_use;
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/filter.qc

diff --git a/qc/triggers/filter.qc b/qc/triggers/filter.qc
new file mode 100644
index 0000000..f008c1f
--- /dev/null
+++ b/qc/triggers/filter.qc
@@ -0,0 +1,226 @@
+//==============================================================================
+// trigger_filter
+//==============================================================================
+
+const float FILTER_FIELD_STATE = 0;
+const float FILTER_FIELD_HEALTH = 1;
+const float FILTER_FIELD_WEAPON = 2;
+const float FILTER_FIELD_FLAGS = 3;
+const float FILTER_FIELD_SPAWNFLAGS = 4;
+const float FILTER_FIELD_CLASSNAME = 5;
+const float FILTER_FIELD_ESTATE = 6;
+const float FILTER_FIELD_TARGETNAME = 8;
+const float FILTER_FIELD_ITEMS = 10;
+const float FILTER_FIELD_COUNT = 11;
+const float FILTER_FIELD_CNT = 12;
+const float FILTER_FIELD_TYPE = 13;
+
+const float FILTER_FIELDTYPE_FLOAT = 0;
+const float FILTER_FIELDTYPE_STRING = 1;
+const float FILTER_FIELDTYPE_FLAG = 2;
+
+const float FILTER_OP_EQUALS = 0;
+const float FILTER_OP_LT = 1;
+const float FILTER_OP_LTE = 2;
+const float FILTER_OP_GT = 3;
+const float FILTER_OP_GTE = 4;
+const float FILTER_OP_BITMASK_AND = 5;
+const float FILTER_OP_BITMASK_OR = 6;
+
+void() trigger_filter_use =
+{
+ self.state = 0;
+
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ entity targ;
+ float fieldtype, op, result, targfloat;
+ string targstring;
+
+ targfloat = fieldtype = op = result = 0;
+ targstring = "";
+
+ if (self.include != "")
+ {
+ targ = find (world, targetname, self.include);
+ if (!targ)
+ targ = find (world, targetname2, self.include);
+ if (!targ)
+ return;
+ }
+ else
+ {
+ targ = activator;
+ }
+
+ op = self.weapon;
+
+ switch (self.style)
+ {
+ case FILTER_FIELD_STATE:
+ fieldtype = FILTER_FIELDTYPE_FLOAT;
+ targfloat = targ.state;
+ break;
+
+ case FILTER_FIELD_ESTATE:
+ fieldtype = FILTER_FIELDTYPE_FLOAT;
+ targfloat = targ.estate;
+ break;
+
+ case FILTER_FIELD_HEALTH:
+ fieldtype = FILTER_FIELDTYPE_FLOAT;
+ targfloat = targ.health;
+ break;
+
+ case FILTER_FIELD_COUNT:
+ fieldtype = FILTER_FIELDTYPE_FLOAT;
+ targfloat = targ.count;
+ break;
+
+ case FILTER_FIELD_CNT:
+ fieldtype = FILTER_FIELDTYPE_FLOAT;
+ targfloat = targ.cnt;
+ break;
+
+ case FILTER_FIELD_WEAPON:
+ fieldtype = FILTER_FIELDTYPE_FLOAT;
+ targfloat = targ.weapon;
+ break;
+
+ case FILTER_FIELD_FLAGS:
+ fieldtype = FILTER_FIELDTYPE_FLAG;
+ targfloat = targ.flags;
+ break;
+
+ case FILTER_FIELD_SPAWNFLAGS:
+ fieldtype = FILTER_FIELDTYPE_FLAG;
+ targfloat = targ.spawnflags;
+ break;
+
+ case FILTER_FIELD_ITEMS:
+ fieldtype = FILTER_FIELDTYPE_FLAG;
+ targfloat = targ.items;
+ break;
+
+ case FILTER_FIELD_CLASSNAME:
+ fieldtype = FILTER_FIELDTYPE_STRING;
+ targstring = targ.classname;
+ break;
+
+ case FILTER_FIELD_TARGETNAME:
+ fieldtype = FILTER_FIELDTYPE_STRING;
+ targstring = targ.targetname;
+ break;
+
+ case FILTER_FIELD_TYPE:
+ fieldtype = FILTER_FIELDTYPE_STRING;
+ targstring = targ.type;
+ break;
+ }
+
+ if (fieldtype == FILTER_FIELDTYPE_FLOAT)
+ {
+ if (op == FILTER_OP_EQUALS)
+ {
+ if (targfloat == self.count)
+ result = 1;
+ }
+ else if (op == FILTER_OP_LT)
+ {
+ if (targfloat < self.count)
+ result = 1;
+ }
+ else if (op == FILTER_OP_LTE)
+ {
+ if (targfloat <= self.count)
+ result = 1;
+ }
+ else if (op == FILTER_OP_GT)
+ {
+ if (targfloat > self.count)
+ result = 1;
+ }
+ else if (op == FILTER_OP_GTE)
+ {
+ if (targfloat >= self.count)
+ result = 1;
+ }
+ else if (op == FILTER_OP_BITMASK_AND)
+ {
+ if (targfloat & self.count)
+ result = 1;
+ }
+ else if (op == FILTER_OP_BITMASK_OR)
+ {
+ if (targfloat | self.count)
+ result = 1;
+ }
+ else
+ {
+ if (targfloat == self.count)
+ result = 1;
+ }
+ }
+ else if (fieldtype == FILTER_FIELDTYPE_FLAG)
+ {
+ if (op == FILTER_OP_EQUALS)
+ {
+ if (targfloat == self.aflag)
+ result = 1;
+ }
+ else if (op == FILTER_OP_BITMASK_AND)
+ {
+ if (targfloat & self.aflag)
+ result = 1;
+ }
+ else if (op == FILTER_OP_BITMASK_OR)
+ {
+ if (targfloat | self.aflag)
+ result = 1;
+ }
+ else
+ {
+ if (targfloat == self.aflag)
+ result = 1;
+ }
+ }
+ else if (fieldtype == FILTER_FIELDTYPE_STRING)
+ {
+
+ if (targstring == self.type)
+ result = 1;
+ }
+ else
+ {
+ objerror ("invalid fieldtype");
+ return;
+ }
+
+ if (self.spawnflags & 1)
+ // negate
+ result = 1 - result;
+
+ if (result)
+ {
+ self.state = 1;
+
+ // relay activator as owner
+ if (self.spawnflags & 2 && activator.owner)
+ activator = activator.owner;
+
+ SUB_UseTargets ();
+ if (other.classname == "trigger_everything" &&
+ other.spawnflags & 1)
+ {
+ if (other.wait)
+ other.attack_finished = time + other.wait;
+ }
+
+ }
+};
+
+void() trigger_filter = {
+ self.use = trigger_filter_use;
+
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/heal.qc

diff --git a/qc/triggers/heal.qc b/qc/triggers/heal.qc
index 52c1912..4e60b69 100644
--- a/qc/triggers/heal.qc
+++ b/qc/triggers/heal.qc
@@ -7,6 +7,16 @@

// was in dtmisc.qc -- CEV

+// fields for healing trigger
+.float heal_timer;
+.float heal_amount;
+.float health_max;
+
+// Constants for the healing trigger
+float HEAL_START_ON = 1;
+float HEAL_PLAYER_ONLY = 2;
+float HEAL_MONSTER_ONLY = 4;
+
//----------------------------------------------------------------------
void() heal_think =
{

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/hurt.qc

diff --git a/qc/triggers/hurt.qc b/qc/triggers/hurt.qc
new file mode 100644
index 0000000..679ed19
--- /dev/null
+++ b/qc/triggers/hurt.qc
@@ -0,0 +1,89 @@
+//==============================================================================
+// trigger_hurt
+//==============================================================================
+
+//----------------------------------------------------------------------
+
+// 1998-07-03 hurt_touch fix by Robert Field start
+//
+// triggers.qc
+//
+.float hurt_together_time;
+.float hurt_nextthink;
+// 1998-07-03 hurt_touch fix by Robert Field end
+
+//----------------------------------------------------------------------
+
+// from hip_rotate.qc by Jim Dose' 10/17/96
+void(entity ent, float amount) hurt_setdamage =
+{
+ ent.dmg = amount;
+
+ if (!amount)
+ ent.solid = SOLID_NOT;
+ else
+ ent.solid = SOLID_TRIGGER;
+
+ ent.nextthink = -1;
+};
+
+//----------------------------------------------------------------------
+
+// 1998-07-03 hurt_touch fix by Robert Field start
+/*
+void() hurt_on =
+{
+ self.solid = SOLID_TRIGGER;
+ self.nextthink = -1;
+};
+*/
+// 1998-07-03 hurt_touch fix by Robert Field end
+
+void() hurt_touch =
+{
+
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ // from Copper -- dumptruck_ds
+ if (other.movetype == MOVETYPE_NOCLIP)
+ return;
+
+ if (other.takedamage && self.nextthink < time)
+ {
+ // 1998-07-03 hurt_touch fix by Robert Field start
+ // self.solid = SOLID_NOT;
+ if (time != self.hurt_together_time)
+ if (time < self.hurt_nextthink)
+ return;
+ // 1998-07-03 hurt_touch fix by Robert Field end
+ T_Damage (other, self, self, self.dmg);
+ // 1998-07-03 hurt_touch fix by Robert Field start
+ // self.think = hurt_on;
+ // self.nextthink = time + 1;
+ self.hurt_together_time = time;
+ self.hurt_nextthink = time + 1;
+ // 1998-07-03 hurt_touch fix by Robert Field end
+ }
+
+ return;
+};
+
+/*QUAKED trigger_hurt (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+Any object touching this will be hurt
+set dmg to damage amount
+defalt dmg = 5
+*/
+void() trigger_hurt =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ InitTrigger ();
+ self.touch = hurt_touch;
+ if (!self.dmg)
+ self.dmg = 5;
+
+ SUB_CheckWaiting ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/look.qc

diff --git a/qc/triggers/look.qc b/qc/triggers/look.qc
new file mode 100644
index 0000000..73a94f7
--- /dev/null
+++ b/qc/triggers/look.qc
@@ -0,0 +1,124 @@
+//==============================================================================
+// trigger_look
+//==============================================================================
+
+///////////////////////////////////////////////////////////////
+//trigger_look (a.k.a. trigger_onlookat from NullPointPaladin!)
+///////////////////////////////////////////////////////////////
+void() onlookat_touch =
+{
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ if (self.nextthink > time)
+ // allready been triggered
+ return;
+
+ // added player view offset to make this more accurate
+ // to the player crosshairs
+ local vector player_offset;
+ player_offset = other.origin + other.view_ofs;
+
+ makevectors (other.v_angle);
+
+ // using speed to determine the reach of the trace
+ if (!self.speed)
+ self.speed = 500;
+
+ traceline (player_offset, (player_offset + (v_forward * self.speed)),
+ FALSE, other);
+
+ if (trace_ent.targetname == self.target)
+ {
+ // Play message if available
+ if (self.message != "")
+ centerprint (other, self.message);
+
+ self.use = multi_trigger;
+ SUB_UseTargets ();
+
+ if (self.noise != "")
+ sound (self, CHAN_VOICE, self.noise, 1,
+ ATTN_NORM);
+ else
+ sound (self, CHAN_VOICE, self.noise1, 1,
+ ATTN_NORM);
+
+ // added wait
+ if (self.wait > 0)
+ {
+ self.think = multi_wait;
+ self.nextthink = time + self.wait;
+ }
+ else
+ {
+ // we can't just remove (self) here, because this
+ // is a touch function called wheil C code is looping
+ // through area links...
+ self.touch = SUB_Null;
+ self.nextthink = time + 0.1;
+ self.think = SUB_Remove;
+ }
+ }
+};
+
+/*QUAKED trigger_look (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+This will trigger when a player is within the brush trigger and looks directly at a target entity.
+Use the first target key for the "looked at entity" and use the subsequent targets (2-4) to trigger other events.
+
+speed = Distance from player to search for trigger, adjust if the target is too far from the trigger (default 500 units)
+wait = Time between re-triggering (default 0)
+sounds = 0-3 are standard Quake trigger choices, 4 allows a custom sound, requires a path set in noise1 key
+noise1 = Path to custom sound. Use with sounds key set to 4 (e.g. fish/bite.wav)
+
+See manual for complete details. See pd_cutscenes sample map for example
+*/
+void() trigger_look =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ // play all the sounds available for a normal trigger
+ if (self.sounds == 0)
+ {
+ precache_sound ("misc/null.wav");
+ self.noise = "misc/null.wav";
+ }
+ else if (self.sounds == 1)
+ {
+ precache_sound ("misc/secret.wav");
+ self.noise = "misc/secret.wav";
+ }
+ else if (self.sounds == 2)
+ {
+ precache_sound ("misc/talk.wav");
+ self.noise = "misc/talk.wav";
+ }
+ else if (self.sounds == 3)
+ {
+ precache_sound ("misc/trigger1.wav");
+ self.noise = "misc/trigger1.wav";
+ }
+ else if (self.sounds == 4)
+ {
+ if (!self.noise1)
+ {
+ // dumptruck_ds
+ objerror ("no soundfile set in noise1!\n");
+ remove (self);
+ return;
+ }
+ else
+ {
+ precache_sound (self.noise1);
+ }
+ self.noise = self.noise1;
+ }
+
+ InitTrigger ();
+ self.touch = onlookat_touch;
+
+ SUB_CheckWaiting ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/misc.qc

diff --git a/qc/triggers/misc.qc b/qc/triggers/misc.qc
new file mode 100644
index 0000000..7f89031
--- /dev/null
+++ b/qc/triggers/misc.qc
@@ -0,0 +1,506 @@
+//==============================================================================
+// TRIGGERS.QC
+//==============================================================================
+
+//----------------------------------------------------------------------
+void() trigger_reactivate =
+{
+ self.solid = SOLID_TRIGGER;
+};
+
+float SPAWNFLAG_NOMESSAGE = 1;
+float SPAWNFLAG_NOTOUCH = 1;
+float SPAWNFLAG_TURNS_OFF = 2; // used for Wait for retrigger spawnflag
+
+//----------------------------------------------------------------------
+// the wait time has passed, so set back up for another activation
+//----------------------------------------------------------------------
+void() multi_wait =
+{
+ if (self.max_health)
+ {
+ self.health = self.max_health;
+ self.takedamage = DAMAGE_YES;
+ self.solid = SOLID_BBOX;
+ }
+};
+
+//----------------------------------------------------------------------
+// the trigger was just touched/killed/used
+// self.enemy should be set to the activator so it can be held through a
+// delay so wait for the delay time before firing
+//----------------------------------------------------------------------
+void() multi_trigger =
+{
+ if (self.nextthink > time)
+ {
+ // allready been triggered
+ return;
+ }
+
+ if (self.classname == "trigger_secret")
+ {
+ if (self.enemy.classname != "player")
+ return;
+ if (cutscene)
+ // Don't activate in cutscene mode
+ return;
+ found_secrets = found_secrets + 1;
+ WriteByte (MSG_ALL, SVC_FOUNDSECRET);
+ }
+
+ if (self.noise != "")
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+
+ // don't trigger again until reset
+ self.takedamage = DAMAGE_NO;
+
+ activator = self.enemy;
+
+ SUB_UseTargets ();
+
+ if (self.wait > 0)
+ {
+ self.think = multi_wait;
+ self.nextthink = time + self.wait;
+ if (self.spawnflags & SPAWNFLAG_TURNS_OFF)
+ {
+ self.is_waiting = 1;
+ SUB_CheckWaiting ();
+ }
+ }
+ else
+ {
+ // we can't just remove (self) here, because this is a touch
+ // function called wheil C code is looping through area links...
+ self.touch = SUB_Null;
+ self.nextthink = time + 0.1;
+ self.think = SUB_Remove;
+ }
+};
+
+//----------------------------------------------------------------------
+// dumptruck_ds
+//----------------------------------------------------------------------
+void() multi_killed =
+{
+ // Supa, restore health and do nothing if we're still waiting to
+ // be activated
+ if (self.estate != STATE_ACTIVE)
+ {
+ self.health = self.max_health; // nyah nyah~!
+ self.takedamage = DAMAGE_YES;
+ self.solid = SOLID_BBOX;
+
+ return;
+ }
+
+ self.enemy = damage_attacker;
+ multi_trigger ();
+};
+
+//----------------------------------------------------------------------
+// dumptruck_ds
+//----------------------------------------------------------------------
+void() multi_use =
+{
+ self.enemy = activator;
+ multi_trigger ();
+};
+
+//----------------------------------------------------------------------
+// dumptruck_ds
+//----------------------------------------------------------------------
+void() multi_touch =
+{
+
+ if (other.classname != "player")
+ return;
+
+ // from Copper -- dumptruck_ds
+ if (other.movetype == MOVETYPE_NOCLIP)
+ return;
+
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ // if the trigger has an angles field, check player's facing direction
+ if (self.movedir != '0 0 0')
+ {
+ makevectors (other.angles);
+ if (v_forward * self.movedir < 0)
+ // not facing the right way
+ return;
+ }
+
+ self.enemy = other;
+ multi_trigger ();
+};
+
+/*QUAKED trigger_multiple (.5 .5 .5) ? notouch WAIT_FOR_RETRIGGER X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+
+Variable sized repeatable trigger. Must be targeted at one or more entities. If "health" is set, the trigger must be killed to activate each time.
+If "WAIT_FOR_RETRIGGER" is set, it must be triggered by another entity before it can trigger again.
+If "delay" is set, the trigger waits some time after activating before firing.
+"wait" : Seconds between triggerings. (.2 default)
+If notouch is set, the trigger is only fired by other entities, not by touching.
+NOTOUCH has been obsoleted by trigger_relay!
+sounds
+1) secret
+2) beep beep
+3) large switch
+set "message" to text string
+"is_waiting" : If set to 1, this trigger will do nothing until another trigger activates it
+*/
+void() trigger_multiple =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (self.sounds == 1)
+ {
+ precache_sound ("misc/secret.wav");
+ self.noise = "misc/secret.wav";
+ }
+ else if (self.sounds == 2)
+ {
+ precache_sound ("misc/talk.wav");
+ self.noise = "misc/talk.wav";
+ }
+ else if (self.sounds == 3)
+ {
+ precache_sound ("misc/trigger1.wav");
+ self.noise = "misc/trigger1.wav";
+ }
+
+ if (!self.wait)
+ {
+ self.wait = 0.2;
+ }
+ else if (self.wait < 0 && (self.spawnflags & SPAWNFLAG_TURNS_OFF))
+ {
+ objerror("Wait for retrigger and negative wait don't"
+ " make sense");
+ }
+
+ self.use = multi_use;
+
+ InitTrigger ();
+
+ if (self.health)
+ {
+ if (self.spawnflags & SPAWNFLAG_NOTOUCH)
+ objerror ("health and notouch don't make sense\n");
+ self.max_health = self.health;
+ self.th_die = multi_killed;
+ self.takedamage = DAMAGE_YES;
+ self.solid = SOLID_BBOX;
+ // make sure it links into the world
+ setorigin (self, self.origin);
+ }
+ else
+ {
+ if (!(self.spawnflags & SPAWNFLAG_NOTOUCH))
+ {
+ self.touch = multi_touch;
+ }
+ }
+
+ SUB_CheckWaiting ();
+};
+
+/*QUAKED trigger_once (.5 .5 .5) ? notouch X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+
+Variable sized trigger. Triggers once, then removes itself. You must set the key "target" to the name of another object in the level that has a matching
+"targetname". If "health" is set, the trigger must be killed to activate.
+If notouch is set, the trigger is only fired by other entities, not by touching.
+if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
+if "angle" is set, the trigger will only fire when someone is facing the direction of the angle. Use "360" for an angle of 0.
+sounds
+1) secret
+2) beep beep
+3) large switch
+set "message" to text string
+*/
+void() trigger_once =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.wait = -1;
+ trigger_multiple ();
+};
+
+//=============================================================================
+
+/*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+This fixed size trigger cannot be touched, it can only be fired by other events. It can contain killtargets, targets, delays, and messages.
+*/
+void() trigger_relay =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.use = SUB_UseTargets;
+};
+
+//----------------------------------------------------------------------
+// target_setstate
+//----------------------------------------------------------------------
+float SETSTATE_STARTOFF = 1;
+float SETSTATE_CLOSEALLDOORS = 2;
+float SETSTATE_DONTRESETBUTTON = 4;
+
+//----------------------------------------------------------------------
+float(entity e) entity_get_state =
+{
+ if (e.classname == "func_door")
+ return e.owner.estate;
+ else
+ return e.estate;
+};
+
+//----------------------------------------------------------------------
+void(entity e, float state, float flags) entity_set_state =
+{
+ float closealldoors = 0;
+
+ if (e.classname == "func_button")
+ {
+ if (state == STATE_ACTIVE)
+ button_unlock (e, flags & SETSTATE_DONTRESETBUTTON);
+ else
+ button_lock (e);
+ }
+ else if (e.classname == "func_door")
+ {
+ if (flags & SETSTATE_CLOSEALLDOORS)
+ closealldoors = 1;
+
+ if (state == STATE_ACTIVE)
+ door_estate_unlock (e, closealldoors);
+ else
+ door_estate_lock (e, closealldoors);
+ }
+ else
+ {
+ e.estate = state;
+ }
+
+ if (e.is_waiting > 0 && state == STATE_ACTIVE)
+ {
+ SUB_CallAsSelf (SUB_EndWaiting, e);
+ }
+
+ // if (e.touch && e.touch != SUB_Null)
+ // {
+ // force_retouch = 2;
+ // }
+};
+
+//----------------------------------------------------------------------
+void(string matchstring, .string matchfield, float state, float flags)
+ target_setstate_set_target =
+{
+ local entity t;
+
+ t = find (world, matchfield, matchstring);
+ while (t != world)
+ {
+ if (state == -1)
+ {
+ if (entity_get_state(t) == STATE_ACTIVE)
+ entity_set_state (t, STATE_INACTIVE, flags);
+ else
+ entity_set_state (t, STATE_ACTIVE, flags);
+ }
+ else
+ {
+ entity_set_state (t, state, flags);
+ }
+
+ t = find (t, matchfield, matchstring);
+ }
+};
+
+//----------------------------------------------------------------------
+void(float state) target_setstate_set_alltargets =
+{
+ if (self.target && self.target != "")
+ {
+ target_setstate_set_target(self.target, targetname,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target, targetname2,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target, targetname3,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target, targetname4,
+ state, self.spawnflags);
+ }
+ if (self.target2 && self.target2 != "")
+ {
+ target_setstate_set_target(self.target2, targetname,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target2, targetname2,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target2, targetname3,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target2, targetname4,
+ state, self.spawnflags);
+ }
+ if (self.target3 && self.target3 != "")
+ {
+ target_setstate_set_target(self.target3, targetname,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target3, targetname2,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target3, targetname3,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target3, targetname4,
+ state, self.spawnflags);
+ }
+ if (self.target4 && self.target4 != "")
+ {
+ target_setstate_set_target(self.target4, targetname,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target4, targetname2,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target4, targetname3,
+ state, self.spawnflags);
+ target_setstate_set_target(self.target4, targetname4,
+ state, self.spawnflags);
+ }
+};
+
+//----------------------------------------------------------------------
+void() target_setstate_use =
+{
+ local float state;
+
+ if (self.style == 1)
+ state = STATE_ACTIVE;
+ else if (self.style == 2)
+ state = STATE_INACTIVE;
+ else
+ state = -1;
+
+ target_setstate_set_alltargets (state);
+};
+
+//----------------------------------------------------------------------
+void() target_setstate_startoff_think =
+{
+ target_setstate_set_alltargets (STATE_INACTIVE);
+};
+
+//----------------------------------------------------------------------
+void() target_setstate =
+{
+ self.use = target_setstate_use;
+
+ if (self.spawnflags & SETSTATE_STARTOFF)
+ {
+ // wait a bit while doors finish being set up
+ self.think = target_setstate_startoff_think;
+ self.nextthink = time + 0.2;
+ }
+};
+
+//----------------------------------------------------------------------
+// trigger_everything
+//----------------------------------------------------------------------
+void() trigger_everything_touch =
+{
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ if (time < self.attack_finished)
+ return;
+
+ activator = other;
+
+ SUB_UseSpecificTarget (self.target, targetname);
+
+ if (self.wait)
+ if (!(self.spawnflags & 1))
+ self.attack_finished = time + self.wait;
+};
+
+//----------------------------------------------------------------------
+void() trigger_everything = {
+ InitTrigger ();
+
+ self.touch = trigger_everything_touch;
+ SUB_CheckWaiting ();
+};
+
+//----------------------------------------------------------------------
+// target_setcount
+//----------------------------------------------------------------------
+void(string name, .string fld) target_setcount_set =
+{
+ local entity t;
+
+ t = find (world, fld, name);
+
+ while (t)
+ {
+ if (self.style == 1)
+ t.count += self.count;
+ else
+ t.count = self.count;
+
+ t = find (t, fld, name);
+ }
+};
+
+//----------------------------------------------------------------------
+void() target_setcount_use =
+{
+ if (self.target && self.target != "")
+ {
+ target_setcount_set (self.target, targetname);
+ target_setcount_set (self.target, targetname2);
+ target_setcount_set (self.target, targetname3);
+ target_setcount_set (self.target, targetname4);
+ }
+ if (self.target2 && self.target2 != "")
+ {
+ target_setcount_set (self.target2, targetname);
+ target_setcount_set (self.target2, targetname2);
+ target_setcount_set (self.target2, targetname3);
+ target_setcount_set (self.target2, targetname4);
+ }
+ if (self.target3 && self.target3 != "")
+ {
+ target_setcount_set (self.target3, targetname);
+ target_setcount_set (self.target3, targetname2);
+ target_setcount_set (self.target3, targetname3);
+ target_setcount_set (self.target3, targetname4);
+ }
+ if (self.target4 && self.target4 != "")
+ {
+ target_setcount_set (self.target4, targetname);
+ target_setcount_set (self.target4, targetname2);
+ target_setcount_set (self.target4, targetname3);
+ target_setcount_set (self.target4, targetname4);
+ }
+
+ if (self.spawnflags & 1)
+ {
+ if (self.style == 1)
+ activator.count += activator.count;
+ else
+ activator.count = activator.count;
+ }
+};
+
+//----------------------------------------------------------------------
+void() target_setcount =
+{
+ self.use = target_setcount_use;
+
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/monsterface.qc

diff --git a/qc/triggers/monsterface.qc b/qc/triggers/monsterface.qc
new file mode 100644
index 0000000..5aa56a4
--- /dev/null
+++ b/qc/triggers/monsterface.qc
@@ -0,0 +1,53 @@
+//==============================================================================
+// trigger_monsterface
+//==============================================================================
+
+void() trigger_monsterface_touch =
+{
+ // only affect ground monsters
+ if (other.flags & (FL_MONSTER | FL_FLY | FL_SWIM) != FL_MONSTER)
+ return;
+
+ if (!visibleToOther(other.enemy))
+ {
+ // enemy is hidden
+ // don't dodge around, just go straight
+ other.t_length = time + self.wait + 0.2;
+ // face where I want
+ other.ideal_yaw = self.angles_y;
+ }
+};
+
+void() trigger_monsterface_init =
+{
+ self.solid = SOLID_TRIGGER;
+ // set size and link into world
+ setmodel (self, self.model);
+ self.movetype = MOVETYPE_NONE;
+ self.modelindex = 0;
+ self.model = "";
+
+ if (self.angles == '0 0 0')
+ self.angles = '0 360 0';
+
+ self.touch = trigger_monsterface_touch;
+};
+
+/*QUAKED trigger_monsterface (.5 .0 .5)
+Running monsters that do not see their target and touch this will face in the direction of the trigger's angle instead of the unseen target.
+Use this trigger to make monsters leave their sniping spot and execute complex maneuvers.
+
+Keys:
+"angle" absolute angle in which the monster should face
+"targetname" entity name
+"wait" time to wait between retriggers
+*/
+void() trigger_monsterface =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ trigger_monsterface_init();
+ // InitTrigger ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/monsterjump.qc

diff --git a/qc/triggers/monsterjump.qc b/qc/triggers/monsterjump.qc
new file mode 100644
index 0000000..02f817f
--- /dev/null
+++ b/qc/triggers/monsterjump.qc
@@ -0,0 +1,61 @@
+//==============================================================================
+// trigger_monsterjump
+//==============================================================================
+
+//----------------------------------------------------------------------
+void() trigger_monsterjump_touch =
+{
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ if (other.flags & (FL_MONSTER | FL_FLY | FL_SWIM) != FL_MONSTER)
+ return;
+
+ // set XY even if not on ground, so the jump will clear lips
+ other.velocity_x = self.movedir_x * self.speed;
+ other.velocity_y = self.movedir_y * self.speed;
+
+ if (!(other.flags & FL_ONGROUND))
+ return;
+
+ other.flags = other.flags - FL_ONGROUND;
+
+ other.velocity_z = self.height;
+};
+
+/*QUAKED trigger_monsterjump (.5 .5 .5) ? X X X DT_STARTOFF X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+
+Walking monsters that touch this will jump in the direction of the
+trigger's angle
+"speed" default to 200, the speed thrown forward
+"height" default to 200, the speed thrown upwards
+
+If DT_STARTOFF flag is set, this makes the trigger inactive. This can
+be targeted and toggled off and on.
+*/
+void() trigger_monsterjump =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.use = push_toggle;
+
+ // dumptruck_ds
+ if (self.spawnflags & DT_STARTOFF)
+ {
+ self.estate = STATE_INACTIVE;
+ }
+
+ if (!self.speed)
+ self.speed = 200;
+ if (!self.height)
+ self.height = 200;
+ if (self.angles == '0 0 0')
+ self.angles = '0 360 0';
+
+ InitTrigger ();
+ self.touch = trigger_monsterjump_touch;
+
+ SUB_CheckWaiting ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/onlyregistered.qc

diff --git a/qc/triggers/onlyregistered.qc b/qc/triggers/onlyregistered.qc
new file mode 100644
index 0000000..710fc6a
--- /dev/null
+++ b/qc/triggers/onlyregistered.qc
@@ -0,0 +1,49 @@
+//==============================================================================
+// trigger_onlyregistered
+//==============================================================================
+
+// ONLY REGISTERED TRIGGERS
+void() trigger_onlyregistered_touch =
+{
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ if (self.attack_finished > time)
+ return;
+
+ self.attack_finished = time + 2;
+
+ if (cvar("registered"))
+ {
+ self.message = "";
+ SUB_UseTargets ();
+ remove (self);
+ }
+ else
+ {
+ if (self.message != "")
+ {
+ centerprint (other, self.message);
+ sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
+ }
+ }
+};
+
+/*QUAKED trigger_onlyregistered (.5 .5 .5) ?
+Only fires if playing the registered version, otherwise prints the message
+*/
+void() trigger_onlyregistered =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ precache_sound ("misc/talk.wav");
+ InitTrigger ();
+ self.touch = trigger_onlyregistered_touch;
+
+ SUB_CheckWaiting ();
+};
+
+

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/push.qc

diff --git a/qc/triggers/push.qc b/qc/triggers/push.qc
index df5e0d0..674a59b 100644
--- a/qc/triggers/push.qc
+++ b/qc/triggers/push.qc
@@ -293,7 +293,7 @@ void() trigger_push =
{
// dumptruck_ds
// new spawnflags for all entities -- iw
- if (SUB_Inhibit ())
+ if (SUB_Inhibit())
return;

InitTrigger ();
@@ -364,66 +364,6 @@ void() trigger_push_custom =
SUB_CheckWaiting ();
};

-//======================================================================
-// monsterjump
-//----------------------------------------------------------------------
-void() trigger_monsterjump_touch =
-{
- if (self.estate != STATE_ACTIVE)
- return;
-
- if (other.flags & (FL_MONSTER | FL_FLY | FL_SWIM) != FL_MONSTER)
- return;
-
- // set XY even if not on ground, so the jump will clear lips
- other.velocity_x = self.movedir_x * self.speed;
- other.velocity_y = self.movedir_y * self.speed;
-
- if (!(other.flags & FL_ONGROUND))
- return;
-
- other.flags = other.flags - FL_ONGROUND;
-
- other.velocity_z = self.height;
-};
-
-/*QUAKED trigger_monsterjump (.5 .5 .5) ? X X X DT_STARTOFF X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
-
-Walking monsters that touch this will jump in the direction of the
-trigger's angle
-"speed" default to 200, the speed thrown forward
-"height" default to 200, the speed thrown upwards
-
-If DT_STARTOFF flag is set, this makes the trigger inactive. This can
-be targeted and toggled off and on.
-*/
-void() trigger_monsterjump =
-{
- // new spawnflags for all entities -- iw
- if (SUB_Inhibit ())
- return;
-
- self.use = push_toggle;
-
- // dumptruck_ds
- if (self.spawnflags & DT_STARTOFF)
- {
- self.estate = STATE_INACTIVE;
- }
-
- if (!self.speed)
- self.speed = 200;
- if (!self.height)
- self.height = 200;
- if (self.angles == '0 0 0')
- self.angles = '0 360 0';
-
- InitTrigger ();
- self.touch = trigger_monsterjump_touch;
-
- SUB_CheckWaiting ();
-};
-
////////////////////////////////////////////////////////////////////////
// end dumptruck_ds additions //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/remove.qc

diff --git a/qc/triggers/remove.qc b/qc/triggers/remove.qc
new file mode 100644
index 0000000..2a85640
--- /dev/null
+++ b/qc/triggers/remove.qc
@@ -0,0 +1,43 @@
+//==============================================================================
+// trigger_remove
+//==============================================================================
+
+// Selections from hiptrig.qc NOT the entire file
+
+/* Trigger QuickC program
+ By Jim Dose' 12/2/96
+ Copyright (c)1996 Hipnotic Interactive, Inc.
+ All rights reserved.
+ Distributed (unsupported) on 3.12.97
+*/
+
+// void() remove_touch =
+// {
+// if (other.flags & self.cnt)
+// return;
+// other.touch = SUB_Null;
+// other.model = "";
+// remove (self);
+// };
+//
+// /*QUAKED trigger_remove (.5 .5 .5) ? ignoremonsters ignoreplayers
+// Variable sized trigger that removes the thing
+// that touches it. Does not affect monsters or
+// players.
+// */
+// void() trigger_remove =
+// {
+// // new spawnflags for all entities -- iw
+// if (SUB_Inhibit())
+// return;
+//
+// self.cnt = FL_CLIENT|FL_MONSTER;
+//
+// if (self.spawnflags & 1)
+// self.cnt = self.cnt - FL_MONSTER;
+// if (self.spawnflags & 2)
+// self.cnt = self.cnt - FL_CLIENT;
+//
+// InitTrigger ();
+// self.touch = remove_touch;
+// };

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/secret.qc

diff --git a/qc/triggers/secret.qc b/qc/triggers/secret.qc
new file mode 100644
index 0000000..a0cbc0b
--- /dev/null
+++ b/qc/triggers/secret.qc
@@ -0,0 +1,39 @@
+//==============================================================================
+// trigger_secret
+//==============================================================================
+
+/*QUAKED trigger_secret (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+secret counter trigger
+sounds
+1) secret
+2) beep beep
+set "message" to text string
+*/
+void() trigger_secret =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ total_secrets = total_secrets + 1;
+ self.wait = -1;
+
+ if (!self.message)
+ self.message = "You found a secret area!";
+
+ if (!self.sounds)
+ self.sounds = 1;
+
+ if (self.sounds == 1)
+ {
+ precache_sound ("misc/secret.wav");
+ self.noise = "misc/secret.wav";
+ }
+ else if (self.sounds == 2)
+ {
+ precache_sound ("misc/talk.wav");
+ self.noise = "misc/talk.wav";
+ }
+
+ trigger_multiple ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/setgravity.qc

diff --git a/qc/triggers/setgravity.qc b/qc/triggers/setgravity.qc
new file mode 100644
index 0000000..48a2b65
--- /dev/null
+++ b/qc/triggers/setgravity.qc
@@ -0,0 +1,103 @@
+//==============================================================================
+// trigger_setgravity; was in hip_trig.qc
+//==============================================================================
+
+/* Trigger QuickC program
+ By Jim Dose' 12/2/96
+ Copyright (c)1996 Hipnotic Interactive, Inc.
+ All rights reserved.
+ Do not distribute.
+*/
+
+float DT_GRAVTOFF = 8; // trigger will start off
+
+//----------------------------------------------------------------------
+// dumptruck_ds based on hipnotic blocker_use
+//----------------------------------------------------------------------
+void() grav_toggle =
+{
+ if (self.estate != STATE_ACTIVE)
+ self.estate = STATE_ACTIVE;
+ else
+ self.estate = STATE_INACTIVE;
+
+};
+
+//----------------------------------------------------------------------
+// from Copper -- dumptruck_ds
+//----------------------------------------------------------------------
+void() trigger_gravity_touch =
+{
+ // if (!CheckValidTouch()) return;
+
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ local float grav;
+
+ // This is commented out so that the changing gravity will
+ // affect everything, if you don't want to use all affecting
+ // gravity changes, then uncomment these two lines.
+ // if (other.classname != "player")
+ // return;
+
+ if (self.gravity == -1)
+ grav = 1;
+ else
+ grav = self.gravity;
+
+ // the player's gravity is now managed in PlayerPreThink(), however
+ // other entities don't have special gravity management, so their
+ // gravity is still set directly -- iw
+ if (other.classname == "player")
+ other.wantedgravity = grav;
+ else
+ other.gravity = grav;
+};
+
+/*QUAKED trigger_setgravity (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+set the gravity of a player
+
+"gravity" what to set the players gravity to
+ - 0 (default) normal gravity
+ - 1 no gravity
+ - 2 almost no gravity
+ - 10 is a good setting
+ - ...
+ - 101 normal gravity
+ - 102 slightly higher gravity
+ - ...
+ - 1000 very high gravity
+
+ NOTE: the amount of gravity can only be changed by touching another
+ trigger_setgravity with a different setting. The gravity key defaults to 0
+ which is normal gravity. Lower numbers (e.g. 25) equal lower gravity. Setting
+ 100 is normal gravity. Numbers above 100 will make the player “heavier”, i.e.
+ harder to jump. If you want multiple trigger setgravity triggers in one room or
+ area, make sure the brushes are not touching each other. This can cause the
+ triggers not to work properly.
+
+*/
+void() trigger_setgravity =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ InitTrigger ();
+
+ // dumptruck_ds
+ self.use = grav_toggle;
+ self.touch = trigger_gravity_touch;
+
+ // dumptruck_ds
+ if (self.spawnflags & DT_GRAVTOFF)
+ self.estate = STATE_INACTIVE;
+
+ if (!self.gravity)
+ self.gravity = -1;
+ else
+ self.gravity = ((self.gravity - 1) / 100);
+
+ SUB_CheckWaiting ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/setskill.qc

diff --git a/qc/triggers/setskill.qc b/qc/triggers/setskill.qc
new file mode 100644
index 0000000..3dc48a0
--- /dev/null
+++ b/qc/triggers/setskill.qc
@@ -0,0 +1,27 @@
+//==============================================================================
+// trigger_setskill
+//==============================================================================
+void() trigger_skill_touch =
+{
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ cvar_set ("skill", self.message);
+};
+
+/*QUAKED trigger_setskill (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+sets skill level to the value of "message".
+Only used on start map.
+*/
+void() trigger_setskill =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ InitTrigger ();
+ self.touch = trigger_skill_touch;
+
+ SUB_CheckWaiting ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/take_weapon.qc

diff --git a/qc/triggers/take_weapon.qc b/qc/triggers/take_weapon.qc
new file mode 100644
index 0000000..6812939
--- /dev/null
+++ b/qc/triggers/take_weapon.qc
@@ -0,0 +1,44 @@
+//==============================================================================
+// trigger_take_weapon
+//==============================================================================
+
+//======================================================================
+// GIVE AND TAKE STUFF (WIP)
+// This is Axe only at the moment. Need to research removing all weapons.
+//----------------------------------------------------------------------
+
+// thanks to ShanJaq and Spike for their help on this.
+void() take_weapon_use =
+{
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ if (!(other.flags & FL_CLIENT))
+ return;
+
+ multi_trigger ();
+ other.items &= ~IT_SHOTGUN;
+ other.currentammo = !other.ammo_shells;
+ other.ammo_shells = !other.ammo_shells;
+ other.items = other.items - (other.items & IT_SHELLS);
+ W_SetCurrentAmmo ();
+ W_BestWeapon ();
+};
+
+/*QUAKED trigger_take_weapon (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+
+Removes shotgun upon touch. You can also set "reset_items" in the worldspawn entity to accomplish an axe only start.
+*/
+void() trigger_take_weapon =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.wait = -1;
+ trigger_multiple ();
+ self.touch = take_weapon_use;
+
+ SUB_CheckWaiting ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/usekey.qc

diff --git a/qc/triggers/usekey.qc b/qc/triggers/usekey.qc
new file mode 100644
index 0000000..eea8980
--- /dev/null
+++ b/qc/triggers/usekey.qc
@@ -0,0 +1,130 @@
+//==============================================================================
+// trigger_usekey
+//==============================================================================
+
+/* Trigger QuickC program
+ By Jim Dose' 12/2/96
+ Copyright (c)1996 Hipnotic Interactive, Inc.
+ All rights reserved.
+ Distributed (unsupported) on 3.12.97
+*/
+
+float USE_SILV_KEY = 8;
+float USE_GOLD_KEY = 16;
+
+//======================================================================
+// keytrigger_unlock
+//
+// Perform the actions which should be performed when self is successfully
+// unlocked with a key.
+//
+// This function exists so that it can be passed as an argument to the new
+// keylock_try_to_unlock function. This code was previously part of the
+// keytrigger_use function. -- iw
+//----------------------------------------------------------------------
+void() keytrigger_unlock =
+{
+ // we can't just remove (self) here, because this is a touch
+ // function called while C code is looping through area links...
+ self.touch = SUB_Null;
+ self.use = SUB_Null;
+ self.nextthink = time + 0.1;
+ self.think = SUB_Remove;
+ self.message = "";
+
+ SUB_UseTargets ();
+};
+
+//----------------------------------------------------------------------
+void() keytrigger_use =
+{
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ if (self.attack_finished > time)
+ return;
+
+ self.attack_finished = time + 2;
+ keylock_try_to_unlock (activator, self.message, keytrigger_unlock);
+};
+
+//----------------------------------------------------------------------
+void() keytrigger_touch =
+{
+ activator = other;
+ keytrigger_use ();
+};
+
+/*QUAKED trigger_usekey (0 .5 0) ? X X X USE_SILV_KEY USE_GOLD_KEY X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+
+Variable sized single use trigger that requires a key to trigger targets. Must be targeted at one or more entities.
+
+"cnt" if 1, leave a used key in the player's inventory (0 default).
+"keyname" if set, this is the keyname of the item_key_custom which unlocks this entity.
+"message" is printed when the trigger is touched without having the right key.
+"noise1" sound file for the "key required" sound (default is per worldtype).
+"noise2" sound file for the "key used" sound (default is per worldtype).
+*/
+void() trigger_usekey =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ // the keylock_* functions use self.noise3 and self.noise4 internally,
+ // but trigger_usekey doesn't use the self.noise1 or self.noise2 fields
+ // for anything, so we allow the mapper to specify custom sound files by
+ // setting self.noise1 and self.noise2, but we move those values into
+ // self.noise3 and self.noise4 -- iw
+ self.noise3 = self.noise1;
+ self.noise4 = self.noise2;
+ self.noise1 = "";
+ self.noise2 = "";
+
+ keylock_init ();
+
+ if (self.spawnflags & USE_SILV_KEY)
+ {
+ //dumptruck_ds
+ keylock_set_silver_key ();
+
+ if (self.keyname != "")
+ {
+ self.netname = self.keyname;
+ self.keyname = "";
+ }
+ }
+
+ if (self.spawnflags & USE_GOLD_KEY)
+ {
+ //dumptruck_ds
+ keylock_set_gold_key ();
+
+ if (self.keyname != "")
+ {
+ self.netname = self.keyname;
+ self.keyname = "";
+ }
+ }
+
+ // support for item_key_custom -- iw
+ if (self.keyname != "")
+ {
+ keylock_set_custom_key (self.keyname);
+ // this should not be referenced again
+ self.keyname = "";
+ }
+
+ if (!keylock_has_key_set())
+ {
+ objerror ("no key specified!");
+ return;
+ }
+
+ self.use = keytrigger_use;
+ self.touch = keytrigger_touch;
+
+ InitTrigger ();
+ SUB_CheckWaiting ();
+};

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/void.qc

diff --git a/qc/triggers/void.qc b/qc/triggers/void.qc
new file mode 100644
index 0000000..cdd6a5c
--- /dev/null
+++ b/qc/triggers/void.qc
@@ -0,0 +1,60 @@
+//==============================================================================
+// trigger_void
+//==============================================================================
+
+//This is necros' trigger_void from Lost Chapters pack, modified by dumptruck_ds
+
+float MONSTER_SAFE = 1;
+float PLAYER_SAFE = 2;
+
+void() trigger_void_touch =
+{
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ // from Copper -- dumptruck_ds
+ if (other.movetype == MOVETYPE_NOCLIP)
+ return FALSE;
+
+ if (self.spawnflags & MONSTER_SAFE && other.flags & FL_MONSTER)
+ // ignore monsters
+ return;
+ if (self.spawnflags & PLAYER_SAFE && other.flags & FL_CLIENT)
+ // ignore players
+ return;
+
+ if (other.takedamage)
+ {
+ // kills even with Pentagram, this took forever to figure
+ // out!! -- dumptruck_ds
+ other.invincible_finished = 0;
+ T_Damage (other, self, self, other.health + 1000);
+
+ if (other.flags & FL_MONSTER)
+ remove (other);
+ }
+
+ if (other.classname == "gib" || other.classname == "grenade" ||
+ other.classname == "spike" || other.classname == "missile")
+ remove (other);
+
+ if (other.flags & FL_ITEM)
+ remove (other);
+
+ force_retouch = 2;
+};
+
+/*QUAKED trigger_void (.5 .5 .5) ? X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
+Use this for a 'void' area. removes monsters, gibs, ammo, etc... also kills player.
+*/
+void() trigger_void =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ InitTrigger ();
+ self.touch = trigger_void_touch;
+
+ SUB_CheckWaiting ();
+};

Return to the top of this page or return to the overview of this repo.