djcev.com

//

Git Repos / fte_dogmode / commit c95cd51

Commit: c95cd513f1bc5fadf1378474b54b714516f96d9b
Parent: f4c96eaf4b4fa9f434c30ffd7ebc480b01ac7e8b
Author: Cameron Vanderzanden, 2023-11-27 23:46
Committer: Cameron Vanderzanden, 2023-11-27 23:46

Commit Message

Code reorg, minor movement changes, misc

Reorganized the various func_ features into their own files
in the func/ directory. (With the exception of Hipnotic's
rotation code which I've kept together). Moved a few things
into the misc/ directory as well. Also reformatted the
source of those files (and a few more).

There are a few more movement fixes in here too, though I
forget exactly what. I believe some more adjustments to
DanceMove.

Change List

Diff qc/buttons.qc

diff --git a/qc/buttons.qc b/qc/buttons.qc
deleted file mode 100644
index d5a1ee0..0000000
--- a/qc/buttons.qc
+++ /dev/null
@@ -1,205 +0,0 @@
-// button and multiple button
-
-void() button_wait;
-void() button_return;
-
-void() button_wait =
-{
- self.state = STATE_TOP;
- self.nextthink = self.ltime + self.wait;
- self.think = button_return;
- activator = self.enemy;
- self.frame = 1; // use alternate textures
-
- if (self.estate != STATE_ACTIVE)
- return;
-
- SUB_UseTargets();
-
-};
-
-void() button_done =
-{
- self.state = STATE_BOTTOM;
-};
-
-void() button_return =
-{
- if (self.estate != STATE_ACTIVE) return;
-
- self.state = STATE_DOWN;
- SUB_CalcMove (self.pos1, self.speed, button_done);
- self.frame = 0; // use normal textures
- if (self.health)
- self.takedamage = DAMAGE_YES; // can be shot again
-};
-
-
-void() button_blocked =
-{ // do nothing, just don't ome all the way back out
-};
-
-
-void() button_fire =
-{
- if (self.estate != STATE_ACTIVE) return;
-
- if (self.state == STATE_UP || self.state == STATE_TOP)
- return;
-
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
-
- self.state = STATE_UP;
- SUB_CalcMove (self.pos2, self.speed, button_wait);
-};
-
-
-void() button_use =
-{
- self.enemy = activator;
- button_fire ();
-};
-
-void() button_touch =
-{
- if (other.classname != "player")
- return;
- self.enemy = other;
- button_fire ();
-};
-
-void() button_killed =
-{
- if (self.estate != STATE_ACTIVE) return;
-
- self.enemy = damage_attacker;
- self.health = self.max_health;
- self.takedamage = DAMAGE_NO; // wil be reset upon return
- button_fire ();
-};
-
-
-
-// adapted from Copper, thanks Lunaran
-void(entity b) button_lock =
-{
- entity oself;
-
- if (b.estate == STATE_INACTIVE)
- return;
-
- oself = self;
- self = b;
-
- if (self.state == STATE_UP || self.state == STATE_TOP)
- self.prevstate = STATE_TOP;
- else
- self.prevstate = STATE_BOTTOM;
-
- if (self.max_health)
- self.takedamage = DAMAGE_NO;
- self.state = STATE_UP;
- SUB_CalcMove (self.pos2, self.speed, button_wait);
- self.estate = STATE_INACTIVE;
-
- self = oself;
-}
-
-void(entity b, float dontresetstate) button_unlock =
-{
- entity oself;
-
- if (b.estate == STATE_ACTIVE)
- return;
-
- oself = self;
- self = b;
-
- if (!dontresetstate || self.wait != -1 || self.prevstate == STATE_BOTTOM) {
- if (self.max_health)
- {
- self.takedamage = DAMAGE_YES;
- self.health = self.max_health;
- }
- self.frame = 0; // use normal textures
- self.state = STATE_DOWN;
- SUB_CalcMove (self.pos1, self.speed, button_done);
- }
-
- self.estate = STATE_ACTIVE;
-
- self = oself;
-}
-
-
-/*QUAKED func_button (0 .5 .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
-When a button is touched, it moves some distance in the direction of it's angle, triggers all of it's targets, waits some time, then returns to it's original position where it can be triggered again.
-
-"angle" determines the opening direction
-"target" all entities with a matching targetname will be used
-"speed" override the default 40 speed
-"wait" override the default 1 second wait (-1 = never return)
-"lip" override the default 4 pixel lip remaining at end of move
-"health" if set, the button must be killed instead of touched
-"sounds"
-0) steam metal
-1) wooden clunk
-2) metallic click
-3) in-out
-*/
-void() func_button =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (self.sounds == 0)
- {
- precache_sound ("buttons/airbut1.wav");
- self.noise = "buttons/airbut1.wav";
- }
- if (self.sounds == 1)
- {
- precache_sound ("buttons/switch21.wav");
- self.noise = "buttons/switch21.wav";
- }
- if (self.sounds == 2)
- {
- precache_sound ("buttons/switch02.wav");
- self.noise = "buttons/switch02.wav";
- }
- if (self.sounds == 3)
- {
- precache_sound ("buttons/switch04.wav");
- self.noise = "buttons/switch04.wav";
- }
-
- SetMovedir ();
-
- self.movetype = MOVETYPE_PUSH;
- self.solid = SOLID_BSP;
- setmodel (self, self.model);
-
- self.blocked = button_blocked;
- self.use = button_use;
-
- if (self.health)
- {
- self.max_health = self.health;
- self.th_die = button_killed;
- self.takedamage = DAMAGE_YES;
- }
- else
- self.touch = button_touch;
-
- if (!self.speed)
- self.speed = 40;
- if (!self.wait)
- self.wait = 1;
- if (!self.lip)
- self.lip = 4;
-
- self.state = STATE_BOTTOM;
-
- self.pos1 = self.origin;
- self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
-};

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 282a524..cb625e4 100644
--- a/qc/client.qc
+++ b/qc/client.qc
@@ -185,6 +185,7 @@ entity() SelectSpawnPoint =
else if (deathmatch)
{
spot = lastspawn;
+ // TODO CEV this loops infinitely if no info_player_deathmatch
while (1)
{
spot = find (spot, classname, "info_player_deathmatch");

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

Diff qc/doe_elbutton.qc

diff --git a/qc/doe_elbutton.qc b/qc/doe_elbutton.qc
deleted file mode 100644
index 16d8b37..0000000
--- a/qc/doe_elbutton.qc
+++ /dev/null
@@ -1,157 +0,0 @@
-// elevator button
-// pmack
-// sept 96
-
-float ELVTR_DOWN = 1;
-
-void() elvtr_button_wait;
-void() elvtr_button_return;
-
-void() elvtr_button_wait =
-{
- elv_butn_dir = 0;
- if (self.spawnflags & ELVTR_DOWN)
- elv_butn_dir = -1;
- else
- elv_butn_dir = 1;
-
- self.state = STATE_TOP;
- self.nextthink = self.ltime + self.wait;
- self.think = elvtr_button_return;
- activator = self.enemy;
- SUB_UseTargets();
- self.frame = 1; // use alternate textures
-};
-
-void() elvtr_button_done =
-{
- self.state = STATE_BOTTOM;
-};
-
-void() elvtr_button_return =
-{
- self.state = STATE_DOWN;
- SUB_CalcMove (self.pos1, self.speed, elvtr_button_done);
- self.frame = 0; // use normal textures
- if (self.health)
- self.takedamage = DAMAGE_YES; // can be shot again
-};
-
-
-void() elvtr_button_blocked =
-{ // do nothing, just don't ome all the way back out
-};
-
-
-void() elvtr_button_fire =
-{
- if (self.state == STATE_UP || self.state == STATE_TOP)
- return;
-
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
-
- self.state = STATE_UP;
- SUB_CalcMove (self.pos2, self.speed, elvtr_button_wait);
-};
-
-
-void() elvtr_button_use =
-{
- self.enemy = activator;
- elvtr_button_fire ();
-};
-
-void() elvtr_button_touch =
-{
- if (other.classname != "player")
- return;
- self.enemy = other;
- elvtr_button_fire ();
-};
-
-void() elvtr_button_killed =
-{
- self.enemy = damage_attacker;
- self.health = self.max_health;
- self.takedamage = DAMAGE_NO; // wil be reset upon return
- elvtr_button_fire ();
-};
-
-
-/*QUAKED func_elvtr_button (0 .5 .8) ? ELVTR_DOWN 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
-
-ELEVATOR BUTTON ONLY!
-
-ELVTR_DOWN causes this to be a DOWN button.
-Default is UP.
-
-When a button is touched, it moves some distance in the direction of it's angle, triggers all of it's targets, waits some time, then returns to it's original position where it can be triggered again.
-
-"angle" determines the opening direction
-"target" all entities with a matching targetname will be used
-"speed" override the default 40 speed
-"wait" override the default 1 second wait (-1 = never return)
-"lip" override the default 4 pixel lip remaining at end of move
-"health" if set, the button must be killed instead of touched
-"sounds"
-0) steam metal
-1) wooden clunk
-2) metallic click
-3) in-out
-*/
-void() func_elvtr_button =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (self.sounds == 0)
- {
- precache_sound ("buttons/airbut1.wav");
- self.noise = "buttons/airbut1.wav";
- }
- if (self.sounds == 1)
- {
- precache_sound ("buttons/switch21.wav");
- self.noise = "buttons/switch21.wav";
- }
- if (self.sounds == 2)
- {
- precache_sound ("buttons/switch02.wav");
- self.noise = "buttons/switch02.wav";
- }
- if (self.sounds == 3)
- {
- precache_sound ("buttons/switch04.wav");
- self.noise = "buttons/switch04.wav";
- }
-
- SetMovedir ();
-
- self.movetype = MOVETYPE_PUSH;
- self.solid = SOLID_BSP;
- setmodel (self, self.model);
-
- self.blocked = elvtr_button_blocked;
- self.use = elvtr_button_use;
-
- if (self.health)
- {
- self.max_health = self.health;
- self.th_die = elvtr_button_killed;
- self.takedamage = DAMAGE_YES;
- }
- else
- self.touch = elvtr_button_touch;
-
- if (!self.speed)
- self.speed = 40;
- if (!self.wait)
- self.wait = 1;
- if (!self.lip)
- self.lip = 4;
-
- self.state = STATE_BOTTOM;
-
- self.pos1 = self.origin;
- self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
-};

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

Diff qc/doe_plats.qc

diff --git a/qc/doe_plats.qc b/qc/doe_plats.qc
deleted file mode 100644
index 3b0b120..0000000
--- a/qc/doe_plats.qc
+++ /dev/null
@@ -1,630 +0,0 @@
-// newplats.qc
-// pmack
-// september 1996
-
-// TYPES
-
-float DN_N_WAIT = 1;
-float PLT_TOGGLE = 2;
-float ELEVATOR = 4;
-float START_AT_TOP = 8;
-float PLAT2 = 16;
-float PLAT2_BOTTOM = 32;
-
-float elv_butn_dir;
-
-// ==================================
-// down N and wait code
-// ==================================
-
-void() dn_and_wait_go_up;
-void() dn_and_wait_go_down;
-void() dn_and_wait_crush;
-
-void() dn_and_wait_hit_top =
-{
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_TOP;
-};
-
-void() dn_and_wait_hit_bottom =
-{
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_BOTTOM;
- self.think = dn_and_wait_go_up;
- self.nextthink = self.ltime + self.health;
-};
-
-void() dn_and_wait_go_down =
-{
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- self.state = STATE_DOWN;
- SUB_CalcMove (self.pos2, self.speed, dn_and_wait_hit_bottom);
-};
-
-void() dn_and_wait_go_up =
-{
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- self.state = STATE_UP;
- SUB_CalcMove (self.pos1, self.speed, dn_and_wait_hit_top);
-};
-
-void() dn_and_wait_crush =
-{
- T_Damage (other, self, self, 1);
-
- if (self.state == STATE_UP)
- dn_and_wait_go_down ();
- else if (self.state == STATE_DOWN)
- dn_and_wait_go_up ();
- else
- objerror ("plat_new_crush: bad self.state\n");
-};
-
-void() dn_and_wait_use =
-{
- if (self.state != STATE_TOP)
- return;
-
- dn_and_wait_go_down ();
-};
-
-// ==================================
-// toggle type code
-// ==================================
-
-void() toggle_go_up;
-void() toggle_go_down;
-void() toggle_crush;
-
-void() toggle_hit_top =
-{
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_TOP;
-};
-
-void() toggle_hit_bottom =
-{
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_BOTTOM;
-};
-
-void() toggle_go_down =
-{
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- self.state = STATE_DOWN;
- SUB_CalcMove (self.pos2, self.speed, toggle_hit_bottom);
-};
-
-void() toggle_go_up =
-{
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- self.state = STATE_UP;
- SUB_CalcMove (self.pos1, self.speed, toggle_hit_top);
-};
-
-void() toggle_crush =
-{
- T_Damage (other, self, self, 1);
-
- if (self.state == STATE_UP)
- toggle_go_down ();
- else if (self.state == STATE_DOWN)
- toggle_go_up ();
- else
- objerror ("plat_new_crush: bad self.state\n");
-};
-
-void() toggle_use =
-{
- if (self.state == STATE_TOP)
- toggle_go_down ();
- else if(self.state == STATE_BOTTOM)
- toggle_go_up ();
-};
-
-// ==================================
-// elvtr type code
-// ==================================
-
-void() elvtr_crush;
-
-void() elvtr_stop =
-{
- self.elevatorOnFloor = self.elevatorToFloor;
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_BOTTOM;
- self.elevatorLastUse = time;
-};
-
-void() elvtr_go =
-{
- self.elevatorDestination = self.pos2;
- self.elevatorDestination_z = self.pos2_z +
- (self.height * self.elevatorToFloor);
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- self.state = STATE_UP;
- SUB_CalcMove (self.elevatorDestination, self.speed, elvtr_stop);
- self.elevatorLastUse = time;
-};
-
-void() elvtr_crush =
-{
- local float tmp;
-
-// T_Damage (other, self, self, 1);
-
- // the elevator is changing direction, so swap the floor it's coming
- // from and the floor it's going to -- iw
- tmp = self.elevatorOnFloor;
- self.elevatorOnFloor = self.elevatorToFloor;
- self.elevatorToFloor = tmp;
-
- elvtr_go ();
-};
-
-// ===============
-// elevator use function
-// self = plat, other = elevator button, other.enemy = player
-// ===============
-void() elvtr_use =
-{
- local float tempDist, elvPos, btnPos;
-
- // the original DoE code allowed an elevator to be activated again
- // when it was in the process of moving between floors (assuming the
- // wait period was over); this resulted in sometimes unintuitive
- // behavior, so, the following test prevents this -- iw
- if (self.elevatorToFloor != self.elevatorOnFloor)
- return;
-
- // the original DoE code had a hard-coded two second wait period;
- // this has been changed for progs_dump so that self.wait is used
- // instead -- iw
- if ((self.elevatorLastUse + self.wait) > time)
- return;
-
- self.elevatorLastUse = time;
-
- if (elv_butn_dir == 0)
- return;
-
- elvPos = (self.absmin_z + self.absmax_z) * 0.5;
- btnPos = (other.absmin_z + other.absmax_z) * 0.5;
-
- if (elvPos > btnPos)
- {
- tempDist = (elvPos - btnPos) / self.height;
- tempDist = ceil ( tempDist);
- self.elevatorToFloor = self.elevatorOnFloor - tempDist;
- elvtr_go ();
- return;
- }
- else
- {
- tempDist = btnPos - elvPos;
- if (tempDist > self.height)
- {
- tempDist = tempDist / self.height;
- tempDist = floor ( tempDist );
- self.elevatorToFloor = self.elevatorOnFloor + tempDist;
- elvtr_go ();
- return;
- }
- }
-
- if (elv_butn_dir == -1)
- {
- if(self.elevatorOnFloor > 0)
- {
- self.elevatorToFloor = self.elevatorOnFloor - 1;
- elvtr_go ();
- }
- }
- else if(elv_butn_dir == 1)
- {
- if(self.elevatorOnFloor < (self.cnt - 1))
- {
- self.elevatorToFloor = self.elevatorOnFloor + 1;
- elvtr_go ();
- }
- }
-};
-
-// ==================================
-// PLAT2 type code
-// ==================================
-
-void() plat2_center_touch;
-void() plat2_go_up;
-void() plat2_go_down;
-void() plat2_crush;
-
-void() plat2_spawn_inside_trigger =
-{
- local entity trigger;
- local vector tmin, tmax;
-
-//
-// middle trigger
-//
- trigger = spawn();
- trigger.touch = plat2_center_touch;
- trigger.movetype = MOVETYPE_NONE;
- trigger.solid = SOLID_TRIGGER;
- trigger.enemy = self;
-
- tmin = self.mins + '25 25 0';
- tmax = self.maxs - '25 25 -8';
- tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
-
- if (self.spawnflags & PLAT_LOW_TRIGGER)
- tmax_z = tmin_z + 8;
-
- if (self.size_x <= 50)
- {
- tmin_x = (self.mins_x + self.maxs_x) / 2;
- tmax_x = tmin_x + 1;
- }
- if (self.size_y <= 50)
- {
- tmin_y = (self.mins_y + self.maxs_y) / 2;
- tmax_y = tmin_y + 1;
- }
-
- setsize (trigger, tmin, tmax);
-};
-
-void() plat2_hit_top =
-{
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_TOP;
-
- self.plat2LastMove = time;
- if(self.plat2Called == 1)
- {
- self.think = plat2_go_down;
- self.nextthink = self.ltime + 1.5;
- self.plat2Called = 0;
- self.plat2LastMove = 0; // allow immediate move
- }
- else if(!(self.spawnflags & START_AT_TOP))
- {
- self.think = plat2_go_down;
- self.nextthink = self.ltime + self.delay;
- self.plat2Called = 0;
- }
-};
-
-void() plat2_hit_bottom =
-{
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_BOTTOM;
-
- self.plat2LastMove = time;
- if(self.plat2Called == 1)
- {
- self.think = plat2_go_up;
- self.nextthink = self.ltime + 1.5;
- self.plat2Called = 0;
- self.plat2LastMove = 0; // allow immediate move
- }
- else if(self.spawnflags & START_AT_TOP)
- {
- self.think = plat2_go_up;
- self.nextthink = self.ltime + self.delay;
- self.plat2Called = 0;
- }
-};
-
-void() plat2_go_down =
-{
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- self.state = STATE_DOWN;
- SUB_CalcMove (self.pos2, self.speed, plat2_hit_bottom);
-};
-
-void() plat2_go_up =
-{
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- self.state = STATE_UP;
- SUB_CalcMove (self.pos1, self.speed, plat2_hit_top);
-};
-
-void() plat2_use =
-{
- if(self.state > 4)
- self.state = self.state - 10;
-
- self.use = SUB_Null;
-};
-
-void() plat2_center_touch =
-{
- local float otherState;
- local vector platPosition;
-
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
- // at this point, self is the trigger. self.enemy is the plat.
- // this changes self to be the plat, other is the player.
- self = self.enemy;
-
- if ((self.plat2LastMove + 2) > time)
- return;
-
- if (self.state > 4) // disabled.
- return;
-
- if (self.plat2GoTo > STATE_BOTTOM)
- {
- if (self.plat2GoTime < time)
- {
- if (self.plat2GoTo == STATE_UP)
- plat2_go_up();
- else
- plat2_go_down();
-
- self.plat2GoTo = 0;
- }
- return;
- }
-
- if (self.state > STATE_BOTTOM) // STATE_UP or STATE_DOWN
- return;
-
- platPosition = (self.absmax + self.absmin) * 0.5;
-
- if (self.state == STATE_TOP)
- {
- otherState = STATE_TOP;
- if ( platPosition_z > other.origin_z )
- otherState = STATE_BOTTOM;
- }
- else
- {
- otherState = STATE_BOTTOM;
- if ( (other.origin_z - platPosition_z) > self.height)
- otherState = STATE_TOP;
- }
-
- if (self.state == otherState)
- {
- self.plat2Called = 0;
- self.plat2GoTime = time + 0.5;
- }
- else
- {
- self.plat2GoTime = time + 0.1;
- self.plat2Called = 1;
- }
-
- if (self.state == STATE_BOTTOM)
- self.plat2GoTo = STATE_UP;
- else if(self.state == STATE_TOP)
- self.plat2GoTo = STATE_DOWN;
-};
-
-void() plat2_crush =
-{
- T_Damage (other, self, self, 1);
-
- if (self.state == STATE_UP)
- plat2_go_down ();
- else if (self.state == STATE_DOWN)
- plat2_go_up ();
- else
- objerror ("plat2_crush: bad self.state\n");
-};
-
-// ==================================
-// Common Plat Code
-// ==================================
-
-/*QUAKED func_new_plat (0 .5 .8) ? DN_N_WAIT PLT_TOGGLE ELEVATOR START_AT_TOP PLAT2 P2_BOTTOM 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
-
-
---------------
-DN_N_WAIT is a plat that starts at the top and when triggered, goes down, waits, then comes back up.
-health - number of seconds to wait (default 5)
---------------
-PLT_TOGGLE is a plat that will change between the top and bottom each time it is triggered.
---------------
-ELEVATOR is an elevator plat. You can have as many levels as you want but they must be all the same distance away. Use elevator button entity as the trigger.
-cnt is the number of floors
-height is the distance between floors
-wait is the number of seconds before the elevator can be activated again after starting or stopping (default 0)
-
-START_AT_TOP is an optional flag for elevators. It just tells the elevator that it's position is the top floor. (Default is the bottom floor) USE THIS ONLY WITH ELEVATORS!
--------------
-PLAT2 is a fixed version of the original plat. If you want the plat to start at the bottom and move to the top on demand, use a negative height. That will tell Quake to lower the plat at spawn time. Always place this plat type in the top position when making the map. This will ensure correct lighting, hopefully. If a plat2 is the target of a trigger, it will be disabled until it has been triggered. Delay is the wait before the plat returns to original position.
-
-If you don't want to bother figuring out the height, don't put a
-value in the height
-
-delay default 3
-speed default 150
-cnt default 2
-
-P2_BOTTOM is an optional switch to have an auto-sized plat2 start at the bottom.
---------------
-Plats are always drawn in the extended position, so they will light correctly.
-
-If the plat is the target of another trigger or button, it will start out disabled in the extended position until it is trigger, when it will lower and become a normal plat.
-
-If the "height" key is set, that will determine the amount the plat moves, instead of being implicitly determined by the model's height.
-Set "sounds" to one of the following:
-1) base fast
-2) chain slow
-*/
-
-void() func_new_plat =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
-//local entity t;
-local float negativeHeight;
-
- negativeHeight = 0;
-
- if (!self.t_length)
- self.t_length = 80;
- if (!self.t_width)
- self.t_width = 10;
-
- if (self.sounds == 0)
- self.sounds = 2;
-// FIX THIS TO LOAD A GENERIC PLAT SOUND
-
- if (self.sounds == 1) {
- if (!self.noise || self.noise == "") self.noise = "plats/plat1.wav";
- if (!self.noise1 || self.noise1 == "") self.noise1 = "plats/plat2.wav";
- }
- else if (self.sounds == 2) {
- if (!self.noise || self.noise == "") self.noise = "plats/medplat1.wav";
- if (!self.noise1 || self.noise1 == "") self.noise1 = "plats/medplat2.wav";
- }
- else if (self.sounds == 3) { // base door sound
- if (!self.noise || self.noise == "") self.noise = "doors/hydro1.wav";
- if (!self.noise1 || self.noise1 == "") self.noise1 = "doors/hydro2.wav";
- }
- else if (self.sounds == 4) { // func_train sounds
- if (!self.noise || self.noise == "") self.noise = "plats/train1.wav";
- if (!self.noise1 || self.noise1 == "") self.noise1 = "plats/train2.wav";
- }
- else {
- if (!self.noise || self.noise == "") self.noise = "misc/null.wav";
- if (!self.noise1 || self.noise1 == "") self.noise1 = "misc/null.wav";
- }
-
- precache_sound(self.noise);
- precache_sound(self.noise1);
-
-
- self.mangle = self.angles;
- self.angles = '0 0 0';
-
- self.classname = "plat";
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- setorigin (self, self.origin);
- setmodel (self, self.model);
- setsize (self, self.mins , self.maxs);
-
- if (!self.speed)
- self.speed = 150;
-
-// pos1 is the top position, pos2 is the bottom
- self.pos1 = self.origin;
- self.pos2 = self.origin;
-
- if (self.height < 0)
- {
- negativeHeight = 1;
- self.height = 0 - self.height;
- }
-
- if (self.height)
- self.pos2_z = self.origin_z - self.height;
- else
- {
- negativeHeight = 1;
- self.height = self.size_z - 8;
- self.pos2_z = self.origin_z - self.height;
- }
-
- if (self.spawnflags & DN_N_WAIT)
- {
- self.use = dn_and_wait_use;
- self.blocked = dn_and_wait_crush;
-
- if (negativeHeight == 1)
- {
- self.state = STATE_BOTTOM;
- setorigin (self, self.pos2);
- }
- else
- self.state = STATE_TOP;
-
- if (!self.health)
- self.health = 5;
- }
- else if (self.spawnflags & PLT_TOGGLE)
- {
- self.use = toggle_use;
- self.blocked = toggle_crush;
- if (negativeHeight == 1)
- {
- setorigin (self, self.pos2);
- self.state = STATE_BOTTOM;
- }
- else
- {
- self.state = STATE_TOP;
- }
- }
- else if (self.spawnflags & ELEVATOR)
- {
- self.elevatorLastUse = 0;
-
- // allow the mapper to set self.wait, but don't allow a negative
- // wait period -- iw
- if (self.wait < 0)
- self.wait = 0;
-
- if (self.spawnflags & START_AT_TOP)
- {
- self.pos1 = self.origin;
- self.pos2 = self.origin;
- self.pos2_z = self.origin_z - (self.height * (self.cnt - 1));
- self.elevatorOnFloor = self.cnt - 1;
- self.elevatorToFloor = self.elevatorOnFloor;
- }
- else
- {
- self.pos1 = self.origin;
- self.pos2 = self.origin;
- self.pos1_z = self.origin_z + (self.height * (self.cnt - 1));
- self.elevatorOnFloor = 0;
- self.elevatorToFloor = self.elevatorOnFloor;
- }
-
- self.use = elvtr_use;
- self.blocked = elvtr_crush;
- }
- else if (self.spawnflags & PLAT2)
- {
- plat2_spawn_inside_trigger (); // the "start moving" trigger
- self.plat2Called = 0;
- self.plat2LastMove = 0;
- self.plat2GoTo = 0;
- self.plat2GoTime = 0;
- self.blocked = plat2_crush;
-
- if (!self.delay)
- self.delay = 3;
-
- if (negativeHeight == 1)
- {
- self.state = STATE_BOTTOM;
- // make sure START_AT_TOP isn't set. We need that...
- self.spawnflags = PLAT2;
- setorigin (self, self.pos2);
- }
- else
- {
- // default position is top.
- self.spawnflags = self.spawnflags | START_AT_TOP;
- self.state = STATE_TOP;
- }
-
- if (self.targetname != "")
- {
- self.use = plat2_use;
- self.state = self.state + 10;
- }
- }
-
-};

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

Diff qc/doors.qc

diff --git a/qc/doors.qc b/qc/doors.qc
deleted file mode 100644
index 419ed89..0000000
--- a/qc/doors.qc
+++ /dev/null
@@ -1,945 +0,0 @@
-
-float DOOR_START_OPEN = 1;
-float DOOR_DONT_LINK = 4;
-float DOOR_GOLD_KEY = 8;
-float DOOR_SILVER_KEY = 16;
-float DOOR_TOGGLE = 32;
-float DOOR_DOOM_STYLE_UNLOCK = 64;
-/*
-
-Doors are similar to buttons, but can spawn a fat trigger field around them
-to open without a touch, and they link together to form simultanious
-double/quad doors.
-
-Door.owner is the master door. If there is only one door, it points to itself.
-If multiple doors, all will point to a single one.
-
-Door.enemy chains from the master door through all doors linked in the chain.
-
-*/
-
-/*
-=============================================================================
-
-THINK FUNCTIONS
-
-=============================================================================
-*/
-
-void() door_go_down;
-void() door_go_up;
-
-void() door_blocked =
-{
- T_Damage (other, self, self, self.dmg);
-
-// if a door has a negative wait, it would never come back if blocked,
-// so let it just squash the object to death real fast
- if (self.wait >= 0)
- {
- if (self.state == STATE_DOWN)
- door_go_up ();
- else
- door_go_down ();
- }
-};
-
-
-void() door_hit_top =
-{
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_TOP;
- if (self.spawnflags & DOOR_TOGGLE)
- return; // don't come down automatically
- self.think = door_go_down;
- self.nextthink = self.ltime + self.wait;
-};
-
-void() door_hit_bottom =
-{
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_BOTTOM;
-};
-
-void() door_go_down =
-{
- entity shadow;
- entity oldself;
-
- sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
- if (self.max_health)
- {
- self.takedamage = DAMAGE_YES;
- self.health = self.max_health;
- }
-
- self.state = STATE_DOWN;
- SUB_CalcMove (self.pos1, self.speed, door_hit_bottom);
-
- if(self.switchshadstyle) {
- shadow = self.shadowcontroller;
- oldself = self;
- self = shadow;
-
- if(oldself.spawnflags & DOOR_START_OPEN) {
- shadow_fade_out();
- shadow.shadowoff = 1;
- } else {
- shadow_fade_in();
- shadow.shadowoff = 0;
- }
-
- self = oldself;
-
- }
-};
-
-void() door_go_up =
-{
- entity shadow;
- entity oldself;
-
- if (self.state == STATE_UP)
- return; // allready going up
-
- if (self.state == STATE_TOP)
- { // reset top wait time
- self.nextthink = self.ltime + self.wait;
- return;
- }
-
- sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
- self.state = STATE_UP;
- SUB_CalcMove (self.pos2, self.speed, door_hit_top);
-
- SUB_UseTargets();
-
- if(self.switchshadstyle) {
- shadow = self.shadowcontroller;
- oldself = self;
- self = shadow;
-
- if(oldself.spawnflags & DOOR_START_OPEN) {
- shadow_fade_in();
- shadow.shadowoff = 0;
- } else {
- shadow_fade_out();
- shadow.shadowoff = 1;
- }
-
- self = oldself;
- }
-};
-
-
-void() door_group_go_down = {
- local entity oself, starte;
-
- oself = self;
- starte = self;
-
- do
- {
- door_go_down ();
- self = self.enemy;
- } while ( (self != starte) && (self != world) );
- self = oself;
-
-};
-
-void() door_group_go_up = {
- local entity oself, starte;
-
- oself = self;
- starte = self;
-
- do
- {
- door_go_up ();
- self = self.enemy;
- } while ( (self != starte) && (self != world) );
-
- self = oself;
-};
-
-/*
-=============================================================================
-
-ACTIVATION FUNCTIONS
-
-=============================================================================
-*/
-
-void() door_fire =
-{
-
- if (self.owner != self)
- objerror ("door_fire: self.owner != self");
-
- if (self.estate != STATE_ACTIVE)
- return;
-// self.noise4 is now played in keylock_try_to_unlock -- iw
-
- self.message = string_null; // no more message
-
-
- if (self.spawnflags & DOOR_TOGGLE)
- {
- if (self.state == STATE_UP || self.state == STATE_TOP)
- {
- door_group_go_down();
- return;
- }
- }
-
- // trigger all paired doors
- door_group_go_up();
-};
-
-
-void() door_use =
-{
- local entity oself;
-
- self.message = ""; // door message are for touch only
- self.owner.message = "";
- self.enemy.message = "";
- oself = self;
- self = self.owner;
- door_fire ();
- self = oself;
-};
-
-
-void() door_trigger_touch =
-{
- if (other.health <= 0)
- return;
-
- if (other.movetype == MOVETYPE_NOCLIP) // from copper -- dumptruck_ds
- return;
-
- if (time < self.attack_finished)
- return;
- self.attack_finished = time + 1;
-
- activator = other;
-
- self = self.owner;
- door_use ();
-};
-
-
-void() door_killed =
-{
- local entity oself;
-
- oself = self;
- self = self.owner;
- self.health = self.max_health;
- self.takedamage = DAMAGE_NO; // wil be reset upon return
- door_use ();
- self = oself;
-};
-
-
-/*
-================
-door_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
-door_touch function. -- iw
-================
-*/
-void() door_unlock =
-{
- if (!(self.spawnflags & DOOR_DOOM_STYLE_UNLOCK))
- {
- self.touch = SUB_Null;
- if (self.enemy)
- self.enemy.touch = SUB_Null; // get paired door
- }
- door_use ();
-};
-
-
-/*
-================
-door_touch
-
-Prints messages and opens key doors
-================
-*/
-void() door_touch =
-{
- // if (other.classname != "player")
- // return;
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
- if (self.owner.attack_finished > time)
- return;
-
- self.owner.attack_finished = time + 2;
-
- if (self.owner.message != "")
- {
- centerprint (other, self.owner.message);
- sound (other, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);
- }
-
-// key door stuff
- if (!keylock_has_key_set ())
- return;
-
- keylock_try_to_unlock (other, "", door_unlock);
-};
-
-
-
-/*
-=============================================================================
-ENTITY STATE FUNCTIONS
-=============================================================================
-*/
-
-void(entity e, float closealldoors) door_estate_lock = {
- local entity oself, next;
-
- if (e.owner.estate == STATE_INACTIVE) return;
-
- // blocks linked doors from updating the same owner repeatedly
- if (e.owner.last_setstate == self && e.owner.last_setstate_frame == framecount) return;
-
- oself = self;
- self = e.owner;
-
- self.estate = STATE_INACTIVE;
-
- self.last_setstate = oself;
- self.last_setstate_frame = framecount;
-
- self.prevstate = self.state;
-
- if (self.state == STATE_UP || self.state == STATE_TOP) {
- if (
- // don't close wait -1 nor toggleable doors...
- !(self.wait == -1 || (self.spawnflags & DOOR_TOGGLE))
- // ...unless the trigger_setstate has a "Close all doors" spawnflag on
- || closealldoors
- )
- door_group_go_down();
-
- }
-
- if (self.max_health) {
- next = self;
- do {
- //e.health = 0;
- next.takedamage = DAMAGE_NO;
- next = next.enemy;
- } while ( (next != self) && (next != world) );
- }
-
- self = oself;
-
-}
-
-void(entity e, float openalldoors) door_estate_unlock = {
- local entity oself, next;
-
- if (e.owner.estate == STATE_ACTIVE) return;
-
- // blocks linked doors from updating the same owner repeatedly
- if (e.owner.last_setstate == self && e.owner.last_setstate_frame == framecount) return;
-
- oself = self;
- self = e.owner;
-
- self.last_setstate = oself;
- self.last_setstate_frame = framecount;
-
- if (self.prevstate == STATE_UP || self.prevstate == STATE_TOP) {
- if (
- (self.wait == -1 || (self.spawnflags & DOOR_TOGGLE))
- && openalldoors
- ) door_group_go_up();
- }
-
- if (self.max_health) {
- next = self;
- do {
- next.health = next.max_health;
- next.takedamage = DAMAGE_YES;
- next = next.enemy;
- } while ( (next != self) && (next != world) );
- }
-
- self.estate = STATE_ACTIVE;
- self = oself;
-}
-
-
-/*
-=============================================================================
-
-SPAWNING FUNCTIONS
-
-=============================================================================
-*/
-
-
-entity(vector fmins, vector fmaxs) spawn_field =
-{
- local entity trigger;
- local vector t1, t2;
-
- trigger = spawn();
- trigger.movetype = MOVETYPE_NONE;
- trigger.solid = SOLID_TRIGGER;
- trigger.owner = self;
- trigger.touch = door_trigger_touch;
-
- t1 = fmins;
- t2 = fmaxs;
- setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
- return (trigger);
-};
-
-
-float (entity e1, entity e2) EntitiesTouching =
-{
- if (e1.mins_x > e2.maxs_x)
- return FALSE;
- if (e1.mins_y > e2.maxs_y)
- return FALSE;
- if (e1.mins_z > e2.maxs_z)
- return FALSE;
- if (e1.maxs_x < e2.mins_x)
- return FALSE;
- if (e1.maxs_y < e2.mins_y)
- return FALSE;
- if (e1.maxs_z < e2.mins_z)
- return FALSE;
- return TRUE;
-};
-
-
-/*
-=============
-LinkDoors
-
-
-=============
-*/
-void() LinkDoors =
-{
- local entity t, starte;
- local vector cmins, cmaxs;
-
- if (self.enemy)
- return; // already linked by another door
- if (self.spawnflags & 4)
- {
- self.owner = self.enemy = self;
- return; // don't want to link this door
- }
-
- cmins = self.mins;
- cmaxs = self.maxs;
-
- starte = self;
- t = self;
-
- do
- {
- self.owner = starte; // master door
-
- if (self.health)
- starte.health = self.health;
- if (self.targetname != "")
- starte.targetname = self.targetname;
- if (self.message != "")
- starte.message = self.message;
-
- t = find (t, classname, self.classname);
- if (!t)
- {
- self.enemy = starte; // make the chain a loop
-
- // shootable, fired, or key doors just needed the owner/enemy links,
- // they don't spawn a field
-
- self = self.owner;
-
- if (self.health)
- return;
- if (self.targetname != "")
- return;
- if (keylock_has_key_set ())
- return;
-
- self.owner.trigger_field = spawn_field(cmins, cmaxs);
-
- return;
- }
-
- if (EntitiesTouching(self,t))
- {
- if (t.enemy)
- objerror ("cross connected doors");
-
- self.enemy = t;
- self = t;
-
- if (t.mins_x < cmins_x)
- cmins_x = t.mins_x;
- if (t.mins_y < cmins_y)
- cmins_y = t.mins_y;
- if (t.mins_z < cmins_z)
- cmins_z = t.mins_z;
- if (t.maxs_x > cmaxs_x)
- cmaxs_x = t.maxs_x;
- if (t.maxs_y > cmaxs_y)
- cmaxs_y = t.maxs_y;
- if (t.maxs_z > cmaxs_z)
- cmaxs_z = t.maxs_z;
- }
- } while (1 );
-
-};
-
-
-/*QUAKED func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE 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
-
-if two doors touch, they are assumed to be connected and operate as a unit.
-
-TOGGLE causes the door to wait in both the start and end states for a trigger event.
-
-START_OPEN causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors).
-
-Key doors are always wait -1.
-
-"message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet
-"angle" determines the opening direction
-"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
-"health" if set, door must be shot open
-"speed" movement speed (100 default)
-"wait" wait before returning (3 default, -1 = never return)
-"lip" lip remaining at end of move (8 default)
-"dmg" damage to inflict when blocked (2 default)
-"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
-"noise1" sound file for the "stop moving" sound (if set, overrides "sounds")
-"noise2" sound file for the "move" sound (if set, overrides "sounds")
-"noise3" sound file for the "key required" sound (default is per worldtype)
-"noise4" sound file for the "key used" sound (default is per worldtype)
-"sounds"
-0) no sound
-1) stone
-2) base
-3) stone chain
-4) screechy metal
-*/
-
-void() func_door =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- local string default_noise1;
- local string default_noise2;
- entity shadow;
- entity oldself;
-
-// self.noise3 and self.noise4 can now be overridden by the mapper, but
-// will be set to default values in keylock_init if necessary -- iw
- keylock_init ();
-
-// self.noise1 and self.noise2 can now be overridden by the mapper -- iw
- default_noise1 = "misc/null.wav";
- default_noise2 = "misc/null.wav";
- if (self.sounds == 1)
- {
- default_noise1 = "doors/drclos4.wav";
- default_noise2 = "doors/doormv1.wav";
- }
- if (self.sounds == 2)
- {
- default_noise1 = "doors/hydro2.wav";
- default_noise2 = "doors/hydro1.wav";
- }
- if (self.sounds == 3)
- {
- default_noise1 = "doors/stndr2.wav";
- default_noise2 = "doors/stndr1.wav";
- }
- if (self.sounds == 4)
- {
- default_noise1 = "doors/ddoor2.wav";
- default_noise2 = "doors/ddoor1.wav";
- }
-
- if (self.noise1 == "")
- self.noise1 = default_noise1;
- if (self.noise2 == "")
- self.noise2 = default_noise2;
-
- precache_sound (self.noise1);
- precache_sound (self.noise2);
-
- SetMovedir ();
-
- self.max_health = self.health;
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- setorigin (self, self.origin);
- setmodel (self, self.model);
- //self.classname = "door";
-
- self.blocked = door_blocked;
- self.use = door_use;
-
- if (self.spawnflags & DOOR_SILVER_KEY){
- keylock_set_silver_key ();
-
- if (self.keyname != "") {
- self.netname = self.keyname;
- self.keyname = "";
- }
- }
- if (self.spawnflags & DOOR_GOLD_KEY){
- 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 (!self.speed)
- self.speed = 100;
- if (!self.wait)
- self.wait = 3;
- if (!self.lip)
- self.lip = 8;
- if (!self.dmg)
- self.dmg = 2;
-
- self.pos1 = self.origin;
- self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
-
-// DOOR_START_OPEN is to allow an entity to be lighted in the closed position
-// but spawn in the open position
- if (self.spawnflags & DOOR_START_OPEN)
- {
- setorigin (self, self.pos2);
- self.pos2 = self.pos1;
- self.pos1 = self.origin;
- }
-
- self.state = STATE_BOTTOM;
-
- if (self.health)
- {
- self.takedamage = DAMAGE_YES;
- self.th_die = door_killed;
- }
-
- if (self.spawnflags & DOOR_DOOM_STYLE_UNLOCK)
- self.cnt = 1;
-
- if (keylock_has_key_set ())
- {
- if (!(self.spawnflags & DOOR_DOOM_STYLE_UNLOCK))
- {
- self.wait = -1;
- }
- }
- self.touch = door_touch;
-
-// LinkDoors can't be done until all of the doors have been spawned, so
-// the sizes can be detected properly.
- self.think = LinkDoors;
- self.nextthink = self.ltime + 0.1;
-
- // creates a shadow controller entity for the door if it has switchable shadows
- if(self.switchshadstyle) {
-
- shadow = spawn();
-
- self.shadowcontroller = shadow;
-
- shadow.classname = "misc_shadowcontroller";
- shadow.switchshadstyle = self.switchshadstyle;
- shadow.speed = vlen(self.pos2 - self.pos1) / self.speed;
-
- if(self.spawnflags & DOOR_START_OPEN) shadow.spawnflags = 1;
- else shadow.spawnflags = 0;
-
-
- oldself = self;
-
- self = shadow;
- misc_shadowcontroller();
-
- self = oldself;
- }
-};
-
-/*
-=============================================================================
-
-SECRET DOORS
-
-=============================================================================
-*/
-
-void() fd_secret_move1;
-void() fd_secret_move2;
-void() fd_secret_move3;
-void() fd_secret_move4;
-void() fd_secret_move5;
-void() fd_secret_move6;
-void() fd_secret_done;
-
-float SECRET_OPEN_ONCE = 1; // stays open
-float SECRET_1ST_LEFT = 2; // 1st move is left of arrow
-float SECRET_1ST_DOWN = 4; // 1st move is down from arrow
-float SECRET_NO_SHOOT = 8; // only opened by trigger
-float SECRET_YES_SHOOT = 16; // shootable even if targeted
-
-
-void () fd_secret_use =
-{
- local float temp;
-
- self.health = 10000;
-
- // exit if still moving around...
- if (self.origin != self.oldorigin)
- return;
-
- self.message = string_null; // no more message
-
- SUB_UseTargets(); // fire all targets / killtargets
-
- if (!(self.spawnflags & SECRET_NO_SHOOT))
- {
- self.th_pain = SUB_NullPain;
- self.takedamage = DAMAGE_NO;
- }
- self.velocity = '0 0 0';
-
- // Make a sound, wait a little...
-
- sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.nextthink = self.ltime + 0.1;
-
- temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1
- makevectors(self.mangle);
-
- if (!self.t_width)
- {
- if (self.spawnflags & SECRET_1ST_DOWN)
- self. t_width = fabs(v_up * self.size);
- else
- self. t_width = fabs(v_right * self.size);
- }
-
- if (!self.t_length)
- self. t_length = fabs(v_forward * self.size);
-
- if (self.spawnflags & SECRET_1ST_DOWN)
- self.dest1 = self.origin - v_up * self.t_width;
- else
- self.dest1 = self.origin + v_right * (self.t_width * temp);
-
- self.dest2 = self.dest1 + v_forward * self.t_length;
- SUB_CalcMove(self.dest1, self.speed, fd_secret_move1);
- sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
-};
-
-void(entity attacker, float damage) fd_secret_pain = { fd_secret_use(); };
-
-// Wait after first movement...
-void () fd_secret_move1 =
-{
- self.nextthink = self.ltime + 1.0;
- self.think = fd_secret_move2;
- sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
-};
-
-// Start moving sideways w/sound...
-void () fd_secret_move2 =
-{
- sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
- SUB_CalcMove(self.dest2, self.speed, fd_secret_move3);
-};
-
-// Wait here until time to go back...
-void () fd_secret_move3 =
-{
- sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
- if (!(self.spawnflags & SECRET_OPEN_ONCE))
- {
- self.nextthink = self.ltime + self.wait;
- self.think = fd_secret_move4;
- }
-};
-
-// Move backward...
-void () fd_secret_move4 =
-{
- sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
- SUB_CalcMove(self.dest1, self.speed, fd_secret_move5);
-};
-
-// Wait 1 second...
-void () fd_secret_move5 =
-{
- self.nextthink = self.ltime + 1.0;
- self.think = fd_secret_move6;
- sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
-};
-
-void () fd_secret_move6 =
-{
- sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
- SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done);
-};
-
-void () fd_secret_done =
-{
- if (!self.targetname || self.spawnflags&SECRET_YES_SHOOT)
- {
- self.health = 10000;
- self.takedamage = DAMAGE_YES;
- self.th_pain = fd_secret_pain;
- }
- sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
-};
-
-void () secret_blocked =
-{
- if (time < self.attack_finished)
- return;
- self.attack_finished = time + 0.5;
- T_Damage (other, self, self, self.dmg);
-};
-
-/*
-================
-ouch
-
-Prints messages
-================
-*/
-void() secret_touch =
-{
-
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
- if (self.attack_finished > time)
- return;
-
- self.attack_finished = time + 2;
-
- if (self.message != "")
- {
- centerprint (other, self.message);
- sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
- }
-};
-
-
-/*QUAKED func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot 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
-
-Basic secret door. Slides back, then to the side. Angle determines direction.
-wait = # of seconds before coming back
-1st_left = 1st move is left of arrow
-1st_down = 1st move is down from arrow
-always_shoot = even if targeted, keep shootable
-t_width = override WIDTH to move back (or height if going down)
-t_length = override LENGTH to move sideways
-"dmg" damage to inflict when blocked (2 default)
-
-If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
-"sounds"
-1) medieval
-2) metal
-3) base
-*/
-
-void () func_door_secret =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (self.sounds == 0)
- self.sounds = 3;
- if (self.sounds == 1)
- {
- precache_sound ("doors/latch2.wav");
- precache_sound ("doors/winch2.wav");
- precache_sound ("doors/drclos4.wav");
- self.noise1 = "doors/latch2.wav";
- self.noise2 = "doors/winch2.wav";
- self.noise3 = "doors/drclos4.wav";
- }
- if (self.sounds == 2)
- {
- precache_sound ("doors/airdoor1.wav");
- precache_sound ("doors/airdoor2.wav");
- self.noise2 = "doors/airdoor1.wav";
- self.noise1 = "doors/airdoor2.wav";
- self.noise3 = "doors/airdoor2.wav";
- }
- if (self.sounds == 3)
- {
- precache_sound ("doors/basesec1.wav");
- precache_sound ("doors/basesec2.wav");
- self.noise2 = "doors/basesec1.wav";
- self.noise1 = "doors/basesec2.wav";
- self.noise3 = "doors/basesec2.wav";
- }
-
- if (!self.dmg)
- self.dmg = 2;
-
- // Magic formula...
- self.mangle = self.angles;
- self.angles = '0 0 0';
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- //self.classname = "door";
- setmodel (self, self.model);
- setorigin (self, self.origin);
-
- self.touch = secret_touch;
- self.blocked = secret_blocked;
- self.speed = 50;
- self.use = fd_secret_use;
- if ( !self.targetname || self.spawnflags&SECRET_YES_SHOOT)
- {
- self.health = 10000;
- self.takedamage = DAMAGE_YES;
- self.th_pain = fd_secret_pain;
- self.th_die = fd_secret_use;
- }
- self.oldorigin = self.origin;
- if (!self.wait)
- self.wait = 5; // 5 seconds before closing
-};

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

Diff qc/dtmisc.qc

diff --git a/qc/dtmisc.qc b/qc/dtmisc.qc
index 1e676a3..c992a44 100644
--- a/qc/dtmisc.qc
+++ b/qc/dtmisc.qc
@@ -820,190 +820,3 @@ void() gib_misc_3 =
};
/* END Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds */

-// /*==============================================================================
-// func_fall from RennyC
-//
-// A brush that drops and fades away when touched or triggered.
-//
-// dumptruck_ds
-// noise = sound to play when triggered
-// wait = wait this long before falling
-// ==============================================================================*/
-float DONT_FADE = 1;
-float SILENT = 2;
-
-void() func_fall_think =
-{
- if (self.cnt == TRUE && self.attack_finished < time)
- {
- self.solid = SOLID_BBOX;
- // self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_TOSS;
-
- if (!(self.spawnflags & DONT_FADE))
- {
-
- if (self.alpha > 0.1)
- self.alpha = self.alpha - 0.03;
- else
- {
- remove(self);
- return;
- }
- }
- }
- self.nextthink = time + 0.1;
-};
-
-void() fall_touch =
-{
- if (other.classname == "player")
- {
- if (!(other.flags & FL_ONGROUND))
- other.flags = other.flags | FL_ONGROUND;
- }
-
- else if (other.flags & FL_MONSTER)
- T_Damage (other, self, other, 50000);
-
- else
- return;
-
- if (self.cnt == TRUE)
- return;
-
- self.attack_finished = time + self.wait;
- self.cnt = TRUE;
-
- if (!(self.spawnflags & SILENT))
- {
- if (self.noise != "")
- sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
- else
- sound (self, CHAN_AUTO, "buttons/switch21.wav", 1, ATTN_NORM);
- }
-};
-
-void() fall_use = // thanks again RennyC for help on revisions --dumptruck_ds
- {
- self.attack_finished = time + self.wait;
- self.cnt = TRUE;
-
- if (self.noise != "")
- sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
- else
- sound (self, CHAN_AUTO, "buttons/switch21.wav", 1, ATTN_NORM);
- };
-
-/*QUAKED func_fall (0 .5 .8) ? DONT_FADE 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 brush that drops and fades away when touched and/or triggered.
-Add some spice to your jumping puzzles or other scripted sequences!
-Monsters will not trigger func_fall but will be gibbed if one falls on them.
-NOTE: When a func_fall brush touches another brush or entity it will stop, which can look odd in certain situations.
-noise = sound to play when triggered, the default is a switch sound.
-wait = wait this long before falling.
-Use the DONT_FADE spawnflag if desired.
-
-Falling brush upon touch
-*/
-
-void() func_fall =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- precache_sound("buttons/switch21.wav");
- if (self.noise != "") precache_sound (self.noise);
-
-
- self.alpha = 1;
- self.cnt = FALSE;
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- self.think = func_fall_think;
- self.nextthink = time;
- self.touch = fall_touch;
- self.use = fall_use;
- setmodel (self, self.model);
-};
-
-//=START PARTICLE-STREAM==================================================
-// from Zerstrorer mod -- dumptruck_ds
-
-void(vector start, vector end, float color1, float color2, float pdensity) Particle_Beam =
-{
-local vector spray, next;
-local float dist, loop, clr;
-
- clr = color1;
- spray = start - end;
- dist = vlen(spray);
- loop = dist / 24;
- spray = normalize(spray);
- next = spray * 24;
- while(loop > 0)
- {
- particle (end, spray, clr, pdensity);
- end = end + next;
- loop = loop - 1;
- if (clr == color1)
- clr = color2;
- else
- clr = color1;
- }
-};
-
-
-void() particle_use =
-{
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- Particle_Beam(self.origin, self.enemy.origin, self.dmg, self.cnt, 15); // was 40 - too many particles for my taste --dumptruck_ds
-};
-
-void() particle_stream_start =
-{
-local entity pspot;
-
- pspot = find(world, targetname, self.target);
- if(!pspot)
- {
- dprint("Particle stream can't find target!");
- return;
- }
-
- self.enemy = pspot;
-};
-
-/*QUAKED misc_particle_stream (0 .5 .8) (-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
-A particle stream! It appears when triggered. This entity is
-one end of the stream, target another entity as the other end-point.
-I used the info_notnull, but you should be able to target anything
-(like monsters).
-
-"target" This entities origin is the end-point of the stream
-"dmg" 1st Color - Use if you want a single color stream
-"cnt" 2nd Color - Mixes particles of both colors
-"noise" Sound to play when triggered
-*/
-void() misc_particle_stream =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if(!self.target)
- objerror("misc_particle_stream with not target!");
-
- if(!self.dmg)
- self.dmg = 73;
- if(!self.cnt)
- self.cnt = self.dmg;
- if(!self.noise)
- self.noise = "misc/null.wav";
-
- precache_sound(self.noise);
-
- self.use = particle_use;
- self.think = particle_stream_start;
- self.nextthink = time + 0.2;
-};
-

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

Diff qc/func/bob.qc

diff --git a/qc/func/bob.qc b/qc/func/bob.qc
new file mode 100644
index 0000000..57b83c7
--- /dev/null
+++ b/qc/func/bob.qc
@@ -0,0 +1,210 @@
+//==============================================================================
+// func_bob -- code attributed to RennyC
+//==============================================================================
+
+// fields
+.float attack_timer;
+.float bsporigin; // All bmodel origins are 0,0,0 check this first
+.float distance;
+.float waitmin2;
+
+// constants
+const float BOB_COLLISION = 2; // Collision for misc_bob
+const float BOB_NONSOLID = 4; // Non solid for func_bob
+
+//----------------------------------------------------------------------
+void() func_bob_timer =
+{
+ // Keep ticking in background, use local timer (faster)
+ self.think = func_bob_timer;
+
+ if (self.bsporigin)
+ self.nextthink = self.ltime + 0.1;
+ else
+ self.nextthink = time + 0.1;
+
+ // Has the cycle completed?
+ if (self.attack_timer < time)
+ {
+ // Setup bob cycle and half way point for slowdown
+ self.attack_timer = time + self.count;
+ self.distance = time + (self.count * 0.5);
+ // Flip direction of bmodel bob
+ self.lefty = 1 - self.lefty;
+ if (self.lefty < 1)
+ self.t_length = self.height;
+ else
+ self.t_length = -self.height;
+
+ // Always reset velocity and flags
+ self.velocity = '0 0 0';
+ self.flags = 0;
+ }
+
+ // Is the direction set?
+ // This is a block condition to prevent the bmodel moving
+ if (self.lefty != -1)
+ {
+ // Slow down velocity (gradually)
+ if (self.distance < time)
+ {
+ self.velocity = self.velocity * self.waitmin2;
+ }
+ else
+ {
+ // Speed up velocity (linear/exponentially)
+ self.t_length = self.t_length * self.waitmin;
+ self.velocity += self.movedir * self.t_length;
+ }
+ }
+};
+
+//----------------------------------------------------------------------
+void() func_bob_on =
+{
+ // This may have been called as a "use" function, so don't allow it
+ // to be called repeatedly -- iw
+ self.use = SUB_Null;
+
+ if (self.bsporigin)
+ {
+ self.movetype = MOVETYPE_PUSH;
+ self.solid = SOLID_BSP;
+ }
+ else
+ {
+ self.movetype = MOVETYPE_FLY;
+ self.solid = SOLID_BBOX;
+ // Reset any onground flags
+ self.flags = 0;
+ }
+
+ if (self.spawnflags & BOB_NONSOLID)
+ self.solid = SOLID_NOT;
+
+ setmodel (self, self.mdl);
+ setsize (self, self.mins , self.maxs);
+
+ self.think = func_bob_timer;
+ if (self.bsporigin)
+ self.nextthink = self.ltime + 0.1 + self.delay;
+ else
+ self.nextthink = time + 0.1 + self.delay;
+};
+
+//----------------------------------------------------------------------
+void() func_bob_off =
+{
+ if (self.bsporigin)
+ {
+ self.movetype = MOVETYPE_PUSH;
+ self.solid = SOLID_BSP;
+ }
+ else
+ {
+ self.movetype = MOVETYPE_FLY;
+ self.solid = SOLID_BBOX;
+ }
+
+ if (self.spawnflags & BOB_NONSOLID)
+ self.solid = SOLID_NOT;
+
+ setmodel (self, self.mdl);
+ setsize (self, self.mins , self.maxs);
+ self.velocity = '0 0 0';
+
+ if (self.style & 1)
+ self.use = func_bob_on;
+};
+
+/*QUAKED func_bob (0 .5 .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
+A SOLID bmodel that gently moves back and forth
+-------- KEYS --------
+targetname : trigger entity (works with entity state system)
+angle : direction movement, use "360" for angle 0
+height : direction intensity (def=8)
+count : direction cycle timer (def=2s, minimum=1s)
+waitmin : Speed up scale (def=1) 1+=non linear
+waitmin2 : Slow down scale (def=0.75)
+delay : Starting time delay (def=0, -1=random)
+style : If set to 1, starts off and waits for trigger
+_dirt : -1 = will be excluded from dirtmapping
+_minlight : Minimum light level for any surface of the brush model
+_mincolor : Minimum light color for any surface (def='1 1 1' RGB)
+_shadow : Will cast shadows on other models and itself
+_shadowself : Will cast shadows on itself
+-------- SPAWNFLAGS --------
+STARTOFF : Starts off and waits for trigger - DISABLED, Ripped out ESTATE System (RennyC)
+-------- NOTES --------
+A SOLID bmodel that gently moves back and forth
+*/
+void() func_bob =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.spawnflags |= BOB_COLLISION;
+ if (self.spawnflags & BOB_NONSOLID)
+ self.spawnflags &= ~BOB_COLLISION;
+
+ // Using a custom model?
+ if (self.mdl == "")
+ {
+ self.bsporigin = TRUE;
+ self.mdl = self.model;
+ }
+ else
+ {
+ self.bsporigin = FALSE;
+ self.modelindex = 0;
+ self.model = "";
+ }
+
+ SetMovedir ();
+ self.movedir = normalize (self.movedir);
+
+ if (self.height <= 0)
+ // Direction intensity
+ self.height = 8;
+ if (self.count < 1)
+ // Direction switch timer
+ self.count = 2;
+ if (self.waitmin <= 0)
+ // Speed up
+ self.waitmin = 1;
+ if (self.waitmin2 <= 0)
+ // Slow down
+ self.waitmin2 = 0.75;
+ if (self.delay < 0)
+ self.delay = random() + random() + random();
+
+ // Setup Entity State functionality - Nope! (RennyC)
+ // if (self.targetname != "")
+ // self.use = func_bob_on;
+
+ // added style key 1 for start off -- dumptruck_ds
+ if (!self.style)
+ func_bob_on ();
+ else
+ func_bob_off ();
+};
+
+/*QUAKED misc_bob (0 0.5 0.8) (-8 -8 -8) (8 8 8) X BOB_COLLISION BOB_NONSOLID 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
+{
+ model ({"path" : mdl, "skin" : skin, "frame": frame});
+}
+Same as func_bob but uses a custom model instead of a brush. Use the mdl key to set the path of the model.
+*/
+void() misc_bob =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (self.mdl == "")
+ self.mdl = string_null;
+ precache_model (self.mdl);
+
+ func_bob ();
+};

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

Diff qc/func/bossgate.qc

diff --git a/qc/func/bossgate.qc b/qc/func/bossgate.qc
new file mode 100644
index 0000000..07f519a
--- /dev/null
+++ b/qc/func/bossgate.qc
@@ -0,0 +1,38 @@
+//==============================================================================
+// func_bossgate
+//==============================================================================
+
+// constants
+// For func_episodegate and func_bossgate appear when player has all runes
+const float BOSSGATE_REVERSE = 16;
+
+/*QUAKED func_bossgate (0 .5 .8) ? X X X X REVERSE_FUNCTIONALITY
+This bmodel appears unless players have all of the episode sigils.
+*/
+void() func_bossgate =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (self.spawnflags & BOSSGATE_REVERSE)
+ {
+ if (!((serverflags & 15) == 15))
+ {
+ // not all complete
+ return;
+ }
+ }
+ else
+ {
+ if ( (serverflags & 15) == 15 )
+ // all episodes completed
+ return;
+ }
+ self.angles = '0 0 0';
+ // so it doesn't get pushed by anything
+ self.movetype = MOVETYPE_PUSH;
+ self.solid = SOLID_BSP;
+ self.use = func_wall_use;
+ setmodel (self, self.model);
+};

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

Diff qc/func/breakable.qc

diff --git a/qc/func/breakable.qc b/qc/func/breakable.qc
new file mode 100644
index 0000000..3cfb7b8
--- /dev/null
+++ b/qc/func/breakable.qc
@@ -0,0 +1,581 @@
+//==============================================================================
+// func_breakable -- AD breakable code modified by Qmaster, iw, and dumptruck_ds
+//==============================================================================
+
+// constants
+const float BREAKABLE_NO_MONSTERS = 1;
+const float BREAK_EXPLODE = 2;
+const float BREAK_CUSTOM = 4;
+const float START_OFF = 1;
+const float SPARKS_BLUE = 2;
+const float SPARKS_PALE = 4;
+
+// prototypes
+void() make_breakable_debris;
+
+// fields
+.string break_template1;
+.string break_template2;
+.string break_template3;
+.string break_template4;
+.string break_template5;
+.float brk_obj_count1;
+.float brk_obj_count2;
+.float brk_obj_count3;
+.float brk_obj_count4;
+.float brk_obj_count5;
+
+//----------------------------------------------------------------------
+// template system from Qmaster -- dumptruck_ds
+//----------------------------------------------------------------------
+void() make_breakable_templates_debris =
+{
+ local float i;
+ local entity new;
+
+ i = 0;
+ if (self.break_template1 != "")
+ {
+ while (i < self.brk_obj_count1)
+ {
+ new = spawn ();
+ new.model = self.break_template1;
+ new.origin_x = (self.maxs_x - self.mins_x) *
+ random() + self.mins_x;
+ new.origin_y = (self.maxs_y - self.mins_y) *
+ random() + self.mins_y;
+ new.origin_z = (self.maxs_z - self.mins_z) *
+ random() + self.mins_z;
+ // dumptruck_ds
+ setmodel (new, new.model);
+ setsize (new, '0 0 0', '0 0 0');
+ new.velocity = VelocityForDamage (self.health * 2);
+ new.movetype = MOVETYPE_BOUNCE;
+ new.solid = SOLID_NOT;
+ new.avelocity_x = random() * 600;
+ new.avelocity_y = random() * 600;
+ new.avelocity_z = random() * 600;
+ new.think = SUB_Remove;
+ new.ltime = time;
+ new.nextthink = time + 10 + random() * 10;
+ new.flags = 0;
+ i++;
+ }
+ }
+
+ i = 0;
+ if (self.break_template2 != "")
+ {
+ while (i < self.brk_obj_count2)
+ {
+ new = spawn ();
+ new.model = self.break_template2;
+ new.origin_x = (self.maxs_x - self.mins_x) *
+ random() + self.mins_x;
+ new.origin_y = (self.maxs_y - self.mins_y) *
+ random() + self.mins_y;
+ new.origin_z = (self.maxs_z - self.mins_z) *
+ random() + self.mins_z;
+ // dumptruck_ds
+ setmodel (new, new.model);
+ setsize (new, '0 0 0', '0 0 0');
+ new.velocity = VelocityForDamage (self.health * 2);
+ new.movetype = MOVETYPE_BOUNCE;
+ new.solid = SOLID_NOT;
+ new.avelocity_x = random() * 600;
+ new.avelocity_y = random() * 600;
+ new.avelocity_z = random() * 600;
+ new.think = SUB_Remove;
+ new.ltime = time;
+ new.nextthink = time + 10 + random() * 10;
+ new.flags = 0;
+ i++;
+ }
+ }
+
+ i = 0;
+ if (self.break_template3 != "")
+ {
+ while (i < self.brk_obj_count3)
+ {
+ new = spawn ();
+ new.model = self.break_template3;
+ new.origin_x = (self.maxs_x - self.mins_x) *
+ random() + self.mins_x;
+ new.origin_y = (self.maxs_y - self.mins_y) *
+ random() + self.mins_y;
+ new.origin_z = (self.maxs_z - self.mins_z) *
+ random() + self.mins_z;
+ // dumptruck_ds
+ setmodel (new, new.model);
+ setsize (new, '0 0 0', '0 0 0');
+ new.velocity = VelocityForDamage (self.health * 2);
+ new.movetype = MOVETYPE_BOUNCE;
+ new.solid = SOLID_NOT;
+ new.avelocity_x = random() * 600;
+ new.avelocity_y = random() * 600;
+ new.avelocity_z = random() * 600;
+ new.think = SUB_Remove;
+ new.ltime = time;
+ new.nextthink = time + 10 + random() * 10;
+ new.flags = 0;
+ i++;
+ }
+ }
+
+ i = 0;
+ if (self.break_template4 != "")
+ {
+ while (i < self.brk_obj_count4)
+ {
+ new = spawn ();
+ new.model = self.break_template4;
+ new.origin_x = (self.maxs_x - self.mins_x) *
+ random() + self.mins_x;
+ new.origin_y = (self.maxs_y - self.mins_y) *
+ random() + self.mins_y;
+ new.origin_z = (self.maxs_z - self.mins_z) *
+ random() + self.mins_z;
+ // dumptruck_ds
+ setmodel (new, new.model);
+ setsize (new, '0 0 0', '0 0 0');
+ new.velocity = VelocityForDamage (self.health * 2);
+ new.movetype = MOVETYPE_BOUNCE;
+ new.solid = SOLID_NOT;
+ new.avelocity_x = random() * 600;
+ new.avelocity_y = random() * 600;
+ new.avelocity_z = random() * 600;
+ new.think = SUB_Remove;
+ new.ltime = time;
+ new.nextthink = time + 10 + random() * 10;
+ new.flags = 0;
+ i++;
+ }
+ }
+
+ i = 0;
+ if (self.break_template5 != "")
+ {
+ while (i < self.brk_obj_count5)
+ {
+ new = spawn ();
+ new.model = self.break_template5;
+ new.origin_x = (self.maxs_x - self.mins_x) *
+ random() + self.mins_x;
+ new.origin_y = (self.maxs_y - self.mins_y) *
+ random() + self.mins_y;
+ new.origin_z = (self.maxs_z - self.mins_z) *
+ random() + self.mins_z;
+ // dumptruck_ds
+ setmodel (new, new.model);
+ setsize (new, '0 0 0', '0 0 0');
+ new.velocity = VelocityForDamage (self.health * 2);
+ new.movetype = MOVETYPE_BOUNCE;
+ new.solid = SOLID_NOT;
+ new.avelocity_x = random() * 600;
+ new.avelocity_y = random() * 600;
+ new.avelocity_z = random() * 600;
+ new.think = SUB_Remove;
+ new.ltime = time;
+ new.nextthink = time + 10 + random() * 10;
+ new.flags = 0;
+ i++;
+ }
+ }
+};
+
+
+//======================================================================
+// Below this is from Rubicon2 -- dumptruck_ds
+//======================================================================
+
+//----------------------------------------------------------------------
+void() make_breakable_debris =
+{
+ local float i = 0;
+
+ while (i < self.cnt)
+ {
+ local entity new;
+
+ new = spawn ();
+ new.origin_x = (self.maxs_x - self.mins_x) *
+ random() + self.mins_x;
+ new.origin_y = (self.maxs_y - self.mins_y) *
+ random() + self.mins_y;
+ new.origin_z = (self.maxs_z - self.mins_z) *
+ random() + self.mins_z;
+
+ // this was originally just an mdl from Rubicon2, now you
+ // set custom model via spawnflag or use the builtin from
+ // Rubicon2 -- dumptruck_ds
+ // setmodel (new, "progs/debris.mdl");
+
+ // dumptruck_ds
+ setmodel (new, self.mdl_debris);
+ setsize (new, '0 0 0', '0 0 0');
+ new.velocity = VelocityForDamage (self.health * 2);
+ new.movetype = MOVETYPE_BOUNCE;
+ new.solid = SOLID_NOT;
+ new.avelocity_x = random() * 600;
+ new.avelocity_y = random() * 600;
+ new.avelocity_z = random() * 600;
+ new.think = SUB_Remove;
+ new.ltime = time;
+ new.nextthink = time + 10 + random() * 10;
+ new.flags = 0;
+
+ // randomly choose size
+ if (random() > 0.333)
+ // larger
+ new.frame = 1;
+ else
+ // smaller
+ new.frame = 2;
+
+ // choose skin based on "style" key
+ if (self.style == 1)
+ new.skin = 1;
+ if (self.style == 2)
+ new.skin = 2;
+ if (self.style == 3)
+ // new debris skins start here - dumptruck_ds
+ new.skin = 3;
+ if (self.style == 4)
+ new.skin = 4;
+ if (self.style == 5)
+ new.skin = 5;
+ if (self.style == 6)
+ new.skin = 6;
+ if (self.style == 7)
+ new.skin = 7;
+ if (self.style == 8)
+ new.skin = 8;
+ if (self.style == 9)
+ new.skin = 9;
+ if (self.style == 10)
+ new.skin = 10;
+ if (self.style == 11)
+ new.skin = 11;
+ if (self.style == 12)
+ new.skin = 12;
+ if (self.style == 13)
+ new.skin = 13;
+ if (self.style == 14)
+ new.skin = 14;
+ if (self.style == 15)
+ new.skin = 15;
+ if (self.style == 16)
+ new.skin = 16;
+ if (self.style == 17)
+ new.skin = 17;
+ if (self.style == 18)
+ new.skin = 18;
+ if (self.style == 19)
+ new.skin = 19;
+ if (self.style == 20)
+ new.skin = 20;
+ if (self.style == 21)
+ new.skin = 21;
+ if (self.style == 22)
+ new.skin = 22;
+ if (self.style == 23)
+ new.skin = 23;
+ if (self.style == 24)
+ new.skin = 24;
+ if (self.style == 25)
+ new.skin = 25;
+ if (self.style == 26)
+ new.skin = 26;
+ if (self.style == 27)
+ new.skin = 27;
+ if (self.style == 28)
+ new.skin = 28;
+ if (self.style == 29)
+ new.skin = 29;
+ if (self.style == 30)
+ new.skin = 30;
+ if (self.style == 31)
+ // new debris skins end here - dumptruck_ds
+ new.skin = 31;
+
+ i = i + 1;
+ }
+};
+
+//----------------------------------------------------------------------
+// dumptruck_ds -- set the spawnflag for cosmetic explosion effect;
+// use "dmg" value to hurt the player
+//----------------------------------------------------------------------
+void() func_breakable_die =
+{
+ {
+ // thanks to Qmaster!!! He helped me sort out noise1
+ // playing from 0 0 0 with this temp entity - dumptruck_ds
+ local entity ent;
+
+ ent = spawn ();
+ ent.origin = ((self.absmin + self.absmax) * 0.5);
+ setsize (ent, '0 0 0', '0 0 0');
+ ent.solid = SOLID_NOT;
+ ent.think = SUB_Remove;
+ // ent.ltime = time;
+ ent.nextthink = time + 60;
+
+ sound (ent, CHAN_AUTO, self.noise1, 1, ATTN_NORM);
+ // remove (self);
+ }
+
+ // this is to ensure that any debris from another func_breakable
+ // which is resting on top of this func_breakable is not left
+ // floating in mid-air after this entity is removed -- iw
+ SUB_DislodgeRestingEntities ();
+
+ if (self.spawnflags & BREAK_EXPLODE)
+ {
+ if (self.spawnflags & BREAK_CUSTOM)
+ {
+ make_breakable_templates_debris ();
+ }
+ else
+ {
+ make_breakable_debris ();
+ }
+ // to let us use noise2
+ func_explobox_explode_silent ();
+
+ // this is broken as of 1.1.0 no custom explosion sound
+ // for now -- dumptruck_ds
+ // sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+ remove (self);
+ }
+ else
+ {
+ self.origin = ((self.absmin + self.absmax) * 0.5);
+ setorigin (self, self.origin);
+ DropStuff ();
+ if (self.spawnflags & BREAK_CUSTOM)
+ {
+ if (self.switchshadstyle)
+ lightstyle(self.switchshadstyle, "m");
+ make_breakable_templates_debris ();
+ remove (self);
+ }
+ else
+ {
+ if (self.switchshadstyle)
+ lightstyle(self.switchshadstyle, "m");
+ make_breakable_debris ();
+ remove (self);
+ }
+ }
+};
+
+//----------------------------------------------------------------------
+void() func_breakable_killed =
+{
+ activator = damage_attacker;
+ SUB_UseTargets ();
+ func_breakable_die ();
+};
+
+//----------------------------------------------------------------------
+void() func_breakable_use =
+{
+ activator = other;
+ SUB_UseTargets ();
+ func_breakable_die ();
+};
+
+//----------------------------------------------------------------------
+void() break_template_setup =
+{
+ if (self.break_template1 != "")
+ precache_model (self.break_template1);
+ if (self.break_template2 != "")
+ precache_model (self.break_template2);
+ if (self.break_template3 != "")
+ precache_model (self.break_template3);
+ if (self.break_template4 != "")
+ precache_model (self.break_template4);
+ if (self.break_template5 != "")
+ precache_model (self.break_template5);
+};
+
+/*QUAKED func_breakable (0 .5 .8) ? NO_MONSTERS 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
+
+"Breakable - See manual for full details
+
+Defaults to built-in .mdl file with 32 styles, cnt is number of pieces of debris to spawn (built-in only)
+Or use spawnflag 4 and break_template1-4 to set path of custom .mdl or .bsp models.
+brk_object_count1-4 sets the number of pieces of each break_template when using custom .mdl or bsp models.
+If noise1 is not set it will default to various sounds in sounds/break folder
+Use spawnflag 2 for an explosion, dmg is amount of damage inflicted"
+
+spawnflags(flags)
+1 : "No Monster Damage" : 0 : "Only the player can break"
+2 : "Explosion" : 0 : "Produces explosion effect and sound"
+4 : "Use custom mdls or bsp models" : 0 : "Uses models specified in break_template1, 2, etc"
+
+style(choices) : "Built-in debris style" : 0
+0 : "Green Metal (default)"
+1 : "Red Metal"
+2 : "Concrete"
+3 : "Pine wood"
+4 : "Brown wood"
+5 : "Red wood"
+6 : "Stained Glass Yellow Flames"
+7 : "Stained Glass Red Rays"
+8 : "Stained Glass Yellow Dragon"
+9 : "Stained Glass Blue Dragon"
+10 : "Stained Glass Red Dragon"
+11 : "Light Copper"
+12 : "Dark Copper"
+13 : "Tan Bricks Large"
+14 : "Brown Bricks Large"
+15 : "Green Bricks Large"
+16 : "Generic Light Brown"
+17 : "Red Brown Computer"
+18 : "Grey Black Computer"
+19 : "Blue Green Metal"
+20 : "Blue Green Runic Wall"
+21 : "Brown Metal"
+22 : "Dark Brown Metal"
+23 : "Medium Brown Metal"
+24 : "Blue Metal"
+25 : "Green Stonework"
+26 : "Blue Stonework"
+27 : "Brown Bricks"
+28 : "Tan Blue Bricks"
+29 : "Red Bricks"
+30 : "Blue Bricks"
+31 : "Metal Rivets"
+
+noise1(string) : "Break noise (overrides default sounds)"
+cnt(integer) : "Number of pieces of debris to spawn" : 5
+health(integer) : "Health of breakable" : 20
+dmg(integer) : "Amount of Explosive Damage" : 20
+break_template1(string) : "Template 1 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
+break_template2(string) : "Template 2 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
+break_template3(string) : "Template 3 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
+break_template4(string) : "Template 4 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
+break_template5(string) : "Template 5 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
+brk_obj_count1(integer) : "Template 1 spawn count"
+brk_obj_count2(integer) : "Template 2 spawn count"
+brk_obj_count3(integer) : "Template 3 spawn count"
+brk_obj_count4(integer) : "Template 4 spawn count"
+brk_obj_count5(integer) : "Template 5 spawn count"
+*/
+void() func_breakable =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ break_template_setup ();
+
+ self.solid = SOLID_BSP;
+ self.movetype = MOVETYPE_PUSH;
+ setmodel (self, self.model);
+ self.mdl_debris = "progs/debris.mdl";
+ precache_model (self.mdl_debris);
+ precache_sound ("blob/hit1.wav");
+
+ if (self.noise1 != "")
+ precache_sound(self.noise1);
+
+ // adding new default sounds for "simple" breakables in 1.2.0
+ // -- dumptruck_ds
+
+ // here's genreic metal breaking
+ if (self.style == 0 || self.style == 11 || self.style == 12 ||
+ self.style == 17 || self.style == 18 || self.style == 19 ||
+ self.style == 24 || self.style == 31)
+ {
+ if !(self.noise1)
+ {
+ precache_sound ("break/metal2.wav");
+ self.noise1 = "break/metal2.wav";
+ }
+ }
+
+ if (self.style == 3 || self.style == 4 || self.style == 5)
+ {
+ if !(self.noise1)
+ {
+ precache_sound ("break/wood1.wav");
+ precache_sound ("break/wood2.wav");
+ // wood only randomized
+ if (random() > 0.6)
+ self.noise1 = "break/wood1.wav";
+ else
+ self.noise1 = "break/wood2.wav";
+ }
+ }
+
+ // glass sounds -- this is more of a shattering sound anyway
+ if (self.style == 6 || self.style == 7 || self.style == 8 ||
+ self.style == 9 || self.style == 10)
+ {
+ if !(self.noise1)
+ {
+ precache_sound ("break/metal1.wav");
+ self.noise1 = "break/metal1.wav";
+ }
+ }
+
+ if (self.style == 1 || self.style == 2 || self.style == 13 ||
+ self.style == 14 || self.style == 15 || self.style == 16 ||
+ self.style == 20 || self.style == 21 || self.style == 22 ||
+ self.style == 23)
+ {
+ if !(self.noise1)
+ {
+ precache_sound ("break/stones1.wav");
+ precache_sound ("break/bricks1.wav");
+ // wood only randomized
+ if (random() > 0.6)
+ self.noise1 = "break/bricks1.wav";
+ else
+ self.noise1 = "break/stones1.wav";
+ }
+ }
+
+ if (self.style == 25 || self.style == 26 || self.style == 27 ||
+ self.style == 28 || self.style == 29 || self.style == 30)
+ {
+ if !(self.noise1)
+ {
+ precache_sound ("break/stones1.wav");
+ precache_sound ("break/bricks1.wav");
+ // wood only randomized
+ if (random() > 0.6)
+ self.noise1 = "break/stones1.wav";
+ else
+ self.noise1 = "break/bricks1.wav";
+ }
+ // else
+ // {
+ // (self.noise1 = "blob/hit1.wav");
+ // }
+ }
+
+ if (!self.health)
+ self.health = 20;
+ if (!self.cnt)
+ // was 6 dumptruck_ds
+ self.cnt = 5;
+
+ if (self.targetname != "")
+ {
+ self.use = func_breakable_use;
+ }
+ else
+ {
+ self.takedamage = DAMAGE_YES;
+ self.th_die = func_breakable_killed;
+ }
+
+ if (self.switchshadstyle)
+ lightstyle (self.switchshadstyle, "a");
+};

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

Diff qc/func/brush.qc

diff --git a/qc/func/brush.qc b/qc/func/brush.qc
new file mode 100644
index 0000000..db7fc5c
--- /dev/null
+++ b/qc/func/brush.qc
@@ -0,0 +1,89 @@
+//==============================================================================
+// func_brush
+//==============================================================================
+
+//this is on hold and not in progs.src
+// crashes in QS at the moment Jaycie is looking into it
+
+// fields
+.float solidstate;
+.float visiblestate;
+
+// constants
+const float START_INVISIBLE = 1;
+const float START_NONSOLID = 2;
+const float START_ALTFRAMES = 4;
+const float TOGGLE_VISIBILITY = 8;
+const float TOGGLE_SOLIDITY = 16;
+const float TOGGLE_FRAMES = 32;
+
+//----------------------------------------------------------------------
+void() func_brush_use =
+{
+ if (self.spawnflags & TOGGLE_VISIBILITY)
+ {
+ if (self.visiblestate == 1)
+ {
+ self.model = "";
+ self.visiblestate = 0;
+ }
+ else
+ {
+ self.model = self.mdl;
+ self.visiblestate = 1;
+ }
+ }
+ if (self.spawnflags & TOGGLE_SOLIDITY)
+ {
+ if (self.solidstate == 1)
+ {
+ self.solid = SOLID_NOT;
+ self.solidstate = 0;
+ }
+ else
+ {
+ self.solid = SOLID_BSP;
+ setorigin(self, self.origin);
+ self.solidstate = 1;
+ }
+ }
+ if (self.spawnflags & TOGGLE_FRAMES)
+ self.frame = 1 - self.frame;
+};
+
+//----------------------------------------------------------------------
+void() func_brush =
+{
+ self.angles = '0 0 0';
+ self.movetype = MOVETYPE_NONE;
+ self.use = func_brush_use;
+ setmodel (self, self.model);
+ self.mdl = self.model;
+ setorigin (self, self.origin);
+
+ if (self.spawnflags & START_INVISIBLE)
+ {
+ self.visiblestate = 0;
+ self.model = "";
+ }
+ else
+ {
+ self.visiblestate = 1;
+ }
+
+ if (self.spawnflags & START_NONSOLID)
+ {
+ self.solidstate = 0;
+ self.solid = SOLID_NOT;
+ }
+ else
+ {
+ self.solidstate = 1;
+ self.solid = SOLID_BSP;
+ }
+
+ if (self.spawnflags & START_ALTFRAMES)
+ self.frame = 1;
+ else
+ self.frame = 0;
+};

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

Diff qc/func/button.qc

diff --git a/qc/func/button.qc b/qc/func/button.qc
new file mode 100644
index 0000000..36ac256
--- /dev/null
+++ b/qc/func/button.qc
@@ -0,0 +1,235 @@
+//==============================================================================
+// func_button -- button and multiple button
+//==============================================================================
+
+// prototypes
+void() button_wait;
+void() button_return;
+
+//----------------------------------------------------------------------
+void() button_wait =
+{
+ self.state = STATE_TOP;
+ self.nextthink = self.ltime + self.wait;
+ self.think = button_return;
+ activator = self.enemy;
+ // use alternate textures
+ self.frame = 1;
+
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ SUB_UseTargets ();
+};
+
+//----------------------------------------------------------------------
+void() button_done =
+{
+ self.state = STATE_BOTTOM;
+};
+
+//----------------------------------------------------------------------
+void() button_return =
+{
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ self.state = STATE_DOWN;
+ SUB_CalcMove (self.pos1, self.speed, button_done);
+ // use normal textures
+ self.frame = 0;
+
+ if (self.health)
+ // can be shot again
+ self.takedamage = DAMAGE_YES;
+};
+
+//----------------------------------------------------------------------
+void() button_blocked =
+{
+ // do nothing, just don't ome all the way back out
+};
+
+//----------------------------------------------------------------------
+void() button_fire =
+{
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ if (self.state == STATE_UP || self.state == STATE_TOP)
+ return;
+
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+
+ self.state = STATE_UP;
+ SUB_CalcMove (self.pos2, self.speed, button_wait);
+};
+
+//----------------------------------------------------------------------
+void() button_use =
+{
+ self.enemy = activator;
+ button_fire ();
+};
+
+//----------------------------------------------------------------------
+void() button_touch =
+{
+ if (other.classname != "player")
+ return;
+
+ self.enemy = other;
+ button_fire ();
+};
+
+//----------------------------------------------------------------------
+void() button_killed =
+{
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ self.enemy = damage_attacker;
+ self.health = self.max_health;
+ // wil be reset upon return
+ self.takedamage = DAMAGE_NO;
+
+ button_fire ();
+};
+
+//----------------------------------------------------------------------
+// adapted from Copper, thanks Lunaran
+//----------------------------------------------------------------------
+void(entity b) button_lock =
+{
+ entity oself;
+
+ if (b.estate == STATE_INACTIVE)
+ return;
+
+ oself = self;
+ self = b;
+
+ if (self.state == STATE_UP || self.state == STATE_TOP)
+ self.prevstate = STATE_TOP;
+ else
+ self.prevstate = STATE_BOTTOM;
+
+ if (self.max_health)
+ self.takedamage = DAMAGE_NO;
+
+ self.state = STATE_UP;
+ SUB_CalcMove (self.pos2, self.speed, button_wait);
+ self.estate = STATE_INACTIVE;
+
+ self = oself;
+};
+
+//----------------------------------------------------------------------
+void(entity b, float dontresetstate) button_unlock =
+{
+ entity oself;
+
+ if (b.estate == STATE_ACTIVE)
+ return;
+
+ oself = self;
+ self = b;
+
+ if (!dontresetstate || self.wait != -1 ||
+ self.prevstate == STATE_BOTTOM)
+ {
+ if (self.max_health)
+ {
+ self.takedamage = DAMAGE_YES;
+ self.health = self.max_health;
+ }
+
+ // use normal textures
+ self.frame = 0;
+ self.state = STATE_DOWN;
+ SUB_CalcMove (self.pos1, self.speed, button_done);
+ }
+
+ self.estate = STATE_ACTIVE;
+
+ self = oself;
+};
+
+/*QUAKED func_button (0 .5 .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
+When a button is touched, it moves some distance in the direction of it's angle, triggers all of it's targets, waits some time, then returns to it's original position where it can be triggered again.
+
+"angle" determines the opening direction
+"target" all entities with a matching targetname will be used
+"speed" override the default 40 speed
+"wait" override the default 1 second wait (-1 = never return)
+"lip" override the default 4 pixel lip remaining at end of move
+"health" if set, the button must be killed instead of touched
+"sounds"
+0) steam metal
+1) wooden clunk
+2) metallic click
+3) in-out
+*/
+void() func_button =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (self.sounds == 0)
+ {
+ precache_sound ("buttons/airbut1.wav");
+ self.noise = "buttons/airbut1.wav";
+ }
+
+ if (self.sounds == 1)
+ {
+ precache_sound ("buttons/switch21.wav");
+ self.noise = "buttons/switch21.wav";
+ }
+
+ if (self.sounds == 2)
+ {
+ precache_sound ("buttons/switch02.wav");
+ self.noise = "buttons/switch02.wav";
+ }
+
+ if (self.sounds == 3)
+ {
+ precache_sound ("buttons/switch04.wav");
+ self.noise = "buttons/switch04.wav";
+ }
+
+ SetMovedir ();
+
+ self.movetype = MOVETYPE_PUSH;
+ self.solid = SOLID_BSP;
+ setmodel (self, self.model);
+
+ self.blocked = button_blocked;
+ self.use = button_use;
+
+ if (self.health)
+ {
+ self.max_health = self.health;
+ self.th_die = button_killed;
+ self.takedamage = DAMAGE_YES;
+ }
+ else
+ {
+ self.touch = button_touch;
+ }
+
+ if (!self.speed)
+ self.speed = 40;
+ if (!self.wait)
+ self.wait = 1;
+ if (!self.lip)
+ self.lip = 4;
+
+ self.state = STATE_BOTTOM;
+
+ self.pos1 = self.origin;
+ self.pos2 = self.pos1 + self.movedir *
+ (fabs(self.movedir * self.size) - self.lip);
+};

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

Diff qc/func/counter.qc

diff --git a/qc/func/counter.qc b/qc/func/counter.qc
new file mode 100644
index 0000000..209c801
--- /dev/null
+++ b/qc/func/counter.qc
@@ -0,0 +1,234 @@
+//==============================================================================
+// func_counter, func_oncount -- Hipnotic Interactive, Jim Dose'
+//==============================================================================
+
+// Counter QuickC program
+// By Jim Dose' 9/13/96
+// Copyright (c)1996 Hipnotic Interactive, Inc.
+// All rights reserved.
+// Distributed (unsupported) on 3.12.97
+
+// constants
+const float COUNTER_TOGGLE = 1;
+const float COUNTER_LOOP = 2;
+const float COUNTER_STEP = 4;
+const float COUNTER_RESET = 8;
+const float COUNTER_RANDOM = 16;
+const float COUNTER_FINISHCOUNT = 32;
+const float COUNTER_START_ON = 64;
+
+// prototypes
+void() counter_on_use;
+void() counter_off_use;
+
+//----------------------------------------------------------------------
+void() counter_think =
+{
+ self.cnt = self.cnt + 1;
+ if (self.spawnflags & COUNTER_RANDOM)
+ {
+ self.state = random() * self.count;
+ self.state = floor(self.state) + 1;
+ }
+ else
+ {
+ self.state = self.cnt;
+ }
+
+ // fix func_counter and func_oncount handling of activator -- iw
+ // activator = other;
+ activator = self.enemy;
+ SUB_UseTargets ();
+ self.nextthink = time + self.wait;
+
+ if (self.spawnflags & COUNTER_STEP)
+ {
+ counter_on_use ();
+ }
+
+ if (self.cnt >= self.count)
+ {
+ self.cnt = 0;
+ if ((self.aflag) || !(self.spawnflags & COUNTER_LOOP))
+ {
+ if (self.spawnflags & COUNTER_TOGGLE)
+ {
+ counter_on_use ();
+ }
+ else
+ {
+ remove (self);
+ }
+ }
+ }
+};
+
+//----------------------------------------------------------------------
+// counter_start_on_think
+// fix func_counter and func_oncount handling of activator -- iw
+//----------------------------------------------------------------------
+void() counter_start_on_think =
+{
+ // to ensure it's not a random entity -- iw
+ activator = world;
+ counter_off_use ();
+};
+
+//----------------------------------------------------------------------
+void() counter_on_use =
+{
+ if (( self.cnt != 0) && (self.spawnflags & COUNTER_FINISHCOUNT))
+ {
+ self.aflag = TRUE;
+ return;
+ }
+
+ self.use = counter_off_use;
+ self.think = SUB_Null;
+ self.aflag = FALSE;
+};
+
+//----------------------------------------------------------------------
+void() counter_off_use =
+{
+ self.aflag = FALSE;
+ if (self.spawnflags & COUNTER_TOGGLE)
+ {
+ self.use = counter_on_use;
+ }
+ else
+ {
+ self.use = SUB_Null;
+ }
+
+ if (self.spawnflags & COUNTER_RESET)
+ {
+ self.cnt = 0;
+ self.state = 0;
+ }
+
+ // fix func_counter and func_oncount handling of activator -- iw
+ self.enemy = activator;
+ self.think = counter_think;
+
+ // fix "delay" making func_counter not work -- iw
+ // if (self.delay)
+ if (self.pausetime)
+ {
+ // fix "delay" making func_counter not work -- iw
+ // self.nextthink = time + self.delay;
+ self.nextthink = time + self.pausetime;
+ }
+ else
+ {
+ counter_think ();
+ }
+};
+
+//----------------------------------------------------------------------
+float(entity counter) counter_GetCount =
+{
+ if (counter.classname == "counter")
+ {
+ return counter.state;
+ }
+
+ return 0;
+};
+
+/*QUAKED func_counter (0 0 0.5) (0 0 0) (32 32 32) TOGGLE LOOP STEP RESET RANDOM FINISHCOUNT START_ON 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
+TOGGLE causes the counter to switch between an on and off state
+each time the counter is triggered.
+
+LOOP causes the counter to repeat infinitly. The count resets to zero
+after reaching the value in "count".
+
+STEP causes the counter to only increment when triggered. Effectively,
+this turns the counter into a relay with counting abilities.
+
+RESET causes the counter to reset to 0 when restarted.
+
+RANDOM causes the counter to generate random values in the range 1 to "count"
+at the specified interval.
+
+FINISHCOUNT causes the counter to continue counting until it reaches "count"
+before shutting down even after being set to an off state.
+
+START_ON causes the counter to be on when the level starts.
+
+"count" specifies how many times to repeat the event. If LOOP is set,
+it specifies how high to count before reseting to zero. Default is 10.
+
+"wait" the length of time between each trigger event. Default is 1 second.
+
+"delay" how much time to wait before firing after being switched on.
+*/
+void() func_counter =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.wait)
+ self.wait = 1;
+
+ self.count = floor (self.count);
+ if (self.count <= 0)
+ self.count = 10;
+
+ // fix "delay" making func_counter not work -- iw
+ self.pausetime = self.delay;
+ self.delay = 0;
+
+ self.cnt = 0;
+ self.state = 0;
+
+ self.classname = "counter";
+ self.use = counter_off_use;
+ self.think = SUB_Null;
+
+ if (self.spawnflags & COUNTER_START_ON)
+ {
+ // fix func_counter and func_oncount handling of activator -- iw
+ // self.think = counter_off_use;
+ self.think = counter_start_on_think;
+ self.nextthink = time + 0.1;
+ }
+};
+
+//----------------------------------------------------------------------
+void() oncount_use =
+{
+ if (counter_GetCount(other) == self.count)
+ {
+ // fix func_counter and func_oncount handling of activator -- iw
+ // activator = other;
+ SUB_UseTargets ();
+ }
+};
+
+/*QUAKED func_oncount (0 0 0.5) (0 0 0) (16 16 16)
+Must be used as the target for func_counter. When the counter
+reaches the value set by count, func_oncount triggers its targets.
+
+"count" specifies the value to trigger on. Default is 1.
+
+"delay" how much time to wait before firing after being triggered.
+*/
+void() func_oncount =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.count = floor (self.count);
+
+ if (self.count <= 0)
+ {
+ self.count = 1;
+ }
+
+ self.classname = "oncount";
+ self.use = oncount_use;
+ self.think = SUB_Null;
+};

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

Diff qc/func/door.qc

diff --git a/qc/func/door.qc b/qc/func/door.qc
new file mode 100644
index 0000000..45600a2
--- /dev/null
+++ b/qc/func/door.qc
@@ -0,0 +1,737 @@
+//==============================================================================
+// func_door
+//==============================================================================
+
+//----------------------------------------------------------------------
+// Doors are similar to buttons, but can spawn a fat trigger field around
+// them to open without a touch, and they link together to form simultanious
+// double/quad doors.
+//
+// Door.owner is the master door. If there is only one door, it points to
+// itself. If multiple doors, all will point to a single one.
+//
+// Door.enemy chains from the master door through all doors linked in the chain.
+//----------------------------------------------------------------------
+
+// constants
+const float DOOR_START_OPEN = 1;
+const float DOOR_DONT_LINK = 4;
+const float DOOR_GOLD_KEY = 8;
+const float DOOR_SILVER_KEY = 16;
+const float DOOR_TOGGLE = 32;
+const float DOOR_DOOM_STYLE_UNLOCK = 64;
+
+// prototypes
+void() door_go_down;
+void() door_go_up;
+
+//----------------------------------------------------------------------
+// THINK FUNCTIONS
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+void() door_blocked =
+{
+ T_Damage (other, self, self, self.dmg);
+
+ // if a door has a negative wait, it would never come back if blocked,
+ // so let it just squash the object to death real fast
+ if (self.wait >= 0)
+ {
+ if (self.state == STATE_DOWN)
+ door_go_up ();
+ else
+ door_go_down ();
+ }
+};
+
+//----------------------------------------------------------------------
+void() door_hit_top =
+{
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_TOP;
+ if (self.spawnflags & DOOR_TOGGLE)
+ // don't come down automatically
+ return;
+ self.think = door_go_down;
+ self.nextthink = self.ltime + self.wait;
+};
+
+//----------------------------------------------------------------------
+void() door_hit_bottom =
+{
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_BOTTOM;
+};
+
+//----------------------------------------------------------------------
+void() door_go_down =
+{
+ local entity oldself, shadow;
+
+ sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+ if (self.max_health)
+ {
+ self.takedamage = DAMAGE_YES;
+ self.health = self.max_health;
+ }
+
+ self.state = STATE_DOWN;
+ SUB_CalcMove (self.pos1, self.speed, door_hit_bottom);
+
+ if (self.switchshadstyle)
+ {
+ shadow = self.shadowcontroller;
+ oldself = self;
+ self = shadow;
+
+ if (oldself.spawnflags & DOOR_START_OPEN)
+ {
+ shadow_fade_out ();
+ shadow.shadowoff = 1;
+ }
+ else
+ {
+ shadow_fade_in ();
+ shadow.shadowoff = 0;
+ }
+
+ self = oldself;
+ }
+};
+
+//----------------------------------------------------------------------
+void() door_go_up =
+{
+ local entity oldself, shadow;
+
+ if (self.state == STATE_UP)
+ // allready going up
+ return;
+
+ if (self.state == STATE_TOP)
+ {
+ // reset top wait time
+ self.nextthink = self.ltime + self.wait;
+ return;
+ }
+
+ sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+ self.state = STATE_UP;
+ SUB_CalcMove (self.pos2, self.speed, door_hit_top);
+
+ SUB_UseTargets ();
+
+ if (self.switchshadstyle)
+ {
+ shadow = self.shadowcontroller;
+ oldself = self;
+ self = shadow;
+
+ if (oldself.spawnflags & DOOR_START_OPEN)
+ {
+ shadow_fade_in ();
+ shadow.shadowoff = 0;
+ }
+ else
+ {
+ shadow_fade_out ();
+ shadow.shadowoff = 1;
+ }
+
+ self = oldself;
+ }
+};
+
+//----------------------------------------------------------------------
+void() door_group_go_down =
+{
+ local entity oself, starte;
+
+ oself = self;
+ starte = self;
+
+ do
+ {
+ door_go_down ();
+ self = self.enemy;
+ }
+ while ((self != starte) && (self != world));
+
+ self = oself;
+};
+
+//----------------------------------------------------------------------
+void() door_group_go_up =
+{
+ local entity oself, starte;
+
+ oself = self;
+ starte = self;
+
+ do
+ {
+ door_go_up ();
+ self = self.enemy;
+ }
+ while ((self != starte) && (self != world));
+
+ self = oself;
+};
+
+//----------------------------------------------------------------------
+// ACTIVATION FUNCTIONS
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+void() door_fire =
+{
+ if (self.owner != self)
+ objerror ("door_fire: self.owner != self");
+
+ if (self.estate != STATE_ACTIVE)
+ return;
+
+ // self.noise4 is now played in keylock_try_to_unlock -- iw
+
+ // no more message
+ self.message = string_null;
+
+
+ if (self.spawnflags & DOOR_TOGGLE)
+ {
+ if (self.state == STATE_UP || self.state == STATE_TOP)
+ {
+ door_group_go_down ();
+ return;
+ }
+ }
+
+ // trigger all paired doors
+ door_group_go_up ();
+};
+
+//----------------------------------------------------------------------
+void() door_use =
+{
+ local entity oself;
+
+ // door message are for touch only
+ self.message = "";
+
+ self.owner.message = "";
+ self.enemy.message = "";
+ oself = self;
+ self = self.owner;
+ door_fire ();
+ self = oself;
+};
+
+//----------------------------------------------------------------------
+void() door_trigger_touch =
+{
+ if (other.health <= 0)
+ return;
+
+ if (other.movetype == MOVETYPE_NOCLIP)
+ // from copper -- dumptruck_ds
+ return;
+
+ if (time < self.attack_finished)
+ return;
+
+ self.attack_finished = time + 1;
+
+ activator = other;
+ self = self.owner;
+ door_use ();
+};
+
+//----------------------------------------------------------------------
+void() door_killed =
+{
+ local entity oself;
+
+ oself = self;
+ self = self.owner;
+ self.health = self.max_health;
+ // wil be reset upon return
+ self.takedamage = DAMAGE_NO;
+ door_use ();
+ self = oself;
+};
+
+//----------------------------------------------------------------------
+// door_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
+// door_touch function. -- iw
+//----------------------------------------------------------------------
+void() door_unlock =
+{
+ if (!(self.spawnflags & DOOR_DOOM_STYLE_UNLOCK))
+ {
+ self.touch = SUB_Null;
+ if (self.enemy)
+ self.enemy.touch = SUB_Null; // get paired door
+ }
+ door_use ();
+};
+
+
+//----------------------------------------------------------------------
+// door_touch -- Prints messages and opens key doors
+//----------------------------------------------------------------------
+void() door_touch =
+{
+ // if (other.classname != "player")
+ // return;
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ if (self.owner.attack_finished > time)
+ return;
+
+ self.owner.attack_finished = time + 2;
+
+ if (self.owner.message != "")
+ {
+ centerprint (other, self.owner.message);
+ sound (other, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);
+ }
+
+ // key door stuff
+ if (!keylock_has_key_set())
+ return;
+
+ keylock_try_to_unlock (other, "", door_unlock);
+};
+
+//----------------------------------------------------------------------
+// ENTITY STATE FUNCTIONS
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+void(entity e, float closealldoors) door_estate_lock =
+{
+ local entity oself, next;
+
+ if (e.owner.estate == STATE_INACTIVE)
+ return;
+
+ // blocks linked doors from updating the same owner repeatedly
+ if (e.owner.last_setstate == self &&
+ e.owner.last_setstate_frame == framecount)
+ {
+ return;
+ }
+
+ oself = self;
+ self = e.owner;
+
+ self.estate = STATE_INACTIVE;
+
+ self.last_setstate = oself;
+ self.last_setstate_frame = framecount;
+
+ self.prevstate = self.state;
+
+ if (self.state == STATE_UP || self.state == STATE_TOP)
+ {
+ // don't close wait -1 nor toggleable doors...
+ // ...unless the trigger_setstate has a "Close all doors"
+ // spawnflag on
+ if (!(self.wait == -1 || (self.spawnflags & DOOR_TOGGLE)) ||
+ closealldoors)
+ {
+ door_group_go_down ();
+ }
+ }
+
+ if (self.max_health)
+ {
+ next = self;
+ do
+ {
+ // e.health = 0;
+ next.takedamage = DAMAGE_NO;
+ next = next.enemy;
+ }
+ while ((next != self) && (next != world));
+ }
+
+ self = oself;
+};
+
+//----------------------------------------------------------------------
+void(entity e, float openalldoors) door_estate_unlock =
+{
+ local entity oself, next;
+
+ if (e.owner.estate == STATE_ACTIVE)
+ return;
+
+ // blocks linked doors from updating the same owner repeatedly
+ if (e.owner.last_setstate == self &&
+ e.owner.last_setstate_frame == framecount)
+ {
+ return;
+ }
+
+ oself = self;
+ self = e.owner;
+
+ self.last_setstate = oself;
+ self.last_setstate_frame = framecount;
+
+ if (self.prevstate == STATE_UP || self.prevstate == STATE_TOP)
+ {
+ if ((self.wait == -1 || (self.spawnflags & DOOR_TOGGLE)) &&
+ openalldoors)
+ {
+ door_group_go_up ();
+ }
+ }
+
+ if (self.max_health)
+ {
+ next = self;
+ do
+ {
+ next.health = next.max_health;
+ next.takedamage = DAMAGE_YES;
+ next = next.enemy;
+ }
+ while ((next != self) && (next != world));
+ }
+
+ self.estate = STATE_ACTIVE;
+ self = oself;
+};
+
+//----------------------------------------------------------------------
+// SPAWNING FUNCTIONS
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+entity(vector fmins, vector fmaxs) spawn_field =
+{
+ local entity trigger;
+ local vector t1, t2;
+
+ trigger = spawn ();
+ trigger.movetype = MOVETYPE_NONE;
+ trigger.solid = SOLID_TRIGGER;
+ trigger.owner = self;
+ trigger.touch = door_trigger_touch;
+
+ t1 = fmins;
+ t2 = fmaxs;
+ setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
+ return (trigger);
+};
+
+//----------------------------------------------------------------------
+float (entity e1, entity e2) EntitiesTouching =
+{
+ if (e1.mins_x > e2.maxs_x)
+ return FALSE;
+ if (e1.mins_y > e2.maxs_y)
+ return FALSE;
+ if (e1.mins_z > e2.maxs_z)
+ return FALSE;
+ if (e1.maxs_x < e2.mins_x)
+ return FALSE;
+ if (e1.maxs_y < e2.mins_y)
+ return FALSE;
+ if (e1.maxs_z < e2.mins_z)
+ return FALSE;
+ return TRUE;
+};
+
+//----------------------------------------------------------------------
+// LinkDoors
+//----------------------------------------------------------------------
+void() LinkDoors =
+{
+ local entity t, starte;
+ local vector cmins, cmaxs;
+
+ if (self.enemy)
+ // already linked by another door
+ return;
+
+ if (self.spawnflags & 4)
+ {
+ // don't want to link this door
+ self.owner = self.enemy = self;
+ return;
+ }
+
+ cmins = self.mins;
+ cmaxs = self.maxs;
+
+ starte = self;
+ t = self;
+
+ do
+ {
+ // master door
+ self.owner = starte;
+
+ if (self.health)
+ starte.health = self.health;
+ if (self.targetname != "")
+ starte.targetname = self.targetname;
+ if (self.message != "")
+ starte.message = self.message;
+
+ t = find (t, classname, self.classname);
+ if (!t)
+ {
+ // make the chain a loop
+ self.enemy = starte;
+
+ // shootable, fired, or key doors just needed the
+ // owner/enemy links, they don't spawn a field
+
+ self = self.owner;
+
+ if (self.health)
+ return;
+ if (self.targetname != "")
+ return;
+ if (keylock_has_key_set())
+ return;
+
+ self.owner.trigger_field = spawn_field (cmins, cmaxs);
+
+ return;
+ }
+
+ if (EntitiesTouching(self,t))
+ {
+ if (t.enemy)
+ objerror ("cross connected doors");
+
+ self.enemy = t;
+ self = t;
+
+ if (t.mins_x < cmins_x)
+ cmins_x = t.mins_x;
+ if (t.mins_y < cmins_y)
+ cmins_y = t.mins_y;
+ if (t.mins_z < cmins_z)
+ cmins_z = t.mins_z;
+ if (t.maxs_x > cmaxs_x)
+ cmaxs_x = t.maxs_x;
+ if (t.maxs_y > cmaxs_y)
+ cmaxs_y = t.maxs_y;
+ if (t.maxs_z > cmaxs_z)
+ cmaxs_z = t.maxs_z;
+ }
+ }
+ while (1);
+};
+
+/*QUAKED func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE 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
+
+if two doors touch, they are assumed to be connected and operate as a unit.
+
+TOGGLE causes the door to wait in both the start and end states for a trigger event.
+
+START_OPEN causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors).
+
+Key doors are always wait -1.
+
+"message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet
+"angle" determines the opening direction
+"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
+"health" if set, door must be shot open
+"speed" movement speed (100 default)
+"wait" wait before returning (3 default, -1 = never return)
+"lip" lip remaining at end of move (8 default)
+"dmg" damage to inflict when blocked (2 default)
+"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
+"noise1" sound file for the "stop moving" sound (if set, overrides "sounds")
+"noise2" sound file for the "move" sound (if set, overrides "sounds")
+"noise3" sound file for the "key required" sound (default is per worldtype)
+"noise4" sound file for the "key used" sound (default is per worldtype)
+"sounds"
+0) no sound
+1) stone
+2) base
+3) stone chain
+4) screechy metal
+*/
+void() func_door =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ local string default_noise1;
+ local string default_noise2;
+ entity shadow;
+ entity oldself;
+
+ // self.noise3 and self.noise4 can now be overridden by the mapper, but
+ // will be set to default values in keylock_init if necessary -- iw
+ keylock_init ();
+
+ // self.noise1 and self.noise2 can now be overridden by the mapper -- iw
+ default_noise1 = "misc/null.wav";
+ default_noise2 = "misc/null.wav";
+
+ if (self.sounds == 1)
+ {
+ default_noise1 = "doors/drclos4.wav";
+ default_noise2 = "doors/doormv1.wav";
+ }
+
+ if (self.sounds == 2)
+ {
+ default_noise1 = "doors/hydro2.wav";
+ default_noise2 = "doors/hydro1.wav";
+ }
+
+ if (self.sounds == 3)
+ {
+ default_noise1 = "doors/stndr2.wav";
+ default_noise2 = "doors/stndr1.wav";
+ }
+
+ if (self.sounds == 4)
+ {
+ default_noise1 = "doors/ddoor2.wav";
+ default_noise2 = "doors/ddoor1.wav";
+ }
+
+ if (self.noise1 == "")
+ self.noise1 = default_noise1;
+ if (self.noise2 == "")
+ self.noise2 = default_noise2;
+
+ precache_sound (self.noise1);
+ precache_sound (self.noise2);
+
+ SetMovedir ();
+
+ self.max_health = self.health;
+ self.solid = SOLID_BSP;
+ self.movetype = MOVETYPE_PUSH;
+ setorigin (self, self.origin);
+ setmodel (self, self.model);
+ // self.classname = "door";
+
+ self.blocked = door_blocked;
+ self.use = door_use;
+
+ if (self.spawnflags & DOOR_SILVER_KEY)
+ {
+ keylock_set_silver_key ();
+
+ if (self.keyname != "")
+ {
+ self.netname = self.keyname;
+ self.keyname = "";
+ }
+ }
+
+ if (self.spawnflags & DOOR_GOLD_KEY)
+ {
+ 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 (!self.speed)
+ self.speed = 100;
+ if (!self.wait)
+ self.wait = 3;
+ if (!self.lip)
+ self.lip = 8;
+ if (!self.dmg)
+ self.dmg = 2;
+
+ self.pos1 = self.origin;
+ self.pos2 = self.pos1 + self.movedir *
+ (fabs(self.movedir * self.size) - self.lip);
+
+ // DOOR_START_OPEN is to allow an entity to be lighted in the
+ // closed position but spawn in the open position
+ if (self.spawnflags & DOOR_START_OPEN)
+ {
+ setorigin (self, self.pos2);
+ self.pos2 = self.pos1;
+ self.pos1 = self.origin;
+ }
+
+ self.state = STATE_BOTTOM;
+
+ if (self.health)
+ {
+ self.takedamage = DAMAGE_YES;
+ self.th_die = door_killed;
+ }
+
+ if (self.spawnflags & DOOR_DOOM_STYLE_UNLOCK)
+ self.cnt = 1;
+
+ if (keylock_has_key_set())
+ {
+ if (!(self.spawnflags & DOOR_DOOM_STYLE_UNLOCK))
+ {
+ self.wait = -1;
+ }
+ }
+ self.touch = door_touch;
+
+ // LinkDoors can't be done until all of the doors have been spawned,
+ // so the sizes can be detected properly.
+ self.think = LinkDoors;
+ self.nextthink = self.ltime + 0.1;
+
+ // creates a shadow controller entity for the door if it has
+ // switchable shadows
+ if (self.switchshadstyle)
+ {
+ shadow = spawn ();
+
+ self.shadowcontroller = shadow;
+
+ shadow.classname = "misc_shadowcontroller";
+ shadow.switchshadstyle = self.switchshadstyle;
+ shadow.speed = vlen (self.pos2 - self.pos1) / self.speed;
+
+ if (self.spawnflags & DOOR_START_OPEN)
+ shadow.spawnflags = 1;
+ else
+ shadow.spawnflags = 0;
+
+ oldself = self;
+
+ self = shadow;
+ misc_shadowcontroller ();
+
+ self = oldself;
+ }
+};

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

Diff qc/func/door_secret.qc

diff --git a/qc/func/door_secret.qc b/qc/func/door_secret.qc
new file mode 100644
index 0000000..c84d176
--- /dev/null
+++ b/qc/func/door_secret.qc
@@ -0,0 +1,271 @@
+//==============================================================================
+// func_door_secret -- SECRET DOORS
+//==============================================================================
+
+// constants
+const float SECRET_OPEN_ONCE = 1; // stays open
+const float SECRET_1ST_LEFT = 2; // 1st move is left of arrow
+const float SECRET_1ST_DOWN = 4; // 1st move is down from arrow
+const float SECRET_NO_SHOOT = 8; // only opened by trigger
+const float SECRET_YES_SHOOT = 16; // shootable even if targeted
+
+// prototypes
+void() fd_secret_move1;
+void() fd_secret_move2;
+void() fd_secret_move3;
+void() fd_secret_move4;
+void() fd_secret_move5;
+void() fd_secret_move6;
+void() fd_secret_done;
+
+//----------------------------------------------------------------------
+void() fd_secret_use =
+{
+ local float temp;
+
+ self.health = 10000;
+
+ // exit if still moving around...
+ if (self.origin != self.oldorigin)
+ return;
+
+ // no more message
+ self.message = string_null;
+
+ // fire all targets / killtargets
+ SUB_UseTargets ();
+
+ if (!(self.spawnflags & SECRET_NO_SHOOT))
+ {
+ self.th_pain = SUB_NullPain;
+ self.takedamage = DAMAGE_NO;
+ }
+
+ self.velocity = '0 0 0';
+
+ // Make a sound, wait a little...
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.nextthink = self.ltime + 0.1;
+
+ // 1 or -1
+ temp = 1 - (self.spawnflags & SECRET_1ST_LEFT);
+ makevectors (self.mangle);
+
+ if (!self.t_width)
+ {
+ if (self.spawnflags & SECRET_1ST_DOWN)
+ self.t_width = fabs (v_up * self.size);
+ else
+ self.t_width = fabs (v_right * self.size);
+ }
+
+ if (!self.t_length)
+ self.t_length = fabs (v_forward * self.size);
+
+ if (self.spawnflags & SECRET_1ST_DOWN)
+ self.dest1 = self.origin - v_up * self.t_width;
+ else
+ self.dest1 = self.origin + v_right * (self.t_width * temp);
+
+ self.dest2 = self.dest1 + v_forward * self.t_length;
+ SUB_CalcMove (self.dest1, self.speed, fd_secret_move1);
+ sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+};
+
+//----------------------------------------------------------------------
+void(entity attacker, float damage) fd_secret_pain =
+{
+ fd_secret_use ();
+};
+
+//----------------------------------------------------------------------
+// fd_secret_move1 -- Wait after first movement...
+//----------------------------------------------------------------------
+void() fd_secret_move1 =
+{
+ self.nextthink = self.ltime + 1.0;
+ self.think = fd_secret_move2;
+ sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+};
+
+//----------------------------------------------------------------------
+// fd_secret_move2 -- Start moving sideways w/sound...
+//----------------------------------------------------------------------
+void() fd_secret_move2 =
+{
+ sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+ SUB_CalcMove (self.dest2, self.speed, fd_secret_move3);
+};
+
+//----------------------------------------------------------------------
+// fd_secret_move3 -- Wait here until time to go back...
+//----------------------------------------------------------------------
+void() fd_secret_move3 =
+{
+ sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+ if (!(self.spawnflags & SECRET_OPEN_ONCE))
+ {
+ self.nextthink = self.ltime + self.wait;
+ self.think = fd_secret_move4;
+ }
+};
+
+//----------------------------------------------------------------------
+// fd_secret_move4 -- Move backward...
+//----------------------------------------------------------------------
+void() fd_secret_move4 =
+{
+ sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+ SUB_CalcMove (self.dest1, self.speed, fd_secret_move5);
+};
+
+//----------------------------------------------------------------------
+// fd_secret_move5 -- Wait 1 second...
+//----------------------------------------------------------------------
+void() fd_secret_move5 =
+{
+ self.nextthink = self.ltime + 1.0;
+ self.think = fd_secret_move6;
+ sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+};
+
+//----------------------------------------------------------------------
+// fd_secret_move6
+//----------------------------------------------------------------------
+void() fd_secret_move6 =
+{
+ sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+ SUB_CalcMove (self.oldorigin, self.speed, fd_secret_done);
+};
+
+//----------------------------------------------------------------------
+// fd_secret_done
+//----------------------------------------------------------------------
+void() fd_secret_done =
+{
+ if (!self.targetname || self.spawnflags & SECRET_YES_SHOOT)
+ {
+ self.health = 10000;
+ self.takedamage = DAMAGE_YES;
+ self.th_pain = fd_secret_pain;
+ }
+
+ sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+};
+
+//----------------------------------------------------------------------
+void() secret_blocked =
+{
+ if (time < self.attack_finished)
+ return;
+
+ self.attack_finished = time + 0.5;
+ T_Damage (other, self, self, self.dmg);
+};
+
+//----------------------------------------------------------------------
+// secret_touch - ouch; Prints messages
+//----------------------------------------------------------------------
+void() secret_touch =
+{
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ if (self.attack_finished > time)
+ return;
+
+ self.attack_finished = time + 2;
+
+ if (self.message != "")
+ {
+ centerprint (other, self.message);
+ sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
+ }
+};
+
+/*QUAKED func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot 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
+
+Basic secret door. Slides back, then to the side. Angle determines direction.
+wait = # of seconds before coming back
+1st_left = 1st move is left of arrow
+1st_down = 1st move is down from arrow
+always_shoot = even if targeted, keep shootable
+t_width = override WIDTH to move back (or height if going down)
+t_length = override LENGTH to move sideways
+"dmg" damage to inflict when blocked (2 default)
+
+If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
+"sounds"
+1) medieval
+2) metal
+3) base
+*/
+void() func_door_secret =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (self.sounds == 0)
+ self.sounds = 3;
+
+ if (self.sounds == 1)
+ {
+ precache_sound ("doors/latch2.wav");
+ precache_sound ("doors/winch2.wav");
+ precache_sound ("doors/drclos4.wav");
+ self.noise1 = "doors/latch2.wav";
+ self.noise2 = "doors/winch2.wav";
+ self.noise3 = "doors/drclos4.wav";
+ }
+
+ if (self.sounds == 2)
+ {
+ precache_sound ("doors/airdoor1.wav");
+ precache_sound ("doors/airdoor2.wav");
+ self.noise2 = "doors/airdoor1.wav";
+ self.noise1 = "doors/airdoor2.wav";
+ self.noise3 = "doors/airdoor2.wav";
+ }
+
+ if (self.sounds == 3)
+ {
+ precache_sound ("doors/basesec1.wav");
+ precache_sound ("doors/basesec2.wav");
+ self.noise2 = "doors/basesec1.wav";
+ self.noise1 = "doors/basesec2.wav";
+ self.noise3 = "doors/basesec2.wav";
+ }
+
+ if (!self.dmg)
+ self.dmg = 2;
+
+ // Magic formula...
+ self.mangle = self.angles;
+ self.angles = '0 0 0';
+ self.solid = SOLID_BSP;
+ self.movetype = MOVETYPE_PUSH;
+ // self.classname = "door";
+ setmodel (self, self.model);
+ setorigin (self, self.origin);
+
+ self.touch = secret_touch;
+ self.blocked = secret_blocked;
+ self.speed = 50;
+ self.use = fd_secret_use;
+
+ if (!self.targetname || self.spawnflags & SECRET_YES_SHOOT)
+ {
+ self.health = 10000;
+ self.takedamage = DAMAGE_YES;
+ self.th_pain = fd_secret_pain;
+ self.th_die = fd_secret_use;
+ }
+
+ self.oldorigin = self.origin;
+
+ if (!self.wait)
+ // 5 seconds before closing
+ self.wait = 5;
+};

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

Diff qc/func/elvtr_button.qc

diff --git a/qc/func/elvtr_button.qc b/qc/func/elvtr_button.qc
new file mode 100644
index 0000000..243f898
--- /dev/null
+++ b/qc/func/elvtr_button.qc
@@ -0,0 +1,182 @@
+//==============================================================================
+// func_elvtr_button - Rogue Dissolution Of Eternity
+//==============================================================================
+
+// elevator button
+// pmack
+// sept 96
+
+// constants
+const float ELVTR_DOWN = 1;
+
+// prototypes
+void() elvtr_button_wait;
+void() elvtr_button_return;
+
+//----------------------------------------------------------------------
+void() elvtr_button_wait =
+{
+ elv_butn_dir = 0;
+ if (self.spawnflags & ELVTR_DOWN)
+ elv_butn_dir = -1;
+ else
+ elv_butn_dir = 1;
+
+ self.state = STATE_TOP;
+ self.nextthink = self.ltime + self.wait;
+ self.think = elvtr_button_return;
+ activator = self.enemy;
+ SUB_UseTargets ();
+ // use alternate textures
+ self.frame = 1;
+};
+
+//----------------------------------------------------------------------
+void() elvtr_button_done =
+{
+ self.state = STATE_BOTTOM;
+};
+
+//----------------------------------------------------------------------
+void() elvtr_button_return =
+{
+ self.state = STATE_DOWN;
+ SUB_CalcMove (self.pos1, self.speed, elvtr_button_done);
+ // use normal textures
+ self.frame = 0;
+ if (self.health)
+ // can be shot again
+ self.takedamage = DAMAGE_YES;
+};
+
+
+//----------------------------------------------------------------------
+void() elvtr_button_blocked =
+{
+ // do nothing, just don't ome all the way back out
+};
+
+
+//----------------------------------------------------------------------
+void() elvtr_button_fire =
+{
+ if (self.state == STATE_UP || self.state == STATE_TOP)
+ return;
+
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+
+ self.state = STATE_UP;
+ SUB_CalcMove (self.pos2, self.speed, elvtr_button_wait);
+};
+
+//----------------------------------------------------------------------
+void() elvtr_button_use =
+{
+ self.enemy = activator;
+ elvtr_button_fire ();
+};
+
+//----------------------------------------------------------------------
+void() elvtr_button_touch =
+{
+ if (other.classname != "player")
+ return;
+
+ self.enemy = other;
+ elvtr_button_fire ();
+};
+
+//----------------------------------------------------------------------
+void() elvtr_button_killed =
+{
+ self.enemy = damage_attacker;
+ self.health = self.max_health;
+ // wil be reset upon return
+ self.takedamage = DAMAGE_NO;
+ elvtr_button_fire ();
+};
+
+/*QUAKED func_elvtr_button (0 .5 .8) ? ELVTR_DOWN 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
+
+ELEVATOR BUTTON ONLY!
+
+ELVTR_DOWN causes this to be a DOWN button.
+Default is UP.
+
+When a button is touched, it moves some distance in the direction of it's angle, triggers all of it's targets, waits some time, then returns to it's original position where it can be triggered again.
+
+"angle" determines the opening direction
+"target" all entities with a matching targetname will be used
+"speed" override the default 40 speed
+"wait" override the default 1 second wait (-1 = never return)
+"lip" override the default 4 pixel lip remaining at end of move
+"health" if set, the button must be killed instead of touched
+"sounds"
+0) steam metal
+1) wooden clunk
+2) metallic click
+3) in-out
+*/
+void() func_elvtr_button =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (self.sounds == 0)
+ {
+ precache_sound ("buttons/airbut1.wav");
+ self.noise = "buttons/airbut1.wav";
+ }
+
+ if (self.sounds == 1)
+ {
+ precache_sound ("buttons/switch21.wav");
+ self.noise = "buttons/switch21.wav";
+ }
+
+ if (self.sounds == 2)
+ {
+ precache_sound ("buttons/switch02.wav");
+ self.noise = "buttons/switch02.wav";
+ }
+
+ if (self.sounds == 3)
+ {
+ precache_sound ("buttons/switch04.wav");
+ self.noise = "buttons/switch04.wav";
+ }
+
+ SetMovedir ();
+
+ self.movetype = MOVETYPE_PUSH;
+ self.solid = SOLID_BSP;
+ setmodel (self, self.model);
+
+ self.blocked = elvtr_button_blocked;
+ self.use = elvtr_button_use;
+
+ if (self.health)
+ {
+ self.max_health = self.health;
+ self.th_die = elvtr_button_killed;
+ self.takedamage = DAMAGE_YES;
+ }
+ else
+ {
+ self.touch = elvtr_button_touch;
+ }
+
+ if (!self.speed)
+ self.speed = 40;
+ if (!self.wait)
+ self.wait = 1;
+ if (!self.lip)
+ self.lip = 4;
+
+ self.state = STATE_BOTTOM;
+
+ self.pos1 = self.origin;
+ self.pos2 = self.pos1 + self.movedir *
+ (fabs(self.movedir * self.size) - self.lip);
+};

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

Diff qc/func/episodegate.qc

diff --git a/qc/func/episodegate.qc b/qc/func/episodegate.qc
new file mode 100644
index 0000000..c238462
--- /dev/null
+++ b/qc/func/episodegate.qc
@@ -0,0 +1,38 @@
+//==============================================================================
+// func_episodegate
+//==============================================================================
+
+// constants
+// For func_episodegate and func_bossgate appear when player has all runes
+const float EPISODEGATE_REVERSE = 16;
+
+/*QUAKED func_episodegate (0 .5 .8) ? E1 E2 E3 E4 REVERSE_FUNCTIONALITY
+This bmodel will appear if the episode has allready been completed, so players can't reenter it.
+*/
+void() func_episodegate =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (self.spawnflags & EPISODEGATE_REVERSE)
+ {
+ // this is to avoid a possible issue with sigil_touch2
+ self.spawnflags = self.spawnflags - EPISODEGATE_REVERSE;
+ if (serverflags & self.spawnflags)
+ // Haven't gotten rune yet
+ return;
+ }
+ else
+ {
+ if (!(serverflags & self.spawnflags))
+ // can still enter episode
+ return;
+ }
+ self.angles = '0 0 0';
+ // so it doesn't get pushed by anything
+ self.movetype = MOVETYPE_PUSH;
+ self.solid = SOLID_BSP;
+ self.use = func_wall_use;
+ setmodel (self, self.model);
+};

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

Diff qc/func/explobox.qc

diff --git a/qc/func/explobox.qc b/qc/func/explobox.qc
new file mode 100644
index 0000000..81ec694
--- /dev/null
+++ b/qc/func/explobox.qc
@@ -0,0 +1,69 @@
+//==============================================================================
+// func_explobox -- selections from Rubicon 2 qc by john fitzgibbons
+//==============================================================================
+
+//----------------------------------------------------------------------
+void() func_explobox_explode_silent =
+{
+ self.takedamage = DAMAGE_NO;
+ self.origin = ((self.absmin + self.absmax) * 0.5);
+ self.classname = "explo_box";
+ T_RadiusDamage (self, self, self.dmg, world);
+ WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte (MSG_BROADCAST, TE_EXPLOSION);
+ WriteCoord (MSG_BROADCAST, self.origin_x);
+ WriteCoord (MSG_BROADCAST, self.origin_y);
+ WriteCoord (MSG_BROADCAST, self.origin_z);
+ BecomeExplosion ();
+};
+
+//----------------------------------------------------------------------
+void() func_explobox_explode =
+{
+ // sound (self, CHAN_VOICE, "weapons/r_exp3.wav", 1, ATTN_NORM);
+ func_explobox_explode_silent ();
+};
+
+//----------------------------------------------------------------------
+void() func_explobox_die =
+{
+ // for some reason, time + 0.2 doesn't work
+ self.nextthink = 0.2;
+ self.think = func_explobox_explode;
+};
+
+/*QUAKED func_explobox (0 .5 .8) ? START_OFF 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
+
+An exploding brush entity. Works just like misc_explobox.
+
+Keys:
+
+"health" Default 20
+
+"dmg" default 100
+
+*/
+void() func_explobox =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.solid = SOLID_BSP;
+ self.movetype = MOVETYPE_PUSH;
+ setmodel (self, self.model);
+ precache_sound ("weapons/r_exp3.wav");
+
+ if (!self.health)
+ {
+ self.health = 20;
+ }
+
+ if (!self.dmg)
+ {
+ self.dmg = 100;
+ }
+
+ self.th_die = func_explobox_die;
+ self.takedamage = DAMAGE_AIM;
+};

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

Diff qc/func/fall.qc

diff --git a/qc/func/fall.qc b/qc/func/fall.qc
new file mode 100644
index 0000000..33c6af0
--- /dev/null
+++ b/qc/func/fall.qc
@@ -0,0 +1,117 @@
+//==============================================================================
+// func_fall from RennyC
+//
+// A brush that drops and fades away when touched or triggered.
+//
+// dumptruck_ds
+// noise = sound to play when triggered
+// wait = wait this long before falling
+//==============================================================================
+
+// constants
+const float DONT_FADE = 1;
+const float SILENT = 2;
+
+//----------------------------------------------------------------------
+void() func_fall_think =
+{
+ if (self.cnt == TRUE && self.attack_finished < time)
+ {
+ self.solid = SOLID_BBOX;
+ // self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_TOSS;
+
+ if (!(self.spawnflags & DONT_FADE))
+ {
+
+ if (self.alpha > 0.1)
+ {
+ self.alpha = self.alpha - 0.03;
+ }
+ else
+ {
+ remove (self);
+ return;
+ }
+ }
+ }
+ self.nextthink = time + 0.1;
+};
+
+//----------------------------------------------------------------------
+void() fall_touch =
+{
+ if (other.classname == "player")
+ {
+ if (!(other.flags & FL_ONGROUND))
+ other.flags = other.flags | FL_ONGROUND;
+ }
+ else if (other.flags & FL_MONSTER)
+ {
+ T_Damage (other, self, other, 50000);
+ }
+ else
+ {
+ return;
+ }
+
+ if (self.cnt == TRUE)
+ return;
+
+ self.attack_finished = time + self.wait;
+ self.cnt = TRUE;
+
+ if (!(self.spawnflags & SILENT))
+ {
+ if (self.noise != "")
+ sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
+ else
+ sound (self, CHAN_AUTO, "buttons/switch21.wav",
+ 1, ATTN_NORM);
+ }
+};
+
+//----------------------------------------------------------------------
+void() fall_use =
+{
+ // thanks again RennyC for help on revisions --dumptruck_ds
+ self.attack_finished = time + self.wait;
+ self.cnt = TRUE;
+
+ if (self.noise != "")
+ sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
+ else
+ sound (self, CHAN_AUTO, "buttons/switch21.wav", 1, ATTN_NORM);
+};
+
+/*QUAKED func_fall (0 .5 .8) ? DONT_FADE 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 brush that drops and fades away when touched and/or triggered.
+Add some spice to your jumping puzzles or other scripted sequences!
+Monsters will not trigger func_fall but will be gibbed if one falls on them.
+NOTE: When a func_fall brush touches another brush or entity it will stop, which can look odd in certain situations.
+noise = sound to play when triggered, the default is a switch sound.
+wait = wait this long before falling.
+Use the DONT_FADE spawnflag if desired.
+
+Falling brush upon touch
+*/
+void() func_fall =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ precache_sound ("buttons/switch21.wav");
+ if (self.noise != "")
+ precache_sound (self.noise);
+
+ self.alpha = 1;
+ self.cnt = FALSE;
+ self.solid = SOLID_BSP;
+ self.movetype = MOVETYPE_PUSH;
+ self.think = func_fall_think;
+ self.nextthink = time;
+ self.touch = fall_touch;
+ self.use = fall_use;
+ setmodel (self, self.model);
+};

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

Diff qc/func/fall2.qc

diff --git a/qc/func/fall2.qc b/qc/func/fall2.qc
new file mode 100644
index 0000000..95e6a1e
--- /dev/null
+++ b/qc/func/fall2.qc
@@ -0,0 +1,362 @@
+//==============================================================================
+// func_fall2 -- code attributed to RennyC & whirledtsar
+//==============================================================================
+
+// fields
+.float alpha; // translucency in supported engines
+.entity char; // linker entity
+
+// constants
+const float PLAYER_TRIGGERED = 1;
+const float MONSTER_TRIGGERED = 2;
+const float FALL_BREAKABLE = 8; // VR
+// const float FALL_SOLID = 16; // VR
+
+// prototypes
+void() fall_break_fields;
+
+//----------------------------------------------------------------------
+void() func_fall2_think =
+{
+ // turn off quake engine splash sound
+ self.waterlevel = self.watertype = 0;
+
+ if (self.attack_finished < time)
+ {
+ if (self.target != __NULL__ && self.target != "")
+ // fire other targets; was SUB_UseTargets ()
+ SUB_UseAndForgetTargets ();
+
+
+ // removed FALL_SOLID behavior -- dumptruck_ds
+ self.solid = SOLID_NOT;
+
+ if (self.pos1 != '0 0 0')
+ // apply stored avelocity vector values
+ self.avelocity = self.pos1;
+
+ if (self.pos2 && !self.velocity)
+ // Add velocity movement
+ self.velocity = self.pos2;
+
+ if (self.cnt > 0)
+ {
+ // cnt over 0
+ if (self.cnt >= 2)
+ {
+ self.movetype = MOVETYPE_BOUNCE;
+ if (self.velocity_z < self.lip)
+ self.velocity_z = self.lip;
+ }
+ else
+ {
+ // cnt is 1
+ self.movetype = MOVETYPE_NOCLIP;
+ if (self.velocity_z > self.lip)
+ self.velocity_z -= self.speed *
+ (frametime * 100);
+ else
+ self.velocity_z = self.lip;
+ }
+ }
+ else
+ {
+ // default behavior (cnt is 0)
+ self.movetype = MOVETYPE_TOSS;
+ if (self.velocity_z < self.lip)
+ self.velocity_z = self.lip;
+ }
+
+ if (self.pain_finished != -1)
+ {
+ if (self.alpha > 0.1)
+ self.alpha = self.alpha - self.pain_finished;
+ else
+ {
+ if (self.noise2 != __NULL__ &&self.noise2 != "")
+ sound (self, CHAN_AUTO, self.noise2,
+ 1, ATTN_NORM);
+ remove (self);
+ return;
+ }
+ }
+
+ if (self.flags & FL_ONGROUND &&
+ self.spawnflags & FALL_BREAKABLE)
+ {
+ // VR
+
+ // aka BREAKABLE_NO_MONSTERS
+ self.spawnflags(-)1;
+ // aka BREAK_EXPLODE
+ self.spawnflags(-)2;
+ // because of how debris origin is calculated
+ self.mins = self.absmin;
+ self.maxs = self.absmax;
+ // debris gets velocity from health
+ self.health = self.lip * 0.1;
+ // func_breakable uses cnt for quantity of debris
+ // to spawn
+ self.cnt = self.count;
+ // removes self
+ func_breakable_die ();
+ return;
+ }
+ }
+
+ self.nextthink = self.ltime + 0.1;
+};
+
+//----------------------------------------------------------------------
+void() fall2_touch =
+{
+ if (!other.takedamage)
+ return;
+
+ if (other.classname != "player")
+ // player activated only
+ return;
+
+ if (self.spawnflags & MONSTER_TRIGGERED)
+ // disable on monster only, also fixes weird issue
+ return;
+
+ self.think = func_fall2_think;
+ self.nextthink = self.ltime + 0.1;
+
+ self.attack_finished = time + self.wait;
+
+ // if (self.spawnflags & FALL_SOLID)
+ // {
+ // // VR
+ // setsize (self, self.mins, self.maxs);
+ // self.solid = SOLID_BBOX;
+ // }
+ // else
+ // {
+ // self.solid = SOLID_NOT;
+ // }
+
+ if (self.noise != __NULL__ && self.noise != "")
+ sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
+
+ // disable touch, only do this once!
+ self.touch = SUB_Null;
+
+ if (self.char)
+ remove (self.char);
+};
+
+//----------------------------------------------------------------------
+void() func_fall2_use =
+{
+ self.think = func_fall2_think;
+ self.nextthink = self.ltime + 0.1;
+ // disable touch when used
+ self.touch = SUB_Null;
+
+ // if (self.spawnflags&FALL_SOLID)
+ // {
+ // // VR
+ // setsize (self, self.mins, self.maxs);
+ // self.solid = SOLID_BBOX;
+ // }
+ // else
+ // {
+ // self.solid = SOLID_NOT;
+ // }
+
+ self.attack_finished = time + self.wait;
+ if (self.noise != __NULL__ && self.noise != "")
+ sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
+};
+
+//----------------------------------------------------------------------
+void() func_fall2_field_touch =
+{
+ if (other.flags & FL_FLY)
+ // flying monsters shouldn't trigger falling platforms
+ return;
+
+ if (other.flags & FL_MONSTER)
+ {
+ local entity oself;
+
+ oself = self;
+
+ self = self.owner;
+ self.think = func_fall2_use;
+ self.nextthink = self.owner.ltime + 0.1;
+
+ self = oself;
+
+ remove (self);
+ }
+};
+
+/*QUAKED func_fall2 (0 .5 .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
+Falling brush by RennyC with additions from whirledtsar
+
+wait - how long until the brush begins falling
+noise - the sound to make when touched / activated
+noise2 - the sound to make before it's removed, pain_finished of -1 disables noise2 as the object stays forever
+cnt - 0 is default behavior (MOVETYPE_TOSS), 1 means collisions are disabled while falling (MOVETYPE_NOCLIP), 2 turns the brush into a bouncing entity (MOVETYPE_BOUNCE)
+pain_finished - default of 0.01, higher value has the object/brush fade out faster thus in turn affecting how long it stays. -1 stays forever
+speed - speed as to how fast something falls per game frame, default is 10, higher values mean faster falling. Only for cnt of 1 (MOVETYPE_NOCLIP).
+Recommended to use lip for max fall speed on MOVETYPE_TOSS/BOUNCE entities (cnt 0 and 2) as they follow Quake's default gravity
+lip - maximum fall speed that can be achieved, caps 'speed' variable. Default is -800
+avelocity - have it spin when activated using X, Y, Z vector coordinates. MOVETYPE_BOUNCE ignores avelocity !Use an origin brush for proper spin!
+
+spawnflags:
+Default behavior allows anyone to activate func_fall2 on touch ONLY
+1 - Player activated only
+2 - Monster activated only
+8 - break on impact (use style key for textures, see manual for more)
+16 - fall solid; remains solid on ground
+
+Able to .target other entities, including other func_fall2s
+*/
+void() func_fall2 =
+{
+ // This is a hack to have monsters be able to trigger it
+ // by fake touch - Thanks to Nahuel
+
+ // Don't spawn on player only or if I'm a targetable
+ if (!(self.spawnflags & PLAYER_TRIGGERED) && !(self.targetname))
+ {
+ local entity func_fall2_field;
+
+ func_fall2_field = spawn ();
+ func_fall2_field.owner = self;
+ // Link 'em
+ self.char = func_fall2_field;
+ func_fall2_field.solid = SOLID_TRIGGER;
+ setsize (func_fall2_field, self.absmin, self.absmax + '0 0 8');
+ setorigin (func_fall2_field, self.origin);
+ setmodel (func_fall2_field, self.model);
+ func_fall2_field.touch = func_fall2_field_touch;
+ }
+
+ if (self.noise != __NULL__ && self.noise != "")
+ precache_sound (self.noise);
+ if (self.noise2 != __NULL__ && self.noise2 != "")
+ precache_sound (self.noise2);
+
+ self.alpha = 1;
+ self.solid = SOLID_BSP;
+ self.movetype = MOVETYPE_PUSH;
+
+ if (!self.pain_finished)
+ self.pain_finished = 0.01;
+ if (!self.targetname)
+ // .touch in this instance is for players only
+ self.touch = fall2_touch;
+
+ if (!self.speed)
+ self.speed = 10;
+ if (!self.lip)
+ self.lip = -800;
+
+ if (self.avelocity != '0 0 0')
+ {
+ // store it
+ self.pos1 = self.avelocity;
+ self.avelocity = '0 0 0';
+ }
+
+ if (self.spawnflags & FALL_BREAKABLE)
+ {
+ // VR
+ // dont fade if set to break
+ self.pain_finished = -1;
+ fall_break_fields ();
+ }
+ self.use = func_fall2_use;
+
+ setmodel (self, self.model);
+};
+
+// You may have to modify your multi_touch(); command in triggers.qc to allow
+// both monsters & players to activate trigger_once/multiple. I recommend
+// allowing the mapper themselves to select how that occurs.
+// Default behavior is player only.
+
+//----------------------------------------------------------------------
+void fall_break_fields ()
+{
+ break_template_setup ();
+
+ self.mdl_debris = "progs/debris.mdl";
+ precache_model (self.mdl_debris);
+
+ if (self.noise1 != "")
+ precache_sound (self.noise1);
+
+ // adding new default sounds for "simple" breakables in 1.2.0
+ // -- dumptruck_ds
+
+ // here's generic metal breaking
+ if (self.style == 0 || self.style == 11 || self.style == 12 ||
+ self.style == 17 || self.style == 18 || self.style == 19
+ || self.style == 24 || self.style == 31)
+ {
+ if !(self.noise1)
+ {
+ precache_sound ("break/metal2.wav");
+ self.noise1 = "break/metal2.wav";
+ }
+ }
+
+ if (self.style == 3 || self.style == 4 || self.style == 5)
+ {
+ if !(self.noise1)
+ {
+ precache_sound ("break/wood1.wav");
+ precache_sound ("break/wood2.wav");
+ // wood only randomized
+ if (random() > 0.6)
+ self.noise1 = "break/wood1.wav";
+ else
+ self.noise1 = "break/wood2.wav";
+ }
+ }
+
+ // glass sounds -- this is more of a shattering sound anyway
+ if (self.style == 6 || self.style == 7 || self.style == 8 ||
+ self.style == 9 || self.style == 10)
+ {
+ if !(self.noise1)
+ {
+ precache_sound ("break/metal1.wav");
+ self.noise1 = "break/metal1.wav";
+ }
+ }
+
+ if (self.style == 1 || self.style == 2 || self.style == 13 ||
+ self.style == 14 || self.style == 15 || self.style == 16 ||
+ self.style == 20 || self.style == 21 || self.style == 22 ||
+ self.style == 23)
+ {
+ if !(self.noise1)
+ {
+ precache_sound ("break/bricks1.wav");
+ self.noise1 = "break/bricks1.wav";
+ }
+ }
+
+ if (self.style == 25 || self.style == 26 || self.style == 27 ||
+ self.style == 28 || self.style == 29 || self.style == 30)
+ {
+ if !(self.noise1)
+ {
+ precache_sound ("break/stones1.wav");
+ self.noise1 = "break/stones1.wav";
+ }
+ }
+
+ if (!self.health)
+ self.health = 20;
+ if (!self.count)
+ // was 6 dumptruck_ds
+ self.count = 5;
+};

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

Diff qc/func/illusionary.qc

diff --git a/qc/func/illusionary.qc b/qc/func/illusionary.qc
new file mode 100644
index 0000000..faaad6f
--- /dev/null
+++ b/qc/func/illusionary.qc
@@ -0,0 +1,19 @@
+//==============================================================================
+// func_illusionary
+//==============================================================================
+
+/*QUAKED func_illusionary (0 .5 .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
+A simple entity that looks solid but lets you walk through it.
+*/
+void() func_illusionary =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.angles = '0 0 0';
+ self.movetype = MOVETYPE_NONE;
+ self.solid = SOLID_NOT;
+ setmodel (self, self.model);
+ makestatic (self);
+};

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

Diff qc/func/laser.qc

diff --git a/qc/func/laser.qc b/qc/func/laser.qc
new file mode 100644
index 0000000..c98ccc6
--- /dev/null
+++ b/qc/func/laser.qc
@@ -0,0 +1,150 @@
+//==============================================================================
+// func_laser -- selections from Rubicon 2 qc by john fitzgibbons
+//==============================================================================
+
+// fields
+.float alpha;
+.string message2;
+
+// constants
+const float LASER_SOLID = 2;
+
+//----------------------------------------------------------------------
+void() laser_helper_think =
+{
+ if (!self.owner || self.owner.classname != "func_laser")
+ {
+ remove (self);
+ return;
+ }
+
+ if (!(self.owner.spawnflags & START_OFF))
+ self.owner.alpha = self.alpha * 0.8 +
+ self.alpha * random() * 0.4;
+
+ self.nextthink = time + 0.05;
+};
+
+//----------------------------------------------------------------------
+void() func_laser_touch =
+{
+ // from Copper -- dumptruck_ds
+ if (other.movetype == MOVETYPE_NOCLIP)
+ return;
+
+ if (other.takedamage && self.attack_finished < time)
+ {
+ T_Damage (other, self, self, self.dmg);
+ self.attack_finished = time + 0.1;
+ }
+
+};
+
+//----------------------------------------------------------------------
+void() func_laser_use =
+{
+ if (self.spawnflags & START_OFF)
+ {
+ setorigin (self, '0 0 0');
+ self.spawnflags = self.spawnflags - START_OFF;
+
+ // changed for progs_dump: the laser sound is now emitted from
+ // the func_laser itself instead of from the activator -- iw
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+
+ if (activator.classname == "player" && self.message != "")
+ {
+ centerprint (activator, self.message);
+ }
+ }
+ else
+ {
+ // changed for progs_dump: the laser sound is now emitted from
+ // the func_laser itself instead of from the activator -- iw
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+
+ setorigin (self, '0 0 9000');
+ self.spawnflags = self.spawnflags + START_OFF;
+
+ if (activator.classname == "player" && self.message2 != "")
+ {
+ centerprint (activator, self.message2);
+ }
+ }
+};
+
+/*QUAKED func_laser (0 .5 .8) ? START_OFF LASER_SOLID 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 toggleable laser, hurts to touch, can be used to block players
+
+START_OFF: Laser starts off.
+
+LASER_SOLID: Laser blocks movement while turned on.
+
+Keys:
+
+"dmg" damage to do on touch. default 1
+
+"alpha" approximate alpha you want the laser drawn at. default 0.5. alpha will vary by 20% of this value.
+
+"message" message to display when activated
+
+"message2" message to display when deactivated
+
+*/
+void () func_laser =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ local entity helper;
+
+ setmodel (self, self.model);
+
+ precache_sound ("buttons/switch02.wav");
+ precache_sound ("buttons/switch04.wav");
+
+ if (self.spawnflags & LASER_SOLID)
+ {
+ // so you can shoot between lasers in a single bmodel
+ self.solid = SOLID_BSP;
+ // required becuase of SOLID_BSP
+ self.movetype = MOVETYPE_PUSH;
+ }
+ else
+ {
+ self.solid = SOLID_TRIGGER;
+ self.movetype = MOVETYPE_NONE;
+ }
+
+ if (!self.alpha)
+ self.alpha = 0.5;
+
+ if (!self.dmg)
+ self.dmg = 1;
+
+ self.use = func_laser_use;
+ self.touch = func_laser_touch;
+
+ if (self.spawnflags & START_OFF)
+ setorigin (self, '0 0 9000');
+
+ if (self.noise != "")
+ precache_sound (self.noise);
+ else
+ self.noise = "buttons/switch02.wav";
+
+ if (self.noise1 != "")
+ precache_sound (self.noise1);
+ else
+ self.noise1 = "buttons/switch04.wav";
+
+ // spawn a second entity to handle alpha changes, since
+ // MOVETYPE_PUSH doesn't support think functions
+ helper = spawn ();
+ helper.alpha = self.alpha;
+ helper.owner = self;
+ helper.nextthink = 0.05;
+ helper.think = laser_helper_think;
+};

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

Diff qc/func/monster_spawner.qc

diff --git a/qc/func/monster_spawner.qc b/qc/func/monster_spawner.qc
new file mode 100644
index 0000000..4a4958a
--- /dev/null
+++ b/qc/func/monster_spawner.qc
@@ -0,0 +1,565 @@
+//==============================================================================
+// func_monster_spawner -- mobot.qc
+//==============================================================================
+
+// Using "bot" creation code for func_monster_spawner
+// most of the code is from a tutorial on creating a bot monster found here:
+// https://www.quaddicted.com/webarchive/minion.planetquake.gamespy.com/tutorial/tutor9.htm
+// I added the MobotSpawnPoint, retriggering and random gen with help from
+// kreathor, 4LT, Paril, Spoike and others on the Quake Mapping Discord.
+// ===================================================================
+// Big thanks to ryanscissorhands for helping fix telefragging issues!
+// ===================================================================
+
+// constants
+const float MOBOT_SPAWNER_RESET = 1;
+const float MOBOT_DONT_SPAWN_ANGRY = 2;
+const float MOBOT_DONT_ADD_KILL_COUNT = 4;
+const float MOBOT_SILENT_SPAWN = 32;
+
+//----------------------------------------------------------------------
+// MobotSpawnPoint -- Returns the entity to spawn at
+//----------------------------------------------------------------------
+entity() MobotSpawnPoint =
+{
+ local entity spot;
+
+ // spot = find (world, classname, "info_monster_spawnpoint");
+ spot = find (world, targetname, self.target);
+
+ if (!spot)
+ objerror ("couldn't find target");
+
+ return spot;
+};
+
+//----------------------------------------------------------------------
+void() create_mobot =
+{
+ local entity bot, spawn_spot;
+
+ // start entity and place it in world
+ bot = spawn ();
+ spawn_spot = MobotSpawnPoint ();
+ // let's not use deathmatch points for this -- dumptruck_ds
+ // spawn_spot = SelectSpawnPoint ();
+ bot.origin = spawn_spot.origin + '0 0 1';
+ bot.angles = spawn_spot.angles;
+ bot.fixangle = TRUE;
+ bot.proj_speed_mod = 1;
+
+ if (!(self.spawnflags & MOBOT_SILENT_SPAWN))
+ // SILENT
+ spawn_tfog (bot.origin);
+ spawn_tdeath (bot.origin, bot);
+
+ if (self.style == 1)
+ {
+ // spawn a Doggo
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/dog.mdl");
+ setsize (bot, '-32 -32 -24', '32 32 40');
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = dog_stand1;
+ bot.th_walk = dog_walk1;
+ bot.th_run = dog_run1;
+ bot.th_die = dog_die;
+ bot.th_melee = dog_atta1;
+ bot.th_missile = dog_leap1;
+ // Berserk test from
+ // http://celephais.net/board/view_thread.php?id=4&start=3465
+ // -- dumptruck_ds
+ if !(self.berserk)
+ bot.th_pain = dog_pain;
+ else
+ bot.th_pain = SUB_NullPain;
+ bot.health = 25;
+
+ // polish him up
+ bot.classname = "monster_dog";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 22';
+ }
+
+ if (self.style == 2)
+ {
+ // spawn a Grunt
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/soldier.mdl");
+ setsize (bot, '-16 -16 -24', '16 16 40');
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = army_stand1;
+ bot.th_walk = army_walk1;
+ bot.th_run = army_run1;
+ bot.th_die = army_die;
+ // bot.th_melee = ogre_melee;
+ bot.th_missile = army_atk1;
+ // Berserk test from
+ // http://celephais.net/board/view_thread.php?id=4&start=3465
+ // -- dumptruck_ds
+ if !(self.berserk)
+ bot.th_pain = army_pain;
+ else
+ bot.th_pain = SUB_NullPain;
+ bot.health = 80;
+
+ // polish him up
+ bot.classname = "monster_army";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 22';
+ }
+
+ if (self.style == 3)
+ {
+ // spawn an Enforcer
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/enforcer.mdl");
+ setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = enf_stand1;
+ bot.th_walk = enf_walk1;
+ bot.th_run = enf_run1;
+ bot.th_die = enf_die;
+ // bot.th_melee = ogre_melee;
+ bot.th_missile = enf_atk1;
+ // Berserk test from
+ // http://celephais.net/board/view_thread.php?id=4&start=3465
+ // -- dumptruck_ds
+ if !(self.berserk)
+ bot.th_pain = enf_pain;
+ else
+ bot.th_pain = SUB_NullPain;
+ bot.health = 80;
+
+ // polish him up
+ bot.classname = "monster_enforcer";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 22';
+ }
+
+ if (self.style == 4)
+ {
+ // spawn an Ogre
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/ogre.mdl");
+ setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = ogre_stand1;
+ bot.th_walk = ogre_walk1;
+ bot.th_run = ogre_run1;
+ bot.th_die = ogre_die;
+ bot.th_melee = ogre_melee;
+ bot.th_missile = ogre_nail1;
+ // Berserk test from
+ // http://celephais.net/board/view_thread.php?id=4&start=3465
+ // -- dumptruck_ds
+ if !(self.berserk)
+ bot.th_pain = ogre_pain;
+ else
+ bot.th_pain = SUB_NullPain;
+ bot.health = 200;
+
+ // polish him up
+ bot.classname = "monster_ogre";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 22';
+ }
+
+ if (self.style == 5)
+ {
+ // spawn an Fiend
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/demon.mdl");
+ setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = demon1_stand1;
+ bot.th_walk = demon1_walk1;
+ bot.th_run = demon1_run1;
+ bot.th_die = demon_die;
+ // one of two attacks
+ bot.th_melee = Demon_MeleeAttack;
+ // jump attack
+ bot.th_missile = demon1_jump1;
+ // Berserk test from
+ // http://celephais.net/board/view_thread.php?id=4&start=3465
+ // -- dumptruck_ds
+ if !(self.berserk)
+ bot.th_pain = demon1_pain;
+ else
+ bot.th_pain = SUB_NullPain;
+ bot.health = 300;
+
+ // polish him up
+ bot.classname = "monster_demon1";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 22';
+ }
+
+ if (self.style == 6)
+ {
+ // spawn a Wizard / Scrag
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/wizard.mdl");
+ setsize (bot, '-16 -16 -24', '16 16 40');
+ bot.flags = bot.flags | FL_FLY;
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = wiz_stand1;
+ bot.th_walk = wiz_walk1;
+ bot.th_run = wiz_run1;
+ bot.th_die = wiz_die;
+ bot.th_missile = Wiz_Missile;
+ // Berserk test from
+ // http://celephais.net/board/view_thread.php?id=4&start=3465
+ // -- dumptruck_ds
+ if !(self.berserk)
+ bot.th_pain = Wiz_Pain;
+ else
+ bot.th_pain = SUB_NullPain;
+ bot.health = 80;
+
+ // polish him up
+ bot.classname = "monster_wizard";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 22';
+ bot.mdl_proj = "progs/w_spike.mdl";
+ }
+
+ if (self.style == 7)
+ {
+ // spawn a Shambler
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/shambler.mdl");
+ setsize (bot, '-16 -16 -24', '16 16 40');
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = sham_stand1;
+ bot.th_walk = sham_walk1;
+ bot.th_run = sham_run1;
+ // Berserk test from
+ // http://celephais.net/board/view_thread.php?id=4&start=3465
+ // -- dumptruck_ds
+ if !(self.berserk)
+ bot.th_pain = sham_pain;
+ else
+ bot.th_pain = SUB_NullPain;
+ bot.th_die = sham_die;
+ bot.th_missile = sham_magic1;
+ bot.th_melee = sham_melee;
+ bot.health = 600;
+
+ // polish him up
+ bot.classname = "monster_shambler";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 2';
+ // bot.view_ofs = '0 0 22';
+ }
+
+ if (self.style == 8)
+ {
+ // spawn a Knight
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/knight.mdl");
+ setsize (bot, '-16 -16 -24', '16 16 40');
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = knight_stand1;
+ bot.th_walk = knight_walk1;
+ bot.th_run = knight_run1;
+ bot.th_die = knight_die;
+ bot.th_melee = knight_atk1;
+ // bot.th_missile = knight_atk1;
+ // Berserk test from
+ // http://celephais.net/board/view_thread.php?id=4&start=3465
+ // -- dumptruck_ds
+ if !(self.berserk)
+ bot.th_pain = knight_pain;
+ else
+ bot.th_pain = SUB_NullPain;
+ bot.health = 75;
+
+ // polish him up
+ bot.classname = "monster_knight";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 22';
+ }
+
+ if (self.style == 9)
+ {
+ // spawn a HellKnight
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/hknight.mdl");
+ setsize (bot, '-16 -16 -24', '16 16 40');
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = hknight_stand1;
+ bot.th_walk = hknight_walk1;
+ bot.th_run = hknight_run1;
+ bot.th_melee = hknight_melee;
+ bot.th_die = hknight_die;
+ bot.th_missile = hknight_magicc1;
+ // Berserk test from
+ // http://celephais.net/board/view_thread.php?id=4&start=3465
+ // -- dumptruck_ds
+ if !(self.berserk)
+ bot.th_pain = hknight_pain;
+ else
+ bot.th_pain = SUB_NullPain;
+ bot.health = 250;
+
+ // polish him up
+ bot.classname = "monster_hell_knight";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 22';
+ }
+
+ if (self.style == 11)
+ {
+ // spawn a Zombie
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/zombie.mdl");
+ setsize (bot, '-16 -16 -24', '16 16 40');
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = zombie_start;
+ bot.th_walk = zombie_walk1;
+ bot.th_run = zombie_decide;
+ bot.th_pain = zombie_pain;
+ bot.th_die = zombie_die;
+ bot.th_missile = zombie_missile;
+ bot.health = 61;
+
+ // polish him up
+ bot.classname = "monster_zombie";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 2';
+ // bot.view_ofs = '0 0 22';
+ }
+
+ if (self.style == 12)
+ {
+ // spawn a Shalrath
+ // set size and shape
+ bot.solid = SOLID_SLIDEBOX;
+ bot.movetype = MOVETYPE_STEP;
+ setmodel (bot, "progs/shalrath.mdl");
+ setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
+ bot.flags = bot.flags | FL_MONSTER;
+ bot.takedamage = DAMAGE_AIM;
+
+ // define his animation
+ bot.th_stand = shal_stand;
+ bot.th_walk = shal_walk1;
+ bot.th_run = shal_run1;
+ bot.th_die = shalrath_die;
+ bot.th_missile = shal_attack1;
+ // fix for func_monster_spawner setting Voreballs to non-homing
+ bot.homing = 1;
+ // Berserk test from
+ // http://celephais.net/board/view_thread.php?id=4&start=3465
+ // -- dumptruck_ds
+ if !(self.berserk)
+ bot.th_pain = shalrath_pain;
+ else
+ bot.th_pain = SUB_NullPain;
+ bot.health = 400;
+
+ // polish him up
+ bot.classname = "monster_shalrath";
+ bot.ideal_yaw = bot.angles * '0 1 0';
+ bot.yaw_speed = 120;
+ bot.view_ofs = '0 0 22';
+ }
+
+ // begin his thinking
+ // this seems better with monster_use -- dumptruck_ds
+ bot.nextthink = time + 0.2;
+ // bot.nextthink = time + 0.1 + random();
+ if (!(self.spawnflags & MOBOT_DONT_SPAWN_ANGRY))
+ {
+ // required to avoid animation issues -- dumptruck_ds
+ if (bot.classname != "monster_zombie")
+ bot.think = monster_use;
+ else
+ bot.think = bot.th_walk;
+ }
+ else
+ {
+ bot.think = walkmonster_start_go;
+ }
+
+ if (!(self.spawnflags & MOBOT_DONT_ADD_KILL_COUNT))
+ {
+ // repacement function from iw -- dumptruck_ds
+ monster_update_total (1);
+ }
+};
+
+//----------------------------------------------------------------------
+void() think_mobot =
+{
+ dprint ("mobot thinking\n");
+ // telefrag check thanks to ryanscissorhands for this code!
+ // -- dumptruck_ds
+ local entity nearby;
+
+ // findradius (vector origin, float radius in Quake units)
+ nearby = findradius (self.origin, 128);
+
+ while (nearby)
+ {
+ if (nearby.takedamage)
+ {
+ dprint ("monster waiting to spawn\n");
+ // qss crash fix from paavohuhtala -- dumptruck_ds
+ self.think = think_mobot;
+ // delay the spawn by some amount;
+ self.nextthink = time + 1;
+ return;
+ }
+ nearby = nearby.chain;
+ }
+
+ self.count = self.count - 1;
+
+ if (self.count < 0)
+ return;
+
+ if (self.count!=0)
+ {
+ if !(self.wait)
+ self.nextthink = time + 5;
+ else
+ self.nextthink = time + self.wait;
+
+ if (self.style2 == 1)
+ {
+ // random monster!! -- dumptruck_ds
+ self.style = floor (random() * 12) + 1;
+ // thanks whirledtsar for your help on this
+ // -- dumptruck_ds
+ create_mobot ();
+ }
+ else
+ {
+ create_mobot ();
+ }
+ }
+ else
+ {
+ if (self.spawnflags & MOBOT_SPAWNER_RESET)
+ {
+ self.count = self.cnt;
+ self.think = SUB_Null;
+ }
+ }
+
+ // qthink I didn't realize I could do this! -- dumptruck_ds
+ self.think = think_mobot;
+};
+
+/*QUAKED func_monster_spawner (.75 0 .75) (-8 -8 -8) (8 8 8) REUSABLE 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
+Spawns monsters to targeted info_monster_spawnpoint
+bot
+Choose Style
+• 1 (Dog (Default)
+• 2 (Grunt)
+• 3 (Enforcer)
+• 4 (Ogre)
+• 5 (Fiend)
+• 6 (Wizard)
+• 7 (Shambler)
+• 8 (Knight)
+• 9 (HellKnight)
+• 10 (Spawn)
+• 11 (Zombie)
+• 12 (Shalrath)
+
+Style 2 set to 1 overrides Style and chooses a random monster (excluding Zombies and Vores)
+
+Default time between spawns is 5 seconds; 12 for Zombies and Vores to reduce telefrags
+
+Can set Berserk to 1 to skip most pain animations.
+
+Can only use default health, models and sounds.
+*/
+void() func_monster_spawner =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if !(self.target)
+ {
+ objerror ("func_monster_spawner needs a target");
+ remove (self);
+ return;
+ }
+
+ if !(self.style)
+ self.style = 1;
+
+ if (!self.count)
+ self.count = 5;
+ // fixes count display
+ self.count = self.count + 1;
+ // hold original count
+ self.cnt = self.count;
+
+ self.use = think_mobot;
+};

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

Diff qc/func/new_plat.qc

diff --git a/qc/func/new_plat.qc b/qc/func/new_plat.qc
new file mode 100644
index 0000000..31b817d
--- /dev/null
+++ b/qc/func/new_plat.qc
@@ -0,0 +1,685 @@
+//==============================================================================
+// func_new_plat - Rogue Dissolution Of Eternity platforms
+//==============================================================================
+
+// newplats.qc
+// pmack
+// september 1996
+
+// constants / TYPES
+const float DN_N_WAIT = 1;
+const float PLT_TOGGLE = 2;
+const float ELEVATOR = 4;
+const float START_AT_TOP = 8;
+const float PLAT2 = 16;
+const float PLAT2_BOTTOM = 32;
+
+// globals
+float elv_butn_dir;
+
+//======================================================================
+// down N and wait code
+//======================================================================
+
+// prototypes
+void() dn_and_wait_go_up;
+void() dn_and_wait_go_down;
+void() dn_and_wait_crush;
+
+//----------------------------------------------------------------------
+void() dn_and_wait_hit_top =
+{
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_TOP;
+};
+
+//----------------------------------------------------------------------
+void() dn_and_wait_hit_bottom =
+{
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_BOTTOM;
+ self.think = dn_and_wait_go_up;
+ self.nextthink = self.ltime + self.health;
+};
+
+//----------------------------------------------------------------------
+void() dn_and_wait_go_down =
+{
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ self.state = STATE_DOWN;
+ SUB_CalcMove (self.pos2, self.speed, dn_and_wait_hit_bottom);
+};
+
+//----------------------------------------------------------------------
+void() dn_and_wait_go_up =
+{
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ self.state = STATE_UP;
+ SUB_CalcMove (self.pos1, self.speed, dn_and_wait_hit_top);
+};
+
+//----------------------------------------------------------------------
+void() dn_and_wait_crush =
+{
+ T_Damage (other, self, self, 1);
+
+ if (self.state == STATE_UP)
+ dn_and_wait_go_down ();
+ else if (self.state == STATE_DOWN)
+ dn_and_wait_go_up ();
+ else
+ objerror ("plat_new_crush: bad self.state\n");
+};
+
+//----------------------------------------------------------------------
+void() dn_and_wait_use =
+{
+ if (self.state != STATE_TOP)
+ return;
+
+ dn_and_wait_go_down ();
+};
+
+//======================================================================
+// toggle type code
+//======================================================================
+
+// prototypes
+void() toggle_go_up;
+void() toggle_go_down;
+void() toggle_crush;
+
+//----------------------------------------------------------------------
+void() toggle_hit_top =
+{
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_TOP;
+};
+
+//----------------------------------------------------------------------
+void() toggle_hit_bottom =
+{
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_BOTTOM;
+};
+
+//----------------------------------------------------------------------
+void() toggle_go_down =
+{
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ self.state = STATE_DOWN;
+ SUB_CalcMove (self.pos2, self.speed, toggle_hit_bottom);
+};
+
+//----------------------------------------------------------------------
+void() toggle_go_up =
+{
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ self.state = STATE_UP;
+ SUB_CalcMove (self.pos1, self.speed, toggle_hit_top);
+};
+
+//----------------------------------------------------------------------
+void() toggle_crush =
+{
+ T_Damage (other, self, self, 1);
+
+ if (self.state == STATE_UP)
+ toggle_go_down ();
+ else if (self.state == STATE_DOWN)
+ toggle_go_up ();
+ else
+ objerror ("plat_new_crush: bad self.state\n");
+};
+
+//----------------------------------------------------------------------
+void() toggle_use =
+{
+ if (self.state == STATE_TOP)
+ toggle_go_down ();
+ else if (self.state == STATE_BOTTOM)
+ toggle_go_up ();
+};
+
+//======================================================================
+// elvtr type code
+//======================================================================
+
+// prototypes
+void() elvtr_crush;
+
+//----------------------------------------------------------------------
+void() elvtr_stop =
+{
+ self.elevatorOnFloor = self.elevatorToFloor;
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_BOTTOM;
+ self.elevatorLastUse = time;
+};
+
+//----------------------------------------------------------------------
+void() elvtr_go =
+{
+ self.elevatorDestination = self.pos2;
+ self.elevatorDestination_z = self.pos2_z +
+ (self.height * self.elevatorToFloor);
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ self.state = STATE_UP;
+ SUB_CalcMove (self.elevatorDestination, self.speed, elvtr_stop);
+ self.elevatorLastUse = time;
+};
+
+//----------------------------------------------------------------------
+void() elvtr_crush =
+{
+ local float tmp;
+
+ // T_Damage (other, self, self, 1);
+
+ // the elevator is changing direction, so swap the floor it's coming
+ // from and the floor it's going to -- iw
+ tmp = self.elevatorOnFloor;
+ self.elevatorOnFloor = self.elevatorToFloor;
+ self.elevatorToFloor = tmp;
+
+ elvtr_go ();
+};
+
+//----------------------------------------------------------------------
+// elvtr_use -- elevator use function
+// self = plat, other = elevator button, other.enemy = player
+//----------------------------------------------------------------------
+void() elvtr_use =
+{
+ local float tempDist, elvPos, btnPos;
+
+ // the original DoE code allowed an elevator to be activated again
+ // when it was in the process of moving between floors (assuming the
+ // wait period was over); this resulted in sometimes unintuitive
+ // behavior, so, the following test prevents this -- iw
+ if (self.elevatorToFloor != self.elevatorOnFloor)
+ return;
+
+ // the original DoE code had a hard-coded two second wait period;
+ // this has been changed for progs_dump so that self.wait is used
+ // instead -- iw
+ if ((self.elevatorLastUse + self.wait) > time)
+ return;
+
+ self.elevatorLastUse = time;
+
+ if (elv_butn_dir == 0)
+ return;
+
+ elvPos = (self.absmin_z + self.absmax_z) * 0.5;
+ btnPos = (other.absmin_z + other.absmax_z) * 0.5;
+
+ if (elvPos > btnPos)
+ {
+ tempDist = (elvPos - btnPos) / self.height;
+ tempDist = ceil (tempDist);
+ self.elevatorToFloor = self.elevatorOnFloor - tempDist;
+ elvtr_go ();
+ return;
+ }
+ else
+ {
+ tempDist = btnPos - elvPos;
+ if (tempDist > self.height)
+ {
+ tempDist = tempDist / self.height;
+ tempDist = floor (tempDist);
+ self.elevatorToFloor = self.elevatorOnFloor + tempDist;
+ elvtr_go ();
+ return;
+ }
+ }
+
+ if (elv_butn_dir == -1)
+ {
+ if (self.elevatorOnFloor > 0)
+ {
+ self.elevatorToFloor = self.elevatorOnFloor - 1;
+ elvtr_go ();
+ }
+ }
+ else if (elv_butn_dir == 1)
+ {
+ if (self.elevatorOnFloor < (self.cnt - 1))
+ {
+ self.elevatorToFloor = self.elevatorOnFloor + 1;
+ elvtr_go ();
+ }
+ }
+};
+
+//======================================================================
+// PLAT2 type code
+//======================================================================
+
+// prototypes
+void() plat2_center_touch;
+void() plat2_go_up;
+void() plat2_go_down;
+void() plat2_crush;
+
+//----------------------------------------------------------------------
+void() plat2_spawn_inside_trigger =
+{
+ local entity trigger;
+ local vector tmin, tmax;
+
+ // middle trigger
+ trigger = spawn ();
+ trigger.touch = plat2_center_touch;
+ trigger.movetype = MOVETYPE_NONE;
+ trigger.solid = SOLID_TRIGGER;
+ trigger.enemy = self;
+
+ tmin = self.mins + '25 25 0';
+ tmax = self.maxs - '25 25 -8';
+ tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
+
+ if (self.spawnflags & PLAT_LOW_TRIGGER)
+ tmax_z = tmin_z + 8;
+
+ if (self.size_x <= 50)
+ {
+ tmin_x = (self.mins_x + self.maxs_x) / 2;
+ tmax_x = tmin_x + 1;
+ }
+ if (self.size_y <= 50)
+ {
+ tmin_y = (self.mins_y + self.maxs_y) / 2;
+ tmax_y = tmin_y + 1;
+ }
+
+ setsize (trigger, tmin, tmax);
+};
+
+//----------------------------------------------------------------------
+void() plat2_hit_top =
+{
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_TOP;
+
+ self.plat2LastMove = time;
+ if (self.plat2Called == 1)
+ {
+ self.think = plat2_go_down;
+ self.nextthink = self.ltime + 1.5;
+ self.plat2Called = 0;
+ // allow immediate move
+ self.plat2LastMove = 0;
+ }
+ else if (!(self.spawnflags & START_AT_TOP))
+ {
+ self.think = plat2_go_down;
+ self.nextthink = self.ltime + self.delay;
+ self.plat2Called = 0;
+ }
+};
+
+//----------------------------------------------------------------------
+void() plat2_hit_bottom =
+{
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_BOTTOM;
+
+ self.plat2LastMove = time;
+ if (self.plat2Called == 1)
+ {
+ self.think = plat2_go_up;
+ self.nextthink = self.ltime + 1.5;
+ self.plat2Called = 0;
+ // allow immediate move
+ self.plat2LastMove = 0;
+ }
+ else if (self.spawnflags & START_AT_TOP)
+ {
+ self.think = plat2_go_up;
+ self.nextthink = self.ltime + self.delay;
+ self.plat2Called = 0;
+ }
+};
+
+//----------------------------------------------------------------------
+void() plat2_go_down =
+{
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ self.state = STATE_DOWN;
+ SUB_CalcMove (self.pos2, self.speed, plat2_hit_bottom);
+};
+
+//----------------------------------------------------------------------
+void() plat2_go_up =
+{
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ self.state = STATE_UP;
+ SUB_CalcMove (self.pos1, self.speed, plat2_hit_top);
+};
+
+//----------------------------------------------------------------------
+void() plat2_use =
+{
+ if(self.state > 4)
+ self.state = self.state - 10;
+
+ self.use = SUB_Null;
+};
+
+//----------------------------------------------------------------------
+void() plat2_center_touch =
+{
+ local float otherState;
+ local vector platPosition;
+
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ // at this point, self is the trigger. self.enemy is the plat.
+ // this changes self to be the plat, other is the player.
+ self = self.enemy;
+
+ if ((self.plat2LastMove + 2) > time)
+ return;
+
+ if (self.state > 4)
+ // disabled.
+ return;
+
+ if (self.plat2GoTo > STATE_BOTTOM)
+ {
+ if (self.plat2GoTime < time)
+ {
+ if (self.plat2GoTo == STATE_UP)
+ plat2_go_up ();
+ else
+ plat2_go_down ();
+
+ self.plat2GoTo = 0;
+ }
+ return;
+ }
+
+ if (self.state > STATE_BOTTOM)
+ // STATE_UP or STATE_DOWN
+ return;
+
+ platPosition = (self.absmax + self.absmin) * 0.5;
+
+ if (self.state == STATE_TOP)
+ {
+ otherState = STATE_TOP;
+ if (platPosition_z > other.origin_z)
+ otherState = STATE_BOTTOM;
+ }
+ else
+ {
+ otherState = STATE_BOTTOM;
+ if ((other.origin_z - platPosition_z) > self.height)
+ otherState = STATE_TOP;
+ }
+
+ if (self.state == otherState)
+ {
+ self.plat2Called = 0;
+ self.plat2GoTime = time + 0.5;
+ }
+ else
+ {
+ self.plat2GoTime = time + 0.1;
+ self.plat2Called = 1;
+ }
+
+ if (self.state == STATE_BOTTOM)
+ self.plat2GoTo = STATE_UP;
+ else if (self.state == STATE_TOP)
+ self.plat2GoTo = STATE_DOWN;
+};
+
+//----------------------------------------------------------------------
+void() plat2_crush =
+{
+ T_Damage (other, self, self, 1);
+
+ if (self.state == STATE_UP)
+ plat2_go_down ();
+ else if (self.state == STATE_DOWN)
+ plat2_go_up ();
+ else
+ objerror ("plat2_crush: bad self.state\n");
+};
+
+//======================================================================
+// Common Plat Code
+//======================================================================
+
+/*QUAKED func_new_plat (0 .5 .8) ? DN_N_WAIT PLT_TOGGLE ELEVATOR START_AT_TOP PLAT2 P2_BOTTOM 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
+
+
+--------------
+DN_N_WAIT is a plat that starts at the top and when triggered, goes down, waits, then comes back up.
+health - number of seconds to wait (default 5)
+--------------
+PLT_TOGGLE is a plat that will change between the top and bottom each time it is triggered.
+--------------
+ELEVATOR is an elevator plat. You can have as many levels as you want but they must be all the same distance away. Use elevator button entity as the trigger.
+cnt is the number of floors
+height is the distance between floors
+wait is the number of seconds before the elevator can be activated again after starting or stopping (default 0)
+
+START_AT_TOP is an optional flag for elevators. It just tells the elevator that it's position is the top floor. (Default is the bottom floor) USE THIS ONLY WITH ELEVATORS!
+-------------
+PLAT2 is a fixed version of the original plat. If you want the plat to start at the bottom and move to the top on demand, use a negative height. That will tell Quake to lower the plat at spawn time. Always place this plat type in the top position when making the map. This will ensure correct lighting, hopefully. If a plat2 is the target of a trigger, it will be disabled until it has been triggered. Delay is the wait before the plat returns to original position.
+
+If you don't want to bother figuring out the height, don't put a
+value in the height
+
+delay default 3
+speed default 150
+cnt default 2
+
+P2_BOTTOM is an optional switch to have an auto-sized plat2 start at the bottom.
+--------------
+Plats are always drawn in the extended position, so they will light correctly.
+
+If the plat is the target of another trigger or button, it will start out disabled in the extended position until it is trigger, when it will lower and become a normal plat.
+
+If the "height" key is set, that will determine the amount the plat moves, instead of being implicitly determined by the model's height.
+Set "sounds" to one of the following:
+1) base fast
+2) chain slow
+*/
+void() func_new_plat =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ //local entity t;
+ local float negativeHeight;
+
+ negativeHeight = 0;
+
+ if (!self.t_length)
+ self.t_length = 80;
+ if (!self.t_width)
+ self.t_width = 10;
+
+ if (self.sounds == 0)
+ self.sounds = 2;
+
+ // FIX THIS TO LOAD A GENERIC PLAT SOUND
+
+ if (self.sounds == 1)
+ {
+ if (!self.noise || self.noise == "")
+ self.noise = "plats/plat1.wav";
+ if (!self.noise1 || self.noise1 == "")
+ self.noise1 = "plats/plat2.wav";
+ }
+ else if (self.sounds == 2)
+ {
+ if (!self.noise || self.noise == "")
+ self.noise = "plats/medplat1.wav";
+ if (!self.noise1 || self.noise1 == "")
+ self.noise1 = "plats/medplat2.wav";
+ }
+ else if (self.sounds == 3)
+ {
+ // base door sound
+ if (!self.noise || self.noise == "")
+ self.noise = "doors/hydro1.wav";
+ if (!self.noise1 || self.noise1 == "")
+ self.noise1 = "doors/hydro2.wav";
+ }
+ else if (self.sounds == 4)
+ {
+ // func_train sounds
+ if (!self.noise || self.noise == "")
+ self.noise = "plats/train1.wav";
+ if (!self.noise1 || self.noise1 == "")
+ self.noise1 = "plats/train2.wav";
+ }
+ else
+ {
+ if (!self.noise || self.noise == "")
+ self.noise = "misc/null.wav";
+ if (!self.noise1 || self.noise1 == "")
+ self.noise1 = "misc/null.wav";
+ }
+
+ precache_sound (self.noise);
+ precache_sound (self.noise1);
+
+ self.mangle = self.angles;
+ self.angles = '0 0 0';
+
+ self.classname = "plat";
+ self.solid = SOLID_BSP;
+ self.movetype = MOVETYPE_PUSH;
+ setorigin (self, self.origin);
+ setmodel (self, self.model);
+ setsize (self, self.mins , self.maxs);
+
+ if (!self.speed)
+ self.speed = 150;
+
+ // pos1 is the top position, pos2 is the bottom
+ self.pos1 = self.origin;
+ self.pos2 = self.origin;
+
+ if (self.height < 0)
+ {
+ negativeHeight = 1;
+ self.height = 0 - self.height;
+ }
+
+ if (self.height)
+ {
+ self.pos2_z = self.origin_z - self.height;
+ }
+ else
+ {
+ negativeHeight = 1;
+ self.height = self.size_z - 8;
+ self.pos2_z = self.origin_z - self.height;
+ }
+
+ if (self.spawnflags & DN_N_WAIT)
+ {
+ self.use = dn_and_wait_use;
+ self.blocked = dn_and_wait_crush;
+
+ if (negativeHeight == 1)
+ {
+ self.state = STATE_BOTTOM;
+ setorigin (self, self.pos2);
+ }
+ else
+ self.state = STATE_TOP;
+
+ if (!self.health)
+ self.health = 5;
+ }
+ else if (self.spawnflags & PLT_TOGGLE)
+ {
+ self.use = toggle_use;
+ self.blocked = toggle_crush;
+ if (negativeHeight == 1)
+ {
+ setorigin (self, self.pos2);
+ self.state = STATE_BOTTOM;
+ }
+ else
+ {
+ self.state = STATE_TOP;
+ }
+ }
+ else if (self.spawnflags & ELEVATOR)
+ {
+ self.elevatorLastUse = 0;
+
+ // allow the mapper to set self.wait, but don't allow a negative
+ // wait period -- iw
+ if (self.wait < 0)
+ self.wait = 0;
+
+ if (self.spawnflags & START_AT_TOP)
+ {
+ self.pos1 = self.origin;
+ self.pos2 = self.origin;
+ self.pos2_z = self.origin_z -
+ (self.height * (self.cnt - 1));
+ self.elevatorOnFloor = self.cnt - 1;
+ self.elevatorToFloor = self.elevatorOnFloor;
+ }
+ else
+ {
+ self.pos1 = self.origin;
+ self.pos2 = self.origin;
+ self.pos1_z = self.origin_z +
+ (self.height * (self.cnt - 1));
+ self.elevatorOnFloor = 0;
+ self.elevatorToFloor = self.elevatorOnFloor;
+ }
+
+ self.use = elvtr_use;
+ self.blocked = elvtr_crush;
+ }
+ else if (self.spawnflags & PLAT2)
+ {
+ // the "start moving" trigger
+ plat2_spawn_inside_trigger ();
+ self.plat2Called = 0;
+ self.plat2LastMove = 0;
+ self.plat2GoTo = 0;
+ self.plat2GoTime = 0;
+ self.blocked = plat2_crush;
+
+ if (!self.delay)
+ self.delay = 3;
+
+ if (negativeHeight == 1)
+ {
+ self.state = STATE_BOTTOM;
+ // make sure START_AT_TOP isn't set. We need that...
+ self.spawnflags = PLAT2;
+ setorigin (self, self.pos2);
+ }
+ else
+ {
+ // default position is top.
+ self.spawnflags = self.spawnflags | START_AT_TOP;
+ self.state = STATE_TOP;
+ }
+
+ if (self.targetname != "")
+ {
+ self.use = plat2_use;
+ self.state = self.state + 10;
+ }
+ }
+};

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

Diff qc/func/particlefield.qc

diff --git a/qc/func/particlefield.qc b/qc/func/particlefield.qc
new file mode 100644
index 0000000..e2fb276
--- /dev/null
+++ b/qc/func/particlefield.qc
@@ -0,0 +1,258 @@
+//==============================================================================
+// func_particlefield -- Hipnotic Interactive, Jim Dose'
+//==============================================================================
+
+// Particle effects QuickC program
+// By Jim Dose' 9/19/96
+// Copyright (c)1996 Hipnotic Interactive, Inc.
+// All rights reserved.
+// Distributed (unsupported) on 3.12.97
+
+// constants
+// float START_OFF = 1;
+const float USE_COUNT = 1;
+
+//----------------------------------------------------------------------
+void() particlefield_XZ =
+{
+ local vector pos;
+ local vector start;
+ local vector end;
+
+ if ((self.spawnflags & USE_COUNT) &&
+ (counter_GetCount(other) != self.cnt))
+ {
+ return;
+ }
+
+ // dprint( "XZ\n" );
+ self.ltime = time + 0.25;
+
+ if (self.noise != "")
+ {
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ }
+
+ // Only show particles if client is visible.
+ // This helps to keep network traffic down to a minimum.
+ if (!checkclient())
+ return;
+
+ start = self.dest1 + self.origin;
+ end = self.dest2 + self.origin;
+ pos_y = start_y;
+ pos_z = start_z;
+
+ while (pos_z <= end_z)
+ {
+ pos_x = start_x;
+ while (pos_x <= end_x)
+ {
+ particle (pos, '0 0 0', self.color, self.count);
+ pos_x = pos_x + 16;
+ }
+ pos_z = pos_z + 16;
+ }
+};
+
+//----------------------------------------------------------------------
+void() particlefield_YZ =
+{
+ local vector pos;
+ local vector start;
+ local vector end;
+
+ if ((self.spawnflags & USE_COUNT) &&
+ (counter_GetCount(other) != self.cnt))
+ {
+ return;
+ }
+
+ // dprint( "YZ: " );
+ // dprint( vtos( self.dest1 ) );
+ // dprint( " - " );
+ // dprint( vtos( self.dest2 ) );
+ // dprint( "\n" );
+
+ self.ltime = time + 0.25;
+
+ if (self.noise != "")
+ {
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ }
+
+ // Only show particles if client is visible.
+ // This helps to keep network traffic down to a minimum.
+ if (!checkclient())
+ return;
+
+ start = self.dest1 + self.origin;
+ end = self.dest2 + self.origin;
+ pos_x = start_x;
+ pos_z = start_z;
+
+ while (pos_z < end_z)
+ {
+ pos_y = start_y;
+ while (pos_y < end_y)
+ {
+ particle (pos, '0 0 0', self.color, self.count);
+ pos_y = pos_y + 16;
+ }
+ pos_z = pos_z + 16;
+ }
+};
+
+//----------------------------------------------------------------------
+void() particlefield_XY =
+{
+ local vector pos;
+ local vector start;
+ local vector end;
+
+ if (( self.spawnflags & USE_COUNT) &&
+ (counter_GetCount( other ) != self.cnt ))
+ {
+ return;
+ }
+
+ // dprint( "XY\n" );
+
+ self.ltime = time + 0.25;
+
+ if (self.noise != "")
+ {
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ }
+
+ // Only show particles if client is visible.
+ // This helps to keep network traffic down to a minimum.
+ if (!checkclient())
+ return;
+
+ start = self.dest1 + self.origin;
+ end = self.dest2 + self.origin;
+ pos_x = start_x;
+ pos_z = start_z;
+
+ while (pos_x < end_x)
+ {
+ pos_y = start_y;
+ while (pos_y < end_y)
+ {
+ particle (pos, '0 0 0', self.color, self.count);
+ pos_y = pos_y + 16;
+ }
+ pos_x = pos_x + 16;
+ }
+};
+
+//----------------------------------------------------------------------
+void() particlefield_touch =
+{
+ if (!self.dmg)
+ return;
+
+ if (time > self.ltime)
+ return;
+
+ if (time < self.attack_finished)
+ return;
+
+ self.attack_finished = time + 0.5;
+ T_Damage (other, self, self, self.dmg);
+};
+
+/*QUAKED func_particlefield (0 .5 .8) ? USE_COUNT 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
+
+Creates a brief particle flash roughly the size of the defining
+brush each time it is triggered.
+
+USE_COUNT when the activator is a func_counter, the field will only
+activate when count is equal to "cnt". Same as using a func_oncount
+to trigger.
+
+"cnt" is the count to activate on when USE_COUNT is set.
+"color" is the color of the particles. Default is 192 (yellow).
+"count" is the density of the particles. Default is 2.
+"noise" is the sound to play when triggered. Do not use a looping sound here.
+"dmg" is the amount of damage to cause when touched.
+*/
+void() func_particlefield =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.color)
+ {
+ self.color = 192;
+ }
+
+ if (self.count == 0)
+ {
+ self.count = 2;
+ }
+
+ self.classname = "particlefield";
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NONE;
+ setmodel (self, self.model);
+ self.model = string_null;
+
+ self.origin = (self.mins + self.maxs) * 0.5;
+ setorigin (self, self.origin);
+ self.dest = self.maxs - self.mins - '16 16 16';
+ self.dest1 = self.mins + '8 8 8' - self.origin;
+ self.dest2 = self.maxs + '7.9 7.9 7.9' - self.origin;
+ setsize (self, self.mins, self.maxs);
+ self.touch = particlefield_touch;
+ // dprint (vtos(self.dest));
+ // dprint (" ");
+
+ if (self.dest_x > self.dest_z)
+ {
+ if (self.dest_y > self.dest_z)
+ {
+ // dprint ("XY1 - ");
+ // dprint (ftos(self.cnt));
+ // dprint ("\n");
+
+ self.use = particlefield_XY;
+ self.dest1_z = (self.dest1_z + self.dest2_z) / 2;
+ }
+ else
+ {
+ // dprint ("XZ1 - ");
+ // dprint (ftos(self.cnt));
+ // dprint ("\n");
+ self.use = particlefield_XZ;
+ self.dest1_y = (self.dest1_y + self.dest2_y) / 2;
+ }
+ }
+ else
+ {
+ if (self.dest_y > self.dest_x)
+ {
+ // dprint ("YZ2 - ");
+ // dprint (ftos(self.cnt));
+ // dprint ("\n");
+ self.use = particlefield_YZ;
+ self.dest1_x = (self.dest1_x + self.dest2_x) / 2;
+ }
+ else
+ {
+ // dprint ("XZ2 - ");
+ // dprint (ftos(self.cnt));
+ // dprint ("\n");
+ self.use = particlefield_XZ;
+ self.dest1_y = (self.dest1_y + self.dest2_y) / 2;
+ }
+ }
+
+ if (self.noise != "")
+ {
+ precache_sound (self.noise);
+ }
+ self.ltime = time;
+};

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

Diff qc/func/plat.qc

diff --git a/qc/func/plat.qc b/qc/func/plat.qc
new file mode 100644
index 0000000..85e309c
--- /dev/null
+++ b/qc/func/plat.qc
@@ -0,0 +1,226 @@
+//==============================================================================
+// func_plat -- was plats.qc
+//==============================================================================
+
+// constants
+const float PLAT_LOW_TRIGGER = 1;
+
+// prototypes
+void() plat_center_touch;
+void() plat_outside_touch;
+void() plat_trigger_use;
+void() plat_go_up;
+void() plat_go_down;
+void() plat_crush;
+
+//----------------------------------------------------------------------
+void() plat_spawn_inside_trigger =
+{
+ local entity trigger;
+ local vector tmin, tmax;
+
+ // middle trigger
+ trigger = spawn ();
+ trigger.touch = plat_center_touch;
+ trigger.movetype = MOVETYPE_NONE;
+ trigger.solid = SOLID_TRIGGER;
+ trigger.enemy = self;
+
+ tmin = self.mins + '25 25 0';
+ tmax = self.maxs - '25 25 -8';
+ tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
+ if (self.spawnflags & PLAT_LOW_TRIGGER)
+ tmax_z = tmin_z + 8;
+
+ if (self.size_x <= 50)
+ {
+ tmin_x = (self.mins_x + self.maxs_x) / 2;
+ tmax_x = tmin_x + 1;
+ }
+
+ if (self.size_y <= 50)
+ {
+ tmin_y = (self.mins_y + self.maxs_y) / 2;
+ tmax_y = tmin_y + 1;
+ }
+
+ setsize (trigger, tmin, tmax);
+};
+
+//----------------------------------------------------------------------
+void() plat_hit_top =
+{
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_TOP;
+ self.think = plat_go_down;
+ self.nextthink = self.ltime + 3;
+};
+
+//----------------------------------------------------------------------
+void() plat_hit_bottom =
+{
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ self.state = STATE_BOTTOM;
+};
+
+//----------------------------------------------------------------------
+void() plat_go_down =
+{
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ self.state = STATE_DOWN;
+ SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom);
+};
+
+//----------------------------------------------------------------------
+void() plat_go_up =
+{
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ self.state = STATE_UP;
+ SUB_CalcMove (self.pos1, self.speed, plat_hit_top);
+};
+
+//----------------------------------------------------------------------
+void() plat_center_touch =
+{
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ self = self.enemy;
+
+ if (self.state == STATE_BOTTOM)
+ plat_go_up ();
+ else if (self.state == STATE_TOP)
+ // delay going down
+ self.nextthink = self.ltime + 1;
+};
+
+//----------------------------------------------------------------------
+void() plat_outside_touch =
+{
+ // from Copper -- dumptruck_ds
+ if (!CheckValidTouch())
+ return;
+
+ // dprint ("plat_outside_touch\n");
+ self = self.enemy;
+ if (self.state == STATE_TOP)
+ plat_go_down ();
+};
+
+//----------------------------------------------------------------------
+void() plat_trigger_use =
+{
+ if (self.think)
+ // allready activated
+ return;
+
+ plat_go_down ();
+};
+
+//----------------------------------------------------------------------
+void() plat_crush =
+{
+ // dprint ("plat_crush\n");
+
+ T_Damage (other, self, self, 1);
+
+ if (self.state == STATE_UP)
+ plat_go_down ();
+ else if (self.state == STATE_DOWN)
+ plat_go_up ();
+ else
+ objerror ("plat_crush: bad self.state\n");
+};
+
+//----------------------------------------------------------------------
+void() plat_use =
+{
+ self.use = SUB_Null;
+ if (self.state != STATE_UP)
+ objerror ("plat_use: not in up state");
+ plat_go_down ();
+};
+
+/*QUAKED func_plat (0 .5 .8) ? PLAT_LOW_TRIGGER 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
+
+speed default 150
+
+Plats are always drawn in the extended position, so they will light correctly.
+
+If the plat is the target of another trigger or button, it will start out disabled in the extended position until it is trigger, when it will lower and become a normal plat.
+
+If the "height" key is set, that will determine the amount the plat moves, instead of being implicitly determined by the model's height.
+Set "sounds" to one of the following:
+1) base fast
+2) chain slow
+*/
+void() func_plat =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.t_length)
+ self.t_length = 80;
+ if (!self.t_width)
+ self.t_width = 10;
+
+ if (self.sounds == 0)
+ self.sounds = 2;
+ // FIX THIS TO LOAD A GENERIC PLAT SOUND
+
+ if (self.sounds == 1)
+ {
+ precache_sound ("plats/plat1.wav");
+ precache_sound ("plats/plat2.wav");
+ self.noise = "plats/plat1.wav";
+ self.noise1 = "plats/plat2.wav";
+ }
+
+ if (self.sounds == 2)
+ {
+ precache_sound ("plats/medplat1.wav");
+ precache_sound ("plats/medplat2.wav");
+ self.noise = "plats/medplat1.wav";
+ self.noise1 = "plats/medplat2.wav";
+ }
+
+ self.mangle = self.angles;
+ self.angles = '0 0 0';
+
+ self.classname = "plat";
+ self.solid = SOLID_BSP;
+ self.movetype = MOVETYPE_PUSH;
+ setorigin (self, self.origin);
+ setmodel (self, self.model);
+ setsize (self, self.mins , self.maxs);
+
+ self.blocked = plat_crush;
+ if (!self.speed)
+ self.speed = 150;
+
+ // pos1 is the top position, pos2 is the bottom
+ self.pos1 = self.origin;
+ self.pos2 = self.origin;
+ if (self.height)
+ self.pos2_z = self.origin_z - self.height;
+ else
+ self.pos2_z = self.origin_z - self.size_z + 8;
+
+ self.use = plat_trigger_use;
+
+ // the "start moving" trigger
+ plat_spawn_inside_trigger ();
+
+ if (self.targetname != "")
+ {
+ self.state = STATE_UP;
+ self.use = plat_use;
+ }
+ else
+ {
+ setorigin (self, self.pos2);
+ self.state = STATE_BOTTOM;
+ }
+};

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

Diff qc/func/rotate.qc

diff --git a/qc/func/rotate.qc b/qc/func/rotate.qc
new file mode 100644
index 0000000..47ae6d1
--- /dev/null
+++ b/qc/func/rotate.qc
@@ -0,0 +1,1250 @@
+//==============================================================================
+// func_movewall, func_rotate_door, func_rotate_entity, func_rotate_train
+//==============================================================================
+
+//======================================================================
+// Rotate QuickC program
+// By Jim Dose' 10/17/96
+// Copyright (c)1996 Hipnotic Interactive, Inc.
+// All rights reserved.
+// Distributed (unsupported) on 3.12.97
+//======================================================================
+
+// fields
+.float rotate_type;
+.vector neworigin;
+.vector rotate;
+.float endtime;
+.float duration;
+.vector finalangle;
+.string path;
+.string group;
+.string event;
+
+// constants
+const float STATE_ACTIVE = 0;
+const float STATE_INACTIVE = 1;
+const float STATE_SPEEDINGUP = 2;
+const float STATE_SLOWINGDOWN = 3;
+
+const float STATE_CLOSED = 4;
+const float STATE_OPEN = 5;
+const float STATE_OPENING = 6;
+const float STATE_CLOSING = 7;
+
+const float STATE_WAIT = 0;
+const float STATE_MOVE = 1;
+const float STATE_STOP = 2;
+const float STATE_FIND = 3;
+const float STATE_NEXT = 4;
+
+const float OBJECT_ROTATE = 0;
+const float OBJECT_MOVEWALL = 1;
+const float OBJECT_SETORIGIN = 2;
+
+const float ROTATE_ENTITY_TOGGLE = 1; // spawnflags for func_rotate_entity
+const float ROTATE_ENTITY_START_ON = 2;
+
+const float PATH_ROTATE_ROTATION = 1; // spawnflags for path_rotate
+const float PATH_ROTATE_ANGLES = 2;
+const float PATH_ROTATE_STOP = 4;
+const float PATH_ROTATE_NO_ROTATE = 8;
+const float PATH_ROTATE_DAMAGE = 16;
+const float PATH_ROTATE_MOVETIME = 32;
+const float PATH_ROTATE_SET_DAMAGE = 64;
+
+const float ROTATE_DOOR_STAYOPEN = 1; // spawnflags for func_rotate_door
+
+//----------------------------------------------------------------------
+// SUB_NormalizeAngles
+//----------------------------------------------------------------------
+vector(vector ang) SUB_NormalizeAngles =
+{
+ while (ang_x > 360)
+ {
+ ang_x = ang_x - 360;
+ }
+ while (ang_x < 0)
+ {
+ ang_x = ang_x + 360;
+ }
+
+ while (ang_y > 360)
+ {
+ ang_y = ang_y - 360;
+ }
+ while (ang_y < 0)
+ {
+ ang_y = ang_y + 360;
+ }
+
+ while (ang_z > 360)
+ {
+ ang_z = ang_z - 360;
+ }
+ while (ang_z < 0)
+ {
+ ang_z = ang_z + 360;
+ }
+
+ return ang;
+};
+
+/*QUAKED info_rotate (0 0.5 0) (-4 -4 -4) (4 4 4) 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
+Used as the point of rotation for rotatable objects.
+*/
+void() info_rotate =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ // remove self after a little while, to make sure that entities that
+ // have targeted it have had a chance to spawn
+ self.nextthink = time + 2;
+ self.think = SUB_Remove;
+};
+
+//----------------------------------------------------------------------
+void() RotateTargets =
+{
+ local vector org, vx, vy, vz;
+ local entity ent;
+
+ makevectors (self.angles);
+
+ ent = find (world, targetname, self.target);
+
+ while (ent)
+ {
+ if (ent.rotate_type == OBJECT_SETORIGIN)
+ {
+ org = ent.oldorigin;
+ vx = (v_forward * org_x);
+ vy = (v_right * org_y);
+ vy = vy * -1;
+ vz = (v_up * org_z);
+ ent.neworigin = vx + vy + vz;
+ setorigin (ent, ent.neworigin + self.origin);
+ }
+ else if (ent.rotate_type == OBJECT_ROTATE)
+ {
+ ent.angles = self.angles;
+ org = ent.oldorigin;
+ vx = (v_forward * org_x);
+ vy = (v_right * org_y);
+ vy = vy * -1;
+ vz = (v_up * org_z);
+ ent.neworigin = vx + vy + vz;
+ setorigin (ent, ent.neworigin + self.origin);
+ }
+ else
+ {
+ org = ent.oldorigin;
+ vx = (v_forward * org_x);
+ vy = (v_right * org_y);
+ vy = vy * -1;
+ vz = (v_up * org_z);
+ ent.neworigin = vx + vy + vz;
+ ent.neworigin = self.origin - self.oldorigin +
+ (ent.neworigin - ent.oldorigin);
+ ent.velocity = (ent.neworigin - ent.origin) * 25;
+ }
+ ent = find (ent, targetname, self.target);
+ }
+};
+
+//----------------------------------------------------------------------
+void() RotateTargetsFinal =
+{
+ local entity ent;
+
+ ent = find (world, targetname, self.target);
+
+ while (ent)
+ {
+ ent.velocity = '0 0 0';
+ if (ent.rotate_type == OBJECT_ROTATE)
+ {
+ ent.angles = self.angles;
+ }
+ ent = find (ent, targetname, self.target);
+ }
+};
+
+//----------------------------------------------------------------------
+void() SetTargetOrigin =
+{
+ local entity ent;
+
+ ent = find (world, targetname, self.target);
+
+ while (ent)
+ {
+ if (ent.rotate_type == OBJECT_MOVEWALL)
+ {
+ setorigin (ent, self.origin - self.oldorigin +
+ (ent.neworigin - ent.oldorigin) );
+ }
+ else
+ {
+ setorigin (ent, ent.neworigin + self.origin);
+ }
+ ent = find (ent, targetname, self.target);
+ }
+};
+
+//----------------------------------------------------------------------
+void() LinkRotateTargets =
+{
+ local entity ent;
+ local vector tempvec;
+
+ self.oldorigin = self.origin;
+ ent = find (world, targetname, self.target);
+
+ while (ent)
+ {
+ if (ent.classname == "rotate_object")
+ {
+ ent.rotate_type = OBJECT_ROTATE;
+ ent.oldorigin = ent.origin - self.oldorigin;
+ ent.neworigin = ent.origin - self.oldorigin;
+ ent.owner = self;
+ }
+ else if (ent.classname == "func_movewall")
+ {
+ ent.rotate_type = OBJECT_MOVEWALL;
+ tempvec = (ent.absmin + ent.absmax) * 0.5;
+ ent.oldorigin = tempvec - self.oldorigin;
+ ent.neworigin = ent.oldorigin;
+ ent.owner = self;
+ }
+ else
+ {
+ ent.rotate_type = OBJECT_SETORIGIN;
+ ent.oldorigin = ent.origin - self.oldorigin;
+ ent.neworigin = ent.origin - self.oldorigin;
+ }
+ ent = find (ent, targetname, self.target);
+ }
+};
+
+//----------------------------------------------------------------------
+void(float amount) SetDamageOnTargets =
+{
+ local entity ent;
+
+ ent = find (world, targetname, self.target);
+
+ while (ent)
+ {
+ if (ent.classname == "trigger_hurt")
+ {
+ hurt_setdamage (ent, amount);
+ }
+ else if (ent.classname == "func_movewall")
+ {
+ ent.dmg = amount;
+ }
+ ent = find (ent, targetname, self.target);
+ }
+};
+
+//======================================================================
+// Simple continual rotatation
+//======================================================================
+
+//----------------------------------------------------------------------
+void() rotate_entity_think =
+{
+ local float t;
+
+ t = time - self.ltime;
+ self.ltime = time;
+
+ if (self.state == STATE_SPEEDINGUP)
+ {
+ self.count = self.count + self.cnt * t;
+ if (self.count > 1)
+ {
+ self.count = 1;
+ }
+
+ // get rate of rotation
+ t = t * self.count;
+ }
+ else if (self.state == STATE_SLOWINGDOWN)
+ {
+ self.count = self.count - self.cnt * t;
+ if (self.count < 0)
+ {
+ RotateTargetsFinal ();
+ self.state = STATE_INACTIVE;
+ self.think = SUB_Null;
+ return;
+ }
+
+ // get rate of rotation
+ t = t * self.count;
+ }
+
+ self.angles = self.angles + (self.rotate * t);
+ self.angles = SUB_NormalizeAngles (self.angles);
+ RotateTargets ();
+ self.nextthink = time + 0.02;
+};
+
+//----------------------------------------------------------------------
+void() rotate_entity_use =
+{
+ // change to alternate textures
+ self.frame = 1 - self.frame;
+
+ if (self.state == STATE_ACTIVE)
+ {
+ if (self.spawnflags & ROTATE_ENTITY_TOGGLE)
+ {
+ if (self.speed)
+ {
+ self.count = 1;
+ self.state = STATE_SLOWINGDOWN;
+ }
+ else
+ {
+ self.state = STATE_INACTIVE;
+ self.think = SUB_Null;
+ }
+ }
+ }
+ else if (self.state == STATE_INACTIVE)
+ {
+ self.think = rotate_entity_think;
+ self.nextthink = time + 0.02;
+ self.ltime = time;
+ if (self.speed)
+ {
+ self.count = 0;
+ self.state = STATE_SPEEDINGUP;
+ }
+ else
+ {
+ self.state = STATE_ACTIVE;
+ }
+ }
+ else if (self.state == STATE_SPEEDINGUP)
+ {
+ if (self.spawnflags & ROTATE_ENTITY_TOGGLE)
+ {
+ self.state = STATE_SLOWINGDOWN;
+ }
+ }
+ else
+ {
+ self.state = STATE_SPEEDINGUP;
+ }
+};
+
+//----------------------------------------------------------------------
+void() rotate_entity_firstthink =
+{
+ LinkRotateTargets ();
+ if (self.spawnflags & ROTATE_ENTITY_START_ON)
+ {
+ self.state = STATE_ACTIVE;
+ self.think = rotate_entity_think;
+ self.nextthink = time + 0.02;
+ self.ltime = time;
+ }
+ else
+ {
+ self.state = STATE_INACTIVE;
+ self.think = SUB_Null;
+ }
+ self.use = rotate_entity_use;
+};
+
+/*QUAKED func_rotate_entity (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE START_ON 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
+
+Creates an entity that continually rotates. Can be toggled on and
+off if targeted.
+
+TOGGLE = allows the rotation to be toggled on/off
+
+START_ON = wether the entity is spinning when spawned. If TOGGLE is 0, entity can be turned on, but not off.
+
+If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train.
+
+"rotate" is the rate to rotate.
+"target" is the center of rotation.
+"speed" is how long the entity takes to go from standing still to full speed and vice-versa.
+*/
+void() func_rotate_entity =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NONE;
+
+ setmodel (self, self.model);
+ setsize (self, self.mins, self.maxs);
+
+ if (self.speed != 0)
+ {
+ self.cnt = 1 / self.speed;
+ }
+
+ self.think = rotate_entity_firstthink;
+ self.nextthink = time + 0.1;
+ self.ltime = time;
+};
+
+//======================================================================
+// Train with rotation functionality
+//======================================================================
+
+/*QUAKED path_rotate (0.5 0.3 0) (-8 -8 -8) (8 8 8) ROTATION ANGLES STOP NO_ROTATE DAMAGE MOVETIME SET_DAMAGE
+ Path for rotate_train.
+
+ ROTATION tells train to rotate at rate specified by "rotate". Use '0 0 0' to stop rotation.
+
+ ANGLES tells train to rotate to the angles specified by "angles" while traveling to this path_rotate. Use values < 0 or > 360 to guarantee that it turns in a certain direction. Having this flag set automatically clears any rotation.
+
+ STOP tells the train to stop and wait to be retriggered.
+
+ NO_ROTATE tells the train to stop rotating when waiting to be triggered.
+
+ DAMAGE tells the train to cause damage based on "dmg".
+
+ MOVETIME tells the train to interpret "speed" as the length of time to take moving from one corner to another.
+
+ SET_DAMAGE tells the train to set all targets damage to "dmg"
+
+ "noise" contains the name of the sound to play when train stops.
+ "noise1" contains the name of the sound to play when train moves.
+ "event" is a target to trigger when train arrives at path_rotate.
+*/
+void() path_rotate =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (self.noise != "")
+ {
+ precache_sound (self.noise);
+ }
+ if ( self.noise1 != "" )
+ {
+ precache_sound (self.noise1);
+ }
+};
+
+// prototypes
+void() rotate_train;
+void() rotate_train_next;
+void() rotate_train_find;
+
+//----------------------------------------------------------------------
+void() rotate_train_think =
+{
+ local float t, timeelapsed;
+
+ t = time - self.ltime;
+ self.ltime = time;
+
+ if ((self.endtime) && (time >= self.endtime))
+ {
+ self.endtime = 0;
+ if (self.state == STATE_MOVE)
+ {
+ setorigin (self, self.finaldest);
+ self.velocity = '0 0 0';
+ }
+ if (self.think1)
+ self.think1 ();
+ }
+ else
+ {
+ timeelapsed = (time - self.cnt) * self.duration;
+ if (timeelapsed > 1)
+ timeelapsed = 1;
+ setorigin (self, self.dest1 + (self.dest2 * timeelapsed));
+ }
+
+ self.angles = self.angles + (self.rotate * t);
+ self.angles = SUB_NormalizeAngles (self.angles);
+ RotateTargets ();
+
+ self.nextthink = time + 0.02;
+};
+
+//----------------------------------------------------------------------
+void() rotate_train_use =
+{
+ if (self.think1 != rotate_train_find)
+ {
+ if (self.velocity != '0 0 0')
+ // already activated
+ return;
+ if (self.think1)
+ {
+ self.think1 ();
+ }
+ }
+};
+
+//----------------------------------------------------------------------
+void() rotate_train_wait =
+{
+ self.state = STATE_WAIT;
+
+ if (self.goalentity.noise != "")
+ {
+ sound (self, CHAN_VOICE, self.goalentity.noise, 1, ATTN_NORM);
+ }
+ else
+ {
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ }
+
+ if (self.goalentity.spawnflags & PATH_ROTATE_ANGLES)
+ {
+ self.rotate = '0 0 0';
+ self.angles = self.finalangle;
+ }
+
+ if (self.goalentity.spawnflags & PATH_ROTATE_NO_ROTATE)
+ {
+ self.rotate = '0 0 0';
+ }
+
+ self.endtime = self.ltime + self.goalentity.wait;
+ self.think1 = rotate_train_next;
+};
+
+//----------------------------------------------------------------------
+void() rotate_train_stop =
+{
+ self.state = STATE_STOP;
+
+ if (self.goalentity.noise != "")
+ {
+ sound (self, CHAN_VOICE, self.goalentity.noise, 1, ATTN_NORM);
+ }
+ else
+ {
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ }
+
+ if (self.goalentity.spawnflags & PATH_ROTATE_ANGLES)
+ {
+ self.rotate = '0 0 0';
+ self.angles = self.finalangle;
+ }
+
+ if (self.goalentity.spawnflags & PATH_ROTATE_NO_ROTATE)
+ {
+ self.rotate = '0 0 0';
+ }
+
+ self.dmg = 0;
+ self.think1 = rotate_train_next;
+};
+
+//----------------------------------------------------------------------
+void() rotate_train_next =
+{
+ local entity current, targ;
+ local vector vdestdelta;
+ local float len, traveltime, div;
+ local string temp;
+
+ self.state = STATE_NEXT;
+
+ current = self.goalentity;
+ targ = find (world, targetname, self.path);
+ if (targ.classname != "path_rotate")
+ objerror ("Next target is not path_rotate");
+
+ if (self.goalentity.noise1 != "")
+ {
+ self.noise1 = self.goalentity.noise1;
+ }
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+
+ self.goalentity = targ;
+ self.path = targ.target;
+ if (!self.path )
+ objerror ("rotate_train_next: no next target");
+
+ if (targ.spawnflags & PATH_ROTATE_STOP)
+ {
+ self.think1 = rotate_train_stop;
+ }
+ else if (targ.wait)
+ {
+ self.think1 = rotate_train_wait;
+ }
+ else
+ {
+ self.think1 = rotate_train_next;
+ }
+
+ if (current.event != "")
+ {
+ // Trigger any events that should happen at the corner.
+ temp = self.target;
+ self.target = current.event;
+ self.message = current.message;
+ SUB_UseTargets ();
+ self.target = temp;
+ self.message = string_null;
+ }
+
+ if (current.spawnflags & PATH_ROTATE_ANGLES)
+ {
+ self.rotate = '0 0 0';
+ self.angles = self.finalangle;
+ }
+
+ if (current.spawnflags & PATH_ROTATE_ROTATION)
+ {
+ self.rotate = current.rotate;
+ }
+
+ if (current.spawnflags & PATH_ROTATE_DAMAGE)
+ {
+ self.dmg = current.dmg;
+ }
+
+ if (current.spawnflags & PATH_ROTATE_SET_DAMAGE)
+ {
+ SetDamageOnTargets (current.dmg);
+ }
+
+ if (current.speed == -1)
+ {
+ // Warp to the next path_corner
+ setorigin (self, targ.origin);
+ self.endtime = self.ltime + 0.01;
+ SetTargetOrigin ();
+
+ if (targ.spawnflags & PATH_ROTATE_ANGLES)
+ {
+ self.angles = targ.angles;
+ }
+
+ self.duration = 1; // 1 / duration
+ self.cnt = time; // start time
+ self.dest2 = '0 0 0'; // delta
+ self.dest1 = self.origin; // original position
+ self.finaldest = self.origin;
+ }
+ else
+ {
+ self.state = STATE_MOVE;
+
+ self.finaldest = targ.origin;
+ if (self.finaldest == self.origin)
+ {
+ self.velocity = '0 0 0';
+ self.endtime = self.ltime + 0.1;
+
+ self.duration = 1; // 1 / duration
+ self.cnt = time; // start time
+ self.dest2 = '0 0 0'; // delta
+ self.dest1 = self.origin; // original position
+ self.finaldest = self.origin;
+ return;
+ }
+ // set destdelta to the vector needed to move
+ vdestdelta = self.finaldest - self.origin;
+
+ // calculate length of vector
+ len = vlen (vdestdelta);
+
+ if (current.spawnflags & PATH_ROTATE_MOVETIME)
+ {
+ traveltime = current.speed;
+ }
+ else
+ {
+ // check if there's a speed change
+ if (current.speed > 0)
+ self.speed = current.speed;
+
+ if (!self.speed)
+ objerror ("No speed is defined!");
+
+ // divide by speed to get time to reach dest
+ traveltime = len / self.speed;
+ }
+
+ if (traveltime < 0.1)
+ {
+ self.velocity = '0 0 0';
+ self.endtime = self.ltime + 0.1;
+ if (targ.spawnflags & PATH_ROTATE_ANGLES)
+ {
+ self.angles = targ.angles;
+ }
+ return;
+ }
+
+ // qcc won't take vec/float
+ div = 1 / traveltime;
+
+ if (targ.spawnflags & PATH_ROTATE_ANGLES)
+ {
+ self.finalangle = SUB_NormalizeAngles (targ.angles);
+ self.rotate = (targ.angles - self.angles) * div;
+ }
+
+ // set endtime to trigger a think when dest is reached
+ self.endtime = self.ltime + traveltime;
+
+ // scale the destdelta vector by the time spent
+ // traveling to get velocity
+ self.velocity = vdestdelta * div;
+
+ self.duration = div; // 1 / duration
+ self.cnt = time; // start time
+ self.dest2 = vdestdelta; // delta
+ self.dest1 = self.origin; // original position
+ }
+};
+
+//----------------------------------------------------------------------
+void() rotate_train_find =
+{
+ local entity targ;
+
+ self.state = STATE_FIND;
+
+ LinkRotateTargets ();
+
+ // the first target is the point of rotation.
+ // the second target is the path.
+ targ = find (world, targetname, self.path);
+ if (targ.classname != "path_rotate")
+ objerror ("Next target is not path_rotate");
+
+ // Save the current entity
+ self.goalentity = targ;
+
+ if (targ.spawnflags & PATH_ROTATE_ANGLES)
+ {
+ self.angles = targ.angles;
+ self.finalangle = SUB_NormalizeAngles (targ.angles);
+ }
+
+ self.path = targ.target;
+ setorigin (self, targ.origin);
+ SetTargetOrigin ();
+ RotateTargetsFinal ();
+ self.think1 = rotate_train_next;
+
+ if (!self.targetname)
+ {
+ // not triggered, so start immediately
+ self.endtime = self.ltime + 0.1;
+ }
+ else
+ {
+ self.endtime = 0;
+ }
+
+ self.duration = 1; // 1 / duration
+ self.cnt = time; // start time
+ self.dest2 = '0 0 0'; // delta
+ self.dest1 = self.origin; // original position
+};
+
+//----------------------------------------------------------------------
+void() rotate_train =
+{
+ objerror ("rotate_train entities should be changed to "
+ "rotate_object with\nfunc_rotate_train controllers\n");
+};
+
+/*QUAKED func_rotate_train (0 .5 .8) (-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
+
+In path_rotate, set speed to be the new speed of the train after it reaches
+the path change. If speed is -1, the train will warp directly to the next
+path change after the specified wait time. If MOVETIME is set on the
+path_rotate, the train to interprets "speed" as the length of time to
+take moving from one corner to another.
+
+"noise" contains the name of the sound to play when train stops.
+"noise1" contains the name of the sound to play when train moves.
+Both "noise" and "noise1" defaults depend upon "sounds" variable and
+can be overridden by the "noise" and "noise1" variable in path_rotate.
+
+Also in path_rotate, if STOP is set, the train will wait until it is
+retriggered before moving on to the next goal.
+
+Trains are moving platforms that players can ride.
+"path" specifies the first path_rotate and is the starting position.
+If the train is the target of a button or trigger, it will not begin moving until activated.
+The func_rotate_train entity is the center of rotation of all objects targeted by it.
+
+If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train.
+
+speed default 100
+dmg default 0
+sounds
+1) ratchet metal
+*/
+void() func_rotate_train =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.speed)
+ self.speed = 100;
+ if (!self.target)
+ objerror ("rotate_train without a target");
+
+ if (!self.noise)
+ {
+ if (self.sounds == 0)
+ {
+ self.noise = "misc/null.wav";
+ }
+
+ if (self.sounds == 1)
+ {
+ self.noise = "plats/train2.wav";
+ }
+ }
+
+ if (!self.noise1)
+ {
+ if (self.sounds == 0)
+ {
+ self.noise1 = "misc/null.wav";
+ }
+
+ if (self.sounds == 1)
+ {
+ self.noise1 = "plats/train1.wav";
+ }
+ }
+
+ precache_sound (self.noise);
+ precache_sound (self.noise1);
+
+ self.cnt = 1;
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_STEP;
+ self.use = rotate_train_use;
+
+ setmodel (self, self.model);
+ setsize (self, self.mins, self.maxs);
+ setorigin (self, self.origin);
+
+ // start trains on the second frame, to make sure their targets
+ // have had a chance to spawn
+ self.ltime = time;
+ self.nextthink = self.ltime + 0.1;
+ self.endtime = self.ltime + 0.1;
+ self.think = rotate_train_think;
+ self.think1 = rotate_train_find;
+ self.state = STATE_FIND;
+
+ self.duration = 1; // 1 / duration
+ self.cnt = 0.1; // start time
+ self.dest2 = '0 0 0'; // delta
+ self.dest1 = self.origin; // original position
+
+ self.flags = self.flags | FL_ONGROUND;
+};
+
+//======================================================================
+// Moving clip walls
+//======================================================================
+
+// prototypes
+void() rotate_door_reversedirection;
+void() rotate_door_group_reversedirection;
+
+//----------------------------------------------------------------------
+void() movewall_touch =
+{
+ if (time < self.owner.attack_finished)
+ return;
+
+ if (self.dmg)
+ {
+ T_Damage (other, self, self.owner, self.dmg);
+ self.owner.attack_finished = time + 0.5;
+ }
+ else if (self.owner.dmg)
+ {
+ T_Damage (other, self, self.owner, self.owner.dmg);
+ self.owner.attack_finished = time + 0.5;
+ }
+};
+
+//----------------------------------------------------------------------
+void() movewall_blocked =
+{
+ local entity temp;
+
+ if (time < self.owner.attack_finished)
+ return;
+
+ self.owner.attack_finished = time + 0.5;
+
+ if (self.owner.classname == "func_rotate_door")
+ {
+ temp = self;
+ self = self.owner;
+ rotate_door_group_reversedirection ();
+ self = temp;
+ }
+
+ if (self.dmg)
+ {
+ T_Damage (other, self, self.owner, self.dmg);
+ self.owner.attack_finished = time + 0.5;
+ }
+ else if (self.owner.dmg)
+ {
+ T_Damage (other, self, self.owner, self.owner.dmg);
+ self.owner.attack_finished = time + 0.5;
+ }
+};
+
+//----------------------------------------------------------------------
+void() movewall_think =
+{
+ self.ltime = time;
+ self.nextthink = time + 0.02;
+};
+
+/*QUAKED func_movewall (0 .5 .8) ? VISIBLE TOUCH NONBLOCKING 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
+
+Used to emulate collision on rotating objects.
+
+VISIBLE causes brush to be displayed.
+
+TOUCH specifies whether to cause damage when touched by player.
+
+NONBLOCKING makes the brush non-solid. This is useless if VISIBLE is set.
+
+"dmg" specifies the damage to cause when touched or blocked.
+*/
+void() func_movewall =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.angles = '0 0 0';
+ self.movetype = MOVETYPE_PUSH;
+
+ if (self.spawnflags & MOVEWALL_NONBLOCKING)
+ {
+ self.solid = SOLID_NOT;
+ }
+ else
+ {
+ self.solid = SOLID_BSP;
+ self.blocked = movewall_blocked;
+ }
+
+ if (self.spawnflags & MOVEWALL_TOUCH)
+ {
+ self.touch = movewall_touch;
+ }
+
+ setmodel (self,self.model);
+
+ if (!(self.spawnflags & MOVEWALL_VISIBLE))
+ {
+ self.model = string_null;
+ }
+
+ self.think = movewall_think;
+ self.nextthink = time + 0.02;
+ self.ltime = time;
+};
+
+/*QUAKED rotate_object (0 .5 .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 defines an object to be rotated. Used as the target of func_rotate_door.
+*/
+void() rotate_object =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.classname = "rotate_object";
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NONE;
+ setmodel (self,self.model);
+ setsize (self, self.mins, self.maxs);
+ self.think = SUB_Null;
+};
+
+//======================================================================
+// Rotating doors
+//======================================================================
+
+//----------------------------------------------------------------------
+void() rotate_door_think2 =
+{
+ local float t;
+
+ t = time - self.ltime;
+ self.ltime = time;
+
+ // change to alternate textures
+ self.frame = 1 - self.frame;
+
+ self.angles = self.dest;
+
+ if (self.state == STATE_OPENING)
+ {
+ self.state = STATE_OPEN;
+ }
+ else
+ {
+ if (self.spawnflags & ROTATE_DOOR_STAYOPEN)
+ {
+ rotate_door_group_reversedirection ();
+ return;
+ }
+ self.state = STATE_CLOSED;
+ }
+
+ sound (self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
+ self.think = SUB_Null;
+
+ RotateTargetsFinal ();
+};
+
+//----------------------------------------------------------------------
+void() rotate_door_think =
+{
+ local float t;
+
+ t = time - self.ltime;
+ self.ltime = time;
+
+ if (time < self.endtime)
+ {
+ self.angles = self.angles + (self.rotate * t);
+ RotateTargets ();
+ }
+ else
+ {
+ self.angles = self.dest;
+ RotateTargets ();
+ self.think = rotate_door_think2;
+ }
+
+ self.nextthink = time + 0.01;
+};
+
+//----------------------------------------------------------------------
+void() rotate_door_reversedirection =
+{
+ local vector start;
+
+ // change to alternate textures
+ self.frame = 1 - self.frame;
+
+ if (self.state == STATE_CLOSING)
+ {
+ start = self.dest1;
+ self.dest = self.dest2;
+ self.state = STATE_OPENING;
+ }
+ else
+ {
+ start = self.dest2;
+ self.dest = self.dest1;
+ self.state = STATE_CLOSING;
+ }
+
+ sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+
+ self.rotate = (self.dest - start) * (1 / self.speed);
+ self.think = rotate_door_think;
+ self.nextthink = time + 0.02;
+ self.endtime = time + self.speed - (self.endtime - time);
+ self.ltime = time;
+};
+
+//----------------------------------------------------------------------
+void() rotate_door_group_reversedirection =
+{
+ local string name;
+
+ // tell all associated rotaters to reverse direction
+ if (self.group != "")
+ {
+ name = self.group;
+ self = find (world, group, name);
+ while (self)
+ {
+ rotate_door_reversedirection ();
+ self = find (self, group, name);
+ }
+ }
+ else
+ {
+ rotate_door_reversedirection ();
+ }
+};
+
+//----------------------------------------------------------------------
+void() rotate_door_use =
+{
+ local vector start;
+
+ if ((self.state != STATE_OPEN) && (self.state != STATE_CLOSED))
+ return;
+
+ if (!self.cnt)
+ {
+ self.cnt = 1;
+ LinkRotateTargets ();
+ }
+
+ // change to alternate textures
+ self.frame = 1 - self.frame;
+
+ if (self.state == STATE_CLOSED)
+ {
+ start = self.dest1;
+ self.dest = self.dest2;
+ self.state = STATE_OPENING;
+ }
+ else
+ {
+ start = self.dest2;
+ self.dest = self.dest1;
+ self.state = STATE_CLOSING;
+ }
+
+ sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
+
+ self.rotate = (self.dest - start) * (1 / self.speed);
+ self.think = rotate_door_think;
+ self.nextthink = time + 0.01;
+ self.endtime = time + self.speed;
+ self.ltime = time;
+};
+
+/*QUAKED func_rotate_door (0 .5 .8) (-8 -8 -8) (8 8 8) STAYOPEN 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
+
+Creates a door that rotates between two positions around a point of
+rotation each time it's triggered.
+
+STAYOPEN tells the door to reopen after closing. This prevents a trigger-
+once door from closing again when it's blocked.
+
+"dmg" specifies the damage to cause when blocked. Defaults to 2. Negative numbers indicate no damage.
+"speed" specifies how the time it takes to rotate
+
+"sounds"
+1) medieval (default)
+2) metal
+3) base
+*/
+void() func_rotate_door =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.target)
+ {
+ objerror ("rotate_door without target.");
+ }
+
+ self.dest1 = '0 0 0';
+ self.dest2 = self.angles;
+ self.angles = self.dest1;
+
+ // default to 2 seconds
+ if (!self.speed)
+ {
+ self.speed = 2;
+ }
+
+ self.cnt = 0;
+
+ if (!self.dmg)
+ {
+ self.dmg = 2;
+ }
+ else if (self.dmg < 0)
+ {
+ self.dmg = 0;
+ }
+
+ if (self.sounds == 0)
+ {
+ // If at least one custom sound is defined, then let's
+ // ignore the presets and go for the custom sounds,
+ // otherwise let's use preset #1 by default
+ if (self.noise1=="" && self.noise2=="" && self.noise3=="")
+ {
+ self.sounds = 1;
+ }
+ else
+ {
+ if (self.noise1=="")
+ self.noise1 = "misc/null.wav";
+ if (self.noise2=="")
+ self.noise2 = "misc/null.wav";
+ if (self.noise3=="")
+ self.noise3 = "misc/null.wav";
+ }
+ }
+
+ if (self.sounds == 1)
+ {
+ self.noise1 = "doors/latch2.wav";
+ self.noise2 = "doors/winch2.wav";
+ self.noise3 = "doors/drclos4.wav";
+ }
+ else if (self.sounds == 2)
+ {
+ self.noise2 = "doors/airdoor1.wav";
+ self.noise1 = "doors/airdoor2.wav";
+ self.noise3 = self.noise1;
+ }
+ else if (self.sounds == 3)
+ {
+ self.noise2 = "doors/basesec1.wav";
+ self.noise1 = "doors/basesec2.wav";
+ self.noise3 = self.noise1;
+ }
+ else if (self.sounds == 4)
+ {
+ // added slinet option - sounds 4 -- dumptruck_ds
+ self.noise1 = self.noise2 = self.noise3 = "misc/null.wav";
+ }
+
+ precache_sound (self.noise1);
+ precache_sound (self.noise2);
+ precache_sound (self.noise3);
+
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NONE;
+ setmodel (self, self.model);
+ setorigin (self, self.origin);
+ setsize (self, self.mins, self.maxs);
+ self.state = STATE_CLOSED;
+ self.use = rotate_door_use;
+ self.think = SUB_Null;
+};

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

Diff qc/func/shadow.qc

diff --git a/qc/func/shadow.qc b/qc/func/shadow.qc
new file mode 100644
index 0000000..b4b6558
--- /dev/null
+++ b/qc/func/shadow.qc
@@ -0,0 +1,194 @@
+//==============================================================================
+// func_shadow -- An invisible bmodel that can be used to only cast shadows.
+//==============================================================================
+
+// constants
+const float SHADOWCONTROLLER_STARTOFF = 1;
+
+//----------------------------------------------------------------------
+void() shadow_fade_out =
+{
+ if (self.count < 0)
+ self.count = 0;
+ if (self.count > 12)
+ self.count = 12;
+
+ dprint (ftos(self.count));
+ dprint ("\n");
+
+ lightstyle (self.switchshadstyle, lightstyle_fade_lookup(self.count));
+ self.count = self.count + self.dmg;
+ if (self.count > 12)
+ return;
+
+ self.think = shadow_fade_out;
+ self.nextthink = time + self.delay;
+};
+
+//----------------------------------------------------------------------
+void() shadow_fade_in =
+{
+ if (self.count < 0)
+ self.count = 0;
+ if (self.count > 12)
+ self.count = 12;
+
+ dprint (ftos(self.count));
+ dprint ("\n");
+
+ lightstyle (self.switchshadstyle, lightstyle_fade_lookup(self.count));
+ self.count = self.count - self.dmg;
+ if (self.count < 0)
+ return;
+
+ self.think = shadow_fade_in;
+ self.nextthink = time + self.delay;
+};
+
+//----------------------------------------------------------------------
+void(float speed) misc_shadowcontroller_setsteps =
+{
+ // self.delay -> time between steps
+ // self.dmg -> step size
+ if (speed >= 0.24)
+ {
+ self.delay = (speed / 12);
+ self.dmg = 1;
+ }
+ else if (speed >= 0.12)
+ {
+ self.delay = (speed / 6);
+ self.dmg = 2;
+ }
+ else if (speed >= 0.06)
+ {
+ self.delay = (speed / 3);
+ self.dmg = 4;
+ }
+ else if (speed >= 0.04)
+ {
+ self.delay = (speed / 2);
+ self.dmg = 6;
+ }
+ else
+ {
+ self.delay = 0;
+ self.dmg = 12;
+ }
+};
+
+//----------------------------------------------------------------------
+void() misc_shadowcontroller_use =
+{
+ if (self.shadowoff)
+ {
+ dprint ("Fade in:\n");
+ misc_shadowcontroller_setsteps (self.speed);
+ shadow_fade_in ();
+ self.shadowoff = 0;
+ }
+ else
+ {
+ dprint ("Fade out:\n");
+ misc_shadowcontroller_setsteps (self.speed2);
+ shadow_fade_out ();
+ self.shadowoff = 1;
+ }
+};
+
+//----------------------------------------------------------------------
+// misc_shadowcontroller
+//
+// Controls switchable shadows on any bmodel entity (except doors).
+// Target entity must have set _switchableshadow set to 1.
+//
+// speed: Controls the time in seconds it takes to fade the shadow in.
+// Default is 0.5, and setting it to -1 disables fading.
+// speed2: Same as 'speed' but for the fade out animation. If unset it's
+// the same value as 'speed'.
+// spawnflag 1: target shadow starts as disabled
+//----------------------------------------------------------------------
+void() misc_shadowcontroller =
+{
+ entity t1;
+
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+
+ // doesn't search for a target if switchshadstyle is already set
+ // used for built-in shadow controllers
+ if (!self.switchshadstyle)
+ {
+ // we need to find only the first target entity with
+ // switchable shadows set, since shadow lightstyles
+ // are bound by targetname
+ t1 = find (world, targetname2, self.target);
+
+ while (t1 != world && !t1.switchshadstyle)
+ {
+ t1 = find (t1, targetname2, self.target);
+ }
+
+ if (t1 == world)
+ {
+ t1 = find (world, targetname, self.target);
+
+ while (t1 != world && !t1.switchshadstyle)
+ {
+ t1 = find (t1, targetname, self.target);
+ }
+ }
+
+ if (t1 == world)
+ {
+ dprint ("\b[misc_shadowcontroller]\b "
+ "_switchableshadow not set in target ");
+ dprint (self.target);
+ dprint ("\n");
+ return;
+ }
+
+ self.switchshadstyle = t1.switchshadstyle;
+ }
+
+ if (!self.speed)
+ self.speed = 0.5;
+ if (!self.speed2)
+ self.speed2 = self.speed;
+
+ if (self.spawnflags & SHADOWCONTROLLER_STARTOFF)
+ {
+ lightstyle (self.switchshadstyle, "m");
+
+ self.shadowoff = 1;
+ self.count = 12;
+
+ misc_shadowcontroller_setsteps (self.speed2);
+ }
+ else
+ {
+ lightstyle (self.switchshadstyle, "a");
+ self.shadowoff = 0;
+ self.count = 0;
+ misc_shadowcontroller_setsteps (self.speed);
+ }
+
+ self.use = misc_shadowcontroller_use;
+};
+
+//----------------------------------------------------------------------
+void() func_shadow =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.angles = '0 0 0';
+ self.movetype = MOVETYPE_NONE;
+ self.solid = SOLID_NOT;
+
+ self.modelindex = 0;
+ self.model = "";
+};

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

Diff qc/func/togglevisiblewall.qc

diff --git a/qc/func/togglevisiblewall.qc b/qc/func/togglevisiblewall.qc
new file mode 100644
index 0000000..6afd14f
--- /dev/null
+++ b/qc/func/togglevisiblewall.qc
@@ -0,0 +1,68 @@
+//==============================================================================
+// func_togglevisiblewall
+//
+// A bmodel which you can toggle its visibility. Behaves much like a
+// traditional func_wall in any other way, but you can target it to
+// toggle visible/invisible. If the entity has a switchable shadow it
+// also toggles.
+//
+// spawnflag 1: starts invisible
+// spawnflag 2: set brush as non-solid
+//==============================================================================
+
+// constants
+const float TOGGLEVISWALL_STARTOFF = 1;
+const float TOGGLEVISWALL_NOTSOLID = 2;
+
+//----------------------------------------------------------------------
+void() func_togglevisiblewall_use =
+{
+ if (!self.state)
+ {
+ if (!(self.spawnflags & TOGGLEVISWALL_NOTSOLID))
+ {
+ self.solid = SOLID_BSP;
+ self.movetype = MOVETYPE_PUSH;
+ }
+ setmodel (self, self.origmodel);
+ if (self.switchshadstyle)
+ lightstyle (self.switchshadstyle, "a");
+ self.state = 1;
+ }
+ else
+ {
+
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NONE;
+ setmodel (self, "");
+ if (self.switchshadstyle)
+ lightstyle (self.switchshadstyle, "m");
+ self.state = 0;
+ }
+};
+
+//----------------------------------------------------------------------
+void() func_togglevisiblewall =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.angles = '0 0 0';
+ self.use = func_togglevisiblewall_use;
+
+ self.origmodel = self.model;
+
+ if (self.spawnflags & TOGGLEVISWALL_STARTOFF)
+ self.state = 1;
+ else
+ self.state = 0;
+
+ if (self.spawnflags & TOGGLEVISWALL_NOTSOLID)
+ {
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NONE;
+ }
+
+ func_togglevisiblewall_use ();
+};

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

Diff qc/func/togglewall.qc

diff --git a/qc/func/togglewall.qc b/qc/func/togglewall.qc
new file mode 100644
index 0000000..d9a86de
--- /dev/null
+++ b/qc/func/togglewall.qc
@@ -0,0 +1,91 @@
+//==============================================================================
+// func_togglewall -- Hipnotic Interactive, Jim Dose'
+//==============================================================================
+
+// Particle effects QuickC program
+// By Jim Dose' 9/19/96
+// Copyright (c)1996 Hipnotic Interactive, Inc.
+// All rights reserved.
+// Distributed (unsupported) on 3.12.97
+
+//----------------------------------------------------------------------
+void() blocker_touch =
+{
+ if (!self.dmg)
+ return;
+
+ if (time < self.attack_finished)
+ return;
+ self.attack_finished = time + 0.5;
+ T_Damage (other, self, self, self.dmg);
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+};
+
+//----------------------------------------------------------------------
+void() blocker_use =
+{
+ if (!self.state)
+ {
+ self.state = 1;
+ setorigin (self, self.origin - '8000 8000 8000');
+ // sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ }
+ else
+ {
+ self.state = 0;
+ setorigin (self, self.origin + '8000 8000 8000');
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ }
+};
+
+/*QUAKED func_togglewall (0 .5 .8) ? START_OFF 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
+
+Creates a invisible wall that can be toggled on and off.
+
+START_OFF wall doesn't block until triggered.
+
+"noise" is the sound to play when wall is turned off.
+"noise1" is the sound to play when wall is blocking.
+"dmg" is the amount of damage to cause when touched.
+*/
+void() func_togglewall =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.classname = "togglewall";
+ self.movetype = MOVETYPE_PUSH;
+ self.mdl = self.model;
+ setmodel (self, self.model);
+ setsize (self, self.mins, self.maxs);
+ setorigin (self, self.origin);
+ self.touch = blocker_touch;
+ self.use = blocker_use;
+ if (!self.noise)
+ {
+ self.noise = "misc/null.wav";
+ }
+
+ if ( !self.noise1 )
+ {
+ self.noise1 = "misc/null.wav";
+ }
+
+ precache_sound (self.noise);
+ precache_sound (self.noise1);
+
+ self.solid = SOLID_BSP;
+ self.model = string_null;
+
+ if (self.spawnflags & START_OFF)
+ {
+ self.state = 0;
+ setorigin (self, self.origin + '8000 8000 8000');
+ }
+ else
+ {
+ self.state = 1;
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+ }
+};

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

Diff qc/func/train.qc

diff --git a/qc/func/train.qc b/qc/func/train.qc
new file mode 100644
index 0000000..a41bd5e
--- /dev/null
+++ b/qc/func/train.qc
@@ -0,0 +1,426 @@
+//==============================================================================
+// func_train
+//==============================================================================
+
+// constants
+const float TRAIN_RETRIGGER = 1;
+const float TRAIN_MOVEONTRIGGER = 2;
+const float TRAIN_STOPONTRIGGER = 4;
+const float TRAIN_NONSOLID = 8;
+const float TRAIN_NOROTATE = 16;
+const float TRAIN_ROTATEY = 32;
+const float TRAIN_CUSTOMALIGN = 64;
+
+const float TRAIN_NEXT_WAIT = 0; // normal movement
+const float TRAIN_NEXT_STOP = 1; // force a stop on the next path_corner
+const float TRAIN_NEXT_CONTINUE = 2; // force continue on the next
+ // path_corner (ignores wait time)
+const float TRAIN_STYLE_SINGLEANIM = 1;
+
+const float TRAIN_ANIMTYPE_FORWARD = 1;
+const float TRAIN_ANIMTYPE_BACKFORTH = 2;
+
+// prototypes
+void() train_next;
+void() func_train_find;
+
+//----------------------------------------------------------------------
+void() train_blocked =
+{
+ if (time < self.attack_finished)
+ return;
+
+ self.attack_finished = time + 0.5;
+ T_Damage (other, self, self, self.dmg);
+};
+
+//----------------------------------------------------------------------
+// Use function for when the train is stopped.
+// Makes the train continue on path_corners with wait -1,
+// or forces a continue if the "move on trigger" spawnflag is set.
+//----------------------------------------------------------------------
+void() train_use =
+{
+
+ if (self.spawnflags & TRAIN_MOVEONTRIGGER || self.wait < 0)
+ {
+ train_next ();
+ return;
+ }
+
+ // Train has already moved after startup, and has no
+ // "stop on trigger" flag, so ignore activation.
+ if (self.think != func_train_find && self.cnt != TRAIN_NEXT_STOP)
+ return;
+
+ train_next ();
+};
+
+//----------------------------------------------------------------------
+// Use function for when the train is moving.
+// Forces a stop or an instant continue on the next path_corner depending
+// on the spawnflag set
+//----------------------------------------------------------------------
+void() train_moving_use =
+{
+ if (self.spawnflags & TRAIN_MOVEONTRIGGER || self.wait < 0)
+ self.cnt = TRAIN_NEXT_CONTINUE;
+ else if (self.spawnflags & TRAIN_STOPONTRIGGER)
+ self.cnt = TRAIN_NEXT_STOP;
+};
+
+//----------------------------------------------------------------------
+// path_corner has been reached, so decide what to do next
+//----------------------------------------------------------------------
+void() train_wait =
+{
+ local float localtime;
+
+ if (self.movetype == MOVETYPE_PUSH)
+ localtime = self.ltime;
+ else
+ localtime = time;
+
+ // ready to be re-triggered
+ self.use = train_use;
+
+ // from Copper
+ // Trains now fire their path_corners' targets on arrival.
+ // If a player is riding the train, treat them as activator.
+ activator = nextent (world);
+
+ while (!EntitiesTouching(self,activator) &&
+ activator.classname == "player")
+ {
+ activator = nextent (activator);
+ }
+
+ if (activator.classname != "player")
+ // default to player1 wherever they are
+ activator = nextent (world);
+
+ SUB_UseEntTargets (self.enemy);
+
+ if (self.enemy.speed)
+ // sets the speed from the current path_corner
+ self.speed2 = self.enemy.speed;
+
+ // copies the modeltrain animation parameters set in the
+ // path_corner, if any
+ if (self.classname == "misc_modeltrain")
+ {
+ if (self.enemy.first_frame)
+ self.first_frame = self.enemy.first_frame;
+ if (self.enemy.last_frame)
+ self.last_frame = self.enemy.last_frame;
+ if (self.enemy.first_frame2)
+ self.first_frame2 = self.enemy.first_frame2;
+ if (self.enemy.last_frame2)
+ self.last_frame2 = self.enemy.last_frame2;
+ if (self.enemy.frtime)
+ self.frtime = self.enemy.frtime;
+ if (self.enemy.frtime2)
+ self.frtime2 = self.enemy.frtime2;
+ if (self.enemy.animtype)
+ self.animtype = self.enemy.animtype;
+ if (self.enemy.animtype2)
+ self.animtype2 = self.enemy.animtype2;
+ if (self.enemy.multiplier)
+ self.multiplier = self.enemy.multiplier;
+ }
+
+ self.think = train_next;
+
+ // train is moving normally and path_corner has a wait set,
+ // so pause for that time.
+ if (self.wait > 0 && self.cnt == TRAIN_NEXT_WAIT &&
+ !(self.spawnflags & TRAIN_RETRIGGER))
+ {
+ // state: stopped
+ self.state = 0;
+ if (self.classname == "misc_modeltrain")
+ SUB_CallAsSelf (self.animcontroller.think,
+ self.animcontroller);
+ self.nextthink = localtime + self.wait;
+
+ // play stopping sound. If path_corner has a custom
+ // sound, play that instead
+ if (self.enemy.noise != "")
+ sound (self, CHAN_WEAPON, self.enemy.noise,
+ 1, ATTN_NORM);
+ else
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ }
+ // train is moving normally and path_corner has no wait time,
+ // or has been forced to move instantly through a triggering.
+ else if (self.cnt != TRAIN_NEXT_STOP && !self.wait &&
+ !(self.spawnflags & TRAIN_RETRIGGER))
+ {
+
+ // play "passing by" sound, if any. If path_corner has
+ // a custom one, play that instead
+ if (self.enemy.noise2 != "")
+ sound (self, CHAN_WEAPON, self.enemy.noise2,
+ 1, ATTN_NORM);
+ else if (self.noise2 != "")
+ sound (self, CHAN_WEAPON, self.noise2, 1, ATTN_NORM);
+
+ // move instantly
+ self.nextthink = -1;
+ train_next ();
+ }
+ // path_corner has wait -1, or train has been forced to stop
+ // through a triggering. Also catches the backwards compatible
+ // case for the original rubicon2 "retrigger" flag.
+ else
+ {
+ // play stopping sound. If path_corner has a custom
+ // sound, play that instead
+ if (self.enemy.noise != "")
+ sound (self, CHAN_WEAPON, self.enemy.noise,
+ 1, ATTN_NORM);
+ else
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+
+ // state: stopped
+ self.state = 0;
+
+ if (self.classname == "misc_modeltrain")
+ SUB_CallAsSelf (self.animcontroller.think,
+ self.animcontroller);
+ self.nextthink = -1;
+ }
+};
+
+//----------------------------------------------------------------------
+// searches for the next path_corner and sends the train on its way
+//----------------------------------------------------------------------
+void() train_next =
+{
+ local entity targ;
+ vector destang, displ;
+
+ destang = displ = '0 0 0';
+
+ targ = find (world, targetname, self.target);
+
+ if (!targ || self.target == "")
+ objerror ("train_next: no next target");
+
+ self.target = targ.target;
+
+ // gets the wait time from the upcoming path_corner if set
+ if (targ.wait)
+ {
+ // wait -2 on the path_corner forces it to continue moving
+ // (no wait), even if the train has a default wait time
+ if (targ.wait == -2)
+ self.wait = 0;
+ else
+ self.wait = targ.wait;
+ }
+ // uses train's current wait time otherwise
+ else
+ {
+ self.wait = self.pausetime;
+ }
+
+ self.enemy = targ;
+
+ sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
+
+ if (!(!self.wait && self.cnt == TRAIN_NEXT_CONTINUE))
+ self.cnt = TRAIN_NEXT_WAIT;
+
+ // store up any premature triggerings until current
+ // movement is finished
+ self.use = train_moving_use;
+
+ if (self.classname == "misc_modeltrain")
+ {
+ if (!(self.spawnflags & TRAIN_NOROTATE))
+ {
+ destang = vectoangles (targ.origin - self.origin);
+ if (self.spawnflags & TRAIN_ROTATEY)
+ {
+ destang_x = self.angles_x;
+ destang_z = self.angles_z;
+ }
+ if (self.multiplier > 0)
+ SUB_CalcAngleMoveController (destang,
+ self.speed2 * self.multiplier,
+ SUB_Null, self.rotatecontroller);
+ else
+ self.angles = destang;
+ }
+ }
+
+ if (!self.state)
+ {
+ self.state = 1;
+ if (self.classname == "misc_modeltrain" &&
+ self.style != TRAIN_STYLE_SINGLEANIM)
+ {
+ SUB_CallAsSelf (self.animcontroller.think,
+ self.animcontroller);
+ }
+ }
+
+ // if the TRAIN_CUSTOMALIGN flag is checked then the train should
+ // align with its path_corners based on the location of an "origin"
+ // brush added to the train by the mapper instead of the mins corner
+ // -therektafire
+ local float doDisplace;
+ if (self.spawnflags & TRAIN_CUSTOMALIGN)
+ doDisplace = 0.0;
+ else
+ doDisplace = 1.0;
+
+ if (self.classname != "misc_modeltrain")
+ displ = self.mins;
+
+ SUB_CalcMove (targ.origin - (displ * doDisplace), self.speed2,
+ train_wait);
+};
+
+//----------------------------------------------------------------------
+// searches for the first path_corner after the train entity is initialized
+//----------------------------------------------------------------------
+void() func_train_find =
+{
+ local entity targ;
+ local float localtime;
+ local vector displ = '0 0 0';
+
+ if (self.movetype == MOVETYPE_PUSH)
+ localtime = self.ltime;
+ else
+ localtime = time;
+
+ targ = find (world, targetname, self.target);
+ self.target = targ.target;
+
+ local float doDisplace;
+ if (self.spawnflags & TRAIN_CUSTOMALIGN)
+ doDisplace = 0.0;
+ else
+ doDisplace = 1.0;
+
+ if (self.classname != "misc_modeltrain")
+ displ = self.mins;
+
+ self.enemy = targ;
+ setorigin (self, targ.origin - (displ * doDisplace));
+ if (targ.speed)
+ // uses speed from the 1st path corner if set
+ self.speed2 = targ.speed;
+
+ if (!self.targetname)
+ {
+ // not triggered, so start immediately
+ self.nextthink = localtime + 0.1;
+ self.think = train_next;
+ }
+};
+
+/*QUAKED func_train (0 .5 .8) ? RETRIGGER
+Trains are moving platforms that players can ride.
+The targets origin specifies the min point of the train at each corner.
+The train spawns at the first target it is pointing at.
+If the train is the target of a button or trigger, it will not begin moving until activated.
+
+RETRIGGER: stop at each path_corner and don't resume until triggered again (ignores wait time)
+
+speed default 100
+dmg default 2
+sounds
+1) ratchet metal
+2) base
+
+*/
+void() func_train =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.speed)
+ self.speed = 100;
+ if (!self.target)
+ objerror ("func_train without a target");
+ if (!self.dmg)
+ self.dmg = 2;
+
+ if(self.spawnflags & TRAIN_STOPONTRIGGER &&
+ self.spawnflags & TRAIN_MOVEONTRIGGER)
+ {
+ objerror ("func_train: Stop and move on trigger "
+ "set at the same time");
+ }
+
+ if (self.sounds == 1)
+ {
+ if (self.noise == "")
+ self.noise = "plats/train2.wav";
+ if (self.noise1 == "")
+ self.noise1 = "plats/train1.wav";
+ }
+ else if (self.sounds == 2)
+ {
+ // base door sound
+ if (self.noise == "")
+ self.noise = "doors/hydro2.wav";
+ if (self.noise1 == "")
+ self.noise1 = "doors/hydro1.wav";
+ }
+ else
+ {
+ if (self.noise == "")
+ self.noise = "misc/null.wav";
+ if (self.noise1 == "")
+ self.noise1 = "misc/null.wav";
+ }
+
+ // backwards compatibility with previous version
+ if (self.noise3 != "")
+ self.noise = self.noise3;
+ if (self.noise4 != "")
+ self.noise1 = self.noise4;
+
+ precache_sound (self.noise);
+ precache_sound (self.noise1);
+ if (self.noise2 != "")
+ precache_sound (self.noise2);
+
+ self.cnt = TRAIN_NEXT_WAIT;
+
+ if (self.spawnflags & TRAIN_NONSOLID)
+ {
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NOCLIP;
+ }
+ else
+ {
+ self.solid = SOLID_BSP;
+ self.movetype = MOVETYPE_PUSH;
+ }
+
+ self.blocked = train_blocked;
+ self.use = train_use;
+ // self.classname = "train";
+
+ setmodel (self, self.model);
+ setsize (self, self.mins , self.maxs);
+ setorigin (self, self.origin);
+
+ // start trains on the second frame, to make sure their targets
+ // have had a chance to spawn
+
+ if (self.movetype == MOVETYPE_PUSH)
+ self.nextthink = self.ltime + 0.1;
+ else
+ self.nextthink = time + 0.1;
+
+ self.think = func_train_find;
+ self.speed2 = self.speed;
+};

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

Diff qc/func/wall.qc

diff --git a/qc/func/wall.qc b/qc/func/wall.qc
new file mode 100644
index 0000000..7e7b251
--- /dev/null
+++ b/qc/func/wall.qc
@@ -0,0 +1,27 @@
+//==============================================================================
+// func_wall
+//==============================================================================
+
+//----------------------------------------------------------------------
+void() func_wall_use =
+{
+ // change to alternate textures
+ self.frame = 1 - self.frame;
+};
+
+/*QUAKED func_wall (0 .5 .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 is just a solid wall if not inhibitted
+*/
+void() func_wall =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ self.angles = '0 0 0';
+ // so it doesn't get pushed by anything
+ self.movetype = MOVETYPE_PUSH;
+ self.solid = SOLID_BSP;
+ self.use = func_wall_use;
+ setmodel (self, self.model);
+};

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

Diff qc/func_bob.qc

diff --git a/qc/func_bob.qc b/qc/func_bob.qc
deleted file mode 100644
index 494cce3..0000000
--- a/qc/func_bob.qc
+++ /dev/null
@@ -1,198 +0,0 @@
-.float attack_timer;
-.float bsporigin; // All bmodel origins are 0,0,0 check this first
-.float distance;
-.float waitmin2;
-
-float BOB_COLLISION = 2; // Collision for misc_bob
-float BOB_NONSOLID = 4; // Non solid for func_bob
-
-/*QUAKED func_bob (0 .5 .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
-A SOLID bmodel that gently moves back and forth
--------- KEYS --------
-targetname : trigger entity (works with entity state system)
-angle : direction movement, use "360" for angle 0
-height : direction intensity (def=8)
-count : direction cycle timer (def=2s, minimum=1s)
-waitmin : Speed up scale (def=1) 1+=non linear
-waitmin2 : Slow down scale (def=0.75)
-delay : Starting time delay (def=0, -1=random)
-style : If set to 1, starts off and waits for trigger
-_dirt : -1 = will be excluded from dirtmapping
-_minlight : Minimum light level for any surface of the brush model
-_mincolor : Minimum light color for any surface (def='1 1 1' RGB)
-_shadow : Will cast shadows on other models and itself
-_shadowself : Will cast shadows on itself
--------- SPAWNFLAGS --------
-STARTOFF : Starts off and waits for trigger - DISABLED, Ripped out ESTATE System (RennyC)
--------- NOTES --------
-A SOLID bmodel that gently moves back and forth
-*/
-
-//----------------------------------------------------------------------
-void() func_bob_timer =
-{
- // Keep ticking in background, use local timer (faster)
- self.think = func_bob_timer;
-
- if (self.bsporigin)
- self.nextthink = self.ltime + 0.1;
- else
- self.nextthink = time + 0.1;
-
- // Has the cycle completed?
- if (self.attack_timer < time)
- {
- // Setup bob cycle and half way point for slowdown
- self.attack_timer = time + self.count;
- self.distance = time + (self.count * 0.5);
- // Flip direction of bmodel bob
- self.lefty = 1 - self.lefty;
- if (self.lefty < 1)
- self.t_length = self.height;
- else
- self.t_length = -self.height;
-
- // Always reset velocity and flags
- self.velocity = '0 0 0';
- self.flags = 0;
- }
-
- // Is the direction set?
- // This is a block condition to prevent the bmodel moving
- if (self.lefty != -1)
- {
- // Slow down velocity (gradually)
- if (self.distance < time)
- self.velocity = self.velocity * self.waitmin2;
- else
- {
- // Speed up velocity (linear/exponentially)
- self.t_length = self.t_length * self.waitmin;
- self.velocity = self.velocity + (self.movedir * self.t_length);
- }
- }
-};
-
-//----------------------------------------------------------------------
-void() func_bob_on =
-{
- // This may have been called as a "use" function, so don't allow it
- // to be called repeatedly -- iw
- self.use = SUB_Null;
-
- if (self.bsporigin)
- {
- self.movetype = MOVETYPE_PUSH;
- self.solid = SOLID_BSP;
- }
- else
- {
- self.movetype = MOVETYPE_FLY;
- self.solid = SOLID_BBOX;
- self.flags = 0; // Reset any onground flags
- }
-
- if (self.spawnflags & BOB_NONSOLID)
- self.solid = SOLID_NOT;
-
- setmodel (self, self.mdl);
- setsize (self, self.mins , self.maxs);
-
- self.think = func_bob_timer;
- if (self.bsporigin)
- self.nextthink = self.ltime + 0.1 + self.delay;
- else
- self.nextthink = time + 0.1 + self.delay;
-};
-
-//----------------------------------------------------------------------
-void() func_bob_off =
-{
- if (self.bsporigin)
- {
- self.movetype = MOVETYPE_PUSH;
- self.solid = SOLID_BSP;
- }
- else
- {
- self.movetype = MOVETYPE_FLY;
- self.solid = SOLID_BBOX;
- }
-
- if (self.spawnflags & BOB_NONSOLID)
- self.solid = SOLID_NOT;
-
- setmodel (self, self.mdl);
- setsize (self, self.mins , self.maxs);
- self.velocity = '0 0 0';
-
- if (self.style & 1)
- self.use = func_bob_on;
-};
-
-//----------------------------------------------------------------------
-void() func_bob =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.spawnflags = self.spawnflags | BOB_COLLISION;
- if (self.spawnflags & BOB_NONSOLID)
- self.spawnflags = self.spawnflags - (self.spawnflags & BOB_COLLISION);
-
- // Using a custom model?
- if (self.mdl == "")
- {
- self.bsporigin = TRUE;
- self.mdl = self.model;
- }
- else
- {
- self.bsporigin = FALSE;
- self.modelindex = 0;
- self.model = "";
- }
-
- SetMovedir ();
- self.movedir = normalize(self.movedir);
-
- if (self.height <= 0)
- self.height = 8; // Direction intensity
- if (self.count < 1)
- self.count = 2; // Direction switch timer
- if (self.waitmin <= 0)
- self.waitmin = 1; // Speed up
- if (self.waitmin2 <= 0)
- self.waitmin2 = 0.75; // Slow down
- if (self.delay < 0)
- self.delay = random() + random() + random();
-
- // Setup Entity State functionality - Nope! (RennyC)
- // if (self.targetname != "")
- // self.use = func_bob_on;
-
- if (!self.style) //added style key 1 for start off -- dumptruck_ds
- func_bob_on();
- else
- func_bob_off();
-};
-
-//----------------------------------------------------------------------
-
-/*QUAKED misc_bob (0 0.5 0.8) (-8 -8 -8) (8 8 8) X BOB_COLLISION BOB_NONSOLID 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
-{
- model ({"path" : mdl, "skin" : skin, "frame": frame});
-}
-Same as func_bob but uses a custom model instead of a brush. Use the mdl key to set the path of the model.
-*/
-void() misc_bob =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (self.mdl == "")
- self.mdl = string_null;
- precache_model(self.mdl);
-
- func_bob();
-};

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

Diff qc/func_brush.qc

diff --git a/qc/func_brush.qc b/qc/func_brush.qc
deleted file mode 100644
index e5f6aaf..0000000
--- a/qc/func_brush.qc
+++ /dev/null
@@ -1,80 +0,0 @@
-//this is on hold and not in progs.src
-// crashes in QS at the moment Jaycie is looking into it
-.float solidstate;
-.float visiblestate;
-
-float START_INVISIBLE = 1;
-float START_NONSOLID = 2;
-float START_ALTFRAMES = 4;
-float TOGGLE_VISIBILITY = 8;
-float TOGGLE_SOLIDITY = 16;
-float TOGGLE_FRAMES = 32;
-
-void() func_brush_use =
-{
- if (self.spawnflags & TOGGLE_VISIBILITY)
- {
- if (self.visiblestate == 1)
- {
- self.model = "";
- self.visiblestate = 0;
- }
- else
- {
- self.model = self.mdl;
- self.visiblestate = 1;
- }
- }
- if (self.spawnflags & TOGGLE_SOLIDITY)
- {
- if (self.solidstate == 1)
- {
- self.solid = SOLID_NOT;
- self.solidstate = 0;
- }
- else
- {
- self.solid = SOLID_BSP;
- setorigin(self, self.origin);
- self.solidstate = 1;
- }
- }
- if (self.spawnflags & TOGGLE_FRAMES)
- self.frame = 1 - self.frame;
-};
-
-void() func_brush =
-{
- self.angles = '0 0 0';
- self.movetype = MOVETYPE_NONE;
- self.use = func_brush_use;
- setmodel(self, self.model);
- self.mdl = self.model;
- setorigin(self, self.origin);
-
- if (self.spawnflags & START_INVISIBLE)
- {
- self.visiblestate = 0;
- self.model = "";
- }
- else
- {
- self.visiblestate = 1;
- }
-
- if (self.spawnflags & START_NONSOLID)
- {
- self.solidstate = 0;
- self.solid = SOLID_NOT;
- }
- else
- {
- self.solidstate = 1;
- self.solid = SOLID_BSP;
- }
-
- if (self.spawnflags & START_ALTFRAMES)
- self.frame = 1;
- else
- self.frame = 0;
-};

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

Diff qc/func_fall2.qc

diff --git a/qc/func_fall2.qc b/qc/func_fall2.qc
deleted file mode 100644
index 000f95d..0000000
--- a/qc/func_fall2.qc
+++ /dev/null
@@ -1,281 +0,0 @@
-.float alpha; // translucency in supported engines
-.entity char; // linker entity
-float PLAYER_TRIGGERED = 1;
-float MONSTER_TRIGGERED = 2;
-float FALL_BREAKABLE = 8; //VR
-// float FALL_SOLID = 16; //VR
-
-void() fall_break_fields;
-
-void() func_fall2_think =
-{
- self.waterlevel = self.watertype = 0; // turn off quake engine splash sound
-
- if (self.attack_finished < time)
- {
- if (self.target != __NULL__ && self.target != "")
- // fire other targets
- SUB_UseAndForgetTargets();
- // SUB_UseTargets();
-
- self.solid = SOLID_NOT; // removed FALL_SOLID behavior -- dumptruck_ds
- if (self.pos1 != '0 0 0')
- self.avelocity = self.pos1; // apply stored avelocity vector values
-
- if (self.pos2 && !self.velocity) // Add velocity movement
- self.velocity = self.pos2;
-
- if (self.cnt > 0) // cnt over 0
- {
- if (self.cnt >= 2)
- {
- self.movetype = MOVETYPE_BOUNCE;
- if (self.velocity_z < self.lip)
- self.velocity_z = self.lip;
- }
- else // cnt is 1
- {
- self.movetype = MOVETYPE_NOCLIP;
- if (self.velocity_z > self.lip)
- self.velocity_z = self.velocity_z - self.speed * (frametime * 100);
- else
- self.velocity_z = self.lip;
- }
- }
- else // default behavior (cnt is 0)
- {
- self.movetype = MOVETYPE_TOSS;
- if (self.velocity_z < self.lip)
- self.velocity_z = self.lip;
- }
-
- if (self.pain_finished != -1)
- {
- if (self.alpha > 0.1)
- self.alpha = self.alpha - self.pain_finished;
- else
- {
- if (self.noise2 != __NULL__ &&self.noise2 != "")
- sound (self, CHAN_AUTO, self.noise2, 1, ATTN_NORM);
- remove(self);
- return;
- }
- }
-
- if (self.flags&FL_ONGROUND && self.spawnflags&FALL_BREAKABLE) { //VR
- self.spawnflags(-)1; //aka BREAKABLE_NO_MONSTERS
- self.spawnflags(-)2; //aka BREAK_EXPLODE
- self.mins = self.absmin; //because of how debris origin is calculated
- self.maxs = self.absmax;
- self.health = self.lip*0.1; //debris gets velocity from health
- self.cnt = self.count; //func_breakable uses cnt for quantity of debris to spawn
- func_breakable_die(); //removes self
- return;
- }
- }
-
- self.nextthink = self.ltime + 0.1;
-};
-
-void() fall2_touch =
-{
- if (!other.takedamage)
- return;
- if (other.classname != "player") // player activated only
- return;
- if (self.spawnflags & MONSTER_TRIGGERED) // disable on monster only, also fixes weird issue
- return;
-
- self.think = func_fall2_think;
- self.nextthink = self.ltime + 0.1;
-
- self.attack_finished = time + self.wait;
-
- // if (self.spawnflags&FALL_SOLID) { //VR
- // setsize(self, self.mins, self.maxs);
- // self.solid = SOLID_BBOX;
- // }
- // else
- // self.solid = SOLID_NOT;
-
- if (self.noise != __NULL__ && self.noise != "")
- sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
-
- self.touch = SUB_Null; // disable touch, only do this once!
-
- if (self.char)
- remove(self.char);
-};
-
-void() func_fall2_use =
-{
- self.think = func_fall2_think;
- self.nextthink = self.ltime + 0.1;
- self.touch = SUB_Null; // disable touch when used
-
- // if (self.spawnflags&FALL_SOLID) { //VR
- // setsize(self, self.mins, self.maxs);
- // self.solid = SOLID_BBOX;
- // }
- // else
- // self.solid = SOLID_NOT;
-
- self.attack_finished = time + self.wait;
- if (self.noise != __NULL__ && self.noise != "")
- sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
-};
-
-void() func_fall2_field_touch =
-{
- if (other.flags & FL_FLY) // flying monsters shouldn't trigger falling platforms
- return;
-
- if (other.flags & FL_MONSTER)
- {
- local entity oself;
-
- oself = self;
-
- self = self.owner;
- self.think = func_fall2_use;
- self.nextthink = self.owner.ltime + 0.1;
-
- self = oself;
-
- remove(self);
- }
-};
-
-/*QUAKED func_fall2 (0 .5 .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
-Falling brush by RennyC with additions from whirledtsar
-
-wait - how long until the brush begins falling
-noise - the sound to make when touched / activated
-noise2 - the sound to make before it's removed, pain_finished of -1 disables noise2 as the object stays forever
-cnt - 0 is default behavior (MOVETYPE_TOSS), 1 means collisions are disabled while falling (MOVETYPE_NOCLIP), 2 turns the brush into a bouncing entity (MOVETYPE_BOUNCE)
-pain_finished - default of 0.01, higher value has the object/brush fade out faster thus in turn affecting how long it stays. -1 stays forever
-speed - speed as to how fast something falls per game frame, default is 10, higher values mean faster falling. Only for cnt of 1 (MOVETYPE_NOCLIP).
-Recommended to use lip for max fall speed on MOVETYPE_TOSS/BOUNCE entities (cnt 0 and 2) as they follow Quake's default gravity
-lip - maximum fall speed that can be achieved, caps 'speed' variable. Default is -800
-avelocity - have it spin when activated using X, Y, Z vector coordinates. MOVETYPE_BOUNCE ignores avelocity !Use an origin brush for proper spin!
-
-spawnflags:
-Default behavior allows anyone to activate func_fall2 on touch ONLY
-1 - Player activated only
-2 - Monster activated only
-8 - break on impact (use style key for textures, see manual for more)
-16 - fall solid; remains solid on ground
-
-Able to .target other entities, including other func_fall2s
-*/
-
-void() func_fall2 =
-{
- //
- // This is a hack to have monsters be able to trigger it by fake touch - Thanks to Nahuel
- //
-
- // Don't spawn on player only or if I'm a targetable
- if (!(self.spawnflags & PLAYER_TRIGGERED) && !(self.targetname))
- {
- local entity func_fall2_field;
-
- func_fall2_field = spawn();
- func_fall2_field.owner = self;
- self.char = func_fall2_field; // Link 'em
- func_fall2_field.solid = SOLID_TRIGGER;
- setsize (func_fall2_field, self.absmin, self.absmax + '0 0 8');
- setorigin (func_fall2_field, self.origin);
- setmodel (func_fall2_field, self.model);
- func_fall2_field.touch = func_fall2_field_touch;
- }
-
- if (self.noise != __NULL__ && self.noise != "")
- precache_sound(self.noise);
- if (self.noise2 != __NULL__ && self.noise2 != "")
- precache_sound(self.noise2);
-
- self.alpha = 1;
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
-
- if (!self.pain_finished)
- self.pain_finished = 0.01;
- if (!self.targetname)
- self.touch = fall2_touch; // .touch in this instance is for players only
- if (!self.speed)
- self.speed = 10;
- if (!self.lip)
- self.lip = -800;
- if (self.avelocity != '0 0 0')
- {
- self.pos1 = self.avelocity; // store it
- self.avelocity = '0 0 0';
- }
- if (self.spawnflags&FALL_BREAKABLE) { //VR
- self.pain_finished = -1; //dont fade if set to break
- fall_break_fields();
- }
- self.use = func_fall2_use;
-
- setmodel (self, self.model);
-};
-
-// * You may have to modify your multi_touch(); command in triggers.qc to allow
-// * both monsters & players to activate trigger_once/multiple. I recommend allowing
-// * the mapper themselves to select how that occurs. Default behavior is player only.
-
-void fall_break_fields ()
-{
- break_template_setup();
-
- self.mdl_debris = "progs/debris.mdl";
- precache_model (self.mdl_debris);
-
- if (self.noise1 != "") precache_sound(self.noise1);
-// adding new default sounds for "simple" breakables in 1.2.0 -- dumptruck_ds
-// here's genreic metal breaking
- if (self.style == 0 || self.style == 11 || self.style == 12 || self.style == 17 || self.style == 18 || self.style == 19
- || self.style == 24 || self.style == 31)
- if !(self.noise1)
- {
- precache_sound("break/metal2.wav");
- self.noise1 = "break/metal2.wav";
- }
- if (self.style == 3 || self.style == 4 || self.style == 5)
- if !(self.noise1)
- {
- precache_sound("break/wood1.wav");
- precache_sound("break/wood2.wav");
- if (random() > 0.6) // wood only randomized
- self.noise1 = "break/wood1.wav";
- else
- self.noise1 = "break/wood2.wav";
- }
- // glass sounds -- this is more of a shattering sound anyway
- if (self.style == 6 || self.style == 7 || self.style == 8 || self.style == 9 || self.style == 10)
- if !(self.noise1)
- {
- precache_sound("break/metal1.wav");
- self.noise1 = "break/metal1.wav";
- }
- if (self.style == 1 || self.style == 2 || self.style == 13 || self.style == 14
- || self.style == 15 || self.style == 16 || self.style == 20 || self.style == 21
- || self.style == 22 || self.style == 23)
- if !(self.noise1)
- {
- precache_sound("break/bricks1.wav");
- self.noise1 = "break/bricks1.wav";
- }
- if (self.style == 25 || self.style == 26 || self.style == 27 || self.style == 28 || self.style == 29 || self.style == 30)
- if !(self.noise1)
- {
- precache_sound("break/stones1.wav");
- self.noise1 = "break/stones1.wav";
- }
-
- if (!self.health)
- self.health = 20;
- if (!self.count)
- self.count = 5; // was 6 dumptruck_ds
-}

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

Diff qc/hip_count.qc

diff --git a/qc/hip_count.qc b/qc/hip_count.qc
deleted file mode 100644
index 0b91e46..0000000
--- a/qc/hip_count.qc
+++ /dev/null
@@ -1,219 +0,0 @@
-/* Counter QuickC program
- By Jim Dose' 9/13/96
- Copyright (c)1996 Hipnotic Interactive, Inc.
- All rights reserved.
- Do not distribute.
-*/
-
-float COUNTER_TOGGLE = 1;
-float COUNTER_LOOP = 2;
-float COUNTER_STEP = 4;
-float COUNTER_RESET = 8;
-float COUNTER_RANDOM = 16;
-float COUNTER_FINISHCOUNT = 32;
-float COUNTER_START_ON = 64;
-
-void() counter_on_use;
-void() counter_off_use;
-
-void() counter_think =
- {
- self.cnt = self.cnt + 1;
- if ( self.spawnflags & COUNTER_RANDOM )
- {
- self.state = random() * self.count;
- self.state = floor( self.state ) + 1;
- }
- else
- {
- self.state = self.cnt;
- }
-
- // fix func_counter and func_oncount handling of activator -- iw
- //activator = other;
- activator = self.enemy;
- SUB_UseTargets();
- self.nextthink = time + self.wait;
-
- if ( self.spawnflags & COUNTER_STEP )
- {
- counter_on_use();
- }
-
- if ( self.cnt >= self.count )
- {
- self.cnt = 0;
- if ( ( self.aflag ) || !( self.spawnflags & COUNTER_LOOP ) )
- {
- if (self.spawnflags & COUNTER_TOGGLE)
- {
- counter_on_use();
- }
- else
- {
- remove (self);
- }
- }
- }
- };
-
-// fix func_counter and func_oncount handling of activator -- iw
-void() counter_start_on_think =
- {
- activator = world; // to ensure it's not a random entity -- iw
- counter_off_use();
- };
-
-void() counter_on_use =
- {
- if ( ( self.cnt != 0 ) && ( self.spawnflags & COUNTER_FINISHCOUNT ) )
- {
- self.aflag = TRUE;
- return;
- }
-
- self.use = counter_off_use;
- self.think = SUB_Null;
- self.aflag = FALSE;
- };
-
-void() counter_off_use =
- {
- self.aflag = FALSE;
- if (self.spawnflags & COUNTER_TOGGLE)
- {
- self.use = counter_on_use;
- }
- else
- {
- self.use = SUB_Null;
- }
-
- if ( self.spawnflags & COUNTER_RESET )
- {
- self.cnt = 0;
- self.state = 0;
- }
- // fix func_counter and func_oncount handling of activator -- iw
- self.enemy = activator;
- self.think = counter_think;
- // fix "delay" making func_counter not work -- iw
- //if (self.delay)
- if (self.pausetime)
- {
- // fix "delay" making func_counter not work -- iw
- //self.nextthink = time + self.delay;
- self.nextthink = time + self.pausetime;
- }
- else
- {
- counter_think();
- }
- };
-
-float( entity counter ) counter_GetCount =
- {
- if ( counter.classname == "counter" )
- {
- return counter.state;
- }
- return 0;
- };
-
-/*QUAKED func_counter (0 0 0.5) (0 0 0) (32 32 32) TOGGLE LOOP STEP RESET RANDOM FINISHCOUNT START_ON 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
-TOGGLE causes the counter to switch between an on and off state
-each time the counter is triggered.
-
-LOOP causes the counter to repeat infinitly. The count resets to zero
-after reaching the value in "count".
-
-STEP causes the counter to only increment when triggered. Effectively,
-this turns the counter into a relay with counting abilities.
-
-RESET causes the counter to reset to 0 when restarted.
-
-RANDOM causes the counter to generate random values in the range 1 to "count"
-at the specified interval.
-
-FINISHCOUNT causes the counter to continue counting until it reaches "count"
-before shutting down even after being set to an off state.
-
-START_ON causes the counter to be on when the level starts.
-
-"count" specifies how many times to repeat the event. If LOOP is set,
-it specifies how high to count before reseting to zero. Default is 10.
-
-"wait" the length of time between each trigger event. Default is 1 second.
-
-"delay" how much time to wait before firing after being switched on.
-*/
-
-void() func_counter =
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if ( !self.wait )
- {
- self.wait = 1;
- }
-
- self.count = floor( self.count );
- if ( self.count <= 0 )
- {
- self.count = 10;
- }
-
- // fix "delay" making func_counter not work -- iw
- self.pausetime = self.delay;
- self.delay = 0;
-
- self.cnt = 0;
- self.state = 0;
-
- self.classname = "counter";
- self.use = counter_off_use;
- self.think = SUB_Null;
- if ( self.spawnflags & COUNTER_START_ON )
- {
- // fix func_counter and func_oncount handling of activator -- iw
- //self.think = counter_off_use;
- self.think = counter_start_on_think;
- self.nextthink = time + 0.1;
- }
- };
-
-void() oncount_use =
- {
- if ( counter_GetCount( other ) == self.count )
- {
- // fix func_counter and func_oncount handling of activator -- iw
- //activator = other;
- SUB_UseTargets();
- }
- };
-
-/*QUAKED func_oncount (0 0 0.5) (0 0 0) (16 16 16)
-Must be used as the target for func_counter. When the counter
-reaches the value set by count, func_oncount triggers its targets.
-
-"count" specifies the value to trigger on. Default is 1.
-
-"delay" how much time to wait before firing after being triggered.
-*/
-
-void() func_oncount =
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.count = floor( self.count );
- if ( self.count <= 0 )
- {
- self.count = 1;
- }
-
- self.classname = "oncount";
- self.use = oncount_use;
- self.think = SUB_Null;
- };

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

Diff qc/hip_part.qc

diff --git a/qc/hip_part.qc b/qc/hip_part.qc
deleted file mode 100644
index e759742..0000000
--- a/qc/hip_part.qc
+++ /dev/null
@@ -1,316 +0,0 @@
-/* Particle effects QuickC program
- By Jim Dose' 9/19/96
- Copyright (c)1996 Hipnotic Interactive, Inc.
- All rights reserved.
- Do not distribute.
-*/
-
-//float START_OFF = 1;
-float USE_COUNT = 1;
-
-void () particlefield_XZ =
- {
- local vector pos;
- local vector start;
- local vector end;
-
- if ( ( self.spawnflags & USE_COUNT ) &&
- ( counter_GetCount( other ) != self.cnt ) )
- {
- return;
- }
-// dprint( "XZ\n" );
-
- self.ltime = time + 0.25;
- if ( self.noise != "" )
- {
- sound(self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- }
-
- // Only show particles if client is visible.
- // This helps to keep network traffic down to a minimum.
- if (!checkclient() )
- return;
-
- start = self.dest1 + self.origin;
- end = self.dest2 + self.origin;
- pos_y = start_y;
- pos_z = start_z;
- while( pos_z <= end_z )
- {
- pos_x = start_x;
- while( pos_x <= end_x )
- {
- particle ( pos, '0 0 0', self.color, self.count );
- pos_x = pos_x + 16;
- }
- pos_z = pos_z + 16;
- }
- };
-
-void () particlefield_YZ =
- {
- local vector pos;
- local vector start;
- local vector end;
-
- if ( ( self.spawnflags & USE_COUNT ) &&
- ( counter_GetCount( other ) != self.cnt ) )
- {
- return;
- }
-
-// dprint( "YZ: " );
-// dprint( vtos( self.dest1 ) );
-// dprint( " - " );
-// dprint( vtos( self.dest2 ) );
-// dprint( "\n" );
- self.ltime = time + 0.25;
- if ( self.noise != "" )
- {
- sound(self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- }
-
- // Only show particles if client is visible.
- // This helps to keep network traffic down to a minimum.
- if (!checkclient() )
- return;
-
- start = self.dest1 + self.origin;
- end = self.dest2 + self.origin;
- pos_x = start_x;
- pos_z = start_z;
- while( pos_z < end_z )
- {
- pos_y = start_y;
- while( pos_y < end_y )
- {
- particle ( pos, '0 0 0', self.color, self.count );
- pos_y = pos_y + 16;
- }
- pos_z = pos_z + 16;
- }
- };
-
-void () particlefield_XY =
- {
- local vector pos;
- local vector start;
- local vector end;
-
- if ( ( self.spawnflags & USE_COUNT ) &&
- ( counter_GetCount( other ) != self.cnt ) )
- {
- return;
- }
-
-// dprint( "XY\n" );
- self.ltime = time + 0.25;
- if ( self.noise != "" )
- {
- sound(self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- }
-
- // Only show particles if client is visible.
- // This helps to keep network traffic down to a minimum.
- if (!checkclient() )
- return;
-
-
- start = self.dest1 + self.origin;
- end = self.dest2 + self.origin;
- pos_x = start_x;
- pos_z = start_z;
- while( pos_x < end_x )
- {
- pos_y = start_y;
- while( pos_y < end_y )
- {
- particle ( pos, '0 0 0', self.color, self.count );
- pos_y = pos_y + 16;
- }
- pos_x = pos_x + 16;
- }
- };
-
-void () particlefield_touch =
- {
- if ( !self.dmg )
- return;
-
- if ( time > self.ltime)
- return;
-
- if (time < self.attack_finished)
- return;
- self.attack_finished = time + 0.5;
- T_Damage (other, self, self, self.dmg);
- };
-
-/*QUAKED func_particlefield (0 .5 .8) ? USE_COUNT 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
-
-Creates a brief particle flash roughly the size of the defining
-brush each time it is triggered.
-
-USE_COUNT when the activator is a func_counter, the field will only
-activate when count is equal to "cnt". Same as using a func_oncount
-to trigger.
-
-"cnt" is the count to activate on when USE_COUNT is set.
-"color" is the color of the particles. Default is 192 (yellow).
-"count" is the density of the particles. Default is 2.
-"noise" is the sound to play when triggered. Do not use a looping sound here.
-"dmg" is the amount of damage to cause when touched.
-*/
-
-void() func_particlefield =
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if ( !self.color )
- {
- self.color = 192;
- }
- if ( self.count == 0 )
- {
- self.count = 2;
- }
- self.classname = "particlefield";
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_NONE;
- setmodel (self, self.model);
- self.model = string_null;
-
- self.origin = ( self.mins + self.maxs ) * 0.5;
- setorigin (self, self.origin);
- self.dest = self.maxs - self.mins - '16 16 16';
- self.dest1 = self.mins + '8 8 8' - self.origin;
- self.dest2 = self.maxs + '7.9 7.9 7.9' - self.origin;
- setsize (self, self.mins, self.maxs);
- self.touch = particlefield_touch;
-// dprint( vtos( self.dest ) );
-// dprint( " " );
- if ( self.dest_x > self.dest_z )
- {
- if ( self.dest_y > self.dest_z )
- {
-// dprint( "XY1 - " );
-// dprint( ftos( self.cnt ) );
-// dprint( "\n" );
- self.use = particlefield_XY;
- self.dest1_z = ( self.dest1_z + self.dest2_z ) / 2;
- }
- else
- {
-// dprint( "XZ1 - " );
-// dprint( ftos( self.cnt ) );
-// dprint( "\n" );
- self.use = particlefield_XZ;
- self.dest1_y = ( self.dest1_y + self.dest2_y ) / 2;
- }
- }
- else
- {
- if ( self.dest_y > self.dest_x )
- {
-// dprint( "YZ2 - " );
-// dprint( ftos( self.cnt ) );
-// dprint( "\n" );
- self.use = particlefield_YZ;
- self.dest1_x = ( self.dest1_x + self.dest2_x ) / 2;
- }
- else
- {
-// dprint( "XZ2 - " );
-// dprint( ftos( self.cnt ) );
-// dprint( "\n" );
- self.use = particlefield_XZ;
- self.dest1_y = ( self.dest1_y + self.dest2_y ) / 2;
- }
- }
-
- if ( self.noise != "" )
- {
- precache_sound( self.noise );
- }
- self.ltime = time;
- };
-
-void () blocker_touch =
- {
- if ( !self.dmg )
- return;
-
- if (time < self.attack_finished)
- return;
- self.attack_finished = time + 0.5;
- T_Damage (other, self, self, self.dmg);
- sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- };
-
-void () blocker_use =
- {
- if ( !self.state )
- {
- self.state = 1;
- setorigin( self, self.origin - '8000 8000 8000' );
- // sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- }
- else
- {
- self.state = 0;
- setorigin( self, self.origin + '8000 8000 8000' );
- sound(self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- }
- };
-
-/*QUAKED func_togglewall (0 .5 .8) ? START_OFF 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
-
-Creates a invisible wall that can be toggled on and off.
-
-START_OFF wall doesn't block until triggered.
-
-"noise" is the sound to play when wall is turned off.
-"noise1" is the sound to play when wall is blocking.
-"dmg" is the amount of damage to cause when touched.
-*/
-
-void() func_togglewall =
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.classname = "togglewall";
- self.movetype = MOVETYPE_PUSH;
- self.mdl = self.model;
- setmodel (self, self.model);
- setsize (self, self.mins, self.maxs);
- setorigin (self, self.origin);
- self.touch = blocker_touch;
- self.use = blocker_use;
- if ( !self.noise )
- {
- self.noise = ("misc/null.wav");
- }
- if ( !self.noise1 )
- {
- self.noise1 = ("misc/null.wav");
- }
-
- precache_sound( self.noise );
- precache_sound( self.noise1 );
-
- self.solid = SOLID_BSP;
- self.model = string_null;
- if ( self.spawnflags & START_OFF )
- {
- self.state = 0;
- setorigin( self, self.origin + '8000 8000 8000' );
- }
- else
- {
- self.state = 1;
- sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- }
- };

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
deleted file mode 100644
index b3e73be..0000000
--- a/qc/hip_rotate.qc
+++ /dev/null
@@ -1,1208 +0,0 @@
-/* Rotate QuickC program
- By Jim Dose' 10/17/96
- Copyright (c)1996 Hipnotic Interactive, Inc.
- All rights reserved.
- Distributed (unsupported) on 3.12.97
-*/
-
-float STATE_ACTIVE = 0;
-float STATE_INACTIVE = 1;
-float STATE_SPEEDINGUP = 2;
-float STATE_SLOWINGDOWN = 3;
-
-float STATE_CLOSED = 4;
-float STATE_OPEN = 5;
-float STATE_OPENING = 6;
-float STATE_CLOSING = 7;
-
-float STATE_WAIT = 0;
-float STATE_MOVE = 1;
-float STATE_STOP = 2;
-float STATE_FIND = 3;
-float STATE_NEXT = 4;
-
-float OBJECT_ROTATE = 0;
-float OBJECT_MOVEWALL = 1;
-float OBJECT_SETORIGIN = 2;
-
-// spawnflags for func_rotate_entity
-float ROTATE_ENTITY_TOGGLE = 1;
-float ROTATE_ENTITY_START_ON = 2;
-
-// spawnflags for path_rotate
-float PATH_ROTATE_ROTATION = 1;
-float PATH_ROTATE_ANGLES = 2;
-float PATH_ROTATE_STOP = 4;
-float PATH_ROTATE_NO_ROTATE = 8;
-float PATH_ROTATE_DAMAGE = 16;
-float PATH_ROTATE_MOVETIME = 32;
-float PATH_ROTATE_SET_DAMAGE = 64;
-
-// spawnflags for func_rotate_door
-float ROTATE_DOOR_STAYOPEN = 1;
-
-.float rotate_type;
-.vector neworigin;
-.vector rotate;
-.float endtime;
-.float duration;
-.vector finalangle;
-.string path;
-.string group;
-.string event;
-
-
-//=========================
-//
-// SUB_NormalizeAngles
-//
-//=========================
-
-vector (vector ang) SUB_NormalizeAngles =
-{
- while( ang_x > 360 )
- {
- ang_x = ang_x - 360;
- }
- while( ang_x < 0 )
- {
- ang_x = ang_x + 360;
- }
-
- while( ang_y > 360 )
- {
- ang_y = ang_y - 360;
- }
- while( ang_y < 0 )
- {
- ang_y = ang_y + 360;
- }
-
- while( ang_z > 360 )
- {
- ang_z = ang_z - 360;
- }
- while( ang_z < 0 )
- {
- ang_z = ang_z + 360;
- }
-
- return ang;
-};
-
-/*QUAKED info_rotate (0 0.5 0) (-4 -4 -4) (4 4 4) 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
-Used as the point of rotation for rotatable objects.
-*/
-void() info_rotate =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
-// remove self after a little while, to make sure that entities that
-// have targeted it have had a chance to spawn
- self.nextthink = time + 2;
- self.think = SUB_Remove;
-};
-
-void() RotateTargets =
-{
- local entity ent;
- local vector vx;
- local vector vy;
- local vector vz;
- local vector org;
-
- makevectors (self.angles);
-
- ent = find( world, targetname, self.target);
- while( ent )
- {
- if ( ent.rotate_type == OBJECT_SETORIGIN )
- {
- org = ent.oldorigin;
- vx = ( v_forward * org_x );
- vy = ( v_right * org_y );
- vy = vy * -1;
- vz = ( v_up * org_z );
- ent.neworigin = vx + vy + vz;
- setorigin( ent, ent.neworigin + self.origin );
- }
- else if ( ent.rotate_type == OBJECT_ROTATE )
- {
- ent.angles = self.angles;
- org = ent.oldorigin;
- vx = ( v_forward * org_x );
- vy = ( v_right * org_y );
- vy = vy * -1;
- vz = ( v_up * org_z );
- ent.neworigin = vx + vy + vz;
- setorigin( ent, ent.neworigin + self.origin );
- }
- else
- {
- org = ent.oldorigin;
- vx = ( v_forward * org_x );
- vy = ( v_right * org_y );
- vy = vy * -1;
- vz = ( v_up * org_z );
- ent.neworigin = vx + vy + vz;
- ent.neworigin = self.origin - self.oldorigin + (ent.neworigin - ent.oldorigin);
- ent.velocity = (ent.neworigin-ent.origin)*25;
- }
- ent = find( ent, targetname, self.target);
- }
-};
-
-void() RotateTargetsFinal =
- {
- local entity ent;
-
- ent = find( world, targetname, self.target);
- while( ent )
- {
- ent.velocity = '0 0 0';
- if ( ent.rotate_type == OBJECT_ROTATE )
- {
- ent.angles = self.angles;
- }
- ent = find( ent, targetname, self.target);
- }
- };
-
-void() SetTargetOrigin =
- {
- local entity ent;
-
- ent = find( world, targetname, self.target);
- while( ent )
- {
- if ( ent.rotate_type == OBJECT_MOVEWALL )
- {
- setorigin( ent, self.origin - self.oldorigin +
- (ent.neworigin - ent.oldorigin) );
- }
- else
- {
- setorigin( ent, ent.neworigin + self.origin );
- }
- ent = find( ent, targetname, self.target);
- }
- };
-
-void() LinkRotateTargets =
- {
- local entity ent;
- local vector tempvec;
-
- self.oldorigin = self.origin;
- ent = find( world, targetname, self.target);
- while( ent )
- {
- if ( ent.classname == "rotate_object" )
- {
- ent.rotate_type = OBJECT_ROTATE;
- ent.oldorigin = ent.origin - self.oldorigin;
- ent.neworigin = ent.origin - self.oldorigin;
- ent.owner = self;
- }
- else if ( ent.classname == "func_movewall" )
- {
- ent.rotate_type = OBJECT_MOVEWALL;
- tempvec = ( ent.absmin + ent.absmax ) * 0.5;
- ent.oldorigin = tempvec - self.oldorigin;
- ent.neworigin = ent.oldorigin;
- ent.owner = self;
- }
- else
- {
- ent.rotate_type = OBJECT_SETORIGIN;
- ent.oldorigin = ent.origin - self.oldorigin;
- ent.neworigin = ent.origin - self.oldorigin;
- }
- ent = find (ent, targetname, self.target);
- }
- };
-
-void( float amount ) SetDamageOnTargets =
- {
- local entity ent;
-
- ent = find( world, targetname, self.target);
- while( ent )
- {
- if ( ent.classname == "trigger_hurt" )
- {
- hurt_setdamage( ent, amount );
- }
- else if ( ent.classname == "func_movewall" )
- {
- ent.dmg = amount;
- }
- ent = find( ent, targetname, self.target);
- }
- };
-
-
-//************************************************
-//
-// Simple continual rotatation
-//
-//************************************************
-
-void() rotate_entity_think =
- {
- local float t;
-
- t = time - self.ltime;
- self.ltime = time;
-
- if ( self.state == STATE_SPEEDINGUP )
- {
- self.count = self.count + self.cnt * t;
- if ( self.count > 1 )
- {
- self.count = 1;
- }
-
- // get rate of rotation
- t = t * self.count;
- }
- else if ( self.state == STATE_SLOWINGDOWN )
- {
- self.count = self.count - self.cnt * t;
- if ( self.count < 0 )
- {
- RotateTargetsFinal();
- self.state = STATE_INACTIVE;
- self.think = SUB_Null;
- return;
- }
-
- // get rate of rotation
- t = t * self.count;
- }
-
- self.angles = self.angles + ( self.rotate * t );
- self.angles = SUB_NormalizeAngles( self.angles );
- RotateTargets();
- self.nextthink = time + 0.02;
- };
-
-void() rotate_entity_use =
- {
- // change to alternate textures
- self.frame = 1 - self.frame;
-
- if ( self.state == STATE_ACTIVE )
- {
- if ( self.spawnflags & ROTATE_ENTITY_TOGGLE )
- {
- if ( self.speed )
- {
- self.count = 1;
- self.state = STATE_SLOWINGDOWN;
- }
- else
- {
- self.state = STATE_INACTIVE;
- self.think = SUB_Null;
- }
- }
- }
- else if ( self.state == STATE_INACTIVE )
- {
- self.think = rotate_entity_think;
- self.nextthink = time + 0.02;
- self.ltime = time;
- if ( self.speed )
- {
- self.count = 0;
- self.state = STATE_SPEEDINGUP;
- }
- else
- {
- self.state = STATE_ACTIVE;
- }
- }
- else if ( self.state == STATE_SPEEDINGUP )
- {
- if ( self.spawnflags & ROTATE_ENTITY_TOGGLE )
- {
- self.state = STATE_SLOWINGDOWN;
- }
- }
- else
- {
- self.state = STATE_SPEEDINGUP;
- }
- };
-
-void() rotate_entity_firstthink =
- {
- LinkRotateTargets();
- if ( self.spawnflags & ROTATE_ENTITY_START_ON )
- {
- self.state = STATE_ACTIVE;
- self.think = rotate_entity_think;
- self.nextthink = time + 0.02;
- self.ltime = time;
- }
- else
- {
- self.state = STATE_INACTIVE;
- self.think = SUB_Null;
- }
- self.use = rotate_entity_use;
- };
-
-/*QUAKED func_rotate_entity (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE START_ON 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
-
-Creates an entity that continually rotates. Can be toggled on and
-off if targeted.
-
-TOGGLE = allows the rotation to be toggled on/off
-
-START_ON = wether the entity is spinning when spawned. If TOGGLE is 0, entity can be turned on, but not off.
-
-If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train.
-
-"rotate" is the rate to rotate.
-"target" is the center of rotation.
-"speed" is how long the entity takes to go from standing still to full speed and vice-versa.
-*/
-
-void() func_rotate_entity =
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_NONE;
-
- setmodel (self, self.model);
- setsize( self, self.mins, self.maxs );
-
- if ( self.speed != 0 )
- {
- self.cnt = 1 / self.speed;
- }
-
- self.think = rotate_entity_firstthink;
- self.nextthink = time + 0.1;
- self.ltime = time;
- };
-
-//************************************************
-//
-// Train with rotation functionality
-//
-//************************************************
-
-/*QUAKED path_rotate (0.5 0.3 0) (-8 -8 -8) (8 8 8) ROTATION ANGLES STOP NO_ROTATE DAMAGE MOVETIME SET_DAMAGE
- Path for rotate_train.
-
- ROTATION tells train to rotate at rate specified by "rotate". Use '0 0 0' to stop rotation.
-
- ANGLES tells train to rotate to the angles specified by "angles" while traveling to this path_rotate. Use values < 0 or > 360 to guarantee that it turns in a certain direction. Having this flag set automatically clears any rotation.
-
- STOP tells the train to stop and wait to be retriggered.
-
- NO_ROTATE tells the train to stop rotating when waiting to be triggered.
-
- DAMAGE tells the train to cause damage based on "dmg".
-
- MOVETIME tells the train to interpret "speed" as the length of time to take moving from one corner to another.
-
- SET_DAMAGE tells the train to set all targets damage to "dmg"
-
- "noise" contains the name of the sound to play when train stops.
- "noise1" contains the name of the sound to play when train moves.
- "event" is a target to trigger when train arrives at path_rotate.
-*/
-void() path_rotate =
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if ( self.noise != "" )
- {
- precache_sound( self.noise );
- }
- if ( self.noise1 != "" )
- {
- precache_sound( self.noise1 );
- }
- };
-
-
-void() rotate_train;
-void() rotate_train_next;
-void() rotate_train_find;
-
-void() rotate_train_think =
- {
- local float t;
- local float timeelapsed;
-
- t = time - self.ltime;
- self.ltime = time;
-
- if ( ( self.endtime ) && ( time >= self.endtime ) )
- {
- self.endtime = 0;
- if ( self.state == STATE_MOVE )
- {
- setorigin(self, self.finaldest);
- self.velocity = '0 0 0';
- }
-
- if (self.think1)
- self.think1();
- }
- else
- {
- timeelapsed = (time - self.cnt) * self.duration;
- if ( timeelapsed > 1 )
- timeelapsed = 1;
- setorigin( self, self.dest1 + ( self.dest2 * timeelapsed ) );
- }
-
- self.angles = self.angles + ( self.rotate * t );
- self.angles = SUB_NormalizeAngles( self.angles );
- RotateTargets();
-
- self.nextthink = time + 0.02;
- };
-
-void() rotate_train_use =
- {
- if (self.think1 != rotate_train_find)
- {
- if ( self.velocity != '0 0 0' )
- return; // already activated
- if ( self.think1 )
- {
- self.think1();
- }
- }
- };
-
-void() rotate_train_wait =
- {
- self.state = STATE_WAIT;
-
- if ( self.goalentity.noise != "" )
- {
- sound (self, CHAN_VOICE, self.goalentity.noise, 1, ATTN_NORM);
- }
- else
- {
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- }
- if ( self.goalentity.spawnflags & PATH_ROTATE_ANGLES )
- {
- self.rotate = '0 0 0';
- self.angles = self.finalangle;
- }
- if ( self.goalentity.spawnflags & PATH_ROTATE_NO_ROTATE )
- {
- self.rotate = '0 0 0';
- }
- self.endtime = self.ltime + self.goalentity.wait;
- self.think1 = rotate_train_next;
- };
-
-void() rotate_train_stop =
- {
- self.state = STATE_STOP;
-
- if ( self.goalentity.noise != "" )
- {
- sound (self, CHAN_VOICE, self.goalentity.noise, 1, ATTN_NORM);
- }
- else
- {
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- }
- if ( self.goalentity.spawnflags & PATH_ROTATE_ANGLES )
- {
- self.rotate = '0 0 0';
- self.angles = self.finalangle;
- }
- if ( self.goalentity.spawnflags & PATH_ROTATE_NO_ROTATE )
- {
- self.rotate = '0 0 0';
- }
-
- self.dmg = 0;
- self.think1 = rotate_train_next;
- };
-
-void() rotate_train_next =
-{
- local entity targ;
- local entity current;
- local vector vdestdelta;
- local float len, traveltime, div;
- local string temp;
-
- self.state = STATE_NEXT;
-
- current = self.goalentity;
- targ = find (world, targetname, self.path);
- if ( targ.classname != "path_rotate" )
- objerror( "Next target is not path_rotate" );
-
- if ( self.goalentity.noise1 != "" )
- {
- self.noise1 = self.goalentity.noise1;
- }
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
-
- self.goalentity = targ;
- self.path = targ.target;
- if (!self.path )
- objerror ("rotate_train_next: no next target");
-
- if ( targ.spawnflags & PATH_ROTATE_STOP )
- {
- self.think1 = rotate_train_stop;
- }
- else if (targ.wait)
- {
- self.think1 = rotate_train_wait;
- }
- else
- {
- self.think1 = rotate_train_next;
- }
-
- if ( current.event != "" )
- {
- // Trigger any events that should happen at the corner.
- temp = self.target;
- self.target = current.event;
- self.message = current.message;
- SUB_UseTargets();
- self.target = temp;
- self.message = string_null;
- }
-
- if ( current.spawnflags & PATH_ROTATE_ANGLES )
- {
- self.rotate = '0 0 0';
- self.angles = self.finalangle;
- }
-
- if ( current.spawnflags & PATH_ROTATE_ROTATION )
- {
- self.rotate = current.rotate;
- }
-
- if ( current.spawnflags & PATH_ROTATE_DAMAGE )
- {
- self.dmg = current.dmg;
- }
-
- if ( current.spawnflags & PATH_ROTATE_SET_DAMAGE )
- {
- SetDamageOnTargets( current.dmg );
- }
-
- if ( current.speed == -1 )
- {
- // Warp to the next path_corner
- setorigin( self, targ.origin );
- self.endtime = self.ltime + 0.01;
- SetTargetOrigin();
-
- if ( targ.spawnflags & PATH_ROTATE_ANGLES )
- {
- self.angles = targ.angles;
- }
-
- self.duration = 1; // 1 / duration
- self.cnt = time; // start time
- self.dest2 = '0 0 0'; // delta
- self.dest1 = self.origin; // original position
- self.finaldest = self.origin;
- }
- else
- {
- self.state = STATE_MOVE;
-
- self.finaldest = targ.origin;
- if (self.finaldest == self.origin)
- {
- self.velocity = '0 0 0';
- self.endtime = self.ltime + 0.1;
-
- self.duration = 1; // 1 / duration
- self.cnt = time; // start time
- self.dest2 = '0 0 0'; // delta
- self.dest1 = self.origin; // original position
- self.finaldest = self.origin;
- return;
- }
- // set destdelta to the vector needed to move
- vdestdelta = self.finaldest - self.origin;
-
- // calculate length of vector
- len = vlen (vdestdelta);
-
- if ( current.spawnflags & PATH_ROTATE_MOVETIME )
- {
- traveltime = current.speed;
- }
- else
- {
- // check if there's a speed change
- if (current.speed>0)
- self.speed = current.speed;
-
- if (!self.speed)
- objerror("No speed is defined!");
-
- // divide by speed to get time to reach dest
- traveltime = len / self.speed;
- }
-
- if (traveltime < 0.1)
- {
- self.velocity = '0 0 0';
- self.endtime = self.ltime + 0.1;
- if ( targ.spawnflags & PATH_ROTATE_ANGLES )
- {
- self.angles = targ.angles;
- }
- return;
- }
-
- // qcc won't take vec/float
- div = 1 / traveltime;
-
- if ( targ.spawnflags & PATH_ROTATE_ANGLES )
- {
- self.finalangle = SUB_NormalizeAngles( targ.angles );
- self.rotate = ( targ.angles - self.angles ) * div;
- }
-
- // set endtime to trigger a think when dest is reached
- self.endtime = self.ltime + traveltime;
-
- // scale the destdelta vector by the time spent traveling to get velocity
- self.velocity = vdestdelta * div;
-
- self.duration = div; // 1 / duration
- self.cnt = time; // start time
- self.dest2 = vdestdelta; // delta
- self.dest1 = self.origin; // original position
- }
- };
-
-void() rotate_train_find =
- {
- local entity targ;
-
- self.state = STATE_FIND;
-
- LinkRotateTargets();
-
- // the first target is the point of rotation.
- // the second target is the path.
- targ = find ( world, targetname, self.path);
- if ( targ.classname != "path_rotate" )
- objerror( "Next target is not path_rotate" );
-
- // Save the current entity
- self.goalentity = targ;
-
- if ( targ.spawnflags & PATH_ROTATE_ANGLES )
- {
- self.angles = targ.angles;
- self.finalangle = SUB_NormalizeAngles( targ.angles );
- }
-
- self.path = targ.target;
- setorigin (self, targ.origin );
- SetTargetOrigin();
- RotateTargetsFinal();
- self.think1 = rotate_train_next;
- if (!self.targetname)
- {
- // not triggered, so start immediately
- self.endtime = self.ltime + 0.1;
- }
- else
- {
- self.endtime = 0;
- }
-
- self.duration = 1; // 1 / duration
- self.cnt = time; // start time
- self.dest2 = '0 0 0'; // delta
- self.dest1 = self.origin; // original position
- };
-
-/*QUAKED func_rotate_train (0 .5 .8) (-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
-
-In path_rotate, set speed to be the new speed of the train after it reaches
-the path change. If speed is -1, the train will warp directly to the next
-path change after the specified wait time. If MOVETIME is set on the
-path_rotate, the train to interprets "speed" as the length of time to
-take moving from one corner to another.
-
-"noise" contains the name of the sound to play when train stops.
-"noise1" contains the name of the sound to play when train moves.
-Both "noise" and "noise1" defaults depend upon "sounds" variable and
-can be overridden by the "noise" and "noise1" variable in path_rotate.
-
-Also in path_rotate, if STOP is set, the train will wait until it is
-retriggered before moving on to the next goal.
-
-Trains are moving platforms that players can ride.
-"path" specifies the first path_rotate and is the starting position.
-If the train is the target of a button or trigger, it will not begin moving until activated.
-The func_rotate_train entity is the center of rotation of all objects targeted by it.
-
-If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train.
-
-speed default 100
-dmg default 0
-sounds
-1) ratchet metal
-*/
-
-void() rotate_train =
- {
- objerror ("rotate_train entities should be changed to rotate_object with\nfunc_rotate_train controllers\n");
- };
-
-void() func_rotate_train =
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (!self.speed)
- self.speed = 100;
- if (!self.target)
- objerror ("rotate_train without a target");
-
- if ( !self.noise )
- {
- if (self.sounds == 0)
- {
- self.noise = ("misc/null.wav");
- }
-
- if (self.sounds == 1)
- {
- self.noise = ("plats/train2.wav");
- }
- }
- if ( !self.noise1 )
- {
- if (self.sounds == 0)
- {
- self.noise1 = ("misc/null.wav");
- }
- if (self.sounds == 1)
- {
- self.noise1 = ("plats/train1.wav");
- }
- }
-
- precache_sound( self.noise );
- precache_sound( self.noise1 );
-
- self.cnt = 1;
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_STEP;
- self.use = rotate_train_use;
-
- setmodel (self, self.model);
- setsize (self, self.mins, self.maxs);
- setorigin (self, self.origin);
-
-// start trains on the second frame, to make sure their targets have had
-// a chance to spawn
- self.ltime = time;
- self.nextthink = self.ltime + 0.1;
- self.endtime = self.ltime + 0.1;
- self.think = rotate_train_think;
- self.think1 = rotate_train_find;
- self.state = STATE_FIND;
-
- self.duration = 1; // 1 / duration
- self.cnt = 0.1; // start time
- self.dest2 = '0 0 0'; // delta
- self.dest1 = self.origin; // original position
-
-
- self.flags = self.flags | FL_ONGROUND;
- };
-
-//************************************************
-//
-// Moving clip walls
-//
-//************************************************
-
-void() rotate_door_reversedirection;
-void() rotate_door_group_reversedirection;
-
-void() movewall_touch =
- {
- if (time < self.owner.attack_finished)
- return;
-
- if ( self.dmg )
- {
- T_Damage (other, self, self.owner, self.dmg);
- self.owner.attack_finished = time + 0.5;
- }
- else if ( self.owner.dmg )
- {
- T_Damage (other, self, self.owner, self.owner.dmg);
- self.owner.attack_finished = time + 0.5;
- }
- };
-
-void() movewall_blocked =
- {
- local entity temp;
-
- if (time < self.owner.attack_finished)
- return;
-
- self.owner.attack_finished = time + 0.5;
-
- if ( self.owner.classname == "func_rotate_door" )
- {
- temp = self;
- self = self.owner;
- rotate_door_group_reversedirection();
- self = temp;
- }
-
- if ( self.dmg )
- {
- T_Damage (other, self, self.owner, self.dmg);
- self.owner.attack_finished = time + 0.5;
- }
- else if ( self.owner.dmg )
- {
- T_Damage (other, self, self.owner, self.owner.dmg);
- self.owner.attack_finished = time + 0.5;
- }
- };
-
-void() movewall_think =
- {
- self.ltime = time;
- self.nextthink = time + 0.02;
- };
-
-/*QUAKED func_movewall (0 .5 .8) ? VISIBLE TOUCH NONBLOCKING 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
-
-Used to emulate collision on rotating objects.
-
-VISIBLE causes brush to be displayed.
-
-TOUCH specifies whether to cause damage when touched by player.
-
-NONBLOCKING makes the brush non-solid. This is useless if VISIBLE is set.
-
-"dmg" specifies the damage to cause when touched or blocked.
-*/
-void() func_movewall =
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.angles = '0 0 0';
- self.movetype = MOVETYPE_PUSH;
- if ( self.spawnflags & MOVEWALL_NONBLOCKING )
- {
- self.solid = SOLID_NOT;
- }
- else
- {
- self.solid = SOLID_BSP;
- self.blocked = movewall_blocked;
- }
- if ( self.spawnflags & MOVEWALL_TOUCH )
- {
- self.touch = movewall_touch;
- }
- setmodel (self,self.model);
- if ( !( self.spawnflags & MOVEWALL_VISIBLE ) )
- {
- self.model = string_null;
- }
- self.think = movewall_think;
- self.nextthink = time + 0.02;
- self.ltime = time;
- };
-
-/*QUAKED rotate_object (0 .5 .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 defines an object to be rotated. Used as the target of func_rotate_door.
-*/
-void() rotate_object =
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.classname = "rotate_object";
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_NONE;
- setmodel (self,self.model);
- setsize( self, self.mins, self.maxs );
- self.think = SUB_Null;
- };
-
-//************************************************
-//
-// Rotating doors
-//
-//************************************************
-
-void() rotate_door_think2 =
- {
- local float t;
-
- t = time - self.ltime;
- self.ltime = time;
-
- // change to alternate textures
- self.frame = 1 - self.frame;
-
- self.angles = self.dest;
-
- if ( self.state == STATE_OPENING )
- {
- self.state = STATE_OPEN;
- }
- else
- {
- if ( self.spawnflags & ROTATE_DOOR_STAYOPEN )
- {
- rotate_door_group_reversedirection();
- return;
- }
- self.state = STATE_CLOSED;
- }
-
- sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
- self.think = SUB_Null;
-
- RotateTargetsFinal();
- };
-
-void() rotate_door_think =
- {
- local float t;
-
- t = time - self.ltime;
- self.ltime = time;
-
- if ( time < self.endtime )
- {
- self.angles = self.angles + ( self.rotate * t );
- RotateTargets();
- }
- else
- {
- self.angles = self.dest;
- RotateTargets();
- self.think = rotate_door_think2;
- }
-
- self.nextthink = time + 0.01;
- };
-
-void() rotate_door_reversedirection =
- {
- local vector start;
-
- // change to alternate textures
- self.frame = 1 - self.frame;
-
- if ( self.state == STATE_CLOSING )
- {
- start = self.dest1;
- self.dest = self.dest2;
- self.state = STATE_OPENING;
- }
- else
- {
- start = self.dest2;
- self.dest = self.dest1;
- self.state = STATE_CLOSING;
- }
-
- sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
-
- self.rotate = ( self.dest - start ) * ( 1 / self.speed );
- self.think = rotate_door_think;
- self.nextthink = time + 0.02;
- self.endtime = time + self.speed - ( self.endtime - time );
- self.ltime = time;
- };
-
-void() rotate_door_group_reversedirection =
- {
- local string name;
-
- // tell all associated rotaters to reverse direction
- if ( self.group != "" )
- {
- name = self.group;
- self = find( world, group, name);
- while( self )
- {
- rotate_door_reversedirection();
- self = find( self, group, name);
- }
- }
- else
- {
- rotate_door_reversedirection();
- }
- };
-
-void() rotate_door_use =
- {
- local vector start;
-
- if ( ( self.state != STATE_OPEN ) && ( self.state != STATE_CLOSED ) )
- return;
-
- if ( !self.cnt )
- {
- self.cnt = 1;
- LinkRotateTargets();
- }
-
- // change to alternate textures
- self.frame = 1 - self.frame;
-
- if ( self.state == STATE_CLOSED )
- {
- start = self.dest1;
- self.dest = self.dest2;
- self.state = STATE_OPENING;
- }
- else
- {
- start = self.dest2;
- self.dest = self.dest1;
- self.state = STATE_CLOSING;
- }
-
- sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
-
- self.rotate = ( self.dest - start ) * ( 1 / self.speed );
- self.think = rotate_door_think;
- self.nextthink = time + 0.01;
- self.endtime = time + self.speed;
- self.ltime = time;
- };
-
-
-/*QUAKED func_rotate_door (0 .5 .8) (-8 -8 -8) (8 8 8) STAYOPEN 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
-
-Creates a door that rotates between two positions around a point of
-rotation each time it's triggered.
-
-STAYOPEN tells the door to reopen after closing. This prevents a trigger-
-once door from closing again when it's blocked.
-
-"dmg" specifies the damage to cause when blocked. Defaults to 2. Negative numbers indicate no damage.
-"speed" specifies how the time it takes to rotate
-
-"sounds"
-1) medieval (default)
-2) metal
-3) base
-*/
-
-void() func_rotate_door = // added slinet option - sounds 4 -- dumptruck_ds
- {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (!self.target)
- {
- objerror( "rotate_door without target." );
- }
-
- self.dest1 = '0 0 0';
- self.dest2 = self.angles;
- self.angles = self.dest1;
-
- // default to 2 seconds
- if ( !self.speed )
- {
- self.speed = 2;
- }
-
- self.cnt = 0;
-
- if (!self.dmg)
- self.dmg = 2;
- else if ( self.dmg < 0 )
- {
- self.dmg = 0;
- }
-
- if (self.sounds == 0)
- {
- //If at least one custom sound is defined, then let's ignore the presets and go for the custom sounds,
- //otherwise let's use preset #1 by default
- if(self.noise1=="" && self.noise2=="" && self.noise3=="")
- {
- self.sounds = 1;
- }
- else
- {
- if(self.noise1=="") self.noise1 = "misc/null.wav";
- if(self.noise2=="") self.noise2 = "misc/null.wav";
- if(self.noise3=="") self.noise3 = "misc/null.wav";
- }
- }
- if (self.sounds == 1)
- {
- self.noise1 = "doors/latch2.wav";
- self.noise2 = "doors/winch2.wav";
- self.noise3 = "doors/drclos4.wav";
- }
- else if (self.sounds == 2)
- {
- self.noise2 = "doors/airdoor1.wav";
- self.noise1 = "doors/airdoor2.wav";
- self.noise3 = self.noise1;
- }
- else if (self.sounds == 3)
- {
- self.noise2 = "doors/basesec1.wav";
- self.noise1 = "doors/basesec2.wav";
- self.noise3 = self.noise1;
- }
- else if (self.sounds == 4)
- {
- self.noise1 = self.noise2 = self.noise3 = "misc/null.wav";
- }
- precache_sound (self.noise1);
- precache_sound (self.noise2);
- precache_sound (self.noise3);
-
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_NONE;
- setmodel (self, self.model);
- setorigin( self, self.origin );
- setsize( self, self.mins, self.maxs );
- self.state = STATE_CLOSED;
- self.use = rotate_door_use;
- self.think = SUB_Null;
- };

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

Diff qc/math.qc

diff --git a/qc/math.qc b/qc/math.qc
index 6dbe27d..7559803 100644
--- a/qc/math.qc
+++ b/qc/math.qc
@@ -1,10 +1,8 @@
-/*
- * math.qc
- *
- * Author: Joshua Skelton joshua.skelton@gmail.com
- *
- * A collection of helpful math functions.
- */
+//==============================================================================
+// math.qc
+// Author: Joshua Skelton joshua.skelton@gmail.com
+// A collection of helpful math functions.
+//==============================================================================

// Forward declarations
float(float value, float minValue, float maxValue) clamp;
@@ -12,198 +10,178 @@ float(float a, float b) mod;
float(float x) sign;
float(float value, float minValue, float maxValue) wrap;

-/*
- * clamp
- *
- * Limits the given value to the given range.
- *
- * value: A number
- *
- * minValue: The minimum value of the range
- *
- * maxValue: The maximum value of the range
- *
- * Returns: A number within the given range.
- */
-float(float value, float minValue, float maxValue) clamp = {
- if (value < minValue) {
- return minValue;
- }
- else if (value > maxValue) {
- return maxValue;
- }
-
- return value;
+//----------------------------------------------------------------------
+// clamp
+//
+// Limits the given value to the given range.
+// value: A number
+// minValue: The minimum value of the range
+// maxValue: The maximum value of the range
+// Returns: A number within the given range.
+//----------------------------------------------------------------------
+float(float value, float minValue, float maxValue) clamp =
+{
+ if (value < minValue)
+ {
+ return minValue;
+ }
+ else if (value > maxValue)
+ {
+ return maxValue;
+ }
+
+ return value;
};

-/*
- * mod
- *
- * Returns the remainder after the division of a by n
- *
- * a: The dividend
- *
- * b: The divisor
- *
- * Returns: The remainder of a divided by n
- */
-float(float a, float n) mod = {
- return a - (n * floor(a / n));
+//----------------------------------------------------------------------
+// mod
+//
+// Returns the remainder after the division of a by n
+// a: The dividend
+// b: The divisor
+// Returns: The remainder of a divided by n
+//----------------------------------------------------------------------
+float(float a, float n) mod =
+{
+ return a - (n * floor(a / n));
};

-/*
- * sign
- *
- * Returns an indication of the sign of the given number.
- *
- * x: A number
- *
- * Returns: -1 if x < 0, 0 if x == 0, 1 if x > 0.
- */
-float(float x) sign = {
- if (x > 0) {
- return 1;
- }
- else if (x < 0) {
- return -1;
- }
-
- return 0;
+//----------------------------------------------------------------------
+// sign
+//
+// Returns an indication of the sign of the given number.
+// x: A number
+// Returns: -1 if x < 0, 0 if x == 0, 1 if x > 0.
+//----------------------------------------------------------------------
+float(float x) sign =
+{
+ if (x > 0)
+ {
+ return 1;
+ }
+ else if (x < 0)
+ {
+ return -1;
+ }
+
+ return 0;
};

-/*
- * wrap
- *
- * Limits the given value to the given range and will wrap the value to the
- * the other end of the range if exceeded.
- *
- * value: A number
- *
- * minValue: The minimum value of the range
- *
- * maxValue: The maximum value of the range
- *
- * Returns: A number within the given range.
- */
-float(float value, float minValue, float maxValue) wrap = {
- local float range = maxValue - minValue;
-
- return mod(value - minValue, range + 1) + minValue;
+//----------------------------------------------------------------------
+// wrap
+//
+// Limits the given value to the given range and will wrap the value to the
+// the other end of the range if exceeded.
+//
+// value: A number
+// minValue: The minimum value of the range
+// maxValue: The maximum value of the range
+// Returns: A number within the given range.
+//----------------------------------------------------------------------
+float(float value, float minValue, float maxValue) wrap =
+{
+ local float range = maxValue - minValue;
+ return mod (value - minValue, range + 1) + minValue;
};

-
-
+//----------------------------------------------------------------------
float(float a, float b, float mix) lerp =
{
- if (mix <= 0) return a;
- if (mix >= 1) return b;
- return (b * mix + a * ( 1 - mix ) );
-}
+ if (mix <= 0)
+ return a;
+ if (mix >= 1)
+ return b;
+ return (b * mix + a * ( 1 - mix ) );
+};

+//----------------------------------------------------------------------
vector(vector a, vector b, float mix) lerpVector =
{
- if (mix <= 0) return a;
- if (mix >= 1) return b;
- return (b * mix + a * ( 1 - mix ) );
-}
+ if (mix <= 0)
+ return a;
+ if (mix >= 1)
+ return b;
+ return (b * mix + a * ( 1 - mix ) );
+};

+//----------------------------------------------------------------------
// for a relaxing lerp: hermite lerp.
+//----------------------------------------------------------------------
float(float a, float b, float mix) lerpHermite =
{
- if (mix <= 0) return a;
- if (mix >= 1) return b;
-
- local float h01;
-
- h01 = mix * mix;
- h01 *= 3 - 2 * mix;
-
- return (b * h01 + a * ( 1 - h01 ) );
-}
+ if (mix <= 0)
+ return a;
+ if (mix >= 1)
+ return b;

-vector(vector a, vector b, float mix) lerpVectorHermite =
-{
- if (mix <= 0) return a;
- if (mix >= 1) return b;
+ local float h01;

- local float h01;
-
- h01 = mix * mix;
- h01 *= 3 - 2 * mix;
-
- return (b * h01 + a * ( 1 - h01 ) );
-}
+ h01 = mix * mix;
+ h01 *= 3 - 2 * mix;

-float(float anga, float angb) angledif =
-{
- float dif;
- dif = fabs(anga - angb);
- if (dif > 180)
- dif = 360 - dif;
- return dif;
-}
-
-float(vector ang, vector base_ang, vector offset) isInAngle = {
- if (angledif(ang_x, base_ang_x) > offset_x || angledif(ang_y, base_ang_y) > offset_y)
- return FALSE;
- else
- return TRUE;
+ return (b * h01 + a * (1 - h01));
};

+//----------------------------------------------------------------------
+vector(vector a, vector b, float mix) lerpVectorHermite =
+{
+ if (mix <= 0)
+ return a;
+ if (mix >= 1)
+ return b;

-// normalizes an angle vector to the 0/+359 range
-vector(vector ang) normalizeAngles = {
-
- ang_x = ang_x - floor(ang_x/360) * 360;
- ang_y = ang_y - floor(ang_y/360) * 360;
- ang_z = ang_z - floor(ang_z/360) * 360;
+ local float h01;

- /*
- while (ang_x > 360)
- ang_x = ang_x - 360;
+ h01 = mix * mix;
+ h01 *= 3 - 2 * mix;

- while (ang_x < 0)
- ang_x = ang_x + 360;
+ return (b * h01 + a * (1 - h01));
+};

- while (ang_y > 360)
- ang_y = ang_y - 360;
+//----------------------------------------------------------------------
+float(float anga, float angb) angledif =
+{
+ local float dif;
+ dif = fabs (anga - angb);
+ if (dif > 180)
+ dif = 360 - dif;
+ return dif;
+};

- while (ang_y < 0)
- ang_y = ang_y + 360;
+//----------------------------------------------------------------------
+float(vector ang, vector base_ang, vector offset) isInAngle =
+{
+ if (angledif(ang_x, base_ang_x) > offset_x ||
+ angledif(ang_y, base_ang_y) > offset_y)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+};

- while (ang_z > 360)
- ang_z = ang_z - 360;
+//----------------------------------------------------------------------
+// normalizes an angle vector to the 0/+359 range
+//----------------------------------------------------------------------
+vector(vector ang) normalizeAngles =
+{
+ ang_x = ang_x - floor (ang_x / 360) * 360;
+ ang_y = ang_y - floor (ang_y / 360) * 360;
+ ang_z = ang_z - floor (ang_z / 360) * 360;

- while (ang_z < 0)
- ang_z = ang_z + 360;
- */
return ang;
};

+//----------------------------------------------------------------------
// normalizes an angle vector to the -180/+179 range
-vector(vector ang) normalizeAngles180 = {
- ang_x = ((ang_x+180) - floor((ang_x+180)/360) * 360) - 180;
- ang_y = ((ang_y+180) - floor((ang_y+180)/360) * 360) - 180;
- ang_z = ((ang_z+180) - floor((ang_z+180)/360) * 360) - 180;
-
- /*
- while (ang_x > 180)
- ang_x = ang_x - 360;
-
- while (ang_x < -180)
- ang_x = ang_x + 360;
-
- while (ang_y > 180)
- ang_y = ang_y - 360;
-
- while (ang_y < -180)
- ang_y = ang_y + 360;
-
- while (ang_z > 180)
- ang_z = ang_z - 360;
+//----------------------------------------------------------------------
+vector(vector ang) normalizeAngles180 =
+{
+ ang_x = ((ang_x + 180) - floor ((ang_x + 180)/360) * 360) - 180;
+ ang_y = ((ang_y + 180) - floor ((ang_y + 180)/360) * 360) - 180;
+ ang_z = ((ang_z + 180) - floor ((ang_z + 180)/360) * 360) - 180;

- while (ang_z < -180)
- ang_z = ang_z + 360;
- */
return ang;
};

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

Diff qc/misc.qc

diff --git a/qc/misc.qc b/qc/misc.qc
index 26009a1..ce251f5 100644
--- a/qc/misc.qc
+++ b/qc/misc.qc
@@ -951,345 +951,6 @@ void() viewthing =
setmodel (self, "progs/player.mdl");
};

-
-/*
-==============================================================================
-
-SIMPLE BMODELS
-
-==============================================================================
-*/
-
-void() func_wall_use =
-{ // change to alternate textures
- self.frame = 1 - self.frame;
-};
-
-/*QUAKED func_wall (0 .5 .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 is just a solid wall if not inhibitted
-*/
-void() func_wall =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.angles = '0 0 0';
- self.movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything
- self.solid = SOLID_BSP;
- self.use = func_wall_use;
- setmodel (self, self.model);
-};
-
-
-/*QUAKED func_illusionary (0 .5 .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
-A simple entity that looks solid but lets you walk through it.
-*/
-void() func_illusionary =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.angles = '0 0 0';
- self.movetype = MOVETYPE_NONE;
- self.solid = SOLID_NOT;
- setmodel (self, self.model);
- makestatic (self);
-};
-
-
-float GATE_REVERSE = 16; // For func_episodegate and func_bossgate appear when player has all runes
-
-/*QUAKED func_episodegate (0 .5 .8) ? E1 E2 E3 E4 REVERSE_FUNCTIONALITY
-This bmodel will appear if the episode has allready been completed, so players can't reenter it.
-*/
-void() func_episodegate =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (self.spawnflags & GATE_REVERSE)
- {
- self.spawnflags = self.spawnflags - GATE_REVERSE; // this is to avoid a possible issue with sigil_touch2
- if (serverflags & self.spawnflags)
- return; // Haven't gotten rune yet
- }
- else
- {
- if (!(serverflags & self.spawnflags))
- return; // can still enter episode
- }
- self.angles = '0 0 0';
- self.movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything
- self.solid = SOLID_BSP;
- self.use = func_wall_use;
- setmodel (self, self.model);
-};
-
-/*QUAKED func_bossgate (0 .5 .8) ? X X X X REVERSE_FUNCTIONALITY
-This bmodel appears unless players have all of the episode sigils.
-*/
-void() func_bossgate =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (self.spawnflags & GATE_REVERSE)
- {
- if (!((serverflags & 15) == 15))
- {
- return; // not all complete
- }
- }
- else
- {
- if ( (serverflags & 15) == 15 )
- return; // all episodes completed
- }
- self.angles = '0 0 0';
- self.movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything
- self.solid = SOLID_BSP;
- self.use = func_wall_use;
- setmodel (self, self.model);
-};
-
-/*****************
-func_togglevisiblewall
-
-A bmodel which you can toggle its visibility. Behaves much like a traditional func_wall in any other way,
-but you can target it to toggle visible/invisible.
-If the entity has a switchable shadow it also toggles.
-
-spawnflag 1: starts invisible
-spawnflag 2: set brush as non-solid
-
-******************/
-
-float TOGGLEVISWALL_STARTOFF = 1;
-float TOGGLEVISWALL_NOTSOLID = 2;
-
-void() func_togglevisiblewall_use =
-{
- if(!self.state) {
- if(!(self.spawnflags & TOGGLEVISWALL_NOTSOLID)) {
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- }
- setmodel (self, self.origmodel);
- if(self.switchshadstyle) lightstyle(self.switchshadstyle, "a");
- self.state = 1;
- } else {
-
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_NONE;
- setmodel (self, "");
- if(self.switchshadstyle) lightstyle(self.switchshadstyle, "m");
- self.state = 0;
- }
-
-};
-
-void() func_togglevisiblewall =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.angles = '0 0 0';
- self.use = func_togglevisiblewall_use;
-
- self.origmodel = self.model;
-
- if(self.spawnflags & TOGGLEVISWALL_STARTOFF) self.state = 1;
- else self.state = 0;
-
- if(self.spawnflags & TOGGLEVISWALL_NOTSOLID) {
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_NONE;
- }
-
- func_togglevisiblewall_use();
-
-};
-
-
-/*****************
-func_shadow
-
-An invisible bmodel that can be used to only cast shadows.
-
-******************/
-
-void() func_shadow = {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.angles = '0 0 0';
- self.movetype = MOVETYPE_NONE;
- self.solid = SOLID_NOT;
-
- self.modelindex = 0;
- self.model = "";
-
-}
-
-
-
-/********************
-misc_shadowcontroller
-
-Controls switchable shadows on any bmodel entity (except doors).
-Target entity must have set _switchableshadow set to 1.
-
-speed: Controls the time in seconds it takes to fade the shadow in. Default is 0.5, and setting it to -1 disables fading.
-speed2: Same as 'speed' but for the fade out animation. If unset it's the same value as 'speed'.
-spawnflag 1: target shadow starts as disabled
-
-*********************/
-
-float SHADOWCONTROLLER_STARTOFF = 1;
-
-void() shadow_fade_out =
-{
- if (self.count < 0)
- self.count = 0;
- if (self.count > 12)
- self.count = 12;
-
- dprint(ftos(self.count));dprint("\n");
-
- lightstyle(self.switchshadstyle, lightstyle_fade_lookup(self.count));
- self.count = self.count + self.dmg;
- if (self.count > 12)
- return;
-
- self.think = shadow_fade_out;
- self.nextthink = time + self.delay;
-};
-
-void() shadow_fade_in =
-{
- if (self.count < 0)
- self.count = 0;
- if (self.count > 12)
- self.count = 12;
-
- dprint(ftos(self.count));dprint("\n");
-
- lightstyle(self.switchshadstyle, lightstyle_fade_lookup(self.count));
- self.count = self.count - self.dmg;
- if (self.count < 0)
- return;
-
- self.think = shadow_fade_in;
- self.nextthink = time + self.delay;
-
-};
-
-void(float speed) misc_shadowcontroller_setsteps = {
- // self.delay -> time between steps
- // self.dmg -> step size
- if(speed >= 0.24) {
- self.delay = (speed/12);
- self.dmg = 1;
- }
- else if(speed >= 0.12) {
- self.delay = (speed/6);
- self.dmg = 2;
- }
- else if(speed >= 0.06) {
- self.delay = (speed/3);
- self.dmg = 4;
- }
- else if(speed >= 0.04) {
- self.delay = (speed/2);
- self.dmg = 6;
- }
- else {
- self.delay = 0;
- self.dmg = 12;
- }
-
-}
-
-void() misc_shadowcontroller_use = {
-
- if(self.shadowoff) {
- dprint("Fade in:\n");
-
- misc_shadowcontroller_setsteps(self.speed);
-
- shadow_fade_in();
-
- self.shadowoff = 0;
- } else {
- dprint("Fade out:\n");
-
- misc_shadowcontroller_setsteps(self.speed2);
-
- shadow_fade_out();
-
- self.shadowoff = 1;
- }
-}
-
-void() misc_shadowcontroller = {
- entity t1;
-
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
-
- // doesn't search for a target if switchshadstyle is already set
- // used for built-in shadow controllers
- if(!self.switchshadstyle) {
-
- // we need to find only the first target entity with switchable shadows set, since shadow lightstyles are bound by targetname
-
-
- t1 = find(world, targetname2, self.target);
-
- while(t1 != world && !t1.switchshadstyle) {
- t1 = find(t1, targetname2, self.target);
- }
-
- if(t1 == world) {
- t1 = find(world, targetname, self.target);
-
- while(t1 != world && !t1.switchshadstyle) {
- t1 = find(t1, targetname, self.target);
- }
- }
-
-
- if(t1 == world) {
- dprint("\b[misc_shadowcontroller]\b _switchableshadow not set in target ");dprint(self.target);dprint("\n");
- return;
- }
-
- self.switchshadstyle = t1.switchshadstyle;
- }
-
- if(!self.speed) self.speed = 0.5;
- if(!self.speed2) self.speed2 = self.speed;
-
- if(self.spawnflags & SHADOWCONTROLLER_STARTOFF) {
- lightstyle(self.switchshadstyle, "m");
-
- self.shadowoff = 1;
- self.count = 12;
-
- misc_shadowcontroller_setsteps(self.speed2);
- }
- else {
- lightstyle(self.switchshadstyle, "a");
- self.shadowoff = 0;
- self.count = 0;
- misc_shadowcontroller_setsteps(self.speed);
- }
-
- self.use = misc_shadowcontroller_use;
-}
-
-
/*
misc_infight

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

Diff qc/misc/modeltrain.qc

diff --git a/qc/misc/modeltrain.qc b/qc/misc/modeltrain.qc
new file mode 100644
index 0000000..f303113
--- /dev/null
+++ b/qc/misc/modeltrain.qc
@@ -0,0 +1,162 @@
+//==============================================================================
+// misc_modeltrain -- was plats.qc
+//==============================================================================
+
+//----------------------------------------------------------------------
+void() animcontroller_think =
+{
+ local float first, last, step, atype, dir, nextframe;
+ local entity tr;
+
+ tr = self.owner;
+
+ // train just went from stopped to moving or vice-versa,
+ // and have both animations set
+ if (self.state != tr.state && tr.style != TRAIN_STYLE_SINGLEANIM)
+ {
+ if (tr.state)
+ {
+ // just started moving
+ tr.frame = zeroconvert (tr.first_frame2);
+ }
+ else
+ {
+ // just stopped
+ tr.frame = zeroconvert (tr.first_frame);
+ }
+ // reset back/forth status
+ tr.distance = 1;
+ self.state = tr.state;
+ }
+ else
+ {
+ if (self.state && tr.style != TRAIN_STYLE_SINGLEANIM)
+ {
+ // moving train animation, if set
+ first = zeroconvert (tr.first_frame2);
+ last = zeroconvert (tr.last_frame2);
+ atype = tr.animtype2;
+ }
+ else
+ {
+ // stopped/default train animation
+ first = zeroconvert (tr.first_frame);
+ last = zeroconvert (tr.last_frame);
+ atype = tr.animtype;
+ }
+
+ if (first > last)
+ // reverse direction
+ step = dir = -1;
+ else
+ step = dir = 1;
+
+ // back-and-forth is going the other way, so invert
+ // the step's signal
+ if (tr.distance < 0)
+ step = step * (-1);
+
+ nextframe = tr.frame + step;
+
+ if (atype == TRAIN_ANIMTYPE_BACKFORTH)
+ {
+ if (dir > 0 && (nextframe > last ||
+ nextframe < first) ||
+ dir < 0 && (nextframe > first ||
+ nextframe < last))
+ {
+ nextframe = tr.frame - step;
+ tr.distance = tr.distance * (-1);
+ }
+ }
+
+ if (dir > 0)
+ nextframe = wrap (nextframe, first, last);
+ else
+ nextframe = wrap (nextframe, last, first);
+
+ tr.frame = nextframe;
+
+ }
+
+ self.think = animcontroller_think;
+ if (self.state || tr.style == TRAIN_STYLE_SINGLEANIM)
+ self.nextthink = time + tr.frtime;
+ else
+ self.nextthink = time + tr.frtime2;
+};
+
+//----------------------------------------------------------------------
+void() misc_modeltrain =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ precache_model (self.mdl);
+
+ func_train ();
+
+ if (self.spawnflags & TRAIN_NONSOLID)
+ {
+ self.solid = SOLID_NOT;
+ }
+ else
+ {
+ self.solid = SOLID_BBOX;
+ if (self.cmins == VEC_ORIGIN)
+ self.cmins = '-8 -8 -8';
+ if (self.cmaxs == VEC_ORIGIN)
+ self.cmaxs = '8 8 8';
+ }
+
+ self.movetype = MOVETYPE_NOCLIP;
+ setmodel (self, self.mdl);
+ setsize (self, self.cmins , self.cmaxs);
+ setorigin (self, self.origin);
+
+ local entity rot, anim;
+
+ rot = spawn ();
+ self.rotatecontroller = rot;
+ rot.classname = "rotatecontroller";
+ rot.owner = self;
+
+ anim = spawn ();
+ self.animcontroller = anim;
+ anim.classname = "animcontroller";
+ anim.owner = self;
+
+ anim.think = animcontroller_think;
+ anim.nextthink = time + 0.2;
+
+ self.distance = 1;
+
+ if (!self.frtime)
+ self.frtime = 0.1;
+ if (!self.frtime2)
+ self.frtime2 = self.frtime;
+ if (!self.multiplier)
+ self.multiplier = 1;
+
+ // make sure all first and last frame fields are filled
+ if (self.first_frame && !self.last_frame)
+ self.last_frame = self.first_frame;
+ else if (!self.first_frame && self.last_frame)
+ self.first_frame = self.last_frame;
+
+ if (self.first_frame2 && !self.last_frame2)
+ self.last_frame2 = self.first_frame2;
+ else if (!self.first_frame2 && self.last_frame2)
+ self.first_frame2 = self.last_frame2;
+
+ if (!self.first_frame2)
+ self.style = TRAIN_STYLE_SINGLEANIM;
+
+ if (!self.animtype)
+ self.animtype = TRAIN_ANIMTYPE_FORWARD;
+ if (!self.animtype2)
+ self.animtype2 = self.animtype;
+
+ self.frame = self.first_frame;
+};

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

Diff qc/misc/particle_stream.qc

diff --git a/qc/misc/particle_stream.qc b/qc/misc/particle_stream.qc
new file mode 100644
index 0000000..7517999
--- /dev/null
+++ b/qc/misc/particle_stream.qc
@@ -0,0 +1,89 @@
+//==============================================================================
+// misc_particle_stream -- from Zerstrorer mod -- dumptruck_ds
+//==============================================================================
+
+//=START PARTICLE-STREAM================================================
+
+//----------------------------------------------------------------------
+void(vector start, vector end, float color1, float color2, float pdensity)
+ Particle_Beam =
+{
+ local vector spray, next;
+ local float dist, loop, clr;
+
+ clr = color1;
+ spray = start - end;
+ dist = vlen (spray);
+ loop = dist / 24;
+ spray = normalize (spray);
+ next = spray * 24;
+
+ while (loop > 0)
+ {
+ particle (end, spray, clr, pdensity);
+ end = end + next;
+ loop = loop - 1;
+ if (clr == color1)
+ clr = color2;
+ else
+ clr = color1;
+ }
+};
+
+//----------------------------------------------------------------------
+void() particle_use =
+{
+ sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
+ // was 40 - too many particles for my taste -- dumptruck_ds
+ Particle_Beam(self.origin, self.enemy.origin, self.dmg, self.cnt, 15);
+};
+
+//----------------------------------------------------------------------
+void() particle_stream_start =
+{
+ local entity pspot;
+
+ pspot = find (world, targetname, self.target);
+
+ if (!pspot)
+ {
+ dprint ("Particle stream can't find target!");
+ return;
+ }
+
+ self.enemy = pspot;
+};
+
+/*QUAKED misc_particle_stream (0 .5 .8) (-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
+A particle stream! It appears when triggered. This entity is
+one end of the stream, target another entity as the other end-point.
+I used the info_notnull, but you should be able to target anything
+(like monsters).
+
+"target" This entities origin is the end-point of the stream
+"dmg" 1st Color - Use if you want a single color stream
+"cnt" 2nd Color - Mixes particles of both colors
+"noise" Sound to play when triggered
+*/
+void() misc_particle_stream =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.target)
+ objerror ("misc_particle_stream with not target!");
+
+ if (!self.dmg)
+ self.dmg = 73;
+ if (!self.cnt)
+ self.cnt = self.dmg;
+ if (!self.noise)
+ self.noise = "misc/null.wav";
+
+ precache_sound(self.noise);
+
+ self.use = particle_use;
+ self.think = particle_stream_start;
+ self.nextthink = time + 0.2;
+};

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

Diff qc/misc/particles.qc

diff --git a/qc/misc/particles.qc b/qc/misc/particles.qc
new file mode 100644
index 0000000..7263432
--- /dev/null
+++ b/qc/misc/particles.qc
@@ -0,0 +1,74 @@
+//==============================================================================
+// misc_particles AKA misc_splash
+// selections from Rubicon 2 qc by john fitzgibbons
+//==============================================================================
+
+//======================================================================
+// misc_particles
+// renamed from misc_splash (Rubcion 2) --dumptruck_ds
+//======================================================================
+
+//----------------------------------------------------------------------
+void() splash_use =
+{
+ if (self.spawnflags & START_OFF)
+ self.spawnflags = self.spawnflags - START_OFF;
+ else
+ self.spawnflags = self.spawnflags + START_OFF;
+};
+
+//----------------------------------------------------------------------
+void() splash_think =
+{
+ if (self.spawnflags & START_OFF)
+ {
+ self.nextthink = time + 0.1;
+ self.think = splash_think;
+ }
+ else
+ {
+ local vector vec;
+ local float variance;
+ variance = vlen(self.movedir) / 2;
+ vec_x = self.movedir_x - variance + random() * variance * 2;
+ vec_y = self.movedir_y - variance + random() * variance * 2;
+ vec_z = self.movedir_z - variance + random() * variance * 2;
+ particle (self.origin, vec, self.color, self.volume);
+ self.nextthink = time + self.wait;
+ }
+};
+
+/*QUAKED misc_particles (0 .5 .8) (-8 -8 -8) (8 8 8) START_OFF 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
+
+Produces a continuous particle splash for waterfalls and other effects
+
+"color" color of particles. 0 through 15, corresponds to a row of the quake palette. (default 0)
+
+"movedir" average movement vector of particles (default 0 0 4)
+
+"wait" time between particle generation cycles. (default 0.1)
+
+"volume" density of particles. (default 10)
+
+
+*/
+void() misc_particles =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.wait)
+ self.wait = 0.1;
+
+ if (!self.movedir)
+ self.movedir = '0 0 4';
+
+ if (!self.volume)
+ self.volume = 10;
+
+ self.color = self.color * 16;
+ self.use = splash_use;
+ self.nextthink = time + self.wait;
+ self.think = splash_think;
+};

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

Diff qc/misc/particlespray.qc

diff --git a/qc/misc/particlespray.qc b/qc/misc/particlespray.qc
new file mode 100644
index 0000000..864665c
--- /dev/null
+++ b/qc/misc/particlespray.qc
@@ -0,0 +1,76 @@
+//==============================================================================
+// misc_particlespray
+//==============================================================================
+
+//======================================================================
+// Particle Sprayer
+// this is from Custents not Rubicon2 -- dumptruck_ds
+// renamed from func to misc
+//======================================================================
+
+// fields
+.float endtime;
+.float duration;
+
+//----------------------------------------------------------------------
+void() partspray_think =
+{
+ particle (self.origin, self.movedir, self.color, self.count);
+
+ if (!self.targetname || self.endtime > time)
+ self.nextthink = time + self.delay;
+
+ if (self.noise != "")
+ sound (self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
+ else
+ sound (self, CHAN_AUTO, "misc/null.wav", 1, ATTN_NORM);
+};
+
+//----------------------------------------------------------------------
+void() partspray_use =
+{
+ self.endtime = time + self.duration;
+ partspray_think ();
+};
+
+/*QUAKED misc_particlespray (0 .5 .8) (-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
+Shoots particles either when triggered, or contiuously when not triggered by anything.
+"color" is the palette color of the particles
+
+"count" is the number of particles to make each time
+
+"delay" is the delay between each triggering
+
+"noise" is the name of the wav file to play when triggered
+
+"movedir" is the vector distance that the particles will travel before disappearing. (in x y z)
+
+"duration" is the amount of time that the it will continue to release particles so that it can release a long stream of particles with only one triggering.
+*/
+void() misc_particlespray =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.color)
+ self.color = 47;
+
+ if (self.count <= 0)
+ self.count = 15;
+
+ if (self.delay <= 0)
+ self.delay = 0.1;
+
+ if (self.noise != "")
+ precache_sound (self.noise);
+ precache_sound ("misc/null.wav");
+
+ self.classname = "particlespray";
+ self.think = partspray_think;
+
+ if (!self.targetname)
+ self.nextthink = time + 0.1 + self.delay;
+ else
+ self.use = partspray_use;
+};

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

Diff qc/misc/sparks.qc

diff --git a/qc/misc/sparks.qc b/qc/misc/sparks.qc
new file mode 100644
index 0000000..5685b0b
--- /dev/null
+++ b/qc/misc/sparks.qc
@@ -0,0 +1,160 @@
+//==============================================================================
+// misc_sparks -- selections from Rubicon 2 qc by john fitzgibbons
+//==============================================================================
+
+// prototypes
+void() make_sparks;
+
+//----------------------------------------------------------------------
+void() sparks_fade1 = [0, sparks_fade2]
+{
+ self.alpha = 0.8; self.nextthink = time + 0.05;
+};
+
+//----------------------------------------------------------------------
+void() sparks_fade2 = [0, sparks_fade3]
+{
+ self.alpha = 0.6; self.nextthink = time + 0.05;
+};
+
+//----------------------------------------------------------------------
+void() sparks_fade3 = [0, sparks_fade4]
+{
+ self.alpha = 0.4; self.nextthink = time + 0.05;
+};
+
+//----------------------------------------------------------------------
+void() sparks_fade4 = [0, SUB_Remove]
+{
+ self.alpha = 0.2; self.nextthink = time + 0.05;
+};
+
+//----------------------------------------------------------------------
+void() sparks_use =
+{
+ if (self.spawnflags & START_OFF)
+ self.spawnflags = self.spawnflags - START_OFF;
+ else
+ self.spawnflags = self.spawnflags + START_OFF;
+};
+
+//----------------------------------------------------------------------
+void() spark_turnofflight =
+{
+ SUB_UseTargets ();
+ self.think = make_sparks;
+ self.nextthink = time + (random() + 0.5) * self.wait - 0.15;
+};
+
+//----------------------------------------------------------------------
+void() make_sparks =
+{
+
+ if (self.spawnflags & START_OFF)
+ {
+ self.nextthink = time + 0.1;
+ self.think = make_sparks;
+ }
+ else
+ {
+ local float i;
+ i = -0.25 * self.cnt + random() * 0.5 * self.cnt;
+ while (i < self.cnt)
+ {
+
+ local entity spark;
+ spark = spawn ();
+ spark.owner = self;
+ setmodel (spark, "progs/spark.mdl");
+ setorigin (spark, self.origin);
+ spark.movetype = MOVETYPE_BOUNCE;
+ spark.solid = SOLID_TRIGGER;
+ spark.gravity = 0.3;
+ spark.velocity_x = -40 + random() * 80;
+ spark.velocity_y = -40 + random() * 80;
+ spark.velocity_z = -40 + random() * 80;
+ spark.avelocity = '3000 3000 3000';
+ spark.nextthink = time + 0.5 + 1.5 * random();
+ spark.think = sparks_fade1;
+ spark.classname = "spark";
+
+ if (random() < 0.33)
+ spark.skin = 0;
+ else if (random() < 0.5)
+ spark.skin = 1;
+ else
+ spark.skin = 2;
+
+ if (self.spawnflags & SPARKS_PALE)
+ spark.skin = spark.skin + 6;
+ else if (self.spawnflags & SPARKS_BLUE)
+ spark.skin = spark.skin + 3;
+
+ setsize (spark, '0 0 0', '0 0 0');
+ i = i + 1;
+ }
+
+ if (self.sounds == 1)
+ {
+ if (self.noise != "")
+ {
+ sound (self, CHAN_AUTO, self.noise,
+ 1, ATTN_STATIC);
+ }
+ else
+ {
+ sound (self, CHAN_AUTO, "enforcer/enfstop.wav",
+ 1, ATTN_STATIC);
+ }
+ }
+
+ SUB_UseTargets ();
+ self.nextthink = time + 0.1 + random() * 0.1;
+ self.think = spark_turnofflight;
+ }
+};
+
+/*QUAKED misc_sparks (0 .5 .8) (-8 -8 -8) (8 8 8) START_OFF SPARKS_BLUE SPARKS_PALE 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
+
+Produces a burst of yellow sparks at random intervals. If targeted, it will toggle between on or off. If it targets a light, that light will flash allong with each burst of sparks. Note: targeted lights should be set to START_OFF.
+
+SPARKS_BLUE: sparks are blue in color
+
+SPARKS_PALE: sparks are pale yellow in color
+
+Keys:
+
+"wait" is the average delay between bursts (variance is 1/2 wait). Default is 2.
+
+"cnt" is the average number of sparks in a burst (variance is 1/4 cnt). Default is 15.
+
+"sounds"
+0) no sound
+1) sparks
+*/
+void() misc_sparks =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ precache_model ("progs/spark.mdl");
+
+ if (!self.noise)
+ precache_sound ("dump/spark.wav");
+ else
+ precache_sound (self.noise);
+
+ if (!self.movedir)
+ self.movedir = '0 0 -30';
+
+ if (!self.wait)
+ self.wait = 2;
+
+ if (!self.cnt)
+ self.cnt = 15;
+
+ self.use = sparks_use;
+ self.nextthink = time + random() * 0.1;
+ self.think = make_sparks;
+};

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

Diff qc/misc/teleporttrain.qc

diff --git a/qc/misc/teleporttrain.qc b/qc/misc/teleporttrain.qc
new file mode 100644
index 0000000..032363d
--- /dev/null
+++ b/qc/misc/teleporttrain.qc
@@ -0,0 +1,158 @@
+//==============================================================================
+// misc_teleporttrain -- was plats.qc
+// Code for the fixed teleporttrain written by c0burn and modified by ZungryWare
+//==============================================================================
+
+// prototypes
+void() teleporttrain_calcmove;
+
+//----------------------------------------------------------------------
+void() teleporttrain_next =
+{
+ local vector dir;
+
+ setorigin (self, self.enemy.origin + '16 16 16');
+
+ if (!self.target)
+ {
+ self.enemy = world;
+ return;
+ }
+
+ self.enemy = find (world, targetname, self.target);
+ if (self.enemy.classname == "path_corner")
+ {
+ dir = normalize ((self.enemy.origin + '16 16 16') -
+ self.origin);
+ self.velocity = dir * self.speed;
+ self.target = self.enemy.target;
+ }
+ else
+ {
+ objerror ("unable to find target\n");
+ remove (self);
+ }
+
+ teleporttrain_calcmove ();
+};
+
+//----------------------------------------------------------------------
+void() teleporttrain_wait =
+{
+ local float wait_time;
+
+ if (self.enemy.wait > 0)
+ wait_time = self.enemy.wait;
+ else
+ wait_time = 0.1;
+
+ self.velocity = '0 0 0';
+ self.nextthink = time + wait_time;
+ self.think = teleporttrain_next;
+};
+
+//----------------------------------------------------------------------
+void() teleporttrain_calcmove =
+{
+ local vector delta;
+ local float len, spd;
+
+ delta = (self.enemy.origin + '16 16 16') - self.origin;
+ len = vlen (delta);
+ spd = vlen (self.velocity);
+ self.nextthink = time + (len / spd);
+ self.think = teleporttrain_wait;
+};
+
+//----------------------------------------------------------------------
+void() teleporttrain_use =
+{
+ if (self.velocity == '0 0 0')
+ teleporttrain_next ();
+};
+
+//----------------------------------------------------------------------
+void() teleporttrain_find =
+{
+ // always start positioned on the first path_corner
+ self.enemy = find (world, targetname, self.target);
+ if (self.enemy.classname == "path_corner")
+ {
+ setorigin (self, self.enemy.origin + '16 16 16');
+ self.target = self.enemy.target;
+ }
+ else
+ {
+ objerror ("unable to find target\n");
+ remove (self);
+ return;
+ }
+
+ if (self.spawnflags & 4)
+ // start immediately even with a targetname
+ teleporttrain_next ();
+ else if (!self.targetname)
+ // not triggered, so start immediately
+ teleporttrain_next ();
+ else
+ self.use = teleporttrain_use;
+};
+
+/*QUAKED misc_teleporttrain (.5 .5 .5) (-16 -16 -16) (16 16 16) X DONT_ROTATE START_ON_WITH_TARGETNAME INVISIBLE 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
+{ model("progs/teleport.mdl"); }
+This was used for the final boss level in the original game. In progs_dump you can use this as a moving decoration or even target it as a spawn point for a func_monster_spawner. Make sure and select the Don't Rotate spawnflag though or you'll experience a pretty hilarious effect!
+
+You set this up like a func_train using path_corners. By default, it will move automatically between path corners upon map load. However, you can have it wait to move by giving it a targetname. If you need to target it as a spawner and want it to move on map load, use the Start On spawnflag.
+
+You can add effects, use a custom model using the mdl_body keyvalue and even make it invisible with spawnflag 8.
+
+Effects
+0: "None (Default)"
+1 : "Brightfield (yellow particles)"
+4 : "Bright light"
+8 : "Dim light"
+
+
+Teleporter target for final boss level. Must target a series of 'path_corner' entities.
+It will position itself on its first target at map load.
+If a targetname is set, it must be triggered to start moving, otherwise it will start automatically.
+*/
+void() misc_teleporttrain =
+{
+ // new spawnflags for all entities -- iw
+ if (SUB_Inhibit())
+ return;
+
+ if (!self.target)
+ {
+ objerror ("misc_teleporttrain has no target");
+ remove (self);
+ return;
+ }
+
+ if (self.speed <= 0)
+ self.speed = 100;
+
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_FLY;
+ // custom custom_mdls -- dumptruck_ds
+ precache_body_model ("progs/teleport.mdl");
+ // invisble -- dumptruck_ds
+ precache_model ("progs/s_null.spr");
+ if (self.spawnflags & 8)
+ // setmodel (self, "progs/s_null.spr");
+ body_model ("progs/s_null.spr");
+ else
+ body_model ("progs/teleport.mdl");
+ // precache_model ("progs/teleport.mdl");
+ setsize (self, '-16 -16 -16', '16 16 16');
+
+ // Causes the ball to spin around like it was originally intended to.
+ if (!(self.spawnflags & 2))
+ // don't spin - helpful for invisible spawner -- dumptruck_ds
+ self.avelocity = '40 80 120';
+ // self.avelocity = '100 200 300';
+
+ self.think = teleporttrain_find;
+ self.nextthink = time + 0.1;
+};

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

Diff qc/mobot.qc

diff --git a/qc/mobot.qc b/qc/mobot.qc
deleted file mode 100644
index f0bf1a5..0000000
--- a/qc/mobot.qc
+++ /dev/null
@@ -1,500 +0,0 @@
-// Using "bot" creation code for func_monster_spawner
-// most of the code is from a tutorial on creating a bot monster found here:
-// https://www.quaddicted.com/webarchive/minion.planetquake.gamespy.com/tutorial/tutor9.htm
-// I added the MobotSpawnPoint, retriggering and random gen with help from
-// kreathor, 4LT, Paril, Spoike and others on the Quake Mapping Discord.
-// ===================================================================
-// Big thanks to ryanscissorhands for helping fix telefragging issues!
-// ===================================================================
-
-float MOBOT_SPAWNER_RESET = 1;
-float MOBOT_DONT_SPAWN_ANGRY = 2;
-float MOBOT_DONT_ADD_KILL_COUNT = 4;
-float MOBOT_SILENT_SPAWN = 32;
-
-/*
-============
-MobotSpawnPoint
-
-Returns the entity to spawn at
-============
-*/
-entity() MobotSpawnPoint =
-{
- local entity spot;
-
- // spot = find (world, classname, "info_monster_spawnpoint");
- spot = find (world, targetname, self.target);
-
- if (!spot)
- objerror ("couldn't find target");
-
- return spot;
-};
-
-// ------------------------------------------------
-void() create_mobot =
-// ------------------------------------------------
-{
-
-local entity bot, spawn_spot;
-
-// start entity and place it in world
- bot = spawn();
- spawn_spot = MobotSpawnPoint();
- // spawn_spot = SelectSpawnPoint (); // let's not use deathmatch points for this -- dumptruck_ds
- bot.origin = spawn_spot.origin + '0 0 1';
- bot.angles = spawn_spot.angles;
- bot.fixangle = TRUE;
- bot.proj_speed_mod = 1;
- if (!(self.spawnflags & MOBOT_SILENT_SPAWN)) // SILENT
- spawn_tfog (bot.origin);
- spawn_tdeath (bot.origin, bot);
-
- if (self.style == 1) // spawn a Doggo
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/dog.mdl");
- setsize (bot, '-32 -32 -24', '32 32 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = dog_stand1;
- bot.th_walk = dog_walk1;
- bot.th_run = dog_run1;
- bot.th_die = dog_die;
- bot.th_melee = dog_atta1;
- bot.th_missile = dog_leap1;
- if !(self.berserk) //Berserk test from http://celephais.net/board/view_thread.php?id=4&start=3465 -- dumptruck_ds
- bot.th_pain = dog_pain;
- else
- bot.th_pain = SUB_NullPain;
- bot.health = 25;
-
- // polish him up
- bot.classname = "monster_dog";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- }
-
-if (self.style == 2) // spawn a Grunt
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/soldier.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = army_stand1;
- bot.th_walk = army_walk1;
- bot.th_run = army_run1;
- bot.th_die = army_die;
- // bot.th_melee = ogre_melee;
- bot.th_missile = army_atk1;
- if !(self.berserk) //Berserk test from http://celephais.net/board/view_thread.php?id=4&start=3465 -- dumptruck_ds
- bot.th_pain = army_pain;
- else
- bot.th_pain = SUB_NullPain;
- bot.health = 80;
-
- // polish him up
- bot.classname = "monster_army";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- }
-
-if (self.style == 3) // spawn an Enforcer
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/enforcer.mdl");
- setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = enf_stand1;
- bot.th_walk = enf_walk1;
- bot.th_run = enf_run1;
- bot.th_die = enf_die;
- // bot.th_melee = ogre_melee;
- bot.th_missile = enf_atk1;
- if !(self.berserk) //Berserk test from http://celephais.net/board/view_thread.php?id=4&start=3465 -- dumptruck_ds
- bot.th_pain = enf_pain;
- else
- bot.th_pain = SUB_NullPain;
- bot.health = 80;
-
- // polish him up
- bot.classname = "monster_enforcer";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- }
-
-if (self.style == 4) // spawn an Ogre
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/ogre.mdl");
- setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = ogre_stand1;
- bot.th_walk = ogre_walk1;
- bot.th_run = ogre_run1;
- bot.th_die = ogre_die;
- bot.th_melee = ogre_melee;
- bot.th_missile = ogre_nail1;
- if !(self.berserk) //Berserk test from http://celephais.net/board/view_thread.php?id=4&start=3465 -- dumptruck_ds
- bot.th_pain = ogre_pain;
- else
- bot.th_pain = SUB_NullPain;
- bot.health = 200;
-
- // polish him up
- bot.classname = "monster_ogre";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- }
-
-if (self.style == 5) // spawn an Fiend
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/demon.mdl");
- setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = demon1_stand1;
- bot.th_walk = demon1_walk1;
- bot.th_run = demon1_run1;
- bot.th_die = demon_die;
- bot.th_melee = Demon_MeleeAttack; // one of two attacks
- bot.th_missile = demon1_jump1; // jump attack
- if !(self.berserk) //Berserk test from http://celephais.net/board/view_thread.php?id=4&start=3465 -- dumptruck_ds
- bot.th_pain = demon1_pain;
- else
- bot.th_pain = SUB_NullPain;
- bot.health = 300;
-
- // polish him up
- bot.classname = "monster_demon1";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- }
-
-if (self.style == 6) // spawn a Wizard / Scrag
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/wizard.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_FLY;
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = wiz_stand1;
- bot.th_walk = wiz_walk1;
- bot.th_run = wiz_run1;
- bot.th_die = wiz_die;
- bot.th_missile = Wiz_Missile;
- if !(self.berserk) //Berserk test from http://celephais.net/board/view_thread.php?id=4&start=3465 -- dumptruck_ds
- bot.th_pain = Wiz_Pain;
- else
- bot.th_pain = SUB_NullPain;
- bot.health = 80;
-
- // polish him up
- bot.classname = "monster_wizard";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- bot.mdl_proj = "progs/w_spike.mdl";
-
- }
-
- if (self.style == 7) // spawn a Shambler
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/shambler.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = sham_stand1;
- bot.th_walk = sham_walk1;
- bot.th_run = sham_run1;
- if !(self.berserk) //Berserk test from http://celephais.net/board/view_thread.php?id=4&start=3465 -- dumptruck_ds
- bot.th_pain = sham_pain;
- else
- bot.th_pain = SUB_NullPain;
- bot.th_die = sham_die;
- bot.th_missile = sham_magic1;
- bot.th_melee = sham_melee;
- bot.health = 600;
-
- // polish him up
- bot.classname = "monster_shambler";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 2';
- // bot.view_ofs = '0 0 22';
- }
-
-if (self.style == 8) // spawn a Knight
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/knight.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = knight_stand1;
- bot.th_walk = knight_walk1;
- bot.th_run = knight_run1;
- bot.th_die = knight_die;
- bot.th_melee = knight_atk1;
- // bot.th_missile = knight_atk1;
- if !(self.berserk) //Berserk test from http://celephais.net/board/view_thread.php?id=4&start=3465 -- dumptruck_ds
- bot.th_pain = knight_pain;
- else
- bot.th_pain = SUB_NullPain;
- bot.health = 75;
-
- // polish him up
- bot.classname = "monster_knight";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- }
-
-if (self.style == 9) // spawn a HellKnight
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/hknight.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = hknight_stand1;
- bot.th_walk = hknight_walk1;
- bot.th_run = hknight_run1;
- bot.th_melee = hknight_melee;
- bot.th_die = hknight_die;
- bot.th_missile = hknight_magicc1;
- if !(self.berserk) //Berserk test from http://celephais.net/board/view_thread.php?id=4&start=3465 -- dumptruck_ds
- bot.th_pain = hknight_pain;
- else
- bot.th_pain = SUB_NullPain;
- bot.health = 250;
-
- // polish him up
- bot.classname = "monster_hell_knight";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- }
-
-if (self.style == 11) // spawn a Zombie
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/zombie.mdl");
- setsize (bot, '-16 -16 -24', '16 16 40');
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = zombie_start;
- bot.th_walk = zombie_walk1;
- bot.th_run = zombie_decide;
- bot.th_pain = zombie_pain;
- bot.th_die = zombie_die;
- bot.th_missile = zombie_missile;
- bot.health = 61;
-
- // polish him up
- bot.classname = "monster_zombie";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 2';
- // bot.view_ofs = '0 0 22';
- }
-if (self.style == 12) // spawn a Shalrath
- {
- // set size and shape
- bot.solid = SOLID_SLIDEBOX;
- bot.movetype = MOVETYPE_STEP;
- setmodel(bot, "progs/shalrath.mdl");
- setsize (bot, VEC_HULL2_MIN, VEC_HULL2_MAX);
- bot.flags = bot.flags | FL_MONSTER;
- bot.takedamage = DAMAGE_AIM;
-
- // define his animation
- bot.th_stand = shal_stand;
- bot.th_walk = shal_walk1;
- bot.th_run = shal_run1;
- bot.th_die = shalrath_die;
- bot.th_missile = shal_attack1;
- bot.homing = 1; //fix for func_monster_spawner setting Voreballs to non-homing
- if !(self.berserk) //Berserk test from http://celephais.net/board/view_thread.php?id=4&start=3465 -- dumptruck_ds
- bot.th_pain = shalrath_pain;
- else
- bot.th_pain = SUB_NullPain;
- bot.health = 400;
-
- // polish him up
- bot.classname = "monster_shalrath";
- bot.ideal_yaw = bot.angles * '0 1 0';
- bot.yaw_speed = 120;
- bot.view_ofs = '0 0 22';
- }
-
-// begin his thinking
- bot.nextthink = time + 0.2; // this seems better with monster_use -- dumptruck_ds
- // bot.nextthink = time + 0.1 + random();
- if (!(self.spawnflags & MOBOT_DONT_SPAWN_ANGRY))
- {
- if (bot.classname != "monster_zombie") // required to avoid animation issues -- dumptruck_ds
- bot.think = monster_use;
- else
- bot.think = bot.th_walk;
- }
- else
- {
- bot.think = walkmonster_start_go;
- }
- if (!(self.spawnflags & MOBOT_DONT_ADD_KILL_COUNT))
- {
- monster_update_total (1); // repacement function from iw -- dumptruck_ds
- }
-};
-
-void() think_mobot =
- {
- dprint("mobot thinking\n");
- local entity nearby; // telefrag check thanks to ryanscissorhands for this code! -- dumptruck_ds
-
- nearby = findradius(self.origin, 128); // findradius (vector origin, float radius in Quake units)
-
- while (nearby)
- {
- if (nearby.takedamage)
- {
- dprint("monster waiting to spawn\n");
- self.think = think_mobot; // qss crash fix from paavohuhtala -- dumptruck_ds
- self.nextthink = time + 1; //delay the spawn by some amount;
- return;
- }
- nearby = nearby.chain;
- }
-
- self.count = self.count - 1;
-
- if (self.count < 0)
- {
- return;
- }
- if (self.count!=0)
- {
- if !(self.wait)
- self.nextthink = time + 5;
- else
- self.nextthink = time + self.wait;
-
- if (self.style2 == 1)
- {
- self.style = floor(random() * 12) + 1; // random monster!! -- dumptruck_ds
- create_mobot(); //thanks whirledtsar for your help on this -- dumptruck_ds
- }
- else
- create_mobot();
- }
- else {
- if (self.spawnflags & MOBOT_SPAWNER_RESET)
- {
- self.count = self.cnt;
- self.think = SUB_Null;
- }
- }
-
- self.think = think_mobot; // qthink I didn't realize I could do this! -- dumptruck_ds
- };
-
-/*QUAKED func_monster_spawner (.75 0 .75) (-8 -8 -8) (8 8 8) REUSABLE 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
-Spawns monsters to targeted info_monster_spawnpoint
-bot
-Choose Style
-• 1 (Dog (Default)
-• 2 (Grunt)
-• 3 (Enforcer)
-• 4 (Ogre)
-• 5 (Fiend)
-• 6 (Wizard)
-• 7 (Shambler)
-• 8 (Knight)
-• 9 (HellKnight)
-• 10 (Spawn)
-• 11 (Zombie)
-• 12 (Shalrath)
-
-Style 2 set to 1 overrides Style and chooses a random monster (excluding Zombies and Vores)
-
-Default time between spawns is 5 seconds; 12 for Zombies and Vores to reduce telefrags
-
-Can set Berserk to 1 to skip most pain animations.
-
-Can only use default health, models and sounds.
-*/
-void() func_monster_spawner =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if !(self.target)
- {
- objerror("func_monster_spawner needs a target");
- remove(self);
- return;
- }
-
- if !(self.style)
- self.style = 1;
-
- if (!self.count)
- self.count = 5;
- self.count = self.count + 1; // fixes count display
- self.cnt = self.count; // hold original count
-
- self.use = think_mobot;
-};

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

Diff qc/newflags.qc

diff --git a/qc/newflags.qc b/qc/newflags.qc
index 07d8ff5..a7ac7ba 100644
--- a/qc/newflags.qc
+++ b/qc/newflags.qc
@@ -56,12 +56,11 @@ affecting the other.
========================================================================
*/

-
// The new spawnflags. (16384 is already used elsewhere.)
-float SPAWNFLAG_NOT_IN_COOP = 4096; // Not in Coop
-float SPAWNFLAG_NOT_IN_SP = 8192; // Not in Single Player
-float SPAWNFLAG_NOT_ON_SKILL2 = 32768; // Not on Hard Only
-float SPAWNFLAG_NOT_ON_SKILL3 = 65536; // Not on Nightmare Only
+const float SPAWNFLAG_NOT_IN_COOP = 4096; // Not in Coop
+const float SPAWNFLAG_NOT_IN_SP = 8192; // Not in Single Player
+const float SPAWNFLAG_NOT_ON_SKILL2 = 32768; // Not on Hard Only
+const float SPAWNFLAG_NOT_ON_SKILL3 = 65536; // Not on Nightmare Only

// The number of entities inhibited by each of the new spawnflags.
float total_not_in_coop;
@@ -72,7 +71,6 @@ float total_not_on_skill3;
// TRUE if the developer summary has been printed.
float done_inhibition_summary;

-
/*
================
InitNewSpawnflags
@@ -97,7 +95,6 @@ void() InitNewSpawnflags =
skill = cvar ("skill");
};

-
/*
================
SUB_Inhibit
@@ -152,7 +149,6 @@ float() SUB_Inhibit =
return FALSE;
};

-
/*
================
PrintInhibitionTotal
@@ -174,7 +170,6 @@ void(float total, string spawnflag_name) PrintInhibitionTotal =
dprint ("' spawnflag\n");
};

-
/*
================
PrintInhibitionSummary

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
deleted file mode 100644
index 650c375..0000000
--- a/qc/plats.qc
+++ /dev/null
@@ -1,789 +0,0 @@
-
-
-void() plat_center_touch;
-void() plat_outside_touch;
-void() plat_trigger_use;
-void() plat_go_up;
-void() plat_go_down;
-void() plat_crush;
-float PLAT_LOW_TRIGGER = 1;
-
-void() plat_spawn_inside_trigger =
-{
- local entity trigger;
- local vector tmin, tmax;
-
-//
-// middle trigger
-//
- trigger = spawn();
- trigger.touch = plat_center_touch;
- trigger.movetype = MOVETYPE_NONE;
- trigger.solid = SOLID_TRIGGER;
- trigger.enemy = self;
-
- tmin = self.mins + '25 25 0';
- tmax = self.maxs - '25 25 -8';
- tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
- if (self.spawnflags & PLAT_LOW_TRIGGER)
- tmax_z = tmin_z + 8;
-
- if (self.size_x <= 50)
- {
- tmin_x = (self.mins_x + self.maxs_x) / 2;
- tmax_x = tmin_x + 1;
- }
- if (self.size_y <= 50)
- {
- tmin_y = (self.mins_y + self.maxs_y) / 2;
- tmax_y = tmin_y + 1;
- }
-
- setsize (trigger, tmin, tmax);
-};
-
-void() plat_hit_top =
-{
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_TOP;
- self.think = plat_go_down;
- self.nextthink = self.ltime + 3;
-};
-
-void() plat_hit_bottom =
-{
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
- self.state = STATE_BOTTOM;
-};
-
-void() plat_go_down =
-{
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- self.state = STATE_DOWN;
- SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom);
-};
-
-void() plat_go_up =
-{
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- self.state = STATE_UP;
- SUB_CalcMove (self.pos1, self.speed, plat_hit_top);
-};
-
-void() plat_center_touch =
-{
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
- self = self.enemy;
- if (self.state == STATE_BOTTOM)
- plat_go_up ();
- else if (self.state == STATE_TOP)
- self.nextthink = self.ltime + 1; // delay going down
-};
-
-void() plat_outside_touch =
-{
- // from Copper -- dumptruck_ds
- if (!CheckValidTouch()) return;
-
-//dprint ("plat_outside_touch\n");
- self = self.enemy;
- if (self.state == STATE_TOP)
- plat_go_down ();
-};
-
-void() plat_trigger_use =
-{
- if (self.think)
- return; // allready activated
- plat_go_down();
-};
-
-
-void() plat_crush =
-{
-//dprint ("plat_crush\n");
-
- T_Damage (other, self, self, 1);
-
- if (self.state == STATE_UP)
- plat_go_down ();
- else if (self.state == STATE_DOWN)
- plat_go_up ();
- else
- objerror ("plat_crush: bad self.state\n");
-};
-
-void() plat_use =
-{
- self.use = SUB_Null;
- if (self.state != STATE_UP)
- objerror ("plat_use: not in up state");
- plat_go_down();
-};
-
-
-/*QUAKED func_plat (0 .5 .8) ? PLAT_LOW_TRIGGER 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
-
-speed default 150
-
-Plats are always drawn in the extended position, so they will light correctly.
-
-If the plat is the target of another trigger or button, it will start out disabled in the extended position until it is trigger, when it will lower and become a normal plat.
-
-If the "height" key is set, that will determine the amount the plat moves, instead of being implicitly determined by the model's height.
-Set "sounds" to one of the following:
-1) base fast
-2) chain slow
-*/
-
-
-void() func_plat =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (!self.t_length)
- self.t_length = 80;
- if (!self.t_width)
- self.t_width = 10;
-
- if (self.sounds == 0)
- self.sounds = 2;
-// FIX THIS TO LOAD A GENERIC PLAT SOUND
-
- if (self.sounds == 1)
- {
- precache_sound ("plats/plat1.wav");
- precache_sound ("plats/plat2.wav");
- self.noise = "plats/plat1.wav";
- self.noise1 = "plats/plat2.wav";
- }
-
- if (self.sounds == 2)
- {
- precache_sound ("plats/medplat1.wav");
- precache_sound ("plats/medplat2.wav");
- self.noise = "plats/medplat1.wav";
- self.noise1 = "plats/medplat2.wav";
- }
-
-
- self.mangle = self.angles;
- self.angles = '0 0 0';
-
- self.classname = "plat";
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- setorigin (self, self.origin);
- setmodel (self, self.model);
- setsize (self, self.mins , self.maxs);
-
- self.blocked = plat_crush;
- if (!self.speed)
- self.speed = 150;
-
-// pos1 is the top position, pos2 is the bottom
- self.pos1 = self.origin;
- self.pos2 = self.origin;
- if (self.height)
- self.pos2_z = self.origin_z - self.height;
- else
- self.pos2_z = self.origin_z - self.size_z + 8;
-
- self.use = plat_trigger_use;
-
- plat_spawn_inside_trigger (); // the "start moving" trigger
-
- if (self.targetname != "")
- {
- self.state = STATE_UP;
- self.use = plat_use;
- }
- else
- {
- setorigin (self, self.pos2);
- self.state = STATE_BOTTOM;
- }
-};
-
-//============================================================================
-// TRAINS
-//============================================================================
-void() train_next;
-void() func_train_find;
-
-float TRAIN_RETRIGGER = 1;
-float TRAIN_MOVEONTRIGGER = 2;
-float TRAIN_STOPONTRIGGER = 4;
-float TRAIN_NONSOLID = 8;
-float TRAIN_NOROTATE = 16;
-float TRAIN_ROTATEY = 32;
-float TRAIN_CUSTOMALIGN = 64;
-
-float TRAIN_NEXT_WAIT = 0; //normal movement
-float TRAIN_NEXT_STOP = 1; // force a stop on the next path_corner
-float TRAIN_NEXT_CONTINUE = 2; // force continue on the next path_corner (ignores wait time)
-
-float TRAIN_STYLE_SINGLEANIM = 1;
-
-float TRAIN_ANIMTYPE_FORWARD = 1;
-float TRAIN_ANIMTYPE_BACKFORTH = 2;
-
-void() train_blocked = {
- if (time < self.attack_finished) return;
-
- self.attack_finished = time + 0.5;
- T_Damage (other, self, self, self.dmg);
-};
-
-
-// Use function for when the train is stopped.
-// Makes the train continue on path_corners with wait -1,
-// or forces a continue if the "move on trigger" spawnflag is set.
-void() train_use = {
-
- if (self.spawnflags & TRAIN_MOVEONTRIGGER || self.wait < 0) {
- train_next();
- return;
- }
-
- // Train has already moved after startup, and has no "stop on trigger" flag,
- // so ignore activation.
- if (self.think != func_train_find && self.cnt != TRAIN_NEXT_STOP)
- return;
-
- train_next();
-};
-
-// Use function for when the train is moving.
-// Forces a stop or an instant continue on the next path_corner depending on the spawnflag set
-void() train_moving_use = {
- if (self.spawnflags & TRAIN_MOVEONTRIGGER || self.wait < 0)
- self.cnt = TRAIN_NEXT_CONTINUE;
- else if (self.spawnflags & TRAIN_STOPONTRIGGER)
- self.cnt = TRAIN_NEXT_STOP;
-}
-
-// path_corner has been reached, so decide what to do next
-void() train_wait = {
- float localtime;
- if (self.movetype == MOVETYPE_PUSH) localtime = self.ltime;
- else localtime = time;
-
- self.use = train_use; //ready to be re-triggered
-
- // from Copper
- // Trains now fire their path_corners' targets on arrival.
- // If a player is riding the train, treat them as activator.
- activator = nextent(world);
- while (!EntitiesTouching(self,activator) && activator.classname == "player")
- activator = nextent(activator);
- if (activator.classname != "player")
- activator = nextent(world); // default to player1 wherever they are
- SUB_UseEntTargets(self.enemy);
-
- if (self.enemy.speed) self.speed2 = self.enemy.speed; // sets the speed from the current path_corner
-
- // copies the modeltrain animation parameters set in the path_corner, if any
- if (self.classname == "misc_modeltrain") {
- if (self.enemy.first_frame) self.first_frame = self.enemy.first_frame;
- if (self.enemy.last_frame) self.last_frame = self.enemy.last_frame;
- if (self.enemy.first_frame2) self.first_frame2 = self.enemy.first_frame2;
- if (self.enemy.last_frame2) self.last_frame2 = self.enemy.last_frame2;
- if (self.enemy.frtime) self.frtime = self.enemy.frtime;
- if (self.enemy.frtime2) self.frtime2 = self.enemy.frtime2;
- if (self.enemy.animtype) self.animtype = self.enemy.animtype;
- if (self.enemy.animtype2) self.animtype2 = self.enemy.animtype2;
- if (self.enemy.multiplier) self.multiplier = self.enemy.multiplier;
- }
-
- self.think = train_next;
-
- // train is moving normally and path_corner has a wait set, so pause for that time.
- if (self.wait > 0 && self.cnt == TRAIN_NEXT_WAIT && !(self.spawnflags & TRAIN_RETRIGGER)) {
- // state: stopped
- self.state = 0;
- if (self.classname == "misc_modeltrain") SUB_CallAsSelf(self.animcontroller.think, self.animcontroller);
- self.nextthink = localtime + self.wait;
-
- //play stopping sound. If path_corner has a custom sound, play that instead
- if (self.enemy.noise != "") sound(self, CHAN_WEAPON, self.enemy.noise, 1, ATTN_NORM);
- else sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
- }
- // train is moving normally and path_corner has no wait time,
- // or has been forced to move instantly through a triggering.
- else if (self.cnt != TRAIN_NEXT_STOP && !self.wait && !(self.spawnflags & TRAIN_RETRIGGER)) {
-
- //play "passing by" sound, if any. If path_corner has a custom one, play that instead
- if (self.enemy.noise2 != "") sound(self, CHAN_WEAPON, self.enemy.noise2, 1, ATTN_NORM);
- else if (self.noise2 != "") sound(self, CHAN_WEAPON, self.noise2, 1, ATTN_NORM);
-
- self.nextthink = -1; // move instantly
- train_next();
- }
- // path_corner has wait -1, or train has been forced to stop through a triggering.
- // Also catches the backwards compatible case for the original rubicon2 "retrigger" flag.
- else {
- //play stopping sound. If path_corner has a custom sound, play that instead
- if (self.enemy.noise != "") sound(self, CHAN_WEAPON, self.enemy.noise, 1, ATTN_NORM);
- else sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
-
- // state: stopped
- self.state = 0;
-
- if (self.classname == "misc_modeltrain") SUB_CallAsSelf(self.animcontroller.think, self.animcontroller);
- self.nextthink = -1;
- }
-
-
-};
-
-// searches for the next path_corner and sends the train on its way
-void() train_next = {
- local entity targ;
- vector destang, displ;
-
- destang = displ = '0 0 0';
-
- targ = find(world, targetname, self.target);
-
- if (!targ || self.target == "")
- objerror("train_next: no next target");
-
- self.target = targ.target;
-
- // gets the wait time from the upcoming path_corner if set
- if (targ.wait){
- // wait -2 on the path_corner forces it to continue moving (no wait),
- // even if the train has a default wait time
- if (targ.wait == -2) self.wait = 0;
- else self.wait = targ.wait;
- }
- // uses train's current wait time otherwise
- else
- self.wait = self.pausetime;
-
- self.enemy = targ;
-
- sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
-
- if(!(!self.wait && self.cnt == TRAIN_NEXT_CONTINUE)) self.cnt = TRAIN_NEXT_WAIT;
-
- //store up any premature triggerings until current movement is finished
- self.use = train_moving_use;
-
- if (self.classname == "misc_modeltrain") {
- if (!(self.spawnflags & TRAIN_NOROTATE)) {
- destang = vectoangles(targ.origin - self.origin);
- if (self.spawnflags & TRAIN_ROTATEY) {
- destang_x = self.angles_x;
- destang_z = self.angles_z;
- }
- if (self.multiplier > 0) SUB_CalcAngleMoveController(destang, self.speed2*self.multiplier, SUB_Null, self.rotatecontroller);
- else self.angles = destang;
- }
- }
-
- if (!self.state) {
- self.state = 1;
- if (self.classname == "misc_modeltrain" && self.style != TRAIN_STYLE_SINGLEANIM)
- SUB_CallAsSelf(self.animcontroller.think, self.animcontroller);
- }
- // if the TRAIN_CUSTOMALIGN flag is checked then the train should align
- // with its path_corners based on the location of an "origin" brush added
- // to the train by the mapper instead of the mins corner
- // -therektafire
- float doDisplace;
- if (self.spawnflags & TRAIN_CUSTOMALIGN) doDisplace = 0.0;
- else doDisplace = 1.0;
-
- if (self.classname != "misc_modeltrain")
- displ = self.mins;
-
- SUB_CalcMove(targ.origin - (displ * doDisplace), self.speed2, train_wait);
-};
-
-// searches for the first path_corner after the train entity is initialized
-void() func_train_find = {
- local entity targ;
- float localtime;
- vector displ = '0 0 0';
-
- if (self.movetype == MOVETYPE_PUSH) localtime = self.ltime;
- else localtime = time;
-
- targ = find(world, targetname, self.target);
- self.target = targ.target;
-
- float doDisplace;
- if (self.spawnflags & TRAIN_CUSTOMALIGN) doDisplace = 0.0;
- else doDisplace = 1.0;
-
- if (self.classname != "misc_modeltrain") displ = self.mins;
- self.enemy = targ;
- setorigin(self, targ.origin - (displ * doDisplace));
- if (targ.speed) self.speed2 = targ.speed; // uses speed from the 1st path corner if set
-
- if (!self.targetname)
- { // not triggered, so start immediately
- self.nextthink = localtime + 0.1;
- self.think = train_next;
- }
-};
-
-/*QUAKED func_train (0 .5 .8) ? RETRIGGER
-Trains are moving platforms that players can ride.
-The targets origin specifies the min point of the train at each corner.
-The train spawns at the first target it is pointing at.
-If the train is the target of a button or trigger, it will not begin moving until activated.
-
-RETRIGGER: stop at each path_corner and don't resume until triggered again (ignores wait time)
-
-speed default 100
-dmg default 2
-sounds
-1) ratchet metal
-2) base
-
-*/
-void() func_train =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (!self.speed)
- self.speed = 100;
- if (!self.target)
- objerror ("func_train without a target");
- if (!self.dmg)
- self.dmg = 2;
-
- if(self.spawnflags & TRAIN_STOPONTRIGGER && self.spawnflags & TRAIN_MOVEONTRIGGER)
- objerror("func_train: Stop and move on trigger set at the same time");
-
-
-
- if (self.sounds == 1) {
- if (self.noise == "") self.noise = ("plats/train2.wav");
- if (self.noise1 == "") self.noise1 = ("plats/train1.wav");
- }
- else if (self.sounds == 2) { // base door sound
- if (self.noise == "") self.noise = "doors/hydro2.wav";
- if (self.noise1 == "") self.noise1 = "doors/hydro1.wav";
- }
- else {
- if (self.noise == "") self.noise = ("misc/null.wav");
- if (self.noise1 == "") self.noise1 = ("misc/null.wav");
- }
-
- // backwards compatibility with previous version
- if (self.noise3 != "") self.noise = self.noise3;
- if (self.noise4 != "") self.noise1 = self.noise4;
-
- precache_sound(self.noise);
- precache_sound(self.noise1);
- if (self.noise2 != "") precache_sound(self.noise2);
-
-
- self.cnt = TRAIN_NEXT_WAIT;
-
- if (self.spawnflags & TRAIN_NONSOLID) {
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_NOCLIP;
- }
- else {
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- }
-
- self.blocked = train_blocked;
- self.use = train_use;
- //self.classname = "train";
-
- setmodel (self, self.model);
- setsize (self, self.mins , self.maxs);
- setorigin (self, self.origin);
-
- // start trains on the second frame, to make sure their targets have had
- // a chance to spawn
-
- if (self.movetype == MOVETYPE_PUSH) self.nextthink = self.ltime + 0.1;
- else self.nextthink = time + 0.1;
-
- self.think = func_train_find;
-
- self.speed2 = self.speed;
-};
-
-
-//===================================================
-
-
-void() animcontroller_think = {
- entity tr;
- tr = self.owner;
-
- float first, last, step, atype, dir, nextframe;
-
- // train just went from stopped to moving or vice-versa,
- // and have both animations set
- if (self.state != tr.state && tr.style != TRAIN_STYLE_SINGLEANIM) {
- if (tr.state) { // just started moving
- tr.frame = zeroconvert(tr.first_frame2);
- }
- else { // just stopped
- tr.frame = zeroconvert(tr.first_frame);
- }
- tr.distance = 1; // reset back/forth status
- self.state = tr.state;
- }
-
- else {
- if (self.state && tr.style != TRAIN_STYLE_SINGLEANIM) { // moving train animation, if set
- first = zeroconvert(tr.first_frame2);
- last = zeroconvert(tr.last_frame2);
- atype = tr.animtype2;
- }
- else { // stopped/default train animation
- first = zeroconvert(tr.first_frame);
- last = zeroconvert(tr.last_frame);
- atype = tr.animtype;
- }
-
- if (first > last) step = dir = -1; // reverse direction
- else step = dir = 1;
-
- // back-and-forth is going the other way, so invert the step's signal
- if (tr.distance < 0) step = step * (-1);
-
- nextframe = tr.frame + step;
-
- if (atype == TRAIN_ANIMTYPE_BACKFORTH){
- if (dir > 0 && (nextframe > last || nextframe < first) ||
- dir < 0 && (nextframe > first || nextframe < last)
- ) {
- nextframe = tr.frame - step;
- tr.distance = tr.distance * (-1);
- }
- }
-
- if (dir > 0) nextframe = wrap(nextframe, first, last);
- else nextframe = wrap(nextframe, last, first);
-
- tr.frame = nextframe;
-
- }
-
- self.think = animcontroller_think;
- if (self.state || tr.style == TRAIN_STYLE_SINGLEANIM) self.nextthink = time + tr.frtime;
- else self.nextthink = time + tr.frtime2;
-};
-
-void() misc_modeltrain = {
-
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- precache_model(self.mdl);
-
- func_train();
-
- if (self.spawnflags & TRAIN_NONSOLID)
- self.solid = SOLID_NOT;
- else {
- self.solid = SOLID_BBOX;
- if (self.cmins == VEC_ORIGIN) self.cmins = '-8 -8 -8';
- if (self.cmaxs == VEC_ORIGIN) self.cmaxs = '8 8 8';
- }
-
- self.movetype = MOVETYPE_NOCLIP;
- setmodel (self, self.mdl);
- setsize (self, self.cmins , self.cmaxs);
- setorigin (self, self.origin);
-
- entity rot, anim;
-
- rot = spawn();
- self.rotatecontroller = rot;
- rot.classname = "rotatecontroller";
- rot.owner = self;
-
- anim = spawn();
- self.animcontroller = anim;
- anim.classname = "animcontroller";
- anim.owner = self;
-
- anim.think = animcontroller_think;
- anim.nextthink = time + 0.2;
-
- self.distance = 1;
-
- if (!self.frtime) self.frtime = 0.1;
- if (!self.frtime2) self.frtime2 = self.frtime;
- if (!self.multiplier) self.multiplier = 1;
-
-
- // make sure all first and last frame fields are filled
- if (self.first_frame && !self.last_frame) self.last_frame = self.first_frame;
- else if (!self.first_frame && self.last_frame) self.first_frame = self.last_frame;
-
- if (self.first_frame2 && !self.last_frame2) self.last_frame2 = self.first_frame2;
- else if (!self.first_frame2 && self.last_frame2) self.first_frame2 = self.last_frame2;
-
- if (!self.first_frame2) self.style = TRAIN_STYLE_SINGLEANIM;
-
- if (!self.animtype) self.animtype = TRAIN_ANIMTYPE_FORWARD;
- if (!self.animtype2) self.animtype2 = self.animtype;
-
- self.frame = self.first_frame;
-
-};
-
-
-//===================================================
-
-
-//Code for the fixed teleporttrain written by c0burn and modified by ZungryWare
-void() teleporttrain_calcmove;
-void() teleporttrain_next =
-{
- local vector dir;
- setorigin(self, self.enemy.origin + '16 16 16');
-
- if (!self.target)
- {
- self.enemy = world;
- return;
- }
- self.enemy = find(world, targetname, self.target);
- if (self.enemy.classname == "path_corner")
- {
- dir = normalize((self.enemy.origin + '16 16 16') - self.origin);
- self.velocity = dir * self.speed;
- self.target = self.enemy.target;
- }
- else
- {
- objerror("unable to find target\n");
- remove(self);
- }
- teleporttrain_calcmove();
-};
-void() teleporttrain_wait =
-{
- local float wait_time;
- if (self.enemy.wait > 0)
- wait_time = self.enemy.wait;
- else
- wait_time = .1;
- self.velocity = '0 0 0';
- self.nextthink = time + wait_time;
- self.think = teleporttrain_next;
-
-}
-void() teleporttrain_calcmove =
-{
- local float len;
- local vector delta;
- local float spd;
-
- delta = (self.enemy.origin + '16 16 16') - self.origin;
- len = vlen(delta);
- spd = vlen(self.velocity);
- self.nextthink = time + (len / spd);
- self.think = teleporttrain_wait;
-};
-void() teleporttrain_use =
-{
- if (self.velocity == '0 0 0')
- {
- teleporttrain_next();
- }
-};
-void() teleporttrain_find =
-{
- // always start positioned on the first path_corner
- self.enemy = find(world, targetname, self.target);
- if (self.enemy.classname == "path_corner")
- {
- setorigin (self, self.enemy.origin + '16 16 16');
- self.target = self.enemy.target;
- }
- else
- {
- objerror("unable to find target\n");
- remove(self);
- return;
- }
-
- if (self.spawnflags & 4) // start immediately even with a targetname
- {
- teleporttrain_next();
- }
- // not triggered, so start immediately
- else if (!self.targetname)
- {
- teleporttrain_next();
- }
- else
- {
- self.use = teleporttrain_use;
- }
-};
-/*QUAKED misc_teleporttrain (.5 .5 .5) (-16 -16 -16) (16 16 16) X DONT_ROTATE START_ON_WITH_TARGETNAME INVISIBLE 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
-{ model("progs/teleport.mdl"); }
-This was used for the final boss level in the original game. In progs_dump you can use this as a moving decoration or even target it as a spawn point for a func_monster_spawner. Make sure and select the Don't Rotate spawnflag though or you'll experience a pretty hilarious effect!
-
-You set this up like a func_train using path_corners. By default, it will move automatically between path corners upon map load. However, you can have it wait to move by giving it a targetname. If you need to target it as a spawner and want it to move on map load, use the Start On spawnflag.
-
-You can add effects, use a custom model using the mdl_body keyvalue and even make it invisible with spawnflag 8.
-
-Effects
-0: "None (Default)"
-1 : "Brightfield (yellow particles)"
-4 : "Bright light"
-8 : "Dim light"
-
-
-Teleporter target for final boss level. Must target a series of 'path_corner' entities.
-It will position itself on its first target at map load.
-If a targetname is set, it must be triggered to start moving, otherwise it will start automatically.
-*/
-void() misc_teleporttrain =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (!self.target)
- {
- objerror ("misc_teleporttrain has no target");
- remove(self);
- return;
- }
- if (self.speed <= 0)
- {
- self.speed = 100;
- }
-
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_FLY;
- precache_body_model ("progs/teleport.mdl"); // custom custom_mdls -- dumptruck_ds
- precache_model ("progs/s_null.spr"); // invisble -- dumptruck_ds
- if (self.spawnflags & 8)
- // setmodel (self, "progs/s_null.spr");
- body_model ("progs/s_null.spr");
- else
- body_model ("progs/teleport.mdl");
- // precache_model ("progs/teleport.mdl");
- setsize (self, '-16 -16 -16', '16 16 16');
-
- //Causes the ball to spin around like it was originally intended to.
- if (!(self.spawnflags & 2)) //don't spin - helpful for invisible spawner -- dumptruck_ds
- self.avelocity = '40 80 120';
- // self.avelocity = '100 200 300';
-
- self.think = teleporttrain_find;
- self.nextthink = time + 0.1;
-};

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 83d3953..b15ce7b 100644
--- a/qc/pmove.qc
+++ b/qc/pmove.qc
@@ -3,6 +3,10 @@
//==============================================================================

// TODO CEV: crouching
+// TODO CEV: crouch sliding (useful for sliding up stairs)
+// TODO CEV: crouch-wall-thing (wallrunning? wall sliding?)
+// TODO CEV: more work on walking
+// TODO CEV: varied sounds (footsteps, different jump sounds)

// globals managed by FTEQW, from fteextensions.qc -- CEV
float input_buttons;
@@ -12,10 +16,9 @@ vector input_angles; // +x = DOWN
vector input_movevalues;

// fields
+// note: timers are expensive, require synch between server and client -- CEV
.entity groundentity;
.vector groundnormal;
-
-// note: timers are expensive, require synch between server and client -- CEV
.float pmove_flags; // custom movement flags -- CEV
.float doublejump_timer; // time in which a player can doublejump
.float groundboost_timer; // time to apply low friction -- CEV
@@ -50,10 +53,11 @@ 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_DOUBLEJUMPSPEED = 270.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_WALLJUMPGROUND = 36.0f; // distance from ground to allow WJ
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
@@ -62,11 +66,12 @@ const float PM_WALLJUMPDOUBLE = 360.0f; // 315 = 90 * 3.5; wall doublejump
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.25f; // duration between walljumps
+const float PM_WALLJUMP_WINDOW = 0.2f; // 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_ONESIDEDCLIP = -0.01; // -0.001;
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
@@ -97,6 +102,7 @@ enumflags
};

// prototypes
+static void(entity ent) PM_DoTouch;
float() PM_Nudge;
void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove;
void() PM_CategorizePosition;
@@ -131,6 +137,23 @@ void() SV_RunClientCommand =
#endif

//======================================================================
+// PM_DoTouch
+//----------------------------------------------------------------------
+static void(entity ent) PM_DoTouch =
+{
+ if (ent && ent.touch != __NULL__)
+ {
+ local entity orig_self;
+
+ orig_self = self;
+ other = self;
+ self = ent;
+ self.touch ();
+ self = orig_self;
+ }
+};
+
+//======================================================================
// PM_Nudge
// from the GPL2 CSQCTest code that comes with FTEQW; is called often
// to nudge player origin due to float/network precision errors -- CEV
@@ -243,14 +266,17 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =

// nah, we're stuck. don't build up falling damage
// but allow sideways acceleration -- CEV
+ /*
#ifdef CSQC
dprint ("PM_DanceMove: client ");
- #elif SSQC
+ #endif
+ #ifdef SSQC
dprint ("PM_DanceMove: server ");
#endif
#if defined(CSQC) || defined(SSQC)
dprint ("entity trapped in a solid!\n");
#endif
+ */
self.velocity_z = 0;
break;
}
@@ -296,7 +322,17 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
if (trace_ent && trace_ent.touch != __NULL__)
touched_ent = trace_ent;

- if (trace_fraction >= 1.0f)
+ if (trace_allsolid || trace_startsolid)
+ {
+ // reject the move immediately -- CEV
+ #ifdef SSQC
+ dprint ("PM_DanceMove: fwd move solid\n");
+ #endif
+ stepsize = 0;
+ self.velocity = '0 0 0';
+ break;
+ }
+ else if (trace_fraction >= 1.0f)
{
// storing another vector, disappointed in
// myself -- CEV
@@ -309,7 +345,18 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
tracebox (trace_endpos, self.mins, self.maxs,
end, FALSE, self);

- if (trace_fraction < 1.0f &&
+ if (trace_allsolid || trace_startsolid)
+ {
+ // again reject the move -- CEV
+ #ifdef SSQC
+ dprint ("PM_DanceMove: down move "
+ "solid\n");
+ #endif
+ stepsize = 0;
+ self.velocity = '0 0 0';
+ break;
+ }
+ else if (trace_fraction < 1.0f &&
trace_plane_normal_z > 0.7f)
{
// good ground, accept the move
@@ -424,7 +471,7 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
if (sticky)
backoff /= PM_OVERCLIP;
else
- backoff *= -0.001;
+ backoff *= PM_ONESIDEDCLIP;

self.velocity -= plane * backoff;

@@ -442,7 +489,7 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
if (sticky)
backoff /= PM_OVERCLIP;
else
- backoff *= -0.001;
+ backoff *= PM_ONESIDEDCLIP;

self.velocity -= prev_plane * backoff;

@@ -509,7 +556,7 @@ void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMove =
// we've airstepped. this check is here as a placeholder for possible
// functionality later -- CEV
#ifdef SSQC
- if (stepsize && !(self.pmove_flags & PMF_STARTGROUND) &&
+ if (stepsize > 0 && !(self.pmove_flags & PMF_STARTGROUND) &&
self.pmove_flags & PMF_ONGROUND)
{
// more debugging -- CEV
@@ -725,6 +772,10 @@ void() PM_Jump =
self.pmove_flags & PMF_JUMP_HELD)
return;

+ #ifdef SSQC
+ local string msg = "";
+ #endif
+
// make sure we get at least jumpspeed upwards from
// the ground plane by clamping it first.
if (self.groundnormal && (self.velocity * self.groundnormal < 0))
@@ -750,8 +801,8 @@ void() PM_Jump =
// a teleport jump: allow a larger (+0.2) window to
// account for time to travel thru teleporter -- CEV
#ifdef SSQC
- dprint (sprintf("PM_Jump: telejump %g, ",
- self.velocity_z));
+ msg = sprintf ("PM_Jump: telejump %g, ",
+ self.velocity_z);
#endif
// non-additive jump, though it shouldn't matter -- CEV
self.velocity_z = PM_TELEJUMPSPEED;
@@ -760,8 +811,8 @@ void() PM_Jump =
self.groundboost_timer > 0)
{
#ifdef SSQC
- dprint (sprintf("PM_Jump: stairjump %g, ",
- self.velocity_z));
+ msg = sprintf ("PM_Jump: stairjump %g, ",
+ self.velocity_z);
#endif
// don't do additive stairjumps on flat ground -- CEV
self.velocity_z = PM_STAIRJUMPSPEED;
@@ -769,8 +820,8 @@ void() PM_Jump =
else
{
#ifdef SSQC
- dprint (sprintf("PM_Jump: doublejump %g, ",
- self.velocity_z));
+ msg = sprintf ("PM_Jump: doublejump %g, ",
+ self.velocity_z);
#endif
// the groundnormal might be weird - some kind of
// ramp - so we want an additive doublejump here -- CEV
@@ -784,7 +835,8 @@ void() PM_Jump =
{
// normal jump
#ifdef SSQC
- dprint (sprintf("PM_Jump: jump %g, ", self.velocity_z));
+ if (self.velocity_z > 0)
+ msg = sprintf ("PM_Jump: jump %g, ", self.velocity_z);
#endif

// do an additive jump -- CEV
@@ -793,7 +845,8 @@ void() PM_Jump =

// report new Z velocity
#ifdef SSQC
- dprint (sprintf("%g\n", self.velocity_z));
+ if (msg != "")
+ dprint (sprintf("%s %g\n", msg, self.velocity_z));
#endif

// manage flags -- CEV
@@ -802,8 +855,8 @@ void() PM_Jump =
self.pmove_flags &= ~PMF_ONGROUND;
self.flags &= ~FL_ONGROUND;
self.pmove_flags |= PMF_JUMP_HELD;
- #ifdef SSQC
self.button2 = 0;
+ #ifdef SSQC
// player jumping sound; copied into pmove from client.qc -- CEV
sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
#endif
@@ -835,10 +888,26 @@ void() PM_WallJump =
// TODO CEV it would be a good idea to include a sound here.
return;

+ // minimum distance from ground to walljump
+ local vector end = self.origin;
+ end_z -= PM_WALLJUMPGROUND;
+ tracebox (self.origin, self.mins, self.maxs, end, TRUE, self);
+
+ if (trace_fraction < 1.0f)
+ {
+ /*
+ #ifdef SSQC
+ dprint ("PM_WallJump: too close to ground to walljump\n");
+ #endif
+ */
+ return;
+ }
+
// start at STEPHEIGHT + 1 to try and clear any steps -- CEV
- local vector start, end;
- start = end = self.origin;
+ local vector start;
+ start = self.origin;
start_z += PM_STEPHEIGHT + 1;
+ end = start;

for (int i = 0; i < 4; i++)
{
@@ -907,18 +976,15 @@ void() PM_WallJump =
self.velocity_z += PM_WALLJUMPSPEED;
}

- #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
+ dprint (sprintf("dist %g, normalspeed %g\n",
+ vlen(self.origin - trace_endpos),
+ self.velocity * trace_plane_normal));
self.button2 = 0;
sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
#endif
@@ -1173,8 +1239,10 @@ void(vector wishvel, float move_time) PM_SwimAccelerate =
self.pmove_flags &= ~PMF_JUMP_HELD;
// Z velocity was 225
self.velocity_z = PM_JUMPSPEED;
- // safety net
- self.teleport_time = time + 2;
+ // we don't care about the 'safety net'
+ // in this movement set (unlike vanilla)
+ // so don't set teleport_time -- CEV
+ // self.teleport_time = time + 2;
}
}
}
@@ -1315,7 +1383,7 @@ void(entity target) PM_Move =
}

// TODO CEV this is the wrong place to clear PMF_JUMP_HELD
- if (!(input_buttons & 2) || self.button2 == 0)
+ if (!(input_buttons & 2))
self.pmove_flags &= ~PMF_JUMP_HELD;

// figure out the properties of the player's position, then clear timers
@@ -1428,7 +1496,6 @@ void(entity target) PM_Move =
// clear ladder flag -- CEV
if (self.pmove_flags & PMF_ONLADDER)
self.pmove_flags &= ~PMF_ONLADDER;
-
break;

case MOVETYPE_FLY:
@@ -1463,6 +1530,11 @@ void(entity target) PM_Move =
break;
}

+ // make sure we've touched the ground entity (it might've slipped
+ // through the slidemove above) -- CEV
+ if (self.groundentity && self.groundentity.touch != __NULL__)
+ PM_DoTouch (self.groundentity);
+
touchtriggers (self);
self = oldself;
};

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 8647d24..6923255 100644
--- a/qc/progs.src
+++ b/qc/progs.src
@@ -13,35 +13,62 @@ defs_globalvars.qc // globalvars_t
defs_entvars.qc // entvars_t
defs_builtins.qc // builtin functions (& overrides)
defs_misc.qc // additional
-newflags.qc // new spawnflags for all entities
+
math.qc // Code by Joshua Skelton
utility.qc
+newflags.qc // new spawnflags for all entities

subs.qc // modified targets, triggers and killtargets
+keydata.qc // functions which deal with key item bitflags + names
+keylock.qc // common code for entities unlockable with keys

fight.qc
custom_snd.qc // mapper-settable sound FX for monsters - iw
custom_mdls.qc // mapper-settable models for monsters - iw
ai.qc
combat.qc
-keydata.qc // functions which deal with key item bitflags + names
-items.qc
-items_armor.qc
-items_health.qc
-weapons.qc
world.qc
intermission.qc
pmove.qc // QC player movement code -- CEV
client.qc
cutscene.qc // Drake version -- dumptruck_ds
player.qc
-keylock.qc // common code for entities unlockable with keys
-doors.qc
-buttons.qc
+
+//----------------------------------------------------------------------
+// items
+//----------------------------------------------------------------------
+items.qc
+items_armor.qc
+items_health.qc
+weapons.qc

//----------------------------------------------------------------------
// func
//----------------------------------------------------------------------
+func/bob.qc // RennyC's stand alone version based on AD
+func/bossgate.qc // was misc.qc -- CEV
+func/breakable.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
+func/button.qc
+func/counter.qc // Hipnotic counter; was in hipcount.qc
+func/door.qc // was doors.qc -- CEV
+func/door_secret.qc // was doors.qc -- CEV
+func/elvtr_button.qc // Rogue elevator code (pmack)
+func/episodegate.qc // was misc.qc -- CEV
+func/explobox.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
+func/fall.qc // Renny's original version
+func/fall2.qc // Renny's improved version.
+func/illusionary.qc // was misc.qc -- CEV
+func/laser.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
+func/monster_spawner.qc // Using "bot" creation code for func_monster_spawner
+func/new_plat.qc // Rogue MP newplats.qc
+func/plat.qc // was plats.qc -- CEV
+func/particlefield.qc // Hipnotic particlefield and func_togglewall
+func/rotate.qc // from Hipnotic thanks RennyC; was rotate.qc
+func/shadow.qc //
+func/togglevisiblewall.qc// was misc.qc -- CEV
+func/togglewall.qc // was hippart.qc -- CEV
+func/train.qc // was plats.qc -- CEV
+func/wall.qc // was misc.qc -- CEV

//----------------------------------------------------------------------
// triggers
@@ -71,12 +98,6 @@ 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
//----------------------------------------------------------------------
@@ -99,22 +120,26 @@ monsters/oldone.qc // registered
monsters/oldone2.qc // killable Shub
monsters/shalrath.qc // registered

+//----------------------------------------------------------------------
+// misc
+//----------------------------------------------------------------------
+misc/modeltrain.qc // was in plats.qc -- CEV
+misc/particles.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
+misc/particlespray.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
+misc/particle_stream.qc // from Zerstrorer mod -- dumptruck_ds; was dtmisc.qc
+misc/sparks.qc // selections from Rubicon2 QC; was rubicon2.qc -- CEV
+misc/teleporttrain.qc // was in plats.qc -- CEV
+
+misc.qc
+fog.qc // fog triggers
+
+cshift.qc // background color shift controller
dtmisc.qc // sound code from Hipnotic & Rubicon Rumble
// and misc visual effects
-
+lights.qc // c0burn's excellent switchable lights
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
-doe_elbutton.qc // Rogue elevator code
doe_ltrail.qc // from DOE lightnin.qc
-doe_plats.qc // Rogue MP newplats.qc
-
-rubicon2.qc // selections from Rubicon2 QC
-func_bob.qc // RennyC's stand alone version based on AD
-func_fall2.qc // Renny's improved version.
-mobot.qc // Using "bot" creation code for func_monster_spawner

compat_quake3.qc // entrypoints & support for Quake 3 entities
#endlist

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

Diff qc/rubicon2.qc

diff --git a/qc/rubicon2.qc b/qc/rubicon2.qc
deleted file mode 100644
index 7c33972..0000000
--- a/qc/rubicon2.qc
+++ /dev/null
@@ -1,956 +0,0 @@
-//selections from Rubicon 2 qc by john fitzgibbons
-//and AD breakable code modified by Qmaster,iw and dumptruck_ds
-float BREAKABLE_NO_MONSTERS = 1;
-float BREAK_EXPLODE = 2;
-float BREAK_CUSTOM = 4;
-float START_OFF = 1;
-float SPARKS_BLUE = 2;
-float SPARKS_PALE = 4;
-
-void() make_breakable_debris;
-
-/*
-===============================================================================
-func_explobox
-===============================================================================
-*/
-
-void () func_explobox_explode_silent =
-{
- self.takedamage = DAMAGE_NO;
- self.origin = ((self.absmin + self.absmax) * 0.5);
- self.classname = "explo_box";
- T_RadiusDamage (self, self, self.dmg, world);
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_EXPLOSION);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
- BecomeExplosion ();
-
-};
-
-void () func_explobox_explode = {
- // sound (self, CHAN_VOICE, "weapons/r_exp3.wav", 1, ATTN_NORM);
- func_explobox_explode_silent();
-};
-
-void () func_explobox_die =
-{
- self.nextthink = 0.2; //for some reason, time + 0.2 doesn't work
- self.think = func_explobox_explode;
-};
-
-/*QUAKED func_explobox (0 .5 .8) ? START_OFF 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
-
-An exploding brush entity. Works just like misc_explobox.
-
-Keys:
-
-"health" Default 20
-
-"dmg" default 100
-
-*/
-void () func_explobox =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- setmodel (self, self.model);
- precache_sound ("weapons/r_exp3.wav");
- if (!self.health)
- {
- self.health = 20;
- }
- if (!self.dmg)
- {
- self.dmg = 100;
- }
- self.th_die = func_explobox_die;
- self.takedamage = DAMAGE_AIM;
-};
-
-
-/*
-===============================================================================
-func_breakable
-===============================================================================
-*/
-
-.string break_template1;
-.string break_template2;
-.string break_template3;
-.string break_template4;
-.string break_template5;
-.float brk_obj_count1;
-.float brk_obj_count2;
-.float brk_obj_count3;
-.float brk_obj_count4;
-.float brk_obj_count5;
-
-
-// template system from Qmaster -- dumptruck_ds
-void() make_breakable_templates_debris = {
- local float i;
- local entity new;
-
- i = 0;
- if (self.break_template1 != "") {
- while (i < self.brk_obj_count1) {
- new = spawn();
- new.model = self.break_template1;
- new.origin_x = (self.maxs_x - self.mins_x)*random() + self.mins_x;
- new.origin_y = (self.maxs_y - self.mins_y)*random() + self.mins_y;
- new.origin_z = (self.maxs_z - self.mins_z)*random() + self.mins_z;
- setmodel (new, new.model); //dumptruck_ds
- setsize (new, '0 0 0', '0 0 0');
- new.velocity = VelocityForDamage (self.health*2);
- new.movetype = MOVETYPE_BOUNCE;
- new.solid = SOLID_NOT;
- new.avelocity_x = random()*600;
- new.avelocity_y = random()*600;
- new.avelocity_z = random()*600;
- new.think = SUB_Remove;
- new.ltime = time;
- new.nextthink = time + 10 + random()*10;
- new.flags = 0;
- i++;
- }
- }
-
- i = 0;
- if (self.break_template2 != "") {
- while (i < self.brk_obj_count2) {
- new = spawn();
- new.model = self.break_template2;
- new.origin_x = (self.maxs_x - self.mins_x)*random() + self.mins_x;
- new.origin_y = (self.maxs_y - self.mins_y)*random() + self.mins_y;
- new.origin_z = (self.maxs_z - self.mins_z)*random() + self.mins_z;
- setmodel (new, new.model); //dumptruck_ds
- setsize (new, '0 0 0', '0 0 0');
- new.velocity = VelocityForDamage (self.health*2);
- new.movetype = MOVETYPE_BOUNCE;
- new.solid = SOLID_NOT;
- new.avelocity_x = random()*600;
- new.avelocity_y = random()*600;
- new.avelocity_z = random()*600;
- new.think = SUB_Remove;
- new.ltime = time;
- new.nextthink = time + 10 + random()*10;
- new.flags = 0;
- i++;
- }
- }
-
- i = 0;
- if (self.break_template3 != "") {
- while (i < self.brk_obj_count3) {
- new = spawn();
- new.model = self.break_template3;
- new.origin_x = (self.maxs_x - self.mins_x)*random() + self.mins_x;
- new.origin_y = (self.maxs_y - self.mins_y)*random() + self.mins_y;
- new.origin_z = (self.maxs_z - self.mins_z)*random() + self.mins_z;
- setmodel (new, new.model); //dumptruck_ds
- setsize (new, '0 0 0', '0 0 0');
- new.velocity = VelocityForDamage (self.health*2);
- new.movetype = MOVETYPE_BOUNCE;
- new.solid = SOLID_NOT;
- new.avelocity_x = random()*600;
- new.avelocity_y = random()*600;
- new.avelocity_z = random()*600;
- new.think = SUB_Remove;
- new.ltime = time;
- new.nextthink = time + 10 + random()*10;
- new.flags = 0;
- i++;
- }
- }
-
- i = 0;
- if (self.break_template4 != "") {
- while (i < self.brk_obj_count4) {
- new = spawn();
- new.model = self.break_template4;
- new.origin_x = (self.maxs_x - self.mins_x)*random() + self.mins_x;
- new.origin_y = (self.maxs_y - self.mins_y)*random() + self.mins_y;
- new.origin_z = (self.maxs_z - self.mins_z)*random() + self.mins_z;
- setmodel (new, new.model); //dumptruck_ds
- setsize (new, '0 0 0', '0 0 0');
- new.velocity = VelocityForDamage (self.health*2);
- new.movetype = MOVETYPE_BOUNCE;
- new.solid = SOLID_NOT;
- new.avelocity_x = random()*600;
- new.avelocity_y = random()*600;
- new.avelocity_z = random()*600;
- new.think = SUB_Remove;
- new.ltime = time;
- new.nextthink = time + 10 + random()*10;
- new.flags = 0;
- i++;
- }
- }
-
- i = 0;
- if (self.break_template5 != "") {
- while (i < self.brk_obj_count5) {
- new = spawn();
- new.model = self.break_template5;
- new.origin_x = (self.maxs_x - self.mins_x)*random() + self.mins_x;
- new.origin_y = (self.maxs_y - self.mins_y)*random() + self.mins_y;
- new.origin_z = (self.maxs_z - self.mins_z)*random() + self.mins_z;
- setmodel (new, new.model); //dumptruck_ds
- setsize (new, '0 0 0', '0 0 0');
- new.velocity = VelocityForDamage (self.health*2);
- new.movetype = MOVETYPE_BOUNCE;
- new.solid = SOLID_NOT;
- new.avelocity_x = random()*600;
- new.avelocity_y = random()*600;
- new.avelocity_z = random()*600;
- new.think = SUB_Remove;
- new.ltime = time;
- new.nextthink = time + 10 + random()*10;
- new.flags = 0;
- i++;
- }
- }
-};
-
-
-//Below this is from Rubicon2 -- dumptruck_ds
-
-void() make_breakable_debris = {
- local float i;
- i = 0;
- while (i < self.cnt)
- {
- local entity new;
-
- new = spawn();
- new.origin_x = (self.maxs_x - self.mins_x)*random() + self.mins_x;
- new.origin_y = (self.maxs_y - self.mins_y)*random() + self.mins_y;
- new.origin_z = (self.maxs_z - self.mins_z)*random() + self.mins_z;
- // setmodel (new, "progs/debris.mdl"); this was originally just an mdl from Rubicon2, now you set custom model via spawnflag or use the builtin from Rubicon2 -- dumptruck_ds
- setmodel (new, self.mdl_debris); //dumptruck_ds
- setsize (new, '0 0 0', '0 0 0');
- new.velocity = VelocityForDamage (self.health*2);
- new.movetype = MOVETYPE_BOUNCE;
- new.solid = SOLID_NOT;
- new.avelocity_x = random()*600;
- new.avelocity_y = random()*600;
- new.avelocity_z = random()*600;
- new.think = SUB_Remove;
- new.ltime = time;
- new.nextthink = time + 10 + random()*10;
- new.flags = 0;
-
- // randomly choose size
- if (random() > 0.333)
- new.frame = 1; //larger
- else
- new.frame = 2; //smaller
-
- // choose skin based on "style" key
- if (self.style == 1)
- new.skin = 1;
- if (self.style == 2)
- new.skin = 2;
- if (self.style == 3) // new debris skins start here - dumptruck_ds
- new.skin = 3;
- if (self.style == 4)
- new.skin = 4;
- if (self.style == 5)
- new.skin = 5;
- if (self.style == 6)
- new.skin = 6;
- if (self.style == 7)
- new.skin = 7;
- if (self.style == 8)
- new.skin = 8;
- if (self.style == 9)
- new.skin = 9;
- if (self.style == 10)
- new.skin = 10;
- if (self.style == 11)
- new.skin = 11;
- if (self.style == 12)
- new.skin = 12;
- if (self.style == 13)
- new.skin = 13;
- if (self.style == 14)
- new.skin = 14;
- if (self.style == 15)
- new.skin = 15;
- if (self.style == 16)
- new.skin = 16;
- if (self.style == 17)
- new.skin = 17;
- if (self.style == 18)
- new.skin = 18;
- if (self.style == 19)
- new.skin = 19;
- if (self.style == 20)
- new.skin = 20;
- if (self.style == 21)
- new.skin = 21;
- if (self.style == 22)
- new.skin = 22;
- if (self.style == 23)
- new.skin = 23;
- if (self.style == 24)
- new.skin = 24;
- if (self.style == 25)
- new.skin = 25;
- if (self.style == 26)
- new.skin = 26;
- if (self.style == 27)
- new.skin = 27;
- if (self.style == 28)
- new.skin = 28;
- if (self.style == 29)
- new.skin = 29;
- if (self.style == 30)
- new.skin = 30;
- if (self.style == 31)// new debris skins end here - dumptruck_ds
- new.skin = 31;
-
- i = i + 1;
- }
-};
-
-void () func_breakable_die = {
- //dumptruck_ds -- set the spawnflag for cosmetic explosion effect; use "dmg" value to hurt the player
- {
- local entity ent; //thanks to Qmaster!!! He helped me sort out noise1 playing from 0 0 0 with this temp entity - dumptruck_ds
-
- ent = spawn();
- ent.origin = ((self.absmin + self.absmax) * 0.5);
- setsize (ent, '0 0 0', '0 0 0');
- ent.solid = SOLID_NOT;
- ent.think = SUB_Remove;
- // ent.ltime = time;
- ent.nextthink = time + 60;
-
- sound(ent, CHAN_AUTO, self.noise1, 1, ATTN_NORM);
- // remove (self);
- }
-
- // this is to ensure that any debris from another func_breakable
- // which is resting on top of this func_breakable is not left
- // floating in mid-air after this entity is removed -- iw
- SUB_DislodgeRestingEntities ();
-
- if (self.spawnflags & BREAK_EXPLODE) {
- if (self.spawnflags & BREAK_CUSTOM) {
- make_breakable_templates_debris ();
- } else {
- make_breakable_debris ();
- }
- func_explobox_explode_silent(); // to let us use noise2
- // sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM); this is broken as of 1.1.0 no custom explosion sound for now -- dumptruck_ds
- remove (self);
- } else {
- self.origin = ((self.absmin + self.absmax) * 0.5);
- setorigin (self, self.origin);
- DropStuff();
- if (self.spawnflags & BREAK_CUSTOM) {
- if (self.switchshadstyle) lightstyle(self.switchshadstyle, "m");
- make_breakable_templates_debris ();
- remove (self);
- } else {
- if (self.switchshadstyle) lightstyle(self.switchshadstyle, "m");
- make_breakable_debris ();
- remove (self);
- }
- }
-};
-
-void () func_breakable_killed =
-{
- activator = damage_attacker;
- SUB_UseTargets ();
- func_breakable_die ();
-};
-
-void () func_breakable_use =
-{
- activator = other;
- SUB_UseTargets ();
- func_breakable_die ();
-};
-
-/*QUAKED func_breakable (0 .5 .8) ? NO_MONSTERS 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
-
-"Breakable - See manual for full details
-
-Defaults to built-in .mdl file with 32 styles, cnt is number of pieces of debris to spawn (built-in only)
-Or use spawnflag 4 and break_template1-4 to set path of custom .mdl or .bsp models.
-brk_object_count1-4 sets the number of pieces of each break_template when using custom .mdl or bsp models.
-If noise1 is not set it will default to various sounds in sounds/break folder
-Use spawnflag 2 for an explosion, dmg is amount of damage inflicted"
-
-spawnflags(flags)
-1 : "No Monster Damage" : 0 : "Only the player can break"
-2 : "Explosion" : 0 : "Produces explosion effect and sound"
-4 : "Use custom mdls or bsp models" : 0 : "Uses models specified in break_template1, 2, etc"
-
-style(choices) : "Built-in debris style" : 0
-0 : "Green Metal (default)"
-1 : "Red Metal"
-2 : "Concrete"
-3 : "Pine wood"
-4 : "Brown wood"
-5 : "Red wood"
-6 : "Stained Glass Yellow Flames"
-7 : "Stained Glass Red Rays"
-8 : "Stained Glass Yellow Dragon"
-9 : "Stained Glass Blue Dragon"
-10 : "Stained Glass Red Dragon"
-11 : "Light Copper"
-12 : "Dark Copper"
-13 : "Tan Bricks Large"
-14 : "Brown Bricks Large"
-15 : "Green Bricks Large"
-16 : "Generic Light Brown"
-17 : "Red Brown Computer"
-18 : "Grey Black Computer"
-19 : "Blue Green Metal"
-20 : "Blue Green Runic Wall"
-21 : "Brown Metal"
-22 : "Dark Brown Metal"
-23 : "Medium Brown Metal"
-24 : "Blue Metal"
-25 : "Green Stonework"
-26 : "Blue Stonework"
-27 : "Brown Bricks"
-28 : "Tan Blue Bricks"
-29 : "Red Bricks"
-30 : "Blue Bricks"
-31 : "Metal Rivets"
-
-noise1(string) : "Break noise (overrides default sounds)"
-cnt(integer) : "Number of pieces of debris to spawn" : 5
-health(integer) : "Health of breakable" : 20
-dmg(integer) : "Amount of Explosive Damage" : 20
-break_template1(string) : "Template 1 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
-break_template2(string) : "Template 2 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
-break_template3(string) : "Template 3 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
-break_template4(string) : "Template 4 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
-break_template5(string) : "Template 5 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
-brk_obj_count1(integer) : "Template 1 spawn count"
-brk_obj_count2(integer) : "Template 2 spawn count"
-brk_obj_count3(integer) : "Template 3 spawn count"
-brk_obj_count4(integer) : "Template 4 spawn count"
-brk_obj_count5(integer) : "Template 5 spawn count"
-*/
-
-void() break_template_setup = {
- if (self.break_template1 != "") precache_model(self.break_template1);
- if (self.break_template2 != "") precache_model(self.break_template2);
- if (self.break_template3 != "") precache_model(self.break_template3);
- if (self.break_template4 != "") precache_model(self.break_template4);
- if (self.break_template5 != "") precache_model(self.break_template5);
-};
-
-void () func_breakable = {
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- break_template_setup();
-
- self.solid = SOLID_BSP;
- self.movetype = MOVETYPE_PUSH;
- setmodel (self, self.model);
- self.mdl_debris = "progs/debris.mdl";
- precache_model (self.mdl_debris);
- precache_sound ("blob/hit1.wav");
-
- if (self.noise1 != "") precache_sound(self.noise1);
-// adding new default sounds for "simple" breakables in 1.2.0 -- dumptruck_ds
-// here's genreic metal breaking
- if (self.style == 0 || self.style == 11 || self.style == 12 || self.style == 17 || self.style == 18 || self.style == 19
- || self.style == 24 || self.style == 31)
- if !(self.noise1)
- {
- precache_sound("break/metal2.wav");
- self.noise1 = "break/metal2.wav";
- }
- if (self.style == 3 || self.style == 4 || self.style == 5)
- if !(self.noise1)
- {
- precache_sound("break/wood1.wav");
- precache_sound("break/wood2.wav");
- if (random() > 0.6) // wood only randomized
- self.noise1 = "break/wood1.wav";
- else
- self.noise1 = "break/wood2.wav";
- }
- // glass sounds -- this is more of a shattering sound anyway
- if (self.style == 6 || self.style == 7 || self.style == 8 || self.style == 9 || self.style == 10)
- if !(self.noise1)
- {
- precache_sound("break/metal1.wav");
- self.noise1 = "break/metal1.wav";
- }
- if (self.style == 1 || self.style == 2 || self.style == 13 || self.style == 14
- || self.style == 15 || self.style == 16 || self.style == 20 || self.style == 21
- || self.style == 22 || self.style == 23)
- if !(self.noise1)
- {
- precache_sound("break/stones1.wav");
- precache_sound("break/bricks1.wav");
- if (random() > 0.6) // wood only randomized
- self.noise1 = "break/bricks1.wav";
- else
- self.noise1 = "break/stones1.wav";
- }
- if (self.style == 25 || self.style == 26 || self.style == 27 || self.style == 28 || self.style == 29 || self.style == 30)
- if !(self.noise1)
- {
- precache_sound("break/stones1.wav");
- precache_sound("break/bricks1.wav");
- if (random() > 0.6) // wood only randomized
- self.noise1 = "break/stones1.wav";
- else
- self.noise1 = "break/bricks1.wav";
- }
- // else
- // (self.noise1 = "blob/hit1.wav");
-
- if (!self.health)
- self.health = 20;
- if (!self.cnt)
- self.cnt = 5; // was 6 dumptruck_ds
-
- if (self.targetname != "")
- {
- self.use = func_breakable_use;
- }
- else
- {
- self.takedamage = DAMAGE_YES;
- self.th_die = func_breakable_killed;
- }
-
- if (self.switchshadstyle) lightstyle(self.switchshadstyle, "a");
-};
-
-/*
-===============================================================================
-func_laser
-===============================================================================
-*/
-float LASER_SOLID = 2;
-.string message2;
-.float alpha;
-
-
-void() laser_helper_think =
-{
- if (!self.owner || self.owner.classname != "func_laser")
- {
- remove(self);
- return;
- }
-
-
- if (!(self.owner.spawnflags & START_OFF))
- self.owner.alpha = self.alpha * 0.8 + self.alpha * random() * 0.4;
-
- self.nextthink = time + 0.05;
-};
-
-void() func_laser_touch =
-{
- // from Copper -- dumptruck_ds
- if (other.movetype == MOVETYPE_NOCLIP)
- return;
-
- if (other.takedamage && self.attack_finished < time)
- {
- T_Damage (other, self, self, self.dmg);
- self.attack_finished = time + 0.1;
- }
-
-};
-
-void () func_laser_use =
-{
- if (self.spawnflags & START_OFF)
- {
- setorigin(self, '0 0 0');
- self.spawnflags = self.spawnflags - START_OFF;
-
- // changed for progs_dump: the laser sound is now emitted from
- // the func_laser itself instead of from the activator -- iw
- sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
-
- if (activator.classname == "player" && self.message != "")
- {
- centerprint (activator, self.message);
- }
- }
- else
- {
- // changed for progs_dump: the laser sound is now emitted from
- // the func_laser itself instead of from the activator -- iw
- sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
-
- setorigin(self, '0 0 9000');
- self.spawnflags = self.spawnflags + START_OFF;
-
- if (activator.classname == "player" && self.message2 != "")
- {
- centerprint (activator, self.message2);
- }
- }
-};
-
-/*QUAKED func_laser (0 .5 .8) ? START_OFF LASER_SOLID 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 toggleable laser, hurts to touch, can be used to block players
-
-START_OFF: Laser starts off.
-
-LASER_SOLID: Laser blocks movement while turned on.
-
-Keys:
-
-"dmg" damage to do on touch. default 1
-
-"alpha" approximate alpha you want the laser drawn at. default 0.5. alpha will vary by 20% of this value.
-
-"message" message to display when activated
-
-"message2" message to display when deactivated
-
-*/
-void () func_laser =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- local entity helper;
-
- setmodel (self, self.model);
-
- precache_sound ("buttons/switch02.wav");
- precache_sound ("buttons/switch04.wav");
-
- if (self.spawnflags & LASER_SOLID)
- {
- self.solid = SOLID_BSP; //so you can shoot between lasers in a single bmodel
- self.movetype = MOVETYPE_PUSH; //required becuase of SOLID_BSP
- }
- else
- {
- self.solid = SOLID_TRIGGER;
- self.movetype = MOVETYPE_NONE;
- }
-
- if (!self.alpha)
- self.alpha = 0.5;
-
- if (!self.dmg)
- self.dmg = 1;
-
- self.use = func_laser_use;
- self.touch = func_laser_touch;
-
- if (self.spawnflags & START_OFF)
- setorigin(self, '0 0 9000');
- {
- if (self.noise != "") precache_sound(self.noise);
-
- else
- (self.noise = "buttons/switch02.wav");
- }
- {
- if (self.noise1 != "") precache_sound(self.noise1);
-
- else
- (self.noise1 = "buttons/switch04.wav");
- }
-
-
-
-
- //spawn a second entity to handle alpha changes, since MOVETYPE_PUSH doesn't support think functions
- helper = spawn();
- helper.alpha = self.alpha;
- helper.owner = self;
- helper.nextthink = 0.05;
- helper.think = laser_helper_think;
-};
-
-/*
-===============================================================================
-misc_sparks
-===============================================================================
-*/
-
-void() sparks_fade1 = [0, sparks_fade2] {self.alpha = 0.8; self.nextthink = time + 0.05;};
-void() sparks_fade2 = [0, sparks_fade3] {self.alpha = 0.6; self.nextthink = time + 0.05;};
-void() sparks_fade3 = [0, sparks_fade4] {self.alpha = 0.4; self.nextthink = time + 0.05;};
-void() sparks_fade4 = [0, SUB_Remove] {self.alpha = 0.2; self.nextthink = time + 0.05;};
-
-void() sparks_use =
-{
- if (self.spawnflags & START_OFF)
- self.spawnflags = self.spawnflags - START_OFF;
- else
- self.spawnflags = self.spawnflags + START_OFF;
-};
-
-void() make_sparks;
-
-void() spark_turnofflight =
-{
- SUB_UseTargets();
- self.think = make_sparks;
- self.nextthink = time + (random() + 0.5)*self.wait - 0.15;
-}
-
-void() make_sparks =
-{
-
- if (self.spawnflags & START_OFF)
- {
- self.nextthink = time + 0.1;
- self.think = make_sparks;
- }
- else
- {
- local float i;
- i = -0.25*self.cnt + random()*0.5*self.cnt;
- while (i < self.cnt)
- {
-
- local entity spark;
- spark = spawn();
- spark.owner = self;
- setmodel (spark, "progs/spark.mdl");
- setorigin (spark, self.origin);
- spark.movetype = MOVETYPE_BOUNCE;
- spark.solid = SOLID_TRIGGER;
- spark.gravity = 0.3;
- spark.velocity_x = -40 + random() * 80;
- spark.velocity_y = -40 + random() * 80;
- spark.velocity_z = -40 + random() * 80;
- spark.avelocity = '3000 3000 3000';
- spark.nextthink = time + 0.5 + 1.5*random();
- spark.think = sparks_fade1;
- spark.classname = "spark";
-
- if (random() < 0.33)
- spark.skin = 0;
- else if (random() < 0.5)
- spark.skin = 1;
- else
- spark.skin = 2;
-
- if (self.spawnflags & SPARKS_PALE)
- spark.skin = spark.skin + 6;
- else if (self.spawnflags & SPARKS_BLUE)
- spark.skin = spark.skin + 3;
-
- setsize (spark, '0 0 0', '0 0 0');
- i = i + 1;
- }
- if (self.sounds == 1)
- {
- if (self.noise != "")
- {
- sound (self, CHAN_AUTO, self.noise, 1, ATTN_STATIC);
- }
- else
- sound (self, CHAN_AUTO, "enforcer/enfstop.wav", 1, ATTN_STATIC);
- }
- SUB_UseTargets();
- self.nextthink = time + 0.1 + random() * 0.1;
- self.think = spark_turnofflight;
-
- }
-
-};
-
-/*QUAKED misc_sparks (0 .5 .8) (-8 -8 -8) (8 8 8) START_OFF SPARKS_BLUE SPARKS_PALE 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
-
-Produces a burst of yellow sparks at random intervals. If targeted, it will toggle between on or off. If it targets a light, that light will flash allong with each burst of sparks. Note: targeted lights should be set to START_OFF.
-
-SPARKS_BLUE: sparks are blue in color
-
-SPARKS_PALE: sparks are pale yellow in color
-
-Keys:
-
-"wait" is the average delay between bursts (variance is 1/2 wait). Default is 2.
-
-"cnt" is the average number of sparks in a burst (variance is 1/4 cnt). Default is 15.
-
-"sounds"
-0) no sound
-1) sparks
-*/
-void() misc_sparks =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- precache_model ("progs/spark.mdl");
- if (!self.noise)
- precache_sound ("dump/spark.wav");
- else
- precache_sound (self.noise);
-
- if (!self.movedir)
- self.movedir = '0 0 -30';
- if (!self.wait)
- self.wait = 2;
- if (!self.cnt)
- self.cnt = 15;
-
- self.use = sparks_use;
- self.nextthink = time + random()*0.1;
- self.think = make_sparks;
-};
-
-/*
-===============================================================================
-misc_particles a.k.a. misc_splash
-===============================================================================
-*/
-void() splash_use =
-{
- if (self.spawnflags & START_OFF)
- self.spawnflags = self.spawnflags - START_OFF;
- else
- self.spawnflags = self.spawnflags + START_OFF;
-};
-
-void() splash_think =
-{
- if (self.spawnflags & START_OFF)
- {
- self.nextthink = time + 0.1;
- self.think = splash_think;
- }
- else
- {
- local vector vec;
- local float variance;
- variance = vlen(self.movedir) / 2;
- vec_x = self.movedir_x - variance + random() * variance * 2;
- vec_y = self.movedir_y - variance + random() * variance * 2;
- vec_z = self.movedir_z - variance + random() * variance * 2;
- particle (self.origin, vec, self.color, self.volume);
- self.nextthink = time + self.wait;
- }
-};
-
-//
-//misc_particles
-//
-// renamed from misc_splash (Rubcion 2) --dumptruck_ds
-//
-
-/*QUAKED misc_particles (0 .5 .8) (-8 -8 -8) (8 8 8) START_OFF 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
-
-Produces a continuous particle splash for waterfalls and other effects
-
-"color" color of particles. 0 through 15, corresponds to a row of the quake palette. (default 0)
-
-"movedir" average movement vector of particles (default 0 0 4)
-
-"wait" time between particle generation cycles. (default 0.1)
-
-"volume" density of particles. (default 10)
-
-
-*/
-void() misc_particles =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if (!self.wait)
- self.wait = 0.1;
- if (!self.movedir)
- self.movedir = '0 0 4';
- if (!self.volume)
- self.volume = 10;
- self.color = self.color * 16;
-
- self.use = splash_use;
- self.nextthink = time + self.wait;
- self.think = splash_think;
-};
-
-//##########################################
-//#### Particle Sprayer ####
-//##########################################
-
-//this is from Custents not Rubicon2 -- dumptruck_ds
-//renamed from func to misc
-
-/*QUAKED misc_particlespray (0 .5 .8) (-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
-Shoots particles either when triggered, or contiuously when not triggered by anything.
-"color" is the palette color of the particles
-
-"count" is the number of particles to make each time
-
-"delay" is the delay between each triggering
-
-"noise" is the name of the wav file to play when triggered
-
-"movedir" is the vector distance that the particles will travel before disappearing. (in x y z)
-
-"duration" is the amount of time that the it will continue to release particles so that it can release a long stream of particles with only one triggering.
-*/
-
-.float endtime;
-.float duration;
-
-void() partspray_think =
-{
- particle (self.origin, self.movedir, self.color, self.count);
-
- if(!self.targetname || self.endtime > time)
- self.nextthink = time + self.delay;
-
- if(self.noise != "")
- sound(self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
- else
- sound(self, CHAN_AUTO, "misc/null.wav", 1, ATTN_NORM);
-
-};
-
-void() partspray_use =
-{
- self.endtime = time + self.duration;
- partspray_think();
-};
-
-void() misc_particlespray =
-{
- if (SUB_Inhibit ()) // new spawnflags for all entities -- iw
- return;
-
- if ( !self.color )
- self.color = 47;
- if ( self.count <= 0 )
- self.count = 15;
- if(self.delay <= 0)
- self.delay = 0.1;
- self.classname = "particlespray";
- if (self.noise != "")
- precache_sound(self.noise);
- precache_sound ("misc/null.wav");
- self.think = partspray_think;
- if(!self.targetname)
- self.nextthink = time + 0.1 + self.delay;
- else
- self.use = partspray_use;
-};

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

Diff qc/utility.qc

diff --git a/qc/utility.qc b/qc/utility.qc
index 7e98b90..d0cbe0d 100644
--- a/qc/utility.qc
+++ b/qc/utility.qc
@@ -1,218 +1,285 @@
-void(string s, string ss) dprint2 =
- { dprint(s); dprint(ss); }
-void(string s, string ss, string sss) dprint3 =
- { dprint(s); dprint(ss); dprint(sss); }
-void(string s, string ss, string sss, string ssss) dprint4 =
- { dprint(s); dprint(ss); dprint(sss); dprint(ssss); }
-void(string s, string ss, string sss, string ssss, string sssss) dprint5 =
- { dprint(s); dprint(ss); dprint(sss); dprint(ssss); dprint(sssss); }
-void(string s, string ss, string sss, string ssss, string sssss, string ssssss) dprint6 =
- { dprint(s); dprint(ss); dprint(sss); dprint(ssss); dprint(sssss); dprint(ssssss);}
-void(string s, string ss, string sss, string ssss, string sssss, string ssssss, string sssssss) dprint7 =
- { dprint(s); dprint(ss); dprint(sss); dprint(ssss); dprint(sssss); dprint(ssssss); dprint(sssssss);}
-void(string s, string ss, string sss, string ssss, string sssss, string ssssss, string sssssss, string ssssssss) dprint8 =
- { dprint(s); dprint(ss); dprint(sss); dprint(ssss); dprint(sssss); dprint(ssssss); dprint(sssssss); dprint(ssssssss); }
-void(string s, string ss, string sss, string ssss, string sssss, string ssssss, string sssssss, string ssssssss, string sssssssss) dprint9 =
- { dprint(s); dprint(ss); dprint(sss); dprint(ssss); dprint(sssss); dprint(ssssss); dprint(sssssss); dprint(ssssssss); dprint(sssssssss); }
-
-/**********************************
- Sourced from utility.qc from smej2
- **********************************/
+//==============================================================================
+// utility.qc
+//==============================================================================

+//----------------------------------------------------------------------
+// dprint shims
+//----------------------------------------------------------------------
+void(string s1, string s2) dprint2 =
+{
+ dprint (s1);
+ dprint (s2);
+};
+
+void(string s1, string s2, string s3) dprint3 =
+{
+ dprint (s1);
+ dprint (s2);
+ dprint (s3);
+};
+
+void(string s1, string s2, string s3, string s4) dprint4 =
+{
+ dprint (s1);
+ dprint (s2);
+ dprint (s3);
+ dprint (s4);
+};
+
+void(string s1, string s2, string s3, string s4, string s5) dprint5 =
+{
+ dprint (s1);
+ dprint (s2);
+ dprint (s3);
+ dprint (s4);
+ dprint (s5);
+};
+
+void(string s1, string s2, string s3, string s4, string s5, string s6) dprint6 =
+{
+ dprint (s1);
+ dprint (s2);
+ dprint (s3);
+ dprint (s4);
+ dprint (s5);
+ dprint (s6);
+};
+
+void(string s1, string s2, string s3, string s4, string s5, string s6,
+ string s7) dprint7 =
+{
+ dprint (s1);
+ dprint (s2);
+ dprint (s3);
+ dprint (s4);
+ dprint (s5);
+ dprint (s6);
+ dprint (s7);
+};

+void(string s1, string s2, string s3, string s4, string s5, string s6,
+ string s7, string s8) dprint8 =
+{
+ dprint (s1);
+ dprint (s2);
+ dprint (s3);
+ dprint (s4);
+ dprint (s5);
+ dprint (s6);
+ dprint (s7);
+ dprint (s8);
+};
+
+void(string s1, string s2, string s3, string s4, string s5, string s6,
+ string s7, string s8, string s9) dprint9 =
+{
+ dprint (s1);
+ dprint (s2);
+ dprint (s3);
+ dprint (s4);
+ dprint (s5);
+ dprint (s6);
+ dprint (s7);
+ dprint (s8);
+ dprint (s9);
+};
+
+//======================================================================
+// Sourced from utility.qc from smej2
+//======================================================================
+
+//----------------------------------------------------------------------
float(float in) bprint_int =
{
- in = floor(in);
- if (in <= 0) return 0;
+ in = floor (in);
+ if (in <= 0)
+ return 0;

- float digit;
- digit = in - bprint_int(in / 10);
+ local float digit;
+ digit = in - bprint_int (in / 10);

- switch(digit) {
- case 9:
- bprint("9"); break;
- case 8:
- bprint("8"); break;
- case 7:
- bprint("7"); break;
- case 6:
- bprint("6"); break;
- case 5:
- bprint("5"); break;
- case 4:
- bprint("4"); break;
- case 3:
- bprint("3"); break;
- case 2:
- bprint("2"); break;
- case 1:
- bprint("1"); break;
- case 0:
- bprint("0"); break;
+ switch (digit)
+ {
+ case 9: bprint("9"); break;
+ case 8: bprint("8"); break;
+ case 7: bprint("7"); break;
+ case 6: bprint("6"); break;
+ case 5: bprint("5"); break;
+ case 4: bprint("4"); break;
+ case 3: bprint("3"); break;
+ case 2: bprint("2"); break;
+ case 1: bprint("1"); break;
+ case 0: bprint("0"); break;
}

return in * 10;
-}
-
-
-float(float in, float def) defaultFl = {
- if (in) return in;
- else return def;
-}
+};

+//----------------------------------------------------------------------
+float(float in, float def) defaultFl =
+{
+ if (in)
+ return in;
+ else
+ return def;
+};

-// shorthand for turning -1 to 0 for keyvalues for which 0 is a valid non-default selection
+//----------------------------------------------------------------------
+// shorthand for turning -1 to 0 for keyvalues for which 0 is a
+// valid non-default selection
+//----------------------------------------------------------------------
float(float in) zeroconvert =
{
- if (in == -1) return 0;
+ if (in == -1)
+ return 0;
return in;
-}
+};
+
+//----------------------------------------------------------------------
float(float in, float def) zeroconvertdefault =
{
- if (in == -1) return 0;
- if (in == 0) return def;
+ if (in == -1)
+ return 0;
+ if (in == 0)
+ return def;
return in;
}

-
-
-
+//----------------------------------------------------------------------
// for measuring how large an entity is along an arbitrary vector
// FIXME: this is trash and it returns trash
+//----------------------------------------------------------------------
float(vector v, vector s) BoundsAngleSize =
{
- v_x = fabs(v_x);
- v_y = fabs(v_y);
- v_z = fabs(v_z);
+ v_x = fabs (v_x);
+ v_y = fabs (v_y);
+ v_z = fabs (v_z);

- // size is always + + + but this is in case I switch the parameters somewhere
- s_x = fabs(s_x);
- s_y = fabs(s_y);
- s_z = fabs(s_z);
+ // size is always + + + but this is in case I switch the
+ // parameters somewhere
+ s_x = fabs (s_x);
+ s_y = fabs (s_y);
+ s_z = fabs (s_z);

return v * s;
-}
+};

+//----------------------------------------------------------------------
//count -4 = numclients in coop
-/*void(.float fld) playercount_convert =
+//----------------------------------------------------------------------
+/*
+void(.float fld) playercount_convert =
{
- if (self.fld != -4) return;
+ if (self.fld != -4)
+ return;
if (!coop)
self.fld = 1;
else
self.fld = clients;
-}
+};
*/

-
+//======================================================================
// wonderful stuffcmd code from Honey by czg
+//======================================================================

-/*
-=============
-stuffcmd_float
+//----------------------------------------------------------------------
+// stuffcmd_float
+// This is a horrible hack that I am ashamed of!
+//----------------------------------------------------------------------
+void(entity client, float f) stuffcmd_digit =
+{
+ local float d;
+ d = floor (f);
+ d = mod (d, 10);

-This is a horrible hack that I am ashamed of!
-===============
-*/
-void stuffcmd_digit( entity client, float f) =
-{
- float d;
- d = floor(f);
- d = mod(d, 10);
-
- //CLOSE YOUR EYES, HONEY! DON'T LOOK!
- if(d == 0)
- stuffcmd(client, "0");
- else if(d == 1)
- stuffcmd(client, "1");
- else if(d == 2)
- stuffcmd(client, "2");
- else if(d == 3)
- stuffcmd(client, "3");
- else if(d == 4)
- stuffcmd(client, "4");
- else if(d == 5)
- stuffcmd(client, "5");
- else if(d == 6)
- stuffcmd(client, "6");
- else if(d == 7)
- stuffcmd(client, "7");
- else if(d == 8)
- stuffcmd(client, "8");
- else if(d == 9)
- stuffcmd(client, "9");
-}
+ // CLOSE YOUR EYES, HONEY! DON'T LOOK!
+ switch (d)
+ {
+ case 0: stuffcmd (client, "0"); break;
+ case 1: stuffcmd (client, "1"); break;
+ case 2: stuffcmd (client, "2"); break;
+ case 3: stuffcmd (client, "3"); break;
+ case 4: stuffcmd (client, "4"); break;
+ case 5: stuffcmd (client, "5"); break;
+ case 6: stuffcmd (client, "6"); break;
+ case 7: stuffcmd (client, "7"); break;
+ case 8: stuffcmd (client, "8"); break;
+ case 9: stuffcmd (client, "9"); break;
+ }
+};

-void stuffcmd_int( entity client, float f, float numdigits) =
+//----------------------------------------------------------------------
+void(entity client, float f, float numdigits) stuffcmd_int =
{
+ local float tmp;

- float tmp;
-
-
- if(f == 0)
+ if (f == 0)
{
- stuffcmd( client, "0");
+ stuffcmd (client, "0");
return;
}

- if(f < 0)
+ if (f < 0)
{
// Yeah sure.
- stuffcmd( client, "-");
- f = fabs(f);
+ stuffcmd (client, "-");
+ f = fabs (f);
}

- if(numdigits <= 0)
+ if (numdigits <= 0)
{
tmp = f;
numdigits = 1;
- while(tmp >= 1){
+ while (tmp >= 1)
+ {
tmp = tmp / 10;
numdigits = numdigits * 10;
}
}

- //I don't know what I'm thinking here...
- //I need to do this to get zero-padding to work.
+ // I don't know what I'm thinking here...
+ // I need to do this to get zero-padding to work.

- while( numdigits > 1 )
+ while (numdigits > 1)
{
numdigits = numdigits / 10;
tmp = f / numdigits;
- stuffcmd_digit( client, tmp);
+ stuffcmd_digit (client, tmp);
}
-}
+};

-void stuffcmd_float( entity client, float f) =
+//----------------------------------------------------------------------
+void(entity client, float f) stuffcmd_float =
{
- float intpart, decpart, isNegative;
+ local float intpart, decpart, isNegative;

isNegative = FALSE;

- if(f == 0)
+ if (f == 0)
{
- stuffcmd( client, "0");
+ stuffcmd (client, "0");
return;
}

- if(f < 0)
+ if (f < 0)
{
// easier this way
isNegative = TRUE;
- f = fabs(f);
+ f = fabs (f);
}

// 1: stuff the integer part.
- intpart = floor(f);
- if(isNegative)
- stuffcmd( client, "-");
- stuffcmd_int( client, intpart, 0);
+ intpart = floor (f);
+ if (isNegative)
+ stuffcmd (client, "-");
+ stuffcmd_int (client, intpart, 0);

// 2: stuff the decimal point.
- stuffcmd( client, ".");
+ stuffcmd (client, ".");

// 3: stuff the decimal part.
- decpart = mod( f, 1);
+ decpart = mod (f, 1);
decpart = decpart * 10000;
- stuffcmd_int( client, decpart, 10000);
-}
+ stuffcmd_int (client, decpart, 10000);
+};

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

Diff qc/weapons.qc

diff --git a/qc/weapons.qc b/qc/weapons.qc
index 5d80257..f674b26 100644
--- a/qc/weapons.qc
+++ b/qc/weapons.qc
@@ -1097,6 +1097,8 @@ void() superspike_touch =
}
else
{
+ // TODO CEV radiusdamage from spikes (for climbing purposes)
+ T_RadiusDamage (self, self.owner, 40, world);
if (self.owner.snd_hit != __NULL__ && self.owner.snd_hit != "")
{
sound (self, CHAN_WEAPON, self.owner.snd_hit, 1, ATTN_STATIC); //dumptruck_ds

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