mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-10 11:59:58 -05:00
Quack 2
This commit is contained in:
committed by
GitHub
parent
b585e51a81
commit
e8bd66b89c
769
game/g_save.c
Normal file
769
game/g_save.c
Normal file
@@ -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 ; i<game.maxclients ; i++)
|
||||
WriteClient (f, &game.clients[i]);
|
||||
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
void ReadGame (char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
char str[16];
|
||||
|
||||
gi.FreeTags (TAG_GAME);
|
||||
|
||||
f = fopen (filename, "rb");
|
||||
if (!f)
|
||||
gi.error ("Couldn't open %s", filename);
|
||||
|
||||
fread (str, sizeof(str), 1, f);
|
||||
if (strcmp (str, __DATE__))
|
||||
{
|
||||
fclose (f);
|
||||
gi.error ("Savegame from an older version.\n");
|
||||
}
|
||||
|
||||
g_edicts = gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
|
||||
globals.edicts = g_edicts;
|
||||
|
||||
fread (&game, sizeof(game), 1, f);
|
||||
game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
|
||||
for (i=0 ; i<game.maxclients ; i++)
|
||||
ReadClient (f, &game.clients[i]);
|
||||
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
WriteEdict
|
||||
|
||||
All pointer variables (except function pointers) must be handled specially.
|
||||
==============
|
||||
*/
|
||||
void WriteEdict (FILE *f, edict_t *ent)
|
||||
{
|
||||
field_t *field;
|
||||
edict_t temp;
|
||||
|
||||
// all of the ints, floats, and vectors stay as they are
|
||||
temp = *ent;
|
||||
|
||||
// change the pointers to lengths or indexes
|
||||
for (field=fields ; 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=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 ; i<globals.num_edicts ; i++)
|
||||
{
|
||||
ent = &g_edicts[i];
|
||||
if (!ent->inuse)
|
||||
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 ; i<maxclients->value ; 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 ; i<globals.num_edicts ; i++)
|
||||
{
|
||||
ent = &g_edicts[i];
|
||||
|
||||
if (!ent->inuse)
|
||||
continue;
|
||||
|
||||
// fire any cross-level triggers
|
||||
if (ent->classname)
|
||||
if (strcmp(ent->classname, "target_crosslevel_target") == 0)
|
||||
ent->nextthink = level.time + ent->delay;
|
||||
}
|
||||
}
|
||||
984
game/g_spawn.c
Normal file
984
game/g_spawn.c
Normal file
@@ -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 ; i<game.num_items ; i++,item++)
|
||||
{
|
||||
if (!item->classname)
|
||||
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 ; i<game.maxclients ; i++)
|
||||
g_edicts[i+1].client = game.clients + i;
|
||||
|
||||
ent = NULL;
|
||||
inhibit = 0;
|
||||
|
||||
// parse ents
|
||||
while (1)
|
||||
{
|
||||
// parse the opening brace
|
||||
com_token = COM_Parse (&entities);
|
||||
if (!entities)
|
||||
break;
|
||||
if (com_token[0] != '{')
|
||||
gi.error ("ED_LoadFromFile: found %s when expecting {",com_token);
|
||||
|
||||
if (!ent)
|
||||
ent = g_edicts;
|
||||
else
|
||||
ent = G_Spawn ();
|
||||
entities = ED_ParseEdict (entities, ent);
|
||||
|
||||
// yet another map hack
|
||||
if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "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 <value>
|
||||
xr <value>
|
||||
yb <value>
|
||||
yt <value>
|
||||
xv <value>
|
||||
yv <value>
|
||||
|
||||
// drawing
|
||||
statpic <name>
|
||||
pic <stat>
|
||||
num <fieldwidth> <stat>
|
||||
string <stat>
|
||||
|
||||
// control
|
||||
if <stat>
|
||||
ifeq <stat> <value>
|
||||
ifbit <stat> <value>
|
||||
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");
|
||||
}
|
||||
|
||||
300
game/g_svcmds.c
Normal file
300
game/g_svcmds.c
Normal file
@@ -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 <ip>
|
||||
removeip <ip>
|
||||
|
||||
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 <ip>" 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 ; i<numipfilters ; i++)
|
||||
if ( (in & ipfilters[i].mask) == ipfilters[i].compare)
|
||||
return (int)filterban->value;
|
||||
|
||||
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 <ip-mask>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
if (ipfilters[i].compare == 0xffffffff)
|
||||
break; // free spot
|
||||
if (i == numipfilters)
|
||||
{
|
||||
if (numipfilters == MAX_IPFILTERS)
|
||||
{
|
||||
gi.cprintf (NULL, PRINT_HIGH, "IP filter list is full\n");
|
||||
return;
|
||||
}
|
||||
numipfilters++;
|
||||
}
|
||||
|
||||
if (!StringToFilter (gi.argv(2), &ipfilters[i]))
|
||||
ipfilters[i].compare = 0xffffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_RemoveIP_f
|
||||
=================
|
||||
*/
|
||||
void SVCmd_RemoveIP_f (void)
|
||||
{
|
||||
ipfilter_t f;
|
||||
int i, j;
|
||||
|
||||
if (gi.argc() < 3) {
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Usage: sv removeip <ip-mask>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!StringToFilter (gi.argv(2), &f))
|
||||
return;
|
||||
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
if (ipfilters[i].mask == f.mask
|
||||
&& ipfilters[i].compare == f.compare)
|
||||
{
|
||||
for (j=i+1 ; j<numipfilters ; j++)
|
||||
ipfilters[j-1] = ipfilters[j];
|
||||
numipfilters--;
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Removed.\n");
|
||||
return;
|
||||
}
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Didn't find %s.\n", gi.argv(2));
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_ListIP_f
|
||||
=================
|
||||
*/
|
||||
void SVCmd_ListIP_f (void)
|
||||
{
|
||||
int i;
|
||||
byte b[4];
|
||||
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Filter list:\n");
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
{
|
||||
*(unsigned *)b = ipfilters[i].compare;
|
||||
gi.cprintf (NULL, PRINT_HIGH, "%3i.%3i.%3i.%3i\n", b[0], b[1], b[2], b[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_WriteIP_f
|
||||
=================
|
||||
*/
|
||||
void SVCmd_WriteIP_f (void)
|
||||
{
|
||||
FILE *f;
|
||||
char name[MAX_OSPATH];
|
||||
byte b[4];
|
||||
int i;
|
||||
cvar_t *game;
|
||||
|
||||
game = gi.cvar("game", "", 0);
|
||||
|
||||
if (!*game->string)
|
||||
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 ; i<numipfilters ; i++)
|
||||
{
|
||||
*(unsigned *)b = ipfilters[i].compare;
|
||||
fprintf (f, "sv addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]);
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
ServerCommand
|
||||
|
||||
ServerCommand will be called when an "sv" command is issued.
|
||||
The game can issue gi.argc() / gi.argv() commands to get the rest
|
||||
of the parameters
|
||||
=================
|
||||
*/
|
||||
void ServerCommand (void)
|
||||
{
|
||||
char *cmd;
|
||||
|
||||
cmd = gi.argv(1);
|
||||
if (Q_stricmp (cmd, "test") == 0)
|
||||
Svcmd_Test_f ();
|
||||
else if (Q_stricmp (cmd, "addip") == 0)
|
||||
SVCmd_AddIP_f ();
|
||||
else if (Q_stricmp (cmd, "removeip") == 0)
|
||||
SVCmd_RemoveIP_f ();
|
||||
else if (Q_stricmp (cmd, "listip") == 0)
|
||||
SVCmd_ListIP_f ();
|
||||
else if (Q_stricmp (cmd, "writeip") == 0)
|
||||
SVCmd_WriteIP_f ();
|
||||
else
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd);
|
||||
}
|
||||
|
||||
809
game/g_target.c
Normal file
809
game/g_target.c
Normal file
@@ -0,0 +1,809 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
/*QUAKED target_temp_entity (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
Fire an origin based temp entity event to the clients.
|
||||
"style" type byte
|
||||
*/
|
||||
void Use_Target_Tent (edict_t *ent, edict_t *other, edict_t *activator)
|
||||
{
|
||||
gi.WriteByte (svc_temp_entity);
|
||||
gi.WriteByte (ent->style);
|
||||
gi.WritePosition (ent->s.origin);
|
||||
gi.multicast (ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
void SP_target_temp_entity (edict_t *ent)
|
||||
{
|
||||
ent->use = Use_Target_Tent;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
//==========================================================
|
||||
|
||||
/*QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off reliable
|
||||
"noise" wav file to play
|
||||
"attenuation"
|
||||
-1 = none, send to whole level
|
||||
1 = normal fighting sounds
|
||||
2 = idle sound level
|
||||
3 = ambient sound level
|
||||
"volume" 0.0 to 1.0
|
||||
|
||||
Normal sounds play each time the target is used. The reliable flag can be set for crucial voiceovers.
|
||||
|
||||
Looped sounds are always atten 3 / vol 1, and the use function toggles it on/off.
|
||||
Multiple identical looping sounds will just increase volume without any speed cost.
|
||||
*/
|
||||
void Use_Target_Speaker (edict_t *ent, edict_t *other, edict_t *activator)
|
||||
{
|
||||
int chan;
|
||||
|
||||
if (ent->spawnflags & 3)
|
||||
{ // looping sound toggles
|
||||
if (ent->s.sound)
|
||||
ent->s.sound = 0; // turn it off
|
||||
else
|
||||
ent->s.sound = ent->noise_index; // start it
|
||||
}
|
||||
else
|
||||
{ // normal sound
|
||||
if (ent->spawnflags & 4)
|
||||
chan = CHAN_VOICE|CHAN_RELIABLE;
|
||||
else
|
||||
chan = CHAN_VOICE;
|
||||
// use a positioned_sound, because this entity won't normally be
|
||||
// sent to any clients because it is invisible
|
||||
gi.positioned_sound (ent->s.origin, ent, chan, ent->noise_index, ent->volume, ent->attenuation, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SP_target_speaker (edict_t *ent)
|
||||
{
|
||||
char buffer[MAX_QPATH];
|
||||
|
||||
if(!st.noise)
|
||||
{
|
||||
gi.dprintf("target_speaker with no noise set at %s\n", vtos(ent->s.origin));
|
||||
return;
|
||||
}
|
||||
if (!strstr (st.noise, ".wav"))
|
||||
Com_sprintf (buffer, sizeof(buffer), "%s.wav", st.noise);
|
||||
else
|
||||
strncpy (buffer, st.noise, sizeof(buffer));
|
||||
ent->noise_index = gi.soundindex (buffer);
|
||||
|
||||
if (!ent->volume)
|
||||
ent->volume = 1.0;
|
||||
|
||||
if (!ent->attenuation)
|
||||
ent->attenuation = 1.0;
|
||||
else if (ent->attenuation == -1) // use -1 so 0 defaults to 1
|
||||
ent->attenuation = 0;
|
||||
|
||||
// check for prestarted looping sound
|
||||
if (ent->spawnflags & 1)
|
||||
ent->s.sound = ent->noise_index;
|
||||
|
||||
ent->use = Use_Target_Speaker;
|
||||
|
||||
// must link the entity so we get areas and clusters so
|
||||
// the server can determine who to send updates to
|
||||
gi.linkentity (ent);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
void Use_Target_Help (edict_t *ent, edict_t *other, edict_t *activator)
|
||||
{
|
||||
if (ent->spawnflags & 1)
|
||||
strncpy (game.helpmessage1, ent->message, sizeof(game.helpmessage2)-1);
|
||||
else
|
||||
strncpy (game.helpmessage2, ent->message, sizeof(game.helpmessage1)-1);
|
||||
|
||||
game.helpchanged++;
|
||||
}
|
||||
|
||||
/*QUAKED target_help (1 0 1) (-16 -16 -24) (16 16 24) help1
|
||||
When fired, the "message" key becomes the current personal computer string, and the message light will be set on all clients status bars.
|
||||
*/
|
||||
void SP_target_help(edict_t *ent)
|
||||
{
|
||||
if (deathmatch->value)
|
||||
{ // auto-remove for deathmatch
|
||||
G_FreeEdict (ent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ent->message)
|
||||
{
|
||||
gi.dprintf ("%s with no message at %s\n", ent->classname, vtos(ent->s.origin));
|
||||
G_FreeEdict (ent);
|
||||
return;
|
||||
}
|
||||
ent->use = Use_Target_Help;
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
/*QUAKED target_secret (1 0 1) (-8 -8 -8) (8 8 8)
|
||||
Counts a secret found.
|
||||
These are single use targets.
|
||||
*/
|
||||
void use_target_secret (edict_t *ent, edict_t *other, edict_t *activator)
|
||||
{
|
||||
gi.sound (ent, CHAN_VOICE, ent->noise_index, 1, ATTN_NORM, 0);
|
||||
|
||||
level.found_secrets++;
|
||||
|
||||
G_UseTargets (ent, activator);
|
||||
G_FreeEdict (ent);
|
||||
}
|
||||
|
||||
void SP_target_secret (edict_t *ent)
|
||||
{
|
||||
if (deathmatch->value)
|
||||
{ // auto-remove for deathmatch
|
||||
G_FreeEdict (ent);
|
||||
return;
|
||||
}
|
||||
|
||||
ent->use = use_target_secret;
|
||||
if (!st.noise)
|
||||
st.noise = "misc/secret.wav";
|
||||
ent->noise_index = gi.soundindex (st.noise);
|
||||
ent->svflags = SVF_NOCLIENT;
|
||||
level.total_secrets++;
|
||||
// map bug hack
|
||||
if (!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");
|
||||
}
|
||||
598
game/g_trigger.c
Normal file
598
game/g_trigger.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
432
game/g_turret.c
Normal file
432
game/g_turret.c
Normal file
@@ -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);
|
||||
}
|
||||
568
game/g_utils.c
Normal file
568
game/g_utils.c
Normal file
@@ -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 ; i<globals.num_edicts ; i++, e++)
|
||||
{
|
||||
// the first couple seconds of server time can involve a lot of
|
||||
// freeing and allocating, so relax the replacement policy
|
||||
if (!e->inuse && ( 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 ; i<num ; i++)
|
||||
{
|
||||
hit = touch[i];
|
||||
if (!hit->inuse)
|
||||
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 ; i<num ; i++)
|
||||
{
|
||||
hit = touch[i];
|
||||
if (!hit->inuse)
|
||||
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
|
||||
}
|
||||
916
game/g_weapon.c
Normal file
916
game/g_weapon.c
Normal file
@@ -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);
|
||||
}
|
||||
1619
game/game.001
Normal file
1619
game/game.001
Normal file
File diff suppressed because it is too large
Load Diff
2
game/game.def
Normal file
2
game/game.def
Normal file
@@ -0,0 +1,2 @@
|
||||
EXPORTS
|
||||
GetGameAPI
|
||||
1618
game/game.dsp
Normal file
1618
game/game.dsp
Normal file
File diff suppressed because it is too large
Load Diff
254
game/game.h
Normal file
254
game/game.h
Normal file
@@ -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>" 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);
|
||||
75
game/game.plg
Normal file
75
game/game.plg
Normal file
@@ -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 ""
|
||||
"<Component 0xa>" with flags ""
|
||||
|
||||
Creating temp file "C:\TEMP\RSPA6.tmp" with contents </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/" /c
|
||||
"G:\quake2\code\game\p_weapon.c"
|
||||
>
|
||||
Creating command line "cl.exe @C:\TEMP\RSPA6.tmp"
|
||||
Creating temp file "C:\TEMP\RSPA7.tmp" with contents <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"
|
||||
.\ReleaseAXP\g_ai.obj
|
||||
.\ReleaseAXP\g_chase.obj
|
||||
.\ReleaseAXP\g_cmds.obj
|
||||
.\ReleaseAXP\g_combat.obj
|
||||
.\ReleaseAXP\g_func.obj
|
||||
.\ReleaseAXP\g_items.obj
|
||||
.\ReleaseAXP\g_main.obj
|
||||
.\ReleaseAXP\g_misc.obj
|
||||
.\ReleaseAXP\g_monster.obj
|
||||
.\ReleaseAXP\g_phys.obj
|
||||
.\ReleaseAXP\g_save.obj
|
||||
.\ReleaseAXP\g_spawn.obj
|
||||
.\ReleaseAXP\g_svcmds.obj
|
||||
.\ReleaseAXP\g_target.obj
|
||||
.\ReleaseAXP\g_trigger.obj
|
||||
.\ReleaseAXP\g_turret.obj
|
||||
.\ReleaseAXP\g_utils.obj
|
||||
.\ReleaseAXP\g_weapon.obj
|
||||
.\ReleaseAXP\m_actor.obj
|
||||
.\ReleaseAXP\m_berserk.obj
|
||||
.\ReleaseAXP\m_boss2.obj
|
||||
.\ReleaseAXP\m_boss3.obj
|
||||
.\ReleaseAXP\m_boss31.obj
|
||||
.\ReleaseAXP\m_boss32.obj
|
||||
.\ReleaseAXP\m_brain.obj
|
||||
.\ReleaseAXP\m_chick.obj
|
||||
.\ReleaseAXP\m_flash.obj
|
||||
.\ReleaseAXP\m_flipper.obj
|
||||
.\ReleaseAXP\m_float.obj
|
||||
.\ReleaseAXP\m_flyer.obj
|
||||
.\ReleaseAXP\m_gladiator.obj
|
||||
.\ReleaseAXP\m_gunner.obj
|
||||
.\ReleaseAXP\m_hover.obj
|
||||
.\ReleaseAXP\m_infantry.obj
|
||||
.\ReleaseAXP\m_insane.obj
|
||||
.\ReleaseAXP\m_medic.obj
|
||||
.\ReleaseAXP\m_move.obj
|
||||
.\ReleaseAXP\m_mutant.obj
|
||||
.\ReleaseAXP\m_parasite.obj
|
||||
.\ReleaseAXP\m_soldier.obj
|
||||
.\ReleaseAXP\m_supertank.obj
|
||||
.\ReleaseAXP\m_tank.obj
|
||||
.\ReleaseAXP\p_client.obj
|
||||
.\ReleaseAXP\p_hud.obj
|
||||
.\ReleaseAXP\p_trail.obj
|
||||
.\ReleaseAXP\p_view.obj
|
||||
.\ReleaseAXP\p_weapon.obj
|
||||
.\ReleaseAXP\q_shared.obj>
|
||||
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)
|
||||
609
game/m_actor.c
Normal file
609
game/m_actor.c
Normal file
@@ -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);
|
||||
}
|
||||
506
game/m_actor.h
Normal file
506
game/m_actor.h
Normal file
@@ -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
|
||||
457
game/m_berserk.c
Normal file
457
game/m_berserk.c
Normal file
@@ -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);
|
||||
}
|
||||
269
game/m_berserk.h
Normal file
269
game/m_berserk.h
Normal file
@@ -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
|
||||
679
game/m_boss2.c
Normal file
679
game/m_boss2.c
Normal file
@@ -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);
|
||||
}
|
||||
206
game/m_boss2.h
Normal file
206
game/m_boss2.h
Normal file
@@ -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
|
||||
76
game/m_boss3.c
Normal file
76
game/m_boss3.c
Normal file
@@ -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);
|
||||
}
|
||||
749
game/m_boss31.c
Normal file
749
game/m_boss31.c
Normal file
@@ -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);
|
||||
}
|
||||
213
game/m_boss31.h
Normal file
213
game/m_boss31.h
Normal file
@@ -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
|
||||
913
game/m_boss32.c
Normal file
913
game/m_boss32.c
Normal file
@@ -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);
|
||||
}
|
||||
516
game/m_boss32.h
Normal file
516
game/m_boss32.h
Normal file
@@ -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
|
||||
676
game/m_brain.c
Normal file
676
game/m_brain.c
Normal file
@@ -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);
|
||||
}
|
||||
247
game/m_brain.h
Normal file
247
game/m_brain.h
Normal file
@@ -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
|
||||
677
game/m_chick.c
Normal file
677
game/m_chick.c
Normal file
@@ -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);
|
||||
}
|
||||
313
game/m_chick.h
Normal file
313
game/m_chick.h
Normal file
@@ -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
|
||||
488
game/m_flash.c
Normal file
488
game/m_flash.c
Normal file
@@ -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
|
||||
};
|
||||
403
game/m_flipper.c
Normal file
403
game/m_flipper.c
Normal file
@@ -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);
|
||||
}
|
||||
185
game/m_flipper.h
Normal file
185
game/m_flipper.h
Normal file
@@ -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
|
||||
663
game/m_float.c
Normal file
663
game/m_float.c
Normal file
@@ -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);
|
||||
}
|
||||
273
game/m_float.h
Normal file
273
game/m_float.h
Normal file
@@ -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
|
||||
626
game/m_flyer.c
Normal file
626
game/m_flyer.c
Normal file
@@ -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);
|
||||
}
|
||||
182
game/m_flyer.h
Normal file
182
game/m_flyer.h
Normal file
@@ -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
|
||||
387
game/m_gladiator.c
Normal file
387
game/m_gladiator.c
Normal file
@@ -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);
|
||||
}
|
||||
115
game/m_gladiator.h
Normal file
115
game/m_gladiator.h
Normal file
@@ -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
|
||||
628
game/m_gunner.c
Normal file
628
game/m_gunner.c
Normal file
@@ -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);
|
||||
}
|
||||
234
game/m_gunner.h
Normal file
234
game/m_gunner.h
Normal file
@@ -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
|
||||
620
game/m_hover.c
Normal file
620
game/m_hover.c
Normal file
@@ -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);
|
||||
}
|
||||
230
game/m_hover.h
Normal file
230
game/m_hover.h
Normal file
@@ -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
|
||||
607
game/m_infantry.c
Normal file
607
game/m_infantry.c
Normal file
@@ -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);
|
||||
}
|
||||
232
game/m_infantry.h
Normal file
232
game/m_infantry.h
Normal file
@@ -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
|
||||
693
game/m_insane.c
Normal file
693
game/m_insane.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
307
game/m_insane.h
Normal file
307
game/m_insane.h
Normal file
@@ -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
|
||||
769
game/m_medic.c
Normal file
769
game/m_medic.c
Normal file
@@ -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);
|
||||
}
|
||||
262
game/m_medic.h
Normal file
262
game/m_medic.h
Normal file
@@ -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
|
||||
556
game/m_move.c
Normal file
556
game/m_move.c
Normal file
@@ -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);
|
||||
}
|
||||
663
game/m_mutant.c
Normal file
663
game/m_mutant.c
Normal file
@@ -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);
|
||||
}
|
||||
174
game/m_mutant.h
Normal file
174
game/m_mutant.h
Normal file
@@ -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
|
||||
552
game/m_parasite.c
Normal file
552
game/m_parasite.c
Normal file
@@ -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);
|
||||
}
|
||||
143
game/m_parasite.h
Normal file
143
game/m_parasite.h
Normal file
@@ -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
|
||||
224
game/m_player.h
Normal file
224
game/m_player.h
Normal file
@@ -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
|
||||
|
||||
66
game/m_rider.h
Normal file
66
game/m_rider.h
Normal file
@@ -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
|
||||
1299
game/m_soldier.c
Normal file
1299
game/m_soldier.c
Normal file
File diff suppressed because it is too large
Load Diff
500
game/m_soldier.h
Normal file
500
game/m_soldier.h
Normal file
@@ -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
|
||||
717
game/m_supertank.c
Normal file
717
game/m_supertank.c
Normal file
@@ -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);
|
||||
}
|
||||
279
game/m_supertank.h
Normal file
279
game/m_supertank.h
Normal file
@@ -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
|
||||
856
game/m_tank.c
Normal file
856
game/m_tank.c
Normal file
@@ -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;
|
||||
}
|
||||
319
game/m_tank.h
Normal file
319
game/m_tank.h
Normal file
@@ -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
|
||||
1805
game/p_client.c
Normal file
1805
game/p_client.c
Normal file
File diff suppressed because it is too large
Load Diff
571
game/p_hud.c
Normal file
571
game/p_hud.c
Normal file
@@ -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 ; i<maxclients->value ; 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 ; i<maxclients->value ; 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 ; i<maxclients->value ; 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 ; i<game.maxclients ; i++)
|
||||
{
|
||||
cl_ent = g_edicts + 1 + i;
|
||||
if (!cl_ent->inuse || game.clients[i].resp.spectator)
|
||||
continue;
|
||||
score = game.clients[i].resp.score;
|
||||
for (j=0 ; j<total ; j++)
|
||||
{
|
||||
if (score > 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<total ; i++)
|
||||
{
|
||||
cl = &game.clients[sorted[i]];
|
||||
cl_ent = g_edicts + 1 + sorted[i];
|
||||
|
||||
picnum = gi.imageindex ("i_fixme");
|
||||
x = (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;
|
||||
}
|
||||
|
||||
146
game/p_trail.c
Normal file
146
game/p_trail.c
Normal file
@@ -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)];
|
||||
}
|
||||
1087
game/p_view.c
Normal file
1087
game/p_view.c
Normal file
File diff suppressed because it is too large
Load Diff
1434
game/p_weapon.c
Normal file
1434
game/p_weapon.c
Normal file
File diff suppressed because it is too large
Load Diff
1418
game/q_shared.c
Normal file
1418
game/q_shared.c
Normal file
File diff suppressed because it is too large
Load Diff
1200
game/q_shared.h
Normal file
1200
game/q_shared.h
Normal file
File diff suppressed because it is too large
Load Diff
40
irix/cd_irix.c
Normal file
40
irix/cd_irix.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <sys/types.h>
|
||||
#include <cdaudio.h>
|
||||
|
||||
#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");
|
||||
}
|
||||
927
irix/glw_imp.c
Normal file
927
irix/glw_imp.c
Normal file
@@ -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 <signal.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <Xm/MwmUtil.h>
|
||||
|
||||
#include <GL/glx.h>
|
||||
|
||||
#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 <id#>\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<<b;
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
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<<b);
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
config_notify_width = x_event.xconfigure.width;
|
||||
config_notify_height = x_event.xconfigure.height;
|
||||
config_notify = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (doShm && x_event.type == x_shmeventtype)
|
||||
oktodraw = true;
|
||||
}
|
||||
|
||||
if (old_windowed_mouse != _windowed_mouse->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<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
|
||||
in_state->Key_Event_fp (K_MOUSE1 + i, true);
|
||||
|
||||
if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
|
||||
in_state->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");
|
||||
|
||||
}
|
||||
200
irix/q_shirix.c
Normal file
200
irix/q_shirix.c
Normal file
@@ -0,0 +1,200 @@
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
//============================================
|
||||
|
||||
3997
irix/qgl_irix.c
Normal file
3997
irix/qgl_irix.c
Normal file
File diff suppressed because it is too large
Load Diff
222
irix/snd_irix.c
Normal file
222
irix/snd_irix.c
Normal file
@@ -0,0 +1,222 @@
|
||||
#include <dmedia/dmedia.h>
|
||||
#include <dmedia/audio.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
}
|
||||
383
irix/sys_irix.c
Normal file
383
irix/sys_irix.c
Normal file
@@ -0,0 +1,383 @@
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <mntent.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#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
|
||||
426
irix/vid_menu.c
Normal file
426
irix/vid_menu.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
492
irix/vid_so.c
Normal file
492
irix/vid_so.c
Normal file
@@ -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 <errno.h>
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h> // ELF dl loader
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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());
|
||||
}
|
||||
|
||||
716
linux/Makefile.AXP
Normal file
716
linux/Makefile.AXP
Normal file
@@ -0,0 +1,716 @@
|
||||
#
|
||||
# Quake2 Makefile for Solaris
|
||||
#
|
||||
# Nov '97 by Zoid <zoid@idsoftware.com>
|
||||
#
|
||||
# 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)
|
||||
|
||||
1085
linux/Makefile.i386
Normal file
1085
linux/Makefile.i386
Normal file
File diff suppressed because it is too large
Load Diff
123
linux/block16.h
Normal file
123
linux/block16.h
Normal file
@@ -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
|
||||
124
linux/block8.h
Normal file
124
linux/block8.h
Normal file
@@ -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
|
||||
|
||||
420
linux/cd_linux.c
Normal file
420
linux/cd_linux.c
Normal file
@@ -0,0 +1,420 @@
|
||||
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
|
||||
// rights reserved.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <linux/cdrom.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
147
linux/d_copy.s
Normal file
147
linux/d_copy.s
Normal file
@@ -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
|
||||
|
||||
79
linux/d_ifacea.h
Normal file
79
linux/d_ifacea.h
Normal file
@@ -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
|
||||
|
||||
1250
linux/d_polysa.s
Normal file
1250
linux/d_polysa.s
Normal file
File diff suppressed because it is too large
Load Diff
206
linux/gl_fxmesa.c
Normal file
206
linux/gl_fxmesa.c
Normal file
@@ -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 <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vt.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "../ref_gl/gl_local.h"
|
||||
#include "../client/keys.h"
|
||||
#include "../linux/rw_linux.h"
|
||||
|
||||
#include <GL/fxmesa.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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<NUM_RESOLUTIONS;i++)
|
||||
if((*width<=resolutions[i][0]) && (*height<=resolutions[i][1])) {
|
||||
*width = resolutions[i][0];
|
||||
*height = resolutions[i][1];
|
||||
return resolutions[i][2];
|
||||
}
|
||||
|
||||
*width = 640;
|
||||
*height = 480;
|
||||
return GR_RESOLUTION_640x480;
|
||||
}
|
||||
|
||||
static void signal_handler(int sig)
|
||||
{
|
||||
printf("Received signal %d, exiting...\n", sig);
|
||||
GLimp_Shutdown();
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
static void InitSig(void)
|
||||
{
|
||||
signal(SIGHUP, signal_handler);
|
||||
signal(SIGQUIT, signal_handler);
|
||||
signal(SIGILL, signal_handler);
|
||||
signal(SIGTRAP, signal_handler);
|
||||
signal(SIGIOT, signal_handler);
|
||||
signal(SIGBUS, signal_handler);
|
||||
signal(SIGFPE, signal_handler);
|
||||
signal(SIGSEGV, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_SetMode
|
||||
*/
|
||||
int GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
|
||||
{
|
||||
int width, height;
|
||||
GLint attribs[32];
|
||||
|
||||
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 ();
|
||||
|
||||
// set fx attribs
|
||||
attribs[0] = FXMESA_DOUBLEBUFFER;
|
||||
attribs[1] = FXMESA_ALPHA_SIZE;
|
||||
attribs[2] = 1;
|
||||
attribs[3] = FXMESA_DEPTH_SIZE;
|
||||
attribs[4] = 1;
|
||||
attribs[5] = FXMESA_NONE;
|
||||
|
||||
fc = fxMesaCreateContext(0, findres(&width, &height), GR_REFRESH_75Hz,
|
||||
attribs);
|
||||
if (!fc)
|
||||
return rserr_invalid_mode;
|
||||
|
||||
*pwidth = width;
|
||||
*pheight = height;
|
||||
|
||||
// let the sound and input subsystems know about the new window
|
||||
ri.Vid_NewWindow (width, height);
|
||||
|
||||
fxMesaMakeCurrent(fc);
|
||||
|
||||
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 )
|
||||
{
|
||||
if (fc) {
|
||||
fxMesaDestroyContext(fc);
|
||||
fc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_Init
|
||||
**
|
||||
** This routine is responsible for initializing the OS specific portions
|
||||
** of OpenGL.
|
||||
*/
|
||||
int GLimp_Init( void *hinstance, void *wndproc )
|
||||
{
|
||||
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();
|
||||
fxMesaSwapBuffers();
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_AppActivate
|
||||
*/
|
||||
void GLimp_AppActivate( qboolean active )
|
||||
{
|
||||
}
|
||||
|
||||
extern void gl3DfxSetPaletteEXT(GLuint *pal);
|
||||
|
||||
void Fake_glColorTableEXT( GLenum target, GLenum internalformat,
|
||||
GLsizei width, GLenum format, GLenum type,
|
||||
const GLvoid *table )
|
||||
{
|
||||
byte temptable[256][4];
|
||||
byte *intbl;
|
||||
int i;
|
||||
|
||||
for (intbl = (byte *)table, i = 0; i < 256; i++) {
|
||||
temptable[i][2] = *intbl++;
|
||||
temptable[i][1] = *intbl++;
|
||||
temptable[i][0] = *intbl++;
|
||||
temptable[i][3] = 255;
|
||||
}
|
||||
gl3DfxSetPaletteEXT((GLuint *)temptable);
|
||||
}
|
||||
|
||||
|
||||
164
linux/glob.c
Normal file
164
linux/glob.c
Normal file
@@ -0,0 +1,164 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#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';
|
||||
}
|
||||
|
||||
1
linux/glob.h
Normal file
1
linux/glob.h
Normal file
@@ -0,0 +1 @@
|
||||
int glob_match(char *pattern, char *text);
|
||||
29
linux/in_linux.c
Normal file
29
linux/in_linux.c
Normal file
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
403
linux/math.s
Normal file
403
linux/math.s
Normal file
@@ -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
|
||||
537
linux/net_udp.c
Normal file
537
linux/net_udp.c
Normal file
@@ -0,0 +1,537 @@
|
||||
// net_wins.c
|
||||
|
||||
#include "../qcommon/qcommon.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef NeXT
|
||||
#include <libc.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user