From 02b5d16c4530ee9c47df90430657a42e5a170c25 Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 13 Jul 2020 17:07:59 +1000 Subject: [PATCH] Move gametype registers into their own files, fallback now selects a supported gametype at random (with DM preferred, and CTF/TDM taking priority over others) --- qcsrc/client/hud/panel/infomessages.qc | 2 +- qcsrc/client/hud/panel/modicons.qc | 223 +------- qcsrc/client/hud/panel/physics.qc | 1 + qcsrc/client/hud/panel/racetimer.qc | 1 + qcsrc/client/hud/panel/radar.qc | 2 +- qcsrc/client/hud/panel/score.qc | 1 + qcsrc/client/hud/panel/scoreboard.qc | 1 + qcsrc/client/hud/panel/vote.qc | 1 + qcsrc/client/shownames.qc | 1 + .../gamemodes/gamemode/assault/_mod.inc | 1 + .../common/gamemodes/gamemode/assault/_mod.qh | 1 + .../gamemodes/gamemode/assault/assault.qc | 1 + .../gamemodes/gamemode/assault/assault.qh | 27 + .../gamemodes/gamemode/clanarena/_mod.inc | 4 + .../gamemodes/gamemode/clanarena/_mod.qh | 4 + .../gamemode/clanarena/cl_clanarena.qc | 79 +++ .../gamemode/clanarena/cl_clanarena.qh | 4 + .../gamemodes/gamemode/clanarena/clanarena.qc | 1 + .../gamemodes/gamemode/clanarena/clanarena.qh | 49 ++ qcsrc/common/gamemodes/gamemode/ctf/ctf.qh | 40 ++ qcsrc/common/gamemodes/gamemode/cts/_mod.inc | 1 + qcsrc/common/gamemodes/gamemode/cts/_mod.qh | 1 + qcsrc/common/gamemodes/gamemode/cts/cts.qc | 1 + qcsrc/common/gamemodes/gamemode/cts/cts.qh | 36 ++ .../gamemodes/gamemode/deathmatch/_mod.inc | 1 + .../gamemodes/gamemode/deathmatch/_mod.qh | 1 + .../gamemode/deathmatch/deathmatch.qc | 1 + .../gamemode/deathmatch/deathmatch.qh | 16 + .../gamemode/domination/cl_domination.qc | 5 + .../gamemode/domination/cl_domination.qh | 1 + .../gamemode/domination/domination.qh | 42 ++ qcsrc/common/gamemodes/gamemode/duel/_mod.inc | 1 + qcsrc/common/gamemodes/gamemode/duel/_mod.qh | 1 + qcsrc/common/gamemodes/gamemode/duel/duel.qc | 1 + qcsrc/common/gamemodes/gamemode/duel/duel.qh | 28 + .../gamemodes/gamemode/freezetag/_mod.inc | 4 + .../gamemodes/gamemode/freezetag/_mod.qh | 4 + .../gamemode/freezetag/cl_freezetag.qc | 6 + .../gamemode/freezetag/cl_freezetag.qh | 3 + .../gamemodes/gamemode/freezetag/freezetag.qc | 1 + .../gamemodes/gamemode/freezetag/freezetag.qh | 51 ++ .../gamemodes/gamemode/invasion/_mod.inc | 1 + .../gamemodes/gamemode/invasion/_mod.qh | 1 + .../gamemodes/gamemode/invasion/invasion.qc | 1 + .../gamemodes/gamemode/invasion/invasion.qh | 33 ++ .../gamemodes/gamemode/keepaway/keepaway.qh | 20 + .../gamemodes/gamemode/keyhunt/keyhunt.qh | 45 ++ qcsrc/common/gamemodes/gamemode/lms/_mod.inc | 1 + qcsrc/common/gamemodes/gamemode/lms/_mod.qh | 1 + qcsrc/common/gamemodes/gamemode/lms/lms.qc | 1 + qcsrc/common/gamemodes/gamemode/lms/lms.qh | 21 + .../gamemodes/gamemode/nexball/nexball.qh | 32 ++ .../gamemodes/gamemode/nexball/weapon.qh | 2 + .../gamemodes/gamemode/onslaught/onslaught.qh | 21 + qcsrc/common/gamemodes/gamemode/race/_mod.inc | 4 + qcsrc/common/gamemodes/gamemode/race/_mod.qh | 4 + .../common/gamemodes/gamemode/race/cl_race.qc | 147 +++++ .../common/gamemodes/gamemode/race/cl_race.qh | 3 + qcsrc/common/gamemodes/gamemode/race/race.qc | 1 + qcsrc/common/gamemodes/gamemode/race/race.qh | 46 ++ qcsrc/common/gamemodes/gamemode/tdm/_mod.inc | 1 + qcsrc/common/gamemodes/gamemode/tdm/_mod.qh | 1 + qcsrc/common/gamemodes/gamemode/tdm/tdm.qc | 1 + qcsrc/common/gamemodes/gamemode/tdm/tdm.qh | 52 ++ qcsrc/common/mapinfo.qc | 13 +- qcsrc/common/mapinfo.qh | 515 +----------------- qcsrc/common/mapobjects/teleporters.qc | 2 +- .../mutators/mutator/instagib/sv_instagib.qh | 1 + qcsrc/common/util.qc | 2 + qcsrc/menu/xonotic/dialog_singleplayer.qc | 2 +- qcsrc/menu/xonotic/gametypelist.qc | 1 + qcsrc/menu/xonotic/util.qc | 2 +- qcsrc/server/bot/default/waypoints.qc | 1 + qcsrc/server/command/getreplies.qc | 2 +- qcsrc/server/compat/quake3.qc | 1 + qcsrc/server/g_damage.qc | 1 + qcsrc/server/g_world.qc | 1 + qcsrc/server/impulse.qc | 2 + qcsrc/server/race.qc | 2 +- qcsrc/server/spawnpoints.qc | 2 +- 80 files changed, 908 insertions(+), 732 deletions(-) create mode 100644 qcsrc/common/gamemodes/gamemode/assault/assault.qc create mode 100644 qcsrc/common/gamemodes/gamemode/assault/assault.qh create mode 100644 qcsrc/common/gamemodes/gamemode/clanarena/cl_clanarena.qc create mode 100644 qcsrc/common/gamemodes/gamemode/clanarena/cl_clanarena.qh create mode 100644 qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qc create mode 100644 qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qh create mode 100644 qcsrc/common/gamemodes/gamemode/cts/cts.qc create mode 100644 qcsrc/common/gamemodes/gamemode/cts/cts.qh create mode 100644 qcsrc/common/gamemodes/gamemode/deathmatch/deathmatch.qc create mode 100644 qcsrc/common/gamemodes/gamemode/deathmatch/deathmatch.qh create mode 100644 qcsrc/common/gamemodes/gamemode/duel/duel.qc create mode 100644 qcsrc/common/gamemodes/gamemode/duel/duel.qh create mode 100644 qcsrc/common/gamemodes/gamemode/freezetag/cl_freezetag.qc create mode 100644 qcsrc/common/gamemodes/gamemode/freezetag/cl_freezetag.qh create mode 100644 qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qc create mode 100644 qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qh create mode 100644 qcsrc/common/gamemodes/gamemode/invasion/invasion.qc create mode 100644 qcsrc/common/gamemodes/gamemode/invasion/invasion.qh create mode 100644 qcsrc/common/gamemodes/gamemode/lms/lms.qc create mode 100644 qcsrc/common/gamemodes/gamemode/lms/lms.qh create mode 100644 qcsrc/common/gamemodes/gamemode/race/cl_race.qc create mode 100644 qcsrc/common/gamemodes/gamemode/race/cl_race.qh create mode 100644 qcsrc/common/gamemodes/gamemode/race/race.qc create mode 100644 qcsrc/common/gamemodes/gamemode/race/race.qh create mode 100644 qcsrc/common/gamemodes/gamemode/tdm/tdm.qc create mode 100644 qcsrc/common/gamemodes/gamemode/tdm/tdm.qh diff --git a/qcsrc/client/hud/panel/infomessages.qc b/qcsrc/client/hud/panel/infomessages.qc index 363465dfb7..627fd67efb 100644 --- a/qcsrc/client/hud/panel/infomessages.qc +++ b/qcsrc/client/hud/panel/infomessages.qc @@ -4,7 +4,7 @@ #include #include -#include +#include // Info messages (#14) diff --git a/qcsrc/client/hud/panel/modicons.qc b/qcsrc/client/hud/panel/modicons.qc index 0a8b8cf5ed..17ea987bf6 100644 --- a/qcsrc/client/hud/panel/modicons.qc +++ b/qcsrc/client/hud/panel/modicons.qc @@ -6,234 +6,15 @@ #include #include #include +#include // Mod icons (#10) void HUD_ModIcons_Export(int fh) { // allow saving cvars that aesthetically change the panel into hud skin files - HUD_Write_Cvar("hud_panel_modicons_ca_layout"); - HUD_Write_Cvar("hud_panel_modicons_dom_layout"); - HUD_Write_Cvar("hud_panel_modicons_freezetag_layout"); -} - -void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i) -{ - TC(int, layout); TC(int, i); - int stat = -1; - string pic = ""; - vector color = '0 0 0'; - switch(i) - { - case 0: stat = STAT(REDALIVE); pic = "player_red"; color = '1 0 0'; break; - case 1: stat = STAT(BLUEALIVE); pic = "player_blue"; color = '0 0 1'; break; - case 2: stat = STAT(YELLOWALIVE); pic = "player_yellow"; color = '1 1 0'; break; - default: - case 3: stat = STAT(PINKALIVE); pic = "player_pink"; color = '1 0 1'; break; - } - - if(mySize.x/mySize.y > aspect_ratio) - { - i = aspect_ratio * mySize.y; - myPos.x = myPos.x + (mySize.x - i) / 2; - mySize.x = i; - } - else - { - i = 1/aspect_ratio * mySize.x; - myPos.y = myPos.y + (mySize.y - i) / 2; - mySize.y = i; - } - - if(layout) - { - drawpic_aspect_skin(myPos, pic, vec2(0.5 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring_aspect(myPos + eX * 0.5 * mySize.x, ftos(stat), vec2(0.5 * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL); - } - else - drawstring_aspect(myPos, ftos(stat), mySize, color, panel_fg_alpha, DRAWFLAG_NORMAL); -} - -// Clan Arena and Freeze Tag HUD modicons -void HUD_Mod_CA(vector myPos, vector mySize) -{ - mod_active = 1; // required in each mod function that always shows something - - int layout; - if(ISGAMETYPE(CA)) - layout = autocvar_hud_panel_modicons_ca_layout; - else //if(ISGAMETYPE(FREEZETAG)) - layout = autocvar_hud_panel_modicons_freezetag_layout; - int rows, columns; - float aspect_ratio; - aspect_ratio = (layout) ? 2 : 1; - rows = HUD_GetRowCount(team_count, mySize, aspect_ratio); - columns = ceil(team_count/rows); - - int i; - float row = 0, column = 0; - vector pos = '0 0 0', itemSize; - itemSize = vec2(mySize.x / columns, mySize.y / rows); - for(i=0; i= rows) - { - row = 0; - ++column; - } - } -} - -// Race/CTS HUD mod icons -float crecordtime_prev; // last remembered crecordtime -float crecordtime_change_time; // time when crecordtime last changed -float srecordtime_prev; // last remembered srecordtime -float srecordtime_change_time; // time when srecordtime last changed - -float race_status_time; -int race_status_prev; -string race_status_name_prev; - -// Check if the given name already exist in race rankings? In that case, where? (otherwise return 0) -int race_CheckName(string net_name) -{ - int rank = 0; - string zoned_name = strzone(strdecolorize(entcs_GetName(player_localnum))); - for (int i = RANKINGS_CNT - 1; i >= 0; --i) - if (strdecolorize(grecordholder[i]) == zoned_name) - { - rank = i + 1; - break; - } - strfree(zoned_name); - return rank; -} -void race_showTime(string text, vector pos, vector timeText_ofs, float theTime, vector textSize, float f) -{ - drawstring_aspect(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring_aspect(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); - if (f < 1) { - drawstring_aspect_expanding(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f); - drawstring_aspect_expanding(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f); - } -} - -void HUD_Mod_Race(vector pos, vector mySize) -{ - entity me = playerslots[player_localnum]; - float score = me.(scores(ps_primary)); - - if(!(scores_flags(ps_primary) & SFL_TIME) || teamplay) // race/cts record display on HUD - { - mod_active = 0; // hide it in this case! - return; // no records in the actual race - } - - mod_active = 1; - - // clientside personal record - string rr; - if(ISGAMETYPE(CTS)) - rr = CTS_RECORD; - else - rr = RACE_RECORD; - float t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time"))); - - if(score && (score < t || !t)) { - db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score)); - if(autocvar_cl_autodemo_delete_keeprecords) - { - float f = autocvar_cl_autodemo_delete; - f &= ~1; - cvar_set("cl_autodemo_delete", ftos(f)); // don't delete demo with new record! - } - } - - if(t != crecordtime_prev) { - crecordtime_prev = t; - crecordtime_change_time = time; - } - - vector textPos, medalPos; - float squareSize; - if(mySize.x > mySize.y) { - // text on left side - squareSize = min(mySize.y, mySize.x/2); - vector ofs = vec2(0.5 * max(0, mySize.x/2 - squareSize), 0.5 * (mySize.y - squareSize)); - textPos = pos + ofs; - ofs.x += 0.5 * mySize.x; - medalPos = pos + ofs; - } else { - // text on top - squareSize = min(mySize.x, mySize.y/2); - vector ofs = vec2(0.5 * (mySize.x - squareSize), 0.5 * max(0, mySize.y/2 - squareSize)); - textPos = pos + ofs; - ofs.y += 0.5 * mySize.y; - medalPos = pos + ofs; - } - vector textSize = vec2(squareSize, 0.25 * squareSize); - - race_showTime(_("Personal best"), textPos, eY * 0.25 * squareSize, t, textSize, time - crecordtime_change_time); - - // server record - t = race_server_record; - if(t != srecordtime_prev) { - srecordtime_prev = t; - srecordtime_change_time = time; - } - - textPos += eY * 0.5 * squareSize; - race_showTime(_("Server best"), textPos, eY * 0.25 * squareSize, t, textSize, time - srecordtime_change_time); - - if (race_status != race_status_prev || race_status_name != race_status_name_prev) { - race_status_time = time + 5; - race_status_prev = race_status; - strcpy(race_status_name_prev, race_status_name); - } - - // race "awards" - float a = bound(0, race_status_time - time, 1); - string s = textShortenToWidth(ColorTranslateRGB(race_status_name), squareSize, '1 1 0' * 0.1 * squareSize, stringwidth_colors); - - float rank = 0; - if(race_status > 0) - rank = race_CheckName(race_status_name); - string rankname = count_ordinal(rank); - vector namepos = medalPos + '0 0.8 0' * squareSize; - vector rankpos = medalPos + '0 0.15 0' * squareSize; - - if(race_status == 0) - drawpic_aspect_skin(medalPos, "race_newfail", '1 1 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); - else if(race_status == 1) { - drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newtime", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); - drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL); - drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); - } else if(race_status == 2) { - if(strdecolorize(race_status_name) == strdecolorize(entcs_GetName(player_localnum)) || !race_myrank || race_myrank < rank) - drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankgreen", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); - else - drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankyellow", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); - drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL); - drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); - } else if(race_status == 3) { - drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrecordserver", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); - drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL); - drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); - } - - if (race_status_time - time <= 0) { - race_status_prev = -1; - race_status = -1; - strfree(race_status_name); - strfree(race_status_name_prev); - } + FOREACH(Gametypes, it.m_modicons_export, it.m_modicons_export(fh)); } void HUD_ModIcons_SetFunc() diff --git a/qcsrc/client/hud/panel/physics.qc b/qcsrc/client/hud/panel/physics.qc index a451f924b0..e49ea3a48c 100644 --- a/qcsrc/client/hud/panel/physics.qc +++ b/qcsrc/client/hud/panel/physics.qc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include diff --git a/qcsrc/client/hud/panel/racetimer.qc b/qcsrc/client/hud/panel/racetimer.qc index cd0b26e0bd..c82d764022 100644 --- a/qcsrc/client/hud/panel/racetimer.qc +++ b/qcsrc/client/hud/panel/racetimer.qc @@ -3,6 +3,7 @@ #include #include #include +#include #include // Race timer (#8) diff --git a/qcsrc/client/hud/panel/radar.qc b/qcsrc/client/hud/panel/radar.qc index e31aa01e91..14cdb4f68a 100644 --- a/qcsrc/client/hud/panel/radar.qc +++ b/qcsrc/client/hud/panel/radar.qc @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/qcsrc/client/hud/panel/score.qc b/qcsrc/client/hud/panel/score.qc index 10aec79ff6..70a47a8120 100644 --- a/qcsrc/client/hud/panel/score.qc +++ b/qcsrc/client/hud/panel/score.qc @@ -5,6 +5,7 @@ #include #include "scoreboard.qh" #include +#include #include #include diff --git a/qcsrc/client/hud/panel/scoreboard.qc b/qcsrc/client/hud/panel/scoreboard.qc index 120feeafa0..9d2b950d65 100644 --- a/qcsrc/client/hud/panel/scoreboard.qc +++ b/qcsrc/client/hud/panel/scoreboard.qc @@ -7,6 +7,7 @@ #include "quickmenu.qh" #include #include +#include #include #include #include diff --git a/qcsrc/client/hud/panel/vote.qc b/qcsrc/client/hud/panel/vote.qc index 4aab1b93bb..9783ff1257 100644 --- a/qcsrc/client/hud/panel/vote.qc +++ b/qcsrc/client/hud/panel/vote.qc @@ -2,6 +2,7 @@ #include #include +#include #include #include diff --git a/qcsrc/client/shownames.qc b/qcsrc/client/shownames.qc index 8d219c5444..acd4bc3710 100644 --- a/qcsrc/client/shownames.qc +++ b/qcsrc/client/shownames.qc @@ -7,6 +7,7 @@ #include #include +#include #include #include #include diff --git a/qcsrc/common/gamemodes/gamemode/assault/_mod.inc b/qcsrc/common/gamemodes/gamemode/assault/_mod.inc index e03d3c52e6..2235e53d74 100644 --- a/qcsrc/common/gamemodes/gamemode/assault/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/assault/_mod.inc @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/assault/_mod.qh b/qcsrc/common/gamemodes/gamemode/assault/_mod.qh index 211daa89e3..32bd160ba9 100644 --- a/qcsrc/common/gamemodes/gamemode/assault/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/assault/_mod.qh @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/assault/assault.qc b/qcsrc/common/gamemodes/gamemode/assault/assault.qc new file mode 100644 index 0000000000..c3e582a0f3 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/assault/assault.qc @@ -0,0 +1 @@ +#include "assault.qh" diff --git a/qcsrc/common/gamemodes/gamemode/assault/assault.qh b/qcsrc/common/gamemodes/gamemode/assault/assault.qh new file mode 100644 index 0000000000..f4f4b3f92f --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/assault/assault.qh @@ -0,0 +1,27 @@ +#pragma once + +#include + +CLASS(Assault, Gametype) + INIT(Assault) + { + this.gametype_init(this, _("Assault"),"as","g_assault",GAMETYPE_FLAG_TEAMPLAY,"","timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out")); + } + METHOD(Assault, m_generate_mapinfo, void(Gametype this, string v)) + { + if(v == "target_assault_roundend") + MapInfo_Map_supportedGametypes |= this.m_flags; + } + METHOD(Assault, m_isTwoBaseMode, bool()) + { + return true; + } + METHOD(Assault, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); + } + ATTRIB(Assault, m_legacydefaults, string, "20 0"); +ENDCLASS(Assault) +REGISTER_GAMETYPE(ASSAULT, NEW(Assault)); +#define g_assault IS_GAMETYPE(ASSAULT) diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/_mod.inc b/qcsrc/common/gamemodes/gamemode/clanarena/_mod.inc index ce7b59399a..d2a6992f67 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/clanarena/_mod.inc @@ -1,4 +1,8 @@ // generated file; do not modify +#include +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/_mod.qh b/qcsrc/common/gamemodes/gamemode/clanarena/_mod.qh index 55789f77ab..b583c0dd6e 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/clanarena/_mod.qh @@ -1,4 +1,8 @@ // generated file; do not modify +#include +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/cl_clanarena.qc b/qcsrc/common/gamemodes/gamemode/clanarena/cl_clanarena.qc new file mode 100644 index 0000000000..2bf470f156 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/clanarena/cl_clanarena.qc @@ -0,0 +1,79 @@ +#include "cl_clanarena.qh" + +void HUD_Mod_CA_Export(int fh) +{ + HUD_Write_Cvar("hud_panel_modicons_ca_layout"); +} + +void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i) +{ + TC(int, layout); TC(int, i); + int stat = -1; + string pic = ""; + vector color = '0 0 0'; + switch(i) + { + case 0: stat = STAT(REDALIVE); pic = "player_red"; color = '1 0 0'; break; + case 1: stat = STAT(BLUEALIVE); pic = "player_blue"; color = '0 0 1'; break; + case 2: stat = STAT(YELLOWALIVE); pic = "player_yellow"; color = '1 1 0'; break; + default: + case 3: stat = STAT(PINKALIVE); pic = "player_pink"; color = '1 0 1'; break; + } + + if(mySize.x/mySize.y > aspect_ratio) + { + i = aspect_ratio * mySize.y; + myPos.x = myPos.x + (mySize.x - i) / 2; + mySize.x = i; + } + else + { + i = 1/aspect_ratio * mySize.x; + myPos.y = myPos.y + (mySize.y - i) / 2; + mySize.y = i; + } + + if(layout) + { + drawpic_aspect_skin(myPos, pic, vec2(0.5 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(myPos + eX * 0.5 * mySize.x, ftos(stat), vec2(0.5 * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL); + } + else + drawstring_aspect(myPos, ftos(stat), mySize, color, panel_fg_alpha, DRAWFLAG_NORMAL); +} + +// Clan Arena and Freeze Tag HUD modicons +void HUD_Mod_CA(vector myPos, vector mySize) +{ + mod_active = 1; // required in each mod function that always shows something + + int layout; + if(ISGAMETYPE(CA)) + layout = autocvar_hud_panel_modicons_ca_layout; + else //if(ISGAMETYPE(FREEZETAG)) + layout = autocvar_hud_panel_modicons_freezetag_layout; + int rows, columns; + float aspect_ratio; + aspect_ratio = (layout) ? 2 : 1; + rows = HUD_GetRowCount(team_count, mySize, aspect_ratio); + columns = ceil(team_count/rows); + + int i; + float row = 0, column = 0; + vector pos = '0 0 0', itemSize; + itemSize = vec2(mySize.x / columns, mySize.y / rows); + for(i=0; i= rows) + { + row = 0; + ++column; + } + } +} diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/cl_clanarena.qh b/qcsrc/common/gamemodes/gamemode/clanarena/cl_clanarena.qh new file mode 100644 index 0000000000..206f1f5db3 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/clanarena/cl_clanarena.qh @@ -0,0 +1,4 @@ +#pragma once + +void HUD_Mod_CA(vector myPos, vector mySize); +void HUD_Mod_CA_Export(int fh); diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qc b/qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qc new file mode 100644 index 0000000000..079d4b6e58 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qc @@ -0,0 +1 @@ +#include "clanarena.qh" diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qh b/qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qh new file mode 100644 index 0000000000..3b3dace64e --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qh @@ -0,0 +1,49 @@ +#pragma once + +#include + +#ifdef CSQC +void HUD_Mod_CA(vector pos, vector mySize); +void HUD_Mod_CA_Export(int fh); +#endif +CLASS(ClanArena, Gametype) + INIT(ClanArena) + { + this.gametype_init(this, _("Clan Arena"),"ca","g_ca",GAMETYPE_FLAG_TEAMPLAY | GAMETYPE_FLAG_USEPOINTS,"","timelimit=20 pointlimit=10 teams=2 leadlimit=6",_("Kill all enemy teammates to win the round")); + } + METHOD(ClanArena, m_parse_mapinfo, bool(string k, string v)) + { + if (!k) { + cvar_set("g_ca_teams", cvar_defstring("g_ca_teams")); + return true; + } + switch (k) { + case "teams": + cvar_set("g_ca_teams", v); + return true; + } + return false; + } + METHOD(ClanArena, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) + { + if(spawnpoints >= 8 && diameter > 4096) + return true; + return false; + } + METHOD(ClanArena, m_setTeams, void(string sa)) + { + cvar_set("g_ca_teams", sa); + } + METHOD(ClanArena, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Frag limit:"), 5, 100, 5, "fraglimit_override", "g_ca_teams_override", _("The amount of frags needed before the match will end")); + } +#ifdef CSQC + ATTRIB(ClanArena, m_modicons, void(vector pos, vector mySize), HUD_Mod_CA); + ATTRIB(ClanArena, m_modicons_export, void(int fh), HUD_Mod_CA_Export); +#endif + ATTRIB(ClanArena, m_legacydefaults, string, "10 20 0"); +ENDCLASS(ClanArena) +REGISTER_GAMETYPE(CA, NEW(ClanArena)); +#define g_ca IS_GAMETYPE(CA) diff --git a/qcsrc/common/gamemodes/gamemode/ctf/ctf.qh b/qcsrc/common/gamemodes/gamemode/ctf/ctf.qh index 3cbd334b27..5d74f31cce 100644 --- a/qcsrc/common/gamemodes/gamemode/ctf/ctf.qh +++ b/qcsrc/common/gamemodes/gamemode/ctf/ctf.qh @@ -1,5 +1,44 @@ #pragma once +#include + +#ifdef CSQC +void HUD_Mod_CTF(vector pos, vector mySize); +void HUD_Mod_CTF_Reset(); +#endif +CLASS(CaptureTheFlag, Gametype) + INIT(CaptureTheFlag) + { + this.gametype_init(this, _("Capture the Flag"),"ctf","g_ctf",GAMETYPE_FLAG_TEAMPLAY | GAMETYPE_FLAG_USEPOINTS | GAMETYPE_FLAG_PRIORITY,"","timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it, defend your base from the other team")); + } + METHOD(CaptureTheFlag, m_generate_mapinfo, void(Gametype this, string v)) + { + if(v == "item_flag_team2" || v == "team_CTF_blueflag") + MapInfo_Map_supportedGametypes |= this.m_flags; + } + METHOD(CaptureTheFlag, m_isTwoBaseMode, bool()) + { + return true; + } + METHOD(CaptureTheFlag, m_setTeams, void(string sa)) + { + cvar_set("fraglimit", sa); + } + METHOD(CaptureTheFlag, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Capture limit:"), 1, 20, 1, "capturelimit_override", string_null, _("The amount of captures needed before the match will end")); + } +#ifdef CSQC + ATTRIB(CaptureTheFlag, m_modicons, void(vector pos, vector mySize), HUD_Mod_CTF); + ATTRIB(CaptureTheFlag, m_modicons_reset, void(), HUD_Mod_CTF_Reset); +#endif + ATTRIB(CaptureTheFlag, m_legacydefaults, string, "300 20 10 0"); +ENDCLASS(CaptureTheFlag) +REGISTER_GAMETYPE(CTF, NEW(CaptureTheFlag)); +#define g_ctf IS_GAMETYPE(CTF) + +#ifdef GAMEQC const int CTF_RED_FLAG_TAKEN = 1; const int CTF_RED_FLAG_LOST = 2; const int CTF_RED_FLAG_CARRYING = 3; @@ -18,3 +57,4 @@ const int CTF_NEUTRAL_FLAG_CARRYING = 768; const int CTF_FLAG_NEUTRAL = 2048; const int CTF_SHIELDED = 4096; const int CTF_STALEMATE = 8192; +#endif diff --git a/qcsrc/common/gamemodes/gamemode/cts/_mod.inc b/qcsrc/common/gamemodes/gamemode/cts/_mod.inc index a48cd89dda..5978c8bac1 100644 --- a/qcsrc/common/gamemodes/gamemode/cts/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/cts/_mod.inc @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/cts/_mod.qh b/qcsrc/common/gamemodes/gamemode/cts/_mod.qh index d05e62987f..e062122407 100644 --- a/qcsrc/common/gamemodes/gamemode/cts/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/cts/_mod.qh @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/cts/cts.qc b/qcsrc/common/gamemodes/gamemode/cts/cts.qc new file mode 100644 index 0000000000..cfc0c6f441 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/cts/cts.qc @@ -0,0 +1 @@ +#include "cts.qh" diff --git a/qcsrc/common/gamemodes/gamemode/cts/cts.qh b/qcsrc/common/gamemodes/gamemode/cts/cts.qh new file mode 100644 index 0000000000..c59b73c363 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/cts/cts.qh @@ -0,0 +1,36 @@ +#pragma once + +#include +#if defined(CSQC) + #include +#endif + +CLASS(RaceCTS, Gametype) + INIT(RaceCTS) + { + this.gametype_init(this, _("Race CTS"),"cts","g_cts",0,"cloaked","timelimit=20",_("Race for fastest time.")); + } + METHOD(RaceCTS, m_generate_mapinfo, void(Gametype this, string v)) + { + if(v == "target_startTimer") + MapInfo_Map_supportedGametypes |= this.m_flags; + } + METHOD(RaceCTS, m_setTeams, void(string sa)) + { + // this is the skill of the map + // not parsed by anything yet + // for map databases + // cvar_set("fraglimit", sa); + } + METHOD(RaceCTS, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); + } +#ifdef CSQC + ATTRIB(RaceCTS, m_modicons, void(vector pos, vector mySize), HUD_Mod_Race); +#endif + ATTRIB(RaceCTS, m_legacydefaults, string, "20 0 0"); +ENDCLASS(RaceCTS) +REGISTER_GAMETYPE(CTS, NEW(RaceCTS)); +#define g_cts IS_GAMETYPE(CTS) diff --git a/qcsrc/common/gamemodes/gamemode/deathmatch/_mod.inc b/qcsrc/common/gamemodes/gamemode/deathmatch/_mod.inc index ba2449386c..4b37b093e2 100644 --- a/qcsrc/common/gamemodes/gamemode/deathmatch/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/deathmatch/_mod.inc @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/deathmatch/_mod.qh b/qcsrc/common/gamemodes/gamemode/deathmatch/_mod.qh index abc7db377a..3e67c78ef2 100644 --- a/qcsrc/common/gamemodes/gamemode/deathmatch/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/deathmatch/_mod.qh @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/deathmatch/deathmatch.qc b/qcsrc/common/gamemodes/gamemode/deathmatch/deathmatch.qc new file mode 100644 index 0000000000..fd1e1e10e7 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/deathmatch/deathmatch.qc @@ -0,0 +1 @@ +#include "deathmatch.qh" diff --git a/qcsrc/common/gamemodes/gamemode/deathmatch/deathmatch.qh b/qcsrc/common/gamemodes/gamemode/deathmatch/deathmatch.qh new file mode 100644 index 0000000000..ca55a3b872 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/deathmatch/deathmatch.qh @@ -0,0 +1,16 @@ +#pragma once + +#include + +CLASS(Deathmatch, Gametype) + INIT(Deathmatch) + { + this.gametype_init(this, _("Deathmatch"),"dm","g_dm",GAMETYPE_FLAG_USEPOINTS | GAMETYPE_FLAG_PREFERRED,"","timelimit=15 pointlimit=30 leadlimit=0",_("Score as many frags as you can")); + } + METHOD(Deathmatch, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) + { + return true; + } + ATTRIB(Deathmatch, m_legacydefaults, string, "30 20 0"); +ENDCLASS(Deathmatch) +REGISTER_GAMETYPE(DEATHMATCH, NEW(Deathmatch)); diff --git a/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qc b/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qc index 418a843d9b..5a91165e95 100644 --- a/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qc +++ b/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qc @@ -2,6 +2,11 @@ #include +void HUD_Mod_Dom_Export(int fh) +{ + HUD_Write_Cvar("hud_panel_modicons_dom_layout"); +} + int autocvar_hud_panel_modicons_dom_layout; void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i) diff --git a/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qh b/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qh index 11ab3daca7..5e04dd0491 100644 --- a/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qh +++ b/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qh @@ -1,3 +1,4 @@ #pragma once void HUD_Mod_Dom(vector myPos, vector mySize); +void HUD_Mod_Dom_Export(int fh); diff --git a/qcsrc/common/gamemodes/gamemode/domination/domination.qh b/qcsrc/common/gamemodes/gamemode/domination/domination.qh index 6f70f09bee..4ebb684255 100644 --- a/qcsrc/common/gamemodes/gamemode/domination/domination.qh +++ b/qcsrc/common/gamemodes/gamemode/domination/domination.qh @@ -1 +1,43 @@ #pragma once + +#include + +#ifdef CSQC +void HUD_Mod_Dom(vector pos, vector mySize); +void HUD_Mod_Dom_Export(int fh); +#endif +CLASS(Domination, Gametype) + INIT(Domination) + { + this.gametype_init(this, _("Domination"),"dom","g_domination",GAMETYPE_FLAG_TEAMPLAY | GAMETYPE_FLAG_USEPOINTS,"","timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture and defend all the control points to win")); + } + METHOD(Domination, m_parse_mapinfo, bool(string k, string v)) + { + if (!k) { + cvar_set("g_domination_default_teams", cvar_defstring("g_domination_default_teams")); + return true; + } + switch (k) { + case "teams": + cvar_set("g_domination_default_teams", v); + return true; + } + return false; + } + METHOD(Domination, m_generate_mapinfo, void(Gametype this, string v)) + { + if(v == "dom_controlpoint") + MapInfo_Map_supportedGametypes |= this.m_flags; + } + METHOD(Domination, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Point limit:"), 50, 500, 10, "g_domination_point_limit", "g_domination_teams_override", _("The amount of points needed before the match will end")); + } +#ifdef CSQC + ATTRIB(Domination, m_modicons, void(vector pos, vector mySize), HUD_Mod_Dom); + ATTRIB(Domination, m_modicons_export, void(int fh), HUD_Mod_Dom_Export); +#endif + ATTRIB(Domination, m_legacydefaults, string, "200 20 0"); +ENDCLASS(Domination) +REGISTER_GAMETYPE(DOMINATION, NEW(Domination)); diff --git a/qcsrc/common/gamemodes/gamemode/duel/_mod.inc b/qcsrc/common/gamemodes/gamemode/duel/_mod.inc index 5925816750..1a7e0d3396 100644 --- a/qcsrc/common/gamemodes/gamemode/duel/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/duel/_mod.inc @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/duel/_mod.qh b/qcsrc/common/gamemodes/gamemode/duel/_mod.qh index 00e553c202..6d6cc3c2e2 100644 --- a/qcsrc/common/gamemodes/gamemode/duel/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/duel/_mod.qh @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/duel/duel.qc b/qcsrc/common/gamemodes/gamemode/duel/duel.qc new file mode 100644 index 0000000000..6cba48c2f3 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/duel/duel.qc @@ -0,0 +1 @@ +#include "duel.qh" diff --git a/qcsrc/common/gamemodes/gamemode/duel/duel.qh b/qcsrc/common/gamemodes/gamemode/duel/duel.qh new file mode 100644 index 0000000000..298e62e003 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/duel/duel.qh @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +CLASS(Duel, Gametype) + INIT(Duel) + { + this.gametype_init(this, _("Duel"),"duel","g_duel",GAMETYPE_FLAG_USEPOINTS,"","timelimit=10 pointlimit=0 leadlimit=0",_("Fight in a one versus one arena battle to decide the winner")); + } + METHOD(Duel, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) + { + return (diameter < 16384); + } + METHOD(Duel, m_isForcedSupported, bool(Gametype this)) + { + if(!cvar("g_duel_not_dm_maps")) + { + // if this is set, all DM maps support duel too + // TODO: we should really check the size of maps, some DM maps do not work for duel! + if(!(MapInfo_Map_supportedGametypes & this.m_flags) && (MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH.m_flags)) + return true; // TODO: references another gametype (alternatively, we could check which gamemodes are always enabled and append this if any are supported) + } + return false; + } +ENDCLASS(Duel) +REGISTER_GAMETYPE(DUEL, NEW(Duel)); +#define g_duel IS_GAMETYPE(DUEL) diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/_mod.inc b/qcsrc/common/gamemodes/gamemode/freezetag/_mod.inc index 4d62800356..28034e64c4 100644 --- a/qcsrc/common/gamemodes/gamemode/freezetag/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/freezetag/_mod.inc @@ -1,4 +1,8 @@ // generated file; do not modify +#include +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/_mod.qh b/qcsrc/common/gamemodes/gamemode/freezetag/_mod.qh index 785d7b8136..84007e936e 100644 --- a/qcsrc/common/gamemodes/gamemode/freezetag/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/freezetag/_mod.qh @@ -1,4 +1,8 @@ // generated file; do not modify +#include +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/cl_freezetag.qc b/qcsrc/common/gamemodes/gamemode/freezetag/cl_freezetag.qc new file mode 100644 index 0000000000..e7443db678 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/freezetag/cl_freezetag.qc @@ -0,0 +1,6 @@ +#include "cl_freezetag.qh" + +void HUD_Mod_FreezeTag_Export(int fh) +{ + HUD_Write_Cvar("hud_panel_modicons_freezetag_layout"); +} diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/cl_freezetag.qh b/qcsrc/common/gamemodes/gamemode/freezetag/cl_freezetag.qh new file mode 100644 index 0000000000..0d2f4407be --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/freezetag/cl_freezetag.qh @@ -0,0 +1,3 @@ +#pragma once + +void HUD_Mod_FreezeTag_Export(int fh); diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qc b/qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qc new file mode 100644 index 0000000000..9bb8304eb2 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qc @@ -0,0 +1 @@ +#include "freezetag.qh" diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qh b/qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qh new file mode 100644 index 0000000000..66eda36159 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qh @@ -0,0 +1,51 @@ +#pragma once + +#include +#if defined(CSQC) + #include +#endif + +#ifdef CSQC +void HUD_Mod_FreezeTag_Export(int fh); +#endif +CLASS(FreezeTag, Gametype) + INIT(FreezeTag) + { + this.gametype_init(this, _("Freeze Tag"),"ft","g_freezetag",GAMETYPE_FLAG_TEAMPLAY | GAMETYPE_FLAG_USEPOINTS,"","timelimit=20 pointlimit=10 teams=2 leadlimit=6",_("Kill enemies to freeze them, stand next to frozen teammates to revive them; freeze all enemies to win")); + } + METHOD(FreezeTag, m_parse_mapinfo, bool(string k, string v)) + { + if (!k) { + cvar_set("g_freezetag_teams", cvar_defstring("g_freezetag_teams")); + return true; + } + switch (k) { + case "teams": + cvar_set("g_freezetag_teams", v); + return true; + } + return false; + } + METHOD(FreezeTag, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) + { + if(spawnpoints >= 8 && diameter > 4096) + return true; + return false; + } + METHOD(FreezeTag, m_setTeams, void(string sa)) + { + cvar_set("g_freezetag_teams", sa); + } + METHOD(FreezeTag, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Frag limit:"), 5, 100, 5, "fraglimit_override", "g_freezetag_teams_override", _("The amount of frags needed before the match will end")); + } +#ifdef CSQC + ATTRIB(FreezeTag, m_modicons, void(vector pos, vector mySize), HUD_Mod_CA); + ATTRIB(FreezeTag, m_modicons_export, void(int fh), HUD_Mod_FreezeTag_Export); +#endif + ATTRIB(FreezeTag, m_legacydefaults, string, "10 20 0"); +ENDCLASS(FreezeTag) +REGISTER_GAMETYPE(FREEZETAG, NEW(FreezeTag)); +#define g_freezetag IS_GAMETYPE(FREEZETAG) diff --git a/qcsrc/common/gamemodes/gamemode/invasion/_mod.inc b/qcsrc/common/gamemodes/gamemode/invasion/_mod.inc index a197891fe8..e8b28e96bc 100644 --- a/qcsrc/common/gamemodes/gamemode/invasion/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/invasion/_mod.inc @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/invasion/_mod.qh b/qcsrc/common/gamemodes/gamemode/invasion/_mod.qh index f90ea9b31e..5181956f20 100644 --- a/qcsrc/common/gamemodes/gamemode/invasion/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/invasion/_mod.qh @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/invasion/invasion.qc b/qcsrc/common/gamemodes/gamemode/invasion/invasion.qc new file mode 100644 index 0000000000..6462b92bf6 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/invasion/invasion.qc @@ -0,0 +1 @@ +#include "invasion.qh" diff --git a/qcsrc/common/gamemodes/gamemode/invasion/invasion.qh b/qcsrc/common/gamemodes/gamemode/invasion/invasion.qh new file mode 100644 index 0000000000..2195b84c71 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/invasion/invasion.qh @@ -0,0 +1,33 @@ +#pragma once + +#include + +CLASS(Invasion, Gametype) + INIT(Invasion) + { + this.gametype_init(this, _("Invasion"),"inv","g_invasion",GAMETYPE_FLAG_USEPOINTS,"","pointlimit=50 teams=0 type=0",_("Survive against waves of monsters")); + } + METHOD(Invasion, m_parse_mapinfo, bool(string k, string v)) + { + switch (k) { + case "teams": + cvar_set("g_invasion_teams", v); + return true; + case "type": + cvar_set("g_invasion_type", v); + return true; + } + return false; + } + METHOD(Invasion, m_generate_mapinfo, void(Gametype this, string v)) + { + if(v == "invasion_spawnpoint") + MapInfo_Map_supportedGametypes |= this.m_flags; + } + METHOD(Invasion, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); + } +ENDCLASS(Invasion) +REGISTER_GAMETYPE(INVASION, NEW(Invasion)); diff --git a/qcsrc/common/gamemodes/gamemode/keepaway/keepaway.qh b/qcsrc/common/gamemodes/gamemode/keepaway/keepaway.qh index 6f70f09bee..cf21ab0d37 100644 --- a/qcsrc/common/gamemodes/gamemode/keepaway/keepaway.qh +++ b/qcsrc/common/gamemodes/gamemode/keepaway/keepaway.qh @@ -1 +1,21 @@ #pragma once + +#include + +#ifdef CSQC +void HUD_Mod_Keepaway(vector pos, vector mySize); +#endif +CLASS(Keepaway, Gametype) + INIT(Keepaway) + { + this.gametype_init(this, _("Keepaway"),"ka","g_keepaway",GAMETYPE_FLAG_USEPOINTS,"","timelimit=20 pointlimit=30",_("Hold the ball to get points for kills")); + } + METHOD(Keepaway, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) + { + return true; + } +#ifdef CSQC + ATTRIB(Keepaway, m_modicons, void(vector pos, vector mySize), HUD_Mod_Keepaway); +#endif +ENDCLASS(Keepaway) +REGISTER_GAMETYPE(KEEPAWAY, NEW(Keepaway)); diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qh b/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qh index 6f70f09bee..cc9cecdaf2 100644 --- a/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qh +++ b/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qh @@ -1 +1,46 @@ #pragma once + +#include + +#ifdef CSQC +void HUD_Mod_KH(vector pos, vector mySize); +#endif +CLASS(KeyHunt, Gametype) + INIT(KeyHunt) + { + this.gametype_init(this, _("Key Hunt"),"kh","g_keyhunt",GAMETYPE_FLAG_TEAMPLAY | GAMETYPE_FLAG_USEPOINTS,"","timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round")); + } + METHOD(KeyHunt, m_parse_mapinfo, bool(string k, string v)) + { + if (!k) { + cvar_set("g_keyhunt_teams", cvar_defstring("g_keyhunt_teams")); + return true; + } + switch (k) { + case "teams": + cvar_set("g_keyhunt_teams", v); + return true; + } + return false; + } + METHOD(KeyHunt, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) + { + if(spawnpoints >= 12 && diameter > 5120) + return true; + return false; + } + METHOD(KeyHunt, m_setTeams, void(string sa)) + { + cvar_set("g_keyhunt_teams", sa); + } + METHOD(KeyHunt, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Point limit:"), 200, 1500, 50, "g_keyhunt_point_limit", "g_keyhunt_teams_override", _("The amount of points needed before the match will end")); + } +#ifdef CSQC + ATTRIB(KeyHunt, m_modicons, void(vector pos, vector mySize), HUD_Mod_KH); +#endif + ATTRIB(KeyHunt, m_legacydefaults, string, "1000 20 3 0"); +ENDCLASS(KeyHunt) +REGISTER_GAMETYPE(KEYHUNT, NEW(KeyHunt)); diff --git a/qcsrc/common/gamemodes/gamemode/lms/_mod.inc b/qcsrc/common/gamemodes/gamemode/lms/_mod.inc index fcf63d7cc9..69be66feb5 100644 --- a/qcsrc/common/gamemodes/gamemode/lms/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/lms/_mod.inc @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/lms/_mod.qh b/qcsrc/common/gamemodes/gamemode/lms/_mod.qh index 51c1ee15f4..cbb42ad8d3 100644 --- a/qcsrc/common/gamemodes/gamemode/lms/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/lms/_mod.qh @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/lms/lms.qc b/qcsrc/common/gamemodes/gamemode/lms/lms.qc new file mode 100644 index 0000000000..92fb7df9e6 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/lms/lms.qc @@ -0,0 +1 @@ +#include "lms.qh" diff --git a/qcsrc/common/gamemodes/gamemode/lms/lms.qh b/qcsrc/common/gamemodes/gamemode/lms/lms.qh new file mode 100644 index 0000000000..0191839a43 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/lms/lms.qh @@ -0,0 +1,21 @@ +#pragma once + +#include + +CLASS(LastManStanding, Gametype) + INIT(LastManStanding) + { + this.gametype_init(this, _("Last Man Standing"),"lms","g_lms",GAMETYPE_FLAG_USEPOINTS,"","timelimit=20 lives=5 leadlimit=0",_("Survive and kill until the enemies have no lives left")); + } + METHOD(LastManStanding, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) + { + return true; + } + METHOD(LastManStanding, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Lives:"), 3, 50, 1, "g_lms_lives_override", string_null, string_null); + } + ATTRIB(LastManStanding, m_legacydefaults, string, "9 20 0"); +ENDCLASS(LastManStanding) +REGISTER_GAMETYPE(LMS, NEW(LastManStanding)); diff --git a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qh b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qh index 6f70f09bee..9a8fca3ab9 100644 --- a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qh +++ b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qh @@ -1 +1,33 @@ #pragma once + +#include + +#ifdef CSQC +void HUD_Mod_NexBall(vector pos, vector mySize); +#endif +CLASS(NexBall, Gametype) + INIT(NexBall) + { + this.gametype_init(this, _("Nexball"),"nb","g_nexball",GAMETYPE_FLAG_TEAMPLAY | GAMETYPE_FLAG_USEPOINTS,"","timelimit=20 pointlimit=5 leadlimit=0",_("Shoot and kick the ball into the enemies goal, keep your goal clean")); + } + METHOD(NexBall, m_generate_mapinfo, void(Gametype this, string v)) + { + if(substring(v, 0, 8) == "nexball_" || substring(v, 0, 4) == "ball") + MapInfo_Map_supportedGametypes |= this.m_flags; + } + METHOD(NexBall, m_isTwoBaseMode, bool()) + { + return true; + } + METHOD(NexBall, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Goals:"), 1, 50, 1, "g_nexball_goallimit", string_null, _("The amount of goals needed before the match will end")); + } +#ifdef CSQC + ATTRIB(NexBall, m_modicons, void(vector pos, vector mySize), HUD_Mod_NexBall); +#endif + ATTRIB(NexBall, m_legacydefaults, string, "5 20 0"); +ENDCLASS(NexBall) +REGISTER_GAMETYPE(NEXBALL, NEW(NexBall)); +#define g_nexball IS_GAMETYPE(NEXBALL) diff --git a/qcsrc/common/gamemodes/gamemode/nexball/weapon.qh b/qcsrc/common/gamemodes/gamemode/nexball/weapon.qh index ccabc47a51..bde6340798 100644 --- a/qcsrc/common/gamemodes/gamemode/nexball/weapon.qh +++ b/qcsrc/common/gamemodes/gamemode/nexball/weapon.qh @@ -1,5 +1,7 @@ #pragma once +#include + CLASS(BallStealer, PortoLaunch) /* flags */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_NOTRUEAIM); /* impulse */ ATTRIB(BallStealer, impulse, int, 0); diff --git a/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qh b/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qh index add678d7b3..0c375494bc 100644 --- a/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qh +++ b/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qh @@ -1,5 +1,26 @@ #pragma once +#include + +CLASS(Onslaught, Gametype) + INIT(Onslaught) + { + this.gametype_init(this, _("Onslaught"),"ons","g_onslaught",GAMETYPE_FLAG_TEAMPLAY,"","pointlimit=1 timelimit=20",_("Capture control points to reach and destroy the enemy generator")); + } + METHOD(Onslaught, m_generate_mapinfo, void(Gametype this, string v)) + { + if(v == "onslaught_generator") + MapInfo_Map_supportedGametypes |= this.m_flags; + } + METHOD(Onslaught, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); + } + ATTRIB(Onslaught, m_legacydefaults, string, "20 0"); +ENDCLASS(Onslaught) +REGISTER_GAMETYPE(ONSLAUGHT, NEW(Onslaught)); + #ifdef GAMEQC REGISTER_NET_LINKED(ENT_CLIENT_GENERATOR) REGISTER_NET_LINKED(ENT_CLIENT_CONTROLPOINT_ICON) diff --git a/qcsrc/common/gamemodes/gamemode/race/_mod.inc b/qcsrc/common/gamemodes/gamemode/race/_mod.inc index 5ed2c95981..f7c47947a6 100644 --- a/qcsrc/common/gamemodes/gamemode/race/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/race/_mod.inc @@ -1,4 +1,8 @@ // generated file; do not modify +#include +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/race/_mod.qh b/qcsrc/common/gamemodes/gamemode/race/_mod.qh index 1e76e7af30..52348a2197 100644 --- a/qcsrc/common/gamemodes/gamemode/race/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/race/_mod.qh @@ -1,4 +1,8 @@ // generated file; do not modify +#include +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/race/cl_race.qc b/qcsrc/common/gamemodes/gamemode/race/cl_race.qc new file mode 100644 index 0000000000..ee90914a3d --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/race/cl_race.qc @@ -0,0 +1,147 @@ +#include "cl_race.qh" + +// Race/CTS HUD mod icons +float crecordtime_prev; // last remembered crecordtime +float crecordtime_change_time; // time when crecordtime last changed +float srecordtime_prev; // last remembered srecordtime +float srecordtime_change_time; // time when srecordtime last changed + +float race_status_time; +int race_status_prev; +string race_status_name_prev; + +// Check if the given name already exist in race rankings? In that case, where? (otherwise return 0) +int race_CheckName(string net_name) +{ + int rank = 0; + string zoned_name = strzone(strdecolorize(entcs_GetName(player_localnum))); + for (int i = RANKINGS_CNT - 1; i >= 0; --i) + if (strdecolorize(grecordholder[i]) == zoned_name) + { + rank = i + 1; + break; + } + strfree(zoned_name); + return rank; +} + +void race_showTime(string text, vector pos, vector timeText_ofs, float theTime, vector textSize, float f) +{ + drawstring_aspect(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + if (f < 1) { + drawstring_aspect_expanding(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f); + drawstring_aspect_expanding(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f); + } +} + +void HUD_Mod_Race(vector pos, vector mySize) +{ + entity me = playerslots[player_localnum]; + float score = me.(scores(ps_primary)); + + if(!(scores_flags(ps_primary) & SFL_TIME) || teamplay) // race/cts record display on HUD + { + mod_active = 0; // hide it in this case! + return; // no records in the actual race + } + + mod_active = 1; + + // clientside personal record + string rr; + if(ISGAMETYPE(CTS)) + rr = CTS_RECORD; + else + rr = RACE_RECORD; + float t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time"))); + + if(score && (score < t || !t)) { + db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score)); + if(autocvar_cl_autodemo_delete_keeprecords) + { + float f = autocvar_cl_autodemo_delete; + f &= ~1; + cvar_set("cl_autodemo_delete", ftos(f)); // don't delete demo with new record! + } + } + + if(t != crecordtime_prev) { + crecordtime_prev = t; + crecordtime_change_time = time; + } + + vector textPos, medalPos; + float squareSize; + if(mySize.x > mySize.y) { + // text on left side + squareSize = min(mySize.y, mySize.x/2); + vector ofs = vec2(0.5 * max(0, mySize.x/2 - squareSize), 0.5 * (mySize.y - squareSize)); + textPos = pos + ofs; + ofs.x += 0.5 * mySize.x; + medalPos = pos + ofs; + } else { + // text on top + squareSize = min(mySize.x, mySize.y/2); + vector ofs = vec2(0.5 * (mySize.x - squareSize), 0.5 * max(0, mySize.y/2 - squareSize)); + textPos = pos + ofs; + ofs.y += 0.5 * mySize.y; + medalPos = pos + ofs; + } + vector textSize = vec2(squareSize, 0.25 * squareSize); + + race_showTime(_("Personal best"), textPos, eY * 0.25 * squareSize, t, textSize, time - crecordtime_change_time); + + // server record + t = race_server_record; + if(t != srecordtime_prev) { + srecordtime_prev = t; + srecordtime_change_time = time; + } + + textPos += eY * 0.5 * squareSize; + race_showTime(_("Server best"), textPos, eY * 0.25 * squareSize, t, textSize, time - srecordtime_change_time); + + if (race_status != race_status_prev || race_status_name != race_status_name_prev) { + race_status_time = time + 5; + race_status_prev = race_status; + strcpy(race_status_name_prev, race_status_name); + } + + // race "awards" + float a = bound(0, race_status_time - time, 1); + string s = textShortenToWidth(ColorTranslateRGB(race_status_name), squareSize, '1 1 0' * 0.1 * squareSize, stringwidth_colors); + + float rank = 0; + if(race_status > 0) + rank = race_CheckName(race_status_name); + string rankname = count_ordinal(rank); + vector namepos = medalPos + '0 0.8 0' * squareSize; + vector rankpos = medalPos + '0 0.15 0' * squareSize; + + if(race_status == 0) + drawpic_aspect_skin(medalPos, "race_newfail", '1 1 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + else if(race_status == 1) { + drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newtime", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL); + drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + } else if(race_status == 2) { + if(strdecolorize(race_status_name) == strdecolorize(entcs_GetName(player_localnum)) || !race_myrank || race_myrank < rank) + drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankgreen", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + else + drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankyellow", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL); + drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + } else if(race_status == 3) { + drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrecordserver", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL); + drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + } + + if (race_status_time - time <= 0) { + race_status_prev = -1; + race_status = -1; + strfree(race_status_name); + strfree(race_status_name_prev); + } +} diff --git a/qcsrc/common/gamemodes/gamemode/race/cl_race.qh b/qcsrc/common/gamemodes/gamemode/race/cl_race.qh new file mode 100644 index 0000000000..8ed2e3a671 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/race/cl_race.qh @@ -0,0 +1,3 @@ +#pragma once + +void HUD_Mod_Race(vector pos, vector mySize); diff --git a/qcsrc/common/gamemodes/gamemode/race/race.qc b/qcsrc/common/gamemodes/gamemode/race/race.qc new file mode 100644 index 0000000000..f41a747c5c --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/race/race.qc @@ -0,0 +1 @@ +#include "race.qh" diff --git a/qcsrc/common/gamemodes/gamemode/race/race.qh b/qcsrc/common/gamemodes/gamemode/race/race.qh new file mode 100644 index 0000000000..2eed3433f4 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/race/race.qh @@ -0,0 +1,46 @@ +#pragma once + +#include + +#ifdef CSQC +void HUD_Mod_Race(vector pos, vector mySize); +#endif +CLASS(Race, Gametype) + INIT(Race) + { + this.gametype_init(this, _("Race"),"rc","g_race",GAMETYPE_FLAG_USEPOINTS,"","timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line")); + } + METHOD(Race, m_parse_mapinfo, bool(string k, string v)) + { + if (!k) { + cvar_set("g_race_qualifying_timelimit", cvar_defstring("g_race_qualifying_timelimit")); + return true; + } + switch (k) { + case "qualifying_timelimit": + cvar_set("g_race_qualifying_timelimit", v); + return true; + } + return false; + } + METHOD(Race, m_generate_mapinfo, void(Gametype this, string v)) + { + if(v == "trigger_race_checkpoint") + MapInfo_Map_supportedGametypes |= this.m_flags; + } + METHOD(Race, m_isTwoBaseMode, bool()) + { + return true; + } + METHOD(Race, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Laps:"), 1, 25, 1, "g_race_laps_limit", string_null, string_null); + } +#ifdef CSQC + ATTRIB(Race, m_modicons, void(vector pos, vector mySize), HUD_Mod_Race); +#endif + ATTRIB(Race, m_legacydefaults, string, "20 5 7 15 0"); +ENDCLASS(Race) +REGISTER_GAMETYPE(RACE, NEW(Race)); +#define g_race IS_GAMETYPE(RACE) diff --git a/qcsrc/common/gamemodes/gamemode/tdm/_mod.inc b/qcsrc/common/gamemodes/gamemode/tdm/_mod.inc index 5c0e949a8a..bea3814f00 100644 --- a/qcsrc/common/gamemodes/gamemode/tdm/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/tdm/_mod.inc @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/tdm/_mod.qh b/qcsrc/common/gamemodes/gamemode/tdm/_mod.qh index 5be8ea6e6f..4ff6f48a04 100644 --- a/qcsrc/common/gamemodes/gamemode/tdm/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/tdm/_mod.qh @@ -1,4 +1,5 @@ // generated file; do not modify +#include #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/tdm/tdm.qc b/qcsrc/common/gamemodes/gamemode/tdm/tdm.qc new file mode 100644 index 0000000000..ca84d01d5e --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/tdm/tdm.qc @@ -0,0 +1 @@ +#include "tdm.qh" diff --git a/qcsrc/common/gamemodes/gamemode/tdm/tdm.qh b/qcsrc/common/gamemodes/gamemode/tdm/tdm.qh new file mode 100644 index 0000000000..d0e23940a3 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/tdm/tdm.qh @@ -0,0 +1,52 @@ +#pragma once + +#include +#include + +CLASS(TeamDeathmatch, Gametype) + INIT(TeamDeathmatch) + { + this.gametype_init(this, _("Team Deathmatch"),"tdm","g_tdm",GAMETYPE_FLAG_TEAMPLAY | GAMETYPE_FLAG_USEPOINTS | GAMETYPE_FLAG_PRIORITY,"","timelimit=15 pointlimit=50 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team")); + } + METHOD(TeamDeathmatch, m_parse_mapinfo, bool(string k, string v)) + { + if (!k) { + cvar_set("g_tdm_teams", cvar_defstring("g_tdm_teams")); + return true; + } + switch (k) { + case "teams": + cvar_set("g_tdm_teams", v); + return true; + } + return false; + } + METHOD(TeamDeathmatch, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) + { + if(spawnpoints >= 8 && diameter > 4096) + return true; + return false; + } + METHOD(TeamDeathmatch, m_isForcedSupported, bool(Gametype this)) + { + if(cvar("g_tdm_on_dm_maps")) + { + // if this is set, all DM maps support TDM too + if(!(MapInfo_Map_supportedGametypes & this.m_flags) && (MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH.m_flags)) + return true; // TODO: references another gametype (alternatively, we could check which gamemodes are always enabled and append this if any are supported) + } + return false; + } + METHOD(TeamDeathmatch, m_setTeams, void(string sa)) + { + cvar_set("g_tdm_teams", sa); + } + METHOD(TeamDeathmatch, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) + { + TC(Gametype, this); + returns(menu, _("Point limit:"), 5, 100, 5, "g_tdm_point_limit", "g_tdm_teams_override", _("The amount of points needed before the match will end")); + } + ATTRIB(TeamDeathmatch, m_legacydefaults, string, "50 20 2 0"); +ENDCLASS(TeamDeathmatch) +REGISTER_GAMETYPE(TEAM_DEATHMATCH, NEW(TeamDeathmatch)); +#define g_tdm IS_GAMETYPE(TEAM_DEATHMATCH) diff --git a/qcsrc/common/mapinfo.qc b/qcsrc/common/mapinfo.qc index ae387e3db9..1589892696 100644 --- a/qcsrc/common/mapinfo.qc +++ b/qcsrc/common/mapinfo.qc @@ -1258,14 +1258,25 @@ void MapInfo_LoadMapSettings(string s) // to be called from worldspawn return; // do not call Get_ByName! } +#if 0 + // find the lowest bit in the supported gametypes + // unnecessary now that we select one at random int _t = 1; while(!(MapInfo_Map_supportedGametypes & 1)) { _t <<= 1; MapInfo_Map_supportedGametypes = floor(MapInfo_Map_supportedGametypes >> 1); + LOG_INFO("_t: ", ftos(_t), ", types: ", ftos(MapInfo_Map_supportedGametypes)); } +#endif + RandomSelection_Init(); Gametype t_prev = t; - FOREACH(Gametypes, it.m_flags == _t, { t = it; break; }); + FOREACH(Gametypes, MapInfo_Map_supportedGametypes & it.m_flags, + { + RandomSelection_AddEnt(it, 1, it.m_priority); + }); + if(RandomSelection_chosen_ent) + t = RandomSelection_chosen_ent; // t is now a supported mode! LOG_WARNF("can't play the selected map in the given game mode (%s). Falling back to a supported mode (%s).", t_prev.mdl, t.mdl); diff --git a/qcsrc/common/mapinfo.qh b/qcsrc/common/mapinfo.qh index 9b4dfa2575..c5b9906c13 100644 --- a/qcsrc/common/mapinfo.qh +++ b/qcsrc/common/mapinfo.qh @@ -16,6 +16,11 @@ int MapInfo_Map_flags; vector MapInfo_Map_mins; // these are '0 0 0' if not supported! vector MapInfo_Map_maxs; // these are '0 0 0' if not specified! +const int GAMETYPE_FLAG_TEAMPLAY = BIT(0); // teamplay based +const int GAMETYPE_FLAG_USEPOINTS = BIT(1); // gametype has point-based scoring +const int GAMETYPE_FLAG_PREFERRED = BIT(2); // preferred (when available) in random selections +const int GAMETYPE_FLAG_PRIORITY = BIT(3); // priority selection when preferred gametype isn't available in random selections + int MAPINFO_TYPE_ALL; .int m_flags; @@ -37,9 +42,12 @@ CLASS(Gametype, Object) ATTRIB(Gametype, model2, string); /** game type description */ ATTRIB(Gametype, gametype_description, string); + /** game type priority in random selections */ + ATTRIB(Gametype, m_priority, int, 0); #ifdef CSQC ATTRIB(Gametype, m_modicons, void(vector pos, vector mySize)); ATTRIB(Gametype, m_modicons_reset, void()); + ATTRIB(Gametype, m_modicons_export, void(int fh)); #endif /** DO NOT USE, this is compatibility for legacy maps! */ @@ -84,16 +92,17 @@ CLASS(Gametype, Object) returns(this.message, strcat("gametype_", this.mdl)); } - METHOD(Gametype, gametype_init, void(Gametype this, string hname, string sname, string g_name, bool gteamplay, bool gusepoints, string mutators, string defaults, string gdescription)) + METHOD(Gametype, gametype_init, void(Gametype this, string hname, string sname, string g_name, int gflags, string mutators, string defaults, string gdescription)) { this.netname = g_name; this.mdl = sname; this.message = hname; - this.team = gteamplay; + this.team = (gflags & GAMETYPE_FLAG_TEAMPLAY); this.m_mutators = cons(sname, mutators); this.model2 = defaults; this.gametype_description = gdescription; - this.frags = gusepoints; + this.frags = (gflags & GAMETYPE_FLAG_USEPOINTS); + this.m_priority = ((gflags & GAMETYPE_FLAG_PREFERRED) ? 2 : ((gflags & GAMETYPE_FLAG_PRIORITY) ? 1 : 0)); // same as `1 << m_id` MAPINFO_TYPE_ALL |= this.items = this.m_flags = (MAPINFO_TYPE_ALL + 1); @@ -102,6 +111,7 @@ ENDCLASS(Gametype) REGISTRY(Gametypes, 24) REGISTER_REGISTRY(Gametypes) +REGISTRY_SORT(Gametypes); REGISTRY_CHECK(Gametypes) REGISTRY_DEFINE_GET(Gametypes, NULL) @@ -109,505 +119,6 @@ REGISTRY_DEFINE_GET(Gametypes, NULL) #define IS_GAMETYPE(NAME) (MapInfo_LoadedGametype == MAPINFO_TYPE_##NAME) -CLASS(Deathmatch, Gametype) - INIT(Deathmatch) - { - this.gametype_init(this, _("Deathmatch"),"dm","g_dm",false,true,"","timelimit=15 pointlimit=30 leadlimit=0",_("Score as many frags as you can")); - } - METHOD(Deathmatch, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) - { - return true; - } - ATTRIB(Deathmatch, m_legacydefaults, string, "30 20 0"); -ENDCLASS(Deathmatch) -REGISTER_GAMETYPE(DEATHMATCH, NEW(Deathmatch)); - -CLASS(LastManStanding, Gametype) - INIT(LastManStanding) - { - this.gametype_init(this, _("Last Man Standing"),"lms","g_lms",false,true,"","timelimit=20 lives=5 leadlimit=0",_("Survive and kill until the enemies have no lives left")); - } - METHOD(LastManStanding, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) - { - return true; - } - METHOD(LastManStanding, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Lives:"), 3, 50, 1, "g_lms_lives_override", string_null, string_null); - } - ATTRIB(LastManStanding, m_legacydefaults, string, "9 20 0"); -ENDCLASS(LastManStanding) -REGISTER_GAMETYPE(LMS, NEW(LastManStanding)); - -#ifdef CSQC -void HUD_Mod_Race(vector pos, vector mySize); -#endif -CLASS(Race, Gametype) - INIT(Race) - { - this.gametype_init(this, _("Race"),"rc","g_race",false,true,"","timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line")); - } - METHOD(Race, m_parse_mapinfo, bool(string k, string v)) - { - if (!k) { - cvar_set("g_race_qualifying_timelimit", cvar_defstring("g_race_qualifying_timelimit")); - return true; - } - switch (k) { - case "qualifying_timelimit": - cvar_set("g_race_qualifying_timelimit", v); - return true; - } - return false; - } - METHOD(Race, m_generate_mapinfo, void(Gametype this, string v)) - { - if(v == "trigger_race_checkpoint") - MapInfo_Map_supportedGametypes |= this.m_flags; - } - METHOD(Race, m_isTwoBaseMode, bool()) - { - return true; - } - METHOD(Race, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Laps:"), 1, 25, 1, "g_race_laps_limit", string_null, string_null); - } -#ifdef CSQC - ATTRIB(Race, m_modicons, void(vector pos, vector mySize), HUD_Mod_Race); -#endif - ATTRIB(Race, m_legacydefaults, string, "20 5 7 15 0"); -ENDCLASS(Race) -REGISTER_GAMETYPE(RACE, NEW(Race)); -#define g_race IS_GAMETYPE(RACE) - -CLASS(RaceCTS, Gametype) - INIT(RaceCTS) - { - this.gametype_init(this, _("Race CTS"),"cts","g_cts",false,false,"cloaked","timelimit=20",_("Race for fastest time.")); - } - METHOD(RaceCTS, m_generate_mapinfo, void(Gametype this, string v)) - { - if(v == "target_startTimer") - MapInfo_Map_supportedGametypes |= this.m_flags; - } - METHOD(RaceCTS, m_setTeams, void(string sa)) - { - // this is the skill of the map - // not parsed by anything yet - // for map databases - // cvar_set("fraglimit", sa); - } - METHOD(RaceCTS, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); - } -#ifdef CSQC - ATTRIB(RaceCTS, m_modicons, void(vector pos, vector mySize), HUD_Mod_Race); -#endif - ATTRIB(RaceCTS, m_legacydefaults, string, "20 0 0"); -ENDCLASS(RaceCTS) -REGISTER_GAMETYPE(CTS, NEW(RaceCTS)); -#define g_cts IS_GAMETYPE(CTS) - -CLASS(TeamDeathmatch, Gametype) - INIT(TeamDeathmatch) - { - this.gametype_init(this, _("Team Deathmatch"),"tdm","g_tdm",true,true,"","timelimit=15 pointlimit=50 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team")); - } - METHOD(TeamDeathmatch, m_parse_mapinfo, bool(string k, string v)) - { - if (!k) { - cvar_set("g_tdm_teams", cvar_defstring("g_tdm_teams")); - return true; - } - switch (k) { - case "teams": - cvar_set("g_tdm_teams", v); - return true; - } - return false; - } - METHOD(TeamDeathmatch, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) - { - if(spawnpoints >= 8 && diameter > 4096) - return true; - return false; - } - METHOD(TeamDeathmatch, m_isForcedSupported, bool(Gametype this)) - { - if(cvar("g_tdm_on_dm_maps")) - { - // if this is set, all DM maps support TDM too - if(!(MapInfo_Map_supportedGametypes & this.m_flags) && (MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH.m_flags)) - return true; // TODO: references another gametype (alternatively, we could check which gamemodes are always enabled and append this if any are supported) - } - return false; - } - METHOD(TeamDeathmatch, m_setTeams, void(string sa)) - { - cvar_set("g_tdm_teams", sa); - } - METHOD(TeamDeathmatch, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Point limit:"), 5, 100, 5, "g_tdm_point_limit", "g_tdm_teams_override", _("The amount of points needed before the match will end")); - } - ATTRIB(TeamDeathmatch, m_legacydefaults, string, "50 20 2 0"); -ENDCLASS(TeamDeathmatch) -REGISTER_GAMETYPE(TEAM_DEATHMATCH, NEW(TeamDeathmatch)); -#define g_tdm IS_GAMETYPE(TEAM_DEATHMATCH) - -#ifdef CSQC -void HUD_Mod_CTF(vector pos, vector mySize); -void HUD_Mod_CTF_Reset(); -#endif -CLASS(CaptureTheFlag, Gametype) - INIT(CaptureTheFlag) - { - this.gametype_init(this, _("Capture the Flag"),"ctf","g_ctf",true,true,"","timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it, defend your base from the other team")); - } - METHOD(CaptureTheFlag, m_generate_mapinfo, void(Gametype this, string v)) - { - if(v == "item_flag_team2" || v == "team_CTF_blueflag") - MapInfo_Map_supportedGametypes |= this.m_flags; - } - METHOD(CaptureTheFlag, m_isTwoBaseMode, bool()) - { - return true; - } - METHOD(CaptureTheFlag, m_setTeams, void(string sa)) - { - cvar_set("fraglimit", sa); - } - METHOD(CaptureTheFlag, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Capture limit:"), 1, 20, 1, "capturelimit_override", string_null, _("The amount of captures needed before the match will end")); - } -#ifdef CSQC - ATTRIB(CaptureTheFlag, m_modicons, void(vector pos, vector mySize), HUD_Mod_CTF); - ATTRIB(CaptureTheFlag, m_modicons_reset, void(), HUD_Mod_CTF_Reset); -#endif - ATTRIB(CaptureTheFlag, m_legacydefaults, string, "300 20 10 0"); -ENDCLASS(CaptureTheFlag) -REGISTER_GAMETYPE(CTF, NEW(CaptureTheFlag)); -#define g_ctf IS_GAMETYPE(CTF) - -#ifdef CSQC -void HUD_Mod_CA(vector pos, vector mySize); -#endif -CLASS(ClanArena, Gametype) - INIT(ClanArena) - { - this.gametype_init(this, _("Clan Arena"),"ca","g_ca",true,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=6",_("Kill all enemy teammates to win the round")); - } - METHOD(ClanArena, m_parse_mapinfo, bool(string k, string v)) - { - if (!k) { - cvar_set("g_ca_teams", cvar_defstring("g_ca_teams")); - return true; - } - switch (k) { - case "teams": - cvar_set("g_ca_teams", v); - return true; - } - return false; - } - METHOD(ClanArena, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) - { - if(spawnpoints >= 8 && diameter > 4096) - return true; - return false; - } - METHOD(ClanArena, m_setTeams, void(string sa)) - { - cvar_set("g_ca_teams", sa); - } - METHOD(ClanArena, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Frag limit:"), 5, 100, 5, "fraglimit_override", "g_ca_teams_override", _("The amount of frags needed before the match will end")); - } -#ifdef CSQC - ATTRIB(ClanArena, m_modicons, void(vector pos, vector mySize), HUD_Mod_CA); -#endif - ATTRIB(ClanArena, m_legacydefaults, string, "10 20 0"); -ENDCLASS(ClanArena) -REGISTER_GAMETYPE(CA, NEW(ClanArena)); -#define g_ca IS_GAMETYPE(CA) - -#ifdef CSQC -void HUD_Mod_Dom(vector pos, vector mySize); -#endif -CLASS(Domination, Gametype) - INIT(Domination) - { - this.gametype_init(this, _("Domination"),"dom","g_domination",true,true,"","timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture and defend all the control points to win")); - } - METHOD(Domination, m_parse_mapinfo, bool(string k, string v)) - { - if (!k) { - cvar_set("g_domination_default_teams", cvar_defstring("g_domination_default_teams")); - return true; - } - switch (k) { - case "teams": - cvar_set("g_domination_default_teams", v); - return true; - } - return false; - } - METHOD(Domination, m_generate_mapinfo, void(Gametype this, string v)) - { - if(v == "dom_controlpoint") - MapInfo_Map_supportedGametypes |= this.m_flags; - } - METHOD(Domination, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Point limit:"), 50, 500, 10, "g_domination_point_limit", "g_domination_teams_override", _("The amount of points needed before the match will end")); - } -#ifdef CSQC - ATTRIB(Domination, m_modicons, void(vector pos, vector mySize), HUD_Mod_Dom); -#endif - ATTRIB(Domination, m_legacydefaults, string, "200 20 0"); -ENDCLASS(Domination) -REGISTER_GAMETYPE(DOMINATION, NEW(Domination)); - -#ifdef CSQC -void HUD_Mod_KH(vector pos, vector mySize); -#endif -CLASS(KeyHunt, Gametype) - INIT(KeyHunt) - { - this.gametype_init(this, _("Key Hunt"),"kh","g_keyhunt",true,true,"","timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round")); - } - METHOD(KeyHunt, m_parse_mapinfo, bool(string k, string v)) - { - if (!k) { - cvar_set("g_keyhunt_teams", cvar_defstring("g_keyhunt_teams")); - return true; - } - switch (k) { - case "teams": - cvar_set("g_keyhunt_teams", v); - return true; - } - return false; - } - METHOD(KeyHunt, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) - { - if(spawnpoints >= 12 && diameter > 5120) - return true; - return false; - } - METHOD(KeyHunt, m_setTeams, void(string sa)) - { - cvar_set("g_keyhunt_teams", sa); - } - METHOD(KeyHunt, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Point limit:"), 200, 1500, 50, "g_keyhunt_point_limit", "g_keyhunt_teams_override", _("The amount of points needed before the match will end")); - } -#ifdef CSQC - ATTRIB(KeyHunt, m_modicons, void(vector pos, vector mySize), HUD_Mod_KH); -#endif - ATTRIB(KeyHunt, m_legacydefaults, string, "1000 20 3 0"); -ENDCLASS(KeyHunt) -REGISTER_GAMETYPE(KEYHUNT, NEW(KeyHunt)); - -CLASS(Assault, Gametype) - INIT(Assault) - { - this.gametype_init(this, _("Assault"),"as","g_assault",true,false,"","timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out")); - } - METHOD(Assault, m_generate_mapinfo, void(Gametype this, string v)) - { - if(v == "target_assault_roundend") - MapInfo_Map_supportedGametypes |= this.m_flags; - } - METHOD(Assault, m_isTwoBaseMode, bool()) - { - return true; - } - METHOD(Assault, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); - } - ATTRIB(Assault, m_legacydefaults, string, "20 0"); -ENDCLASS(Assault) -REGISTER_GAMETYPE(ASSAULT, NEW(Assault)); -#define g_assault IS_GAMETYPE(ASSAULT) - -CLASS(Onslaught, Gametype) - INIT(Onslaught) - { - this.gametype_init(this, _("Onslaught"),"ons","g_onslaught",true,false,"","pointlimit=1 timelimit=20",_("Capture control points to reach and destroy the enemy generator")); - } - METHOD(Onslaught, m_generate_mapinfo, void(Gametype this, string v)) - { - if(v == "onslaught_generator") - MapInfo_Map_supportedGametypes |= this.m_flags; - } - METHOD(Onslaught, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); - } - ATTRIB(Onslaught, m_legacydefaults, string, "20 0"); -ENDCLASS(Onslaught) -REGISTER_GAMETYPE(ONSLAUGHT, NEW(Onslaught)); - -#ifdef CSQC -void HUD_Mod_NexBall(vector pos, vector mySize); -#endif -CLASS(NexBall, Gametype) - INIT(NexBall) - { - this.gametype_init(this, _("Nexball"),"nb","g_nexball",true,true,"","timelimit=20 pointlimit=5 leadlimit=0",_("Shoot and kick the ball into the enemies goal, keep your goal clean")); - } - METHOD(NexBall, m_generate_mapinfo, void(Gametype this, string v)) - { - if(substring(v, 0, 8) == "nexball_" || substring(v, 0, 4) == "ball") - MapInfo_Map_supportedGametypes |= this.m_flags; - } - METHOD(NexBall, m_isTwoBaseMode, bool()) - { - return true; - } - METHOD(NexBall, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Goals:"), 1, 50, 1, "g_nexball_goallimit", string_null, _("The amount of goals needed before the match will end")); - } -#ifdef CSQC - ATTRIB(NexBall, m_modicons, void(vector pos, vector mySize), HUD_Mod_NexBall); -#endif - ATTRIB(NexBall, m_legacydefaults, string, "5 20 0"); -ENDCLASS(NexBall) -REGISTER_GAMETYPE(NEXBALL, NEW(NexBall)); -#define g_nexball IS_GAMETYPE(NEXBALL) - -CLASS(FreezeTag, Gametype) - INIT(FreezeTag) - { - this.gametype_init(this, _("Freeze Tag"),"ft","g_freezetag",true,true,"","timelimit=20 pointlimit=10 teams=2 leadlimit=6",_("Kill enemies to freeze them, stand next to frozen teammates to revive them; freeze all enemies to win")); - } - METHOD(FreezeTag, m_parse_mapinfo, bool(string k, string v)) - { - if (!k) { - cvar_set("g_freezetag_teams", cvar_defstring("g_freezetag_teams")); - return true; - } - switch (k) { - case "teams": - cvar_set("g_freezetag_teams", v); - return true; - } - return false; - } - METHOD(FreezeTag, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) - { - if(spawnpoints >= 8 && diameter > 4096) - return true; - return false; - } - METHOD(FreezeTag, m_setTeams, void(string sa)) - { - cvar_set("g_freezetag_teams", sa); - } - METHOD(FreezeTag, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Frag limit:"), 5, 100, 5, "fraglimit_override", "g_freezetag_teams_override", _("The amount of frags needed before the match will end")); - } -#ifdef CSQC - ATTRIB(FreezeTag, m_modicons, void(vector pos, vector mySize), HUD_Mod_CA); -#endif - ATTRIB(FreezeTag, m_legacydefaults, string, "10 20 0"); -ENDCLASS(FreezeTag) -REGISTER_GAMETYPE(FREEZETAG, NEW(FreezeTag)); -#define g_freezetag IS_GAMETYPE(FREEZETAG) - -#ifdef CSQC -void HUD_Mod_Keepaway(vector pos, vector mySize); -#endif -CLASS(Keepaway, Gametype) - INIT(Keepaway) - { - this.gametype_init(this, _("Keepaway"),"ka","g_keepaway",false,true,"","timelimit=20 pointlimit=30",_("Hold the ball to get points for kills")); - } - METHOD(Keepaway, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) - { - return true; - } -#ifdef CSQC - ATTRIB(Keepaway, m_modicons, void(vector pos, vector mySize), HUD_Mod_Keepaway); -#endif -ENDCLASS(Keepaway) -REGISTER_GAMETYPE(KEEPAWAY, NEW(Keepaway)); - -CLASS(Invasion, Gametype) - INIT(Invasion) - { - this.gametype_init(this, _("Invasion"),"inv","g_invasion",false,true,"","pointlimit=50 teams=0 type=0",_("Survive against waves of monsters")); - } - METHOD(Invasion, m_parse_mapinfo, bool(string k, string v)) - { - switch (k) { - case "teams": - cvar_set("g_invasion_teams", v); - return true; - case "type": - cvar_set("g_invasion_type", v); - return true; - } - return false; - } - METHOD(Invasion, m_generate_mapinfo, void(Gametype this, string v)) - { - if(v == "invasion_spawnpoint") - MapInfo_Map_supportedGametypes |= this.m_flags; - } - METHOD(Invasion, m_configuremenu, void(Gametype this, entity menu, void(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip) returns)) - { - TC(Gametype, this); - returns(menu, _("Point limit:"), 50, 500, 10, string_null, string_null, string_null); - } -ENDCLASS(Invasion) -REGISTER_GAMETYPE(INVASION, NEW(Invasion)); - -CLASS(Duel, Gametype) - INIT(Duel) - { - this.gametype_init(this, _("Duel"),"duel","g_duel",false,true,"","timelimit=10 pointlimit=0 leadlimit=0",_("Fight in a one versus one arena battle to decide the winner")); - } - METHOD(Duel, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) - { - return (diameter < 16384); - } - METHOD(Duel, m_isForcedSupported, bool(Gametype this)) - { - if(!cvar("g_duel_not_dm_maps")) - { - // if this is set, all DM maps support duel too - // TODO: we should really check the size of maps, some DM maps do not work for duel! - if(!(MapInfo_Map_supportedGametypes & this.m_flags) && (MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH.m_flags)) - return true; // TODO: references another gametype (alternatively, we could check which gamemodes are always enabled and append this if any are supported) - } - return false; - } -ENDCLASS(Duel) -REGISTER_GAMETYPE(DUEL, NEW(Duel)); -#define g_duel IS_GAMETYPE(DUEL) - const int MAPINFO_FEATURE_WEAPONS = 1; // not defined for instagib-only maps const int MAPINFO_FEATURE_VEHICLES = 2; const int MAPINFO_FEATURE_TURRETS = 4; diff --git a/qcsrc/common/mapobjects/teleporters.qc b/qcsrc/common/mapobjects/teleporters.qc index 987347283f..ab9c8dca57 100644 --- a/qcsrc/common/mapobjects/teleporters.qc +++ b/qcsrc/common/mapobjects/teleporters.qc @@ -16,7 +16,7 @@ #include "../deathtypes/all.qh" #include "../turrets/sv_turrets.qh" #include "../vehicles/all.qh" - #include "../mapinfo.qh" + #include #include #endif diff --git a/qcsrc/common/mutators/mutator/instagib/sv_instagib.qh b/qcsrc/common/mutators/mutator/instagib/sv_instagib.qh index 1f74f1fe53..723a3ccbc6 100644 --- a/qcsrc/common/mutators/mutator/instagib/sv_instagib.qh +++ b/qcsrc/common/mutators/mutator/instagib/sv_instagib.qh @@ -1,6 +1,7 @@ #pragma once #include "items.qh" +#include float autocvar_g_instagib_invis_alpha; int autocvar_g_instagib_extralives; diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index 3567a2b095..ae0c2ae77a 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -7,12 +7,14 @@ #include "notifications/all.qh" #include "scores.qh" #include + #include #elif defined(MENUQC) #elif defined(SVQC) #include "constants.qh" #include #include "notifications/all.qh" #include + #include #include "scores.qh" #include "mapinfo.qh" #endif diff --git a/qcsrc/menu/xonotic/dialog_singleplayer.qc b/qcsrc/menu/xonotic/dialog_singleplayer.qc index b2ae8c0ba9..717fe524bb 100644 --- a/qcsrc/menu/xonotic/dialog_singleplayer.qc +++ b/qcsrc/menu/xonotic/dialog_singleplayer.qc @@ -1,6 +1,6 @@ #include "dialog_singleplayer.qh" -#include +#include #include "bigbutton.qh" #include "radiobutton.qh" #include "textlabel.qh" diff --git a/qcsrc/menu/xonotic/gametypelist.qc b/qcsrc/menu/xonotic/gametypelist.qc index 2de655940f..da495b91c9 100644 --- a/qcsrc/menu/xonotic/gametypelist.qc +++ b/qcsrc/menu/xonotic/gametypelist.qc @@ -1,6 +1,7 @@ #include "gametypelist.qh" #include "dialog_multiplayer_create.qh" +#include #include entity makeXonoticGametypeList() diff --git a/qcsrc/menu/xonotic/util.qc b/qcsrc/menu/xonotic/util.qc index c0a8c6b2b5..ac993e622b 100644 --- a/qcsrc/menu/xonotic/util.qc +++ b/qcsrc/menu/xonotic/util.qc @@ -6,7 +6,7 @@ #include "../menu.qh" #include #include -#include +#include #include #include diff --git a/qcsrc/server/bot/default/waypoints.qc b/qcsrc/server/bot/default/waypoints.qc index da407cbbc8..b4e6df09c6 100644 --- a/qcsrc/server/bot/default/waypoints.qc +++ b/qcsrc/server/bot/default/waypoints.qc @@ -13,6 +13,7 @@ #include #include +#include #include #include #include diff --git a/qcsrc/server/command/getreplies.qc b/qcsrc/server/command/getreplies.qc index b768ccb7e8..3e75b5b6f1 100644 --- a/qcsrc/server/command/getreplies.qc +++ b/qcsrc/server/command/getreplies.qc @@ -9,8 +9,8 @@ #include "../race.qh" #include +#include #include -#include #include #include diff --git a/qcsrc/server/compat/quake3.qc b/qcsrc/server/compat/quake3.qc index 4d469b455d..73bf3c375f 100644 --- a/qcsrc/server/compat/quake3.qc +++ b/qcsrc/server/compat/quake3.qc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index 274378f17e..b9dc7c3d20 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -27,6 +27,7 @@ #include "../common/playerstats.qh" #include "../common/teams.qh" #include "../common/util.qh" +#include #include #include #include "../lib/csqcmodel/sv_model.qh" diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 7231bd8f6f..8044eaf8ef 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -23,6 +23,7 @@ #include "../common/constants.qh" #include #include "../common/deathtypes/all.qh" +#include #include "../common/gamemodes/sv_rules.qh" #include "../common/mapinfo.qh" #include "../common/monsters/_mod.qh" diff --git a/qcsrc/server/impulse.qc b/qcsrc/server/impulse.qc index 62acd99d8d..090b239cc8 100644 --- a/qcsrc/server/impulse.qc +++ b/qcsrc/server/impulse.qc @@ -9,6 +9,8 @@ #include "weapons/tracing.qh" #include "weapons/weaponsystem.qh" +#include + #include #include "../common/minigames/sv_minigames.qh" diff --git a/qcsrc/server/race.qc b/qcsrc/server/race.qc index 32fdbba172..43443a11ff 100644 --- a/qcsrc/server/race.qc +++ b/qcsrc/server/race.qc @@ -10,7 +10,7 @@ #include "command/getreplies.qh" #include "../common/deathtypes/all.qh" #include "../common/notifications/all.qh" -#include "../common/mapinfo.qh" +#include #include #include #include diff --git a/qcsrc/server/spawnpoints.qc b/qcsrc/server/spawnpoints.qc index 0e270d30d1..3dc76afc0d 100644 --- a/qcsrc/server/spawnpoints.qc +++ b/qcsrc/server/spawnpoints.qc @@ -8,7 +8,7 @@ #include "../common/constants.qh" #include #include "../common/teams.qh" -#include +#include #include "../common/mapobjects/subs.qh" #include "../common/mapobjects/target/spawnpoint.qh" #include "../common/util.qh" -- 2.39.2