Get rid of now redundant code.

This commit is contained in:
Marco Cawthorne 2025-02-21 19:14:15 -08:00
commit 67c03934bc
49 changed files with 305 additions and 5508 deletions

View file

@ -1,6 +1,6 @@
ISC License
Copyright (c) 2016-2021, Marco "eukara" Hladik <marco@icculus.org>
Copyright (c) 2016-2025, Marco "eukara" Cawthorne <marco@icculus.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View file

@ -1,4 +1,5 @@
# ![](img/te.png) Team Effort
Clean-room reimplementation of Team Fortress Classic in QuakeC.
![Preview 1](img/preview1.jpg)
@ -28,7 +29,7 @@ We've had people ask in the oddest of places for help, please don't do that.
## License
ISC License
Copyright (c) 2016-2025 Marco Hladik <marco@icculus.org>
Copyright (c) 2016-2025 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

View file

@ -1,2 +1,3 @@
set "hostname" "FreeTFC Server"
set "hostname" "Team Effort Server"
set "maxplayers" "8"
set g_gametype "default"

View file

@ -2,5 +2,5 @@ CC=fteqcc
all:
cd client && $(MAKE)
cd rules && $(MAKE)
cd server && $(MAKE)
cd rules && $(MAKE)

View file

@ -21,8 +21,6 @@ defs.h
../../../src/gs-entbase/shared.src
../shared/include.src
vox.qc
../../../valve/src/client/damage.qc
draw.qc
init.qc

View file

@ -1,5 +1,5 @@
QCC=fteqcc
all:
mkdir -pv ../../zpak001.pk3dir/progs/
mkdir -pv ../../progs/
$(QCC) $(CFLAGS) -I../../../src/server default.qc

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2024-2025 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,7 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma PROGS_DAT "../../zpak001.pk3dir/progs/default.dat"
#pragma PROGS_DAT "../../progs/default.dat"
#include "../../../src/server/api.h"
@ -77,6 +77,14 @@ TF_GoSpectator(entity targetPlayer)
game.TeleportToSpawn(targetPlayer);
}
void
CodeCallback_Precache(void)
{
for (int i = 0i; i < g_tfClasses.length; i++) {
precache.Entity(g_tfClasses[i]);
}
}
void
CodeCallback_StartGameType(void)
{
@ -110,12 +118,12 @@ CodeCallback_PlayerDamage(entity inflictor, entity attacker)
}
void
CodeCallback_PlayerKilled(entity inflictor, entity attacker, string weapon)
CodeCallback_PlayerKilled(entity playerEntity, entity inflictor, entity attacker, string weapon)
{
combat.Obituary(self.netname, attacker.netname, weapon, "");
combat.Obituary(playerEntity.netname, attacker.netname, weapon, "");
/* death-counter */
self.deaths++;
playerEntity.deaths++;
/* update score-counter */
if (ents.isPlayer(attacker)) {
@ -142,7 +150,7 @@ CodeCallback_ClientCommand(entity targetPlayer, string command)
switch (argv(0)) {
case "random":
int classID = (int)floor(0, g_tfClasses.length);
int classID = (int)floor(random(0, g_tfClasses.length));
TF_SwitchClass(targetPlayer, classID);
break;
case "scout":

View file

@ -1,25 +0,0 @@
class
TFCBot:ncBot
{
void TFCBot(void);
//virtual void CreateObjective(void);
};
void CSEv_TeamJoin_f(float f);
void CSEv_ClassJoin_f(float f);
void
TFCBot::TFCBot(void)
{
CSEv_TeamJoin_f(0);
CSEv_ClassJoin_f(0);
}
#if 0
void
TFCBot::CreateObjective(void)
{
super:: CreateObjective();
}
#endif

View file

@ -1,48 +0,0 @@
/*
* Copyright (c) 2016-2022 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.
*/
/* called every input frame */
void
Game_RunClientCommand(void)
{
TFPlayer pl = (TFPlayer)self;
/* clear map triggers */
pl.gflags &= ~GF_NOBUILDZONE;
pl.gflags &= ~GF_NOGRENADEZONE;
pl.Physics_Run();
}
/* client cmd overrides happen here */
void
Game_ParseClientCommand(string cmd)
{
tokenize(cmd);
if (argv(1) == "timeleft") {
string msg;
string timestring;
float timeleft;
timeleft = cvar("timelimit") - (time / 60);
timestring = Util_TimeToString(timeleft);
msg = sprintf("we have %s minutes remaining", timestring);
bprint(PRINT_CHAT, msg);
return;
}
clientcommand(self, cmd);
}

15
src/server/entities.src Normal file
View file

@ -0,0 +1,15 @@
#includelist
dispenser.qc
sentry.qc
teleporter.qc
func_nobuild.qc
func_nogrenades.qc
info_player_teamspawn.qc
item_tfgoal.qc
info_tfgoal.qc
info_areadef.qc
info_tfdetect.qc
item_armor.qc
item_healthkit.qc
#endlist

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2022-2025 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
@ -23,24 +23,20 @@ Brush volume that when entered, will not allow you to deploy anything as an engi
-------- KEYS --------
"targetname" Name
*/
class
func_nobuild:ncBrushTrigger
{
void(void) func_nobuild;
public:
void func_nobuild(void);
virtual void(void) Respawn;
virtual void(entity) Touch;
virtual void Respawn(void);
virtual void Touch(entity);
};
void
func_nobuild::Touch(entity eToucher)
func_nobuild::func_nobuild(void)
{
TFPlayer pl = (TFPlayer)eToucher;
if (!(eToucher.flags & FL_CLIENT))
return;
pl.gflags |= GF_NOBUILDZONE;
}
void
@ -50,7 +46,13 @@ func_nobuild::Respawn(void)
}
void
func_nobuild::func_nobuild(void)
func_nobuild::Touch(entity eToucher)
{
TFPlayer pl = (TFPlayer)eToucher;
}
if (isPlayer(eToucher) == false) {
return;
}
pl.gflags |= GF_NOBUILDZONE;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2022-2025 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
@ -23,24 +23,20 @@ Brush volume that when entered, will not allow you to deploy any grenades.
-------- KEYS --------
"targetname" Name
*/
class
func_nogrenades:ncBrushTrigger
{
void(void) func_nogrenades;
public:
void func_nogrenades(void);
virtual void(void) Respawn;
virtual void(entity) Touch;
virtual void Respawn(void);
virtual void Touch(entity);
};
void
func_nogrenades::Touch(entity eToucher)
func_nogrenades::func_nogrenades(void)
{
TFPlayer pl = (TFPlayer)eToucher;
if (!(eToucher.flags & FL_CLIENT))
return;
pl.gflags |= GF_NOGRENADEZONE;
}
void
@ -50,7 +46,13 @@ func_nogrenades::Respawn(void)
}
void
func_nogrenades::func_nogrenades(void)
func_nogrenades::Touch(entity eToucher)
{
TFPlayer pl = (TFPlayer)eToucher;
}
if (isPlayer(eToucher) == false) {
return;
}
pl.gflags |= GF_NOGRENADEZONE;
}

View file

