X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fcompat%2Fquake3.qc;h=264daeca1a9306277cd2b6f333be4039fd12c55a;hp=134956e7d8fc528c328e1ee68f21a908139f6bac;hb=dc02e4d78fb0e67b47a0c1e150b4c18c0711b8bf;hpb=19c09c8cfc6a4cb71c07e63bf739b7720ec6b0a0 diff --git a/qcsrc/server/compat/quake3.qc b/qcsrc/server/compat/quake3.qc index 134956e7d..264daeca1 100644 --- a/qcsrc/server/compat/quake3.qc +++ b/qcsrc/server/compat/quake3.qc @@ -1,63 +1,102 @@ #include "quake3.qh" -#include +#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 -//*********************** +/*********************** + * QUAKE 3 ENTITIES - So people can play quake3 maps with the xonotic weapons + *********************** + + * Map entities NOT handled in this file: + holdable_invulnerability Q3TA buffs mutator + holdable_kamikaze Q3TA buffs mutator + holdable_teleporter Q3A buffs mutator + item_ammoregen Q3TA buffs mutator + item_doubler Q3TA buffs mutator + item_guard Q3TA buffs mutator + item_scout Q3TA buffs mutator + item_armor_jacket CPMA quake2.qc + item_flight Q3A buffs mutator + item_haste Q3A buffs mutator + item_health Q3A quake.qc + item_health_large Q3A items.qc + item_health_small Q3A health.qh + item_health_mega Q3A health.qh + item_invis Q3A buffs mutator + item_quad Q3A items.qc + item_regen Q3A buffs mutator + weapon_machinegun Q3A machinegun.qh + weapon_grenadelauncher Q3A mortar.qh + weapon_rocketlauncher Q3A devastator.qh + 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_Q3_COND(weapon_shotgun, ammo_shells, (q3compat & Q3COMPAT_ARENA), WEP_MACHINEGUN, WEP_SHOTGUN) + +// MG -> SG || MG +// Technically we should replace weapon_machinegun with WEP_SHOTGUN if Q3COMPAT_ARENA, but it almost never occurs on Q3 maps +SPAWNFUNC_Q3AMMO_COND(ammo_bullets, (q3compat & Q3COMPAT_ARENA), WEP_SHOTGUN, WEP_MACHINEGUN) -// NOTE: for best experience, you need to swap MGs with SGs in the map or it won't have a MG +// GL -> Mortar +SPAWNFUNC_Q3AMMO(ammo_grenades, WEP_MORTAR) -// SG -> SG -SPAWNFUNC_ITEM(ammo_shells, ITEM_Shells) +// 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_Q3(weapon_prox_launcher, ammo_mines, WEP_MORTAR) -// MG -> MG -SPAWNFUNC_ITEM(ammo_bullets, ITEM_Bullets) +// Team Arena Chaingun -> HLAC +SPAWNFUNC_Q3(weapon_chaingun, ammo_belt, WEP_HLAC) -// GL -> Mortar -SPAWNFUNC_ITEM(ammo_grenades, ITEM_Rockets) +// Quake Live Heavy Machine Gun -> HLAC +SPAWNFUNC_Q3(weapon_hmg, ammo_hmg, WEP_HLAC) -// Mines -> Rockets -SPAWNFUNC_WEAPON(weapon_prox_launcher, WEP_MINE_LAYER) -SPAWNFUNC_ITEM(ammo_mines, ITEM_Rockets) +// Team Arena Nailgun -> Crylink || Quake Nailgun -> Electro +SPAWNFUNC_Q3_COND(weapon_nailgun, ammo_nails, cvar("sv_mapformat_is_quake3"), WEP_CRYLINK, WEP_ELECTRO) -// LG -> Lightning -SPAWNFUNC_WEAPON(weapon_lightning, WEP_ELECTRO) -SPAWNFUNC_ITEM(ammo_lightning, ITEM_Cells) +// LG -> Electro +SPAWNFUNC_Q3(weapon_lightning, ammo_lightning, WEP_ELECTRO) // Plasma -> Hagar -SPAWNFUNC_WEAPON(weapon_plasmagun, WEP_HAGAR) -SPAWNFUNC_ITEM(ammo_cells, ITEM_Rockets) +SPAWNFUNC_Q3(weapon_plasmagun, ammo_cells, WEP_HAGAR) // Rail -> Vortex -SPAWNFUNC_WEAPON(weapon_railgun, WEP_VORTEX) -SPAWNFUNC_ITEM(ammo_slugs, ITEM_Cells) +SPAWNFUNC_Q3(weapon_railgun, ammo_slugs, WEP_VORTEX) -// BFG -> Crylink -SPAWNFUNC_WEAPON(weapon_bfg, WEP_CRYLINK) -SPAWNFUNC_ITEM(ammo_bfg, ITEM_Cells) +// BFG -> Crylink || Fireball +SPAWNFUNC_Q3_COND(weapon_bfg, ammo_bfg, cvar_string("g_mod_balance") == "XDF", WEP_CRYLINK, WEP_FIREBALL) + // FIXME: WEP_FIREBALL has no ammo_type field so ammo_bfg is deleted by spawnfunc_body // grappling hook -> hook SPAWNFUNC_WEAPON(weapon_grapplinghook, WEP_HOOK) // RL -> RL -SPAWNFUNC_ITEM(ammo_rockets, ITEM_Rockets) +SPAWNFUNC_Q3AMMO(ammo_rockets, WEP_DEVASTATOR) + +// Gauntlet -> Tuba +SPAWNFUNC_ITEM(weapon_gauntlet, WEP_TUBA) // Armor 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) @@ -156,52 +195,42 @@ 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, { - if (it.classname == "weapon_devastator") { - SetResourceExplicit(this, RES_ROCKETS, GetResource(this, RES_ROCKETS) + it.count * WEP_CVAR_PRI(devastator, ammo)); // WEAPONTODO - this.netname = cons(this.netname, "devastator"); - } - else if (it.classname == "weapon_vortex") { - SetResourceExplicit(this, RES_CELLS, GetResource(this, RES_CELLS) + it.count * WEP_CVAR_PRI(vortex, ammo)); // WEAPONTODO - this.netname = cons(this.netname, "vortex"); - } - else if (it.classname == "weapon_electro") { - SetResourceExplicit(this, RES_CELLS, GetResource(this, RES_CELLS) + it.count * WEP_CVAR_PRI(electro, ammo)); // WEAPONTODO - this.netname = cons(this.netname, "electro"); - } - else if (it.classname == "weapon_hagar") { - SetResourceExplicit(this, RES_ROCKETS, GetResource(this, RES_ROCKETS) + it.count * WEP_CVAR_PRI(hagar, ammo)); // WEAPONTODO - this.netname = cons(this.netname, "hagar"); - } - else if (it.classname == "weapon_crylink") { - SetResourceExplicit(this, RES_CELLS, GetResource(this, RES_CELLS) + it.count * WEP_CVAR_PRI(crylink, ammo)); // WEAPONTODO - this.netname = cons(this.netname, "crylink"); - } - else if (it.classname == "weapon_mortar") { - 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 == "item_armor_mega") - SetResourceExplicit(this, RES_ARMOR, 100); - else if (it.classname == "item_health_mega") - SetResourceExplicit(this, RES_HEALTH, 200); - else if (it.classname == "item_buff") { + if (it.classname == "item_buff") + { entity buff = buff_FirstFromFlags(STAT(BUFFS, it)); this.netname = cons(this.netname, buff.netname); - STAT(BUFF_TIME, this) = it.count; + STAT(BUFF_TIME, this) += it.count; + } + else + { + if (it.ammo_rockets) + this.ammo_rockets += it.ammo_rockets; + else if (it.ammo_cells) + this.ammo_cells += it.ammo_cells; + else if (it.ammo_shells) + this.ammo_shells += it.ammo_shells; + else if (it.ammo_nails) + this.ammo_nails += it.ammo_nails; + else if (it.invincible_finished) + this.invincible_finished += it.invincible_finished; + else if (it.strength_finished) + this.strength_finished += it.strength_finished; + else if (it.health) + this.health += it.health; + else if (it.armorvalue) + this.armorvalue += it.armorvalue; + + this.netname = cons(this.netname, it.netname); } //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; @@ -245,35 +274,31 @@ spawnfunc(target_fragsFilter) 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) @@ -290,7 +315,7 @@ 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"; @@ -302,7 +327,7 @@ bool DoesQ3ARemoveThisEntity(entity this) 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; }