diff options
Diffstat (limited to 'src/jake2/game/GameTarget.java')
-rw-r--r-- | src/jake2/game/GameTarget.java | 613 |
1 files changed, 22 insertions, 591 deletions
diff --git a/src/jake2/game/GameTarget.java b/src/jake2/game/GameTarget.java index c28e1d3..8a13ade 100644 --- a/src/jake2/game/GameTarget.java +++ b/src/jake2/game/GameTarget.java @@ -19,77 +19,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 28.12.2003 by RST. -// $Id: GameTarget.java,v 1.1 2004-07-07 19:59:03 hzi Exp $ +// $Id: GameTarget.java,v 1.2 2004-07-08 15:58:43 hzi Exp $ package jake2.game; import jake2.*; import jake2.client.*; -import jake2.game.*; import jake2.qcommon.*; import jake2.render.*; import jake2.server.*; +import jake2.util.Lib; +import jake2.util.Math3D; public class GameTarget extends GameTurret { - /*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 - */ - public static EntUseAdapter Use_Target_Tent = new EntUseAdapter() { - public void use(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); - } - }; - public static void SP_target_temp_entity(edict_t ent) { - ent.use = Use_Target_Tent; + ent.use = GameTargetAdapters.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. - */ - public static EntUseAdapter Use_Target_Speaker = new EntUseAdapter() { - public void use(edict_t ent, edict_t other, edict_t activator) { - int chan; - - if ((ent.spawnflags & 3) != 0) { // looping sound toggles - if (ent.s.sound != 0) - ent.s.sound = 0; // turn it off - else - ent.s.sound = ent.noise_index; // start it - } - else { // normal sound - if ((ent.spawnflags & 4) != 0) - 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); - } - - } - }; - public static void SP_target_speaker(edict_t ent) { //char buffer[MAX_QPATH]; String buffer; @@ -119,28 +66,13 @@ public class GameTarget extends GameTurret { if ((ent.spawnflags & 1) != 0) ent.s.sound = ent.noise_index; - ent.use = Use_Target_Speaker; + ent.use = GameTargetAdapters.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); } - //========================================================== - public static EntUseAdapter Use_Target_Help = new EntUseAdapter() { - public void use(edict_t ent, edict_t other, edict_t activator) { - - if ((ent.spawnflags & 1) != 0) - //strncpy(game.helpmessage1, ent.message, sizeof(game.helpmessage2) - 1); - ent.message = game.helpmessage1; - else - //strncpy(game.helpmessage2, ent.message, sizeof(game.helpmessage1) - 1); - ent.message = game.helpmessage2; - - 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. */ @@ -155,33 +87,16 @@ public class GameTarget extends GameTurret { G_FreeEdict(ent); return; } - ent.use = Use_Target_Help; + ent.use = GameTargetAdapters.Use_Target_Help; } - //========================================================== - - /*QUAKED target_secret (1 0 1) (-8 -8 -8) (8 8 8) - Counts a secret found. - These are single use targets. - */ - static EntUseAdapter use_target_secret = new EntUseAdapter() { - public void use(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); - } - }; - public static void SP_target_secret(edict_t ent) { if (deathmatch.value != 0) { // auto-remove for deathmatch G_FreeEdict(ent); return; } - ent.use = use_target_secret; + ent.use = GameTargetAdapters.use_target_secret; if (st.noise == null) st.noise = "misc/secret.wav"; ent.noise_index = gi.soundindex(st.noise); @@ -192,33 +107,13 @@ public class GameTarget extends GameTurret { 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. - */ - static EntUseAdapter use_target_goal = new EntUseAdapter() { - public void use(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); - } - }; - public static void SP_target_goal(edict_t ent) { if (deathmatch.value != 0) { // auto-remove for deathmatch G_FreeEdict(ent); return; } - ent.use = use_target_goal; + ent.use = GameTargetAdapters.use_target_goal; if (st.noise == null) st.noise = "misc/secret.wav"; ent.noise_index = gi.soundindex(st.noise); @@ -226,89 +121,11 @@ public class GameTarget extends GameTurret { 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 - */ - static EntThinkAdapter target_explosion_explode = new EntThinkAdapter() { - public boolean think(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; - return true; - } - }; - - static EntUseAdapter use_target_explosion = new EntUseAdapter() { - public void use(edict_t self, edict_t other, edict_t activator) { - self.activator = activator; - - if (0 == self.delay) { - target_explosion_explode.think(self); - return; - } - - self.think = target_explosion_explode; - self.nextthink = level.time + self.delay; - } - }; - public static void SP_target_explosion(edict_t ent) { - ent.use = use_target_explosion; + ent.use = GameTargetAdapters.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 - */ - static EntUseAdapter use_target_changelevel = new EntUseAdapter() { - public void use(edict_t self, edict_t other, edict_t activator) { - if (level.intermissiontime != 0) - return; // already activated - - if (0 == deathmatch.value && 0 == coop.value) { - if (g_edicts[1].health <= 0) - return; - } - - // if noexit, do a ton of damage to other - if (deathmatch.value != 0 && 0 == ((int) dmflags.value & DF_ALLOW_EXIT) && other != g_edicts[0] /*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 != 0) { - if (activator != null && activator.client != null) - gi.bprintf(PRINT_HIGH, activator.client.pers.netname + " exited the level.\n"); - } - - // if going to a new unit, clear cross triggers - if (self.map.indexOf('*') > -1) - game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); - - PlayerHud.BeginIntermission(self); - } - }; - public static void SP_target_changelevel(edict_t ent) { if (ent.map == null) { gi.dprintf("target_changelevel with no map at " + vtos(ent.s.origin) + "\n"); @@ -320,44 +137,12 @@ public class GameTarget extends GameTurret { if ((Q_stricmp(level.mapname, "fact1") == 0) && (Q_stricmp(ent.map, "fact3") == 0)) ent.map = "fact3$secret1"; - ent.use = use_target_changelevel; + ent.use = GameTargetAdapters.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 - */ - static EntUseAdapter use_target_splash = new EntUseAdapter() { - public void use(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 != 0) - T_RadiusDamage(self, activator, self.dmg, null, self.dmg + 40, MOD_SPLASH); - } - }; - public static void SP_target_splash(edict_t self) { - self.use = use_target_splash; + self.use = GameTargetAdapters.use_target_splash; G_SetMovedir(self.s.angles, self.movedir); if (0 == self.count) @@ -366,40 +151,8 @@ public class GameTarget extends GameTurret { 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 - */ - - static EntUseAdapter use_target_spawner = new EntUseAdapter() { - public void use(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); - GameSpawn.ED_CallSpawn(ent); - gi.unlinkentity(ent); - KillBox(ent); - gi.linkentity(ent); - if (self.speed != 0) - VectorCopy(self.movedir, ent.velocity); - } - }; - public static void SP_target_spawner(edict_t self) { - self.use = use_target_spawner; + self.use = GameTargetAdapters.use_target_spawner; self.svflags = SVF_NOCLIENT; if (self.speed != 0) { G_SetMovedir(self.s.angles, self.movedir); @@ -407,34 +160,8 @@ public class GameTarget extends GameTurret { } } - //========================================================== - - /*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 - */ - public static EntUseAdapter use_target_blaster = new EntUseAdapter() { - public void use(edict_t self, edict_t other, edict_t activator) { - int effect; - - if ((self.spawnflags & 2) != 0) - effect = 0; - else if ((self.spawnflags & 1) != 0) - effect = EF_HYPERBLASTER; - else - effect = EF_BLASTER; - - Fire.fire_blaster(self, self.s.origin, self.movedir, self.dmg, (int) self.speed, EF_BLASTER, MOD_TARGET_BLASTER != 0 - /*true*/ - ); - gi.sound(self, CHAN_VOICE, self.noise_index, 1, ATTN_NORM, 0); - } - }; - public static void SP_target_blaster(edict_t self) { - self.use = use_target_blaster; + self.use = GameTargetAdapters.use_target_blaster; G_SetMovedir(self.s.angles, self.movedir); self.noise_index = gi.soundindex("weapons/laser2.wav"); @@ -446,134 +173,26 @@ public class GameTarget extends GameTurret { 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. - */ - public static EntUseAdapter trigger_crosslevel_trigger_use = new EntUseAdapter() { - public void use(edict_t self, edict_t other, edict_t activator) { - game.serverflags |= self.spawnflags; - G_FreeEdict(self); - } - }; - public static void SP_target_crosslevel_trigger(edict_t self) { self.svflags = SVF_NOCLIENT; - self.use = trigger_crosslevel_trigger_use; + self.use = GameTargetAdapters.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) - */ - static EntThinkAdapter target_crosslevel_target_think = new EntThinkAdapter() { - public boolean think(edict_t self) { - if (self.spawnflags == (game.serverflags & SFL_CROSS_TRIGGER_MASK & self.spawnflags)) { - G_UseTargets(self, self); - G_FreeEdict(self); - } - return true; - } - }; - public static void SP_target_crosslevel_target(edict_t self) { if (0 == self.delay) self.delay = 1; self.svflags = SVF_NOCLIENT; - self.think = target_crosslevel_target_think; + self.think = GameTargetAdapters.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. - */ - public static EntThinkAdapter target_laser_think = new EntThinkAdapter() { - public boolean think(edict_t self) { - - edict_t ignore; - float[] start = { 0, 0, 0 }; - float[] end = { 0, 0, 0 }; - trace_t tr; - float[] point = { 0, 0, 0 }; - float[] last_movedir = { 0, 0, 0 }; - int count; - - if ((self.spawnflags & 0x80000000) != 0) - count = 8; - else - count = 4; - - if (self.enemy != null) { - VectorCopy(self.movedir, last_movedir); - VectorMA(self.enemy.absmin, 0.5f, self.enemy.size, point); - VectorSubtract(point, self.s.origin, self.movedir); - VectorNormalize(self.movedir); - if (0 == VectorCompare(self.movedir, last_movedir)) - self.spawnflags |= 0x80000000; - } - - ignore = self; - VectorCopy(self.s.origin, start); - VectorMA(start, 2048, self.movedir, end); - while (true) { - tr = gi.trace(start, null, null, end, ignore, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_DEADMONSTER); - - if (tr.ent == null) - break; - - // hurt it if we can - if ((tr.ent.takedamage != 0) && 0 == (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); - - // if we hit something that's not a monster or player or is immune to lasers, we're done - if (0 == (tr.ent.svflags & SVF_MONSTER) && (null == tr.ent.client)) { - if ((self.spawnflags & 0x80000000) != 0) { - 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); - } - break; - } - - ignore = tr.ent; - VectorCopy(tr.endpos, start); - } - - VectorCopy(tr.endpos, self.s.old_origin); - - self.nextthink = level.time + FRAMETIME; - return true; - } - }; - public static void target_laser_on(edict_t self) { if (null == self.activator) self.activator = self; self.spawnflags |= 0x80000001; self.svflags &= ~SVF_NOCLIENT; - target_laser_think.think(self); + GameTargetAdapters.target_laser_think.think(self); } public static void target_laser_off(edict_t self) { @@ -582,151 +201,15 @@ public class GameTarget extends GameTurret { self.nextthink = 0; } - public static EntUseAdapter target_laser_use = new EntUseAdapter() { - - public void use(edict_t self, edict_t other, edict_t activator) { - self.activator = activator; - if ((self.spawnflags & 1) != 0) - target_laser_off(self); - else - target_laser_on(self); - } - }; - - static EntThinkAdapter target_laser_start = new EntThinkAdapter() { - public boolean think(edict_t self) { - - edict_t ent; - - self.movetype = MOVETYPE_NONE; - self.solid = SOLID_NOT; - self.s.renderfx |= RF_BEAM | RF_TRANSLUCENT; - self.s.modelindex = 1; // must be non-zero - - // set the beam diameter - if ((self.spawnflags & 64) != 0) - self.s.frame = 16; - else - self.s.frame = 4; - - // set the color - if ((self.spawnflags & 2) != 0) - self.s.skinnum = 0xf2f2f0f0; - else if ((self.spawnflags & 4) != 0) - self.s.skinnum = 0xd0d1d2d3; - else if ((self.spawnflags & 8) != 0) - self.s.skinnum = 0xf3f3f1f1; - else if ((self.spawnflags & 16) != 0) - self.s.skinnum = 0xdcdddedf; - else if ((self.spawnflags & 32) != 0) - self.s.skinnum = 0xe0e1e2e3; - - if (null == self.enemy) { - if (self.target != null) { - ent = G_Find(null, findByTarget, self.target).o; - if (ent == null) - gi.dprintf(self.classname + " at " + vtos(self.s.origin) + ": " + self.target + " is a bad target\n"); - self.enemy = ent; - } - else { - G_SetMovedir(self.s.angles, self.movedir); - } - } - self.use = target_laser_use; - self.think = target_laser_think; - - if (0 == self.dmg) - self.dmg = 1; - - VectorSet(self.mins, -8, -8, -8); - VectorSet(self.maxs, 8, 8, 8); - gi.linkentity(self); - - if ((self.spawnflags & 1) != 0) - target_laser_on(self); - else - target_laser_off(self); - return true; - } - }; - public static void SP_target_laser(edict_t self) { // let everything else get spawned before we start firing - self.think = target_laser_start; + self.think = GameTargetAdapters.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 - */ - - static EntThinkAdapter target_lightramp_think = new EntThinkAdapter() { - public boolean think(edict_t self) { - - char style[] = { ' ', ' ' }; - - style[0] = (char) ('a' + (int) (self.movedir[0] + (level.time - self.timestamp) / FRAMETIME * self.movedir[2])); - style[1] = 0; - gi.configstring(CS_LIGHTS + self.enemy.style, new String(style)); - - if ((level.time - self.timestamp) < self.speed) { - self.nextthink = level.time + FRAMETIME; - } - else if ((self.spawnflags & 1) != 0) { - char temp; - - temp = (char) self.movedir[0]; - self.movedir[0] = self.movedir[1]; - self.movedir[1] = temp; - self.movedir[2] *= -1; - } - - return true; - } - }; - - static EntUseAdapter target_lightramp_use = new EntUseAdapter() { - public void use(edict_t self, edict_t other, edict_t activator) { - if (self.enemy == null) { - edict_t e; - - // check all the targets - e = null; - EdictIterator es = null; - - while (true) { - es = G_Find(es, findByTarget, self.target); - e = es.o; - - if (e == null) - break; - if (strcmp(e.classname, "light") != 0) { - gi.dprintf(self.classname + " at " + vtos(self.s.origin)); - gi.dprintf("target " + self.target + " (" + e.classname + " at " + vtos(e.s.origin) + ") is not a light\n"); - } - else { - self.enemy = e; - } - } - - if (null == self.enemy) { - gi.dprintf(self.classname + " target " + self.target + " not found at " + vtos(self.s.origin) + "\n"); - G_FreeEdict(self); - return; - } - } - - self.timestamp = level.time; - target_lightramp_think.think(self); - } - }; - public static void SP_target_lightramp(edict_t self) { if (self.message == null - || strlen(self.message) != 2 + || self.message.length() != 2 || self.message.charAt(0) < 'a' || self.message.charAt(0) > 'z' || self.message.charAt(1) < 'a' @@ -749,66 +232,14 @@ public class GameTarget extends GameTurret { } self.svflags |= SVF_NOCLIENT; - self.use = target_lightramp_use; - self.think = target_lightramp_think; + self.use = GameTargetAdapters.target_lightramp_use; + self.think = GameTargetAdapters.target_lightramp_think; self.movedir[0] = self.message.charAt(0) - 'a'; self.movedir[1] = self.message.charAt(1) - 'a'; self.movedir[2] = (self.movedir[1] - self.movedir[0]) / (self.speed / FRAMETIME); } - //========================================================== - - /*QUAKED target_earthquake (1 0 0) (-8 -8 -8) (8 8 8) - 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) - */ - - static EntThinkAdapter target_earthquake_think = new EntThinkAdapter() { - public boolean think(edict_t self) { - - int i; - edict_t e; - - if (self.last_move_time < level.time) { - gi.positioned_sound(self.s.origin, self, CHAN_AUTO, self.noise_index, 1.0f, ATTN_NONE, 0); - self.last_move_time = level.time + 0.5f; - } - - for (i = 1; i < globals.num_edicts; i++) { - e = g_edicts[i]; - - if (!e.inuse) - continue; - if (null == e.client) - continue; - if (null == e.groundentity) - continue; - - e.groundentity = null; - e.velocity[0] += crandom() * 150; - e.velocity[1] += crandom() * 150; - e.velocity[2] = self.speed * (100.0f / e.mass); - } - - if (level.time < self.timestamp) - self.nextthink = level.time + FRAMETIME; - - return true; - } - }; - - static EntUseAdapter target_earthquake_use = new EntUseAdapter() { - public void use(edict_t self, edict_t other, edict_t activator) { - self.timestamp = level.time + self.count; - self.nextthink = level.time + FRAMETIME; - self.activator = activator; - self.last_move_time = 0; - } - }; - public static void SP_target_earthquake(edict_t self) { if (null == self.targetname) gi.dprintf("untargeted " + self.classname + " at " + vtos(self.s.origin) + "\n"); @@ -820,8 +251,8 @@ public class GameTarget extends GameTurret { self.speed = 200; self.svflags |= SVF_NOCLIENT; - self.think = target_earthquake_think; - self.use = target_earthquake_use; + self.think = GameTargetAdapters.target_earthquake_think; + self.use = GameTargetAdapters.target_earthquake_use; self.noise_index = gi.soundindex("world/quake.wav"); } |