vector org = targ.origin;
#ifdef SVQC
- if(autocvar_sv_q3defragcompat)
+ if(q3compat)
#elif defined(CSQC)
- if(STAT(Q3DEFRAGCOMPAT))
+ if(STAT(Q3COMPAT))
#endif
{
org.z += targ.mins_z;
WriteString(MSG_ENTITY, this.targetname);
WriteVector(MSG_ENTITY, this.origin);
- WriteAngle(MSG_ENTITY, this.angles_x);
- WriteAngle(MSG_ENTITY, this.angles_y);
- WriteAngle(MSG_ENTITY, this.angles_z);
+ WriteAngleVector(MSG_ENTITY, this.angles);
return true;
}
this.targetname = strzone(ReadString());
this.origin = ReadVector();
- this.angles_x = ReadAngle();
- this.angles_y = ReadAngle();
- this.angles_z = ReadAngle();
+ this.angles = ReadAngleVector();
return = true;
return; // only players
}
- // TODO: restructure this so that trigger_secret is more independent
- if (this.classname == "trigger_secret")
- {
- if (!IS_PLAYER(this.enemy))
- return;
- found_secrets = found_secrets + 1;
- WriteByte (MSG_ALL, SVC_FOUNDSECRET);
- }
-
- if (this.noise)
+ if (this.noise && this.noise != "")
{
_sound (this.enemy, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
}
else if (this.sounds == 3)
this.noise = "misc/trigger1.wav";
- if(this.noise)
+ if(this.noise && this.noise != "")
precache_sound(this.noise);
if (!this.wait)
this.wait = 0;
this.use = multi_use;
- if(this.wait == -1 && autocvar_sv_q3defragcompat)
+ if(this.wait == -1 && (q3compat & BIT(1)))
this.wait = 0.1; // compatibility for q3df: "instant" return
EXACTTRIGGER_INIT;
#ifdef SVQC
#include <server/miscfunctions.qh>
+ #include <common/mapobjects/defs.qh>
#include "../mapobjects/trigger/viewloc.qh"
// client side physics
STAT(MOVEVARS_HIGHSPEED, this) = autocvar_g_movement_highspeed;
MUTATOR_CALLHOOK(PlayerPhysics_UpdateStats, this);
- float maxspd_mod = PHYS_HIGHSPEED(this) * ((this.swampslug.active) ? this.swampslug.swamp_slowdown : 1);
+ float maxspd_mod = PHYS_HIGHSPEED(this) * ((this.swampslug.active == ACTIVE_ACTIVE) ? this.swampslug.swamp_slowdown : 1);
STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed", autocvar_sv_maxspeed) * maxspd_mod; // also slow walking
if (autocvar_g_movement_highspeed_q3_compat) {
STAT(MOVEVARS_AIRACCEL_QW, this) = Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw);
: 0;
STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw) * maxspd_mod;
}
- bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox; // NOTE: these hitboxes are off by 1 due to engine differences
- STAT(PL_MIN, this) = (q3dfcompat) ? '-15 -15 -20' : autocvar_sv_player_mins;
- STAT(PL_MAX, this) = (q3dfcompat) ? '15 15 36' : autocvar_sv_player_maxs;
- STAT(PL_VIEW_OFS, this) = (q3dfcompat) ? '0 0 30' : autocvar_sv_player_viewoffset;
- STAT(PL_CROUCH_MIN, this) = (q3dfcompat) ? '-15 -15 -20' : autocvar_sv_player_crouch_mins;
- STAT(PL_CROUCH_MAX, this) = (q3dfcompat) ? '15 15 20' : autocvar_sv_player_crouch_maxs;
- STAT(PL_CROUCH_VIEW_OFS, this) = (q3dfcompat) ? '0 0 16' : autocvar_sv_player_crouch_viewoffset;
+ bool q3hb = q3compat && autocvar_sv_q3compat_changehitbox; // NOTE: these hitboxes are off by 1 due to engine differences
+ STAT(PL_MIN, this) = (q3hb) ? '-15 -15 -20' : autocvar_sv_player_mins;
+ STAT(PL_MAX, this) = (q3hb) ? '15 15 36' : autocvar_sv_player_maxs;
+ STAT(PL_VIEW_OFS, this) = (q3hb) ? '0 0 30' : autocvar_sv_player_viewoffset;
+ STAT(PL_CROUCH_MIN, this) = (q3hb) ? '-15 -15 -20' : autocvar_sv_player_crouch_mins;
+ STAT(PL_CROUCH_MAX, this) = (q3hb) ? '15 15 20' : autocvar_sv_player_crouch_maxs;
+ STAT(PL_CROUCH_VIEW_OFS, this) = (q3hb) ? '0 0 16' : autocvar_sv_player_crouch_viewoffset;
// old stats
// fix some new settings
#ifdef SVQC
#include <server/autocvars.qh>
#include <server/client.qh>
+#include <server/compat/quake3.qh>
+ #include <common/mapobjects/trigger/secret.qh>
#endif
// Full list of all stat constants, included in a single location for easy reference
REGISTER_STAT(VEHICLESTAT_RELOAD2, int)
REGISTER_STAT(VEHICLESTAT_W2MODE, int)
REGISTER_STAT(NADE_TIMER, float)
- REGISTER_STAT(SECRETS_TOTAL, float)
- REGISTER_STAT(SECRETS_FOUND, float)
+ REGISTER_STAT(SECRETS_TOTAL, int, secrets_total)
+ REGISTER_STAT(SECRETS_FOUND, int, secrets_found)
REGISTER_STAT(RESPAWN_TIME, float)
REGISTER_STAT(ROUNDSTARTTIME, float, round_starttime)
REGISTER_STAT(MONSTERS_TOTAL, int)
#endif
REGISTER_STAT(SLICK_APPLYGRAVITY, bool, autocvar_sv_slick_applygravity)
-#ifdef SVQC
-bool autocvar_sv_q3defragcompat;
-#endif
-REGISTER_STAT(Q3DEFRAGCOMPAT, bool, autocvar_sv_q3defragcompat)
+REGISTER_STAT(Q3COMPAT, int, q3compat)
#ifdef SVQC
#include "physics/movetypes/movetypes.qh"
// enable to debug melee range
//#define SHOTGUN_MELEEDEBUG
-METHOD(Shotgun, m_spawnfunc_hookreplace, Weapon(Shotgun this, entity e))
-{
- if (autocvar_sv_q3acompat_machineshotgunswap && !Item_IsLoot(e))
- {
- return WEP_MACHINEGUN;
- }
- return this;
-}
-
void W_Shotgun_Attack(Weapon thiswep, entity actor, .entity weaponentity, float isprimary, float ammocount, float damage, float bullets, float spread, float solidpenetration, float force, entity bullet_trail_effect)
{
W_DecreaseAmmo(thiswep, actor, ammocount, weaponentity);
antilag_takeback_all(actor, lag);
for(int sc = 0;sc < bullets;sc = sc + 1)
- fireBullet_antilag(actor, weaponentity, w_shotorg, w_shotdir, spread, solidpenetration, damage, force, thiswep.m_id, bullet_trail_effect, false);
+ fireBullet_antilag(actor, weaponentity, w_shotorg, w_shotdir, spread, solidpenetration, damage, 0, force, thiswep.m_id, bullet_trail_effect, false);
if(lag && bullets > 0)
antilag_restore_all(actor);
setthink(this, func_null);
this.nextthink = 0;
this.deadflag = DEAD_NO;
- this.crouch = false;
+ UNSET_DUCKED(this);
STAT(REVIVE_PROGRESS, this) = 0;
this.revival_time = 0;
this.draggable = drag_undraggable;
this.respawn_flags = 0;
this.respawn_time = 0;
STAT(RESPAWN_TIME, this) = 0;
- bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox;
- this.scale = ((q3dfcompat) ? 0.9 : autocvar_sv_player_scale);
+ this.scale = ((q3compat && autocvar_sv_q3compat_changehitbox) ? 0.9 : autocvar_sv_player_scale);
this.fade_time = 0;
this.pain_frame = 0;
this.pain_finished = 0;
this.spawnpoint_targ = NULL;
- this.crouch = false;
+ UNSET_DUCKED(this);
this.view_ofs = STAT(PL_VIEW_OFS, this);
setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
this.spawnorigin = spot.origin;
}
}
+ void calculate_player_respawn_time(entity this)
+ {
+ if(MUTATOR_CALLHOOK(CalculateRespawnTime, this))
+ return;
+
+ float gametype_setting_tmp;
+ float sdelay_max = GAMETYPE_DEFAULTED_SETTING(respawn_delay_max);
+ float sdelay_small = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small);
+ float sdelay_large = GAMETYPE_DEFAULTED_SETTING(respawn_delay_large);
+ float sdelay_small_count = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small_count);
+ float sdelay_large_count = GAMETYPE_DEFAULTED_SETTING(respawn_delay_large_count);
+ float waves = GAMETYPE_DEFAULTED_SETTING(respawn_waves);
+
+ float pcount = 1; // Include myself whether or not team is already set right and I'm a "player".
+ if (teamplay)
+ {
+ FOREACH_CLIENT(IS_PLAYER(it) && it != this, {
+ if(it.team == this.team)
+ ++pcount;
+ });
+ if (sdelay_small_count == 0)
+ sdelay_small_count = 1;
+ if (sdelay_large_count == 0)
+ sdelay_large_count = 1;
+ }
+ else
+ {
+ FOREACH_CLIENT(IS_PLAYER(it) && it != this, {
+ ++pcount;
+ });
+ if (sdelay_small_count == 0)
+ {
+ if (IS_INDEPENDENT_PLAYER(this))
+ {
+ // Players play independently. No point in requiring enemies.
+ sdelay_small_count = 1;
+ }
+ else
+ {
+ // Players play AGAINST each other. Enemies required.
+ sdelay_small_count = 2;
+ }
+ }
+ if (sdelay_large_count == 0)
+ {
+ if (IS_INDEPENDENT_PLAYER(this))
+ {
+ // Players play independently. No point in requiring enemies.
+ sdelay_large_count = 1;
+ }
+ else
+ {
+ // Players play AGAINST each other. Enemies required.
+ sdelay_large_count = 2;
+ }
+ }
+ }
+
+ float sdelay;
+
+ if (pcount <= sdelay_small_count)
+ sdelay = sdelay_small;
+ else if (pcount >= sdelay_large_count)
+ sdelay = sdelay_large;
+ else // NOTE: this case implies sdelay_large_count > sdelay_small_count.
+ sdelay = sdelay_small + (sdelay_large - sdelay_small) * (pcount - sdelay_small_count) / (sdelay_large_count - sdelay_small_count);
+
+ if(waves)
+ this.respawn_time = ceil((time + sdelay) / waves) * waves;
+ else
+ this.respawn_time = time + sdelay;
+
+ if(sdelay < sdelay_max)
+ this.respawn_time_max = time + sdelay_max;
+ else
+ this.respawn_time_max = this.respawn_time;
+
+ if((sdelay + waves >= 5.0) && (this.respawn_time - time > 1.75))
+ this.respawn_countdown = 10; // first number to count down from is 10
+ else
+ this.respawn_countdown = -1; // do not count down
+
+ if(autocvar_g_forced_respawn)
+ this.respawn_flags = this.respawn_flags | RESPAWN_FORCE;
+ }
// LordHavoc: this hack will be removed when proper _pants/_shirt layers are
// added to the model skins
this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
}
- secrets_setstatus(this);
monsters_setstatus(this);
return true;
#include <server/defs.qh>
#include <server/miscfunctions.qh>
- #include <server/items.qh>
+ #include <server/items/items.qh>
+ #include <server/items/spawning.qh>
#include <server/resources.qh>
#include <common/gamemodes/_mod.qh>
- #include <common/t_items.qh>
#include <common/gamemodes/gamemode/ctf/sv_ctf.qh>
#include <common/mapobjects/triggers.qh>
#include <common/mapobjects/trigger/counter.qh>
#include <common/notifications/all.qh>
#include <common/weapons/_all.qh>
-//***********************
-//QUAKE 3 ENTITIES - So people can play quake3 maps with the xonotic weapons
-//***********************
-
-// NOTE: for best experience, you need to swap MGs with SGs in the map or it won't have a MG
-
-// SG -> SG
-SPAWNFUNC_ITEM(ammo_shells, ITEM_Shells)
-
-// MG -> MG
-SPAWNFUNC_ITEM(ammo_bullets, ITEM_Bullets)
+/***********************
+ * QUAKE 3 ENTITIES - So people can play quake3 maps with the xonotic weapons
+ ***********************
+
+ * Map entities NOT handled in this file:
+ holdable_invulnerability Q3TA currently unsupported
+ holdable_kamikaze Q3TA currently unsupported
+ item_ammoregen Q3TA handled by buffs mutator
+ item_doubler Q3TA handled by buffs mutator
+ item_guard Q3TA handled by buffs mutator
+ item_scout Q3TA handled by buffs mutator
+ item_armor_jacket CPMA handled in quake2.qc
+ item_flight Q3A handled by buffs mutator
+ item_haste Q3A handled by buffs mutator
+ item_health Q3A handled in quake.qc
+ item_health_large Q3A handled in items.qc
+ item_health_small Q3A handled in health.qh
+ item_health_mega Q3A handled in health.qh
+ item_invis Q3A handled by buffs mutator
+ item_quad Q3A handled in items.qc
+ item_regen Q3A handled by buffs mutator
+ CTF spawnfuncs handled in sv_ctf.qc
+
+ NOTE: for best experience, you need to swap MGs with SGs in the map or it won't have a MG
+*/
+
+// SG -> MG || SG
+SPAWNFUNC_ITEM_COND(ammo_shells, (q3compat & BIT(0)), ITEM_Bullets, ITEM_Shells)
+SPAWNFUNC_WEAPON_COND(weapon_shotgun, (q3compat & BIT(0)), WEP_MACHINEGUN, WEP_SHOTGUN)
+
+// MG -> SG || MG
+SPAWNFUNC_ITEM_COND(ammo_bullets, (q3compat & BIT(0)), ITEM_Shells, ITEM_Bullets)
// GL -> Mortar
SPAWNFUNC_ITEM(ammo_grenades, ITEM_Rockets)
-// Mines -> Rockets
+// Team Arena Proximity Launcher -> Mine Layer
SPAWNFUNC_WEAPON(weapon_prox_launcher, WEP_MINE_LAYER)
SPAWNFUNC_ITEM(ammo_mines, ITEM_Rockets)
-// LG -> Lightning
+// Team Arena Chaingun -> HLAC
+SPAWNFUNC_WEAPON(weapon_chaingun, WEP_HLAC)
+SPAWNFUNC_ITEM(ammo_belt, ITEM_Cells)
+
+// Team Arena Nailgun -> Crylink || Quake Nailgun -> Electro
+SPAWNFUNC_WEAPON_COND(weapon_nailgun, cvar("sv_mapformat_is_quake3"), WEP_CRYLINK, WEP_ELECTRO)
+SPAWNFUNC_ITEM(ammo_nails, ITEM_Cells)
+
+// LG -> Electro
SPAWNFUNC_WEAPON(weapon_lightning, WEP_ELECTRO)
SPAWNFUNC_ITEM(ammo_lightning, ITEM_Cells)
SPAWNFUNC_WEAPON(weapon_railgun, WEP_VORTEX)
SPAWNFUNC_ITEM(ammo_slugs, ITEM_Cells)
-// BFG -> Crylink
-SPAWNFUNC_WEAPON(weapon_bfg, WEP_CRYLINK)
-SPAWNFUNC_ITEM(ammo_bfg, ITEM_Cells)
+// BFG -> Crylink || Fireball
+SPAWNFUNC_WEAPON_COND(weapon_bfg, cvar_string("g_mod_balance") == "XDF", WEP_CRYLINK, WEP_FIREBALL)
+SPAWNFUNC_ITEM_COND(ammo_bfg, cvar_string("g_mod_balance") == "XDF", ITEM_Cells, ITEM_Rockets)
// grappling hook -> hook
SPAWNFUNC_WEAPON(weapon_grapplinghook, WEP_HOOK)
SPAWNFUNC_ITEM(item_armor_body, ITEM_ArmorMega)
SPAWNFUNC_ITEM(item_armor_combat, ITEM_ArmorBig)
SPAWNFUNC_ITEM(item_armor_shard, ITEM_ArmorSmall)
+SPAWNFUNC_ITEM(item_armor_green, ITEM_ArmorMedium) // CCTF
+
+// Battle Suit
SPAWNFUNC_ITEM(item_enviro, ITEM_Shield)
// medkit -> armor (we have no holdables)
this.use = fragsfilter_use;
}
-//spawnfunc(item_flight) /* handled by buffs mutator */
-//spawnfunc(item_doubler) /* handled by buffs mutator */
-//spawnfunc(item_haste) /* handled by buffs mutator */
-//spawnfunc(item_health) /* handled in t_quake.qc */
-//spawnfunc(item_health_large) /* handled in items.qc */
-//spawnfunc(item_health_small) /* handled in items.qc */
-//spawnfunc(item_health_mega) /* handled in items.qc */
-//spawnfunc(item_invis) /* handled by buffs mutator */
-//spawnfunc(item_regen) /* handled by buffs mutator */
-
-// CTF spawnfuncs handled in mutators/gamemode_ctf.qc now
-
-.float notteam;
-.float notsingle;
-.float notfree;
-.float notq3a;
-.float notta;
+.bool notteam;
+.bool notsingle;
+.bool notfree;
+.bool notta;
+.bool notvq3;
+.bool notcpm;
.string gametype;
bool DoesQ3ARemoveThisEntity(entity this)
{
// Q3 style filters (DO NOT USE, THIS IS COMPAT ONLY)
- if(this.notq3a)
- if(!teamplay || g_tdm || g_ctf)
+ // DeFRaG mappers use "notcpm" or "notvq3" to disable an entity in CPM or VQ3 physics
+ // Xonotic is usually played with a CPM-based physics so we default to CPM mode
+ if(cvar_string("g_mod_physics") == "Q3")
+ {
+ if(this.notvq3)
return true;
+ }
+ else if(this.notcpm)
+ return true;
+ // Q3 mappers use "notq3a" or "notta" to disable an entity in Q3A or Q3TA
+ // Xonotic has ~equivalent features to Team Arena
if(this.notta)
- if (!(!teamplay || g_tdm || g_ctf))
- return true;
+ return true;
if(this.notsingle)
if(maxclients == 1)
if(this.gametype)
{
string gametypename;
- // static char *gametypeNames[] = {"ffa", "tournament", "single", "team", "ctf", "oneflag", "obelisk", "harvester", "teamtournament"}
+ // From ioq3 g_spawn.c: static char *gametypeNames[] = {"ffa", "tournament", "single", "team", "ctf", "oneflag", "obelisk", "harvester"};
gametypename = "ffa";
if(teamplay)
gametypename = "team";
gametypename = "tournament";
if(maxclients == 1)
gametypename = "single";
- // we do not have the other types (obelisk, harvester, teamtournament)
+ // we do not have the other types (obelisk, harvester)
if(strstrofs(this.gametype, gametypename, 0) < 0)
return true;
}
MapInfo_Enumerate();
MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1);
- if(fexists(strcat("scripts/", mapname, ".arena")))
- cvar_settemp("sv_q3acompat_machineshotgunswap", "1");
-
- if(fexists(strcat("scripts/", mapname, ".defi")))
- cvar_settemp("sv_q3defragcompat", "1");
+ q3compat = BITSET(q3compat, BIT(0), fexists(strcat("scripts/", mapname, ".arena")));
+ q3compat = BITSET(q3compat, BIT(1), fexists(strcat("scripts/", mapname, ".defi")));
if(whichpack(strcat("maps/", mapname, ".cfg")) != "")
{
Nagger_Init();
- next_pingtime = time + 5;
-
// set up information replies for clients and server to use
maplist_reply = strzone(getmaplist());
lsmaps_reply = strzone(getlsmaps());
--- /dev/null
-// FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
-SPAWNFUNC_ITEM(item_armor1, ITEM_ArmorSmall)
+ #include "spawning.qh"
+
+ /// \file
+ /// \brief Source file that contains implementation of the functions related to
+ /// creation of game items.
+ /// \copyright GNU GPLv2 or any later version.
+
+ #include <server/mutators/_mod.qh>
+ #include <server/weapons/spawning.qh>
+ #include <common/weapons/all.qh>
+ #include <common/mapobjects/subs.qh>
+
+ .bool m_isloot; ///< Holds whether item is loot.
+ /// \brief Holds whether strength, shield or superweapon timers expire while
+ /// this item is on the ground.
+ .bool m_isexpiring;
+
+ entity Item_FindDefinition(string class_name)
+ {
+ FOREACH(Items, it.m_canonical_spawnfunc == class_name,
+ {
+ return it;
+ });
+ FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
+ {
+ return it.m_pickup;
+ });
+ return NULL;
+ }
+
+ bool Item_IsAllowed(string class_name)
+ {
+ entity definition = Item_FindDefinition(class_name);
+ if (definition == NULL)
+ {
+ return false;
+ }
+ return Item_IsDefinitionAllowed(definition);
+ }
+
+ bool Item_IsDefinitionAllowed(entity definition)
+ {
+ return !MUTATOR_CALLHOOK(FilterItemDefinition, definition);
+ }
+
+ entity Item_Create(string class_name, vector position, bool no_align)
+ {
+ entity item = spawn();
+ item.classname = class_name;
+ item.spawnfunc_checked = true;
+ setorigin(item, position);
+ item.noalign = no_align;
+ Item_Initialize(item, class_name);
+ if (wasfreed(item))
+ {
+ return NULL;
+ }
+ return item;
+ }
+
+ void Item_Initialize(entity item, string class_name)
+ {
+ FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
+ {
+ weapon_defaultspawnfunc(item, it);
+ return;
+ });
+ FOREACH(Items, it.m_canonical_spawnfunc == class_name,
+ {
+ StartItem(item, it);
+ return;
+ });
+ LOG_FATALF("Item_Initialize: Invalid classname: %s", class_name);
+ }
+
+ entity Item_CreateLoot(string class_name, vector position, vector vel,
+ float time_to_live)
+ {
+ entity item = spawn();
+ if (!Item_InitializeLoot(item, class_name, position, vel, time_to_live))
+ {
+ return NULL;
+ }
+ return item;
+ }
+
+ bool Item_InitializeLoot(entity item, string class_name, vector position,
+ vector vel, float time_to_live)
+ {
+ item.classname = class_name;
+ Item_SetLoot(item, true);
+ item.noalign = true;
+ setorigin(item, position);
+ item.pickup_anyway = true;
+ item.spawnfunc_checked = true;
+ Item_Initialize(item, class_name);
+ if (wasfreed(item))
+ {
+ return false;
+ }
+ item.gravity = 1;
+ item.velocity = vel;
+ SUB_SetFade(item, time + time_to_live, 1);
+ return true;
+ }
+
+ bool Item_IsLoot(entity item)
+ {
+ return item.m_isloot || item.classname == "droppedweapon";
+ }
+
+ void Item_SetLoot(entity item, bool loot)
+ {
+ item.m_isloot = loot;
+ }
+
+ bool Item_ShouldKeepPosition(entity item)
+ {
+ return item.noalign || (item.spawnflags & 1);
+ }
+
+ bool Item_IsExpiring(entity item)
+ {
+ return item.m_isexpiring;
+ }
+
+ void Item_SetExpiring(entity item, bool expiring)
+ {
+ item.m_isexpiring = expiring;
+ }
+
+ // Compatibility spawn functions
+
++SPAWNFUNC_ITEM_COND(item_armor1, cvar("sv_mapformat_is_quake3"), ITEM_ArmorSmall, ITEM_ArmorMedium)
+
+ SPAWNFUNC_ITEM(item_armor25, ITEM_ArmorMega)
+
+ SPAWNFUNC_ITEM(item_armor_large, ITEM_ArmorMega)
+
+ SPAWNFUNC_ITEM(item_health1, ITEM_HealthSmall)
+
+ SPAWNFUNC_ITEM(item_health25, ITEM_HealthMedium)
+
+ SPAWNFUNC_ITEM(item_health_large, ITEM_HealthBig)
+
+ SPAWNFUNC_ITEM(item_health100, ITEM_HealthMega)
+
+ SPAWNFUNC_ITEM(item_quad, ITEM_Strength)
set sv_gibhealth 100 "Minus health a dead body must have in order to get gibbed"
// use default physics
+ sv_playerphysicsqc 1
set sv_friction_on_land 0 "movement friction applied for half a second upon landing on the ground"
set sv_friction_slick 0.5 "movement friction while on slick surfaces"
sv_gameplayfix_gravityunaffectedbyticrate 1
sv_gameplayfix_nogravityonground 1
-set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping machinegun and shotgun (for Q3A map compatibility in mapinfo files)"
-set sv_q3defragcompat 0 "toggle for some compatibility hacks (for Q3DF map compatibility)"
+set sv_q3compat_changehitbox 0 "use Q3 player hitbox dimensions and camera height on Q3 maps (maps with an entry in a .arena or .defi file)
set g_movement_highspeed 1 "multiplier scale for movement speed (applies to sv_maxspeed and sv_maxairspeed, also applies to air acceleration when g_movement_highspeed_q3_compat is set to 0)"
set g_movement_highspeed_q3_compat 0 "apply speed modifiers to air movement in a more Q3-compatible way (only apply speed buffs and g_movement_highspeed to max air speed, not to acceleration)"