mirror of
https://github.com/id-Software/Quake-III-Arena.git
synced 2026-05-14 09:59:07 +02:00
The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
# game building
|
||||
# builds the game for vanilla Q3 and TA
|
||||
|
||||
# there are slight differences between Q3 and TA build:
|
||||
# -DMISSIONPACK
|
||||
# the config is passed in the imported variable TARGET_DIR
|
||||
|
||||
# qvm building against native:
|
||||
# only native has g_syscalls.c
|
||||
# only qvm has ../game/bg_lib.c
|
||||
# qvm uses a custom g_syscalls.asm with equ stubs
|
||||
|
||||
Import qw( BASE_CFLAGS TARGET_DIR INSTALL_DIR NO_VM NO_SO CC CXX LINK );
|
||||
|
||||
$env = new cons(
|
||||
# the code has the very bad habit of doing things like #include "../ui/ui_shared.h"
|
||||
# this seems to confuse the dependency analysis, explicit toplevel includes seem to fix
|
||||
CPPPATH => '#cgame:#game:#q3_ui',
|
||||
CC => $CC,
|
||||
CXX => $CXX,
|
||||
LINK => $LINK,
|
||||
ENV => { PATH => $ENV{PATH}, HOME => $ENV{HOME} },
|
||||
CFLAGS => $BASE_CFLAGS . '-fPIC',
|
||||
LDFLAGS => '-shared -ldl -lm'
|
||||
);
|
||||
|
||||
# for TA, use -DMISSIONPACK
|
||||
%ta_env_hash = $env->copy(
|
||||
CPPPATH => '#cgame:#game:#ui'
|
||||
);
|
||||
$ta_env_hash{CFLAGS} = '-DMISSIONPACK ' . $ta_env_hash{CFLAGS};
|
||||
$ta_env = new cons(%ta_env_hash);
|
||||
|
||||
# qvm building
|
||||
# we heavily customize the cons environment
|
||||
$vm_env = new cons(
|
||||
# the code has the very bad habit of doing things like #include "../ui/ui_shared.h"
|
||||
# this seems to confuse the dependency analysis, explicit toplevel includes seem to fix
|
||||
CPPPATH => '#cgame:#game:#q3_ui',
|
||||
CC => 'q3lcc',
|
||||
CCCOM => '%CC %CFLAGS %_IFLAGS -c %< -o %>',
|
||||
SUFOBJ => '.asm',
|
||||
LINK => 'q3asm',
|
||||
CFLAGS => '-DQ3_VM -S -Wf-target=bytecode -Wf-g',
|
||||
# need to know where to find the compiler tools
|
||||
ENV => { PATH => $ENV{PATH} . ":./qvmtools", },
|
||||
);
|
||||
|
||||
# TA qvm building
|
||||
%vm_ta_env_hash = $vm_env->copy(
|
||||
CPPPATH => '#cgame:#game:#ui'
|
||||
);
|
||||
$vm_ta_env_hash{CFLAGS} = '-DMISSIONPACK ' . $vm_ta_env_hash{CFLAGS};
|
||||
$vm_ta_env = new cons(%vm_ta_env_hash);
|
||||
|
||||
# the file with vmMain function MUST be the first one of the list
|
||||
@FILES = qw(
|
||||
g_main.c
|
||||
ai_chat.c
|
||||
ai_cmd.c
|
||||
ai_dmnet.c
|
||||
ai_dmq3.c
|
||||
ai_main.c
|
||||
ai_team.c
|
||||
ai_vcmd.c
|
||||
bg_misc.c
|
||||
bg_pmove.c
|
||||
bg_slidemove.c
|
||||
g_active.c
|
||||
g_arenas.c
|
||||
g_bot.c
|
||||
g_client.c
|
||||
g_cmds.c
|
||||
g_combat.c
|
||||
g_items.c
|
||||
g_mem.c
|
||||
g_misc.c
|
||||
g_missile.c
|
||||
g_mover.c
|
||||
g_session.c
|
||||
g_spawn.c
|
||||
g_svcmds.c
|
||||
g_target.c
|
||||
g_team.c
|
||||
g_trigger.c
|
||||
g_utils.c
|
||||
g_weapon.c
|
||||
q_math.c
|
||||
q_shared.c
|
||||
);
|
||||
$FILESREF = \@FILES;
|
||||
|
||||
# only in .so
|
||||
# (VM uses a custom .asm with equ stubs)
|
||||
@SO_FILES = qw(
|
||||
g_syscalls.c
|
||||
);
|
||||
$SO_FILESREF = \@SO_FILES;
|
||||
|
||||
# only for VM
|
||||
@VM_FILES = qw(
|
||||
bg_lib.c
|
||||
g_syscalls.asm
|
||||
);
|
||||
$VM_FILESREF = \@VM_FILES;
|
||||
|
||||
# FIXME CPU string?
|
||||
# NOTE: $env $ta_env and $vm_env $vm_ta_env may not be necessary
|
||||
# we could alter the $env and $ta_env based on $TARGET_DIR
|
||||
# doing it this way to ensure homogeneity with cgame building
|
||||
if ($TARGET_DIR eq 'Q3')
|
||||
{
|
||||
if ($NO_SO eq 0)
|
||||
{
|
||||
Program $env 'qagamei386.so', @$FILESREF, @$SO_FILESREF;
|
||||
Install $env $INSTALL_DIR, 'qagamei386.so';
|
||||
}
|
||||
if ($NO_VM eq 0)
|
||||
{
|
||||
Depends $vm_env 'qagame.qvm', '#qvmtools/q3lcc';
|
||||
Depends $vm_env 'qagame.qvm', '#qvmtools/q3asm';
|
||||
Program $vm_env 'qagame.qvm', @$FILESREF, @$VM_FILESREF;
|
||||
Install $vm_env $INSTALL_DIR . '/vm', 'qagame.qvm';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($NO_SO eq 0)
|
||||
{
|
||||
Program $ta_env 'qagamei386.so', @$FILESREF, @$SO_FILESREF;
|
||||
Install $ta_env $INSTALL_DIR, 'qagamei386.so';
|
||||
}
|
||||
if ($NO_VM eq 0)
|
||||
{
|
||||
Depends $vm_env 'qagame.qvm', '#qvmtools/q3lcc';
|
||||
Depends $vm_env 'qagame.qvm', '#qvmtools/q3asm';
|
||||
Program $vm_ta_env 'qagame.qvm', @$FILESREF, @$VM_FILESREF;
|
||||
Install $vm_ta_env $INSTALL_DIR . '/vm', 'qagame.qvm';
|
||||
}
|
||||
}
|
||||
+1226
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: ai_chat.h
|
||||
*
|
||||
* desc: Quake3 bot AI
|
||||
*
|
||||
* $Archive: /source/code/botai/ai_chat.c $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//
|
||||
int BotChat_EnterGame(bot_state_t *bs);
|
||||
//
|
||||
int BotChat_ExitGame(bot_state_t *bs);
|
||||
//
|
||||
int BotChat_StartLevel(bot_state_t *bs);
|
||||
//
|
||||
int BotChat_EndLevel(bot_state_t *bs);
|
||||
//
|
||||
int BotChat_HitTalking(bot_state_t *bs);
|
||||
//
|
||||
int BotChat_HitNoDeath(bot_state_t *bs);
|
||||
//
|
||||
int BotChat_HitNoKill(bot_state_t *bs);
|
||||
//
|
||||
int BotChat_Death(bot_state_t *bs);
|
||||
//
|
||||
int BotChat_Kill(bot_state_t *bs);
|
||||
//
|
||||
int BotChat_EnemySuicide(bot_state_t *bs);
|
||||
//
|
||||
int BotChat_Random(bot_state_t *bs);
|
||||
// time the selected chat takes to type in
|
||||
float BotChatTime(bot_state_t *bs);
|
||||
// returns true if the bot can chat at the current position
|
||||
int BotValidChatPosition(bot_state_t *bs);
|
||||
// test the initial bot chats
|
||||
void BotChatTest(bot_state_t *bs);
|
||||
|
||||
+1992
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: ai_cmd.h
|
||||
*
|
||||
* desc: Quake3 bot AI
|
||||
*
|
||||
* $Archive: /source/code/botai/ai_chat.c $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
extern int notleader[MAX_CLIENTS];
|
||||
|
||||
int BotMatchMessage(bot_state_t *bs, char *message);
|
||||
void BotPrintTeamGoal(bot_state_t *bs);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: ai_dmnet.h
|
||||
*
|
||||
* desc: Quake3 bot AI
|
||||
*
|
||||
* $Archive: /source/code/botai/ai_chat.c $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define MAX_NODESWITCHES 50
|
||||
|
||||
void AIEnter_Intermission(bot_state_t *bs, char *s);
|
||||
void AIEnter_Observer(bot_state_t *bs, char *s);
|
||||
void AIEnter_Respawn(bot_state_t *bs, char *s);
|
||||
void AIEnter_Stand(bot_state_t *bs, char *s);
|
||||
void AIEnter_Seek_ActivateEntity(bot_state_t *bs, char *s);
|
||||
void AIEnter_Seek_NBG(bot_state_t *bs, char *s);
|
||||
void AIEnter_Seek_LTG(bot_state_t *bs, char *s);
|
||||
void AIEnter_Seek_Camp(bot_state_t *bs, char *s);
|
||||
void AIEnter_Battle_Fight(bot_state_t *bs, char *s);
|
||||
void AIEnter_Battle_Chase(bot_state_t *bs, char *s);
|
||||
void AIEnter_Battle_Retreat(bot_state_t *bs, char *s);
|
||||
void AIEnter_Battle_NBG(bot_state_t *bs, char *s);
|
||||
int AINode_Intermission(bot_state_t *bs);
|
||||
int AINode_Observer(bot_state_t *bs);
|
||||
int AINode_Respawn(bot_state_t *bs);
|
||||
int AINode_Stand(bot_state_t *bs);
|
||||
int AINode_Seek_ActivateEntity(bot_state_t *bs);
|
||||
int AINode_Seek_NBG(bot_state_t *bs);
|
||||
int AINode_Seek_LTG(bot_state_t *bs);
|
||||
int AINode_Battle_Fight(bot_state_t *bs);
|
||||
int AINode_Battle_Chase(bot_state_t *bs);
|
||||
int AINode_Battle_Retreat(bot_state_t *bs);
|
||||
int AINode_Battle_NBG(bot_state_t *bs);
|
||||
|
||||
void BotResetNodeSwitches(void);
|
||||
void BotDumpNodeSwitches(bot_state_t *bs);
|
||||
|
||||
+5461
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: ai_dmq3.h
|
||||
*
|
||||
* desc: Quake3 bot AI
|
||||
*
|
||||
* $Archive: /source/code/botai/ai_chat.c $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//setup the deathmatch AI
|
||||
void BotSetupDeathmatchAI(void);
|
||||
//shutdown the deathmatch AI
|
||||
void BotShutdownDeathmatchAI(void);
|
||||
//let the bot live within it's deathmatch AI net
|
||||
void BotDeathmatchAI(bot_state_t *bs, float thinktime);
|
||||
//free waypoints
|
||||
void BotFreeWaypoints(bot_waypoint_t *wp);
|
||||
//choose a weapon
|
||||
void BotChooseWeapon(bot_state_t *bs);
|
||||
//setup movement stuff
|
||||
void BotSetupForMovement(bot_state_t *bs);
|
||||
//update the inventory
|
||||
void BotUpdateInventory(bot_state_t *bs);
|
||||
//update the inventory during battle
|
||||
void BotUpdateBattleInventory(bot_state_t *bs, int enemy);
|
||||
//use holdable items during battle
|
||||
void BotBattleUseItems(bot_state_t *bs);
|
||||
//return true if the bot is dead
|
||||
qboolean BotIsDead(bot_state_t *bs);
|
||||
//returns true if the bot is in observer mode
|
||||
qboolean BotIsObserver(bot_state_t *bs);
|
||||
//returns true if the bot is in the intermission
|
||||
qboolean BotIntermission(bot_state_t *bs);
|
||||
//returns true if the bot is in lava or slime
|
||||
qboolean BotInLavaOrSlime(bot_state_t *bs);
|
||||
//returns true if the entity is dead
|
||||
qboolean EntityIsDead(aas_entityinfo_t *entinfo);
|
||||
//returns true if the entity is invisible
|
||||
qboolean EntityIsInvisible(aas_entityinfo_t *entinfo);
|
||||
//returns true if the entity is shooting
|
||||
qboolean EntityIsShooting(aas_entityinfo_t *entinfo);
|
||||
#ifdef MISSIONPACK
|
||||
//returns true if this entity has the kamikaze
|
||||
qboolean EntityHasKamikaze(aas_entityinfo_t *entinfo);
|
||||
#endif
|
||||
// set a user info key/value pair
|
||||
void BotSetUserInfo(bot_state_t *bs, char *key, char *value);
|
||||
// set the team status (offense, defense etc.)
|
||||
void BotSetTeamStatus(bot_state_t *bs);
|
||||
//returns the name of the client
|
||||
char *ClientName(int client, char *name, int size);
|
||||
//returns an simplyfied client name
|
||||
char *EasyClientName(int client, char *name, int size);
|
||||
//returns the skin used by the client
|
||||
char *ClientSkin(int client, char *skin, int size);
|
||||
// returns the appropriate synonym context for the current game type and situation
|
||||
int BotSynonymContext(bot_state_t *bs);
|
||||
// set last ordered task
|
||||
int BotSetLastOrderedTask(bot_state_t *bs);
|
||||
// selection of goals for teamplay
|
||||
void BotTeamGoals(bot_state_t *bs, int retreat);
|
||||
//returns the aggression of the bot in the range [0, 100]
|
||||
float BotAggression(bot_state_t *bs);
|
||||
//returns how bad the bot feels
|
||||
float BotFeelingBad(bot_state_t *bs);
|
||||
//returns true if the bot wants to retreat
|
||||
int BotWantsToRetreat(bot_state_t *bs);
|
||||
//returns true if the bot wants to chase
|
||||
int BotWantsToChase(bot_state_t *bs);
|
||||
//returns true if the bot wants to help
|
||||
int BotWantsToHelp(bot_state_t *bs);
|
||||
//returns true if the bot can and wants to rocketjump
|
||||
int BotCanAndWantsToRocketJump(bot_state_t *bs);
|
||||
// returns true if the bot has a persistant powerup and a weapon
|
||||
int BotHasPersistantPowerupAndWeapon(bot_state_t *bs);
|
||||
//returns true if the bot wants to and goes camping
|
||||
int BotWantsToCamp(bot_state_t *bs);
|
||||
//the bot will perform attack movements
|
||||
bot_moveresult_t BotAttackMove(bot_state_t *bs, int tfl);
|
||||
//returns true if the bot and the entity are in the same team
|
||||
int BotSameTeam(bot_state_t *bs, int entnum);
|
||||
//returns true if teamplay is on
|
||||
int TeamPlayIsOn(void);
|
||||
// returns the client number of the team mate flag carrier (-1 if none)
|
||||
int BotTeamFlagCarrier(bot_state_t *bs);
|
||||
//returns visible team mate flag carrier if available
|
||||
int BotTeamFlagCarrierVisible(bot_state_t *bs);
|
||||
//returns visible enemy flag carrier if available
|
||||
int BotEnemyFlagCarrierVisible(bot_state_t *bs);
|
||||
//get the number of visible teammates and enemies
|
||||
void BotVisibleTeamMatesAndEnemies(bot_state_t *bs, int *teammates, int *enemies, float range);
|
||||
//returns true if within the field of vision for the given angles
|
||||
qboolean InFieldOfVision(vec3_t viewangles, float fov, vec3_t angles);
|
||||
//returns true and sets the .enemy field when an enemy is found
|
||||
int BotFindEnemy(bot_state_t *bs, int curenemy);
|
||||
//returns a roam goal
|
||||
void BotRoamGoal(bot_state_t *bs, vec3_t goal);
|
||||
//returns entity visibility in the range [0, 1]
|
||||
float BotEntityVisible(int viewer, vec3_t eye, vec3_t viewangles, float fov, int ent);
|
||||
//the bot will aim at the current enemy
|
||||
void BotAimAtEnemy(bot_state_t *bs);
|
||||
//check if the bot should attack
|
||||
void BotCheckAttack(bot_state_t *bs);
|
||||
//AI when the bot is blocked
|
||||
void BotAIBlocked(bot_state_t *bs, bot_moveresult_t *moveresult, int activate);
|
||||
//AI to predict obstacles
|
||||
int BotAIPredictObstacles(bot_state_t *bs, bot_goal_t *goal);
|
||||
//enable or disable the areas the blocking entity is in
|
||||
void BotEnableActivateGoalAreas(bot_activategoal_t *activategoal, int enable);
|
||||
//pop an activate goal from the stack
|
||||
int BotPopFromActivateGoalStack(bot_state_t *bs);
|
||||
//clear the activate goal stack
|
||||
void BotClearActivateGoalStack(bot_state_t *bs);
|
||||
//returns the team the bot is in
|
||||
int BotTeam(bot_state_t *bs);
|
||||
//retuns the opposite team of the bot
|
||||
int BotOppositeTeam(bot_state_t *bs);
|
||||
//returns the flag the bot is carrying (CTFFLAG_?)
|
||||
int BotCTFCarryingFlag(bot_state_t *bs);
|
||||
//remember the last ordered task
|
||||
void BotRememberLastOrderedTask(bot_state_t *bs);
|
||||
//set ctf goals (defend base, get enemy flag) during seek
|
||||
void BotCTFSeekGoals(bot_state_t *bs);
|
||||
//set ctf goals (defend base, get enemy flag) during retreat
|
||||
void BotCTFRetreatGoals(bot_state_t *bs);
|
||||
//
|
||||
#ifdef MISSIONPACK
|
||||
int Bot1FCTFCarryingFlag(bot_state_t *bs);
|
||||
int BotHarvesterCarryingCubes(bot_state_t *bs);
|
||||
void Bot1FCTFSeekGoals(bot_state_t *bs);
|
||||
void Bot1FCTFRetreatGoals(bot_state_t *bs);
|
||||
void BotObeliskSeekGoals(bot_state_t *bs);
|
||||
void BotObeliskRetreatGoals(bot_state_t *bs);
|
||||
void BotGoHarvest(bot_state_t *bs);
|
||||
void BotHarvesterSeekGoals(bot_state_t *bs);
|
||||
void BotHarvesterRetreatGoals(bot_state_t *bs);
|
||||
int BotTeamCubeCarrierVisible(bot_state_t *bs);
|
||||
int BotEnemyCubeCarrierVisible(bot_state_t *bs);
|
||||
#endif
|
||||
//get a random alternate route goal towards the given base
|
||||
int BotGetAlternateRouteGoal(bot_state_t *bs, int base);
|
||||
//returns either the alternate route goal or the given goal
|
||||
bot_goal_t *BotAlternateRoute(bot_state_t *bs, bot_goal_t *goal);
|
||||
//create a new waypoint
|
||||
bot_waypoint_t *BotCreateWayPoint(char *name, vec3_t origin, int areanum);
|
||||
//find a waypoint with the given name
|
||||
bot_waypoint_t *BotFindWayPoint(bot_waypoint_t *waypoints, char *name);
|
||||
//strstr but case insensitive
|
||||
char *stristr(char *str, char *charset);
|
||||
//returns the number of the client with the given name
|
||||
int ClientFromName(char *name);
|
||||
int ClientOnSameTeamFromName(bot_state_t *bs, char *name);
|
||||
//
|
||||
int BotPointAreaNum(vec3_t origin);
|
||||
//
|
||||
void BotMapScripts(bot_state_t *bs);
|
||||
|
||||
//ctf flags
|
||||
#define CTF_FLAG_NONE 0
|
||||
#define CTF_FLAG_RED 1
|
||||
#define CTF_FLAG_BLUE 2
|
||||
//CTF skins
|
||||
#define CTF_SKIN_REDTEAM "red"
|
||||
#define CTF_SKIN_BLUETEAM "blue"
|
||||
|
||||
extern int gametype; //game type
|
||||
extern int maxclients; //maximum number of clients
|
||||
|
||||
extern vmCvar_t bot_grapple;
|
||||
extern vmCvar_t bot_rocketjump;
|
||||
extern vmCvar_t bot_fastchat;
|
||||
extern vmCvar_t bot_nochat;
|
||||
extern vmCvar_t bot_testrchat;
|
||||
extern vmCvar_t bot_challenge;
|
||||
|
||||
extern bot_goal_t ctf_redflag;
|
||||
extern bot_goal_t ctf_blueflag;
|
||||
#ifdef MISSIONPACK
|
||||
extern bot_goal_t ctf_neutralflag;
|
||||
extern bot_goal_t redobelisk;
|
||||
extern bot_goal_t blueobelisk;
|
||||
extern bot_goal_t neutralobelisk;
|
||||
#endif
|
||||
+1695
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: ai_main.h
|
||||
*
|
||||
* desc: Quake3 bot AI
|
||||
*
|
||||
* $Archive: /source/code/botai/ai_chat.c $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//#define DEBUG
|
||||
#define CTF
|
||||
|
||||
#define MAX_ITEMS 256
|
||||
//bot flags
|
||||
#define BFL_STRAFERIGHT 1 //strafe to the right
|
||||
#define BFL_ATTACKED 2 //bot has attacked last ai frame
|
||||
#define BFL_ATTACKJUMPED 4 //bot jumped during attack last frame
|
||||
#define BFL_AIMATENEMY 8 //bot aimed at the enemy this frame
|
||||
#define BFL_AVOIDRIGHT 16 //avoid obstacles by going to the right
|
||||
#define BFL_IDEALVIEWSET 32 //bot has ideal view angles set
|
||||
#define BFL_FIGHTSUICIDAL 64 //bot is in a suicidal fight
|
||||
//long term goal types
|
||||
#define LTG_TEAMHELP 1 //help a team mate
|
||||
#define LTG_TEAMACCOMPANY 2 //accompany a team mate
|
||||
#define LTG_DEFENDKEYAREA 3 //defend a key area
|
||||
#define LTG_GETFLAG 4 //get the enemy flag
|
||||
#define LTG_RUSHBASE 5 //rush to the base
|
||||
#define LTG_RETURNFLAG 6 //return the flag
|
||||
#define LTG_CAMP 7 //camp somewhere
|
||||
#define LTG_CAMPORDER 8 //ordered to camp somewhere
|
||||
#define LTG_PATROL 9 //patrol
|
||||
#define LTG_GETITEM 10 //get an item
|
||||
#define LTG_KILL 11 //kill someone
|
||||
#define LTG_HARVEST 12 //harvest skulls
|
||||
#define LTG_ATTACKENEMYBASE 13 //attack the enemy base
|
||||
#define LTG_MAKELOVE_UNDER 14
|
||||
#define LTG_MAKELOVE_ONTOP 15
|
||||
//some goal dedication times
|
||||
#define TEAM_HELP_TIME 60 //1 minute teamplay help time
|
||||
#define TEAM_ACCOMPANY_TIME 600 //10 minutes teamplay accompany time
|
||||
#define TEAM_DEFENDKEYAREA_TIME 600 //10 minutes ctf defend base time
|
||||
#define TEAM_CAMP_TIME 600 //10 minutes camping time
|
||||
#define TEAM_PATROL_TIME 600 //10 minutes patrolling time
|
||||
#define TEAM_LEAD_TIME 600 //10 minutes taking the lead
|
||||
#define TEAM_GETITEM_TIME 60 //1 minute
|
||||
#define TEAM_KILL_SOMEONE 180 //3 minute to kill someone
|
||||
#define TEAM_ATTACKENEMYBASE_TIME 600 //10 minutes
|
||||
#define TEAM_HARVEST_TIME 120 //2 minutes
|
||||
#define CTF_GETFLAG_TIME 600 //10 minutes ctf get flag time
|
||||
#define CTF_RUSHBASE_TIME 120 //2 minutes ctf rush base time
|
||||
#define CTF_RETURNFLAG_TIME 180 //3 minutes to return the flag
|
||||
#define CTF_ROAM_TIME 60 //1 minute ctf roam time
|
||||
//patrol flags
|
||||
#define PATROL_LOOP 1
|
||||
#define PATROL_REVERSE 2
|
||||
#define PATROL_BACK 4
|
||||
//teamplay task preference
|
||||
#define TEAMTP_DEFENDER 1
|
||||
#define TEAMTP_ATTACKER 2
|
||||
//CTF strategy
|
||||
#define CTFS_AGRESSIVE 1
|
||||
//copied from the aas file header
|
||||
#define PRESENCE_NONE 1
|
||||
#define PRESENCE_NORMAL 2
|
||||
#define PRESENCE_CROUCH 4
|
||||
//
|
||||
#define MAX_PROXMINES 64
|
||||
|
||||
//check points
|
||||
typedef struct bot_waypoint_s
|
||||
{
|
||||
int inuse;
|
||||
char name[32];
|
||||
bot_goal_t goal;
|
||||
struct bot_waypoint_s *next, *prev;
|
||||
} bot_waypoint_t;
|
||||
|
||||
#define MAX_ACTIVATESTACK 8
|
||||
#define MAX_ACTIVATEAREAS 32
|
||||
|
||||
typedef struct bot_activategoal_s
|
||||
{
|
||||
int inuse;
|
||||
bot_goal_t goal; //goal to activate (buttons etc.)
|
||||
float time; //time to activate something
|
||||
float start_time; //time starting to activate something
|
||||
float justused_time; //time the goal was used
|
||||
int shoot; //true if bot has to shoot to activate
|
||||
int weapon; //weapon to be used for activation
|
||||
vec3_t target; //target to shoot at to activate something
|
||||
vec3_t origin; //origin of the blocking entity to activate
|
||||
int areas[MAX_ACTIVATEAREAS]; //routing areas disabled by blocking entity
|
||||
int numareas; //number of disabled routing areas
|
||||
int areasdisabled; //true if the areas are disabled for the routing
|
||||
struct bot_activategoal_s *next; //next activate goal on stack
|
||||
} bot_activategoal_t;
|
||||
|
||||
//bot state
|
||||
typedef struct bot_state_s
|
||||
{
|
||||
int inuse; //true if this state is used by a bot client
|
||||
int botthink_residual; //residual for the bot thinks
|
||||
int client; //client number of the bot
|
||||
int entitynum; //entity number of the bot
|
||||
playerState_t cur_ps; //current player state
|
||||
int last_eFlags; //last ps flags
|
||||
usercmd_t lastucmd; //usercmd from last frame
|
||||
int entityeventTime[1024]; //last entity event time
|
||||
//
|
||||
bot_settings_t settings; //several bot settings
|
||||
int (*ainode)(struct bot_state_s *bs); //current AI node
|
||||
float thinktime; //time the bot thinks this frame
|
||||
vec3_t origin; //origin of the bot
|
||||
vec3_t velocity; //velocity of the bot
|
||||
int presencetype; //presence type of the bot
|
||||
vec3_t eye; //eye coordinates of the bot
|
||||
int areanum; //the number of the area the bot is in
|
||||
int inventory[MAX_ITEMS]; //string with items amounts the bot has
|
||||
int tfl; //the travel flags the bot uses
|
||||
int flags; //several flags
|
||||
int respawn_wait; //wait until respawned
|
||||
int lasthealth; //health value previous frame
|
||||
int lastkilledplayer; //last killed player
|
||||
int lastkilledby; //player that last killed this bot
|
||||
int botdeathtype; //the death type of the bot
|
||||
int enemydeathtype; //the death type of the enemy
|
||||
int botsuicide; //true when the bot suicides
|
||||
int enemysuicide; //true when the enemy of the bot suicides
|
||||
int setupcount; //true when the bot has just been setup
|
||||
int map_restart; //true when the map is being restarted
|
||||
int entergamechat; //true when the bot used an enter game chat
|
||||
int num_deaths; //number of time this bot died
|
||||
int num_kills; //number of kills of this bot
|
||||
int revenge_enemy; //the revenge enemy
|
||||
int revenge_kills; //number of kills the enemy made
|
||||
int lastframe_health; //health value the last frame
|
||||
int lasthitcount; //number of hits last frame
|
||||
int chatto; //chat to all or team
|
||||
float walker; //walker charactertic
|
||||
float ltime; //local bot time
|
||||
float entergame_time; //time the bot entered the game
|
||||
float ltg_time; //long term goal time
|
||||
float nbg_time; //nearby goal time
|
||||
float respawn_time; //time the bot takes to respawn
|
||||
float respawnchat_time; //time the bot started a chat during respawn
|
||||
float chase_time; //time the bot will chase the enemy
|
||||
float enemyvisible_time; //time the enemy was last visible
|
||||
float check_time; //time to check for nearby items
|
||||
float stand_time; //time the bot is standing still
|
||||
float lastchat_time; //time the bot last selected a chat
|
||||
float kamikaze_time; //time to check for kamikaze usage
|
||||
float invulnerability_time; //time to check for invulnerability usage
|
||||
float standfindenemy_time; //time to find enemy while standing
|
||||
float attackstrafe_time; //time the bot is strafing in one dir
|
||||
float attackcrouch_time; //time the bot will stop crouching
|
||||
float attackchase_time; //time the bot chases during actual attack
|
||||
float attackjump_time; //time the bot jumped during attack
|
||||
float enemysight_time; //time before reacting to enemy
|
||||
float enemydeath_time; //time the enemy died
|
||||
float enemyposition_time; //time the position and velocity of the enemy were stored
|
||||
float defendaway_time; //time away while defending
|
||||
float defendaway_range; //max travel time away from defend area
|
||||
float rushbaseaway_time; //time away from rushing to the base
|
||||
float attackaway_time; //time away from attacking the enemy base
|
||||
float harvestaway_time; //time away from harvesting
|
||||
float ctfroam_time; //time the bot is roaming in ctf
|
||||
float killedenemy_time; //time the bot killed the enemy
|
||||
float arrive_time; //time arrived (at companion)
|
||||
float lastair_time; //last time the bot had air
|
||||
float teleport_time; //last time the bot teleported
|
||||
float camp_time; //last time camped
|
||||
float camp_range; //camp range
|
||||
float weaponchange_time; //time the bot started changing weapons
|
||||
float firethrottlewait_time; //amount of time to wait
|
||||
float firethrottleshoot_time; //amount of time to shoot
|
||||
float notblocked_time; //last time the bot was not blocked
|
||||
float blockedbyavoidspot_time; //time blocked by an avoid spot
|
||||
float predictobstacles_time; //last time the bot predicted obstacles
|
||||
int predictobstacles_goalareanum; //last goal areanum the bot predicted obstacles for
|
||||
vec3_t aimtarget;
|
||||
vec3_t enemyvelocity; //enemy velocity 0.5 secs ago during battle
|
||||
vec3_t enemyorigin; //enemy origin 0.5 secs ago during battle
|
||||
//
|
||||
int kamikazebody; //kamikaze body
|
||||
int proxmines[MAX_PROXMINES];
|
||||
int numproxmines;
|
||||
//
|
||||
int character; //the bot character
|
||||
int ms; //move state of the bot
|
||||
int gs; //goal state of the bot
|
||||
int cs; //chat state of the bot
|
||||
int ws; //weapon state of the bot
|
||||
//
|
||||
int enemy; //enemy entity number
|
||||
int lastenemyareanum; //last reachability area the enemy was in
|
||||
vec3_t lastenemyorigin; //last origin of the enemy in the reachability area
|
||||
int weaponnum; //current weapon number
|
||||
vec3_t viewangles; //current view angles
|
||||
vec3_t ideal_viewangles; //ideal view angles
|
||||
vec3_t viewanglespeed;
|
||||
//
|
||||
int ltgtype; //long term goal type
|
||||
// team goals
|
||||
int teammate; //team mate involved in this team goal
|
||||
int decisionmaker; //player who decided to go for this goal
|
||||
int ordered; //true if ordered to do something
|
||||
float order_time; //time ordered to do something
|
||||
int owndecision_time; //time the bot made it's own decision
|
||||
bot_goal_t teamgoal; //the team goal
|
||||
bot_goal_t altroutegoal; //alternative route goal
|
||||
float reachedaltroutegoal_time; //time the bot reached the alt route goal
|
||||
float teammessage_time; //time to message team mates what the bot is doing
|
||||
float teamgoal_time; //time to stop helping team mate
|
||||
float teammatevisible_time; //last time the team mate was NOT visible
|
||||
int teamtaskpreference; //team task preference
|
||||
// last ordered team goal
|
||||
int lastgoal_decisionmaker;
|
||||
int lastgoal_ltgtype;
|
||||
int lastgoal_teammate;
|
||||
bot_goal_t lastgoal_teamgoal;
|
||||
// for leading team mates
|
||||
int lead_teammate; //team mate the bot is leading
|
||||
bot_goal_t lead_teamgoal; //team goal while leading
|
||||
float lead_time; //time leading someone
|
||||
float leadvisible_time; //last time the team mate was visible
|
||||
float leadmessage_time; //last time a messaged was sent to the team mate
|
||||
float leadbackup_time; //time backing up towards team mate
|
||||
//
|
||||
char teamleader[32]; //netname of the team leader
|
||||
float askteamleader_time; //time asked for team leader
|
||||
float becometeamleader_time; //time the bot will become the team leader
|
||||
float teamgiveorders_time; //time to give team orders
|
||||
float lastflagcapture_time; //last time a flag was captured
|
||||
int numteammates; //number of team mates
|
||||
int redflagstatus; //0 = at base, 1 = not at base
|
||||
int blueflagstatus; //0 = at base, 1 = not at base
|
||||
int neutralflagstatus; //0 = at base, 1 = our team has flag, 2 = enemy team has flag, 3 = enemy team dropped the flag
|
||||
int flagstatuschanged; //flag status changed
|
||||
int forceorders; //true if forced to give orders
|
||||
int flagcarrier; //team mate carrying the enemy flag
|
||||
int ctfstrategy; //ctf strategy
|
||||
char subteam[32]; //sub team name
|
||||
float formation_dist; //formation team mate intervening space
|
||||
char formation_teammate[16]; //netname of the team mate the bot uses for relative positioning
|
||||
float formation_angle; //angle relative to the formation team mate
|
||||
vec3_t formation_dir; //the direction the formation is moving in
|
||||
vec3_t formation_origin; //origin the bot uses for relative positioning
|
||||
bot_goal_t formation_goal; //formation goal
|
||||
|
||||
bot_activategoal_t *activatestack; //first activate goal on the stack
|
||||
bot_activategoal_t activategoalheap[MAX_ACTIVATESTACK]; //activate goal heap
|
||||
|
||||
bot_waypoint_t *checkpoints; //check points
|
||||
bot_waypoint_t *patrolpoints; //patrol points
|
||||
bot_waypoint_t *curpatrolpoint; //current patrol point the bot is going for
|
||||
int patrolflags; //patrol flags
|
||||
} bot_state_t;
|
||||
|
||||
//resets the whole bot state
|
||||
void BotResetState(bot_state_t *bs);
|
||||
//returns the number of bots in the game
|
||||
int NumBots(void);
|
||||
//returns info about the entity
|
||||
void BotEntityInfo(int entnum, aas_entityinfo_t *info);
|
||||
|
||||
extern float floattime;
|
||||
#define FloatTime() floattime
|
||||
|
||||
// from the game source
|
||||
void QDECL BotAI_Print(int type, char *fmt, ...);
|
||||
void QDECL QDECL BotAI_BotInitialChat( bot_state_t *bs, char *type, ... );
|
||||
void BotAI_Trace(bsp_trace_t *bsptrace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask);
|
||||
int BotAI_GetClientState( int clientNum, playerState_t *state );
|
||||
int BotAI_GetEntityState( int entityNum, entityState_t *state );
|
||||
int BotAI_GetSnapshotEntity( int clientNum, int sequence, entityState_t *state );
|
||||
int BotTeamLeader(bot_state_t *bs);
|
||||
+2080
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: ai_team.h
|
||||
*
|
||||
* desc: Quake3 bot AI
|
||||
*
|
||||
* $Archive: /source/code/botai/ai_chat.c $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void BotTeamAI(bot_state_t *bs);
|
||||
int BotGetTeamMateTaskPreference(bot_state_t *bs, int teammate);
|
||||
void BotSetTeamMateTaskPreference(bot_state_t *bs, int teammate, int preference);
|
||||
void BotVoiceChat(bot_state_t *bs, int toclient, char *voicechat);
|
||||
void BotVoiceChatOnly(bot_state_t *bs, int toclient, char *voicechat);
|
||||
|
||||
|
||||
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: ai_vcmd.c
|
||||
*
|
||||
* desc: Quake3 bot AI
|
||||
*
|
||||
* $Archive: /MissionPack/code/game/ai_vcmd.c $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "g_local.h"
|
||||
#include "botlib.h"
|
||||
#include "be_aas.h"
|
||||
#include "be_ea.h"
|
||||
#include "be_ai_char.h"
|
||||
#include "be_ai_chat.h"
|
||||
#include "be_ai_gen.h"
|
||||
#include "be_ai_goal.h"
|
||||
#include "be_ai_move.h"
|
||||
#include "be_ai_weap.h"
|
||||
//
|
||||
#include "ai_main.h"
|
||||
#include "ai_dmq3.h"
|
||||
#include "ai_chat.h"
|
||||
#include "ai_cmd.h"
|
||||
#include "ai_dmnet.h"
|
||||
#include "ai_team.h"
|
||||
#include "ai_vcmd.h"
|
||||
//
|
||||
#include "chars.h" //characteristics
|
||||
#include "inv.h" //indexes into the inventory
|
||||
#include "syn.h" //synonyms
|
||||
#include "match.h" //string matching types and vars
|
||||
|
||||
// for the voice chats
|
||||
#include "../../ui/menudef.h"
|
||||
|
||||
|
||||
typedef struct voiceCommand_s
|
||||
{
|
||||
char *cmd;
|
||||
void (*func)(bot_state_t *bs, int client, int mode);
|
||||
} voiceCommand_t;
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_GetFlag
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_GetFlag(bot_state_t *bs, int client, int mode) {
|
||||
//
|
||||
if (gametype == GT_CTF) {
|
||||
if (!ctf_redflag.areanum || !ctf_blueflag.areanum)
|
||||
return;
|
||||
}
|
||||
#ifdef MISSIONPACK
|
||||
else if (gametype == GT_1FCTF) {
|
||||
if (!ctf_neutralflag.areanum || !ctf_redflag.areanum || !ctf_blueflag.areanum)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return;
|
||||
}
|
||||
//
|
||||
bs->decisionmaker = client;
|
||||
bs->ordered = qtrue;
|
||||
bs->order_time = FloatTime();
|
||||
//set the time to send a message to the team mates
|
||||
bs->teammessage_time = FloatTime() + 2 * random();
|
||||
//set the ltg type
|
||||
bs->ltgtype = LTG_GETFLAG;
|
||||
//set the team goal time
|
||||
bs->teamgoal_time = FloatTime() + CTF_GETFLAG_TIME;
|
||||
// get an alternate route in ctf
|
||||
if (gametype == GT_CTF) {
|
||||
//get an alternative route goal towards the enemy base
|
||||
BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
|
||||
}
|
||||
//
|
||||
BotSetTeamStatus(bs);
|
||||
// remember last ordered task
|
||||
BotRememberLastOrderedTask(bs);
|
||||
#ifdef DEBUG
|
||||
BotPrintTeamGoal(bs);
|
||||
#endif //DEBUG
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_Offense
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_Offense(bot_state_t *bs, int client, int mode) {
|
||||
if ( gametype == GT_CTF
|
||||
#ifdef MISSIONPACK
|
||||
|| gametype == GT_1FCTF
|
||||
#endif
|
||||
) {
|
||||
BotVoiceChat_GetFlag(bs, client, mode);
|
||||
return;
|
||||
}
|
||||
#ifdef MISSIONPACK
|
||||
if (gametype == GT_HARVESTER) {
|
||||
//
|
||||
bs->decisionmaker = client;
|
||||
bs->ordered = qtrue;
|
||||
bs->order_time = FloatTime();
|
||||
//set the time to send a message to the team mates
|
||||
bs->teammessage_time = FloatTime() + 2 * random();
|
||||
//set the ltg type
|
||||
bs->ltgtype = LTG_HARVEST;
|
||||
//set the team goal time
|
||||
bs->teamgoal_time = FloatTime() + TEAM_HARVEST_TIME;
|
||||
bs->harvestaway_time = 0;
|
||||
//
|
||||
BotSetTeamStatus(bs);
|
||||
// remember last ordered task
|
||||
BotRememberLastOrderedTask(bs);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
//
|
||||
bs->decisionmaker = client;
|
||||
bs->ordered = qtrue;
|
||||
bs->order_time = FloatTime();
|
||||
//set the time to send a message to the team mates
|
||||
bs->teammessage_time = FloatTime() + 2 * random();
|
||||
//set the ltg type
|
||||
bs->ltgtype = LTG_ATTACKENEMYBASE;
|
||||
//set the team goal time
|
||||
bs->teamgoal_time = FloatTime() + TEAM_ATTACKENEMYBASE_TIME;
|
||||
bs->attackaway_time = 0;
|
||||
//
|
||||
BotSetTeamStatus(bs);
|
||||
// remember last ordered task
|
||||
BotRememberLastOrderedTask(bs);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
BotPrintTeamGoal(bs);
|
||||
#endif //DEBUG
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_Defend
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_Defend(bot_state_t *bs, int client, int mode) {
|
||||
#ifdef MISSIONPACK
|
||||
if ( gametype == GT_OBELISK || gametype == GT_HARVESTER) {
|
||||
//
|
||||
switch(BotTeam(bs)) {
|
||||
case TEAM_RED: memcpy(&bs->teamgoal, &redobelisk, sizeof(bot_goal_t)); break;
|
||||
case TEAM_BLUE: memcpy(&bs->teamgoal, &blueobelisk, sizeof(bot_goal_t)); break;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (gametype == GT_CTF
|
||||
#ifdef MISSIONPACK
|
||||
|| gametype == GT_1FCTF
|
||||
#endif
|
||||
) {
|
||||
//
|
||||
switch(BotTeam(bs)) {
|
||||
case TEAM_RED: memcpy(&bs->teamgoal, &ctf_redflag, sizeof(bot_goal_t)); break;
|
||||
case TEAM_BLUE: memcpy(&bs->teamgoal, &ctf_blueflag, sizeof(bot_goal_t)); break;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
//
|
||||
bs->decisionmaker = client;
|
||||
bs->ordered = qtrue;
|
||||
bs->order_time = FloatTime();
|
||||
//set the time to send a message to the team mates
|
||||
bs->teammessage_time = FloatTime() + 2 * random();
|
||||
//set the ltg type
|
||||
bs->ltgtype = LTG_DEFENDKEYAREA;
|
||||
//get the team goal time
|
||||
bs->teamgoal_time = FloatTime() + TEAM_DEFENDKEYAREA_TIME;
|
||||
//away from defending
|
||||
bs->defendaway_time = 0;
|
||||
//
|
||||
BotSetTeamStatus(bs);
|
||||
// remember last ordered task
|
||||
BotRememberLastOrderedTask(bs);
|
||||
#ifdef DEBUG
|
||||
BotPrintTeamGoal(bs);
|
||||
#endif //DEBUG
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_DefendFlag
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_DefendFlag(bot_state_t *bs, int client, int mode) {
|
||||
BotVoiceChat_Defend(bs, client, mode);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_Patrol
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_Patrol(bot_state_t *bs, int client, int mode) {
|
||||
//
|
||||
bs->decisionmaker = client;
|
||||
//
|
||||
bs->ltgtype = 0;
|
||||
bs->lead_time = 0;
|
||||
bs->lastgoal_ltgtype = 0;
|
||||
//
|
||||
BotAI_BotInitialChat(bs, "dismissed", NULL);
|
||||
trap_BotEnterChat(bs->cs, client, CHAT_TELL);
|
||||
BotVoiceChatOnly(bs, -1, VOICECHAT_ONPATROL);
|
||||
//
|
||||
BotSetTeamStatus(bs);
|
||||
#ifdef DEBUG
|
||||
BotPrintTeamGoal(bs);
|
||||
#endif //DEBUG
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_Camp
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_Camp(bot_state_t *bs, int client, int mode) {
|
||||
int areanum;
|
||||
aas_entityinfo_t entinfo;
|
||||
char netname[MAX_NETNAME];
|
||||
|
||||
//
|
||||
bs->teamgoal.entitynum = -1;
|
||||
BotEntityInfo(client, &entinfo);
|
||||
//if info is valid (in PVS)
|
||||
if (entinfo.valid) {
|
||||
areanum = BotPointAreaNum(entinfo.origin);
|
||||
if (areanum) { // && trap_AAS_AreaReachability(areanum)) {
|
||||
//NOTE: just assume the bot knows where the person is
|
||||
//if (BotEntityVisible(bs->entitynum, bs->eye, bs->viewangles, 360, client)) {
|
||||
bs->teamgoal.entitynum = client;
|
||||
bs->teamgoal.areanum = areanum;
|
||||
VectorCopy(entinfo.origin, bs->teamgoal.origin);
|
||||
VectorSet(bs->teamgoal.mins, -8, -8, -8);
|
||||
VectorSet(bs->teamgoal.maxs, 8, 8, 8);
|
||||
//}
|
||||
}
|
||||
}
|
||||
//if the other is not visible
|
||||
if (bs->teamgoal.entitynum < 0) {
|
||||
BotAI_BotInitialChat(bs, "whereareyou", EasyClientName(client, netname, sizeof(netname)), NULL);
|
||||
trap_BotEnterChat(bs->cs, client, CHAT_TELL);
|
||||
return;
|
||||
}
|
||||
//
|
||||
bs->decisionmaker = client;
|
||||
bs->ordered = qtrue;
|
||||
bs->order_time = FloatTime();
|
||||
//set the time to send a message to the team mates
|
||||
bs->teammessage_time = FloatTime() + 2 * random();
|
||||
//set the ltg type
|
||||
bs->ltgtype = LTG_CAMPORDER;
|
||||
//get the team goal time
|
||||
bs->teamgoal_time = FloatTime() + TEAM_CAMP_TIME;
|
||||
//the teammate that requested the camping
|
||||
bs->teammate = client;
|
||||
//not arrived yet
|
||||
bs->arrive_time = 0;
|
||||
//
|
||||
BotSetTeamStatus(bs);
|
||||
// remember last ordered task
|
||||
BotRememberLastOrderedTask(bs);
|
||||
#ifdef DEBUG
|
||||
BotPrintTeamGoal(bs);
|
||||
#endif //DEBUG
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_FollowMe
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_FollowMe(bot_state_t *bs, int client, int mode) {
|
||||
int areanum;
|
||||
aas_entityinfo_t entinfo;
|
||||
char netname[MAX_NETNAME];
|
||||
|
||||
bs->teamgoal.entitynum = -1;
|
||||
BotEntityInfo(client, &entinfo);
|
||||
//if info is valid (in PVS)
|
||||
if (entinfo.valid) {
|
||||
areanum = BotPointAreaNum(entinfo.origin);
|
||||
if (areanum) { // && trap_AAS_AreaReachability(areanum)) {
|
||||
bs->teamgoal.entitynum = client;
|
||||
bs->teamgoal.areanum = areanum;
|
||||
VectorCopy(entinfo.origin, bs->teamgoal.origin);
|
||||
VectorSet(bs->teamgoal.mins, -8, -8, -8);
|
||||
VectorSet(bs->teamgoal.maxs, 8, 8, 8);
|
||||
}
|
||||
}
|
||||
//if the other is not visible
|
||||
if (bs->teamgoal.entitynum < 0) {
|
||||
BotAI_BotInitialChat(bs, "whereareyou", EasyClientName(client, netname, sizeof(netname)), NULL);
|
||||
trap_BotEnterChat(bs->cs, client, CHAT_TELL);
|
||||
return;
|
||||
}
|
||||
//
|
||||
bs->decisionmaker = client;
|
||||
bs->ordered = qtrue;
|
||||
bs->order_time = FloatTime();
|
||||
//the team mate
|
||||
bs->teammate = client;
|
||||
//last time the team mate was assumed visible
|
||||
bs->teammatevisible_time = FloatTime();
|
||||
//set the time to send a message to the team mates
|
||||
bs->teammessage_time = FloatTime() + 2 * random();
|
||||
//get the team goal time
|
||||
bs->teamgoal_time = FloatTime() + TEAM_ACCOMPANY_TIME;
|
||||
//set the ltg type
|
||||
bs->ltgtype = LTG_TEAMACCOMPANY;
|
||||
bs->formation_dist = 3.5 * 32; //3.5 meter
|
||||
bs->arrive_time = 0;
|
||||
//
|
||||
BotSetTeamStatus(bs);
|
||||
// remember last ordered task
|
||||
BotRememberLastOrderedTask(bs);
|
||||
#ifdef DEBUG
|
||||
BotPrintTeamGoal(bs);
|
||||
#endif //DEBUG
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_FollowFlagCarrier
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_FollowFlagCarrier(bot_state_t *bs, int client, int mode) {
|
||||
int carrier;
|
||||
|
||||
carrier = BotTeamFlagCarrier(bs);
|
||||
if (carrier >= 0)
|
||||
BotVoiceChat_FollowMe(bs, carrier, mode);
|
||||
#ifdef DEBUG
|
||||
BotPrintTeamGoal(bs);
|
||||
#endif //DEBUG
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_ReturnFlag
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_ReturnFlag(bot_state_t *bs, int client, int mode) {
|
||||
//if not in CTF mode
|
||||
if (
|
||||
gametype != GT_CTF
|
||||
#ifdef MISSIONPACK
|
||||
&& gametype != GT_1FCTF
|
||||
#endif
|
||||
) {
|
||||
return;
|
||||
}
|
||||
//
|
||||
bs->decisionmaker = client;
|
||||
bs->ordered = qtrue;
|
||||
bs->order_time = FloatTime();
|
||||
//set the time to send a message to the team mates
|
||||
bs->teammessage_time = FloatTime() + 2 * random();
|
||||
//set the ltg type
|
||||
bs->ltgtype = LTG_RETURNFLAG;
|
||||
//set the team goal time
|
||||
bs->teamgoal_time = FloatTime() + CTF_RETURNFLAG_TIME;
|
||||
bs->rushbaseaway_time = 0;
|
||||
BotSetTeamStatus(bs);
|
||||
#ifdef DEBUG
|
||||
BotPrintTeamGoal(bs);
|
||||
#endif //DEBUG
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_StartLeader
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_StartLeader(bot_state_t *bs, int client, int mode) {
|
||||
ClientName(client, bs->teamleader, sizeof(bs->teamleader));
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_StopLeader
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_StopLeader(bot_state_t *bs, int client, int mode) {
|
||||
char netname[MAX_MESSAGE_SIZE];
|
||||
|
||||
if (!Q_stricmp(bs->teamleader, ClientName(client, netname, sizeof(netname)))) {
|
||||
bs->teamleader[0] = '\0';
|
||||
notleader[client] = qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_WhoIsLeader
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_WhoIsLeader(bot_state_t *bs, int client, int mode) {
|
||||
char netname[MAX_MESSAGE_SIZE];
|
||||
|
||||
if (!TeamPlayIsOn()) return;
|
||||
|
||||
ClientName(bs->client, netname, sizeof(netname));
|
||||
//if this bot IS the team leader
|
||||
if (!Q_stricmp(netname, bs->teamleader)) {
|
||||
BotAI_BotInitialChat(bs, "iamteamleader", NULL);
|
||||
trap_BotEnterChat(bs->cs, 0, CHAT_TEAM);
|
||||
BotVoiceChatOnly(bs, -1, VOICECHAT_STARTLEADER);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_WantOnDefense
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_WantOnDefense(bot_state_t *bs, int client, int mode) {
|
||||
char netname[MAX_NETNAME];
|
||||
int preference;
|
||||
|
||||
preference = BotGetTeamMateTaskPreference(bs, client);
|
||||
preference &= ~TEAMTP_ATTACKER;
|
||||
preference |= TEAMTP_DEFENDER;
|
||||
BotSetTeamMateTaskPreference(bs, client, preference);
|
||||
//
|
||||
EasyClientName(client, netname, sizeof(netname));
|
||||
BotAI_BotInitialChat(bs, "keepinmind", netname, NULL);
|
||||
trap_BotEnterChat(bs->cs, client, CHAT_TELL);
|
||||
BotVoiceChatOnly(bs, client, VOICECHAT_YES);
|
||||
trap_EA_Action(bs->client, ACTION_AFFIRMATIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
BotVoiceChat_WantOnOffense
|
||||
==================
|
||||
*/
|
||||
void BotVoiceChat_WantOnOffense(bot_state_t *bs, int client, int mode) {
|
||||
char netname[MAX_NETNAME];
|
||||
int preference;
|
||||
|
||||
preference = BotGetTeamMateTaskPreference(bs, client);
|
||||
preference &= ~TEAMTP_DEFENDER;
|
||||
preference |= TEAMTP_ATTACKER;
|
||||
BotSetTeamMateTaskPreference(bs, client, preference);
|
||||
//
|
||||
EasyClientName(client, netname, sizeof(netname));
|
||||
BotAI_BotInitialChat(bs, "keepinmind", netname, NULL);
|
||||
trap_BotEnterChat(bs->cs, client, CHAT_TELL);
|
||||
BotVoiceChatOnly(bs, client, VOICECHAT_YES);
|
||||
trap_EA_Action(bs->client, ACTION_AFFIRMATIVE);
|
||||
}
|
||||
|
||||
void BotVoiceChat_Dummy(bot_state_t *bs, int client, int mode) {
|
||||
}
|
||||
|
||||
voiceCommand_t voiceCommands[] = {
|
||||
{VOICECHAT_GETFLAG, BotVoiceChat_GetFlag},
|
||||
{VOICECHAT_OFFENSE, BotVoiceChat_Offense },
|
||||
{VOICECHAT_DEFEND, BotVoiceChat_Defend },
|
||||
{VOICECHAT_DEFENDFLAG, BotVoiceChat_DefendFlag },
|
||||
{VOICECHAT_PATROL, BotVoiceChat_Patrol },
|
||||
{VOICECHAT_CAMP, BotVoiceChat_Camp },
|
||||
{VOICECHAT_FOLLOWME, BotVoiceChat_FollowMe },
|
||||
{VOICECHAT_FOLLOWFLAGCARRIER, BotVoiceChat_FollowFlagCarrier },
|
||||
{VOICECHAT_RETURNFLAG, BotVoiceChat_ReturnFlag },
|
||||
{VOICECHAT_STARTLEADER, BotVoiceChat_StartLeader },
|
||||
{VOICECHAT_STOPLEADER, BotVoiceChat_StopLeader },
|
||||
{VOICECHAT_WHOISLEADER, BotVoiceChat_WhoIsLeader },
|
||||
{VOICECHAT_WANTONDEFENSE, BotVoiceChat_WantOnDefense },
|
||||
{VOICECHAT_WANTONOFFENSE, BotVoiceChat_WantOnOffense },
|
||||
{NULL, BotVoiceChat_Dummy}
|
||||
};
|
||||
|
||||
int BotVoiceChatCommand(bot_state_t *bs, int mode, char *voiceChat) {
|
||||
int i, voiceOnly, clientNum, color;
|
||||
char *ptr, buf[MAX_MESSAGE_SIZE], *cmd;
|
||||
|
||||
if (!TeamPlayIsOn()) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if ( mode == SAY_ALL ) {
|
||||
return qfalse; // don't do anything with voice chats to everyone
|
||||
}
|
||||
|
||||
Q_strncpyz(buf, voiceChat, sizeof(buf));
|
||||
cmd = buf;
|
||||
for (ptr = cmd; *cmd && *cmd > ' '; cmd++);
|
||||
while (*cmd && *cmd <= ' ') *cmd++ = '\0';
|
||||
voiceOnly = atoi(ptr);
|
||||
for (ptr = cmd; *cmd && *cmd > ' '; cmd++);
|
||||
while (*cmd && *cmd <= ' ') *cmd++ = '\0';
|
||||
clientNum = atoi(ptr);
|
||||
for (ptr = cmd; *cmd && *cmd > ' '; cmd++);
|
||||
while (*cmd && *cmd <= ' ') *cmd++ = '\0';
|
||||
color = atoi(ptr);
|
||||
|
||||
if (!BotSameTeam(bs, clientNum)) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
for (i = 0; voiceCommands[i].cmd; i++) {
|
||||
if (!Q_stricmp(cmd, voiceCommands[i].cmd)) {
|
||||
voiceCommands[i].func(bs, clientNum, mode);
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
return qfalse;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: ai_vcmd.h
|
||||
*
|
||||
* desc: Quake3 bot AI
|
||||
*
|
||||
* $Archive: /source/code/botai/ai_vcmd.c $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
int BotVoiceChatCommand(bot_state_t *bs, int mode, char *voicechat);
|
||||
void BotVoiceChat_Defend(bot_state_t *bs, int client, int mode);
|
||||
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: be_aas.h
|
||||
*
|
||||
* desc: Area Awareness System, stuff exported to the AI
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas.h $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef MAX_STRINGFIELD
|
||||
#define MAX_STRINGFIELD 80
|
||||
#endif
|
||||
|
||||
//travel flags
|
||||
#define TFL_INVALID 0x00000001 //traveling temporary not possible
|
||||
#define TFL_WALK 0x00000002 //walking
|
||||
#define TFL_CROUCH 0x00000004 //crouching
|
||||
#define TFL_BARRIERJUMP 0x00000008 //jumping onto a barrier
|
||||
#define TFL_JUMP 0x00000010 //jumping
|
||||
#define TFL_LADDER 0x00000020 //climbing a ladder
|
||||
#define TFL_WALKOFFLEDGE 0x00000080 //walking of a ledge
|
||||
#define TFL_SWIM 0x00000100 //swimming
|
||||
#define TFL_WATERJUMP 0x00000200 //jumping out of the water
|
||||
#define TFL_TELEPORT 0x00000400 //teleporting
|
||||
#define TFL_ELEVATOR 0x00000800 //elevator
|
||||
#define TFL_ROCKETJUMP 0x00001000 //rocket jumping
|
||||
#define TFL_BFGJUMP 0x00002000 //bfg jumping
|
||||
#define TFL_GRAPPLEHOOK 0x00004000 //grappling hook
|
||||
#define TFL_DOUBLEJUMP 0x00008000 //double jump
|
||||
#define TFL_RAMPJUMP 0x00010000 //ramp jump
|
||||
#define TFL_STRAFEJUMP 0x00020000 //strafe jump
|
||||
#define TFL_JUMPPAD 0x00040000 //jump pad
|
||||
#define TFL_AIR 0x00080000 //travel through air
|
||||
#define TFL_WATER 0x00100000 //travel through water
|
||||
#define TFL_SLIME 0x00200000 //travel through slime
|
||||
#define TFL_LAVA 0x00400000 //travel through lava
|
||||
#define TFL_DONOTENTER 0x00800000 //travel through donotenter area
|
||||
#define TFL_FUNCBOB 0x01000000 //func bobbing
|
||||
#define TFL_FLIGHT 0x02000000 //flight
|
||||
#define TFL_BRIDGE 0x04000000 //move over a bridge
|
||||
//
|
||||
#define TFL_NOTTEAM1 0x08000000 //not team 1
|
||||
#define TFL_NOTTEAM2 0x10000000 //not team 2
|
||||
|
||||
//default travel flags
|
||||
#define TFL_DEFAULT TFL_WALK|TFL_CROUCH|TFL_BARRIERJUMP|\
|
||||
TFL_JUMP|TFL_LADDER|\
|
||||
TFL_WALKOFFLEDGE|TFL_SWIM|TFL_WATERJUMP|\
|
||||
TFL_TELEPORT|TFL_ELEVATOR|\
|
||||
TFL_AIR|TFL_WATER|TFL_JUMPPAD|TFL_FUNCBOB
|
||||
|
||||
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;
|
||||
|
||||
//a trace is returned when a box is swept through the AAS world
|
||||
typedef struct aas_trace_s
|
||||
{
|
||||
qboolean startsolid; // if true, the initial point was in a solid area
|
||||
float fraction; // time completed, 1.0 = didn't hit anything
|
||||
vec3_t endpos; // final position
|
||||
int ent; // entity blocking the trace
|
||||
int lastarea; // last area the trace was in (zero if none)
|
||||
int area; // area blocking the trace (zero if none)
|
||||
int planenum; // number of the plane that was hit
|
||||
} aas_trace_t;
|
||||
|
||||
/* Defined in botlib.h
|
||||
|
||||
//bsp_trace_t hit surface
|
||||
typedef struct bsp_surface_s
|
||||
{
|
||||
char name[16];
|
||||
int flags;
|
||||
int value;
|
||||
} bsp_surface_t;
|
||||
|
||||
//a trace is returned when a box is swept through the BSP world
|
||||
typedef struct bsp_trace_s
|
||||
{
|
||||
qboolean allsolid; // if true, plane is not valid
|
||||
qboolean startsolid; // if true, the initial point was in a solid area
|
||||
float fraction; // time completed, 1.0 = didn't hit anything
|
||||
vec3_t endpos; // final position
|
||||
cplane_t plane; // surface normal at impact
|
||||
float exp_dist; // expanded plane distance
|
||||
int sidenum; // number of the brush side hit
|
||||
bsp_surface_t surface; // hit surface
|
||||
int contents; // contents on other side of surface hit
|
||||
int ent; // number of entity hit
|
||||
} bsp_trace_t;
|
||||
//
|
||||
*/
|
||||
|
||||
//entity info
|
||||
typedef struct aas_entityinfo_s
|
||||
{
|
||||
int valid; // true if updated this frame
|
||||
int type; // entity type
|
||||
int flags; // entity flags
|
||||
float ltime; // local time
|
||||
float update_time; // time between last and current update
|
||||
int number; // number of the entity
|
||||
vec3_t origin; // origin of the entity
|
||||
vec3_t angles; // angles of the model
|
||||
vec3_t old_origin; // for lerping
|
||||
vec3_t lastvisorigin; // last visible origin
|
||||
vec3_t mins; // bounding box minimums
|
||||
vec3_t maxs; // bounding box maximums
|
||||
int groundent; // ground entity
|
||||
int solid; // solid type
|
||||
int modelindex; // model used
|
||||
int modelindex2; // weapons, CTF flags, etc
|
||||
int frame; // model frame number
|
||||
int event; // impulse events -- muzzle flashes, footsteps, etc
|
||||
int eventParm; // even parameter
|
||||
int powerups; // bit flags
|
||||
int weapon; // determines weapon and flash model, etc
|
||||
int legsAnim; // mask off ANIM_TOGGLEBIT
|
||||
int torsoAnim; // mask off ANIM_TOGGLEBIT
|
||||
} aas_entityinfo_t;
|
||||
|
||||
// area info
|
||||
typedef struct aas_areainfo_s
|
||||
{
|
||||
int contents;
|
||||
int flags;
|
||||
int presencetype;
|
||||
int cluster;
|
||||
vec3_t mins;
|
||||
vec3_t maxs;
|
||||
vec3_t center;
|
||||
} aas_areainfo_t;
|
||||
|
||||
// client movement prediction stop events, stop as soon as:
|
||||
#define SE_NONE 0
|
||||
#define SE_HITGROUND 1 // the ground is hit
|
||||
#define SE_LEAVEGROUND 2 // there's no ground
|
||||
#define SE_ENTERWATER 4 // water is entered
|
||||
#define SE_ENTERSLIME 8 // slime is entered
|
||||
#define SE_ENTERLAVA 16 // lava is entered
|
||||
#define SE_HITGROUNDDAMAGE 32 // the ground is hit with damage
|
||||
#define SE_GAP 64 // there's a gap
|
||||
#define SE_TOUCHJUMPPAD 128 // touching a jump pad area
|
||||
#define SE_TOUCHTELEPORTER 256 // touching teleporter
|
||||
#define SE_ENTERAREA 512 // the given stoparea is entered
|
||||
#define SE_HITGROUNDAREA 1024 // a ground face in the area is hit
|
||||
#define SE_HITBOUNDINGBOX 2048 // hit the specified bounding box
|
||||
#define SE_TOUCHCLUSTERPORTAL 4096 // touching a cluster portal
|
||||
|
||||
typedef struct aas_clientmove_s
|
||||
{
|
||||
vec3_t endpos; //position at the end of movement prediction
|
||||
int endarea; //area at end of movement prediction
|
||||
vec3_t velocity; //velocity at the end of movement prediction
|
||||
aas_trace_t trace; //last trace
|
||||
int presencetype; //presence type at end of movement prediction
|
||||
int stopevent; //event that made the prediction stop
|
||||
int endcontents; //contents at the end of movement prediction
|
||||
float time; //time predicted ahead
|
||||
int frames; //number of frames predicted ahead
|
||||
} aas_clientmove_t;
|
||||
|
||||
// alternate route goals
|
||||
#define ALTROUTEGOAL_ALL 1
|
||||
#define ALTROUTEGOAL_CLUSTERPORTALS 2
|
||||
#define ALTROUTEGOAL_VIEWPORTALS 4
|
||||
|
||||
typedef struct aas_altroutegoal_s
|
||||
{
|
||||
vec3_t origin;
|
||||
int areanum;
|
||||
unsigned short starttraveltime;
|
||||
unsigned short goaltraveltime;
|
||||
unsigned short extratraveltime;
|
||||
} aas_altroutegoal_t;
|
||||
|
||||
// route prediction stop events
|
||||
#define RSE_NONE 0
|
||||
#define RSE_NOROUTE 1 //no route to goal
|
||||
#define RSE_USETRAVELTYPE 2 //stop as soon as on of the given travel types is used
|
||||
#define RSE_ENTERCONTENTS 4 //stop when entering the given contents
|
||||
#define RSE_ENTERAREA 8 //stop when entering the given area
|
||||
|
||||
typedef struct aas_predictroute_s
|
||||
{
|
||||
vec3_t endpos; //position at the end of movement prediction
|
||||
int endarea; //area at end of movement prediction
|
||||
int stopevent; //event that made the prediction stop
|
||||
int endcontents; //contents at the end of movement prediction
|
||||
int endtravelflags; //end travel flags
|
||||
int numareas; //number of areas predicted ahead
|
||||
int time; //time predicted ahead (in hundreth of a sec)
|
||||
} aas_predictroute_t;
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: be_ai_char.h
|
||||
*
|
||||
* desc: bot characters
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_ai_char.h $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//loads a bot character from a file
|
||||
int BotLoadCharacter(char *charfile, float skill);
|
||||
//frees a bot character
|
||||
void BotFreeCharacter(int character);
|
||||
//returns a float characteristic
|
||||
float Characteristic_Float(int character, int index);
|
||||
//returns a bounded float characteristic
|
||||
float Characteristic_BFloat(int character, int index, float min, float max);
|
||||
//returns an integer characteristic
|
||||
int Characteristic_Integer(int character, int index);
|
||||
//returns a bounded integer characteristic
|
||||
int Characteristic_BInteger(int character, int index, int min, int max);
|
||||
//returns a string characteristic
|
||||
void Characteristic_String(int character, int index, char *buf, int size);
|
||||
//free cached bot characters
|
||||
void BotShutdownCharacters(void);
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
/*****************************************************************************
|
||||
* name: be_ai_chat.h
|
||||
*
|
||||
* desc: char AI
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_ai_chat.h $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define MAX_MESSAGE_SIZE 256
|
||||
#define MAX_CHATTYPE_NAME 32
|
||||
#define MAX_MATCHVARIABLES 8
|
||||
|
||||
#define CHAT_GENDERLESS 0
|
||||
#define CHAT_GENDERFEMALE 1
|
||||
#define CHAT_GENDERMALE 2
|
||||
|
||||
#define CHAT_ALL 0
|
||||
#define CHAT_TEAM 1
|
||||
#define CHAT_TELL 2
|
||||
|
||||
//a console message
|
||||
typedef struct bot_consolemessage_s
|
||||
{
|
||||
int handle;
|
||||
float time; //message time
|
||||
int type; //message type
|
||||
char message[MAX_MESSAGE_SIZE]; //message
|
||||
struct bot_consolemessage_s *prev, *next; //prev and next in list
|
||||
} bot_consolemessage_t;
|
||||
|
||||
//match variable
|
||||
typedef struct bot_matchvariable_s
|
||||
{
|
||||
char offset;
|
||||
int length;
|
||||
} bot_matchvariable_t;
|
||||
//returned to AI when a match is found
|
||||
typedef struct bot_match_s
|
||||
{
|
||||
char string[MAX_MESSAGE_SIZE];
|
||||
int type;
|
||||
int subtype;
|
||||
bot_matchvariable_t variables[MAX_MATCHVARIABLES];
|
||||
} bot_match_t;
|
||||
|
||||
//setup the chat AI
|
||||
int BotSetupChatAI(void);
|
||||
//shutdown the chat AI
|
||||
void BotShutdownChatAI(void);
|
||||
//returns the handle to a newly allocated chat state
|
||||
int BotAllocChatState(void);
|
||||
//frees the chatstate
|
||||
void BotFreeChatState(int handle);
|
||||
//adds a console message to the chat state
|
||||
void BotQueueConsoleMessage(int chatstate, int type, char *message);
|
||||
//removes the console message from the chat state
|
||||
void BotRemoveConsoleMessage(int chatstate, int handle);
|
||||
//returns the next console message from the state
|
||||
int BotNextConsoleMessage(int chatstate, bot_consolemessage_t *cm);
|
||||
//returns the number of console messages currently stored in the state
|
||||
int BotNumConsoleMessages(int chatstate);
|
||||
//selects a chat message of the given type
|
||||
void BotInitialChat(int chatstate, char *type, int mcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7);
|
||||
//returns the number of initial chat messages of the given type
|
||||
int BotNumInitialChats(int chatstate, char *type);
|
||||
//find and select a reply for the given message
|
||||
int BotReplyChat(int chatstate, char *message, int mcontext, int vcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7);
|
||||
//returns the length of the currently selected chat message
|
||||
int BotChatLength(int chatstate);
|
||||
//enters the selected chat message
|
||||
void BotEnterChat(int chatstate, int clientto, int sendto);
|
||||
//get the chat message ready to be output
|
||||
void BotGetChatMessage(int chatstate, char *buf, int size);
|
||||
//checks if the first string contains the second one, returns index into first string or -1 if not found
|
||||
int StringContains(char *str1, char *str2, int casesensitive);
|
||||
//finds a match for the given string using the match templates
|
||||
int BotFindMatch(char *str, bot_match_t *match, unsigned long int context);
|
||||
//returns a variable from a match
|
||||
void BotMatchVariable(bot_match_t *match, int variable, char *buf, int size);
|
||||
//unify all the white spaces in the string
|
||||
void UnifyWhiteSpaces(char *string);
|
||||
//replace all the context related synonyms in the string
|
||||
void BotReplaceSynonyms(char *string, unsigned long int context);
|
||||
//loads a chat file for the chat state
|
||||
int BotLoadChatFile(int chatstate, char *chatfile, char *chatname);
|
||||
//store the gender of the bot in the chat state
|
||||
void BotSetChatGender(int chatstate, int gender);
|
||||
//store the bot name in the chat state
|
||||
void BotSetChatName(int chatstate, char *name, int client);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: be_ai_gen.h
|
||||
*
|
||||
* desc: genetic selection
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_ai_gen.h $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
int GeneticParentsAndChildSelection(int numranks, float *ranks, int *parent1, int *parent2, int *child);
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
/*****************************************************************************
|
||||
* name: be_ai_goal.h
|
||||
*
|
||||
* desc: goal AI
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_ai_goal.h $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define MAX_AVOIDGOALS 256
|
||||
#define MAX_GOALSTACK 8
|
||||
|
||||
#define GFL_NONE 0
|
||||
#define GFL_ITEM 1
|
||||
#define GFL_ROAM 2
|
||||
#define GFL_DROPPED 4
|
||||
|
||||
//a bot goal
|
||||
typedef struct bot_goal_s
|
||||
{
|
||||
vec3_t origin; //origin of the goal
|
||||
int areanum; //area number of the goal
|
||||
vec3_t mins, maxs; //mins and maxs of the goal
|
||||
int entitynum; //number of the goal entity
|
||||
int number; //goal number
|
||||
int flags; //goal flags
|
||||
int iteminfo; //item information
|
||||
} bot_goal_t;
|
||||
|
||||
//reset the whole goal state, but keep the item weights
|
||||
void BotResetGoalState(int goalstate);
|
||||
//reset avoid goals
|
||||
void BotResetAvoidGoals(int goalstate);
|
||||
//remove the goal with the given number from the avoid goals
|
||||
void BotRemoveFromAvoidGoals(int goalstate, int number);
|
||||
//push a goal onto the goal stack
|
||||
void BotPushGoal(int goalstate, bot_goal_t *goal);
|
||||
//pop a goal from the goal stack
|
||||
void BotPopGoal(int goalstate);
|
||||
//empty the bot's goal stack
|
||||
void BotEmptyGoalStack(int goalstate);
|
||||
//dump the avoid goals
|
||||
void BotDumpAvoidGoals(int goalstate);
|
||||
//dump the goal stack
|
||||
void BotDumpGoalStack(int goalstate);
|
||||
//get the name name of the goal with the given number
|
||||
void BotGoalName(int number, char *name, int size);
|
||||
//get the top goal from the stack
|
||||
int BotGetTopGoal(int goalstate, bot_goal_t *goal);
|
||||
//get the second goal on the stack
|
||||
int BotGetSecondGoal(int goalstate, bot_goal_t *goal);
|
||||
//choose the best long term goal item for the bot
|
||||
int BotChooseLTGItem(int goalstate, vec3_t origin, int *inventory, int travelflags);
|
||||
//choose the best nearby goal item for the bot
|
||||
//the item may not be further away from the current bot position than maxtime
|
||||
//also the travel time from the nearby goal towards the long term goal may not
|
||||
//be larger than the travel time towards the long term goal from the current bot position
|
||||
int BotChooseNBGItem(int goalstate, vec3_t origin, int *inventory, int travelflags,
|
||||
bot_goal_t *ltg, float maxtime);
|
||||
//returns true if the bot touches the goal
|
||||
int BotTouchingGoal(vec3_t origin, bot_goal_t *goal);
|
||||
//returns true if the goal should be visible but isn't
|
||||
int BotItemGoalInVisButNotVisible(int viewer, vec3_t eye, vec3_t viewangles, bot_goal_t *goal);
|
||||
//search for a goal for the given classname, the index can be used
|
||||
//as a start point for the search when multiple goals are available with that same classname
|
||||
int BotGetLevelItemGoal(int index, char *classname, bot_goal_t *goal);
|
||||
//get the next camp spot in the map
|
||||
int BotGetNextCampSpotGoal(int num, bot_goal_t *goal);
|
||||
//get the map location with the given name
|
||||
int BotGetMapLocationGoal(char *name, bot_goal_t *goal);
|
||||
//returns the avoid goal time
|
||||
float BotAvoidGoalTime(int goalstate, int number);
|
||||
//set the avoid goal time
|
||||
void BotSetAvoidGoalTime(int goalstate, int number, float avoidtime);
|
||||
//initializes the items in the level
|
||||
void BotInitLevelItems(void);
|
||||
//regularly update dynamic entity items (dropped weapons, flags etc.)
|
||||
void BotUpdateEntityItems(void);
|
||||
//interbreed the goal fuzzy logic
|
||||
void BotInterbreedGoalFuzzyLogic(int parent1, int parent2, int child);
|
||||
//save the goal fuzzy logic to disk
|
||||
void BotSaveGoalFuzzyLogic(int goalstate, char *filename);
|
||||
//mutate the goal fuzzy logic
|
||||
void BotMutateGoalFuzzyLogic(int goalstate, float range);
|
||||
//loads item weights for the bot
|
||||
int BotLoadItemWeights(int goalstate, char *filename);
|
||||
//frees the item weights of the bot
|
||||
void BotFreeItemWeights(int goalstate);
|
||||
//returns the handle of a newly allocated goal state
|
||||
int BotAllocGoalState(int client);
|
||||
//free the given goal state
|
||||
void BotFreeGoalState(int handle);
|
||||
//setup the goal AI
|
||||
int BotSetupGoalAI(void);
|
||||
//shut down the goal AI
|
||||
void BotShutdownGoalAI(void);
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: be_ai_move.h
|
||||
*
|
||||
* desc: movement AI
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_ai_move.h $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//movement types
|
||||
#define MOVE_WALK 1
|
||||
#define MOVE_CROUCH 2
|
||||
#define MOVE_JUMP 4
|
||||
#define MOVE_GRAPPLE 8
|
||||
#define MOVE_ROCKETJUMP 16
|
||||
#define MOVE_BFGJUMP 32
|
||||
//move flags
|
||||
#define MFL_BARRIERJUMP 1 //bot is performing a barrier jump
|
||||
#define MFL_ONGROUND 2 //bot is in the ground
|
||||
#define MFL_SWIMMING 4 //bot is swimming
|
||||
#define MFL_AGAINSTLADDER 8 //bot is against a ladder
|
||||
#define MFL_WATERJUMP 16 //bot is waterjumping
|
||||
#define MFL_TELEPORTED 32 //bot is being teleported
|
||||
#define MFL_GRAPPLEPULL 64 //bot is being pulled by the grapple
|
||||
#define MFL_ACTIVEGRAPPLE 128 //bot is using the grapple hook
|
||||
#define MFL_GRAPPLERESET 256 //bot has reset the grapple
|
||||
#define MFL_WALK 512 //bot should walk slowly
|
||||
// move result flags
|
||||
#define MOVERESULT_MOVEMENTVIEW 1 //bot uses view for movement
|
||||
#define MOVERESULT_SWIMVIEW 2 //bot uses view for swimming
|
||||
#define MOVERESULT_WAITING 4 //bot is waiting for something
|
||||
#define MOVERESULT_MOVEMENTVIEWSET 8 //bot has set the view in movement code
|
||||
#define MOVERESULT_MOVEMENTWEAPON 16 //bot uses weapon for movement
|
||||
#define MOVERESULT_ONTOPOFOBSTACLE 32 //bot is ontop of obstacle
|
||||
#define MOVERESULT_ONTOPOF_FUNCBOB 64 //bot is ontop of a func_bobbing
|
||||
#define MOVERESULT_ONTOPOF_ELEVATOR 128 //bot is ontop of an elevator (func_plat)
|
||||
#define MOVERESULT_BLOCKEDBYAVOIDSPOT 256 //bot is blocked by an avoid spot
|
||||
//
|
||||
#define MAX_AVOIDREACH 1
|
||||
#define MAX_AVOIDSPOTS 32
|
||||
// avoid spot types
|
||||
#define AVOID_CLEAR 0 //clear all avoid spots
|
||||
#define AVOID_ALWAYS 1 //avoid always
|
||||
#define AVOID_DONTBLOCK 2 //never totally block
|
||||
// restult types
|
||||
#define RESULTTYPE_ELEVATORUP 1 //elevator is up
|
||||
#define RESULTTYPE_WAITFORFUNCBOBBING 2 //waiting for func bobbing to arrive
|
||||
#define RESULTTYPE_BADGRAPPLEPATH 4 //grapple path is obstructed
|
||||
#define RESULTTYPE_INSOLIDAREA 8 //stuck in solid area, this is bad
|
||||
|
||||
//structure used to initialize the movement state
|
||||
//the or_moveflags MFL_ONGROUND, MFL_TELEPORTED and MFL_WATERJUMP come from the playerstate
|
||||
typedef struct bot_initmove_s
|
||||
{
|
||||
vec3_t origin; //origin of the bot
|
||||
vec3_t velocity; //velocity of the bot
|
||||
vec3_t viewoffset; //view offset
|
||||
int entitynum; //entity number of the bot
|
||||
int client; //client number of the bot
|
||||
float thinktime; //time the bot thinks
|
||||
int presencetype; //presencetype of the bot
|
||||
vec3_t viewangles; //view angles of the bot
|
||||
int or_moveflags; //values ored to the movement flags
|
||||
} bot_initmove_t;
|
||||
|
||||
//NOTE: the ideal_viewangles are only valid if MFL_MOVEMENTVIEW is set
|
||||
typedef struct bot_moveresult_s
|
||||
{
|
||||
int failure; //true if movement failed all together
|
||||
int type; //failure or blocked type
|
||||
int blocked; //true if blocked by an entity
|
||||
int blockentity; //entity blocking the bot
|
||||
int traveltype; //last executed travel type
|
||||
int flags; //result flags
|
||||
int weapon; //weapon used for movement
|
||||
vec3_t movedir; //movement direction
|
||||
vec3_t ideal_viewangles; //ideal viewangles for the movement
|
||||
} bot_moveresult_t;
|
||||
|
||||
// bk001204: from code/botlib/be_ai_move.c
|
||||
// TTimo 04/12/2001 was moved here to avoid dup defines
|
||||
typedef struct bot_avoidspot_s
|
||||
{
|
||||
vec3_t origin;
|
||||
float radius;
|
||||
int type;
|
||||
} bot_avoidspot_t;
|
||||
|
||||
//resets the whole move state
|
||||
void BotResetMoveState(int movestate);
|
||||
//moves the bot to the given goal
|
||||
void BotMoveToGoal(bot_moveresult_t *result, int movestate, bot_goal_t *goal, int travelflags);
|
||||
//moves the bot in the specified direction using the specified type of movement
|
||||
int BotMoveInDirection(int movestate, vec3_t dir, float speed, int type);
|
||||
//reset avoid reachability
|
||||
void BotResetAvoidReach(int movestate);
|
||||
//resets the last avoid reachability
|
||||
void BotResetLastAvoidReach(int movestate);
|
||||
//returns a reachability area if the origin is in one
|
||||
int BotReachabilityArea(vec3_t origin, int client);
|
||||
//view target based on movement
|
||||
int BotMovementViewTarget(int movestate, bot_goal_t *goal, int travelflags, float lookahead, vec3_t target);
|
||||
//predict the position of a player based on movement towards a goal
|
||||
int BotPredictVisiblePosition(vec3_t origin, int areanum, bot_goal_t *goal, int travelflags, vec3_t target);
|
||||
//returns the handle of a newly allocated movestate
|
||||
int BotAllocMoveState(void);
|
||||
//frees the movestate with the given handle
|
||||
void BotFreeMoveState(int handle);
|
||||
//initialize movement state before performing any movement
|
||||
void BotInitMoveState(int handle, bot_initmove_t *initmove);
|
||||
//add a spot to avoid (if type == AVOID_CLEAR all spots are removed)
|
||||
void BotAddAvoidSpot(int movestate, vec3_t origin, float radius, int type);
|
||||
//must be called every map change
|
||||
void BotSetBrushModelTypes(void);
|
||||
//setup movement AI
|
||||
int BotSetupMoveAI(void);
|
||||
//shutdown movement AI
|
||||
void BotShutdownMoveAI(void);
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: be_ai_weap.h
|
||||
*
|
||||
* desc: weapon AI
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_ai_weap.h $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//projectile flags
|
||||
#define PFL_WINDOWDAMAGE 1 //projectile damages through window
|
||||
#define PFL_RETURN 2 //set when projectile returns to owner
|
||||
//weapon flags
|
||||
#define WFL_FIRERELEASED 1 //set when projectile is fired with key-up event
|
||||
//damage types
|
||||
#define DAMAGETYPE_IMPACT 1 //damage on impact
|
||||
#define DAMAGETYPE_RADIAL 2 //radial damage
|
||||
#define DAMAGETYPE_VISIBLE 4 //damage to all entities visible to the projectile
|
||||
|
||||
typedef struct projectileinfo_s
|
||||
{
|
||||
char name[MAX_STRINGFIELD];
|
||||
char model[MAX_STRINGFIELD];
|
||||
int flags;
|
||||
float gravity;
|
||||
int damage;
|
||||
float radius;
|
||||
int visdamage;
|
||||
int damagetype;
|
||||
int healthinc;
|
||||
float push;
|
||||
float detonation;
|
||||
float bounce;
|
||||
float bouncefric;
|
||||
float bouncestop;
|
||||
} projectileinfo_t;
|
||||
|
||||
typedef struct weaponinfo_s
|
||||
{
|
||||
int valid; //true if the weapon info is valid
|
||||
int number; //number of the weapon
|
||||
char name[MAX_STRINGFIELD];
|
||||
char model[MAX_STRINGFIELD];
|
||||
int level;
|
||||
int weaponindex;
|
||||
int flags;
|
||||
char projectile[MAX_STRINGFIELD];
|
||||
int numprojectiles;
|
||||
float hspread;
|
||||
float vspread;
|
||||
float speed;
|
||||
float acceleration;
|
||||
vec3_t recoil;
|
||||
vec3_t offset;
|
||||
vec3_t angleoffset;
|
||||
float extrazvelocity;
|
||||
int ammoamount;
|
||||
int ammoindex;
|
||||
float activate;
|
||||
float reload;
|
||||
float spinup;
|
||||
float spindown;
|
||||
projectileinfo_t proj; //pointer to the used projectile
|
||||
} weaponinfo_t;
|
||||
|
||||
//setup the weapon AI
|
||||
int BotSetupWeaponAI(void);
|
||||
//shut down the weapon AI
|
||||
void BotShutdownWeaponAI(void);
|
||||
//returns the best weapon to fight with
|
||||
int BotChooseBestFightWeapon(int weaponstate, int *inventory);
|
||||
//returns the information of the current weapon
|
||||
void BotGetWeaponInfo(int weaponstate, int weapon, weaponinfo_t *weaponinfo);
|
||||
//loads the weapon weights
|
||||
int BotLoadWeaponWeights(int weaponstate, char *filename);
|
||||
//returns a handle to a newly allocated weapon state
|
||||
int BotAllocWeaponState(void);
|
||||
//frees the weapon state
|
||||
void BotFreeWeaponState(int weaponstate);
|
||||
//resets the whole weapon state
|
||||
void BotResetWeaponState(int weaponstate);
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
/*****************************************************************************
|
||||
* name: be_ea.h
|
||||
*
|
||||
* desc: elementary actions
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_ea.h $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//ClientCommand elementary actions
|
||||
void EA_Say(int client, char *str);
|
||||
void EA_SayTeam(int client, char *str);
|
||||
void EA_Command(int client, char *command );
|
||||
|
||||
void EA_Action(int client, int action);
|
||||
void EA_Crouch(int client);
|
||||
void EA_Walk(int client);
|
||||
void EA_MoveUp(int client);
|
||||
void EA_MoveDown(int client);
|
||||
void EA_MoveForward(int client);
|
||||
void EA_MoveBack(int client);
|
||||
void EA_MoveLeft(int client);
|
||||
void EA_MoveRight(int client);
|
||||
void EA_Attack(int client);
|
||||
void EA_Respawn(int client);
|
||||
void EA_Talk(int client);
|
||||
void EA_Gesture(int client);
|
||||
void EA_Use(int client);
|
||||
|
||||
//regular elementary actions
|
||||
void EA_SelectWeapon(int client, int weapon);
|
||||
void EA_Jump(int client);
|
||||
void EA_DelayedJump(int client);
|
||||
void EA_Move(int client, vec3_t dir, float speed);
|
||||
void EA_View(int client, vec3_t viewangles);
|
||||
|
||||
//send regular input to the server
|
||||
void EA_EndRegular(int client, float thinktime);
|
||||
void EA_GetInput(int client, float thinktime, bot_input_t *input);
|
||||
void EA_ResetInput(int client);
|
||||
//setup and shutdown routines
|
||||
int EA_Setup(void);
|
||||
void EA_Shutdown(void);
|
||||
+1324
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
// bg_lib.h -- standard C library replacement routines used by code
|
||||
// compiled for the virtual machine
|
||||
|
||||
// This file is NOT included on native builds
|
||||
|
||||
typedef int size_t;
|
||||
|
||||
typedef char * va_list;
|
||||
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
|
||||
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
|
||||
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
|
||||
#define va_end(ap) ( ap = (va_list)0 )
|
||||
|
||||
#define CHAR_BIT 8 /* number of bits in a char */
|
||||
#define SCHAR_MIN (-128) /* minimum signed char value */
|
||||
#define SCHAR_MAX 127 /* maximum signed char value */
|
||||
#define UCHAR_MAX 0xff /* maximum unsigned char value */
|
||||
|
||||
#define SHRT_MIN (-32768) /* minimum (signed) short value */
|
||||
#define SHRT_MAX 32767 /* maximum (signed) short value */
|
||||
#define USHRT_MAX 0xffff /* maximum unsigned short value */
|
||||
#define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */
|
||||
#define INT_MAX 2147483647 /* maximum (signed) int value */
|
||||
#define UINT_MAX 0xffffffff /* maximum unsigned int value */
|
||||
#define LONG_MIN (-2147483647L - 1) /* minimum (signed) long value */
|
||||
#define LONG_MAX 2147483647L /* maximum (signed) long value */
|
||||
#define ULONG_MAX 0xffffffffUL /* maximum unsigned long value */
|
||||
|
||||
// Misc functions
|
||||
typedef int cmp_t(const void *, const void *);
|
||||
void qsort(void *a, size_t n, size_t es, cmp_t *cmp);
|
||||
void srand( unsigned seed );
|
||||
int rand( void );
|
||||
|
||||
// String functions
|
||||
size_t strlen( const char *string );
|
||||
char *strcat( char *strDestination, const char *strSource );
|
||||
char *strcpy( char *strDestination, const char *strSource );
|
||||
int strcmp( const char *string1, const char *string2 );
|
||||
char *strchr( const char *string, int c );
|
||||
char *strstr( const char *string, const char *strCharSet );
|
||||
char *strncpy( char *strDest, const char *strSource, size_t count );
|
||||
int tolower( int c );
|
||||
int toupper( int c );
|
||||
|
||||
double atof( const char *string );
|
||||
double _atof( const char **stringPtr );
|
||||
int atoi( const char *string );
|
||||
int _atoi( const char **stringPtr );
|
||||
|
||||
int vsprintf( char *buffer, const char *fmt, va_list argptr );
|
||||
int sscanf( const char *buffer, const char *fmt, ... );
|
||||
|
||||
// Memory functions
|
||||
void *memmove( void *dest, const void *src, size_t count );
|
||||
void *memset( void *dest, int c, size_t count );
|
||||
void *memcpy( void *dest, const void *src, size_t count );
|
||||
|
||||
// Math functions
|
||||
double ceil( double x );
|
||||
double floor( double x );
|
||||
double sqrt( double x );
|
||||
double sin( double x );
|
||||
double cos( double x );
|
||||
double atan2( double y, double x );
|
||||
double tan( double x );
|
||||
int abs( int n );
|
||||
double fabs( double x );
|
||||
double acos( double x );
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
// bg_local.h -- local definitions for the bg (both games) files
|
||||
|
||||
#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes
|
||||
|
||||
#define STEPSIZE 18
|
||||
|
||||
#define JUMP_VELOCITY 270
|
||||
|
||||
#define TIMER_LAND 130
|
||||
#define TIMER_GESTURE (34*66+50)
|
||||
|
||||
#define OVERCLIP 1.001f
|
||||
|
||||
// all of the locals will be zeroed before each
|
||||
// pmove, just to make damn sure we don't have
|
||||
// any differences when running on client or server
|
||||
typedef struct {
|
||||
vec3_t forward, right, up;
|
||||
float frametime;
|
||||
|
||||
int msec;
|
||||
|
||||
qboolean walking;
|
||||
qboolean groundPlane;
|
||||
trace_t groundTrace;
|
||||
|
||||
float impactSpeed;
|
||||
|
||||
vec3_t previous_origin;
|
||||
vec3_t previous_velocity;
|
||||
int previous_waterlevel;
|
||||
} pml_t;
|
||||
|
||||
extern pmove_t *pm;
|
||||
extern pml_t pml;
|
||||
|
||||
// movement parameters
|
||||
extern float pm_stopspeed;
|
||||
extern float pm_duckScale;
|
||||
extern float pm_swimScale;
|
||||
extern float pm_wadeScale;
|
||||
|
||||
extern float pm_accelerate;
|
||||
extern float pm_airaccelerate;
|
||||
extern float pm_wateraccelerate;
|
||||
extern float pm_flyaccelerate;
|
||||
|
||||
extern float pm_friction;
|
||||
extern float pm_waterfriction;
|
||||
extern float pm_flightfriction;
|
||||
|
||||
extern int c_pmove;
|
||||
|
||||
void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce );
|
||||
void PM_AddTouchEnt( int entityNum );
|
||||
void PM_AddEvent( int newEvent );
|
||||
|
||||
qboolean PM_SlideMove( qboolean gravity );
|
||||
void PM_StepSlideMove( qboolean gravity );
|
||||
|
||||
|
||||
+1604
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,738 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
// bg_public.h -- definitions shared by both the server game and client game modules
|
||||
|
||||
// because games can change separately from the main system version, we need a
|
||||
// second version that must match between game and cgame
|
||||
|
||||
#define GAME_VERSION "baseq3-1"
|
||||
|
||||
#define DEFAULT_GRAVITY 800
|
||||
#define GIB_HEALTH -40
|
||||
#define ARMOR_PROTECTION 0.66
|
||||
|
||||
#define MAX_ITEMS 256
|
||||
|
||||
#define RANK_TIED_FLAG 0x4000
|
||||
|
||||
#define DEFAULT_SHOTGUN_SPREAD 700
|
||||
#define DEFAULT_SHOTGUN_COUNT 11
|
||||
|
||||
#define ITEM_RADIUS 15 // item sizes are needed for client side pickup detection
|
||||
|
||||
#define LIGHTNING_RANGE 768
|
||||
|
||||
#define SCORE_NOT_PRESENT -9999 // for the CS_SCORES[12] when only one player is present
|
||||
|
||||
#define VOTE_TIME 30000 // 30 seconds before vote times out
|
||||
|
||||
#define MINS_Z -24
|
||||
#define DEFAULT_VIEWHEIGHT 26
|
||||
#define CROUCH_VIEWHEIGHT 12
|
||||
#define DEAD_VIEWHEIGHT -16
|
||||
|
||||
//
|
||||
// config strings are a general means of communicating variable length strings
|
||||
// from the server to all connected clients.
|
||||
//
|
||||
|
||||
// CS_SERVERINFO and CS_SYSTEMINFO are defined in q_shared.h
|
||||
#define CS_MUSIC 2
|
||||
#define CS_MESSAGE 3 // from the map worldspawn's message field
|
||||
#define CS_MOTD 4 // g_motd string for server message of the day
|
||||
#define CS_WARMUP 5 // server time when the match will be restarted
|
||||
#define CS_SCORES1 6
|
||||
#define CS_SCORES2 7
|
||||
#define CS_VOTE_TIME 8
|
||||
#define CS_VOTE_STRING 9
|
||||
#define CS_VOTE_YES 10
|
||||
#define CS_VOTE_NO 11
|
||||
|
||||
#define CS_TEAMVOTE_TIME 12
|
||||
#define CS_TEAMVOTE_STRING 14
|
||||
#define CS_TEAMVOTE_YES 16
|
||||
#define CS_TEAMVOTE_NO 18
|
||||
|
||||
#define CS_GAME_VERSION 20
|
||||
#define CS_LEVEL_START_TIME 21 // so the timer only shows the current level
|
||||
#define CS_INTERMISSION 22 // when 1, fraglimit/timelimit has been hit and intermission will start in a second or two
|
||||
#define CS_FLAGSTATUS 23 // string indicating flag status in CTF
|
||||
#define CS_SHADERSTATE 24
|
||||
#define CS_BOTINFO 25
|
||||
|
||||
#define CS_ITEMS 27 // string of 0's and 1's that tell which items are present
|
||||
|
||||
#define CS_MODELS 32
|
||||
#define CS_SOUNDS (CS_MODELS+MAX_MODELS)
|
||||
#define CS_PLAYERS (CS_SOUNDS+MAX_SOUNDS)
|
||||
#define CS_LOCATIONS (CS_PLAYERS+MAX_CLIENTS)
|
||||
#define CS_PARTICLES (CS_LOCATIONS+MAX_LOCATIONS)
|
||||
|
||||
#define CS_MAX (CS_PARTICLES+MAX_LOCATIONS)
|
||||
|
||||
#if (CS_MAX) > MAX_CONFIGSTRINGS
|
||||
#error overflow: (CS_MAX) > MAX_CONFIGSTRINGS
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
GT_FFA, // free for all
|
||||
GT_TOURNAMENT, // one on one tournament
|
||||
GT_SINGLE_PLAYER, // single player ffa
|
||||
|
||||
//-- team games go after this --
|
||||
|
||||
GT_TEAM, // team deathmatch
|
||||
GT_CTF, // capture the flag
|
||||
GT_1FCTF,
|
||||
GT_OBELISK,
|
||||
GT_HARVESTER,
|
||||
GT_MAX_GAME_TYPE
|
||||
} gametype_t;
|
||||
|
||||
typedef enum { GENDER_MALE, GENDER_FEMALE, GENDER_NEUTER } gender_t;
|
||||
|
||||
/*
|
||||
===================================================================================
|
||||
|
||||
PMOVE MODULE
|
||||
|
||||
The pmove code takes a player_state_t and a usercmd_t and generates a new player_state_t
|
||||
and some other output data. Used for local prediction on the client game and true
|
||||
movement on the server game.
|
||||
===================================================================================
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
PM_NORMAL, // can accelerate and turn
|
||||
PM_NOCLIP, // noclip movement
|
||||
PM_SPECTATOR, // still run into walls
|
||||
PM_DEAD, // no acceleration or turning, but free falling
|
||||
PM_FREEZE, // stuck in place with no control
|
||||
PM_INTERMISSION, // no movement or status bar
|
||||
PM_SPINTERMISSION // no movement or status bar
|
||||
} pmtype_t;
|
||||
|
||||
typedef enum {
|
||||
WEAPON_READY,
|
||||
WEAPON_RAISING,
|
||||
WEAPON_DROPPING,
|
||||
WEAPON_FIRING
|
||||
} weaponstate_t;
|
||||
|
||||
// pmove->pm_flags
|
||||
#define PMF_DUCKED 1
|
||||
#define PMF_JUMP_HELD 2
|
||||
#define PMF_BACKWARDS_JUMP 8 // go into backwards land
|
||||
#define PMF_BACKWARDS_RUN 16 // coast down to backwards run
|
||||
#define PMF_TIME_LAND 32 // pm_time is time before rejump
|
||||
#define PMF_TIME_KNOCKBACK 64 // pm_time is an air-accelerate only time
|
||||
#define PMF_TIME_WATERJUMP 256 // pm_time is waterjump
|
||||
#define PMF_RESPAWNED 512 // clear after attack and jump buttons come up
|
||||
#define PMF_USE_ITEM_HELD 1024
|
||||
#define PMF_GRAPPLE_PULL 2048 // pull towards grapple location
|
||||
#define PMF_FOLLOW 4096 // spectate following another player
|
||||
#define PMF_SCOREBOARD 8192 // spectate as a scoreboard
|
||||
#define PMF_INVULEXPAND 16384 // invulnerability sphere set to full size
|
||||
|
||||
#define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK)
|
||||
|
||||
#define MAXTOUCH 32
|
||||
typedef struct {
|
||||
// state (in / out)
|
||||
playerState_t *ps;
|
||||
|
||||
// command (in)
|
||||
usercmd_t cmd;
|
||||
int tracemask; // collide against these types of surfaces
|
||||
int debugLevel; // if set, diagnostic output will be printed
|
||||
qboolean noFootsteps; // if the game is setup for no footsteps by the server
|
||||
qboolean gauntletHit; // true if a gauntlet attack would actually hit something
|
||||
|
||||
int framecount;
|
||||
|
||||
// results (out)
|
||||
int numtouch;
|
||||
int touchents[MAXTOUCH];
|
||||
|
||||
vec3_t mins, maxs; // bounding box size
|
||||
|
||||
int watertype;
|
||||
int waterlevel;
|
||||
|
||||
float xyspeed;
|
||||
|
||||
// for fixed msec Pmove
|
||||
int pmove_fixed;
|
||||
int pmove_msec;
|
||||
|
||||
// callbacks to test the world
|
||||
// these will be different functions during game and cgame
|
||||
void (*trace)( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentMask );
|
||||
int (*pointcontents)( const vec3_t point, int passEntityNum );
|
||||
} pmove_t;
|
||||
|
||||
// if a full pmove isn't done on the client, you can just update the angles
|
||||
void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd );
|
||||
void Pmove (pmove_t *pmove);
|
||||
|
||||
//===================================================================================
|
||||
|
||||
|
||||
// player_state->stats[] indexes
|
||||
// NOTE: may not have more than 16
|
||||
typedef enum {
|
||||
STAT_HEALTH,
|
||||
STAT_HOLDABLE_ITEM,
|
||||
#ifdef MISSIONPACK
|
||||
STAT_PERSISTANT_POWERUP,
|
||||
#endif
|
||||
STAT_WEAPONS, // 16 bit fields
|
||||
STAT_ARMOR,
|
||||
STAT_DEAD_YAW, // look this direction when dead (FIXME: get rid of?)
|
||||
STAT_CLIENTS_READY, // bit mask of clients wishing to exit the intermission (FIXME: configstring?)
|
||||
STAT_MAX_HEALTH // health / armor limit, changable by handicap
|
||||
} statIndex_t;
|
||||
|
||||
|
||||
// player_state->persistant[] indexes
|
||||
// these fields are the only part of player_state that isn't
|
||||
// cleared on respawn
|
||||
// NOTE: may not have more than 16
|
||||
typedef enum {
|
||||
PERS_SCORE, // !!! MUST NOT CHANGE, SERVER AND GAME BOTH REFERENCE !!!
|
||||
PERS_HITS, // total points damage inflicted so damage beeps can sound on change
|
||||
PERS_RANK, // player rank or team rank
|
||||
PERS_TEAM, // player team
|
||||
PERS_SPAWN_COUNT, // incremented every respawn
|
||||
PERS_PLAYEREVENTS, // 16 bits that can be flipped for events
|
||||
PERS_ATTACKER, // clientnum of last damage inflicter
|
||||
PERS_ATTACKEE_ARMOR, // health/armor of last person we attacked
|
||||
PERS_KILLED, // count of the number of times you died
|
||||
// player awards tracking
|
||||
PERS_IMPRESSIVE_COUNT, // two railgun hits in a row
|
||||
PERS_EXCELLENT_COUNT, // two successive kills in a short amount of time
|
||||
PERS_DEFEND_COUNT, // defend awards
|
||||
PERS_ASSIST_COUNT, // assist awards
|
||||
PERS_GAUNTLET_FRAG_COUNT, // kills with the guantlet
|
||||
PERS_CAPTURES // captures
|
||||
} persEnum_t;
|
||||
|
||||
|
||||
// entityState_t->eFlags
|
||||
#define EF_DEAD 0x00000001 // don't draw a foe marker over players with EF_DEAD
|
||||
#ifdef MISSIONPACK
|
||||
#define EF_TICKING 0x00000002 // used to make players play the prox mine ticking sound
|
||||
#endif
|
||||
#define EF_TELEPORT_BIT 0x00000004 // toggled every time the origin abruptly changes
|
||||
#define EF_AWARD_EXCELLENT 0x00000008 // draw an excellent sprite
|
||||
#define EF_PLAYER_EVENT 0x00000010
|
||||
#define EF_BOUNCE 0x00000010 // for missiles
|
||||
#define EF_BOUNCE_HALF 0x00000020 // for missiles
|
||||
#define EF_AWARD_GAUNTLET 0x00000040 // draw a gauntlet sprite
|
||||
#define EF_NODRAW 0x00000080 // may have an event, but no model (unspawned items)
|
||||
#define EF_FIRING 0x00000100 // for lightning gun
|
||||
#define EF_KAMIKAZE 0x00000200
|
||||
#define EF_MOVER_STOP 0x00000400 // will push otherwise
|
||||
#define EF_AWARD_CAP 0x00000800 // draw the capture sprite
|
||||
#define EF_TALK 0x00001000 // draw a talk balloon
|
||||
#define EF_CONNECTION 0x00002000 // draw a connection trouble sprite
|
||||
#define EF_VOTED 0x00004000 // already cast a vote
|
||||
#define EF_AWARD_IMPRESSIVE 0x00008000 // draw an impressive sprite
|
||||
#define EF_AWARD_DEFEND 0x00010000 // draw a defend sprite
|
||||
#define EF_AWARD_ASSIST 0x00020000 // draw a assist sprite
|
||||
#define EF_AWARD_DENIED 0x00040000 // denied
|
||||
#define EF_TEAMVOTED 0x00080000 // already cast a team vote
|
||||
|
||||
// NOTE: may not have more than 16
|
||||
typedef enum {
|
||||
PW_NONE,
|
||||
|
||||
PW_QUAD,
|
||||
PW_BATTLESUIT,
|
||||
PW_HASTE,
|
||||
PW_INVIS,
|
||||
PW_REGEN,
|
||||
PW_FLIGHT,
|
||||
|
||||
PW_REDFLAG,
|
||||
PW_BLUEFLAG,
|
||||
PW_NEUTRALFLAG,
|
||||
|
||||
PW_SCOUT,
|
||||
PW_GUARD,
|
||||
PW_DOUBLER,
|
||||
PW_AMMOREGEN,
|
||||
PW_INVULNERABILITY,
|
||||
|
||||
PW_NUM_POWERUPS
|
||||
|
||||
} powerup_t;
|
||||
|
||||
typedef enum {
|
||||
HI_NONE,
|
||||
|
||||
HI_TELEPORTER,
|
||||
HI_MEDKIT,
|
||||
HI_KAMIKAZE,
|
||||
HI_PORTAL,
|
||||
HI_INVULNERABILITY,
|
||||
|
||||
HI_NUM_HOLDABLE
|
||||
} holdable_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
WP_NONE,
|
||||
|
||||
WP_GAUNTLET,
|
||||
WP_MACHINEGUN,
|
||||
WP_SHOTGUN,
|
||||
WP_GRENADE_LAUNCHER,
|
||||
WP_ROCKET_LAUNCHER,
|
||||
WP_LIGHTNING,
|
||||
WP_RAILGUN,
|
||||
WP_PLASMAGUN,
|
||||
WP_BFG,
|
||||
WP_GRAPPLING_HOOK,
|
||||
#ifdef MISSIONPACK
|
||||
WP_NAILGUN,
|
||||
WP_PROX_LAUNCHER,
|
||||
WP_CHAINGUN,
|
||||
#endif
|
||||
|
||||
WP_NUM_WEAPONS
|
||||
} weapon_t;
|
||||
|
||||
|
||||
// reward sounds (stored in ps->persistant[PERS_PLAYEREVENTS])
|
||||
#define PLAYEREVENT_DENIEDREWARD 0x0001
|
||||
#define PLAYEREVENT_GAUNTLETREWARD 0x0002
|
||||
#define PLAYEREVENT_HOLYSHIT 0x0004
|
||||
|
||||
// entityState_t->event values
|
||||
// entity events are for effects that take place reletive
|
||||
// to an existing entities origin. Very network efficient.
|
||||
|
||||
// two bits at the top of the entityState->event field
|
||||
// will be incremented with each change in the event so
|
||||
// that an identical event started twice in a row can
|
||||
// be distinguished. And off the value with ~EV_EVENT_BITS
|
||||
// to retrieve the actual event number
|
||||
#define EV_EVENT_BIT1 0x00000100
|
||||
#define EV_EVENT_BIT2 0x00000200
|
||||
#define EV_EVENT_BITS (EV_EVENT_BIT1|EV_EVENT_BIT2)
|
||||
|
||||
#define EVENT_VALID_MSEC 300
|
||||
|
||||
typedef enum {
|
||||
EV_NONE,
|
||||
|
||||
EV_FOOTSTEP,
|
||||
EV_FOOTSTEP_METAL,
|
||||
EV_FOOTSPLASH,
|
||||
EV_FOOTWADE,
|
||||
EV_SWIM,
|
||||
|
||||
EV_STEP_4,
|
||||
EV_STEP_8,
|
||||
EV_STEP_12,
|
||||
EV_STEP_16,
|
||||
|
||||
EV_FALL_SHORT,
|
||||
EV_FALL_MEDIUM,
|
||||
EV_FALL_FAR,
|
||||
|
||||
EV_JUMP_PAD, // boing sound at origin, jump sound on player
|
||||
|
||||
EV_JUMP,
|
||||
EV_WATER_TOUCH, // foot touches
|
||||
EV_WATER_LEAVE, // foot leaves
|
||||
EV_WATER_UNDER, // head touches
|
||||
EV_WATER_CLEAR, // head leaves
|
||||
|
||||
EV_ITEM_PICKUP, // normal item pickups are predictable
|
||||
EV_GLOBAL_ITEM_PICKUP, // powerup / team sounds are broadcast to everyone
|
||||
|
||||
EV_NOAMMO,
|
||||
EV_CHANGE_WEAPON,
|
||||
EV_FIRE_WEAPON,
|
||||
|
||||
EV_USE_ITEM0,
|
||||
EV_USE_ITEM1,
|
||||
EV_USE_ITEM2,
|
||||
EV_USE_ITEM3,
|
||||
EV_USE_ITEM4,
|
||||
EV_USE_ITEM5,
|
||||
EV_USE_ITEM6,
|
||||
EV_USE_ITEM7,
|
||||
EV_USE_ITEM8,
|
||||
EV_USE_ITEM9,
|
||||
EV_USE_ITEM10,
|
||||
EV_USE_ITEM11,
|
||||
EV_USE_ITEM12,
|
||||
EV_USE_ITEM13,
|
||||
EV_USE_ITEM14,
|
||||
EV_USE_ITEM15,
|
||||
|
||||
EV_ITEM_RESPAWN,
|
||||
EV_ITEM_POP,
|
||||
EV_PLAYER_TELEPORT_IN,
|
||||
EV_PLAYER_TELEPORT_OUT,
|
||||
|
||||
EV_GRENADE_BOUNCE, // eventParm will be the soundindex
|
||||
|
||||
EV_GENERAL_SOUND,
|
||||
EV_GLOBAL_SOUND, // no attenuation
|
||||
EV_GLOBAL_TEAM_SOUND,
|
||||
|
||||
EV_BULLET_HIT_FLESH,
|
||||
EV_BULLET_HIT_WALL,
|
||||
|
||||
EV_MISSILE_HIT,
|
||||
EV_MISSILE_MISS,
|
||||
EV_MISSILE_MISS_METAL,
|
||||
EV_RAILTRAIL,
|
||||
EV_SHOTGUN,
|
||||
EV_BULLET, // otherEntity is the shooter
|
||||
|
||||
EV_PAIN,
|
||||
EV_DEATH1,
|
||||
EV_DEATH2,
|
||||
EV_DEATH3,
|
||||
EV_OBITUARY,
|
||||
|
||||
EV_POWERUP_QUAD,
|
||||
EV_POWERUP_BATTLESUIT,
|
||||
EV_POWERUP_REGEN,
|
||||
|
||||
EV_GIB_PLAYER, // gib a previously living player
|
||||
EV_SCOREPLUM, // score plum
|
||||
|
||||
//#ifdef MISSIONPACK
|
||||
EV_PROXIMITY_MINE_STICK,
|
||||
EV_PROXIMITY_MINE_TRIGGER,
|
||||
EV_KAMIKAZE, // kamikaze explodes
|
||||
EV_OBELISKEXPLODE, // obelisk explodes
|
||||
EV_OBELISKPAIN, // obelisk is in pain
|
||||
EV_INVUL_IMPACT, // invulnerability sphere impact
|
||||
EV_JUICED, // invulnerability juiced effect
|
||||
EV_LIGHTNINGBOLT, // lightning bolt bounced of invulnerability sphere
|
||||
//#endif
|
||||
|
||||
EV_DEBUG_LINE,
|
||||
EV_STOPLOOPINGSOUND,
|
||||
EV_TAUNT,
|
||||
EV_TAUNT_YES,
|
||||
EV_TAUNT_NO,
|
||||
EV_TAUNT_FOLLOWME,
|
||||
EV_TAUNT_GETFLAG,
|
||||
EV_TAUNT_GUARDBASE,
|
||||
EV_TAUNT_PATROL
|
||||
|
||||
} entity_event_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GTS_RED_CAPTURE,
|
||||
GTS_BLUE_CAPTURE,
|
||||
GTS_RED_RETURN,
|
||||
GTS_BLUE_RETURN,
|
||||
GTS_RED_TAKEN,
|
||||
GTS_BLUE_TAKEN,
|
||||
GTS_REDOBELISK_ATTACKED,
|
||||
GTS_BLUEOBELISK_ATTACKED,
|
||||
GTS_REDTEAM_SCORED,
|
||||
GTS_BLUETEAM_SCORED,
|
||||
GTS_REDTEAM_TOOK_LEAD,
|
||||
GTS_BLUETEAM_TOOK_LEAD,
|
||||
GTS_TEAMS_ARE_TIED,
|
||||
GTS_KAMIKAZE
|
||||
} global_team_sound_t;
|
||||
|
||||
// animations
|
||||
typedef enum {
|
||||
BOTH_DEATH1,
|
||||
BOTH_DEAD1,
|
||||
BOTH_DEATH2,
|
||||
BOTH_DEAD2,
|
||||
BOTH_DEATH3,
|
||||
BOTH_DEAD3,
|
||||
|
||||
TORSO_GESTURE,
|
||||
|
||||
TORSO_ATTACK,
|
||||
TORSO_ATTACK2,
|
||||
|
||||
TORSO_DROP,
|
||||
TORSO_RAISE,
|
||||
|
||||
TORSO_STAND,
|
||||
TORSO_STAND2,
|
||||
|
||||
LEGS_WALKCR,
|
||||
LEGS_WALK,
|
||||
LEGS_RUN,
|
||||
LEGS_BACK,
|
||||
LEGS_SWIM,
|
||||
|
||||
LEGS_JUMP,
|
||||
LEGS_LAND,
|
||||
|
||||
LEGS_JUMPB,
|
||||
LEGS_LANDB,
|
||||
|
||||
LEGS_IDLE,
|
||||
LEGS_IDLECR,
|
||||
|
||||
LEGS_TURN,
|
||||
|
||||
TORSO_GETFLAG,
|
||||
TORSO_GUARDBASE,
|
||||
TORSO_PATROL,
|
||||
TORSO_FOLLOWME,
|
||||
TORSO_AFFIRMATIVE,
|
||||
TORSO_NEGATIVE,
|
||||
|
||||
MAX_ANIMATIONS,
|
||||
|
||||
LEGS_BACKCR,
|
||||
LEGS_BACKWALK,
|
||||
FLAG_RUN,
|
||||
FLAG_STAND,
|
||||
FLAG_STAND2RUN,
|
||||
|
||||
MAX_TOTALANIMATIONS
|
||||
} animNumber_t;
|
||||
|
||||
|
||||
typedef struct animation_s {
|
||||
int firstFrame;
|
||||
int numFrames;
|
||||
int loopFrames; // 0 to numFrames
|
||||
int frameLerp; // msec between frames
|
||||
int initialLerp; // msec to get to first frame
|
||||
int reversed; // true if animation is reversed
|
||||
int flipflop; // true if animation should flipflop back to base
|
||||
} animation_t;
|
||||
|
||||
|
||||
// flip the togglebit every time an animation
|
||||
// changes so a restart of the same anim can be detected
|
||||
#define ANIM_TOGGLEBIT 128
|
||||
|
||||
|
||||
typedef enum {
|
||||
TEAM_FREE,
|
||||
TEAM_RED,
|
||||
TEAM_BLUE,
|
||||
TEAM_SPECTATOR,
|
||||
|
||||
TEAM_NUM_TEAMS
|
||||
} team_t;
|
||||
|
||||
// Time between location updates
|
||||
#define TEAM_LOCATION_UPDATE_TIME 1000
|
||||
|
||||
// How many players on the overlay
|
||||
#define TEAM_MAXOVERLAY 32
|
||||
|
||||
//team task
|
||||
typedef enum {
|
||||
TEAMTASK_NONE,
|
||||
TEAMTASK_OFFENSE,
|
||||
TEAMTASK_DEFENSE,
|
||||
TEAMTASK_PATROL,
|
||||
TEAMTASK_FOLLOW,
|
||||
TEAMTASK_RETRIEVE,
|
||||
TEAMTASK_ESCORT,
|
||||
TEAMTASK_CAMP
|
||||
} teamtask_t;
|
||||
|
||||
// means of death
|
||||
typedef enum {
|
||||
MOD_UNKNOWN,
|
||||
MOD_SHOTGUN,
|
||||
MOD_GAUNTLET,
|
||||
MOD_MACHINEGUN,
|
||||
MOD_GRENADE,
|
||||
MOD_GRENADE_SPLASH,
|
||||
MOD_ROCKET,
|
||||
MOD_ROCKET_SPLASH,
|
||||
MOD_PLASMA,
|
||||
MOD_PLASMA_SPLASH,
|
||||
MOD_RAILGUN,
|
||||
MOD_LIGHTNING,
|
||||
MOD_BFG,
|
||||
MOD_BFG_SPLASH,
|
||||
MOD_WATER,
|
||||
MOD_SLIME,
|
||||
MOD_LAVA,
|
||||
MOD_CRUSH,
|
||||
MOD_TELEFRAG,
|
||||
MOD_FALLING,
|
||||
MOD_SUICIDE,
|
||||
MOD_TARGET_LASER,
|
||||
MOD_TRIGGER_HURT,
|
||||
#ifdef MISSIONPACK
|
||||
MOD_NAIL,
|
||||
MOD_CHAINGUN,
|
||||
MOD_PROXIMITY_MINE,
|
||||
MOD_KAMIKAZE,
|
||||
MOD_JUICED,
|
||||
#endif
|
||||
MOD_GRAPPLE
|
||||
} meansOfDeath_t;
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
// gitem_t->type
|
||||
typedef enum {
|
||||
IT_BAD,
|
||||
IT_WEAPON, // EFX: rotate + upscale + minlight
|
||||
IT_AMMO, // EFX: rotate
|
||||
IT_ARMOR, // EFX: rotate + minlight
|
||||
IT_HEALTH, // EFX: static external sphere + rotating internal
|
||||
IT_POWERUP, // instant on, timer based
|
||||
// EFX: rotate + external ring that rotates
|
||||
IT_HOLDABLE, // single use, holdable item
|
||||
// EFX: rotate + bob
|
||||
IT_PERSISTANT_POWERUP,
|
||||
IT_TEAM
|
||||
} itemType_t;
|
||||
|
||||
#define MAX_ITEM_MODELS 4
|
||||
|
||||
typedef struct gitem_s {
|
||||
char *classname; // spawning name
|
||||
char *pickup_sound;
|
||||
char *world_model[MAX_ITEM_MODELS];
|
||||
|
||||
char *icon;
|
||||
char *pickup_name; // for printing on pickup
|
||||
|
||||
int quantity; // for ammo how much, or duration of powerup
|
||||
itemType_t giType; // IT_* flags
|
||||
|
||||
int giTag;
|
||||
|
||||
char *precaches; // string of all models and images this item will use
|
||||
char *sounds; // string of all sounds this item will use
|
||||
} gitem_t;
|
||||
|
||||
// included in both the game dll and the client
|
||||
extern gitem_t bg_itemlist[];
|
||||
extern int bg_numItems;
|
||||
|
||||
gitem_t *BG_FindItem( const char *pickupName );
|
||||
gitem_t *BG_FindItemForWeapon( weapon_t weapon );
|
||||
gitem_t *BG_FindItemForPowerup( powerup_t pw );
|
||||
gitem_t *BG_FindItemForHoldable( holdable_t pw );
|
||||
#define ITEM_INDEX(x) ((x)-bg_itemlist)
|
||||
|
||||
qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const playerState_t *ps );
|
||||
|
||||
|
||||
// g_dmflags->integer flags
|
||||
#define DF_NO_FALLING 8
|
||||
#define DF_FIXED_FOV 16
|
||||
#define DF_NO_FOOTSTEPS 32
|
||||
|
||||
// content masks
|
||||
#define MASK_ALL (-1)
|
||||
#define MASK_SOLID (CONTENTS_SOLID)
|
||||
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_BODY)
|
||||
#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP)
|
||||
#define MASK_WATER (CONTENTS_WATER|CONTENTS_LAVA|CONTENTS_SLIME)
|
||||
#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_SLIME|CONTENTS_LAVA)
|
||||
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_BODY|CONTENTS_CORPSE)
|
||||
|
||||
|
||||
//
|
||||
// entityState_t->eType
|
||||
//
|
||||
typedef enum {
|
||||
ET_GENERAL,
|
||||
ET_PLAYER,
|
||||
ET_ITEM,
|
||||
ET_MISSILE,
|
||||
ET_MOVER,
|
||||
ET_BEAM,
|
||||
ET_PORTAL,
|
||||
ET_SPEAKER,
|
||||
ET_PUSH_TRIGGER,
|
||||
ET_TELEPORT_TRIGGER,
|
||||
ET_INVISIBLE,
|
||||
ET_GRAPPLE, // grapple hooked on wall
|
||||
ET_TEAM,
|
||||
|
||||
ET_EVENTS // any of the EV_* events can be added freestanding
|
||||
// by setting eType to ET_EVENTS + eventNum
|
||||
// this avoids having to set eFlags and eventNum
|
||||
} entityType_t;
|
||||
|
||||
|
||||
|
||||
void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result );
|
||||
void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result );
|
||||
|
||||
void BG_AddPredictableEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps );
|
||||
|
||||
void BG_TouchJumpPad( playerState_t *ps, entityState_t *jumppad );
|
||||
|
||||
void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap );
|
||||
void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap );
|
||||
|
||||
qboolean BG_PlayerTouchesItem( playerState_t *ps, entityState_t *item, int atTime );
|
||||
|
||||
|
||||
#define ARENAS_PER_TIER 4
|
||||
#define MAX_ARENAS 1024
|
||||
#define MAX_ARENAS_TEXT 8192
|
||||
|
||||
#define MAX_BOTS 1024
|
||||
#define MAX_BOTS_TEXT 8192
|
||||
|
||||
|
||||
// Kamikaze
|
||||
|
||||
// 1st shockwave times
|
||||
#define KAMI_SHOCKWAVE_STARTTIME 0
|
||||
#define KAMI_SHOCKWAVEFADE_STARTTIME 1500
|
||||
#define KAMI_SHOCKWAVE_ENDTIME 2000
|
||||
// explosion/implosion times
|
||||
#define KAMI_EXPLODE_STARTTIME 250
|
||||
#define KAMI_IMPLODE_STARTTIME 2000
|
||||
#define KAMI_IMPLODE_ENDTIME 2250
|
||||
// 2nd shockwave times
|
||||
#define KAMI_SHOCKWAVE2_STARTTIME 2000
|
||||
#define KAMI_SHOCKWAVE2FADE_STARTTIME 2500
|
||||
#define KAMI_SHOCKWAVE2_ENDTIME 3000
|
||||
// radius of the models without scaling
|
||||
#define KAMI_SHOCKWAVEMODEL_RADIUS 88
|
||||
#define KAMI_BOOMSPHEREMODEL_RADIUS 72
|
||||
// maximum radius of the models during the effect
|
||||
#define KAMI_SHOCKWAVE_MAXRADIUS 1320
|
||||
#define KAMI_BOOMSPHERE_MAXRADIUS 720
|
||||
#define KAMI_SHOCKWAVE2_MAXRADIUS 704
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
// bg_slidemove.c -- part of bg_pmove functionality
|
||||
|
||||
#include "q_shared.h"
|
||||
#include "bg_public.h"
|
||||
#include "bg_local.h"
|
||||
|
||||
/*
|
||||
|
||||
input: origin, velocity, bounds, groundPlane, trace function
|
||||
|
||||
output: origin, velocity, impacts, stairup boolean
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
==================
|
||||
PM_SlideMove
|
||||
|
||||
Returns qtrue if the velocity was clipped in some way
|
||||
==================
|
||||
*/
|
||||
#define MAX_CLIP_PLANES 5
|
||||
qboolean PM_SlideMove( qboolean gravity ) {
|
||||
int bumpcount, numbumps;
|
||||
vec3_t dir;
|
||||
float d;
|
||||
int numplanes;
|
||||
vec3_t planes[MAX_CLIP_PLANES];
|
||||
vec3_t primal_velocity;
|
||||
vec3_t clipVelocity;
|
||||
int i, j, k;
|
||||
trace_t trace;
|
||||
vec3_t end;
|
||||
float time_left;
|
||||
float into;
|
||||
vec3_t endVelocity;
|
||||
vec3_t endClipVelocity;
|
||||
|
||||
numbumps = 4;
|
||||
|
||||
VectorCopy (pm->ps->velocity, primal_velocity);
|
||||
|
||||
if ( gravity ) {
|
||||
VectorCopy( pm->ps->velocity, endVelocity );
|
||||
endVelocity[2] -= pm->ps->gravity * pml.frametime;
|
||||
pm->ps->velocity[2] = ( pm->ps->velocity[2] + endVelocity[2] ) * 0.5;
|
||||
primal_velocity[2] = endVelocity[2];
|
||||
if ( pml.groundPlane ) {
|
||||
// slide along the ground plane
|
||||
PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal,
|
||||
pm->ps->velocity, OVERCLIP );
|
||||
}
|
||||
}
|
||||
|
||||
time_left = pml.frametime;
|
||||
|
||||
// never turn against the ground plane
|
||||
if ( pml.groundPlane ) {
|
||||
numplanes = 1;
|
||||
VectorCopy( pml.groundTrace.plane.normal, planes[0] );
|
||||
} else {
|
||||
numplanes = 0;
|
||||
}
|
||||
|
||||
// never turn against original velocity
|
||||
VectorNormalize2( pm->ps->velocity, planes[numplanes] );
|
||||
numplanes++;
|
||||
|
||||
for ( bumpcount=0 ; bumpcount < numbumps ; bumpcount++ ) {
|
||||
|
||||
// calculate position we are trying to move to
|
||||
VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end );
|
||||
|
||||
// see if we can make it there
|
||||
pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask);
|
||||
|
||||
if (trace.allsolid) {
|
||||
// entity is completely trapped in another solid
|
||||
pm->ps->velocity[2] = 0; // don't build up falling damage, but allow sideways acceleration
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (trace.fraction > 0) {
|
||||
// actually covered some distance
|
||||
VectorCopy (trace.endpos, pm->ps->origin);
|
||||
}
|
||||
|
||||
if (trace.fraction == 1) {
|
||||
break; // moved the entire distance
|
||||
}
|
||||
|
||||
// save entity for contact
|
||||
PM_AddTouchEnt( trace.entityNum );
|
||||
|
||||
time_left -= time_left * trace.fraction;
|
||||
|
||||
if (numplanes >= MAX_CLIP_PLANES) {
|
||||
// this shouldn't really happen
|
||||
VectorClear( pm->ps->velocity );
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
//
|
||||
// if this is the same plane we hit before, nudge velocity
|
||||
// out along it, which fixes some epsilon issues with
|
||||
// non-axial planes
|
||||
//
|
||||
for ( i = 0 ; i < numplanes ; i++ ) {
|
||||
if ( DotProduct( trace.plane.normal, planes[i] ) > 0.99 ) {
|
||||
VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i < numplanes ) {
|
||||
continue;
|
||||
}
|
||||
VectorCopy (trace.plane.normal, planes[numplanes]);
|
||||
numplanes++;
|
||||
|
||||
//
|
||||
// modify velocity so it parallels all of the clip planes
|
||||
//
|
||||
|
||||
// find a plane that it enters
|
||||
for ( i = 0 ; i < numplanes ; i++ ) {
|
||||
into = DotProduct( pm->ps->velocity, planes[i] );
|
||||
if ( into >= 0.1 ) {
|
||||
continue; // move doesn't interact with the plane
|
||||
}
|
||||
|
||||
// see how hard we are hitting things
|
||||
if ( -into > pml.impactSpeed ) {
|
||||
pml.impactSpeed = -into;
|
||||
}
|
||||
|
||||
// slide along the plane
|
||||
PM_ClipVelocity (pm->ps->velocity, planes[i], clipVelocity, OVERCLIP );
|
||||
|
||||
// slide along the plane
|
||||
PM_ClipVelocity (endVelocity, planes[i], endClipVelocity, OVERCLIP );
|
||||
|
||||
// see if there is a second plane that the new move enters
|
||||
for ( j = 0 ; j < numplanes ; j++ ) {
|
||||
if ( j == i ) {
|
||||
continue;
|
||||
}
|
||||
if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 ) {
|
||||
continue; // move doesn't interact with the plane
|
||||
}
|
||||
|
||||
// try clipping the move to the plane
|
||||
PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP );
|
||||
PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );
|
||||
|
||||
// see if it goes back into the first clip plane
|
||||
if ( DotProduct( clipVelocity, planes[i] ) >= 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// slide the original velocity along the crease
|
||||
CrossProduct (planes[i], planes[j], dir);
|
||||
VectorNormalize( dir );
|
||||
d = DotProduct( dir, pm->ps->velocity );
|
||||
VectorScale( dir, d, clipVelocity );
|
||||
|
||||
CrossProduct (planes[i], planes[j], dir);
|
||||
VectorNormalize( dir );
|
||||
d = DotProduct( dir, endVelocity );
|
||||
VectorScale( dir, d, endClipVelocity );
|
||||
|
||||
// see if there is a third plane the the new move enters
|
||||
for ( k = 0 ; k < numplanes ; k++ ) {
|
||||
if ( k == i || k == j ) {
|
||||
continue;
|
||||
}
|
||||
if ( DotProduct( clipVelocity, planes[k] ) >= 0.1 ) {
|
||||
continue; // move doesn't interact with the plane
|
||||
}
|
||||
|
||||
// stop dead at a tripple plane interaction
|
||||
VectorClear( pm->ps->velocity );
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have fixed all interactions, try another move
|
||||
VectorCopy( clipVelocity, pm->ps->velocity );
|
||||
VectorCopy( endClipVelocity, endVelocity );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( gravity ) {
|
||||
VectorCopy( endVelocity, pm->ps->velocity );
|
||||
}
|
||||
|
||||
// don't change velocity if in a timer (FIXME: is this correct?)
|
||||
if ( pm->ps->pm_time ) {
|
||||
VectorCopy( primal_velocity, pm->ps->velocity );
|
||||
}
|
||||
|
||||
return ( bumpcount != 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
PM_StepSlideMove
|
||||
|
||||
==================
|
||||
*/
|
||||
void PM_StepSlideMove( qboolean gravity ) {
|
||||
vec3_t start_o, start_v;
|
||||
vec3_t down_o, down_v;
|
||||
trace_t trace;
|
||||
// float down_dist, up_dist;
|
||||
// vec3_t delta, delta2;
|
||||
vec3_t up, down;
|
||||
float stepSize;
|
||||
|
||||
VectorCopy (pm->ps->origin, start_o);
|
||||
VectorCopy (pm->ps->velocity, start_v);
|
||||
|
||||
if ( PM_SlideMove( gravity ) == 0 ) {
|
||||
return; // we got exactly where we wanted to go first try
|
||||
}
|
||||
|
||||
VectorCopy(start_o, down);
|
||||
down[2] -= STEPSIZE;
|
||||
pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
|
||||
VectorSet(up, 0, 0, 1);
|
||||
// never step up when you still have up velocity
|
||||
if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 ||
|
||||
DotProduct(trace.plane.normal, up) < 0.7)) {
|
||||
return;
|
||||
}
|
||||
|
||||
VectorCopy (pm->ps->origin, down_o);
|
||||
VectorCopy (pm->ps->velocity, down_v);
|
||||
|
||||
VectorCopy (start_o, up);
|
||||
up[2] += STEPSIZE;
|
||||
|
||||
// test the player position if they were a stepheight higher
|
||||
pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask);
|
||||
if ( trace.allsolid ) {
|
||||
if ( pm->debugLevel ) {
|
||||
Com_Printf("%i:bend can't step\n", c_pmove);
|
||||
}
|
||||
return; // can't step up
|
||||
}
|
||||
|
||||
stepSize = trace.endpos[2] - start_o[2];
|
||||
// try slidemove from this position
|
||||
VectorCopy (trace.endpos, pm->ps->origin);
|
||||
VectorCopy (start_v, pm->ps->velocity);
|
||||
|
||||
PM_SlideMove( gravity );
|
||||
|
||||
// push down the final amount
|
||||
VectorCopy (pm->ps->origin, down);
|
||||
down[2] -= stepSize;
|
||||
pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
|
||||
if ( !trace.allsolid ) {
|
||||
VectorCopy (trace.endpos, pm->ps->origin);
|
||||
}
|
||||
if ( trace.fraction < 1.0 ) {
|
||||
PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP );
|
||||
}
|
||||
|
||||
#if 0
|
||||
// if the down trace can trace back to the original position directly, don't step
|
||||
pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask);
|
||||
if ( trace.fraction == 1.0 ) {
|
||||
// use the original move
|
||||
VectorCopy (down_o, pm->ps->origin);
|
||||
VectorCopy (down_v, pm->ps->velocity);
|
||||
if ( pm->debugLevel ) {
|
||||
Com_Printf("%i:bend\n", c_pmove);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// use the step move
|
||||
float delta;
|
||||
|
||||
delta = pm->ps->origin[2] - start_o[2];
|
||||
if ( delta > 2 ) {
|
||||
if ( delta < 7 ) {
|
||||
PM_AddEvent( EV_STEP_4 );
|
||||
} else if ( delta < 11 ) {
|
||||
PM_AddEvent( EV_STEP_8 );
|
||||
} else if ( delta < 15 ) {
|
||||
PM_AddEvent( EV_STEP_12 );
|
||||
} else {
|
||||
PM_AddEvent( EV_STEP_16 );
|
||||
}
|
||||
}
|
||||
if ( pm->debugLevel ) {
|
||||
Com_Printf("%i:stepped\n", c_pmove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
/*****************************************************************************
|
||||
* name: botlib.h
|
||||
*
|
||||
* desc: bot AI library
|
||||
*
|
||||
* $Archive: /source/code/game/botai.h $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define BOTLIB_API_VERSION 2
|
||||
|
||||
struct aas_clientmove_s;
|
||||
struct aas_entityinfo_s;
|
||||
struct aas_areainfo_s;
|
||||
struct aas_altroutegoal_s;
|
||||
struct aas_predictroute_s;
|
||||
struct bot_consolemessage_s;
|
||||
struct bot_match_s;
|
||||
struct bot_goal_s;
|
||||
struct bot_moveresult_s;
|
||||
struct bot_initmove_s;
|
||||
struct weaponinfo_s;
|
||||
|
||||
#define BOTFILESBASEFOLDER "botfiles"
|
||||
//debug line colors
|
||||
#define LINECOLOR_NONE -1
|
||||
#define LINECOLOR_RED 1//0xf2f2f0f0L
|
||||
#define LINECOLOR_GREEN 2//0xd0d1d2d3L
|
||||
#define LINECOLOR_BLUE 3//0xf3f3f1f1L
|
||||
#define LINECOLOR_YELLOW 4//0xdcdddedfL
|
||||
#define LINECOLOR_ORANGE 5//0xe0e1e2e3L
|
||||
|
||||
//Print types
|
||||
#define PRT_MESSAGE 1
|
||||
#define PRT_WARNING 2
|
||||
#define PRT_ERROR 3
|
||||
#define PRT_FATAL 4
|
||||
#define PRT_EXIT 5
|
||||
|
||||
//console message types
|
||||
#define CMS_NORMAL 0
|
||||
#define CMS_CHAT 1
|
||||
|
||||
//botlib error codes
|
||||
#define BLERR_NOERROR 0 //no error
|
||||
#define BLERR_LIBRARYNOTSETUP 1 //library not setup
|
||||
#define BLERR_INVALIDENTITYNUMBER 2 //invalid entity number
|
||||
#define BLERR_NOAASFILE 3 //no AAS file available
|
||||
#define BLERR_CANNOTOPENAASFILE 4 //cannot open AAS file
|
||||
#define BLERR_WRONGAASFILEID 5 //incorrect AAS file id
|
||||
#define BLERR_WRONGAASFILEVERSION 6 //incorrect AAS file version
|
||||
#define BLERR_CANNOTREADAASLUMP 7 //cannot read AAS file lump
|
||||
#define BLERR_CANNOTLOADICHAT 8 //cannot load initial chats
|
||||
#define BLERR_CANNOTLOADITEMWEIGHTS 9 //cannot load item weights
|
||||
#define BLERR_CANNOTLOADITEMCONFIG 10 //cannot load item config
|
||||
#define BLERR_CANNOTLOADWEAPONWEIGHTS 11 //cannot load weapon weights
|
||||
#define BLERR_CANNOTLOADWEAPONCONFIG 12 //cannot load weapon config
|
||||
|
||||
//action flags
|
||||
#define ACTION_ATTACK 0x0000001
|
||||
#define ACTION_USE 0x0000002
|
||||
#define ACTION_RESPAWN 0x0000008
|
||||
#define ACTION_JUMP 0x0000010
|
||||
#define ACTION_MOVEUP 0x0000020
|
||||
#define ACTION_CROUCH 0x0000080
|
||||
#define ACTION_MOVEDOWN 0x0000100
|
||||
#define ACTION_MOVEFORWARD 0x0000200
|
||||
#define ACTION_MOVEBACK 0x0000800
|
||||
#define ACTION_MOVELEFT 0x0001000
|
||||
#define ACTION_MOVERIGHT 0x0002000
|
||||
#define ACTION_DELAYEDJUMP 0x0008000
|
||||
#define ACTION_TALK 0x0010000
|
||||
#define ACTION_GESTURE 0x0020000
|
||||
#define ACTION_WALK 0x0080000
|
||||
#define ACTION_AFFIRMATIVE 0x0100000
|
||||
#define ACTION_NEGATIVE 0x0200000
|
||||
#define ACTION_GETFLAG 0x0800000
|
||||
#define ACTION_GUARDBASE 0x1000000
|
||||
#define ACTION_PATROL 0x2000000
|
||||
#define ACTION_FOLLOWME 0x8000000
|
||||
|
||||
//the bot input, will be converted to an usercmd_t
|
||||
typedef struct bot_input_s
|
||||
{
|
||||
float thinktime; //time since last output (in seconds)
|
||||
vec3_t dir; //movement direction
|
||||
float speed; //speed in the range [0, 400]
|
||||
vec3_t viewangles; //the view angles
|
||||
int actionflags; //one of the ACTION_? flags
|
||||
int weapon; //weapon to use
|
||||
} bot_input_t;
|
||||
|
||||
#ifndef BSPTRACE
|
||||
|
||||
#define BSPTRACE
|
||||
|
||||
//bsp_trace_t hit surface
|
||||
typedef struct bsp_surface_s
|
||||
{
|
||||
char name[16];
|
||||
int flags;
|
||||
int value;
|
||||
} bsp_surface_t;
|
||||
|
||||
//remove the bsp_trace_s structure definition l8r on
|
||||
//a trace is returned when a box is swept through the world
|
||||
typedef struct bsp_trace_s
|
||||
{
|
||||
qboolean allsolid; // if true, plane is not valid
|
||||
qboolean startsolid; // if true, the initial point was in a solid area
|
||||
float fraction; // time completed, 1.0 = didn't hit anything
|
||||
vec3_t endpos; // final position
|
||||
cplane_t plane; // surface normal at impact
|
||||
float exp_dist; // expanded plane distance
|
||||
int sidenum; // number of the brush side hit
|
||||
bsp_surface_t surface; // the hit point surface
|
||||
int contents; // contents on other side of surface hit
|
||||
int ent; // number of entity hit
|
||||
} bsp_trace_t;
|
||||
|
||||
#endif // BSPTRACE
|
||||
|
||||
//entity state
|
||||
typedef struct bot_entitystate_s
|
||||
{
|
||||
int type; // entity type
|
||||
int flags; // entity flags
|
||||
vec3_t origin; // origin of the entity
|
||||
vec3_t angles; // angles of the model
|
||||
vec3_t old_origin; // for lerping
|
||||
vec3_t mins; // bounding box minimums
|
||||
vec3_t maxs; // bounding box maximums
|
||||
int groundent; // ground entity
|
||||
int solid; // solid type
|
||||
int modelindex; // model used
|
||||
int modelindex2; // weapons, CTF flags, etc
|
||||
int frame; // model frame number
|
||||
int event; // impulse events -- muzzle flashes, footsteps, etc
|
||||
int eventParm; // even parameter
|
||||
int powerups; // bit flags
|
||||
int weapon; // determines weapon and flash model, etc
|
||||
int legsAnim; // mask off ANIM_TOGGLEBIT
|
||||
int torsoAnim; // mask off ANIM_TOGGLEBIT
|
||||
} bot_entitystate_t;
|
||||
|
||||
//bot AI library exported functions
|
||||
typedef struct botlib_import_s
|
||||
{
|
||||
//print messages from the bot library
|
||||
void (QDECL *Print)(int type, char *fmt, ...);
|
||||
//trace a bbox through the world
|
||||
void (*Trace)(bsp_trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask);
|
||||
//trace a bbox against a specific entity
|
||||
void (*EntityTrace)(bsp_trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int entnum, int contentmask);
|
||||
//retrieve the contents at the given point
|
||||
int (*PointContents)(vec3_t point);
|
||||
//check if the point is in potential visible sight
|
||||
int (*inPVS)(vec3_t p1, vec3_t p2);
|
||||
//retrieve the BSP entity data lump
|
||||
char *(*BSPEntityData)(void);
|
||||
//
|
||||
void (*BSPModelMinsMaxsOrigin)(int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin);
|
||||
//send a bot client command
|
||||
void (*BotClientCommand)(int client, char *command);
|
||||
//memory allocation
|
||||
void *(*GetMemory)(int size); // allocate from Zone
|
||||
void (*FreeMemory)(void *ptr); // free memory from Zone
|
||||
int (*AvailableMemory)(void); // available Zone memory
|
||||
void *(*HunkAlloc)(int size); // allocate from hunk
|
||||
//file system access
|
||||
int (*FS_FOpenFile)( const char *qpath, fileHandle_t *file, fsMode_t mode );
|
||||
int (*FS_Read)( void *buffer, int len, fileHandle_t f );
|
||||
int (*FS_Write)( const void *buffer, int len, fileHandle_t f );
|
||||
void (*FS_FCloseFile)( fileHandle_t f );
|
||||
int (*FS_Seek)( fileHandle_t f, long offset, int origin );
|
||||
//debug visualisation stuff
|
||||
int (*DebugLineCreate)(void);
|
||||
void (*DebugLineDelete)(int line);
|
||||
void (*DebugLineShow)(int line, vec3_t start, vec3_t end, int color);
|
||||
//
|
||||
int (*DebugPolygonCreate)(int color, int numPoints, vec3_t *points);
|
||||
void (*DebugPolygonDelete)(int id);
|
||||
} botlib_import_t;
|
||||
|
||||
typedef struct aas_export_s
|
||||
{
|
||||
//-----------------------------------
|
||||
// be_aas_entity.h
|
||||
//-----------------------------------
|
||||
void (*AAS_EntityInfo)(int entnum, struct aas_entityinfo_s *info);
|
||||
//-----------------------------------
|
||||
// be_aas_main.h
|
||||
//-----------------------------------
|
||||
int (*AAS_Initialized)(void);
|
||||
void (*AAS_PresenceTypeBoundingBox)(int presencetype, vec3_t mins, vec3_t maxs);
|
||||
float (*AAS_Time)(void);
|
||||
//--------------------------------------------
|
||||
// be_aas_sample.c
|
||||
//--------------------------------------------
|
||||
int (*AAS_PointAreaNum)(vec3_t point);
|
||||
int (*AAS_PointReachabilityAreaIndex)( vec3_t point );
|
||||
int (*AAS_TraceAreas)(vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas);
|
||||
int (*AAS_BBoxAreas)(vec3_t absmins, vec3_t absmaxs, int *areas, int maxareas);
|
||||
int (*AAS_AreaInfo)( int areanum, struct aas_areainfo_s *info );
|
||||
//--------------------------------------------
|
||||
// be_aas_bspq3.c
|
||||
//--------------------------------------------
|
||||
int (*AAS_PointContents)(vec3_t point);
|
||||
int (*AAS_NextBSPEntity)(int ent);
|
||||
int (*AAS_ValueForBSPEpairKey)(int ent, char *key, char *value, int size);
|
||||
int (*AAS_VectorForBSPEpairKey)(int ent, char *key, vec3_t v);
|
||||
int (*AAS_FloatForBSPEpairKey)(int ent, char *key, float *value);
|
||||
int (*AAS_IntForBSPEpairKey)(int ent, char *key, int *value);
|
||||
//--------------------------------------------
|
||||
// be_aas_reach.c
|
||||
//--------------------------------------------
|
||||
int (*AAS_AreaReachability)(int areanum);
|
||||
//--------------------------------------------
|
||||
// be_aas_route.c
|
||||
//--------------------------------------------
|
||||
int (*AAS_AreaTravelTimeToGoalArea)(int areanum, vec3_t origin, int goalareanum, int travelflags);
|
||||
int (*AAS_EnableRoutingArea)(int areanum, int enable);
|
||||
int (*AAS_PredictRoute)(struct aas_predictroute_s *route, int areanum, vec3_t origin,
|
||||
int goalareanum, int travelflags, int maxareas, int maxtime,
|
||||
int stopevent, int stopcontents, int stoptfl, int stopareanum);
|
||||
//--------------------------------------------
|
||||
// be_aas_altroute.c
|
||||
//--------------------------------------------
|
||||
int (*AAS_AlternativeRouteGoals)(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags,
|
||||
struct aas_altroutegoal_s *altroutegoals, int maxaltroutegoals,
|
||||
int type);
|
||||
//--------------------------------------------
|
||||
// be_aas_move.c
|
||||
//--------------------------------------------
|
||||
int (*AAS_Swimming)(vec3_t origin);
|
||||
int (*AAS_PredictClientMovement)(struct aas_clientmove_s *move,
|
||||
int entnum, vec3_t origin,
|
||||
int presencetype, int onground,
|
||||
vec3_t velocity, vec3_t cmdmove,
|
||||
int cmdframes,
|
||||
int maxframes, float frametime,
|
||||
int stopevent, int stopareanum, int visualize);
|
||||
} aas_export_t;
|
||||
|
||||
typedef struct ea_export_s
|
||||
{
|
||||
//ClientCommand elementary actions
|
||||
void (*EA_Command)(int client, char *command );
|
||||
void (*EA_Say)(int client, char *str);
|
||||
void (*EA_SayTeam)(int client, char *str);
|
||||
//
|
||||
void (*EA_Action)(int client, int action);
|
||||
void (*EA_Gesture)(int client);
|
||||
void (*EA_Talk)(int client);
|
||||
void (*EA_Attack)(int client);
|
||||
void (*EA_Use)(int client);
|
||||
void (*EA_Respawn)(int client);
|
||||
void (*EA_MoveUp)(int client);
|
||||
void (*EA_MoveDown)(int client);
|
||||
void (*EA_MoveForward)(int client);
|
||||
void (*EA_MoveBack)(int client);
|
||||
void (*EA_MoveLeft)(int client);
|
||||
void (*EA_MoveRight)(int client);
|
||||
void (*EA_Crouch)(int client);
|
||||
|
||||
void (*EA_SelectWeapon)(int client, int weapon);
|
||||
void (*EA_Jump)(int client);
|
||||
void (*EA_DelayedJump)(int client);
|
||||
void (*EA_Move)(int client, vec3_t dir, float speed);
|
||||
void (*EA_View)(int client, vec3_t viewangles);
|
||||
//send regular input to the server
|
||||
void (*EA_EndRegular)(int client, float thinktime);
|
||||
void (*EA_GetInput)(int client, float thinktime, bot_input_t *input);
|
||||
void (*EA_ResetInput)(int client);
|
||||
} ea_export_t;
|
||||
|
||||
typedef struct ai_export_s
|
||||
{
|
||||
//-----------------------------------
|
||||
// be_ai_char.h
|
||||
//-----------------------------------
|
||||
int (*BotLoadCharacter)(char *charfile, float skill);
|
||||
void (*BotFreeCharacter)(int character);
|
||||
float (*Characteristic_Float)(int character, int index);
|
||||
float (*Characteristic_BFloat)(int character, int index, float min, float max);
|
||||
int (*Characteristic_Integer)(int character, int index);
|
||||
int (*Characteristic_BInteger)(int character, int index, int min, int max);
|
||||
void (*Characteristic_String)(int character, int index, char *buf, int size);
|
||||
//-----------------------------------
|
||||
// be_ai_chat.h
|
||||
//-----------------------------------
|
||||
int (*BotAllocChatState)(void);
|
||||
void (*BotFreeChatState)(int handle);
|
||||
void (*BotQueueConsoleMessage)(int chatstate, int type, char *message);
|
||||
void (*BotRemoveConsoleMessage)(int chatstate, int handle);
|
||||
int (*BotNextConsoleMessage)(int chatstate, struct bot_consolemessage_s *cm);
|
||||
int (*BotNumConsoleMessages)(int chatstate);
|
||||
void (*BotInitialChat)(int chatstate, char *type, int mcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7);
|
||||
int (*BotNumInitialChats)(int chatstate, char *type);
|
||||
int (*BotReplyChat)(int chatstate, char *message, int mcontext, int vcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7);
|
||||
int (*BotChatLength)(int chatstate);
|
||||
void (*BotEnterChat)(int chatstate, int client, int sendto);
|
||||
void (*BotGetChatMessage)(int chatstate, char *buf, int size);
|
||||
int (*StringContains)(char *str1, char *str2, int casesensitive);
|
||||
int (*BotFindMatch)(char *str, struct bot_match_s *match, unsigned long int context);
|
||||
void (*BotMatchVariable)(struct bot_match_s *match, int variable, char *buf, int size);
|
||||
void (*UnifyWhiteSpaces)(char *string);
|
||||
void (*BotReplaceSynonyms)(char *string, unsigned long int context);
|
||||
int (*BotLoadChatFile)(int chatstate, char *chatfile, char *chatname);
|
||||
void (*BotSetChatGender)(int chatstate, int gender);
|
||||
void (*BotSetChatName)(int chatstate, char *name, int client);
|
||||
//-----------------------------------
|
||||
// be_ai_goal.h
|
||||
//-----------------------------------
|
||||
void (*BotResetGoalState)(int goalstate);
|
||||
void (*BotResetAvoidGoals)(int goalstate);
|
||||
void (*BotRemoveFromAvoidGoals)(int goalstate, int number);
|
||||
void (*BotPushGoal)(int goalstate, struct bot_goal_s *goal);
|
||||
void (*BotPopGoal)(int goalstate);
|
||||
void (*BotEmptyGoalStack)(int goalstate);
|
||||
void (*BotDumpAvoidGoals)(int goalstate);
|
||||
void (*BotDumpGoalStack)(int goalstate);
|
||||
void (*BotGoalName)(int number, char *name, int size);
|
||||
int (*BotGetTopGoal)(int goalstate, struct bot_goal_s *goal);
|
||||
int (*BotGetSecondGoal)(int goalstate, struct bot_goal_s *goal);
|
||||
int (*BotChooseLTGItem)(int goalstate, vec3_t origin, int *inventory, int travelflags);
|
||||
int (*BotChooseNBGItem)(int goalstate, vec3_t origin, int *inventory, int travelflags,
|
||||
struct bot_goal_s *ltg, float maxtime);
|
||||
int (*BotTouchingGoal)(vec3_t origin, struct bot_goal_s *goal);
|
||||
int (*BotItemGoalInVisButNotVisible)(int viewer, vec3_t eye, vec3_t viewangles, struct bot_goal_s *goal);
|
||||
int (*BotGetLevelItemGoal)(int index, char *classname, struct bot_goal_s *goal);
|
||||
int (*BotGetNextCampSpotGoal)(int num, struct bot_goal_s *goal);
|
||||
int (*BotGetMapLocationGoal)(char *name, struct bot_goal_s *goal);
|
||||
float (*BotAvoidGoalTime)(int goalstate, int number);
|
||||
void (*BotSetAvoidGoalTime)(int goalstate, int number, float avoidtime);
|
||||
void (*BotInitLevelItems)(void);
|
||||
void (*BotUpdateEntityItems)(void);
|
||||
int (*BotLoadItemWeights)(int goalstate, char *filename);
|
||||
void (*BotFreeItemWeights)(int goalstate);
|
||||
void (*BotInterbreedGoalFuzzyLogic)(int parent1, int parent2, int child);
|
||||
void (*BotSaveGoalFuzzyLogic)(int goalstate, char *filename);
|
||||
void (*BotMutateGoalFuzzyLogic)(int goalstate, float range);
|
||||
int (*BotAllocGoalState)(int client);
|
||||
void (*BotFreeGoalState)(int handle);
|
||||
//-----------------------------------
|
||||
// be_ai_move.h
|
||||
//-----------------------------------
|
||||
void (*BotResetMoveState)(int movestate);
|
||||
void (*BotMoveToGoal)(struct bot_moveresult_s *result, int movestate, struct bot_goal_s *goal, int travelflags);
|
||||
int (*BotMoveInDirection)(int movestate, vec3_t dir, float speed, int type);
|
||||
void (*BotResetAvoidReach)(int movestate);
|
||||
void (*BotResetLastAvoidReach)(int movestate);
|
||||
int (*BotReachabilityArea)(vec3_t origin, int testground);
|
||||
int (*BotMovementViewTarget)(int movestate, struct bot_goal_s *goal, int travelflags, float lookahead, vec3_t target);
|
||||
int (*BotPredictVisiblePosition)(vec3_t origin, int areanum, struct bot_goal_s *goal, int travelflags, vec3_t target);
|
||||
int (*BotAllocMoveState)(void);
|
||||
void (*BotFreeMoveState)(int handle);
|
||||
void (*BotInitMoveState)(int handle, struct bot_initmove_s *initmove);
|
||||
void (*BotAddAvoidSpot)(int movestate, vec3_t origin, float radius, int type);
|
||||
//-----------------------------------
|
||||
// be_ai_weap.h
|
||||
//-----------------------------------
|
||||
int (*BotChooseBestFightWeapon)(int weaponstate, int *inventory);
|
||||
void (*BotGetWeaponInfo)(int weaponstate, int weapon, struct weaponinfo_s *weaponinfo);
|
||||
int (*BotLoadWeaponWeights)(int weaponstate, char *filename);
|
||||
int (*BotAllocWeaponState)(void);
|
||||
void (*BotFreeWeaponState)(int weaponstate);
|
||||
void (*BotResetWeaponState)(int weaponstate);
|
||||
//-----------------------------------
|
||||
// be_ai_gen.h
|
||||
//-----------------------------------
|
||||
int (*GeneticParentsAndChildSelection)(int numranks, float *ranks, int *parent1, int *parent2, int *child);
|
||||
} ai_export_t;
|
||||
|
||||
//bot AI library imported functions
|
||||
typedef struct botlib_export_s
|
||||
{
|
||||
//Area Awareness System functions
|
||||
aas_export_t aas;
|
||||
//Elementary Action functions
|
||||
ea_export_t ea;
|
||||
//AI functions
|
||||
ai_export_t ai;
|
||||
//setup the bot library, returns BLERR_
|
||||
int (*BotLibSetup)(void);
|
||||
//shutdown the bot library, returns BLERR_
|
||||
int (*BotLibShutdown)(void);
|
||||
//sets a library variable returns BLERR_
|
||||
int (*BotLibVarSet)(char *var_name, char *value);
|
||||
//gets a library variable returns BLERR_
|
||||
int (*BotLibVarGet)(char *var_name, char *value, int size);
|
||||
|
||||
//sets a C-like define returns BLERR_
|
||||
int (*PC_AddGlobalDefine)(char *string);
|
||||
int (*PC_LoadSourceHandle)(const char *filename);
|
||||
int (*PC_FreeSourceHandle)(int handle);
|
||||
int (*PC_ReadTokenHandle)(int handle, pc_token_t *pc_token);
|
||||
int (*PC_SourceFileAndLine)(int handle, char *filename, int *line);
|
||||
|
||||
//start a frame in the bot library
|
||||
int (*BotLibStartFrame)(float time);
|
||||
//load a new map in the bot library
|
||||
int (*BotLibLoadMap)(const char *mapname);
|
||||
//entity updates
|
||||
int (*BotLibUpdateEntity)(int ent, bot_entitystate_t *state);
|
||||
//just for testing
|
||||
int (*Test)(int parm0, char *parm1, vec3_t parm2, vec3_t parm3);
|
||||
} botlib_export_t;
|
||||
|
||||
//linking of bot library
|
||||
botlib_export_t *GetBotLibAPI( int apiVersion, botlib_import_t *import );
|
||||
|
||||
/* Library variables:
|
||||
|
||||
name: default: module(s): description:
|
||||
|
||||
"basedir" "" l_utils.c base directory
|
||||
"gamedir" "" l_utils.c game directory
|
||||
"cddir" "" l_utils.c CD directory
|
||||
|
||||
"log" "0" l_log.c enable/disable creating a log file
|
||||
"maxclients" "4" be_interface.c maximum number of clients
|
||||
"maxentities" "1024" be_interface.c maximum number of entities
|
||||
"bot_developer" "0" be_interface.c bot developer mode
|
||||
|
||||
"phys_friction" "6" be_aas_move.c ground friction
|
||||
"phys_stopspeed" "100" be_aas_move.c stop speed
|
||||
"phys_gravity" "800" be_aas_move.c gravity value
|
||||
"phys_waterfriction" "1" be_aas_move.c water friction
|
||||
"phys_watergravity" "400" be_aas_move.c gravity in water
|
||||
"phys_maxvelocity" "320" be_aas_move.c maximum velocity
|
||||
"phys_maxwalkvelocity" "320" be_aas_move.c maximum walk velocity
|
||||
"phys_maxcrouchvelocity" "100" be_aas_move.c maximum crouch velocity
|
||||
"phys_maxswimvelocity" "150" be_aas_move.c maximum swim velocity
|
||||
"phys_walkaccelerate" "10" be_aas_move.c walk acceleration
|
||||
"phys_airaccelerate" "1" be_aas_move.c air acceleration
|
||||
"phys_swimaccelerate" "4" be_aas_move.c swim acceleration
|
||||
"phys_maxstep" "18" be_aas_move.c maximum step height
|
||||
"phys_maxsteepness" "0.7" be_aas_move.c maximum floor steepness
|
||||
"phys_maxbarrier" "32" be_aas_move.c maximum barrier height
|
||||
"phys_maxwaterjump" "19" be_aas_move.c maximum waterjump height
|
||||
"phys_jumpvel" "270" be_aas_move.c jump z velocity
|
||||
"phys_falldelta5" "40" be_aas_move.c
|
||||
"phys_falldelta10" "60" be_aas_move.c
|
||||
"rs_waterjump" "400" be_aas_move.c
|
||||
"rs_teleport" "50" be_aas_move.c
|
||||
"rs_barrierjump" "100" be_aas_move.c
|
||||
"rs_startcrouch" "300" be_aas_move.c
|
||||
"rs_startgrapple" "500" be_aas_move.c
|
||||
"rs_startwalkoffledge" "70" be_aas_move.c
|
||||
"rs_startjump" "300" be_aas_move.c
|
||||
"rs_rocketjump" "500" be_aas_move.c
|
||||
"rs_bfgjump" "500" be_aas_move.c
|
||||
"rs_jumppad" "250" be_aas_move.c
|
||||
"rs_aircontrolledjumppad" "300" be_aas_move.c
|
||||
"rs_funcbob" "300" be_aas_move.c
|
||||
"rs_startelevator" "50" be_aas_move.c
|
||||
"rs_falldamage5" "300" be_aas_move.c
|
||||
"rs_falldamage10" "500" be_aas_move.c
|
||||
"rs_maxjumpfallheight" "450" be_aas_move.c
|
||||
|
||||
"max_aaslinks" "4096" be_aas_sample.c maximum links in the AAS
|
||||
"max_routingcache" "4096" be_aas_route.c maximum routing cache size in KB
|
||||
"forceclustering" "0" be_aas_main.c force recalculation of clusters
|
||||
"forcereachability" "0" be_aas_main.c force recalculation of reachabilities
|
||||
"forcewrite" "0" be_aas_main.c force writing of aas file
|
||||
"aasoptimize" "0" be_aas_main.c enable aas optimization
|
||||
"sv_mapChecksum" "0" be_aas_main.c BSP file checksum
|
||||
"bot_visualizejumppads" "0" be_aas_reach.c visualize jump pads
|
||||
|
||||
"bot_reloadcharacters" "0" - reload bot character files
|
||||
"ai_gametype" "0" be_ai_goal.c game type
|
||||
"droppedweight" "1000" be_ai_goal.c additional dropped item weight
|
||||
"weapindex_rocketlauncher" "5" be_ai_move.c rl weapon index for rocket jumping
|
||||
"weapindex_bfg10k" "9" be_ai_move.c bfg weapon index for bfg jumping
|
||||
"weapindex_grapple" "10" be_ai_move.c grapple weapon index for grappling
|
||||
"entitytypemissile" "3" be_ai_move.c ET_MISSILE
|
||||
"offhandgrapple" "0" be_ai_move.c enable off hand grapple hook
|
||||
"cmd_grappleon" "grappleon" be_ai_move.c command to activate off hand grapple
|
||||
"cmd_grappleoff" "grappleoff" be_ai_move.c command to deactivate off hand grapple
|
||||
"itemconfig" "items.c" be_ai_goal.c item configuration file
|
||||
"weaponconfig" "weapons.c" be_ai_weap.c weapon configuration file
|
||||
"synfile" "syn.c" be_ai_chat.c file with synonyms
|
||||
"rndfile" "rnd.c" be_ai_chat.c file with random strings
|
||||
"matchfile" "match.c" be_ai_chat.c file with match strings
|
||||
"nochat" "0" be_ai_chat.c disable chats
|
||||
"max_messages" "1024" be_ai_chat.c console message heap size
|
||||
"max_weaponinfo" "32" be_ai_weap.c maximum number of weapon info
|
||||
"max_projectileinfo" "32" be_ai_weap.c maximum number of projectile info
|
||||
"max_iteminfo" "256" be_ai_goal.c maximum number of item info
|
||||
"max_levelitems" "256" be_ai_goal.c maximum number of level items
|
||||
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//========================================================
|
||||
//========================================================
|
||||
//name
|
||||
#define CHARACTERISTIC_NAME 0 //string
|
||||
//gender of the bot
|
||||
#define CHARACTERISTIC_GENDER 1 //string ("male", "female", "it")
|
||||
//attack skill
|
||||
// > 0.0 && < 0.2 = don't move
|
||||
// > 0.3 && < 1.0 = aim at enemy during retreat
|
||||
// > 0.0 && < 0.4 = only move forward/backward
|
||||
// >= 0.4 && < 1.0 = circle strafing
|
||||
// > 0.7 && < 1.0 = random strafe direction change
|
||||
#define CHARACTERISTIC_ATTACK_SKILL 2 //float [0, 1]
|
||||
//weapon weight file
|
||||
#define CHARACTERISTIC_WEAPONWEIGHTS 3 //string
|
||||
//view angle difference to angle change factor
|
||||
#define CHARACTERISTIC_VIEW_FACTOR 4 //float <0, 1]
|
||||
//maximum view angle change
|
||||
#define CHARACTERISTIC_VIEW_MAXCHANGE 5 //float [1, 360]
|
||||
//reaction time in seconds
|
||||
#define CHARACTERISTIC_REACTIONTIME 6 //float [0, 5]
|
||||
//accuracy when aiming
|
||||
#define CHARACTERISTIC_AIM_ACCURACY 7 //float [0, 1]
|
||||
//weapon specific aim accuracy
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_MACHINEGUN 8 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_SHOTGUN 9 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_ROCKETLAUNCHER 10 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_GRENADELAUNCHER 11 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_LIGHTNING 12
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_PLASMAGUN 13 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_RAILGUN 14
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_BFG10K 15 //float [0, 1]
|
||||
//skill when aiming
|
||||
// > 0.0 && < 0.9 = aim is affected by enemy movement
|
||||
// > 0.4 && <= 0.8 = enemy linear leading
|
||||
// > 0.8 && <= 1.0 = enemy exact movement leading
|
||||
// > 0.5 && <= 1.0 = prediction shots when enemy is not visible
|
||||
// > 0.6 && <= 1.0 = splash damage by shooting nearby geometry
|
||||
#define CHARACTERISTIC_AIM_SKILL 16 //float [0, 1]
|
||||
//weapon specific aim skill
|
||||
#define CHARACTERISTIC_AIM_SKILL_ROCKETLAUNCHER 17 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_SKILL_GRENADELAUNCHER 18 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_SKILL_PLASMAGUN 19 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_SKILL_BFG10K 20 //float [0, 1]
|
||||
//========================================================
|
||||
//chat
|
||||
//========================================================
|
||||
//file with chats
|
||||
#define CHARACTERISTIC_CHAT_FILE 21 //string
|
||||
//name of the chat character
|
||||
#define CHARACTERISTIC_CHAT_NAME 22 //string
|
||||
//characters per minute type speed
|
||||
#define CHARACTERISTIC_CHAT_CPM 23 //integer [1, 4000]
|
||||
//tendency to insult/praise
|
||||
#define CHARACTERISTIC_CHAT_INSULT 24 //float [0, 1]
|
||||
//tendency to chat misc
|
||||
#define CHARACTERISTIC_CHAT_MISC 25 //float [0, 1]
|
||||
//tendency to chat at start or end of level
|
||||
#define CHARACTERISTIC_CHAT_STARTENDLEVEL 26 //float [0, 1]
|
||||
//tendency to chat entering or exiting the game
|
||||
#define CHARACTERISTIC_CHAT_ENTEREXITGAME 27 //float [0, 1]
|
||||
//tendency to chat when killed someone
|
||||
#define CHARACTERISTIC_CHAT_KILL 28 //float [0, 1]
|
||||
//tendency to chat when died
|
||||
#define CHARACTERISTIC_CHAT_DEATH 29 //float [0, 1]
|
||||
//tendency to chat when enemy suicides
|
||||
#define CHARACTERISTIC_CHAT_ENEMYSUICIDE 30 //float [0, 1]
|
||||
//tendency to chat when hit while talking
|
||||
#define CHARACTERISTIC_CHAT_HITTALKING 31 //float [0, 1]
|
||||
//tendency to chat when bot was hit but didn't dye
|
||||
#define CHARACTERISTIC_CHAT_HITNODEATH 32 //float [0, 1]
|
||||
//tendency to chat when bot hit the enemy but enemy didn't dye
|
||||
#define CHARACTERISTIC_CHAT_HITNOKILL 33 //float [0, 1]
|
||||
//tendency to randomly chat
|
||||
#define CHARACTERISTIC_CHAT_RANDOM 34 //float [0, 1]
|
||||
//tendency to reply
|
||||
#define CHARACTERISTIC_CHAT_REPLY 35 //float [0, 1]
|
||||
//========================================================
|
||||
//movement
|
||||
//========================================================
|
||||
//tendency to crouch
|
||||
#define CHARACTERISTIC_CROUCHER 36 //float [0, 1]
|
||||
//tendency to jump
|
||||
#define CHARACTERISTIC_JUMPER 37 //float [0, 1]
|
||||
//tendency to walk
|
||||
#define CHARACTERISTIC_WALKER 48 //float [0, 1]
|
||||
//tendency to jump using a weapon
|
||||
#define CHARACTERISTIC_WEAPONJUMPING 38 //float [0, 1]
|
||||
//tendency to use the grapple hook when available
|
||||
#define CHARACTERISTIC_GRAPPLE_USER 39 //float [0, 1] //use this!!
|
||||
//========================================================
|
||||
//goal
|
||||
//========================================================
|
||||
//item weight file
|
||||
#define CHARACTERISTIC_ITEMWEIGHTS 40 //string
|
||||
//the aggression of the bot
|
||||
#define CHARACTERISTIC_AGGRESSION 41 //float [0, 1]
|
||||
//the self preservation of the bot (rockets near walls etc.)
|
||||
#define CHARACTERISTIC_SELFPRESERVATION 42 //float [0, 1]
|
||||
//how likely the bot is to take revenge
|
||||
#define CHARACTERISTIC_VENGEFULNESS 43 //float [0, 1] //use this!!
|
||||
//tendency to camp
|
||||
#define CHARACTERISTIC_CAMPER 44 //float [0, 1]
|
||||
//========================================================
|
||||
//========================================================
|
||||
//tendency to get easy frags
|
||||
#define CHARACTERISTIC_EASY_FRAGGER 45 //float [0, 1]
|
||||
//how alert the bot is (view distance)
|
||||
#define CHARACTERISTIC_ALERTNESS 46 //float [0, 1]
|
||||
//how much the bot fires it's weapon
|
||||
#define CHARACTERISTIC_FIRETHROTTLE 47 //float [0, 1]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
//
|
||||
// g_arenas.c
|
||||
//
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
|
||||
gentity_t *podium1;
|
||||
gentity_t *podium2;
|
||||
gentity_t *podium3;
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
UpdateTournamentInfo
|
||||
==================
|
||||
*/
|
||||
void UpdateTournamentInfo( void ) {
|
||||
int i;
|
||||
gentity_t *player;
|
||||
int playerClientNum;
|
||||
int n, accuracy, perfect, msglen;
|
||||
int buflen;
|
||||
#ifdef MISSIONPACK // bk001205
|
||||
int score1, score2;
|
||||
qboolean won;
|
||||
#endif
|
||||
char buf[32];
|
||||
char msg[MAX_STRING_CHARS];
|
||||
|
||||
// find the real player
|
||||
player = NULL;
|
||||
for (i = 0; i < level.maxclients; i++ ) {
|
||||
player = &g_entities[i];
|
||||
if ( !player->inuse ) {
|
||||
continue;
|
||||
}
|
||||
if ( !( player->r.svFlags & SVF_BOT ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// this should never happen!
|
||||
if ( !player || i == level.maxclients ) {
|
||||
return;
|
||||
}
|
||||
playerClientNum = i;
|
||||
|
||||
CalculateRanks();
|
||||
|
||||
if ( level.clients[playerClientNum].sess.sessionTeam == TEAM_SPECTATOR ) {
|
||||
#ifdef MISSIONPACK
|
||||
Com_sprintf( msg, sizeof(msg), "postgame %i %i 0 0 0 0 0 0 0 0 0 0 0", level.numNonSpectatorClients, playerClientNum );
|
||||
#else
|
||||
Com_sprintf( msg, sizeof(msg), "postgame %i %i 0 0 0 0 0 0", level.numNonSpectatorClients, playerClientNum );
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if( player->client->accuracy_shots ) {
|
||||
accuracy = player->client->accuracy_hits * 100 / player->client->accuracy_shots;
|
||||
}
|
||||
else {
|
||||
accuracy = 0;
|
||||
}
|
||||
#ifdef MISSIONPACK
|
||||
won = qfalse;
|
||||
if (g_gametype.integer >= GT_CTF) {
|
||||
score1 = level.teamScores[TEAM_RED];
|
||||
score2 = level.teamScores[TEAM_BLUE];
|
||||
if (level.clients[playerClientNum].sess.sessionTeam == TEAM_RED) {
|
||||
won = (level.teamScores[TEAM_RED] > level.teamScores[TEAM_BLUE]);
|
||||
} else {
|
||||
won = (level.teamScores[TEAM_BLUE] > level.teamScores[TEAM_RED]);
|
||||
}
|
||||
} else {
|
||||
if (&level.clients[playerClientNum] == &level.clients[ level.sortedClients[0] ]) {
|
||||
won = qtrue;
|
||||
score1 = level.clients[ level.sortedClients[0] ].ps.persistant[PERS_SCORE];
|
||||
score2 = level.clients[ level.sortedClients[1] ].ps.persistant[PERS_SCORE];
|
||||
} else {
|
||||
score2 = level.clients[ level.sortedClients[0] ].ps.persistant[PERS_SCORE];
|
||||
score1 = level.clients[ level.sortedClients[1] ].ps.persistant[PERS_SCORE];
|
||||
}
|
||||
}
|
||||
if (won && player->client->ps.persistant[PERS_KILLED] == 0) {
|
||||
perfect = 1;
|
||||
} else {
|
||||
perfect = 0;
|
||||
}
|
||||
Com_sprintf( msg, sizeof(msg), "postgame %i %i %i %i %i %i %i %i %i %i %i %i %i %i", level.numNonSpectatorClients, playerClientNum, accuracy,
|
||||
player->client->ps.persistant[PERS_IMPRESSIVE_COUNT], player->client->ps.persistant[PERS_EXCELLENT_COUNT],player->client->ps.persistant[PERS_DEFEND_COUNT],
|
||||
player->client->ps.persistant[PERS_ASSIST_COUNT], player->client->ps.persistant[PERS_GAUNTLET_FRAG_COUNT], player->client->ps.persistant[PERS_SCORE],
|
||||
perfect, score1, score2, level.time, player->client->ps.persistant[PERS_CAPTURES] );
|
||||
|
||||
#else
|
||||
perfect = ( level.clients[playerClientNum].ps.persistant[PERS_RANK] == 0 && player->client->ps.persistant[PERS_KILLED] == 0 ) ? 1 : 0;
|
||||
Com_sprintf( msg, sizeof(msg), "postgame %i %i %i %i %i %i %i %i", level.numNonSpectatorClients, playerClientNum, accuracy,
|
||||
player->client->ps.persistant[PERS_IMPRESSIVE_COUNT], player->client->ps.persistant[PERS_EXCELLENT_COUNT],
|
||||
player->client->ps.persistant[PERS_GAUNTLET_FRAG_COUNT], player->client->ps.persistant[PERS_SCORE],
|
||||
perfect );
|
||||
#endif
|
||||
}
|
||||
|
||||
msglen = strlen( msg );
|
||||
for( i = 0; i < level.numNonSpectatorClients; i++ ) {
|
||||
n = level.sortedClients[i];
|
||||
Com_sprintf( buf, sizeof(buf), " %i %i %i", n, level.clients[n].ps.persistant[PERS_RANK], level.clients[n].ps.persistant[PERS_SCORE] );
|
||||
buflen = strlen( buf );
|
||||
if( msglen + buflen + 1 >= sizeof(msg) ) {
|
||||
break;
|
||||
}
|
||||
strcat( msg, buf );
|
||||
}
|
||||
trap_SendConsoleCommand( EXEC_APPEND, msg );
|
||||
}
|
||||
|
||||
|
||||
static gentity_t *SpawnModelOnVictoryPad( gentity_t *pad, vec3_t offset, gentity_t *ent, int place ) {
|
||||
gentity_t *body;
|
||||
vec3_t vec;
|
||||
vec3_t f, r, u;
|
||||
|
||||
body = G_Spawn();
|
||||
if ( !body ) {
|
||||
G_Printf( S_COLOR_RED "ERROR: out of gentities\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
body->classname = ent->client->pers.netname;
|
||||
body->client = ent->client;
|
||||
body->s = ent->s;
|
||||
body->s.eType = ET_PLAYER; // could be ET_INVISIBLE
|
||||
body->s.eFlags = 0; // clear EF_TALK, etc
|
||||
body->s.powerups = 0; // clear powerups
|
||||
body->s.loopSound = 0; // clear lava burning
|
||||
body->s.number = body - g_entities;
|
||||
body->timestamp = level.time;
|
||||
body->physicsObject = qtrue;
|
||||
body->physicsBounce = 0; // don't bounce
|
||||
body->s.event = 0;
|
||||
body->s.pos.trType = TR_STATIONARY;
|
||||
body->s.groundEntityNum = ENTITYNUM_WORLD;
|
||||
body->s.legsAnim = LEGS_IDLE;
|
||||
body->s.torsoAnim = TORSO_STAND;
|
||||
if( body->s.weapon == WP_NONE ) {
|
||||
body->s.weapon = WP_MACHINEGUN;
|
||||
}
|
||||
if( body->s.weapon == WP_GAUNTLET) {
|
||||
body->s.torsoAnim = TORSO_STAND2;
|
||||
}
|
||||
body->s.event = 0;
|
||||
body->r.svFlags = ent->r.svFlags;
|
||||
VectorCopy (ent->r.mins, body->r.mins);
|
||||
VectorCopy (ent->r.maxs, body->r.maxs);
|
||||
VectorCopy (ent->r.absmin, body->r.absmin);
|
||||
VectorCopy (ent->r.absmax, body->r.absmax);
|
||||
body->clipmask = CONTENTS_SOLID | CONTENTS_PLAYERCLIP;
|
||||
body->r.contents = CONTENTS_BODY;
|
||||
body->r.ownerNum = ent->r.ownerNum;
|
||||
body->takedamage = qfalse;
|
||||
|
||||
VectorSubtract( level.intermission_origin, pad->r.currentOrigin, vec );
|
||||
vectoangles( vec, body->s.apos.trBase );
|
||||
body->s.apos.trBase[PITCH] = 0;
|
||||
body->s.apos.trBase[ROLL] = 0;
|
||||
|
||||
AngleVectors( body->s.apos.trBase, f, r, u );
|
||||
VectorMA( pad->r.currentOrigin, offset[0], f, vec );
|
||||
VectorMA( vec, offset[1], r, vec );
|
||||
VectorMA( vec, offset[2], u, vec );
|
||||
|
||||
G_SetOrigin( body, vec );
|
||||
|
||||
trap_LinkEntity (body);
|
||||
|
||||
body->count = place;
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
|
||||
static void CelebrateStop( gentity_t *player ) {
|
||||
int anim;
|
||||
|
||||
if( player->s.weapon == WP_GAUNTLET) {
|
||||
anim = TORSO_STAND2;
|
||||
}
|
||||
else {
|
||||
anim = TORSO_STAND;
|
||||
}
|
||||
player->s.torsoAnim = ( ( player->s.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
|
||||
}
|
||||
|
||||
|
||||
#define TIMER_GESTURE (34*66+50)
|
||||
static void CelebrateStart( gentity_t *player ) {
|
||||
player->s.torsoAnim = ( ( player->s.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | TORSO_GESTURE;
|
||||
player->nextthink = level.time + TIMER_GESTURE;
|
||||
player->think = CelebrateStop;
|
||||
|
||||
/*
|
||||
player->client->ps.events[player->client->ps.eventSequence & (MAX_PS_EVENTS-1)] = EV_TAUNT;
|
||||
player->client->ps.eventParms[player->client->ps.eventSequence & (MAX_PS_EVENTS-1)] = 0;
|
||||
player->client->ps.eventSequence++;
|
||||
*/
|
||||
G_AddEvent(player, EV_TAUNT, 0);
|
||||
}
|
||||
|
||||
|
||||
static vec3_t offsetFirst = {0, 0, 74};
|
||||
static vec3_t offsetSecond = {-10, 60, 54};
|
||||
static vec3_t offsetThird = {-19, -60, 45};
|
||||
|
||||
static void PodiumPlacementThink( gentity_t *podium ) {
|
||||
vec3_t vec;
|
||||
vec3_t origin;
|
||||
vec3_t f, r, u;
|
||||
|
||||
podium->nextthink = level.time + 100;
|
||||
|
||||
AngleVectors( level.intermission_angle, vec, NULL, NULL );
|
||||
VectorMA( level.intermission_origin, trap_Cvar_VariableIntegerValue( "g_podiumDist" ), vec, origin );
|
||||
origin[2] -= trap_Cvar_VariableIntegerValue( "g_podiumDrop" );
|
||||
G_SetOrigin( podium, origin );
|
||||
|
||||
if( podium1 ) {
|
||||
VectorSubtract( level.intermission_origin, podium->r.currentOrigin, vec );
|
||||
vectoangles( vec, podium1->s.apos.trBase );
|
||||
podium1->s.apos.trBase[PITCH] = 0;
|
||||
podium1->s.apos.trBase[ROLL] = 0;
|
||||
|
||||
AngleVectors( podium1->s.apos.trBase, f, r, u );
|
||||
VectorMA( podium->r.currentOrigin, offsetFirst[0], f, vec );
|
||||
VectorMA( vec, offsetFirst[1], r, vec );
|
||||
VectorMA( vec, offsetFirst[2], u, vec );
|
||||
|
||||
G_SetOrigin( podium1, vec );
|
||||
}
|
||||
|
||||
if( podium2 ) {
|
||||
VectorSubtract( level.intermission_origin, podium->r.currentOrigin, vec );
|
||||
vectoangles( vec, podium2->s.apos.trBase );
|
||||
podium2->s.apos.trBase[PITCH] = 0;
|
||||
podium2->s.apos.trBase[ROLL] = 0;
|
||||
|
||||
AngleVectors( podium2->s.apos.trBase, f, r, u );
|
||||
VectorMA( podium->r.currentOrigin, offsetSecond[0], f, vec );
|
||||
VectorMA( vec, offsetSecond[1], r, vec );
|
||||
VectorMA( vec, offsetSecond[2], u, vec );
|
||||
|
||||
G_SetOrigin( podium2, vec );
|
||||
}
|
||||
|
||||
if( podium3 ) {
|
||||
VectorSubtract( level.intermission_origin, podium->r.currentOrigin, vec );
|
||||
vectoangles( vec, podium3->s.apos.trBase );
|
||||
podium3->s.apos.trBase[PITCH] = 0;
|
||||
podium3->s.apos.trBase[ROLL] = 0;
|
||||
|
||||
AngleVectors( podium3->s.apos.trBase, f, r, u );
|
||||
VectorMA( podium->r.currentOrigin, offsetThird[0], f, vec );
|
||||
VectorMA( vec, offsetThird[1], r, vec );
|
||||
VectorMA( vec, offsetThird[2], u, vec );
|
||||
|
||||
G_SetOrigin( podium3, vec );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gentity_t *SpawnPodium( void ) {
|
||||
gentity_t *podium;
|
||||
vec3_t vec;
|
||||
vec3_t origin;
|
||||
|
||||
podium = G_Spawn();
|
||||
if ( !podium ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
podium->classname = "podium";
|
||||
podium->s.eType = ET_GENERAL;
|
||||
podium->s.number = podium - g_entities;
|
||||
podium->clipmask = CONTENTS_SOLID;
|
||||
podium->r.contents = CONTENTS_SOLID;
|
||||
podium->s.modelindex = G_ModelIndex( SP_PODIUM_MODEL );
|
||||
|
||||
AngleVectors( level.intermission_angle, vec, NULL, NULL );
|
||||
VectorMA( level.intermission_origin, trap_Cvar_VariableIntegerValue( "g_podiumDist" ), vec, origin );
|
||||
origin[2] -= trap_Cvar_VariableIntegerValue( "g_podiumDrop" );
|
||||
G_SetOrigin( podium, origin );
|
||||
|
||||
VectorSubtract( level.intermission_origin, podium->r.currentOrigin, vec );
|
||||
podium->s.apos.trBase[YAW] = vectoyaw( vec );
|
||||
trap_LinkEntity (podium);
|
||||
|
||||
podium->think = PodiumPlacementThink;
|
||||
podium->nextthink = level.time + 100;
|
||||
return podium;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
SpawnModelsOnVictoryPads
|
||||
==================
|
||||
*/
|
||||
void SpawnModelsOnVictoryPads( void ) {
|
||||
gentity_t *player;
|
||||
gentity_t *podium;
|
||||
|
||||
podium1 = NULL;
|
||||
podium2 = NULL;
|
||||
podium3 = NULL;
|
||||
|
||||
podium = SpawnPodium();
|
||||
|
||||
player = SpawnModelOnVictoryPad( podium, offsetFirst, &g_entities[level.sortedClients[0]],
|
||||
level.clients[ level.sortedClients[0] ].ps.persistant[PERS_RANK] &~ RANK_TIED_FLAG );
|
||||
if ( player ) {
|
||||
player->nextthink = level.time + 2000;
|
||||
player->think = CelebrateStart;
|
||||
podium1 = player;
|
||||
}
|
||||
|
||||
player = SpawnModelOnVictoryPad( podium, offsetSecond, &g_entities[level.sortedClients[1]],
|
||||
level.clients[ level.sortedClients[1] ].ps.persistant[PERS_RANK] &~ RANK_TIED_FLAG );
|
||||
if ( player ) {
|
||||
podium2 = player;
|
||||
}
|
||||
|
||||
if ( level.numNonSpectatorClients > 2 ) {
|
||||
player = SpawnModelOnVictoryPad( podium, offsetThird, &g_entities[level.sortedClients[2]],
|
||||
level.clients[ level.sortedClients[2] ].ps.persistant[PERS_RANK] &~ RANK_TIED_FLAG );
|
||||
if ( player ) {
|
||||
podium3 = player;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Svcmd_AbortPodium_f
|
||||
===============
|
||||
*/
|
||||
void Svcmd_AbortPodium_f( void ) {
|
||||
if( g_gametype.integer != GT_SINGLE_PLAYER ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( podium1 ) {
|
||||
podium1->nextthink = level.time;
|
||||
podium1->think = CelebrateStop;
|
||||
}
|
||||
}
|
||||
+1017
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1701
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1010
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,971 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
// g_local.h -- local definitions for game module
|
||||
|
||||
#include "q_shared.h"
|
||||
#include "bg_public.h"
|
||||
#include "g_public.h"
|
||||
|
||||
//==================================================================
|
||||
|
||||
// the "gameversion" client command will print this plus compile date
|
||||
#define GAMEVERSION "baseq3"
|
||||
|
||||
#define BODY_QUEUE_SIZE 8
|
||||
|
||||
#define INFINITE 1000000
|
||||
|
||||
#define FRAMETIME 100 // msec
|
||||
#define CARNAGE_REWARD_TIME 3000
|
||||
#define REWARD_SPRITE_TIME 2000
|
||||
|
||||
#define INTERMISSION_DELAY_TIME 1000
|
||||
#define SP_INTERMISSION_DELAY_TIME 5000
|
||||
|
||||
// gentity->flags
|
||||
#define FL_GODMODE 0x00000010
|
||||
#define FL_NOTARGET 0x00000020
|
||||
#define FL_TEAMSLAVE 0x00000400 // not the first on the team
|
||||
#define FL_NO_KNOCKBACK 0x00000800
|
||||
#define FL_DROPPED_ITEM 0x00001000
|
||||
#define FL_NO_BOTS 0x00002000 // spawn point not for bot use
|
||||
#define FL_NO_HUMANS 0x00004000 // spawn point just for bots
|
||||
#define FL_FORCE_GESTURE 0x00008000 // force gesture on client
|
||||
|
||||
// movers are things like doors, plats, buttons, etc
|
||||
typedef enum {
|
||||
MOVER_POS1,
|
||||
MOVER_POS2,
|
||||
MOVER_1TO2,
|
||||
MOVER_2TO1
|
||||
} moverState_t;
|
||||
|
||||
#define SP_PODIUM_MODEL "models/mapobjects/podium/podium4.md3"
|
||||
|
||||
//============================================================================
|
||||
|
||||
typedef struct gentity_s gentity_t;
|
||||
typedef struct gclient_s gclient_t;
|
||||
|
||||
struct gentity_s {
|
||||
entityState_t s; // communicated by server to clients
|
||||
entityShared_t r; // shared by both the server system and game
|
||||
|
||||
// DO NOT MODIFY ANYTHING ABOVE THIS, THE SERVER
|
||||
// EXPECTS THE FIELDS IN THAT ORDER!
|
||||
//================================
|
||||
|
||||
struct gclient_s *client; // NULL if not a client
|
||||
|
||||
qboolean inuse;
|
||||
|
||||
char *classname; // set in QuakeEd
|
||||
int spawnflags; // set in QuakeEd
|
||||
|
||||
qboolean neverFree; // if true, FreeEntity will only unlink
|
||||
// bodyque uses this
|
||||
|
||||
int flags; // FL_* variables
|
||||
|
||||
char *model;
|
||||
char *model2;
|
||||
int freetime; // level.time when the object was freed
|
||||
|
||||
int eventTime; // events will be cleared EVENT_VALID_MSEC after set
|
||||
qboolean freeAfterEvent;
|
||||
qboolean unlinkAfterEvent;
|
||||
|
||||
qboolean physicsObject; // if true, it can be pushed by movers and fall off edges
|
||||
// all game items are physicsObjects,
|
||||
float physicsBounce; // 1.0 = continuous bounce, 0.0 = no bounce
|
||||
int clipmask; // brushes with this content value will be collided against
|
||||
// when moving. items and corpses do not collide against
|
||||
// players, for instance
|
||||
|
||||
// movers
|
||||
moverState_t moverState;
|
||||
int soundPos1;
|
||||
int sound1to2;
|
||||
int sound2to1;
|
||||
int soundPos2;
|
||||
int soundLoop;
|
||||
gentity_t *parent;
|
||||
gentity_t *nextTrain;
|
||||
gentity_t *prevTrain;
|
||||
vec3_t pos1, pos2;
|
||||
|
||||
char *message;
|
||||
|
||||
int timestamp; // body queue sinking, etc
|
||||
|
||||
float angle; // set in editor, -1 = up, -2 = down
|
||||
char *target;
|
||||
char *targetname;
|
||||
char *team;
|
||||
char *targetShaderName;
|
||||
char *targetShaderNewName;
|
||||
gentity_t *target_ent;
|
||||
|
||||
float speed;
|
||||
vec3_t movedir;
|
||||
|
||||
int nextthink;
|
||||
void (*think)(gentity_t *self);
|
||||
void (*reached)(gentity_t *self); // movers call this when hitting endpoint
|
||||
void (*blocked)(gentity_t *self, gentity_t *other);
|
||||
void (*touch)(gentity_t *self, gentity_t *other, trace_t *trace);
|
||||
void (*use)(gentity_t *self, gentity_t *other, gentity_t *activator);
|
||||
void (*pain)(gentity_t *self, gentity_t *attacker, int damage);
|
||||
void (*die)(gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod);
|
||||
|
||||
int pain_debounce_time;
|
||||
int fly_sound_debounce_time; // wind tunnel
|
||||
int last_move_time;
|
||||
|
||||
int health;
|
||||
|
||||
qboolean takedamage;
|
||||
|
||||
int damage;
|
||||
int splashDamage; // quad will increase this without increasing radius
|
||||
int splashRadius;
|
||||
int methodOfDeath;
|
||||
int splashMethodOfDeath;
|
||||
|
||||
int count;
|
||||
|
||||
gentity_t *chain;
|
||||
gentity_t *enemy;
|
||||
gentity_t *activator;
|
||||
gentity_t *teamchain; // next entity in team
|
||||
gentity_t *teammaster; // master of the team
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
int kamikazeTime;
|
||||
int kamikazeShockTime;
|
||||
#endif
|
||||
|
||||
int watertype;
|
||||
int waterlevel;
|
||||
|
||||
int noise_index;
|
||||
|
||||
// timing variables
|
||||
float wait;
|
||||
float random;
|
||||
|
||||
gitem_t *item; // for bonus items
|
||||
};
|
||||
|
||||
|
||||
typedef enum {
|
||||
CON_DISCONNECTED,
|
||||
CON_CONNECTING,
|
||||
CON_CONNECTED
|
||||
} clientConnected_t;
|
||||
|
||||
typedef enum {
|
||||
SPECTATOR_NOT,
|
||||
SPECTATOR_FREE,
|
||||
SPECTATOR_FOLLOW,
|
||||
SPECTATOR_SCOREBOARD
|
||||
} spectatorState_t;
|
||||
|
||||
typedef enum {
|
||||
TEAM_BEGIN, // Beginning a team game, spawn at base
|
||||
TEAM_ACTIVE // Now actively playing
|
||||
} playerTeamStateState_t;
|
||||
|
||||
typedef struct {
|
||||
playerTeamStateState_t state;
|
||||
|
||||
int location;
|
||||
|
||||
int captures;
|
||||
int basedefense;
|
||||
int carrierdefense;
|
||||
int flagrecovery;
|
||||
int fragcarrier;
|
||||
int assists;
|
||||
|
||||
float lasthurtcarrier;
|
||||
float lastreturnedflag;
|
||||
float flagsince;
|
||||
float lastfraggedcarrier;
|
||||
} playerTeamState_t;
|
||||
|
||||
// the auto following clients don't follow a specific client
|
||||
// number, but instead follow the first two active players
|
||||
#define FOLLOW_ACTIVE1 -1
|
||||
#define FOLLOW_ACTIVE2 -2
|
||||
|
||||
// client data that stays across multiple levels or tournament restarts
|
||||
// this is achieved by writing all the data to cvar strings at game shutdown
|
||||
// time and reading them back at connection time. Anything added here
|
||||
// MUST be dealt with in G_InitSessionData() / G_ReadSessionData() / G_WriteSessionData()
|
||||
typedef struct {
|
||||
team_t sessionTeam;
|
||||
int spectatorTime; // for determining next-in-line to play
|
||||
spectatorState_t spectatorState;
|
||||
int spectatorClient; // for chasecam and follow mode
|
||||
int wins, losses; // tournament stats
|
||||
qboolean teamLeader; // true when this client is a team leader
|
||||
} clientSession_t;
|
||||
|
||||
//
|
||||
#define MAX_NETNAME 36
|
||||
#define MAX_VOTE_COUNT 3
|
||||
|
||||
// client data that stays across multiple respawns, but is cleared
|
||||
// on each level change or team change at ClientBegin()
|
||||
typedef struct {
|
||||
clientConnected_t connected;
|
||||
usercmd_t cmd; // we would lose angles if not persistant
|
||||
qboolean localClient; // true if "ip" info key is "localhost"
|
||||
qboolean initialSpawn; // the first spawn should be at a cool location
|
||||
qboolean predictItemPickup; // based on cg_predictItems userinfo
|
||||
qboolean pmoveFixed; //
|
||||
char netname[MAX_NETNAME];
|
||||
int maxHealth; // for handicapping
|
||||
int enterTime; // level.time the client entered the game
|
||||
playerTeamState_t teamState; // status in teamplay games
|
||||
int voteCount; // to prevent people from constantly calling votes
|
||||
int teamVoteCount; // to prevent people from constantly calling votes
|
||||
qboolean teamInfo; // send team overlay updates?
|
||||
} clientPersistant_t;
|
||||
|
||||
|
||||
// this structure is cleared on each ClientSpawn(),
|
||||
// except for 'client->pers' and 'client->sess'
|
||||
struct gclient_s {
|
||||
// ps MUST be the first element, because the server expects it
|
||||
playerState_t ps; // communicated by server to clients
|
||||
|
||||
// the rest of the structure is private to game
|
||||
clientPersistant_t pers;
|
||||
clientSession_t sess;
|
||||
|
||||
qboolean readyToExit; // wishes to leave the intermission
|
||||
|
||||
qboolean noclip;
|
||||
|
||||
int lastCmdTime; // level.time of last usercmd_t, for EF_CONNECTION
|
||||
// we can't just use pers.lastCommand.time, because
|
||||
// of the g_sycronousclients case
|
||||
int buttons;
|
||||
int oldbuttons;
|
||||
int latched_buttons;
|
||||
|
||||
vec3_t oldOrigin;
|
||||
|
||||
// sum up damage over an entire frame, so
|
||||
// shotgun blasts give a single big kick
|
||||
int damage_armor; // damage absorbed by armor
|
||||
int damage_blood; // damage taken out of health
|
||||
int damage_knockback; // impact damage
|
||||
vec3_t damage_from; // origin for vector calculation
|
||||
qboolean damage_fromWorld; // if true, don't use the damage_from vector
|
||||
|
||||
int accurateCount; // for "impressive" reward sound
|
||||
|
||||
int accuracy_shots; // total number of shots
|
||||
int accuracy_hits; // total number of hits
|
||||
|
||||
//
|
||||
int lastkilled_client; // last client that this client killed
|
||||
int lasthurt_client; // last client that damaged this client
|
||||
int lasthurt_mod; // type of damage the client did
|
||||
|
||||
// timers
|
||||
int respawnTime; // can respawn when time > this, force after g_forcerespwan
|
||||
int inactivityTime; // kick players when time > this
|
||||
qboolean inactivityWarning; // qtrue if the five seoond warning has been given
|
||||
int rewardTime; // clear the EF_AWARD_IMPRESSIVE, etc when time > this
|
||||
|
||||
int airOutTime;
|
||||
|
||||
int lastKillTime; // for multiple kill rewards
|
||||
|
||||
qboolean fireHeld; // used for hook
|
||||
gentity_t *hook; // grapple hook if out
|
||||
|
||||
int switchTeamTime; // time the player switched teams
|
||||
|
||||
// timeResidual is used to handle events that happen every second
|
||||
// like health / armor countdowns and regeneration
|
||||
int timeResidual;
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
gentity_t *persistantPowerup;
|
||||
int portalID;
|
||||
int ammoTimes[WP_NUM_WEAPONS];
|
||||
int invulnerabilityTime;
|
||||
#endif
|
||||
|
||||
char *areabits;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// this structure is cleared as each map is entered
|
||||
//
|
||||
#define MAX_SPAWN_VARS 64
|
||||
#define MAX_SPAWN_VARS_CHARS 4096
|
||||
|
||||
typedef struct {
|
||||
struct gclient_s *clients; // [maxclients]
|
||||
|
||||
struct gentity_s *gentities;
|
||||
int gentitySize;
|
||||
int num_entities; // current number, <= MAX_GENTITIES
|
||||
|
||||
int warmupTime; // restart match at this time
|
||||
|
||||
fileHandle_t logFile;
|
||||
|
||||
// store latched cvars here that we want to get at often
|
||||
int maxclients;
|
||||
|
||||
int framenum;
|
||||
int time; // in msec
|
||||
int previousTime; // so movers can back up when blocked
|
||||
|
||||
int startTime; // level.time the map was started
|
||||
|
||||
int teamScores[TEAM_NUM_TEAMS];
|
||||
int lastTeamLocationTime; // last time of client team location update
|
||||
|
||||
qboolean newSession; // don't use any old session data, because
|
||||
// we changed gametype
|
||||
|
||||
qboolean restarted; // waiting for a map_restart to fire
|
||||
|
||||
int numConnectedClients;
|
||||
int numNonSpectatorClients; // includes connecting clients
|
||||
int numPlayingClients; // connected, non-spectators
|
||||
int sortedClients[MAX_CLIENTS]; // sorted by score
|
||||
int follow1, follow2; // clientNums for auto-follow spectators
|
||||
|
||||
int snd_fry; // sound index for standing in lava
|
||||
|
||||
int warmupModificationCount; // for detecting if g_warmup is changed
|
||||
|
||||
// voting state
|
||||
char voteString[MAX_STRING_CHARS];
|
||||
char voteDisplayString[MAX_STRING_CHARS];
|
||||
int voteTime; // level.time vote was called
|
||||
int voteExecuteTime; // time the vote is executed
|
||||
int voteYes;
|
||||
int voteNo;
|
||||
int numVotingClients; // set by CalculateRanks
|
||||
|
||||
// team voting state
|
||||
char teamVoteString[2][MAX_STRING_CHARS];
|
||||
int teamVoteTime[2]; // level.time vote was called
|
||||
int teamVoteYes[2];
|
||||
int teamVoteNo[2];
|
||||
int numteamVotingClients[2];// set by CalculateRanks
|
||||
|
||||
// spawn variables
|
||||
qboolean spawning; // the G_Spawn*() functions are valid
|
||||
int numSpawnVars;
|
||||
char *spawnVars[MAX_SPAWN_VARS][2]; // key / value pairs
|
||||
int numSpawnVarChars;
|
||||
char spawnVarChars[MAX_SPAWN_VARS_CHARS];
|
||||
|
||||
// intermission state
|
||||
int intermissionQueued; // intermission was qualified, but
|
||||
// wait INTERMISSION_DELAY_TIME before
|
||||
// actually going there so the last
|
||||
// frag can be watched. Disable future
|
||||
// kills during this delay
|
||||
int intermissiontime; // time the intermission was started
|
||||
char *changemap;
|
||||
qboolean readyToExit; // at least one client wants to exit
|
||||
int exitTime;
|
||||
vec3_t intermission_origin; // also used for spectator spawns
|
||||
vec3_t intermission_angle;
|
||||
|
||||
qboolean locationLinked; // target_locations get linked
|
||||
gentity_t *locationHead; // head of the location list
|
||||
int bodyQueIndex; // dead bodies
|
||||
gentity_t *bodyQue[BODY_QUEUE_SIZE];
|
||||
#ifdef MISSIONPACK
|
||||
int portalSequence;
|
||||
#endif
|
||||
} level_locals_t;
|
||||
|
||||
|
||||
//
|
||||
// g_spawn.c
|
||||
//
|
||||
qboolean G_SpawnString( const char *key, const char *defaultString, char **out );
|
||||
// spawn string returns a temporary reference, you must CopyString() if you want to keep it
|
||||
qboolean G_SpawnFloat( const char *key, const char *defaultString, float *out );
|
||||
qboolean G_SpawnInt( const char *key, const char *defaultString, int *out );
|
||||
qboolean G_SpawnVector( const char *key, const char *defaultString, float *out );
|
||||
void G_SpawnEntitiesFromString( void );
|
||||
char *G_NewString( const char *string );
|
||||
|
||||
//
|
||||
// g_cmds.c
|
||||
//
|
||||
void Cmd_Score_f (gentity_t *ent);
|
||||
void StopFollowing( gentity_t *ent );
|
||||
void BroadcastTeamChange( gclient_t *client, int oldTeam );
|
||||
void SetTeam( gentity_t *ent, char *s );
|
||||
void Cmd_FollowCycle_f( gentity_t *ent, int dir );
|
||||
|
||||
//
|
||||
// g_items.c
|
||||
//
|
||||
void G_CheckTeamItems( void );
|
||||
void G_RunItem( gentity_t *ent );
|
||||
void RespawnItem( gentity_t *ent );
|
||||
|
||||
void UseHoldableItem( gentity_t *ent );
|
||||
void PrecacheItem (gitem_t *it);
|
||||
gentity_t *Drop_Item( gentity_t *ent, gitem_t *item, float angle );
|
||||
gentity_t *LaunchItem( gitem_t *item, vec3_t origin, vec3_t velocity );
|
||||
void SetRespawn (gentity_t *ent, float delay);
|
||||
void G_SpawnItem (gentity_t *ent, gitem_t *item);
|
||||
void FinishSpawningItem( gentity_t *ent );
|
||||
void Think_Weapon (gentity_t *ent);
|
||||
int ArmorIndex (gentity_t *ent);
|
||||
void Add_Ammo (gentity_t *ent, int weapon, int count);
|
||||
void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace);
|
||||
|
||||
void ClearRegisteredItems( void );
|
||||
void RegisterItem( gitem_t *item );
|
||||
void SaveRegisteredItems( void );
|
||||
|
||||
//
|
||||
// g_utils.c
|
||||
//
|
||||
int G_ModelIndex( char *name );
|
||||
int G_SoundIndex( char *name );
|
||||
void G_TeamCommand( team_t team, char *cmd );
|
||||
void G_KillBox (gentity_t *ent);
|
||||
gentity_t *G_Find (gentity_t *from, int fieldofs, const char *match);
|
||||
gentity_t *G_PickTarget (char *targetname);
|
||||
void G_UseTargets (gentity_t *ent, gentity_t *activator);
|
||||
void G_SetMovedir ( vec3_t angles, vec3_t movedir);
|
||||
|
||||
void G_InitGentity( gentity_t *e );
|
||||
gentity_t *G_Spawn (void);
|
||||
gentity_t *G_TempEntity( vec3_t origin, int event );
|
||||
void G_Sound( gentity_t *ent, int channel, int soundIndex );
|
||||
void G_FreeEntity( gentity_t *e );
|
||||
qboolean G_EntitiesFree( void );
|
||||
|
||||
void G_TouchTriggers (gentity_t *ent);
|
||||
void G_TouchSolids (gentity_t *ent);
|
||||
|
||||
float *tv (float x, float y, float z);
|
||||
char *vtos( const vec3_t v );
|
||||
|
||||
float vectoyaw( const vec3_t vec );
|
||||
|
||||
void G_AddPredictableEvent( gentity_t *ent, int event, int eventParm );
|
||||
void G_AddEvent( gentity_t *ent, int event, int eventParm );
|
||||
void G_SetOrigin( gentity_t *ent, vec3_t origin );
|
||||
void AddRemap(const char *oldShader, const char *newShader, float timeOffset);
|
||||
const char *BuildShaderStateConfig();
|
||||
|
||||
//
|
||||
// g_combat.c
|
||||
//
|
||||
qboolean CanDamage (gentity_t *targ, vec3_t origin);
|
||||
void G_Damage (gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, vec3_t dir, vec3_t point, int damage, int dflags, int mod);
|
||||
qboolean G_RadiusDamage (vec3_t origin, gentity_t *attacker, float damage, float radius, gentity_t *ignore, int mod);
|
||||
int G_InvulnerabilityEffect( gentity_t *targ, vec3_t dir, vec3_t point, vec3_t impactpoint, vec3_t bouncedir );
|
||||
void body_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath );
|
||||
void TossClientItems( gentity_t *self );
|
||||
#ifdef MISSIONPACK
|
||||
void TossClientPersistantPowerups( gentity_t *self );
|
||||
#endif
|
||||
void TossClientCubes( gentity_t *self );
|
||||
|
||||
// damage flags
|
||||
#define DAMAGE_RADIUS 0x00000001 // damage was indirect
|
||||
#define DAMAGE_NO_ARMOR 0x00000002 // armour does not protect from this damage
|
||||
#define DAMAGE_NO_KNOCKBACK 0x00000004 // do not affect velocity, just view angles
|
||||
#define DAMAGE_NO_PROTECTION 0x00000008 // armor, shields, invulnerability, and godmode have no effect
|
||||
#ifdef MISSIONPACK
|
||||
#define DAMAGE_NO_TEAM_PROTECTION 0x00000010 // armor, shields, invulnerability, and godmode have no effect
|
||||
#endif
|
||||
|
||||
//
|
||||
// g_missile.c
|
||||
//
|
||||
void G_RunMissile( gentity_t *ent );
|
||||
|
||||
gentity_t *fire_blaster (gentity_t *self, vec3_t start, vec3_t aimdir);
|
||||
gentity_t *fire_plasma (gentity_t *self, vec3_t start, vec3_t aimdir);
|
||||
gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t aimdir);
|
||||
gentity_t *fire_rocket (gentity_t *self, vec3_t start, vec3_t dir);
|
||||
gentity_t *fire_bfg (gentity_t *self, vec3_t start, vec3_t dir);
|
||||
gentity_t *fire_grapple (gentity_t *self, vec3_t start, vec3_t dir);
|
||||
#ifdef MISSIONPACK
|
||||
gentity_t *fire_nail( gentity_t *self, vec3_t start, vec3_t forward, vec3_t right, vec3_t up );
|
||||
gentity_t *fire_prox( gentity_t *self, vec3_t start, vec3_t aimdir );
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// g_mover.c
|
||||
//
|
||||
void G_RunMover( gentity_t *ent );
|
||||
void Touch_DoorTrigger( gentity_t *ent, gentity_t *other, trace_t *trace );
|
||||
|
||||
//
|
||||
// g_trigger.c
|
||||
//
|
||||
void trigger_teleporter_touch (gentity_t *self, gentity_t *other, trace_t *trace );
|
||||
|
||||
|
||||
//
|
||||
// g_misc.c
|
||||
//
|
||||
void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles );
|
||||
#ifdef MISSIONPACK
|
||||
void DropPortalSource( gentity_t *ent );
|
||||
void DropPortalDestination( gentity_t *ent );
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// g_weapon.c
|
||||
//
|
||||
qboolean LogAccuracyHit( gentity_t *target, gentity_t *attacker );
|
||||
void CalcMuzzlePoint ( gentity_t *ent, vec3_t forward, vec3_t right, vec3_t up, vec3_t muzzlePoint );
|
||||
void SnapVectorTowards( vec3_t v, vec3_t to );
|
||||
qboolean CheckGauntletAttack( gentity_t *ent );
|
||||
void Weapon_HookFree (gentity_t *ent);
|
||||
void Weapon_HookThink (gentity_t *ent);
|
||||
|
||||
|
||||
//
|
||||
// g_client.c
|
||||
//
|
||||
team_t TeamCount( int ignoreClientNum, int team );
|
||||
int TeamLeader( int team );
|
||||
team_t PickTeam( int ignoreClientNum );
|
||||
void SetClientViewAngle( gentity_t *ent, vec3_t angle );
|
||||
gentity_t *SelectSpawnPoint ( vec3_t avoidPoint, vec3_t origin, vec3_t angles );
|
||||
void CopyToBodyQue( gentity_t *ent );
|
||||
void respawn (gentity_t *ent);
|
||||
void BeginIntermission (void);
|
||||
void InitClientPersistant (gclient_t *client);
|
||||
void InitClientResp (gclient_t *client);
|
||||
void InitBodyQue (void);
|
||||
void ClientSpawn( gentity_t *ent );
|
||||
void player_die (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod);
|
||||
void AddScore( gentity_t *ent, vec3_t origin, int score );
|
||||
void CalculateRanks( void );
|
||||
qboolean SpotWouldTelefrag( gentity_t *spot );
|
||||
|
||||
//
|
||||
// g_svcmds.c
|
||||
//
|
||||
qboolean ConsoleCommand( void );
|
||||
void G_ProcessIPBans(void);
|
||||
qboolean G_FilterPacket (char *from);
|
||||
|
||||
//
|
||||
// g_weapon.c
|
||||
//
|
||||
void FireWeapon( gentity_t *ent );
|
||||
#ifdef MISSIONPACK
|
||||
void G_StartKamikaze( gentity_t *ent );
|
||||
#endif
|
||||
|
||||
//
|
||||
// p_hud.c
|
||||
//
|
||||
void MoveClientToIntermission (gentity_t *client);
|
||||
void G_SetStats (gentity_t *ent);
|
||||
void DeathmatchScoreboardMessage (gentity_t *client);
|
||||
|
||||
//
|
||||
// g_cmds.c
|
||||
//
|
||||
|
||||
//
|
||||
// g_pweapon.c
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// g_main.c
|
||||
//
|
||||
void FindIntermissionPoint( void );
|
||||
void SetLeader(int team, int client);
|
||||
void CheckTeamLeader( int team );
|
||||
void G_RunThink (gentity_t *ent);
|
||||
void QDECL G_LogPrintf( const char *fmt, ... );
|
||||
void SendScoreboardMessageToAllClients( void );
|
||||
void QDECL G_Printf( const char *fmt, ... );
|
||||
void QDECL G_Error( const char *fmt, ... );
|
||||
|
||||
//
|
||||
// g_client.c
|
||||
//
|
||||
char *ClientConnect( int clientNum, qboolean firstTime, qboolean isBot );
|
||||
void ClientUserinfoChanged( int clientNum );
|
||||
void ClientDisconnect( int clientNum );
|
||||
void ClientBegin( int clientNum );
|
||||
void ClientCommand( int clientNum );
|
||||
|
||||
//
|
||||
// g_active.c
|
||||
//
|
||||
void ClientThink( int clientNum );
|
||||
void ClientEndFrame( gentity_t *ent );
|
||||
void G_RunClient( gentity_t *ent );
|
||||
|
||||
//
|
||||
// g_team.c
|
||||
//
|
||||
qboolean OnSameTeam( gentity_t *ent1, gentity_t *ent2 );
|
||||
void Team_CheckDroppedItem( gentity_t *dropped );
|
||||
qboolean CheckObeliskAttack( gentity_t *obelisk, gentity_t *attacker );
|
||||
|
||||
//
|
||||
// g_mem.c
|
||||
//
|
||||
void *G_Alloc( int size );
|
||||
void G_InitMemory( void );
|
||||
void Svcmd_GameMem_f( void );
|
||||
|
||||
//
|
||||
// g_session.c
|
||||
//
|
||||
void G_ReadSessionData( gclient_t *client );
|
||||
void G_InitSessionData( gclient_t *client, char *userinfo );
|
||||
|
||||
void G_InitWorldSession( void );
|
||||
void G_WriteSessionData( void );
|
||||
|
||||
//
|
||||
// g_arenas.c
|
||||
//
|
||||
void UpdateTournamentInfo( void );
|
||||
void SpawnModelsOnVictoryPads( void );
|
||||
void Svcmd_AbortPodium_f( void );
|
||||
|
||||
//
|
||||
// g_bot.c
|
||||
//
|
||||
void G_InitBots( qboolean restart );
|
||||
char *G_GetBotInfoByNumber( int num );
|
||||
char *G_GetBotInfoByName( const char *name );
|
||||
void G_CheckBotSpawn( void );
|
||||
void G_RemoveQueuedBotBegin( int clientNum );
|
||||
qboolean G_BotConnect( int clientNum, qboolean restart );
|
||||
void Svcmd_AddBot_f( void );
|
||||
void Svcmd_BotList_f( void );
|
||||
void BotInterbreedEndMatch( void );
|
||||
|
||||
// ai_main.c
|
||||
#define MAX_FILEPATH 144
|
||||
|
||||
//bot settings
|
||||
typedef struct bot_settings_s
|
||||
{
|
||||
char characterfile[MAX_FILEPATH];
|
||||
float skill;
|
||||
char team[MAX_FILEPATH];
|
||||
} bot_settings_t;
|
||||
|
||||
int BotAISetup( int restart );
|
||||
int BotAIShutdown( int restart );
|
||||
int BotAILoadMap( int restart );
|
||||
int BotAISetupClient(int client, struct bot_settings_s *settings, qboolean restart);
|
||||
int BotAIShutdownClient( int client, qboolean restart );
|
||||
int BotAIStartFrame( int time );
|
||||
void BotTestAAS(vec3_t origin);
|
||||
|
||||
#include "g_team.h" // teamplay specific stuff
|
||||
|
||||
|
||||
extern level_locals_t level;
|
||||
extern gentity_t g_entities[MAX_GENTITIES];
|
||||
|
||||
#define FOFS(x) ((int)&(((gentity_t *)0)->x))
|
||||
|
||||
extern vmCvar_t g_gametype;
|
||||
extern vmCvar_t g_dedicated;
|
||||
extern vmCvar_t g_cheats;
|
||||
extern vmCvar_t g_maxclients; // allow this many total, including spectators
|
||||
extern vmCvar_t g_maxGameClients; // allow this many active
|
||||
extern vmCvar_t g_restarted;
|
||||
|
||||
extern vmCvar_t g_dmflags;
|
||||
extern vmCvar_t g_fraglimit;
|
||||
extern vmCvar_t g_timelimit;
|
||||
extern vmCvar_t g_capturelimit;
|
||||
extern vmCvar_t g_friendlyFire;
|
||||
extern vmCvar_t g_password;
|
||||
extern vmCvar_t g_needpass;
|
||||
extern vmCvar_t g_gravity;
|
||||
extern vmCvar_t g_speed;
|
||||
extern vmCvar_t g_knockback;
|
||||
extern vmCvar_t g_quadfactor;
|
||||
extern vmCvar_t g_forcerespawn;
|
||||
extern vmCvar_t g_inactivity;
|
||||
extern vmCvar_t g_debugMove;
|
||||
extern vmCvar_t g_debugAlloc;
|
||||
extern vmCvar_t g_debugDamage;
|
||||
extern vmCvar_t g_weaponRespawn;
|
||||
extern vmCvar_t g_weaponTeamRespawn;
|
||||
extern vmCvar_t g_synchronousClients;
|
||||
extern vmCvar_t g_motd;
|
||||
extern vmCvar_t g_warmup;
|
||||
extern vmCvar_t g_doWarmup;
|
||||
extern vmCvar_t g_blood;
|
||||
extern vmCvar_t g_allowVote;
|
||||
extern vmCvar_t g_teamAutoJoin;
|
||||
extern vmCvar_t g_teamForceBalance;
|
||||
extern vmCvar_t g_banIPs;
|
||||
extern vmCvar_t g_filterBan;
|
||||
extern vmCvar_t g_obeliskHealth;
|
||||
extern vmCvar_t g_obeliskRegenPeriod;
|
||||
extern vmCvar_t g_obeliskRegenAmount;
|
||||
extern vmCvar_t g_obeliskRespawnDelay;
|
||||
extern vmCvar_t g_cubeTimeout;
|
||||
extern vmCvar_t g_redteam;
|
||||
extern vmCvar_t g_blueteam;
|
||||
extern vmCvar_t g_smoothClients;
|
||||
extern vmCvar_t pmove_fixed;
|
||||
extern vmCvar_t pmove_msec;
|
||||
extern vmCvar_t g_rankings;
|
||||
extern vmCvar_t g_enableDust;
|
||||
extern vmCvar_t g_enableBreath;
|
||||
extern vmCvar_t g_singlePlayer;
|
||||
extern vmCvar_t g_proxMineTimeout;
|
||||
|
||||
void trap_Printf( const char *fmt );
|
||||
void trap_Error( const char *fmt );
|
||||
int trap_Milliseconds( void );
|
||||
int trap_Argc( void );
|
||||
void trap_Argv( int n, char *buffer, int bufferLength );
|
||||
void trap_Args( char *buffer, int bufferLength );
|
||||
int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode );
|
||||
void trap_FS_Read( void *buffer, int len, fileHandle_t f );
|
||||
void trap_FS_Write( const void *buffer, int len, fileHandle_t f );
|
||||
void trap_FS_FCloseFile( fileHandle_t f );
|
||||
int trap_FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize );
|
||||
int trap_FS_Seek( fileHandle_t f, long offset, int origin ); // fsOrigin_t
|
||||
void trap_SendConsoleCommand( int exec_when, const char *text );
|
||||
void trap_Cvar_Register( vmCvar_t *cvar, const char *var_name, const char *value, int flags );
|
||||
void trap_Cvar_Update( vmCvar_t *cvar );
|
||||
void trap_Cvar_Set( const char *var_name, const char *value );
|
||||
int trap_Cvar_VariableIntegerValue( const char *var_name );
|
||||
float trap_Cvar_VariableValue( const char *var_name );
|
||||
void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
|
||||
void trap_LocateGameData( gentity_t *gEnts, int numGEntities, int sizeofGEntity_t, playerState_t *gameClients, int sizeofGameClient );
|
||||
void trap_DropClient( int clientNum, const char *reason );
|
||||
void trap_SendServerCommand( int clientNum, const char *text );
|
||||
void trap_SetConfigstring( int num, const char *string );
|
||||
void trap_GetConfigstring( int num, char *buffer, int bufferSize );
|
||||
void trap_GetUserinfo( int num, char *buffer, int bufferSize );
|
||||
void trap_SetUserinfo( int num, const char *buffer );
|
||||
void trap_GetServerinfo( char *buffer, int bufferSize );
|
||||
void trap_SetBrushModel( gentity_t *ent, const char *name );
|
||||
void trap_Trace( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask );
|
||||
int trap_PointContents( const vec3_t point, int passEntityNum );
|
||||
qboolean trap_InPVS( const vec3_t p1, const vec3_t p2 );
|
||||
qboolean trap_InPVSIgnorePortals( const vec3_t p1, const vec3_t p2 );
|
||||
void trap_AdjustAreaPortalState( gentity_t *ent, qboolean open );
|
||||
qboolean trap_AreasConnected( int area1, int area2 );
|
||||
void trap_LinkEntity( gentity_t *ent );
|
||||
void trap_UnlinkEntity( gentity_t *ent );
|
||||
int trap_EntitiesInBox( const vec3_t mins, const vec3_t maxs, int *entityList, int maxcount );
|
||||
qboolean trap_EntityContact( const vec3_t mins, const vec3_t maxs, const gentity_t *ent );
|
||||
int trap_BotAllocateClient( void );
|
||||
void trap_BotFreeClient( int clientNum );
|
||||
void trap_GetUsercmd( int clientNum, usercmd_t *cmd );
|
||||
qboolean trap_GetEntityToken( char *buffer, int bufferSize );
|
||||
|
||||
int trap_DebugPolygonCreate(int color, int numPoints, vec3_t *points);
|
||||
void trap_DebugPolygonDelete(int id);
|
||||
|
||||
int trap_BotLibSetup( void );
|
||||
int trap_BotLibShutdown( void );
|
||||
int trap_BotLibVarSet(char *var_name, char *value);
|
||||
int trap_BotLibVarGet(char *var_name, char *value, int size);
|
||||
int trap_BotLibDefine(char *string);
|
||||
int trap_BotLibStartFrame(float time);
|
||||
int trap_BotLibLoadMap(const char *mapname);
|
||||
int trap_BotLibUpdateEntity(int ent, void /* struct bot_updateentity_s */ *bue);
|
||||
int trap_BotLibTest(int parm0, char *parm1, vec3_t parm2, vec3_t parm3);
|
||||
|
||||
int trap_BotGetSnapshotEntity( int clientNum, int sequence );
|
||||
int trap_BotGetServerCommand(int clientNum, char *message, int size);
|
||||
void trap_BotUserCommand(int client, usercmd_t *ucmd);
|
||||
|
||||
int trap_AAS_BBoxAreas(vec3_t absmins, vec3_t absmaxs, int *areas, int maxareas);
|
||||
int trap_AAS_AreaInfo( int areanum, void /* struct aas_areainfo_s */ *info );
|
||||
void trap_AAS_EntityInfo(int entnum, void /* struct aas_entityinfo_s */ *info);
|
||||
|
||||
int trap_AAS_Initialized(void);
|
||||
void trap_AAS_PresenceTypeBoundingBox(int presencetype, vec3_t mins, vec3_t maxs);
|
||||
float trap_AAS_Time(void);
|
||||
|
||||
int trap_AAS_PointAreaNum(vec3_t point);
|
||||
int trap_AAS_PointReachabilityAreaIndex(vec3_t point);
|
||||
int trap_AAS_TraceAreas(vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas);
|
||||
|
||||
int trap_AAS_PointContents(vec3_t point);
|
||||
int trap_AAS_NextBSPEntity(int ent);
|
||||
int trap_AAS_ValueForBSPEpairKey(int ent, char *key, char *value, int size);
|
||||
int trap_AAS_VectorForBSPEpairKey(int ent, char *key, vec3_t v);
|
||||
int trap_AAS_FloatForBSPEpairKey(int ent, char *key, float *value);
|
||||
int trap_AAS_IntForBSPEpairKey(int ent, char *key, int *value);
|
||||
|
||||
int trap_AAS_AreaReachability(int areanum);
|
||||
|
||||
int trap_AAS_AreaTravelTimeToGoalArea(int areanum, vec3_t origin, int goalareanum, int travelflags);
|
||||
int trap_AAS_EnableRoutingArea( int areanum, int enable );
|
||||
int trap_AAS_PredictRoute(void /*struct aas_predictroute_s*/ *route, int areanum, vec3_t origin,
|
||||
int goalareanum, int travelflags, int maxareas, int maxtime,
|
||||
int stopevent, int stopcontents, int stoptfl, int stopareanum);
|
||||
|
||||
int trap_AAS_AlternativeRouteGoals(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags,
|
||||
void /*struct aas_altroutegoal_s*/ *altroutegoals, int maxaltroutegoals,
|
||||
int type);
|
||||
int trap_AAS_Swimming(vec3_t origin);
|
||||
int trap_AAS_PredictClientMovement(void /* aas_clientmove_s */ *move, int entnum, vec3_t origin, int presencetype, int onground, vec3_t velocity, vec3_t cmdmove, int cmdframes, int maxframes, float frametime, int stopevent, int stopareanum, int visualize);
|
||||
|
||||
|
||||
void trap_EA_Say(int client, char *str);
|
||||
void trap_EA_SayTeam(int client, char *str);
|
||||
void trap_EA_Command(int client, char *command);
|
||||
|
||||
void trap_EA_Action(int client, int action);
|
||||
void trap_EA_Gesture(int client);
|
||||
void trap_EA_Talk(int client);
|
||||
void trap_EA_Attack(int client);
|
||||
void trap_EA_Use(int client);
|
||||
void trap_EA_Respawn(int client);
|
||||
void trap_EA_Crouch(int client);
|
||||
void trap_EA_MoveUp(int client);
|
||||
void trap_EA_MoveDown(int client);
|
||||
void trap_EA_MoveForward(int client);
|
||||
void trap_EA_MoveBack(int client);
|
||||
void trap_EA_MoveLeft(int client);
|
||||
void trap_EA_MoveRight(int client);
|
||||
void trap_EA_SelectWeapon(int client, int weapon);
|
||||
void trap_EA_Jump(int client);
|
||||
void trap_EA_DelayedJump(int client);
|
||||
void trap_EA_Move(int client, vec3_t dir, float speed);
|
||||
void trap_EA_View(int client, vec3_t viewangles);
|
||||
|
||||
void trap_EA_EndRegular(int client, float thinktime);
|
||||
void trap_EA_GetInput(int client, float thinktime, void /* struct bot_input_s */ *input);
|
||||
void trap_EA_ResetInput(int client);
|
||||
|
||||
|
||||
int trap_BotLoadCharacter(char *charfile, float skill);
|
||||
void trap_BotFreeCharacter(int character);
|
||||
float trap_Characteristic_Float(int character, int index);
|
||||
float trap_Characteristic_BFloat(int character, int index, float min, float max);
|
||||
int trap_Characteristic_Integer(int character, int index);
|
||||
int trap_Characteristic_BInteger(int character, int index, int min, int max);
|
||||
void trap_Characteristic_String(int character, int index, char *buf, int size);
|
||||
|
||||
int trap_BotAllocChatState(void);
|
||||
void trap_BotFreeChatState(int handle);
|
||||
void trap_BotQueueConsoleMessage(int chatstate, int type, char *message);
|
||||
void trap_BotRemoveConsoleMessage(int chatstate, int handle);
|
||||
int trap_BotNextConsoleMessage(int chatstate, void /* struct bot_consolemessage_s */ *cm);
|
||||
int trap_BotNumConsoleMessages(int chatstate);
|
||||
void trap_BotInitialChat(int chatstate, char *type, int mcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7 );
|
||||
int trap_BotNumInitialChats(int chatstate, char *type);
|
||||
int trap_BotReplyChat(int chatstate, char *message, int mcontext, int vcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7 );
|
||||
int trap_BotChatLength(int chatstate);
|
||||
void trap_BotEnterChat(int chatstate, int client, int sendto);
|
||||
void trap_BotGetChatMessage(int chatstate, char *buf, int size);
|
||||
int trap_StringContains(char *str1, char *str2, int casesensitive);
|
||||
int trap_BotFindMatch(char *str, void /* struct bot_match_s */ *match, unsigned long int context);
|
||||
void trap_BotMatchVariable(void /* struct bot_match_s */ *match, int variable, char *buf, int size);
|
||||
void trap_UnifyWhiteSpaces(char *string);
|
||||
void trap_BotReplaceSynonyms(char *string, unsigned long int context);
|
||||
int trap_BotLoadChatFile(int chatstate, char *chatfile, char *chatname);
|
||||
void trap_BotSetChatGender(int chatstate, int gender);
|
||||
void trap_BotSetChatName(int chatstate, char *name, int client);
|
||||
void trap_BotResetGoalState(int goalstate);
|
||||
void trap_BotRemoveFromAvoidGoals(int goalstate, int number);
|
||||
void trap_BotResetAvoidGoals(int goalstate);
|
||||
void trap_BotPushGoal(int goalstate, void /* struct bot_goal_s */ *goal);
|
||||
void trap_BotPopGoal(int goalstate);
|
||||
void trap_BotEmptyGoalStack(int goalstate);
|
||||
void trap_BotDumpAvoidGoals(int goalstate);
|
||||
void trap_BotDumpGoalStack(int goalstate);
|
||||
void trap_BotGoalName(int number, char *name, int size);
|
||||
int trap_BotGetTopGoal(int goalstate, void /* struct bot_goal_s */ *goal);
|
||||
int trap_BotGetSecondGoal(int goalstate, void /* struct bot_goal_s */ *goal);
|
||||
int trap_BotChooseLTGItem(int goalstate, vec3_t origin, int *inventory, int travelflags);
|
||||
int trap_BotChooseNBGItem(int goalstate, vec3_t origin, int *inventory, int travelflags, void /* struct bot_goal_s */ *ltg, float maxtime);
|
||||
int trap_BotTouchingGoal(vec3_t origin, void /* struct bot_goal_s */ *goal);
|
||||
int trap_BotItemGoalInVisButNotVisible(int viewer, vec3_t eye, vec3_t viewangles, void /* struct bot_goal_s */ *goal);
|
||||
int trap_BotGetNextCampSpotGoal(int num, void /* struct bot_goal_s */ *goal);
|
||||
int trap_BotGetMapLocationGoal(char *name, void /* struct bot_goal_s */ *goal);
|
||||
int trap_BotGetLevelItemGoal(int index, char *classname, void /* struct bot_goal_s */ *goal);
|
||||
float trap_BotAvoidGoalTime(int goalstate, int number);
|
||||
void trap_BotSetAvoidGoalTime(int goalstate, int number, float avoidtime);
|
||||
void trap_BotInitLevelItems(void);
|
||||
void trap_BotUpdateEntityItems(void);
|
||||
int trap_BotLoadItemWeights(int goalstate, char *filename);
|
||||
void trap_BotFreeItemWeights(int goalstate);
|
||||
void trap_BotInterbreedGoalFuzzyLogic(int parent1, int parent2, int child);
|
||||
void trap_BotSaveGoalFuzzyLogic(int goalstate, char *filename);
|
||||
void trap_BotMutateGoalFuzzyLogic(int goalstate, float range);
|
||||
int trap_BotAllocGoalState(int state);
|
||||
void trap_BotFreeGoalState(int handle);
|
||||
|
||||
void trap_BotResetMoveState(int movestate);
|
||||
void trap_BotMoveToGoal(void /* struct bot_moveresult_s */ *result, int movestate, void /* struct bot_goal_s */ *goal, int travelflags);
|
||||
int trap_BotMoveInDirection(int movestate, vec3_t dir, float speed, int type);
|
||||
void trap_BotResetAvoidReach(int movestate);
|
||||
void trap_BotResetLastAvoidReach(int movestate);
|
||||
int trap_BotReachabilityArea(vec3_t origin, int testground);
|
||||
int trap_BotMovementViewTarget(int movestate, void /* struct bot_goal_s */ *goal, int travelflags, float lookahead, vec3_t target);
|
||||
int trap_BotPredictVisiblePosition(vec3_t origin, int areanum, void /* struct bot_goal_s */ *goal, int travelflags, vec3_t target);
|
||||
int trap_BotAllocMoveState(void);
|
||||
void trap_BotFreeMoveState(int handle);
|
||||
void trap_BotInitMoveState(int handle, void /* struct bot_initmove_s */ *initmove);
|
||||
void trap_BotAddAvoidSpot(int movestate, vec3_t origin, float radius, int type);
|
||||
|
||||
int trap_BotChooseBestFightWeapon(int weaponstate, int *inventory);
|
||||
void trap_BotGetWeaponInfo(int weaponstate, int weapon, void /* struct weaponinfo_s */ *weaponinfo);
|
||||
int trap_BotLoadWeaponWeights(int weaponstate, char *filename);
|
||||
int trap_BotAllocWeaponState(void);
|
||||
void trap_BotFreeWeaponState(int weaponstate);
|
||||
void trap_BotResetWeaponState(int weaponstate);
|
||||
|
||||
int trap_GeneticParentsAndChildSelection(int numranks, float *ranks, int *parent1, int *parent2, int *child);
|
||||
|
||||
void trap_SnapVector( float *v );
|
||||
|
||||
+1832
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
//
|
||||
// g_mem.c
|
||||
//
|
||||
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
|
||||
#define POOLSIZE (256 * 1024)
|
||||
|
||||
static char memoryPool[POOLSIZE];
|
||||
static int allocPoint;
|
||||
|
||||
void *G_Alloc( int size ) {
|
||||
char *p;
|
||||
|
||||
if ( g_debugAlloc.integer ) {
|
||||
G_Printf( "G_Alloc of %i bytes (%i left)\n", size, POOLSIZE - allocPoint - ( ( size + 31 ) & ~31 ) );
|
||||
}
|
||||
|
||||
if ( allocPoint + size > POOLSIZE ) {
|
||||
G_Error( "G_Alloc: failed on allocation of %i bytes\n", size ); // bk010103 - was %u, but is signed
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = &memoryPool[allocPoint];
|
||||
|
||||
allocPoint += ( size + 31 ) & ~31;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void G_InitMemory( void ) {
|
||||
allocPoint = 0;
|
||||
}
|
||||
|
||||
void Svcmd_GameMem_f( void ) {
|
||||
G_Printf( "Game memory status: %i out of %i bytes allocated\n", allocPoint, POOLSIZE );
|
||||
}
|
||||
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
// g_misc.c
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
|
||||
/*QUAKED func_group (0 0 0) ?
|
||||
Used to group brushes together just for editor convenience. They are turned into normal brushes by the utilities.
|
||||
*/
|
||||
|
||||
|
||||
/*QUAKED info_camp (0 0.5 0) (-4 -4 -4) (4 4 4)
|
||||
Used as a positional target for calculations in the utilities (spotlights, etc), but removed during gameplay.
|
||||
*/
|
||||
void SP_info_camp( gentity_t *self ) {
|
||||
G_SetOrigin( self, self->s.origin );
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4)
|
||||
Used as a positional target for calculations in the utilities (spotlights, etc), but removed during gameplay.
|
||||
*/
|
||||
void SP_info_null( gentity_t *self ) {
|
||||
G_FreeEntity( self );
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4)
|
||||
Used as a positional target for in-game calculation, like jumppad targets.
|
||||
target_position does the same thing
|
||||
*/
|
||||
void SP_info_notnull( gentity_t *self ){
|
||||
G_SetOrigin( self, self->s.origin );
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) linear
|
||||
Non-displayed light.
|
||||
"light" overrides the default 300 intensity.
|
||||
Linear checbox gives linear falloff instead of inverse square
|
||||
Lights pointed at a target will be spotlights.
|
||||
"radius" overrides the default 64 unit radius of a spotlight at the target point.
|
||||
*/
|
||||
void SP_light( gentity_t *self ) {
|
||||
G_FreeEntity( self );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================================================================================
|
||||
|
||||
TELEPORTERS
|
||||
|
||||
=================================================================================
|
||||
*/
|
||||
|
||||
void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles ) {
|
||||
gentity_t *tent;
|
||||
|
||||
// use temp events at source and destination to prevent the effect
|
||||
// from getting dropped by a second player event
|
||||
if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
|
||||
tent = G_TempEntity( player->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
|
||||
tent->s.clientNum = player->s.clientNum;
|
||||
|
||||
tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN );
|
||||
tent->s.clientNum = player->s.clientNum;
|
||||
}
|
||||
|
||||
// unlink to make sure it can't possibly interfere with G_KillBox
|
||||
trap_UnlinkEntity (player);
|
||||
|
||||
VectorCopy ( origin, player->client->ps.origin );
|
||||
player->client->ps.origin[2] += 1;
|
||||
|
||||
// spit the player out
|
||||
AngleVectors( angles, player->client->ps.velocity, NULL, NULL );
|
||||
VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity );
|
||||
player->client->ps.pm_time = 160; // hold time
|
||||
player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
|
||||
|
||||
// toggle the teleport bit so the client knows to not lerp
|
||||
player->client->ps.eFlags ^= EF_TELEPORT_BIT;
|
||||
|
||||
// set angles
|
||||
SetClientViewAngle( player, angles );
|
||||
|
||||
// kill anything at the destination
|
||||
if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
|
||||
G_KillBox (player);
|
||||
}
|
||||
|
||||
// save results of pmove
|
||||
BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue );
|
||||
|
||||
// use the precise origin for linking
|
||||
VectorCopy( player->client->ps.origin, player->r.currentOrigin );
|
||||
|
||||
if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
|
||||
trap_LinkEntity (player);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED misc_teleporter_dest (1 0 0) (-32 -32 -24) (32 32 -16)
|
||||
Point teleporters at these.
|
||||
Now that we don't have teleport destination pads, this is just
|
||||
an info_notnull
|
||||
*/
|
||||
void SP_misc_teleporter_dest( gentity_t *ent ) {
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
|
||||
/*QUAKED misc_model (1 0 0) (-16 -16 -16) (16 16 16)
|
||||
"model" arbitrary .md3 file to display
|
||||
*/
|
||||
void SP_misc_model( gentity_t *ent ) {
|
||||
|
||||
#if 0
|
||||
ent->s.modelindex = G_ModelIndex( ent->model );
|
||||
VectorSet (ent->mins, -16, -16, -16);
|
||||
VectorSet (ent->maxs, 16, 16, 16);
|
||||
trap_LinkEntity (ent);
|
||||
|
||||
G_SetOrigin( ent, ent->s.origin );
|
||||
VectorCopy( ent->s.angles, ent->s.apos.trBase );
|
||||
#else
|
||||
G_FreeEntity( ent );
|
||||
#endif
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
|
||||
void locateCamera( gentity_t *ent ) {
|
||||
vec3_t dir;
|
||||
gentity_t *target;
|
||||
gentity_t *owner;
|
||||
|
||||
owner = G_PickTarget( ent->target );
|
||||
if ( !owner ) {
|
||||
G_Printf( "Couldn't find target for misc_partal_surface\n" );
|
||||
G_FreeEntity( ent );
|
||||
return;
|
||||
}
|
||||
ent->r.ownerNum = owner->s.number;
|
||||
|
||||
// frame holds the rotate speed
|
||||
if ( owner->spawnflags & 1 ) {
|
||||
ent->s.frame = 25;
|
||||
} else if ( owner->spawnflags & 2 ) {
|
||||
ent->s.frame = 75;
|
||||
}
|
||||
|
||||
// swing camera ?
|
||||
if ( owner->spawnflags & 4 ) {
|
||||
// set to 0 for no rotation at all
|
||||
ent->s.powerups = 0;
|
||||
}
|
||||
else {
|
||||
ent->s.powerups = 1;
|
||||
}
|
||||
|
||||
// clientNum holds the rotate offset
|
||||
ent->s.clientNum = owner->s.clientNum;
|
||||
|
||||
VectorCopy( owner->s.origin, ent->s.origin2 );
|
||||
|
||||
// see if the portal_camera has a target
|
||||
target = G_PickTarget( owner->target );
|
||||
if ( target ) {
|
||||
VectorSubtract( target->s.origin, owner->s.origin, dir );
|
||||
VectorNormalize( dir );
|
||||
} else {
|
||||
G_SetMovedir( owner->s.angles, dir );
|
||||
}
|
||||
|
||||
ent->s.eventParm = DirToByte( dir );
|
||||
}
|
||||
|
||||
/*QUAKED misc_portal_surface (0 0 1) (-8 -8 -8) (8 8 8)
|
||||
The portal surface nearest this entity will show a view from the targeted misc_portal_camera, or a mirror view if untargeted.
|
||||
This must be within 64 world units of the surface!
|
||||
*/
|
||||
void SP_misc_portal_surface(gentity_t *ent) {
|
||||
VectorClear( ent->r.mins );
|
||||
VectorClear( ent->r.maxs );
|
||||
trap_LinkEntity (ent);
|
||||
|
||||
ent->r.svFlags = SVF_PORTAL;
|
||||
ent->s.eType = ET_PORTAL;
|
||||
|
||||
if ( !ent->target ) {
|
||||
VectorCopy( ent->s.origin, ent->s.origin2 );
|
||||
} else {
|
||||
ent->think = locateCamera;
|
||||
ent->nextthink = level.time + 100;
|
||||
}
|
||||
}
|
||||
|
||||
/*QUAKED misc_portal_camera (0 0 1) (-8 -8 -8) (8 8 8) slowrotate fastrotate noswing
|
||||
The target for a misc_portal_director. You can set either angles or target another entity to determine the direction of view.
|
||||
"roll" an angle modifier to orient the camera around the target vector;
|
||||
*/
|
||||
void SP_misc_portal_camera(gentity_t *ent) {
|
||||
float roll;
|
||||
|
||||
VectorClear( ent->r.mins );
|
||||
VectorClear( ent->r.maxs );
|
||||
trap_LinkEntity (ent);
|
||||
|
||||
G_SpawnFloat( "roll", "0", &roll );
|
||||
|
||||
ent->s.clientNum = roll/360.0 * 256;
|
||||
}
|
||||
|
||||
/*
|
||||
======================================================================
|
||||
|
||||
SHOOTERS
|
||||
|
||||
======================================================================
|
||||
*/
|
||||
|
||||
void Use_Shooter( gentity_t *ent, gentity_t *other, gentity_t *activator ) {
|
||||
vec3_t dir;
|
||||
float deg;
|
||||
vec3_t up, right;
|
||||
|
||||
// see if we have a target
|
||||
if ( ent->enemy ) {
|
||||
VectorSubtract( ent->enemy->r.currentOrigin, ent->s.origin, dir );
|
||||
VectorNormalize( dir );
|
||||
} else {
|
||||
VectorCopy( ent->movedir, dir );
|
||||
}
|
||||
|
||||
// randomize a bit
|
||||
PerpendicularVector( up, dir );
|
||||
CrossProduct( up, dir, right );
|
||||
|
||||
deg = crandom() * ent->random;
|
||||
VectorMA( dir, deg, up, dir );
|
||||
|
||||
deg = crandom() * ent->random;
|
||||
VectorMA( dir, deg, right, dir );
|
||||
|
||||
VectorNormalize( dir );
|
||||
|
||||
switch ( ent->s.weapon ) {
|
||||
case WP_GRENADE_LAUNCHER:
|
||||
fire_grenade( ent, ent->s.origin, dir );
|
||||
break;
|
||||
case WP_ROCKET_LAUNCHER:
|
||||
fire_rocket( ent, ent->s.origin, dir );
|
||||
break;
|
||||
case WP_PLASMAGUN:
|
||||
fire_plasma( ent, ent->s.origin, dir );
|
||||
break;
|
||||
}
|
||||
|
||||
G_AddEvent( ent, EV_FIRE_WEAPON, 0 );
|
||||
}
|
||||
|
||||
|
||||
static void InitShooter_Finish( gentity_t *ent ) {
|
||||
ent->enemy = G_PickTarget( ent->target );
|
||||
ent->think = 0;
|
||||
ent->nextthink = 0;
|
||||
}
|
||||
|
||||
void InitShooter( gentity_t *ent, int weapon ) {
|
||||
ent->use = Use_Shooter;
|
||||
ent->s.weapon = weapon;
|
||||
|
||||
RegisterItem( BG_FindItemForWeapon( weapon ) );
|
||||
|
||||
G_SetMovedir( ent->s.angles, ent->movedir );
|
||||
|
||||
if ( !ent->random ) {
|
||||
ent->random = 1.0;
|
||||
}
|
||||
ent->random = sin( M_PI * ent->random / 180 );
|
||||
// target might be a moving object, so we can't set movedir for it
|
||||
if ( ent->target ) {
|
||||
ent->think = InitShooter_Finish;
|
||||
ent->nextthink = level.time + 500;
|
||||
}
|
||||
trap_LinkEntity( ent );
|
||||
}
|
||||
|
||||
/*QUAKED shooter_rocket (1 0 0) (-16 -16 -16) (16 16 16)
|
||||
Fires at either the target or the current direction.
|
||||
"random" the number of degrees of deviance from the taget. (1.0 default)
|
||||
*/
|
||||
void SP_shooter_rocket( gentity_t *ent ) {
|
||||
InitShooter( ent, WP_ROCKET_LAUNCHER );
|
||||
}
|
||||
|
||||
/*QUAKED shooter_plasma (1 0 0) (-16 -16 -16) (16 16 16)
|
||||
Fires at either the target or the current direction.
|
||||
"random" is the number of degrees of deviance from the taget. (1.0 default)
|
||||
*/
|
||||
void SP_shooter_plasma( gentity_t *ent ) {
|
||||
InitShooter( ent, WP_PLASMAGUN);
|
||||
}
|
||||
|
||||
/*QUAKED shooter_grenade (1 0 0) (-16 -16 -16) (16 16 16)
|
||||
Fires at either the target or the current direction.
|
||||
"random" is the number of degrees of deviance from the taget. (1.0 default)
|
||||
*/
|
||||
void SP_shooter_grenade( gentity_t *ent ) {
|
||||
InitShooter( ent, WP_GRENADE_LAUNCHER);
|
||||
}
|
||||
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
static void PortalDie (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod) {
|
||||
G_FreeEntity( self );
|
||||
//FIXME do something more interesting
|
||||
}
|
||||
|
||||
|
||||
void DropPortalDestination( gentity_t *player ) {
|
||||
gentity_t *ent;
|
||||
vec3_t snapped;
|
||||
|
||||
// create the portal destination
|
||||
ent = G_Spawn();
|
||||
ent->s.modelindex = G_ModelIndex( "models/powerups/teleporter/tele_exit.md3" );
|
||||
|
||||
VectorCopy( player->s.pos.trBase, snapped );
|
||||
SnapVector( snapped );
|
||||
G_SetOrigin( ent, snapped );
|
||||
VectorCopy( player->r.mins, ent->r.mins );
|
||||
VectorCopy( player->r.maxs, ent->r.maxs );
|
||||
|
||||
ent->classname = "hi_portal destination";
|
||||
ent->s.pos.trType = TR_STATIONARY;
|
||||
|
||||
ent->r.contents = CONTENTS_CORPSE;
|
||||
ent->takedamage = qtrue;
|
||||
ent->health = 200;
|
||||
ent->die = PortalDie;
|
||||
|
||||
VectorCopy( player->s.apos.trBase, ent->s.angles );
|
||||
|
||||
ent->think = G_FreeEntity;
|
||||
ent->nextthink = level.time + 2 * 60 * 1000;
|
||||
|
||||
trap_LinkEntity( ent );
|
||||
|
||||
player->client->portalID = ++level.portalSequence;
|
||||
ent->count = player->client->portalID;
|
||||
|
||||
// give the item back so they can drop the source now
|
||||
player->client->ps.stats[STAT_HOLDABLE_ITEM] = BG_FindItem( "Portal" ) - bg_itemlist;
|
||||
}
|
||||
|
||||
|
||||
static void PortalTouch( gentity_t *self, gentity_t *other, trace_t *trace) {
|
||||
gentity_t *destination;
|
||||
|
||||
// see if we will even let other try to use it
|
||||
if( other->health <= 0 ) {
|
||||
return;
|
||||
}
|
||||
if( !other->client ) {
|
||||
return;
|
||||
}
|
||||
// if( other->client->ps.persistant[PERS_TEAM] != self->spawnflags ) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
if ( other->client->ps.powerups[PW_NEUTRALFLAG] ) { // only happens in One Flag CTF
|
||||
Drop_Item( other, BG_FindItemForPowerup( PW_NEUTRALFLAG ), 0 );
|
||||
other->client->ps.powerups[PW_NEUTRALFLAG] = 0;
|
||||
}
|
||||
else if ( other->client->ps.powerups[PW_REDFLAG] ) { // only happens in standard CTF
|
||||
Drop_Item( other, BG_FindItemForPowerup( PW_REDFLAG ), 0 );
|
||||
other->client->ps.powerups[PW_REDFLAG] = 0;
|
||||
}
|
||||
else if ( other->client->ps.powerups[PW_BLUEFLAG] ) { // only happens in standard CTF
|
||||
Drop_Item( other, BG_FindItemForPowerup( PW_BLUEFLAG ), 0 );
|
||||
other->client->ps.powerups[PW_BLUEFLAG] = 0;
|
||||
}
|
||||
|
||||
// find the destination
|
||||
destination = NULL;
|
||||
while( (destination = G_Find(destination, FOFS(classname), "hi_portal destination")) != NULL ) {
|
||||
if( destination->count == self->count ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if there is not one, die!
|
||||
if( !destination ) {
|
||||
if( self->pos1[0] || self->pos1[1] || self->pos1[2] ) {
|
||||
TeleportPlayer( other, self->pos1, self->s.angles );
|
||||
}
|
||||
G_Damage( other, other, other, NULL, NULL, 100000, DAMAGE_NO_PROTECTION, MOD_TELEFRAG );
|
||||
return;
|
||||
}
|
||||
|
||||
TeleportPlayer( other, destination->s.pos.trBase, destination->s.angles );
|
||||
}
|
||||
|
||||
|
||||
static void PortalEnable( gentity_t *self ) {
|
||||
self->touch = PortalTouch;
|
||||
self->think = G_FreeEntity;
|
||||
self->nextthink = level.time + 2 * 60 * 1000;
|
||||
}
|
||||
|
||||
|
||||
void DropPortalSource( gentity_t *player ) {
|
||||
gentity_t *ent;
|
||||
gentity_t *destination;
|
||||
vec3_t snapped;
|
||||
|
||||
// create the portal source
|
||||
ent = G_Spawn();
|
||||
ent->s.modelindex = G_ModelIndex( "models/powerups/teleporter/tele_enter.md3" );
|
||||
|
||||
VectorCopy( player->s.pos.trBase, snapped );
|
||||
SnapVector( snapped );
|
||||
G_SetOrigin( ent, snapped );
|
||||
VectorCopy( player->r.mins, ent->r.mins );
|
||||
VectorCopy( player->r.maxs, ent->r.maxs );
|
||||
|
||||
ent->classname = "hi_portal source";
|
||||
ent->s.pos.trType = TR_STATIONARY;
|
||||
|
||||
ent->r.contents = CONTENTS_CORPSE | CONTENTS_TRIGGER;
|
||||
ent->takedamage = qtrue;
|
||||
ent->health = 200;
|
||||
ent->die = PortalDie;
|
||||
|
||||
trap_LinkEntity( ent );
|
||||
|
||||
ent->count = player->client->portalID;
|
||||
player->client->portalID = 0;
|
||||
|
||||
// ent->spawnflags = player->client->ps.persistant[PERS_TEAM];
|
||||
|
||||
ent->nextthink = level.time + 1000;
|
||||
ent->think = PortalEnable;
|
||||
|
||||
// find the destination
|
||||
destination = NULL;
|
||||
while( (destination = G_Find(destination, FOFS(classname), "hi_portal destination")) != NULL ) {
|
||||
if( destination->count == ent->count ) {
|
||||
VectorCopy( destination->s.pos.trBase, ent->pos1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,808 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
#include "g_local.h"
|
||||
|
||||
#define MISSILE_PRESTEP_TIME 50
|
||||
|
||||
/*
|
||||
================
|
||||
G_BounceMissile
|
||||
|
||||
================
|
||||
*/
|
||||
void G_BounceMissile( gentity_t *ent, trace_t *trace ) {
|
||||
vec3_t velocity;
|
||||
float dot;
|
||||
int hitTime;
|
||||
|
||||
// reflect the velocity on the trace plane
|
||||
hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
|
||||
BG_EvaluateTrajectoryDelta( &ent->s.pos, hitTime, velocity );
|
||||
dot = DotProduct( velocity, trace->plane.normal );
|
||||
VectorMA( velocity, -2*dot, trace->plane.normal, ent->s.pos.trDelta );
|
||||
|
||||
if ( ent->s.eFlags & EF_BOUNCE_HALF ) {
|
||||
VectorScale( ent->s.pos.trDelta, 0.65, ent->s.pos.trDelta );
|
||||
// check for stop
|
||||
if ( trace->plane.normal[2] > 0.2 && VectorLength( ent->s.pos.trDelta ) < 40 ) {
|
||||
G_SetOrigin( ent, trace->endpos );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
VectorAdd( ent->r.currentOrigin, trace->plane.normal, ent->r.currentOrigin);
|
||||
VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase );
|
||||
ent->s.pos.trTime = level.time;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
G_ExplodeMissile
|
||||
|
||||
Explode a missile without an impact
|
||||
================
|
||||
*/
|
||||
void G_ExplodeMissile( gentity_t *ent ) {
|
||||
vec3_t dir;
|
||||
vec3_t origin;
|
||||
|
||||
BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );
|
||||
SnapVector( origin );
|
||||
G_SetOrigin( ent, origin );
|
||||
|
||||
// we don't have a valid direction, so just point straight up
|
||||
dir[0] = dir[1] = 0;
|
||||
dir[2] = 1;
|
||||
|
||||
ent->s.eType = ET_GENERAL;
|
||||
G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( dir ) );
|
||||
|
||||
ent->freeAfterEvent = qtrue;
|
||||
|
||||
// splash damage
|
||||
if ( ent->splashDamage ) {
|
||||
if( G_RadiusDamage( ent->r.currentOrigin, ent->parent, ent->splashDamage, ent->splashRadius, ent
|
||||
, ent->splashMethodOfDeath ) ) {
|
||||
g_entities[ent->r.ownerNum].client->accuracy_hits++;
|
||||
}
|
||||
}
|
||||
|
||||
trap_LinkEntity( ent );
|
||||
}
|
||||
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
/*
|
||||
================
|
||||
ProximityMine_Explode
|
||||
================
|
||||
*/
|
||||
static void ProximityMine_Explode( gentity_t *mine ) {
|
||||
G_ExplodeMissile( mine );
|
||||
// if the prox mine has a trigger free it
|
||||
if (mine->activator) {
|
||||
G_FreeEntity(mine->activator);
|
||||
mine->activator = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
ProximityMine_Die
|
||||
================
|
||||
*/
|
||||
static void ProximityMine_Die( gentity_t *ent, gentity_t *inflictor, gentity_t *attacker, int damage, int mod ) {
|
||||
ent->think = ProximityMine_Explode;
|
||||
ent->nextthink = level.time + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
ProximityMine_Trigger
|
||||
================
|
||||
*/
|
||||
void ProximityMine_Trigger( gentity_t *trigger, gentity_t *other, trace_t *trace ) {
|
||||
vec3_t v;
|
||||
gentity_t *mine;
|
||||
|
||||
if( !other->client ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// trigger is a cube, do a distance test now to act as if it's a sphere
|
||||
VectorSubtract( trigger->s.pos.trBase, other->s.pos.trBase, v );
|
||||
if( VectorLength( v ) > trigger->parent->splashRadius ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ( g_gametype.integer >= GT_TEAM ) {
|
||||
// don't trigger same team mines
|
||||
if (trigger->parent->s.generic1 == other->client->sess.sessionTeam) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ok, now check for ability to damage so we don't get triggered thru walls, closed doors, etc...
|
||||
if( !CanDamage( other, trigger->s.pos.trBase ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// trigger the mine!
|
||||
mine = trigger->parent;
|
||||
mine->s.loopSound = 0;
|
||||
G_AddEvent( mine, EV_PROXIMITY_MINE_TRIGGER, 0 );
|
||||
mine->nextthink = level.time + 500;
|
||||
|
||||
G_FreeEntity( trigger );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
ProximityMine_Activate
|
||||
================
|
||||
*/
|
||||
static void ProximityMine_Activate( gentity_t *ent ) {
|
||||
gentity_t *trigger;
|
||||
float r;
|
||||
|
||||
ent->think = ProximityMine_Explode;
|
||||
ent->nextthink = level.time + g_proxMineTimeout.integer;
|
||||
|
||||
ent->takedamage = qtrue;
|
||||
ent->health = 1;
|
||||
ent->die = ProximityMine_Die;
|
||||
|
||||
ent->s.loopSound = G_SoundIndex( "sound/weapons/proxmine/wstbtick.wav" );
|
||||
|
||||
// build the proximity trigger
|
||||
trigger = G_Spawn ();
|
||||
|
||||
trigger->classname = "proxmine_trigger";
|
||||
|
||||
r = ent->splashRadius;
|
||||
VectorSet( trigger->r.mins, -r, -r, -r );
|
||||
VectorSet( trigger->r.maxs, r, r, r );
|
||||
|
||||
G_SetOrigin( trigger, ent->s.pos.trBase );
|
||||
|
||||
trigger->parent = ent;
|
||||
trigger->r.contents = CONTENTS_TRIGGER;
|
||||
trigger->touch = ProximityMine_Trigger;
|
||||
|
||||
trap_LinkEntity (trigger);
|
||||
|
||||
// set pointer to trigger so the entity can be freed when the mine explodes
|
||||
ent->activator = trigger;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
ProximityMine_ExplodeOnPlayer
|
||||
================
|
||||
*/
|
||||
static void ProximityMine_ExplodeOnPlayer( gentity_t *mine ) {
|
||||
gentity_t *player;
|
||||
|
||||
player = mine->enemy;
|
||||
player->client->ps.eFlags &= ~EF_TICKING;
|
||||
|
||||
if ( player->client->invulnerabilityTime > level.time ) {
|
||||
G_Damage( player, mine->parent, mine->parent, vec3_origin, mine->s.origin, 1000, DAMAGE_NO_KNOCKBACK, MOD_JUICED );
|
||||
player->client->invulnerabilityTime = 0;
|
||||
G_TempEntity( player->client->ps.origin, EV_JUICED );
|
||||
}
|
||||
else {
|
||||
G_SetOrigin( mine, player->s.pos.trBase );
|
||||
// make sure the explosion gets to the client
|
||||
mine->r.svFlags &= ~SVF_NOCLIENT;
|
||||
mine->splashMethodOfDeath = MOD_PROXIMITY_MINE;
|
||||
G_ExplodeMissile( mine );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
ProximityMine_Player
|
||||
================
|
||||
*/
|
||||
static void ProximityMine_Player( gentity_t *mine, gentity_t *player ) {
|
||||
if( mine->s.eFlags & EF_NODRAW ) {
|
||||
return;
|
||||
}
|
||||
|
||||
G_AddEvent( mine, EV_PROXIMITY_MINE_STICK, 0 );
|
||||
|
||||
if( player->s.eFlags & EF_TICKING ) {
|
||||
player->activator->splashDamage += mine->splashDamage;
|
||||
player->activator->splashRadius *= 1.50;
|
||||
mine->think = G_FreeEntity;
|
||||
mine->nextthink = level.time;
|
||||
return;
|
||||
}
|
||||
|
||||
player->client->ps.eFlags |= EF_TICKING;
|
||||
player->activator = mine;
|
||||
|
||||
mine->s.eFlags |= EF_NODRAW;
|
||||
mine->r.svFlags |= SVF_NOCLIENT;
|
||||
mine->s.pos.trType = TR_LINEAR;
|
||||
VectorClear( mine->s.pos.trDelta );
|
||||
|
||||
mine->enemy = player;
|
||||
mine->think = ProximityMine_ExplodeOnPlayer;
|
||||
if ( player->client->invulnerabilityTime > level.time ) {
|
||||
mine->nextthink = level.time + 2 * 1000;
|
||||
}
|
||||
else {
|
||||
mine->nextthink = level.time + 10 * 1000;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
================
|
||||
G_MissileImpact
|
||||
================
|
||||
*/
|
||||
void G_MissileImpact( gentity_t *ent, trace_t *trace ) {
|
||||
gentity_t *other;
|
||||
qboolean hitClient = qfalse;
|
||||
#ifdef MISSIONPACK
|
||||
vec3_t forward, impactpoint, bouncedir;
|
||||
int eFlags;
|
||||
#endif
|
||||
other = &g_entities[trace->entityNum];
|
||||
|
||||
// check for bounce
|
||||
if ( !other->takedamage &&
|
||||
( ent->s.eFlags & ( EF_BOUNCE | EF_BOUNCE_HALF ) ) ) {
|
||||
G_BounceMissile( ent, trace );
|
||||
G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
if ( other->takedamage ) {
|
||||
if ( ent->s.weapon != WP_PROX_LAUNCHER ) {
|
||||
if ( other->client && other->client->invulnerabilityTime > level.time ) {
|
||||
//
|
||||
VectorCopy( ent->s.pos.trDelta, forward );
|
||||
VectorNormalize( forward );
|
||||
if (G_InvulnerabilityEffect( other, forward, ent->s.pos.trBase, impactpoint, bouncedir )) {
|
||||
VectorCopy( bouncedir, trace->plane.normal );
|
||||
eFlags = ent->s.eFlags & EF_BOUNCE_HALF;
|
||||
ent->s.eFlags &= ~EF_BOUNCE_HALF;
|
||||
G_BounceMissile( ent, trace );
|
||||
ent->s.eFlags |= eFlags;
|
||||
}
|
||||
ent->target_ent = other;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// impact damage
|
||||
if (other->takedamage) {
|
||||
// FIXME: wrong damage direction?
|
||||
if ( ent->damage ) {
|
||||
vec3_t velocity;
|
||||
|
||||
if( LogAccuracyHit( other, &g_entities[ent->r.ownerNum] ) ) {
|
||||
g_entities[ent->r.ownerNum].client->accuracy_hits++;
|
||||
hitClient = qtrue;
|
||||
}
|
||||
BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
|
||||
if ( VectorLength( velocity ) == 0 ) {
|
||||
velocity[2] = 1; // stepped on a grenade
|
||||
}
|
||||
G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
|
||||
ent->s.origin, ent->damage,
|
||||
0, ent->methodOfDeath);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
if( ent->s.weapon == WP_PROX_LAUNCHER ) {
|
||||
if( ent->s.pos.trType != TR_GRAVITY ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's a player, stick it on to them (flag them and remove this entity)
|
||||
if( other->s.eType == ET_PLAYER && other->health > 0 ) {
|
||||
ProximityMine_Player( ent, other );
|
||||
return;
|
||||
}
|
||||
|
||||
SnapVectorTowards( trace->endpos, ent->s.pos.trBase );
|
||||
G_SetOrigin( ent, trace->endpos );
|
||||
ent->s.pos.trType = TR_STATIONARY;
|
||||
VectorClear( ent->s.pos.trDelta );
|
||||
|
||||
G_AddEvent( ent, EV_PROXIMITY_MINE_STICK, trace->surfaceFlags );
|
||||
|
||||
ent->think = ProximityMine_Activate;
|
||||
ent->nextthink = level.time + 2000;
|
||||
|
||||
vectoangles( trace->plane.normal, ent->s.angles );
|
||||
ent->s.angles[0] += 90;
|
||||
|
||||
// link the prox mine to the other entity
|
||||
ent->enemy = other;
|
||||
ent->die = ProximityMine_Die;
|
||||
VectorCopy(trace->plane.normal, ent->movedir);
|
||||
VectorSet(ent->r.mins, -4, -4, -4);
|
||||
VectorSet(ent->r.maxs, 4, 4, 4);
|
||||
trap_LinkEntity(ent);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp(ent->classname, "hook")) {
|
||||
gentity_t *nent;
|
||||
vec3_t v;
|
||||
|
||||
nent = G_Spawn();
|
||||
if ( other->takedamage && other->client ) {
|
||||
|
||||
G_AddEvent( nent, EV_MISSILE_HIT, DirToByte( trace->plane.normal ) );
|
||||
nent->s.otherEntityNum = other->s.number;
|
||||
|
||||
ent->enemy = other;
|
||||
|
||||
v[0] = other->r.currentOrigin[0] + (other->r.mins[0] + other->r.maxs[0]) * 0.5;
|
||||
v[1] = other->r.currentOrigin[1] + (other->r.mins[1] + other->r.maxs[1]) * 0.5;
|
||||
v[2] = other->r.currentOrigin[2] + (other->r.mins[2] + other->r.maxs[2]) * 0.5;
|
||||
|
||||
SnapVectorTowards( v, ent->s.pos.trBase ); // save net bandwidth
|
||||
} else {
|
||||
VectorCopy(trace->endpos, v);
|
||||
G_AddEvent( nent, EV_MISSILE_MISS, DirToByte( trace->plane.normal ) );
|
||||
ent->enemy = NULL;
|
||||
}
|
||||
|
||||
SnapVectorTowards( v, ent->s.pos.trBase ); // save net bandwidth
|
||||
|
||||
nent->freeAfterEvent = qtrue;
|
||||
// change over to a normal entity right at the point of impact
|
||||
nent->s.eType = ET_GENERAL;
|
||||
ent->s.eType = ET_GRAPPLE;
|
||||
|
||||
G_SetOrigin( ent, v );
|
||||
G_SetOrigin( nent, v );
|
||||
|
||||
ent->think = Weapon_HookThink;
|
||||
ent->nextthink = level.time + FRAMETIME;
|
||||
|
||||
ent->parent->client->ps.pm_flags |= PMF_GRAPPLE_PULL;
|
||||
VectorCopy( ent->r.currentOrigin, ent->parent->client->ps.grapplePoint);
|
||||
|
||||
trap_LinkEntity( ent );
|
||||
trap_LinkEntity( nent );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// is it cheaper in bandwidth to just remove this ent and create a new
|
||||
// one, rather than changing the missile into the explosion?
|
||||
|
||||
if ( other->takedamage && other->client ) {
|
||||
G_AddEvent( ent, EV_MISSILE_HIT, DirToByte( trace->plane.normal ) );
|
||||
ent->s.otherEntityNum = other->s.number;
|
||||
} else if( trace->surfaceFlags & SURF_METALSTEPS ) {
|
||||
G_AddEvent( ent, EV_MISSILE_MISS_METAL, DirToByte( trace->plane.normal ) );
|
||||
} else {
|
||||
G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( trace->plane.normal ) );
|
||||
}
|
||||
|
||||
ent->freeAfterEvent = qtrue;
|
||||
|
||||
// change over to a normal entity right at the point of impact
|
||||
ent->s.eType = ET_GENERAL;
|
||||
|
||||
SnapVectorTowards( trace->endpos, ent->s.pos.trBase ); // save net bandwidth
|
||||
|
||||
G_SetOrigin( ent, trace->endpos );
|
||||
|
||||
// splash damage (doesn't apply to person directly hit)
|
||||
if ( ent->splashDamage ) {
|
||||
if( G_RadiusDamage( trace->endpos, ent->parent, ent->splashDamage, ent->splashRadius,
|
||||
other, ent->splashMethodOfDeath ) ) {
|
||||
if( !hitClient ) {
|
||||
g_entities[ent->r.ownerNum].client->accuracy_hits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trap_LinkEntity( ent );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
G_RunMissile
|
||||
================
|
||||
*/
|
||||
void G_RunMissile( gentity_t *ent ) {
|
||||
vec3_t origin;
|
||||
trace_t tr;
|
||||
int passent;
|
||||
|
||||
// get current position
|
||||
BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );
|
||||
|
||||
// if this missile bounced off an invulnerability sphere
|
||||
if ( ent->target_ent ) {
|
||||
passent = ent->target_ent->s.number;
|
||||
}
|
||||
#ifdef MISSIONPACK
|
||||
// prox mines that left the owner bbox will attach to anything, even the owner
|
||||
else if (ent->s.weapon == WP_PROX_LAUNCHER && ent->count) {
|
||||
passent = ENTITYNUM_NONE;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
// ignore interactions with the missile owner
|
||||
passent = ent->r.ownerNum;
|
||||
}
|
||||
// trace a line from the previous position to the current position
|
||||
trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask );
|
||||
|
||||
if ( tr.startsolid || tr.allsolid ) {
|
||||
// make sure the tr.entityNum is set to the entity we're stuck in
|
||||
trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, passent, ent->clipmask );
|
||||
tr.fraction = 0;
|
||||
}
|
||||
else {
|
||||
VectorCopy( tr.endpos, ent->r.currentOrigin );
|
||||
}
|
||||
|
||||
trap_LinkEntity( ent );
|
||||
|
||||
if ( tr.fraction != 1 ) {
|
||||
// never explode or bounce on sky
|
||||
if ( tr.surfaceFlags & SURF_NOIMPACT ) {
|
||||
// If grapple, reset owner
|
||||
if (ent->parent && ent->parent->client && ent->parent->client->hook == ent) {
|
||||
ent->parent->client->hook = NULL;
|
||||
}
|
||||
G_FreeEntity( ent );
|
||||
return;
|
||||
}
|
||||
G_MissileImpact( ent, &tr );
|
||||
if ( ent->s.eType != ET_MISSILE ) {
|
||||
return; // exploded
|
||||
}
|
||||
}
|
||||
#ifdef MISSIONPACK
|
||||
// if the prox mine wasn't yet outside the player body
|
||||
if (ent->s.weapon == WP_PROX_LAUNCHER && !ent->count) {
|
||||
// check if the prox mine is outside the owner bbox
|
||||
trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, ENTITYNUM_NONE, ent->clipmask );
|
||||
if (!tr.startsolid || tr.entityNum != ent->r.ownerNum) {
|
||||
ent->count = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// check think function after bouncing
|
||||
G_RunThink( ent );
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
=================
|
||||
fire_plasma
|
||||
|
||||
=================
|
||||
*/
|
||||
gentity_t *fire_plasma (gentity_t *self, vec3_t start, vec3_t dir) {
|
||||
gentity_t *bolt;
|
||||
|
||||
VectorNormalize (dir);
|
||||
|
||||
bolt = G_Spawn();
|
||||
bolt->classname = "plasma";
|
||||
bolt->nextthink = level.time + 10000;
|
||||
bolt->think = G_ExplodeMissile;
|
||||
bolt->s.eType = ET_MISSILE;
|
||||
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
|
||||
bolt->s.weapon = WP_PLASMAGUN;
|
||||
bolt->r.ownerNum = self->s.number;
|
||||
bolt->parent = self;
|
||||
bolt->damage = 20;
|
||||
bolt->splashDamage = 15;
|
||||
bolt->splashRadius = 20;
|
||||
bolt->methodOfDeath = MOD_PLASMA;
|
||||
bolt->splashMethodOfDeath = MOD_PLASMA_SPLASH;
|
||||
bolt->clipmask = MASK_SHOT;
|
||||
bolt->target_ent = NULL;
|
||||
|
||||
bolt->s.pos.trType = TR_LINEAR;
|
||||
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
|
||||
VectorCopy( start, bolt->s.pos.trBase );
|
||||
VectorScale( dir, 2000, bolt->s.pos.trDelta );
|
||||
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
|
||||
|
||||
VectorCopy (start, bolt->r.currentOrigin);
|
||||
|
||||
return bolt;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
fire_grenade
|
||||
=================
|
||||
*/
|
||||
gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t dir) {
|
||||
gentity_t *bolt;
|
||||
|
||||
VectorNormalize (dir);
|
||||
|
||||
bolt = G_Spawn();
|
||||
bolt->classname = "grenade";
|
||||
bolt->nextthink = level.time + 2500;
|
||||
bolt->think = G_ExplodeMissile;
|
||||
bolt->s.eType = ET_MISSILE;
|
||||
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
|
||||
bolt->s.weapon = WP_GRENADE_LAUNCHER;
|
||||
bolt->s.eFlags = EF_BOUNCE_HALF;
|
||||
bolt->r.ownerNum = self->s.number;
|
||||
bolt->parent = self;
|
||||
bolt->damage = 100;
|
||||
bolt->splashDamage = 100;
|
||||
bolt->splashRadius = 150;
|
||||
bolt->methodOfDeath = MOD_GRENADE;
|
||||
bolt->splashMethodOfDeath = MOD_GRENADE_SPLASH;
|
||||
bolt->clipmask = MASK_SHOT;
|
||||
bolt->target_ent = NULL;
|
||||
|
||||
bolt->s.pos.trType = TR_GRAVITY;
|
||||
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
|
||||
VectorCopy( start, bolt->s.pos.trBase );
|
||||
VectorScale( dir, 700, bolt->s.pos.trDelta );
|
||||
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
|
||||
|
||||
VectorCopy (start, bolt->r.currentOrigin);
|
||||
|
||||
return bolt;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
fire_bfg
|
||||
=================
|
||||
*/
|
||||
gentity_t *fire_bfg (gentity_t *self, vec3_t start, vec3_t dir) {
|
||||
gentity_t *bolt;
|
||||
|
||||
VectorNormalize (dir);
|
||||
|
||||
bolt = G_Spawn();
|
||||
bolt->classname = "bfg";
|
||||
bolt->nextthink = level.time + 10000;
|
||||
bolt->think = G_ExplodeMissile;
|
||||
bolt->s.eType = ET_MISSILE;
|
||||
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
|
||||
bolt->s.weapon = WP_BFG;
|
||||
bolt->r.ownerNum = self->s.number;
|
||||
bolt->parent = self;
|
||||
bolt->damage = 100;
|
||||
bolt->splashDamage = 100;
|
||||
bolt->splashRadius = 120;
|
||||
bolt->methodOfDeath = MOD_BFG;
|
||||
bolt->splashMethodOfDeath = MOD_BFG_SPLASH;
|
||||
bolt->clipmask = MASK_SHOT;
|
||||
bolt->target_ent = NULL;
|
||||
|
||||
bolt->s.pos.trType = TR_LINEAR;
|
||||
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
|
||||
VectorCopy( start, bolt->s.pos.trBase );
|
||||
VectorScale( dir, 2000, bolt->s.pos.trDelta );
|
||||
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
|
||||
VectorCopy (start, bolt->r.currentOrigin);
|
||||
|
||||
return bolt;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
fire_rocket
|
||||
=================
|
||||
*/
|
||||
gentity_t *fire_rocket (gentity_t *self, vec3_t start, vec3_t dir) {
|
||||
gentity_t *bolt;
|
||||
|
||||
VectorNormalize (dir);
|
||||
|
||||
bolt = G_Spawn();
|
||||
bolt->classname = "rocket";
|
||||
bolt->nextthink = level.time + 15000;
|
||||
bolt->think = G_ExplodeMissile;
|
||||
bolt->s.eType = ET_MISSILE;
|
||||
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
|
||||
bolt->s.weapon = WP_ROCKET_LAUNCHER;
|
||||
bolt->r.ownerNum = self->s.number;
|
||||
bolt->parent = self;
|
||||
bolt->damage = 100;
|
||||
bolt->splashDamage = 100;
|
||||
bolt->splashRadius = 120;
|
||||
bolt->methodOfDeath = MOD_ROCKET;
|
||||
bolt->splashMethodOfDeath = MOD_ROCKET_SPLASH;
|
||||
bolt->clipmask = MASK_SHOT;
|
||||
bolt->target_ent = NULL;
|
||||
|
||||
bolt->s.pos.trType = TR_LINEAR;
|
||||
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
|
||||
VectorCopy( start, bolt->s.pos.trBase );
|
||||
VectorScale( dir, 900, bolt->s.pos.trDelta );
|
||||
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
|
||||
VectorCopy (start, bolt->r.currentOrigin);
|
||||
|
||||
return bolt;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
fire_grapple
|
||||
=================
|
||||
*/
|
||||
gentity_t *fire_grapple (gentity_t *self, vec3_t start, vec3_t dir) {
|
||||
gentity_t *hook;
|
||||
|
||||
VectorNormalize (dir);
|
||||
|
||||
hook = G_Spawn();
|
||||
hook->classname = "hook";
|
||||
hook->nextthink = level.time + 10000;
|
||||
hook->think = Weapon_HookFree;
|
||||
hook->s.eType = ET_MISSILE;
|
||||
hook->r.svFlags = SVF_USE_CURRENT_ORIGIN;
|
||||
hook->s.weapon = WP_GRAPPLING_HOOK;
|
||||
hook->r.ownerNum = self->s.number;
|
||||
hook->methodOfDeath = MOD_GRAPPLE;
|
||||
hook->clipmask = MASK_SHOT;
|
||||
hook->parent = self;
|
||||
hook->target_ent = NULL;
|
||||
|
||||
hook->s.pos.trType = TR_LINEAR;
|
||||
hook->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
|
||||
hook->s.otherEntityNum = self->s.number; // use to match beam in client
|
||||
VectorCopy( start, hook->s.pos.trBase );
|
||||
VectorScale( dir, 800, hook->s.pos.trDelta );
|
||||
SnapVector( hook->s.pos.trDelta ); // save net bandwidth
|
||||
VectorCopy (start, hook->r.currentOrigin);
|
||||
|
||||
self->client->hook = hook;
|
||||
|
||||
return hook;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
/*
|
||||
=================
|
||||
fire_nail
|
||||
=================
|
||||
*/
|
||||
#define NAILGUN_SPREAD 500
|
||||
|
||||
gentity_t *fire_nail( gentity_t *self, vec3_t start, vec3_t forward, vec3_t right, vec3_t up ) {
|
||||
gentity_t *bolt;
|
||||
vec3_t dir;
|
||||
vec3_t end;
|
||||
float r, u, scale;
|
||||
|
||||
bolt = G_Spawn();
|
||||
bolt->classname = "nail";
|
||||
bolt->nextthink = level.time + 10000;
|
||||
bolt->think = G_ExplodeMissile;
|
||||
bolt->s.eType = ET_MISSILE;
|
||||
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
|
||||
bolt->s.weapon = WP_NAILGUN;
|
||||
bolt->r.ownerNum = self->s.number;
|
||||
bolt->parent = self;
|
||||
bolt->damage = 20;
|
||||
bolt->methodOfDeath = MOD_NAIL;
|
||||
bolt->clipmask = MASK_SHOT;
|
||||
bolt->target_ent = NULL;
|
||||
|
||||
bolt->s.pos.trType = TR_LINEAR;
|
||||
bolt->s.pos.trTime = level.time;
|
||||
VectorCopy( start, bolt->s.pos.trBase );
|
||||
|
||||
r = random() * M_PI * 2.0f;
|
||||
u = sin(r) * crandom() * NAILGUN_SPREAD * 16;
|
||||
r = cos(r) * crandom() * NAILGUN_SPREAD * 16;
|
||||
VectorMA( start, 8192 * 16, forward, end);
|
||||
VectorMA (end, r, right, end);
|
||||
VectorMA (end, u, up, end);
|
||||
VectorSubtract( end, start, dir );
|
||||
VectorNormalize( dir );
|
||||
|
||||
scale = 555 + random() * 1800;
|
||||
VectorScale( dir, scale, bolt->s.pos.trDelta );
|
||||
SnapVector( bolt->s.pos.trDelta );
|
||||
|
||||
VectorCopy( start, bolt->r.currentOrigin );
|
||||
|
||||
return bolt;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
fire_prox
|
||||
=================
|
||||
*/
|
||||
gentity_t *fire_prox( gentity_t *self, vec3_t start, vec3_t dir ) {
|
||||
gentity_t *bolt;
|
||||
|
||||
VectorNormalize (dir);
|
||||
|
||||
bolt = G_Spawn();
|
||||
bolt->classname = "prox mine";
|
||||
bolt->nextthink = level.time + 3000;
|
||||
bolt->think = G_ExplodeMissile;
|
||||
bolt->s.eType = ET_MISSILE;
|
||||
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
|
||||
bolt->s.weapon = WP_PROX_LAUNCHER;
|
||||
bolt->s.eFlags = 0;
|
||||
bolt->r.ownerNum = self->s.number;
|
||||
bolt->parent = self;
|
||||
bolt->damage = 0;
|
||||
bolt->splashDamage = 100;
|
||||
bolt->splashRadius = 150;
|
||||
bolt->methodOfDeath = MOD_PROXIMITY_MINE;
|
||||
bolt->splashMethodOfDeath = MOD_PROXIMITY_MINE;
|
||||
bolt->clipmask = MASK_SHOT;
|
||||
bolt->target_ent = NULL;
|
||||
// count is used to check if the prox mine left the player bbox
|
||||
// if count == 1 then the prox mine left the player bbox and can attack to it
|
||||
bolt->count = 0;
|
||||
|
||||
//FIXME: we prolly wanna abuse another field
|
||||
bolt->s.generic1 = self->client->sess.sessionTeam;
|
||||
|
||||
bolt->s.pos.trType = TR_GRAVITY;
|
||||
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
|
||||
VectorCopy( start, bolt->s.pos.trBase );
|
||||
VectorScale( dir, 700, bolt->s.pos.trDelta );
|
||||
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
|
||||
|
||||
VectorCopy (start, bolt->r.currentOrigin);
|
||||
|
||||
return bolt;
|
||||
}
|
||||
#endif
|
||||
+1612
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
// g_public.h -- game module information visible to server
|
||||
|
||||
#define GAME_API_VERSION 8
|
||||
|
||||
// entity->svFlags
|
||||
// the server does not know how to interpret most of the values
|
||||
// in entityStates (level eType), so the game must explicitly flag
|
||||
// special server behaviors
|
||||
#define SVF_NOCLIENT 0x00000001 // don't send entity to clients, even if it has effects
|
||||
|
||||
// TTimo
|
||||
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=551
|
||||
#define SVF_CLIENTMASK 0x00000002
|
||||
|
||||
#define SVF_BOT 0x00000008 // set if the entity is a bot
|
||||
#define SVF_BROADCAST 0x00000020 // send to all connected clients
|
||||
#define SVF_PORTAL 0x00000040 // merge a second pvs at origin2 into snapshots
|
||||
#define SVF_USE_CURRENT_ORIGIN 0x00000080 // entity->r.currentOrigin instead of entity->s.origin
|
||||
// for link position (missiles and movers)
|
||||
#define SVF_SINGLECLIENT 0x00000100 // only send to a single client (entityShared_t->singleClient)
|
||||
#define SVF_NOSERVERINFO 0x00000200 // don't send CS_SERVERINFO updates to this client
|
||||
// so that it can be updated for ping tools without
|
||||
// lagging clients
|
||||
#define SVF_CAPSULE 0x00000400 // use capsule for collision detection instead of bbox
|
||||
#define SVF_NOTSINGLECLIENT 0x00000800 // send entity to everyone but one client
|
||||
// (entityShared_t->singleClient)
|
||||
|
||||
|
||||
|
||||
//===============================================================
|
||||
|
||||
|
||||
typedef struct {
|
||||
entityState_t s; // communicated by server to clients
|
||||
|
||||
qboolean linked; // qfalse if not in any good cluster
|
||||
int linkcount;
|
||||
|
||||
int svFlags; // SVF_NOCLIENT, SVF_BROADCAST, etc
|
||||
|
||||
// only send to this client when SVF_SINGLECLIENT is set
|
||||
// if SVF_CLIENTMASK is set, use bitmask for clients to send to (maxclients must be <= 32, up to the mod to enforce this)
|
||||
int singleClient;
|
||||
|
||||
qboolean bmodel; // if false, assume an explicit mins / maxs bounding box
|
||||
// only set by trap_SetBrushModel
|
||||
vec3_t mins, maxs;
|
||||
int contents; // CONTENTS_TRIGGER, CONTENTS_SOLID, CONTENTS_BODY, etc
|
||||
// a non-solid entity should set to 0
|
||||
|
||||
vec3_t absmin, absmax; // derived from mins/maxs and origin + rotation
|
||||
|
||||
// currentOrigin will be used for all collision detection and world linking.
|
||||
// it will not necessarily be the same as the trajectory evaluation for the current
|
||||
// time, because each entity must be moved one at a time after time is advanced
|
||||
// to avoid simultanious collision issues
|
||||
vec3_t currentOrigin;
|
||||
vec3_t currentAngles;
|
||||
|
||||
// when a trace call is made and passEntityNum != ENTITYNUM_NONE,
|
||||
// an ent will be excluded from testing if:
|
||||
// ent->s.number == passEntityNum (don't interact with self)
|
||||
// ent->s.ownerNum = passEntityNum (don't interact with your own missiles)
|
||||
// entity[ent->s.ownerNum].ownerNum = passEntityNum (don't interact with other missiles from owner)
|
||||
int ownerNum;
|
||||
} entityShared_t;
|
||||
|
||||
|
||||
|
||||
// the server looks at a sharedEntity, which is the start of the game's gentity_t structure
|
||||
typedef struct {
|
||||
entityState_t s; // communicated by server to clients
|
||||
entityShared_t r; // shared by both the server system and game
|
||||
} sharedEntity_t;
|
||||
|
||||
|
||||
|
||||
//===============================================================
|
||||
|
||||
//
|
||||
// system traps provided by the main engine
|
||||
//
|
||||
typedef enum {
|
||||
//============== general Quake services ==================
|
||||
|
||||
G_PRINT, // ( const char *string );
|
||||
// print message on the local console
|
||||
|
||||
G_ERROR, // ( const char *string );
|
||||
// abort the game
|
||||
|
||||
G_MILLISECONDS, // ( void );
|
||||
// get current time for profiling reasons
|
||||
// this should NOT be used for any game related tasks,
|
||||
// because it is not journaled
|
||||
|
||||
// console variable interaction
|
||||
G_CVAR_REGISTER, // ( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags );
|
||||
G_CVAR_UPDATE, // ( vmCvar_t *vmCvar );
|
||||
G_CVAR_SET, // ( const char *var_name, const char *value );
|
||||
G_CVAR_VARIABLE_INTEGER_VALUE, // ( const char *var_name );
|
||||
|
||||
G_CVAR_VARIABLE_STRING_BUFFER, // ( const char *var_name, char *buffer, int bufsize );
|
||||
|
||||
G_ARGC, // ( void );
|
||||
// ClientCommand and ServerCommand parameter access
|
||||
|
||||
G_ARGV, // ( int n, char *buffer, int bufferLength );
|
||||
|
||||
G_FS_FOPEN_FILE, // ( const char *qpath, fileHandle_t *file, fsMode_t mode );
|
||||
G_FS_READ, // ( void *buffer, int len, fileHandle_t f );
|
||||
G_FS_WRITE, // ( const void *buffer, int len, fileHandle_t f );
|
||||
G_FS_FCLOSE_FILE, // ( fileHandle_t f );
|
||||
|
||||
G_SEND_CONSOLE_COMMAND, // ( const char *text );
|
||||
// add commands to the console as if they were typed in
|
||||
// for map changing, etc
|
||||
|
||||
|
||||
//=========== server specific functionality =============
|
||||
|
||||
G_LOCATE_GAME_DATA, // ( gentity_t *gEnts, int numGEntities, int sizeofGEntity_t,
|
||||
// playerState_t *clients, int sizeofGameClient );
|
||||
// the game needs to let the server system know where and how big the gentities
|
||||
// are, so it can look at them directly without going through an interface
|
||||
|
||||
G_DROP_CLIENT, // ( int clientNum, const char *reason );
|
||||
// kick a client off the server with a message
|
||||
|
||||
G_SEND_SERVER_COMMAND, // ( int clientNum, const char *fmt, ... );
|
||||
// reliably sends a command string to be interpreted by the given
|
||||
// client. If clientNum is -1, it will be sent to all clients
|
||||
|
||||
G_SET_CONFIGSTRING, // ( int num, const char *string );
|
||||
// config strings hold all the index strings, and various other information
|
||||
// that is reliably communicated to all clients
|
||||
// All of the current configstrings are sent to clients when
|
||||
// they connect, and changes are sent to all connected clients.
|
||||
// All confgstrings are cleared at each level start.
|
||||
|
||||
G_GET_CONFIGSTRING, // ( int num, char *buffer, int bufferSize );
|
||||
|
||||
G_GET_USERINFO, // ( int num, char *buffer, int bufferSize );
|
||||
// userinfo strings are maintained by the server system, so they
|
||||
// are persistant across level loads, while all other game visible
|
||||
// data is completely reset
|
||||
|
||||
G_SET_USERINFO, // ( int num, const char *buffer );
|
||||
|
||||
G_GET_SERVERINFO, // ( char *buffer, int bufferSize );
|
||||
// the serverinfo info string has all the cvars visible to server browsers
|
||||
|
||||
G_SET_BRUSH_MODEL, // ( gentity_t *ent, const char *name );
|
||||
// sets mins and maxs based on the brushmodel name
|
||||
|
||||
G_TRACE, // ( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask );
|
||||
// collision detection against all linked entities
|
||||
|
||||
G_POINT_CONTENTS, // ( const vec3_t point, int passEntityNum );
|
||||
// point contents against all linked entities
|
||||
|
||||
G_IN_PVS, // ( const vec3_t p1, const vec3_t p2 );
|
||||
|
||||
G_IN_PVS_IGNORE_PORTALS, // ( const vec3_t p1, const vec3_t p2 );
|
||||
|
||||
G_ADJUST_AREA_PORTAL_STATE, // ( gentity_t *ent, qboolean open );
|
||||
|
||||
G_AREAS_CONNECTED, // ( int area1, int area2 );
|
||||
|
||||
G_LINKENTITY, // ( gentity_t *ent );
|
||||
// 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.
|
||||
|
||||
G_UNLINKENTITY, // ( gentity_t *ent );
|
||||
// call before removing an interactive entity
|
||||
|
||||
G_ENTITIES_IN_BOX, // ( const vec3_t mins, const vec3_t maxs, gentity_t **list, int maxcount );
|
||||
// EntitiesInBox will return brush models based on their bounding box,
|
||||
// so exact determination must still be done with EntityContact
|
||||
|
||||
G_ENTITY_CONTACT, // ( const vec3_t mins, const vec3_t maxs, const gentity_t *ent );
|
||||
// perform an exact check against inline brush models of non-square shape
|
||||
|
||||
// access for bots to get and free a server client (FIXME?)
|
||||
G_BOT_ALLOCATE_CLIENT, // ( void );
|
||||
|
||||
G_BOT_FREE_CLIENT, // ( int clientNum );
|
||||
|
||||
G_GET_USERCMD, // ( int clientNum, usercmd_t *cmd )
|
||||
|
||||
G_GET_ENTITY_TOKEN, // qboolean ( char *buffer, int bufferSize )
|
||||
// Retrieves the next string token from the entity spawn text, returning
|
||||
// false when all tokens have been parsed.
|
||||
// This should only be done at GAME_INIT time.
|
||||
|
||||
G_FS_GETFILELIST,
|
||||
G_DEBUG_POLYGON_CREATE,
|
||||
G_DEBUG_POLYGON_DELETE,
|
||||
G_REAL_TIME,
|
||||
G_SNAPVECTOR,
|
||||
|
||||
G_TRACECAPSULE, // ( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask );
|
||||
G_ENTITY_CONTACTCAPSULE, // ( const vec3_t mins, const vec3_t maxs, const gentity_t *ent );
|
||||
|
||||
// 1.32
|
||||
G_FS_SEEK,
|
||||
|
||||
BOTLIB_SETUP = 200, // ( void );
|
||||
BOTLIB_SHUTDOWN, // ( void );
|
||||
BOTLIB_LIBVAR_SET,
|
||||
BOTLIB_LIBVAR_GET,
|
||||
BOTLIB_PC_ADD_GLOBAL_DEFINE,
|
||||
BOTLIB_START_FRAME,
|
||||
BOTLIB_LOAD_MAP,
|
||||
BOTLIB_UPDATENTITY,
|
||||
BOTLIB_TEST,
|
||||
|
||||
BOTLIB_GET_SNAPSHOT_ENTITY, // ( int client, int ent );
|
||||
BOTLIB_GET_CONSOLE_MESSAGE, // ( int client, char *message, int size );
|
||||
BOTLIB_USER_COMMAND, // ( int client, usercmd_t *ucmd );
|
||||
|
||||
BOTLIB_AAS_ENABLE_ROUTING_AREA = 300,
|
||||
BOTLIB_AAS_BBOX_AREAS,
|
||||
BOTLIB_AAS_AREA_INFO,
|
||||
BOTLIB_AAS_ENTITY_INFO,
|
||||
|
||||
BOTLIB_AAS_INITIALIZED,
|
||||
BOTLIB_AAS_PRESENCE_TYPE_BOUNDING_BOX,
|
||||
BOTLIB_AAS_TIME,
|
||||
|
||||
BOTLIB_AAS_POINT_AREA_NUM,
|
||||
BOTLIB_AAS_TRACE_AREAS,
|
||||
|
||||
BOTLIB_AAS_POINT_CONTENTS,
|
||||
BOTLIB_AAS_NEXT_BSP_ENTITY,
|
||||
BOTLIB_AAS_VALUE_FOR_BSP_EPAIR_KEY,
|
||||
BOTLIB_AAS_VECTOR_FOR_BSP_EPAIR_KEY,
|
||||
BOTLIB_AAS_FLOAT_FOR_BSP_EPAIR_KEY,
|
||||
BOTLIB_AAS_INT_FOR_BSP_EPAIR_KEY,
|
||||
|
||||
BOTLIB_AAS_AREA_REACHABILITY,
|
||||
|
||||
BOTLIB_AAS_AREA_TRAVEL_TIME_TO_GOAL_AREA,
|
||||
|
||||
BOTLIB_AAS_SWIMMING,
|
||||
BOTLIB_AAS_PREDICT_CLIENT_MOVEMENT,
|
||||
|
||||
BOTLIB_EA_SAY = 400,
|
||||
BOTLIB_EA_SAY_TEAM,
|
||||
BOTLIB_EA_COMMAND,
|
||||
|
||||
BOTLIB_EA_ACTION,
|
||||
BOTLIB_EA_GESTURE,
|
||||
BOTLIB_EA_TALK,
|
||||
BOTLIB_EA_ATTACK,
|
||||
BOTLIB_EA_USE,
|
||||
BOTLIB_EA_RESPAWN,
|
||||
BOTLIB_EA_CROUCH,
|
||||
BOTLIB_EA_MOVE_UP,
|
||||
BOTLIB_EA_MOVE_DOWN,
|
||||
BOTLIB_EA_MOVE_FORWARD,
|
||||
BOTLIB_EA_MOVE_BACK,
|
||||
BOTLIB_EA_MOVE_LEFT,
|
||||
BOTLIB_EA_MOVE_RIGHT,
|
||||
|
||||
BOTLIB_EA_SELECT_WEAPON,
|
||||
BOTLIB_EA_JUMP,
|
||||
BOTLIB_EA_DELAYED_JUMP,
|
||||
BOTLIB_EA_MOVE,
|
||||
BOTLIB_EA_VIEW,
|
||||
|
||||
BOTLIB_EA_END_REGULAR,
|
||||
BOTLIB_EA_GET_INPUT,
|
||||
BOTLIB_EA_RESET_INPUT,
|
||||
|
||||
|
||||
BOTLIB_AI_LOAD_CHARACTER = 500,
|
||||
BOTLIB_AI_FREE_CHARACTER,
|
||||
BOTLIB_AI_CHARACTERISTIC_FLOAT,
|
||||
BOTLIB_AI_CHARACTERISTIC_BFLOAT,
|
||||
BOTLIB_AI_CHARACTERISTIC_INTEGER,
|
||||
BOTLIB_AI_CHARACTERISTIC_BINTEGER,
|
||||
BOTLIB_AI_CHARACTERISTIC_STRING,
|
||||
|
||||
BOTLIB_AI_ALLOC_CHAT_STATE,
|
||||
BOTLIB_AI_FREE_CHAT_STATE,
|
||||
BOTLIB_AI_QUEUE_CONSOLE_MESSAGE,
|
||||
BOTLIB_AI_REMOVE_CONSOLE_MESSAGE,
|
||||
BOTLIB_AI_NEXT_CONSOLE_MESSAGE,
|
||||
BOTLIB_AI_NUM_CONSOLE_MESSAGE,
|
||||
BOTLIB_AI_INITIAL_CHAT,
|
||||
BOTLIB_AI_REPLY_CHAT,
|
||||
BOTLIB_AI_CHAT_LENGTH,
|
||||
BOTLIB_AI_ENTER_CHAT,
|
||||
BOTLIB_AI_STRING_CONTAINS,
|
||||
BOTLIB_AI_FIND_MATCH,
|
||||
BOTLIB_AI_MATCH_VARIABLE,
|
||||
BOTLIB_AI_UNIFY_WHITE_SPACES,
|
||||
BOTLIB_AI_REPLACE_SYNONYMS,
|
||||
BOTLIB_AI_LOAD_CHAT_FILE,
|
||||
BOTLIB_AI_SET_CHAT_GENDER,
|
||||
BOTLIB_AI_SET_CHAT_NAME,
|
||||
|
||||
BOTLIB_AI_RESET_GOAL_STATE,
|
||||
BOTLIB_AI_RESET_AVOID_GOALS,
|
||||
BOTLIB_AI_PUSH_GOAL,
|
||||
BOTLIB_AI_POP_GOAL,
|
||||
BOTLIB_AI_EMPTY_GOAL_STACK,
|
||||
BOTLIB_AI_DUMP_AVOID_GOALS,
|
||||
BOTLIB_AI_DUMP_GOAL_STACK,
|
||||
BOTLIB_AI_GOAL_NAME,
|
||||
BOTLIB_AI_GET_TOP_GOAL,
|
||||
BOTLIB_AI_GET_SECOND_GOAL,
|
||||
BOTLIB_AI_CHOOSE_LTG_ITEM,
|
||||
BOTLIB_AI_CHOOSE_NBG_ITEM,
|
||||
BOTLIB_AI_TOUCHING_GOAL,
|
||||
BOTLIB_AI_ITEM_GOAL_IN_VIS_BUT_NOT_VISIBLE,
|
||||
BOTLIB_AI_GET_LEVEL_ITEM_GOAL,
|
||||
BOTLIB_AI_AVOID_GOAL_TIME,
|
||||
BOTLIB_AI_INIT_LEVEL_ITEMS,
|
||||
BOTLIB_AI_UPDATE_ENTITY_ITEMS,
|
||||
BOTLIB_AI_LOAD_ITEM_WEIGHTS,
|
||||
BOTLIB_AI_FREE_ITEM_WEIGHTS,
|
||||
BOTLIB_AI_SAVE_GOAL_FUZZY_LOGIC,
|
||||
BOTLIB_AI_ALLOC_GOAL_STATE,
|
||||
BOTLIB_AI_FREE_GOAL_STATE,
|
||||
|
||||
BOTLIB_AI_RESET_MOVE_STATE,
|
||||
BOTLIB_AI_MOVE_TO_GOAL,
|
||||
BOTLIB_AI_MOVE_IN_DIRECTION,
|
||||
BOTLIB_AI_RESET_AVOID_REACH,
|
||||
BOTLIB_AI_RESET_LAST_AVOID_REACH,
|
||||
BOTLIB_AI_REACHABILITY_AREA,
|
||||
BOTLIB_AI_MOVEMENT_VIEW_TARGET,
|
||||
BOTLIB_AI_ALLOC_MOVE_STATE,
|
||||
BOTLIB_AI_FREE_MOVE_STATE,
|
||||
BOTLIB_AI_INIT_MOVE_STATE,
|
||||
|
||||
BOTLIB_AI_CHOOSE_BEST_FIGHT_WEAPON,
|
||||
BOTLIB_AI_GET_WEAPON_INFO,
|
||||
BOTLIB_AI_LOAD_WEAPON_WEIGHTS,
|
||||
BOTLIB_AI_ALLOC_WEAPON_STATE,
|
||||
BOTLIB_AI_FREE_WEAPON_STATE,
|
||||
BOTLIB_AI_RESET_WEAPON_STATE,
|
||||
|
||||
BOTLIB_AI_GENETIC_PARENTS_AND_CHILD_SELECTION,
|
||||
BOTLIB_AI_INTERBREED_GOAL_FUZZY_LOGIC,
|
||||
BOTLIB_AI_MUTATE_GOAL_FUZZY_LOGIC,
|
||||
BOTLIB_AI_GET_NEXT_CAMP_SPOT_GOAL,
|
||||
BOTLIB_AI_GET_MAP_LOCATION_GOAL,
|
||||
BOTLIB_AI_NUM_INITIAL_CHATS,
|
||||
BOTLIB_AI_GET_CHAT_MESSAGE,
|
||||
BOTLIB_AI_REMOVE_FROM_AVOID_GOALS,
|
||||
BOTLIB_AI_PREDICT_VISIBLE_POSITION,
|
||||
|
||||
BOTLIB_AI_SET_AVOID_GOAL_TIME,
|
||||
BOTLIB_AI_ADD_AVOID_SPOT,
|
||||
BOTLIB_AAS_ALTERNATIVE_ROUTE_GOAL,
|
||||
BOTLIB_AAS_PREDICT_ROUTE,
|
||||
BOTLIB_AAS_POINT_REACHABILITY_AREA_INDEX,
|
||||
|
||||
BOTLIB_PC_LOAD_SOURCE,
|
||||
BOTLIB_PC_FREE_SOURCE,
|
||||
BOTLIB_PC_READ_TOKEN,
|
||||
BOTLIB_PC_SOURCE_FILE_AND_LINE
|
||||
|
||||
} gameImport_t;
|
||||
|
||||
|
||||
//
|
||||
// functions exported by the game subsystem
|
||||
//
|
||||
typedef enum {
|
||||
GAME_INIT, // ( int levelTime, int randomSeed, int restart );
|
||||
// init and shutdown will be called every single level
|
||||
// The game should call G_GET_ENTITY_TOKEN to parse through all the
|
||||
// entity configuration text and spawn gentities.
|
||||
|
||||
GAME_SHUTDOWN, // (void);
|
||||
|
||||
GAME_CLIENT_CONNECT, // ( int clientNum, qboolean firstTime, qboolean isBot );
|
||||
// return NULL if the client is allowed to connect, otherwise return
|
||||
// a text string with the reason for denial
|
||||
|
||||
GAME_CLIENT_BEGIN, // ( int clientNum );
|
||||
|
||||
GAME_CLIENT_USERINFO_CHANGED, // ( int clientNum );
|
||||
|
||||
GAME_CLIENT_DISCONNECT, // ( int clientNum );
|
||||
|
||||
GAME_CLIENT_COMMAND, // ( int clientNum );
|
||||
|
||||
GAME_CLIENT_THINK, // ( int clientNum );
|
||||
|
||||
GAME_RUN_FRAME, // ( int levelTime );
|
||||
|
||||
GAME_CONSOLE_COMMAND, // ( void );
|
||||
// ConsoleCommand will be called when a command has been issued
|
||||
// that is not recognized as a builtin function.
|
||||
// The game can issue trap_argc() / trap_argv() commands to get the command
|
||||
// and parameters. Return qfalse if the game doesn't recognize it as a command.
|
||||
|
||||
BOTAI_START_FRAME // ( int time );
|
||||
} gameExport_t;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
// g_rankings.h -- score keys for global rankings
|
||||
|
||||
#ifndef _G_RANKINGS_H_
|
||||
#define _G_RANKINGS_H_
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
Key digits:
|
||||
10^9: report type
|
||||
1 = normal
|
||||
2 = developer-only
|
||||
10^8: stat type
|
||||
0 = match stat
|
||||
1 = single player stat
|
||||
2 = duel stat
|
||||
10^7: data type
|
||||
0 = string
|
||||
1 = uint32
|
||||
10^6: calculation
|
||||
0 = use raw value
|
||||
1 = add to total
|
||||
2 = average
|
||||
3 = max
|
||||
4 = min
|
||||
10^5
|
||||
10^4: category
|
||||
00 = general
|
||||
01 = session
|
||||
02 = weapon
|
||||
03 = ammo
|
||||
04 = health
|
||||
05 = armor
|
||||
06 = powerup
|
||||
07 = holdable
|
||||
08 = hazard
|
||||
09 = reward
|
||||
10 = teammate
|
||||
11 = ctf
|
||||
10^3:
|
||||
10^2: sub-category
|
||||
10^1:
|
||||
10^0: ordinal
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// general keys
|
||||
#define QGR_KEY_MATCH_RATING 1112000001
|
||||
#define QGR_KEY_PLAYED_WITH 1210000002
|
||||
|
||||
// session keys
|
||||
#define QGR_KEY_HOSTNAME 1000010000
|
||||
#define QGR_KEY_MAP 1000010001
|
||||
#define QGR_KEY_MOD 1000010002
|
||||
#define QGR_KEY_GAMETYPE 1010010003
|
||||
#define QGR_KEY_FRAGLIMIT 1010010004
|
||||
#define QGR_KEY_TIMELIMIT 1010010005
|
||||
#define QGR_KEY_MAXCLIENTS 1010010006
|
||||
#define QGR_KEY_MAXRATE 1010010007
|
||||
#define QGR_KEY_MINPING 1010010008
|
||||
#define QGR_KEY_MAXPING 1010010009
|
||||
#define QGR_KEY_DEDICATED 1010010010
|
||||
#define QGR_KEY_VERSION 1000010011
|
||||
|
||||
// weapon keys
|
||||
#define QGR_KEY_FRAG 1211020000
|
||||
#define QGR_KEY_SUICIDE 1111020001
|
||||
#define QGR_KEY_SHOT_FIRED 1111020002
|
||||
#define QGR_KEY_HIT_GIVEN 1111020003
|
||||
#define QGR_KEY_HIT_TAKEN 1111020004
|
||||
#define QGR_KEY_DAMAGE_GIVEN 1111020005
|
||||
#define QGR_KEY_DAMAGE_TAKEN 1111020006
|
||||
#define QGR_KEY_SPLASH_GIVEN 1111020007
|
||||
#define QGR_KEY_SPLASH_TAKEN 1111020008
|
||||
#define QGR_KEY_PICKUP_WEAPON 1111020009
|
||||
#define QGR_KEY_TIME 1111020010
|
||||
|
||||
#define QGR_KEY_FRAG_GAUNTLET 1211020100
|
||||
#define QGR_KEY_SUICIDE_GAUNTLET 1111020101
|
||||
#define QGR_KEY_SHOT_FIRED_GAUNTLET 1111020102
|
||||
#define QGR_KEY_HIT_GIVEN_GAUNTLET 1111020103
|
||||
#define QGR_KEY_HIT_TAKEN_GAUNTLET 1111020104
|
||||
#define QGR_KEY_DAMAGE_GIVEN_GAUNTLET 1111020105
|
||||
#define QGR_KEY_DAMAGE_TAKEN_GAUNTLET 1111020106
|
||||
#define QGR_KEY_SPLASH_GIVEN_GAUNTLET 1111020107
|
||||
#define QGR_KEY_SPLASH_TAKEN_GAUNTLET 1111020108
|
||||
#define QGR_KEY_PICKUP_GAUNTLET 1111020109
|
||||
#define QGR_KEY_TIME_GAUNTLET 1111020110
|
||||
|
||||
#define QGR_KEY_FRAG_MACHINEGUN 1211020200
|
||||
#define QGR_KEY_SUICIDE_MACHINEGUN 1111020201
|
||||
#define QGR_KEY_SHOT_FIRED_MACHINEGUN 1111020202
|
||||
#define QGR_KEY_HIT_GIVEN_MACHINEGUN 1111020203
|
||||
#define QGR_KEY_HIT_TAKEN_MACHINEGUN 1111020204
|
||||
#define QGR_KEY_DAMAGE_GIVEN_MACHINEGUN 1111020205
|
||||
#define QGR_KEY_DAMAGE_TAKEN_MACHINEGUN 1111020206
|
||||
#define QGR_KEY_SPLASH_GIVEN_MACHINEGUN 1111020207
|
||||
#define QGR_KEY_SPLASH_TAKEN_MACHINEGUN 1111020208
|
||||
#define QGR_KEY_PICKUP_MACHINEGUN 1111020209
|
||||
#define QGR_KEY_TIME_MACHINEGUN 1111020210
|
||||
|
||||
#define QGR_KEY_FRAG_SHOTGUN 1211020300
|
||||
#define QGR_KEY_SUICIDE_SHOTGUN 1111020301
|
||||
#define QGR_KEY_SHOT_FIRED_SHOTGUN 1111020302
|
||||
#define QGR_KEY_HIT_GIVEN_SHOTGUN 1111020303
|
||||
#define QGR_KEY_HIT_TAKEN_SHOTGUN 1111020304
|
||||
#define QGR_KEY_DAMAGE_GIVEN_SHOTGUN 1111020305
|
||||
#define QGR_KEY_DAMAGE_TAKEN_SHOTGUN 1111020306
|
||||
#define QGR_KEY_SPLASH_GIVEN_SHOTGUN 1111020307
|
||||
#define QGR_KEY_SPLASH_TAKEN_SHOTGUN 1111020308
|
||||
#define QGR_KEY_PICKUP_SHOTGUN 1111020309
|
||||
#define QGR_KEY_TIME_SHOTGUN 1111020310
|
||||
|
||||
#define QGR_KEY_FRAG_GRENADE 1211020400
|
||||
#define QGR_KEY_SUICIDE_GRENADE 1111020401
|
||||
#define QGR_KEY_SHOT_FIRED_GRENADE 1111020402
|
||||
#define QGR_KEY_HIT_GIVEN_GRENADE 1111020403
|
||||
#define QGR_KEY_HIT_TAKEN_GRENADE 1111020404
|
||||
#define QGR_KEY_DAMAGE_GIVEN_GRENADE 1111020405
|
||||
#define QGR_KEY_DAMAGE_TAKEN_GRENADE 1111020406
|
||||
#define QGR_KEY_SPLASH_GIVEN_GRENADE 1111020407
|
||||
#define QGR_KEY_SPLASH_TAKEN_GRENADE 1111020408
|
||||
#define QGR_KEY_PICKUP_GRENADE 1111020409
|
||||
#define QGR_KEY_TIME_GRENADE 1111020410
|
||||
|
||||
#define QGR_KEY_FRAG_ROCKET 1211020500
|
||||
#define QGR_KEY_SUICIDE_ROCKET 1111020501
|
||||
#define QGR_KEY_SHOT_FIRED_ROCKET 1111020502
|
||||
#define QGR_KEY_HIT_GIVEN_ROCKET 1111020503
|
||||
#define QGR_KEY_HIT_TAKEN_ROCKET 1111020504
|
||||
#define QGR_KEY_DAMAGE_GIVEN_ROCKET 1111020505
|
||||
#define QGR_KEY_DAMAGE_TAKEN_ROCKET 1111020506
|
||||
#define QGR_KEY_SPLASH_GIVEN_ROCKET 1111020507
|
||||
#define QGR_KEY_SPLASH_TAKEN_ROCKET 1111020508
|
||||
#define QGR_KEY_PICKUP_ROCKET 1111020509
|
||||
#define QGR_KEY_TIME_ROCKET 1111020510
|
||||
|
||||
#define QGR_KEY_FRAG_PLASMA 1211020600
|
||||
#define QGR_KEY_SUICIDE_PLASMA 1111020601
|
||||
#define QGR_KEY_SHOT_FIRED_PLASMA 1111020602
|
||||
#define QGR_KEY_HIT_GIVEN_PLASMA 1111020603
|
||||
#define QGR_KEY_HIT_TAKEN_PLASMA 1111020604
|
||||
#define QGR_KEY_DAMAGE_GIVEN_PLASMA 1111020605
|
||||
#define QGR_KEY_DAMAGE_TAKEN_PLASMA 1111020606
|
||||
#define QGR_KEY_SPLASH_GIVEN_PLASMA 1111020607
|
||||
#define QGR_KEY_SPLASH_TAKEN_PLASMA 1111020608
|
||||
#define QGR_KEY_PICKUP_PLASMA 1111020609
|
||||
#define QGR_KEY_TIME_PLASMA 1111020610
|
||||
|
||||
#define QGR_KEY_FRAG_RAILGUN 1211020700
|
||||
#define QGR_KEY_SUICIDE_RAILGUN 1111020701
|
||||
#define QGR_KEY_SHOT_FIRED_RAILGUN 1111020702
|
||||
#define QGR_KEY_HIT_GIVEN_RAILGUN 1111020703
|
||||
#define QGR_KEY_HIT_TAKEN_RAILGUN 1111020704
|
||||
#define QGR_KEY_DAMAGE_GIVEN_RAILGUN 1111020705
|
||||
#define QGR_KEY_DAMAGE_TAKEN_RAILGUN 1111020706
|
||||
#define QGR_KEY_SPLASH_GIVEN_RAILGUN 1111020707
|
||||
#define QGR_KEY_SPLASH_TAKEN_RAILGUN 1111020708
|
||||
#define QGR_KEY_PICKUP_RAILGUN 1111020709
|
||||
#define QGR_KEY_TIME_RAILGUN 1111020710
|
||||
|
||||
#define QGR_KEY_FRAG_LIGHTNING 1211020800
|
||||
#define QGR_KEY_SUICIDE_LIGHTNING 1111020801
|
||||
#define QGR_KEY_SHOT_FIRED_LIGHTNING 1111020802
|
||||
#define QGR_KEY_HIT_GIVEN_LIGHTNING 1111020803
|
||||
#define QGR_KEY_HIT_TAKEN_LIGHTNING 1111020804
|
||||
#define QGR_KEY_DAMAGE_GIVEN_LIGHTNING 1111020805
|
||||
#define QGR_KEY_DAMAGE_TAKEN_LIGHTNING 1111020806
|
||||
#define QGR_KEY_SPLASH_GIVEN_LIGHTNING 1111020807
|
||||
#define QGR_KEY_SPLASH_TAKEN_LIGHTNING 1111020808
|
||||
#define QGR_KEY_PICKUP_LIGHTNING 1111020809
|
||||
#define QGR_KEY_TIME_LIGHTNING 1111020810
|
||||
|
||||
#define QGR_KEY_FRAG_BFG 1211020900
|
||||
#define QGR_KEY_SUICIDE_BFG 1111020901
|
||||
#define QGR_KEY_SHOT_FIRED_BFG 1111020902
|
||||
#define QGR_KEY_HIT_GIVEN_BFG 1111020903
|
||||
#define QGR_KEY_HIT_TAKEN_BFG 1111020904
|
||||
#define QGR_KEY_DAMAGE_GIVEN_BFG 1111020905
|
||||
#define QGR_KEY_DAMAGE_TAKEN_BFG 1111020906
|
||||
#define QGR_KEY_SPLASH_GIVEN_BFG 1111020907
|
||||
#define QGR_KEY_SPLASH_TAKEN_BFG 1111020908
|
||||
#define QGR_KEY_PICKUP_BFG 1111020909
|
||||
#define QGR_KEY_TIME_BFG 1111020910
|
||||
|
||||
#define QGR_KEY_FRAG_GRAPPLE 1211021000
|
||||
#define QGR_KEY_SUICIDE_GRAPPLE 1111021001
|
||||
#define QGR_KEY_SHOT_FIRED_GRAPPLE 1111021002
|
||||
#define QGR_KEY_HIT_GIVEN_GRAPPLE 1111021003
|
||||
#define QGR_KEY_HIT_TAKEN_GRAPPLE 1111021004
|
||||
#define QGR_KEY_DAMAGE_GIVEN_GRAPPLE 1111021005
|
||||
#define QGR_KEY_DAMAGE_TAKEN_GRAPPLE 1111021006
|
||||
#define QGR_KEY_SPLASH_GIVEN_GRAPPLE 1111021007
|
||||
#define QGR_KEY_SPLASH_TAKEN_GRAPPLE 1111021008
|
||||
#define QGR_KEY_PICKUP_GRAPPLE 1111021009
|
||||
#define QGR_KEY_TIME_GRAPPLE 1111021010
|
||||
|
||||
#define QGR_KEY_FRAG_UNKNOWN 1211021100
|
||||
#define QGR_KEY_SUICIDE_UNKNOWN 1111021101
|
||||
#define QGR_KEY_SHOT_FIRED_UNKNOWN 1111021102
|
||||
#define QGR_KEY_HIT_GIVEN_UNKNOWN 1111021103
|
||||
#define QGR_KEY_HIT_TAKEN_UNKNOWN 1111021104
|
||||
#define QGR_KEY_DAMAGE_GIVEN_UNKNOWN 1111021105
|
||||
#define QGR_KEY_DAMAGE_TAKEN_UNKNOWN 1111021106
|
||||
#define QGR_KEY_SPLASH_GIVEN_UNKNOWN 1111021107
|
||||
#define QGR_KEY_SPLASH_TAKEN_UNKNOWN 1111021108
|
||||
#define QGR_KEY_PICKUP_UNKNOWN 1111021109
|
||||
#define QGR_KEY_TIME_UNKNOWN 1111021110
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
// new to team arena
|
||||
#define QGR_KEY_FRAG_NAILGIN 1211021200
|
||||
#define QGR_KEY_SUICIDE_NAILGIN 1111021201
|
||||
#define QGR_KEY_SHOT_FIRED_NAILGIN 1111021202
|
||||
#define QGR_KEY_HIT_GIVEN_NAILGIN 1111021203
|
||||
#define QGR_KEY_HIT_TAKEN_NAILGIN 1111021204
|
||||
#define QGR_KEY_DAMAGE_GIVEN_NAILGIN 1111021205
|
||||
#define QGR_KEY_DAMAGE_TAKEN_NAILGIN 1111021206
|
||||
#define QGR_KEY_SPLASH_GIVEN_NAILGIN 1111021207
|
||||
#define QGR_KEY_SPLASH_TAKEN_NAILGIN 1111021208
|
||||
#define QGR_KEY_PICKUP_NAILGIN 1111021209
|
||||
#define QGR_KEY_TIME_NAILGIN 1111021210
|
||||
// new to team arena
|
||||
#define QGR_KEY_FRAG_PROX_LAUNCHER 1211021300
|
||||
#define QGR_KEY_SUICIDE_PROX_LAUNCHER 1111021301
|
||||
#define QGR_KEY_SHOT_FIRED_PROX_LAUNCHER 1111021302
|
||||
#define QGR_KEY_HIT_GIVEN_PROX_LAUNCHER 1111021303
|
||||
#define QGR_KEY_HIT_TAKEN_PROX_LAUNCHER 1111021304
|
||||
#define QGR_KEY_DAMAGE_GIVEN_PROX_LAUNCHER 1111021305
|
||||
#define QGR_KEY_DAMAGE_TAKEN_PROX_LAUNCHER 1111021306
|
||||
#define QGR_KEY_SPLASH_GIVEN_PROX_LAUNCHER 1111021307
|
||||
#define QGR_KEY_SPLASH_TAKEN_PROX_LAUNCHER 1111021308
|
||||
#define QGR_KEY_PICKUP_PROX_LAUNCHER 1111021309
|
||||
#define QGR_KEY_TIME_PROX_LAUNCHER 1111021310
|
||||
// new to team arena
|
||||
#define QGR_KEY_FRAG_CHAINGUN 1211021400
|
||||
#define QGR_KEY_SUICIDE_CHAINGUN 1111021401
|
||||
#define QGR_KEY_SHOT_FIRED_CHAINGUN 1111021402
|
||||
#define QGR_KEY_HIT_GIVEN_CHAINGUN 1111021403
|
||||
#define QGR_KEY_HIT_TAKEN_CHAINGUN 1111021404
|
||||
#define QGR_KEY_DAMAGE_GIVEN_CHAINGUN 1111021405
|
||||
#define QGR_KEY_DAMAGE_TAKEN_CHAINGUN 1111021406
|
||||
#define QGR_KEY_SPLASH_GIVEN_CHAINGUN 1111021407
|
||||
#define QGR_KEY_SPLASH_TAKEN_CHAINGUN 1111021408
|
||||
#define QGR_KEY_PICKUP_CHAINGUN 1111021409
|
||||
#define QGR_KEY_TIME_CHAINGUN 1111021410
|
||||
#endif /* MISSIONPACK */
|
||||
|
||||
// ammo keys
|
||||
#define QGR_KEY_BOXES 1111030000
|
||||
#define QGR_KEY_ROUNDS 1111030001
|
||||
|
||||
#define QGR_KEY_BOXES_BULLETS 1111030100
|
||||
#define QGR_KEY_ROUNDS_BULLETS 1111030101
|
||||
|
||||
#define QGR_KEY_BOXES_SHELLS 1111030200
|
||||
#define QGR_KEY_ROUNDS_SHELLS 1111030201
|
||||
|
||||
#define QGR_KEY_BOXES_GRENADES 1111030300
|
||||
#define QGR_KEY_ROUNDS_GRENADES 1111030301
|
||||
|
||||
#define QGR_KEY_BOXES_ROCKETS 1111030400
|
||||
#define QGR_KEY_ROUNDS_ROCKETS 1111030401
|
||||
|
||||
#define QGR_KEY_BOXES_CELLS 1111030500
|
||||
#define QGR_KEY_ROUNDS_CELLS 1111030501
|
||||
|
||||
#define QGR_KEY_BOXES_SLUGS 1111030600
|
||||
#define QGR_KEY_ROUNDS_SLUGS 1111030601
|
||||
|
||||
#define QGR_KEY_BOXES_LG_AMMO 1111030700
|
||||
#define QGR_KEY_ROUNDS_LG_AMMO 1111030701
|
||||
|
||||
#define QGR_KEY_BOXES_BFG_AMMO 1111030800
|
||||
#define QGR_KEY_ROUNDS_BFG_AMMO 1111030801
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
// new to team arena
|
||||
#define QGR_KEY_BOXES_NAILGUN_AMMO 1111030900
|
||||
#define QGR_KEY_ROUNDS_NAILGUN_AMMO 1111030901
|
||||
// new to team arena
|
||||
#define QGR_KEY_BOXES_PROX_LAUNCHER_AMMO 1111031000
|
||||
#define QGR_KEY_ROUNDS_PROX_LAUNCHER_AMMO 1111031001
|
||||
// new to team arena
|
||||
#define QGR_KEY_BOXES_CHAINGUN_AMMO 1111031100
|
||||
#define QGR_KEY_ROUNDS_CHAINGUN_AMMO 1111031101
|
||||
#endif /* MISSIONPACK */
|
||||
|
||||
// health keys
|
||||
#define QGR_KEY_HEALTH 1111040000
|
||||
#define QGR_KEY_HEALTH_TOTAL 1111040001
|
||||
|
||||
#define QGR_KEY_HEALTH_5 1111040100
|
||||
#define QGR_KEY_HEALTH_25 1111040200
|
||||
#define QGR_KEY_HEALTH_50 1111040300
|
||||
#define QGR_KEY_HEALTH_MEGA 1111040400
|
||||
|
||||
// armor keys
|
||||
#define QGR_KEY_ARMOR 1111050000
|
||||
#define QGR_KEY_ARMOR_TOTAL 1111050001
|
||||
|
||||
#define QGR_KEY_ARMOR_SHARD 1111050100
|
||||
#define QGR_KEY_ARMOR_YELLOW 1111050200
|
||||
#define QGR_KEY_ARMOR_RED 1111050300
|
||||
|
||||
// powerup keys
|
||||
#define QGR_KEY_POWERUP 1111060000
|
||||
#define QGR_KEY_QUAD 1111060100
|
||||
#define QGR_KEY_SUIT 1111060200
|
||||
#define QGR_KEY_HASTE 1111060300
|
||||
#define QGR_KEY_INVIS 1111060400
|
||||
#define QGR_KEY_REGEN 1111060500
|
||||
#define QGR_KEY_FLIGHT 1111060600
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
// persistant powerup keys
|
||||
// new to team arena
|
||||
#define QGR_KEY_SCOUT 1111160800
|
||||
#define QGR_KEY_GUARD 1111160801
|
||||
#define QGR_KEY_DOUBLER 1111160802
|
||||
#define QGR_KEY_AMMOREGEN 1111160803
|
||||
|
||||
#endif //MISSIONPACK
|
||||
|
||||
// holdable item keys
|
||||
#define QGR_KEY_MEDKIT 1111070000
|
||||
#define QGR_KEY_MEDKIT_USE 1111070001
|
||||
|
||||
#define QGR_KEY_TELEPORTER 1111070100
|
||||
#define QGR_KEY_TELEPORTER_USE 1111070101
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
// new to team arena
|
||||
#define QGR_KEY_KAMIKAZE 1111070200
|
||||
#define QGR_KEY_KAMIKAZE_USE 1111070201
|
||||
// new to team arena
|
||||
#define QGR_KEY_PORTAL 1111070300
|
||||
#define QGR_KEY_PORTAL_USE 1111070301
|
||||
// new to team arena
|
||||
#define QGR_KEY_INVULNERABILITY 1111070400
|
||||
#define QGR_KEY_INVULNERABILITY_USE 1111070401
|
||||
#endif /* MISSIONPACK */
|
||||
|
||||
// hazard keys
|
||||
#define QGR_KEY_HAZARD_DEATH 1111080000
|
||||
#define QGR_KEY_WATER 1111080100
|
||||
#define QGR_KEY_SLIME 1111080200
|
||||
#define QGR_KEY_LAVA 1111080300
|
||||
#define QGR_KEY_CRUSH 1111080400
|
||||
#define QGR_KEY_TELEFRAG 1111080500
|
||||
#define QGR_KEY_FALLING 1111080600
|
||||
#define QGR_KEY_SUICIDE_CMD 1111080700
|
||||
#define QGR_KEY_TRIGGER_HURT 1111080800
|
||||
#define QGR_KEY_HAZARD_MISC 1111080900
|
||||
|
||||
// reward keys
|
||||
#define QGR_KEY_IMPRESSIVE 1111090000
|
||||
#define QGR_KEY_EXCELLENT 1111090100
|
||||
|
||||
// teammate keys
|
||||
#define QGR_KEY_TEAMMATE_FRAG 1211100000
|
||||
#define QGR_KEY_TEAMMATE_HIT_GIVEN 1111100001
|
||||
#define QGR_KEY_TEAMMATE_HIT_TAKEN 1111100002
|
||||
#define QGR_KEY_TEAMMATE_DAMAGE_GIVEN 1111100003
|
||||
#define QGR_KEY_TEAMMATE_DAMAGE_TAKEN 1111100004
|
||||
#define QGR_KEY_TEAMMATE_SPLASH_GIVEN 1111100005
|
||||
#define QGR_KEY_TEAMMATE_SPLASH_TAKEN 1111100006
|
||||
#define QGR_KEY_TEAM_NAME 1100100007
|
||||
|
||||
// ctf keys
|
||||
#define QGR_KEY_FLAG_PICKUP 1111110000
|
||||
#define QGR_KEY_FLAG_CAPTURE 1111110001
|
||||
|
||||
#endif // _G_RANKINGS_H_
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
#include "g_local.h"
|
||||
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
SESSION DATA
|
||||
|
||||
Session data is the only data that stays persistant across level loads
|
||||
and tournament restarts.
|
||||
=======================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
================
|
||||
G_WriteClientSessionData
|
||||
|
||||
Called on game shutdown
|
||||
================
|
||||
*/
|
||||
void G_WriteClientSessionData( gclient_t *client ) {
|
||||
const char *s;
|
||||
const char *var;
|
||||
|
||||
s = va("%i %i %i %i %i %i %i",
|
||||
client->sess.sessionTeam,
|
||||
client->sess.spectatorTime,
|
||||
client->sess.spectatorState,
|
||||
client->sess.spectatorClient,
|
||||
client->sess.wins,
|
||||
client->sess.losses,
|
||||
client->sess.teamLeader
|
||||
);
|
||||
|
||||
var = va( "session%i", client - level.clients );
|
||||
|
||||
trap_Cvar_Set( var, s );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
G_ReadSessionData
|
||||
|
||||
Called on a reconnect
|
||||
================
|
||||
*/
|
||||
void G_ReadSessionData( gclient_t *client ) {
|
||||
char s[MAX_STRING_CHARS];
|
||||
const char *var;
|
||||
|
||||
// bk001205 - format
|
||||
int teamLeader;
|
||||
int spectatorState;
|
||||
int sessionTeam;
|
||||
|
||||
var = va( "session%i", client - level.clients );
|
||||
trap_Cvar_VariableStringBuffer( var, s, sizeof(s) );
|
||||
|
||||
sscanf( s, "%i %i %i %i %i %i %i",
|
||||
&sessionTeam, // bk010221 - format
|
||||
&client->sess.spectatorTime,
|
||||
&spectatorState, // bk010221 - format
|
||||
&client->sess.spectatorClient,
|
||||
&client->sess.wins,
|
||||
&client->sess.losses,
|
||||
&teamLeader // bk010221 - format
|
||||
);
|
||||
|
||||
// bk001205 - format issues
|
||||
client->sess.sessionTeam = (team_t)sessionTeam;
|
||||
client->sess.spectatorState = (spectatorState_t)spectatorState;
|
||||
client->sess.teamLeader = (qboolean)teamLeader;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
G_InitSessionData
|
||||
|
||||
Called on a first-time connect
|
||||
================
|
||||
*/
|
||||
void G_InitSessionData( gclient_t *client, char *userinfo ) {
|
||||
clientSession_t *sess;
|
||||
const char *value;
|
||||
|
||||
sess = &client->sess;
|
||||
|
||||
// initial team determination
|
||||
if ( g_gametype.integer >= GT_TEAM ) {
|
||||
if ( g_teamAutoJoin.integer ) {
|
||||
sess->sessionTeam = PickTeam( -1 );
|
||||
BroadcastTeamChange( client, -1 );
|
||||
} else {
|
||||
// always spawn as spectator in team games
|
||||
sess->sessionTeam = TEAM_SPECTATOR;
|
||||
}
|
||||
} else {
|
||||
value = Info_ValueForKey( userinfo, "team" );
|
||||
if ( value[0] == 's' ) {
|
||||
// a willing spectator, not a waiting-in-line
|
||||
sess->sessionTeam = TEAM_SPECTATOR;
|
||||
} else {
|
||||
switch ( g_gametype.integer ) {
|
||||
default:
|
||||
case GT_FFA:
|
||||
case GT_SINGLE_PLAYER:
|
||||
if ( g_maxGameClients.integer > 0 &&
|
||||
level.numNonSpectatorClients >= g_maxGameClients.integer ) {
|
||||
sess->sessionTeam = TEAM_SPECTATOR;
|
||||
} else {
|
||||
sess->sessionTeam = TEAM_FREE;
|
||||
}
|
||||
break;
|
||||
case GT_TOURNAMENT:
|
||||
// if the game is full, go into a waiting mode
|
||||
if ( level.numNonSpectatorClients >= 2 ) {
|
||||
sess->sessionTeam = TEAM_SPECTATOR;
|
||||
} else {
|
||||
sess->sessionTeam = TEAM_FREE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sess->spectatorState = SPECTATOR_FREE;
|
||||
sess->spectatorTime = level.time;
|
||||
|
||||
G_WriteClientSessionData( client );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
G_InitWorldSession
|
||||
|
||||
==================
|
||||
*/
|
||||
void G_InitWorldSession( void ) {
|
||||
char s[MAX_STRING_CHARS];
|
||||
int gt;
|
||||
|
||||
trap_Cvar_VariableStringBuffer( "session", s, sizeof(s) );
|
||||
gt = atoi( s );
|
||||
|
||||
// if the gametype changed since the last session, don't use any
|
||||
// client sessions
|
||||
if ( g_gametype.integer != gt ) {
|
||||
level.newSession = qtrue;
|
||||
G_Printf( "Gametype changed, clearing session data.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
G_WriteSessionData
|
||||
|
||||
==================
|
||||
*/
|
||||
void G_WriteSessionData( void ) {
|
||||
int i;
|
||||
|
||||
trap_Cvar_Set( "session", va("%i", g_gametype.integer) );
|
||||
|
||||
for ( i = 0 ; i < level.maxclients ; i++ ) {
|
||||
if ( level.clients[i].pers.connected == CON_CONNECTED ) {
|
||||
G_WriteClientSessionData( &level.clients[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,643 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
qboolean G_SpawnString( const char *key, const char *defaultString, char **out ) {
|
||||
int i;
|
||||
|
||||
if ( !level.spawning ) {
|
||||
*out = (char *)defaultString;
|
||||
// G_Error( "G_SpawnString() called while not spawning" );
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < level.numSpawnVars ; i++ ) {
|
||||
if ( !Q_stricmp( key, level.spawnVars[i][0] ) ) {
|
||||
*out = level.spawnVars[i][1];
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
*out = (char *)defaultString;
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
qboolean G_SpawnFloat( const char *key, const char *defaultString, float *out ) {
|
||||
char *s;
|
||||
qboolean present;
|
||||
|
||||
present = G_SpawnString( key, defaultString, &s );
|
||||
*out = atof( s );
|
||||
return present;
|
||||
}
|
||||
|
||||
qboolean G_SpawnInt( const char *key, const char *defaultString, int *out ) {
|
||||
char *s;
|
||||
qboolean present;
|
||||
|
||||
present = G_SpawnString( key, defaultString, &s );
|
||||
*out = atoi( s );
|
||||
return present;
|
||||
}
|
||||
|
||||
qboolean G_SpawnVector( const char *key, const char *defaultString, float *out ) {
|
||||
char *s;
|
||||
qboolean present;
|
||||
|
||||
present = G_SpawnString( key, defaultString, &s );
|
||||
sscanf( s, "%f %f %f", &out[0], &out[1], &out[2] );
|
||||
return present;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// fields are needed for spawning from the entity string
|
||||
//
|
||||
typedef enum {
|
||||
F_INT,
|
||||
F_FLOAT,
|
||||
F_LSTRING, // string on disk, pointer in memory, TAG_LEVEL
|
||||
F_GSTRING, // string on disk, pointer in memory, TAG_GAME
|
||||
F_VECTOR,
|
||||
F_ANGLEHACK,
|
||||
F_ENTITY, // index on disk, pointer in memory
|
||||
F_ITEM, // index on disk, pointer in memory
|
||||
F_CLIENT, // index on disk, pointer in memory
|
||||
F_IGNORE
|
||||
} fieldtype_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
int ofs;
|
||||
fieldtype_t type;
|
||||
int flags;
|
||||
} field_t;
|
||||
|
||||
field_t fields[] = {
|
||||
{"classname", FOFS(classname), F_LSTRING},
|
||||
{"origin", FOFS(s.origin), F_VECTOR},
|
||||
{"model", FOFS(model), F_LSTRING},
|
||||
{"model2", FOFS(model2), F_LSTRING},
|
||||
{"spawnflags", FOFS(spawnflags), F_INT},
|
||||
{"speed", FOFS(speed), F_FLOAT},
|
||||
{"target", FOFS(target), F_LSTRING},
|
||||
{"targetname", FOFS(targetname), F_LSTRING},
|
||||
{"message", FOFS(message), F_LSTRING},
|
||||
{"team", FOFS(team), F_LSTRING},
|
||||
{"wait", FOFS(wait), F_FLOAT},
|
||||
{"random", FOFS(random), F_FLOAT},
|
||||
{"count", FOFS(count), F_INT},
|
||||
{"health", FOFS(health), F_INT},
|
||||
{"light", 0, F_IGNORE},
|
||||
{"dmg", FOFS(damage), F_INT},
|
||||
{"angles", FOFS(s.angles), F_VECTOR},
|
||||
{"angle", FOFS(s.angles), F_ANGLEHACK},
|
||||
{"targetShaderName", FOFS(targetShaderName), F_LSTRING},
|
||||
{"targetShaderNewName", FOFS(targetShaderNewName), F_LSTRING},
|
||||
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
void (*spawn)(gentity_t *ent);
|
||||
} spawn_t;
|
||||
|
||||
void SP_info_player_start (gentity_t *ent);
|
||||
void SP_info_player_deathmatch (gentity_t *ent);
|
||||
void SP_info_player_intermission (gentity_t *ent);
|
||||
void SP_info_firstplace(gentity_t *ent);
|
||||
void SP_info_secondplace(gentity_t *ent);
|
||||
void SP_info_thirdplace(gentity_t *ent);
|
||||
void SP_info_podium(gentity_t *ent);
|
||||
|
||||
void SP_func_plat (gentity_t *ent);
|
||||
void SP_func_static (gentity_t *ent);
|
||||
void SP_func_rotating (gentity_t *ent);
|
||||
void SP_func_bobbing (gentity_t *ent);
|
||||
void SP_func_pendulum( gentity_t *ent );
|
||||
void SP_func_button (gentity_t *ent);
|
||||
void SP_func_door (gentity_t *ent);
|
||||
void SP_func_train (gentity_t *ent);
|
||||
void SP_func_timer (gentity_t *self);
|
||||
|
||||
void SP_trigger_always (gentity_t *ent);
|
||||
void SP_trigger_multiple (gentity_t *ent);
|
||||
void SP_trigger_push (gentity_t *ent);
|
||||
void SP_trigger_teleport (gentity_t *ent);
|
||||
void SP_trigger_hurt (gentity_t *ent);
|
||||
|
||||
void SP_target_remove_powerups( gentity_t *ent );
|
||||
void SP_target_give (gentity_t *ent);
|
||||
void SP_target_delay (gentity_t *ent);
|
||||
void SP_target_speaker (gentity_t *ent);
|
||||
void SP_target_print (gentity_t *ent);
|
||||
void SP_target_laser (gentity_t *self);
|
||||
void SP_target_character (gentity_t *ent);
|
||||
void SP_target_score( gentity_t *ent );
|
||||
void SP_target_teleporter( gentity_t *ent );
|
||||
void SP_target_relay (gentity_t *ent);
|
||||
void SP_target_kill (gentity_t *ent);
|
||||
void SP_target_position (gentity_t *ent);
|
||||
void SP_target_location (gentity_t *ent);
|
||||
void SP_target_push (gentity_t *ent);
|
||||
|
||||
void SP_light (gentity_t *self);
|
||||
void SP_info_null (gentity_t *self);
|
||||
void SP_info_notnull (gentity_t *self);
|
||||
void SP_info_camp (gentity_t *self);
|
||||
void SP_path_corner (gentity_t *self);
|
||||
|
||||
void SP_misc_teleporter_dest (gentity_t *self);
|
||||
void SP_misc_model(gentity_t *ent);
|
||||
void SP_misc_portal_camera(gentity_t *ent);
|
||||
void SP_misc_portal_surface(gentity_t *ent);
|
||||
|
||||
void SP_shooter_rocket( gentity_t *ent );
|
||||
void SP_shooter_plasma( gentity_t *ent );
|
||||
void SP_shooter_grenade( gentity_t *ent );
|
||||
|
||||
void SP_team_CTF_redplayer( gentity_t *ent );
|
||||
void SP_team_CTF_blueplayer( gentity_t *ent );
|
||||
|
||||
void SP_team_CTF_redspawn( gentity_t *ent );
|
||||
void SP_team_CTF_bluespawn( gentity_t *ent );
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
void SP_team_blueobelisk( gentity_t *ent );
|
||||
void SP_team_redobelisk( gentity_t *ent );
|
||||
void SP_team_neutralobelisk( gentity_t *ent );
|
||||
#endif
|
||||
void SP_item_botroam( gentity_t *ent ) {};
|
||||
|
||||
spawn_t spawns[] = {
|
||||
// info entities don't do anything at all, but provide positional
|
||||
// information for things controlled by other processes
|
||||
{"info_player_start", SP_info_player_start},
|
||||
{"info_player_deathmatch", SP_info_player_deathmatch},
|
||||
{"info_player_intermission", SP_info_player_intermission},
|
||||
{"info_null", SP_info_null},
|
||||
{"info_notnull", SP_info_notnull}, // use target_position instead
|
||||
{"info_camp", SP_info_camp},
|
||||
|
||||
{"func_plat", SP_func_plat},
|
||||
{"func_button", SP_func_button},
|
||||
{"func_door", SP_func_door},
|
||||
{"func_static", SP_func_static},
|
||||
{"func_rotating", SP_func_rotating},
|
||||
{"func_bobbing", SP_func_bobbing},
|
||||
{"func_pendulum", SP_func_pendulum},
|
||||
{"func_train", SP_func_train},
|
||||
{"func_group", SP_info_null},
|
||||
{"func_timer", SP_func_timer}, // rename trigger_timer?
|
||||
|
||||
// Triggers are brush objects that cause an effect when contacted
|
||||
// by a living player, usually involving firing targets.
|
||||
// While almost everything could be done with
|
||||
// a single trigger class and different targets, triggered effects
|
||||
// could not be client side predicted (push and teleport).
|
||||
{"trigger_always", SP_trigger_always},
|
||||
{"trigger_multiple", SP_trigger_multiple},
|
||||
{"trigger_push", SP_trigger_push},
|
||||
{"trigger_teleport", SP_trigger_teleport},
|
||||
{"trigger_hurt", SP_trigger_hurt},
|
||||
|
||||
// targets perform no action by themselves, but must be triggered
|
||||
// by another entity
|
||||
{"target_give", SP_target_give},
|
||||
{"target_remove_powerups", SP_target_remove_powerups},
|
||||
{"target_delay", SP_target_delay},
|
||||
{"target_speaker", SP_target_speaker},
|
||||
{"target_print", SP_target_print},
|
||||
{"target_laser", SP_target_laser},
|
||||
{"target_score", SP_target_score},
|
||||
{"target_teleporter", SP_target_teleporter},
|
||||
{"target_relay", SP_target_relay},
|
||||
{"target_kill", SP_target_kill},
|
||||
{"target_position", SP_target_position},
|
||||
{"target_location", SP_target_location},
|
||||
{"target_push", SP_target_push},
|
||||
|
||||
{"light", SP_light},
|
||||
{"path_corner", SP_path_corner},
|
||||
|
||||
{"misc_teleporter_dest", SP_misc_teleporter_dest},
|
||||
{"misc_model", SP_misc_model},
|
||||
{"misc_portal_surface", SP_misc_portal_surface},
|
||||
{"misc_portal_camera", SP_misc_portal_camera},
|
||||
|
||||
{"shooter_rocket", SP_shooter_rocket},
|
||||
{"shooter_grenade", SP_shooter_grenade},
|
||||
{"shooter_plasma", SP_shooter_plasma},
|
||||
|
||||
{"team_CTF_redplayer", SP_team_CTF_redplayer},
|
||||
{"team_CTF_blueplayer", SP_team_CTF_blueplayer},
|
||||
|
||||
{"team_CTF_redspawn", SP_team_CTF_redspawn},
|
||||
{"team_CTF_bluespawn", SP_team_CTF_bluespawn},
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
{"team_redobelisk", SP_team_redobelisk},
|
||||
{"team_blueobelisk", SP_team_blueobelisk},
|
||||
{"team_neutralobelisk", SP_team_neutralobelisk},
|
||||
#endif
|
||||
{"item_botroam", SP_item_botroam},
|
||||
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
===============
|
||||
G_CallSpawn
|
||||
|
||||
Finds the spawn function for the entity and calls it,
|
||||
returning qfalse if not found
|
||||
===============
|
||||
*/
|
||||
qboolean G_CallSpawn( gentity_t *ent ) {
|
||||
spawn_t *s;
|
||||
gitem_t *item;
|
||||
|
||||
if ( !ent->classname ) {
|
||||
G_Printf ("G_CallSpawn: NULL classname\n");
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// check item spawn functions
|
||||
for ( item=bg_itemlist+1 ; item->classname ; item++ ) {
|
||||
if ( !strcmp(item->classname, ent->classname) ) {
|
||||
G_SpawnItem( ent, item );
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
// check normal spawn functions
|
||||
for ( s=spawns ; s->name ; s++ ) {
|
||||
if ( !strcmp(s->name, ent->classname) ) {
|
||||
// found it
|
||||
s->spawn(ent);
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
G_Printf ("%s doesn't have a spawn function\n", ent->classname);
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
G_NewString
|
||||
|
||||
Builds a copy of the string, translating \n to real linefeeds
|
||||
so message texts can be multi-line
|
||||
=============
|
||||
*/
|
||||
char *G_NewString( const char *string ) {
|
||||
char *newb, *new_p;
|
||||
int i,l;
|
||||
|
||||
l = strlen(string) + 1;
|
||||
|
||||
newb = G_Alloc( l );
|
||||
|
||||
new_p = newb;
|
||||
|
||||
// turn \n into a real linefeed
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
G_ParseField
|
||||
|
||||
Takes a key/value pair and sets the binary values
|
||||
in a gentity
|
||||
===============
|
||||
*/
|
||||
void G_ParseField( const char *key, const char *value, gentity_t *ent ) {
|
||||
field_t *f;
|
||||
byte *b;
|
||||
float v;
|
||||
vec3_t vec;
|
||||
|
||||
for ( f=fields ; f->name ; f++ ) {
|
||||
if ( !Q_stricmp(f->name, key) ) {
|
||||
// found it
|
||||
b = (byte *)ent;
|
||||
|
||||
switch( f->type ) {
|
||||
case F_LSTRING:
|
||||
*(char **)(b+f->ofs) = G_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;
|
||||
default:
|
||||
case F_IGNORE:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
G_SpawnGEntityFromSpawnVars
|
||||
|
||||
Spawn an entity and fill in all of the level fields from
|
||||
level.spawnVars[], then call the class specfic spawn function
|
||||
===================
|
||||
*/
|
||||
void G_SpawnGEntityFromSpawnVars( void ) {
|
||||
int i;
|
||||
gentity_t *ent;
|
||||
char *s, *value, *gametypeName;
|
||||
static char *gametypeNames[] = {"ffa", "tournament", "single", "team", "ctf", "oneflag", "obelisk", "harvester", "teamtournament"};
|
||||
|
||||
// get the next free entity
|
||||
ent = G_Spawn();
|
||||
|
||||
for ( i = 0 ; i < level.numSpawnVars ; i++ ) {
|
||||
G_ParseField( level.spawnVars[i][0], level.spawnVars[i][1], ent );
|
||||
}
|
||||
|
||||
// check for "notsingle" flag
|
||||
if ( g_gametype.integer == GT_SINGLE_PLAYER ) {
|
||||
G_SpawnInt( "notsingle", "0", &i );
|
||||
if ( i ) {
|
||||
G_FreeEntity( ent );
|
||||
return;
|
||||
}
|
||||
}
|
||||
// check for "notteam" flag (GT_FFA, GT_TOURNAMENT, GT_SINGLE_PLAYER)
|
||||
if ( g_gametype.integer >= GT_TEAM ) {
|
||||
G_SpawnInt( "notteam", "0", &i );
|
||||
if ( i ) {
|
||||
G_FreeEntity( ent );
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
G_SpawnInt( "notfree", "0", &i );
|
||||
if ( i ) {
|
||||
G_FreeEntity( ent );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
G_SpawnInt( "notta", "0", &i );
|
||||
if ( i ) {
|
||||
G_FreeEntity( ent );
|
||||
return;
|
||||
}
|
||||
#else
|
||||
G_SpawnInt( "notq3a", "0", &i );
|
||||
if ( i ) {
|
||||
G_FreeEntity( ent );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( G_SpawnString( "gametype", NULL, &value ) ) {
|
||||
if( g_gametype.integer >= GT_FFA && g_gametype.integer < GT_MAX_GAME_TYPE ) {
|
||||
gametypeName = gametypeNames[g_gametype.integer];
|
||||
|
||||
s = strstr( value, gametypeName );
|
||||
if( !s ) {
|
||||
G_FreeEntity( ent );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move editor origin to pos
|
||||
VectorCopy( ent->s.origin, ent->s.pos.trBase );
|
||||
VectorCopy( ent->s.origin, ent->r.currentOrigin );
|
||||
|
||||
// if we didn't get a classname, don't bother spawning anything
|
||||
if ( !G_CallSpawn( ent ) ) {
|
||||
G_FreeEntity( ent );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
G_AddSpawnVarToken
|
||||
====================
|
||||
*/
|
||||
char *G_AddSpawnVarToken( const char *string ) {
|
||||
int l;
|
||||
char *dest;
|
||||
|
||||
l = strlen( string );
|
||||
if ( level.numSpawnVarChars + l + 1 > MAX_SPAWN_VARS_CHARS ) {
|
||||
G_Error( "G_AddSpawnVarToken: MAX_SPAWN_CHARS" );
|
||||
}
|
||||
|
||||
dest = level.spawnVarChars + level.numSpawnVarChars;
|
||||
memcpy( dest, string, l+1 );
|
||||
|
||||
level.numSpawnVarChars += l + 1;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
G_ParseSpawnVars
|
||||
|
||||
Parses a brace bounded set of key / value pairs out of the
|
||||
level's entity strings into level.spawnVars[]
|
||||
|
||||
This does not actually spawn an entity.
|
||||
====================
|
||||
*/
|
||||
qboolean G_ParseSpawnVars( void ) {
|
||||
char keyname[MAX_TOKEN_CHARS];
|
||||
char com_token[MAX_TOKEN_CHARS];
|
||||
|
||||
level.numSpawnVars = 0;
|
||||
level.numSpawnVarChars = 0;
|
||||
|
||||
// parse the opening brace
|
||||
if ( !trap_GetEntityToken( com_token, sizeof( com_token ) ) ) {
|
||||
// end of spawn string
|
||||
return qfalse;
|
||||
}
|
||||
if ( com_token[0] != '{' ) {
|
||||
G_Error( "G_ParseSpawnVars: found %s when expecting {",com_token );
|
||||
}
|
||||
|
||||
// go through all the key / value pairs
|
||||
while ( 1 ) {
|
||||
// parse key
|
||||
if ( !trap_GetEntityToken( keyname, sizeof( keyname ) ) ) {
|
||||
G_Error( "G_ParseSpawnVars: EOF without closing brace" );
|
||||
}
|
||||
|
||||
if ( keyname[0] == '}' ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// parse value
|
||||
if ( !trap_GetEntityToken( com_token, sizeof( com_token ) ) ) {
|
||||
G_Error( "G_ParseSpawnVars: EOF without closing brace" );
|
||||
}
|
||||
|
||||
if ( com_token[0] == '}' ) {
|
||||
G_Error( "G_ParseSpawnVars: closing brace without data" );
|
||||
}
|
||||
if ( level.numSpawnVars == MAX_SPAWN_VARS ) {
|
||||
G_Error( "G_ParseSpawnVars: MAX_SPAWN_VARS" );
|
||||
}
|
||||
level.spawnVars[ level.numSpawnVars ][0] = G_AddSpawnVarToken( keyname );
|
||||
level.spawnVars[ level.numSpawnVars ][1] = G_AddSpawnVarToken( com_token );
|
||||
level.numSpawnVars++;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*QUAKED worldspawn (0 0 0) ?
|
||||
|
||||
Every map should have exactly one worldspawn.
|
||||
"music" music wav file
|
||||
"gravity" 800 is default gravity
|
||||
"message" Text to print during connection process
|
||||
*/
|
||||
void SP_worldspawn( void ) {
|
||||
char *s;
|
||||
|
||||
G_SpawnString( "classname", "", &s );
|
||||
if ( Q_stricmp( s, "worldspawn" ) ) {
|
||||
G_Error( "SP_worldspawn: The first entity isn't 'worldspawn'" );
|
||||
}
|
||||
|
||||
// make some data visible to connecting client
|
||||
trap_SetConfigstring( CS_GAME_VERSION, GAME_VERSION );
|
||||
|
||||
trap_SetConfigstring( CS_LEVEL_START_TIME, va("%i", level.startTime ) );
|
||||
|
||||
G_SpawnString( "music", "", &s );
|
||||
trap_SetConfigstring( CS_MUSIC, s );
|
||||
|
||||
G_SpawnString( "message", "", &s );
|
||||
trap_SetConfigstring( CS_MESSAGE, s ); // map specific message
|
||||
|
||||
trap_SetConfigstring( CS_MOTD, g_motd.string ); // message of the day
|
||||
|
||||
G_SpawnString( "gravity", "800", &s );
|
||||
trap_Cvar_Set( "g_gravity", s );
|
||||
|
||||
G_SpawnString( "enableDust", "0", &s );
|
||||
trap_Cvar_Set( "g_enableDust", s );
|
||||
|
||||
G_SpawnString( "enableBreath", "0", &s );
|
||||
trap_Cvar_Set( "g_enableBreath", s );
|
||||
|
||||
g_entities[ENTITYNUM_WORLD].s.number = ENTITYNUM_WORLD;
|
||||
g_entities[ENTITYNUM_WORLD].classname = "worldspawn";
|
||||
|
||||
// see if we want a warmup time
|
||||
trap_SetConfigstring( CS_WARMUP, "" );
|
||||
if ( g_restarted.integer ) {
|
||||
trap_Cvar_Set( "g_restarted", "0" );
|
||||
level.warmupTime = 0;
|
||||
} else if ( g_doWarmup.integer ) { // Turn it on
|
||||
level.warmupTime = -1;
|
||||
trap_SetConfigstring( CS_WARMUP, va("%i", level.warmupTime) );
|
||||
G_LogPrintf( "Warmup:\n" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
G_SpawnEntitiesFromString
|
||||
|
||||
Parses textual entity definitions out of an entstring and spawns gentities.
|
||||
==============
|
||||
*/
|
||||
void G_SpawnEntitiesFromString( void ) {
|
||||
// allow calls to G_Spawn*()
|
||||
level.spawning = qtrue;
|
||||
level.numSpawnVars = 0;
|
||||
|
||||
// the worldspawn is not an actual entity, but it still
|
||||
// has a "spawn" function to perform any global setup
|
||||
// needed by a level (setting configstrings or cvars, etc)
|
||||
if ( !G_ParseSpawnVars() ) {
|
||||
G_Error( "SpawnEntities: no entities" );
|
||||
}
|
||||
SP_worldspawn();
|
||||
|
||||
// parse ents
|
||||
while( G_ParseSpawnVars() ) {
|
||||
G_SpawnGEntityFromSpawnVars();
|
||||
}
|
||||
|
||||
level.spawning = qfalse; // any future calls to G_Spawn*() will be errors
|
||||
}
|
||||
|
||||
@@ -0,0 +1,508 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
// this file holds commands that can be executed by the server console, but not remote clients
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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 you can use '*' to 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.
|
||||
|
||||
g_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.
|
||||
|
||||
TTimo NOTE: for persistence, bans are stored in g_banIPs cvar MAX_CVAR_VALUE_STRING
|
||||
The size of the cvar string buffer is limiting the banning to around 20 masks
|
||||
this could be improved by putting some g_banIPs2 g_banIps3 etc. maybe
|
||||
still, you should rely on PB for banning instead
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
typedef struct ipFilter_s
|
||||
{
|
||||
unsigned mask;
|
||||
unsigned compare;
|
||||
} ipFilter_t;
|
||||
|
||||
#define MAX_IPFILTERS 1024
|
||||
|
||||
static ipFilter_t ipFilters[MAX_IPFILTERS];
|
||||
static 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')
|
||||
{
|
||||
if (*s == '*') // 'match any'
|
||||
{
|
||||
// b[i] and m[i] to 0
|
||||
s++;
|
||||
if (!*s)
|
||||
break;
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
G_Printf( "Bad filter address: %s\n", s );
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
while (*s >= '0' && *s <= '9')
|
||||
{
|
||||
num[j++] = *s++;
|
||||
}
|
||||
num[j] = 0;
|
||||
b[i] = atoi(num);
|
||||
m[i] = 255;
|
||||
|
||||
if (!*s)
|
||||
break;
|
||||
s++;
|
||||
}
|
||||
|
||||
f->mask = *(unsigned *)m;
|
||||
f->compare = *(unsigned *)b;
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
UpdateIPBans
|
||||
=================
|
||||
*/
|
||||
static void UpdateIPBans (void)
|
||||
{
|
||||
byte b[4];
|
||||
byte m[4];
|
||||
int i,j;
|
||||
char iplist_final[MAX_CVAR_VALUE_STRING];
|
||||
char ip[64];
|
||||
|
||||
*iplist_final = 0;
|
||||
for (i = 0 ; i < numIPFilters ; i++)
|
||||
{
|
||||
if (ipFilters[i].compare == 0xffffffff)
|
||||
continue;
|
||||
|
||||
*(unsigned *)b = ipFilters[i].compare;
|
||||
*(unsigned *)m = ipFilters[i].mask;
|
||||
*ip = 0;
|
||||
for (j = 0 ; j < 4 ; j++)
|
||||
{
|
||||
if (m[j]!=255)
|
||||
Q_strcat(ip, sizeof(ip), "*");
|
||||
else
|
||||
Q_strcat(ip, sizeof(ip), va("%i", b[j]));
|
||||
Q_strcat(ip, sizeof(ip), (j<3) ? "." : " ");
|
||||
}
|
||||
if (strlen(iplist_final)+strlen(ip) < MAX_CVAR_VALUE_STRING)
|
||||
{
|
||||
Q_strcat( iplist_final, sizeof(iplist_final), ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf("g_banIPs overflowed at MAX_CVAR_VALUE_STRING\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
trap_Cvar_Set( "g_banIPs", iplist_final );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
G_FilterPacket
|
||||
=================
|
||||
*/
|
||||
qboolean G_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 g_filterBan.integer != 0;
|
||||
|
||||
return g_filterBan.integer == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
AddIP
|
||||
=================
|
||||
*/
|
||||
static void AddIP( char *str )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < numIPFilters ; i++)
|
||||
if (ipFilters[i].compare == 0xffffffff)
|
||||
break; // free spot
|
||||
if (i == numIPFilters)
|
||||
{
|
||||
if (numIPFilters == MAX_IPFILTERS)
|
||||
{
|
||||
G_Printf ("IP filter list is full\n");
|
||||
return;
|
||||
}
|
||||
numIPFilters++;
|
||||
}
|
||||
|
||||
if (!StringToFilter (str, &ipFilters[i]))
|
||||
ipFilters[i].compare = 0xffffffffu;
|
||||
|
||||
UpdateIPBans();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
G_ProcessIPBans
|
||||
=================
|
||||
*/
|
||||
void G_ProcessIPBans(void)
|
||||
{
|
||||
char *s, *t;
|
||||
char str[MAX_CVAR_VALUE_STRING];
|
||||
|
||||
Q_strncpyz( str, g_banIPs.string, sizeof(str) );
|
||||
|
||||
for (t = s = g_banIPs.string; *t; /* */ ) {
|
||||
s = strchr(s, ' ');
|
||||
if (!s)
|
||||
break;
|
||||
while (*s == ' ')
|
||||
*s++ = 0;
|
||||
if (*t)
|
||||
AddIP( t );
|
||||
t = s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Svcmd_AddIP_f
|
||||
=================
|
||||
*/
|
||||
void Svcmd_AddIP_f (void)
|
||||
{
|
||||
char str[MAX_TOKEN_CHARS];
|
||||
|
||||
if ( trap_Argc() < 2 ) {
|
||||
G_Printf("Usage: addip <ip-mask>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
trap_Argv( 1, str, sizeof( str ) );
|
||||
|
||||
AddIP( str );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Svcmd_RemoveIP_f
|
||||
=================
|
||||
*/
|
||||
void Svcmd_RemoveIP_f (void)
|
||||
{
|
||||
ipFilter_t f;
|
||||
int i;
|
||||
char str[MAX_TOKEN_CHARS];
|
||||
|
||||
if ( trap_Argc() < 2 ) {
|
||||
G_Printf("Usage: sv removeip <ip-mask>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
trap_Argv( 1, str, sizeof( str ) );
|
||||
|
||||
if (!StringToFilter (str, &f))
|
||||
return;
|
||||
|
||||
for (i=0 ; i<numIPFilters ; i++) {
|
||||
if (ipFilters[i].mask == f.mask &&
|
||||
ipFilters[i].compare == f.compare) {
|
||||
ipFilters[i].compare = 0xffffffffu;
|
||||
G_Printf ("Removed.\n");
|
||||
|
||||
UpdateIPBans();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
G_Printf ( "Didn't find %s.\n", str );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Svcmd_EntityList_f
|
||||
===================
|
||||
*/
|
||||
void Svcmd_EntityList_f (void) {
|
||||
int e;
|
||||
gentity_t *check;
|
||||
|
||||
check = g_entities+1;
|
||||
for (e = 1; e < level.num_entities ; e++, check++) {
|
||||
if ( !check->inuse ) {
|
||||
continue;
|
||||
}
|
||||
G_Printf("%3i:", e);
|
||||
switch ( check->s.eType ) {
|
||||
case ET_GENERAL:
|
||||
G_Printf("ET_GENERAL ");
|
||||
break;
|
||||
case ET_PLAYER:
|
||||
G_Printf("ET_PLAYER ");
|
||||
break;
|
||||
case ET_ITEM:
|
||||
G_Printf("ET_ITEM ");
|
||||
break;
|
||||
case ET_MISSILE:
|
||||
G_Printf("ET_MISSILE ");
|
||||
break;
|
||||
case ET_MOVER:
|
||||
G_Printf("ET_MOVER ");
|
||||
break;
|
||||
case ET_BEAM:
|
||||
G_Printf("ET_BEAM ");
|
||||
break;
|
||||
case ET_PORTAL:
|
||||
G_Printf("ET_PORTAL ");
|
||||
break;
|
||||
case ET_SPEAKER:
|
||||
G_Printf("ET_SPEAKER ");
|
||||
break;
|
||||
case ET_PUSH_TRIGGER:
|
||||
G_Printf("ET_PUSH_TRIGGER ");
|
||||
break;
|
||||
case ET_TELEPORT_TRIGGER:
|
||||
G_Printf("ET_TELEPORT_TRIGGER ");
|
||||
break;
|
||||
case ET_INVISIBLE:
|
||||
G_Printf("ET_INVISIBLE ");
|
||||
break;
|
||||
case ET_GRAPPLE:
|
||||
G_Printf("ET_GRAPPLE ");
|
||||
break;
|
||||
default:
|
||||
G_Printf("%3i ", check->s.eType);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( check->classname ) {
|
||||
G_Printf("%s", check->classname);
|
||||
}
|
||||
G_Printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
gclient_t *ClientForString( const char *s ) {
|
||||
gclient_t *cl;
|
||||
int i;
|
||||
int idnum;
|
||||
|
||||
// numeric values are just slot numbers
|
||||
if ( s[0] >= '0' && s[0] <= '9' ) {
|
||||
idnum = atoi( s );
|
||||
if ( idnum < 0 || idnum >= level.maxclients ) {
|
||||
Com_Printf( "Bad client slot: %i\n", idnum );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cl = &level.clients[idnum];
|
||||
if ( cl->pers.connected == CON_DISCONNECTED ) {
|
||||
G_Printf( "Client %i is not connected\n", idnum );
|
||||
return NULL;
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
// check for a name match
|
||||
for ( i=0 ; i < level.maxclients ; i++ ) {
|
||||
cl = &level.clients[i];
|
||||
if ( cl->pers.connected == CON_DISCONNECTED ) {
|
||||
continue;
|
||||
}
|
||||
if ( !Q_stricmp( cl->pers.netname, s ) ) {
|
||||
return cl;
|
||||
}
|
||||
}
|
||||
|
||||
G_Printf( "User %s is not on the server\n", s );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Svcmd_ForceTeam_f
|
||||
|
||||
forceteam <player> <team>
|
||||
===================
|
||||
*/
|
||||
void Svcmd_ForceTeam_f( void ) {
|
||||
gclient_t *cl;
|
||||
char str[MAX_TOKEN_CHARS];
|
||||
|
||||
// find the player
|
||||
trap_Argv( 1, str, sizeof( str ) );
|
||||
cl = ClientForString( str );
|
||||
if ( !cl ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set the team
|
||||
trap_Argv( 2, str, sizeof( str ) );
|
||||
SetTeam( &g_entities[cl - level.clients], str );
|
||||
}
|
||||
|
||||
char *ConcatArgs( int start );
|
||||
|
||||
/*
|
||||
=================
|
||||
ConsoleCommand
|
||||
|
||||
=================
|
||||
*/
|
||||
qboolean ConsoleCommand( void ) {
|
||||
char cmd[MAX_TOKEN_CHARS];
|
||||
|
||||
trap_Argv( 0, cmd, sizeof( cmd ) );
|
||||
|
||||
if ( Q_stricmp (cmd, "entitylist") == 0 ) {
|
||||
Svcmd_EntityList_f();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if ( Q_stricmp (cmd, "forceteam") == 0 ) {
|
||||
Svcmd_ForceTeam_f();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (Q_stricmp (cmd, "game_memory") == 0) {
|
||||
Svcmd_GameMem_f();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (Q_stricmp (cmd, "addbot") == 0) {
|
||||
Svcmd_AddBot_f();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (Q_stricmp (cmd, "botlist") == 0) {
|
||||
Svcmd_BotList_f();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (Q_stricmp (cmd, "abort_podium") == 0) {
|
||||
Svcmd_AbortPodium_f();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (Q_stricmp (cmd, "addip") == 0) {
|
||||
Svcmd_AddIP_f();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (Q_stricmp (cmd, "removeip") == 0) {
|
||||
Svcmd_RemoveIP_f();
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (Q_stricmp (cmd, "listip") == 0) {
|
||||
trap_SendConsoleCommand( EXEC_NOW, "g_banIPs\n" );
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if (g_dedicated.integer) {
|
||||
if (Q_stricmp (cmd, "say") == 0) {
|
||||
trap_SendServerCommand( -1, va("print \"server: %s\"", ConcatArgs(1) ) );
|
||||
return qtrue;
|
||||
}
|
||||
// everything else will also be printed as a say command
|
||||
trap_SendServerCommand( -1, va("print \"server: %s\"", ConcatArgs(0) ) );
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
code
|
||||
|
||||
equ trap_Printf -1
|
||||
equ trap_Error -2
|
||||
equ trap_Milliseconds -3
|
||||
equ trap_Cvar_Register -4
|
||||
equ trap_Cvar_Update -5
|
||||
equ trap_Cvar_Set -6
|
||||
equ trap_Cvar_VariableIntegerValue -7
|
||||
equ trap_Cvar_VariableStringBuffer -8
|
||||
equ trap_Argc -9
|
||||
equ trap_Argv -10
|
||||
equ trap_FS_FOpenFile -11
|
||||
equ trap_FS_Read -12
|
||||
equ trap_FS_Write -13
|
||||
equ trap_FS_FCloseFile -14
|
||||
equ trap_SendConsoleCommand -15
|
||||
equ trap_LocateGameData -16
|
||||
equ trap_DropClient -17
|
||||
equ trap_SendServerCommand -18
|
||||
equ trap_SetConfigstring -19
|
||||
equ trap_GetConfigstring -20
|
||||
equ trap_GetUserinfo -21
|
||||
equ trap_SetUserinfo -22
|
||||
equ trap_GetServerinfo -23
|
||||
equ trap_SetBrushModel -24
|
||||
equ trap_Trace -25
|
||||
equ trap_PointContents -26
|
||||
equ trap_InPVS -27
|
||||
equ trap_InPVSIgnorePortals -28
|
||||
equ trap_AdjustAreaPortalState -29
|
||||
equ trap_AreasConnected -30
|
||||
equ trap_LinkEntity -31
|
||||
equ trap_UnlinkEntity -32
|
||||
equ trap_EntitiesInBox -33
|
||||
equ trap_EntityContact -34
|
||||
equ trap_BotAllocateClient -35
|
||||
equ trap_BotFreeClient -36
|
||||
equ trap_GetUsercmd -37
|
||||
equ trap_GetEntityToken -38
|
||||
equ trap_FS_GetFileList -39
|
||||
equ trap_DebugPolygonCreate -40
|
||||
equ trap_DebugPolygonDelete -41
|
||||
equ trap_RealTime -42
|
||||
equ trap_SnapVector -43
|
||||
equ trap_TraceCapsule -44
|
||||
equ trap_EntityContactCapsule -45
|
||||
equ trap_FS_Seek -46
|
||||
|
||||
equ memset -101
|
||||
equ memcpy -102
|
||||
equ strncpy -103
|
||||
equ sin -104
|
||||
equ cos -105
|
||||
equ atan2 -106
|
||||
equ sqrt -107
|
||||
equ floor -111
|
||||
equ ceil -112
|
||||
equ testPrintInt -113
|
||||
equ testPrintFloat -114
|
||||
|
||||
|
||||
|
||||
equ trap_BotLibSetup -201
|
||||
equ trap_BotLibShutdown -202
|
||||
equ trap_BotLibVarSet -203
|
||||
equ trap_BotLibVarGet -204
|
||||
equ trap_BotLibDefine -205
|
||||
equ trap_BotLibStartFrame -206
|
||||
equ trap_BotLibLoadMap -207
|
||||
equ trap_BotLibUpdateEntity -208
|
||||
equ trap_BotLibTest -209
|
||||
|
||||
equ trap_BotGetSnapshotEntity -210
|
||||
equ trap_BotGetServerCommand -211
|
||||
equ trap_BotUserCommand -212
|
||||
|
||||
|
||||
|
||||
equ trap_AAS_EnableRoutingArea -301
|
||||
equ trap_AAS_BBoxAreas -302
|
||||
equ trap_AAS_AreaInfo -303
|
||||
equ trap_AAS_EntityInfo -304
|
||||
|
||||
equ trap_AAS_Initialized -305
|
||||
equ trap_AAS_PresenceTypeBoundingBox -306
|
||||
equ trap_AAS_Time -307
|
||||
|
||||
equ trap_AAS_PointAreaNum -308
|
||||
equ trap_AAS_TraceAreas -309
|
||||
|
||||
equ trap_AAS_PointContents -310
|
||||
equ trap_AAS_NextBSPEntity -311
|
||||
equ trap_AAS_ValueForBSPEpairKey -312
|
||||
equ trap_AAS_VectorForBSPEpairKey -313
|
||||
equ trap_AAS_FloatForBSPEpairKey -314
|
||||
equ trap_AAS_IntForBSPEpairKey -315
|
||||
|
||||
equ trap_AAS_AreaReachability -316
|
||||
|
||||
equ trap_AAS_AreaTravelTimeToGoalArea -317
|
||||
|
||||
equ trap_AAS_Swimming -318
|
||||
equ trap_AAS_PredictClientMovement -319
|
||||
|
||||
|
||||
|
||||
equ trap_EA_Say -401
|
||||
equ trap_EA_SayTeam -402
|
||||
equ trap_EA_Command -403
|
||||
|
||||
equ trap_EA_Action -404
|
||||
equ trap_EA_Gesture -405
|
||||
equ trap_EA_Talk -406
|
||||
equ trap_EA_Attack -407
|
||||
equ trap_EA_Use -408
|
||||
equ trap_EA_Respawn -409
|
||||
equ trap_EA_Crouch -410
|
||||
equ trap_EA_MoveUp -411
|
||||
equ trap_EA_MoveDown -412
|
||||
equ trap_EA_MoveForward -413
|
||||
equ trap_EA_MoveBack -414
|
||||
equ trap_EA_MoveLeft -415
|
||||
equ trap_EA_MoveRight -416
|
||||
|
||||
equ trap_EA_SelectWeapon -417
|
||||
equ trap_EA_Jump -418
|
||||
equ trap_EA_DelayedJump -419
|
||||
equ trap_EA_Move -420
|
||||
equ trap_EA_View -421
|
||||
|
||||
equ trap_EA_EndRegular -422
|
||||
equ trap_EA_GetInput -423
|
||||
equ trap_EA_ResetInput -424
|
||||
|
||||
|
||||
|
||||
equ trap_BotLoadCharacter -501
|
||||
equ trap_BotFreeCharacter -502
|
||||
equ trap_Characteristic_Float -503
|
||||
equ trap_Characteristic_BFloat -504
|
||||
equ trap_Characteristic_Integer -505
|
||||
equ trap_Characteristic_BInteger -506
|
||||
equ trap_Characteristic_String -507
|
||||
|
||||
equ trap_BotAllocChatState -508
|
||||
equ trap_BotFreeChatState -509
|
||||
equ trap_BotQueueConsoleMessage -510
|
||||
equ trap_BotRemoveConsoleMessage -511
|
||||
equ trap_BotNextConsoleMessage -512
|
||||
equ trap_BotNumConsoleMessages -513
|
||||
equ trap_BotInitialChat -514
|
||||
equ trap_BotReplyChat -515
|
||||
equ trap_BotChatLength -516
|
||||
equ trap_BotEnterChat -517
|
||||
equ trap_StringContains -518
|
||||
equ trap_BotFindMatch -519
|
||||
equ trap_BotMatchVariable -520
|
||||
equ trap_UnifyWhiteSpaces -521
|
||||
equ trap_BotReplaceSynonyms -522
|
||||
equ trap_BotLoadChatFile -523
|
||||
equ trap_BotSetChatGender -524
|
||||
equ trap_BotSetChatName -525
|
||||
|
||||
equ trap_BotResetGoalState -526
|
||||
equ trap_BotResetAvoidGoals -527
|
||||
equ trap_BotPushGoal -528
|
||||
equ trap_BotPopGoal -529
|
||||
equ trap_BotEmptyGoalStack -530
|
||||
equ trap_BotDumpAvoidGoals -531
|
||||
equ trap_BotDumpGoalStack -532
|
||||
equ trap_BotGoalName -533
|
||||
equ trap_BotGetTopGoal -534
|
||||
equ trap_BotGetSecondGoal -535
|
||||
equ trap_BotChooseLTGItem -536
|
||||
equ trap_BotChooseNBGItem -537
|
||||
equ trap_BotTouchingGoal -538
|
||||
equ trap_BotItemGoalInVisButNotVisible -539
|
||||
equ trap_BotGetLevelItemGoal -540
|
||||
equ trap_BotAvoidGoalTime -541
|
||||
equ trap_BotInitLevelItems -542
|
||||
equ trap_BotUpdateEntityItems -543
|
||||
equ trap_BotLoadItemWeights -544
|
||||
equ trap_BotFreeItemWeights -546
|
||||
equ trap_BotSaveGoalFuzzyLogic -546
|
||||
equ trap_BotAllocGoalState -547
|
||||
equ trap_BotFreeGoalState -548
|
||||
|
||||
equ trap_BotResetMoveState -549
|
||||
equ trap_BotMoveToGoal -550
|
||||
equ trap_BotMoveInDirection -551
|
||||
equ trap_BotResetAvoidReach -552
|
||||
equ trap_BotResetLastAvoidReach -553
|
||||
equ trap_BotReachabilityArea -554
|
||||
equ trap_BotMovementViewTarget -555
|
||||
equ trap_BotAllocMoveState -556
|
||||
equ trap_BotFreeMoveState -557
|
||||
equ trap_BotInitMoveState -558
|
||||
|
||||
equ trap_BotChooseBestFightWeapon -559
|
||||
equ trap_BotGetWeaponInfo -560
|
||||
equ trap_BotLoadWeaponWeights -561
|
||||
equ trap_BotAllocWeaponState -562
|
||||
equ trap_BotFreeWeaponState -563
|
||||
equ trap_BotResetWeaponState -564
|
||||
equ trap_GeneticParentsAndChildSelection -565
|
||||
equ trap_BotInterbreedGoalFuzzyLogic -566
|
||||
equ trap_BotMutateGoalFuzzyLogic -567
|
||||
equ trap_BotGetNextCampSpotGoal -568
|
||||
equ trap_BotGetMapLocationGoal -569
|
||||
equ trap_BotNumInitialChats -570
|
||||
equ trap_BotGetChatMessage -571
|
||||
equ trap_BotRemoveFromAvoidGoals -572
|
||||
equ trap_BotPredictVisiblePosition -573
|
||||
equ trap_BotSetAvoidGoalTime -574
|
||||
equ trap_BotAddAvoidSpot -575
|
||||
equ trap_AAS_AlternativeRouteGoals -576
|
||||
equ trap_AAS_PredictRoute -577
|
||||
equ trap_AAS_PointReachabilityAreaIndex -578
|
||||
|
||||
equ trap_BotLibLoadSource -579
|
||||
equ trap_BotLibFreeSource -580
|
||||
equ trap_BotLibReadToken -581
|
||||
equ trap_BotLibSourceFileAndLine -582
|
||||
|
||||
@@ -0,0 +1,790 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
#include "g_local.h"
|
||||
|
||||
// this file is only included when building a dll
|
||||
// g_syscalls.asm is included instead when building a qvm
|
||||
#ifdef Q3_VM
|
||||
#error "Do not use in VM build"
|
||||
#endif
|
||||
|
||||
static int (QDECL *syscall)( int arg, ... ) = (int (QDECL *)( int, ...))-1;
|
||||
|
||||
|
||||
void dllEntry( int (QDECL *syscallptr)( int arg,... ) ) {
|
||||
syscall = syscallptr;
|
||||
}
|
||||
|
||||
int PASSFLOAT( float x ) {
|
||||
float floatTemp;
|
||||
floatTemp = x;
|
||||
return *(int *)&floatTemp;
|
||||
}
|
||||
|
||||
void trap_Printf( const char *fmt ) {
|
||||
syscall( G_PRINT, fmt );
|
||||
}
|
||||
|
||||
void trap_Error( const char *fmt ) {
|
||||
syscall( G_ERROR, fmt );
|
||||
}
|
||||
|
||||
int trap_Milliseconds( void ) {
|
||||
return syscall( G_MILLISECONDS );
|
||||
}
|
||||
int trap_Argc( void ) {
|
||||
return syscall( G_ARGC );
|
||||
}
|
||||
|
||||
void trap_Argv( int n, char *buffer, int bufferLength ) {
|
||||
syscall( G_ARGV, n, buffer, bufferLength );
|
||||
}
|
||||
|
||||
int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode ) {
|
||||
return syscall( G_FS_FOPEN_FILE, qpath, f, mode );
|
||||
}
|
||||
|
||||
void trap_FS_Read( void *buffer, int len, fileHandle_t f ) {
|
||||
syscall( G_FS_READ, buffer, len, f );
|
||||
}
|
||||
|
||||
void trap_FS_Write( const void *buffer, int len, fileHandle_t f ) {
|
||||
syscall( G_FS_WRITE, buffer, len, f );
|
||||
}
|
||||
|
||||
void trap_FS_FCloseFile( fileHandle_t f ) {
|
||||
syscall( G_FS_FCLOSE_FILE, f );
|
||||
}
|
||||
|
||||
int trap_FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize ) {
|
||||
return syscall( G_FS_GETFILELIST, path, extension, listbuf, bufsize );
|
||||
}
|
||||
|
||||
int trap_FS_Seek( fileHandle_t f, long offset, int origin ) {
|
||||
return syscall( G_FS_SEEK, f, offset, origin );
|
||||
}
|
||||
|
||||
void trap_SendConsoleCommand( int exec_when, const char *text ) {
|
||||
syscall( G_SEND_CONSOLE_COMMAND, exec_when, text );
|
||||
}
|
||||
|
||||
void trap_Cvar_Register( vmCvar_t *cvar, const char *var_name, const char *value, int flags ) {
|
||||
syscall( G_CVAR_REGISTER, cvar, var_name, value, flags );
|
||||
}
|
||||
|
||||
void trap_Cvar_Update( vmCvar_t *cvar ) {
|
||||
syscall( G_CVAR_UPDATE, cvar );
|
||||
}
|
||||
|
||||
void trap_Cvar_Set( const char *var_name, const char *value ) {
|
||||
syscall( G_CVAR_SET, var_name, value );
|
||||
}
|
||||
|
||||
int trap_Cvar_VariableIntegerValue( const char *var_name ) {
|
||||
return syscall( G_CVAR_VARIABLE_INTEGER_VALUE, var_name );
|
||||
}
|
||||
|
||||
void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ) {
|
||||
syscall( G_CVAR_VARIABLE_STRING_BUFFER, var_name, buffer, bufsize );
|
||||
}
|
||||
|
||||
|
||||
void trap_LocateGameData( gentity_t *gEnts, int numGEntities, int sizeofGEntity_t,
|
||||
playerState_t *clients, int sizeofGClient ) {
|
||||
syscall( G_LOCATE_GAME_DATA, gEnts, numGEntities, sizeofGEntity_t, clients, sizeofGClient );
|
||||
}
|
||||
|
||||
void trap_DropClient( int clientNum, const char *reason ) {
|
||||
syscall( G_DROP_CLIENT, clientNum, reason );
|
||||
}
|
||||
|
||||
void trap_SendServerCommand( int clientNum, const char *text ) {
|
||||
syscall( G_SEND_SERVER_COMMAND, clientNum, text );
|
||||
}
|
||||
|
||||
void trap_SetConfigstring( int num, const char *string ) {
|
||||
syscall( G_SET_CONFIGSTRING, num, string );
|
||||
}
|
||||
|
||||
void trap_GetConfigstring( int num, char *buffer, int bufferSize ) {
|
||||
syscall( G_GET_CONFIGSTRING, num, buffer, bufferSize );
|
||||
}
|
||||
|
||||
void trap_GetUserinfo( int num, char *buffer, int bufferSize ) {
|
||||
syscall( G_GET_USERINFO, num, buffer, bufferSize );
|
||||
}
|
||||
|
||||
void trap_SetUserinfo( int num, const char *buffer ) {
|
||||
syscall( G_SET_USERINFO, num, buffer );
|
||||
}
|
||||
|
||||
void trap_GetServerinfo( char *buffer, int bufferSize ) {
|
||||
syscall( G_GET_SERVERINFO, buffer, bufferSize );
|
||||
}
|
||||
|
||||
void trap_SetBrushModel( gentity_t *ent, const char *name ) {
|
||||
syscall( G_SET_BRUSH_MODEL, ent, name );
|
||||
}
|
||||
|
||||
void trap_Trace( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask ) {
|
||||
syscall( G_TRACE, results, start, mins, maxs, end, passEntityNum, contentmask );
|
||||
}
|
||||
|
||||
void trap_TraceCapsule( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask ) {
|
||||
syscall( G_TRACECAPSULE, results, start, mins, maxs, end, passEntityNum, contentmask );
|
||||
}
|
||||
|
||||
int trap_PointContents( const vec3_t point, int passEntityNum ) {
|
||||
return syscall( G_POINT_CONTENTS, point, passEntityNum );
|
||||
}
|
||||
|
||||
|
||||
qboolean trap_InPVS( const vec3_t p1, const vec3_t p2 ) {
|
||||
return syscall( G_IN_PVS, p1, p2 );
|
||||
}
|
||||
|
||||
qboolean trap_InPVSIgnorePortals( const vec3_t p1, const vec3_t p2 ) {
|
||||
return syscall( G_IN_PVS_IGNORE_PORTALS, p1, p2 );
|
||||
}
|
||||
|
||||
void trap_AdjustAreaPortalState( gentity_t *ent, qboolean open ) {
|
||||
syscall( G_ADJUST_AREA_PORTAL_STATE, ent, open );
|
||||
}
|
||||
|
||||
qboolean trap_AreasConnected( int area1, int area2 ) {
|
||||
return syscall( G_AREAS_CONNECTED, area1, area2 );
|
||||
}
|
||||
|
||||
void trap_LinkEntity( gentity_t *ent ) {
|
||||
syscall( G_LINKENTITY, ent );
|
||||
}
|
||||
|
||||
void trap_UnlinkEntity( gentity_t *ent ) {
|
||||
syscall( G_UNLINKENTITY, ent );
|
||||
}
|
||||
|
||||
int trap_EntitiesInBox( const vec3_t mins, const vec3_t maxs, int *list, int maxcount ) {
|
||||
return syscall( G_ENTITIES_IN_BOX, mins, maxs, list, maxcount );
|
||||
}
|
||||
|
||||
qboolean trap_EntityContact( const vec3_t mins, const vec3_t maxs, const gentity_t *ent ) {
|
||||
return syscall( G_ENTITY_CONTACT, mins, maxs, ent );
|
||||
}
|
||||
|
||||
qboolean trap_EntityContactCapsule( const vec3_t mins, const vec3_t maxs, const gentity_t *ent ) {
|
||||
return syscall( G_ENTITY_CONTACTCAPSULE, mins, maxs, ent );
|
||||
}
|
||||
|
||||
int trap_BotAllocateClient( void ) {
|
||||
return syscall( G_BOT_ALLOCATE_CLIENT );
|
||||
}
|
||||
|
||||
void trap_BotFreeClient( int clientNum ) {
|
||||
syscall( G_BOT_FREE_CLIENT, clientNum );
|
||||
}
|
||||
|
||||
void trap_GetUsercmd( int clientNum, usercmd_t *cmd ) {
|
||||
syscall( G_GET_USERCMD, clientNum, cmd );
|
||||
}
|
||||
|
||||
qboolean trap_GetEntityToken( char *buffer, int bufferSize ) {
|
||||
return syscall( G_GET_ENTITY_TOKEN, buffer, bufferSize );
|
||||
}
|
||||
|
||||
int trap_DebugPolygonCreate(int color, int numPoints, vec3_t *points) {
|
||||
return syscall( G_DEBUG_POLYGON_CREATE, color, numPoints, points );
|
||||
}
|
||||
|
||||
void trap_DebugPolygonDelete(int id) {
|
||||
syscall( G_DEBUG_POLYGON_DELETE, id );
|
||||
}
|
||||
|
||||
int trap_RealTime( qtime_t *qtime ) {
|
||||
return syscall( G_REAL_TIME, qtime );
|
||||
}
|
||||
|
||||
void trap_SnapVector( float *v ) {
|
||||
syscall( G_SNAPVECTOR, v );
|
||||
return;
|
||||
}
|
||||
|
||||
// BotLib traps start here
|
||||
int trap_BotLibSetup( void ) {
|
||||
return syscall( BOTLIB_SETUP );
|
||||
}
|
||||
|
||||
int trap_BotLibShutdown( void ) {
|
||||
return syscall( BOTLIB_SHUTDOWN );
|
||||
}
|
||||
|
||||
int trap_BotLibVarSet(char *var_name, char *value) {
|
||||
return syscall( BOTLIB_LIBVAR_SET, var_name, value );
|
||||
}
|
||||
|
||||
int trap_BotLibVarGet(char *var_name, char *value, int size) {
|
||||
return syscall( BOTLIB_LIBVAR_GET, var_name, value, size );
|
||||
}
|
||||
|
||||
int trap_BotLibDefine(char *string) {
|
||||
return syscall( BOTLIB_PC_ADD_GLOBAL_DEFINE, string );
|
||||
}
|
||||
|
||||
int trap_BotLibStartFrame(float time) {
|
||||
return syscall( BOTLIB_START_FRAME, PASSFLOAT( time ) );
|
||||
}
|
||||
|
||||
int trap_BotLibLoadMap(const char *mapname) {
|
||||
return syscall( BOTLIB_LOAD_MAP, mapname );
|
||||
}
|
||||
|
||||
int trap_BotLibUpdateEntity(int ent, void /* struct bot_updateentity_s */ *bue) {
|
||||
return syscall( BOTLIB_UPDATENTITY, ent, bue );
|
||||
}
|
||||
|
||||
int trap_BotLibTest(int parm0, char *parm1, vec3_t parm2, vec3_t parm3) {
|
||||
return syscall( BOTLIB_TEST, parm0, parm1, parm2, parm3 );
|
||||
}
|
||||
|
||||
int trap_BotGetSnapshotEntity( int clientNum, int sequence ) {
|
||||
return syscall( BOTLIB_GET_SNAPSHOT_ENTITY, clientNum, sequence );
|
||||
}
|
||||
|
||||
int trap_BotGetServerCommand(int clientNum, char *message, int size) {
|
||||
return syscall( BOTLIB_GET_CONSOLE_MESSAGE, clientNum, message, size );
|
||||
}
|
||||
|
||||
void trap_BotUserCommand(int clientNum, usercmd_t *ucmd) {
|
||||
syscall( BOTLIB_USER_COMMAND, clientNum, ucmd );
|
||||
}
|
||||
|
||||
void trap_AAS_EntityInfo(int entnum, void /* struct aas_entityinfo_s */ *info) {
|
||||
syscall( BOTLIB_AAS_ENTITY_INFO, entnum, info );
|
||||
}
|
||||
|
||||
int trap_AAS_Initialized(void) {
|
||||
return syscall( BOTLIB_AAS_INITIALIZED );
|
||||
}
|
||||
|
||||
void trap_AAS_PresenceTypeBoundingBox(int presencetype, vec3_t mins, vec3_t maxs) {
|
||||
syscall( BOTLIB_AAS_PRESENCE_TYPE_BOUNDING_BOX, presencetype, mins, maxs );
|
||||
}
|
||||
|
||||
float trap_AAS_Time(void) {
|
||||
int temp;
|
||||
temp = syscall( BOTLIB_AAS_TIME );
|
||||
return (*(float*)&temp);
|
||||
}
|
||||
|
||||
int trap_AAS_PointAreaNum(vec3_t point) {
|
||||
return syscall( BOTLIB_AAS_POINT_AREA_NUM, point );
|
||||
}
|
||||
|
||||
int trap_AAS_PointReachabilityAreaIndex(vec3_t point) {
|
||||
return syscall( BOTLIB_AAS_POINT_REACHABILITY_AREA_INDEX, point );
|
||||
}
|
||||
|
||||
int trap_AAS_TraceAreas(vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas) {
|
||||
return syscall( BOTLIB_AAS_TRACE_AREAS, start, end, areas, points, maxareas );
|
||||
}
|
||||
|
||||
int trap_AAS_BBoxAreas(vec3_t absmins, vec3_t absmaxs, int *areas, int maxareas) {
|
||||
return syscall( BOTLIB_AAS_BBOX_AREAS, absmins, absmaxs, areas, maxareas );
|
||||
}
|
||||
|
||||
int trap_AAS_AreaInfo( int areanum, void /* struct aas_areainfo_s */ *info ) {
|
||||
return syscall( BOTLIB_AAS_AREA_INFO, areanum, info );
|
||||
}
|
||||
|
||||
int trap_AAS_PointContents(vec3_t point) {
|
||||
return syscall( BOTLIB_AAS_POINT_CONTENTS, point );
|
||||
}
|
||||
|
||||
int trap_AAS_NextBSPEntity(int ent) {
|
||||
return syscall( BOTLIB_AAS_NEXT_BSP_ENTITY, ent );
|
||||
}
|
||||
|
||||
int trap_AAS_ValueForBSPEpairKey(int ent, char *key, char *value, int size) {
|
||||
return syscall( BOTLIB_AAS_VALUE_FOR_BSP_EPAIR_KEY, ent, key, value, size );
|
||||
}
|
||||
|
||||
int trap_AAS_VectorForBSPEpairKey(int ent, char *key, vec3_t v) {
|
||||
return syscall( BOTLIB_AAS_VECTOR_FOR_BSP_EPAIR_KEY, ent, key, v );
|
||||
}
|
||||
|
||||
int trap_AAS_FloatForBSPEpairKey(int ent, char *key, float *value) {
|
||||
return syscall( BOTLIB_AAS_FLOAT_FOR_BSP_EPAIR_KEY, ent, key, value );
|
||||
}
|
||||
|
||||
int trap_AAS_IntForBSPEpairKey(int ent, char *key, int *value) {
|
||||
return syscall( BOTLIB_AAS_INT_FOR_BSP_EPAIR_KEY, ent, key, value );
|
||||
}
|
||||
|
||||
int trap_AAS_AreaReachability(int areanum) {
|
||||
return syscall( BOTLIB_AAS_AREA_REACHABILITY, areanum );
|
||||
}
|
||||
|
||||
int trap_AAS_AreaTravelTimeToGoalArea(int areanum, vec3_t origin, int goalareanum, int travelflags) {
|
||||
return syscall( BOTLIB_AAS_AREA_TRAVEL_TIME_TO_GOAL_AREA, areanum, origin, goalareanum, travelflags );
|
||||
}
|
||||
|
||||
int trap_AAS_EnableRoutingArea( int areanum, int enable ) {
|
||||
return syscall( BOTLIB_AAS_ENABLE_ROUTING_AREA, areanum, enable );
|
||||
}
|
||||
|
||||
int trap_AAS_PredictRoute(void /*struct aas_predictroute_s*/ *route, int areanum, vec3_t origin,
|
||||
int goalareanum, int travelflags, int maxareas, int maxtime,
|
||||
int stopevent, int stopcontents, int stoptfl, int stopareanum) {
|
||||
return syscall( BOTLIB_AAS_PREDICT_ROUTE, route, areanum, origin, goalareanum, travelflags, maxareas, maxtime, stopevent, stopcontents, stoptfl, stopareanum );
|
||||
}
|
||||
|
||||
int trap_AAS_AlternativeRouteGoals(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags,
|
||||
void /*struct aas_altroutegoal_s*/ *altroutegoals, int maxaltroutegoals,
|
||||
int type) {
|
||||
return syscall( BOTLIB_AAS_ALTERNATIVE_ROUTE_GOAL, start, startareanum, goal, goalareanum, travelflags, altroutegoals, maxaltroutegoals, type );
|
||||
}
|
||||
|
||||
int trap_AAS_Swimming(vec3_t origin) {
|
||||
return syscall( BOTLIB_AAS_SWIMMING, origin );
|
||||
}
|
||||
|
||||
int trap_AAS_PredictClientMovement(void /* struct aas_clientmove_s */ *move, int entnum, vec3_t origin, int presencetype, int onground, vec3_t velocity, vec3_t cmdmove, int cmdframes, int maxframes, float frametime, int stopevent, int stopareanum, int visualize) {
|
||||
return syscall( BOTLIB_AAS_PREDICT_CLIENT_MOVEMENT, move, entnum, origin, presencetype, onground, velocity, cmdmove, cmdframes, maxframes, PASSFLOAT(frametime), stopevent, stopareanum, visualize );
|
||||
}
|
||||
|
||||
void trap_EA_Say(int client, char *str) {
|
||||
syscall( BOTLIB_EA_SAY, client, str );
|
||||
}
|
||||
|
||||
void trap_EA_SayTeam(int client, char *str) {
|
||||
syscall( BOTLIB_EA_SAY_TEAM, client, str );
|
||||
}
|
||||
|
||||
void trap_EA_Command(int client, char *command) {
|
||||
syscall( BOTLIB_EA_COMMAND, client, command );
|
||||
}
|
||||
|
||||
void trap_EA_Action(int client, int action) {
|
||||
syscall( BOTLIB_EA_ACTION, client, action );
|
||||
}
|
||||
|
||||
void trap_EA_Gesture(int client) {
|
||||
syscall( BOTLIB_EA_GESTURE, client );
|
||||
}
|
||||
|
||||
void trap_EA_Talk(int client) {
|
||||
syscall( BOTLIB_EA_TALK, client );
|
||||
}
|
||||
|
||||
void trap_EA_Attack(int client) {
|
||||
syscall( BOTLIB_EA_ATTACK, client );
|
||||
}
|
||||
|
||||
void trap_EA_Use(int client) {
|
||||
syscall( BOTLIB_EA_USE, client );
|
||||
}
|
||||
|
||||
void trap_EA_Respawn(int client) {
|
||||
syscall( BOTLIB_EA_RESPAWN, client );
|
||||
}
|
||||
|
||||
void trap_EA_Crouch(int client) {
|
||||
syscall( BOTLIB_EA_CROUCH, client );
|
||||
}
|
||||
|
||||
void trap_EA_MoveUp(int client) {
|
||||
syscall( BOTLIB_EA_MOVE_UP, client );
|
||||
}
|
||||
|
||||
void trap_EA_MoveDown(int client) {
|
||||
syscall( BOTLIB_EA_MOVE_DOWN, client );
|
||||
}
|
||||
|
||||
void trap_EA_MoveForward(int client) {
|
||||
syscall( BOTLIB_EA_MOVE_FORWARD, client );
|
||||
}
|
||||
|
||||
void trap_EA_MoveBack(int client) {
|
||||
syscall( BOTLIB_EA_MOVE_BACK, client );
|
||||
}
|
||||
|
||||
void trap_EA_MoveLeft(int client) {
|
||||
syscall( BOTLIB_EA_MOVE_LEFT, client );
|
||||
}
|
||||
|
||||
void trap_EA_MoveRight(int client) {
|
||||
syscall( BOTLIB_EA_MOVE_RIGHT, client );
|
||||
}
|
||||
|
||||
void trap_EA_SelectWeapon(int client, int weapon) {
|
||||
syscall( BOTLIB_EA_SELECT_WEAPON, client, weapon );
|
||||
}
|
||||
|
||||
void trap_EA_Jump(int client) {
|
||||
syscall( BOTLIB_EA_JUMP, client );
|
||||
}
|
||||
|
||||
void trap_EA_DelayedJump(int client) {
|
||||
syscall( BOTLIB_EA_DELAYED_JUMP, client );
|
||||
}
|
||||
|
||||
void trap_EA_Move(int client, vec3_t dir, float speed) {
|
||||
syscall( BOTLIB_EA_MOVE, client, dir, PASSFLOAT(speed) );
|
||||
}
|
||||
|
||||
void trap_EA_View(int client, vec3_t viewangles) {
|
||||
syscall( BOTLIB_EA_VIEW, client, viewangles );
|
||||
}
|
||||
|
||||
void trap_EA_EndRegular(int client, float thinktime) {
|
||||
syscall( BOTLIB_EA_END_REGULAR, client, PASSFLOAT(thinktime) );
|
||||
}
|
||||
|
||||
void trap_EA_GetInput(int client, float thinktime, void /* struct bot_input_s */ *input) {
|
||||
syscall( BOTLIB_EA_GET_INPUT, client, PASSFLOAT(thinktime), input );
|
||||
}
|
||||
|
||||
void trap_EA_ResetInput(int client) {
|
||||
syscall( BOTLIB_EA_RESET_INPUT, client );
|
||||
}
|
||||
|
||||
int trap_BotLoadCharacter(char *charfile, float skill) {
|
||||
return syscall( BOTLIB_AI_LOAD_CHARACTER, charfile, PASSFLOAT(skill));
|
||||
}
|
||||
|
||||
void trap_BotFreeCharacter(int character) {
|
||||
syscall( BOTLIB_AI_FREE_CHARACTER, character );
|
||||
}
|
||||
|
||||
float trap_Characteristic_Float(int character, int index) {
|
||||
int temp;
|
||||
temp = syscall( BOTLIB_AI_CHARACTERISTIC_FLOAT, character, index );
|
||||
return (*(float*)&temp);
|
||||
}
|
||||
|
||||
float trap_Characteristic_BFloat(int character, int index, float min, float max) {
|
||||
int temp;
|
||||
temp = syscall( BOTLIB_AI_CHARACTERISTIC_BFLOAT, character, index, PASSFLOAT(min), PASSFLOAT(max) );
|
||||
return (*(float*)&temp);
|
||||
}
|
||||
|
||||
int trap_Characteristic_Integer(int character, int index) {
|
||||
return syscall( BOTLIB_AI_CHARACTERISTIC_INTEGER, character, index );
|
||||
}
|
||||
|
||||
int trap_Characteristic_BInteger(int character, int index, int min, int max) {
|
||||
return syscall( BOTLIB_AI_CHARACTERISTIC_BINTEGER, character, index, min, max );
|
||||
}
|
||||
|
||||
void trap_Characteristic_String(int character, int index, char *buf, int size) {
|
||||
syscall( BOTLIB_AI_CHARACTERISTIC_STRING, character, index, buf, size );
|
||||
}
|
||||
|
||||
int trap_BotAllocChatState(void) {
|
||||
return syscall( BOTLIB_AI_ALLOC_CHAT_STATE );
|
||||
}
|
||||
|
||||
void trap_BotFreeChatState(int handle) {
|
||||
syscall( BOTLIB_AI_FREE_CHAT_STATE, handle );
|
||||
}
|
||||
|
||||
void trap_BotQueueConsoleMessage(int chatstate, int type, char *message) {
|
||||
syscall( BOTLIB_AI_QUEUE_CONSOLE_MESSAGE, chatstate, type, message );
|
||||
}
|
||||
|
||||
void trap_BotRemoveConsoleMessage(int chatstate, int handle) {
|
||||
syscall( BOTLIB_AI_REMOVE_CONSOLE_MESSAGE, chatstate, handle );
|
||||
}
|
||||
|
||||
int trap_BotNextConsoleMessage(int chatstate, void /* struct bot_consolemessage_s */ *cm) {
|
||||
return syscall( BOTLIB_AI_NEXT_CONSOLE_MESSAGE, chatstate, cm );
|
||||
}
|
||||
|
||||
int trap_BotNumConsoleMessages(int chatstate) {
|
||||
return syscall( BOTLIB_AI_NUM_CONSOLE_MESSAGE, chatstate );
|
||||
}
|
||||
|
||||
void trap_BotInitialChat(int chatstate, char *type, int mcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7 ) {
|
||||
syscall( BOTLIB_AI_INITIAL_CHAT, chatstate, type, mcontext, var0, var1, var2, var3, var4, var5, var6, var7 );
|
||||
}
|
||||
|
||||
int trap_BotNumInitialChats(int chatstate, char *type) {
|
||||
return syscall( BOTLIB_AI_NUM_INITIAL_CHATS, chatstate, type );
|
||||
}
|
||||
|
||||
int trap_BotReplyChat(int chatstate, char *message, int mcontext, int vcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7 ) {
|
||||
return syscall( BOTLIB_AI_REPLY_CHAT, chatstate, message, mcontext, vcontext, var0, var1, var2, var3, var4, var5, var6, var7 );
|
||||
}
|
||||
|
||||
int trap_BotChatLength(int chatstate) {
|
||||
return syscall( BOTLIB_AI_CHAT_LENGTH, chatstate );
|
||||
}
|
||||
|
||||
void trap_BotEnterChat(int chatstate, int client, int sendto) {
|
||||
syscall( BOTLIB_AI_ENTER_CHAT, chatstate, client, sendto );
|
||||
}
|
||||
|
||||
void trap_BotGetChatMessage(int chatstate, char *buf, int size) {
|
||||
syscall( BOTLIB_AI_GET_CHAT_MESSAGE, chatstate, buf, size);
|
||||
}
|
||||
|
||||
int trap_StringContains(char *str1, char *str2, int casesensitive) {
|
||||
return syscall( BOTLIB_AI_STRING_CONTAINS, str1, str2, casesensitive );
|
||||
}
|
||||
|
||||
int trap_BotFindMatch(char *str, void /* struct bot_match_s */ *match, unsigned long int context) {
|
||||
return syscall( BOTLIB_AI_FIND_MATCH, str, match, context );
|
||||
}
|
||||
|
||||
void trap_BotMatchVariable(void /* struct bot_match_s */ *match, int variable, char *buf, int size) {
|
||||
syscall( BOTLIB_AI_MATCH_VARIABLE, match, variable, buf, size );
|
||||
}
|
||||
|
||||
void trap_UnifyWhiteSpaces(char *string) {
|
||||
syscall( BOTLIB_AI_UNIFY_WHITE_SPACES, string );
|
||||
}
|
||||
|
||||
void trap_BotReplaceSynonyms(char *string, unsigned long int context) {
|
||||
syscall( BOTLIB_AI_REPLACE_SYNONYMS, string, context );
|
||||
}
|
||||
|
||||
int trap_BotLoadChatFile(int chatstate, char *chatfile, char *chatname) {
|
||||
return syscall( BOTLIB_AI_LOAD_CHAT_FILE, chatstate, chatfile, chatname );
|
||||
}
|
||||
|
||||
void trap_BotSetChatGender(int chatstate, int gender) {
|
||||
syscall( BOTLIB_AI_SET_CHAT_GENDER, chatstate, gender );
|
||||
}
|
||||
|
||||
void trap_BotSetChatName(int chatstate, char *name, int client) {
|
||||
syscall( BOTLIB_AI_SET_CHAT_NAME, chatstate, name, client );
|
||||
}
|
||||
|
||||
void trap_BotResetGoalState(int goalstate) {
|
||||
syscall( BOTLIB_AI_RESET_GOAL_STATE, goalstate );
|
||||
}
|
||||
|
||||
void trap_BotResetAvoidGoals(int goalstate) {
|
||||
syscall( BOTLIB_AI_RESET_AVOID_GOALS, goalstate );
|
||||
}
|
||||
|
||||
void trap_BotRemoveFromAvoidGoals(int goalstate, int number) {
|
||||
syscall( BOTLIB_AI_REMOVE_FROM_AVOID_GOALS, goalstate, number);
|
||||
}
|
||||
|
||||
void trap_BotPushGoal(int goalstate, void /* struct bot_goal_s */ *goal) {
|
||||
syscall( BOTLIB_AI_PUSH_GOAL, goalstate, goal );
|
||||
}
|
||||
|
||||
void trap_BotPopGoal(int goalstate) {
|
||||
syscall( BOTLIB_AI_POP_GOAL, goalstate );
|
||||
}
|
||||
|
||||
void trap_BotEmptyGoalStack(int goalstate) {
|
||||
syscall( BOTLIB_AI_EMPTY_GOAL_STACK, goalstate );
|
||||
}
|
||||
|
||||
void trap_BotDumpAvoidGoals(int goalstate) {
|
||||
syscall( BOTLIB_AI_DUMP_AVOID_GOALS, goalstate );
|
||||
}
|
||||
|
||||
void trap_BotDumpGoalStack(int goalstate) {
|
||||
syscall( BOTLIB_AI_DUMP_GOAL_STACK, goalstate );
|
||||
}
|
||||
|
||||
void trap_BotGoalName(int number, char *name, int size) {
|
||||
syscall( BOTLIB_AI_GOAL_NAME, number, name, size );
|
||||
}
|
||||
|
||||
int trap_BotGetTopGoal(int goalstate, void /* struct bot_goal_s */ *goal) {
|
||||
return syscall( BOTLIB_AI_GET_TOP_GOAL, goalstate, goal );
|
||||
}
|
||||
|
||||
int trap_BotGetSecondGoal(int goalstate, void /* struct bot_goal_s */ *goal) {
|
||||
return syscall( BOTLIB_AI_GET_SECOND_GOAL, goalstate, goal );
|
||||
}
|
||||
|
||||
int trap_BotChooseLTGItem(int goalstate, vec3_t origin, int *inventory, int travelflags) {
|
||||
return syscall( BOTLIB_AI_CHOOSE_LTG_ITEM, goalstate, origin, inventory, travelflags );
|
||||
}
|
||||
|
||||
int trap_BotChooseNBGItem(int goalstate, vec3_t origin, int *inventory, int travelflags, void /* struct bot_goal_s */ *ltg, float maxtime) {
|
||||
return syscall( BOTLIB_AI_CHOOSE_NBG_ITEM, goalstate, origin, inventory, travelflags, ltg, PASSFLOAT(maxtime) );
|
||||
}
|
||||
|
||||
int trap_BotTouchingGoal(vec3_t origin, void /* struct bot_goal_s */ *goal) {
|
||||
return syscall( BOTLIB_AI_TOUCHING_GOAL, origin, goal );
|
||||
}
|
||||
|
||||
int trap_BotItemGoalInVisButNotVisible(int viewer, vec3_t eye, vec3_t viewangles, void /* struct bot_goal_s */ *goal) {
|
||||
return syscall( BOTLIB_AI_ITEM_GOAL_IN_VIS_BUT_NOT_VISIBLE, viewer, eye, viewangles, goal );
|
||||
}
|
||||
|
||||
int trap_BotGetLevelItemGoal(int index, char *classname, void /* struct bot_goal_s */ *goal) {
|
||||
return syscall( BOTLIB_AI_GET_LEVEL_ITEM_GOAL, index, classname, goal );
|
||||
}
|
||||
|
||||
int trap_BotGetNextCampSpotGoal(int num, void /* struct bot_goal_s */ *goal) {
|
||||
return syscall( BOTLIB_AI_GET_NEXT_CAMP_SPOT_GOAL, num, goal );
|
||||
}
|
||||
|
||||
int trap_BotGetMapLocationGoal(char *name, void /* struct bot_goal_s */ *goal) {
|
||||
return syscall( BOTLIB_AI_GET_MAP_LOCATION_GOAL, name, goal );
|
||||
}
|
||||
|
||||
float trap_BotAvoidGoalTime(int goalstate, int number) {
|
||||
int temp;
|
||||
temp = syscall( BOTLIB_AI_AVOID_GOAL_TIME, goalstate, number );
|
||||
return (*(float*)&temp);
|
||||
}
|
||||
|
||||
void trap_BotSetAvoidGoalTime(int goalstate, int number, float avoidtime) {
|
||||
syscall( BOTLIB_AI_SET_AVOID_GOAL_TIME, goalstate, number, PASSFLOAT(avoidtime));
|
||||
}
|
||||
|
||||
void trap_BotInitLevelItems(void) {
|
||||
syscall( BOTLIB_AI_INIT_LEVEL_ITEMS );
|
||||
}
|
||||
|
||||
void trap_BotUpdateEntityItems(void) {
|
||||
syscall( BOTLIB_AI_UPDATE_ENTITY_ITEMS );
|
||||
}
|
||||
|
||||
int trap_BotLoadItemWeights(int goalstate, char *filename) {
|
||||
return syscall( BOTLIB_AI_LOAD_ITEM_WEIGHTS, goalstate, filename );
|
||||
}
|
||||
|
||||
void trap_BotFreeItemWeights(int goalstate) {
|
||||
syscall( BOTLIB_AI_FREE_ITEM_WEIGHTS, goalstate );
|
||||
}
|
||||
|
||||
void trap_BotInterbreedGoalFuzzyLogic(int parent1, int parent2, int child) {
|
||||
syscall( BOTLIB_AI_INTERBREED_GOAL_FUZZY_LOGIC, parent1, parent2, child );
|
||||
}
|
||||
|
||||
void trap_BotSaveGoalFuzzyLogic(int goalstate, char *filename) {
|
||||
syscall( BOTLIB_AI_SAVE_GOAL_FUZZY_LOGIC, goalstate, filename );
|
||||
}
|
||||
|
||||
void trap_BotMutateGoalFuzzyLogic(int goalstate, float range) {
|
||||
syscall( BOTLIB_AI_MUTATE_GOAL_FUZZY_LOGIC, goalstate, range );
|
||||
}
|
||||
|
||||
int trap_BotAllocGoalState(int state) {
|
||||
return syscall( BOTLIB_AI_ALLOC_GOAL_STATE, state );
|
||||
}
|
||||
|
||||
void trap_BotFreeGoalState(int handle) {
|
||||
syscall( BOTLIB_AI_FREE_GOAL_STATE, handle );
|
||||
}
|
||||
|
||||
void trap_BotResetMoveState(int movestate) {
|
||||
syscall( BOTLIB_AI_RESET_MOVE_STATE, movestate );
|
||||
}
|
||||
|
||||
void trap_BotAddAvoidSpot(int movestate, vec3_t origin, float radius, int type) {
|
||||
syscall( BOTLIB_AI_ADD_AVOID_SPOT, movestate, origin, PASSFLOAT(radius), type);
|
||||
}
|
||||
|
||||
void trap_BotMoveToGoal(void /* struct bot_moveresult_s */ *result, int movestate, void /* struct bot_goal_s */ *goal, int travelflags) {
|
||||
syscall( BOTLIB_AI_MOVE_TO_GOAL, result, movestate, goal, travelflags );
|
||||
}
|
||||
|
||||
int trap_BotMoveInDirection(int movestate, vec3_t dir, float speed, int type) {
|
||||
return syscall( BOTLIB_AI_MOVE_IN_DIRECTION, movestate, dir, PASSFLOAT(speed), type );
|
||||
}
|
||||
|
||||
void trap_BotResetAvoidReach(int movestate) {
|
||||
syscall( BOTLIB_AI_RESET_AVOID_REACH, movestate );
|
||||
}
|
||||
|
||||
void trap_BotResetLastAvoidReach(int movestate) {
|
||||
syscall( BOTLIB_AI_RESET_LAST_AVOID_REACH,movestate );
|
||||
}
|
||||
|
||||
int trap_BotReachabilityArea(vec3_t origin, int testground) {
|
||||
return syscall( BOTLIB_AI_REACHABILITY_AREA, origin, testground );
|
||||
}
|
||||
|
||||
int trap_BotMovementViewTarget(int movestate, void /* struct bot_goal_s */ *goal, int travelflags, float lookahead, vec3_t target) {
|
||||
return syscall( BOTLIB_AI_MOVEMENT_VIEW_TARGET, movestate, goal, travelflags, PASSFLOAT(lookahead), target );
|
||||
}
|
||||
|
||||
int trap_BotPredictVisiblePosition(vec3_t origin, int areanum, void /* struct bot_goal_s */ *goal, int travelflags, vec3_t target) {
|
||||
return syscall( BOTLIB_AI_PREDICT_VISIBLE_POSITION, origin, areanum, goal, travelflags, target );
|
||||
}
|
||||
|
||||
int trap_BotAllocMoveState(void) {
|
||||
return syscall( BOTLIB_AI_ALLOC_MOVE_STATE );
|
||||
}
|
||||
|
||||
void trap_BotFreeMoveState(int handle) {
|
||||
syscall( BOTLIB_AI_FREE_MOVE_STATE, handle );
|
||||
}
|
||||
|
||||
void trap_BotInitMoveState(int handle, void /* struct bot_initmove_s */ *initmove) {
|
||||
syscall( BOTLIB_AI_INIT_MOVE_STATE, handle, initmove );
|
||||
}
|
||||
|
||||
int trap_BotChooseBestFightWeapon(int weaponstate, int *inventory) {
|
||||
return syscall( BOTLIB_AI_CHOOSE_BEST_FIGHT_WEAPON, weaponstate, inventory );
|
||||
}
|
||||
|
||||
void trap_BotGetWeaponInfo(int weaponstate, int weapon, void /* struct weaponinfo_s */ *weaponinfo) {
|
||||
syscall( BOTLIB_AI_GET_WEAPON_INFO, weaponstate, weapon, weaponinfo );
|
||||
}
|
||||
|
||||
int trap_BotLoadWeaponWeights(int weaponstate, char *filename) {
|
||||
return syscall( BOTLIB_AI_LOAD_WEAPON_WEIGHTS, weaponstate, filename );
|
||||
}
|
||||
|
||||
int trap_BotAllocWeaponState(void) {
|
||||
return syscall( BOTLIB_AI_ALLOC_WEAPON_STATE );
|
||||
}
|
||||
|
||||
void trap_BotFreeWeaponState(int weaponstate) {
|
||||
syscall( BOTLIB_AI_FREE_WEAPON_STATE, weaponstate );
|
||||
}
|
||||
|
||||
void trap_BotResetWeaponState(int weaponstate) {
|
||||
syscall( BOTLIB_AI_RESET_WEAPON_STATE, weaponstate );
|
||||
}
|
||||
|
||||
int trap_GeneticParentsAndChildSelection(int numranks, float *ranks, int *parent1, int *parent2, int *child) {
|
||||
return syscall( BOTLIB_AI_GENETIC_PARENTS_AND_CHILD_SELECTION, numranks, ranks, parent1, parent2, child );
|
||||
}
|
||||
|
||||
int trap_PC_LoadSource( const char *filename ) {
|
||||
return syscall( BOTLIB_PC_LOAD_SOURCE, filename );
|
||||
}
|
||||
|
||||
int trap_PC_FreeSource( int handle ) {
|
||||
return syscall( BOTLIB_PC_FREE_SOURCE, handle );
|
||||
}
|
||||
|
||||
int trap_PC_ReadToken( int handle, pc_token_t *pc_token ) {
|
||||
return syscall( BOTLIB_PC_READ_TOKEN, handle, pc_token );
|
||||
}
|
||||
|
||||
int trap_PC_SourceFileAndLine( int handle, char *filename, int *line ) {
|
||||
return syscall( BOTLIB_PC_SOURCE_FILE_AND_LINE, handle, filename, line );
|
||||
}
|
||||
@@ -0,0 +1,467 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
#include "g_local.h"
|
||||
|
||||
//==========================================================
|
||||
|
||||
/*QUAKED target_give (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
Gives the activator all the items pointed to.
|
||||
*/
|
||||
void Use_Target_Give( gentity_t *ent, gentity_t *other, gentity_t *activator ) {
|
||||
gentity_t *t;
|
||||
trace_t trace;
|
||||
|
||||
if ( !activator->client ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !ent->target ) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset( &trace, 0, sizeof( trace ) );
|
||||
t = NULL;
|
||||
while ( (t = G_Find (t, FOFS(targetname), ent->target)) != NULL ) {
|
||||
if ( !t->item ) {
|
||||
continue;
|
||||
}
|
||||
Touch_Item( t, activator, &trace );
|
||||
|
||||
// make sure it isn't going to respawn or show any events
|
||||
t->nextthink = 0;
|
||||
trap_UnlinkEntity( t );
|
||||
}
|
||||
}
|
||||
|
||||
void SP_target_give( gentity_t *ent ) {
|
||||
ent->use = Use_Target_Give;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
/*QUAKED target_remove_powerups (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
takes away all the activators powerups.
|
||||
Used to drop flight powerups into death puts.
|
||||
*/
|
||||
void Use_target_remove_powerups( gentity_t *ent, gentity_t *other, gentity_t *activator ) {
|
||||
if( !activator->client ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( activator->client->ps.powerups[PW_REDFLAG] ) {
|
||||
Team_ReturnFlag( TEAM_RED );
|
||||
} else if( activator->client->ps.powerups[PW_BLUEFLAG] ) {
|
||||
Team_ReturnFlag( TEAM_BLUE );
|
||||
} else if( activator->client->ps.powerups[PW_NEUTRALFLAG] ) {
|
||||
Team_ReturnFlag( TEAM_FREE );
|
||||
}
|
||||
|
||||
memset( activator->client->ps.powerups, 0, sizeof( activator->client->ps.powerups ) );
|
||||
}
|
||||
|
||||
void SP_target_remove_powerups( gentity_t *ent ) {
|
||||
ent->use = Use_target_remove_powerups;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
/*QUAKED target_delay (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
"wait" seconds to pause before firing targets.
|
||||
"random" delay variance, total delay = delay +/- random seconds
|
||||
*/
|
||||
void Think_Target_Delay( gentity_t *ent ) {
|
||||
G_UseTargets( ent, ent->activator );
|
||||
}
|
||||
|
||||
void Use_Target_Delay( gentity_t *ent, gentity_t *other, gentity_t *activator ) {
|
||||
ent->nextthink = level.time + ( ent->wait + ent->random * crandom() ) * 1000;
|
||||
ent->think = Think_Target_Delay;
|
||||
ent->activator = activator;
|
||||
}
|
||||
|
||||
void SP_target_delay( gentity_t *ent ) {
|
||||
// check delay for backwards compatability
|
||||
if ( !G_SpawnFloat( "delay", "0", &ent->wait ) ) {
|
||||
G_SpawnFloat( "wait", "1", &ent->wait );
|
||||
}
|
||||
|
||||
if ( !ent->wait ) {
|
||||
ent->wait = 1;
|
||||
}
|
||||
ent->use = Use_Target_Delay;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
/*QUAKED target_score (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
"count" number of points to add, default 1
|
||||
|
||||
The activator is given this many points.
|
||||
*/
|
||||
void Use_Target_Score (gentity_t *ent, gentity_t *other, gentity_t *activator) {
|
||||
AddScore( activator, ent->r.currentOrigin, ent->count );
|
||||
}
|
||||
|
||||
void SP_target_score( gentity_t *ent ) {
|
||||
if ( !ent->count ) {
|
||||
ent->count = 1;
|
||||
}
|
||||
ent->use = Use_Target_Score;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
/*QUAKED target_print (1 0 0) (-8 -8 -8) (8 8 8) redteam blueteam private
|
||||
"message" text to print
|
||||
If "private", only the activator gets the message. If no checks, all clients get the message.
|
||||
*/
|
||||
void Use_Target_Print (gentity_t *ent, gentity_t *other, gentity_t *activator) {
|
||||
if ( activator->client && ( ent->spawnflags & 4 ) ) {
|
||||
trap_SendServerCommand( activator-g_entities, va("cp \"%s\"", ent->message ));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ent->spawnflags & 3 ) {
|
||||
if ( ent->spawnflags & 1 ) {
|
||||
G_TeamCommand( TEAM_RED, va("cp \"%s\"", ent->message) );
|
||||
}
|
||||
if ( ent->spawnflags & 2 ) {
|
||||
G_TeamCommand( TEAM_BLUE, va("cp \"%s\"", ent->message) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
trap_SendServerCommand( -1, va("cp \"%s\"", ent->message ));
|
||||
}
|
||||
|
||||
void SP_target_print( gentity_t *ent ) {
|
||||
ent->use = Use_Target_Print;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
|
||||
/*QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off global activator
|
||||
"noise" wav file to play
|
||||
|
||||
A global sound will play full volume throughout the level.
|
||||
Activator sounds will play on the player that activated the target.
|
||||
Global and activator sounds can't be combined with looping.
|
||||
Normal sounds play each time the target is used.
|
||||
Looped sounds will be toggled by use functions.
|
||||
Multiple identical looping sounds will just increase volume without any speed cost.
|
||||
"wait" : Seconds between auto triggerings, 0 = don't auto trigger
|
||||
"random" wait variance, default is 0
|
||||
*/
|
||||
void Use_Target_Speaker (gentity_t *ent, gentity_t *other, gentity_t *activator) {
|
||||
if (ent->spawnflags & 3) { // looping sound toggles
|
||||
if (ent->s.loopSound)
|
||||
ent->s.loopSound = 0; // turn it off
|
||||
else
|
||||
ent->s.loopSound = ent->noise_index; // start it
|
||||
}else { // normal sound
|
||||
if ( ent->spawnflags & 8 ) {
|
||||
G_AddEvent( activator, EV_GENERAL_SOUND, ent->noise_index );
|
||||
} else if (ent->spawnflags & 4) {
|
||||
G_AddEvent( ent, EV_GLOBAL_SOUND, ent->noise_index );
|
||||
} else {
|
||||
G_AddEvent( ent, EV_GENERAL_SOUND, ent->noise_index );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SP_target_speaker( gentity_t *ent ) {
|
||||
char buffer[MAX_QPATH];
|
||||
char *s;
|
||||
|
||||
G_SpawnFloat( "wait", "0", &ent->wait );
|
||||
G_SpawnFloat( "random", "0", &ent->random );
|
||||
|
||||
if ( !G_SpawnString( "noise", "NOSOUND", &s ) ) {
|
||||
G_Error( "target_speaker without a noise key at %s", vtos( ent->s.origin ) );
|
||||
}
|
||||
|
||||
// force all client reletive sounds to be "activator" speakers that
|
||||
// play on the entity that activates it
|
||||
if ( s[0] == '*' ) {
|
||||
ent->spawnflags |= 8;
|
||||
}
|
||||
|
||||
if (!strstr( s, ".wav" )) {
|
||||
Com_sprintf (buffer, sizeof(buffer), "%s.wav", s );
|
||||
} else {
|
||||
Q_strncpyz( buffer, s, sizeof(buffer) );
|
||||
}
|
||||
ent->noise_index = G_SoundIndex(buffer);
|
||||
|
||||
// a repeating speaker can be done completely client side
|
||||
ent->s.eType = ET_SPEAKER;
|
||||
ent->s.eventParm = ent->noise_index;
|
||||
ent->s.frame = ent->wait * 10;
|
||||
ent->s.clientNum = ent->random * 10;
|
||||
|
||||
|
||||
// check for prestarted looping sound
|
||||
if ( ent->spawnflags & 1 ) {
|
||||
ent->s.loopSound = ent->noise_index;
|
||||
}
|
||||
|
||||
ent->use = Use_Target_Speaker;
|
||||
|
||||
if (ent->spawnflags & 4) {
|
||||
ent->r.svFlags |= SVF_BROADCAST;
|
||||
}
|
||||
|
||||
VectorCopy( ent->s.origin, ent->s.pos.trBase );
|
||||
|
||||
// must link the entity so we get areas and clusters so
|
||||
// the server can determine who to send updates to
|
||||
trap_LinkEntity( ent );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
/*QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON
|
||||
When triggered, fires a laser. You can either set a target or a direction.
|
||||
*/
|
||||
void target_laser_think (gentity_t *self) {
|
||||
vec3_t end;
|
||||
trace_t tr;
|
||||
vec3_t point;
|
||||
|
||||
// if pointed at another entity, set movedir to point at it
|
||||
if ( self->enemy ) {
|
||||
VectorMA (self->enemy->s.origin, 0.5, self->enemy->r.mins, point);
|
||||
VectorMA (point, 0.5, self->enemy->r.maxs, point);
|
||||
VectorSubtract (point, self->s.origin, self->movedir);
|
||||
VectorNormalize (self->movedir);
|
||||
}
|
||||
|
||||
// fire forward and see what we hit
|
||||
VectorMA (self->s.origin, 2048, self->movedir, end);
|
||||
|
||||
trap_Trace( &tr, self->s.origin, NULL, NULL, end, self->s.number, CONTENTS_SOLID|CONTENTS_BODY|CONTENTS_CORPSE);
|
||||
|
||||
if ( tr.entityNum ) {
|
||||
// hurt it if we can
|
||||
G_Damage ( &g_entities[tr.entityNum], self, self->activator, self->movedir,
|
||||
tr.endpos, self->damage, DAMAGE_NO_KNOCKBACK, MOD_TARGET_LASER);
|
||||
}
|
||||
|
||||
VectorCopy (tr.endpos, self->s.origin2);
|
||||
|
||||
trap_LinkEntity( self );
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
}
|
||||
|
||||
void target_laser_on (gentity_t *self)
|
||||
{
|
||||
if (!self->activator)
|
||||
self->activator = self;
|
||||
target_laser_think (self);
|
||||
}
|
||||
|
||||
void target_laser_off (gentity_t *self)
|
||||
{
|
||||
trap_UnlinkEntity( self );
|
||||
self->nextthink = 0;
|
||||
}
|
||||
|
||||
void target_laser_use (gentity_t *self, gentity_t *other, gentity_t *activator)
|
||||
{
|
||||
self->activator = activator;
|
||||
if ( self->nextthink > 0 )
|
||||
target_laser_off (self);
|
||||
else
|
||||
target_laser_on (self);
|
||||
}
|
||||
|
||||
void target_laser_start (gentity_t *self)
|
||||
{
|
||||
gentity_t *ent;
|
||||
|
||||
self->s.eType = ET_BEAM;
|
||||
|
||||
if (self->target) {
|
||||
ent = G_Find (NULL, FOFS(targetname), self->target);
|
||||
if (!ent) {
|
||||
G_Printf ("%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->damage ) {
|
||||
self->damage = 1;
|
||||
}
|
||||
|
||||
if (self->spawnflags & 1)
|
||||
target_laser_on (self);
|
||||
else
|
||||
target_laser_off (self);
|
||||
}
|
||||
|
||||
void SP_target_laser (gentity_t *self)
|
||||
{
|
||||
// let everything else get spawned before we start firing
|
||||
self->think = target_laser_start;
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
void target_teleporter_use( gentity_t *self, gentity_t *other, gentity_t *activator ) {
|
||||
gentity_t *dest;
|
||||
|
||||
if (!activator->client)
|
||||
return;
|
||||
dest = G_PickTarget( self->target );
|
||||
if (!dest) {
|
||||
G_Printf ("Couldn't find teleporter destination\n");
|
||||
return;
|
||||
}
|
||||
|
||||
TeleportPlayer( activator, dest->s.origin, dest->s.angles );
|
||||
}
|
||||
|
||||
/*QUAKED target_teleporter (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
The activator will be teleported away.
|
||||
*/
|
||||
void SP_target_teleporter( gentity_t *self ) {
|
||||
if (!self->targetname)
|
||||
G_Printf("untargeted %s at %s\n", self->classname, vtos(self->s.origin));
|
||||
|
||||
self->use = target_teleporter_use;
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
|
||||
/*QUAKED target_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) RED_ONLY BLUE_ONLY RANDOM
|
||||
This doesn't perform any actions except fire its targets.
|
||||
The activator can be forced to be from a certain team.
|
||||
if RANDOM is checked, only one of the targets will be fired, not all of them
|
||||
*/
|
||||
void target_relay_use (gentity_t *self, gentity_t *other, gentity_t *activator) {
|
||||
if ( ( self->spawnflags & 1 ) && activator->client
|
||||
&& activator->client->sess.sessionTeam != TEAM_RED ) {
|
||||
return;
|
||||
}
|
||||
if ( ( self->spawnflags & 2 ) && activator->client
|
||||
&& activator->client->sess.sessionTeam != TEAM_BLUE ) {
|
||||
return;
|
||||
}
|
||||
if ( self->spawnflags & 4 ) {
|
||||
gentity_t *ent;
|
||||
|
||||
ent = G_PickTarget( self->target );
|
||||
if ( ent && ent->use ) {
|
||||
ent->use( ent, self, activator );
|
||||
}
|
||||
return;
|
||||
}
|
||||
G_UseTargets (self, activator);
|
||||
}
|
||||
|
||||
void SP_target_relay (gentity_t *self) {
|
||||
self->use = target_relay_use;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
|
||||
/*QUAKED target_kill (.5 .5 .5) (-8 -8 -8) (8 8 8)
|
||||
Kills the activator.
|
||||
*/
|
||||
void target_kill_use( gentity_t *self, gentity_t *other, gentity_t *activator ) {
|
||||
G_Damage ( activator, NULL, NULL, NULL, NULL, 100000, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
|
||||
}
|
||||
|
||||
void SP_target_kill( gentity_t *self ) {
|
||||
self->use = target_kill_use;
|
||||
}
|
||||
|
||||
/*QUAKED target_position (0 0.5 0) (-4 -4 -4) (4 4 4)
|
||||
Used as a positional target for in-game calculation, like jumppad targets.
|
||||
*/
|
||||
void SP_target_position( gentity_t *self ){
|
||||
G_SetOrigin( self, self->s.origin );
|
||||
}
|
||||
|
||||
static void target_location_linkup(gentity_t *ent)
|
||||
{
|
||||
int i;
|
||||
int n;
|
||||
|
||||
if (level.locationLinked)
|
||||
return;
|
||||
|
||||
level.locationLinked = qtrue;
|
||||
|
||||
level.locationHead = NULL;
|
||||
|
||||
trap_SetConfigstring( CS_LOCATIONS, "unknown" );
|
||||
|
||||
for (i = 0, ent = g_entities, n = 1;
|
||||
i < level.num_entities;
|
||||
i++, ent++) {
|
||||
if (ent->classname && !Q_stricmp(ent->classname, "target_location")) {
|
||||
// lets overload some variables!
|
||||
ent->health = n; // use for location marking
|
||||
trap_SetConfigstring( CS_LOCATIONS + n, ent->message );
|
||||
n++;
|
||||
ent->nextTrain = level.locationHead;
|
||||
level.locationHead = ent;
|
||||
}
|
||||
}
|
||||
|
||||
// All linked together now
|
||||
}
|
||||
|
||||
/*QUAKED target_location (0 0.5 0) (-8 -8 -8) (8 8 8)
|
||||
Set "message" to the name of this location.
|
||||
Set "count" to 0-7 for color.
|
||||
0:white 1:red 2:green 3:yellow 4:blue 5:cyan 6:magenta 7:white
|
||||
|
||||
Closest target_location in sight used for the location, if none
|
||||
in site, closest in distance
|
||||
*/
|
||||
void SP_target_location( gentity_t *self ){
|
||||
self->think = target_location_linkup;
|
||||
self->nextthink = level.time + 200; // Let them all spawn first
|
||||
|
||||
G_SetOrigin( self, self->s.origin );
|
||||
}
|
||||
|
||||
+1483
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
|
||||
#define CTF_CAPTURE_BONUS 100 // what you get for capture
|
||||
#define CTF_TEAM_BONUS 25 // what your team gets for capture
|
||||
#define CTF_RECOVERY_BONUS 10 // what you get for recovery
|
||||
#define CTF_FLAG_BONUS 10 // what you get for picking up enemy flag
|
||||
#define CTF_FRAG_CARRIER_BONUS 20 // what you get for fragging enemy flag carrier
|
||||
#define CTF_FLAG_RETURN_TIME 40000 // seconds until auto return
|
||||
|
||||
#define CTF_CARRIER_DANGER_PROTECT_BONUS 5 // bonus for fraggin someone who has recently hurt your flag carrier
|
||||
#define CTF_CARRIER_PROTECT_BONUS 2 // bonus for fraggin someone while either you or your target are near your flag carrier
|
||||
#define CTF_FLAG_DEFENSE_BONUS 10 // bonus for fraggin someone while either you or your target are near your flag
|
||||
#define CTF_RETURN_FLAG_ASSIST_BONUS 10 // awarded for returning a flag that causes a capture to happen almost immediately
|
||||
#define CTF_FRAG_CARRIER_ASSIST_BONUS 10 // award for fragging a flag carrier if a capture happens almost immediately
|
||||
|
||||
#else
|
||||
|
||||
#define CTF_CAPTURE_BONUS 5 // what you get for capture
|
||||
#define CTF_TEAM_BONUS 0 // what your team gets for capture
|
||||
#define CTF_RECOVERY_BONUS 1 // what you get for recovery
|
||||
#define CTF_FLAG_BONUS 0 // what you get for picking up enemy flag
|
||||
#define CTF_FRAG_CARRIER_BONUS 2 // what you get for fragging enemy flag carrier
|
||||
#define CTF_FLAG_RETURN_TIME 40000 // seconds until auto return
|
||||
|
||||
#define CTF_CARRIER_DANGER_PROTECT_BONUS 2 // bonus for fraggin someone who has recently hurt your flag carrier
|
||||
#define CTF_CARRIER_PROTECT_BONUS 1 // bonus for fraggin someone while either you or your target are near your flag carrier
|
||||
#define CTF_FLAG_DEFENSE_BONUS 1 // bonus for fraggin someone while either you or your target are near your flag
|
||||
#define CTF_RETURN_FLAG_ASSIST_BONUS 1 // awarded for returning a flag that causes a capture to happen almost immediately
|
||||
#define CTF_FRAG_CARRIER_ASSIST_BONUS 2 // award for fragging a flag carrier if a capture happens almost immediately
|
||||
|
||||
#endif
|
||||
|
||||
#define CTF_TARGET_PROTECT_RADIUS 1000 // the radius around an object being defended where a target will be worth extra frags
|
||||
#define CTF_ATTACKER_PROTECT_RADIUS 1000 // the radius around an object being defended where an attacker will get extra frags when making kills
|
||||
|
||||
#define CTF_CARRIER_DANGER_PROTECT_TIMEOUT 8000
|
||||
#define CTF_FRAG_CARRIER_ASSIST_TIMEOUT 10000
|
||||
#define CTF_RETURN_FLAG_ASSIST_TIMEOUT 10000
|
||||
|
||||
#define CTF_GRAPPLE_SPEED 750 // speed of grapple in flight
|
||||
#define CTF_GRAPPLE_PULL_SPEED 750 // speed player is pulled at
|
||||
|
||||
#define OVERLOAD_ATTACK_BASE_SOUND_TIME 20000
|
||||
|
||||
// Prototypes
|
||||
|
||||
int OtherTeam(int team);
|
||||
const char *TeamName(int team);
|
||||
const char *OtherTeamName(int team);
|
||||
const char *TeamColorString(int team);
|
||||
void AddTeamScore(vec3_t origin, int team, int score);
|
||||
|
||||
void Team_DroppedFlagThink(gentity_t *ent);
|
||||
void Team_FragBonuses(gentity_t *targ, gentity_t *inflictor, gentity_t *attacker);
|
||||
void Team_CheckHurtCarrier(gentity_t *targ, gentity_t *attacker);
|
||||
void Team_InitGame(void);
|
||||
void Team_ReturnFlag(int team);
|
||||
void Team_FreeEntity(gentity_t *ent);
|
||||
gentity_t *SelectCTFSpawnPoint ( team_t team, int teamstate, vec3_t origin, vec3_t angles );
|
||||
gentity_t *Team_GetLocation(gentity_t *ent);
|
||||
qboolean Team_GetLocationMsg(gentity_t *ent, char *loc, int loclen);
|
||||
void TeamplayInfoMessage( gentity_t *ent );
|
||||
void CheckTeamStatus(void);
|
||||
|
||||
int Pickup_Team( gentity_t *ent, gentity_t *other );
|
||||
@@ -0,0 +1,465 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
#include "g_local.h"
|
||||
|
||||
|
||||
void InitTrigger( gentity_t *self ) {
|
||||
if (!VectorCompare (self->s.angles, vec3_origin))
|
||||
G_SetMovedir (self->s.angles, self->movedir);
|
||||
|
||||
trap_SetBrushModel( self, self->model );
|
||||
self->r.contents = CONTENTS_TRIGGER; // replaces the -1 from trap_SetBrushModel
|
||||
self->r.svFlags = SVF_NOCLIENT;
|
||||
}
|
||||
|
||||
|
||||
// the wait time has passed, so set back up for another activation
|
||||
void multi_wait( gentity_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( gentity_t *ent, gentity_t *activator ) {
|
||||
ent->activator = activator;
|
||||
if ( ent->nextthink ) {
|
||||
return; // can't retrigger until the wait is over
|
||||
}
|
||||
|
||||
if ( activator->client ) {
|
||||
if ( ( ent->spawnflags & 1 ) &&
|
||||
activator->client->sess.sessionTeam != TEAM_RED ) {
|
||||
return;
|
||||
}
|
||||
if ( ( ent->spawnflags & 2 ) &&
|
||||
activator->client->sess.sessionTeam != TEAM_BLUE ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
G_UseTargets (ent, ent->activator);
|
||||
|
||||
if ( ent->wait > 0 ) {
|
||||
ent->think = multi_wait;
|
||||
ent->nextthink = level.time + ( ent->wait + ent->random * crandom() ) * 1000;
|
||||
} else {
|
||||
// we can't just remove (self) here, because this is a touch function
|
||||
// called while looping through area links...
|
||||
ent->touch = 0;
|
||||
ent->nextthink = level.time + FRAMETIME;
|
||||
ent->think = G_FreeEntity;
|
||||
}
|
||||
}
|
||||
|
||||
void Use_Multi( gentity_t *ent, gentity_t *other, gentity_t *activator ) {
|
||||
multi_trigger( ent, activator );
|
||||
}
|
||||
|
||||
void Touch_Multi( gentity_t *self, gentity_t *other, trace_t *trace ) {
|
||||
if( !other->client ) {
|
||||
return;
|
||||
}
|
||||
multi_trigger( self, other );
|
||||
}
|
||||
|
||||
/*QUAKED trigger_multiple (.5 .5 .5) ?
|
||||
"wait" : Seconds between triggerings, 0.5 default, -1 = one time only.
|
||||
"random" wait variance, default is 0
|
||||
Variable sized repeatable trigger. Must be targeted at one or more entities.
|
||||
so, the basic time between firing is a random time between
|
||||
(wait - random) and (wait + random)
|
||||
*/
|
||||
void SP_trigger_multiple( gentity_t *ent ) {
|
||||
G_SpawnFloat( "wait", "0.5", &ent->wait );
|
||||
G_SpawnFloat( "random", "0", &ent->random );
|
||||
|
||||
if ( ent->random >= ent->wait && ent->wait >= 0 ) {
|
||||
ent->random = ent->wait - FRAMETIME;
|
||||
G_Printf( "trigger_multiple has random >= wait\n" );
|
||||
}
|
||||
|
||||
ent->touch = Touch_Multi;
|
||||
ent->use = Use_Multi;
|
||||
|
||||
InitTrigger( ent );
|
||||
trap_LinkEntity (ent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
trigger_always
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
void trigger_always_think( gentity_t *ent ) {
|
||||
G_UseTargets(ent, ent);
|
||||
G_FreeEntity( ent );
|
||||
}
|
||||
|
||||
/*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 (gentity_t *ent) {
|
||||
// we must have some delay to make sure our use targets are present
|
||||
ent->nextthink = level.time + 300;
|
||||
ent->think = trigger_always_think;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
trigger_push
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
void trigger_push_touch (gentity_t *self, gentity_t *other, trace_t *trace ) {
|
||||
|
||||
if ( !other->client ) {
|
||||
return;
|
||||
}
|
||||
|
||||
BG_TouchJumpPad( &other->client->ps, &self->s );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
AimAtTarget
|
||||
|
||||
Calculate origin2 so the target apogee will be hit
|
||||
=================
|
||||
*/
|
||||
void AimAtTarget( gentity_t *self ) {
|
||||
gentity_t *ent;
|
||||
vec3_t origin;
|
||||
float height, gravity, time, forward;
|
||||
float dist;
|
||||
|
||||
VectorAdd( self->r.absmin, self->r.absmax, origin );
|
||||
VectorScale ( origin, 0.5, origin );
|
||||
|
||||
ent = G_PickTarget( self->target );
|
||||
if ( !ent ) {
|
||||
G_FreeEntity( self );
|
||||
return;
|
||||
}
|
||||
|
||||
height = ent->s.origin[2] - origin[2];
|
||||
gravity = g_gravity.value;
|
||||
time = sqrt( height / ( .5 * gravity ) );
|
||||
if ( !time ) {
|
||||
G_FreeEntity( self );
|
||||
return;
|
||||
}
|
||||
|
||||
// set s.origin2 to the push velocity
|
||||
VectorSubtract ( ent->s.origin, origin, self->s.origin2 );
|
||||
self->s.origin2[2] = 0;
|
||||
dist = VectorNormalize( self->s.origin2);
|
||||
|
||||
forward = dist / time;
|
||||
VectorScale( self->s.origin2, forward, self->s.origin2 );
|
||||
|
||||
self->s.origin2[2] = time * gravity;
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED trigger_push (.5 .5 .5) ?
|
||||
Must point at a target_position, which will be the apex of the leap.
|
||||
This will be client side predicted, unlike target_push
|
||||
*/
|
||||
void SP_trigger_push( gentity_t *self ) {
|
||||
InitTrigger (self);
|
||||
|
||||
// unlike other triggers, we need to send this one to the client
|
||||
self->r.svFlags &= ~SVF_NOCLIENT;
|
||||
|
||||
// make sure the client precaches this sound
|
||||
G_SoundIndex("sound/world/jumppad.wav");
|
||||
|
||||
self->s.eType = ET_PUSH_TRIGGER;
|
||||
self->touch = trigger_push_touch;
|
||||
self->think = AimAtTarget;
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
trap_LinkEntity (self);
|
||||
}
|
||||
|
||||
|
||||
void Use_target_push( gentity_t *self, gentity_t *other, gentity_t *activator ) {
|
||||
if ( !activator->client ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( activator->client->ps.pm_type != PM_NORMAL ) {
|
||||
return;
|
||||
}
|
||||
if ( activator->client->ps.powerups[PW_FLIGHT] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
VectorCopy (self->s.origin2, activator->client->ps.velocity);
|
||||
|
||||
// play fly sound every 1.5 seconds
|
||||
if ( activator->fly_sound_debounce_time < level.time ) {
|
||||
activator->fly_sound_debounce_time = level.time + 1500;
|
||||
G_Sound( activator, CHAN_AUTO, self->noise_index );
|
||||
}
|
||||
}
|
||||
|
||||
/*QUAKED target_push (.5 .5 .5) (-8 -8 -8) (8 8 8) bouncepad
|
||||
Pushes the activator in the direction.of angle, or towards a target apex.
|
||||
"speed" defaults to 1000
|
||||
if "bouncepad", play bounce noise instead of windfly
|
||||
*/
|
||||
void SP_target_push( gentity_t *self ) {
|
||||
if (!self->speed) {
|
||||
self->speed = 1000;
|
||||
}
|
||||
G_SetMovedir (self->s.angles, self->s.origin2);
|
||||
VectorScale (self->s.origin2, self->speed, self->s.origin2);
|
||||
|
||||
if ( self->spawnflags & 1 ) {
|
||||
self->noise_index = G_SoundIndex("sound/world/jumppad.wav");
|
||||
} else {
|
||||
self->noise_index = G_SoundIndex("sound/misc/windfly.wav");
|
||||
}
|
||||
if ( self->target ) {
|
||||
VectorCopy( self->s.origin, self->r.absmin );
|
||||
VectorCopy( self->s.origin, self->r.absmax );
|
||||
self->think = AimAtTarget;
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
}
|
||||
self->use = Use_target_push;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
trigger_teleport
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
void trigger_teleporter_touch (gentity_t *self, gentity_t *other, trace_t *trace ) {
|
||||
gentity_t *dest;
|
||||
|
||||
if ( !other->client ) {
|
||||
return;
|
||||
}
|
||||
if ( other->client->ps.pm_type == PM_DEAD ) {
|
||||
return;
|
||||
}
|
||||
// Spectators only?
|
||||
if ( ( self->spawnflags & 1 ) &&
|
||||
other->client->sess.sessionTeam != TEAM_SPECTATOR ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
dest = G_PickTarget( self->target );
|
||||
if (!dest) {
|
||||
G_Printf ("Couldn't find teleporter destination\n");
|
||||
return;
|
||||
}
|
||||
|
||||
TeleportPlayer( other, dest->s.origin, dest->s.angles );
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED trigger_teleport (.5 .5 .5) ? SPECTATOR
|
||||
Allows client side prediction of teleportation events.
|
||||
Must point at a target_position, which will be the teleport destination.
|
||||
|
||||
If spectator is set, only spectators can use this teleport
|
||||
Spectator teleporters are not normally placed in the editor, but are created
|
||||
automatically near doors to allow spectators to move through them
|
||||
*/
|
||||
void SP_trigger_teleport( gentity_t *self ) {
|
||||
InitTrigger (self);
|
||||
|
||||
// unlike other triggers, we need to send this one to the client
|
||||
// unless is a spectator trigger
|
||||
if ( self->spawnflags & 1 ) {
|
||||
self->r.svFlags |= SVF_NOCLIENT;
|
||||
} else {
|
||||
self->r.svFlags &= ~SVF_NOCLIENT;
|
||||
}
|
||||
|
||||
// make sure the client precaches this sound
|
||||
G_SoundIndex("sound/world/jumppad.wav");
|
||||
|
||||
self->s.eType = ET_TELEPORT_TRIGGER;
|
||||
self->touch = trigger_teleporter_touch;
|
||||
|
||||
trap_LinkEntity (self);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
trigger_hurt
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*QUAKED trigger_hurt (.5 .5 .5) ? START_OFF - SILENT NO_PROTECTION SLOW
|
||||
Any entity that touches this will be hurt.
|
||||
It does dmg points of damage each server frame
|
||||
Targeting the trigger will toggle its on / off state.
|
||||
|
||||
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( gentity_t *self, gentity_t *other, gentity_t *activator ) {
|
||||
if ( self->r.linked ) {
|
||||
trap_UnlinkEntity( self );
|
||||
} else {
|
||||
trap_LinkEntity( self );
|
||||
}
|
||||
}
|
||||
|
||||
void hurt_touch( gentity_t *self, gentity_t *other, trace_t *trace ) {
|
||||
int dflags;
|
||||
|
||||
if ( !other->takedamage ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self->timestamp > level.time ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self->spawnflags & 16 ) {
|
||||
self->timestamp = level.time + 1000;
|
||||
} else {
|
||||
self->timestamp = level.time + FRAMETIME;
|
||||
}
|
||||
|
||||
// play sound
|
||||
if ( !(self->spawnflags & 4) ) {
|
||||
G_Sound( other, CHAN_AUTO, self->noise_index );
|
||||
}
|
||||
|
||||
if (self->spawnflags & 8)
|
||||
dflags = DAMAGE_NO_PROTECTION;
|
||||
else
|
||||
dflags = 0;
|
||||
G_Damage (other, self, self, NULL, NULL, self->damage, dflags, MOD_TRIGGER_HURT);
|
||||
}
|
||||
|
||||
void SP_trigger_hurt( gentity_t *self ) {
|
||||
InitTrigger (self);
|
||||
|
||||
self->noise_index = G_SoundIndex( "sound/world/electro.wav" );
|
||||
self->touch = hurt_touch;
|
||||
|
||||
if ( !self->damage ) {
|
||||
self->damage = 5;
|
||||
}
|
||||
|
||||
self->r.contents = CONTENTS_TRIGGER;
|
||||
|
||||
if ( self->spawnflags & 2 ) {
|
||||
self->use = hurt_use;
|
||||
}
|
||||
|
||||
// link in to the world if starting active
|
||||
if ( ! (self->spawnflags & 1) ) {
|
||||
trap_LinkEntity (self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
timer
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
/*QUAKED func_timer (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) START_ON
|
||||
This should be renamed trigger_timer...
|
||||
Repeatedly fires its targets.
|
||||
Can be turned on or off by using.
|
||||
|
||||
"wait" base time between triggering all targets, default is 1
|
||||
"random" wait variance, default is 0
|
||||
so, the basic time between firing is a random time between
|
||||
(wait - random) and (wait + random)
|
||||
|
||||
*/
|
||||
void func_timer_think( gentity_t *self ) {
|
||||
G_UseTargets (self, self->activator);
|
||||
// set time before next firing
|
||||
self->nextthink = level.time + 1000 * ( self->wait + crandom() * self->random );
|
||||
}
|
||||
|
||||
void func_timer_use( gentity_t *self, gentity_t *other, gentity_t *activator ) {
|
||||
self->activator = activator;
|
||||
|
||||
// if on, turn it off
|
||||
if ( self->nextthink ) {
|
||||
self->nextthink = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// turn it on
|
||||
func_timer_think (self);
|
||||
}
|
||||
|
||||
void SP_func_timer( gentity_t *self ) {
|
||||
G_SpawnFloat( "random", "1", &self->random);
|
||||
G_SpawnFloat( "wait", "1", &self->wait );
|
||||
|
||||
self->use = func_timer_use;
|
||||
self->think = func_timer_think;
|
||||
|
||||
if ( self->random >= self->wait ) {
|
||||
self->random = self->wait - FRAMETIME;
|
||||
G_Printf( "func_timer at %s has random >= wait\n", vtos( self->s.origin ) );
|
||||
}
|
||||
|
||||
if ( self->spawnflags & 1 ) {
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
self->activator = self;
|
||||
}
|
||||
|
||||
self->r.svFlags = SVF_NOCLIENT;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
// g_utils.c -- misc utility functions for game module
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
typedef struct {
|
||||
char oldShader[MAX_QPATH];
|
||||
char newShader[MAX_QPATH];
|
||||
float timeOffset;
|
||||
} shaderRemap_t;
|
||||
|
||||
#define MAX_SHADER_REMAPS 128
|
||||
|
||||
int remapCount = 0;
|
||||
shaderRemap_t remappedShaders[MAX_SHADER_REMAPS];
|
||||
|
||||
void AddRemap(const char *oldShader, const char *newShader, float timeOffset) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < remapCount; i++) {
|
||||
if (Q_stricmp(oldShader, remappedShaders[i].oldShader) == 0) {
|
||||
// found it, just update this one
|
||||
strcpy(remappedShaders[i].newShader,newShader);
|
||||
remappedShaders[i].timeOffset = timeOffset;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (remapCount < MAX_SHADER_REMAPS) {
|
||||
strcpy(remappedShaders[remapCount].newShader,newShader);
|
||||
strcpy(remappedShaders[remapCount].oldShader,oldShader);
|
||||
remappedShaders[remapCount].timeOffset = timeOffset;
|
||||
remapCount++;
|
||||
}
|
||||
}
|
||||
|
||||
const char *BuildShaderStateConfig() {
|
||||
static char buff[MAX_STRING_CHARS*4];
|
||||
char out[(MAX_QPATH * 2) + 5];
|
||||
int i;
|
||||
|
||||
memset(buff, 0, MAX_STRING_CHARS);
|
||||
for (i = 0; i < remapCount; i++) {
|
||||
Com_sprintf(out, (MAX_QPATH * 2) + 5, "%s=%s:%5.2f@", remappedShaders[i].oldShader, remappedShaders[i].newShader, remappedShaders[i].timeOffset);
|
||||
Q_strcat( buff, sizeof( buff ), out);
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
model / sound configstring indexes
|
||||
|
||||
=========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
================
|
||||
G_FindConfigstringIndex
|
||||
|
||||
================
|
||||
*/
|
||||
int G_FindConfigstringIndex( char *name, int start, int max, qboolean create ) {
|
||||
int i;
|
||||
char s[MAX_STRING_CHARS];
|
||||
|
||||
if ( !name || !name[0] ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( i=1 ; i<max ; i++ ) {
|
||||
trap_GetConfigstring( start + i, s, sizeof( s ) );
|
||||
if ( !s[0] ) {
|
||||
break;
|
||||
}
|
||||
if ( !strcmp( s, name ) ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !create ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( i == max ) {
|
||||
G_Error( "G_FindConfigstringIndex: overflow" );
|
||||
}
|
||||
|
||||
trap_SetConfigstring( start + i, name );
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
int G_ModelIndex( char *name ) {
|
||||
return G_FindConfigstringIndex (name, CS_MODELS, MAX_MODELS, qtrue);
|
||||
}
|
||||
|
||||
int G_SoundIndex( char *name ) {
|
||||
return G_FindConfigstringIndex (name, CS_SOUNDS, MAX_SOUNDS, qtrue);
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
G_TeamCommand
|
||||
|
||||
Broadcasts a command to only a specific team
|
||||
================
|
||||
*/
|
||||
void G_TeamCommand( team_t team, char *cmd ) {
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < level.maxclients ; i++ ) {
|
||||
if ( level.clients[i].pers.connected == CON_CONNECTED ) {
|
||||
if ( level.clients[i].sess.sessionTeam == team ) {
|
||||
trap_SendServerCommand( i, va("%s", cmd ));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
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 entity after from, or the beginning if NULL
|
||||
NULL will be returned if the end of the list is reached.
|
||||
|
||||
=============
|
||||
*/
|
||||
gentity_t *G_Find (gentity_t *from, int fieldofs, const char *match)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (!from)
|
||||
from = g_entities;
|
||||
else
|
||||
from++;
|
||||
|
||||
for ( ; from < &g_entities[level.num_entities] ; from++)
|
||||
{
|
||||
if (!from->inuse)
|
||||
continue;
|
||||
s = *(char **) ((byte *)from + fieldofs);
|
||||
if (!s)
|
||||
continue;
|
||||
if (!Q_stricmp (s, match))
|
||||
return from;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
G_PickTarget
|
||||
|
||||
Selects a random entity from among the targets
|
||||
=============
|
||||
*/
|
||||
#define MAXCHOICES 32
|
||||
|
||||
gentity_t *G_PickTarget (char *targetname)
|
||||
{
|
||||
gentity_t *ent = NULL;
|
||||
int num_choices = 0;
|
||||
gentity_t *choice[MAXCHOICES];
|
||||
|
||||
if (!targetname)
|
||||
{
|
||||
G_Printf("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)
|
||||
{
|
||||
G_Printf("G_PickTarget: target %s not found\n", targetname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return choice[rand() % num_choices];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================
|
||||
G_UseTargets
|
||||
|
||||
"activator" should be set to the entity that initiated the firing.
|
||||
|
||||
Search for (string)targetname in all entities that
|
||||
match (string)self.target and call their .use function
|
||||
|
||||
==============================
|
||||
*/
|
||||
void G_UseTargets( gentity_t *ent, gentity_t *activator ) {
|
||||
gentity_t *t;
|
||||
|
||||
if ( !ent ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ent->targetShaderName && ent->targetShaderNewName) {
|
||||
float f = level.time * 0.001;
|
||||
AddRemap(ent->targetShaderName, ent->targetShaderNewName, f);
|
||||
trap_SetConfigstring(CS_SHADERSTATE, BuildShaderStateConfig());
|
||||
}
|
||||
|
||||
if ( !ent->target ) {
|
||||
return;
|
||||
}
|
||||
|
||||
t = NULL;
|
||||
while ( (t = G_Find (t, FOFS(targetname), ent->target)) != NULL ) {
|
||||
if ( t == ent ) {
|
||||
G_Printf ("WARNING: Entity used itself.\n");
|
||||
} else {
|
||||
if ( t->use ) {
|
||||
t->use (t, ent, activator);
|
||||
}
|
||||
}
|
||||
if ( !ent->inuse ) {
|
||||
G_Printf("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( const 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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
G_SetMovedir
|
||||
|
||||
The editor only specifies a single value for angles (yaw),
|
||||
but we have special constants to generate an up or down direction.
|
||||
Angles will be cleared, because it is being used to represent a direction
|
||||
instead of an orientation.
|
||||
===============
|
||||
*/
|
||||
void G_SetMovedir( vec3_t angles, vec3_t movedir ) {
|
||||
static vec3_t VEC_UP = {0, -1, 0};
|
||||
static vec3_t MOVEDIR_UP = {0, 0, 1};
|
||||
static vec3_t VEC_DOWN = {0, -2, 0};
|
||||
static vec3_t MOVEDIR_DOWN = {0, 0, -1};
|
||||
|
||||
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( const vec3_t vec ) {
|
||||
float yaw;
|
||||
|
||||
if (vec[YAW] == 0 && vec[PITCH] == 0) {
|
||||
yaw = 0;
|
||||
} else {
|
||||
if (vec[PITCH]) {
|
||||
yaw = ( atan2( vec[YAW], vec[PITCH]) * 180 / M_PI );
|
||||
} else if (vec[YAW] > 0) {
|
||||
yaw = 90;
|
||||
} else {
|
||||
yaw = 270;
|
||||
}
|
||||
if (yaw < 0) {
|
||||
yaw += 360;
|
||||
}
|
||||
}
|
||||
|
||||
return yaw;
|
||||
}
|
||||
|
||||
|
||||
void G_InitGentity( gentity_t *e ) {
|
||||
e->inuse = qtrue;
|
||||
e->classname = "noclass";
|
||||
e->s.number = e - g_entities;
|
||||
e->r.ownerNum = ENTITYNUM_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
G_Spawn
|
||||
|
||||
Either finds a free entity, or allocates a new one.
|
||||
|
||||
The slots from 0 to MAX_CLIENTS-1 are always reserved for clients, and will
|
||||
never be used by anything else.
|
||||
|
||||
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.
|
||||
=================
|
||||
*/
|
||||
gentity_t *G_Spawn( void ) {
|
||||
int i, force;
|
||||
gentity_t *e;
|
||||
|
||||
e = NULL; // shut up warning
|
||||
i = 0; // shut up warning
|
||||
for ( force = 0 ; force < 2 ; force++ ) {
|
||||
// if we go through all entities and can't find one to free,
|
||||
// override the normal minimum times before use
|
||||
e = &g_entities[MAX_CLIENTS];
|
||||
for ( i = MAX_CLIENTS ; i<level.num_entities ; i++, e++) {
|
||||
if ( e->inuse ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// the first couple seconds of server time can involve a lot of
|
||||
// freeing and allocating, so relax the replacement policy
|
||||
if ( !force && e->freetime > level.startTime + 2000 && level.time - e->freetime < 1000 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// reuse this slot
|
||||
G_InitGentity( e );
|
||||
return e;
|
||||
}
|
||||
if ( i != MAX_GENTITIES ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i == ENTITYNUM_MAX_NORMAL ) {
|
||||
for (i = 0; i < MAX_GENTITIES; i++) {
|
||||
G_Printf("%4i: %s\n", i, g_entities[i].classname);
|
||||
}
|
||||
G_Error( "G_Spawn: no free entities" );
|
||||
}
|
||||
|
||||
// open up a new slot
|
||||
level.num_entities++;
|
||||
|
||||
// let the server system know that there are more entities
|
||||
trap_LocateGameData( level.gentities, level.num_entities, sizeof( gentity_t ),
|
||||
&level.clients[0].ps, sizeof( level.clients[0] ) );
|
||||
|
||||
G_InitGentity( e );
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
G_EntitiesFree
|
||||
=================
|
||||
*/
|
||||
qboolean G_EntitiesFree( void ) {
|
||||
int i;
|
||||
gentity_t *e;
|
||||
|
||||
e = &g_entities[MAX_CLIENTS];
|
||||
for ( i = MAX_CLIENTS; i < level.num_entities; i++, e++) {
|
||||
if ( e->inuse ) {
|
||||
continue;
|
||||
}
|
||||
// slot available
|
||||
return qtrue;
|
||||
}
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
G_FreeEntity
|
||||
|
||||
Marks the entity as free
|
||||
=================
|
||||
*/
|
||||
void G_FreeEntity( gentity_t *ed ) {
|
||||
trap_UnlinkEntity (ed); // unlink from world
|
||||
|
||||
if ( ed->neverFree ) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset (ed, 0, sizeof(*ed));
|
||||
ed->classname = "freed";
|
||||
ed->freetime = level.time;
|
||||
ed->inuse = qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
G_TempEntity
|
||||
|
||||
Spawns an event entity that will be auto-removed
|
||||
The origin will be snapped to save net bandwidth, so care
|
||||
must be taken if the origin is right on a surface (snap towards start vector first)
|
||||
=================
|
||||
*/
|
||||
gentity_t *G_TempEntity( vec3_t origin, int event ) {
|
||||
gentity_t *e;
|
||||
vec3_t snapped;
|
||||
|
||||
e = G_Spawn();
|
||||
e->s.eType = ET_EVENTS + event;
|
||||
|
||||
e->classname = "tempEntity";
|
||||
e->eventTime = level.time;
|
||||
e->freeAfterEvent = qtrue;
|
||||
|
||||
VectorCopy( origin, snapped );
|
||||
SnapVector( snapped ); // save network bandwidth
|
||||
G_SetOrigin( e, snapped );
|
||||
|
||||
// find cluster for PVS
|
||||
trap_LinkEntity( e );
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
Kill box
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=================
|
||||
G_KillBox
|
||||
|
||||
Kills all entities that would touch the proposed new positioning
|
||||
of ent. Ent should be unlinked before calling this!
|
||||
=================
|
||||
*/
|
||||
void G_KillBox (gentity_t *ent) {
|
||||
int i, num;
|
||||
int touch[MAX_GENTITIES];
|
||||
gentity_t *hit;
|
||||
vec3_t mins, maxs;
|
||||
|
||||
VectorAdd( ent->client->ps.origin, ent->r.mins, mins );
|
||||
VectorAdd( ent->client->ps.origin, ent->r.maxs, maxs );
|
||||
num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );
|
||||
|
||||
for (i=0 ; i<num ; i++) {
|
||||
hit = &g_entities[touch[i]];
|
||||
if ( !hit->client ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// nail it
|
||||
G_Damage ( hit, ent, ent, NULL, NULL,
|
||||
100000, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
===============
|
||||
G_AddPredictableEvent
|
||||
|
||||
Use for non-pmove events that would also be predicted on the
|
||||
client side: jumppads and item pickups
|
||||
Adds an event+parm and twiddles the event counter
|
||||
===============
|
||||
*/
|
||||
void G_AddPredictableEvent( gentity_t *ent, int event, int eventParm ) {
|
||||
if ( !ent->client ) {
|
||||
return;
|
||||
}
|
||||
BG_AddPredictableEventToPlayerstate( event, eventParm, &ent->client->ps );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
G_AddEvent
|
||||
|
||||
Adds an event+parm and twiddles the event counter
|
||||
===============
|
||||
*/
|
||||
void G_AddEvent( gentity_t *ent, int event, int eventParm ) {
|
||||
int bits;
|
||||
|
||||
if ( !event ) {
|
||||
G_Printf( "G_AddEvent: zero event added for entity %i\n", ent->s.number );
|
||||
return;
|
||||
}
|
||||
|
||||
// clients need to add the event in playerState_t instead of entityState_t
|
||||
if ( ent->client ) {
|
||||
bits = ent->client->ps.externalEvent & EV_EVENT_BITS;
|
||||
bits = ( bits + EV_EVENT_BIT1 ) & EV_EVENT_BITS;
|
||||
ent->client->ps.externalEvent = event | bits;
|
||||
ent->client->ps.externalEventParm = eventParm;
|
||||
ent->client->ps.externalEventTime = level.time;
|
||||
} else {
|
||||
bits = ent->s.event & EV_EVENT_BITS;
|
||||
bits = ( bits + EV_EVENT_BIT1 ) & EV_EVENT_BITS;
|
||||
ent->s.event = event | bits;
|
||||
ent->s.eventParm = eventParm;
|
||||
}
|
||||
ent->eventTime = level.time;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
G_Sound
|
||||
=============
|
||||
*/
|
||||
void G_Sound( gentity_t *ent, int channel, int soundIndex ) {
|
||||
gentity_t *te;
|
||||
|
||||
te = G_TempEntity( ent->r.currentOrigin, EV_GENERAL_SOUND );
|
||||
te->s.eventParm = soundIndex;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
G_SetOrigin
|
||||
|
||||
Sets the pos trajectory for a fixed position
|
||||
================
|
||||
*/
|
||||
void G_SetOrigin( gentity_t *ent, vec3_t origin ) {
|
||||
VectorCopy( origin, ent->s.pos.trBase );
|
||||
ent->s.pos.trType = TR_STATIONARY;
|
||||
ent->s.pos.trTime = 0;
|
||||
ent->s.pos.trDuration = 0;
|
||||
VectorClear( ent->s.pos.trDelta );
|
||||
|
||||
VectorCopy( origin, ent->r.currentOrigin );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DebugLine
|
||||
|
||||
debug polygons only work when running a local game
|
||||
with r_debugSurface set to 2
|
||||
================
|
||||
*/
|
||||
int DebugLine(vec3_t start, vec3_t end, int color) {
|
||||
vec3_t points[4], dir, cross, up = {0, 0, 1};
|
||||
float dot;
|
||||
|
||||
VectorCopy(start, points[0]);
|
||||
VectorCopy(start, points[1]);
|
||||
//points[1][2] -= 2;
|
||||
VectorCopy(end, points[2]);
|
||||
//points[2][2] -= 2;
|
||||
VectorCopy(end, points[3]);
|
||||
|
||||
|
||||
VectorSubtract(end, start, dir);
|
||||
VectorNormalize(dir);
|
||||
dot = DotProduct(dir, up);
|
||||
if (dot > 0.99 || dot < -0.99) VectorSet(cross, 1, 0, 0);
|
||||
else CrossProduct(dir, up, cross);
|
||||
|
||||
VectorNormalize(cross);
|
||||
|
||||
VectorMA(points[0], 2, cross, points[0]);
|
||||
VectorMA(points[1], -2, cross, points[1]);
|
||||
VectorMA(points[2], -2, cross, points[2]);
|
||||
VectorMA(points[3], 2, cross, points[3]);
|
||||
|
||||
return trap_DebugPolygonCreate(color, 4, points);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,85 @@
|
||||
rem make sure we have a safe environement
|
||||
set LIBRARY=
|
||||
set INCLUDE=
|
||||
|
||||
mkdir vm
|
||||
cd vm
|
||||
set cc=lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui %1
|
||||
|
||||
%cc% ../g_main.c
|
||||
@if errorlevel 1 goto quit
|
||||
|
||||
%cc% ../g_syscalls.c
|
||||
@if errorlevel 1 goto quit
|
||||
|
||||
%cc% ../bg_misc.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../bg_lib.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../bg_pmove.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../bg_slidemove.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../q_math.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../q_shared.c
|
||||
@if errorlevel 1 goto quit
|
||||
|
||||
%cc% ../ai_dmnet.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_dmq3.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_main.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_chat.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_cmd.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_team.c
|
||||
@if errorlevel 1 goto quit
|
||||
|
||||
%cc% ../g_active.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_arenas.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_bot.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_client.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_cmds.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_combat.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_items.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_mem.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_misc.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_missile.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_mover.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_session.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_spawn.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_svcmds.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_target.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_team.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_trigger.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_utils.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_weapon.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_vcmd.c
|
||||
@if errorlevel 1 goto quit
|
||||
|
||||
|
||||
q3asm -f ../game
|
||||
:quit
|
||||
cd ..
|
||||
@@ -0,0 +1,3 @@
|
||||
EXPORTS
|
||||
dllEntry
|
||||
vmMain
|
||||
@@ -0,0 +1,35 @@
|
||||
-o "\quake3\baseq3\vm\qagame"
|
||||
g_main
|
||||
..\g_syscalls
|
||||
bg_misc
|
||||
bg_lib
|
||||
bg_pmove
|
||||
bg_slidemove
|
||||
q_math
|
||||
q_shared
|
||||
ai_dmnet
|
||||
ai_dmq3
|
||||
ai_team
|
||||
ai_main
|
||||
ai_chat
|
||||
ai_cmd
|
||||
ai_vcmd
|
||||
g_active
|
||||
g_arenas
|
||||
g_bot
|
||||
g_client
|
||||
g_cmds
|
||||
g_combat
|
||||
g_items
|
||||
g_mem
|
||||
g_misc
|
||||
g_missile
|
||||
g_mover
|
||||
g_session
|
||||
g_spawn
|
||||
g_svcmds
|
||||
g_target
|
||||
g_team
|
||||
g_trigger
|
||||
g_utils
|
||||
g_weapon
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
|
||||
mkdir -p vm
|
||||
cd vm
|
||||
|
||||
CC="q3lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g -I../../cgame -I../../game -I../../q3_ui"
|
||||
|
||||
$CC ../g_main.c
|
||||
$CC ../g_syscalls.c
|
||||
|
||||
$CC ../bg_misc.c
|
||||
$CC ../bg_lib.c
|
||||
$CC ../bg_pmove.c
|
||||
$CC ../bg_slidemove.c
|
||||
$CC ../q_math.c
|
||||
$CC ../q_shared.c
|
||||
|
||||
$CC ../ai_vcmd.c
|
||||
$CC ../ai_dmnet.c
|
||||
$CC ../ai_dmq3.c
|
||||
$CC ../ai_main.c
|
||||
$CC ../ai_chat.c
|
||||
$CC ../ai_cmd.c
|
||||
$CC ../ai_team.c
|
||||
|
||||
$CC ../g_active.c
|
||||
$CC ../g_arenas.c
|
||||
$CC ../g_bot.c
|
||||
$CC ../g_client.c
|
||||
$CC ../g_cmds.c
|
||||
$CC ../g_combat.c
|
||||
$CC ../g_items.c
|
||||
$CC ../g_mem.c
|
||||
$CC ../g_misc.c
|
||||
$CC ../g_missile.c
|
||||
$CC ../g_mover.c
|
||||
$CC ../g_session.c
|
||||
$CC ../g_spawn.c
|
||||
$CC ../g_svcmds.c
|
||||
$CC ../g_target.c
|
||||
$CC ../g_team.c
|
||||
$CC ../g_trigger.c
|
||||
$CC ../g_utils.c
|
||||
$CC ../g_weapon.c
|
||||
|
||||
q3asm -f ../game
|
||||
|
||||
cd ..
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
||||
rem make sure we have a safe environement
|
||||
set LIBRARY=
|
||||
set INCLUDE=
|
||||
|
||||
mkdir vm
|
||||
cd vm
|
||||
set cc=lcc -DQ3_VM -DMISSIONPACK -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui %1
|
||||
|
||||
%cc% ../g_main.c
|
||||
@if errorlevel 1 goto quit
|
||||
|
||||
%cc% ../g_syscalls.c
|
||||
@if errorlevel 1 goto quit
|
||||
|
||||
%cc% ../bg_misc.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../bg_lib.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../bg_pmove.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../bg_slidemove.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../q_math.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../q_shared.c
|
||||
@if errorlevel 1 goto quit
|
||||
|
||||
%cc% ../ai_dmnet.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_dmq3.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_main.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_chat.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_cmd.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_team.c
|
||||
@if errorlevel 1 goto quit
|
||||
|
||||
%cc% ../g_active.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_arenas.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_bot.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_client.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_cmds.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_combat.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_items.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_mem.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_misc.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_missile.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_mover.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_session.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_spawn.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_svcmds.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_target.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_team.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_trigger.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_utils.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../g_weapon.c
|
||||
@if errorlevel 1 goto quit
|
||||
%cc% ../ai_vcmd.c
|
||||
@if errorlevel 1 goto quit
|
||||
|
||||
|
||||
|
||||
q3asm -f ../game_ta
|
||||
:quit
|
||||
cd ..
|
||||
@@ -0,0 +1,35 @@
|
||||
-o "\quake3\missionpack\vm\qagame"
|
||||
g_main
|
||||
..\g_syscalls
|
||||
bg_misc
|
||||
bg_lib
|
||||
bg_pmove
|
||||
bg_slidemove
|
||||
q_math
|
||||
q_shared
|
||||
ai_dmnet
|
||||
ai_dmq3
|
||||
ai_team
|
||||
ai_main
|
||||
ai_chat
|
||||
ai_cmd
|
||||
g_active
|
||||
g_arenas
|
||||
g_bot
|
||||
g_client
|
||||
g_cmds
|
||||
g_combat
|
||||
g_items
|
||||
g_mem
|
||||
g_misc
|
||||
g_missile
|
||||
g_mover
|
||||
g_session
|
||||
g_spawn
|
||||
g_svcmds
|
||||
g_target
|
||||
g_team
|
||||
g_trigger
|
||||
g_utils
|
||||
g_weapon
|
||||
ai_vcmd
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
|
||||
mkdir -p vm
|
||||
cd vm
|
||||
|
||||
CC="q3lcc -DQ3_VM -DMISSIONPACK -S -Wf-target=bytecode -Wf-g -I../../cgame -I../../game -I../../ui"
|
||||
|
||||
$CC ../g_main.c
|
||||
$CC ../g_syscalls.c
|
||||
|
||||
$CC ../bg_misc.c
|
||||
$CC ../bg_lib.c
|
||||
$CC ../bg_pmove.c
|
||||
$CC ../bg_slidemove.c
|
||||
$CC ../q_math.c
|
||||
$CC ../q_shared.c
|
||||
|
||||
$CC ../ai_vcmd.c
|
||||
$CC ../ai_dmnet.c
|
||||
$CC ../ai_dmq3.c
|
||||
$CC ../ai_main.c
|
||||
$CC ../ai_chat.c
|
||||
$CC ../ai_cmd.c
|
||||
$CC ../ai_team.c
|
||||
|
||||
$CC ../g_active.c
|
||||
$CC ../g_arenas.c
|
||||
$CC ../g_bot.c
|
||||
$CC ../g_client.c
|
||||
$CC ../g_cmds.c
|
||||
$CC ../g_combat.c
|
||||
$CC ../g_items.c
|
||||
$CC ../g_mem.c
|
||||
$CC ../g_misc.c
|
||||
$CC ../g_missile.c
|
||||
$CC ../g_mover.c
|
||||
$CC ../g_session.c
|
||||
$CC ../g_spawn.c
|
||||
$CC ../g_svcmds.c
|
||||
$CC ../g_target.c
|
||||
$CC ../g_team.c
|
||||
$CC ../g_trigger.c
|
||||
$CC ../g_utils.c
|
||||
$CC ../g_weapon.c
|
||||
|
||||
q3asm -f ../game_ta
|
||||
|
||||
cd ..
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#define INVENTORY_NONE 0
|
||||
//armor
|
||||
#define INVENTORY_ARMOR 1
|
||||
//weapons
|
||||
#define INVENTORY_GAUNTLET 4
|
||||
#define INVENTORY_SHOTGUN 5
|
||||
#define INVENTORY_MACHINEGUN 6
|
||||
#define INVENTORY_GRENADELAUNCHER 7
|
||||
#define INVENTORY_ROCKETLAUNCHER 8
|
||||
#define INVENTORY_LIGHTNING 9
|
||||
#define INVENTORY_RAILGUN 10
|
||||
#define INVENTORY_PLASMAGUN 11
|
||||
#define INVENTORY_BFG10K 13
|
||||
#define INVENTORY_GRAPPLINGHOOK 14
|
||||
#define INVENTORY_NAILGUN 15
|
||||
#define INVENTORY_PROXLAUNCHER 16
|
||||
#define INVENTORY_CHAINGUN 17
|
||||
//ammo
|
||||
#define INVENTORY_SHELLS 18
|
||||
#define INVENTORY_BULLETS 19
|
||||
#define INVENTORY_GRENADES 20
|
||||
#define INVENTORY_CELLS 21
|
||||
#define INVENTORY_LIGHTNINGAMMO 22
|
||||
#define INVENTORY_ROCKETS 23
|
||||
#define INVENTORY_SLUGS 24
|
||||
#define INVENTORY_BFGAMMO 25
|
||||
#define INVENTORY_NAILS 26
|
||||
#define INVENTORY_MINES 27
|
||||
#define INVENTORY_BELT 28
|
||||
//powerups
|
||||
#define INVENTORY_HEALTH 29
|
||||
#define INVENTORY_TELEPORTER 30
|
||||
#define INVENTORY_MEDKIT 31
|
||||
#define INVENTORY_KAMIKAZE 32
|
||||
#define INVENTORY_PORTAL 33
|
||||
#define INVENTORY_INVULNERABILITY 34
|
||||
#define INVENTORY_QUAD 35
|
||||
#define INVENTORY_ENVIRONMENTSUIT 36
|
||||
#define INVENTORY_HASTE 37
|
||||
#define INVENTORY_INVISIBILITY 38
|
||||
#define INVENTORY_REGEN 39
|
||||
#define INVENTORY_FLIGHT 40
|
||||
#define INVENTORY_SCOUT 41
|
||||
#define INVENTORY_GUARD 42
|
||||
#define INVENTORY_DOUBLER 43
|
||||
#define INVENTORY_AMMOREGEN 44
|
||||
|
||||
#define INVENTORY_REDFLAG 45
|
||||
#define INVENTORY_BLUEFLAG 46
|
||||
#define INVENTORY_NEUTRALFLAG 47
|
||||
#define INVENTORY_REDCUBE 48
|
||||
#define INVENTORY_BLUECUBE 49
|
||||
//enemy stuff
|
||||
#define ENEMY_HORIZONTAL_DIST 200
|
||||
#define ENEMY_HEIGHT 201
|
||||
#define NUM_VISIBLE_ENEMIES 202
|
||||
#define NUM_VISIBLE_TEAMMATES 203
|
||||
|
||||
// if running the mission pack
|
||||
#ifdef MISSIONPACK
|
||||
|
||||
//#error "running mission pack"
|
||||
|
||||
#endif
|
||||
|
||||
//item numbers (make sure they are in sync with bg_itemlist in bg_misc.c)
|
||||
#define MODELINDEX_ARMORSHARD 1
|
||||
#define MODELINDEX_ARMORCOMBAT 2
|
||||
#define MODELINDEX_ARMORBODY 3
|
||||
#define MODELINDEX_HEALTHSMALL 4
|
||||
#define MODELINDEX_HEALTH 5
|
||||
#define MODELINDEX_HEALTHLARGE 6
|
||||
#define MODELINDEX_HEALTHMEGA 7
|
||||
|
||||
#define MODELINDEX_GAUNTLET 8
|
||||
#define MODELINDEX_SHOTGUN 9
|
||||
#define MODELINDEX_MACHINEGUN 10
|
||||
#define MODELINDEX_GRENADELAUNCHER 11
|
||||
#define MODELINDEX_ROCKETLAUNCHER 12
|
||||
#define MODELINDEX_LIGHTNING 13
|
||||
#define MODELINDEX_RAILGUN 14
|
||||
#define MODELINDEX_PLASMAGUN 15
|
||||
#define MODELINDEX_BFG10K 16
|
||||
#define MODELINDEX_GRAPPLINGHOOK 17
|
||||
|
||||
#define MODELINDEX_SHELLS 18
|
||||
#define MODELINDEX_BULLETS 19
|
||||
#define MODELINDEX_GRENADES 20
|
||||
#define MODELINDEX_CELLS 21
|
||||
#define MODELINDEX_LIGHTNINGAMMO 22
|
||||
#define MODELINDEX_ROCKETS 23
|
||||
#define MODELINDEX_SLUGS 24
|
||||
#define MODELINDEX_BFGAMMO 25
|
||||
|
||||
#define MODELINDEX_TELEPORTER 26
|
||||
#define MODELINDEX_MEDKIT 27
|
||||
#define MODELINDEX_QUAD 28
|
||||
#define MODELINDEX_ENVIRONMENTSUIT 29
|
||||
#define MODELINDEX_HASTE 30
|
||||
#define MODELINDEX_INVISIBILITY 31
|
||||
#define MODELINDEX_REGEN 32
|
||||
#define MODELINDEX_FLIGHT 33
|
||||
|
||||
#define MODELINDEX_REDFLAG 34
|
||||
#define MODELINDEX_BLUEFLAG 35
|
||||
|
||||
// mission pack only defines
|
||||
|
||||
#define MODELINDEX_KAMIKAZE 36
|
||||
#define MODELINDEX_PORTAL 37
|
||||
#define MODELINDEX_INVULNERABILITY 38
|
||||
|
||||
#define MODELINDEX_NAILS 39
|
||||
#define MODELINDEX_MINES 40
|
||||
#define MODELINDEX_BELT 41
|
||||
|
||||
#define MODELINDEX_SCOUT 42
|
||||
#define MODELINDEX_GUARD 43
|
||||
#define MODELINDEX_DOUBLER 44
|
||||
#define MODELINDEX_AMMOREGEN 45
|
||||
|
||||
#define MODELINDEX_NEUTRALFLAG 46
|
||||
#define MODELINDEX_REDCUBE 47
|
||||
#define MODELINDEX_BLUECUBE 48
|
||||
|
||||
#define MODELINDEX_NAILGUN 49
|
||||
#define MODELINDEX_PROXLAUNCHER 50
|
||||
#define MODELINDEX_CHAINGUN 51
|
||||
|
||||
|
||||
//
|
||||
#define WEAPONINDEX_GAUNTLET 1
|
||||
#define WEAPONINDEX_MACHINEGUN 2
|
||||
#define WEAPONINDEX_SHOTGUN 3
|
||||
#define WEAPONINDEX_GRENADE_LAUNCHER 4
|
||||
#define WEAPONINDEX_ROCKET_LAUNCHER 5
|
||||
#define WEAPONINDEX_LIGHTNING 6
|
||||
#define WEAPONINDEX_RAILGUN 7
|
||||
#define WEAPONINDEX_PLASMAGUN 8
|
||||
#define WEAPONINDEX_BFG 9
|
||||
#define WEAPONINDEX_GRAPPLING_HOOK 10
|
||||
#define WEAPONINDEX_NAILGUN 11
|
||||
#define WEAPONINDEX_PROXLAUNCHER 12
|
||||
#define WEAPONINDEX_CHAINGUN 13
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// make sure this is the same character as we use in chats in g_cmd.c
|
||||
#define EC "\x19"
|
||||
|
||||
//match template contexts
|
||||
#define MTCONTEXT_MISC 2
|
||||
#define MTCONTEXT_INITIALTEAMCHAT 4
|
||||
#define MTCONTEXT_TIME 8
|
||||
#define MTCONTEXT_TEAMMATE 16
|
||||
#define MTCONTEXT_ADDRESSEE 32
|
||||
#define MTCONTEXT_PATROLKEYAREA 64
|
||||
#define MTCONTEXT_REPLYCHAT 128
|
||||
#define MTCONTEXT_CTF 256
|
||||
|
||||
//message types
|
||||
#define MSG_NEWLEADER 1 //new leader
|
||||
#define MSG_ENTERGAME 2 //enter game message
|
||||
#define MSG_HELP 3 //help someone
|
||||
#define MSG_ACCOMPANY 4 //accompany someone
|
||||
#define MSG_DEFENDKEYAREA 5 //defend a key area
|
||||
#define MSG_RUSHBASE 6 //everyone rush to base
|
||||
#define MSG_GETFLAG 7 //get the enemy flag
|
||||
#define MSG_STARTTEAMLEADERSHIP 8 //someone wants to become the team leader
|
||||
#define MSG_STOPTEAMLEADERSHIP 9 //someone wants to stop being the team leader
|
||||
#define MSG_WHOISTEAMLAEDER 10 //who is the team leader
|
||||
#define MSG_WAIT 11 //wait for someone
|
||||
#define MSG_WHATAREYOUDOING 12 //what are you doing?
|
||||
#define MSG_JOINSUBTEAM 13 //join a sub-team
|
||||
#define MSG_LEAVESUBTEAM 14 //leave a sub-team
|
||||
#define MSG_CREATENEWFORMATION 15 //create a new formation
|
||||
#define MSG_FORMATIONPOSITION 16 //tell someone his/her position in a formation
|
||||
#define MSG_FORMATIONSPACE 17 //set the formation intervening space
|
||||
#define MSG_DOFORMATION 18 //form a known formation
|
||||
#define MSG_DISMISS 19 //dismiss commanded team mates
|
||||
#define MSG_CAMP 20 //camp somewhere
|
||||
#define MSG_CHECKPOINT 21 //remember a check point
|
||||
#define MSG_PATROL 22 //patrol between certain keypoints
|
||||
#define MSG_LEADTHEWAY 23 //lead the way
|
||||
#define MSG_GETITEM 24 //get an item
|
||||
#define MSG_KILL 25 //kill someone
|
||||
#define MSG_WHEREAREYOU 26 //where is someone
|
||||
#define MSG_RETURNFLAG 27 //return the flag
|
||||
#define MSG_WHATISMYCOMMAND 28 //ask the team leader what to do
|
||||
#define MSG_WHICHTEAM 29 //ask which team a bot is in
|
||||
#define MSG_TASKPREFERENCE 30 //tell your teamplay task preference
|
||||
#define MSG_ATTACKENEMYBASE 31 //attack the enemy base
|
||||
#define MSG_HARVEST 32 //go harvest
|
||||
#define MSG_SUICIDE 33 //order to suicide
|
||||
//
|
||||
#define MSG_ME 100
|
||||
#define MSG_EVERYONE 101
|
||||
#define MSG_MULTIPLENAMES 102
|
||||
#define MSG_NAME 103
|
||||
#define MSG_PATROLKEYAREA 104
|
||||
#define MSG_MINUTES 105
|
||||
#define MSG_SECONDS 106
|
||||
#define MSG_FOREVER 107
|
||||
#define MSG_FORALONGTIME 108
|
||||
#define MSG_FORAWHILE 109
|
||||
//
|
||||
#define MSG_CHATALL 200
|
||||
#define MSG_CHATTEAM 201
|
||||
#define MSG_CHATTELL 202
|
||||
//
|
||||
#define MSG_CTF 300 //ctf message
|
||||
|
||||
//command sub types
|
||||
#define ST_SOMEWHERE 0
|
||||
#define ST_NEARITEM 1
|
||||
#define ST_ADDRESSED 2
|
||||
#define ST_METER 4
|
||||
#define ST_FEET 8
|
||||
#define ST_TIME 16
|
||||
#define ST_HERE 32
|
||||
#define ST_THERE 64
|
||||
#define ST_I 128
|
||||
#define ST_MORE 256
|
||||
#define ST_BACK 512
|
||||
#define ST_REVERSE 1024
|
||||
#define ST_SOMEONE 2048
|
||||
#define ST_GOTFLAG 4096
|
||||
#define ST_CAPTUREDFLAG 8192
|
||||
#define ST_RETURNEDFLAG 16384
|
||||
#define ST_TEAM 32768
|
||||
#define ST_1FCTFGOTFLAG 65535
|
||||
//ctf task preferences
|
||||
#define ST_DEFENDER 1
|
||||
#define ST_ATTACKER 2
|
||||
#define ST_ROAMER 4
|
||||
|
||||
|
||||
//word replacement variables
|
||||
#define THE_ENEMY 7
|
||||
#define THE_TEAM 7
|
||||
//team message variables
|
||||
#define NETNAME 0
|
||||
#define PLACE 1
|
||||
#define FLAG 1
|
||||
#define MESSAGE 2
|
||||
#define ADDRESSEE 2
|
||||
#define ITEM 3
|
||||
#define TEAMMATE 4
|
||||
#define TEAMNAME 4
|
||||
#define ENEMY 4
|
||||
#define KEYAREA 5
|
||||
#define FORMATION 5
|
||||
#define POSITION 5
|
||||
#define NUMBER 5
|
||||
#define TIME 6
|
||||
#define NAME 6
|
||||
#define MORE 6
|
||||
|
||||
|
||||
+1308
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
//
|
||||
// This file must be identical in the quake and utils directories
|
||||
|
||||
// contents flags are seperate bits
|
||||
// a given brush can contribute multiple content bits
|
||||
|
||||
// these definitions also need to be in q_shared.h!
|
||||
|
||||
#define CONTENTS_SOLID 1 // an eye is never valid in a solid
|
||||
#define CONTENTS_LAVA 8
|
||||
#define CONTENTS_SLIME 16
|
||||
#define CONTENTS_WATER 32
|
||||
#define CONTENTS_FOG 64
|
||||
|
||||
#define CONTENTS_NOTTEAM1 0x0080
|
||||
#define CONTENTS_NOTTEAM2 0x0100
|
||||
#define CONTENTS_NOBOTCLIP 0x0200
|
||||
|
||||
#define CONTENTS_AREAPORTAL 0x8000
|
||||
|
||||
#define CONTENTS_PLAYERCLIP 0x10000
|
||||
#define CONTENTS_MONSTERCLIP 0x20000
|
||||
//bot specific contents types
|
||||
#define CONTENTS_TELEPORTER 0x40000
|
||||
#define CONTENTS_JUMPPAD 0x80000
|
||||
#define CONTENTS_CLUSTERPORTAL 0x100000
|
||||
#define CONTENTS_DONOTENTER 0x200000
|
||||
#define CONTENTS_BOTCLIP 0x400000
|
||||
#define CONTENTS_MOVER 0x800000
|
||||
|
||||
#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity
|
||||
|
||||
#define CONTENTS_BODY 0x2000000 // should never be on a brush, only in game
|
||||
#define CONTENTS_CORPSE 0x4000000
|
||||
#define CONTENTS_DETAIL 0x8000000 // brushes not used for the bsp
|
||||
#define CONTENTS_STRUCTURAL 0x10000000 // brushes used for the bsp
|
||||
#define CONTENTS_TRANSLUCENT 0x20000000 // don't consume surface fragments inside
|
||||
#define CONTENTS_TRIGGER 0x40000000
|
||||
#define CONTENTS_NODROP 0x80000000 // don't leave bodies or items (death fog, lava)
|
||||
|
||||
#define SURF_NODAMAGE 0x1 // never give falling damage
|
||||
#define SURF_SLICK 0x2 // effects game physics
|
||||
#define SURF_SKY 0x4 // lighting from environment map
|
||||
#define SURF_LADDER 0x8
|
||||
#define SURF_NOIMPACT 0x10 // don't make missile explosions
|
||||
#define SURF_NOMARKS 0x20 // don't leave missile marks
|
||||
#define SURF_FLESH 0x40 // make flesh sounds and effects
|
||||
#define SURF_NODRAW 0x80 // don't generate a drawsurface at all
|
||||
#define SURF_HINT 0x100 // make a primary bsp splitter
|
||||
#define SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes
|
||||
#define SURF_NOLIGHTMAP 0x400 // surface doesn't need a lightmap
|
||||
#define SURF_POINTLIGHT 0x800 // generate lighting info at vertexes
|
||||
#define SURF_METALSTEPS 0x1000 // clanking footsteps
|
||||
#define SURF_NOSTEPS 0x2000 // no footstep sounds
|
||||
#define SURF_NONSOLID 0x4000 // don't collide against curves with this set
|
||||
#define SURF_LIGHTFILTER 0x8000 // act as a light filter during q3map -light
|
||||
#define SURF_ALPHASHADOW 0x10000 // do per-pixel light shadow casting in q3map
|
||||
#define SURF_NODLIGHT 0x20000 // don't dlight even if solid (solid lava, skies)
|
||||
#define SURF_DUST 0x40000 // leave a dust trail when walking on this surface
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#define CONTEXT_ALL 0xFFFFFFFF
|
||||
#define CONTEXT_NORMAL 1
|
||||
#define CONTEXT_NEARBYITEM 2
|
||||
#define CONTEXT_CTFREDTEAM 4
|
||||
#define CONTEXT_CTFBLUETEAM 8
|
||||
#define CONTEXT_REPLY 16
|
||||
#define CONTEXT_OBELISKREDTEAM 32
|
||||
#define CONTEXT_OBELISKBLUETEAM 64
|
||||
#define CONTEXT_HARVESTERREDTEAM 128
|
||||
#define CONTEXT_HARVESTERBLUETEAM 256
|
||||
|
||||
#define CONTEXT_NAMES 1024
|
||||
Reference in New Issue
Block a user