summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/game')
-rw-r--r--src/game/bg_lib.c22
-rw-r--r--src/game/bg_lib.h2
-rw-r--r--src/game/bg_misc.c4
-rw-r--r--src/game/bg_public.h6
-rw-r--r--src/game/g_admin.c11
-rw-r--r--src/game/g_cmds.c118
-rw-r--r--src/game/g_spawn.c251
-rw-r--r--src/game/g_svcmds.c64
8 files changed, 236 insertions, 242 deletions
diff --git a/src/game/bg_lib.c b/src/game/bg_lib.c
index 1ed9c6b3..7a3afdfb 100644
--- a/src/game/bg_lib.c
+++ b/src/game/bg_lib.c
@@ -2450,4 +2450,26 @@ int sscanf( const char *buffer, const char *fmt, ... )
return count;
}
+void *bsearch( const void *key, const void *base, size_t nmemb, size_t size,
+ cmp_t *compar )
+{
+ size_t low = 0, high = nmemb, mid;
+ int comp;
+ void *ptr;
+
+ while( low <= high )
+ {
+ mid = low + (high - low) / 2;
+ ptr = (void *)((char *)base + ( mid * size ));
+ comp = compar (key, ptr);
+ if( comp < 0 )
+ high = mid - 1;
+ else if( comp > 0 )
+ low = mid + 1;
+ else
+ return ptr;
+ }
+ return NULL;
+}
+
#endif
diff --git a/src/game/bg_lib.h b/src/game/bg_lib.h
index 5b5bacaf..005f285d 100644
--- a/src/game/bg_lib.h
+++ b/src/game/bg_lib.h
@@ -87,6 +87,8 @@ 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 );
+void *bsearch( const void *key, const void *base, size_t nmemb,
+ size_t size, cmp_t *compar );
// String functions
size_t strlen( const char *string );
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 204fa878..ed4dd30c 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -3973,3 +3973,7 @@ char *BG_TeamName( team_t team )
return "<team>";
}
+int cmdcmp( const void *a, const void *b )
+{
+ return Q_stricmp( (const char *)a, ((dummyCmd_t *)b)->name );
+}
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index 30ac860d..e952624a 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -1307,3 +1307,9 @@ voiceTrack_t *BG_VoiceTrackFind( voiceTrack_t *head, team_t team,
int BG_LoadEmoticons( char names[ ][ MAX_EMOTICON_NAME_LEN ], int widths[ ] );
char *BG_TeamName( team_t team );
+
+typedef struct
+{
+ const char *name;
+} dummyCmd_t;
+int cmdcmp( const void *a, const void *b );
diff --git a/src/game/g_admin.c b/src/game/g_admin.c
index 9981812b..b894324b 100644
--- a/src/game/g_admin.c
+++ b/src/game/g_admin.c
@@ -225,15 +225,8 @@ static qboolean admin_permission( char *flags, const char *flag, qboolean *perm
g_admin_cmd_t *G_admin_cmd( const char *cmd )
{
- int i;
-
- for( i = 0; i < adminNumCmds; i++ )
- {
- if( !Q_stricmp( g_admin_cmds[ i ].keyword, cmd ) )
- return &g_admin_cmds[ i ];
- }
-
- return NULL;
+ return bsearch( cmd, g_admin_cmds, adminNumCmds, sizeof( g_admin_cmd_t ),
+ cmdcmp );
}
g_admin_level_t *G_admin_level( const int l )
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index ac88b825..ed32ae05 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -2887,63 +2887,49 @@ int G_FloodLimited( gentity_t *ent )
}
commands_t cmds[ ] = {
- // normal commands
- { "team", 0, Cmd_Team_f },
- { "vote", 0, Cmd_Vote_f },
- { "ignore", 0, Cmd_Ignore_f },
- { "unignore", 0, Cmd_Ignore_f },
-
- // communication commands
- { "callvote", CMD_MESSAGE, Cmd_CallVote_f },
- { "callteamvote", CMD_MESSAGE|CMD_TEAM, Cmd_CallVote_f },
- { "say_area", CMD_MESSAGE|CMD_TEAM|CMD_LIVING, Cmd_SayArea_f },
- // can be used even during intermission
- { "say", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f },
- { "say_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f },
- { "vsay", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f },
- { "vsay_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f },
- { "vsay_local", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f },
- { "m", CMD_MESSAGE|CMD_INTERMISSION, Cmd_PrivateMessage_f },
- { "mt", CMD_MESSAGE|CMD_INTERMISSION, Cmd_PrivateMessage_f },
{ "a", CMD_MESSAGE|CMD_INTERMISSION, Cmd_AdminMessage_f },
-
- { "score", CMD_INTERMISSION, ScoreboardMessage },
-
- // cheats
- { "give", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Give_f },
- { "god", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_God_f },
- { "notarget", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Notarget_f },
- { "noclip", CMD_CHEAT_TEAM, Cmd_Noclip_f },
- { "levelshot", CMD_CHEAT, Cmd_LevelShot_f },
- { "setviewpos", CMD_CHEAT_TEAM, Cmd_SetViewpos_f },
- { "destroy", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Destroy_f },
- { "test", CMD_CHEAT, Cmd_Test_f },
+ { "build", CMD_TEAM|CMD_LIVING, Cmd_Build_f },
+ { "buy", CMD_HUMAN|CMD_LIVING, Cmd_Buy_f },
+ { "callteamvote", CMD_MESSAGE|CMD_TEAM, Cmd_CallVote_f },
+ { "callvote", CMD_MESSAGE, Cmd_CallVote_f },
+ { "class", CMD_TEAM, Cmd_Class_f },
{ "damage", CMD_CHEAT|CMD_LIVING, Cmd_Damage_f },
- { "where", 0, Cmd_Where_f },
-
- // game commands
- { "ptrcverify", CMD_SPEC, Cmd_PTRCVerify_f },
- { "ptrcrestore", CMD_SPEC, Cmd_PTRCRestore_f },
-
+ { "deconstruct", CMD_TEAM|CMD_LIVING, Cmd_Destroy_f },
+ { "destroy", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Destroy_f },
{ "follow", CMD_SPEC, Cmd_Follow_f },
- { "follownext", CMD_SPEC, Cmd_FollowCycle_f },
{ "followprev", CMD_SPEC, Cmd_FollowCycle_f },
-
- { "teamvote", CMD_TEAM, Cmd_Vote_f },
- { "class", CMD_TEAM, Cmd_Class_f },
- { "kill", CMD_TEAM|CMD_LIVING, Cmd_Kill_f },
-
- { "build", CMD_TEAM|CMD_LIVING, Cmd_Build_f },
- { "deconstruct", CMD_TEAM|CMD_LIVING, Cmd_Destroy_f },
-
- { "buy", CMD_HUMAN|CMD_LIVING, Cmd_Buy_f },
- { "sell", CMD_HUMAN|CMD_LIVING, Cmd_Sell_f },
+ { "give", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Give_f },
+ { "god", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_God_f },
+ { "ignore", 0, Cmd_Ignore_f },
{ "itemact", CMD_HUMAN|CMD_LIVING, Cmd_ActivateItem_f },
{ "itemdeact", CMD_HUMAN|CMD_LIVING, Cmd_DeActivateItem_f },
{ "itemtoggle", CMD_HUMAN|CMD_LIVING, Cmd_ToggleItem_f },
+ { "kill", CMD_TEAM|CMD_LIVING, Cmd_Kill_f },
+ { "levelshot", CMD_CHEAT, Cmd_LevelShot_f },
+ { "m", CMD_MESSAGE|CMD_INTERMISSION, Cmd_PrivateMessage_f },
+ { "mt", CMD_MESSAGE|CMD_INTERMISSION, Cmd_PrivateMessage_f },
+ { "noclip", CMD_CHEAT_TEAM, Cmd_Noclip_f },
+ { "notarget", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Notarget_f },
+ { "ptrcrestore", CMD_SPEC, Cmd_PTRCRestore_f },
+ { "ptrcverify", CMD_SPEC, Cmd_PTRCVerify_f },
{ "reload", CMD_HUMAN|CMD_LIVING, Cmd_Reload_f },
+ { "say_area", CMD_MESSAGE|CMD_TEAM|CMD_LIVING, Cmd_SayArea_f },
+ { "say", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f },
+ { "say_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f },
+ { "score", CMD_INTERMISSION, ScoreboardMessage },
+ { "sell", CMD_HUMAN|CMD_LIVING, Cmd_Sell_f },
+ { "setviewpos", CMD_CHEAT_TEAM, Cmd_SetViewpos_f },
+ { "team", 0, Cmd_Team_f },
+ { "teamvote", CMD_TEAM, Cmd_Vote_f },
+ { "test", CMD_CHEAT, Cmd_Test_f },
+ { "unignore", 0, Cmd_Ignore_f },
+ { "vote", 0, Cmd_Vote_f },
+ { "vsay", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f },
+ { "vsay_local", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f },
+ { "vsay_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f },
+ { "where", 0, Cmd_Where_f }
};
-static int numCmds = sizeof( cmds ) / sizeof( cmds[ 0 ] );
+static size_t numCmds = sizeof( cmds ) / sizeof( cmds[ 0 ] );
/*
=================
@@ -2952,9 +2938,9 @@ ClientCommand
*/
void ClientCommand( int clientNum )
{
- gentity_t *ent;
- char cmd[ MAX_TOKEN_CHARS ];
- int i;
+ gentity_t *ent;
+ char cmd[ MAX_TOKEN_CHARS ];
+ commands_t *command;
ent = g_entities + clientNum;
if( !ent->client )
@@ -2962,13 +2948,9 @@ void ClientCommand( int clientNum )
trap_Argv( 0, cmd, sizeof( cmd ) );
- for( i = 0; i < numCmds; i++ )
- {
- if( Q_stricmp( cmd, cmds[ i ].cmdName ) == 0 )
- break;
- }
+ command = bsearch( cmd, cmds, numCmds, sizeof( cmds[ 0 ] ), cmdcmp );
- if( i == numCmds )
+ if( !command )
{
if( !G_admin_cmd_check( ent, qfalse ) )
trap_SendServerCommand( clientNum,
@@ -2978,56 +2960,56 @@ void ClientCommand( int clientNum )
// do tests here to reduce the amount of repeated code
- if( !( cmds[ i ].cmdFlags & CMD_INTERMISSION ) && level.intermissiontime )
+ if( !( command->cmdFlags & CMD_INTERMISSION ) && level.intermissiontime )
return;
- if( cmds[ i ].cmdFlags & CMD_CHEAT && !g_cheats.integer )
+ if( command->cmdFlags & CMD_CHEAT && !g_cheats.integer )
{
G_TriggerMenu( clientNum, MN_CMD_CHEAT );
return;
}
- if( cmds[ i ].cmdFlags & CMD_MESSAGE && ( ent->client->pers.muted ||
+ if( command->cmdFlags & CMD_MESSAGE && ( ent->client->pers.muted ||
G_FloodLimited( ent ) ) )
return;
- if( ( cmds[ i ].cmdFlags & CMD_TEAM ||
- ( cmds[ i ].cmdFlags & CMD_CHEAT_TEAM && !g_cheats.integer ) ) &&
+ if( ( command->cmdFlags & CMD_TEAM ||
+ ( command->cmdFlags & CMD_CHEAT_TEAM && !g_cheats.integer ) ) &&
ent->client->pers.teamSelection == TEAM_NONE )
{
G_TriggerMenu( clientNum, MN_CMD_TEAM );
return;
}
- if( cmds[ i ].cmdFlags & CMD_CHEAT_TEAM && !g_cheats.integer &&
+ if( command->cmdFlags & CMD_CHEAT_TEAM && !g_cheats.integer &&
ent->client->pers.teamSelection != TEAM_NONE )
{
G_TriggerMenu( clientNum, MN_CMD_CHEAT_TEAM );
return;
}
- if( cmds[ i ].cmdFlags & CMD_SPEC &&
+ if( command->cmdFlags & CMD_SPEC &&
ent->client->sess.spectatorState == SPECTATOR_NOT )
{
G_TriggerMenu( clientNum, MN_CMD_SPEC );
return;
}
- if( cmds[ i ].cmdFlags & CMD_ALIEN &&
+ if( command->cmdFlags & CMD_ALIEN &&
ent->client->pers.teamSelection != TEAM_ALIENS )
{
G_TriggerMenu( clientNum, MN_CMD_ALIEN );
return;
}
- if( cmds[ i ].cmdFlags & CMD_HUMAN &&
+ if( command->cmdFlags & CMD_HUMAN &&
ent->client->pers.teamSelection != TEAM_HUMANS )
{
G_TriggerMenu( clientNum, MN_CMD_HUMAN );
return;
}
- if( cmds[ i ].cmdFlags & CMD_LIVING &&
+ if( command->cmdFlags & CMD_LIVING &&
( ent->client->ps.stats[ STAT_HEALTH ] <= 0 ||
ent->client->sess.spectatorState != SPECTATOR_NOT ) )
{
@@ -3035,7 +3017,7 @@ void ClientCommand( int clientNum )
return;
}
- cmds[ i ].cmdHandler( ent );
+ command->cmdHandler( ent );
}
/*
diff --git a/src/game/g_spawn.c b/src/game/g_spawn.c
index 35c29b4e..0eade5c4 100644
--- a/src/game/g_spawn.c
+++ b/src/game/g_spawn.c
@@ -116,34 +116,32 @@ typedef struct
field_t fields[ ] =
{
+ {"acceleration", FOFS(acceleration), F_VECTOR},
+ {"alpha", FOFS(pos1), F_VECTOR},
+ {"angle", FOFS(s.angles), F_ANGLEHACK},
+ {"angles", FOFS(s.angles), F_VECTOR},
+ {"animation", FOFS(animation), F_VECTOR4},
+ {"bounce", FOFS(physicsBounce), F_FLOAT},
{"classname", FOFS(classname), F_LSTRING},
- {"origin", FOFS(s.origin), F_VECTOR},
+ {"count", FOFS(count), F_INT},
+ {"dmg", FOFS(damage), F_INT},
+ {"health", FOFS(health), F_INT},
+ {"light", 0, F_IGNORE},
+ {"message", FOFS(message), F_LSTRING},
{"model", FOFS(model), F_LSTRING},
{"model2", FOFS(model2), F_LSTRING},
+ {"origin", FOFS(s.origin), F_VECTOR},
+ {"radius", FOFS(pos2), F_VECTOR},
+ {"random", FOFS(random), F_FLOAT},
+ {"rotatorAngle", FOFS(rotatorAngle), F_FLOAT},
{"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},
- {"bounce", FOFS(physicsBounce), F_FLOAT},
- {"alpha", FOFS(pos1), F_VECTOR},
- {"radius", FOFS(pos2), F_VECTOR},
- {"acceleration", FOFS(acceleration), F_VECTOR},
- {"animation", FOFS(animation), F_VECTOR4},
- {"rotatorAngle", FOFS(rotatorAngle), F_FLOAT},
{"targetShaderName", FOFS(targetShaderName), F_LSTRING},
{"targetShaderNewName", FOFS(targetShaderNewName), F_LSTRING},
-
- {NULL}
+ {"team", FOFS(team), F_LSTRING},
+ {"wait", FOFS(wait), F_FLOAT}
};
@@ -228,30 +226,54 @@ void SP_misc_light_flare( gentity_t *ent );
spawn_t spawns[ ] =
{
+ { "func_bobbing", SP_func_bobbing },
+ { "func_button", SP_func_button },
+ { "func_door", SP_func_door },
+ { "func_door_model", SP_func_door_model },
+ { "func_door_rotating", SP_func_door_rotating },
+ { "func_group", SP_info_null },
+ { "func_pendulum", SP_func_pendulum },
+ { "func_plat", SP_func_plat },
+ { "func_rotating", SP_func_rotating },
+ { "func_static", SP_func_static },
+ { "func_timer", SP_func_timer }, // rename trigger_timer?
+ { "func_train", SP_func_train },
+
// 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_alien_intermission", SP_info_alien_intermission },
{ "info_human_intermission", SP_info_human_intermission },
-
- { "info_null", SP_info_null },
{ "info_notnull", SP_info_notnull }, // use target_position instead
+ { "info_null", SP_info_null },
+ { "info_player_deathmatch", SP_info_player_deathmatch },
+ { "info_player_intermission", SP_info_player_intermission },
+ { "info_player_start", SP_info_player_start },
+ { "light", SP_light },
+ { "misc_anim_model", SP_misc_anim_model },
+ { "misc_light_flare", SP_misc_light_flare },
+ { "misc_model", SP_misc_model },
+ { "misc_particle_system", SP_misc_particle_system },
+ { "misc_portal_camera", SP_misc_portal_camera },
+ { "misc_portal_surface", SP_misc_portal_surface },
+ { "misc_teleporter_dest", SP_misc_teleporter_dest },
+ { "path_corner", SP_path_corner },
- { "func_plat", SP_func_plat },
- { "func_button", SP_func_button },
- { "func_door", SP_func_door },
- { "func_door_rotating", SP_func_door_rotating },
- { "func_door_model", SP_func_door_model },
- { "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?
+ // targets perform no action by themselves, but must be triggered
+ // by another entity
+ { "target_alien_win", SP_target_alien_win },
+ { "target_delay", SP_target_delay },
+ { "target_human_win", SP_target_human_win },
+ { "target_hurt", SP_target_hurt },
+ { "target_kill", SP_target_kill },
+ { "target_location", SP_target_location },
+ { "target_position", SP_target_position },
+ { "target_print", SP_target_print },
+ { "target_push", SP_target_push },
+ { "target_relay", SP_target_relay },
+ { "target_rumble", SP_target_rumble },
+ { "target_score", SP_target_score },
+ { "target_speaker", SP_target_speaker },
+ { "target_teleporter", SP_target_teleporter },
// Triggers are brush objects that cause an effect when contacted
// by a living player, usually involving firing targets.
@@ -259,49 +281,18 @@ spawn_t spawns[ ] =
// 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 },
- { "trigger_stage", SP_trigger_stage },
- { "trigger_win", SP_trigger_win },
+ { "trigger_ammo", SP_trigger_ammo },
{ "trigger_buildable", SP_trigger_buildable },
{ "trigger_class", SP_trigger_class },
{ "trigger_equipment", SP_trigger_equipment },
{ "trigger_gravity", SP_trigger_gravity },
{ "trigger_heal", SP_trigger_heal },
- { "trigger_ammo", SP_trigger_ammo },
-
- // targets perform no action by themselves, but must be triggered
- // by another entity
- { "target_delay", SP_target_delay },
- { "target_speaker", SP_target_speaker },
- { "target_print", SP_target_print },
- { "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 },
- { "target_rumble", SP_target_rumble },
- { "target_alien_win", SP_target_alien_win },
- { "target_human_win", SP_target_human_win },
- { "target_hurt", SP_target_hurt },
-
- { "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 },
-
- { "misc_particle_system", SP_misc_particle_system },
- { "misc_anim_model", SP_misc_anim_model },
- { "misc_light_flare", SP_misc_light_flare },
-
- { NULL, 0 }
+ { "trigger_hurt", SP_trigger_hurt },
+ { "trigger_multiple", SP_trigger_multiple },
+ { "trigger_push", SP_trigger_push },
+ { "trigger_stage", SP_trigger_stage },
+ { "trigger_teleport", SP_trigger_teleport },
+ { "trigger_win", SP_trigger_win }
};
/*
@@ -342,14 +333,13 @@ qboolean G_CallSpawn( gentity_t *ent )
}
// check normal spawn functions
- for( s = spawns; s->name; s++ )
+ s = bsearch( ent->classname, spawns, sizeof( spawns ) / sizeof( spawn_t ),
+ sizeof( spawn_t ), cmdcmp );
+ if( s )
{
- if( !strcmp( s->name, ent->classname ) )
- {
- // found it
- s->spawn( ent );
- return qtrue;
- }
+ // found it
+ s->spawn( ent );
+ return qtrue;
}
G_Printf( "%s doesn't have a spawn function\n", ent->classname );
@@ -412,58 +402,53 @@ void G_ParseField( const char *key, const char *value, gentity_t *ent )
vec3_t vec;
vec4_t vec4;
- for( f = fields; f->name; f++ )
+ f = bsearch( key, fields, sizeof( fields ) / sizeof( field_t ),
+ sizeof( field_t ), cmdcmp );
+ if( !f )
+ return;
+ b = (byte *)ent;
+
+ switch( f->type )
{
- 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_VECTOR4:
- sscanf( value, "%f %f %f %f", &vec4[ 0 ], &vec4[ 1 ], &vec4[ 2 ], &vec4[ 3 ] );
-
- ( (float *)( b + f->ofs ) )[ 0 ] = vec4[ 0 ];
- ( (float *)( b + f->ofs ) )[ 1 ] = vec4[ 1 ];
- ( (float *)( b + f->ofs ) )[ 2 ] = vec4[ 2 ];
- ( (float *)( b + f->ofs ) )[ 3 ] = vec4[ 3 ];
- 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;
- }
+ 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_VECTOR4:
+ sscanf( value, "%f %f %f %f", &vec4[ 0 ], &vec4[ 1 ], &vec4[ 2 ], &vec4[ 3 ] );
+
+ ( (float *)( b + f->ofs ) )[ 0 ] = vec4[ 0 ];
+ ( (float *)( b + f->ofs ) )[ 1 ] = vec4[ 1 ];
+ ( (float *)( b + f->ofs ) )[ 2 ] = vec4[ 2 ];
+ ( (float *)( b + f->ofs ) )[ 3 ] = vec4[ 3 ];
+ 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;
}
}
diff --git a/src/game/g_svcmds.c b/src/game/g_svcmds.c
index 755948b5..f75236ed 100644
--- a/src/game/g_svcmds.c
+++ b/src/game/g_svcmds.c
@@ -513,34 +513,33 @@ static void Svcmd_SuddenDeath_f( void )
offset, offset == 1 ? "" : "s" ) );
}
-struct
+struct svcmd
{
char *cmd;
qboolean dedicated;
void ( *function )( void );
} svcmds[ ] = {
- { "entityList", qfalse, Svcmd_EntityList_f },
- { "status", qfalse, Svcmd_Status_f },
- { "forceTeam", qfalse, Svcmd_ForceTeam_f },
- { "mapRotation", qfalse, Svcmd_MapRotation_f },
- { "stopMapRotation", qfalse, G_StopMapRotation },
+ { "a", qtrue, Svcmd_MessageWrapper },
+ { "admitDefeat", qfalse, Svcmd_AdmitDefeat_f },
{ "advanceMapRotation", qfalse, G_AdvanceMapRotation },
{ "alienWin", qfalse, Svcmd_TeamWin_f },
- { "humanWin", qfalse, Svcmd_TeamWin_f },
- { "layoutSave", qfalse, Svcmd_LayoutSave_f },
- { "layoutLoad", qfalse, Svcmd_LayoutLoad_f },
- { "eject", qfalse, Svcmd_EjectClient_f },
+ { "chat", qtrue, Svcmd_MessageWrapper },
+ { "cp", qtrue, Svcmd_CenterPrint_f },
{ "dumpuser", qfalse, Svcmd_DumpUser_f },
- { "admitDefeat", qfalse, Svcmd_AdmitDefeat_f },
+ { "eject", qfalse, Svcmd_EjectClient_f },
+ { "entityList", qfalse, Svcmd_EntityList_f },
{ "evacuation", qfalse, Svcmd_Evacuation_f },
+ { "forceTeam", qfalse, Svcmd_ForceTeam_f },
+ { "humanWin", qfalse, Svcmd_TeamWin_f },
+ { "layoutLoad", qfalse, Svcmd_LayoutLoad_f },
+ { "layoutSave", qfalse, Svcmd_LayoutSave_f },
+ { "m", qtrue, Svcmd_MessageWrapper },
+ { "mapRotation", qfalse, Svcmd_MapRotation_f },
{ "printqueue", qfalse, Svcmd_PrintQueue_f },
- // don't handle communication commands unless dedicated
- { "cp", qtrue, Svcmd_CenterPrint_f },
- { "say_team", qtrue, Svcmd_TeamMessage_f },
{ "say", qtrue, Svcmd_MessageWrapper },
- { "chat", qtrue, Svcmd_MessageWrapper },
- { "m", qtrue, Svcmd_MessageWrapper },
- { "a", qtrue, Svcmd_MessageWrapper },
+ { "say_team", qtrue, Svcmd_TeamMessage_f },
+ { "status", qfalse, Svcmd_Status_f },
+ { "stopMapRotation", qfalse, G_StopMapRotation },
{ "suddendeath", qfalse, Svcmd_SuddenDeath_f }
};
@@ -553,28 +552,29 @@ ConsoleCommand
qboolean ConsoleCommand( void )
{
char cmd[ MAX_TOKEN_CHARS ];
- int i;
+ struct svcmd *command;
trap_Argv( 0, cmd, sizeof( cmd ) );
- for( i = 0; i < sizeof( svcmds ) / sizeof( svcmds[ 0 ] ); i++ )
+ command = bsearch( cmd, svcmds, sizeof( svcmds ) / sizeof( struct svcmd ),
+ sizeof( struct svcmd ), cmdcmp );
+
+ if( !command )
{
- if( !Q_stricmp( cmd, svcmds[ i ].cmd ) )
- {
- if( svcmds[ i ].dedicated && !g_dedicated.integer )
- return qfalse;
- svcmds[ i ].function( );
+ // see if this is an admin command
+ if( G_admin_cmd_check( NULL, qfalse ) )
return qtrue;
- }
- }
- // see if this is an admin command
- if( G_admin_cmd_check( NULL, qfalse ) )
- return qtrue;
+ if( g_dedicated.integer )
+ G_Printf( "unknown command: %s\n", cmd );
+
+ return qfalse;
+ }
- if( g_dedicated.integer )
- G_Printf( "unknown command: %s\n", cmd );
+ if( command->dedicated && !g_dedicated.integer )
+ return qfalse;
- return qfalse;
+ command->function( );
+ return qtrue;
}