X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fcompat%2Fquake3.qc;h=a68cc8a339c987a3822617b78b5458e900164531;hb=1758e185f4fdf82f079c649f78d9e22770eacc50;hp=8205b81284d2811d618b38e6c8675aca3942482b;hpb=ca9f533b1a28ea7648da1df2c6548f11675d2bc1;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/compat/quake3.qc b/qcsrc/server/compat/quake3.qc index 8205b8128..a68cc8a33 100644 --- a/qcsrc/server/compat/quake3.qc +++ b/qcsrc/server/compat/quake3.qc @@ -1,36 +1,74 @@ #include "quake3.qh" -#include +#include +#include +#include #include -#include +#include +#include #include -#include +#include +#include #include #include #include #include #include -//*********************** -//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 & Q3COMPAT_ARENA), ITEM_Bullets, ITEM_Shells) +SPAWNFUNC_WEAPON_COND(weapon_shotgun, (q3compat & Q3COMPAT_ARENA), WEP_MACHINEGUN, WEP_SHOTGUN) + +// MG -> SG || MG +SPAWNFUNC_ITEM_COND(ammo_bullets, (q3compat & Q3COMPAT_ARENA), ITEM_Shells, ITEM_Bullets) // GL -> Mortar SPAWNFUNC_ITEM(ammo_grenades, ITEM_Rockets) -// Mines -> Rockets -SPAWNFUNC_WEAPON(weapon_prox_launcher, WEP_MINE_LAYER) +// Team Arena Proximity Launcher -> Mortar +// It's more accurate to spawn Mine Layer but players prefer Mortar, and weapon_grenadelauncher is usually disabled by "notta" and weapon_prox_launcher placed at the same origin +SPAWNFUNC_WEAPON(weapon_prox_launcher, WEP_MORTAR) SPAWNFUNC_ITEM(ammo_mines, ITEM_Rockets) -// LG -> Lightning +// Team Arena Chaingun -> HLAC +SPAWNFUNC_WEAPON(weapon_chaingun, WEP_HLAC) +SPAWNFUNC_ITEM(ammo_belt, ITEM_Cells) + +// Quake Live Heavy Machine Gun -> HLAC +SPAWNFUNC_WEAPON(weapon_hmg, WEP_HLAC) +SPAWNFUNC_ITEM(ammo_hmg, 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) @@ -42,9 +80,9 @@ SPAWNFUNC_ITEM(ammo_cells, ITEM_Rockets) 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) @@ -56,13 +94,13 @@ SPAWNFUNC_ITEM(ammo_rockets, ITEM_Rockets) 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) -SPAWNFUNC_ITEM(holdable_medkit, ITEM_ArmorMega) - -// doubler -> strength -SPAWNFUNC_ITEM(item_doubler, ITEM_Strength) +SPAWNFUNC_ITEM(holdable_medkit, ITEM_ArmorBig) .float wait; .float delay; @@ -103,24 +141,34 @@ void target_init_use(entity this, entity actor, entity trigger) if (!(this.spawnflags & 4)) { - SetResource(actor, RES_SHELLS, start_ammo_shells); - SetResource(actor, RES_BULLETS, start_ammo_nails); - SetResource(actor, RES_ROCKETS, start_ammo_rockets); - SetResource(actor, RES_CELLS, start_ammo_cells); - SetResource(actor, RES_PLASMA, start_ammo_plasma); - SetResource(actor, RES_FUEL, start_ammo_fuel); - - STAT(WEAPONS, actor) = start_weapons; - if (this.spawnflags & 32) + if(this.spawnflags & 32) // spawn with only melee { - // TODO + SetResource(actor, RES_SHELLS, 0); + SetResource(actor, RES_BULLETS, 0); + SetResource(actor, RES_ROCKETS, 0); + SetResource(actor, RES_CELLS, 0); + SetResource(actor, RES_PLASMA, 0); + SetResource(actor, RES_FUEL, 0); + + STAT(WEAPONS, actor) = WEPSET(SHOTGUN); + } + else + { + SetResource(actor, RES_SHELLS, start_ammo_shells); + SetResource(actor, RES_BULLETS, start_ammo_nails); + SetResource(actor, RES_ROCKETS, start_ammo_rockets); + SetResource(actor, RES_CELLS, start_ammo_cells); + SetResource(actor, RES_PLASMA, start_ammo_plasma); + SetResource(actor, RES_FUEL, start_ammo_fuel); + + STAT(WEAPONS, actor) = start_weapons; } } if (!(this.spawnflags & 8)) { - actor.strength_finished = 0; - actor.invincible_finished = 0; + STAT(STRENGTH_FINISHED, actor) = 0; + STAT(INVINCIBLE_FINISHED, actor) = 0; if(STAT(BUFFS, actor)) // TODO: make a dropbuffs function to handle this { int buffid = buff_FirstFromFlags(STAT(BUFFS, actor)).m_id; @@ -147,7 +195,7 @@ spawnfunc(target_init) InitializeEntity(this, target_init_verify, INITPRIO_FINDTARGET); } -// weapon give ent from defrag +// weapon give ent from Q3 void target_give_init(entity this) { IL_EACH(g_items, it.targetname == this.target, @@ -176,6 +224,14 @@ void target_give_init(entity this) SetResourceExplicit(this, RES_ROCKETS, GetResource(this, RES_ROCKETS) + it.count * WEP_CVAR_PRI(mortar, ammo)); // WEAPONTODO this.netname = cons(this.netname, "mortar"); } + else if (it.classname == "weapon_shotgun") { + SetResourceExplicit(this, RES_SHELLS, GetResource(this, RES_SHELLS) + it.count * WEP_CVAR_PRI(shotgun, ammo)); // WEAPONTODO + this.netname = cons(this.netname, "shotgun"); + } + else if (it.classname == "weapon_machinegun") { + SetResourceExplicit(this, RES_BULLETS, GetResource(this, RES_BULLETS) + it.count * WEP_CVAR(machinegun, burst_ammo)); // WEAPONTODO + this.netname = cons(this.netname, "machinegun"); + } else if (it.classname == "item_armor_mega") SetResourceExplicit(this, RES_ARMOR, 100); else if (it.classname == "item_health_mega") @@ -185,10 +241,18 @@ void target_give_init(entity this) this.netname = cons(this.netname, buff.netname); STAT(BUFF_TIME, this) = it.count; } + else if (it.classname == "item_shield") { + this.invincible_finished = it.count; + this.netname = cons(this.netname, "invincible"); + } + else if (it.classname == "item_strength") { + this.strength_finished = it.count; + this.netname = cons(this.netname, "strength"); + } //remove(it); // removing ents in init functions causes havoc, workaround: - setthink(it, SUB_Remove); - it.nextthink = time; + setthink(it, SUB_Remove); + it.nextthink = time; }); this.spawnflags = 2; this.spawnfunc_checked = true; @@ -232,34 +296,31 @@ spawnfunc(target_fragsFilter) this.use = fragsfilter_use; } -//spawnfunc(item_flight) /* 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) @@ -276,17 +337,19 @@ bool DoesQ3ARemoveThisEntity(entity this) 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"; if(g_ctf) gametypename = "ctf"; + if(g_ctf && ctf_oneflag) + gametypename = "oneflag"; if(g_duel) gametypename = "tournament"; if(maxclients == 1) gametypename = "single"; - // we do not have the other types (oneflag, obelisk, harvester, teamtournament) + // we do not have the other types (obelisk, harvester) if(strstrofs(this.gametype, gametypename, 0) < 0) return true; }