From 19ae55654c7c2f100409a945ca9ef157c08b668c Mon Sep 17 00:00:00 2001 From: moto Date: Mon, 24 Oct 2022 08:44:41 -0400 Subject: [PATCH] Server: Revamp Purchase of Wall Weapon Ammo Adds some utility functions to make grabbing specific pieces of weapon information in any of a player's slots easier. Fixes some mulekick bugs as a side effect. Fixes https://github.com/nzp-team/nzportable/issues/52. --- source/server/clientfuncs.qc | 117 +++++++++++++++++++------ source/server/entities/map_entities.qc | 78 ++++++++++------- source/shared/weapon_defines.qc | 6 +- 3 files changed, 137 insertions(+), 64 deletions(-) diff --git a/source/server/clientfuncs.qc b/source/server/clientfuncs.qc index a7fc61d..cb41381 100644 --- a/source/server/clientfuncs.qc +++ b/source/server/clientfuncs.qc @@ -3,7 +3,7 @@ used to communicate between server and client - Copyright (C) 2021 NZ:P Team + Copyright (C) 2021-2022 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 @@ -99,7 +99,7 @@ void NotifyNewRound(float to) { WriteByte(MSG_MULTICAST, EVENT_NEWROUND); WriteByte(MSG_MULTICAST, to); multicast('0 0 0', MULTICAST_ALL); - + #endif #endif #endif @@ -115,24 +115,24 @@ void SetRound(entity client, float to) { WriteByte(MSG_MULTICAST, to); msg_entity = client; multicast('0 0 0', MULTICAST_ONE); - + #endif #endif #endif } -void SetPerk(entity client, float to) +void SetPerk(entity client, float to) { #ifndef PSP #ifndef NX #ifndef CTR - + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); WriteByte(MSG_MULTICAST, EVENT_PERK); WriteLong(MSG_MULTICAST, to); msg_entity = client; multicast('0 0 0', MULTICAST_ONE); - + #endif #endif #endif @@ -143,7 +143,7 @@ void(float to) SwitchWeapon = #ifndef PSP #ifndef NX #ifndef CTR - + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); WriteByte(MSG_MULTICAST, EVENT_WEAPONCHANGE); WriteByte(MSG_MULTICAST, to); @@ -152,7 +152,7 @@ void(float to) SwitchWeapon = // hotfix for weapon2models not reseting self.weapon2model = GetWeapon2Model(to); - + #endif #endif #endif @@ -170,7 +170,7 @@ void(string to, float skin) UpdateVmodel = WriteByte(MSG_MULTICAST, skin); msg_entity = self; multicast('0 0 0', MULTICAST_ONE); - + #endif #endif #endif @@ -188,7 +188,7 @@ void(string to, float skin) UpdateV2model = WriteByte(MSG_MULTICAST, skin); msg_entity = self; multicast('0 0 0', MULTICAST_ONE); - #endif + #endif #endif #endif } @@ -203,7 +203,7 @@ void(float broadcast_time, float type) BroadcastMessage = WriteByte(MSG_MULTICAST, broadcast_time); WriteByte(MSG_MULTICAST, type); multicast('0 0 0', MULTICAST_ALL); - + #endif #endif #endif @@ -235,7 +235,7 @@ void(float playernum, float points, float am, float kills, string name, entity p WriteString(MSG_MULTICAST, name); multicast('0 0 0', MULTICAST_ALL); } - + #endif #endif #endif @@ -259,7 +259,7 @@ void(float count) UpdatePlayerCount = { #endif } -void(float newtime, float newtype, entity change) PromptLevelChange = +void(float newtime, float newtype, entity change) PromptLevelChange = { #ifndef PSP #ifndef NX @@ -271,14 +271,14 @@ void(float newtime, float newtype, entity change) PromptLevelChange = WriteByte(MSG_MULTICAST, newtype); msg_entity = change; multicast('0 0 0', MULTICAST_ONE); - + #endif #endif #endif } -void(entity who) UpdatePunchangle = -{ +void(entity who) UpdatePunchangle = +{ // naievil -- shit logic lol...but result looks clean as fuck... #ifndef PSP @@ -291,9 +291,9 @@ void(entity who) UpdatePunchangle = WriteCoord(MSG_MULTICAST, who.punchangle_z); msg_entity = who; multicast('0 0 0', MULTICAST_ONE); - + vector tempv = who.punchangle; - + if (fabs(who.punchangle_x) > 0.01) { if (who.punchangle_x >= 0.05*tempv_x) who.punchangle_x -= 0.05*tempv_x; @@ -301,29 +301,29 @@ void(entity who) UpdatePunchangle = who.punchangle_x -= 0.05*tempv_x; else who.punchangle_x = 0; - } else + } else who.punchangle_x = 0; - + if (fabs(who.punchangle_y) > 0.01) { if (who.punchangle_y >= 0.05*tempv_y) who.punchangle_y -= 0.05*tempv_y; else if (who.punchangle_y <= -0.05*tempv_y) who.punchangle_y -= 0.05*tempv_y; - else + else who.punchangle_y = 0; - } else + } else who.punchangle_y = 0; - + if (fabs(who.punchangle_z) > 0.01) { if (who.punchangle_z >= 0.05*tempv_z) who.punchangle_z -= 0.05*tempv_z; else if (who.punchangle_z <= -0.05*tempv_z) who.punchangle_z -= 0.05*tempv_z; - else + else who.punchangle_z = 0; - } else + } else who.punchangle_z = 0; - + #endif #endif #endif @@ -579,6 +579,69 @@ void(entity person, float expamt, float doublepoint) addmoney = total_powerup_points += expamt; person.points += expamt; - + UpdatePlayerPoints(person.playernum, person.points, expamt, person.kills, person.netname, person); }; + +// +// Util_GetPlayerAmmoInSlot(person, slot) +// Returns the reserve ammo the player has in a weapon slot. +// +float(entity person, float slot) Util_GetPlayerAmmoInSlot = +{ + switch(slot) { + case 1: return person.currentammo; + case 2: return person.secondaryammo; + case 3: return person.thirdammo; + default: return 0; + } +} + +// +// Util_SetPlayerAmmoInSlot(person, slot, ammo) +// Sets the player's reserve ammo in a slot to param3. +// +void(entity person, float slot, float ammo) Util_SetPlayerAmmoInSlot = +{ + switch(slot) { + case 1: person.currentammo = ammo; + case 2: person.secondaryammo = ammo; + case 3: person.thirdammo = ammo; + default: return; + } +}; + +// +// Util_PlayerHasWeapon(peron, comparison, include_pap) +// Checks to see if the Player is holding a weapon in any +// of their three slots. `include_pap` dictates whether to +// consider Pack-A-Punch'd varients. Returns 1, 2, 3 depending +// on the slot the weapon is contained in. +// +float(entity person, float comparison, float include_pap) Util_PlayerHasWeapon = +{ + // Storage. + float first, second, third; + + // If we're including pap'd weapons, just convert the weapon set to the base + // ones to save on comparison checks. + if (include_pap == true) { + first = EqualNonPapWeapon(person.weapon); + second = EqualNonPapWeapon(person.secondaryweapon); + third = EqualNonPapWeapon(person.thirdweapon); + } else { + first = person.weapon; + second = person.secondaryweapon; + third = person.thirdweapon; + } + + // Now do the comparisons + if (first == comparison) + return 1; + if (second == comparison) + return 2; + if (third == comparison) + return 3; + + return 0; +}; diff --git a/source/server/entities/map_entities.qc b/source/server/entities/map_entities.qc index 684ac9d..26bb723 100644 --- a/source/server/entities/map_entities.qc +++ b/source/server/entities/map_entities.qc @@ -254,55 +254,64 @@ void () buy_weapon_touch = float startframe,endframe; string modelname; - if (other.classname != "player" || other.downed || other.isBuying/* || !isFacing(other, self)*/) { + if (other.classname != "player" || other.downed || other.isBuying) { return; } - + #ifndef PC other.Weapon_Name_Touch = GetWeaponName(self.weapon); #endif - - if (self.weapon == other.weapon || self.weapon == other.secondaryweapon - || self.weapon == EqualNonPapWeapon(other.weapon) - || self.weapon == EqualNonPapWeapon(other.secondaryweapon)) { - if (self.weapon == EqualNonPapWeapon(other.secondaryweapon) - || self.weapon == EqualNonPapWeapon(other.weapon)) - useprint (other, 3, 4500, other.weapon); - else - useprint (other, 3, self.cost2, self.weapon); + float slot; + + // Player has this weapon in any of their slots, PaP'd or not. + if ((slot = Util_PlayerHasWeapon(other, self.weapon, true)) != 0) { + float is_pap = true; + + + // But the utility function returns the same value if we are NOT PaP'd + if (Util_PlayerHasWeapon(other, self.weapon, false) == slot) + is_pap = false; + + // Set the cost and weapon value (for useprint). + float wcost = (is_pap) ? 4500 : self.cost2; + float wep = (is_pap) ? EqualPapWeapon(self.weapon) : self.weapon; + + useprint(other, 3, wcost, wep); if (!other.button7 || other.semiuse || other.isBuying) { return; } - if ((self.weapon == other.weapon && other.currentammo >= getWeaponAmmo(self.weapon)) - ||(self.weapon == other.secondaryweapon && other.secondaryammo >= getWeaponAmmo(self.weapon))) { - return; - } + + // Store current Ammo value. + float ammo = Util_GetPlayerAmmoInSlot(other, slot); + + // Max carrying capacity of the wall weapon + float wall_ammo = (is_pap) ? getWeaponAmmo(EqualPapWeapon(self.weapon)) : getWeaponAmmo(self.weapon); + + // Weapon is already full. Abort. + if (ammo >= wall_ammo) + return; other.semiuse = true; - if ((other.points < self.cost2 && !IsPapWeapon(other.weapon)) || (other.points < 4500 && IsPapWeapon(other.weapon))) { + + // Player doesn't have enough points. Abort. + if (other.points < wcost) { centerprint(other, STR_NOTENOUGHPOINTS); return; } other.ach_tracker_coll++; - if (self.weapon == other.weapon || (self.weapon == EqualNonPapWeapon(other.weapon))) { - other.currentammo = getWeaponAmmo(self.weapon); - } else if (self.weapon == other.secondaryweapon || (self.weapon == EqualNonPapWeapon(other.secondaryweapon)) ) { - other.secondaryammo = getWeaponAmmo(self.weapon); - } - + // Set the weapon's ammo to the max capacity. + Util_SetPlayerAmmoInSlot(other, slot, wall_ammo); sound(other, 0,"sounds/misc/ching.wav", 1, 1); other.reload_delay = 0; - - if (!IsPapWeapon(other.weapon)) - addmoney(other, -1*self.cost2, 0); - else - addmoney(other, -1*4500, 0); - + + // Subtract the cost from player points. + addmoney(other, wcost*-1, 0); + if (self.enemy) { oldent = self; self = self.enemy; @@ -402,7 +411,7 @@ void () buy_weapon_touch = else { entity tempe; - + //centerprint(other, self.message); useprint (other, 4, self.cost, self.weapon); @@ -416,6 +425,7 @@ void () buy_weapon_touch = return; } + other.semiuse = true; other.ach_tracker_coll++; if (other.weapon && !other.secondaryweapon) { @@ -458,7 +468,7 @@ void () buy_weapon_touch = other.currentmag = 0; other.weapon = 0; } - + sound(other, 0,"sounds/misc/ching.wav", 1, 1); other.reload_delay = 0; addmoney(other, -1*self.cost, 0); @@ -469,7 +479,7 @@ void () buy_weapon_touch = self = oldent; } other.weapon = self.weapon; - + other.currentammo = getWeaponAmmo(self.weapon); other.currentmag = getWeaponMag(self.weapon); tempe = self; @@ -477,20 +487,20 @@ void () buy_weapon_touch = startframe = GetFrame(self.weapon,TAKE_OUT_START); endframe = GetFrame(self.weapon,TAKE_OUT_END); modelname = GetWeaponModel(self.weapon, 0); - + if (self.weapon != W_KAR_SCOPE && self.weapon != W_HEADCRACKER && !IsDualWeapon(self.weapon)) { self.weapon2model = ""; } SwitchWeapon(self.weapon); Set_W_Frame (startframe, endframe, 0, 0, 0, SUB_Null, modelname, false, S_BOTH);//FIXME - + #ifndef PC self.Flash_Offset = GetWeaponFlash_Offset(self.weapon); self.Flash_Size = GetWeaponFlash_Size(self.weapon); self.Weapon_Name = GetWeaponName(self.weapon); #endif - + self = tempe; } diff --git a/source/shared/weapon_defines.qc b/source/shared/weapon_defines.qc index c482e1c..3bf92b1 100644 --- a/source/shared/weapon_defines.qc +++ b/source/shared/weapon_defines.qc @@ -3,7 +3,7 @@ all weapon stats are stored here - Copyright (C) 2021 NZ:P Team + Copyright (C) 2021-2022 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 @@ -2622,7 +2622,7 @@ float(float wep) GetWepSkin = { } -float(float wep) EqualNonPapWeapon = +loat(float wep) EqualNonPapWeapon = { switch (wep) { @@ -2683,7 +2683,7 @@ float(float wep) EqualNonPapWeapon = case W_FIW: return W_M2; default: - return 0; + return wep; } } float(float wep) EqualPapWeapon =