@ -30,24 +30,31 @@ Describes an area's bounds and description/name.
class
info_areadef:ncPointTrigger
{
public:
void info_areadef(void);
virtual void Respawn(void);
virtual void SpawnKey(string,string);
virtual void Touch(entity);
private:
string m_strDescription;
vector m_vecMins;
vector m_vecMaxs;
void(void) info_areadef;
virtual void(void) Respawn;
virtual void(string,string) SpawnKey;
virtual void(entity) Touch;
};
void
info_areadef::Touch(entity eToucher)
info_areadef::info_areadef(void)
{
if (!(eToucher.flags & FL_CLIENT))
return;
serverinfo.SetBool("areadefs", true);
}
forceinfokey(eToucher, "*areadef", m_strDescription);
void
info_areadef::Touch(entity touchingEntity)
{
if (isPlayer(touchingEntity) == false) {
return;
}
userinfo.SetString(touchingEntity, "*areadef", m_strDescription);
}
void
@ -61,12 +68,6 @@ info_areadef::SpawnKey(string strKey, string strValue)
m_strDescription = strreplace("GREEN", "^x4F4GREEN^7", m_strDescription);
m_strDescription = strreplace("YELLOW", "^xFF4YELLOW^7", m_strDescription);
break;
case "mins":
m_vecMins = stov(strValue);
break;
case "maxs":
m_vecMaxs = stov(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
}
@ -79,11 +80,5 @@ info_areadef::Respawn(void)
/* set up our volume */
SetSolid(SOLID_TRIGGER);
SetSize(m_vecMins, m_vecMaxs);
}
void
info_areadef::info_areadef(void)
{
forceinfokey(world, "areadefs", "1");
SetSize(GetSpawnFloat("mins"), GetSpawnFloat("maxs"));
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2025 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
@ -17,33 +17,22 @@
class
info_player_teamspawn:ncSpawnPoint
{
public:
void(void) info_player_teamspawn;
virtual void SpawnKey(string, string);
virtual void Spawned(void);
};
void
info_player_teamspawn::info_player_teamspawn(void)
{
}
void
info_player_teamspawn::SpawnKey(string keyName, string setValue)
{
switch (keyName) {
case "team_no":
team = ReadInt(setValue);
break;
default:
super::SpawnKey(keyName, setValue);
}
}
void
info_player_teamspawn::Spawned(void)
{
team = GetSpawnInt ("team_no");
switch (team) {
case 1:
classname = "info_teamspawn_blue";

View file

@ -242,7 +242,7 @@ info_tfdetect::Setup(void)
}
/* the evil localcmd feature of this entity. */
if (m_strLocalCommand) {
if (STRING_SET(m_strLocalCommand)) {
localcmd(m_strLocalCommand);
localcmd("\n");
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2025 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
@ -119,19 +119,63 @@ private:
string m_strSpawnModel; /* because we mangle it */
};
void
info_tfgoal::info_tfgoal(void)
{
m_tfgState = TFGOAL_INACTIVE;
m_tfgResult = TFRESULT_REMOVE;
m_strName = __NULL__;
m_strActivatedSound = __NULL__;
m_iGoalID = 0i;
m_iGoalGroupID = 0i;
m_tfgActivation = 0;
m_tfgEffects = 0;
m_Activator = __NULL__;
m_dMustCarry = 0.0f;
m_dRespawn = 0.0f;
m_dTeamBlueGain = 0.0f;
m_dTeamRedGain = 0.0f;
m_dTeamYellowGain = 0.0f;
m_dTeamGreenGain = 0.0f;
m_dScore = 0.0f;
m_iTeamUses = 0i;
m_iTeamOwner = 0i;
m_iHealth = 0i;
m_iArmor = 0i;
m_iShells = 0i;
m_iNails = 0i;
m_iCells = 0i;
m_iMedikit = 0i;
m_iRockets = 0i;
m_iDetpack = 0i;
m_msgAll = __NULL__;
m_msgActivator = __NULL__;
m_msgActTeam = __NULL__;
m_msgNonActTeam = __NULL__;
m_msgOwnerTeam = __NULL__;
m_msgNonOwnerTeams = __NULL__;
m_voxAll = __NULL__;
m_voxActivator = __NULL__;
m_voxActTeam = __NULL__;
m_voxNonActTeam = __NULL__;
m_voxOwnerTeam = __NULL__;
m_voxNonOwnerTeams = __NULL__;
m_strSpawnModel = __NULL__;
}
void
info_tfgoal::Spawned(void)
{
super::Spawned();
/* HACK: goals without a targetname and TFGOAL_REMOVED can't work */
if (m_tfgState == TFGOAL_REMOVED && !targetname) {
if (m_tfgState == TFGOAL_REMOVED && HasTargetname() == false) {
m_tfgState = TFGOAL_INACTIVE;
}
}
void
info_tfgoal::Touch(entity eToucher)
info_tfgoal::Touch(entity touchingEntity)
{
item_tfgoal findme = __NULL__;
int rocketType = ammoNumForName("ammo_rockets");
@ -141,10 +185,11 @@ info_tfgoal::Touch(entity eToucher)
int medikitType = ammoNumForName("ammo_medkit");
int detpackType = ammoNumForName("ammo_detpack");
if (eToucher.classname != "player") {
if (isPlayer(touchingEntity) == false) {
return;
}
TFPlayer pl = (TFPlayer)eToucher;
TFPlayer pl = (TFPlayer)touchingEntity;
/* check for state */
if (m_tfgState != TFGOAL_INACTIVE) {
@ -154,7 +199,7 @@ info_tfgoal::Touch(entity eToucher)
/* check for team eligibility */
if (m_iTeamUses)
if (eToucher.team != m_iTeamUses) {
if (touchingEntity.team != m_iTeamUses) {
print("not eligble\n");
return;
}
@ -165,8 +210,9 @@ info_tfgoal::Touch(entity eToucher)
for (entity e = world; (e = find(e, ::classname, "item_tfgoal"));) {
item_tfgoal a = (item_tfgoal)e;
if (a.m_dItemID == m_dMustCarry)
if (a.m_dItemID == m_dMustCarry) {
findme = a;
}
}
if (!findme) {
@ -194,7 +240,7 @@ info_tfgoal::Touch(entity eToucher)
}
sound(this, CHAN_ITEM, m_strActivatedSound, 1.0f, ATTN_NORM);
Logging_Pickup(eToucher, this, m_strName);
Logging_Pickup(touchingEntity, this, m_strName);
/* here we increase/decrease funstuff */
pl.health += m_iHealth;
@ -215,27 +261,27 @@ info_tfgoal::Touch(entity eToucher)
string ts;
if (m_dScore) {
ts = sprintf("teamscore_%i", m_iTeamUses);
forceinfokey(world, ts, sprintf("%d", serverkeyfloat(ts) + m_dScore));
serverinfo.SetFloat(ts, serverkeyfloat(ts) + m_dScore);
}
if (m_dTeamBlueGain) {
ts = "teamscore_1";
forceinfokey(world, ts, sprintf("%d", serverkeyfloat(ts) + m_dTeamBlueGain));
serverinfo.SetFloat(ts, serverkeyfloat(ts) + m_dTeamBlueGain);
}
if (m_dTeamRedGain) {
ts = "teamscore_2";
forceinfokey(world, ts, sprintf("%d", serverkeyfloat(ts) + m_dTeamRedGain));
serverinfo.SetFloat(ts, serverkeyfloat(ts) + m_dTeamRedGain);
}
if (m_dTeamYellowGain) {
ts = "teamscore_3";
forceinfokey(world, ts, sprintf("%d", serverkeyfloat(ts) + m_dTeamYellowGain));
serverinfo.SetFloat(ts, serverkeyfloat(ts) + m_dTeamYellowGain);
}
if (m_dTeamGreenGain) {
ts = "teamscore_4";
forceinfokey(world, ts, sprintf("%d", serverkeyfloat(ts) + m_dTeamGreenGain));
serverinfo.SetFloat(ts, serverkeyfloat(ts) + m_dTeamGreenGain);
}
/* message broadcaster */
if (m_msgAll) {
if (STRING_SET(m_msgAll)) {
env_message_broadcast(m_msgAll);
} else {
for (entity e = world; (e = find(e, ::classname, "player")); ) {
@ -244,20 +290,21 @@ info_tfgoal::Touch(entity eToucher)
} else if (e.team == pl.team ) {
env_message_single(e, m_msgActTeam);
} else if (e.team != pl.team) {
if (e.team == m_iTeamOwner && m_msgOwnerTeam)
if (e.team == m_iTeamOwner && STRING_SET(m_msgOwnerTeam)) {
env_message_single(e, m_msgOwnerTeam);
else {
if (m_msgNonOwnerTeams)
} else {
if (STRING_SET(m_msgNonOwnerTeams)) {
env_message_single(e, m_msgNonOwnerTeams);
else
} else {
env_message_single(e, m_msgNonActTeam);
}
}
}
}
}
/* vox speaker */
if (m_voxAll) {
if (STRING_SET(m_voxAll)) {
Vox_Sentence_Broadcast(m_voxAll);
} else {
for (entity e = world; (e = find(e, ::classname, "player")); ) {
@ -266,13 +313,14 @@ info_tfgoal::Touch(entity eToucher)
} else if (e.team == pl.team ) {
Vox_Sentence_Single(e, m_voxActTeam);
} else if (e.team != pl.team) {
if (e.team == m_iTeamOwner && m_voxOwnerTeam)
if (e.team == m_iTeamOwner && m_voxOwnerTeam) {
Vox_Sentence_Single(e, m_voxOwnerTeam);
else {
if (m_voxNonOwnerTeams)
} else {
if (STRING_SET(m_voxNonOwnerTeams)) {
Vox_Sentence_Single(e, m_voxNonOwnerTeams);
else
} else {
Vox_Sentence_Single(e, m_voxNonActTeam);
}
}
}
}
@ -295,161 +343,155 @@ info_tfgoal::Respawn(void)
SetOrigin(GetSpawnVector("origin"));
team = m_iTeamUses;
if (frags > 0)
if (frags > 0) {
botinfo = BOTINFO_TEAM_GOALCAPTURE;
}
}
void
info_tfgoal::SpawnKey(string strKey, string strValue)
info_tfgoal::SpawnKey(string keyName, string setValue)
{
switch (strKey) {
switch (keyName) {
case "netname":
netname = strValue;
netname = ReadString(setValue);
break;
case "noise":
m_strActivatedSound = strValue;
m_strActivatedSound = ReadString(setValue);
break;
case "model":
case "mdl":
m_strSpawnModel = strValue;
m_strSpawnModel = ReadString(setValue);
if (serverkeyfloat("*bspversion") == 0) {
if (serverinfo.GetInteger("*bspversion") == 0i) {
m_strSpawnModel = strreplace("progs", "models", model);
m_strSpawnModel = strreplace("tf_stan", "flag", model);
}
break;
case "goal_state":
m_tfgState = stof(strValue);
m_tfgState = ReadFloat(setValue);
break;
case "g_a":
m_tfgActivation = stof(strValue);
m_tfgActivation = ReadFloat(setValue);
break;
case "g_e":
m_tfgEffects = stof(strValue);
m_tfgEffects = ReadFloat(setValue);
break;
case "goal_result":
m_tfgResult = stof(strValue);
m_tfgResult = ReadFloat(setValue);
break;
case "items_allowed":
m_dMustCarry = stof(strValue);
m_dMustCarry = ReadFloat(setValue);
break;
case "team_no":
m_iTeamUses = stoi(strValue);
m_iTeamUses = ReadInt(setValue);
break;
case "owned_by":
m_iTeamOwner = stoi(strValue);
m_iTeamOwner = ReadInt(setValue);
break;
case "count":
m_dScore = stof(strValue);
m_dScore = ReadFloat(setValue);
break;
case "wait":
m_dRespawn = stof(strValue);
m_dRespawn = ReadFloat(setValue);
break;
case "increase_team1":
m_dTeamBlueGain = stof(strValue);
m_dTeamBlueGain = ReadFloat(setValue);
break;
case "increase_team2":
m_dTeamRedGain = stof(strValue);
m_dTeamRedGain = ReadFloat(setValue);
break;
case "increase_team3":
m_dTeamYellowGain = stof(strValue);
m_dTeamYellowGain = ReadFloat(setValue);
break;
case "increase_team4":
m_dTeamGreenGain = stof(strValue);
m_dTeamGreenGain = ReadFloat(setValue);
break;
/* messages that get sent */
case "b_b":
m_msgAll = strValue; /* global */
m_msgAll = ReadString(setValue); /* global */
break;
case "message":
m_msgActivator = strValue; /* AP */
m_msgActivator = ReadString(setValue); /* AP */
break;
case "b_t":
case "team_broadcast":
m_msgActTeam = strValue; /* AP team */
m_msgActTeam = ReadString(setValue); /* AP team */
break;
case "b_n":
case "netname_non_team_broadcast":
m_msgNonActTeam = strValue; /* non-AP team */
m_msgNonActTeam = ReadString(setValue); /* non-AP team */
break;
case "b_o":
case "owners_team_broadcast":
m_msgOwnerTeam = strValue; /* owner team */
m_msgOwnerTeam = ReadString(setValue); /* owner team */
break;
case "non_owners_team_broadcast":
m_msgNonOwnerTeams = strValue; /* non-owner team */
m_msgNonOwnerTeams = ReadString(setValue); /* non-owner team */
break;
/* sentences that get played */
case "speak":
m_voxAll = strValue; /* global */
m_voxAll = ReadString(setValue); /* global */
break;
case "AP_speak":
m_voxActivator = strValue; /* AP */
m_voxActivator = ReadString(setValue); /* AP */
break;
case "team_speak":
m_voxActTeam = strValue; /* AP team */
m_voxActTeam = ReadString(setValue); /* AP team */
break;
case "non_team_speak":
m_voxNonActTeam = strValue; /* non-AP team */
m_voxNonActTeam = ReadString(setValue); /* non-AP team */
break;
case "owners_team_speak":
m_voxOwnerTeam = strValue; /* owner team */
m_voxOwnerTeam = ReadString(setValue); /* owner team */
break;
case "non_owners_team_speak":
m_voxNonOwnerTeams = strValue; /* non-owner team */
m_voxNonOwnerTeams = ReadString(setValue); /* non-owner team */
break;
/* AP manipulators */
case "health":
m_iHealth = stoi(strValue);
m_iHealth = ReadInt(setValue);
break;
case "armor":
m_iArmor = stoi(strValue);
m_iArmor = ReadInt(setValue);
break;
case "ammo_shells":
m_iShells = stoi(strValue);
m_iShells = ReadInt(setValue);
break;
case "ammo_nails":
m_iNails = stoi(strValue);
m_iNails = ReadInt(setValue);
break;
case "ammo_rockets":
m_iRockets = stoi(strValue);
m_iRockets = ReadInt(setValue);
break;
case "ammo_cells":
m_iCells = stoi(strValue);
m_iCells = ReadInt(setValue);
break;
case "ammo_medikit":
m_iMedikit = stoi(strValue);
m_iMedikit = ReadInt(setValue);
break;
default:
super::SpawnKey(strKey, strValue);
super::SpawnKey(keyName, setValue);
break;
}
}
void
info_tfgoal::info_tfgoal(void)
{
m_tfgState = TFGOAL_INACTIVE;
m_tfgResult = TFRESULT_REMOVE;
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
SpawnKey(argv(i), argv(i+1));
}
precache_sound(m_strActivatedSound);
super::ncRenderableEntity();
info_tfgoal::Respawn();
}
/* the brush based version of tfgoal */
class i_t_g:info_tfgoal
{
public:
void(void) i_t_g;
virtual void(void) Respawn;
};
void
i_t_g::i_t_g(void)
{
classname = "info_tfgoal";
m_tfgState = TFGOAL_INACTIVE;
m_tfgResult = TFRESULT_NONE;
}
void
i_t_g::Respawn(void)
{
@ -458,26 +500,10 @@ i_t_g::Respawn(void)
SetModel(m_strSpawnModel);
SetOrigin(GetSpawnVector("origin"));
Hide();
team = m_iTeamUses;
if (frags > 0)
if (frags > 0) {
botinfo = BOTINFO_TEAM_GOALCAPTURE;
}
void
i_t_g::i_t_g(void)
{
classname = "info_tfgoal";
m_tfgState = TFGOAL_INACTIVE;
m_tfgResult = TFRESULT_NONE;
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
SpawnKey(argv(i), argv(i+1));
}
super::ncRenderableEntity();
precache_sound(m_strActivatedSound);
Respawn();
}

View file

@ -102,6 +102,21 @@ private:
string m_strSpawnModel; /* because we mangle it */
};
void
item_tfgoal::item_tfgoal(void)
{
m_status = GISTATUS_HOME;
m_returnOwner = m_returnTeam = __NULL__;
m_flPausetime = 0;
}
void
item_tfgoal::Spawned(void)
{
super::Spawned();
precache_sound(m_strSound);
}
void
item_tfgoal::DropReturnable(ncPlayer pp)
{
@ -126,21 +141,22 @@ item_tfgoal::TeamOwnerReturns(void)
Respawn();
for (entity e = world; (e = find(e, ::classname, "player")); ) {
if (e.team == m_iTeamUses)
if (e.team == m_iTeamUses) {
env_message_single(e, m_returnTeam);
else if (e.team == m_iTeamOwner)
} else if (e.team == m_iTeamOwner) {
env_message_single(e, m_returnOwner);
}
}
}
void
item_tfgoal::Touch(entity eToucher)
item_tfgoal::Touch(entity touchingEntity)
{
if (eToucher.classname != "player") {
if (isPlayer(touchingEntity) == false) {
return;
}
TFPlayer pl = (TFPlayer)eToucher;
TFPlayer pl = (TFPlayer)touchingEntity;
/* not in standard TFC, make cvar? */
#if 0
@ -170,7 +186,7 @@ item_tfgoal::Touch(entity eToucher)
sound(this, CHAN_ITEM, m_strSound, 1.0f, ATTN_NONE);
/* message broadcaster */
if (m_msgAll) {
if (STRING_SET(m_msgAll)) {
env_message_broadcast(m_msgAll);
} else {
for (entity e = world; (e = find(e, ::classname, "player")); ) {
@ -192,7 +208,7 @@ item_tfgoal::Touch(entity eToucher)
}
/* vox speaker */
if (m_voxAll) {
if (STRING_SET(m_voxAll)) {
Vox_Sentence_Broadcast(m_voxAll);
} else {
for (entity e = world; (e = find(e, ::classname, "player")); ) {
@ -201,13 +217,14 @@ item_tfgoal::Touch(entity eToucher)
} else if (e.team == pl.team ) {
Vox_Sentence_Single(e, m_voxActTeam);
} else if (e.team != pl.team) {
if (e.team == m_iTeamOwner && m_voxOwnerTeam)
if (e.team == m_iTeamOwner && STRING_SET(m_voxOwnerTeam)) {
Vox_Sentence_Single(e, m_voxOwnerTeam);
else {
if (m_voxNonOwnerTeams)
} else {
if (STRING_SET(m_voxNonOwnerTeams)) {
Vox_Sentence_Single(e, m_voxNonOwnerTeams);
else
} else {
Vox_Sentence_Single(e, m_voxNonActTeam);
}
}
}
}
@ -224,6 +241,7 @@ item_tfgoal::Respawn(void)
m_eActivator = __NULL__;
ReleaseThink();
m_status = GISTATUS_HOME;
SetRenderMode(RM_NORMAL);
/* helps with bots */
team = m_iTeamOwner;
@ -236,24 +254,25 @@ item_tfgoal::Respawn(void)
}
if (m_iTeamOwner) {
SetRenderAmt(1.0f);
SetRenderAmt(1);
SetRenderFX(RFX_GLOWSHELL);
} else
} else {
return;
}
/* spawn into the world */
switch (m_iTeamOwner) {
case 1:
SetRenderColor([0,0,1]);
SetRenderColor([0,0,255]);
break;
case 2:
SetRenderColor([1,0,0]);
SetRenderColor([255,0,0]);
break;
case 3:
SetRenderColor([1,1,0]);
SetRenderColor([255, 255,0]);
break;
case 4:
SetRenderColor([0,1,0]);
SetRenderColor([0,255,0]);
break;
}
}
@ -339,18 +358,3 @@ item_tfgoal::SpawnKey(string strKey, string strValue)
break;
}
}
void
item_tfgoal::Spawned(void)
{
super::Spawned();
precache_sound(m_strSound);
}
void
item_tfgoal::item_tfgoal(void)
{
m_status = GISTATUS_HOME;
m_returnOwner = m_returnTeam = __NULL__;
m_flPausetime = 0;
}

View file

@ -17,25 +17,10 @@
../../../src/gs-entbase/shared.src
defs.h
../shared/include.src
dispenser.qc
sentry.qc
teleporter.qc
func_nobuild.qc
func_nogrenades.qc
vox.qc
entities.src
../../../src/botlib/include.src
bot.qc
info_player_teamspawn.qc
item_tfgoal.qc
info_tfgoal.qc
info_areadef.qc
info_tfdetect.qc
item_armor.qc
item_healthkit.qc
nades.qc
client.qc
server.qc
spawn.qc
../../../src/server/include.src
../../../src/shared/include.src
#endlist

View file

@ -1,157 +0,0 @@
/*
* 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.
*/
float
TFCTeamJoin_SmallestTeam(int blue, int red, int yellow, int green)
{
while (blue > 0i || red > 0i || yellow > 0i || green > 0i) {
/* the first team that goes to 0, gets picked. */
if (blue <= 0i)
return 1;
else if (red <= 0i)
return 2;
else if (yellow <= 0i)
return 3;
else if (green <= 0i)
return 4;
blue--;
red--;
yellow--;
green--;
}
/* the first team that goes to 0, gets picked. */
if (blue == 0i)
return 1;
else if (red == 0i)
return 2;
else if (yellow == 0i)
return 3;
else if (green == 0i)
return 4;
return 0;
}
void
CSEv_TeamJoin_f(float f)
{
TFPlayer pl = (TFPlayer)self;
/* random... */
if (f == 0) {
int bluePlayers = 0i;
int redPlayers = 0i;
int yellowPlayers = 0i;
int greenPlayers = 0i;
/* hack to get it to never pick this team */
if (g_tfcHasBlueTeam == false)
bluePlayers = (int)cvar("sv_playerslots");
if (g_tfcHasRedTeam == false)
redPlayers = (int)cvar("sv_playerslots");
if (g_tfcHasYellowTeam == false)
yellowPlayers = (int)cvar("sv_playerslots");
if (g_tfcHasGreenTeam == false)
greenPlayers = (int)cvar("sv_playerslots");
/* count all valid players within each team */
for (entity e = world; (e = find(e, ::classname, "player"));) {
if (e.team == 1)
bluePlayers++;
else if (e.team == 2)
redPlayers++;
else if (e.team == 3)
yellowPlayers++;
else if (e.team == 4)
greenPlayers++;
}
/* assign us to the team with the lowest amount of players */
f = TFCTeamJoin_SmallestTeam(bluePlayers, redPlayers, yellowPlayers, greenPlayers);
}
/* mess, do it better */
if (f == 1) {
pl.team = 1; /* Blue */
forceinfokey(pl, "topcolor", "0x9aff");
forceinfokey(pl, "bottomcolor", "0x9aff");
} else if (f == 2) {
pl.team = 2; /* Red */
f -= 10;
forceinfokey(pl, "topcolor", "0xff1800");
forceinfokey(pl, "bottomcolor", "0xff1800");
} else if (f == 3) {
pl.team = 3; /* Yellow */
f -= 20;
forceinfokey(pl, "topcolor", "0xffca00");
forceinfokey(pl, "bottomcolor", "0xffca00");
} else if (f == 4) {
pl.team = 4; /* Green */
f -= 30;
forceinfokey(pl, "topcolor", "0x3bff00");
forceinfokey(pl, "bottomcolor", "0x3bff00");
} else {
return;
}
if (self.health > 0) {
ClientKill();
return;
}
}
/** Called by the client-side VGUI menu when we choose a class. */
void
CSEv_ClassJoin_f(float f)
{
TFPlayer pl = (TFPlayer)self;
/* choose a random class. */
if (f == 0) {
float newClass = 0;
while (newClass == 0 || newClass == pl.classtype)
newClass = floor(random(CLASS_SCOUT, CLASS_ENGINEER + 1));
f = newClass;
}
/* invalid */
if (pl.team == 0) {
return;
}
/* invalid */
if (pl.classtype == f)
return;
/* if we're still alive... */
if (pl.health > 0) {
pl.classtype = f;
pl.MakeClass(f);
ClientKill();
} else {
/* insta spawn */
/* assign our class type for safe keeping */
pl.classtype = f;
/* turn the player into the class of his choice */
pl.MakeClass(f);
}
}

View file

@ -1,40 +0,0 @@
/*
* Copyright (c) 2022 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
Vox_Sentence_Broadcast(string msg)
{
if (!msg || msg == "")
return;
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_TFC_VOXMSG);
WriteString(MSG_MULTICAST, msg);
multicast([0,0,0], MULTICAST_ALL_R);
}
void
Vox_Sentence_Single(entity targ, string msg)
{
if (!msg || msg == "")
return;
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_TFC_VOXMSG);
WriteString(MSG_MULTICAST, msg);
msg_entity = targ;
multicast([0,0,0], MULTICAST_ONE_R);
}

View file

@ -12,5 +12,6 @@ player.qc
animations_tfc.h
../../../valve/src/shared/animations.qc
pmove.qc
vox.qc
../../../valve/src/shared/HLWeapon.qc
#endlist

View file

@ -47,6 +47,7 @@ TFPlayer:HLPlayer
nonvirtual void TFC_ReleaseGren1(void);
nonvirtual void TFC_ReleaseGren2(void);
virtual void UpdatePlayerAnimation(float);
virtual void Physics_InputPreMove(void);
#ifdef CLIENT
virtual void ReceiveEntity(float,float);
@ -62,9 +63,6 @@ TFPlayer:HLPlayer
virtual void EvaluateEntity(void);
virtual float SendEntity(entity, float);
virtual void SpawnIntoGame(void);
virtual void MakeClass(classtype_e);
virtual void ServerInputFrame(void);
nonvirtual void TFC_FragSelf(void);
@ -77,6 +75,17 @@ TFPlayer::TFPlayer(void)
{
}
void
TFPlayer::Physics_InputPreMove(void)
{
super::Physics_InputPreMove();
gflags &= ~GF_NOBUILDZONE;
gflags &= ~GF_NOGRENADEZONE;
}
void
TFPlayer::UpdatePlayerAnimation(float timelength)
{
@ -389,83 +398,6 @@ TFPlayer::EvaluateEntity(void)
EVALUATE_FIELD(m_flHallucination, PLAYER_AMMOTYPES)
}
void
TFPlayer::SpawnIntoGame(void)
{
entity spot = world;
/* spawn into the world */
switch (team) {
case 1:
spot = Spawn_SelectRandom("info_teamspawn_blue");
break;
case 2:
spot = Spawn_SelectRandom("info_teamspawn_red");
break;
case 3:
spot = Spawn_SelectRandom("info_teamspawn_yellow");
break;
case 4:
spot = Spawn_SelectRandom("info_teamspawn_green");
break;
}
setorigin(this, spot.origin);
angles = spot.angles;
fixangle = TRUE;
}
void
TFPlayer::MakeClass(classtype_e classType)
{
int oldTeam = team;
switch (classType) {
case CLASS_SCOUT:
EntityDef_SpawnClassname("player_scout");
env_message_single(this, "HELP_SCOUT");
break;
case CLASS_SNIPER:
EntityDef_SpawnClassname("player_sniper");
env_message_single(this, "HELP_SNIPER");
break;
case CLASS_SOLDIER:
EntityDef_SpawnClassname("player_soldier");
env_message_single(this, "HELP_SOLDIER");
break;
case CLASS_DEMO:
EntityDef_SpawnClassname("player_demo");
env_message_single(this, "HELP_DEMOMAN");
break;
case CLASS_MEDIC:
EntityDef_SpawnClassname("player_medic");
env_message_single(this, "HELP_MEDIC");
break;
case CLASS_HVYWEAPON:
EntityDef_SpawnClassname("player_heavy");
env_message_single(this, "HELP_HWGUY");
break;
case CLASS_PYRO:
EntityDef_SpawnClassname("player_pyro");
env_message_single(this, "HELP_PYRO");
break;
case CLASS_SPY:
EntityDef_SpawnClassname("player_spy");
env_message_single(this, "HELP_SPY");
break;
case CLASS_ENGINEER:
EntityDef_SpawnClassname("player_engineer");
env_message_single(this, "HELP_ENGINEER");
break;
}
MakePlayer();
team = oldTeam;
forceinfokey(this, "*team", ftos(team));
GiveItem("item_suit");
SpawnIntoGame();
}
float
TFPlayer::SendEntity(entity ePEnt, float flChanged)
{

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2022-2025 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,35 +14,65 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef CLIENT
class
TFCVox:ncTalkMonster
VOX:ncTalkMonster
{
void(void) TFCVox;
public:
void(void) VOX;
virtual void(string) SentenceSample;
};
TFCVox g_vox;
void
TFCVox::SentenceSample(string sample)
VOX::SentenceSample(string sample)
{
sound(this, CHAN_VOICE, sample, 1.0, ATTN_NONE, 100, SOUNDFLAG_FOLLOW | SOUNDFLAG_NOSPACIALISE);
}
void
TFCVox::TFCVox(void)
VOX:: VOX(void)
{
}
void
Vox_Parse(void)
{
static VOX voxDelegate;
string msg = readstring();
if (!g_vox)
g_vox = spawn(TFCVox);
if (!voxDelegate) {
voxDelegate = spawn(VOX);
}
print(msg);
print("\n");
g_vox.Sentence(msg);
voxDelegate.Sentence(msg);
}
#endif
#ifdef SERVER
void
Vox_Sentence_Broadcast(string wordsToBroadcast)
{
if (!STRING_SET(wordsToBroadcast)) {
return;
}
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_TFC_VOXMSG);
WriteString(MSG_MULTICAST, wordsToBroadcast);
multicast(g_vec_null, MULTICAST_ALL_R);
}
void
Vox_Sentence_Single(entity targetClient, string wordsToVOX)
{
if (!STRING_SET(wordsToVOX)) {
return;
}
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_TFC_VOXMSG);
WriteString(MSG_MULTICAST, wordsToVOX);
msg_entity = targetClient;
multicast(g_vec_null, MULTICAST_ONE_R);
}
#endif

View file

@ -1,296 +0,0 @@
/*
* Copyright (c) 2016-2021 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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.
*/
/* Animations */
enum
{
ASSCAN_IDLE1,
ASSCAN_IDLE2,
ASSCAN_SPINUP,
ASSCAN_SPINDOWN,
ASSCAN_FIRE,
ASSCAN_DRAW,
ASSCAN_HOLSTER
};
#ifdef CLIENT
void w_asscan_ejectshell(void)
{
static void w_asscan_ejectshell_death(void) {
remove(self);
}
static void w_asscan_ejectshell_touch(void) {
if (other == world)
Sound_Play(self, CHAN_BODY, "modelevent_shell.land");
}
entity eShell = spawn();
setmodel(eShell, "models/shell.mdl");
eShell.solid = SOLID_BBOX;
eShell.movetype = MOVETYPE_BOUNCE;
eShell.drawmask = MASK_ENGINE;
eShell.angles = [pSeat->m_eViewModel.angles[0], pSeat->m_eViewModel.angles[1], 0];
eShell.velocity = pSeat->m_vecPredictedVelocity;
makevectors(pSeat->m_eViewModel.angles);
eShell.velocity += (v_forward * 0);
eShell.velocity += (v_right * -80);
eShell.velocity += (v_up * 100);
eShell.touch = w_asscan_ejectshell_touch;
eShell.avelocity = [0,45,900];
eShell.think = w_asscan_ejectshell_death;
eShell.nextthink = time + 2.5f;
setsize(eShell, [0,0,0], [0,0,0]);
setorigin(eShell, pSeat->m_eViewModel.origin + (v_forward * 26) + (v_up * -15));
}
#endif
void
w_asscan_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_asscan.fire");
Sound_Precache("weapon_asscan.reload");
Sound_Precache("weapon_asscan.spindown");
Sound_Precache("weapon_asscan.spinup");
precache_model("models/w_tfac.mdl");
precache_model("models/p_tfac.mdl");
#endif
#ifdef CLIENT
precache_model("models/v_tfac.mdl");
Sound_Precache("modelevent_shell.land");
#endif
}
int
w_asscan_pickup(player pl, int new, int startammo)
{
return (1);
}
void
w_asscan_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, -1, pl.m_iAmmoShells, -1);
}
string
w_asscan_wmodel(void)
{
return "models/w_tfac.mdl";
}
string
w_asscan_pmodel(player pl)
{
return "models/p_mini2.mdl";
}
string
w_asscan_deathmsg(void)
{
return "%s was rolled over by %s' Chaingun.";
}
void
w_asscan_draw(player pl)
{
pl.mode_tempstate = 0;
Weapons_SetModel("models/v_tfac.mdl");
Weapons_ViewAnimation(pl, ASSCAN_DRAW);
}
void
w_asscan_holster(player pl)
{
Weapons_ViewAnimation(pl, ASSCAN_HOLSTER);
}
void
w_asscan_release(player pl)
{
/* end firing */
if (pl.mode_tempstate == 1) {
pl.mode_tempstate = 0;
Weapons_Sound(pl, CHAN_WEAPON, "weapon_asscan.spindown");
Weapons_ViewAnimation(pl, ASSCAN_SPINDOWN);
pl.w_attack_next = 1.0f;
pl.w_idle_next = 4.0f;
return;
}
if (pl.w_idle_next > 0.0)
return;
int r = (float)input_sequence % 2;
if (r) {
Weapons_ViewAnimation(pl, ASSCAN_IDLE1);
} else {
Weapons_ViewAnimation(pl, ASSCAN_IDLE2);
}
pl.w_idle_next = 15.0f;
}
void
w_asscan_primary(player pl)
{
/* rate check */
if (pl.w_attack_next > 0.0)
return;
/* ammo check */
if (pl.m_iAmmoShells <= 0) {
w_asscan_release(pl);
return;
}
/* spin up first */
if (pl.mode_tempstate == 0) {
pl.mode_tempstate = 1;
Weapons_ViewAnimation(pl, ASSCAN_SPINUP);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_asscan.spinup");
pl.w_attack_next = 0.5f;
pl.w_idle_next = pl.w_attack_next;
return;
}
/* from now on we're just going rambo */
pl.m_iAmmoShells--;
Weapons_ViewAnimation(pl, ASSCAN_FIRE);
Weapons_ViewPunchAngle(pl, [random(-2, 2),0,0]);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_asscan.fire");
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTASSCAN, 0.1f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTASSCAN, 0.1f);
#ifdef CLIENT
View_AddEvent(w_asscan_ejectshell, 0.0f);
View_SetMuzzleflash(MUZZLE_WEIRD);
#else
TraceAttack_FireBullets(1, Weapons_GetCameraPos(pl), 8, [0.15,0.15], WEAPON_ASSCAN);
#endif
pl.w_attack_next = 0.1f;
pl.w_idle_next = 0.0f;
}
void
w_asscan_hud(player pl)
{
#ifdef CLIENT
vector aicon_pos;
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
Cross_DrawSub(g_cross_spr, [24,24], [48/128,24/128], [0.1875, 0.1875]);
HUD_DrawAmmo2();
drawsubpic(aicon_pos, [24,24], g_hud7_spr, [72/256,72/128], [24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
float
w_asscan_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMASSCAN : TFCANIM_AIMASSCAN;
}
void
w_asscan_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
vector hud_col;
if (pl.m_iAmmoShells == 0)
hud_col = [1,0,0];
else
hud_col = g_hud_color;
HUD_DrawAmmoBar(pos, pl.m_iAmmoShells, 200, a);
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud4_spr,
[0,90/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud3_spr,
[0,45/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
int
w_asscan_isempty(player pl)
{
if (pl.m_iAmmoShells <= 0)
return 1;
return 0;
}
weapontype_t
w_asscan_type(player pl)
{
return WPNTYPE_RANGED;
}
weapon_t w_asscan =
{
.name = "asscan",
.id = ITEM_ASSCAN,
.slot = 3,
.slot_pos = 3,
.weight = WEIGHT_ASSCAN,
.draw = w_asscan_draw,
.holster = w_asscan_holster,
.primary = w_asscan_primary,
.secondary = w_asscan_release,
.reload = __NULL__,
.release = w_asscan_release,
.postdraw = w_asscan_hud,
.precache = w_asscan_precache,
.pickup = w_asscan_pickup,
.updateammo = w_asscan_updateammo,
.wmodel = w_asscan_wmodel,
.pmodel = w_asscan_pmodel,
.deathmsg = w_asscan_deathmsg,
.aimanim = w_asscan_aimanim,
.isempty = w_asscan_isempty,
.type = w_asscan_type,
.hudpic = w_asscan_hudpic
};

View file

@ -1,187 +0,0 @@
/*
* 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.
*/
enum
{
SNIPER_IDLE,
SNIPER_AIM,
SNIPER_FIRE,
SNIPER_DRAW,
SNIPER_HOLSTER,
SNIPER_AUTOIDLE,
SNIPER_AUTOFIRE,
SNIPER_AUTODRAW,
SNIPER_AUTOHOLSTER,
};
void
w_autorifle_precache(void)
{
precache_model("models/v_tfc_sniper.mdl");
precache_model("models/p_sniper2.mdl");
Sound_Precache("weapon_sniper.fire");
}
void
w_autorifle_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, __NULL__, pl.m_iAmmoShells, __NULL__);
}
string
w_autorifle_wmodel(void)
{
return "";
}
string
w_autorifle_pmodel(player pl)
{
return "models/p_sniper2.mdl";
}
string
w_autorifle_deathmsg(void)
{
return "%s was assaulted by %s's Assault Cannon.";
}
void
w_autorifle_release(player pl)
{
if (pl.w_idle_next > 0)
return;
Weapons_ViewAnimation(pl, SNIPER_AUTOIDLE);
}
void
w_autorifle_draw(player pl)
{
Weapons_SetModel("models/v_tfc_sniper.mdl");
Weapons_ViewAnimation(pl, SNIPER_AUTODRAW);
pl.w_idle_next = 1.0f;
}
float
w_autorifle_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMAUTOSNIPER : TFCANIM_AIMAUTOSNIPER;
}
void
w_autorifle_primary(player pl)
{
int s = w_baseauto_fire(WEAPON_AUTORIFLE, player::m_iAmmoShells, 8, [0,0]);
switch (s) {
case AUTO_FIRE_FAILED:
return;
break;
case AUTO_FIRED:
case AUTO_LAST:
Weapons_ViewAnimation(pl, SNIPER_AUTOFIRE);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTAUTOSNIPER, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTAUTOSNIPER, 0.45f);
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_RIFLE);
#endif
Weapons_Sound(pl, CHAN_WEAPON, "weapon_sniper.fire");
pl.w_attack_next = 0.1f;
break;
case AUTO_EMPTY:
w_autorifle_release(pl);
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 0.0f;
}
void
w_autorifle_postdraw(player pl)
{
#ifdef CLIENT
// crosshair
if (pl.viewzoom == 1) {
Cross_DrawSub(g_cross_spr, [24,24], [72/128,0], [0.1875, 0.1875]);
} else {
Cross_DrawSub(g_cross_spr, [104,16], [24/128,96/128], [104/128, 16/128]);
}
// ammo counter
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [24,24], "sprites/640hud7.spr_0.tga", [72/256,72/128], [24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
void
w_autorifle_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud2_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud1_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_autorifle =
{
.name = "autorifle",
.id = ITEM_AUTORIFLE,
.slot = 2,
.slot_pos = 0,
.weight = WEIGHT_AUTORIFLE,
.draw = w_autorifle_draw,
.holster = __NULL__,
.primary = w_autorifle_primary,
.secondary = w_autorifle_release,
.reload = __NULL__,
.release = w_autorifle_release,
.postdraw = w_autorifle_postdraw,
.precache = w_autorifle_precache,
.pickup = __NULL__,
.updateammo = w_autorifle_updateammo,
.wmodel = __NULL__,
.pmodel = w_autorifle_pmodel,
.deathmsg = w_autorifle_deathmsg,
.aimanim = w_autorifle_aimanim,
.hudpic = w_autorifle_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,228 +0,0 @@
/*
* Copyright (c) 2016-2021 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 weapon_crowbar (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_crowbar.mdl"
HALF-LIFE (1998) ENTITY
Crowbar Weapon
*/
enum
{
CBAR_IDLE,
CBAR_DRAW,
CBAR_HOLSTER,
CBAR_ATTACK1HIT,
CBAR_ATTACK1MISS,
CBAR_ATTACK2MISS,
CBAR_ATTACK2HIT,
CBAR_ATTACK3MISS,
CBAR_ATTACK3HIT
};
void
w_crowbar_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_crowbar.hit");
Sound_Precache("weapon_crowbar.miss");
Sound_Precache("weapon_crowbar.hitbody");
precache_model("models/w_crowbar.mdl");
#else
precache_model("models/v_tfc_crowbar.mdl");
precache_model("models/p_crowbar.mdl");
#endif
}
void
w_crowbar_updateammo(player pl)
{
}
string
w_crowbar_wmodel(void)
{
return "models/w_crowbar.mdl";
}
string
w_crowbar_pmodel(player pl)
{
return "models/p_crowbar.mdl";
}
string
w_crowbar_deathmsg(void)
{
return "%s was assaulted by %s's Crowbar.";
}
void
w_crowbar_draw(player pl)
{
Weapons_SetModel("models/v_tfc_crowbar.mdl");
Weapons_ViewAnimation(pl, CBAR_DRAW);
}
void
w_crowbar_holster(player pl)
{
Weapons_ViewAnimation(pl, CBAR_HOLSTER);
}
void
w_crowbar_primary(player pl)
{
int anim = 0;
vector src;
if (pl.w_attack_next) {
return;
}
Weapons_MakeVectors(pl);
src = pl.origin + pl.view_ofs;
/* make sure we can gib corpses */
int oldhitcontents = self.hitcontentsmaski;
self.hitcontentsmaski = CONTENTBITS_POINTSOLID | CONTENTBIT_CORPSE;
traceline(src, src + (v_forward * 32), FALSE, pl);
self.hitcontentsmaski = oldhitcontents;
if (trace_fraction >= 1.0) {
pl.w_attack_next = 0.5f;
} else {
pl.w_attack_next = 0.25f;
}
pl.w_idle_next = 2.5f;
int r = (float)input_sequence % 3;
switch (r) {
case 0:
Weapons_ViewAnimation(pl, trace_fraction >= 1 ? CBAR_ATTACK1MISS:CBAR_ATTACK1HIT);
break;
case 1:
Weapons_ViewAnimation(pl, trace_fraction >= 1 ? CBAR_ATTACK2MISS:CBAR_ATTACK2HIT);
break;
default:
Weapons_ViewAnimation(pl, trace_fraction >= 1 ? CBAR_ATTACK3MISS:CBAR_ATTACK3HIT);
}
if (pl.IsCrouching())
Animation_PlayerTop(pl, ANIM_CR_SHOOTCROWBAR, 0.41f);
else
Animation_PlayerTop(pl, ANIM_SHOOTCROWBAR, 0.5f);
#ifdef SERVER
Sound_Play(self, CHAN_WEAPON, "weapon_crowbar.miss");
if (trace_fraction >= 1.0) {
return;
}
/* don't bother with decals, we got squibs */
if (trace_ent.iBleeds) {
FX_Blood(trace_endpos, [1,0,0]);
} else {
SurfData_Impact(trace_ent, trace_endpos, trace_plane_normal);
}
if (trace_ent.takedamage) {
Damage_Apply(trace_ent, pl, 18, WEAPON_CROWBAR, DMG_BLUNT);
if (trace_ent.iBleeds) {
Sound_Play(self, CHAN_WEAPON, "weapon_crowbar.hitbody");
}
} else {
Sound_Play(self, CHAN_WEAPON, "weapon_crowbar.hit");
}
#endif
}
void
w_crowbar_release(player pl)
{
if (pl.w_idle_next) {
return;
}
Weapons_ViewAnimation(pl, CBAR_IDLE);
pl.w_idle_next = 15.0f;
}
float
w_crowbar_aimanim(player pl)
{
return pl.IsCrouching() ? ANIM_CR_AIMCROWBAR : ANIM_AIMCROWBAR;
}
void
w_crowbar_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_hud4_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_hud1_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_crowbar =
{
.name = "crowbar",
.id = ITEM_CROWBAR,
.slot = 0,
.slot_pos = 0,
.weight = WEIGHT_CROWBAR,
.draw = w_crowbar_draw,
.holster = w_crowbar_holster,
.primary = w_crowbar_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = w_crowbar_release,
.postdraw = __NULL__,
.precache = w_crowbar_precache,
.pickup = __NULL__,
.updateammo = w_crowbar_updateammo,
.wmodel = w_crowbar_wmodel,
.pmodel = w_crowbar_pmodel,
.deathmsg = w_crowbar_deathmsg,
.aimanim = w_crowbar_aimanim,
.hudpic = w_crowbar_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,222 +0,0 @@
/*
* 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.
*/
enum
{
DBS_IDLE1,
DBS_FIRE1,
DBS_FIRE2,
DBS_ADDSHELL,
DBS_PUMP,
DBS_START_RELOAD,
DBS_DRAW,
DBS_HOLSTER,
DBS_IDLE2,
DBS_IDLE3
};
void
w_dbs_precache(void)
{
precache_model("models/v_tfc_shotgun.mdl");
precache_model("models/w_shot2.mdl");
precache_model("models/p_shot2.mdl");
#ifdef SERVER
Sound_Precache("weapon_dbs.cock");
Sound_Precache("weapon_dbs.fire");
Sound_Precache("weapon_dbs.reload");
#endif
}
void
w_dbs_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.mag_dbs, pl.m_iAmmoShells, __NULL__);
}
string
w_dbs_wmodel(void)
{
return "models/w_shot2.mdl";
}
string
w_dbs_pmodel(player pl)
{
return "models/p_shotgun2.mdl";
}
string
w_dbs_deathmsg(void)
{
return "";
}
int
w_dbs_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
pl.mag_dbs = bound(0, pl.mag_dbs + 16, 16);
#endif
return (1);
}
void
w_dbs_draw(player pl)
{
Weapons_SetModel("models/v_tfc_shotgun.mdl");
Weapons_ViewAnimation(pl, DBS_DRAW);
}
void
w_dbs_holster(player pl)
{
Weapons_ViewAnimation(pl, DBS_HOLSTER);
}
void
w_dbs_primary(player pl)
{
int s;
if (pl.mag_dbs != 1)
s = w_baseshotgun_fire(WEAPON_DBS, player::mag_dbs, 14, 4, [0.14, 0.08, 0]);
else
s = w_baseshotgun_fire(WEAPON_DBS, player::mag_dbs, 6, 4, [0.14, 0.08, 0]);
switch (s) {
case AUTO_FIRE_FAILED:
return;
break;
case AUTO_LAST:
case AUTO_FIRED:
pl.mag_dbs--;
Weapons_ViewAnimation(pl, DBS_FIRE1);
Weapons_ViewPunchAngle(pl, [-2,0,0]);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTSHOTGUN, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTSHOTGUN, 0.45f);
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_ROUND);
#endif
Weapons_Sound(pl, CHAN_WEAPON, "weapon_dbs.fire");
pl.w_attack_next = 0.7f;
break;
case AUTO_EMPTY:
Weapons_Sound(pl, CHAN_WEAPON, "weapon_dbs.fire_empty");
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 1.5f;
}
void
w_dbs_reload(player pl)
{
w_baseshotgun_reload(player::mag_dbs, player::m_iAmmoShells, 16);
}
void
w_dbs_release(player pl)
{
int s = w_baseshotgun_release(player::mag_dbs, player::m_iAmmoShells, 16);
switch (s) {
case SHOTGUN_IDLE:
int r = (float)input_sequence % 3;
if (r == 1) {
Weapons_ViewAnimation(pl, DBS_IDLE1);
} else if (r == 2) {
Weapons_ViewAnimation(pl, DBS_IDLE2);
} else {
Weapons_ViewAnimation(pl, DBS_IDLE3);
}
pl.w_idle_next = 5.0f;
break;
case SHOTGUN_BUSY:
break;
case SHOTGUN_START_RELOAD:
Weapons_ViewAnimation(pl, DBS_START_RELOAD);
break;
case SHOTGUN_RELOAD:
Weapons_ViewAnimation(pl, DBS_ADDSHELL);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_dbs.reload");
break;
case SHOTGUN_END_RELOAD:
Weapons_ViewAnimation(pl, DBS_PUMP);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_dbs.cock");
break;
}
}
void
w_dbs_crosshair(player pl)
{
#ifdef CLIENT
Cross_DrawSub(g_cross_spr, [24,24], [48/128,24/128], [0.1875, 0.1875]);
HUD_DrawAmmo1();
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [24,24], "sprites/640hud7.spr_0.tga", [72/256,72/128], [24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
float
w_dbs_aimanim(player pl)
{
return pl.IsCrouching() ? ANIM_CR_AIMSHOTGUN : ANIM_AIMSHOTGUN;
}
void
w_dbs_hudpic(player pl, int s, vector pos, float a)
{
#ifdef CLIENT
if (s) {
drawsubpic(pos, [170,45], g_hud4_spr, [0,180/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
} else {
drawsubpic(pos, [170,45], g_hud1_spr, [0,180/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
}
#endif
}
weapon_t w_dbs =
{
.name = "sbs",
.id = ITEM_DBS,
.slot = 2,
.slot_pos = 1,
.weight = WEIGHT_DBS,
.draw = w_dbs_draw,
.holster = w_dbs_holster,
.primary = w_dbs_primary,
.secondary = w_dbs_release,
.reload = w_dbs_reload,
.release = w_dbs_release,
.postdraw = w_dbs_crosshair,
.precache = w_dbs_precache,
.pickup = w_dbs_pickup,
.updateammo = w_dbs_updateammo,
.wmodel = w_dbs_wmodel,
.pmodel = w_dbs_pmodel,
.deathmsg = w_dbs_deathmsg,
.aimanim = w_dbs_aimanim,
.hudpic = w_dbs_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,255 +0,0 @@
/*
* Copyright (c) 2016-2021 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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.
*/
enum
{
EGON_IDLE1,
EGON_FIDGET1,
EGON_ALTFIREON,
EGON_ALTFIRECYCLE,
EGON_ALTFIREOFF,
EGON_FIRE1,
EGON_FIRE2,
EGON_FIRE3,
EGON_FIRE4,
EGON_DRAW,
EGON_HOLSTER
};
void
w_flamer_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_flame.fire");
precache_model("sprites/fthrow.spr");
#endif
precache_model("models/v_flame.mdl");
precache_model("models/w_egon.mdl");
precache_model("models/p_egon.mdl");
}
void
w_flamer_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, -1, pl.m_iAmmoCells, -1);
}
string
w_flamer_wmodel(void)
{
return "models/w_egon.mdl";
}
string
w_flamer_pmodel(player pl)
{
return "models/p_egon2.mdl";
}
string
w_flamer_deathmsg(void)
{
return "%s burned to a crisp by %s's Flamethrower.";
}
int
w_flamer_pickup(player pl, int new, int startammo)
{
return (1);
}
void
w_flamer_draw(player pl)
{
Weapons_SetModel("models/v_flame.mdl");
Weapons_ViewAnimation(pl, EGON_DRAW);
}
void
w_flamer_holster(player pl)
{
}
void
w_flamer_primary(player pl)
{
if (pl.w_attack_next > 0.0)
return;
/* Ammo check */
if (pl.m_iAmmoCells <= 0)
return;
pl.m_iAmmoCells--;
Weapons_ViewAnimation(pl, EGON_FIRE1);
#ifdef SERVER
static void w_flamer_die(void) {
ncEntity::Destroy();
}
static void w_flamer_touch(entity target, entity source) {
ncEntity me = (ncEntity)source;
if (target.takedamage == DAMAGE_YES) {
ncSurfacePropEntity m = (ncSurfacePropEntity)target;
m.Ignite(source, 5.0f, WEAPON_FLAMER);
}
}
Sound_Play(pl, CHAN_WEAPON, "weapon_flame.fire");
ncProjectile ball = spawn(ncProjectile);
ball.SetModel("sprites/fthrow.spr");
ball.SetRenderMode(RM_ADDITIVE);
ball.SetOwner(pl);
ball.SetImpact(w_flamer_touch);
ball.AnimateOnce(0, 15, 0.1f);
// To be added to spec
// ball.Animate(0,15);
// ball.effects |= EF_BRIGHTLIGHT;
// Also will need check for water contents (so projectile will die underwater)
Weapons_MakeVectors(pl);
ball.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 16));
ball.SetVelocity(v_forward * 300);
#endif
pl.w_attack_next = 0.2f;
pl.w_idle_next = 0.2f;
}
void
w_flamer_reload(player pl)
{
}
void
w_flamer_release(player pl)
{
if (pl.w_attack_next > 0)
return;
if (pl.w_idle_next > 0)
return;
Weapons_ViewAnimation(pl, EGON_IDLE1);
}
void
w_flamer_crosshair(player pl)
{
#ifdef CLIENT
Cross_DrawSub(g_cross_spr, [24,24], [48/128,24/128], [0.1875, 0.1875]);
//Cross_DrawSub(g_cross_spr, [24,24], [72/128,48/128], [0.1875, 0.1875]);
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [24,24], g_hud7_spr, [0,96/128], [24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
float
w_flamer_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMEGON : TFCANIM_AIMEGON;
}
void
w_flamer_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
vector hud_col;
if (pl.m_iAmmoCells == 0)
hud_col = [1,0,0];
else
hud_col = g_hud_color;
HUD_DrawAmmoBar(pos, pl.m_iAmmoCells, 200, a);
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud4_spr,
[0,45/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud3_spr,
[0,0/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
int
w_flamer_isempty(player pl)
{
if (pl.m_iAmmoCells <= 0)
return 1;
return 0;
}
weapontype_t
w_flamer_type(player pl)
{
return WPNTYPE_RANGED;
}
weapon_t w_flamer =
{
.name = "flamer",
.id = ITEM_FLAMER,
.slot = 3,
.slot_pos = 2,
.weight = WEIGHT_FLAMER,
.draw = w_flamer_draw,
.holster = __NULL__,
.primary = w_flamer_primary,
.secondary = w_flamer_release,
.reload = __NULL__,
.release = w_flamer_release,
.postdraw = w_flamer_crosshair,
.precache = w_flamer_precache,
.pickup = w_flamer_pickup,
.updateammo = w_flamer_updateammo,
.wmodel = w_flamer_wmodel,
.pmodel = w_flamer_pmodel,
.deathmsg = w_flamer_deathmsg,
.aimanim = w_flamer_aimanim,
.isempty = w_flamer_isempty,
.type = w_flamer_type,
.hudpic = w_flamer_hudpic
};

View file

@ -1,279 +0,0 @@
/*
* 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.
*/
typedef enum
{
GLAUNCHER_GIDLE,
GLAUNCHER_PIDLE,
GLAUNCHER_GFIRE,
GLAUNCHER_PFIRE,
GLAUNCHER_GRELOAD1,
GLAUNCHER_GRELOAD2,
GLAUNCHER_PRELOAD1,
GLAUNCHER_PRELOAD2,
GLAUNCHER_GDRAW,
GLAUNCHER_PDRAW,
GLAUNCHER_GHOLSTER,
GLAUNCHER_PHOLSTER
} w_glauncher_anims_t;
void
w_glauncher_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_handgrenade.bounce");
Sound_Precache("weapon_mp5.gl");
precache_model("models/w_glauncher.mdl");
precache_model("models/p_glauncher.mdl");
precache_model("models/pipebomb.mdl");
#else
precache_model("models/v_tfgl.mdl");
#endif
}
void
w_glauncher_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.mag_glauncher, pl.m_iAmmoRockets, __NULL__);
}
int
w_glauncher_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
pl.mag_glauncher = bound(0, pl.mag_glauncher + 6, 6);
#endif
return (1);
}
string
w_glauncher_wmodel(void)
{
return "models/w_glauncher.mdl";
}
string
w_glauncher_pmodel(player pl)
{
return "models/p_glauncher2.mdl";
}
string
w_glauncher_deathmsg(void)
{
return "%s was assaulted by %s's Assault Cannon.";
}
void
w_glauncher_draw(player pl)
{
Weapons_SetModel("models/v_tfgl.mdl");
Weapons_ViewAnimation(pl, GLAUNCHER_GDRAW);
}
void
w_glauncher_shootnade(player pl)
{
#ifdef SERVER
vector vecNadeVelocity;
static void w_glauncher_shootnade_touch(void) {
Sound_Play(self, CHAN_BODY, "weapon_handgrenade.bounce");
if (vlen(self.velocity))
self.avelocity = g_vec_null;
}
static void w_glauncher_explode(void) {
float dmg = 100;
pointparticles(particleeffectnum("fx_explosion.main"), self.origin, [0,0,0], 1);
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_GLAUNCHER);
Sound_Play(self, CHAN_VOICE, "fx.explosion");
ncEntity::Destroy();
}
Weapons_MakeVectors(pl);
vecNadeVelocity = v_forward * 600 + v_up * 200 + crandom() * v_right * 10 + crandom() * v_up * 10;
ncRenderableEntity eNade = spawn(ncRenderableEntity);
eNade.SetModel("models/pipebomb.mdl");
eNade.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
eNade.SetMovetype(MOVETYPE_BOUNCE);
eNade.SetSolid(SOLID_BBOX);
eNade.SetGravity(1.0f);
eNade.SetVelocity(vecNadeVelocity);
eNade.SetAngularVelocity([300, 300, 300]);
eNade.SetAngles(vectoangles(eNade.GetVelocity()));
eNade.SetSkin(1);
eNade.touch = w_glauncher_shootnade_touch;
eNade.think = w_glauncher_explode;
eNade.nextthink = time + 2.5f;
Sound_Play(pl, CHAN_WEAPON, "weapon_mp5.gl");
//eNade.traileffectnum = particleeffectnum("weapon_rpg.trail");
#endif
}
void
w_glauncher_reload(player pl)
{
w_baseshotgun_reload(player::mag_glauncher, player::m_iAmmoRockets, 6);
}
void
w_glauncher_release(player pl)
{
int s = w_baseshotgun_release(player::mag_glauncher, player::m_iAmmoRockets, 6);
switch (s) {
case SHOTGUN_IDLE:
Weapons_ViewAnimation(pl, GLAUNCHER_GIDLE);
pl.w_idle_next = 5.0f;
break;
case SHOTGUN_BUSY:
break;
case SHOTGUN_START_RELOAD:
Weapons_ViewAnimation(pl, GLAUNCHER_GRELOAD1);
break;
case SHOTGUN_RELOAD:
break;
case SHOTGUN_END_RELOAD:
Weapons_ViewAnimation(pl, GLAUNCHER_GRELOAD2);
break;
}
}
void
w_glauncher_primary(player pl)
{
int s = w_baseprojectile_fire(pl, WEAPON_GLAUNCHER, player::mag_glauncher, w_glauncher_shootnade);
switch (s) {
case AUTO_FIRE_FAILED:
w_glauncher_release(pl);
return;
break;
case AUTO_FIRED:
case AUTO_LAST:
Weapons_ViewAnimation(pl, GLAUNCHER_GFIRE);
Weapons_ViewPunchAngle(pl, [-1,0,0]);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTSHOTGUN, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTSHOTGUN, 0.45f);
pl.w_attack_next = 0.6f;
break;
case AUTO_EMPTY:
Weapons_ViewAnimation(pl, GLAUNCHER_GIDLE);
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 0.6f;
}
void
w_glauncher_postdraw(player pl)
{
#ifdef CLIENT
vector aicon_pos;
Cross_DrawSub(g_cross_spr, [24,24], [24/128,48/128], [0.1875, 0.1875]);
/* ammo counters */
HUD_DrawAmmo1();
HUD_DrawAmmo2();
/* ammo icon */
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(
aicon_pos,
[24,24],
"sprites/640hud7.spr_0.tga",
[120/256,72/128],
[24/256, 24/128],
g_hud_color,
pSeatLocal->m_flAmmo2Alpha,
DRAWFLAG_ADDITIVE
);
#endif
}
float
w_glauncher_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMSHOTGUN : TFCANIM_AIMSHOTGUN;
}
void
w_glauncher_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud2_spr,
[0,135/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud1_spr,
[0,135/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_glauncher =
{
.name = "glauncher",
.id = ITEM_GLAUNCHER,
.slot = 3,
.slot_pos = 1,
.weight = WEIGHT_GLAUNCHER,
.draw = w_glauncher_draw,
.holster = __NULL__,
.primary = w_glauncher_primary,
.secondary = __NULL__,
.reload = w_glauncher_reload,
.release = w_glauncher_release,
.postdraw = w_glauncher_postdraw,
.precache = w_glauncher_precache,
.pickup = w_glauncher_pickup,
.updateammo = w_glauncher_updateammo,
.wmodel = w_glauncher_wmodel,
.pmodel = w_glauncher_pmodel,
.deathmsg = w_glauncher_deathmsg,
.aimanim = w_glauncher_aimanim,
.hudpic = w_glauncher_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,116 +0,0 @@
/*
* 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
w_grapple_precache(void)
{
precache_model("models/v_grapple.mdl");
precache_model("models/w_grapple.mdl");
precache_model("models/p_grapple.mdl");
}
void
w_grapple_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, __NULL__, __NULL__, __NULL__);
#endif
}
string
w_grapple_wmodel(void)
{
return "models/w_grapple.mdl";
}
string
w_grapple_pmodel(player pl)
{
return "models/p_grapple.mdl";
}
string
w_grapple_deathmsg(void)
{
return "%s was assaulted by %s's Assault Cannon.";
}
void
w_grapple_draw(player pl)
{
Weapons_SetModel("models/v_grapple.mdl");
Weapons_ViewAnimation(pl, 0);
}
float
w_grapple_aimanim(player pl)
{
return pl.IsCrouching() ? ANIM_CR_AIMCROWBAR : ANIM_AIMCROWBAR;
}
void
w_grapple_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud4_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud1_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_grapple =
{
.name = "grapple",
.id = ITEM_GRAPPLE,
.slot = 5,
.slot_pos = 0,
.weight = WEIGHT_GRAPPLE,
.draw = w_grapple_draw,
.holster = __NULL__,
.primary = __NULL__,
.secondary = __NULL__,
.reload = __NULL__,
.release = __NULL__,
.postdraw = __NULL__,
.precache = w_grapple_precache,
.pickup = __NULL__,
.updateammo = w_grapple_updateammo,
.wmodel = w_grapple_wmodel,
.pmodel = w_grapple_pmodel,
.deathmsg = w_grapple_deathmsg,
.aimanim = w_grapple_aimanim,
.hudpic = w_grapple_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,203 +0,0 @@
/*
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2023 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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.
*/
#define TFC_RPG_ROCKET_SPEED 900.0f
enum
{
INC_IDLE1,
INC_FIDGET1,
INC_FIRE,
INC_HOLSTER1,
INC_DRAW1,
INC_HOLSTER2,
INC_DRAW2,
INC_RELOAD_START,
INC_RELOAD,
INC_RELOAD_END,
INC_IDLE2,
INC_FIDGET2
};
void
w_incendiary_precache(void)
{
precache_model("models/v_tfc_rpg.mdl");
precache_model("models/w_incendiary.mdl");
precache_model("models/p_incendiary.mdl");
Sound_Precache("weapon_incendiary.fire");
}
void
w_incendiary_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, __NULL__, pl.m_iAmmoRockets, __NULL__);
}
string
w_incendiary_wmodel(void)
{
return "models/w_incendiary.mdl";
}
string
w_incendiary_pmodel(player pl)
{
return "models/p_rpg2.mdl";
}
string
w_incendiary_deathmsg(void)
{
return "%s gets well done by %s's incendiary rocket.";
// TODO
// Has special birthday and suicide death messages
}
void
w_incendiary_draw(player pl)
{
Weapons_SetModel("models/v_tfc_rpg.mdl");
Weapons_ViewAnimation(pl, 0);
}
void
w_incendiary_shootrocket(player pl)
{
static void w_incendiary_shootrocket_touch(void) {
pointparticles(particleeffectnum("fx_explosion.main"), self.origin, [0,0,0], 1);
remove(self);
}
Weapons_MakeVectors(pl);
entity p = spawn();
setmodel(p, "models/rpgrocket.mdl");
setorigin(p, Weapons_GetCameraPos(pl) + (v_forward * 8));
p.owner = self;
p.movetype = MOVETYPE_FLYMISSILE;
p.solid = SOLID_BBOX;
p.gravity = 0.5f;
p.velocity = (v_forward * TFC_RPG_ROCKET_SPEED);
p.angles = vectoangles(p.velocity);
p.touch = w_incendiary_shootrocket_touch;
p.think = Util_Destroy;
p.nextthink = time + 5.0f;
}
void
w_incendiary_primary(player pl)
{
int s = w_baseprojectile_fire(pl, WEAPON_INCENDIARY, player::m_iAmmoRockets, w_incendiary_shootrocket);
switch (s) {
case AUTO_FIRE_FAILED:
return;
break;
case AUTO_FIRED:
case AUTO_LAST:
Weapons_ViewAnimation(pl, INC_FIRE);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_incendiary.fire");
Weapons_ViewPunchAngle(pl, [-2,0,0]);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTRPG, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTRPG, 0.45f);
pl.w_attack_next = 0.8f;
break;
case AUTO_EMPTY:
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 1.5f;
}
float
w_incendiary_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMRPG : TFCANIM_AIMRPG;
}
void
w_incendiary_postdraw(player pl)
{
#ifdef CLIENT
// crosshair
Cross_DrawSub(g_cross_spr, [24,24], [24/128,48/128], [0.1875, 0.1875]);
// ammo counter
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [24,24], g_hud7_spr, [120/256,72/128],[24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
void
w_incendiary_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud5_spr,
[0,90/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud6_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_incendiary =
{
.name = "incendiary",
.id = ITEM_INCENDIARY,
.slot = 4,
.slot_pos = 3,
.weight = WEIGHT_INCENDIARY,
.draw = w_incendiary_draw,
.holster = __NULL__,
.primary = w_incendiary_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = __NULL__,
.postdraw = w_incendiary_postdraw,
.precache = w_incendiary_precache,
.pickup = __NULL__,
.updateammo = w_incendiary_updateammo,
.wmodel = w_incendiary_wmodel,
.pmodel = w_incendiary_pmodel,
.deathmsg = w_incendiary_deathmsg,
.aimanim = w_incendiary_aimanim,
.hudpic = w_incendiary_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,203 +0,0 @@
/*
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2023 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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.
*/
enum
{
KNIFE_IDLE,
KNIFE_IDLE2,
KNIFE_SLASH,
KNIFE_STAB,
KNIFE_DRAW,
KNIFE_HOLSTER
};
void
w_knife_precache(void)
{
Sound_Precache("weapon_crowbar.hit");
Sound_Precache("weapon_crowbar.miss");
Sound_Precache("weapon_crowbar.hitbody");
precache_model("models/v_tfc_knife.mdl");
precache_model("models/w_knife.mdl");
precache_model("models/p_knife.mdl");
}
void
w_knife_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, __NULL__, __NULL__, __NULL__);
#endif
}
string
w_knife_wmodel(void)
{
return "models/w_knife.mdl";
}
string
w_knife_pmodel(player pl)
{
return "models/p_knife.mdl";
}
string
w_knife_deathmsg(void)
{
return "%s was assaulted by %s's Assault Cannon.";
}
void
w_knife_draw(player pl)
{
Weapons_SetModel("models/v_tfc_knife.mdl");
Weapons_ViewAnimation(pl, KNIFE_DRAW);
}
void
w_knife_holster(player pl)
{
Weapons_ViewAnimation(pl, KNIFE_HOLSTER);
}
void
w_knife_primary(player pl)
{
int anim = 0;
vector src;
if (pl.w_attack_next) {
return;
}
Weapons_MakeVectors(pl);
src = pl.origin + pl.view_ofs;
/* make sure we can gib corpses */
int oldhitcontents = self.hitcontentsmaski;
self.hitcontentsmaski = CONTENTBITS_POINTSOLID | CONTENTBIT_CORPSE;
traceline(src, src + (v_forward * 32), FALSE, pl);
self.hitcontentsmaski = oldhitcontents;
pl.w_attack_next = 0.4f;
pl.w_idle_next = 2.5f;
Weapons_ViewAnimation(pl, KNIFE_SLASH);
if (pl.IsCrouching())
Animation_PlayerTop(pl, ANIM_CR_SHOOTCROWBAR, 0.41f);
else
Animation_PlayerTop(pl, ANIM_SHOOTCROWBAR, 0.5f);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_crowbar.miss");
#ifdef SERVER
if (trace_fraction >= 1.0) {
return;
}
/* don't bother with decals, we got squibs */
if (trace_ent.iBleeds) {
FX_Blood(trace_endpos, [1,0,0]);
} else {
SurfData_Impact(trace_ent, trace_endpos, trace_plane_normal);
}
// Backstab detection
if (trace_ent.takedamage) {
int damage = 36;
damageType_t dmgtype = DMG_BLUNT;
if (trace_ent.classname == "player") {
player otherpl = (player) trace_ent;
if (otherpl.IsFacing(pl) == false) {
damage = 500;
dmgtype = DMG_CRUSH;
}
}
Damage_Apply(trace_ent, pl, damage, WEAPON_KNIFE, dmgtype);
if (trace_ent.iBleeds) {
Weapons_Sound(pl, CHAN_WEAPON, "weapon_crowbar.hitbody");
} else {
Weapons_Sound(pl, CHAN_WEAPON, "weapon_crowbar.hit");
}
}
#endif
}
float
w_knife_aimanim(player pl)
{
return pl.IsCrouching() ? ANIM_CR_AIMCROWBAR : ANIM_AIMCROWBAR;
}
void
w_knife_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud4_spr,
[0,135/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud3_spr,
[0,90/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_knife =
{
.name = "knife",
.id = ITEM_KNIFE,
.slot = 0,
.slot_pos = 2,
.weight = WEIGHT_KNIFE,
.draw = w_knife_draw,
.holster = w_knife_holster,
.primary = w_knife_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = __NULL__,
.postdraw = __NULL__,
.precache = w_knife_precache,
.pickup = __NULL__,
.updateammo = w_knife_updateammo,
.wmodel = w_knife_wmodel,
.pmodel = w_knife_pmodel,
.deathmsg = w_knife_deathmsg,
.aimanim = w_knife_aimanim,
.hudpic = w_knife_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,190 +0,0 @@
/*
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2023 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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.
*/
enum
{
MEDKIT_IDLE1,
MEDKIT_IDLE2,
MEDKIT_USE,
MEDKIT_UNUSED,
MEDKIT_HOLSTER,
MEDKIT_DRAW
};
void
w_medkit_precache(void)
{
precache_model("models/v_tfc_medkit.mdl");
precache_model("models/w_medkit.mdl");
precache_model("models/p_medkit.mdl");
}
void
w_medkit_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, __NULL__, __NULL__, __NULL__);
#endif
}
string
w_medkit_wmodel(void)
{
return "models/w_medkit.mdl";
}
string
w_medkit_pmodel(player pl)
{
return "models/p_medkit.mdl";
}
string
w_medkit_deathmsg(void)
{
return "%s was assaulted by %s's Assault Cannon.";
}
void
w_medkit_draw(player pl)
{
Weapons_SetModel("models/v_tfc_medkit.mdl");
Weapons_ViewAnimation(pl, 0);
}
void
w_medkit_primary(player pl)
{
vector src;
if (pl.w_attack_next > 0.0)
return;
// cast our traceline
Weapons_MakeVectors(pl);
src = pl.origin + pl.view_ofs;
traceline(src, src + (v_forward * 64), FALSE, pl);
Weapons_ViewAnimation(pl, MEDKIT_USE);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTMEDKIT, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTMEDKIT, 0.45f);
if (trace_ent.classname == "player") {
player otherpl = (player) trace_ent;
#ifdef SERVER
if (otherpl.GetTeam() == pl.GetTeam()) {
/* Don't give the player more than 100% health */
if (otherpl.health < otherpl.m_iMaxHealth) {
/* We want to only give health to our teammate & skip armor */
otherpl.health = bound(0, otherpl.health + 15, otherpl.m_iMaxHealth);
}
} else {
/* Poison the enemey */
// TODO
// Needs to last for 10+ seconds and spread to others
Damage_Apply(otherpl, pl, 15, WEAPON_MEDKIT, DMG_GENERIC);
}
Weapons_Sound(pl, CHAN_WEAPON, "weapon_medkit.heal");
#endif
}
pl.w_attack_next = 0.4f;
pl.w_idle_next = 5.0f;
}
void
w_medkit_release(player pl)
{
if (pl.w_idle_next > 0.0)
return;
int r = (float)input_sequence % 2;
switch (r) {
case 0:
Weapons_ViewAnimation(pl, MEDKIT_IDLE1);
pl.w_idle_next = 1.16f;
break;
default:
Weapons_ViewAnimation(pl, MEDKIT_IDLE2);
pl.w_idle_next = 2.36f;
break;
}
}
float
w_medkit_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMMEDKIT : TFCANIM_AIMMEDKIT;
}
void
w_medkit_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud5_spr,
[0,180/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud6_spr,
[0,90/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_medkit =
{
.name = "medkit",
.id = ITEM_MEDKIT,
.slot = 0,
.slot_pos = 1,
.weight = WEIGHT_MEDKIT,
.draw = w_medkit_draw,
.holster = __NULL__,
.primary = w_medkit_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = w_medkit_release,
.postdraw = __NULL__,
.precache = w_medkit_precache,
.pickup = __NULL__,
.updateammo = w_medkit_updateammo,
.wmodel = w_medkit_wmodel,
.pmodel = w_medkit_pmodel,
.deathmsg = w_medkit_deathmsg,
.aimanim = w_medkit_aimanim,
.hudpic = w_medkit_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,214 +0,0 @@
/*
* Copyright (c) 2016-2024 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.
*/
enum
{
NAILGUN_IDLE,
NAILGUN_FIDGET1,
NAILGUN_UNUSED1,
NAILGUN_UNUSED2,
NAILGUN_DEPLOY,
NAILGUN_SHOOT1,
NAILGUN_SHOOT2,
NAILGUN_SHOOT3,
};
void
w_nailgun_precache(void)
{
precache_model("models/v_tfc_nailgun.mdl");
precache_model("models/w_nailgun.mdl");
precache_model("models/p_nailgun.mdl");
precache_model("models/nail.mdl");
Sound_Precache("weapon_nailgun.fire");
}
void
w_nailgun_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, __NULL__, pl.m_iAmmoNails, __NULL__);
}
string
w_nailgun_wmodel(void)
{
return "models/w_nailgun.mdl";
}
string
w_nailgun_pmodel(player pl)
{
return "models/p_nailgun2.mdl";
}
string
w_nailgun_deathmsg(void)
{
return "%s was assaulted by %s's Assault Cannon.";
}
void
w_nailgun_draw(player pl)
{
Weapons_SetModel("models/v_tfc_nailgun.mdl");
Weapons_ViewAnimation(pl, NAILGUN_DEPLOY);
}
float
w_nailgun_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMMP5 : TFCANIM_AIMMP5;
}
void
w_nailgun_shootnail(player pl)
{
static void w_rpg_shootrocket_touch(void) {
#ifndef CLIENT
/* impact per bullet */
if (trace_ent.iBleeds == 0) {
DecalGroups_Place("Impact.Shot", trace_endpos + (v_forward * -2));
SurfData_Impact(trace_ent, trace_endpos, trace_plane_normal);
}
if (trace_ent.takedamage == DAMAGE_YES) {
Damage_Apply(trace_ent, self.owner, 9, WEAPON_NAILGUN, DMG_BULLET);
}
#endif
remove(self);
}
Weapons_MakeVectors(pl);
entity p = spawn();
setmodel(p, "models/nail.mdl");
setorigin(p, Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
p.owner = self;
p.movetype = MOVETYPE_FLYMISSILE;
p.solid = SOLID_BBOX;
p.gravity = 0.5f;
p.velocity = (v_forward * 1000) + (v_up * 4) + (v_right * -2);
p.angles = vectoangles(p.velocity);
p.touch = w_rpg_shootrocket_touch;
p.think = Util_Destroy;
p.nextthink = time + 5.0f;
}
void
w_nailgun_primary(player pl)
{
int s = w_baseprojectile_fire(pl, WEAPON_NAILGUN, player::m_iAmmoNails, w_nailgun_shootnail);
switch (s) {
case AUTO_FIRE_FAILED:
return;
break;
case AUTO_FIRED:
case AUTO_LAST:
int r = (float)input_sequence % 3;
if (r == 1) {
Weapons_ViewAnimation(pl, NAILGUN_SHOOT1);
} else if (r == 2) {
Weapons_ViewAnimation(pl, NAILGUN_SHOOT2);
} else {
Weapons_ViewAnimation(pl, NAILGUN_SHOOT3);
}
Weapons_ViewAnimation(pl, NAILGUN_SHOOT2);
Weapons_ViewPunchAngle(pl, [-1,0,0]);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTMP5, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTMP5, 0.45f);
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_RIFLE);
#endif
#ifndef CLIENT
Sound_Play(pl, CHAN_WEAPON, "weapon_nailgun.fire");
#endif
pl.w_attack_next = 0.1f;
break;
case AUTO_EMPTY:
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 1.5f;
}
void
w_nailgun_crosshair(player pl)
{
#ifdef CLIENT
Cross_DrawSub(g_cross_spr, [24,24], [0.1875,0], [0.1875, 0.1875]);
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [24,24], g_hud7_spr, [0,72/128],[24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
void
w_nailgun_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud7_spr,
[0,90/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud7_spr,
[0,90/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_nailgun =
{
.name = "nailgun",
.id = ITEM_NAILGUN,
.slot = 3,
.slot_pos = 0,
.weight = WEIGHT_NAILGUN,
.draw = w_nailgun_draw,
.holster = __NULL__,
.primary = w_nailgun_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = __NULL__,
.postdraw = w_nailgun_crosshair,
.precache = w_nailgun_precache,
.pickup = __NULL__,
.updateammo = w_nailgun_updateammo,
.wmodel = w_nailgun_wmodel,
.pmodel = w_nailgun_pmodel,
.deathmsg = w_nailgun_deathmsg,
.aimanim = w_nailgun_aimanim,
.hudpic = w_nailgun_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,309 +0,0 @@
/*
* 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
w_pipebomb_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_handgrenade.bounce");
Sound_Precache("weapon_mp5.gl");
precache_model("models/w_pipebomb.mdl");
precache_model("models/p_pipebomb.mdl");
precache_model("models/pipebomb.mdl");
#else
precache_model("models/v_tfgl.mdl");
#endif
}
void
w_pipebomb_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.mag_glauncher, pl.m_iAmmoRockets, __NULL__);
}
int
w_pipebomb_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
pl.mag_glauncher = bound(0, pl.mag_glauncher + 6, 6);
#endif
return (1);
}
string
w_pipebomb_wmodel(void)
{
return "models/p_glauncher.mdl";
}
string
w_pipebomb_pmodel(player pl)
{
return "models/p_glauncher.mdl";
}
string
w_pipebomb_deathmsg(void)
{
return "%s was assaulted by %s's Assault Cannon.";
}
void
w_pipebomb_draw(player pl)
{
Weapons_SetModel("models/v_tfgl.mdl");
Weapons_ViewAnimation(pl, GLAUNCHER_PDRAW);
}
#ifdef SERVER
void w_pipebomb_explode(void)
{
pointparticles(particleeffectnum("fx_explosion.main"), self.origin, [0,0,0], 1);
/* dmg/radius taken from http://web.archive.org/web/20030323072941fw_/http://www.planetfortress.com/tfce/grenades/pipebomb.htm */
Damage_Radius(self.origin, self.owner, 80, 128, TRUE, WEAPON_GLAUNCHER);
Sound_Play(self, CHAN_VOICE, "fx.explosion");
ncEntity::Destroy();
}
#endif
void
w_pipebomb_shootnade(player pl)
{
vector vecNadeVelocity;
ncEntity first_nade;
int known_nades = 0i;
float oldest_time = 0.0f;
static void w_pipebomb_shootnade_touch(void) {
Sound_Play(self, CHAN_BODY, "weapon_handgrenade.bounce");
if (vlen(self.velocity))
self.avelocity = g_vec_null;
}
Weapons_MakeVectors(pl);
vecNadeVelocity = v_forward * 600 + v_up * 200 + crandom() * v_right * 10 + crandom() * v_up * 10;
ncRenderableEntity eNade = spawn(ncRenderableEntity);
eNade.classname = "pipebomb";
eNade.SetModel("models/pipebomb.mdl");
eNade.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
eNade.SetMovetype(MOVETYPE_BOUNCE);
eNade.SetSolid(SOLID_BBOX);
eNade.SetGravity(1.0f);
eNade.SetVelocity(vecNadeVelocity);
eNade.SetAngularVelocity([300, 300, 300]);
eNade.SetAngles(vectoangles(eNade.GetVelocity()));
eNade.SetSkin(0);
eNade.touch = w_pipebomb_shootnade_touch;
Sound_Play(pl, CHAN_WEAPON, "weapon_mp5.gl");
#ifdef SERVER
/* iterate through and mark the first nade we own */
for (entity e = world; (e = find(e, ::classname, "pipebomb"));) {
ncEntity pb = (ncEntity)e;
if (pb.GetOwner() == pl) {
if (pb.GetSpawnAge() > oldest_time) {
first_nade = pb;
oldest_time = pb.GetSpawnAge();
}
known_nades++;
}
}
/* if we have more than 8, destroy the first one we placed */
if (known_nades > 8) {
first_nade.ScheduleThink(w_pipebomb_explode, 0.0f);
}
#endif
//eNade.traileffectnum = particleeffectnum("weapon_rpg.trail");
}
void
w_pipebomb_reload(player pl)
{
w_baseshotgun_reload(player::mag_glauncher, player::m_iAmmoRockets, 6);
}
void
w_pipebomb_release(player pl)
{
int s = w_baseshotgun_release(player::mag_glauncher, player::m_iAmmoRockets, 6);
switch (s) {
case SHOTGUN_IDLE:
Weapons_ViewAnimation(pl, GLAUNCHER_PIDLE);
pl.w_idle_next = 5.0f;
break;
case SHOTGUN_BUSY:
break;
case SHOTGUN_START_RELOAD:
Weapons_ViewAnimation(pl, GLAUNCHER_PRELOAD1);
break;
case SHOTGUN_RELOAD:
break;
case SHOTGUN_END_RELOAD:
Weapons_ViewAnimation(pl, GLAUNCHER_PRELOAD2);
break;
}
}
void
w_pipebomb_primary(player pl)
{
int s = w_baseprojectile_fire(pl, WEAPON_PIPEBOMB, player::mag_glauncher, w_pipebomb_shootnade);
switch (s) {
case AUTO_FIRE_FAILED:
w_pipebomb_release(pl);
return;
break;
case AUTO_FIRED:
case AUTO_LAST:
Weapons_ViewAnimation(pl, GLAUNCHER_PFIRE);
Weapons_ViewPunchAngle(pl, [-1,0,0]);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTSHOTGUN, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTSHOTGUN, 0.45f);
pl.w_attack_next = 0.6f;
break;
case AUTO_EMPTY:
Weapons_ViewAnimation(pl, GLAUNCHER_PIDLE);
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 0.6f;
}
void
w_pipebomb_secondary(player pl)
{
float pb_timer = 0.0f;
if (pl.w_attack_next > 0)
return;
#ifdef SERVER
for (entity e = world; (e = find(e, ::classname, "pipebomb"));) {
ncEntity pb = (ncEntity)e;
if (pb.GetOwner() == pl) {
pb.ScheduleThink(w_pipebomb_explode, pb_timer);
pb_timer += 0.1f;
}
}
#endif
pl.w_attack_next = 0.5f;
}
void
w_pipebomb_postdraw(player pl)
{
#ifdef CLIENT
vector aicon_pos;
Cross_DrawSub(g_cross_spr, [24,24], [24/128,48/128], [0.1875, 0.1875]);
/* ammo counters */
HUD_DrawAmmo1();
HUD_DrawAmmo2();
/* ammo icon */
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(
aicon_pos,
[24,24],
"sprites/640hud7.spr_0.tga",
[120/256,72/128],
[24/256, 24/128],
g_hud_color,
pSeatLocal->m_flAmmo2Alpha,
DRAWFLAG_ADDITIVE
);
#endif
}
float
w_pipebomb_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMSHOTGUN : TFCANIM_AIMSHOTGUN;
}
void
w_pipebomb_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud2_spr,
[0,90/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud1_spr,
[0,90/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_pipebomb =
{
.name = "pipebomb",
.id = ITEM_PIPEBOMB,
.slot = 4,
.slot_pos = 1,
.weight = WEIGHT_PIPEBOMB,
.draw = w_pipebomb_draw,
.holster = __NULL__,
.primary = w_pipebomb_primary,
.secondary = w_pipebomb_secondary,
.reload = w_pipebomb_reload,
.release = w_pipebomb_release,
.postdraw = w_pipebomb_postdraw,
.precache = w_pipebomb_precache,
.pickup = w_pipebomb_pickup,
.updateammo = w_pipebomb_updateammo,
.wmodel = w_pipebomb_wmodel,
.pmodel = w_pipebomb_pmodel,
.deathmsg = w_pipebomb_deathmsg,
.aimanim = w_pipebomb_aimanim,
.hudpic = w_pipebomb_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,204 +0,0 @@
/*
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2023 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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.
*/
enum
{
RAILGUN_IDLE,
RAILGUN_SHOOT,
RAILGUN_DRAW,
RAILGUN_HOLSTER,
};
void
w_railgun_precache(void)
{
precache_model("models/v_tfc_railgun.mdl");
precache_model("models/w_railgun.mdl");
precache_model("models/p_railgun.mdl");
Sound_Precache("weapon_railgun.fire");
}
void
w_railgun_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, __NULL__, pl.m_iAmmoNails, __NULL__);
}
string
w_railgun_wmodel(void)
{
return "models/w_railgun.mdl";
}
string
w_railgun_pmodel(player pl)
{
return "models/p_9mmhandgun.mdl";
}
string
w_railgun_deathmsg(void)
{
return "%s was assaulted by %s's railgun.";
}
void
w_railgun_draw(player pl)
{
Weapons_SetModel("models/v_tfc_railgun.mdl");
Weapons_ViewAnimation(pl, RAILGUN_DRAW);
}
float
w_railgun_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIM1HAND : TFCANIM_AIM1HAND;
}
void
w_railgun_shootbeam(player pl)
{
#ifdef SERVER
static void w_railgun_shootbeam_touch(void) {
#ifndef CLIENT
/* impact per bullet */
if (trace_ent.iBleeds == 0) {
DecalGroups_Place("Impact.BigShot", trace_endpos + (v_forward * -2));
SurfData_Impact(trace_ent, trace_surfaceflagsi, trace_endpos, trace_plane_normal);
}
if (trace_ent.takedamage == DAMAGE_YES) {
Damage_Apply(trace_ent, self.owner, 23, WEAPON_RAILGUN, DMG_BULLET);
}
#endif
remove(self);
}
Weapons_MakeVectors(pl);
entity p = spawn();
setmodel(p, "models/nail.mdl");
setorigin(p, Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -5) + (v_right * 3.5));
p.owner = self;
p.movetype = MOVETYPE_FLYMISSILE;
p.solid = SOLID_BBOX;
p.gravity = 0.5f;
p.velocity = (v_forward * 1000) + (v_up * 5) + (v_right * -3.5);
p.angles = vectoangles(p.velocity);
p.touch = w_railgun_shootbeam_touch;
p.think = Util_Destroy;
p.nextthink = time + 5.0f;
p.alpha = 0.01f;
p.traileffectnum = particleeffectnum("weapon_railgun.trail");
#endif
}
void
w_railgun_primary(player pl)
{
int s = w_baseprojectile_fire(pl, WEAPON_RAILGUN, player::m_iAmmoNails, w_railgun_shootbeam);
switch (s) {
case AUTO_FIRE_FAILED:
return;
break;
case AUTO_FIRED:
case AUTO_LAST:
int r = (float)input_sequence % 3;
Weapons_ViewAnimation(pl, RAILGUN_SHOOT);
Weapons_ViewPunchAngle(pl, [-1,0,0]);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOT1HAND, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOT1HAND, 0.45f);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_railgun.fire");
pl.w_attack_next = 0.4f;
break;
case AUTO_EMPTY:
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 1.5f;
}
void
w_railgun_postdraw(player pl)
{
#ifdef CLIENT
// crosshair
Cross_DrawSub(g_cross_spr, [24,24], [48/128,24/128], [0.1875, 0.1875]);
// ammo counter
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [24,24], g_hud7_spr, [0,72/128],[24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
void
w_railgun_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud7_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud7_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_railgun =
{
.name = "railgun",
.id = ITEM_RAILGUN,
.slot = 1,
.slot_pos = 3,
.weight = WEIGHT_RAILGUN,
.draw = w_railgun_draw,
.holster = __NULL__,
.primary = w_railgun_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = __NULL__,
.postdraw = w_railgun_postdraw,
.precache = w_railgun_precache,
.pickup = __NULL__,
.updateammo = w_railgun_updateammo,
.wmodel = w_railgun_wmodel,
.pmodel = w_railgun_pmodel,
.deathmsg = w_railgun_deathmsg,
.aimanim = w_railgun_aimanim,
.hudpic = w_railgun_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,244 +0,0 @@
/*
* 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.
*/
#define TFC_RPG_ROCKET_SPEED 900.0f
enum
{
RPG_IDLE1,
RPG_FIDGET1,
RPG_FIRE,
RPG_HOLSTER1,
RPG_DRAW1,
RPG_HOLSTER2,
RPG_DRAW2,
RPG_RELOAD_START,
RPG_RELOAD,
RPG_RELOAD_END,
RPG_IDLE2,
RPG_FIDGET2
};
void
w_rpg_precache(void)
{
precache_model("models/v_tfc_rpg.mdl");
precache_model("models/w_rpg.mdl");
precache_model("models/p_rpg.mdl");
precache_model("models/rpgrocket.mdl");
Sound_Precache("weapon_rpg.fire");
}
int
w_rpg_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
pl.mag_rpg = bound(0, pl.mag_rpg + 4, 4);
#endif
return (1);
}
void
w_rpg_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.mag_rpg, pl.m_iAmmoRockets, __NULL__);
}
string
w_rpg_wmodel(void)
{
return "models/w_rpg.mdl";
}
string
w_rpg_pmodel(player pl)
{
return "models/p_rpg.mdl";
}
string
w_rpg_deathmsg(void)
{
return "%s was assaulted by %s's Assault Cannon.";
}
void
w_rpg_draw(player pl)
{
Weapons_SetModel("models/v_tfc_rpg.mdl");
Weapons_ViewAnimation(pl, 0);
}
void
w_rpg_shootrocket(player pl)
{
static void w_rpg_shootrocket_touch(void) {
pointparticles(particleeffectnum("fx_explosion.main"), self.origin, [0,0,0], 1);
remove(self);
}
Weapons_MakeVectors(pl);
entity p = spawn();
setmodel(p, "models/rpgrocket.mdl");
setorigin(p, Weapons_GetCameraPos(pl) + (v_forward * 8));
p.owner = self;
p.movetype = MOVETYPE_FLYMISSILE;
p.solid = SOLID_BBOX;
p.gravity = 0.5f;
p.velocity = (v_forward * TFC_RPG_ROCKET_SPEED);
p.angles = vectoangles(p.velocity);
p.touch = w_rpg_shootrocket_touch;
p.think = Util_Destroy;
p.nextthink = time + 5.0f;
}
void
w_rpg_primary(player pl)
{
int s = w_baseprojectile_fire(pl, WEAPON_RPG, player::mag_rpg, w_rpg_shootrocket);
switch (s) {
case AUTO_FIRE_FAILED:
return;
break;
case AUTO_LAST:
case AUTO_FIRED:
Weapons_ViewAnimation(pl, RPG_FIRE);
Weapons_ViewPunchAngle(pl, [-2,0,0]);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_rpg.fire");
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTRPG, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTRPG, 0.45f);
pl.w_attack_next = 0.8f;
break;
case AUTO_EMPTY:
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 1.5f;
}
void
w_rpg_reload(player pl)
{
w_baseshotgun_reload(player::mag_rpg, player::m_iAmmoRockets, 4);
}
void
w_rpg_release(player pl)
{
int s = w_baseshotgun_release(player::mag_rpg, player::m_iAmmoRockets, 4);
switch (s) {
case SHOTGUN_IDLE:
int r = (float)input_sequence % 3;
if (r == 1) {
Weapons_ViewAnimation(pl, RPG_IDLE1);
} else if (r == 2) {
Weapons_ViewAnimation(pl, RPG_FIDGET1);
} else {
Weapons_ViewAnimation(pl, RPG_FIDGET2);
}
pl.w_idle_next = 5.0f;
break;
case SHOTGUN_BUSY:
break;
case SHOTGUN_START_RELOAD:
Weapons_ViewAnimation(pl, RPG_RELOAD_START);
break;
case SHOTGUN_RELOAD:
Weapons_ViewAnimation(pl, RPG_RELOAD);
break;
case SHOTGUN_END_RELOAD:
Weapons_ViewAnimation(pl, RPG_RELOAD_END);
break;
}
}
float
w_rpg_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMRPG : TFCANIM_AIMRPG;
}
void
w_rpg_hud(player pl)
{
#ifdef CLIENT
vector aicon_pos;
Cross_DrawSub(g_cross_spr, [24,24], [24/128,48/128], [0.1875, 0.1875]);
/* ammo counters */
HUD_DrawAmmo1();
HUD_DrawAmmo2();
/* ammo icon */
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(
aicon_pos,
[24,24],
g_hud7_spr,
[120/256,72/128],
[24/256, 24/128],
g_hud_color,
pSeatLocal->m_flAmmo2Alpha,
DRAWFLAG_ADDITIVE
);
#endif
}
void
w_rpg_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(pos, [170,45], g_hud5_spr, [0,45/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
} else {
drawsubpic(pos, [170,45], g_hud2_spr, [0,45/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
}
#endif
}
weapon_t w_rpg =
{
.name = "rpg",
.id = ITEM_RPG,
.slot = 4,
.slot_pos = 0,
.weight = WEIGHT_RPG,
.draw = w_rpg_draw,
.holster = __NULL__,
.primary = w_rpg_primary,
.secondary = __NULL__,
.reload = w_rpg_reload,
.release = w_rpg_release,
.postdraw = w_rpg_hud,
.precache = w_rpg_precache,
.pickup = w_rpg_pickup,
.updateammo = w_rpg_updateammo,
.wmodel = w_rpg_wmodel,
.pmodel = w_rpg_pmodel,
.deathmsg = w_rpg_deathmsg,
.aimanim = w_rpg_aimanim,
.hudpic = w_rpg_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,210 +0,0 @@
/*
* 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.
*/
enum
{
SBS_IDLE1,
SBS_FIRE1,
SBS_FIRE2,
SBS_ADDSHELL,
SBS_PUMP,
SBS_START_RELOAD,
SBS_DRAW,
SBS_HOLSTER,
SBS_IDLE2,
SBS_IDLE3
};
void
w_sbs_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_sbs.cock");
Sound_Precache("weapon_sbs.fire");
Sound_Precache("weapon_sbs.reload");
#endif
precache_model("models/v_tfc_12gauge.mdl");
precache_model("models/p_shotgun.mdl");
precache_sound("weapons/dbarrel1.wav");
}
void
w_sbs_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.mag_sbs, pl.m_iAmmoShells, __NULL__);
}
string w_sbs_wmodel(void)
{
return "models/ball.mdl";
}
string w_sbs_pmodel(player pl)
{
return "models/p_shotgun.mdl";
}
string w_sbs_deathmsg(void)
{
return "";
}
int
w_sbs_pickup(player pl, int new, int startammo)
{
#ifdef SERVER
pl.mag_sbs = bound(0, pl.mag_sbs + 8, 8);
#endif
return (1);
}
void
w_sbs_draw(player pl)
{
Weapons_SetModel("models/v_tfc_12gauge.mdl");
Weapons_ViewAnimation(pl, SBS_DRAW);
}
void
w_sbs_holster(player pl)
{
Weapons_ViewAnimation(pl, SBS_HOLSTER);
}
void
w_sbs_primary(player pl)
{
int s = w_baseshotgun_fire(WEAPON_SBS, player::mag_sbs, 6, 4, [0.04, 0.04, 0]);
switch (s) {
case AUTO_FIRE_FAILED:
return;
break;
case AUTO_LAST:
case AUTO_FIRED:
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_ROUND);
#endif
Weapons_ViewAnimation(pl, SBS_FIRE1);
Weapons_ViewPunchAngle(pl, [-2,0,0]);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTSHOTGUN, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTSHOTGUN, 0.45f);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_sbs.fire");
pl.w_attack_next = 0.5f;
break;
case AUTO_EMPTY:
Weapons_Sound(pl, CHAN_WEAPON, "weapon_sbs.fire_empty");
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 1.5f;
}
void
w_sbs_reload(player pl)
{
w_baseshotgun_reload(player::mag_sbs, player::m_iAmmoShells, 8);
}
void
w_sbs_release(player pl)
{
int s = w_baseshotgun_release(player::mag_sbs, player::m_iAmmoShells, 8);
switch (s) {
case SHOTGUN_IDLE:
int r = (float)input_sequence % 3;
if (r == 1) {
Weapons_ViewAnimation(pl, SBS_IDLE1);
} else if (r == 2) {
Weapons_ViewAnimation(pl, SBS_IDLE2);
} else {
Weapons_ViewAnimation(pl, SBS_IDLE3);
}
pl.w_idle_next = 5.0f;
break;
case SHOTGUN_BUSY:
break;
case SHOTGUN_START_RELOAD:
Weapons_ViewAnimation(pl, SBS_START_RELOAD);
break;
case SHOTGUN_RELOAD:
Weapons_ViewAnimation(pl, SBS_ADDSHELL);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_sbs.reload");
break;
case SHOTGUN_END_RELOAD:
Weapons_ViewAnimation(pl, SBS_PUMP);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_sbs.cock");
break;
}
}
void
w_sbs_crosshair(player pl)
{
#ifdef CLIENT
Cross_DrawSub(g_cross_spr, [24,24], [48/128,24/128], [0.1875, 0.1875]);
HUD_DrawAmmo1();
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [24,24], "sprites/640hud7.spr_0.tga", [72/256,72/128], [24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
float
w_sbs_aimanim(player pl)
{
return pl.IsCrouching() ? ANIM_CR_AIMSHOTGUN : ANIM_AIMSHOTGUN;
}
void
w_sbs_hudpic(player pl, int s, vector pos, float a)
{
#ifdef CLIENT
if (s) {
drawsubpic(pos, [170,45], g_tfchud2_spr, [0,180/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
} else {
drawsubpic(pos, [170,45], g_tfchud1_spr, [0,180/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
}
#endif
}
weapon_t w_sbs =
{
.name = "sbs",
.id = ITEM_SBS,
.slot = 1,
.slot_pos = 0,
.weight = WEIGHT_SBS,
.draw = w_sbs_draw,
.holster = w_sbs_holster,
.primary = w_sbs_primary,
.secondary = w_sbs_release,
.reload = w_sbs_reload,
.release = w_sbs_release,
.postdraw = w_sbs_crosshair,
.precache = w_sbs_precache,
.pickup = w_sbs_pickup,
.updateammo = w_sbs_updateammo,
.wmodel = w_sbs_wmodel,
.pmodel = w_sbs_pmodel,
.deathmsg = w_sbs_deathmsg,
.aimanim = w_sbs_aimanim,
.hudpic = w_sbs_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,240 +0,0 @@
/*
* 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.
*/
enum
{
SNIPER_IDLE,
SNIPER_AIM,
SNIPER_FIRE,
SNIPER_DRAW,
SNIPER_HOLSTER,
SNIPER_AUTOIDLE,
SNIPER_AUTOFIRE,
SNIPER_AUTODRAW,
SNIPER_AUTOHOLSTER,
};
void
w_sniper_precache(void)
{
precache_model("models/v_tfc_sniper.mdl");
precache_model("models/p_sniper.mdl");
Sound_Precache("weapon_sniper.fire");
}
void
w_sniper_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, __NULL__, pl.m_iAmmoShells, __NULL__);
}
string
w_sniper_wmodel(void)
{
return "";
}
string
w_sniper_pmodel(player pl)
{
return "models/p_sniper.mdl";
}
string
w_sniper_deathmsg(void)
{
return "%s was assaulted by %s's Assault Cannon.";
}
void
w_sniper_draw(player pl)
{
Weapons_SetModel("models/v_tfc_sniper.mdl");
Weapons_ViewAnimation(pl, SNIPER_DRAW);
pl.w_idle_next = 1.0f;
}
float
w_sniper_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMSNIPER : TFCANIM_AIMSNIPER;
}
void
w_sniper_release(player pl)
{
if (pl.w_idle_next > 0.0)
return;
if (pl.mode_tempstate > 0) {
float dmg = bound(75, (pl.mode_tempstate/2) * 75, 375);
w_baseauto_fire(WEAPON_SNIPER, player::m_iAmmoShells, dmg, [0,0]);
Weapons_ViewAnimation(pl, SNIPER_FIRE);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTSNIPER, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTSNIPER, 0.45f);
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_RIFLE);
#endif
Weapons_Sound(pl, CHAN_WEAPON, "weapon_sniper.fire");
pl.w_attack_next = 2.0f;
pl.w_idle_next = 0.5f;
pl.mode_tempstate = 0;
}
}
void
w_sniper_primary(player pl)
{
/* when moving, immediately release */
if (vlen(pl.velocity) > 0) {
w_sniper_release(pl);
return;
}
/* weapon speed check */
if (pl.w_attack_next > 0.0)
return;
/* if we aren't already, 'aim' down... */
pl.mode_tempstate += 1;
pl.w_attack_next = 1.0f;
if (pl.mode_tempstate == 0) {
Weapons_ViewAnimation(pl, SNIPER_AIM);
pl.w_idle_next = pl.w_attack_next;
}
}
void
w_sniper_secondary(player pl)
{
if (!(input_buttons & INPUT_BUTTON0)) {
if (pl.mode_tempstate != 0) {
w_sniper_release(pl);
return;
}
}
if (pl.w_idle_next > 0) {
return;
}
/* Simple toggle of fovs */
if (pl.viewzoom == 1.0f) {
pl.viewzoom = 0.2f;
} else {
pl.viewzoom = 1.0f;
}
pl.w_idle_next = 0.25f;
}
void
w_sniper_postdraw(player pl)
{
#ifdef CLIENT
Cross_DrawSub(g_cross_spr, [24,24], [72/128,0], [0.1875, 0.1875]);
if (pl.mode_tempstate) {
vector laser_pos;
float lerpF;
vector jitter = [0.0f, 0.0f, 0.0f];
Weapons_MakeVectors(pl);
vector src = pl.origin + pl.view_ofs;
float a = bound(0.0, (pl.mode_tempstate / 10), 1.0) * 0.75;
traceline(src, src + (v_forward * 256), FALSE, pl);
lerpF = lerp(32,16, trace_fraction);
jitter[0] = (random(0,2) - 2) * (1 - trace_fraction);
jitter[1] = (random(0,2) - 2) * (1 - trace_fraction);
laser_pos = g_hudmins + (g_hudres / 2) + ([-lerpF,-lerpF] / 2);
drawsubpic(
laser_pos + jitter,
[lerpF,lerpF],
g_laser_spr,
[0,0],
[1.0, 1.0],
[1,1,1] * (0.25 + a),
1.0,
DRAWFLAG_ADDITIVE
);
}
// ammo counter
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [24,24], g_hud7_spr, [72/256,72/128], [24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
void
w_sniper_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud2_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud1_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_sniper =
{
.name = "sniper",
.id = ITEM_SNIPER,
.slot = 1,
.slot_pos = 1,
.weight = WEIGHT_SNIPER,
.draw = w_sniper_draw,
.holster = __NULL__,
.primary = w_sniper_primary,
.secondary = w_sniper_secondary,
.reload = __NULL__,
.release = w_sniper_release,
.postdraw = w_sniper_postdraw,
.precache = w_sniper_precache,
.pickup = __NULL__,
.updateammo = w_sniper_updateammo,
.wmodel = __NULL__,
.pmodel = w_sniper_pmodel,
.deathmsg = w_sniper_deathmsg,
.aimanim = w_sniper_aimanim,
.hudpic = w_sniper_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,229 +0,0 @@
/*
* Copyright (c) 2016-2024 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.
*/
enum
{
NAILGUN_IDLE,
NAILGUN_FIDGET1,
NAILGUN_UNUSED1,
NAILGUN_UNUSED2,
NAILGUN_DEPLOY,
NAILGUN_SHOOT1,
NAILGUN_SHOOT2,
NAILGUN_SHOOT3,
};
void
w_supernail_precache(void)
{
#ifdef CLIENT
precache_model("models/v_tfc_supernailgun.mdl");
#else
precache_model("models/w_supernail.mdl");
precache_model("models/p_supernail.mdl");
precache_model("models/nail.mdl");
Sound_Precache("weapon_nailgun.fire");
#endif
}
void
w_supernail_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, __NULL__, pl.m_iAmmoNails, __NULL__);
}
string
w_supernail_wmodel(void)
{
return "models/p_snailgun2.mdl";
}
string
w_supernail_pmodel(player pl)
{
return "models/p_snailgun2.mdl";
}
string
w_supernail_deathmsg(void)
{
return "%s was assaulted by %s's Assault Cannon.";
}
void
w_supernail_draw(player pl)
{
Weapons_SetModel("models/v_tfc_supernailgun.mdl");
Weapons_ViewAnimation(pl, NAILGUN_DEPLOY);
}
float
w_supernail_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIMMP5 : TFCANIM_AIMMP5;
}
void
w_supernail_shootnail(player pl)
{
static void w_rpg_shootrocket_touch(void) {
#ifndef CLIENT
/* impact per bullet */
if (trace_ent.iBleeds == 0) {
DecalGroups_Place("Impact.BigShot", trace_endpos + (v_forward * -2));
SurfData_Impact(trace_ent, trace_endpos, trace_plane_normal);
}
if (trace_ent.takedamage == DAMAGE_YES) {
Damage_Apply(trace_ent, self.owner, 14, WEAPON_NAILGUN, DMG_BULLET);
}
#endif
remove(self);
}
Weapons_MakeVectors(pl);
entity p = spawn();
setmodel(p, "models/nail.mdl");
setorigin(p, Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
p.owner = self;
p.movetype = MOVETYPE_FLYMISSILE;
p.solid = SOLID_BBOX;
p.gravity = 0.5f;
p.velocity = (v_forward * 1000) + (v_up * 4) + (v_right * -2);
p.angles = vectoangles(p.velocity);
p.touch = w_rpg_shootrocket_touch;
p.think = Util_Destroy;
p.nextthink = time + 5.0f;
}
void
w_supernail_primary(player pl)
{
int s = w_baseprojectile_fire_num(pl, WEAPON_NAILGUN, player::m_iAmmoNails, w_supernail_shootnail, 2);
switch (s) {
case AUTO_FIRE_FAILED:
return;
break;
case AUTO_FIRED:
case AUTO_LAST:
int r = (float)input_sequence % 3;
if (r == 1) {
Weapons_ViewAnimation(pl, NAILGUN_SHOOT1);
} else if (r == 2) {
Weapons_ViewAnimation(pl, NAILGUN_SHOOT2);
} else {
Weapons_ViewAnimation(pl, NAILGUN_SHOOT3);
}
Weapons_ViewAnimation(pl, NAILGUN_SHOOT2);
Weapons_ViewPunchAngle(pl, [-1,0,0]);
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTMP5, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTMP5, 0.45f);
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_RIFLE);
#endif
#ifndef CLIENT
Sound_Play(pl, CHAN_WEAPON, "weapon_nailgun.fire");
#endif
pl.w_attack_next = 0.1f;
break;
case AUTO_EMPTY:
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 1.5f;
}
void
w_supernail_hud(player pl)
{
#ifdef CLIENT
vector aicon_pos;
Cross_DrawSub(g_cross_spr, [24,24], [0.1875,0], [0.1875, 0.1875]);
HUD_DrawAmmo2();
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(
aicon_pos,
[24,24],
g_hud7_spr,
[0,72/128],
[24/256, 24/128],
g_hud_color,
pSeatLocal->m_flAmmo2Alpha,
DRAWFLAG_ADDITIVE
);
#endif
}
void
w_supernail_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud7_spr,
[0,135/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud7_spr,
[0,135/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_supernail =
{
.name = "supernail",
.id = ITEM_SUPERNAIL,
.slot = 3,
.slot_pos = 2,
.weight = WEIGHT_SUPERNAIL,
.draw = w_supernail_draw,
.holster = __NULL__,
.primary = w_supernail_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = __NULL__,
.postdraw = w_supernail_hud,
.precache = w_supernail_precache,
.pickup = __NULL__,
.updateammo = w_supernail_updateammo,
.wmodel = w_supernail_wmodel,
.pmodel = w_supernail_pmodel,
.deathmsg = w_supernail_deathmsg,
.aimanim = w_supernail_aimanim,
.hudpic = w_supernail_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,208 +0,0 @@
/*
* 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.
*/
enum
{
TRANQUIL_IDLE1,
TRANQUIL_IDLE2,
TRANQUIL_IDLE3,
TRANQUIL_SHOOT,
TRANQUIL_SHOOT_EMPTY,
TRANQUIL_RELOAD_EMPTY,
TRANQUIL_RELOAD,
TRANQUIL_DRAW,
TRANQUIL_HOLSTER
};
void
w_tranquil_precache(void)
{
precache_model("models/v_tfc_pistol.mdl");
precache_model("models/w_tranquil.mdl");
precache_model("models/p_tranquil.mdl");
Sound_Precache("weapon_tranquilizer.fire");
}
void
w_tranquil_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, __NULL__, pl.m_iAmmoShells, __NULL__);
}
string
w_tranquil_wmodel(void)
{
return "models/w_tranquil.mdl";
}
string
w_tranquil_pmodel(player pl)
{
return "models/p_9mmhandgun2.mdl";
}
string
w_tranquil_deathmsg(void)
{
return "%s is put to sleep by %s.";
}
void
w_tranquil_draw(player pl)
{
Weapons_SetModel("models/v_tfc_pistol.mdl");
Weapons_ViewAnimation(pl, TRANQUIL_DRAW);
Weapons_SetGeomset("geomset 2 2\n");
}
void
w_tranquil_shootdart(player pl)
{
static void w_rpg_shootrocket_touch(void) {
#ifndef CLIENT
/* impact per bullet */
if (trace_ent.iBleeds == 0) {
DecalGroups_Place("Impact.BigShot", trace_endpos + (v_forward * -2));
SurfData_Impact(trace_ent, trace_surfaceflagsi, trace_endpos, trace_plane_normal);
}
if (trace_ent.takedamage == DAMAGE_YES) {
Damage_Apply(trace_ent, self.owner, 18, WEAPON_TRANQUIL, DMG_BULLET);
}
#endif
remove(self);
}
Weapons_MakeVectors(pl);
entity p = spawn();
setmodel(p, "models/nail.mdl");
setorigin(p, Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
p.owner = self;
p.movetype = MOVETYPE_FLYMISSILE;
p.solid = SOLID_BBOX;
p.gravity = 0.5f;
p.velocity = (v_forward * 1000) + (v_up * 4) + (v_right * -2);
p.angles = vectoangles(p.velocity);
p.touch = w_rpg_shootrocket_touch;
p.think = Util_Destroy;
p.nextthink = time + 5.0f;
}
void
w_tranquil_primary(player pl)
{
int s = w_baseprojectile_fire(pl, WEAPON_TRANQUIL, player::m_iAmmoShells, w_tranquil_shootdart);
switch (s) {
case AUTO_FIRE_FAILED:
return;
break;
case AUTO_FIRED:
case AUTO_LAST:
Weapons_ViewAnimation(pl, TRANQUIL_SHOOT);
Weapons_ViewPunchAngle(pl, [-2,0,0]);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_tranquilizer.fire");
if (pl.IsCrouching())
Animation_PlayerTop(pl, TFCANIM_CR_SHOOT1HAND, 0.45f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOT1HAND, 0.45f);
pl.w_attack_next = 1.5f;
break;
case AUTO_EMPTY:
pl.w_attack_next = 0.2f;
break;
}
pl.w_idle_next = 2.5f;
}
float
w_tranquil_aimanim(player pl)
{
return pl.IsCrouching() ? TFCANIM_CR_AIM1HAND : TFCANIM_AIM1HAND;
}
void
w_tranquil_hud(player pl)
{
#ifdef CLIENT
vector aicon_pos;
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
Cross_DrawSub(g_cross_spr, [24,24], [0.1875,0], [0.1875, 0.1875]);
HUD_DrawAmmo2();
drawsubpic(aicon_pos, [24,24], g_hud7_spr, [72/256,72/128], [24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
void
w_tranquil_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud5_spr,
[0,135/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud6_spr,
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_tranquil =
{
.name = "tranquil",
.id = ITEM_TRANQUIL,
.slot = 1,
.slot_pos = 2,
.weight = WEIGHT_TRANQUIL,
.draw = w_tranquil_draw,
.holster = __NULL__,
.primary = w_tranquil_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = __NULL__,
.postdraw = w_tranquil_hud,
.precache = w_tranquil_precache,
.pickup = __NULL__,
.updateammo = w_tranquil_updateammo,
.wmodel = w_tranquil_wmodel,
.pmodel = w_tranquil_pmodel,
.deathmsg = w_tranquil_deathmsg,
.aimanim = w_tranquil_aimanim,
.hudpic = w_tranquil_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,235 +0,0 @@
/*
* 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.
*/
/* stat wise is this the same as the crowbar, but we might tweak it, so it's a
* seperate weapon entry. who knows what modders/servers come up with, too */
enum
{
UMBRELLA_IDLE,
UMBRELLA_DRAW,
UMBRELLA_HOLSTER,
UMBRELLA_ATTACK1HIT,
UMBRELLA_ATTACK1MISS,
UMBRELLA_ATTACK2MISS,
UMBRELLA_ATTACK2HIT,
UMBRELLA_ATTACK3MISS,
UMBRELLA_ATTACK3HIT
};
void
w_umbrella_precache(void)
{
precache_sound("weapons/cbar_miss1.wav");
precache_sound("weapons/cbar_hit1.wav");
precache_sound("weapons/cbar_hit2.wav");
precache_sound("weapons/cbar_hitbod1.wav");
precache_sound("weapons/cbar_hitbod2.wav");
precache_sound("weapons/cbar_hitbod3.wav");
precache_model("models/v_umbrella.mdl");
precache_model("models/w_umbrella.mdl");
precache_model("models/p_umbrella.mdl");
}
void
w_umbrella_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, __NULL__, __NULL__, __NULL__);
#endif
}
string
w_umbrella_wmodel(void)
{
return "models/w_umbrella.mdl";
}
string
w_umbrella_pmodel(player pl)
{
return "models/p_umbrella.mdl";
}
string
w_umbrella_deathmsg(void)
{
return "%s was assaulted by %s's Umbrella.";
}
void
w_umbrella_draw(player pl)
{
Weapons_SetModel("models/v_umbrella.mdl");
Weapons_ViewAnimation(pl, UMBRELLA_DRAW);
}
void
w_umbrella_holster(player pl)
{
Weapons_ViewAnimation(pl, UMBRELLA_HOLSTER);
}
void
w_umbrella_primary(player pl)
{
int anim = 0;
vector src;
if (pl.w_attack_next) {
return;
}
Weapons_MakeVectors(pl);
src = pl.origin + pl.view_ofs;
traceline(src, src + (v_forward * 32), FALSE, pl);
int r = (float)input_sequence % 3;
switch (r) {
case 0:
anim = trace_fraction >= 1 ? UMBRELLA_ATTACK1MISS:UMBRELLA_ATTACK1HIT;
break;
case 1:
anim = trace_fraction >= 1 ? UMBRELLA_ATTACK2MISS:UMBRELLA_ATTACK2HIT;
break;
default:
anim = trace_fraction >= 1 ? UMBRELLA_ATTACK3MISS:UMBRELLA_ATTACK3HIT;
}
Weapons_ViewAnimation(pl, anim);
if (trace_fraction >= 1.0) {
pl.w_attack_next = 0.5f;
} else {
pl.w_attack_next = 0.25f;
}
pl.w_idle_next = 2.5f;
#ifdef SERVER
if (pl.IsCrouching()) {
Animation_PlayerTop(pl, ANIM_SHOOTCROWBAR, 0.5f);
} else {
Animation_PlayerTop(pl, ANIM_CR_SHOOTCROWBAR, 0.42f);
}
sound(pl, CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM);
if (trace_fraction >= 1.0) {
return;
}
/* don't bother with decals, we got squibs */
if (trace_ent.iBleeds) {
FX_Blood(trace_endpos, [1,0,0]);
} else {
SurfData_Impact(trace_ent, trace_endpos, trace_plane_normal);
}
if (trace_ent.takedamage) {
Damage_Apply(trace_ent, self, 18, WEAPON_UMBRELLA, DMG_BLUNT);
if (!trace_ent.iBleeds) {
return;
}
if (random() < 0.33) {
sound(pl, 8, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM);
} else if (random() < 0.66) {
sound(pl, 8, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM);
} else {
sound(pl, 8, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM);
}
} else {
if (random() < 0.5) {
sound(pl, 8, "weapons/cbar_hit1.wav", 1, ATTN_NORM);
} else {
sound(pl, 8, "weapons/cbar_hit2.wav", 1, ATTN_NORM);
}
}
#endif
}
void
w_umbrella_release(player pl)
{
if (pl.w_idle_next) {
return;
}
Weapons_ViewAnimation(pl, UMBRELLA_IDLE);
pl.w_idle_next = 15.0f;
}
float
w_umbrella_aimanim(player pl)
{
return pl.IsCrouching() ? ANIM_CR_AIMCROWBAR : ANIM_AIMCROWBAR;
}
void
w_umbrella_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_hud4_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_hud1_spr,
[0,0],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_umbrella =
{
.name = "umbrella",
.id = ITEM_UMBRELLA,
.slot = 0,
.slot_pos = 4,
.weight = WEIGHT_UMBRELLA,
.draw = w_umbrella_draw,
.holster = w_umbrella_holster,
.primary = w_umbrella_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = w_umbrella_release,
.postdraw = __NULL__,
.precache = w_umbrella_precache,
.pickup = __NULL__,
.updateammo = w_umbrella_updateammo,
.wmodel = w_umbrella_wmodel,
.pmodel = w_umbrella_pmodel,
.deathmsg = w_umbrella_deathmsg,
.aimanim = w_umbrella_aimanim,
.hudpic = w_umbrella_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,252 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2022 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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.
*/
enum
{
WRENCH_IDLE,
WRENCH_ATTACK1,
WRENCH_ATTACK2,
WRENCH_USE,
WRENCH_DRAW,
WRENCH_HOLSTER
};
void
w_wrench_precache(void)
{
precache_sound("weapons/cbar_miss1.wav");
precache_sound("weapons/cbar_hit1.wav");
precache_sound("weapons/cbar_hit2.wav");
precache_sound("weapons/cbar_hitbod1.wav");
precache_sound("weapons/cbar_hitbod2.wav");
precache_sound("weapons/cbar_hitbod3.wav");
precache_model("models/v_tfc_spanner.mdl");
precache_model("models/p_spanner.mdl");
}
void
w_wrench_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, __NULL__, pl.m_iAmmoCells, __NULL__);
}
string
w_wrench_wmodel(void)
{
return "models/ball.mdl";
}
string
w_wrench_pmodel(player pl)
{
return "models/p_spanner.mdl";
}
string
w_wrench_deathmsg(void)
{
return "%s was assaulted by %s's wrench.";
}
void
w_wrench_draw(player pl)
{
Weapons_SetModel("models/v_tfc_spanner.mdl");
Weapons_ViewAnimation(pl, WRENCH_DRAW);
}
void
w_wrench_holster(player pl)
{
Weapons_ViewAnimation(pl, WRENCH_HOLSTER);
}
void
w_wrench_primary(player pl)
{
int anim = 0;
vector src;
if (pl.w_attack_next) {
return;
}
Weapons_MakeVectors(pl);
src = pl.origin + pl.view_ofs;
traceline(src, src + (v_forward * 32), FALSE, pl);
int r = (float)input_sequence % 2;
switch (r) {
case 0:
anim = WRENCH_ATTACK1;
break;
default:
anim = WRENCH_ATTACK2;
}
Weapons_ViewAnimation(pl, anim);
if (trace_fraction < 1.0) {
pl.w_attack_next = 0.25f;
} else {
pl.w_attack_next = 0.5f;
}
pl.w_idle_next = 2.5f;
#ifdef SERVER
if (pl.IsCrouching()) {
Animation_PlayerTop(pl, ANIM_SHOOTCROWBAR, 0.5f);
} else {
Animation_PlayerTop(pl, ANIM_CR_SHOOTCROWBAR, 0.42f);
}
sound(pl, CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM);
if (trace_fraction >= 1.0) {
return;
}
if (trace_ent.classname == "TFCSentry") {
TFCSentry sentry = (TFCSentry)trace_ent;
/* todo
} else if (trace_ent.classname == "TFCDispenser") {
TFCDispenser dispenser = (TFCDispenser)trace_ent;
todo
} else if (trace_ent.classname == "TFCTeleporter") {
TFCTeleporter teleporter = (TFCTeleporter)trace_ent;
todo
} else if (trace_ent.classname == "TFCTeleporterExit") {
TFCTeleporterExit teleporterexit = (TFCTeleporterExit)trace_ent;
todo */
} else {
/* don't bother with decals, we got squibs */
if (trace_ent.iBleeds) {
FX_Blood(trace_endpos, [1,0,0]);
} else {
SurfData_Impact(trace_ent, trace_endpos, trace_plane_normal);
}
/* Damage without armor is between 12 - 20, so let's just do 15 for now */
if (trace_ent.takedamage) {
Damage_Apply(trace_ent, pl, 18, WEAPON_WRENCH, DMG_BLUNT);
if (trace_ent.iBleeds) {
Sound_Play(self, CHAN_WEAPON, "weapon_crowbar.hitbody");
}
} else {
Sound_Play(self, CHAN_WEAPON, "weapon_crowbar.hit");
}
}
#endif
}
void
w_wrench_release(player pl)
{
if (pl.w_idle_next) {
return;
}
Weapons_ViewAnimation(pl, WRENCH_IDLE);
pl.w_idle_next = 15.0f;
}
void
w_wrench_crosshair(player pl)
{
#ifdef CLIENT
vector aicon_pos;
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(
aicon_pos,
[24,24],
g_hud7_spr,
[0,96/128],
[24/256,24/128],
g_hud_color,
pSeatLocal->m_flAmmo2Alpha,
DRAWFLAG_ADDITIVE
);
HUD_DrawAmmo2();
#endif
}
float
w_wrench_aimanim(player pl)
{
return pl.IsCrouching() ? ANIM_CR_AIMCROWBAR : ANIM_AIMCROWBAR;
}
void
w_wrench_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud4_spr,
[0,180/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud3_spr,
[0,135/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
HUD_DrawAmmoBar(pos, pl.m_iAmmoCells, MAX_A_CELLS, a);
#endif
}
weapon_t w_wrench =
{
.name = "wrench",
.id = ITEM_WRENCH,
.slot = 0,
.slot_pos = 3,
.weight = WEIGHT_WRENCH,
.draw = w_wrench_draw,
.holster = w_wrench_holster,
.primary = w_wrench_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = w_wrench_release,
.postdraw = w_wrench_crosshair,
.precache = w_wrench_precache,
.pickup = __NULL__,
.updateammo = w_wrench_updateammo,
.wmodel = w_wrench_wmodel,
.pmodel = w_wrench_pmodel,
.deathmsg = w_wrench_deathmsg,
.aimanim = w_wrench_aimanim,
.hudpic = w_wrench_hudpic,
.isempty = w_asscan_isempty
};

View file

@ -1,51 +0,0 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* 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.
*/
enum
{
AUTO_FIRE_FAILED,
AUTO_FIRED,
AUTO_LAST,
AUTO_EMPTY
};
int
w_baseauto_fire(int w, .int mag, int d, vector bs)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return (AUTO_FIRE_FAILED);
}
if (pl.gflags & GF_SEMI_TOGGLED) {
return (AUTO_FIRE_FAILED);
}
if (pl.(mag) <= 0) {
pl.gflags |= GF_SEMI_TOGGLED;
return (AUTO_EMPTY);
}
pl.(mag)--;
#ifdef SERVER
TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, d, bs, w);
#endif
if (pl.(mag) == 0)
return (AUTO_LAST);
else
return (AUTO_FIRED);
}

View file

@ -1,59 +0,0 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* 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.
*/
enum
{
MELEE_FAILED,
MELEE_MISS,
MELEE_HIT,
MELEE_HITBODY
};
int
w_basemelee_fire(int d, int w)
{
int anim = 0;
vector src;
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return (MELEE_FAILED);
}
Weapons_MakeVectors(pl);
src = pl.origin + pl.view_ofs;
/* make sure we can gib corpses */
int oldhitcontents = self.hitcontentsmaski;
self.hitcontentsmaski = CONTENTBITS_POINTSOLID | CONTENTBIT_CORPSE;
traceline(src, src + (v_forward * 32), FALSE, pl);
self.hitcontentsmaski = oldhitcontents;
pl.w_attack_next = 0.5f;
pl.w_idle_next = 2.5f;
if (trace_fraction >= 1.0) {
return (MELEE_MISS);
}
#ifdef SERVER
if (trace_ent.takedamage) {
Damage_Apply(trace_ent, pl, d, w, DMG_BLUNT);
}
#endif
return (MELEE_HIT);
}

View file

@ -1,74 +0,0 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* 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.
*/
enum
{
SEMI_FIRE_FAILED,
SEMI_FIRED,
SEMI_LAST,
SEMI_EMPTY
};
int
w_baseprojectile_fire(player pl, int w, .int mag, void(player) spawnfunc)
{
if (pl.w_attack_next > 0.0) {
return (SEMI_FIRE_FAILED);
}
if (pl.gflags & GF_SEMI_TOGGLED) {
return (SEMI_FIRE_FAILED);
}
if (pl.(mag) <= 0) {
return (SEMI_EMPTY);
}
pl.(mag)--;
#ifdef SERVER
spawnfunc(pl);
#endif
if (pl.(mag) == 0)
return (SEMI_LAST);
else
return (SEMI_FIRED);
}
int
w_baseprojectile_fire_num(player pl, int w, .int mag, void(player) spawnfunc, int num)
{
if (pl.w_attack_next > 0.0) {
return (SEMI_FIRE_FAILED);
}
if (pl.gflags & GF_SEMI_TOGGLED) {
return (SEMI_FIRE_FAILED);
}
if ((pl.(mag) - num) < 0) {
return (SEMI_EMPTY);
}
pl.(mag) -= num;
#ifdef SERVER
spawnfunc(pl);
#endif
if (pl.(mag) == 0)
return (SEMI_LAST);
else
return (SEMI_FIRED);
}

View file

@ -1,53 +0,0 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* 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.
*/
enum
{
SEMI_FIRE_FAILED,
SEMI_FIRED,
SEMI_LAST,
SEMI_EMPTY
};
int
w_basesemi_fire(int w, .int mag, int d, vector bs)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return (SEMI_FIRE_FAILED);
}
if (pl.gflags & GF_SEMI_TOGGLED) {
return (SEMI_FIRE_FAILED);
}
if (pl.(mag) <= 0) {
pl.gflags |= GF_SEMI_TOGGLED;
return (SEMI_EMPTY);
}
pl.(mag)--;
#ifdef SERVER
TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, d, bs, w);
#endif
pl.gflags |= GF_SEMI_TOGGLED;
if (pl.(mag) == 0)
return (SEMI_LAST);
else
return (SEMI_FIRED);
}

View file

@ -1,121 +0,0 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* 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.
*/
enum
{
SHOTGUN_FIRE_FAILED,
SHOTGUN_FIRED,
SHOTGUN_LAST,
SHOTGUN_EMPTY
};
int
w_baseshotgun_fire(int w, .int mag, int c, int d, vector bs)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return (SHOTGUN_FIRE_FAILED);
}
if (pl.gflags & GF_SEMI_TOGGLED) {
return (SHOTGUN_FIRE_FAILED);
}
if (pl.(mag) <= 0) {
pl.gflags |= GF_SEMI_TOGGLED;
return (SHOTGUN_EMPTY);
}
pl.(mag)--;
#ifdef SERVER
TraceAttack_FireBullets(c, pl.origin + pl.view_ofs, d, bs, w);
#endif
if (pl.(mag) == 0)
return (SHOTGUN_LAST);
else
return (SHOTGUN_FIRED);
}
enum
{
SHOTTY_IDLE,
SHOTTY_RELOAD_START,
SHOTTY_RELOAD,
SHOTTY_RELOAD_END,
SHOTTY_COCKSOUND
};
void
w_baseshotgun_reload(.int mag, .int ammo, int max)
{
player pl = (player)self;
if (pl.(mag) >= max) {
return;
}
if (pl.(ammo) <= 0) {
return;
}
if (pl.mode_tempstate > SHOTTY_IDLE) {
return;
}
pl.mode_tempstate = SHOTTY_RELOAD_START;
pl.w_idle_next = 0.0f;
}
enum
{
SHOTGUN_IDLE,
SHOTGUN_BUSY,
SHOTGUN_START_RELOAD,
SHOTGUN_RELOAD,
SHOTGUN_END_RELOAD
};
int
w_baseshotgun_release(.int mag, .int ammo, int max)
{
player pl = (player)self;
if (pl.w_idle_next > 0.0) {
return (SHOTGUN_BUSY);
}
if (pl.mode_tempstate == SHOTTY_RELOAD_START) {
pl.mode_tempstate = SHOTTY_RELOAD;
pl.w_idle_next = 0.65f;
return (SHOTGUN_START_RELOAD);
} else if (pl.mode_tempstate == SHOTTY_RELOAD) {
pl.(mag)++;
pl.(ammo)--;
if (pl.(ammo) <= 0 || pl.(mag) >= max) {
pl.mode_tempstate = SHOTTY_RELOAD_END;
}
Weapons_UpdateAmmo(pl, pl.(mag), pl.(ammo), pl.mode_tempstate);
pl.w_idle_next = 0.5f;
return (SHOTGUN_RELOAD);
} else if (pl.mode_tempstate == SHOTTY_RELOAD_END) {
pl.mode_tempstate = SHOTTY_IDLE;
pl.w_idle_next = 10.0f;
pl.w_attack_next = 0.5f;
return (SHOTGUN_END_RELOAD);
}
return (SHOTGUN_IDLE);
}

View file

@ -1,40 +0,0 @@
/*
* 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.
*/
weapon_t w_null = {};
weapon_t g_weapons[] = {
w_null,
w_crowbar,
w_medkit,
w_knife,
w_wrench,
w_umbrella,
w_sbs,
w_sniper,
w_tranquil,
w_railgun,
w_autorifle,
w_dbs,
w_nailgun,
w_glauncher,
w_supernail,
w_flamer,
w_rpg,
w_pipebomb,
w_asscan,
w_incendiary,
w_grapple
};