I've designed a grenade intending Traitors to randomly produce one of several overpowered weapons.
However, my test SWEP is not functioning correctly, while it occasioonally successfully drops one of the listed weapons it does not leave the players inventory and it only drops one kind of weapon per map.
Any help would be wonderful.
[CODE]
if SERVER then
AddCSLuaFile( "shared.lua" )
end
SWEP.HoldType = "grenade"
if CLIENT then
SWEP.PrintName = "Mystery"
SWEP.Slot = 3
SWEP.SlotPos = 0
SWEP.Icon = "VGUI/ttt/icon_nades"
end
SWEP.Base = "weapon_tttbasegrenade"
SWEP.Kind = WEAPON_NADE
SWEP.WeaponID = AMMO_DISCOMB
SWEP.Spawnable = true
SWEP.AdminSpawnable = true
SWEP.AutoSpawnable = false
SWEP.UseHands = true
SWEP.ViewModelFlip = false
SWEP.ViewModelFOV = 54
SWEP.ViewModel = "models/weapons/cstrike/c_eq_fraggrenade.mdl"
SWEP.WorldModel = "models/weapons/w_eq_fraggrenade.mdl"
SWEP.Weight = 5
-- really the only difference between grenade weapons: the model and the thrown
-- ent.
function SWEP:GetGrenadeName()
local chance = math.random(4)
if chance == 1 then
return "weapon_ttt_knife"
elseif chance == 2 then
return "dragon"
elseif chance == 3 then
return "heatgoogles"
else
return "ttt_manhacknade_proj"
end
end
[/CODE]
Try that
[CODE]function SWEP:GetGrenadeName()
local chance = math.random(1,4)
if chance == 1 then
return "weapon_ttt_knife"
elseif chance == 2 then
return "dragon"
elseif chance == 3 then
return "heatgoogles"
else
return "ttt_manhacknade_proj"
end
end[/CODE]
or this:
[CODE]function SWEP:GetGrenadeName()
local chance = math.Rand(1,4)
if chance == 1 then
return "weapon_ttt_knife"
elseif chance == 2 then
return "dragon"
elseif chance == 3 then
return "heatgoogles"
else
return "ttt_manhacknade_proj"
end
end[/CODE]
All that does is change the possible numbers from 0, 1, 2, or 3 to 1, 2, 3, or 4.
Or it does nothing I forget whether lua counts from zero.
Well if that is the case then you need to look at the grenades base. I see nothing wrong with what you have.
I should mention that the only thing I've gotten to work from it is the knife. Additionally here is the base grenade code, it is quite lengthy.
-- common code for all types of grenade
[LUA]if SERVER then
AddCSLuaFile( "shared.lua" )
end
SWEP.HoldReady = "grenade"
SWEP.HoldNormal = "slam"
if CLIENT then
SWEP.PrintName = "Incendiary grenade"
SWEP.Instructions = "Burn."
SWEP.Slot = 3
SWEP.SlotPos = 0
SWEP.Icon = "VGUI/ttt/icon_nades"
end
SWEP.Base = "weapon_tttbase"
SWEP.Kind = WEAPON_NADE
SWEP.ViewModel = "models/weapons/v_eq_flashbang.mdl"
SWEP.WorldModel = "models/weapons/w_eq_flashbang.mdl"
SWEP.Weight = 5
SWEP.ViewModelFlip = true
SWEP.AutoSwitchFrom = true
SWEP.DrawCrosshair = false
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = false
SWEP.Primary.Delay = 1.0
SWEP.Primary.Ammo = "none"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.IsGrenade = true
SWEP.NoSights = true
SWEP.pin_pulled = false
SWEP.throw_time = 0
SWEP.was_thrown = false
SWEP.detonate_timer = 5
SWEP.DeploySpeed = 1.5
AccessorFuncDT( SWEP, "pin_pulled", "Pin")
AccessorFuncDT( SWEP, "throw_time", "ThrowTime")
AccessorFunc(SWEP, "det_time", "DetTime")
CreateConVar("ttt_no_nade_throw_during_prep", "0")
function SWEP:SetupDataTables()
self:DTVar("Bool", 0, "pin_pulled")
self:DTVar("Int", 0, "throw_time")
end
function SWEP:PrimaryAttack()
self.Weapon:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
if GetRoundState() == ROUND_PREP and GetConVar("ttt_no_nade_throw_during_prep"):GetBool() then
return
end
self:PullPin()
end
function SWEP:SecondaryAttack()
end
function SWEP:PullPin()
if self:GetPin() then return end
local ply = self.Owner
if not IsValid(ply) then return end
self.Weapon:SendWeaponAnim(ACT_VM_PULLPIN)
if self.SetWeaponHoldType then
self:SetWeaponHoldType(self.HoldReady)
end
self:SetPin(true)
self:SetDetTime(CurTime() + self.detonate_timer)
end
function SWEP:Think()
local ply = self.Owner
if not IsValid(ply) then return end
-- pin pulled and attack loose = throw
if self:GetPin() then
-- we will throw now
if not ply:KeyDown(IN_ATTACK) then
self:StartThrow()
self:SetPin(false)
self.Weapon:SendWeaponAnim(ACT_VM_THROW)
if SERVER then
self.Owner:SetAnimation( PLAYER_ATTACK1 )
end
else
-- still cooking it, see if our time is up
if SERVER and self:GetDetTime() < CurTime() then
self:BlowInFace()
end
end
elseif self:GetThrowTime() > 0 and self:GetThrowTime() < CurTime() then
self:Throw()
end
end
function SWEP:BlowInFace()
local ply = self.Owner
if not IsValid(ply) then return end
if self.was_thrown then return end
self.was_thrown = true
-- drop the grenade so it can immediately explode
local ang = ply:GetAngles()
local src = ply:GetPos() + (ply:Crouching() and ply:GetViewOffsetDucked() or ply:GetViewOffset())
src = src + (ang:Right() * 10)
self:CreateGrenade(src, Angle(0,0,0), Vector(0,0,1), Vector(0,0,1), ply)
self:SetThrowTime(0)
self:Remove()
end
function SWEP:StartThrow()
self:SetThrowTime(CurTime() + 0.1)
end
function SWEP:Throw()
if CLIENT then
self:SetThrowTime(0)
elseif SERVER then
local ply = self.Owner
if not IsValid(ply) then return end
if self.was_thrown then return end
self.was_thrown = true
local ang = ply:EyeAngles()
-- don't even know what this bit is for, but SDK has it
-- probably to make it throw upward a bit
if ang.p < 90 then
ang.p = -10 + ang.p * ((90 + 10) / 90)
else
ang.p = 360 - ang.p
ang.p = -10 + ang.p * -((90 + 10) / 90)
end
local vel = math.min(800, (90 - ang.p) * 6)
local vfw = ang:Forward()
local vrt = ang:Right()
-- local vup = ang:Up()
local src = ply:GetPos() + (ply:Crouching() and ply:GetViewOffsetDucked() or ply:GetViewOffset())
src = src + (vfw * 8) + (vrt * 10)
local thr = vfw * vel + ply:GetVelocity()
self:CreateGrenade(src, Angle(0,0,0), thr, Vector(600, math.random(-1200, 1200), 0), ply)
self:SetThrowTime(0)
self:Remove()
end
end
-- subclasses must override with their own grenade ent
function SWEP:GetGrenadeName()
ErrorNoHalt("SWEP BASEGRENADE ERROR: GetGrenadeName not overridden! This is probably wrong!\n")
return "ttt_firegrenade_proj"
end
function SWEP:CreateGrenade(src, ang, vel, angimp, ply)
local gren = ents.Create(self:GetGrenadeName())
if not IsValid(gren) then return end
gren:SetPos(src)
gren:SetAngles(ang)
-- gren:SetVelocity(vel)
gren:SetOwner(ply)
gren:SetThrower(ply)
gren:SetGravity(0.4)
gren:SetFriction(0.2)
gren:SetElasticity(0.45)
gren:Spawn()
gren:PhysWake()
local phys = gren:GetPhysicsObject()
if IsValid(phys) then
phys:SetVelocity(vel)
phys:AddAngleVelocity(angimp)
end
-- This has to happen AFTER Spawn() calls gren's Initialize()
gren:SetDetonateExact(self:GetDetTime())
return gren
end
function SWEP:PreDrop()
-- if owner dies or drops us while the pin has been pulled, create the armed
-- grenade anyway
if self:GetPin() then
self:BlowInFace()
end
end
function SWEP:Deploy()
if self.SetWeaponHoldType then
self:SetWeaponHoldType(self.HoldNormal)
end
self:SetThrowTime(0)
self:SetPin(false)
return true
end
function SWEP:Holster()
if self:GetPin() then
return false -- no switching after pulling pin
end
self:SetThrowTime(0)
self:SetPin(false)
return true
end
function SWEP:Reload()
return false
end
function SWEP:Initialize()
if self.SetWeaponHoldType then
self:SetWeaponHoldType(self.HoldNormal)
end
self:SetDeploySpeed(self.DeploySpeed)
self:SetDetTime(0)
self:SetThrowTime(0)
self:SetPin(false)
self.was_thrown = false
end
function SWEP:OnRemove()
if CLIENT and IsValid(self.Owner) and self.Owner == LocalPlayer() and self.Owner:Alive() then
RunConsoleCommand("use", "weapon_ttt_unarmed")
end
end
[/LUA]
Instead of it being a grenade which throws a knife and such, why dont you just make it a weapon? I mean why dont you just do the math random and just do if chance == 4 then self.Owner:Give("weapon_ttt_manhackgrenade") ? It would work better.
Ideally I'm trying to make a grenade that will wait a few seconds and then spawn an item with this grenade acting as a placeholder but that may work as a last resort.
[editline]24th January 2014[/editline]
Alright modified the primary attack of the teleporter slightly to give weapons with an effect so here is the code I modified
[CODE]function SWEP:PrimaryAttack()
--test
self.Weapon:SetNextSecondaryFire( CurTime() + self.Secondary.Delay )
if SERVER then
self:TeleportStore()
else
surface.PlaySound("ui/buttonrollover.wav")
end
--test
self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
if self.Weapon:Clip1() <= 0 then
self:DryFire(self.SetNextSecondaryFire)
return
end
-- Disallow initiating teleports during post, as it will occur across the
-- restart and allow the user an advantage during prep
if GetRoundState() == ROUND_POST then return end
if SERVER then
self:TeleportRecall()
self.remove()
local chance = math.Rand(1,4)
if chance == 1 then
self.Owner:Give("weapon_ttt_knife")
elseif chance == 2 then
self.Owner:Give("dragon")
elseif chance == 3 then
self.Owner:Give("heatgoogles")
else
self.Owner:Give("weapon_ttt_manhackgrenade")
end
else
surface.PlaySound("buttons/combine_button7.wav")
end
end[/CODE]
And here is all of the code put together
[CODE]
-- traitor equipment: teleporter
if SERVER then
AddCSLuaFile( "shared.lua" )
end
SWEP.HoldType = "normal"
if CLIENT then
SWEP.PrintName = "Mystery"
SWEP.Slot = 7
SWEP.ViewModelFOV = 10
SWEP.EquipMenuData = {
type = "item_weapon",
desc = "Teleport a weapon from the aether"
};
SWEP.Icon = "VGUI/ttt/icon_beacon"
end
SWEP.Base = "weapon_tttbase"
SWEP.ViewModel = "models/weapons/v_crowbar.mdl"
SWEP.WorldModel = "models/weapons/w_slam.mdl"
SWEP.DrawCrosshair = false
SWEP.ViewModelFlip = false
SWEP.Primary.ClipSize = 1
SWEP.Primary.DefaultClip = 1
SWEP.Primary.ClipMax = 1
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "GaussEnergy"
SWEP.Primary.Delay = 0.5
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.Secondary.Delay = 1.0
SWEP.Kind = WEAPON_EQUIP2
--SWEP.CanBuy = {ROLE_TRAITOR, ROLE_DETECTIVE}
SWEP.WeaponID = AMMO_TELEPORT
SWEP.AllowDrop = true
SWEP.NoSights = true
SWEP.CSMuzzleFlashes = false
local delay_beamup = 1
local delay_beamdown = 1
local ttt_telefrags = CreateConVar("ttt_teleport_telefrags", "0")
function SWEP:SetTeleportMark(pos, ang)
self.teleport = {pos = pos, ang = ang}
end
function SWEP:GetTeleportMark() return self.teleport end
function SWEP:PrimaryAttack()
--test
self.Weapon:SetNextSecondaryFire( CurTime() + self.Secondary.Delay )
if SERVER then
self:TeleportStore()
else
surface.PlaySound("ui/buttonrollover.wav")
end
--test
self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
if self.Weapon:Clip1() <= 0 then
self:DryFire(self.SetNextSecondaryFire)
return
end
-- Disallow initiating teleports during post, as it will occur across the
-- restart and allow the user an advantage during prep
if GetRoundState() == ROUND_POST then return end
if SERVER then
self:TeleportRecall()
self.remove()
local chance = math.Rand(1,4)
if chance == 1 then
self.Owner:Give("weapon_ttt_knife")
elseif chance == 2 then
self.Owner:Give("dragon")
elseif chance == 3 then
self.Owner:Give("heatgoogles")
else
self.Owner:Give("weapon_ttt_manhackgrenade")
end
else
surface.PlaySound("buttons/combine_button7.wav")
end
end
function SWEP:SecondaryAttack()
self.Weapon:SetNextSecondaryFire( CurTime() + self.Secondary.Delay )
if SERVER then
self:TeleportStore()
else
surface.PlaySound("ui/buttonrollover.wav")
end
end
local zap = Sound("ambient/levels/labs/electric_explosion4.wav")
local unzap = Sound("ambient/levels/labs/electric_explosion2.wav")
local function Telefrag(victim, attacker)
if not IsValid(victim) then return end
local dmginfo = DamageInfo()
dmginfo:SetDamage(5000)
dmginfo:SetDamageType(DMG_SONIC)
dmginfo:SetAttacker(attacker)
dmginfo:SetDamageForce(Vector(0,0,10))
dmginfo:SetDamagePosition(attacker:GetPos())
victim:TakeDamageInfo(dmginfo)
end
local function ShouldCollide(ent)
local g = ent:GetCollisionGroup()
return (g != COLLISION_GROUP_WEAPON and
g != COLLISION_GROUP_DEBRIS and
g != COLLISION_GROUP_DEBRIS_TRIGGER and
g != COLLISION_GROUP_INTERACTIVE_DEBRIS)
end
-- Teleport a player to a {pos, ang}
local function TeleportPlayer(ply, teleport)
local oldpos = ply:GetPos()
local pos = teleport.pos
local ang = teleport.ang
-- print decal on destination
util.PaintDown(pos + Vector(0,0,25), "GlassBreak", ply)
-- perform teleport
ply:SetPos(pos)
ply:SetEyeAngles(ang) -- ineffective due to freeze...
timer.Simple(delay_beamdown, function ()
if IsValid(ply) then
ply:Freeze(false)
end
end)
sound.Play(zap, oldpos, 65, 100)
sound.Play(unzap, pos, 55, 100)
-- print decal on source now that we're gone, because else it will refuse
-- to draw for some reason
util.PaintDown(oldpos + Vector(0,0,25), "GlassBreak", ply)
end
-- Checks teleport destination. Returns bool and table, if bool is true then
-- location is blocked by world or prop. If table is non-nil it contains a list
-- of blocking players.
local function CanTeleportToPos(ply, pos)
-- first check if we can teleport here at all, because any solid object or
-- brush will make us stuck and therefore kills/blocks us instead, so the
-- trace checks for anything solid to players that isn't a player
local tr = nil
local tres = {start=pos, endpos=pos, mask=MASK_PLAYERSOLID, filter=player.GetAll()}
local collide = false
-- This thing is unnecessary if we can supply a collision group to trace
-- functions, like we can in source and sanity suggests we should be able
-- to do so, but I have not found a way to do so yet. Until then, re-trace
-- while extending our filter whenever we hit something we don't want to
-- hit (like weapons or ragdolls).
repeat
tr = util.TraceEntity(tres, ply)
if tr.HitWorld then
collide = true
elseif IsValid(tr.Entity) then
if ShouldCollide(tr.Entity) then
collide = true
else
table.insert(tres.filter, tr.Entity)
end
end
until (not tr.Hit) or collide
if collide then
--Telefrag(ply, ply)
return true, nil
else
-- find all players in the place where we will be and telefrag them
local blockers = ents.FindInBox(pos + Vector(-16, -16, 0),
pos + Vector(16, 16, 64))
local blocking_plys = {}
for _, block in pairs(blockers) do
if IsValid(block) then
if block:IsPlayer() and block != ply then
if block:IsTerror() and block:Alive() then
table.insert(blocking_plys, block)
-- telefrag blocker
--Telefrag(block, ply)
end
end
end
end
return false, blocking_plys
end
return false, nil
end
local function DoTeleport(ply, teleport)
if IsValid(ply) and ply:IsTerror() and teleport then
local fail = false
local block_world, block_plys = CanTeleportToPos(ply, teleport.pos)
if block_world then
-- if blocked by prop/world, always fail
fail = true
elseif block_plys and #block_plys > 0 then
-- if blocked by player, maybe telefrag
if ttt_telefrags:GetBool() then
for _, p in pairs(block_plys) do
Sorry, you need to Log In to post a reply to this thread.