The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
This commit is contained in:
commit
dbe4ddb103
1409 changed files with 806066 additions and 0 deletions
140
code/game/Conscript
Normal file
140
code/game/Conscript
Normal file
|
|
@ -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
code/game/ai_chat.c
Normal file
1226
code/game/ai_chat.c
Normal file
File diff suppressed because it is too large
Load diff
61
code/game/ai_chat.h
Normal file
61
code/game/ai_chat.h
Normal file
|
|
@ -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
code/game/ai_cmd.c
Normal file
1992
code/game/ai_cmd.c
Normal file
File diff suppressed because it is too large
Load diff
37
code/game/ai_cmd.h
Normal file
37
code/game/ai_cmd.h
Normal file
|
|
@ -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);
|
||||
|
||||
2610
code/game/ai_dmnet.c
Normal file
2610
code/game/ai_dmnet.c
Normal file
File diff suppressed because it is too large
Load diff
61
code/game/ai_dmnet.h
Normal file
61
code/game/ai_dmnet.h
Normal file
|
|
@ -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
code/game/ai_dmq3.c
Normal file
5461
code/game/ai_dmq3.c
Normal file
File diff suppressed because it is too large
Load diff
206
code/game/ai_dmq3.h
Normal file
206
code/game/ai_dmq3.h
Normal file
|
|
@ -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
code/game/ai_main.c
Normal file
1695
code/game/ai_main.c
Normal file
File diff suppressed because it is too large
Load diff
299
code/game/ai_main.h
Normal file
299
code/game/ai_main.h
Normal file
|
|
@ -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
code/game/ai_team.c
Normal file
2080
code/game/ai_team.c
Normal file
File diff suppressed because it is too large
Load diff
39
code/game/ai_team.h
Normal file
39
code/game/ai_team.h
Normal file
|
|
@ -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);
|
||||
|
||||
|
||||
550
code/game/ai_vcmd.c
Normal file
550
code/game/ai_vcmd.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
36
code/game/ai_vcmd.h
Normal file
36
code/game/ai_vcmd.h
Normal file
|
|
@ -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);
|
||||
|
||||
|
||||
221
code/game/be_aas.h
Normal file
221
code/game/be_aas.h
Normal file
|
|
@ -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;
|
||||
48
code/game/be_ai_char.h
Normal file
48
code/game/be_ai_char.h
Normal file
|
|
@ -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);
|
||||
113
code/game/be_ai_chat.h
Normal file
113
code/game/be_ai_chat.h
Normal file
|
|
@ -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);
|
||||
|
||||
33
code/game/be_ai_gen.h
Normal file
33
code/game/be_ai_gen.h
Normal file
|
|
@ -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);
|
||||
118
code/game/be_ai_goal.h
Normal file
118
code/game/be_ai_goal.h
Normal file
|
|
@ -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);
|
||||
142
code/game/be_ai_move.h
Normal file
142
code/game/be_ai_move.h
Normal file
|
|
@ -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);
|
||||
|
||||
104
code/game/be_ai_weap.h
Normal file
104
code/game/be_ai_weap.h
Normal file
|
|
@ -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);
|
||||
66
code/game/be_ea.h
Normal file
66
code/game/be_ea.h
Normal file
|
|
@ -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
code/game/bg_lib.c
Normal file
1324
code/game/bg_lib.c
Normal file
File diff suppressed because it is too large
Load diff
91
code/game/bg_lib.h
Normal file
91
code/game/bg_lib.h
Normal file
|
|
@ -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 );
|
||||
|
||||
83
code/game/bg_local.h
Normal file
83
code/game/bg_local.h
Normal file
|
|
@ -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
code/game/bg_misc.c
Normal file
1604
code/game/bg_misc.c
Normal file
File diff suppressed because it is too large
Load diff
2069
code/game/bg_pmove.c
Normal file
2069
code/game/bg_pmove.c
Normal file
File diff suppressed because it is too large
Load diff
738
code/game/bg_public.h
Normal file
738
code/game/bg_public.h
Normal file
|
|
@ -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
|
||||
|
||||
325
code/game/bg_slidemove.c
Normal file
325
code/game/bg_slidemove.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
516
code/game/botlib.h
Normal file
516
code/game/botlib.h
Normal file
|
|
@ -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
|
||||
|
||||
*/
|
||||
|
||||
134
code/game/chars.h
Normal file
134
code/game/chars.h
Normal file
|
|
@ -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]
|
||||
|
||||
1191
code/game/g_active.c
Normal file
1191
code/game/g_active.c
Normal file
File diff suppressed because it is too large
Load diff
376
code/game/g_arenas.c
Normal file
376
code/game/g_arenas.c
Normal file
|
|
@ -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
code/game/g_bot.c
Normal file
1017
code/game/g_bot.c
Normal file
File diff suppressed because it is too large
Load diff
1344
code/game/g_client.c
Normal file
1344
code/game/g_client.c
Normal file
File diff suppressed because it is too large
Load diff
1701
code/game/g_cmds.c
Normal file
1701
code/game/g_cmds.c
Normal file
File diff suppressed because it is too large
Load diff
1195
code/game/g_combat.c
Normal file
1195
code/game/g_combat.c
Normal file
File diff suppressed because it is too large
Load diff
1010
code/game/g_items.c
Normal file
1010
code/game/g_items.c
Normal file
File diff suppressed because it is too large
Load diff
971
code/game/g_local.h
Normal file
971
code/game/g_local.h
Normal file
|
|
@ -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
code/game/g_main.c
Normal file
1832
code/game/g_main.c
Normal file
File diff suppressed because it is too large
Load diff
61
code/game/g_mem.c
Normal file
61
code/game/g_mem.c
Normal file
|
|
@ -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 );
|
||||
}
|
||||
482
code/game/g_misc.c
Normal file
482
code/game/g_misc.c
Normal file
|
|
@ -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
|
||||
808
code/game/g_missile.c
Normal file
808
code/game/g_missile.c
Normal file
|
|
@ -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
code/game/g_mover.c
Normal file
1612
code/game/g_mover.c
Normal file
File diff suppressed because it is too large
Load diff
429
code/game/g_public.h
Normal file
429
code/game/g_public.h
Normal file
|
|
@ -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;
|
||||
|
||||
1135
code/game/g_rankings.c
Normal file
1135
code/game/g_rankings.c
Normal file
File diff suppressed because it is too large
Load diff
396
code/game/g_rankings.h
Normal file
396
code/game/g_rankings.h
Normal file
|
|
@ -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_
|
||||
193
code/game/g_session.c
Normal file
193
code/game/g_session.c
Normal file
|
|
@ -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] );
|
||||
}
|
||||
}
|
||||
}
|
||||
643
code/game/g_spawn.c
Normal file
643
code/game/g_spawn.c
Normal file
|
|
@ -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
|
||||
}
|
||||
|
||||
508
code/game/g_svcmds.c
Normal file
508
code/game/g_svcmds.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
||||
225
code/game/g_syscalls.asm
Normal file
225
code/game/g_syscalls.asm
Normal file
|
|
@ -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
|
||||
|
||||
790
code/game/g_syscalls.c
Normal file
790
code/game/g_syscalls.c
Normal file
|
|
@ -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 );
|
||||
}
|
||||
467
code/game/g_target.c
Normal file
467
code/game/g_target.c
Normal file
|
|
@ -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
code/game/g_team.c
Normal file
1483
code/game/g_team.c
Normal file
File diff suppressed because it is too large
Load diff
88
code/game/g_team.h
Normal file
88
code/game/g_team.h
Normal file
|
|
@ -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 );
|
||||
465
code/game/g_trigger.c
Normal file
465
code/game/g_trigger.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
666
code/game/g_utils.c
Normal file
666
code/game/g_utils.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
1145
code/game/g_weapon.c
Normal file
1145
code/game/g_weapon.c
Normal file
File diff suppressed because it is too large
Load diff
85
code/game/game.bat
Normal file
85
code/game/game.bat
Normal file
|
|
@ -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 ..
|
||||
3
code/game/game.def
Normal file
3
code/game/game.def
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
EXPORTS
|
||||
dllEntry
|
||||
vmMain
|
||||
35
code/game/game.q3asm
Normal file
35
code/game/game.q3asm
Normal file
|
|
@ -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
|
||||
48
code/game/game.sh
Normal file
48
code/game/game.sh
Normal file
|
|
@ -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 ..
|
||||
2132
code/game/game.vcproj
Normal file
2132
code/game/game.vcproj
Normal file
File diff suppressed because it is too large
Load diff
86
code/game/game_ta.bat
Normal file
86
code/game/game_ta.bat
Normal file
|
|
@ -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 ..
|
||||
35
code/game/game_ta.q3asm
Normal file
35
code/game/game_ta.q3asm
Normal file
|
|
@ -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
|
||||
48
code/game/game_ta.sh
Normal file
48
code/game/game_ta.sh
Normal file
|
|
@ -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
code/game/inv.h
Normal file
166
code/game/inv.h
Normal file
|
|
@ -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
|
||||
134
code/game/match.h
Normal file
134
code/game/match.h
Normal file
|
|
@ -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
code/game/q_math.c
Normal file
1308
code/game/q_math.c
Normal file
File diff suppressed because it is too large
Load diff
1258
code/game/q_shared.c
Normal file
1258
code/game/q_shared.c
Normal file
File diff suppressed because it is too large
Load diff
1432
code/game/q_shared.h
Normal file
1432
code/game/q_shared.h
Normal file
File diff suppressed because it is too large
Load diff
80
code/game/surfaceflags.h
Normal file
80
code/game/surfaceflags.h
Normal file
|
|
@ -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
|
||||
34
code/game/syn.h
Normal file
34
code/game/syn.h
Normal file
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue