diff --git a/src/client/cmds.qc b/src/client/cmds.qc new file mode 100644 index 0000000..e52d7d9 --- /dev/null +++ b/src/client/cmds.qc @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016-2020 Marco Cawthorne + * + * 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. + */ + +int +ClientGame_ConsoleCommand(void) +{ + switch(argv(0)) { + case "build": + int type = stoi(argv(1)); + + switch (type) { + case 1: + sendevent("TFC_BuildDispenser", ""); + break; + case 2: + sendevent("TFC_BuildSentry", ""); + break; + case 4: + sendevent("TFC_BuildTele", ""); + break; + case 5: + sendevent("TFC_BuildTeleExit", ""); + break; + } + break; + default: + return (0); + } + return (1); +} diff --git a/src/client/init.qc b/src/client/init.qc index 27a24f7..10d5b8a 100644 --- a/src/client/init.qc +++ b/src/client/init.qc @@ -24,6 +24,7 @@ Comparable to worldspawn in SSQC in that it's mostly used for precaches void ClientGame_Init(float apilevel, string enginename, float engineversion) { + registercommand("build"); Obituary_Init(); } diff --git a/src/client/progs.src b/src/client/progs.src index b6cc890..02a7b2b 100644 --- a/src/client/progs.src +++ b/src/client/progs.src @@ -26,7 +26,7 @@ init.qc ../../../valve/src/client/flashlight.qc ../../../valve/src/client/player.qc entities.qc -../../../valve/src/client/cmds.qc +cmds.qc game_event.qc ../../../valve/src/client/camera.qc ../../../valve/src/client/viewmodel.qc diff --git a/src/server/dispencer.qc b/src/server/dispencer.qc new file mode 100644 index 0000000..4d7ff32 --- /dev/null +++ b/src/server/dispencer.qc @@ -0,0 +1,75 @@ + +#define TFC_SENTRY_COST 130 + +class +TFCSentry:NSSurfacePropEntity +{ + NSSurfacePropEntity m_eHead; + + void(void) TFCSentry; + + virtual void(player) Place; + virtual void(void) FinishPlacing; +}; + +void +TFCSentry::Place(player pl) +{ + SetAngles(pl.GetAngles()); + + makevectors([0, pl.v_angle[1], 0]); + SetOrigin(pl.origin + (v_forward * 48)); + DropToFloor(); + + think = FinishPlacing; + nextthink = time + 5.0f; + real_owner = pl; + + env_message_single(real_owner, "#Engineer_building"); + Sound_Play(this, CHAN_BODY, "engineer.build"); +} + +void +TFCSentry::FinishPlacing(void) +{ + /* put the top on that spins */ + m_eHead.SetModel("models/sentry1.mdl"); + m_eHead.SetAngles(GetAngles()); + m_eHead.SetSolid(SOLID_BBOX); + m_eHead.SetMovetype(MOVETYPE_NONE); + m_eHead.SetSize([-16,-16,0], [16,16,32]); + m_eHead.SetOrigin(GetOrigin() + [0,0,20]); + + env_message_single(real_owner, "#Sentry_finish"); + Sound_Play(this, CHAN_BODY, "engineer.turret_set"); +} + +void +TFCSentry::TFCSentry(void) +{ + m_eHead = spawn(NSSurfacePropEntity); + SetModel("models/base.mdl"); + SetSolid(SOLID_BBOX); + SetMovetype(MOVETYPE_NONE); + SetSize([-16,-16,0], [16,16,20]); +} + +void +CSEv_TFC_BuildSentry_(void) +{ + player pl = (player)self; + + /* only engineers can do this */ + if (pl.classtype != CLASS_ENGINEER) + return; + + /* it costs */ + if (pl.m_iAmmoCells < TFC_SENTRY_COST) + return; + + pl.m_iAmmoCells -= TFC_SENTRY_COST; + + /* deploy */ + TFCSentry sentry = spawn(TFCSentry); + sentry.Place(pl); +} diff --git a/src/server/dispenser.qc b/src/server/dispenser.qc new file mode 100644 index 0000000..08529bf --- /dev/null +++ b/src/server/dispenser.qc @@ -0,0 +1,66 @@ + +#define TFC_DISPENSER_COST 100 + +class +TFCDispenser:NSSurfacePropEntity +{ + + void(void) TFCDispenser; + + virtual void(player) Place; + virtual void(void) FinishPlacing; +}; + +void +TFCDispenser::Place(player pl) +{ + SetAngles(pl.GetAngles()); + + makevectors([0, pl.v_angle[1], 0]); + SetOrigin(pl.origin + (v_forward * 48)); + DropToFloor(); + + think = FinishPlacing; + nextthink = time + 5.0f; + real_owner = pl; + colormap = pl.colormap; + + env_message_single(real_owner, "#Engineer_building"); + Sound_Play(this, CHAN_BODY, "engineer.build"); +} + +void +TFCDispenser::FinishPlacing(void) +{ + env_message_single(real_owner, "#Dispenser_finish"); + Sound_Play(this, CHAN_BODY, "engineer.turret_set"); +} + +void +TFCDispenser::TFCDispenser(void) +{ + SetModel("models/dispenser.mdl"); + SetSolid(SOLID_BBOX); + SetMovetype(MOVETYPE_NONE); + SetSize([-16,-16,0], [16,16,48]); +} + +void +CSEv_TFC_BuildDispenser_(void) +{ + player pl = (player)self; + + /* only engineers can do this */ + if (pl.classtype != CLASS_ENGINEER) + return; + + /* it costs */ + if (pl.m_iAmmoCells < TFC_DISPENSER_COST) + return; + + pl.m_iAmmoCells -= TFC_DISPENSER_COST; + + /* deploy */ + TFCDispenser dispenser = spawn(TFCDispenser); + dispenser.Place(pl); +} diff --git a/src/server/progs.src b/src/server/progs.src index 6bbb601..af48289 100644 --- a/src/server/progs.src +++ b/src/server/progs.src @@ -22,6 +22,10 @@ defs.h ../../../valve/src/server/player.qc ../../../valve/src/server/spectator.qc +dispenser.qc +sentry.qc +teleporter.qc + vox.qc ../../../valve/src/server/items.qc info_player_teamspawn.qc diff --git a/src/server/sentry.qc b/src/server/sentry.qc new file mode 100644 index 0000000..ebcccb6 --- /dev/null +++ b/src/server/sentry.qc @@ -0,0 +1,76 @@ + +#define TFC_SENTRY_COST 130 + +class +TFCSentry:NSSurfacePropEntity +{ + NSSurfacePropEntity m_eHead; + + void(void) TFCSentry; + + virtual void(player) Place; + virtual void(void) FinishPlacing; +}; + +void +TFCSentry::Place(player pl) +{ + SetAngles(pl.GetAngles()); + + makevectors([0, pl.v_angle[1], 0]); + SetOrigin(pl.origin + (v_forward * 48)); + DropToFloor(); + + think = FinishPlacing; + nextthink = time + 5.0f; + real_owner = pl; + colormap = pl.colormap; + + env_message_single(real_owner, "#Engineer_building"); + Sound_Play(this, CHAN_BODY, "engineer.build"); +} + +void +TFCSentry::FinishPlacing(void) +{ + /* put the top on that spins */ + m_eHead.SetModel("models/sentry1.mdl"); + m_eHead.SetAngles(GetAngles()); + m_eHead.SetSolid(SOLID_BBOX); + m_eHead.SetMovetype(MOVETYPE_NONE); + m_eHead.SetSize([-16,-16,0], [16,16,32]); + m_eHead.SetOrigin(GetOrigin() + [0,0,20]); + + env_message_single(real_owner, "#Sentry_finish"); + Sound_Play(this, CHAN_BODY, "engineer.turret_set"); +} + +void +TFCSentry::TFCSentry(void) +{ + m_eHead = spawn(NSSurfacePropEntity); + SetModel("models/base.mdl"); + SetSolid(SOLID_BBOX); + SetMovetype(MOVETYPE_NONE); + SetSize([-16,-16,0], [16,16,20]); +} + +void +CSEv_TFC_BuildSentry_(void) +{ + player pl = (player)self; + + /* only engineers can do this */ + if (pl.classtype != CLASS_ENGINEER) + return; + + /* it costs */ + if (pl.m_iAmmoCells < TFC_SENTRY_COST) + return; + + pl.m_iAmmoCells -= TFC_SENTRY_COST; + + /* deploy */ + TFCSentry sentry = spawn(TFCSentry); + sentry.Place(pl); +} diff --git a/src/server/server.qc b/src/server/server.qc index 35d8b61..7248689 100644 --- a/src/server/server.qc +++ b/src/server/server.qc @@ -29,6 +29,8 @@ Game_Worldspawn(void) Sound_Precache("player.lightfall"); Sound_Precache("player_tfc.death"); Sound_Precache("player_tfc.jump"); + Sound_Precache("engineer.build"); + Sound_Precache("engineer.turret_set"); precache_model("models/player.mdl"); precache_model("models/w_weaponbox.mdl"); diff --git a/src/server/teleporter.qc b/src/server/teleporter.qc new file mode 100644 index 0000000..97122d2 --- /dev/null +++ b/src/server/teleporter.qc @@ -0,0 +1,153 @@ + +#define TFC_TELEPORTER_COST 125 + +/* main teleporter */ +class +TFCTeleporter:NSSurfacePropEntity +{ + float m_flNextTeleport; + + void(void) TFCTeleporter; + + virtual void(player) Place; + virtual void(void) FinishPlacing; + virtual void(entity) Touch; +}; + +void +TFCTeleporter::Touch(entity eToucher) +{ + if (eToucher.team != real_owner.team) + return; + + if (m_flNextTeleport > time) + return; + + TFCTeleporter target = world; + string exitname; + + if (classname == "TFCTeleporter") + exitname = "TFCTeleporterExit"; + else + return; + + /* loop through all exits */ + for (entity e = world; (e = find(e, ::classname, exitname));) { + /* if it's not places by our owner... */ + if (e.real_owner != real_owner) + continue; + + target = (TFCTeleporter)e; + break; + } + + if (!target) + return; + + /* teleport our player */ + setorigin(eToucher, target.origin + [0,0,32]); + + /* if the teleport was successful, make them unusable for 2.5 secs */ + target.m_flNextTeleport = m_flNextTeleport = time + 2.5f; + +} + +void +TFCTeleporter::Place(player pl) +{ + SetAngles(pl.GetAngles()); + + makevectors([0, pl.v_angle[1], 0]); + SetOrigin(pl.origin + (v_forward * 48)); + DropToFloor(); + + think = FinishPlacing; + nextthink = time + 5.0f; + real_owner = pl; + colormap = pl.colormap; + + env_message_single(real_owner, "#Engineer_building"); + Sound_Play(this, CHAN_BODY, "engineer.build"); +} + +void +TFCTeleporter::FinishPlacing(void) +{ + env_message_single(real_owner, "You built the entrance, sonny!"); + Sound_Play(this, CHAN_BODY, "engineer.turret_set"); +} + +void +TFCTeleporter::TFCTeleporter(void) +{ + SetModel("models/dispenser.mdl"); + SetSolid(SOLID_TRIGGER); + SetMovetype(MOVETYPE_NONE); + SetSize([-16,-16,0], [16,16,48]); +} + + +/* exit only */ +class +TFCTeleporterExit:TFCTeleporter +{ + void(void) TFCTeleporterExit; + virtual void(void) FinishPlacing; +}; + +void +TFCTeleporterExit::FinishPlacing(void) +{ + env_message_single(real_owner, "You built the exit, sonny!"); + Sound_Play(this, CHAN_BODY, "engineer.turret_set"); +} + +void +TFCTeleporterExit::TFCTeleporterExit(void) +{ + SetModel("models/dispenser.mdl"); + SetSolid(SOLID_TRIGGER); + SetMovetype(MOVETYPE_NONE); + SetSize([-16,-16,0], [16,16,48]); +} + +void +CSEv_TFC_BuildTele_(void) +{ + player pl = (player)self; + + /* only engineers can do this */ + if (pl.classtype != CLASS_ENGINEER) + return; + + /* it costs */ + if (pl.m_iAmmoCells < TFC_TELEPORTER_COST) + return; + + pl.m_iAmmoCells -= TFC_TELEPORTER_COST; + + /* deploy */ + TFCTeleporter start = spawn(TFCTeleporter); + start.Place(pl); +} + + +void +CSEv_TFC_BuildTeleExit_(void) +{ + player pl = (player)self; + + /* only engineers can do this */ + if (pl.classtype != CLASS_ENGINEER) + return; + + /* it costs */ + if (pl.m_iAmmoCells < TFC_TELEPORTER_COST) + return; + + pl.m_iAmmoCells -= TFC_TELEPORTER_COST; + + /* deploy */ + TFCTeleporterExit end = spawn(TFCTeleporterExit); + end.Place(pl); +} diff --git a/zpak001.pk3dir/sound/weapons_tfc.sndshd b/zpak001.pk3dir/sound/weapons_tfc.sndshd index e49af20..0a69d13 100644 --- a/zpak001.pk3dir/sound/weapons_tfc.sndshd +++ b/zpak001.pk3dir/sound/weapons_tfc.sndshd @@ -17,3 +17,13 @@ weapon_sbs.reload { sample weapons/reload3.wav } + +engineer.build +{ + sample weapons/building.wav +} + +engineer.turret_set +{ + sample weapons/turrset.wav +}