(TTT) Make a T weapon limited on the whole team

So, I have a defib weapon for T’s that turns an innocent into a Traitor.

I think it’s a bit too OP and I want to limit it for the whole team.

Anyway to do that?

EDIT: Sorry forgot to post the weapon code.

here it is:




local STATE_NONE, STATE_PROGRESS, STATE_ERROR = 0, 1, 2
local color_red = Color(255, 0, 0)

SWEP.Base = "weapon_tttbase"

SWEP.HoldType = "slam"
SWEP.ViewModel = Model("models/weapons/v_c4.mdl")
SWEP.WorldModel = Model("models/weapons/w_c4.mdl")

--- TTT Vars

SWEP.Kind = WEAPON_EQUIP2
SWEP.AutoSpawnable = false
SWEP.CanBuy = {ROLE_TRAITOR}
SWEP.LimitedStock = true

if CLIENT then
  SWEP.PrintName = "Defibrillator"
  SWEP.Slot = 7

  SWEP.Icon = "windfrontier/wf_defibrillator"

  SWEP.EquipMenuData = {
    type = "item_weapon",
    name = "Defribrillator",
    desc = "Resurrect dead teammates with this one! If you resurrect a non-traitor, they'll come back as a traitor!"
  }

  surface.CreateFont("DefibText", {
    font = "Tahoma",
    size = 13,
    weight = 700,
    shadow = true
  })

  function SWEP:DrawHUD()
    local state = self:GetDefibState()
    local scrW, scrH = ScrW(), ScrH()
    local progress = 1
    local outlineCol, progressCol, progressText = color_white, color_white, ""

    if state == STATE_PROGRESS then
      local startTime, endTime = self:GetDefibStartTime(), self:GetDefibStartTime() + 5

      progress = math.TimeFraction(startTime, endTime, CurTime())

      if progress <= 0 then
        return
      end

      outlineCol = Color(0, 100, 0)
      progressCol = Color(0, 255, 0, (math.abs(math.sin(RealTime() * 3)) * 100) + 20)
      progressText = self:GetStateText() or "DEFIBRILLATING"
    elseif state == STATE_ERROR then
      outlineCol = color_red
      progressCol = Color(255, 0, 0, math.abs(math.sin(RealTime() * 15)) * 255)
      progressText = self:GetStateText() or ""
    else
      return
    end

    progress = math.Clamp(progress, 0, 1)

    surface.SetDrawColor(outlineCol)
    surface.DrawOutlinedRect(scrW / 2 - (200 / 2) - 1, scrH / 2 + 10 - 1, 202, 16)

    surface.SetDrawColor(progressCol)
    surface.DrawRect(scrW / 2  - (200 / 2), scrH / 2 + 10, 200 * progress, 14)

    surface.SetFont("DefibText")
    local textW, textH = surface.GetTextSize(progressText)

    surface.SetTextPos(scrW / 2 - 100 + 2, scrH / 2 - 20 + textH)
    surface.SetTextColor(color_white)
    surface.DrawText(progressText)
  end
end

function SWEP:SetupDataTables()
  self:NetworkVar("Int", 0, "DefibState")
  self:NetworkVar("Float", 1, "DefibStartTime")

  self:NetworkVar("String", 0, "StateText")
end

function SWEP:Initialize()
  self:SetDefibState(STATE_NONE)
  self:SetDefibStartTime(0)
end

function SWEP:Deploy()
  self:SetDefibState(STATE_NONE)
  self:SetDefibStartTime(0)

  return true
end

function SWEP:Holster()
  self:SetDefibState(STATE_NONE)
  self:SetDefibStartTime(0)

  return true
end


function SWEP:PrimaryAttack()
  if CLIENT then return end

  local tr = util.TraceLine({
    start = self.Owner:EyePos(),
    endpos = self.Owner:EyePos() + self.Owner:GetAimVector() * 80,
    filter = self.Owner
  })

  if IsValid(tr.Entity) and tr.Entity:GetClass() == "prop_ragdoll" then
    if not tr.Entity.uqid then
      self:FireError("FAILURE - SUBJECT BRAINDEAD")
      return
    end

    local ply = player.GetByUniqueID(tr.Entity.uqid)

    if IsValid(ply) then
      self:BeginDefib(ply, tr.Entity)
    else
      self:FireError("FAILURE - SUBJECT BRAINDEAD")
      return
    end
  else
    self:FireError("FAILURE - INVALID TARGET")
  end
end

