quake-rerelease-qc/quakec_mg1/plats.qc

394 lines
8.5 KiB
C++

/* Copyright (C) 1996-2022 id Software LLC
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
See file, 'COPYING', for details.
*/
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 =
{
if (other.classname != "player")
return;
if (other.health <= 0)
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 =
{
if (other.classname != "player")
return;
if (other.health <= 0)
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
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 (!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;
}
};
//============================================================================
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);
};
void() train_use =
{
if (self.think != func_train_find)
return; // already activated
train_next();
};
void() train_wait =
{
if (self.wait)
{
self.nextthink = self.ltime + self.wait;
sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
}
else
self.nextthink = self.ltime + 0.1;
self.think = train_next;
};
void() train_next =
{
local entity targ;
targ = find (world, targetname, self.target);
self.target = targ.target;
if (!self.target)
objerror ("train_next: no next target");
if (targ.wait)
self.wait = targ.wait;
else
self.wait = 0;
sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
SUB_CalcMove (targ.origin - self.mins, self.speed, train_wait);
};
void() func_train_find =
{
local entity targ;
targ = find (world, targetname, self.target);
self.target = targ.target;
setorigin (self, targ.origin - self.mins);
if (!self.targetname)
{ // not triggered, so start immediately
self.nextthink = self.ltime + 0.1;
self.think = train_next;
}
};
const float FUNC_TRAIN_NONSOLID = 1;
/*QUAKED func_train (0 .5 .8) ?
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.
speed default 100
dmg default 2
sounds
1) ratchet metal
*/
void() func_train =
{
if (!self.speed)
self.speed = 100;
if (!self.target)
objerror ("func_train without a target");
if (!self.dmg)
self.dmg = 2;
if (self.sounds == 0)
{
self.noise = ("misc/null.wav");
precache_sound ("misc/null.wav");
self.noise1 = ("misc/null.wav");
precache_sound ("misc/null.wav");
}
if (self.sounds == 1)
{
self.noise = ("plats/train2.wav");//stop sound
precache_sound ("plats/train2.wav");
self.noise1 = ("plats/train1.wav");//move sound
precache_sound ("plats/train1.wav");
}
self.cnt = 1;
if(self.spawnflags & FUNC_TRAIN_NONSOLID)
{
self.solid = SOLID_NOT;
self.movetype = MOVETYPE_PUSH;
//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
self.nextthink = self.ltime + 0.1;
self.think = func_train_find;
};
/*QUAKED misc_teleporttrain (0 .5 .8) (-8 -8 -8) (8 8 8)
This is used for the final bos
*/
void() misc_teleporttrain =
{
if (!self.speed)
self.speed = 100;
if (!self.target)
objerror ("func_train without a target");
self.cnt = 1;
self.solid = SOLID_NOT;
self.movetype = MOVETYPE_PUSH;
self.blocked = train_blocked;
self.use = train_use;
self.avelocity = '100 200 300';
self.noise = ("misc/null.wav");
precache_sound ("misc/null.wav");
self.noise1 = ("misc/null.wav");
precache_sound ("misc/null.wav");
precache_model2 ("progs/teleport.mdl");
setmodel (self, "progs/teleport.mdl");
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.nextthink = self.ltime + 0.1;
self.think = func_train_find;
};