From 811e038971e37b429d98d4d9e3fd369be6c6fab2 Mon Sep 17 00:00:00 2001 From: Yamagi Burmeister Date: Tue, 28 Jan 2014 17:29:17 +0100 Subject: [PATCH] Cleanup g_target.c and add sanity checks --- src/g_target.c | 1199 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 791 insertions(+), 408 deletions(-) diff --git a/src/g_target.c b/src/g_target.c index 570e4b3..b0298cf 100644 --- a/src/g_target.c +++ b/src/g_target.c @@ -1,234 +1,361 @@ #include "header/local.h" + +#define LASER_ON 0x0001 +#define LASER_RED 0x0002 +#define LASER_GREEN 0x0004 +#define LASER_BLUE 0x0008 +#define LASER_YELLOW 0x0010 +#define LASER_ORANGE 0x0020 +#define LASER_FAT 0x0040 +#define LASER_STOPWINDOW 0x0080 + +void ED_CallSpawn(edict_t *ent); -/*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) +/* + * 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); + 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) +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) +/* + * 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 /* unused */, edict_t *activator /* unused */) { - int chan; - + int chan; + + if (!ent) + { + return; + } + if (ent->spawnflags & 3) - { // looping sound toggles + { + /* looping sound toggles */ if (ent->s.sound) - ent->s.sound = 0; // turn it off + { + ent->s.sound = 0; /* turn it off */ + } else - ent->s.sound = ent->noise_index; // start it + { + ent->s.sound = ent->noise_index; /* start it */ + } } else - { // normal sound + { + /* normal sound */ if (ent->spawnflags & 4) - chan = CHAN_VOICE|CHAN_RELIABLE; + { + 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); + } + + /* 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) +void +SP_target_speaker(edict_t *ent) { - char buffer[MAX_QPATH]; - - if(!st.noise) + char buffer[MAX_QPATH]; + + if (!ent) + { + return; + } + + 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); + + 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); + { + 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 + } + else if (ent->attenuation == -1) /* use -1 so 0 defaults to 1 */ + { ent->attenuation = 0; + } - // check for prestarted looping sound + /* 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); + /* 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) -{ +void +Use_Target_Help(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) +{ + if (!ent) + { + return; + } + if (ent->spawnflags & 1) - strncpy (game.helpmessage1, ent->message, sizeof(game.helpmessage2)-1); + { + strncpy(game.helpmessage1, ent->message, sizeof(game.helpmessage2) - 1); + } else - strncpy (game.helpmessage2, ent->message, sizeof(game.helpmessage1)-1); + { + 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) -{ +/* + * 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 (!ent) + { + return; + } + if (deathmatch->value) - { // auto-remove for deathmatch - G_FreeEdict (ent); + { + /* 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); + 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); +/* + * 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 /* unused */, edict_t *activator /* unused */) +{ + if (!ent) + { + return; + } + + gi.sound(ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0); level.found_secrets++; - G_UseTargets (ent, activator); - G_FreeEdict (ent); + G_UseTargets(ent, activator); + G_FreeEdict(ent); } -void SP_target_secret (edict_t *ent) -{ +void +SP_target_secret(edict_t *ent) +{ + if (!ent) + { + return; + } + if (deathmatch->value) - { // auto-remove for deathmatch - G_FreeEdict (ent); + { + /* 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->noise_index = gi.soundindex(st.noise); ent->svflags = SVF_NOCLIENT; level.total_secrets++; - // map bug hack - if (!Q_stricmp(level.mapname, "mine3") && ent->s.origin[0] == 280 && ent->s.origin[1] == -2048 && ent->s.origin[2] == -624) + + /* map bug hack */ + if (!Q_stricmp(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); +/* + * 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 /* unused */, edict_t *activator /* unused */) +{ + if (!ent) + { + return; + } + + 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"); + { + gi.configstring(CS_CDTRACK, "0"); + } - G_UseTargets (ent, activator); - G_FreeEdict (ent); + G_UseTargets(ent, activator); + G_FreeEdict(ent); } -void SP_target_goal (edict_t *ent) -{ +void +SP_target_goal(edict_t *ent) +{ + if (!ent) + { + return; + } + if (deathmatch->value) - { // auto-remove for deathmatch - G_FreeEdict (ent); + { + /* 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->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) +/* + * 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; + float save; + + if (!self) + { + return; + } + + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_EXPLOSION1); + gi.WritePosition(self->s.origin); + gi.multicast(self->s.origin, MULTICAST_PHS); - 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); + T_RadiusDamage(self, self->activator, self->dmg, + NULL, self->dmg + 40, MOD_EXPLOSIVE); save = self->delay; self->delay = 0; - G_UseTargets (self, self->activator); + G_UseTargets(self, self->activator); self->delay = save; } -void use_target_explosion (edict_t *self, edict_t *other, edict_t *activator) -{ +void +use_target_explosion(edict_t *self, edict_t *other /* unused */, edict_t *activator) +{ + if (!self || !activator) + { + return; + } + self->activator = activator; if (!self->delay) { - target_explosion_explode (self); + target_explosion_explode(self); return; } @@ -236,427 +363,623 @@ void use_target_explosion (edict_t *self, edict_t *other, edict_t *activator) self->nextthink = level.time + self->delay; } -void SP_target_explosion (edict_t *ent) -{ +void +SP_target_explosion(edict_t *ent) +{ + if (!ent) + { + return; + } + 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) -{ +/* + * 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 (!self || !other || !activator) + { + return; + } + if (level.intermissiontime) - return; // already activated + { + 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) + /* 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); + 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 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); + { + 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, "*")) + /* if going to a new unit, clear cross triggers */ + if (strstr(self->map, "*")) + { game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); + } - BeginIntermission (self); + BeginIntermission(self); } -void SP_target_changelevel (edict_t *ent) -{ +void +SP_target_changelevel(edict_t *ent) +{ + if (!ent) + { + return; + } + if (!ent->map) { gi.dprintf("target_changelevel with no map at %s\n", vtos(ent->s.origin)); - G_FreeEdict (ent); + G_FreeEdict(ent); return; } - // ugly hack because *SOMEBODY* screwed up their map - if((Q_stricmp(level.mapname, "fact1") == 0) && (Q_stricmp(ent->map, "fact3") == 0)) - ent->map = "fact3$secret1"; + /* ugly hack because *SOMEBODY* screwed up their map */ + if ((Q_stricmp(level.mapname, "fact1") == 0) && (Q_stricmp(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 + */ -/*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); +void +use_target_splash(edict_t *self, edict_t *other /* unused */, edict_t *activator) +{ + if (!self || !activator) + { + return; + } + + 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); - - ent->s.renderfx |= RF_IR_VISIBLE; //PGM -} - -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); + T_RadiusDamage(self, activator, self->dmg, NULL, + self->dmg + 40, MOD_SPLASH); } } -//========================================================== +void +SP_target_splash(edict_t *self) +{ + if (!self) + { + return; + } + + self->use = use_target_splash; + G_SetMovedir(self->s.angles, 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) -{ - 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; + 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 + */ -/*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) +void +use_target_spawner(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { - game.serverflags |= self->spawnflags; - G_FreeEdict (self); + edict_t *ent; + + if (!self) + { + return; + } + + 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); + } + + ent->s.renderfx |= RF_IR_VISIBLE; /* PGM */ } -void SP_target_crosslevel_trigger (edict_t *self) -{ +void +SP_target_spawner(edict_t *self) +{ + if (!self) + { + return; + } + + 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) +{ + if (!self) + { + return; + } + + 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) +{ + if (!self) + { + return; + } + + 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 /* unused */, edict_t *activator /* unused */) +{ + if (!self) + { + return; + } + + game.serverflags |= self->spawnflags; + G_FreeEdict(self); +} + +void +SP_target_crosslevel_trigger(edict_t *self) +{ + if (!self) + { + return; + } + 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) -{ +/* + * 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) + { + return; + } + if (self->spawnflags == (game.serverflags & SFL_CROSS_TRIGGER_MASK & self->spawnflags)) { - G_UseTargets (self, self); - G_FreeEdict (self); + G_UseTargets(self, self); + G_FreeEdict(self); } } -void SP_target_crosslevel_target (edict_t *self) -{ - if (! self->delay) +void +SP_target_crosslevel_target(edict_t *self) +{ + if (!self) + { + return; + } + + 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 WINDOWSTOP -When triggered, fires a laser. You can either set a target -or a direction. - -WINDOWSTOP - stops at CONTENTS_WINDOW -*/ - -//====== -// PGM -#define LASER_ON 0x0001 -#define LASER_RED 0x0002 -#define LASER_GREEN 0x0004 -#define LASER_BLUE 0x0008 -#define LASER_YELLOW 0x0010 -#define LASER_ORANGE 0x0020 -#define LASER_FAT 0x0040 -#define LASER_STOPWINDOW 0x0080 -// PGM -//====== - -void target_laser_think (edict_t *self) +/* + * QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON RED GREEN BLUE YELLOW ORANGE FAT WINDOWSTOP + * When triggered, fires a laser. You can either set a target + * or a direction. + * + * WINDOWSTOP - stops at CONTENTS_WINDOW + */ +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; - + edict_t *ignore; + vec3_t start; + vec3_t end; + trace_t tr; + vec3_t point; + vec3_t last_movedir; + int count; + + if (!self) + { + return; + } + 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); - VectorSubtract (point, self->s.origin, self->movedir); - VectorNormalize (self->movedir); + VectorCopy(self->movedir, last_movedir); + VectorMA(self->enemy->absmin, 0.5, self->enemy->size, point); + VectorSubtract(point, self->s.origin, self->movedir); + VectorNormalize(self->movedir); + if (!VectorCompare(self->movedir, last_movedir)) + { self->spawnflags |= 0x80000000; + } } ignore = self; - VectorCopy (self->s.origin, start); - VectorMA (start, 2048, self->movedir, end); - while(1) + VectorCopy(self->s.origin, start); + VectorMA(start, 2048, self->movedir, end); + + while (1) { - //====== - // PGM - if(self->spawnflags & LASER_STOPWINDOW) - tr = gi.trace (start, NULL, NULL, end, ignore, MASK_SHOT); + if (self->spawnflags & LASER_STOPWINDOW) + { + tr = gi.trace(start, NULL, NULL, end, ignore, MASK_SHOT); + } else - tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); - // PGM - //====== + { + tr = gi.trace(start, NULL, NULL, end, ignore, + CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_DEADMONSTER); + } if (!tr.ent) + { break; + } - // hurt it if we can + /* hurt it if we can */ if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER)) - T_Damage (tr.ent, self, self->activator, self->movedir, tr.endpos, vec3_origin, self->dmg, 1, DAMAGE_ENERGY, MOD_TARGET_LASER); + { + T_Damage(tr.ent, self, self->activator, self->movedir, tr.endpos, + vec3_origin, self->dmg, 1, DAMAGE_ENERGY, MOD_TARGET_LASER); + } - // if we hit something that's not a monster or player or is immune to lasers, we're done - //PMM added SVF_DAMAGEABLE - if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client) && !(tr.ent->svflags & SVF_DAMAGEABLE)) + /* if we hit something that's not a monster or player or is immune to lasers, we're done */ + if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client) && + !(tr.ent->svflags & SVF_DAMAGEABLE)) { if (self->spawnflags & 0x80000000) { self->spawnflags &= ~0x80000000; - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_LASER_SPARKS); - gi.WriteByte (count); - gi.WritePosition (tr.endpos); - gi.WriteDir (tr.plane.normal); - gi.WriteByte (self->s.skinnum); - gi.multicast (tr.endpos, MULTICAST_PVS); + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_LASER_SPARKS); + gi.WriteByte(count); + gi.WritePosition(tr.endpos); + gi.WriteDir(tr.plane.normal); + gi.WriteByte(self->s.skinnum); + gi.multicast(tr.endpos, MULTICAST_PVS); } + break; } ignore = tr.ent; - VectorCopy (tr.endpos, start); + VectorCopy(tr.endpos, start); } - VectorCopy (tr.endpos, self->s.old_origin); + VectorCopy(tr.endpos, self->s.old_origin); self->nextthink = level.time + FRAMETIME; } -void target_laser_on (edict_t *self) -{ +void +target_laser_on(edict_t *self) +{ + if (!self) + { + return; + } + if (!self->activator) + { self->activator = self; + } + self->spawnflags |= 0x80000001; self->svflags &= ~SVF_NOCLIENT; - target_laser_think (self); + target_laser_think(self); } -void target_laser_off (edict_t *self) -{ +void +target_laser_off(edict_t *self) +{ + if (!self) + { + return; + } + self->spawnflags &= ~1; self->svflags |= SVF_NOCLIENT; self->nextthink = 0; } -void target_laser_use (edict_t *self, edict_t *other, edict_t *activator) -{ +void +target_laser_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) +{ + if (!self || !activator) + { + return; + } + self->activator = activator; + if (self->spawnflags & 1) - target_laser_off (self); + { + target_laser_off(self); + } else - target_laser_on (self); + { + target_laser_on(self); + } } -void target_laser_start (edict_t *self) +void +target_laser_start(edict_t *self) { edict_t *ent; - + + if (!self) + { + return; + } + self->movetype = MOVETYPE_NONE; self->solid = SOLID_NOT; - self->s.renderfx |= RF_BEAM|RF_TRANSLUCENT; - self->s.modelindex = 1; // must be non-zero + self->s.renderfx |= RF_BEAM | RF_TRANSLUCENT; + self->s.modelindex = 1; /* must be non-zero */ - // set the beam diameter + /* set the beam diameter */ if (self->spawnflags & 64) + { self->s.frame = 16; + } else + { self->s.frame = 4; + } - // set the color + /* set the color */ if (self->spawnflags & 2) + { self->s.skinnum = 0xf2f2f0f0; + } else if (self->spawnflags & 4) + { self->s.skinnum = 0xd0d1d2d3; + } else if (self->spawnflags & 8) + { self->s.skinnum = 0xf3f3f1f1; + } else if (self->spawnflags & 16) + { self->s.skinnum = 0xdcdddedf; + } else if (self->spawnflags & 32) + { self->s.skinnum = 0xe0e1e2e3; + } if (!self->enemy) { if (self->target) { - ent = G_Find (NULL, FOFS(targetname), self->target); + ent = G_Find(NULL, FOFS(targetname), self->target); + if (!ent) - gi.dprintf ("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target); + { + gi.dprintf("%s at %s: %s is a bad target\n", self->classname, + vtos(self->s.origin), self->target); + } + self->enemy = ent; } else { - G_SetMovedir (self->s.angles, self->movedir); + G_SetMovedir(self->s.angles, self->movedir); } } + self->use = target_laser_use; self->think = target_laser_think; if (!self->dmg) + { self->dmg = 1; + } - VectorSet (self->mins, -8, -8, -8); - VectorSet (self->maxs, 8, 8, 8); - gi.linkentity (self); + VectorSet(self->mins, -8, -8, -8); + VectorSet(self->maxs, 8, 8, 8); + gi.linkentity(self); if (self->spawnflags & 1) - target_laser_on (self); + { + target_laser_on(self); + } else - target_laser_off (self); + { + target_laser_off(self); + } } -void SP_target_laser (edict_t *self) -{ - // let everything else get spawned before we start firing +void +SP_target_laser(edict_t *self) +{ + if (!self) + { + return; + } + self->think = target_laser_start; self->nextthink = level.time + 1; } -//========================================================== +/* ========================================================== */ -/*QUAKED target_lightramp (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE -speed How many seconds the ramping will take -message two letters; starting lightlevel and ending lightlevel -*/ +/* + * QUAKED target_lightramp (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE + * + * speed How many seconds the ramping will take + * message two letters; starting lightlevel and ending lightlevel + */ -void target_lightramp_think (edict_t *self) +void +target_lightramp_think(edict_t *self) { - char style[2]; - + char style[2]; + + if (!self) + { + return; + } + style[0] = 'a' + self->movedir[0] + (level.time - self->timestamp) / FRAMETIME * self->movedir[2]; style[1] = 0; - gi.configstring (CS_LIGHTS+self->enemy->style, style); + gi.configstring(CS_LIGHTS + self->enemy->style, style); if ((level.time - self->timestamp) < self->speed) { @@ -664,7 +987,7 @@ void target_lightramp_think (edict_t *self) } else if (self->spawnflags & 1) { - char temp; + char temp; temp = self->movedir[0]; self->movedir[0] = self->movedir[1]; @@ -673,23 +996,35 @@ void target_lightramp_think (edict_t *self) } } -void target_lightramp_use (edict_t *self, edict_t *other, edict_t *activator) -{ +void +target_lightramp_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) +{ + if (!self) + { + return; + } + if (!self->enemy) { - edict_t *e; + edict_t *e; - // check all the targets + /* check all the targets */ e = NULL; + while (1) { - e = G_Find (e, FOFS(targetname), self->target); + e = G_Find(e, FOFS(targetname), self->target); + if (!e) + { break; + } + if (strcmp(e->classname, "light") != 0) { gi.dprintf("%s at %s ", self->classname, vtos(self->s.origin)); - gi.dprintf("target %s (%s at %s) is not a light\n", self->target, e->classname, vtos(e->s.origin)); + gi.dprintf("target %s (%s at %s) is not a light\n", self->target, + e->classname, vtos(e->s.origin)); } else { @@ -699,35 +1034,45 @@ void target_lightramp_use (edict_t *self, edict_t *other, edict_t *activator) if (!self->enemy) { - gi.dprintf("%s target %s not found at %s\n", self->classname, self->target, vtos(self->s.origin)); - G_FreeEdict (self); + gi.dprintf("%s target %s not found at %s\n", self->classname, + self->target, vtos(self->s.origin)); + G_FreeEdict(self); return; } } self->timestamp = level.time; - target_lightramp_think (self); + target_lightramp_think(self); } -void SP_target_lightramp (edict_t *self) -{ - if (!self->message || strlen(self->message) != 2 || self->message[0] < 'a' || self->message[0] > 'z' || self->message[1] < 'a' || self->message[1] > 'z' || self->message[0] == self->message[1]) +void +SP_target_lightramp(edict_t *self) +{ + if (!self) + { + return; + } + + if (!self->message || (strlen(self->message) != 2) || + (self->message[0] < 'a') || (self->message[0] > 'z') || + (self->message[1] < 'a') || (self->message[1] > 'z') || + (self->message[0] == self->message[1])) { gi.dprintf("target_lightramp has bad ramp (%s) at %s\n", self->message, vtos(self->s.origin)); - G_FreeEdict (self); + G_FreeEdict(self); return; } if (deathmatch->value) { - G_FreeEdict (self); + G_FreeEdict(self); return; } if (!self->target) { gi.dprintf("%s with no target at %s\n", self->classname, vtos(self->s.origin)); - G_FreeEdict (self); + G_FreeEdict(self); return; } @@ -740,71 +1085,109 @@ void SP_target_lightramp (edict_t *self) self->movedir[2] = (self->movedir[1] - self->movedir[0]) / (self->speed / FRAMETIME); } -//========================================================== +/* ========================================================== */ -/*QUAKED target_earthquake (1 0 0) (-8 -8 -8) (8 8 8) SILENT -When triggered, this initiates a level-wide earthquake. -All players and monsters are affected. -"speed" severity of the quake (default:200) -"count" duration of the quake (default:5) -*/ - -void target_earthquake_think (edict_t *self) +/* + * QUAKED target_earthquake (1 0 0) (-8 -8 -8) (8 8 8) SILENT + * + * When triggered, this initiates a level-wide earthquake. + * All players and monsters are affected. + * "speed" severity of the quake (default:200) + * "count" duration of the quake (default:5) + */ +void +target_earthquake_think(edict_t *self) { - int i; - edict_t *e; - - if(!(self->spawnflags & 1)) // PGM - { // PGM + int i; + edict_t *e; + + if (!self) + { + return; + } + + if (!(self->spawnflags & 1)) + { if (self->last_move_time < level.time) { - gi.positioned_sound (self->s.origin, self, CHAN_AUTO, self->noise_index, 1.0, ATTN_NONE, 0); + gi.positioned_sound(self->s.origin, self, CHAN_AUTO, self->noise_index, + 1.0, ATTN_NONE, 0); self->last_move_time = level.time + 0.5; } - } // PGM + } - for (i=1, e=g_edicts+i; i < globals.num_edicts; i++,e++) + for (i = 1, e = g_edicts + i; i < globals.num_edicts; i++, e++) { if (!e->inuse) + { continue; + } + if (!e->client) + { continue; + } + if (!e->groundentity) + { continue; + } e->groundentity = NULL; - e->velocity[0] += crandom()* 150; - e->velocity[1] += crandom()* 150; + e->velocity[0] += crandom() * 150; + e->velocity[1] += crandom() * 150; e->velocity[2] = self->speed * (100.0 / e->mass); } if (level.time < self->timestamp) + { self->nextthink = level.time + FRAMETIME; + } } -void target_earthquake_use (edict_t *self, edict_t *other, edict_t *activator) -{ +void +target_earthquake_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) +{ + if (!self || !activator) + { + return; + } + self->timestamp = level.time + self->count; self->nextthink = level.time + FRAMETIME; self->activator = activator; self->last_move_time = 0; } -void SP_target_earthquake (edict_t *self) -{ +void +SP_target_earthquake(edict_t *self) +{ + if (!self) + { + return; + } + if (!self->targetname) - gi.dprintf("untargeted %s at %s\n", self->classname, vtos(self->s.origin)); + { + gi.dprintf("untargeted %s at %s\n", self->classname, vtos( self->s.origin)); + } if (!self->count) + { self->count = 5; + } if (!self->speed) + { self->speed = 200; + } self->svflags |= SVF_NOCLIENT; self->think = target_earthquake_think; self->use = target_earthquake_use; - if(!(self->spawnflags & 1)) // PGM - self->noise_index = gi.soundindex ("world/quake.wav"); + if (!(self->spawnflags & 1)) + { + self->noise_index = gi.soundindex("world/quake.wav"); + } }