mirror of
https://github.com/OpenArena/gamecode
synced 2026-08-20 18:23:03 -04:00
- captureLimit should not end non-capturing games anymore - additional surfaceflags for different surface types such as snow, wood, sand, gravel, foilage, ice, and glass - improve hexcolors in the ui, allow for on-demand refresh of ui colors, add more hexcolors - increase some limits of elements in the ui - suppress excess ui warnings into developer - sergei/kyonshi do not exist in OA3; default to sarge for missionpack currently (avoids crashes) - don't attempt to load from characters/ - changing one model also changes teammodel - add preliminary support for entity glow functionality and alternate shells for them (requires renderer engine changes to support). the primary idea behind alternate shell is performance and to avoid overdraw by force altering the model's vertex colors instead (overriding lighting and any other rgbGen op) - add preliminary support for drawing player names above teammate heads (requires client engine changes to support) - cg_hitSound camel-cased and defaults to 1 (again) - reducing clown cruft by dropping the reference from the teamnames and just going for red/blue for now - removed cg_leiChibi (again) - bloodExplosion starts the shader (ancient bug/oversight) - reverted superfluous cruft
1965 lines
44 KiB
C
1965 lines
44 KiB
C
/*
|
|
===========================================================================
|
|
Copyright (C) 1999-2005 Id Software, Inc.
|
|
|
|
This file is part of Open Arena source code.
|
|
Portions copied from Tremulous under GPL version 2 including any later version.
|
|
|
|
Open 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.
|
|
|
|
Open 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 Open Arena source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
//
|
|
// bg_misc.c -- both games misc functions, all completely stateless
|
|
|
|
#include "../qcommon/q_shared.h"
|
|
#include "bg_public.h"
|
|
|
|
/*QUAKED item_***** ( 0 0 0 ) (-16 -16 -16) (16 16 16) suspended
|
|
DO NOT USE THIS CLASS, IT JUST HOLDS GENERAL INFORMATION.
|
|
The suspended flag will allow items to hang in the air, otherwise they are dropped to the next surface.
|
|
|
|
If an item is the target of another entity, it will not spawn in until fired.
|
|
|
|
An item fires all of its targets when it is picked up. If the toucher can't carry it, the targets won't be fired.
|
|
|
|
"notfree" if set to 1, don't spawn in free for all games
|
|
"notteam" if set to 1, don't spawn in team games
|
|
"notsingle" if set to 1, don't spawn in single player games
|
|
"wait" override the default wait before respawning. -1 = never respawn automatically, which can be used with targeted spawning.
|
|
"random" random number of plus or minus seconds varied from the respawn time
|
|
"count" override quantity or duration on most items.
|
|
*/
|
|
|
|
gitem_t bg_itemlist[] ={
|
|
{
|
|
NULL,
|
|
NULL,
|
|
{ NULL,
|
|
NULL,
|
|
NULL, NULL},
|
|
/* icon */ NULL,
|
|
/* pickup */ NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
}, // leave index 0 alone
|
|
|
|
//
|
|
// ARMOR
|
|
//
|
|
|
|
/*QUAKED item_armor_shard (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_armor_shard",
|
|
"sound/misc/ar1_pkup.wav",
|
|
{ "models/powerups/armor/shard.md3",
|
|
"models/powerups/armor/shard_sphere.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/iconr_shard",
|
|
/* pickup */ "Armor Shard",
|
|
5,
|
|
IT_ARMOR,
|
|
0,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED item_armor_combat (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_armor_combat",
|
|
"sound/misc/ar2_pkup.wav",
|
|
{ "models/powerups/armor/armor_yel.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconr_yellow",
|
|
/* pickup */ "Armor",
|
|
50,
|
|
IT_ARMOR,
|
|
0,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED item_armor_body (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_armor_body",
|
|
"sound/misc/ar2_pkup.wav",
|
|
{ "models/powerups/armor/armor_red.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconr_red",
|
|
/* pickup */ "Heavy Armor",
|
|
100,
|
|
IT_ARMOR,
|
|
0,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
//
|
|
// health
|
|
//
|
|
/*QUAKED item_health_small (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_health_small",
|
|
"sound/items/s_health.wav",
|
|
{ "models/powerups/health/small_cross.md3",
|
|
"models/powerups/health/small_sphere.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/iconh_green",
|
|
/* pickup */ "5 Health",
|
|
5,
|
|
IT_HEALTH,
|
|
0,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED item_health (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_health",
|
|
"sound/items/n_health.wav",
|
|
{ "models/powerups/health/medium_cross.md3",
|
|
"models/powerups/health/medium_sphere.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/iconh_yellow",
|
|
/* pickup */ "25 Health",
|
|
25,
|
|
IT_HEALTH,
|
|
0,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED item_health_large (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_health_large",
|
|
"sound/items/l_health.wav",
|
|
{ "models/powerups/health/large_cross.md3",
|
|
"models/powerups/health/large_sphere.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/iconh_red",
|
|
/* pickup */ "50 Health",
|
|
50,
|
|
IT_HEALTH,
|
|
0,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED item_health_mega (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_health_mega",
|
|
"sound/items/m_health.wav",
|
|
{ "models/powerups/health/mega_cross.md3",
|
|
"models/powerups/health/mega_sphere.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/iconh_mega",
|
|
/* pickup */ "Mega Health",
|
|
100,
|
|
IT_HEALTH,
|
|
0,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
|
|
//
|
|
// WEAPONS
|
|
//
|
|
|
|
/*QUAKED weapon_gauntlet (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_gauntlet",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons2/gauntlet/gauntlet.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_gauntlet",
|
|
/* pickup */ "Gauntlet",
|
|
0,
|
|
IT_WEAPON,
|
|
WP_GAUNTLET,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED weapon_shotgun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_shotgun",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons2/shotgun/shotgun.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_shotgun",
|
|
/* pickup */ "Shotgun",
|
|
10,
|
|
IT_WEAPON,
|
|
WP_SHOTGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED weapon_machinegun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_machinegun",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons2/machinegun/machinegun.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_machinegun",
|
|
/* pickup */ "Machinegun",
|
|
40,
|
|
IT_WEAPON,
|
|
WP_MACHINEGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED weapon_grenadelauncher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_grenadelauncher",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons2/grenadel/grenadel.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_grenade",
|
|
/* pickup */ "Grenade Launcher",
|
|
10,
|
|
IT_WEAPON,
|
|
WP_GRENADE_LAUNCHER,
|
|
/* precache */ "",
|
|
/* sounds */ "sound/weapons/grenade/hgrenb1a.wav sound/weapons/grenade/hgrenb2a.wav"
|
|
},
|
|
|
|
/*QUAKED weapon_rocketlauncher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_rocketlauncher",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons2/rocketl/rocketl.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_rocket",
|
|
/* pickup */ "Rocket Launcher",
|
|
10,
|
|
IT_WEAPON,
|
|
WP_ROCKET_LAUNCHER,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED weapon_lightning (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_lightning",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons2/lightning/lightning.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_lightning",
|
|
/* pickup */ "Lightning Gun",
|
|
100,
|
|
IT_WEAPON,
|
|
WP_LIGHTNING,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED weapon_railgun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_railgun",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons2/railgun/railgun.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_railgun",
|
|
/* pickup */ "Railgun",
|
|
10,
|
|
IT_WEAPON,
|
|
WP_RAILGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED weapon_plasmagun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_plasmagun",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons2/plasma/plasma.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_plasma",
|
|
/* pickup */ "Plasma Gun",
|
|
50,
|
|
IT_WEAPON,
|
|
WP_PLASMAGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED weapon_bfg (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_bfg",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons2/bfg/bfg.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_bfg",
|
|
/* pickup */ "BFG10K",
|
|
20,
|
|
IT_WEAPON,
|
|
WP_BFG,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED weapon_grapplinghook (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_grapplinghook",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons2/grapple/grapple.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_grapple",
|
|
/* pickup */ "Grappling Hook",
|
|
0,
|
|
IT_WEAPON,
|
|
WP_GRAPPLING_HOOK,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
//
|
|
// AMMO ITEMS
|
|
//
|
|
|
|
/*QUAKED ammo_shells (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_shells",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/shotgunam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_shotgun",
|
|
/* pickup */ "Shells",
|
|
10,
|
|
IT_AMMO,
|
|
WP_SHOTGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_bullets (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_bullets",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/machinegunam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_machinegun",
|
|
/* pickup */ "Bullets",
|
|
50,
|
|
IT_AMMO,
|
|
WP_MACHINEGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_grenades (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_grenades",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/grenadeam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_grenade",
|
|
/* pickup */ "Grenades",
|
|
5,
|
|
IT_AMMO,
|
|
WP_GRENADE_LAUNCHER,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_cells (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_cells",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/plasmaam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_plasma",
|
|
/* pickup */ "Cells",
|
|
30,
|
|
IT_AMMO,
|
|
WP_PLASMAGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_lightning (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_lightning",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/lightningam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_lightning",
|
|
/* pickup */ "Lightning",
|
|
60,
|
|
IT_AMMO,
|
|
WP_LIGHTNING,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_rockets",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/rocketam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_rocket",
|
|
/* pickup */ "Rockets",
|
|
5,
|
|
IT_AMMO,
|
|
WP_ROCKET_LAUNCHER,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_slugs (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_slugs",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/railgunam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_railgun",
|
|
/* pickup */ "Slugs",
|
|
10,
|
|
IT_AMMO,
|
|
WP_RAILGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_bfg (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_bfg",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/bfgam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_bfg",
|
|
/* pickup */ "Bfg Ammo",
|
|
15,
|
|
IT_AMMO,
|
|
WP_BFG,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
//
|
|
// HOLDABLE ITEMS
|
|
//
|
|
/*QUAKED holdable_teleporter (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"holdable_teleporter",
|
|
"sound/items/holdable.wav",
|
|
{ "models/powerups/holdable/teleporter.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/teleporter",
|
|
/* pickup */ "Personal Teleporter",
|
|
60,
|
|
IT_HOLDABLE,
|
|
HI_TELEPORTER,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
/*QUAKED holdable_medkit (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"holdable_medkit",
|
|
"sound/items/holdable.wav",
|
|
{
|
|
"models/powerups/holdable/medkit.md3",
|
|
"models/powerups/holdable/medkit_sphere.md3",
|
|
NULL, NULL
|
|
},
|
|
/* icon */ "icons/medkit",
|
|
/* pickup */ "Medkit",
|
|
60,
|
|
IT_HOLDABLE,
|
|
HI_MEDKIT,
|
|
/* precache */ "",
|
|
/* sounds */ "sound/items/use_medkit.wav"
|
|
},
|
|
|
|
//
|
|
// POWERUP ITEMS
|
|
//
|
|
/*QUAKED item_quad (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_quad",
|
|
"sound/items/quaddamage.wav",
|
|
{ "models/powerups/instant/quad.md3",
|
|
"models/powerups/instant/quad_ring.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/quad",
|
|
/* pickup */ "Quad Damage",
|
|
30,
|
|
IT_POWERUP,
|
|
PW_QUAD,
|
|
/* precache */ "",
|
|
/* sounds */ "sound/items/damage2.wav sound/items/damage3.wav"
|
|
},
|
|
|
|
/*QUAKED item_enviro (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_enviro",
|
|
"sound/items/protect.wav",
|
|
{ "models/powerups/instant/enviro.md3",
|
|
"models/powerups/instant/enviro_ring.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/envirosuit",
|
|
/* pickup */ "Battle Suit",
|
|
30,
|
|
IT_POWERUP,
|
|
PW_BATTLESUIT,
|
|
/* precache */ "",
|
|
/* sounds */ "sound/items/airout.wav sound/items/protect3.wav"
|
|
},
|
|
|
|
/*QUAKED item_haste (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_haste",
|
|
"sound/items/haste.wav",
|
|
{ "models/powerups/instant/haste.md3",
|
|
"models/powerups/instant/haste_ring.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/haste",
|
|
/* pickup */ "Speed",
|
|
30,
|
|
IT_POWERUP,
|
|
PW_HASTE,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED item_invis (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_invis",
|
|
"sound/items/invisibility.wav",
|
|
{ "models/powerups/instant/invis.md3",
|
|
"models/powerups/instant/invis_ring.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/invis",
|
|
/* pickup */ "Invisibility",
|
|
30,
|
|
IT_POWERUP,
|
|
PW_INVIS,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED item_regen (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_regen",
|
|
"sound/items/regeneration.wav",
|
|
{ "models/powerups/instant/regen.md3",
|
|
"models/powerups/instant/regen_ring.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/regen",
|
|
/* pickup */ "Regeneration",
|
|
30,
|
|
IT_POWERUP,
|
|
PW_REGEN,
|
|
/* precache */ "",
|
|
/* sounds */ "sound/items/regen.wav"
|
|
},
|
|
|
|
/*QUAKED item_flight (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"item_flight",
|
|
"sound/items/flight.wav",
|
|
{ "models/powerups/instant/flight.md3",
|
|
"models/powerups/instant/flight_ring.md3",
|
|
NULL, NULL},
|
|
/* icon */ "icons/flight",
|
|
/* pickup */ "Flight",
|
|
60,
|
|
IT_POWERUP,
|
|
PW_FLIGHT,
|
|
/* precache */ "",
|
|
/* sounds */ "sound/items/flight.wav"
|
|
},
|
|
|
|
/*QUAKED team_CTF_redflag (1 0 0) (-16 -16 -16) (16 16 16)
|
|
Only in CTF games
|
|
*/
|
|
{
|
|
"team_CTF_redflag",
|
|
NULL,
|
|
{ "models/flags/r_flag.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconf_red1",
|
|
/* pickup */ "Red Flag",
|
|
0,
|
|
IT_TEAM,
|
|
PW_REDFLAG,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED team_CTF_blueflag (0 0 1) (-16 -16 -16) (16 16 16)
|
|
Only in CTF games
|
|
*/
|
|
{
|
|
"team_CTF_blueflag",
|
|
NULL,
|
|
{ "models/flags/b_flag.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconf_blu1",
|
|
/* pickup */ "Blue Flag",
|
|
0,
|
|
IT_TEAM,
|
|
PW_BLUEFLAG,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED holdable_kamikaze (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"holdable_kamikaze",
|
|
"sound/items/holdable.wav",
|
|
{ "models/powerups/kamikazi.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/kamikaze",
|
|
/* pickup */ "Kamikaze",
|
|
60,
|
|
IT_HOLDABLE,
|
|
HI_KAMIKAZE,
|
|
/* precache */ "",
|
|
/* sounds */ "sound/items/kamikazerespawn.wav"
|
|
},
|
|
|
|
/*QUAKED holdable_portal (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"holdable_portal",
|
|
"sound/items/holdable.wav",
|
|
{ "models/powerups/holdable/porter.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/portal",
|
|
/* pickup */ "Portal",
|
|
60,
|
|
IT_HOLDABLE,
|
|
HI_PORTAL,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED holdable_invulnerability (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"holdable_invulnerability",
|
|
"sound/items/holdable.wav",
|
|
{ "models/powerups/holdable/invulnerability.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/invulnerability",
|
|
/* pickup */ "Invulnerability",
|
|
60,
|
|
IT_HOLDABLE,
|
|
HI_INVULNERABILITY,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_nails (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_nails",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/nailgunam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_nailgun",
|
|
/* pickup */ "Nails",
|
|
20,
|
|
IT_AMMO,
|
|
WP_NAILGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_mines (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_mines",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/proxmineam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_proxlauncher",
|
|
/* pickup */ "Proximity Mines",
|
|
10,
|
|
IT_AMMO,
|
|
WP_PROX_LAUNCHER,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_belt (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"ammo_belt",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/ammo/chaingunam.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_chaingun",
|
|
/* pickup */ "Chaingun Belt",
|
|
100,
|
|
IT_AMMO,
|
|
WP_CHAINGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
//
|
|
// PERSISTANT POWERUP ITEMS
|
|
//
|
|
/*QUAKED item_scout (.3 .3 1) (-16 -16 -16) (16 16 16) suspended redTeam blueTeam
|
|
*/
|
|
{
|
|
"item_scout",
|
|
"sound/items/scout.wav",
|
|
{ "models/powerups/scout.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/scout",
|
|
/* pickup */ "Scout",
|
|
30,
|
|
IT_PERSISTANT_POWERUP,
|
|
PW_SCOUT,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED item_guard (.3 .3 1) (-16 -16 -16) (16 16 16) suspended redTeam blueTeam
|
|
*/
|
|
{
|
|
"item_guard",
|
|
"sound/items/guard.wav",
|
|
{ "models/powerups/guard.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/guard",
|
|
/* pickup */ "Guard",
|
|
30,
|
|
IT_PERSISTANT_POWERUP,
|
|
PW_GUARD,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED item_doubler (.3 .3 1) (-16 -16 -16) (16 16 16) suspended redTeam blueTeam
|
|
*/
|
|
{
|
|
"item_doubler",
|
|
"sound/items/doubler.wav",
|
|
{ "models/powerups/doubler.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/doubler",
|
|
/* pickup */ "Doubler",
|
|
30,
|
|
IT_PERSISTANT_POWERUP,
|
|
PW_DOUBLER,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED item_doubler (.3 .3 1) (-16 -16 -16) (16 16 16) suspended redTeam blueTeam
|
|
*/
|
|
{
|
|
"item_ammoregen",
|
|
"sound/items/ammoregen.wav",
|
|
{ "models/powerups/ammo.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/ammo_regen",
|
|
/* pickup */ "Ammo Regen",
|
|
30,
|
|
IT_PERSISTANT_POWERUP,
|
|
PW_AMMOREGEN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
|
|
/*QUAKED team_CTF_neutralflag (0 0 1) (-16 -16 -16) (16 16 16)
|
|
Only in One Flag CTF games
|
|
*/
|
|
{
|
|
"team_CTF_neutralflag",
|
|
NULL,
|
|
{ "models/flags/n_flag.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconf_neutral1",
|
|
/* pickup */ "Neutral Flag",
|
|
0,
|
|
IT_TEAM,
|
|
PW_NEUTRALFLAG,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
{
|
|
"item_redcube",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/orb/r_orb.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconh_rorb",
|
|
/* pickup */ "Red Cube",
|
|
0,
|
|
IT_TEAM,
|
|
0,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
{
|
|
"item_bluecube",
|
|
"sound/misc/am_pkup.wav",
|
|
{ "models/powerups/orb/b_orb.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconh_borb",
|
|
/* pickup */ "Blue Cube",
|
|
0,
|
|
IT_TEAM,
|
|
0,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
/*QUAKED weapon_nailgun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_nailgun",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons/nailgun/nailgun.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_nailgun",
|
|
/* pickup */ "Nailgun",
|
|
10,
|
|
IT_WEAPON,
|
|
WP_NAILGUN,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*QUAKED weapon_prox_launcher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_prox_launcher",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons/proxmine/proxmine.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_proxlauncher",
|
|
/* pickup */ "Prox Launcher",
|
|
5,
|
|
IT_WEAPON,
|
|
WP_PROX_LAUNCHER,
|
|
/* precache */ "",
|
|
/* sounds */ "sound/weapons/proxmine/wstbtick.wav "
|
|
"sound/weapons/proxmine/wstbactv.wav "
|
|
"sound/weapons/proxmine/wstbimpl.wav "
|
|
"sound/weapons/proxmine/wstbimpm.wav "
|
|
"sound/weapons/proxmine/wstbimpd.wav "
|
|
"sound/weapons/proxmine/wstbactv.wav"
|
|
},
|
|
|
|
/*QUAKED weapon_chaingun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
|
|
*/
|
|
{
|
|
"weapon_chaingun",
|
|
"sound/misc/w_pkup.wav",
|
|
{ "models/weapons/vulcan/vulcan.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconw_chaingun",
|
|
/* pickup */ "Chaingun",
|
|
80,
|
|
IT_WEAPON,
|
|
WP_CHAINGUN,
|
|
/* precache */ "",
|
|
/* sounds */ "sound/weapons/vulcan/wvulwind.wav"
|
|
},
|
|
//#endif
|
|
|
|
/*team_DD_point - NOT USED IN THE EDITOR
|
|
Only in DD games
|
|
*/
|
|
{
|
|
"team_DD_pointAblue",
|
|
NULL,
|
|
{ "models/dpoints/a_blue.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_blue",
|
|
/* pickup */ "Point A (Blue)",
|
|
0,
|
|
IT_TEAM,
|
|
DD_POINTABLUE,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*team_DD_point - NOT USED IN THE EDITOR
|
|
Only in DD games
|
|
*/
|
|
{
|
|
"team_DD_pointBblue",
|
|
NULL,
|
|
{ "models/dpoints/b_blue.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconb_blue",
|
|
/* pickup */ "Point B (Blue)",
|
|
0,
|
|
IT_TEAM,
|
|
DD_POINTBBLUE,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*team_DD_point - NOT USED IN THE EDITOR
|
|
Only in DD games
|
|
*/
|
|
{
|
|
"team_DD_pointAred",
|
|
NULL,
|
|
{ "models/dpoints/a_red.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_red",
|
|
/* pickup */ "Point A (Red)",
|
|
0,
|
|
IT_TEAM,
|
|
DD_POINTARED,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*team_DD_point - NOT USED IN THE EDITOR
|
|
Only in DD games
|
|
*/
|
|
{
|
|
"team_DD_pointBred",
|
|
NULL,
|
|
{ "models/dpoints/b_red.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconb_red",
|
|
/* pickup */ "Point B (Red)",
|
|
0,
|
|
IT_TEAM,
|
|
DD_POINTBRED,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*team_DD_point - NOT USED IN THE EDITOR
|
|
Only in DD games
|
|
*/
|
|
{
|
|
"team_DD_pointAwhite",
|
|
NULL,
|
|
{ "models/dpoints/a_white.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/icona_white",
|
|
/* pickup */ "Point A (White)",
|
|
0,
|
|
IT_TEAM,
|
|
DD_POINTAWHITE,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*team_DD_point - NOT USED IN THE EDITOR
|
|
Only in DD games
|
|
*/
|
|
{
|
|
"team_DD_pointBwhite",
|
|
NULL,
|
|
{ "models/dpoints/b_white.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconb_white",
|
|
/* pickup */ "Point B (White)",
|
|
0,
|
|
IT_TEAM,
|
|
DD_POINTBWHITE,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
//Now things for standard domination:
|
|
|
|
|
|
/*team_dom_pointWhite - NOT USED IN THE EDITOR
|
|
Only in Domination games
|
|
*/
|
|
{
|
|
"team_dom_pointWhite",
|
|
NULL,
|
|
{ "models/flags/n_flag.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconf_neutral1",
|
|
/* pickup */ "Neutral domination point",
|
|
0,
|
|
IT_TEAM,
|
|
DOM_POINTWHITE,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*team_dom_pointWhite - NOT USED IN THE EDITOR
|
|
Only in Domination games
|
|
*/
|
|
{
|
|
"team_dom_pointRed",
|
|
NULL,
|
|
{ "models/flags/r_flag.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconf_red1",
|
|
/* pickup */ "Red domination point",
|
|
0,
|
|
IT_TEAM,
|
|
DOM_POINTRED,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
/*team_dom_pointBlue - NOT USED IN THE EDITOR
|
|
Only in Domination games
|
|
*/
|
|
{
|
|
"team_dom_pointBlue",
|
|
NULL,
|
|
{ "models/flags/b_flag.md3",
|
|
NULL, NULL, NULL},
|
|
/* icon */ "icons/iconf_blu1",
|
|
/* pickup */ "Blue domination point",
|
|
0,
|
|
IT_TEAM,
|
|
DOM_POINTBLUE,
|
|
/* precache */ "",
|
|
/* sounds */ ""
|
|
},
|
|
|
|
// end of list marker
|
|
{NULL}
|
|
};
|
|
|
|
int bg_numItems = sizeof (bg_itemlist) / sizeof (bg_itemlist[0]) - 1;
|
|
|
|
/*
|
|
==============
|
|
BG_FindItemForPowerup
|
|
==============
|
|
*/
|
|
gitem_t *BG_FindItemForPowerup(powerup_t pw) {
|
|
int i;
|
|
|
|
for (i = 0; i < bg_numItems; i++) {
|
|
if ((bg_itemlist[i].giType == IT_POWERUP ||
|
|
bg_itemlist[i].giType == IT_TEAM ||
|
|
bg_itemlist[i].giType == IT_PERSISTANT_POWERUP) &&
|
|
bg_itemlist[i].giTag == pw) {
|
|
return &bg_itemlist[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
==============
|
|
BG_FindItemForHoldable
|
|
==============
|
|
*/
|
|
gitem_t *BG_FindItemForHoldable(holdable_t pw) {
|
|
int i;
|
|
|
|
for (i = 0; i < bg_numItems; i++) {
|
|
if (bg_itemlist[i].giType == IT_HOLDABLE && bg_itemlist[i].giTag == pw) {
|
|
return &bg_itemlist[i];
|
|
}
|
|
}
|
|
|
|
Com_Error(ERR_DROP, "HoldableItem not found");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
BG_FindItemForWeapon
|
|
|
|
===============
|
|
*/
|
|
gitem_t *BG_FindItemForWeapon(weapon_t weapon) {
|
|
gitem_t *it;
|
|
|
|
for (it = bg_itemlist + 1; it->classname; it++) {
|
|
if (it->giType == IT_WEAPON && it->giTag == weapon) {
|
|
return it;
|
|
}
|
|
}
|
|
|
|
Com_Error(ERR_DROP, "Couldn't find item for weapon %i", weapon);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
BG_FindItem
|
|
|
|
===============
|
|
*/
|
|
gitem_t *BG_FindItem(const char *pickupName) {
|
|
gitem_t *it;
|
|
|
|
for (it = bg_itemlist + 1; it->classname; it++) {
|
|
if (Q_strequal(it->pickup_name, pickupName))
|
|
return it;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
============
|
|
BG_PlayerTouchesItem
|
|
|
|
Items can be picked up without actually touching their physical bounds to make
|
|
grabbing them easier
|
|
============
|
|
*/
|
|
qboolean BG_PlayerTouchesItem(playerState_t *ps, entityState_t *item, int atTime) {
|
|
vec3_t origin;
|
|
|
|
BG_EvaluateTrajectory(&item->pos, atTime, origin);
|
|
|
|
// we are ignoring ducked differences here
|
|
if (ps->origin[0] - origin[0] > 44
|
|
|| ps->origin[0] - origin[0] < -50
|
|
|| ps->origin[1] - origin[1] > 36
|
|
|| ps->origin[1] - origin[1] < -36
|
|
|| ps->origin[2] - origin[2] > 36
|
|
|| ps->origin[2] - origin[2] < -36) {
|
|
return qfalse;
|
|
}
|
|
|
|
return qtrue;
|
|
}
|
|
|
|
/*
|
|
================
|
|
BG_CanItemBeGrabbed
|
|
|
|
Returns false if the item should not be picked up.
|
|
This needs to be the same for client side prediction and server use.
|
|
================
|
|
*/
|
|
qboolean BG_CanItemBeGrabbed(int gametype, const entityState_t *ent, const playerState_t *ps) {
|
|
gitem_t *item;
|
|
int upperBound;
|
|
|
|
if (ent->modelindex < 1 || ent->modelindex >= bg_numItems) {
|
|
Com_Error(ERR_DROP, "BG_CanItemBeGrabbed: index out of range");
|
|
}
|
|
|
|
item = &bg_itemlist[ent->modelindex];
|
|
|
|
switch (item->giType) {
|
|
case IT_WEAPON:
|
|
return qtrue; // weapons are always picked up
|
|
|
|
case IT_AMMO:
|
|
if (ps->ammo[ item->giTag ] >= 200) {
|
|
return qfalse; // can't hold any more
|
|
}
|
|
return qtrue;
|
|
|
|
case IT_ARMOR:
|
|
if (bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_SCOUT) {
|
|
return qfalse;
|
|
}
|
|
|
|
// we also clamp armor to the maxhealth for handicapping
|
|
if (bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD) {
|
|
upperBound = ps->stats[STAT_MAX_HEALTH];
|
|
} else {
|
|
upperBound = ps->stats[STAT_MAX_HEALTH] * 2;
|
|
}
|
|
|
|
if (ps->stats[STAT_ARMOR] >= upperBound) {
|
|
return qfalse;
|
|
}
|
|
return qtrue;
|
|
|
|
case IT_HEALTH:
|
|
// small and mega healths will go over the max, otherwise
|
|
// don't pick up if already at max
|
|
if (bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD) {
|
|
upperBound = ps->stats[STAT_MAX_HEALTH];
|
|
} else
|
|
if (item->quantity == 5 || item->quantity == 100) {
|
|
if (ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] * 2) {
|
|
return qfalse;
|
|
}
|
|
return qtrue;
|
|
}
|
|
|
|
if (ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH]) {
|
|
return qfalse;
|
|
}
|
|
return qtrue;
|
|
|
|
case IT_POWERUP:
|
|
return qtrue; // powerups are always picked up
|
|
|
|
case IT_PERSISTANT_POWERUP:
|
|
|
|
//In Double D we don't want persistant Powerups (or maybe, can be discussed)
|
|
if (gametype == GT_DOUBLE_D)
|
|
return qfalse;
|
|
|
|
// can only hold one item at a time
|
|
if (ps->stats[STAT_PERSISTANT_POWERUP]) {
|
|
return qfalse;
|
|
}
|
|
|
|
// check team only
|
|
if ((ent->generic1 & 2) && (ps->persistant[PERS_TEAM] != TEAM_RED)) {
|
|
return qfalse;
|
|
}
|
|
if ((ent->generic1 & 4) && (ps->persistant[PERS_TEAM] != TEAM_BLUE)) {
|
|
return qfalse;
|
|
}
|
|
|
|
return qtrue;
|
|
|
|
case IT_TEAM: // team items, such as flags
|
|
if (gametype == GT_POSSESSION) {
|
|
if (item->giTag == PW_NEUTRALFLAG) {
|
|
return qtrue;
|
|
}
|
|
}
|
|
if (gametype == GT_1FCTF) {
|
|
// neutral flag can always be picked up
|
|
if (item->giTag == PW_NEUTRALFLAG) {
|
|
return qtrue;
|
|
}
|
|
if (ps->persistant[PERS_TEAM] == TEAM_RED) {
|
|
if (item->giTag == PW_BLUEFLAG && ps->powerups[PW_NEUTRALFLAG]) {
|
|
return qtrue;
|
|
}
|
|
} else if (ps->persistant[PERS_TEAM] == TEAM_BLUE) {
|
|
if (item->giTag == PW_REDFLAG && ps->powerups[PW_NEUTRALFLAG]) {
|
|
return qtrue;
|
|
}
|
|
}
|
|
}
|
|
if (gametype == GT_CTF || gametype == GT_CTF_ELIMINATION) {
|
|
// ent->modelindex2 is non-zero on items if they are dropped
|
|
// we need to know this because we can pick up our dropped flag (and return it)
|
|
// but we can't pick up our flag at base
|
|
if (ps->persistant[PERS_TEAM] == TEAM_RED) {
|
|
if (item->giTag == PW_BLUEFLAG ||
|
|
(item->giTag == PW_REDFLAG && ent->modelindex2) ||
|
|
(item->giTag == PW_REDFLAG && ps->powerups[PW_BLUEFLAG]))
|
|
return qtrue;
|
|
} else if (ps->persistant[PERS_TEAM] == TEAM_BLUE) {
|
|
if (item->giTag == PW_REDFLAG ||
|
|
(item->giTag == PW_BLUEFLAG && ent->modelindex2) ||
|
|
(item->giTag == PW_BLUEFLAG && ps->powerups[PW_REDFLAG]))
|
|
return qtrue;
|
|
}
|
|
}
|
|
|
|
if (gametype == GT_DOUBLE_D) {
|
|
//We can touch both flags
|
|
if (item->giTag == PW_BLUEFLAG || item->giTag == PW_REDFLAG)
|
|
return qtrue;
|
|
}
|
|
|
|
if (gametype == GT_DOMINATION) {
|
|
if (item->giTag == DOM_POINTWHITE)
|
|
return qtrue;
|
|
if (ps->persistant[PERS_TEAM] == TEAM_RED) {
|
|
if (item->giTag == DOM_POINTBLUE)
|
|
return qtrue;
|
|
} else if (ps->persistant[PERS_TEAM] == TEAM_BLUE) {
|
|
if (item->giTag == DOM_POINTRED)
|
|
return qtrue;
|
|
}
|
|
}
|
|
|
|
if (gametype == GT_HARVESTER) {
|
|
return qtrue;
|
|
}
|
|
return qfalse;
|
|
|
|
case IT_HOLDABLE:
|
|
// can only hold one item at a time
|
|
if (ps->stats[STAT_HOLDABLE_ITEM]) {
|
|
return qfalse;
|
|
}
|
|
return qtrue;
|
|
|
|
case IT_BAD:
|
|
Com_Error(ERR_DROP, "BG_CanItemBeGrabbed: IT_BAD");
|
|
default:
|
|
#ifndef Q3_VM
|
|
#ifndef NDEBUG // bk0001204
|
|
Com_Printf("BG_CanItemBeGrabbed: unknown enum %d\n", item->giType);
|
|
#endif
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
return qfalse;
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
/*
|
|
================
|
|
BG_EvaluateTrajectory
|
|
|
|
================
|
|
*/
|
|
void BG_EvaluateTrajectory(const trajectory_t *tr, int atTime, vec3_t result) {
|
|
float deltaTime;
|
|
float phase;
|
|
|
|
switch (tr->trType) {
|
|
case TR_STATIONARY:
|
|
case TR_INTERPOLATE:
|
|
VectorCopy(tr->trBase, result);
|
|
break;
|
|
case TR_LINEAR:
|
|
deltaTime = (atTime - tr->trTime) * 0.001; // milliseconds to seconds
|
|
VectorMA(tr->trBase, deltaTime, tr->trDelta, result);
|
|
break;
|
|
case TR_SINE:
|
|
deltaTime = (atTime - tr->trTime) / (float) tr->trDuration;
|
|
phase = sin(deltaTime * M_PI * 2);
|
|
VectorMA(tr->trBase, phase, tr->trDelta, result);
|
|
break;
|
|
case TR_LINEAR_STOP:
|
|
if (atTime > tr->trTime + tr->trDuration) {
|
|
atTime = tr->trTime + tr->trDuration;
|
|
}
|
|
deltaTime = (atTime - tr->trTime) * 0.001; // milliseconds to seconds
|
|
if (deltaTime < 0) {
|
|
deltaTime = 0;
|
|
}
|
|
VectorMA(tr->trBase, deltaTime, tr->trDelta, result);
|
|
break;
|
|
case TR_GRAVITY:
|
|
deltaTime = (atTime - tr->trTime) * 0.001; // milliseconds to seconds
|
|
VectorMA(tr->trBase, deltaTime, tr->trDelta, result);
|
|
result[2] -= 0.5 * DEFAULT_GRAVITY * deltaTime * deltaTime; // FIXME: local gravity...
|
|
break;
|
|
default:
|
|
Com_Error(ERR_DROP, "BG_EvaluateTrajectory: unknown trType: %i", tr->trTime);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
BG_EvaluateTrajectoryDelta
|
|
|
|
For determining velocity at a given time
|
|
================
|
|
*/
|
|
void BG_EvaluateTrajectoryDelta(const trajectory_t *tr, int atTime, vec3_t result) {
|
|
float deltaTime;
|
|
float phase;
|
|
|
|
switch (tr->trType) {
|
|
case TR_STATIONARY:
|
|
case TR_INTERPOLATE:
|
|
VectorClear(result);
|
|
break;
|
|
case TR_LINEAR:
|
|
VectorCopy(tr->trDelta, result);
|
|
break;
|
|
case TR_SINE:
|
|
deltaTime = (atTime - tr->trTime) / (float) tr->trDuration;
|
|
phase = cos(deltaTime * M_PI * 2); // derivative of sin = cos
|
|
phase *= 0.5;
|
|
VectorScale(tr->trDelta, phase, result);
|
|
break;
|
|
case TR_LINEAR_STOP:
|
|
if (atTime > tr->trTime + tr->trDuration) {
|
|
VectorClear(result);
|
|
return;
|
|
}
|
|
VectorCopy(tr->trDelta, result);
|
|
break;
|
|
case TR_GRAVITY:
|
|
deltaTime = (atTime - tr->trTime) * 0.001; // milliseconds to seconds
|
|
VectorCopy(tr->trDelta, result);
|
|
result[2] -= DEFAULT_GRAVITY * deltaTime; // FIXME: local gravity...
|
|
break;
|
|
default:
|
|
Com_Error(ERR_DROP, "BG_EvaluateTrajectoryDelta: unknown trType: %i", tr->trTime);
|
|
break;
|
|
}
|
|
}
|
|
|
|
char *eventnames[] = {
|
|
"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
|
|
|
|
//Not all of these are used in baseoa but we keep them to gurantie event numbers between version
|
|
"EV_PROXIMITY_MINE_STICK",
|
|
"EV_PROXIMITY_MINE_TRIGGER",
|
|
"EV_KAMIKAZE", // kamikaze explodes
|
|
"EV_OBELISKEXPLODE", // obelisk explodes
|
|
"EV_INVUL_IMPACT", // invulnerability sphere impact
|
|
"EV_JUICED", // invulnerability juiced effect
|
|
"EV_LIGHTNINGBOLT", // lightning bolt bounced of invulnerability sphere
|
|
|
|
|
|
"EV_DEBUG_LINE",
|
|
"EV_STOPLOOPINGSOUND",
|
|
"EV_TAUNT",
|
|
"EV_FOOTSTEP_WOOD",
|
|
"EV_FOOTSTEP_SNOW",
|
|
"EV_FOOTSTEP_SAND",
|
|
"EV_FOOTSTEP_GRAVEL",
|
|
"EV_FOOTSTEP_FOILAGE",
|
|
"EV_FOOTSTEP_ICE",
|
|
"EV_FOOTSTEP_GLASS",
|
|
"EV_BULLET_HIT_WOOD",
|
|
"EV_BULLET_HIT_SAND",
|
|
"EV_BULLET_HIT_SNOW",
|
|
"EV_BULLET_HIT_GLASS"
|
|
|
|
};
|
|
|
|
/*
|
|
===============
|
|
BG_AddPredictableEventToPlayerstate
|
|
|
|
Handles the sequence numbers
|
|
===============
|
|
*/
|
|
|
|
void trap_Cvar_VariableStringBuffer(const char *var_name, char *buffer, int bufsize);
|
|
|
|
void BG_AddPredictableEventToPlayerstate(int newEvent, int eventParm, playerState_t *ps) {
|
|
|
|
#ifdef _DEBUG
|
|
{
|
|
char buf[256];
|
|
trap_Cvar_VariableStringBuffer("showevents", buf, sizeof (buf));
|
|
if (atof(buf) != 0) {
|
|
#ifdef QAGAME
|
|
Com_Printf(" game event svt %5d -> %5d: num = %20s parm %d\n", ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, eventnames[newEvent], eventParm);
|
|
#else
|
|
Com_Printf("Cgame event svt %5d -> %5d: num = %20s parm %d\n", ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, eventnames[newEvent], eventParm);
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
ps->events[ps->eventSequence & (MAX_PS_EVENTS - 1)] = newEvent;
|
|
ps->eventParms[ps->eventSequence & (MAX_PS_EVENTS - 1)] = eventParm;
|
|
ps->eventSequence++;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
BG_TouchJumpPad
|
|
========================
|
|
*/
|
|
void BG_TouchJumpPad(playerState_t *ps, entityState_t *jumppad) {
|
|
vec3_t angles;
|
|
float p;
|
|
int effectNum;
|
|
|
|
// spectators don't use jump pads
|
|
if (ps->pm_type != PM_NORMAL) {
|
|
return;
|
|
}
|
|
|
|
// flying characters don't hit bounce pads
|
|
if (ps->powerups[PW_FLIGHT]) {
|
|
return;
|
|
}
|
|
|
|
// if we didn't hit this same jumppad the previous frame
|
|
// then don't play the event sound again if we are in a fat trigger
|
|
if (ps->jumppad_ent != jumppad->number) {
|
|
|
|
vectoangles(jumppad->origin2, angles);
|
|
p = fabs(AngleNormalize180(angles[PITCH]));
|
|
if (p < 45) {
|
|
effectNum = 0;
|
|
} else {
|
|
effectNum = 1;
|
|
}
|
|
BG_AddPredictableEventToPlayerstate(EV_JUMP_PAD, effectNum, ps);
|
|
}
|
|
// remember hitting this jumppad this frame
|
|
ps->jumppad_ent = jumppad->number;
|
|
ps->jumppad_frame = ps->pmove_framecount;
|
|
// give the player the velocity from the jumppad
|
|
VectorCopy(jumppad->origin2, ps->velocity);
|
|
}
|
|
|
|
/*
|
|
========================
|
|
BG_PlayerStateToEntityState
|
|
|
|
This is done after each set of usercmd_t on the server,
|
|
and after local prediction on the client
|
|
========================
|
|
*/
|
|
void BG_PlayerStateToEntityState(playerState_t *ps, entityState_t *s, qboolean snap) {
|
|
int i;
|
|
|
|
if (ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR) {
|
|
s->eType = ET_INVISIBLE;
|
|
} else if (ps->stats[STAT_HEALTH] <= GIB_HEALTH) {
|
|
s->eType = ET_INVISIBLE;
|
|
} else {
|
|
s->eType = ET_PLAYER;
|
|
}
|
|
|
|
s->number = ps->clientNum;
|
|
|
|
s->pos.trType = TR_INTERPOLATE;
|
|
VectorCopy(ps->origin, s->pos.trBase);
|
|
if (snap) {
|
|
SnapVector(s->pos.trBase);
|
|
}
|
|
// set the trDelta for flag direction
|
|
VectorCopy(ps->velocity, s->pos.trDelta);
|
|
|
|
s->apos.trType = TR_INTERPOLATE;
|
|
VectorCopy(ps->viewangles, s->apos.trBase);
|
|
if (snap) {
|
|
SnapVector(s->apos.trBase);
|
|
}
|
|
|
|
s->angles2[YAW] = ps->movementDir;
|
|
s->legsAnim = ps->legsAnim;
|
|
s->torsoAnim = ps->torsoAnim;
|
|
s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number
|
|
// so corpses can also reference the proper config
|
|
s->eFlags = ps->eFlags;
|
|
if (ps->stats[STAT_HEALTH] <= 0) {
|
|
s->eFlags |= EF_DEAD;
|
|
} else {
|
|
s->eFlags &= ~EF_DEAD;
|
|
}
|
|
|
|
if (ps->externalEvent) {
|
|
s->event = ps->externalEvent;
|
|
s->eventParm = ps->externalEventParm;
|
|
} else if (ps->entityEventSequence < ps->eventSequence) {
|
|
int seq;
|
|
|
|
if (ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS) {
|
|
ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS;
|
|
}
|
|
seq = ps->entityEventSequence & (MAX_PS_EVENTS - 1);
|
|
s->event = ps->events[ seq ] | ((ps->entityEventSequence & 3) << 8);
|
|
s->eventParm = ps->eventParms[ seq ];
|
|
ps->entityEventSequence++;
|
|
}
|
|
|
|
s->weapon = ps->weapon;
|
|
s->groundEntityNum = ps->groundEntityNum;
|
|
|
|
s->powerups = 0;
|
|
for (i = 0; i < MAX_POWERUPS; i++) {
|
|
if (ps->powerups[ i ]) {
|
|
s->powerups |= 1 << i;
|
|
}
|
|
}
|
|
|
|
s->loopSound = ps->loopSound;
|
|
s->generic1 = ps->generic1;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
BG_PlayerStateToEntityStateExtraPolate
|
|
|
|
This is done after each set of usercmd_t on the server,
|
|
and after local prediction on the client
|
|
========================
|
|
*/
|
|
void BG_PlayerStateToEntityStateExtraPolate(playerState_t *ps, entityState_t *s, int time, qboolean snap) {
|
|
int i;
|
|
|
|
if (ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR) {
|
|
s->eType = ET_INVISIBLE;
|
|
} else if (ps->stats[STAT_HEALTH] <= GIB_HEALTH) {
|
|
s->eType = ET_INVISIBLE;
|
|
} else {
|
|
s->eType = ET_PLAYER;
|
|
}
|
|
|
|
s->number = ps->clientNum;
|
|
|
|
s->pos.trType = TR_LINEAR_STOP;
|
|
VectorCopy(ps->origin, s->pos.trBase);
|
|
if (snap) {
|
|
SnapVector(s->pos.trBase);
|
|
}
|
|
// set the trDelta for flag direction and linear prediction
|
|
VectorCopy(ps->velocity, s->pos.trDelta);
|
|
// set the time for linear prediction
|
|
s->pos.trTime = time;
|
|
// set maximum extra polation time
|
|
s->pos.trDuration = 50; // 1000 / sv_fps (default = 20)
|
|
|
|
s->apos.trType = TR_INTERPOLATE;
|
|
VectorCopy(ps->viewangles, s->apos.trBase);
|
|
if (snap) {
|
|
SnapVector(s->apos.trBase);
|
|
}
|
|
|
|
s->angles2[YAW] = ps->movementDir;
|
|
s->legsAnim = ps->legsAnim;
|
|
s->torsoAnim = ps->torsoAnim;
|
|
s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number
|
|
// so corpses can also reference the proper config
|
|
s->eFlags = ps->eFlags;
|
|
if (ps->stats[STAT_HEALTH] <= 0) {
|
|
s->eFlags |= EF_DEAD;
|
|
} else {
|
|
s->eFlags &= ~EF_DEAD;
|
|
}
|
|
|
|
if (ps->externalEvent) {
|
|
s->event = ps->externalEvent;
|
|
s->eventParm = ps->externalEventParm;
|
|
} else if (ps->entityEventSequence < ps->eventSequence) {
|
|
int seq;
|
|
|
|
if (ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS) {
|
|
ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS;
|
|
}
|
|
seq = ps->entityEventSequence & (MAX_PS_EVENTS - 1);
|
|
s->event = ps->events[ seq ] | ((ps->entityEventSequence & 3) << 8);
|
|
s->eventParm = ps->eventParms[ seq ];
|
|
ps->entityEventSequence++;
|
|
}
|
|
|
|
s->weapon = ps->weapon;
|
|
s->groundEntityNum = ps->groundEntityNum;
|
|
|
|
s->powerups = 0;
|
|
for (i = 0; i < MAX_POWERUPS; i++) {
|
|
if (ps->powerups[ i ]) {
|
|
s->powerups |= 1 << i;
|
|
}
|
|
}
|
|
|
|
s->loopSound = ps->loopSound;
|
|
s->generic1 = ps->generic1;
|
|
}
|
|
|
|
/*
|
|
============
|
|
BG_TeamName
|
|
KK-OAX Copied from Tremulous
|
|
============
|
|
*/
|
|
const char *BG_TeamName(team_t team) {
|
|
if (team == TEAM_NONE)
|
|
return "spectator";
|
|
if (team == TEAM_RED)
|
|
return "Red";
|
|
if (team == TEAM_BLUE)
|
|
return "Blue";
|
|
if (team == TEAM_FREE)
|
|
return "Free For All";
|
|
return "<team>";
|
|
}
|
|
|
|
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_FCloseFile(fileHandle_t f);
|
|
|
|
qboolean MatchesGametype(int gametype, const char* gametypeName) {
|
|
qboolean mayRead = qfalse;
|
|
switch (gametype) {
|
|
case GT_FFA:
|
|
if (Q_strequal(gametypeName, "dm")) mayRead = qtrue;
|
|
break;
|
|
case GT_TEAM:
|
|
if (Q_strequal(gametypeName, "team")) mayRead = qtrue;
|
|
break;
|
|
case GT_TOURNAMENT:
|
|
if (Q_strequal(gametypeName, "tourney")) mayRead = qtrue;
|
|
break;
|
|
case GT_CTF:
|
|
if (Q_strequal(gametypeName, "ctf")) mayRead = qtrue;
|
|
break;
|
|
case GT_1FCTF:
|
|
if (Q_strequal(gametypeName, "1fctf")) mayRead = qtrue;
|
|
break;
|
|
case GT_OBELISK:
|
|
if (Q_strequal(gametypeName, "obelisk")) mayRead = qtrue;
|
|
break;
|
|
case GT_HARVESTER:
|
|
if (Q_strequal(gametypeName, "harvester")) mayRead = qtrue;
|
|
break;
|
|
case GT_ELIMINATION:
|
|
if (Q_strequal(gametypeName, "elimination")) mayRead = qtrue;
|
|
break;
|
|
case GT_CTF_ELIMINATION:
|
|
if (Q_strequal(gametypeName, "ctfelim")) mayRead = qtrue;
|
|
break;
|
|
case GT_LMS:
|
|
if (Q_strequal(gametypeName, "lms")) mayRead = qtrue;
|
|
break;
|
|
case GT_DOUBLE_D:
|
|
if (Q_strequal(gametypeName, "dd")) mayRead = qtrue;
|
|
break;
|
|
case GT_DOMINATION:
|
|
if (Q_strequal(gametypeName, "dom")) mayRead = qtrue;
|
|
break;
|
|
case GT_POSSESSION:
|
|
if (Q_strequal(gametypeName, "pos")) mayRead = qtrue;
|
|
break;
|
|
};
|
|
return mayRead;
|
|
}
|
|
|
|
void MapInfoGet(const char* mapname, int gametype, mapinfo_result_t *result) {
|
|
fileHandle_t file;
|
|
char buffer[4 * 1024];
|
|
char keyBuffer[MAX_TOKEN_CHARS];
|
|
char *token;
|
|
char *pointer;
|
|
int mayRead;
|
|
int i;
|
|
|
|
memset(result, 0, sizeof (*result));
|
|
Com_sprintf(buffer, sizeof (buffer), "maps/%s.info", mapname);
|
|
Q_strlwr(buffer);
|
|
|
|
trap_FS_FOpenFile(buffer, &file, FS_READ);
|
|
|
|
if (!file) {
|
|
Com_Printf("File %s not found\n", buffer);
|
|
return;
|
|
}
|
|
|
|
memset(&buffer, 0, sizeof (buffer));
|
|
|
|
trap_FS_Read(&buffer, sizeof (buffer), file);
|
|
|
|
pointer = buffer;
|
|
mayRead = qtrue;
|
|
|
|
while (qtrue) {
|
|
token = COM_Parse(&pointer);
|
|
if (!token[0]) {
|
|
break;
|
|
}
|
|
Q_strncpyz(keyBuffer, token, sizeof (keyBuffer));
|
|
token = COM_Parse(&pointer);
|
|
|
|
Com_Printf("Token \"%s\" found, with value: \"%s\"\n", keyBuffer, token);
|
|
|
|
if (Q_strequal(keyBuffer, "gametype")) {
|
|
mayRead = qfalse;
|
|
if (!token[0]) {
|
|
break;
|
|
}
|
|
if (Q_strequal(token, "*")) {
|
|
mayRead = qtrue;
|
|
}
|
|
else {
|
|
mayRead = MatchesGametype(gametype, token);
|
|
}
|
|
}
|
|
if (Q_strequal(keyBuffer, "author")) {
|
|
if (mayRead) Q_strncpyz(result->author, token, sizeof (result->author));
|
|
}
|
|
if (Q_strequal(keyBuffer, "title")) {
|
|
if (mayRead) Q_strncpyz(result->title, token, sizeof (result->title));
|
|
}
|
|
if (Q_strequal(keyBuffer, "description")) {
|
|
if (mayRead) Q_strncpyz(result->description, token, sizeof (result->description));
|
|
}
|
|
if (Q_strequal(keyBuffer, "mpBots")) {
|
|
if (mayRead) Q_strncpyz(result->mpBots, token, sizeof (result->mpBots));
|
|
}
|
|
if (Q_strequal(keyBuffer, "mpBotCount")) {
|
|
if (mayRead) result->mpBotCount = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "redBots")) {
|
|
if (mayRead) Q_strncpyz(result->redBots, token, sizeof (result->redBots));
|
|
}
|
|
if (Q_strequal(keyBuffer, "redBotCount")) {
|
|
if (mayRead) result->redBotCount = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "blueBots")) {
|
|
if (mayRead) Q_strncpyz(result->blueBots, token, sizeof (result->blueBots));
|
|
}
|
|
if (Q_strequal(keyBuffer, "blueBotCount")) {
|
|
if (mayRead) result->blueBotCount = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "captureLimit")) {
|
|
if (mayRead) result->captureLimit = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "fragLimit")) {
|
|
if (mayRead) result->fragLimit = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "maxPlayers")) {
|
|
if (mayRead) result->maxPlayers = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "maxTeamSize")) {
|
|
if (mayRead) result->maxTeamSize = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "minPlayers")) {
|
|
if (mayRead) result->minPlayers = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "minTeamSize")) {
|
|
if (mayRead) result->minTeamSize = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "recommendedPlayers")) {
|
|
if (mayRead) result->recommendedPlayers = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "recommendedTeamSize")) {
|
|
if (mayRead) result->recommendedTeamSize = atoi(token);
|
|
}
|
|
if (Q_strequal(keyBuffer, "timeLimit")) {
|
|
if (mayRead) result->timeLimit = atoi(token);
|
|
}
|
|
#define SUPPORT_GAMETYPE_PREFIX "support_"
|
|
if (Q_strequaln(keyBuffer, SUPPORT_GAMETYPE_PREFIX, sizeof (SUPPORT_GAMETYPE_PREFIX) - 1)) {
|
|
//Com_Printf("Saw %s, gametype part: %s\n", token, &token[sizeof(SUPPORT_GAMETYPE_PREFIX)-1]);
|
|
for (i = 0; i < GT_MAX_GAME_TYPE; ++i) {
|
|
if (MatchesGametype(i, &keyBuffer[sizeof (SUPPORT_GAMETYPE_PREFIX) - 1])) {
|
|
//Com_Printf("Matched gametype %d, %s\n", i, token);
|
|
result->gametypeSupported[i] = token[0];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
trap_FS_FCloseFile(file);
|
|
}
|