#include "common.qh" #include "effect.qh" #include "weapon.qh" #include "misc.qh" #include "mapents_util.qh" #include "damage.qh" #include "mapents_triggers.qh" #include "mapents.qh" #include "teleport.qh" float(float d) _takedamage_use = { if (time < self.attack_finished) return FALSE; self.attack_finished = time + self.wait; self.health -= d; if (self.health <= 0) { self.health = self.max_health; if (util_use_targets()) self.use(); } deathmsg_nodisplay(); if (self.wait <= 0) { self.solid = SOLID_NOT; util_map_entity_cull(); } return FALSE; /* Lie */ }; void() _trigger_generic_touch = { local void() selfuse; if (!is_living(other)) return; if (time < self.attack_finished) return; self.attack_finished = time + self.wait; selfuse = self.use; self.use = NOTHING_function; /* Avoid endless loop */ if (util_use_targets()) selfuse(); self.use = selfuse; if (self.wait <= 0) { self.solid = SOLID_NOT; util_map_entity_cull(); } }; /*QUAKED trigger_generic (.5 .5 .5) NOTOUCH Variable sized repeatable trigger. Must be targeted at one or more entities. If "model" is set, the trigger will set it as its model. If "health" is set, trigger must be killed to activate each time. If "delay" is set, the trigger waits some time after activating before firing. If "wait" is set, the trigger waits some time before able to trigger again. If "count" is > 0, the trigger will only trigger count times. If notouch is set, the trigger is only fired by other entities, not by touching or killing. "noise1" is played at the trigger when triggered, if set. "noise2" is played to the activator when triggered, if set. "message" is displayed when triggered, if set. */ void() trigger_generic = { /* Get mins/maxs */ setmodel(self, self.model); /* Avoid displaying triggers */ self.model = ""; self.modelindex = 0; if (self.health) { self.max_health = self.health; self.solid = SOLID_BBOX; self.takedamage = DAMAGE_YES; self.th_takedamage = _takedamage_use; } if (!self.solid) { if (!(self.spawnflags & SPAWNFLAGS_TRIGGER_NOTOUCH)) { self.solid = SOLID_TRIGGER; self.touch = _trigger_generic_touch; } } /* FIXME: This is a hackaround for qwsv */ if (self.origin == '0 0 0') { self.origin = (self.mins + self.maxs) * 0.5; self.mins = self.mins - self.origin; self.maxs = self.maxs - self.origin; setsize(self, self.mins, self.maxs); setorigin(self, self.origin); } if (!self.use) self.use = NOTHING_function; util_map_entity_init(); util_map_entity_cull(); }; /*QUAKED info_teleport_destination (.5 .5 .5) (-8 -8 -8) (8 8 32) This is the destination marker for a teleporter. It should have a "targetname" field with the same value as a teleporter's "target" field. */ void() info_teleport_destination = { self.origin = self.origin + '0 0 27'; info_notnull(); }; void() _trigger_teleport_touch = { local entity spot; local float spd; if (!is_teleportable(other)) return; spot = find(world, targetname, self.target); if (!spot) { damage(other, other, other, DAMAGE_MUSTDIE, NOTHING_function); return; } effect_teleport_fog(other.origin); teleport(other, spot); spd = vlen(other.velocity); makevectors(other.angles); other.velocity = v_forward * spd; }; #define SPAWNFLAGS_SILENT 2 /*QUAKED trigger_teleport (.5 .5 .5) ? PLAYER_ONLY SILENT Any object touching this will be transported to the corresponding info_teleport_destination entity. You must set the "target" field, and create an object with a "targetname" field that matches. If the trigger_teleport has a targetname, it will only teleport entities when it has been fired. */ void() trigger_teleport = { if (!(self.spawnflags & SPAWNFLAGS_SILENT) && !self.noise) self.noise = "ambience/hum1.wav"; setmodel(self, self.model); self.model = NIL; self.modelindex = 0; util_map_entity_init(); self.solid = SOLID_TRIGGER; self.touch = _trigger_teleport_touch; self.use = _trigger_teleport_touch; }; void() _trigger_hurt_deathmsg = { bprint(PRINT_DEATH, name(self), " was in the wrong place.\n"); }; void() _trigger_hurt_use = { damage(other, self, self, self.dmg, _trigger_hurt_deathmsg); }; /*QUAKED trigger_hurt (.5 .5 .5) ? Any object touching this will be hurt set dmg to damage amount */ void() trigger_hurt = { if (!self.wait) self.wait = 1; trigger_generic(); self.use = _trigger_hurt_use; }; #define SPAWNFLAGS_PUSH_ONCE 1 #define SPAWNFLAGS_PUSH_ADD 2 void() _trigger_push_use = { if (!is_solid(other)) return; if (!util_use_targets()) return; if (self.spawnflags & SPAWNFLAGS_PUSH_ADD) other.velocity = other.velocity + self.movedir; else other.velocity = self.movedir; if (!is_living(other)) return; if (self.noise3) sound(other, CHAN_AUTO, self.noise3, 1, ATTN_NORM); }; /*QUAKED trigger_push (.5 .5 .5) ? PUSH_ADD PUSH_ONCE Pushes the player */ void() trigger_push = { if (!self.wait) self.wait = 1; if (!self.speed) self.speed = 1000; if (!self.noise1 && !self.noise2 && !self.noise3) self.noise3 = "ambience/windfly.wav"; if (self.noise3) precache_sound(self.noise3); if (self.spawnflags & SPAWNFLAGS_PUSH_ONCE) self.count = 1; trigger_generic(); util_set_movedir(); self.movedir = self.movedir * self.speed * 10; self.use = _trigger_push_use; }; #define SPAWNFLAGS_NO_INTERMISSION 1 void() _trigger_changelevel_do = { local string nextmap; nextmap = self.map; if (!self.map) nextmap = "start.bsp"; changelevel(nextmap); }; void() _trigger_changelevel_use = { if (!is_living(other) || !is_cl(other)) return; // Bleah. self.touch = NOTHING_function; self.think = _trigger_changelevel_do; self.nextthink = time; }; /*QUAKED trigger_changelevel (.5 .5 .5) ? NO_INTERMISSION When a player touches this, the level changes. The level will change to the map set in the map variable. If it is not set, the map will change to a random level in the list. If NO_INTERMISSION is set, the view will not go to an info_intermission spot and display stats in co-op games. */ void() trigger_changelevel = { trigger_generic(); self.use = _trigger_changelevel_use; };