199 lines
4.6 KiB
Plaintext
199 lines
4.6 KiB
Plaintext
static enumflags { TELEPORT_PLAYER_ONLY, TELEPORT_SILENT };
|
|
|
|
/*==========
|
|
play_teleport
|
|
==========*/
|
|
static void() play_teleport =
|
|
{
|
|
float r = randomrange(5);
|
|
if (r == 0)
|
|
sound (self, CHAN_VOICE, "misc/r_tele1.wav", 1, ATTN_NORM);
|
|
else if (r == 1)
|
|
sound (self, CHAN_VOICE, "misc/r_tele2.wav", 1, ATTN_NORM);
|
|
else if (r == 2)
|
|
sound (self, CHAN_VOICE, "misc/r_tele3.wav", 1, ATTN_NORM);
|
|
else if (r == 3)
|
|
sound (self, CHAN_VOICE, "misc/r_tele4.wav", 1, ATTN_NORM);
|
|
else
|
|
sound (self, CHAN_VOICE, "misc/r_tele5.wav", 1, ATTN_NORM);
|
|
|
|
remove(self);
|
|
};
|
|
|
|
/*==========
|
|
spawn_tfog
|
|
==========*/
|
|
void(vector org) spawn_tfog =
|
|
{
|
|
te_teleport(org);
|
|
|
|
entity e = spawn();
|
|
setorigin(e, org);
|
|
e.think = play_teleport;
|
|
e.nextthink = time + 0.2; // delay sound slightly
|
|
};
|
|
|
|
/*==========
|
|
tdeath_touch
|
|
==========*/
|
|
static void() tdeath_touch =
|
|
{
|
|
if (!other.takedamage)
|
|
return;
|
|
if (other == self.owner) // the engine doesn't respect .owner for triggers!
|
|
return;
|
|
|
|
if (other.classname == "player")
|
|
{
|
|
// monsters can't telefrag players
|
|
if (self.owner.flags & FL_MONSTER)
|
|
{
|
|
Damage (self.owner, self, self, 50000);
|
|
return;
|
|
}
|
|
|
|
// check for pentagram on the player on the spot
|
|
if (other.items & IT_INVULNERABILITY)
|
|
{
|
|
// check for pentagram on both players
|
|
if (self.owner.items & IT_INVULNERABILITY)
|
|
{
|
|
// kill the player on the spot
|
|
self.classname = "teledeath3";
|
|
other.items = other.items - IT_INVULNERABILITY;
|
|
other.invincible_time = other.invincible_finished = 0;
|
|
Damage (other, self, self, 50000);
|
|
}
|
|
else
|
|
{
|
|
// kill the teleporting player
|
|
self.classname = "teledeath2";
|
|
Damage (self.owner, self, self, 50000);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
Damage(other, self, self, 50000);
|
|
};
|
|
|
|
/*==========
|
|
spawn_tdeath
|
|
==========*/
|
|
void(vector org, entity who) spawn_tdeath =
|
|
{
|
|
force_retouch = 2; // make sure even still objects get hit
|
|
|
|
entity e = spawn();
|
|
e.classname = "teledeath";
|
|
e.owner = who;
|
|
e.movetype = MOVETYPE_NONE;
|
|
e.solid = SOLID_TRIGGER;
|
|
setsize (e, who.mins - '1 1 1', who.maxs + '1 1 1');
|
|
setorigin (e, org);
|
|
e.touch = tdeath_touch;
|
|
e.think = SUB_Remove;
|
|
e.nextthink = time + 0.2;
|
|
};
|
|
|
|
/*==========
|
|
teleport_touch
|
|
==========*/
|
|
static void() teleport_touch =
|
|
{
|
|
if (self.spawnflags & TELEPORT_PLAYER_ONLY)
|
|
{
|
|
if (other.classname != "player")
|
|
return;
|
|
}
|
|
if (other.health <= 0)
|
|
return;
|
|
if (other.solid != SOLID_SLIDEBOX) // only players/monsters
|
|
return;
|
|
|
|
// look for the destination spot
|
|
entity t = find (world, targetname, self.target);
|
|
if (!t)
|
|
{
|
|
objerror ("couldn't find target");
|
|
remove(self);
|
|
return;
|
|
}
|
|
|
|
// some maps use things other then info_teleport_destination as targets for
|
|
// teleporters. just print a warning.
|
|
if (developer > 1)
|
|
{
|
|
if (t.classname != "info_teleport_destination")
|
|
{
|
|
dprint("warning: teleport destination is ");
|
|
dprint(t.classname);
|
|
dprint(" at ");
|
|
dprint(vtos(t.origin));
|
|
dprint("\n");
|
|
}
|
|
}
|
|
|
|
// fire targets
|
|
activator = other;
|
|
UseTargets();
|
|
|
|
// spawn teleport flash at source and destination
|
|
spawn_tfog (other.origin);
|
|
makevectors (t.angles);
|
|
vector org = t.origin + '0 0 27';
|
|
spawn_tfog (org + v_forward * 32);
|
|
spawn_tdeath(org, other);
|
|
|
|
// move the player/monster
|
|
setorigin (other, org);
|
|
other.angles = t.angles;
|
|
other.flags = other.flags - (other.flags & FL_ONGROUND);
|
|
if (other.classname == "player")
|
|
{
|
|
other.fixangle = TRUE; // turn this way immediately
|
|
other.teleport_time = time + 0.7; // don't let player move back into teleporter
|
|
other.velocity = v_forward * 300; // give a forwards push
|
|
}
|
|
};
|
|
|
|
/*==========
|
|
teleport_use
|
|
|
|
using a teleporter makes it active. it then behaves like any other teleporter.
|
|
==========*/
|
|
static void() teleport_use =
|
|
{
|
|
force_retouch = 2; // make sure even still objects get hit
|
|
self.touch = teleport_touch;
|
|
self.use = SUB_Null;
|
|
};
|
|
|
|
/*QUAKED trigger_teleport (.5 .5 .5) ? PLAYER_ONLY SILENT X X X X X X NOT_IN_EASY NOT_IN_NORMAL NOT_IN_HARD NOT_IN_DM
|
|
Variable sized trigger that teleports players and monsters to a destination marker.
|
|
"target" must be set to an info_teleport_destination with a matching "targetname" field.
|
|
If the trigger_teleport has a "targetname", it will only teleport entities once it has been triggered.
|
|
This is used in id1 for teleporting monsters - this has been obsoleted by the MONSTER_TELEPORT flag.
|
|
|
|
Spawnflags:
|
|
PLAYER_ONLY - just players, not monsters
|
|
SILENT - don't spawn ambient teleporter noise
|
|
*/
|
|
void() trigger_teleport =
|
|
{
|
|
if (!self.target)
|
|
{
|
|
objerror ("no target");
|
|
remove(self);
|
|
return;
|
|
}
|
|
if (self.targetname != "")
|
|
self.use = teleport_use;
|
|
else
|
|
self.touch = teleport_touch;
|
|
|
|
if (!(self.spawnflags & TELEPORT_SILENT))
|
|
ambient_teleport();
|
|
|
|
InitTrigger();
|
|
};
|