function SWEP:BeginDefib(ply, ragdoll)
  local spawnPos = self:FindPosition(self.Owner)

  if not spawnPos then
    self:FireError("FAILURE - INSUFFICIENT ROOM")
    return
  end

  self:SetStateText("DEFIBRILLATING - "..string.upper(ply:Name()))
  self:SetDefibState(STATE_PROGRESS)
  self:SetDefibStartTime(CurTime())

  self.TargetPly = ply
  self.TargetRagdoll = ragdoll

  self:SetNextPrimaryFire(CurTime() + 6)
end

function SWEP:FireError(err)
  if err then
    self:SetStateText(err)
  else
    self:SetStateText("")
  end

  self:SetDefibState(STATE_ERROR)

  timer.Simple(1, function()
    if IsValid(self) then
      self:SetDefibState(STATE_NONE)
      self:SetStateText("")
    end
  end)

  self:SetNextPrimaryFire(CurTime() + 1.2)
end

function SWEP:FireSuccess()
  self:SetDefibState(STATE_NONE)
  self:SetNextPrimaryFire(CurTime() + 1)
  
  hook.Call("UsedDefib", GAMEMODE, self.Owner)

  self:Remove()
end

function SWEP:Think()
  if CLIENT then return end

  if self:GetDefibState() == STATE_PROGRESS then
    if not IsValid(self.Owner) then
      self:FireError()
      return
    end

    if not (IsValid(self.TargetPly) and IsValid(self.TargetRagdoll)) then
      self:FireError("ERROR - SUBJECT BRAINDEAD")
      return
    end

    local tr = util.TraceLine({
      start = self.Owner:EyePos(),
      endpos = self.Owner:EyePos() + self.Owner:GetAimVector() * 80,
      filter = self.Owner
    })

    if tr.Entity ~= self.TargetRagdoll then
      self:FireError("ERROR - TARGET LOST")
      return
    end

    if CurTime() >= self:GetDefibStartTime() + 5 then
      if self:HandleRespawn() then
        self:FireSuccess()
      else
        self:FireError("ERROR - INSUFFICIENT ROOM")
        return
      end
    end


    self:NextThink(CurTime())
    return true
  end
end

function SWEP:HandleRespawn()
  local ply, ragdoll = self.TargetPly, self.TargetRagdoll
  local spawnPos = self:FindPosition(self.Owner)

  if not spawnPos then
    return false
  end
  
  --local credits = 2
  local credits = CORPSE.GetCredits(ragdoll, 0)

  ply:SpawnForRound(true)
  ply:SetCredits(credits)
  --ply:SetRole(ROLE_TRAITOR)
  --SendFullStateUpdate()
  ply:SetPos(spawnPos)
  ply:SetEyeAngles(Angle(0, ragdoll:GetAngles().y, 0))

  ragdoll:Remove()

  return true
end


local Positions = {}
for i=0,360,22.5 do table.insert( Positions, Vector(math.cos(i),math.sin(i),0) ) end -- Populate Around Player
table.insert(Positions, Vector(0, 0, 1)) -- Populate Above Player

function SWEP:FindPosition(ply)
  local size = Vector(32, 32, 72)
  
  local StartPos = ply:GetPos() + Vector(0, 0, size.z/2)
  
  local len = #Positions
  
  for i = 1, len do
    local v = Positions*
    local Pos = StartPos + v * size * 1.5
    
    local tr = {}
    tr.start = Pos
    tr.endpos = Pos
    tr.mins = size / 2 * -1
    tr.maxs = size / 2
    local trace = util.TraceHull(tr)
    
    if(not trace.Hit) then
      return Pos - Vector(0, 0, size.z/2)
    end
  end

  return false
end



Bump.

No one knows what you are talking about.

Instead of having this weapon being limited to ONE PURCHASE for ONE PLAYER, I want it to be limited to TWO PURCHASES for ALL THE PLAYERS per round.

Tried to do another attempt at it.




hook.Add("TTTPrepareRound", "defibtAmountBought Reset", function()

	defibtAmountBought = 0

end )

function SWEP:Initialize()
	if defibtAmountBought < 2 then
		self:SetDefibState(STATE_NONE)
		self:SetDefibStartTime(0)
		defibtAmountBought = defibtAmountBought + 1
	else
		self.Owner:StripWeapon( "weapon_ttt_defibt" )
	end
end



I got this error though…



[ERROR] gamemodes/terrortown/entities/weapons/weapon_ttt_defibt.lua:101: attempt to call method 'StripWeapon' (a nil value) 1. unknown - gamemodes/terrortown/entities/weapons/weapon_ttt_defibt.lua:101


Is the error yellow? If it is, you are trying to call a serverside method on client, which does not exist on client.

add “if SERVER then /code/ end” check

