Skip to content

Commit

Permalink
Add Shotgun powerup (#46)
Browse files Browse the repository at this point in the history
* Add Shotgun powerup

* Style

* Also csluafile the client-only file
  • Loading branch information
legokidlogan authored Dec 13, 2024
1 parent cbcbec1 commit 75eec44
Show file tree
Hide file tree
Showing 11 changed files with 290 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lua/autorun/sh_powerups_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ end
require( "logger" )

CFCPowerups = {
Logger = Logger( "CFC Powerups" )
Logger = Logger( "CFC Powerups" ),
SharedHandlers = {}, -- For powerup handler classes that carry duplicate code between server and client relams
}

if SERVER then
Expand Down
1 change: 1 addition & 0 deletions lua/entities/powerup_shotgun/cl_init.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include "shared.lua"
7 changes: 7 additions & 0 deletions lua/entities/powerup_shotgun/init.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
AddCSLuaFile "cl_init.lua"
AddCSLuaFile "shared.lua"
include "shared.lua"

ENT.Base = "base_cfc_powerup"
ENT.Powerup = "powerup_shotgun"
ENT.Color = Color 75, 65, 75
9 changes: 9 additions & 0 deletions lua/entities/powerup_shotgun/shared.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ENT.Base = "base_cfc_powerup"

ENT.Type = "anim"
ENT.PrintName = "Shotgun Powerup"
ENT.Purpose = "All guns shoot multiple bullets"
ENT.Category = "Powerups"

ENT.Spawnable = true
ENT.AdminOnly = true
32 changes: 32 additions & 0 deletions lua/powerups/client/shotgun.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import ShotgunPowerupHandler from CFCPowerups.SharedHandlers

shotguns = {}

removeShotgun = (ownerSteamID64) ->
shotgun = shotguns[ownerSteamID64]
return unless shotgun

shotgun\Remove!
shotguns[ownerSteamID64] = nil

net.Receive "CFC_Powerups-Shotgun-Start", ->
ownerSteamID64 = net.ReadString!
singleBulletsMin = net.ReadUInt 7
singleBulletsMax = net.ReadUInt 7
singleDamageMult = net.ReadFloat!
singleSpreadMult = net.ReadFloat!
singleSpreadAdd = net.ReadFloat!
multiBulletsMult = net.ReadFloat!
multiDamageMult = net.ReadFloat!

removeShotgun ownerSteamID64 -- Just in case

owner = player.GetBySteamID64 ownerSteamID64
return unless IsValid owner

shotguns[ownerSteamID64] = ShotgunPowerupHandler owner, singleBulletsMin, singleBulletsMax, singleDamageMult, singleSpreadMult, singleSpreadAdd, multiBulletsMult, multiDamageMult

net.Receive "CFC_Powerups-Shotgun-Stop", ->
ownerSteamID64 = net.ReadString!

removeShotgun ownerSteamID64
33 changes: 33 additions & 0 deletions lua/powerups/config/sv_config.moon
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,39 @@
helpText: "What sound should play when the bolt acquires a target?"
-- =======================================================================

-- Shotgun ================================================================
"cfc_powerups_shotgun_duration":
default: 300
helpText: "How long does the Shotgun powerup last, in seconds"

"cfc_powerups_shotgun_single_bullets_min":
default: 6
helpText: "Minimum number of bullets for single-bullet weapons"

"cfc_powerups_shotgun_single_bullets_max":
default: 8
helpText: "Maximum number of bullets for single-bullet weapons"

"cfc_powerups_shotgun_single_damage_multiplier":
default: 0.5
helpText: "Damage multiplier for single-bullet weapons"

"cfc_powerups_shotgun_single_spread_multiplier":
default: 1.25
helpText: "Spread multiplier for single-bullet weapons"

"cfc_powerups_shotgun_single_spread_add":
default: 0.04
helpText: "Spread additive for single-bullet weapons"

"cfc_powerups_shotgun_multi_bullets_multiplier":
default: 1.5
helpText: "Multiplier against the number of bullets for multi-bullet weapons"

"cfc_powerups_shotgun_multi_damage_multiplier":
default: 1.5
helpText: "Damage multiplier for multi-bullet weapons"

-- Phoenix =============================================================
"cfc_powerups_phoenix_uses":
default: 1
Expand Down
3 changes: 3 additions & 0 deletions lua/powerups/loaders/cl_powerups_init.moon
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
include "powerups/shared/shotgun.lua"

include "powerups/client/halos.lua"
include "powerups/client/flux_shield.lua"
include "powerups/client/thorns.lua"
include "powerups/client/shotgun.lua"
include "powerups/client/curse.lua"
6 changes: 6 additions & 0 deletions lua/powerups/loaders/sv_powerups_init.moon
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ include "utils/server/sv_config_manager.lua"
include "utils/server/sv_powerups_manager.lua"
include "utils/server/sv_powerups_spawner.lua"

include "powerups/shared/shotgun.lua"

include "powerups/server/base.lua"
include "powerups/server/cluster_combine_ball.lua"
include "powerups/server/regen.lua"
Expand All @@ -15,13 +17,17 @@ include "powerups/server/grenadier.lua"
include "powerups/server/flux_shield.lua"
include "powerups/server/thorns.lua"
include "powerups/server/magnetic_crossbow.lua"
include "powerups/server/shotgun.lua"
include "powerups/server/phoenix.lua"
include "powerups/server/super_speed.lua"
include "powerups/server/curse.lua"

AddCSLuaFile "powerups/shared/shotgun.lua"

AddCSLuaFile "powerups/client/halos.lua"
AddCSLuaFile "powerups/client/flux_shield.lua"
AddCSLuaFile "powerups/client/thorns.lua"
AddCSLuaFile "powerups/client/shotgun.lua"
AddCSLuaFile "powerups/client/curse.lua"

resource.AddWorkshop "3114946264"
Expand Down
75 changes: 75 additions & 0 deletions lua/powerups/server/shotgun.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{get: getConf} = CFCPowerups.Config

import ShotgunPowerupHandler from CFCPowerups.SharedHandlers

util.AddNetworkString "CFC_Powerups-Shotgun-Start"
util.AddNetworkString "CFC_Powerups-Shotgun-Stop"

export ShotgunPowerup
class ShotgunPowerup extends BasePowerup
@powerupID: "powerup_shotgun"

@powerupWeights:
tier1: 1
tier2: 1
tier3: 1
tier4: 1

new: (ply) =>
super ply

@ownerSteamID64 = @owner\SteamID64!

@duration = getConf "shotgun_duration"
@singleBulletsMin = getConf "shotgun_single_bullets_min"
@singleBulletsMax = getConf "shotgun_single_bullets_max"
@singleDamageMult = getConf "shotgun_single_damage_multiplier"
@singleSpreadMult = getConf "shotgun_single_spread_multiplier"
@singleSpreadAdd = getConf "shotgun_single_spread_add"
@multiBulletsMult = getConf "shotgun_multi_bullets_multiplier"
@multiDamageMult = getConf "shotgun_multi_damage_multiplier"

@timerName = "CFC-Powerups_Shotgun-#{@ownerSteamID64}"
@handler = ShotgunPowerupHandler ply, @singleBulletsMin, @singleBulletsMax, @singleDamageMult, @singleSpreadMult, @singleSpreadAdd, @multiBulletsMult, @multiDamageMult

@ApplyEffect!

ApplyEffect: =>
super self

timer.Create @timerName, @duration, 1, -> @Remove!

-- Need to network to all clients so they can predict the new bullets correctly.
-- However, this isn't using NW or NW2, so players who join after won't see it correctly.
-- But that is preferable to using NW/NW2 slots, a permanent EFB hook listener, and needing to re-check the convars on client.
net.Start "CFC_Powerups-Shotgun-Start"
net.WriteString @ownerSteamID64
net.WriteUInt @singleBulletsMin, 7
net.WriteUInt @singleBulletsMax, 7
net.WriteFloat @singleDamageMult
net.WriteFloat @singleSpreadMult
net.WriteFloat @singleSpreadAdd
net.WriteFloat @multiBulletsMult
net.WriteFloat @multiDamageMult
net.Broadcast!

@owner\ChatPrint "You've gained #{@duration} seconds of the Shotgun powerup"

Remove: =>
super self

timer.Remove @timerName

@handler\Remove!
@handler = nil

net.Start "CFC_Powerups-Shotgun-Stop"
net.WriteString @ownerSteamID64
net.Broadcast!

return unless IsValid @owner

@owner\ChatPrint "You've lost the Shotgun powerup"

-- TODO: Should the PowerupManager do this?
@owner.Powerups[@@powerupID] = nil
122 changes: 122 additions & 0 deletions lua/powerups/shared/shotgun.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@

-- Some addons shoot multiple separate bullets instead of using the Num param.
-- Put them here so they get treated properly, with the value being a function or string to get the intended bullet count.
FORCE_MULTI_CLASSES = { -- Direct class lookup

}
FORCE_MULTI_CLASS_STARTS = { -- Anything that starts with these strings
"cw_": "Shots"
}

forceMultiClassCache = {}
lastCommandNum = nil
commandSeedIncr = 0

isForcedMulti = (wep) ->
wepClass = wep\GetClass!
cached = forceMultiClassCache[wepClass]
return cached if cached ~= nil

getter = FORCE_MULTI_CLASSES[wepClass]

if not getter
for start, newGetter in *FORCE_MULTI_CLASS_STARTS
continue unless string.StartsWith wepClass, start

getter = newGetter
break

if not getter
forceMultiClassCache[wepClass] = false
return false

-- Need to also check the gun's listed bullet count, to see if it actually shoots multiple bullets or not.
num = ( type getter == "function" ) and ( getter wep ) or wep[getter] or 1
forcedMulti = num > 1

forceMultiClassCache[wepClass] = forcedMulti
return forcedMulti

-- Handles the shared logic of modifying bullets for the shotgun powerup.
class ShotgunPowerupHandler
new: (owner, singleBulletsMin, singleBulletsMax, singleDamageMult, singleSpreadMult, singleSpreadAdd, multiBulletsMult, multiDamageMult) =>
@owner = owner
@singleBulletsMin = singleBulletsMin
@singleBulletsMax = singleBulletsMax
@singleDamageMult = singleDamageMult
@singleSpreadMult = singleSpreadMult
@singleSpreadAdd = singleSpreadAdd
@multiBulletsMult = multiBulletsMult
@multiDamageMult = multiDamageMult

@ownerSteamID64 = @owner\SteamID64!
@hookName = "CFC-Powerups_Shotgun-#{@ownerSteamID64}"

@ApplyEffect!

BulletWatcher: =>
(ent, bullet) ->
return unless ent == @owner

num = bullet.Num

-- Multi-bullet gun
if num > 1
bullet.Num = math.ceil bullet.Num * @multiBulletsMult
bullet.Damage = bullet.Damage * @multiDamageMult
return

wep = ent\GetActiveWeapon!
return unless IsValid wep -- Shooting bullets with your mind? Nonsense!

commandNum = lastCommandNum

-- Bullets on players should always be fired in a predicted hook, but for just in case...
if GetPredictionPlayer! == ent
commandNum = ent\GetCurrentCommand!\CommandNumber!

-- If multiple bullets are fired in the same command (i.e. with force-multi weapons), increment the seed
if commandNum == lastCommandNum
commandSeedIncr = commandSeedIncr + 1
else
lastCommandNum = commandNum
commandSeedIncr = 0
wep\EmitSound "weapons/shotgun/shotgun_fire6.wav", 75, 100, 1, CHAN_WEAPON -- Play a sound to make the powerup more noticeable, but only once per command

seed = ent\EntIndex! .. commandNum .. commandSeedIncr

-- Single-bullet gun
if not isForcedMulti wep
bullet.Num = util.SharedRandom seed, @singleBulletsMin, @singleBulletsMax
bullet.Damage = bullet.Damage * @singleDamageMult

spread = bullet.Spread
spreadMult = @singleSpreadMult
spreadAdd = @singleSpreadAdd

spread.x = spread.x * spreadMult + spreadAdd
spread.y = spread.y * spreadMult + spreadAdd

return

-- Forced-multi gun
bullet.Damage = bullet.Damage * @multiDamageMult

multiBulletsMult = @multiBulletsMult
newNum = math.floor multiBulletsMult
leftover = multiBulletsMult - newNum

if leftover > 0
-- Leftover is used as a chance to add another bullet
if (util.SharedRandom seed, 0, 1) < leftover
newNum = newNum + 1

bullet.Num = newNum

ApplyEffect: =>
hook.Add "EntityFireBullets", @hookName, @BulletWatcher!

Remove: =>
hook.Remove "EntityFireBullets", @hookName

CFCPowerups.SharedHandlers.ShotgunPowerupHandler = ShotgunPowerupHandler
Binary file added materials/entities/powerup_shotgun.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 75eec44

Please sign in to comment.