From f9479abb3d409db5099ab669a98dbe4948d4469c Mon Sep 17 00:00:00 2001 From: cypress Date: Thu, 23 Nov 2023 11:42:08 -0500 Subject: [PATCH] SERVER: Revamp Pack-A-Punch --- progs/fte-server.src | 1 + progs/standard.src | 1 + source/server/entities/machines.qc | 222 +---------- source/server/entities/pack_a_punch.qc | 499 +++++++++++++++++++++++++ source/server/entities/wall_weapon.qc | 2 + 5 files changed, 516 insertions(+), 209 deletions(-) create mode 100644 source/server/entities/pack_a_punch.qc diff --git a/progs/fte-server.src b/progs/fte-server.src index 1f20016..98e7758 100644 --- a/progs/fte-server.src +++ b/progs/fte-server.src @@ -26,6 +26,7 @@ ../source/server/entities/func.qc ../source/server/entities/traps.qc ../source/server/entities/lights.qc +../source/server/entities/pack_a_punch.qc ../source/server/entities/mystery_box.qc ../source/server/entities/doors.qc ../source/server/entities/window.qc diff --git a/progs/standard.src b/progs/standard.src index 0e6b07e..b45cd78 100644 --- a/progs/standard.src +++ b/progs/standard.src @@ -30,6 +30,7 @@ ../source/server/entities/func.qc ../source/server/entities/traps.qc ../source/server/entities/lights.qc +../source/server/entities/pack_a_punch.qc ../source/server/entities/mystery_box.qc ../source/server/entities/doors.qc ../source/server/entities/window.qc diff --git a/source/server/entities/machines.qc b/source/server/entities/machines.qc index 43d356c..1d297aa 100644 --- a/source/server/entities/machines.qc +++ b/source/server/entities/machines.qc @@ -1,7 +1,7 @@ /* server/entities/machines.qc - perks, pap, power + perks, power Copyright (C) 2021-2023 NZ:P Team @@ -27,7 +27,6 @@ float backupWepSkin; float sound_perk_delay; -void() W_PutOutHack; void(entity person) W_HideCrosshair; // @@ -1005,7 +1004,8 @@ void() Turn_Lights = entity tempe = findfloat(world, requirespower, 1); while (tempe) { - Turn_PerkLight_On(tempe); + if (tempe.classname != "perk_pap") + Turn_PerkLight_On(tempe); tempe = findfloat (tempe, requirespower, 1); } @@ -1078,6 +1078,16 @@ void() touch_power_Switch = tempe = find (tempe, classname, "door_nzp");// trigger all paired doors } } + + tempe = find(world, classname, "perk_pap"); + while(tempe != world) { + entity tempe2 = self; + self = tempe; + PAP_TurnOn(); + self = tempe2; + tempe = find(tempe, classname, "perk_pap"); + } + Turn_Lights(); SUB_UseTargets(); } @@ -1112,212 +1122,6 @@ void() power_switch = isPowerOn = false; } -// -// -------------------- -// Pack-a-Punch -// -------------------- -// -// cypress 19 OCT 2023 -- Changed storage from .owner to .usedent, -// as .owner causes issues with entity relinking, subsequently breaking -// PlayerIsLooking(). -// - -void removeinpap() { - //remove(self); -}; - -//Self = floating gun -void velocity_reduce_output() { - makevectors(self.usedent.angles); - self.velocity = [0,0,0]; - setorigin(self, self.usedent.origin + v_forward*25); - - //start floating back into pap - self.velocity = v_forward*-1.5; -} - -//Self = floating gun -void velocity_reduce_output_in() { - self.velocity = [0,0,0]; - setorigin(self, self.usedent.origin); -} - -void() reset_pap = -{ - self.weapon = 0; - self.usedent = 0; - - - if (self.goaldummy) { - remove(self.goaldummy); - self.goaldummy = 0; - } - - - self.papState = 0; -} - -//Self = pap -void PapSendOut() { - makevectors(self.angles); - setorigin(self.goaldummy, self.origin); - self.goaldummy.velocity = v_forward*25; - - self.goaldummy.think = velocity_reduce_output; - self.goaldummy.nextthink = time + 1; - - self.papState = 2; - self.nextthink = time + 15; - self.think = reset_pap; -} -void() W_PlayTakeOut; -void PapUpgrade(entity pap, entity buyer) { - entity tempe; - string modelname; - - tempe = self; - self = buyer; - addmoney (self, -5000, 0); - - //////////WepModel IN Floating test//////// - - entity floatmodelin; - - modelname = GetWeaponModel(self.weapon, 1); - - floatmodelin = spawn (); - - - //model goes in - makevectors(pap.angles); - setorigin (floatmodelin, pap.origin + v_forward*25); - setmodel (floatmodelin, modelname); - setsize (floatmodelin, '0 0 0', '0 0 0'); - floatmodelin.angles = pap.angles; - floatmodelin.angles_y = 90 + pap.angles_y; - - floatmodelin.movetype = MOVETYPE_NOCLIP; - floatmodelin.solid = SOLID_NOT; - - floatmodelin.usedent = pap; - floatmodelin.velocity = v_forward*-25; - - floatmodelin.think = velocity_reduce_output_in; - floatmodelin.nextthink = time + 1; - - //model goes velocity_reduce_output - pap.usedent = self; - pap.goaldummy = floatmodelin; - pap.think = PapSendOut; - pap.nextthink = time + 3.5; - - - //////////////////////////////////////// - - self.fire_delay = self.reload_delay = 2.0 + time; - sound(self,CHAN_WEAPON,"sounds/machines/papsound.wav",1,ATTN_NORM); - - pap.weapon = self.weapon; - - Weapon_RemoveWeapon(0); - W_HideCrosshair(self); - Set_W_Frame (0, 39, 2.0, 0, 0, W_PutOutHack, "models/machines/v_pap.mdl", true, S_BOTH); - self.weapon2model = ""; - UpdateV2model(self.weapon2model, 0); - -#ifndef FTE - - self.Weapon_Name = ""; - -#endif // FTE - - self = tempe; - - self.papState = 1; - -} - -void touch_pap() { - - if (other.classname != "player" || other.downed || !PlayerIsLooking(other, self)) { - return; - } - - if (other.reload_delay > time || other.reload_delay2 > time || - other.fire_delay > time || other.fire_delay2 > time) - return; - - if (self.requirespower == true && !isPowerOn) { - useprint (other, 8, 0, 0); - return; - } - - if (!self.papState) { - if (IsPapWeapon(other.weapon) == 1) { - return; - } - useprint (other, 12, 5000, 5); - if (other.points >= 5000 && other.button7 && other.weapon) - { - PapUpgrade(self, other); - - } - else if (other.button7 && other.weapon && !other.semiuse) { - other.semiuse = true; - centerprint (other, STR_NOTENOUGHPOINTS); - sound(other, 0, "sounds/misc/denybuy.wav", 1, 1); - } - } else if (self.papState == 2) { - -#ifndef FTE - - other.Weapon_Name_Touch = GetWeaponName(EqualPapWeapon(self.weapon)); - -#endif // FTE - - useprint (other, 7, 0, EqualPapWeapon(self.weapon)); - - if (other.button7) { - entity tempe = self; - self = other; - Weapon_GiveWeapon(EqualPapWeapon(tempe.weapon), 0, 0); - self = tempe; - // because PaP broke itself - self.think = reset_pap; - self.nextthink = time + 0.1; - } - } -} - -void() perk_pap = -{ - entity tempe; - - tempe = find (world, classname, "power_switch");// trigger all paired doors - - self.solid = SOLID_TRIGGER; - - if (tempe) { - self.requirespower = true; - } else { - self.requirespower = false; - } - - // Only cache the dual wield pap weapons if we have pap.. - precache_extra(W_BIATCH); - precache_extra(W_SNUFF); - - precache_model ("models/machines/quake_scale/pap.mdl"); - precache_model ("models/machines/v_pap.mdl"); - precache_sound ("sounds/machines/papsound.wav"); - precache_sound("sounds/weapons/papfire.wav"); - setorigin(self, self.origin); - setmodel (self, "models/machines/quake_scale/pap.mdl"); - setsize (self, VEC_HULL2_MIN, VEC_HULL2_MAX); - self.classname = "perk_pap"; - self.touch = touch_pap; -} - // Sorta ugly function but whatever void() perk_random = { diff --git a/source/server/entities/pack_a_punch.qc b/source/server/entities/pack_a_punch.qc new file mode 100644 index 0000000..419261d --- /dev/null +++ b/source/server/entities/pack_a_punch.qc @@ -0,0 +1,499 @@ +/* + server/entities/pack_a_punch.qc + + Pack-A-Punch Entity Logic + + Copyright (C) 2021-2023 NZ:P Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#define PAP_SPAWNFLAG_USEROLLER 1 +#define PAP_SPAWNFLAG_USEFLAG 2 +#define PAP_SPAWNFLAG_NOSPARK 4 + +void() W_PutOutHack; +void(vector where, float time_alive) SpawnSpark; + +// +// PAP_FlagStopMoving() +// Resets flag's angular velocity. +// +void() PAP_FlagStopMoving = +{ + self.avelocity = '0 0 0'; + + if (self.ltime) + self.angles_z = 180; + else + self.angles_z = 0; + + self.think = SUB_Null; +} + +// +// PAP_FlagMoveDown() +// Moves the Flag Downwards +// +void() PAP_FlagMoveDown = +{ + // Make a note that we're moving "down" + self.ltime = 1; + self.avelocity = '0 0 500'; + self.think = PAP_FlagStopMoving; + self.nextthink = time + 0.35; +} + +// +// PAP_FlagMoveUp() +// Moves the Flag upwards +// +void() PAP_FlagMoveUp = +{ + // Make a note that we're moving "up" + self.ltime = 0; + self.avelocity = '0 0 -500'; + self.think = PAP_FlagStopMoving; + self.nextthink = time + 0.35; +} + +// +// PAP_WeaponFallIntoMachine() +// Slowy reel the Upgraded Weapon back into +// the Pack-A-Punch. +// +void() PAP_WeaponFallIntoMachine = +{ + makevectors(self.usedent.angles); + self.velocity = '0 0 0'; + setorigin(self, self.usedent.oldorigin + v_forward*self.usedent.oldz); + self.velocity = v_forward*-1.5; +}; + +// +// PAP_WeaponStopMoving() +// Stop all velocity on the floating Weapon +// and let it sit in the machine. +// +void() PAP_WeaponStopMoving = +{ + self.velocity = [0,0,0]; + setorigin(self, self.usedent.oldorigin); +}; + +// +// PAP_Reset() +// Allow the Pack-A-Punch to Upgrade another Weapon. +// +void() PAP_Reset = +{ + self.weapon = 0; + self.usedent = 0; + + + if (self.goaldummy) { + remove(self.goaldummy); + self.goaldummy = 0; + } + + + self.papState = 0; +}; + +// +// PAP_Tick() +// Weapon is slowly going back to machine, tick for +// anxiety. +// +void() PAP_Tick = +{ + // Time is up, Weapon is gone. + if (self.ltime < time) + PAP_Reset(); + else { + sound(self, CHAN_BODY, "sounds/machines/packapunch/tick.wav", 1, 1); + self.nextthink = time + 0.87; + } +}; + +// +// PAP_SendWeaponOut() +// Spits out the floating Weapon for pick-up. +// +void() PAP_SendWeaponOut = +{ + makevectors(self.angles); + + self.goaldummy.origin = self.oldorigin; + setorigin(self.goaldummy, self.goaldummy.origin); + self.goaldummy.velocity = v_forward*self.oldz; + + // Reel the Weapon in + self.goaldummy.think = PAP_WeaponFallIntoMachine; + self.goaldummy.nextthink = time + 1; + + self.papState = 2; + self.nextthink = time + 0.05; + self.ltime = time + 15; + self.think = PAP_Tick; + Light_None(self); + + if ((self.spawnflags & PAP_SPAWNFLAG_USEFLAG)) { + self.boxweapon.think = PAP_FlagMoveDown; + self.boxweapon.nextthink = time + 0.05; + } +}; + +// +// PAP_UpgradeWeapon(pap, buyer) +// Prepares a weapon for Upgrade and initiates Player +// animation. +// +void(entity pap, entity buyer) PAP_UpgradeWeapon = +{ + entity tempe; + + tempe = self; + self = buyer; + addmoney (self, -pap.cost, 0); + + // Spawn Upgrade Spark if permitted + if (!(pap.spawnflags & PAP_SPAWNFLAG_NOSPARK)) + SpawnSpark(pap.box2, 3.5); + + // Machine is using the flag, so spawn it in. + if ((pap.spawnflags & PAP_SPAWNFLAG_USEFLAG)) { + pap.boxweapon.think = PAP_FlagMoveUp; + pap.boxweapon.nextthink = time + 0.05; + } + + // Give a nice blue glow and play upgrade sound + Light_Cyan(pap, false); + sound(pap, CHAN_ITEM, pap.oldmodel, 0.8, 1); + + // Mapper-provided musical sting. + if (pap.powerup_vo) + sound(pap, CHAN_AUTO, pap.powerup_vo, 1, ATTN_IDLE); + + // + // Spawn and prepare the floating Weapon + // + entity floating_weapon = spawn(); + string floating_weapon_model = GetWeaponModel(self.weapon, 1); + setmodel(floating_weapon, floating_weapon_model); + setsize(floating_weapon, '0 0 0', '0 0 0'); + floating_weapon.movetype = MOVETYPE_NOCLIP; + floating_weapon.solid = SOLID_NOT; + + // Send the model into the Machine + makevectors(pap.angles); + floating_weapon.origin = pap.oldorigin; + setorigin(floating_weapon, floating_weapon.origin + v_forward * pap.oldz); + floating_weapon.angles = pap.angles; + floating_weapon.angles_y = 90 + pap.angles_y; + floating_weapon.velocity = v_forward*-pap.oldz; + floating_weapon.think = PAP_WeaponStopMoving; + floating_weapon.nextthink = time + 1; + + // Link the Weapon with the Machine + floating_weapon.usedent = pap; + pap.usedent = self; + pap.goaldummy = floating_weapon; + + // Upgrade Timer + pap.think = PAP_SendWeaponOut; + pap.nextthink = time + 3.5; + + // Play Player's view model animation and sound. + self.fire_delay = self.reload_delay = 2.0 + time; + sound(self,CHAN_WEAPON,"sounds/machines/papsound.wav",1,ATTN_NORM); + + pap.weapon = self.weapon; + + Weapon_RemoveWeapon(0); + W_HideCrosshair(self); + Set_W_Frame (0, 39, 2.0, 0, 0, W_PutOutHack, "models/machines/v_pap.mdl", true, S_BOTH); + self.weapon2model = ""; + UpdateV2model(self.weapon2model, 0); + +#ifndef FTE + + self.Weapon_Name = ""; + +#endif // FTE + + self = tempe; + + // Notify that the Machine is currently Upgrading. + self.papState = 1; +}; + +// +// PAP_Touch() +// Touch/Interaction function for Clients + Pack-A-Punch. +// +void() PAP_Touch = +{ + + if (other.classname != "player" || other.downed || !PlayerIsLooking(other, self)) { + return; + } + + if (other.reload_delay > time || other.reload_delay2 > time || + other.fire_delay > time || other.fire_delay2 > time) + return; + + // Power is not turned on. + if (self.requirespower == true && !isPowerOn) { + useprint (other, 8, 0, 0); + return; + } + + // Purchasing Machine + putting Weapon in + if (!self.papState) { + if (IsPapWeapon(other.weapon) == 1) { + return; + } + + useprint (other, 12, self.cost, 5); + + // Player has enough points, begin Upgrade process + if (other.points >= self.cost && other.button7 && other.weapon) { + PAP_UpgradeWeapon(self, other); + } + // They're broke! Notify. + else if (other.button7 && other.weapon && !other.semiuse) { + other.semiuse = true; + centerprint (other, STR_NOTENOUGHPOINTS); + sound(other, 0, "sounds/misc/denybuy.wav", 1, 1); + } + } + + // Claiming upgraded Weapon + else if (self.papState == 2) { + +#ifndef FTE + + other.Weapon_Name_Touch = GetWeaponName(EqualPapWeapon(self.weapon)); + +#endif // FTE + + useprint (other, 7, 0, EqualPapWeapon(self.weapon)); + + if (other.button7) { + entity tempe = self; + self = other; + Weapon_GiveWeapon(EqualPapWeapon(tempe.weapon), 0, 0); + self = tempe; + + // Prep Pack-A-Punch to Upgrade again + self.think = PAP_Reset; + self.nextthink = time + 0.1; + } + } +}; + +// +// PAP_RotateRoller() +// Think function for the Rollers - rotate indefinitely. +// +void() PAP_Click = +{ + if (!self.active_door.papState) + sound(self, CHAN_ITEM, "sounds/machines/packapunch/gear_shift.wav", 1, 1); + self.nextthink = time + 0.75; +}; + +// +// PAP_TurnOn() +// Turns on the Pack-A-Punch machine. +// +void() PAP_TurnOn = +{ + if (self.active_door != world) { + self.active_door.movetype = MOVETYPE_NOCLIP; + self.active_door.avelocity = '-200 0 0'; + self.active_door.think = PAP_Click; + self.active_door.nextthink = time + 0.75; + } +}; + +// +// PAP_Initialize() +// Turns the Pack-A-Punch On if the Power is on. +// +void() PAP_Initalize = +{ + // Start on if there's no Power Switch + entity tempe = find (world, classname, "power_switch"); + if (tempe) self.requirespower = true; + else PAP_TurnOn(); +}; + +// +// perk_pap() +// QuakeC Spawn Function for Pack-A-Punch Machine +// +void() perk_pap = +{ + // + // Set Default Stats for Compatibility + // + + // Model + if (!self.model) { + self.model = "models/machines/quake_scale/pap.mdl"; + } + + // Floating Weapon Offset + if (!self.oldorigin) { + self.oldorigin = '0 0 -1'; + } + + // Floating model forward velocity + if (!self.oldz) { + self.oldz = 20; + } + + // Roller Model + if (!self.weapon2model) { + self.weapon2model = "models/machines/hl_scale/packapunch/p_roller.mdl"; + } + + // Roller Offset + if (!self.box1) { + self.box1 = '7.5 0.1 6.0'; + } + + // Flag Model + if (!self.door_model_name) { + self.door_model_name = "models/machines/hl_scale/packapunch/p_flag.mdl"; + } + + // Flag Offset + if (!self.box3) { + self.box3 = '-18 -31.7 18'; + } + + // Spark Offset + if (!self.box2) { + self.box2 = '8 0 2'; + } + + // Cost + if (!self.cost) { + self.cost = 5000; + } + + // Upgrade Sound + if (!self.oldmodel) { + self.oldmodel = "sounds/machines/packapunch/upgrade.wav"; + } + + // Precaches + // FIXME: Don't hardcode weapon precaches here. + precache_extra(W_BIATCH); + precache_extra(W_SNUFF); + + precache_model (self.model); + precache_model ("models/machines/v_pap.mdl"); + + if (!(self.spawnflags & PAP_SPAWNFLAG_NOSPARK)) + precache_model("models/sprites/lightning.spr"); + + precache_sound(self.oldmodel); + + if (self.powerup_vo) + precache_sound(self.powerup_vo); + + precache_sound ("sounds/machines/papsound.wav"); + precache_sound("sounds/weapons/papfire.wav"); + precache_sound("sounds/machines/packapunch/gear_shift.wav"); + precache_sound("sounds/machines/packapunch/tick.wav"); + + // Lock its Pitch and Roll (sorry!) + self.angles_x = 0; + self.angles_z = 0; + + // Spawn the Roller + if (self.spawnflags & PAP_SPAWNFLAG_USEROLLER) { + precache_model(self.weapon2model); + entity roller = spawn(); + setmodel(roller, self.weapon2model); + makevectors(self.angles); + roller.origin = self.origin; + roller.origin += v_right * self.box1_y; + roller.origin += v_forward * self.box1_x; + roller.origin += v_up * self.box1_z; + roller.angles = self.angles; + setorigin(roller, roller.origin); + self.active_door = roller; + roller.active_door = self; + } + + // Spawn the Flag + if (self.spawnflags & PAP_SPAWNFLAG_USEFLAG) { + precache_model(self.door_model_name); + entity flag = spawn(); + setmodel(flag, self.door_model_name); + makevectors(self.angles); + flag.origin = self.origin; + flag.origin += v_right * self.box3_y; + flag.origin += v_forward * self.box3_x; + flag.origin += v_up * self.box3_z; + flag.angles = self.angles; + setorigin(flag, flag.origin); + flag.movetype = MOVETYPE_NOCLIP; + self.boxweapon = flag; + + // Start down + flag.angles_z = 180; + } + + vector tempv; + + // Calculate the Spark offset if permitted + if (!(self.spawnflags & PAP_SPAWNFLAG_NOSPARK)) { + tempv = self.origin; + makevectors(self.angles); + tempv += v_right * self.box2_y; + tempv += v_forward * self.box2_x; + tempv += v_up * self.box2_z; + self.box2 = tempv; + } + + // Calculate the floating weapon offset + tempv = self.origin; + makevectors(self.angles); + tempv += v_right * self.oldorigin_y; + tempv += v_forward * self.oldorigin_x; + tempv += v_up * self.oldorigin_z; + self.oldorigin = tempv; + + self.classname = "perk_pap"; + self.touch = PAP_Touch; + self.solid = SOLID_TRIGGER; + setorigin(self, self.origin); + setmodel(self, self.model); + setsize(self, '-44 -44 -24', '44 44 64'); + + self.think = PAP_Initalize; + self.nextthink = time + 0.2; +}; diff --git a/source/server/entities/wall_weapon.qc b/source/server/entities/wall_weapon.qc index 4cb7f5e..dab96e0 100644 --- a/source/server/entities/wall_weapon.qc +++ b/source/server/entities/wall_weapon.qc @@ -26,6 +26,8 @@ */ +void() W_PlayTakeOut; + // ================================= // Wall Chalk Functionality // =================================