besides the error
on the else part you’ll wan’t to add
[lua]
self.Owner:SetCredits(self.Owner:GetCredits() + 1)
[/lua]

Credits are already set in HandleRespawn function in the original code.

the player getting respawned is not the same as the player who respawns the player

the point of setting the credits in the else statement is so that guy who’s already purchased the weapon twice gets his credits back instead of just losing his credits.

the handle respawn function won’t even be called after you strip the weapon

Oh, I misunderstood. My apologies. Unfortunately, the code didn’t work anyway.

Trying a different approach…

So, I made it count the number of alive players, the number of default traitors, and the amount of traitors that are allowed.

But, when I want it to print the values of the variables in console, it produces nil.

Here’s where I print my values…



function SWEP:PrimaryAttack()
	print (numberOfTraitors)
	print (numberTefibLimit)
  if CLIENT then return end

  local tr = util.TraceLine({
    start = self.Owner:EyePos(),
    endpos = self.Owner:EyePos() + self.Owner:GetAimVector() * 80,
    filter = self.Owner
  })

  if IsValid(tr.Entity) and tr.Entity:GetClass() == "prop_ragdoll" then
    if not tr.Entity.uqid then
      self:FireError("FAILURE - SUBJECT BRAINDEAD")
      return
    end

    local ply = player.GetByUniqueID(tr.Entity.uqid)

    if IsValid(ply) then
      self:BeginDefib(ply, tr.Entity)
    else
      self:FireError("FAILURE - SUBJECT BRAINDEAD")
      return
    end
  else
    self:FireError("FAILURE - INVALID TARGET")
  end
end


Here’s my code for the numbers check.



if (SERVER) then
        hook.Add( "TTTBeginRound", "NumberOfTypes", function()
                local numberOfTraitors = 0
				local numberOfPlayers = 0
                for k, v in pairs( player.GetAll() ) do
                        if v:IsTraitor() and v:Alive() then
                                numberOfTraitors=numberOfTraitors+1
                        end
						if v:Alive() and !v:IsSpec() then
								numberOfPlayers=numberOfPlayers+1
						end
                end
                timer.Simple( .5, function() 
                        PrintMessage( HUD_PRINTTALK, "Traitors: "..numberOfTraitors )
						PrintMessage( HUD_PRINTTALK, "Number of Players: "..numberOfPlayers )
                end )
				local numberTefibLimit = numberOfTraitors + 2
				PrintMessage( HUD_PRINTTALK, "Number of Traitors Allowed: "..numberTefibLimit )
        end )
end


Here’s my altered error message in Think…



function SWEP:Think()
  if CLIENT then return end

  if self:GetDefibState() == STATE_PROGRESS then
    if not IsValid(self.Owner) then
      self:FireError()
      return
    end

    if not (IsValid(self.TargetPly) and IsValid(self.TargetRagdoll)) then
      self:FireError("ERROR - SUBJECT BRAINDEAD")
      return
    end

    local tr = util.TraceLine({
      start = self.Owner:EyePos(),
      endpos = self.Owner:EyePos() + self.Owner:GetAimVector() * 80,
      filter = self.Owner
    })

    if tr.Entity ~= self.TargetRagdoll then
      self:FireError("ERROR - TARGET LOST")
      return
    end
	
	if numberOfTraitors == numberTefibLimit then
      self:FireError("ERROR - TOO MANY TRAITORS")
      return
    end

    if CurTime() >= self:GetDefibStartTime() + 5 then
      if self:HandleRespawn() then
        self:FireSuccess()
      else
        self:FireError("ERROR - INSUFFICIENT ROOM")
        return
      end
    end


    self:NextThink(CurTime())
    return true
  end
end


And here’s where I produce the amount of traitors and adding and stuff…



function SWEP:HandleRespawn()
  local ply, ragdoll = self.TargetPly, self.TargetRagdoll
  local spawnPos = self:FindPosition(self.Owner)

  if not spawnPos then
    return false
  end
  
  local credits = CORPSE.GetCredits(ragdoll, 0)
  local health = 50
  
  if ragdoll:GetRole() == "ROLE_INNOCENT" or ragdoll:GetRole() == "ROLE_DETECTIVE" then
	numberOfTraitors = numberOfTraitors + 1
  end
  

  ply:SpawnForRound(true)
  ply:SetCredits(credits)
  ply:SetRole(ROLE_TRAITOR)
  ply:SetHealth(health)
  SendFullStateUpdate()
  ply:SetPos(spawnPos)
  ply:SetEyeAngles(Angle(0, ragdoll:GetAngles().y, 0))

  ragdoll:Remove()

  return true
end


If you need any addition code to help, I’ll be more than happy to provide it.

bump