#include "ammo.qh"
-#ifdef SVQC
-
-METHOD(Shells, m_spawnfunc_hookreplace, GameItem(Shells this, entity e))
-{
- if (autocvar_sv_q3acompat_machineshotgunswap && !Item_IsLoot(e))
- {
- return ITEM_Bullets;
- }
- return this;
-}
-
-#endif
if (!this.lip)
this.lip = 4;
- if(this.wait == -1 && autocvar_sv_q3defragcompat)
- this.wait = 0.1; // compatibility for q3df: "instant" return
+ if(this.wait < 0 && q3compat)
+ this.wait = 0.1; // compatibility for q3: -1 = return immediately
if(this.noise != "")
precache_sound(this.noise);
}
else if (!this.speed)
{
- if (autocvar_sv_q3defragcompat)
+ if (q3compat)
this.speed = 400;
else
this.speed = 100;
if (toucher.triggerhurttime < time)
{
EXACTTRIGGER_TOUCH(this, toucher);
- toucher.triggerhurttime = time + ((autocvar_sv_q3defragcompat && !(this.spawnflags & HURT_SLOW)) ? 0.1 : 1);
+ toucher.triggerhurttime = time + ((q3compat && !(this.spawnflags & HURT_SLOW)) ? 0.1 : 1);
entity own;
own = this.enemy;
this.use = trigger_hurt_use;
this.enemy = world; // I hate you all
if (!this.dmg)
- this.dmg = ((autocvar_sv_q3defragcompat) ? 5 : 10000);
+ this.dmg = ((q3compat) ? 5 : 10000);
if (this.message == "")
this.message = "was in the wrong place";
if (this.message2 == "")
vector org = targ.origin;
#ifdef SVQC
- if(autocvar_sv_q3defragcompat)
+ if(q3compat)
#elif defined(CSQC)
if(STAT(Q3DEFRAGCOMPAT))
#endif
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;
{
switch(buffname)
{
- case "ammoregen": return "ammo";
- case "haste": case "scout": return "speed";
- case "guard": return "resistance";
- case "revival": case "regen": return "medic";
- case "invis": return "invisible";
- case "jumper": return "jump";
+ case "ammoregen": return "ammo"; // Q3TA ammoregen
+ case "haste": return "speed"; // Q3A haste
+ case "doubler": return "inferno"; // Q3TA doubler
+ case "scout": return "bash"; // Q3TA scout
+ case "guard": return "resistance"; // Q3TA guard
+ case "revival": case "regen": return "medic"; // WOP revival, Q3A regen
+ case "invis": return "invisible"; // Q3A invis
+ case "jumper": return "jump"; // WOP jumper
default: return buffname;
}
}
}
BUFF_SPAWNFUNCS(speed, BUFF_SPEED)
BUFF_SPAWNFUNC_Q3TA_COMPAT(haste, BUFF_SPEED)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(scout, BUFF_SPEED)
REGISTER_BUFF(MEDIC) {
this.m_name = _("Medic");
this.m_color = '1 0.39 0';
}
BUFF_SPAWNFUNCS(bash, BUFF_BASH)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(doubler, BUFF_BASH)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(scout, BUFF_BASH)
REGISTER_BUFF(VAMPIRE) {
this.m_name = _("Vampire");
this.m_color = '1 0.62 0';
}
BUFF_SPAWNFUNCS(inferno, BUFF_INFERNO)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(doubler, BUFF_INFERNO)
REGISTER_BUFF(SWAPPER) {
this.m_name = _("Swapper");
: 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
+ bool q3dfcompat = q3compat && 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;
#ifdef SVQC
#include <server/autocvars.qh>
#include <server/client.qh>
+#include <server/compat/quake3.qh>
#endif
// Full list of all stat constants, included in a single location for easy reference
#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(Q3DEFRAGCOMPAT, bool, q3compat)
#ifdef SVQC
#include "physics/movetypes/movetypes.qh"
REGISTER_NET_TEMP(TE_CSQC_SHOCKWAVEPARTICLE)
#ifdef SVQC
-// enable when shockwave replaces shotgun
-#if 0
-METHOD(Shockwave, m_spawnfunc_hookreplace, Weapon(Shockwave this, entity e))
-{
- //if(autocvar_sv_q3acompat_machineshockwaveswap) // WEAPONTODO
- if (autocvar_sv_q3acompat_machineshotgunswap && !Item_IsLoot(e))
- {
- return WEP_MACHINEGUN;
- }
- return this;
-}
-#endif
const float MAX_SHOCKWAVE_HITS = 10;
//#define DEBUG_SHOCKWAVE
// 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);
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);
-
+
if(lag && bullets > 0)
antilag_restore_all(actor);
ENDCLASS(Shotgun)
REGISTER_WEAPON(SHOTGUN, shotgun, NEW(Shotgun));
-SPAWNFUNC_WEAPON(weapon_shotgun, WEP_SHOTGUN)
string autocvar_sv_motd;
int autocvar_sv_name_maxlength = 64;
bool autocvar_sv_precacheplayermodels;
-bool autocvar_sv_q3acompat_machineshotgunswap;
bool autocvar_sv_servermodelsonly;
int autocvar_sv_spectate;
float autocvar_sv_spectator_speed_multiplier;
this.respawn_flags = 0;
this.respawn_time = 0;
STAT(RESPAWN_TIME, this) = 0;
- bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox;
+ bool q3dfcompat = q3compat && autocvar_sv_q3defragcompat_changehitbox;
this.scale = ((q3dfcompat) ? 0.9 : autocvar_sv_player_scale);
this.fade_time = 0;
this.pain_frame = 0;
//***********************
//QUAKE 1 ENTITIES - So people can play quake1 maps with the xonotic weapons
//***********************
-SPAWNFUNC_WEAPON(weapon_nailgun, WEP_ELECTRO)
+// see: quake3.qc for weapon_nailgun
SPAWNFUNC_WEAPON(weapon_supernailgun, WEP_HAGAR)
SPAWNFUNC_WEAPON(weapon_supershotgun, WEP_MACHINEGUN)
#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_string("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)
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 t_items.qc */
-//spawnfunc(item_health_small) /* handled in t_items.qc */
-//spawnfunc(item_health_mega) /* handled in t_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)
#pragma once
+int q3compat = 0;
bool DoesQ3ARemoveThisEntity(entity this);
.int fragsfilter_cnt;
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")));
+ LOG_INFO("CHECKED FOR: scripts/", mapname, ".arena and scripts/", mapname, ".defi, q3compat set to ", ftos(q3compat));
if(whichpack(strcat("maps/", mapname, ".cfg")) != "")
{
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 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)"