diff options
Diffstat (limited to 'src/jake2/game/GameMisc.java')
-rw-r--r-- | src/jake2/game/GameMisc.java | 2374 |
1 files changed, 1647 insertions, 727 deletions
diff --git a/src/jake2/game/GameMisc.java b/src/jake2/game/GameMisc.java index 1d4f4e8..dba1e26 100644 --- a/src/jake2/game/GameMisc.java +++ b/src/jake2/game/GameMisc.java @@ -1,733 +1,1653 @@ /* -Copyright (C) 1997-2001 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ + * Copyright (C) 1997-2001 Id Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ // Created on 27.12.2003 by RST. -// $Id: GameMisc.java,v 1.3 2004-09-10 19:02:54 salomo Exp $ - +// $Id: GameMisc.java,v 1.4 2004-09-22 19:22:03 salomo Exp $ package jake2.game; -import jake2.client.M; +import java.util.Calendar; -public class GameMisc extends GameTrigger -{ - public static void SP_path_corner(edict_t self) - { - if (self.targetname == null) - { - gi.dprintf("path_corner with no targetname at " + vtos(self.s.origin) + "\n"); - G_FreeEdict(self); - return; - } - - self.solid = SOLID_TRIGGER; - self.touch = GameMiscAdapters.path_corner_touch; - VectorSet(self.mins, -8, -8, -8); - VectorSet(self.maxs, 8, 8, 8); - self.svflags |= SVF_NOCLIENT; - gi.linkentity(self); - } - - public static void SP_point_combat(edict_t self) - { - if (deathmatch.value != 0) - { - G_FreeEdict(self); - return; - } - self.solid = SOLID_TRIGGER; - self.touch = GameMiscAdapters.point_combat_touch; - VectorSet(self.mins, -8, -8, -16); - VectorSet(self.maxs, 8, 8, 16); - self.svflags = SVF_NOCLIENT; - gi.linkentity(self); - }; - - public static void SP_viewthing(edict_t ent) - { - gi.dprintf("viewthing spawned\n"); - - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_BBOX; - ent.s.renderfx = RF_FRAMELERP; - VectorSet(ent.mins, -16, -16, -24); - VectorSet(ent.maxs, 16, 16, 32); - ent.s.modelindex = gi.modelindex("models/objects/banner/tris.md2"); - gi.linkentity(ent); - ent.nextthink = level.time + 0.5f; - ent.think = GameMiscAdapters.TH_viewthing; - return; - } - - /*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4) - Used as a positional target for spotlights, etc. - */ - public static void SP_info_null(edict_t self) - { - G_FreeEdict(self); - }; - - /*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4) - Used as a positional target for lightning. - */ - public static void SP_info_notnull(edict_t self) - { - VectorCopy(self.s.origin, self.absmin); - VectorCopy(self.s.origin, self.absmax); - }; - - public static void SP_light(edict_t self) - { - // no targeted lights in deathmatch, because they cause global messages - if (null == self.targetname || deathmatch.value != 0) - { - G_FreeEdict(self); - return; - } - - if (self.style >= 32) - { - self.use = GameMiscAdapters.light_use; - if ((self.spawnflags & GameMiscAdapters.START_OFF) != 0) - gi.configstring(CS_LIGHTS + self.style, "a"); - else - gi.configstring(CS_LIGHTS + self.style, "m"); - } - } - - public static void SP_func_wall(edict_t self) - { - self.movetype = MOVETYPE_PUSH; - gi.setmodel(self, self.model); - - if ((self.spawnflags & 8) != 0) - self.s.effects |= EF_ANIM_ALL; - if ((self.spawnflags & 16) != 0) - self.s.effects |= EF_ANIM_ALLFAST; - - // just a wall - if ((self.spawnflags & 7) == 0) - { - self.solid = SOLID_BSP; - gi.linkentity(self); - return; - } - - // it must be TRIGGER_SPAWN - if (0 == (self.spawnflags & 1)) - { - gi.dprintf("func_wall missing TRIGGER_SPAWN\n"); - self.spawnflags |= 1; - } - - // yell if the spawnflags are odd - if ((self.spawnflags & 4) != 0) - { - if (0 == (self.spawnflags & 2)) - { - gi.dprintf("func_wall START_ON without TOGGLE\n"); - self.spawnflags |= 2; - } - } - - self.use = GameMiscAdapters.func_wall_use; - if ((self.spawnflags & 4) != 0) - { - self.solid = SOLID_BSP; - } - else - { - self.solid = SOLID_NOT; - self.svflags |= SVF_NOCLIENT; - } - gi.linkentity(self); - } - - public static void SP_func_object(edict_t self) - { - gi.setmodel(self, self.model); - - self.mins[0] += 1; - self.mins[1] += 1; - self.mins[2] += 1; - self.maxs[0] -= 1; - self.maxs[1] -= 1; - self.maxs[2] -= 1; - - if (self.dmg == 0) - self.dmg = 100; - - if (self.spawnflags == 0) - { - self.solid = SOLID_BSP; - self.movetype = MOVETYPE_PUSH; - self.think = GameMiscAdapters.func_object_release; - self.nextthink = level.time + 2 * FRAMETIME; - } - else - { - self.solid = SOLID_NOT; - self.movetype = MOVETYPE_PUSH; - self.use = GameMiscAdapters.func_object_use; - self.svflags |= SVF_NOCLIENT; - } - - if ((self.spawnflags & 2) != 0) - self.s.effects |= EF_ANIM_ALL; - if ((self.spawnflags & 4) != 0) - self.s.effects |= EF_ANIM_ALLFAST; - - self.clipmask = MASK_MONSTERSOLID; - - gi.linkentity(self); - } - - public static void SP_func_explosive(edict_t self) - { - if (deathmatch.value != 0) - { // auto-remove for deathmatch - G_FreeEdict(self); - return; - } - - self.movetype = MOVETYPE_PUSH; - - gi.modelindex("models/objects/debris1/tris.md2"); - gi.modelindex("models/objects/debris2/tris.md2"); - - gi.setmodel(self, self.model); - - if ((self.spawnflags & 1) != 0) - { - self.svflags |= SVF_NOCLIENT; - self.solid = SOLID_NOT; - self.use = GameMiscAdapters.func_explosive_spawn; - } - else - { - self.solid = SOLID_BSP; - if (self.targetname != null) - self.use = GameMiscAdapters.func_explosive_use; - } - - if ((self.spawnflags & 2) != 0) - self.s.effects |= EF_ANIM_ALL; - if ((self.spawnflags & 4) != 0) - self.s.effects |= EF_ANIM_ALLFAST; - - if (self.use != GameMiscAdapters.func_explosive_use) - { - if (self.health == 0) - self.health = 100; - self.die = GameMiscAdapters.func_explosive_explode; - self.takedamage = DAMAGE_YES; - } - - gi.linkentity(self); - } - - public static void SP_misc_explobox(edict_t self) - { - if (deathmatch.value != 0) - { // auto-remove for deathmatch - G_FreeEdict(self); - return; - } - - gi.modelindex("models/objects/debris1/tris.md2"); - gi.modelindex("models/objects/debris2/tris.md2"); - gi.modelindex("models/objects/debris3/tris.md2"); - - self.solid = SOLID_BBOX; - self.movetype = MOVETYPE_STEP; - - self.model = "models/objects/barrels/tris.md2"; - self.s.modelindex = gi.modelindex(self.model); - VectorSet(self.mins, -16, -16, 0); - VectorSet(self.maxs, 16, 16, 40); - - if (self.mass == 0) - self.mass = 400; - if (0 == self.health) - self.health = 10; - if (0 == self.dmg) - self.dmg = 150; - - self.die = GameMiscAdapters.barrel_delay; - self.takedamage = DAMAGE_YES; - self.monsterinfo.aiflags = AI_NOSTEP; - - self.touch = GameMiscAdapters.barrel_touch; - - self.think = M.M_droptofloor; - self.nextthink = level.time + 2 * FRAMETIME; - - gi.linkentity(self); - } - - public static void SP_misc_blackhole(edict_t ent) - { - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_NOT; - VectorSet(ent.mins, -64, -64, 0); - VectorSet(ent.maxs, 64, 64, 8); - ent.s.modelindex = gi.modelindex("models/objects/black/tris.md2"); - ent.s.renderfx = RF_TRANSLUCENT; - ent.use = GameMiscAdapters.misc_blackhole_use; - ent.think = GameMiscAdapters.misc_blackhole_think; - ent.nextthink = level.time + 2 * FRAMETIME; - gi.linkentity(ent); - } - - public static void SP_misc_eastertank(edict_t ent) - { - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_BBOX; - VectorSet(ent.mins, -32, -32, -16); - VectorSet(ent.maxs, 32, 32, 32); - ent.s.modelindex = gi.modelindex("models/monsters/tank/tris.md2"); - ent.s.frame = 254; - ent.think = GameMiscAdapters.misc_eastertank_think; - ent.nextthink = level.time + 2 * FRAMETIME; - gi.linkentity(ent); - } - - public static void SP_misc_easterchick(edict_t ent) - { - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_BBOX; - VectorSet(ent.mins, -32, -32, 0); - VectorSet(ent.maxs, 32, 32, 32); - ent.s.modelindex = gi.modelindex("models/monsters/bitch/tris.md2"); - ent.s.frame = 208; - ent.think = GameMiscAdapters.misc_easterchick_think; - ent.nextthink = level.time + 2 * FRAMETIME; - gi.linkentity(ent); - } - - public static void SP_misc_easterchick2(edict_t ent) - { - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_BBOX; - VectorSet(ent.mins, -32, -32, 0); - VectorSet(ent.maxs, 32, 32, 32); - ent.s.modelindex = gi.modelindex("models/monsters/bitch/tris.md2"); - ent.s.frame = 248; - ent.think = GameMiscAdapters.misc_easterchick2_think; - ent.nextthink = level.time + 2 * FRAMETIME; - gi.linkentity(ent); - } - - public static void SP_monster_commander_body(edict_t self) - { - self.movetype = MOVETYPE_NONE; - self.solid = SOLID_BBOX; - self.model = "models/monsters/commandr/tris.md2"; - self.s.modelindex = gi.modelindex(self.model); - VectorSet(self.mins, -32, -32, 0); - VectorSet(self.maxs, 32, 32, 48); - self.use = GameMiscAdapters.commander_body_use; - self.takedamage = DAMAGE_YES; - self.flags = FL_GODMODE; - self.s.renderfx |= RF_FRAMELERP; - gi.linkentity(self); - - gi.soundindex("tank/thud.wav"); - gi.soundindex("tank/pain.wav"); - - self.think = GameMiscAdapters.commander_body_drop; - self.nextthink = level.time + 5 * FRAMETIME; - } - - public static void SP_misc_banner(edict_t ent) - { - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_NOT; - ent.s.modelindex = gi.modelindex("models/objects/banner/tris.md2"); - ent.s.frame = rand() % 16; - gi.linkentity(ent); - - ent.think = GameMiscAdapters.misc_banner_think; - ent.nextthink = level.time + FRAMETIME; - } - - public static void SP_misc_deadsoldier(edict_t ent) - { - if (deathmatch.value != 0) - { // auto-remove for deathmatch - G_FreeEdict(ent); - return; - } - - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_BBOX; - ent.s.modelindex = gi.modelindex("models/deadbods/dude/tris.md2"); - - // Defaults to frame 0 - if ((ent.spawnflags & 2) != 0) - ent.s.frame = 1; - else if ((ent.spawnflags & 4) != 0) - ent.s.frame = 2; - else if ((ent.spawnflags & 8) != 0) - ent.s.frame = 3; - else if ((ent.spawnflags & 16) != 0) - ent.s.frame = 4; - else if ((ent.spawnflags & 32) != 0) - ent.s.frame = 5; - else - ent.s.frame = 0; - - VectorSet(ent.mins, -16, -16, 0); - VectorSet(ent.maxs, 16, 16, 16); - ent.deadflag = DEAD_DEAD; - ent.takedamage = DAMAGE_YES; - ent.svflags |= SVF_MONSTER | SVF_DEADMONSTER; - ent.die = GameMiscAdapters.misc_deadsoldier_die; - ent.monsterinfo.aiflags |= AI_GOOD_GUY; - - gi.linkentity(ent); - } - - public static void SP_misc_viper(edict_t ent) - { - if (null == ent.target) - { - gi.dprintf("misc_viper without a target at " + vtos(ent.absmin) + "\n"); - G_FreeEdict(ent); - return; - } - - if (0 == ent.speed) - ent.speed = 300; - - ent.movetype = MOVETYPE_PUSH; - ent.solid = SOLID_NOT; - ent.s.modelindex = gi.modelindex("models/ships/viper/tris.md2"); - VectorSet(ent.mins, -16, -16, 0); - VectorSet(ent.maxs, 16, 16, 32); - - ent.think = GameFuncAdapters.func_train_find; - ent.nextthink = level.time + FRAMETIME; - ent.use = GameMiscAdapters.misc_viper_use; - ent.svflags |= SVF_NOCLIENT; - ent.moveinfo.accel = ent.moveinfo.decel = ent.moveinfo.speed = ent.speed; - - gi.linkentity(ent); - } - - /*QUAKED misc_bigviper (1 .5 0) (-176 -120 -24) (176 120 72) - This is a large stationary viper as seen in Paul's intro - */ - public static void SP_misc_bigviper(edict_t ent) - { - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_BBOX; - VectorSet(ent.mins, -176, -120, -24); - VectorSet(ent.maxs, 176, 120, 72); - ent.s.modelindex = gi.modelindex("models/ships/bigviper/tris.md2"); - gi.linkentity(ent); - } - - public static void SP_misc_viper_bomb(edict_t self) - { - self.movetype = MOVETYPE_NONE; - self.solid = SOLID_NOT; - VectorSet(self.mins, -8, -8, -8); - VectorSet(self.maxs, 8, 8, 8); - - self.s.modelindex = gi.modelindex("models/objects/bomb/tris.md2"); - - if (self.dmg == 0) - self.dmg = 1000; - - self.use = GameMiscAdapters.misc_viper_bomb_use; - self.svflags |= SVF_NOCLIENT; - - gi.linkentity(self); - } - - public static void SP_misc_strogg_ship(edict_t ent) - { - if (null == ent.target) - { - gi.dprintf(ent.classname + " without a target at " + vtos(ent.absmin) + "\n"); - G_FreeEdict(ent); - return; - } - - if (0 == ent.speed) - ent.speed = 300; - - ent.movetype = MOVETYPE_PUSH; - ent.solid = SOLID_NOT; - ent.s.modelindex = gi.modelindex("models/ships/strogg1/tris.md2"); - VectorSet(ent.mins, -16, -16, 0); - VectorSet(ent.maxs, 16, 16, 32); - - ent.think = GameFuncAdapters.func_train_find; - ent.nextthink = level.time + FRAMETIME; - ent.use = GameMiscAdapters.misc_strogg_ship_use; - ent.svflags |= SVF_NOCLIENT; - ent.moveinfo.accel = ent.moveinfo.decel = ent.moveinfo.speed = ent.speed; - - gi.linkentity(ent); - } - - public static void SP_misc_satellite_dish(edict_t ent) - { - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_BBOX; - VectorSet(ent.mins, -64, -64, 0); - VectorSet(ent.maxs, 64, 64, 128); - ent.s.modelindex = gi.modelindex("models/objects/satellite/tris.md2"); - ent.use = GameMiscAdapters.misc_satellite_dish_use; - gi.linkentity(ent); - } - - /*QUAKED light_mine1 (0 1 0) (-2 -2 -12) (2 2 12) - */ - public static void SP_light_mine1(edict_t ent) - { - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_BBOX; - ent.s.modelindex = gi.modelindex("models/objects/minelite/light1/tris.md2"); - gi.linkentity(ent); - } - - /*QUAKED light_mine2 (0 1 0) (-2 -2 -12) (2 2 12) - */ - public static void SP_light_mine2(edict_t ent) - { - ent.movetype = MOVETYPE_NONE; - ent.solid = SOLID_BBOX; - ent.s.modelindex = gi.modelindex("models/objects/minelite/light2/tris.md2"); - gi.linkentity(ent); - } - - /*QUAKED misc_gib_arm (1 0 0) (-8 -8 -8) (8 8 8) - Intended for use with the target_spawner - */ - public static void SP_misc_gib_arm(edict_t ent) - { - gi.setmodel(ent, "models/objects/gibs/arm/tris.md2"); - ent.solid = SOLID_NOT; - ent.s.effects |= EF_GIB; - ent.takedamage = DAMAGE_YES; - ent.die = GameAIAdapters.gib_die; - ent.movetype = MOVETYPE_TOSS; - ent.svflags |= SVF_MONSTER; - ent.deadflag = DEAD_DEAD; - ent.avelocity[0] = random() * 200; - ent.avelocity[1] = random() * 200; - ent.avelocity[2] = random() * 200; - ent.think = GameUtilAdapters.G_FreeEdictA; - ent.nextthink = level.time + 30; - gi.linkentity(ent); - } - - /*QUAKED misc_gib_leg (1 0 0) (-8 -8 -8) (8 8 8) - Intended for use with the target_spawner - */ - public static void SP_misc_gib_leg(edict_t ent) - { - gi.setmodel(ent, "models/objects/gibs/leg/tris.md2"); - ent.solid = SOLID_NOT; - ent.s.effects |= EF_GIB; - ent.takedamage = DAMAGE_YES; - ent.die = GameAIAdapters.gib_die; - ent.movetype = MOVETYPE_TOSS; - ent.svflags |= SVF_MONSTER; - ent.deadflag = DEAD_DEAD; - ent.avelocity[0] = random() * 200; - ent.avelocity[1] = random() * 200; - ent.avelocity[2] = random() * 200; - ent.think = GameUtilAdapters.G_FreeEdictA; - ent.nextthink = level.time + 30; - gi.linkentity(ent); - } - - /*QUAKED misc_gib_head (1 0 0) (-8 -8 -8) (8 8 8) - Intended for use with the target_spawner - */ - public static void SP_misc_gib_head(edict_t ent) - { - gi.setmodel(ent, "models/objects/gibs/head/tris.md2"); - ent.solid = SOLID_NOT; - ent.s.effects |= EF_GIB; - ent.takedamage = DAMAGE_YES; - ent.die = GameAIAdapters.gib_die; - ent.movetype = MOVETYPE_TOSS; - ent.svflags |= SVF_MONSTER; - ent.deadflag = DEAD_DEAD; - ent.avelocity[0] = random() * 200; - ent.avelocity[1] = random() * 200; - ent.avelocity[2] = random() * 200; - ent.think = GameUtilAdapters.G_FreeEdictA; - ent.nextthink = level.time + 30; - gi.linkentity(ent); - } - - //===================================================== - - /*QUAKED target_character (0 0 1) ? - used with target_string (must be on same "team") - "count" is position in the string (starts at 1) - */ - - public static void SP_target_character(edict_t self) - { - self.movetype = MOVETYPE_PUSH; - gi.setmodel(self, self.model); - self.solid = SOLID_BSP; - self.s.frame = 12; - gi.linkentity(self); - return; - } - - public static void SP_target_string(edict_t self) - { - if (self.message == null) - self.message = ""; - self.use = GameMiscAdapters.target_string_use; - } - - // don't let field width of any clock messages change, or it - // could cause an overwrite after a game load - - public static void func_clock_reset(edict_t self) - { - self.activator = null; - if ((self.spawnflags & 1) != 0) - { - self.health = 0; - self.wait = self.count; - } - else if ((self.spawnflags & 2) != 0) - { - self.health = self.count; - self.wait = 0; - } - } - - public static void func_clock_format_countdown(edict_t self) - { - if (self.style == 0) - { - self.message = "" + self.health; - //Com_sprintf(self.message, CLOCK_MESSAGE_SIZE, "%2i", self.health); - return; - } - - if (self.style == 1) - { - self.message = "" + self.health / 60 + ":" + self.health % 60; - //Com_sprintf(self.message, CLOCK_MESSAGE_SIZE, "%2i:%2i", self.health / 60, self.health % 60); - /* - if (self.message.charAt(3) == ' ') - self.message.charAt(3) = '0'; - */ - return; - } - - if (self.style == 2) - { - self.message = "" + self.health / 3600 + ":" + (self.health - (self.health / 3600) * 3600) / 60 + ":" + self.health % 60; - /* - Com_sprintf( - self.message, - CLOCK_MESSAGE_SIZE, - "%2i:%2i:%2i", - self.health / 3600, - (self.health - (self.health / 3600) * 3600) / 60, - self.health % 60); - if (self.message[3] == ' ') - self.message[3] = '0'; - if (self.message[6] == ' ') - self.message[6] = '0'; - */ - return; - } - } - - public static void SP_func_clock(edict_t self) - { - if (self.target == null) - { - gi.dprintf(self.classname + " with no target at " + vtos(self.s.origin) + "\n"); - G_FreeEdict(self); - return; - } - - if ((self.spawnflags & 2) != 0 && (0 == self.count)) - { - gi.dprintf(self.classname + " with no count at " + vtos(self.s.origin) + "\n"); - G_FreeEdict(self); - return; - } - - if ((self.spawnflags & 1) != 0 && (0 == self.count)) - self.count = 60 * 60; - - func_clock_reset(self); - - self.message = new String(); - - self.think = GameMiscAdapters.func_clock_think; - - if ((self.spawnflags & 4) != 0) - self.use = GameMiscAdapters.func_clock_use; - else - self.nextthink = level.time + 1; - } - - /*QUAKED misc_teleporter (1 0 0) (-32 -32 -24) (32 32 -16) - Stepping onto this disc will teleport players to the targeted misc_teleporter_dest object. - */ - public static void SP_misc_teleporter(edict_t ent) - { - edict_t trig; - - if (ent.target == null) - { - gi.dprintf("teleporter without a target.\n"); - G_FreeEdict(ent); - return; - } - - gi.setmodel(ent, "models/objects/dmspot/tris.md2"); - ent.s.skinnum = 1; - ent.s.effects = EF_TELEPORTER; - ent.s.sound = gi.soundindex("world/amb10.wav"); - ent.solid = SOLID_BBOX; - - VectorSet(ent.mins, -32, -32, -24); - VectorSet(ent.maxs, 32, 32, -16); - gi.linkentity(ent); - - trig = G_Spawn(); - trig.touch = GameMiscAdapters.teleporter_touch; - trig.solid = SOLID_TRIGGER; - trig.target = ent.target; - trig.owner = ent; - VectorCopy(ent.s.origin, trig.s.origin); - VectorSet(trig.mins, -8, -8, 8); - VectorSet(trig.maxs, 8, 8, 24); - gi.linkentity(trig); - } -} +import jake2.Defines; +import jake2.Globals; +import jake2.client.M; +import jake2.util.Lib; +import jake2.util.Math3D; + +public class GameMisc { + public static void SP_path_corner(edict_t self) { + if (self.targetname == null) { + GameBase.gi.dprintf("path_corner with no targetname at " + + Lib.vtos(self.s.origin) + "\n"); + GameUtil.G_FreeEdict(self); + return; + } + + self.solid = Defines.SOLID_TRIGGER; + self.touch = path_corner_touch; + Math3D.VectorSet(self.mins, -8, -8, -8); + Math3D.VectorSet(self.maxs, 8, 8, 8); + self.svflags |= Defines.SVF_NOCLIENT; + GameBase.gi.linkentity(self); + } + + public static void SP_point_combat(edict_t self) { + if (GameBase.deathmatch.value != 0) { + GameUtil.G_FreeEdict(self); + return; + } + self.solid = Defines.SOLID_TRIGGER; + self.touch = point_combat_touch; + Math3D.VectorSet(self.mins, -8, -8, -16); + Math3D.VectorSet(self.maxs, 8, 8, 16); + self.svflags = Defines.SVF_NOCLIENT; + GameBase.gi.linkentity(self); + }; + + public static void SP_viewthing(edict_t ent) { + GameBase.gi.dprintf("viewthing spawned\n"); + + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_BBOX; + ent.s.renderfx = Defines.RF_FRAMELERP; + Math3D.VectorSet(ent.mins, -16, -16, -24); + Math3D.VectorSet(ent.maxs, 16, 16, 32); + ent.s.modelindex = GameBase.gi + .modelindex("models/objects/banner/tris.md2"); + GameBase.gi.linkentity(ent); + ent.nextthink = GameBase.level.time + 0.5f; + ent.think = TH_viewthing; + return; + } + + /* + * QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4) Used as a positional target + * for spotlights, etc. + */ + public static void SP_info_null(edict_t self) { + GameUtil.G_FreeEdict(self); + }; + + /* + * QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4) Used as a positional + * target for lightning. + */ + public static void SP_info_notnull(edict_t self) { + Math3D.VectorCopy(self.s.origin, self.absmin); + Math3D.VectorCopy(self.s.origin, self.absmax); + }; + + public static void SP_light(edict_t self) { + // no targeted lights in deathmatch, because they cause global messages + if (null == self.targetname || GameBase.deathmatch.value != 0) { + GameUtil.G_FreeEdict(self); + return; + } + + if (self.style >= 32) { + self.use = light_use; + if ((self.spawnflags & START_OFF) != 0) + GameBase.gi.configstring(Defines.CS_LIGHTS + self.style, "a"); + else + GameBase.gi.configstring(Defines.CS_LIGHTS + self.style, "m"); + } + } + + public static void SP_func_wall(edict_t self) { + self.movetype = Defines.MOVETYPE_PUSH; + GameBase.gi.setmodel(self, self.model); + + if ((self.spawnflags & 8) != 0) + self.s.effects |= Defines.EF_ANIM_ALL; + if ((self.spawnflags & 16) != 0) + self.s.effects |= Defines.EF_ANIM_ALLFAST; + + // just a wall + if ((self.spawnflags & 7) == 0) { + self.solid = Defines.SOLID_BSP; + GameBase.gi.linkentity(self); + return; + } + + // it must be TRIGGER_SPAWN + if (0 == (self.spawnflags & 1)) { + GameBase.gi.dprintf("func_wall missing TRIGGER_SPAWN\n"); + self.spawnflags |= 1; + } + + // yell if the spawnflags are odd + if ((self.spawnflags & 4) != 0) { + if (0 == (self.spawnflags & 2)) { + GameBase.gi.dprintf("func_wall START_ON without TOGGLE\n"); + self.spawnflags |= 2; + } + } + + self.use = func_wall_use; + if ((self.spawnflags & 4) != 0) { + self.solid = Defines.SOLID_BSP; + } else { + self.solid = Defines.SOLID_NOT; + self.svflags |= Defines.SVF_NOCLIENT; + } + GameBase.gi.linkentity(self); + } + + public static void SP_func_object(edict_t self) { + GameBase.gi.setmodel(self, self.model); + + self.mins[0] += 1; + self.mins[1] += 1; + self.mins[2] += 1; + self.maxs[0] -= 1; + self.maxs[1] -= 1; + self.maxs[2] -= 1; + + if (self.dmg == 0) + self.dmg = 100; + + if (self.spawnflags == 0) { + self.solid = Defines.SOLID_BSP; + self.movetype = Defines.MOVETYPE_PUSH; + self.think = func_object_release; + self.nextthink = GameBase.level.time + 2 * Defines.FRAMETIME; + } else { + self.solid = Defines.SOLID_NOT; + self.movetype = Defines.MOVETYPE_PUSH; + self.use = func_object_use; + self.svflags |= Defines.SVF_NOCLIENT; + } + + if ((self.spawnflags & 2) != 0) + self.s.effects |= Defines.EF_ANIM_ALL; + if ((self.spawnflags & 4) != 0) + self.s.effects |= Defines.EF_ANIM_ALLFAST; + + self.clipmask = Defines.MASK_MONSTERSOLID; + + GameBase.gi.linkentity(self); + } + + public static void SP_func_explosive(edict_t self) { + if (GameBase.deathmatch.value != 0) { // auto-remove for deathmatch + GameUtil.G_FreeEdict(self); + return; + } + + self.movetype = Defines.MOVETYPE_PUSH; + + GameBase.gi.modelindex("models/objects/debris1/tris.md2"); + GameBase.gi.modelindex("models/objects/debris2/tris.md2"); + + GameBase.gi.setmodel(self, self.model); + + if ((self.spawnflags & 1) != 0) { + self.svflags |= Defines.SVF_NOCLIENT; + self.solid = Defines.SOLID_NOT; + self.use = func_explosive_spawn; + } else { + self.solid = Defines.SOLID_BSP; + if (self.targetname != null) + self.use = func_explosive_use; + } + + if ((self.spawnflags & 2) != 0) + self.s.effects |= Defines.EF_ANIM_ALL; + if ((self.spawnflags & 4) != 0) + self.s.effects |= Defines.EF_ANIM_ALLFAST; + + if (self.use != func_explosive_use) { + if (self.health == 0) + self.health = 100; + self.die = func_explosive_explode; + self.takedamage = Defines.DAMAGE_YES; + } + + GameBase.gi.linkentity(self); + } + + public static void SP_misc_explobox(edict_t self) { + if (GameBase.deathmatch.value != 0) { // auto-remove for deathmatch + GameUtil.G_FreeEdict(self); + return; + } + + GameBase.gi.modelindex("models/objects/debris1/tris.md2"); + GameBase.gi.modelindex("models/objects/debris2/tris.md2"); + GameBase.gi.modelindex("models/objects/debris3/tris.md2"); + + self.solid = Defines.SOLID_BBOX; + self.movetype = Defines.MOVETYPE_STEP; + + self.model = "models/objects/barrels/tris.md2"; + self.s.modelindex = GameBase.gi.modelindex(self.model); + Math3D.VectorSet(self.mins, -16, -16, 0); + Math3D.VectorSet(self.maxs, 16, 16, 40); + + if (self.mass == 0) + self.mass = 400; + if (0 == self.health) + self.health = 10; + if (0 == self.dmg) + self.dmg = 150; + + self.die = barrel_delay; + self.takedamage = Defines.DAMAGE_YES; + self.monsterinfo.aiflags = Defines.AI_NOSTEP; + + self.touch = barrel_touch; + + self.think = M.M_droptofloor; + self.nextthink = GameBase.level.time + 2 * Defines.FRAMETIME; + + GameBase.gi.linkentity(self); + } + + public static void SP_misc_blackhole(edict_t ent) { + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_NOT; + Math3D.VectorSet(ent.mins, -64, -64, 0); + Math3D.VectorSet(ent.maxs, 64, 64, 8); + ent.s.modelindex = GameBase.gi + .modelindex("models/objects/black/tris.md2"); + ent.s.renderfx = Defines.RF_TRANSLUCENT; + ent.use = misc_blackhole_use; + ent.think = misc_blackhole_think; + ent.nextthink = GameBase.level.time + 2 * Defines.FRAMETIME; + GameBase.gi.linkentity(ent); + } + + public static void SP_misc_eastertank(edict_t ent) { + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_BBOX; + Math3D.VectorSet(ent.mins, -32, -32, -16); + Math3D.VectorSet(ent.maxs, 32, 32, 32); + ent.s.modelindex = GameBase.gi + .modelindex("models/monsters/tank/tris.md2"); + ent.s.frame = 254; + ent.think = misc_eastertank_think; + ent.nextthink = GameBase.level.time + 2 * Defines.FRAMETIME; + GameBase.gi.linkentity(ent); + } + + public static void SP_misc_easterchick(edict_t ent) { + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_BBOX; + Math3D.VectorSet(ent.mins, -32, -32, 0); + Math3D.VectorSet(ent.maxs, 32, 32, 32); + ent.s.modelindex = GameBase.gi + .modelindex("models/monsters/bitch/tris.md2"); + ent.s.frame = 208; + ent.think = misc_easterchick_think; + ent.nextthink = GameBase.level.time + 2 * Defines.FRAMETIME; + GameBase.gi.linkentity(ent); + } + + public static void SP_misc_easterchick2(edict_t ent) { + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_BBOX; + Math3D.VectorSet(ent.mins, -32, -32, 0); + Math3D.VectorSet(ent.maxs, 32, 32, 32); + ent.s.modelindex = GameBase.gi + .modelindex("models/monsters/bitch/tris.md2"); + ent.s.frame = 248; + ent.think = misc_easterchick2_think; + ent.nextthink = GameBase.level.time + 2 * Defines.FRAMETIME; + GameBase.gi.linkentity(ent); + } + + public static void SP_monster_commander_body(edict_t self) { + self.movetype = Defines.MOVETYPE_NONE; + self.solid = Defines.SOLID_BBOX; + self.model = "models/monsters/commandr/tris.md2"; + self.s.modelindex = GameBase.gi.modelindex(self.model); + Math3D.VectorSet(self.mins, -32, -32, 0); + Math3D.VectorSet(self.maxs, 32, 32, 48); + self.use = commander_body_use; + self.takedamage = Defines.DAMAGE_YES; + self.flags = Defines.FL_GODMODE; + self.s.renderfx |= Defines.RF_FRAMELERP; + GameBase.gi.linkentity(self); + + GameBase.gi.soundindex("tank/thud.wav"); + GameBase.gi.soundindex("tank/pain.wav"); + + self.think = commander_body_drop; + self.nextthink = GameBase.level.time + 5 * Defines.FRAMETIME; + } + + public static void SP_misc_banner(edict_t ent) { + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_NOT; + ent.s.modelindex = GameBase.gi + .modelindex("models/objects/banner/tris.md2"); + ent.s.frame = Lib.rand() % 16; + GameBase.gi.linkentity(ent); + + ent.think = misc_banner_think; + ent.nextthink = GameBase.level.time + Defines.FRAMETIME; + } + + public static void SP_misc_deadsoldier(edict_t ent) { + if (GameBase.deathmatch.value != 0) { // auto-remove for deathmatch + GameUtil.G_FreeEdict(ent); + return; + } + + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_BBOX; + ent.s.modelindex = GameBase.gi + .modelindex("models/deadbods/dude/tris.md2"); + + // Defaults to frame 0 + if ((ent.spawnflags & 2) != 0) + ent.s.frame = 1; + else if ((ent.spawnflags & 4) != 0) + ent.s.frame = 2; + else if ((ent.spawnflags & 8) != 0) + ent.s.frame = 3; + else if ((ent.spawnflags & 16) != 0) + ent.s.frame = 4; + else if ((ent.spawnflags & 32) != 0) + ent.s.frame = 5; + else + ent.s.frame = 0; + + Math3D.VectorSet(ent.mins, -16, -16, 0); + Math3D.VectorSet(ent.maxs, 16, 16, 16); + ent.deadflag = Defines.DEAD_DEAD; + ent.takedamage = Defines.DAMAGE_YES; + ent.svflags |= Defines.SVF_MONSTER | Defines.SVF_DEADMONSTER; + ent.die = misc_deadsoldier_die; + ent.monsterinfo.aiflags |= Defines.AI_GOOD_GUY; + + GameBase.gi.linkentity(ent); + } + + public static void SP_misc_viper(edict_t ent) { + if (null == ent.target) { + GameBase.gi.dprintf("misc_viper without a target at " + + Lib.vtos(ent.absmin) + "\n"); + GameUtil.G_FreeEdict(ent); + return; + } + + if (0 == ent.speed) + ent.speed = 300; + + ent.movetype = Defines.MOVETYPE_PUSH; + ent.solid = Defines.SOLID_NOT; + ent.s.modelindex = GameBase.gi + .modelindex("models/ships/viper/tris.md2"); + Math3D.VectorSet(ent.mins, -16, -16, 0); + Math3D.VectorSet(ent.maxs, 16, 16, 32); + + ent.think = GameFunc.func_train_find; + ent.nextthink = GameBase.level.time + Defines.FRAMETIME; + ent.use = misc_viper_use; + ent.svflags |= Defines.SVF_NOCLIENT; + ent.moveinfo.accel = ent.moveinfo.decel = ent.moveinfo.speed = ent.speed; + + GameBase.gi.linkentity(ent); + } + + /* + * QUAKED misc_bigviper (1 .5 0) (-176 -120 -24) (176 120 72) This is a + * large stationary viper as seen in Paul's intro + */ + public static void SP_misc_bigviper(edict_t ent) { + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_BBOX; + Math3D.VectorSet(ent.mins, -176, -120, -24); + Math3D.VectorSet(ent.maxs, 176, 120, 72); + ent.s.modelindex = GameBase.gi + .modelindex("models/ships/bigviper/tris.md2"); + GameBase.gi.linkentity(ent); + } + + public static void SP_misc_viper_bomb(edict_t self) { + self.movetype = Defines.MOVETYPE_NONE; + self.solid = Defines.SOLID_NOT; + Math3D.VectorSet(self.mins, -8, -8, -8); + Math3D.VectorSet(self.maxs, 8, 8, 8); + + self.s.modelindex = GameBase.gi + .modelindex("models/objects/bomb/tris.md2"); + + if (self.dmg == 0) + self.dmg = 1000; + + self.use = misc_viper_bomb_use; + self.svflags |= Defines.SVF_NOCLIENT; + + GameBase.gi.linkentity(self); + } + + public static void SP_misc_strogg_ship(edict_t ent) { + if (null == ent.target) { + GameBase.gi.dprintf(ent.classname + " without a target at " + + Lib.vtos(ent.absmin) + "\n"); + GameUtil.G_FreeEdict(ent); + return; + } + + if (0 == ent.speed) + ent.speed = 300; + + ent.movetype = Defines.MOVETYPE_PUSH; + ent.solid = Defines.SOLID_NOT; + ent.s.modelindex = GameBase.gi + .modelindex("models/ships/strogg1/tris.md2"); + Math3D.VectorSet(ent.mins, -16, -16, 0); + Math3D.VectorSet(ent.maxs, 16, 16, 32); + + ent.think = GameFunc.func_train_find; + ent.nextthink = GameBase.level.time + Defines.FRAMETIME; + ent.use = misc_strogg_ship_use; + ent.svflags |= Defines.SVF_NOCLIENT; + ent.moveinfo.accel = ent.moveinfo.decel = ent.moveinfo.speed = ent.speed; + + GameBase.gi.linkentity(ent); + } + + public static void SP_misc_satellite_dish(edict_t ent) { + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_BBOX; + Math3D.VectorSet(ent.mins, -64, -64, 0); + Math3D.VectorSet(ent.maxs, 64, 64, 128); + ent.s.modelindex = GameBase.gi + .modelindex("models/objects/satellite/tris.md2"); + ent.use = misc_satellite_dish_use; + GameBase.gi.linkentity(ent); + } + + /* + * QUAKED light_mine1 (0 1 0) (-2 -2 -12) (2 2 12) + */ + public static void SP_light_mine1(edict_t ent) { + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_BBOX; + ent.s.modelindex = GameBase.gi + .modelindex("models/objects/minelite/light1/tris.md2"); + GameBase.gi.linkentity(ent); + } + + /* + * QUAKED light_mine2 (0 1 0) (-2 -2 -12) (2 2 12) + */ + public static void SP_light_mine2(edict_t ent) { + ent.movetype = Defines.MOVETYPE_NONE; + ent.solid = Defines.SOLID_BBOX; + ent.s.modelindex = GameBase.gi + .modelindex("models/objects/minelite/light2/tris.md2"); + GameBase.gi.linkentity(ent); + } + + /* + * QUAKED misc_gib_arm (1 0 0) (-8 -8 -8) (8 8 8) Intended for use with the + * target_spawner + */ + public static void SP_misc_gib_arm(edict_t ent) { + GameBase.gi.setmodel(ent, "models/objects/gibs/arm/tris.md2"); + ent.solid = Defines.SOLID_NOT; + ent.s.effects |= Defines.EF_GIB; + ent.takedamage = Defines.DAMAGE_YES; + ent.die = GameAI.gib_die; + ent.movetype = Defines.MOVETYPE_TOSS; + ent.svflags |= Defines.SVF_MONSTER; + ent.deadflag = Defines.DEAD_DEAD; + ent.avelocity[0] = Lib.random() * 200; + ent.avelocity[1] = Lib.random() * 200; + ent.avelocity[2] = Lib.random() * 200; + ent.think = GameUtil.G_FreeEdictA; + ent.nextthink = GameBase.level.time + 30; + GameBase.gi.linkentity(ent); + } + + /* + * QUAKED misc_gib_leg (1 0 0) (-8 -8 -8) (8 8 8) Intended for use with the + * target_spawner + */ + public static void SP_misc_gib_leg(edict_t ent) { + GameBase.gi.setmodel(ent, "models/objects/gibs/leg/tris.md2"); + ent.solid = Defines.SOLID_NOT; + ent.s.effects |= Defines.EF_GIB; + ent.takedamage = Defines.DAMAGE_YES; + ent.die = GameAI.gib_die; + ent.movetype = Defines.MOVETYPE_TOSS; + ent.svflags |= Defines.SVF_MONSTER; + ent.deadflag = Defines.DEAD_DEAD; + ent.avelocity[0] = Lib.random() * 200; + ent.avelocity[1] = Lib.random() * 200; + ent.avelocity[2] = Lib.random() * 200; + ent.think = GameUtil.G_FreeEdictA; + ent.nextthink = GameBase.level.time + 30; + GameBase.gi.linkentity(ent); + } + + /* + * QUAKED misc_gib_head (1 0 0) (-8 -8 -8) (8 8 8) Intended for use with the + * target_spawner + */ + public static void SP_misc_gib_head(edict_t ent) { + GameBase.gi.setmodel(ent, "models/objects/gibs/head/tris.md2"); + ent.solid = Defines.SOLID_NOT; + ent.s.effects |= Defines.EF_GIB; + ent.takedamage = Defines.DAMAGE_YES; + ent.die = GameAI.gib_die; + ent.movetype = Defines.MOVETYPE_TOSS; + ent.svflags |= Defines.SVF_MONSTER; + ent.deadflag = Defines.DEAD_DEAD; + ent.avelocity[0] = Lib.random() * 200; + ent.avelocity[1] = Lib.random() * 200; + ent.avelocity[2] = Lib.random() * 200; + ent.think = GameUtil.G_FreeEdictA; + ent.nextthink = GameBase.level.time + 30; + GameBase.gi.linkentity(ent); + } + + //===================================================== + + /* + * QUAKED target_character (0 0 1) ? used with target_string (must be on + * same "team") "count" is position in the string (starts at 1) + */ + + public static void SP_target_character(edict_t self) { + self.movetype = Defines.MOVETYPE_PUSH; + GameBase.gi.setmodel(self, self.model); + self.solid = Defines.SOLID_BSP; + self.s.frame = 12; + GameBase.gi.linkentity(self); + return; + } + + public static void SP_target_string(edict_t self) { + if (self.message == null) + self.message = ""; + self.use = target_string_use; + } + + // don't let field width of any clock messages change, or it + // could cause an overwrite after a game load + + public static void func_clock_reset(edict_t self) { + self.activator = null; + if ((self.spawnflags & 1) != 0) { + self.health = 0; + self.wait = self.count; + } else if ((self.spawnflags & 2) != 0) { + self.health = self.count; + self.wait = 0; + } + } + + public static void func_clock_format_countdown(edict_t self) { + if (self.style == 0) { + self.message = "" + self.health; + //Com_sprintf(self.message, CLOCK_MESSAGE_SIZE, "%2i", + // self.health); + return; + } + + if (self.style == 1) { + self.message = "" + self.health / 60 + ":" + self.health % 60; + //Com_sprintf(self.message, CLOCK_MESSAGE_SIZE, "%2i:%2i", + // self.health / 60, self.health % 60); + /* + * if (self.message.charAt(3) == ' ') self.message.charAt(3) = '0'; + */ + return; + } + + if (self.style == 2) { + self.message = "" + self.health / 3600 + ":" + + (self.health - (self.health / 3600) * 3600) / 60 + ":" + + self.health % 60; + /* + * Com_sprintf( self.message, CLOCK_MESSAGE_SIZE, "%2i:%2i:%2i", + * self.health / 3600, (self.health - (self.health / 3600) * 3600) / + * 60, self.health % 60); if (self.message[3] == ' ') + * self.message[3] = '0'; if (self.message[6] == ' ') + * self.message[6] = '0'; + */ + return; + } + } + + public static void SP_func_clock(edict_t self) { + if (self.target == null) { + GameBase.gi.dprintf(self.classname + " with no target at " + + Lib.vtos(self.s.origin) + "\n"); + GameUtil.G_FreeEdict(self); + return; + } + + if ((self.spawnflags & 2) != 0 && (0 == self.count)) { + GameBase.gi.dprintf(self.classname + " with no count at " + + Lib.vtos(self.s.origin) + "\n"); + GameUtil.G_FreeEdict(self); + return; + } + + if ((self.spawnflags & 1) != 0 && (0 == self.count)) + self.count = 60 * 60; + + func_clock_reset(self); + + self.message = new String(); + + self.think = func_clock_think; + + if ((self.spawnflags & 4) != 0) + self.use = func_clock_use; + else + self.nextthink = GameBase.level.time + 1; + } + + /* + * QUAKED misc_teleporter (1 0 0) (-32 -32 -24) (32 32 -16) Stepping onto + * this disc will teleport players to the targeted misc_teleporter_dest + * object. + */ + public static void SP_misc_teleporter(edict_t ent) { + edict_t trig; + + if (ent.target == null) { + GameBase.gi.dprintf("teleporter without a target.\n"); + GameUtil.G_FreeEdict(ent); + return; + } + + GameBase.gi.setmodel(ent, "models/objects/dmspot/tris.md2"); + ent.s.skinnum = 1; + ent.s.effects = Defines.EF_TELEPORTER; + ent.s.sound = GameBase.gi.soundindex("world/amb10.wav"); + ent.solid = Defines.SOLID_BBOX; + + Math3D.VectorSet(ent.mins, -32, -32, -24); + Math3D.VectorSet(ent.maxs, 32, 32, -16); + GameBase.gi.linkentity(ent); + + trig = GameUtil.G_Spawn(); + trig.touch = teleporter_touch; + trig.solid = Defines.SOLID_TRIGGER; + trig.target = ent.target; + trig.owner = ent; + Math3D.VectorCopy(ent.s.origin, trig.s.origin); + Math3D.VectorSet(trig.mins, -8, -8, 8); + Math3D.VectorSet(trig.maxs, 8, 8, 24); + GameBase.gi.linkentity(trig); + } + + /* + * QUAKED func_group (0 0 0) ? Used to group brushes together just for + * editor convenience. + */ + + //===================================================== + public static EntUseAdapter Use_Areaportal = new EntUseAdapter() { + public void use(edict_t ent, edict_t other, edict_t activator) { + ent.count ^= 1; // toggle state + // gi.dprintf ("portalstate: %i = %i\n", ent.style, ent.count); + GameBase.gi.SetAreaPortalState(ent.style, ent.count != 0); + } + }; + + /* + * QUAKED func_areaportal (0 0 0) ? + * + * This is a non-visible object that divides the world into areas that are + * seperated when this portal is not activated. Usually enclosed in the + * middle of a door. + */ + + static EntThinkAdapter SP_func_areaportal = new EntThinkAdapter() { + public boolean think(edict_t ent) { + ent.use = Use_Areaportal; + ent.count = 0; // always start closed; + return true; + } + }; + + /* + * QUAKED path_corner (.5 .3 0) (-8 -8 -8) (8 8 8) TELEPORT Target: next + * path corner Pathtarget: gets used when an entity that has this + * path_corner targeted touches it + */ + public static EntTouchAdapter path_corner_touch = new EntTouchAdapter() { + public void touch(edict_t self, edict_t other, cplane_t plane, + csurface_t surf) { + float[] v = { 0, 0, 0 }; + edict_t next; + + if (other.movetarget != self) + return; + + if (other.enemy != null) + return; + + if (self.pathtarget != null) { + String savetarget; + + savetarget = self.target; + self.target = self.pathtarget; + GameUtil.G_UseTargets(self, other); + self.target = savetarget; + } + + if (self.target != null) + next = GameBase.G_PickTarget(self.target); + else + next = null; + + if ((next != null) && (next.spawnflags & 1) != 0) { + Math3D.VectorCopy(next.s.origin, v); + v[2] += next.mins[2]; + v[2] -= other.mins[2]; + Math3D.VectorCopy(v, other.s.origin); + next = GameBase.G_PickTarget(next.target); + other.s.event = Defines.EV_OTHER_TELEPORT; + } + + other.goalentity = other.movetarget = next; + + if (self.wait != 0) { + other.monsterinfo.pausetime = GameBase.level.time + self.wait; + other.monsterinfo.stand.think(other); + return; + } + + if (other.movetarget == null) { + other.monsterinfo.pausetime = GameBase.level.time + 100000000; + other.monsterinfo.stand.think(other); + } else { + Math3D.VectorSubtract(other.goalentity.s.origin, + other.s.origin, v); + other.ideal_yaw = Math3D.vectoyaw(v); + } + } + }; + + /* + * QUAKED point_combat (0.5 0.3 0) (-8 -8 -8) (8 8 8) Hold Makes this the + * target of a monster and it will head here when first activated before + * going after the activator. If hold is selected, it will stay here. + */ + public static EntTouchAdapter point_combat_touch = new EntTouchAdapter() { + public void touch(edict_t self, edict_t other, cplane_t plane, + csurface_t surf) { + edict_t activator; + + if (other.movetarget != self) + return; + + if (self.target != null) { + other.target = self.target; + other.goalentity = other.movetarget = GameBase + .G_PickTarget(other.target); + if (null == other.goalentity) { + GameBase.gi.dprintf(self.classname + " at " + + Lib.vtos(self.s.origin) + " target " + + self.target + " does not exist\n"); + other.movetarget = self; + } + self.target = null; + } else if ((self.spawnflags & 1) != 0 + && 0 == (other.flags & (Defines.FL_SWIM | Defines.FL_FLY))) { + other.monsterinfo.pausetime = GameBase.level.time + 100000000; + other.monsterinfo.aiflags |= Defines.AI_STAND_GROUND; + other.monsterinfo.stand.think(other); + } + + if (other.movetarget == self) { + other.target = null; + other.movetarget = null; + other.goalentity = other.enemy; + other.monsterinfo.aiflags &= ~Defines.AI_COMBAT_POINT; + } + + if (self.pathtarget != null) { + String savetarget; + + savetarget = self.target; + self.target = self.pathtarget; + if (other.enemy != null && other.enemy.client != null) + activator = other.enemy; + else if (other.oldenemy != null + && other.oldenemy.client != null) + activator = other.oldenemy; + else if (other.activator != null + && other.activator.client != null) + activator = other.activator; + else + activator = other; + GameUtil.G_UseTargets(self, activator); + self.target = savetarget; + } + } + }; + + /* + * QUAKED viewthing (0 .5 .8) (-8 -8 -8) (8 8 8) Just for the debugging + * level. Don't use + */ + public static EntThinkAdapter TH_viewthing = new EntThinkAdapter() { + public boolean think(edict_t ent) { + ent.s.frame = (ent.s.frame + 1) % 7; + ent.nextthink = GameBase.level.time + Defines.FRAMETIME; + return true; + } + }; + + /* + * QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) START_OFF Non-displayed light. + * Default light value is 300. Default style is 0. If targeted, will toggle + * between on and off. Default _cone value is 10 (used to set size of light + * for spotlights) + */ + + public static final int START_OFF = 1; + + public static EntUseAdapter light_use = new EntUseAdapter() { + + public void use(edict_t self, edict_t other, edict_t activator) { + if ((self.spawnflags & START_OFF) != 0) { + GameBase.gi.configstring(Defines.CS_LIGHTS + self.style, "m"); + self.spawnflags &= ~START_OFF; + } else { + GameBase.gi.configstring(Defines.CS_LIGHTS + self.style, "a"); + self.spawnflags |= START_OFF; + } + } + }; + + /* + * QUAKED func_wall (0 .5 .8) ? TRIGGER_SPAWN TOGGLE START_ON ANIMATED + * ANIMATED_FAST This is just a solid wall if not inhibited + * + * TRIGGER_SPAWN the wall will not be present until triggered it will then + * blink in to existance; it will kill anything that was in it's way + * + * TOGGLE only valid for TRIGGER_SPAWN walls this allows the wall to be + * turned on and off + * + * START_ON only valid for TRIGGER_SPAWN walls the wall will initially be + * present + */ + + static EntUseAdapter func_wall_use = new EntUseAdapter() { + public void use(edict_t self, edict_t other, edict_t activator) { + if (self.solid == Defines.SOLID_NOT) { + self.solid = Defines.SOLID_BSP; + self.svflags &= ~Defines.SVF_NOCLIENT; + GameUtil.KillBox(self); + } else { + self.solid = Defines.SOLID_NOT; + self.svflags |= Defines.SVF_NOCLIENT; + } + GameBase.gi.linkentity(self); + + if (0 == (self.spawnflags & 2)) + self.use = null; + } + }; + + /* + * QUAKED func_object (0 .5 .8) ? TRIGGER_SPAWN ANIMATED ANIMATED_FAST This + * is solid bmodel that will fall if it's support it removed. + */ + static EntTouchAdapter func_object_touch = new EntTouchAdapter() { + public void touch(edict_t self, edict_t other, cplane_t plane, + csurface_t surf) { + // only squash thing we fall on top of + if (plane == null) + return; + if (plane.normal[2] < 1.0) + return; + if (other.takedamage == Defines.DAMAGE_NO) + return; + GameUtil.T_Damage(other, self, self, Globals.vec3_origin, + self.s.origin, Globals.vec3_origin, self.dmg, 1, 0, + Defines.MOD_CRUSH); + } + }; + + static EntThinkAdapter func_object_release = new EntThinkAdapter() { + public boolean think(edict_t self) { + self.movetype = Defines.MOVETYPE_TOSS; + self.touch = func_object_touch; + return true; + } + }; + + static EntUseAdapter func_object_use = new EntUseAdapter() { + public void use(edict_t self, edict_t other, edict_t activator) { + self.solid = Defines.SOLID_BSP; + self.svflags &= ~Defines.SVF_NOCLIENT; + self.use = null; + GameUtil.KillBox(self); + func_object_release.think(self); + } + }; + + /* + * QUAKED func_explosive (0 .5 .8) ? Trigger_Spawn ANIMATED ANIMATED_FAST + * Any brush that you want to explode or break apart. If you want an + * ex0plosion, set dmg and it will do a radius explosion of that amount at + * the center of the bursh. + * + * If targeted it will not be shootable. + * + * health defaults to 100. + * + * mass defaults to 75. This determines how much debris is emitted when it + * explodes. You get one large chunk per 100 of mass (up to 8) and one small + * chunk per 25 of mass (up to 16). So 800 gives the most. + */ + public static EntDieAdapter func_explosive_explode = new EntDieAdapter() { + + public void die(edict_t self, edict_t inflictor, edict_t attacker, + int damage, float[] point) { + float[] origin = { 0, 0, 0 }; + float[] chunkorigin = { 0, 0, 0 }; + float[] size = { 0, 0, 0 }; + int count; + int mass; + + // bmodel origins are (0 0 0), we need to adjust that here + Math3D.VectorScale(self.size, 0.5f, size); + Math3D.VectorAdd(self.absmin, size, origin); + Math3D.VectorCopy(origin, self.s.origin); + + self.takedamage = Defines.DAMAGE_NO; + + if (self.dmg != 0) + GameUtil.T_RadiusDamage(self, attacker, self.dmg, null, + self.dmg + 40, Defines.MOD_EXPLOSIVE); + + Math3D.VectorSubtract(self.s.origin, inflictor.s.origin, + self.velocity); + Math3D.VectorNormalize(self.velocity); + Math3D.VectorScale(self.velocity, 150, self.velocity); + + // start chunks towards the center + Math3D.VectorScale(size, 0.5f, size); + + mass = self.mass; + if (0 == mass) + mass = 75; + + // big chunks + if (mass >= 100) { + count = mass / 100; + if (count > 8) + count = 8; + while (count-- != 0) { + chunkorigin[0] = origin[0] + Lib.crandom() * size[0]; + chunkorigin[1] = origin[1] + Lib.crandom() * size[1]; + chunkorigin[2] = origin[2] + Lib.crandom() * size[2]; + GameAI.ThrowDebris(self, "models/objects/debris1/tris.md2", + 1, chunkorigin); + } + } + + // small chunks + count = mass / 25; + if (count > 16) + count = 16; + while (count-- != 0) { + chunkorigin[0] = origin[0] + Lib.crandom() * size[0]; + chunkorigin[1] = origin[1] + Lib.crandom() * size[1]; + chunkorigin[2] = origin[2] + Lib.crandom() * size[2]; + GameAI.ThrowDebris(self, "models/objects/debris2/tris.md2", 2, + chunkorigin); + } + + GameUtil.G_UseTargets(self, attacker); + + if (self.dmg != 0) + GameAI.BecomeExplosion1(self); + else + GameUtil.G_FreeEdict(self); + } + }; + + public static EntUseAdapter func_explosive_use = new EntUseAdapter() { + public void use(edict_t self, edict_t other, edict_t activator) { + func_explosive_explode.die(self, self, other, self.health, + Globals.vec3_origin); + } + }; + + public static EntUseAdapter func_explosive_spawn = new EntUseAdapter() { + + public void use(edict_t self, edict_t other, edict_t activator) { + self.solid = Defines.SOLID_BSP; + self.svflags &= ~Defines.SVF_NOCLIENT; + self.use = null; + GameUtil.KillBox(self); + GameBase.gi.linkentity(self); + } + }; + + /* + * QUAKED misc_explobox (0 .5 .8) (-16 -16 0) (16 16 40) Large exploding + * box. You can override its mass (100), health (80), and dmg (150). + */ + + public static EntTouchAdapter barrel_touch = new EntTouchAdapter() { + + public void touch(edict_t self, edict_t other, cplane_t plane, + csurface_t surf) { + float ratio; + float[] v = { 0, 0, 0 }; + + if ((null == other.groundentity) || (other.groundentity == self)) + return; + + ratio = (float) other.mass / (float) self.mass; + Math3D.VectorSubtract(self.s.origin, other.s.origin, v); + M.M_walkmove(self, Math3D.vectoyaw(v), 20 * ratio + * Defines.FRAMETIME); + } + }; + + public static EntThinkAdapter barrel_explode = new EntThinkAdapter() { + public boolean think(edict_t self) { + + float[] org = { 0, 0, 0 }; + float spd; + float[] save = { 0, 0, 0 }; + + GameUtil.T_RadiusDamage(self, self.activator, self.dmg, null, + self.dmg + 40, Defines.MOD_BARREL); + + Math3D.VectorCopy(self.s.origin, save); + Math3D.VectorMA(self.absmin, 0.5f, self.size, self.s.origin); + + // a few big chunks + spd = 1.5f * (float) self.dmg / 200.0f; + org[0] = self.s.origin[0] + Lib.crandom() * self.size[0]; + org[1] = self.s.origin[1] + Lib.crandom() * self.size[1]; + org[2] = self.s.origin[2] + Lib.crandom() * self.size[2]; + GameAI.ThrowDebris(self, "models/objects/debris1/tris.md2", spd, + org); + org[0] = self.s.origin[0] + Lib.crandom() * self.size[0]; + org[1] = self.s.origin[1] + Lib.crandom() * self.size[1]; + org[2] = self.s.origin[2] + Lib.crandom() * self.size[2]; + GameAI.ThrowDebris(self, "models/objects/debris1/tris.md2", spd, + org); + + // bottom corners + spd = 1.75f * (float) self.dmg / 200.0f; + Math3D.VectorCopy(self.absmin, org); + GameAI.ThrowDebris(self, "models/objects/debris3/tris.md2", spd, + org); + Math3D.VectorCopy(self.absmin, org); + org[0] += self.size[0]; + GameAI.ThrowDebris(self, "models/objects/debris3/tris.md2", spd, + org); + Math3D.VectorCopy(self.absmin, org); + org[1] += self.size[1]; + GameAI.ThrowDebris(self, "models/objects/debris3/tris.md2", spd, + org); + Math3D.VectorCopy(self.absmin, org); + org[0] += self.size[0]; + org[1] += self.size[1]; + GameAI.ThrowDebris(self, "models/objects/debris3/tris.md2", spd, + org); + + // a bunch of little chunks + spd = 2 * self.dmg / 200; + org[0] = self.s.origin[0] + Lib.crandom() * self.size[0]; + org[1] = self.s.origin[1] + Lib.crandom() * self.size[1]; + org[2] = self.s.origin[2] + Lib.crandom() * self.size[2]; + GameAI.ThrowDebris(self, "models/objects/debris2/tris.md2", spd, + org); + org[0] = self.s.origin[0] + Lib.crandom() * self.size[0]; + org[1] = self.s.origin[1] + Lib.crandom() * self.size[1]; + org[2] = self.s.origin[2] + Lib.crandom() * self.size[2]; + GameAI.ThrowDebris(self, "models/objects/debris2/tris.md2", spd, + org); + org[0] = self.s.origin[0] + Lib.crandom() * self.size[0]; + org[1] = self.s.origin[1] + Lib.crandom() * self.size[1]; + org[2] = self.s.origin[2] + Lib.crandom() * self.size[2]; + GameAI.ThrowDebris(self, "models/objects/debris2/tris.md2", spd, + org); + org[0] = self.s.origin[0] + Lib.crandom() * self.size[0]; + org[1] = self.s.origin[1] + Lib.crandom() * self.size[1]; + org[2] = self.s.origin[2] + Lib.crandom() * self.size[2]; + GameAI.ThrowDebris(self, "models/objects/debris2/tris.md2", spd, + org); + org[0] = self.s.origin[0] + Lib.crandom() * self.size[0]; + org[1] = self.s.origin[1] + Lib.crandom() * self.size[1]; + org[2] = self.s.origin[2] + Lib.crandom() * self.size[2]; + GameAI.ThrowDebris(self, "models/objects/debris2/tris.md2", spd, + org); + org[0] = self.s.origin[0] + Lib.crandom() * self.size[0]; + org[1] = self.s.origin[1] + Lib.crandom() * self.size[1]; + org[2] = self.s.origin[2] + Lib.crandom() * self.size[2]; + GameAI.ThrowDebris(self, "models/objects/debris2/tris.md2", spd, + org); + org[0] = self.s.origin[0] + Lib.crandom() * self.size[0]; + org[1] = self.s.origin[1] + Lib.crandom() * self.size[1]; + org[2] = self.s.origin[2] + Lib.crandom() * self.size[2]; + GameAI.ThrowDebris(self, "models/objects/debris2/tris.md2", spd, + org); + org[0] = self.s.origin[0] + Lib.crandom() * self.size[0]; + org[1] = self.s.origin[1] + Lib.crandom() * self.size[1]; + org[2] = self.s.origin[2] + Lib.crandom() * self.size[2]; + GameAI.ThrowDebris(self, "models/objects/debris2/tris.md2", spd, + org); + + Math3D.VectorCopy(save, self.s.origin); + if (self.groundentity != null) + GameAI.BecomeExplosion2(self); + else + GameAI.BecomeExplosion1(self); + + return true; + } + }; + + public static EntDieAdapter barrel_delay = new EntDieAdapter() { + public void die(edict_t self, edict_t inflictor, edict_t attacker, + int damage, float[] point) { + + self.takedamage = Defines.DAMAGE_NO; + self.nextthink = GameBase.level.time + 2 * Defines.FRAMETIME; + self.think = barrel_explode; + self.activator = attacker; + } + }; + + // + // miscellaneous specialty items + // + + /* + * QUAKED misc_blackhole (1 .5 0) (-8 -8 -8) (8 8 8) + */ + + static EntUseAdapter misc_blackhole_use = new EntUseAdapter() { + public void use(edict_t ent, edict_t other, edict_t activator) { + /* + * gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BOSSTPORT); + * gi.WritePosition (ent.s.origin); gi.multicast (ent.s.origin, + * MULTICAST_PVS); + */ + GameUtil.G_FreeEdict(ent); + } + }; + + static EntThinkAdapter misc_blackhole_think = new EntThinkAdapter() { + public boolean think(edict_t self) { + + if (++self.s.frame < 19) + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + else { + self.s.frame = 0; + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + } + return true; + } + }; + + /* + * QUAKED misc_eastertank (1 .5 0) (-32 -32 -16) (32 32 32) + */ + + static EntThinkAdapter misc_eastertank_think = new EntThinkAdapter() { + public boolean think(edict_t self) { + if (++self.s.frame < 293) + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + else { + self.s.frame = 254; + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + } + return true; + } + }; + + /* + * QUAKED misc_easterchick (1 .5 0) (-32 -32 0) (32 32 32) + */ + + static EntThinkAdapter misc_easterchick_think = new EntThinkAdapter() { + public boolean think(edict_t self) { + if (++self.s.frame < 247) + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + else { + self.s.frame = 208; + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + } + return true; + } + }; + + /* + * QUAKED misc_easterchick2 (1 .5 0) (-32 -32 0) (32 32 32) + */ + static EntThinkAdapter misc_easterchick2_think = new EntThinkAdapter() { + public boolean think(edict_t self) { + if (++self.s.frame < 287) + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + else { + self.s.frame = 248; + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + } + return true; + } + }; + + /* + * QUAKED monster_commander_body (1 .5 0) (-32 -32 0) (32 32 48) Not really + * a monster, this is the Tank Commander's decapitated body. There should be + * a item_commander_head that has this as it's target. + */ + + public static EntThinkAdapter commander_body_think = new EntThinkAdapter() { + public boolean think(edict_t self) { + if (++self.s.frame < 24) + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + else + self.nextthink = 0; + + if (self.s.frame == 22) + GameBase.gi.sound(self, Defines.CHAN_BODY, GameBase.gi + .soundindex("tank/thud.wav"), 1, Defines.ATTN_NORM, 0); + return true; + } + }; + + public static EntUseAdapter commander_body_use = new EntUseAdapter() { + + public void use(edict_t self, edict_t other, edict_t activator) { + self.think = commander_body_think; + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + GameBase.gi.sound(self, Defines.CHAN_BODY, GameBase.gi + .soundindex("tank/pain.wav"), 1, Defines.ATTN_NORM, 0); + } + }; + + public static EntThinkAdapter commander_body_drop = new EntThinkAdapter() { + public boolean think(edict_t self) { + self.movetype = Defines.MOVETYPE_TOSS; + self.s.origin[2] += 2; + return true; + } + }; + + /* + * QUAKED misc_banner (1 .5 0) (-4 -4 -4) (4 4 4) The origin is the bottom + * of the banner. The banner is 128 tall. + */ + static EntThinkAdapter misc_banner_think = new EntThinkAdapter() { + public boolean think(edict_t ent) { + ent.s.frame = (ent.s.frame + 1) % 16; + ent.nextthink = GameBase.level.time + Defines.FRAMETIME; + return true; + } + }; + + /* + * QUAKED misc_deadsoldier (1 .5 0) (-16 -16 0) (16 16 16) ON_BACK + * ON_STOMACH BACK_DECAP FETAL_POS SIT_DECAP IMPALED This is the dead player + * model. Comes in 6 exciting different poses! + */ + static EntDieAdapter misc_deadsoldier_die = new EntDieAdapter() { + + public void die(edict_t self, edict_t inflictor, edict_t attacker, + int damage, float[] point) { + int n; + + if (self.health > -80) + return; + + GameBase.gi.sound(self, Defines.CHAN_BODY, GameBase.gi + .soundindex("misc/udeath.wav"), 1, Defines.ATTN_NORM, 0); + for (n = 0; n < 4; n++) + GameAI.ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", + damage, Defines.GIB_ORGANIC); + GameAI.ThrowHead(self, "models/objects/gibs/head2/tris.md2", + damage, Defines.GIB_ORGANIC); + } + }; + + /* + * QUAKED misc_viper (1 .5 0) (-16 -16 0) (16 16 32) This is the Viper for + * the flyby bombing. It is trigger_spawned, so you must have something use + * it for it to show up. There must be a path for it to follow once it is + * activated. + * + * "speed" How fast the Viper should fly + */ + + static EntUseAdapter misc_viper_use = new EntUseAdapter() { + public void use(edict_t self, edict_t other, edict_t activator) { + self.svflags &= ~Defines.SVF_NOCLIENT; + self.use = GameFunc.train_use; + GameFunc.train_use.use(self, other, activator); + } + }; + + /* + * QUAKED misc_viper_bomb (1 0 0) (-8 -8 -8) (8 8 8) "dmg" how much boom + * should the bomb make? + */ + static EntTouchAdapter misc_viper_bomb_touch = new EntTouchAdapter() { + + public void touch(edict_t self, edict_t other, cplane_t plane, + csurface_t surf) { + GameUtil.G_UseTargets(self, self.activator); + + self.s.origin[2] = self.absmin[2] + 1; + GameUtil.T_RadiusDamage(self, self, self.dmg, null, self.dmg + 40, + Defines.MOD_BOMB); + GameAI.BecomeExplosion2(self); + } + }; + + static EntThinkAdapter misc_viper_bomb_prethink = new EntThinkAdapter() { + public boolean think(edict_t self) { + + float[] v = { 0, 0, 0 }; + float diff; + + self.groundentity = null; + + diff = self.timestamp - GameBase.level.time; + if (diff < -1.0) + diff = -1.0f; + + Math3D.VectorScale(self.moveinfo.dir, 1.0f + diff, v); + v[2] = diff; + + diff = self.s.angles[2]; + Math3D.vectoangles(v, self.s.angles); + self.s.angles[2] = diff + 10; + + return true; + } + }; + + static EntUseAdapter misc_viper_bomb_use = new EntUseAdapter() { + public void use(edict_t self, edict_t other, edict_t activator) { + edict_t viper = null; + + self.solid = Defines.SOLID_BBOX; + self.svflags &= ~Defines.SVF_NOCLIENT; + self.s.effects |= Defines.EF_ROCKET; + self.use = null; + self.movetype = Defines.MOVETYPE_TOSS; + self.prethink = misc_viper_bomb_prethink; + self.touch = misc_viper_bomb_touch; + self.activator = activator; + + EdictIterator es = null; + + es = GameBase.G_Find(es, GameBase.findByClass, "misc_viper"); + if (es != null) + viper = es.o; + + Math3D.VectorScale(viper.moveinfo.dir, viper.moveinfo.speed, + self.velocity); + + self.timestamp = GameBase.level.time; + Math3D.VectorCopy(viper.moveinfo.dir, self.moveinfo.dir); + } + }; + + /* + * QUAKED misc_strogg_ship (1 .5 0) (-16 -16 0) (16 16 32) This is a Storgg + * ship for the flybys. It is trigger_spawned, so you must have something + * use it for it to show up. There must be a path for it to follow once it + * is activated. + * + * "speed" How fast it should fly + */ + + static EntUseAdapter misc_strogg_ship_use = new EntUseAdapter() { + public void use(edict_t self, edict_t other, edict_t activator) { + self.svflags &= ~Defines.SVF_NOCLIENT; + self.use = GameFunc.train_use; + GameFunc.train_use.use(self, other, activator); + } + }; + + /* + * QUAKED misc_satellite_dish (1 .5 0) (-64 -64 0) (64 64 128) + */ + static EntThinkAdapter misc_satellite_dish_think = new EntThinkAdapter() { + public boolean think(edict_t self) { + self.s.frame++; + if (self.s.frame < 38) + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + return true; + } + }; + + static EntUseAdapter misc_satellite_dish_use = new EntUseAdapter() { + public void use(edict_t self, edict_t other, edict_t activator) { + self.s.frame = 0; + self.think = misc_satellite_dish_think; + self.nextthink = GameBase.level.time + Defines.FRAMETIME; + } + }; + + /* + * QUAKED target_string (0 0 1) (-8 -8 -8) (8 8 8) + */ + + static EntUseAdapter target_string_use = new EntUseAdapter() { + public void use(edict_t self, edict_t other, edict_t activator) { + edict_t e; + int n, l; + char c; + + l = self.message.length(); + for (e = self.teammaster; e != null; e = e.teamchain) { + if (e.count == 0) + continue; + n = e.count - 1; + if (n >= l) { + e.s.frame = 12; + continue; + } + + c = self.message.charAt(n); + if (c >= '0' && c <= '9') + e.s.frame = c - '0'; + else if (c == '-') + e.s.frame = 10; + else if (c == ':') + e.s.frame = 11; + else + e.s.frame = 12; + } + } + }; + + /* + * QUAKED func_clock (0 0 1) (-8 -8 -8) (8 8 8) TIMER_UP TIMER_DOWN + * START_OFF MULTI_USE target a target_string with this + * + * The default is to be a time of day clock + * + * TIMER_UP and TIMER_DOWN run for "count" seconds and the fire "pathtarget" + * If START_OFF, this entity must be used before it starts + * + * "style" 0 "xx" 1 "xx:xx" 2 "xx:xx:xx" + */ + + public static final int CLOCK_MESSAGE_SIZE = 16; + + public static EntThinkAdapter func_clock_think = new EntThinkAdapter() { + + public boolean think(edict_t self) { + if (null == self.enemy) { + + EdictIterator es = null; + + es = GameBase.G_Find(es, GameBase.findByTarget, self.target); + if (es != null) + self.enemy = es.o; + if (self.enemy == null) + return true; + } + + if ((self.spawnflags & 1) != 0) { + func_clock_format_countdown(self); + self.health++; + } else if ((self.spawnflags & 2) != 0) { + func_clock_format_countdown(self); + self.health--; + } else { + Calendar c = Calendar.getInstance(); + self.message = "" + c.get(Calendar.HOUR_OF_DAY) + ":" + + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND); + + /* + * struct tm * ltime; time_t gmtime; + * + * time(& gmtime); ltime = localtime(& gmtime); + * Com_sprintf(self.message, CLOCK_MESSAGE_SIZE, "%2i:%2i:%2i", + * ltime.tm_hour, ltime.tm_min, ltime.tm_sec); if + * (self.message[3] == ' ') self.message[3] = '0'; if + * (self.message[6] == ' ') self.message[6] = '0'; + */ + } + + self.enemy.message = self.message; + self.enemy.use.use(self.enemy, self, self); + + if (((self.spawnflags & 1) != 0 && (self.health > self.wait)) + || ((self.spawnflags & 2) != 0 && (self.health < self.wait))) { + if (self.pathtarget != null) { + String savetarget; + String savemessage; + + savetarget = self.target; + savemessage = self.message; + self.target = self.pathtarget; + self.message = null; + GameUtil.G_UseTargets(self, self.activator); + self.target = savetarget; + self.message = savemessage; + } + + if (0 == (self.spawnflags & 8)) + return true; + + func_clock_reset(self); + + if ((self.spawnflags & 4) != 0) + return true; + } + + self.nextthink = GameBase.level.time + 1; + return true; + + } + }; + + public static EntUseAdapter func_clock_use = new EntUseAdapter() { + + public void use(edict_t self, edict_t other, edict_t activator) { + if (0 == (self.spawnflags & 8)) + self.use = null; + if (self.activator != null) + return; + self.activator = activator; + self.think.think(self); + } + }; + + //================================================================================= + + static EntTouchAdapter teleporter_touch = new EntTouchAdapter() { + public void touch(edict_t self, edict_t other, cplane_t plane, + csurface_t surf) { + edict_t dest; + int i; + + if (other.client == null) + return; + + EdictIterator es = null; + dest = GameBase.G_Find(null, GameBase.findByTarget, self.target).o; + + if (dest == null) { + GameBase.gi.dprintf("Couldn't find destination\n"); + return; + } + + // unlink to make sure it can't possibly interfere with KillBox + GameBase.gi.unlinkentity(other); + + Math3D.VectorCopy(dest.s.origin, other.s.origin); + Math3D.VectorCopy(dest.s.origin, other.s.old_origin); + other.s.origin[2] += 10; + + // clear the velocity and hold them in place briefly + Math3D.VectorClear(other.velocity); + other.client.ps.pmove.pm_time = 160 >> 3; // hold time + other.client.ps.pmove.pm_flags |= pmove_t.PMF_TIME_TELEPORT; + + // draw the teleport splash at source and on the player + self.owner.s.event = Defines.EV_PLAYER_TELEPORT; + other.s.event = Defines.EV_PLAYER_TELEPORT; + + // set angles + for (i = 0; i < 3; i++) { + other.client.ps.pmove.delta_angles[i] = (short) Math3D + .ANGLE2SHORT(dest.s.angles[i] + - other.client.resp.cmd_angles[i]); + } + + Math3D.VectorClear(other.s.angles); + Math3D.VectorClear(other.client.ps.viewangles); + Math3D.VectorClear(other.client.v_angle); + + // kill anything at the destination + GameUtil.KillBox(other); + + GameBase.gi.linkentity(other); + } + }; + + /* + * QUAKED misc_teleporter_dest (1 0 0) (-32 -32 -24) (32 32 -16) Point + * teleporters at these. + */ + + public static EntThinkAdapter SP_misc_teleporter_dest = new EntThinkAdapter() { + public boolean think(edict_t ent) { + GameBase.gi.setmodel(ent, "models/objects/dmspot/tris.md2"); + ent.s.skinnum = 0; + ent.solid = Defines.SOLID_BBOX; + // ent.s.effects |= EF_FLIES; + Math3D.VectorSet(ent.mins, -32, -32, -24); + Math3D.VectorSet(ent.maxs, 32, 32, -16); + GameBase.gi.linkentity(ent); + return true; + } + }; +}
\ No newline at end of file |