From e8bd66b89c8d4d131b76b0137e454ae515c69c24 Mon Sep 17 00:00:00 2001 From: Literally A Penguin Date: Wed, 25 Sep 2024 15:38:23 -0500 Subject: [PATCH] Quack 2 --- game/g_save.c | 769 +++++++++ game/g_spawn.c | 984 +++++++++++ game/g_svcmds.c | 300 ++++ game/g_target.c | 809 +++++++++ game/g_trigger.c | 598 +++++++ game/g_turret.c | 432 +++++ game/g_utils.c | 568 ++++++ game/g_weapon.c | 916 ++++++++++ game/game.001 | 1619 ++++++++++++++++++ game/game.def | 2 + game/game.dsp | 1618 ++++++++++++++++++ game/game.h | 254 +++ game/game.plg | 75 + game/m_actor.c | 609 +++++++ game/m_actor.h | 506 ++++++ game/m_berserk.c | 457 +++++ game/m_berserk.h | 269 +++ game/m_boss2.c | 679 ++++++++ game/m_boss2.h | 206 +++ game/m_boss3.c | 76 + game/m_boss31.c | 749 ++++++++ game/m_boss31.h | 213 +++ game/m_boss32.c | 913 ++++++++++ game/m_boss32.h | 516 ++++++ game/m_brain.c | 676 ++++++++ game/m_brain.h | 247 +++ game/m_chick.c | 677 ++++++++ game/m_chick.h | 313 ++++ game/m_flash.c | 488 ++++++ game/m_flipper.c | 403 +++++ game/m_flipper.h | 185 ++ game/m_float.c | 663 +++++++ game/m_float.h | 273 +++ game/m_flyer.c | 626 +++++++ game/m_flyer.h | 182 ++ game/m_gladiator.c | 387 +++++ game/m_gladiator.h | 115 ++ game/m_gunner.c | 628 +++++++ game/m_gunner.h | 234 +++ game/m_hover.c | 620 +++++++ game/m_hover.h | 230 +++ game/m_infantry.c | 607 +++++++ game/m_infantry.h | 232 +++ game/m_insane.c | 693 ++++++++ game/m_insane.h | 307 ++++ game/m_medic.c | 769 +++++++++ game/m_medic.h | 262 +++ game/m_move.c | 556 ++++++ game/m_mutant.c | 663 +++++++ game/m_mutant.h | 174 ++ game/m_parasite.c | 552 ++++++ game/m_parasite.h | 143 ++ game/m_player.h | 224 +++ game/m_rider.h | 66 + game/m_soldier.c | 1299 ++++++++++++++ game/m_soldier.h | 500 ++++++ game/m_supertank.c | 717 ++++++++ game/m_supertank.h | 279 +++ game/m_tank.c | 856 +++++++++ game/m_tank.h | 319 ++++ game/p_client.c | 1805 +++++++++++++++++++ game/p_hud.c | 571 +++++++ game/p_trail.c | 146 ++ game/p_view.c | 1087 ++++++++++++ game/p_weapon.c | 1434 ++++++++++++++++ game/q_shared.c | 1418 +++++++++++++++ game/q_shared.h | 1200 +++++++++++++ irix/cd_irix.c | 40 + irix/glw_imp.c | 927 ++++++++++ irix/q_shirix.c | 200 +++ irix/qgl_irix.c | 3997 +++++++++++++++++++++++++++++++++++++++++++ irix/snd_irix.c | 222 +++ irix/sys_irix.c | 383 +++++ irix/vid_menu.c | 426 +++++ irix/vid_so.c | 492 ++++++ linux/Makefile.AXP | 716 ++++++++ linux/Makefile.i386 | 1085 ++++++++++++ linux/block16.h | 123 ++ linux/block8.h | 124 ++ linux/cd_linux.c | 420 +++++ linux/d_copy.s | 147 ++ linux/d_ifacea.h | 79 + linux/d_polysa.s | 1250 ++++++++++++++ linux/gl_fxmesa.c | 206 +++ linux/glob.c | 164 ++ linux/glob.h | 1 + linux/in_linux.c | 29 + linux/math.s | 403 +++++ linux/net_udp.c | 537 ++++++ 89 files changed, 49934 insertions(+) create mode 100644 game/g_save.c create mode 100644 game/g_spawn.c create mode 100644 game/g_svcmds.c create mode 100644 game/g_target.c create mode 100644 game/g_trigger.c create mode 100644 game/g_turret.c create mode 100644 game/g_utils.c create mode 100644 game/g_weapon.c create mode 100644 game/game.001 create mode 100644 game/game.def create mode 100644 game/game.dsp create mode 100644 game/game.h create mode 100644 game/game.plg create mode 100644 game/m_actor.c create mode 100644 game/m_actor.h create mode 100644 game/m_berserk.c create mode 100644 game/m_berserk.h create mode 100644 game/m_boss2.c create mode 100644 game/m_boss2.h create mode 100644 game/m_boss3.c create mode 100644 game/m_boss31.c create mode 100644 game/m_boss31.h create mode 100644 game/m_boss32.c create mode 100644 game/m_boss32.h create mode 100644 game/m_brain.c create mode 100644 game/m_brain.h create mode 100644 game/m_chick.c create mode 100644 game/m_chick.h create mode 100644 game/m_flash.c create mode 100644 game/m_flipper.c create mode 100644 game/m_flipper.h create mode 100644 game/m_float.c create mode 100644 game/m_float.h create mode 100644 game/m_flyer.c create mode 100644 game/m_flyer.h create mode 100644 game/m_gladiator.c create mode 100644 game/m_gladiator.h create mode 100644 game/m_gunner.c create mode 100644 game/m_gunner.h create mode 100644 game/m_hover.c create mode 100644 game/m_hover.h create mode 100644 game/m_infantry.c create mode 100644 game/m_infantry.h create mode 100644 game/m_insane.c create mode 100644 game/m_insane.h create mode 100644 game/m_medic.c create mode 100644 game/m_medic.h create mode 100644 game/m_move.c create mode 100644 game/m_mutant.c create mode 100644 game/m_mutant.h create mode 100644 game/m_parasite.c create mode 100644 game/m_parasite.h create mode 100644 game/m_player.h create mode 100644 game/m_rider.h create mode 100644 game/m_soldier.c create mode 100644 game/m_soldier.h create mode 100644 game/m_supertank.c create mode 100644 game/m_supertank.h create mode 100644 game/m_tank.c create mode 100644 game/m_tank.h create mode 100644 game/p_client.c create mode 100644 game/p_hud.c create mode 100644 game/p_trail.c create mode 100644 game/p_view.c create mode 100644 game/p_weapon.c create mode 100644 game/q_shared.c create mode 100644 game/q_shared.h create mode 100644 irix/cd_irix.c create mode 100644 irix/glw_imp.c create mode 100644 irix/q_shirix.c create mode 100644 irix/qgl_irix.c create mode 100644 irix/snd_irix.c create mode 100644 irix/sys_irix.c create mode 100644 irix/vid_menu.c create mode 100644 irix/vid_so.c create mode 100644 linux/Makefile.AXP create mode 100644 linux/Makefile.i386 create mode 100644 linux/block16.h create mode 100644 linux/block8.h create mode 100644 linux/cd_linux.c create mode 100644 linux/d_copy.s create mode 100644 linux/d_ifacea.h create mode 100644 linux/d_polysa.s create mode 100644 linux/gl_fxmesa.c create mode 100644 linux/glob.c create mode 100644 linux/glob.h create mode 100644 linux/in_linux.c create mode 100644 linux/math.s create mode 100644 linux/net_udp.c diff --git a/game/g_save.c b/game/g_save.c new file mode 100644 index 000000000..1153f511a --- /dev/null +++ b/game/g_save.c @@ -0,0 +1,769 @@ +/* +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. + +*/ + +#include "g_local.h" + +#define Function(f) {#f, f} + +mmove_t mmove_reloc; + +field_t fields[] = { + {"classname", FOFS(classname), F_LSTRING}, + {"model", FOFS(model), F_LSTRING}, + {"spawnflags", FOFS(spawnflags), F_INT}, + {"speed", FOFS(speed), F_FLOAT}, + {"accel", FOFS(accel), F_FLOAT}, + {"decel", FOFS(decel), F_FLOAT}, + {"target", FOFS(target), F_LSTRING}, + {"targetname", FOFS(targetname), F_LSTRING}, + {"pathtarget", FOFS(pathtarget), F_LSTRING}, + {"deathtarget", FOFS(deathtarget), F_LSTRING}, + {"killtarget", FOFS(killtarget), F_LSTRING}, + {"combattarget", FOFS(combattarget), F_LSTRING}, + {"message", FOFS(message), F_LSTRING}, + {"team", FOFS(team), F_LSTRING}, + {"wait", FOFS(wait), F_FLOAT}, + {"delay", FOFS(delay), F_FLOAT}, + {"random", FOFS(random), F_FLOAT}, + {"move_origin", FOFS(move_origin), F_VECTOR}, + {"move_angles", FOFS(move_angles), F_VECTOR}, + {"style", FOFS(style), F_INT}, + {"count", FOFS(count), F_INT}, + {"health", FOFS(health), F_INT}, + {"sounds", FOFS(sounds), F_INT}, + {"light", 0, F_IGNORE}, + {"dmg", FOFS(dmg), F_INT}, + {"mass", FOFS(mass), F_INT}, + {"volume", FOFS(volume), F_FLOAT}, + {"attenuation", FOFS(attenuation), F_FLOAT}, + {"map", FOFS(map), F_LSTRING}, + {"origin", FOFS(s.origin), F_VECTOR}, + {"angles", FOFS(s.angles), F_VECTOR}, + {"angle", FOFS(s.angles), F_ANGLEHACK}, + + {"goalentity", FOFS(goalentity), F_EDICT, FFL_NOSPAWN}, + {"movetarget", FOFS(movetarget), F_EDICT, FFL_NOSPAWN}, + {"enemy", FOFS(enemy), F_EDICT, FFL_NOSPAWN}, + {"oldenemy", FOFS(oldenemy), F_EDICT, FFL_NOSPAWN}, + {"activator", FOFS(activator), F_EDICT, FFL_NOSPAWN}, + {"groundentity", FOFS(groundentity), F_EDICT, FFL_NOSPAWN}, + {"teamchain", FOFS(teamchain), F_EDICT, FFL_NOSPAWN}, + {"teammaster", FOFS(teammaster), F_EDICT, FFL_NOSPAWN}, + {"owner", FOFS(owner), F_EDICT, FFL_NOSPAWN}, + {"mynoise", FOFS(mynoise), F_EDICT, FFL_NOSPAWN}, + {"mynoise2", FOFS(mynoise2), F_EDICT, FFL_NOSPAWN}, + {"target_ent", FOFS(target_ent), F_EDICT, FFL_NOSPAWN}, + {"chain", FOFS(chain), F_EDICT, FFL_NOSPAWN}, + + {"prethink", FOFS(prethink), F_FUNCTION, FFL_NOSPAWN}, + {"think", FOFS(think), F_FUNCTION, FFL_NOSPAWN}, + {"blocked", FOFS(blocked), F_FUNCTION, FFL_NOSPAWN}, + {"touch", FOFS(touch), F_FUNCTION, FFL_NOSPAWN}, + {"use", FOFS(use), F_FUNCTION, FFL_NOSPAWN}, + {"pain", FOFS(pain), F_FUNCTION, FFL_NOSPAWN}, + {"die", FOFS(die), F_FUNCTION, FFL_NOSPAWN}, + + {"stand", FOFS(monsterinfo.stand), F_FUNCTION, FFL_NOSPAWN}, + {"idle", FOFS(monsterinfo.idle), F_FUNCTION, FFL_NOSPAWN}, + {"search", FOFS(monsterinfo.search), F_FUNCTION, FFL_NOSPAWN}, + {"walk", FOFS(monsterinfo.walk), F_FUNCTION, FFL_NOSPAWN}, + {"run", FOFS(monsterinfo.run), F_FUNCTION, FFL_NOSPAWN}, + {"dodge", FOFS(monsterinfo.dodge), F_FUNCTION, FFL_NOSPAWN}, + {"attack", FOFS(monsterinfo.attack), F_FUNCTION, FFL_NOSPAWN}, + {"melee", FOFS(monsterinfo.melee), F_FUNCTION, FFL_NOSPAWN}, + {"sight", FOFS(monsterinfo.sight), F_FUNCTION, FFL_NOSPAWN}, + {"checkattack", FOFS(monsterinfo.checkattack), F_FUNCTION, FFL_NOSPAWN}, + {"currentmove", FOFS(monsterinfo.currentmove), F_MMOVE, FFL_NOSPAWN}, + + {"endfunc", FOFS(moveinfo.endfunc), F_FUNCTION, FFL_NOSPAWN}, + + // temp spawn vars -- only valid when the spawn function is called + {"lip", STOFS(lip), F_INT, FFL_SPAWNTEMP}, + {"distance", STOFS(distance), F_INT, FFL_SPAWNTEMP}, + {"height", STOFS(height), F_INT, FFL_SPAWNTEMP}, + {"noise", STOFS(noise), F_LSTRING, FFL_SPAWNTEMP}, + {"pausetime", STOFS(pausetime), F_FLOAT, FFL_SPAWNTEMP}, + {"item", STOFS(item), F_LSTRING, FFL_SPAWNTEMP}, + +//need for item field in edict struct, FFL_SPAWNTEMP item will be skipped on saves + {"item", FOFS(item), F_ITEM}, + + {"gravity", STOFS(gravity), F_LSTRING, FFL_SPAWNTEMP}, + {"sky", STOFS(sky), F_LSTRING, FFL_SPAWNTEMP}, + {"skyrotate", STOFS(skyrotate), F_FLOAT, FFL_SPAWNTEMP}, + {"skyaxis", STOFS(skyaxis), F_VECTOR, FFL_SPAWNTEMP}, + {"minyaw", STOFS(minyaw), F_FLOAT, FFL_SPAWNTEMP}, + {"maxyaw", STOFS(maxyaw), F_FLOAT, FFL_SPAWNTEMP}, + {"minpitch", STOFS(minpitch), F_FLOAT, FFL_SPAWNTEMP}, + {"maxpitch", STOFS(maxpitch), F_FLOAT, FFL_SPAWNTEMP}, + {"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP}, + + {0, 0, 0, 0} + +}; + +field_t levelfields[] = +{ + {"changemap", LLOFS(changemap), F_LSTRING}, + + {"sight_client", LLOFS(sight_client), F_EDICT}, + {"sight_entity", LLOFS(sight_entity), F_EDICT}, + {"sound_entity", LLOFS(sound_entity), F_EDICT}, + {"sound2_entity", LLOFS(sound2_entity), F_EDICT}, + + {NULL, 0, F_INT} +}; + +field_t clientfields[] = +{ + {"pers.weapon", CLOFS(pers.weapon), F_ITEM}, + {"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM}, + {"newweapon", CLOFS(newweapon), F_ITEM}, + + {NULL, 0, F_INT} +}; + +/* +============ +InitGame + +This will be called when the dll is first loaded, which +only happens when a new game is started or a save game +is loaded. +============ +*/ +void InitGame (void) +{ + gi.dprintf ("==== InitGame ====\n"); + + gun_x = gi.cvar ("gun_x", "0", 0); + gun_y = gi.cvar ("gun_y", "0", 0); + gun_z = gi.cvar ("gun_z", "0", 0); + + //FIXME: sv_ prefix is wrong for these + sv_rollspeed = gi.cvar ("sv_rollspeed", "200", 0); + sv_rollangle = gi.cvar ("sv_rollangle", "2", 0); + sv_maxvelocity = gi.cvar ("sv_maxvelocity", "2000", 0); + sv_gravity = gi.cvar ("sv_gravity", "800", 0); + + // noset vars + dedicated = gi.cvar ("dedicated", "0", CVAR_NOSET); + + // latched vars + sv_cheats = gi.cvar ("cheats", "0", CVAR_SERVERINFO|CVAR_LATCH); + gi.cvar ("gamename", GAMEVERSION , CVAR_SERVERINFO | CVAR_LATCH); + gi.cvar ("gamedate", __DATE__ , CVAR_SERVERINFO | CVAR_LATCH); + + maxclients = gi.cvar ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH); + maxspectators = gi.cvar ("maxspectators", "4", CVAR_SERVERINFO); + deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH); + coop = gi.cvar ("coop", "0", CVAR_LATCH); + skill = gi.cvar ("skill", "1", CVAR_LATCH); + maxentities = gi.cvar ("maxentities", "1024", CVAR_LATCH); + + // change anytime vars + dmflags = gi.cvar ("dmflags", "0", CVAR_SERVERINFO); + fraglimit = gi.cvar ("fraglimit", "0", CVAR_SERVERINFO); + timelimit = gi.cvar ("timelimit", "0", CVAR_SERVERINFO); + password = gi.cvar ("password", "", CVAR_USERINFO); + spectator_password = gi.cvar ("spectator_password", "", CVAR_USERINFO); + filterban = gi.cvar ("filterban", "1", 0); + + g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE); + + run_pitch = gi.cvar ("run_pitch", "0.002", 0); + run_roll = gi.cvar ("run_roll", "0.005", 0); + bob_up = gi.cvar ("bob_up", "0.005", 0); + bob_pitch = gi.cvar ("bob_pitch", "0.002", 0); + bob_roll = gi.cvar ("bob_roll", "0.002", 0); + + // flood control + flood_msgs = gi.cvar ("flood_msgs", "4", 0); + flood_persecond = gi.cvar ("flood_persecond", "4", 0); + flood_waitdelay = gi.cvar ("flood_waitdelay", "10", 0); + + // dm map list + sv_maplist = gi.cvar ("sv_maplist", "", 0); + + // items + InitItems (); + + Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), ""); + + Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), ""); + + // initialize all entities for this game + game.maxentities = maxentities->value; + g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME); + globals.edicts = g_edicts; + globals.max_edicts = game.maxentities; + + // initialize all clients for this game + game.maxclients = maxclients->value; + game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME); + globals.num_edicts = game.maxclients+1; +} + +//========================================================= + +void WriteField1 (FILE *f, field_t *field, byte *base) +{ + void *p; + int len; + int index; + + if (field->flags & FFL_SPAWNTEMP) + return; + + p = (void *)(base + field->ofs); + switch (field->type) + { + case F_INT: + case F_FLOAT: + case F_ANGLEHACK: + case F_VECTOR: + case F_IGNORE: + break; + + case F_LSTRING: + case F_GSTRING: + if ( *(char **)p ) + len = strlen(*(char **)p) + 1; + else + len = 0; + *(int *)p = len; + break; + case F_EDICT: + if ( *(edict_t **)p == NULL) + index = -1; + else + index = *(edict_t **)p - g_edicts; + *(int *)p = index; + break; + case F_CLIENT: + if ( *(gclient_t **)p == NULL) + index = -1; + else + index = *(gclient_t **)p - game.clients; + *(int *)p = index; + break; + case F_ITEM: + if ( *(edict_t **)p == NULL) + index = -1; + else + index = *(gitem_t **)p - itemlist; + *(int *)p = index; + break; + + //relative to code segment + case F_FUNCTION: + if (*(byte **)p == NULL) + index = 0; + else + index = *(byte **)p - ((byte *)InitGame); + *(int *)p = index; + break; + + //relative to data segment + case F_MMOVE: + if (*(byte **)p == NULL) + index = 0; + else + index = *(byte **)p - (byte *)&mmove_reloc; + *(int *)p = index; + break; + + default: + gi.error ("WriteEdict: unknown field type"); + } +} + + +void WriteField2 (FILE *f, field_t *field, byte *base) +{ + int len; + void *p; + + if (field->flags & FFL_SPAWNTEMP) + return; + + p = (void *)(base + field->ofs); + switch (field->type) + { + case F_LSTRING: + if ( *(char **)p ) + { + len = strlen(*(char **)p) + 1; + fwrite (*(char **)p, len, 1, f); + } + break; + } +} + +void ReadField (FILE *f, field_t *field, byte *base) +{ + void *p; + int len; + int index; + + if (field->flags & FFL_SPAWNTEMP) + return; + + p = (void *)(base + field->ofs); + switch (field->type) + { + case F_INT: + case F_FLOAT: + case F_ANGLEHACK: + case F_VECTOR: + case F_IGNORE: + break; + + case F_LSTRING: + len = *(int *)p; + if (!len) + *(char **)p = NULL; + else + { + *(char **)p = gi.TagMalloc (len, TAG_LEVEL); + fread (*(char **)p, len, 1, f); + } + break; + case F_EDICT: + index = *(int *)p; + if ( index == -1 ) + *(edict_t **)p = NULL; + else + *(edict_t **)p = &g_edicts[index]; + break; + case F_CLIENT: + index = *(int *)p; + if ( index == -1 ) + *(gclient_t **)p = NULL; + else + *(gclient_t **)p = &game.clients[index]; + break; + case F_ITEM: + index = *(int *)p; + if ( index == -1 ) + *(gitem_t **)p = NULL; + else + *(gitem_t **)p = &itemlist[index]; + break; + + //relative to code segment + case F_FUNCTION: + index = *(int *)p; + if ( index == 0 ) + *(byte **)p = NULL; + else + *(byte **)p = ((byte *)InitGame) + index; + break; + + //relative to data segment + case F_MMOVE: + index = *(int *)p; + if (index == 0) + *(byte **)p = NULL; + else + *(byte **)p = (byte *)&mmove_reloc + index; + break; + + default: + gi.error ("ReadEdict: unknown field type"); + } +} + +//========================================================= + +/* +============== +WriteClient + +All pointer variables (except function pointers) must be handled specially. +============== +*/ +void WriteClient (FILE *f, gclient_t *client) +{ + field_t *field; + gclient_t temp; + + // all of the ints, floats, and vectors stay as they are + temp = *client; + + // change the pointers to lengths or indexes + for (field=clientfields ; field->name ; field++) + { + WriteField1 (f, field, (byte *)&temp); + } + + // write the block + fwrite (&temp, sizeof(temp), 1, f); + + // now write any allocated data following the edict + for (field=clientfields ; field->name ; field++) + { + WriteField2 (f, field, (byte *)client); + } +} + +/* +============== +ReadClient + +All pointer variables (except function pointers) must be handled specially. +============== +*/ +void ReadClient (FILE *f, gclient_t *client) +{ + field_t *field; + + fread (client, sizeof(*client), 1, f); + + for (field=clientfields ; field->name ; field++) + { + ReadField (f, field, (byte *)client); + } +} + +/* +============ +WriteGame + +This will be called whenever the game goes to a new level, +and when the user explicitly saves the game. + +Game information include cross level data, like multi level +triggers, help computer info, and all client states. + +A single player death will automatically restore from the +last save position. +============ +*/ +void WriteGame (char *filename, qboolean autosave) +{ + FILE *f; + int i; + char str[16]; + + if (!autosave) + SaveClientData (); + + f = fopen (filename, "wb"); + if (!f) + gi.error ("Couldn't open %s", filename); + + memset (str, 0, sizeof(str)); + strcpy (str, __DATE__); + fwrite (str, sizeof(str), 1, f); + + game.autosaved = autosave; + fwrite (&game, sizeof(game), 1, f); + game.autosaved = false; + + for (i=0 ; iname ; field++) + { + WriteField1 (f, field, (byte *)&temp); + } + + // write the block + fwrite (&temp, sizeof(temp), 1, f); + + // now write any allocated data following the edict + for (field=fields ; field->name ; field++) + { + WriteField2 (f, field, (byte *)ent); + } + +} + +/* +============== +WriteLevelLocals + +All pointer variables (except function pointers) must be handled specially. +============== +*/ +void WriteLevelLocals (FILE *f) +{ + field_t *field; + level_locals_t temp; + + // all of the ints, floats, and vectors stay as they are + temp = level; + + // change the pointers to lengths or indexes + for (field=levelfields ; field->name ; field++) + { + WriteField1 (f, field, (byte *)&temp); + } + + // write the block + fwrite (&temp, sizeof(temp), 1, f); + + // now write any allocated data following the edict + for (field=levelfields ; field->name ; field++) + { + WriteField2 (f, field, (byte *)&level); + } +} + + +/* +============== +ReadEdict + +All pointer variables (except function pointers) must be handled specially. +============== +*/ +void ReadEdict (FILE *f, edict_t *ent) +{ + field_t *field; + + fread (ent, sizeof(*ent), 1, f); + + for (field=fields ; field->name ; field++) + { + ReadField (f, field, (byte *)ent); + } +} + +/* +============== +ReadLevelLocals + +All pointer variables (except function pointers) must be handled specially. +============== +*/ +void ReadLevelLocals (FILE *f) +{ + field_t *field; + + fread (&level, sizeof(level), 1, f); + + for (field=levelfields ; field->name ; field++) + { + ReadField (f, field, (byte *)&level); + } +} + +/* +================= +WriteLevel + +================= +*/ +void WriteLevel (char *filename) +{ + int i; + edict_t *ent; + FILE *f; + void *base; + + f = fopen (filename, "wb"); + if (!f) + gi.error ("Couldn't open %s", filename); + + // write out edict size for checking + i = sizeof(edict_t); + fwrite (&i, sizeof(i), 1, f); + + // write out a function pointer for checking + base = (void *)InitGame; + fwrite (&base, sizeof(base), 1, f); + + // write out level_locals_t + WriteLevelLocals (f); + + // write out all the entities + for (i=0 ; iinuse) + continue; + fwrite (&i, sizeof(i), 1, f); + WriteEdict (f, ent); + } + i = -1; + fwrite (&i, sizeof(i), 1, f); + + fclose (f); +} + + +/* +================= +ReadLevel + +SpawnEntities will allready have been called on the +level the same way it was when the level was saved. + +That is necessary to get the baselines +set up identically. + +The server will have cleared all of the world links before +calling ReadLevel. + +No clients are connected yet. +================= +*/ +void ReadLevel (char *filename) +{ + int entnum; + FILE *f; + int i; + void *base; + edict_t *ent; + + f = fopen (filename, "rb"); + if (!f) + gi.error ("Couldn't open %s", filename); + + // free any dynamic memory allocated by loading the level + // base state + gi.FreeTags (TAG_LEVEL); + + // wipe all the entities + memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0])); + globals.num_edicts = maxclients->value+1; + + // check edict size + fread (&i, sizeof(i), 1, f); + if (i != sizeof(edict_t)) + { + fclose (f); + gi.error ("ReadLevel: mismatched edict size"); + } + + // check function pointer base address + fread (&base, sizeof(base), 1, f); +#ifdef _WIN32 + if (base != (void *)InitGame) + { + fclose (f); + gi.error ("ReadLevel: function pointers have moved"); + } +#else + gi.dprintf("Function offsets %d\n", ((byte *)base) - ((byte *)InitGame)); +#endif + + // load the level locals + ReadLevelLocals (f); + + // load all the entities + while (1) + { + if (fread (&entnum, sizeof(entnum), 1, f) != 1) + { + fclose (f); + gi.error ("ReadLevel: failed to read entnum"); + } + if (entnum == -1) + break; + if (entnum >= globals.num_edicts) + globals.num_edicts = entnum+1; + + ent = &g_edicts[entnum]; + ReadEdict (f, ent); + + // let the server rebuild world links for this ent + memset (&ent->area, 0, sizeof(ent->area)); + gi.linkentity (ent); + } + + fclose (f); + + // mark all clients as unconnected + for (i=0 ; ivalue ; i++) + { + ent = &g_edicts[i+1]; + ent->client = game.clients + i; + ent->client->pers.connected = false; + } + + // do any load time things at this point + for (i=0 ; iinuse) + continue; + + // fire any cross-level triggers + if (ent->classname) + if (strcmp(ent->classname, "target_crosslevel_target") == 0) + ent->nextthink = level.time + ent->delay; + } +} diff --git a/game/g_spawn.c b/game/g_spawn.c new file mode 100644 index 000000000..c6084e9e7 --- /dev/null +++ b/game/g_spawn.c @@ -0,0 +1,984 @@ +/* +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. + +*/ + +#include "g_local.h" + +typedef struct +{ + char *name; + void (*spawn)(edict_t *ent); +} spawn_t; + + +void SP_item_health (edict_t *self); +void SP_item_health_small (edict_t *self); +void SP_item_health_large (edict_t *self); +void SP_item_health_mega (edict_t *self); + +void SP_info_player_start (edict_t *ent); +void SP_info_player_deathmatch (edict_t *ent); +void SP_info_player_coop (edict_t *ent); +void SP_info_player_intermission (edict_t *ent); + +void SP_func_plat (edict_t *ent); +void SP_func_rotating (edict_t *ent); +void SP_func_button (edict_t *ent); +void SP_func_door (edict_t *ent); +void SP_func_door_secret (edict_t *ent); +void SP_func_door_rotating (edict_t *ent); +void SP_func_water (edict_t *ent); +void SP_func_train (edict_t *ent); +void SP_func_conveyor (edict_t *self); +void SP_func_wall (edict_t *self); +void SP_func_object (edict_t *self); +void SP_func_explosive (edict_t *self); +void SP_func_timer (edict_t *self); +void SP_func_areaportal (edict_t *ent); +void SP_func_clock (edict_t *ent); +void SP_func_killbox (edict_t *ent); + +void SP_trigger_always (edict_t *ent); +void SP_trigger_once (edict_t *ent); +void SP_trigger_multiple (edict_t *ent); +void SP_trigger_relay (edict_t *ent); +void SP_trigger_push (edict_t *ent); +void SP_trigger_hurt (edict_t *ent); +void SP_trigger_key (edict_t *ent); +void SP_trigger_counter (edict_t *ent); +void SP_trigger_elevator (edict_t *ent); +void SP_trigger_gravity (edict_t *ent); +void SP_trigger_monsterjump (edict_t *ent); + +void SP_target_temp_entity (edict_t *ent); +void SP_target_speaker (edict_t *ent); +void SP_target_explosion (edict_t *ent); +void SP_target_changelevel (edict_t *ent); +void SP_target_secret (edict_t *ent); +void SP_target_goal (edict_t *ent); +void SP_target_splash (edict_t *ent); +void SP_target_spawner (edict_t *ent); +void SP_target_blaster (edict_t *ent); +void SP_target_crosslevel_trigger (edict_t *ent); +void SP_target_crosslevel_target (edict_t *ent); +void SP_target_laser (edict_t *self); +void SP_target_help (edict_t *ent); +void SP_target_actor (edict_t *ent); +void SP_target_lightramp (edict_t *self); +void SP_target_earthquake (edict_t *ent); +void SP_target_character (edict_t *ent); +void SP_target_string (edict_t *ent); + +void SP_worldspawn (edict_t *ent); +void SP_viewthing (edict_t *ent); + +void SP_light (edict_t *self); +void SP_light_mine1 (edict_t *ent); +void SP_light_mine2 (edict_t *ent); +void SP_info_null (edict_t *self); +void SP_info_notnull (edict_t *self); +void SP_path_corner (edict_t *self); +void SP_point_combat (edict_t *self); + +void SP_misc_explobox (edict_t *self); +void SP_misc_banner (edict_t *self); +void SP_misc_satellite_dish (edict_t *self); +void SP_misc_actor (edict_t *self); +void SP_misc_gib_arm (edict_t *self); +void SP_misc_gib_leg (edict_t *self); +void SP_misc_gib_head (edict_t *self); +void SP_misc_insane (edict_t *self); +void SP_misc_deadsoldier (edict_t *self); +void SP_misc_viper (edict_t *self); +void SP_misc_viper_bomb (edict_t *self); +void SP_misc_bigviper (edict_t *self); +void SP_misc_strogg_ship (edict_t *self); +void SP_misc_teleporter (edict_t *self); +void SP_misc_teleporter_dest (edict_t *self); +void SP_misc_blackhole (edict_t *self); +void SP_misc_eastertank (edict_t *self); +void SP_misc_easterchick (edict_t *self); +void SP_misc_easterchick2 (edict_t *self); + +void SP_monster_berserk (edict_t *self); +void SP_monster_gladiator (edict_t *self); +void SP_monster_gunner (edict_t *self); +void SP_monster_infantry (edict_t *self); +void SP_monster_soldier_light (edict_t *self); +void SP_monster_soldier (edict_t *self); +void SP_monster_soldier_ss (edict_t *self); +void SP_monster_tank (edict_t *self); +void SP_monster_medic (edict_t *self); +void SP_monster_flipper (edict_t *self); +void SP_monster_chick (edict_t *self); +void SP_monster_parasite (edict_t *self); +void SP_monster_flyer (edict_t *self); +void SP_monster_brain (edict_t *self); +void SP_monster_floater (edict_t *self); +void SP_monster_hover (edict_t *self); +void SP_monster_mutant (edict_t *self); +void SP_monster_supertank (edict_t *self); +void SP_monster_boss2 (edict_t *self); +void SP_monster_jorg (edict_t *self); +void SP_monster_boss3_stand (edict_t *self); + +void SP_monster_commander_body (edict_t *self); + +void SP_turret_breach (edict_t *self); +void SP_turret_base (edict_t *self); +void SP_turret_driver (edict_t *self); + + +spawn_t spawns[] = { + {"item_health", SP_item_health}, + {"item_health_small", SP_item_health_small}, + {"item_health_large", SP_item_health_large}, + {"item_health_mega", SP_item_health_mega}, + + {"info_player_start", SP_info_player_start}, + {"info_player_deathmatch", SP_info_player_deathmatch}, + {"info_player_coop", SP_info_player_coop}, + {"info_player_intermission", SP_info_player_intermission}, + + {"func_plat", SP_func_plat}, + {"func_button", SP_func_button}, + {"func_door", SP_func_door}, + {"func_door_secret", SP_func_door_secret}, + {"func_door_rotating", SP_func_door_rotating}, + {"func_rotating", SP_func_rotating}, + {"func_train", SP_func_train}, + {"func_water", SP_func_water}, + {"func_conveyor", SP_func_conveyor}, + {"func_areaportal", SP_func_areaportal}, + {"func_clock", SP_func_clock}, + {"func_wall", SP_func_wall}, + {"func_object", SP_func_object}, + {"func_timer", SP_func_timer}, + {"func_explosive", SP_func_explosive}, + {"func_killbox", SP_func_killbox}, + + {"trigger_always", SP_trigger_always}, + {"trigger_once", SP_trigger_once}, + {"trigger_multiple", SP_trigger_multiple}, + {"trigger_relay", SP_trigger_relay}, + {"trigger_push", SP_trigger_push}, + {"trigger_hurt", SP_trigger_hurt}, + {"trigger_key", SP_trigger_key}, + {"trigger_counter", SP_trigger_counter}, + {"trigger_elevator", SP_trigger_elevator}, + {"trigger_gravity", SP_trigger_gravity}, + {"trigger_monsterjump", SP_trigger_monsterjump}, + + {"target_temp_entity", SP_target_temp_entity}, + {"target_speaker", SP_target_speaker}, + {"target_explosion", SP_target_explosion}, + {"target_changelevel", SP_target_changelevel}, + {"target_secret", SP_target_secret}, + {"target_goal", SP_target_goal}, + {"target_splash", SP_target_splash}, + {"target_spawner", SP_target_spawner}, + {"target_blaster", SP_target_blaster}, + {"target_crosslevel_trigger", SP_target_crosslevel_trigger}, + {"target_crosslevel_target", SP_target_crosslevel_target}, + {"target_laser", SP_target_laser}, + {"target_help", SP_target_help}, + {"target_actor", SP_target_actor}, + {"target_lightramp", SP_target_lightramp}, + {"target_earthquake", SP_target_earthquake}, + {"target_character", SP_target_character}, + {"target_string", SP_target_string}, + + {"worldspawn", SP_worldspawn}, + {"viewthing", SP_viewthing}, + + {"light", SP_light}, + {"light_mine1", SP_light_mine1}, + {"light_mine2", SP_light_mine2}, + {"info_null", SP_info_null}, + {"func_group", SP_info_null}, + {"info_notnull", SP_info_notnull}, + {"path_corner", SP_path_corner}, + {"point_combat", SP_point_combat}, + + {"misc_explobox", SP_misc_explobox}, + {"misc_banner", SP_misc_banner}, + {"misc_satellite_dish", SP_misc_satellite_dish}, + {"misc_actor", SP_misc_actor}, + {"misc_gib_arm", SP_misc_gib_arm}, + {"misc_gib_leg", SP_misc_gib_leg}, + {"misc_gib_head", SP_misc_gib_head}, + {"misc_insane", SP_misc_insane}, + {"misc_deadsoldier", SP_misc_deadsoldier}, + {"misc_viper", SP_misc_viper}, + {"misc_viper_bomb", SP_misc_viper_bomb}, + {"misc_bigviper", SP_misc_bigviper}, + {"misc_strogg_ship", SP_misc_strogg_ship}, + {"misc_teleporter", SP_misc_teleporter}, + {"misc_teleporter_dest", SP_misc_teleporter_dest}, + {"misc_blackhole", SP_misc_blackhole}, + {"misc_eastertank", SP_misc_eastertank}, + {"misc_easterchick", SP_misc_easterchick}, + {"misc_easterchick2", SP_misc_easterchick2}, + + {"monster_berserk", SP_monster_berserk}, + {"monster_gladiator", SP_monster_gladiator}, + {"monster_gunner", SP_monster_gunner}, + {"monster_infantry", SP_monster_infantry}, + {"monster_soldier_light", SP_monster_soldier_light}, + {"monster_soldier", SP_monster_soldier}, + {"monster_soldier_ss", SP_monster_soldier_ss}, + {"monster_tank", SP_monster_tank}, + {"monster_tank_commander", SP_monster_tank}, + {"monster_medic", SP_monster_medic}, + {"monster_flipper", SP_monster_flipper}, + {"monster_chick", SP_monster_chick}, + {"monster_parasite", SP_monster_parasite}, + {"monster_flyer", SP_monster_flyer}, + {"monster_brain", SP_monster_brain}, + {"monster_floater", SP_monster_floater}, + {"monster_hover", SP_monster_hover}, + {"monster_mutant", SP_monster_mutant}, + {"monster_supertank", SP_monster_supertank}, + {"monster_boss2", SP_monster_boss2}, + {"monster_boss3_stand", SP_monster_boss3_stand}, + {"monster_jorg", SP_monster_jorg}, + + {"monster_commander_body", SP_monster_commander_body}, + + {"turret_breach", SP_turret_breach}, + {"turret_base", SP_turret_base}, + {"turret_driver", SP_turret_driver}, + + {NULL, NULL} +}; + +/* +=============== +ED_CallSpawn + +Finds the spawn function for the entity and calls it +=============== +*/ +void ED_CallSpawn (edict_t *ent) +{ + spawn_t *s; + gitem_t *item; + int i; + + if (!ent->classname) + { + gi.dprintf ("ED_CallSpawn: NULL classname\n"); + return; + } + + // check item spawn functions + for (i=0,item=itemlist ; iclassname) + continue; + if (!strcmp(item->classname, ent->classname)) + { // found it + SpawnItem (ent, item); + return; + } + } + + // check normal spawn functions + for (s=spawns ; s->name ; s++) + { + if (!strcmp(s->name, ent->classname)) + { // found it + s->spawn (ent); + return; + } + } + gi.dprintf ("%s doesn't have a spawn function\n", ent->classname); +} + +/* +============= +ED_NewString +============= +*/ +char *ED_NewString (char *string) +{ + char *newb, *new_p; + int i,l; + + l = strlen(string) + 1; + + newb = gi.TagMalloc (l, TAG_LEVEL); + + new_p = newb; + + for (i=0 ; i< l ; i++) + { + if (string[i] == '\\' && i < l-1) + { + i++; + if (string[i] == 'n') + *new_p++ = '\n'; + else + *new_p++ = '\\'; + } + else + *new_p++ = string[i]; + } + + return newb; +} + + + + +/* +=============== +ED_ParseField + +Takes a key/value pair and sets the binary values +in an edict +=============== +*/ +void ED_ParseField (char *key, char *value, edict_t *ent) +{ + field_t *f; + byte *b; + float v; + vec3_t vec; + + for (f=fields ; f->name ; f++) + { + if (!(f->flags & FFL_NOSPAWN) && !Q_stricmp(f->name, key)) + { // found it + if (f->flags & FFL_SPAWNTEMP) + b = (byte *)&st; + else + b = (byte *)ent; + + switch (f->type) + { + case F_LSTRING: + *(char **)(b+f->ofs) = ED_NewString (value); + break; + case F_VECTOR: + sscanf (value, "%f %f %f", &vec[0], &vec[1], &vec[2]); + ((float *)(b+f->ofs))[0] = vec[0]; + ((float *)(b+f->ofs))[1] = vec[1]; + ((float *)(b+f->ofs))[2] = vec[2]; + break; + case F_INT: + *(int *)(b+f->ofs) = atoi(value); + break; + case F_FLOAT: + *(float *)(b+f->ofs) = atof(value); + break; + case F_ANGLEHACK: + v = atof(value); + ((float *)(b+f->ofs))[0] = 0; + ((float *)(b+f->ofs))[1] = v; + ((float *)(b+f->ofs))[2] = 0; + break; + case F_IGNORE: + break; + } + return; + } + } + gi.dprintf ("%s is not a field\n", key); +} + +/* +==================== +ED_ParseEdict + +Parses an edict out of the given string, returning the new position +ed should be a properly initialized empty edict. +==================== +*/ +char *ED_ParseEdict (char *data, edict_t *ent) +{ + qboolean init; + char keyname[256]; + char *com_token; + + init = false; + memset (&st, 0, sizeof(st)); + +// go through all the dictionary pairs + while (1) + { + // parse key + com_token = COM_Parse (&data); + if (com_token[0] == '}') + break; + if (!data) + gi.error ("ED_ParseEntity: EOF without closing brace"); + + strncpy (keyname, com_token, sizeof(keyname)-1); + + // parse value + com_token = COM_Parse (&data); + if (!data) + gi.error ("ED_ParseEntity: EOF without closing brace"); + + if (com_token[0] == '}') + gi.error ("ED_ParseEntity: closing brace without data"); + + init = true; + + // keynames with a leading underscore are used for utility comments, + // and are immediately discarded by quake + if (keyname[0] == '_') + continue; + + ED_ParseField (keyname, com_token, ent); + } + + if (!init) + memset (ent, 0, sizeof(*ent)); + + return data; +} + + +/* +================ +G_FindTeams + +Chain together all entities with a matching team field. + +All but the first will have the FL_TEAMSLAVE flag set. +All but the last will have the teamchain field set to the next one +================ +*/ +void G_FindTeams (void) +{ + edict_t *e, *e2, *chain; + int i, j; + int c, c2; + + c = 0; + c2 = 0; + for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++) + { + if (!e->inuse) + continue; + if (!e->team) + continue; + if (e->flags & FL_TEAMSLAVE) + continue; + chain = e; + e->teammaster = e; + c++; + c2++; + for (j=i+1, e2=e+1 ; j < globals.num_edicts ; j++,e2++) + { + if (!e2->inuse) + continue; + if (!e2->team) + continue; + if (e2->flags & FL_TEAMSLAVE) + continue; + if (!strcmp(e->team, e2->team)) + { + c2++; + chain->teamchain = e2; + e2->teammaster = e; + chain = e2; + e2->flags |= FL_TEAMSLAVE; + } + } + } + + gi.dprintf ("%i teams with %i entities\n", c, c2); +} + +/* +============== +SpawnEntities + +Creates a server's entity / program execution context by +parsing textual entity definitions out of an ent file. +============== +*/ +void SpawnEntities (char *mapname, char *entities, char *spawnpoint) +{ + edict_t *ent; + int inhibit; + char *com_token; + int i; + float skill_level; + + skill_level = floor (skill->value); + if (skill_level < 0) + skill_level = 0; + if (skill_level > 3) + skill_level = 3; + if (skill->value != skill_level) + gi.cvar_forceset("skill", va("%f", skill_level)); + + SaveClientData (); + + gi.FreeTags (TAG_LEVEL); + + memset (&level, 0, sizeof(level)); + memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0])); + + strncpy (level.mapname, mapname, sizeof(level.mapname)-1); + strncpy (game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)-1); + + // set client fields on player ents + for (i=0 ; iclassname, "trigger_once") && !Q_stricmp(ent->model, "*27")) + ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; + + // remove things (except the world) from different skill levels or deathmatch + if (ent != g_edicts) + { + if (deathmatch->value) + { + if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH ) + { + G_FreeEdict (ent); + inhibit++; + continue; + } + } + else + { + if ( /* ((coop->value) && (ent->spawnflags & SPAWNFLAG_NOT_COOP)) || */ + ((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || + ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || + (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) + ) + { + G_FreeEdict (ent); + inhibit++; + continue; + } + } + + ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY|SPAWNFLAG_NOT_MEDIUM|SPAWNFLAG_NOT_HARD|SPAWNFLAG_NOT_COOP|SPAWNFLAG_NOT_DEATHMATCH); + } + + ED_CallSpawn (ent); + } + + gi.dprintf ("%i entities inhibited\n", inhibit); + +#ifdef DEBUG + i = 1; + ent = EDICT_NUM(i); + while (i < globals.num_edicts) { + if (ent->inuse != 0 || ent->inuse != 1) + Com_DPrintf("Invalid entity %d\n", i); + i++, ent++; + } +#endif + + G_FindTeams (); + + PlayerTrail_Init (); +} + + +//=================================================================== + +#if 0 + // cursor positioning + xl + xr + yb + yt + xv + yv + + // drawing + statpic + pic + num + string + + // control + if + ifeq + ifbit + endif + +#endif + +char *single_statusbar = +"yb -24 " + +// health +"xv 0 " +"hnum " +"xv 50 " +"pic 0 " + +// ammo +"if 2 " +" xv 100 " +" anum " +" xv 150 " +" pic 2 " +"endif " + +// armor +"if 4 " +" xv 200 " +" rnum " +" xv 250 " +" pic 4 " +"endif " + +// selected item +"if 6 " +" xv 296 " +" pic 6 " +"endif " + +"yb -50 " + +// picked up item +"if 7 " +" xv 0 " +" pic 7 " +" xv 26 " +" yb -42 " +" stat_string 8 " +" yb -50 " +"endif " + +// timer +"if 9 " +" xv 262 " +" num 2 10 " +" xv 296 " +" pic 9 " +"endif " + +// help / weapon icon +"if 11 " +" xv 148 " +" pic 11 " +"endif " +; + +char *dm_statusbar = +"yb -24 " + +// health +"xv 0 " +"hnum " +"xv 50 " +"pic 0 " + +// ammo +"if 2 " +" xv 100 " +" anum " +" xv 150 " +" pic 2 " +"endif " + +// armor +"if 4 " +" xv 200 " +" rnum " +" xv 250 " +" pic 4 " +"endif " + +// selected item +"if 6 " +" xv 296 " +" pic 6 " +"endif " + +"yb -50 " + +// picked up item +"if 7 " +" xv 0 " +" pic 7 " +" xv 26 " +" yb -42 " +" stat_string 8 " +" yb -50 " +"endif " + +// timer +"if 9 " +" xv 246 " +" num 2 10 " +" xv 296 " +" pic 9 " +"endif " + +// help / weapon icon +"if 11 " +" xv 148 " +" pic 11 " +"endif " + +// frags +"xr -50 " +"yt 2 " +"num 3 14 " + +// spectator +"if 17 " + "xv 0 " + "yb -58 " + "string2 \"SPECTATOR MODE\" " +"endif " + +// chase camera +"if 16 " + "xv 0 " + "yb -68 " + "string \"Chasing\" " + "xv 64 " + "stat_string 16 " +"endif " +; + + +/*QUAKED worldspawn (0 0 0) ? + +Only used for the world. +"sky" environment map name +"skyaxis" vector axis for rotating sky +"skyrotate" speed of rotation in degrees/second +"sounds" music cd track number +"gravity" 800 is default gravity +"message" text to print at user logon +*/ +void SP_worldspawn (edict_t *ent) +{ + ent->movetype = MOVETYPE_PUSH; + ent->solid = SOLID_BSP; + ent->inuse = true; // since the world doesn't use G_Spawn() + ent->s.modelindex = 1; // world model is always index 1 + + //--------------- + + // reserve some spots for dead player bodies for coop / deathmatch + InitBodyQue (); + + // set configstrings for items + SetItemNames (); + + if (st.nextmap) + strcpy (level.nextmap, st.nextmap); + + // make some data visible to the server + + if (ent->message && ent->message[0]) + { + gi.configstring (CS_NAME, ent->message); + strncpy (level.level_name, ent->message, sizeof(level.level_name)); + } + else + strncpy (level.level_name, level.mapname, sizeof(level.level_name)); + + if (st.sky && st.sky[0]) + gi.configstring (CS_SKY, st.sky); + else + gi.configstring (CS_SKY, "unit1_"); + + gi.configstring (CS_SKYROTATE, va("%f", st.skyrotate) ); + + gi.configstring (CS_SKYAXIS, va("%f %f %f", + st.skyaxis[0], st.skyaxis[1], st.skyaxis[2]) ); + + gi.configstring (CS_CDTRACK, va("%i", ent->sounds) ); + + gi.configstring (CS_MAXCLIENTS, va("%i", (int)(maxclients->value) ) ); + + // status bar program + if (deathmatch->value) + gi.configstring (CS_STATUSBAR, dm_statusbar); + else + gi.configstring (CS_STATUSBAR, single_statusbar); + + //--------------- + + + // help icon for statusbar + gi.imageindex ("i_help"); + level.pic_health = gi.imageindex ("i_health"); + gi.imageindex ("help"); + gi.imageindex ("field_3"); + + if (!st.gravity) + gi.cvar_set("sv_gravity", "800"); + else + gi.cvar_set("sv_gravity", st.gravity); + + snd_fry = gi.soundindex ("player/fry.wav"); // standing in lava / slime + + PrecacheItem (FindItem ("Blaster")); + + gi.soundindex ("player/lava1.wav"); + gi.soundindex ("player/lava2.wav"); + + gi.soundindex ("misc/pc_up.wav"); + gi.soundindex ("misc/talk1.wav"); + + gi.soundindex ("misc/udeath.wav"); + + // gibs + gi.soundindex ("items/respawn1.wav"); + + // sexed sounds + gi.soundindex ("*death1.wav"); + gi.soundindex ("*death2.wav"); + gi.soundindex ("*death3.wav"); + gi.soundindex ("*death4.wav"); + gi.soundindex ("*fall1.wav"); + gi.soundindex ("*fall2.wav"); + gi.soundindex ("*gurp1.wav"); // drowning damage + gi.soundindex ("*gurp2.wav"); + gi.soundindex ("*jump1.wav"); // player jump + gi.soundindex ("*pain25_1.wav"); + gi.soundindex ("*pain25_2.wav"); + gi.soundindex ("*pain50_1.wav"); + gi.soundindex ("*pain50_2.wav"); + gi.soundindex ("*pain75_1.wav"); + gi.soundindex ("*pain75_2.wav"); + gi.soundindex ("*pain100_1.wav"); + gi.soundindex ("*pain100_2.wav"); + + // sexed models + // THIS ORDER MUST MATCH THE DEFINES IN g_local.h + // you can add more, max 15 + gi.modelindex ("#w_blaster.md2"); + gi.modelindex ("#w_shotgun.md2"); + gi.modelindex ("#w_sshotgun.md2"); + gi.modelindex ("#w_machinegun.md2"); + gi.modelindex ("#w_chaingun.md2"); + gi.modelindex ("#a_grenades.md2"); + gi.modelindex ("#w_glauncher.md2"); + gi.modelindex ("#w_rlauncher.md2"); + gi.modelindex ("#w_hyperblaster.md2"); + gi.modelindex ("#w_railgun.md2"); + gi.modelindex ("#w_bfg.md2"); + + //------------------- + + gi.soundindex ("player/gasp1.wav"); // gasping for air + gi.soundindex ("player/gasp2.wav"); // head breaking surface, not gasping + + gi.soundindex ("player/watr_in.wav"); // feet hitting water + gi.soundindex ("player/watr_out.wav"); // feet leaving water + + gi.soundindex ("player/watr_un.wav"); // head going underwater + + gi.soundindex ("player/u_breath1.wav"); + gi.soundindex ("player/u_breath2.wav"); + + gi.soundindex ("items/pkup.wav"); // bonus item pickup + gi.soundindex ("world/land.wav"); // landing thud + gi.soundindex ("misc/h2ohit1.wav"); // landing splash + + gi.soundindex ("items/damage.wav"); + gi.soundindex ("items/protect.wav"); + gi.soundindex ("items/protect4.wav"); + gi.soundindex ("weapons/noammo.wav"); + + gi.soundindex ("infantry/inflies1.wav"); + + sm_meat_index = gi.modelindex ("models/objects/gibs/sm_meat/tris.md2"); + gi.modelindex ("models/objects/gibs/arm/tris.md2"); + gi.modelindex ("models/objects/gibs/bone/tris.md2"); + gi.modelindex ("models/objects/gibs/bone2/tris.md2"); + gi.modelindex ("models/objects/gibs/chest/tris.md2"); + gi.modelindex ("models/objects/gibs/skull/tris.md2"); + gi.modelindex ("models/objects/gibs/head2/tris.md2"); + +// +// Setup light animation tables. 'a' is total darkness, 'z' is doublebright. +// + + // 0 normal + gi.configstring(CS_LIGHTS+0, "m"); + + // 1 FLICKER (first variety) + gi.configstring(CS_LIGHTS+1, "mmnmmommommnonmmonqnmmo"); + + // 2 SLOW STRONG PULSE + gi.configstring(CS_LIGHTS+2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"); + + // 3 CANDLE (first variety) + gi.configstring(CS_LIGHTS+3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg"); + + // 4 FAST STROBE + gi.configstring(CS_LIGHTS+4, "mamamamamama"); + + // 5 GENTLE PULSE 1 + gi.configstring(CS_LIGHTS+5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj"); + + // 6 FLICKER (second variety) + gi.configstring(CS_LIGHTS+6, "nmonqnmomnmomomno"); + + // 7 CANDLE (second variety) + gi.configstring(CS_LIGHTS+7, "mmmaaaabcdefgmmmmaaaammmaamm"); + + // 8 CANDLE (third variety) + gi.configstring(CS_LIGHTS+8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"); + + // 9 SLOW STROBE (fourth variety) + gi.configstring(CS_LIGHTS+9, "aaaaaaaazzzzzzzz"); + + // 10 FLUORESCENT FLICKER + gi.configstring(CS_LIGHTS+10, "mmamammmmammamamaaamammma"); + + // 11 SLOW PULSE NOT FADE TO BLACK + gi.configstring(CS_LIGHTS+11, "abcdefghijklmnopqrrqponmlkjihgfedcba"); + + // styles 32-62 are assigned by the light program for switchable lights + + // 63 testing + gi.configstring(CS_LIGHTS+63, "a"); +} + diff --git a/game/g_svcmds.c b/game/g_svcmds.c new file mode 100644 index 000000000..686863334 --- /dev/null +++ b/game/g_svcmds.c @@ -0,0 +1,300 @@ +/* +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. + +*/ + +#include "g_local.h" + + +void Svcmd_Test_f (void) +{ + gi.cprintf (NULL, PRINT_HIGH, "Svcmd_Test_f()\n"); +} + +/* +============================================================================== + +PACKET FILTERING + + +You can add or remove addresses from the filter list with: + +addip +removeip + +The ip address is specified in dot format, and any unspecified digits will match any value, so you can specify an entire class C network with "addip 192.246.40". + +Removeip will only remove an address specified exactly the same way. You cannot addip a subnet, then removeip a single host. + +listip +Prints the current list of filters. + +writeip +Dumps "addip " commands to listip.cfg so it can be execed at a later date. The filter lists are not saved and restored by default, because I beleive it would cause too much confusion. + +filterban <0 or 1> + +If 1 (the default), then ip addresses matching the current list will be prohibited from entering the game. This is the default setting. + +If 0, then only addresses matching the list will be allowed. This lets you easily set up a private game, or a game that only allows players from your local network. + + +============================================================================== +*/ + +typedef struct +{ + unsigned mask; + unsigned compare; +} ipfilter_t; + +#define MAX_IPFILTERS 1024 + +ipfilter_t ipfilters[MAX_IPFILTERS]; +int numipfilters; + +/* +================= +StringToFilter +================= +*/ +static qboolean StringToFilter (char *s, ipfilter_t *f) +{ + char num[128]; + int i, j; + byte b[4]; + byte m[4]; + + for (i=0 ; i<4 ; i++) + { + b[i] = 0; + m[i] = 0; + } + + for (i=0 ; i<4 ; i++) + { + if (*s < '0' || *s > '9') + { + gi.cprintf(NULL, PRINT_HIGH, "Bad filter address: %s\n", s); + return false; + } + + j = 0; + while (*s >= '0' && *s <= '9') + { + num[j++] = *s++; + } + num[j] = 0; + b[i] = atoi(num); + if (b[i] != 0) + m[i] = 255; + + if (!*s) + break; + s++; + } + + f->mask = *(unsigned *)m; + f->compare = *(unsigned *)b; + + return true; +} + +/* +================= +SV_FilterPacket +================= +*/ +qboolean SV_FilterPacket (char *from) +{ + int i; + unsigned in; + byte m[4]; + char *p; + + i = 0; + p = from; + while (*p && i < 4) { + m[i] = 0; + while (*p >= '0' && *p <= '9') { + m[i] = m[i]*10 + (*p - '0'); + p++; + } + if (!*p || *p == ':') + break; + i++, p++; + } + + in = *(unsigned *)m; + + for (i=0 ; ivalue; + + return (int)!filterban->value; +} + + +/* +================= +SV_AddIP_f +================= +*/ +void SVCmd_AddIP_f (void) +{ + int i; + + if (gi.argc() < 3) { + gi.cprintf(NULL, PRINT_HIGH, "Usage: addip \n"); + return; + } + + for (i=0 ; i\n"); + return; + } + + if (!StringToFilter (gi.argv(2), &f)) + return; + + for (i=0 ; istring) + sprintf (name, "%s/listip.cfg", GAMEVERSION); + else + sprintf (name, "%s/listip.cfg", game->string); + + gi.cprintf (NULL, PRINT_HIGH, "Writing %s.\n", name); + + f = fopen (name, "wb"); + if (!f) + { + gi.cprintf (NULL, PRINT_HIGH, "Couldn't open %s\n", name); + return; + } + + fprintf(f, "set filterban %d\n", (int)filterban->value); + + for (i=0 ; istyle); + gi.WritePosition (ent->s.origin); + gi.multicast (ent->s.origin, MULTICAST_PVS); +} + +void SP_target_temp_entity (edict_t *ent) +{ + ent->use = Use_Target_Tent; +} + + +//========================================================== + +//========================================================== + +/*QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off reliable +"noise" wav file to play +"attenuation" +-1 = none, send to whole level +1 = normal fighting sounds +2 = idle sound level +3 = ambient sound level +"volume" 0.0 to 1.0 + +Normal sounds play each time the target is used. The reliable flag can be set for crucial voiceovers. + +Looped sounds are always atten 3 / vol 1, and the use function toggles it on/off. +Multiple identical looping sounds will just increase volume without any speed cost. +*/ +void Use_Target_Speaker (edict_t *ent, edict_t *other, edict_t *activator) +{ + int chan; + + if (ent->spawnflags & 3) + { // looping sound toggles + if (ent->s.sound) + ent->s.sound = 0; // turn it off + else + ent->s.sound = ent->noise_index; // start it + } + else + { // normal sound + if (ent->spawnflags & 4) + chan = CHAN_VOICE|CHAN_RELIABLE; + else + chan = CHAN_VOICE; + // use a positioned_sound, because this entity won't normally be + // sent to any clients because it is invisible + gi.positioned_sound (ent->s.origin, ent, chan, ent->noise_index, ent->volume, ent->attenuation, 0); + } +} + +void SP_target_speaker (edict_t *ent) +{ + char buffer[MAX_QPATH]; + + if(!st.noise) + { + gi.dprintf("target_speaker with no noise set at %s\n", vtos(ent->s.origin)); + return; + } + if (!strstr (st.noise, ".wav")) + Com_sprintf (buffer, sizeof(buffer), "%s.wav", st.noise); + else + strncpy (buffer, st.noise, sizeof(buffer)); + ent->noise_index = gi.soundindex (buffer); + + if (!ent->volume) + ent->volume = 1.0; + + if (!ent->attenuation) + ent->attenuation = 1.0; + else if (ent->attenuation == -1) // use -1 so 0 defaults to 1 + ent->attenuation = 0; + + // check for prestarted looping sound + if (ent->spawnflags & 1) + ent->s.sound = ent->noise_index; + + ent->use = Use_Target_Speaker; + + // must link the entity so we get areas and clusters so + // the server can determine who to send updates to + gi.linkentity (ent); +} + + +//========================================================== + +void Use_Target_Help (edict_t *ent, edict_t *other, edict_t *activator) +{ + if (ent->spawnflags & 1) + strncpy (game.helpmessage1, ent->message, sizeof(game.helpmessage2)-1); + else + strncpy (game.helpmessage2, ent->message, sizeof(game.helpmessage1)-1); + + game.helpchanged++; +} + +/*QUAKED target_help (1 0 1) (-16 -16 -24) (16 16 24) help1 +When fired, the "message" key becomes the current personal computer string, and the message light will be set on all clients status bars. +*/ +void SP_target_help(edict_t *ent) +{ + if (deathmatch->value) + { // auto-remove for deathmatch + G_FreeEdict (ent); + return; + } + + if (!ent->message) + { + gi.dprintf ("%s with no message at %s\n", ent->classname, vtos(ent->s.origin)); + G_FreeEdict (ent); + return; + } + ent->use = Use_Target_Help; +} + +//========================================================== + +/*QUAKED target_secret (1 0 1) (-8 -8 -8) (8 8 8) +Counts a secret found. +These are single use targets. +*/ +void use_target_secret (edict_t *ent, edict_t *other, edict_t *activator) +{ + gi.sound (ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0); + + level.found_secrets++; + + G_UseTargets (ent, activator); + G_FreeEdict (ent); +} + +void SP_target_secret (edict_t *ent) +{ + if (deathmatch->value) + { // auto-remove for deathmatch + G_FreeEdict (ent); + return; + } + + ent->use = use_target_secret; + if (!st.noise) + st.noise = "misc/secret.wav"; + ent->noise_index = gi.soundindex (st.noise); + ent->svflags = SVF_NOCLIENT; + level.total_secrets++; + // map bug hack + if (!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); + + level.found_goals++; + + if (level.found_goals == level.total_goals) + gi.configstring (CS_CDTRACK, "0"); + + G_UseTargets (ent, activator); + G_FreeEdict (ent); +} + +void SP_target_goal (edict_t *ent) +{ + if (deathmatch->value) + { // auto-remove for deathmatch + G_FreeEdict (ent); + return; + } + + ent->use = use_target_goal; + if (!st.noise) + st.noise = "misc/secret.wav"; + ent->noise_index = gi.soundindex (st.noise); + ent->svflags = SVF_NOCLIENT; + level.total_goals++; +} + +//========================================================== + + +/*QUAKED target_explosion (1 0 0) (-8 -8 -8) (8 8 8) +Spawns an explosion temporary entity when used. + +"delay" wait this long before going off +"dmg" how much radius damage should be done, defaults to 0 +*/ +void target_explosion_explode (edict_t *self) +{ + float save; + + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_EXPLOSION1); + gi.WritePosition (self->s.origin); + gi.multicast (self->s.origin, MULTICAST_PHS); + + T_RadiusDamage (self, self->activator, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE); + + save = self->delay; + self->delay = 0; + G_UseTargets (self, self->activator); + self->delay = save; +} + +void use_target_explosion (edict_t *self, edict_t *other, edict_t *activator) +{ + self->activator = activator; + + if (!self->delay) + { + target_explosion_explode (self); + return; + } + + self->think = target_explosion_explode; + self->nextthink = level.time + self->delay; +} + +void SP_target_explosion (edict_t *ent) +{ + ent->use = use_target_explosion; + ent->svflags = SVF_NOCLIENT; +} + + +//========================================================== + +/*QUAKED target_changelevel (1 0 0) (-8 -8 -8) (8 8 8) +Changes level to "map" when fired +*/ +void use_target_changelevel (edict_t *self, edict_t *other, edict_t *activator) +{ + if (level.intermissiontime) + return; // already activated + + if (!deathmatch->value && !coop->value) + { + if (g_edicts[1].health <= 0) + return; + } + + // if noexit, do a ton of damage to other + if (deathmatch->value && !( (int)dmflags->value & DF_ALLOW_EXIT) && other != world) + { + T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 10 * other->max_health, 1000, 0, MOD_EXIT); + return; + } + + // if multiplayer, let everyone know who hit the exit + if (deathmatch->value) + { + if (activator && activator->client) + gi.bprintf (PRINT_HIGH, "%s exited the level.\n", activator->client->pers.netname); + } + + // if going to a new unit, clear cross triggers + if (strstr(self->map, "*")) + game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); + + BeginIntermission (self); +} + +void SP_target_changelevel (edict_t *ent) +{ + if (!ent->map) + { + gi.dprintf("target_changelevel with no map at %s\n", vtos(ent->s.origin)); + G_FreeEdict (ent); + return; + } + + // ugly hack because *SOMEBODY* screwed up their map + if((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 +*/ + +void use_target_splash (edict_t *self, edict_t *other, edict_t *activator) +{ + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_SPLASH); + gi.WriteByte (self->count); + gi.WritePosition (self->s.origin); + gi.WriteDir (self->movedir); + gi.WriteByte (self->sounds); + gi.multicast (self->s.origin, MULTICAST_PVS); + + if (self->dmg) + T_RadiusDamage (self, activator, self->dmg, NULL, self->dmg+40, MOD_SPLASH); +} + +void SP_target_splash (edict_t *self) +{ + self->use = use_target_splash; + G_SetMovedir (self->s.angles, self->movedir); + + if (!self->count) + self->count = 32; + + self->svflags = SVF_NOCLIENT; +} + + +//========================================================== + +/*QUAKED target_spawner (1 0 0) (-8 -8 -8) (8 8 8) +Set target to the type of entity you want spawned. +Useful for spawning monsters and gibs in the factory levels. + +For monsters: + Set direction to the facing you want it to have. + +For gibs: + Set direction if you want it moving and + speed how fast it should be moving otherwise it + will just be dropped +*/ +void ED_CallSpawn (edict_t *ent); + +void use_target_spawner (edict_t *self, edict_t *other, edict_t *activator) +{ + edict_t *ent; + + ent = G_Spawn(); + ent->classname = self->target; + VectorCopy (self->s.origin, ent->s.origin); + VectorCopy (self->s.angles, ent->s.angles); + ED_CallSpawn (ent); + gi.unlinkentity (ent); + KillBox (ent); + gi.linkentity (ent); + if (self->speed) + VectorCopy (self->movedir, ent->velocity); +} + +void SP_target_spawner (edict_t *self) +{ + self->use = use_target_spawner; + self->svflags = SVF_NOCLIENT; + if (self->speed) + { + G_SetMovedir (self->s.angles, self->movedir); + VectorScale (self->movedir, self->speed, self->movedir); + } +} + +//========================================================== + +/*QUAKED target_blaster (1 0 0) (-8 -8 -8) (8 8 8) NOTRAIL NOEFFECTS +Fires a blaster bolt in the set direction when triggered. + +dmg default is 15 +speed default is 1000 +*/ + +void use_target_blaster (edict_t *self, edict_t *other, edict_t *activator) +{ + int effect; + + if (self->spawnflags & 2) + effect = 0; + else if (self->spawnflags & 1) + effect = EF_HYPERBLASTER; + else + effect = EF_BLASTER; + + fire_blaster (self, self->s.origin, self->movedir, self->dmg, self->speed, EF_BLASTER, MOD_TARGET_BLASTER); + gi.sound (self, CHAN_VOICE, self->noise_index, 1, ATTN_NORM, 0); +} + +void SP_target_blaster (edict_t *self) +{ + self->use = use_target_blaster; + G_SetMovedir (self->s.angles, self->movedir); + self->noise_index = gi.soundindex ("weapons/laser2.wav"); + + if (!self->dmg) + self->dmg = 15; + if (!self->speed) + self->speed = 1000; + + self->svflags = SVF_NOCLIENT; +} + + +//========================================================== + +/*QUAKED target_crosslevel_trigger (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8 +Once this trigger is touched/used, any trigger_crosslevel_target with the same trigger number is automatically used when a level is started within the same unit. It is OK to check multiple triggers. Message, delay, target, and killtarget also work. +*/ +void trigger_crosslevel_trigger_use (edict_t *self, edict_t *other, edict_t *activator) +{ + game.serverflags |= self->spawnflags; + G_FreeEdict (self); +} + +void SP_target_crosslevel_trigger (edict_t *self) +{ + self->svflags = SVF_NOCLIENT; + self->use = trigger_crosslevel_trigger_use; +} + +/*QUAKED target_crosslevel_target (.5 .5 .5) (-8 -8 -8) (8 8 8) trigger1 trigger2 trigger3 trigger4 trigger5 trigger6 trigger7 trigger8 +Triggered by a trigger_crosslevel elsewhere within a unit. If multiple triggers are checked, all must be true. Delay, target and +killtarget also work. + +"delay" delay before using targets if the trigger has been activated (default 1) +*/ +void target_crosslevel_target_think (edict_t *self) +{ + if (self->spawnflags == (game.serverflags & SFL_CROSS_TRIGGER_MASK & self->spawnflags)) + { + G_UseTargets (self, self); + G_FreeEdict (self); + } +} + +void SP_target_crosslevel_target (edict_t *self) +{ + if (! self->delay) + self->delay = 1; + self->svflags = SVF_NOCLIENT; + + self->think = target_crosslevel_target_think; + self->nextthink = level.time + self->delay; +} + +//========================================================== + +/*QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON RED GREEN BLUE YELLOW ORANGE FAT +When triggered, fires a laser. You can either set a target +or a direction. +*/ + +void target_laser_think (edict_t *self) +{ + edict_t *ignore; + vec3_t start; + vec3_t end; + trace_t tr; + vec3_t point; + vec3_t last_movedir; + int count; + + if (self->spawnflags & 0x80000000) + count = 8; + else + count = 4; + + if (self->enemy) + { + VectorCopy (self->movedir, last_movedir); + VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point); + 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) + { + tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); + + if (!tr.ent) + break; + + // 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); + + // 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)) + { + 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); + } + break; + } + + ignore = tr.ent; + VectorCopy (tr.endpos, start); + } + + VectorCopy (tr.endpos, self->s.old_origin); + + self->nextthink = level.time + FRAMETIME; +} + +void target_laser_on (edict_t *self) +{ + if (!self->activator) + self->activator = self; + self->spawnflags |= 0x80000001; + self->svflags &= ~SVF_NOCLIENT; + target_laser_think (self); +} + +void target_laser_off (edict_t *self) +{ + self->spawnflags &= ~1; + self->svflags |= SVF_NOCLIENT; + self->nextthink = 0; +} + +void target_laser_use (edict_t *self, edict_t *other, edict_t *activator) +{ + self->activator = activator; + if (self->spawnflags & 1) + target_laser_off (self); + else + target_laser_on (self); +} + +void target_laser_start (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) + self->s.frame = 16; + else + self->s.frame = 4; + + // 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); + if (!ent) + 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); + } + } + 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); + + if (self->spawnflags & 1) + target_laser_on (self); + else + target_laser_off (self); +} + +void SP_target_laser (edict_t *self) +{ + // let everything else get spawned before we start firing + 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 +*/ + +void target_lightramp_think (edict_t *self) +{ + char style[2]; + + 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); + + if ((level.time - self->timestamp) < self->speed) + { + self->nextthink = level.time + FRAMETIME; + } + else if (self->spawnflags & 1) + { + char temp; + + temp = self->movedir[0]; + self->movedir[0] = self->movedir[1]; + self->movedir[1] = temp; + self->movedir[2] *= -1; + } +} + +void target_lightramp_use (edict_t *self, edict_t *other, edict_t *activator) +{ + if (!self->enemy) + { + edict_t *e; + + // check all the targets + e = NULL; + while (1) + { + 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)); + } + else + { + self->enemy = e; + } + } + + if (!self->enemy) + { + 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); +} + +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]) + { + gi.dprintf("target_lightramp has bad ramp (%s) at %s\n", self->message, vtos(self->s.origin)); + G_FreeEdict (self); + return; + } + + if (deathmatch->value) + { + 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); + return; + } + + self->svflags |= SVF_NOCLIENT; + self->use = target_lightramp_use; + self->think = target_lightramp_think; + + self->movedir[0] = self->message[0] - 'a'; + self->movedir[1] = self->message[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) +*/ + +void target_earthquake_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.0, ATTN_NONE, 0); + self->last_move_time = level.time + 0.5; + } + + 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[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) +{ + 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) +{ + if (!self->targetname) + 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; + + self->noise_index = gi.soundindex ("world/quake.wav"); +} diff --git a/game/g_trigger.c b/game/g_trigger.c new file mode 100644 index 000000000..53a1b6c73 --- /dev/null +++ b/game/g_trigger.c @@ -0,0 +1,598 @@ +/* +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. + +*/ +#include "g_local.h" + + +void InitTrigger (edict_t *self) +{ + if (!VectorCompare (self->s.angles, vec3_origin)) + G_SetMovedir (self->s.angles, self->movedir); + + self->solid = SOLID_TRIGGER; + self->movetype = MOVETYPE_NONE; + gi.setmodel (self, self->model); + self->svflags = SVF_NOCLIENT; +} + + +// the wait time has passed, so set back up for another activation +void multi_wait (edict_t *ent) +{ + ent->nextthink = 0; +} + + +// the trigger was just activated +// ent->activator should be set to the activator so it can be held through a delay +// so wait for the delay time before firing +void multi_trigger (edict_t *ent) +{ + if (ent->nextthink) + return; // already been triggered + + G_UseTargets (ent, ent->activator); + + if (ent->wait > 0) + { + ent->think = multi_wait; + ent->nextthink = level.time + ent->wait; + } + else + { // we can't just remove (self) here, because this is a touch function + // called while looping through area links... + ent->touch = NULL; + ent->nextthink = level.time + FRAMETIME; + ent->think = G_FreeEdict; + } +} + +void Use_Multi (edict_t *ent, edict_t *other, edict_t *activator) +{ + ent->activator = activator; + multi_trigger (ent); +} + +void Touch_Multi (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + if(other->client) + { + if (self->spawnflags & 2) + return; + } + else if (other->svflags & SVF_MONSTER) + { + if (!(self->spawnflags & 1)) + return; + } + else + return; + + if (!VectorCompare(self->movedir, vec3_origin)) + { + vec3_t forward; + + AngleVectors(other->s.angles, forward, NULL, NULL); + if (_DotProduct(forward, self->movedir) < 0) + return; + } + + self->activator = other; + multi_trigger (self); +} + +/*QUAKED trigger_multiple (.5 .5 .5) ? MONSTER NOT_PLAYER TRIGGERED +Variable sized repeatable trigger. Must be targeted at one or more entities. +If "delay" is set, the trigger waits some time after activating before firing. +"wait" : Seconds between triggerings. (.2 default) +sounds +1) secret +2) beep beep +3) large switch +4) +set "message" to text string +*/ +void trigger_enable (edict_t *self, edict_t *other, edict_t *activator) +{ + self->solid = SOLID_TRIGGER; + self->use = Use_Multi; + gi.linkentity (self); +} + +void SP_trigger_multiple (edict_t *ent) +{ + if (ent->sounds == 1) + ent->noise_index = gi.soundindex ("misc/secret.wav"); + else if (ent->sounds == 2) + ent->noise_index = gi.soundindex ("misc/talk.wav"); + else if (ent->sounds == 3) + ent->noise_index = gi.soundindex ("misc/trigger1.wav"); + + if (!ent->wait) + ent->wait = 0.2; + ent->touch = Touch_Multi; + ent->movetype = MOVETYPE_NONE; + ent->svflags |= SVF_NOCLIENT; + + + if (ent->spawnflags & 4) + { + ent->solid = SOLID_NOT; + ent->use = trigger_enable; + } + else + { + ent->solid = SOLID_TRIGGER; + ent->use = Use_Multi; + } + + if (!VectorCompare(ent->s.angles, vec3_origin)) + G_SetMovedir (ent->s.angles, ent->movedir); + + gi.setmodel (ent, ent->model); + gi.linkentity (ent); +} + + +/*QUAKED trigger_once (.5 .5 .5) ? x x TRIGGERED +Triggers once, then removes itself. +You must set the key "target" to the name of another object in the level that has a matching "targetname". + +If TRIGGERED, this trigger must be triggered before it is live. + +sounds + 1) secret + 2) beep beep + 3) large switch + 4) + +"message" string to be displayed when triggered +*/ + +void SP_trigger_once(edict_t *ent) +{ + // make old maps work because I messed up on flag assignments here + // triggered was on bit 1 when it should have been on bit 4 + if (ent->spawnflags & 1) + { + vec3_t v; + + VectorMA (ent->mins, 0.5, ent->size, v); + ent->spawnflags &= ~1; + ent->spawnflags |= 4; + gi.dprintf("fixed TRIGGERED flag on %s at %s\n", ent->classname, vtos(v)); + } + + ent->wait = -1; + SP_trigger_multiple (ent); +} + +/*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) +This fixed size trigger cannot be touched, it can only be fired by other events. +*/ +void trigger_relay_use (edict_t *self, edict_t *other, edict_t *activator) +{ + G_UseTargets (self, activator); +} + +void SP_trigger_relay (edict_t *self) +{ + self->use = trigger_relay_use; +} + + +/* +============================================================================== + +trigger_key + +============================================================================== +*/ + +/*QUAKED trigger_key (.5 .5 .5) (-8 -8 -8) (8 8 8) +A relay trigger that only fires it's targets if player has the proper key. +Use "item" to specify the required key, for example "key_data_cd" +*/ +void trigger_key_use (edict_t *self, edict_t *other, edict_t *activator) +{ + int index; + + if (!self->item) + return; + if (!activator->client) + return; + + index = ITEM_INDEX(self->item); + if (!activator->client->pers.inventory[index]) + { + if (level.time < self->touch_debounce_time) + return; + self->touch_debounce_time = level.time + 5.0; + gi.centerprintf (activator, "You need the %s", self->item->pickup_name); + gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/keytry.wav"), 1, ATTN_NORM, 0); + return; + } + + gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/keyuse.wav"), 1, ATTN_NORM, 0); + if (coop->value) + { + int player; + edict_t *ent; + + if (strcmp(self->item->classname, "key_power_cube") == 0) + { + int cube; + + for (cube = 0; cube < 8; cube++) + if (activator->client->pers.power_cubes & (1 << cube)) + break; + for (player = 1; player <= game.maxclients; player++) + { + ent = &g_edicts[player]; + if (!ent->inuse) + continue; + if (!ent->client) + continue; + if (ent->client->pers.power_cubes & (1 << cube)) + { + ent->client->pers.inventory[index]--; + ent->client->pers.power_cubes &= ~(1 << cube); + } + } + } + else + { + for (player = 1; player <= game.maxclients; player++) + { + ent = &g_edicts[player]; + if (!ent->inuse) + continue; + if (!ent->client) + continue; + ent->client->pers.inventory[index] = 0; + } + } + } + else + { + activator->client->pers.inventory[index]--; + } + + G_UseTargets (self, activator); + + self->use = NULL; +} + +void SP_trigger_key (edict_t *self) +{ + if (!st.item) + { + gi.dprintf("no key item for trigger_key at %s\n", vtos(self->s.origin)); + return; + } + self->item = FindItemByClassname (st.item); + + if (!self->item) + { + gi.dprintf("item %s not found for trigger_key at %s\n", st.item, vtos(self->s.origin)); + return; + } + + if (!self->target) + { + gi.dprintf("%s at %s has no target\n", self->classname, vtos(self->s.origin)); + return; + } + + gi.soundindex ("misc/keytry.wav"); + gi.soundindex ("misc/keyuse.wav"); + + self->use = trigger_key_use; +} + + +/* +============================================================================== + +trigger_counter + +============================================================================== +*/ + +/*QUAKED trigger_counter (.5 .5 .5) ? nomessage +Acts as an intermediary for an action that takes multiple inputs. + +If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished. + +After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself. +*/ + +void trigger_counter_use(edict_t *self, edict_t *other, edict_t *activator) +{ + if (self->count == 0) + return; + + self->count--; + + if (self->count) + { + if (! (self->spawnflags & 1)) + { + gi.centerprintf(activator, "%i more to go...", self->count); + gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); + } + return; + } + + if (! (self->spawnflags & 1)) + { + gi.centerprintf(activator, "Sequence completed!"); + gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); + } + self->activator = activator; + multi_trigger (self); +} + +void SP_trigger_counter (edict_t *self) +{ + self->wait = -1; + if (!self->count) + self->count = 2; + + self->use = trigger_counter_use; +} + + +/* +============================================================================== + +trigger_always + +============================================================================== +*/ + +/*QUAKED trigger_always (.5 .5 .5) (-8 -8 -8) (8 8 8) +This trigger will always fire. It is activated by the world. +*/ +void SP_trigger_always (edict_t *ent) +{ + // we must have some delay to make sure our use targets are present + if (ent->delay < 0.2) + ent->delay = 0.2; + G_UseTargets(ent, ent); +} + + +/* +============================================================================== + +trigger_push + +============================================================================== +*/ + +#define PUSH_ONCE 1 + +static int windsound; + +void trigger_push_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + if (strcmp(other->classname, "grenade") == 0) + { + VectorScale (self->movedir, self->speed * 10, other->velocity); + } + else if (other->health > 0) + { + VectorScale (self->movedir, self->speed * 10, other->velocity); + + if (other->client) + { + // don't take falling damage immediately from this + VectorCopy (other->velocity, other->client->oldvelocity); + if (other->fly_sound_debounce_time < level.time) + { + other->fly_sound_debounce_time = level.time + 1.5; + gi.sound (other, CHAN_AUTO, windsound, 1, ATTN_NORM, 0); + } + } + } + if (self->spawnflags & PUSH_ONCE) + G_FreeEdict (self); +} + + +/*QUAKED trigger_push (.5 .5 .5) ? PUSH_ONCE +Pushes the player +"speed" defaults to 1000 +*/ +void SP_trigger_push (edict_t *self) +{ + InitTrigger (self); + windsound = gi.soundindex ("misc/windfly.wav"); + self->touch = trigger_push_touch; + if (!self->speed) + self->speed = 1000; + gi.linkentity (self); +} + + +/* +============================================================================== + +trigger_hurt + +============================================================================== +*/ + +/*QUAKED trigger_hurt (.5 .5 .5) ? START_OFF TOGGLE SILENT NO_PROTECTION SLOW +Any entity that touches this will be hurt. + +It does dmg points of damage each server frame + +SILENT supresses playing the sound +SLOW changes the damage rate to once per second +NO_PROTECTION *nothing* stops the damage + +"dmg" default 5 (whole numbers only) + +*/ +void hurt_use (edict_t *self, edict_t *other, edict_t *activator) +{ + if (self->solid == SOLID_NOT) + self->solid = SOLID_TRIGGER; + else + self->solid = SOLID_NOT; + gi.linkentity (self); + + if (!(self->spawnflags & 2)) + self->use = NULL; +} + + +void hurt_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + int dflags; + + if (!other->takedamage) + return; + + if (self->timestamp > level.time) + return; + + if (self->spawnflags & 16) + self->timestamp = level.time + 1; + else + self->timestamp = level.time + FRAMETIME; + + if (!(self->spawnflags & 4)) + { + if ((level.framenum % 10) == 0) + gi.sound (other, CHAN_AUTO, self->noise_index, 1, ATTN_NORM, 0); + } + + if (self->spawnflags & 8) + dflags = DAMAGE_NO_PROTECTION; + else + dflags = 0; + T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, self->dmg, dflags, MOD_TRIGGER_HURT); +} + +void SP_trigger_hurt (edict_t *self) +{ + InitTrigger (self); + + self->noise_index = gi.soundindex ("world/electro.wav"); + self->touch = hurt_touch; + + if (!self->dmg) + self->dmg = 5; + + if (self->spawnflags & 1) + self->solid = SOLID_NOT; + else + self->solid = SOLID_TRIGGER; + + if (self->spawnflags & 2) + self->use = hurt_use; + + gi.linkentity (self); +} + + +/* +============================================================================== + +trigger_gravity + +============================================================================== +*/ + +/*QUAKED trigger_gravity (.5 .5 .5) ? +Changes the touching entites gravity to +the value of "gravity". 1.0 is standard +gravity for the level. +*/ + +void trigger_gravity_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + other->gravity = self->gravity; +} + +void SP_trigger_gravity (edict_t *self) +{ + if (st.gravity == 0) + { + gi.dprintf("trigger_gravity without gravity set at %s\n", vtos(self->s.origin)); + G_FreeEdict (self); + return; + } + + InitTrigger (self); + self->gravity = atoi(st.gravity); + self->touch = trigger_gravity_touch; +} + + +/* +============================================================================== + +trigger_monsterjump + +============================================================================== +*/ + +/*QUAKED trigger_monsterjump (.5 .5 .5) ? +Walking monsters that touch this will jump in the direction of the trigger's angle +"speed" default to 200, the speed thrown forward +"height" default to 200, the speed thrown upwards +*/ + +void trigger_monsterjump_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + if (other->flags & (FL_FLY | FL_SWIM) ) + return; + if (other->svflags & SVF_DEADMONSTER) + return; + if ( !(other->svflags & SVF_MONSTER)) + return; + +// set XY even if not on ground, so the jump will clear lips + other->velocity[0] = self->movedir[0] * self->speed; + other->velocity[1] = self->movedir[1] * self->speed; + + if (!other->groundentity) + return; + + other->groundentity = NULL; + other->velocity[2] = self->movedir[2]; +} + +void SP_trigger_monsterjump (edict_t *self) +{ + if (!self->speed) + self->speed = 200; + if (!st.height) + st.height = 200; + if (self->s.angles[YAW] == 0) + self->s.angles[YAW] = 360; + InitTrigger (self); + self->touch = trigger_monsterjump_touch; + self->movedir[2] = st.height; +} + diff --git a/game/g_turret.c b/game/g_turret.c new file mode 100644 index 000000000..0153fd939 --- /dev/null +++ b/game/g_turret.c @@ -0,0 +1,432 @@ +/* +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. + +*/ +// g_turret.c + +#include "g_local.h" + + +void AnglesNormalize(vec3_t vec) +{ + while(vec[0] > 360) + vec[0] -= 360; + while(vec[0] < 0) + vec[0] += 360; + while(vec[1] > 360) + vec[1] -= 360; + while(vec[1] < 0) + vec[1] += 360; +} + +float SnapToEights(float x) +{ + x *= 8.0; + if (x > 0.0) + x += 0.5; + else + x -= 0.5; + return 0.125 * (int)x; +} + + +void turret_blocked(edict_t *self, edict_t *other) +{ + edict_t *attacker; + + if (other->takedamage) + { + if (self->teammaster->owner) + attacker = self->teammaster->owner; + else + attacker = self->teammaster; + T_Damage (other, self, attacker, vec3_origin, other->s.origin, vec3_origin, self->teammaster->dmg, 10, 0, MOD_CRUSH); + } +} + +/*QUAKED turret_breach (0 0 0) ? +This portion of the turret can change both pitch and yaw. +The model should be made with a flat pitch. +It (and the associated base) need to be oriented towards 0. +Use "angle" to set the starting angle. + +"speed" default 50 +"dmg" default 10 +"angle" point this forward +"target" point this at an info_notnull at the muzzle tip +"minpitch" min acceptable pitch angle : default -30 +"maxpitch" max acceptable pitch angle : default 30 +"minyaw" min acceptable yaw angle : default 0 +"maxyaw" max acceptable yaw angle : default 360 +*/ + +void turret_breach_fire (edict_t *self) +{ + vec3_t f, r, u; + vec3_t start; + int damage; + int speed; + + AngleVectors (self->s.angles, f, r, u); + VectorMA (self->s.origin, self->move_origin[0], f, start); + VectorMA (start, self->move_origin[1], r, start); + VectorMA (start, self->move_origin[2], u, start); + + damage = 100 + random() * 50; + speed = 550 + 50 * skill->value; + fire_rocket (self->teammaster->owner, start, f, damage, speed, 150, damage); + gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/rocklf1a.wav"), 1, ATTN_NORM, 0); +} + +void turret_breach_think (edict_t *self) +{ + edict_t *ent; + vec3_t current_angles; + vec3_t delta; + + VectorCopy (self->s.angles, current_angles); + AnglesNormalize(current_angles); + + AnglesNormalize(self->move_angles); + if (self->move_angles[PITCH] > 180) + self->move_angles[PITCH] -= 360; + + // clamp angles to mins & maxs + if (self->move_angles[PITCH] > self->pos1[PITCH]) + self->move_angles[PITCH] = self->pos1[PITCH]; + else if (self->move_angles[PITCH] < self->pos2[PITCH]) + self->move_angles[PITCH] = self->pos2[PITCH]; + + if ((self->move_angles[YAW] < self->pos1[YAW]) || (self->move_angles[YAW] > self->pos2[YAW])) + { + float dmin, dmax; + + dmin = fabs(self->pos1[YAW] - self->move_angles[YAW]); + if (dmin < -180) + dmin += 360; + else if (dmin > 180) + dmin -= 360; + dmax = fabs(self->pos2[YAW] - self->move_angles[YAW]); + if (dmax < -180) + dmax += 360; + else if (dmax > 180) + dmax -= 360; + if (fabs(dmin) < fabs(dmax)) + self->move_angles[YAW] = self->pos1[YAW]; + else + self->move_angles[YAW] = self->pos2[YAW]; + } + + VectorSubtract (self->move_angles, current_angles, delta); + if (delta[0] < -180) + delta[0] += 360; + else if (delta[0] > 180) + delta[0] -= 360; + if (delta[1] < -180) + delta[1] += 360; + else if (delta[1] > 180) + delta[1] -= 360; + delta[2] = 0; + + if (delta[0] > self->speed * FRAMETIME) + delta[0] = self->speed * FRAMETIME; + if (delta[0] < -1 * self->speed * FRAMETIME) + delta[0] = -1 * self->speed * FRAMETIME; + if (delta[1] > self->speed * FRAMETIME) + delta[1] = self->speed * FRAMETIME; + if (delta[1] < -1 * self->speed * FRAMETIME) + delta[1] = -1 * self->speed * FRAMETIME; + + VectorScale (delta, 1.0/FRAMETIME, self->avelocity); + + self->nextthink = level.time + FRAMETIME; + + for (ent = self->teammaster; ent; ent = ent->teamchain) + ent->avelocity[1] = self->avelocity[1]; + + // if we have adriver, adjust his velocities + if (self->owner) + { + float angle; + float target_z; + float diff; + vec3_t target; + vec3_t dir; + + // angular is easy, just copy ours + self->owner->avelocity[0] = self->avelocity[0]; + self->owner->avelocity[1] = self->avelocity[1]; + + // x & y + angle = self->s.angles[1] + self->owner->move_origin[1]; + angle *= (M_PI*2 / 360); + target[0] = SnapToEights(self->s.origin[0] + cos(angle) * self->owner->move_origin[0]); + target[1] = SnapToEights(self->s.origin[1] + sin(angle) * self->owner->move_origin[0]); + target[2] = self->owner->s.origin[2]; + + VectorSubtract (target, self->owner->s.origin, dir); + self->owner->velocity[0] = dir[0] * 1.0 / FRAMETIME; + self->owner->velocity[1] = dir[1] * 1.0 / FRAMETIME; + + // z + angle = self->s.angles[PITCH] * (M_PI*2 / 360); + target_z = SnapToEights(self->s.origin[2] + self->owner->move_origin[0] * tan(angle) + self->owner->move_origin[2]); + + diff = target_z - self->owner->s.origin[2]; + self->owner->velocity[2] = diff * 1.0 / FRAMETIME; + + if (self->spawnflags & 65536) + { + turret_breach_fire (self); + self->spawnflags &= ~65536; + } + } +} + +void turret_breach_finish_init (edict_t *self) +{ + // get and save info for muzzle location + if (!self->target) + { + gi.dprintf("%s at %s needs a target\n", self->classname, vtos(self->s.origin)); + } + else + { + self->target_ent = G_PickTarget (self->target); + VectorSubtract (self->target_ent->s.origin, self->s.origin, self->move_origin); + G_FreeEdict(self->target_ent); + } + + self->teammaster->dmg = self->dmg; + self->think = turret_breach_think; + self->think (self); +} + +void SP_turret_breach (edict_t *self) +{ + self->solid = SOLID_BSP; + self->movetype = MOVETYPE_PUSH; + gi.setmodel (self, self->model); + + if (!self->speed) + self->speed = 50; + if (!self->dmg) + self->dmg = 10; + + if (!st.minpitch) + st.minpitch = -30; + if (!st.maxpitch) + st.maxpitch = 30; + if (!st.maxyaw) + st.maxyaw = 360; + + self->pos1[PITCH] = -1 * st.minpitch; + self->pos1[YAW] = st.minyaw; + self->pos2[PITCH] = -1 * st.maxpitch; + self->pos2[YAW] = st.maxyaw; + + self->ideal_yaw = self->s.angles[YAW]; + self->move_angles[YAW] = self->ideal_yaw; + + self->blocked = turret_blocked; + + self->think = turret_breach_finish_init; + self->nextthink = level.time + FRAMETIME; + gi.linkentity (self); +} + + +/*QUAKED turret_base (0 0 0) ? +This portion of the turret changes yaw only. +MUST be teamed with a turret_breach. +*/ + +void SP_turret_base (edict_t *self) +{ + self->solid = SOLID_BSP; + self->movetype = MOVETYPE_PUSH; + gi.setmodel (self, self->model); + self->blocked = turret_blocked; + gi.linkentity (self); +} + + +/*QUAKED turret_driver (1 .5 0) (-16 -16 -24) (16 16 32) +Must NOT be on the team with the rest of the turret parts. +Instead it must target the turret_breach. +*/ + +void infantry_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage); +void infantry_stand (edict_t *self); +void monster_use (edict_t *self, edict_t *other, edict_t *activator); + +void turret_driver_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + edict_t *ent; + + // level the gun + self->target_ent->move_angles[0] = 0; + + // remove the driver from the end of them team chain + for (ent = self->target_ent->teammaster; ent->teamchain != self; ent = ent->teamchain) + ; + ent->teamchain = NULL; + self->teammaster = NULL; + self->flags &= ~FL_TEAMSLAVE; + + self->target_ent->owner = NULL; + self->target_ent->teammaster->owner = NULL; + + infantry_die (self, inflictor, attacker, damage); +} + +qboolean FindTarget (edict_t *self); + +void turret_driver_think (edict_t *self) +{ + vec3_t target; + vec3_t dir; + float reaction_time; + + self->nextthink = level.time + FRAMETIME; + + if (self->enemy && (!self->enemy->inuse || self->enemy->health <= 0)) + self->enemy = NULL; + + if (!self->enemy) + { + if (!FindTarget (self)) + return; + self->monsterinfo.trail_time = level.time; + self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; + } + else + { + if (visible (self, self->enemy)) + { + if (self->monsterinfo.aiflags & AI_LOST_SIGHT) + { + self->monsterinfo.trail_time = level.time; + self->monsterinfo.aiflags &= ~AI_LOST_SIGHT; + } + } + else + { + self->monsterinfo.aiflags |= AI_LOST_SIGHT; + return; + } + } + + // let the turret know where we want it to aim + VectorCopy (self->enemy->s.origin, target); + target[2] += self->enemy->viewheight; + VectorSubtract (target, self->target_ent->s.origin, dir); + vectoangles (dir, self->target_ent->move_angles); + + // decide if we should shoot + if (level.time < self->monsterinfo.attack_finished) + return; + + reaction_time = (3 - skill->value) * 1.0; + if ((level.time - self->monsterinfo.trail_time) < reaction_time) + return; + + self->monsterinfo.attack_finished = level.time + reaction_time + 1.0; + //FIXME how do we really want to pass this along? + self->target_ent->spawnflags |= 65536; +} + +void turret_driver_link (edict_t *self) +{ + vec3_t vec; + edict_t *ent; + + self->think = turret_driver_think; + self->nextthink = level.time + FRAMETIME; + + self->target_ent = G_PickTarget (self->target); + self->target_ent->owner = self; + self->target_ent->teammaster->owner = self; + VectorCopy (self->target_ent->s.angles, self->s.angles); + + vec[0] = self->target_ent->s.origin[0] - self->s.origin[0]; + vec[1] = self->target_ent->s.origin[1] - self->s.origin[1]; + vec[2] = 0; + self->move_origin[0] = VectorLength(vec); + + VectorSubtract (self->s.origin, self->target_ent->s.origin, vec); + vectoangles (vec, vec); + AnglesNormalize(vec); + self->move_origin[1] = vec[1]; + + self->move_origin[2] = self->s.origin[2] - self->target_ent->s.origin[2]; + + // add the driver to the end of them team chain + for (ent = self->target_ent->teammaster; ent->teamchain; ent = ent->teamchain) + ; + ent->teamchain = self; + self->teammaster = self->target_ent->teammaster; + self->flags |= FL_TEAMSLAVE; +} + +void SP_turret_driver (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + self->movetype = MOVETYPE_PUSH; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2"); + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 32); + + self->health = 100; + self->gib_health = 0; + self->mass = 200; + self->viewheight = 24; + + self->die = turret_driver_die; + self->monsterinfo.stand = infantry_stand; + + self->flags |= FL_NO_KNOCKBACK; + + level.total_monsters++; + + self->svflags |= SVF_MONSTER; + self->s.renderfx |= RF_FRAMELERP; + self->takedamage = DAMAGE_AIM; + self->use = monster_use; + self->clipmask = MASK_MONSTERSOLID; + VectorCopy (self->s.origin, self->s.old_origin); + self->monsterinfo.aiflags |= AI_STAND_GROUND|AI_DUCKED; + + if (st.item) + { + self->item = FindItemByClassname (st.item); + if (!self->item) + gi.dprintf("%s at %s has bad item: %s\n", self->classname, vtos(self->s.origin), st.item); + } + + self->think = turret_driver_link; + self->nextthink = level.time + FRAMETIME; + + gi.linkentity (self); +} diff --git a/game/g_utils.c b/game/g_utils.c new file mode 100644 index 000000000..af2e645b7 --- /dev/null +++ b/game/g_utils.c @@ -0,0 +1,568 @@ +/* +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. + +*/ +// g_utils.c -- misc utility functions for game module + +#include "g_local.h" + + +void G_ProjectSource (vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result) +{ + result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1]; + result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1]; + result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] + distance[2]; +} + + +/* +============= +G_Find + +Searches all active entities for the next one that holds +the matching string at fieldofs (use the FOFS() macro) in the structure. + +Searches beginning at the edict after from, or the beginning if NULL +NULL will be returned if the end of the list is reached. + +============= +*/ +edict_t *G_Find (edict_t *from, int fieldofs, char *match) +{ + char *s; + + if (!from) + from = g_edicts; + else + from++; + + for ( ; from < &g_edicts[globals.num_edicts] ; from++) + { + if (!from->inuse) + continue; + s = *(char **) ((byte *)from + fieldofs); + if (!s) + continue; + if (!Q_stricmp (s, match)) + return from; + } + + return NULL; +} + + +/* +================= +findradius + +Returns entities that have origins within a spherical area + +findradius (origin, radius) +================= +*/ +edict_t *findradius (edict_t *from, vec3_t org, float rad) +{ + vec3_t eorg; + int j; + + if (!from) + from = g_edicts; + else + from++; + for ( ; from < &g_edicts[globals.num_edicts]; from++) + { + if (!from->inuse) + continue; + if (from->solid == SOLID_NOT) + continue; + for (j=0 ; j<3 ; j++) + eorg[j] = org[j] - (from->s.origin[j] + (from->mins[j] + from->maxs[j])*0.5); + if (VectorLength(eorg) > rad) + continue; + return from; + } + + return NULL; +} + + +/* +============= +G_PickTarget + +Searches all active entities for the next one that holds +the matching string at fieldofs (use the FOFS() macro) in the structure. + +Searches beginning at the edict after from, or the beginning if NULL +NULL will be returned if the end of the list is reached. + +============= +*/ +#define MAXCHOICES 8 + +edict_t *G_PickTarget (char *targetname) +{ + edict_t *ent = NULL; + int num_choices = 0; + edict_t *choice[MAXCHOICES]; + + if (!targetname) + { + gi.dprintf("G_PickTarget called with NULL targetname\n"); + return NULL; + } + + while(1) + { + ent = G_Find (ent, FOFS(targetname), targetname); + if (!ent) + break; + choice[num_choices++] = ent; + if (num_choices == MAXCHOICES) + break; + } + + if (!num_choices) + { + gi.dprintf("G_PickTarget: target %s not found\n", targetname); + return NULL; + } + + return choice[rand() % num_choices]; +} + + + +void Think_Delay (edict_t *ent) +{ + G_UseTargets (ent, ent->activator); + G_FreeEdict (ent); +} + +/* +============================== +G_UseTargets + +the global "activator" should be set to the entity that initiated the firing. + +If self.delay is set, a DelayedUse entity will be created that will actually +do the SUB_UseTargets after that many seconds have passed. + +Centerprints any self.message to the activator. + +Search for (string)targetname in all entities that +match (string)self.target and call their .use function + +============================== +*/ +void G_UseTargets (edict_t *ent, edict_t *activator) +{ + edict_t *t; + +// +// check for a delay +// + if (ent->delay) + { + // create a temp object to fire at a later time + t = G_Spawn(); + t->classname = "DelayedUse"; + t->nextthink = level.time + ent->delay; + t->think = Think_Delay; + t->activator = activator; + if (!activator) + gi.dprintf ("Think_Delay with no activator\n"); + t->message = ent->message; + t->target = ent->target; + t->killtarget = ent->killtarget; + return; + } + + +// +// print the message +// + if ((ent->message) && !(activator->svflags & SVF_MONSTER)) + { + gi.centerprintf (activator, "%s", ent->message); + if (ent->noise_index) + gi.sound (activator, CHAN_AUTO, ent->noise_index, 1, ATTN_NORM, 0); + else + gi.sound (activator, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0); + } + +// +// kill killtargets +// + if (ent->killtarget) + { + t = NULL; + while ((t = G_Find (t, FOFS(targetname), ent->killtarget))) + { + G_FreeEdict (t); + if (!ent->inuse) + { + gi.dprintf("entity was removed while using killtargets\n"); + return; + } + } + } + +// +// fire targets +// + if (ent->target) + { + t = NULL; + while ((t = G_Find (t, FOFS(targetname), ent->target))) + { + // doors fire area portals in a specific way + if (!Q_stricmp(t->classname, "func_areaportal") && + (!Q_stricmp(ent->classname, "func_door") || !Q_stricmp(ent->classname, "func_door_rotating"))) + continue; + + if (t == ent) + { + gi.dprintf ("WARNING: Entity used itself.\n"); + } + else + { + if (t->use) + t->use (t, ent, activator); + } + if (!ent->inuse) + { + gi.dprintf("entity was removed while using targets\n"); + return; + } + } + } +} + + +/* +============= +TempVector + +This is just a convenience function +for making temporary vectors for function calls +============= +*/ +float *tv (float x, float y, float z) +{ + static int index; + static vec3_t vecs[8]; + float *v; + + // use an array so that multiple tempvectors won't collide + // for a while + v = vecs[index]; + index = (index + 1)&7; + + v[0] = x; + v[1] = y; + v[2] = z; + + return v; +} + + +/* +============= +VectorToString + +This is just a convenience function +for printing vectors +============= +*/ +char *vtos (vec3_t v) +{ + static int index; + static char str[8][32]; + char *s; + + // use an array so that multiple vtos won't collide + s = str[index]; + index = (index + 1)&7; + + Com_sprintf (s, 32, "(%i %i %i)", (int)v[0], (int)v[1], (int)v[2]); + + return s; +} + + +vec3_t VEC_UP = {0, -1, 0}; +vec3_t MOVEDIR_UP = {0, 0, 1}; +vec3_t VEC_DOWN = {0, -2, 0}; +vec3_t MOVEDIR_DOWN = {0, 0, -1}; + +void G_SetMovedir (vec3_t angles, vec3_t movedir) +{ + if (VectorCompare (angles, VEC_UP)) + { + VectorCopy (MOVEDIR_UP, movedir); + } + else if (VectorCompare (angles, VEC_DOWN)) + { + VectorCopy (MOVEDIR_DOWN, movedir); + } + else + { + AngleVectors (angles, movedir, NULL, NULL); + } + + VectorClear (angles); +} + + +float vectoyaw (vec3_t vec) +{ + float yaw; + + if (/*vec[YAW] == 0 &&*/ vec[PITCH] == 0) + { + yaw = 0; + if (vec[YAW] > 0) + yaw = 90; + else if (vec[YAW] < 0) + yaw = -90; + } + else + { + yaw = (int) (atan2(vec[YAW], vec[PITCH]) * 180 / M_PI); + if (yaw < 0) + yaw += 360; + } + + return yaw; +} + + +void vectoangles (vec3_t value1, vec3_t angles) +{ + float forward; + float yaw, pitch; + + if (value1[1] == 0 && value1[0] == 0) + { + yaw = 0; + if (value1[2] > 0) + pitch = 90; + else + pitch = 270; + } + else + { + if (value1[0]) + yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); + else if (value1[1] > 0) + yaw = 90; + else + yaw = -90; + if (yaw < 0) + yaw += 360; + + forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]); + pitch = (int) (atan2(value1[2], forward) * 180 / M_PI); + if (pitch < 0) + pitch += 360; + } + + angles[PITCH] = -pitch; + angles[YAW] = yaw; + angles[ROLL] = 0; +} + +char *G_CopyString (char *in) +{ + char *out; + + out = gi.TagMalloc (strlen(in)+1, TAG_LEVEL); + strcpy (out, in); + return out; +} + + +void G_InitEdict (edict_t *e) +{ + e->inuse = true; + e->classname = "noclass"; + e->gravity = 1.0; + e->s.number = e - g_edicts; +} + +/* +================= +G_Spawn + +Either finds a free edict, or allocates a new one. +Try to avoid reusing an entity that was recently freed, because it +can cause the client to think the entity morphed into something else +instead of being removed and recreated, which can cause interpolated +angles and bad trails. +================= +*/ +edict_t *G_Spawn (void) +{ + int i; + edict_t *e; + + e = &g_edicts[(int)maxclients->value+1]; + for ( i=maxclients->value+1 ; iinuse && ( e->freetime < 2 || level.time - e->freetime > 0.5 ) ) + { + G_InitEdict (e); + return e; + } + } + + if (i == game.maxentities) + gi.error ("ED_Alloc: no free edicts"); + + globals.num_edicts++; + G_InitEdict (e); + return e; +} + +/* +================= +G_FreeEdict + +Marks the edict as free +================= +*/ +void G_FreeEdict (edict_t *ed) +{ + gi.unlinkentity (ed); // unlink from world + + if ((ed - g_edicts) <= (maxclients->value + BODY_QUEUE_SIZE)) + { +// gi.dprintf("tried to free special edict\n"); + return; + } + + memset (ed, 0, sizeof(*ed)); + ed->classname = "freed"; + ed->freetime = level.time; + ed->inuse = false; +} + + +/* +============ +G_TouchTriggers + +============ +*/ +void G_TouchTriggers (edict_t *ent) +{ + int i, num; + edict_t *touch[MAX_EDICTS], *hit; + + // dead things don't activate triggers! + if ((ent->client || (ent->svflags & SVF_MONSTER)) && (ent->health <= 0)) + return; + + num = gi.BoxEdicts (ent->absmin, ent->absmax, touch + , MAX_EDICTS, AREA_TRIGGERS); + + // be careful, it is possible to have an entity in this + // list removed before we get to it (killtriggered) + for (i=0 ; iinuse) + continue; + if (!hit->touch) + continue; + hit->touch (hit, ent, NULL, NULL); + } +} + +/* +============ +G_TouchSolids + +Call after linking a new trigger in during gameplay +to force all entities it covers to immediately touch it +============ +*/ +void G_TouchSolids (edict_t *ent) +{ + int i, num; + edict_t *touch[MAX_EDICTS], *hit; + + num = gi.BoxEdicts (ent->absmin, ent->absmax, touch + , MAX_EDICTS, AREA_SOLID); + + // be careful, it is possible to have an entity in this + // list removed before we get to it (killtriggered) + for (i=0 ; iinuse) + continue; + if (ent->touch) + ent->touch (hit, ent, NULL, NULL); + if (!ent->inuse) + break; + } +} + + + + +/* +============================================================================== + +Kill box + +============================================================================== +*/ + +/* +================= +KillBox + +Kills all entities that would touch the proposed new positioning +of ent. Ent should be unlinked before calling this! +================= +*/ +qboolean KillBox (edict_t *ent) +{ + trace_t tr; + + while (1) + { + tr = gi.trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, NULL, MASK_PLAYERSOLID); + if (!tr.ent) + break; + + // nail it + T_Damage (tr.ent, ent, ent, vec3_origin, ent->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG); + + // if we didn't kill it, fail + if (tr.ent->solid) + return false; + } + + return true; // all clear +} diff --git a/game/g_weapon.c b/game/g_weapon.c new file mode 100644 index 000000000..de985cfb1 --- /dev/null +++ b/game/g_weapon.c @@ -0,0 +1,916 @@ +/* +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. + +*/ +#include "g_local.h" + + +/* +================= +check_dodge + +This is a support routine used when a client is firing +a non-instant attack weapon. It checks to see if a +monster's dodge function should be called. +================= +*/ +static void check_dodge (edict_t *self, vec3_t start, vec3_t dir, int speed) +{ + vec3_t end; + vec3_t v; + trace_t tr; + float eta; + + // easy mode only ducks one quarter the time + if (skill->value == 0) + { + if (random() > 0.25) + return; + } + VectorMA (start, 8192, dir, end); + tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT); + if ((tr.ent) && (tr.ent->svflags & SVF_MONSTER) && (tr.ent->health > 0) && (tr.ent->monsterinfo.dodge) && infront(tr.ent, self)) + { + VectorSubtract (tr.endpos, start, v); + eta = (VectorLength(v) - tr.ent->maxs[0]) / speed; + tr.ent->monsterinfo.dodge (tr.ent, self, eta); + } +} + + +/* +================= +fire_hit + +Used for all impact (hit/punch/slash) attacks +================= +*/ +qboolean fire_hit (edict_t *self, vec3_t aim, int damage, int kick) +{ + trace_t tr; + vec3_t forward, right, up; + vec3_t v; + vec3_t point; + float range; + vec3_t dir; + + //see if enemy is in range + VectorSubtract (self->enemy->s.origin, self->s.origin, dir); + range = VectorLength(dir); + if (range > aim[0]) + return false; + + if (aim[1] > self->mins[0] && aim[1] < self->maxs[0]) + { + // the hit is straight on so back the range up to the edge of their bbox + range -= self->enemy->maxs[0]; + } + else + { + // this is a side hit so adjust the "right" value out to the edge of their bbox + if (aim[1] < 0) + aim[1] = self->enemy->mins[0]; + else + aim[1] = self->enemy->maxs[0]; + } + + VectorMA (self->s.origin, range, dir, point); + + tr = gi.trace (self->s.origin, NULL, NULL, point, self, MASK_SHOT); + if (tr.fraction < 1) + { + if (!tr.ent->takedamage) + return false; + // if it will hit any client/monster then hit the one we wanted to hit + if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client)) + tr.ent = self->enemy; + } + + AngleVectors(self->s.angles, forward, right, up); + VectorMA (self->s.origin, range, forward, point); + VectorMA (point, aim[1], right, point); + VectorMA (point, aim[2], up, point); + VectorSubtract (point, self->enemy->s.origin, dir); + + // do the damage + T_Damage (tr.ent, self, self, dir, point, vec3_origin, damage, kick/2, DAMAGE_NO_KNOCKBACK, MOD_HIT); + + if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client)) + return false; + + // do our special form of knockback here + VectorMA (self->enemy->absmin, 0.5, self->enemy->size, v); + VectorSubtract (v, point, v); + VectorNormalize (v); + VectorMA (self->enemy->velocity, kick, v, self->enemy->velocity); + if (self->enemy->velocity[2] > 0) + self->enemy->groundentity = NULL; + return true; +} + + +/* +================= +fire_lead + +This is an internal support routine used for bullet/pellet based weapons. +================= +*/ +static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread, int mod) +{ + trace_t tr; + vec3_t dir; + vec3_t forward, right, up; + vec3_t end; + float r; + float u; + vec3_t water_start; + qboolean water = false; + int content_mask = MASK_SHOT | MASK_WATER; + + tr = gi.trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT); + if (!(tr.fraction < 1.0)) + { + vectoangles (aimdir, dir); + AngleVectors (dir, forward, right, up); + + r = crandom()*hspread; + u = crandom()*vspread; + VectorMA (start, 8192, forward, end); + VectorMA (end, r, right, end); + VectorMA (end, u, up, end); + + if (gi.pointcontents (start) & MASK_WATER) + { + water = true; + VectorCopy (start, water_start); + content_mask &= ~MASK_WATER; + } + + tr = gi.trace (start, NULL, NULL, end, self, content_mask); + + // see if we hit water + if (tr.contents & MASK_WATER) + { + int color; + + water = true; + VectorCopy (tr.endpos, water_start); + + if (!VectorCompare (start, tr.endpos)) + { + if (tr.contents & CONTENTS_WATER) + { + if (strcmp(tr.surface->name, "*brwater") == 0) + color = SPLASH_BROWN_WATER; + else + color = SPLASH_BLUE_WATER; + } + else if (tr.contents & CONTENTS_SLIME) + color = SPLASH_SLIME; + else if (tr.contents & CONTENTS_LAVA) + color = SPLASH_LAVA; + else + color = SPLASH_UNKNOWN; + + if (color != SPLASH_UNKNOWN) + { + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_SPLASH); + gi.WriteByte (8); + gi.WritePosition (tr.endpos); + gi.WriteDir (tr.plane.normal); + gi.WriteByte (color); + gi.multicast (tr.endpos, MULTICAST_PVS); + } + + // change bullet's course when it enters water + VectorSubtract (end, start, dir); + vectoangles (dir, dir); + AngleVectors (dir, forward, right, up); + r = crandom()*hspread*2; + u = crandom()*vspread*2; + VectorMA (water_start, 8192, forward, end); + VectorMA (end, r, right, end); + VectorMA (end, u, up, end); + } + + // re-trace ignoring water this time + tr = gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT); + } + } + + // send gun puff / flash + if (!((tr.surface) && (tr.surface->flags & SURF_SKY))) + { + if (tr.fraction < 1.0) + { + if (tr.ent->takedamage) + { + T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, mod); + } + else + { + if (strncmp (tr.surface->name, "sky", 3) != 0) + { + gi.WriteByte (svc_temp_entity); + gi.WriteByte (te_impact); + gi.WritePosition (tr.endpos); + gi.WriteDir (tr.plane.normal); + gi.multicast (tr.endpos, MULTICAST_PVS); + + if (self->client) + PlayerNoise(self, tr.endpos, PNOISE_IMPACT); + } + } + } + } + + // if went through water, determine where the end and make a bubble trail + if (water) + { + vec3_t pos; + + VectorSubtract (tr.endpos, water_start, dir); + VectorNormalize (dir); + VectorMA (tr.endpos, -2, dir, pos); + if (gi.pointcontents (pos) & MASK_WATER) + VectorCopy (pos, tr.endpos); + else + tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER); + + VectorAdd (water_start, tr.endpos, pos); + VectorScale (pos, 0.5, pos); + + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_BUBBLETRAIL); + gi.WritePosition (water_start); + gi.WritePosition (tr.endpos); + gi.multicast (pos, MULTICAST_PVS); + } +} + + +/* +================= +fire_bullet + +Fires a single round. Used for machinegun and chaingun. Would be fine for +pistols, rifles, etc.... +================= +*/ +void fire_bullet (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod) +{ + fire_lead (self, start, aimdir, damage, kick, TE_GUNSHOT, hspread, vspread, mod); +} + + +/* +================= +fire_shotgun + +Shoots shotgun pellets. Used by shotgun and super shotgun. +================= +*/ +void fire_shotgun (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int mod) +{ + int i; + + for (i = 0; i < count; i++) + fire_lead (self, start, aimdir, damage, kick, TE_SHOTGUN, hspread, vspread, mod); +} + + +/* +================= +fire_blaster + +Fires a single blaster bolt. Used by the blaster and hyper blaster. +================= +*/ +void blaster_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + int mod; + + if (other == self->owner) + return; + + if (surf && (surf->flags & SURF_SKY)) + { + G_FreeEdict (self); + return; + } + + if (self->owner->client) + PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); + + if (other->takedamage) + { + if (self->spawnflags & 1) + mod = MOD_HYPERBLASTER; + else + mod = MOD_BLASTER; + T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod); + } + else + { + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_BLASTER); + gi.WritePosition (self->s.origin); + if (!plane) + gi.WriteDir (vec3_origin); + else + gi.WriteDir (plane->normal); + gi.multicast (self->s.origin, MULTICAST_PVS); + } + + G_FreeEdict (self); +} + +void fire_blaster (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int effect, qboolean hyper) +{ + edict_t *bolt; + trace_t tr; + + VectorNormalize (dir); + + bolt = G_Spawn(); + bolt->svflags = SVF_DEADMONSTER; + // yes, I know it looks weird that projectiles are deadmonsters + // what this means is that when prediction is used against the object + // (blaster/hyperblaster shots), the player won't be solid clipped against + // the object. Right now trying to run into a firing hyperblaster + // is very jerky since you are predicted 'against' the shots. + VectorCopy (start, bolt->s.origin); + VectorCopy (start, bolt->s.old_origin); + vectoangles (dir, bolt->s.angles); + VectorScale (dir, speed, bolt->velocity); + bolt->movetype = MOVETYPE_FLYMISSILE; + bolt->clipmask = MASK_SHOT; + bolt->solid = SOLID_BBOX; + bolt->s.effects |= effect; + VectorClear (bolt->mins); + VectorClear (bolt->maxs); + bolt->s.modelindex = gi.modelindex ("models/objects/laser/tris.md2"); + bolt->s.sound = gi.soundindex ("misc/lasfly.wav"); + bolt->owner = self; + bolt->touch = blaster_touch; + bolt->nextthink = level.time + 2; + bolt->think = G_FreeEdict; + bolt->dmg = damage; + bolt->classname = "bolt"; + if (hyper) + bolt->spawnflags = 1; + gi.linkentity (bolt); + + if (self->client) + check_dodge (self, bolt->s.origin, dir, speed); + + tr = gi.trace (self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT); + if (tr.fraction < 1.0) + { + VectorMA (bolt->s.origin, -10, dir, bolt->s.origin); + bolt->touch (bolt, tr.ent, NULL, NULL); + } +} + + +/* +================= +fire_grenade +================= +*/ +static void Grenade_Explode (edict_t *ent) +{ + vec3_t origin; + int mod; + + if (ent->owner->client) + PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); + + //FIXME: if we are onground then raise our Z just a bit since we are a point? + if (ent->enemy) + { + float points; + vec3_t v; + vec3_t dir; + + VectorAdd (ent->enemy->mins, ent->enemy->maxs, v); + VectorMA (ent->enemy->s.origin, 0.5, v, v); + VectorSubtract (ent->s.origin, v, v); + points = ent->dmg - 0.5 * VectorLength (v); + VectorSubtract (ent->enemy->s.origin, ent->s.origin, dir); + if (ent->spawnflags & 1) + mod = MOD_HANDGRENADE; + else + mod = MOD_GRENADE; + T_Damage (ent->enemy, ent, ent->owner, dir, ent->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); + } + + if (ent->spawnflags & 2) + mod = MOD_HELD_GRENADE; + else if (ent->spawnflags & 1) + mod = MOD_HG_SPLASH; + else + mod = MOD_G_SPLASH; + T_RadiusDamage(ent, ent->owner, ent->dmg, ent->enemy, ent->dmg_radius, mod); + + VectorMA (ent->s.origin, -0.02, ent->velocity, origin); + gi.WriteByte (svc_temp_entity); + if (ent->waterlevel) + { + if (ent->groundentity) + gi.WriteByte (TE_GRENADE_EXPLOSION_WATER); + else + gi.WriteByte (TE_ROCKET_EXPLOSION_WATER); + } + else + { + if (ent->groundentity) + gi.WriteByte (TE_GRENADE_EXPLOSION); + else + gi.WriteByte (TE_ROCKET_EXPLOSION); + } + gi.WritePosition (origin); + gi.multicast (ent->s.origin, MULTICAST_PHS); + + G_FreeEdict (ent); +} + +static void Grenade_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + if (other == ent->owner) + return; + + if (surf && (surf->flags & SURF_SKY)) + { + G_FreeEdict (ent); + return; + } + + if (!other->takedamage) + { + if (ent->spawnflags & 1) + { + if (random() > 0.5) + gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0); + else + gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0); + } + else + { + gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/grenlb1b.wav"), 1, ATTN_NORM, 0); + } + return; + } + + ent->enemy = other; + Grenade_Explode (ent); +} + +void fire_grenade (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius) +{ + edict_t *grenade; + vec3_t dir; + vec3_t forward, right, up; + + vectoangles (aimdir, dir); + AngleVectors (dir, forward, right, up); + + grenade = G_Spawn(); + VectorCopy (start, grenade->s.origin); + VectorScale (aimdir, speed, grenade->velocity); + VectorMA (grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity); + VectorMA (grenade->velocity, crandom() * 10.0, right, grenade->velocity); + VectorSet (grenade->avelocity, 300, 300, 300); + grenade->movetype = MOVETYPE_BOUNCE; + grenade->clipmask = MASK_SHOT; + grenade->solid = SOLID_BBOX; + grenade->s.effects |= EF_GRENADE; + VectorClear (grenade->mins); + VectorClear (grenade->maxs); + grenade->s.modelindex = gi.modelindex ("models/objects/grenade/tris.md2"); + grenade->owner = self; + grenade->touch = Grenade_Touch; + grenade->nextthink = level.time + timer; + grenade->think = Grenade_Explode; + grenade->dmg = damage; + grenade->dmg_radius = damage_radius; + grenade->classname = "grenade"; + + gi.linkentity (grenade); +} + +void fire_grenade2 (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius, qboolean held) +{ + edict_t *grenade; + vec3_t dir; + vec3_t forward, right, up; + + vectoangles (aimdir, dir); + AngleVectors (dir, forward, right, up); + + grenade = G_Spawn(); + VectorCopy (start, grenade->s.origin); + VectorScale (aimdir, speed, grenade->velocity); + VectorMA (grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity); + VectorMA (grenade->velocity, crandom() * 10.0, right, grenade->velocity); + VectorSet (grenade->avelocity, 300, 300, 300); + grenade->movetype = MOVETYPE_BOUNCE; + grenade->clipmask = MASK_SHOT; + grenade->solid = SOLID_BBOX; + grenade->s.effects |= EF_GRENADE; + VectorClear (grenade->mins); + VectorClear (grenade->maxs); + grenade->s.modelindex = gi.modelindex ("models/objects/grenade2/tris.md2"); + grenade->owner = self; + grenade->touch = Grenade_Touch; + grenade->nextthink = level.time + timer; + grenade->think = Grenade_Explode; + grenade->dmg = damage; + grenade->dmg_radius = damage_radius; + grenade->classname = "hgrenade"; + if (held) + grenade->spawnflags = 3; + else + grenade->spawnflags = 1; + grenade->s.sound = gi.soundindex("weapons/hgrenc1b.wav"); + + if (timer <= 0.0) + Grenade_Explode (grenade); + else + { + gi.sound (self, CHAN_WEAPON, gi.soundindex ("weapons/hgrent1a.wav"), 1, ATTN_NORM, 0); + gi.linkentity (grenade); + } +} + + +/* +================= +fire_rocket +================= +*/ +void rocket_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + vec3_t origin; + int n; + + if (other == ent->owner) + return; + + if (surf && (surf->flags & SURF_SKY)) + { + G_FreeEdict (ent); + return; + } + + if (ent->owner->client) + PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); + + // calculate position for the explosion entity + VectorMA (ent->s.origin, -0.02, ent->velocity, origin); + + if (other->takedamage) + { + T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_ROCKET); + } + else + { + // don't throw any debris in net games + if (!deathmatch->value && !coop->value) + { + if ((surf) && !(surf->flags & (SURF_WARP|SURF_TRANS33|SURF_TRANS66|SURF_FLOWING))) + { + n = rand() % 5; + while(n--) + ThrowDebris (ent, "models/objects/debris2/tris.md2", 2, ent->s.origin); + } + } + } + + T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius, MOD_R_SPLASH); + + gi.WriteByte (svc_temp_entity); + if (ent->waterlevel) + gi.WriteByte (TE_ROCKET_EXPLOSION_WATER); + else + gi.WriteByte (TE_ROCKET_EXPLOSION); + gi.WritePosition (origin); + gi.multicast (ent->s.origin, MULTICAST_PHS); + + G_FreeEdict (ent); +} + +void fire_rocket (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage) +{ + edict_t *rocket; + + rocket = G_Spawn(); + VectorCopy (start, rocket->s.origin); + VectorCopy (dir, rocket->movedir); + vectoangles (dir, rocket->s.angles); + VectorScale (dir, speed, rocket->velocity); + rocket->movetype = MOVETYPE_FLYMISSILE; + rocket->clipmask = MASK_SHOT; + rocket->solid = SOLID_BBOX; + rocket->s.effects |= EF_ROCKET; + VectorClear (rocket->mins); + VectorClear (rocket->maxs); + rocket->s.modelindex = gi.modelindex ("models/objects/rocket/tris.md2"); + rocket->owner = self; + rocket->touch = rocket_touch; + rocket->nextthink = level.time + 8000/speed; + rocket->think = G_FreeEdict; + rocket->dmg = damage; + rocket->radius_dmg = radius_damage; + rocket->dmg_radius = damage_radius; + rocket->s.sound = gi.soundindex ("weapons/rockfly.wav"); + rocket->classname = "rocket"; + + if (self->client) + check_dodge (self, rocket->s.origin, dir, speed); + + gi.linkentity (rocket); +} + + +/* +================= +fire_rail +================= +*/ +void fire_rail (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick) +{ + vec3_t from; + vec3_t end; + trace_t tr; + edict_t *ignore; + int mask; + qboolean water; + + VectorMA (start, 8192, aimdir, end); + VectorCopy (start, from); + ignore = self; + water = false; + mask = MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA; + while (ignore) + { + tr = gi.trace (from, NULL, NULL, end, ignore, mask); + + if (tr.contents & (CONTENTS_SLIME|CONTENTS_LAVA)) + { + mask &= ~(CONTENTS_SLIME|CONTENTS_LAVA); + water = true; + } + else + { + if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client)) + ignore = tr.ent; + else + ignore = NULL; + + if ((tr.ent != self) && (tr.ent->takedamage)) + T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, 0, MOD_RAILGUN); + } + + VectorCopy (tr.endpos, from); + } + + // send gun puff / flash + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_RAILTRAIL); + gi.WritePosition (start); + gi.WritePosition (tr.endpos); + gi.multicast (self->s.origin, MULTICAST_PHS); +// gi.multicast (start, MULTICAST_PHS); + if (water) + { + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_RAILTRAIL); + gi.WritePosition (start); + gi.WritePosition (tr.endpos); + gi.multicast (tr.endpos, MULTICAST_PHS); + } + + if (self->client) + PlayerNoise(self, tr.endpos, PNOISE_IMPACT); +} + + +/* +================= +fire_bfg +================= +*/ +void bfg_explode (edict_t *self) +{ + edict_t *ent; + float points; + vec3_t v; + float dist; + + if (self->s.frame == 0) + { + // the BFG effect + ent = NULL; + while ((ent = findradius(ent, self->s.origin, self->dmg_radius)) != NULL) + { + if (!ent->takedamage) + continue; + if (ent == self->owner) + continue; + if (!CanDamage (ent, self)) + continue; + if (!CanDamage (ent, self->owner)) + continue; + + VectorAdd (ent->mins, ent->maxs, v); + VectorMA (ent->s.origin, 0.5, v, v); + VectorSubtract (self->s.origin, v, v); + dist = VectorLength(v); + points = self->radius_dmg * (1.0 - sqrt(dist/self->dmg_radius)); + if (ent == self->owner) + points = points * 0.5; + + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_BFG_EXPLOSION); + gi.WritePosition (ent->s.origin); + gi.multicast (ent->s.origin, MULTICAST_PHS); + T_Damage (ent, self, self->owner, self->velocity, ent->s.origin, vec3_origin, (int)points, 0, DAMAGE_ENERGY, MOD_BFG_EFFECT); + } + } + + self->nextthink = level.time + FRAMETIME; + self->s.frame++; + if (self->s.frame == 5) + self->think = G_FreeEdict; +} + +void bfg_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + if (other == self->owner) + return; + + if (surf && (surf->flags & SURF_SKY)) + { + G_FreeEdict (self); + return; + } + + if (self->owner->client) + PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); + + // core explosion - prevents firing it into the wall/floor + if (other->takedamage) + T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, 200, 0, 0, MOD_BFG_BLAST); + T_RadiusDamage(self, self->owner, 200, other, 100, MOD_BFG_BLAST); + + gi.sound (self, CHAN_VOICE, gi.soundindex ("weapons/bfg__x1b.wav"), 1, ATTN_NORM, 0); + self->solid = SOLID_NOT; + self->touch = NULL; + VectorMA (self->s.origin, -1 * FRAMETIME, self->velocity, self->s.origin); + VectorClear (self->velocity); + self->s.modelindex = gi.modelindex ("sprites/s_bfg3.sp2"); + self->s.frame = 0; + self->s.sound = 0; + self->s.effects &= ~EF_ANIM_ALLFAST; + self->think = bfg_explode; + self->nextthink = level.time + FRAMETIME; + self->enemy = other; + + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_BFG_BIGEXPLOSION); + gi.WritePosition (self->s.origin); + gi.multicast (self->s.origin, MULTICAST_PVS); +} + + +void bfg_think (edict_t *self) +{ + edict_t *ent; + edict_t *ignore; + vec3_t point; + vec3_t dir; + vec3_t start; + vec3_t end; + int dmg; + trace_t tr; + + if (deathmatch->value) + dmg = 5; + else + dmg = 10; + + ent = NULL; + while ((ent = findradius(ent, self->s.origin, 256)) != NULL) + { + if (ent == self) + continue; + + if (ent == self->owner) + continue; + + if (!ent->takedamage) + continue; + + if (!(ent->svflags & SVF_MONSTER) && (!ent->client) && (strcmp(ent->classname, "misc_explobox") != 0)) + continue; + + VectorMA (ent->absmin, 0.5, ent->size, point); + + VectorSubtract (point, self->s.origin, dir); + VectorNormalize (dir); + + ignore = self; + VectorCopy (self->s.origin, start); + VectorMA (start, 2048, dir, end); + while(1) + { + tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); + + if (!tr.ent) + break; + + // hurt it if we can + if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER) && (tr.ent != self->owner)) + T_Damage (tr.ent, self, self->owner, dir, tr.endpos, vec3_origin, dmg, 1, DAMAGE_ENERGY, MOD_BFG_LASER); + + // if we hit something that's not a monster or player we're done + if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client)) + { + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_LASER_SPARKS); + gi.WriteByte (4); + 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); + } + + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_BFG_LASER); + gi.WritePosition (self->s.origin); + gi.WritePosition (tr.endpos); + gi.multicast (self->s.origin, MULTICAST_PHS); + } + + self->nextthink = level.time + FRAMETIME; +} + + +void fire_bfg (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius) +{ + edict_t *bfg; + + bfg = G_Spawn(); + VectorCopy (start, bfg->s.origin); + VectorCopy (dir, bfg->movedir); + vectoangles (dir, bfg->s.angles); + VectorScale (dir, speed, bfg->velocity); + bfg->movetype = MOVETYPE_FLYMISSILE; + bfg->clipmask = MASK_SHOT; + bfg->solid = SOLID_BBOX; + bfg->s.effects |= EF_BFG | EF_ANIM_ALLFAST; + VectorClear (bfg->mins); + VectorClear (bfg->maxs); + bfg->s.modelindex = gi.modelindex ("sprites/s_bfg1.sp2"); + bfg->owner = self; + bfg->touch = bfg_touch; + bfg->nextthink = level.time + 8000/speed; + bfg->think = G_FreeEdict; + bfg->radius_dmg = damage; + bfg->dmg_radius = damage_radius; + bfg->classname = "bfg blast"; + bfg->s.sound = gi.soundindex ("weapons/bfg__l1a.wav"); + + bfg->think = bfg_think; + bfg->nextthink = level.time + FRAMETIME; + bfg->teammaster = bfg; + bfg->teamchain = NULL; + + if (self->client) + check_dodge (self, bfg->s.origin, dir, speed); + + gi.linkentity (bfg); +} diff --git a/game/game.001 b/game/game.001 new file mode 100644 index 000000000..6e84a178f --- /dev/null +++ b/game/game.001 @@ -0,0 +1,1619 @@ +# Microsoft Developer Studio Project File - Name="game" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 +# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602 + +CFG=game - Win32 Debug Alpha +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "game.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "game.mak" CFG="game - Win32 Debug Alpha" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "game - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "game - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "game - Win32 Debug Alpha" (based on\ + "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE "game - Win32 Release Alpha" (based on\ + "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "game - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\release" +# PROP Intermediate_Dir ".\release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MT /W4 /GX /Zd /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib winmm.lib /nologo /base:"0x20000000" /subsystem:windows /dll /machine:I386 /out:"..\release\gamex86.dll" +# SUBTRACT LINK32 /incremental:yes /debug + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\debug" +# PROP Intermediate_Dir ".\debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "BUILDING_REF_GL" /FR /YX /FD /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib winmm.lib /nologo /base:"0x20000000" /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"..\debug\gamex86.dll" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug Alpha" +# PROP BASE Intermediate_Dir "Debug Alpha" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\DebugAxp" +# PROP Intermediate_Dir ".\DebugAxp" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /QA21164 /MTd /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "C_ONLY" /YX /FD /c +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x20000000" /subsystem:windows /dll /debug /machine:ALPHA +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x20000000" /subsystem:windows /dll /debug /machine:ALPHA /out:"..\DebugAxp/gameaxp.dll" + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "game___W" +# PROP BASE Intermediate_Dir "game___W" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\ReleaseAXP" +# PROP Intermediate_Dir ".\ReleaseAXP" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +CPP=cl.exe +# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /Zd /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /QA21164 /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "C_ONLY" /YX /FD /c +# SUBTRACT CPP /Z /Fr +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x20000000" /subsystem:windows /dll /machine:ALPHA /out:"..\Release/gamex86.dll" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /base:"0x20000000" /subsystem:windows /dll /machine:ALPHA /out:"..\ReleaseAXP/gameaxp.dll" +# SUBTRACT LINK32 /debug + +!ENDIF + +# Begin Target + +# Name "game - Win32 Release" +# Name "game - Win32 Debug" +# Name "game - Win32 Debug Alpha" +# Name "game - Win32 Release Alpha" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\g_ai.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_AI_=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_AI_=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_chase.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_CHA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_CHA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_cmds.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_CMD=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_CMD=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_combat.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_COM=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_COM=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_func.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_FUN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_FUN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_items.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_ITE=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_ITE=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_main.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_MAI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_MAI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_misc.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_MIS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_MIS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_monster.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_MON=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_MON=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_phys.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_PHY=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_PHY=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_save.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_SAV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_SAV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_spawn.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_SPA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_SPA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_svcmds.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_SVC=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_SVC=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_target.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_TAR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_TAR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_trigger.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_TRI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_TRI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_turret.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_TUR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_TUR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_utils.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_UTI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_UTI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_weapon.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_WEA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_WEA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_actor.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_ACT=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_actor.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_ACT=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_actor.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_berserk.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BER=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_berserk.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BER=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_berserk.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_boss2.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BOS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss2.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BOS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss2.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_boss3.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BOSS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss32.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BOSS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss32.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_boss31.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BOSS3=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss31.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BOSS3=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss31.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_boss32.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BOSS32=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss32.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BOSS32=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss32.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_brain.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BRA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_brain.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BRA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_brain.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_chick.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_CHI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_chick.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_CHI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_chick.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_flash.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_FLA=\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_FLA=\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_flipper.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_FLI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_flipper.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_FLI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_flipper.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_float.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_FLO=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_float.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_FLO=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_float.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_flyer.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_FLY=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_flyer.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_FLY=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_flyer.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_gladiator.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_GLA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_gladiator.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_GLA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_gladiator.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_gunner.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_GUN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_gunner.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_GUN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_gunner.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_hover.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_HOV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_hover.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_HOV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_hover.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_infantry.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_INF=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_infantry.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_INF=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_infantry.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_insane.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_INS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_insane.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_INS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_insane.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_medic.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_MED=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_medic.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_MED=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_medic.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_move.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_MOV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_MOV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_mutant.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_MUT=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_mutant.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_MUT=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_mutant.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_parasite.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_PAR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_parasite.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_PAR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_parasite.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_soldier.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_SOL=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_soldier.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_SOL=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_soldier.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_supertank.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_SUP=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_supertank.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_SUP=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_supertank.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_tank.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_TAN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_tank.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_TAN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_tank.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\p_client.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_P_CLI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_P_CLI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\p_hud.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_P_HUD=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_P_HUD=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\p_trail.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_P_TRA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_P_TRA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\p_view.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_P_VIE=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_P_VIE=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\p_weapon.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_P_WEA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_P_WEA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\q_shared.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_Q_SHA=\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_Q_SHA=\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\g_local.h +# End Source File +# Begin Source File + +SOURCE=.\game.h +# End Source File +# Begin Source File + +SOURCE=.\m_actor.h +# End Source File +# Begin Source File + +SOURCE=.\m_berserk.h +# End Source File +# Begin Source File + +SOURCE=.\m_boss2.h +# End Source File +# Begin Source File + +SOURCE=.\m_boss31.h +# End Source File +# Begin Source File + +SOURCE=.\m_boss32.h +# End Source File +# Begin Source File + +SOURCE=.\m_brain.h +# End Source File +# Begin Source File + +SOURCE=.\m_chick.h +# End Source File +# Begin Source File + +SOURCE=.\m_flipper.h +# End Source File +# Begin Source File + +SOURCE=.\m_float.h +# End Source File +# Begin Source File + +SOURCE=.\m_flyer.h +# End Source File +# Begin Source File + +SOURCE=.\m_gladiator.h +# End Source File +# Begin Source File + +SOURCE=.\m_gunner.h +# End Source File +# Begin Source File + +SOURCE=.\m_hover.h +# End Source File +# Begin Source File + +SOURCE=.\m_infantry.h +# End Source File +# Begin Source File + +SOURCE=.\m_insane.h +# End Source File +# Begin Source File + +SOURCE=.\m_medic.h +# End Source File +# Begin Source File + +SOURCE=.\m_mutant.h +# End Source File +# Begin Source File + +SOURCE=.\m_parasite.h +# End Source File +# Begin Source File + +SOURCE=.\m_player.h +# End Source File +# Begin Source File + +SOURCE=.\m_soldier.h +# End Source File +# Begin Source File + +SOURCE=.\m_supertank.h +# End Source File +# Begin Source File + +SOURCE=.\m_tank.h +# End Source File +# Begin Source File + +SOURCE=.\q_shared.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\game.def +# End Source File +# End Group +# End Target +# End Project diff --git a/game/game.def b/game/game.def new file mode 100644 index 000000000..44612438b --- /dev/null +++ b/game/game.def @@ -0,0 +1,2 @@ +EXPORTS + GetGameAPI diff --git a/game/game.dsp b/game/game.dsp new file mode 100644 index 000000000..4ee4456f8 --- /dev/null +++ b/game/game.dsp @@ -0,0 +1,1618 @@ +# Microsoft Developer Studio Project File - Name="game" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 +# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602 + +CFG=game - Win32 Debug Alpha +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "game.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "game.mak" CFG="game - Win32 Debug Alpha" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "game - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "game - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "game - Win32 Debug Alpha" (based on "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE "game - Win32 Release Alpha" (based on "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "game - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\release" +# PROP Intermediate_Dir ".\release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MT /W4 /GX /Zd /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib winmm.lib /nologo /base:"0x20000000" /subsystem:windows /dll /machine:I386 /out:"..\release\gamex86.dll" +# SUBTRACT LINK32 /incremental:yes /debug + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\debug" +# PROP Intermediate_Dir ".\debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "BUILDING_REF_GL" /FR /YX /FD /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib winmm.lib /nologo /base:"0x20000000" /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"..\debug\gamex86.dll" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug Alpha" +# PROP BASE Intermediate_Dir "Debug Alpha" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\DebugAxp" +# PROP Intermediate_Dir ".\DebugAxp" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /QA21164 /MTd /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "C_ONLY" /YX /FD /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x20000000" /subsystem:windows /dll /debug /machine:ALPHA +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x20000000" /subsystem:windows /dll /debug /machine:ALPHA /out:"..\DebugAxp/gameaxp.dll" + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "game___W" +# PROP BASE Intermediate_Dir "game___W" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\ReleaseAXP" +# PROP Intermediate_Dir ".\ReleaseAXP" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /Zd /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /QA21164 /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "C_ONLY" /YX /FD /c +# SUBTRACT CPP /Z /Fr +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x20000000" /subsystem:windows /dll /machine:ALPHA /out:"..\Release/gamex86.dll" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /base:"0x20000000" /subsystem:windows /dll /machine:ALPHA /out:"..\ReleaseAXP/gameaxp.dll" +# SUBTRACT LINK32 /debug + +!ENDIF + +# Begin Target + +# Name "game - Win32 Release" +# Name "game - Win32 Debug" +# Name "game - Win32 Debug Alpha" +# Name "game - Win32 Release Alpha" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\g_ai.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_AI_=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_AI_=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_chase.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_CHA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_CHA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_cmds.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_CMD=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_CMD=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_combat.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_COM=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_COM=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_func.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_FUN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_FUN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_items.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_ITE=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_ITE=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_main.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_MAI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_MAI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_misc.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_MIS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_MIS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_monster.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_MON=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_MON=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_phys.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_PHY=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_PHY=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_save.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_SAV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_SAV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_spawn.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_SPA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_SPA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_svcmds.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_SVC=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_SVC=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_target.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_TAR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_TAR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_trigger.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_TRI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_TRI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_turret.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_TUR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_TUR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_utils.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_UTI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_UTI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\g_weapon.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_G_WEA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_G_WEA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_actor.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_ACT=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_actor.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_ACT=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_actor.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_berserk.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BER=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_berserk.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BER=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_berserk.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_boss2.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BOS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss2.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BOS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss2.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_boss3.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BOSS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss32.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BOSS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss32.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_boss31.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BOSS3=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss31.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BOSS3=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss31.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_boss32.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BOSS32=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss32.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BOSS32=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_boss32.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_brain.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_BRA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_brain.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_BRA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_brain.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_chick.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_CHI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_chick.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_CHI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_chick.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_flash.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_FLA=\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_FLA=\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_flipper.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_FLI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_flipper.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_FLI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_flipper.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_float.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_FLO=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_float.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_FLO=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_float.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_flyer.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_FLY=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_flyer.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_FLY=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_flyer.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_gladiator.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_GLA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_gladiator.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_GLA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_gladiator.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_gunner.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_GUN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_gunner.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_GUN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_gunner.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_hover.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_HOV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_hover.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_HOV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_hover.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_infantry.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_INF=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_infantry.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_INF=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_infantry.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_insane.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_INS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_insane.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_INS=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_insane.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_medic.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_MED=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_medic.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_MED=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_medic.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_move.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_MOV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_MOV=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_mutant.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_MUT=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_mutant.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_MUT=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_mutant.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_parasite.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_PAR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_parasite.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_PAR=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_parasite.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_soldier.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_SOL=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_soldier.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_SOL=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_soldier.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_supertank.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_SUP=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_supertank.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_SUP=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_supertank.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\m_tank.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_M_TAN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_tank.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_M_TAN=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_tank.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\p_client.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_P_CLI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_P_CLI=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\p_hud.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_P_HUD=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_P_HUD=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\p_trail.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_P_TRA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_P_TRA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\p_view.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_P_VIE=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_P_VIE=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\p_weapon.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_P_WEA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_P_WEA=\ + ".\g_local.h"\ + ".\game.h"\ + ".\m_player.h"\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\q_shared.c + +!IF "$(CFG)" == "game - Win32 Release" + +!ELSEIF "$(CFG)" == "game - Win32 Debug" + +!ELSEIF "$(CFG)" == "game - Win32 Debug Alpha" + +DEP_CPP_Q_SHA=\ + ".\q_shared.h"\ + + +!ELSEIF "$(CFG)" == "game - Win32 Release Alpha" + +DEP_CPP_Q_SHA=\ + ".\q_shared.h"\ + + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\g_local.h +# End Source File +# Begin Source File + +SOURCE=.\game.h +# End Source File +# Begin Source File + +SOURCE=.\m_actor.h +# End Source File +# Begin Source File + +SOURCE=.\m_berserk.h +# End Source File +# Begin Source File + +SOURCE=.\m_boss2.h +# End Source File +# Begin Source File + +SOURCE=.\m_boss31.h +# End Source File +# Begin Source File + +SOURCE=.\m_boss32.h +# End Source File +# Begin Source File + +SOURCE=.\m_brain.h +# End Source File +# Begin Source File + +SOURCE=.\m_chick.h +# End Source File +# Begin Source File + +SOURCE=.\m_flipper.h +# End Source File +# Begin Source File + +SOURCE=.\m_float.h +# End Source File +# Begin Source File + +SOURCE=.\m_flyer.h +# End Source File +# Begin Source File + +SOURCE=.\m_gladiator.h +# End Source File +# Begin Source File + +SOURCE=.\m_gunner.h +# End Source File +# Begin Source File + +SOURCE=.\m_hover.h +# End Source File +# Begin Source File + +SOURCE=.\m_infantry.h +# End Source File +# Begin Source File + +SOURCE=.\m_insane.h +# End Source File +# Begin Source File + +SOURCE=.\m_medic.h +# End Source File +# Begin Source File + +SOURCE=.\m_mutant.h +# End Source File +# Begin Source File + +SOURCE=.\m_parasite.h +# End Source File +# Begin Source File + +SOURCE=.\m_player.h +# End Source File +# Begin Source File + +SOURCE=.\m_soldier.h +# End Source File +# Begin Source File + +SOURCE=.\m_supertank.h +# End Source File +# Begin Source File + +SOURCE=.\m_tank.h +# End Source File +# Begin Source File + +SOURCE=.\q_shared.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\game.def +# End Source File +# End Group +# End Target +# End Project diff --git a/game/game.h b/game/game.h new file mode 100644 index 000000000..7b6218aed --- /dev/null +++ b/game/game.h @@ -0,0 +1,254 @@ +/* +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. + +*/ + +// game.h -- game dll information visible to server + +#define GAME_API_VERSION 3 + +// edict->svflags + +#define SVF_NOCLIENT 0x00000001 // don't send entity to clients, even if it has effects +#define SVF_DEADMONSTER 0x00000002 // treat as CONTENTS_DEADMONSTER for collision +#define SVF_MONSTER 0x00000004 // treat as CONTENTS_MONSTER for collision + +// edict->solid values + +typedef enum +{ +SOLID_NOT, // no interaction with other objects +SOLID_TRIGGER, // only touch when inside, after moving +SOLID_BBOX, // touch on edge +SOLID_BSP // bsp clip, touch on edge +} solid_t; + +//=============================================================== + +// link_t is only used for entity area links now +typedef struct link_s +{ + struct link_s *prev, *next; +} link_t; + +#define MAX_ENT_CLUSTERS 16 + + +typedef struct edict_s edict_t; +typedef struct gclient_s gclient_t; + + +#ifndef GAME_INCLUDE + +struct gclient_s +{ + player_state_t ps; // communicated by server to clients + int ping; + // the game dll can add anything it wants after + // this point in the structure +}; + + +struct edict_s +{ + entity_state_t s; + struct gclient_s *client; + qboolean inuse; + int linkcount; + + // FIXME: move these fields to a server private sv_entity_t + link_t area; // linked to a division node or leaf + + int num_clusters; // if -1, use headnode instead + int clusternums[MAX_ENT_CLUSTERS]; + int headnode; // unused if num_clusters != -1 + int areanum, areanum2; + + //================================ + + int svflags; // SVF_NOCLIENT, SVF_DEADMONSTER, SVF_MONSTER, etc + vec3_t mins, maxs; + vec3_t absmin, absmax, size; + solid_t solid; + int clipmask; + edict_t *owner; + + // the game dll can add anything it wants after + // this point in the structure +}; + +#endif // GAME_INCLUDE + +//=============================================================== + +// +// functions provided by the main engine +// +typedef struct +{ + // special messages + void (*bprintf) (int printlevel, char *fmt, ...); + void (*dprintf) (char *fmt, ...); + void (*cprintf) (edict_t *ent, int printlevel, char *fmt, ...); + void (*centerprintf) (edict_t *ent, char *fmt, ...); + void (*sound) (edict_t *ent, int channel, int soundindex, float volume, float attenuation, float timeofs); + void (*positioned_sound) (vec3_t origin, edict_t *ent, int channel, int soundinedex, float volume, float attenuation, float timeofs); + + // config strings hold all the index strings, the lightstyles, + // and misc data like the sky definition and cdtrack. + // All of the current configstrings are sent to clients when + // they connect, and changes are sent to all connected clients. + void (*configstring) (int num, char *string); + + void (*error) (char *fmt, ...); + + // the *index functions create configstrings and some internal server state + int (*modelindex) (char *name); + int (*soundindex) (char *name); + int (*imageindex) (char *name); + + void (*setmodel) (edict_t *ent, char *name); + + // collision detection + trace_t (*trace) (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passent, int contentmask); + int (*pointcontents) (vec3_t point); + qboolean (*inPVS) (vec3_t p1, vec3_t p2); + qboolean (*inPHS) (vec3_t p1, vec3_t p2); + void (*SetAreaPortalState) (int portalnum, qboolean open); + qboolean (*AreasConnected) (int area1, int area2); + + // an entity will never be sent to a client or used for collision + // if it is not passed to linkentity. If the size, position, or + // solidity changes, it must be relinked. + void (*linkentity) (edict_t *ent); + void (*unlinkentity) (edict_t *ent); // call before removing an interactive edict + int (*BoxEdicts) (vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int areatype); + void (*Pmove) (pmove_t *pmove); // player movement code common with client prediction + + // network messaging + void (*multicast) (vec3_t origin, multicast_t to); + void (*unicast) (edict_t *ent, qboolean reliable); + void (*WriteChar) (int c); + void (*WriteByte) (int c); + void (*WriteShort) (int c); + void (*WriteLong) (int c); + void (*WriteFloat) (float f); + void (*WriteString) (char *s); + void (*WritePosition) (vec3_t pos); // some fractional bits + void (*WriteDir) (vec3_t pos); // single byte encoded, very coarse + void (*WriteAngle) (float f); + + // managed memory allocation + void *(*TagMalloc) (int size, int tag); + void (*TagFree) (void *block); + void (*FreeTags) (int tag); + + // console variable interaction + cvar_t *(*cvar) (char *var_name, char *value, int flags); + cvar_t *(*cvar_set) (char *var_name, char *value); + cvar_t *(*cvar_forceset) (char *var_name, char *value); + + // ClientCommand and ServerCommand parameter access + int (*argc) (void); + char *(*argv) (int n); + char *(*args) (void); // concatenation of all argv >= 1 + + // add commands to the server console as if they were typed in + // for map changing, etc + void (*AddCommandString) (char *text); + + void (*DebugGraph) (float value, int color); +} game_import_t; + +// +// functions exported by the game subsystem +// +typedef struct +{ + int apiversion; + + // the init function will only be called when a game starts, + // not each time a level is loaded. Persistant data for clients + // and the server can be allocated in init + void (*Init) (void); + void (*Shutdown) (void); + + // each new level entered will cause a call to SpawnEntities + void (*SpawnEntities) (char *mapname, char *entstring, char *spawnpoint); + + // Read/Write Game is for storing persistant cross level information + // about the world state and the clients. + // WriteGame is called every time a level is exited. + // ReadGame is called on a loadgame. + void (*WriteGame) (char *filename, qboolean autosave); + void (*ReadGame) (char *filename); + + // ReadLevel is called after the default map information has been + // loaded with SpawnEntities + void (*WriteLevel) (char *filename); + void (*ReadLevel) (char *filename); + + qboolean (*ClientConnect) (edict_t *ent, char *userinfo); + void (*ClientBegin) (edict_t *ent); + void (*ClientUserinfoChanged) (edict_t *ent, char *userinfo); + void (*ClientDisconnect) (edict_t *ent); + void (*ClientCommand) (edict_t *ent); + void (*ClientThink) (edict_t *ent, usercmd_t *cmd); + + void (*RunFrame) (void); + + // ServerCommand will be called when an "sv " command is issued on the + // server console. + // The game can issue gi.argc() / gi.argv() commands to get the rest + // of the parameters + void (*ServerCommand) (void); + + // + // global variables shared between game and server + // + + // The edict array is allocated in the game dll so it + // can vary in size from one game to another. + // + // The size will be fixed when ge->Init() is called + struct edict_s *edicts; + int edict_size; + int num_edicts; // current number, <= max_edicts + int max_edicts; +} game_export_t; + +game_export_t *GetGameApi (game_import_t *import); diff --git a/game/game.plg b/game/game.plg new file mode 100644 index 000000000..3d0da9bc8 --- /dev/null +++ b/game/game.plg @@ -0,0 +1,75 @@ +--------------------Configuration: game - Win32 Release Alpha-------------------- +Begining build with project "G:\quake2\code\game\game.dsp", at root. +Active configuration is Win32 (ALPHA) Dynamic-Link Library (based on Win32 (ALPHA) Dynamic-Link Library) + +Project's tools are: + "OLE Type Library Maker" with flags "/nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 " + "C/C++ Compiler for Alpha" with flags "/nologo /QA21164 /MT /Gt0 /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "C_ONLY" /Fp".\ReleaseAXP/game.pch" /YX /Fo".\ReleaseAXP/" /Fd".\ReleaseAXP/" /FD /c " + "Win32 Resource Compiler" with flags "/l 0x409 /d "NDEBUG" " + "Browser Database Maker" with flags "/nologo /o"..\ReleaseAXP/game.bsc" " + "COFF Linker for Alpha" with flags "kernel32.lib user32.lib gdi32.lib /nologo /base:"0x20000000" /subsystem:windows /dll /incremental:no /pdb:"..\ReleaseAXP/gameaxp.pdb" /debug /machine:ALPHA /def:".\game.def" /out:"..\ReleaseAXP/gameaxp.dll" /implib:"..\ReleaseAXP/gameaxp.lib" " + "Custom Build" with flags "" + "" with flags "" + +Creating temp file "C:\TEMP\RSPA6.tmp" with contents +Creating command line "cl.exe @C:\TEMP\RSPA6.tmp" +Creating temp file "C:\TEMP\RSPA7.tmp" with contents +Creating command line "link.exe @C:\TEMP\RSPA7.tmp" +Compiling... +p_weapon.c +Linking... + Creating library ..\ReleaseAXP/gameaxp.lib and object ..\ReleaseAXP/gameaxp.exp + + + +gameaxp.dll - 0 error(s), 0 warning(s) diff --git a/game/m_actor.c b/game/m_actor.c new file mode 100644 index 000000000..d7fc15d78 --- /dev/null +++ b/game/m_actor.c @@ -0,0 +1,609 @@ +/* +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. + +*/ +// g_actor.c + +#include "g_local.h" +#include "m_actor.h" + +#define MAX_ACTOR_NAMES 8 +char *actor_names[MAX_ACTOR_NAMES] = +{ + "Hellrot", + "Tokay", + "Killme", + "Disruptor", + "Adrianator", + "Rambear", + "Titus", + "Bitterman" +}; + + +mframe_t actor_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t actor_move_stand = {FRAME_stand101, FRAME_stand140, actor_frames_stand, NULL}; + +void actor_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &actor_move_stand; + + // randomize on startup + if (level.time < 1.0) + self->s.frame = self->monsterinfo.currentmove->firstframe + (rand() % (self->monsterinfo.currentmove->lastframe - self->monsterinfo.currentmove->firstframe + 1)); +} + + +mframe_t actor_frames_walk [] = +{ + ai_walk, 0, NULL, + ai_walk, 6, NULL, + ai_walk, 10, NULL, + ai_walk, 3, NULL, + ai_walk, 2, NULL, + ai_walk, 7, NULL, + ai_walk, 10, NULL, + ai_walk, 1, NULL, + ai_walk, 4, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL +}; +mmove_t actor_move_walk = {FRAME_walk01, FRAME_walk08, actor_frames_walk, NULL}; + +void actor_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &actor_move_walk; +} + + +mframe_t actor_frames_run [] = +{ + ai_run, 4, NULL, + ai_run, 15, NULL, + ai_run, 15, NULL, + ai_run, 8, NULL, + ai_run, 20, NULL, + ai_run, 15, NULL, + ai_run, 8, NULL, + ai_run, 17, NULL, + ai_run, 12, NULL, + ai_run, -2, NULL, + ai_run, -2, NULL, + ai_run, -1, NULL +}; +mmove_t actor_move_run = {FRAME_run02, FRAME_run07, actor_frames_run, NULL}; + +void actor_run (edict_t *self) +{ + if ((level.time < self->pain_debounce_time) && (!self->enemy)) + { + if (self->movetarget) + actor_walk(self); + else + actor_stand(self); + return; + } + + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + { + actor_stand(self); + return; + } + + self->monsterinfo.currentmove = &actor_move_run; +} + + +mframe_t actor_frames_pain1 [] = +{ + ai_move, -5, NULL, + ai_move, 4, NULL, + ai_move, 1, NULL +}; +mmove_t actor_move_pain1 = {FRAME_pain101, FRAME_pain103, actor_frames_pain1, actor_run}; + +mframe_t actor_frames_pain2 [] = +{ + ai_move, -4, NULL, + ai_move, 4, NULL, + ai_move, 0, NULL +}; +mmove_t actor_move_pain2 = {FRAME_pain201, FRAME_pain203, actor_frames_pain2, actor_run}; + +mframe_t actor_frames_pain3 [] = +{ + ai_move, -1, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL +}; +mmove_t actor_move_pain3 = {FRAME_pain301, FRAME_pain303, actor_frames_pain3, actor_run}; + +mframe_t actor_frames_flipoff [] = +{ + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL +}; +mmove_t actor_move_flipoff = {FRAME_flip01, FRAME_flip14, actor_frames_flipoff, actor_run}; + +mframe_t actor_frames_taunt [] = +{ + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL, + ai_turn, 0, NULL +}; +mmove_t actor_move_taunt = {FRAME_taunt01, FRAME_taunt17, actor_frames_taunt, actor_run}; + +char *messages[] = +{ + "Watch it", + "#$@*&", + "Idiot", + "Check your targets" +}; + +void actor_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + int n; + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; +// gi.sound (self, CHAN_VOICE, actor.sound_pain, 1, ATTN_NORM, 0); + + if ((other->client) && (random() < 0.4)) + { + vec3_t v; + char *name; + + VectorSubtract (other->s.origin, self->s.origin, v); + self->ideal_yaw = vectoyaw (v); + if (random() < 0.5) + self->monsterinfo.currentmove = &actor_move_flipoff; + else + self->monsterinfo.currentmove = &actor_move_taunt; + name = actor_names[(self - g_edicts)%MAX_ACTOR_NAMES]; + gi.cprintf (other, PRINT_CHAT, "%s: %s!\n", name, messages[rand()%3]); + return; + } + + n = rand() % 3; + if (n == 0) + self->monsterinfo.currentmove = &actor_move_pain1; + else if (n == 1) + self->monsterinfo.currentmove = &actor_move_pain2; + else + self->monsterinfo.currentmove = &actor_move_pain3; +} + + +void actorMachineGun (edict_t *self) +{ + vec3_t start, target; + vec3_t forward, right; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_ACTOR_MACHINEGUN_1], forward, right, start); + if (self->enemy) + { + if (self->enemy->health > 0) + { + VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); + target[2] += self->enemy->viewheight; + } + else + { + VectorCopy (self->enemy->absmin, target); + target[2] += (self->enemy->size[2] / 2); + } + VectorSubtract (target, start, forward); + VectorNormalize (forward); + } + else + { + AngleVectors (self->s.angles, forward, NULL, NULL); + } + monster_fire_bullet (self, start, forward, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_ACTOR_MACHINEGUN_1); +} + + +void actor_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +mframe_t actor_frames_death1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -13, NULL, + ai_move, 14, NULL, + ai_move, 3, NULL, + ai_move, -2, NULL, + ai_move, 1, NULL +}; +mmove_t actor_move_death1 = {FRAME_death101, FRAME_death107, actor_frames_death1, actor_dead}; + +mframe_t actor_frames_death2 [] = +{ + ai_move, 0, NULL, + ai_move, 7, NULL, + ai_move, -6, NULL, + ai_move, -5, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, -1, NULL, + ai_move, -2, NULL, + ai_move, -1, NULL, + ai_move, -9, NULL, + ai_move, -13, NULL, + ai_move, -13, NULL, + ai_move, 0, NULL +}; +mmove_t actor_move_death2 = {FRAME_death201, FRAME_death213, actor_frames_death2, actor_dead}; + +void actor_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + +// check for gib + if (self->health <= -80) + { +// gi.sound (self, CHAN_VOICE, actor.sound_gib, 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death +// gi.sound (self, CHAN_VOICE, actor.sound_die, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + + n = rand() % 2; + if (n == 0) + self->monsterinfo.currentmove = &actor_move_death1; + else + self->monsterinfo.currentmove = &actor_move_death2; +} + + +void actor_fire (edict_t *self) +{ + actorMachineGun (self); + + if (level.time >= self->monsterinfo.pausetime) + self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; + else + self->monsterinfo.aiflags |= AI_HOLD_FRAME; +} + +mframe_t actor_frames_attack [] = +{ + ai_charge, -2, actor_fire, + ai_charge, -2, NULL, + ai_charge, 3, NULL, + ai_charge, 2, NULL +}; +mmove_t actor_move_attack = {FRAME_attak01, FRAME_attak04, actor_frames_attack, actor_run}; + +void actor_attack(edict_t *self) +{ + int n; + + self->monsterinfo.currentmove = &actor_move_attack; + n = (rand() & 15) + 3 + 7; + self->monsterinfo.pausetime = level.time + n * FRAMETIME; +} + + +void actor_use (edict_t *self, edict_t *other, edict_t *activator) +{ + vec3_t v; + + self->goalentity = self->movetarget = G_PickTarget(self->target); + if ((!self->movetarget) || (strcmp(self->movetarget->classname, "target_actor") != 0)) + { + gi.dprintf ("%s has bad target %s at %s\n", self->classname, self->target, vtos(self->s.origin)); + self->target = NULL; + self->monsterinfo.pausetime = 100000000; + self->monsterinfo.stand (self); + return; + } + + VectorSubtract (self->goalentity->s.origin, self->s.origin, v); + self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v); + self->monsterinfo.walk (self); + self->target = NULL; +} + + +/*QUAKED misc_actor (1 .5 0) (-16 -16 -24) (16 16 32) +*/ + +void SP_misc_actor (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + if (!self->targetname) + { + gi.dprintf("untargeted %s at %s\n", self->classname, vtos(self->s.origin)); + 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); + return; + } + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex("players/male/tris.md2"); + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 32); + + if (!self->health) + self->health = 100; + self->mass = 200; + + self->pain = actor_pain; + self->die = actor_die; + + self->monsterinfo.stand = actor_stand; + self->monsterinfo.walk = actor_walk; + self->monsterinfo.run = actor_run; + self->monsterinfo.attack = actor_attack; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = NULL; + + self->monsterinfo.aiflags |= AI_GOOD_GUY; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &actor_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start (self); + + // actors always start in a dormant state, they *must* be used to get going + self->use = actor_use; +} + + +/*QUAKED target_actor (.5 .3 0) (-8 -8 -8) (8 8 8) JUMP SHOOT ATTACK x HOLD BRUTAL +JUMP jump in set direction upon reaching this target +SHOOT take a single shot at the pathtarget +ATTACK attack pathtarget until it or actor is dead + +"target" next target_actor +"pathtarget" target of any action to be taken at this point +"wait" amount of time actor should pause at this point +"message" actor will "say" this to the player + +for JUMP only: +"speed" speed thrown forward (default 200) +"height" speed thrown upwards (default 200) +*/ + +void target_actor_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + vec3_t v; + + if (other->movetarget != self) + return; + + if (other->enemy) + return; + + other->goalentity = other->movetarget = NULL; + + if (self->message) + { + int n; + edict_t *ent; + + for (n = 1; n <= game.maxclients; n++) + { + ent = &g_edicts[n]; + if (!ent->inuse) + continue; + gi.cprintf (ent, PRINT_CHAT, "%s: %s\n", actor_names[(other - g_edicts)%MAX_ACTOR_NAMES], self->message); + } + } + + if (self->spawnflags & 1) //jump + { + other->velocity[0] = self->movedir[0] * self->speed; + other->velocity[1] = self->movedir[1] * self->speed; + + if (other->groundentity) + { + other->groundentity = NULL; + other->velocity[2] = self->movedir[2]; + gi.sound(other, CHAN_VOICE, gi.soundindex("player/male/jump1.wav"), 1, ATTN_NORM, 0); + } + } + + if (self->spawnflags & 2) //shoot + { + } + else if (self->spawnflags & 4) //attack + { + other->enemy = G_PickTarget(self->pathtarget); + if (other->enemy) + { + other->goalentity = other->enemy; + if (self->spawnflags & 32) + other->monsterinfo.aiflags |= AI_BRUTAL; + if (self->spawnflags & 16) + { + other->monsterinfo.aiflags |= AI_STAND_GROUND; + actor_stand (other); + } + else + { + actor_run (other); + } + } + } + + if (!(self->spawnflags & 6) && (self->pathtarget)) + { + char *savetarget; + + savetarget = self->target; + self->target = self->pathtarget; + G_UseTargets (self, other); + self->target = savetarget; + } + + other->movetarget = G_PickTarget(self->target); + + if (!other->goalentity) + other->goalentity = other->movetarget; + + if (!other->movetarget && !other->enemy) + { + other->monsterinfo.pausetime = level.time + 100000000; + other->monsterinfo.stand (other); + } + else if (other->movetarget == other->goalentity) + { + VectorSubtract (other->movetarget->s.origin, other->s.origin, v); + other->ideal_yaw = vectoyaw (v); + } +} + +void SP_target_actor (edict_t *self) +{ + if (!self->targetname) + gi.dprintf ("%s with no targetname at %s\n", self->classname, vtos(self->s.origin)); + + self->solid = SOLID_TRIGGER; + self->touch = target_actor_touch; + VectorSet (self->mins, -8, -8, -8); + VectorSet (self->maxs, 8, 8, 8); + self->svflags = SVF_NOCLIENT; + + if (self->spawnflags & 1) + { + if (!self->speed) + self->speed = 200; + if (!st.height) + st.height = 200; + if (self->s.angles[YAW] == 0) + self->s.angles[YAW] = 360; + G_SetMovedir (self->s.angles, self->movedir); + self->movedir[2] = st.height; + } + + gi.linkentity (self); +} diff --git a/game/m_actor.h b/game/m_actor.h new file mode 100644 index 000000000..5fc0d8df5 --- /dev/null +++ b/game/m_actor.h @@ -0,0 +1,506 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/player_y + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_attak01 0 +#define FRAME_attak02 1 +#define FRAME_attak03 2 +#define FRAME_attak04 3 +#define FRAME_death101 4 +#define FRAME_death102 5 +#define FRAME_death103 6 +#define FRAME_death104 7 +#define FRAME_death105 8 +#define FRAME_death106 9 +#define FRAME_death107 10 +#define FRAME_death201 11 +#define FRAME_death202 12 +#define FRAME_death203 13 +#define FRAME_death204 14 +#define FRAME_death205 15 +#define FRAME_death206 16 +#define FRAME_death207 17 +#define FRAME_death208 18 +#define FRAME_death209 19 +#define FRAME_death210 20 +#define FRAME_death211 21 +#define FRAME_death212 22 +#define FRAME_death213 23 +#define FRAME_death301 24 +#define FRAME_death302 25 +#define FRAME_death303 26 +#define FRAME_death304 27 +#define FRAME_death305 28 +#define FRAME_death306 29 +#define FRAME_death307 30 +#define FRAME_death308 31 +#define FRAME_death309 32 +#define FRAME_death310 33 +#define FRAME_death311 34 +#define FRAME_death312 35 +#define FRAME_death313 36 +#define FRAME_death314 37 +#define FRAME_death315 38 +#define FRAME_flip01 39 +#define FRAME_flip02 40 +#define FRAME_flip03 41 +#define FRAME_flip04 42 +#define FRAME_flip05 43 +#define FRAME_flip06 44 +#define FRAME_flip07 45 +#define FRAME_flip08 46 +#define FRAME_flip09 47 +#define FRAME_flip10 48 +#define FRAME_flip11 49 +#define FRAME_flip12 50 +#define FRAME_flip13 51 +#define FRAME_flip14 52 +#define FRAME_grenad01 53 +#define FRAME_grenad02 54 +#define FRAME_grenad03 55 +#define FRAME_grenad04 56 +#define FRAME_grenad05 57 +#define FRAME_grenad06 58 +#define FRAME_grenad07 59 +#define FRAME_grenad08 60 +#define FRAME_grenad09 61 +#define FRAME_grenad10 62 +#define FRAME_grenad11 63 +#define FRAME_grenad12 64 +#define FRAME_grenad13 65 +#define FRAME_grenad14 66 +#define FRAME_grenad15 67 +#define FRAME_jump01 68 +#define FRAME_jump02 69 +#define FRAME_jump03 70 +#define FRAME_jump04 71 +#define FRAME_jump05 72 +#define FRAME_jump06 73 +#define FRAME_pain101 74 +#define FRAME_pain102 75 +#define FRAME_pain103 76 +#define FRAME_pain201 77 +#define FRAME_pain202 78 +#define FRAME_pain203 79 +#define FRAME_pain301 80 +#define FRAME_pain302 81 +#define FRAME_pain303 82 +#define FRAME_push01 83 +#define FRAME_push02 84 +#define FRAME_push03 85 +#define FRAME_push04 86 +#define FRAME_push05 87 +#define FRAME_push06 88 +#define FRAME_push07 89 +#define FRAME_push08 90 +#define FRAME_push09 91 +#define FRAME_run01 92 +#define FRAME_run02 93 +#define FRAME_run03 94 +#define FRAME_run04 95 +#define FRAME_run05 96 +#define FRAME_run06 97 +#define FRAME_run07 98 +#define FRAME_run08 99 +#define FRAME_run09 100 +#define FRAME_run10 101 +#define FRAME_run11 102 +#define FRAME_run12 103 +#define FRAME_runs01 104 +#define FRAME_runs02 105 +#define FRAME_runs03 106 +#define FRAME_runs04 107 +#define FRAME_runs05 108 +#define FRAME_runs06 109 +#define FRAME_runs07 110 +#define FRAME_runs08 111 +#define FRAME_runs09 112 +#define FRAME_runs10 113 +#define FRAME_runs11 114 +#define FRAME_runs12 115 +#define FRAME_salute01 116 +#define FRAME_salute02 117 +#define FRAME_salute03 118 +#define FRAME_salute04 119 +#define FRAME_salute05 120 +#define FRAME_salute06 121 +#define FRAME_salute07 122 +#define FRAME_salute08 123 +#define FRAME_salute09 124 +#define FRAME_salute10 125 +#define FRAME_salute11 126 +#define FRAME_salute12 127 +#define FRAME_stand101 128 +#define FRAME_stand102 129 +#define FRAME_stand103 130 +#define FRAME_stand104 131 +#define FRAME_stand105 132 +#define FRAME_stand106 133 +#define FRAME_stand107 134 +#define FRAME_stand108 135 +#define FRAME_stand109 136 +#define FRAME_stand110 137 +#define FRAME_stand111 138 +#define FRAME_stand112 139 +#define FRAME_stand113 140 +#define FRAME_stand114 141 +#define FRAME_stand115 142 +#define FRAME_stand116 143 +#define FRAME_stand117 144 +#define FRAME_stand118 145 +#define FRAME_stand119 146 +#define FRAME_stand120 147 +#define FRAME_stand121 148 +#define FRAME_stand122 149 +#define FRAME_stand123 150 +#define FRAME_stand124 151 +#define FRAME_stand125 152 +#define FRAME_stand126 153 +#define FRAME_stand127 154 +#define FRAME_stand128 155 +#define FRAME_stand129 156 +#define FRAME_stand130 157 +#define FRAME_stand131 158 +#define FRAME_stand132 159 +#define FRAME_stand133 160 +#define FRAME_stand134 161 +#define FRAME_stand135 162 +#define FRAME_stand136 163 +#define FRAME_stand137 164 +#define FRAME_stand138 165 +#define FRAME_stand139 166 +#define FRAME_stand140 167 +#define FRAME_stand201 168 +#define FRAME_stand202 169 +#define FRAME_stand203 170 +#define FRAME_stand204 171 +#define FRAME_stand205 172 +#define FRAME_stand206 173 +#define FRAME_stand207 174 +#define FRAME_stand208 175 +#define FRAME_stand209 176 +#define FRAME_stand210 177 +#define FRAME_stand211 178 +#define FRAME_stand212 179 +#define FRAME_stand213 180 +#define FRAME_stand214 181 +#define FRAME_stand215 182 +#define FRAME_stand216 183 +#define FRAME_stand217 184 +#define FRAME_stand218 185 +#define FRAME_stand219 186 +#define FRAME_stand220 187 +#define FRAME_stand221 188 +#define FRAME_stand222 189 +#define FRAME_stand223 190 +#define FRAME_swim01 191 +#define FRAME_swim02 192 +#define FRAME_swim03 193 +#define FRAME_swim04 194 +#define FRAME_swim05 195 +#define FRAME_swim06 196 +#define FRAME_swim07 197 +#define FRAME_swim08 198 +#define FRAME_swim09 199 +#define FRAME_swim10 200 +#define FRAME_swim11 201 +#define FRAME_swim12 202 +#define FRAME_sw_atk01 203 +#define FRAME_sw_atk02 204 +#define FRAME_sw_atk03 205 +#define FRAME_sw_atk04 206 +#define FRAME_sw_atk05 207 +#define FRAME_sw_atk06 208 +#define FRAME_sw_pan01 209 +#define FRAME_sw_pan02 210 +#define FRAME_sw_pan03 211 +#define FRAME_sw_pan04 212 +#define FRAME_sw_pan05 213 +#define FRAME_sw_std01 214 +#define FRAME_sw_std02 215 +#define FRAME_sw_std03 216 +#define FRAME_sw_std04 217 +#define FRAME_sw_std05 218 +#define FRAME_sw_std06 219 +#define FRAME_sw_std07 220 +#define FRAME_sw_std08 221 +#define FRAME_sw_std09 222 +#define FRAME_sw_std10 223 +#define FRAME_sw_std11 224 +#define FRAME_sw_std12 225 +#define FRAME_sw_std13 226 +#define FRAME_sw_std14 227 +#define FRAME_sw_std15 228 +#define FRAME_sw_std16 229 +#define FRAME_sw_std17 230 +#define FRAME_sw_std18 231 +#define FRAME_sw_std19 232 +#define FRAME_sw_std20 233 +#define FRAME_taunt01 234 +#define FRAME_taunt02 235 +#define FRAME_taunt03 236 +#define FRAME_taunt04 237 +#define FRAME_taunt05 238 +#define FRAME_taunt06 239 +#define FRAME_taunt07 240 +#define FRAME_taunt08 241 +#define FRAME_taunt09 242 +#define FRAME_taunt10 243 +#define FRAME_taunt11 244 +#define FRAME_taunt12 245 +#define FRAME_taunt13 246 +#define FRAME_taunt14 247 +#define FRAME_taunt15 248 +#define FRAME_taunt16 249 +#define FRAME_taunt17 250 +#define FRAME_walk01 251 +#define FRAME_walk02 252 +#define FRAME_walk03 253 +#define FRAME_walk04 254 +#define FRAME_walk05 255 +#define FRAME_walk06 256 +#define FRAME_walk07 257 +#define FRAME_walk08 258 +#define FRAME_walk09 259 +#define FRAME_walk10 260 +#define FRAME_walk11 261 +#define FRAME_wave01 262 +#define FRAME_wave02 263 +#define FRAME_wave03 264 +#define FRAME_wave04 265 +#define FRAME_wave05 266 +#define FRAME_wave06 267 +#define FRAME_wave07 268 +#define FRAME_wave08 269 +#define FRAME_wave09 270 +#define FRAME_wave10 271 +#define FRAME_wave11 272 +#define FRAME_wave12 273 +#define FRAME_wave13 274 +#define FRAME_wave14 275 +#define FRAME_wave15 276 +#define FRAME_wave16 277 +#define FRAME_wave17 278 +#define FRAME_wave18 279 +#define FRAME_wave19 280 +#define FRAME_wave20 281 +#define FRAME_wave21 282 +#define FRAME_bl_atk01 283 +#define FRAME_bl_atk02 284 +#define FRAME_bl_atk03 285 +#define FRAME_bl_atk04 286 +#define FRAME_bl_atk05 287 +#define FRAME_bl_atk06 288 +#define FRAME_bl_flp01 289 +#define FRAME_bl_flp02 290 +#define FRAME_bl_flp13 291 +#define FRAME_bl_flp14 292 +#define FRAME_bl_flp15 293 +#define FRAME_bl_jmp01 294 +#define FRAME_bl_jmp02 295 +#define FRAME_bl_jmp03 296 +#define FRAME_bl_jmp04 297 +#define FRAME_bl_jmp05 298 +#define FRAME_bl_jmp06 299 +#define FRAME_bl_pn101 300 +#define FRAME_bl_pn102 301 +#define FRAME_bl_pn103 302 +#define FRAME_bl_pn201 303 +#define FRAME_bl_pn202 304 +#define FRAME_bl_pn203 305 +#define FRAME_bl_pn301 306 +#define FRAME_bl_pn302 307 +#define FRAME_bl_pn303 308 +#define FRAME_bl_psh08 309 +#define FRAME_bl_psh09 310 +#define FRAME_bl_run01 311 +#define FRAME_bl_run02 312 +#define FRAME_bl_run03 313 +#define FRAME_bl_run04 314 +#define FRAME_bl_run05 315 +#define FRAME_bl_run06 316 +#define FRAME_bl_run07 317 +#define FRAME_bl_run08 318 +#define FRAME_bl_run09 319 +#define FRAME_bl_run10 320 +#define FRAME_bl_run11 321 +#define FRAME_bl_run12 322 +#define FRAME_bl_rns03 323 +#define FRAME_bl_rns04 324 +#define FRAME_bl_rns05 325 +#define FRAME_bl_rns06 326 +#define FRAME_bl_rns07 327 +#define FRAME_bl_rns08 328 +#define FRAME_bl_rns09 329 +#define FRAME_bl_sal10 330 +#define FRAME_bl_sal11 331 +#define FRAME_bl_sal12 332 +#define FRAME_bl_std01 333 +#define FRAME_bl_std02 334 +#define FRAME_bl_std03 335 +#define FRAME_bl_std04 336 +#define FRAME_bl_std05 337 +#define FRAME_bl_std06 338 +#define FRAME_bl_std07 339 +#define FRAME_bl_std08 340 +#define FRAME_bl_std09 341 +#define FRAME_bl_std10 342 +#define FRAME_bl_std11 343 +#define FRAME_bl_std12 344 +#define FRAME_bl_std13 345 +#define FRAME_bl_std14 346 +#define FRAME_bl_std15 347 +#define FRAME_bl_std16 348 +#define FRAME_bl_std17 349 +#define FRAME_bl_std18 350 +#define FRAME_bl_std19 351 +#define FRAME_bl_std20 352 +#define FRAME_bl_std21 353 +#define FRAME_bl_std22 354 +#define FRAME_bl_std23 355 +#define FRAME_bl_std24 356 +#define FRAME_bl_std25 357 +#define FRAME_bl_std26 358 +#define FRAME_bl_std27 359 +#define FRAME_bl_std28 360 +#define FRAME_bl_std29 361 +#define FRAME_bl_std30 362 +#define FRAME_bl_std31 363 +#define FRAME_bl_std32 364 +#define FRAME_bl_std33 365 +#define FRAME_bl_std34 366 +#define FRAME_bl_std35 367 +#define FRAME_bl_std36 368 +#define FRAME_bl_std37 369 +#define FRAME_bl_std38 370 +#define FRAME_bl_std39 371 +#define FRAME_bl_std40 372 +#define FRAME_bl_swm01 373 +#define FRAME_bl_swm02 374 +#define FRAME_bl_swm03 375 +#define FRAME_bl_swm04 376 +#define FRAME_bl_swm05 377 +#define FRAME_bl_swm06 378 +#define FRAME_bl_swm07 379 +#define FRAME_bl_swm08 380 +#define FRAME_bl_swm09 381 +#define FRAME_bl_swm10 382 +#define FRAME_bl_swm11 383 +#define FRAME_bl_swm12 384 +#define FRAME_bl_swk01 385 +#define FRAME_bl_swk02 386 +#define FRAME_bl_swk03 387 +#define FRAME_bl_swk04 388 +#define FRAME_bl_swk05 389 +#define FRAME_bl_swk06 390 +#define FRAME_bl_swp01 391 +#define FRAME_bl_swp02 392 +#define FRAME_bl_swp03 393 +#define FRAME_bl_swp04 394 +#define FRAME_bl_swp05 395 +#define FRAME_bl_sws01 396 +#define FRAME_bl_sws02 397 +#define FRAME_bl_sws03 398 +#define FRAME_bl_sws04 399 +#define FRAME_bl_sws05 400 +#define FRAME_bl_sws06 401 +#define FRAME_bl_sws07 402 +#define FRAME_bl_sws08 403 +#define FRAME_bl_sws09 404 +#define FRAME_bl_sws10 405 +#define FRAME_bl_sws11 406 +#define FRAME_bl_sws12 407 +#define FRAME_bl_sws13 408 +#define FRAME_bl_sws14 409 +#define FRAME_bl_tau14 410 +#define FRAME_bl_tau15 411 +#define FRAME_bl_tau16 412 +#define FRAME_bl_tau17 413 +#define FRAME_bl_wlk01 414 +#define FRAME_bl_wlk02 415 +#define FRAME_bl_wlk03 416 +#define FRAME_bl_wlk04 417 +#define FRAME_bl_wlk05 418 +#define FRAME_bl_wlk06 419 +#define FRAME_bl_wlk07 420 +#define FRAME_bl_wlk08 421 +#define FRAME_bl_wlk09 422 +#define FRAME_bl_wlk10 423 +#define FRAME_bl_wlk11 424 +#define FRAME_bl_wav19 425 +#define FRAME_bl_wav20 426 +#define FRAME_bl_wav21 427 +#define FRAME_cr_atk01 428 +#define FRAME_cr_atk02 429 +#define FRAME_cr_atk03 430 +#define FRAME_cr_atk04 431 +#define FRAME_cr_atk05 432 +#define FRAME_cr_atk06 433 +#define FRAME_cr_atk07 434 +#define FRAME_cr_atk08 435 +#define FRAME_cr_pan01 436 +#define FRAME_cr_pan02 437 +#define FRAME_cr_pan03 438 +#define FRAME_cr_pan04 439 +#define FRAME_cr_std01 440 +#define FRAME_cr_std02 441 +#define FRAME_cr_std03 442 +#define FRAME_cr_std04 443 +#define FRAME_cr_std05 444 +#define FRAME_cr_std06 445 +#define FRAME_cr_std07 446 +#define FRAME_cr_std08 447 +#define FRAME_cr_wlk01 448 +#define FRAME_cr_wlk02 449 +#define FRAME_cr_wlk03 450 +#define FRAME_cr_wlk04 451 +#define FRAME_cr_wlk05 452 +#define FRAME_cr_wlk06 453 +#define FRAME_cr_wlk07 454 +#define FRAME_crbl_a01 455 +#define FRAME_crbl_a02 456 +#define FRAME_crbl_a03 457 +#define FRAME_crbl_a04 458 +#define FRAME_crbl_a05 459 +#define FRAME_crbl_a06 460 +#define FRAME_crbl_a07 461 +#define FRAME_crbl_p01 462 +#define FRAME_crbl_p02 463 +#define FRAME_crbl_p03 464 +#define FRAME_crbl_p04 465 +#define FRAME_crbl_s01 466 +#define FRAME_crbl_s02 467 +#define FRAME_crbl_s03 468 +#define FRAME_crbl_s04 469 +#define FRAME_crbl_s05 470 +#define FRAME_crbl_s06 471 +#define FRAME_crbl_s07 472 +#define FRAME_crbl_s08 473 +#define FRAME_crbl_w01 474 +#define FRAME_crbl_w02 475 +#define FRAME_crbl_w03 476 +#define FRAME_crbl_w04 477 +#define FRAME_crbl_w05 478 +#define FRAME_crbl_w06 479 +#define FRAME_crbl_w07 480 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_berserk.c b/game/m_berserk.c new file mode 100644 index 000000000..c5d0bd026 --- /dev/null +++ b/game/m_berserk.c @@ -0,0 +1,457 @@ +/* +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. + +*/ +/* +============================================================================== + +BERSERK + +============================================================================== +*/ + +#include "g_local.h" +#include "m_berserk.h" + + +static int sound_pain; +static int sound_die; +static int sound_idle; +static int sound_punch; +static int sound_sight; +static int sound_search; + +void berserk_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + +void berserk_search (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); +} + + +void berserk_fidget (edict_t *self); +mframe_t berserk_frames_stand [] = +{ + ai_stand, 0, berserk_fidget, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t berserk_move_stand = {FRAME_stand1, FRAME_stand5, berserk_frames_stand, NULL}; + +void berserk_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &berserk_move_stand; +} + +mframe_t berserk_frames_stand_fidget [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t berserk_move_stand_fidget = {FRAME_standb1, FRAME_standb20, berserk_frames_stand_fidget, berserk_stand}; + +void berserk_fidget (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + return; + if (random() > 0.15) + return; + + self->monsterinfo.currentmove = &berserk_move_stand_fidget; + gi.sound (self, CHAN_WEAPON, sound_idle, 1, ATTN_IDLE, 0); +} + + +mframe_t berserk_frames_walk [] = +{ + ai_walk, 9.1, NULL, + ai_walk, 6.3, NULL, + ai_walk, 4.9, NULL, + ai_walk, 6.7, NULL, + ai_walk, 6.0, NULL, + ai_walk, 8.2, NULL, + ai_walk, 7.2, NULL, + ai_walk, 6.1, NULL, + ai_walk, 4.9, NULL, + ai_walk, 4.7, NULL, + ai_walk, 4.7, NULL, + ai_walk, 4.8, NULL +}; +mmove_t berserk_move_walk = {FRAME_walkc1, FRAME_walkc11, berserk_frames_walk, NULL}; + +void berserk_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &berserk_move_walk; +} + +/* + + ***************************** + SKIPPED THIS FOR NOW! + ***************************** + + Running -> Arm raised in air + +void() berserk_runb1 =[ $r_att1 , berserk_runb2 ] {ai_run(21);}; +void() berserk_runb2 =[ $r_att2 , berserk_runb3 ] {ai_run(11);}; +void() berserk_runb3 =[ $r_att3 , berserk_runb4 ] {ai_run(21);}; +void() berserk_runb4 =[ $r_att4 , berserk_runb5 ] {ai_run(25);}; +void() berserk_runb5 =[ $r_att5 , berserk_runb6 ] {ai_run(18);}; +void() berserk_runb6 =[ $r_att6 , berserk_runb7 ] {ai_run(19);}; +// running with arm in air : start loop +void() berserk_runb7 =[ $r_att7 , berserk_runb8 ] {ai_run(21);}; +void() berserk_runb8 =[ $r_att8 , berserk_runb9 ] {ai_run(11);}; +void() berserk_runb9 =[ $r_att9 , berserk_runb10 ] {ai_run(21);}; +void() berserk_runb10 =[ $r_att10 , berserk_runb11 ] {ai_run(25);}; +void() berserk_runb11 =[ $r_att11 , berserk_runb12 ] {ai_run(18);}; +void() berserk_runb12 =[ $r_att12 , berserk_runb7 ] {ai_run(19);}; +// running with arm in air : end loop +*/ + + +mframe_t berserk_frames_run1 [] = +{ + ai_run, 21, NULL, + ai_run, 11, NULL, + ai_run, 21, NULL, + ai_run, 25, NULL, + ai_run, 18, NULL, + ai_run, 19, NULL +}; +mmove_t berserk_move_run1 = {FRAME_run1, FRAME_run6, berserk_frames_run1, NULL}; + +void berserk_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &berserk_move_stand; + else + self->monsterinfo.currentmove = &berserk_move_run1; +} + + +void berserk_attack_spike (edict_t *self) +{ + static vec3_t aim = {MELEE_DISTANCE, 0, -24}; + fire_hit (self, aim, (15 + (rand() % 6)), 400); // Faster attack -- upwards and backwards +} + + +void berserk_swing (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_punch, 1, ATTN_NORM, 0); +} + +mframe_t berserk_frames_attack_spike [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, berserk_swing, + ai_charge, 0, berserk_attack_spike, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t berserk_move_attack_spike = {FRAME_att_c1, FRAME_att_c8, berserk_frames_attack_spike, berserk_run}; + + +void berserk_attack_club (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, self->mins[0], -4); + fire_hit (self, aim, (5 + (rand() % 6)), 400); // Slower attack +} + +mframe_t berserk_frames_attack_club [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, berserk_swing, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, berserk_attack_club, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t berserk_move_attack_club = {FRAME_att_c9, FRAME_att_c20, berserk_frames_attack_club, berserk_run}; + + +void berserk_strike (edict_t *self) +{ + //FIXME play impact sound +} + + +mframe_t berserk_frames_attack_strike [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, berserk_swing, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, berserk_strike, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 9.7, NULL, + ai_move, 13.6, NULL +}; + +mmove_t berserk_move_attack_strike = {FRAME_att_c21, FRAME_att_c34, berserk_frames_attack_strike, berserk_run}; + + +void berserk_melee (edict_t *self) +{ + if ((rand() % 2) == 0) + self->monsterinfo.currentmove = &berserk_move_attack_spike; + else + self->monsterinfo.currentmove = &berserk_move_attack_club; +} + + +/* +void() berserk_atke1 =[ $r_attb1, berserk_atke2 ] {ai_run(9);}; +void() berserk_atke2 =[ $r_attb2, berserk_atke3 ] {ai_run(6);}; +void() berserk_atke3 =[ $r_attb3, berserk_atke4 ] {ai_run(18.4);}; +void() berserk_atke4 =[ $r_attb4, berserk_atke5 ] {ai_run(25);}; +void() berserk_atke5 =[ $r_attb5, berserk_atke6 ] {ai_run(14);}; +void() berserk_atke6 =[ $r_attb6, berserk_atke7 ] {ai_run(20);}; +void() berserk_atke7 =[ $r_attb7, berserk_atke8 ] {ai_run(8.5);}; +void() berserk_atke8 =[ $r_attb8, berserk_atke9 ] {ai_run(3);}; +void() berserk_atke9 =[ $r_attb9, berserk_atke10 ] {ai_run(17.5);}; +void() berserk_atke10 =[ $r_attb10, berserk_atke11 ] {ai_run(17);}; +void() berserk_atke11 =[ $r_attb11, berserk_atke12 ] {ai_run(9);}; +void() berserk_atke12 =[ $r_attb12, berserk_atke13 ] {ai_run(25);}; +void() berserk_atke13 =[ $r_attb13, berserk_atke14 ] {ai_run(3.7);}; +void() berserk_atke14 =[ $r_attb14, berserk_atke15 ] {ai_run(2.6);}; +void() berserk_atke15 =[ $r_attb15, berserk_atke16 ] {ai_run(19);}; +void() berserk_atke16 =[ $r_attb16, berserk_atke17 ] {ai_run(25);}; +void() berserk_atke17 =[ $r_attb17, berserk_atke18 ] {ai_run(19.6);}; +void() berserk_atke18 =[ $r_attb18, berserk_run1 ] {ai_run(7.8);}; +*/ + + +mframe_t berserk_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t berserk_move_pain1 = {FRAME_painc1, FRAME_painc4, berserk_frames_pain1, berserk_run}; + + +mframe_t berserk_frames_pain2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t berserk_move_pain2 = {FRAME_painb1, FRAME_painb20, berserk_frames_pain2, berserk_run}; + +void berserk_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); + + if (skill->value == 3) + return; // no pain anims in nightmare + + if ((damage < 20) || (random() < 0.5)) + self->monsterinfo.currentmove = &berserk_move_pain1; + else + self->monsterinfo.currentmove = &berserk_move_pain2; +} + + +void berserk_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + + +mframe_t berserk_frames_death1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL + +}; +mmove_t berserk_move_death1 = {FRAME_death1, FRAME_death13, berserk_frames_death1, berserk_dead}; + + +mframe_t berserk_frames_death2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t berserk_move_death2 = {FRAME_deathc1, FRAME_deathc8, berserk_frames_death2, berserk_dead}; + + +void berserk_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + + gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + + if (damage >= 50) + self->monsterinfo.currentmove = &berserk_move_death1; + else + self->monsterinfo.currentmove = &berserk_move_death2; +} + + +/*QUAKED monster_berserk (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_berserk (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + // pre-caches + sound_pain = gi.soundindex ("berserk/berpain2.wav"); + sound_die = gi.soundindex ("berserk/berdeth2.wav"); + sound_idle = gi.soundindex ("berserk/beridle1.wav"); + sound_punch = gi.soundindex ("berserk/attack.wav"); + sound_search = gi.soundindex ("berserk/bersrch1.wav"); + sound_sight = gi.soundindex ("berserk/sight.wav"); + + self->s.modelindex = gi.modelindex("models/monsters/berserk/tris.md2"); + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 32); + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + + self->health = 240; + self->gib_health = -60; + self->mass = 250; + + self->pain = berserk_pain; + self->die = berserk_die; + + self->monsterinfo.stand = berserk_stand; + self->monsterinfo.walk = berserk_walk; + self->monsterinfo.run = berserk_run; + self->monsterinfo.dodge = NULL; + self->monsterinfo.attack = NULL; + self->monsterinfo.melee = berserk_melee; + self->monsterinfo.sight = berserk_sight; + self->monsterinfo.search = berserk_search; + + self->monsterinfo.currentmove = &berserk_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + gi.linkentity (self); + + walkmonster_start (self); +} diff --git a/game/m_berserk.h b/game/m_berserk.h new file mode 100644 index 000000000..6cce9e86a --- /dev/null +++ b/game/m_berserk.h @@ -0,0 +1,269 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/berserk + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_stand1 0 +#define FRAME_stand2 1 +#define FRAME_stand3 2 +#define FRAME_stand4 3 +#define FRAME_stand5 4 +#define FRAME_standb1 5 +#define FRAME_standb2 6 +#define FRAME_standb3 7 +#define FRAME_standb4 8 +#define FRAME_standb5 9 +#define FRAME_standb6 10 +#define FRAME_standb7 11 +#define FRAME_standb8 12 +#define FRAME_standb9 13 +#define FRAME_standb10 14 +#define FRAME_standb11 15 +#define FRAME_standb12 16 +#define FRAME_standb13 17 +#define FRAME_standb14 18 +#define FRAME_standb15 19 +#define FRAME_standb16 20 +#define FRAME_standb17 21 +#define FRAME_standb18 22 +#define FRAME_standb19 23 +#define FRAME_standb20 24 +#define FRAME_walkc1 25 +#define FRAME_walkc2 26 +#define FRAME_walkc3 27 +#define FRAME_walkc4 28 +#define FRAME_walkc5 29 +#define FRAME_walkc6 30 +#define FRAME_walkc7 31 +#define FRAME_walkc8 32 +#define FRAME_walkc9 33 +#define FRAME_walkc10 34 +#define FRAME_walkc11 35 +#define FRAME_run1 36 +#define FRAME_run2 37 +#define FRAME_run3 38 +#define FRAME_run4 39 +#define FRAME_run5 40 +#define FRAME_run6 41 +#define FRAME_att_a1 42 +#define FRAME_att_a2 43 +#define FRAME_att_a3 44 +#define FRAME_att_a4 45 +#define FRAME_att_a5 46 +#define FRAME_att_a6 47 +#define FRAME_att_a7 48 +#define FRAME_att_a8 49 +#define FRAME_att_a9 50 +#define FRAME_att_a10 51 +#define FRAME_att_a11 52 +#define FRAME_att_a12 53 +#define FRAME_att_a13 54 +#define FRAME_att_b1 55 +#define FRAME_att_b2 56 +#define FRAME_att_b3 57 +#define FRAME_att_b4 58 +#define FRAME_att_b5 59 +#define FRAME_att_b6 60 +#define FRAME_att_b7 61 +#define FRAME_att_b8 62 +#define FRAME_att_b9 63 +#define FRAME_att_b10 64 +#define FRAME_att_b11 65 +#define FRAME_att_b12 66 +#define FRAME_att_b13 67 +#define FRAME_att_b14 68 +#define FRAME_att_b15 69 +#define FRAME_att_b16 70 +#define FRAME_att_b17 71 +#define FRAME_att_b18 72 +#define FRAME_att_b19 73 +#define FRAME_att_b20 74 +#define FRAME_att_b21 75 +#define FRAME_att_c1 76 +#define FRAME_att_c2 77 +#define FRAME_att_c3 78 +#define FRAME_att_c4 79 +#define FRAME_att_c5 80 +#define FRAME_att_c6 81 +#define FRAME_att_c7 82 +#define FRAME_att_c8 83 +#define FRAME_att_c9 84 +#define FRAME_att_c10 85 +#define FRAME_att_c11 86 +#define FRAME_att_c12 87 +#define FRAME_att_c13 88 +#define FRAME_att_c14 89 +#define FRAME_att_c15 90 +#define FRAME_att_c16 91 +#define FRAME_att_c17 92 +#define FRAME_att_c18 93 +#define FRAME_att_c19 94 +#define FRAME_att_c20 95 +#define FRAME_att_c21 96 +#define FRAME_att_c22 97 +#define FRAME_att_c23 98 +#define FRAME_att_c24 99 +#define FRAME_att_c25 100 +#define FRAME_att_c26 101 +#define FRAME_att_c27 102 +#define FRAME_att_c28 103 +#define FRAME_att_c29 104 +#define FRAME_att_c30 105 +#define FRAME_att_c31 106 +#define FRAME_att_c32 107 +#define FRAME_att_c33 108 +#define FRAME_att_c34 109 +#define FRAME_r_att1 110 +#define FRAME_r_att2 111 +#define FRAME_r_att3 112 +#define FRAME_r_att4 113 +#define FRAME_r_att5 114 +#define FRAME_r_att6 115 +#define FRAME_r_att7 116 +#define FRAME_r_att8 117 +#define FRAME_r_att9 118 +#define FRAME_r_att10 119 +#define FRAME_r_att11 120 +#define FRAME_r_att12 121 +#define FRAME_r_att13 122 +#define FRAME_r_att14 123 +#define FRAME_r_att15 124 +#define FRAME_r_att16 125 +#define FRAME_r_att17 126 +#define FRAME_r_att18 127 +#define FRAME_r_attb1 128 +#define FRAME_r_attb2 129 +#define FRAME_r_attb3 130 +#define FRAME_r_attb4 131 +#define FRAME_r_attb5 132 +#define FRAME_r_attb6 133 +#define FRAME_r_attb7 134 +#define FRAME_r_attb8 135 +#define FRAME_r_attb9 136 +#define FRAME_r_attb10 137 +#define FRAME_r_attb11 138 +#define FRAME_r_attb12 139 +#define FRAME_r_attb13 140 +#define FRAME_r_attb14 141 +#define FRAME_r_attb15 142 +#define FRAME_r_attb16 143 +#define FRAME_r_attb17 144 +#define FRAME_r_attb18 145 +#define FRAME_slam1 146 +#define FRAME_slam2 147 +#define FRAME_slam3 148 +#define FRAME_slam4 149 +#define FRAME_slam5 150 +#define FRAME_slam6 151 +#define FRAME_slam7 152 +#define FRAME_slam8 153 +#define FRAME_slam9 154 +#define FRAME_slam10 155 +#define FRAME_slam11 156 +#define FRAME_slam12 157 +#define FRAME_slam13 158 +#define FRAME_slam14 159 +#define FRAME_slam15 160 +#define FRAME_slam16 161 +#define FRAME_slam17 162 +#define FRAME_slam18 163 +#define FRAME_slam19 164 +#define FRAME_slam20 165 +#define FRAME_slam21 166 +#define FRAME_slam22 167 +#define FRAME_slam23 168 +#define FRAME_duck1 169 +#define FRAME_duck2 170 +#define FRAME_duck3 171 +#define FRAME_duck4 172 +#define FRAME_duck5 173 +#define FRAME_duck6 174 +#define FRAME_duck7 175 +#define FRAME_duck8 176 +#define FRAME_duck9 177 +#define FRAME_duck10 178 +#define FRAME_fall1 179 +#define FRAME_fall2 180 +#define FRAME_fall3 181 +#define FRAME_fall4 182 +#define FRAME_fall5 183 +#define FRAME_fall6 184 +#define FRAME_fall7 185 +#define FRAME_fall8 186 +#define FRAME_fall9 187 +#define FRAME_fall10 188 +#define FRAME_fall11 189 +#define FRAME_fall12 190 +#define FRAME_fall13 191 +#define FRAME_fall14 192 +#define FRAME_fall15 193 +#define FRAME_fall16 194 +#define FRAME_fall17 195 +#define FRAME_fall18 196 +#define FRAME_fall19 197 +#define FRAME_fall20 198 +#define FRAME_painc1 199 +#define FRAME_painc2 200 +#define FRAME_painc3 201 +#define FRAME_painc4 202 +#define FRAME_painb1 203 +#define FRAME_painb2 204 +#define FRAME_painb3 205 +#define FRAME_painb4 206 +#define FRAME_painb5 207 +#define FRAME_painb6 208 +#define FRAME_painb7 209 +#define FRAME_painb8 210 +#define FRAME_painb9 211 +#define FRAME_painb10 212 +#define FRAME_painb11 213 +#define FRAME_painb12 214 +#define FRAME_painb13 215 +#define FRAME_painb14 216 +#define FRAME_painb15 217 +#define FRAME_painb16 218 +#define FRAME_painb17 219 +#define FRAME_painb18 220 +#define FRAME_painb19 221 +#define FRAME_painb20 222 +#define FRAME_death1 223 +#define FRAME_death2 224 +#define FRAME_death3 225 +#define FRAME_death4 226 +#define FRAME_death5 227 +#define FRAME_death6 228 +#define FRAME_death7 229 +#define FRAME_death8 230 +#define FRAME_death9 231 +#define FRAME_death10 232 +#define FRAME_death11 233 +#define FRAME_death12 234 +#define FRAME_death13 235 +#define FRAME_deathc1 236 +#define FRAME_deathc2 237 +#define FRAME_deathc3 238 +#define FRAME_deathc4 239 +#define FRAME_deathc5 240 +#define FRAME_deathc6 241 +#define FRAME_deathc7 242 +#define FRAME_deathc8 243 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_boss2.c b/game/m_boss2.c new file mode 100644 index 000000000..3b64884c3 --- /dev/null +++ b/game/m_boss2.c @@ -0,0 +1,679 @@ +/* +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. + +*/ +/* +============================================================================== + +boss2 + +============================================================================== +*/ + +#include "g_local.h" +#include "m_boss2.h" + +void BossExplode (edict_t *self); + +qboolean infront (edict_t *self, edict_t *other); + +static int sound_pain1; +static int sound_pain2; +static int sound_pain3; +static int sound_death; +static int sound_search1; + +void boss2_search (edict_t *self) +{ + if (random() < 0.5) + gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NONE, 0); +} + +void boss2_run (edict_t *self); +void boss2_stand (edict_t *self); +void boss2_dead (edict_t *self); +void boss2_attack (edict_t *self); +void boss2_attack_mg (edict_t *self); +void boss2_reattack_mg (edict_t *self); +void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); + +void Boss2Rocket (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + + AngleVectors (self->s.angles, forward, right, NULL); + +//1 + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start); + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_1); + +//2 + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start); + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_2); + +//3 + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start); + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_3); + +//4 + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start); + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_4); +} + +void boss2_firebullet_right (edict_t *self) +{ + vec3_t forward, right, target; + vec3_t start; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_R1], forward, right, start); + + VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); + target[2] += self->enemy->viewheight; + VectorSubtract (target, start, forward); + VectorNormalize (forward); + + monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_R1); +} + +void boss2_firebullet_left (edict_t *self) +{ + vec3_t forward, right, target; + vec3_t start; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_L1], forward, right, start); + + VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); + + target[2] += self->enemy->viewheight; + VectorSubtract (target, start, forward); + VectorNormalize (forward); + + monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_L1); +} + +void Boss2MachineGun (edict_t *self) +{ +/* vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + int flash_number; + + AngleVectors (self->s.angles, forward, right, NULL); + + flash_number = MZ2_BOSS2_MACHINEGUN_1 + (self->s.frame - FRAME_attack10); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + monster_fire_bullet (self, start, dir, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); +*/ + boss2_firebullet_left(self); + boss2_firebullet_right(self); +} + + +mframe_t boss2_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t boss2_move_stand = {FRAME_stand30, FRAME_stand50, boss2_frames_stand, NULL}; + +mframe_t boss2_frames_fidget [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t boss2_move_fidget = {FRAME_stand1, FRAME_stand30, boss2_frames_fidget, NULL}; + +mframe_t boss2_frames_walk [] = +{ + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL +}; +mmove_t boss2_move_walk = {FRAME_walk1, FRAME_walk20, boss2_frames_walk, NULL}; + + +mframe_t boss2_frames_run [] = +{ + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL +}; +mmove_t boss2_move_run = {FRAME_walk1, FRAME_walk20, boss2_frames_run, NULL}; + +mframe_t boss2_frames_attack_pre_mg [] = +{ + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, boss2_attack_mg +}; +mmove_t boss2_move_attack_pre_mg = {FRAME_attack1, FRAME_attack9, boss2_frames_attack_pre_mg, NULL}; + + +// Loop this +mframe_t boss2_frames_attack_mg [] = +{ + ai_charge, 1, Boss2MachineGun, + ai_charge, 1, Boss2MachineGun, + ai_charge, 1, Boss2MachineGun, + ai_charge, 1, Boss2MachineGun, + ai_charge, 1, Boss2MachineGun, + ai_charge, 1, boss2_reattack_mg +}; +mmove_t boss2_move_attack_mg = {FRAME_attack10, FRAME_attack15, boss2_frames_attack_mg, NULL}; + +mframe_t boss2_frames_attack_post_mg [] = +{ + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL +}; +mmove_t boss2_move_attack_post_mg = {FRAME_attack16, FRAME_attack19, boss2_frames_attack_post_mg, boss2_run}; + +mframe_t boss2_frames_attack_rocket [] = +{ + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_move, -20, Boss2Rocket, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL +}; +mmove_t boss2_move_attack_rocket = {FRAME_attack20, FRAME_attack40, boss2_frames_attack_rocket, boss2_run}; + +mframe_t boss2_frames_pain_heavy [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t boss2_move_pain_heavy = {FRAME_pain2, FRAME_pain19, boss2_frames_pain_heavy, boss2_run}; + +mframe_t boss2_frames_pain_light [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t boss2_move_pain_light = {FRAME_pain20, FRAME_pain23, boss2_frames_pain_light, boss2_run}; + +mframe_t boss2_frames_death [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, BossExplode +}; +mmove_t boss2_move_death = {FRAME_death2, FRAME_death50, boss2_frames_death, boss2_dead}; + +void boss2_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &boss2_move_stand; +} + +void boss2_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &boss2_move_stand; + else + self->monsterinfo.currentmove = &boss2_move_run; +} + +void boss2_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &boss2_move_walk; +} + +void boss2_attack (edict_t *self) +{ + vec3_t vec; + float range; + + VectorSubtract (self->enemy->s.origin, self->s.origin, vec); + range = VectorLength (vec); + + if (range <= 125) + { + self->monsterinfo.currentmove = &boss2_move_attack_pre_mg; + } + else + { + if (random() <= 0.6) + self->monsterinfo.currentmove = &boss2_move_attack_pre_mg; + else + self->monsterinfo.currentmove = &boss2_move_attack_rocket; + } +} + +void boss2_attack_mg (edict_t *self) +{ + self->monsterinfo.currentmove = &boss2_move_attack_mg; +} + +void boss2_reattack_mg (edict_t *self) +{ + if ( infront(self, self->enemy) ) + if (random() <= 0.7) + self->monsterinfo.currentmove = &boss2_move_attack_mg; + else + self->monsterinfo.currentmove = &boss2_move_attack_post_mg; + else + self->monsterinfo.currentmove = &boss2_move_attack_post_mg; +} + + +void boss2_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; +// American wanted these at no attenuation + if (damage < 10) + { + gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NONE, 0); + self->monsterinfo.currentmove = &boss2_move_pain_light; + } + else if (damage < 30) + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NONE, 0); + self->monsterinfo.currentmove = &boss2_move_pain_light; + } + else + { + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NONE, 0); + self->monsterinfo.currentmove = &boss2_move_pain_heavy; + } +} + +void boss2_dead (edict_t *self) +{ + VectorSet (self->mins, -56, -56, 0); + VectorSet (self->maxs, 56, 56, 80); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_NO; + self->count = 0; + self->monsterinfo.currentmove = &boss2_move_death; +#if 0 + int n; + + self->s.sound = 0; + // check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + self->monsterinfo.currentmove = &boss2_move_death; +#endif +} + +qboolean Boss2_CheckAttack (edict_t *self) +{ + vec3_t spot1, spot2; + vec3_t temp; + float chance; + trace_t tr; + qboolean enemy_infront; + int enemy_range; + float enemy_yaw; + + if (self->enemy->health > 0) + { + // see if any entities are in the way of the shot + VectorCopy (self->s.origin, spot1); + spot1[2] += self->viewheight; + VectorCopy (self->enemy->s.origin, spot2); + spot2[2] += self->enemy->viewheight; + + tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA); + + // do we have a clear shot? + if (tr.ent != self->enemy) + return false; + } + + enemy_infront = infront(self, self->enemy); + enemy_range = range(self, self->enemy); + VectorSubtract (self->enemy->s.origin, self->s.origin, temp); + enemy_yaw = vectoyaw(temp); + + self->ideal_yaw = enemy_yaw; + + + // melee attack + if (enemy_range == RANGE_MELEE) + { + if (self->monsterinfo.melee) + self->monsterinfo.attack_state = AS_MELEE; + else + self->monsterinfo.attack_state = AS_MISSILE; + return true; + } + +// missile attack + if (!self->monsterinfo.attack) + return false; + + if (level.time < self->monsterinfo.attack_finished) + return false; + + if (enemy_range == RANGE_FAR) + return false; + + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + { + chance = 0.4; + } + else if (enemy_range == RANGE_MELEE) + { + chance = 0.8; + } + else if (enemy_range == RANGE_NEAR) + { + chance = 0.8; + } + else if (enemy_range == RANGE_MID) + { + chance = 0.8; + } + else + { + return false; + } + + if (random () < chance) + { + self->monsterinfo.attack_state = AS_MISSILE; + self->monsterinfo.attack_finished = level.time + 2*random(); + return true; + } + + if (self->flags & FL_FLY) + { + if (random() < 0.3) + self->monsterinfo.attack_state = AS_SLIDING; + else + self->monsterinfo.attack_state = AS_STRAIGHT; + } + + return false; +} + + + +/*QUAKED monster_boss2 (1 .5 0) (-56 -56 0) (56 56 80) Ambush Trigger_Spawn Sight +*/ +void SP_monster_boss2 (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_pain1 = gi.soundindex ("bosshovr/bhvpain1.wav"); + sound_pain2 = gi.soundindex ("bosshovr/bhvpain2.wav"); + sound_pain3 = gi.soundindex ("bosshovr/bhvpain3.wav"); + sound_death = gi.soundindex ("bosshovr/bhvdeth1.wav"); + sound_search1 = gi.soundindex ("bosshovr/bhvunqv1.wav"); + + self->s.sound = gi.soundindex ("bosshovr/bhvengn1.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/boss2/tris.md2"); + VectorSet (self->mins, -56, -56, 0); + VectorSet (self->maxs, 56, 56, 80); + + self->health = 2000; + self->gib_health = -200; + self->mass = 1000; + + self->flags |= FL_IMMUNE_LASER; + + self->pain = boss2_pain; + self->die = boss2_die; + + self->monsterinfo.stand = boss2_stand; + self->monsterinfo.walk = boss2_walk; + self->monsterinfo.run = boss2_run; + self->monsterinfo.attack = boss2_attack; + self->monsterinfo.search = boss2_search; + self->monsterinfo.checkattack = Boss2_CheckAttack; + gi.linkentity (self); + + self->monsterinfo.currentmove = &boss2_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + flymonster_start (self); +} diff --git a/game/m_boss2.h b/game/m_boss2.h new file mode 100644 index 000000000..05b0a08b5 --- /dev/null +++ b/game/m_boss2.h @@ -0,0 +1,206 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/boss2 + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_stand30 0 +#define FRAME_stand31 1 +#define FRAME_stand32 2 +#define FRAME_stand33 3 +#define FRAME_stand34 4 +#define FRAME_stand35 5 +#define FRAME_stand36 6 +#define FRAME_stand37 7 +#define FRAME_stand38 8 +#define FRAME_stand39 9 +#define FRAME_stand40 10 +#define FRAME_stand41 11 +#define FRAME_stand42 12 +#define FRAME_stand43 13 +#define FRAME_stand44 14 +#define FRAME_stand45 15 +#define FRAME_stand46 16 +#define FRAME_stand47 17 +#define FRAME_stand48 18 +#define FRAME_stand49 19 +#define FRAME_stand50 20 +#define FRAME_stand1 21 +#define FRAME_stand2 22 +#define FRAME_stand3 23 +#define FRAME_stand4 24 +#define FRAME_stand5 25 +#define FRAME_stand6 26 +#define FRAME_stand7 27 +#define FRAME_stand8 28 +#define FRAME_stand9 29 +#define FRAME_stand10 30 +#define FRAME_stand11 31 +#define FRAME_stand12 32 +#define FRAME_stand13 33 +#define FRAME_stand14 34 +#define FRAME_stand15 35 +#define FRAME_stand16 36 +#define FRAME_stand17 37 +#define FRAME_stand18 38 +#define FRAME_stand19 39 +#define FRAME_stand20 40 +#define FRAME_stand21 41 +#define FRAME_stand22 42 +#define FRAME_stand23 43 +#define FRAME_stand24 44 +#define FRAME_stand25 45 +#define FRAME_stand26 46 +#define FRAME_stand27 47 +#define FRAME_stand28 48 +#define FRAME_stand29 49 +#define FRAME_walk1 50 +#define FRAME_walk2 51 +#define FRAME_walk3 52 +#define FRAME_walk4 53 +#define FRAME_walk5 54 +#define FRAME_walk6 55 +#define FRAME_walk7 56 +#define FRAME_walk8 57 +#define FRAME_walk9 58 +#define FRAME_walk10 59 +#define FRAME_walk11 60 +#define FRAME_walk12 61 +#define FRAME_walk13 62 +#define FRAME_walk14 63 +#define FRAME_walk15 64 +#define FRAME_walk16 65 +#define FRAME_walk17 66 +#define FRAME_walk18 67 +#define FRAME_walk19 68 +#define FRAME_walk20 69 +#define FRAME_attack1 70 +#define FRAME_attack2 71 +#define FRAME_attack3 72 +#define FRAME_attack4 73 +#define FRAME_attack5 74 +#define FRAME_attack6 75 +#define FRAME_attack7 76 +#define FRAME_attack8 77 +#define FRAME_attack9 78 +#define FRAME_attack10 79 +#define FRAME_attack11 80 +#define FRAME_attack12 81 +#define FRAME_attack13 82 +#define FRAME_attack14 83 +#define FRAME_attack15 84 +#define FRAME_attack16 85 +#define FRAME_attack17 86 +#define FRAME_attack18 87 +#define FRAME_attack19 88 +#define FRAME_attack20 89 +#define FRAME_attack21 90 +#define FRAME_attack22 91 +#define FRAME_attack23 92 +#define FRAME_attack24 93 +#define FRAME_attack25 94 +#define FRAME_attack26 95 +#define FRAME_attack27 96 +#define FRAME_attack28 97 +#define FRAME_attack29 98 +#define FRAME_attack30 99 +#define FRAME_attack31 100 +#define FRAME_attack32 101 +#define FRAME_attack33 102 +#define FRAME_attack34 103 +#define FRAME_attack35 104 +#define FRAME_attack36 105 +#define FRAME_attack37 106 +#define FRAME_attack38 107 +#define FRAME_attack39 108 +#define FRAME_attack40 109 +#define FRAME_pain2 110 +#define FRAME_pain3 111 +#define FRAME_pain4 112 +#define FRAME_pain5 113 +#define FRAME_pain6 114 +#define FRAME_pain7 115 +#define FRAME_pain8 116 +#define FRAME_pain9 117 +#define FRAME_pain10 118 +#define FRAME_pain11 119 +#define FRAME_pain12 120 +#define FRAME_pain13 121 +#define FRAME_pain14 122 +#define FRAME_pain15 123 +#define FRAME_pain16 124 +#define FRAME_pain17 125 +#define FRAME_pain18 126 +#define FRAME_pain19 127 +#define FRAME_pain20 128 +#define FRAME_pain21 129 +#define FRAME_pain22 130 +#define FRAME_pain23 131 +#define FRAME_death2 132 +#define FRAME_death3 133 +#define FRAME_death4 134 +#define FRAME_death5 135 +#define FRAME_death6 136 +#define FRAME_death7 137 +#define FRAME_death8 138 +#define FRAME_death9 139 +#define FRAME_death10 140 +#define FRAME_death11 141 +#define FRAME_death12 142 +#define FRAME_death13 143 +#define FRAME_death14 144 +#define FRAME_death15 145 +#define FRAME_death16 146 +#define FRAME_death17 147 +#define FRAME_death18 148 +#define FRAME_death19 149 +#define FRAME_death20 150 +#define FRAME_death21 151 +#define FRAME_death22 152 +#define FRAME_death23 153 +#define FRAME_death24 154 +#define FRAME_death25 155 +#define FRAME_death26 156 +#define FRAME_death27 157 +#define FRAME_death28 158 +#define FRAME_death29 159 +#define FRAME_death30 160 +#define FRAME_death31 161 +#define FRAME_death32 162 +#define FRAME_death33 163 +#define FRAME_death34 164 +#define FRAME_death35 165 +#define FRAME_death36 166 +#define FRAME_death37 167 +#define FRAME_death38 168 +#define FRAME_death39 169 +#define FRAME_death40 170 +#define FRAME_death41 171 +#define FRAME_death42 172 +#define FRAME_death43 173 +#define FRAME_death44 174 +#define FRAME_death45 175 +#define FRAME_death46 176 +#define FRAME_death47 177 +#define FRAME_death48 178 +#define FRAME_death49 179 +#define FRAME_death50 180 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_boss3.c b/game/m_boss3.c new file mode 100644 index 000000000..d1f11df5f --- /dev/null +++ b/game/m_boss3.c @@ -0,0 +1,76 @@ +/* +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. + +*/ +/* +============================================================================== + +boss3 + +============================================================================== +*/ + +#include "g_local.h" +#include "m_boss32.h" + +void Use_Boss3 (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); + G_FreeEdict (ent); +} + +void Think_Boss3Stand (edict_t *ent) +{ + if (ent->s.frame == FRAME_stand260) + ent->s.frame = FRAME_stand201; + else + ent->s.frame++; + ent->nextthink = level.time + FRAMETIME; +} + +/*QUAKED monster_boss3_stand (1 .5 0) (-32 -32 0) (32 32 90) + +Just stands and cycles in one place until targeted, then teleports away. +*/ +void SP_monster_boss3_stand (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->model = "models/monsters/boss3/rider/tris.md2"; + self->s.modelindex = gi.modelindex (self->model); + self->s.frame = FRAME_stand201; + + gi.soundindex ("misc/bigtele.wav"); + + VectorSet (self->mins, -32, -32, 0); + VectorSet (self->maxs, 32, 32, 90); + + self->use = Use_Boss3; + self->think = Think_Boss3Stand; + self->nextthink = level.time + FRAMETIME; + gi.linkentity (self); +} diff --git a/game/m_boss31.c b/game/m_boss31.c new file mode 100644 index 000000000..7c91d9912 --- /dev/null +++ b/game/m_boss31.c @@ -0,0 +1,749 @@ +/* +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. + +*/ +/* +============================================================================== + +jorg + +============================================================================== +*/ + +#include "g_local.h" +#include "m_boss31.h" + +extern SP_monster_makron (edict_t *self); +qboolean visible (edict_t *self, edict_t *other); + +static int sound_pain1; +static int sound_pain2; +static int sound_pain3; +static int sound_idle; +static int sound_death; +static int sound_search1; +static int sound_search2; +static int sound_search3; +static int sound_attack1; +static int sound_attack2; +static int sound_firegun; +static int sound_step_left; +static int sound_step_right; +static int sound_death_hit; + +void BossExplode (edict_t *self); +void MakronToss (edict_t *self); + + +void jorg_search (edict_t *self) +{ + float r; + + r = random(); + + if (r <= 0.3) + gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0); + else if (r <= 0.6) + gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_search3, 1, ATTN_NORM, 0); +} + + +void jorg_dead (edict_t *self); +void jorgBFG (edict_t *self); +void jorgMachineGun (edict_t *self); +void jorg_firebullet (edict_t *self); +void jorg_reattack1(edict_t *self); +void jorg_attack1(edict_t *self); +void jorg_idle(edict_t *self); +void jorg_step_left(edict_t *self); +void jorg_step_right(edict_t *self); +void jorg_death_hit(edict_t *self); + +// +// stand +// + +mframe_t jorg_frames_stand []= +{ + ai_stand, 0, jorg_idle, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 10 + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 20 + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 30 + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 19, NULL, + ai_stand, 11, jorg_step_left, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 6, NULL, + ai_stand, 9, jorg_step_right, + ai_stand, 0, NULL, // 40 + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, -2, NULL, + ai_stand, -17, jorg_step_left, + ai_stand, 0, NULL, + ai_stand, -12, NULL, // 50 + ai_stand, -14, jorg_step_right // 51 +}; +mmove_t jorg_move_stand = {FRAME_stand01, FRAME_stand51, jorg_frames_stand, NULL}; + +void jorg_idle (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_NORM,0); +} + +void jorg_death_hit (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_death_hit, 1, ATTN_NORM,0); +} + + +void jorg_step_left (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_step_left, 1, ATTN_NORM,0); +} + +void jorg_step_right (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_step_right, 1, ATTN_NORM,0); +} + + +void jorg_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &jorg_move_stand; +} + +mframe_t jorg_frames_run [] = +{ + ai_run, 17, jorg_step_left, + ai_run, 0, NULL, + ai_run, 0, NULL, + ai_run, 0, NULL, + ai_run, 12, NULL, + ai_run, 8, NULL, + ai_run, 10, NULL, + ai_run, 33, jorg_step_right, + ai_run, 0, NULL, + ai_run, 0, NULL, + ai_run, 0, NULL, + ai_run, 9, NULL, + ai_run, 9, NULL, + ai_run, 9, NULL +}; +mmove_t jorg_move_run = {FRAME_walk06, FRAME_walk19, jorg_frames_run, NULL}; + +// +// walk +// + +mframe_t jorg_frames_start_walk [] = +{ + ai_walk, 5, NULL, + ai_walk, 6, NULL, + ai_walk, 7, NULL, + ai_walk, 9, NULL, + ai_walk, 15, NULL +}; +mmove_t jorg_move_start_walk = {FRAME_walk01, FRAME_walk05, jorg_frames_start_walk, NULL}; + +mframe_t jorg_frames_walk [] = +{ + ai_walk, 17, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 12, NULL, + ai_walk, 8, NULL, + ai_walk, 10, NULL, + ai_walk, 33, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 9, NULL, + ai_walk, 9, NULL, + ai_walk, 9, NULL +}; +mmove_t jorg_move_walk = {FRAME_walk06, FRAME_walk19, jorg_frames_walk, NULL}; + +mframe_t jorg_frames_end_walk [] = +{ + ai_walk, 11, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 8, NULL, + ai_walk, -8, NULL +}; +mmove_t jorg_move_end_walk = {FRAME_walk20, FRAME_walk25, jorg_frames_end_walk, NULL}; + +void jorg_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &jorg_move_walk; +} + +void jorg_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &jorg_move_stand; + else + self->monsterinfo.currentmove = &jorg_move_run; +} + +mframe_t jorg_frames_pain3 [] = +{ + ai_move, -28, NULL, + ai_move, -6, NULL, + ai_move, -3, jorg_step_left, + ai_move, -9, NULL, + ai_move, 0, jorg_step_right, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -7, NULL, + ai_move, 1, NULL, + ai_move, -11, NULL, + ai_move, -4, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 10, NULL, + ai_move, 11, NULL, + ai_move, 0, NULL, + ai_move, 10, NULL, + ai_move, 3, NULL, + ai_move, 10, NULL, + ai_move, 7, jorg_step_left, + ai_move, 17, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, jorg_step_right +}; +mmove_t jorg_move_pain3 = {FRAME_pain301, FRAME_pain325, jorg_frames_pain3, jorg_run}; + +mframe_t jorg_frames_pain2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t jorg_move_pain2 = {FRAME_pain201, FRAME_pain203, jorg_frames_pain2, jorg_run}; + +mframe_t jorg_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t jorg_move_pain1 = {FRAME_pain101, FRAME_pain103, jorg_frames_pain1, jorg_run}; + +mframe_t jorg_frames_death1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 10 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 20 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 30 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 40 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, MakronToss, + ai_move, 0, BossExplode // 50 +}; +mmove_t jorg_move_death = {FRAME_death01, FRAME_death50, jorg_frames_death1, jorg_dead}; + +mframe_t jorg_frames_attack2 []= +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, jorgBFG, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t jorg_move_attack2 = {FRAME_attak201, FRAME_attak213, jorg_frames_attack2, jorg_run}; + +mframe_t jorg_frames_start_attack1 [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t jorg_move_start_attack1 = {FRAME_attak101, FRAME_attak108, jorg_frames_start_attack1, jorg_attack1}; + +mframe_t jorg_frames_attack1[]= +{ + ai_charge, 0, jorg_firebullet, + ai_charge, 0, jorg_firebullet, + ai_charge, 0, jorg_firebullet, + ai_charge, 0, jorg_firebullet, + ai_charge, 0, jorg_firebullet, + ai_charge, 0, jorg_firebullet +}; +mmove_t jorg_move_attack1 = {FRAME_attak109, FRAME_attak114, jorg_frames_attack1, jorg_reattack1}; + +mframe_t jorg_frames_end_attack1[]= +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t jorg_move_end_attack1 = {FRAME_attak115, FRAME_attak118, jorg_frames_end_attack1, jorg_run}; + +void jorg_reattack1(edict_t *self) +{ + if (visible(self, self->enemy)) + if (random() < 0.9) + self->monsterinfo.currentmove = &jorg_move_attack1; + else + { + self->s.sound = 0; + self->monsterinfo.currentmove = &jorg_move_end_attack1; + } + else + { + self->s.sound = 0; + self->monsterinfo.currentmove = &jorg_move_end_attack1; + } +} + +void jorg_attack1(edict_t *self) +{ + self->monsterinfo.currentmove = &jorg_move_attack1; +} + +void jorg_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + self->s.sound = 0; + + if (level.time < self->pain_debounce_time) + return; + + // Lessen the chance of him going into his pain frames if he takes little damage + if (damage <= 40) + if (random()<=0.6) + return; + + /* + If he's entering his attack1 or using attack1, lessen the chance of him + going into pain + */ + + if ( (self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak108) ) + if (random() <= 0.005) + return; + + if ( (self->s.frame >= FRAME_attak109) && (self->s.frame <= FRAME_attak114) ) + if (random() <= 0.00005) + return; + + + if ( (self->s.frame >= FRAME_attak201) && (self->s.frame <= FRAME_attak208) ) + if (random() <= 0.005) + return; + + + self->pain_debounce_time = level.time + 3; + if (skill->value == 3) + return; // no pain anims in nightmare + + if (damage <= 50) + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM,0); + self->monsterinfo.currentmove = &jorg_move_pain1; + } + else if (damage <= 100) + { + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM,0); + self->monsterinfo.currentmove = &jorg_move_pain2; + } + else + { + if (random() <= 0.3) + { + gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM,0); + self->monsterinfo.currentmove = &jorg_move_pain3; + } + } +}; + +void jorgBFG (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_BFG_1], forward, right, start); + + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + gi.sound (self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM, 0); + /*void monster_fire_bfg (edict_t *self, + vec3_t start, + vec3_t aimdir, + int damage, + int speed, + int kick, + float damage_radius, + int flashtype)*/ + monster_fire_bfg (self, start, dir, 50, 300, 100, 200, MZ2_JORG_BFG_1); +} + +void jorg_firebullet_right (edict_t *self) +{ + vec3_t forward, right, target; + vec3_t start; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_R1], forward, right, start); + + VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); + target[2] += self->enemy->viewheight; + VectorSubtract (target, start, forward); + VectorNormalize (forward); + + monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_R1); +} + +void jorg_firebullet_left (edict_t *self) +{ + vec3_t forward, right, target; + vec3_t start; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_L1], forward, right, start); + + VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); + target[2] += self->enemy->viewheight; + VectorSubtract (target, start, forward); + VectorNormalize (forward); + + monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_L1); +} + +void jorg_firebullet (edict_t *self) +{ + jorg_firebullet_left(self); + jorg_firebullet_right(self); +}; + +void jorg_attack(edict_t *self) +{ + vec3_t vec; + float range; + + VectorSubtract (self->enemy->s.origin, self->s.origin, vec); + range = VectorLength (vec); + + if (random() <= 0.75) + { + gi.sound (self, CHAN_VOICE, sound_attack1, 1, ATTN_NORM,0); + self->s.sound = gi.soundindex ("boss3/w_loop.wav"); + self->monsterinfo.currentmove = &jorg_move_start_attack1; + } + else + { + gi.sound (self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM,0); + self->monsterinfo.currentmove = &jorg_move_attack2; + } +} + +void jorg_dead (edict_t *self) +{ +#if 0 + edict_t *tempent; + /* + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + */ + + // Jorg is on modelindex2. Do not clear him. + VectorSet (self->mins, -60, -60, 0); + VectorSet (self->maxs, 60, 60, 72); + self->movetype = MOVETYPE_TOSS; + self->nextthink = 0; + gi.linkentity (self); + + tempent = G_Spawn(); + VectorCopy (self->s.origin, tempent->s.origin); + VectorCopy (self->s.angles, tempent->s.angles); + tempent->killtarget = self->killtarget; + tempent->target = self->target; + tempent->activator = self->enemy; + self->killtarget = 0; + self->target = 0; + SP_monster_makron (tempent); +#endif +} + + +void jorg_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_NO; + self->s.sound = 0; + self->count = 0; + self->monsterinfo.currentmove = &jorg_move_death; +} + +qboolean Jorg_CheckAttack (edict_t *self) +{ + vec3_t spot1, spot2; + vec3_t temp; + float chance; + trace_t tr; + qboolean enemy_infront; + int enemy_range; + float enemy_yaw; + + if (self->enemy->health > 0) + { + // see if any entities are in the way of the shot + VectorCopy (self->s.origin, spot1); + spot1[2] += self->viewheight; + VectorCopy (self->enemy->s.origin, spot2); + spot2[2] += self->enemy->viewheight; + + tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA); + + // do we have a clear shot? + if (tr.ent != self->enemy) + return false; + } + + enemy_infront = infront(self, self->enemy); + enemy_range = range(self, self->enemy); + VectorSubtract (self->enemy->s.origin, self->s.origin, temp); + enemy_yaw = vectoyaw(temp); + + self->ideal_yaw = enemy_yaw; + + + // melee attack + if (enemy_range == RANGE_MELEE) + { + if (self->monsterinfo.melee) + self->monsterinfo.attack_state = AS_MELEE; + else + self->monsterinfo.attack_state = AS_MISSILE; + return true; + } + +// missile attack + if (!self->monsterinfo.attack) + return false; + + if (level.time < self->monsterinfo.attack_finished) + return false; + + if (enemy_range == RANGE_FAR) + return false; + + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + { + chance = 0.4; + } + else if (enemy_range == RANGE_MELEE) + { + chance = 0.8; + } + else if (enemy_range == RANGE_NEAR) + { + chance = 0.4; + } + else if (enemy_range == RANGE_MID) + { + chance = 0.2; + } + else + { + return false; + } + + if (random () < chance) + { + self->monsterinfo.attack_state = AS_MISSILE; + self->monsterinfo.attack_finished = level.time + 2*random(); + return true; + } + + if (self->flags & FL_FLY) + { + if (random() < 0.3) + self->monsterinfo.attack_state = AS_SLIDING; + else + self->monsterinfo.attack_state = AS_STRAIGHT; + } + + return false; +} + + +void MakronPrecache (void); + +/*QUAKED monster_jorg (1 .5 0) (-80 -80 0) (90 90 140) Ambush Trigger_Spawn Sight +*/ +void SP_monster_jorg (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_pain1 = gi.soundindex ("boss3/bs3pain1.wav"); + sound_pain2 = gi.soundindex ("boss3/bs3pain2.wav"); + sound_pain3 = gi.soundindex ("boss3/bs3pain3.wav"); + sound_death = gi.soundindex ("boss3/bs3deth1.wav"); + sound_attack1 = gi.soundindex ("boss3/bs3atck1.wav"); + sound_attack2 = gi.soundindex ("boss3/bs3atck2.wav"); + sound_search1 = gi.soundindex ("boss3/bs3srch1.wav"); + sound_search2 = gi.soundindex ("boss3/bs3srch2.wav"); + sound_search3 = gi.soundindex ("boss3/bs3srch3.wav"); + sound_idle = gi.soundindex ("boss3/bs3idle1.wav"); + sound_step_left = gi.soundindex ("boss3/step1.wav"); + sound_step_right = gi.soundindex ("boss3/step2.wav"); + sound_firegun = gi.soundindex ("boss3/xfire.wav"); + sound_death_hit = gi.soundindex ("boss3/d_hit.wav"); + + MakronPrecache (); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2"); + self->s.modelindex2 = gi.modelindex ("models/monsters/boss3/jorg/tris.md2"); + VectorSet (self->mins, -80, -80, 0); + VectorSet (self->maxs, 80, 80, 140); + + self->health = 3000; + self->gib_health = -2000; + self->mass = 1000; + + self->pain = jorg_pain; + self->die = jorg_die; + self->monsterinfo.stand = jorg_stand; + self->monsterinfo.walk = jorg_walk; + self->monsterinfo.run = jorg_run; + self->monsterinfo.dodge = NULL; + self->monsterinfo.attack = jorg_attack; + self->monsterinfo.search = jorg_search; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = NULL; + self->monsterinfo.checkattack = Jorg_CheckAttack; + gi.linkentity (self); + + self->monsterinfo.currentmove = &jorg_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start(self); +} diff --git a/game/m_boss31.h b/game/m_boss31.h new file mode 100644 index 000000000..39f3af55c --- /dev/null +++ b/game/m_boss31.h @@ -0,0 +1,213 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/boss3/jorg + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_attak101 0 +#define FRAME_attak102 1 +#define FRAME_attak103 2 +#define FRAME_attak104 3 +#define FRAME_attak105 4 +#define FRAME_attak106 5 +#define FRAME_attak107 6 +#define FRAME_attak108 7 +#define FRAME_attak109 8 +#define FRAME_attak110 9 +#define FRAME_attak111 10 +#define FRAME_attak112 11 +#define FRAME_attak113 12 +#define FRAME_attak114 13 +#define FRAME_attak115 14 +#define FRAME_attak116 15 +#define FRAME_attak117 16 +#define FRAME_attak118 17 +#define FRAME_attak201 18 +#define FRAME_attak202 19 +#define FRAME_attak203 20 +#define FRAME_attak204 21 +#define FRAME_attak205 22 +#define FRAME_attak206 23 +#define FRAME_attak207 24 +#define FRAME_attak208 25 +#define FRAME_attak209 26 +#define FRAME_attak210 27 +#define FRAME_attak211 28 +#define FRAME_attak212 29 +#define FRAME_attak213 30 +#define FRAME_death01 31 +#define FRAME_death02 32 +#define FRAME_death03 33 +#define FRAME_death04 34 +#define FRAME_death05 35 +#define FRAME_death06 36 +#define FRAME_death07 37 +#define FRAME_death08 38 +#define FRAME_death09 39 +#define FRAME_death10 40 +#define FRAME_death11 41 +#define FRAME_death12 42 +#define FRAME_death13 43 +#define FRAME_death14 44 +#define FRAME_death15 45 +#define FRAME_death16 46 +#define FRAME_death17 47 +#define FRAME_death18 48 +#define FRAME_death19 49 +#define FRAME_death20 50 +#define FRAME_death21 51 +#define FRAME_death22 52 +#define FRAME_death23 53 +#define FRAME_death24 54 +#define FRAME_death25 55 +#define FRAME_death26 56 +#define FRAME_death27 57 +#define FRAME_death28 58 +#define FRAME_death29 59 +#define FRAME_death30 60 +#define FRAME_death31 61 +#define FRAME_death32 62 +#define FRAME_death33 63 +#define FRAME_death34 64 +#define FRAME_death35 65 +#define FRAME_death36 66 +#define FRAME_death37 67 +#define FRAME_death38 68 +#define FRAME_death39 69 +#define FRAME_death40 70 +#define FRAME_death41 71 +#define FRAME_death42 72 +#define FRAME_death43 73 +#define FRAME_death44 74 +#define FRAME_death45 75 +#define FRAME_death46 76 +#define FRAME_death47 77 +#define FRAME_death48 78 +#define FRAME_death49 79 +#define FRAME_death50 80 +#define FRAME_pain101 81 +#define FRAME_pain102 82 +#define FRAME_pain103 83 +#define FRAME_pain201 84 +#define FRAME_pain202 85 +#define FRAME_pain203 86 +#define FRAME_pain301 87 +#define FRAME_pain302 88 +#define FRAME_pain303 89 +#define FRAME_pain304 90 +#define FRAME_pain305 91 +#define FRAME_pain306 92 +#define FRAME_pain307 93 +#define FRAME_pain308 94 +#define FRAME_pain309 95 +#define FRAME_pain310 96 +#define FRAME_pain311 97 +#define FRAME_pain312 98 +#define FRAME_pain313 99 +#define FRAME_pain314 100 +#define FRAME_pain315 101 +#define FRAME_pain316 102 +#define FRAME_pain317 103 +#define FRAME_pain318 104 +#define FRAME_pain319 105 +#define FRAME_pain320 106 +#define FRAME_pain321 107 +#define FRAME_pain322 108 +#define FRAME_pain323 109 +#define FRAME_pain324 110 +#define FRAME_pain325 111 +#define FRAME_stand01 112 +#define FRAME_stand02 113 +#define FRAME_stand03 114 +#define FRAME_stand04 115 +#define FRAME_stand05 116 +#define FRAME_stand06 117 +#define FRAME_stand07 118 +#define FRAME_stand08 119 +#define FRAME_stand09 120 +#define FRAME_stand10 121 +#define FRAME_stand11 122 +#define FRAME_stand12 123 +#define FRAME_stand13 124 +#define FRAME_stand14 125 +#define FRAME_stand15 126 +#define FRAME_stand16 127 +#define FRAME_stand17 128 +#define FRAME_stand18 129 +#define FRAME_stand19 130 +#define FRAME_stand20 131 +#define FRAME_stand21 132 +#define FRAME_stand22 133 +#define FRAME_stand23 134 +#define FRAME_stand24 135 +#define FRAME_stand25 136 +#define FRAME_stand26 137 +#define FRAME_stand27 138 +#define FRAME_stand28 139 +#define FRAME_stand29 140 +#define FRAME_stand30 141 +#define FRAME_stand31 142 +#define FRAME_stand32 143 +#define FRAME_stand33 144 +#define FRAME_stand34 145 +#define FRAME_stand35 146 +#define FRAME_stand36 147 +#define FRAME_stand37 148 +#define FRAME_stand38 149 +#define FRAME_stand39 150 +#define FRAME_stand40 151 +#define FRAME_stand41 152 +#define FRAME_stand42 153 +#define FRAME_stand43 154 +#define FRAME_stand44 155 +#define FRAME_stand45 156 +#define FRAME_stand46 157 +#define FRAME_stand47 158 +#define FRAME_stand48 159 +#define FRAME_stand49 160 +#define FRAME_stand50 161 +#define FRAME_stand51 162 +#define FRAME_walk01 163 +#define FRAME_walk02 164 +#define FRAME_walk03 165 +#define FRAME_walk04 166 +#define FRAME_walk05 167 +#define FRAME_walk06 168 +#define FRAME_walk07 169 +#define FRAME_walk08 170 +#define FRAME_walk09 171 +#define FRAME_walk10 172 +#define FRAME_walk11 173 +#define FRAME_walk12 174 +#define FRAME_walk13 175 +#define FRAME_walk14 176 +#define FRAME_walk15 177 +#define FRAME_walk16 178 +#define FRAME_walk17 179 +#define FRAME_walk18 180 +#define FRAME_walk19 181 +#define FRAME_walk20 182 +#define FRAME_walk21 183 +#define FRAME_walk22 184 +#define FRAME_walk23 185 +#define FRAME_walk24 186 +#define FRAME_walk25 187 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_boss32.c b/game/m_boss32.c new file mode 100644 index 000000000..c4c19ded0 --- /dev/null +++ b/game/m_boss32.c @@ -0,0 +1,913 @@ +/* +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. + +*/ +/* +============================================================================== + +Makron -- Final Boss + +============================================================================== +*/ + +#include "g_local.h" +#include "m_boss32.h" + +qboolean visible (edict_t *self, edict_t *other); + +void MakronRailgun (edict_t *self); +void MakronSaveloc (edict_t *self); +void MakronHyperblaster (edict_t *self); +void makron_step_left (edict_t *self); +void makron_step_right (edict_t *self); +void makronBFG (edict_t *self); +void makron_dead (edict_t *self); + +static int sound_pain4; +static int sound_pain5; +static int sound_pain6; +static int sound_death; +static int sound_step_left; +static int sound_step_right; +static int sound_attack_bfg; +static int sound_brainsplorch; +static int sound_prerailgun; +static int sound_popup; +static int sound_taunt1; +static int sound_taunt2; +static int sound_taunt3; +static int sound_hit; + +void makron_taunt (edict_t *self) +{ + float r; + + r=random(); + if (r <= 0.3) + gi.sound (self, CHAN_AUTO, sound_taunt1, 1, ATTN_NONE, 0); + else if (r <= 0.6) + gi.sound (self, CHAN_AUTO, sound_taunt2, 1, ATTN_NONE, 0); + else + gi.sound (self, CHAN_AUTO, sound_taunt3, 1, ATTN_NONE, 0); +} + +// +// stand +// + +mframe_t makron_frames_stand []= +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 10 + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 20 + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 30 + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 40 + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 50 + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL // 60 +}; +mmove_t makron_move_stand = {FRAME_stand201, FRAME_stand260, makron_frames_stand, NULL}; + +void makron_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &makron_move_stand; +} + +mframe_t makron_frames_run [] = +{ + ai_run, 3, makron_step_left, + ai_run, 12, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, makron_step_right, + ai_run, 6, NULL, + ai_run, 12, NULL, + ai_run, 9, NULL, + ai_run, 6, NULL, + ai_run, 12, NULL +}; +mmove_t makron_move_run = {FRAME_walk204, FRAME_walk213, makron_frames_run, NULL}; + +void makron_hit (edict_t *self) +{ + gi.sound (self, CHAN_AUTO, sound_hit, 1, ATTN_NONE,0); +} + +void makron_popup (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_popup, 1, ATTN_NONE,0); +} + +void makron_step_left (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_step_left, 1, ATTN_NORM,0); +} + +void makron_step_right (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_step_right, 1, ATTN_NORM,0); +} + +void makron_brainsplorch (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_brainsplorch, 1, ATTN_NORM,0); +} + +void makron_prerailgun (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_prerailgun, 1, ATTN_NORM,0); +} + + +mframe_t makron_frames_walk [] = +{ + ai_walk, 3, makron_step_left, + ai_walk, 12, NULL, + ai_walk, 8, NULL, + ai_walk, 8, NULL, + ai_walk, 8, makron_step_right, + ai_walk, 6, NULL, + ai_walk, 12, NULL, + ai_walk, 9, NULL, + ai_walk, 6, NULL, + ai_walk, 12, NULL +}; +mmove_t makron_move_walk = {FRAME_walk204, FRAME_walk213, makron_frames_run, NULL}; + +void makron_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &makron_move_walk; +} + +void makron_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &makron_move_stand; + else + self->monsterinfo.currentmove = &makron_move_run; +} + +mframe_t makron_frames_pain6 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 10 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, makron_popup, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 20 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, makron_taunt, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t makron_move_pain6 = {FRAME_pain601, FRAME_pain627, makron_frames_pain6, makron_run}; + +mframe_t makron_frames_pain5 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t makron_move_pain5 = {FRAME_pain501, FRAME_pain504, makron_frames_pain5, makron_run}; + +mframe_t makron_frames_pain4 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t makron_move_pain4 = {FRAME_pain401, FRAME_pain404, makron_frames_pain4, makron_run}; + +mframe_t makron_frames_death2 [] = +{ + ai_move, -15, NULL, + ai_move, 3, NULL, + ai_move, -12, NULL, + ai_move, 0, makron_step_left, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 10 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 11, NULL, + ai_move, 12, NULL, + ai_move, 11, makron_step_right, + ai_move, 0, NULL, + ai_move, 0, NULL, // 20 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 30 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 5, NULL, + ai_move, 7, NULL, + ai_move, 6, makron_step_left, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -1, NULL, + ai_move, 2, NULL, // 40 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 50 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -6, NULL, + ai_move, -4, NULL, + ai_move, -6, makron_step_right, + ai_move, -4, NULL, + ai_move, -4, makron_step_left, + ai_move, 0, NULL, + ai_move, 0, NULL, // 60 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -2, NULL, + ai_move, -5, NULL, + ai_move, -3, makron_step_right, + ai_move, -8, NULL, + ai_move, -3, makron_step_left, + ai_move, -7, NULL, + ai_move, -4, NULL, + ai_move, -4, makron_step_right, // 70 + ai_move, -6, NULL, + ai_move, -7, NULL, + ai_move, 0, makron_step_left, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 80 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -2, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL, // 90 + ai_move, 27, makron_hit, + ai_move, 26, NULL, + ai_move, 0, makron_brainsplorch, + ai_move, 0, NULL, + ai_move, 0, NULL // 95 +}; +mmove_t makron_move_death2 = {FRAME_death201, FRAME_death295, makron_frames_death2, makron_dead}; + +mframe_t makron_frames_death3 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t makron_move_death3 = {FRAME_death301, FRAME_death320, makron_frames_death3, NULL}; + +mframe_t makron_frames_sight [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t makron_move_sight= {FRAME_active01, FRAME_active13, makron_frames_sight, makron_run}; + +void makronBFG (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MAKRON_BFG], forward, right, start); + + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + gi.sound (self, CHAN_VOICE, sound_attack_bfg, 1, ATTN_NORM, 0); + monster_fire_bfg (self, start, dir, 50, 300, 100, 300, MZ2_MAKRON_BFG); +} + + +mframe_t makron_frames_attack3 []= +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, makronBFG, // FIXME: BFG Attack here + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t makron_move_attack3 = {FRAME_attak301, FRAME_attak308, makron_frames_attack3, makron_run}; + +mframe_t makron_frames_attack4[]= +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, MakronHyperblaster, // fire + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t makron_move_attack4 = {FRAME_attak401, FRAME_attak426, makron_frames_attack4, makron_run}; + +mframe_t makron_frames_attack5[]= +{ + ai_charge, 0, makron_prerailgun, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, MakronSaveloc, + ai_move, 0, MakronRailgun, // Fire railgun + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t makron_move_attack5 = {FRAME_attak501, FRAME_attak516, makron_frames_attack5, makron_run}; + +void MakronSaveloc (edict_t *self) +{ + VectorCopy (self->enemy->s.origin, self->pos1); //save for aiming the shot + self->pos1[2] += self->enemy->viewheight; +}; + +// FIXME: He's not firing from the proper Z +void MakronRailgun (edict_t *self) +{ + vec3_t start; + vec3_t dir; + vec3_t forward, right; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MAKRON_RAILGUN_1], forward, right, start); + + // calc direction to where we targted + VectorSubtract (self->pos1, start, dir); + VectorNormalize (dir); + + monster_fire_railgun (self, start, dir, 50, 100, MZ2_MAKRON_RAILGUN_1); +} + +// FIXME: This is all wrong. He's not firing at the proper angles. +void MakronHyperblaster (edict_t *self) +{ + vec3_t dir; + vec3_t vec; + vec3_t start; + vec3_t forward, right; + int flash_number; + + flash_number = MZ2_MAKRON_BLASTER_1 + (self->s.frame - FRAME_attak405); + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + if (self->enemy) + { + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, vec); + vectoangles (vec, vec); + dir[0] = vec[0]; + } + else + { + dir[0] = 0; + } + if (self->s.frame <= FRAME_attak413) + dir[1] = self->s.angles[1] - 10 * (self->s.frame - FRAME_attak413); + else + dir[1] = self->s.angles[1] + 10 * (self->s.frame - FRAME_attak421); + dir[2] = 0; + + AngleVectors (dir, forward, NULL, NULL); + + monster_fire_blaster (self, start, forward, 15, 1000, MZ2_MAKRON_BLASTER_1, EF_BLASTER); +} + + +void makron_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + // Lessen the chance of him going into his pain frames + if (damage <=25) + if (random()<0.2) + return; + + self->pain_debounce_time = level.time + 3; + if (skill->value == 3) + return; // no pain anims in nightmare + + + if (damage <= 40) + { + gi.sound (self, CHAN_VOICE, sound_pain4, 1, ATTN_NONE,0); + self->monsterinfo.currentmove = &makron_move_pain4; + } + else if (damage <= 110) + { + gi.sound (self, CHAN_VOICE, sound_pain5, 1, ATTN_NONE,0); + self->monsterinfo.currentmove = &makron_move_pain5; + } + else + { + if (damage <= 150) + if (random() <= 0.45) + { + gi.sound (self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE,0); + self->monsterinfo.currentmove = &makron_move_pain6; + } + else + if (random() <= 0.35) + { + gi.sound (self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE,0); + self->monsterinfo.currentmove = &makron_move_pain6; + } + } +}; + +void makron_sight(edict_t *self, edict_t *other) +{ + self->monsterinfo.currentmove = &makron_move_sight; +}; + +void makron_attack(edict_t *self) +{ + vec3_t vec; + float range; + float r; + + r = random(); + + VectorSubtract (self->enemy->s.origin, self->s.origin, vec); + range = VectorLength (vec); + + + if (r <= 0.3) + self->monsterinfo.currentmove = &makron_move_attack3; + else if (r <= 0.6) + self->monsterinfo.currentmove = &makron_move_attack4; + else + self->monsterinfo.currentmove = &makron_move_attack5; +} + +/* +--- +Makron Torso. This needs to be spawned in +--- +*/ + +void makron_torso_think (edict_t *self) +{ + if (++self->s.frame < 365) + self->nextthink = level.time + FRAMETIME; + else + { + self->s.frame = 346; + self->nextthink = level.time + FRAMETIME; + } +} + +void makron_torso (edict_t *ent) +{ + ent->movetype = MOVETYPE_NONE; + ent->solid = SOLID_NOT; + VectorSet (ent->mins, -8, -8, 0); + VectorSet (ent->maxs, 8, 8, 8); + ent->s.frame = 346; + ent->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2"); + ent->think = makron_torso_think; + ent->nextthink = level.time + 2 * FRAMETIME; + ent->s.sound = gi.soundindex ("makron/spine.wav"); + gi.linkentity (ent); +} + + +// +// death +// + +void makron_dead (edict_t *self) +{ + VectorSet (self->mins, -60, -60, 0); + VectorSet (self->maxs, 60, 60, 72); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + + +void makron_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + edict_t *tempent; + + int n; + + self->s.sound = 0; + // check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 1 /*4*/; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC); + ThrowHead (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + + tempent = G_Spawn(); + VectorCopy (self->s.origin, tempent->s.origin); + VectorCopy (self->s.angles, tempent->s.angles); + tempent->s.origin[1] -= 84; + makron_torso (tempent); + + self->monsterinfo.currentmove = &makron_move_death2; + +} + +qboolean Makron_CheckAttack (edict_t *self) +{ + vec3_t spot1, spot2; + vec3_t temp; + float chance; + trace_t tr; + qboolean enemy_infront; + int enemy_range; + float enemy_yaw; + + if (self->enemy->health > 0) + { + // see if any entities are in the way of the shot + VectorCopy (self->s.origin, spot1); + spot1[2] += self->viewheight; + VectorCopy (self->enemy->s.origin, spot2); + spot2[2] += self->enemy->viewheight; + + tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA); + + // do we have a clear shot? + if (tr.ent != self->enemy) + return false; + } + + enemy_infront = infront(self, self->enemy); + enemy_range = range(self, self->enemy); + VectorSubtract (self->enemy->s.origin, self->s.origin, temp); + enemy_yaw = vectoyaw(temp); + + self->ideal_yaw = enemy_yaw; + + + // melee attack + if (enemy_range == RANGE_MELEE) + { + if (self->monsterinfo.melee) + self->monsterinfo.attack_state = AS_MELEE; + else + self->monsterinfo.attack_state = AS_MISSILE; + return true; + } + +// missile attack + if (!self->monsterinfo.attack) + return false; + + if (level.time < self->monsterinfo.attack_finished) + return false; + + if (enemy_range == RANGE_FAR) + return false; + + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + { + chance = 0.4; + } + else if (enemy_range == RANGE_MELEE) + { + chance = 0.8; + } + else if (enemy_range == RANGE_NEAR) + { + chance = 0.4; + } + else if (enemy_range == RANGE_MID) + { + chance = 0.2; + } + else + { + return false; + } + + if (random () < chance) + { + self->monsterinfo.attack_state = AS_MISSILE; + self->monsterinfo.attack_finished = level.time + 2*random(); + return true; + } + + if (self->flags & FL_FLY) + { + if (random() < 0.3) + self->monsterinfo.attack_state = AS_SLIDING; + else + self->monsterinfo.attack_state = AS_STRAIGHT; + } + + return false; +} + + +// +// monster_makron +// + +void MakronPrecache (void) +{ + sound_pain4 = gi.soundindex ("makron/pain3.wav"); + sound_pain5 = gi.soundindex ("makron/pain2.wav"); + sound_pain6 = gi.soundindex ("makron/pain1.wav"); + sound_death = gi.soundindex ("makron/death.wav"); + sound_step_left = gi.soundindex ("makron/step1.wav"); + sound_step_right = gi.soundindex ("makron/step2.wav"); + sound_attack_bfg = gi.soundindex ("makron/bfg_fire.wav"); + sound_brainsplorch = gi.soundindex ("makron/brain1.wav"); + sound_prerailgun = gi.soundindex ("makron/rail_up.wav"); + sound_popup = gi.soundindex ("makron/popup.wav"); + sound_taunt1 = gi.soundindex ("makron/voice4.wav"); + sound_taunt2 = gi.soundindex ("makron/voice3.wav"); + sound_taunt3 = gi.soundindex ("makron/voice.wav"); + sound_hit = gi.soundindex ("makron/bhit.wav"); + + gi.modelindex ("models/monsters/boss3/rider/tris.md2"); +} + +/*QUAKED monster_makron (1 .5 0) (-30 -30 0) (30 30 90) Ambush Trigger_Spawn Sight +*/ +void SP_monster_makron (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + MakronPrecache (); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2"); + VectorSet (self->mins, -30, -30, 0); + VectorSet (self->maxs, 30, 30, 90); + + self->health = 3000; + self->gib_health = -2000; + self->mass = 500; + + self->pain = makron_pain; + self->die = makron_die; + self->monsterinfo.stand = makron_stand; + self->monsterinfo.walk = makron_walk; + self->monsterinfo.run = makron_run; + self->monsterinfo.dodge = NULL; + self->monsterinfo.attack = makron_attack; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = makron_sight; + self->monsterinfo.checkattack = Makron_CheckAttack; + + gi.linkentity (self); + +// self->monsterinfo.currentmove = &makron_move_stand; + self->monsterinfo.currentmove = &makron_move_sight; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start(self); +} + + +/* +================= +MakronSpawn + +================= +*/ +void MakronSpawn (edict_t *self) +{ + vec3_t vec; + edict_t *player; + + SP_monster_makron (self); + + // jump at player + player = level.sight_client; + if (!player) + return; + + VectorSubtract (player->s.origin, self->s.origin, vec); + self->s.angles[YAW] = vectoyaw(vec); + VectorNormalize (vec); + VectorMA (vec3_origin, 400, vec, self->velocity); + self->velocity[2] = 200; + self->groundentity = NULL; +} + +/* +================= +MakronToss + +Jorg is just about dead, so set up to launch Makron out +================= +*/ +void MakronToss (edict_t *self) +{ + edict_t *ent; + + ent = G_Spawn (); + ent->nextthink = level.time + 0.8; + ent->think = MakronSpawn; + ent->target = self->target; + VectorCopy (self->s.origin, ent->s.origin); +} diff --git a/game/m_boss32.h b/game/m_boss32.h new file mode 100644 index 000000000..b01861e55 --- /dev/null +++ b/game/m_boss32.h @@ -0,0 +1,516 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/boss3/rider + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_attak101 0 +#define FRAME_attak102 1 +#define FRAME_attak103 2 +#define FRAME_attak104 3 +#define FRAME_attak105 4 +#define FRAME_attak106 5 +#define FRAME_attak107 6 +#define FRAME_attak108 7 +#define FRAME_attak109 8 +#define FRAME_attak110 9 +#define FRAME_attak111 10 +#define FRAME_attak112 11 +#define FRAME_attak113 12 +#define FRAME_attak114 13 +#define FRAME_attak115 14 +#define FRAME_attak116 15 +#define FRAME_attak117 16 +#define FRAME_attak118 17 +#define FRAME_attak201 18 +#define FRAME_attak202 19 +#define FRAME_attak203 20 +#define FRAME_attak204 21 +#define FRAME_attak205 22 +#define FRAME_attak206 23 +#define FRAME_attak207 24 +#define FRAME_attak208 25 +#define FRAME_attak209 26 +#define FRAME_attak210 27 +#define FRAME_attak211 28 +#define FRAME_attak212 29 +#define FRAME_attak213 30 +#define FRAME_death01 31 +#define FRAME_death02 32 +#define FRAME_death03 33 +#define FRAME_death04 34 +#define FRAME_death05 35 +#define FRAME_death06 36 +#define FRAME_death07 37 +#define FRAME_death08 38 +#define FRAME_death09 39 +#define FRAME_death10 40 +#define FRAME_death11 41 +#define FRAME_death12 42 +#define FRAME_death13 43 +#define FRAME_death14 44 +#define FRAME_death15 45 +#define FRAME_death16 46 +#define FRAME_death17 47 +#define FRAME_death18 48 +#define FRAME_death19 49 +#define FRAME_death20 50 +#define FRAME_death21 51 +#define FRAME_death22 52 +#define FRAME_death23 53 +#define FRAME_death24 54 +#define FRAME_death25 55 +#define FRAME_death26 56 +#define FRAME_death27 57 +#define FRAME_death28 58 +#define FRAME_death29 59 +#define FRAME_death30 60 +#define FRAME_death31 61 +#define FRAME_death32 62 +#define FRAME_death33 63 +#define FRAME_death34 64 +#define FRAME_death35 65 +#define FRAME_death36 66 +#define FRAME_death37 67 +#define FRAME_death38 68 +#define FRAME_death39 69 +#define FRAME_death40 70 +#define FRAME_death41 71 +#define FRAME_death42 72 +#define FRAME_death43 73 +#define FRAME_death44 74 +#define FRAME_death45 75 +#define FRAME_death46 76 +#define FRAME_death47 77 +#define FRAME_death48 78 +#define FRAME_death49 79 +#define FRAME_death50 80 +#define FRAME_pain101 81 +#define FRAME_pain102 82 +#define FRAME_pain103 83 +#define FRAME_pain201 84 +#define FRAME_pain202 85 +#define FRAME_pain203 86 +#define FRAME_pain301 87 +#define FRAME_pain302 88 +#define FRAME_pain303 89 +#define FRAME_pain304 90 +#define FRAME_pain305 91 +#define FRAME_pain306 92 +#define FRAME_pain307 93 +#define FRAME_pain308 94 +#define FRAME_pain309 95 +#define FRAME_pain310 96 +#define FRAME_pain311 97 +#define FRAME_pain312 98 +#define FRAME_pain313 99 +#define FRAME_pain314 100 +#define FRAME_pain315 101 +#define FRAME_pain316 102 +#define FRAME_pain317 103 +#define FRAME_pain318 104 +#define FRAME_pain319 105 +#define FRAME_pain320 106 +#define FRAME_pain321 107 +#define FRAME_pain322 108 +#define FRAME_pain323 109 +#define FRAME_pain324 110 +#define FRAME_pain325 111 +#define FRAME_stand01 112 +#define FRAME_stand02 113 +#define FRAME_stand03 114 +#define FRAME_stand04 115 +#define FRAME_stand05 116 +#define FRAME_stand06 117 +#define FRAME_stand07 118 +#define FRAME_stand08 119 +#define FRAME_stand09 120 +#define FRAME_stand10 121 +#define FRAME_stand11 122 +#define FRAME_stand12 123 +#define FRAME_stand13 124 +#define FRAME_stand14 125 +#define FRAME_stand15 126 +#define FRAME_stand16 127 +#define FRAME_stand17 128 +#define FRAME_stand18 129 +#define FRAME_stand19 130 +#define FRAME_stand20 131 +#define FRAME_stand21 132 +#define FRAME_stand22 133 +#define FRAME_stand23 134 +#define FRAME_stand24 135 +#define FRAME_stand25 136 +#define FRAME_stand26 137 +#define FRAME_stand27 138 +#define FRAME_stand28 139 +#define FRAME_stand29 140 +#define FRAME_stand30 141 +#define FRAME_stand31 142 +#define FRAME_stand32 143 +#define FRAME_stand33 144 +#define FRAME_stand34 145 +#define FRAME_stand35 146 +#define FRAME_stand36 147 +#define FRAME_stand37 148 +#define FRAME_stand38 149 +#define FRAME_stand39 150 +#define FRAME_stand40 151 +#define FRAME_stand41 152 +#define FRAME_stand42 153 +#define FRAME_stand43 154 +#define FRAME_stand44 155 +#define FRAME_stand45 156 +#define FRAME_stand46 157 +#define FRAME_stand47 158 +#define FRAME_stand48 159 +#define FRAME_stand49 160 +#define FRAME_stand50 161 +#define FRAME_stand51 162 +#define FRAME_walk01 163 +#define FRAME_walk02 164 +#define FRAME_walk03 165 +#define FRAME_walk04 166 +#define FRAME_walk05 167 +#define FRAME_walk06 168 +#define FRAME_walk07 169 +#define FRAME_walk08 170 +#define FRAME_walk09 171 +#define FRAME_walk10 172 +#define FRAME_walk11 173 +#define FRAME_walk12 174 +#define FRAME_walk13 175 +#define FRAME_walk14 176 +#define FRAME_walk15 177 +#define FRAME_walk16 178 +#define FRAME_walk17 179 +#define FRAME_walk18 180 +#define FRAME_walk19 181 +#define FRAME_walk20 182 +#define FRAME_walk21 183 +#define FRAME_walk22 184 +#define FRAME_walk23 185 +#define FRAME_walk24 186 +#define FRAME_walk25 187 +#define FRAME_active01 188 +#define FRAME_active02 189 +#define FRAME_active03 190 +#define FRAME_active04 191 +#define FRAME_active05 192 +#define FRAME_active06 193 +#define FRAME_active07 194 +#define FRAME_active08 195 +#define FRAME_active09 196 +#define FRAME_active10 197 +#define FRAME_active11 198 +#define FRAME_active12 199 +#define FRAME_active13 200 +#define FRAME_attak301 201 +#define FRAME_attak302 202 +#define FRAME_attak303 203 +#define FRAME_attak304 204 +#define FRAME_attak305 205 +#define FRAME_attak306 206 +#define FRAME_attak307 207 +#define FRAME_attak308 208 +#define FRAME_attak401 209 +#define FRAME_attak402 210 +#define FRAME_attak403 211 +#define FRAME_attak404 212 +#define FRAME_attak405 213 +#define FRAME_attak406 214 +#define FRAME_attak407 215 +#define FRAME_attak408 216 +#define FRAME_attak409 217 +#define FRAME_attak410 218 +#define FRAME_attak411 219 +#define FRAME_attak412 220 +#define FRAME_attak413 221 +#define FRAME_attak414 222 +#define FRAME_attak415 223 +#define FRAME_attak416 224 +#define FRAME_attak417 225 +#define FRAME_attak418 226 +#define FRAME_attak419 227 +#define FRAME_attak420 228 +#define FRAME_attak421 229 +#define FRAME_attak422 230 +#define FRAME_attak423 231 +#define FRAME_attak424 232 +#define FRAME_attak425 233 +#define FRAME_attak426 234 +#define FRAME_attak501 235 +#define FRAME_attak502 236 +#define FRAME_attak503 237 +#define FRAME_attak504 238 +#define FRAME_attak505 239 +#define FRAME_attak506 240 +#define FRAME_attak507 241 +#define FRAME_attak508 242 +#define FRAME_attak509 243 +#define FRAME_attak510 244 +#define FRAME_attak511 245 +#define FRAME_attak512 246 +#define FRAME_attak513 247 +#define FRAME_attak514 248 +#define FRAME_attak515 249 +#define FRAME_attak516 250 +#define FRAME_death201 251 +#define FRAME_death202 252 +#define FRAME_death203 253 +#define FRAME_death204 254 +#define FRAME_death205 255 +#define FRAME_death206 256 +#define FRAME_death207 257 +#define FRAME_death208 258 +#define FRAME_death209 259 +#define FRAME_death210 260 +#define FRAME_death211 261 +#define FRAME_death212 262 +#define FRAME_death213 263 +#define FRAME_death214 264 +#define FRAME_death215 265 +#define FRAME_death216 266 +#define FRAME_death217 267 +#define FRAME_death218 268 +#define FRAME_death219 269 +#define FRAME_death220 270 +#define FRAME_death221 271 +#define FRAME_death222 272 +#define FRAME_death223 273 +#define FRAME_death224 274 +#define FRAME_death225 275 +#define FRAME_death226 276 +#define FRAME_death227 277 +#define FRAME_death228 278 +#define FRAME_death229 279 +#define FRAME_death230 280 +#define FRAME_death231 281 +#define FRAME_death232 282 +#define FRAME_death233 283 +#define FRAME_death234 284 +#define FRAME_death235 285 +#define FRAME_death236 286 +#define FRAME_death237 287 +#define FRAME_death238 288 +#define FRAME_death239 289 +#define FRAME_death240 290 +#define FRAME_death241 291 +#define FRAME_death242 292 +#define FRAME_death243 293 +#define FRAME_death244 294 +#define FRAME_death245 295 +#define FRAME_death246 296 +#define FRAME_death247 297 +#define FRAME_death248 298 +#define FRAME_death249 299 +#define FRAME_death250 300 +#define FRAME_death251 301 +#define FRAME_death252 302 +#define FRAME_death253 303 +#define FRAME_death254 304 +#define FRAME_death255 305 +#define FRAME_death256 306 +#define FRAME_death257 307 +#define FRAME_death258 308 +#define FRAME_death259 309 +#define FRAME_death260 310 +#define FRAME_death261 311 +#define FRAME_death262 312 +#define FRAME_death263 313 +#define FRAME_death264 314 +#define FRAME_death265 315 +#define FRAME_death266 316 +#define FRAME_death267 317 +#define FRAME_death268 318 +#define FRAME_death269 319 +#define FRAME_death270 320 +#define FRAME_death271 321 +#define FRAME_death272 322 +#define FRAME_death273 323 +#define FRAME_death274 324 +#define FRAME_death275 325 +#define FRAME_death276 326 +#define FRAME_death277 327 +#define FRAME_death278 328 +#define FRAME_death279 329 +#define FRAME_death280 330 +#define FRAME_death281 331 +#define FRAME_death282 332 +#define FRAME_death283 333 +#define FRAME_death284 334 +#define FRAME_death285 335 +#define FRAME_death286 336 +#define FRAME_death287 337 +#define FRAME_death288 338 +#define FRAME_death289 339 +#define FRAME_death290 340 +#define FRAME_death291 341 +#define FRAME_death292 342 +#define FRAME_death293 343 +#define FRAME_death294 344 +#define FRAME_death295 345 +#define FRAME_death301 346 +#define FRAME_death302 347 +#define FRAME_death303 348 +#define FRAME_death304 349 +#define FRAME_death305 350 +#define FRAME_death306 351 +#define FRAME_death307 352 +#define FRAME_death308 353 +#define FRAME_death309 354 +#define FRAME_death310 355 +#define FRAME_death311 356 +#define FRAME_death312 357 +#define FRAME_death313 358 +#define FRAME_death314 359 +#define FRAME_death315 360 +#define FRAME_death316 361 +#define FRAME_death317 362 +#define FRAME_death318 363 +#define FRAME_death319 364 +#define FRAME_death320 365 +#define FRAME_jump01 366 +#define FRAME_jump02 367 +#define FRAME_jump03 368 +#define FRAME_jump04 369 +#define FRAME_jump05 370 +#define FRAME_jump06 371 +#define FRAME_jump07 372 +#define FRAME_jump08 373 +#define FRAME_jump09 374 +#define FRAME_jump10 375 +#define FRAME_jump11 376 +#define FRAME_jump12 377 +#define FRAME_jump13 378 +#define FRAME_pain401 379 +#define FRAME_pain402 380 +#define FRAME_pain403 381 +#define FRAME_pain404 382 +#define FRAME_pain501 383 +#define FRAME_pain502 384 +#define FRAME_pain503 385 +#define FRAME_pain504 386 +#define FRAME_pain601 387 +#define FRAME_pain602 388 +#define FRAME_pain603 389 +#define FRAME_pain604 390 +#define FRAME_pain605 391 +#define FRAME_pain606 392 +#define FRAME_pain607 393 +#define FRAME_pain608 394 +#define FRAME_pain609 395 +#define FRAME_pain610 396 +#define FRAME_pain611 397 +#define FRAME_pain612 398 +#define FRAME_pain613 399 +#define FRAME_pain614 400 +#define FRAME_pain615 401 +#define FRAME_pain616 402 +#define FRAME_pain617 403 +#define FRAME_pain618 404 +#define FRAME_pain619 405 +#define FRAME_pain620 406 +#define FRAME_pain621 407 +#define FRAME_pain622 408 +#define FRAME_pain623 409 +#define FRAME_pain624 410 +#define FRAME_pain625 411 +#define FRAME_pain626 412 +#define FRAME_pain627 413 +#define FRAME_stand201 414 +#define FRAME_stand202 415 +#define FRAME_stand203 416 +#define FRAME_stand204 417 +#define FRAME_stand205 418 +#define FRAME_stand206 419 +#define FRAME_stand207 420 +#define FRAME_stand208 421 +#define FRAME_stand209 422 +#define FRAME_stand210 423 +#define FRAME_stand211 424 +#define FRAME_stand212 425 +#define FRAME_stand213 426 +#define FRAME_stand214 427 +#define FRAME_stand215 428 +#define FRAME_stand216 429 +#define FRAME_stand217 430 +#define FRAME_stand218 431 +#define FRAME_stand219 432 +#define FRAME_stand220 433 +#define FRAME_stand221 434 +#define FRAME_stand222 435 +#define FRAME_stand223 436 +#define FRAME_stand224 437 +#define FRAME_stand225 438 +#define FRAME_stand226 439 +#define FRAME_stand227 440 +#define FRAME_stand228 441 +#define FRAME_stand229 442 +#define FRAME_stand230 443 +#define FRAME_stand231 444 +#define FRAME_stand232 445 +#define FRAME_stand233 446 +#define FRAME_stand234 447 +#define FRAME_stand235 448 +#define FRAME_stand236 449 +#define FRAME_stand237 450 +#define FRAME_stand238 451 +#define FRAME_stand239 452 +#define FRAME_stand240 453 +#define FRAME_stand241 454 +#define FRAME_stand242 455 +#define FRAME_stand243 456 +#define FRAME_stand244 457 +#define FRAME_stand245 458 +#define FRAME_stand246 459 +#define FRAME_stand247 460 +#define FRAME_stand248 461 +#define FRAME_stand249 462 +#define FRAME_stand250 463 +#define FRAME_stand251 464 +#define FRAME_stand252 465 +#define FRAME_stand253 466 +#define FRAME_stand254 467 +#define FRAME_stand255 468 +#define FRAME_stand256 469 +#define FRAME_stand257 470 +#define FRAME_stand258 471 +#define FRAME_stand259 472 +#define FRAME_stand260 473 +#define FRAME_walk201 474 +#define FRAME_walk202 475 +#define FRAME_walk203 476 +#define FRAME_walk204 477 +#define FRAME_walk205 478 +#define FRAME_walk206 479 +#define FRAME_walk207 480 +#define FRAME_walk208 481 +#define FRAME_walk209 482 +#define FRAME_walk210 483 +#define FRAME_walk211 484 +#define FRAME_walk212 485 +#define FRAME_walk213 486 +#define FRAME_walk214 487 +#define FRAME_walk215 488 +#define FRAME_walk216 489 +#define FRAME_walk217 490 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_brain.c b/game/m_brain.c new file mode 100644 index 000000000..87c50471c --- /dev/null +++ b/game/m_brain.c @@ -0,0 +1,676 @@ +/* +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. + +*/ +/* +============================================================================== + +brain + +============================================================================== +*/ + +#include "g_local.h" +#include "m_brain.h" + + +static int sound_chest_open; +static int sound_tentacles_extend; +static int sound_tentacles_retract; +static int sound_death; +static int sound_idle1; +static int sound_idle2; +static int sound_idle3; +static int sound_pain1; +static int sound_pain2; +static int sound_sight; +static int sound_search; +static int sound_melee1; +static int sound_melee2; +static int sound_melee3; + + +void brain_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + +void brain_search (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); +} + + +void brain_run (edict_t *self); +void brain_dead (edict_t *self); + + +// +// STAND +// + +mframe_t brain_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t brain_move_stand = {FRAME_stand01, FRAME_stand30, brain_frames_stand, NULL}; + +void brain_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &brain_move_stand; +} + + +// +// IDLE +// + +mframe_t brain_frames_idle [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t brain_move_idle = {FRAME_stand31, FRAME_stand60, brain_frames_idle, brain_stand}; + +void brain_idle (edict_t *self) +{ + gi.sound (self, CHAN_AUTO, sound_idle3, 1, ATTN_IDLE, 0); + self->monsterinfo.currentmove = &brain_move_idle; +} + + +// +// WALK +// +mframe_t brain_frames_walk1 [] = +{ + ai_walk, 7, NULL, + ai_walk, 2, NULL, + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 1, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 9, NULL, + ai_walk, -4, NULL, + ai_walk, -1, NULL, + ai_walk, 2, NULL +}; +mmove_t brain_move_walk1 = {FRAME_walk101, FRAME_walk111, brain_frames_walk1, NULL}; + +// walk2 is FUBAR, do not use +#if 0 +void brain_walk2_cycle (edict_t *self) +{ + if (random() > 0.1) + self->monsterinfo.nextframe = FRAME_walk220; +} + +mframe_t brain_frames_walk2 [] = +{ + ai_walk, 3, NULL, + ai_walk, -2, NULL, + ai_walk, -4, NULL, + ai_walk, -3, NULL, + ai_walk, 0, NULL, + ai_walk, 1, NULL, + ai_walk, 12, NULL, + ai_walk, 0, NULL, + ai_walk, -3, NULL, + ai_walk, 0, NULL, + + ai_walk, -2, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 1, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 10, NULL, // Cycle Start + + ai_walk, -1, NULL, + ai_walk, 7, NULL, + ai_walk, 0, NULL, + ai_walk, 3, NULL, + ai_walk, -3, NULL, + ai_walk, 2, NULL, + ai_walk, 4, NULL, + ai_walk, -3, NULL, + ai_walk, 2, NULL, + ai_walk, 0, NULL, + + ai_walk, 4, brain_walk2_cycle, + ai_walk, -1, NULL, + ai_walk, -1, NULL, + ai_walk, -8, NULL, + ai_walk, 0, NULL, + ai_walk, 1, NULL, + ai_walk, 5, NULL, + ai_walk, 2, NULL, + ai_walk, -1, NULL, + ai_walk, -5, NULL +}; +mmove_t brain_move_walk2 = {FRAME_walk201, FRAME_walk240, brain_frames_walk2, NULL}; +#endif + +void brain_walk (edict_t *self) +{ +// if (random() <= 0.5) + self->monsterinfo.currentmove = &brain_move_walk1; +// else +// self->monsterinfo.currentmove = &brain_move_walk2; +} + + + +mframe_t brain_frames_defense [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t brain_move_defense = {FRAME_defens01, FRAME_defens08, brain_frames_defense, NULL}; + +mframe_t brain_frames_pain3 [] = +{ + ai_move, -2, NULL, + ai_move, 2, NULL, + ai_move, 1, NULL, + ai_move, 3, NULL, + ai_move, 0, NULL, + ai_move, -4, NULL +}; +mmove_t brain_move_pain3 = {FRAME_pain301, FRAME_pain306, brain_frames_pain3, brain_run}; + +mframe_t brain_frames_pain2 [] = +{ + ai_move, -2, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 3, NULL, + ai_move, 1, NULL, + ai_move, -2, NULL +}; +mmove_t brain_move_pain2 = {FRAME_pain201, FRAME_pain208, brain_frames_pain2, brain_run}; + +mframe_t brain_frames_pain1 [] = +{ + ai_move, -6, NULL, + ai_move, -2, NULL, + ai_move, -6, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 1, NULL, + ai_move, 7, NULL, + ai_move, 0, NULL, + ai_move, 3, NULL, + ai_move, -1, NULL +}; +mmove_t brain_move_pain1 = {FRAME_pain101, FRAME_pain121, brain_frames_pain1, brain_run}; + + +// +// DUCK +// + +void brain_duck_down (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_DUCKED) + return; + self->monsterinfo.aiflags |= AI_DUCKED; + self->maxs[2] -= 32; + self->takedamage = DAMAGE_YES; + gi.linkentity (self); +} + +void brain_duck_hold (edict_t *self) +{ + if (level.time >= self->monsterinfo.pausetime) + self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; + else + self->monsterinfo.aiflags |= AI_HOLD_FRAME; +} + +void brain_duck_up (edict_t *self) +{ + self->monsterinfo.aiflags &= ~AI_DUCKED; + self->maxs[2] += 32; + self->takedamage = DAMAGE_AIM; + gi.linkentity (self); +} + +mframe_t brain_frames_duck [] = +{ + ai_move, 0, NULL, + ai_move, -2, brain_duck_down, + ai_move, 17, brain_duck_hold, + ai_move, -3, NULL, + ai_move, -1, brain_duck_up, + ai_move, -5, NULL, + ai_move, -6, NULL, + ai_move, -6, NULL +}; +mmove_t brain_move_duck = {FRAME_duck01, FRAME_duck08, brain_frames_duck, brain_run}; + +void brain_dodge (edict_t *self, edict_t *attacker, float eta) +{ + if (random() > 0.25) + return; + + if (!self->enemy) + self->enemy = attacker; + + self->monsterinfo.pausetime = level.time + eta + 0.5; + self->monsterinfo.currentmove = &brain_move_duck; +} + + +mframe_t brain_frames_death2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 9, NULL, + ai_move, 0, NULL +}; +mmove_t brain_move_death2 = {FRAME_death201, FRAME_death205, brain_frames_death2, brain_dead}; + +mframe_t brain_frames_death1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -2, NULL, + ai_move, 9, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t brain_move_death1 = {FRAME_death101, FRAME_death118, brain_frames_death1, brain_dead}; + + +// +// MELEE +// + +void brain_swing_right (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_melee1, 1, ATTN_NORM, 0); +} + +void brain_hit_right (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 8); + if (fire_hit (self, aim, (15 + (rand() %5)), 40)) + gi.sound (self, CHAN_WEAPON, sound_melee3, 1, ATTN_NORM, 0); +} + +void brain_swing_left (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_melee2, 1, ATTN_NORM, 0); +} + +void brain_hit_left (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8); + if (fire_hit (self, aim, (15 + (rand() %5)), 40)) + gi.sound (self, CHAN_WEAPON, sound_melee3, 1, ATTN_NORM, 0); +} + +mframe_t brain_frames_attack1 [] = +{ + ai_charge, 8, NULL, + ai_charge, 3, NULL, + ai_charge, 5, NULL, + ai_charge, 0, NULL, + ai_charge, -3, brain_swing_right, + ai_charge, 0, NULL, + ai_charge, -5, NULL, + ai_charge, -7, brain_hit_right, + ai_charge, 0, NULL, + ai_charge, 6, brain_swing_left, + ai_charge, 1, NULL, + ai_charge, 2, brain_hit_left, + ai_charge, -3, NULL, + ai_charge, 6, NULL, + ai_charge, -1, NULL, + ai_charge, -3, NULL, + ai_charge, 2, NULL, + ai_charge, -11,NULL +}; +mmove_t brain_move_attack1 = {FRAME_attak101, FRAME_attak118, brain_frames_attack1, brain_run}; + +void brain_chest_open (edict_t *self) +{ + self->spawnflags &= ~65536; + self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; + gi.sound (self, CHAN_BODY, sound_chest_open, 1, ATTN_NORM, 0); +} + +void brain_tentacle_attack (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, 0, 8); + if (fire_hit (self, aim, (10 + (rand() %5)), -600) && skill->value > 0) + self->spawnflags |= 65536; + gi.sound (self, CHAN_WEAPON, sound_tentacles_retract, 1, ATTN_NORM, 0); +} + +void brain_chest_closed (edict_t *self) +{ + self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; + if (self->spawnflags & 65536) + { + self->spawnflags &= ~65536; + self->monsterinfo.currentmove = &brain_move_attack1; + } +} + +mframe_t brain_frames_attack2 [] = +{ + ai_charge, 5, NULL, + ai_charge, -4, NULL, + ai_charge, -4, NULL, + ai_charge, -3, NULL, + ai_charge, 0, brain_chest_open, + ai_charge, 0, NULL, + ai_charge, 13, brain_tentacle_attack, + ai_charge, 0, NULL, + ai_charge, 2, NULL, + ai_charge, 0, NULL, + ai_charge, -9, brain_chest_closed, + ai_charge, 0, NULL, + ai_charge, 4, NULL, + ai_charge, 3, NULL, + ai_charge, 2, NULL, + ai_charge, -3, NULL, + ai_charge, -6, NULL +}; +mmove_t brain_move_attack2 = {FRAME_attak201, FRAME_attak217, brain_frames_attack2, brain_run}; + +void brain_melee(edict_t *self) +{ + if (random() <= 0.5) + self->monsterinfo.currentmove = &brain_move_attack1; + else + self->monsterinfo.currentmove = &brain_move_attack2; +} + + +// +// RUN +// + +mframe_t brain_frames_run [] = +{ + ai_run, 9, NULL, + ai_run, 2, NULL, + ai_run, 3, NULL, + ai_run, 3, NULL, + ai_run, 1, NULL, + ai_run, 0, NULL, + ai_run, 0, NULL, + ai_run, 10, NULL, + ai_run, -4, NULL, + ai_run, -1, NULL, + ai_run, 2, NULL +}; +mmove_t brain_move_run = {FRAME_walk101, FRAME_walk111, brain_frames_run, NULL}; + +void brain_run (edict_t *self) +{ + self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &brain_move_stand; + else + self->monsterinfo.currentmove = &brain_move_run; +} + + +void brain_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + float r; + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + if (skill->value == 3) + return; // no pain anims in nightmare + + r = random(); + if (r < 0.33) + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &brain_move_pain1; + } + else if (r < 0.66) + { + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &brain_move_pain2; + } + else + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &brain_move_pain3; + } +} + +void brain_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + + + +void brain_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + + self->s.effects = 0; + self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + if (random() <= 0.5) + self->monsterinfo.currentmove = &brain_move_death1; + else + self->monsterinfo.currentmove = &brain_move_death2; +} + +/*QUAKED monster_brain (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_brain (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_chest_open = gi.soundindex ("brain/brnatck1.wav"); + sound_tentacles_extend = gi.soundindex ("brain/brnatck2.wav"); + sound_tentacles_retract = gi.soundindex ("brain/brnatck3.wav"); + sound_death = gi.soundindex ("brain/brndeth1.wav"); + sound_idle1 = gi.soundindex ("brain/brnidle1.wav"); + sound_idle2 = gi.soundindex ("brain/brnidle2.wav"); + sound_idle3 = gi.soundindex ("brain/brnlens1.wav"); + sound_pain1 = gi.soundindex ("brain/brnpain1.wav"); + sound_pain2 = gi.soundindex ("brain/brnpain2.wav"); + sound_sight = gi.soundindex ("brain/brnsght1.wav"); + sound_search = gi.soundindex ("brain/brnsrch1.wav"); + sound_melee1 = gi.soundindex ("brain/melee1.wav"); + sound_melee2 = gi.soundindex ("brain/melee2.wav"); + sound_melee3 = gi.soundindex ("brain/melee3.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/brain/tris.md2"); + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 32); + + self->health = 300; + self->gib_health = -150; + self->mass = 400; + + self->pain = brain_pain; + self->die = brain_die; + + self->monsterinfo.stand = brain_stand; + self->monsterinfo.walk = brain_walk; + self->monsterinfo.run = brain_run; + self->monsterinfo.dodge = brain_dodge; +// self->monsterinfo.attack = brain_attack; + self->monsterinfo.melee = brain_melee; + self->monsterinfo.sight = brain_sight; + self->monsterinfo.search = brain_search; + self->monsterinfo.idle = brain_idle; + + self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; + self->monsterinfo.power_armor_power = 100; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &brain_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start (self); +} diff --git a/game/m_brain.h b/game/m_brain.h new file mode 100644 index 000000000..99a9ad304 --- /dev/null +++ b/game/m_brain.h @@ -0,0 +1,247 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/brain + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_walk101 0 +#define FRAME_walk102 1 +#define FRAME_walk103 2 +#define FRAME_walk104 3 +#define FRAME_walk105 4 +#define FRAME_walk106 5 +#define FRAME_walk107 6 +#define FRAME_walk108 7 +#define FRAME_walk109 8 +#define FRAME_walk110 9 +#define FRAME_walk111 10 +#define FRAME_walk112 11 +#define FRAME_walk113 12 +#define FRAME_walk201 13 +#define FRAME_walk202 14 +#define FRAME_walk203 15 +#define FRAME_walk204 16 +#define FRAME_walk205 17 +#define FRAME_walk206 18 +#define FRAME_walk207 19 +#define FRAME_walk208 20 +#define FRAME_walk209 21 +#define FRAME_walk210 22 +#define FRAME_walk211 23 +#define FRAME_walk212 24 +#define FRAME_walk213 25 +#define FRAME_walk214 26 +#define FRAME_walk215 27 +#define FRAME_walk216 28 +#define FRAME_walk217 29 +#define FRAME_walk218 30 +#define FRAME_walk219 31 +#define FRAME_walk220 32 +#define FRAME_walk221 33 +#define FRAME_walk222 34 +#define FRAME_walk223 35 +#define FRAME_walk224 36 +#define FRAME_walk225 37 +#define FRAME_walk226 38 +#define FRAME_walk227 39 +#define FRAME_walk228 40 +#define FRAME_walk229 41 +#define FRAME_walk230 42 +#define FRAME_walk231 43 +#define FRAME_walk232 44 +#define FRAME_walk233 45 +#define FRAME_walk234 46 +#define FRAME_walk235 47 +#define FRAME_walk236 48 +#define FRAME_walk237 49 +#define FRAME_walk238 50 +#define FRAME_walk239 51 +#define FRAME_walk240 52 +#define FRAME_attak101 53 +#define FRAME_attak102 54 +#define FRAME_attak103 55 +#define FRAME_attak104 56 +#define FRAME_attak105 57 +#define FRAME_attak106 58 +#define FRAME_attak107 59 +#define FRAME_attak108 60 +#define FRAME_attak109 61 +#define FRAME_attak110 62 +#define FRAME_attak111 63 +#define FRAME_attak112 64 +#define FRAME_attak113 65 +#define FRAME_attak114 66 +#define FRAME_attak115 67 +#define FRAME_attak116 68 +#define FRAME_attak117 69 +#define FRAME_attak118 70 +#define FRAME_attak201 71 +#define FRAME_attak202 72 +#define FRAME_attak203 73 +#define FRAME_attak204 74 +#define FRAME_attak205 75 +#define FRAME_attak206 76 +#define FRAME_attak207 77 +#define FRAME_attak208 78 +#define FRAME_attak209 79 +#define FRAME_attak210 80 +#define FRAME_attak211 81 +#define FRAME_attak212 82 +#define FRAME_attak213 83 +#define FRAME_attak214 84 +#define FRAME_attak215 85 +#define FRAME_attak216 86 +#define FRAME_attak217 87 +#define FRAME_pain101 88 +#define FRAME_pain102 89 +#define FRAME_pain103 90 +#define FRAME_pain104 91 +#define FRAME_pain105 92 +#define FRAME_pain106 93 +#define FRAME_pain107 94 +#define FRAME_pain108 95 +#define FRAME_pain109 96 +#define FRAME_pain110 97 +#define FRAME_pain111 98 +#define FRAME_pain112 99 +#define FRAME_pain113 100 +#define FRAME_pain114 101 +#define FRAME_pain115 102 +#define FRAME_pain116 103 +#define FRAME_pain117 104 +#define FRAME_pain118 105 +#define FRAME_pain119 106 +#define FRAME_pain120 107 +#define FRAME_pain121 108 +#define FRAME_pain201 109 +#define FRAME_pain202 110 +#define FRAME_pain203 111 +#define FRAME_pain204 112 +#define FRAME_pain205 113 +#define FRAME_pain206 114 +#define FRAME_pain207 115 +#define FRAME_pain208 116 +#define FRAME_pain301 117 +#define FRAME_pain302 118 +#define FRAME_pain303 119 +#define FRAME_pain304 120 +#define FRAME_pain305 121 +#define FRAME_pain306 122 +#define FRAME_death101 123 +#define FRAME_death102 124 +#define FRAME_death103 125 +#define FRAME_death104 126 +#define FRAME_death105 127 +#define FRAME_death106 128 +#define FRAME_death107 129 +#define FRAME_death108 130 +#define FRAME_death109 131 +#define FRAME_death110 132 +#define FRAME_death111 133 +#define FRAME_death112 134 +#define FRAME_death113 135 +#define FRAME_death114 136 +#define FRAME_death115 137 +#define FRAME_death116 138 +#define FRAME_death117 139 +#define FRAME_death118 140 +#define FRAME_death201 141 +#define FRAME_death202 142 +#define FRAME_death203 143 +#define FRAME_death204 144 +#define FRAME_death205 145 +#define FRAME_duck01 146 +#define FRAME_duck02 147 +#define FRAME_duck03 148 +#define FRAME_duck04 149 +#define FRAME_duck05 150 +#define FRAME_duck06 151 +#define FRAME_duck07 152 +#define FRAME_duck08 153 +#define FRAME_defens01 154 +#define FRAME_defens02 155 +#define FRAME_defens03 156 +#define FRAME_defens04 157 +#define FRAME_defens05 158 +#define FRAME_defens06 159 +#define FRAME_defens07 160 +#define FRAME_defens08 161 +#define FRAME_stand01 162 +#define FRAME_stand02 163 +#define FRAME_stand03 164 +#define FRAME_stand04 165 +#define FRAME_stand05 166 +#define FRAME_stand06 167 +#define FRAME_stand07 168 +#define FRAME_stand08 169 +#define FRAME_stand09 170 +#define FRAME_stand10 171 +#define FRAME_stand11 172 +#define FRAME_stand12 173 +#define FRAME_stand13 174 +#define FRAME_stand14 175 +#define FRAME_stand15 176 +#define FRAME_stand16 177 +#define FRAME_stand17 178 +#define FRAME_stand18 179 +#define FRAME_stand19 180 +#define FRAME_stand20 181 +#define FRAME_stand21 182 +#define FRAME_stand22 183 +#define FRAME_stand23 184 +#define FRAME_stand24 185 +#define FRAME_stand25 186 +#define FRAME_stand26 187 +#define FRAME_stand27 188 +#define FRAME_stand28 189 +#define FRAME_stand29 190 +#define FRAME_stand30 191 +#define FRAME_stand31 192 +#define FRAME_stand32 193 +#define FRAME_stand33 194 +#define FRAME_stand34 195 +#define FRAME_stand35 196 +#define FRAME_stand36 197 +#define FRAME_stand37 198 +#define FRAME_stand38 199 +#define FRAME_stand39 200 +#define FRAME_stand40 201 +#define FRAME_stand41 202 +#define FRAME_stand42 203 +#define FRAME_stand43 204 +#define FRAME_stand44 205 +#define FRAME_stand45 206 +#define FRAME_stand46 207 +#define FRAME_stand47 208 +#define FRAME_stand48 209 +#define FRAME_stand49 210 +#define FRAME_stand50 211 +#define FRAME_stand51 212 +#define FRAME_stand52 213 +#define FRAME_stand53 214 +#define FRAME_stand54 215 +#define FRAME_stand55 216 +#define FRAME_stand56 217 +#define FRAME_stand57 218 +#define FRAME_stand58 219 +#define FRAME_stand59 220 +#define FRAME_stand60 221 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_chick.c b/game/m_chick.c new file mode 100644 index 000000000..cde143119 --- /dev/null +++ b/game/m_chick.c @@ -0,0 +1,677 @@ +/* +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. + +*/ +/* +============================================================================== + +chick + +============================================================================== +*/ + +#include "g_local.h" +#include "m_chick.h" + +qboolean visible (edict_t *self, edict_t *other); + +void chick_stand (edict_t *self); +void chick_run (edict_t *self); +void chick_reslash(edict_t *self); +void chick_rerocket(edict_t *self); +void chick_attack1(edict_t *self); + +static int sound_missile_prelaunch; +static int sound_missile_launch; +static int sound_melee_swing; +static int sound_melee_hit; +static int sound_missile_reload; +static int sound_death1; +static int sound_death2; +static int sound_fall_down; +static int sound_idle1; +static int sound_idle2; +static int sound_pain1; +static int sound_pain2; +static int sound_pain3; +static int sound_sight; +static int sound_search; + + +void ChickMoan (edict_t *self) +{ + if (random() < 0.5) + gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0); + else + gi.sound (self, CHAN_VOICE, sound_idle2, 1, ATTN_IDLE, 0); +} + +mframe_t chick_frames_fidget [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, ChickMoan, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t chick_move_fidget = {FRAME_stand201, FRAME_stand230, chick_frames_fidget, chick_stand}; + +void chick_fidget (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + return; + if (random() <= 0.3) + self->monsterinfo.currentmove = &chick_move_fidget; +} + +mframe_t chick_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, chick_fidget, + +}; +mmove_t chick_move_stand = {FRAME_stand101, FRAME_stand130, chick_frames_stand, NULL}; + +void chick_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &chick_move_stand; +} + +mframe_t chick_frames_start_run [] = +{ + ai_run, 1, NULL, + ai_run, 0, NULL, + ai_run, 0, NULL, + ai_run, -1, NULL, + ai_run, -1, NULL, + ai_run, 0, NULL, + ai_run, 1, NULL, + ai_run, 3, NULL, + ai_run, 6, NULL, + ai_run, 3, NULL +}; +mmove_t chick_move_start_run = {FRAME_walk01, FRAME_walk10, chick_frames_start_run, chick_run}; + +mframe_t chick_frames_run [] = +{ + ai_run, 6, NULL, + ai_run, 8, NULL, + ai_run, 13, NULL, + ai_run, 5, NULL, + ai_run, 7, NULL, + ai_run, 4, NULL, + ai_run, 11, NULL, + ai_run, 5, NULL, + ai_run, 9, NULL, + ai_run, 7, NULL + +}; + +mmove_t chick_move_run = {FRAME_walk11, FRAME_walk20, chick_frames_run, NULL}; + +mframe_t chick_frames_walk [] = +{ + ai_walk, 6, NULL, + ai_walk, 8, NULL, + ai_walk, 13, NULL, + ai_walk, 5, NULL, + ai_walk, 7, NULL, + ai_walk, 4, NULL, + ai_walk, 11, NULL, + ai_walk, 5, NULL, + ai_walk, 9, NULL, + ai_walk, 7, NULL +}; + +mmove_t chick_move_walk = {FRAME_walk11, FRAME_walk20, chick_frames_walk, NULL}; + +void chick_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &chick_move_walk; +} + +void chick_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + { + self->monsterinfo.currentmove = &chick_move_stand; + return; + } + + if (self->monsterinfo.currentmove == &chick_move_walk || + self->monsterinfo.currentmove == &chick_move_start_run) + { + self->monsterinfo.currentmove = &chick_move_run; + } + else + { + self->monsterinfo.currentmove = &chick_move_start_run; + } +} + +mframe_t chick_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t chick_move_pain1 = {FRAME_pain101, FRAME_pain105, chick_frames_pain1, chick_run}; + +mframe_t chick_frames_pain2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t chick_move_pain2 = {FRAME_pain201, FRAME_pain205, chick_frames_pain2, chick_run}; + +mframe_t chick_frames_pain3 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -6, NULL, + ai_move, 3, NULL, + ai_move, 11, NULL, + ai_move, 3, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 4, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, -3, NULL, + ai_move, -4, NULL, + ai_move, 5, NULL, + ai_move, 7, NULL, + ai_move, -2, NULL, + ai_move, 3, NULL, + ai_move, -5, NULL, + ai_move, -2, NULL, + ai_move, -8, NULL, + ai_move, 2, NULL +}; +mmove_t chick_move_pain3 = {FRAME_pain301, FRAME_pain321, chick_frames_pain3, chick_run}; + +void chick_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + float r; + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + + r = random(); + if (r < 0.33) + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + else if (r < 0.66) + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM, 0); + + if (skill->value == 3) + return; // no pain anims in nightmare + + if (damage <= 10) + self->monsterinfo.currentmove = &chick_move_pain1; + else if (damage <= 25) + self->monsterinfo.currentmove = &chick_move_pain2; + else + self->monsterinfo.currentmove = &chick_move_pain3; +} + +void chick_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, 0); + VectorSet (self->maxs, 16, 16, 16); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +mframe_t chick_frames_death2 [] = +{ + ai_move, -6, NULL, + ai_move, 0, NULL, + ai_move, -1, NULL, + ai_move, -5, NULL, + ai_move, 0, NULL, + ai_move, -1, NULL, + ai_move, -2, NULL, + ai_move, 1, NULL, + ai_move, 10, NULL, + ai_move, 2, NULL, + ai_move, 3, NULL, + ai_move, 1, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL, + ai_move, 3, NULL, + ai_move, 3, NULL, + ai_move, 1, NULL, + ai_move, -3, NULL, + ai_move, -5, NULL, + ai_move, 4, NULL, + ai_move, 15, NULL, + ai_move, 14, NULL, + ai_move, 1, NULL +}; +mmove_t chick_move_death2 = {FRAME_death201, FRAME_death223, chick_frames_death2, chick_dead}; + +mframe_t chick_frames_death1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -7, NULL, + ai_move, 4, NULL, + ai_move, 11, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL + +}; +mmove_t chick_move_death1 = {FRAME_death101, FRAME_death112, chick_frames_death1, chick_dead}; + +void chick_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + + n = rand() % 2; + if (n == 0) + { + self->monsterinfo.currentmove = &chick_move_death1; + gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); + } + else + { + self->monsterinfo.currentmove = &chick_move_death2; + gi.sound (self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0); + } +} + + +void chick_duck_down (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_DUCKED) + return; + self->monsterinfo.aiflags |= AI_DUCKED; + self->maxs[2] -= 32; + self->takedamage = DAMAGE_YES; + self->monsterinfo.pausetime = level.time + 1; + gi.linkentity (self); +} + +void chick_duck_hold (edict_t *self) +{ + if (level.time >= self->monsterinfo.pausetime) + self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; + else + self->monsterinfo.aiflags |= AI_HOLD_FRAME; +} + +void chick_duck_up (edict_t *self) +{ + self->monsterinfo.aiflags &= ~AI_DUCKED; + self->maxs[2] += 32; + self->takedamage = DAMAGE_AIM; + gi.linkentity (self); +} + +mframe_t chick_frames_duck [] = +{ + ai_move, 0, chick_duck_down, + ai_move, 1, NULL, + ai_move, 4, chick_duck_hold, + ai_move, -4, NULL, + ai_move, -5, chick_duck_up, + ai_move, 3, NULL, + ai_move, 1, NULL +}; +mmove_t chick_move_duck = {FRAME_duck01, FRAME_duck07, chick_frames_duck, chick_run}; + +void chick_dodge (edict_t *self, edict_t *attacker, float eta) +{ + if (random() > 0.25) + return; + + if (!self->enemy) + self->enemy = attacker; + + self->monsterinfo.currentmove = &chick_move_duck; +} + +void ChickSlash (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, self->mins[0], 10); + gi.sound (self, CHAN_WEAPON, sound_melee_swing, 1, ATTN_NORM, 0); + fire_hit (self, aim, (10 + (rand() %6)), 100); +} + + +void ChickRocket (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_CHICK_ROCKET_1], forward, right, start); + + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + + monster_fire_rocket (self, start, dir, 50, 500, MZ2_CHICK_ROCKET_1); +} + +void Chick_PreAttack1 (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_missile_prelaunch, 1, ATTN_NORM, 0); +} + +void ChickReload (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_missile_reload, 1, ATTN_NORM, 0); +} + + +mframe_t chick_frames_start_attack1 [] = +{ + ai_charge, 0, Chick_PreAttack1, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 4, NULL, + ai_charge, 0, NULL, + ai_charge, -3, NULL, + ai_charge, 3, NULL, + ai_charge, 5, NULL, + ai_charge, 7, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, chick_attack1 +}; +mmove_t chick_move_start_attack1 = {FRAME_attak101, FRAME_attak113, chick_frames_start_attack1, NULL}; + + +mframe_t chick_frames_attack1 [] = +{ + ai_charge, 19, ChickRocket, + ai_charge, -6, NULL, + ai_charge, -5, NULL, + ai_charge, -2, NULL, + ai_charge, -7, NULL, + ai_charge, 0, NULL, + ai_charge, 1, NULL, + ai_charge, 10, ChickReload, + ai_charge, 4, NULL, + ai_charge, 5, NULL, + ai_charge, 6, NULL, + ai_charge, 6, NULL, + ai_charge, 4, NULL, + ai_charge, 3, chick_rerocket + +}; +mmove_t chick_move_attack1 = {FRAME_attak114, FRAME_attak127, chick_frames_attack1, NULL}; + +mframe_t chick_frames_end_attack1 [] = +{ + ai_charge, -3, NULL, + ai_charge, 0, NULL, + ai_charge, -6, NULL, + ai_charge, -4, NULL, + ai_charge, -2, NULL +}; +mmove_t chick_move_end_attack1 = {FRAME_attak128, FRAME_attak132, chick_frames_end_attack1, chick_run}; + +void chick_rerocket(edict_t *self) +{ + if (self->enemy->health > 0) + { + if (range (self, self->enemy) > RANGE_MELEE) + if ( visible (self, self->enemy) ) + if (random() <= 0.6) + { + self->monsterinfo.currentmove = &chick_move_attack1; + return; + } + } + self->monsterinfo.currentmove = &chick_move_end_attack1; +} + +void chick_attack1(edict_t *self) +{ + self->monsterinfo.currentmove = &chick_move_attack1; +} + +mframe_t chick_frames_slash [] = +{ + ai_charge, 1, NULL, + ai_charge, 7, ChickSlash, + ai_charge, -7, NULL, + ai_charge, 1, NULL, + ai_charge, -1, NULL, + ai_charge, 1, NULL, + ai_charge, 0, NULL, + ai_charge, 1, NULL, + ai_charge, -2, chick_reslash +}; +mmove_t chick_move_slash = {FRAME_attak204, FRAME_attak212, chick_frames_slash, NULL}; + +mframe_t chick_frames_end_slash [] = +{ + ai_charge, -6, NULL, + ai_charge, -1, NULL, + ai_charge, -6, NULL, + ai_charge, 0, NULL +}; +mmove_t chick_move_end_slash = {FRAME_attak213, FRAME_attak216, chick_frames_end_slash, chick_run}; + + +void chick_reslash(edict_t *self) +{ + if (self->enemy->health > 0) + { + if (range (self, self->enemy) == RANGE_MELEE) + if (random() <= 0.9) + { + self->monsterinfo.currentmove = &chick_move_slash; + return; + } + else + { + self->monsterinfo.currentmove = &chick_move_end_slash; + return; + } + } + self->monsterinfo.currentmove = &chick_move_end_slash; +} + +void chick_slash(edict_t *self) +{ + self->monsterinfo.currentmove = &chick_move_slash; +} + + +mframe_t chick_frames_start_slash [] = +{ + ai_charge, 1, NULL, + ai_charge, 8, NULL, + ai_charge, 3, NULL +}; +mmove_t chick_move_start_slash = {FRAME_attak201, FRAME_attak203, chick_frames_start_slash, chick_slash}; + + + +void chick_melee(edict_t *self) +{ + self->monsterinfo.currentmove = &chick_move_start_slash; +} + + +void chick_attack(edict_t *self) +{ + self->monsterinfo.currentmove = &chick_move_start_attack1; +} + +void chick_sight(edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + +/*QUAKED monster_chick (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_chick (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_missile_prelaunch = gi.soundindex ("chick/chkatck1.wav"); + sound_missile_launch = gi.soundindex ("chick/chkatck2.wav"); + sound_melee_swing = gi.soundindex ("chick/chkatck3.wav"); + sound_melee_hit = gi.soundindex ("chick/chkatck4.wav"); + sound_missile_reload = gi.soundindex ("chick/chkatck5.wav"); + sound_death1 = gi.soundindex ("chick/chkdeth1.wav"); + sound_death2 = gi.soundindex ("chick/chkdeth2.wav"); + sound_fall_down = gi.soundindex ("chick/chkfall1.wav"); + sound_idle1 = gi.soundindex ("chick/chkidle1.wav"); + sound_idle2 = gi.soundindex ("chick/chkidle2.wav"); + sound_pain1 = gi.soundindex ("chick/chkpain1.wav"); + sound_pain2 = gi.soundindex ("chick/chkpain2.wav"); + sound_pain3 = gi.soundindex ("chick/chkpain3.wav"); + sound_sight = gi.soundindex ("chick/chksght1.wav"); + sound_search = gi.soundindex ("chick/chksrch1.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/bitch/tris.md2"); + VectorSet (self->mins, -16, -16, 0); + VectorSet (self->maxs, 16, 16, 56); + + self->health = 175; + self->gib_health = -70; + self->mass = 200; + + self->pain = chick_pain; + self->die = chick_die; + + self->monsterinfo.stand = chick_stand; + self->monsterinfo.walk = chick_walk; + self->monsterinfo.run = chick_run; + self->monsterinfo.dodge = chick_dodge; + self->monsterinfo.attack = chick_attack; + self->monsterinfo.melee = chick_melee; + self->monsterinfo.sight = chick_sight; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &chick_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start (self); +} diff --git a/game/m_chick.h b/game/m_chick.h new file mode 100644 index 000000000..a7b5c9fc4 --- /dev/null +++ b/game/m_chick.h @@ -0,0 +1,313 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/bitch + +// This file generated by qdata - Do NOT Modify + +#define FRAME_attak101 0 +#define FRAME_attak102 1 +#define FRAME_attak103 2 +#define FRAME_attak104 3 +#define FRAME_attak105 4 +#define FRAME_attak106 5 +#define FRAME_attak107 6 +#define FRAME_attak108 7 +#define FRAME_attak109 8 +#define FRAME_attak110 9 +#define FRAME_attak111 10 +#define FRAME_attak112 11 +#define FRAME_attak113 12 +#define FRAME_attak114 13 +#define FRAME_attak115 14 +#define FRAME_attak116 15 +#define FRAME_attak117 16 +#define FRAME_attak118 17 +#define FRAME_attak119 18 +#define FRAME_attak120 19 +#define FRAME_attak121 20 +#define FRAME_attak122 21 +#define FRAME_attak123 22 +#define FRAME_attak124 23 +#define FRAME_attak125 24 +#define FRAME_attak126 25 +#define FRAME_attak127 26 +#define FRAME_attak128 27 +#define FRAME_attak129 28 +#define FRAME_attak130 29 +#define FRAME_attak131 30 +#define FRAME_attak132 31 +#define FRAME_attak201 32 +#define FRAME_attak202 33 +#define FRAME_attak203 34 +#define FRAME_attak204 35 +#define FRAME_attak205 36 +#define FRAME_attak206 37 +#define FRAME_attak207 38 +#define FRAME_attak208 39 +#define FRAME_attak209 40 +#define FRAME_attak210 41 +#define FRAME_attak211 42 +#define FRAME_attak212 43 +#define FRAME_attak213 44 +#define FRAME_attak214 45 +#define FRAME_attak215 46 +#define FRAME_attak216 47 +#define FRAME_death101 48 +#define FRAME_death102 49 +#define FRAME_death103 50 +#define FRAME_death104 51 +#define FRAME_death105 52 +#define FRAME_death106 53 +#define FRAME_death107 54 +#define FRAME_death108 55 +#define FRAME_death109 56 +#define FRAME_death110 57 +#define FRAME_death111 58 +#define FRAME_death112 59 +#define FRAME_death201 60 +#define FRAME_death202 61 +#define FRAME_death203 62 +#define FRAME_death204 63 +#define FRAME_death205 64 +#define FRAME_death206 65 +#define FRAME_death207 66 +#define FRAME_death208 67 +#define FRAME_death209 68 +#define FRAME_death210 69 +#define FRAME_death211 70 +#define FRAME_death212 71 +#define FRAME_death213 72 +#define FRAME_death214 73 +#define FRAME_death215 74 +#define FRAME_death216 75 +#define FRAME_death217 76 +#define FRAME_death218 77 +#define FRAME_death219 78 +#define FRAME_death220 79 +#define FRAME_death221 80 +#define FRAME_death222 81 +#define FRAME_death223 82 +#define FRAME_duck01 83 +#define FRAME_duck02 84 +#define FRAME_duck03 85 +#define FRAME_duck04 86 +#define FRAME_duck05 87 +#define FRAME_duck06 88 +#define FRAME_duck07 89 +#define FRAME_pain101 90 +#define FRAME_pain102 91 +#define FRAME_pain103 92 +#define FRAME_pain104 93 +#define FRAME_pain105 94 +#define FRAME_pain201 95 +#define FRAME_pain202 96 +#define FRAME_pain203 97 +#define FRAME_pain204 98 +#define FRAME_pain205 99 +#define FRAME_pain301 100 +#define FRAME_pain302 101 +#define FRAME_pain303 102 +#define FRAME_pain304 103 +#define FRAME_pain305 104 +#define FRAME_pain306 105 +#define FRAME_pain307 106 +#define FRAME_pain308 107 +#define FRAME_pain309 108 +#define FRAME_pain310 109 +#define FRAME_pain311 110 +#define FRAME_pain312 111 +#define FRAME_pain313 112 +#define FRAME_pain314 113 +#define FRAME_pain315 114 +#define FRAME_pain316 115 +#define FRAME_pain317 116 +#define FRAME_pain318 117 +#define FRAME_pain319 118 +#define FRAME_pain320 119 +#define FRAME_pain321 120 +#define FRAME_stand101 121 +#define FRAME_stand102 122 +#define FRAME_stand103 123 +#define FRAME_stand104 124 +#define FRAME_stand105 125 +#define FRAME_stand106 126 +#define FRAME_stand107 127 +#define FRAME_stand108 128 +#define FRAME_stand109 129 +#define FRAME_stand110 130 +#define FRAME_stand111 131 +#define FRAME_stand112 132 +#define FRAME_stand113 133 +#define FRAME_stand114 134 +#define FRAME_stand115 135 +#define FRAME_stand116 136 +#define FRAME_stand117 137 +#define FRAME_stand118 138 +#define FRAME_stand119 139 +#define FRAME_stand120 140 +#define FRAME_stand121 141 +#define FRAME_stand122 142 +#define FRAME_stand123 143 +#define FRAME_stand124 144 +#define FRAME_stand125 145 +#define FRAME_stand126 146 +#define FRAME_stand127 147 +#define FRAME_stand128 148 +#define FRAME_stand129 149 +#define FRAME_stand130 150 +#define FRAME_stand201 151 +#define FRAME_stand202 152 +#define FRAME_stand203 153 +#define FRAME_stand204 154 +#define FRAME_stand205 155 +#define FRAME_stand206 156 +#define FRAME_stand207 157 +#define FRAME_stand208 158 +#define FRAME_stand209 159 +#define FRAME_stand210 160 +#define FRAME_stand211 161 +#define FRAME_stand212 162 +#define FRAME_stand213 163 +#define FRAME_stand214 164 +#define FRAME_stand215 165 +#define FRAME_stand216 166 +#define FRAME_stand217 167 +#define FRAME_stand218 168 +#define FRAME_stand219 169 +#define FRAME_stand220 170 +#define FRAME_stand221 171 +#define FRAME_stand222 172 +#define FRAME_stand223 173 +#define FRAME_stand224 174 +#define FRAME_stand225 175 +#define FRAME_stand226 176 +#define FRAME_stand227 177 +#define FRAME_stand228 178 +#define FRAME_stand229 179 +#define FRAME_stand230 180 +#define FRAME_walk01 181 +#define FRAME_walk02 182 +#define FRAME_walk03 183 +#define FRAME_walk04 184 +#define FRAME_walk05 185 +#define FRAME_walk06 186 +#define FRAME_walk07 187 +#define FRAME_walk08 188 +#define FRAME_walk09 189 +#define FRAME_walk10 190 +#define FRAME_walk11 191 +#define FRAME_walk12 192 +#define FRAME_walk13 193 +#define FRAME_walk14 194 +#define FRAME_walk15 195 +#define FRAME_walk16 196 +#define FRAME_walk17 197 +#define FRAME_walk18 198 +#define FRAME_walk19 199 +#define FRAME_walk20 200 +#define FRAME_walk21 201 +#define FRAME_walk22 202 +#define FRAME_walk23 203 +#define FRAME_walk24 204 +#define FRAME_walk25 205 +#define FRAME_walk26 206 +#define FRAME_walk27 207 +#define FRAME_recln201 208 +#define FRAME_recln202 209 +#define FRAME_recln203 210 +#define FRAME_recln204 211 +#define FRAME_recln205 212 +#define FRAME_recln206 213 +#define FRAME_recln207 214 +#define FRAME_recln208 215 +#define FRAME_recln209 216 +#define FRAME_recln210 217 +#define FRAME_recln211 218 +#define FRAME_recln212 219 +#define FRAME_recln213 220 +#define FRAME_recln214 221 +#define FRAME_recln215 222 +#define FRAME_recln216 223 +#define FRAME_recln217 224 +#define FRAME_recln218 225 +#define FRAME_recln219 226 +#define FRAME_recln220 227 +#define FRAME_recln221 228 +#define FRAME_recln222 229 +#define FRAME_recln223 230 +#define FRAME_recln224 231 +#define FRAME_recln225 232 +#define FRAME_recln226 233 +#define FRAME_recln227 234 +#define FRAME_recln228 235 +#define FRAME_recln229 236 +#define FRAME_recln230 237 +#define FRAME_recln231 238 +#define FRAME_recln232 239 +#define FRAME_recln233 240 +#define FRAME_recln234 241 +#define FRAME_recln235 242 +#define FRAME_recln236 243 +#define FRAME_recln237 244 +#define FRAME_recln238 245 +#define FRAME_recln239 246 +#define FRAME_recln240 247 +#define FRAME_recln101 248 +#define FRAME_recln102 249 +#define FRAME_recln103 250 +#define FRAME_recln104 251 +#define FRAME_recln105 252 +#define FRAME_recln106 253 +#define FRAME_recln107 254 +#define FRAME_recln108 255 +#define FRAME_recln109 256 +#define FRAME_recln110 257 +#define FRAME_recln111 258 +#define FRAME_recln112 259 +#define FRAME_recln113 260 +#define FRAME_recln114 261 +#define FRAME_recln115 262 +#define FRAME_recln116 263 +#define FRAME_recln117 264 +#define FRAME_recln118 265 +#define FRAME_recln119 266 +#define FRAME_recln120 267 +#define FRAME_recln121 268 +#define FRAME_recln122 269 +#define FRAME_recln123 270 +#define FRAME_recln124 271 +#define FRAME_recln125 272 +#define FRAME_recln126 273 +#define FRAME_recln127 274 +#define FRAME_recln128 275 +#define FRAME_recln129 276 +#define FRAME_recln130 277 +#define FRAME_recln131 278 +#define FRAME_recln132 279 +#define FRAME_recln133 280 +#define FRAME_recln134 281 +#define FRAME_recln135 282 +#define FRAME_recln136 283 +#define FRAME_recln137 284 +#define FRAME_recln138 285 +#define FRAME_recln139 286 +#define FRAME_recln140 287 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_flash.c b/game/m_flash.c new file mode 100644 index 000000000..f6b458c89 --- /dev/null +++ b/game/m_flash.c @@ -0,0 +1,488 @@ +/* +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. + +*/ +// m_flash.c + +#include "q_shared.h" + +// this file is included in both the game dll and quake2, +// the game needs it to source shot locations, the client +// needs it to position muzzle flashes +vec3_t monster_flash_offset [] = +{ +// flash 0 is not used + 0.0, 0.0, 0.0, + +// MZ2_TANK_BLASTER_1 1 + 20.7, -18.5, 28.7, +// MZ2_TANK_BLASTER_2 2 + 16.6, -21.5, 30.1, +// MZ2_TANK_BLASTER_3 3 + 11.8, -23.9, 32.1, +// MZ2_TANK_MACHINEGUN_1 4 + 22.9, -0.7, 25.3, +// MZ2_TANK_MACHINEGUN_2 5 + 22.2, 6.2, 22.3, +// MZ2_TANK_MACHINEGUN_3 6 + 19.4, 13.1, 18.6, +// MZ2_TANK_MACHINEGUN_4 7 + 19.4, 18.8, 18.6, +// MZ2_TANK_MACHINEGUN_5 8 + 17.9, 25.0, 18.6, +// MZ2_TANK_MACHINEGUN_6 9 + 14.1, 30.5, 20.6, +// MZ2_TANK_MACHINEGUN_7 10 + 9.3, 35.3, 22.1, +// MZ2_TANK_MACHINEGUN_8 11 + 4.7, 38.4, 22.1, +// MZ2_TANK_MACHINEGUN_9 12 + -1.1, 40.4, 24.1, +// MZ2_TANK_MACHINEGUN_10 13 + -6.5, 41.2, 24.1, +// MZ2_TANK_MACHINEGUN_11 14 + 3.2, 40.1, 24.7, +// MZ2_TANK_MACHINEGUN_12 15 + 11.7, 36.7, 26.0, +// MZ2_TANK_MACHINEGUN_13 16 + 18.9, 31.3, 26.0, +// MZ2_TANK_MACHINEGUN_14 17 + 24.4, 24.4, 26.4, +// MZ2_TANK_MACHINEGUN_15 18 + 27.1, 17.1, 27.2, +// MZ2_TANK_MACHINEGUN_16 19 + 28.5, 9.1, 28.0, +// MZ2_TANK_MACHINEGUN_17 20 + 27.1, 2.2, 28.0, +// MZ2_TANK_MACHINEGUN_18 21 + 24.9, -2.8, 28.0, +// MZ2_TANK_MACHINEGUN_19 22 + 21.6, -7.0, 26.4, +// MZ2_TANK_ROCKET_1 23 + 6.2, 29.1, 49.1, +// MZ2_TANK_ROCKET_2 24 + 6.9, 23.8, 49.1, +// MZ2_TANK_ROCKET_3 25 + 8.3, 17.8, 49.5, + +// MZ2_INFANTRY_MACHINEGUN_1 26 + 26.6, 7.1, 13.1, +// MZ2_INFANTRY_MACHINEGUN_2 27 + 18.2, 7.5, 15.4, +// MZ2_INFANTRY_MACHINEGUN_3 28 + 17.2, 10.3, 17.9, +// MZ2_INFANTRY_MACHINEGUN_4 29 + 17.0, 12.8, 20.1, +// MZ2_INFANTRY_MACHINEGUN_5 30 + 15.1, 14.1, 21.8, +// MZ2_INFANTRY_MACHINEGUN_6 31 + 11.8, 17.2, 23.1, +// MZ2_INFANTRY_MACHINEGUN_7 32 + 11.4, 20.2, 21.0, +// MZ2_INFANTRY_MACHINEGUN_8 33 + 9.0, 23.0, 18.9, +// MZ2_INFANTRY_MACHINEGUN_9 34 + 13.9, 18.6, 17.7, +// MZ2_INFANTRY_MACHINEGUN_10 35 + 15.4, 15.6, 15.8, +// MZ2_INFANTRY_MACHINEGUN_11 36 + 10.2, 15.2, 25.1, +// MZ2_INFANTRY_MACHINEGUN_12 37 + -1.9, 15.1, 28.2, +// MZ2_INFANTRY_MACHINEGUN_13 38 + -12.4, 13.0, 20.2, + +// MZ2_SOLDIER_BLASTER_1 39 + 10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2, +// MZ2_SOLDIER_BLASTER_2 40 + 21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2, +// MZ2_SOLDIER_SHOTGUN_1 41 + 10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2, +// MZ2_SOLDIER_SHOTGUN_2 42 + 21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2, +// MZ2_SOLDIER_MACHINEGUN_1 43 + 10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2, +// MZ2_SOLDIER_MACHINEGUN_2 44 + 21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2, + +// MZ2_GUNNER_MACHINEGUN_1 45 + 30.1 * 1.15, 3.9 * 1.15, 19.6 * 1.15, +// MZ2_GUNNER_MACHINEGUN_2 46 + 29.1 * 1.15, 2.5 * 1.15, 20.7 * 1.15, +// MZ2_GUNNER_MACHINEGUN_3 47 + 28.2 * 1.15, 2.5 * 1.15, 22.2 * 1.15, +// MZ2_GUNNER_MACHINEGUN_4 48 + 28.2 * 1.15, 3.6 * 1.15, 22.0 * 1.15, +// MZ2_GUNNER_MACHINEGUN_5 49 + 26.9 * 1.15, 2.0 * 1.15, 23.4 * 1.15, +// MZ2_GUNNER_MACHINEGUN_6 50 + 26.5 * 1.15, 0.6 * 1.15, 20.8 * 1.15, +// MZ2_GUNNER_MACHINEGUN_7 51 + 26.9 * 1.15, 0.5 * 1.15, 21.5 * 1.15, +// MZ2_GUNNER_MACHINEGUN_8 52 + 29.0 * 1.15, 2.4 * 1.15, 19.5 * 1.15, +// MZ2_GUNNER_GRENADE_1 53 + 4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15, +// MZ2_GUNNER_GRENADE_2 54 + 4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15, +// MZ2_GUNNER_GRENADE_3 55 + 4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15, +// MZ2_GUNNER_GRENADE_4 56 + 4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15, + +// MZ2_CHICK_ROCKET_1 57 +// -24.8, -9.0, 39.0, + 24.8, -9.0, 39.0, // PGM - this was incorrect in Q2 + +// MZ2_FLYER_BLASTER_1 58 + 12.1, 13.4, -14.5, +// MZ2_FLYER_BLASTER_2 59 + 12.1, -7.4, -14.5, + +// MZ2_MEDIC_BLASTER_1 60 + 12.1, 5.4, 16.5, + +// MZ2_GLADIATOR_RAILGUN_1 61 + 30.0, 18.0, 28.0, + +// MZ2_HOVER_BLASTER_1 62 + 32.5, -0.8, 10.0, + +// MZ2_ACTOR_MACHINEGUN_1 63 + 18.4, 7.4, 9.6, + +// MZ2_SUPERTANK_MACHINEGUN_1 64 + 30.0, 30.0, 88.5, +// MZ2_SUPERTANK_MACHINEGUN_2 65 + 30.0, 30.0, 88.5, +// MZ2_SUPERTANK_MACHINEGUN_3 66 + 30.0, 30.0, 88.5, +// MZ2_SUPERTANK_MACHINEGUN_4 67 + 30.0, 30.0, 88.5, +// MZ2_SUPERTANK_MACHINEGUN_5 68 + 30.0, 30.0, 88.5, +// MZ2_SUPERTANK_MACHINEGUN_6 69 + 30.0, 30.0, 88.5, +// MZ2_SUPERTANK_ROCKET_1 70 + 16.0, -22.5, 91.2, +// MZ2_SUPERTANK_ROCKET_2 71 + 16.0, -33.4, 86.7, +// MZ2_SUPERTANK_ROCKET_3 72 + 16.0, -42.8, 83.3, + +// --- Start Xian Stuff --- +// MZ2_BOSS2_MACHINEGUN_L1 73 + 32, -40, 70, +// MZ2_BOSS2_MACHINEGUN_L2 74 + 32, -40, 70, +// MZ2_BOSS2_MACHINEGUN_L3 75 + 32, -40, 70, +// MZ2_BOSS2_MACHINEGUN_L4 76 + 32, -40, 70, +// MZ2_BOSS2_MACHINEGUN_L5 77 + 32, -40, 70, +// --- End Xian Stuff + +// MZ2_BOSS2_ROCKET_1 78 + 22.0, 16.0, 10.0, +// MZ2_BOSS2_ROCKET_2 79 + 22.0, 8.0, 10.0, +// MZ2_BOSS2_ROCKET_3 80 + 22.0, -8.0, 10.0, +// MZ2_BOSS2_ROCKET_4 81 + 22.0, -16.0, 10.0, + +// MZ2_FLOAT_BLASTER_1 82 + 32.5, -0.8, 10, + +// MZ2_SOLDIER_BLASTER_3 83 + 20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2, +// MZ2_SOLDIER_SHOTGUN_3 84 + 20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2, +// MZ2_SOLDIER_MACHINEGUN_3 85 + 20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2, +// MZ2_SOLDIER_BLASTER_4 86 + 7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2, +// MZ2_SOLDIER_SHOTGUN_4 87 + 7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2, +// MZ2_SOLDIER_MACHINEGUN_4 88 + 7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2, +// MZ2_SOLDIER_BLASTER_5 89 + 30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2, +// MZ2_SOLDIER_SHOTGUN_5 90 + 30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2, +// MZ2_SOLDIER_MACHINEGUN_5 91 + 30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2, +// MZ2_SOLDIER_BLASTER_6 92 + 27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2, +// MZ2_SOLDIER_SHOTGUN_6 93 + 27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2, +// MZ2_SOLDIER_MACHINEGUN_6 94 + 27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2, +// MZ2_SOLDIER_BLASTER_7 95 + 28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2, +// MZ2_SOLDIER_SHOTGUN_7 96 + 28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2, +// MZ2_SOLDIER_MACHINEGUN_7 97 + 28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2, +// MZ2_SOLDIER_BLASTER_8 98 +// 34.5 * 1.2, 9.6 * 1.2, 6.1 * 1.2, + 31.5 * 1.2, 9.6 * 1.2, 10.1 * 1.2, +// MZ2_SOLDIER_SHOTGUN_8 99 + 34.5 * 1.2, 9.6 * 1.2, 6.1 * 1.2, +// MZ2_SOLDIER_MACHINEGUN_8 100 + 34.5 * 1.2, 9.6 * 1.2, 6.1 * 1.2, + +// --- Xian shit below --- +// MZ2_MAKRON_BFG 101 + 17, -19.5, 62.9, +// MZ2_MAKRON_BLASTER_1 102 + -3.6, -24.1, 59.5, +// MZ2_MAKRON_BLASTER_2 103 + -1.6, -19.3, 59.5, +// MZ2_MAKRON_BLASTER_3 104 + -0.1, -14.4, 59.5, +// MZ2_MAKRON_BLASTER_4 105 + 2.0, -7.6, 59.5, +// MZ2_MAKRON_BLASTER_5 106 + 3.4, 1.3, 59.5, +// MZ2_MAKRON_BLASTER_6 107 + 3.7, 11.1, 59.5, +// MZ2_MAKRON_BLASTER_7 108 + -0.3, 22.3, 59.5, +// MZ2_MAKRON_BLASTER_8 109 + -6, 33, 59.5, +// MZ2_MAKRON_BLASTER_9 110 + -9.3, 36.4, 59.5, +// MZ2_MAKRON_BLASTER_10 111 + -7, 35, 59.5, +// MZ2_MAKRON_BLASTER_11 112 + -2.1, 29, 59.5, +// MZ2_MAKRON_BLASTER_12 113 + 3.9, 17.3, 59.5, +// MZ2_MAKRON_BLASTER_13 114 + 6.1, 5.8, 59.5, +// MZ2_MAKRON_BLASTER_14 115 + 5.9, -4.4, 59.5, +// MZ2_MAKRON_BLASTER_15 116 + 4.2, -14.1, 59.5, +// MZ2_MAKRON_BLASTER_16 117 + 2.4, -18.8, 59.5, +// MZ2_MAKRON_BLASTER_17 118 + -1.8, -25.5, 59.5, +// MZ2_MAKRON_RAILGUN_1 119 + -17.3, 7.8, 72.4, + +// MZ2_JORG_MACHINEGUN_L1 120 + 78.5, -47.1, 96, +// MZ2_JORG_MACHINEGUN_L2 121 + 78.5, -47.1, 96, +// MZ2_JORG_MACHINEGUN_L3 122 + 78.5, -47.1, 96, +// MZ2_JORG_MACHINEGUN_L4 123 + 78.5, -47.1, 96, +// MZ2_JORG_MACHINEGUN_L5 124 + 78.5, -47.1, 96, +// MZ2_JORG_MACHINEGUN_L6 125 + 78.5, -47.1, 96, +// MZ2_JORG_MACHINEGUN_R1 126 + 78.5, 46.7, 96, +// MZ2_JORG_MACHINEGUN_R2 127 + 78.5, 46.7, 96, +// MZ2_JORG_MACHINEGUN_R3 128 + 78.5, 46.7, 96, +// MZ2_JORG_MACHINEGUN_R4 129 + 78.5, 46.7, 96, +// MZ2_JORG_MACHINEGUN_R5 130 + 78.5, 46.7, 96, +// MZ2_JORG_MACHINEGUN_R6 131 + 78.5, 46.7, 96, +// MZ2_JORG_BFG_1 132 + 6.3, -9, 111.2, + +// MZ2_BOSS2_MACHINEGUN_R1 73 + 32, 40, 70, +// MZ2_BOSS2_MACHINEGUN_R2 74 + 32, 40, 70, +// MZ2_BOSS2_MACHINEGUN_R3 75 + 32, 40, 70, +// MZ2_BOSS2_MACHINEGUN_R4 76 + 32, 40, 70, +// MZ2_BOSS2_MACHINEGUN_R5 77 + 32, 40, 70, + +// --- End Xian Shit --- + +// ROGUE +// note that the above really ends at 137 +// carrier machineguns +// MZ2_CARRIER_MACHINEGUN_L1 + 56, -32, 32, +// MZ2_CARRIER_MACHINEGUN_R1 + 56, 32, 32, +// MZ2_CARRIER_GRENADE + 42, 24, 50, +// MZ2_TURRET_MACHINEGUN 141 + 16, 0, 0, +// MZ2_TURRET_ROCKET 142 + 16, 0, 0, +// MZ2_TURRET_BLASTER 143 + 16, 0, 0, +// MZ2_STALKER_BLASTER 144 + 24, 0, 6, +// MZ2_DAEDALUS_BLASTER 145 + 32.5, -0.8, 10.0, +// MZ2_MEDIC_BLASTER_2 146 + 12.1, 5.4, 16.5, +// MZ2_CARRIER_RAILGUN 147 + 32, 0, 6, +// MZ2_WIDOW_DISRUPTOR 148 + 57.72, 14.50, 88.81, +// MZ2_WIDOW_BLASTER 149 + 56, 32, 32, +// MZ2_WIDOW_RAIL 150 + 62, -20, 84, +// MZ2_WIDOW_PLASMABEAM 151 // PMM - not used! + 32, 0, 6, +// MZ2_CARRIER_MACHINEGUN_L2 152 + 61, -32, 12, +// MZ2_CARRIER_MACHINEGUN_R2 153 + 61, 32, 12, +// MZ2_WIDOW_RAIL_LEFT 154 + 17, -62, 91, +// MZ2_WIDOW_RAIL_RIGHT 155 + 68, 12, 86, +// MZ2_WIDOW_BLASTER_SWEEP1 156 pmm - the sweeps need to be in sequential order + 47.5, 56, 89, +// MZ2_WIDOW_BLASTER_SWEEP2 157 + 54, 52, 91, +// MZ2_WIDOW_BLASTER_SWEEP3 158 + 58, 40, 91, +// MZ2_WIDOW_BLASTER_SWEEP4 159 + 68, 30, 88, +// MZ2_WIDOW_BLASTER_SWEEP5 160 + 74, 20, 88, +// MZ2_WIDOW_BLASTER_SWEEP6 161 + 73, 11, 87, +// MZ2_WIDOW_BLASTER_SWEEP7 162 + 73, 3, 87, +// MZ2_WIDOW_BLASTER_SWEEP8 163 + 70, -12, 87, +// MZ2_WIDOW_BLASTER_SWEEP9 164 + 67, -20, 90, +// MZ2_WIDOW_BLASTER_100 165 + -20, 76, 90, +// MZ2_WIDOW_BLASTER_90 166 + -8, 74, 90, +// MZ2_WIDOW_BLASTER_80 167 + 0, 72, 90, +// MZ2_WIDOW_BLASTER_70 168 d06 + 10, 71, 89, +// MZ2_WIDOW_BLASTER_60 169 d07 + 23, 70, 87, +// MZ2_WIDOW_BLASTER_50 170 d08 + 32, 64, 85, +// MZ2_WIDOW_BLASTER_40 171 + 40, 58, 84, +// MZ2_WIDOW_BLASTER_30 172 d10 + 48, 50, 83, +// MZ2_WIDOW_BLASTER_20 173 + 54, 42, 82, +// MZ2_WIDOW_BLASTER_10 174 d12 + 56, 34, 82, +// MZ2_WIDOW_BLASTER_0 175 + 58, 26, 82, +// MZ2_WIDOW_BLASTER_10L 176 d14 + 60, 16, 82, +// MZ2_WIDOW_BLASTER_20L 177 + 59, 6, 81, +// MZ2_WIDOW_BLASTER_30L 178 d16 + 58, -2, 80, +// MZ2_WIDOW_BLASTER_40L 179 + 57, -10, 79, +// MZ2_WIDOW_BLASTER_50L 180 d18 + 54, -18, 78, +// MZ2_WIDOW_BLASTER_60L 181 + 42, -32, 80, +// MZ2_WIDOW_BLASTER_70L 182 d20 + 36, -40, 78, +// MZ2_WIDOW_RUN_1 183 + 68.4, 10.88, 82.08, +// MZ2_WIDOW_RUN_2 184 + 68.51, 8.64, 85.14, +// MZ2_WIDOW_RUN_3 185 + 68.66, 6.38, 88.78, +// MZ2_WIDOW_RUN_4 186 + 68.73, 5.1, 84.47, +// MZ2_WIDOW_RUN_5 187 + 68.82, 4.79, 80.52, +// MZ2_WIDOW_RUN_6 188 + 68.77, 6.11, 85.37, +// MZ2_WIDOW_RUN_7 189 + 68.67, 7.99, 90.24, +// MZ2_WIDOW_RUN_8 190 + 68.55, 9.54, 87.36, +// MZ2_CARRIER_ROCKET_1 191 + 0, 0, -5, +// MZ2_CARRIER_ROCKET_2 192 + 0, 0, -5, +// MZ2_CARRIER_ROCKET_3 193 + 0, 0, -5, +// MZ2_CARRIER_ROCKET_4 194 + 0, 0, -5, +// MZ2_WIDOW2_BEAMER_1 195 +// 72.13, -17.63, 93.77, + 69.00, -17.63, 93.77, +// MZ2_WIDOW2_BEAMER_2 196 +// 71.46, -17.08, 89.82, + 69.00, -17.08, 89.82, +// MZ2_WIDOW2_BEAMER_3 197 +// 71.47, -18.40, 90.70, + 69.00, -18.40, 90.70, +// MZ2_WIDOW2_BEAMER_4 198 +// 71.96, -18.34, 94.32, + 69.00, -18.34, 94.32, +// MZ2_WIDOW2_BEAMER_5 199 +// 72.25, -18.30, 97.98, + 69.00, -18.30, 97.98, +// MZ2_WIDOW2_BEAM_SWEEP_1 200 + 45.04, -59.02, 92.24, +// MZ2_WIDOW2_BEAM_SWEEP_2 201 + 50.68, -54.70, 91.96, +// MZ2_WIDOW2_BEAM_SWEEP_3 202 + 56.57, -47.72, 91.65, +// MZ2_WIDOW2_BEAM_SWEEP_4 203 + 61.75, -38.75, 91.38, +// MZ2_WIDOW2_BEAM_SWEEP_5 204 + 65.55, -28.76, 91.24, +// MZ2_WIDOW2_BEAM_SWEEP_6 205 + 67.79, -18.90, 91.22, +// MZ2_WIDOW2_BEAM_SWEEP_7 206 + 68.60, -9.52, 91.23, +// MZ2_WIDOW2_BEAM_SWEEP_8 207 + 68.08, 0.18, 91.32, +// MZ2_WIDOW2_BEAM_SWEEP_9 208 + 66.14, 9.79, 91.44, +// MZ2_WIDOW2_BEAM_SWEEP_10 209 + 62.77, 18.91, 91.65, +// MZ2_WIDOW2_BEAM_SWEEP_11 210 + 58.29, 27.11, 92.00, + +// end of table + 0.0, 0.0, 0.0 +}; diff --git a/game/m_flipper.c b/game/m_flipper.c new file mode 100644 index 000000000..6c623294f --- /dev/null +++ b/game/m_flipper.c @@ -0,0 +1,403 @@ +/* +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. + +*/ +/* +============================================================================== + +FLIPPER + +============================================================================== +*/ + +#include "g_local.h" +#include "m_flipper.h" + + +static int sound_chomp; +static int sound_attack; +static int sound_pain1; +static int sound_pain2; +static int sound_death; +static int sound_idle; +static int sound_search; +static int sound_sight; + + +void flipper_stand (edict_t *self); + +mframe_t flipper_frames_stand [] = +{ + ai_stand, 0, NULL +}; + +mmove_t flipper_move_stand = {FRAME_flphor01, FRAME_flphor01, flipper_frames_stand, NULL}; + +void flipper_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &flipper_move_stand; +} + +#define FLIPPER_RUN_SPEED 24 + +mframe_t flipper_frames_run [] = +{ + ai_run, FLIPPER_RUN_SPEED, NULL, // 6 + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, // 10 + + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, // 20 + + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL, + ai_run, FLIPPER_RUN_SPEED, NULL // 29 +}; +mmove_t flipper_move_run_loop = {FRAME_flpver06, FRAME_flpver29, flipper_frames_run, NULL}; + +void flipper_run_loop (edict_t *self) +{ + self->monsterinfo.currentmove = &flipper_move_run_loop; +} + +mframe_t flipper_frames_run_start [] = +{ + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL +}; +mmove_t flipper_move_run_start = {FRAME_flpver01, FRAME_flpver06, flipper_frames_run_start, flipper_run_loop}; + +void flipper_run (edict_t *self) +{ + self->monsterinfo.currentmove = &flipper_move_run_start; +} + +/* Standard Swimming */ +mframe_t flipper_frames_walk [] = +{ + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL +}; +mmove_t flipper_move_walk = {FRAME_flphor01, FRAME_flphor24, flipper_frames_walk, NULL}; + +void flipper_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &flipper_move_walk; +} + +mframe_t flipper_frames_start_run [] = +{ + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, NULL, + ai_run, 8, flipper_run +}; +mmove_t flipper_move_start_run = {FRAME_flphor01, FRAME_flphor05, flipper_frames_start_run, NULL}; + +void flipper_start_run (edict_t *self) +{ + self->monsterinfo.currentmove = &flipper_move_start_run; +} + +mframe_t flipper_frames_pain2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flipper_move_pain2 = {FRAME_flppn101, FRAME_flppn105, flipper_frames_pain2, flipper_run}; + +mframe_t flipper_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flipper_move_pain1 = {FRAME_flppn201, FRAME_flppn205, flipper_frames_pain1, flipper_run}; + +void flipper_bite (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, 0, 0); + fire_hit (self, aim, 5, 0); +} + +void flipper_preattack (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_chomp, 1, ATTN_NORM, 0); +} + +mframe_t flipper_frames_attack [] = +{ + ai_charge, 0, flipper_preattack, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, flipper_bite, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, flipper_bite, + ai_charge, 0, NULL +}; +mmove_t flipper_move_attack = {FRAME_flpbit01, FRAME_flpbit20, flipper_frames_attack, flipper_run}; + +void flipper_melee(edict_t *self) +{ + self->monsterinfo.currentmove = &flipper_move_attack; +} + +void flipper_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + int n; + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + + if (skill->value == 3) + return; // no pain anims in nightmare + + n = (rand() + 1) % 2; + if (n == 0) + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &flipper_move_pain1; + } + else + { + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &flipper_move_pain2; + } +} + +void flipper_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +mframe_t flipper_frames_death [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flipper_move_death = {FRAME_flpdth01, FRAME_flpdth56, flipper_frames_death, flipper_dead}; + +void flipper_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + +void flipper_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + self->monsterinfo.currentmove = &flipper_move_death; +} + +/*QUAKED monster_flipper (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_flipper (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_pain1 = gi.soundindex ("flipper/flppain1.wav"); + sound_pain2 = gi.soundindex ("flipper/flppain2.wav"); + sound_death = gi.soundindex ("flipper/flpdeth1.wav"); + sound_chomp = gi.soundindex ("flipper/flpatck1.wav"); + sound_attack = gi.soundindex ("flipper/flpatck2.wav"); + sound_idle = gi.soundindex ("flipper/flpidle1.wav"); + sound_search = gi.soundindex ("flipper/flpsrch1.wav"); + sound_sight = gi.soundindex ("flipper/flpsght1.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/flipper/tris.md2"); + VectorSet (self->mins, -16, -16, 0); + VectorSet (self->maxs, 16, 16, 32); + + self->health = 50; + self->gib_health = -30; + self->mass = 100; + + self->pain = flipper_pain; + self->die = flipper_die; + + self->monsterinfo.stand = flipper_stand; + self->monsterinfo.walk = flipper_walk; + self->monsterinfo.run = flipper_start_run; + self->monsterinfo.melee = flipper_melee; + self->monsterinfo.sight = flipper_sight; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &flipper_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + swimmonster_start (self); +} diff --git a/game/m_flipper.h b/game/m_flipper.h new file mode 100644 index 000000000..24522c0b7 --- /dev/null +++ b/game/m_flipper.h @@ -0,0 +1,185 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/flipper + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_flpbit01 0 +#define FRAME_flpbit02 1 +#define FRAME_flpbit03 2 +#define FRAME_flpbit04 3 +#define FRAME_flpbit05 4 +#define FRAME_flpbit06 5 +#define FRAME_flpbit07 6 +#define FRAME_flpbit08 7 +#define FRAME_flpbit09 8 +#define FRAME_flpbit10 9 +#define FRAME_flpbit11 10 +#define FRAME_flpbit12 11 +#define FRAME_flpbit13 12 +#define FRAME_flpbit14 13 +#define FRAME_flpbit15 14 +#define FRAME_flpbit16 15 +#define FRAME_flpbit17 16 +#define FRAME_flpbit18 17 +#define FRAME_flpbit19 18 +#define FRAME_flpbit20 19 +#define FRAME_flptal01 20 +#define FRAME_flptal02 21 +#define FRAME_flptal03 22 +#define FRAME_flptal04 23 +#define FRAME_flptal05 24 +#define FRAME_flptal06 25 +#define FRAME_flptal07 26 +#define FRAME_flptal08 27 +#define FRAME_flptal09 28 +#define FRAME_flptal10 29 +#define FRAME_flptal11 30 +#define FRAME_flptal12 31 +#define FRAME_flptal13 32 +#define FRAME_flptal14 33 +#define FRAME_flptal15 34 +#define FRAME_flptal16 35 +#define FRAME_flptal17 36 +#define FRAME_flptal18 37 +#define FRAME_flptal19 38 +#define FRAME_flptal20 39 +#define FRAME_flptal21 40 +#define FRAME_flphor01 41 +#define FRAME_flphor02 42 +#define FRAME_flphor03 43 +#define FRAME_flphor04 44 +#define FRAME_flphor05 45 +#define FRAME_flphor06 46 +#define FRAME_flphor07 47 +#define FRAME_flphor08 48 +#define FRAME_flphor09 49 +#define FRAME_flphor10 50 +#define FRAME_flphor11 51 +#define FRAME_flphor12 52 +#define FRAME_flphor13 53 +#define FRAME_flphor14 54 +#define FRAME_flphor15 55 +#define FRAME_flphor16 56 +#define FRAME_flphor17 57 +#define FRAME_flphor18 58 +#define FRAME_flphor19 59 +#define FRAME_flphor20 60 +#define FRAME_flphor21 61 +#define FRAME_flphor22 62 +#define FRAME_flphor23 63 +#define FRAME_flphor24 64 +#define FRAME_flpver01 65 +#define FRAME_flpver02 66 +#define FRAME_flpver03 67 +#define FRAME_flpver04 68 +#define FRAME_flpver05 69 +#define FRAME_flpver06 70 +#define FRAME_flpver07 71 +#define FRAME_flpver08 72 +#define FRAME_flpver09 73 +#define FRAME_flpver10 74 +#define FRAME_flpver11 75 +#define FRAME_flpver12 76 +#define FRAME_flpver13 77 +#define FRAME_flpver14 78 +#define FRAME_flpver15 79 +#define FRAME_flpver16 80 +#define FRAME_flpver17 81 +#define FRAME_flpver18 82 +#define FRAME_flpver19 83 +#define FRAME_flpver20 84 +#define FRAME_flpver21 85 +#define FRAME_flpver22 86 +#define FRAME_flpver23 87 +#define FRAME_flpver24 88 +#define FRAME_flpver25 89 +#define FRAME_flpver26 90 +#define FRAME_flpver27 91 +#define FRAME_flpver28 92 +#define FRAME_flpver29 93 +#define FRAME_flppn101 94 +#define FRAME_flppn102 95 +#define FRAME_flppn103 96 +#define FRAME_flppn104 97 +#define FRAME_flppn105 98 +#define FRAME_flppn201 99 +#define FRAME_flppn202 100 +#define FRAME_flppn203 101 +#define FRAME_flppn204 102 +#define FRAME_flppn205 103 +#define FRAME_flpdth01 104 +#define FRAME_flpdth02 105 +#define FRAME_flpdth03 106 +#define FRAME_flpdth04 107 +#define FRAME_flpdth05 108 +#define FRAME_flpdth06 109 +#define FRAME_flpdth07 110 +#define FRAME_flpdth08 111 +#define FRAME_flpdth09 112 +#define FRAME_flpdth10 113 +#define FRAME_flpdth11 114 +#define FRAME_flpdth12 115 +#define FRAME_flpdth13 116 +#define FRAME_flpdth14 117 +#define FRAME_flpdth15 118 +#define FRAME_flpdth16 119 +#define FRAME_flpdth17 120 +#define FRAME_flpdth18 121 +#define FRAME_flpdth19 122 +#define FRAME_flpdth20 123 +#define FRAME_flpdth21 124 +#define FRAME_flpdth22 125 +#define FRAME_flpdth23 126 +#define FRAME_flpdth24 127 +#define FRAME_flpdth25 128 +#define FRAME_flpdth26 129 +#define FRAME_flpdth27 130 +#define FRAME_flpdth28 131 +#define FRAME_flpdth29 132 +#define FRAME_flpdth30 133 +#define FRAME_flpdth31 134 +#define FRAME_flpdth32 135 +#define FRAME_flpdth33 136 +#define FRAME_flpdth34 137 +#define FRAME_flpdth35 138 +#define FRAME_flpdth36 139 +#define FRAME_flpdth37 140 +#define FRAME_flpdth38 141 +#define FRAME_flpdth39 142 +#define FRAME_flpdth40 143 +#define FRAME_flpdth41 144 +#define FRAME_flpdth42 145 +#define FRAME_flpdth43 146 +#define FRAME_flpdth44 147 +#define FRAME_flpdth45 148 +#define FRAME_flpdth46 149 +#define FRAME_flpdth47 150 +#define FRAME_flpdth48 151 +#define FRAME_flpdth49 152 +#define FRAME_flpdth50 153 +#define FRAME_flpdth51 154 +#define FRAME_flpdth52 155 +#define FRAME_flpdth53 156 +#define FRAME_flpdth54 157 +#define FRAME_flpdth55 158 +#define FRAME_flpdth56 159 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_float.c b/game/m_float.c new file mode 100644 index 000000000..57f4750ec --- /dev/null +++ b/game/m_float.c @@ -0,0 +1,663 @@ +/* +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. + +*/ +/* +============================================================================== + +floater + +============================================================================== +*/ + +#include "g_local.h" +#include "m_float.h" + + +static int sound_attack2; +static int sound_attack3; +static int sound_death1; +static int sound_idle; +static int sound_pain1; +static int sound_pain2; +static int sound_sight; + + +void floater_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + +void floater_idle (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); +} + + +//void floater_stand1 (edict_t *self); +void floater_dead (edict_t *self); +void floater_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); +void floater_run (edict_t *self); +void floater_wham (edict_t *self); +void floater_zap (edict_t *self); + + +void floater_fire_blaster (edict_t *self) +{ + vec3_t start; + vec3_t forward, right; + vec3_t end; + vec3_t dir; + int effect; + + if ((self->s.frame == FRAME_attak104) || (self->s.frame == FRAME_attak107)) + effect = EF_HYPERBLASTER; + else + effect = 0; + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_FLOAT_BLASTER_1], forward, right, start); + + VectorCopy (self->enemy->s.origin, end); + end[2] += self->enemy->viewheight; + VectorSubtract (end, start, dir); + + monster_fire_blaster (self, start, dir, 1, 1000, MZ2_FLOAT_BLASTER_1, effect); +} + + +mframe_t floater_frames_stand1 [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t floater_move_stand1 = {FRAME_stand101, FRAME_stand152, floater_frames_stand1, NULL}; + +mframe_t floater_frames_stand2 [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t floater_move_stand2 = {FRAME_stand201, FRAME_stand252, floater_frames_stand2, NULL}; + +void floater_stand (edict_t *self) +{ + if (random() <= 0.5) + self->monsterinfo.currentmove = &floater_move_stand1; + else + self->monsterinfo.currentmove = &floater_move_stand2; +} + +mframe_t floater_frames_activate [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t floater_move_activate = {FRAME_actvat01, FRAME_actvat31, floater_frames_activate, NULL}; + +mframe_t floater_frames_attack1 [] = +{ + ai_charge, 0, NULL, // Blaster attack + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, floater_fire_blaster, // BOOM (0, -25.8, 32.5) -- LOOP Starts + ai_charge, 0, floater_fire_blaster, + ai_charge, 0, floater_fire_blaster, + ai_charge, 0, floater_fire_blaster, + ai_charge, 0, floater_fire_blaster, + ai_charge, 0, floater_fire_blaster, + ai_charge, 0, floater_fire_blaster, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL // -- LOOP Ends +}; +mmove_t floater_move_attack1 = {FRAME_attak101, FRAME_attak114, floater_frames_attack1, floater_run}; + +mframe_t floater_frames_attack2 [] = +{ + ai_charge, 0, NULL, // Claws + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, floater_wham, // WHAM (0, -45, 29.6) -- LOOP Starts + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // -- LOOP Ends + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t floater_move_attack2 = {FRAME_attak201, FRAME_attak225, floater_frames_attack2, floater_run}; + +mframe_t floater_frames_attack3 [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, floater_zap, // -- LOOP Starts + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // -- LOOP Ends + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t floater_move_attack3 = {FRAME_attak301, FRAME_attak334, floater_frames_attack3, floater_run}; + +mframe_t floater_frames_death [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t floater_move_death = {FRAME_death01, FRAME_death13, floater_frames_death, floater_dead}; + +mframe_t floater_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t floater_move_pain1 = {FRAME_pain101, FRAME_pain107, floater_frames_pain1, floater_run}; + +mframe_t floater_frames_pain2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t floater_move_pain2 = {FRAME_pain201, FRAME_pain208, floater_frames_pain2, floater_run}; + +mframe_t floater_frames_pain3 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t floater_move_pain3 = {FRAME_pain301, FRAME_pain312, floater_frames_pain3, floater_run}; + +mframe_t floater_frames_walk [] = +{ + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL +}; +mmove_t floater_move_walk = {FRAME_stand101, FRAME_stand152, floater_frames_walk, NULL}; + +mframe_t floater_frames_run [] = +{ + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL, + ai_run, 13, NULL +}; +mmove_t floater_move_run = {FRAME_stand101, FRAME_stand152, floater_frames_run, NULL}; + +void floater_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &floater_move_stand1; + else + self->monsterinfo.currentmove = &floater_move_run; +} + +void floater_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &floater_move_walk; +} + +void floater_wham (edict_t *self) +{ + static vec3_t aim = {MELEE_DISTANCE, 0, 0}; + gi.sound (self, CHAN_WEAPON, sound_attack3, 1, ATTN_NORM, 0); + fire_hit (self, aim, 5 + rand() % 6, -50); +} + +void floater_zap (edict_t *self) +{ + vec3_t forward, right; + vec3_t origin; + vec3_t dir; + vec3_t offset; + + VectorSubtract (self->enemy->s.origin, self->s.origin, dir); + + AngleVectors (self->s.angles, forward, right, NULL); + //FIXME use a flash and replace these two lines with the commented one + VectorSet (offset, 18.5, -0.9, 10); + G_ProjectSource (self->s.origin, offset, forward, right, origin); +// G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, origin); + + gi.sound (self, CHAN_WEAPON, sound_attack2, 1, ATTN_NORM, 0); + + //FIXME use the flash, Luke + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_SPLASH); + gi.WriteByte (32); + gi.WritePosition (origin); + gi.WriteDir (dir); + gi.WriteByte (1); //sparks + gi.multicast (origin, MULTICAST_PVS); + + T_Damage (self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, 5 + rand() % 6, -10, DAMAGE_ENERGY, MOD_UNKNOWN); +} + +void floater_attack(edict_t *self) +{ + self->monsterinfo.currentmove = &floater_move_attack1; +} + + +void floater_melee(edict_t *self) +{ + if (random() < 0.5) + self->monsterinfo.currentmove = &floater_move_attack3; + else + self->monsterinfo.currentmove = &floater_move_attack2; +} + + +void floater_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + int n; + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + if (skill->value == 3) + return; // no pain anims in nightmare + + n = (rand() + 1) % 3; + if (n == 0) + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &floater_move_pain1; + } + else + { + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &floater_move_pain2; + } +} + +void floater_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +void floater_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); + BecomeExplosion1(self); +} + +/*QUAKED monster_floater (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_floater (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_attack2 = gi.soundindex ("floater/fltatck2.wav"); + sound_attack3 = gi.soundindex ("floater/fltatck3.wav"); + sound_death1 = gi.soundindex ("floater/fltdeth1.wav"); + sound_idle = gi.soundindex ("floater/fltidle1.wav"); + sound_pain1 = gi.soundindex ("floater/fltpain1.wav"); + sound_pain2 = gi.soundindex ("floater/fltpain2.wav"); + sound_sight = gi.soundindex ("floater/fltsght1.wav"); + + gi.soundindex ("floater/fltatck1.wav"); + + self->s.sound = gi.soundindex ("floater/fltsrch1.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/float/tris.md2"); + VectorSet (self->mins, -24, -24, -24); + VectorSet (self->maxs, 24, 24, 32); + + self->health = 200; + self->gib_health = -80; + self->mass = 300; + + self->pain = floater_pain; + self->die = floater_die; + + self->monsterinfo.stand = floater_stand; + self->monsterinfo.walk = floater_walk; + self->monsterinfo.run = floater_run; +// self->monsterinfo.dodge = floater_dodge; + self->monsterinfo.attack = floater_attack; + self->monsterinfo.melee = floater_melee; + self->monsterinfo.sight = floater_sight; + self->monsterinfo.idle = floater_idle; + + gi.linkentity (self); + + if (random() <= 0.5) + self->monsterinfo.currentmove = &floater_move_stand1; + else + self->monsterinfo.currentmove = &floater_move_stand2; + + self->monsterinfo.scale = MODEL_SCALE; + + flymonster_start (self); +} diff --git a/game/m_float.h b/game/m_float.h new file mode 100644 index 000000000..453e5dc4d --- /dev/null +++ b/game/m_float.h @@ -0,0 +1,273 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/float + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_actvat01 0 +#define FRAME_actvat02 1 +#define FRAME_actvat03 2 +#define FRAME_actvat04 3 +#define FRAME_actvat05 4 +#define FRAME_actvat06 5 +#define FRAME_actvat07 6 +#define FRAME_actvat08 7 +#define FRAME_actvat09 8 +#define FRAME_actvat10 9 +#define FRAME_actvat11 10 +#define FRAME_actvat12 11 +#define FRAME_actvat13 12 +#define FRAME_actvat14 13 +#define FRAME_actvat15 14 +#define FRAME_actvat16 15 +#define FRAME_actvat17 16 +#define FRAME_actvat18 17 +#define FRAME_actvat19 18 +#define FRAME_actvat20 19 +#define FRAME_actvat21 20 +#define FRAME_actvat22 21 +#define FRAME_actvat23 22 +#define FRAME_actvat24 23 +#define FRAME_actvat25 24 +#define FRAME_actvat26 25 +#define FRAME_actvat27 26 +#define FRAME_actvat28 27 +#define FRAME_actvat29 28 +#define FRAME_actvat30 29 +#define FRAME_actvat31 30 +#define FRAME_attak101 31 +#define FRAME_attak102 32 +#define FRAME_attak103 33 +#define FRAME_attak104 34 +#define FRAME_attak105 35 +#define FRAME_attak106 36 +#define FRAME_attak107 37 +#define FRAME_attak108 38 +#define FRAME_attak109 39 +#define FRAME_attak110 40 +#define FRAME_attak111 41 +#define FRAME_attak112 42 +#define FRAME_attak113 43 +#define FRAME_attak114 44 +#define FRAME_attak201 45 +#define FRAME_attak202 46 +#define FRAME_attak203 47 +#define FRAME_attak204 48 +#define FRAME_attak205 49 +#define FRAME_attak206 50 +#define FRAME_attak207 51 +#define FRAME_attak208 52 +#define FRAME_attak209 53 +#define FRAME_attak210 54 +#define FRAME_attak211 55 +#define FRAME_attak212 56 +#define FRAME_attak213 57 +#define FRAME_attak214 58 +#define FRAME_attak215 59 +#define FRAME_attak216 60 +#define FRAME_attak217 61 +#define FRAME_attak218 62 +#define FRAME_attak219 63 +#define FRAME_attak220 64 +#define FRAME_attak221 65 +#define FRAME_attak222 66 +#define FRAME_attak223 67 +#define FRAME_attak224 68 +#define FRAME_attak225 69 +#define FRAME_attak301 70 +#define FRAME_attak302 71 +#define FRAME_attak303 72 +#define FRAME_attak304 73 +#define FRAME_attak305 74 +#define FRAME_attak306 75 +#define FRAME_attak307 76 +#define FRAME_attak308 77 +#define FRAME_attak309 78 +#define FRAME_attak310 79 +#define FRAME_attak311 80 +#define FRAME_attak312 81 +#define FRAME_attak313 82 +#define FRAME_attak314 83 +#define FRAME_attak315 84 +#define FRAME_attak316 85 +#define FRAME_attak317 86 +#define FRAME_attak318 87 +#define FRAME_attak319 88 +#define FRAME_attak320 89 +#define FRAME_attak321 90 +#define FRAME_attak322 91 +#define FRAME_attak323 92 +#define FRAME_attak324 93 +#define FRAME_attak325 94 +#define FRAME_attak326 95 +#define FRAME_attak327 96 +#define FRAME_attak328 97 +#define FRAME_attak329 98 +#define FRAME_attak330 99 +#define FRAME_attak331 100 +#define FRAME_attak332 101 +#define FRAME_attak333 102 +#define FRAME_attak334 103 +#define FRAME_death01 104 +#define FRAME_death02 105 +#define FRAME_death03 106 +#define FRAME_death04 107 +#define FRAME_death05 108 +#define FRAME_death06 109 +#define FRAME_death07 110 +#define FRAME_death08 111 +#define FRAME_death09 112 +#define FRAME_death10 113 +#define FRAME_death11 114 +#define FRAME_death12 115 +#define FRAME_death13 116 +#define FRAME_pain101 117 +#define FRAME_pain102 118 +#define FRAME_pain103 119 +#define FRAME_pain104 120 +#define FRAME_pain105 121 +#define FRAME_pain106 122 +#define FRAME_pain107 123 +#define FRAME_pain201 124 +#define FRAME_pain202 125 +#define FRAME_pain203 126 +#define FRAME_pain204 127 +#define FRAME_pain205 128 +#define FRAME_pain206 129 +#define FRAME_pain207 130 +#define FRAME_pain208 131 +#define FRAME_pain301 132 +#define FRAME_pain302 133 +#define FRAME_pain303 134 +#define FRAME_pain304 135 +#define FRAME_pain305 136 +#define FRAME_pain306 137 +#define FRAME_pain307 138 +#define FRAME_pain308 139 +#define FRAME_pain309 140 +#define FRAME_pain310 141 +#define FRAME_pain311 142 +#define FRAME_pain312 143 +#define FRAME_stand101 144 +#define FRAME_stand102 145 +#define FRAME_stand103 146 +#define FRAME_stand104 147 +#define FRAME_stand105 148 +#define FRAME_stand106 149 +#define FRAME_stand107 150 +#define FRAME_stand108 151 +#define FRAME_stand109 152 +#define FRAME_stand110 153 +#define FRAME_stand111 154 +#define FRAME_stand112 155 +#define FRAME_stand113 156 +#define FRAME_stand114 157 +#define FRAME_stand115 158 +#define FRAME_stand116 159 +#define FRAME_stand117 160 +#define FRAME_stand118 161 +#define FRAME_stand119 162 +#define FRAME_stand120 163 +#define FRAME_stand121 164 +#define FRAME_stand122 165 +#define FRAME_stand123 166 +#define FRAME_stand124 167 +#define FRAME_stand125 168 +#define FRAME_stand126 169 +#define FRAME_stand127 170 +#define FRAME_stand128 171 +#define FRAME_stand129 172 +#define FRAME_stand130 173 +#define FRAME_stand131 174 +#define FRAME_stand132 175 +#define FRAME_stand133 176 +#define FRAME_stand134 177 +#define FRAME_stand135 178 +#define FRAME_stand136 179 +#define FRAME_stand137 180 +#define FRAME_stand138 181 +#define FRAME_stand139 182 +#define FRAME_stand140 183 +#define FRAME_stand141 184 +#define FRAME_stand142 185 +#define FRAME_stand143 186 +#define FRAME_stand144 187 +#define FRAME_stand145 188 +#define FRAME_stand146 189 +#define FRAME_stand147 190 +#define FRAME_stand148 191 +#define FRAME_stand149 192 +#define FRAME_stand150 193 +#define FRAME_stand151 194 +#define FRAME_stand152 195 +#define FRAME_stand201 196 +#define FRAME_stand202 197 +#define FRAME_stand203 198 +#define FRAME_stand204 199 +#define FRAME_stand205 200 +#define FRAME_stand206 201 +#define FRAME_stand207 202 +#define FRAME_stand208 203 +#define FRAME_stand209 204 +#define FRAME_stand210 205 +#define FRAME_stand211 206 +#define FRAME_stand212 207 +#define FRAME_stand213 208 +#define FRAME_stand214 209 +#define FRAME_stand215 210 +#define FRAME_stand216 211 +#define FRAME_stand217 212 +#define FRAME_stand218 213 +#define FRAME_stand219 214 +#define FRAME_stand220 215 +#define FRAME_stand221 216 +#define FRAME_stand222 217 +#define FRAME_stand223 218 +#define FRAME_stand224 219 +#define FRAME_stand225 220 +#define FRAME_stand226 221 +#define FRAME_stand227 222 +#define FRAME_stand228 223 +#define FRAME_stand229 224 +#define FRAME_stand230 225 +#define FRAME_stand231 226 +#define FRAME_stand232 227 +#define FRAME_stand233 228 +#define FRAME_stand234 229 +#define FRAME_stand235 230 +#define FRAME_stand236 231 +#define FRAME_stand237 232 +#define FRAME_stand238 233 +#define FRAME_stand239 234 +#define FRAME_stand240 235 +#define FRAME_stand241 236 +#define FRAME_stand242 237 +#define FRAME_stand243 238 +#define FRAME_stand244 239 +#define FRAME_stand245 240 +#define FRAME_stand246 241 +#define FRAME_stand247 242 +#define FRAME_stand248 243 +#define FRAME_stand249 244 +#define FRAME_stand250 245 +#define FRAME_stand251 246 +#define FRAME_stand252 247 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_flyer.c b/game/m_flyer.c new file mode 100644 index 000000000..86409a61e --- /dev/null +++ b/game/m_flyer.c @@ -0,0 +1,626 @@ +/* +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. + +*/ +/* +============================================================================== + +flyer + +============================================================================== +*/ + +#include "g_local.h" +#include "m_flyer.h" + +qboolean visible (edict_t *self, edict_t *other); + +static int nextmove; // Used for start/stop frames + +static int sound_sight; +static int sound_idle; +static int sound_pain1; +static int sound_pain2; +static int sound_slash; +static int sound_sproing; +static int sound_die; + + +void flyer_check_melee(edict_t *self); +void flyer_loop_melee (edict_t *self); +void flyer_melee (edict_t *self); +void flyer_setstart (edict_t *self); +void flyer_stand (edict_t *self); +void flyer_nextmove (edict_t *self); + + +void flyer_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + +void flyer_idle (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); +} + +void flyer_pop_blades (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_sproing, 1, ATTN_NORM, 0); +} + + +mframe_t flyer_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t flyer_move_stand = {FRAME_stand01, FRAME_stand45, flyer_frames_stand, NULL}; + + +mframe_t flyer_frames_walk [] = +{ + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL +}; +mmove_t flyer_move_walk = {FRAME_stand01, FRAME_stand45, flyer_frames_walk, NULL}; + +mframe_t flyer_frames_run [] = +{ + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL +}; +mmove_t flyer_move_run = {FRAME_stand01, FRAME_stand45, flyer_frames_run, NULL}; + +void flyer_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &flyer_move_stand; + else + self->monsterinfo.currentmove = &flyer_move_run; +} + +void flyer_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &flyer_move_walk; +} + +void flyer_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &flyer_move_stand; +} + +mframe_t flyer_frames_start [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, flyer_nextmove +}; +mmove_t flyer_move_start = {FRAME_start01, FRAME_start06, flyer_frames_start, NULL}; + +mframe_t flyer_frames_stop [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, flyer_nextmove +}; +mmove_t flyer_move_stop = {FRAME_stop01, FRAME_stop07, flyer_frames_stop, NULL}; + +void flyer_stop (edict_t *self) +{ + self->monsterinfo.currentmove = &flyer_move_stop; +} + +void flyer_start (edict_t *self) +{ + self->monsterinfo.currentmove = &flyer_move_start; +} + + +mframe_t flyer_frames_rollright [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flyer_move_rollright = {FRAME_rollr01, FRAME_rollr09, flyer_frames_rollright, NULL}; + +mframe_t flyer_frames_rollleft [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flyer_move_rollleft = {FRAME_rollf01, FRAME_rollf09, flyer_frames_rollleft, NULL}; + +mframe_t flyer_frames_pain3 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flyer_move_pain3 = {FRAME_pain301, FRAME_pain304, flyer_frames_pain3, flyer_run}; + +mframe_t flyer_frames_pain2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flyer_move_pain2 = {FRAME_pain201, FRAME_pain204, flyer_frames_pain2, flyer_run}; + +mframe_t flyer_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flyer_move_pain1 = {FRAME_pain101, FRAME_pain109, flyer_frames_pain1, flyer_run}; + +mframe_t flyer_frames_defense [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // Hold this frame + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flyer_move_defense = {FRAME_defens01, FRAME_defens06, flyer_frames_defense, NULL}; + +mframe_t flyer_frames_bankright [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flyer_move_bankright = {FRAME_bankr01, FRAME_bankr07, flyer_frames_bankright, NULL}; + +mframe_t flyer_frames_bankleft [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t flyer_move_bankleft = {FRAME_bankl01, FRAME_bankl07, flyer_frames_bankleft, NULL}; + + +void flyer_fire (edict_t *self, int flash_number) +{ + vec3_t start; + vec3_t forward, right; + vec3_t end; + vec3_t dir; + int effect; + + if ((self->s.frame == FRAME_attak204) || (self->s.frame == FRAME_attak207) || (self->s.frame == FRAME_attak210)) + effect = EF_HYPERBLASTER; + else + effect = 0; + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + VectorCopy (self->enemy->s.origin, end); + end[2] += self->enemy->viewheight; + VectorSubtract (end, start, dir); + + monster_fire_blaster (self, start, dir, 1, 1000, flash_number, effect); +} + +void flyer_fireleft (edict_t *self) +{ + flyer_fire (self, MZ2_FLYER_BLASTER_1); +} + +void flyer_fireright (edict_t *self) +{ + flyer_fire (self, MZ2_FLYER_BLASTER_2); +} + + +mframe_t flyer_frames_attack2 [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, -10, flyer_fireleft, // left gun + ai_charge, -10, flyer_fireright, // right gun + ai_charge, -10, flyer_fireleft, // left gun + ai_charge, -10, flyer_fireright, // right gun + ai_charge, -10, flyer_fireleft, // left gun + ai_charge, -10, flyer_fireright, // right gun + ai_charge, -10, flyer_fireleft, // left gun + ai_charge, -10, flyer_fireright, // right gun + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t flyer_move_attack2 = {FRAME_attak201, FRAME_attak217, flyer_frames_attack2, flyer_run}; + + +void flyer_slash_left (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, self->mins[0], 0); + fire_hit (self, aim, 5, 0); + gi.sound (self, CHAN_WEAPON, sound_slash, 1, ATTN_NORM, 0); +} + +void flyer_slash_right (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 0); + fire_hit (self, aim, 5, 0); + gi.sound (self, CHAN_WEAPON, sound_slash, 1, ATTN_NORM, 0); +} + +mframe_t flyer_frames_start_melee [] = +{ + ai_charge, 0, flyer_pop_blades, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t flyer_move_start_melee = {FRAME_attak101, FRAME_attak106, flyer_frames_start_melee, flyer_loop_melee}; + +mframe_t flyer_frames_end_melee [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t flyer_move_end_melee = {FRAME_attak119, FRAME_attak121, flyer_frames_end_melee, flyer_run}; + + +mframe_t flyer_frames_loop_melee [] = +{ + ai_charge, 0, NULL, // Loop Start + ai_charge, 0, NULL, + ai_charge, 0, flyer_slash_left, // Left Wing Strike + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, flyer_slash_right, // Right Wing Strike + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL // Loop Ends + +}; +mmove_t flyer_move_loop_melee = {FRAME_attak107, FRAME_attak118, flyer_frames_loop_melee, flyer_check_melee}; + +void flyer_loop_melee (edict_t *self) +{ +/* if (random() <= 0.5) + self->monsterinfo.currentmove = &flyer_move_attack1; + else */ + self->monsterinfo.currentmove = &flyer_move_loop_melee; +} + + + +void flyer_attack (edict_t *self) +{ +/* if (random() <= 0.5) + self->monsterinfo.currentmove = &flyer_move_attack1; + else */ + self->monsterinfo.currentmove = &flyer_move_attack2; +} + +void flyer_setstart (edict_t *self) +{ + nextmove = ACTION_run; + self->monsterinfo.currentmove = &flyer_move_start; +} + +void flyer_nextmove (edict_t *self) +{ + if (nextmove == ACTION_attack1) + self->monsterinfo.currentmove = &flyer_move_start_melee; + else if (nextmove == ACTION_attack2) + self->monsterinfo.currentmove = &flyer_move_attack2; + else if (nextmove == ACTION_run) + self->monsterinfo.currentmove = &flyer_move_run; +} + +void flyer_melee (edict_t *self) +{ +// flyer.nextmove = ACTION_attack1; +// self->monsterinfo.currentmove = &flyer_move_stop; + self->monsterinfo.currentmove = &flyer_move_start_melee; +} + +void flyer_check_melee(edict_t *self) +{ + if (range (self, self->enemy) == RANGE_MELEE) + if (random() <= 0.8) + self->monsterinfo.currentmove = &flyer_move_loop_melee; + else + self->monsterinfo.currentmove = &flyer_move_end_melee; + else + self->monsterinfo.currentmove = &flyer_move_end_melee; +} + +void flyer_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + int n; + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + if (skill->value == 3) + return; // no pain anims in nightmare + + n = rand() % 3; + if (n == 0) + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &flyer_move_pain1; + } + else if (n == 1) + { + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &flyer_move_pain2; + } + else + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &flyer_move_pain3; + } +} + + +void flyer_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); + BecomeExplosion1(self); +} + + +/*QUAKED monster_flyer (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_flyer (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + // fix a map bug in jail5.bsp + if (!Q_stricmp(level.mapname, "jail5") && (self->s.origin[2] == -104)) + { + self->targetname = self->target; + self->target = NULL; + } + + sound_sight = gi.soundindex ("flyer/flysght1.wav"); + sound_idle = gi.soundindex ("flyer/flysrch1.wav"); + sound_pain1 = gi.soundindex ("flyer/flypain1.wav"); + sound_pain2 = gi.soundindex ("flyer/flypain2.wav"); + sound_slash = gi.soundindex ("flyer/flyatck2.wav"); + sound_sproing = gi.soundindex ("flyer/flyatck1.wav"); + sound_die = gi.soundindex ("flyer/flydeth1.wav"); + + gi.soundindex ("flyer/flyatck3.wav"); + + self->s.modelindex = gi.modelindex ("models/monsters/flyer/tris.md2"); + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 32); + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + + self->s.sound = gi.soundindex ("flyer/flyidle1.wav"); + + self->health = 50; + self->mass = 50; + + self->pain = flyer_pain; + self->die = flyer_die; + + self->monsterinfo.stand = flyer_stand; + self->monsterinfo.walk = flyer_walk; + self->monsterinfo.run = flyer_run; + self->monsterinfo.attack = flyer_attack; + self->monsterinfo.melee = flyer_melee; + self->monsterinfo.sight = flyer_sight; + self->monsterinfo.idle = flyer_idle; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &flyer_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + flymonster_start (self); +} diff --git a/game/m_flyer.h b/game/m_flyer.h new file mode 100644 index 000000000..ebe080649 --- /dev/null +++ b/game/m_flyer.h @@ -0,0 +1,182 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/flyer + +// This file generated by ModelGen - Do NOT Modify + +#define ACTION_nothing 0 +#define ACTION_attack1 1 +#define ACTION_attack2 2 +#define ACTION_run 3 +#define ACTION_walk 4 + +#define FRAME_start01 0 +#define FRAME_start02 1 +#define FRAME_start03 2 +#define FRAME_start04 3 +#define FRAME_start05 4 +#define FRAME_start06 5 +#define FRAME_stop01 6 +#define FRAME_stop02 7 +#define FRAME_stop03 8 +#define FRAME_stop04 9 +#define FRAME_stop05 10 +#define FRAME_stop06 11 +#define FRAME_stop07 12 +#define FRAME_stand01 13 +#define FRAME_stand02 14 +#define FRAME_stand03 15 +#define FRAME_stand04 16 +#define FRAME_stand05 17 +#define FRAME_stand06 18 +#define FRAME_stand07 19 +#define FRAME_stand08 20 +#define FRAME_stand09 21 +#define FRAME_stand10 22 +#define FRAME_stand11 23 +#define FRAME_stand12 24 +#define FRAME_stand13 25 +#define FRAME_stand14 26 +#define FRAME_stand15 27 +#define FRAME_stand16 28 +#define FRAME_stand17 29 +#define FRAME_stand18 30 +#define FRAME_stand19 31 +#define FRAME_stand20 32 +#define FRAME_stand21 33 +#define FRAME_stand22 34 +#define FRAME_stand23 35 +#define FRAME_stand24 36 +#define FRAME_stand25 37 +#define FRAME_stand26 38 +#define FRAME_stand27 39 +#define FRAME_stand28 40 +#define FRAME_stand29 41 +#define FRAME_stand30 42 +#define FRAME_stand31 43 +#define FRAME_stand32 44 +#define FRAME_stand33 45 +#define FRAME_stand34 46 +#define FRAME_stand35 47 +#define FRAME_stand36 48 +#define FRAME_stand37 49 +#define FRAME_stand38 50 +#define FRAME_stand39 51 +#define FRAME_stand40 52 +#define FRAME_stand41 53 +#define FRAME_stand42 54 +#define FRAME_stand43 55 +#define FRAME_stand44 56 +#define FRAME_stand45 57 +#define FRAME_attak101 58 +#define FRAME_attak102 59 +#define FRAME_attak103 60 +#define FRAME_attak104 61 +#define FRAME_attak105 62 +#define FRAME_attak106 63 +#define FRAME_attak107 64 +#define FRAME_attak108 65 +#define FRAME_attak109 66 +#define FRAME_attak110 67 +#define FRAME_attak111 68 +#define FRAME_attak112 69 +#define FRAME_attak113 70 +#define FRAME_attak114 71 +#define FRAME_attak115 72 +#define FRAME_attak116 73 +#define FRAME_attak117 74 +#define FRAME_attak118 75 +#define FRAME_attak119 76 +#define FRAME_attak120 77 +#define FRAME_attak121 78 +#define FRAME_attak201 79 +#define FRAME_attak202 80 +#define FRAME_attak203 81 +#define FRAME_attak204 82 +#define FRAME_attak205 83 +#define FRAME_attak206 84 +#define FRAME_attak207 85 +#define FRAME_attak208 86 +#define FRAME_attak209 87 +#define FRAME_attak210 88 +#define FRAME_attak211 89 +#define FRAME_attak212 90 +#define FRAME_attak213 91 +#define FRAME_attak214 92 +#define FRAME_attak215 93 +#define FRAME_attak216 94 +#define FRAME_attak217 95 +#define FRAME_bankl01 96 +#define FRAME_bankl02 97 +#define FRAME_bankl03 98 +#define FRAME_bankl04 99 +#define FRAME_bankl05 100 +#define FRAME_bankl06 101 +#define FRAME_bankl07 102 +#define FRAME_bankr01 103 +#define FRAME_bankr02 104 +#define FRAME_bankr03 105 +#define FRAME_bankr04 106 +#define FRAME_bankr05 107 +#define FRAME_bankr06 108 +#define FRAME_bankr07 109 +#define FRAME_rollf01 110 +#define FRAME_rollf02 111 +#define FRAME_rollf03 112 +#define FRAME_rollf04 113 +#define FRAME_rollf05 114 +#define FRAME_rollf06 115 +#define FRAME_rollf07 116 +#define FRAME_rollf08 117 +#define FRAME_rollf09 118 +#define FRAME_rollr01 119 +#define FRAME_rollr02 120 +#define FRAME_rollr03 121 +#define FRAME_rollr04 122 +#define FRAME_rollr05 123 +#define FRAME_rollr06 124 +#define FRAME_rollr07 125 +#define FRAME_rollr08 126 +#define FRAME_rollr09 127 +#define FRAME_defens01 128 +#define FRAME_defens02 129 +#define FRAME_defens03 130 +#define FRAME_defens04 131 +#define FRAME_defens05 132 +#define FRAME_defens06 133 +#define FRAME_pain101 134 +#define FRAME_pain102 135 +#define FRAME_pain103 136 +#define FRAME_pain104 137 +#define FRAME_pain105 138 +#define FRAME_pain106 139 +#define FRAME_pain107 140 +#define FRAME_pain108 141 +#define FRAME_pain109 142 +#define FRAME_pain201 143 +#define FRAME_pain202 144 +#define FRAME_pain203 145 +#define FRAME_pain204 146 +#define FRAME_pain301 147 +#define FRAME_pain302 148 +#define FRAME_pain303 149 +#define FRAME_pain304 150 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_gladiator.c b/game/m_gladiator.c new file mode 100644 index 000000000..69556e892 --- /dev/null +++ b/game/m_gladiator.c @@ -0,0 +1,387 @@ +/* +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. + +*/ +/* +============================================================================== + +GLADIATOR + +============================================================================== +*/ + +#include "g_local.h" +#include "m_gladiator.h" + + +static int sound_pain1; +static int sound_pain2; +static int sound_die; +static int sound_gun; +static int sound_cleaver_swing; +static int sound_cleaver_hit; +static int sound_cleaver_miss; +static int sound_idle; +static int sound_search; +static int sound_sight; + + +void gladiator_idle (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); +} + +void gladiator_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + +void gladiator_search (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); +} + +void gladiator_cleaver_swing (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_cleaver_swing, 1, ATTN_NORM, 0); +} + +mframe_t gladiator_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t gladiator_move_stand = {FRAME_stand1, FRAME_stand7, gladiator_frames_stand, NULL}; + +void gladiator_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &gladiator_move_stand; +} + + +mframe_t gladiator_frames_walk [] = +{ + ai_walk, 15, NULL, + ai_walk, 7, NULL, + ai_walk, 6, NULL, + ai_walk, 5, NULL, + ai_walk, 2, NULL, + ai_walk, 0, NULL, + ai_walk, 2, NULL, + ai_walk, 8, NULL, + ai_walk, 12, NULL, + ai_walk, 8, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 2, NULL, + ai_walk, 2, NULL, + ai_walk, 1, NULL, + ai_walk, 8, NULL +}; +mmove_t gladiator_move_walk = {FRAME_walk1, FRAME_walk16, gladiator_frames_walk, NULL}; + +void gladiator_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &gladiator_move_walk; +} + + +mframe_t gladiator_frames_run [] = +{ + ai_run, 23, NULL, + ai_run, 14, NULL, + ai_run, 14, NULL, + ai_run, 21, NULL, + ai_run, 12, NULL, + ai_run, 13, NULL +}; +mmove_t gladiator_move_run = {FRAME_run1, FRAME_run6, gladiator_frames_run, NULL}; + +void gladiator_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &gladiator_move_stand; + else + self->monsterinfo.currentmove = &gladiator_move_run; +} + + +void GaldiatorMelee (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, self->mins[0], -4); + if (fire_hit (self, aim, (20 + (rand() %5)), 300)) + gi.sound (self, CHAN_AUTO, sound_cleaver_hit, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_AUTO, sound_cleaver_miss, 1, ATTN_NORM, 0); +} + +mframe_t gladiator_frames_attack_melee [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, gladiator_cleaver_swing, + ai_charge, 0, NULL, + ai_charge, 0, GaldiatorMelee, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, gladiator_cleaver_swing, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, GaldiatorMelee, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t gladiator_move_attack_melee = {FRAME_melee1, FRAME_melee17, gladiator_frames_attack_melee, gladiator_run}; + +void gladiator_melee(edict_t *self) +{ + self->monsterinfo.currentmove = &gladiator_move_attack_melee; +} + + +void GladiatorGun (edict_t *self) +{ + vec3_t start; + vec3_t dir; + vec3_t forward, right; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_GLADIATOR_RAILGUN_1], forward, right, start); + + // calc direction to where we targted + VectorSubtract (self->pos1, start, dir); + VectorNormalize (dir); + + monster_fire_railgun (self, start, dir, 50, 100, MZ2_GLADIATOR_RAILGUN_1); +} + +mframe_t gladiator_frames_attack_gun [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, GladiatorGun, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t gladiator_move_attack_gun = {FRAME_attack1, FRAME_attack9, gladiator_frames_attack_gun, gladiator_run}; + +void gladiator_attack(edict_t *self) +{ + float range; + vec3_t v; + + // a small safe zone + VectorSubtract (self->s.origin, self->enemy->s.origin, v); + range = VectorLength(v); + if (range <= (MELEE_DISTANCE + 32)) + return; + + // charge up the railgun + gi.sound (self, CHAN_WEAPON, sound_gun, 1, ATTN_NORM, 0); + VectorCopy (self->enemy->s.origin, self->pos1); //save for aiming the shot + self->pos1[2] += self->enemy->viewheight; + self->monsterinfo.currentmove = &gladiator_move_attack_gun; +} + + +mframe_t gladiator_frames_pain [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t gladiator_move_pain = {FRAME_pain1, FRAME_pain6, gladiator_frames_pain, gladiator_run}; + +mframe_t gladiator_frames_pain_air [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t gladiator_move_pain_air = {FRAME_painup1, FRAME_painup7, gladiator_frames_pain_air, gladiator_run}; + +void gladiator_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + { + if ((self->velocity[2] > 100) && (self->monsterinfo.currentmove == &gladiator_move_pain)) + self->monsterinfo.currentmove = &gladiator_move_pain_air; + return; + } + + self->pain_debounce_time = level.time + 3; + + if (random() < 0.5) + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + + if (skill->value == 3) + return; // no pain anims in nightmare + + if (self->velocity[2] > 100) + self->monsterinfo.currentmove = &gladiator_move_pain_air; + else + self->monsterinfo.currentmove = &gladiator_move_pain; + +} + + +void gladiator_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +mframe_t gladiator_frames_death [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t gladiator_move_death = {FRAME_death1, FRAME_death22, gladiator_frames_death, gladiator_dead}; + +void gladiator_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + + self->monsterinfo.currentmove = &gladiator_move_death; +} + + +/*QUAKED monster_gladiator (1 .5 0) (-32 -32 -24) (32 32 64) Ambush Trigger_Spawn Sight +*/ +void SP_monster_gladiator (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + + sound_pain1 = gi.soundindex ("gladiator/pain.wav"); + sound_pain2 = gi.soundindex ("gladiator/gldpain2.wav"); + sound_die = gi.soundindex ("gladiator/glddeth2.wav"); + sound_gun = gi.soundindex ("gladiator/railgun.wav"); + sound_cleaver_swing = gi.soundindex ("gladiator/melee1.wav"); + sound_cleaver_hit = gi.soundindex ("gladiator/melee2.wav"); + sound_cleaver_miss = gi.soundindex ("gladiator/melee3.wav"); + sound_idle = gi.soundindex ("gladiator/gldidle1.wav"); + sound_search = gi.soundindex ("gladiator/gldsrch1.wav"); + sound_sight = gi.soundindex ("gladiator/sight.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/gladiatr/tris.md2"); + VectorSet (self->mins, -32, -32, -24); + VectorSet (self->maxs, 32, 32, 64); + + self->health = 400; + self->gib_health = -175; + self->mass = 400; + + self->pain = gladiator_pain; + self->die = gladiator_die; + + self->monsterinfo.stand = gladiator_stand; + self->monsterinfo.walk = gladiator_walk; + self->monsterinfo.run = gladiator_run; + self->monsterinfo.dodge = NULL; + self->monsterinfo.attack = gladiator_attack; + self->monsterinfo.melee = gladiator_melee; + self->monsterinfo.sight = gladiator_sight; + self->monsterinfo.idle = gladiator_idle; + self->monsterinfo.search = gladiator_search; + + gi.linkentity (self); + self->monsterinfo.currentmove = &gladiator_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start (self); +} diff --git a/game/m_gladiator.h b/game/m_gladiator.h new file mode 100644 index 000000000..898c7b13f --- /dev/null +++ b/game/m_gladiator.h @@ -0,0 +1,115 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/gladiatr + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_stand1 0 +#define FRAME_stand2 1 +#define FRAME_stand3 2 +#define FRAME_stand4 3 +#define FRAME_stand5 4 +#define FRAME_stand6 5 +#define FRAME_stand7 6 +#define FRAME_walk1 7 +#define FRAME_walk2 8 +#define FRAME_walk3 9 +#define FRAME_walk4 10 +#define FRAME_walk5 11 +#define FRAME_walk6 12 +#define FRAME_walk7 13 +#define FRAME_walk8 14 +#define FRAME_walk9 15 +#define FRAME_walk10 16 +#define FRAME_walk11 17 +#define FRAME_walk12 18 +#define FRAME_walk13 19 +#define FRAME_walk14 20 +#define FRAME_walk15 21 +#define FRAME_walk16 22 +#define FRAME_run1 23 +#define FRAME_run2 24 +#define FRAME_run3 25 +#define FRAME_run4 26 +#define FRAME_run5 27 +#define FRAME_run6 28 +#define FRAME_melee1 29 +#define FRAME_melee2 30 +#define FRAME_melee3 31 +#define FRAME_melee4 32 +#define FRAME_melee5 33 +#define FRAME_melee6 34 +#define FRAME_melee7 35 +#define FRAME_melee8 36 +#define FRAME_melee9 37 +#define FRAME_melee10 38 +#define FRAME_melee11 39 +#define FRAME_melee12 40 +#define FRAME_melee13 41 +#define FRAME_melee14 42 +#define FRAME_melee15 43 +#define FRAME_melee16 44 +#define FRAME_melee17 45 +#define FRAME_attack1 46 +#define FRAME_attack2 47 +#define FRAME_attack3 48 +#define FRAME_attack4 49 +#define FRAME_attack5 50 +#define FRAME_attack6 51 +#define FRAME_attack7 52 +#define FRAME_attack8 53 +#define FRAME_attack9 54 +#define FRAME_pain1 55 +#define FRAME_pain2 56 +#define FRAME_pain3 57 +#define FRAME_pain4 58 +#define FRAME_pain5 59 +#define FRAME_pain6 60 +#define FRAME_death1 61 +#define FRAME_death2 62 +#define FRAME_death3 63 +#define FRAME_death4 64 +#define FRAME_death5 65 +#define FRAME_death6 66 +#define FRAME_death7 67 +#define FRAME_death8 68 +#define FRAME_death9 69 +#define FRAME_death10 70 +#define FRAME_death11 71 +#define FRAME_death12 72 +#define FRAME_death13 73 +#define FRAME_death14 74 +#define FRAME_death15 75 +#define FRAME_death16 76 +#define FRAME_death17 77 +#define FRAME_death18 78 +#define FRAME_death19 79 +#define FRAME_death20 80 +#define FRAME_death21 81 +#define FRAME_death22 82 +#define FRAME_painup1 83 +#define FRAME_painup2 84 +#define FRAME_painup3 85 +#define FRAME_painup4 86 +#define FRAME_painup5 87 +#define FRAME_painup6 88 +#define FRAME_painup7 89 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_gunner.c b/game/m_gunner.c new file mode 100644 index 000000000..96bea136c --- /dev/null +++ b/game/m_gunner.c @@ -0,0 +1,628 @@ +/* +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. + +*/ +/* +============================================================================== + +GUNNER + +============================================================================== +*/ + +#include "g_local.h" +#include "m_gunner.h" + + +static int sound_pain; +static int sound_pain2; +static int sound_death; +static int sound_idle; +static int sound_open; +static int sound_search; +static int sound_sight; + + +void gunner_idlesound (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); +} + +void gunner_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + +void gunner_search (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); +} + + +qboolean visible (edict_t *self, edict_t *other); +void GunnerGrenade (edict_t *self); +void GunnerFire (edict_t *self); +void gunner_fire_chain(edict_t *self); +void gunner_refire_chain(edict_t *self); + + +void gunner_stand (edict_t *self); + +mframe_t gunner_frames_fidget [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, gunner_idlesound, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t gunner_move_fidget = {FRAME_stand31, FRAME_stand70, gunner_frames_fidget, gunner_stand}; + +void gunner_fidget (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + return; + if (random() <= 0.05) + self->monsterinfo.currentmove = &gunner_move_fidget; +} + +mframe_t gunner_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, gunner_fidget, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, gunner_fidget, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, gunner_fidget +}; +mmove_t gunner_move_stand = {FRAME_stand01, FRAME_stand30, gunner_frames_stand, NULL}; + +void gunner_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &gunner_move_stand; +} + + +mframe_t gunner_frames_walk [] = +{ + ai_walk, 0, NULL, + ai_walk, 3, NULL, + ai_walk, 4, NULL, + ai_walk, 5, NULL, + ai_walk, 7, NULL, + ai_walk, 2, NULL, + ai_walk, 6, NULL, + ai_walk, 4, NULL, + ai_walk, 2, NULL, + ai_walk, 7, NULL, + ai_walk, 5, NULL, + ai_walk, 7, NULL, + ai_walk, 4, NULL +}; +mmove_t gunner_move_walk = {FRAME_walk07, FRAME_walk19, gunner_frames_walk, NULL}; + +void gunner_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &gunner_move_walk; +} + +mframe_t gunner_frames_run [] = +{ + ai_run, 26, NULL, + ai_run, 9, NULL, + ai_run, 9, NULL, + ai_run, 9, NULL, + ai_run, 15, NULL, + ai_run, 10, NULL, + ai_run, 13, NULL, + ai_run, 6, NULL +}; + +mmove_t gunner_move_run = {FRAME_run01, FRAME_run08, gunner_frames_run, NULL}; + +void gunner_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &gunner_move_stand; + else + self->monsterinfo.currentmove = &gunner_move_run; +} + +mframe_t gunner_frames_runandshoot [] = +{ + ai_run, 32, NULL, + ai_run, 15, NULL, + ai_run, 10, NULL, + ai_run, 18, NULL, + ai_run, 8, NULL, + ai_run, 20, NULL +}; + +mmove_t gunner_move_runandshoot = {FRAME_runs01, FRAME_runs06, gunner_frames_runandshoot, NULL}; + +void gunner_runandshoot (edict_t *self) +{ + self->monsterinfo.currentmove = &gunner_move_runandshoot; +} + +mframe_t gunner_frames_pain3 [] = +{ + ai_move, -3, NULL, + ai_move, 1, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, 1, NULL +}; +mmove_t gunner_move_pain3 = {FRAME_pain301, FRAME_pain305, gunner_frames_pain3, gunner_run}; + +mframe_t gunner_frames_pain2 [] = +{ + ai_move, -2, NULL, + ai_move, 11, NULL, + ai_move, 6, NULL, + ai_move, 2, NULL, + ai_move, -1, NULL, + ai_move, -7, NULL, + ai_move, -2, NULL, + ai_move, -7, NULL +}; +mmove_t gunner_move_pain2 = {FRAME_pain201, FRAME_pain208, gunner_frames_pain2, gunner_run}; + +mframe_t gunner_frames_pain1 [] = +{ + ai_move, 2, NULL, + ai_move, 0, NULL, + ai_move, -5, NULL, + ai_move, 3, NULL, + ai_move, -1, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 1, NULL, + ai_move, 1, NULL, + ai_move, 2, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, -2, NULL, + ai_move, -2, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t gunner_move_pain1 = {FRAME_pain101, FRAME_pain118, gunner_frames_pain1, gunner_run}; + +void gunner_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + + if (rand()&1) + gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + + if (skill->value == 3) + return; // no pain anims in nightmare + + if (damage <= 10) + self->monsterinfo.currentmove = &gunner_move_pain3; + else if (damage <= 25) + self->monsterinfo.currentmove = &gunner_move_pain2; + else + self->monsterinfo.currentmove = &gunner_move_pain1; +} + +void gunner_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +mframe_t gunner_frames_death [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -7, NULL, + ai_move, -3, NULL, + ai_move, -5, NULL, + ai_move, 8, NULL, + ai_move, 6, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t gunner_move_death = {FRAME_death01, FRAME_death11, gunner_frames_death, gunner_dead}; + +void gunner_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + self->monsterinfo.currentmove = &gunner_move_death; +} + + +void gunner_duck_down (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_DUCKED) + return; + self->monsterinfo.aiflags |= AI_DUCKED; + if (skill->value >= 2) + { + if (random() > 0.5) + GunnerGrenade (self); + } + + self->maxs[2] -= 32; + self->takedamage = DAMAGE_YES; + self->monsterinfo.pausetime = level.time + 1; + gi.linkentity (self); +} + +void gunner_duck_hold (edict_t *self) +{ + if (level.time >= self->monsterinfo.pausetime) + self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; + else + self->monsterinfo.aiflags |= AI_HOLD_FRAME; +} + +void gunner_duck_up (edict_t *self) +{ + self->monsterinfo.aiflags &= ~AI_DUCKED; + self->maxs[2] += 32; + self->takedamage = DAMAGE_AIM; + gi.linkentity (self); +} + +mframe_t gunner_frames_duck [] = +{ + ai_move, 1, gunner_duck_down, + ai_move, 1, NULL, + ai_move, 1, gunner_duck_hold, + ai_move, 0, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, 0, gunner_duck_up, + ai_move, -1, NULL +}; +mmove_t gunner_move_duck = {FRAME_duck01, FRAME_duck08, gunner_frames_duck, gunner_run}; + +void gunner_dodge (edict_t *self, edict_t *attacker, float eta) +{ + if (random() > 0.25) + return; + + if (!self->enemy) + self->enemy = attacker; + + self->monsterinfo.currentmove = &gunner_move_duck; +} + + +void gunner_opengun (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_open, 1, ATTN_IDLE, 0); +} + +void GunnerFire (edict_t *self) +{ + vec3_t start; + vec3_t forward, right; + vec3_t target; + vec3_t aim; + int flash_number; + + flash_number = MZ2_GUNNER_MACHINEGUN_1 + (self->s.frame - FRAME_attak216); + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + // project enemy back a bit and target there + VectorCopy (self->enemy->s.origin, target); + VectorMA (target, -0.2, self->enemy->velocity, target); + target[2] += self->enemy->viewheight; + + VectorSubtract (target, start, aim); + VectorNormalize (aim); + monster_fire_bullet (self, start, aim, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); +} + +void GunnerGrenade (edict_t *self) +{ + vec3_t start; + vec3_t forward, right; + vec3_t aim; + int flash_number; + + if (self->s.frame == FRAME_attak105) + flash_number = MZ2_GUNNER_GRENADE_1; + else if (self->s.frame == FRAME_attak108) + flash_number = MZ2_GUNNER_GRENADE_2; + else if (self->s.frame == FRAME_attak111) + flash_number = MZ2_GUNNER_GRENADE_3; + else // (self->s.frame == FRAME_attak114) + flash_number = MZ2_GUNNER_GRENADE_4; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + //FIXME : do a spread -225 -75 75 225 degrees around forward + VectorCopy (forward, aim); + + monster_fire_grenade (self, start, aim, 50, 600, flash_number); +} + +mframe_t gunner_frames_attack_chain [] = +{ + /* + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + */ + ai_charge, 0, gunner_opengun, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t gunner_move_attack_chain = {FRAME_attak209, FRAME_attak215, gunner_frames_attack_chain, gunner_fire_chain}; + +mframe_t gunner_frames_fire_chain [] = +{ + ai_charge, 0, GunnerFire, + ai_charge, 0, GunnerFire, + ai_charge, 0, GunnerFire, + ai_charge, 0, GunnerFire, + ai_charge, 0, GunnerFire, + ai_charge, 0, GunnerFire, + ai_charge, 0, GunnerFire, + ai_charge, 0, GunnerFire +}; +mmove_t gunner_move_fire_chain = {FRAME_attak216, FRAME_attak223, gunner_frames_fire_chain, gunner_refire_chain}; + +mframe_t gunner_frames_endfire_chain [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t gunner_move_endfire_chain = {FRAME_attak224, FRAME_attak230, gunner_frames_endfire_chain, gunner_run}; + +mframe_t gunner_frames_attack_grenade [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, GunnerGrenade, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, GunnerGrenade, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, GunnerGrenade, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, GunnerGrenade, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t gunner_move_attack_grenade = {FRAME_attak101, FRAME_attak121, gunner_frames_attack_grenade, gunner_run}; + +void gunner_attack(edict_t *self) +{ + if (range (self, self->enemy) == RANGE_MELEE) + { + self->monsterinfo.currentmove = &gunner_move_attack_chain; + } + else + { + if (random() <= 0.5) + self->monsterinfo.currentmove = &gunner_move_attack_grenade; + else + self->monsterinfo.currentmove = &gunner_move_attack_chain; + } +} + +void gunner_fire_chain(edict_t *self) +{ + self->monsterinfo.currentmove = &gunner_move_fire_chain; +} + +void gunner_refire_chain(edict_t *self) +{ + if (self->enemy->health > 0) + if ( visible (self, self->enemy) ) + if (random() <= 0.5) + { + self->monsterinfo.currentmove = &gunner_move_fire_chain; + return; + } + self->monsterinfo.currentmove = &gunner_move_endfire_chain; +} + +/*QUAKED monster_gunner (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_gunner (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_death = gi.soundindex ("gunner/death1.wav"); + sound_pain = gi.soundindex ("gunner/gunpain2.wav"); + sound_pain2 = gi.soundindex ("gunner/gunpain1.wav"); + sound_idle = gi.soundindex ("gunner/gunidle1.wav"); + sound_open = gi.soundindex ("gunner/gunatck1.wav"); + sound_search = gi.soundindex ("gunner/gunsrch1.wav"); + sound_sight = gi.soundindex ("gunner/sight1.wav"); + + gi.soundindex ("gunner/gunatck2.wav"); + gi.soundindex ("gunner/gunatck3.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/gunner/tris.md2"); + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 32); + + self->health = 175; + self->gib_health = -70; + self->mass = 200; + + self->pain = gunner_pain; + self->die = gunner_die; + + self->monsterinfo.stand = gunner_stand; + self->monsterinfo.walk = gunner_walk; + self->monsterinfo.run = gunner_run; + self->monsterinfo.dodge = gunner_dodge; + self->monsterinfo.attack = gunner_attack; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = gunner_sight; + self->monsterinfo.search = gunner_search; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &gunner_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start (self); +} diff --git a/game/m_gunner.h b/game/m_gunner.h new file mode 100644 index 000000000..718832c10 --- /dev/null +++ b/game/m_gunner.h @@ -0,0 +1,234 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/gunner + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_stand01 0 +#define FRAME_stand02 1 +#define FRAME_stand03 2 +#define FRAME_stand04 3 +#define FRAME_stand05 4 +#define FRAME_stand06 5 +#define FRAME_stand07 6 +#define FRAME_stand08 7 +#define FRAME_stand09 8 +#define FRAME_stand10 9 +#define FRAME_stand11 10 +#define FRAME_stand12 11 +#define FRAME_stand13 12 +#define FRAME_stand14 13 +#define FRAME_stand15 14 +#define FRAME_stand16 15 +#define FRAME_stand17 16 +#define FRAME_stand18 17 +#define FRAME_stand19 18 +#define FRAME_stand20 19 +#define FRAME_stand21 20 +#define FRAME_stand22 21 +#define FRAME_stand23 22 +#define FRAME_stand24 23 +#define FRAME_stand25 24 +#define FRAME_stand26 25 +#define FRAME_stand27 26 +#define FRAME_stand28 27 +#define FRAME_stand29 28 +#define FRAME_stand30 29 +#define FRAME_stand31 30 +#define FRAME_stand32 31 +#define FRAME_stand33 32 +#define FRAME_stand34 33 +#define FRAME_stand35 34 +#define FRAME_stand36 35 +#define FRAME_stand37 36 +#define FRAME_stand38 37 +#define FRAME_stand39 38 +#define FRAME_stand40 39 +#define FRAME_stand41 40 +#define FRAME_stand42 41 +#define FRAME_stand43 42 +#define FRAME_stand44 43 +#define FRAME_stand45 44 +#define FRAME_stand46 45 +#define FRAME_stand47 46 +#define FRAME_stand48 47 +#define FRAME_stand49 48 +#define FRAME_stand50 49 +#define FRAME_stand51 50 +#define FRAME_stand52 51 +#define FRAME_stand53 52 +#define FRAME_stand54 53 +#define FRAME_stand55 54 +#define FRAME_stand56 55 +#define FRAME_stand57 56 +#define FRAME_stand58 57 +#define FRAME_stand59 58 +#define FRAME_stand60 59 +#define FRAME_stand61 60 +#define FRAME_stand62 61 +#define FRAME_stand63 62 +#define FRAME_stand64 63 +#define FRAME_stand65 64 +#define FRAME_stand66 65 +#define FRAME_stand67 66 +#define FRAME_stand68 67 +#define FRAME_stand69 68 +#define FRAME_stand70 69 +#define FRAME_walk01 70 +#define FRAME_walk02 71 +#define FRAME_walk03 72 +#define FRAME_walk04 73 +#define FRAME_walk05 74 +#define FRAME_walk06 75 +#define FRAME_walk07 76 +#define FRAME_walk08 77 +#define FRAME_walk09 78 +#define FRAME_walk10 79 +#define FRAME_walk11 80 +#define FRAME_walk12 81 +#define FRAME_walk13 82 +#define FRAME_walk14 83 +#define FRAME_walk15 84 +#define FRAME_walk16 85 +#define FRAME_walk17 86 +#define FRAME_walk18 87 +#define FRAME_walk19 88 +#define FRAME_walk20 89 +#define FRAME_walk21 90 +#define FRAME_walk22 91 +#define FRAME_walk23 92 +#define FRAME_walk24 93 +#define FRAME_run01 94 +#define FRAME_run02 95 +#define FRAME_run03 96 +#define FRAME_run04 97 +#define FRAME_run05 98 +#define FRAME_run06 99 +#define FRAME_run07 100 +#define FRAME_run08 101 +#define FRAME_runs01 102 +#define FRAME_runs02 103 +#define FRAME_runs03 104 +#define FRAME_runs04 105 +#define FRAME_runs05 106 +#define FRAME_runs06 107 +#define FRAME_attak101 108 +#define FRAME_attak102 109 +#define FRAME_attak103 110 +#define FRAME_attak104 111 +#define FRAME_attak105 112 +#define FRAME_attak106 113 +#define FRAME_attak107 114 +#define FRAME_attak108 115 +#define FRAME_attak109 116 +#define FRAME_attak110 117 +#define FRAME_attak111 118 +#define FRAME_attak112 119 +#define FRAME_attak113 120 +#define FRAME_attak114 121 +#define FRAME_attak115 122 +#define FRAME_attak116 123 +#define FRAME_attak117 124 +#define FRAME_attak118 125 +#define FRAME_attak119 126 +#define FRAME_attak120 127 +#define FRAME_attak121 128 +#define FRAME_attak201 129 +#define FRAME_attak202 130 +#define FRAME_attak203 131 +#define FRAME_attak204 132 +#define FRAME_attak205 133 +#define FRAME_attak206 134 +#define FRAME_attak207 135 +#define FRAME_attak208 136 +#define FRAME_attak209 137 +#define FRAME_attak210 138 +#define FRAME_attak211 139 +#define FRAME_attak212 140 +#define FRAME_attak213 141 +#define FRAME_attak214 142 +#define FRAME_attak215 143 +#define FRAME_attak216 144 +#define FRAME_attak217 145 +#define FRAME_attak218 146 +#define FRAME_attak219 147 +#define FRAME_attak220 148 +#define FRAME_attak221 149 +#define FRAME_attak222 150 +#define FRAME_attak223 151 +#define FRAME_attak224 152 +#define FRAME_attak225 153 +#define FRAME_attak226 154 +#define FRAME_attak227 155 +#define FRAME_attak228 156 +#define FRAME_attak229 157 +#define FRAME_attak230 158 +#define FRAME_pain101 159 +#define FRAME_pain102 160 +#define FRAME_pain103 161 +#define FRAME_pain104 162 +#define FRAME_pain105 163 +#define FRAME_pain106 164 +#define FRAME_pain107 165 +#define FRAME_pain108 166 +#define FRAME_pain109 167 +#define FRAME_pain110 168 +#define FRAME_pain111 169 +#define FRAME_pain112 170 +#define FRAME_pain113 171 +#define FRAME_pain114 172 +#define FRAME_pain115 173 +#define FRAME_pain116 174 +#define FRAME_pain117 175 +#define FRAME_pain118 176 +#define FRAME_pain201 177 +#define FRAME_pain202 178 +#define FRAME_pain203 179 +#define FRAME_pain204 180 +#define FRAME_pain205 181 +#define FRAME_pain206 182 +#define FRAME_pain207 183 +#define FRAME_pain208 184 +#define FRAME_pain301 185 +#define FRAME_pain302 186 +#define FRAME_pain303 187 +#define FRAME_pain304 188 +#define FRAME_pain305 189 +#define FRAME_death01 190 +#define FRAME_death02 191 +#define FRAME_death03 192 +#define FRAME_death04 193 +#define FRAME_death05 194 +#define FRAME_death06 195 +#define FRAME_death07 196 +#define FRAME_death08 197 +#define FRAME_death09 198 +#define FRAME_death10 199 +#define FRAME_death11 200 +#define FRAME_duck01 201 +#define FRAME_duck02 202 +#define FRAME_duck03 203 +#define FRAME_duck04 204 +#define FRAME_duck05 205 +#define FRAME_duck06 206 +#define FRAME_duck07 207 +#define FRAME_duck08 208 + +#define MODEL_SCALE 1.150000 diff --git a/game/m_hover.c b/game/m_hover.c new file mode 100644 index 000000000..0851d3d48 --- /dev/null +++ b/game/m_hover.c @@ -0,0 +1,620 @@ +/* +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. + +*/ +/* +============================================================================== + +hover + +============================================================================== +*/ + +#include "g_local.h" +#include "m_hover.h" + +qboolean visible (edict_t *self, edict_t *other); + + +static int sound_pain1; +static int sound_pain2; +static int sound_death1; +static int sound_death2; +static int sound_sight; +static int sound_search1; +static int sound_search2; + + +void hover_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + +void hover_search (edict_t *self) +{ + if (random() < 0.5) + gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0); +} + + +void hover_run (edict_t *self); +void hover_stand (edict_t *self); +void hover_dead (edict_t *self); +void hover_attack (edict_t *self); +void hover_reattack (edict_t *self); +void hover_fire_blaster (edict_t *self); +void hover_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); + +mframe_t hover_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t hover_move_stand = {FRAME_stand01, FRAME_stand30, hover_frames_stand, NULL}; + +mframe_t hover_frames_stop1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t hover_move_stop1 = {FRAME_stop101, FRAME_stop109, hover_frames_stop1, NULL}; + +mframe_t hover_frames_stop2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t hover_move_stop2 = {FRAME_stop201, FRAME_stop208, hover_frames_stop2, NULL}; + +mframe_t hover_frames_takeoff [] = +{ + ai_move, 0, NULL, + ai_move, -2, NULL, + ai_move, 5, NULL, + ai_move, -1, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 2, NULL, + ai_move, 1, NULL, + ai_move, 1, NULL, + ai_move, -6, NULL, + ai_move, -9, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 2, NULL, + ai_move, 1, NULL, + ai_move, 1, NULL, + ai_move, 1, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 3, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL +}; +mmove_t hover_move_takeoff = {FRAME_takeof01, FRAME_takeof30, hover_frames_takeoff, NULL}; + +mframe_t hover_frames_pain3 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t hover_move_pain3 = {FRAME_pain301, FRAME_pain309, hover_frames_pain3, hover_run}; + +mframe_t hover_frames_pain2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t hover_move_pain2 = {FRAME_pain201, FRAME_pain212, hover_frames_pain2, hover_run}; + +mframe_t hover_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, -8, NULL, + ai_move, -4, NULL, + ai_move, -6, NULL, + ai_move, -4, NULL, + ai_move, -3, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 3, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 3, NULL, + ai_move, 2, NULL, + ai_move, 7, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 5, NULL, + ai_move, 3, NULL, + ai_move, 4, NULL +}; +mmove_t hover_move_pain1 = {FRAME_pain101, FRAME_pain128, hover_frames_pain1, hover_run}; + +mframe_t hover_frames_land [] = +{ + ai_move, 0, NULL +}; +mmove_t hover_move_land = {FRAME_land01, FRAME_land01, hover_frames_land, NULL}; + +mframe_t hover_frames_forward [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t hover_move_forward = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_forward, NULL}; + +mframe_t hover_frames_walk [] = +{ + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL +}; +mmove_t hover_move_walk = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_walk, NULL}; + +mframe_t hover_frames_run [] = +{ + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL, + ai_run, 10, NULL +}; +mmove_t hover_move_run = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_run, NULL}; + +mframe_t hover_frames_death1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -10,NULL, + ai_move, 3, NULL, + ai_move, 5, NULL, + ai_move, 4, NULL, + ai_move, 7, NULL +}; +mmove_t hover_move_death1 = {FRAME_death101, FRAME_death111, hover_frames_death1, hover_dead}; + +mframe_t hover_frames_backward [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t hover_move_backward = {FRAME_backwd01, FRAME_backwd24, hover_frames_backward, NULL}; + +mframe_t hover_frames_start_attack [] = +{ + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL +}; +mmove_t hover_move_start_attack = {FRAME_attak101, FRAME_attak103, hover_frames_start_attack, hover_attack}; + +mframe_t hover_frames_attack1 [] = +{ + ai_charge, -10, hover_fire_blaster, + ai_charge, -10, hover_fire_blaster, + ai_charge, 0, hover_reattack, +}; +mmove_t hover_move_attack1 = {FRAME_attak104, FRAME_attak106, hover_frames_attack1, NULL}; + + +mframe_t hover_frames_end_attack [] = +{ + ai_charge, 1, NULL, + ai_charge, 1, NULL +}; +mmove_t hover_move_end_attack = {FRAME_attak107, FRAME_attak108, hover_frames_end_attack, hover_run}; + +void hover_reattack (edict_t *self) +{ + if (self->enemy->health > 0 ) + if (visible (self, self->enemy) ) + if (random() <= 0.6) + { + self->monsterinfo.currentmove = &hover_move_attack1; + return; + } + self->monsterinfo.currentmove = &hover_move_end_attack; +} + + +void hover_fire_blaster (edict_t *self) +{ + vec3_t start; + vec3_t forward, right; + vec3_t end; + vec3_t dir; + int effect; + + if (self->s.frame == FRAME_attak104) + effect = EF_HYPERBLASTER; + else + effect = 0; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_HOVER_BLASTER_1], forward, right, start); + + VectorCopy (self->enemy->s.origin, end); + end[2] += self->enemy->viewheight; + VectorSubtract (end, start, dir); + + monster_fire_blaster (self, start, dir, 1, 1000, MZ2_HOVER_BLASTER_1, effect); +} + + +void hover_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &hover_move_stand; +} + +void hover_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &hover_move_stand; + else + self->monsterinfo.currentmove = &hover_move_run; +} + +void hover_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &hover_move_walk; +} + +void hover_start_attack (edict_t *self) +{ + self->monsterinfo.currentmove = &hover_move_start_attack; +} + +void hover_attack(edict_t *self) +{ + self->monsterinfo.currentmove = &hover_move_attack1; +} + + +void hover_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + + if (skill->value == 3) + return; // no pain anims in nightmare + + if (damage <= 25) + { + if (random() < 0.5) + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &hover_move_pain3; + } + else + { + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &hover_move_pain2; + } + } + else + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &hover_move_pain1; + } +} + +void hover_deadthink (edict_t *self) +{ + if (!self->groundentity && level.time < self->timestamp) + { + self->nextthink = level.time + FRAMETIME; + return; + } + BecomeExplosion1(self); +} + +void hover_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->think = hover_deadthink; + self->nextthink = level.time + FRAMETIME; + self->timestamp = level.time + 15; + gi.linkentity (self); +} + +void hover_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + if (random() < 0.5) + gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + self->monsterinfo.currentmove = &hover_move_death1; +} + +/*QUAKED monster_hover (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_hover (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_pain1 = gi.soundindex ("hover/hovpain1.wav"); + sound_pain2 = gi.soundindex ("hover/hovpain2.wav"); + sound_death1 = gi.soundindex ("hover/hovdeth1.wav"); + sound_death2 = gi.soundindex ("hover/hovdeth2.wav"); + sound_sight = gi.soundindex ("hover/hovsght1.wav"); + sound_search1 = gi.soundindex ("hover/hovsrch1.wav"); + sound_search2 = gi.soundindex ("hover/hovsrch2.wav"); + + gi.soundindex ("hover/hovatck1.wav"); + + self->s.sound = gi.soundindex ("hover/hovidle1.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex("models/monsters/hover/tris.md2"); + VectorSet (self->mins, -24, -24, -24); + VectorSet (self->maxs, 24, 24, 32); + + self->health = 240; + self->gib_health = -100; + self->mass = 150; + + self->pain = hover_pain; + self->die = hover_die; + + self->monsterinfo.stand = hover_stand; + self->monsterinfo.walk = hover_walk; + self->monsterinfo.run = hover_run; +// self->monsterinfo.dodge = hover_dodge; + self->monsterinfo.attack = hover_start_attack; + self->monsterinfo.sight = hover_sight; + self->monsterinfo.search = hover_search; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &hover_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + flymonster_start (self); +} diff --git a/game/m_hover.h b/game/m_hover.h new file mode 100644 index 000000000..c236eaa48 --- /dev/null +++ b/game/m_hover.h @@ -0,0 +1,230 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/hover + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_stand01 0 +#define FRAME_stand02 1 +#define FRAME_stand03 2 +#define FRAME_stand04 3 +#define FRAME_stand05 4 +#define FRAME_stand06 5 +#define FRAME_stand07 6 +#define FRAME_stand08 7 +#define FRAME_stand09 8 +#define FRAME_stand10 9 +#define FRAME_stand11 10 +#define FRAME_stand12 11 +#define FRAME_stand13 12 +#define FRAME_stand14 13 +#define FRAME_stand15 14 +#define FRAME_stand16 15 +#define FRAME_stand17 16 +#define FRAME_stand18 17 +#define FRAME_stand19 18 +#define FRAME_stand20 19 +#define FRAME_stand21 20 +#define FRAME_stand22 21 +#define FRAME_stand23 22 +#define FRAME_stand24 23 +#define FRAME_stand25 24 +#define FRAME_stand26 25 +#define FRAME_stand27 26 +#define FRAME_stand28 27 +#define FRAME_stand29 28 +#define FRAME_stand30 29 +#define FRAME_forwrd01 30 +#define FRAME_forwrd02 31 +#define FRAME_forwrd03 32 +#define FRAME_forwrd04 33 +#define FRAME_forwrd05 34 +#define FRAME_forwrd06 35 +#define FRAME_forwrd07 36 +#define FRAME_forwrd08 37 +#define FRAME_forwrd09 38 +#define FRAME_forwrd10 39 +#define FRAME_forwrd11 40 +#define FRAME_forwrd12 41 +#define FRAME_forwrd13 42 +#define FRAME_forwrd14 43 +#define FRAME_forwrd15 44 +#define FRAME_forwrd16 45 +#define FRAME_forwrd17 46 +#define FRAME_forwrd18 47 +#define FRAME_forwrd19 48 +#define FRAME_forwrd20 49 +#define FRAME_forwrd21 50 +#define FRAME_forwrd22 51 +#define FRAME_forwrd23 52 +#define FRAME_forwrd24 53 +#define FRAME_forwrd25 54 +#define FRAME_forwrd26 55 +#define FRAME_forwrd27 56 +#define FRAME_forwrd28 57 +#define FRAME_forwrd29 58 +#define FRAME_forwrd30 59 +#define FRAME_forwrd31 60 +#define FRAME_forwrd32 61 +#define FRAME_forwrd33 62 +#define FRAME_forwrd34 63 +#define FRAME_forwrd35 64 +#define FRAME_stop101 65 +#define FRAME_stop102 66 +#define FRAME_stop103 67 +#define FRAME_stop104 68 +#define FRAME_stop105 69 +#define FRAME_stop106 70 +#define FRAME_stop107 71 +#define FRAME_stop108 72 +#define FRAME_stop109 73 +#define FRAME_stop201 74 +#define FRAME_stop202 75 +#define FRAME_stop203 76 +#define FRAME_stop204 77 +#define FRAME_stop205 78 +#define FRAME_stop206 79 +#define FRAME_stop207 80 +#define FRAME_stop208 81 +#define FRAME_takeof01 82 +#define FRAME_takeof02 83 +#define FRAME_takeof03 84 +#define FRAME_takeof04 85 +#define FRAME_takeof05 86 +#define FRAME_takeof06 87 +#define FRAME_takeof07 88 +#define FRAME_takeof08 89 +#define FRAME_takeof09 90 +#define FRAME_takeof10 91 +#define FRAME_takeof11 92 +#define FRAME_takeof12 93 +#define FRAME_takeof13 94 +#define FRAME_takeof14 95 +#define FRAME_takeof15 96 +#define FRAME_takeof16 97 +#define FRAME_takeof17 98 +#define FRAME_takeof18 99 +#define FRAME_takeof19 100 +#define FRAME_takeof20 101 +#define FRAME_takeof21 102 +#define FRAME_takeof22 103 +#define FRAME_takeof23 104 +#define FRAME_takeof24 105 +#define FRAME_takeof25 106 +#define FRAME_takeof26 107 +#define FRAME_takeof27 108 +#define FRAME_takeof28 109 +#define FRAME_takeof29 110 +#define FRAME_takeof30 111 +#define FRAME_land01 112 +#define FRAME_pain101 113 +#define FRAME_pain102 114 +#define FRAME_pain103 115 +#define FRAME_pain104 116 +#define FRAME_pain105 117 +#define FRAME_pain106 118 +#define FRAME_pain107 119 +#define FRAME_pain108 120 +#define FRAME_pain109 121 +#define FRAME_pain110 122 +#define FRAME_pain111 123 +#define FRAME_pain112 124 +#define FRAME_pain113 125 +#define FRAME_pain114 126 +#define FRAME_pain115 127 +#define FRAME_pain116 128 +#define FRAME_pain117 129 +#define FRAME_pain118 130 +#define FRAME_pain119 131 +#define FRAME_pain120 132 +#define FRAME_pain121 133 +#define FRAME_pain122 134 +#define FRAME_pain123 135 +#define FRAME_pain124 136 +#define FRAME_pain125 137 +#define FRAME_pain126 138 +#define FRAME_pain127 139 +#define FRAME_pain128 140 +#define FRAME_pain201 141 +#define FRAME_pain202 142 +#define FRAME_pain203 143 +#define FRAME_pain204 144 +#define FRAME_pain205 145 +#define FRAME_pain206 146 +#define FRAME_pain207 147 +#define FRAME_pain208 148 +#define FRAME_pain209 149 +#define FRAME_pain210 150 +#define FRAME_pain211 151 +#define FRAME_pain212 152 +#define FRAME_pain301 153 +#define FRAME_pain302 154 +#define FRAME_pain303 155 +#define FRAME_pain304 156 +#define FRAME_pain305 157 +#define FRAME_pain306 158 +#define FRAME_pain307 159 +#define FRAME_pain308 160 +#define FRAME_pain309 161 +#define FRAME_death101 162 +#define FRAME_death102 163 +#define FRAME_death103 164 +#define FRAME_death104 165 +#define FRAME_death105 166 +#define FRAME_death106 167 +#define FRAME_death107 168 +#define FRAME_death108 169 +#define FRAME_death109 170 +#define FRAME_death110 171 +#define FRAME_death111 172 +#define FRAME_backwd01 173 +#define FRAME_backwd02 174 +#define FRAME_backwd03 175 +#define FRAME_backwd04 176 +#define FRAME_backwd05 177 +#define FRAME_backwd06 178 +#define FRAME_backwd07 179 +#define FRAME_backwd08 180 +#define FRAME_backwd09 181 +#define FRAME_backwd10 182 +#define FRAME_backwd11 183 +#define FRAME_backwd12 184 +#define FRAME_backwd13 185 +#define FRAME_backwd14 186 +#define FRAME_backwd15 187 +#define FRAME_backwd16 188 +#define FRAME_backwd17 189 +#define FRAME_backwd18 190 +#define FRAME_backwd19 191 +#define FRAME_backwd20 192 +#define FRAME_backwd21 193 +#define FRAME_backwd22 194 +#define FRAME_backwd23 195 +#define FRAME_backwd24 196 +#define FRAME_attak101 197 +#define FRAME_attak102 198 +#define FRAME_attak103 199 +#define FRAME_attak104 200 +#define FRAME_attak105 201 +#define FRAME_attak106 202 +#define FRAME_attak107 203 +#define FRAME_attak108 204 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_infantry.c b/game/m_infantry.c new file mode 100644 index 000000000..9ce7f214b --- /dev/null +++ b/game/m_infantry.c @@ -0,0 +1,607 @@ +/* +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. + +*/ +/* +============================================================================== + +INFANTRY + +============================================================================== +*/ + +#include "g_local.h" +#include "m_infantry.h" + +void InfantryMachineGun (edict_t *self); + + +static int sound_pain1; +static int sound_pain2; +static int sound_die1; +static int sound_die2; + +static int sound_gunshot; +static int sound_weapon_cock; +static int sound_punch_swing; +static int sound_punch_hit; +static int sound_sight; +static int sound_search; +static int sound_idle; + + +mframe_t infantry_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t infantry_move_stand = {FRAME_stand50, FRAME_stand71, infantry_frames_stand, NULL}; + +void infantry_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &infantry_move_stand; +} + + +mframe_t infantry_frames_fidget [] = +{ + ai_stand, 1, NULL, + ai_stand, 0, NULL, + ai_stand, 1, NULL, + ai_stand, 3, NULL, + ai_stand, 6, NULL, + ai_stand, 3, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 1, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 1, NULL, + ai_stand, 0, NULL, + ai_stand, -1, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 1, NULL, + ai_stand, 0, NULL, + ai_stand, -2, NULL, + ai_stand, 1, NULL, + ai_stand, 1, NULL, + ai_stand, 1, NULL, + ai_stand, -1, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, -1, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, -1, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 1, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, -1, NULL, + ai_stand, -1, NULL, + ai_stand, 0, NULL, + ai_stand, -3, NULL, + ai_stand, -2, NULL, + ai_stand, -3, NULL, + ai_stand, -3, NULL, + ai_stand, -2, NULL +}; +mmove_t infantry_move_fidget = {FRAME_stand01, FRAME_stand49, infantry_frames_fidget, infantry_stand}; + +void infantry_fidget (edict_t *self) +{ + self->monsterinfo.currentmove = &infantry_move_fidget; + gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); +} + +mframe_t infantry_frames_walk [] = +{ + ai_walk, 5, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 5, NULL, + ai_walk, 4, NULL, + ai_walk, 5, NULL, + ai_walk, 6, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 5, NULL +}; +mmove_t infantry_move_walk = {FRAME_walk03, FRAME_walk14, infantry_frames_walk, NULL}; + +void infantry_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &infantry_move_walk; +} + +mframe_t infantry_frames_run [] = +{ + ai_run, 10, NULL, + ai_run, 20, NULL, + ai_run, 5, NULL, + ai_run, 7, NULL, + ai_run, 30, NULL, + ai_run, 35, NULL, + ai_run, 2, NULL, + ai_run, 6, NULL +}; +mmove_t infantry_move_run = {FRAME_run01, FRAME_run08, infantry_frames_run, NULL}; + +void infantry_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &infantry_move_stand; + else + self->monsterinfo.currentmove = &infantry_move_run; +} + + +mframe_t infantry_frames_pain1 [] = +{ + ai_move, -3, NULL, + ai_move, -2, NULL, + ai_move, -1, NULL, + ai_move, -2, NULL, + ai_move, -1, NULL, + ai_move, 1, NULL, + ai_move, -1, NULL, + ai_move, 1, NULL, + ai_move, 6, NULL, + ai_move, 2, NULL +}; +mmove_t infantry_move_pain1 = {FRAME_pain101, FRAME_pain110, infantry_frames_pain1, infantry_run}; + +mframe_t infantry_frames_pain2 [] = +{ + ai_move, -3, NULL, + ai_move, -3, NULL, + ai_move, 0, NULL, + ai_move, -1, NULL, + ai_move, -2, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 5, NULL, + ai_move, 2, NULL +}; +mmove_t infantry_move_pain2 = {FRAME_pain201, FRAME_pain210, infantry_frames_pain2, infantry_run}; + +void infantry_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + int n; + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + + if (skill->value == 3) + return; // no pain anims in nightmare + + n = rand() % 2; + if (n == 0) + { + self->monsterinfo.currentmove = &infantry_move_pain1; + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + } + else + { + self->monsterinfo.currentmove = &infantry_move_pain2; + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + } +} + + +vec3_t aimangles[] = +{ + 0.0, 5.0, 0.0, + 10.0, 15.0, 0.0, + 20.0, 25.0, 0.0, + 25.0, 35.0, 0.0, + 30.0, 40.0, 0.0, + 30.0, 45.0, 0.0, + 25.0, 50.0, 0.0, + 20.0, 40.0, 0.0, + 15.0, 35.0, 0.0, + 40.0, 35.0, 0.0, + 70.0, 35.0, 0.0, + 90.0, 35.0, 0.0 +}; + +void InfantryMachineGun (edict_t *self) +{ + vec3_t start, target; + vec3_t forward, right; + vec3_t vec; + int flash_number; + + if (self->s.frame == FRAME_attak111) + { + flash_number = MZ2_INFANTRY_MACHINEGUN_1; + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + if (self->enemy) + { + VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target); + target[2] += self->enemy->viewheight; + VectorSubtract (target, start, forward); + VectorNormalize (forward); + } + else + { + AngleVectors (self->s.angles, forward, right, NULL); + } + } + else + { + flash_number = MZ2_INFANTRY_MACHINEGUN_2 + (self->s.frame - FRAME_death211); + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + VectorSubtract (self->s.angles, aimangles[flash_number-MZ2_INFANTRY_MACHINEGUN_2], vec); + AngleVectors (vec, forward, NULL, NULL); + } + + monster_fire_bullet (self, start, forward, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); +} + +void infantry_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_BODY, sound_sight, 1, ATTN_NORM, 0); +} + +void infantry_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + gi.linkentity (self); + + M_FlyCheck (self); +} + +mframe_t infantry_frames_death1 [] = +{ + ai_move, -4, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -1, NULL, + ai_move, -4, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -1, NULL, + ai_move, 3, NULL, + ai_move, 1, NULL, + ai_move, 1, NULL, + ai_move, -2, NULL, + ai_move, 2, NULL, + ai_move, 2, NULL, + ai_move, 9, NULL, + ai_move, 9, NULL, + ai_move, 5, NULL, + ai_move, -3, NULL, + ai_move, -3, NULL +}; +mmove_t infantry_move_death1 = {FRAME_death101, FRAME_death120, infantry_frames_death1, infantry_dead}; + +// Off with his head +mframe_t infantry_frames_death2 [] = +{ + ai_move, 0, NULL, + ai_move, 1, NULL, + ai_move, 5, NULL, + ai_move, -1, NULL, + ai_move, 0, NULL, + ai_move, 1, NULL, + ai_move, 1, NULL, + ai_move, 4, NULL, + ai_move, 3, NULL, + ai_move, 0, NULL, + ai_move, -2, InfantryMachineGun, + ai_move, -2, InfantryMachineGun, + ai_move, -3, InfantryMachineGun, + ai_move, -1, InfantryMachineGun, + ai_move, -2, InfantryMachineGun, + ai_move, 0, InfantryMachineGun, + ai_move, 2, InfantryMachineGun, + ai_move, 2, InfantryMachineGun, + ai_move, 3, InfantryMachineGun, + ai_move, -10, InfantryMachineGun, + ai_move, -7, InfantryMachineGun, + ai_move, -8, InfantryMachineGun, + ai_move, -6, NULL, + ai_move, 4, NULL, + ai_move, 0, NULL +}; +mmove_t infantry_move_death2 = {FRAME_death201, FRAME_death225, infantry_frames_death2, infantry_dead}; + +mframe_t infantry_frames_death3 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -6, NULL, + ai_move, -11, NULL, + ai_move, -3, NULL, + ai_move, -11, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t infantry_move_death3 = {FRAME_death301, FRAME_death309, infantry_frames_death3, infantry_dead}; + + +void infantry_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + + n = rand() % 3; + if (n == 0) + { + self->monsterinfo.currentmove = &infantry_move_death1; + gi.sound (self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0); + } + else if (n == 1) + { + self->monsterinfo.currentmove = &infantry_move_death2; + gi.sound (self, CHAN_VOICE, sound_die1, 1, ATTN_NORM, 0); + } + else + { + self->monsterinfo.currentmove = &infantry_move_death3; + gi.sound (self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0); + } +} + + +void infantry_duck_down (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_DUCKED) + return; + self->monsterinfo.aiflags |= AI_DUCKED; + self->maxs[2] -= 32; + self->takedamage = DAMAGE_YES; + self->monsterinfo.pausetime = level.time + 1; + gi.linkentity (self); +} + +void infantry_duck_hold (edict_t *self) +{ + if (level.time >= self->monsterinfo.pausetime) + self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; + else + self->monsterinfo.aiflags |= AI_HOLD_FRAME; +} + +void infantry_duck_up (edict_t *self) +{ + self->monsterinfo.aiflags &= ~AI_DUCKED; + self->maxs[2] += 32; + self->takedamage = DAMAGE_AIM; + gi.linkentity (self); +} + +mframe_t infantry_frames_duck [] = +{ + ai_move, -2, infantry_duck_down, + ai_move, -5, infantry_duck_hold, + ai_move, 3, NULL, + ai_move, 4, infantry_duck_up, + ai_move, 0, NULL +}; +mmove_t infantry_move_duck = {FRAME_duck01, FRAME_duck05, infantry_frames_duck, infantry_run}; + +void infantry_dodge (edict_t *self, edict_t *attacker, float eta) +{ + if (random() > 0.25) + return; + + if (!self->enemy) + self->enemy = attacker; + + self->monsterinfo.currentmove = &infantry_move_duck; +} + + +void infantry_cock_gun (edict_t *self) +{ + int n; + + gi.sound (self, CHAN_WEAPON, sound_weapon_cock, 1, ATTN_NORM, 0); + n = (rand() & 15) + 3 + 7; + self->monsterinfo.pausetime = level.time + n * FRAMETIME; +} + +void infantry_fire (edict_t *self) +{ + InfantryMachineGun (self); + + if (level.time >= self->monsterinfo.pausetime) + self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; + else + self->monsterinfo.aiflags |= AI_HOLD_FRAME; +} + +mframe_t infantry_frames_attack1 [] = +{ + ai_charge, 4, NULL, + ai_charge, -1, NULL, + ai_charge, -1, NULL, + ai_charge, 0, infantry_cock_gun, + ai_charge, -1, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 2, NULL, + ai_charge, -2, NULL, + ai_charge, -3, NULL, + ai_charge, 1, infantry_fire, + ai_charge, 5, NULL, + ai_charge, -1, NULL, + ai_charge, -2, NULL, + ai_charge, -3, NULL +}; +mmove_t infantry_move_attack1 = {FRAME_attak101, FRAME_attak115, infantry_frames_attack1, infantry_run}; + + +void infantry_swing (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_punch_swing, 1, ATTN_NORM, 0); +} + +void infantry_smack (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, 0, 0); + if (fire_hit (self, aim, (5 + (rand() % 5)), 50)) + gi.sound (self, CHAN_WEAPON, sound_punch_hit, 1, ATTN_NORM, 0); +} + +mframe_t infantry_frames_attack2 [] = +{ + ai_charge, 3, NULL, + ai_charge, 6, NULL, + ai_charge, 0, infantry_swing, + ai_charge, 8, NULL, + ai_charge, 5, NULL, + ai_charge, 8, infantry_smack, + ai_charge, 6, NULL, + ai_charge, 3, NULL, +}; +mmove_t infantry_move_attack2 = {FRAME_attak201, FRAME_attak208, infantry_frames_attack2, infantry_run}; + +void infantry_attack(edict_t *self) +{ + if (range (self, self->enemy) == RANGE_MELEE) + self->monsterinfo.currentmove = &infantry_move_attack2; + else + self->monsterinfo.currentmove = &infantry_move_attack1; +} + + +/*QUAKED monster_infantry (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_infantry (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_pain1 = gi.soundindex ("infantry/infpain1.wav"); + sound_pain2 = gi.soundindex ("infantry/infpain2.wav"); + sound_die1 = gi.soundindex ("infantry/infdeth1.wav"); + sound_die2 = gi.soundindex ("infantry/infdeth2.wav"); + + sound_gunshot = gi.soundindex ("infantry/infatck1.wav"); + sound_weapon_cock = gi.soundindex ("infantry/infatck3.wav"); + sound_punch_swing = gi.soundindex ("infantry/infatck2.wav"); + sound_punch_hit = gi.soundindex ("infantry/melee2.wav"); + + sound_sight = gi.soundindex ("infantry/infsght1.wav"); + sound_search = gi.soundindex ("infantry/infsrch1.wav"); + sound_idle = gi.soundindex ("infantry/infidle1.wav"); + + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2"); + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 32); + + self->health = 100; + self->gib_health = -40; + self->mass = 200; + + self->pain = infantry_pain; + self->die = infantry_die; + + self->monsterinfo.stand = infantry_stand; + self->monsterinfo.walk = infantry_walk; + self->monsterinfo.run = infantry_run; + self->monsterinfo.dodge = infantry_dodge; + self->monsterinfo.attack = infantry_attack; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = infantry_sight; + self->monsterinfo.idle = infantry_fidget; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &infantry_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start (self); +} diff --git a/game/m_infantry.h b/game/m_infantry.h new file mode 100644 index 000000000..be5e3252d --- /dev/null +++ b/game/m_infantry.h @@ -0,0 +1,232 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/infantry + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_gun02 0 +#define FRAME_stand01 1 +#define FRAME_stand02 2 +#define FRAME_stand03 3 +#define FRAME_stand04 4 +#define FRAME_stand05 5 +#define FRAME_stand06 6 +#define FRAME_stand07 7 +#define FRAME_stand08 8 +#define FRAME_stand09 9 +#define FRAME_stand10 10 +#define FRAME_stand11 11 +#define FRAME_stand12 12 +#define FRAME_stand13 13 +#define FRAME_stand14 14 +#define FRAME_stand15 15 +#define FRAME_stand16 16 +#define FRAME_stand17 17 +#define FRAME_stand18 18 +#define FRAME_stand19 19 +#define FRAME_stand20 20 +#define FRAME_stand21 21 +#define FRAME_stand22 22 +#define FRAME_stand23 23 +#define FRAME_stand24 24 +#define FRAME_stand25 25 +#define FRAME_stand26 26 +#define FRAME_stand27 27 +#define FRAME_stand28 28 +#define FRAME_stand29 29 +#define FRAME_stand30 30 +#define FRAME_stand31 31 +#define FRAME_stand32 32 +#define FRAME_stand33 33 +#define FRAME_stand34 34 +#define FRAME_stand35 35 +#define FRAME_stand36 36 +#define FRAME_stand37 37 +#define FRAME_stand38 38 +#define FRAME_stand39 39 +#define FRAME_stand40 40 +#define FRAME_stand41 41 +#define FRAME_stand42 42 +#define FRAME_stand43 43 +#define FRAME_stand44 44 +#define FRAME_stand45 45 +#define FRAME_stand46 46 +#define FRAME_stand47 47 +#define FRAME_stand48 48 +#define FRAME_stand49 49 +#define FRAME_stand50 50 +#define FRAME_stand51 51 +#define FRAME_stand52 52 +#define FRAME_stand53 53 +#define FRAME_stand54 54 +#define FRAME_stand55 55 +#define FRAME_stand56 56 +#define FRAME_stand57 57 +#define FRAME_stand58 58 +#define FRAME_stand59 59 +#define FRAME_stand60 60 +#define FRAME_stand61 61 +#define FRAME_stand62 62 +#define FRAME_stand63 63 +#define FRAME_stand64 64 +#define FRAME_stand65 65 +#define FRAME_stand66 66 +#define FRAME_stand67 67 +#define FRAME_stand68 68 +#define FRAME_stand69 69 +#define FRAME_stand70 70 +#define FRAME_stand71 71 +#define FRAME_walk01 72 +#define FRAME_walk02 73 +#define FRAME_walk03 74 +#define FRAME_walk04 75 +#define FRAME_walk05 76 +#define FRAME_walk06 77 +#define FRAME_walk07 78 +#define FRAME_walk08 79 +#define FRAME_walk09 80 +#define FRAME_walk10 81 +#define FRAME_walk11 82 +#define FRAME_walk12 83 +#define FRAME_walk13 84 +#define FRAME_walk14 85 +#define FRAME_walk15 86 +#define FRAME_walk16 87 +#define FRAME_walk17 88 +#define FRAME_walk18 89 +#define FRAME_walk19 90 +#define FRAME_walk20 91 +#define FRAME_run01 92 +#define FRAME_run02 93 +#define FRAME_run03 94 +#define FRAME_run04 95 +#define FRAME_run05 96 +#define FRAME_run06 97 +#define FRAME_run07 98 +#define FRAME_run08 99 +#define FRAME_pain101 100 +#define FRAME_pain102 101 +#define FRAME_pain103 102 +#define FRAME_pain104 103 +#define FRAME_pain105 104 +#define FRAME_pain106 105 +#define FRAME_pain107 106 +#define FRAME_pain108 107 +#define FRAME_pain109 108 +#define FRAME_pain110 109 +#define FRAME_pain201 110 +#define FRAME_pain202 111 +#define FRAME_pain203 112 +#define FRAME_pain204 113 +#define FRAME_pain205 114 +#define FRAME_pain206 115 +#define FRAME_pain207 116 +#define FRAME_pain208 117 +#define FRAME_pain209 118 +#define FRAME_pain210 119 +#define FRAME_duck01 120 +#define FRAME_duck02 121 +#define FRAME_duck03 122 +#define FRAME_duck04 123 +#define FRAME_duck05 124 +#define FRAME_death101 125 +#define FRAME_death102 126 +#define FRAME_death103 127 +#define FRAME_death104 128 +#define FRAME_death105 129 +#define FRAME_death106 130 +#define FRAME_death107 131 +#define FRAME_death108 132 +#define FRAME_death109 133 +#define FRAME_death110 134 +#define FRAME_death111 135 +#define FRAME_death112 136 +#define FRAME_death113 137 +#define FRAME_death114 138 +#define FRAME_death115 139 +#define FRAME_death116 140 +#define FRAME_death117 141 +#define FRAME_death118 142 +#define FRAME_death119 143 +#define FRAME_death120 144 +#define FRAME_death201 145 +#define FRAME_death202 146 +#define FRAME_death203 147 +#define FRAME_death204 148 +#define FRAME_death205 149 +#define FRAME_death206 150 +#define FRAME_death207 151 +#define FRAME_death208 152 +#define FRAME_death209 153 +#define FRAME_death210 154 +#define FRAME_death211 155 +#define FRAME_death212 156 +#define FRAME_death213 157 +#define FRAME_death214 158 +#define FRAME_death215 159 +#define FRAME_death216 160 +#define FRAME_death217 161 +#define FRAME_death218 162 +#define FRAME_death219 163 +#define FRAME_death220 164 +#define FRAME_death221 165 +#define FRAME_death222 166 +#define FRAME_death223 167 +#define FRAME_death224 168 +#define FRAME_death225 169 +#define FRAME_death301 170 +#define FRAME_death302 171 +#define FRAME_death303 172 +#define FRAME_death304 173 +#define FRAME_death305 174 +#define FRAME_death306 175 +#define FRAME_death307 176 +#define FRAME_death308 177 +#define FRAME_death309 178 +#define FRAME_block01 179 +#define FRAME_block02 180 +#define FRAME_block03 181 +#define FRAME_block04 182 +#define FRAME_block05 183 +#define FRAME_attak101 184 +#define FRAME_attak102 185 +#define FRAME_attak103 186 +#define FRAME_attak104 187 +#define FRAME_attak105 188 +#define FRAME_attak106 189 +#define FRAME_attak107 190 +#define FRAME_attak108 191 +#define FRAME_attak109 192 +#define FRAME_attak110 193 +#define FRAME_attak111 194 +#define FRAME_attak112 195 +#define FRAME_attak113 196 +#define FRAME_attak114 197 +#define FRAME_attak115 198 +#define FRAME_attak201 199 +#define FRAME_attak202 200 +#define FRAME_attak203 201 +#define FRAME_attak204 202 +#define FRAME_attak205 203 +#define FRAME_attak206 204 +#define FRAME_attak207 205 +#define FRAME_attak208 206 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_insane.c b/game/m_insane.c new file mode 100644 index 000000000..7f7cfd306 --- /dev/null +++ b/game/m_insane.c @@ -0,0 +1,693 @@ +/* +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. + +*/ +/* +============================================================================== + +insane + +============================================================================== +*/ + +#include "g_local.h" +#include "m_insane.h" + + +static int sound_fist; +static int sound_shake; +static int sound_moan; +static int sound_scream[8]; + +void insane_fist (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_fist, 1, ATTN_IDLE, 0); +} + +void insane_shake (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_shake, 1, ATTN_IDLE, 0); +} + +void insane_moan (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_moan, 1, ATTN_IDLE, 0); +} + +void insane_scream (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_scream[rand()%8], 1, ATTN_IDLE, 0); +} + + +void insane_stand (edict_t *self); +void insane_dead (edict_t *self); +void insane_cross (edict_t *self); +void insane_walk (edict_t *self); +void insane_run (edict_t *self); +void insane_checkdown (edict_t *self); +void insane_checkup (edict_t *self); +void insane_onground (edict_t *self); + + +mframe_t insane_frames_stand_normal [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, insane_checkdown +}; +mmove_t insane_move_stand_normal = {FRAME_stand60, FRAME_stand65, insane_frames_stand_normal, insane_stand}; + +mframe_t insane_frames_stand_insane [] = +{ + ai_stand, 0, insane_shake, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, insane_checkdown +}; +mmove_t insane_move_stand_insane = {FRAME_stand65, FRAME_stand94, insane_frames_stand_insane, insane_stand}; + +mframe_t insane_frames_uptodown [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, insane_moan, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 2.7, NULL, + ai_move, 4.1, NULL, + ai_move, 6, NULL, + ai_move, 7.6, NULL, + ai_move, 3.6, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, insane_fist, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, insane_fist, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t insane_move_uptodown = {FRAME_stand1, FRAME_stand40, insane_frames_uptodown, insane_onground}; + + +mframe_t insane_frames_downtoup [] = +{ + ai_move, -0.7, NULL, // 41 + ai_move, -1.2, NULL, // 42 + ai_move, -1.5, NULL, // 43 + ai_move, -4.5, NULL, // 44 + ai_move, -3.5, NULL, // 45 + ai_move, -0.2, NULL, // 46 + ai_move, 0, NULL, // 47 + ai_move, -1.3, NULL, // 48 + ai_move, -3, NULL, // 49 + ai_move, -2, NULL, // 50 + ai_move, 0, NULL, // 51 + ai_move, 0, NULL, // 52 + ai_move, 0, NULL, // 53 + ai_move, -3.3, NULL, // 54 + ai_move, -1.6, NULL, // 55 + ai_move, -0.3, NULL, // 56 + ai_move, 0, NULL, // 57 + ai_move, 0, NULL, // 58 + ai_move, 0, NULL // 59 +}; +mmove_t insane_move_downtoup = {FRAME_stand41, FRAME_stand59, insane_frames_downtoup, insane_stand}; + +mframe_t insane_frames_jumpdown [] = +{ + ai_move, 0.2, NULL, + ai_move, 11.5, NULL, + ai_move, 5.1, NULL, + ai_move, 7.1, NULL, + ai_move, 0, NULL +}; +mmove_t insane_move_jumpdown = {FRAME_stand96, FRAME_stand100, insane_frames_jumpdown, insane_onground}; + + +mframe_t insane_frames_down [] = +{ + ai_move, 0, NULL, // 100 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 110 + ai_move, -1.7, NULL, + ai_move, -1.6, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, insane_fist, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 120 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 130 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, insane_moan, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 140 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 150 + ai_move, 0.5, NULL, + ai_move, 0, NULL, + ai_move, -0.2, insane_scream, + ai_move, 0, NULL, + ai_move, 0.2, NULL, + ai_move, 0.4, NULL, + ai_move, 0.6, NULL, + ai_move, 0.8, NULL, + ai_move, 0.7, NULL, + ai_move, 0, insane_checkup // 160 +}; +mmove_t insane_move_down = {FRAME_stand100, FRAME_stand160, insane_frames_down, insane_onground}; + +mframe_t insane_frames_walk_normal [] = +{ + ai_walk, 0, insane_scream, + ai_walk, 2.5, NULL, + ai_walk, 3.5, NULL, + ai_walk, 1.7, NULL, + ai_walk, 2.3, NULL, + ai_walk, 2.4, NULL, + ai_walk, 2.2, NULL, + ai_walk, 4.2, NULL, + ai_walk, 5.6, NULL, + ai_walk, 3.3, NULL, + ai_walk, 2.4, NULL, + ai_walk, 0.9, NULL, + ai_walk, 0, NULL +}; +mmove_t insane_move_walk_normal = {FRAME_walk27, FRAME_walk39, insane_frames_walk_normal, insane_walk}; +mmove_t insane_move_run_normal = {FRAME_walk27, FRAME_walk39, insane_frames_walk_normal, insane_run}; + +mframe_t insane_frames_walk_insane [] = +{ + ai_walk, 0, insane_scream, // walk 1 + ai_walk, 3.4, NULL, // walk 2 + ai_walk, 3.6, NULL, // 3 + ai_walk, 2.9, NULL, // 4 + ai_walk, 2.2, NULL, // 5 + ai_walk, 2.6, NULL, // 6 + ai_walk, 0, NULL, // 7 + ai_walk, 0.7, NULL, // 8 + ai_walk, 4.8, NULL, // 9 + ai_walk, 5.3, NULL, // 10 + ai_walk, 1.1, NULL, // 11 + ai_walk, 2, NULL, // 12 + ai_walk, 0.5, NULL, // 13 + ai_walk, 0, NULL, // 14 + ai_walk, 0, NULL, // 15 + ai_walk, 4.9, NULL, // 16 + ai_walk, 6.7, NULL, // 17 + ai_walk, 3.8, NULL, // 18 + ai_walk, 2, NULL, // 19 + ai_walk, 0.2, NULL, // 20 + ai_walk, 0, NULL, // 21 + ai_walk, 3.4, NULL, // 22 + ai_walk, 6.4, NULL, // 23 + ai_walk, 5, NULL, // 24 + ai_walk, 1.8, NULL, // 25 + ai_walk, 0, NULL // 26 +}; +mmove_t insane_move_walk_insane = {FRAME_walk1, FRAME_walk26, insane_frames_walk_insane, insane_walk}; +mmove_t insane_move_run_insane = {FRAME_walk1, FRAME_walk26, insane_frames_walk_insane, insane_run}; + +mframe_t insane_frames_stand_pain [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t insane_move_stand_pain = {FRAME_st_pain2, FRAME_st_pain12, insane_frames_stand_pain, insane_run}; + +mframe_t insane_frames_stand_death [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t insane_move_stand_death = {FRAME_st_death2, FRAME_st_death18, insane_frames_stand_death, insane_dead}; + +mframe_t insane_frames_crawl [] = +{ + ai_walk, 0, insane_scream, + ai_walk, 1.5, NULL, + ai_walk, 2.1, NULL, + ai_walk, 3.6, NULL, + ai_walk, 2, NULL, + ai_walk, 0.9, NULL, + ai_walk, 3, NULL, + ai_walk, 3.4, NULL, + ai_walk, 2.4, NULL +}; +mmove_t insane_move_crawl = {FRAME_crawl1, FRAME_crawl9, insane_frames_crawl, NULL}; +mmove_t insane_move_runcrawl = {FRAME_crawl1, FRAME_crawl9, insane_frames_crawl, NULL}; + +mframe_t insane_frames_crawl_pain [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t insane_move_crawl_pain = {FRAME_cr_pain2, FRAME_cr_pain10, insane_frames_crawl_pain, insane_run}; + +mframe_t insane_frames_crawl_death [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t insane_move_crawl_death = {FRAME_cr_death10, FRAME_cr_death16, insane_frames_crawl_death, insane_dead}; + +mframe_t insane_frames_cross [] = +{ + ai_move, 0, insane_moan, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t insane_move_cross = {FRAME_cross1, FRAME_cross15, insane_frames_cross, insane_cross}; + +mframe_t insane_frames_struggle_cross [] = +{ + ai_move, 0, insane_scream, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t insane_move_struggle_cross = {FRAME_cross16, FRAME_cross30, insane_frames_struggle_cross, insane_cross}; + +void insane_cross (edict_t *self) +{ + if (random() < 0.8) + self->monsterinfo.currentmove = &insane_move_cross; + else + self->monsterinfo.currentmove = &insane_move_struggle_cross; +} + +void insane_walk (edict_t *self) +{ + if ( self->spawnflags & 16 ) // Hold Ground? + if (self->s.frame == FRAME_cr_pain10) + { + self->monsterinfo.currentmove = &insane_move_down; + return; + } + if (self->spawnflags & 4) + self->monsterinfo.currentmove = &insane_move_crawl; + else + if (random() <= 0.5) + self->monsterinfo.currentmove = &insane_move_walk_normal; + else + self->monsterinfo.currentmove = &insane_move_walk_insane; +} + +void insane_run (edict_t *self) +{ + if ( self->spawnflags & 16 ) // Hold Ground? + if (self->s.frame == FRAME_cr_pain10) + { + self->monsterinfo.currentmove = &insane_move_down; + return; + } + if (self->spawnflags & 4) // Crawling? + self->monsterinfo.currentmove = &insane_move_runcrawl; + else + if (random() <= 0.5) // Else, mix it up + self->monsterinfo.currentmove = &insane_move_run_normal; + else + self->monsterinfo.currentmove = &insane_move_run_insane; +} + + +void insane_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + int l,r; + +// if (self->health < (self->max_health / 2)) +// self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + + r = 1 + (rand()&1); + if (self->health < 25) + l = 25; + else if (self->health < 50) + l = 50; + else if (self->health < 75) + l = 75; + else + l = 100; + gi.sound (self, CHAN_VOICE, gi.soundindex (va("player/male/pain%i_%i.wav", l, r)), 1, ATTN_IDLE, 0); + + if (skill->value == 3) + return; // no pain anims in nightmare + + // Don't go into pain frames if crucified. + if (self->spawnflags & 8) + { + self->monsterinfo.currentmove = &insane_move_struggle_cross; + return; + } + + if ( ((self->s.frame >= FRAME_crawl1) && (self->s.frame <= FRAME_crawl9)) || ((self->s.frame >= FRAME_stand99) && (self->s.frame <= FRAME_stand160)) ) + { + self->monsterinfo.currentmove = &insane_move_crawl_pain; + } + else + self->monsterinfo.currentmove = &insane_move_stand_pain; + +} + +void insane_onground (edict_t *self) +{ + self->monsterinfo.currentmove = &insane_move_down; +} + +void insane_checkdown (edict_t *self) +{ +// if ( (self->s.frame == FRAME_stand94) || (self->s.frame == FRAME_stand65) ) + if (self->spawnflags & 32) // Always stand + return; + if (random() < 0.3) + if (random() < 0.5) + self->monsterinfo.currentmove = &insane_move_uptodown; + else + self->monsterinfo.currentmove = &insane_move_jumpdown; +} + +void insane_checkup (edict_t *self) +{ + // If Hold_Ground and Crawl are set + if ( (self->spawnflags & 4) && (self->spawnflags & 16) ) + return; + if (random() < 0.5) + self->monsterinfo.currentmove = &insane_move_downtoup; + +} + +void insane_stand (edict_t *self) +{ + if (self->spawnflags & 8) // If crucified + { + self->monsterinfo.currentmove = &insane_move_cross; + self->monsterinfo.aiflags |= AI_STAND_GROUND; + } + // If Hold_Ground and Crawl are set + else if ( (self->spawnflags & 4) && (self->spawnflags & 16) ) + self->monsterinfo.currentmove = &insane_move_down; + else + if (random() < 0.5) + self->monsterinfo.currentmove = &insane_move_stand_normal; + else + self->monsterinfo.currentmove = &insane_move_stand_insane; +} + +void insane_dead (edict_t *self) +{ + if (self->spawnflags & 8) + { + self->flags |= FL_FLY; + } + else + { + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + } + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + + +void insane_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_IDLE, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + + gi.sound (self, CHAN_VOICE, gi.soundindex(va("player/male/death%i.wav", (rand()%4)+1)), 1, ATTN_IDLE, 0); + + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + + if (self->spawnflags & 8) + { + insane_dead (self); + } + else + { + if ( ((self->s.frame >= FRAME_crawl1) && (self->s.frame <= FRAME_crawl9)) || ((self->s.frame >= FRAME_stand99) && (self->s.frame <= FRAME_stand160)) ) + self->monsterinfo.currentmove = &insane_move_crawl_death; + else + self->monsterinfo.currentmove = &insane_move_stand_death; + } +} + + +/*QUAKED misc_insane (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn CRAWL CRUCIFIED STAND_GROUND ALWAYS_STAND +*/ +void SP_misc_insane (edict_t *self) +{ +// static int skin = 0; //@@ + + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_fist = gi.soundindex ("insane/insane11.wav"); + sound_shake = gi.soundindex ("insane/insane5.wav"); + sound_moan = gi.soundindex ("insane/insane7.wav"); + sound_scream[0] = gi.soundindex ("insane/insane1.wav"); + sound_scream[1] = gi.soundindex ("insane/insane2.wav"); + sound_scream[2] = gi.soundindex ("insane/insane3.wav"); + sound_scream[3] = gi.soundindex ("insane/insane4.wav"); + sound_scream[4] = gi.soundindex ("insane/insane6.wav"); + sound_scream[5] = gi.soundindex ("insane/insane8.wav"); + sound_scream[6] = gi.soundindex ("insane/insane9.wav"); + sound_scream[7] = gi.soundindex ("insane/insane10.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex("models/monsters/insane/tris.md2"); + + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 32); + + self->health = 100; + self->gib_health = -50; + self->mass = 300; + + self->pain = insane_pain; + self->die = insane_die; + + self->monsterinfo.stand = insane_stand; + self->monsterinfo.walk = insane_walk; + self->monsterinfo.run = insane_run; + self->monsterinfo.dodge = NULL; + self->monsterinfo.attack = NULL; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = NULL; + self->monsterinfo.aiflags |= AI_GOOD_GUY; + +//@@ +// self->s.skinnum = skin; +// skin++; +// if (skin > 12) +// skin = 0; + + gi.linkentity (self); + + if (self->spawnflags & 16) // Stand Ground + self->monsterinfo.aiflags |= AI_STAND_GROUND; + + self->monsterinfo.currentmove = &insane_move_stand_normal; + + self->monsterinfo.scale = MODEL_SCALE; + + if (self->spawnflags & 8) // Crucified ? + { + VectorSet (self->mins, -16, 0, 0); + VectorSet (self->maxs, 16, 8, 32); + self->flags |= FL_NO_KNOCKBACK; + flymonster_start (self); + } + else + { + walkmonster_start (self); + self->s.skinnum = rand()%3; + } +} diff --git a/game/m_insane.h b/game/m_insane.h new file mode 100644 index 000000000..cd5ad9aba --- /dev/null +++ b/game/m_insane.h @@ -0,0 +1,307 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/insane + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_stand1 0 +#define FRAME_stand2 1 +#define FRAME_stand3 2 +#define FRAME_stand4 3 +#define FRAME_stand5 4 +#define FRAME_stand6 5 +#define FRAME_stand7 6 +#define FRAME_stand8 7 +#define FRAME_stand9 8 +#define FRAME_stand10 9 +#define FRAME_stand11 10 +#define FRAME_stand12 11 +#define FRAME_stand13 12 +#define FRAME_stand14 13 +#define FRAME_stand15 14 +#define FRAME_stand16 15 +#define FRAME_stand17 16 +#define FRAME_stand18 17 +#define FRAME_stand19 18 +#define FRAME_stand20 19 +#define FRAME_stand21 20 +#define FRAME_stand22 21 +#define FRAME_stand23 22 +#define FRAME_stand24 23 +#define FRAME_stand25 24 +#define FRAME_stand26 25 +#define FRAME_stand27 26 +#define FRAME_stand28 27 +#define FRAME_stand29 28 +#define FRAME_stand30 29 +#define FRAME_stand31 30 +#define FRAME_stand32 31 +#define FRAME_stand33 32 +#define FRAME_stand34 33 +#define FRAME_stand35 34 +#define FRAME_stand36 35 +#define FRAME_stand37 36 +#define FRAME_stand38 37 +#define FRAME_stand39 38 +#define FRAME_stand40 39 +#define FRAME_stand41 40 +#define FRAME_stand42 41 +#define FRAME_stand43 42 +#define FRAME_stand44 43 +#define FRAME_stand45 44 +#define FRAME_stand46 45 +#define FRAME_stand47 46 +#define FRAME_stand48 47 +#define FRAME_stand49 48 +#define FRAME_stand50 49 +#define FRAME_stand51 50 +#define FRAME_stand52 51 +#define FRAME_stand53 52 +#define FRAME_stand54 53 +#define FRAME_stand55 54 +#define FRAME_stand56 55 +#define FRAME_stand57 56 +#define FRAME_stand58 57 +#define FRAME_stand59 58 +#define FRAME_stand60 59 +#define FRAME_stand61 60 +#define FRAME_stand62 61 +#define FRAME_stand63 62 +#define FRAME_stand64 63 +#define FRAME_stand65 64 +#define FRAME_stand66 65 +#define FRAME_stand67 66 +#define FRAME_stand68 67 +#define FRAME_stand69 68 +#define FRAME_stand70 69 +#define FRAME_stand71 70 +#define FRAME_stand72 71 +#define FRAME_stand73 72 +#define FRAME_stand74 73 +#define FRAME_stand75 74 +#define FRAME_stand76 75 +#define FRAME_stand77 76 +#define FRAME_stand78 77 +#define FRAME_stand79 78 +#define FRAME_stand80 79 +#define FRAME_stand81 80 +#define FRAME_stand82 81 +#define FRAME_stand83 82 +#define FRAME_stand84 83 +#define FRAME_stand85 84 +#define FRAME_stand86 85 +#define FRAME_stand87 86 +#define FRAME_stand88 87 +#define FRAME_stand89 88 +#define FRAME_stand90 89 +#define FRAME_stand91 90 +#define FRAME_stand92 91 +#define FRAME_stand93 92 +#define FRAME_stand94 93 +#define FRAME_stand95 94 +#define FRAME_stand96 95 +#define FRAME_stand97 96 +#define FRAME_stand98 97 +#define FRAME_stand99 98 +#define FRAME_stand100 99 +#define FRAME_stand101 100 +#define FRAME_stand102 101 +#define FRAME_stand103 102 +#define FRAME_stand104 103 +#define FRAME_stand105 104 +#define FRAME_stand106 105 +#define FRAME_stand107 106 +#define FRAME_stand108 107 +#define FRAME_stand109 108 +#define FRAME_stand110 109 +#define FRAME_stand111 110 +#define FRAME_stand112 111 +#define FRAME_stand113 112 +#define FRAME_stand114 113 +#define FRAME_stand115 114 +#define FRAME_stand116 115 +#define FRAME_stand117 116 +#define FRAME_stand118 117 +#define FRAME_stand119 118 +#define FRAME_stand120 119 +#define FRAME_stand121 120 +#define FRAME_stand122 121 +#define FRAME_stand123 122 +#define FRAME_stand124 123 +#define FRAME_stand125 124 +#define FRAME_stand126 125 +#define FRAME_stand127 126 +#define FRAME_stand128 127 +#define FRAME_stand129 128 +#define FRAME_stand130 129 +#define FRAME_stand131 130 +#define FRAME_stand132 131 +#define FRAME_stand133 132 +#define FRAME_stand134 133 +#define FRAME_stand135 134 +#define FRAME_stand136 135 +#define FRAME_stand137 136 +#define FRAME_stand138 137 +#define FRAME_stand139 138 +#define FRAME_stand140 139 +#define FRAME_stand141 140 +#define FRAME_stand142 141 +#define FRAME_stand143 142 +#define FRAME_stand144 143 +#define FRAME_stand145 144 +#define FRAME_stand146 145 +#define FRAME_stand147 146 +#define FRAME_stand148 147 +#define FRAME_stand149 148 +#define FRAME_stand150 149 +#define FRAME_stand151 150 +#define FRAME_stand152 151 +#define FRAME_stand153 152 +#define FRAME_stand154 153 +#define FRAME_stand155 154 +#define FRAME_stand156 155 +#define FRAME_stand157 156 +#define FRAME_stand158 157 +#define FRAME_stand159 158 +#define FRAME_stand160 159 +#define FRAME_walk27 160 +#define FRAME_walk28 161 +#define FRAME_walk29 162 +#define FRAME_walk30 163 +#define FRAME_walk31 164 +#define FRAME_walk32 165 +#define FRAME_walk33 166 +#define FRAME_walk34 167 +#define FRAME_walk35 168 +#define FRAME_walk36 169 +#define FRAME_walk37 170 +#define FRAME_walk38 171 +#define FRAME_walk39 172 +#define FRAME_walk1 173 +#define FRAME_walk2 174 +#define FRAME_walk3 175 +#define FRAME_walk4 176 +#define FRAME_walk5 177 +#define FRAME_walk6 178 +#define FRAME_walk7 179 +#define FRAME_walk8 180 +#define FRAME_walk9 181 +#define FRAME_walk10 182 +#define FRAME_walk11 183 +#define FRAME_walk12 184 +#define FRAME_walk13 185 +#define FRAME_walk14 186 +#define FRAME_walk15 187 +#define FRAME_walk16 188 +#define FRAME_walk17 189 +#define FRAME_walk18 190 +#define FRAME_walk19 191 +#define FRAME_walk20 192 +#define FRAME_walk21 193 +#define FRAME_walk22 194 +#define FRAME_walk23 195 +#define FRAME_walk24 196 +#define FRAME_walk25 197 +#define FRAME_walk26 198 +#define FRAME_st_pain2 199 +#define FRAME_st_pain3 200 +#define FRAME_st_pain4 201 +#define FRAME_st_pain5 202 +#define FRAME_st_pain6 203 +#define FRAME_st_pain7 204 +#define FRAME_st_pain8 205 +#define FRAME_st_pain9 206 +#define FRAME_st_pain10 207 +#define FRAME_st_pain11 208 +#define FRAME_st_pain12 209 +#define FRAME_st_death2 210 +#define FRAME_st_death3 211 +#define FRAME_st_death4 212 +#define FRAME_st_death5 213 +#define FRAME_st_death6 214 +#define FRAME_st_death7 215 +#define FRAME_st_death8 216 +#define FRAME_st_death9 217 +#define FRAME_st_death10 218 +#define FRAME_st_death11 219 +#define FRAME_st_death12 220 +#define FRAME_st_death13 221 +#define FRAME_st_death14 222 +#define FRAME_st_death15 223 +#define FRAME_st_death16 224 +#define FRAME_st_death17 225 +#define FRAME_st_death18 226 +#define FRAME_crawl1 227 +#define FRAME_crawl2 228 +#define FRAME_crawl3 229 +#define FRAME_crawl4 230 +#define FRAME_crawl5 231 +#define FRAME_crawl6 232 +#define FRAME_crawl7 233 +#define FRAME_crawl8 234 +#define FRAME_crawl9 235 +#define FRAME_cr_pain2 236 +#define FRAME_cr_pain3 237 +#define FRAME_cr_pain4 238 +#define FRAME_cr_pain5 239 +#define FRAME_cr_pain6 240 +#define FRAME_cr_pain7 241 +#define FRAME_cr_pain8 242 +#define FRAME_cr_pain9 243 +#define FRAME_cr_pain10 244 +#define FRAME_cr_death10 245 +#define FRAME_cr_death11 246 +#define FRAME_cr_death12 247 +#define FRAME_cr_death13 248 +#define FRAME_cr_death14 249 +#define FRAME_cr_death15 250 +#define FRAME_cr_death16 251 +#define FRAME_cross1 252 +#define FRAME_cross2 253 +#define FRAME_cross3 254 +#define FRAME_cross4 255 +#define FRAME_cross5 256 +#define FRAME_cross6 257 +#define FRAME_cross7 258 +#define FRAME_cross8 259 +#define FRAME_cross9 260 +#define FRAME_cross10 261 +#define FRAME_cross11 262 +#define FRAME_cross12 263 +#define FRAME_cross13 264 +#define FRAME_cross14 265 +#define FRAME_cross15 266 +#define FRAME_cross16 267 +#define FRAME_cross17 268 +#define FRAME_cross18 269 +#define FRAME_cross19 270 +#define FRAME_cross20 271 +#define FRAME_cross21 272 +#define FRAME_cross22 273 +#define FRAME_cross23 274 +#define FRAME_cross24 275 +#define FRAME_cross25 276 +#define FRAME_cross26 277 +#define FRAME_cross27 278 +#define FRAME_cross28 279 +#define FRAME_cross29 280 +#define FRAME_cross30 281 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_medic.c b/game/m_medic.c new file mode 100644 index 000000000..7607f8225 --- /dev/null +++ b/game/m_medic.c @@ -0,0 +1,769 @@ +/* +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. + +*/ +/* +============================================================================== + +MEDIC + +============================================================================== +*/ + +#include "g_local.h" +#include "m_medic.h" + +qboolean visible (edict_t *self, edict_t *other); + + +static int sound_idle1; +static int sound_pain1; +static int sound_pain2; +static int sound_die; +static int sound_sight; +static int sound_search; +static int sound_hook_launch; +static int sound_hook_hit; +static int sound_hook_heal; +static int sound_hook_retract; + + +edict_t *medic_FindDeadMonster (edict_t *self) +{ + edict_t *ent = NULL; + edict_t *best = NULL; + + while ((ent = findradius(ent, self->s.origin, 1024)) != NULL) + { + if (ent == self) + continue; + if (!(ent->svflags & SVF_MONSTER)) + continue; + if (ent->monsterinfo.aiflags & AI_GOOD_GUY) + continue; + if (ent->owner) + continue; + if (ent->health > 0) + continue; + if (ent->nextthink) + continue; + if (!visible(self, ent)) + continue; + if (!best) + { + best = ent; + continue; + } + if (ent->max_health <= best->max_health) + continue; + best = ent; + } + + return best; +} + +void medic_idle (edict_t *self) +{ + edict_t *ent; + + gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0); + + ent = medic_FindDeadMonster(self); + if (ent) + { + self->enemy = ent; + self->enemy->owner = self; + self->monsterinfo.aiflags |= AI_MEDIC; + FoundTarget (self); + } +} + +void medic_search (edict_t *self) +{ + edict_t *ent; + + gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_IDLE, 0); + + if (!self->oldenemy) + { + ent = medic_FindDeadMonster(self); + if (ent) + { + self->oldenemy = self->enemy; + self->enemy = ent; + self->enemy->owner = self; + self->monsterinfo.aiflags |= AI_MEDIC; + FoundTarget (self); + } + } +} + +void medic_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + + +mframe_t medic_frames_stand [] = +{ + ai_stand, 0, medic_idle, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + +}; +mmove_t medic_move_stand = {FRAME_wait1, FRAME_wait90, medic_frames_stand, NULL}; + +void medic_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &medic_move_stand; +} + + +mframe_t medic_frames_walk [] = +{ + ai_walk, 6.2, NULL, + ai_walk, 18.1, NULL, + ai_walk, 1, NULL, + ai_walk, 9, NULL, + ai_walk, 10, NULL, + ai_walk, 9, NULL, + ai_walk, 11, NULL, + ai_walk, 11.6, NULL, + ai_walk, 2, NULL, + ai_walk, 9.9, NULL, + ai_walk, 14, NULL, + ai_walk, 9.3, NULL +}; +mmove_t medic_move_walk = {FRAME_walk1, FRAME_walk12, medic_frames_walk, NULL}; + +void medic_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &medic_move_walk; +} + + +mframe_t medic_frames_run [] = +{ + ai_run, 18, NULL, + ai_run, 22.5, NULL, + ai_run, 25.4, NULL, + ai_run, 23.4, NULL, + ai_run, 24, NULL, + ai_run, 35.6, NULL + +}; +mmove_t medic_move_run = {FRAME_run1, FRAME_run6, medic_frames_run, NULL}; + +void medic_run (edict_t *self) +{ + if (!(self->monsterinfo.aiflags & AI_MEDIC)) + { + edict_t *ent; + + ent = medic_FindDeadMonster(self); + if (ent) + { + self->oldenemy = self->enemy; + self->enemy = ent; + self->enemy->owner = self; + self->monsterinfo.aiflags |= AI_MEDIC; + FoundTarget (self); + return; + } + } + + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &medic_move_stand; + else + self->monsterinfo.currentmove = &medic_move_run; +} + + +mframe_t medic_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t medic_move_pain1 = {FRAME_paina1, FRAME_paina8, medic_frames_pain1, medic_run}; + +mframe_t medic_frames_pain2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t medic_move_pain2 = {FRAME_painb1, FRAME_painb15, medic_frames_pain2, medic_run}; + +void medic_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + + if (skill->value == 3) + return; // no pain anims in nightmare + + if (random() < 0.5) + { + self->monsterinfo.currentmove = &medic_move_pain1; + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + } + else + { + self->monsterinfo.currentmove = &medic_move_pain2; + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + } +} + +void medic_fire_blaster (edict_t *self) +{ + vec3_t start; + vec3_t forward, right; + vec3_t end; + vec3_t dir; + int effect; + + if ((self->s.frame == FRAME_attack9) || (self->s.frame == FRAME_attack12)) + effect = EF_BLASTER; + else if ((self->s.frame == FRAME_attack19) || (self->s.frame == FRAME_attack22) || (self->s.frame == FRAME_attack25) || (self->s.frame == FRAME_attack28)) + effect = EF_HYPERBLASTER; + else + effect = 0; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MEDIC_BLASTER_1], forward, right, start); + + VectorCopy (self->enemy->s.origin, end); + end[2] += self->enemy->viewheight; + VectorSubtract (end, start, dir); + + monster_fire_blaster (self, start, dir, 2, 1000, MZ2_MEDIC_BLASTER_1, effect); +} + + +void medic_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +mframe_t medic_frames_death [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t medic_move_death = {FRAME_death1, FRAME_death30, medic_frames_death, medic_dead}; + +void medic_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + + // if we had a pending patient, free him up for another medic + if ((self->enemy) && (self->enemy->owner == self)) + self->enemy->owner = NULL; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + + self->monsterinfo.currentmove = &medic_move_death; +} + + +void medic_duck_down (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_DUCKED) + return; + self->monsterinfo.aiflags |= AI_DUCKED; + self->maxs[2] -= 32; + self->takedamage = DAMAGE_YES; + self->monsterinfo.pausetime = level.time + 1; + gi.linkentity (self); +} + +void medic_duck_hold (edict_t *self) +{ + if (level.time >= self->monsterinfo.pausetime) + self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; + else + self->monsterinfo.aiflags |= AI_HOLD_FRAME; +} + +void medic_duck_up (edict_t *self) +{ + self->monsterinfo.aiflags &= ~AI_DUCKED; + self->maxs[2] += 32; + self->takedamage = DAMAGE_AIM; + gi.linkentity (self); +} + +mframe_t medic_frames_duck [] = +{ + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, medic_duck_down, + ai_move, -1, medic_duck_hold, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, medic_duck_up, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL +}; +mmove_t medic_move_duck = {FRAME_duck1, FRAME_duck16, medic_frames_duck, medic_run}; + +void medic_dodge (edict_t *self, edict_t *attacker, float eta) +{ + if (random() > 0.25) + return; + + if (!self->enemy) + self->enemy = attacker; + + self->monsterinfo.currentmove = &medic_move_duck; +} + +mframe_t medic_frames_attackHyperBlaster [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, medic_fire_blaster +}; +mmove_t medic_move_attackHyperBlaster = {FRAME_attack15, FRAME_attack30, medic_frames_attackHyperBlaster, medic_run}; + + +void medic_continue (edict_t *self) +{ + if (visible (self, self->enemy) ) + if (random() <= 0.95) + self->monsterinfo.currentmove = &medic_move_attackHyperBlaster; +} + + +mframe_t medic_frames_attackBlaster [] = +{ + ai_charge, 0, NULL, + ai_charge, 5, NULL, + ai_charge, 5, NULL, + ai_charge, 3, NULL, + ai_charge, 2, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, medic_fire_blaster, + ai_charge, 0, NULL, + ai_charge, 0, medic_continue // Change to medic_continue... Else, go to frame 32 +}; +mmove_t medic_move_attackBlaster = {FRAME_attack1, FRAME_attack14, medic_frames_attackBlaster, medic_run}; + + +void medic_hook_launch (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_hook_launch, 1, ATTN_NORM, 0); +} + +void ED_CallSpawn (edict_t *ent); + +static vec3_t medic_cable_offsets[] = +{ + 45.0, -9.2, 15.5, + 48.4, -9.7, 15.2, + 47.8, -9.8, 15.8, + 47.3, -9.3, 14.3, + 45.4, -10.1, 13.1, + 41.9, -12.7, 12.0, + 37.8, -15.8, 11.2, + 34.3, -18.4, 10.7, + 32.7, -19.7, 10.4, + 32.7, -19.7, 10.4 +}; + +void medic_cable_attack (edict_t *self) +{ + vec3_t offset, start, end, f, r; + trace_t tr; + vec3_t dir, angles; + float distance; + + if (!self->enemy->inuse) + return; + + AngleVectors (self->s.angles, f, r, NULL); + VectorCopy (medic_cable_offsets[self->s.frame - FRAME_attack42], offset); + G_ProjectSource (self->s.origin, offset, f, r, start); + + // check for max distance + VectorSubtract (start, self->enemy->s.origin, dir); + distance = VectorLength(dir); + if (distance > 256) + return; + + // check for min/max pitch + vectoangles (dir, angles); + if (angles[0] < -180) + angles[0] += 360; + if (fabs(angles[0]) > 45) + return; + + tr = gi.trace (start, NULL, NULL, self->enemy->s.origin, self, MASK_SHOT); + if (tr.fraction != 1.0 && tr.ent != self->enemy) + return; + + if (self->s.frame == FRAME_attack43) + { + gi.sound (self->enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0); + self->enemy->monsterinfo.aiflags |= AI_RESURRECTING; + } + else if (self->s.frame == FRAME_attack50) + { + self->enemy->spawnflags = 0; + self->enemy->monsterinfo.aiflags = 0; + self->enemy->target = NULL; + self->enemy->targetname = NULL; + self->enemy->combattarget = NULL; + self->enemy->deathtarget = NULL; + self->enemy->owner = self; + ED_CallSpawn (self->enemy); + self->enemy->owner = NULL; + if (self->enemy->think) + { + self->enemy->nextthink = level.time; + self->enemy->think (self->enemy); + } + self->enemy->monsterinfo.aiflags |= AI_RESURRECTING; + if (self->oldenemy && self->oldenemy->client) + { + self->enemy->enemy = self->oldenemy; + FoundTarget (self->enemy); + } + } + else + { + if (self->s.frame == FRAME_attack44) + gi.sound (self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0); + } + + // adjust start for beam origin being in middle of a segment + VectorMA (start, 8, f, start); + + // adjust end z for end spot since the monster is currently dead + VectorCopy (self->enemy->s.origin, end); + end[2] = self->enemy->absmin[2] + self->enemy->size[2] / 2; + + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_MEDIC_CABLE_ATTACK); + gi.WriteShort (self - g_edicts); + gi.WritePosition (start); + gi.WritePosition (end); + gi.multicast (self->s.origin, MULTICAST_PVS); +} + +void medic_hook_retract (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_hook_retract, 1, ATTN_NORM, 0); + self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING; +} + +mframe_t medic_frames_attackCable [] = +{ + ai_move, 2, NULL, + ai_move, 3, NULL, + ai_move, 5, NULL, + ai_move, 4.4, NULL, + ai_charge, 4.7, NULL, + ai_charge, 5, NULL, + ai_charge, 6, NULL, + ai_charge, 4, NULL, + ai_charge, 0, NULL, + ai_move, 0, medic_hook_launch, + ai_move, 0, medic_cable_attack, + ai_move, 0, medic_cable_attack, + ai_move, 0, medic_cable_attack, + ai_move, 0, medic_cable_attack, + ai_move, 0, medic_cable_attack, + ai_move, 0, medic_cable_attack, + ai_move, 0, medic_cable_attack, + ai_move, 0, medic_cable_attack, + ai_move, 0, medic_cable_attack, + ai_move, -15, medic_hook_retract, + ai_move, -1.5, NULL, + ai_move, -1.2, NULL, + ai_move, -3, NULL, + ai_move, -2, NULL, + ai_move, 0.3, NULL, + ai_move, 0.7, NULL, + ai_move, 1.2, NULL, + ai_move, 1.3, NULL +}; +mmove_t medic_move_attackCable = {FRAME_attack33, FRAME_attack60, medic_frames_attackCable, medic_run}; + + +void medic_attack(edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_MEDIC) + self->monsterinfo.currentmove = &medic_move_attackCable; + else + self->monsterinfo.currentmove = &medic_move_attackBlaster; +} + +qboolean medic_checkattack (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_MEDIC) + { + medic_attack(self); + return true; + } + + return M_CheckAttack (self); +} + + +/*QUAKED monster_medic (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_medic (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_idle1 = gi.soundindex ("medic/idle.wav"); + sound_pain1 = gi.soundindex ("medic/medpain1.wav"); + sound_pain2 = gi.soundindex ("medic/medpain2.wav"); + sound_die = gi.soundindex ("medic/meddeth1.wav"); + sound_sight = gi.soundindex ("medic/medsght1.wav"); + sound_search = gi.soundindex ("medic/medsrch1.wav"); + sound_hook_launch = gi.soundindex ("medic/medatck2.wav"); + sound_hook_hit = gi.soundindex ("medic/medatck3.wav"); + sound_hook_heal = gi.soundindex ("medic/medatck4.wav"); + sound_hook_retract = gi.soundindex ("medic/medatck5.wav"); + + gi.soundindex ("medic/medatck1.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/medic/tris.md2"); + VectorSet (self->mins, -24, -24, -24); + VectorSet (self->maxs, 24, 24, 32); + + self->health = 300; + self->gib_health = -130; + self->mass = 400; + + self->pain = medic_pain; + self->die = medic_die; + + self->monsterinfo.stand = medic_stand; + self->monsterinfo.walk = medic_walk; + self->monsterinfo.run = medic_run; + self->monsterinfo.dodge = medic_dodge; + self->monsterinfo.attack = medic_attack; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = medic_sight; + self->monsterinfo.idle = medic_idle; + self->monsterinfo.search = medic_search; + self->monsterinfo.checkattack = medic_checkattack; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &medic_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start (self); +} diff --git a/game/m_medic.h b/game/m_medic.h new file mode 100644 index 000000000..88675c94f --- /dev/null +++ b/game/m_medic.h @@ -0,0 +1,262 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/medic + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_walk1 0 +#define FRAME_walk2 1 +#define FRAME_walk3 2 +#define FRAME_walk4 3 +#define FRAME_walk5 4 +#define FRAME_walk6 5 +#define FRAME_walk7 6 +#define FRAME_walk8 7 +#define FRAME_walk9 8 +#define FRAME_walk10 9 +#define FRAME_walk11 10 +#define FRAME_walk12 11 +#define FRAME_wait1 12 +#define FRAME_wait2 13 +#define FRAME_wait3 14 +#define FRAME_wait4 15 +#define FRAME_wait5 16 +#define FRAME_wait6 17 +#define FRAME_wait7 18 +#define FRAME_wait8 19 +#define FRAME_wait9 20 +#define FRAME_wait10 21 +#define FRAME_wait11 22 +#define FRAME_wait12 23 +#define FRAME_wait13 24 +#define FRAME_wait14 25 +#define FRAME_wait15 26 +#define FRAME_wait16 27 +#define FRAME_wait17 28 +#define FRAME_wait18 29 +#define FRAME_wait19 30 +#define FRAME_wait20 31 +#define FRAME_wait21 32 +#define FRAME_wait22 33 +#define FRAME_wait23 34 +#define FRAME_wait24 35 +#define FRAME_wait25 36 +#define FRAME_wait26 37 +#define FRAME_wait27 38 +#define FRAME_wait28 39 +#define FRAME_wait29 40 +#define FRAME_wait30 41 +#define FRAME_wait31 42 +#define FRAME_wait32 43 +#define FRAME_wait33 44 +#define FRAME_wait34 45 +#define FRAME_wait35 46 +#define FRAME_wait36 47 +#define FRAME_wait37 48 +#define FRAME_wait38 49 +#define FRAME_wait39 50 +#define FRAME_wait40 51 +#define FRAME_wait41 52 +#define FRAME_wait42 53 +#define FRAME_wait43 54 +#define FRAME_wait44 55 +#define FRAME_wait45 56 +#define FRAME_wait46 57 +#define FRAME_wait47 58 +#define FRAME_wait48 59 +#define FRAME_wait49 60 +#define FRAME_wait50 61 +#define FRAME_wait51 62 +#define FRAME_wait52 63 +#define FRAME_wait53 64 +#define FRAME_wait54 65 +#define FRAME_wait55 66 +#define FRAME_wait56 67 +#define FRAME_wait57 68 +#define FRAME_wait58 69 +#define FRAME_wait59 70 +#define FRAME_wait60 71 +#define FRAME_wait61 72 +#define FRAME_wait62 73 +#define FRAME_wait63 74 +#define FRAME_wait64 75 +#define FRAME_wait65 76 +#define FRAME_wait66 77 +#define FRAME_wait67 78 +#define FRAME_wait68 79 +#define FRAME_wait69 80 +#define FRAME_wait70 81 +#define FRAME_wait71 82 +#define FRAME_wait72 83 +#define FRAME_wait73 84 +#define FRAME_wait74 85 +#define FRAME_wait75 86 +#define FRAME_wait76 87 +#define FRAME_wait77 88 +#define FRAME_wait78 89 +#define FRAME_wait79 90 +#define FRAME_wait80 91 +#define FRAME_wait81 92 +#define FRAME_wait82 93 +#define FRAME_wait83 94 +#define FRAME_wait84 95 +#define FRAME_wait85 96 +#define FRAME_wait86 97 +#define FRAME_wait87 98 +#define FRAME_wait88 99 +#define FRAME_wait89 100 +#define FRAME_wait90 101 +#define FRAME_run1 102 +#define FRAME_run2 103 +#define FRAME_run3 104 +#define FRAME_run4 105 +#define FRAME_run5 106 +#define FRAME_run6 107 +#define FRAME_paina1 108 +#define FRAME_paina2 109 +#define FRAME_paina3 110 +#define FRAME_paina4 111 +#define FRAME_paina5 112 +#define FRAME_paina6 113 +#define FRAME_paina7 114 +#define FRAME_paina8 115 +#define FRAME_painb1 116 +#define FRAME_painb2 117 +#define FRAME_painb3 118 +#define FRAME_painb4 119 +#define FRAME_painb5 120 +#define FRAME_painb6 121 +#define FRAME_painb7 122 +#define FRAME_painb8 123 +#define FRAME_painb9 124 +#define FRAME_painb10 125 +#define FRAME_painb11 126 +#define FRAME_painb12 127 +#define FRAME_painb13 128 +#define FRAME_painb14 129 +#define FRAME_painb15 130 +#define FRAME_duck1 131 +#define FRAME_duck2 132 +#define FRAME_duck3 133 +#define FRAME_duck4 134 +#define FRAME_duck5 135 +#define FRAME_duck6 136 +#define FRAME_duck7 137 +#define FRAME_duck8 138 +#define FRAME_duck9 139 +#define FRAME_duck10 140 +#define FRAME_duck11 141 +#define FRAME_duck12 142 +#define FRAME_duck13 143 +#define FRAME_duck14 144 +#define FRAME_duck15 145 +#define FRAME_duck16 146 +#define FRAME_death1 147 +#define FRAME_death2 148 +#define FRAME_death3 149 +#define FRAME_death4 150 +#define FRAME_death5 151 +#define FRAME_death6 152 +#define FRAME_death7 153 +#define FRAME_death8 154 +#define FRAME_death9 155 +#define FRAME_death10 156 +#define FRAME_death11 157 +#define FRAME_death12 158 +#define FRAME_death13 159 +#define FRAME_death14 160 +#define FRAME_death15 161 +#define FRAME_death16 162 +#define FRAME_death17 163 +#define FRAME_death18 164 +#define FRAME_death19 165 +#define FRAME_death20 166 +#define FRAME_death21 167 +#define FRAME_death22 168 +#define FRAME_death23 169 +#define FRAME_death24 170 +#define FRAME_death25 171 +#define FRAME_death26 172 +#define FRAME_death27 173 +#define FRAME_death28 174 +#define FRAME_death29 175 +#define FRAME_death30 176 +#define FRAME_attack1 177 +#define FRAME_attack2 178 +#define FRAME_attack3 179 +#define FRAME_attack4 180 +#define FRAME_attack5 181 +#define FRAME_attack6 182 +#define FRAME_attack7 183 +#define FRAME_attack8 184 +#define FRAME_attack9 185 +#define FRAME_attack10 186 +#define FRAME_attack11 187 +#define FRAME_attack12 188 +#define FRAME_attack13 189 +#define FRAME_attack14 190 +#define FRAME_attack15 191 +#define FRAME_attack16 192 +#define FRAME_attack17 193 +#define FRAME_attack18 194 +#define FRAME_attack19 195 +#define FRAME_attack20 196 +#define FRAME_attack21 197 +#define FRAME_attack22 198 +#define FRAME_attack23 199 +#define FRAME_attack24 200 +#define FRAME_attack25 201 +#define FRAME_attack26 202 +#define FRAME_attack27 203 +#define FRAME_attack28 204 +#define FRAME_attack29 205 +#define FRAME_attack30 206 +#define FRAME_attack31 207 +#define FRAME_attack32 208 +#define FRAME_attack33 209 +#define FRAME_attack34 210 +#define FRAME_attack35 211 +#define FRAME_attack36 212 +#define FRAME_attack37 213 +#define FRAME_attack38 214 +#define FRAME_attack39 215 +#define FRAME_attack40 216 +#define FRAME_attack41 217 +#define FRAME_attack42 218 +#define FRAME_attack43 219 +#define FRAME_attack44 220 +#define FRAME_attack45 221 +#define FRAME_attack46 222 +#define FRAME_attack47 223 +#define FRAME_attack48 224 +#define FRAME_attack49 225 +#define FRAME_attack50 226 +#define FRAME_attack51 227 +#define FRAME_attack52 228 +#define FRAME_attack53 229 +#define FRAME_attack54 230 +#define FRAME_attack55 231 +#define FRAME_attack56 232 +#define FRAME_attack57 233 +#define FRAME_attack58 234 +#define FRAME_attack59 235 +#define FRAME_attack60 236 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_move.c b/game/m_move.c new file mode 100644 index 000000000..229cfcd7e --- /dev/null +++ b/game/m_move.c @@ -0,0 +1,556 @@ +/* +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. + +*/ +// m_move.c -- monster movement + +#include "g_local.h" + +#define STEPSIZE 18 + +/* +============= +M_CheckBottom + +Returns false if any part of the bottom of the entity is off an edge that +is not a staircase. + +============= +*/ +int c_yes, c_no; + +qboolean M_CheckBottom (edict_t *ent) +{ + vec3_t mins, maxs, start, stop; + trace_t trace; + int x, y; + float mid, bottom; + + VectorAdd (ent->s.origin, ent->mins, mins); + VectorAdd (ent->s.origin, ent->maxs, maxs); + +// if all of the points under the corners are solid world, don't bother +// with the tougher checks +// the corners must be within 16 of the midpoint + start[2] = mins[2] - 1; + for (x=0 ; x<=1 ; x++) + for (y=0 ; y<=1 ; y++) + { + start[0] = x ? maxs[0] : mins[0]; + start[1] = y ? maxs[1] : mins[1]; + if (gi.pointcontents (start) != CONTENTS_SOLID) + goto realcheck; + } + + c_yes++; + return true; // we got out easy + +realcheck: + c_no++; +// +// check it for real... +// + start[2] = mins[2]; + +// the midpoint must be within 16 of the bottom + start[0] = stop[0] = (mins[0] + maxs[0])*0.5; + start[1] = stop[1] = (mins[1] + maxs[1])*0.5; + stop[2] = start[2] - 2*STEPSIZE; + trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); + + if (trace.fraction == 1.0) + return false; + mid = bottom = trace.endpos[2]; + +// the corners must be within 16 of the midpoint + for (x=0 ; x<=1 ; x++) + for (y=0 ; y<=1 ; y++) + { + start[0] = stop[0] = x ? maxs[0] : mins[0]; + start[1] = stop[1] = y ? maxs[1] : mins[1]; + + trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); + + if (trace.fraction != 1.0 && trace.endpos[2] > bottom) + bottom = trace.endpos[2]; + if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE) + return false; + } + + c_yes++; + return true; +} + + +/* +============= +SV_movestep + +Called by monster program code. +The move will be adjusted for slopes and stairs, but if the move isn't +possible, no move is done, false is returned, and +pr_global_struct->trace_normal is set to the normal of the blocking wall +============= +*/ +//FIXME since we need to test end position contents here, can we avoid doing +//it again later in catagorize position? +qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink) +{ + float dz; + vec3_t oldorg, neworg, end; + trace_t trace; + int i; + float stepsize; + vec3_t test; + int contents; + +// try the move + VectorCopy (ent->s.origin, oldorg); + VectorAdd (ent->s.origin, move, neworg); + +// flying monsters don't step up + if ( ent->flags & (FL_SWIM | FL_FLY) ) + { + // try one move with vertical motion, then one without + for (i=0 ; i<2 ; i++) + { + VectorAdd (ent->s.origin, move, neworg); + if (i == 0 && ent->enemy) + { + if (!ent->goalentity) + ent->goalentity = ent->enemy; + dz = ent->s.origin[2] - ent->goalentity->s.origin[2]; + if (ent->goalentity->client) + { + if (dz > 40) + neworg[2] -= 8; + if (!((ent->flags & FL_SWIM) && (ent->waterlevel < 2))) + if (dz < 30) + neworg[2] += 8; + } + else + { + if (dz > 8) + neworg[2] -= 8; + else if (dz > 0) + neworg[2] -= dz; + else if (dz < -8) + neworg[2] += 8; + else + neworg[2] += dz; + } + } + trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, neworg, ent, MASK_MONSTERSOLID); + + // fly monsters don't enter water voluntarily + if (ent->flags & FL_FLY) + { + if (!ent->waterlevel) + { + test[0] = trace.endpos[0]; + test[1] = trace.endpos[1]; + test[2] = trace.endpos[2] + ent->mins[2] + 1; + contents = gi.pointcontents(test); + if (contents & MASK_WATER) + return false; + } + } + + // swim monsters don't exit water voluntarily + if (ent->flags & FL_SWIM) + { + if (ent->waterlevel < 2) + { + test[0] = trace.endpos[0]; + test[1] = trace.endpos[1]; + test[2] = trace.endpos[2] + ent->mins[2] + 1; + contents = gi.pointcontents(test); + if (!(contents & MASK_WATER)) + return false; + } + } + + if (trace.fraction == 1) + { + VectorCopy (trace.endpos, ent->s.origin); + if (relink) + { + gi.linkentity (ent); + G_TouchTriggers (ent); + } + return true; + } + + if (!ent->enemy) + break; + } + + return false; + } + +// push down from a step height above the wished position + if (!(ent->monsterinfo.aiflags & AI_NOSTEP)) + stepsize = STEPSIZE; + else + stepsize = 1; + + neworg[2] += stepsize; + VectorCopy (neworg, end); + end[2] -= stepsize*2; + + trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); + + if (trace.allsolid) + return false; + + if (trace.startsolid) + { + neworg[2] -= stepsize; + trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID); + if (trace.allsolid || trace.startsolid) + return false; + } + + + // don't go in to water + if (ent->waterlevel == 0) + { + test[0] = trace.endpos[0]; + test[1] = trace.endpos[1]; + test[2] = trace.endpos[2] + ent->mins[2] + 1; + contents = gi.pointcontents(test); + + if (contents & MASK_WATER) + return false; + } + + if (trace.fraction == 1) + { + // if monster had the ground pulled out, go ahead and fall + if ( ent->flags & FL_PARTIALGROUND ) + { + VectorAdd (ent->s.origin, move, ent->s.origin); + if (relink) + { + gi.linkentity (ent); + G_TouchTriggers (ent); + } + ent->groundentity = NULL; + return true; + } + + return false; // walked off an edge + } + +// check point traces down for dangling corners + VectorCopy (trace.endpos, ent->s.origin); + + if (!M_CheckBottom (ent)) + { + if ( ent->flags & FL_PARTIALGROUND ) + { // entity had floor mostly pulled out from underneath it + // and is trying to correct + if (relink) + { + gi.linkentity (ent); + G_TouchTriggers (ent); + } + return true; + } + VectorCopy (oldorg, ent->s.origin); + return false; + } + + if ( ent->flags & FL_PARTIALGROUND ) + { + ent->flags &= ~FL_PARTIALGROUND; + } + ent->groundentity = trace.ent; + ent->groundentity_linkcount = trace.ent->linkcount; + +// the move is ok + if (relink) + { + gi.linkentity (ent); + G_TouchTriggers (ent); + } + return true; +} + + +//============================================================================ + +/* +=============== +M_ChangeYaw + +=============== +*/ +void M_ChangeYaw (edict_t *ent) +{ + float ideal; + float current; + float move; + float speed; + + current = anglemod(ent->s.angles[YAW]); + ideal = ent->ideal_yaw; + + if (current == ideal) + return; + + move = ideal - current; + speed = ent->yaw_speed; + if (ideal > current) + { + if (move >= 180) + move = move - 360; + } + else + { + if (move <= -180) + move = move + 360; + } + if (move > 0) + { + if (move > speed) + move = speed; + } + else + { + if (move < -speed) + move = -speed; + } + + ent->s.angles[YAW] = anglemod (current + move); +} + + +/* +====================== +SV_StepDirection + +Turns to the movement direction, and walks the current distance if +facing it. + +====================== +*/ +qboolean SV_StepDirection (edict_t *ent, float yaw, float dist) +{ + vec3_t move, oldorigin; + float delta; + + ent->ideal_yaw = yaw; + M_ChangeYaw (ent); + + yaw = yaw*M_PI*2 / 360; + move[0] = cos(yaw)*dist; + move[1] = sin(yaw)*dist; + move[2] = 0; + + VectorCopy (ent->s.origin, oldorigin); + if (SV_movestep (ent, move, false)) + { + delta = ent->s.angles[YAW] - ent->ideal_yaw; + if (delta > 45 && delta < 315) + { // not turned far enough, so don't take the step + VectorCopy (oldorigin, ent->s.origin); + } + gi.linkentity (ent); + G_TouchTriggers (ent); + return true; + } + gi.linkentity (ent); + G_TouchTriggers (ent); + return false; +} + +/* +====================== +SV_FixCheckBottom + +====================== +*/ +void SV_FixCheckBottom (edict_t *ent) +{ + ent->flags |= FL_PARTIALGROUND; +} + + + +/* +================ +SV_NewChaseDir + +================ +*/ +#define DI_NODIR -1 +void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) +{ + float deltax,deltay; + float d[3]; + float tdir, olddir, turnaround; + + //FIXME: how did we get here with no enemy + if (!enemy) + return; + + olddir = anglemod( (int)(actor->ideal_yaw/45)*45 ); + turnaround = anglemod(olddir - 180); + + deltax = enemy->s.origin[0] - actor->s.origin[0]; + deltay = enemy->s.origin[1] - actor->s.origin[1]; + if (deltax>10) + d[1]= 0; + else if (deltax<-10) + d[1]= 180; + else + d[1]= DI_NODIR; + if (deltay<-10) + d[2]= 270; + else if (deltay>10) + d[2]= 90; + else + d[2]= DI_NODIR; + +// try direct route + if (d[1] != DI_NODIR && d[2] != DI_NODIR) + { + if (d[1] == 0) + tdir = d[2] == 90 ? 45 : 315; + else + tdir = d[2] == 90 ? 135 : 215; + + if (tdir != turnaround && SV_StepDirection(actor, tdir, dist)) + return; + } + +// try other directions + if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax)) + { + tdir=d[1]; + d[1]=d[2]; + d[2]=tdir; + } + + if (d[1]!=DI_NODIR && d[1]!=turnaround + && SV_StepDirection(actor, d[1], dist)) + return; + + if (d[2]!=DI_NODIR && d[2]!=turnaround + && SV_StepDirection(actor, d[2], dist)) + return; + +/* there is no direct path to the player, so pick another direction */ + + if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist)) + return; + + if (rand()&1) /*randomly determine direction of search*/ + { + for (tdir=0 ; tdir<=315 ; tdir += 45) + if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) + return; + } + else + { + for (tdir=315 ; tdir >=0 ; tdir -= 45) + if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) + return; + } + + if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) ) + return; + + actor->ideal_yaw = olddir; // can't move + +// if a bridge was pulled out from underneath a monster, it may not have +// a valid standing position at all + + if (!M_CheckBottom (actor)) + SV_FixCheckBottom (actor); +} + +/* +====================== +SV_CloseEnough + +====================== +*/ +qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist) +{ + int i; + + for (i=0 ; i<3 ; i++) + { + if (goal->absmin[i] > ent->absmax[i] + dist) + return false; + if (goal->absmax[i] < ent->absmin[i] - dist) + return false; + } + return true; +} + + +/* +====================== +M_MoveToGoal +====================== +*/ +void M_MoveToGoal (edict_t *ent, float dist) +{ + edict_t *goal; + + goal = ent->goalentity; + + if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM))) + return; + +// if the next step hits the enemy, return immediately + if (ent->enemy && SV_CloseEnough (ent, ent->enemy, dist) ) + return; + +// bump around... + if ( (rand()&3)==1 || !SV_StepDirection (ent, ent->ideal_yaw, dist)) + { + if (ent->inuse) + SV_NewChaseDir (ent, goal, dist); + } +} + + +/* +=============== +M_walkmove +=============== +*/ +qboolean M_walkmove (edict_t *ent, float yaw, float dist) +{ + vec3_t move; + + if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM))) + return false; + + yaw = yaw*M_PI*2 / 360; + + move[0] = cos(yaw)*dist; + move[1] = sin(yaw)*dist; + move[2] = 0; + + return SV_movestep(ent, move, true); +} diff --git a/game/m_mutant.c b/game/m_mutant.c new file mode 100644 index 000000000..f61acbf29 --- /dev/null +++ b/game/m_mutant.c @@ -0,0 +1,663 @@ +/* +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. + +*/ +/* +============================================================================== + +mutant + +============================================================================== +*/ + +#include "g_local.h" +#include "m_mutant.h" + + +static int sound_swing; +static int sound_hit; +static int sound_hit2; +static int sound_death; +static int sound_idle; +static int sound_pain1; +static int sound_pain2; +static int sound_sight; +static int sound_search; +static int sound_step1; +static int sound_step2; +static int sound_step3; +static int sound_thud; + +// +// SOUNDS +// + +void mutant_step (edict_t *self) +{ + int n; + n = (rand() + 1) % 3; + if (n == 0) + gi.sound (self, CHAN_VOICE, sound_step1, 1, ATTN_NORM, 0); + else if (n == 1) + gi.sound (self, CHAN_VOICE, sound_step2, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_step3, 1, ATTN_NORM, 0); +} + +void mutant_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + +void mutant_search (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); +} + +void mutant_swing (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_swing, 1, ATTN_NORM, 0); +} + + +// +// STAND +// + +mframe_t mutant_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 10 + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 20 + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 30 + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 40 + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 50 + + ai_stand, 0, NULL +}; +mmove_t mutant_move_stand = {FRAME_stand101, FRAME_stand151, mutant_frames_stand, NULL}; + +void mutant_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &mutant_move_stand; +} + + +// +// IDLE +// + +void mutant_idle_loop (edict_t *self) +{ + if (random() < 0.75) + self->monsterinfo.nextframe = FRAME_stand155; +} + +mframe_t mutant_frames_idle [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // scratch loop start + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, mutant_idle_loop, // scratch loop end + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t mutant_move_idle = {FRAME_stand152, FRAME_stand164, mutant_frames_idle, mutant_stand}; + +void mutant_idle (edict_t *self) +{ + self->monsterinfo.currentmove = &mutant_move_idle; + gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); +} + + +// +// WALK +// + +void mutant_walk (edict_t *self); + +mframe_t mutant_frames_walk [] = +{ + ai_walk, 3, NULL, + ai_walk, 1, NULL, + ai_walk, 5, NULL, + ai_walk, 10, NULL, + ai_walk, 13, NULL, + ai_walk, 10, NULL, + ai_walk, 0, NULL, + ai_walk, 5, NULL, + ai_walk, 6, NULL, + ai_walk, 16, NULL, + ai_walk, 15, NULL, + ai_walk, 6, NULL +}; +mmove_t mutant_move_walk = {FRAME_walk05, FRAME_walk16, mutant_frames_walk, NULL}; + +void mutant_walk_loop (edict_t *self) +{ + self->monsterinfo.currentmove = &mutant_move_walk; +} + +mframe_t mutant_frames_start_walk [] = +{ + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, -2, NULL, + ai_walk, 1, NULL +}; +mmove_t mutant_move_start_walk = {FRAME_walk01, FRAME_walk04, mutant_frames_start_walk, mutant_walk_loop}; + +void mutant_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &mutant_move_start_walk; +} + + +// +// RUN +// + +mframe_t mutant_frames_run [] = +{ + ai_run, 40, NULL, + ai_run, 40, mutant_step, + ai_run, 24, NULL, + ai_run, 5, mutant_step, + ai_run, 17, NULL, + ai_run, 10, NULL +}; +mmove_t mutant_move_run = {FRAME_run03, FRAME_run08, mutant_frames_run, NULL}; + +void mutant_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &mutant_move_stand; + else + self->monsterinfo.currentmove = &mutant_move_run; +} + + +// +// MELEE +// + +void mutant_hit_left (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8); + if (fire_hit (self, aim, (10 + (rand() %5)), 100)) + gi.sound (self, CHAN_WEAPON, sound_hit, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0); +} + +void mutant_hit_right (edict_t *self) +{ + vec3_t aim; + + VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 8); + if (fire_hit (self, aim, (10 + (rand() %5)), 100)) + gi.sound (self, CHAN_WEAPON, sound_hit2, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0); +} + +void mutant_check_refire (edict_t *self) +{ + if (!self->enemy || !self->enemy->inuse || self->enemy->health <= 0) + return; + + if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) + self->monsterinfo.nextframe = FRAME_attack09; +} + +mframe_t mutant_frames_attack [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, mutant_hit_left, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, mutant_hit_right, + ai_charge, 0, mutant_check_refire +}; +mmove_t mutant_move_attack = {FRAME_attack09, FRAME_attack15, mutant_frames_attack, mutant_run}; + +void mutant_melee (edict_t *self) +{ + self->monsterinfo.currentmove = &mutant_move_attack; +} + + +// +// ATTACK +// + +void mutant_jump_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + if (self->health <= 0) + { + self->touch = NULL; + return; + } + + if (other->takedamage) + { + if (VectorLength(self->velocity) > 400) + { + vec3_t point; + vec3_t normal; + int damage; + + VectorCopy (self->velocity, normal); + VectorNormalize(normal); + VectorMA (self->s.origin, self->maxs[0], normal, point); + damage = 40 + 10 * random(); + T_Damage (other, self, self, self->velocity, point, normal, damage, damage, 0, MOD_UNKNOWN); + } + } + + if (!M_CheckBottom (self)) + { + if (self->groundentity) + { + self->monsterinfo.nextframe = FRAME_attack02; + self->touch = NULL; + } + return; + } + + self->touch = NULL; +} + +void mutant_jump_takeoff (edict_t *self) +{ + vec3_t forward; + + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); + AngleVectors (self->s.angles, forward, NULL, NULL); + self->s.origin[2] += 1; + VectorScale (forward, 600, self->velocity); + self->velocity[2] = 250; + self->groundentity = NULL; + self->monsterinfo.aiflags |= AI_DUCKED; + self->monsterinfo.attack_finished = level.time + 3; + self->touch = mutant_jump_touch; +} + +void mutant_check_landing (edict_t *self) +{ + if (self->groundentity) + { + gi.sound (self, CHAN_WEAPON, sound_thud, 1, ATTN_NORM, 0); + self->monsterinfo.attack_finished = 0; + self->monsterinfo.aiflags &= ~AI_DUCKED; + return; + } + + if (level.time > self->monsterinfo.attack_finished) + self->monsterinfo.nextframe = FRAME_attack02; + else + self->monsterinfo.nextframe = FRAME_attack05; +} + +mframe_t mutant_frames_jump [] = +{ + ai_charge, 0, NULL, + ai_charge, 17, NULL, + ai_charge, 15, mutant_jump_takeoff, + ai_charge, 15, NULL, + ai_charge, 15, mutant_check_landing, + ai_charge, 0, NULL, + ai_charge, 3, NULL, + ai_charge, 0, NULL +}; +mmove_t mutant_move_jump = {FRAME_attack01, FRAME_attack08, mutant_frames_jump, mutant_run}; + +void mutant_jump (edict_t *self) +{ + self->monsterinfo.currentmove = &mutant_move_jump; +} + + +// +// CHECKATTACK +// + +qboolean mutant_check_melee (edict_t *self) +{ + if (range (self, self->enemy) == RANGE_MELEE) + return true; + return false; +} + +qboolean mutant_check_jump (edict_t *self) +{ + vec3_t v; + float distance; + + if (self->absmin[2] > (self->enemy->absmin[2] + 0.75 * self->enemy->size[2])) + return false; + + if (self->absmax[2] < (self->enemy->absmin[2] + 0.25 * self->enemy->size[2])) + return false; + + v[0] = self->s.origin[0] - self->enemy->s.origin[0]; + v[1] = self->s.origin[1] - self->enemy->s.origin[1]; + v[2] = 0; + distance = VectorLength(v); + + if (distance < 100) + return false; + if (distance > 100) + { + if (random() < 0.9) + return false; + } + + return true; +} + +qboolean mutant_checkattack (edict_t *self) +{ + if (!self->enemy || self->enemy->health <= 0) + return false; + + if (mutant_check_melee(self)) + { + self->monsterinfo.attack_state = AS_MELEE; + return true; + } + + if (mutant_check_jump(self)) + { + self->monsterinfo.attack_state = AS_MISSILE; + // FIXME play a jump sound here + return true; + } + + return false; +} + + +// +// PAIN +// + +mframe_t mutant_frames_pain1 [] = +{ + ai_move, 4, NULL, + ai_move, -3, NULL, + ai_move, -8, NULL, + ai_move, 2, NULL, + ai_move, 5, NULL +}; +mmove_t mutant_move_pain1 = {FRAME_pain101, FRAME_pain105, mutant_frames_pain1, mutant_run}; + +mframe_t mutant_frames_pain2 [] = +{ + ai_move, -24,NULL, + ai_move, 11, NULL, + ai_move, 5, NULL, + ai_move, -2, NULL, + ai_move, 6, NULL, + ai_move, 4, NULL +}; +mmove_t mutant_move_pain2 = {FRAME_pain201, FRAME_pain206, mutant_frames_pain2, mutant_run}; + +mframe_t mutant_frames_pain3 [] = +{ + ai_move, -22,NULL, + ai_move, 3, NULL, + ai_move, 3, NULL, + ai_move, 2, NULL, + ai_move, 1, NULL, + ai_move, 1, NULL, + ai_move, 6, NULL, + ai_move, 3, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL, + ai_move, 1, NULL +}; +mmove_t mutant_move_pain3 = {FRAME_pain301, FRAME_pain311, mutant_frames_pain3, mutant_run}; + +void mutant_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + float r; + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + + if (skill->value == 3) + return; // no pain anims in nightmare + + r = random(); + if (r < 0.33) + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &mutant_move_pain1; + } + else if (r < 0.66) + { + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &mutant_move_pain2; + } + else + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &mutant_move_pain3; + } +} + + +// +// DEATH +// + +void mutant_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + gi.linkentity (self); + + M_FlyCheck (self); +} + +mframe_t mutant_frames_death1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t mutant_move_death1 = {FRAME_death101, FRAME_death109, mutant_frames_death1, mutant_dead}; + +mframe_t mutant_frames_death2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t mutant_move_death2 = {FRAME_death201, FRAME_death210, mutant_frames_death2, mutant_dead}; + +void mutant_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + + gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + self->s.skinnum = 1; + + if (random() < 0.5) + self->monsterinfo.currentmove = &mutant_move_death1; + else + self->monsterinfo.currentmove = &mutant_move_death2; +} + + +// +// SPAWN +// + +/*QUAKED monster_mutant (1 .5 0) (-32 -32 -24) (32 32 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_mutant (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_swing = gi.soundindex ("mutant/mutatck1.wav"); + sound_hit = gi.soundindex ("mutant/mutatck2.wav"); + sound_hit2 = gi.soundindex ("mutant/mutatck3.wav"); + sound_death = gi.soundindex ("mutant/mutdeth1.wav"); + sound_idle = gi.soundindex ("mutant/mutidle1.wav"); + sound_pain1 = gi.soundindex ("mutant/mutpain1.wav"); + sound_pain2 = gi.soundindex ("mutant/mutpain2.wav"); + sound_sight = gi.soundindex ("mutant/mutsght1.wav"); + sound_search = gi.soundindex ("mutant/mutsrch1.wav"); + sound_step1 = gi.soundindex ("mutant/step1.wav"); + sound_step2 = gi.soundindex ("mutant/step2.wav"); + sound_step3 = gi.soundindex ("mutant/step3.wav"); + sound_thud = gi.soundindex ("mutant/thud1.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/mutant/tris.md2"); + VectorSet (self->mins, -32, -32, -24); + VectorSet (self->maxs, 32, 32, 48); + + self->health = 300; + self->gib_health = -120; + self->mass = 300; + + self->pain = mutant_pain; + self->die = mutant_die; + + self->monsterinfo.stand = mutant_stand; + self->monsterinfo.walk = mutant_walk; + self->monsterinfo.run = mutant_run; + self->monsterinfo.dodge = NULL; + self->monsterinfo.attack = mutant_jump; + self->monsterinfo.melee = mutant_melee; + self->monsterinfo.sight = mutant_sight; + self->monsterinfo.search = mutant_search; + self->monsterinfo.idle = mutant_idle; + self->monsterinfo.checkattack = mutant_checkattack; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &mutant_move_stand; + + self->monsterinfo.scale = MODEL_SCALE; + walkmonster_start (self); +} diff --git a/game/m_mutant.h b/game/m_mutant.h new file mode 100644 index 000000000..8c6f3fed0 --- /dev/null +++ b/game/m_mutant.h @@ -0,0 +1,174 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/mutant + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_attack01 0 +#define FRAME_attack02 1 +#define FRAME_attack03 2 +#define FRAME_attack04 3 +#define FRAME_attack05 4 +#define FRAME_attack06 5 +#define FRAME_attack07 6 +#define FRAME_attack08 7 +#define FRAME_attack09 8 +#define FRAME_attack10 9 +#define FRAME_attack11 10 +#define FRAME_attack12 11 +#define FRAME_attack13 12 +#define FRAME_attack14 13 +#define FRAME_attack15 14 +#define FRAME_death101 15 +#define FRAME_death102 16 +#define FRAME_death103 17 +#define FRAME_death104 18 +#define FRAME_death105 19 +#define FRAME_death106 20 +#define FRAME_death107 21 +#define FRAME_death108 22 +#define FRAME_death109 23 +#define FRAME_death201 24 +#define FRAME_death202 25 +#define FRAME_death203 26 +#define FRAME_death204 27 +#define FRAME_death205 28 +#define FRAME_death206 29 +#define FRAME_death207 30 +#define FRAME_death208 31 +#define FRAME_death209 32 +#define FRAME_death210 33 +#define FRAME_pain101 34 +#define FRAME_pain102 35 +#define FRAME_pain103 36 +#define FRAME_pain104 37 +#define FRAME_pain105 38 +#define FRAME_pain201 39 +#define FRAME_pain202 40 +#define FRAME_pain203 41 +#define FRAME_pain204 42 +#define FRAME_pain205 43 +#define FRAME_pain206 44 +#define FRAME_pain301 45 +#define FRAME_pain302 46 +#define FRAME_pain303 47 +#define FRAME_pain304 48 +#define FRAME_pain305 49 +#define FRAME_pain306 50 +#define FRAME_pain307 51 +#define FRAME_pain308 52 +#define FRAME_pain309 53 +#define FRAME_pain310 54 +#define FRAME_pain311 55 +#define FRAME_run03 56 +#define FRAME_run04 57 +#define FRAME_run05 58 +#define FRAME_run06 59 +#define FRAME_run07 60 +#define FRAME_run08 61 +#define FRAME_stand101 62 +#define FRAME_stand102 63 +#define FRAME_stand103 64 +#define FRAME_stand104 65 +#define FRAME_stand105 66 +#define FRAME_stand106 67 +#define FRAME_stand107 68 +#define FRAME_stand108 69 +#define FRAME_stand109 70 +#define FRAME_stand110 71 +#define FRAME_stand111 72 +#define FRAME_stand112 73 +#define FRAME_stand113 74 +#define FRAME_stand114 75 +#define FRAME_stand115 76 +#define FRAME_stand116 77 +#define FRAME_stand117 78 +#define FRAME_stand118 79 +#define FRAME_stand119 80 +#define FRAME_stand120 81 +#define FRAME_stand121 82 +#define FRAME_stand122 83 +#define FRAME_stand123 84 +#define FRAME_stand124 85 +#define FRAME_stand125 86 +#define FRAME_stand126 87 +#define FRAME_stand127 88 +#define FRAME_stand128 89 +#define FRAME_stand129 90 +#define FRAME_stand130 91 +#define FRAME_stand131 92 +#define FRAME_stand132 93 +#define FRAME_stand133 94 +#define FRAME_stand134 95 +#define FRAME_stand135 96 +#define FRAME_stand136 97 +#define FRAME_stand137 98 +#define FRAME_stand138 99 +#define FRAME_stand139 100 +#define FRAME_stand140 101 +#define FRAME_stand141 102 +#define FRAME_stand142 103 +#define FRAME_stand143 104 +#define FRAME_stand144 105 +#define FRAME_stand145 106 +#define FRAME_stand146 107 +#define FRAME_stand147 108 +#define FRAME_stand148 109 +#define FRAME_stand149 110 +#define FRAME_stand150 111 +#define FRAME_stand151 112 +#define FRAME_stand152 113 +#define FRAME_stand153 114 +#define FRAME_stand154 115 +#define FRAME_stand155 116 +#define FRAME_stand156 117 +#define FRAME_stand157 118 +#define FRAME_stand158 119 +#define FRAME_stand159 120 +#define FRAME_stand160 121 +#define FRAME_stand161 122 +#define FRAME_stand162 123 +#define FRAME_stand163 124 +#define FRAME_stand164 125 +#define FRAME_walk01 126 +#define FRAME_walk02 127 +#define FRAME_walk03 128 +#define FRAME_walk04 129 +#define FRAME_walk05 130 +#define FRAME_walk06 131 +#define FRAME_walk07 132 +#define FRAME_walk08 133 +#define FRAME_walk09 134 +#define FRAME_walk10 135 +#define FRAME_walk11 136 +#define FRAME_walk12 137 +#define FRAME_walk13 138 +#define FRAME_walk14 139 +#define FRAME_walk15 140 +#define FRAME_walk16 141 +#define FRAME_walk17 142 +#define FRAME_walk18 143 +#define FRAME_walk19 144 +#define FRAME_walk20 145 +#define FRAME_walk21 146 +#define FRAME_walk22 147 +#define FRAME_walk23 148 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_parasite.c b/game/m_parasite.c new file mode 100644 index 000000000..347875078 --- /dev/null +++ b/game/m_parasite.c @@ -0,0 +1,552 @@ +/* +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. + +*/ +/* +============================================================================== + +parasite + +============================================================================== +*/ + +#include "g_local.h" +#include "m_parasite.h" + + +static int sound_pain1; +static int sound_pain2; +static int sound_die; +static int sound_launch; +static int sound_impact; +static int sound_suck; +static int sound_reelin; +static int sound_sight; +static int sound_tap; +static int sound_scratch; +static int sound_search; + + +void parasite_stand (edict_t *self); +void parasite_start_run (edict_t *self); +void parasite_run (edict_t *self); +void parasite_walk (edict_t *self); +void parasite_start_walk (edict_t *self); +void parasite_end_fidget (edict_t *self); +void parasite_do_fidget (edict_t *self); +void parasite_refidget (edict_t *self); + + +void parasite_launch (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_launch, 1, ATTN_NORM, 0); +} + +void parasite_reel_in (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_reelin, 1, ATTN_NORM, 0); +} + +void parasite_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_WEAPON, sound_sight, 1, ATTN_NORM, 0); +} + +void parasite_tap (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_tap, 1, ATTN_IDLE, 0); +} + +void parasite_scratch (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_scratch, 1, ATTN_IDLE, 0); +} + +void parasite_search (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_search, 1, ATTN_IDLE, 0); +} + + +mframe_t parasite_frames_start_fidget [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t parasite_move_start_fidget = {FRAME_stand18, FRAME_stand21, parasite_frames_start_fidget, parasite_do_fidget}; + +mframe_t parasite_frames_fidget [] = +{ + ai_stand, 0, parasite_scratch, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, parasite_scratch, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t parasite_move_fidget = {FRAME_stand22, FRAME_stand27, parasite_frames_fidget, parasite_refidget}; + +mframe_t parasite_frames_end_fidget [] = +{ + ai_stand, 0, parasite_scratch, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t parasite_move_end_fidget = {FRAME_stand28, FRAME_stand35, parasite_frames_end_fidget, parasite_stand}; + +void parasite_end_fidget (edict_t *self) +{ + self->monsterinfo.currentmove = ¶site_move_end_fidget; +} + +void parasite_do_fidget (edict_t *self) +{ + self->monsterinfo.currentmove = ¶site_move_fidget; +} + +void parasite_refidget (edict_t *self) +{ + if (random() <= 0.8) + self->monsterinfo.currentmove = ¶site_move_fidget; + else + self->monsterinfo.currentmove = ¶site_move_end_fidget; +} + +void parasite_idle (edict_t *self) +{ + self->monsterinfo.currentmove = ¶site_move_start_fidget; +} + + +mframe_t parasite_frames_stand [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, parasite_tap, + ai_stand, 0, NULL, + ai_stand, 0, parasite_tap, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, parasite_tap, + ai_stand, 0, NULL, + ai_stand, 0, parasite_tap, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, parasite_tap, + ai_stand, 0, NULL, + ai_stand, 0, parasite_tap +}; +mmove_t parasite_move_stand = {FRAME_stand01, FRAME_stand17, parasite_frames_stand, parasite_stand}; + +void parasite_stand (edict_t *self) +{ + self->monsterinfo.currentmove = ¶site_move_stand; +} + + +mframe_t parasite_frames_run [] = +{ + ai_run, 30, NULL, + ai_run, 30, NULL, + ai_run, 22, NULL, + ai_run, 19, NULL, + ai_run, 24, NULL, + ai_run, 28, NULL, + ai_run, 25, NULL +}; +mmove_t parasite_move_run = {FRAME_run03, FRAME_run09, parasite_frames_run, NULL}; + +mframe_t parasite_frames_start_run [] = +{ + ai_run, 0, NULL, + ai_run, 30, NULL, +}; +mmove_t parasite_move_start_run = {FRAME_run01, FRAME_run02, parasite_frames_start_run, parasite_run}; + +mframe_t parasite_frames_stop_run [] = +{ + ai_run, 20, NULL, + ai_run, 20, NULL, + ai_run, 12, NULL, + ai_run, 10, NULL, + ai_run, 0, NULL, + ai_run, 0, NULL +}; +mmove_t parasite_move_stop_run = {FRAME_run10, FRAME_run15, parasite_frames_stop_run, NULL}; + +void parasite_start_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = ¶site_move_stand; + else + self->monsterinfo.currentmove = ¶site_move_start_run; +} + +void parasite_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = ¶site_move_stand; + else + self->monsterinfo.currentmove = ¶site_move_run; +} + + +mframe_t parasite_frames_walk [] = +{ + ai_walk, 30, NULL, + ai_walk, 30, NULL, + ai_walk, 22, NULL, + ai_walk, 19, NULL, + ai_walk, 24, NULL, + ai_walk, 28, NULL, + ai_walk, 25, NULL +}; +mmove_t parasite_move_walk = {FRAME_run03, FRAME_run09, parasite_frames_walk, parasite_walk}; + +mframe_t parasite_frames_start_walk [] = +{ + ai_walk, 0, NULL, + ai_walk, 30, parasite_walk +}; +mmove_t parasite_move_start_walk = {FRAME_run01, FRAME_run02, parasite_frames_start_walk, NULL}; + +mframe_t parasite_frames_stop_walk [] = +{ + ai_walk, 20, NULL, + ai_walk, 20, NULL, + ai_walk, 12, NULL, + ai_walk, 10, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL +}; +mmove_t parasite_move_stop_walk = {FRAME_run10, FRAME_run15, parasite_frames_stop_walk, NULL}; + +void parasite_start_walk (edict_t *self) +{ + self->monsterinfo.currentmove = ¶site_move_start_walk; +} + +void parasite_walk (edict_t *self) +{ + self->monsterinfo.currentmove = ¶site_move_walk; +} + + +mframe_t parasite_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 6, NULL, + ai_move, 16, NULL, + ai_move, -6, NULL, + ai_move, -7, NULL, + ai_move, 0, NULL +}; +mmove_t parasite_move_pain1 = {FRAME_pain101, FRAME_pain111, parasite_frames_pain1, parasite_start_run}; + +void parasite_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 3; + + if (skill->value == 3) + return; // no pain anims in nightmare + + if (random() < 0.5) + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + + self->monsterinfo.currentmove = ¶site_move_pain1; +} + + +static qboolean parasite_drain_attack_ok (vec3_t start, vec3_t end) +{ + vec3_t dir, angles; + + // check for max distance + VectorSubtract (start, end, dir); + if (VectorLength(dir) > 256) + return false; + + // check for min/max pitch + vectoangles (dir, angles); + if (angles[0] < -180) + angles[0] += 360; + if (fabs(angles[0]) > 30) + return false; + + return true; +} + +void parasite_drain_attack (edict_t *self) +{ + vec3_t offset, start, f, r, end, dir; + trace_t tr; + int damage; + + AngleVectors (self->s.angles, f, r, NULL); + VectorSet (offset, 24, 0, 6); + G_ProjectSource (self->s.origin, offset, f, r, start); + + VectorCopy (self->enemy->s.origin, end); + if (!parasite_drain_attack_ok(start, end)) + { + end[2] = self->enemy->s.origin[2] + self->enemy->maxs[2] - 8; + if (!parasite_drain_attack_ok(start, end)) + { + end[2] = self->enemy->s.origin[2] + self->enemy->mins[2] + 8; + if (!parasite_drain_attack_ok(start, end)) + return; + } + } + VectorCopy (self->enemy->s.origin, end); + + tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT); + if (tr.ent != self->enemy) + return; + + if (self->s.frame == FRAME_drain03) + { + damage = 5; + gi.sound (self->enemy, CHAN_AUTO, sound_impact, 1, ATTN_NORM, 0); + } + else + { + if (self->s.frame == FRAME_drain04) + gi.sound (self, CHAN_WEAPON, sound_suck, 1, ATTN_NORM, 0); + damage = 2; + } + + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_PARASITE_ATTACK); + gi.WriteShort (self - g_edicts); + gi.WritePosition (start); + gi.WritePosition (end); + gi.multicast (self->s.origin, MULTICAST_PVS); + + VectorSubtract (start, end, dir); + T_Damage (self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, damage, 0, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN); +} + +mframe_t parasite_frames_drain [] = +{ + ai_charge, 0, parasite_launch, + ai_charge, 0, NULL, + ai_charge, 15, parasite_drain_attack, // Target hits + ai_charge, 0, parasite_drain_attack, // drain + ai_charge, 0, parasite_drain_attack, // drain + ai_charge, 0, parasite_drain_attack, // drain + ai_charge, 0, parasite_drain_attack, // drain + ai_charge, -2, parasite_drain_attack, // drain + ai_charge, -2, parasite_drain_attack, // drain + ai_charge, -3, parasite_drain_attack, // drain + ai_charge, -2, parasite_drain_attack, // drain + ai_charge, 0, parasite_drain_attack, // drain + ai_charge, -1, parasite_drain_attack, // drain + ai_charge, 0, parasite_reel_in, // let go + ai_charge, -2, NULL, + ai_charge, -2, NULL, + ai_charge, -3, NULL, + ai_charge, 0, NULL +}; +mmove_t parasite_move_drain = {FRAME_drain01, FRAME_drain18, parasite_frames_drain, parasite_start_run}; + + +mframe_t parasite_frames_break [] = +{ + ai_charge, 0, NULL, + ai_charge, -3, NULL, + ai_charge, 1, NULL, + ai_charge, 2, NULL, + ai_charge, -3, NULL, + ai_charge, 1, NULL, + ai_charge, 1, NULL, + ai_charge, 3, NULL, + ai_charge, 0, NULL, + ai_charge, -18, NULL, + ai_charge, 3, NULL, + ai_charge, 9, NULL, + ai_charge, 6, NULL, + ai_charge, 0, NULL, + ai_charge, -18, NULL, + ai_charge, 0, NULL, + ai_charge, 8, NULL, + ai_charge, 9, NULL, + ai_charge, 0, NULL, + ai_charge, -18, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // airborne + ai_charge, 0, NULL, // airborne + ai_charge, 0, NULL, // slides + ai_charge, 0, NULL, // slides + ai_charge, 0, NULL, // slides + ai_charge, 0, NULL, // slides + ai_charge, 4, NULL, + ai_charge, 11, NULL, + ai_charge, -2, NULL, + ai_charge, -5, NULL, + ai_charge, 1, NULL +}; +mmove_t parasite_move_break = {FRAME_break01, FRAME_break32, parasite_frames_break, parasite_start_run}; + +/* +=== +Break Stuff Ends +=== +*/ + +void parasite_attack (edict_t *self) +{ +// if (random() <= 0.2) +// self->monsterinfo.currentmove = ¶site_move_break; +// else + self->monsterinfo.currentmove = ¶site_move_drain; +} + + + +/* +=== +Death Stuff Starts +=== +*/ + +void parasite_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +mframe_t parasite_frames_death [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t parasite_move_death = {FRAME_death101, FRAME_death107, parasite_frames_death, parasite_dead}; + +void parasite_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + self->monsterinfo.currentmove = ¶site_move_death; +} + +/* +=== +End Death Stuff +=== +*/ + +/*QUAKED monster_parasite (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_parasite (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_pain1 = gi.soundindex ("parasite/parpain1.wav"); + sound_pain2 = gi.soundindex ("parasite/parpain2.wav"); + sound_die = gi.soundindex ("parasite/pardeth1.wav"); + sound_launch = gi.soundindex("parasite/paratck1.wav"); + sound_impact = gi.soundindex("parasite/paratck2.wav"); + sound_suck = gi.soundindex("parasite/paratck3.wav"); + sound_reelin = gi.soundindex("parasite/paratck4.wav"); + sound_sight = gi.soundindex("parasite/parsght1.wav"); + sound_tap = gi.soundindex("parasite/paridle1.wav"); + sound_scratch = gi.soundindex("parasite/paridle2.wav"); + sound_search = gi.soundindex("parasite/parsrch1.wav"); + + self->s.modelindex = gi.modelindex ("models/monsters/parasite/tris.md2"); + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 24); + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + + self->health = 175; + self->gib_health = -50; + self->mass = 250; + + self->pain = parasite_pain; + self->die = parasite_die; + + self->monsterinfo.stand = parasite_stand; + self->monsterinfo.walk = parasite_start_walk; + self->monsterinfo.run = parasite_start_run; + self->monsterinfo.attack = parasite_attack; + self->monsterinfo.sight = parasite_sight; + self->monsterinfo.idle = parasite_idle; + + gi.linkentity (self); + + self->monsterinfo.currentmove = ¶site_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start (self); +} diff --git a/game/m_parasite.h b/game/m_parasite.h new file mode 100644 index 000000000..2410e7985 --- /dev/null +++ b/game/m_parasite.h @@ -0,0 +1,143 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/parasite + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_break01 0 +#define FRAME_break02 1 +#define FRAME_break03 2 +#define FRAME_break04 3 +#define FRAME_break05 4 +#define FRAME_break06 5 +#define FRAME_break07 6 +#define FRAME_break08 7 +#define FRAME_break09 8 +#define FRAME_break10 9 +#define FRAME_break11 10 +#define FRAME_break12 11 +#define FRAME_break13 12 +#define FRAME_break14 13 +#define FRAME_break15 14 +#define FRAME_break16 15 +#define FRAME_break17 16 +#define FRAME_break18 17 +#define FRAME_break19 18 +#define FRAME_break20 19 +#define FRAME_break21 20 +#define FRAME_break22 21 +#define FRAME_break23 22 +#define FRAME_break24 23 +#define FRAME_break25 24 +#define FRAME_break26 25 +#define FRAME_break27 26 +#define FRAME_break28 27 +#define FRAME_break29 28 +#define FRAME_break30 29 +#define FRAME_break31 30 +#define FRAME_break32 31 +#define FRAME_death101 32 +#define FRAME_death102 33 +#define FRAME_death103 34 +#define FRAME_death104 35 +#define FRAME_death105 36 +#define FRAME_death106 37 +#define FRAME_death107 38 +#define FRAME_drain01 39 +#define FRAME_drain02 40 +#define FRAME_drain03 41 +#define FRAME_drain04 42 +#define FRAME_drain05 43 +#define FRAME_drain06 44 +#define FRAME_drain07 45 +#define FRAME_drain08 46 +#define FRAME_drain09 47 +#define FRAME_drain10 48 +#define FRAME_drain11 49 +#define FRAME_drain12 50 +#define FRAME_drain13 51 +#define FRAME_drain14 52 +#define FRAME_drain15 53 +#define FRAME_drain16 54 +#define FRAME_drain17 55 +#define FRAME_drain18 56 +#define FRAME_pain101 57 +#define FRAME_pain102 58 +#define FRAME_pain103 59 +#define FRAME_pain104 60 +#define FRAME_pain105 61 +#define FRAME_pain106 62 +#define FRAME_pain107 63 +#define FRAME_pain108 64 +#define FRAME_pain109 65 +#define FRAME_pain110 66 +#define FRAME_pain111 67 +#define FRAME_run01 68 +#define FRAME_run02 69 +#define FRAME_run03 70 +#define FRAME_run04 71 +#define FRAME_run05 72 +#define FRAME_run06 73 +#define FRAME_run07 74 +#define FRAME_run08 75 +#define FRAME_run09 76 +#define FRAME_run10 77 +#define FRAME_run11 78 +#define FRAME_run12 79 +#define FRAME_run13 80 +#define FRAME_run14 81 +#define FRAME_run15 82 +#define FRAME_stand01 83 +#define FRAME_stand02 84 +#define FRAME_stand03 85 +#define FRAME_stand04 86 +#define FRAME_stand05 87 +#define FRAME_stand06 88 +#define FRAME_stand07 89 +#define FRAME_stand08 90 +#define FRAME_stand09 91 +#define FRAME_stand10 92 +#define FRAME_stand11 93 +#define FRAME_stand12 94 +#define FRAME_stand13 95 +#define FRAME_stand14 96 +#define FRAME_stand15 97 +#define FRAME_stand16 98 +#define FRAME_stand17 99 +#define FRAME_stand18 100 +#define FRAME_stand19 101 +#define FRAME_stand20 102 +#define FRAME_stand21 103 +#define FRAME_stand22 104 +#define FRAME_stand23 105 +#define FRAME_stand24 106 +#define FRAME_stand25 107 +#define FRAME_stand26 108 +#define FRAME_stand27 109 +#define FRAME_stand28 110 +#define FRAME_stand29 111 +#define FRAME_stand30 112 +#define FRAME_stand31 113 +#define FRAME_stand32 114 +#define FRAME_stand33 115 +#define FRAME_stand34 116 +#define FRAME_stand35 117 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_player.h b/game/m_player.h new file mode 100644 index 000000000..15f5a6221 --- /dev/null +++ b/game/m_player.h @@ -0,0 +1,224 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/player_x/frames + +// This file generated by qdata - Do NOT Modify + +#define FRAME_stand01 0 +#define FRAME_stand02 1 +#define FRAME_stand03 2 +#define FRAME_stand04 3 +#define FRAME_stand05 4 +#define FRAME_stand06 5 +#define FRAME_stand07 6 +#define FRAME_stand08 7 +#define FRAME_stand09 8 +#define FRAME_stand10 9 +#define FRAME_stand11 10 +#define FRAME_stand12 11 +#define FRAME_stand13 12 +#define FRAME_stand14 13 +#define FRAME_stand15 14 +#define FRAME_stand16 15 +#define FRAME_stand17 16 +#define FRAME_stand18 17 +#define FRAME_stand19 18 +#define FRAME_stand20 19 +#define FRAME_stand21 20 +#define FRAME_stand22 21 +#define FRAME_stand23 22 +#define FRAME_stand24 23 +#define FRAME_stand25 24 +#define FRAME_stand26 25 +#define FRAME_stand27 26 +#define FRAME_stand28 27 +#define FRAME_stand29 28 +#define FRAME_stand30 29 +#define FRAME_stand31 30 +#define FRAME_stand32 31 +#define FRAME_stand33 32 +#define FRAME_stand34 33 +#define FRAME_stand35 34 +#define FRAME_stand36 35 +#define FRAME_stand37 36 +#define FRAME_stand38 37 +#define FRAME_stand39 38 +#define FRAME_stand40 39 +#define FRAME_run1 40 +#define FRAME_run2 41 +#define FRAME_run3 42 +#define FRAME_run4 43 +#define FRAME_run5 44 +#define FRAME_run6 45 +#define FRAME_attack1 46 +#define FRAME_attack2 47 +#define FRAME_attack3 48 +#define FRAME_attack4 49 +#define FRAME_attack5 50 +#define FRAME_attack6 51 +#define FRAME_attack7 52 +#define FRAME_attack8 53 +#define FRAME_pain101 54 +#define FRAME_pain102 55 +#define FRAME_pain103 56 +#define FRAME_pain104 57 +#define FRAME_pain201 58 +#define FRAME_pain202 59 +#define FRAME_pain203 60 +#define FRAME_pain204 61 +#define FRAME_pain301 62 +#define FRAME_pain302 63 +#define FRAME_pain303 64 +#define FRAME_pain304 65 +#define FRAME_jump1 66 +#define FRAME_jump2 67 +#define FRAME_jump3 68 +#define FRAME_jump4 69 +#define FRAME_jump5 70 +#define FRAME_jump6 71 +#define FRAME_flip01 72 +#define FRAME_flip02 73 +#define FRAME_flip03 74 +#define FRAME_flip04 75 +#define FRAME_flip05 76 +#define FRAME_flip06 77 +#define FRAME_flip07 78 +#define FRAME_flip08 79 +#define FRAME_flip09 80 +#define FRAME_flip10 81 +#define FRAME_flip11 82 +#define FRAME_flip12 83 +#define FRAME_salute01 84 +#define FRAME_salute02 85 +#define FRAME_salute03 86 +#define FRAME_salute04 87 +#define FRAME_salute05 88 +#define FRAME_salute06 89 +#define FRAME_salute07 90 +#define FRAME_salute08 91 +#define FRAME_salute09 92 +#define FRAME_salute10 93 +#define FRAME_salute11 94 +#define FRAME_taunt01 95 +#define FRAME_taunt02 96 +#define FRAME_taunt03 97 +#define FRAME_taunt04 98 +#define FRAME_taunt05 99 +#define FRAME_taunt06 100 +#define FRAME_taunt07 101 +#define FRAME_taunt08 102 +#define FRAME_taunt09 103 +#define FRAME_taunt10 104 +#define FRAME_taunt11 105 +#define FRAME_taunt12 106 +#define FRAME_taunt13 107 +#define FRAME_taunt14 108 +#define FRAME_taunt15 109 +#define FRAME_taunt16 110 +#define FRAME_taunt17 111 +#define FRAME_wave01 112 +#define FRAME_wave02 113 +#define FRAME_wave03 114 +#define FRAME_wave04 115 +#define FRAME_wave05 116 +#define FRAME_wave06 117 +#define FRAME_wave07 118 +#define FRAME_wave08 119 +#define FRAME_wave09 120 +#define FRAME_wave10 121 +#define FRAME_wave11 122 +#define FRAME_point01 123 +#define FRAME_point02 124 +#define FRAME_point03 125 +#define FRAME_point04 126 +#define FRAME_point05 127 +#define FRAME_point06 128 +#define FRAME_point07 129 +#define FRAME_point08 130 +#define FRAME_point09 131 +#define FRAME_point10 132 +#define FRAME_point11 133 +#define FRAME_point12 134 +#define FRAME_crstnd01 135 +#define FRAME_crstnd02 136 +#define FRAME_crstnd03 137 +#define FRAME_crstnd04 138 +#define FRAME_crstnd05 139 +#define FRAME_crstnd06 140 +#define FRAME_crstnd07 141 +#define FRAME_crstnd08 142 +#define FRAME_crstnd09 143 +#define FRAME_crstnd10 144 +#define FRAME_crstnd11 145 +#define FRAME_crstnd12 146 +#define FRAME_crstnd13 147 +#define FRAME_crstnd14 148 +#define FRAME_crstnd15 149 +#define FRAME_crstnd16 150 +#define FRAME_crstnd17 151 +#define FRAME_crstnd18 152 +#define FRAME_crstnd19 153 +#define FRAME_crwalk1 154 +#define FRAME_crwalk2 155 +#define FRAME_crwalk3 156 +#define FRAME_crwalk4 157 +#define FRAME_crwalk5 158 +#define FRAME_crwalk6 159 +#define FRAME_crattak1 160 +#define FRAME_crattak2 161 +#define FRAME_crattak3 162 +#define FRAME_crattak4 163 +#define FRAME_crattak5 164 +#define FRAME_crattak6 165 +#define FRAME_crattak7 166 +#define FRAME_crattak8 167 +#define FRAME_crattak9 168 +#define FRAME_crpain1 169 +#define FRAME_crpain2 170 +#define FRAME_crpain3 171 +#define FRAME_crpain4 172 +#define FRAME_crdeath1 173 +#define FRAME_crdeath2 174 +#define FRAME_crdeath3 175 +#define FRAME_crdeath4 176 +#define FRAME_crdeath5 177 +#define FRAME_death101 178 +#define FRAME_death102 179 +#define FRAME_death103 180 +#define FRAME_death104 181 +#define FRAME_death105 182 +#define FRAME_death106 183 +#define FRAME_death201 184 +#define FRAME_death202 185 +#define FRAME_death203 186 +#define FRAME_death204 187 +#define FRAME_death205 188 +#define FRAME_death206 189 +#define FRAME_death301 190 +#define FRAME_death302 191 +#define FRAME_death303 192 +#define FRAME_death304 193 +#define FRAME_death305 194 +#define FRAME_death306 195 +#define FRAME_death307 196 +#define FRAME_death308 197 + +#define MODEL_SCALE 1.000000 + diff --git a/game/m_rider.h b/game/m_rider.h new file mode 100644 index 000000000..f47af79c2 --- /dev/null +++ b/game/m_rider.h @@ -0,0 +1,66 @@ +// G:\quake2\baseq2\models/monsters/boss3/rider + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_stand201 0 +#define FRAME_stand202 1 +#define FRAME_stand203 2 +#define FRAME_stand204 3 +#define FRAME_stand205 4 +#define FRAME_stand206 5 +#define FRAME_stand207 6 +#define FRAME_stand208 7 +#define FRAME_stand209 8 +#define FRAME_stand210 9 +#define FRAME_stand211 10 +#define FRAME_stand212 11 +#define FRAME_stand213 12 +#define FRAME_stand214 13 +#define FRAME_stand215 14 +#define FRAME_stand216 15 +#define FRAME_stand217 16 +#define FRAME_stand218 17 +#define FRAME_stand219 18 +#define FRAME_stand220 19 +#define FRAME_stand221 20 +#define FRAME_stand222 21 +#define FRAME_stand223 22 +#define FRAME_stand224 23 +#define FRAME_stand225 24 +#define FRAME_stand226 25 +#define FRAME_stand227 26 +#define FRAME_stand228 27 +#define FRAME_stand229 28 +#define FRAME_stand230 29 +#define FRAME_stand231 30 +#define FRAME_stand232 31 +#define FRAME_stand233 32 +#define FRAME_stand234 33 +#define FRAME_stand235 34 +#define FRAME_stand236 35 +#define FRAME_stand237 36 +#define FRAME_stand238 37 +#define FRAME_stand239 38 +#define FRAME_stand240 39 +#define FRAME_stand241 40 +#define FRAME_stand242 41 +#define FRAME_stand243 42 +#define FRAME_stand244 43 +#define FRAME_stand245 44 +#define FRAME_stand246 45 +#define FRAME_stand247 46 +#define FRAME_stand248 47 +#define FRAME_stand249 48 +#define FRAME_stand250 49 +#define FRAME_stand251 50 +#define FRAME_stand252 51 +#define FRAME_stand253 52 +#define FRAME_stand254 53 +#define FRAME_stand255 54 +#define FRAME_stand256 55 +#define FRAME_stand257 56 +#define FRAME_stand258 57 +#define FRAME_stand259 58 +#define FRAME_stand260 59 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_soldier.c b/game/m_soldier.c new file mode 100644 index 000000000..dae6d61fc --- /dev/null +++ b/game/m_soldier.c @@ -0,0 +1,1299 @@ +/* +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. + +*/ +/* +============================================================================== + +SOLDIER + +============================================================================== +*/ + +#include "g_local.h" +#include "m_soldier.h" + + +static int sound_idle; +static int sound_sight1; +static int sound_sight2; +static int sound_pain_light; +static int sound_pain; +static int sound_pain_ss; +static int sound_death_light; +static int sound_death; +static int sound_death_ss; +static int sound_cock; + + +void soldier_idle (edict_t *self) +{ + if (random() > 0.8) + gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); +} + +void soldier_cock (edict_t *self) +{ + if (self->s.frame == FRAME_stand322) + gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_IDLE, 0); + else + gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_NORM, 0); +} + + +// STAND + +void soldier_stand (edict_t *self); + +mframe_t soldier_frames_stand1 [] = +{ + ai_stand, 0, soldier_idle, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t soldier_move_stand1 = {FRAME_stand101, FRAME_stand130, soldier_frames_stand1, soldier_stand}; + +mframe_t soldier_frames_stand3 [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, soldier_cock, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t soldier_move_stand3 = {FRAME_stand301, FRAME_stand339, soldier_frames_stand3, soldier_stand}; + +#if 0 +mframe_t soldier_frames_stand4 [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 4, NULL, + ai_stand, 1, NULL, + ai_stand, -1, NULL, + ai_stand, -2, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t soldier_move_stand4 = {FRAME_stand401, FRAME_stand452, soldier_frames_stand4, NULL}; +#endif + +void soldier_stand (edict_t *self) +{ + if ((self->monsterinfo.currentmove == &soldier_move_stand3) || (random() < 0.8)) + self->monsterinfo.currentmove = &soldier_move_stand1; + else + self->monsterinfo.currentmove = &soldier_move_stand3; +} + + +// +// WALK +// + +void soldier_walk1_random (edict_t *self) +{ + if (random() > 0.1) + self->monsterinfo.nextframe = FRAME_walk101; +} + +mframe_t soldier_frames_walk1 [] = +{ + ai_walk, 3, NULL, + ai_walk, 6, NULL, + ai_walk, 2, NULL, + ai_walk, 2, NULL, + ai_walk, 2, NULL, + ai_walk, 1, NULL, + ai_walk, 6, NULL, + ai_walk, 5, NULL, + ai_walk, 3, NULL, + ai_walk, -1, soldier_walk1_random, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL +}; +mmove_t soldier_move_walk1 = {FRAME_walk101, FRAME_walk133, soldier_frames_walk1, NULL}; + +mframe_t soldier_frames_walk2 [] = +{ + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 9, NULL, + ai_walk, 8, NULL, + ai_walk, 5, NULL, + ai_walk, 1, NULL, + ai_walk, 3, NULL, + ai_walk, 7, NULL, + ai_walk, 6, NULL, + ai_walk, 7, NULL +}; +mmove_t soldier_move_walk2 = {FRAME_walk209, FRAME_walk218, soldier_frames_walk2, NULL}; + +void soldier_walk (edict_t *self) +{ + if (random() < 0.5) + self->monsterinfo.currentmove = &soldier_move_walk1; + else + self->monsterinfo.currentmove = &soldier_move_walk2; +} + + +// +// RUN +// + +void soldier_run (edict_t *self); + +mframe_t soldier_frames_start_run [] = +{ + ai_run, 7, NULL, + ai_run, 5, NULL +}; +mmove_t soldier_move_start_run = {FRAME_run01, FRAME_run02, soldier_frames_start_run, soldier_run}; + +mframe_t soldier_frames_run [] = +{ + ai_run, 10, NULL, + ai_run, 11, NULL, + ai_run, 11, NULL, + ai_run, 16, NULL, + ai_run, 10, NULL, + ai_run, 15, NULL +}; +mmove_t soldier_move_run = {FRAME_run03, FRAME_run08, soldier_frames_run, NULL}; + +void soldier_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + { + self->monsterinfo.currentmove = &soldier_move_stand1; + return; + } + + if (self->monsterinfo.currentmove == &soldier_move_walk1 || + self->monsterinfo.currentmove == &soldier_move_walk2 || + self->monsterinfo.currentmove == &soldier_move_start_run) + { + self->monsterinfo.currentmove = &soldier_move_run; + } + else + { + self->monsterinfo.currentmove = &soldier_move_start_run; + } +} + + +// +// PAIN +// + +mframe_t soldier_frames_pain1 [] = +{ + ai_move, -3, NULL, + ai_move, 4, NULL, + ai_move, 1, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL +}; +mmove_t soldier_move_pain1 = {FRAME_pain101, FRAME_pain105, soldier_frames_pain1, soldier_run}; + +mframe_t soldier_frames_pain2 [] = +{ + ai_move, -13, NULL, + ai_move, -1, NULL, + ai_move, 2, NULL, + ai_move, 4, NULL, + ai_move, 2, NULL, + ai_move, 3, NULL, + ai_move, 2, NULL +}; +mmove_t soldier_move_pain2 = {FRAME_pain201, FRAME_pain207, soldier_frames_pain2, soldier_run}; + +mframe_t soldier_frames_pain3 [] = +{ + ai_move, -8, NULL, + ai_move, 10, NULL, + ai_move, -4, NULL, + ai_move, -1, NULL, + ai_move, -3, NULL, + ai_move, 0, NULL, + ai_move, 3, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, 1, NULL, + ai_move, 2, NULL, + ai_move, 4, NULL, + ai_move, 3, NULL, + ai_move, 2, NULL +}; +mmove_t soldier_move_pain3 = {FRAME_pain301, FRAME_pain318, soldier_frames_pain3, soldier_run}; + +mframe_t soldier_frames_pain4 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -10, NULL, + ai_move, -6, NULL, + ai_move, 8, NULL, + ai_move, 4, NULL, + ai_move, 1, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 5, NULL, + ai_move, 2, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, 3, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL +}; +mmove_t soldier_move_pain4 = {FRAME_pain401, FRAME_pain417, soldier_frames_pain4, soldier_run}; + + +void soldier_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + float r; + int n; + + if (self->health < (self->max_health / 2)) + self->s.skinnum |= 1; + + if (level.time < self->pain_debounce_time) + { + if ((self->velocity[2] > 100) && ( (self->monsterinfo.currentmove == &soldier_move_pain1) || (self->monsterinfo.currentmove == &soldier_move_pain2) || (self->monsterinfo.currentmove == &soldier_move_pain3))) + self->monsterinfo.currentmove = &soldier_move_pain4; + return; + } + + self->pain_debounce_time = level.time + 3; + + n = self->s.skinnum | 1; + if (n == 1) + gi.sound (self, CHAN_VOICE, sound_pain_light, 1, ATTN_NORM, 0); + else if (n == 3) + gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_pain_ss, 1, ATTN_NORM, 0); + + if (self->velocity[2] > 100) + { + self->monsterinfo.currentmove = &soldier_move_pain4; + return; + } + + if (skill->value == 3) + return; // no pain anims in nightmare + + r = random(); + + if (r < 0.33) + self->monsterinfo.currentmove = &soldier_move_pain1; + else if (r < 0.66) + self->monsterinfo.currentmove = &soldier_move_pain2; + else + self->monsterinfo.currentmove = &soldier_move_pain3; +} + + +// +// ATTACK +// + +static int blaster_flash [] = {MZ2_SOLDIER_BLASTER_1, MZ2_SOLDIER_BLASTER_2, MZ2_SOLDIER_BLASTER_3, MZ2_SOLDIER_BLASTER_4, MZ2_SOLDIER_BLASTER_5, MZ2_SOLDIER_BLASTER_6, MZ2_SOLDIER_BLASTER_7, MZ2_SOLDIER_BLASTER_8}; +static int shotgun_flash [] = {MZ2_SOLDIER_SHOTGUN_1, MZ2_SOLDIER_SHOTGUN_2, MZ2_SOLDIER_SHOTGUN_3, MZ2_SOLDIER_SHOTGUN_4, MZ2_SOLDIER_SHOTGUN_5, MZ2_SOLDIER_SHOTGUN_6, MZ2_SOLDIER_SHOTGUN_7, MZ2_SOLDIER_SHOTGUN_8}; +static int machinegun_flash [] = {MZ2_SOLDIER_MACHINEGUN_1, MZ2_SOLDIER_MACHINEGUN_2, MZ2_SOLDIER_MACHINEGUN_3, MZ2_SOLDIER_MACHINEGUN_4, MZ2_SOLDIER_MACHINEGUN_5, MZ2_SOLDIER_MACHINEGUN_6, MZ2_SOLDIER_MACHINEGUN_7, MZ2_SOLDIER_MACHINEGUN_8}; + +void soldier_fire (edict_t *self, int flash_number) +{ + vec3_t start; + vec3_t forward, right, up; + vec3_t aim; + vec3_t dir; + vec3_t end; + float r, u; + int flash_index; + + if (self->s.skinnum < 2) + flash_index = blaster_flash[flash_number]; + else if (self->s.skinnum < 4) + flash_index = shotgun_flash[flash_number]; + else + flash_index = machinegun_flash[flash_number]; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start); + + if (flash_number == 5 || flash_number == 6) + { + VectorCopy (forward, aim); + } + else + { + VectorCopy (self->enemy->s.origin, end); + end[2] += self->enemy->viewheight; + VectorSubtract (end, start, aim); + vectoangles (aim, dir); + AngleVectors (dir, forward, right, up); + + r = crandom()*1000; + u = crandom()*500; + VectorMA (start, 8192, forward, end); + VectorMA (end, r, right, end); + VectorMA (end, u, up, end); + + VectorSubtract (end, start, aim); + VectorNormalize (aim); + } + + if (self->s.skinnum <= 1) + { + monster_fire_blaster (self, start, aim, 5, 600, flash_index, EF_BLASTER); + } + else if (self->s.skinnum <= 3) + { + monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index); + } + else + { + if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME)) + self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME; + + monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index); + + if (level.time >= self->monsterinfo.pausetime) + self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; + else + self->monsterinfo.aiflags |= AI_HOLD_FRAME; + } +} + +// ATTACK1 (blaster/shotgun) + +void soldier_fire1 (edict_t *self) +{ + soldier_fire (self, 0); +} + +void soldier_attack1_refire1 (edict_t *self) +{ + if (self->s.skinnum > 1) + return; + + if (self->enemy->health <= 0) + return; + + if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) + self->monsterinfo.nextframe = FRAME_attak102; + else + self->monsterinfo.nextframe = FRAME_attak110; +} + +void soldier_attack1_refire2 (edict_t *self) +{ + if (self->s.skinnum < 2) + return; + + if (self->enemy->health <= 0) + return; + + if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) + self->monsterinfo.nextframe = FRAME_attak102; +} + +mframe_t soldier_frames_attack1 [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, soldier_fire1, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, soldier_attack1_refire1, + ai_charge, 0, NULL, + ai_charge, 0, soldier_cock, + ai_charge, 0, soldier_attack1_refire2, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t soldier_move_attack1 = {FRAME_attak101, FRAME_attak112, soldier_frames_attack1, soldier_run}; + +// ATTACK2 (blaster/shotgun) + +void soldier_fire2 (edict_t *self) +{ + soldier_fire (self, 1); +} + +void soldier_attack2_refire1 (edict_t *self) +{ + if (self->s.skinnum > 1) + return; + + if (self->enemy->health <= 0) + return; + + if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) + self->monsterinfo.nextframe = FRAME_attak204; + else + self->monsterinfo.nextframe = FRAME_attak216; +} + +void soldier_attack2_refire2 (edict_t *self) +{ + if (self->s.skinnum < 2) + return; + + if (self->enemy->health <= 0) + return; + + if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) + self->monsterinfo.nextframe = FRAME_attak204; +} + +mframe_t soldier_frames_attack2 [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, soldier_fire2, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, soldier_attack2_refire1, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, soldier_cock, + ai_charge, 0, NULL, + ai_charge, 0, soldier_attack2_refire2, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t soldier_move_attack2 = {FRAME_attak201, FRAME_attak218, soldier_frames_attack2, soldier_run}; + +// ATTACK3 (duck and shoot) + +void soldier_duck_down (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_DUCKED) + return; + self->monsterinfo.aiflags |= AI_DUCKED; + self->maxs[2] -= 32; + self->takedamage = DAMAGE_YES; + self->monsterinfo.pausetime = level.time + 1; + gi.linkentity (self); +} + +void soldier_duck_up (edict_t *self) +{ + self->monsterinfo.aiflags &= ~AI_DUCKED; + self->maxs[2] += 32; + self->takedamage = DAMAGE_AIM; + gi.linkentity (self); +} + +void soldier_fire3 (edict_t *self) +{ + soldier_duck_down (self); + soldier_fire (self, 2); +} + +void soldier_attack3_refire (edict_t *self) +{ + if ((level.time + 0.4) < self->monsterinfo.pausetime) + self->monsterinfo.nextframe = FRAME_attak303; +} + +mframe_t soldier_frames_attack3 [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, soldier_fire3, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, soldier_attack3_refire, + ai_charge, 0, soldier_duck_up, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t soldier_move_attack3 = {FRAME_attak301, FRAME_attak309, soldier_frames_attack3, soldier_run}; + +// ATTACK4 (machinegun) + +void soldier_fire4 (edict_t *self) +{ + soldier_fire (self, 3); +// +// if (self->enemy->health <= 0) +// return; +// +// if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) +// self->monsterinfo.nextframe = FRAME_attak402; +} + +mframe_t soldier_frames_attack4 [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, soldier_fire4, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t soldier_move_attack4 = {FRAME_attak401, FRAME_attak406, soldier_frames_attack4, soldier_run}; + +#if 0 +// ATTACK5 (prone) + +void soldier_fire5 (edict_t *self) +{ + soldier_fire (self, 4); +} + +void soldier_attack5_refire (edict_t *self) +{ + if (self->enemy->health <= 0) + return; + + if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) ) + self->monsterinfo.nextframe = FRAME_attak505; +} + +mframe_t soldier_frames_attack5 [] = +{ + ai_charge, 8, NULL, + ai_charge, 8, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, soldier_fire5, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, soldier_attack5_refire +}; +mmove_t soldier_move_attack5 = {FRAME_attak501, FRAME_attak508, soldier_frames_attack5, soldier_run}; +#endif + +// ATTACK6 (run & shoot) + +void soldier_fire8 (edict_t *self) +{ + soldier_fire (self, 7); +} + +void soldier_attack6_refire (edict_t *self) +{ + if (self->enemy->health <= 0) + return; + + if (range(self, self->enemy) < RANGE_MID) + return; + + if (skill->value == 3) + self->monsterinfo.nextframe = FRAME_runs03; +} + +mframe_t soldier_frames_attack6 [] = +{ + ai_charge, 10, NULL, + ai_charge, 4, NULL, + ai_charge, 12, NULL, + ai_charge, 11, soldier_fire8, + ai_charge, 13, NULL, + ai_charge, 18, NULL, + ai_charge, 15, NULL, + ai_charge, 14, NULL, + ai_charge, 11, NULL, + ai_charge, 8, NULL, + ai_charge, 11, NULL, + ai_charge, 12, NULL, + ai_charge, 12, NULL, + ai_charge, 17, soldier_attack6_refire +}; +mmove_t soldier_move_attack6 = {FRAME_runs01, FRAME_runs14, soldier_frames_attack6, soldier_run}; + +void soldier_attack(edict_t *self) +{ + if (self->s.skinnum < 4) + { + if (random() < 0.5) + self->monsterinfo.currentmove = &soldier_move_attack1; + else + self->monsterinfo.currentmove = &soldier_move_attack2; + } + else + { + self->monsterinfo.currentmove = &soldier_move_attack4; + } +} + + +// +// SIGHT +// + +void soldier_sight(edict_t *self, edict_t *other) +{ + if (random() < 0.5) + gi.sound (self, CHAN_VOICE, sound_sight1, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_sight2, 1, ATTN_NORM, 0); + + if ((skill->value > 0) && (range(self, self->enemy) >= RANGE_MID)) + { + if (random() > 0.5) + self->monsterinfo.currentmove = &soldier_move_attack6; + } +} + +// +// DUCK +// + +void soldier_duck_hold (edict_t *self) +{ + if (level.time >= self->monsterinfo.pausetime) + self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; + else + self->monsterinfo.aiflags |= AI_HOLD_FRAME; +} + +mframe_t soldier_frames_duck [] = +{ + ai_move, 5, soldier_duck_down, + ai_move, -1, soldier_duck_hold, + ai_move, 1, NULL, + ai_move, 0, soldier_duck_up, + ai_move, 5, NULL +}; +mmove_t soldier_move_duck = {FRAME_duck01, FRAME_duck05, soldier_frames_duck, soldier_run}; + +void soldier_dodge (edict_t *self, edict_t *attacker, float eta) +{ + float r; + + r = random(); + if (r > 0.25) + return; + + if (!self->enemy) + self->enemy = attacker; + + if (skill->value == 0) + { + self->monsterinfo.currentmove = &soldier_move_duck; + return; + } + + self->monsterinfo.pausetime = level.time + eta + 0.3; + r = random(); + + if (skill->value == 1) + { + if (r > 0.33) + self->monsterinfo.currentmove = &soldier_move_duck; + else + self->monsterinfo.currentmove = &soldier_move_attack3; + return; + } + + if (skill->value >= 2) + { + if (r > 0.66) + self->monsterinfo.currentmove = &soldier_move_duck; + else + self->monsterinfo.currentmove = &soldier_move_attack3; + return; + } + + self->monsterinfo.currentmove = &soldier_move_attack3; +} + + +// +// DEATH +// + +void soldier_fire6 (edict_t *self) +{ + soldier_fire (self, 5); +} + +void soldier_fire7 (edict_t *self) +{ + soldier_fire (self, 6); +} + +void soldier_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +mframe_t soldier_frames_death1 [] = +{ + ai_move, 0, NULL, + ai_move, -10, NULL, + ai_move, -10, NULL, + ai_move, -10, NULL, + ai_move, -5, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, soldier_fire6, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, soldier_fire7, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t soldier_move_death1 = {FRAME_death101, FRAME_death136, soldier_frames_death1, soldier_dead}; + +mframe_t soldier_frames_death2 [] = +{ + ai_move, -5, NULL, + ai_move, -5, NULL, + ai_move, -5, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t soldier_move_death2 = {FRAME_death201, FRAME_death235, soldier_frames_death2, soldier_dead}; + +mframe_t soldier_frames_death3 [] = +{ + ai_move, -5, NULL, + ai_move, -5, NULL, + ai_move, -5, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, +}; +mmove_t soldier_move_death3 = {FRAME_death301, FRAME_death345, soldier_frames_death3, soldier_dead}; + +mframe_t soldier_frames_death4 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t soldier_move_death4 = {FRAME_death401, FRAME_death453, soldier_frames_death4, soldier_dead}; + +mframe_t soldier_frames_death5 [] = +{ + ai_move, -5, NULL, + ai_move, -5, NULL, + ai_move, -5, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t soldier_move_death5 = {FRAME_death501, FRAME_death524, soldier_frames_death5, soldier_dead}; + +mframe_t soldier_frames_death6 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t soldier_move_death6 = {FRAME_death601, FRAME_death610, soldier_frames_death6, soldier_dead}; + +void soldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 3; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + self->s.skinnum |= 1; + + if (self->s.skinnum == 1) + gi.sound (self, CHAN_VOICE, sound_death_light, 1, ATTN_NORM, 0); + else if (self->s.skinnum == 3) + gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); + else // (self->s.skinnum == 5) + gi.sound (self, CHAN_VOICE, sound_death_ss, 1, ATTN_NORM, 0); + + if (fabs((self->s.origin[2] + self->viewheight) - point[2]) <= 4) + { + // head shot + self->monsterinfo.currentmove = &soldier_move_death3; + return; + } + + n = rand() % 5; + if (n == 0) + self->monsterinfo.currentmove = &soldier_move_death1; + else if (n == 1) + self->monsterinfo.currentmove = &soldier_move_death2; + else if (n == 2) + self->monsterinfo.currentmove = &soldier_move_death4; + else if (n == 3) + self->monsterinfo.currentmove = &soldier_move_death5; + else + self->monsterinfo.currentmove = &soldier_move_death6; +} + + +// +// SPAWN +// + +void SP_monster_soldier_x (edict_t *self) +{ + + self->s.modelindex = gi.modelindex ("models/monsters/soldier/tris.md2"); + self->monsterinfo.scale = MODEL_SCALE; + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 32); + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + + sound_idle = gi.soundindex ("soldier/solidle1.wav"); + sound_sight1 = gi.soundindex ("soldier/solsght1.wav"); + sound_sight2 = gi.soundindex ("soldier/solsrch1.wav"); + sound_cock = gi.soundindex ("infantry/infatck3.wav"); + + self->mass = 100; + + self->pain = soldier_pain; + self->die = soldier_die; + + self->monsterinfo.stand = soldier_stand; + self->monsterinfo.walk = soldier_walk; + self->monsterinfo.run = soldier_run; + self->monsterinfo.dodge = soldier_dodge; + self->monsterinfo.attack = soldier_attack; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = soldier_sight; + + gi.linkentity (self); + + self->monsterinfo.stand (self); + + walkmonster_start (self); +} + + +/*QUAKED monster_soldier_light (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_soldier_light (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + SP_monster_soldier_x (self); + + sound_pain_light = gi.soundindex ("soldier/solpain2.wav"); + sound_death_light = gi.soundindex ("soldier/soldeth2.wav"); + gi.modelindex ("models/objects/laser/tris.md2"); + gi.soundindex ("misc/lasfly.wav"); + gi.soundindex ("soldier/solatck2.wav"); + + self->s.skinnum = 0; + self->health = 20; + self->gib_health = -30; +} + +/*QUAKED monster_soldier (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_soldier (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + SP_monster_soldier_x (self); + + sound_pain = gi.soundindex ("soldier/solpain1.wav"); + sound_death = gi.soundindex ("soldier/soldeth1.wav"); + gi.soundindex ("soldier/solatck1.wav"); + + self->s.skinnum = 2; + self->health = 30; + self->gib_health = -30; +} + +/*QUAKED monster_soldier_ss (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_soldier_ss (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + SP_monster_soldier_x (self); + + sound_pain_ss = gi.soundindex ("soldier/solpain3.wav"); + sound_death_ss = gi.soundindex ("soldier/soldeth3.wav"); + gi.soundindex ("soldier/solatck3.wav"); + + self->s.skinnum = 4; + self->health = 40; + self->gib_health = -30; +} diff --git a/game/m_soldier.h b/game/m_soldier.h new file mode 100644 index 000000000..91167be47 --- /dev/null +++ b/game/m_soldier.h @@ -0,0 +1,500 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/soldier + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_attak101 0 +#define FRAME_attak102 1 +#define FRAME_attak103 2 +#define FRAME_attak104 3 +#define FRAME_attak105 4 +#define FRAME_attak106 5 +#define FRAME_attak107 6 +#define FRAME_attak108 7 +#define FRAME_attak109 8 +#define FRAME_attak110 9 +#define FRAME_attak111 10 +#define FRAME_attak112 11 +#define FRAME_attak201 12 +#define FRAME_attak202 13 +#define FRAME_attak203 14 +#define FRAME_attak204 15 +#define FRAME_attak205 16 +#define FRAME_attak206 17 +#define FRAME_attak207 18 +#define FRAME_attak208 19 +#define FRAME_attak209 20 +#define FRAME_attak210 21 +#define FRAME_attak211 22 +#define FRAME_attak212 23 +#define FRAME_attak213 24 +#define FRAME_attak214 25 +#define FRAME_attak215 26 +#define FRAME_attak216 27 +#define FRAME_attak217 28 +#define FRAME_attak218 29 +#define FRAME_attak301 30 +#define FRAME_attak302 31 +#define FRAME_attak303 32 +#define FRAME_attak304 33 +#define FRAME_attak305 34 +#define FRAME_attak306 35 +#define FRAME_attak307 36 +#define FRAME_attak308 37 +#define FRAME_attak309 38 +#define FRAME_attak401 39 +#define FRAME_attak402 40 +#define FRAME_attak403 41 +#define FRAME_attak404 42 +#define FRAME_attak405 43 +#define FRAME_attak406 44 +#define FRAME_duck01 45 +#define FRAME_duck02 46 +#define FRAME_duck03 47 +#define FRAME_duck04 48 +#define FRAME_duck05 49 +#define FRAME_pain101 50 +#define FRAME_pain102 51 +#define FRAME_pain103 52 +#define FRAME_pain104 53 +#define FRAME_pain105 54 +#define FRAME_pain201 55 +#define FRAME_pain202 56 +#define FRAME_pain203 57 +#define FRAME_pain204 58 +#define FRAME_pain205 59 +#define FRAME_pain206 60 +#define FRAME_pain207 61 +#define FRAME_pain301 62 +#define FRAME_pain302 63 +#define FRAME_pain303 64 +#define FRAME_pain304 65 +#define FRAME_pain305 66 +#define FRAME_pain306 67 +#define FRAME_pain307 68 +#define FRAME_pain308 69 +#define FRAME_pain309 70 +#define FRAME_pain310 71 +#define FRAME_pain311 72 +#define FRAME_pain312 73 +#define FRAME_pain313 74 +#define FRAME_pain314 75 +#define FRAME_pain315 76 +#define FRAME_pain316 77 +#define FRAME_pain317 78 +#define FRAME_pain318 79 +#define FRAME_pain401 80 +#define FRAME_pain402 81 +#define FRAME_pain403 82 +#define FRAME_pain404 83 +#define FRAME_pain405 84 +#define FRAME_pain406 85 +#define FRAME_pain407 86 +#define FRAME_pain408 87 +#define FRAME_pain409 88 +#define FRAME_pain410 89 +#define FRAME_pain411 90 +#define FRAME_pain412 91 +#define FRAME_pain413 92 +#define FRAME_pain414 93 +#define FRAME_pain415 94 +#define FRAME_pain416 95 +#define FRAME_pain417 96 +#define FRAME_run01 97 +#define FRAME_run02 98 +#define FRAME_run03 99 +#define FRAME_run04 100 +#define FRAME_run05 101 +#define FRAME_run06 102 +#define FRAME_run07 103 +#define FRAME_run08 104 +#define FRAME_run09 105 +#define FRAME_run10 106 +#define FRAME_run11 107 +#define FRAME_run12 108 +#define FRAME_runs01 109 +#define FRAME_runs02 110 +#define FRAME_runs03 111 +#define FRAME_runs04 112 +#define FRAME_runs05 113 +#define FRAME_runs06 114 +#define FRAME_runs07 115 +#define FRAME_runs08 116 +#define FRAME_runs09 117 +#define FRAME_runs10 118 +#define FRAME_runs11 119 +#define FRAME_runs12 120 +#define FRAME_runs13 121 +#define FRAME_runs14 122 +#define FRAME_runs15 123 +#define FRAME_runs16 124 +#define FRAME_runs17 125 +#define FRAME_runs18 126 +#define FRAME_runt01 127 +#define FRAME_runt02 128 +#define FRAME_runt03 129 +#define FRAME_runt04 130 +#define FRAME_runt05 131 +#define FRAME_runt06 132 +#define FRAME_runt07 133 +#define FRAME_runt08 134 +#define FRAME_runt09 135 +#define FRAME_runt10 136 +#define FRAME_runt11 137 +#define FRAME_runt12 138 +#define FRAME_runt13 139 +#define FRAME_runt14 140 +#define FRAME_runt15 141 +#define FRAME_runt16 142 +#define FRAME_runt17 143 +#define FRAME_runt18 144 +#define FRAME_runt19 145 +#define FRAME_stand101 146 +#define FRAME_stand102 147 +#define FRAME_stand103 148 +#define FRAME_stand104 149 +#define FRAME_stand105 150 +#define FRAME_stand106 151 +#define FRAME_stand107 152 +#define FRAME_stand108 153 +#define FRAME_stand109 154 +#define FRAME_stand110 155 +#define FRAME_stand111 156 +#define FRAME_stand112 157 +#define FRAME_stand113 158 +#define FRAME_stand114 159 +#define FRAME_stand115 160 +#define FRAME_stand116 161 +#define FRAME_stand117 162 +#define FRAME_stand118 163 +#define FRAME_stand119 164 +#define FRAME_stand120 165 +#define FRAME_stand121 166 +#define FRAME_stand122 167 +#define FRAME_stand123 168 +#define FRAME_stand124 169 +#define FRAME_stand125 170 +#define FRAME_stand126 171 +#define FRAME_stand127 172 +#define FRAME_stand128 173 +#define FRAME_stand129 174 +#define FRAME_stand130 175 +#define FRAME_stand301 176 +#define FRAME_stand302 177 +#define FRAME_stand303 178 +#define FRAME_stand304 179 +#define FRAME_stand305 180 +#define FRAME_stand306 181 +#define FRAME_stand307 182 +#define FRAME_stand308 183 +#define FRAME_stand309 184 +#define FRAME_stand310 185 +#define FRAME_stand311 186 +#define FRAME_stand312 187 +#define FRAME_stand313 188 +#define FRAME_stand314 189 +#define FRAME_stand315 190 +#define FRAME_stand316 191 +#define FRAME_stand317 192 +#define FRAME_stand318 193 +#define FRAME_stand319 194 +#define FRAME_stand320 195 +#define FRAME_stand321 196 +#define FRAME_stand322 197 +#define FRAME_stand323 198 +#define FRAME_stand324 199 +#define FRAME_stand325 200 +#define FRAME_stand326 201 +#define FRAME_stand327 202 +#define FRAME_stand328 203 +#define FRAME_stand329 204 +#define FRAME_stand330 205 +#define FRAME_stand331 206 +#define FRAME_stand332 207 +#define FRAME_stand333 208 +#define FRAME_stand334 209 +#define FRAME_stand335 210 +#define FRAME_stand336 211 +#define FRAME_stand337 212 +#define FRAME_stand338 213 +#define FRAME_stand339 214 +#define FRAME_walk101 215 +#define FRAME_walk102 216 +#define FRAME_walk103 217 +#define FRAME_walk104 218 +#define FRAME_walk105 219 +#define FRAME_walk106 220 +#define FRAME_walk107 221 +#define FRAME_walk108 222 +#define FRAME_walk109 223 +#define FRAME_walk110 224 +#define FRAME_walk111 225 +#define FRAME_walk112 226 +#define FRAME_walk113 227 +#define FRAME_walk114 228 +#define FRAME_walk115 229 +#define FRAME_walk116 230 +#define FRAME_walk117 231 +#define FRAME_walk118 232 +#define FRAME_walk119 233 +#define FRAME_walk120 234 +#define FRAME_walk121 235 +#define FRAME_walk122 236 +#define FRAME_walk123 237 +#define FRAME_walk124 238 +#define FRAME_walk125 239 +#define FRAME_walk126 240 +#define FRAME_walk127 241 +#define FRAME_walk128 242 +#define FRAME_walk129 243 +#define FRAME_walk130 244 +#define FRAME_walk131 245 +#define FRAME_walk132 246 +#define FRAME_walk133 247 +#define FRAME_walk201 248 +#define FRAME_walk202 249 +#define FRAME_walk203 250 +#define FRAME_walk204 251 +#define FRAME_walk205 252 +#define FRAME_walk206 253 +#define FRAME_walk207 254 +#define FRAME_walk208 255 +#define FRAME_walk209 256 +#define FRAME_walk210 257 +#define FRAME_walk211 258 +#define FRAME_walk212 259 +#define FRAME_walk213 260 +#define FRAME_walk214 261 +#define FRAME_walk215 262 +#define FRAME_walk216 263 +#define FRAME_walk217 264 +#define FRAME_walk218 265 +#define FRAME_walk219 266 +#define FRAME_walk220 267 +#define FRAME_walk221 268 +#define FRAME_walk222 269 +#define FRAME_walk223 270 +#define FRAME_walk224 271 +#define FRAME_death101 272 +#define FRAME_death102 273 +#define FRAME_death103 274 +#define FRAME_death104 275 +#define FRAME_death105 276 +#define FRAME_death106 277 +#define FRAME_death107 278 +#define FRAME_death108 279 +#define FRAME_death109 280 +#define FRAME_death110 281 +#define FRAME_death111 282 +#define FRAME_death112 283 +#define FRAME_death113 284 +#define FRAME_death114 285 +#define FRAME_death115 286 +#define FRAME_death116 287 +#define FRAME_death117 288 +#define FRAME_death118 289 +#define FRAME_death119 290 +#define FRAME_death120 291 +#define FRAME_death121 292 +#define FRAME_death122 293 +#define FRAME_death123 294 +#define FRAME_death124 295 +#define FRAME_death125 296 +#define FRAME_death126 297 +#define FRAME_death127 298 +#define FRAME_death128 299 +#define FRAME_death129 300 +#define FRAME_death130 301 +#define FRAME_death131 302 +#define FRAME_death132 303 +#define FRAME_death133 304 +#define FRAME_death134 305 +#define FRAME_death135 306 +#define FRAME_death136 307 +#define FRAME_death201 308 +#define FRAME_death202 309 +#define FRAME_death203 310 +#define FRAME_death204 311 +#define FRAME_death205 312 +#define FRAME_death206 313 +#define FRAME_death207 314 +#define FRAME_death208 315 +#define FRAME_death209 316 +#define FRAME_death210 317 +#define FRAME_death211 318 +#define FRAME_death212 319 +#define FRAME_death213 320 +#define FRAME_death214 321 +#define FRAME_death215 322 +#define FRAME_death216 323 +#define FRAME_death217 324 +#define FRAME_death218 325 +#define FRAME_death219 326 +#define FRAME_death220 327 +#define FRAME_death221 328 +#define FRAME_death222 329 +#define FRAME_death223 330 +#define FRAME_death224 331 +#define FRAME_death225 332 +#define FRAME_death226 333 +#define FRAME_death227 334 +#define FRAME_death228 335 +#define FRAME_death229 336 +#define FRAME_death230 337 +#define FRAME_death231 338 +#define FRAME_death232 339 +#define FRAME_death233 340 +#define FRAME_death234 341 +#define FRAME_death235 342 +#define FRAME_death301 343 +#define FRAME_death302 344 +#define FRAME_death303 345 +#define FRAME_death304 346 +#define FRAME_death305 347 +#define FRAME_death306 348 +#define FRAME_death307 349 +#define FRAME_death308 350 +#define FRAME_death309 351 +#define FRAME_death310 352 +#define FRAME_death311 353 +#define FRAME_death312 354 +#define FRAME_death313 355 +#define FRAME_death314 356 +#define FRAME_death315 357 +#define FRAME_death316 358 +#define FRAME_death317 359 +#define FRAME_death318 360 +#define FRAME_death319 361 +#define FRAME_death320 362 +#define FRAME_death321 363 +#define FRAME_death322 364 +#define FRAME_death323 365 +#define FRAME_death324 366 +#define FRAME_death325 367 +#define FRAME_death326 368 +#define FRAME_death327 369 +#define FRAME_death328 370 +#define FRAME_death329 371 +#define FRAME_death330 372 +#define FRAME_death331 373 +#define FRAME_death332 374 +#define FRAME_death333 375 +#define FRAME_death334 376 +#define FRAME_death335 377 +#define FRAME_death336 378 +#define FRAME_death337 379 +#define FRAME_death338 380 +#define FRAME_death339 381 +#define FRAME_death340 382 +#define FRAME_death341 383 +#define FRAME_death342 384 +#define FRAME_death343 385 +#define FRAME_death344 386 +#define FRAME_death345 387 +#define FRAME_death401 388 +#define FRAME_death402 389 +#define FRAME_death403 390 +#define FRAME_death404 391 +#define FRAME_death405 392 +#define FRAME_death406 393 +#define FRAME_death407 394 +#define FRAME_death408 395 +#define FRAME_death409 396 +#define FRAME_death410 397 +#define FRAME_death411 398 +#define FRAME_death412 399 +#define FRAME_death413 400 +#define FRAME_death414 401 +#define FRAME_death415 402 +#define FRAME_death416 403 +#define FRAME_death417 404 +#define FRAME_death418 405 +#define FRAME_death419 406 +#define FRAME_death420 407 +#define FRAME_death421 408 +#define FRAME_death422 409 +#define FRAME_death423 410 +#define FRAME_death424 411 +#define FRAME_death425 412 +#define FRAME_death426 413 +#define FRAME_death427 414 +#define FRAME_death428 415 +#define FRAME_death429 416 +#define FRAME_death430 417 +#define FRAME_death431 418 +#define FRAME_death432 419 +#define FRAME_death433 420 +#define FRAME_death434 421 +#define FRAME_death435 422 +#define FRAME_death436 423 +#define FRAME_death437 424 +#define FRAME_death438 425 +#define FRAME_death439 426 +#define FRAME_death440 427 +#define FRAME_death441 428 +#define FRAME_death442 429 +#define FRAME_death443 430 +#define FRAME_death444 431 +#define FRAME_death445 432 +#define FRAME_death446 433 +#define FRAME_death447 434 +#define FRAME_death448 435 +#define FRAME_death449 436 +#define FRAME_death450 437 +#define FRAME_death451 438 +#define FRAME_death452 439 +#define FRAME_death453 440 +#define FRAME_death501 441 +#define FRAME_death502 442 +#define FRAME_death503 443 +#define FRAME_death504 444 +#define FRAME_death505 445 +#define FRAME_death506 446 +#define FRAME_death507 447 +#define FRAME_death508 448 +#define FRAME_death509 449 +#define FRAME_death510 450 +#define FRAME_death511 451 +#define FRAME_death512 452 +#define FRAME_death513 453 +#define FRAME_death514 454 +#define FRAME_death515 455 +#define FRAME_death516 456 +#define FRAME_death517 457 +#define FRAME_death518 458 +#define FRAME_death519 459 +#define FRAME_death520 460 +#define FRAME_death521 461 +#define FRAME_death522 462 +#define FRAME_death523 463 +#define FRAME_death524 464 +#define FRAME_death601 465 +#define FRAME_death602 466 +#define FRAME_death603 467 +#define FRAME_death604 468 +#define FRAME_death605 469 +#define FRAME_death606 470 +#define FRAME_death607 471 +#define FRAME_death608 472 +#define FRAME_death609 473 +#define FRAME_death610 474 + +#define MODEL_SCALE 1.200000 diff --git a/game/m_supertank.c b/game/m_supertank.c new file mode 100644 index 000000000..c1de0e8a9 --- /dev/null +++ b/game/m_supertank.c @@ -0,0 +1,717 @@ +/* +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. + +*/ +/* +============================================================================== + +SUPERTANK + +============================================================================== +*/ + +#include "g_local.h" +#include "m_supertank.h" + +qboolean visible (edict_t *self, edict_t *other); + +static int sound_pain1; +static int sound_pain2; +static int sound_pain3; +static int sound_death; +static int sound_search1; +static int sound_search2; + +static int tread_sound; + +void BossExplode (edict_t *self); + +void TreadSound (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, tread_sound, 1, ATTN_NORM, 0); +} + +void supertank_search (edict_t *self) +{ + if (random() < 0.5) + gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0); + else + gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0); +} + + +void supertank_dead (edict_t *self); +void supertankRocket (edict_t *self); +void supertankMachineGun (edict_t *self); +void supertank_reattack1(edict_t *self); + + +// +// stand +// + +mframe_t supertank_frames_stand []= +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t supertank_move_stand = {FRAME_stand_1, FRAME_stand_60, supertank_frames_stand, NULL}; + +void supertank_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &supertank_move_stand; +} + + +mframe_t supertank_frames_run [] = +{ + ai_run, 12, TreadSound, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL, + ai_run, 12, NULL +}; +mmove_t supertank_move_run = {FRAME_forwrd_1, FRAME_forwrd_18, supertank_frames_run, NULL}; + +// +// walk +// + + +mframe_t supertank_frames_forward [] = +{ + ai_walk, 4, TreadSound, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL +}; +mmove_t supertank_move_forward = {FRAME_forwrd_1, FRAME_forwrd_18, supertank_frames_forward, NULL}; + +void supertank_forward (edict_t *self) +{ + self->monsterinfo.currentmove = &supertank_move_forward; +} + +void supertank_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &supertank_move_forward; +} + +void supertank_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + self->monsterinfo.currentmove = &supertank_move_stand; + else + self->monsterinfo.currentmove = &supertank_move_run; +} + +mframe_t supertank_frames_turn_right [] = +{ + ai_move, 0, TreadSound, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t supertank_move_turn_right = {FRAME_right_1, FRAME_right_18, supertank_frames_turn_right, supertank_run}; + +mframe_t supertank_frames_turn_left [] = +{ + ai_move, 0, TreadSound, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t supertank_move_turn_left = {FRAME_left_1, FRAME_left_18, supertank_frames_turn_left, supertank_run}; + + +mframe_t supertank_frames_pain3 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t supertank_move_pain3 = {FRAME_pain3_9, FRAME_pain3_12, supertank_frames_pain3, supertank_run}; + +mframe_t supertank_frames_pain2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t supertank_move_pain2 = {FRAME_pain2_5, FRAME_pain2_8, supertank_frames_pain2, supertank_run}; + +mframe_t supertank_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t supertank_move_pain1 = {FRAME_pain1_1, FRAME_pain1_4, supertank_frames_pain1, supertank_run}; + +mframe_t supertank_frames_death1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, BossExplode +}; +mmove_t supertank_move_death = {FRAME_death_1, FRAME_death_24, supertank_frames_death1, supertank_dead}; + +mframe_t supertank_frames_backward[] = +{ + ai_walk, 0, TreadSound, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL, + ai_walk, 0, NULL +}; +mmove_t supertank_move_backward = {FRAME_backwd_1, FRAME_backwd_18, supertank_frames_backward, NULL}; + +mframe_t supertank_frames_attack4[]= +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t supertank_move_attack4 = {FRAME_attak4_1, FRAME_attak4_6, supertank_frames_attack4, supertank_run}; + +mframe_t supertank_frames_attack3[]= +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t supertank_move_attack3 = {FRAME_attak3_1, FRAME_attak3_27, supertank_frames_attack3, supertank_run}; + +mframe_t supertank_frames_attack2[]= +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, supertankRocket, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, supertankRocket, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, supertankRocket, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t supertank_move_attack2 = {FRAME_attak2_1, FRAME_attak2_27, supertank_frames_attack2, supertank_run}; + +mframe_t supertank_frames_attack1[]= +{ + ai_charge, 0, supertankMachineGun, + ai_charge, 0, supertankMachineGun, + ai_charge, 0, supertankMachineGun, + ai_charge, 0, supertankMachineGun, + ai_charge, 0, supertankMachineGun, + ai_charge, 0, supertankMachineGun, + +}; +mmove_t supertank_move_attack1 = {FRAME_attak1_1, FRAME_attak1_6, supertank_frames_attack1, supertank_reattack1}; + +mframe_t supertank_frames_end_attack1[]= +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t supertank_move_end_attack1 = {FRAME_attak1_7, FRAME_attak1_20, supertank_frames_end_attack1, supertank_run}; + + +void supertank_reattack1(edict_t *self) +{ + if (visible(self, self->enemy)) + if (random() < 0.9) + self->monsterinfo.currentmove = &supertank_move_attack1; + else + self->monsterinfo.currentmove = &supertank_move_end_attack1; + else + self->monsterinfo.currentmove = &supertank_move_end_attack1; +} + +void supertank_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + + if (self->health < (self->max_health / 2)) + self->s.skinnum = 1; + + if (level.time < self->pain_debounce_time) + return; + + // Lessen the chance of him going into his pain frames + if (damage <=25) + if (random()<0.2) + return; + + // Don't go into pain if he's firing his rockets + if (skill->value >= 2) + if ( (self->s.frame >= FRAME_attak2_1) && (self->s.frame <= FRAME_attak2_14) ) + return; + + self->pain_debounce_time = level.time + 3; + + if (skill->value == 3) + return; // no pain anims in nightmare + + if (damage <= 10) + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM,0); + self->monsterinfo.currentmove = &supertank_move_pain1; + } + else if (damage <= 25) + { + gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM,0); + self->monsterinfo.currentmove = &supertank_move_pain2; + } + else + { + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM,0); + self->monsterinfo.currentmove = &supertank_move_pain3; + } +}; + + +void supertankRocket (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + int flash_number; + + if (self->s.frame == FRAME_attak2_8) + flash_number = MZ2_SUPERTANK_ROCKET_1; + else if (self->s.frame == FRAME_attak2_11) + flash_number = MZ2_SUPERTANK_ROCKET_2; + else // (self->s.frame == FRAME_attak2_14) + flash_number = MZ2_SUPERTANK_ROCKET_3; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + + monster_fire_rocket (self, start, dir, 50, 500, flash_number); +} + +void supertankMachineGun (edict_t *self) +{ + vec3_t dir; + vec3_t vec; + vec3_t start; + vec3_t forward, right; + int flash_number; + + flash_number = MZ2_SUPERTANK_MACHINEGUN_1 + (self->s.frame - FRAME_attak1_1); + + //FIXME!!! + dir[0] = 0; + dir[1] = self->s.angles[1]; + dir[2] = 0; + + AngleVectors (dir, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + if (self->enemy) + { + VectorCopy (self->enemy->s.origin, vec); + VectorMA (vec, 0, self->enemy->velocity, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, forward); + VectorNormalize (forward); + } + + monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); +} + + +void supertank_attack(edict_t *self) +{ + vec3_t vec; + float range; + //float r; + + VectorSubtract (self->enemy->s.origin, self->s.origin, vec); + range = VectorLength (vec); + + //r = random(); + + // Attack 1 == Chaingun + // Attack 2 == Rocket Launcher + + if (range <= 160) + { + self->monsterinfo.currentmove = &supertank_move_attack1; + } + else + { // fire rockets more often at distance + if (random() < 0.3) + self->monsterinfo.currentmove = &supertank_move_attack1; + else + self->monsterinfo.currentmove = &supertank_move_attack2; + } +} + + +// +// death +// + +void supertank_dead (edict_t *self) +{ + VectorSet (self->mins, -60, -60, 0); + VectorSet (self->maxs, 60, 60, 72); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + + +void BossExplode (edict_t *self) +{ + vec3_t org; + int n; + + self->think = BossExplode; + VectorCopy (self->s.origin, org); + org[2] += 24 + (rand()&15); + switch (self->count++) + { + case 0: + org[0] -= 24; + org[1] -= 24; + break; + case 1: + org[0] += 24; + org[1] += 24; + break; + case 2: + org[0] += 24; + org[1] -= 24; + break; + case 3: + org[0] -= 24; + org[1] += 24; + break; + case 4: + org[0] -= 48; + org[1] -= 48; + break; + case 5: + org[0] += 48; + org[1] += 48; + break; + case 6: + org[0] -= 48; + org[1] += 48; + break; + case 7: + org[0] += 48; + org[1] -= 48; + break; + case 8: + self->s.sound = 0; + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", 500, GIB_ORGANIC); + for (n= 0; n < 8; n++) + ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", 500, GIB_METALLIC); + ThrowGib (self, "models/objects/gibs/chest/tris.md2", 500, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/gear/tris.md2", 500, GIB_METALLIC); + self->deadflag = DEAD_DEAD; + return; + } + + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_EXPLOSION1); + gi.WritePosition (org); + gi.multicast (self->s.origin, MULTICAST_PVS); + + self->nextthink = level.time + 0.1; +} + + +void supertank_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_NO; + self->count = 0; + self->monsterinfo.currentmove = &supertank_move_death; +} + +// +// monster_supertank +// + +/*QUAKED monster_supertank (1 .5 0) (-64 -64 0) (64 64 72) Ambush Trigger_Spawn Sight +*/ +void SP_monster_supertank (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + sound_pain1 = gi.soundindex ("bosstank/btkpain1.wav"); + sound_pain2 = gi.soundindex ("bosstank/btkpain2.wav"); + sound_pain3 = gi.soundindex ("bosstank/btkpain3.wav"); + sound_death = gi.soundindex ("bosstank/btkdeth1.wav"); + sound_search1 = gi.soundindex ("bosstank/btkunqv1.wav"); + sound_search2 = gi.soundindex ("bosstank/btkunqv2.wav"); + +// self->s.sound = gi.soundindex ("bosstank/btkengn1.wav"); + tread_sound = gi.soundindex ("bosstank/btkengn1.wav"); + + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->s.modelindex = gi.modelindex ("models/monsters/boss1/tris.md2"); + VectorSet (self->mins, -64, -64, 0); + VectorSet (self->maxs, 64, 64, 112); + + self->health = 1500; + self->gib_health = -500; + self->mass = 800; + + self->pain = supertank_pain; + self->die = supertank_die; + self->monsterinfo.stand = supertank_stand; + self->monsterinfo.walk = supertank_walk; + self->monsterinfo.run = supertank_run; + self->monsterinfo.dodge = NULL; + self->monsterinfo.attack = supertank_attack; + self->monsterinfo.search = supertank_search; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = NULL; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &supertank_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start(self); +} diff --git a/game/m_supertank.h b/game/m_supertank.h new file mode 100644 index 000000000..53f4a662c --- /dev/null +++ b/game/m_supertank.h @@ -0,0 +1,279 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/boss1/backup + +// This file generated by ModelGen - Do NOT Modify + +#define FRAME_attak1_1 0 +#define FRAME_attak1_2 1 +#define FRAME_attak1_3 2 +#define FRAME_attak1_4 3 +#define FRAME_attak1_5 4 +#define FRAME_attak1_6 5 +#define FRAME_attak1_7 6 +#define FRAME_attak1_8 7 +#define FRAME_attak1_9 8 +#define FRAME_attak1_10 9 +#define FRAME_attak1_11 10 +#define FRAME_attak1_12 11 +#define FRAME_attak1_13 12 +#define FRAME_attak1_14 13 +#define FRAME_attak1_15 14 +#define FRAME_attak1_16 15 +#define FRAME_attak1_17 16 +#define FRAME_attak1_18 17 +#define FRAME_attak1_19 18 +#define FRAME_attak1_20 19 +#define FRAME_attak2_1 20 +#define FRAME_attak2_2 21 +#define FRAME_attak2_3 22 +#define FRAME_attak2_4 23 +#define FRAME_attak2_5 24 +#define FRAME_attak2_6 25 +#define FRAME_attak2_7 26 +#define FRAME_attak2_8 27 +#define FRAME_attak2_9 28 +#define FRAME_attak2_10 29 +#define FRAME_attak2_11 30 +#define FRAME_attak2_12 31 +#define FRAME_attak2_13 32 +#define FRAME_attak2_14 33 +#define FRAME_attak2_15 34 +#define FRAME_attak2_16 35 +#define FRAME_attak2_17 36 +#define FRAME_attak2_18 37 +#define FRAME_attak2_19 38 +#define FRAME_attak2_20 39 +#define FRAME_attak2_21 40 +#define FRAME_attak2_22 41 +#define FRAME_attak2_23 42 +#define FRAME_attak2_24 43 +#define FRAME_attak2_25 44 +#define FRAME_attak2_26 45 +#define FRAME_attak2_27 46 +#define FRAME_attak3_1 47 +#define FRAME_attak3_2 48 +#define FRAME_attak3_3 49 +#define FRAME_attak3_4 50 +#define FRAME_attak3_5 51 +#define FRAME_attak3_6 52 +#define FRAME_attak3_7 53 +#define FRAME_attak3_8 54 +#define FRAME_attak3_9 55 +#define FRAME_attak3_10 56 +#define FRAME_attak3_11 57 +#define FRAME_attak3_12 58 +#define FRAME_attak3_13 59 +#define FRAME_attak3_14 60 +#define FRAME_attak3_15 61 +#define FRAME_attak3_16 62 +#define FRAME_attak3_17 63 +#define FRAME_attak3_18 64 +#define FRAME_attak3_19 65 +#define FRAME_attak3_20 66 +#define FRAME_attak3_21 67 +#define FRAME_attak3_22 68 +#define FRAME_attak3_23 69 +#define FRAME_attak3_24 70 +#define FRAME_attak3_25 71 +#define FRAME_attak3_26 72 +#define FRAME_attak3_27 73 +#define FRAME_attak4_1 74 +#define FRAME_attak4_2 75 +#define FRAME_attak4_3 76 +#define FRAME_attak4_4 77 +#define FRAME_attak4_5 78 +#define FRAME_attak4_6 79 +#define FRAME_backwd_1 80 +#define FRAME_backwd_2 81 +#define FRAME_backwd_3 82 +#define FRAME_backwd_4 83 +#define FRAME_backwd_5 84 +#define FRAME_backwd_6 85 +#define FRAME_backwd_7 86 +#define FRAME_backwd_8 87 +#define FRAME_backwd_9 88 +#define FRAME_backwd_10 89 +#define FRAME_backwd_11 90 +#define FRAME_backwd_12 91 +#define FRAME_backwd_13 92 +#define FRAME_backwd_14 93 +#define FRAME_backwd_15 94 +#define FRAME_backwd_16 95 +#define FRAME_backwd_17 96 +#define FRAME_backwd_18 97 +#define FRAME_death_1 98 +#define FRAME_death_2 99 +#define FRAME_death_3 100 +#define FRAME_death_4 101 +#define FRAME_death_5 102 +#define FRAME_death_6 103 +#define FRAME_death_7 104 +#define FRAME_death_8 105 +#define FRAME_death_9 106 +#define FRAME_death_10 107 +#define FRAME_death_11 108 +#define FRAME_death_12 109 +#define FRAME_death_13 110 +#define FRAME_death_14 111 +#define FRAME_death_15 112 +#define FRAME_death_16 113 +#define FRAME_death_17 114 +#define FRAME_death_18 115 +#define FRAME_death_19 116 +#define FRAME_death_20 117 +#define FRAME_death_21 118 +#define FRAME_death_22 119 +#define FRAME_death_23 120 +#define FRAME_death_24 121 +#define FRAME_death_31 122 +#define FRAME_death_32 123 +#define FRAME_death_33 124 +#define FRAME_death_45 125 +#define FRAME_death_46 126 +#define FRAME_death_47 127 +#define FRAME_forwrd_1 128 +#define FRAME_forwrd_2 129 +#define FRAME_forwrd_3 130 +#define FRAME_forwrd_4 131 +#define FRAME_forwrd_5 132 +#define FRAME_forwrd_6 133 +#define FRAME_forwrd_7 134 +#define FRAME_forwrd_8 135 +#define FRAME_forwrd_9 136 +#define FRAME_forwrd_10 137 +#define FRAME_forwrd_11 138 +#define FRAME_forwrd_12 139 +#define FRAME_forwrd_13 140 +#define FRAME_forwrd_14 141 +#define FRAME_forwrd_15 142 +#define FRAME_forwrd_16 143 +#define FRAME_forwrd_17 144 +#define FRAME_forwrd_18 145 +#define FRAME_left_1 146 +#define FRAME_left_2 147 +#define FRAME_left_3 148 +#define FRAME_left_4 149 +#define FRAME_left_5 150 +#define FRAME_left_6 151 +#define FRAME_left_7 152 +#define FRAME_left_8 153 +#define FRAME_left_9 154 +#define FRAME_left_10 155 +#define FRAME_left_11 156 +#define FRAME_left_12 157 +#define FRAME_left_13 158 +#define FRAME_left_14 159 +#define FRAME_left_15 160 +#define FRAME_left_16 161 +#define FRAME_left_17 162 +#define FRAME_left_18 163 +#define FRAME_pain1_1 164 +#define FRAME_pain1_2 165 +#define FRAME_pain1_3 166 +#define FRAME_pain1_4 167 +#define FRAME_pain2_5 168 +#define FRAME_pain2_6 169 +#define FRAME_pain2_7 170 +#define FRAME_pain2_8 171 +#define FRAME_pain3_9 172 +#define FRAME_pain3_10 173 +#define FRAME_pain3_11 174 +#define FRAME_pain3_12 175 +#define FRAME_right_1 176 +#define FRAME_right_2 177 +#define FRAME_right_3 178 +#define FRAME_right_4 179 +#define FRAME_right_5 180 +#define FRAME_right_6 181 +#define FRAME_right_7 182 +#define FRAME_right_8 183 +#define FRAME_right_9 184 +#define FRAME_right_10 185 +#define FRAME_right_11 186 +#define FRAME_right_12 187 +#define FRAME_right_13 188 +#define FRAME_right_14 189 +#define FRAME_right_15 190 +#define FRAME_right_16 191 +#define FRAME_right_17 192 +#define FRAME_right_18 193 +#define FRAME_stand_1 194 +#define FRAME_stand_2 195 +#define FRAME_stand_3 196 +#define FRAME_stand_4 197 +#define FRAME_stand_5 198 +#define FRAME_stand_6 199 +#define FRAME_stand_7 200 +#define FRAME_stand_8 201 +#define FRAME_stand_9 202 +#define FRAME_stand_10 203 +#define FRAME_stand_11 204 +#define FRAME_stand_12 205 +#define FRAME_stand_13 206 +#define FRAME_stand_14 207 +#define FRAME_stand_15 208 +#define FRAME_stand_16 209 +#define FRAME_stand_17 210 +#define FRAME_stand_18 211 +#define FRAME_stand_19 212 +#define FRAME_stand_20 213 +#define FRAME_stand_21 214 +#define FRAME_stand_22 215 +#define FRAME_stand_23 216 +#define FRAME_stand_24 217 +#define FRAME_stand_25 218 +#define FRAME_stand_26 219 +#define FRAME_stand_27 220 +#define FRAME_stand_28 221 +#define FRAME_stand_29 222 +#define FRAME_stand_30 223 +#define FRAME_stand_31 224 +#define FRAME_stand_32 225 +#define FRAME_stand_33 226 +#define FRAME_stand_34 227 +#define FRAME_stand_35 228 +#define FRAME_stand_36 229 +#define FRAME_stand_37 230 +#define FRAME_stand_38 231 +#define FRAME_stand_39 232 +#define FRAME_stand_40 233 +#define FRAME_stand_41 234 +#define FRAME_stand_42 235 +#define FRAME_stand_43 236 +#define FRAME_stand_44 237 +#define FRAME_stand_45 238 +#define FRAME_stand_46 239 +#define FRAME_stand_47 240 +#define FRAME_stand_48 241 +#define FRAME_stand_49 242 +#define FRAME_stand_50 243 +#define FRAME_stand_51 244 +#define FRAME_stand_52 245 +#define FRAME_stand_53 246 +#define FRAME_stand_54 247 +#define FRAME_stand_55 248 +#define FRAME_stand_56 249 +#define FRAME_stand_57 250 +#define FRAME_stand_58 251 +#define FRAME_stand_59 252 +#define FRAME_stand_60 253 + +#define MODEL_SCALE 1.000000 diff --git a/game/m_tank.c b/game/m_tank.c new file mode 100644 index 000000000..f1bccba37 --- /dev/null +++ b/game/m_tank.c @@ -0,0 +1,856 @@ +/* +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. + +*/ +/* +============================================================================== + +TANK + +============================================================================== +*/ + +#include "g_local.h" +#include "m_tank.h" + + +void tank_refire_rocket (edict_t *self); +void tank_doattack_rocket (edict_t *self); +void tank_reattack_blaster (edict_t *self); + +static int sound_thud; +static int sound_pain; +static int sound_idle; +static int sound_die; +static int sound_step; +static int sound_sight; +static int sound_windup; +static int sound_strike; + +// +// misc +// + +void tank_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + + +void tank_footstep (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0); +} + +void tank_thud (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_thud, 1, ATTN_NORM, 0); +} + +void tank_windup (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_windup, 1, ATTN_NORM, 0); +} + +void tank_idle (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); +} + + +// +// stand +// + +mframe_t tank_frames_stand []= +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL +}; +mmove_t tank_move_stand = {FRAME_stand01, FRAME_stand30, tank_frames_stand, NULL}; + +void tank_stand (edict_t *self) +{ + self->monsterinfo.currentmove = &tank_move_stand; +} + + +// +// walk +// + +void tank_walk (edict_t *self); + +mframe_t tank_frames_start_walk [] = +{ + ai_walk, 0, NULL, + ai_walk, 6, NULL, + ai_walk, 6, NULL, + ai_walk, 11, tank_footstep +}; +mmove_t tank_move_start_walk = {FRAME_walk01, FRAME_walk04, tank_frames_start_walk, tank_walk}; + +mframe_t tank_frames_walk [] = +{ + ai_walk, 4, NULL, + ai_walk, 5, NULL, + ai_walk, 3, NULL, + ai_walk, 2, NULL, + ai_walk, 5, NULL, + ai_walk, 5, NULL, + ai_walk, 4, NULL, + ai_walk, 4, tank_footstep, + ai_walk, 3, NULL, + ai_walk, 5, NULL, + ai_walk, 4, NULL, + ai_walk, 5, NULL, + ai_walk, 7, NULL, + ai_walk, 7, NULL, + ai_walk, 6, NULL, + ai_walk, 6, tank_footstep +}; +mmove_t tank_move_walk = {FRAME_walk05, FRAME_walk20, tank_frames_walk, NULL}; + +mframe_t tank_frames_stop_walk [] = +{ + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 2, NULL, + ai_walk, 2, NULL, + ai_walk, 4, tank_footstep +}; +mmove_t tank_move_stop_walk = {FRAME_walk21, FRAME_walk25, tank_frames_stop_walk, tank_stand}; + +void tank_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &tank_move_walk; +} + + +// +// run +// + +void tank_run (edict_t *self); + +mframe_t tank_frames_start_run [] = +{ + ai_run, 0, NULL, + ai_run, 6, NULL, + ai_run, 6, NULL, + ai_run, 11, tank_footstep +}; +mmove_t tank_move_start_run = {FRAME_walk01, FRAME_walk04, tank_frames_start_run, tank_run}; + +mframe_t tank_frames_run [] = +{ + ai_run, 4, NULL, + ai_run, 5, NULL, + ai_run, 3, NULL, + ai_run, 2, NULL, + ai_run, 5, NULL, + ai_run, 5, NULL, + ai_run, 4, NULL, + ai_run, 4, tank_footstep, + ai_run, 3, NULL, + ai_run, 5, NULL, + ai_run, 4, NULL, + ai_run, 5, NULL, + ai_run, 7, NULL, + ai_run, 7, NULL, + ai_run, 6, NULL, + ai_run, 6, tank_footstep +}; +mmove_t tank_move_run = {FRAME_walk05, FRAME_walk20, tank_frames_run, NULL}; + +mframe_t tank_frames_stop_run [] = +{ + ai_run, 3, NULL, + ai_run, 3, NULL, + ai_run, 2, NULL, + ai_run, 2, NULL, + ai_run, 4, tank_footstep +}; +mmove_t tank_move_stop_run = {FRAME_walk21, FRAME_walk25, tank_frames_stop_run, tank_walk}; + +void tank_run (edict_t *self) +{ + if (self->enemy && self->enemy->client) + self->monsterinfo.aiflags |= AI_BRUTAL; + else + self->monsterinfo.aiflags &= ~AI_BRUTAL; + + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + { + self->monsterinfo.currentmove = &tank_move_stand; + return; + } + + if (self->monsterinfo.currentmove == &tank_move_walk || + self->monsterinfo.currentmove == &tank_move_start_run) + { + self->monsterinfo.currentmove = &tank_move_run; + } + else + { + self->monsterinfo.currentmove = &tank_move_start_run; + } +} + +// +// pain +// + +mframe_t tank_frames_pain1 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t tank_move_pain1 = {FRAME_pain101, FRAME_pain104, tank_frames_pain1, tank_run}; + +mframe_t tank_frames_pain2 [] = +{ + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t tank_move_pain2 = {FRAME_pain201, FRAME_pain205, tank_frames_pain2, tank_run}; + +mframe_t tank_frames_pain3 [] = +{ + ai_move, -7, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 3, NULL, + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, tank_footstep +}; +mmove_t tank_move_pain3 = {FRAME_pain301, FRAME_pain316, tank_frames_pain3, tank_run}; + + +void tank_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + if (self->health < (self->max_health / 2)) + self->s.skinnum |= 1; + + if (damage <= 10) + return; + + if (level.time < self->pain_debounce_time) + return; + + if (damage <= 30) + if (random() > 0.2) + return; + + // If hard or nightmare, don't go into pain while attacking + if ( skill->value >= 2) + { + if ( (self->s.frame >= FRAME_attak301) && (self->s.frame <= FRAME_attak330) ) + return; + if ( (self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak116) ) + return; + } + + self->pain_debounce_time = level.time + 3; + gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); + + if (skill->value == 3) + return; // no pain anims in nightmare + + if (damage <= 30) + self->monsterinfo.currentmove = &tank_move_pain1; + else if (damage <= 60) + self->monsterinfo.currentmove = &tank_move_pain2; + else + self->monsterinfo.currentmove = &tank_move_pain3; +}; + + +// +// attacks +// + +void TankBlaster (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t end; + vec3_t dir; + int flash_number; + + if (self->s.frame == FRAME_attak110) + flash_number = MZ2_TANK_BLASTER_1; + else if (self->s.frame == FRAME_attak113) + flash_number = MZ2_TANK_BLASTER_2; + else // (self->s.frame == FRAME_attak116) + flash_number = MZ2_TANK_BLASTER_3; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + VectorCopy (self->enemy->s.origin, end); + end[2] += self->enemy->viewheight; + VectorSubtract (end, start, dir); + + monster_fire_blaster (self, start, dir, 30, 800, flash_number, EF_BLASTER); +} + +void TankStrike (edict_t *self) +{ + gi.sound (self, CHAN_WEAPON, sound_strike, 1, ATTN_NORM, 0); +} + +void TankRocket (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + int flash_number; + + if (self->s.frame == FRAME_attak324) + flash_number = MZ2_TANK_ROCKET_1; + else if (self->s.frame == FRAME_attak327) + flash_number = MZ2_TANK_ROCKET_2; + else // (self->s.frame == FRAME_attak330) + flash_number = MZ2_TANK_ROCKET_3; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + + monster_fire_rocket (self, start, dir, 50, 550, flash_number); +} + +void TankMachineGun (edict_t *self) +{ + vec3_t dir; + vec3_t vec; + vec3_t start; + vec3_t forward, right; + int flash_number; + + flash_number = MZ2_TANK_MACHINEGUN_1 + (self->s.frame - FRAME_attak406); + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start); + + if (self->enemy) + { + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, vec); + vectoangles (vec, vec); + dir[0] = vec[0]; + } + else + { + dir[0] = 0; + } + if (self->s.frame <= FRAME_attak415) + dir[1] = self->s.angles[1] - 8 * (self->s.frame - FRAME_attak411); + else + dir[1] = self->s.angles[1] + 8 * (self->s.frame - FRAME_attak419); + dir[2] = 0; + + AngleVectors (dir, forward, NULL, NULL); + + monster_fire_bullet (self, start, forward, 20, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number); +} + + +mframe_t tank_frames_attack_blast [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, -1, NULL, + ai_charge, -2, NULL, + ai_charge, -1, NULL, + ai_charge, -1, NULL, + ai_charge, 0, NULL, + ai_charge, 0, TankBlaster, // 10 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, TankBlaster, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, TankBlaster // 16 +}; +mmove_t tank_move_attack_blast = {FRAME_attak101, FRAME_attak116, tank_frames_attack_blast, tank_reattack_blaster}; + +mframe_t tank_frames_reattack_blast [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, TankBlaster, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, TankBlaster // 16 +}; +mmove_t tank_move_reattack_blast = {FRAME_attak111, FRAME_attak116, tank_frames_reattack_blast, tank_reattack_blaster}; + +mframe_t tank_frames_attack_post_blast [] = +{ + ai_move, 0, NULL, // 17 + ai_move, 0, NULL, + ai_move, 2, NULL, + ai_move, 3, NULL, + ai_move, 2, NULL, + ai_move, -2, tank_footstep // 22 +}; +mmove_t tank_move_attack_post_blast = {FRAME_attak117, FRAME_attak122, tank_frames_attack_post_blast, tank_run}; + +void tank_reattack_blaster (edict_t *self) +{ + if (skill->value >= 2) + if (visible (self, self->enemy)) + if (self->enemy->health > 0) + if (random() <= 0.6) + { + self->monsterinfo.currentmove = &tank_move_reattack_blast; + return; + } + self->monsterinfo.currentmove = &tank_move_attack_post_blast; +} + + +void tank_poststrike (edict_t *self) +{ + self->enemy = NULL; + tank_run (self); +} + +mframe_t tank_frames_attack_strike [] = +{ + ai_move, 3, NULL, + ai_move, 2, NULL, + ai_move, 2, NULL, + ai_move, 1, NULL, + ai_move, 6, NULL, + ai_move, 7, NULL, + ai_move, 9, tank_footstep, + ai_move, 2, NULL, + ai_move, 1, NULL, + ai_move, 2, NULL, + ai_move, 2, tank_footstep, + ai_move, 2, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -2, NULL, + ai_move, -2, NULL, + ai_move, 0, tank_windup, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, TankStrike, + ai_move, 0, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -1, NULL, + ai_move, -3, NULL, + ai_move, -10, NULL, + ai_move, -10, NULL, + ai_move, -2, NULL, + ai_move, -3, NULL, + ai_move, -2, tank_footstep +}; +mmove_t tank_move_attack_strike = {FRAME_attak201, FRAME_attak238, tank_frames_attack_strike, tank_poststrike}; + +mframe_t tank_frames_attack_pre_rocket [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 10 + + ai_charge, 0, NULL, + ai_charge, 1, NULL, + ai_charge, 2, NULL, + ai_charge, 7, NULL, + ai_charge, 7, NULL, + ai_charge, 7, tank_footstep, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 20 + + ai_charge, -3, NULL +}; +mmove_t tank_move_attack_pre_rocket = {FRAME_attak301, FRAME_attak321, tank_frames_attack_pre_rocket, tank_doattack_rocket}; + +mframe_t tank_frames_attack_fire_rocket [] = +{ + ai_charge, -3, NULL, // Loop Start 22 + ai_charge, 0, NULL, + ai_charge, 0, TankRocket, // 24 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, TankRocket, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, -1, TankRocket // 30 Loop End +}; +mmove_t tank_move_attack_fire_rocket = {FRAME_attak322, FRAME_attak330, tank_frames_attack_fire_rocket, tank_refire_rocket}; + +mframe_t tank_frames_attack_post_rocket [] = +{ + ai_charge, 0, NULL, // 31 + ai_charge, -1, NULL, + ai_charge, -1, NULL, + ai_charge, 0, NULL, + ai_charge, 2, NULL, + ai_charge, 3, NULL, + ai_charge, 4, NULL, + ai_charge, 2, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 40 + + ai_charge, 0, NULL, + ai_charge, -9, NULL, + ai_charge, -8, NULL, + ai_charge, -7, NULL, + ai_charge, -1, NULL, + ai_charge, -1, tank_footstep, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 50 + + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t tank_move_attack_post_rocket = {FRAME_attak331, FRAME_attak353, tank_frames_attack_post_rocket, tank_run}; + +mframe_t tank_frames_attack_chain [] = +{ + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + NULL, 0, TankMachineGun, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL +}; +mmove_t tank_move_attack_chain = {FRAME_attak401, FRAME_attak429, tank_frames_attack_chain, tank_run}; + +void tank_refire_rocket (edict_t *self) +{ + // Only on hard or nightmare + if ( skill->value >= 2 ) + if (self->enemy->health > 0) + if (visible(self, self->enemy) ) + if (random() <= 0.4) + { + self->monsterinfo.currentmove = &tank_move_attack_fire_rocket; + return; + } + self->monsterinfo.currentmove = &tank_move_attack_post_rocket; +} + +void tank_doattack_rocket (edict_t *self) +{ + self->monsterinfo.currentmove = &tank_move_attack_fire_rocket; +} + +void tank_attack(edict_t *self) +{ + vec3_t vec; + float range; + float r; + + if (self->enemy->health < 0) + { + self->monsterinfo.currentmove = &tank_move_attack_strike; + self->monsterinfo.aiflags &= ~AI_BRUTAL; + return; + } + + VectorSubtract (self->enemy->s.origin, self->s.origin, vec); + range = VectorLength (vec); + + r = random(); + + if (range <= 125) + { + if (r < 0.4) + self->monsterinfo.currentmove = &tank_move_attack_chain; + else + self->monsterinfo.currentmove = &tank_move_attack_blast; + } + else if (range <= 250) + { + if (r < 0.5) + self->monsterinfo.currentmove = &tank_move_attack_chain; + else + self->monsterinfo.currentmove = &tank_move_attack_blast; + } + else + { + if (r < 0.33) + self->monsterinfo.currentmove = &tank_move_attack_chain; + else if (r < 0.66) + { + self->monsterinfo.currentmove = &tank_move_attack_pre_rocket; + self->pain_debounce_time = level.time + 5.0; // no pain for a while + } + else + self->monsterinfo.currentmove = &tank_move_attack_blast; + } +} + + +// +// death +// + +void tank_dead (edict_t *self) +{ + VectorSet (self->mins, -16, -16, -16); + VectorSet (self->maxs, 16, 16, -0); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + +mframe_t tank_frames_death1 [] = +{ + ai_move, -7, NULL, + ai_move, -2, NULL, + ai_move, -2, NULL, + ai_move, 1, NULL, + ai_move, 3, NULL, + ai_move, 6, NULL, + ai_move, 1, NULL, + ai_move, 1, NULL, + ai_move, 2, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -2, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -3, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, -4, NULL, + ai_move, -6, NULL, + ai_move, -4, NULL, + ai_move, -5, NULL, + ai_move, -7, NULL, + ai_move, -15, tank_thud, + ai_move, -5, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL +}; +mmove_t tank_move_death = {FRAME_death101, FRAME_death132, tank_frames_death1, tank_dead}; + +void tank_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + +// check for gib + if (self->health <= self->gib_health) + { + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 1 /*4*/; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC); + ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC); + ThrowHead (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0); + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + + self->monsterinfo.currentmove = &tank_move_death; + +} + + +// +// monster_tank +// + +/*QUAKED monster_tank (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight +*/ +/*QUAKED monster_tank_commander (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight +*/ +void SP_monster_tank (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + self->s.modelindex = gi.modelindex ("models/monsters/tank/tris.md2"); + VectorSet (self->mins, -32, -32, -16); + VectorSet (self->maxs, 32, 32, 72); + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + + sound_pain = gi.soundindex ("tank/tnkpain2.wav"); + sound_thud = gi.soundindex ("tank/tnkdeth2.wav"); + sound_idle = gi.soundindex ("tank/tnkidle1.wav"); + sound_die = gi.soundindex ("tank/death.wav"); + sound_step = gi.soundindex ("tank/step.wav"); + sound_windup = gi.soundindex ("tank/tnkatck4.wav"); + sound_strike = gi.soundindex ("tank/tnkatck5.wav"); + sound_sight = gi.soundindex ("tank/sight1.wav"); + + gi.soundindex ("tank/tnkatck1.wav"); + gi.soundindex ("tank/tnkatk2a.wav"); + gi.soundindex ("tank/tnkatk2b.wav"); + gi.soundindex ("tank/tnkatk2c.wav"); + gi.soundindex ("tank/tnkatk2d.wav"); + gi.soundindex ("tank/tnkatk2e.wav"); + gi.soundindex ("tank/tnkatck3.wav"); + + if (strcmp(self->classname, "monster_tank_commander") == 0) + { + self->health = 1000; + self->gib_health = -225; + } + else + { + self->health = 750; + self->gib_health = -200; + } + + self->mass = 500; + + self->pain = tank_pain; + self->die = tank_die; + self->monsterinfo.stand = tank_stand; + self->monsterinfo.walk = tank_walk; + self->monsterinfo.run = tank_run; + self->monsterinfo.dodge = NULL; + self->monsterinfo.attack = tank_attack; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = tank_sight; + self->monsterinfo.idle = tank_idle; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &tank_move_stand; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start(self); + + if (strcmp(self->classname, "monster_tank_commander") == 0) + self->s.skinnum = 2; +} diff --git a/game/m_tank.h b/game/m_tank.h new file mode 100644 index 000000000..284a5be23 --- /dev/null +++ b/game/m_tank.h @@ -0,0 +1,319 @@ +/* +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. + +*/ +// G:\quake2\baseq2\models/monsters/tank + +// This file generated by qdata - Do NOT Modify + +#define FRAME_stand01 0 +#define FRAME_stand02 1 +#define FRAME_stand03 2 +#define FRAME_stand04 3 +#define FRAME_stand05 4 +#define FRAME_stand06 5 +#define FRAME_stand07 6 +#define FRAME_stand08 7 +#define FRAME_stand09 8 +#define FRAME_stand10 9 +#define FRAME_stand11 10 +#define FRAME_stand12 11 +#define FRAME_stand13 12 +#define FRAME_stand14 13 +#define FRAME_stand15 14 +#define FRAME_stand16 15 +#define FRAME_stand17 16 +#define FRAME_stand18 17 +#define FRAME_stand19 18 +#define FRAME_stand20 19 +#define FRAME_stand21 20 +#define FRAME_stand22 21 +#define FRAME_stand23 22 +#define FRAME_stand24 23 +#define FRAME_stand25 24 +#define FRAME_stand26 25 +#define FRAME_stand27 26 +#define FRAME_stand28 27 +#define FRAME_stand29 28 +#define FRAME_stand30 29 +#define FRAME_walk01 30 +#define FRAME_walk02 31 +#define FRAME_walk03 32 +#define FRAME_walk04 33 +#define FRAME_walk05 34 +#define FRAME_walk06 35 +#define FRAME_walk07 36 +#define FRAME_walk08 37 +#define FRAME_walk09 38 +#define FRAME_walk10 39 +#define FRAME_walk11 40 +#define FRAME_walk12 41 +#define FRAME_walk13 42 +#define FRAME_walk14 43 +#define FRAME_walk15 44 +#define FRAME_walk16 45 +#define FRAME_walk17 46 +#define FRAME_walk18 47 +#define FRAME_walk19 48 +#define FRAME_walk20 49 +#define FRAME_walk21 50 +#define FRAME_walk22 51 +#define FRAME_walk23 52 +#define FRAME_walk24 53 +#define FRAME_walk25 54 +#define FRAME_attak101 55 +#define FRAME_attak102 56 +#define FRAME_attak103 57 +#define FRAME_attak104 58 +#define FRAME_attak105 59 +#define FRAME_attak106 60 +#define FRAME_attak107 61 +#define FRAME_attak108 62 +#define FRAME_attak109 63 +#define FRAME_attak110 64 +#define FRAME_attak111 65 +#define FRAME_attak112 66 +#define FRAME_attak113 67 +#define FRAME_attak114 68 +#define FRAME_attak115 69 +#define FRAME_attak116 70 +#define FRAME_attak117 71 +#define FRAME_attak118 72 +#define FRAME_attak119 73 +#define FRAME_attak120 74 +#define FRAME_attak121 75 +#define FRAME_attak122 76 +#define FRAME_attak201 77 +#define FRAME_attak202 78 +#define FRAME_attak203 79 +#define FRAME_attak204 80 +#define FRAME_attak205 81 +#define FRAME_attak206 82 +#define FRAME_attak207 83 +#define FRAME_attak208 84 +#define FRAME_attak209 85 +#define FRAME_attak210 86 +#define FRAME_attak211 87 +#define FRAME_attak212 88 +#define FRAME_attak213 89 +#define FRAME_attak214 90 +#define FRAME_attak215 91 +#define FRAME_attak216 92 +#define FRAME_attak217 93 +#define FRAME_attak218 94 +#define FRAME_attak219 95 +#define FRAME_attak220 96 +#define FRAME_attak221 97 +#define FRAME_attak222 98 +#define FRAME_attak223 99 +#define FRAME_attak224 100 +#define FRAME_attak225 101 +#define FRAME_attak226 102 +#define FRAME_attak227 103 +#define FRAME_attak228 104 +#define FRAME_attak229 105 +#define FRAME_attak230 106 +#define FRAME_attak231 107 +#define FRAME_attak232 108 +#define FRAME_attak233 109 +#define FRAME_attak234 110 +#define FRAME_attak235 111 +#define FRAME_attak236 112 +#define FRAME_attak237 113 +#define FRAME_attak238 114 +#define FRAME_attak301 115 +#define FRAME_attak302 116 +#define FRAME_attak303 117 +#define FRAME_attak304 118 +#define FRAME_attak305 119 +#define FRAME_attak306 120 +#define FRAME_attak307 121 +#define FRAME_attak308 122 +#define FRAME_attak309 123 +#define FRAME_attak310 124 +#define FRAME_attak311 125 +#define FRAME_attak312 126 +#define FRAME_attak313 127 +#define FRAME_attak314 128 +#define FRAME_attak315 129 +#define FRAME_attak316 130 +#define FRAME_attak317 131 +#define FRAME_attak318 132 +#define FRAME_attak319 133 +#define FRAME_attak320 134 +#define FRAME_attak321 135 +#define FRAME_attak322 136 +#define FRAME_attak323 137 +#define FRAME_attak324 138 +#define FRAME_attak325 139 +#define FRAME_attak326 140 +#define FRAME_attak327 141 +#define FRAME_attak328 142 +#define FRAME_attak329 143 +#define FRAME_attak330 144 +#define FRAME_attak331 145 +#define FRAME_attak332 146 +#define FRAME_attak333 147 +#define FRAME_attak334 148 +#define FRAME_attak335 149 +#define FRAME_attak336 150 +#define FRAME_attak337 151 +#define FRAME_attak338 152 +#define FRAME_attak339 153 +#define FRAME_attak340 154 +#define FRAME_attak341 155 +#define FRAME_attak342 156 +#define FRAME_attak343 157 +#define FRAME_attak344 158 +#define FRAME_attak345 159 +#define FRAME_attak346 160 +#define FRAME_attak347 161 +#define FRAME_attak348 162 +#define FRAME_attak349 163 +#define FRAME_attak350 164 +#define FRAME_attak351 165 +#define FRAME_attak352 166 +#define FRAME_attak353 167 +#define FRAME_attak401 168 +#define FRAME_attak402 169 +#define FRAME_attak403 170 +#define FRAME_attak404 171 +#define FRAME_attak405 172 +#define FRAME_attak406 173 +#define FRAME_attak407 174 +#define FRAME_attak408 175 +#define FRAME_attak409 176 +#define FRAME_attak410 177 +#define FRAME_attak411 178 +#define FRAME_attak412 179 +#define FRAME_attak413 180 +#define FRAME_attak414 181 +#define FRAME_attak415 182 +#define FRAME_attak416 183 +#define FRAME_attak417 184 +#define FRAME_attak418 185 +#define FRAME_attak419 186 +#define FRAME_attak420 187 +#define FRAME_attak421 188 +#define FRAME_attak422 189 +#define FRAME_attak423 190 +#define FRAME_attak424 191 +#define FRAME_attak425 192 +#define FRAME_attak426 193 +#define FRAME_attak427 194 +#define FRAME_attak428 195 +#define FRAME_attak429 196 +#define FRAME_pain101 197 +#define FRAME_pain102 198 +#define FRAME_pain103 199 +#define FRAME_pain104 200 +#define FRAME_pain201 201 +#define FRAME_pain202 202 +#define FRAME_pain203 203 +#define FRAME_pain204 204 +#define FRAME_pain205 205 +#define FRAME_pain301 206 +#define FRAME_pain302 207 +#define FRAME_pain303 208 +#define FRAME_pain304 209 +#define FRAME_pain305 210 +#define FRAME_pain306 211 +#define FRAME_pain307 212 +#define FRAME_pain308 213 +#define FRAME_pain309 214 +#define FRAME_pain310 215 +#define FRAME_pain311 216 +#define FRAME_pain312 217 +#define FRAME_pain313 218 +#define FRAME_pain314 219 +#define FRAME_pain315 220 +#define FRAME_pain316 221 +#define FRAME_death101 222 +#define FRAME_death102 223 +#define FRAME_death103 224 +#define FRAME_death104 225 +#define FRAME_death105 226 +#define FRAME_death106 227 +#define FRAME_death107 228 +#define FRAME_death108 229 +#define FRAME_death109 230 +#define FRAME_death110 231 +#define FRAME_death111 232 +#define FRAME_death112 233 +#define FRAME_death113 234 +#define FRAME_death114 235 +#define FRAME_death115 236 +#define FRAME_death116 237 +#define FRAME_death117 238 +#define FRAME_death118 239 +#define FRAME_death119 240 +#define FRAME_death120 241 +#define FRAME_death121 242 +#define FRAME_death122 243 +#define FRAME_death123 244 +#define FRAME_death124 245 +#define FRAME_death125 246 +#define FRAME_death126 247 +#define FRAME_death127 248 +#define FRAME_death128 249 +#define FRAME_death129 250 +#define FRAME_death130 251 +#define FRAME_death131 252 +#define FRAME_death132 253 +#define FRAME_recln101 254 +#define FRAME_recln102 255 +#define FRAME_recln103 256 +#define FRAME_recln104 257 +#define FRAME_recln105 258 +#define FRAME_recln106 259 +#define FRAME_recln107 260 +#define FRAME_recln108 261 +#define FRAME_recln109 262 +#define FRAME_recln110 263 +#define FRAME_recln111 264 +#define FRAME_recln112 265 +#define FRAME_recln113 266 +#define FRAME_recln114 267 +#define FRAME_recln115 268 +#define FRAME_recln116 269 +#define FRAME_recln117 270 +#define FRAME_recln118 271 +#define FRAME_recln119 272 +#define FRAME_recln120 273 +#define FRAME_recln121 274 +#define FRAME_recln122 275 +#define FRAME_recln123 276 +#define FRAME_recln124 277 +#define FRAME_recln125 278 +#define FRAME_recln126 279 +#define FRAME_recln127 280 +#define FRAME_recln128 281 +#define FRAME_recln129 282 +#define FRAME_recln130 283 +#define FRAME_recln131 284 +#define FRAME_recln132 285 +#define FRAME_recln133 286 +#define FRAME_recln134 287 +#define FRAME_recln135 288 +#define FRAME_recln136 289 +#define FRAME_recln137 290 +#define FRAME_recln138 291 +#define FRAME_recln139 292 +#define FRAME_recln140 293 + +#define MODEL_SCALE 1.000000 diff --git a/game/p_client.c b/game/p_client.c new file mode 100644 index 000000000..80e444d2f --- /dev/null +++ b/game/p_client.c @@ -0,0 +1,1805 @@ +/* +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. + +*/ +#include "g_local.h" +#include "m_player.h" + +void ClientUserinfoChanged (edict_t *ent, char *userinfo); + +void SP_misc_teleporter_dest (edict_t *ent); + +// +// Gross, ugly, disgustuing hack section +// + +// this function is an ugly as hell hack to fix some map flaws +// +// the coop spawn spots on some maps are SNAFU. There are coop spots +// with the wrong targetname as well as spots with no name at all +// +// we use carnal knowledge of the maps to fix the coop spot targetnames to match +// that of the nearest named single player spot + +static void SP_FixCoopSpots (edict_t *self) +{ + edict_t *spot; + vec3_t d; + + spot = NULL; + + while(1) + { + spot = G_Find(spot, FOFS(classname), "info_player_start"); + if (!spot) + return; + if (!spot->targetname) + continue; + VectorSubtract(self->s.origin, spot->s.origin, d); + if (VectorLength(d) < 384) + { + if ((!self->targetname) || Q_stricmp(self->targetname, spot->targetname) != 0) + { +// gi.dprintf("FixCoopSpots changed %s at %s targetname from %s to %s\n", self->classname, vtos(self->s.origin), self->targetname, spot->targetname); + self->targetname = spot->targetname; + } + return; + } + } +} + +// now if that one wasn't ugly enough for you then try this one on for size +// some maps don't have any coop spots at all, so we need to create them +// where they should have been + +static void SP_CreateCoopSpots (edict_t *self) +{ + edict_t *spot; + + if(Q_stricmp(level.mapname, "security") == 0) + { + spot = G_Spawn(); + spot->classname = "info_player_coop"; + spot->s.origin[0] = 188 - 64; + spot->s.origin[1] = -164; + spot->s.origin[2] = 80; + spot->targetname = "jail3"; + spot->s.angles[1] = 90; + + spot = G_Spawn(); + spot->classname = "info_player_coop"; + spot->s.origin[0] = 188 + 64; + spot->s.origin[1] = -164; + spot->s.origin[2] = 80; + spot->targetname = "jail3"; + spot->s.angles[1] = 90; + + spot = G_Spawn(); + spot->classname = "info_player_coop"; + spot->s.origin[0] = 188 + 128; + spot->s.origin[1] = -164; + spot->s.origin[2] = 80; + spot->targetname = "jail3"; + spot->s.angles[1] = 90; + + return; + } +} + + +/*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 32) +The normal starting point for a level. +*/ +void SP_info_player_start(edict_t *self) +{ + if (!coop->value) + return; + if(Q_stricmp(level.mapname, "security") == 0) + { + // invoke one of our gross, ugly, disgusting hacks + self->think = SP_CreateCoopSpots; + self->nextthink = level.time + FRAMETIME; + } +} + +/*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 32) +potential spawning position for deathmatch games +*/ +void SP_info_player_deathmatch(edict_t *self) +{ + if (!deathmatch->value) + { + G_FreeEdict (self); + return; + } + SP_misc_teleporter_dest (self); +} + +/*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 32) +potential spawning position for coop games +*/ + +void SP_info_player_coop(edict_t *self) +{ + if (!coop->value) + { + G_FreeEdict (self); + return; + } + + if((Q_stricmp(level.mapname, "jail2") == 0) || + (Q_stricmp(level.mapname, "jail4") == 0) || + (Q_stricmp(level.mapname, "mine1") == 0) || + (Q_stricmp(level.mapname, "mine2") == 0) || + (Q_stricmp(level.mapname, "mine3") == 0) || + (Q_stricmp(level.mapname, "mine4") == 0) || + (Q_stricmp(level.mapname, "lab") == 0) || + (Q_stricmp(level.mapname, "boss1") == 0) || + (Q_stricmp(level.mapname, "fact3") == 0) || + (Q_stricmp(level.mapname, "biggun") == 0) || + (Q_stricmp(level.mapname, "space") == 0) || + (Q_stricmp(level.mapname, "command") == 0) || + (Q_stricmp(level.mapname, "power2") == 0) || + (Q_stricmp(level.mapname, "strike") == 0)) + { + // invoke one of our gross, ugly, disgusting hacks + self->think = SP_FixCoopSpots; + self->nextthink = level.time + FRAMETIME; + } +} + + +/*QUAKED info_player_intermission (1 0 1) (-16 -16 -24) (16 16 32) +The deathmatch intermission point will be at one of these +Use 'angles' instead of 'angle', so you can set pitch or roll as well as yaw. 'pitch yaw roll' +*/ +void SP_info_player_intermission(void) +{ +} + + +//======================================================================= + + +void player_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + // player pain is handled at the end of the frame in P_DamageFeedback +} + + +qboolean IsFemale (edict_t *ent) +{ + char *info; + + if (!ent->client) + return false; + + info = Info_ValueForKey (ent->client->pers.userinfo, "gender"); + if (info[0] == 'f' || info[0] == 'F') + return true; + return false; +} + +qboolean IsNeutral (edict_t *ent) +{ + char *info; + + if (!ent->client) + return false; + + info = Info_ValueForKey (ent->client->pers.userinfo, "gender"); + if (info[0] != 'f' && info[0] != 'F' && info[0] != 'm' && info[0] != 'M') + return true; + return false; +} + +void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker) +{ + int mod; + char *message; + char *message2; + qboolean ff; + + if (coop->value && attacker->client) + meansOfDeath |= MOD_FRIENDLY_FIRE; + + if (deathmatch->value || coop->value) + { + ff = meansOfDeath & MOD_FRIENDLY_FIRE; + mod = meansOfDeath & ~MOD_FRIENDLY_FIRE; + message = NULL; + message2 = ""; + + switch (mod) + { + case MOD_SUICIDE: + message = "suicides"; + break; + case MOD_FALLING: + message = "cratered"; + break; + case MOD_CRUSH: + message = "was squished"; + break; + case MOD_WATER: + message = "sank like a rock"; + break; + case MOD_SLIME: + message = "melted"; + break; + case MOD_LAVA: + message = "does a back flip into the lava"; + break; + case MOD_EXPLOSIVE: + case MOD_BARREL: + message = "blew up"; + break; + case MOD_EXIT: + message = "found a way out"; + break; + case MOD_TARGET_LASER: + message = "saw the light"; + break; + case MOD_TARGET_BLASTER: + message = "got blasted"; + break; + case MOD_BOMB: + case MOD_SPLASH: + case MOD_TRIGGER_HURT: + message = "was in the wrong place"; + break; + } + if (attacker == self) + { + switch (mod) + { + case MOD_HELD_GRENADE: + message = "tried to put the pin back in"; + break; + case MOD_HG_SPLASH: + case MOD_G_SPLASH: + if (IsNeutral(self)) + message = "tripped on its own grenade"; + else if (IsFemale(self)) + message = "tripped on her own grenade"; + else + message = "tripped on his own grenade"; + break; + case MOD_R_SPLASH: + if (IsNeutral(self)) + message = "blew itself up"; + else if (IsFemale(self)) + message = "blew herself up"; + else + message = "blew himself up"; + break; + case MOD_BFG_BLAST: + message = "should have used a smaller gun"; + break; + default: + if (IsNeutral(self)) + message = "killed itself"; + else if (IsFemale(self)) + message = "killed herself"; + else + message = "killed himself"; + break; + } + } + if (message) + { + gi.bprintf (PRINT_MEDIUM, "%s %s.\n", self->client->pers.netname, message); + if (deathmatch->value) + self->client->resp.score--; + self->enemy = NULL; + return; + } + + self->enemy = attacker; + if (attacker && attacker->client) + { + switch (mod) + { + case MOD_BLASTER: + message = "was blasted by"; + break; + case MOD_SHOTGUN: + message = "was gunned down by"; + break; + case MOD_SSHOTGUN: + message = "was blown away by"; + message2 = "'s super shotgun"; + break; + case MOD_MACHINEGUN: + message = "was machinegunned by"; + break; + case MOD_CHAINGUN: + message = "was cut in half by"; + message2 = "'s chaingun"; + break; + case MOD_GRENADE: + message = "was popped by"; + message2 = "'s grenade"; + break; + case MOD_G_SPLASH: + message = "was shredded by"; + message2 = "'s shrapnel"; + break; + case MOD_ROCKET: + message = "ate"; + message2 = "'s rocket"; + break; + case MOD_R_SPLASH: + message = "almost dodged"; + message2 = "'s rocket"; + break; + case MOD_HYPERBLASTER: + message = "was melted by"; + message2 = "'s hyperblaster"; + break; + case MOD_RAILGUN: + message = "was railed by"; + break; + case MOD_BFG_LASER: + message = "saw the pretty lights from"; + message2 = "'s BFG"; + break; + case MOD_BFG_BLAST: + message = "was disintegrated by"; + message2 = "'s BFG blast"; + break; + case MOD_BFG_EFFECT: + message = "couldn't hide from"; + message2 = "'s BFG"; + break; + case MOD_HANDGRENADE: + message = "caught"; + message2 = "'s handgrenade"; + break; + case MOD_HG_SPLASH: + message = "didn't see"; + message2 = "'s handgrenade"; + break; + case MOD_HELD_GRENADE: + message = "feels"; + message2 = "'s pain"; + break; + case MOD_TELEFRAG: + message = "tried to invade"; + message2 = "'s personal space"; + break; + } + if (message) + { + gi.bprintf (PRINT_MEDIUM,"%s %s %s%s\n", self->client->pers.netname, message, attacker->client->pers.netname, message2); + if (deathmatch->value) + { + if (ff) + attacker->client->resp.score--; + else + attacker->client->resp.score++; + } + return; + } + } + } + + gi.bprintf (PRINT_MEDIUM,"%s died.\n", self->client->pers.netname); + if (deathmatch->value) + self->client->resp.score--; +} + + +void Touch_Item (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf); + +void TossClientWeapon (edict_t *self) +{ + gitem_t *item; + edict_t *drop; + qboolean quad; + float spread; + + if (!deathmatch->value) + return; + + item = self->client->pers.weapon; + if (! self->client->pers.inventory[self->client->ammo_index] ) + item = NULL; + if (item && (strcmp (item->pickup_name, "Blaster") == 0)) + item = NULL; + + if (!((int)(dmflags->value) & DF_QUAD_DROP)) + quad = false; + else + quad = (self->client->quad_framenum > (level.framenum + 10)); + + if (item && quad) + spread = 22.5; + else + spread = 0.0; + + if (item) + { + self->client->v_angle[YAW] -= spread; + drop = Drop_Item (self, item); + self->client->v_angle[YAW] += spread; + drop->spawnflags = DROPPED_PLAYER_ITEM; + } + + if (quad) + { + self->client->v_angle[YAW] += spread; + drop = Drop_Item (self, FindItemByClassname ("item_quad")); + self->client->v_angle[YAW] -= spread; + drop->spawnflags |= DROPPED_PLAYER_ITEM; + + drop->touch = Touch_Item; + drop->nextthink = level.time + (self->client->quad_framenum - level.framenum) * FRAMETIME; + drop->think = G_FreeEdict; + } +} + + +/* +================== +LookAtKiller +================== +*/ +void LookAtKiller (edict_t *self, edict_t *inflictor, edict_t *attacker) +{ + vec3_t dir; + + if (attacker && attacker != world && attacker != self) + { + VectorSubtract (attacker->s.origin, self->s.origin, dir); + } + else if (inflictor && inflictor != world && inflictor != self) + { + VectorSubtract (inflictor->s.origin, self->s.origin, dir); + } + else + { + self->client->killer_yaw = self->s.angles[YAW]; + return; + } + + if (dir[0]) + self->client->killer_yaw = 180/M_PI*atan2(dir[1], dir[0]); + else { + self->client->killer_yaw = 0; + if (dir[1] > 0) + self->client->killer_yaw = 90; + else if (dir[1] < 0) + self->client->killer_yaw = -90; + } + if (self->client->killer_yaw < 0) + self->client->killer_yaw += 360; + + +} + +/* +================== +player_die +================== +*/ +void player_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + + VectorClear (self->avelocity); + + self->takedamage = DAMAGE_YES; + self->movetype = MOVETYPE_TOSS; + + self->s.modelindex2 = 0; // remove linked weapon model + + self->s.angles[0] = 0; + self->s.angles[2] = 0; + + self->s.sound = 0; + self->client->weapon_sound = 0; + + self->maxs[2] = -8; + +// self->solid = SOLID_NOT; + self->svflags |= SVF_DEADMONSTER; + + if (!self->deadflag) + { + self->client->respawn_time = level.time + 1.0; + LookAtKiller (self, inflictor, attacker); + self->client->ps.pmove.pm_type = PM_DEAD; + ClientObituary (self, inflictor, attacker); + TossClientWeapon (self); + if (deathmatch->value) + Cmd_Help_f (self); // show scores + + // clear inventory + // this is kind of ugly, but it's how we want to handle keys in coop + for (n = 0; n < game.num_items; n++) + { + if (coop->value && itemlist[n].flags & IT_KEY) + self->client->resp.coop_respawn.inventory[n] = self->client->pers.inventory[n]; + self->client->pers.inventory[n] = 0; + } + } + + // remove powerups + self->client->quad_framenum = 0; + self->client->invincible_framenum = 0; + self->client->breather_framenum = 0; + self->client->enviro_framenum = 0; + self->flags &= ~FL_POWER_ARMOR; + + if (self->health < -40) + { // gib + gi.sound (self, CHAN_BODY, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + ThrowClientHead (self, damage); + + self->takedamage = DAMAGE_NO; + } + else + { // normal death + if (!self->deadflag) + { + static int i; + + i = (i+1)%3; + // start a death animation + self->client->anim_priority = ANIM_DEATH; + if (self->client->ps.pmove.pm_flags & PMF_DUCKED) + { + self->s.frame = FRAME_crdeath1-1; + self->client->anim_end = FRAME_crdeath5; + } + else switch (i) + { + case 0: + self->s.frame = FRAME_death101-1; + self->client->anim_end = FRAME_death106; + break; + case 1: + self->s.frame = FRAME_death201-1; + self->client->anim_end = FRAME_death206; + break; + case 2: + self->s.frame = FRAME_death301-1; + self->client->anim_end = FRAME_death308; + break; + } + gi.sound (self, CHAN_VOICE, gi.soundindex(va("*death%i.wav", (rand()%4)+1)), 1, ATTN_NORM, 0); + } + } + + self->deadflag = DEAD_DEAD; + + gi.linkentity (self); +} + +//======================================================================= + +/* +============== +InitClientPersistant + +This is only called when the game first initializes in single player, +but is called after each death and level change in deathmatch +============== +*/ +void InitClientPersistant (gclient_t *client) +{ + gitem_t *item; + + memset (&client->pers, 0, sizeof(client->pers)); + + item = FindItem("Blaster"); + client->pers.selected_item = ITEM_INDEX(item); + client->pers.inventory[client->pers.selected_item] = 1; + + client->pers.weapon = item; + + client->pers.health = 100; + client->pers.max_health = 100; + + client->pers.max_bullets = 200; + client->pers.max_shells = 100; + client->pers.max_rockets = 50; + client->pers.max_grenades = 50; + client->pers.max_cells = 200; + client->pers.max_slugs = 50; + + client->pers.connected = true; +} + + +void InitClientResp (gclient_t *client) +{ + memset (&client->resp, 0, sizeof(client->resp)); + client->resp.enterframe = level.framenum; + client->resp.coop_respawn = client->pers; +} + +/* +================== +SaveClientData + +Some information that should be persistant, like health, +is still stored in the edict structure, so it needs to +be mirrored out to the client structure before all the +edicts are wiped. +================== +*/ +void SaveClientData (void) +{ + int i; + edict_t *ent; + + for (i=0 ; iinuse) + continue; + game.clients[i].pers.health = ent->health; + game.clients[i].pers.max_health = ent->max_health; + game.clients[i].pers.savedFlags = (ent->flags & (FL_GODMODE|FL_NOTARGET|FL_POWER_ARMOR)); + if (coop->value) + game.clients[i].pers.score = ent->client->resp.score; + } +} + +void FetchClientEntData (edict_t *ent) +{ + ent->health = ent->client->pers.health; + ent->max_health = ent->client->pers.max_health; + ent->flags |= ent->client->pers.savedFlags; + if (coop->value) + ent->client->resp.score = ent->client->pers.score; +} + + + +/* +======================================================================= + + SelectSpawnPoint + +======================================================================= +*/ + +/* +================ +PlayersRangeFromSpot + +Returns the distance to the nearest player from the given spot +================ +*/ +float PlayersRangeFromSpot (edict_t *spot) +{ + edict_t *player; + float bestplayerdistance; + vec3_t v; + int n; + float playerdistance; + + + bestplayerdistance = 9999999; + + for (n = 1; n <= maxclients->value; n++) + { + player = &g_edicts[n]; + + if (!player->inuse) + continue; + + if (player->health <= 0) + continue; + + VectorSubtract (spot->s.origin, player->s.origin, v); + playerdistance = VectorLength (v); + + if (playerdistance < bestplayerdistance) + bestplayerdistance = playerdistance; + } + + return bestplayerdistance; +} + +/* +================ +SelectRandomDeathmatchSpawnPoint + +go to a random point, but NOT the two points closest +to other players +================ +*/ +edict_t *SelectRandomDeathmatchSpawnPoint (void) +{ + edict_t *spot, *spot1, *spot2; + int count = 0; + int selection; + float range, range1, range2; + + spot = NULL; + range1 = range2 = 99999; + spot1 = spot2 = NULL; + + while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) + { + count++; + range = PlayersRangeFromSpot(spot); + if (range < range1) + { + range1 = range; + spot1 = spot; + } + else if (range < range2) + { + range2 = range; + spot2 = spot; + } + } + + if (!count) + return NULL; + + if (count <= 2) + { + spot1 = spot2 = NULL; + } + else + count -= 2; + + selection = rand() % count; + + spot = NULL; + do + { + spot = G_Find (spot, FOFS(classname), "info_player_deathmatch"); + if (spot == spot1 || spot == spot2) + selection++; + } while(selection--); + + return spot; +} + +/* +================ +SelectFarthestDeathmatchSpawnPoint + +================ +*/ +edict_t *SelectFarthestDeathmatchSpawnPoint (void) +{ + edict_t *bestspot; + float bestdistance, bestplayerdistance; + edict_t *spot; + + + spot = NULL; + bestspot = NULL; + bestdistance = 0; + while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) + { + bestplayerdistance = PlayersRangeFromSpot (spot); + + if (bestplayerdistance > bestdistance) + { + bestspot = spot; + bestdistance = bestplayerdistance; + } + } + + if (bestspot) + { + return bestspot; + } + + // if there is a player just spawned on each and every start spot + // we have no choice to turn one into a telefrag meltdown + spot = G_Find (NULL, FOFS(classname), "info_player_deathmatch"); + + return spot; +} + +edict_t *SelectDeathmatchSpawnPoint (void) +{ + if ( (int)(dmflags->value) & DF_SPAWN_FARTHEST) + return SelectFarthestDeathmatchSpawnPoint (); + else + return SelectRandomDeathmatchSpawnPoint (); +} + + +edict_t *SelectCoopSpawnPoint (edict_t *ent) +{ + int index; + edict_t *spot = NULL; + char *target; + + index = ent->client - game.clients; + + // player 0 starts in normal player spawn point + if (!index) + return NULL; + + spot = NULL; + + // assume there are four coop spots at each spawnpoint + while (1) + { + spot = G_Find (spot, FOFS(classname), "info_player_coop"); + if (!spot) + return NULL; // we didn't have enough... + + target = spot->targetname; + if (!target) + target = ""; + if ( Q_stricmp(game.spawnpoint, target) == 0 ) + { // this is a coop spawn point for one of the clients here + index--; + if (!index) + return spot; // this is it + } + } + + + return spot; +} + + +/* +=========== +SelectSpawnPoint + +Chooses a player start, deathmatch start, coop start, etc +============ +*/ +void SelectSpawnPoint (edict_t *ent, vec3_t origin, vec3_t angles) +{ + edict_t *spot = NULL; + + if (deathmatch->value) + spot = SelectDeathmatchSpawnPoint (); + else if (coop->value) + spot = SelectCoopSpawnPoint (ent); + + // find a single player start spot + if (!spot) + { + while ((spot = G_Find (spot, FOFS(classname), "info_player_start")) != NULL) + { + if (!game.spawnpoint[0] && !spot->targetname) + break; + + if (!game.spawnpoint[0] || !spot->targetname) + continue; + + if (Q_stricmp(game.spawnpoint, spot->targetname) == 0) + break; + } + + if (!spot) + { + if (!game.spawnpoint[0]) + { // there wasn't a spawnpoint without a target, so use any + spot = G_Find (spot, FOFS(classname), "info_player_start"); + } + if (!spot) + gi.error ("Couldn't find spawn point %s\n", game.spawnpoint); + } + } + + VectorCopy (spot->s.origin, origin); + origin[2] += 9; + VectorCopy (spot->s.angles, angles); +} + +//====================================================================== + + +void InitBodyQue (void) +{ + int i; + edict_t *ent; + + level.body_que = 0; + for (i=0; iclassname = "bodyque"; + } +} + +void body_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + + if (self->health < -40) + { + gi.sound (self, CHAN_BODY, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + self->s.origin[2] -= 48; + ThrowClientHead (self, damage); + self->takedamage = DAMAGE_NO; + } +} + +void CopyToBodyQue (edict_t *ent) +{ + edict_t *body; + + // grab a body que and cycle to the next one + body = &g_edicts[(int)maxclients->value + level.body_que + 1]; + level.body_que = (level.body_que + 1) % BODY_QUEUE_SIZE; + + // FIXME: send an effect on the removed body + + gi.unlinkentity (ent); + + gi.unlinkentity (body); + body->s = ent->s; + body->s.number = body - g_edicts; + + body->svflags = ent->svflags; + VectorCopy (ent->mins, body->mins); + VectorCopy (ent->maxs, body->maxs); + VectorCopy (ent->absmin, body->absmin); + VectorCopy (ent->absmax, body->absmax); + VectorCopy (ent->size, body->size); + body->solid = ent->solid; + body->clipmask = ent->clipmask; + body->owner = ent->owner; + body->movetype = ent->movetype; + + body->die = body_die; + body->takedamage = DAMAGE_YES; + + gi.linkentity (body); +} + + +void respawn (edict_t *self) +{ + if (deathmatch->value || coop->value) + { + // spectator's don't leave bodies + if (self->movetype != MOVETYPE_NOCLIP) + CopyToBodyQue (self); + self->svflags &= ~SVF_NOCLIENT; + PutClientInServer (self); + + // add a teleportation effect + self->s.event = EV_PLAYER_TELEPORT; + + // hold in place briefly + self->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; + self->client->ps.pmove.pm_time = 14; + + self->client->respawn_time = level.time; + + return; + } + + // restart the entire server + gi.AddCommandString ("menu_loadgame\n"); +} + +/* + * only called when pers.spectator changes + * note that resp.spectator should be the opposite of pers.spectator here + */ +void spectator_respawn (edict_t *ent) +{ + int i, numspec; + + // if the user wants to become a spectator, make sure he doesn't + // exceed max_spectators + + if (ent->client->pers.spectator) { + char *value = Info_ValueForKey (ent->client->pers.userinfo, "spectator"); + if (*spectator_password->string && + strcmp(spectator_password->string, "none") && + strcmp(spectator_password->string, value)) { + gi.cprintf(ent, PRINT_HIGH, "Spectator password incorrect.\n"); + ent->client->pers.spectator = false; + gi.WriteByte (svc_stufftext); + gi.WriteString ("spectator 0\n"); + gi.unicast(ent, true); + return; + } + + // count spectators + for (i = 1, numspec = 0; i <= maxclients->value; i++) + if (g_edicts[i].inuse && g_edicts[i].client->pers.spectator) + numspec++; + + if (numspec >= maxspectators->value) { + gi.cprintf(ent, PRINT_HIGH, "Server spectator limit is full."); + ent->client->pers.spectator = false; + // reset his spectator var + gi.WriteByte (svc_stufftext); + gi.WriteString ("spectator 0\n"); + gi.unicast(ent, true); + return; + } + } else { + // he was a spectator and wants to join the game + // he must have the right password + char *value = Info_ValueForKey (ent->client->pers.userinfo, "password"); + if (*password->string && strcmp(password->string, "none") && + strcmp(password->string, value)) { + gi.cprintf(ent, PRINT_HIGH, "Password incorrect.\n"); + ent->client->pers.spectator = true; + gi.WriteByte (svc_stufftext); + gi.WriteString ("spectator 1\n"); + gi.unicast(ent, true); + return; + } + } + + // clear score on respawn + ent->client->pers.score = ent->client->resp.score = 0; + + ent->svflags &= ~SVF_NOCLIENT; + PutClientInServer (ent); + + // add a teleportation effect + if (!ent->client->pers.spectator) { + // send effect + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_LOGIN); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + // hold in place briefly + ent->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; + ent->client->ps.pmove.pm_time = 14; + } + + ent->client->respawn_time = level.time; + + if (ent->client->pers.spectator) + gi.bprintf (PRINT_HIGH, "%s has moved to the sidelines\n", ent->client->pers.netname); + else + gi.bprintf (PRINT_HIGH, "%s joined the game\n", ent->client->pers.netname); +} + +//============================================================== + + +/* +=========== +PutClientInServer + +Called when a player connects to a server or respawns in +a deathmatch. +============ +*/ +void PutClientInServer (edict_t *ent) +{ + vec3_t mins = {-16, -16, -24}; + vec3_t maxs = {16, 16, 32}; + int index; + vec3_t spawn_origin, spawn_angles; + gclient_t *client; + int i; + client_persistant_t saved; + client_respawn_t resp; + + // find a spawn point + // do it before setting health back up, so farthest + // ranging doesn't count this client + SelectSpawnPoint (ent, spawn_origin, spawn_angles); + + index = ent-g_edicts-1; + client = ent->client; + + // deathmatch wipes most client data every spawn + if (deathmatch->value) + { + char userinfo[MAX_INFO_STRING]; + + resp = client->resp; + memcpy (userinfo, client->pers.userinfo, sizeof(userinfo)); + InitClientPersistant (client); + ClientUserinfoChanged (ent, userinfo); + } + else if (coop->value) + { +// int n; + char userinfo[MAX_INFO_STRING]; + + resp = client->resp; + memcpy (userinfo, client->pers.userinfo, sizeof(userinfo)); + // this is kind of ugly, but it's how we want to handle keys in coop +// for (n = 0; n < game.num_items; n++) +// { +// if (itemlist[n].flags & IT_KEY) +// resp.coop_respawn.inventory[n] = client->pers.inventory[n]; +// } + resp.coop_respawn.game_helpchanged = client->pers.game_helpchanged; + resp.coop_respawn.helpchanged = client->pers.helpchanged; + client->pers = resp.coop_respawn; + ClientUserinfoChanged (ent, userinfo); + if (resp.score > client->pers.score) + client->pers.score = resp.score; + } + else + { + memset (&resp, 0, sizeof(resp)); + } + + // clear everything but the persistant data + saved = client->pers; + memset (client, 0, sizeof(*client)); + client->pers = saved; + if (client->pers.health <= 0) + InitClientPersistant(client); + client->resp = resp; + + // copy some data from the client to the entity + FetchClientEntData (ent); + + // clear entity values + ent->groundentity = NULL; + ent->client = &game.clients[index]; + ent->takedamage = DAMAGE_AIM; + ent->movetype = MOVETYPE_WALK; + ent->viewheight = 22; + ent->inuse = true; + ent->classname = "player"; + ent->mass = 200; + ent->solid = SOLID_BBOX; + ent->deadflag = DEAD_NO; + ent->air_finished = level.time + 12; + ent->clipmask = MASK_PLAYERSOLID; + ent->model = "players/male/tris.md2"; + ent->pain = player_pain; + ent->die = player_die; + ent->waterlevel = 0; + ent->watertype = 0; + ent->flags &= ~FL_NO_KNOCKBACK; + ent->svflags &= ~SVF_DEADMONSTER; + + VectorCopy (mins, ent->mins); + VectorCopy (maxs, ent->maxs); + VectorClear (ent->velocity); + + // clear playerstate values + memset (&ent->client->ps, 0, sizeof(client->ps)); + + client->ps.pmove.origin[0] = spawn_origin[0]*8; + client->ps.pmove.origin[1] = spawn_origin[1]*8; + client->ps.pmove.origin[2] = spawn_origin[2]*8; + + if (deathmatch->value && ((int)dmflags->value & DF_FIXED_FOV)) + { + client->ps.fov = 90; + } + else + { + client->ps.fov = atoi(Info_ValueForKey(client->pers.userinfo, "fov")); + if (client->ps.fov < 1) + client->ps.fov = 90; + else if (client->ps.fov > 160) + client->ps.fov = 160; + } + + client->ps.gunindex = gi.modelindex(client->pers.weapon->view_model); + + // clear entity state values + ent->s.effects = 0; + ent->s.modelindex = 255; // will use the skin specified model + ent->s.modelindex2 = 255; // custom gun model + // sknum is player num and weapon number + // weapon number will be added in changeweapon + ent->s.skinnum = ent - g_edicts - 1; + + ent->s.frame = 0; + VectorCopy (spawn_origin, ent->s.origin); + ent->s.origin[2] += 1; // make sure off ground + VectorCopy (ent->s.origin, ent->s.old_origin); + + // set the delta angle + for (i=0 ; i<3 ; i++) + client->ps.pmove.delta_angles[i] = ANGLE2SHORT(spawn_angles[i] - client->resp.cmd_angles[i]); + + ent->s.angles[PITCH] = 0; + ent->s.angles[YAW] = spawn_angles[YAW]; + ent->s.angles[ROLL] = 0; + VectorCopy (ent->s.angles, client->ps.viewangles); + VectorCopy (ent->s.angles, client->v_angle); + + // spawn a spectator + if (client->pers.spectator) { + client->chase_target = NULL; + + client->resp.spectator = true; + + ent->movetype = MOVETYPE_NOCLIP; + ent->solid = SOLID_NOT; + ent->svflags |= SVF_NOCLIENT; + ent->client->ps.gunindex = 0; + gi.linkentity (ent); + return; + } else + client->resp.spectator = false; + + if (!KillBox (ent)) + { // could't spawn in? + } + + gi.linkentity (ent); + + // force the current weapon up + client->newweapon = client->pers.weapon; + ChangeWeapon (ent); +} + +/* +===================== +ClientBeginDeathmatch + +A client has just connected to the server in +deathmatch mode, so clear everything out before starting them. +===================== +*/ +void ClientBeginDeathmatch (edict_t *ent) +{ + G_InitEdict (ent); + + InitClientResp (ent->client); + + // locate ent at a spawn point + PutClientInServer (ent); + + // send effect + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_LOGIN); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname); + + // make sure all view stuff is valid + ClientEndServerFrame (ent); +} + + +/* +=========== +ClientBegin + +called when a client has finished connecting, and is ready +to be placed into the game. This will happen every level load. +============ +*/ +void ClientBegin (edict_t *ent) +{ + int i; + + ent->client = game.clients + (ent - g_edicts - 1); + + if (deathmatch->value) + { + ClientBeginDeathmatch (ent); + return; + } + + // if there is already a body waiting for us (a loadgame), just + // take it, otherwise spawn one from scratch + if (ent->inuse == true) + { + // the client has cleared the client side viewangles upon + // connecting to the server, which is different than the + // state when the game is saved, so we need to compensate + // with deltaangles + for (i=0 ; i<3 ; i++) + ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(ent->client->ps.viewangles[i]); + } + else + { + // a spawn point will completely reinitialize the entity + // except for the persistant data that was initialized at + // ClientConnect() time + G_InitEdict (ent); + ent->classname = "player"; + InitClientResp (ent->client); + PutClientInServer (ent); + } + + if (level.intermissiontime) + { + MoveClientToIntermission (ent); + } + else + { + // send effect if in a multiplayer game + if (game.maxclients > 1) + { + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_LOGIN); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname); + } + } + + // make sure all view stuff is valid + ClientEndServerFrame (ent); +} + +/* +=========== +ClientUserInfoChanged + +called whenever the player updates a userinfo variable. + +The game can override any of the settings in place +(forcing skins or names, etc) before copying it off. +============ +*/ +void ClientUserinfoChanged (edict_t *ent, char *userinfo) +{ + char *s; + int playernum; + + // check for malformed or illegal info strings + if (!Info_Validate(userinfo)) + { + strcpy (userinfo, "\\name\\badinfo\\skin\\male/grunt"); + } + + // set name + s = Info_ValueForKey (userinfo, "name"); + strncpy (ent->client->pers.netname, s, sizeof(ent->client->pers.netname)-1); + + // set spectator + s = Info_ValueForKey (userinfo, "spectator"); + // spectators are only supported in deathmatch + if (deathmatch->value && *s && strcmp(s, "0")) + ent->client->pers.spectator = true; + else + ent->client->pers.spectator = false; + + // set skin + s = Info_ValueForKey (userinfo, "skin"); + + playernum = ent-g_edicts-1; + + // combine name and skin into a configstring + gi.configstring (CS_PLAYERSKINS+playernum, va("%s\\%s", ent->client->pers.netname, s) ); + + // fov + if (deathmatch->value && ((int)dmflags->value & DF_FIXED_FOV)) + { + ent->client->ps.fov = 90; + } + else + { + ent->client->ps.fov = atoi(Info_ValueForKey(userinfo, "fov")); + if (ent->client->ps.fov < 1) + ent->client->ps.fov = 90; + else if (ent->client->ps.fov > 160) + ent->client->ps.fov = 160; + } + + // handedness + s = Info_ValueForKey (userinfo, "hand"); + if (strlen(s)) + { + ent->client->pers.hand = atoi(s); + } + + // save off the userinfo in case we want to check something later + strncpy (ent->client->pers.userinfo, userinfo, sizeof(ent->client->pers.userinfo)-1); +} + + +/* +=========== +ClientConnect + +Called when a player begins connecting to the server. +The game can refuse entrance to a client by returning false. +If the client is allowed, the connection process will continue +and eventually get to ClientBegin() +Changing levels will NOT cause this to be called again, but +loadgames will. +============ +*/ +qboolean ClientConnect (edict_t *ent, char *userinfo) +{ + char *value; + + // check to see if they are on the banned IP list + value = Info_ValueForKey (userinfo, "ip"); + if (SV_FilterPacket(value)) { + Info_SetValueForKey(userinfo, "rejmsg", "Banned."); + return false; + } + + // check for a spectator + value = Info_ValueForKey (userinfo, "spectator"); + if (deathmatch->value && *value && strcmp(value, "0")) { + int i, numspec; + + if (*spectator_password->string && + strcmp(spectator_password->string, "none") && + strcmp(spectator_password->string, value)) { + Info_SetValueForKey(userinfo, "rejmsg", "Spectator password required or incorrect."); + return false; + } + + // count spectators + for (i = numspec = 0; i < maxclients->value; i++) + if (g_edicts[i+1].inuse && g_edicts[i+1].client->pers.spectator) + numspec++; + + if (numspec >= maxspectators->value) { + Info_SetValueForKey(userinfo, "rejmsg", "Server spectator limit is full."); + return false; + } + } else { + // check for a password + value = Info_ValueForKey (userinfo, "password"); + if (*password->string && strcmp(password->string, "none") && + strcmp(password->string, value)) { + Info_SetValueForKey(userinfo, "rejmsg", "Password required or incorrect."); + return false; + } + } + + + // they can connect + ent->client = game.clients + (ent - g_edicts - 1); + + // if there is already a body waiting for us (a loadgame), just + // take it, otherwise spawn one from scratch + if (ent->inuse == false) + { + // clear the respawning variables + InitClientResp (ent->client); + if (!game.autosaved || !ent->client->pers.weapon) + InitClientPersistant (ent->client); + } + + ClientUserinfoChanged (ent, userinfo); + + if (game.maxclients > 1) + gi.dprintf ("%s connected\n", ent->client->pers.netname); + + ent->client->pers.connected = true; + return true; +} + +/* +=========== +ClientDisconnect + +Called when a player drops from the server. +Will not be called between levels. +============ +*/ +void ClientDisconnect (edict_t *ent) +{ + int playernum; + + if (!ent->client) + return; + + gi.bprintf (PRINT_HIGH, "%s disconnected\n", ent->client->pers.netname); + + // send effect + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_LOGOUT); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + gi.unlinkentity (ent); + ent->s.modelindex = 0; + ent->solid = SOLID_NOT; + ent->inuse = false; + ent->classname = "disconnected"; + ent->client->pers.connected = false; + + playernum = ent-g_edicts-1; + gi.configstring (CS_PLAYERSKINS+playernum, ""); +} + + +//============================================================== + + +edict_t *pm_passent; + +// pmove doesn't need to know about passent and contentmask +trace_t PM_trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end) +{ + if (pm_passent->health > 0) + return gi.trace (start, mins, maxs, end, pm_passent, MASK_PLAYERSOLID); + else + return gi.trace (start, mins, maxs, end, pm_passent, MASK_DEADSOLID); +} + +unsigned CheckBlock (void *b, int c) +{ + int v,i; + v = 0; + for (i=0 ; is, sizeof(pm->s)); + c2 = CheckBlock (&pm->cmd, sizeof(pm->cmd)); + Com_Printf ("sv %3i:%i %i\n", pm->cmd.impulse, c1, c2); +} + +/* +============== +ClientThink + +This will be called once for each client frame, which will +usually be a couple times for each server frame. +============== +*/ +void ClientThink (edict_t *ent, usercmd_t *ucmd) +{ + gclient_t *client; + edict_t *other; + int i, j; + pmove_t pm; + + level.current_entity = ent; + client = ent->client; + + if (level.intermissiontime) + { + client->ps.pmove.pm_type = PM_FREEZE; + // can exit intermission after five seconds + if (level.time > level.intermissiontime + 5.0 + && (ucmd->buttons & BUTTON_ANY) ) + level.exitintermission = true; + return; + } + + pm_passent = ent; + + if (ent->client->chase_target) { + + client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]); + client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]); + client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]); + + } else { + + // set up for pmove + memset (&pm, 0, sizeof(pm)); + + if (ent->movetype == MOVETYPE_NOCLIP) + client->ps.pmove.pm_type = PM_SPECTATOR; + else if (ent->s.modelindex != 255) + client->ps.pmove.pm_type = PM_GIB; + else if (ent->deadflag) + client->ps.pmove.pm_type = PM_DEAD; + else + client->ps.pmove.pm_type = PM_NORMAL; + + client->ps.pmove.gravity = sv_gravity->value; + pm.s = client->ps.pmove; + + for (i=0 ; i<3 ; i++) + { + pm.s.origin[i] = ent->s.origin[i]*8; + pm.s.velocity[i] = ent->velocity[i]*8; + } + + if (memcmp(&client->old_pmove, &pm.s, sizeof(pm.s))) + { + pm.snapinitial = true; + // gi.dprintf ("pmove changed!\n"); + } + + pm.cmd = *ucmd; + + pm.trace = PM_trace; // adds default parms + pm.pointcontents = gi.pointcontents; + + // perform a pmove + gi.Pmove (&pm); + + // save results of pmove + client->ps.pmove = pm.s; + client->old_pmove = pm.s; + + for (i=0 ; i<3 ; i++) + { + ent->s.origin[i] = pm.s.origin[i]*0.125; + ent->velocity[i] = pm.s.velocity[i]*0.125; + } + + VectorCopy (pm.mins, ent->mins); + VectorCopy (pm.maxs, ent->maxs); + + client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]); + client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]); + client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]); + + if (ent->groundentity && !pm.groundentity && (pm.cmd.upmove >= 10) && (pm.waterlevel == 0)) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0); + PlayerNoise(ent, ent->s.origin, PNOISE_SELF); + } + + ent->viewheight = pm.viewheight; + ent->waterlevel = pm.waterlevel; + ent->watertype = pm.watertype; + ent->groundentity = pm.groundentity; + if (pm.groundentity) + ent->groundentity_linkcount = pm.groundentity->linkcount; + + if (ent->deadflag) + { + client->ps.viewangles[ROLL] = 40; + client->ps.viewangles[PITCH] = -15; + client->ps.viewangles[YAW] = client->killer_yaw; + } + else + { + VectorCopy (pm.viewangles, client->v_angle); + VectorCopy (pm.viewangles, client->ps.viewangles); + } + + gi.linkentity (ent); + + if (ent->movetype != MOVETYPE_NOCLIP) + G_TouchTriggers (ent); + + // touch other objects + for (i=0 ; itouch) + continue; + other->touch (other, ent, NULL, NULL); + } + + } + + client->oldbuttons = client->buttons; + client->buttons = ucmd->buttons; + client->latched_buttons |= client->buttons & ~client->oldbuttons; + + // save light level the player is standing on for + // monster sighting AI + ent->light_level = ucmd->lightlevel; + + // fire weapon from final position if needed + if (client->latched_buttons & BUTTON_ATTACK) + { + if (client->resp.spectator) { + + client->latched_buttons = 0; + + if (client->chase_target) { + client->chase_target = NULL; + client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; + } else + GetChaseTarget(ent); + + } else if (!client->weapon_thunk) { + client->weapon_thunk = true; + Think_Weapon (ent); + } + } + + if (client->resp.spectator) { + if (ucmd->upmove >= 10) { + if (!(client->ps.pmove.pm_flags & PMF_JUMP_HELD)) { + client->ps.pmove.pm_flags |= PMF_JUMP_HELD; + if (client->chase_target) + ChaseNext(ent); + else + GetChaseTarget(ent); + } + } else + client->ps.pmove.pm_flags &= ~PMF_JUMP_HELD; + } + + // update chase cam if being followed + for (i = 1; i <= maxclients->value; i++) { + other = g_edicts + i; + if (other->inuse && other->client->chase_target == ent) + UpdateChaseCam(other); + } +} + + +/* +============== +ClientBeginServerFrame + +This will be called once for each server frame, before running +any other entities in the world. +============== +*/ +void ClientBeginServerFrame (edict_t *ent) +{ + gclient_t *client; + int buttonMask; + + if (level.intermissiontime) + return; + + client = ent->client; + + if (deathmatch->value && + client->pers.spectator != client->resp.spectator && + (level.time - client->respawn_time) >= 5) { + spectator_respawn(ent); + return; + } + + // run weapon animations if it hasn't been done by a ucmd_t + if (!client->weapon_thunk && !client->resp.spectator) + Think_Weapon (ent); + else + client->weapon_thunk = false; + + if (ent->deadflag) + { + // wait for any button just going down + if ( level.time > client->respawn_time) + { + // in deathmatch, only wait for attack button + if (deathmatch->value) + buttonMask = BUTTON_ATTACK; + else + buttonMask = -1; + + if ( ( client->latched_buttons & buttonMask ) || + (deathmatch->value && ((int)dmflags->value & DF_FORCE_RESPAWN) ) ) + { + respawn(ent); + client->latched_buttons = 0; + } + } + return; + } + + // add player trail so monsters can follow + if (!deathmatch->value) + if (!visible (ent, PlayerTrail_LastSpot() ) ) + PlayerTrail_Add (ent->s.old_origin); + + client->latched_buttons = 0; +} diff --git a/game/p_hud.c b/game/p_hud.c new file mode 100644 index 000000000..d5249a035 --- /dev/null +++ b/game/p_hud.c @@ -0,0 +1,571 @@ +/* +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. + +*/ +#include "g_local.h" + + + +/* +====================================================================== + +INTERMISSION + +====================================================================== +*/ + +void MoveClientToIntermission (edict_t *ent) +{ + if (deathmatch->value || coop->value) + ent->client->showscores = true; + VectorCopy (level.intermission_origin, ent->s.origin); + ent->client->ps.pmove.origin[0] = level.intermission_origin[0]*8; + ent->client->ps.pmove.origin[1] = level.intermission_origin[1]*8; + ent->client->ps.pmove.origin[2] = level.intermission_origin[2]*8; + VectorCopy (level.intermission_angle, ent->client->ps.viewangles); + ent->client->ps.pmove.pm_type = PM_FREEZE; + ent->client->ps.gunindex = 0; + ent->client->ps.blend[3] = 0; + ent->client->ps.rdflags &= ~RDF_UNDERWATER; + + // clean up powerup info + ent->client->quad_framenum = 0; + ent->client->invincible_framenum = 0; + ent->client->breather_framenum = 0; + ent->client->enviro_framenum = 0; + ent->client->grenade_blew_up = false; + ent->client->grenade_time = 0; + + ent->viewheight = 0; + ent->s.modelindex = 0; + ent->s.modelindex2 = 0; + ent->s.modelindex3 = 0; + ent->s.modelindex = 0; + ent->s.effects = 0; + ent->s.sound = 0; + ent->solid = SOLID_NOT; + + // add the layout + + if (deathmatch->value || coop->value) + { + DeathmatchScoreboardMessage (ent, NULL); + gi.unicast (ent, true); + } + +} + +void BeginIntermission (edict_t *targ) +{ + int i, n; + edict_t *ent, *client; + + if (level.intermissiontime) + return; // already activated + + game.autosaved = false; + + // respawn any dead clients + for (i=0 ; ivalue ; i++) + { + client = g_edicts + 1 + i; + if (!client->inuse) + continue; + if (client->health <= 0) + respawn(client); + } + + level.intermissiontime = level.time; + level.changemap = targ->map; + + if (strstr(level.changemap, "*")) + { + if (coop->value) + { + for (i=0 ; ivalue ; i++) + { + client = g_edicts + 1 + i; + if (!client->inuse) + continue; + // strip players of all keys between units + for (n = 0; n < MAX_ITEMS; n++) + { + if (itemlist[n].flags & IT_KEY) + client->client->pers.inventory[n] = 0; + } + } + } + } + else + { + if (!deathmatch->value) + { + level.exitintermission = 1; // go immediately to the next level + return; + } + } + + level.exitintermission = 0; + + // find an intermission spot + ent = G_Find (NULL, FOFS(classname), "info_player_intermission"); + if (!ent) + { // the map creator forgot to put in an intermission point... + ent = G_Find (NULL, FOFS(classname), "info_player_start"); + if (!ent) + ent = G_Find (NULL, FOFS(classname), "info_player_deathmatch"); + } + else + { // chose one of four spots + i = rand() & 3; + while (i--) + { + ent = G_Find (ent, FOFS(classname), "info_player_intermission"); + if (!ent) // wrap around the list + ent = G_Find (ent, FOFS(classname), "info_player_intermission"); + } + } + + VectorCopy (ent->s.origin, level.intermission_origin); + VectorCopy (ent->s.angles, level.intermission_angle); + + // move all clients to the intermission point + for (i=0 ; ivalue ; i++) + { + client = g_edicts + 1 + i; + if (!client->inuse) + continue; + MoveClientToIntermission (client); + } +} + + +/* +================== +DeathmatchScoreboardMessage + +================== +*/ +void DeathmatchScoreboardMessage (edict_t *ent, edict_t *killer) +{ + char entry[1024]; + char string[1400]; + int stringlength; + int i, j, k; + int sorted[MAX_CLIENTS]; + int sortedscores[MAX_CLIENTS]; + int score, total; + int picnum; + int x, y; + gclient_t *cl; + edict_t *cl_ent; + char *tag; + + // sort the clients by score + total = 0; + for (i=0 ; iinuse || game.clients[i].resp.spectator) + continue; + score = game.clients[i].resp.score; + for (j=0 ; j sortedscores[j]) + break; + } + for (k=total ; k>j ; k--) + { + sorted[k] = sorted[k-1]; + sortedscores[k] = sortedscores[k-1]; + } + sorted[j] = i; + sortedscores[j] = score; + total++; + } + + // print level name and exit rules + string[0] = 0; + + stringlength = strlen(string); + + // add the clients in sorted order + if (total > 12) + total = 12; + + for (i=0 ; i=6) ? 160 : 0; + y = 32 + 32 * (i%6); + + // add a dogtag + if (cl_ent == ent) + tag = "tag1"; + else if (cl_ent == killer) + tag = "tag2"; + else + tag = NULL; + if (tag) + { + Com_sprintf (entry, sizeof(entry), + "xv %i yv %i picn %s ",x+32, y, tag); + j = strlen(entry); + if (stringlength + j > 1024) + break; + strcpy (string + stringlength, entry); + stringlength += j; + } + + // send the layout + Com_sprintf (entry, sizeof(entry), + "client %i %i %i %i %i %i ", + x, y, sorted[i], cl->resp.score, cl->ping, (level.framenum - cl->resp.enterframe)/600); + j = strlen(entry); + if (stringlength + j > 1024) + break; + strcpy (string + stringlength, entry); + stringlength += j; + } + + gi.WriteByte (svc_layout); + gi.WriteString (string); +} + + +/* +================== +DeathmatchScoreboard + +Draw instead of help message. +Note that it isn't that hard to overflow the 1400 byte message limit! +================== +*/ +void DeathmatchScoreboard (edict_t *ent) +{ + DeathmatchScoreboardMessage (ent, ent->enemy); + gi.unicast (ent, true); +} + + +/* +================== +Cmd_Score_f + +Display the scoreboard +================== +*/ +void Cmd_Score_f (edict_t *ent) +{ + ent->client->showinventory = false; + ent->client->showhelp = false; + + if (!deathmatch->value && !coop->value) + return; + + if (ent->client->showscores) + { + ent->client->showscores = false; + return; + } + + ent->client->showscores = true; + DeathmatchScoreboard (ent); +} + + +/* +================== +HelpComputer + +Draw help computer. +================== +*/ +void HelpComputer (edict_t *ent) +{ + char string[1024]; + char *sk; + + if (skill->value == 0) + sk = "easy"; + else if (skill->value == 1) + sk = "medium"; + else if (skill->value == 2) + sk = "hard"; + else + sk = "hard+"; + + // send the layout + Com_sprintf (string, sizeof(string), + "xv 32 yv 8 picn help " // background + "xv 202 yv 12 string2 \"%s\" " // skill + "xv 0 yv 24 cstring2 \"%s\" " // level name + "xv 0 yv 54 cstring2 \"%s\" " // help 1 + "xv 0 yv 110 cstring2 \"%s\" " // help 2 + "xv 50 yv 164 string2 \" kills goals secrets\" " + "xv 50 yv 172 string2 \"%3i/%3i %i/%i %i/%i\" ", + sk, + level.level_name, + game.helpmessage1, + game.helpmessage2, + level.killed_monsters, level.total_monsters, + level.found_goals, level.total_goals, + level.found_secrets, level.total_secrets); + + gi.WriteByte (svc_layout); + gi.WriteString (string); + gi.unicast (ent, true); +} + + +/* +================== +Cmd_Help_f + +Display the current help message +================== +*/ +void Cmd_Help_f (edict_t *ent) +{ + // this is for backwards compatability + if (deathmatch->value) + { + Cmd_Score_f (ent); + return; + } + + ent->client->showinventory = false; + ent->client->showscores = false; + + if (ent->client->showhelp && (ent->client->pers.game_helpchanged == game.helpchanged)) + { + ent->client->showhelp = false; + return; + } + + ent->client->showhelp = true; + ent->client->pers.helpchanged = 0; + HelpComputer (ent); +} + + +//======================================================================= + +/* +=============== +G_SetStats +=============== +*/ +void G_SetStats (edict_t *ent) +{ + gitem_t *item; + int index, cells; + int power_armor_type; + + // + // health + // + ent->client->ps.stats[STAT_HEALTH_ICON] = level.pic_health; + ent->client->ps.stats[STAT_HEALTH] = ent->health; + + // + // ammo + // + if (!ent->client->ammo_index /* || !ent->client->pers.inventory[ent->client->ammo_index] */) + { + ent->client->ps.stats[STAT_AMMO_ICON] = 0; + ent->client->ps.stats[STAT_AMMO] = 0; + } + else + { + item = &itemlist[ent->client->ammo_index]; + ent->client->ps.stats[STAT_AMMO_ICON] = gi.imageindex (item->icon); + ent->client->ps.stats[STAT_AMMO] = ent->client->pers.inventory[ent->client->ammo_index]; + } + + // + // armor + // + power_armor_type = PowerArmorType (ent); + if (power_armor_type) + { + cells = ent->client->pers.inventory[ITEM_INDEX(FindItem ("cells"))]; + if (cells == 0) + { // ran out of cells for power armor + ent->flags &= ~FL_POWER_ARMOR; + gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0); + power_armor_type = 0;; + } + } + + index = ArmorIndex (ent); + if (power_armor_type && (!index || (level.framenum & 8) ) ) + { // flash between power armor and other armor icon + ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex ("i_powershield"); + ent->client->ps.stats[STAT_ARMOR] = cells; + } + else if (index) + { + item = GetItemByIndex (index); + ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex (item->icon); + ent->client->ps.stats[STAT_ARMOR] = ent->client->pers.inventory[index]; + } + else + { + ent->client->ps.stats[STAT_ARMOR_ICON] = 0; + ent->client->ps.stats[STAT_ARMOR] = 0; + } + + // + // pickup message + // + if (level.time > ent->client->pickup_msg_time) + { + ent->client->ps.stats[STAT_PICKUP_ICON] = 0; + ent->client->ps.stats[STAT_PICKUP_STRING] = 0; + } + + // + // timers + // + if (ent->client->quad_framenum > level.framenum) + { + ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_quad"); + ent->client->ps.stats[STAT_TIMER] = (ent->client->quad_framenum - level.framenum)/10; + } + else if (ent->client->invincible_framenum > level.framenum) + { + ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_invulnerability"); + ent->client->ps.stats[STAT_TIMER] = (ent->client->invincible_framenum - level.framenum)/10; + } + else if (ent->client->enviro_framenum > level.framenum) + { + ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_envirosuit"); + ent->client->ps.stats[STAT_TIMER] = (ent->client->enviro_framenum - level.framenum)/10; + } + else if (ent->client->breather_framenum > level.framenum) + { + ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_rebreather"); + ent->client->ps.stats[STAT_TIMER] = (ent->client->breather_framenum - level.framenum)/10; + } + else + { + ent->client->ps.stats[STAT_TIMER_ICON] = 0; + ent->client->ps.stats[STAT_TIMER] = 0; + } + + // + // selected item + // + if (ent->client->pers.selected_item == -1) + ent->client->ps.stats[STAT_SELECTED_ICON] = 0; + else + ent->client->ps.stats[STAT_SELECTED_ICON] = gi.imageindex (itemlist[ent->client->pers.selected_item].icon); + + ent->client->ps.stats[STAT_SELECTED_ITEM] = ent->client->pers.selected_item; + + // + // layouts + // + ent->client->ps.stats[STAT_LAYOUTS] = 0; + + if (deathmatch->value) + { + if (ent->client->pers.health <= 0 || level.intermissiontime + || ent->client->showscores) + ent->client->ps.stats[STAT_LAYOUTS] |= 1; + if (ent->client->showinventory && ent->client->pers.health > 0) + ent->client->ps.stats[STAT_LAYOUTS] |= 2; + } + else + { + if (ent->client->showscores || ent->client->showhelp) + ent->client->ps.stats[STAT_LAYOUTS] |= 1; + if (ent->client->showinventory && ent->client->pers.health > 0) + ent->client->ps.stats[STAT_LAYOUTS] |= 2; + } + + // + // frags + // + ent->client->ps.stats[STAT_FRAGS] = ent->client->resp.score; + + // + // help icon / current weapon if not shown + // + if (ent->client->pers.helpchanged && (level.framenum&8) ) + ent->client->ps.stats[STAT_HELPICON] = gi.imageindex ("i_help"); + else if ( (ent->client->pers.hand == CENTER_HANDED || ent->client->ps.fov > 91) + && ent->client->pers.weapon) + ent->client->ps.stats[STAT_HELPICON] = gi.imageindex (ent->client->pers.weapon->icon); + else + ent->client->ps.stats[STAT_HELPICON] = 0; + + ent->client->ps.stats[STAT_SPECTATOR] = 0; +} + +/* +=============== +G_CheckChaseStats +=============== +*/ +void G_CheckChaseStats (edict_t *ent) +{ + int i; + gclient_t *cl; + + for (i = 1; i <= maxclients->value; i++) { + cl = g_edicts[i].client; + if (!g_edicts[i].inuse || cl->chase_target != ent) + continue; + memcpy(cl->ps.stats, ent->client->ps.stats, sizeof(cl->ps.stats)); + G_SetSpectatorStats(g_edicts + i); + } +} + +/* +=============== +G_SetSpectatorStats +=============== +*/ +void G_SetSpectatorStats (edict_t *ent) +{ + gclient_t *cl = ent->client; + + if (!cl->chase_target) + G_SetStats (ent); + + cl->ps.stats[STAT_SPECTATOR] = 1; + + // layouts are independant in spectator + cl->ps.stats[STAT_LAYOUTS] = 0; + if (cl->pers.health <= 0 || level.intermissiontime || cl->showscores) + cl->ps.stats[STAT_LAYOUTS] |= 1; + if (cl->showinventory && cl->pers.health > 0) + cl->ps.stats[STAT_LAYOUTS] |= 2; + + if (cl->chase_target && cl->chase_target->inuse) + cl->ps.stats[STAT_CHASE] = CS_PLAYERSKINS + + (cl->chase_target - g_edicts) - 1; + else + cl->ps.stats[STAT_CHASE] = 0; +} + diff --git a/game/p_trail.c b/game/p_trail.c new file mode 100644 index 000000000..d968682f2 --- /dev/null +++ b/game/p_trail.c @@ -0,0 +1,146 @@ +/* +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. + +*/ +#include "g_local.h" + + +/* +============================================================================== + +PLAYER TRAIL + +============================================================================== + +This is a circular list containing the a list of points of where +the player has been recently. It is used by monsters for pursuit. + +.origin the spot +.owner forward link +.aiment backward link +*/ + + +#define TRAIL_LENGTH 8 + +edict_t *trail[TRAIL_LENGTH]; +int trail_head; +qboolean trail_active = false; + +#define NEXT(n) (((n) + 1) & (TRAIL_LENGTH - 1)) +#define PREV(n) (((n) - 1) & (TRAIL_LENGTH - 1)) + + +void PlayerTrail_Init (void) +{ + int n; + + if (deathmatch->value /* FIXME || coop */) + return; + + for (n = 0; n < TRAIL_LENGTH; n++) + { + trail[n] = G_Spawn(); + trail[n]->classname = "player_trail"; + } + + trail_head = 0; + trail_active = true; +} + + +void PlayerTrail_Add (vec3_t spot) +{ + vec3_t temp; + + if (!trail_active) + return; + + VectorCopy (spot, trail[trail_head]->s.origin); + + trail[trail_head]->timestamp = level.time; + + VectorSubtract (spot, trail[PREV(trail_head)]->s.origin, temp); + trail[trail_head]->s.angles[1] = vectoyaw (temp); + + trail_head = NEXT(trail_head); +} + + +void PlayerTrail_New (vec3_t spot) +{ + if (!trail_active) + return; + + PlayerTrail_Init (); + PlayerTrail_Add (spot); +} + + +edict_t *PlayerTrail_PickFirst (edict_t *self) +{ + int marker; + int n; + + if (!trail_active) + return NULL; + + for (marker = trail_head, n = TRAIL_LENGTH; n; n--) + { + if(trail[marker]->timestamp <= self->monsterinfo.trail_time) + marker = NEXT(marker); + else + break; + } + + if (visible(self, trail[marker])) + { + return trail[marker]; + } + + if (visible(self, trail[PREV(marker)])) + { + return trail[PREV(marker)]; + } + + return trail[marker]; +} + +edict_t *PlayerTrail_PickNext (edict_t *self) +{ + int marker; + int n; + + if (!trail_active) + return NULL; + + for (marker = trail_head, n = TRAIL_LENGTH; n; n--) + { + if(trail[marker]->timestamp <= self->monsterinfo.trail_time) + marker = NEXT(marker); + else + break; + } + + return trail[marker]; +} + +edict_t *PlayerTrail_LastSpot (void) +{ + return trail[PREV(trail_head)]; +} diff --git a/game/p_view.c b/game/p_view.c new file mode 100644 index 000000000..04ba7c6a6 --- /dev/null +++ b/game/p_view.c @@ -0,0 +1,1087 @@ +/* +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. + +*/ + +#include "g_local.h" +#include "m_player.h" + + + +static edict_t *current_player; +static gclient_t *current_client; + +static vec3_t forward, right, up; +float xyspeed; + +float bobmove; +int bobcycle; // odd cycles are right foot going forward +float bobfracsin; // sin(bobfrac*M_PI) + +/* +=============== +SV_CalcRoll + +=============== +*/ +float SV_CalcRoll (vec3_t angles, vec3_t velocity) +{ + float sign; + float side; + float value; + + side = DotProduct (velocity, right); + sign = side < 0 ? -1 : 1; + side = fabs(side); + + value = sv_rollangle->value; + + if (side < sv_rollspeed->value) + side = side * value / sv_rollspeed->value; + else + side = value; + + return side*sign; + +} + + +/* +=============== +P_DamageFeedback + +Handles color blends and view kicks +=============== +*/ +void P_DamageFeedback (edict_t *player) +{ + gclient_t *client; + float side; + float realcount, count, kick; + vec3_t v; + int r, l; + static vec3_t power_color = {0.0, 1.0, 0.0}; + static vec3_t acolor = {1.0, 1.0, 1.0}; + static vec3_t bcolor = {1.0, 0.0, 0.0}; + + client = player->client; + + // flash the backgrounds behind the status numbers + client->ps.stats[STAT_FLASHES] = 0; + if (client->damage_blood) + client->ps.stats[STAT_FLASHES] |= 1; + if (client->damage_armor && !(player->flags & FL_GODMODE) && (client->invincible_framenum <= level.framenum)) + client->ps.stats[STAT_FLASHES] |= 2; + + // total points of damage shot at the player this frame + count = (client->damage_blood + client->damage_armor + client->damage_parmor); + if (count == 0) + return; // didn't take any damage + + // start a pain animation if still in the player model + if (client->anim_priority < ANIM_PAIN && player->s.modelindex == 255) + { + static int i; + + client->anim_priority = ANIM_PAIN; + if (client->ps.pmove.pm_flags & PMF_DUCKED) + { + player->s.frame = FRAME_crpain1-1; + client->anim_end = FRAME_crpain4; + } + else + { + i = (i+1)%3; + switch (i) + { + case 0: + player->s.frame = FRAME_pain101-1; + client->anim_end = FRAME_pain104; + break; + case 1: + player->s.frame = FRAME_pain201-1; + client->anim_end = FRAME_pain204; + break; + case 2: + player->s.frame = FRAME_pain301-1; + client->anim_end = FRAME_pain304; + break; + } + } + } + + realcount = count; + if (count < 10) + count = 10; // always make a visible effect + + // play an apropriate pain sound + if ((level.time > player->pain_debounce_time) && !(player->flags & FL_GODMODE) && (client->invincible_framenum <= level.framenum)) + { + r = 1 + (rand()&1); + player->pain_debounce_time = level.time + 0.7; + if (player->health < 25) + l = 25; + else if (player->health < 50) + l = 50; + else if (player->health < 75) + l = 75; + else + l = 100; + gi.sound (player, CHAN_VOICE, gi.soundindex(va("*pain%i_%i.wav", l, r)), 1, ATTN_NORM, 0); + } + + // the total alpha of the blend is always proportional to count + if (client->damage_alpha < 0) + client->damage_alpha = 0; + client->damage_alpha += count*0.01; + if (client->damage_alpha < 0.2) + client->damage_alpha = 0.2; + if (client->damage_alpha > 0.6) + client->damage_alpha = 0.6; // don't go too saturated + + // the color of the blend will vary based on how much was absorbed + // by different armors + VectorClear (v); + if (client->damage_parmor) + VectorMA (v, (float)client->damage_parmor/realcount, power_color, v); + if (client->damage_armor) + VectorMA (v, (float)client->damage_armor/realcount, acolor, v); + if (client->damage_blood) + VectorMA (v, (float)client->damage_blood/realcount, bcolor, v); + VectorCopy (v, client->damage_blend); + + + // + // calculate view angle kicks + // + kick = abs(client->damage_knockback); + if (kick && player->health > 0) // kick of 0 means no view adjust at all + { + kick = kick * 100 / player->health; + + if (kick < count*0.5) + kick = count*0.5; + if (kick > 50) + kick = 50; + + VectorSubtract (client->damage_from, player->s.origin, v); + VectorNormalize (v); + + side = DotProduct (v, right); + client->v_dmg_roll = kick*side*0.3; + + side = -DotProduct (v, forward); + client->v_dmg_pitch = kick*side*0.3; + + client->v_dmg_time = level.time + DAMAGE_TIME; + } + + // + // clear totals + // + client->damage_blood = 0; + client->damage_armor = 0; + client->damage_parmor = 0; + client->damage_knockback = 0; +} + + + + +/* +=============== +SV_CalcViewOffset + +Auto pitching on slopes? + + fall from 128: 400 = 160000 + fall from 256: 580 = 336400 + fall from 384: 720 = 518400 + fall from 512: 800 = 640000 + fall from 640: 960 = + + damage = deltavelocity*deltavelocity * 0.0001 + +=============== +*/ +void SV_CalcViewOffset (edict_t *ent) +{ + float *angles; + float bob; + float ratio; + float delta; + vec3_t v; + + +//=================================== + + // base angles + angles = ent->client->ps.kick_angles; + + // if dead, fix the angle and don't add any kick + if (ent->deadflag) + { + VectorClear (angles); + + ent->client->ps.viewangles[ROLL] = 40; + ent->client->ps.viewangles[PITCH] = -15; + ent->client->ps.viewangles[YAW] = ent->client->killer_yaw; + } + else + { + // add angles based on weapon kick + + VectorCopy (ent->client->kick_angles, angles); + + // add angles based on damage kick + + ratio = (ent->client->v_dmg_time - level.time) / DAMAGE_TIME; + if (ratio < 0) + { + ratio = 0; + ent->client->v_dmg_pitch = 0; + ent->client->v_dmg_roll = 0; + } + angles[PITCH] += ratio * ent->client->v_dmg_pitch; + angles[ROLL] += ratio * ent->client->v_dmg_roll; + + // add pitch based on fall kick + + ratio = (ent->client->fall_time - level.time) / FALL_TIME; + if (ratio < 0) + ratio = 0; + angles[PITCH] += ratio * ent->client->fall_value; + + // add angles based on velocity + + delta = DotProduct (ent->velocity, forward); + angles[PITCH] += delta*run_pitch->value; + + delta = DotProduct (ent->velocity, right); + angles[ROLL] += delta*run_roll->value; + + // add angles based on bob + + delta = bobfracsin * bob_pitch->value * xyspeed; + if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) + delta *= 6; // crouching + angles[PITCH] += delta; + delta = bobfracsin * bob_roll->value * xyspeed; + if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) + delta *= 6; // crouching + if (bobcycle & 1) + delta = -delta; + angles[ROLL] += delta; + } + +//=================================== + + // base origin + + VectorClear (v); + + // add view height + + v[2] += ent->viewheight; + + // add fall height + + ratio = (ent->client->fall_time - level.time) / FALL_TIME; + if (ratio < 0) + ratio = 0; + v[2] -= ratio * ent->client->fall_value * 0.4; + + // add bob height + + bob = bobfracsin * xyspeed * bob_up->value; + if (bob > 6) + bob = 6; + //gi.DebugGraph (bob *2, 255); + v[2] += bob; + + // add kick offset + + VectorAdd (v, ent->client->kick_origin, v); + + // absolutely bound offsets + // so the view can never be outside the player box + + if (v[0] < -14) + v[0] = -14; + else if (v[0] > 14) + v[0] = 14; + if (v[1] < -14) + v[1] = -14; + else if (v[1] > 14) + v[1] = 14; + if (v[2] < -22) + v[2] = -22; + else if (v[2] > 30) + v[2] = 30; + + VectorCopy (v, ent->client->ps.viewoffset); +} + +/* +============== +SV_CalcGunOffset +============== +*/ +void SV_CalcGunOffset (edict_t *ent) +{ + int i; + float delta; + + // gun angles from bobbing + ent->client->ps.gunangles[ROLL] = xyspeed * bobfracsin * 0.005; + ent->client->ps.gunangles[YAW] = xyspeed * bobfracsin * 0.01; + if (bobcycle & 1) + { + ent->client->ps.gunangles[ROLL] = -ent->client->ps.gunangles[ROLL]; + ent->client->ps.gunangles[YAW] = -ent->client->ps.gunangles[YAW]; + } + + ent->client->ps.gunangles[PITCH] = xyspeed * bobfracsin * 0.005; + + // gun angles from delta movement + for (i=0 ; i<3 ; i++) + { + delta = ent->client->oldviewangles[i] - ent->client->ps.viewangles[i]; + if (delta > 180) + delta -= 360; + if (delta < -180) + delta += 360; + if (delta > 45) + delta = 45; + if (delta < -45) + delta = -45; + if (i == YAW) + ent->client->ps.gunangles[ROLL] += 0.1*delta; + ent->client->ps.gunangles[i] += 0.2 * delta; + } + + // gun height + VectorClear (ent->client->ps.gunoffset); +// ent->ps->gunorigin[2] += bob; + + // gun_x / gun_y / gun_z are development tools + for (i=0 ; i<3 ; i++) + { + ent->client->ps.gunoffset[i] += forward[i]*(gun_y->value); + ent->client->ps.gunoffset[i] += right[i]*gun_x->value; + ent->client->ps.gunoffset[i] += up[i]* (-gun_z->value); + } +} + + +/* +============= +SV_AddBlend +============= +*/ +void SV_AddBlend (float r, float g, float b, float a, float *v_blend) +{ + float a2, a3; + + if (a <= 0) + return; + a2 = v_blend[3] + (1-v_blend[3])*a; // new total alpha + a3 = v_blend[3]/a2; // fraction of color from old + + v_blend[0] = v_blend[0]*a3 + r*(1-a3); + v_blend[1] = v_blend[1]*a3 + g*(1-a3); + v_blend[2] = v_blend[2]*a3 + b*(1-a3); + v_blend[3] = a2; +} + + +/* +============= +SV_CalcBlend +============= +*/ +void SV_CalcBlend (edict_t *ent) +{ + int contents; + vec3_t vieworg; + int remaining; + + ent->client->ps.blend[0] = ent->client->ps.blend[1] = + ent->client->ps.blend[2] = ent->client->ps.blend[3] = 0; + + // add for contents + VectorAdd (ent->s.origin, ent->client->ps.viewoffset, vieworg); + contents = gi.pointcontents (vieworg); + if (contents & (CONTENTS_LAVA|CONTENTS_SLIME|CONTENTS_WATER) ) + ent->client->ps.rdflags |= RDF_UNDERWATER; + else + ent->client->ps.rdflags &= ~RDF_UNDERWATER; + + if (contents & (CONTENTS_SOLID|CONTENTS_LAVA)) + SV_AddBlend (1.0, 0.3, 0.0, 0.6, ent->client->ps.blend); + else if (contents & CONTENTS_SLIME) + SV_AddBlend (0.0, 0.1, 0.05, 0.6, ent->client->ps.blend); + else if (contents & CONTENTS_WATER) + SV_AddBlend (0.5, 0.3, 0.2, 0.4, ent->client->ps.blend); + + // add for powerups + if (ent->client->quad_framenum > level.framenum) + { + remaining = ent->client->quad_framenum - level.framenum; + if (remaining == 30) // beginning to fade + gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage2.wav"), 1, ATTN_NORM, 0); + if (remaining > 30 || (remaining & 4) ) + SV_AddBlend (0, 0, 1, 0.08, ent->client->ps.blend); + } + else if (ent->client->invincible_framenum > level.framenum) + { + remaining = ent->client->invincible_framenum - level.framenum; + if (remaining == 30) // beginning to fade + gi.sound(ent, CHAN_ITEM, gi.soundindex("items/protect2.wav"), 1, ATTN_NORM, 0); + if (remaining > 30 || (remaining & 4) ) + SV_AddBlend (1, 1, 0, 0.08, ent->client->ps.blend); + } + else if (ent->client->enviro_framenum > level.framenum) + { + remaining = ent->client->enviro_framenum - level.framenum; + if (remaining == 30) // beginning to fade + gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0); + if (remaining > 30 || (remaining & 4) ) + SV_AddBlend (0, 1, 0, 0.08, ent->client->ps.blend); + } + else if (ent->client->breather_framenum > level.framenum) + { + remaining = ent->client->breather_framenum - level.framenum; + if (remaining == 30) // beginning to fade + gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0); + if (remaining > 30 || (remaining & 4) ) + SV_AddBlend (0.4, 1, 0.4, 0.04, ent->client->ps.blend); + } + + // add for damage + if (ent->client->damage_alpha > 0) + SV_AddBlend (ent->client->damage_blend[0],ent->client->damage_blend[1] + ,ent->client->damage_blend[2], ent->client->damage_alpha, ent->client->ps.blend); + + if (ent->client->bonus_alpha > 0) + SV_AddBlend (0.85, 0.7, 0.3, ent->client->bonus_alpha, ent->client->ps.blend); + + // drop the damage value + ent->client->damage_alpha -= 0.06; + if (ent->client->damage_alpha < 0) + ent->client->damage_alpha = 0; + + // drop the bonus value + ent->client->bonus_alpha -= 0.1; + if (ent->client->bonus_alpha < 0) + ent->client->bonus_alpha = 0; +} + + +/* +================= +P_FallingDamage +================= +*/ +void P_FallingDamage (edict_t *ent) +{ + float delta; + int damage; + vec3_t dir; + + if (ent->s.modelindex != 255) + return; // not in the player model + + if (ent->movetype == MOVETYPE_NOCLIP) + return; + + if ((ent->client->oldvelocity[2] < 0) && (ent->velocity[2] > ent->client->oldvelocity[2]) && (!ent->groundentity)) + { + delta = ent->client->oldvelocity[2]; + } + else + { + if (!ent->groundentity) + return; + delta = ent->velocity[2] - ent->client->oldvelocity[2]; + } + delta = delta*delta * 0.0001; + + // never take falling damage if completely underwater + if (ent->waterlevel == 3) + return; + if (ent->waterlevel == 2) + delta *= 0.25; + if (ent->waterlevel == 1) + delta *= 0.5; + + if (delta < 1) + return; + + if (delta < 15) + { + ent->s.event = EV_FOOTSTEP; + return; + } + + ent->client->fall_value = delta*0.5; + if (ent->client->fall_value > 40) + ent->client->fall_value = 40; + ent->client->fall_time = level.time + FALL_TIME; + + if (delta > 30) + { + if (ent->health > 0) + { + if (delta >= 55) + ent->s.event = EV_FALLFAR; + else + ent->s.event = EV_FALL; + } + ent->pain_debounce_time = level.time; // no normal pain sound + damage = (delta-30)/2; + if (damage < 1) + damage = 1; + VectorSet (dir, 0, 0, 1); + + if (!deathmatch->value || !((int)dmflags->value & DF_NO_FALLING) ) + T_Damage (ent, world, world, dir, ent->s.origin, vec3_origin, damage, 0, 0, MOD_FALLING); + } + else + { + ent->s.event = EV_FALLSHORT; + return; + } +} + + + +/* +============= +P_WorldEffects +============= +*/ +void P_WorldEffects (void) +{ + qboolean breather; + qboolean envirosuit; + int waterlevel, old_waterlevel; + + if (current_player->movetype == MOVETYPE_NOCLIP) + { + current_player->air_finished = level.time + 12; // don't need air + return; + } + + waterlevel = current_player->waterlevel; + old_waterlevel = current_client->old_waterlevel; + current_client->old_waterlevel = waterlevel; + + breather = current_client->breather_framenum > level.framenum; + envirosuit = current_client->enviro_framenum > level.framenum; + + // + // if just entered a water volume, play a sound + // + if (!old_waterlevel && waterlevel) + { + PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); + if (current_player->watertype & CONTENTS_LAVA) + gi.sound (current_player, CHAN_BODY, gi.soundindex("player/lava_in.wav"), 1, ATTN_NORM, 0); + else if (current_player->watertype & CONTENTS_SLIME) + gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); + else if (current_player->watertype & CONTENTS_WATER) + gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); + current_player->flags |= FL_INWATER; + + // clear damage_debounce, so the pain sound will play immediately + current_player->damage_debounce_time = level.time - 1; + } + + // + // if just completely exited a water volume, play a sound + // + if (old_waterlevel && ! waterlevel) + { + PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); + gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_out.wav"), 1, ATTN_NORM, 0); + current_player->flags &= ~FL_INWATER; + } + + // + // check for head just going under water + // + if (old_waterlevel != 3 && waterlevel == 3) + { + gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_un.wav"), 1, ATTN_NORM, 0); + } + + // + // check for head just coming out of water + // + if (old_waterlevel == 3 && waterlevel != 3) + { + if (current_player->air_finished < level.time) + { // gasp for air + gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/gasp1.wav"), 1, ATTN_NORM, 0); + PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); + } + else if (current_player->air_finished < level.time + 11) + { // just break surface + gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/gasp2.wav"), 1, ATTN_NORM, 0); + } + } + + // + // check for drowning + // + if (waterlevel == 3) + { + // breather or envirosuit give air + if (breather || envirosuit) + { + current_player->air_finished = level.time + 10; + + if (((int)(current_client->breather_framenum - level.framenum) % 25) == 0) + { + if (!current_client->breather_sound) + gi.sound (current_player, CHAN_AUTO, gi.soundindex("player/u_breath1.wav"), 1, ATTN_NORM, 0); + else + gi.sound (current_player, CHAN_AUTO, gi.soundindex("player/u_breath2.wav"), 1, ATTN_NORM, 0); + current_client->breather_sound ^= 1; + PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); + //FIXME: release a bubble? + } + } + + // if out of air, start drowning + if (current_player->air_finished < level.time) + { // drown! + if (current_player->client->next_drown_time < level.time + && current_player->health > 0) + { + current_player->client->next_drown_time = level.time + 1; + + // take more damage the longer underwater + current_player->dmg += 2; + if (current_player->dmg > 15) + current_player->dmg = 15; + + // play a gurp sound instead of a normal pain sound + if (current_player->health <= current_player->dmg) + gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/drown1.wav"), 1, ATTN_NORM, 0); + else if (rand()&1) + gi.sound (current_player, CHAN_VOICE, gi.soundindex("*gurp1.wav"), 1, ATTN_NORM, 0); + else + gi.sound (current_player, CHAN_VOICE, gi.soundindex("*gurp2.wav"), 1, ATTN_NORM, 0); + + current_player->pain_debounce_time = level.time; + + T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, current_player->dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER); + } + } + } + else + { + current_player->air_finished = level.time + 12; + current_player->dmg = 2; + } + + // + // check for sizzle damage + // + if (waterlevel && (current_player->watertype&(CONTENTS_LAVA|CONTENTS_SLIME)) ) + { + if (current_player->watertype & CONTENTS_LAVA) + { + if (current_player->health > 0 + && current_player->pain_debounce_time <= level.time + && current_client->invincible_framenum < level.framenum) + { + if (rand()&1) + gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/burn1.wav"), 1, ATTN_NORM, 0); + else + gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/burn2.wav"), 1, ATTN_NORM, 0); + current_player->pain_debounce_time = level.time + 1; + } + + if (envirosuit) // take 1/3 damage with envirosuit + T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1*waterlevel, 0, 0, MOD_LAVA); + else + T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 3*waterlevel, 0, 0, MOD_LAVA); + } + + if (current_player->watertype & CONTENTS_SLIME) + { + if (!envirosuit) + { // no damage from slime with envirosuit + T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1*waterlevel, 0, 0, MOD_SLIME); + } + } + } +} + + +/* +=============== +G_SetClientEffects +=============== +*/ +void G_SetClientEffects (edict_t *ent) +{ + int pa_type; + int remaining; + + ent->s.effects = 0; + ent->s.renderfx = 0; + + if (ent->health <= 0 || level.intermissiontime) + return; + + if (ent->powerarmor_time > level.time) + { + pa_type = PowerArmorType (ent); + if (pa_type == POWER_ARMOR_SCREEN) + { + ent->s.effects |= EF_POWERSCREEN; + } + else if (pa_type == POWER_ARMOR_SHIELD) + { + ent->s.effects |= EF_COLOR_SHELL; + ent->s.renderfx |= RF_SHELL_GREEN; + } + } + + if (ent->client->quad_framenum > level.framenum) + { + remaining = ent->client->quad_framenum - level.framenum; + if (remaining > 30 || (remaining & 4) ) + ent->s.effects |= EF_QUAD; + } + + if (ent->client->invincible_framenum > level.framenum) + { + remaining = ent->client->invincible_framenum - level.framenum; + if (remaining > 30 || (remaining & 4) ) + ent->s.effects |= EF_PENT; + } + + // show cheaters!!! + if (ent->flags & FL_GODMODE) + { + ent->s.effects |= EF_COLOR_SHELL; + ent->s.renderfx |= (RF_SHELL_RED|RF_SHELL_GREEN|RF_SHELL_BLUE); + } +} + + +/* +=============== +G_SetClientEvent +=============== +*/ +void G_SetClientEvent (edict_t *ent) +{ + if (ent->s.event) + return; + + if ( ent->groundentity && xyspeed > 225) + { + if ( (int)(current_client->bobtime+bobmove) != bobcycle ) + ent->s.event = EV_FOOTSTEP; + } +} + +/* +=============== +G_SetClientSound +=============== +*/ +void G_SetClientSound (edict_t *ent) +{ + char *weap; + + if (ent->client->pers.game_helpchanged != game.helpchanged) + { + ent->client->pers.game_helpchanged = game.helpchanged; + ent->client->pers.helpchanged = 1; + } + + // help beep (no more than three times) + if (ent->client->pers.helpchanged && ent->client->pers.helpchanged <= 3 && !(level.framenum&63) ) + { + ent->client->pers.helpchanged++; + gi.sound (ent, CHAN_VOICE, gi.soundindex ("misc/pc_up.wav"), 1, ATTN_STATIC, 0); + } + + + if (ent->client->pers.weapon) + weap = ent->client->pers.weapon->classname; + else + weap = ""; + + if (ent->waterlevel && (ent->watertype&(CONTENTS_LAVA|CONTENTS_SLIME)) ) + ent->s.sound = snd_fry; + else if (strcmp(weap, "weapon_railgun") == 0) + ent->s.sound = gi.soundindex("weapons/rg_hum.wav"); + else if (strcmp(weap, "weapon_bfg") == 0) + ent->s.sound = gi.soundindex("weapons/bfg_hum.wav"); + else if (ent->client->weapon_sound) + ent->s.sound = ent->client->weapon_sound; + else + ent->s.sound = 0; +} + +/* +=============== +G_SetClientFrame +=============== +*/ +void G_SetClientFrame (edict_t *ent) +{ + gclient_t *client; + qboolean duck, run; + + if (ent->s.modelindex != 255) + return; // not in the player model + + client = ent->client; + + if (client->ps.pmove.pm_flags & PMF_DUCKED) + duck = true; + else + duck = false; + if (xyspeed) + run = true; + else + run = false; + + // check for stand/duck and stop/go transitions + if (duck != client->anim_duck && client->anim_priority < ANIM_DEATH) + goto newanim; + if (run != client->anim_run && client->anim_priority == ANIM_BASIC) + goto newanim; + if (!ent->groundentity && client->anim_priority <= ANIM_WAVE) + goto newanim; + + if(client->anim_priority == ANIM_REVERSE) + { + if(ent->s.frame > client->anim_end) + { + ent->s.frame--; + return; + } + } + else if (ent->s.frame < client->anim_end) + { // continue an animation + ent->s.frame++; + return; + } + + if (client->anim_priority == ANIM_DEATH) + return; // stay there + if (client->anim_priority == ANIM_JUMP) + { + if (!ent->groundentity) + return; // stay there + ent->client->anim_priority = ANIM_WAVE; + ent->s.frame = FRAME_jump3; + ent->client->anim_end = FRAME_jump6; + return; + } + +newanim: + // return to either a running or standing frame + client->anim_priority = ANIM_BASIC; + client->anim_duck = duck; + client->anim_run = run; + + if (!ent->groundentity) + { + client->anim_priority = ANIM_JUMP; + if (ent->s.frame != FRAME_jump2) + ent->s.frame = FRAME_jump1; + client->anim_end = FRAME_jump2; + } + else if (run) + { // running + if (duck) + { + ent->s.frame = FRAME_crwalk1; + client->anim_end = FRAME_crwalk6; + } + else + { + ent->s.frame = FRAME_run1; + client->anim_end = FRAME_run6; + } + } + else + { // standing + if (duck) + { + ent->s.frame = FRAME_crstnd01; + client->anim_end = FRAME_crstnd19; + } + else + { + ent->s.frame = FRAME_stand01; + client->anim_end = FRAME_stand40; + } + } +} + + +/* +================= +ClientEndServerFrame + +Called for each player at the end of the server frame +and right after spawning +================= +*/ +void ClientEndServerFrame (edict_t *ent) +{ + float bobtime; + int i; + + current_player = ent; + current_client = ent->client; + + // + // If the origin or velocity have changed since ClientThink(), + // update the pmove values. This will happen when the client + // is pushed by a bmodel or kicked by an explosion. + // + // If it wasn't updated here, the view position would lag a frame + // behind the body position when pushed -- "sinking into plats" + // + for (i=0 ; i<3 ; i++) + { + current_client->ps.pmove.origin[i] = ent->s.origin[i]*8.0; + current_client->ps.pmove.velocity[i] = ent->velocity[i]*8.0; + } + + // + // If the end of unit layout is displayed, don't give + // the player any normal movement attributes + // + if (level.intermissiontime) + { + // FIXME: add view drifting here? + current_client->ps.blend[3] = 0; + current_client->ps.fov = 90; + G_SetStats (ent); + return; + } + + AngleVectors (ent->client->v_angle, forward, right, up); + + // burn from lava, etc + P_WorldEffects (); + + // + // set model angles from view angles so other things in + // the world can tell which direction you are looking + // + if (ent->client->v_angle[PITCH] > 180) + ent->s.angles[PITCH] = (-360 + ent->client->v_angle[PITCH])/3; + else + ent->s.angles[PITCH] = ent->client->v_angle[PITCH]/3; + ent->s.angles[YAW] = ent->client->v_angle[YAW]; + ent->s.angles[ROLL] = 0; + ent->s.angles[ROLL] = SV_CalcRoll (ent->s.angles, ent->velocity)*4; + + // + // calculate speed and cycle to be used for + // all cyclic walking effects + // + xyspeed = sqrt(ent->velocity[0]*ent->velocity[0] + ent->velocity[1]*ent->velocity[1]); + + if (xyspeed < 5) + { + bobmove = 0; + current_client->bobtime = 0; // start at beginning of cycle again + } + else if (ent->groundentity) + { // so bobbing only cycles when on ground + if (xyspeed > 210) + bobmove = 0.25; + else if (xyspeed > 100) + bobmove = 0.125; + else + bobmove = 0.0625; + } + + bobtime = (current_client->bobtime += bobmove); + + if (current_client->ps.pmove.pm_flags & PMF_DUCKED) + bobtime *= 4; + + bobcycle = (int)bobtime; + bobfracsin = fabs(sin(bobtime*M_PI)); + + // detect hitting the floor + P_FallingDamage (ent); + + // apply all the damage taken this frame + P_DamageFeedback (ent); + + // determine the view offsets + SV_CalcViewOffset (ent); + + // determine the gun offsets + SV_CalcGunOffset (ent); + + // determine the full screen color blend + // must be after viewoffset, so eye contents can be + // accurately determined + // FIXME: with client prediction, the contents + // should be determined by the client + SV_CalcBlend (ent); + + // chase cam stuff + if (ent->client->resp.spectator) + G_SetSpectatorStats(ent); + else + G_SetStats (ent); + G_CheckChaseStats(ent); + + G_SetClientEvent (ent); + + G_SetClientEffects (ent); + + G_SetClientSound (ent); + + G_SetClientFrame (ent); + + VectorCopy (ent->velocity, ent->client->oldvelocity); + VectorCopy (ent->client->ps.viewangles, ent->client->oldviewangles); + + // clear weapon kicks + VectorClear (ent->client->kick_origin); + VectorClear (ent->client->kick_angles); + + // if the scoreboard is up, update it + if (ent->client->showscores && !(level.framenum & 31) ) + { + DeathmatchScoreboardMessage (ent, ent->enemy); + gi.unicast (ent, false); + } +} + diff --git a/game/p_weapon.c b/game/p_weapon.c new file mode 100644 index 000000000..dc418f355 --- /dev/null +++ b/game/p_weapon.c @@ -0,0 +1,1434 @@ +/* +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. + +*/ +// g_weapon.c + +#include "g_local.h" +#include "m_player.h" + + +static qboolean is_quad; +static byte is_silenced; + + +void weapon_grenade_fire (edict_t *ent, qboolean held); + + +static void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result) +{ + vec3_t _distance; + + VectorCopy (distance, _distance); + if (client->pers.hand == LEFT_HANDED) + _distance[1] *= -1; + else if (client->pers.hand == CENTER_HANDED) + _distance[1] = 0; + G_ProjectSource (point, _distance, forward, right, result); +} + + +/* +=============== +PlayerNoise + +Each player can have two noise objects associated with it: +a personal noise (jumping, pain, weapon firing), and a weapon +target noise (bullet wall impacts) + +Monsters that don't directly see the player can move +to a noise in hopes of seeing the player from there. +=============== +*/ +void PlayerNoise(edict_t *who, vec3_t where, int type) +{ + edict_t *noise; + + if (type == PNOISE_WEAPON) + { + if (who->client->silencer_shots) + { + who->client->silencer_shots--; + return; + } + } + + if (deathmatch->value) + return; + + if (who->flags & FL_NOTARGET) + return; + + + if (!who->mynoise) + { + noise = G_Spawn(); + noise->classname = "player_noise"; + VectorSet (noise->mins, -8, -8, -8); + VectorSet (noise->maxs, 8, 8, 8); + noise->owner = who; + noise->svflags = SVF_NOCLIENT; + who->mynoise = noise; + + noise = G_Spawn(); + noise->classname = "player_noise"; + VectorSet (noise->mins, -8, -8, -8); + VectorSet (noise->maxs, 8, 8, 8); + noise->owner = who; + noise->svflags = SVF_NOCLIENT; + who->mynoise2 = noise; + } + + if (type == PNOISE_SELF || type == PNOISE_WEAPON) + { + noise = who->mynoise; + level.sound_entity = noise; + level.sound_entity_framenum = level.framenum; + } + else // type == PNOISE_IMPACT + { + noise = who->mynoise2; + level.sound2_entity = noise; + level.sound2_entity_framenum = level.framenum; + } + + VectorCopy (where, noise->s.origin); + VectorSubtract (where, noise->maxs, noise->absmin); + VectorAdd (where, noise->maxs, noise->absmax); + noise->teleport_time = level.time; + gi.linkentity (noise); +} + + +qboolean Pickup_Weapon (edict_t *ent, edict_t *other) +{ + int index; + gitem_t *ammo; + + index = ITEM_INDEX(ent->item); + + if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value) + && other->client->pers.inventory[index]) + { + if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) ) + return false; // leave the weapon for others to pickup + } + + other->client->pers.inventory[index]++; + + if (!(ent->spawnflags & DROPPED_ITEM) ) + { + // give them some ammo with it + ammo = FindItem (ent->item->ammo); + if ( (int)dmflags->value & DF_INFINITE_AMMO ) + Add_Ammo (other, ammo, 1000); + else + Add_Ammo (other, ammo, ammo->quantity); + + if (! (ent->spawnflags & DROPPED_PLAYER_ITEM) ) + { + if (deathmatch->value) + { + if ((int)(dmflags->value) & DF_WEAPONS_STAY) + ent->flags |= FL_RESPAWN; + else + SetRespawn (ent, 30); + } + if (coop->value) + ent->flags |= FL_RESPAWN; + } + } + + if (other->client->pers.weapon != ent->item && + (other->client->pers.inventory[index] == 1) && + ( !deathmatch->value || other->client->pers.weapon == FindItem("blaster") ) ) + other->client->newweapon = ent->item; + + return true; +} + + +/* +=============== +ChangeWeapon + +The old weapon has been dropped all the way, so make the new one +current +=============== +*/ +void ChangeWeapon (edict_t *ent) +{ + int i; + + if (ent->client->grenade_time) + { + ent->client->grenade_time = level.time; + ent->client->weapon_sound = 0; + weapon_grenade_fire (ent, false); + ent->client->grenade_time = 0; + } + + ent->client->pers.lastweapon = ent->client->pers.weapon; + ent->client->pers.weapon = ent->client->newweapon; + ent->client->newweapon = NULL; + ent->client->machinegun_shots = 0; + + // set visible model + if (ent->s.modelindex == 255) { + if (ent->client->pers.weapon) + i = ((ent->client->pers.weapon->weapmodel & 0xff) << 8); + else + i = 0; + ent->s.skinnum = (ent - g_edicts - 1) | i; + } + + if (ent->client->pers.weapon && ent->client->pers.weapon->ammo) + ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo)); + else + ent->client->ammo_index = 0; + + if (!ent->client->pers.weapon) + { // dead + ent->client->ps.gunindex = 0; + return; + } + + ent->client->weaponstate = WEAPON_ACTIVATING; + ent->client->ps.gunframe = 0; + ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); + + ent->client->anim_priority = ANIM_PAIN; + if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) + { + ent->s.frame = FRAME_crpain1; + ent->client->anim_end = FRAME_crpain4; + } + else + { + ent->s.frame = FRAME_pain301; + ent->client->anim_end = FRAME_pain304; + + } +} + +/* +================= +NoAmmoWeaponChange +================= +*/ +void NoAmmoWeaponChange (edict_t *ent) +{ + if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("slugs"))] + && ent->client->pers.inventory[ITEM_INDEX(FindItem("railgun"))] ) + { + ent->client->newweapon = FindItem ("railgun"); + return; + } + if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))] + && ent->client->pers.inventory[ITEM_INDEX(FindItem("hyperblaster"))] ) + { + ent->client->newweapon = FindItem ("hyperblaster"); + return; + } + if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] + && ent->client->pers.inventory[ITEM_INDEX(FindItem("chaingun"))] ) + { + ent->client->newweapon = FindItem ("chaingun"); + return; + } + if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] + && ent->client->pers.inventory[ITEM_INDEX(FindItem("machinegun"))] ) + { + ent->client->newweapon = FindItem ("machinegun"); + return; + } + if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] > 1 + && ent->client->pers.inventory[ITEM_INDEX(FindItem("super shotgun"))] ) + { + ent->client->newweapon = FindItem ("super shotgun"); + return; + } + if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] + && ent->client->pers.inventory[ITEM_INDEX(FindItem("shotgun"))] ) + { + ent->client->newweapon = FindItem ("shotgun"); + return; + } + ent->client->newweapon = FindItem ("blaster"); +} + +/* +================= +Think_Weapon + +Called by ClientBeginServerFrame and ClientThink +================= +*/ +void Think_Weapon (edict_t *ent) +{ + // if just died, put the weapon away + if (ent->health < 1) + { + ent->client->newweapon = NULL; + ChangeWeapon (ent); + } + + // call active weapon think routine + if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink) + { + is_quad = (ent->client->quad_framenum > level.framenum); + if (ent->client->silencer_shots) + is_silenced = MZ_SILENCED; + else + is_silenced = 0; + ent->client->pers.weapon->weaponthink (ent); + } +} + + +/* +================ +Use_Weapon + +Make the weapon ready if there is ammo +================ +*/ +void Use_Weapon (edict_t *ent, gitem_t *item) +{ + int ammo_index; + gitem_t *ammo_item; + + // see if we're already using it + if (item == ent->client->pers.weapon) + return; + + if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO)) + { + ammo_item = FindItem(item->ammo); + ammo_index = ITEM_INDEX(ammo_item); + + if (!ent->client->pers.inventory[ammo_index]) + { + gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name); + return; + } + + if (ent->client->pers.inventory[ammo_index] < item->quantity) + { + gi.cprintf (ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name); + return; + } + } + + // change to this weapon when down + ent->client->newweapon = item; +} + + + +/* +================ +Drop_Weapon +================ +*/ +void Drop_Weapon (edict_t *ent, gitem_t *item) +{ + int index; + + if ((int)(dmflags->value) & DF_WEAPONS_STAY) + return; + + index = ITEM_INDEX(item); + // see if we're already using it + if ( ((item == ent->client->pers.weapon) || (item == ent->client->newweapon))&& (ent->client->pers.inventory[index] == 1) ) + { + gi.cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n"); + return; + } + + Drop_Item (ent, item); + ent->client->pers.inventory[index]--; +} + + +/* +================ +Weapon_Generic + +A generic function to handle the basics of weapon thinking +================ +*/ +#define FRAME_FIRE_FIRST (FRAME_ACTIVATE_LAST + 1) +#define FRAME_IDLE_FIRST (FRAME_FIRE_LAST + 1) +#define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1) + +void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent)) +{ + int n; + + if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses + { + return; + } + + if (ent->client->weaponstate == WEAPON_DROPPING) + { + if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST) + { + ChangeWeapon (ent); + return; + } + else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4) + { + ent->client->anim_priority = ANIM_REVERSE; + if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) + { + ent->s.frame = FRAME_crpain4+1; + ent->client->anim_end = FRAME_crpain1; + } + else + { + ent->s.frame = FRAME_pain304+1; + ent->client->anim_end = FRAME_pain301; + + } + } + + ent->client->ps.gunframe++; + return; + } + + if (ent->client->weaponstate == WEAPON_ACTIVATING) + { + if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST) + { + ent->client->weaponstate = WEAPON_READY; + ent->client->ps.gunframe = FRAME_IDLE_FIRST; + return; + } + + ent->client->ps.gunframe++; + return; + } + + if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING)) + { + ent->client->weaponstate = WEAPON_DROPPING; + ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST; + + if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4) + { + ent->client->anim_priority = ANIM_REVERSE; + if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) + { + ent->s.frame = FRAME_crpain4+1; + ent->client->anim_end = FRAME_crpain1; + } + else + { + ent->s.frame = FRAME_pain304+1; + ent->client->anim_end = FRAME_pain301; + + } + } + return; + } + + if (ent->client->weaponstate == WEAPON_READY) + { + if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) + { + ent->client->latched_buttons &= ~BUTTON_ATTACK; + if ((!ent->client->ammo_index) || + ( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity)) + { + ent->client->ps.gunframe = FRAME_FIRE_FIRST; + ent->client->weaponstate = WEAPON_FIRING; + + // start the animation + ent->client->anim_priority = ANIM_ATTACK; + if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) + { + ent->s.frame = FRAME_crattak1-1; + ent->client->anim_end = FRAME_crattak9; + } + else + { + ent->s.frame = FRAME_attack1-1; + ent->client->anim_end = FRAME_attack8; + } + } + else + { + if (level.time >= ent->pain_debounce_time) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); + ent->pain_debounce_time = level.time + 1; + } + NoAmmoWeaponChange (ent); + } + } + else + { + if (ent->client->ps.gunframe == FRAME_IDLE_LAST) + { + ent->client->ps.gunframe = FRAME_IDLE_FIRST; + return; + } + + if (pause_frames) + { + for (n = 0; pause_frames[n]; n++) + { + if (ent->client->ps.gunframe == pause_frames[n]) + { + if (rand()&15) + return; + } + } + } + + ent->client->ps.gunframe++; + return; + } + } + + if (ent->client->weaponstate == WEAPON_FIRING) + { + for (n = 0; fire_frames[n]; n++) + { + if (ent->client->ps.gunframe == fire_frames[n]) + { + if (ent->client->quad_framenum > level.framenum) + gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); + + fire (ent); + break; + } + } + + if (!fire_frames[n]) + ent->client->ps.gunframe++; + + if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1) + ent->client->weaponstate = WEAPON_READY; + } +} + + +/* +====================================================================== + +GRENADE + +====================================================================== +*/ + +#define GRENADE_TIMER 3.0 +#define GRENADE_MINSPEED 400 +#define GRENADE_MAXSPEED 800 + +void weapon_grenade_fire (edict_t *ent, qboolean held) +{ + vec3_t offset; + vec3_t forward, right; + vec3_t start; + int damage = 125; + float timer; + int speed; + float radius; + + radius = damage+40; + if (is_quad) + damage *= 4; + + VectorSet(offset, 8, 8, ent->viewheight-8); + AngleVectors (ent->client->v_angle, forward, right, NULL); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + + timer = ent->client->grenade_time - level.time; + speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER); + fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held); + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index]--; + + ent->client->grenade_time = level.time + 1.0; + + if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses + { + return; + } + + if (ent->health <= 0) + return; + + if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) + { + ent->client->anim_priority = ANIM_ATTACK; + ent->s.frame = FRAME_crattak1-1; + ent->client->anim_end = FRAME_crattak3; + } + else + { + ent->client->anim_priority = ANIM_REVERSE; + ent->s.frame = FRAME_wave08; + ent->client->anim_end = FRAME_wave01; + } +} + +void Weapon_Grenade (edict_t *ent) +{ + if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY)) + { + ChangeWeapon (ent); + return; + } + + if (ent->client->weaponstate == WEAPON_ACTIVATING) + { + ent->client->weaponstate = WEAPON_READY; + ent->client->ps.gunframe = 16; + return; + } + + if (ent->client->weaponstate == WEAPON_READY) + { + if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) + { + ent->client->latched_buttons &= ~BUTTON_ATTACK; + if (ent->client->pers.inventory[ent->client->ammo_index]) + { + ent->client->ps.gunframe = 1; + ent->client->weaponstate = WEAPON_FIRING; + ent->client->grenade_time = 0; + } + else + { + if (level.time >= ent->pain_debounce_time) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); + ent->pain_debounce_time = level.time + 1; + } + NoAmmoWeaponChange (ent); + } + return; + } + + if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48)) + { + if (rand()&15) + return; + } + + if (++ent->client->ps.gunframe > 48) + ent->client->ps.gunframe = 16; + return; + } + + if (ent->client->weaponstate == WEAPON_FIRING) + { + if (ent->client->ps.gunframe == 5) + gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0); + + if (ent->client->ps.gunframe == 11) + { + if (!ent->client->grenade_time) + { + ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2; + ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav"); + } + + // they waited too long, detonate it in their hand + if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time) + { + ent->client->weapon_sound = 0; + weapon_grenade_fire (ent, true); + ent->client->grenade_blew_up = true; + } + + if (ent->client->buttons & BUTTON_ATTACK) + return; + + if (ent->client->grenade_blew_up) + { + if (level.time >= ent->client->grenade_time) + { + ent->client->ps.gunframe = 15; + ent->client->grenade_blew_up = false; + } + else + { + return; + } + } + } + + if (ent->client->ps.gunframe == 12) + { + ent->client->weapon_sound = 0; + weapon_grenade_fire (ent, false); + } + + if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time)) + return; + + ent->client->ps.gunframe++; + + if (ent->client->ps.gunframe == 16) + { + ent->client->grenade_time = 0; + ent->client->weaponstate = WEAPON_READY; + } + } +} + +/* +====================================================================== + +GRENADE LAUNCHER + +====================================================================== +*/ + +void weapon_grenadelauncher_fire (edict_t *ent) +{ + vec3_t offset; + vec3_t forward, right; + vec3_t start; + int damage = 120; + float radius; + + radius = damage+40; + if (is_quad) + damage *= 4; + + VectorSet(offset, 8, 8, ent->viewheight-8); + AngleVectors (ent->client->v_angle, forward, right, NULL); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + + VectorScale (forward, -2, ent->client->kick_origin); + ent->client->kick_angles[0] = -1; + + fire_grenade (ent, start, forward, damage, 600, 2.5, radius); + + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_GRENADE | is_silenced); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + ent->client->ps.gunframe++; + + PlayerNoise(ent, start, PNOISE_WEAPON); + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index]--; +} + +void Weapon_GrenadeLauncher (edict_t *ent) +{ + static int pause_frames[] = {34, 51, 59, 0}; + static int fire_frames[] = {6, 0}; + + Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire); +} + +/* +====================================================================== + +ROCKET + +====================================================================== +*/ + +void Weapon_RocketLauncher_Fire (edict_t *ent) +{ + vec3_t offset, start; + vec3_t forward, right; + int damage; + float damage_radius; + int radius_damage; + + damage = 100 + (int)(random() * 20.0); + radius_damage = 120; + damage_radius = 120; + if (is_quad) + { + damage *= 4; + radius_damage *= 4; + } + + AngleVectors (ent->client->v_angle, forward, right, NULL); + + VectorScale (forward, -2, ent->client->kick_origin); + ent->client->kick_angles[0] = -1; + + VectorSet(offset, 8, 8, ent->viewheight-8); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage); + + // send muzzle flash + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_ROCKET | is_silenced); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + ent->client->ps.gunframe++; + + PlayerNoise(ent, start, PNOISE_WEAPON); + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index]--; +} + +void Weapon_RocketLauncher (edict_t *ent) +{ + static int pause_frames[] = {25, 33, 42, 50, 0}; + static int fire_frames[] = {5, 0}; + + Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire); +} + + +/* +====================================================================== + +BLASTER / HYPERBLASTER + +====================================================================== +*/ + +void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect) +{ + vec3_t forward, right; + vec3_t start; + vec3_t offset; + + if (is_quad) + damage *= 4; + AngleVectors (ent->client->v_angle, forward, right, NULL); + VectorSet(offset, 24, 8, ent->viewheight-8); + VectorAdd (offset, g_offset, offset); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + + VectorScale (forward, -2, ent->client->kick_origin); + ent->client->kick_angles[0] = -1; + + fire_blaster (ent, start, forward, damage, 1000, effect, hyper); + + // send muzzle flash + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + if (hyper) + gi.WriteByte (MZ_HYPERBLASTER | is_silenced); + else + gi.WriteByte (MZ_BLASTER | is_silenced); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + PlayerNoise(ent, start, PNOISE_WEAPON); +} + + +void Weapon_Blaster_Fire (edict_t *ent) +{ + int damage; + + if (deathmatch->value) + damage = 15; + else + damage = 10; + Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER); + ent->client->ps.gunframe++; +} + +void Weapon_Blaster (edict_t *ent) +{ + static int pause_frames[] = {19, 32, 0}; + static int fire_frames[] = {5, 0}; + + Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire); +} + + +void Weapon_HyperBlaster_Fire (edict_t *ent) +{ + float rotation; + vec3_t offset; + int effect; + int damage; + + ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav"); + + if (!(ent->client->buttons & BUTTON_ATTACK)) + { + ent->client->ps.gunframe++; + } + else + { + if (! ent->client->pers.inventory[ent->client->ammo_index] ) + { + if (level.time >= ent->pain_debounce_time) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); + ent->pain_debounce_time = level.time + 1; + } + NoAmmoWeaponChange (ent); + } + else + { + rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6; + offset[0] = -4 * sin(rotation); + offset[1] = 0; + offset[2] = 4 * cos(rotation); + + if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9)) + effect = EF_HYPERBLASTER; + else + effect = 0; + if (deathmatch->value) + damage = 15; + else + damage = 20; + Blaster_Fire (ent, offset, damage, true, effect); + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index]--; + + ent->client->anim_priority = ANIM_ATTACK; + if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) + { + ent->s.frame = FRAME_crattak1 - 1; + ent->client->anim_end = FRAME_crattak9; + } + else + { + ent->s.frame = FRAME_attack1 - 1; + ent->client->anim_end = FRAME_attack8; + } + } + + ent->client->ps.gunframe++; + if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index]) + ent->client->ps.gunframe = 6; + } + + if (ent->client->ps.gunframe == 12) + { + gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0); + ent->client->weapon_sound = 0; + } + +} + +void Weapon_HyperBlaster (edict_t *ent) +{ + static int pause_frames[] = {0}; + static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0}; + + Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire); +} + +/* +====================================================================== + +MACHINEGUN / CHAINGUN + +====================================================================== +*/ + +void Machinegun_Fire (edict_t *ent) +{ + int i; + vec3_t start; + vec3_t forward, right; + vec3_t angles; + int damage = 8; + int kick = 2; + vec3_t offset; + + if (!(ent->client->buttons & BUTTON_ATTACK)) + { + ent->client->machinegun_shots = 0; + ent->client->ps.gunframe++; + return; + } + + if (ent->client->ps.gunframe == 5) + ent->client->ps.gunframe = 4; + else + ent->client->ps.gunframe = 5; + + if (ent->client->pers.inventory[ent->client->ammo_index] < 1) + { + ent->client->ps.gunframe = 6; + if (level.time >= ent->pain_debounce_time) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); + ent->pain_debounce_time = level.time + 1; + } + NoAmmoWeaponChange (ent); + return; + } + + if (is_quad) + { + damage *= 4; + kick *= 4; + } + + for (i=1 ; i<3 ; i++) + { + ent->client->kick_origin[i] = crandom() * 0.35; + ent->client->kick_angles[i] = crandom() * 0.7; + } + ent->client->kick_origin[0] = crandom() * 0.35; + ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5; + + // raise the gun as it is firing + if (!deathmatch->value) + { + ent->client->machinegun_shots++; + if (ent->client->machinegun_shots > 9) + ent->client->machinegun_shots = 9; + } + + // get start / end positions + VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles); + AngleVectors (angles, forward, right, NULL); + VectorSet(offset, 0, 8, ent->viewheight-8); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); + + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_MACHINEGUN | is_silenced); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + PlayerNoise(ent, start, PNOISE_WEAPON); + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index]--; + + ent->client->anim_priority = ANIM_ATTACK; + if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) + { + ent->s.frame = FRAME_crattak1 - (int) (random()+0.25); + ent->client->anim_end = FRAME_crattak9; + } + else + { + ent->s.frame = FRAME_attack1 - (int) (random()+0.25); + ent->client->anim_end = FRAME_attack8; + } +} + +void Weapon_Machinegun (edict_t *ent) +{ + static int pause_frames[] = {23, 45, 0}; + static int fire_frames[] = {4, 5, 0}; + + Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire); +} + +void Chaingun_Fire (edict_t *ent) +{ + int i; + int shots; + vec3_t start; + vec3_t forward, right, up; + float r, u; + vec3_t offset; + int damage; + int kick = 2; + + if (deathmatch->value) + damage = 6; + else + damage = 8; + + if (ent->client->ps.gunframe == 5) + gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0); + + if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK)) + { + ent->client->ps.gunframe = 32; + ent->client->weapon_sound = 0; + return; + } + else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK) + && ent->client->pers.inventory[ent->client->ammo_index]) + { + ent->client->ps.gunframe = 15; + } + else + { + ent->client->ps.gunframe++; + } + + if (ent->client->ps.gunframe == 22) + { + ent->client->weapon_sound = 0; + gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0); + } + else + { + ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav"); + } + + ent->client->anim_priority = ANIM_ATTACK; + if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) + { + ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1); + ent->client->anim_end = FRAME_crattak9; + } + else + { + ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1); + ent->client->anim_end = FRAME_attack8; + } + + if (ent->client->ps.gunframe <= 9) + shots = 1; + else if (ent->client->ps.gunframe <= 14) + { + if (ent->client->buttons & BUTTON_ATTACK) + shots = 2; + else + shots = 1; + } + else + shots = 3; + + if (ent->client->pers.inventory[ent->client->ammo_index] < shots) + shots = ent->client->pers.inventory[ent->client->ammo_index]; + + if (!shots) + { + if (level.time >= ent->pain_debounce_time) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); + ent->pain_debounce_time = level.time + 1; + } + NoAmmoWeaponChange (ent); + return; + } + + if (is_quad) + { + damage *= 4; + kick *= 4; + } + + for (i=0 ; i<3 ; i++) + { + ent->client->kick_origin[i] = crandom() * 0.35; + ent->client->kick_angles[i] = crandom() * 0.7; + } + + for (i=0 ; iclient->v_angle, forward, right, up); + r = 7 + crandom()*4; + u = crandom()*4; + VectorSet(offset, 0, r, u + ent->viewheight-8); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + + fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN); + } + + // send muzzle flash + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + PlayerNoise(ent, start, PNOISE_WEAPON); + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index] -= shots; +} + + +void Weapon_Chaingun (edict_t *ent) +{ + static int pause_frames[] = {38, 43, 51, 61, 0}; + static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0}; + + Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire); +} + + +/* +====================================================================== + +SHOTGUN / SUPERSHOTGUN + +====================================================================== +*/ + +void weapon_shotgun_fire (edict_t *ent) +{ + vec3_t start; + vec3_t forward, right; + vec3_t offset; + int damage = 4; + int kick = 8; + + if (ent->client->ps.gunframe == 9) + { + ent->client->ps.gunframe++; + return; + } + + AngleVectors (ent->client->v_angle, forward, right, NULL); + + VectorScale (forward, -2, ent->client->kick_origin); + ent->client->kick_angles[0] = -2; + + VectorSet(offset, 0, 8, ent->viewheight-8); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + + if (is_quad) + { + damage *= 4; + kick *= 4; + } + + if (deathmatch->value) + fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN); + else + fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN); + + // send muzzle flash + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_SHOTGUN | is_silenced); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + ent->client->ps.gunframe++; + PlayerNoise(ent, start, PNOISE_WEAPON); + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index]--; +} + +void Weapon_Shotgun (edict_t *ent) +{ + static int pause_frames[] = {22, 28, 34, 0}; + static int fire_frames[] = {8, 9, 0}; + + Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire); +} + + +void weapon_supershotgun_fire (edict_t *ent) +{ + vec3_t start; + vec3_t forward, right; + vec3_t offset; + vec3_t v; + int damage = 6; + int kick = 12; + + AngleVectors (ent->client->v_angle, forward, right, NULL); + + VectorScale (forward, -2, ent->client->kick_origin); + ent->client->kick_angles[0] = -2; + + VectorSet(offset, 0, 8, ent->viewheight-8); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + + if (is_quad) + { + damage *= 4; + kick *= 4; + } + + v[PITCH] = ent->client->v_angle[PITCH]; + v[YAW] = ent->client->v_angle[YAW] - 5; + v[ROLL] = ent->client->v_angle[ROLL]; + AngleVectors (v, forward, NULL, NULL); + fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); + v[YAW] = ent->client->v_angle[YAW] + 5; + AngleVectors (v, forward, NULL, NULL); + fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); + + // send muzzle flash + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_SSHOTGUN | is_silenced); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + ent->client->ps.gunframe++; + PlayerNoise(ent, start, PNOISE_WEAPON); + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index] -= 2; +} + +void Weapon_SuperShotgun (edict_t *ent) +{ + static int pause_frames[] = {29, 42, 57, 0}; + static int fire_frames[] = {7, 0}; + + Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire); +} + + + +/* +====================================================================== + +RAILGUN + +====================================================================== +*/ + +void weapon_railgun_fire (edict_t *ent) +{ + vec3_t start; + vec3_t forward, right; + vec3_t offset; + int damage; + int kick; + + if (deathmatch->value) + { // normal damage is too extreme in dm + damage = 100; + kick = 200; + } + else + { + damage = 150; + kick = 250; + } + + if (is_quad) + { + damage *= 4; + kick *= 4; + } + + AngleVectors (ent->client->v_angle, forward, right, NULL); + + VectorScale (forward, -3, ent->client->kick_origin); + ent->client->kick_angles[0] = -3; + + VectorSet(offset, 0, 7, ent->viewheight-8); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + fire_rail (ent, start, forward, damage, kick); + + // send muzzle flash + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_RAILGUN | is_silenced); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + ent->client->ps.gunframe++; + PlayerNoise(ent, start, PNOISE_WEAPON); + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index]--; +} + + +void Weapon_Railgun (edict_t *ent) +{ + static int pause_frames[] = {56, 0}; + static int fire_frames[] = {4, 0}; + + Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire); +} + + +/* +====================================================================== + +BFG10K + +====================================================================== +*/ + +void weapon_bfg_fire (edict_t *ent) +{ + vec3_t offset, start; + vec3_t forward, right; + int damage; + float damage_radius = 1000; + + if (deathmatch->value) + damage = 200; + else + damage = 500; + + if (ent->client->ps.gunframe == 9) + { + // send muzzle flash + gi.WriteByte (svc_muzzleflash); + gi.WriteShort (ent-g_edicts); + gi.WriteByte (MZ_BFG | is_silenced); + gi.multicast (ent->s.origin, MULTICAST_PVS); + + ent->client->ps.gunframe++; + + PlayerNoise(ent, ent->s.origin, PNOISE_WEAPON); + return; + } + + // cells can go down during windup (from power armor hits), so + // check again and abort firing if we don't have enough now + if (ent->client->pers.inventory[ent->client->ammo_index] < 50) + { + ent->client->ps.gunframe++; + return; + } + + if (is_quad) + damage *= 4; + + AngleVectors (ent->client->v_angle, forward, right, NULL); + + VectorScale (forward, -2, ent->client->kick_origin); + + // make a big pitch kick with an inverse fall + ent->client->v_dmg_pitch = -40; + ent->client->v_dmg_roll = crandom()*8; + ent->client->v_dmg_time = level.time + DAMAGE_TIME; + + VectorSet(offset, 8, 8, ent->viewheight-8); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + fire_bfg (ent, start, forward, damage, 400, damage_radius); + + ent->client->ps.gunframe++; + + PlayerNoise(ent, start, PNOISE_WEAPON); + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index] -= 50; +} + +void Weapon_BFG (edict_t *ent) +{ + static int pause_frames[] = {39, 45, 50, 55, 0}; + static int fire_frames[] = {9, 17, 0}; + + Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire); +} + + +//====================================================================== diff --git a/game/q_shared.c b/game/q_shared.c new file mode 100644 index 000000000..9f640a373 --- /dev/null +++ b/game/q_shared.c @@ -0,0 +1,1418 @@ +/* +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. + +*/ +#include "q_shared.h" + +#define DEG2RAD( a ) ( a * M_PI ) / 180.0F + +vec3_t vec3_origin = {0,0,0}; + +//============================================================================ + +#ifdef _WIN32 +#pragma optimize( "", off ) +#endif + +void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ) +{ + float m[3][3]; + float im[3][3]; + float zrot[3][3]; + float tmpmat[3][3]; + float rot[3][3]; + int i; + vec3_t vr, vup, vf; + + vf[0] = dir[0]; + vf[1] = dir[1]; + vf[2] = dir[2]; + + PerpendicularVector( vr, dir ); + CrossProduct( vr, vf, vup ); + + m[0][0] = vr[0]; + m[1][0] = vr[1]; + m[2][0] = vr[2]; + + m[0][1] = vup[0]; + m[1][1] = vup[1]; + m[2][1] = vup[2]; + + m[0][2] = vf[0]; + m[1][2] = vf[1]; + m[2][2] = vf[2]; + + memcpy( im, m, sizeof( im ) ); + + im[0][1] = m[1][0]; + im[0][2] = m[2][0]; + im[1][0] = m[0][1]; + im[1][2] = m[2][1]; + im[2][0] = m[0][2]; + im[2][1] = m[1][2]; + + memset( zrot, 0, sizeof( zrot ) ); + zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F; + + zrot[0][0] = cos( DEG2RAD( degrees ) ); + zrot[0][1] = sin( DEG2RAD( degrees ) ); + zrot[1][0] = -sin( DEG2RAD( degrees ) ); + zrot[1][1] = cos( DEG2RAD( degrees ) ); + + R_ConcatRotations( m, zrot, tmpmat ); + R_ConcatRotations( tmpmat, im, rot ); + + for ( i = 0; i < 3; i++ ) + { + dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2]; + } +} + +#ifdef _WIN32 +#pragma optimize( "", on ) +#endif + + + +void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) +{ + float angle; + static float sr, sp, sy, cr, cp, cy; + // static to help MS compiler fp bugs + + angle = angles[YAW] * (M_PI*2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[PITCH] * (M_PI*2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[ROLL] * (M_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + if (forward) + { + forward[0] = cp*cy; + forward[1] = cp*sy; + forward[2] = -sp; + } + if (right) + { + right[0] = (-1*sr*sp*cy+-1*cr*-sy); + right[1] = (-1*sr*sp*sy+-1*cr*cy); + right[2] = -1*sr*cp; + } + if (up) + { + up[0] = (cr*sp*cy+-sr*-sy); + up[1] = (cr*sp*sy+-sr*cy); + up[2] = cr*cp; + } +} + + +void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ) +{ + float d; + vec3_t n; + float inv_denom; + + inv_denom = 1.0F / DotProduct( normal, normal ); + + d = DotProduct( normal, p ) * inv_denom; + + n[0] = normal[0] * inv_denom; + n[1] = normal[1] * inv_denom; + n[2] = normal[2] * inv_denom; + + dst[0] = p[0] - d * n[0]; + dst[1] = p[1] - d * n[1]; + dst[2] = p[2] - d * n[2]; +} + +/* +** assumes "src" is normalized +*/ +void PerpendicularVector( vec3_t dst, const vec3_t src ) +{ + int pos; + int i; + float minelem = 1.0F; + vec3_t tempvec; + + /* + ** find the smallest magnitude axially aligned vector + */ + for ( pos = 0, i = 0; i < 3; i++ ) + { + if ( fabs( src[i] ) < minelem ) + { + pos = i; + minelem = fabs( src[i] ); + } + } + tempvec[0] = tempvec[1] = tempvec[2] = 0.0F; + tempvec[pos] = 1.0F; + + /* + ** project the point onto the plane defined by src + */ + ProjectPointOnPlane( dst, tempvec, src ); + + /* + ** normalize the result + */ + VectorNormalize( dst ); +} + + + +/* +================ +R_ConcatRotations +================ +*/ +void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + + in1[0][2] * in2[2][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + + in1[0][2] * in2[2][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + + in1[0][2] * in2[2][2]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + + in1[1][2] * in2[2][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + + in1[1][2] * in2[2][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + + in1[1][2] * in2[2][2]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + + in1[2][2] * in2[2][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + + in1[2][2] * in2[2][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + + in1[2][2] * in2[2][2]; +} + + +/* +================ +R_ConcatTransforms +================ +*/ +void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + + in1[0][2] * in2[2][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + + in1[0][2] * in2[2][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + + in1[0][2] * in2[2][2]; + out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + + in1[0][2] * in2[2][3] + in1[0][3]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + + in1[1][2] * in2[2][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + + in1[1][2] * in2[2][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + + in1[1][2] * in2[2][2]; + out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + + in1[1][2] * in2[2][3] + in1[1][3]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + + in1[2][2] * in2[2][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + + in1[2][2] * in2[2][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + + in1[2][2] * in2[2][2]; + out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + + in1[2][2] * in2[2][3] + in1[2][3]; +} + + +//============================================================================ + + +float Q_fabs (float f) +{ +#if 0 + if (f >= 0) + return f; + return -f; +#else + int tmp = * ( int * ) &f; + tmp &= 0x7FFFFFFF; + return * ( float * ) &tmp; +#endif +} + +#if defined _M_IX86 && !defined C_ONLY +#pragma warning (disable:4035) +__declspec( naked ) long Q_ftol( float f ) +{ + static int tmp; + __asm fld dword ptr [esp+4] + __asm fistp tmp + __asm mov eax, tmp + __asm ret +} +#pragma warning (default:4035) +#endif + +/* +=============== +LerpAngle + +=============== +*/ +float LerpAngle (float a2, float a1, float frac) +{ + if (a1 - a2 > 180) + a1 -= 360; + if (a1 - a2 < -180) + a1 += 360; + return a2 + frac * (a1 - a2); +} + + +float anglemod(float a) +{ +#if 0 + if (a >= 0) + a -= 360*(int)(a/360); + else + a += 360*( 1 + (int)(-a/360) ); +#endif + a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535); + return a; +} + + int i; + vec3_t corners[2]; + + +// this is the slow, general version +int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p) +{ + int i; + float dist1, dist2; + int sides; + vec3_t corners[2]; + + for (i=0 ; i<3 ; i++) + { + if (p->normal[i] < 0) + { + corners[0][i] = emins[i]; + corners[1][i] = emaxs[i]; + } + else + { + corners[1][i] = emins[i]; + corners[0][i] = emaxs[i]; + } + } + dist1 = DotProduct (p->normal, corners[0]) - p->dist; + dist2 = DotProduct (p->normal, corners[1]) - p->dist; + sides = 0; + if (dist1 >= 0) + sides = 1; + if (dist2 < 0) + sides |= 2; + + return sides; +} + +/* +================== +BoxOnPlaneSide + +Returns 1, 2, or 1 + 2 +================== +*/ +#if !id386 || defined __linux__ +int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p) +{ + float dist1, dist2; + int sides; + +// fast axial cases + if (p->type < 3) + { + if (p->dist <= emins[p->type]) + return 1; + if (p->dist >= emaxs[p->type]) + return 2; + return 3; + } + +// general case + switch (p->signbits) + { + case 0: +dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; + break; + case 1: +dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; + break; + case 2: +dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; + break; + case 3: +dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; + break; + case 4: +dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; + break; + case 5: +dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; + break; + case 6: +dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; + break; + case 7: +dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; + break; + default: + dist1 = dist2 = 0; // shut up compiler + assert( 0 ); + break; + } + + sides = 0; + if (dist1 >= p->dist) + sides = 1; + if (dist2 < p->dist) + sides |= 2; + + assert( sides != 0 ); + + return sides; +} +#else +#pragma warning( disable: 4035 ) + +__declspec( naked ) int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p) +{ + static int bops_initialized; + static int Ljmptab[8]; + + __asm { + + push ebx + + cmp bops_initialized, 1 + je initialized + mov bops_initialized, 1 + + mov Ljmptab[0*4], offset Lcase0 + mov Ljmptab[1*4], offset Lcase1 + mov Ljmptab[2*4], offset Lcase2 + mov Ljmptab[3*4], offset Lcase3 + mov Ljmptab[4*4], offset Lcase4 + mov Ljmptab[5*4], offset Lcase5 + mov Ljmptab[6*4], offset Lcase6 + mov Ljmptab[7*4], offset Lcase7 + +initialized: + + mov edx,ds:dword ptr[4+12+esp] + mov ecx,ds:dword ptr[4+4+esp] + xor eax,eax + mov ebx,ds:dword ptr[4+8+esp] + mov al,ds:byte ptr[17+edx] + cmp al,8 + jge Lerror + fld ds:dword ptr[0+edx] + fld st(0) + jmp dword ptr[Ljmptab+eax*4] +Lcase0: + fmul ds:dword ptr[ebx] + fld ds:dword ptr[0+4+edx] + fxch st(2) + fmul ds:dword ptr[ecx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[4+ebx] + fld ds:dword ptr[0+8+edx] + fxch st(2) + fmul ds:dword ptr[4+ecx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[8+ebx] + fxch st(5) + faddp st(3),st(0) + fmul ds:dword ptr[8+ecx] + fxch st(1) + faddp st(3),st(0) + fxch st(3) + faddp st(2),st(0) + jmp LSetSides +Lcase1: + fmul ds:dword ptr[ecx] + fld ds:dword ptr[0+4+edx] + fxch st(2) + fmul ds:dword ptr[ebx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[4+ebx] + fld ds:dword ptr[0+8+edx] + fxch st(2) + fmul ds:dword ptr[4+ecx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[8+ebx] + fxch st(5) + faddp st(3),st(0) + fmul ds:dword ptr[8+ecx] + fxch st(1) + faddp st(3),st(0) + fxch st(3) + faddp st(2),st(0) + jmp LSetSides +Lcase2: + fmul ds:dword ptr[ebx] + fld ds:dword ptr[0+4+edx] + fxch st(2) + fmul ds:dword ptr[ecx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[4+ecx] + fld ds:dword ptr[0+8+edx] + fxch st(2) + fmul ds:dword ptr[4+ebx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[8+ebx] + fxch st(5) + faddp st(3),st(0) + fmul ds:dword ptr[8+ecx] + fxch st(1) + faddp st(3),st(0) + fxch st(3) + faddp st(2),st(0) + jmp LSetSides +Lcase3: + fmul ds:dword ptr[ecx] + fld ds:dword ptr[0+4+edx] + fxch st(2) + fmul ds:dword ptr[ebx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[4+ecx] + fld ds:dword ptr[0+8+edx] + fxch st(2) + fmul ds:dword ptr[4+ebx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[8+ebx] + fxch st(5) + faddp st(3),st(0) + fmul ds:dword ptr[8+ecx] + fxch st(1) + faddp st(3),st(0) + fxch st(3) + faddp st(2),st(0) + jmp LSetSides +Lcase4: + fmul ds:dword ptr[ebx] + fld ds:dword ptr[0+4+edx] + fxch st(2) + fmul ds:dword ptr[ecx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[4+ebx] + fld ds:dword ptr[0+8+edx] + fxch st(2) + fmul ds:dword ptr[4+ecx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[8+ecx] + fxch st(5) + faddp st(3),st(0) + fmul ds:dword ptr[8+ebx] + fxch st(1) + faddp st(3),st(0) + fxch st(3) + faddp st(2),st(0) + jmp LSetSides +Lcase5: + fmul ds:dword ptr[ecx] + fld ds:dword ptr[0+4+edx] + fxch st(2) + fmul ds:dword ptr[ebx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[4+ebx] + fld ds:dword ptr[0+8+edx] + fxch st(2) + fmul ds:dword ptr[4+ecx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[8+ecx] + fxch st(5) + faddp st(3),st(0) + fmul ds:dword ptr[8+ebx] + fxch st(1) + faddp st(3),st(0) + fxch st(3) + faddp st(2),st(0) + jmp LSetSides +Lcase6: + fmul ds:dword ptr[ebx] + fld ds:dword ptr[0+4+edx] + fxch st(2) + fmul ds:dword ptr[ecx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[4+ecx] + fld ds:dword ptr[0+8+edx] + fxch st(2) + fmul ds:dword ptr[4+ebx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[8+ecx] + fxch st(5) + faddp st(3),st(0) + fmul ds:dword ptr[8+ebx] + fxch st(1) + faddp st(3),st(0) + fxch st(3) + faddp st(2),st(0) + jmp LSetSides +Lcase7: + fmul ds:dword ptr[ecx] + fld ds:dword ptr[0+4+edx] + fxch st(2) + fmul ds:dword ptr[ebx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[4+ecx] + fld ds:dword ptr[0+8+edx] + fxch st(2) + fmul ds:dword ptr[4+ebx] + fxch st(2) + fld st(0) + fmul ds:dword ptr[8+ecx] + fxch st(5) + faddp st(3),st(0) + fmul ds:dword ptr[8+ebx] + fxch st(1) + faddp st(3),st(0) + fxch st(3) + faddp st(2),st(0) +LSetSides: + faddp st(2),st(0) + fcomp ds:dword ptr[12+edx] + xor ecx,ecx + fnstsw ax + fcomp ds:dword ptr[12+edx] + and ah,1 + xor ah,1 + add cl,ah + fnstsw ax + and ah,1 + add ah,ah + add cl,ah + pop ebx + mov eax,ecx + ret +Lerror: + int 3 + } +} +#pragma warning( default: 4035 ) +#endif + +void ClearBounds (vec3_t mins, vec3_t maxs) +{ + mins[0] = mins[1] = mins[2] = 99999; + maxs[0] = maxs[1] = maxs[2] = -99999; +} + +void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs) +{ + int i; + vec_t val; + + for (i=0 ; i<3 ; i++) + { + val = v[i]; + if (val < mins[i]) + mins[i] = val; + if (val > maxs[i]) + maxs[i] = val; + } +} + + +int VectorCompare (vec3_t v1, vec3_t v2) +{ + if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2]) + return 0; + + return 1; +} + + +vec_t VectorNormalize (vec3_t v) +{ + float length, ilength; + + length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; + length = sqrt (length); // FIXME + + if (length) + { + ilength = 1/length; + v[0] *= ilength; + v[1] *= ilength; + v[2] *= ilength; + } + + return length; + +} + +vec_t VectorNormalize2 (vec3_t v, vec3_t out) +{ + float length, ilength; + + length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; + length = sqrt (length); // FIXME + + if (length) + { + ilength = 1/length; + out[0] = v[0]*ilength; + out[1] = v[1]*ilength; + out[2] = v[2]*ilength; + } + + return length; + +} + +void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) +{ + vecc[0] = veca[0] + scale*vecb[0]; + vecc[1] = veca[1] + scale*vecb[1]; + vecc[2] = veca[2] + scale*vecb[2]; +} + + +vec_t _DotProduct (vec3_t v1, vec3_t v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out) +{ + out[0] = veca[0]-vecb[0]; + out[1] = veca[1]-vecb[1]; + out[2] = veca[2]-vecb[2]; +} + +void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out) +{ + out[0] = veca[0]+vecb[0]; + out[1] = veca[1]+vecb[1]; + out[2] = veca[2]+vecb[2]; +} + +void _VectorCopy (vec3_t in, vec3_t out) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; +} + +void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross) +{ + cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; + cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; + cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} + +double sqrt(double x); + +vec_t VectorLength(vec3_t v) +{ + int i; + float length; + + length = 0; + for (i=0 ; i< 3 ; i++) + length += v[i]*v[i]; + length = sqrt (length); // FIXME + + return length; +} + +void VectorInverse (vec3_t v) +{ + v[0] = -v[0]; + v[1] = -v[1]; + v[2] = -v[2]; +} + +void VectorScale (vec3_t in, vec_t scale, vec3_t out) +{ + out[0] = in[0]*scale; + out[1] = in[1]*scale; + out[2] = in[2]*scale; +} + + +int Q_log2(int val) +{ + int answer=0; + while (val>>=1) + answer++; + return answer; +} + + + +//==================================================================================== + +/* +============ +COM_SkipPath +============ +*/ +char *COM_SkipPath (char *pathname) +{ + char *last; + + last = pathname; + while (*pathname) + { + if (*pathname=='/') + last = pathname+1; + pathname++; + } + return last; +} + +/* +============ +COM_StripExtension +============ +*/ +void COM_StripExtension (char *in, char *out) +{ + while (*in && *in != '.') + *out++ = *in++; + *out = 0; +} + +/* +============ +COM_FileExtension +============ +*/ +char *COM_FileExtension (char *in) +{ + static char exten[8]; + int i; + + while (*in && *in != '.') + in++; + if (!*in) + return ""; + in++; + for (i=0 ; i<7 && *in ; i++,in++) + exten[i] = *in; + exten[i] = 0; + return exten; +} + +/* +============ +COM_FileBase +============ +*/ +void COM_FileBase (char *in, char *out) +{ + char *s, *s2; + + s = in + strlen(in) - 1; + + while (s != in && *s != '.') + s--; + + for (s2 = s ; s2 != in && *s2 != '/' ; s2--) + ; + + if (s-s2 < 2) + out[0] = 0; + else + { + s--; + strncpy (out,s2+1, s-s2); + out[s-s2] = 0; + } +} + +/* +============ +COM_FilePath + +Returns the path up to, but not including the last / +============ +*/ +void COM_FilePath (char *in, char *out) +{ + char *s; + + s = in + strlen(in) - 1; + + while (s != in && *s != '/') + s--; + + strncpy (out,in, s-in); + out[s-in] = 0; +} + + +/* +================== +COM_DefaultExtension +================== +*/ +void COM_DefaultExtension (char *path, char *extension) +{ + char *src; +// +// if path doesn't have a .EXT, append extension +// (extension should include the .) +// + src = path + strlen(path) - 1; + + while (*src != '/' && src != path) + { + if (*src == '.') + return; // it has an extension + src--; + } + + strcat (path, extension); +} + +/* +============================================================================ + + BYTE ORDER FUNCTIONS + +============================================================================ +*/ + +qboolean bigendien; + +// can't just use function pointers, or dll linkage can +// mess up when qcommon is included in multiple places +short (*_BigShort) (short l); +short (*_LittleShort) (short l); +int (*_BigLong) (int l); +int (*_LittleLong) (int l); +float (*_BigFloat) (float l); +float (*_LittleFloat) (float l); + +short BigShort(short l){return _BigShort(l);} +short LittleShort(short l) {return _LittleShort(l);} +int BigLong (int l) {return _BigLong(l);} +int LittleLong (int l) {return _LittleLong(l);} +float BigFloat (float l) {return _BigFloat(l);} +float LittleFloat (float l) {return _LittleFloat(l);} + +short ShortSwap (short l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; +} + +short ShortNoSwap (short l) +{ + return l; +} + +int LongSwap (int l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; +} + +int LongNoSwap (int l) +{ + return l; +} + +float FloatSwap (float f) +{ + union + { + float f; + byte b[4]; + } dat1, dat2; + + + dat1.f = f; + dat2.b[0] = dat1.b[3]; + dat2.b[1] = dat1.b[2]; + dat2.b[2] = dat1.b[1]; + dat2.b[3] = dat1.b[0]; + return dat2.f; +} + +float FloatNoSwap (float f) +{ + return f; +} + +/* +================ +Swap_Init +================ +*/ +void Swap_Init (void) +{ + byte swaptest[2] = {1,0}; + +// set the byte swapping variables in a portable manner + if ( *(short *)swaptest == 1) + { + bigendien = false; + _BigShort = ShortSwap; + _LittleShort = ShortNoSwap; + _BigLong = LongSwap; + _LittleLong = LongNoSwap; + _BigFloat = FloatSwap; + _LittleFloat = FloatNoSwap; + } + else + { + bigendien = true; + _BigShort = ShortNoSwap; + _LittleShort = ShortSwap; + _BigLong = LongNoSwap; + _LittleLong = LongSwap; + _BigFloat = FloatNoSwap; + _LittleFloat = FloatSwap; + } + +} + + + +/* +============ +va + +does a varargs printf into a temp buffer, so I don't need to have +varargs versions of all text functions. +FIXME: make this buffer size safe someday +============ +*/ +char *va(char *format, ...) +{ + va_list argptr; + static char string[1024]; + + va_start (argptr, format); + vsprintf (string, format,argptr); + va_end (argptr); + + return string; +} + + +char com_token[MAX_TOKEN_CHARS]; + +/* +============== +COM_Parse + +Parse a token out of a string +============== +*/ +char *COM_Parse (char **data_p) +{ + int c; + int len; + char *data; + + data = *data_p; + len = 0; + com_token[0] = 0; + + if (!data) + { + *data_p = NULL; + return ""; + } + +// skip whitespace +skipwhite: + while ( (c = *data) <= ' ') + { + if (c == 0) + { + *data_p = NULL; + return ""; + } + data++; + } + +// skip // comments + if (c=='/' && data[1] == '/') + { + while (*data && *data != '\n') + data++; + goto skipwhite; + } + +// handle quoted strings specially + if (c == '\"') + { + data++; + while (1) + { + c = *data++; + if (c=='\"' || !c) + { + com_token[len] = 0; + *data_p = data; + return com_token; + } + if (len < MAX_TOKEN_CHARS) + { + com_token[len] = c; + len++; + } + } + } + +// parse a regular word + do + { + if (len < MAX_TOKEN_CHARS) + { + com_token[len] = c; + len++; + } + data++; + c = *data; + } while (c>32); + + if (len == MAX_TOKEN_CHARS) + { +// Com_Printf ("Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS); + len = 0; + } + com_token[len] = 0; + + *data_p = data; + return com_token; +} + + +/* +=============== +Com_PageInMemory + +=============== +*/ +int paged_total; + +void Com_PageInMemory (byte *buffer, int size) +{ + int i; + + for (i=size-1 ; i>0 ; i-=4096) + paged_total += buffer[i]; +} + + + +/* +============================================================================ + + LIBRARY REPLACEMENT FUNCTIONS + +============================================================================ +*/ + +// FIXME: replace all Q_stricmp with Q_strcasecmp +int Q_stricmp (char *s1, char *s2) +{ +#if defined(WIN32) + return _stricmp (s1, s2); +#else + return strcasecmp (s1, s2); +#endif +} + + +int Q_strncasecmp (char *s1, char *s2, int n) +{ + int c1, c2; + + do + { + c1 = *s1++; + c2 = *s2++; + + if (!n--) + return 0; // strings are equal until end point + + if (c1 != c2) + { + if (c1 >= 'a' && c1 <= 'z') + c1 -= ('a' - 'A'); + if (c2 >= 'a' && c2 <= 'z') + c2 -= ('a' - 'A'); + if (c1 != c2) + return -1; // strings not equal + } + } while (c1); + + return 0; // strings are equal +} + +int Q_strcasecmp (char *s1, char *s2) +{ + return Q_strncasecmp (s1, s2, 99999); +} + + + +void Com_sprintf (char *dest, int size, char *fmt, ...) +{ + int len; + va_list argptr; + char bigbuffer[0x10000]; + + va_start (argptr,fmt); + len = vsprintf (bigbuffer,fmt,argptr); + va_end (argptr); + if (len >= size) + Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size); + strncpy (dest, bigbuffer, size-1); +} + +/* +===================================================================== + + INFO STRINGS + +===================================================================== +*/ + +/* +=============== +Info_ValueForKey + +Searches the string for the given +key and returns the associated value, or an empty string. +=============== +*/ +char *Info_ValueForKey (char *s, char *key) +{ + char pkey[512]; + static char value[2][512]; // use two buffers so compares + // work without stomping on each other + static int valueindex; + char *o; + + valueindex ^= 1; + if (*s == '\\') + s++; + while (1) + { + o = pkey; + while (*s != '\\') + { + if (!*s) + return ""; + *o++ = *s++; + } + *o = 0; + s++; + + o = value[valueindex]; + + while (*s != '\\' && *s) + { + if (!*s) + return ""; + *o++ = *s++; + } + *o = 0; + + if (!strcmp (key, pkey) ) + return value[valueindex]; + + if (!*s) + return ""; + s++; + } +} + +void Info_RemoveKey (char *s, char *key) +{ + char *start; + char pkey[512]; + char value[512]; + char *o; + + if (strstr (key, "\\")) + { +// Com_Printf ("Can't use a key with a \\\n"); + return; + } + + while (1) + { + start = s; + if (*s == '\\') + s++; + o = pkey; + while (*s != '\\') + { + if (!*s) + return; + *o++ = *s++; + } + *o = 0; + s++; + + o = value; + while (*s != '\\' && *s) + { + if (!*s) + return; + *o++ = *s++; + } + *o = 0; + + if (!strcmp (key, pkey) ) + { + strcpy (start, s); // remove this part + return; + } + + if (!*s) + return; + } + +} + + +/* +================== +Info_Validate + +Some characters are illegal in info strings because they +can mess up the server's parsing +================== +*/ +qboolean Info_Validate (char *s) +{ + if (strstr (s, "\"")) + return false; + if (strstr (s, ";")) + return false; + return true; +} + +void Info_SetValueForKey (char *s, char *key, char *value) +{ + char newi[MAX_INFO_STRING], *v; + int c; + int maxsize = MAX_INFO_STRING; + + if (strstr (key, "\\") || strstr (value, "\\") ) + { + Com_Printf ("Can't use keys or values with a \\\n"); + return; + } + + if (strstr (key, ";") ) + { + Com_Printf ("Can't use keys or values with a semicolon\n"); + return; + } + + if (strstr (key, "\"") || strstr (value, "\"") ) + { + Com_Printf ("Can't use keys or values with a \"\n"); + return; + } + + if (strlen(key) > MAX_INFO_KEY-1 || strlen(value) > MAX_INFO_KEY-1) + { + Com_Printf ("Keys and values must be < 64 characters.\n"); + return; + } + Info_RemoveKey (s, key); + if (!value || !strlen(value)) + return; + + Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value); + + if (strlen(newi) + strlen(s) > maxsize) + { + Com_Printf ("Info string length exceeded\n"); + return; + } + + // only copy ascii values + s += strlen(s); + v = newi; + while (*v) + { + c = *v++; + c &= 127; // strip high bits + if (c >= 32 && c < 127) + *s++ = c; + } + *s = 0; +} + +//==================================================================== + + diff --git a/game/q_shared.h b/game/q_shared.h new file mode 100644 index 000000000..b10b741bd --- /dev/null +++ b/game/q_shared.h @@ -0,0 +1,1200 @@ +/* +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. + +*/ + +// q_shared.h -- included first by ALL program modules + +#ifdef _WIN32 +// unknown pragmas are SUPPOSED to be ignored, but.... +#pragma warning(disable : 4244) // MIPS +#pragma warning(disable : 4136) // X86 +#pragma warning(disable : 4051) // ALPHA + +#pragma warning(disable : 4018) // signed/unsigned mismatch +#pragma warning(disable : 4305) // truncation from const double to float + +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if (defined _M_IX86 || defined __i386__) && !defined C_ONLY && !defined __sun__ +#define id386 1 +#else +#define id386 0 +#endif + +#if defined _M_ALPHA && !defined C_ONLY +#define idaxp 1 +#else +#define idaxp 0 +#endif + +typedef unsigned char byte; +typedef enum {false, true} qboolean; + + +#ifndef NULL +#define NULL ((void *)0) +#endif + + +// angle indexes +#define PITCH 0 // up / down +#define YAW 1 // left / right +#define ROLL 2 // fall over + +#define MAX_STRING_CHARS 1024 // max length of a string passed to Cmd_TokenizeString +#define MAX_STRING_TOKENS 80 // max tokens resulting from Cmd_TokenizeString +#define MAX_TOKEN_CHARS 128 // max length of an individual token + +#define MAX_QPATH 64 // max length of a quake game pathname +#define MAX_OSPATH 128 // max length of a filesystem pathname + +// +// per-level limits +// +#define MAX_CLIENTS 256 // absolute limit +#define MAX_EDICTS 1024 // must change protocol to increase more +#define MAX_LIGHTSTYLES 256 +#define MAX_MODELS 256 // these are sent over the net as bytes +#define MAX_SOUNDS 256 // so they cannot be blindly increased +#define MAX_IMAGES 256 +#define MAX_ITEMS 256 +#define MAX_GENERAL (MAX_CLIENTS*2) // general config strings + + +// game print flags +#define PRINT_LOW 0 // pickup messages +#define PRINT_MEDIUM 1 // death messages +#define PRINT_HIGH 2 // critical messages +#define PRINT_CHAT 3 // chat messages + + + +#define ERR_FATAL 0 // exit the entire game with a popup window +#define ERR_DROP 1 // print to console and disconnect from game +#define ERR_DISCONNECT 2 // don't kill server + +#define PRINT_ALL 0 +#define PRINT_DEVELOPER 1 // only print when "developer 1" +#define PRINT_ALERT 2 + + +// destination class for gi.multicast() +typedef enum +{ +MULTICAST_ALL, +MULTICAST_PHS, +MULTICAST_PVS, +MULTICAST_ALL_R, +MULTICAST_PHS_R, +MULTICAST_PVS_R +} multicast_t; + + +/* +============================================================== + +MATHLIB + +============================================================== +*/ + +typedef float vec_t; +typedef vec_t vec3_t[3]; +typedef vec_t vec5_t[5]; + +typedef int fixed4_t; +typedef int fixed8_t; +typedef int fixed16_t; + +#ifndef M_PI +#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h +#endif + +struct cplane_s; + +extern vec3_t vec3_origin; + +#define nanmask (255<<23) + +#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) + +// microsoft's fabs seems to be ungodly slow... +//float Q_fabs (float f); +//#define fabs(f) Q_fabs(f) +#if !defined C_ONLY && !defined __linux__ && !defined __sgi +extern long Q_ftol( float f ); +#else +#define Q_ftol( f ) ( long ) (f) +#endif + +#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) +#define VectorSubtract(a,b,c) (c[0]=a[0]-b[0],c[1]=a[1]-b[1],c[2]=a[2]-b[2]) +#define VectorAdd(a,b,c) (c[0]=a[0]+b[0],c[1]=a[1]+b[1],c[2]=a[2]+b[2]) +#define VectorCopy(a,b) (b[0]=a[0],b[1]=a[1],b[2]=a[2]) +#define VectorClear(a) (a[0]=a[1]=a[2]=0) +#define VectorNegate(a,b) (b[0]=-a[0],b[1]=-a[1],b[2]=-a[2]) +#define VectorSet(v, x, y, z) (v[0]=(x), v[1]=(y), v[2]=(z)) + +void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); + +// just in case you do't want to use the macros +vec_t _DotProduct (vec3_t v1, vec3_t v2); +void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out); +void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out); +void _VectorCopy (vec3_t in, vec3_t out); + +void ClearBounds (vec3_t mins, vec3_t maxs); +void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs); +int VectorCompare (vec3_t v1, vec3_t v2); +vec_t VectorLength (vec3_t v); +void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross); +vec_t VectorNormalize (vec3_t v); // returns vector length +vec_t VectorNormalize2 (vec3_t v, vec3_t out); +void VectorInverse (vec3_t v); +void VectorScale (vec3_t in, vec_t scale, vec3_t out); +int Q_log2(int val); + +void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]); +void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]); + +void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); +int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *plane); +float anglemod(float a); +float LerpAngle (float a1, float a2, float frac); + +#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \ + (((p)->type < 3)? \ + ( \ + ((p)->dist <= (emins)[(p)->type])? \ + 1 \ + : \ + ( \ + ((p)->dist >= (emaxs)[(p)->type])?\ + 2 \ + : \ + 3 \ + ) \ + ) \ + : \ + BoxOnPlaneSide( (emins), (emaxs), (p))) + +void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ); +void PerpendicularVector( vec3_t dst, const vec3_t src ); +void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ); + + +//============================================= + +char *COM_SkipPath (char *pathname); +void COM_StripExtension (char *in, char *out); +void COM_FileBase (char *in, char *out); +void COM_FilePath (char *in, char *out); +void COM_DefaultExtension (char *path, char *extension); + +char *COM_Parse (char **data_p); +// data is an in/out parm, returns a parsed out token + +void Com_sprintf (char *dest, int size, char *fmt, ...); + +void Com_PageInMemory (byte *buffer, int size); + +//============================================= + +// portable case insensitive compare +int Q_stricmp (char *s1, char *s2); +int Q_strcasecmp (char *s1, char *s2); +int Q_strncasecmp (char *s1, char *s2, int n); + +//============================================= + +short BigShort(short l); +short LittleShort(short l); +int BigLong (int l); +int LittleLong (int l); +float BigFloat (float l); +float LittleFloat (float l); + +void Swap_Init (void); +char *va(char *format, ...); + +//============================================= + +// +// key / value info strings +// +#define MAX_INFO_KEY 64 +#define MAX_INFO_VALUE 64 +#define MAX_INFO_STRING 512 + +char *Info_ValueForKey (char *s, char *key); +void Info_RemoveKey (char *s, char *key); +void Info_SetValueForKey (char *s, char *key, char *value); +qboolean Info_Validate (char *s); + +/* +============================================================== + +SYSTEM SPECIFIC + +============================================================== +*/ + +extern int curtime; // time returned by last Sys_Milliseconds + +int Sys_Milliseconds (void); +void Sys_Mkdir (char *path); + +// large block stack allocation routines +void *Hunk_Begin (int maxsize); +void *Hunk_Alloc (int size); +void Hunk_Free (void *buf); +int Hunk_End (void); + +// directory searching +#define SFF_ARCH 0x01 +#define SFF_HIDDEN 0x02 +#define SFF_RDONLY 0x04 +#define SFF_SUBDIR 0x08 +#define SFF_SYSTEM 0x10 + +/* +** pass in an attribute mask of things you wish to REJECT +*/ +char *Sys_FindFirst (char *path, unsigned musthave, unsigned canthave ); +char *Sys_FindNext ( unsigned musthave, unsigned canthave ); +void Sys_FindClose (void); + + +// this is only here so the functions in q_shared.c and q_shwin.c can link +void Sys_Error (char *error, ...); +void Com_Printf (char *msg, ...); + + +/* +========================================================== + +CVARS (console variables) + +========================================================== +*/ + +#ifndef CVAR +#define CVAR + +#define CVAR_ARCHIVE 1 // set to cause it to be saved to vars.rc +#define CVAR_USERINFO 2 // added to userinfo when changed +#define CVAR_SERVERINFO 4 // added to serverinfo when changed +#define CVAR_NOSET 8 // don't allow change from console at all, + // but can be set from the command line +#define CVAR_LATCH 16 // save changes until server restart + +// nothing outside the Cvar_*() functions should modify these fields! +typedef struct cvar_s +{ + char *name; + char *string; + char *latched_string; // for CVAR_LATCH vars + int flags; + qboolean modified; // set each time the cvar is changed + float value; + struct cvar_s *next; +} cvar_t; + +#endif // CVAR + +/* +============================================================== + +COLLISION DETECTION + +============================================================== +*/ + +// lower bits are stronger, and will eat weaker brushes completely +#define CONTENTS_SOLID 1 // an eye is never valid in a solid +#define CONTENTS_WINDOW 2 // translucent, but not watery +#define CONTENTS_AUX 4 +#define CONTENTS_LAVA 8 +#define CONTENTS_SLIME 16 +#define CONTENTS_WATER 32 +#define CONTENTS_MIST 64 +#define LAST_VISIBLE_CONTENTS 64 + +// remaining contents are non-visible, and don't eat brushes + +#define CONTENTS_AREAPORTAL 0x8000 + +#define CONTENTS_PLAYERCLIP 0x10000 +#define CONTENTS_MONSTERCLIP 0x20000 + +// currents can be added to any other contents, and may be mixed +#define CONTENTS_CURRENT_0 0x40000 +#define CONTENTS_CURRENT_90 0x80000 +#define CONTENTS_CURRENT_180 0x100000 +#define CONTENTS_CURRENT_270 0x200000 +#define CONTENTS_CURRENT_UP 0x400000 +#define CONTENTS_CURRENT_DOWN 0x800000 + +#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity + +#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game +#define CONTENTS_DEADMONSTER 0x4000000 +#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs +#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans +#define CONTENTS_LADDER 0x20000000 + + + +#define SURF_LIGHT 0x1 // value will hold the light strength + +#define SURF_SLICK 0x2 // effects game physics + +#define SURF_SKY 0x4 // don't draw, but add to skybox +#define SURF_WARP 0x8 // turbulent water warp +#define SURF_TRANS33 0x10 +#define SURF_TRANS66 0x20 +#define SURF_FLOWING 0x40 // scroll towards angle +#define SURF_NODRAW 0x80 // don't bother referencing the texture + + + +// content masks +#define MASK_ALL (-1) +#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_WINDOW) +#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER) +#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW) +#define MASK_MONSTERSOLID (CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER) +#define MASK_WATER (CONTENTS_WATER|CONTENTS_LAVA|CONTENTS_SLIME) +#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_SLIME|CONTENTS_LAVA) +#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEADMONSTER) +#define MASK_CURRENT (CONTENTS_CURRENT_0|CONTENTS_CURRENT_90|CONTENTS_CURRENT_180|CONTENTS_CURRENT_270|CONTENTS_CURRENT_UP|CONTENTS_CURRENT_DOWN) + + +// gi.BoxEdicts() can return a list of either solid or trigger entities +// FIXME: eliminate AREA_ distinction? +#define AREA_SOLID 1 +#define AREA_TRIGGERS 2 + + +// plane_t structure +// !!! if this is changed, it must be changed in asm code too !!! +typedef struct cplane_s +{ + vec3_t normal; + float dist; + byte type; // for fast side tests + byte signbits; // signx + (signy<<1) + (signz<<1) + byte pad[2]; +} cplane_t; + +// structure offset for asm code +#define CPLANE_NORMAL_X 0 +#define CPLANE_NORMAL_Y 4 +#define CPLANE_NORMAL_Z 8 +#define CPLANE_DIST 12 +#define CPLANE_TYPE 16 +#define CPLANE_SIGNBITS 17 +#define CPLANE_PAD0 18 +#define CPLANE_PAD1 19 + +typedef struct cmodel_s +{ + vec3_t mins, maxs; + vec3_t origin; // for sounds or lights + int headnode; +} cmodel_t; + +typedef struct csurface_s +{ + char name[16]; + int flags; + int value; +} csurface_t; + +typedef struct mapsurface_s // used internally due to name len probs //ZOID +{ + csurface_t c; + char rname[32]; +} mapsurface_t; + +// a trace is returned when a box is swept through the world +typedef struct +{ + qboolean allsolid; // if true, plane is not valid + qboolean startsolid; // if true, the initial point was in a solid area + float fraction; // time completed, 1.0 = didn't hit anything + vec3_t endpos; // final position + cplane_t plane; // surface normal at impact + csurface_t *surface; // surface hit + int contents; // contents on other side of surface hit + struct edict_s *ent; // not set by CM_*() functions +} trace_t; + + + +// pmove_state_t is the information necessary for client side movement +// prediction +typedef enum +{ + // can accelerate and turn + PM_NORMAL, + PM_SPECTATOR, + // no acceleration or turning + PM_DEAD, + PM_GIB, // different bounding box + PM_FREEZE +} pmtype_t; + +// pmove->pm_flags +#define PMF_DUCKED 1 +#define PMF_JUMP_HELD 2 +#define PMF_ON_GROUND 4 +#define PMF_TIME_WATERJUMP 8 // pm_time is waterjump +#define PMF_TIME_LAND 16 // pm_time is time before rejump +#define PMF_TIME_TELEPORT 32 // pm_time is non-moving time +#define PMF_NO_PREDICTION 64 // temporarily disables prediction (used for grappling hook) + +// this structure needs to be communicated bit-accurate +// from the server to the client to guarantee that +// prediction stays in sync, so no floats are used. +// if any part of the game code modifies this struct, it +// will result in a prediction error of some degree. +typedef struct +{ + pmtype_t pm_type; + + short origin[3]; // 12.3 + short velocity[3]; // 12.3 + byte pm_flags; // ducked, jump_held, etc + byte pm_time; // each unit = 8 ms + short gravity; + short delta_angles[3]; // add to command angles to get view direction + // changed by spawns, rotating objects, and teleporters +} pmove_state_t; + + +// +// button bits +// +#define BUTTON_ATTACK 1 +#define BUTTON_USE 2 +#define BUTTON_ANY 128 // any key whatsoever + + +// usercmd_t is sent to the server each client frame +typedef struct usercmd_s +{ + byte msec; + byte buttons; + short angles[3]; + short forwardmove, sidemove, upmove; + byte impulse; // remove? + byte lightlevel; // light level the player is standing on +} usercmd_t; + + +#define MAXTOUCH 32 +typedef struct +{ + // state (in / out) + pmove_state_t s; + + // command (in) + usercmd_t cmd; + qboolean snapinitial; // if s has been changed outside pmove + + // results (out) + int numtouch; + struct edict_s *touchents[MAXTOUCH]; + + vec3_t viewangles; // clamped + float viewheight; + + vec3_t mins, maxs; // bounding box size + + struct edict_s *groundentity; + int watertype; + int waterlevel; + + // callbacks to test the world + trace_t (*trace) (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end); + int (*pointcontents) (vec3_t point); +} pmove_t; + + +// entity_state_t->effects +// Effects are things handled on the client side (lights, particles, frame animations) +// that happen constantly on the given entity. +// An entity that has effects will be sent to the client +// even if it has a zero index model. +#define EF_ROTATE 0x00000001 // rotate (bonus items) +#define EF_GIB 0x00000002 // leave a trail +#define EF_BLASTER 0x00000008 // redlight + trail +#define EF_ROCKET 0x00000010 // redlight + trail +#define EF_GRENADE 0x00000020 +#define EF_HYPERBLASTER 0x00000040 +#define EF_BFG 0x00000080 +#define EF_COLOR_SHELL 0x00000100 +#define EF_POWERSCREEN 0x00000200 +#define EF_ANIM01 0x00000400 // automatically cycle between frames 0 and 1 at 2 hz +#define EF_ANIM23 0x00000800 // automatically cycle between frames 2 and 3 at 2 hz +#define EF_ANIM_ALL 0x00001000 // automatically cycle through all frames at 2hz +#define EF_ANIM_ALLFAST 0x00002000 // automatically cycle through all frames at 10hz +#define EF_FLIES 0x00004000 +#define EF_QUAD 0x00008000 +#define EF_PENT 0x00010000 +#define EF_TELEPORTER 0x00020000 // particle fountain +#define EF_FLAG1 0x00040000 +#define EF_FLAG2 0x00080000 +// RAFAEL +#define EF_IONRIPPER 0x00100000 +#define EF_GREENGIB 0x00200000 +#define EF_BLUEHYPERBLASTER 0x00400000 +#define EF_SPINNINGLIGHTS 0x00800000 +#define EF_PLASMA 0x01000000 +#define EF_TRAP 0x02000000 + +//ROGUE +#define EF_TRACKER 0x04000000 +#define EF_DOUBLE 0x08000000 +#define EF_SPHERETRANS 0x10000000 +#define EF_TAGTRAIL 0x20000000 +#define EF_HALF_DAMAGE 0x40000000 +#define EF_TRACKERTRAIL 0x80000000 +//ROGUE + +// entity_state_t->renderfx flags +#define RF_MINLIGHT 1 // allways have some light (viewmodel) +#define RF_VIEWERMODEL 2 // don't draw through eyes, only mirrors +#define RF_WEAPONMODEL 4 // only draw through eyes +#define RF_FULLBRIGHT 8 // allways draw full intensity +#define RF_DEPTHHACK 16 // for view weapon Z crunching +#define RF_TRANSLUCENT 32 +#define RF_FRAMELERP 64 +#define RF_BEAM 128 +#define RF_CUSTOMSKIN 256 // skin is an index in image_precache +#define RF_GLOW 512 // pulse lighting for bonus items +#define RF_SHELL_RED 1024 +#define RF_SHELL_GREEN 2048 +#define RF_SHELL_BLUE 4096 + +//ROGUE +#define RF_IR_VISIBLE 0x00008000 // 32768 +#define RF_SHELL_DOUBLE 0x00010000 // 65536 +#define RF_SHELL_HALF_DAM 0x00020000 +#define RF_USE_DISGUISE 0x00040000 +//ROGUE + +// player_state_t->refdef flags +#define RDF_UNDERWATER 1 // warp the screen as apropriate +#define RDF_NOWORLDMODEL 2 // used for player configuration screen + +//ROGUE +#define RDF_IRGOGGLES 4 +#define RDF_UVGOGGLES 8 +//ROGUE + +// +// muzzle flashes / player effects +// +#define MZ_BLASTER 0 +#define MZ_MACHINEGUN 1 +#define MZ_SHOTGUN 2 +#define MZ_CHAINGUN1 3 +#define MZ_CHAINGUN2 4 +#define MZ_CHAINGUN3 5 +#define MZ_RAILGUN 6 +#define MZ_ROCKET 7 +#define MZ_GRENADE 8 +#define MZ_LOGIN 9 +#define MZ_LOGOUT 10 +#define MZ_RESPAWN 11 +#define MZ_BFG 12 +#define MZ_SSHOTGUN 13 +#define MZ_HYPERBLASTER 14 +#define MZ_ITEMRESPAWN 15 +// RAFAEL +#define MZ_IONRIPPER 16 +#define MZ_BLUEHYPERBLASTER 17 +#define MZ_PHALANX 18 +#define MZ_SILENCED 128 // bit flag ORed with one of the above numbers + +//ROGUE +#define MZ_ETF_RIFLE 30 +#define MZ_UNUSED 31 +#define MZ_SHOTGUN2 32 +#define MZ_HEATBEAM 33 +#define MZ_BLASTER2 34 +#define MZ_TRACKER 35 +#define MZ_NUKE1 36 +#define MZ_NUKE2 37 +#define MZ_NUKE4 38 +#define MZ_NUKE8 39 +//ROGUE + +// +// monster muzzle flashes +// +#define MZ2_TANK_BLASTER_1 1 +#define MZ2_TANK_BLASTER_2 2 +#define MZ2_TANK_BLASTER_3 3 +#define MZ2_TANK_MACHINEGUN_1 4 +#define MZ2_TANK_MACHINEGUN_2 5 +#define MZ2_TANK_MACHINEGUN_3 6 +#define MZ2_TANK_MACHINEGUN_4 7 +#define MZ2_TANK_MACHINEGUN_5 8 +#define MZ2_TANK_MACHINEGUN_6 9 +#define MZ2_TANK_MACHINEGUN_7 10 +#define MZ2_TANK_MACHINEGUN_8 11 +#define MZ2_TANK_MACHINEGUN_9 12 +#define MZ2_TANK_MACHINEGUN_10 13 +#define MZ2_TANK_MACHINEGUN_11 14 +#define MZ2_TANK_MACHINEGUN_12 15 +#define MZ2_TANK_MACHINEGUN_13 16 +#define MZ2_TANK_MACHINEGUN_14 17 +#define MZ2_TANK_MACHINEGUN_15 18 +#define MZ2_TANK_MACHINEGUN_16 19 +#define MZ2_TANK_MACHINEGUN_17 20 +#define MZ2_TANK_MACHINEGUN_18 21 +#define MZ2_TANK_MACHINEGUN_19 22 +#define MZ2_TANK_ROCKET_1 23 +#define MZ2_TANK_ROCKET_2 24 +#define MZ2_TANK_ROCKET_3 25 + +#define MZ2_INFANTRY_MACHINEGUN_1 26 +#define MZ2_INFANTRY_MACHINEGUN_2 27 +#define MZ2_INFANTRY_MACHINEGUN_3 28 +#define MZ2_INFANTRY_MACHINEGUN_4 29 +#define MZ2_INFANTRY_MACHINEGUN_5 30 +#define MZ2_INFANTRY_MACHINEGUN_6 31 +#define MZ2_INFANTRY_MACHINEGUN_7 32 +#define MZ2_INFANTRY_MACHINEGUN_8 33 +#define MZ2_INFANTRY_MACHINEGUN_9 34 +#define MZ2_INFANTRY_MACHINEGUN_10 35 +#define MZ2_INFANTRY_MACHINEGUN_11 36 +#define MZ2_INFANTRY_MACHINEGUN_12 37 +#define MZ2_INFANTRY_MACHINEGUN_13 38 + +#define MZ2_SOLDIER_BLASTER_1 39 +#define MZ2_SOLDIER_BLASTER_2 40 +#define MZ2_SOLDIER_SHOTGUN_1 41 +#define MZ2_SOLDIER_SHOTGUN_2 42 +#define MZ2_SOLDIER_MACHINEGUN_1 43 +#define MZ2_SOLDIER_MACHINEGUN_2 44 + +#define MZ2_GUNNER_MACHINEGUN_1 45 +#define MZ2_GUNNER_MACHINEGUN_2 46 +#define MZ2_GUNNER_MACHINEGUN_3 47 +#define MZ2_GUNNER_MACHINEGUN_4 48 +#define MZ2_GUNNER_MACHINEGUN_5 49 +#define MZ2_GUNNER_MACHINEGUN_6 50 +#define MZ2_GUNNER_MACHINEGUN_7 51 +#define MZ2_GUNNER_MACHINEGUN_8 52 +#define MZ2_GUNNER_GRENADE_1 53 +#define MZ2_GUNNER_GRENADE_2 54 +#define MZ2_GUNNER_GRENADE_3 55 +#define MZ2_GUNNER_GRENADE_4 56 + +#define MZ2_CHICK_ROCKET_1 57 + +#define MZ2_FLYER_BLASTER_1 58 +#define MZ2_FLYER_BLASTER_2 59 + +#define MZ2_MEDIC_BLASTER_1 60 + +#define MZ2_GLADIATOR_RAILGUN_1 61 + +#define MZ2_HOVER_BLASTER_1 62 + +#define MZ2_ACTOR_MACHINEGUN_1 63 + +#define MZ2_SUPERTANK_MACHINEGUN_1 64 +#define MZ2_SUPERTANK_MACHINEGUN_2 65 +#define MZ2_SUPERTANK_MACHINEGUN_3 66 +#define MZ2_SUPERTANK_MACHINEGUN_4 67 +#define MZ2_SUPERTANK_MACHINEGUN_5 68 +#define MZ2_SUPERTANK_MACHINEGUN_6 69 +#define MZ2_SUPERTANK_ROCKET_1 70 +#define MZ2_SUPERTANK_ROCKET_2 71 +#define MZ2_SUPERTANK_ROCKET_3 72 + +#define MZ2_BOSS2_MACHINEGUN_L1 73 +#define MZ2_BOSS2_MACHINEGUN_L2 74 +#define MZ2_BOSS2_MACHINEGUN_L3 75 +#define MZ2_BOSS2_MACHINEGUN_L4 76 +#define MZ2_BOSS2_MACHINEGUN_L5 77 +#define MZ2_BOSS2_ROCKET_1 78 +#define MZ2_BOSS2_ROCKET_2 79 +#define MZ2_BOSS2_ROCKET_3 80 +#define MZ2_BOSS2_ROCKET_4 81 + +#define MZ2_FLOAT_BLASTER_1 82 + +#define MZ2_SOLDIER_BLASTER_3 83 +#define MZ2_SOLDIER_SHOTGUN_3 84 +#define MZ2_SOLDIER_MACHINEGUN_3 85 +#define MZ2_SOLDIER_BLASTER_4 86 +#define MZ2_SOLDIER_SHOTGUN_4 87 +#define MZ2_SOLDIER_MACHINEGUN_4 88 +#define MZ2_SOLDIER_BLASTER_5 89 +#define MZ2_SOLDIER_SHOTGUN_5 90 +#define MZ2_SOLDIER_MACHINEGUN_5 91 +#define MZ2_SOLDIER_BLASTER_6 92 +#define MZ2_SOLDIER_SHOTGUN_6 93 +#define MZ2_SOLDIER_MACHINEGUN_6 94 +#define MZ2_SOLDIER_BLASTER_7 95 +#define MZ2_SOLDIER_SHOTGUN_7 96 +#define MZ2_SOLDIER_MACHINEGUN_7 97 +#define MZ2_SOLDIER_BLASTER_8 98 +#define MZ2_SOLDIER_SHOTGUN_8 99 +#define MZ2_SOLDIER_MACHINEGUN_8 100 + +// --- Xian shit below --- +#define MZ2_MAKRON_BFG 101 +#define MZ2_MAKRON_BLASTER_1 102 +#define MZ2_MAKRON_BLASTER_2 103 +#define MZ2_MAKRON_BLASTER_3 104 +#define MZ2_MAKRON_BLASTER_4 105 +#define MZ2_MAKRON_BLASTER_5 106 +#define MZ2_MAKRON_BLASTER_6 107 +#define MZ2_MAKRON_BLASTER_7 108 +#define MZ2_MAKRON_BLASTER_8 109 +#define MZ2_MAKRON_BLASTER_9 110 +#define MZ2_MAKRON_BLASTER_10 111 +#define MZ2_MAKRON_BLASTER_11 112 +#define MZ2_MAKRON_BLASTER_12 113 +#define MZ2_MAKRON_BLASTER_13 114 +#define MZ2_MAKRON_BLASTER_14 115 +#define MZ2_MAKRON_BLASTER_15 116 +#define MZ2_MAKRON_BLASTER_16 117 +#define MZ2_MAKRON_BLASTER_17 118 +#define MZ2_MAKRON_RAILGUN_1 119 +#define MZ2_JORG_MACHINEGUN_L1 120 +#define MZ2_JORG_MACHINEGUN_L2 121 +#define MZ2_JORG_MACHINEGUN_L3 122 +#define MZ2_JORG_MACHINEGUN_L4 123 +#define MZ2_JORG_MACHINEGUN_L5 124 +#define MZ2_JORG_MACHINEGUN_L6 125 +#define MZ2_JORG_MACHINEGUN_R1 126 +#define MZ2_JORG_MACHINEGUN_R2 127 +#define MZ2_JORG_MACHINEGUN_R3 128 +#define MZ2_JORG_MACHINEGUN_R4 129 +#define MZ2_JORG_MACHINEGUN_R5 130 +#define MZ2_JORG_MACHINEGUN_R6 131 +#define MZ2_JORG_BFG_1 132 +#define MZ2_BOSS2_MACHINEGUN_R1 133 +#define MZ2_BOSS2_MACHINEGUN_R2 134 +#define MZ2_BOSS2_MACHINEGUN_R3 135 +#define MZ2_BOSS2_MACHINEGUN_R4 136 +#define MZ2_BOSS2_MACHINEGUN_R5 137 + +//ROGUE +#define MZ2_CARRIER_MACHINEGUN_L1 138 +#define MZ2_CARRIER_MACHINEGUN_R1 139 +#define MZ2_CARRIER_GRENADE 140 +#define MZ2_TURRET_MACHINEGUN 141 +#define MZ2_TURRET_ROCKET 142 +#define MZ2_TURRET_BLASTER 143 +#define MZ2_STALKER_BLASTER 144 +#define MZ2_DAEDALUS_BLASTER 145 +#define MZ2_MEDIC_BLASTER_2 146 +#define MZ2_CARRIER_RAILGUN 147 +#define MZ2_WIDOW_DISRUPTOR 148 +#define MZ2_WIDOW_BLASTER 149 +#define MZ2_WIDOW_RAIL 150 +#define MZ2_WIDOW_PLASMABEAM 151 // PMM - not used +#define MZ2_CARRIER_MACHINEGUN_L2 152 +#define MZ2_CARRIER_MACHINEGUN_R2 153 +#define MZ2_WIDOW_RAIL_LEFT 154 +#define MZ2_WIDOW_RAIL_RIGHT 155 +#define MZ2_WIDOW_BLASTER_SWEEP1 156 +#define MZ2_WIDOW_BLASTER_SWEEP2 157 +#define MZ2_WIDOW_BLASTER_SWEEP3 158 +#define MZ2_WIDOW_BLASTER_SWEEP4 159 +#define MZ2_WIDOW_BLASTER_SWEEP5 160 +#define MZ2_WIDOW_BLASTER_SWEEP6 161 +#define MZ2_WIDOW_BLASTER_SWEEP7 162 +#define MZ2_WIDOW_BLASTER_SWEEP8 163 +#define MZ2_WIDOW_BLASTER_SWEEP9 164 +#define MZ2_WIDOW_BLASTER_100 165 +#define MZ2_WIDOW_BLASTER_90 166 +#define MZ2_WIDOW_BLASTER_80 167 +#define MZ2_WIDOW_BLASTER_70 168 +#define MZ2_WIDOW_BLASTER_60 169 +#define MZ2_WIDOW_BLASTER_50 170 +#define MZ2_WIDOW_BLASTER_40 171 +#define MZ2_WIDOW_BLASTER_30 172 +#define MZ2_WIDOW_BLASTER_20 173 +#define MZ2_WIDOW_BLASTER_10 174 +#define MZ2_WIDOW_BLASTER_0 175 +#define MZ2_WIDOW_BLASTER_10L 176 +#define MZ2_WIDOW_BLASTER_20L 177 +#define MZ2_WIDOW_BLASTER_30L 178 +#define MZ2_WIDOW_BLASTER_40L 179 +#define MZ2_WIDOW_BLASTER_50L 180 +#define MZ2_WIDOW_BLASTER_60L 181 +#define MZ2_WIDOW_BLASTER_70L 182 +#define MZ2_WIDOW_RUN_1 183 +#define MZ2_WIDOW_RUN_2 184 +#define MZ2_WIDOW_RUN_3 185 +#define MZ2_WIDOW_RUN_4 186 +#define MZ2_WIDOW_RUN_5 187 +#define MZ2_WIDOW_RUN_6 188 +#define MZ2_WIDOW_RUN_7 189 +#define MZ2_WIDOW_RUN_8 190 +#define MZ2_CARRIER_ROCKET_1 191 +#define MZ2_CARRIER_ROCKET_2 192 +#define MZ2_CARRIER_ROCKET_3 193 +#define MZ2_CARRIER_ROCKET_4 194 +#define MZ2_WIDOW2_BEAMER_1 195 +#define MZ2_WIDOW2_BEAMER_2 196 +#define MZ2_WIDOW2_BEAMER_3 197 +#define MZ2_WIDOW2_BEAMER_4 198 +#define MZ2_WIDOW2_BEAMER_5 199 +#define MZ2_WIDOW2_BEAM_SWEEP_1 200 +#define MZ2_WIDOW2_BEAM_SWEEP_2 201 +#define MZ2_WIDOW2_BEAM_SWEEP_3 202 +#define MZ2_WIDOW2_BEAM_SWEEP_4 203 +#define MZ2_WIDOW2_BEAM_SWEEP_5 204 +#define MZ2_WIDOW2_BEAM_SWEEP_6 205 +#define MZ2_WIDOW2_BEAM_SWEEP_7 206 +#define MZ2_WIDOW2_BEAM_SWEEP_8 207 +#define MZ2_WIDOW2_BEAM_SWEEP_9 208 +#define MZ2_WIDOW2_BEAM_SWEEP_10 209 +#define MZ2_WIDOW2_BEAM_SWEEP_11 210 + +// ROGUE + +extern vec3_t monster_flash_offset []; + + +// temp entity events +// +// Temp entity events are for things that happen +// at a location seperate from any existing entity. +// Temporary entity messages are explicitly constructed +// and broadcast. +typedef enum +{ + TE_GUNSHOT, + TE_BLOOD, + TE_BLASTER, + TE_RAILTRAIL, + TE_SHOTGUN, + TE_EXPLOSION1, + TE_EXPLOSION2, + TE_ROCKET_EXPLOSION, + TE_GRENADE_EXPLOSION, + TE_SPARKS, + TE_SPLASH, + TE_BUBBLETRAIL, + TE_SCREEN_SPARKS, + TE_SHIELD_SPARKS, + TE_BULLET_SPARKS, + TE_LASER_SPARKS, + TE_PARASITE_ATTACK, + TE_ROCKET_EXPLOSION_WATER, + TE_GRENADE_EXPLOSION_WATER, + TE_MEDIC_CABLE_ATTACK, + TE_BFG_EXPLOSION, + TE_BFG_BIGEXPLOSION, + TE_BOSSTPORT, // used as '22' in a map, so DON'T RENUMBER!!! + TE_BFG_LASER, + TE_GRAPPLE_CABLE, + TE_WELDING_SPARKS, + TE_GREENBLOOD, + TE_BLUEHYPERBLASTER, + TE_PLASMA_EXPLOSION, + TE_TUNNEL_SPARKS, +//ROGUE + TE_BLASTER2, + TE_RAILTRAIL2, + TE_FLAME, + TE_LIGHTNING, + TE_DEBUGTRAIL, + TE_PLAIN_EXPLOSION, + TE_FLASHLIGHT, + TE_FORCEWALL, + TE_HEATBEAM, + TE_MONSTER_HEATBEAM, + TE_STEAM, + TE_BUBBLETRAIL2, + TE_MOREBLOOD, + TE_HEATBEAM_SPARKS, + TE_HEATBEAM_STEAM, + TE_CHAINFIST_SMOKE, + TE_ELECTRIC_SPARKS, + TE_TRACKER_EXPLOSION, + TE_TELEPORT_EFFECT, + TE_DBALL_GOAL, + TE_WIDOWBEAMOUT, + TE_NUKEBLAST, + TE_WIDOWSPLASH, + TE_EXPLOSION1_BIG, + TE_EXPLOSION1_NP, + TE_FLECHETTE +//ROGUE +} temp_event_t; + +#define SPLASH_UNKNOWN 0 +#define SPLASH_SPARKS 1 +#define SPLASH_BLUE_WATER 2 +#define SPLASH_BROWN_WATER 3 +#define SPLASH_SLIME 4 +#define SPLASH_LAVA 5 +#define SPLASH_BLOOD 6 + + +// sound channels +// channel 0 never willingly overrides +// other channels (1-7) allways override a playing sound on that channel +#define CHAN_AUTO 0 +#define CHAN_WEAPON 1 +#define CHAN_VOICE 2 +#define CHAN_ITEM 3 +#define CHAN_BODY 4 +// modifier flags +#define CHAN_NO_PHS_ADD 8 // send to all clients, not just ones in PHS (ATTN 0 will also do this) +#define CHAN_RELIABLE 16 // send by reliable message, not datagram + + +// sound attenuation values +#define ATTN_NONE 0 // full volume the entire level +#define ATTN_NORM 1 +#define ATTN_IDLE 2 +#define ATTN_STATIC 3 // diminish very rapidly with distance + + +// player_state->stats[] indexes +#define STAT_HEALTH_ICON 0 +#define STAT_HEALTH 1 +#define STAT_AMMO_ICON 2 +#define STAT_AMMO 3 +#define STAT_ARMOR_ICON 4 +#define STAT_ARMOR 5 +#define STAT_SELECTED_ICON 6 +#define STAT_PICKUP_ICON 7 +#define STAT_PICKUP_STRING 8 +#define STAT_TIMER_ICON 9 +#define STAT_TIMER 10 +#define STAT_HELPICON 11 +#define STAT_SELECTED_ITEM 12 +#define STAT_LAYOUTS 13 +#define STAT_FRAGS 14 +#define STAT_FLASHES 15 // cleared each frame, 1 = health, 2 = armor +#define STAT_CHASE 16 +#define STAT_SPECTATOR 17 + +#define MAX_STATS 32 + + +// dmflags->value flags +#define DF_NO_HEALTH 0x00000001 // 1 +#define DF_NO_ITEMS 0x00000002 // 2 +#define DF_WEAPONS_STAY 0x00000004 // 4 +#define DF_NO_FALLING 0x00000008 // 8 +#define DF_INSTANT_ITEMS 0x00000010 // 16 +#define DF_SAME_LEVEL 0x00000020 // 32 +#define DF_SKINTEAMS 0x00000040 // 64 +#define DF_MODELTEAMS 0x00000080 // 128 +#define DF_NO_FRIENDLY_FIRE 0x00000100 // 256 +#define DF_SPAWN_FARTHEST 0x00000200 // 512 +#define DF_FORCE_RESPAWN 0x00000400 // 1024 +#define DF_NO_ARMOR 0x00000800 // 2048 +#define DF_ALLOW_EXIT 0x00001000 // 4096 +#define DF_INFINITE_AMMO 0x00002000 // 8192 +#define DF_QUAD_DROP 0x00004000 // 16384 +#define DF_FIXED_FOV 0x00008000 // 32768 + +// RAFAEL +#define DF_QUADFIRE_DROP 0x00010000 // 65536 + +//ROGUE +#define DF_NO_MINES 0x00020000 +#define DF_NO_STACK_DOUBLE 0x00040000 +#define DF_NO_NUKES 0x00080000 +#define DF_NO_SPHERES 0x00100000 +//ROGUE + +/* +ROGUE - VERSIONS +1234 08/13/1998 Activision +1235 08/14/1998 Id Software +1236 08/15/1998 Steve Tietze +1237 08/15/1998 Phil Dobranski +1238 08/15/1998 John Sheley +1239 08/17/1998 Barrett Alexander +1230 08/17/1998 Brandon Fish +1245 08/17/1998 Don MacAskill +1246 08/17/1998 David "Zoid" Kirsch +1247 08/17/1998 Manu Smith +1248 08/17/1998 Geoff Scully +1249 08/17/1998 Andy Van Fossen +1240 08/20/1998 Activision Build 2 +1256 08/20/1998 Ranger Clan +1257 08/20/1998 Ensemble Studios +1258 08/21/1998 Robert Duffy +1259 08/21/1998 Stephen Seachord +1250 08/21/1998 Stephen Heaslip +1267 08/21/1998 Samir Sandesara +1268 08/21/1998 Oliver Wyman +1269 08/21/1998 Steven Marchegiano +1260 08/21/1998 Build #2 for Nihilistic +1278 08/21/1998 Build #2 for Ensemble + +9999 08/20/1998 Internal Use +*/ +#define ROGUE_VERSION_ID 1278 + +#define ROGUE_VERSION_STRING "08/21/1998 Beta 2 for Ensemble" + +// ROGUE +/* +========================================================== + + ELEMENTS COMMUNICATED ACROSS THE NET + +========================================================== +*/ + +#define ANGLE2SHORT(x) ((int)((x)*65536/360) & 65535) +#define SHORT2ANGLE(x) ((x)*(360.0/65536)) + + +// +// config strings are a general means of communication from +// the server to all connected clients. +// Each config string can be at most MAX_QPATH characters. +// +#define CS_NAME 0 +#define CS_CDTRACK 1 +#define CS_SKY 2 +#define CS_SKYAXIS 3 // %f %f %f format +#define CS_SKYROTATE 4 +#define CS_STATUSBAR 5 // display program string + +#define CS_AIRACCEL 29 // air acceleration control +#define CS_MAXCLIENTS 30 +#define CS_MAPCHECKSUM 31 // for catching cheater maps + +#define CS_MODELS 32 +#define CS_SOUNDS (CS_MODELS+MAX_MODELS) +#define CS_IMAGES (CS_SOUNDS+MAX_SOUNDS) +#define CS_LIGHTS (CS_IMAGES+MAX_IMAGES) +#define CS_ITEMS (CS_LIGHTS+MAX_LIGHTSTYLES) +#define CS_PLAYERSKINS (CS_ITEMS+MAX_ITEMS) +#define CS_GENERAL (CS_PLAYERSKINS+MAX_CLIENTS) +#define MAX_CONFIGSTRINGS (CS_GENERAL+MAX_GENERAL) + + +//============================================== + + +// entity_state_t->event values +// ertity events are for effects that take place reletive +// to an existing entities origin. Very network efficient. +// All muzzle flashes really should be converted to events... +typedef enum +{ + EV_NONE, + EV_ITEM_RESPAWN, + EV_FOOTSTEP, + EV_FALLSHORT, + EV_FALL, + EV_FALLFAR, + EV_PLAYER_TELEPORT, + EV_OTHER_TELEPORT +} entity_event_t; + + +// entity_state_t is the information conveyed from the server +// in an update message about entities that the client will +// need to render in some way +typedef struct entity_state_s +{ + int number; // edict index + + vec3_t origin; + vec3_t angles; + vec3_t old_origin; // for lerping + int modelindex; + int modelindex2, modelindex3, modelindex4; // weapons, CTF flags, etc + int frame; + int skinnum; + unsigned int effects; // PGM - we're filling it, so it needs to be unsigned + int renderfx; + int solid; // for client side prediction, 8*(bits 0-4) is x/y radius + // 8*(bits 5-9) is z down distance, 8(bits10-15) is z up + // gi.linkentity sets this properly + int sound; // for looping sounds, to guarantee shutoff + int event; // impulse events -- muzzle flashes, footsteps, etc + // events only go out for a single frame, they + // are automatically cleared each frame +} entity_state_t; + +//============================================== + + +// player_state_t is the information needed in addition to pmove_state_t +// to rendered a view. There will only be 10 player_state_t sent each second, +// but the number of pmove_state_t changes will be reletive to client +// frame rates +typedef struct +{ + pmove_state_t pmove; // for prediction + + // these fields do not need to be communicated bit-precise + + vec3_t viewangles; // for fixed views + vec3_t viewoffset; // add to pmovestate->origin + vec3_t kick_angles; // add to view direction to get render angles + // set by weapon kicks, pain effects, etc + + vec3_t gunangles; + vec3_t gunoffset; + int gunindex; + int gunframe; + + float blend[4]; // rgba full screen effect + + float fov; // horizontal field of view + + int rdflags; // refdef flags + + short stats[MAX_STATS]; // fast status bar updates +} player_state_t; + + +// ================== +// PGM +#define VIDREF_GL 1 +#define VIDREF_SOFT 2 +#define VIDREF_OTHER 3 + +extern int vidref_val; +// PGM +// ================== diff --git a/irix/cd_irix.c b/irix/cd_irix.c new file mode 100644 index 000000000..75a17c3bf --- /dev/null +++ b/irix/cd_irix.c @@ -0,0 +1,40 @@ +#include +#include + +#include "../client/client.h" + +void CDAudio_Play(int track, qboolean looping) +{ + Com_Printf("XXX - CDAudio_Play %i (%i)\n", track, looping); +} + + +void CDAudio_Stop(void) +{ + Com_Printf("XXX - CDAudio_Stop\n"); +} + + +void CDAudio_Resume(void) +{ + Com_Printf("XXX - CDAudio_Resume\n"); +} + + +void CDAudio_Update(void) +{ +/* Com_Printf("XXX - CDAudio_Update\n"); */ +} + + +int CDAudio_Init(void) +{ + Com_Printf("XXX - CDAudio_Init\n"); + return 0; +} + + +void CDAudio_Shutdown(void) +{ + Com_Printf("XXX - CDAudio_Shutdown\n"); +} diff --git a/irix/glw_imp.c b/irix/glw_imp.c new file mode 100644 index 000000000..fb4accfe7 --- /dev/null +++ b/irix/glw_imp.c @@ -0,0 +1,927 @@ +/* +** GLW_IMP.C +** +** This file contains ALL Linux specific stuff having to do with the +** OpenGL refresh. When a port is being made the following functions +** must be implemented by the port: +** +** GLimp_EndFrame +** GLimp_Init +** GLimp_Shutdown +** GLimp_SwitchFullscreen +** +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "../ref_gl/gl_local.h" +#include "../client/keys.h" +#include "../linux/rw_linux.h" + +GLXContext gl_cx; + +static qboolean doShm; +static Display *x_disp; +static Colormap x_cmap; +static Window x_win; +static GC x_gc; +static Visual *x_vis; +static XVisualInfo *x_visinfo; + +static int StudlyRGBattributes[] = +{ + GLX_DOUBLEBUFFER, + GLX_RGBA, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 1, + GLX_SAMPLES_SGIS, 4, /* for better AA */ + None, +}; + +static int RGBattributes[] = +{ + GLX_DOUBLEBUFFER, + GLX_RGBA, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 1, + None, +}; + +#define STD_EVENT_MASK (StructureNotifyMask | KeyPressMask \ + | KeyReleaseMask | ExposureMask | PointerMotionMask | \ + ButtonPressMask | ButtonReleaseMask) + +int current_framebuffer; +static int x_shmeventtype; +//static XShmSegmentInfo x_shminfo; + +static qboolean oktodraw = false; +static qboolean X11_active = false; + +struct +{ + int key; + int down; +} keyq[64]; +int keyq_head=0; +int keyq_tail=0; + +static int mx, my; +static int p_mouse_x, p_mouse_y; +static cvar_t *_windowed_mouse; + +static cvar_t *sensitivity; +static cvar_t *lookstrafe; +static cvar_t *m_side; +static cvar_t *m_yaw; +static cvar_t *m_pitch; +static cvar_t *m_forward; +static cvar_t *freelook; + +int config_notify=0; +int config_notify_width; +int config_notify_height; + +typedef unsigned short PIXEL; + +// Console variables that we need to access from this module + +/*****************************************************************************/ +/* MOUSE */ +/*****************************************************************************/ + +// this is inside the renderer shared lib, so these are called from vid_so + +static qboolean mouse_avail; +static int mouse_buttonstate; +static int mouse_oldbuttonstate; +static int mouse_x, mouse_y; +static int old_mouse_x, old_mouse_y; +static float old_windowed_mouse; +static int p_mouse_x, p_mouse_y; + +static cvar_t *_windowed_mouse; +static cvar_t *m_filter; +static cvar_t *in_mouse; + +static qboolean mlooking; + +// state struct passed in Init +static in_state_t *in_state; + +int XShmQueryExtension(Display *); +int XShmGetEventBase(Display *); + +static void signal_handler(int sig) +{ + fprintf(stderr, "Received signal %d, exiting...\n", sig); + GLimp_Shutdown(); + _exit(0); +} + +static void InitSig(void) +{ + struct sigaction sa; + sigaction(SIGINT, 0, &sa); + sa.sa_handler = signal_handler; + sigaction(SIGINT, &sa, 0); + sigaction(SIGTERM, &sa, 0); +} + +/* +** GLimp_SetMode +*/ +int GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen ) +{ + int width, height; + GLint attribs[32]; + + fprintf(stderr, "GLimp_SetMode\n"); + + ri.Con_Printf( PRINT_ALL, "Initializing OpenGL display\n"); + + ri.Con_Printf (PRINT_ALL, "...setting mode %d:", mode ); + + if ( !ri.Vid_GetModeInfo( &width, &height, mode ) ) + { + ri.Con_Printf( PRINT_ALL, " invalid mode\n" ); + return rserr_invalid_mode; + } + + ri.Con_Printf( PRINT_ALL, " %d %d\n", width, height ); + + // destroy the existing window + GLimp_Shutdown (); + + *pwidth = width; + *pheight = height; + + if ( !GLimp_InitGraphics( fullscreen ) ) { + // failed to set a valid mode in windowed mode + return rserr_invalid_mode; + } +/* gl_cx = glXCreateContext( x_disp, x_visinfo, 0, True ); */ + + // let the sound and input subsystems know about the new window + ri.Vid_NewWindow (width, height); + + return rserr_ok; +} + +/* +** GLimp_Shutdown +** +** This routine does all OS specific shutdown procedures for the OpenGL +** subsystem. Under OpenGL this means NULLing out the current DC and +** HGLRC, deleting the rendering context, and releasing the DC acquired +** for the window. The state structure is also nulled out. +** +*/ +void GLimp_Shutdown( void ) +{ + fprintf(stderr, "GLimp_Shutdown\n"); + + if (!x_disp) + return; + + XSynchronize( x_disp, True ); + XAutoRepeatOn(x_disp); + XCloseDisplay(x_disp); + x_disp = NULL; +} + +/* +** GLimp_Init +** +** This routine is responsible for initializing the OS specific portions +** of OpenGL. +*/ +int GLimp_Init( void *hinstance, void *wndproc ) +{ +// catch signals so i can turn on auto-repeat and stuff + InitSig(); + + return true; +} + +/* +** GLimp_BeginFrame +*/ +void GLimp_BeginFrame( float camera_seperation ) +{ +} + +/* +** GLimp_EndFrame +** +** Responsible for doing a swapbuffers and possibly for other stuff +** as yet to be determined. Probably better not to make this a GLimp +** function and instead do a call to GLimp_SwapBuffers. +*/ +void GLimp_EndFrame (void) +{ + glFlush(); + glXSwapBuffers( x_disp, x_win ); +} + +/* +** GLimp_AppActivate +*/ +void GLimp_AppActivate( qboolean active ) +{ +} + +// ======================================================================== +// makes a null cursor +// ======================================================================== + +static Cursor CreateNullCursor(Display *display, Window root) +{ + Pixmap cursormask; + XGCValues xgc; + GC gc; + XColor dummycolour; + Cursor cursor; + + cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); + xgc.function = GXclear; + gc = XCreateGC(display, cursormask, GCFunction, &xgc); + XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); + dummycolour.pixel = 0; + dummycolour.red = 0; + dummycolour.flags = 04; + cursor = XCreatePixmapCursor(display, cursormask, cursormask, + &dummycolour,&dummycolour, 0,0); + XFreePixmap(display,cursormask); + XFreeGC(display,gc); + return cursor; +} + +/* +** GLimp_InitGraphics +** +** This initializes the GL implementation specific +** graphics subsystem. +** +** The necessary width and height parameters are grabbed from +** vid.width and vid.height. +*/ +qboolean GLimp_InitGraphics( qboolean fullscreen ) +{ + int pnum, i; + XVisualInfo template; + int num_visuals; + int template_mask; + + fprintf(stderr, "GLimp_InitGraphics\n"); + + srandom(getpid()); + + // let the sound and input subsystems know about the new window + ri.Vid_NewWindow (vid.width, vid.height); + + // open the display + x_disp = XOpenDisplay(NULL); + if (!x_disp) + { + if (getenv("DISPLAY")) + Sys_Error("VID: Could not open display [%s]\n", + getenv("DISPLAY")); + else + Sys_Error("VID: Could not open local display\n"); + } + else + fprintf(stderr, "VID: Opened display %s\n", getenv("DISPLAY")); + + XAutoRepeatOff(x_disp); + +// for debugging only + XSynchronize(x_disp, True); + +// check for command-line window size + template_mask = 0; + +#if 0 +// specify a visual id + if ((pnum=COM_CheckParm("-visualid"))) + { + if (pnum >= com_argc-1) + Sys_Error("VID: -visualid \n"); + template.visualid = Q_atoi(com_argv[pnum+1]); + template_mask = VisualIDMask; + } + +// If not specified, use default visual + else +#endif + { + int screen; + screen = XDefaultScreen(x_disp); + template.visualid = + XVisualIDFromVisual(XDefaultVisual(x_disp, screen)); + template_mask = VisualIDMask; + } + +// pick a visual- warn if more than one was available + + x_visinfo = glXChooseVisual( x_disp, DefaultScreen( x_disp ), + StudlyRGBattributes ); + if (!x_visinfo) + { + fprintf(stderr, "Using non studly RGB attributes\n"); + x_visinfo = glXChooseVisual( x_disp, DefaultScreen( x_disp ), + RGBattributes ); + if (!x_visinfo) Sys_Error( "No matching visual available!\n" ); + } + + ri.Con_Printf(PRINT_ALL, "Using visualid 0x%x:\n", + (int)(x_visinfo->visualid)); +#if 0 + if (verbose) + { + printf("Using visualid %d:\n", (int)(x_visinfo->visualid)); + printf(" screen %d\n", x_visinfo->screen); + printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask)); + printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask)); + printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask)); + printf(" colormap_size %d\n", x_visinfo->colormap_size); + printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb); + } +#endif + + x_vis = x_visinfo->visual; + +// setup attributes for main window + { + int attribmask = CWEventMask | CWColormap | CWBorderPixel; + XSetWindowAttributes attribs; + Colormap tmpcmap; + + Window root_win = XRootWindow(x_disp, x_visinfo->screen); + + tmpcmap = XCreateColormap(x_disp, root_win, x_vis, AllocNone); + + + attribs.event_mask = STD_EVENT_MASK; + attribs.border_pixel = 0; + attribs.colormap = tmpcmap; + +// create the main window + x_win = XCreateWindow( x_disp, + root_win, + 0, 0, // x, y + vid.width, vid.height, + 0, // borderwidth + x_visinfo->depth, + InputOutput, + x_vis, + attribmask, + &attribs ); + XStoreName(x_disp, x_win, "Quake II"); + + if (x_visinfo->class != TrueColor) + XFreeColormap(x_disp, tmpcmap); + } + + if (x_visinfo->depth == 8) + { + // create and upload the palette + if (x_visinfo->class == PseudoColor) + { + x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll); + XSetWindowColormap(x_disp, x_win, x_cmap); + } + + } + +// inviso cursor + XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win)); + +// create the GC + { + XGCValues xgcvalues; + int valuemask = GCGraphicsExposures; + xgcvalues.graphics_exposures = False; + x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues ); + } + +// set window properties for full screen + if (fullscreen) { + MotifWmHints wmhints; + Atom aHints; + XSizeHints sizehints; + XWindowChanges changes; + + aHints = XInternAtom( x_disp, "_MOTIF_WM_HINTS", 0 ); + if (aHints == None) + { + ri.Con_Printf( PRINT_ALL, "Could not intern X atom for _MOTIF_WM_HINTS." ); +/* return( false ); */ + } + else { + wmhints.flags = MWM_HINTS_DECORATIONS; + wmhints.decorations = 0; // Absolutely no decorations. + XChangeProperty(x_disp, x_win, aHints, aHints, 32, + PropModeReplace, (unsigned char *)&wmhints, + 4 ); + + sizehints.flags = USPosition | USSize; + sizehints.x = 0; + sizehints.y = 0; + sizehints.width = vid.width; + sizehints.height = vid.height; + XSetWMNormalHints( x_disp, x_win, &sizehints ); + + changes.x = 0; + changes.y = 0; + changes.width = vid.width; + changes.height = vid.height; + changes.stack_mode = TopIf; + XConfigureWindow(x_disp, x_win, + CWX | CWY | CWWidth | CWHeight | CWStackMode, + &changes); + } + } + +// map the window + XMapWindow(x_disp, x_win); + +// wait for first exposure event + { + XEvent event; + do + { + XNextEvent(x_disp, &event); + if (event.type == Expose && !event.xexpose.count) + oktodraw = true; + } while (!oktodraw); + } +// now safe to draw + + gl_cx = glXCreateContext( x_disp, x_visinfo, 0, True ); + if (!glXMakeCurrent( x_disp, x_win, gl_cx )) + Sys_Error( "Can't make window current to context\n" ); + +// even if MITSHM is available, make sure it's a local connection +#if 0 +// This is messing up the DISPLAY environment variable so can't close and +// reopen the window (it lops off the :0.0)... + if (XShmQueryExtension(x_disp)) + { + char *displayname; + doShm = true; + displayname = (char *) getenv("DISPLAY"); + if (displayname) + { + char *d = displayname; + while (*d && (*d != ':')) d++; + if (*d) *d = 0; + if (!(!strcasecmp(displayname, "unix") || !*displayname)) + doShm = false; + } + } +#endif + +#if 0 + if (doShm) + { + x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion; + ResetSharedFrameBuffers(); + } + else + ResetFrameBuffer(); +#endif + + current_framebuffer = 0; +/* vid.rowbytes = x_framebuffer[0]->bytes_per_line; */ +/* vid.buffer = x_framebuffer[0]->data; */ + +// XSynchronize(x_disp, False); + + X11_active = true; + + return true; +} + +/*****************************************************************************/ + +int XLateKey(XKeyEvent *ev) +{ + + int key; + char buf[64]; + KeySym keysym; + + key = 0; + + XLookupString(ev, buf, sizeof buf, &keysym, 0); + + switch(keysym) + { + case XK_KP_Page_Up: key = K_KP_PGUP; break; + case XK_Page_Up: key = K_PGUP; break; + + case XK_KP_Page_Down: key = K_KP_PGDN; break; + case XK_Page_Down: key = K_PGDN; break; + + case XK_KP_Home: key = K_KP_HOME; break; + case XK_Home: key = K_HOME; break; + + case XK_KP_End: key = K_KP_END; break; + case XK_End: key = K_END; break; + + case XK_KP_Left: key = K_KP_LEFTARROW; break; + case XK_Left: key = K_LEFTARROW; break; + + case XK_KP_Right: key = K_KP_RIGHTARROW; break; + case XK_Right: key = K_RIGHTARROW; break; + + case XK_KP_Down: key = K_KP_DOWNARROW; break; + case XK_Down: key = K_DOWNARROW; break; + + case XK_KP_Up: key = K_KP_UPARROW; break; + case XK_Up: key = K_UPARROW; break; + + case XK_Escape: key = K_ESCAPE; break; + + case XK_KP_Enter: key = K_KP_ENTER; break; + case XK_Return: key = K_ENTER; break; + + case XK_Tab: key = K_TAB; break; + + case XK_F1: key = K_F1; break; + + case XK_F2: key = K_F2; break; + + case XK_F3: key = K_F3; break; + + case XK_F4: key = K_F4; break; + + case XK_F5: key = K_F5; break; + + case XK_F6: key = K_F6; break; + + case XK_F7: key = K_F7; break; + + case XK_F8: key = K_F8; break; + + case XK_F9: key = K_F9; break; + + case XK_F10: key = K_F10; break; + + case XK_F11: key = K_F11; break; + + case XK_F12: key = K_F12; break; + + case XK_BackSpace: key = K_BACKSPACE; break; + + case XK_KP_Delete: key = K_KP_DEL; break; + case XK_Delete: key = K_DEL; break; + + case XK_Pause: key = K_PAUSE; break; + + case XK_Shift_L: + case XK_Shift_R: key = K_SHIFT; break; + + case XK_Execute: + case XK_Control_L: + case XK_Control_R: key = K_CTRL; break; + + case XK_Alt_L: + case XK_Meta_L: + case XK_Alt_R: + case XK_Meta_R: key = K_ALT; break; + + case XK_KP_Begin: key = K_KP_5; break; + + case XK_Insert:key = K_INS; break; + case XK_KP_Insert: key = K_KP_INS; break; + + case XK_KP_Multiply: key = '*'; break; + case XK_KP_Add: key = K_KP_PLUS; break; + case XK_KP_Subtract: key = K_KP_MINUS; break; + case XK_KP_Divide: key = K_KP_SLASH; break; + +#if 0 + case 0x021: key = '1';break;/* [!] */ + case 0x040: key = '2';break;/* [@] */ + case 0x023: key = '3';break;/* [#] */ + case 0x024: key = '4';break;/* [$] */ + case 0x025: key = '5';break;/* [%] */ + case 0x05e: key = '6';break;/* [^] */ + case 0x026: key = '7';break;/* [&] */ + case 0x02a: key = '8';break;/* [*] */ + case 0x028: key = '9';;break;/* [(] */ + case 0x029: key = '0';break;/* [)] */ + case 0x05f: key = '-';break;/* [_] */ + case 0x02b: key = '=';break;/* [+] */ + case 0x07c: key = '\'';break;/* [|] */ + case 0x07d: key = '[';break;/* [}] */ + case 0x07b: key = ']';break;/* [{] */ + case 0x022: key = '\'';break;/* ["] */ + case 0x03a: key = ';';break;/* [:] */ + case 0x03f: key = '/';break;/* [?] */ + case 0x03e: key = '.';break;/* [>] */ + case 0x03c: key = ',';break;/* [<] */ +#endif + + default: + key = *(unsigned char*)buf; + if (key >= 'A' && key <= 'Z') + key = key - 'A' + 'a'; + break; + } + + return key; +} + +void GetEvent(void) +{ + XEvent x_event; + int b; + + XNextEvent(x_disp, &x_event); + switch(x_event.type) { + case KeyPress: + keyq[keyq_head].key = XLateKey(&x_event.xkey); + keyq[keyq_head].down = true; + keyq_head = (keyq_head + 1) & 63; + break; + case KeyRelease: + keyq[keyq_head].key = XLateKey(&x_event.xkey); + keyq[keyq_head].down = false; + keyq_head = (keyq_head + 1) & 63; + break; + + case MotionNotify: + if (_windowed_mouse->value) { + mx += ((int)x_event.xmotion.x - (int)(vid.width/2)); + my += ((int)x_event.xmotion.y - (int)(vid.height/2)); + + /* move the mouse to the window center again */ + XSelectInput(x_disp,x_win, STD_EVENT_MASK & ~PointerMotionMask); + XWarpPointer(x_disp,None,x_win,0,0,0,0, + (vid.width/2),(vid.height/2)); + XSelectInput(x_disp,x_win, STD_EVENT_MASK); + } else { + mx = ((int)x_event.xmotion.x - (int)p_mouse_x); + my = ((int)x_event.xmotion.y - (int)p_mouse_y); + p_mouse_x=x_event.xmotion.x; + p_mouse_y=x_event.xmotion.y; + } + break; + + case ButtonPress: + b=-1; + if (x_event.xbutton.button == 1) + b = 0; + else if (x_event.xbutton.button == 2) + b = 2; + else if (x_event.xbutton.button == 3) + b = 1; + if (b>=0) + mouse_buttonstate |= 1<=0) + mouse_buttonstate &= ~(1<value) { + old_windowed_mouse = _windowed_mouse->value; + + if (!_windowed_mouse->value) { + /* ungrab the pointer */ + XUngrabPointer(x_disp,CurrentTime); + } else { + /* grab the pointer */ + XGrabPointer(x_disp,x_win,True,0,GrabModeAsync, + GrabModeAsync,x_win,None,CurrentTime); + } + } +} + +/*****************************************************************************/ + +/*****************************************************************************/ +/* KEYBOARD */ +/*****************************************************************************/ + +Key_Event_fp_t Key_Event_fp; + +void KBD_Init(Key_Event_fp_t fp) +{ + _windowed_mouse = ri.Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE); + Key_Event_fp = fp; +} + +void KBD_Update(void) +{ +// get events from x server + if (x_disp) + { + while (XPending(x_disp)) + GetEvent(); + while (keyq_head != keyq_tail) + { + Key_Event_fp(keyq[keyq_tail].key, keyq[keyq_tail].down); + keyq_tail = (keyq_tail + 1) & 63; + } + } +} + +void KBD_Close(void) +{ +} + + +static void Force_CenterView_f (void) +{ + in_state->viewangles[PITCH] = 0; +} + +static void RW_IN_MLookDown (void) +{ + mlooking = true; +} + +static void RW_IN_MLookUp (void) +{ + mlooking = false; + in_state->IN_CenterView_fp (); +} + +void RW_IN_Init(in_state_t *in_state_p) +{ + int mtype; + int i; + + fprintf(stderr, "GL RW_IN_Init\n"); + + in_state = in_state_p; + + // mouse variables + _windowed_mouse = ri.Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE); + m_filter = ri.Cvar_Get ("m_filter", "0", 0); + in_mouse = ri.Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE); + freelook = ri.Cvar_Get( "freelook", "0", 0 ); + lookstrafe = ri.Cvar_Get ("lookstrafe", "0", 0); + sensitivity = ri.Cvar_Get ("sensitivity", "3", 0); + m_pitch = ri.Cvar_Get ("m_pitch", "0.022", 0); + m_yaw = ri.Cvar_Get ("m_yaw", "0.022", 0); + m_forward = ri.Cvar_Get ("m_forward", "1", 0); + m_side = ri.Cvar_Get ("m_side", "0.8", 0); + + ri.Cmd_AddCommand ("+mlook", RW_IN_MLookDown); + ri.Cmd_AddCommand ("-mlook", RW_IN_MLookUp); + + ri.Cmd_AddCommand ("force_centerview", Force_CenterView_f); + + mouse_x = mouse_y = 0.0; + mouse_avail = true; +} + +void RW_IN_Shutdown(void) +{ + mouse_avail = false; + + ri.Cmd_RemoveCommand ("force_centerview"); + ri.Cmd_RemoveCommand ("+mlook"); + ri.Cmd_RemoveCommand ("-mlook"); +} + +/* +=========== +IN_Commands +=========== +*/ +void RW_IN_Commands (void) +{ + int i; + + if (!mouse_avail) + return; + + for (i=0 ; i<3 ; i++) { + if ( (mouse_buttonstate & (1<Key_Event_fp (K_MOUSE1 + i, true); + + if ( !(mouse_buttonstate & (1<Key_Event_fp (K_MOUSE1 + i, false); + } + mouse_oldbuttonstate = mouse_buttonstate; +} + +/* +=========== +IN_Move +=========== +*/ +void RW_IN_Move (usercmd_t *cmd) +{ + if (!mouse_avail) + return; + + if (m_filter->value) + { + mouse_x = (mx + old_mouse_x) * 0.5; + mouse_y = (my + old_mouse_y) * 0.5; + } else { + mouse_x = mx; + mouse_y = my; + } + + old_mouse_x = mx; + old_mouse_y = my; + + if (!mouse_x && !mouse_y) + return; + + mouse_x *= sensitivity->value; + mouse_y *= sensitivity->value; + +// add mouse X/Y movement to cmd + if ( (*in_state->in_strafe_state & 1) || + (lookstrafe->value && mlooking )) + cmd->sidemove += m_side->value * mouse_x; + else + in_state->viewangles[YAW] -= m_yaw->value * mouse_x; + + if ( (mlooking || freelook->value) && + !(*in_state->in_strafe_state & 1)) + { + in_state->viewangles[PITCH] += m_pitch->value * mouse_y; + } + else + { + cmd->forwardmove -= m_forward->value * mouse_y; + } + mx = my = 0; +} + +void RW_IN_Frame (void) +{ +} + +void RW_IN_Activate(void) +{ +} + + +//=============================================================================== + +/* +================ +Sys_MakeCodeWriteable +================ +*/ +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +{ + + int r; + unsigned long addr; + int psize = getpagesize(); + + addr = (startaddr & ~(psize-1)) - psize; + +// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr, +// addr, startaddr+length, length); + + r = mprotect((char*)addr, length + startaddr - addr + psize, 7); + + if (r < 0) + Sys_Error("Protection change failed\n"); + +} diff --git a/irix/q_shirix.c b/irix/q_shirix.c new file mode 100644 index 000000000..9d2726438 --- /dev/null +++ b/irix/q_shirix.c @@ -0,0 +1,200 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../linux/glob.h" + +#include "../qcommon/qcommon.h" + +//=============================================================================== + +byte *membase; +int maxhunksize; +int curhunksize; + +void *Hunk_Begin (int maxsize) +{ + maxhunksize = maxsize + sizeof(int); + curhunksize = 0; +/* membase = mmap(0, maxhunksize, PROT_READ|PROT_WRITE, */ +/* MAP_PRIVATE, -1, 0); */ +/* if ((membase == NULL) || (membase == MAP_FAILED)) */ + membase = malloc(maxhunksize); + if (membase == NULL) + Com_Error(ERR_FATAL, "unable to virtual allocate %d bytes", maxsize); + + *((int *)membase) = curhunksize; + + return membase + sizeof(int); +} + +void *Hunk_Alloc (int size) +{ + byte *buf; + + // round to cacheline + size = (size+31)&~31; + if (curhunksize + size > maxhunksize) + Com_Error(ERR_FATAL, "Hunk_Alloc overflow"); + buf = membase + sizeof(int) + curhunksize; + curhunksize += size; + return buf; +} + +int Hunk_End (void) +{ + return curhunksize; +} + +void Hunk_Free (void *base) +{ + byte *m; + + if (base) { + m = ((byte *)base) - sizeof(int); + free(m); + } +} + +//=============================================================================== + + +/* +================ +Sys_Milliseconds +================ +*/ +int curtime; +int Sys_Milliseconds (void) +{ + struct timeval tp; + struct timezone tzp; + static int secbase; + + gettimeofday(&tp, &tzp); + + if (!secbase) + { + secbase = tp.tv_sec; + return tp.tv_usec/1000; + } + + curtime = (tp.tv_sec - secbase)*1000 + tp.tv_usec/1000; + + return curtime; +} + +void Sys_Mkdir (char *path) +{ + mkdir (path, 0777); +} + +char *strlwr (char *s) +{ + char *origs = s; + while (*s) { + *s = tolower(*s); + s++; + } + return origs; +} + +//============================================ + +static char findbase[MAX_OSPATH]; +static char findpath[MAX_OSPATH]; +static char findpattern[MAX_OSPATH]; +static DIR *fdir; + +static qboolean CompareAttributes(char *path, char *name, + unsigned musthave, unsigned canthave ) +{ + struct stat st; + char fn[MAX_OSPATH]; + +// . and .. never match + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + return false; + + sprintf(fn, "%s/%s", path, name); + if (stat(fn, &st) == -1) + return false; // shouldn't happen + + if ( ( st.st_mode & S_IFDIR ) && ( canthave & SFF_SUBDIR ) ) + return false; + + if ( ( musthave & SFF_SUBDIR ) && !( st.st_mode & S_IFDIR ) ) + return false; + + return true; +} + +char *Sys_FindFirst (char *path, unsigned musthave, unsigned canhave) +{ + struct dirent *d; + char *p; + + if (fdir) + Sys_Error ("Sys_BeginFind without close"); + +// COM_FilePath (path, findbase); + strcpy(findbase, path); + + if ((p = strrchr(findbase, '/')) != NULL) { + *p = 0; + strcpy(findpattern, p + 1); + } else + strcpy(findpattern, "*"); + + if (strcmp(findpattern, "*.*") == 0) + strcpy(findpattern, "*"); + + if ((fdir = opendir(findbase)) == NULL) + return NULL; + while ((d = readdir(fdir)) != NULL) { + if (!*findpattern || glob_match(findpattern, d->d_name)) { +// if (*findpattern) +// printf("%s matched %s\n", findpattern, d->d_name); + if (CompareAttributes(findbase, d->d_name, musthave, canhave)) { + sprintf (findpath, "%s/%s", findbase, d->d_name); + return findpath; + } + } + } + return NULL; +} + +char *Sys_FindNext (unsigned musthave, unsigned canhave) +{ + struct dirent *d; + + if (fdir == NULL) + return NULL; + while ((d = readdir(fdir)) != NULL) { + if (!*findpattern || glob_match(findpattern, d->d_name)) { +// if (*findpattern) +// printf("%s matched %s\n", findpattern, d->d_name); + if (CompareAttributes(findbase, d->d_name, musthave, canhave)) { + sprintf (findpath, "%s/%s", findbase, d->d_name); + return findpath; + } + } + } + return NULL; +} + +void Sys_FindClose (void) +{ + if (fdir != NULL) + closedir(fdir); + fdir = NULL; +} + + +//============================================ + diff --git a/irix/qgl_irix.c b/irix/qgl_irix.c new file mode 100644 index 000000000..c80c2c5f6 --- /dev/null +++ b/irix/qgl_irix.c @@ -0,0 +1,3997 @@ +/* +** QGL_WIN.C +** +** This file implements the operating system binding of GL to QGL function +** pointers. When doing a port of Quake2 you must implement the following +** two functions: +** +** QGL_Init() - loads libraries, assigns function pointers, etc. +** QGL_Shutdown() - unloads libraries, NULLs function pointers +*/ +#define QGL +#include "../ref_gl/gl_local.h" + +static FILE *log_fp = NULL; + +void ( APIENTRY * qglAccum )(GLenum op, GLfloat value); +void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref); +GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences); +void ( APIENTRY * qglArrayElement )(GLint i); +void ( APIENTRY * qglBegin )(GLenum mode); +void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture); +void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor); +void ( APIENTRY * qglCallList )(GLuint list); +void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists); +void ( APIENTRY * qglClear )(GLbitfield mask); +void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +void ( APIENTRY * qglClearDepth )(GLclampd depth); +void ( APIENTRY * qglClearIndex )(GLfloat c); +void ( APIENTRY * qglClearStencil )(GLint s); +void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation); +void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue); +void ( APIENTRY * qglColor3bv )(const GLbyte *v); +void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue); +void ( APIENTRY * qglColor3dv )(const GLdouble *v); +void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue); +void ( APIENTRY * qglColor3fv )(const GLfloat *v); +void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue); +void ( APIENTRY * qglColor3iv )(const GLint *v); +void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue); +void ( APIENTRY * qglColor3sv )(const GLshort *v); +void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue); +void ( APIENTRY * qglColor3ubv )(const GLubyte *v); +void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue); +void ( APIENTRY * qglColor3uiv )(const GLuint *v); +void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue); +void ( APIENTRY * qglColor3usv )(const GLushort *v); +void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +void ( APIENTRY * qglColor4bv )(const GLbyte *v); +void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +void ( APIENTRY * qglColor4dv )(const GLdouble *v); +void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +void ( APIENTRY * qglColor4fv )(const GLfloat *v); +void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha); +void ( APIENTRY * qglColor4iv )(const GLint *v); +void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha); +void ( APIENTRY * qglColor4sv )(const GLshort *v); +void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +void ( APIENTRY * qglColor4ubv )(const GLubyte *v); +void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha); +void ( APIENTRY * qglColor4uiv )(const GLuint *v); +void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha); +void ( APIENTRY * qglColor4usv )(const GLushort *v); +void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode); +void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +void ( APIENTRY * qglCullFace )(GLenum mode); +void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range); +void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures); +void ( APIENTRY * qglDepthFunc )(GLenum func); +void ( APIENTRY * qglDepthMask )(GLboolean flag); +void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar); +void ( APIENTRY * qglDisable )(GLenum cap); +void ( APIENTRY * qglDisableClientState )(GLenum array); +void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count); +void ( APIENTRY * qglDrawBuffer )(GLenum mode); +void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +void ( APIENTRY * qglEdgeFlag )(GLboolean flag); +void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag); +void ( APIENTRY * qglEnable )(GLenum cap); +void ( APIENTRY * qglEnableClientState )(GLenum array); +void ( APIENTRY * qglEnd )(void); +void ( APIENTRY * qglEndList )(void); +void ( APIENTRY * qglEvalCoord1d )(GLdouble u); +void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u); +void ( APIENTRY * qglEvalCoord1f )(GLfloat u); +void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u); +void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v); +void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u); +void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v); +void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u); +void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2); +void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +void ( APIENTRY * qglEvalPoint1 )(GLint i); +void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j); +void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer); +void ( APIENTRY * qglFinish )(void); +void ( APIENTRY * qglFlush )(void); +void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param); +void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params); +void ( APIENTRY * qglFogi )(GLenum pname, GLint param); +void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params); +void ( APIENTRY * qglFrontFace )(GLenum mode); +void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLuint ( APIENTRY * qglGenLists )(GLsizei range); +void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures); +void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params); +void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation); +void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params); +GLenum ( APIENTRY * qglGetError )(void); +void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params); +void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params); +void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v); +void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v); +void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v); +void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params); +void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values); +void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values); +void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values); +void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params); +void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask); +const GLubyte * ( APIENTRY * qglGetString )(GLenum name); +void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params); +void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params); +void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params); +void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params); +void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params); +void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params); +void ( APIENTRY * qglHint )(GLenum target, GLenum mode); +void ( APIENTRY * qglIndexMask )(GLuint mask); +void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglIndexd )(GLdouble c); +void ( APIENTRY * qglIndexdv )(const GLdouble *c); +void ( APIENTRY * qglIndexf )(GLfloat c); +void ( APIENTRY * qglIndexfv )(const GLfloat *c); +void ( APIENTRY * qglIndexi )(GLint c); +void ( APIENTRY * qglIndexiv )(const GLint *c); +void ( APIENTRY * qglIndexs )(GLshort c); +void ( APIENTRY * qglIndexsv )(const GLshort *c); +void ( APIENTRY * qglIndexub )(GLubyte c); +void ( APIENTRY * qglIndexubv )(const GLubyte *c); +void ( APIENTRY * qglInitNames )(void); +void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer); +GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap); +GLboolean ( APIENTRY * qglIsList )(GLuint list); +GLboolean ( APIENTRY * qglIsTexture )(GLuint texture); +void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param); +void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params); +void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param); +void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params); +void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param); +void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params); +void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param); +void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params); +void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern); +void ( APIENTRY * qglLineWidth )(GLfloat width); +void ( APIENTRY * qglListBase )(GLuint base); +void ( APIENTRY * qglLoadIdentity )(void); +void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m); +void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m); +void ( APIENTRY * qglLoadName )(GLuint name); +void ( APIENTRY * qglLogicOp )(GLenum opcode); +void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2); +void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2); +void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param); +void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params); +void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param); +void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params); +void ( APIENTRY * qglMatrixMode )(GLenum mode); +void ( APIENTRY * qglMultMatrixd )(const GLdouble *m); +void ( APIENTRY * qglMultMatrixf )(const GLfloat *m); +void ( APIENTRY * qglNewList )(GLuint list, GLenum mode); +void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz); +void ( APIENTRY * qglNormal3bv )(const GLbyte *v); +void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz); +void ( APIENTRY * qglNormal3dv )(const GLdouble *v); +void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz); +void ( APIENTRY * qglNormal3fv )(const GLfloat *v); +void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz); +void ( APIENTRY * qglNormal3iv )(const GLint *v); +void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz); +void ( APIENTRY * qglNormal3sv )(const GLshort *v); +void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +void ( APIENTRY * qglPassThrough )(GLfloat token); +void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values); +void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values); +void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values); +void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param); +void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param); +void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param); +void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param); +void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor); +void ( APIENTRY * qglPointSize )(GLfloat size); +void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode); +void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units); +void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask); +void ( APIENTRY * qglPopAttrib )(void); +void ( APIENTRY * qglPopClientAttrib )(void); +void ( APIENTRY * qglPopMatrix )(void); +void ( APIENTRY * qglPopName )(void); +void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities); +void ( APIENTRY * qglPushAttrib )(GLbitfield mask); +void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask); +void ( APIENTRY * qglPushMatrix )(void); +void ( APIENTRY * qglPushName )(GLuint name); +void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y); +void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v); +void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y); +void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v); +void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y); +void ( APIENTRY * qglRasterPos2iv )(const GLint *v); +void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y); +void ( APIENTRY * qglRasterPos2sv )(const GLshort *v); +void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z); +void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v); +void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z); +void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v); +void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z); +void ( APIENTRY * qglRasterPos3iv )(const GLint *v); +void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z); +void ( APIENTRY * qglRasterPos3sv )(const GLshort *v); +void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v); +void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v); +void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w); +void ( APIENTRY * qglRasterPos4iv )(const GLint *v); +void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w); +void ( APIENTRY * qglRasterPos4sv )(const GLshort *v); +void ( APIENTRY * qglReadBuffer )(GLenum mode); +void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2); +void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2); +void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2); +void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2); +void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2); +void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2); +GLint ( APIENTRY * qglRenderMode )(GLenum mode); +void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z); +void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z); +void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height); +void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer); +void ( APIENTRY * qglShadeModel )(GLenum mode); +void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask); +void ( APIENTRY * qglStencilMask )(GLuint mask); +void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass); +void ( APIENTRY * qglTexCoord1d )(GLdouble s); +void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v); +void ( APIENTRY * qglTexCoord1f )(GLfloat s); +void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v); +void ( APIENTRY * qglTexCoord1i )(GLint s); +void ( APIENTRY * qglTexCoord1iv )(const GLint *v); +void ( APIENTRY * qglTexCoord1s )(GLshort s); +void ( APIENTRY * qglTexCoord1sv )(const GLshort *v); +void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t); +void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v); +void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t); +void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v); +void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t); +void ( APIENTRY * qglTexCoord2iv )(const GLint *v); +void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t); +void ( APIENTRY * qglTexCoord2sv )(const GLshort *v); +void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r); +void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v); +void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r); +void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v); +void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r); +void ( APIENTRY * qglTexCoord3iv )(const GLint *v); +void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r); +void ( APIENTRY * qglTexCoord3sv )(const GLshort *v); +void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q); +void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v); +void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q); +void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v); +void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q); +void ( APIENTRY * qglTexCoord4iv )(const GLint *v); +void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q); +void ( APIENTRY * qglTexCoord4sv )(const GLshort *v); +void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param); +void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params); +void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param); +void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params); +void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param); +void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params); +void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param); +void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params); +void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param); +void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params); +void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param); +void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params); +void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param); +void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params); +void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z); +void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z); +void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y); +void ( APIENTRY * qglVertex2dv )(const GLdouble *v); +void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y); +void ( APIENTRY * qglVertex2fv )(const GLfloat *v); +void ( APIENTRY * qglVertex2i )(GLint x, GLint y); +void ( APIENTRY * qglVertex2iv )(const GLint *v); +void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y); +void ( APIENTRY * qglVertex2sv )(const GLshort *v); +void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z); +void ( APIENTRY * qglVertex3dv )(const GLdouble *v); +void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z); +void ( APIENTRY * qglVertex3fv )(const GLfloat *v); +void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z); +void ( APIENTRY * qglVertex3iv )(const GLint *v); +void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z); +void ( APIENTRY * qglVertex3sv )(const GLshort *v); +void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +void ( APIENTRY * qglVertex4dv )(const GLdouble *v); +void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +void ( APIENTRY * qglVertex4fv )(const GLfloat *v); +void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w); +void ( APIENTRY * qglVertex4iv )(const GLint *v); +void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w); +void ( APIENTRY * qglVertex4sv )(const GLshort *v); +void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height); + +void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value ); +void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value ); +void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * ); +void ( APIENTRY * qglSelectTextureSGIS)( GLenum ); +void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat ); + +static void ( APIENTRY * dllAccum )(GLenum op, GLfloat value); +static void ( APIENTRY * dllAlphaFunc )(GLenum func, GLclampf ref); +GLboolean ( APIENTRY * dllAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences); +static void ( APIENTRY * dllArrayElement )(GLint i); +static void ( APIENTRY * dllBegin )(GLenum mode); +static void ( APIENTRY * dllBindTexture )(GLenum target, GLuint texture); +static void ( APIENTRY * dllBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +static void ( APIENTRY * dllBlendFunc )(GLenum sfactor, GLenum dfactor); +static void ( APIENTRY * dllCallList )(GLuint list); +static void ( APIENTRY * dllCallLists )(GLsizei n, GLenum type, const GLvoid *lists); +static void ( APIENTRY * dllClear )(GLbitfield mask); +static void ( APIENTRY * dllClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +static void ( APIENTRY * dllClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +static void ( APIENTRY * dllClearDepth )(GLclampd depth); +static void ( APIENTRY * dllClearIndex )(GLfloat c); +static void ( APIENTRY * dllClearStencil )(GLint s); +static void ( APIENTRY * dllClipPlane )(GLenum plane, const GLdouble *equation); +static void ( APIENTRY * dllColor3b )(GLbyte red, GLbyte green, GLbyte blue); +static void ( APIENTRY * dllColor3bv )(const GLbyte *v); +static void ( APIENTRY * dllColor3d )(GLdouble red, GLdouble green, GLdouble blue); +static void ( APIENTRY * dllColor3dv )(const GLdouble *v); +static void ( APIENTRY * dllColor3f )(GLfloat red, GLfloat green, GLfloat blue); +static void ( APIENTRY * dllColor3fv )(const GLfloat *v); +static void ( APIENTRY * dllColor3i )(GLint red, GLint green, GLint blue); +static void ( APIENTRY * dllColor3iv )(const GLint *v); +static void ( APIENTRY * dllColor3s )(GLshort red, GLshort green, GLshort blue); +static void ( APIENTRY * dllColor3sv )(const GLshort *v); +static void ( APIENTRY * dllColor3ub )(GLubyte red, GLubyte green, GLubyte blue); +static void ( APIENTRY * dllColor3ubv )(const GLubyte *v); +static void ( APIENTRY * dllColor3ui )(GLuint red, GLuint green, GLuint blue); +static void ( APIENTRY * dllColor3uiv )(const GLuint *v); +static void ( APIENTRY * dllColor3us )(GLushort red, GLushort green, GLushort blue); +static void ( APIENTRY * dllColor3usv )(const GLushort *v); +static void ( APIENTRY * dllColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +static void ( APIENTRY * dllColor4bv )(const GLbyte *v); +static void ( APIENTRY * dllColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +static void ( APIENTRY * dllColor4dv )(const GLdouble *v); +static void ( APIENTRY * dllColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +static void ( APIENTRY * dllColor4fv )(const GLfloat *v); +static void ( APIENTRY * dllColor4i )(GLint red, GLint green, GLint blue, GLint alpha); +static void ( APIENTRY * dllColor4iv )(const GLint *v); +static void ( APIENTRY * dllColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha); +static void ( APIENTRY * dllColor4sv )(const GLshort *v); +static void ( APIENTRY * dllColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +static void ( APIENTRY * dllColor4ubv )(const GLubyte *v); +static void ( APIENTRY * dllColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha); +static void ( APIENTRY * dllColor4uiv )(const GLuint *v); +static void ( APIENTRY * dllColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha); +static void ( APIENTRY * dllColor4usv )(const GLushort *v); +static void ( APIENTRY * dllColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +static void ( APIENTRY * dllColorMaterial )(GLenum face, GLenum mode); +static void ( APIENTRY * dllColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +static void ( APIENTRY * dllCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +static void ( APIENTRY * dllCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +static void ( APIENTRY * dllCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +static void ( APIENTRY * dllCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +static void ( APIENTRY * dllCullFace )(GLenum mode); +static void ( APIENTRY * dllDeleteLists )(GLuint list, GLsizei range); +static void ( APIENTRY * dllDeleteTextures )(GLsizei n, const GLuint *textures); +static void ( APIENTRY * dllDepthFunc )(GLenum func); +static void ( APIENTRY * dllDepthMask )(GLboolean flag); +static void ( APIENTRY * dllDepthRange )(GLclampd zNear, GLclampd zFar); +static void ( APIENTRY * dllDisable )(GLenum cap); +static void ( APIENTRY * dllDisableClientState )(GLenum array); +static void ( APIENTRY * dllDrawArrays )(GLenum mode, GLint first, GLsizei count); +static void ( APIENTRY * dllDrawBuffer )(GLenum mode); +static void ( APIENTRY * dllDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +static void ( APIENTRY * dllDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +static void ( APIENTRY * dllEdgeFlag )(GLboolean flag); +static void ( APIENTRY * dllEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllEdgeFlagv )(const GLboolean *flag); +static void ( APIENTRY * dllEnable )(GLenum cap); +static void ( APIENTRY * dllEnableClientState )(GLenum array); +static void ( APIENTRY * dllEnd )(void); +static void ( APIENTRY * dllEndList )(void); +static void ( APIENTRY * dllEvalCoord1d )(GLdouble u); +static void ( APIENTRY * dllEvalCoord1dv )(const GLdouble *u); +static void ( APIENTRY * dllEvalCoord1f )(GLfloat u); +static void ( APIENTRY * dllEvalCoord1fv )(const GLfloat *u); +static void ( APIENTRY * dllEvalCoord2d )(GLdouble u, GLdouble v); +static void ( APIENTRY * dllEvalCoord2dv )(const GLdouble *u); +static void ( APIENTRY * dllEvalCoord2f )(GLfloat u, GLfloat v); +static void ( APIENTRY * dllEvalCoord2fv )(const GLfloat *u); +static void ( APIENTRY * dllEvalMesh1 )(GLenum mode, GLint i1, GLint i2); +static void ( APIENTRY * dllEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +static void ( APIENTRY * dllEvalPoint1 )(GLint i); +static void ( APIENTRY * dllEvalPoint2 )(GLint i, GLint j); +static void ( APIENTRY * dllFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer); +static void ( APIENTRY * dllFinish )(void); +static void ( APIENTRY * dllFlush )(void); +static void ( APIENTRY * dllFogf )(GLenum pname, GLfloat param); +static void ( APIENTRY * dllFogfv )(GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllFogi )(GLenum pname, GLint param); +static void ( APIENTRY * dllFogiv )(GLenum pname, const GLint *params); +static void ( APIENTRY * dllFrontFace )(GLenum mode); +static void ( APIENTRY * dllFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLuint ( APIENTRY * dllGenLists )(GLsizei range); +static void ( APIENTRY * dllGenTextures )(GLsizei n, GLuint *textures); +static void ( APIENTRY * dllGetBooleanv )(GLenum pname, GLboolean *params); +static void ( APIENTRY * dllGetClipPlane )(GLenum plane, GLdouble *equation); +static void ( APIENTRY * dllGetDoublev )(GLenum pname, GLdouble *params); +GLenum ( APIENTRY * dllGetError )(void); +static void ( APIENTRY * dllGetFloatv )(GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetIntegerv )(GLenum pname, GLint *params); +static void ( APIENTRY * dllGetLightfv )(GLenum light, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetLightiv )(GLenum light, GLenum pname, GLint *params); +static void ( APIENTRY * dllGetMapdv )(GLenum target, GLenum query, GLdouble *v); +static void ( APIENTRY * dllGetMapfv )(GLenum target, GLenum query, GLfloat *v); +static void ( APIENTRY * dllGetMapiv )(GLenum target, GLenum query, GLint *v); +static void ( APIENTRY * dllGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetMaterialiv )(GLenum face, GLenum pname, GLint *params); +static void ( APIENTRY * dllGetPixelMapfv )(GLenum map, GLfloat *values); +static void ( APIENTRY * dllGetPixelMapuiv )(GLenum map, GLuint *values); +static void ( APIENTRY * dllGetPixelMapusv )(GLenum map, GLushort *values); +static void ( APIENTRY * dllGetPointerv )(GLenum pname, GLvoid* *params); +static void ( APIENTRY * dllGetPolygonStipple )(GLubyte *mask); +const GLubyte * ( APIENTRY * dllGetString )(GLenum name); +static void ( APIENTRY * dllGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetTexEnviv )(GLenum target, GLenum pname, GLint *params); +static void ( APIENTRY * dllGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params); +static void ( APIENTRY * dllGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetTexGeniv )(GLenum coord, GLenum pname, GLint *params); +static void ( APIENTRY * dllGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +static void ( APIENTRY * dllGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params); +static void ( APIENTRY * dllGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params); +static void ( APIENTRY * dllGetTexParameteriv )(GLenum target, GLenum pname, GLint *params); +static void ( APIENTRY * dllHint )(GLenum target, GLenum mode); +static void ( APIENTRY * dllIndexMask )(GLuint mask); +static void ( APIENTRY * dllIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllIndexd )(GLdouble c); +static void ( APIENTRY * dllIndexdv )(const GLdouble *c); +static void ( APIENTRY * dllIndexf )(GLfloat c); +static void ( APIENTRY * dllIndexfv )(const GLfloat *c); +static void ( APIENTRY * dllIndexi )(GLint c); +static void ( APIENTRY * dllIndexiv )(const GLint *c); +static void ( APIENTRY * dllIndexs )(GLshort c); +static void ( APIENTRY * dllIndexsv )(const GLshort *c); +static void ( APIENTRY * dllIndexub )(GLubyte c); +static void ( APIENTRY * dllIndexubv )(const GLubyte *c); +static void ( APIENTRY * dllInitNames )(void); +static void ( APIENTRY * dllInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer); +GLboolean ( APIENTRY * dllIsEnabled )(GLenum cap); +GLboolean ( APIENTRY * dllIsList )(GLuint list); +GLboolean ( APIENTRY * dllIsTexture )(GLuint texture); +static void ( APIENTRY * dllLightModelf )(GLenum pname, GLfloat param); +static void ( APIENTRY * dllLightModelfv )(GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllLightModeli )(GLenum pname, GLint param); +static void ( APIENTRY * dllLightModeliv )(GLenum pname, const GLint *params); +static void ( APIENTRY * dllLightf )(GLenum light, GLenum pname, GLfloat param); +static void ( APIENTRY * dllLightfv )(GLenum light, GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllLighti )(GLenum light, GLenum pname, GLint param); +static void ( APIENTRY * dllLightiv )(GLenum light, GLenum pname, const GLint *params); +static void ( APIENTRY * dllLineStipple )(GLint factor, GLushort pattern); +static void ( APIENTRY * dllLineWidth )(GLfloat width); +static void ( APIENTRY * dllListBase )(GLuint base); +static void ( APIENTRY * dllLoadIdentity )(void); +static void ( APIENTRY * dllLoadMatrixd )(const GLdouble *m); +static void ( APIENTRY * dllLoadMatrixf )(const GLfloat *m); +static void ( APIENTRY * dllLoadName )(GLuint name); +static void ( APIENTRY * dllLogicOp )(GLenum opcode); +static void ( APIENTRY * dllMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +static void ( APIENTRY * dllMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +static void ( APIENTRY * dllMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +static void ( APIENTRY * dllMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +static void ( APIENTRY * dllMapGrid1d )(GLint un, GLdouble u1, GLdouble u2); +static void ( APIENTRY * dllMapGrid1f )(GLint un, GLfloat u1, GLfloat u2); +static void ( APIENTRY * dllMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +static void ( APIENTRY * dllMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +static void ( APIENTRY * dllMaterialf )(GLenum face, GLenum pname, GLfloat param); +static void ( APIENTRY * dllMaterialfv )(GLenum face, GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllMateriali )(GLenum face, GLenum pname, GLint param); +static void ( APIENTRY * dllMaterialiv )(GLenum face, GLenum pname, const GLint *params); +static void ( APIENTRY * dllMatrixMode )(GLenum mode); +static void ( APIENTRY * dllMultMatrixd )(const GLdouble *m); +static void ( APIENTRY * dllMultMatrixf )(const GLfloat *m); +static void ( APIENTRY * dllNewList )(GLuint list, GLenum mode); +static void ( APIENTRY * dllNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz); +static void ( APIENTRY * dllNormal3bv )(const GLbyte *v); +static void ( APIENTRY * dllNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz); +static void ( APIENTRY * dllNormal3dv )(const GLdouble *v); +static void ( APIENTRY * dllNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz); +static void ( APIENTRY * dllNormal3fv )(const GLfloat *v); +static void ( APIENTRY * dllNormal3i )(GLint nx, GLint ny, GLint nz); +static void ( APIENTRY * dllNormal3iv )(const GLint *v); +static void ( APIENTRY * dllNormal3s )(GLshort nx, GLshort ny, GLshort nz); +static void ( APIENTRY * dllNormal3sv )(const GLshort *v); +static void ( APIENTRY * dllNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +static void ( APIENTRY * dllPassThrough )(GLfloat token); +static void ( APIENTRY * dllPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values); +static void ( APIENTRY * dllPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values); +static void ( APIENTRY * dllPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values); +static void ( APIENTRY * dllPixelStoref )(GLenum pname, GLfloat param); +static void ( APIENTRY * dllPixelStorei )(GLenum pname, GLint param); +static void ( APIENTRY * dllPixelTransferf )(GLenum pname, GLfloat param); +static void ( APIENTRY * dllPixelTransferi )(GLenum pname, GLint param); +static void ( APIENTRY * dllPixelZoom )(GLfloat xfactor, GLfloat yfactor); +static void ( APIENTRY * dllPointSize )(GLfloat size); +static void ( APIENTRY * dllPolygonMode )(GLenum face, GLenum mode); +static void ( APIENTRY * dllPolygonOffset )(GLfloat factor, GLfloat units); +static void ( APIENTRY * dllPolygonStipple )(const GLubyte *mask); +static void ( APIENTRY * dllPopAttrib )(void); +static void ( APIENTRY * dllPopClientAttrib )(void); +static void ( APIENTRY * dllPopMatrix )(void); +static void ( APIENTRY * dllPopName )(void); +static void ( APIENTRY * dllPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities); +static void ( APIENTRY * dllPushAttrib )(GLbitfield mask); +static void ( APIENTRY * dllPushClientAttrib )(GLbitfield mask); +static void ( APIENTRY * dllPushMatrix )(void); +static void ( APIENTRY * dllPushName )(GLuint name); +static void ( APIENTRY * dllRasterPos2d )(GLdouble x, GLdouble y); +static void ( APIENTRY * dllRasterPos2dv )(const GLdouble *v); +static void ( APIENTRY * dllRasterPos2f )(GLfloat x, GLfloat y); +static void ( APIENTRY * dllRasterPos2fv )(const GLfloat *v); +static void ( APIENTRY * dllRasterPos2i )(GLint x, GLint y); +static void ( APIENTRY * dllRasterPos2iv )(const GLint *v); +static void ( APIENTRY * dllRasterPos2s )(GLshort x, GLshort y); +static void ( APIENTRY * dllRasterPos2sv )(const GLshort *v); +static void ( APIENTRY * dllRasterPos3d )(GLdouble x, GLdouble y, GLdouble z); +static void ( APIENTRY * dllRasterPos3dv )(const GLdouble *v); +static void ( APIENTRY * dllRasterPos3f )(GLfloat x, GLfloat y, GLfloat z); +static void ( APIENTRY * dllRasterPos3fv )(const GLfloat *v); +static void ( APIENTRY * dllRasterPos3i )(GLint x, GLint y, GLint z); +static void ( APIENTRY * dllRasterPos3iv )(const GLint *v); +static void ( APIENTRY * dllRasterPos3s )(GLshort x, GLshort y, GLshort z); +static void ( APIENTRY * dllRasterPos3sv )(const GLshort *v); +static void ( APIENTRY * dllRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +static void ( APIENTRY * dllRasterPos4dv )(const GLdouble *v); +static void ( APIENTRY * dllRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +static void ( APIENTRY * dllRasterPos4fv )(const GLfloat *v); +static void ( APIENTRY * dllRasterPos4i )(GLint x, GLint y, GLint z, GLint w); +static void ( APIENTRY * dllRasterPos4iv )(const GLint *v); +static void ( APIENTRY * dllRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w); +static void ( APIENTRY * dllRasterPos4sv )(const GLshort *v); +static void ( APIENTRY * dllReadBuffer )(GLenum mode); +static void ( APIENTRY * dllReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +static void ( APIENTRY * dllRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +static void ( APIENTRY * dllRectdv )(const GLdouble *v1, const GLdouble *v2); +static void ( APIENTRY * dllRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +static void ( APIENTRY * dllRectfv )(const GLfloat *v1, const GLfloat *v2); +static void ( APIENTRY * dllRecti )(GLint x1, GLint y1, GLint x2, GLint y2); +static void ( APIENTRY * dllRectiv )(const GLint *v1, const GLint *v2); +static void ( APIENTRY * dllRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2); +static void ( APIENTRY * dllRectsv )(const GLshort *v1, const GLshort *v2); +GLint ( APIENTRY * dllRenderMode )(GLenum mode); +static void ( APIENTRY * dllRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +static void ( APIENTRY * dllRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +static void ( APIENTRY * dllScaled )(GLdouble x, GLdouble y, GLdouble z); +static void ( APIENTRY * dllScalef )(GLfloat x, GLfloat y, GLfloat z); +static void ( APIENTRY * dllScissor )(GLint x, GLint y, GLsizei width, GLsizei height); +static void ( APIENTRY * dllSelectBuffer )(GLsizei size, GLuint *buffer); +static void ( APIENTRY * dllShadeModel )(GLenum mode); +static void ( APIENTRY * dllStencilFunc )(GLenum func, GLint ref, GLuint mask); +static void ( APIENTRY * dllStencilMask )(GLuint mask); +static void ( APIENTRY * dllStencilOp )(GLenum fail, GLenum zfail, GLenum zpass); +static void ( APIENTRY * dllTexCoord1d )(GLdouble s); +static void ( APIENTRY * dllTexCoord1dv )(const GLdouble *v); +static void ( APIENTRY * dllTexCoord1f )(GLfloat s); +static void ( APIENTRY * dllTexCoord1fv )(const GLfloat *v); +static void ( APIENTRY * dllTexCoord1i )(GLint s); +static void ( APIENTRY * dllTexCoord1iv )(const GLint *v); +static void ( APIENTRY * dllTexCoord1s )(GLshort s); +static void ( APIENTRY * dllTexCoord1sv )(const GLshort *v); +static void ( APIENTRY * dllTexCoord2d )(GLdouble s, GLdouble t); +static void ( APIENTRY * dllTexCoord2dv )(const GLdouble *v); +static void ( APIENTRY * dllTexCoord2f )(GLfloat s, GLfloat t); +static void ( APIENTRY * dllTexCoord2fv )(const GLfloat *v); +static void ( APIENTRY * dllTexCoord2i )(GLint s, GLint t); +static void ( APIENTRY * dllTexCoord2iv )(const GLint *v); +static void ( APIENTRY * dllTexCoord2s )(GLshort s, GLshort t); +static void ( APIENTRY * dllTexCoord2sv )(const GLshort *v); +static void ( APIENTRY * dllTexCoord3d )(GLdouble s, GLdouble t, GLdouble r); +static void ( APIENTRY * dllTexCoord3dv )(const GLdouble *v); +static void ( APIENTRY * dllTexCoord3f )(GLfloat s, GLfloat t, GLfloat r); +static void ( APIENTRY * dllTexCoord3fv )(const GLfloat *v); +static void ( APIENTRY * dllTexCoord3i )(GLint s, GLint t, GLint r); +static void ( APIENTRY * dllTexCoord3iv )(const GLint *v); +static void ( APIENTRY * dllTexCoord3s )(GLshort s, GLshort t, GLshort r); +static void ( APIENTRY * dllTexCoord3sv )(const GLshort *v); +static void ( APIENTRY * dllTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q); +static void ( APIENTRY * dllTexCoord4dv )(const GLdouble *v); +static void ( APIENTRY * dllTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q); +static void ( APIENTRY * dllTexCoord4fv )(const GLfloat *v); +static void ( APIENTRY * dllTexCoord4i )(GLint s, GLint t, GLint r, GLint q); +static void ( APIENTRY * dllTexCoord4iv )(const GLint *v); +static void ( APIENTRY * dllTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q); +static void ( APIENTRY * dllTexCoord4sv )(const GLshort *v); +static void ( APIENTRY * dllTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllTexEnvf )(GLenum target, GLenum pname, GLfloat param); +static void ( APIENTRY * dllTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllTexEnvi )(GLenum target, GLenum pname, GLint param); +static void ( APIENTRY * dllTexEnviv )(GLenum target, GLenum pname, const GLint *params); +static void ( APIENTRY * dllTexGend )(GLenum coord, GLenum pname, GLdouble param); +static void ( APIENTRY * dllTexGendv )(GLenum coord, GLenum pname, const GLdouble *params); +static void ( APIENTRY * dllTexGenf )(GLenum coord, GLenum pname, GLfloat param); +static void ( APIENTRY * dllTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllTexGeni )(GLenum coord, GLenum pname, GLint param); +static void ( APIENTRY * dllTexGeniv )(GLenum coord, GLenum pname, const GLint *params); +static void ( APIENTRY * dllTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +static void ( APIENTRY * dllTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +static void ( APIENTRY * dllTexParameterf )(GLenum target, GLenum pname, GLfloat param); +static void ( APIENTRY * dllTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params); +static void ( APIENTRY * dllTexParameteri )(GLenum target, GLenum pname, GLint param); +static void ( APIENTRY * dllTexParameteriv )(GLenum target, GLenum pname, const GLint *params); +static void ( APIENTRY * dllTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +static void ( APIENTRY * dllTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +static void ( APIENTRY * dllTranslated )(GLdouble x, GLdouble y, GLdouble z); +static void ( APIENTRY * dllTranslatef )(GLfloat x, GLfloat y, GLfloat z); +static void ( APIENTRY * dllVertex2d )(GLdouble x, GLdouble y); +static void ( APIENTRY * dllVertex2dv )(const GLdouble *v); +static void ( APIENTRY * dllVertex2f )(GLfloat x, GLfloat y); +static void ( APIENTRY * dllVertex2fv )(const GLfloat *v); +static void ( APIENTRY * dllVertex2i )(GLint x, GLint y); +static void ( APIENTRY * dllVertex2iv )(const GLint *v); +static void ( APIENTRY * dllVertex2s )(GLshort x, GLshort y); +static void ( APIENTRY * dllVertex2sv )(const GLshort *v); +static void ( APIENTRY * dllVertex3d )(GLdouble x, GLdouble y, GLdouble z); +static void ( APIENTRY * dllVertex3dv )(const GLdouble *v); +static void ( APIENTRY * dllVertex3f )(GLfloat x, GLfloat y, GLfloat z); +static void ( APIENTRY * dllVertex3fv )(const GLfloat *v); +static void ( APIENTRY * dllVertex3i )(GLint x, GLint y, GLint z); +static void ( APIENTRY * dllVertex3iv )(const GLint *v); +static void ( APIENTRY * dllVertex3s )(GLshort x, GLshort y, GLshort z); +static void ( APIENTRY * dllVertex3sv )(const GLshort *v); +static void ( APIENTRY * dllVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +static void ( APIENTRY * dllVertex4dv )(const GLdouble *v); +static void ( APIENTRY * dllVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +static void ( APIENTRY * dllVertex4fv )(const GLfloat *v); +static void ( APIENTRY * dllVertex4i )(GLint x, GLint y, GLint z, GLint w); +static void ( APIENTRY * dllVertex4iv )(const GLint *v); +static void ( APIENTRY * dllVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w); +static void ( APIENTRY * dllVertex4sv )(const GLshort *v); +static void ( APIENTRY * dllVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static void ( APIENTRY * dllViewport )(GLint x, GLint y, GLsizei width, GLsizei height); + +static void APIENTRY logAccum(GLenum op, GLfloat value) +{ + fprintf( log_fp, "glAccum\n" ); + dllAccum( op, value ); +} + +static void APIENTRY logAlphaFunc(GLenum func, GLclampf ref) +{ + fprintf( log_fp, "glAlphaFunc( 0x%x, %f )\n", func, ref ); + dllAlphaFunc( func, ref ); +} + +static GLboolean APIENTRY logAreTexturesResident(GLsizei n, const GLuint *textures, GLboolean *residences) +{ + fprintf( log_fp, "glAreTexturesResident\n" ); + return dllAreTexturesResident( n, textures, residences ); +} + +static void APIENTRY logArrayElement(GLint i) +{ + fprintf( log_fp, "glArrayElement\n" ); + dllArrayElement( i ); +} + +static void APIENTRY logBegin(GLenum mode) +{ + fprintf( log_fp, "glBegin( 0x%x )\n", mode ); + dllBegin( mode ); +} + +static void APIENTRY logBindTexture(GLenum target, GLuint texture) +{ + fprintf( log_fp, "glBindTexture( 0x%x, %u )\n", target, texture ); + dllBindTexture( target, texture ); +} + +static void APIENTRY logBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) +{ + fprintf( log_fp, "glBitmap\n" ); + dllBitmap( width, height, xorig, yorig, xmove, ymove, bitmap ); +} + +static void APIENTRY logBlendFunc(GLenum sfactor, GLenum dfactor) +{ + fprintf( log_fp, "glBlendFunc( 0x%x, 0x%x )\n", sfactor, dfactor ); + dllBlendFunc( sfactor, dfactor ); +} + +static void APIENTRY logCallList(GLuint list) +{ + fprintf( log_fp, "glCallList( %u )\n", list ); + dllCallList( list ); +} + +static void APIENTRY logCallLists(GLsizei n, GLenum type, const void *lists) +{ + fprintf( log_fp, "glCallLists\n" ); + dllCallLists( n, type, lists ); +} + +static void APIENTRY logClear(GLbitfield mask) +{ + fprintf( log_fp, "glClear\n" ); + dllClear( mask ); +} + +static void APIENTRY logClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +{ + fprintf( log_fp, "glClearAccum\n" ); + dllClearAccum( red, green, blue, alpha ); +} + +static void APIENTRY logClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + fprintf( log_fp, "glClearColor\n" ); + dllClearColor( red, green, blue, alpha ); +} + +static void APIENTRY logClearDepth(GLclampd depth) +{ + fprintf( log_fp, "glClearDepth\n" ); + dllClearDepth( depth ); +} + +static void APIENTRY logClearIndex(GLfloat c) +{ + fprintf( log_fp, "glClearIndex\n" ); + dllClearIndex( c ); +} + +static void APIENTRY logClearStencil(GLint s) +{ + fprintf( log_fp, "glClearStencil\n" ); + dllClearStencil( s ); +} + +static void APIENTRY logClipPlane(GLenum plane, const GLdouble *equation) +{ + fprintf( log_fp, "glClipPlane\n" ); + dllClipPlane( plane, equation ); +} + +static void APIENTRY logColor3b(GLbyte red, GLbyte green, GLbyte blue) +{ + fprintf( log_fp, "glColor3b\n" ); + dllColor3b( red, green, blue ); +} + +static void APIENTRY logColor3bv(const GLbyte *v) +{ + fprintf( log_fp, "glColor3bv\n" ); + dllColor3bv( v ); +} + +static void APIENTRY logColor3d(GLdouble red, GLdouble green, GLdouble blue) +{ + fprintf( log_fp, "glColor3d\n" ); + dllColor3d( red, green, blue ); +} + +static void APIENTRY logColor3dv(const GLdouble *v) +{ + fprintf( log_fp, "glColor3dv\n" ); + dllColor3dv( v ); +} + +static void APIENTRY logColor3f(GLfloat red, GLfloat green, GLfloat blue) +{ + fprintf( log_fp, "glColor3f\n" ); + dllColor3f( red, green, blue ); +} + +static void APIENTRY logColor3fv(const GLfloat *v) +{ + fprintf( log_fp, "glColor3fv\n" ); + dllColor3fv( v ); +} + +static void APIENTRY logColor3i(GLint red, GLint green, GLint blue) +{ + fprintf( log_fp, "glColor3i\n" ); + dllColor3i( red, green, blue ); +} + +static void APIENTRY logColor3iv(const GLint *v) +{ + fprintf( log_fp, "glColor3iv\n" ); + dllColor3iv( v ); +} + +static void APIENTRY logColor3s(GLshort red, GLshort green, GLshort blue) +{ + fprintf( log_fp, "glColor3s\n" ); + dllColor3s( red, green, blue ); +} + +static void APIENTRY logColor3sv(const GLshort *v) +{ + fprintf( log_fp, "glColor3sv\n" ); + dllColor3sv( v ); +} + +static void APIENTRY logColor3ub(GLubyte red, GLubyte green, GLubyte blue) +{ + fprintf( log_fp, "glColor3ub\n" ); + dllColor3ub( red, green, blue ); +} + +static void APIENTRY logColor3ubv(const GLubyte *v) +{ + fprintf( log_fp, "glColor3ubv\n" ); + dllColor3ubv( v ); +} + +#define SIG( x ) fprintf( log_fp, x "\n" ) + +static void APIENTRY logColor3ui(GLuint red, GLuint green, GLuint blue) +{ + SIG( "glColor3ui" ); + dllColor3ui( red, green, blue ); +} + +static void APIENTRY logColor3uiv(const GLuint *v) +{ + SIG( "glColor3uiv" ); + dllColor3uiv( v ); +} + +static void APIENTRY logColor3us(GLushort red, GLushort green, GLushort blue) +{ + SIG( "glColor3us" ); + dllColor3us( red, green, blue ); +} + +static void APIENTRY logColor3usv(const GLushort *v) +{ + SIG( "glColor3usv" ); + dllColor3usv( v ); +} + +static void APIENTRY logColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) +{ + SIG( "glColor4b" ); + dllColor4b( red, green, blue, alpha ); +} + +static void APIENTRY logColor4bv(const GLbyte *v) +{ + SIG( "glColor4bv" ); + dllColor4bv( v ); +} + +static void APIENTRY logColor4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) +{ + SIG( "glColor4d" ); + dllColor4d( red, green, blue, alpha ); +} +static void APIENTRY logColor4dv(const GLdouble *v) +{ + SIG( "glColor4dv" ); + dllColor4dv( v ); +} +static void APIENTRY logColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +{ + SIG( "glColor4f" ); + dllColor4f( red, green, blue, alpha ); +} +static void APIENTRY logColor4fv(const GLfloat *v) +{ + SIG( "glColor4fv" ); + dllColor4fv( v ); +} +static void APIENTRY logColor4i(GLint red, GLint green, GLint blue, GLint alpha) +{ + SIG( "glColor4i" ); + dllColor4i( red, green, blue, alpha ); +} +static void APIENTRY logColor4iv(const GLint *v) +{ + SIG( "glColor4iv" ); + dllColor4iv( v ); +} +static void APIENTRY logColor4s(GLshort red, GLshort green, GLshort blue, GLshort alpha) +{ + SIG( "glColor4s" ); + dllColor4s( red, green, blue, alpha ); +} +static void APIENTRY logColor4sv(const GLshort *v) +{ + SIG( "glColor4sv" ); + dllColor4sv( v ); +} +static void APIENTRY logColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) +{ + SIG( "glColor4b" ); + dllColor4b( red, green, blue, alpha ); +} +static void APIENTRY logColor4ubv(const GLubyte *v) +{ + SIG( "glColor4ubv" ); + dllColor4ubv( v ); +} +static void APIENTRY logColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha) +{ + SIG( "glColor4ui" ); + dllColor4ui( red, green, blue, alpha ); +} +static void APIENTRY logColor4uiv(const GLuint *v) +{ + SIG( "glColor4uiv" ); + dllColor4uiv( v ); +} +static void APIENTRY logColor4us(GLushort red, GLushort green, GLushort blue, GLushort alpha) +{ + SIG( "glColor4us" ); + dllColor4us( red, green, blue, alpha ); +} +static void APIENTRY logColor4usv(const GLushort *v) +{ + SIG( "glColor4usv" ); + dllColor4usv( v ); +} +static void APIENTRY logColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + SIG( "glColorMask" ); + dllColorMask( red, green, blue, alpha ); +} +static void APIENTRY logColorMaterial(GLenum face, GLenum mode) +{ + SIG( "glColorMaterial" ); + dllColorMaterial( face, mode ); +} + +static void APIENTRY logColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) +{ + SIG( "glColorPointer" ); + dllColorPointer( size, type, stride, pointer ); +} + +static void APIENTRY logCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) +{ + SIG( "glCopyPixels" ); + dllCopyPixels( x, y, width, height, type ); +} + +static void APIENTRY logCopyTexImage1D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border) +{ + SIG( "glCopyTexImage1D" ); + dllCopyTexImage1D( target, level, internalFormat, x, y, width, border ); +} + +static void APIENTRY logCopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + SIG( "glCopyTexImage2D" ); + dllCopyTexImage2D( target, level, internalFormat, x, y, width, height, border ); +} + +static void APIENTRY logCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) +{ + SIG( "glCopyTexSubImage1D" ); + dllCopyTexSubImage1D( target, level, xoffset, x, y, width ); +} + +static void APIENTRY logCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + SIG( "glCopyTexSubImage2D" ); + dllCopyTexSubImage2D( target, level, xoffset, yoffset, x, y, width, height ); +} + +static void APIENTRY logCullFace(GLenum mode) +{ + SIG( "glCullFace" ); + dllCullFace( mode ); +} + +static void APIENTRY logDeleteLists(GLuint list, GLsizei range) +{ + SIG( "glDeleteLists" ); + dllDeleteLists( list, range ); +} + +static void APIENTRY logDeleteTextures(GLsizei n, const GLuint *textures) +{ + SIG( "glDeleteTextures" ); + dllDeleteTextures( n, textures ); +} + +static void APIENTRY logDepthFunc(GLenum func) +{ + SIG( "glDepthFunc" ); + dllDepthFunc( func ); +} + +static void APIENTRY logDepthMask(GLboolean flag) +{ + SIG( "glDepthMask" ); + dllDepthMask( flag ); +} + +static void APIENTRY logDepthRange(GLclampd zNear, GLclampd zFar) +{ + SIG( "glDepthRange" ); + dllDepthRange( zNear, zFar ); +} + +static void APIENTRY logDisable(GLenum cap) +{ + fprintf( log_fp, "glDisable( 0x%x )\n", cap ); + dllDisable( cap ); +} + +static void APIENTRY logDisableClientState(GLenum array) +{ + SIG( "glDisableClientState" ); + dllDisableClientState( array ); +} + +static void APIENTRY logDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + SIG( "glDrawArrays" ); + dllDrawArrays( mode, first, count ); +} + +static void APIENTRY logDrawBuffer(GLenum mode) +{ + SIG( "glDrawBuffer" ); + dllDrawBuffer( mode ); +} + +static void APIENTRY logDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) +{ + SIG( "glDrawElements" ); + dllDrawElements( mode, count, type, indices ); +} + +static void APIENTRY logDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) +{ + SIG( "glDrawPixels" ); + dllDrawPixels( width, height, format, type, pixels ); +} + +static void APIENTRY logEdgeFlag(GLboolean flag) +{ + SIG( "glEdgeFlag" ); + dllEdgeFlag( flag ); +} + +static void APIENTRY logEdgeFlagPointer(GLsizei stride, const void *pointer) +{ + SIG( "glEdgeFlagPointer" ); + dllEdgeFlagPointer( stride, pointer ); +} + +static void APIENTRY logEdgeFlagv(const GLboolean *flag) +{ + SIG( "glEdgeFlagv" ); + dllEdgeFlagv( flag ); +} + +static void APIENTRY logEnable(GLenum cap) +{ + fprintf( log_fp, "glEnable( 0x%x )\n", cap ); + dllEnable( cap ); +} + +static void APIENTRY logEnableClientState(GLenum array) +{ + SIG( "glEnableClientState" ); + dllEnableClientState( array ); +} + +static void APIENTRY logEnd(void) +{ + SIG( "glEnd" ); + dllEnd(); +} + +static void APIENTRY logEndList(void) +{ + SIG( "glEndList" ); + dllEndList(); +} + +static void APIENTRY logEvalCoord1d(GLdouble u) +{ + SIG( "glEvalCoord1d" ); + dllEvalCoord1d( u ); +} + +static void APIENTRY logEvalCoord1dv(const GLdouble *u) +{ + SIG( "glEvalCoord1dv" ); + dllEvalCoord1dv( u ); +} + +static void APIENTRY logEvalCoord1f(GLfloat u) +{ + SIG( "glEvalCoord1f" ); + dllEvalCoord1f( u ); +} + +static void APIENTRY logEvalCoord1fv(const GLfloat *u) +{ + SIG( "glEvalCoord1fv" ); + dllEvalCoord1fv( u ); +} +static void APIENTRY logEvalCoord2d(GLdouble u, GLdouble v) +{ + SIG( "glEvalCoord2d" ); + dllEvalCoord2d( u, v ); +} +static void APIENTRY logEvalCoord2dv(const GLdouble *u) +{ + SIG( "glEvalCoord2dv" ); + dllEvalCoord2dv( u ); +} +static void APIENTRY logEvalCoord2f(GLfloat u, GLfloat v) +{ + SIG( "glEvalCoord2f" ); + dllEvalCoord2f( u, v ); +} +static void APIENTRY logEvalCoord2fv(const GLfloat *u) +{ + SIG( "glEvalCoord2fv" ); + dllEvalCoord2fv( u ); +} + +static void APIENTRY logEvalMesh1(GLenum mode, GLint i1, GLint i2) +{ + SIG( "glEvalMesh1" ); + dllEvalMesh1( mode, i1, i2 ); +} +static void APIENTRY logEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) +{ + SIG( "glEvalMesh2" ); + dllEvalMesh2( mode, i1, i2, j1, j2 ); +} +static void APIENTRY logEvalPoint1(GLint i) +{ + SIG( "glEvalPoint1" ); + dllEvalPoint1( i ); +} +static void APIENTRY logEvalPoint2(GLint i, GLint j) +{ + SIG( "glEvalPoint2" ); + dllEvalPoint2( i, j ); +} + +static void APIENTRY logFeedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer) +{ + SIG( "glFeedbackBuffer" ); + dllFeedbackBuffer( size, type, buffer ); +} + +static void APIENTRY logFinish(void) +{ + SIG( "glFinish" ); + dllFinish(); +} + +static void APIENTRY logFlush(void) +{ + SIG( "glFlush" ); + dllFlush(); +} + +static void APIENTRY logFogf(GLenum pname, GLfloat param) +{ + SIG( "glFogf" ); + dllFogf( pname, param ); +} + +static void APIENTRY logFogfv(GLenum pname, const GLfloat *params) +{ + SIG( "glFogfv" ); + dllFogfv( pname, params ); +} + +static void APIENTRY logFogi(GLenum pname, GLint param) +{ + SIG( "glFogi" ); + dllFogi( pname, param ); +} + +static void APIENTRY logFogiv(GLenum pname, const GLint *params) +{ + SIG( "glFogiv" ); + dllFogiv( pname, params ); +} + +static void APIENTRY logFrontFace(GLenum mode) +{ + SIG( "glFrontFace" ); + dllFrontFace( mode ); +} + +static void APIENTRY logFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) +{ + SIG( "glFrustum" ); + dllFrustum( left, right, bottom, top, zNear, zFar ); +} + +static GLuint APIENTRY logGenLists(GLsizei range) +{ + SIG( "glGenLists" ); + return dllGenLists( range ); +} + +static void APIENTRY logGenTextures(GLsizei n, GLuint *textures) +{ + SIG( "glGenTextures" ); + dllGenTextures( n, textures ); +} + +static void APIENTRY logGetBooleanv(GLenum pname, GLboolean *params) +{ + SIG( "glGetBooleanv" ); + dllGetBooleanv( pname, params ); +} + +static void APIENTRY logGetClipPlane(GLenum plane, GLdouble *equation) +{ + SIG( "glGetClipPlane" ); + dllGetClipPlane( plane, equation ); +} + +static void APIENTRY logGetDoublev(GLenum pname, GLdouble *params) +{ + SIG( "glGetDoublev" ); + dllGetDoublev( pname, params ); +} + +static GLenum APIENTRY logGetError(void) +{ + SIG( "glGetError" ); + return dllGetError(); +} + +static void APIENTRY logGetFloatv(GLenum pname, GLfloat *params) +{ + SIG( "glGetFloatv" ); + dllGetFloatv( pname, params ); +} + +static void APIENTRY logGetIntegerv(GLenum pname, GLint *params) +{ + SIG( "glGetIntegerv" ); + dllGetIntegerv( pname, params ); +} + +static void APIENTRY logGetLightfv(GLenum light, GLenum pname, GLfloat *params) +{ + SIG( "glGetLightfv" ); + dllGetLightfv( light, pname, params ); +} + +static void APIENTRY logGetLightiv(GLenum light, GLenum pname, GLint *params) +{ + SIG( "glGetLightiv" ); + dllGetLightiv( light, pname, params ); +} + +static void APIENTRY logGetMapdv(GLenum target, GLenum query, GLdouble *v) +{ + SIG( "glGetMapdv" ); + dllGetMapdv( target, query, v ); +} + +static void APIENTRY logGetMapfv(GLenum target, GLenum query, GLfloat *v) +{ + SIG( "glGetMapfv" ); + dllGetMapfv( target, query, v ); +} + +static void APIENTRY logGetMapiv(GLenum target, GLenum query, GLint *v) +{ + SIG( "glGetMapiv" ); + dllGetMapiv( target, query, v ); +} + +static void APIENTRY logGetMaterialfv(GLenum face, GLenum pname, GLfloat *params) +{ + SIG( "glGetMaterialfv" ); + dllGetMaterialfv( face, pname, params ); +} + +static void APIENTRY logGetMaterialiv(GLenum face, GLenum pname, GLint *params) +{ + SIG( "glGetMaterialiv" ); + dllGetMaterialiv( face, pname, params ); +} + +static void APIENTRY logGetPixelMapfv(GLenum map, GLfloat *values) +{ + SIG( "glGetPixelMapfv" ); + dllGetPixelMapfv( map, values ); +} + +static void APIENTRY logGetPixelMapuiv(GLenum map, GLuint *values) +{ + SIG( "glGetPixelMapuiv" ); + dllGetPixelMapuiv( map, values ); +} + +static void APIENTRY logGetPixelMapusv(GLenum map, GLushort *values) +{ + SIG( "glGetPixelMapusv" ); + dllGetPixelMapusv( map, values ); +} + +static void APIENTRY logGetPointerv(GLenum pname, GLvoid* *params) +{ + SIG( "glGetPointerv" ); + dllGetPointerv( pname, params ); +} + +static void APIENTRY logGetPolygonStipple(GLubyte *mask) +{ + SIG( "glGetPolygonStipple" ); + dllGetPolygonStipple( mask ); +} + +static const GLubyte * APIENTRY logGetString(GLenum name) +{ + SIG( "glGetString" ); + return dllGetString( name ); +} + +static void APIENTRY logGetTexEnvfv(GLenum target, GLenum pname, GLfloat *params) +{ + SIG( "glGetTexEnvfv" ); + dllGetTexEnvfv( target, pname, params ); +} + +static void APIENTRY logGetTexEnviv(GLenum target, GLenum pname, GLint *params) +{ + SIG( "glGetTexEnviv" ); + dllGetTexEnviv( target, pname, params ); +} + +static void APIENTRY logGetTexGendv(GLenum coord, GLenum pname, GLdouble *params) +{ + SIG( "glGetTexGendv" ); + dllGetTexGendv( coord, pname, params ); +} + +static void APIENTRY logGetTexGenfv(GLenum coord, GLenum pname, GLfloat *params) +{ + SIG( "glGetTexGenfv" ); + dllGetTexGenfv( coord, pname, params ); +} + +static void APIENTRY logGetTexGeniv(GLenum coord, GLenum pname, GLint *params) +{ + SIG( "glGetTexGeniv" ); + dllGetTexGeniv( coord, pname, params ); +} + +static void APIENTRY logGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, void *pixels) +{ + SIG( "glGetTexImage" ); + dllGetTexImage( target, level, format, type, pixels ); +} +static void APIENTRY logGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params ) +{ + SIG( "glGetTexLevelParameterfv" ); + dllGetTexLevelParameterfv( target, level, pname, params ); +} + +static void APIENTRY logGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) +{ + SIG( "glGetTexLevelParameteriv" ); + dllGetTexLevelParameteriv( target, level, pname, params ); +} + +static void APIENTRY logGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) +{ + SIG( "glGetTexParameterfv" ); + dllGetTexParameterfv( target, pname, params ); +} + +static void APIENTRY logGetTexParameteriv(GLenum target, GLenum pname, GLint *params) +{ + SIG( "glGetTexParameteriv" ); + dllGetTexParameteriv( target, pname, params ); +} + +static void APIENTRY logHint(GLenum target, GLenum mode) +{ + fprintf( log_fp, "glHint( 0x%x, 0x%x )\n", target, mode ); + dllHint( target, mode ); +} + +static void APIENTRY logIndexMask(GLuint mask) +{ + SIG( "glIndexMask" ); + dllIndexMask( mask ); +} + +static void APIENTRY logIndexPointer(GLenum type, GLsizei stride, const void *pointer) +{ + SIG( "glIndexPointer" ); + dllIndexPointer( type, stride, pointer ); +} + +static void APIENTRY logIndexd(GLdouble c) +{ + SIG( "glIndexd" ); + dllIndexd( c ); +} + +static void APIENTRY logIndexdv(const GLdouble *c) +{ + SIG( "glIndexdv" ); + dllIndexdv( c ); +} + +static void APIENTRY logIndexf(GLfloat c) +{ + SIG( "glIndexf" ); + dllIndexf( c ); +} + +static void APIENTRY logIndexfv(const GLfloat *c) +{ + SIG( "glIndexfv" ); + dllIndexfv( c ); +} + +static void APIENTRY logIndexi(GLint c) +{ + SIG( "glIndexi" ); + dllIndexi( c ); +} + +static void APIENTRY logIndexiv(const GLint *c) +{ + SIG( "glIndexiv" ); + dllIndexiv( c ); +} + +static void APIENTRY logIndexs(GLshort c) +{ + SIG( "glIndexs" ); + dllIndexs( c ); +} + +static void APIENTRY logIndexsv(const GLshort *c) +{ + SIG( "glIndexsv" ); + dllIndexsv( c ); +} + +static void APIENTRY logIndexub(GLubyte c) +{ + SIG( "glIndexub" ); + dllIndexub( c ); +} + +static void APIENTRY logIndexubv(const GLubyte *c) +{ + SIG( "glIndexubv" ); + dllIndexubv( c ); +} + +static void APIENTRY logInitNames(void) +{ + SIG( "glInitNames" ); + dllInitNames(); +} + +static void APIENTRY logInterleavedArrays(GLenum format, GLsizei stride, const void *pointer) +{ + SIG( "glInterleavedArrays" ); + dllInterleavedArrays( format, stride, pointer ); +} + +static GLboolean APIENTRY logIsEnabled(GLenum cap) +{ + SIG( "glIsEnabled" ); + return dllIsEnabled( cap ); +} +static GLboolean APIENTRY logIsList(GLuint list) +{ + SIG( "glIsList" ); + return dllIsList( list ); +} +static GLboolean APIENTRY logIsTexture(GLuint texture) +{ + SIG( "glIsTexture" ); + return dllIsTexture( texture ); +} + +static void APIENTRY logLightModelf(GLenum pname, GLfloat param) +{ + SIG( "glLightModelf" ); + dllLightModelf( pname, param ); +} + +static void APIENTRY logLightModelfv(GLenum pname, const GLfloat *params) +{ + SIG( "glLightModelfv" ); + dllLightModelfv( pname, params ); +} + +static void APIENTRY logLightModeli(GLenum pname, GLint param) +{ + SIG( "glLightModeli" ); + dllLightModeli( pname, param ); + +} + +static void APIENTRY logLightModeliv(GLenum pname, const GLint *params) +{ + SIG( "glLightModeliv" ); + dllLightModeliv( pname, params ); +} + +static void APIENTRY logLightf(GLenum light, GLenum pname, GLfloat param) +{ + SIG( "glLightf" ); + dllLightf( light, pname, param ); +} + +static void APIENTRY logLightfv(GLenum light, GLenum pname, const GLfloat *params) +{ + SIG( "glLightfv" ); + dllLightfv( light, pname, params ); +} + +static void APIENTRY logLighti(GLenum light, GLenum pname, GLint param) +{ + SIG( "glLighti" ); + dllLighti( light, pname, param ); +} + +static void APIENTRY logLightiv(GLenum light, GLenum pname, const GLint *params) +{ + SIG( "glLightiv" ); + dllLightiv( light, pname, params ); +} + +static void APIENTRY logLineStipple(GLint factor, GLushort pattern) +{ + SIG( "glLineStipple" ); + dllLineStipple( factor, pattern ); +} + +static void APIENTRY logLineWidth(GLfloat width) +{ + SIG( "glLineWidth" ); + dllLineWidth( width ); +} + +static void APIENTRY logListBase(GLuint base) +{ + SIG( "glListBase" ); + dllListBase( base ); +} + +static void APIENTRY logLoadIdentity(void) +{ + SIG( "glLoadIdentity" ); + dllLoadIdentity(); +} + +static void APIENTRY logLoadMatrixd(const GLdouble *m) +{ + SIG( "glLoadMatrixd" ); + dllLoadMatrixd( m ); +} + +static void APIENTRY logLoadMatrixf(const GLfloat *m) +{ + SIG( "glLoadMatrixf" ); + dllLoadMatrixf( m ); +} + +static void APIENTRY logLoadName(GLuint name) +{ + SIG( "glLoadName" ); + dllLoadName( name ); +} + +static void APIENTRY logLogicOp(GLenum opcode) +{ + SIG( "glLogicOp" ); + dllLogicOp( opcode ); +} + +static void APIENTRY logMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points) +{ + SIG( "glMap1d" ); + dllMap1d( target, u1, u2, stride, order, points ); +} + +static void APIENTRY logMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points) +{ + SIG( "glMap1f" ); + dllMap1f( target, u1, u2, stride, order, points ); +} + +static void APIENTRY logMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points) +{ + SIG( "glMap2d" ); + dllMap2d( target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points ); +} + +static void APIENTRY logMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points) +{ + SIG( "glMap2f" ); + dllMap2f( target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points ); +} + +static void APIENTRY logMapGrid1d(GLint un, GLdouble u1, GLdouble u2) +{ + SIG( "glMapGrid1d" ); + dllMapGrid1d( un, u1, u2 ); +} + +static void APIENTRY logMapGrid1f(GLint un, GLfloat u1, GLfloat u2) +{ + SIG( "glMapGrid1f" ); + dllMapGrid1f( un, u1, u2 ); +} + +static void APIENTRY logMapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2) +{ + SIG( "glMapGrid2d" ); + dllMapGrid2d( un, u1, u2, vn, v1, v2 ); +} +static void APIENTRY logMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) +{ + SIG( "glMapGrid2f" ); + dllMapGrid2f( un, u1, u2, vn, v1, v2 ); +} +static void APIENTRY logMaterialf(GLenum face, GLenum pname, GLfloat param) +{ + SIG( "glMaterialf" ); + dllMaterialf( face, pname, param ); +} +static void APIENTRY logMaterialfv(GLenum face, GLenum pname, const GLfloat *params) +{ + SIG( "glMaterialfv" ); + dllMaterialfv( face, pname, params ); +} + +static void APIENTRY logMateriali(GLenum face, GLenum pname, GLint param) +{ + SIG( "glMateriali" ); + dllMateriali( face, pname, param ); +} + +static void APIENTRY logMaterialiv(GLenum face, GLenum pname, const GLint *params) +{ + SIG( "glMaterialiv" ); + dllMaterialiv( face, pname, params ); +} + +static void APIENTRY logMatrixMode(GLenum mode) +{ + SIG( "glMatrixMode" ); + dllMatrixMode( mode ); +} + +static void APIENTRY logMultMatrixd(const GLdouble *m) +{ + SIG( "glMultMatrixd" ); + dllMultMatrixd( m ); +} + +static void APIENTRY logMultMatrixf(const GLfloat *m) +{ + SIG( "glMultMatrixf" ); + dllMultMatrixf( m ); +} + +static void APIENTRY logNewList(GLuint list, GLenum mode) +{ + SIG( "glNewList" ); + dllNewList( list, mode ); +} + +static void APIENTRY logNormal3b(GLbyte nx, GLbyte ny, GLbyte nz) +{ + SIG ("glNormal3b" ); + dllNormal3b( nx, ny, nz ); +} + +static void APIENTRY logNormal3bv(const GLbyte *v) +{ + SIG( "glNormal3bv" ); + dllNormal3bv( v ); +} + +static void APIENTRY logNormal3d(GLdouble nx, GLdouble ny, GLdouble nz) +{ + SIG( "glNormal3d" ); + dllNormal3d( nx, ny, nz ); +} + +static void APIENTRY logNormal3dv(const GLdouble *v) +{ + SIG( "glNormal3dv" ); + dllNormal3dv( v ); +} + +static void APIENTRY logNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) +{ + SIG( "glNormal3f" ); + dllNormal3f( nx, ny, nz ); +} + +static void APIENTRY logNormal3fv(const GLfloat *v) +{ + SIG( "glNormal3fv" ); + dllNormal3fv( v ); +} +static void APIENTRY logNormal3i(GLint nx, GLint ny, GLint nz) +{ + SIG( "glNormal3i" ); + dllNormal3i( nx, ny, nz ); +} +static void APIENTRY logNormal3iv(const GLint *v) +{ + SIG( "glNormal3iv" ); + dllNormal3iv( v ); +} +static void APIENTRY logNormal3s(GLshort nx, GLshort ny, GLshort nz) +{ + SIG( "glNormal3s" ); + dllNormal3s( nx, ny, nz ); +} +static void APIENTRY logNormal3sv(const GLshort *v) +{ + SIG( "glNormal3sv" ); + dllNormal3sv( v ); +} +static void APIENTRY logNormalPointer(GLenum type, GLsizei stride, const void *pointer) +{ + SIG( "glNormalPointer" ); + dllNormalPointer( type, stride, pointer ); +} +static void APIENTRY logOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) +{ + SIG( "glOrtho" ); + dllOrtho( left, right, bottom, top, zNear, zFar ); +} + +static void APIENTRY logPassThrough(GLfloat token) +{ + SIG( "glPassThrough" ); + dllPassThrough( token ); +} + +static void APIENTRY logPixelMapfv(GLenum map, GLsizei mapsize, const GLfloat *values) +{ + SIG( "glPixelMapfv" ); + dllPixelMapfv( map, mapsize, values ); +} + +static void APIENTRY logPixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values) +{ + SIG( "glPixelMapuiv" ); + dllPixelMapuiv( map, mapsize, values ); +} + +static void APIENTRY logPixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values) +{ + SIG( "glPixelMapusv" ); + dllPixelMapusv( map, mapsize, values ); +} +static void APIENTRY logPixelStoref(GLenum pname, GLfloat param) +{ + SIG( "glPixelStoref" ); + dllPixelStoref( pname, param ); +} +static void APIENTRY logPixelStorei(GLenum pname, GLint param) +{ + SIG( "glPixelStorei" ); + dllPixelStorei( pname, param ); +} +static void APIENTRY logPixelTransferf(GLenum pname, GLfloat param) +{ + SIG( "glPixelTransferf" ); + dllPixelTransferf( pname, param ); +} + +static void APIENTRY logPixelTransferi(GLenum pname, GLint param) +{ + SIG( "glPixelTransferi" ); + dllPixelTransferi( pname, param ); +} + +static void APIENTRY logPixelZoom(GLfloat xfactor, GLfloat yfactor) +{ + SIG( "glPixelZoom" ); + dllPixelZoom( xfactor, yfactor ); +} + +static void APIENTRY logPointSize(GLfloat size) +{ + SIG( "glPointSize" ); + dllPointSize( size ); +} + +static void APIENTRY logPolygonMode(GLenum face, GLenum mode) +{ + fprintf( log_fp, "glPolygonMode( 0x%x, 0x%x )\n", face, mode ); + dllPolygonMode( face, mode ); +} + +static void APIENTRY logPolygonOffset(GLfloat factor, GLfloat units) +{ + SIG( "glPolygonOffset" ); + dllPolygonOffset( factor, units ); +} +static void APIENTRY logPolygonStipple(const GLubyte *mask ) +{ + SIG( "glPolygonStipple" ); + dllPolygonStipple( mask ); +} +static void APIENTRY logPopAttrib(void) +{ + SIG( "glPopAttrib" ); + dllPopAttrib(); +} + +static void APIENTRY logPopClientAttrib(void) +{ + SIG( "glPopClientAttrib" ); + dllPopClientAttrib(); +} + +static void APIENTRY logPopMatrix(void) +{ + SIG( "glPopMatrix" ); + dllPopMatrix(); +} + +static void APIENTRY logPopName(void) +{ + SIG( "glPopName" ); + dllPopName(); +} + +static void APIENTRY logPrioritizeTextures(GLsizei n, const GLuint *textures, const GLclampf *priorities) +{ + SIG( "glPrioritizeTextures" ); + dllPrioritizeTextures( n, textures, priorities ); +} + +static void APIENTRY logPushAttrib(GLbitfield mask) +{ + SIG( "glPushAttrib" ); + dllPushAttrib( mask ); +} + +static void APIENTRY logPushClientAttrib(GLbitfield mask) +{ + SIG( "glPushClientAttrib" ); + dllPushClientAttrib( mask ); +} + +static void APIENTRY logPushMatrix(void) +{ + SIG( "glPushMatrix" ); + dllPushMatrix(); +} + +static void APIENTRY logPushName(GLuint name) +{ + SIG( "glPushName" ); + dllPushName( name ); +} + +static void APIENTRY logRasterPos2d(GLdouble x, GLdouble y) +{ + SIG ("glRasterPot2d" ); + dllRasterPos2d( x, y ); +} + +static void APIENTRY logRasterPos2dv(const GLdouble *v) +{ + SIG( "glRasterPos2dv" ); + dllRasterPos2dv( v ); +} + +static void APIENTRY logRasterPos2f(GLfloat x, GLfloat y) +{ + SIG( "glRasterPos2f" ); + dllRasterPos2f( x, y ); +} +static void APIENTRY logRasterPos2fv(const GLfloat *v) +{ + SIG( "glRasterPos2dv" ); + dllRasterPos2fv( v ); +} +static void APIENTRY logRasterPos2i(GLint x, GLint y) +{ + SIG( "glRasterPos2if" ); + dllRasterPos2i( x, y ); +} +static void APIENTRY logRasterPos2iv(const GLint *v) +{ + SIG( "glRasterPos2iv" ); + dllRasterPos2iv( v ); +} +static void APIENTRY logRasterPos2s(GLshort x, GLshort y) +{ + SIG( "glRasterPos2s" ); + dllRasterPos2s( x, y ); +} +static void APIENTRY logRasterPos2sv(const GLshort *v) +{ + SIG( "glRasterPos2sv" ); + dllRasterPos2sv( v ); +} +static void APIENTRY logRasterPos3d(GLdouble x, GLdouble y, GLdouble z) +{ + SIG( "glRasterPos3d" ); + dllRasterPos3d( x, y, z ); +} +static void APIENTRY logRasterPos3dv(const GLdouble *v) +{ + SIG( "glRasterPos3dv" ); + dllRasterPos3dv( v ); +} +static void APIENTRY logRasterPos3f(GLfloat x, GLfloat y, GLfloat z) +{ + SIG( "glRasterPos3f" ); + dllRasterPos3f( x, y, z ); +} +static void APIENTRY logRasterPos3fv(const GLfloat *v) +{ + SIG( "glRasterPos3fv" ); + dllRasterPos3fv( v ); +} +static void APIENTRY logRasterPos3i(GLint x, GLint y, GLint z) +{ + SIG( "glRasterPos3i" ); + dllRasterPos3i( x, y, z ); +} +static void APIENTRY logRasterPos3iv(const GLint *v) +{ + SIG( "glRasterPos3iv" ); + dllRasterPos3iv( v ); +} +static void APIENTRY logRasterPos3s(GLshort x, GLshort y, GLshort z) +{ + SIG( "glRasterPos3s" ); + dllRasterPos3s( x, y, z ); +} +static void APIENTRY logRasterPos3sv(const GLshort *v) +{ + SIG( "glRasterPos3sv" ); + dllRasterPos3sv( v ); +} +static void APIENTRY logRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + SIG( "glRasterPos4d" ); + dllRasterPos4d( x, y, z, w ); +} +static void APIENTRY logRasterPos4dv(const GLdouble *v) +{ + SIG( "glRasterPos4dv" ); + dllRasterPos4dv( v ); +} +static void APIENTRY logRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + SIG( "glRasterPos4f" ); + dllRasterPos4f( x, y, z, w ); +} +static void APIENTRY logRasterPos4fv(const GLfloat *v) +{ + SIG( "glRasterPos4fv" ); + dllRasterPos4fv( v ); +} +static void APIENTRY logRasterPos4i(GLint x, GLint y, GLint z, GLint w) +{ + SIG( "glRasterPos4i" ); + dllRasterPos4i( x, y, z, w ); +} +static void APIENTRY logRasterPos4iv(const GLint *v) +{ + SIG( "glRasterPos4iv" ); + dllRasterPos4iv( v ); +} +static void APIENTRY logRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w) +{ + SIG( "glRasterPos4s" ); + dllRasterPos4s( x, y, z, w ); +} +static void APIENTRY logRasterPos4sv(const GLshort *v) +{ + SIG( "glRasterPos4sv" ); + dllRasterPos4sv( v ); +} +static void APIENTRY logReadBuffer(GLenum mode) +{ + SIG( "glReadBuffer" ); + dllReadBuffer( mode ); +} +static void APIENTRY logReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) +{ + SIG( "glReadPixels" ); + dllReadPixels( x, y, width, height, format, type, pixels ); +} + +static void APIENTRY logRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) +{ + SIG( "glRectd" ); + dllRectd( x1, y1, x2, y2 ); +} + +static void APIENTRY logRectdv(const GLdouble *v1, const GLdouble *v2) +{ + SIG( "glRectdv" ); + dllRectdv( v1, v2 ); +} + +static void APIENTRY logRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) +{ + SIG( "glRectf" ); + dllRectf( x1, y1, x2, y2 ); +} + +static void APIENTRY logRectfv(const GLfloat *v1, const GLfloat *v2) +{ + SIG( "glRectfv" ); + dllRectfv( v1, v2 ); +} +static void APIENTRY logRecti(GLint x1, GLint y1, GLint x2, GLint y2) +{ + SIG( "glRecti" ); + dllRecti( x1, y1, x2, y2 ); +} +static void APIENTRY logRectiv(const GLint *v1, const GLint *v2) +{ + SIG( "glRectiv" ); + dllRectiv( v1, v2 ); +} +static void APIENTRY logRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2) +{ + SIG( "glRects" ); + dllRects( x1, y1, x2, y2 ); +} +static void APIENTRY logRectsv(const GLshort *v1, const GLshort *v2) +{ + SIG( "glRectsv" ); + dllRectsv( v1, v2 ); +} +static GLint APIENTRY logRenderMode(GLenum mode) +{ + SIG( "glRenderMode" ); + return dllRenderMode( mode ); +} +static void APIENTRY logRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) +{ + SIG( "glRotated" ); + dllRotated( angle, x, y, z ); +} + +static void APIENTRY logRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + SIG( "glRotatef" ); + dllRotatef( angle, x, y, z ); +} + +static void APIENTRY logScaled(GLdouble x, GLdouble y, GLdouble z) +{ + SIG( "glScaled" ); + dllScaled( x, y, z ); +} + +static void APIENTRY logScalef(GLfloat x, GLfloat y, GLfloat z) +{ + SIG( "glScalef" ); + dllScalef( x, y, z ); +} + +static void APIENTRY logScissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + SIG( "glScissor" ); + dllScissor( x, y, width, height ); +} + +static void APIENTRY logSelectBuffer(GLsizei size, GLuint *buffer) +{ + SIG( "glSelectBuffer" ); + dllSelectBuffer( size, buffer ); +} + +static void APIENTRY logShadeModel(GLenum mode) +{ + SIG( "glShadeModel" ); + dllShadeModel( mode ); +} + +static void APIENTRY logStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + SIG( "glStencilFunc" ); + dllStencilFunc( func, ref, mask ); +} + +static void APIENTRY logStencilMask(GLuint mask) +{ + SIG( "glStencilMask" ); + dllStencilMask( mask ); +} + +static void APIENTRY logStencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + SIG( "glStencilOp" ); + dllStencilOp( fail, zfail, zpass ); +} + +static void APIENTRY logTexCoord1d(GLdouble s) +{ + SIG( "glTexCoord1d" ); + dllTexCoord1d( s ); +} + +static void APIENTRY logTexCoord1dv(const GLdouble *v) +{ + SIG( "glTexCoord1dv" ); + dllTexCoord1dv( v ); +} + +static void APIENTRY logTexCoord1f(GLfloat s) +{ + SIG( "glTexCoord1f" ); + dllTexCoord1f( s ); +} +static void APIENTRY logTexCoord1fv(const GLfloat *v) +{ + SIG( "glTexCoord1fv" ); + dllTexCoord1fv( v ); +} +static void APIENTRY logTexCoord1i(GLint s) +{ + SIG( "glTexCoord1i" ); + dllTexCoord1i( s ); +} +static void APIENTRY logTexCoord1iv(const GLint *v) +{ + SIG( "glTexCoord1iv" ); + dllTexCoord1iv( v ); +} +static void APIENTRY logTexCoord1s(GLshort s) +{ + SIG( "glTexCoord1s" ); + dllTexCoord1s( s ); +} +static void APIENTRY logTexCoord1sv(const GLshort *v) +{ + SIG( "glTexCoord1sv" ); + dllTexCoord1sv( v ); +} +static void APIENTRY logTexCoord2d(GLdouble s, GLdouble t) +{ + SIG( "glTexCoord2d" ); + dllTexCoord2d( s, t ); +} + +static void APIENTRY logTexCoord2dv(const GLdouble *v) +{ + SIG( "glTexCoord2dv" ); + dllTexCoord2dv( v ); +} +static void APIENTRY logTexCoord2f(GLfloat s, GLfloat t) +{ + SIG( "glTexCoord2f" ); + dllTexCoord2f( s, t ); +} +static void APIENTRY logTexCoord2fv(const GLfloat *v) +{ + SIG( "glTexCoord2fv" ); + dllTexCoord2fv( v ); +} +static void APIENTRY logTexCoord2i(GLint s, GLint t) +{ + SIG( "glTexCoord2i" ); + dllTexCoord2i( s, t ); +} +static void APIENTRY logTexCoord2iv(const GLint *v) +{ + SIG( "glTexCoord2iv" ); + dllTexCoord2iv( v ); +} +static void APIENTRY logTexCoord2s(GLshort s, GLshort t) +{ + SIG( "glTexCoord2s" ); + dllTexCoord2s( s, t ); +} +static void APIENTRY logTexCoord2sv(const GLshort *v) +{ + SIG( "glTexCoord2sv" ); + dllTexCoord2sv( v ); +} +static void APIENTRY logTexCoord3d(GLdouble s, GLdouble t, GLdouble r) +{ + SIG( "glTexCoord3d" ); + dllTexCoord3d( s, t, r ); +} +static void APIENTRY logTexCoord3dv(const GLdouble *v) +{ + SIG( "glTexCoord3dv" ); + dllTexCoord3dv( v ); +} +static void APIENTRY logTexCoord3f(GLfloat s, GLfloat t, GLfloat r) +{ + SIG( "glTexCoord3f" ); + dllTexCoord3f( s, t, r ); +} +static void APIENTRY logTexCoord3fv(const GLfloat *v) +{ + SIG( "glTexCoord3fv" ); + dllTexCoord3fv( v ); +} +static void APIENTRY logTexCoord3i(GLint s, GLint t, GLint r) +{ + SIG( "glTexCoord3i" ); + dllTexCoord3i( s, t, r ); +} +static void APIENTRY logTexCoord3iv(const GLint *v) +{ + SIG( "glTexCoord3iv" ); + dllTexCoord3iv( v ); +} +static void APIENTRY logTexCoord3s(GLshort s, GLshort t, GLshort r) +{ + SIG( "glTexCoord3s" ); + dllTexCoord3s( s, t, r ); +} +static void APIENTRY logTexCoord3sv(const GLshort *v) +{ + SIG( "glTexCoord3sv" ); + dllTexCoord3sv( v ); +} +static void APIENTRY logTexCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q) +{ + SIG( "glTexCoord4d" ); + dllTexCoord4d( s, t, r, q ); +} +static void APIENTRY logTexCoord4dv(const GLdouble *v) +{ + SIG( "glTexCoord4dv" ); + dllTexCoord4dv( v ); +} +static void APIENTRY logTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + SIG( "glTexCoord4f" ); + dllTexCoord4f( s, t, r, q ); +} +static void APIENTRY logTexCoord4fv(const GLfloat *v) +{ + SIG( "glTexCoord4fv" ); + dllTexCoord4fv( v ); +} +static void APIENTRY logTexCoord4i(GLint s, GLint t, GLint r, GLint q) +{ + SIG( "glTexCoord4i" ); + dllTexCoord4i( s, t, r, q ); +} +static void APIENTRY logTexCoord4iv(const GLint *v) +{ + SIG( "glTexCoord4iv" ); + dllTexCoord4iv( v ); +} +static void APIENTRY logTexCoord4s(GLshort s, GLshort t, GLshort r, GLshort q) +{ + SIG( "glTexCoord4s" ); + dllTexCoord4s( s, t, r, q ); +} +static void APIENTRY logTexCoord4sv(const GLshort *v) +{ + SIG( "glTexCoord4sv" ); + dllTexCoord4sv( v ); +} +static void APIENTRY logTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) +{ + SIG( "glTexCoordPointer" ); + dllTexCoordPointer( size, type, stride, pointer ); +} + +static void APIENTRY logTexEnvf(GLenum target, GLenum pname, GLfloat param) +{ + fprintf( log_fp, "glTexEnvf( 0x%x, 0x%x, %f )\n", target, pname, param ); + dllTexEnvf( target, pname, param ); +} + +static void APIENTRY logTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) +{ + SIG( "glTexEnvfv" ); + dllTexEnvfv( target, pname, params ); +} + +static void APIENTRY logTexEnvi(GLenum target, GLenum pname, GLint param) +{ + fprintf( log_fp, "glTexEnvi( 0x%x, 0x%x, 0x%x )\n", target, pname, param ); + dllTexEnvi( target, pname, param ); +} +static void APIENTRY logTexEnviv(GLenum target, GLenum pname, const GLint *params) +{ + SIG( "glTexEnviv" ); + dllTexEnviv( target, pname, params ); +} + +static void APIENTRY logTexGend(GLenum coord, GLenum pname, GLdouble param) +{ + SIG( "glTexGend" ); + dllTexGend( coord, pname, param ); +} + +static void APIENTRY logTexGendv(GLenum coord, GLenum pname, const GLdouble *params) +{ + SIG( "glTexGendv" ); + dllTexGendv( coord, pname, params ); +} + +static void APIENTRY logTexGenf(GLenum coord, GLenum pname, GLfloat param) +{ + SIG( "glTexGenf" ); + dllTexGenf( coord, pname, param ); +} +static void APIENTRY logTexGenfv(GLenum coord, GLenum pname, const GLfloat *params) +{ + SIG( "glTexGenfv" ); + dllTexGenfv( coord, pname, params ); +} +static void APIENTRY logTexGeni(GLenum coord, GLenum pname, GLint param) +{ + SIG( "glTexGeni" ); + dllTexGeni( coord, pname, param ); +} +static void APIENTRY logTexGeniv(GLenum coord, GLenum pname, const GLint *params) +{ + SIG( "glTexGeniv" ); + dllTexGeniv( coord, pname, params ); +} +static void APIENTRY logTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels) +{ + SIG( "glTexImage1D" ); + dllTexImage1D( target, level, internalformat, width, border, format, type, pixels ); +} +static void APIENTRY logTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) +{ + SIG( "glTexImage2D" ); + dllTexImage2D( target, level, internalformat, width, height, border, format, type, pixels ); +} + +static void APIENTRY logTexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + fprintf( log_fp, "glTexParameterf( 0x%x, 0x%x, %f )\n", target, pname, param ); + dllTexParameterf( target, pname, param ); +} + +static void APIENTRY logTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) +{ + SIG( "glTexParameterfv" ); + dllTexParameterfv( target, pname, params ); +} +static void APIENTRY logTexParameteri(GLenum target, GLenum pname, GLint param) +{ + fprintf( log_fp, "glTexParameteri( 0x%x, 0x%x, 0x%x )\n", target, pname, param ); + dllTexParameteri( target, pname, param ); +} +static void APIENTRY logTexParameteriv(GLenum target, GLenum pname, const GLint *params) +{ + SIG( "glTexParameteriv" ); + dllTexParameteriv( target, pname, params ); +} +static void APIENTRY logTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels) +{ + SIG( "glTexSubImage1D" ); + dllTexSubImage1D( target, level, xoffset, width, format, type, pixels ); +} +static void APIENTRY logTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) +{ + SIG( "glTexSubImage2D" ); + dllTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, pixels ); +} +static void APIENTRY logTranslated(GLdouble x, GLdouble y, GLdouble z) +{ + SIG( "glTranslated" ); + dllTranslated( x, y, z ); +} + +static void APIENTRY logTranslatef(GLfloat x, GLfloat y, GLfloat z) +{ + SIG( "glTranslatef" ); + dllTranslatef( x, y, z ); +} + +static void APIENTRY logVertex2d(GLdouble x, GLdouble y) +{ + SIG( "glVertex2d" ); + dllVertex2d( x, y ); +} + +static void APIENTRY logVertex2dv(const GLdouble *v) +{ + SIG( "glVertex2dv" ); + dllVertex2dv( v ); +} +static void APIENTRY logVertex2f(GLfloat x, GLfloat y) +{ + SIG( "glVertex2f" ); + dllVertex2f( x, y ); +} +static void APIENTRY logVertex2fv(const GLfloat *v) +{ + SIG( "glVertex2fv" ); + dllVertex2fv( v ); +} +static void APIENTRY logVertex2i(GLint x, GLint y) +{ + SIG( "glVertex2i" ); + dllVertex2i( x, y ); +} +static void APIENTRY logVertex2iv(const GLint *v) +{ + SIG( "glVertex2iv" ); + dllVertex2iv( v ); +} +static void APIENTRY logVertex2s(GLshort x, GLshort y) +{ + SIG( "glVertex2s" ); + dllVertex2s( x, y ); +} +static void APIENTRY logVertex2sv(const GLshort *v) +{ + SIG( "glVertex2sv" ); + dllVertex2sv( v ); +} +static void APIENTRY logVertex3d(GLdouble x, GLdouble y, GLdouble z) +{ + SIG( "glVertex3d" ); + dllVertex3d( x, y, z ); +} +static void APIENTRY logVertex3dv(const GLdouble *v) +{ + SIG( "glVertex3dv" ); + dllVertex3dv( v ); +} +static void APIENTRY logVertex3f(GLfloat x, GLfloat y, GLfloat z) +{ + SIG( "glVertex3f" ); + dllVertex3f( x, y, z ); +} +static void APIENTRY logVertex3fv(const GLfloat *v) +{ + SIG( "glVertex3fv" ); + dllVertex3fv( v ); +} +static void APIENTRY logVertex3i(GLint x, GLint y, GLint z) +{ + SIG( "glVertex3i" ); + dllVertex3i( x, y, z ); +} +static void APIENTRY logVertex3iv(const GLint *v) +{ + SIG( "glVertex3iv" ); + dllVertex3iv( v ); +} +static void APIENTRY logVertex3s(GLshort x, GLshort y, GLshort z) +{ + SIG( "glVertex3s" ); + dllVertex3s( x, y, z ); +} +static void APIENTRY logVertex3sv(const GLshort *v) +{ + SIG( "glVertex3sv" ); + dllVertex3sv( v ); +} +static void APIENTRY logVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + SIG( "glVertex4d" ); + dllVertex4d( x, y, z, w ); +} +static void APIENTRY logVertex4dv(const GLdouble *v) +{ + SIG( "glVertex4dv" ); + dllVertex4dv( v ); +} +static void APIENTRY logVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + SIG( "glVertex4f" ); + dllVertex4f( x, y, z, w ); +} +static void APIENTRY logVertex4fv(const GLfloat *v) +{ + SIG( "glVertex4fv" ); + dllVertex4fv( v ); +} +static void APIENTRY logVertex4i(GLint x, GLint y, GLint z, GLint w) +{ + SIG( "glVertex4i" ); + dllVertex4i( x, y, z, w ); +} +static void APIENTRY logVertex4iv(const GLint *v) +{ + SIG( "glVertex4iv" ); + dllVertex4iv( v ); +} +static void APIENTRY logVertex4s(GLshort x, GLshort y, GLshort z, GLshort w) +{ + SIG( "glVertex4s" ); + dllVertex4s( x, y, z, w ); +} +static void APIENTRY logVertex4sv(const GLshort *v) +{ + SIG( "glVertex4sv" ); + dllVertex4sv( v ); +} +static void APIENTRY logVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) +{ + SIG( "glVertexPointer" ); + dllVertexPointer( size, type, stride, pointer ); +} +static void APIENTRY logViewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + SIG( "glViewport" ); + dllViewport( x, y, width, height ); +} + +/* +** QGL_Shutdown +** +** Unloads the specified DLL then nulls out all the proc pointers. +*/ +void QGL_Shutdown( void ) +{ + qglAccum = NULL; + qglAlphaFunc = NULL; + qglAreTexturesResident = NULL; + qglArrayElement = NULL; + qglBegin = NULL; + qglBindTexture = NULL; + qglBitmap = NULL; + qglBlendFunc = NULL; + qglCallList = NULL; + qglCallLists = NULL; + qglClear = NULL; + qglClearAccum = NULL; + qglClearColor = NULL; + qglClearDepth = NULL; + qglClearIndex = NULL; + qglClearStencil = NULL; + qglClipPlane = NULL; + qglColor3b = NULL; + qglColor3bv = NULL; + qglColor3d = NULL; + qglColor3dv = NULL; + qglColor3f = NULL; + qglColor3fv = NULL; + qglColor3i = NULL; + qglColor3iv = NULL; + qglColor3s = NULL; + qglColor3sv = NULL; + qglColor3ub = NULL; + qglColor3ubv = NULL; + qglColor3ui = NULL; + qglColor3uiv = NULL; + qglColor3us = NULL; + qglColor3usv = NULL; + qglColor4b = NULL; + qglColor4bv = NULL; + qglColor4d = NULL; + qglColor4dv = NULL; + qglColor4f = NULL; + qglColor4fv = NULL; + qglColor4i = NULL; + qglColor4iv = NULL; + qglColor4s = NULL; + qglColor4sv = NULL; + qglColor4ub = NULL; + qglColor4ubv = NULL; + qglColor4ui = NULL; + qglColor4uiv = NULL; + qglColor4us = NULL; + qglColor4usv = NULL; + qglColorMask = NULL; + qglColorMaterial = NULL; + qglColorPointer = NULL; + qglCopyPixels = NULL; + qglCopyTexImage1D = NULL; + qglCopyTexImage2D = NULL; + qglCopyTexSubImage1D = NULL; + qglCopyTexSubImage2D = NULL; + qglCullFace = NULL; + qglDeleteLists = NULL; + qglDeleteTextures = NULL; + qglDepthFunc = NULL; + qglDepthMask = NULL; + qglDepthRange = NULL; + qglDisable = NULL; + qglDisableClientState = NULL; + qglDrawArrays = NULL; + qglDrawBuffer = NULL; + qglDrawElements = NULL; + qglDrawPixels = NULL; + qglEdgeFlag = NULL; + qglEdgeFlagPointer = NULL; + qglEdgeFlagv = NULL; + qglEnable = NULL; + qglEnableClientState = NULL; + qglEnd = NULL; + qglEndList = NULL; + qglEvalCoord1d = NULL; + qglEvalCoord1dv = NULL; + qglEvalCoord1f = NULL; + qglEvalCoord1fv = NULL; + qglEvalCoord2d = NULL; + qglEvalCoord2dv = NULL; + qglEvalCoord2f = NULL; + qglEvalCoord2fv = NULL; + qglEvalMesh1 = NULL; + qglEvalMesh2 = NULL; + qglEvalPoint1 = NULL; + qglEvalPoint2 = NULL; + qglFeedbackBuffer = NULL; + qglFinish = NULL; + qglFlush = NULL; + qglFogf = NULL; + qglFogfv = NULL; + qglFogi = NULL; + qglFogiv = NULL; + qglFrontFace = NULL; + qglFrustum = NULL; + qglGenLists = NULL; + qglGenTextures = NULL; + qglGetBooleanv = NULL; + qglGetClipPlane = NULL; + qglGetDoublev = NULL; + qglGetError = NULL; + qglGetFloatv = NULL; + qglGetIntegerv = NULL; + qglGetLightfv = NULL; + qglGetLightiv = NULL; + qglGetMapdv = NULL; + qglGetMapfv = NULL; + qglGetMapiv = NULL; + qglGetMaterialfv = NULL; + qglGetMaterialiv = NULL; + qglGetPixelMapfv = NULL; + qglGetPixelMapuiv = NULL; + qglGetPixelMapusv = NULL; + qglGetPointerv = NULL; + qglGetPolygonStipple = NULL; + qglGetString = NULL; + qglGetTexEnvfv = NULL; + qglGetTexEnviv = NULL; + qglGetTexGendv = NULL; + qglGetTexGenfv = NULL; + qglGetTexGeniv = NULL; + qglGetTexImage = NULL; + qglGetTexLevelParameterfv = NULL; + qglGetTexLevelParameteriv = NULL; + qglGetTexParameterfv = NULL; + qglGetTexParameteriv = NULL; + qglHint = NULL; + qglIndexMask = NULL; + qglIndexPointer = NULL; + qglIndexd = NULL; + qglIndexdv = NULL; + qglIndexf = NULL; + qglIndexfv = NULL; + qglIndexi = NULL; + qglIndexiv = NULL; + qglIndexs = NULL; + qglIndexsv = NULL; + qglIndexub = NULL; + qglIndexubv = NULL; + qglInitNames = NULL; + qglInterleavedArrays = NULL; + qglIsEnabled = NULL; + qglIsList = NULL; + qglIsTexture = NULL; + qglLightModelf = NULL; + qglLightModelfv = NULL; + qglLightModeli = NULL; + qglLightModeliv = NULL; + qglLightf = NULL; + qglLightfv = NULL; + qglLighti = NULL; + qglLightiv = NULL; + qglLineStipple = NULL; + qglLineWidth = NULL; + qglListBase = NULL; + qglLoadIdentity = NULL; + qglLoadMatrixd = NULL; + qglLoadMatrixf = NULL; + qglLoadName = NULL; + qglLogicOp = NULL; + qglMap1d = NULL; + qglMap1f = NULL; + qglMap2d = NULL; + qglMap2f = NULL; + qglMapGrid1d = NULL; + qglMapGrid1f = NULL; + qglMapGrid2d = NULL; + qglMapGrid2f = NULL; + qglMaterialf = NULL; + qglMaterialfv = NULL; + qglMateriali = NULL; + qglMaterialiv = NULL; + qglMatrixMode = NULL; + qglMultMatrixd = NULL; + qglMultMatrixf = NULL; + qglNewList = NULL; + qglNormal3b = NULL; + qglNormal3bv = NULL; + qglNormal3d = NULL; + qglNormal3dv = NULL; + qglNormal3f = NULL; + qglNormal3fv = NULL; + qglNormal3i = NULL; + qglNormal3iv = NULL; + qglNormal3s = NULL; + qglNormal3sv = NULL; + qglNormalPointer = NULL; + qglOrtho = NULL; + qglPassThrough = NULL; + qglPixelMapfv = NULL; + qglPixelMapuiv = NULL; + qglPixelMapusv = NULL; + qglPixelStoref = NULL; + qglPixelStorei = NULL; + qglPixelTransferf = NULL; + qglPixelTransferi = NULL; + qglPixelZoom = NULL; + qglPointSize = NULL; + qglPolygonMode = NULL; + qglPolygonOffset = NULL; + qglPolygonStipple = NULL; + qglPopAttrib = NULL; + qglPopClientAttrib = NULL; + qglPopMatrix = NULL; + qglPopName = NULL; + qglPrioritizeTextures = NULL; + qglPushAttrib = NULL; + qglPushClientAttrib = NULL; + qglPushMatrix = NULL; + qglPushName = NULL; + qglRasterPos2d = NULL; + qglRasterPos2dv = NULL; + qglRasterPos2f = NULL; + qglRasterPos2fv = NULL; + qglRasterPos2i = NULL; + qglRasterPos2iv = NULL; + qglRasterPos2s = NULL; + qglRasterPos2sv = NULL; + qglRasterPos3d = NULL; + qglRasterPos3dv = NULL; + qglRasterPos3f = NULL; + qglRasterPos3fv = NULL; + qglRasterPos3i = NULL; + qglRasterPos3iv = NULL; + qglRasterPos3s = NULL; + qglRasterPos3sv = NULL; + qglRasterPos4d = NULL; + qglRasterPos4dv = NULL; + qglRasterPos4f = NULL; + qglRasterPos4fv = NULL; + qglRasterPos4i = NULL; + qglRasterPos4iv = NULL; + qglRasterPos4s = NULL; + qglRasterPos4sv = NULL; + qglReadBuffer = NULL; + qglReadPixels = NULL; + qglRectd = NULL; + qglRectdv = NULL; + qglRectf = NULL; + qglRectfv = NULL; + qglRecti = NULL; + qglRectiv = NULL; + qglRects = NULL; + qglRectsv = NULL; + qglRenderMode = NULL; + qglRotated = NULL; + qglRotatef = NULL; + qglScaled = NULL; + qglScalef = NULL; + qglScissor = NULL; + qglSelectBuffer = NULL; + qglShadeModel = NULL; + qglStencilFunc = NULL; + qglStencilMask = NULL; + qglStencilOp = NULL; + qglTexCoord1d = NULL; + qglTexCoord1dv = NULL; + qglTexCoord1f = NULL; + qglTexCoord1fv = NULL; + qglTexCoord1i = NULL; + qglTexCoord1iv = NULL; + qglTexCoord1s = NULL; + qglTexCoord1sv = NULL; + qglTexCoord2d = NULL; + qglTexCoord2dv = NULL; + qglTexCoord2f = NULL; + qglTexCoord2fv = NULL; + qglTexCoord2i = NULL; + qglTexCoord2iv = NULL; + qglTexCoord2s = NULL; + qglTexCoord2sv = NULL; + qglTexCoord3d = NULL; + qglTexCoord3dv = NULL; + qglTexCoord3f = NULL; + qglTexCoord3fv = NULL; + qglTexCoord3i = NULL; + qglTexCoord3iv = NULL; + qglTexCoord3s = NULL; + qglTexCoord3sv = NULL; + qglTexCoord4d = NULL; + qglTexCoord4dv = NULL; + qglTexCoord4f = NULL; + qglTexCoord4fv = NULL; + qglTexCoord4i = NULL; + qglTexCoord4iv = NULL; + qglTexCoord4s = NULL; + qglTexCoord4sv = NULL; + qglTexCoordPointer = NULL; + qglTexEnvf = NULL; + qglTexEnvfv = NULL; + qglTexEnvi = NULL; + qglTexEnviv = NULL; + qglTexGend = NULL; + qglTexGendv = NULL; + qglTexGenf = NULL; + qglTexGenfv = NULL; + qglTexGeni = NULL; + qglTexGeniv = NULL; + qglTexImage1D = NULL; + qglTexImage2D = NULL; + qglTexParameterf = NULL; + qglTexParameterfv = NULL; + qglTexParameteri = NULL; + qglTexParameteriv = NULL; + qglTexSubImage1D = NULL; + qglTexSubImage2D = NULL; + qglTranslated = NULL; + qglTranslatef = NULL; + qglVertex2d = NULL; + qglVertex2dv = NULL; + qglVertex2f = NULL; + qglVertex2fv = NULL; + qglVertex2i = NULL; + qglVertex2iv = NULL; + qglVertex2s = NULL; + qglVertex2sv = NULL; + qglVertex3d = NULL; + qglVertex3dv = NULL; + qglVertex3f = NULL; + qglVertex3fv = NULL; + qglVertex3i = NULL; + qglVertex3iv = NULL; + qglVertex3s = NULL; + qglVertex3sv = NULL; + qglVertex4d = NULL; + qglVertex4dv = NULL; + qglVertex4f = NULL; + qglVertex4fv = NULL; + qglVertex4i = NULL; + qglVertex4iv = NULL; + qglVertex4s = NULL; + qglVertex4sv = NULL; + qglVertexPointer = NULL; + qglViewport = NULL; + + qglColorTableEXT = NULL; + +} + +/* +** QGL_Init +** +** This is responsible for binding our qgl function pointers to +** the appropriate GL stuff. In Windows this means doing a +** LoadLibrary and a bunch of calls to GetProcAddress. On other +** operating systems we need to do the right thing, whatever that +** might be. +** +*/ +qboolean QGL_Init( const char *dllname ) +{ + gl_config.allow_cds = true; + + qglAccum = dllAccum = glAccum; + qglAlphaFunc = dllAlphaFunc = glAlphaFunc; + qglAreTexturesResident = dllAreTexturesResident = glAreTexturesResident; + qglArrayElement = dllArrayElement = glArrayElement; + qglBegin = dllBegin = glBegin; + qglBindTexture = dllBindTexture = glBindTexture; + qglBitmap = dllBitmap = glBitmap; + qglBlendFunc = dllBlendFunc = glBlendFunc; + qglCallList = dllCallList = glCallList; + qglCallLists = dllCallLists = glCallLists; + qglClear = dllClear = glClear; + qglClearAccum = dllClearAccum = glClearAccum; + qglClearColor = dllClearColor = glClearColor; + qglClearDepth = dllClearDepth = glClearDepth; + qglClearIndex = dllClearIndex = glClearIndex; + qglClearStencil = dllClearStencil = glClearStencil; + qglClipPlane = dllClipPlane = glClipPlane; + qglColor3b = dllColor3b = glColor3b; + qglColor3bv = dllColor3bv = glColor3bv; + qglColor3d = dllColor3d = glColor3d; + qglColor3dv = dllColor3dv = glColor3dv; + qglColor3f = dllColor3f = glColor3f; + qglColor3fv = dllColor3fv = glColor3fv; + qglColor3i = dllColor3i = glColor3i; + qglColor3iv = dllColor3iv = glColor3iv; + qglColor3s = dllColor3s = glColor3s; + qglColor3sv = dllColor3sv = glColor3sv; + qglColor3ub = dllColor3ub = glColor3ub; + qglColor3ubv = dllColor3ubv = glColor3ubv; + qglColor3ui = dllColor3ui = glColor3ui; + qglColor3uiv = dllColor3uiv = glColor3uiv; + qglColor3us = dllColor3us = glColor3us; + qglColor3usv = dllColor3usv = glColor3usv; + qglColor4b = dllColor4b = glColor4b; + qglColor4bv = dllColor4bv = glColor4bv; + qglColor4d = dllColor4d = glColor4d; + qglColor4dv = dllColor4dv = glColor4dv; + qglColor4f = dllColor4f = glColor4f; + qglColor4fv = dllColor4fv = glColor4fv; + qglColor4i = dllColor4i = glColor4i; + qglColor4iv = dllColor4iv = glColor4iv; + qglColor4s = dllColor4s = glColor4s; + qglColor4sv = dllColor4sv = glColor4sv; + qglColor4ub = dllColor4ub = glColor4ub; + qglColor4ubv = dllColor4ubv = glColor4ubv; + qglColor4ui = dllColor4ui = glColor4ui; + qglColor4uiv = dllColor4uiv = glColor4uiv; + qglColor4us = dllColor4us = glColor4us; + qglColor4usv = dllColor4usv = glColor4usv; + qglColorMask = dllColorMask = glColorMask; + qglColorMaterial = dllColorMaterial = glColorMaterial; + qglColorPointer = dllColorPointer = glColorPointer; + qglCopyPixels = dllCopyPixels = glCopyPixels; + qglCopyTexImage1D = dllCopyTexImage1D = glCopyTexImage1D; + qglCopyTexImage2D = dllCopyTexImage2D = glCopyTexImage2D; + qglCopyTexSubImage1D = dllCopyTexSubImage1D = glCopyTexSubImage1D; + qglCopyTexSubImage2D = dllCopyTexSubImage2D = glCopyTexSubImage2D; + qglCullFace = dllCullFace = glCullFace; + qglDeleteLists = dllDeleteLists = glDeleteLists; + qglDeleteTextures = dllDeleteTextures = glDeleteTextures; + qglDepthFunc = dllDepthFunc = glDepthFunc; + qglDepthMask = dllDepthMask = glDepthMask; + qglDepthRange = dllDepthRange = glDepthRange; + qglDisable = dllDisable = glDisable; + qglDisableClientState = dllDisableClientState = glDisableClientState; + qglDrawArrays = dllDrawArrays = glDrawArrays; + qglDrawBuffer = dllDrawBuffer = glDrawBuffer; + qglDrawElements = dllDrawElements = glDrawElements; + qglDrawPixels = dllDrawPixels = glDrawPixels; + qglEdgeFlag = dllEdgeFlag = glEdgeFlag; + qglEdgeFlagPointer = dllEdgeFlagPointer = glEdgeFlagPointer; + qglEdgeFlagv = dllEdgeFlagv = glEdgeFlagv; + qglEnable = dllEnable = glEnable; + qglEnableClientState = dllEnableClientState = glEnableClientState; + qglEnd = dllEnd = glEnd; + qglEndList = dllEndList = glEndList; + qglEvalCoord1d = dllEvalCoord1d = glEvalCoord1d; + qglEvalCoord1dv = dllEvalCoord1dv = glEvalCoord1dv; + qglEvalCoord1f = dllEvalCoord1f = glEvalCoord1f; + qglEvalCoord1fv = dllEvalCoord1fv = glEvalCoord1fv; + qglEvalCoord2d = dllEvalCoord2d = glEvalCoord2d; + qglEvalCoord2dv = dllEvalCoord2dv = glEvalCoord2dv; + qglEvalCoord2f = dllEvalCoord2f = glEvalCoord2f; + qglEvalCoord2fv = dllEvalCoord2fv = glEvalCoord2fv; + qglEvalMesh1 = dllEvalMesh1 = glEvalMesh1; + qglEvalMesh2 = dllEvalMesh2 = glEvalMesh2; + qglEvalPoint1 = dllEvalPoint1 = glEvalPoint1; + qglEvalPoint2 = dllEvalPoint2 = glEvalPoint2; + qglFeedbackBuffer = dllFeedbackBuffer = glFeedbackBuffer; + qglFinish = dllFinish = glFinish; + qglFlush = dllFlush = glFlush; + qglFogf = dllFogf = glFogf; + qglFogfv = dllFogfv = glFogfv; + qglFogi = dllFogi = glFogi; + qglFogiv = dllFogiv = glFogiv; + qglFrontFace = dllFrontFace = glFrontFace; + qglFrustum = dllFrustum = glFrustum; + qglGenLists = dllGenLists = glGenLists; + qglGenTextures = dllGenTextures = glGenTextures; + qglGetBooleanv = dllGetBooleanv = glGetBooleanv; + qglGetClipPlane = dllGetClipPlane = glGetClipPlane; + qglGetDoublev = dllGetDoublev = glGetDoublev; + qglGetError = dllGetError = glGetError; + qglGetFloatv = dllGetFloatv = glGetFloatv; + qglGetIntegerv = dllGetIntegerv = glGetIntegerv; + qglGetLightfv = dllGetLightfv = glGetLightfv; + qglGetLightiv = dllGetLightiv = glGetLightiv; + qglGetMapdv = dllGetMapdv = glGetMapdv; + qglGetMapfv = dllGetMapfv = glGetMapfv; + qglGetMapiv = dllGetMapiv = glGetMapiv; + qglGetMaterialfv = dllGetMaterialfv = glGetMaterialfv; + qglGetMaterialiv = dllGetMaterialiv = glGetMaterialiv; + qglGetPixelMapfv = dllGetPixelMapfv = glGetPixelMapfv; + qglGetPixelMapuiv = dllGetPixelMapuiv = glGetPixelMapuiv; + qglGetPixelMapusv = dllGetPixelMapusv = glGetPixelMapusv; + qglGetPointerv = dllGetPointerv = glGetPointerv; + qglGetPolygonStipple = dllGetPolygonStipple = glGetPolygonStipple; + qglGetString = dllGetString = glGetString; + qglGetTexEnvfv = dllGetTexEnvfv = glGetTexEnvfv; + qglGetTexEnviv = dllGetTexEnviv = glGetTexEnviv; + qglGetTexGendv = dllGetTexGendv = glGetTexGendv; + qglGetTexGenfv = dllGetTexGenfv = glGetTexGenfv; + qglGetTexGeniv = dllGetTexGeniv = glGetTexGeniv; + qglGetTexImage = dllGetTexImage = glGetTexImage; +// qglGetTexLevelParameterfv = dllGetTexLevelParameterfv = glGetLevelParameterfv; +// qglGetTexLevelParameteriv = dllGetTexLevelParameteriv = glGetLevelParameteriv; + qglGetTexParameterfv = dllGetTexParameterfv = glGetTexParameterfv; + qglGetTexParameteriv = dllGetTexParameteriv = glGetTexParameteriv; + qglHint = dllHint = glHint; + qglIndexMask = dllIndexMask = glIndexMask; + qglIndexPointer = dllIndexPointer = glIndexPointer; + qglIndexd = dllIndexd = glIndexd; + qglIndexdv = dllIndexdv = glIndexdv; + qglIndexf = dllIndexf = glIndexf; + qglIndexfv = dllIndexfv = glIndexfv; + qglIndexi = dllIndexi = glIndexi; + qglIndexiv = dllIndexiv = glIndexiv; + qglIndexs = dllIndexs = glIndexs; + qglIndexsv = dllIndexsv = glIndexsv; + qglIndexub = dllIndexub = glIndexub; + qglIndexubv = dllIndexubv = glIndexubv; + qglInitNames = dllInitNames = glInitNames; + qglInterleavedArrays = dllInterleavedArrays = glInterleavedArrays; + qglIsEnabled = dllIsEnabled = glIsEnabled; + qglIsList = dllIsList = glIsList; + qglIsTexture = dllIsTexture = glIsTexture; + qglLightModelf = dllLightModelf = glLightModelf; + qglLightModelfv = dllLightModelfv = glLightModelfv; + qglLightModeli = dllLightModeli = glLightModeli; + qglLightModeliv = dllLightModeliv = glLightModeliv; + qglLightf = dllLightf = glLightf; + qglLightfv = dllLightfv = glLightfv; + qglLighti = dllLighti = glLighti; + qglLightiv = dllLightiv = glLightiv; + qglLineStipple = dllLineStipple = glLineStipple; + qglLineWidth = dllLineWidth = glLineWidth; + qglListBase = dllListBase = glListBase; + qglLoadIdentity = dllLoadIdentity = glLoadIdentity; + qglLoadMatrixd = dllLoadMatrixd = glLoadMatrixd; + qglLoadMatrixf = dllLoadMatrixf = glLoadMatrixf; + qglLoadName = dllLoadName = glLoadName; + qglLogicOp = dllLogicOp = glLogicOp; + qglMap1d = dllMap1d = glMap1d; + qglMap1f = dllMap1f = glMap1f; + qglMap2d = dllMap2d = glMap2d; + qglMap2f = dllMap2f = glMap2f; + qglMapGrid1d = dllMapGrid1d = glMapGrid1d; + qglMapGrid1f = dllMapGrid1f = glMapGrid1f; + qglMapGrid2d = dllMapGrid2d = glMapGrid2d; + qglMapGrid2f = dllMapGrid2f = glMapGrid2f; + qglMaterialf = dllMaterialf = glMaterialf; + qglMaterialfv = dllMaterialfv = glMaterialfv; + qglMateriali = dllMateriali = glMateriali; + qglMaterialiv = dllMaterialiv = glMaterialiv; + qglMatrixMode = dllMatrixMode = glMatrixMode; + qglMultMatrixd = dllMultMatrixd = glMultMatrixd; + qglMultMatrixf = dllMultMatrixf = glMultMatrixf; + qglNewList = dllNewList = glNewList; + qglNormal3b = dllNormal3b = glNormal3b; + qglNormal3bv = dllNormal3bv = glNormal3bv; + qglNormal3d = dllNormal3d = glNormal3d; + qglNormal3dv = dllNormal3dv = glNormal3dv; + qglNormal3f = dllNormal3f = glNormal3f; + qglNormal3fv = dllNormal3fv = glNormal3fv; + qglNormal3i = dllNormal3i = glNormal3i; + qglNormal3iv = dllNormal3iv = glNormal3iv; + qglNormal3s = dllNormal3s = glNormal3s; + qglNormal3sv = dllNormal3sv = glNormal3sv; + qglNormalPointer = dllNormalPointer = glNormalPointer; + qglOrtho = dllOrtho = glOrtho; + qglPassThrough = dllPassThrough = glPassThrough; + qglPixelMapfv = dllPixelMapfv = glPixelMapfv; + qglPixelMapuiv = dllPixelMapuiv = glPixelMapuiv; + qglPixelMapusv = dllPixelMapusv = glPixelMapusv; + qglPixelStoref = dllPixelStoref = glPixelStoref; + qglPixelStorei = dllPixelStorei = glPixelStorei; + qglPixelTransferf = dllPixelTransferf = glPixelTransferf; + qglPixelTransferi = dllPixelTransferi = glPixelTransferi; + qglPixelZoom = dllPixelZoom = glPixelZoom; + qglPointSize = dllPointSize = glPointSize; + qglPolygonMode = dllPolygonMode = glPolygonMode; + qglPolygonOffset = dllPolygonOffset = glPolygonOffset; + qglPolygonStipple = dllPolygonStipple = glPolygonStipple; + qglPopAttrib = dllPopAttrib = glPopAttrib; + qglPopClientAttrib = dllPopClientAttrib = glPopClientAttrib; + qglPopMatrix = dllPopMatrix = glPopMatrix; + qglPopName = dllPopName = glPopName; + qglPrioritizeTextures = dllPrioritizeTextures = glPrioritizeTextures; + qglPushAttrib = dllPushAttrib = glPushAttrib; + qglPushClientAttrib = dllPushClientAttrib = glPushClientAttrib; + qglPushMatrix = dllPushMatrix = glPushMatrix; + qglPushName = dllPushName = glPushName; + qglRasterPos2d = dllRasterPos2d = glRasterPos2d; + qglRasterPos2dv = dllRasterPos2dv = glRasterPos2dv; + qglRasterPos2f = dllRasterPos2f = glRasterPos2f; + qglRasterPos2fv = dllRasterPos2fv = glRasterPos2fv; + qglRasterPos2i = dllRasterPos2i = glRasterPos2i; + qglRasterPos2iv = dllRasterPos2iv = glRasterPos2iv; + qglRasterPos2s = dllRasterPos2s = glRasterPos2s; + qglRasterPos2sv = dllRasterPos2sv = glRasterPos2sv; + qglRasterPos3d = dllRasterPos3d = glRasterPos3d; + qglRasterPos3dv = dllRasterPos3dv = glRasterPos3dv; + qglRasterPos3f = dllRasterPos3f = glRasterPos3f; + qglRasterPos3fv = dllRasterPos3fv = glRasterPos3fv; + qglRasterPos3i = dllRasterPos3i = glRasterPos3i; + qglRasterPos3iv = dllRasterPos3iv = glRasterPos3iv; + qglRasterPos3s = dllRasterPos3s = glRasterPos3s; + qglRasterPos3sv = dllRasterPos3sv = glRasterPos3sv; + qglRasterPos4d = dllRasterPos4d = glRasterPos4d; + qglRasterPos4dv = dllRasterPos4dv = glRasterPos4dv; + qglRasterPos4f = dllRasterPos4f = glRasterPos4f; + qglRasterPos4fv = dllRasterPos4fv = glRasterPos4fv; + qglRasterPos4i = dllRasterPos4i = glRasterPos4i; + qglRasterPos4iv = dllRasterPos4iv = glRasterPos4iv; + qglRasterPos4s = dllRasterPos4s = glRasterPos4s; + qglRasterPos4sv = dllRasterPos4sv = glRasterPos4sv; + qglReadBuffer = dllReadBuffer = glReadBuffer; + qglReadPixels = dllReadPixels = glReadPixels; + qglRectd = dllRectd = glRectd; + qglRectdv = dllRectdv = glRectdv; + qglRectf = dllRectf = glRectf; + qglRectfv = dllRectfv = glRectfv; + qglRecti = dllRecti = glRecti; + qglRectiv = dllRectiv = glRectiv; + qglRects = dllRects = glRects; + qglRectsv = dllRectsv = glRectsv; + qglRenderMode = dllRenderMode = glRenderMode; + qglRotated = dllRotated = glRotated; + qglRotatef = dllRotatef = glRotatef; + qglScaled = dllScaled = glScaled; + qglScalef = dllScalef = glScalef; + qglScissor = dllScissor = glScissor; + qglSelectBuffer = dllSelectBuffer = glSelectBuffer; + qglShadeModel = dllShadeModel = glShadeModel; + qglStencilFunc = dllStencilFunc = glStencilFunc; + qglStencilMask = dllStencilMask = glStencilMask; + qglStencilOp = dllStencilOp = glStencilOp; + qglTexCoord1d = dllTexCoord1d = glTexCoord1d; + qglTexCoord1dv = dllTexCoord1dv = glTexCoord1dv; + qglTexCoord1f = dllTexCoord1f = glTexCoord1f; + qglTexCoord1fv = dllTexCoord1fv = glTexCoord1fv; + qglTexCoord1i = dllTexCoord1i = glTexCoord1i; + qglTexCoord1iv = dllTexCoord1iv = glTexCoord1iv; + qglTexCoord1s = dllTexCoord1s = glTexCoord1s; + qglTexCoord1sv = dllTexCoord1sv = glTexCoord1sv; + qglTexCoord2d = dllTexCoord2d = glTexCoord2d; + qglTexCoord2dv = dllTexCoord2dv = glTexCoord2dv; + qglTexCoord2f = dllTexCoord2f = glTexCoord2f; + qglTexCoord2fv = dllTexCoord2fv = glTexCoord2fv; + qglTexCoord2i = dllTexCoord2i = glTexCoord2i; + qglTexCoord2iv = dllTexCoord2iv = glTexCoord2iv; + qglTexCoord2s = dllTexCoord2s = glTexCoord2s; + qglTexCoord2sv = dllTexCoord2sv = glTexCoord2sv; + qglTexCoord3d = dllTexCoord3d = glTexCoord3d; + qglTexCoord3dv = dllTexCoord3dv = glTexCoord3dv; + qglTexCoord3f = dllTexCoord3f = glTexCoord3f; + qglTexCoord3fv = dllTexCoord3fv = glTexCoord3fv; + qglTexCoord3i = dllTexCoord3i = glTexCoord3i; + qglTexCoord3iv = dllTexCoord3iv = glTexCoord3iv; + qglTexCoord3s = dllTexCoord3s = glTexCoord3s; + qglTexCoord3sv = dllTexCoord3sv = glTexCoord3sv; + qglTexCoord4d = dllTexCoord4d = glTexCoord4d; + qglTexCoord4dv = dllTexCoord4dv = glTexCoord4dv; + qglTexCoord4f = dllTexCoord4f = glTexCoord4f; + qglTexCoord4fv = dllTexCoord4fv = glTexCoord4fv; + qglTexCoord4i = dllTexCoord4i = glTexCoord4i; + qglTexCoord4iv = dllTexCoord4iv = glTexCoord4iv; + qglTexCoord4s = dllTexCoord4s = glTexCoord4s; + qglTexCoord4sv = dllTexCoord4sv = glTexCoord4sv; + qglTexCoordPointer = dllTexCoordPointer = glTexCoordPointer; + qglTexEnvf = dllTexEnvf = glTexEnvf; + qglTexEnvfv = dllTexEnvfv = glTexEnvfv; + qglTexEnvi = dllTexEnvi = glTexEnvi; + qglTexEnviv = dllTexEnviv = glTexEnviv; + qglTexGend = dllTexGend = glTexGend; + qglTexGendv = dllTexGendv = glTexGendv; + qglTexGenf = dllTexGenf = glTexGenf; + qglTexGenfv = dllTexGenfv = glTexGenfv; + qglTexGeni = dllTexGeni = glTexGeni; + qglTexGeniv = dllTexGeniv = glTexGeniv; + qglTexImage1D = dllTexImage1D = glTexImage1D; + qglTexImage2D = dllTexImage2D = glTexImage2D; + qglTexParameterf = dllTexParameterf = glTexParameterf; + qglTexParameterfv = dllTexParameterfv = glTexParameterfv; + qglTexParameteri = dllTexParameteri = glTexParameteri; + qglTexParameteriv = dllTexParameteriv = glTexParameteriv; + qglTexSubImage1D = dllTexSubImage1D = glTexSubImage1D; + qglTexSubImage2D = dllTexSubImage2D = glTexSubImage2D; + qglTranslated = dllTranslated = glTranslated; + qglTranslatef = dllTranslatef = glTranslatef; + qglVertex2d = dllVertex2d = glVertex2d; + qglVertex2dv = dllVertex2dv = glVertex2dv; + qglVertex2f = dllVertex2f = glVertex2f; + qglVertex2fv = dllVertex2fv = glVertex2fv; + qglVertex2i = dllVertex2i = glVertex2i; + qglVertex2iv = dllVertex2iv = glVertex2iv; + qglVertex2s = dllVertex2s = glVertex2s; + qglVertex2sv = dllVertex2sv = glVertex2sv; + qglVertex3d = dllVertex3d = glVertex3d; + qglVertex3dv = dllVertex3dv = glVertex3dv; + qglVertex3f = dllVertex3f = glVertex3f; + qglVertex3fv = dllVertex3fv = glVertex3fv; + qglVertex3i = dllVertex3i = glVertex3i; + qglVertex3iv = dllVertex3iv = glVertex3iv; + qglVertex3s = dllVertex3s = glVertex3s; + qglVertex3sv = dllVertex3sv = glVertex3sv; + qglVertex4d = dllVertex4d = glVertex4d; + qglVertex4dv = dllVertex4dv = glVertex4dv; + qglVertex4f = dllVertex4f = glVertex4f; + qglVertex4fv = dllVertex4fv = glVertex4fv; + qglVertex4i = dllVertex4i = glVertex4i; + qglVertex4iv = dllVertex4iv = glVertex4iv; + qglVertex4s = dllVertex4s = glVertex4s; + qglVertex4sv = dllVertex4sv = glVertex4sv; + qglVertexPointer = dllVertexPointer = glVertexPointer; + qglViewport = dllViewport = glViewport; + + qglPointParameterfEXT = 0; + qglPointParameterfvEXT = 0; + qglColorTableEXT = glColorTableSGI; + qglColorTableEXT = 0; + qglSelectTextureSGIS = 0; + qglMTexCoord2fSGIS = 0; + + return true; +} + +void GLimp_EnableLogging( qboolean enable ) +{ + if ( enable ) + { + if ( !log_fp ) + { + struct tm *newtime; + time_t aclock; + char buffer[1024]; + + time( &aclock ); + newtime = localtime( &aclock ); + + asctime( newtime ); + + sprintf( buffer, "%s/gl.log", ri.FS_Gamedir() ); + log_fp = fopen( buffer, "wt"); + + fprintf( log_fp, "%s\n", asctime( newtime ) ); + } + + qglAccum = logAccum; + qglAlphaFunc = logAlphaFunc; + qglAreTexturesResident = logAreTexturesResident; + qglArrayElement = logArrayElement; + qglBegin = logBegin; + qglBindTexture = logBindTexture; + qglBitmap = logBitmap; + qglBlendFunc = logBlendFunc; + qglCallList = logCallList; + qglCallLists = logCallLists; + qglClear = logClear; + qglClearAccum = logClearAccum; + qglClearColor = logClearColor; + qglClearDepth = logClearDepth; + qglClearIndex = logClearIndex; + qglClearStencil = logClearStencil; + qglClipPlane = logClipPlane; + qglColor3b = logColor3b; + qglColor3bv = logColor3bv; + qglColor3d = logColor3d; + qglColor3dv = logColor3dv; + qglColor3f = logColor3f; + qglColor3fv = logColor3fv; + qglColor3i = logColor3i; + qglColor3iv = logColor3iv; + qglColor3s = logColor3s; + qglColor3sv = logColor3sv; + qglColor3ub = logColor3ub; + qglColor3ubv = logColor3ubv; + qglColor3ui = logColor3ui; + qglColor3uiv = logColor3uiv; + qglColor3us = logColor3us; + qglColor3usv = logColor3usv; + qglColor4b = logColor4b; + qglColor4bv = logColor4bv; + qglColor4d = logColor4d; + qglColor4dv = logColor4dv; + qglColor4f = logColor4f; + qglColor4fv = logColor4fv; + qglColor4i = logColor4i; + qglColor4iv = logColor4iv; + qglColor4s = logColor4s; + qglColor4sv = logColor4sv; + qglColor4ub = logColor4ub; + qglColor4ubv = logColor4ubv; + qglColor4ui = logColor4ui; + qglColor4uiv = logColor4uiv; + qglColor4us = logColor4us; + qglColor4usv = logColor4usv; + qglColorMask = logColorMask; + qglColorMaterial = logColorMaterial; + qglColorPointer = logColorPointer; + qglCopyPixels = logCopyPixels; + qglCopyTexImage1D = logCopyTexImage1D; + qglCopyTexImage2D = logCopyTexImage2D; + qglCopyTexSubImage1D = logCopyTexSubImage1D; + qglCopyTexSubImage2D = logCopyTexSubImage2D; + qglCullFace = logCullFace; + qglDeleteLists = logDeleteLists ; + qglDeleteTextures = logDeleteTextures ; + qglDepthFunc = logDepthFunc ; + qglDepthMask = logDepthMask ; + qglDepthRange = logDepthRange ; + qglDisable = logDisable ; + qglDisableClientState = logDisableClientState ; + qglDrawArrays = logDrawArrays ; + qglDrawBuffer = logDrawBuffer ; + qglDrawElements = logDrawElements ; + qglDrawPixels = logDrawPixels ; + qglEdgeFlag = logEdgeFlag ; + qglEdgeFlagPointer = logEdgeFlagPointer ; + qglEdgeFlagv = logEdgeFlagv ; + qglEnable = logEnable ; + qglEnableClientState = logEnableClientState ; + qglEnd = logEnd ; + qglEndList = logEndList ; + qglEvalCoord1d = logEvalCoord1d ; + qglEvalCoord1dv = logEvalCoord1dv ; + qglEvalCoord1f = logEvalCoord1f ; + qglEvalCoord1fv = logEvalCoord1fv ; + qglEvalCoord2d = logEvalCoord2d ; + qglEvalCoord2dv = logEvalCoord2dv ; + qglEvalCoord2f = logEvalCoord2f ; + qglEvalCoord2fv = logEvalCoord2fv ; + qglEvalMesh1 = logEvalMesh1 ; + qglEvalMesh2 = logEvalMesh2 ; + qglEvalPoint1 = logEvalPoint1 ; + qglEvalPoint2 = logEvalPoint2 ; + qglFeedbackBuffer = logFeedbackBuffer ; + qglFinish = logFinish ; + qglFlush = logFlush ; + qglFogf = logFogf ; + qglFogfv = logFogfv ; + qglFogi = logFogi ; + qglFogiv = logFogiv ; + qglFrontFace = logFrontFace ; + qglFrustum = logFrustum ; + qglGenLists = logGenLists ; + qglGenTextures = logGenTextures ; + qglGetBooleanv = logGetBooleanv ; + qglGetClipPlane = logGetClipPlane ; + qglGetDoublev = logGetDoublev ; + qglGetError = logGetError ; + qglGetFloatv = logGetFloatv ; + qglGetIntegerv = logGetIntegerv ; + qglGetLightfv = logGetLightfv ; + qglGetLightiv = logGetLightiv ; + qglGetMapdv = logGetMapdv ; + qglGetMapfv = logGetMapfv ; + qglGetMapiv = logGetMapiv ; + qglGetMaterialfv = logGetMaterialfv ; + qglGetMaterialiv = logGetMaterialiv ; + qglGetPixelMapfv = logGetPixelMapfv ; + qglGetPixelMapuiv = logGetPixelMapuiv ; + qglGetPixelMapusv = logGetPixelMapusv ; + qglGetPointerv = logGetPointerv ; + qglGetPolygonStipple = logGetPolygonStipple ; + qglGetString = logGetString ; + qglGetTexEnvfv = logGetTexEnvfv ; + qglGetTexEnviv = logGetTexEnviv ; + qglGetTexGendv = logGetTexGendv ; + qglGetTexGenfv = logGetTexGenfv ; + qglGetTexGeniv = logGetTexGeniv ; + qglGetTexImage = logGetTexImage ; +// qglGetTexLevelParameterfv = logGetTexLevelParameterfv ; +// qglGetTexLevelParameteriv = logGetTexLevelParameteriv ; + qglGetTexParameterfv = logGetTexParameterfv ; + qglGetTexParameteriv = logGetTexParameteriv ; + qglHint = logHint ; + qglIndexMask = logIndexMask ; + qglIndexPointer = logIndexPointer ; + qglIndexd = logIndexd ; + qglIndexdv = logIndexdv ; + qglIndexf = logIndexf ; + qglIndexfv = logIndexfv ; + qglIndexi = logIndexi ; + qglIndexiv = logIndexiv ; + qglIndexs = logIndexs ; + qglIndexsv = logIndexsv ; + qglIndexub = logIndexub ; + qglIndexubv = logIndexubv ; + qglInitNames = logInitNames ; + qglInterleavedArrays = logInterleavedArrays ; + qglIsEnabled = logIsEnabled ; + qglIsList = logIsList ; + qglIsTexture = logIsTexture ; + qglLightModelf = logLightModelf ; + qglLightModelfv = logLightModelfv ; + qglLightModeli = logLightModeli ; + qglLightModeliv = logLightModeliv ; + qglLightf = logLightf ; + qglLightfv = logLightfv ; + qglLighti = logLighti ; + qglLightiv = logLightiv ; + qglLineStipple = logLineStipple ; + qglLineWidth = logLineWidth ; + qglListBase = logListBase ; + qglLoadIdentity = logLoadIdentity ; + qglLoadMatrixd = logLoadMatrixd ; + qglLoadMatrixf = logLoadMatrixf ; + qglLoadName = logLoadName ; + qglLogicOp = logLogicOp ; + qglMap1d = logMap1d ; + qglMap1f = logMap1f ; + qglMap2d = logMap2d ; + qglMap2f = logMap2f ; + qglMapGrid1d = logMapGrid1d ; + qglMapGrid1f = logMapGrid1f ; + qglMapGrid2d = logMapGrid2d ; + qglMapGrid2f = logMapGrid2f ; + qglMaterialf = logMaterialf ; + qglMaterialfv = logMaterialfv ; + qglMateriali = logMateriali ; + qglMaterialiv = logMaterialiv ; + qglMatrixMode = logMatrixMode ; + qglMultMatrixd = logMultMatrixd ; + qglMultMatrixf = logMultMatrixf ; + qglNewList = logNewList ; + qglNormal3b = logNormal3b ; + qglNormal3bv = logNormal3bv ; + qglNormal3d = logNormal3d ; + qglNormal3dv = logNormal3dv ; + qglNormal3f = logNormal3f ; + qglNormal3fv = logNormal3fv ; + qglNormal3i = logNormal3i ; + qglNormal3iv = logNormal3iv ; + qglNormal3s = logNormal3s ; + qglNormal3sv = logNormal3sv ; + qglNormalPointer = logNormalPointer ; + qglOrtho = logOrtho ; + qglPassThrough = logPassThrough ; + qglPixelMapfv = logPixelMapfv ; + qglPixelMapuiv = logPixelMapuiv ; + qglPixelMapusv = logPixelMapusv ; + qglPixelStoref = logPixelStoref ; + qglPixelStorei = logPixelStorei ; + qglPixelTransferf = logPixelTransferf ; + qglPixelTransferi = logPixelTransferi ; + qglPixelZoom = logPixelZoom ; + qglPointSize = logPointSize ; + qglPolygonMode = logPolygonMode ; + qglPolygonOffset = logPolygonOffset ; + qglPolygonStipple = logPolygonStipple ; + qglPopAttrib = logPopAttrib ; + qglPopClientAttrib = logPopClientAttrib ; + qglPopMatrix = logPopMatrix ; + qglPopName = logPopName ; + qglPrioritizeTextures = logPrioritizeTextures ; + qglPushAttrib = logPushAttrib ; + qglPushClientAttrib = logPushClientAttrib ; + qglPushMatrix = logPushMatrix ; + qglPushName = logPushName ; + qglRasterPos2d = logRasterPos2d ; + qglRasterPos2dv = logRasterPos2dv ; + qglRasterPos2f = logRasterPos2f ; + qglRasterPos2fv = logRasterPos2fv ; + qglRasterPos2i = logRasterPos2i ; + qglRasterPos2iv = logRasterPos2iv ; + qglRasterPos2s = logRasterPos2s ; + qglRasterPos2sv = logRasterPos2sv ; + qglRasterPos3d = logRasterPos3d ; + qglRasterPos3dv = logRasterPos3dv ; + qglRasterPos3f = logRasterPos3f ; + qglRasterPos3fv = logRasterPos3fv ; + qglRasterPos3i = logRasterPos3i ; + qglRasterPos3iv = logRasterPos3iv ; + qglRasterPos3s = logRasterPos3s ; + qglRasterPos3sv = logRasterPos3sv ; + qglRasterPos4d = logRasterPos4d ; + qglRasterPos4dv = logRasterPos4dv ; + qglRasterPos4f = logRasterPos4f ; + qglRasterPos4fv = logRasterPos4fv ; + qglRasterPos4i = logRasterPos4i ; + qglRasterPos4iv = logRasterPos4iv ; + qglRasterPos4s = logRasterPos4s ; + qglRasterPos4sv = logRasterPos4sv ; + qglReadBuffer = logReadBuffer ; + qglReadPixels = logReadPixels ; + qglRectd = logRectd ; + qglRectdv = logRectdv ; + qglRectf = logRectf ; + qglRectfv = logRectfv ; + qglRecti = logRecti ; + qglRectiv = logRectiv ; + qglRects = logRects ; + qglRectsv = logRectsv ; + qglRenderMode = logRenderMode ; + qglRotated = logRotated ; + qglRotatef = logRotatef ; + qglScaled = logScaled ; + qglScalef = logScalef ; + qglScissor = logScissor ; + qglSelectBuffer = logSelectBuffer ; + qglShadeModel = logShadeModel ; + qglStencilFunc = logStencilFunc ; + qglStencilMask = logStencilMask ; + qglStencilOp = logStencilOp ; + qglTexCoord1d = logTexCoord1d ; + qglTexCoord1dv = logTexCoord1dv ; + qglTexCoord1f = logTexCoord1f ; + qglTexCoord1fv = logTexCoord1fv ; + qglTexCoord1i = logTexCoord1i ; + qglTexCoord1iv = logTexCoord1iv ; + qglTexCoord1s = logTexCoord1s ; + qglTexCoord1sv = logTexCoord1sv ; + qglTexCoord2d = logTexCoord2d ; + qglTexCoord2dv = logTexCoord2dv ; + qglTexCoord2f = logTexCoord2f ; + qglTexCoord2fv = logTexCoord2fv ; + qglTexCoord2i = logTexCoord2i ; + qglTexCoord2iv = logTexCoord2iv ; + qglTexCoord2s = logTexCoord2s ; + qglTexCoord2sv = logTexCoord2sv ; + qglTexCoord3d = logTexCoord3d ; + qglTexCoord3dv = logTexCoord3dv ; + qglTexCoord3f = logTexCoord3f ; + qglTexCoord3fv = logTexCoord3fv ; + qglTexCoord3i = logTexCoord3i ; + qglTexCoord3iv = logTexCoord3iv ; + qglTexCoord3s = logTexCoord3s ; + qglTexCoord3sv = logTexCoord3sv ; + qglTexCoord4d = logTexCoord4d ; + qglTexCoord4dv = logTexCoord4dv ; + qglTexCoord4f = logTexCoord4f ; + qglTexCoord4fv = logTexCoord4fv ; + qglTexCoord4i = logTexCoord4i ; + qglTexCoord4iv = logTexCoord4iv ; + qglTexCoord4s = logTexCoord4s ; + qglTexCoord4sv = logTexCoord4sv ; + qglTexCoordPointer = logTexCoordPointer ; + qglTexEnvf = logTexEnvf ; + qglTexEnvfv = logTexEnvfv ; + qglTexEnvi = logTexEnvi ; + qglTexEnviv = logTexEnviv ; + qglTexGend = logTexGend ; + qglTexGendv = logTexGendv ; + qglTexGenf = logTexGenf ; + qglTexGenfv = logTexGenfv ; + qglTexGeni = logTexGeni ; + qglTexGeniv = logTexGeniv ; + qglTexImage1D = logTexImage1D ; + qglTexImage2D = logTexImage2D ; + qglTexParameterf = logTexParameterf ; + qglTexParameterfv = logTexParameterfv ; + qglTexParameteri = logTexParameteri ; + qglTexParameteriv = logTexParameteriv ; + qglTexSubImage1D = logTexSubImage1D ; + qglTexSubImage2D = logTexSubImage2D ; + qglTranslated = logTranslated ; + qglTranslatef = logTranslatef ; + qglVertex2d = logVertex2d ; + qglVertex2dv = logVertex2dv ; + qglVertex2f = logVertex2f ; + qglVertex2fv = logVertex2fv ; + qglVertex2i = logVertex2i ; + qglVertex2iv = logVertex2iv ; + qglVertex2s = logVertex2s ; + qglVertex2sv = logVertex2sv ; + qglVertex3d = logVertex3d ; + qglVertex3dv = logVertex3dv ; + qglVertex3f = logVertex3f ; + qglVertex3fv = logVertex3fv ; + qglVertex3i = logVertex3i ; + qglVertex3iv = logVertex3iv ; + qglVertex3s = logVertex3s ; + qglVertex3sv = logVertex3sv ; + qglVertex4d = logVertex4d ; + qglVertex4dv = logVertex4dv ; + qglVertex4f = logVertex4f ; + qglVertex4fv = logVertex4fv ; + qglVertex4i = logVertex4i ; + qglVertex4iv = logVertex4iv ; + qglVertex4s = logVertex4s ; + qglVertex4sv = logVertex4sv ; + qglVertexPointer = logVertexPointer ; + qglViewport = logViewport ; + } + else + { + qglAccum = dllAccum; + qglAlphaFunc = dllAlphaFunc; + qglAreTexturesResident = dllAreTexturesResident; + qglArrayElement = dllArrayElement; + qglBegin = dllBegin; + qglBindTexture = dllBindTexture; + qglBitmap = dllBitmap; + qglBlendFunc = dllBlendFunc; + qglCallList = dllCallList; + qglCallLists = dllCallLists; + qglClear = dllClear; + qglClearAccum = dllClearAccum; + qglClearColor = dllClearColor; + qglClearDepth = dllClearDepth; + qglClearIndex = dllClearIndex; + qglClearStencil = dllClearStencil; + qglClipPlane = dllClipPlane; + qglColor3b = dllColor3b; + qglColor3bv = dllColor3bv; + qglColor3d = dllColor3d; + qglColor3dv = dllColor3dv; + qglColor3f = dllColor3f; + qglColor3fv = dllColor3fv; + qglColor3i = dllColor3i; + qglColor3iv = dllColor3iv; + qglColor3s = dllColor3s; + qglColor3sv = dllColor3sv; + qglColor3ub = dllColor3ub; + qglColor3ubv = dllColor3ubv; + qglColor3ui = dllColor3ui; + qglColor3uiv = dllColor3uiv; + qglColor3us = dllColor3us; + qglColor3usv = dllColor3usv; + qglColor4b = dllColor4b; + qglColor4bv = dllColor4bv; + qglColor4d = dllColor4d; + qglColor4dv = dllColor4dv; + qglColor4f = dllColor4f; + qglColor4fv = dllColor4fv; + qglColor4i = dllColor4i; + qglColor4iv = dllColor4iv; + qglColor4s = dllColor4s; + qglColor4sv = dllColor4sv; + qglColor4ub = dllColor4ub; + qglColor4ubv = dllColor4ubv; + qglColor4ui = dllColor4ui; + qglColor4uiv = dllColor4uiv; + qglColor4us = dllColor4us; + qglColor4usv = dllColor4usv; + qglColorMask = dllColorMask; + qglColorMaterial = dllColorMaterial; + qglColorPointer = dllColorPointer; + qglCopyPixels = dllCopyPixels; + qglCopyTexImage1D = dllCopyTexImage1D; + qglCopyTexImage2D = dllCopyTexImage2D; + qglCopyTexSubImage1D = dllCopyTexSubImage1D; + qglCopyTexSubImage2D = dllCopyTexSubImage2D; + qglCullFace = dllCullFace; + qglDeleteLists = dllDeleteLists ; + qglDeleteTextures = dllDeleteTextures ; + qglDepthFunc = dllDepthFunc ; + qglDepthMask = dllDepthMask ; + qglDepthRange = dllDepthRange ; + qglDisable = dllDisable ; + qglDisableClientState = dllDisableClientState ; + qglDrawArrays = dllDrawArrays ; + qglDrawBuffer = dllDrawBuffer ; + qglDrawElements = dllDrawElements ; + qglDrawPixels = dllDrawPixels ; + qglEdgeFlag = dllEdgeFlag ; + qglEdgeFlagPointer = dllEdgeFlagPointer ; + qglEdgeFlagv = dllEdgeFlagv ; + qglEnable = dllEnable ; + qglEnableClientState = dllEnableClientState ; + qglEnd = dllEnd ; + qglEndList = dllEndList ; + qglEvalCoord1d = dllEvalCoord1d ; + qglEvalCoord1dv = dllEvalCoord1dv ; + qglEvalCoord1f = dllEvalCoord1f ; + qglEvalCoord1fv = dllEvalCoord1fv ; + qglEvalCoord2d = dllEvalCoord2d ; + qglEvalCoord2dv = dllEvalCoord2dv ; + qglEvalCoord2f = dllEvalCoord2f ; + qglEvalCoord2fv = dllEvalCoord2fv ; + qglEvalMesh1 = dllEvalMesh1 ; + qglEvalMesh2 = dllEvalMesh2 ; + qglEvalPoint1 = dllEvalPoint1 ; + qglEvalPoint2 = dllEvalPoint2 ; + qglFeedbackBuffer = dllFeedbackBuffer ; + qglFinish = dllFinish ; + qglFlush = dllFlush ; + qglFogf = dllFogf ; + qglFogfv = dllFogfv ; + qglFogi = dllFogi ; + qglFogiv = dllFogiv ; + qglFrontFace = dllFrontFace ; + qglFrustum = dllFrustum ; + qglGenLists = dllGenLists ; + qglGenTextures = dllGenTextures ; + qglGetBooleanv = dllGetBooleanv ; + qglGetClipPlane = dllGetClipPlane ; + qglGetDoublev = dllGetDoublev ; + qglGetError = dllGetError ; + qglGetFloatv = dllGetFloatv ; + qglGetIntegerv = dllGetIntegerv ; + qglGetLightfv = dllGetLightfv ; + qglGetLightiv = dllGetLightiv ; + qglGetMapdv = dllGetMapdv ; + qglGetMapfv = dllGetMapfv ; + qglGetMapiv = dllGetMapiv ; + qglGetMaterialfv = dllGetMaterialfv ; + qglGetMaterialiv = dllGetMaterialiv ; + qglGetPixelMapfv = dllGetPixelMapfv ; + qglGetPixelMapuiv = dllGetPixelMapuiv ; + qglGetPixelMapusv = dllGetPixelMapusv ; + qglGetPointerv = dllGetPointerv ; + qglGetPolygonStipple = dllGetPolygonStipple ; + qglGetString = dllGetString ; + qglGetTexEnvfv = dllGetTexEnvfv ; + qglGetTexEnviv = dllGetTexEnviv ; + qglGetTexGendv = dllGetTexGendv ; + qglGetTexGenfv = dllGetTexGenfv ; + qglGetTexGeniv = dllGetTexGeniv ; + qglGetTexImage = dllGetTexImage ; + qglGetTexLevelParameterfv = dllGetTexLevelParameterfv ; + qglGetTexLevelParameteriv = dllGetTexLevelParameteriv ; + qglGetTexParameterfv = dllGetTexParameterfv ; + qglGetTexParameteriv = dllGetTexParameteriv ; + qglHint = dllHint ; + qglIndexMask = dllIndexMask ; + qglIndexPointer = dllIndexPointer ; + qglIndexd = dllIndexd ; + qglIndexdv = dllIndexdv ; + qglIndexf = dllIndexf ; + qglIndexfv = dllIndexfv ; + qglIndexi = dllIndexi ; + qglIndexiv = dllIndexiv ; + qglIndexs = dllIndexs ; + qglIndexsv = dllIndexsv ; + qglIndexub = dllIndexub ; + qglIndexubv = dllIndexubv ; + qglInitNames = dllInitNames ; + qglInterleavedArrays = dllInterleavedArrays ; + qglIsEnabled = dllIsEnabled ; + qglIsList = dllIsList ; + qglIsTexture = dllIsTexture ; + qglLightModelf = dllLightModelf ; + qglLightModelfv = dllLightModelfv ; + qglLightModeli = dllLightModeli ; + qglLightModeliv = dllLightModeliv ; + qglLightf = dllLightf ; + qglLightfv = dllLightfv ; + qglLighti = dllLighti ; + qglLightiv = dllLightiv ; + qglLineStipple = dllLineStipple ; + qglLineWidth = dllLineWidth ; + qglListBase = dllListBase ; + qglLoadIdentity = dllLoadIdentity ; + qglLoadMatrixd = dllLoadMatrixd ; + qglLoadMatrixf = dllLoadMatrixf ; + qglLoadName = dllLoadName ; + qglLogicOp = dllLogicOp ; + qglMap1d = dllMap1d ; + qglMap1f = dllMap1f ; + qglMap2d = dllMap2d ; + qglMap2f = dllMap2f ; + qglMapGrid1d = dllMapGrid1d ; + qglMapGrid1f = dllMapGrid1f ; + qglMapGrid2d = dllMapGrid2d ; + qglMapGrid2f = dllMapGrid2f ; + qglMaterialf = dllMaterialf ; + qglMaterialfv = dllMaterialfv ; + qglMateriali = dllMateriali ; + qglMaterialiv = dllMaterialiv ; + qglMatrixMode = dllMatrixMode ; + qglMultMatrixd = dllMultMatrixd ; + qglMultMatrixf = dllMultMatrixf ; + qglNewList = dllNewList ; + qglNormal3b = dllNormal3b ; + qglNormal3bv = dllNormal3bv ; + qglNormal3d = dllNormal3d ; + qglNormal3dv = dllNormal3dv ; + qglNormal3f = dllNormal3f ; + qglNormal3fv = dllNormal3fv ; + qglNormal3i = dllNormal3i ; + qglNormal3iv = dllNormal3iv ; + qglNormal3s = dllNormal3s ; + qglNormal3sv = dllNormal3sv ; + qglNormalPointer = dllNormalPointer ; + qglOrtho = dllOrtho ; + qglPassThrough = dllPassThrough ; + qglPixelMapfv = dllPixelMapfv ; + qglPixelMapuiv = dllPixelMapuiv ; + qglPixelMapusv = dllPixelMapusv ; + qglPixelStoref = dllPixelStoref ; + qglPixelStorei = dllPixelStorei ; + qglPixelTransferf = dllPixelTransferf ; + qglPixelTransferi = dllPixelTransferi ; + qglPixelZoom = dllPixelZoom ; + qglPointSize = dllPointSize ; + qglPolygonMode = dllPolygonMode ; + qglPolygonOffset = dllPolygonOffset ; + qglPolygonStipple = dllPolygonStipple ; + qglPopAttrib = dllPopAttrib ; + qglPopClientAttrib = dllPopClientAttrib ; + qglPopMatrix = dllPopMatrix ; + qglPopName = dllPopName ; + qglPrioritizeTextures = dllPrioritizeTextures ; + qglPushAttrib = dllPushAttrib ; + qglPushClientAttrib = dllPushClientAttrib ; + qglPushMatrix = dllPushMatrix ; + qglPushName = dllPushName ; + qglRasterPos2d = dllRasterPos2d ; + qglRasterPos2dv = dllRasterPos2dv ; + qglRasterPos2f = dllRasterPos2f ; + qglRasterPos2fv = dllRasterPos2fv ; + qglRasterPos2i = dllRasterPos2i ; + qglRasterPos2iv = dllRasterPos2iv ; + qglRasterPos2s = dllRasterPos2s ; + qglRasterPos2sv = dllRasterPos2sv ; + qglRasterPos3d = dllRasterPos3d ; + qglRasterPos3dv = dllRasterPos3dv ; + qglRasterPos3f = dllRasterPos3f ; + qglRasterPos3fv = dllRasterPos3fv ; + qglRasterPos3i = dllRasterPos3i ; + qglRasterPos3iv = dllRasterPos3iv ; + qglRasterPos3s = dllRasterPos3s ; + qglRasterPos3sv = dllRasterPos3sv ; + qglRasterPos4d = dllRasterPos4d ; + qglRasterPos4dv = dllRasterPos4dv ; + qglRasterPos4f = dllRasterPos4f ; + qglRasterPos4fv = dllRasterPos4fv ; + qglRasterPos4i = dllRasterPos4i ; + qglRasterPos4iv = dllRasterPos4iv ; + qglRasterPos4s = dllRasterPos4s ; + qglRasterPos4sv = dllRasterPos4sv ; + qglReadBuffer = dllReadBuffer ; + qglReadPixels = dllReadPixels ; + qglRectd = dllRectd ; + qglRectdv = dllRectdv ; + qglRectf = dllRectf ; + qglRectfv = dllRectfv ; + qglRecti = dllRecti ; + qglRectiv = dllRectiv ; + qglRects = dllRects ; + qglRectsv = dllRectsv ; + qglRenderMode = dllRenderMode ; + qglRotated = dllRotated ; + qglRotatef = dllRotatef ; + qglScaled = dllScaled ; + qglScalef = dllScalef ; + qglScissor = dllScissor ; + qglSelectBuffer = dllSelectBuffer ; + qglShadeModel = dllShadeModel ; + qglStencilFunc = dllStencilFunc ; + qglStencilMask = dllStencilMask ; + qglStencilOp = dllStencilOp ; + qglTexCoord1d = dllTexCoord1d ; + qglTexCoord1dv = dllTexCoord1dv ; + qglTexCoord1f = dllTexCoord1f ; + qglTexCoord1fv = dllTexCoord1fv ; + qglTexCoord1i = dllTexCoord1i ; + qglTexCoord1iv = dllTexCoord1iv ; + qglTexCoord1s = dllTexCoord1s ; + qglTexCoord1sv = dllTexCoord1sv ; + qglTexCoord2d = dllTexCoord2d ; + qglTexCoord2dv = dllTexCoord2dv ; + qglTexCoord2f = dllTexCoord2f ; + qglTexCoord2fv = dllTexCoord2fv ; + qglTexCoord2i = dllTexCoord2i ; + qglTexCoord2iv = dllTexCoord2iv ; + qglTexCoord2s = dllTexCoord2s ; + qglTexCoord2sv = dllTexCoord2sv ; + qglTexCoord3d = dllTexCoord3d ; + qglTexCoord3dv = dllTexCoord3dv ; + qglTexCoord3f = dllTexCoord3f ; + qglTexCoord3fv = dllTexCoord3fv ; + qglTexCoord3i = dllTexCoord3i ; + qglTexCoord3iv = dllTexCoord3iv ; + qglTexCoord3s = dllTexCoord3s ; + qglTexCoord3sv = dllTexCoord3sv ; + qglTexCoord4d = dllTexCoord4d ; + qglTexCoord4dv = dllTexCoord4dv ; + qglTexCoord4f = dllTexCoord4f ; + qglTexCoord4fv = dllTexCoord4fv ; + qglTexCoord4i = dllTexCoord4i ; + qglTexCoord4iv = dllTexCoord4iv ; + qglTexCoord4s = dllTexCoord4s ; + qglTexCoord4sv = dllTexCoord4sv ; + qglTexCoordPointer = dllTexCoordPointer ; + qglTexEnvf = dllTexEnvf ; + qglTexEnvfv = dllTexEnvfv ; + qglTexEnvi = dllTexEnvi ; + qglTexEnviv = dllTexEnviv ; + qglTexGend = dllTexGend ; + qglTexGendv = dllTexGendv ; + qglTexGenf = dllTexGenf ; + qglTexGenfv = dllTexGenfv ; + qglTexGeni = dllTexGeni ; + qglTexGeniv = dllTexGeniv ; + qglTexImage1D = dllTexImage1D ; + qglTexImage2D = dllTexImage2D ; + qglTexParameterf = dllTexParameterf ; + qglTexParameterfv = dllTexParameterfv ; + qglTexParameteri = dllTexParameteri ; + qglTexParameteriv = dllTexParameteriv ; + qglTexSubImage1D = dllTexSubImage1D ; + qglTexSubImage2D = dllTexSubImage2D ; + qglTranslated = dllTranslated ; + qglTranslatef = dllTranslatef ; + qglVertex2d = dllVertex2d ; + qglVertex2dv = dllVertex2dv ; + qglVertex2f = dllVertex2f ; + qglVertex2fv = dllVertex2fv ; + qglVertex2i = dllVertex2i ; + qglVertex2iv = dllVertex2iv ; + qglVertex2s = dllVertex2s ; + qglVertex2sv = dllVertex2sv ; + qglVertex3d = dllVertex3d ; + qglVertex3dv = dllVertex3dv ; + qglVertex3f = dllVertex3f ; + qglVertex3fv = dllVertex3fv ; + qglVertex3i = dllVertex3i ; + qglVertex3iv = dllVertex3iv ; + qglVertex3s = dllVertex3s ; + qglVertex3sv = dllVertex3sv ; + qglVertex4d = dllVertex4d ; + qglVertex4dv = dllVertex4dv ; + qglVertex4f = dllVertex4f ; + qglVertex4fv = dllVertex4fv ; + qglVertex4i = dllVertex4i ; + qglVertex4iv = dllVertex4iv ; + qglVertex4s = dllVertex4s ; + qglVertex4sv = dllVertex4sv ; + qglVertexPointer = dllVertexPointer ; + qglViewport = dllViewport ; + } +} + + +void GLimp_LogNewFrame( void ) +{ + fprintf( log_fp, "*** R_BeginFrame ***\n"); +} + + diff --git a/irix/snd_irix.c b/irix/snd_irix.c new file mode 100644 index 000000000..a15bcb0b7 --- /dev/null +++ b/irix/snd_irix.c @@ -0,0 +1,222 @@ +#include +#include + +#include "../client/client.h" +#include "../client/snd_loc.h" + +/* +================== +SNDDM_Init + +Try to find a sound device to mix for. +Returns false if nothing is found. +Returns true and fills in the "dma" structure with information for the mixer. +================== +*/ + +// must be power of two! +#define QSND_SKID 2 +#define QSND_BUFFER_FRAMES 8192 +#define QSND_BUFFER_SIZE (QSND_BUFFER_FRAMES*2) + +#define UST_TO_BUFFPOS(ust) ((int)((ust) & (QSND_BUFFER_FRAMES - 1)) << 1) + +cvar_t *s_loadas8bit; +cvar_t *s_khz; +cvar_t *sndchannels; + +short int dma_buffer[QSND_BUFFER_SIZE]; +ALport sgisnd_aport = NULL; +long long sgisnd_startframe; +double sgisnd_frames_per_ns; +long long sgisnd_lastframewritten = 0; + +qboolean SNDDMA_Init(void) +{ + ALconfig ac = NULL; + ALpv pvbuf[2]; + + s_loadas8bit = Cvar_Get("s_loadas8bit", "16", CVAR_ARCHIVE); + if ((int)s_loadas8bit->value) + dma.samplebits = 8; + else + dma.samplebits = 16; + + if (dma.samplebits != 16) { + Com_Printf("Don't currently support %i-bit data. Forcing 16-bit.\n", + dma.samplebits); + dma.samplebits = 16; + Cvar_SetValue( "s_loadas8bit", false ); + } + + s_khz = Cvar_Get("s_khz", "0", CVAR_ARCHIVE); + switch ((int)s_khz->value) { + case 48: + dma.speed = AL_RATE_48000; + break; + case 44: + dma.speed = AL_RATE_44100; + break; + case 32: + dma.speed = AL_RATE_32000; + break; + case 22: + dma.speed = AL_RATE_22050; + break; + case 16: + dma.speed = AL_RATE_16000; + break; + case 11: + dma.speed = AL_RATE_11025; + break; + case 8: + dma.speed = AL_RATE_8000; + break; + default: + dma.speed = AL_RATE_22050; + Com_Printf("Don't currently support %i kHz sample rate. Using %i.\n", + (int)s_khz->value, (int)(dma.speed/1000)); + } + + sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE); + dma.channels = (int)sndchannels->value; + if (dma.channels != 2) + Com_Printf("Don't currently support %i sound channels. Try 2.\n", + sndchannels); + + /***********************/ + + ac = alNewConfig(); + alSetChannels( ac, AL_STEREO ); + alSetSampFmt( ac, AL_SAMPFMT_TWOSCOMP ); + alSetQueueSize( ac, QSND_BUFFER_FRAMES ); + if (dma.samplebits == 8) + alSetWidth( ac, AL_SAMPLE_8 ); + else + alSetWidth( ac, AL_SAMPLE_16 ); + + sgisnd_aport = alOpenPort( "Quake", "w", ac ); + if (!sgisnd_aport) + { + printf( "failed to open audio port!\n" ); + } + + // set desired sample rate + pvbuf[0].param = AL_MASTER_CLOCK; + pvbuf[0].value.i = AL_CRYSTAL_MCLK_TYPE; + pvbuf[1].param = AL_RATE; + pvbuf[1].value.ll = alIntToFixed( dma.speed ); + alSetParams( alGetResource( sgisnd_aport ), pvbuf, 2 ); + if (pvbuf[1].sizeOut < 0) + printf( "illegal sample rate %d\n", dma.speed ); + + sgisnd_frames_per_ns = dma.speed * 1.0e-9; + + dma.samples = sizeof(dma_buffer)/(dma.samplebits/8); + dma.submission_chunk = 1; + + dma.buffer = (unsigned char *)dma_buffer; + + dma.samplepos = 0; + + alFreeConfig( ac ); + return true; +} + + +/* +============== +SNDDMA_GetDMAPos + +return the current sample position (in mono samples, not stereo) +inside the recirculating dma buffer, so the mixing code will know +how many sample are required to fill it up. +=============== +*/ +int SNDDMA_GetDMAPos(void) +{ + long long ustFuture, ustNow; + if (!sgisnd_aport) return( 0 ); + alGetFrameTime( sgisnd_aport, &sgisnd_startframe, &ustFuture ); + dmGetUST( (unsigned long long *)&ustNow ); + sgisnd_startframe -= (long long)((ustFuture - ustNow) * sgisnd_frames_per_ns); + sgisnd_startframe += 100; +//printf( "frame %ld pos %d\n", frame, UST_TO_BUFFPOS( sgisnd_startframe ) ); + return( UST_TO_BUFFPOS( sgisnd_startframe ) ); +} + +/* +============== +SNDDMA_Shutdown + +Reset the sound device for exiting +=============== +*/ +void SNDDMA_Shutdown(void) +{ + if (sgisnd_aport) alClosePort( sgisnd_aport ), sgisnd_aport = NULL; + return; +} + +/* +============== +SNDDMA_Submit + +Send sound to device if buffer isn't really the dma buffer +=============== +*/ + +extern int soundtime; + +void SNDDMA_Submit(void) +{ + int nFillable, nFilled, nPos; + int nFrames, nFramesLeft; + unsigned endtime; + + if (!sgisnd_aport) return; + + nFillable = alGetFillable( sgisnd_aport ); + nFilled = QSND_BUFFER_FRAMES - nFillable; + + nFrames = dma.samples >> (dma.channels - 1); + + if (paintedtime - soundtime < nFrames) + nFrames = paintedtime - soundtime; + + if (nFrames <= QSND_SKID) return; + + nPos = UST_TO_BUFFPOS( sgisnd_startframe ); + + // dump re-written contents of the buffer + if (sgisnd_lastframewritten > sgisnd_startframe) + { + alDiscardFrames( sgisnd_aport, sgisnd_lastframewritten - sgisnd_startframe ); + } + else if ((int)(sgisnd_startframe - sgisnd_lastframewritten) >= QSND_BUFFER_FRAMES) + { + // blow away everything if we've underflowed + alDiscardFrames( sgisnd_aport, QSND_BUFFER_FRAMES ); + } + + // don't block + if (nFrames > nFillable) nFrames = nFillable; + + // account for stereo + nFramesLeft = nFrames; + if (nPos + nFrames * dma.channels > QSND_BUFFER_SIZE) + { + int nFramesAtEnd = (QSND_BUFFER_SIZE - nPos) >> (dma.channels - 1); + + alWriteFrames( sgisnd_aport, &dma_buffer[nPos], nFramesAtEnd ); + nPos = 0; + nFramesLeft -= nFramesAtEnd; + } + alWriteFrames( sgisnd_aport, &dma_buffer[nPos], nFramesLeft ); + + sgisnd_lastframewritten = sgisnd_startframe + nFrames; +} + +void SNDDMA_BeginPainting (void) +{ +} diff --git a/irix/sys_irix.c b/irix/sys_irix.c new file mode 100644 index 000000000..ed1834bd7 --- /dev/null +++ b/irix/sys_irix.c @@ -0,0 +1,383 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../qcommon/qcommon.h" + +#include "../linux/rw_linux.h" + +cvar_t *nostdout; + +unsigned sys_frame_time; + +uid_t saved_euid; +qboolean stdin_active = true; + +// ======================================================================= +// General routines +// ======================================================================= + +void Sys_ConsoleOutput (char *string) +{ + if (nostdout && nostdout->value) + return; + + fputs(string, stdout); +} + +void Sys_Printf (char *fmt, ...) +{ + va_list argptr; + char text[1024]; + unsigned char *p; + + va_start (argptr,fmt); + vsprintf (text,fmt,argptr); + va_end (argptr); + + if (strlen(text) > sizeof(text)) + Sys_Error("memory overwrite in Sys_Printf"); + + if (nostdout && nostdout->value) + return; + + for (p = (unsigned char *)text; *p; p++) { + *p &= 0x7f; + if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9) + printf("[%02x]", *p); + else + putc(*p, stdout); + } +} + +void Sys_Quit (void) +{ + CL_Shutdown (); + Qcommon_Shutdown (); + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); + _exit(0); +} + +void Sys_Init(void) +{ +#if id386 +// Sys_SetFPCW(); +#endif +} + +void Sys_Error (char *error, ...) +{ + va_list argptr; + char string[1024]; + +// change stdin to non blocking + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); + + va_start (argptr,error); + vsprintf (string,error,argptr); + va_end (argptr); + fprintf(stderr, "Error: %s\n", string); + + CL_Shutdown (); + Qcommon_Shutdown (); + _exit (1); + +} + +void Sys_Warn (char *warning, ...) +{ + va_list argptr; + char string[1024]; + + va_start (argptr,warning); + vsprintf (string,warning,argptr); + va_end (argptr); + fprintf(stderr, "Warning: %s", string); +} + +/* +============ +Sys_FileTime + +returns -1 if not present +============ +*/ +int Sys_FileTime (char *path) +{ + struct stat buf; + + if (stat (path,&buf) == -1) + return -1; + + return buf.st_mtime; +} + +void floating_point_exception_handler(int whatever) +{ +// Sys_Warn("floating point exception\n"); + signal(SIGFPE, floating_point_exception_handler); +} + +char *Sys_ConsoleInput(void) +{ + static char text[256]; + int len; + fd_set fdset; + struct timeval timeout; + + if (!dedicated || !dedicated->value) + return NULL; + + if (!stdin_active) + return NULL; + + FD_ZERO(&fdset); + FD_SET(0, &fdset); // stdin + timeout.tv_sec = 0; + timeout.tv_usec = 0; + if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset)) + return NULL; + + len = read (0, text, sizeof(text)); + if (len == 0) { // eof! + stdin_active = false; + return NULL; + } + + if (len < 1) + return NULL; + text[len-1] = 0; // rip off the /n and terminate + + return text; +} + +/*****************************************************************************/ + +static void *game_library; + +/* +================= +Sys_UnloadGame +================= +*/ +void Sys_UnloadGame (void) +{ + if (game_library) + dlclose (game_library); + game_library = NULL; +} + +/* +================= +Sys_GetGameAPI + +Loads the game dll +================= +*/ +void *Sys_GetGameAPI (void *parms) +{ +#ifndef REF_HARD_LINKED + void *(*GetGameAPI) (void *); + + char name[MAX_OSPATH]; + char curpath[MAX_OSPATH]; + char *path; +#ifdef __sgi + const char *gamename = "gamemips.so"; +#else +#error Unknown arch +#endif + + setreuid(getuid(), getuid()); + setegid(getgid()); + + if (game_library) + Com_Error (ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame"); + + getcwd(curpath, sizeof(curpath)); + + Com_Printf("------- Loading %s -------", gamename); + + // now run through the search paths + path = NULL; + while (1) + { + path = FS_NextPath (path); + if (!path) + return NULL; // couldn't find one anywhere + sprintf (name, "%s/%s/%s", curpath, path, gamename); + Com_Printf ("Trying to load library (%s)\n",name); + game_library = dlopen (name, RTLD_NOW ); + if (game_library) + { + Com_DPrintf ("LoadLibrary (%s)\n",name); + break; + } + } + + GetGameAPI = (void *)dlsym (game_library, "GetGameAPI"); + if (!GetGameAPI) + { + Sys_UnloadGame (); + return NULL; + } + + return GetGameAPI (parms); +#else + return (void *)GetGameAPI (parms); +#endif +} + +/*****************************************************************************/ + +void Sys_AppActivate (void) +{ +} + +void Sys_SendKeyEvents (void) +{ + if (KBD_Update_fp) + KBD_Update_fp(); + + // grab frame time + sys_frame_time = Sys_Milliseconds(); +} + +/*****************************************************************************/ + +char *Sys_GetClipboardData(void) +{ + return NULL; +} + +int main (int argc, char **argv) +{ + int time, oldtime, newtime; + + // go back to real user for config loads + saved_euid = geteuid(); + seteuid(getuid()); + + Qcommon_Init(argc, argv); + +/* fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); */ + + nostdout = Cvar_Get("nostdout", "0", 0); + if (!nostdout->value) { +/* fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); */ +// printf ("Linux Quake -- Version %0.3f\n", LINUX_VERSION); + } + + oldtime = Sys_Milliseconds (); + while (1) + { +// find time spent rendering last frame + do { + newtime = Sys_Milliseconds (); + time = newtime - oldtime; + } while (time < 1); + Qcommon_Frame (time); + oldtime = newtime; + } + +} + +void Sys_CopyProtect(void) +{ + FILE *mnt; + struct mntent *ent; + char path[MAX_OSPATH]; + struct stat st; + qboolean found_cd = false; + + static qboolean checked = false; + + if (checked) + return; + + Com_Printf("XXX - Sys_CopyProtect disabled\n"); + checked = true; + return; + + if ((mnt = setmntent("/etc/mtab", "r")) == NULL) + Com_Error(ERR_FATAL, "Can't read mount table to determine mounted cd location."); + + while ((ent = getmntent(mnt)) != NULL) { + if (strcmp(ent->mnt_type, "iso9660") == 0) { + // found a cd file system + found_cd = true; + sprintf(path, "%s/%s", ent->mnt_dir, "install/data/quake2.exe"); + if (stat(path, &st) == 0) { + // found it + checked = true; + endmntent(mnt); + return; + } + sprintf(path, "%s/%s", ent->mnt_dir, "Install/Data/quake2.exe"); + if (stat(path, &st) == 0) { + // found it + checked = true; + endmntent(mnt); + return; + } + sprintf(path, "%s/%s", ent->mnt_dir, "quake2.exe"); + if (stat(path, &st) == 0) { + // found it + checked = true; + endmntent(mnt); + return; + } + } + } + endmntent(mnt); + + if (found_cd) + Com_Error (ERR_FATAL, "Could not find a Quake2 CD in your CD drive."); + Com_Error (ERR_FATAL, "Unable to find a mounted iso9660 file system.\n" + "You must mount the Quake2 CD in a cdrom drive in order to play."); +} + +#if 0 +/* +================ +Sys_MakeCodeWriteable +================ +*/ +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +{ + + int r; + unsigned long addr; + int psize = getpagesize(); + + addr = (startaddr & ~(psize-1)) - psize; + +// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr, +// addr, startaddr+length, length); + + r = mprotect((char*)addr, length + startaddr - addr + psize, 7); + + if (r < 0) + Sys_Error("Protection change failed\n"); + +} + +#endif diff --git a/irix/vid_menu.c b/irix/vid_menu.c new file mode 100644 index 000000000..523487da1 --- /dev/null +++ b/irix/vid_menu.c @@ -0,0 +1,426 @@ +#include "../client/client.h" +#include "../client/qmenu.h" + +#define REF_SOFT 0 +#define REF_OPENGL 1 + +extern cvar_t *vid_ref; +extern cvar_t *vid_fullscreen; +extern cvar_t *vid_gamma; +extern cvar_t *scr_viewsize; + +static cvar_t *gl_mode; +static cvar_t *gl_driver; +static cvar_t *gl_picmip; +static cvar_t *gl_ext_palettedtexture; + +static cvar_t *sw_mode; +static cvar_t *sw_stipplealpha; + +static cvar_t *_windowed_mouse; + +extern void M_ForceMenuOff( void ); + +/* +==================================================================== + +MENU INTERACTION + +==================================================================== +*/ +#define SOFTWARE_MENU 0 +#define OPENGL_MENU 1 + +static menuframework_s s_software_menu; +static menuframework_s s_opengl_menu; +static menuframework_s *s_current_menu; +static int s_current_menu_index; + +static menulist_s s_mode_list[2]; +static menulist_s s_ref_list[2]; +static menuslider_s s_tq_slider; +static menuslider_s s_screensize_slider[2]; +static menuslider_s s_brightness_slider[2]; +static menulist_s s_fs_box[2]; +static menulist_s s_stipple_box; +static menulist_s s_paletted_texture_box; +static menulist_s s_windowed_mouse; +static menuaction_s s_apply_action[2]; +static menuaction_s s_defaults_action[2]; + +static void DriverCallback( void *unused ) +{ + s_ref_list[!s_current_menu_index].curvalue = s_ref_list[s_current_menu_index].curvalue; + + if ( s_ref_list[s_current_menu_index].curvalue < 1 ) + { + s_current_menu = &s_software_menu; + s_current_menu_index = 0; + } + else + { + s_current_menu = &s_opengl_menu; + s_current_menu_index = 1; + } + +} + +static void ScreenSizeCallback( void *s ) +{ + menuslider_s *slider = ( menuslider_s * ) s; + + Cvar_SetValue( "viewsize", slider->curvalue * 10 ); +} + +static void BrightnessCallback( void *s ) +{ + menuslider_s *slider = ( menuslider_s * ) s; + + if ( s_current_menu_index == 0) + s_brightness_slider[1].curvalue = s_brightness_slider[0].curvalue; + else + s_brightness_slider[0].curvalue = s_brightness_slider[1].curvalue; + + if ( Q_stricmp( vid_ref->string, "soft" ) == 0 ) + { + float gamma = ( 0.8 - ( slider->curvalue/10.0 - 0.5 ) ) + 0.5; + + Cvar_SetValue( "vid_gamma", gamma ); + } +} + +static void ResetDefaults( void *unused ) +{ + VID_MenuInit(); +} + +static void ApplyChanges( void *unused ) +{ + float gamma; + + /* + ** make values consistent + */ + s_fs_box[!s_current_menu_index].curvalue = s_fs_box[s_current_menu_index].curvalue; + s_brightness_slider[!s_current_menu_index].curvalue = s_brightness_slider[s_current_menu_index].curvalue; + s_ref_list[!s_current_menu_index].curvalue = s_ref_list[s_current_menu_index].curvalue; + + /* + ** invert sense so greater = brighter, and scale to a range of 0.5 to 1.3 + */ + gamma = ( 0.8 - ( s_brightness_slider[s_current_menu_index].curvalue/10.0 - 0.5 ) ) + 0.5; + + Cvar_SetValue( "vid_gamma", gamma ); + Cvar_SetValue( "sw_stipplealpha", s_stipple_box.curvalue ); + Cvar_SetValue( "gl_picmip", 3 - s_tq_slider.curvalue ); + Cvar_SetValue( "vid_fullscreen", s_fs_box[s_current_menu_index].curvalue ); + Cvar_SetValue( "gl_ext_palettedtexture", s_paletted_texture_box.curvalue ); + Cvar_SetValue( "sw_mode", s_mode_list[SOFTWARE_MENU].curvalue ); + Cvar_SetValue( "gl_mode", s_mode_list[OPENGL_MENU].curvalue ); + Cvar_SetValue( "_windowed_mouse", s_windowed_mouse.curvalue); + + switch ( s_ref_list[s_current_menu_index].curvalue ) + { + case REF_SOFT: + Cvar_Set( "vid_ref", "soft" ); + break; + case REF_OPENGL: + Cvar_Set( "vid_ref", "gl" ); + Cvar_Set( "gl_driver", "opengl32" ); + break; + } + +#if 0 + /* + ** update appropriate stuff if we're running OpenGL and gamma + ** has been modified + */ + if ( Q_stricmp( vid_ref->string, "gl" ) == 0 ) + { + if ( vid_gamma->modified ) + { + vid_ref->modified = true; + if ( Q_stricmp( gl_driver->string, "3dfxgl" ) == 0 ) + { + char envbuffer[1024]; + float g; + + vid_ref->modified = true; + + g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F; + Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g ); + putenv( envbuffer ); + + vid_gamma->modified = false; + } + } + } +#endif + + M_ForceMenuOff(); +} + +/* +** VID_MenuInit +*/ +void VID_MenuInit( void ) +{ + static const char *resolutions[] = + { + "[320 240 ]", + "[400 300 ]", + "[512 384 ]", + "[640 480 ]", + "[800 600 ]", + "[960 720 ]", + "[1024 768 ]", + "[1152 864 ]", + "[1280 1024]", + "[1600 1200]", + 0 + }; + static const char *refs[] = + { + "[software ]", + "[default OpenGL]", + 0 + }; + static const char *yesno_names[] = + { + "no", + "yes", + 0 + }; + int i; + + if ( !gl_driver ) + gl_driver = Cvar_Get( "gl_driver", "opengl32", 0 ); + if ( !gl_picmip ) + gl_picmip = Cvar_Get( "gl_picmip", "0", 0 ); + if ( !gl_mode ) + gl_mode = Cvar_Get( "gl_mode", "3", 0 ); + if ( !sw_mode ) + sw_mode = Cvar_Get( "sw_mode", "0", 0 ); + if ( !gl_ext_palettedtexture ) + gl_ext_palettedtexture = Cvar_Get( "gl_ext_palettedtexture", "1", CVAR_ARCHIVE ); + + if ( !sw_stipplealpha ) + sw_stipplealpha = Cvar_Get( "sw_stipplealpha", "0", CVAR_ARCHIVE ); + + if ( !_windowed_mouse) + _windowed_mouse = Cvar_Get( "_windowed_mouse", "0", CVAR_ARCHIVE ); + + s_mode_list[SOFTWARE_MENU].curvalue = sw_mode->value; + s_mode_list[OPENGL_MENU].curvalue = gl_mode->value; + + if ( !scr_viewsize ) + scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE); + + s_screensize_slider[SOFTWARE_MENU].curvalue = scr_viewsize->value/10; + s_screensize_slider[OPENGL_MENU].curvalue = scr_viewsize->value/10; + + if (strcmp( vid_ref->string, "soft" ) == 0 ) + { + s_current_menu_index = SOFTWARE_MENU; + s_ref_list[0].curvalue = s_ref_list[1].curvalue = REF_SOFT; + } + else if ( strcmp( vid_ref->string, "gl" ) == 0 ) + { + s_current_menu_index = OPENGL_MENU; + s_ref_list[s_current_menu_index].curvalue = REF_OPENGL; +#if 0 + if ( strcmp( gl_driver->string, "3dfxgl" ) == 0 ) + s_ref_list[s_current_menu_index].curvalue = REF_3DFX; + else if ( strcmp( gl_driver->string, "pvrgl" ) == 0 ) + s_ref_list[s_current_menu_index].curvalue = REF_POWERVR; + else if ( strcmp( gl_driver->string, "opengl32" ) == 0 ) + s_ref_list[s_current_menu_index].curvalue = REF_OPENGL; + else + s_ref_list[s_current_menu_index].curvalue = REF_VERITE; +#endif + } + + s_software_menu.x = viddef.width * 0.50; + s_software_menu.nitems = 0; + s_opengl_menu.x = viddef.width * 0.50; + s_opengl_menu.nitems = 0; + + for ( i = 0; i < 2; i++ ) + { + s_ref_list[i].generic.type = MTYPE_SPINCONTROL; + s_ref_list[i].generic.name = "driver"; + s_ref_list[i].generic.x = 0; + s_ref_list[i].generic.y = 0; + s_ref_list[i].generic.callback = DriverCallback; + s_ref_list[i].itemnames = refs; + + s_mode_list[i].generic.type = MTYPE_SPINCONTROL; + s_mode_list[i].generic.name = "video mode"; + s_mode_list[i].generic.x = 0; + s_mode_list[i].generic.y = 10; + s_mode_list[i].itemnames = resolutions; + + s_screensize_slider[i].generic.type = MTYPE_SLIDER; + s_screensize_slider[i].generic.x = 0; + s_screensize_slider[i].generic.y = 20; + s_screensize_slider[i].generic.name = "screen size"; + s_screensize_slider[i].minvalue = 3; + s_screensize_slider[i].maxvalue = 12; + s_screensize_slider[i].generic.callback = ScreenSizeCallback; + + s_brightness_slider[i].generic.type = MTYPE_SLIDER; + s_brightness_slider[i].generic.x = 0; + s_brightness_slider[i].generic.y = 30; + s_brightness_slider[i].generic.name = "brightness"; + s_brightness_slider[i].generic.callback = BrightnessCallback; + s_brightness_slider[i].minvalue = 5; + s_brightness_slider[i].maxvalue = 13; + s_brightness_slider[i].curvalue = ( 1.3 - vid_gamma->value + 0.5 ) * 10; + + s_fs_box[i].generic.type = MTYPE_SPINCONTROL; + s_fs_box[i].generic.x = 0; + s_fs_box[i].generic.y = 40; + s_fs_box[i].generic.name = "fullscreen"; + s_fs_box[i].itemnames = yesno_names; + s_fs_box[i].curvalue = vid_fullscreen->value; + + s_defaults_action[i].generic.type = MTYPE_ACTION; + s_defaults_action[i].generic.name = "reset to default"; + s_defaults_action[i].generic.x = 0; + s_defaults_action[i].generic.y = 90; + s_defaults_action[i].generic.callback = ResetDefaults; + + s_apply_action[i].generic.type = MTYPE_ACTION; + s_apply_action[i].generic.name = "apply"; + s_apply_action[i].generic.x = 0; + s_apply_action[i].generic.y = 100; + s_apply_action[i].generic.callback = ApplyChanges; + } + + s_stipple_box.generic.type = MTYPE_SPINCONTROL; + s_stipple_box.generic.x = 0; + s_stipple_box.generic.y = 60; + s_stipple_box.generic.name = "stipple alpha"; + s_stipple_box.curvalue = sw_stipplealpha->value; + s_stipple_box.itemnames = yesno_names; + + s_windowed_mouse.generic.type = MTYPE_SPINCONTROL; + s_windowed_mouse.generic.x = 0; + s_windowed_mouse.generic.y = 72; + s_windowed_mouse.generic.name = "windowed mouse"; + s_windowed_mouse.curvalue = _windowed_mouse->value; + s_windowed_mouse.itemnames = yesno_names; + + s_tq_slider.generic.type = MTYPE_SLIDER; + s_tq_slider.generic.x = 0; + s_tq_slider.generic.y = 60; + s_tq_slider.generic.name = "texture quality"; + s_tq_slider.minvalue = 0; + s_tq_slider.maxvalue = 3; + s_tq_slider.curvalue = 3-gl_picmip->value; + + s_paletted_texture_box.generic.type = MTYPE_SPINCONTROL; + s_paletted_texture_box.generic.x = 0; + s_paletted_texture_box.generic.y = 70; + s_paletted_texture_box.generic.name = "8-bit textures"; + s_paletted_texture_box.itemnames = yesno_names; + s_paletted_texture_box.curvalue = gl_ext_palettedtexture->value; + + Menu_AddItem( &s_software_menu, ( void * ) &s_ref_list[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_mode_list[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_screensize_slider[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_brightness_slider[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_fs_box[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_stipple_box ); + Menu_AddItem( &s_software_menu, ( void * ) &s_windowed_mouse ); + + Menu_AddItem( &s_opengl_menu, ( void * ) &s_ref_list[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_mode_list[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_screensize_slider[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_brightness_slider[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_fs_box[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_tq_slider ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_paletted_texture_box ); + + Menu_AddItem( &s_software_menu, ( void * ) &s_defaults_action[SOFTWARE_MENU] ); + Menu_AddItem( &s_software_menu, ( void * ) &s_apply_action[SOFTWARE_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_defaults_action[OPENGL_MENU] ); + Menu_AddItem( &s_opengl_menu, ( void * ) &s_apply_action[OPENGL_MENU] ); + + Menu_Center( &s_software_menu ); + Menu_Center( &s_opengl_menu ); + s_opengl_menu.x -= 8; + s_software_menu.x -= 8; +} + +/* +================ +VID_MenuDraw +================ +*/ +void VID_MenuDraw (void) +{ + int w, h; + + if ( s_current_menu_index == 0 ) + s_current_menu = &s_software_menu; + else + s_current_menu = &s_opengl_menu; + + /* + ** draw the banner + */ + re.DrawGetPicSize( &w, &h, "m_banner_video" ); + re.DrawPic( viddef.width / 2 - w / 2, viddef.height /2 - 110, "m_banner_video" ); + + /* + ** move cursor to a reasonable starting position + */ + Menu_AdjustCursor( s_current_menu, 1 ); + + /* + ** draw the menu + */ + Menu_Draw( s_current_menu ); +} + +/* +================ +VID_MenuKey +================ +*/ +const char *VID_MenuKey( int key ) +{ + extern void M_PopMenu( void ); + + menuframework_s *m = s_current_menu; + static const char *sound = "misc/menu1.wav"; + + switch ( key ) + { + case K_ESCAPE: + M_PopMenu(); + return NULL; + case K_UPARROW: + m->cursor--; + Menu_AdjustCursor( m, -1 ); + break; + case K_DOWNARROW: + m->cursor++; + Menu_AdjustCursor( m, 1 ); + break; + case K_LEFTARROW: + Menu_SlideItem( m, -1 ); + break; + case K_RIGHTARROW: + Menu_SlideItem( m, 1 ); + break; + case K_ENTER: + Menu_SelectItem( m ); + break; + } + + return sound; +} + + diff --git a/irix/vid_so.c b/irix/vid_so.c new file mode 100644 index 000000000..df1325aa4 --- /dev/null +++ b/irix/vid_so.c @@ -0,0 +1,492 @@ +// Main windowed and fullscreen graphics interface module. This module +// is used for both the software and OpenGL rendering versions of the +// Quake refresh engine. + +#define SO_FILE "/etc/quake2.conf" + +#include +#include +#include // ELF dl loader +#include +#include + +#include "../client/client.h" + +#include "../linux/rw_linux.h" + +// Structure containing functions exported from refresh DLL +refexport_t re; + +#ifdef REF_HARD_LINKED +refexport_t GetRefAPI (refimport_t rimp); +#endif + +// Console variables that we need to access from this module +cvar_t *vid_gamma; +cvar_t *vid_ref; // Name of Refresh DLL loaded +cvar_t *vid_xpos; // X coordinate of window position +cvar_t *vid_ypos; // Y coordinate of window position +cvar_t *vid_fullscreen; + +// Global variables used internally by this module +viddef_t viddef; // global video state; used by other modules +void *reflib_library; // Handle to refresh DLL +qboolean reflib_active = 0; + +#define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) ) + +/** KEYBOARD **************************************************************/ + +void Do_Key_Event(int key, qboolean down); + +void (*KBD_Update_fp)(void); +void (*KBD_Init_fp)(Key_Event_fp_t fp); +void (*KBD_Close_fp)(void); + +/** MOUSE *****************************************************************/ + +in_state_t in_state; + +void (*RW_IN_Init_fp)(in_state_t *in_state_p); +void (*RW_IN_Shutdown_fp)(void); +void (*RW_IN_Activate_fp)(qboolean active); +void (*RW_IN_Commands_fp)(void); +void (*RW_IN_Move_fp)(usercmd_t *cmd); +void (*RW_IN_Frame_fp)(void); + +void Real_IN_Init (void); + +/* +========================================================================== + +DLL GLUE + +========================================================================== +*/ + +#define MAXPRINTMSG 4096 +void VID_Printf (int print_level, char *fmt, ...) +{ + va_list argptr; + char msg[MAXPRINTMSG]; + static qboolean inupdate; + + va_start (argptr,fmt); + vsprintf (msg,fmt,argptr); + va_end (argptr); + + if (print_level == PRINT_ALL) + Com_Printf ("%s", msg); + else + Com_DPrintf ("%s", msg); +} + +void VID_Error (int err_level, char *fmt, ...) +{ + va_list argptr; + char msg[MAXPRINTMSG]; + static qboolean inupdate; + + va_start (argptr,fmt); + vsprintf (msg,fmt,argptr); + va_end (argptr); + + Com_Error (err_level,"%s", msg); +} + +//========================================================================== + +/* +============ +VID_Restart_f + +Console command to re-start the video mode and refresh DLL. We do this +simply by setting the modified flag for the vid_ref variable, which will +cause the entire video mode and refresh DLL to be reset on the next frame. +============ +*/ +void VID_Restart_f (void) +{ + vid_ref->modified = true; +} + +/* +** VID_GetModeInfo +*/ +typedef struct vidmode_s +{ + const char *description; + int width, height; + int mode; +} vidmode_t; + +vidmode_t vid_modes[] = +{ + { "Mode 0: 320x240", 320, 240, 0 }, + { "Mode 1: 400x300", 400, 300, 1 }, + { "Mode 2: 512x384", 512, 384, 2 }, + { "Mode 3: 640x480", 640, 480, 3 }, + { "Mode 4: 800x600", 800, 600, 4 }, + { "Mode 5: 960x720", 960, 720, 5 }, + { "Mode 6: 1024x768", 1024, 768, 6 }, + { "Mode 7: 1152x864", 1152, 864, 7 }, + { "Mode 8: 1280x1024", 1280, 1024, 8 }, + { "Mode 9: 1600x1200", 1600, 1200, 9 } +}; + +qboolean VID_GetModeInfo( int *width, int *height, int mode ) +{ + if ( mode < 0 || mode >= VID_NUM_MODES ) + return false; + + *width = vid_modes[mode].width; + *height = vid_modes[mode].height; + + return true; +} + +/* +** VID_NewWindow +*/ +void VID_NewWindow ( int width, int height) +{ + viddef.width = width; + viddef.height = height; +} + +void VID_FreeReflib (void) +{ + if (reflib_library) { + if (KBD_Close_fp) + KBD_Close_fp(); + if (RW_IN_Shutdown_fp) + RW_IN_Shutdown_fp(); +#ifndef REF_HARD_LINKED + dlclose(reflib_library); +#endif + } + + KBD_Init_fp = NULL; + KBD_Update_fp = NULL; + KBD_Close_fp = NULL; + RW_IN_Init_fp = NULL; + RW_IN_Shutdown_fp = NULL; + RW_IN_Activate_fp = NULL; + RW_IN_Commands_fp = NULL; + RW_IN_Move_fp = NULL; + RW_IN_Frame_fp = NULL; + + memset (&re, 0, sizeof(re)); + reflib_library = NULL; + reflib_active = false; +} + +/* +============== +VID_LoadRefresh +============== +*/ +qboolean VID_LoadRefresh( char *name ) +{ + refimport_t ri; +#ifndef REF_HARD_LINKED + GetRefAPI_t GetRefAPI; +#endif + char fn[MAX_OSPATH]; + struct stat st; + extern uid_t saved_euid; + FILE *fp; + char *path; + char curpath[MAX_OSPATH]; + + if ( reflib_active ) + { + if (KBD_Close_fp) + KBD_Close_fp(); + if (RW_IN_Shutdown_fp) + RW_IN_Shutdown_fp(); + KBD_Close_fp = NULL; + RW_IN_Shutdown_fp = NULL; + re.Shutdown(); + VID_FreeReflib (); + } + +#ifndef REF_HARD_LINKED + getcwd(curpath, sizeof(curpath)); + + Com_Printf( "------- Loading %s -------\n", name ); + + // now run through the search paths + path = NULL; + while (1) + { + path = FS_NextPath (path); + if (!path) + return NULL; // couldn't find one anywhere + sprintf (fn, "%s/%s/%s", curpath, path, name); + Com_Printf ("Trying to load library (%s)\n", fn); + + reflib_library = dlopen( fn, RTLD_NOW ); + if (reflib_library) + { + Com_DPrintf ("LoadLibrary (%s)\n",name); + break; + } + } + +#endif + + ri.Cmd_AddCommand = Cmd_AddCommand; + ri.Cmd_RemoveCommand = Cmd_RemoveCommand; + ri.Cmd_Argc = Cmd_Argc; + ri.Cmd_Argv = Cmd_Argv; + ri.Cmd_ExecuteText = Cbuf_ExecuteText; + ri.Con_Printf = VID_Printf; + ri.Sys_Error = VID_Error; + ri.FS_LoadFile = FS_LoadFile; + ri.FS_FreeFile = FS_FreeFile; + ri.FS_Gamedir = FS_Gamedir; + ri.Cvar_Get = Cvar_Get; + ri.Cvar_Set = Cvar_Set; + ri.Cvar_SetValue = Cvar_SetValue; + ri.Vid_GetModeInfo = VID_GetModeInfo; + ri.Vid_MenuInit = VID_MenuInit; + ri.Vid_NewWindow = VID_NewWindow; + +#ifndef REF_HARD_LINKED + if ( ( GetRefAPI = (void *) dlsym( reflib_library, "GetRefAPI" ) ) == 0 ) + Com_Error( ERR_FATAL, "dlsym failed on %s", name ); +#endif + re = GetRefAPI( ri ); + + if (re.api_version != API_VERSION) + { + VID_FreeReflib (); + Com_Error (ERR_FATAL, "%s has incompatible api_version", name); + } + + /* Init IN (Mouse) */ + in_state.IN_CenterView_fp = IN_CenterView; + in_state.Key_Event_fp = Do_Key_Event; + in_state.viewangles = cl.viewangles; + in_state.in_strafe_state = &in_strafe.state; + +#ifndef REF_HARD_LINKED + if ((RW_IN_Init_fp = dlsym(reflib_library, "RW_IN_Init")) == NULL || + (RW_IN_Shutdown_fp = dlsym(reflib_library, "RW_IN_Shutdown")) == NULL || + (RW_IN_Activate_fp = dlsym(reflib_library, "RW_IN_Activate")) == NULL || + (RW_IN_Commands_fp = dlsym(reflib_library, "RW_IN_Commands")) == NULL || + (RW_IN_Move_fp = dlsym(reflib_library, "RW_IN_Move")) == NULL || + (RW_IN_Frame_fp = dlsym(reflib_library, "RW_IN_Frame")) == NULL) + Sys_Error("No RW_IN functions in REF.\n"); +#else + { + void RW_IN_Init(in_state_t *in_state_p); + void RW_IN_Shutdown(void); + void RW_IN_Commands (void); + void RW_IN_Move (usercmd_t *cmd); + void RW_IN_Frame (void); + void RW_IN_Activate(void); + + RW_IN_Init_fp = RW_IN_Init; + RW_IN_Shutdown_fp = RW_IN_Shutdown; + RW_IN_Activate_fp = RW_IN_Activate; + RW_IN_Commands_fp = RW_IN_Commands; + RW_IN_Move_fp = RW_IN_Move; + RW_IN_Frame_fp = RW_IN_Frame; + } +#endif + + if ( re.Init( 0, 0 ) == -1 ) + { + re.Shutdown(); + VID_FreeReflib (); + return false; + } + + // give up root now + setreuid(getuid(), getuid()); + setegid(getgid()); + + /* Init KBD */ +#ifndef REF_HARD_LINKED + if ((KBD_Init_fp = dlsym(reflib_library, "KBD_Init")) == NULL || + (KBD_Update_fp = dlsym(reflib_library, "KBD_Update")) == NULL || + (KBD_Close_fp = dlsym(reflib_library, "KBD_Close")) == NULL) + Sys_Error("No KBD functions in REF.\n"); +#else + { + void KBD_Init(void); + void KBD_Update(void); + void KBD_Close(void); + + KBD_Init_fp = KBD_Init; + KBD_Update_fp = KBD_Update; + KBD_Close_fp = KBD_Close; + } +#endif + KBD_Init_fp(Do_Key_Event); + Real_IN_Init(); + + Com_Printf( "------------------------------------\n"); + reflib_active = true; + return true; +} + +/* +============ +VID_CheckChanges + +This function gets called once just before drawing each frame, and it's sole purpose in life +is to check to see if any of the video mode parameters have changed, and if they have to +update the rendering DLL and/or video mode to match. +============ +*/ +void VID_CheckChanges (void) +{ + char name[100]; + cvar_t *sw_mode; + + if ( vid_ref->modified ) + { + S_StopAllSounds(); + } + + while (vid_ref->modified) + { + /* + ** refresh has changed + */ + vid_ref->modified = false; + vid_fullscreen->modified = true; + cl.refresh_prepped = false; + cls.disable_screen = true; + + sprintf( name, "ref_%s.so", vid_ref->string ); + if ( !VID_LoadRefresh( name ) ) + { + if ( strcmp (vid_ref->string, "soft") == 0 ) { + Com_Printf("Refresh failed\n"); + sw_mode = Cvar_Get( "sw_mode", "0", 0 ); + if (sw_mode->value != 0) { + Com_Printf("Trying mode 0\n"); + Cvar_SetValue("sw_mode", 0); + if ( !VID_LoadRefresh( name ) ) + Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!"); + } else + Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!"); + } + + Cvar_Set( "vid_ref", "soft" ); + + /* + ** drop the console if we fail to load a refresh + */ + if ( cls.key_dest != key_console ) + { + Con_ToggleConsole_f(); + } + } + cls.disable_screen = false; + } + +} + +/* +============ +VID_Init +============ +*/ +void VID_Init (void) +{ + /* Create the video variables so we know how to start the graphics drivers */ + vid_ref = Cvar_Get ("vid_ref", "soft", CVAR_ARCHIVE); + vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE); + vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE); + vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE); + vid_gamma = Cvar_Get( "vid_gamma", "1", CVAR_ARCHIVE ); + + /* Add some console commands that we want to handle */ + Cmd_AddCommand ("vid_restart", VID_Restart_f); + + /* Disable the 3Dfx splash screen */ + putenv("FX_GLIDE_NO_SPLASH=0"); + + /* Start the graphics mode and load refresh DLL */ + VID_CheckChanges(); +} + +/* +============ +VID_Shutdown +============ +*/ +void VID_Shutdown (void) +{ + if ( reflib_active ) + { + if (KBD_Close_fp) + KBD_Close_fp(); + if (RW_IN_Shutdown_fp) + RW_IN_Shutdown_fp(); + KBD_Close_fp = NULL; + RW_IN_Shutdown_fp = NULL; + re.Shutdown (); + VID_FreeReflib (); + } +} + + +/*****************************************************************************/ +/* INPUT */ +/*****************************************************************************/ + +cvar_t *in_joystick; + +// This if fake, it's acutally done by the Refresh load +void IN_Init (void) +{ + in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE); +} + +void Real_IN_Init (void) +{ + if (RW_IN_Init_fp) + RW_IN_Init_fp(&in_state); +} + +void IN_Shutdown (void) +{ + if (RW_IN_Shutdown_fp) + RW_IN_Shutdown_fp(); +} + +void IN_Commands (void) +{ + if (RW_IN_Commands_fp) + RW_IN_Commands_fp(); +} + +void IN_Move (usercmd_t *cmd) +{ + if (RW_IN_Move_fp) + RW_IN_Move_fp(cmd); +} + +void IN_Frame (void) +{ + if (RW_IN_Frame_fp) + RW_IN_Frame_fp(); +} + +void IN_Activate (qboolean active) +{ + if (RW_IN_Activate_fp) + RW_IN_Activate_fp(active); +} + +void Do_Key_Event(int key, qboolean down) +{ + Key_Event(key, down, Sys_Milliseconds()); +} + diff --git a/linux/Makefile.AXP b/linux/Makefile.AXP new file mode 100644 index 000000000..24d3d48c9 --- /dev/null +++ b/linux/Makefile.AXP @@ -0,0 +1,716 @@ +# +# Quake2 Makefile for Solaris +# +# Nov '97 by Zoid +# +# ELF only +# + +ARCH=axp + +MOUNT_DIR=/chest/Quake2/code + +BUILD_DEBUG_DIR=debug$(ARCH) +BUILD_RELEASE_DIR=release$(ARCH) +CLIENT_DIR=$(MOUNT_DIR)/client +SERVER_DIR=$(MOUNT_DIR)/server +COMMON_DIR=$(MOUNT_DIR)/qcommon +LINUX_DIR=$(MOUNT_DIR)/linux +GAME_DIR=$(MOUNT_DIR)/game +CTF_DIR=$(MOUNT_DIR)/ctf +XATRIX_DIR=$(MOUNT_DIR)/xatrix +NULL_DIR=$(MOUNT_DIR)/null + +CC=gcc +BASE_CFLAGS=-Dstricmp=strcasecmp -DC_ONLY -DDEDICATED_ONLY +RELEASE_CFLAGS=$(BASE_CFLAGS) -ffast-math -funroll-loops \ + -fomit-frame-pointer -fexpensive-optimizations +DEBUG_CFLAGS=$(BASE_CFLAGS) -g +LDFLAGS=-ldl -lm +XCFLAGS= + +SHLIBEXT=so + +SHLIBCFLAGS=-fPIC +SHLIBLDFLAGS=-shared + +DO_CC=$(CC) $(CFLAGS) -o $@ -c $< +DO_SHLIB_CC=$(CC) $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $< + +############################################################################# +# SETUP AND BUILD +############################################################################# + +TARGETS=$(BUILDDIR)/q2ded \ + $(BUILDDIR)/game$(ARCH).$(SHLIBEXT) \ + $(BUILDDIR)/ctf/game$(ARCH).$(SHLIBEXT) \ + $(BUILDDIR)/xatrix/game$(ARCH).$(SHLIBEXT) + +build_debug: + @-mkdir $(BUILD_DEBUG_DIR) \ + $(BUILD_DEBUG_DIR)/client \ + $(BUILD_DEBUG_DIR)/game \ + $(BUILD_DEBUG_DIR)/ctf \ + $(BUILD_DEBUG_DIR)/xatrix + $(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +build_release: + @-mkdir $(BUILD_RELEASE_DIR) \ + $(BUILD_RELEASE_DIR)/client \ + $(BUILD_RELEASE_DIR)/game \ + $(BUILD_RELEASE_DIR)/ctf \ + $(BUILD_RELEASE_DIR)/xatrix + $(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)" + +all: build_debug build_release + +targets: $(TARGETS) + +############################################################################# +# CLIENT/SERVER +############################################################################# + +QUAKE2_OBJS = \ + \ + $(BUILDDIR)/client/cmd.o \ + $(BUILDDIR)/client/cmodel.o \ + $(BUILDDIR)/client/common.o \ + $(BUILDDIR)/client/crc.o \ + $(BUILDDIR)/client/cvar.o \ + $(BUILDDIR)/client/files.o \ + $(BUILDDIR)/client/md4.o \ + $(BUILDDIR)/client/net_chan.o \ + \ + $(BUILDDIR)/client/sv_ccmds.o \ + $(BUILDDIR)/client/sv_ents.o \ + $(BUILDDIR)/client/sv_game.o \ + $(BUILDDIR)/client/sv_init.o \ + $(BUILDDIR)/client/sv_main.o \ + $(BUILDDIR)/client/sv_send.o \ + $(BUILDDIR)/client/sv_user.o \ + $(BUILDDIR)/client/sv_world.o \ + \ + $(BUILDDIR)/client/q_shlinux.o \ + $(BUILDDIR)/client/sys_linux.o \ + $(BUILDDIR)/client/glob.o \ + $(BUILDDIR)/client/net_udp.o \ + \ + $(BUILDDIR)/client/q_shared.o \ + $(BUILDDIR)/client/pmove.o \ + \ + $(BUILDDIR)/client/cl_null.o \ + $(BUILDDIR)/client/cd_null.o + +$(BUILDDIR)/q2ded : $(QUAKE2_OBJS) + $(CC) $(CFLAGS) -o $@ $(QUAKE2_OBJS) $(LDFLAGS) + +$(BUILDDIR)/client/cmd.o : $(COMMON_DIR)/cmd.c + $(DO_CC) + +$(BUILDDIR)/client/cmodel.o : $(COMMON_DIR)/cmodel.c + $(DO_CC) + +$(BUILDDIR)/client/common.o : $(COMMON_DIR)/common.c + $(DO_CC) + +$(BUILDDIR)/client/crc.o : $(COMMON_DIR)/crc.c + $(DO_CC) + +$(BUILDDIR)/client/cvar.o : $(COMMON_DIR)/cvar.c + $(DO_CC) + +$(BUILDDIR)/client/files.o : $(COMMON_DIR)/files.c + $(DO_CC) + +$(BUILDDIR)/client/md4.o : $(COMMON_DIR)/md4.c + $(DO_CC) + +$(BUILDDIR)/client/net_chan.o : $(COMMON_DIR)/net_chan.c + $(DO_CC) + +$(BUILDDIR)/client/q_shared.o : $(GAME_DIR)/q_shared.c + $(DO_CC) + +$(BUILDDIR)/client/pmove.o : $(COMMON_DIR)/pmove.c + $(DO_CC) + +$(BUILDDIR)/client/sv_ccmds.o : $(SERVER_DIR)/sv_ccmds.c + $(DO_CC) + +$(BUILDDIR)/client/sv_ents.o : $(SERVER_DIR)/sv_ents.c + $(DO_CC) + +$(BUILDDIR)/client/sv_game.o : $(SERVER_DIR)/sv_game.c + $(DO_CC) + +$(BUILDDIR)/client/sv_init.o : $(SERVER_DIR)/sv_init.c + $(DO_CC) + +$(BUILDDIR)/client/sv_main.o : $(SERVER_DIR)/sv_main.c + $(DO_CC) + +$(BUILDDIR)/client/sv_send.o : $(SERVER_DIR)/sv_send.c + $(DO_CC) + +$(BUILDDIR)/client/sv_user.o : $(SERVER_DIR)/sv_user.c + $(DO_CC) + +$(BUILDDIR)/client/sv_world.o : $(SERVER_DIR)/sv_world.c + $(DO_CC) + +$(BUILDDIR)/client/q_shlinux.o : $(LINUX_DIR)/q_shlinux.c + $(DO_CC) + +$(BUILDDIR)/client/sys_linux.o : $(LINUX_DIR)/sys_linux.c + $(DO_CC) + +$(BUILDDIR)/client/glob.o : $(LINUX_DIR)/glob.c + $(DO_CC) + +$(BUILDDIR)/client/net_udp.o : $(LINUX_DIR)/net_udp.c + $(DO_CC) + +$(BUILDDIR)/client/cd_null.o : $(NULL_DIR)/cd_null.c + $(DO_CC) + +$(BUILDDIR)/client/cl_null.o : $(NULL_DIR)/cl_null.c + $(DO_CC) + +############################################################################# +# GAME +############################################################################# + +GAME_OBJS = \ + $(BUILDDIR)/game/g_ai.o \ + $(BUILDDIR)/game/p_client.o \ + $(BUILDDIR)/game/g_cmds.o \ + $(BUILDDIR)/game/g_svcmds.o \ + $(BUILDDIR)/game/g_combat.o \ + $(BUILDDIR)/game/g_func.o \ + $(BUILDDIR)/game/g_items.o \ + $(BUILDDIR)/game/g_main.o \ + $(BUILDDIR)/game/g_misc.o \ + $(BUILDDIR)/game/g_monster.o \ + $(BUILDDIR)/game/g_phys.o \ + $(BUILDDIR)/game/g_save.o \ + $(BUILDDIR)/game/g_spawn.o \ + $(BUILDDIR)/game/g_target.o \ + $(BUILDDIR)/game/g_trigger.o \ + $(BUILDDIR)/game/g_turret.o \ + $(BUILDDIR)/game/g_utils.o \ + $(BUILDDIR)/game/g_weapon.o \ + $(BUILDDIR)/game/m_actor.o \ + $(BUILDDIR)/game/m_berserk.o \ + $(BUILDDIR)/game/m_boss2.o \ + $(BUILDDIR)/game/m_boss3.o \ + $(BUILDDIR)/game/m_boss31.o \ + $(BUILDDIR)/game/m_boss32.o \ + $(BUILDDIR)/game/m_brain.o \ + $(BUILDDIR)/game/m_chick.o \ + $(BUILDDIR)/game/m_flipper.o \ + $(BUILDDIR)/game/m_float.o \ + $(BUILDDIR)/game/m_flyer.o \ + $(BUILDDIR)/game/m_gladiator.o \ + $(BUILDDIR)/game/m_gunner.o \ + $(BUILDDIR)/game/m_hover.o \ + $(BUILDDIR)/game/m_infantry.o \ + $(BUILDDIR)/game/m_insane.o \ + $(BUILDDIR)/game/m_medic.o \ + $(BUILDDIR)/game/m_move.o \ + $(BUILDDIR)/game/m_mutant.o \ + $(BUILDDIR)/game/m_parasite.o \ + $(BUILDDIR)/game/m_soldier.o \ + $(BUILDDIR)/game/m_supertank.o \ + $(BUILDDIR)/game/m_tank.o \ + $(BUILDDIR)/game/p_hud.o \ + $(BUILDDIR)/game/p_trail.o \ + $(BUILDDIR)/game/p_view.o \ + $(BUILDDIR)/game/p_weapon.o \ + $(BUILDDIR)/game/q_shared.o \ + $(BUILDDIR)/game/m_flash.o + +$(BUILDDIR)/game$(ARCH).$(SHLIBEXT) : $(GAME_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(GAME_OBJS) + +$(BUILDDIR)/game/g_ai.o : $(GAME_DIR)/g_ai.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_client.o : $(GAME_DIR)/p_client.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_cmds.o : $(GAME_DIR)/g_cmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_svcmds.o : $(GAME_DIR)/g_svcmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_combat.o : $(GAME_DIR)/g_combat.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_func.o : $(GAME_DIR)/g_func.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_items.o : $(GAME_DIR)/g_items.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_main.o : $(GAME_DIR)/g_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_misc.o : $(GAME_DIR)/g_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_monster.o : $(GAME_DIR)/g_monster.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_phys.o : $(GAME_DIR)/g_phys.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_save.o : $(GAME_DIR)/g_save.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_spawn.o : $(GAME_DIR)/g_spawn.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_target.o : $(GAME_DIR)/g_target.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_trigger.o : $(GAME_DIR)/g_trigger.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_turret.o : $(GAME_DIR)/g_turret.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_utils.o : $(GAME_DIR)/g_utils.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_weapon.o : $(GAME_DIR)/g_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_actor.o : $(GAME_DIR)/m_actor.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_berserk.o : $(GAME_DIR)/m_berserk.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss2.o : $(GAME_DIR)/m_boss2.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss3.o : $(GAME_DIR)/m_boss3.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss31.o : $(GAME_DIR)/m_boss31.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss32.o : $(GAME_DIR)/m_boss32.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_brain.o : $(GAME_DIR)/m_brain.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_chick.o : $(GAME_DIR)/m_chick.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flipper.o : $(GAME_DIR)/m_flipper.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_float.o : $(GAME_DIR)/m_float.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flyer.o : $(GAME_DIR)/m_flyer.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_gladiator.o : $(GAME_DIR)/m_gladiator.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_gunner.o : $(GAME_DIR)/m_gunner.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_hover.o : $(GAME_DIR)/m_hover.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_infantry.o : $(GAME_DIR)/m_infantry.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_insane.o : $(GAME_DIR)/m_insane.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_medic.o : $(GAME_DIR)/m_medic.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_move.o : $(GAME_DIR)/m_move.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_mutant.o : $(GAME_DIR)/m_mutant.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_parasite.o : $(GAME_DIR)/m_parasite.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_soldier.o : $(GAME_DIR)/m_soldier.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_supertank.o : $(GAME_DIR)/m_supertank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_tank.o : $(GAME_DIR)/m_tank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_hud.o : $(GAME_DIR)/p_hud.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_trail.o : $(GAME_DIR)/p_trail.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_view.o : $(GAME_DIR)/p_view.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_weapon.o : $(GAME_DIR)/p_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/q_shared.o : $(GAME_DIR)/q_shared.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flash.o : $(GAME_DIR)/m_flash.c + $(DO_SHLIB_CC) + +############################################################################# +# CTF +############################################################################# + +CTF_OBJS = \ + $(BUILDDIR)/ctf/g_ai.o \ + $(BUILDDIR)/ctf/g_chase.o \ + $(BUILDDIR)/ctf/g_cmds.o \ + $(BUILDDIR)/ctf/g_combat.o \ + $(BUILDDIR)/ctf/g_ctf.o \ + $(BUILDDIR)/ctf/g_func.o \ + $(BUILDDIR)/ctf/g_items.o \ + $(BUILDDIR)/ctf/g_main.o \ + $(BUILDDIR)/ctf/g_misc.o \ + $(BUILDDIR)/ctf/g_monster.o \ + $(BUILDDIR)/ctf/g_phys.o \ + $(BUILDDIR)/ctf/g_save.o \ + $(BUILDDIR)/ctf/g_spawn.o \ + $(BUILDDIR)/ctf/g_svcmds.o \ + $(BUILDDIR)/ctf/g_target.o \ + $(BUILDDIR)/ctf/g_trigger.o \ + $(BUILDDIR)/ctf/g_utils.o \ + $(BUILDDIR)/ctf/g_weapon.o \ + $(BUILDDIR)/ctf/m_move.o \ + $(BUILDDIR)/ctf/p_client.o \ + $(BUILDDIR)/ctf/p_hud.o \ + $(BUILDDIR)/ctf/p_menu.o \ + $(BUILDDIR)/ctf/p_trail.o \ + $(BUILDDIR)/ctf/p_view.o \ + $(BUILDDIR)/ctf/p_weapon.o \ + $(BUILDDIR)/ctf/q_shared.o + +$(BUILDDIR)/ctf/game$(ARCH).$(SHLIBEXT) : $(CTF_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(CTF_OBJS) + +$(BUILDDIR)/ctf/g_ai.o : $(CTF_DIR)/g_ai.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_chase.o : $(CTF_DIR)/g_chase.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_cmds.o : $(CTF_DIR)/g_cmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_combat.o : $(CTF_DIR)/g_combat.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_ctf.o : $(CTF_DIR)/g_ctf.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_func.o : $(CTF_DIR)/g_func.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_items.o : $(CTF_DIR)/g_items.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_main.o : $(CTF_DIR)/g_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_misc.o : $(CTF_DIR)/g_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_monster.o : $(CTF_DIR)/g_monster.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_phys.o : $(CTF_DIR)/g_phys.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_save.o : $(CTF_DIR)/g_save.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_spawn.o : $(CTF_DIR)/g_spawn.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_svcmds.o : $(CTF_DIR)/g_svcmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_target.o : $(CTF_DIR)/g_target.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_trigger.o : $(CTF_DIR)/g_trigger.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_utils.o : $(CTF_DIR)/g_utils.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_weapon.o : $(CTF_DIR)/g_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/m_move.o : $(CTF_DIR)/m_move.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_client.o : $(CTF_DIR)/p_client.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_hud.o : $(CTF_DIR)/p_hud.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_menu.o : $(CTF_DIR)/p_menu.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_trail.o : $(CTF_DIR)/p_trail.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_view.o : $(CTF_DIR)/p_view.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_weapon.o : $(CTF_DIR)/p_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/q_shared.o : $(CTF_DIR)/q_shared.c + $(DO_SHLIB_CC) + +############################################################################# +# XATRIX +############################################################################# + +XATRIX_OBJS = \ + $(BUILDDIR)/xatrix/g_ai.o \ + $(BUILDDIR)/xatrix/g_cmds.o \ + $(BUILDDIR)/xatrix/g_combat.o \ + $(BUILDDIR)/xatrix/g_func.o \ + $(BUILDDIR)/xatrix/g_items.o \ + $(BUILDDIR)/xatrix/g_main.o \ + $(BUILDDIR)/xatrix/g_misc.o \ + $(BUILDDIR)/xatrix/g_monster.o \ + $(BUILDDIR)/xatrix/g_phys.o \ + $(BUILDDIR)/xatrix/g_save.o \ + $(BUILDDIR)/xatrix/g_spawn.o \ + $(BUILDDIR)/xatrix/g_svcmds.o \ + $(BUILDDIR)/xatrix/g_target.o \ + $(BUILDDIR)/xatrix/g_trigger.o \ + $(BUILDDIR)/xatrix/g_turret.o \ + $(BUILDDIR)/xatrix/g_utils.o \ + $(BUILDDIR)/xatrix/g_weapon.o \ + $(BUILDDIR)/xatrix/m_actor.o \ + $(BUILDDIR)/xatrix/m_berserk.o \ + $(BUILDDIR)/xatrix/m_boss2.o \ + $(BUILDDIR)/xatrix/m_boss3.o \ + $(BUILDDIR)/xatrix/m_boss31.o \ + $(BUILDDIR)/xatrix/m_boss32.o \ + $(BUILDDIR)/xatrix/m_boss5.o \ + $(BUILDDIR)/xatrix/m_brain.o \ + $(BUILDDIR)/xatrix/m_chick.o \ + $(BUILDDIR)/xatrix/m_fixbot.o \ + $(BUILDDIR)/xatrix/m_flash.o \ + $(BUILDDIR)/xatrix/m_flipper.o \ + $(BUILDDIR)/xatrix/m_float.o \ + $(BUILDDIR)/xatrix/m_flyer.o \ + $(BUILDDIR)/xatrix/m_gekk.o \ + $(BUILDDIR)/xatrix/m_gladb.o \ + $(BUILDDIR)/xatrix/m_gladiator.o \ + $(BUILDDIR)/xatrix/m_gunner.o \ + $(BUILDDIR)/xatrix/m_hover.o \ + $(BUILDDIR)/xatrix/m_infantry.o \ + $(BUILDDIR)/xatrix/m_insane.o \ + $(BUILDDIR)/xatrix/m_medic.o \ + $(BUILDDIR)/xatrix/m_move.o \ + $(BUILDDIR)/xatrix/m_mutant.o \ + $(BUILDDIR)/xatrix/m_parasite.o \ + $(BUILDDIR)/xatrix/m_soldier.o \ + $(BUILDDIR)/xatrix/m_supertank.o \ + $(BUILDDIR)/xatrix/m_tank.o \ + $(BUILDDIR)/xatrix/p_client.o \ + $(BUILDDIR)/xatrix/p_hud.o \ + $(BUILDDIR)/xatrix/p_trail.o \ + $(BUILDDIR)/xatrix/p_view.o \ + $(BUILDDIR)/xatrix/p_weapon.o \ + $(BUILDDIR)/xatrix/q_shared.o + +$(BUILDDIR)/xatrix/game$(ARCH).$(SHLIBEXT) : $(XATRIX_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(XATRIX_OBJS) + +$(BUILDDIR)/xatrix/g_ai.o : $(XATRIX_DIR)/g_ai.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_cmds.o : $(XATRIX_DIR)/g_cmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_combat.o : $(XATRIX_DIR)/g_combat.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_func.o : $(XATRIX_DIR)/g_func.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_items.o : $(XATRIX_DIR)/g_items.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_main.o : $(XATRIX_DIR)/g_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_misc.o : $(XATRIX_DIR)/g_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_monster.o : $(XATRIX_DIR)/g_monster.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_phys.o : $(XATRIX_DIR)/g_phys.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_save.o : $(XATRIX_DIR)/g_save.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_spawn.o : $(XATRIX_DIR)/g_spawn.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_svcmds.o : $(XATRIX_DIR)/g_svcmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_target.o : $(XATRIX_DIR)/g_target.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_trigger.o : $(XATRIX_DIR)/g_trigger.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_turret.o : $(XATRIX_DIR)/g_turret.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_utils.o : $(XATRIX_DIR)/g_utils.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_weapon.o : $(XATRIX_DIR)/g_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_actor.o : $(XATRIX_DIR)/m_actor.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_berserk.o : $(XATRIX_DIR)/m_berserk.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss2.o : $(XATRIX_DIR)/m_boss2.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss3.o : $(XATRIX_DIR)/m_boss3.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss31.o : $(XATRIX_DIR)/m_boss31.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss32.o : $(XATRIX_DIR)/m_boss32.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss5.o : $(XATRIX_DIR)/m_boss5.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_brain.o : $(XATRIX_DIR)/m_brain.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_chick.o : $(XATRIX_DIR)/m_chick.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_fixbot.o : $(XATRIX_DIR)/m_fixbot.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_flash.o : $(XATRIX_DIR)/m_flash.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_flipper.o : $(XATRIX_DIR)/m_flipper.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_float.o : $(XATRIX_DIR)/m_float.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_flyer.o : $(XATRIX_DIR)/m_flyer.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gekk.o : $(XATRIX_DIR)/m_gekk.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gladb.o : $(XATRIX_DIR)/m_gladb.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gladiator.o : $(XATRIX_DIR)/m_gladiator.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gunner.o : $(XATRIX_DIR)/m_gunner.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_hover.o : $(XATRIX_DIR)/m_hover.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_infantry.o : $(XATRIX_DIR)/m_infantry.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_insane.o : $(XATRIX_DIR)/m_insane.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_medic.o : $(XATRIX_DIR)/m_medic.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_move.o : $(XATRIX_DIR)/m_move.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_mutant.o : $(XATRIX_DIR)/m_mutant.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_parasite.o : $(XATRIX_DIR)/m_parasite.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_soldier.o : $(XATRIX_DIR)/m_soldier.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_supertank.o : $(XATRIX_DIR)/m_supertank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_tank.o : $(XATRIX_DIR)/m_tank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_client.o : $(XATRIX_DIR)/p_client.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_hud.o : $(XATRIX_DIR)/p_hud.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_trail.o : $(XATRIX_DIR)/p_trail.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_view.o : $(XATRIX_DIR)/p_view.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_weapon.o : $(XATRIX_DIR)/p_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/q_shared.o : $(XATRIX_DIR)/q_shared.c + $(DO_SHLIB_CC) + +############################################################################# +# MISC +############################################################################# + +clean: clean-debug clean-release + +clean-debug: + $(MAKE) clean2 BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +clean-release: + $(MAKE) clean2 BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +clean2: + -rm -f $(QUAKE2_OBJS) $(GAME_OBJS) $(CTF_OBJS) $(XATRIX_OBJS) + diff --git a/linux/Makefile.i386 b/linux/Makefile.i386 new file mode 100644 index 000000000..df7bdd1ea --- /dev/null +++ b/linux/Makefile.i386 @@ -0,0 +1,1085 @@ +# +# Quake2 Makefile for Linux 2.0 +# +# Nov '97 by Zoid +# +# ELF only +# + +ifneq (,$(findstring alpha,$(shell uname -m))) +ARCH=axp +else +ARCH=i386 +endif + +MOUNT_DIR=/grog/NewWork/Quake2/code + +BUILD_DEBUG_DIR=debug$(ARCH) +BUILD_RELEASE_DIR=release$(ARCH) +CLIENT_DIR=$(MOUNT_DIR)/client +SERVER_DIR=$(MOUNT_DIR)/server +REF_SOFT_DIR=$(MOUNT_DIR)/ref_soft +REF_GL_DIR=$(MOUNT_DIR)/ref_gl +COMMON_DIR=$(MOUNT_DIR)/qcommon +LINUX_DIR=$(MOUNT_DIR)/linux +GAME_DIR=$(MOUNT_DIR)/game +CTF_DIR=$(MOUNT_DIR)/ctf +XATRIX_DIR=$(MOUNT_DIR)/xatrix + +CC=gcc +BASE_CFLAGS=-Dstricmp=strcasecmp + +ifeq ($(ARCH),axp) +RELEASE_CFLAGS=$(BASE_CFLAGS) -ffast-math -funroll-loops \ + -fomit-frame-pointer -fexpensive-optimizations +else +RELEASE_CFLAGS=$(BASE_CFLAGS) -m486 -O6 -ffast-math -funroll-loops \ + -fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \ + -malign-jumps=2 -malign-functions=2 +endif + +DEBUG_CFLAGS=$(BASE_CFLAGS) -g +LDFLAGS=-ldl -lm +SVGALDFLAGS=-lvga +XLDFLAGS=-L/usr/X11R6/lib -lX11 -lXext +XCFLAGS= + +GLLDFLAGS=-L/usr/local/glide/lib -L/usr/X11/lib -L/usr/local/lib \ + -L/usr/local/src/Mesa-2.6/lib -lMesaGL -lglide2x -lX11 -lXext -lvga +GLCFLAGS=-I/usr/local/src/Mesa-2.6/include -I/usr/local/glide/include + +SHLIBEXT=so + +SHLIBCFLAGS=-fPIC +SHLIBLDFLAGS=-shared + +DO_CC=$(CC) $(CFLAGS) -o $@ -c $< +DO_SHLIB_CC=$(CC) $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $< +DO_GL_SHLIB_CC=$(CC) $(CFLAGS) $(SHLIBCFLAGS) $(GLCFLAGS) -o $@ -c $< +DO_AS=$(CC) $(CFLAGS) -DELF -x assembler-with-cpp -o $@ -c $< +DO_SHLIB_AS=$(CC) $(CFLAGS) $(SHLIBCFLAGS) -DELF -x assembler-with-cpp -o $@ -c $< + +############################################################################# +# SETUP AND BUILD +############################################################################# + +ifeq ($(ARCH),axp) +TARGETS=$(BUILDDIR)/quake2 \ + $(BUILDDIR)/game$(ARCH).$(SHLIBEXT) \ + $(BUILDDIR)/ctf/game$(ARCH).$(SHLIBEXT) \ + $(BUILDDIR)/xatrix/game$(ARCH).$(SHLIBEXT) +else +TARGETS=$(BUILDDIR)/quake2 \ + $(BUILDDIR)/game$(ARCH).$(SHLIBEXT) \ + $(BUILDDIR)/ref_soft.$(SHLIBEXT) \ + $(BUILDDIR)/ref_softx.$(SHLIBEXT) \ + $(BUILDDIR)/ref_gl.$(SHLIBEXT) \ + $(BUILDDIR)/ctf/game$(ARCH).$(SHLIBEXT) \ + $(BUILDDIR)/xatrix/game$(ARCH).$(SHLIBEXT) +endif + +build_debug: + @-mkdir $(BUILD_DEBUG_DIR) \ + $(BUILD_DEBUG_DIR)/client \ + $(BUILD_DEBUG_DIR)/ref_soft \ + $(BUILD_DEBUG_DIR)/ref_gl \ + $(BUILD_DEBUG_DIR)/game \ + $(BUILD_DEBUG_DIR)/ctf \ + $(BUILD_DEBUG_DIR)/xatrix + $(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +build_release: + @-mkdir $(BUILD_RELEASE_DIR) \ + $(BUILD_RELEASE_DIR)/client \ + $(BUILD_RELEASE_DIR)/ref_soft \ + $(BUILD_RELEASE_DIR)/ref_gl \ + $(BUILD_RELEASE_DIR)/game \ + $(BUILD_RELEASE_DIR)/ctf \ + $(BUILD_RELEASE_DIR)/xatrix + $(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)" + +all: build_debug build_release + +targets: $(TARGETS) + +############################################################################# +# CLIENT/SERVER +############################################################################# + +QUAKE2_OBJS = \ + $(BUILDDIR)/client/cl_cin.o \ + $(BUILDDIR)/client/cl_ents.o \ + $(BUILDDIR)/client/cl_fx.o \ + $(BUILDDIR)/client/cl_input.o \ + $(BUILDDIR)/client/cl_inv.o \ + $(BUILDDIR)/client/cl_main.o \ + $(BUILDDIR)/client/cl_parse.o \ + $(BUILDDIR)/client/cl_pred.o \ + $(BUILDDIR)/client/cl_tent.o \ + $(BUILDDIR)/client/cl_scrn.o \ + $(BUILDDIR)/client/cl_view.o \ + $(BUILDDIR)/client/console.o \ + $(BUILDDIR)/client/keys.o \ + $(BUILDDIR)/client/menu.o \ + $(BUILDDIR)/client/snd_dma.o \ + $(BUILDDIR)/client/snd_mem.o \ + $(BUILDDIR)/client/snd_mix.o \ + $(BUILDDIR)/client/qmenu.o \ + $(BUILDDIR)/client/m_flash.o \ + \ + $(BUILDDIR)/client/cmd.o \ + $(BUILDDIR)/client/cmodel.o \ + $(BUILDDIR)/client/common.o \ + $(BUILDDIR)/client/crc.o \ + $(BUILDDIR)/client/cvar.o \ + $(BUILDDIR)/client/files.o \ + $(BUILDDIR)/client/md4.o \ + $(BUILDDIR)/client/net_chan.o \ + \ + $(BUILDDIR)/client/sv_ccmds.o \ + $(BUILDDIR)/client/sv_ents.o \ + $(BUILDDIR)/client/sv_game.o \ + $(BUILDDIR)/client/sv_init.o \ + $(BUILDDIR)/client/sv_main.o \ + $(BUILDDIR)/client/sv_send.o \ + $(BUILDDIR)/client/sv_user.o \ + $(BUILDDIR)/client/sv_world.o \ + \ + $(BUILDDIR)/client/cd_linux.o \ + $(BUILDDIR)/client/q_shlinux.o \ + $(BUILDDIR)/client/vid_menu.o \ + $(BUILDDIR)/client/vid_so.o \ + $(BUILDDIR)/client/snd_linux.o \ + $(BUILDDIR)/client/sys_linux.o \ + $(BUILDDIR)/client/glob.o \ + $(BUILDDIR)/client/net_udp.o \ + \ + $(BUILDDIR)/client/q_shared.o \ + $(BUILDDIR)/client/pmove.o + +ifeq ($(ARCH),axp) +QUAKE2_AS_OBJS = #blank +else +QUAKE2_AS_OBJS = \ + $(BUILDDIR)/client/snd_mixa.o +endif + +$(BUILDDIR)/quake2 : $(QUAKE2_OBJS) $(QUAKE2_AS_OBJS) + $(CC) $(CFLAGS) -o $@ $(QUAKE2_OBJS) $(QUAKE2_AS_OBJS) $(LDFLAGS) + +$(BUILDDIR)/client/cl_cin.o : $(CLIENT_DIR)/cl_cin.c + $(DO_CC) + +$(BUILDDIR)/client/cl_ents.o : $(CLIENT_DIR)/cl_ents.c + $(DO_CC) + +$(BUILDDIR)/client/cl_fx.o : $(CLIENT_DIR)/cl_fx.c + $(DO_CC) + +$(BUILDDIR)/client/cl_input.o : $(CLIENT_DIR)/cl_input.c + $(DO_CC) + +$(BUILDDIR)/client/cl_inv.o : $(CLIENT_DIR)/cl_inv.c + $(DO_CC) + +$(BUILDDIR)/client/cl_main.o : $(CLIENT_DIR)/cl_main.c + $(DO_CC) + +$(BUILDDIR)/client/cl_parse.o : $(CLIENT_DIR)/cl_parse.c + $(DO_CC) + +$(BUILDDIR)/client/cl_pred.o : $(CLIENT_DIR)/cl_pred.c + $(DO_CC) + +$(BUILDDIR)/client/cl_tent.o : $(CLIENT_DIR)/cl_tent.c + $(DO_CC) + +$(BUILDDIR)/client/cl_scrn.o : $(CLIENT_DIR)/cl_scrn.c + $(DO_CC) + +$(BUILDDIR)/client/cl_view.o : $(CLIENT_DIR)/cl_view.c + $(DO_CC) + +$(BUILDDIR)/client/console.o : $(CLIENT_DIR)/console.c + $(DO_CC) + +$(BUILDDIR)/client/keys.o : $(CLIENT_DIR)/keys.c + $(DO_CC) + +$(BUILDDIR)/client/menu.o : $(CLIENT_DIR)/menu.c + $(DO_CC) + +$(BUILDDIR)/client/snd_dma.o : $(CLIENT_DIR)/snd_dma.c + $(DO_CC) + +$(BUILDDIR)/client/snd_mem.o : $(CLIENT_DIR)/snd_mem.c + $(DO_CC) + +$(BUILDDIR)/client/snd_mix.o : $(CLIENT_DIR)/snd_mix.c + $(DO_CC) + +$(BUILDDIR)/client/qmenu.o : $(CLIENT_DIR)/qmenu.c + $(DO_CC) + +$(BUILDDIR)/client/m_flash.o : $(GAME_DIR)/m_flash.c + $(DO_CC) + +$(BUILDDIR)/client/cmd.o : $(COMMON_DIR)/cmd.c + $(DO_CC) + +$(BUILDDIR)/client/cmodel.o : $(COMMON_DIR)/cmodel.c + $(DO_CC) + +$(BUILDDIR)/client/common.o : $(COMMON_DIR)/common.c + $(DO_CC) + +$(BUILDDIR)/client/crc.o : $(COMMON_DIR)/crc.c + $(DO_CC) + +$(BUILDDIR)/client/cvar.o : $(COMMON_DIR)/cvar.c + $(DO_CC) + +$(BUILDDIR)/client/files.o : $(COMMON_DIR)/files.c + $(DO_CC) + +$(BUILDDIR)/client/md4.o : $(COMMON_DIR)/md4.c + $(DO_CC) + +$(BUILDDIR)/client/net_chan.o : $(COMMON_DIR)/net_chan.c + $(DO_CC) + +$(BUILDDIR)/client/q_shared.o : $(GAME_DIR)/q_shared.c + $(DO_CC) + +$(BUILDDIR)/client/pmove.o : $(COMMON_DIR)/pmove.c + $(DO_CC) + +$(BUILDDIR)/client/sv_ccmds.o : $(SERVER_DIR)/sv_ccmds.c + $(DO_CC) + +$(BUILDDIR)/client/sv_ents.o : $(SERVER_DIR)/sv_ents.c + $(DO_CC) + +$(BUILDDIR)/client/sv_game.o : $(SERVER_DIR)/sv_game.c + $(DO_CC) + +$(BUILDDIR)/client/sv_init.o : $(SERVER_DIR)/sv_init.c + $(DO_CC) + +$(BUILDDIR)/client/sv_main.o : $(SERVER_DIR)/sv_main.c + $(DO_CC) + +$(BUILDDIR)/client/sv_send.o : $(SERVER_DIR)/sv_send.c + $(DO_CC) + +$(BUILDDIR)/client/sv_user.o : $(SERVER_DIR)/sv_user.c + $(DO_CC) + +$(BUILDDIR)/client/sv_world.o : $(SERVER_DIR)/sv_world.c + $(DO_CC) + +$(BUILDDIR)/client/cd_linux.o : $(LINUX_DIR)/cd_linux.c + $(DO_CC) + +$(BUILDDIR)/client/q_shlinux.o : $(LINUX_DIR)/q_shlinux.c + $(DO_CC) + +$(BUILDDIR)/client/vid_menu.o : $(LINUX_DIR)/vid_menu.c + $(DO_CC) + +$(BUILDDIR)/client/vid_so.o : $(LINUX_DIR)/vid_so.c + $(DO_CC) + +$(BUILDDIR)/client/snd_linux.o : $(LINUX_DIR)/snd_linux.c + $(DO_CC) + +$(BUILDDIR)/client/snd_mixa.o : $(LINUX_DIR)/snd_mixa.s + $(DO_AS) + +$(BUILDDIR)/client/sys_linux.o : $(LINUX_DIR)/sys_linux.c + $(DO_CC) + +$(BUILDDIR)/client/glob.o : $(LINUX_DIR)/glob.c + $(DO_CC) + +$(BUILDDIR)/client/net_udp.o : $(LINUX_DIR)/net_udp.c + $(DO_CC) + +############################################################################# +# GAME +############################################################################# + +GAME_OBJS = \ + $(BUILDDIR)/game/g_ai.o \ + $(BUILDDIR)/game/p_client.o \ + $(BUILDDIR)/game/g_cmds.o \ + $(BUILDDIR)/game/g_svcmds.o \ + $(BUILDDIR)/game/g_combat.o \ + $(BUILDDIR)/game/g_func.o \ + $(BUILDDIR)/game/g_items.o \ + $(BUILDDIR)/game/g_main.o \ + $(BUILDDIR)/game/g_misc.o \ + $(BUILDDIR)/game/g_monster.o \ + $(BUILDDIR)/game/g_phys.o \ + $(BUILDDIR)/game/g_save.o \ + $(BUILDDIR)/game/g_spawn.o \ + $(BUILDDIR)/game/g_target.o \ + $(BUILDDIR)/game/g_trigger.o \ + $(BUILDDIR)/game/g_turret.o \ + $(BUILDDIR)/game/g_utils.o \ + $(BUILDDIR)/game/g_weapon.o \ + $(BUILDDIR)/game/m_actor.o \ + $(BUILDDIR)/game/m_berserk.o \ + $(BUILDDIR)/game/m_boss2.o \ + $(BUILDDIR)/game/m_boss3.o \ + $(BUILDDIR)/game/m_boss31.o \ + $(BUILDDIR)/game/m_boss32.o \ + $(BUILDDIR)/game/m_brain.o \ + $(BUILDDIR)/game/m_chick.o \ + $(BUILDDIR)/game/m_flipper.o \ + $(BUILDDIR)/game/m_float.o \ + $(BUILDDIR)/game/m_flyer.o \ + $(BUILDDIR)/game/m_gladiator.o \ + $(BUILDDIR)/game/m_gunner.o \ + $(BUILDDIR)/game/m_hover.o \ + $(BUILDDIR)/game/m_infantry.o \ + $(BUILDDIR)/game/m_insane.o \ + $(BUILDDIR)/game/m_medic.o \ + $(BUILDDIR)/game/m_move.o \ + $(BUILDDIR)/game/m_mutant.o \ + $(BUILDDIR)/game/m_parasite.o \ + $(BUILDDIR)/game/m_soldier.o \ + $(BUILDDIR)/game/m_supertank.o \ + $(BUILDDIR)/game/m_tank.o \ + $(BUILDDIR)/game/p_hud.o \ + $(BUILDDIR)/game/p_trail.o \ + $(BUILDDIR)/game/p_view.o \ + $(BUILDDIR)/game/p_weapon.o \ + $(BUILDDIR)/game/q_shared.o \ + $(BUILDDIR)/game/m_flash.o + +$(BUILDDIR)/game$(ARCH).$(SHLIBEXT) : $(GAME_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(GAME_OBJS) + +$(BUILDDIR)/game/g_ai.o : $(GAME_DIR)/g_ai.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_client.o : $(GAME_DIR)/p_client.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_cmds.o : $(GAME_DIR)/g_cmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_svcmds.o : $(GAME_DIR)/g_svcmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_combat.o : $(GAME_DIR)/g_combat.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_func.o : $(GAME_DIR)/g_func.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_items.o : $(GAME_DIR)/g_items.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_main.o : $(GAME_DIR)/g_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_misc.o : $(GAME_DIR)/g_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_monster.o : $(GAME_DIR)/g_monster.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_phys.o : $(GAME_DIR)/g_phys.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_save.o : $(GAME_DIR)/g_save.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_spawn.o : $(GAME_DIR)/g_spawn.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_target.o : $(GAME_DIR)/g_target.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_trigger.o : $(GAME_DIR)/g_trigger.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_turret.o : $(GAME_DIR)/g_turret.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_utils.o : $(GAME_DIR)/g_utils.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/g_weapon.o : $(GAME_DIR)/g_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_actor.o : $(GAME_DIR)/m_actor.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_berserk.o : $(GAME_DIR)/m_berserk.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss2.o : $(GAME_DIR)/m_boss2.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss3.o : $(GAME_DIR)/m_boss3.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss31.o : $(GAME_DIR)/m_boss31.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_boss32.o : $(GAME_DIR)/m_boss32.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_brain.o : $(GAME_DIR)/m_brain.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_chick.o : $(GAME_DIR)/m_chick.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flipper.o : $(GAME_DIR)/m_flipper.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_float.o : $(GAME_DIR)/m_float.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flyer.o : $(GAME_DIR)/m_flyer.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_gladiator.o : $(GAME_DIR)/m_gladiator.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_gunner.o : $(GAME_DIR)/m_gunner.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_hover.o : $(GAME_DIR)/m_hover.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_infantry.o : $(GAME_DIR)/m_infantry.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_insane.o : $(GAME_DIR)/m_insane.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_medic.o : $(GAME_DIR)/m_medic.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_move.o : $(GAME_DIR)/m_move.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_mutant.o : $(GAME_DIR)/m_mutant.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_parasite.o : $(GAME_DIR)/m_parasite.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_soldier.o : $(GAME_DIR)/m_soldier.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_supertank.o : $(GAME_DIR)/m_supertank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_tank.o : $(GAME_DIR)/m_tank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_hud.o : $(GAME_DIR)/p_hud.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_trail.o : $(GAME_DIR)/p_trail.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_view.o : $(GAME_DIR)/p_view.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/p_weapon.o : $(GAME_DIR)/p_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/q_shared.o : $(GAME_DIR)/q_shared.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/game/m_flash.o : $(GAME_DIR)/m_flash.c + $(DO_SHLIB_CC) + +############################################################################# +# CTF +############################################################################# + +CTF_OBJS = \ + $(BUILDDIR)/ctf/g_ai.o \ + $(BUILDDIR)/ctf/g_chase.o \ + $(BUILDDIR)/ctf/g_cmds.o \ + $(BUILDDIR)/ctf/g_combat.o \ + $(BUILDDIR)/ctf/g_ctf.o \ + $(BUILDDIR)/ctf/g_func.o \ + $(BUILDDIR)/ctf/g_items.o \ + $(BUILDDIR)/ctf/g_main.o \ + $(BUILDDIR)/ctf/g_misc.o \ + $(BUILDDIR)/ctf/g_monster.o \ + $(BUILDDIR)/ctf/g_phys.o \ + $(BUILDDIR)/ctf/g_save.o \ + $(BUILDDIR)/ctf/g_spawn.o \ + $(BUILDDIR)/ctf/g_svcmds.o \ + $(BUILDDIR)/ctf/g_target.o \ + $(BUILDDIR)/ctf/g_trigger.o \ + $(BUILDDIR)/ctf/g_utils.o \ + $(BUILDDIR)/ctf/g_weapon.o \ + $(BUILDDIR)/ctf/m_move.o \ + $(BUILDDIR)/ctf/p_client.o \ + $(BUILDDIR)/ctf/p_hud.o \ + $(BUILDDIR)/ctf/p_menu.o \ + $(BUILDDIR)/ctf/p_trail.o \ + $(BUILDDIR)/ctf/p_view.o \ + $(BUILDDIR)/ctf/p_weapon.o \ + $(BUILDDIR)/ctf/q_shared.o + +$(BUILDDIR)/ctf/game$(ARCH).$(SHLIBEXT) : $(CTF_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(CTF_OBJS) + +$(BUILDDIR)/ctf/g_ai.o : $(CTF_DIR)/g_ai.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_chase.o : $(CTF_DIR)/g_chase.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_cmds.o : $(CTF_DIR)/g_cmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_combat.o : $(CTF_DIR)/g_combat.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_ctf.o : $(CTF_DIR)/g_ctf.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_func.o : $(CTF_DIR)/g_func.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_items.o : $(CTF_DIR)/g_items.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_main.o : $(CTF_DIR)/g_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_misc.o : $(CTF_DIR)/g_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_monster.o : $(CTF_DIR)/g_monster.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_phys.o : $(CTF_DIR)/g_phys.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_save.o : $(CTF_DIR)/g_save.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_spawn.o : $(CTF_DIR)/g_spawn.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_svcmds.o : $(CTF_DIR)/g_svcmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_target.o : $(CTF_DIR)/g_target.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_trigger.o : $(CTF_DIR)/g_trigger.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_utils.o : $(CTF_DIR)/g_utils.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/g_weapon.o : $(CTF_DIR)/g_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/m_move.o : $(CTF_DIR)/m_move.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_client.o : $(CTF_DIR)/p_client.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_hud.o : $(CTF_DIR)/p_hud.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_menu.o : $(CTF_DIR)/p_menu.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_trail.o : $(CTF_DIR)/p_trail.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_view.o : $(CTF_DIR)/p_view.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/p_weapon.o : $(CTF_DIR)/p_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ctf/q_shared.o : $(CTF_DIR)/q_shared.c + $(DO_SHLIB_CC) + +############################################################################# +# XATRIX +############################################################################# + +XATRIX_OBJS = \ + $(BUILDDIR)/xatrix/g_ai.o \ + $(BUILDDIR)/xatrix/g_cmds.o \ + $(BUILDDIR)/xatrix/g_combat.o \ + $(BUILDDIR)/xatrix/g_func.o \ + $(BUILDDIR)/xatrix/g_items.o \ + $(BUILDDIR)/xatrix/g_main.o \ + $(BUILDDIR)/xatrix/g_misc.o \ + $(BUILDDIR)/xatrix/g_monster.o \ + $(BUILDDIR)/xatrix/g_phys.o \ + $(BUILDDIR)/xatrix/g_save.o \ + $(BUILDDIR)/xatrix/g_spawn.o \ + $(BUILDDIR)/xatrix/g_svcmds.o \ + $(BUILDDIR)/xatrix/g_target.o \ + $(BUILDDIR)/xatrix/g_trigger.o \ + $(BUILDDIR)/xatrix/g_turret.o \ + $(BUILDDIR)/xatrix/g_utils.o \ + $(BUILDDIR)/xatrix/g_weapon.o \ + $(BUILDDIR)/xatrix/m_actor.o \ + $(BUILDDIR)/xatrix/m_berserk.o \ + $(BUILDDIR)/xatrix/m_boss2.o \ + $(BUILDDIR)/xatrix/m_boss3.o \ + $(BUILDDIR)/xatrix/m_boss31.o \ + $(BUILDDIR)/xatrix/m_boss32.o \ + $(BUILDDIR)/xatrix/m_boss5.o \ + $(BUILDDIR)/xatrix/m_brain.o \ + $(BUILDDIR)/xatrix/m_chick.o \ + $(BUILDDIR)/xatrix/m_fixbot.o \ + $(BUILDDIR)/xatrix/m_flash.o \ + $(BUILDDIR)/xatrix/m_flipper.o \ + $(BUILDDIR)/xatrix/m_float.o \ + $(BUILDDIR)/xatrix/m_flyer.o \ + $(BUILDDIR)/xatrix/m_gekk.o \ + $(BUILDDIR)/xatrix/m_gladb.o \ + $(BUILDDIR)/xatrix/m_gladiator.o \ + $(BUILDDIR)/xatrix/m_gunner.o \ + $(BUILDDIR)/xatrix/m_hover.o \ + $(BUILDDIR)/xatrix/m_infantry.o \ + $(BUILDDIR)/xatrix/m_insane.o \ + $(BUILDDIR)/xatrix/m_medic.o \ + $(BUILDDIR)/xatrix/m_move.o \ + $(BUILDDIR)/xatrix/m_mutant.o \ + $(BUILDDIR)/xatrix/m_parasite.o \ + $(BUILDDIR)/xatrix/m_soldier.o \ + $(BUILDDIR)/xatrix/m_supertank.o \ + $(BUILDDIR)/xatrix/m_tank.o \ + $(BUILDDIR)/xatrix/p_client.o \ + $(BUILDDIR)/xatrix/p_hud.o \ + $(BUILDDIR)/xatrix/p_trail.o \ + $(BUILDDIR)/xatrix/p_view.o \ + $(BUILDDIR)/xatrix/p_weapon.o \ + $(BUILDDIR)/xatrix/q_shared.o + +$(BUILDDIR)/xatrix/game$(ARCH).$(SHLIBEXT) : $(XATRIX_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(XATRIX_OBJS) + +$(BUILDDIR)/xatrix/g_ai.o : $(XATRIX_DIR)/g_ai.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_cmds.o : $(XATRIX_DIR)/g_cmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_combat.o : $(XATRIX_DIR)/g_combat.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_func.o : $(XATRIX_DIR)/g_func.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_items.o : $(XATRIX_DIR)/g_items.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_main.o : $(XATRIX_DIR)/g_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_misc.o : $(XATRIX_DIR)/g_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_monster.o : $(XATRIX_DIR)/g_monster.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_phys.o : $(XATRIX_DIR)/g_phys.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_save.o : $(XATRIX_DIR)/g_save.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_spawn.o : $(XATRIX_DIR)/g_spawn.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_svcmds.o : $(XATRIX_DIR)/g_svcmds.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_target.o : $(XATRIX_DIR)/g_target.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_trigger.o : $(XATRIX_DIR)/g_trigger.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_turret.o : $(XATRIX_DIR)/g_turret.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_utils.o : $(XATRIX_DIR)/g_utils.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/g_weapon.o : $(XATRIX_DIR)/g_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_actor.o : $(XATRIX_DIR)/m_actor.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_berserk.o : $(XATRIX_DIR)/m_berserk.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss2.o : $(XATRIX_DIR)/m_boss2.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss3.o : $(XATRIX_DIR)/m_boss3.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss31.o : $(XATRIX_DIR)/m_boss31.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss32.o : $(XATRIX_DIR)/m_boss32.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_boss5.o : $(XATRIX_DIR)/m_boss5.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_brain.o : $(XATRIX_DIR)/m_brain.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_chick.o : $(XATRIX_DIR)/m_chick.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_fixbot.o : $(XATRIX_DIR)/m_fixbot.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_flash.o : $(XATRIX_DIR)/m_flash.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_flipper.o : $(XATRIX_DIR)/m_flipper.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_float.o : $(XATRIX_DIR)/m_float.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_flyer.o : $(XATRIX_DIR)/m_flyer.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gekk.o : $(XATRIX_DIR)/m_gekk.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gladb.o : $(XATRIX_DIR)/m_gladb.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gladiator.o : $(XATRIX_DIR)/m_gladiator.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_gunner.o : $(XATRIX_DIR)/m_gunner.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_hover.o : $(XATRIX_DIR)/m_hover.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_infantry.o : $(XATRIX_DIR)/m_infantry.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_insane.o : $(XATRIX_DIR)/m_insane.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_medic.o : $(XATRIX_DIR)/m_medic.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_move.o : $(XATRIX_DIR)/m_move.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_mutant.o : $(XATRIX_DIR)/m_mutant.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_parasite.o : $(XATRIX_DIR)/m_parasite.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_soldier.o : $(XATRIX_DIR)/m_soldier.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_supertank.o : $(XATRIX_DIR)/m_supertank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/m_tank.o : $(XATRIX_DIR)/m_tank.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_client.o : $(XATRIX_DIR)/p_client.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_hud.o : $(XATRIX_DIR)/p_hud.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_trail.o : $(XATRIX_DIR)/p_trail.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_view.o : $(XATRIX_DIR)/p_view.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/p_weapon.o : $(XATRIX_DIR)/p_weapon.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/xatrix/q_shared.o : $(XATRIX_DIR)/q_shared.c + $(DO_SHLIB_CC) + + +############################################################################# +# REF_SOFT +############################################################################# + +REF_SOFT_OBJS = \ + $(BUILDDIR)/ref_soft/r_aclip.o \ + $(BUILDDIR)/ref_soft/r_alias.o \ + $(BUILDDIR)/ref_soft/r_bsp.o \ + $(BUILDDIR)/ref_soft/r_draw.o \ + $(BUILDDIR)/ref_soft/r_edge.o \ + $(BUILDDIR)/ref_soft/r_image.o \ + $(BUILDDIR)/ref_soft/r_light.o \ + $(BUILDDIR)/ref_soft/r_main.o \ + $(BUILDDIR)/ref_soft/r_misc.o \ + $(BUILDDIR)/ref_soft/r_model.o \ + $(BUILDDIR)/ref_soft/r_part.o \ + $(BUILDDIR)/ref_soft/r_poly.o \ + $(BUILDDIR)/ref_soft/r_polyse.o \ + $(BUILDDIR)/ref_soft/r_rast.o \ + $(BUILDDIR)/ref_soft/r_scan.o \ + $(BUILDDIR)/ref_soft/r_sprite.o \ + $(BUILDDIR)/ref_soft/r_surf.o \ + \ + $(BUILDDIR)/ref_soft/r_aclipa.o \ + $(BUILDDIR)/ref_soft/r_draw16.o \ + $(BUILDDIR)/ref_soft/r_drawa.o \ + $(BUILDDIR)/ref_soft/r_edgea.o \ + $(BUILDDIR)/ref_soft/r_scana.o \ + $(BUILDDIR)/ref_soft/r_spr8.o \ + $(BUILDDIR)/ref_soft/r_surf8.o \ + $(BUILDDIR)/ref_soft/math.o \ + $(BUILDDIR)/ref_soft/d_polysa.o \ + $(BUILDDIR)/ref_soft/r_varsa.o \ + $(BUILDDIR)/ref_soft/sys_dosa.o \ + \ + $(BUILDDIR)/ref_soft/q_shared.o \ + $(BUILDDIR)/ref_soft/q_shlinux.o \ + $(BUILDDIR)/ref_soft/glob.o + +REF_SOFT_SVGA_OBJS = \ + $(BUILDDIR)/ref_soft/rw_svgalib.o \ + $(BUILDDIR)/ref_soft/d_copy.o \ + $(BUILDDIR)/ref_soft/rw_in_svgalib.o + +REF_SOFT_X11_OBJS = \ + $(BUILDDIR)/ref_soft/rw_x11.o + +$(BUILDDIR)/ref_soft.$(SHLIBEXT) : $(REF_SOFT_OBJS) $(REF_SOFT_SVGA_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(REF_SOFT_OBJS) \ + $(REF_SOFT_SVGA_OBJS) $(SVGALDFLAGS) + +$(BUILDDIR)/ref_softx.$(SHLIBEXT) : $(REF_SOFT_OBJS) $(REF_SOFT_X11_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(REF_SOFT_OBJS) \ + $(REF_SOFT_X11_OBJS) $(XLDFLAGS) + +$(BUILDDIR)/ref_soft/r_aclip.o : $(REF_SOFT_DIR)/r_aclip.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_alias.o : $(REF_SOFT_DIR)/r_alias.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_bsp.o : $(REF_SOFT_DIR)/r_bsp.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_draw.o : $(REF_SOFT_DIR)/r_draw.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_edge.o : $(REF_SOFT_DIR)/r_edge.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_image.o : $(REF_SOFT_DIR)/r_image.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_light.o : $(REF_SOFT_DIR)/r_light.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_main.o : $(REF_SOFT_DIR)/r_main.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_misc.o : $(REF_SOFT_DIR)/r_misc.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_model.o : $(REF_SOFT_DIR)/r_model.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_part.o : $(REF_SOFT_DIR)/r_part.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_poly.o : $(REF_SOFT_DIR)/r_poly.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_polyse.o : $(REF_SOFT_DIR)/r_polyse.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_rast.o : $(REF_SOFT_DIR)/r_rast.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_scan.o : $(REF_SOFT_DIR)/r_scan.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_sprite.o : $(REF_SOFT_DIR)/r_sprite.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_surf.o : $(REF_SOFT_DIR)/r_surf.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/r_aclipa.o : $(LINUX_DIR)/r_aclipa.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/r_draw16.o : $(LINUX_DIR)/r_draw16.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/r_drawa.o : $(LINUX_DIR)/r_drawa.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/r_edgea.o : $(LINUX_DIR)/r_edgea.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/r_scana.o : $(LINUX_DIR)/r_scana.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/r_spr8.o : $(LINUX_DIR)/r_spr8.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/r_surf8.o : $(LINUX_DIR)/r_surf8.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/math.o : $(LINUX_DIR)/math.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/d_polysa.o : $(LINUX_DIR)/d_polysa.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/r_varsa.o : $(LINUX_DIR)/r_varsa.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/sys_dosa.o : $(LINUX_DIR)/sys_dosa.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/q_shared.o : $(GAME_DIR)/q_shared.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/q_shlinux.o : $(LINUX_DIR)/q_shlinux.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/glob.o : $(LINUX_DIR)/glob.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/rw_svgalib.o : $(LINUX_DIR)/rw_svgalib.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/d_copy.o : $(LINUX_DIR)/d_copy.s + $(DO_SHLIB_AS) + +$(BUILDDIR)/ref_soft/rw_in_svgalib.o : $(LINUX_DIR)/rw_in_svgalib.c + $(DO_SHLIB_CC) + +$(BUILDDIR)/ref_soft/rw_x11.o : $(LINUX_DIR)/rw_x11.c + $(DO_SHLIB_CC) + +############################################################################# +# REF_GL +############################################################################# + +REF_GL_OBJS = \ + $(BUILDDIR)/ref_gl/gl_draw.o \ + $(BUILDDIR)/ref_gl/gl_image.o \ + $(BUILDDIR)/ref_gl/gl_light.o \ + $(BUILDDIR)/ref_gl/gl_mesh.o \ + $(BUILDDIR)/ref_gl/gl_model.o \ + $(BUILDDIR)/ref_gl/gl_rmain.o \ + $(BUILDDIR)/ref_gl/gl_rmisc.o \ + $(BUILDDIR)/ref_gl/gl_rsurf.o \ + $(BUILDDIR)/ref_gl/gl_warp.o \ + \ + $(BUILDDIR)/ref_gl/qgl_linux.o \ + $(BUILDDIR)/ref_gl/gl_fxmesa.o \ + $(BUILDDIR)/ref_gl/rw_in_svgalib.o \ + $(BUILDDIR)/ref_gl/q_shared.o \ + $(BUILDDIR)/ref_gl/q_shlinux.o \ + $(BUILDDIR)/ref_gl/glob.o + +$(BUILDDIR)/ref_gl.$(SHLIBEXT) : $(REF_GL_OBJS) + $(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(REF_GL_OBJS) $(GLLDFLAGS) + +$(BUILDDIR)/ref_gl/gl_draw.o : $(REF_GL_DIR)/gl_draw.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/gl_image.o : $(REF_GL_DIR)/gl_image.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/gl_light.o : $(REF_GL_DIR)/gl_light.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/gl_mesh.o : $(REF_GL_DIR)/gl_mesh.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/gl_model.o : $(REF_GL_DIR)/gl_model.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/gl_rmain.o : $(REF_GL_DIR)/gl_rmain.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/gl_rmisc.o : $(REF_GL_DIR)/gl_rmisc.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/gl_rsurf.o : $(REF_GL_DIR)/gl_rsurf.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/gl_warp.o : $(REF_GL_DIR)/gl_warp.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/qgl_linux.o : $(LINUX_DIR)/qgl_linux.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/gl_fxmesa.o : $(LINUX_DIR)/gl_fxmesa.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/rw_in_svgalib.o : $(LINUX_DIR)/rw_in_svgalib.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/q_shared.o : $(GAME_DIR)/q_shared.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/q_shlinux.o : $(LINUX_DIR)/q_shlinux.c + $(DO_GL_SHLIB_CC) + +$(BUILDDIR)/ref_gl/glob.o : $(LINUX_DIR)/glob.c + $(DO_GL_SHLIB_CC) + +############################################################################# +# MISC +############################################################################# + +clean: clean-debug clean-release + +clean-debug: + $(MAKE) clean2 BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +clean-release: + $(MAKE) clean2 BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(DEBUG_CFLAGS)" + +clean2: + -rm -f \ + $(QUAKE2_OBJS) \ + $(QUAKE2_AS_OBJS) \ + $(GAME_OBJS) \ + $(CTF_OBJS) \ + $(XATRIX_OBJS) \ + $(REF_SOFT_OBJS) \ + $(REF_SOFT_SVGA_OBJS) \ + $(REF_SOFT_X11_OBJS) \ + $(REF_GL_OBJS) + diff --git a/linux/block16.h b/linux/block16.h new file mode 100644 index 000000000..98a1cf707 --- /dev/null +++ b/linux/block16.h @@ -0,0 +1,123 @@ +LEnter16_16: + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movw 0x12345678(,%eax,2),%ax +LBPatch0: + addl %ebp,%edx + movw %ax,(%edi) + movw 0x12345678(,%ecx,2),%cx +LBPatch1: + movw %cx,2(%edi) + addl $0x4,%edi + + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movw 0x12345678(,%eax,2),%ax +LBPatch2: + addl %ebp,%edx + movw %ax,(%edi) + movw 0x12345678(,%ecx,2),%cx +LBPatch3: + movw %cx,2(%edi) + addl $0x4,%edi + + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movw 0x12345678(,%eax,2),%ax +LBPatch4: + addl %ebp,%edx + movw %ax,(%edi) + movw 0x12345678(,%ecx,2),%cx +LBPatch5: + movw %cx,2(%edi) + addl $0x4,%edi + + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movw 0x12345678(,%eax,2),%ax +LBPatch6: + addl %ebp,%edx + movw %ax,(%edi) + movw 0x12345678(,%ecx,2),%cx +LBPatch7: + movw %cx,2(%edi) + addl $0x4,%edi + +LEnter8_16: + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movw 0x12345678(,%eax,2),%ax +LBPatch8: + addl %ebp,%edx + movw %ax,(%edi) + movw 0x12345678(,%ecx,2),%cx +LBPatch9: + movw %cx,2(%edi) + addl $0x4,%edi + + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movw 0x12345678(,%eax,2),%ax +LBPatch10: + addl %ebp,%edx + movw %ax,(%edi) + movw 0x12345678(,%ecx,2),%cx +LBPatch11: + movw %cx,2(%edi) + addl $0x4,%edi + +LEnter4_16: + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movw 0x12345678(,%eax,2),%ax +LBPatch12: + addl %ebp,%edx + movw %ax,(%edi) + movw 0x12345678(,%ecx,2),%cx +LBPatch13: + movw %cx,2(%edi) + addl $0x4,%edi + +LEnter2_16: + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movw 0x12345678(,%eax,2),%ax +LBPatch14: + addl %ebp,%edx + movw %ax,(%edi) + movw 0x12345678(,%ecx,2),%cx +LBPatch15: + movw %cx,2(%edi) + addl $0x4,%edi diff --git a/linux/block8.h b/linux/block8.h new file mode 100644 index 000000000..d501379ab --- /dev/null +++ b/linux/block8.h @@ -0,0 +1,124 @@ +LEnter16_8: + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movb 0x12345678(%eax),%al +LBPatch0: + addl %ebp,%edx + movb %al,(%edi) + movb 0x12345678(%ecx),%cl +LBPatch1: + movb %cl,1(%edi) + addl $0x2,%edi + + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movb 0x12345678(%eax),%al +LBPatch2: + addl %ebp,%edx + movb %al,(%edi) + movb 0x12345678(%ecx),%cl +LBPatch3: + movb %cl,1(%edi) + addl $0x2,%edi + + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movb 0x12345678(%eax),%al +LBPatch4: + addl %ebp,%edx + movb %al,(%edi) + movb 0x12345678(%ecx),%cl +LBPatch5: + movb %cl,1(%edi) + addl $0x2,%edi + + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movb 0x12345678(%eax),%al +LBPatch6: + addl %ebp,%edx + movb %al,(%edi) + movb 0x12345678(%ecx),%cl +LBPatch7: + movb %cl,1(%edi) + addl $0x2,%edi + +LEnter8_8: + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movb 0x12345678(%eax),%al +LBPatch8: + addl %ebp,%edx + movb %al,(%edi) + movb 0x12345678(%ecx),%cl +LBPatch9: + movb %cl,1(%edi) + addl $0x2,%edi + + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movb 0x12345678(%eax),%al +LBPatch10: + addl %ebp,%edx + movb %al,(%edi) + movb 0x12345678(%ecx),%cl +LBPatch11: + movb %cl,1(%edi) + addl $0x2,%edi + +LEnter4_8: + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movb 0x12345678(%eax),%al +LBPatch12: + addl %ebp,%edx + movb %al,(%edi) + movb 0x12345678(%ecx),%cl +LBPatch13: + movb %cl,1(%edi) + addl $0x2,%edi + +LEnter2_8: + movb (%esi),%al + movb (%esi,%ebx,),%cl + movb %dh,%ah + addl %ebp,%edx + movb %dh,%ch + leal (%esi,%ebx,2),%esi + movb 0x12345678(%eax),%al +LBPatch14: + addl %ebp,%edx + movb %al,(%edi) + movb 0x12345678(%ecx),%cl +LBPatch15: + movb %cl,1(%edi) + addl $0x2,%edi + diff --git a/linux/cd_linux.c b/linux/cd_linux.c new file mode 100644 index 000000000..9c461fc3d --- /dev/null +++ b/linux/cd_linux.c @@ -0,0 +1,420 @@ +// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All +// rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../client/client.h" + +static qboolean cdValid = false; +static qboolean playing = false; +static qboolean wasPlaying = false; +static qboolean initialized = false; +static qboolean enabled = true; +static qboolean playLooping = false; +static float cdvolume; +static byte remap[100]; +static byte playTrack; +static byte maxTrack; + +static int cdfile = -1; + +//static char cd_dev[64] = "/dev/cdrom"; + +cvar_t *cd_volume; +cvar_t *cd_nocd; +cvar_t *cd_dev; + +void CDAudio_Pause(void); + +static void CDAudio_Eject(void) +{ + if (cdfile == -1 || !enabled) + return; // no cd init'd + + if ( ioctl(cdfile, CDROMEJECT) == -1 ) + Com_DPrintf("ioctl cdromeject failed\n"); +} + + +static void CDAudio_CloseDoor(void) +{ + if (cdfile == -1 || !enabled) + return; // no cd init'd + + if ( ioctl(cdfile, CDROMCLOSETRAY) == -1 ) + Com_DPrintf("ioctl cdromclosetray failed\n"); +} + +static int CDAudio_GetAudioDiskInfo(void) +{ + struct cdrom_tochdr tochdr; + + cdValid = false; + + if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 ) + { + Com_DPrintf("ioctl cdromreadtochdr failed\n"); + return -1; + } + + if (tochdr.cdth_trk0 < 1) + { + Com_DPrintf("CDAudio: no music tracks\n"); + return -1; + } + + cdValid = true; + maxTrack = tochdr.cdth_trk1; + + return 0; +} + + +void CDAudio_Play(int track, qboolean looping) +{ + struct cdrom_tocentry entry; + struct cdrom_ti ti; + + if (cdfile == -1 || !enabled) + return; + + if (!cdValid) + { + CDAudio_GetAudioDiskInfo(); + if (!cdValid) + return; + } + + track = remap[track]; + + if (track < 1 || track > maxTrack) + { + Com_DPrintf("CDAudio: Bad track number %u.\n", track); + return; + } + + // don't try to play a non-audio track + entry.cdte_track = track; + entry.cdte_format = CDROM_MSF; + if ( ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1 ) + { + Com_DPrintf("ioctl cdromreadtocentry failed\n"); + return; + } + if (entry.cdte_ctrl == CDROM_DATA_TRACK) + { + Com_Printf("CDAudio: track %i is not audio\n", track); + return; + } + + if (playing) + { + if (playTrack == track) + return; + CDAudio_Stop(); + } + + ti.cdti_trk0 = track; + ti.cdti_trk1 = track; + ti.cdti_ind0 = 1; + ti.cdti_ind1 = 99; + + if ( ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1 ) + { + Com_DPrintf("ioctl cdromplaytrkind failed\n"); + return; + } + + if ( ioctl(cdfile, CDROMRESUME) == -1 ) + Com_DPrintf("ioctl cdromresume failed\n"); + + playLooping = looping; + playTrack = track; + playing = true; + + if (cd_volume->value == 0.0) + CDAudio_Pause (); +} + + +void CDAudio_Stop(void) +{ + if (cdfile == -1 || !enabled) + return; + + if (!playing) + return; + + if ( ioctl(cdfile, CDROMSTOP) == -1 ) + Com_DPrintf("ioctl cdromstop failed (%d)\n", errno); + + wasPlaying = false; + playing = false; +} + +void CDAudio_Pause(void) +{ + if (cdfile == -1 || !enabled) + return; + + if (!playing) + return; + + if ( ioctl(cdfile, CDROMPAUSE) == -1 ) + Com_DPrintf("ioctl cdrompause failed\n"); + + wasPlaying = playing; + playing = false; +} + + +void CDAudio_Resume(void) +{ + if (cdfile == -1 || !enabled) + return; + + if (!cdValid) + return; + + if (!wasPlaying) + return; + + if ( ioctl(cdfile, CDROMRESUME) == -1 ) + Com_DPrintf("ioctl cdromresume failed\n"); + playing = true; +} + +static void CD_f (void) +{ + char *command; + int ret; + int n; + + if (Cmd_Argc() < 2) + return; + + command = Cmd_Argv (1); + + if (Q_strcasecmp(command, "on") == 0) + { + enabled = true; + return; + } + + if (Q_strcasecmp(command, "off") == 0) + { + if (playing) + CDAudio_Stop(); + enabled = false; + return; + } + + if (Q_strcasecmp(command, "reset") == 0) + { + enabled = true; + if (playing) + CDAudio_Stop(); + for (n = 0; n < 100; n++) + remap[n] = n; + CDAudio_GetAudioDiskInfo(); + return; + } + + if (Q_strcasecmp(command, "remap") == 0) + { + ret = Cmd_Argc() - 2; + if (ret <= 0) + { + for (n = 1; n < 100; n++) + if (remap[n] != n) + Com_Printf(" %u -> %u\n", n, remap[n]); + return; + } + for (n = 1; n <= ret; n++) + remap[n] = atoi(Cmd_Argv (n+1)); + return; + } + + if (Q_strcasecmp(command, "close") == 0) + { + CDAudio_CloseDoor(); + return; + } + + if (!cdValid) + { + CDAudio_GetAudioDiskInfo(); + if (!cdValid) + { + Com_Printf("No CD in player.\n"); + return; + } + } + + if (Q_strcasecmp(command, "play") == 0) + { + CDAudio_Play((byte)atoi(Cmd_Argv (2)), false); + return; + } + + if (Q_strcasecmp(command, "loop") == 0) + { + CDAudio_Play((byte)atoi(Cmd_Argv (2)), true); + return; + } + + if (Q_strcasecmp(command, "stop") == 0) + { + CDAudio_Stop(); + return; + } + + if (Q_strcasecmp(command, "pause") == 0) + { + CDAudio_Pause(); + return; + } + + if (Q_strcasecmp(command, "resume") == 0) + { + CDAudio_Resume(); + return; + } + + if (Q_strcasecmp(command, "eject") == 0) + { + if (playing) + CDAudio_Stop(); + CDAudio_Eject(); + cdValid = false; + return; + } + + if (Q_strcasecmp(command, "info") == 0) + { + Com_Printf("%u tracks\n", maxTrack); + if (playing) + Com_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); + else if (wasPlaying) + Com_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); + Com_Printf("Volume is %f\n", cdvolume); + return; + } +} + +void CDAudio_Update(void) +{ + struct cdrom_subchnl subchnl; + static time_t lastchk; + + if (cdfile == -1 || !enabled) + return; + + if (cd_volume && cd_volume->value != cdvolume) + { + if (cdvolume) + { + Cvar_SetValue ("cd_volume", 0.0); + cdvolume = cd_volume->value; + CDAudio_Pause (); + } + else + { + Cvar_SetValue ("cd_volume", 1.0); + cdvolume = cd_volume->value; + CDAudio_Resume (); + } + } + + if (playing && lastchk < time(NULL)) { + lastchk = time(NULL) + 2; //two seconds between chks + subchnl.cdsc_format = CDROM_MSF; + if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1 ) { + Com_DPrintf("ioctl cdromsubchnl failed\n"); + playing = false; + return; + } + if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY && + subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED) { + playing = false; + if (playLooping) + CDAudio_Play(playTrack, true); + } + } +} + +int CDAudio_Init(void) +{ + int i; + cvar_t *cv; + extern uid_t saved_euid; + + cv = Cvar_Get ("nocdaudio", "0", CVAR_NOSET); + if (cv->value) + return -1; + + cd_nocd = Cvar_Get ("cd_nocd", "0", CVAR_ARCHIVE ); + if ( cd_nocd->value) + return -1; + + cd_volume = Cvar_Get ("cd_volume", "1", CVAR_ARCHIVE); + + cd_dev = Cvar_Get("cd_dev", "/dev/cdrom", CVAR_ARCHIVE); + + seteuid(saved_euid); + + cdfile = open(cd_dev->string, O_RDONLY); + + seteuid(getuid()); + + if (cdfile == -1) { + Com_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev->string, errno); + cdfile = -1; + return -1; + } + + for (i = 0; i < 100; i++) + remap[i] = i; + initialized = true; + enabled = true; + + if (CDAudio_GetAudioDiskInfo()) + { + Com_Printf("CDAudio_Init: No CD in player.\n"); + cdValid = false; + } + + Cmd_AddCommand ("cd", CD_f); + + Com_Printf("CD Audio Initialized\n"); + + return 0; +} + +void CDAudio_Activate (qboolean active) +{ + if (active) + CDAudio_Resume (); + else + CDAudio_Pause (); +} + +void CDAudio_Shutdown(void) +{ + if (!initialized) + return; + CDAudio_Stop(); + close(cdfile); + cdfile = -1; +} diff --git a/linux/d_copy.s b/linux/d_copy.s new file mode 100644 index 000000000..376bcfe50 --- /dev/null +++ b/linux/d_copy.s @@ -0,0 +1,147 @@ +/ +// d_copy.s +// x86 assembly-language screen copying code. +// + +#include "qasm.h" + + .data + +LCopyWidth: .long 0 +LBlockSrcStep: .long 0 +LBlockDestStep: .long 0 +LSrcDelta: .long 0 +LDestDelta: .long 0 + +#define bufptr 4+16 + +// copies 16 rows per plane at a pop; idea is that 16*512 = 8k, and since +// no Mode X mode is wider than 360, all the data should fit in the cache for +// the passes for the next 3 planes + + .text + +.globl C(VGA_UpdatePlanarScreen) +C(VGA_UpdatePlanarScreen): + pushl %ebp // preserve caller's stack frame + pushl %edi + pushl %esi // preserve register variables + pushl %ebx + + movl C(VGA_bufferrowbytes),%eax + shll $1,%eax + movl %eax,LBlockSrcStep + movl C(VGA_rowbytes),%eax + shll $1,%eax + movl %eax,LBlockDestStep + + movl $0x3C4,%edx + movb $2,%al + outb %al,%dx // point the SC to the Map Mask + incl %edx + + movl bufptr(%esp),%esi + movl C(VGA_pagebase),%edi + movl C(VGA_height),%ebp + shrl $1,%ebp + + movl C(VGA_width),%ecx + movl C(VGA_bufferrowbytes),%eax + subl %ecx,%eax + movl %eax,LSrcDelta + movl C(VGA_rowbytes),%eax + shll $2,%eax + subl %ecx,%eax + movl %eax,LDestDelta + shrl $4,%ecx + movl %ecx,LCopyWidth + +LRowLoop: + movb $1,%al + +LPlaneLoop: + outb %al,%dx + movb $2,%ah + + pushl %esi + pushl %edi +LRowSetLoop: + movl LCopyWidth,%ecx +LColumnLoop: + movb 12(%esi),%bh + movb 8(%esi),%bl + shll $16,%ebx + movb 4(%esi),%bh + movb (%esi),%bl + movl %ebx,(%edi) + addl $16,%esi + addl $4,%edi + decl %ecx + jnz LColumnLoop + + addl LDestDelta,%edi + addl LSrcDelta,%esi + decb %ah + jnz LRowSetLoop + + popl %edi + popl %esi + incl %esi + + shlb $1,%al + cmpb $16,%al + jnz LPlaneLoop + + subl $4,%esi + addl LBlockSrcStep,%esi + addl LBlockDestStep,%edi + decl %ebp + jnz LRowLoop + + popl %ebx // restore register variables + popl %esi + popl %edi + popl %ebp // restore the caller's stack frame + + ret + + +#define srcptr 4+16 +#define destptr 8+16 +#define width 12+16 +#define height 16+16 +#define srcrowbytes 20+16 +#define destrowbytes 24+16 + +.globl C(VGA_UpdateLinearScreen) +C(VGA_UpdateLinearScreen): + pushl %ebp // preserve caller's stack frame + pushl %edi + pushl %esi // preserve register variables + pushl %ebx + + cld + movl srcptr(%esp),%esi + movl destptr(%esp),%edi + movl width(%esp),%ebx + movl srcrowbytes(%esp),%eax + subl %ebx,%eax + movl destrowbytes(%esp),%edx + subl %ebx,%edx + shrl $2,%ebx + movl height(%esp),%ebp +LLRowLoop: + movl %ebx,%ecx + rep/movsl (%esi),(%edi) + addl %eax,%esi + addl %edx,%edi + decl %ebp + jnz LLRowLoop + + popl %ebx // restore register variables + popl %esi + popl %edi + popl %ebp // restore the caller's stack frame + + ret + diff --git a/linux/d_ifacea.h b/linux/d_ifacea.h new file mode 100644 index 000000000..220e9a834 --- /dev/null +++ b/linux/d_ifacea.h @@ -0,0 +1,79 @@ +// +// d_ifacea.h +// +// Include file for asm driver interface. +// + +// +// !!! note that this file must match the corresponding C structures in +// d_iface.h at all times !!! +// + +// !!! if this is changed, it must be changed in r_shared.h too !!! +#define ALIAS_ONSEAM 0x0020 + +// !!! if this is changed, it must be changed in d_iface.h too !!! +#define TURB_TEX_SIZE 64 // base turbulent texture size + +// !!! if this is changed, it must be changed in d_iface.h too !!! +#define CYCLE 128 + +// !!! if this is changed, it must be changed in r_shared.h too !!! +#define MAXHEIGHT 1024 + +// !!! if this is changed, it must be changed in quakedef.h too !!! +#define CACHE_SIZE 32 // used to align key data structures + +// particle_t structure +// !!! if this is changed, it must be changed in d_iface.h too !!! +// driver-usable fields +#define pt_org 0 +#define pt_color 12 +// drivers never touch the following fields +#define pt_next 16 +#define pt_vel 20 +#define pt_ramp 32 +#define pt_die 36 +#define pt_type 40 +#define pt_size 44 + +#define PARTICLE_Z_CLIP 8.0 + +// finalvert_t structure +// !!! if this is changed, it must be changed in d_iface.h too !!! +#define fv_v 0 // !!! if this is moved, cases where the !!! + // !!! address of this field is pushed in !!! + // !!! d_polysa.s must be changed !!! +#define fv_flags 24 +#define fv_reserved 28 +#define fv_size 32 +#define fv_shift 5 + + +// stvert_t structure +// !!! if this is changed, it must be changed in modelgen.h too !!! +#define stv_onseam 0 +#define stv_s 4 +#define stv_t 8 +#define stv_size 12 + + +// trivertx_t structure +// !!! if this is changed, it must be changed in modelgen.h too !!! +#define tv_v 0 +#define tv_lightnormalindex 3 +#define tv_size 4 + +// affinetridesc_t structure +// !!! if this is changed, it must be changed in d_iface.h too !!! +#define atd_pskin 0 +#define atd_pskindesc 4 +#define atd_skinwidth 8 +#define atd_skinheight 12 +#define atd_ptriangles 16 +#define atd_pfinalverts 20 +#define atd_numtriangles 24 +#define atd_drawtype 28 +#define atd_seamfixupX16 32 +#define atd_size 36 + diff --git a/linux/d_polysa.s b/linux/d_polysa.s new file mode 100644 index 000000000..6b62fa840 --- /dev/null +++ b/linux/d_polysa.s @@ -0,0 +1,1250 @@ +// +// d_polysa.s +// x86 assembly-language polygon model drawing code +// + +#include "qasm.h" +#include "d_ifacea.h" + +#if id386 + +// !!! if this is changed, it must be changed in d_polyse.c too !!! +#define DPS_MAXSPANS MAXHEIGHT+1 + // 1 extra for spanpackage that marks end + +//#define SPAN_SIZE (((DPS_MAXSPANS + 1 + ((CACHE_SIZE - 1) / spanpackage_t_size)) + 1) * spanpackage_t_size) +#define SPAN_SIZE (1024+1+1+1)*32 + + + + .data + + .align 4 +p10_minus_p20: .single 0 +p01_minus_p21: .single 0 +temp0: .single 0 +temp1: .single 0 +Ltemp: .single 0 + +aff8entryvec_table: .long LDraw8, LDraw7, LDraw6, LDraw5 + .long LDraw4, LDraw3, LDraw2, LDraw1 + +lzistepx: .long 0 + + + .text + +#ifndef NeXT + .extern C(D_PolysetSetEdgeTable) + .extern C(D_RasterizeAliasPolySmooth) +#endif + +//---------------------------------------------------------------------- +// affine triangle gradient calculation code +//---------------------------------------------------------------------- + +#if 0 +#define skinwidth 4+0 + +.globl C(R_PolysetCalcGradients) +C(R_PolysetCalcGradients): + +// p00_minus_p20 = r_p0[0] - r_p2[0]; +// p01_minus_p21 = r_p0[1] - r_p2[1]; +// p10_minus_p20 = r_p1[0] - r_p2[0]; +// p11_minus_p21 = r_p1[1] - r_p2[1]; +// +// xstepdenominv = 1.0 / (p10_minus_p20 * p01_minus_p21 - +// p00_minus_p20 * p11_minus_p21); +// +// ystepdenominv = -xstepdenominv; + + fildl C(r_p0)+0 // r_p0[0] + fildl C(r_p2)+0 // r_p2[0] | r_p0[0] + fildl C(r_p0)+4 // r_p0[1] | r_p2[0] | r_p0[0] + fildl C(r_p2)+4 // r_p2[1] | r_p0[1] | r_p2[0] | r_p0[0] + fildl C(r_p1)+0 // r_p1[0] | r_p2[1] | r_p0[1] | r_p2[0] | r_p0[0] + fildl C(r_p1)+4 // r_p1[1] | r_p1[0] | r_p2[1] | r_p0[1] | + // r_p2[0] | r_p0[0] + fxch %st(3) // r_p0[1] | r_p1[0] | r_p2[1] | r_p1[1] | + // r_p2[0] | r_p0[0] + fsub %st(2),%st(0) // p01_minus_p21 | r_p1[0] | r_p2[1] | r_p1[1] | + // r_p2[0] | r_p0[0] + fxch %st(1) // r_p1[0] | p01_minus_p21 | r_p2[1] | r_p1[1] | + // r_p2[0] | r_p0[0] + fsub %st(4),%st(0) // p10_minus_p20 | p01_minus_p21 | r_p2[1] | + // r_p1[1] | r_p2[0] | r_p0[0] + fxch %st(5) // r_p0[0] | p01_minus_p21 | r_p2[1] | + // r_p1[1] | r_p2[0] | p10_minus_p20 + fsubp %st(0),%st(4) // p01_minus_p21 | r_p2[1] | r_p1[1] | + // p00_minus_p20 | p10_minus_p20 + fxch %st(2) // r_p1[1] | r_p2[1] | p01_minus_p21 | + // p00_minus_p20 | p10_minus_p20 + fsubp %st(0),%st(1) // p11_minus_p21 | p01_minus_p21 | + // p00_minus_p20 | p10_minus_p20 + fxch %st(1) // p01_minus_p21 | p11_minus_p21 | + // p00_minus_p20 | p10_minus_p20 + flds C(d_xdenom) // d_xdenom | p01_minus_p21 | p11_minus_p21 | + // p00_minus_p20 | p10_minus_p20 + fxch %st(4) // p10_minus_p20 | p01_minus_p21 | p11_minus_p21 | + // p00_minus_p20 | d_xdenom + fstps p10_minus_p20 // p01_minus_p21 | p11_minus_p21 | + // p00_minus_p20 | d_xdenom + fstps p01_minus_p21 // p11_minus_p21 | p00_minus_p20 | xstepdenominv + fxch %st(2) // xstepdenominv | p00_minus_p20 | p11_minus_p21 + +//// ceil () for light so positive steps are exaggerated, negative steps +//// diminished, pushing us away from underflow toward overflow. Underflow is +//// very visible, overflow is very unlikely, because of ambient lighting +// t0 = r_p0[4] - r_p2[4]; +// t1 = r_p1[4] - r_p2[4]; + + fildl C(r_p2)+16 // r_p2[4] | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fildl C(r_p0)+16 // r_p0[4] | r_p2[4] | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fildl C(r_p1)+16 // r_p1[4] | r_p0[4] | r_p2[4] | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fxch %st(2) // r_p2[4] | r_p0[4] | r_p1[4] | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fld %st(0) // r_p2[4] | r_p2[4] | r_p0[4] | r_p1[4] | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fsubrp %st(0),%st(2) // r_p2[4] | t0 | r_p1[4] | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fsubrp %st(0),%st(2) // t0 | t1 | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + +// r_lstepx = (int) +// ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); +// r_lstepy = (int) +// ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); + + fld %st(0) // t0 | t0 | t1 | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fmul %st(5),%st(0) // t0*p11_minus_p21 | t0 | t1 | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fxch %st(2) // t1 | t0 | t0*p11_minus_p21 | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fld %st(0) // t1 | t1 | t0 | t0*p11_minus_p21 | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fmuls p01_minus_p21 // t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(2) // t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fmuls p10_minus_p20 // t0*p10_minus_p20 | t1 | t1*p01_minus_p21 | + // t0*p11_minus_p21 | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fxch %st(1) // t1 | t0*p10_minus_p20 | t1*p01_minus_p21 | + // t0*p11_minus_p21 | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fmul %st(5),%st(0) // t1*p00_minus_p20 | t0*p10_minus_p20 | + // t1*p01_minus_p21 | t0*p11_minus_p21 | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(2) // t1*p01_minus_p21 | t0*p10_minus_p20 | + // t1*p00_minus_p20 | t0*p11_minus_p21 | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fsubp %st(0),%st(3) // t0*p10_minus_p20 | t1*p00_minus_p20 | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fsubrp %st(0),%st(1) // t1*p00_minus_p20 - t0*p10_minus_p20 | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fld %st(2) // xstepdenominv | + // t1*p00_minus_p20 - t0*p10_minus_p20 | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fmuls float_minus_1 // ystepdenominv | + // t1*p00_minus_p20 - t0*p10_minus_p20 | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(2) // t1*p01_minus_p21 - t0*p11_minus_p21 | + // t1*p00_minus_p20 - t0*p10_minus_p20 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fmul %st(3),%st(0) // (t1*p01_minus_p21 - t0*p11_minus_p21)* + // xstepdenominv | + // t1*p00_minus_p20 - t0*p10_minus_p20 | + // | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fxch %st(1) // t1*p00_minus_p20 - t0*p10_minus_p20 | + // (t1*p01_minus_p21 - t0*p11_minus_p21)* + // xstepdenominv | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fmul %st(2),%st(0) // (t1*p00_minus_p20 - t0*p10_minus_p20)* + // ystepdenominv | + // (t1*p01_minus_p21 - t0*p11_minus_p21)* + // xstepdenominv | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fldcw ceil_cw + fistpl C(r_lstepy) // r_lstepx | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fistpl C(r_lstepx) // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fldcw single_cw + +// t0 = r_p0[2] - r_p2[2]; +// t1 = r_p1[2] - r_p2[2]; + + fildl C(r_p2)+8 // r_p2[2] | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fildl C(r_p0)+8 // r_p0[2] | r_p2[2] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fildl C(r_p1)+8 // r_p1[2] | r_p0[2] | r_p2[2] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(2) // r_p2[2] | r_p0[2] | r_p1[2] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fld %st(0) // r_p2[2] | r_p2[2] | r_p0[2] | r_p1[2] | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fsubrp %st(0),%st(2) // r_p2[2] | t0 | r_p1[2] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fsubrp %st(0),%st(2) // t0 | t1 | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + +// r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * +// xstepdenominv); +// r_sstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * +// ystepdenominv); + + fld %st(0) // t0 | t0 | t1 | ystepdenominv | xstepdenominv + fmul %st(6),%st(0) // t0*p11_minus_p21 | t0 | t1 | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(2) // t1 | t0 | t0*p11_minus_p21 | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fld %st(0) // t1 | t1 | t0 | t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fmuls p01_minus_p21 // t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fxch %st(2) // t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fmuls p10_minus_p20 // t0*p10_minus_p20 | t1 | t1*p01_minus_p21 | + // t0*p11_minus_p21 | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(1) // t1 | t0*p10_minus_p20 | t1*p01_minus_p21 | + // t0*p11_minus_p21 | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fmul %st(6),%st(0) // t1*p00_minus_p20 | t0*p10_minus_p20 | + // t1*p01_minus_p21 | t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fxch %st(2) // t1*p01_minus_p21 | t0*p10_minus_p20 | + // t1*p00_minus_p20 | t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fsubp %st(0),%st(3) // t0*p10_minus_p20 | t1*p00_minus_p20 | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fsubrp %st(0),%st(1) // t1*p00_minus_p20 - t0*p10_minus_p20 | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fmul %st(2),%st(0) // (t1*p00_minus_p20 - t0*p10_minus_p20)* + // ystepdenominv | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fxch %st(1) // t1*p01_minus_p21 - t0*p11_minus_p21 | + // (t1*p00_minus_p20 - t0*p10_minus_p20)* + // ystepdenominv | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fmul %st(3),%st(0) // (t1*p01_minus_p21 - t0*p11_minus_p21)* + // xstepdenominv | + // (t1*p00_minus_p20 - t0*p10_minus_p20)* + // ystepdenominv | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(1) // (t1*p00_minus_p20 - t0*p10_minus_p20)* + // ystepdenominv | + // (t1*p01_minus_p21 - t0*p11_minus_p21)* + // xstepdenominv | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fistpl C(r_sstepy) // r_sstepx | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fistpl C(r_sstepx) // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + +// t0 = r_p0[3] - r_p2[3]; +// t1 = r_p1[3] - r_p2[3]; + + fildl C(r_p2)+12 // r_p2[3] | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fildl C(r_p0)+12 // r_p0[3] | r_p2[3] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fildl C(r_p1)+12 // r_p1[3] | r_p0[3] | r_p2[3] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(2) // r_p2[3] | r_p0[3] | r_p1[3] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fld %st(0) // r_p2[3] | r_p2[3] | r_p0[3] | r_p1[3] | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fsubrp %st(0),%st(2) // r_p2[3] | t0 | r_p1[3] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fsubrp %st(0),%st(2) // t0 | t1 | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + +// r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * +// xstepdenominv); +// r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * +// ystepdenominv); + + fld %st(0) // t0 | t0 | t1 | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fmul %st(6),%st(0) // t0*p11_minus_p21 | t0 | t1 | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(2) // t1 | t0 | t0*p11_minus_p21 | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fld %st(0) // t1 | t1 | t0 | t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fmuls p01_minus_p21 // t1*p01_minus_p21 | t1 | t0 | t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fxch %st(2) // t0 | t1 | t1*p01_minus_p21 | t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fmuls p10_minus_p20 // t0*p10_minus_p20 | t1 | t1*p01_minus_p21 | + // t0*p11_minus_p21 | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(1) // t1 | t0*p10_minus_p20 | t1*p01_minus_p21 | + // t0*p11_minus_p21 | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fmul %st(6),%st(0) // t1*p00_minus_p20 | t0*p10_minus_p20 | + // t1*p01_minus_p21 | t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fxch %st(2) // t1*p01_minus_p21 | t0*p10_minus_p20 | + // t1*p00_minus_p20 | t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fsubp %st(0),%st(3) // t0*p10_minus_p20 | t1*p00_minus_p20 | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fsubrp %st(0),%st(1) // t1*p00_minus_p20 - t0*p10_minus_p20 | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fmul %st(2),%st(0) // (t1*p00_minus_p20 - t0*p10_minus_p20)* + // ystepdenominv | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fxch %st(1) // t1*p01_minus_p21 - t0*p11_minus_p21 | + // (t1*p00_minus_p20 - t0*p10_minus_p20)* + // ystepdenominv | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fmul %st(3),%st(0) // (t1*p01_minus_p21 - t0*p11_minus_p21)* + // xstepdenominv | + // (t1*p00_minus_p20 - t0*p10_minus_p20)* + // ystepdenominv | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(1) // (t1*p00_minus_p20 - t0*p10_minus_p20)* + // ystepdenominv | + // (t1*p01_minus_p21 - t0*p11_minus_p21)* + // xstepdenominv | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fistpl C(r_tstepy) // r_tstepx | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fistpl C(r_tstepx) // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + +// t0 = r_p0[5] - r_p2[5]; +// t1 = r_p1[5] - r_p2[5]; + + fildl C(r_p2)+20 // r_p2[5] | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fildl C(r_p0)+20 // r_p0[5] | r_p2[5] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fildl C(r_p1)+20 // r_p1[5] | r_p0[5] | r_p2[5] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fxch %st(2) // r_p2[5] | r_p0[5] | r_p1[5] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fld %st(0) // r_p2[5] | r_p2[5] | r_p0[5] | r_p1[5] | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // p11_minus_p21 + fsubrp %st(0),%st(2) // r_p2[5] | t0 | r_p1[5] | ystepdenominv | + // xstepdenominv | p00_minus_p20 | p11_minus_p21 + fsubrp %st(0),%st(2) // t0 | t1 | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + +// r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * +// xstepdenominv); +// r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * +// ystepdenominv); + + fld %st(0) // t0 | t0 | t1 | ystepdenominv | xstepdenominv | + // p00_minus_p20 | p11_minus_p21 + fmulp %st(0),%st(6) // t0 | t1 | ystepdenominv | xstepdenominv | + // p00_minus_p20 | t0*p11_minus_p21 + fxch %st(1) // t1 | t0 | ystepdenominv | xstepdenominv | + // p00_minus_p20 | t0*p11_minus_p21 + fld %st(0) // t1 | t1 | t0 | ystepdenominv | xstepdenominv | + // p00_minus_p20 | t0*p11_minus_p21 + fmuls p01_minus_p21 // t1*p01_minus_p21 | t1 | t0 | ystepdenominv | + // xstepdenominv | p00_minus_p20 | + // t0*p11_minus_p21 + fxch %st(2) // t0 | t1 | t1*p01_minus_p21 | ystepdenominv | + // xstepdenominv | p00_minus_p20 | + // t0*p11_minus_p21 + fmuls p10_minus_p20 // t0*p10_minus_p20 | t1 | t1*p01_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // t0*p11_minus_p21 + fxch %st(1) // t1 | t0*p10_minus_p20 | t1*p01_minus_p21 | + // ystepdenominv | xstepdenominv | p00_minus_p20 | + // t0*p11_minus_p21 + fmulp %st(0),%st(5) // t0*p10_minus_p20 | t1*p01_minus_p21 | + // ystepdenominv | xstepdenominv | + // t1*p00_minus_p20 | t0*p11_minus_p21 + fxch %st(5) // t0*p11_minus_p21 | t1*p01_minus_p21 | + // ystepdenominv | xstepdenominv | + // t1*p00_minus_p20 | t0*p10_minus_p20 + fsubrp %st(0),%st(1) // t1*p01_minus_p21 - t0*p11_minus_p21 | + // ystepdenominv | xstepdenominv | + // t1*p00_minus_p20 | t0*p10_minus_p20 + fxch %st(3) // t1*p00_minus_p20 | ystepdenominv | + // xstepdenominv | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // t0*p10_minus_p20 + fsubp %st(0),%st(4) // ystepdenominv | xstepdenominv | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // t1*p00_minus_p20 - t0*p10_minus_p20 + fxch %st(1) // xstepdenominv | ystepdenominv | + // t1*p01_minus_p21 - t0*p11_minus_p21 | + // t1*p00_minus_p20 - t0*p10_minus_p20 + fmulp %st(0),%st(2) // ystepdenominv | + // (t1*p01_minus_p21 - t0*p11_minus_p21) * + // xstepdenominv | + // t1*p00_minus_p20 - t0*p10_minus_p20 + fmulp %st(0),%st(2) // (t1*p01_minus_p21 - t0*p11_minus_p21) * + // xstepdenominv | + // (t1*p00_minus_p20 - t0*p10_minus_p20) * + // ystepdenominv + fistpl C(r_zistepx) // (t1*p00_minus_p20 - t0*p10_minus_p20) * + // ystepdenominv + fistpl C(r_zistepy) + +// a_sstepxfrac = r_sstepx << 16; +// a_tstepxfrac = r_tstepx << 16; +// +// a_ststepxwhole = r_affinetridesc.skinwidth * (r_tstepx >> 16) + +// (r_sstepx >> 16); + + movl C(r_sstepx),%eax + movl C(r_tstepx),%edx + shll $16,%eax + shll $16,%edx + movl %eax,C(a_sstepxfrac) + movl %edx,C(a_tstepxfrac) + + movl C(r_sstepx),%ecx + movl C(r_tstepx),%eax + sarl $16,%ecx + sarl $16,%eax + imull skinwidth(%esp) + addl %ecx,%eax + movl %eax,C(a_ststepxwhole) + + ret + +#endif + +//---------------------------------------------------------------------- +// recursive subdivision affine triangle drawing code +// +// not C-callable because of stdcall return +//---------------------------------------------------------------------- + +#define lp1 4+16 +#define lp2 8+16 +#define lp3 12+16 + +.globl C(D_PolysetRecursiveTriangle) +C(D_PolysetRecursiveTriangle): + pushl %ebp // preserve caller stack frame pointer + pushl %esi // preserve register variables + pushl %edi + pushl %ebx + +// int *temp; +// int d; +// int new[6]; +// int i; +// int z; +// short *zbuf; + movl lp2(%esp),%esi + movl lp1(%esp),%ebx + movl lp3(%esp),%edi + +// d = lp2[0] - lp1[0]; +// if (d < -1 || d > 1) +// goto split; + movl 0(%esi),%eax + + movl 0(%ebx),%edx + movl 4(%esi),%ebp + + subl %edx,%eax + movl 4(%ebx),%ecx + + subl %ecx,%ebp + incl %eax + + cmpl $2,%eax + ja LSplit + +// d = lp2[1] - lp1[1]; +// if (d < -1 || d > 1) +// goto split; + movl 0(%edi),%eax + incl %ebp + + cmpl $2,%ebp + ja LSplit + +// d = lp3[0] - lp2[0]; +// if (d < -1 || d > 1) +// goto split2; + movl 0(%esi),%edx + movl 4(%edi),%ebp + + subl %edx,%eax + movl 4(%esi),%ecx + + subl %ecx,%ebp + incl %eax + + cmpl $2,%eax + ja LSplit2 + +// d = lp3[1] - lp2[1]; +// if (d < -1 || d > 1) +// goto split2; + movl 0(%ebx),%eax + incl %ebp + + cmpl $2,%ebp + ja LSplit2 + +// d = lp1[0] - lp3[0]; +// if (d < -1 || d > 1) +// goto split3; + movl 0(%edi),%edx + movl 4(%ebx),%ebp + + subl %edx,%eax + movl 4(%edi),%ecx + + subl %ecx,%ebp + incl %eax + + incl %ebp + movl %ebx,%edx + + cmpl $2,%eax + ja LSplit3 + +// d = lp1[1] - lp3[1]; +// if (d < -1 || d > 1) +// { +//split3: +// temp = lp1; +// lp3 = lp2; +// lp1 = lp3; +// lp2 = temp; +// goto split; +// } +// +// return; // entire tri is filled +// + cmpl $2,%ebp + jna LDone + +LSplit3: + movl %edi,%ebx + movl %esi,%edi + movl %edx,%esi + jmp LSplit + +//split2: +LSplit2: + +// temp = lp1; +// lp1 = lp2; +// lp2 = lp3; +// lp3 = temp; + movl %ebx,%eax + movl %esi,%ebx + movl %edi,%esi + movl %eax,%edi + +//split: +LSplit: + + subl $24,%esp // allocate space for a new vertex + +//// split this edge +// new[0] = (lp1[0] + lp2[0]) >> 1; +// new[1] = (lp1[1] + lp2[1]) >> 1; +// new[2] = (lp1[2] + lp2[2]) >> 1; +// new[3] = (lp1[3] + lp2[3]) >> 1; +// new[5] = (lp1[5] + lp2[5]) >> 1; + movl 8(%ebx),%eax + + movl 8(%esi),%edx + movl 12(%ebx),%ecx + + addl %edx,%eax + movl 12(%esi),%edx + + sarl $1,%eax + addl %edx,%ecx + + movl %eax,8(%esp) + movl 20(%ebx),%eax + + sarl $1,%ecx + movl 20(%esi),%edx + + movl %ecx,12(%esp) + addl %edx,%eax + + movl 0(%ebx),%ecx + movl 0(%esi),%edx + + sarl $1,%eax + addl %ecx,%edx + + movl %eax,20(%esp) + movl 4(%ebx),%eax + + sarl $1,%edx + movl 4(%esi),%ebp + + movl %edx,0(%esp) + addl %eax,%ebp + + sarl $1,%ebp + movl %ebp,4(%esp) + +//// draw the point if splitting a leading edge +// if (lp2[1] > lp1[1]) +// goto nodraw; + cmpl %eax,4(%esi) + jg LNoDraw + +// if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0])) +// goto nodraw; + movl 0(%esi),%edx + jnz LDraw + + cmpl %ecx,%edx + jl LNoDraw + +LDraw: + +// z = new[5] >> 16; + movl 20(%esp),%edx + movl 4(%esp),%ecx + + sarl $16,%edx + movl 0(%esp),%ebp + +// zbuf = zspantable[new[1]] + new[0]; + movl C(zspantable)(,%ecx,4),%eax + +// if (z >= *zbuf) +// { + cmpw (%eax,%ebp,2),%dx + jnge LNoDraw + +// int pix; +// +// *zbuf = z; + movw %dx,(%eax,%ebp,2) + +// pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]]; + movl 12(%esp),%eax + + sarl $16,%eax + movl 8(%esp),%edx + + sarl $16,%edx + subl %ecx,%ecx + + movl C(skintable)(,%eax,4),%eax + movl 4(%esp),%ebp + + movb (%eax,%edx,),%cl + movl C(d_pcolormap),%edx + + movb (%edx,%ecx,),%dl + movl 0(%esp),%ecx + +// d_viewbuffer[d_scantable[new[1]] + new[0]] = pix; + movl C(d_scantable)(,%ebp,4),%eax + addl %eax,%ecx + movl C(d_viewbuffer),%eax + movb %dl,(%eax,%ecx,1) + +// } +// +//nodraw: +LNoDraw: + +//// recursively continue +// D_PolysetRecursiveTriangle (lp3, lp1, new); + pushl %esp + pushl %ebx + pushl %edi + call C(D_PolysetRecursiveTriangle) + +// D_PolysetRecursiveTriangle (lp3, new, lp2); + movl %esp,%ebx + pushl %esi + pushl %ebx + pushl %edi + call C(D_PolysetRecursiveTriangle) + addl $24,%esp + +LDone: + popl %ebx // restore register variables + popl %edi + popl %esi + popl %ebp // restore caller stack frame pointer + ret $12 + + +//---------------------------------------------------------------------- +// 8-bpp horizontal span drawing code for affine polygons, with smooth +// shading and no transparency +//---------------------------------------------------------------------- + +#define pspans 4+8 + +.globl C(D_PolysetAff8Start) +C(D_PolysetAff8Start): + +.globl C(R_PolysetDrawSpans8_Opaque) +C(R_PolysetDrawSpans8_Opaque): + pushl %esi // preserve register variables + pushl %ebx + + movl pspans(%esp),%esi // point to the first span descriptor + movl C(r_zistepx),%ecx + + pushl %ebp // preserve caller's stack frame + pushl %edi + + rorl $16,%ecx // put high 16 bits of 1/z step in low word + movl spanpackage_t_count(%esi),%edx + + movl %ecx,lzistepx + +LSpanLoop: + +// lcount = d_aspancount - pspanpackage->count; +// +// errorterm += erroradjustup; +// if (errorterm >= 0) +// { +// d_aspancount += d_countextrastep; +// errorterm -= erroradjustdown; +// } +// else +// { +// d_aspancount += ubasestep; +// } + movl C(d_aspancount),%eax + subl %edx,%eax + + movl C(erroradjustup),%edx + movl C(errorterm),%ebx + addl %edx,%ebx + js LNoTurnover + + movl C(erroradjustdown),%edx + movl C(d_countextrastep),%edi + subl %edx,%ebx + movl C(d_aspancount),%ebp + movl %ebx,C(errorterm) + addl %edi,%ebp + movl %ebp,C(d_aspancount) + jmp LRightEdgeStepped + +LNoTurnover: + movl C(d_aspancount),%edi + movl C(ubasestep),%edx + movl %ebx,C(errorterm) + addl %edx,%edi + movl %edi,C(d_aspancount) + +LRightEdgeStepped: + cmpl $1,%eax + + jl LNextSpan + jz LExactlyOneLong + +// +// set up advancetable +// + movl C(a_ststepxwhole),%ecx + movl C(r_affinetridesc)+atd_skinwidth,%edx + + movl %ecx,advancetable+4 // advance base in t + addl %edx,%ecx + + movl %ecx,advancetable // advance extra in t + movl C(a_tstepxfrac),%ecx + + movw C(r_lstepx),%cx + movl %eax,%edx // count + + movl %ecx,tstep + addl $7,%edx + + shrl $3,%edx // count of full and partial loops + movl spanpackage_t_sfrac(%esi),%ebx + + movw %dx,%bx + movl spanpackage_t_pz(%esi),%ecx + + negl %eax + + movl spanpackage_t_pdest(%esi),%edi + andl $7,%eax // 0->0, 1->7, 2->6, ... , 7->1 + + subl %eax,%edi // compensate for hardwired offsets + subl %eax,%ecx + + subl %eax,%ecx + movl spanpackage_t_tfrac(%esi),%edx + + movw spanpackage_t_light(%esi),%dx + movl spanpackage_t_zi(%esi),%ebp + + rorl $16,%ebp // put high 16 bits of 1/z in low word + pushl %esi + + movl spanpackage_t_ptex(%esi),%esi + jmp aff8entryvec_table(,%eax,4) + +// %bx = count of full and partial loops +// %ebx high word = sfrac +// %ecx = pz +// %dx = light +// %edx high word = tfrac +// %esi = ptex +// %edi = pdest +// %ebp = 1/z +// tstep low word = C(r_lstepx) +// tstep high word = C(a_tstepxfrac) +// C(a_sstepxfrac) low word = 0 +// C(a_sstepxfrac) high word = C(a_sstepxfrac) + +LDrawLoop: + +// FIXME: do we need to clamp light? We may need at least a buffer bit to +// keep it from poking into tfrac and causing problems + +LDraw8: + cmpw (%ecx),%bp + jl Lp1 + xorl %eax,%eax + movb %dh,%ah + movb (%esi),%al + movw %bp,(%ecx) + movb 0x12345678(%eax),%al +LPatch8: + movb %al,(%edi) +Lp1: + addl tstep,%edx + sbbl %eax,%eax + addl lzistepx,%ebp + adcl $0,%ebp + addl C(a_sstepxfrac),%ebx + adcl advancetable+4(,%eax,4),%esi + +LDraw7: + cmpw 2(%ecx),%bp + jl Lp2 + xorl %eax,%eax + movb %dh,%ah + movb (%esi),%al + movw %bp,2(%ecx) + movb 0x12345678(%eax),%al +LPatch7: + movb %al,1(%edi) +Lp2: + addl tstep,%edx + sbbl %eax,%eax + addl lzistepx,%ebp + adcl $0,%ebp + addl C(a_sstepxfrac),%ebx + adcl advancetable+4(,%eax,4),%esi + +LDraw6: + cmpw 4(%ecx),%bp + jl Lp3 + xorl %eax,%eax + movb %dh,%ah + movb (%esi),%al + movw %bp,4(%ecx) + movb 0x12345678(%eax),%al +LPatch6: + movb %al,2(%edi) +Lp3: + addl tstep,%edx + sbbl %eax,%eax + addl lzistepx,%ebp + adcl $0,%ebp + addl C(a_sstepxfrac),%ebx + adcl advancetable+4(,%eax,4),%esi + +LDraw5: + cmpw 6(%ecx),%bp + jl Lp4 + xorl %eax,%eax + movb %dh,%ah + movb (%esi),%al + movw %bp,6(%ecx) + movb 0x12345678(%eax),%al +LPatch5: + movb %al,3(%edi) +Lp4: + addl tstep,%edx + sbbl %eax,%eax + addl lzistepx,%ebp + adcl $0,%ebp + addl C(a_sstepxfrac),%ebx + adcl advancetable+4(,%eax,4),%esi + +LDraw4: + cmpw 8(%ecx),%bp + jl Lp5 + xorl %eax,%eax + movb %dh,%ah + movb (%esi),%al + movw %bp,8(%ecx) + movb 0x12345678(%eax),%al +LPatch4: + movb %al,4(%edi) +Lp5: + addl tstep,%edx + sbbl %eax,%eax + addl lzistepx,%ebp + adcl $0,%ebp + addl C(a_sstepxfrac),%ebx + adcl advancetable+4(,%eax,4),%esi + +LDraw3: + cmpw 10(%ecx),%bp + jl Lp6 + xorl %eax,%eax + movb %dh,%ah + movb (%esi),%al + movw %bp,10(%ecx) + movb 0x12345678(%eax),%al +LPatch3: + movb %al,5(%edi) +Lp6: + addl tstep,%edx + sbbl %eax,%eax + addl lzistepx,%ebp + adcl $0,%ebp + addl C(a_sstepxfrac),%ebx + adcl advancetable+4(,%eax,4),%esi + +LDraw2: + cmpw 12(%ecx),%bp + jl Lp7 + xorl %eax,%eax + movb %dh,%ah + movb (%esi),%al + movw %bp,12(%ecx) + movb 0x12345678(%eax),%al +LPatch2: + movb %al,6(%edi) +Lp7: + addl tstep,%edx + sbbl %eax,%eax + addl lzistepx,%ebp + adcl $0,%ebp + addl C(a_sstepxfrac),%ebx + adcl advancetable+4(,%eax,4),%esi + +LDraw1: + cmpw 14(%ecx),%bp + jl Lp8 + xorl %eax,%eax + movb %dh,%ah + movb (%esi),%al + movw %bp,14(%ecx) + movb 0x12345678(%eax),%al +LPatch1: + movb %al,7(%edi) +Lp8: + addl tstep,%edx + sbbl %eax,%eax + addl lzistepx,%ebp + adcl $0,%ebp + addl C(a_sstepxfrac),%ebx + adcl advancetable+4(,%eax,4),%esi + + addl $8,%edi + addl $16,%ecx + + decw %bx + jnz LDrawLoop + + popl %esi // restore spans pointer +LNextSpan: + addl $(spanpackage_t_size),%esi // point to next span +LNextSpanESISet: + movl spanpackage_t_count(%esi),%edx + cmpl $-999999,%edx // any more spans? + jnz LSpanLoop // yes + + popl %edi + popl %ebp // restore the caller's stack frame + popl %ebx // restore register variables + popl %esi + ret + + +// draw a one-long span + +LExactlyOneLong: + + movl spanpackage_t_pz(%esi),%ecx + movl spanpackage_t_zi(%esi),%ebp + + rorl $16,%ebp // put high 16 bits of 1/z in low word + movl spanpackage_t_ptex(%esi),%ebx + + cmpw (%ecx),%bp + jl LNextSpan + xorl %eax,%eax + movl spanpackage_t_pdest(%esi),%edi + movb spanpackage_t_light+1(%esi),%ah + addl $(spanpackage_t_size),%esi // point to next span + movb (%ebx),%al + movw %bp,(%ecx) + movb 0x12345678(%eax),%al +LPatch9: + movb %al,(%edi) + + jmp LNextSpanESISet + +.globl C(D_PolysetAff8End) +C(D_PolysetAff8End): + + +.extern C(alias_colormap) +// #define pcolormap 4 + +.globl C(D_Aff8Patch) +C(D_Aff8Patch): + movl C(alias_colormap),%eax + movl %eax,LPatch1-4 + movl %eax,LPatch2-4 + movl %eax,LPatch3-4 + movl %eax,LPatch4-4 + movl %eax,LPatch5-4 + movl %eax,LPatch6-4 + movl %eax,LPatch7-4 + movl %eax,LPatch8-4 + movl %eax,LPatch9-4 + + ret + +//---------------------------------------------------------------------- +// Alias model triangle left-edge scanning code +//---------------------------------------------------------------------- + +#define height 4+16 + +.globl C(R_PolysetScanLeftEdge) +C(R_PolysetScanLeftEdge): + pushl %ebp // preserve caller stack frame pointer + pushl %esi // preserve register variables + pushl %edi + pushl %ebx + + movl height(%esp),%eax + movl C(d_sfrac),%ecx + andl $0xFFFF,%eax + movl C(d_ptex),%ebx + orl %eax,%ecx + movl C(d_pedgespanpackage),%esi + movl C(d_tfrac),%edx + movl C(d_light),%edi + movl C(d_zi),%ebp + +// %eax: scratch +// %ebx: d_ptex +// %ecx: d_sfrac in high word, count in low word +// %edx: d_tfrac +// %esi: d_pedgespanpackage, errorterm, scratch alternately +// %edi: d_light +// %ebp: d_zi + +// do +// { + +LScanLoop: + +// d_pedgespanpackage->ptex = ptex; +// d_pedgespanpackage->pdest = d_pdest; +// d_pedgespanpackage->pz = d_pz; +// d_pedgespanpackage->count = d_aspancount; +// d_pedgespanpackage->light = d_light; +// d_pedgespanpackage->zi = d_zi; +// d_pedgespanpackage->sfrac = d_sfrac << 16; +// d_pedgespanpackage->tfrac = d_tfrac << 16; + movl %ebx,spanpackage_t_ptex(%esi) + movl C(d_pdest),%eax + movl %eax,spanpackage_t_pdest(%esi) + movl C(d_pz),%eax + movl %eax,spanpackage_t_pz(%esi) + movl C(d_aspancount),%eax + movl %eax,spanpackage_t_count(%esi) + movl %edi,spanpackage_t_light(%esi) + movl %ebp,spanpackage_t_zi(%esi) + movl %ecx,spanpackage_t_sfrac(%esi) + movl %edx,spanpackage_t_tfrac(%esi) + +// pretouch the next cache line + movb spanpackage_t_size(%esi),%al + +// d_pedgespanpackage++; + addl $(spanpackage_t_size),%esi + movl C(erroradjustup),%eax + movl %esi,C(d_pedgespanpackage) + +// errorterm += erroradjustup; + movl C(errorterm),%esi + addl %eax,%esi + movl C(d_pdest),%eax + +// if (errorterm >= 0) +// { + js LNoLeftEdgeTurnover + +// errorterm -= erroradjustdown; +// d_pdest += d_pdestextrastep; + subl C(erroradjustdown),%esi + addl C(d_pdestextrastep),%eax + movl %esi,C(errorterm) + movl %eax,C(d_pdest) + +// d_pz += d_pzextrastep; +// d_aspancount += d_countextrastep; +// d_ptex += d_ptexextrastep; +// d_sfrac += d_sfracextrastep; +// d_ptex += d_sfrac >> 16; +// d_sfrac &= 0xFFFF; +// d_tfrac += d_tfracextrastep; + movl C(d_pz),%eax + movl C(d_aspancount),%esi + addl C(d_pzextrastep),%eax + addl C(d_sfracextrastep),%ecx + adcl C(d_ptexextrastep),%ebx + addl C(d_countextrastep),%esi + movl %eax,C(d_pz) + movl C(d_tfracextrastep),%eax + movl %esi,C(d_aspancount) + addl %eax,%edx + +// if (d_tfrac & 0x10000) +// { + jnc LSkip1 + +// d_ptex += r_affinetridesc.skinwidth; +// d_tfrac &= 0xFFFF; + addl C(r_affinetridesc)+atd_skinwidth,%ebx + +// } + +LSkip1: + +// d_light += d_lightextrastep; +// d_zi += d_ziextrastep; + addl C(d_lightextrastep),%edi + addl C(d_ziextrastep),%ebp + +// } + movl C(d_pedgespanpackage),%esi + decl %ecx + testl $0xFFFF,%ecx + jnz LScanLoop + + popl %ebx + popl %edi + popl %esi + popl %ebp + ret + +// else +// { + +LNoLeftEdgeTurnover: + movl %esi,C(errorterm) + +// d_pdest += d_pdestbasestep; + addl C(d_pdestbasestep),%eax + movl %eax,C(d_pdest) + +// d_pz += d_pzbasestep; +// d_aspancount += ubasestep; +// d_ptex += d_ptexbasestep; +// d_sfrac += d_sfracbasestep; +// d_ptex += d_sfrac >> 16; +// d_sfrac &= 0xFFFF; + movl C(d_pz),%eax + movl C(d_aspancount),%esi + addl C(d_pzbasestep),%eax + addl C(d_sfracbasestep),%ecx + adcl C(d_ptexbasestep),%ebx + addl C(ubasestep),%esi + movl %eax,C(d_pz) + movl %esi,C(d_aspancount) + +// d_tfrac += d_tfracbasestep; + movl C(d_tfracbasestep),%esi + addl %esi,%edx + +// if (d_tfrac & 0x10000) +// { + jnc LSkip2 + +// d_ptex += r_affinetridesc.skinwidth; +// d_tfrac &= 0xFFFF; + addl C(r_affinetridesc)+atd_skinwidth,%ebx + +// } + +LSkip2: + +// d_light += d_lightbasestep; +// d_zi += d_zibasestep; + addl C(d_lightbasestep),%edi + addl C(d_zibasestep),%ebp + +// } +// } while (--height); + movl C(d_pedgespanpackage),%esi + decl %ecx + testl $0xFFFF,%ecx + jnz LScanLoop + + popl %ebx + popl %edi + popl %esi + popl %ebp + ret + +#endif // id386 + diff --git a/linux/gl_fxmesa.c b/linux/gl_fxmesa.c new file mode 100644 index 000000000..205ce7ec3 --- /dev/null +++ b/linux/gl_fxmesa.c @@ -0,0 +1,206 @@ +/* +** GLW_IMP.C +** +** This file contains ALL Linux specific stuff having to do with the +** OpenGL refresh. When a port is being made the following functions +** must be implemented by the port: +** +** GLimp_EndFrame +** GLimp_Init +** GLimp_Shutdown +** GLimp_SwitchFullscreen +** +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "../ref_gl/gl_local.h" +#include "../client/keys.h" +#include "../linux/rw_linux.h" + +#include + +/*****************************************************************************/ + +static qboolean GLimp_SwitchFullscreen( int width, int height ); +qboolean GLimp_InitGL (void); + +extern cvar_t *vid_fullscreen; +extern cvar_t *vid_ref; + +static fxMesaContext fc = NULL; + +#define NUM_RESOLUTIONS 3 + +static resolutions[NUM_RESOLUTIONS][3]={ + { 512, 384, GR_RESOLUTION_512x384 }, + { 640, 400, GR_RESOLUTION_640x400 }, + { 640, 480, GR_RESOLUTION_640x480 } +}; + +static int findres(int *width, int *height) +{ + int i; + + for(i=0;i +#include "../linux/glob.h" + +/* Like glob_match, but match PATTERN against any final segment of TEXT. */ +static int glob_match_after_star(char *pattern, char *text) +{ + register char *p = pattern, *t = text; + register char c, c1; + + while ((c = *p++) == '?' || c == '*') + if (c == '?' && *t++ == '\0') + return 0; + + if (c == '\0') + return 1; + + if (c == '\\') + c1 = *p; + else + c1 = c; + + while (1) { + if ((c == '[' || *t == c1) && glob_match(p - 1, t)) + return 1; + if (*t++ == '\0') + return 0; + } +} + +/* Return nonzero if PATTERN has any special globbing chars in it. */ +static int glob_pattern_p(char *pattern) +{ + register char *p = pattern; + register char c; + int open = 0; + + while ((c = *p++) != '\0') + switch (c) { + case '?': + case '*': + return 1; + + case '[': /* Only accept an open brace if there is a close */ + open++; /* brace to match it. Bracket expressions must be */ + continue; /* complete, according to Posix.2 */ + case ']': + if (open) + return 1; + continue; + + case '\\': + if (*p++ == '\0') + return 0; + } + + return 0; +} + +/* Match the pattern PATTERN against the string TEXT; + return 1 if it matches, 0 otherwise. + + A match means the entire string TEXT is used up in matching. + + In the pattern string, `*' matches any sequence of characters, + `?' matches any character, [SET] matches any character in the specified set, + [!SET] matches any character not in the specified set. + + A set is composed of characters or ranges; a range looks like + character hyphen character (as in 0-9 or A-Z). + [0-9a-zA-Z_] is the set of characters allowed in C identifiers. + Any other character in the pattern must be matched exactly. + + To suppress the special syntactic significance of any of `[]*?!-\', + and match the character exactly, precede it with a `\'. +*/ + +int glob_match(char *pattern, char *text) +{ + register char *p = pattern, *t = text; + register char c; + + while ((c = *p++) != '\0') + switch (c) { + case '?': + if (*t == '\0') + return 0; + else + ++t; + break; + + case '\\': + if (*p++ != *t++) + return 0; + break; + + case '*': + return glob_match_after_star(p, t); + + case '[': + { + register char c1 = *t++; + int invert; + + if (!c1) + return (0); + + invert = ((*p == '!') || (*p == '^')); + if (invert) + p++; + + c = *p++; + while (1) { + register char cstart = c, cend = c; + + if (c == '\\') { + cstart = *p++; + cend = cstart; + } + if (c == '\0') + return 0; + + c = *p++; + if (c == '-' && *p != ']') { + cend = *p++; + if (cend == '\\') + cend = *p++; + if (cend == '\0') + return 0; + c = *p++; + } + if (c1 >= cstart && c1 <= cend) + goto match; + if (c == ']') + break; + } + if (!invert) + return 0; + break; + + match: + /* Skip the rest of the [...] construct that already matched. */ + while (c != ']') { + if (c == '\0') + return 0; + c = *p++; + if (c == '\0') + return 0; + else if (c == '\\') + ++p; + } + if (invert) + return 0; + break; + } + + default: + if (c != *t++) + return 0; + } + + return *t == '\0'; +} + diff --git a/linux/glob.h b/linux/glob.h new file mode 100644 index 000000000..c4a1b4346 --- /dev/null +++ b/linux/glob.h @@ -0,0 +1 @@ +int glob_match(char *pattern, char *text); diff --git a/linux/in_linux.c b/linux/in_linux.c new file mode 100644 index 000000000..daedff558 --- /dev/null +++ b/linux/in_linux.c @@ -0,0 +1,29 @@ +// in_null.c -- for systems without a mouse + +#include "../client/client.h" + +cvar_t *in_mouse; +cvar_t *in_joystick; + +void IN_Init (void) +{ + in_mouse = Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE); + in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE); +} + +void IN_Shutdown (void) +{ +} + +void IN_Commands (void) +{ +} + +void IN_Move (usercmd_t *cmd) +{ +} + +void IN_Activate (qboolean active) +{ +} + diff --git a/linux/math.s b/linux/math.s new file mode 100644 index 000000000..005a9311e --- /dev/null +++ b/linux/math.s @@ -0,0 +1,403 @@ +// +// math.s +// x86 assembly-language math routines. + +#define GLQUAKE 1 // don't include unneeded defs +#include "qasm.h" + + +#if id386 + + .data + +#if 0 + .align 4 +Ljmptab: .long Lcase0, Lcase1, Lcase2, Lcase3 + .long Lcase4, Lcase5, Lcase6, Lcase7 +#endif + + .text + +// TODO: rounding needed? +// stack parameter offset +#define val 4 + +.globl C(Invert24To16) +C(Invert24To16): + + movl val(%esp),%ecx + movl $0x100,%edx // 0x10000000000 as dividend + cmpl %edx,%ecx + jle LOutOfRange + + subl %eax,%eax + divl %ecx + + ret + +LOutOfRange: + movl $0xFFFFFFFF,%eax + ret + +#define in 4 +#define out 8 + + .align 2 +.globl C(TransformVector) +C(TransformVector): + movl in(%esp),%eax + movl out(%esp),%edx + + flds (%eax) // in[0] + fmuls C(vright) // in[0]*vright[0] + flds (%eax) // in[0] | in[0]*vright[0] + fmuls C(vup) // in[0]*vup[0] | in[0]*vright[0] + flds (%eax) // in[0] | in[0]*vup[0] | in[0]*vright[0] + fmuls C(vpn) // in[0]*vpn[0] | in[0]*vup[0] | in[0]*vright[0] + + flds 4(%eax) // in[1] | ... + fmuls C(vright)+4 // in[1]*vright[1] | ... + flds 4(%eax) // in[1] | in[1]*vright[1] | ... + fmuls C(vup)+4 // in[1]*vup[1] | in[1]*vright[1] | ... + flds 4(%eax) // in[1] | in[1]*vup[1] | in[1]*vright[1] | ... + fmuls C(vpn)+4 // in[1]*vpn[1] | in[1]*vup[1] | in[1]*vright[1] | ... + fxch %st(2) // in[1]*vright[1] | in[1]*vup[1] | in[1]*vpn[1] | ... + + faddp %st(0),%st(5) // in[1]*vup[1] | in[1]*vpn[1] | ... + faddp %st(0),%st(3) // in[1]*vpn[1] | ... + faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum + + flds 8(%eax) // in[2] | ... + fmuls C(vright)+8 // in[2]*vright[2] | ... + flds 8(%eax) // in[2] | in[2]*vright[2] | ... + fmuls C(vup)+8 // in[2]*vup[2] | in[2]*vright[2] | ... + flds 8(%eax) // in[2] | in[2]*vup[2] | in[2]*vright[2] | ... + fmuls C(vpn)+8 // in[2]*vpn[2] | in[2]*vup[2] | in[2]*vright[2] | ... + fxch %st(2) // in[2]*vright[2] | in[2]*vup[2] | in[2]*vpn[2] | ... + + faddp %st(0),%st(5) // in[2]*vup[2] | in[2]*vpn[2] | ... + faddp %st(0),%st(3) // in[2]*vpn[2] | ... + faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum + + fstps 8(%edx) // out[2] + fstps 4(%edx) // out[1] + fstps (%edx) // out[0] + + ret + +#if 0 // in C + +#define EMINS 4+4 +#define EMAXS 4+8 +#define P 4+12 + + .align 2 +.globl C(BoxOnPlaneSide) +C(BoxOnPlaneSide): + pushl %ebx + + movl P(%esp),%edx + movl EMINS(%esp),%ecx + xorl %eax,%eax + movl EMAXS(%esp),%ebx + movb pl_signbits(%edx),%al + cmpb $8,%al + jge Lerror + flds pl_normal(%edx) // p->normal[0] + fld %st(0) // p->normal[0] | p->normal[0] + jmp Ljmptab(,%eax,4) + + +//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +//dist2= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +Lcase0: + fmuls (%ebx) // p->normal[0]*emaxs[0] | p->normal[0] + flds pl_normal+4(%edx) // p->normal[1] | p->normal[0]*emaxs[0] | + // p->normal[0] + fxch %st(2) // p->normal[0] | p->normal[0]*emaxs[0] | + // p->normal[1] + fmuls (%ecx) // p->normal[0]*emins[0] | + // p->normal[0]*emaxs[0] | p->normal[1] + fxch %st(2) // p->normal[1] | p->normal[0]*emaxs[0] | + // p->normal[0]*emins[0] + fld %st(0) // p->normal[1] | p->normal[1] | + // p->normal[0]*emaxs[0] | + // p->normal[0]*emins[0] + fmuls 4(%ebx) // p->normal[1]*emaxs[1] | p->normal[1] | + // p->normal[0]*emaxs[0] | + // p->normal[0]*emins[0] + flds pl_normal+8(%edx) // p->normal[2] | p->normal[1]*emaxs[1] | + // p->normal[1] | p->normal[0]*emaxs[0] | + // p->normal[0]*emins[0] + fxch %st(2) // p->normal[1] | p->normal[1]*emaxs[1] | + // p->normal[2] | p->normal[0]*emaxs[0] | + // p->normal[0]*emins[0] + fmuls 4(%ecx) // p->normal[1]*emins[1] | + // p->normal[1]*emaxs[1] | + // p->normal[2] | p->normal[0]*emaxs[0] | + // p->normal[0]*emins[0] + fxch %st(2) // p->normal[2] | p->normal[1]*emaxs[1] | + // p->normal[1]*emins[1] | + // p->normal[0]*emaxs[0] | + // p->normal[0]*emins[0] + fld %st(0) // p->normal[2] | p->normal[2] | + // p->normal[1]*emaxs[1] | + // p->normal[1]*emins[1] | + // p->normal[0]*emaxs[0] | + // p->normal[0]*emins[0] + fmuls 8(%ebx) // p->normal[2]*emaxs[2] | + // p->normal[2] | + // p->normal[1]*emaxs[1] | + // p->normal[1]*emins[1] | + // p->normal[0]*emaxs[0] | + // p->normal[0]*emins[0] + fxch %st(5) // p->normal[0]*emins[0] | + // p->normal[2] | + // p->normal[1]*emaxs[1] | + // p->normal[1]*emins[1] | + // p->normal[0]*emaxs[0] | + // p->normal[2]*emaxs[2] + faddp %st(0),%st(3) //p->normal[2] | + // p->normal[1]*emaxs[1] | + // p->normal[1]*emins[1]+p->normal[0]*emins[0]| + // p->normal[0]*emaxs[0] | + // p->normal[2]*emaxs[2] + fmuls 8(%ecx) //p->normal[2]*emins[2] | + // p->normal[1]*emaxs[1] | + // p->normal[1]*emins[1]+p->normal[0]*emins[0]| + // p->normal[0]*emaxs[0] | + // p->normal[2]*emaxs[2] + fxch %st(1) //p->normal[1]*emaxs[1] | + // p->normal[2]*emins[2] | + // p->normal[1]*emins[1]+p->normal[0]*emins[0]| + // p->normal[0]*emaxs[0] | + // p->normal[2]*emaxs[2] + faddp %st(0),%st(3) //p->normal[2]*emins[2] | + // p->normal[1]*emins[1]+p->normal[0]*emins[0]| + // p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]| + // p->normal[2]*emaxs[2] + fxch %st(3) //p->normal[2]*emaxs[2] + + // p->normal[1]*emins[1]+p->normal[0]*emins[0]| + // p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]| + // p->normal[2]*emins[2] + faddp %st(0),%st(2) //p->normal[1]*emins[1]+p->normal[0]*emins[0]| + // dist1 | p->normal[2]*emins[2] + + jmp LSetSides + +//dist1= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +Lcase1: + fmuls (%ecx) // emins[0] + flds pl_normal+4(%edx) + fxch %st(2) + fmuls (%ebx) // emaxs[0] + fxch %st(2) + fld %st(0) + fmuls 4(%ebx) // emaxs[1] + flds pl_normal+8(%edx) + fxch %st(2) + fmuls 4(%ecx) // emins[1] + fxch %st(2) + fld %st(0) + fmuls 8(%ebx) // emaxs[2] + fxch %st(5) + faddp %st(0),%st(3) + fmuls 8(%ecx) // emins[2] + fxch %st(1) + faddp %st(0),%st(3) + fxch %st(3) + faddp %st(0),%st(2) + + jmp LSetSides + +//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +//dist2= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +Lcase2: + fmuls (%ebx) // emaxs[0] + flds pl_normal+4(%edx) + fxch %st(2) + fmuls (%ecx) // emins[0] + fxch %st(2) + fld %st(0) + fmuls 4(%ecx) // emins[1] + flds pl_normal+8(%edx) + fxch %st(2) + fmuls 4(%ebx) // emaxs[1] + fxch %st(2) + fld %st(0) + fmuls 8(%ebx) // emaxs[2] + fxch %st(5) + faddp %st(0),%st(3) + fmuls 8(%ecx) // emins[2] + fxch %st(1) + faddp %st(0),%st(3) + fxch %st(3) + faddp %st(0),%st(2) + + jmp LSetSides + +//dist1= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +Lcase3: + fmuls (%ecx) // emins[0] + flds pl_normal+4(%edx) + fxch %st(2) + fmuls (%ebx) // emaxs[0] + fxch %st(2) + fld %st(0) + fmuls 4(%ecx) // emins[1] + flds pl_normal+8(%edx) + fxch %st(2) + fmuls 4(%ebx) // emaxs[1] + fxch %st(2) + fld %st(0) + fmuls 8(%ebx) // emaxs[2] + fxch %st(5) + faddp %st(0),%st(3) + fmuls 8(%ecx) // emins[2] + fxch %st(1) + faddp %st(0),%st(3) + fxch %st(3) + faddp %st(0),%st(2) + + jmp LSetSides + +//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +//dist2= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +Lcase4: + fmuls (%ebx) // emaxs[0] + flds pl_normal+4(%edx) + fxch %st(2) + fmuls (%ecx) // emins[0] + fxch %st(2) + fld %st(0) + fmuls 4(%ebx) // emaxs[1] + flds pl_normal+8(%edx) + fxch %st(2) + fmuls 4(%ecx) // emins[1] + fxch %st(2) + fld %st(0) + fmuls 8(%ecx) // emins[2] + fxch %st(5) + faddp %st(0),%st(3) + fmuls 8(%ebx) // emaxs[2] + fxch %st(1) + faddp %st(0),%st(3) + fxch %st(3) + faddp %st(0),%st(2) + + jmp LSetSides + +//dist1= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +Lcase5: + fmuls (%ecx) // emins[0] + flds pl_normal+4(%edx) + fxch %st(2) + fmuls (%ebx) // emaxs[0] + fxch %st(2) + fld %st(0) + fmuls 4(%ebx) // emaxs[1] + flds pl_normal+8(%edx) + fxch %st(2) + fmuls 4(%ecx) // emins[1] + fxch %st(2) + fld %st(0) + fmuls 8(%ecx) // emins[2] + fxch %st(5) + faddp %st(0),%st(3) + fmuls 8(%ebx) // emaxs[2] + fxch %st(1) + faddp %st(0),%st(3) + fxch %st(3) + faddp %st(0),%st(2) + + jmp LSetSides + +//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +//dist2= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +Lcase6: + fmuls (%ebx) // emaxs[0] + flds pl_normal+4(%edx) + fxch %st(2) + fmuls (%ecx) // emins[0] + fxch %st(2) + fld %st(0) + fmuls 4(%ecx) // emins[1] + flds pl_normal+8(%edx) + fxch %st(2) + fmuls 4(%ebx) // emaxs[1] + fxch %st(2) + fld %st(0) + fmuls 8(%ecx) // emins[2] + fxch %st(5) + faddp %st(0),%st(3) + fmuls 8(%ebx) // emaxs[2] + fxch %st(1) + faddp %st(0),%st(3) + fxch %st(3) + faddp %st(0),%st(2) + + jmp LSetSides + +//dist1= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +Lcase7: + fmuls (%ecx) // emins[0] + flds pl_normal+4(%edx) + fxch %st(2) + fmuls (%ebx) // emaxs[0] + fxch %st(2) + fld %st(0) + fmuls 4(%ecx) // emins[1] + flds pl_normal+8(%edx) + fxch %st(2) + fmuls 4(%ebx) // emaxs[1] + fxch %st(2) + fld %st(0) + fmuls 8(%ecx) // emins[2] + fxch %st(5) + faddp %st(0),%st(3) + fmuls 8(%ebx) // emaxs[2] + fxch %st(1) + faddp %st(0),%st(3) + fxch %st(3) + faddp %st(0),%st(2) + +LSetSides: + +// sides = 0; +// if (dist1 >= p->dist) +// sides = 1; +// if (dist2 < p->dist) +// sides |= 2; + + faddp %st(0),%st(2) // dist1 | dist2 + fcomps pl_dist(%edx) + xorl %ecx,%ecx + fnstsw %ax + fcomps pl_dist(%edx) + andb $1,%ah + xorb $1,%ah + addb %ah,%cl + + fnstsw %ax + andb $1,%ah + addb %ah,%ah + addb %ah,%cl + +// return sides; + + popl %ebx + movl %ecx,%eax // return status + + ret + + +Lerror: + call C(BOPS_Error) + +#endif + +#endif // id386 diff --git a/linux/net_udp.c b/linux/net_udp.c new file mode 100644 index 000000000..81b15b39c --- /dev/null +++ b/linux/net_udp.c @@ -0,0 +1,537 @@ +// net_wins.c + +#include "../qcommon/qcommon.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NeXT +#include +#endif + +netadr_t net_local_adr; + +#define LOOPBACK 0x7f000001 + +#define MAX_LOOPBACK 4 + +typedef struct +{ + byte data[MAX_MSGLEN]; + int datalen; +} loopmsg_t; + +typedef struct +{ + loopmsg_t msgs[MAX_LOOPBACK]; + int get, send; +} loopback_t; + +loopback_t loopbacks[2]; +int ip_sockets[2]; +int ipx_sockets[2]; + +int NET_Socket (char *net_interface, int port); +char *NET_ErrorString (void); + +//============================================================================= + +void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s) +{ + memset (s, 0, sizeof(*s)); + + if (a->type == NA_BROADCAST) + { + s->sin_family = AF_INET; + + s->sin_port = a->port; + *(int *)&s->sin_addr = -1; + } + else if (a->type == NA_IP) + { + s->sin_family = AF_INET; + + *(int *)&s->sin_addr = *(int *)&a->ip; + s->sin_port = a->port; + } +} + +void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a) +{ + *(int *)&a->ip = *(int *)&s->sin_addr; + a->port = s->sin_port; + a->type = NA_IP; +} + + +qboolean NET_CompareAdr (netadr_t a, netadr_t b) +{ + if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port) + return true; + return false; +} + +/* +=================== +NET_CompareBaseAdr + +Compares without the port +=================== +*/ +qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) +{ + if (a.type != b.type) + return false; + + if (a.type == NA_LOOPBACK) + return true; + + if (a.type == NA_IP) + { + if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3]) + return true; + return false; + } + + if (a.type == NA_IPX) + { + if ((memcmp(a.ipx, b.ipx, 10) == 0)) + return true; + return false; + } +} + +char *NET_AdrToString (netadr_t a) +{ + static char s[64]; + + Com_sprintf (s, sizeof(s), "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port)); + + return s; +} + +char *NET_BaseAdrToString (netadr_t a) +{ + static char s[64]; + + Com_sprintf (s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]); + + return s; +} + +/* +============= +NET_StringToAdr + +localhost +idnewt +idnewt:28000 +192.246.40.70 +192.246.40.70:28000 +============= +*/ +qboolean NET_StringToSockaddr (char *s, struct sockaddr *sadr) +{ + struct hostent *h; + char *colon; + char copy[128]; + + memset (sadr, 0, sizeof(*sadr)); + ((struct sockaddr_in *)sadr)->sin_family = AF_INET; + + ((struct sockaddr_in *)sadr)->sin_port = 0; + + strcpy (copy, s); + // strip off a trailing :port if present + for (colon = copy ; *colon ; colon++) + if (*colon == ':') + { + *colon = 0; + ((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1)); + } + + if (copy[0] >= '0' && copy[0] <= '9') + { + *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy); + } + else + { + if (! (h = gethostbyname(copy)) ) + return 0; + *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0]; + } + + return true; +} + +/* +============= +NET_StringToAdr + +localhost +idnewt +idnewt:28000 +192.246.40.70 +192.246.40.70:28000 +============= +*/ +qboolean NET_StringToAdr (char *s, netadr_t *a) +{ + struct sockaddr_in sadr; + + if (!strcmp (s, "localhost")) + { + memset (a, 0, sizeof(*a)); + a->type = NA_LOOPBACK; + return true; + } + + if (!NET_StringToSockaddr (s, (struct sockaddr *)&sadr)) + return false; + + SockadrToNetadr (&sadr, a); + + return true; +} + + +qboolean NET_IsLocalAddress (netadr_t adr) +{ + return NET_CompareAdr (adr, net_local_adr); +} + +/* +============================================================================= + +LOOPBACK BUFFERS FOR LOCAL PLAYER + +============================================================================= +*/ + +qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) +{ + int i; + loopback_t *loop; + + loop = &loopbacks[sock]; + + if (loop->send - loop->get > MAX_LOOPBACK) + loop->get = loop->send - MAX_LOOPBACK; + + if (loop->get >= loop->send) + return false; + + i = loop->get & (MAX_LOOPBACK-1); + loop->get++; + + memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen); + net_message->cursize = loop->msgs[i].datalen; + *net_from = net_local_adr; + return true; + +} + + +void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to) +{ + int i; + loopback_t *loop; + + loop = &loopbacks[sock^1]; + + i = loop->send & (MAX_LOOPBACK-1); + loop->send++; + + memcpy (loop->msgs[i].data, data, length); + loop->msgs[i].datalen = length; +} + +//============================================================================= + +qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) +{ + int ret; + struct sockaddr_in from; + int fromlen; + int net_socket; + int protocol; + int err; + + if (NET_GetLoopPacket (sock, net_from, net_message)) + return true; + + for (protocol = 0 ; protocol < 2 ; protocol++) + { + if (protocol == 0) + net_socket = ip_sockets[sock]; + else + net_socket = ipx_sockets[sock]; + + if (!net_socket) + continue; + + fromlen = sizeof(from); + ret = recvfrom (net_socket, net_message->data, net_message->maxsize + , 0, (struct sockaddr *)&from, &fromlen); + if (ret == -1) + { + err = errno; + + if (err == EWOULDBLOCK || err == ECONNREFUSED) + continue; + Com_Printf ("NET_GetPacket: %s", NET_ErrorString()); + continue; + } + + if (ret == net_message->maxsize) + { + Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from)); + continue; + } + + net_message->cursize = ret; + SockadrToNetadr (&from, net_from); + return true; + } + + return false; +} + +//============================================================================= + +void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to) +{ + int ret; + struct sockaddr_in addr; + int net_socket; + + if ( to.type == NA_LOOPBACK ) + { + NET_SendLoopPacket (sock, length, data, to); + return; + } + + if (to.type == NA_BROADCAST) + { + net_socket = ip_sockets[sock]; + if (!net_socket) + return; + } + else if (to.type == NA_IP) + { + net_socket = ip_sockets[sock]; + if (!net_socket) + return; + } + else if (to.type == NA_IPX) + { + net_socket = ipx_sockets[sock]; + if (!net_socket) + return; + } + else if (to.type == NA_BROADCAST_IPX) + { + net_socket = ipx_sockets[sock]; + if (!net_socket) + return; + } + else + Com_Error (ERR_FATAL, "NET_SendPacket: bad address type"); + + NetadrToSockadr (&to, &addr); + + ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) ); + if (ret == -1) + { + Com_Printf ("NET_SendPacket ERROR: %i\n", NET_ErrorString()); + } +} + + +//============================================================================= + + + + +/* +==================== +NET_OpenIP +==================== +*/ +void NET_OpenIP (void) +{ + cvar_t *port, *ip; + + port = Cvar_Get ("port", va("%i", PORT_SERVER), CVAR_NOSET); + ip = Cvar_Get ("ip", "localhost", CVAR_NOSET); + + if (!ip_sockets[NS_SERVER]) + ip_sockets[NS_SERVER] = NET_Socket (ip->string, port->value); + if (!ip_sockets[NS_CLIENT]) + ip_sockets[NS_CLIENT] = NET_Socket (ip->string, PORT_ANY); +} + +/* +==================== +NET_OpenIPX +==================== +*/ +void NET_OpenIPX (void) +{ +} + + +/* +==================== +NET_Config + +A single player game will only use the loopback code +==================== +*/ +void NET_Config (qboolean multiplayer) +{ + int i; + + if (!multiplayer) + { // shut down any existing sockets + for (i=0 ; i<2 ; i++) + { + if (ip_sockets[i]) + { + close (ip_sockets[i]); + ip_sockets[i] = 0; + } + if (ipx_sockets[i]) + { + close (ipx_sockets[i]); + ipx_sockets[i] = 0; + } + } + } + else + { // open sockets + NET_OpenIP (); + NET_OpenIPX (); + } +} + + +//=================================================================== + + +/* +==================== +NET_Init +==================== +*/ +void NET_Init (void) +{ +} + + +/* +==================== +NET_Socket +==================== +*/ +int NET_Socket (char *net_interface, int port) +{ + int newsocket; + struct sockaddr_in address; + qboolean _true = true; + int i = 1; + + if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + { + Com_Printf ("ERROR: UDP_OpenSocket: socket:", NET_ErrorString()); + return 0; + } + + // make it non-blocking + if (ioctl (newsocket, FIONBIO, &_true) == -1) + { + Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString()); + return 0; + } + + // make it broadcast capable + if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1) + { + Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString()); + return 0; + } + + if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost")) + address.sin_addr.s_addr = INADDR_ANY; + else + NET_StringToSockaddr (net_interface, (struct sockaddr *)&address); + + if (port == PORT_ANY) + address.sin_port = 0; + else + address.sin_port = htons((short)port); + + address.sin_family = AF_INET; + + if( bind (newsocket, (void *)&address, sizeof(address)) == -1) + { + Com_Printf ("ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString()); + close (newsocket); + return 0; + } + + return newsocket; +} + + +/* +==================== +NET_Shutdown +==================== +*/ +void NET_Shutdown (void) +{ + NET_Config (false); // close sockets +} + + +/* +==================== +NET_ErrorString +==================== +*/ +char *NET_ErrorString (void) +{ + int code; + + code = errno; + return strerror (code); +} + +// sleeps msec or until net socket is ready +void NET_Sleep(int msec) +{ + struct timeval timeout; + fd_set fdset; + extern cvar_t *dedicated; + extern qboolean stdin_active; + + if (!ip_sockets[NS_SERVER] || (dedicated && !dedicated->value)) + return; // we're not a server, just run full speed + + FD_ZERO(&fdset); + if (stdin_active) + FD_SET(0, &fdset); // stdin is processed too + FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket + timeout.tv_sec = msec/1000; + timeout.tv_usec = (msec%1000)*1000; + select(ip_sockets[NS_SERVER]+1, &fdset, NULL, NULL, &timeout); +} +