#include <u.h>#include <libc.h>#include <stdio.h>#include "../dat.h"#include "../fns.h" /*QUAKED target_temp_entity (1 0 0) (-8 -8 -8) (8 8 8)Fire an origin based temp entity event to the clients."style" type byte*/void Use_Target_Tent (edict_t *ent, edict_t */*other*/, edict_t */*activator*/){ gi.WriteByte (svc_temp_entity); gi.WriteByte (ent->style); gi.WritePosition (ent->s.origin); gi.multicast (ent->s.origin, MULTICAST_PVS);} void SP_target_temp_entity (edict_t *ent){ ent->use = Use_Target_Tent;} //========================================================== //========================================================== /*QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off reliable"noise" wav file to play"attenuation"-1 = none, send to whole level1 = normal fighting sounds2 = idle sound level3 = ambient sound level"volume" 0.0 to 1.0 Normal sounds play each time the target is used. The reliable flag can be set for crucial voiceovers. Looped sounds are always atten 3 / vol 1, and the use function toggles it on/off.Multiple identical looping sounds will just increase volume without any speed cost.*/void Use_Target_Speaker (edict_t *ent, edict_t */*other*/, edict_t */*activator*/){ int chan; if (ent->spawnflags & 3) { // looping sound toggles if (ent->s.sound) ent->s.sound = 0; // turn it off else ent->s.sound = ent->noise_index; // start it } else { // normal sound if (ent->spawnflags & 4) chan = CHAN_VOICE|CHAN_RELIABLE; else chan = CHAN_VOICE; // use a positioned_sound, because this entity won't normally be // sent to any clients because it is invisible gi.positioned_sound (ent->s.origin, ent, chan, ent->noise_index, ent->volume, ent->attenuation, 0); }} void SP_target_speaker (edict_t *ent){ char buffer[MAX_QPATH]; if(!st.noise) { gi.dprintf("target_speaker with no noise set at %s\n", vtos(ent->s.origin)); return; } if (!strstr (st.noise, ".wav")) Com_sprintf (buffer, sizeof(buffer), "%s.wav", st.noise); else strncpy (buffer, st.noise, sizeof(buffer)); ent->noise_index = gi.soundindex (buffer); if (!ent->volume) ent->volume = 1.0; if (!ent->attenuation) ent->attenuation = 1.0; else if (ent->attenuation == -1) // use -1 so 0 defaults to 1 ent->attenuation = 0; // check for prestarted looping sound if (ent->spawnflags & 1) ent->s.sound = ent->noise_index; ent->use = Use_Target_Speaker; // must link the entity so we get areas and clusters so // the server can determine who to send updates to gi.linkentity (ent);} //========================================================== void Use_Target_Help (edict_t *ent, edict_t */*other*/, edict_t */*activator*/){ if (ent->spawnflags & 1) strncpy (game.helpmessage1, ent->message, sizeof(game.helpmessage2)-1); else strncpy (game.helpmessage2, ent->message, sizeof(game.helpmessage1)-1); game.helpchanged++;} /*QUAKED target_help (1 0 1) (-16 -16 -24) (16 16 24) help1When fired, the "message" key becomes the current personal computer string, and the message light will be set on all clients status bars.*/void SP_target_help(edict_t *ent){ if (deathmatch->value) { // auto-remove for deathmatch G_FreeEdict (ent); return; } if (!ent->message) { gi.dprintf ("%s with no message at %s\n", ent->classname, vtos(ent->s.origin)); G_FreeEdict (ent); return; } ent->use = Use_Target_Help;} //========================================================== /*QUAKED target_secret (1 0 1) (-8 -8 -8) (8 8 8)Counts a secret found.These are single use targets.*/void use_target_secret (edict_t *ent, edict_t */*other*/, edict_t *activator){ gi.sound (ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0); level.found_secrets++; G_UseTargets (ent, activator); G_FreeEdict (ent);} void SP_target_secret (edict_t *ent){ if (deathmatch->value) { // auto-remove for deathmatch G_FreeEdict (ent); return; } ent->use = use_target_secret; if (!st.noise) st.noise = "misc/secret.wav"; ent->noise_index = gi.soundindex (st.noise); ent->svflags = SVF_NOCLIENT; level.total_secrets++; // map bug hack if (!cistrcmp(level.mapname, "mine3") && ent->s.origin[0] == 280 && ent->s.origin[1] == -2048 && ent->s.origin[2] == -624) ent->message = "You have found a secret area.";} //========================================================== /*QUAKED target_goal (1 0 1) (-8 -8 -8) (8 8 8)Counts a goal completed.These are single use targets.*/void use_target_goal (edict_t *ent, edict_t */*other*/, edict_t *activator){ gi.sound (ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0); level.found_goals++; if (level.found_goals == level.total_goals) gi.configstring (CS_CDTRACK, "0"); G_UseTargets (ent, activator); G_FreeEdict (ent);} void SP_target_goal (edict_t *ent){ if (deathmatch->value) { // auto-remove for deathmatch G_FreeEdict (ent); return; } ent->use = use_target_goal; if (!st.noise) st.noise = "misc/secret.wav"; ent->noise_index = gi.soundindex (st.noise); ent->svflags = SVF_NOCLIENT; level.total_goals++;} //========================================================== /*QUAKED target_explosion (1 0 0) (-8 -8 -8) (8 8 8)Spawns an explosion temporary entity when used. "delay" wait this long before going off"dmg" how much radius damage should be done, defaults to 0*/void target_explosion_explode (edict_t *self){ float save; gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_EXPLOSION1); gi.WritePosition (self->s.origin); gi.multicast (self->s.origin, MULTICAST_PHS); T_RadiusDamage (self, self->activator, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE); save = self->delay; self->delay = 0; G_UseTargets (self, self->activator); self->delay = save;} void use_target_explosion (edict_t *self, edict_t */*other*/, edict_t *activator){ self->activator = activator; if (!self->delay) { target_explosion_explode (self); return; } self->think = target_explosion_explode; self->nextthink = level.time + self->delay;} void SP_target_explosion (edict_t *ent){ ent->use = use_target_explosion; ent->svflags = SVF_NOCLIENT;} //========================================================== /*QUAKED target_changelevel (1 0 0) (-8 -8 -8) (8 8 8)Changes level to "map" when fired*/void use_target_changelevel (edict_t *self, edict_t *other, edict_t *activator){ if (level.intermissiontime) return; // already activated if (!deathmatch->value && !coop->value) { if (g_edicts[1].health <= 0) return; } // if noexit, do a ton of damage to other if (deathmatch->value && !( (int)dmflags->value & DF_ALLOW_EXIT) && other != WORLD) { T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 10 * other->max_health, 1000, 0, MOD_EXIT); return; } // if multiplayer, let everyone know who hit the exit if (deathmatch->value) { if (activator && activator->client) gi.bprintf (PRINT_HIGH, "%s exited the level.\n", activator->client->pers.netname); } // if going to a new unit, clear cross triggers if (strstr(self->map, "*")) game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); BeginIntermission (self);} void SP_target_changelevel (edict_t *ent){ if (!ent->map) { gi.dprintf("target_changelevel with no map at %s\n", vtos(ent->s.origin)); G_FreeEdict (ent); return; } // ugly hack because *SOMEBODY* screwed up their map if((cistrcmp(level.mapname, "fact1") == 0) && (cistrcmp(ent->map, "fact3") == 0)) ent->map = "fact3$secret1"; ent->use = use_target_changelevel; ent->svflags = SVF_NOCLIENT;} //========================================================== /*QUAKED target_splash (1 0 0) (-8 -8 -8) (8 8 8)Creates a particle splash effect when used. Set "sounds" to one of the following: 1) sparks 2) blue water 3) brown water 4) slime 5) lava 6) blood "count" how many pixels in the splash"dmg" if set, does a radius damage at this location when it splashes useful for lava/sparks*/ void use_target_splash (edict_t *self, edict_t */*other*/, edict_t *activator){ gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_SPLASH); gi.WriteByte (self->count); gi.WritePosition (self->s.origin); gi.WriteDir (self->movedir); gi.WriteByte (self->sounds); gi.multicast (self->s.origin, MULTICAST_PVS); if (self->dmg) T_RadiusDamage (self, activator, self->dmg, NULL, self->dmg+40, MOD_SPLASH);} void SP_target_splash (edict_t *self){ self->use = use_target_splash; G_SetMovedir (self->s.angles, self->movedir); if (!self->count) self->count = 32; self->svflags = SVF_NOCLIENT;} //========================================================== /*QUAKED target_spawner (1 0 0) (-8 -8 -8) (8 8 8)Set target to the type of entity you want spawned.Useful for spawning monsters and gibs in the factory levels. For monsters: Set direction to the facing you want it to have. For gibs: Set direction if you want it moving and speed how fast it should be moving otherwise it will just be dropped*/void ED_CallSpawn (edict_t *ent); void use_target_spawner (edict_t *self, edict_t */*other*/, edict_t */*activator*/){ edict_t *ent; ent = G_Spawn(); ent->classname = self->target; VectorCopy (self->s.origin, ent->s.origin); VectorCopy (self->s.angles, ent->s.angles); ED_CallSpawn (ent); gi.unlinkentity (ent); KillBox (ent); gi.linkentity (ent); if (self->speed) VectorCopy (self->movedir, ent->velocity);} void SP_target_spawner (edict_t *self){ self->use = use_target_spawner; self->svflags = SVF_NOCLIENT; if (self->speed) { G_SetMovedir (self->s.angles, self->movedir); VectorScale (self->movedir, self->speed, self->movedir); }} //========================================================== /*QUAKED target_blaster (1 0 0) (-8 -8 -8) (8 8 8) NOTRAIL NOEFFECTSFires a blaster bolt in the set direction when triggered. dmg default is 15speed default is 1000*/ void use_target_blaster (edict_t *self, edict_t */*other*/, edict_t */*activator*/){ /* int effect; if (self->spawnflags & 2) effect = 0; else if (self->spawnflags & 1) effect = EF_HYPERBLASTER; else effect = EF_BLASTER; */ fire_blaster (self, self->s.origin, self->movedir, self->dmg, self->speed, EF_BLASTER, MOD_TARGET_BLASTER); gi.sound (self, CHAN_VOICE, self->noise_index, 1, ATTN_NORM, 0);} void SP_target_blaster (edict_t *self){ self->use = use_target_blaster; G_SetMovedir (self->s.angles, self->movedir); self->noise_index = gi.soundindex ("weapons/laser2.wav"); if (!self->dmg) self->dmg = 15; if (!self->speed) self->speed = 1000; self->svflags = SVF_NOCLIENT;} //========================================================== /*QUAKED target_crosslevel_trigger (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8Once this trigger is touched/used, any trigger_crosslevel_target with the same trigger number is automatically used when a level is started within the same unit. It is OK to check multiple triggers. Message, delay, target, and killtarget also work.*/void trigger_crosslevel_trigger_use (edict_t *self, edict_t */*other*/, edict_t */*activator*/){ game.serverflags |= self->spawnflags; G_FreeEdict (self);} void SP_target_crosslevel_trigger (edict_t *self){ self->svflags = SVF_NOCLIENT; self->use = trigger_crosslevel_trigger_use;} /*QUAKED target_crosslevel_target (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8Triggered by a trigger_crosslevel elsewhere within a unit. If multiple triggers are checked, all must be true. Delay, target andkilltarget also work. "delay" delay before using targets if the trigger has been activated (default 1)*/void target_crosslevel_target_think (edict_t *self){ if (self->spawnflags == (game.serverflags & SFL_CROSS_TRIGGER_MASK & self->spawnflags)) { G_UseTargets (self, self); G_FreeEdict (self); }} void SP_target_crosslevel_target (edict_t *self){ if (! self->delay) self->delay = 1; self->svflags = SVF_NOCLIENT; self->think = target_crosslevel_target_think; self->nextthink = level.time + self->delay;} //========================================================== /*QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON RED GREEN BLUE YELLOW ORANGE FATWhen triggered, fires a laser. You can either set a targetor a direction.*/ void target_laser_think (edict_t *self){ edict_t *ignore; vec3_t start; vec3_t end; trace_t tr; vec3_t point; vec3_t last_movedir; int count; if (self->spawnflags & 0x80000000) count = 8; else count = 4; if (self->enemy) { VectorCopy (self->movedir, last_movedir); VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point);Lines 1–500 of 796. Load more
#include <u.h> #include <libc.h> #include <stdio.h> #include "../dat.h" #include "../fns.h" /*QUAKED target_temp_entity (1 0 0) (-8 -8 -8) (8 8 8) Fire an origin based temp entity event to the clients. "style" type byte */ void Use_Target_Tent (edict_t *ent, edict_t */*other*/, edict_t */*activator*/) { gi.WriteByte (svc_temp_entity); gi.WriteByte (ent->style); gi.WritePosition (ent->s.origin); gi.multicast (ent->s.origin, MULTICAST_PVS); } void SP_target_temp_entity (edict_t *ent) { ent->use = Use_Target_Tent; } //========================================================== //========================================================== /*QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off reliable "noise" wav file to play "attenuation" -1 = none, send to whole level 1 = normal fighting sounds 2 = idle sound level 3 = ambient sound level "volume" 0.0 to 1.0 Normal sounds play each time the target is used. The reliable flag can be set for crucial voiceovers. Looped sounds are always atten 3 / vol 1, and the use function toggles it on/off. Multiple identical looping sounds will just increase volume without any speed cost. */ void Use_Target_Speaker (edict_t *ent, edict_t */*other*/, edict_t */*activator*/) { int chan; if (ent->spawnflags & 3) { // looping sound toggles if (ent->s.sound) ent->s.sound = 0; // turn it off else ent->s.sound = ent->noise_index; // start it } else { // normal sound if (ent->spawnflags & 4) chan = CHAN_VOICE|CHAN_RELIABLE; else chan = CHAN_VOICE; // use a positioned_sound, because this entity won't normally be // sent to any clients because it is invisible gi.positioned_sound (ent->s.origin, ent, chan, ent->noise_index, ent->volume, ent->attenuation, 0); } } void SP_target_speaker (edict_t *ent) { char buffer[MAX_QPATH]; if(!st.noise) { gi.dprintf("target_speaker with no noise set at %s\n", vtos(ent->s.origin)); return; } if (!strstr (st.noise, ".wav")) Com_sprintf (buffer, sizeof(buffer), "%s.wav", st.noise); else strncpy (buffer, st.noise, sizeof(buffer)); ent->noise_index = gi.soundindex (buffer); if (!ent->volume) ent->volume = 1.0; if (!ent->attenuation) ent->attenuation = 1.0; else if (ent->attenuation == -1) // use -1 so 0 defaults to 1 ent->attenuation = 0; // check for prestarted looping sound if (ent->spawnflags & 1) ent->s.sound = ent->noise_index; ent->use = Use_Target_Speaker; // must link the entity so we get areas and clusters so // the server can determine who to send updates to gi.linkentity (ent); } //========================================================== void Use_Target_Help (edict_t *ent, edict_t */*other*/, edict_t */*activator*/) { if (ent->spawnflags & 1) strncpy (game.helpmessage1, ent->message, sizeof(game.helpmessage2)-1); else strncpy (game.helpmessage2, ent->message, sizeof(game.helpmessage1)-1); game.helpchanged++; } /*QUAKED target_help (1 0 1) (-16 -16 -24) (16 16 24) help1 When fired, the "message" key becomes the current personal computer string, and the message light will be set on all clients status bars. */ void SP_target_help(edict_t *ent) { if (deathmatch->value) { // auto-remove for deathmatch G_FreeEdict (ent); return; } if (!ent->message) { gi.dprintf ("%s with no message at %s\n", ent->classname, vtos(ent->s.origin)); G_FreeEdict (ent); return; } ent->use = Use_Target_Help; } //========================================================== /*QUAKED target_secret (1 0 1) (-8 -8 -8) (8 8 8) Counts a secret found. These are single use targets. */ void use_target_secret (edict_t *ent, edict_t */*other*/, edict_t *activator) { gi.sound (ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0); level.found_secrets++; G_UseTargets (ent, activator); G_FreeEdict (ent); } void SP_target_secret (edict_t *ent) { if (deathmatch->value) { // auto-remove for deathmatch G_FreeEdict (ent); return; } ent->use = use_target_secret; if (!st.noise) st.noise = "misc/secret.wav"; ent->noise_index = gi.soundindex (st.noise); ent->svflags = SVF_NOCLIENT; level.total_secrets++; // map bug hack if (!cistrcmp(level.mapname, "mine3") && ent->s.origin[0] == 280 && ent->s.origin[1] == -2048 && ent->s.origin[2] == -624) ent->message = "You have found a secret area."; } //========================================================== /*QUAKED target_goal (1 0 1) (-8 -8 -8) (8 8 8) Counts a goal completed. These are single use targets. */ void use_target_goal (edict_t *ent, edict_t */*other*/, edict_t *activator) { gi.sound (ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0); level.found_goals++; if (level.found_goals == level.total_goals) gi.configstring (CS_CDTRACK, "0"); G_UseTargets (ent, activator); G_FreeEdict (ent); } void SP_target_goal (edict_t *ent) { if (deathmatch->value) { // auto-remove for deathmatch G_FreeEdict (ent); return; } ent->use = use_target_goal; if (!st.noise) st.noise = "misc/secret.wav"; ent->noise_index = gi.soundindex (st.noise); ent->svflags = SVF_NOCLIENT; level.total_goals++; } //========================================================== /*QUAKED target_explosion (1 0 0) (-8 -8 -8) (8 8 8) Spawns an explosion temporary entity when used. "delay" wait this long before going off "dmg" how much radius damage should be done, defaults to 0 */ void target_explosion_explode (edict_t *self) { float save; gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_EXPLOSION1); gi.WritePosition (self->s.origin); gi.multicast (self->s.origin, MULTICAST_PHS); T_RadiusDamage (self, self->activator, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE); save = self->delay; self->delay = 0; G_UseTargets (self, self->activator); self->delay = save; } void use_target_explosion (edict_t *self, edict_t */*other*/, edict_t *activator) { self->activator = activator; if (!self->delay) { target_explosion_explode (self); return; } self->think = target_explosion_explode; self->nextthink = level.time + self->delay; } void SP_target_explosion (edict_t *ent) { ent->use = use_target_explosion; ent->svflags = SVF_NOCLIENT; } //========================================================== /*QUAKED target_changelevel (1 0 0) (-8 -8 -8) (8 8 8) Changes level to "map" when fired */ void use_target_changelevel (edict_t *self, edict_t *other, edict_t *activator) { if (level.intermissiontime) return; // already activated if (!deathmatch->value && !coop->value) { if (g_edicts[1].health <= 0) return; } // if noexit, do a ton of damage to other if (deathmatch->value && !( (int)dmflags->value & DF_ALLOW_EXIT) && other != WORLD) { T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 10 * other->max_health, 1000, 0, MOD_EXIT); return; } // if multiplayer, let everyone know who hit the exit if (deathmatch->value) { if (activator && activator->client) gi.bprintf (PRINT_HIGH, "%s exited the level.\n", activator->client->pers.netname); } // if going to a new unit, clear cross triggers if (strstr(self->map, "*")) game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); BeginIntermission (self); } void SP_target_changelevel (edict_t *ent) { if (!ent->map) { gi.dprintf("target_changelevel with no map at %s\n", vtos(ent->s.origin)); G_FreeEdict (ent); return; } // ugly hack because *SOMEBODY* screwed up their map if((cistrcmp(level.mapname, "fact1") == 0) && (cistrcmp(ent->map, "fact3") == 0)) ent->map = "fact3$secret1"; ent->use = use_target_changelevel; ent->svflags = SVF_NOCLIENT; } //========================================================== /*QUAKED target_splash (1 0 0) (-8 -8 -8) (8 8 8) Creates a particle splash effect when used. Set "sounds" to one of the following: 1) sparks 2) blue water 3) brown water 4) slime 5) lava 6) blood "count" how many pixels in the splash "dmg" if set, does a radius damage at this location when it splashes useful for lava/sparks */ void use_target_splash (edict_t *self, edict_t */*other*/, edict_t *activator) { gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_SPLASH); gi.WriteByte (self->count); gi.WritePosition (self->s.origin); gi.WriteDir (self->movedir); gi.WriteByte (self->sounds); gi.multicast (self->s.origin, MULTICAST_PVS); if (self->dmg) T_RadiusDamage (self, activator, self->dmg, NULL, self->dmg+40, MOD_SPLASH); } void SP_target_splash (edict_t *self) { self->use = use_target_splash; G_SetMovedir (self->s.angles, self->movedir); if (!self->count) self->count = 32; self->svflags = SVF_NOCLIENT; } //========================================================== /*QUAKED target_spawner (1 0 0) (-8 -8 -8) (8 8 8) Set target to the type of entity you want spawned. Useful for spawning monsters and gibs in the factory levels. For monsters: Set direction to the facing you want it to have. For gibs: Set direction if you want it moving and speed how fast it should be moving otherwise it will just be dropped */ void ED_CallSpawn (edict_t *ent); void use_target_spawner (edict_t *self, edict_t */*other*/, edict_t */*activator*/) { edict_t *ent; ent = G_Spawn(); ent->classname = self->target; VectorCopy (self->s.origin, ent->s.origin); VectorCopy (self->s.angles, ent->s.angles); ED_CallSpawn (ent); gi.unlinkentity (ent); KillBox (ent); gi.linkentity (ent); if (self->speed) VectorCopy (self->movedir, ent->velocity); } void SP_target_spawner (edict_t *self) { self->use = use_target_spawner; self->svflags = SVF_NOCLIENT; if (self->speed) { G_SetMovedir (self->s.angles, self->movedir); VectorScale (self->movedir, self->speed, self->movedir); } } //========================================================== /*QUAKED target_blaster (1 0 0) (-8 -8 -8) (8 8 8) NOTRAIL NOEFFECTS Fires a blaster bolt in the set direction when triggered. dmg default is 15 speed default is 1000 */ void use_target_blaster (edict_t *self, edict_t */*other*/, edict_t */*activator*/) { /* int effect; if (self->spawnflags & 2) effect = 0; else if (self->spawnflags & 1) effect = EF_HYPERBLASTER; else effect = EF_BLASTER; */ fire_blaster (self, self->s.origin, self->movedir, self->dmg, self->speed, EF_BLASTER, MOD_TARGET_BLASTER); gi.sound (self, CHAN_VOICE, self->noise_index, 1, ATTN_NORM, 0); } void SP_target_blaster (edict_t *self) { self->use = use_target_blaster; G_SetMovedir (self->s.angles, self->movedir); self->noise_index = gi.soundindex ("weapons/laser2.wav"); if (!self->dmg) self->dmg = 15; if (!self->speed) self->speed = 1000; self->svflags = SVF_NOCLIENT; } //========================================================== /*QUAKED target_crosslevel_trigger (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8 Once this trigger is touched/used, any trigger_crosslevel_target with the same trigger number is automatically used when a level is started within the same unit. It is OK to check multiple triggers. Message, delay, target, and killtarget also work. */ void trigger_crosslevel_trigger_use (edict_t *self, edict_t */*other*/, edict_t */*activator*/) { game.serverflags |= self->spawnflags; G_FreeEdict (self); } void SP_target_crosslevel_trigger (edict_t *self) { self->svflags = SVF_NOCLIENT; self->use = trigger_crosslevel_trigger_use; } /*QUAKED target_crosslevel_target (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8 Triggered by a trigger_crosslevel elsewhere within a unit. If multiple triggers are checked, all must be true. Delay, target and killtarget also work. "delay" delay before using targets if the trigger has been activated (default 1) */ void target_crosslevel_target_think (edict_t *self) { if (self->spawnflags == (game.serverflags & SFL_CROSS_TRIGGER_MASK & self->spawnflags)) { G_UseTargets (self, self); G_FreeEdict (self); } } void SP_target_crosslevel_target (edict_t *self) { if (! self->delay) self->delay = 1; self->svflags = SVF_NOCLIENT; self->think = target_crosslevel_target_think; self->nextthink = level.time + self->delay; } //========================================================== /*QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON RED GREEN BLUE YELLOW ORANGE FAT When triggered, fires a laser. You can either set a target or a direction. */ void target_laser_think (edict_t *self) { edict_t *ignore; vec3_t start; vec3_t end; trace_t tr; vec3_t point; vec3_t last_movedir; int count; if (self->spawnflags & 0x80000000) count = 8; else count = 4; if (self->enemy) { VectorCopy (self->movedir, last_movedir); VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point);