Added Capture The Flag game mode.

This commit is contained in:
Marco Cawthorne 2023-06-07 13:55:36 -07:00
parent e57b138438
commit fbcc868870
Signed by: eukara
GPG Key ID: CE2032F0A2882A22
40 changed files with 1939 additions and 497 deletions

38
src/client/cmds.qc Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void VGUI_ChooseClass(float);
int
ClientGame_ConsoleCommand(void)
{
switch(argv(0)) {
case "changeteam":
if (OP4_IsCTF()) {
VGUI_ChooseTeam();
} else {
sendevent("HLDM_Chooseteam", "s", argv(1));
}
break;
case "changeclass":
if (OP4_IsCTF())
VGUI_ChooseClass(0);
break;
default:
return (0);
}
return (1);
}

34
src/client/defs_op4.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var string g_ctfhud1_spr;
var string g_ctfhud2_spr;
var string g_ofhud1_spr;
var string g_ofhud2_spr;
var string g_ofhud3_spr;
var string g_ofhud4_spr;
var string g_ofhud5_spr;
var string g_ofhud6_spr;
var string g_ofch1_spr;
var string g_ofch2_spr;
bool
OP4_IsCTF(void)
{
return serverkeyfloat("ctf") == 0 ? false : true;
}

View File

@ -14,6 +14,63 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void HUD_DrawNums(float fNumber, vector vecPos, float fAlpha, vector vColor);
void
OP4CTF_DrawHud(player pl)
{
vector iconPos;
vector iconBMOfs;
vector iconOP4Ofs;
bool myTeam = getplayerkeyfloat(player_localnum, "*team");
iconPos = g_hudmins + [16, g_hudres[1] - 128];
if (serverkeyfloat("ctfflag_1") == CTFFLAG_IDLE)
iconBMOfs = [67/256, 77/256];
else if (serverkeyfloat("ctfflag_1") == CTFFLAG_TAKEN && myTeam == 1)
iconBMOfs = [105/256, 77/256];
else if (serverkeyfloat("ctfflag_1") == CTFFlAG_MISSING)
iconBMOfs = [143/256, 77/256];
else if (serverkeyfloat("ctfflag_1") == CTFFLAG_TAKEN )
iconBMOfs = [181/256, 77/256];
if (serverkeyfloat("ctfflag_2") == CTFFLAG_IDLE)
iconOP4Ofs = [67/256, 77/256];
else if (serverkeyfloat("ctfflag_2") == CTFFLAG_TAKEN && myTeam == 2)
iconOP4Ofs = [105/256, 77/256];
else if (serverkeyfloat("ctfflag_2") == CTFFlAG_MISSING)
iconOP4Ofs = [143/256, 77/256];
else if (serverkeyfloat("ctfflag_2") == CTFFLAG_TAKEN)
iconOP4Ofs = [181/256, 77/256];
/* black mesa team flag */
drawsubpic(
iconPos,
[38, 38],
g_ctfhud1_spr,
iconBMOfs,
[38/256, 38/256],
[1,1,0],
1.0f,
DRAWFLAG_ADDITIVE
);
HUD_DrawNums(serverkeyfloat("teamscore_1"), iconPos + [64, 6], 1.0, [1,1,0]);
/* opfor team flag */
drawsubpic(
iconPos + [0, 38],
[38, 38],
g_ctfhud1_spr,
iconOP4Ofs,
[38/256, 38/256],
[0,1,0],
1.0f,
DRAWFLAG_ADDITIVE
);
HUD_DrawNums(serverkeyfloat("teamscore_2"), iconPos + [64, 44], 1.0, [0,1,0]);
}
void
ClientGame_PreDraw(void)
{
@ -24,4 +81,77 @@ void
ClientGame_PostDraw(void)
{
Nightvision_PostDraw();
/* CTF Power-Up icons */
{
player pl = (player)pSeat->m_ePlayer;
vector pickupPos;
pickupPos = g_hudmins + [16, (g_hudres[1] / 2) - 32];
if (OP4_IsCTF()) {
OP4CTF_DrawHud(pl);
}
if (pl.g_items & ITEM_CTF_HEALTH) {
drawsubpic(
pickupPos,
[64, 64],
g_ctfhud1_spr,
[0, 0],
[0.25, 0.25],
[0,1,0],
1.0f,
DRAWFLAG_ADDITIVE
);
}
if (pl.g_items & ITEM_CTF_DEATH) {
drawsubpic(
pickupPos,
[64, 64],
g_ctfhud1_spr,
[0.25, 0],
[0.25, 0.25],
[1,0,0],
1.0f,
DRAWFLAG_ADDITIVE
);
}
if (pl.g_items & ITEM_CTF_JUMPPACK) {
drawsubpic(
pickupPos,
[64, 64],
g_ctfhud1_spr,
[0.5, 0],
[0.25, 0.25],
[1,0.5,0],
1.0f,
DRAWFLAG_ADDITIVE
);
}
if (pl.g_items & ITEM_CTF_SHIELD) {
drawsubpic(
pickupPos,
[64, 64],
g_ctfhud1_spr,
[0.75, 0],
[0.25, 0.25],
[0.25,0.25,1],
1.0f,
DRAWFLAG_ADDITIVE
);
}
if (pl.g_items & ITEM_CTF_BACKPACK) {
drawsubpic(
pickupPos,
[64, 64],
g_ctfhud1_spr,
[0, 0.25],
[0.25, 0.25],
[1,1,0],
1.0f,
DRAWFLAG_ADDITIVE
);
}
}
}

View File

@ -15,7 +15,7 @@
*/
float(entity foo, float chanid) getchannellevel = #0;
void VGUI_ChooseTeam(void);
/*
=================
@ -27,12 +27,17 @@ Comparable to worldspawn in SSQC in that it's mostly used for precaches
void
ClientGame_Init(float apilevel, string enginename, float engineversion)
{
registercommand("changeteam");
registercommand("changeclass");
Obituary_Init();
}
void
ClientGame_InitDone(void)
{
if (OP4_IsCTF()) {
VGUI_ChooseTeam();
}
}
void
@ -49,16 +54,19 @@ ClientGame_RendererRestart(string rstr)
FX_Spark_Init();
FX_Impact_Init();
precache_model("sprites/640hudof01.spr");
precache_model("sprites/640hudof02.spr");
precache_model("sprites/640hudof03.spr");
precache_model("sprites/640hudof04.spr");
precache_model("sprites/640hudof05.spr");
precache_model("sprites/640hudof06.spr");
precache_model("sprites/ofch1.spr");
precache_model("sprites/ofch2.spr");
g_ofhud1_spr = spriteframe("sprites/640hudof01.spr", 0, 0.0f);
g_ofhud2_spr = spriteframe("sprites/640hudof02.spr", 0, 0.0f);
g_ofhud3_spr = spriteframe("sprites/640hudof03.spr", 0, 0.0f);
g_ofhud4_spr = spriteframe("sprites/640hudof04.spr", 0, 0.0f);
g_ofhud5_spr = spriteframe("sprites/640hudof05.spr", 0, 0.0f);
g_ofhud6_spr = spriteframe("sprites/640hudof06.spr", 0, 0.0f);
g_ofch1_spr = spriteframe("sprites/ofch1.spr", 0, 0.0f);
g_ofch2_spr = spriteframe("sprites/ofch2.spr", 0, 0.0f);
precache_model("sprites/320hudof01.spr");
g_ctfhud1_spr = spriteframe("sprites/ctf_hud1.spr", 0, 0.0f);
g_ctfhud2_spr = spriteframe("sprites/ctf_hud1.spr", 0, 0.0f);
/* there's also muzzleflash.spr, but that's just MUZZLE_SMALL again */
MUZZLE_RIFLE = (int)getmodelindex("sprites/muzzleflash1.spr");
MUZZLE_SMALL = (int)getmodelindex("sprites/muzzleflash2.spr");

View File

@ -12,6 +12,7 @@
../../../src/shared/defs.h
../../../valve/src/client/defs.h
../../../src/client/defs.h
defs_op4.h
../../../src/vgui/include.src
@ -25,7 +26,7 @@ nightvision.qc
draw.qc
init.qc
../../../valve/src/client/entities.qc
../../../valve/src/client/cmds.qc
cmds.qc
../../../valve/src/client/game_event.qc
../../../valve/src/client/camera.qc
../../../valve/src/client/viewmodel.qc
@ -40,5 +41,7 @@ hud_weaponselect.qc
../../../valve/src/client/modelevent.qc
../../../src/client/include.src
vgui_changechar.qc
vgui_chooseteam.qc
../../../src/shared/include.src
#endlist

View File

@ -0,0 +1,304 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
static string g_charDescrAdrian;
static string g_charDescrBarney;
static string g_charDescrCivRandom;
static string g_charDescrCleansuit;
static string g_charDescrDrillsgt;
static string g_charDescrGina;
static string g_charDescrGordon;
static string g_charDescrGrunt;
static string g_charDescrRandom;
static string g_charDescrOtis;
static string g_charDescrTandom;
static string g_charDescrRecruit;
static string g_charDescrScientist;
static string g_charDescrSquadleader;
static string g_charDescrTower;
static void
OP4Char_Init(void)
{
g_charDescrAdrian = textfile_to_string("classes/short_adrian.txt");
g_charDescrBarney = textfile_to_string("classes/short_barney.txt");
g_charDescrCivRandom = textfile_to_string("classes/short_civ_random.txt");
g_charDescrCleansuit = textfile_to_string("classes/short_cleansuit.txt");
g_charDescrDrillsgt = textfile_to_string("classes/short_drillsgt.txt");
g_charDescrGina = textfile_to_string("classes/short_gina.txt");
g_charDescrGordon = textfile_to_string("classes/short_gordon.txt");
g_charDescrGrunt = textfile_to_string("classes/short_grunt.txt");
g_charDescrRandom = textfile_to_string("classes/short_op4_random.txt");
g_charDescrOtis = textfile_to_string("classes/short_otis.txt");
g_charDescrTandom = textfile_to_string("classes/short_random.txt");
g_charDescrRecruit = textfile_to_string("classes/short_recruit.txt");
g_charDescrScientist = textfile_to_string("classes/short_scientist.txt");
g_charDescrSquadleader = textfile_to_string("classes/short_squadleader.txt");
g_charDescrTower = textfile_to_string("classes/short_tower.txt");
}
static VGUIWindow winCharSelection;
static VGUIPic imgCharPreview;
static VGUILabel lblCharTitle;
static VGUILabel lblCharDescription;
static VGUILabel lblCharCounter;
class OP4CharButton:VGUIButton
{
void OP4CharButton(void);
virtual void OnMouseUp(void);
virtual void OnMouseEntered(void);
};
void
OP4CharButton::OP4CharButton(void)
{
}
void
OP4CharButton::OnMouseUp(void)
{
int classSelection = GetTag();
sendevent("ClassJoin", "f", (float)classSelection);
winCharSelection.Hide();
}
void
OP4CharButton::OnMouseEntered(void)
{
int classSelection = GetTag();
switch (classSelection) {
case 1:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Barney"));
imgCharPreview.SetImage("gfx/vgui/640_barney");
lblCharDescription.SetTitle(g_charDescrBarney);
break;
case 2:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Cleansuit"));
imgCharPreview.SetImage("gfx/vgui/640_cleansuit");
lblCharDescription.SetTitle(g_charDescrCleansuit);
break;
case 3:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Gina"));
imgCharPreview.SetImage("gfx/vgui/640_gina");
lblCharDescription.SetTitle(g_charDescrGina);
break;
case 4:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Gordon"));
imgCharPreview.SetImage("gfx/vgui/640_gordon");
lblCharDescription.SetTitle(g_charDescrGordon);
break;
case 5:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Otis"));
imgCharPreview.SetImage("gfx/vgui/640_otis");
lblCharDescription.SetTitle(g_charDescrOtis);
break;
case 6:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Scientist"));
imgCharPreview.SetImage("gfx/vgui/640_scientist");
lblCharDescription.SetTitle(g_charDescrScientist);
break;
case 0:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Civ_Random"));
imgCharPreview.SetImage("gfx/vgui/640_civ_random");
lblCharDescription.SetTitle(g_charDescrCivRandom);
break;
case 7:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_SquadLeader"));
imgCharPreview.SetImage("gfx/vgui/640_squadleader");
lblCharDescription.SetTitle(g_charDescrSquadleader);
break;
case 8:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_DrillSgt"));
imgCharPreview.SetImage("gfx/vgui/640_drillsgt");
lblCharDescription.SetTitle(g_charDescrDrillsgt);
break;
case 9:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Grunt"));
imgCharPreview.SetImage("gfx/vgui/640_grunt");
lblCharDescription.SetTitle(g_charDescrGrunt);
break;
case 10:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Recruit"));
imgCharPreview.SetImage("gfx/vgui/640_recruit");
lblCharDescription.SetTitle(g_charDescrRecruit);
break;
case 11:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Adrian"));
imgCharPreview.SetImage("gfx/vgui/640_adrian");
lblCharDescription.SetTitle(g_charDescrAdrian);
break;
case 12:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Tower"));
imgCharPreview.SetImage("gfx/vgui/640_tower");
lblCharDescription.SetTitle(g_charDescrTower);
break;
case 13:
lblCharTitle.SetTitle(Titles_GetTextBody("CTFTitle_Op4_Random"));
imgCharPreview.SetImage("gfx/vgui/640_op4_random");
lblCharDescription.SetTitle(g_charDescrTandom);
break;
}
}
/*
Char/Char list:
Barney
CleansuitSci
Gina
Freeman
Otis
Walter(Scientist)
Random
Squad Leader
Drill Sgt
Grunt
Recruit
Shepard
Tower
OP4Random
*/
string g_classnames_blackmesa [] = {
"Barney",
"Cleansuit",
"Gina",
"Gordon",
"Otis",
"Scientist",
"Civ_Random"
};
string g_classnames_opfor [] = {
"SquadLeader",
"DrillSgt",
"Grunt",
"Recruit",
"Adrian",
"Tower",
"Op4_Random"
};
void
VGUI_ChooseClass(float teamChoice)
{
static int initialized;
static OP4CharButton *btns;
static VGUILabel lblSelectChar;
static VGUIFrame frmCharInfo;
if (!teamChoice)
teamChoice = getplayerkeyfloat(player_localnum, "*team");
if (!initialized) {
vector btnpos = [40,80];
initialized = TRUE;
OP4Char_Init();
winCharSelection = spawn(VGUIWindow);
winCharSelection.SetSize([640, 480]);
winCharSelection.SetStyleMask(VGUIWindowBorderless | VGUIWindowFullscreen);
lblSelectChar = spawn(VGUILabel);
lblSelectChar.SetTitle(Titles_GetTextBody("CTFTitle_SelectYourCharacter"));
lblSelectChar.SetTextSize(19);
lblSelectChar.SetPos([40, 38]);
lblSelectChar.SetSize([400, 24]);
frmCharInfo = spawn(VGUIFrame);
frmCharInfo.SetPos([176, 80]);
frmCharInfo.SetSize([424, 312]);
imgCharPreview = spawn(VGUIPic);
imgCharPreview.SetPos([190, 90]);
lblCharTitle = spawn(VGUILabel);
lblCharTitle.SetPos([338, 90]);
lblCharTitle.SetTextSize(19);
lblCharTitle.SetSize([320, 24]);
lblCharCounter = spawn(VGUILabel);
lblCharCounter.SetPos([338, 90 + 32]);
lblCharCounter.SetSize([320, 18]);
lblCharDescription = spawn(VGUILabel);
lblCharDescription.SetPos([338, 90 + 32 + 32]);
lblCharDescription.SetSize([250, 240]);
g_uiDesktop.Add(winCharSelection);
winCharSelection.Add(lblSelectChar);
winCharSelection.Add(frmCharInfo);
winCharSelection.Add(imgCharPreview);
winCharSelection.Add(lblCharTitle);
winCharSelection.Add(lblCharCounter);
winCharSelection.Add(lblCharDescription);
btns = memalloc(sizeof(OP4CharButton) * g_classnames_blackmesa.length);
for (int i = 0; i < g_classnames_blackmesa.length; i++) {
btns[i] = spawn(OP4CharButton);
btns[i].SetTitle(Titles_GetTextBody(g_classnames_blackmesa[i]));
btns[i].SetSize([124, 24]);
btns[i].SetPos(btnpos);
if (i == 7) {
btns[i].SetKeyEquivalent("0");
btns[i].SetTag(0);
} else {
btns[i].SetKeyEquivalent(ftos((float)i+1));
btns[i].SetTag(i+1i);
}
winCharSelection.Add(btns[i]);
btnpos[1] += 32;
}
}
/* relabel the buttons for the currently selected team. */
for (int i = 0; i < g_classnames_blackmesa.length; i++) {
if (teamChoice == 1) {
btns[i].SetTitle(Titles_GetTextBody(g_classnames_blackmesa[i]));
if (i == 6) {
btns[i].SetKeyEquivalent("0");
btns[i].SetTag(0);
} else {
btns[i].SetKeyEquivalent(ftos((float)i+1));
btns[i].SetTag(i+1i);
}
} else {
btns[i].SetTitle(Titles_GetTextBody(g_classnames_opfor[i]));
if (i == 6) {
btns[i].SetTag(13);
btns[i].SetKeyEquivalent("0");
} else {
btns[i].SetTag(6 + i+1i);
btns[i].SetKeyEquivalent(ftos((float)i+1));
}
}
}
winCharSelection.Show();
winCharSelection.SetPos((video_res / 2) - (winCharSelection.GetSize() / 2));
}

View File

@ -0,0 +1,165 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
static VGUIWindow winChooseTeam;
class OP4TeamButton:VGUIButton
{
void OP4TeamButton(void);
virtual void OnMouseUp(void);
};
void
OP4TeamButton::OP4TeamButton(void)
{
}
void
OP4TeamButton::OnMouseUp(void)
{
int tag = GetTag();
VGUI_ChooseClass(tag);
sendevent("TeamJoin", "f", (float)tag);
winChooseTeam.Hide();
}
string
VGUI_ChooseTeam_MapInfo(void)
{
static string mapinfo = __NULL__;
if (mapinfo != __NULL__)
return mapinfo;
filestream fileMap = fopen(strcat("maps/", mapname, ".txt"), FILE_READ);
string temp;
if (fileMap != -1) {
while ((temp = fgets(fileMap))) {
mapinfo = strcat(mapinfo, temp, "\n");
}
} else {
mapinfo = Titles_GetTextBody("Map_Description_not_available");
}
return mapinfo;
}
void
VGUI_ChooseTeam(void)
{
static int initialized;
static VGUIButton btnAutoAssign;
static VGUIButton btnGoSpectator;
static VGUIFrame frmMapInfo;
static VGUILabel lblSelectTeam;
static VGUILabel lblMapName;
static VGUILabel lblMapInfo;
static void VGUI_AutoAssign(void) {
float tag = (random() < 0.5) ? 1 : 2;
VGUI_ChooseClass(tag);
sendevent("TeamJoin", "f", tag);
winChooseTeam.Hide();
}
static void VGUI_GoSpectator(void) {
sendevent("TeamJoin", "f", 0);
winChooseTeam.Hide();
}
if (!initialized) {
vector btnpos = [40,80];
initialized = TRUE;
winChooseTeam = spawn(VGUIWindow);
winChooseTeam.SetSize('640 480');
winChooseTeam.SetStyleMask(VGUIWindowBorderless | VGUIWindowFullscreen);
lblSelectTeam = spawn(VGUILabel);
lblSelectTeam.SetTitle(Titles_GetTextBody("CTFTitle_SelectYourTeam"));
lblSelectTeam.SetTextSize(19);
lblSelectTeam.SetPos([40, 38]);
lblSelectTeam.SetSize('400 24');
frmMapInfo = spawn(VGUIFrame);
frmMapInfo.SetPos('176 80');
frmMapInfo.SetSize('424 312');
lblMapName = spawn(VGUILabel);
lblMapName.SetTitle(mapname);
lblMapName.SetTextSize(19);
lblMapName.SetPos('194 105');
lblMapName.SetSize('250 312');
lblMapInfo = spawn(VGUILabel);
lblMapInfo.SetTitle(VGUI_ChooseTeam_MapInfo());
lblMapInfo.SetPos('194 129');
lblMapInfo.SetSize('375 250');
for (int t = 1; t <= serverkeyfloat("teams"); t++) {
OP4TeamButton btnForTeam;
string team_name = serverkey(sprintf("team_%i", t));
btnForTeam = spawn(OP4TeamButton);
btnForTeam.SetTitle(team_name);
btnForTeam.SetPos(btnpos);
btnForTeam.SetKeyEquivalent(ftos((float)t));
btnForTeam.SetSize('124 24');
switch (team_name) {
case "Black Mesa":
btnForTeam.SetTag(1);
break;
case "Opposing Force":
btnForTeam.SetTag(2);
break;
}
winChooseTeam.Add(btnForTeam);
btnpos[1] += 32;
}
btnAutoAssign = spawn(VGUIButton);
btnAutoAssign.SetTitle(Titles_GetTextBody("CTFTeam_AutoAssign"));
btnAutoAssign.SetPos(btnpos);
btnAutoAssign.SetSize('124 24');
btnAutoAssign.SetKeyEquivalent("5");
btnAutoAssign.SetFunc(VGUI_AutoAssign);
btnpos[1] += 32;
btnGoSpectator = spawn(VGUIButton);
btnGoSpectator.SetTitle(Titles_GetTextBody("CTFMenu_Spectate"));
btnGoSpectator.SetPos(btnpos);
btnGoSpectator.SetSize('124 24');
btnGoSpectator.SetKeyEquivalent("6");
btnGoSpectator.SetFunc(VGUI_GoSpectator);
g_uiDesktop.Add(winChooseTeam);
winChooseTeam.Add(frmMapInfo);
winChooseTeam.Add(lblSelectTeam);
winChooseTeam.Add(lblMapName);
winChooseTeam.Add(lblMapInfo);
winChooseTeam.Add(btnAutoAssign);
winChooseTeam.Add(btnGoSpectator);
}
winChooseTeam.Show();
winChooseTeam.SetPos((video_res / 2) - (winChooseTeam.GetSize() / 2));
}

96
src/server/ctfitem.qc Normal file
View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class OP4CTFItem:NSRenderableEntity
{
public:
void OP4CTFItem(void);
virtual void Respawn(void);
virtual void Touch(entity);
nonvirtual bool CanPlayerGrabPowerup(entity);
virtual void SpawnKey(string, string);
private:
int m_iItemID;
float m_iTeamID;
};
void
OP4CTFItem::OP4CTFItem(void)
{
m_iItemID = 0i;
}
void
OP4CTFItem::Respawn(void)
{
SetSolid(SOLID_TRIGGER);
SetMovetype(MOVETYPE_NONE);
SetOrigin(GetSpawnOrigin());
SetModel(GetSpawnModel());
SetSize([-16, -16, 0], [16, 16, 72]);
DropToFloor();
}
void
OP4CTFItem::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "goal_no":
m_iTeamID = ReadFloat(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
OP4CTFItem::Touch(entity toucherEntity)
{
player pl = (player)toucherEntity;
if (!m_iItemID)
return;
if (!(toucherEntity.flags & FL_CLIENT))
return;
if (CanPlayerGrabPowerup(toucherEntity) == false)
return;
pl.g_items |= m_iItemID; /* add to inventory */
Destroy();
}
bool
OP4CTFItem::CanPlayerGrabPowerup(entity playerEntity)
{
player pl = (player)playerEntity;
if (pl.g_items & ITEM_CTF_JUMPPACK)
return false;
if (pl.g_items & ITEM_CTF_SHIELD)
return false;
if (pl.g_items & ITEM_CTF_HEALTH)
return false;
if (pl.g_items & ITEM_CTF_DEATH)
return false;
if (pl.g_items & ITEM_CTF_BACKPACK)
return false;
return true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -18,3 +18,4 @@
#include "gamerules_ctf.h"
#include "../../../valve/src/server/items.h"
#include "../../../valve/src/server/flashlight.h"
#include "../../../valve/src/server/HLXenMonster.h"

View File

@ -180,6 +180,32 @@ TriggerFlashlight(NSClient target)
self = oldself;
}
void
DropCTFItem(NSClientPlayer pl)
{
string item;
if (pl.classname != "player")
return;
if (pl.g_items & ITEM_CTF_JUMPPACK) {
item = "item_ctflongjump";
pl.g_items &= ~ ITEM_CTF_JUMPPACK;
} else if (pl.g_items & ITEM_CTF_SHIELD) {
item = "item_ctfportablehev";
pl.g_items &= ~ ITEM_CTF_SHIELD;
} else if (pl.g_items & ITEM_CTF_HEALTH) {
item = "item_ctfregeneration";
pl.g_items &= ~ ITEM_CTF_HEALTH;
} else if (pl.g_items & ITEM_CTF_DEATH) {
item = "item_ctfaccelerator";
pl.g_items &= ~ ITEM_CTF_DEATH;
} else if (pl.g_items & ITEM_CTF_BACKPACK) {
item = "item_ctfbackpack";
pl.g_items &= ~ ITEM_CTF_BACKPACK;
}
}
bool
HLGameRules::ImpulseCommand(NSClient bp, float num)
{
@ -187,6 +213,9 @@ HLGameRules::ImpulseCommand(NSClient bp, float num)
case 100:
TriggerFlashlight(bp);
break;
case 205:
DropCTFItem((player)bp);
break;
default:
return super::ImpulseCommand(bp, num);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -14,14 +14,15 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class OP4CTFRules:HLGameRules
class OP4CTFRules:HLMultiplayerRules
{
int m_iIntermission;
int m_iIntermissionTime;
void OP4CTFRules(void);
virtual void(void) FrameStart;
virtual void InitPostEnts(void);
virtual void PlayerSpawn(NSClientPlayer);
virtual void PlayerDeath(NSClientPlayer);
/* client */
virtual void(NSClientPlayer) PlayerSpawn;
virtual void(NSClientPlayer) PlayerDeath;
nonvirtual void CharacterSpawn(NSClientPlayer, string);
nonvirtual void CaptureFlag(NSClientPlayer);
nonvirtual void DropFlag(NSClientPlayer);
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -15,70 +15,35 @@
*/
void
OP4CTFRules::FrameStart(void)
OP4CTFRules::OP4CTFRules(void)
{
if (cvar("mp_timelimit"))
if (time >= (cvar("mp_timelimit") * 60)) {
IntermissionStart();
}
}
void
OP4CTFRules::PlayerDeath(NSClientPlayer pp)
OP4CTFRules::InitPostEnts(void)
{
player pl = (player)pp;
FX_Corpse_Spawn((player)g_dmg_eAttacker, ANIM_DIESIMPLE);
/* Opfor CTF only has two teams. */
forceinfokey(world, "teams", "2");
forceinfokey(world, "team_1", "Black Mesa");
forceinfokey(world, "teamscore_1", "0");
forceinfokey(world, "team_2", "Opposing Force");
forceinfokey(world, "teamscore_2", "0");
/* obituary networking */
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_OBITUARY);
if (g_dmg_eAttacker.netname)
WriteString(MSG_MULTICAST, g_dmg_eAttacker.netname);
else
WriteString(MSG_MULTICAST, g_dmg_eAttacker.classname);
WriteString(MSG_MULTICAST, pl.netname);
WriteByte(MSG_MULTICAST, g_dmg_iWeapon);
WriteByte(MSG_MULTICAST, 0);
msg_entity = world;
multicast([0,0,0], MULTICAST_ALL);
forceinfokey(world, "ctfflag_1", "0");
forceinfokey(world, "ctfflag_2", "0");
/* death-counter */
pl.deaths++;
forceinfokey(pl, "*deaths", ftos(pl.deaths));
Sound_Precache("op4ctf_bm.flag_taken");
Sound_Precache("op4ctf_bm.flag_capture");
/* update score-counter */
if (pl.flags & FL_CLIENT || pl.flags & FL_MONSTER)
if (g_dmg_eAttacker.flags & FL_CLIENT) {
if (pl == g_dmg_eAttacker)
g_dmg_eAttacker.frags--;
else
g_dmg_eAttacker.frags++;
}
Sound_Precache("op4ctf_op4.flag_taken");
Sound_Precache("op4ctf_op4.flag_capture");
}
/* in DM we only care about the frags */
if (cvar("mp_fraglimit"))
if (g_dmg_eAttacker.frags >= cvar("mp_fraglimit")) {
IntermissionStart();
}
weaponbox_spawn(pl);
pl.movetype = MOVETYPE_NONE;
pl.solid = SOLID_NOT;
pl.takedamage = DAMAGE_NO;
pl.gflags &= ~GF_FLASHLIGHT;
pl.armor = pl.activeweapon = pl.g_items = 0;
pl.think = PutClientInServer;
pl.nextthink = time + 4.0f;
Sound_Play(pl, CHAN_AUTO, "player.die");
if (pl.health < -50) {
pl.health = 0;
FX_GibHuman(pl.origin, vectoangles(pl.origin - g_dmg_eAttacker.origin), g_dmg_iDamage * 2.0f);
return;
}
pl.health = 0;
void
OP4CTFRules::PlayerDisconnect(NSClientPlayer pl)
{
DropFlag(pl);
super::PlayerDisconnect(pl);
}
void
@ -86,48 +51,201 @@ OP4CTFRules::PlayerSpawn(NSClientPlayer pp)
{
player pl = (player)pp;
/* this is where the mods want to deviate */
entity spot;
/* not in a team yet, force them into spectator */
if (pl.team == 0) {
pl.MakeTempSpectator(); /* replace this with a non-spectator ghost */
Spawn_ObserverCam(pl);
return;
}
pl.classname = "player";
CharacterSpawn(pp, pl.m_oldModel);
}
void
OP4CTFRules::CharacterSpawn(NSClientPlayer playerEnt, string playerModel)
{
player pl = (player)playerEnt;
pl.m_oldModel = playerModel;
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.SetTakedamage(DAMAGE_YES);
pl.SetSolid(SOLID_SLIDEBOX);
pl.SetMovetype(MOVETYPE_WALK);
pl.SetModel(playerModel);
pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
pl.ClearVelocity();
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
pl.SetInfoKey("*spec", "0");
pl.SetInfoKey("*dead", "0");
LevelNewParms();
LevelDecodeParms(pl);
/* give inventory */
pl.g_items = ITEM_CROWBAR | ITEM_GLOCK | ITEM_SUIT;
pl.activeweapon = WEAPON_GLOCK;
pl.glock_mag = 18;
pl.ammo_9mm = 44;
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
entity spot = Spawn_SelectRandom(strcat("info_ctfspawn_", ftos(pl.team)));
pl.Transport(spot.origin, spot.angles);
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}
void
OP4CTFRules::CaptureFlag(NSClientPlayer pp)
{
player pl = (player)pp;
NSEntity enemyFlag;
string flagName;
string teamScore;
string captureSound;
/* detach flag */
pl.g_items &= ~ITEM_GOALITEM;
pl.flagmodel = 0;
if (pl.team == 1) {
flagName = "info_ctfflag_2";
teamScore = "teamscore_1";
captureSound = "op4ctf_bm.flag_capture";
} else {
flagName = "info_ctfflag_1";
teamScore = "teamscore_2";
captureSound = "op4ctf_op4.flag_capture";
}
/* increment score */
forceinfokey(world, teamScore, sprintf("%d", serverkeyfloat(teamScore) + 1));
enemyFlag = (NSEntity)find(world, ::classname, flagName);
if (!enemyFlag) {
error("What the hell? There's no flag back there!");
return;
}
enemyFlag.StartSoundDef(captureSound, CHAN_ITEM, true);
enemyFlag.Respawn();
}
void
OP4CTFRules::PlayerDeath(NSClientPlayer pp)
{
DropFlag(pp);
super::PlayerDeath(pp);
}
void
OP4CTFRules::DropFlag(NSClientPlayer pp)
{
player pl = (player)pp;
item_ctfflag targetFlag;
string flagName;
/* skip normal players */
if (!(pl.g_items & ITEM_GOALITEM))
return;
if (pl.team == 1) {
flagName = "info_ctfflag_2";
} else {
flagName = "info_ctfflag_1";
}
for (entity e = world; (e = find(e, ::classname, flagName));) {
targetFlag = (item_ctfflag)e;
/* item is still pick-upable */
if (targetFlag.GetSolid() != SOLID_NOT) {
print("the item is not picked up. \n");
continue;
}
/* that's us, yup */
if (targetFlag.m_eActivator == pl) {
targetFlag.FlagDrop(pl);
return;
}
}
print("^1WARNING: ^7Player marked as having impossible goal-item\n");
}
void
CSEv_TeamJoin_f(float teamChoice)
{
self.team = teamChoice;
forceinfokey(self, "*team", ftos(teamChoice));
/* they'll become spectator */
if (teamChoice == 0) {
OP4CTFRules rule = (OP4CTFRules)g_grMode;
rule.PlayerSpawn((NSClientPlayer)self);
}
}
void
CSEv_ClassJoin_f(float classSelection)
{
OP4CTFRules rule = (OP4CTFRules)g_grMode;
string playerModel;
player pl = (player)self;
/* random black mesa char */
if (classSelection == 0)
classSelection = floor(random(1, 7));
/* random opfor char */
if (classSelection == 13)
classSelection = floor(random(7, 13));
switch (classSelection) {
/* black mesa */
case 1:
playerModel = "models/player/ctf_barney/ctf_barney.mdl";
break;
case 2:
playerModel = "models/player/cl_suit/cl_suit.mdl";
break;
case 3:
playerModel = "models/player/ctf_gina/ctf_gina.mdl";
break;
case 4:
playerModel = "models/player/ctf_gordon/ctf_gordon.mdl";
break;
case 5:
playerModel = "models/player/otis/otis.mdl";
break;
case 6:
playerModel = "models/player/ctf_scientist/ctf_scientist.mdl";
break;
/* opfor */
case 7:
playerModel = "models/player/beret/beret.mdl";
break;
case 8:
playerModel = "models/player/drill/drill.mdl";
break;
case 9:
playerModel = "models/player/grunt/grunt.mdl";
break;
case 10:
playerModel = "models/player/recruit/recruit.mdl";
break;
case 11:
playerModel = "models/player/shephard/shephard.mdl";
break;
case 12:
playerModel = "models/player/tower/tower.mdl";
break;
}
/* if we're alive, kill them (we need to drop the flag anyhow */
if (pl.IsAlive()) {
pl.m_oldModel = playerModel;
rule.PlayerDeath(pl);
} else {
rule.CharacterSpawn((NSClientPlayer)self, playerModel);
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED info_ctfdetect (0 0.8 0.8) (-8 -8 -8) (8 8 8)
# OVERVIEW
CTF Map Parameters
When detected, will enable Capture The Flag on the map that it's on.
# KEYS
- "basedefenddist" : Base Defend Distance, default is "30"
- "defendcarriertime" : Defend Carrier Time, default is "192"
- "captureassisttime" : Capture Assist Time, default is "10"
- "poweruprespawntime" : Powerup Respawn Time, default is "30"
- "score_icon_namebm" : Non-Flag Black Mesa icon, default is "item_ctfscorebm"
- "score_icon_nameof" : Non-Flag Opposing Force icon, default is "item_ctfscoreof"
- "map_score_max" : Maximum Map Team Score, default is "0"
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
*/
class info_ctfdetect
{
void info_ctfdetect(void);
};
info_ctfdetect g_ctf;
void
info_ctfdetect::info_ctfdetect(void)
{
g_ctf = this;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED info_ctfspawn (0 0.8 0.8) (-16 -16 -36) (16 16 36)
# OVERVIEW
CTF Player Start
# KEYS
- "team_no" : Team
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
*/
class
info_ctfspawn:NSEntity
{
void info_ctfspawn(void);
virtual void Respawn(void);
virtual void SpawnKey(string, string);
};
void
info_ctfspawn::info_ctfspawn(void)
{
}
void
info_ctfspawn::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "team_no":
team = ReadFloat(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
info_ctfspawn::Respawn(void)
{
SetOrigin(GetSpawnOrigin());
SetSolid(SOLID_NOT);
classname = strcat("info_ctfspawn_", ftos(team));
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED info_ctfspawn_powerup (0 0.8 0.8) (-16 -16 0) (16 16 36)
# OVERVIEW
CTF Powerup Spawn
# KEYS
- "team_no" : Team
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
*/

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED item_ctfaccelerator (0 0.8 0.8) (-16 -16 0) (16 16 36) x x CTFITEM_RANDOM
# OVERVIEW
CTF Double Damage Powerup
# KEYS
- "team_no" : Team
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
model="models/w_accelerator.mdl"
*/
class item_ctfaccelerator:OP4CTFItem
{
void item_ctfaccelerator(void);
virtual void Spawned(void);
};
void
item_ctfaccelerator::item_ctfaccelerator(void)
{
}
void
item_ctfaccelerator::Spawned(void)
{
m_iItemID = ITEM_CTF_DEATH;
model = "models/w_accelerator.mdl";
super::Spawned();
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED item_ctfbackpack (0 0.8 0.8) (-16 -16 0) (16 16 36) x x CTFITEM_RANDOM
# OVERVIEW
CTF Backpack Powerup
# KEYS
- "team_no" : Team
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
model="models/w_backpack.mdl"
*/
class item_ctfbackpack:OP4CTFItem
{
void item_ctfbackpack(void);
virtual void Spawned(void);
};
void
item_ctfbackpack::item_ctfbackpack(void)
{
}
void
item_ctfbackpack::Spawned(void)
{
m_iItemID = ITEM_CTF_BACKPACK;
model = "models/w_backpack.mdl";
super::Spawned();
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED item_ctfbase (0 0.8 0.8) (-16 -16 0) (16 16 72)
# OVERVIEW
CTF Capture-Point/Goal
# KEYS
- "model" : Model path for this item
- "skin" : Skin to use
- "goal_no" : Team
- "goal_min" : Minimum Bounding Box
- "goal_max" : Maximum Bounding Box
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
model="models/civ_stand.mdl"
*/
class item_ctfbase:OP4CTFItem
{
void item_ctfbase(void);
virtual void Respawn(void);
};
void
item_ctfbase::item_ctfbase(void)
{
}
void
item_ctfbase::Respawn(void)
{
SetOrigin(GetSpawnOrigin());
SetModel(GetSpawnModel());
SetSize([-16, -16, 0], [16, 16, 72]);
DropToFloor();
}

141
src/server/item_ctfflag.qc Normal file
View File

@ -0,0 +1,141 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED item_ctfflag (0 0.8 0.8) (-16 -16 0) (16 16 72)
# OVERVIEW
CTF Flag/Goal-Item
# KEYS
- "model" : Model path for this item
- "skin" : Skin to use
- "goal_no" : Team
- "goal_min" : Minimum Bounding Box
- "goal_max" : Maximum Bounding Box
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
model="models/flag.mdl"
*/
class item_ctfflag:OP4CTFItem
{
entity m_eActivator;
void item_ctfflag(void);
virtual void Respawn(void);
virtual void Touch(entity);
nonvirtual void FlagTaken(void);
nonvirtual void FlagDrop(NSClientPlayer);
nonvirtual void FlagReturns(void);
};
void
item_ctfflag::item_ctfflag(void)
{
m_eActivator = __NULL__;
}
void
item_ctfflag::Respawn(void)
{
SetOrigin(GetSpawnOrigin());
SetModel(GetSpawnModel());
SetSize([-16, -16, 0], [16, 16, 72]);
SetSolid(SOLID_TRIGGER);
DropToFloor();
SetFrame(4);
classname = strcat("info_ctfflag_", ftos(m_iTeamID));
forceinfokey(world, strcat("ctfflag_", ftos(m_iTeamID)), ftos(CTFFLAG_IDLE));
m_eActivator = __NULL__;
}
void
item_ctfflag::Touch(entity eToucher)
{
player pl = (player)eToucher;
if (!(eToucher.flags & FL_CLIENT))
return;
if (eToucher.team == 0)
return;
if (eToucher.team == m_iTeamID) {
if (m_eActivator == __NULL__) /* only on flags that haven't been dropped */
if (pl.g_items & ITEM_GOALITEM) {
OP4CTFRules rule = (OP4CTFRules)g_grMode;
rule.CaptureFlag((NSClientPlayer)pl);
}
return;
}
m_eActivator = pl;
pl.g_items |= ITEM_GOALITEM;
pl.flagmodel = GetModelindex();
pl.flagskin = GetSkin();
FlagTaken();
}
void
item_ctfflag::FlagTaken(void)
{
if (m_iTeamID == 1)
StartSoundDef("op4ctf_bm.flag_taken", CHAN_ITEM, true);
else
StartSoundDef("op4ctf_op4.flag_taken", CHAN_ITEM, true);
forceinfokey(world, strcat("ctfflag_", ftos(m_iTeamID)), ftos(CTFFLAG_TAKEN));
Disappear();
}
void
item_ctfflag::FlagDrop(NSClientPlayer pp)
{
player pl = (player)pp;
/* make it available again, put it exactly where we died */
Respawn();
SetOrigin(pl.origin);
DropToFloor();
SetFrame(0);
/* untag it from the player */
pl.g_items &= ~ITEM_GOALITEM;
pl.flagmodel = 0;
m_eActivator = pp; /* to mark that who this was dropped by */
forceinfokey(world, strcat("ctfflag_", ftos(m_iTeamID)), ftos(CTFFlAG_MISSING));
/* return after N secs */
ScheduleThink(FlagReturns, 30.0f);
}
void
item_ctfflag::FlagReturns(void)
{
Respawn();
/*
for (entity e = world; (e = find(e, ::classname, "player")); ) {
if (e.team == m_iTeamUses)
env_message_single(e, m_returnTeam);
else if (e.team == m_iTeamOwner)
env_message_single(e, m_returnOwner);
}
*/
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED item_ctflongjump (0 0.8 0.8) (-16 -16 0) (16 16 36) x x CTFITEM_RANDOM
# OVERVIEW
CTF Longjump Module Powerup
# KEYS
- "team_no" : Team
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
model="models/w_jumppack.mdl"
*/
class item_ctflongjump:OP4CTFItem
{
void item_ctflongjump(void);
virtual void Spawned(void);
};
void
item_ctflongjump::item_ctflongjump(void)
{
}
void
item_ctflongjump::Spawned(void)
{
m_iItemID = ITEM_CTF_JUMPPACK;
model = "models/w_jumppack.mdl";
super::Spawned();
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED item_ctfportablehev (0 0.8 0.8) (-16 -16 0) (16 16 36) x x CTFITEM_RANDOM
# OVERVIEW
CTF HEV Charger Powerup
# KEYS
- "team_no" : Team
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
model="models/w_porthev.mdl"
*/
class item_ctfportablehev:OP4CTFItem
{
void item_ctfportablehev(void);
virtual void Spawned(void);
};
void
item_ctfportablehev::item_ctfportablehev(void)
{
}
void
item_ctfportablehev::Spawned(void)
{
m_iItemID = ITEM_CTF_SHIELD;
model = "models/w_porthev.mdl";
super::Spawned();
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED item_ctfregeneration (0 0.8 0.8) (-16 -16 0) (16 16 36) x x CTFITEM_RANDOM
# OVERVIEW
CTF Health-Regen Powerup
# KEYS
- "team_no" : Team
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
*/
class item_ctfregeneration:OP4CTFItem
{
void item_ctfregeneration(void);
virtual void Spawned(void);
};
void
item_ctfregeneration::item_ctfregeneration(void)
{
}
void
item_ctfregeneration::Spawned(void)
{
m_iItemID = ITEM_CTF_HEALTH;
model = "models/w_health.mdl";
super::Spawned();
}

View File

@ -20,6 +20,7 @@ defs.h
../shared/include.src
../../../valve/src/server/HLXenMonster.qc
../../../valve/src/server/monster_apache.qc
../../../valve/src/server/monster_alien_controller.qc
../../../valve/src/server/monster_alien_grunt.qc
@ -73,6 +74,19 @@ monster_recruit.qc
../../../valve/src/server/ammo.qc
ammo_op4.qc
ctfitem.qc
item_ctfflag.qc
item_ctfbase.qc
info_ctfspawn.qc
info_ctfdetect.qc
item_ctflongjump.qc
item_ctfportablehev.qc
item_ctfregeneration.qc
item_ctfaccelerator.qc
item_ctfbackpack.qc
info_ctfspawn_powerup.qc
trigger_ctfgeneric.qc
../../../src/botlib/include.src
gamerules.qc

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -16,11 +16,18 @@
void
Game_InitRules(void)
{
{
forceinfokey(world, "ctf", "0");
if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) {
g_grMode = spawn(HLSingleplayerRules);
} else {
g_grMode = spawn(HLMultiplayerRules);
/* we have an info_ctfdetect entity */
if (substring(mapname, 0, 7) == "op4ctf_") {
g_grMode = spawn(OP4CTFRules);
forceinfokey(world, "ctf", "1");
} else
g_grMode = spawn(HLMultiplayerRules);
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED trigger_ctfgeneric (0 0.8 0.8) ?
# OVERVIEW
Generic CTF trigger volume
# KEYS
- "team_no" : Team
- "score" : Player score
- "team_score" : Team score
- "trigger_delay" : Reactivation delay
- "triggerstate" : Trigger state
# TRIVIA
This entity was introduced in Half-Life: Opposing Force (1999)
*/

View File

@ -12,6 +12,7 @@ player.qc
../../../valve/src/shared/fx_gaussbeam.qc
../../../valve/src/shared/fx_breakmodel.qc
../../../valve/src/shared/fx_explosion.qc
../../../valve/src/shared/fx_gibalien.qc
../../../valve/src/shared/fx_gibhuman.qc
../../../valve/src/shared/fx_spark.qc
../../../valve/src/shared/fx_impact.qc
@ -19,6 +20,7 @@ player.qc
items.h
weapons.h
player_ctf.qc
../../../valve/src/shared/w_crossbow.qc
../../../valve/src/shared/w_crowbar.qc
../../../valve/src/shared/w_egon.qc

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -43,9 +43,17 @@
#define ITEM_SHOCKRIFLE 0x01000000i
#define ITEM_SPORELAUNCHER 0x02000000i
#define ITEM_UNUSED27 0x04000000i
#define ITEM_UNUSED28 0x08000000i
#define ITEM_UNUSED29 0x10000000i
#define ITEM_UNUSED30 0x20000000i
#define ITEM_UNUSED31 0x40000000i
#define ITEM_UNUSED32 0x80000000i
#define ITEM_CTF_JUMPPACK 0x04000000i
#define ITEM_CTF_SHIELD 0x08000000i
#define ITEM_CTF_HEALTH 0x10000000i
#define ITEM_CTF_DEATH 0x20000000i
#define ITEM_CTF_BACKPACK 0x40000000i
#define ITEM_GOALITEM 0x80000000i
typedef enum
{
CTFFLAG_IDLE = 0,
CTFFLAG_TAKEN,
CTFFlAG_MISSING
} ctfflag_state;

View File

@ -105,7 +105,7 @@ enumflags
PLAYER_AMMO1,
PLAYER_AMMO2,
PLAYER_AMMO3,
PLAYER_UNUSED5,
PLAYER_FLAG,
PLAYER_UNUSED6,
PLAYER_UNUSED7
};
@ -163,18 +163,24 @@ class player:NSClientPlayer
PREDICTED_INT(mode_sporelauncher)
PREDICTED_INT(mode_m249)
PREDICTED_FLOAT(flagmodel)
PREDICTED_FLOAT(flagskin)
virtual void(void) Physics_Jump;
virtual void UpdatePlayerAnimation(float);
#ifdef CLIENT
NSRenderableEntity m_eFlag;
virtual void UpdatePlayerAttachments(bool);
virtual void(float,float) ReceiveEntity;
virtual void(void) PredictPreFrame;
virtual void(void) PredictPostFrame;
virtual void UpdateAliveCam(void);
#else
float m_flPickUpTime;
virtual void(void) EvaluateEntity;
virtual float(entity, float) SendEntity;
nonvirtual void PowerupThink(void);
#endif
};
@ -232,31 +238,6 @@ string Weapons_GetPlayermodel(player, int);
void
player::UpdatePlayerAttachments(bool visible)
{
/* draw the flashlight */
if (gflags & GF_FLASHLIGHT) {
vector src;
vector ang;
if (entnum != player_localentnum) {
src = origin + view_ofs;
ang = v_angle;
} else {
src = pSeat->m_vecPredictedOrigin + [0,0,-8];
ang = view_angles;
}
makevectors(ang);
traceline(src, src + (v_forward * 8096), MOVE_NORMAL, this);
if (serverkeyfloat("*bspversion") == BSPVER_HL) {
dynamiclight_add(trace_endpos + (v_forward * -2), 128, [1,1,1]);
} else {
float p = dynamiclight_add(src, 512, [1,1,1], 0, "textures/flashlight");
dynamiclight_set(p, LFIELD_ANGLES, ang);
dynamiclight_set(p, LFIELD_FLAGS, 3);
}
}
/* FIXME: this needs to be incorporated and simplified, now that we can handle it all in-class */
if (!visible)
return;
@ -284,6 +265,11 @@ player::UpdatePlayerAttachments(bool visible)
setcustomskin(this, "", "geomset 0 1\n");
}
if (m_eFlag != world) {
m_eFlag.SetOrigin(origin);
m_eFlag.SetAngles([0, angles[1], 0]);
}
/* follow thisayer at all times */
setorigin(p_model, origin);
p_model.angles = angles;
@ -316,90 +302,95 @@ player::ReceiveEntity
=================
*/
void
player::ReceiveEntity(float new, float fl)
player::ReceiveEntity(float new, float flChanged)
{
NSClientPlayer::ReceiveEntity(new, fl);
/* the generic client attributes */
NSClientPlayer::ReceiveEntity(new, flChanged);
/* animation */
if (fl & PLAYER_TOPFRAME) {
anim_top = readbyte();
anim_top_time = readfloat();
anim_top_delay = readfloat();
}
if (fl & PLAYER_BOTTOMFRAME) {
anim_bottom = readbyte();
anim_bottom_time = readfloat();
}
READENTITY_BYTE(anim_top, PLAYER_TOPFRAME)
READENTITY_FLOAT(anim_top_time, PLAYER_TOPFRAME)
READENTITY_FLOAT(anim_top_delay, PLAYER_TOPFRAME)
READENTITY_BYTE(anim_bottom, PLAYER_BOTTOMFRAME)
READENTITY_FLOAT(anim_bottom_time, PLAYER_BOTTOMFRAME)
if (fl & PLAYER_AMMO1) {
glock_mag = readbyte();
mp5_mag = readbyte();
python_mag = readbyte();
shotgun_mag = readbyte();
crossbow_mag = readbyte();
rpg_mag = readbyte();
satchel_chg = readbyte();
READENTITY_BYTE(glock_mag, PLAYER_AMMO1)
READENTITY_BYTE(mp5_mag, PLAYER_AMMO1)
READENTITY_BYTE(python_mag, PLAYER_AMMO1)
READENTITY_BYTE(shotgun_mag, PLAYER_AMMO1)
READENTITY_BYTE(crossbow_mag, PLAYER_AMMO1)
READENTITY_BYTE(rpg_mag, PLAYER_AMMO1)
READENTITY_BYTE(satchel_chg, PLAYER_AMMO1)
/* gearbox */
eagle_mag = readbyte();
sniper_mag = readbyte();
m249_mag = readbyte();
sporelauncher_mag = readbyte();
}
if (fl & PLAYER_AMMO2) {
ammo_9mm = readbyte();
ammo_357 = readbyte();
ammo_buckshot = readbyte();
ammo_bolt = readbyte();
ammo_rocket = readbyte();
ammo_uranium = readbyte();
ammo_handgrenade = readbyte();
ammo_satchel = readbyte();
ammo_tripmine = readbyte();
ammo_snark = readbyte();
ammo_hornet = readbyte();
READENTITY_BYTE(ammo_9mm, PLAYER_AMMO2)
READENTITY_BYTE(ammo_357, PLAYER_AMMO2)
READENTITY_BYTE(ammo_buckshot, PLAYER_AMMO2)
READENTITY_BYTE(ammo_bolt, PLAYER_AMMO2)
READENTITY_BYTE(ammo_rocket, PLAYER_AMMO2)
READENTITY_BYTE(ammo_uranium, PLAYER_AMMO2)
READENTITY_BYTE(ammo_handgrenade, PLAYER_AMMO2)
READENTITY_BYTE(ammo_satchel, PLAYER_AMMO2)
READENTITY_BYTE(ammo_tripmine, PLAYER_AMMO2)
READENTITY_BYTE(ammo_snark, PLAYER_AMMO2)
READENTITY_BYTE(ammo_hornet, PLAYER_AMMO2)
/* gearbox */
ammo_556 = readbyte();
ammo_762 = readbyte();
ammo_spore = readbyte();
ammo_shock = readbyte();
ammo_penguin = readbyte();
}
READENTITY_BYTE(ammo_m203_grenade, PLAYER_AMMO3)
READENTITY_BYTE(ammo_gauss_volume, PLAYER_AMMO3)
READENTITY_BYTE(ammo_rpg_state, PLAYER_AMMO3)
READENTITY_BYTE(mode_tempstate, PLAYER_AMMO3)
if (fl & PLAYER_AMMO3) {
ammo_m203_grenade = readbyte();
ammo_gauss_volume = readbyte();
ammo_rpg_state = readbyte();
mode_tempstate = readbyte();
/* gearbox */
READENTITY_BYTE(eagle_mag, PLAYER_AMMO1)
READENTITY_BYTE(sniper_mag, PLAYER_AMMO1)
READENTITY_BYTE(m249_mag, PLAYER_AMMO1)
READENTITY_BYTE(sporelauncher_mag, PLAYER_AMMO1)
/* gearbox */
mode_displacer = readbyte();
mode_eagle = readbyte();
mode_wrench = readbyte();
mode_sporelauncher = readbyte();
mode_m249 = readbyte();
}
READENTITY_BYTE(ammo_556, PLAYER_AMMO2)
READENTITY_BYTE(ammo_762, PLAYER_AMMO2)
READENTITY_BYTE(ammo_spore, PLAYER_AMMO2)
READENTITY_BYTE(ammo_shock, PLAYER_AMMO2)
READENTITY_BYTE(ammo_penguin, PLAYER_AMMO2)
READENTITY_BYTE(mode_displacer, PLAYER_AMMO3)
READENTITY_BYTE(mode_eagle, PLAYER_AMMO3)
READENTITY_BYTE(mode_wrench, PLAYER_AMMO3)
READENTITY_BYTE(mode_sporelauncher, PLAYER_AMMO3)
READENTITY_BYTE(mode_m249, PLAYER_AMMO3)
READENTITY_FLOAT(flagmodel, PLAYER_FLAG)
READENTITY_BYTE(flagskin, PLAYER_FLAG)
setorigin(this, origin);
/* add/remove flag model */
if (flagmodel != 0) {
if (!m_eFlag)
m_eFlag = spawn(NSRenderableEntity);
m_eFlag.SetModelindex(flagmodel);
m_eFlag.SetSkin(flagskin);
m_eFlag.SetFrame(2);
} else if (m_eFlag) {
m_eFlag.Destroy();
remove(m_eFlag);
m_eFlag = world;
}
/* these only concern the current player */
CSQC_UpdateSeat();
if (this != pSeat->m_ePlayer)
return;
/* do not notify us of updates when spawning initially */
if (fl == UPDATE_ALL)
if (flChanged == UPDATE_ALL)
PredictPreFrame();
if (fl & PLAYER_AMMO1 || fl & PLAYER_AMMO2 || fl & PLAYER_AMMO3) {
if (flChanged & PLAYER_AMMO1 || flChanged & PLAYER_AMMO2 || flChanged & PLAYER_AMMO3) {
Weapons_AmmoUpdate(this);
HUD_AmmoNotify_Check(this);
}
if (fl & PLAYER_ITEMS || fl & PLAYER_HEALTH)
if (flChanged & PLAYER_ITEMS || flChanged & PLAYER_HEALTH)
HUD_ItemNotify_Check(this);
}
@ -462,6 +453,8 @@ player::PredictPreFrame(void)
SAVE_STATE(mode_wrench)
SAVE_STATE(mode_sporelauncher)
SAVE_STATE(mode_m249)
SAVE_STATE(flagmodel)
SAVE_STATE(flagskin)
}
/*
@ -522,144 +515,70 @@ player::PredictPostFrame(void)
ROLL_BACK(mode_wrench)
ROLL_BACK(mode_sporelauncher)
ROLL_BACK(mode_m249)
ROLL_BACK(flagmodel)
ROLL_BACK(flagskin)
}
#else
void
player::EvaluateEntity(void)
{
/* the generic client attributes */
NSClientPlayer::EvaluateEntity();
/* animation */
if (ATTR_CHANGED(anim_bottom) || ATTR_CHANGED(anim_bottom_time))
SendFlags |= PLAYER_BOTTOMFRAME;
if (ATTR_CHANGED(anim_top) || ATTR_CHANGED(anim_top_time) || ATTR_CHANGED(anim_top_delay))
SendFlags |= PLAYER_TOPFRAME;
PowerupThink();
/* ammo 1 type updates */
if (ATTR_CHANGED(glock_mag))
SendFlags |= PLAYER_AMMO1;
if (ATTR_CHANGED(mp5_mag))
SendFlags |= PLAYER_AMMO1;
if (ATTR_CHANGED(python_mag))
SendFlags |= PLAYER_AMMO1;
if (ATTR_CHANGED(shotgun_mag))
SendFlags |= PLAYER_AMMO1;
if (ATTR_CHANGED(crossbow_mag))
SendFlags |= PLAYER_AMMO1;
if (ATTR_CHANGED(rpg_mag))
SendFlags |= PLAYER_AMMO1;
if (ATTR_CHANGED(satchel_chg))
SendFlags |= PLAYER_AMMO1;
EVALUATE_FIELD(anim_top, PLAYER_TOPFRAME)
EVALUATE_FIELD(anim_top_time, PLAYER_TOPFRAME)
EVALUATE_FIELD(anim_top_delay, PLAYER_TOPFRAME)
EVALUATE_FIELD(anim_bottom, PLAYER_BOTTOMFRAME)
EVALUATE_FIELD(anim_bottom_time, PLAYER_BOTTOMFRAME)
/* ammo 2 type updates */
if (ATTR_CHANGED(ammo_9mm))
SendFlags |= PLAYER_AMMO2;
if (ATTR_CHANGED(ammo_357))
SendFlags |= PLAYER_AMMO2;
if (ATTR_CHANGED(ammo_buckshot))
SendFlags |= PLAYER_AMMO2;
if (ATTR_CHANGED(ammo_bolt))
SendFlags |= PLAYER_AMMO2;
if (ATTR_CHANGED(ammo_rocket))
SendFlags |= PLAYER_AMMO2;
if (ATTR_CHANGED(ammo_uranium))
SendFlags |= PLAYER_AMMO2;
if (ATTR_CHANGED(ammo_handgrenade))
SendFlags |= PLAYER_AMMO2;
if (ATTR_CHANGED(ammo_satchel))
SendFlags |= PLAYER_AMMO2;
if (ATTR_CHANGED(ammo_tripmine))
SendFlags |= PLAYER_AMMO2;
if (ATTR_CHANGED(ammo_snark))
SendFlags |= PLAYER_AMMO2;
if (ATTR_CHANGED(ammo_hornet))
SendFlags |= PLAYER_AMMO2;
EVALUATE_FIELD(glock_mag, PLAYER_AMMO1)
EVALUATE_FIELD(mp5_mag, PLAYER_AMMO1)
EVALUATE_FIELD(python_mag, PLAYER_AMMO1)
EVALUATE_FIELD(shotgun_mag, PLAYER_AMMO1)
EVALUATE_FIELD(crossbow_mag, PLAYER_AMMO1)
EVALUATE_FIELD(rpg_mag, PLAYER_AMMO1)
EVALUATE_FIELD(satchel_chg, PLAYER_AMMO1)
if (ATTR_CHANGED(ammo_m203_grenade))
SendFlags |= PLAYER_AMMO3;
if (ATTR_CHANGED(ammo_gauss_volume))
SendFlags |= PLAYER_AMMO3;
if (ATTR_CHANGED(ammo_rpg_state))
SendFlags |= PLAYER_AMMO3;
if (ATTR_CHANGED(mode_tempstate))
SendFlags |= PLAYER_AMMO3;
EVALUATE_FIELD(ammo_9mm, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_357, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_buckshot, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_bolt, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_rocket, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_uranium, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_handgrenade, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_satchel, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_tripmine, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_snark, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_hornet, PLAYER_AMMO2)
SAVE_STATE(glock_mag)
SAVE_STATE(mp5_mag)
SAVE_STATE(python_mag)
SAVE_STATE(shotgun_mag)
SAVE_STATE(crossbow_mag)
SAVE_STATE(rpg_mag)
SAVE_STATE(satchel_chg)
SAVE_STATE(ammo_9mm)
SAVE_STATE(ammo_357)
SAVE_STATE(ammo_buckshot)
SAVE_STATE(ammo_bolt)
SAVE_STATE(ammo_rocket)
SAVE_STATE(ammo_uranium)
SAVE_STATE(ammo_handgrenade)
SAVE_STATE(ammo_satchel)
SAVE_STATE(ammo_tripmine)
SAVE_STATE(ammo_snark)
SAVE_STATE(ammo_hornet)
SAVE_STATE(ammo_m203_grenade)
SAVE_STATE(ammo_gauss_volume)
SAVE_STATE(ammo_rpg_state)
SAVE_STATE(mode_tempstate)
SAVE_STATE(anim_top)
SAVE_STATE(anim_top_delay)
SAVE_STATE(anim_top_time)
SAVE_STATE(anim_bottom)
SAVE_STATE(anim_bottom_time)
EVALUATE_FIELD(ammo_m203_grenade, PLAYER_AMMO3)
EVALUATE_FIELD(ammo_gauss_volume, PLAYER_AMMO3)
EVALUATE_FIELD(ammo_rpg_state, PLAYER_AMMO3)
EVALUATE_FIELD(mode_tempstate, PLAYER_AMMO3)
/* gearbox */
if (eagle_mag_net != eagle_mag)
SendFlags |= PLAYER_AMMO1;
if (sniper_mag_net != sniper_mag)
SendFlags |= PLAYER_AMMO1;
if (m249_mag_net != m249_mag)
SendFlags |= PLAYER_AMMO1;
if (sporelauncher_mag_net != sporelauncher_mag)
SendFlags |= PLAYER_AMMO1;
EVALUATE_FIELD(eagle_mag, PLAYER_AMMO1)
EVALUATE_FIELD(sniper_mag, PLAYER_AMMO1)
EVALUATE_FIELD(m249_mag, PLAYER_AMMO1)
EVALUATE_FIELD(sporelauncher_mag, PLAYER_AMMO1)
if (ammo_556_net != ammo_556)
SendFlags |= PLAYER_AMMO2;
if (ammo_762_net != ammo_762)
SendFlags |= PLAYER_AMMO2;
if (ammo_spore_net != ammo_spore)
SendFlags |= PLAYER_AMMO2;
if (ammo_shock_net != ammo_shock)
SendFlags |= PLAYER_AMMO2;
if (ammo_penguin_net != ammo_penguin)
SendFlags |= PLAYER_AMMO2;
EVALUATE_FIELD(ammo_556, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_762, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_spore, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_shock, PLAYER_AMMO2)
EVALUATE_FIELD(ammo_penguin, PLAYER_AMMO2)
if (mode_displacer_net != mode_displacer)
SendFlags |= PLAYER_AMMO3;
if (mode_eagle_net != mode_eagle)
SendFlags |= PLAYER_AMMO3;
if (mode_wrench_net != mode_wrench)
SendFlags |= PLAYER_AMMO3;
if (mode_sporelauncher_net != mode_sporelauncher)
SendFlags |= PLAYER_AMMO3;
/* gearbox */
SAVE_STATE(eagle_mag)
SAVE_STATE(sniper_mag)
SAVE_STATE(m249_mag)
SAVE_STATE(sporelauncher_mag)
SAVE_STATE(ammo_556)
SAVE_STATE(ammo_762)
SAVE_STATE(ammo_spore)
SAVE_STATE(ammo_shock)
SAVE_STATE(ammo_penguin)
SAVE_STATE(mode_displacer)
SAVE_STATE(mode_eagle)
SAVE_STATE(mode_wrench)
SAVE_STATE(mode_sporelauncher)
SAVE_STATE(mode_m249)
EVALUATE_FIELD(mode_displacer, PLAYER_AMMO3)
EVALUATE_FIELD(mode_eagle, PLAYER_AMMO3)
EVALUATE_FIELD(mode_wrench, PLAYER_AMMO3)
EVALUATE_FIELD(mode_sporelauncher, PLAYER_AMMO3)
EVALUATE_FIELD(mode_m249, PLAYER_AMMO3)
EVALUATE_FIELD(flagmodel, PLAYER_FLAG)
EVALUATE_FIELD(flagskin, PLAYER_FLAG)
}
/*
@ -681,69 +600,59 @@ player::SendEntity(entity ePEnt, float flChanged)
WriteByte(MSG_ENTITY, ENT_PLAYER);
WriteFloat(MSG_ENTITY, flChanged);
/* the generic client attributes */
NSClientPlayer::SendEntity(ePEnt, flChanged);
if (flChanged & PLAYER_TOPFRAME) {
WriteByte(MSG_ENTITY, anim_top);
WriteFloat(MSG_ENTITY, anim_top_time);
WriteFloat(MSG_ENTITY, anim_top_delay);
}
if (flChanged & PLAYER_BOTTOMFRAME) {
WriteByte(MSG_ENTITY, anim_bottom);
WriteFloat(MSG_ENTITY, anim_bottom_time);
}
SENDENTITY_BYTE(anim_top, PLAYER_TOPFRAME)
SENDENTITY_FLOAT(anim_top_time, PLAYER_TOPFRAME)
SENDENTITY_FLOAT(anim_top_delay, PLAYER_TOPFRAME)
SENDENTITY_BYTE(anim_bottom, PLAYER_BOTTOMFRAME)
SENDENTITY_FLOAT(anim_bottom_time, PLAYER_BOTTOMFRAME)
if (flChanged & PLAYER_AMMO1) {
WriteByte(MSG_ENTITY, glock_mag);
WriteByte(MSG_ENTITY, mp5_mag);
WriteByte(MSG_ENTITY, python_mag);
WriteByte(MSG_ENTITY, shotgun_mag);
WriteByte(MSG_ENTITY, crossbow_mag);
WriteByte(MSG_ENTITY, rpg_mag);
WriteByte(MSG_ENTITY, satchel_chg);
SENDENTITY_BYTE(glock_mag, PLAYER_AMMO1)
SENDENTITY_BYTE(mp5_mag, PLAYER_AMMO1)
SENDENTITY_BYTE(python_mag, PLAYER_AMMO1)
SENDENTITY_BYTE(shotgun_mag, PLAYER_AMMO1)
SENDENTITY_BYTE(crossbow_mag, PLAYER_AMMO1)
SENDENTITY_BYTE(rpg_mag, PLAYER_AMMO1)
SENDENTITY_BYTE(satchel_chg, PLAYER_AMMO1)
/* gearbox */
WriteByte(MSG_ENTITY, eagle_mag);
WriteByte(MSG_ENTITY, sniper_mag);
WriteByte(MSG_ENTITY, m249_mag);
WriteByte(MSG_ENTITY, sporelauncher_mag);
}
SENDENTITY_BYTE(ammo_9mm, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_357, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_buckshot, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_bolt, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_rocket, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_uranium, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_handgrenade, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_satchel, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_tripmine, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_snark, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_hornet, PLAYER_AMMO2)
if (flChanged & PLAYER_AMMO2) {
WriteByte(MSG_ENTITY, ammo_9mm);
WriteByte(MSG_ENTITY, ammo_357);
WriteByte(MSG_ENTITY, ammo_buckshot);
WriteByte(MSG_ENTITY, ammo_bolt);
WriteByte(MSG_ENTITY, ammo_rocket);
WriteByte(MSG_ENTITY, ammo_uranium);
WriteByte(MSG_ENTITY, ammo_handgrenade);
WriteByte(MSG_ENTITY, ammo_satchel);
WriteByte(MSG_ENTITY, ammo_tripmine);
WriteByte(MSG_ENTITY, ammo_snark);
WriteByte(MSG_ENTITY, ammo_hornet);
SENDENTITY_BYTE(ammo_m203_grenade, PLAYER_AMMO3)
SENDENTITY_BYTE(ammo_gauss_volume, PLAYER_AMMO3)
SENDENTITY_BYTE(ammo_rpg_state, PLAYER_AMMO3)
SENDENTITY_BYTE(mode_tempstate, PLAYER_AMMO3)
/* gearbox */
WriteByte(MSG_ENTITY, ammo_556);
WriteByte(MSG_ENTITY, ammo_762);
WriteByte(MSG_ENTITY, ammo_spore);
WriteByte(MSG_ENTITY, ammo_shock);
WriteByte(MSG_ENTITY, ammo_penguin);
}
/* gearbox */
SENDENTITY_BYTE(eagle_mag, PLAYER_AMMO1)
SENDENTITY_BYTE(sniper_mag, PLAYER_AMMO1)
SENDENTITY_BYTE(m249_mag, PLAYER_AMMO1)
SENDENTITY_BYTE(sporelauncher_mag, PLAYER_AMMO1)
if (flChanged & PLAYER_AMMO3) {
WriteByte(MSG_ENTITY, ammo_m203_grenade);
WriteByte(MSG_ENTITY, ammo_gauss_volume);
WriteByte(MSG_ENTITY, ammo_rpg_state);
WriteByte(MSG_ENTITY, mode_tempstate);
/* gearbox */
WriteByte(MSG_ENTITY, mode_displacer);
WriteByte(MSG_ENTITY, mode_eagle);
WriteByte(MSG_ENTITY, mode_wrench);
WriteByte(MSG_ENTITY, mode_sporelauncher);
WriteByte(MSG_ENTITY, mode_m249);
}
SENDENTITY_BYTE(ammo_556, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_762, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_spore, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_shock, PLAYER_AMMO2)
SENDENTITY_BYTE(ammo_penguin, PLAYER_AMMO2)
SENDENTITY_BYTE(mode_displacer, PLAYER_AMMO3)
SENDENTITY_BYTE(mode_eagle, PLAYER_AMMO3)
SENDENTITY_BYTE(mode_wrench, PLAYER_AMMO3)
SENDENTITY_BYTE(mode_sporelauncher, PLAYER_AMMO3)
SENDENTITY_BYTE(mode_m249, PLAYER_AMMO3)
SENDENTITY_FLOAT(flagmodel, PLAYER_FLAG)
SENDENTITY_BYTE(flagskin, PLAYER_FLAG)
return (1);
}
#endif

35
src/shared/player_ctf.qc Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef SERVER
void
player::PowerupThink(void)
{
if (m_flPickUpTime > time)
return;
if (g_items & ITEM_CTF_SHIELD) {
armor += 1;
m_flPickUpTime = time + 0.5f;
} else if (g_items & ITEM_CTF_HEALTH) {
health += 1;
m_flPickUpTime = time + 0.5f;
} else if (g_items & ITEM_CTF_BACKPACK) {
print("add ammo!\n");
m_flPickUpTime = time + 0.5f;
}
}
#endif

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_displacer (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_displacer.mdl"
HALF-LIFE: OPPOSING FORCE (1999) ENTITY
Displacer Weapon
*/
enum
{
DISP_IDLE1,
@ -273,7 +264,7 @@ w_displacer_hud(player pl)
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
Cross_DrawSub(
"sprites/ofch1.spr_0.tga",
g_ofch1_spr,
[24,24],
[48/72,0],
[24/72,24/72]
@ -321,7 +312,7 @@ w_displacer_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof02.spr_0.tga",
g_ofhud2_spr,
[0,180/256],
[170/256,45/256],
hud_col,
@ -332,7 +323,7 @@ w_displacer_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof01.spr_0.tga",
g_ofhud1_spr,
[0,180/256],
[170/256,45/256],
hud_col,

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_eagle (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_desert_eagle.mdl"
HALF-LIFE: OPPOSING FORCE (1999) ENTITY
Desert Eagle Weapon
*/
enum
{
EAGLE_IDLE1,
@ -275,7 +266,7 @@ w_eagle_crosshair(player pl)
);
} else {
Cross_DrawSub(
"sprites/ofch1.spr_0.tga",
g_ofch1_spr,
[24,24],
[0,0],
[24/72, 24/72]
@ -332,7 +323,7 @@ w_eagle_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof02.spr_0.tga",
g_ofhud2_spr,
[0,90/256],
[170/256,45/256],
hud_col,
@ -343,7 +334,7 @@ w_eagle_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof01.spr_0.tga",
g_ofhud1_spr,
[0,90/256],
[170/256,45/256],
hud_col,

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_grapple (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_bgrap.mdl"
HALF-LIFE: OPPOSING FORCE (1999) ENTITY
Barnacle Grappling-Hook Weapon
*/
#ifdef CLIENT
/* because some people apparently prefer the worse quality one */
var int autocvar_cl_tonguemode = 0;
@ -257,7 +248,7 @@ w_grapple_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof02.spr_0.tga",
g_ofhud2_spr,
[0,45/256],
[170/256,45/256],
g_hud_color,
@ -268,7 +259,7 @@ w_grapple_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof01.spr_0.tga",
g_ofhud1_spr,
[0,45/256],
[170/256,45/256],
g_hud_color,

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_knife (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_knife.mdl"
HALF-LIFE: OPPOSING FORCE (1999) ENTITY
Knife Weapon
*/
enum
{
KNIFE_IDLE1,
@ -219,7 +210,7 @@ w_knife_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof04.spr_0.tga",
g_ofhud4_spr,
[0,90/256],
[170/256,45/256],
g_hud_color,
@ -230,7 +221,7 @@ w_knife_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof03.spr_0.tga",
g_ofhud3_spr,
[0,90/256],
[170/256,45/256],
g_hud_color,

View File

@ -14,16 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_m249 (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_saw.mdl"
HALF-LIFE: OPPOSING FORCE (1999) ENTITY
M249 Weapon
*/
/* Animations */
enum
{
M249_IDLE1,
@ -227,7 +217,7 @@ w_m249_crosshair(player pl)
/* crosshair */
Cross_DrawSub(
"sprites/ofch1.spr_0.tga",
g_ofch1_spr,
[24,24],
[24/72,0],
[24/72, 24/72]
@ -285,7 +275,7 @@ w_m249_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof02.spr_0.tga",
g_ofhud2_spr,
[0,135/256],
[170/256,45/256],
hud_col,
@ -296,7 +286,7 @@ w_m249_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof01.spr_0.tga",
g_ofhud1_spr,
[0,135/256],
[170/256,45/256],
hud_col,

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_penguin (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_penguin.mdl"
HALF-LIFE: OPPOSING FORCE (1999) ENTITY
Penguin Weapon
*/
enum
{
PENGUIN_IDLE,
@ -320,11 +311,11 @@ w_penguin_hudpic(player pl, int s, vector pos, float a)
HUD_DrawAmmoBar(pos, pl.ammo_penguin, MAX_A_PENGUIN, a);
if (s) {
drawsubpic(pos, [170,45], "sprites/640hudof04.spr_0.tga",
drawsubpic(pos, [170,45], g_ofhud4_spr,
[0,180/256], [170/256,45/256],
hud_col, a, DRAWFLAG_ADDITIVE);
} else {
drawsubpic(pos, [170,45], "sprites/640hudof03.spr_0.tga",
drawsubpic(pos, [170,45], g_ofhud3_spr,
[0,180/256], [170/256,45/256],
hud_col, a, DRAWFLAG_ADDITIVE);
}

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_pipewrench (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_pipe_wrench.mdl"
HALF-LIFE: OPPOSING FORCE (1999) ENTITY
Pipe-Wrench Weapon
*/
enum
{
PIPE_IDLE1,
@ -292,7 +283,7 @@ w_pipewrench_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof02.spr_0.tga",
g_ofhud2_spr,
[0,0],
[170/256,45/256],
g_hud_color,
@ -303,7 +294,7 @@ w_pipewrench_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof01.spr_0.tga",
g_ofhud1_spr,
[0,0],
[170/256,45/256],
g_hud_color,

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_shockrifle (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_shock.mdl"
HALF-LIFE: OPPOSING FORCE (1999) ENTITY
Shockrifle Weapon
*/
#ifdef CLIENT
var int PART_SHOCKPIECE;
#endif
@ -198,7 +189,7 @@ w_shockrifle_crosshair(player pl)
vector aicon_pos;
Cross_DrawSub(
"sprites/ofch1.spr_0.tga",
g_ofch1_spr,
[24,24],
[0,24/72],
[24/72, 24/72]
@ -255,7 +246,7 @@ w_shockrifle_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof04.spr_0.tga",
g_ofhud4_spr,
[0,45/256],
[170/256,45/256],
hud_col,
@ -266,7 +257,7 @@ w_shockrifle_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof03.spr_0.tga",
g_ofhud3_spr,
[0,45/256],
[170/256,45/256],
hud_col,

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_sniperrifle (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_m40a1.mdl"
HALF-LIFE: OPPOSING FORCE (1999) ENTITY
Sniper-Rifle Weapon
*/
enum
{
SNIPER_DRAW,
@ -211,14 +202,14 @@ w_sniperrifle_crosshair(player pl)
#ifdef CLIENT
if (pl.viewzoom == 1.0f) {
Cross_DrawSub(
"sprites/ofch1.spr_0.tga",
g_ofch1_spr,
[24,24],
[0,48/72],
[24/72, 24/72]
);
} else {
Cross_Draw(
"sprites/ofch2.spr_0.tga",
g_ofch1_spr,
[256,256]
);
}
@ -261,9 +252,9 @@ w_sniperrifle_hudpic(player pl, int s, vector pos, float a)
HUD_DrawAmmoBar(pos, pl.ammo_762, MAX_A_762, a);
if (s) {
drawsubpic(pos, [170,45], "sprites/640hudof04.spr_0.tga", [0,135/256], [170/256,45/256], hud_col, a, DRAWFLAG_ADDITIVE);
drawsubpic(pos, [170,45], g_ofhud4_spr, [0,135/256], [170/256,45/256], hud_col, a, DRAWFLAG_ADDITIVE);
} else {
drawsubpic(pos, [170,45], "sprites/640hudof03.spr_0.tga", [0,135/256], [170/256,45/256], hud_col, a, DRAWFLAG_ADDITIVE);
drawsubpic(pos, [170,45], g_ofhud3_spr, [0,135/256], [170/256,45/256], hud_col, a, DRAWFLAG_ADDITIVE);
}
#endif
}

View File

@ -14,15 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED weapon_sporelauncher (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_spore_launcher.mdl"
HALF-LIFE: OPPOSING FORCE (1999) ENTITY
Sporelauncher Weapon
*/
enum
{
SPORE_IDLE1,
@ -338,7 +329,7 @@ w_sporelauncher_crosshair(player pl)
vector aicon_pos;
Cross_DrawSub(
"sprites/ofch1.spr_0.tga",
g_ofch1_spr,
[24,24],
[24/72,24/72],
[24/72,24/72]
@ -396,7 +387,7 @@ w_sporelauncher_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof04.spr_0.tga",
g_ofhud4_spr,
[0,0],
[170/256,45/256],
hud_col,
@ -407,7 +398,7 @@ w_sporelauncher_hudpic(player pl, int selected, vector pos, float a)
drawsubpic(
pos,
[170,45],
"sprites/640hudof03.spr_0.tga",
g_ofhud3_spr,
[0,0],
[170/256,45/256],
hud_col,

View File

@ -0,0 +1,23 @@
op4ctf_bm.flag_taken
{
attenuation none
sample "ctf/bm_flagtaken.wav"
}
op4ctf_bm.flag_capture
{
attenuation none
sample "ctf/civ_flag_capture.wav"
}
op4ctf_op4.flag_taken
{
attenuation none
sample "ctf/soldier_flagtaken.wav"
}
op4ctf_op4.flag_capture
{
attenuation none
sample "ctf/marine_flag_capture.wav"
}