add sborka
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add( "ent_lordi_rocket", "vgui/entities/ent_lordi_rocket", Color( 255, 255, 255, 255 ) )
|
||||
|
||||
--Couldnt be bothered to make a world model... This will hold as a placeholder for now
|
||||
|
||||
function ENT:Initialize()
|
||||
self.modelEnt = ClientsideModel("models/weapons/lordi/c_sledgehammer.mdl", RENDER_GROUP_OPAQUE)
|
||||
|
||||
self.Spin_Ang = 0
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
|
||||
self.Spin_Ang = self.Spin_Ang + 10
|
||||
if (IsValid(self.modelEnt)) and self.modelEnt:LookupBone("sledge_hammer") then
|
||||
self.modelEnt:SetPos(self:GetPos() + self:GetAngles():Right() * 20)
|
||||
self.modelEnt:SetAngles(self:GetAngles())
|
||||
self.modelEnt:SetParent(self)
|
||||
self.modelEnt:ManipulateBoneAngles(self.modelEnt:LookupBone("sledge_hammer"),Angle(174 + self.Spin_Ang,110,87))
|
||||
self.modelEnt:ManipulateBonePosition(self.modelEnt:LookupBone("sledge_hammer"),Vector(-20,27,8.6))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (IsValid(self.modelEnt)) then
|
||||
self.modelEnt:Remove()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,75 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
include("shared.lua")
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/weapons/w_crowbar.mdl")
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:EmitSound("npc/zombie/claw_miss1.wav",75,60)
|
||||
local phys = self:GetPhysicsObject()
|
||||
|
||||
if IsValid(phys) then phys:Wake() phys:EnableGravity(false) end
|
||||
|
||||
util.SpriteTrail(self, 0, Color(255,255,255), false, 10, 1, 0.5, 8, "trails/smoke.vmt")
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if self:GetVelocity():Length() <= 400 then
|
||||
self:PhysicsCollide()
|
||||
return
|
||||
end
|
||||
|
||||
self:EmitSound("weapons/slam/throw.wav")
|
||||
end
|
||||
|
||||
function ENT:Use(activator,caller)
|
||||
end
|
||||
|
||||
hook.Add("EntityTakeDamage","Sledgehammer_Kill",function(ply,dmginfo)
|
||||
if IsValid(dmginfo:GetAttacker()) and dmginfo:GetAttacker():GetClass() and dmginfo:GetAttacker():GetClass() == "ent_lordi_sledgehammer" then
|
||||
if IsValid(dmginfo:GetAttacker():GetOwner()) and dmginfo:GetAttacker():GetOwner():IsPlayer() then
|
||||
dmginfo:SetAttacker(dmginfo:GetAttacker():GetOwner())
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function ENT:Touch( ent )
|
||||
if ent:IsValid() then
|
||||
if ent:IsPlayer() or ent:IsNPC() then
|
||||
for i=1,3 do
|
||||
ent:EmitSound("physics/body/body_medium_break"..math.random(2,4)..".wav",75,math.random(70,90))
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin(ent:GetPos() + Vector(0,0,math.random(5,20)))
|
||||
effectdata:SetEntity(ent)
|
||||
util.Effect( "BloodImpact", effectdata )
|
||||
end
|
||||
ent:TakeDamage(math.random(70,120),self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(data,obj)
|
||||
timer.Create("sledge_hammer_next_frame"..self:EntIndex(),0,1,function()
|
||||
self:EmitSound("physics/metal/metal_barrel_impact_hard7.wav")
|
||||
local sledge = ents.Create("weapon_lordi_sledgehammer")
|
||||
sledge:SetPos(self:GetPos())
|
||||
sledge:SetAngles(self:GetAngles())
|
||||
sledge:Spawn()
|
||||
|
||||
sledge:GetPhysicsObject():ApplyForceCenter( self:GetVelocity() * 15 )
|
||||
|
||||
self:Remove()
|
||||
/*
|
||||
local explode = ents.Create("env_explosion")
|
||||
explode:SetPos( self:GetPos() )
|
||||
explode:SetOwner( self:GetOwner() )
|
||||
explode:Spawn()
|
||||
explode:SetKeyValue("iMagnitude","125")
|
||||
explode:Fire("Explode", 0, 0 )
|
||||
self:EmitSound("ambient/explosions/explode_"..math.random(1,5)..".wav")
|
||||
self:Remove()
|
||||
*/
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_gmodentity"
|
||||
ENT.Author = "LordiAnders"
|
||||
ENT.Category = "[FT] Специальное Оружие"
|
||||
ENT.PrintName = "Rocket"
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,319 @@
|
||||
TOOL.Category = "Construction"
|
||||
TOOL.Name = "LED screens"
|
||||
TOOL.Command = nil
|
||||
TOOL.ConfigName = ""
|
||||
|
||||
local TextBox = {}
|
||||
local slider = {}
|
||||
local slider2 = {}
|
||||
local slider3 = {}
|
||||
local frame = {}
|
||||
TOOL.ClientConVar[ "text" ] = ""
|
||||
TOOL.ClientConVar[ "type" ] = 1
|
||||
TOOL.ClientConVar[ "speed" ] = 1.5
|
||||
TOOL.ClientConVar[ "wide" ] = 6
|
||||
TOOL.ClientConVar[ "fx" ] = 0
|
||||
TOOL.ClientConVar[ "wire" ] = 0
|
||||
TOOL.ClientConVar[ "r"] = 255
|
||||
TOOL.ClientConVar[ "g" ] = 200
|
||||
TOOL.ClientConVar[ "b" ] = 0
|
||||
|
||||
if (SERVER) then
|
||||
CreateConVar('sbox_maxledscreens', 5)
|
||||
end
|
||||
|
||||
cleanup.Register("ledscreens")
|
||||
|
||||
TOOL.Information = {
|
||||
{ name = "left" },
|
||||
{ name = "right" }
|
||||
}
|
||||
|
||||
if (CLIENT) then
|
||||
language.Add("Tool.ledscreen.name", "LED screen")
|
||||
language.Add("Tool.ledscreen.desc", "Create a LED panel")
|
||||
|
||||
language.Add("Tool.ledscreen.left", "Spawn a LED panel");
|
||||
language.Add("Tool.ledscreen.right", "Update LED panel");
|
||||
language.Add("Tool.ledscreen.reload", "Copy LED panel's settings");
|
||||
|
||||
language.Add("Undone.ledscreens", "Undone ledscreen")
|
||||
language.Add("Undone_ledscreens", "Undone ledscreen")
|
||||
language.Add("Cleanup.ledscreens", "ledscreens")
|
||||
language.Add("Cleanup_ledscreens", "ledscreens")
|
||||
language.Add("Cleaned.ledscreens", "Cleaned up all ledscreens")
|
||||
language.Add("Cleaned_ledscreens", "Cleaned up all ledscreens")
|
||||
|
||||
language.Add("SBoxLimit.ledscreens", "You've hit the ledscreen limit!")
|
||||
language.Add("SBoxLimit_ledscreens", "You've hit the ledscreen limit!")
|
||||
end
|
||||
|
||||
local function GetConvars(self)
|
||||
local type = tonumber(self:GetClientInfo("type"))
|
||||
if !isnumber(type) then type = 1 end
|
||||
|
||||
local speed = tonumber(self:GetClientInfo("speed"))
|
||||
if !isnumber(speed) then speed = 1.5 end
|
||||
|
||||
local wide = tonumber(self:GetClientInfo("wide"))
|
||||
if !isnumber(wide) then wide = 6 end
|
||||
|
||||
local fx = tonumber(self:GetClientInfo("fx"))
|
||||
if !isnumber(fx) then fx = 0 end
|
||||
|
||||
local r, g, b = tonumber(self:GetClientInfo("r")), tonumber(self:GetClientInfo("g")), tonumber(self:GetClientInfo("b"))
|
||||
if !isnumber(r) or !isnumber(g) or !isnumber(b) then r, g, b = 255, 200, 100 end
|
||||
|
||||
return math.Clamp(type, 1, 4), math.Clamp(speed, 1, 10), math.Clamp(wide, 3, 8), math.Clamp(fx, 0, 1), r, g, b
|
||||
end
|
||||
|
||||
function TOOL:LeftClick(tr)
|
||||
if (tr.Entity:GetClass() == "player") then return false end
|
||||
if (CLIENT) then return true end
|
||||
|
||||
local Ply = self:GetOwner()
|
||||
local centerpos = {
|
||||
[3] = {18, 0},
|
||||
[4] = {11.5, 6},
|
||||
[5] = {18, 6},
|
||||
[6] = {36, 6},
|
||||
[7] = {42, 6},
|
||||
[8] = {48, 6},
|
||||
}
|
||||
|
||||
local type, speed, wide, fx, r, g, b = GetConvars(self)
|
||||
|
||||
local angle = tr.HitNormal:Angle()
|
||||
local SpawnPos = tr.HitPos + angle:Right() * centerpos[wide][1] - angle:Up() * centerpos[wide][2]
|
||||
|
||||
if not (self:GetWeapon():CheckLimit("ledscreens")) then return false end
|
||||
|
||||
local TextScreen
|
||||
if tonumber(self:GetClientInfo("wire")) > 0 then
|
||||
TextScreen = ents.Create("gb_rp_sign_wire")
|
||||
else
|
||||
TextScreen = ents.Create("gb_rp_sign")
|
||||
end
|
||||
TextScreen:SetPos(SpawnPos)
|
||||
TextScreen:Spawn()
|
||||
|
||||
angle:RotateAroundAxis(tr.HitNormal:Angle():Right(), -90)
|
||||
angle:RotateAroundAxis(tr.HitNormal:Angle():Forward(), 90)
|
||||
TextScreen:SetAngles(angle)
|
||||
TextScreen:SetText(self:GetClientInfo("text"))
|
||||
TextScreen:SetType(type)
|
||||
TextScreen:SetSpeed(speed)
|
||||
TextScreen:SetWide(wide)
|
||||
TextScreen:SetModel("models/squad/sf_plates/sf_plate1x"..wide..".mdl")
|
||||
TextScreen:SetTColor(Vector(r/100, g/100, b/100))
|
||||
TextScreen:SetFX(fx)
|
||||
TextScreen:Activate()
|
||||
local Phys = TextScreen:GetPhysicsObject()
|
||||
Phys:EnableMotion( false )
|
||||
|
||||
undo.Create("ledscreens")
|
||||
|
||||
undo.AddEntity(TextScreen)
|
||||
undo.SetPlayer(Ply)
|
||||
undo.Finish()
|
||||
|
||||
Ply:AddCount("ledscreens", TextScreen)
|
||||
Ply:AddCleanup("ledscreens", TextScreen)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function TOOL:RightClick(tr)
|
||||
if (tr.Entity:GetClass() == "player") then return false end
|
||||
if (CLIENT) then return true end
|
||||
|
||||
local TraceEnt = tr.Entity
|
||||
|
||||
local type, speed, wide, fx, r, g, b = GetConvars(self)
|
||||
|
||||
if (TraceEnt:IsValid() and TraceEnt:GetClass() == "gb_rp_sign") then
|
||||
TraceEnt:SetText(self:GetClientInfo("text"))
|
||||
TraceEnt:SetType(type)
|
||||
TraceEnt:SetSpeed(speed)
|
||||
TraceEnt:SetWide(wide)
|
||||
TraceEnt:SetFX(fx)
|
||||
TraceEnt:SetModel("models/squad/sf_plates/sf_plate1x"..wide..".mdl")
|
||||
TraceEnt:SetTColor(Vector(r/100, g/100, b/100))
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
function TOOL:Reload(tr)
|
||||
|
||||
if !IsValid(tr.Entity) then return false end
|
||||
local TraceEnt = tr.Entity
|
||||
|
||||
if (TraceEnt:IsValid() and TraceEnt:GetClass() == "gb_rp_sign") then
|
||||
if CLIENT or game.SinglePlayer() then
|
||||
local color = TraceEnt:GetTColor()
|
||||
RunConsoleCommand("ledscreen_text", TraceEnt:GetText())
|
||||
RunConsoleCommand("ledscreen_type", TraceEnt:GetType())
|
||||
RunConsoleCommand("ledscreen_r", color.x*100)
|
||||
RunConsoleCommand("ledscreen_g", color.y*100)
|
||||
RunConsoleCommand("ledscreen_b", color.z*100)
|
||||
RunConsoleCommand("ledscreen_speed", TraceEnt:GetSpeed())
|
||||
RunConsoleCommand("ledscreen_wide", TraceEnt:GetWide())
|
||||
RunConsoleCommand("ledscreen_fx", TraceEnt:GetFX())
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
|
||||
function TOOL.BuildCPanel(CPanel)
|
||||
CPanel:AddControl("Header", { Text = "#Tool.ledscreen.name" } )
|
||||
resetall = vgui.Create("DButton", resetbuttons)
|
||||
resetall:SetSize(100, 25)
|
||||
resetall:SetText("Reset all")
|
||||
resetall.DoClick = function()
|
||||
RunConsoleCommand("ledscreen_text", "")
|
||||
RunConsoleCommand("ledscreen_type", 1)
|
||||
RunConsoleCommand("ledscreen_r", 255)
|
||||
RunConsoleCommand("ledscreen_g", 200)
|
||||
RunConsoleCommand("ledscreen_b", 0)
|
||||
RunConsoleCommand("ledscreen_speed", 1.5)
|
||||
RunConsoleCommand("ledscreen_wide", 6)
|
||||
RunConsoleCommand("ledscreen_fx", 0)
|
||||
RunConsoleCommand("ledscreen_wire", 0)
|
||||
slider:SetValue(1)
|
||||
slider2:SetValue(1.5)
|
||||
slider3:SetValue(6)
|
||||
TextBox:SetValue("")
|
||||
|
||||
end
|
||||
CPanel:AddItem(resetall)
|
||||
local font = "InfoRUS3"
|
||||
frame = vgui.Create( "DPanel" )
|
||||
frame:SetSize( CPanel:GetWide(), 50 )
|
||||
frame.appr = nil
|
||||
frame.Paint = function(self,w,h)
|
||||
draw.RoundedBox(0,0,0,w,h,Color(0,0,0))
|
||||
surface.SetFont(font)
|
||||
local alfa
|
||||
if GetConVarNumber("ledscreen_fx") > 0 then
|
||||
alfa = math.random(100,220)
|
||||
else
|
||||
alfa = 255
|
||||
end
|
||||
self.Text = GetConVarString("ledscreen_text")
|
||||
self.Type = GetConVarNumber("ledscreen_type")
|
||||
self.Speed = GetConVarNumber("ledscreen_speed")
|
||||
self.static = false
|
||||
local ww,hh = surface.GetTextSize(self.Text)
|
||||
local multiplier = self.Speed * 100
|
||||
self.Color = Color(GetConVarNumber("ledscreen_r"),GetConVarNumber("ledscreen_g"),GetConVarNumber("ledscreen_b"), alfa)
|
||||
if self.Type == 1 then
|
||||
|
||||
local xs = (math.fmod(SysTime() * multiplier,w+ww)) - ww
|
||||
draw.DrawText(self.Text,font,xs,0,self.Color,0)
|
||||
|
||||
elseif self.Type == 2 then
|
||||
|
||||
if !self.appr or self.appr > ww then
|
||||
self.appr = -w
|
||||
else
|
||||
self.appr = math.Approach(self.appr, ww+w, FrameTime() * multiplier)
|
||||
end
|
||||
|
||||
draw.DrawText(self.Text,font,self.appr * -1,0,self.Color,0)
|
||||
|
||||
else
|
||||
if !self.appr then
|
||||
self.appr = 0
|
||||
end
|
||||
|
||||
if w > ww then
|
||||
if self.Type == 3 then
|
||||
if self.appr < w-ww and !self.refl then
|
||||
self.appr = math.Approach(self.appr, ww+w, FrameTime() * multiplier)
|
||||
else
|
||||
if self.appr <= 0 then
|
||||
self.refl = nil
|
||||
else
|
||||
self.refl = true
|
||||
self.appr = math.Approach(self.appr, 0, FrameTime() * multiplier)
|
||||
end
|
||||
end
|
||||
else
|
||||
self.static = true
|
||||
end
|
||||
else
|
||||
if self.appr > w-ww-50 and !self.refl then
|
||||
self.appr = math.Approach(self.appr, w-ww-50, FrameTime() * multiplier)
|
||||
else
|
||||
if self.appr >= 50 then
|
||||
self.refl = nil
|
||||
else
|
||||
self.refl = true
|
||||
self.appr = math.Approach(self.appr, 50, FrameTime() * multiplier)
|
||||
end
|
||||
end
|
||||
end
|
||||
if self.static then
|
||||
draw.DrawText(self.Text,font,w/2,0,self.Color,1)
|
||||
else
|
||||
draw.DrawText(self.Text,font,self.appr,0,self.Color,0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CPanel:AddItem(frame)
|
||||
|
||||
|
||||
slider = vgui.Create("DNumSlider")
|
||||
slider:SetText("Type")
|
||||
slider:SetMinMax(1, 4)
|
||||
slider:SetDecimals(0)
|
||||
slider:SetValue(1)
|
||||
slider:SetConVar("ledscreen_type")
|
||||
CPanel:AddItem(slider)
|
||||
|
||||
slider2 = vgui.Create("DNumSlider")
|
||||
slider2:SetText("Speed")
|
||||
slider2:SetMinMax(1, 10)
|
||||
slider2:SetDecimals(1)
|
||||
slider2:SetValue(1)
|
||||
slider2:SetConVar("ledscreen_speed")
|
||||
CPanel:AddItem(slider2)
|
||||
|
||||
slider3 = vgui.Create("DNumSlider")
|
||||
slider3:SetText("Wide")
|
||||
slider3:SetMinMax(3, 8)
|
||||
slider3:SetDecimals(0)
|
||||
slider3:SetValue(6)
|
||||
slider3:SetConVar("ledscreen_wide")
|
||||
CPanel:AddItem(slider3)
|
||||
|
||||
TextBox = vgui.Create("DTextEntry")
|
||||
TextBox:SetUpdateOnType(true)
|
||||
TextBox:SetEnterAllowed(true)
|
||||
TextBox:SetConVar("ledscreen_text")
|
||||
TextBox:SetValue(GetConVarString("ledscreen_text"))
|
||||
CPanel:AddItem(TextBox)
|
||||
|
||||
CPanel:AddControl( "CheckBox", { Label = "Flicker effect", Description = "", Command = "ledscreen_fx" } )
|
||||
CPanel:AddControl( "CheckBox", { Label = "WireMod support", Description = "", Command = "ledscreen_wire" } )
|
||||
|
||||
CPanel:AddControl("Color", {
|
||||
Label = "LED color",
|
||||
Red = "ledscreen_r",
|
||||
Green = "ledscreen_g",
|
||||
Blue = "ledscreen_b",
|
||||
ShowHSV = 1,
|
||||
ShowRGB = 1,
|
||||
Multiplier = 255
|
||||
})
|
||||
|
||||
CPanel:AddControl("Label", { Text = "Gmod-Best.Ru ©2013-2019\nWith <3 from Mac" } )
|
||||
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
PermaProps
|
||||
Created by Entoros, June 2010
|
||||
Facepunch: http://www.facepunch.com/member.php?u=180808
|
||||
Modified By Malboro 28 / 12 / 2012
|
||||
|
||||
Ideas:
|
||||
Make permaprops cleanup-able
|
||||
|
||||
Errors:
|
||||
Errors on die
|
||||
|
||||
Remake:
|
||||
By Malboro the 28/12/2012
|
||||
*/
|
||||
|
||||
TOOL.Category = "Props Tool"
|
||||
TOOL.Name = "PermaProps"
|
||||
TOOL.Command = nil
|
||||
TOOL.ConfigName = ""
|
||||
|
||||
if CLIENT then
|
||||
language.Add("Tool.permaprops.name", "PermaProps")
|
||||
language.Add("Tool.permaprops.desc", "Save a props permanently")
|
||||
language.Add("Tool.permaprops.0", "LeftClick: Add RightClick: Remove Reload: Update")
|
||||
|
||||
surface.CreateFont("PermaPropsToolScreenFont", { font = "Arial", size = 40, weight = 1000, antialias = true, additive = false })
|
||||
surface.CreateFont("PermaPropsToolScreenSubFont", { font = "Arial", size = 30, weight = 1000, antialias = true, additive = false })
|
||||
end
|
||||
|
||||
function TOOL:LeftClick(trace)
|
||||
|
||||
if CLIENT then return true end
|
||||
|
||||
local ent = trace.Entity
|
||||
local ply = self:GetOwner()
|
||||
|
||||
if not PermaProps then ply:ChatPrint( "ERROR: Lib not found" ) return end
|
||||
|
||||
if !PermaProps.HasPermission( ply, "Save") then return end
|
||||
|
||||
if not ent:IsValid() then ply:ChatPrint( "That is not a valid entity !" ) return end
|
||||
if ent:IsPlayer() then ply:ChatPrint( "That is a player !" ) return end
|
||||
if ent.PermaProps then ply:ChatPrint( "That entity is already permanent !" ) return end
|
||||
|
||||
local content = PermaProps.PPGetEntTable(ent)
|
||||
if not content then return end
|
||||
|
||||
local max = tonumber(sql.QueryValue("SELECT MAX(id) FROM permaprops;"))
|
||||
if not max then max = 1 else max = max + 1 end
|
||||
|
||||
local new_ent = PermaProps.PPEntityFromTable(content, max)
|
||||
if !new_ent or !new_ent:IsValid() then return end
|
||||
|
||||
PermaProps.SparksEffect( ent )
|
||||
|
||||
PermaProps.SQL.Query("INSERT INTO permaprops (id, map, content) VALUES(NULL, ".. sql.SQLStr(game.GetMap()) ..", ".. sql.SQLStr(util.TableToJSON(content)) ..");")
|
||||
ply:ChatPrint("You saved " .. ent:GetClass() .. " with model ".. ent:GetModel() .. " to the database.")
|
||||
|
||||
ent:Remove()
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function TOOL:RightClick(trace)
|
||||
|
||||
if CLIENT then return true end
|
||||
|
||||
local ent = trace.Entity
|
||||
local ply = self:GetOwner()
|
||||
|
||||
if not PermaProps then ply:ChatPrint( "ERROR: Lib not found" ) return end
|
||||
|
||||
if !PermaProps.HasPermission( ply, "Delete") then return end
|
||||
|
||||
if not ent:IsValid() then ply:ChatPrint( "That is not a valid entity !" ) return end
|
||||
if ent:IsPlayer() then ply:ChatPrint( "That is a player !" ) return end
|
||||
if not ent.PermaProps then ply:ChatPrint( "That is not a PermaProp !" ) return end
|
||||
if not ent.PermaProps_ID then ply:ChatPrint( "ERROR: ID not found" ) return end
|
||||
|
||||
PermaProps.SQL.Query("DELETE FROM permaprops WHERE id = ".. ent.PermaProps_ID ..";")
|
||||
|
||||
ply:ChatPrint("You erased " .. ent:GetClass() .. " with a model of " .. ent:GetModel() .. " from the database.")
|
||||
|
||||
ent:Remove()
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function TOOL:Reload(trace)
|
||||
|
||||
if CLIENT then return true end
|
||||
|
||||
if not PermaProps then self:GetOwner():ChatPrint( "ERROR: Lib not found" ) return end
|
||||
|
||||
if (not trace.Entity:IsValid() and PermaProps.HasPermission( self:GetOwner(), "Update")) then self:GetOwner():ChatPrint( "You have reload all PermaProps !" ) PermaProps.ReloadPermaProps() return false end
|
||||
|
||||
if trace.Entity.PermaProps then
|
||||
|
||||
local ent = trace.Entity
|
||||
local ply = self:GetOwner()
|
||||
|
||||
if !PermaProps.HasPermission( ply, "Update") then return end
|
||||
|
||||
if ent:IsPlayer() then ply:ChatPrint( "That is a player !" ) return end
|
||||
|
||||
local content = PermaProps.PPGetEntTable(ent)
|
||||
if not content then return end
|
||||
|
||||
PermaProps.SQL.Query("UPDATE permaprops set content = ".. sql.SQLStr(util.TableToJSON(content)) .." WHERE id = ".. ent.PermaProps_ID .." AND map = ".. sql.SQLStr(game.GetMap()) .. ";")
|
||||
|
||||
local new_ent = PermaProps.PPEntityFromTable(content, ent.PermaProps_ID)
|
||||
if !new_ent or !new_ent:IsValid() then return end
|
||||
|
||||
PermaProps.SparksEffect( ent )
|
||||
|
||||
ply:ChatPrint("You updated the " .. ent:GetClass() .. " in the database.")
|
||||
|
||||
ent:Remove()
|
||||
|
||||
|
||||
else
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function TOOL.BuildCPanel(panel)
|
||||
|
||||
panel:AddControl("Header",{Text = "PermaProps", Description = "PermaProps\n\nSaves entities across map changes\n"})
|
||||
panel:AddControl("Button",{Label = "Open Configuration Menu", Command = "pp_cfg_open"})
|
||||
|
||||
end
|
||||
|
||||
function TOOL:DrawToolScreen(width, height)
|
||||
|
||||
if SERVER then return end
|
||||
|
||||
surface.SetDrawColor(17, 148, 240, 255)
|
||||
surface.DrawRect(0, 0, 256, 256)
|
||||
|
||||
surface.SetFont("PermaPropsToolScreenFont")
|
||||
local w, h = surface.GetTextSize(" ")
|
||||
surface.SetFont("PermaPropsToolScreenSubFont")
|
||||
local w2, h2 = surface.GetTextSize(" ")
|
||||
|
||||
draw.SimpleText("PermaProps", "PermaPropsToolScreenFont", 128, 100, Color(224, 224, 224, 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, Color(17, 148, 240, 255), 4)
|
||||
draw.SimpleText("By Malboro", "PermaPropsToolScreenSubFont", 128, 128 + (h + h2) / 2 - 4, Color(224, 224, 224, 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, Color(17, 148, 240, 255), 4)
|
||||
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,285 @@
|
||||
if ( SERVER ) then
|
||||
AddCSLuaFile( "shared.lua" )
|
||||
|
||||
util.AddNetworkString("anterg0_guitarTab")
|
||||
util.AddNetworkString("anterg0_guitarPlaySong")
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
SWEP.DrawCrosshair = false
|
||||
SWEP.PrintName = "Русская гитара"
|
||||
end
|
||||
|
||||
SWEP.Base = "weapon_base"
|
||||
|
||||
SWEP.PrintName = "Русская гитара"
|
||||
SWEP.Slot = 2
|
||||
SWEP.SlotPos = 4
|
||||
SWEP.DrawAmmo = false
|
||||
SWEP.ViewModel = "models/weapons/tayley/v_guitar.mdl"
|
||||
SWEP.HoldType = "slam"
|
||||
SWEP.ViewModelFOV = 70
|
||||
SWEP.ViewModelFlip = false
|
||||
SWEP.WorldModel = "models/anterg0_Guitar/marauder_guitar.mdl"
|
||||
-- Other settings
|
||||
SWEP.Weight = 5
|
||||
SWEP.AutoSwitchTo = false
|
||||
SWEP.AutoSwitchFrom = false
|
||||
SWEP.Spawnable = true
|
||||
SWEP.AdminSpawnable = true
|
||||
|
||||
-- SWEP info
|
||||
SWEP.Author = "DuckFlit"
|
||||
SWEP.Category = "[FT] Атмосфера"
|
||||
SWEP.Instructions = "Левый клик дабы играть случайную песню. Правый клик чтобы выбрать песню."
|
||||
|
||||
-- Primary fire settings
|
||||
SWEP.Primary.Damage = -1
|
||||
SWEP.Primary.NumShots = -1
|
||||
SWEP.Primary.Delay = 2
|
||||
SWEP.Primary.ClipSize = -1
|
||||
SWEP.Primary.DefaultClip = 0
|
||||
SWEP.Primary.Tracer = -1
|
||||
SWEP.Primary.Force = -1
|
||||
SWEP.Primary.TakeAmmoPerBullet = false
|
||||
SWEP.Primary.Automatic = false
|
||||
SWEP.Primary.Ammo = "none"
|
||||
|
||||
SWEP.ReloadTimer = 1
|
||||
|
||||
local songsTbl = {
|
||||
|
||||
[1] = {"Спецназ - Денис Майданов", "weapons/guitar/ad.mp3"},
|
||||
[2] = {"Мужество Ведёт на Небеса", "weapons/guitar/ac.mp3"},
|
||||
[3] = {"Витязи", "weapons/guitar/ag.mp3"},
|
||||
[4] = {"Чёрный Октябрь ", "weapons/guitar/aj.mp3"},
|
||||
[5] = {"За что мы пьём", "weapons/guitar/ak.mp3"},
|
||||
[6] = {"Набирает высоту", "weapons/guitar/ar.mp3"},
|
||||
[7] = {"Стрим - Песня Бритвы", "weapons/guitar/ay.mp3"},
|
||||
[8] = {"Простите меня", "weapons/guitar/am.mp3"},
|
||||
[9] = {"Владимир Высоцкий - Солдаты Группы", "weapons/guitar/ap.mp3"},
|
||||
[10] = {"ГСН-Российскийспецназ", "weapons/guitar/fa.mp3"},
|
||||
[11] = {"Егор Авдеев - 333 с ночи до зари", "weapons/guitar/fr.mp3"},
|
||||
[12] = {"Николай Анисимов - По самому прямому назначению", "weapons/guitar/fy.mp3"},
|
||||
[13] = {"UKRAINE - Гімн Українскої Артилерії", "weapons/guitar/jj.mp3"},
|
||||
}
|
||||
|
||||
if CLIENT then
|
||||
|
||||
SWEP.WepSelectIcon = surface.GetTextureID("vgui/selection/guitar_ico")
|
||||
function SWEP:DrawWeaponSelection(x, y, wide, tall, alpha)
|
||||
x = x + wide / 2
|
||||
y = y + tall / 2
|
||||
|
||||
tall = tall * 0.75
|
||||
|
||||
x = x - tall / 2
|
||||
y = y - tall / 2 - 10
|
||||
|
||||
surface.SetDrawColor(255, 255, 255, alpha)
|
||||
surface.SetTexture(self.WepSelectIcon)
|
||||
|
||||
surface.DrawTexturedRect(x, y, tall, tall)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Initialize()
|
||||
self:SetWeaponHoldType(self.HoldType)
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
self.Weapon:EmitSound(Sound("weapons/guitar/squak2.mp3"))
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:OnRemove()
|
||||
self:Holster()
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
self:SetNextPrimaryFire(CurTime() + self.Primary.Delay);
|
||||
self.Weapon:EmitSound(Sound("weapons/guitar/squak2.mp3"), 50, math.random(85,100), 1, CHAN_SWEP)
|
||||
|
||||
self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK )
|
||||
self.Owner:SetAnimation( PLAYER_ATTACK1 )
|
||||
if SERVER then
|
||||
local songChoice = math.random(1, #songsTbl)
|
||||
self.Weapon:SetNWBool("guitar_isPlaying", true)
|
||||
self.Weapon:SetNWInt("guitar_songNum", songChoice)
|
||||
end
|
||||
timer.Simple(0.5, function()
|
||||
local song = songsTbl[self.Weapon:GetNWInt("guitar_songNum")][2]
|
||||
if(song == nil) then
|
||||
song = ""
|
||||
end
|
||||
self.Weapon:EmitSound(song, 80, 100, 1, CHAN_SWEP)
|
||||
end)
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
local ply = self.Owner
|
||||
if SERVER then
|
||||
net.Start("anterg0_guitarTab")
|
||||
net.Send(ply)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function SWEP:Think()
|
||||
end
|
||||
|
||||
function SWEP:Reload()
|
||||
if(self.Weapon:GetNextSecondaryFire() <= CurTime() ) then
|
||||
self.Weapon:SetNextSecondaryFire(CurTime() + self.ReloadTimer)
|
||||
self.Weapon:SetNWBool("guitar_isPlaying", false)
|
||||
self.Weapon:EmitSound(Sound("weapons/guitar/squak2.mp3"), 50, math.random(85,100), 1, CHAN_SWEP)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:Deploy()
|
||||
self:SetWeaponHoldType(self.HoldType)
|
||||
return true
|
||||
end
|
||||
|
||||
SWEP.RenderGroup = RENDERGROUP_BOTH
|
||||
|
||||
function SWEP:DrawWorldModelTranslucent()
|
||||
self:DrawModel()
|
||||
|
||||
if self.time == nil then self.time = 0 end
|
||||
surface.SetFont("Trebuchet24")
|
||||
local tag = "Now playing ... "
|
||||
if(self.Weapon:GetNWInt("guitar_songNum") ~= 0) then
|
||||
songName = songsTbl[self.Weapon:GetNWInt("guitar_songNum")][1]
|
||||
tag = "Now playing ... " .. songName
|
||||
end
|
||||
local textwidth = surface.GetTextSize(tag)
|
||||
|
||||
if LocalPlayer():GetPos():Distance(self:GetPos()) < 550 then
|
||||
if(self.Weapon:GetNWBool("guitar_isPlaying") == false) then return end
|
||||
local alpha = (LocalPlayer():GetPos():Distance(self:GetPos()) / 100.0)
|
||||
alpha = math.Clamp(2.5 - alpha, 0 ,1)
|
||||
local a = Angle(0,0,0)
|
||||
a:RotateAroundAxis(Vector(1,0,0),90)
|
||||
a.y = LocalPlayer():GetAngles().y - 90
|
||||
cam.Start3D2D(self:GetPos() + Vector(0,0,45 + (math.sin(self.time*0.5)*2)), a , 0.15)
|
||||
draw.SimpleText(tag,"Trebuchet24", -textwidth*0.5,0,Color(205,225,255,255*alpha) , 0 , 1)
|
||||
cam.End3D2D()
|
||||
end
|
||||
|
||||
self.time = self.time + FrameTime()
|
||||
end
|
||||
|
||||
net.Receive("anterg0_guitarTab", function(len, ply)
|
||||
local songNum = net.ReadFloat()
|
||||
|
||||
local wep = ply:GetActiveWeapon()
|
||||
if(wep:GetClass() == "guitar") then
|
||||
wep:SetNWBool("guitar_isPlaying", true)
|
||||
wep:SetNWInt("guitar_songNum", songNum)
|
||||
wep:EmitSound( songsTbl[songNum][2], 80, 100, 1, CHAN_SWEP)
|
||||
|
||||
end
|
||||
end)
|
||||
|
||||
// DERMA STUFF
|
||||
|
||||
if CLIENT then
|
||||
|
||||
local PANEL = {}
|
||||
|
||||
function PANEL:Init()
|
||||
local w = ScrW()*0.3
|
||||
local h = ScrH()*0.4
|
||||
self:SetSize(w, h)
|
||||
self:SetPos(ScrW()*0.7, ScrH()/2 - (h/2))
|
||||
|
||||
self:MakePopup()
|
||||
self:SetDeleteOnClose(true)
|
||||
self:SetDraggable(true)
|
||||
self:ShowCloseButton(true)
|
||||
self:SetTitle("")
|
||||
|
||||
self.Paint = function(_, w, h)
|
||||
draw.RoundedBox(0, 0, 0, w, h, Color(0, 0, 0, 225))
|
||||
end
|
||||
|
||||
self.MusicOptions = vgui.Create("anterg0_Guitar:DScroll", self)
|
||||
|
||||
end
|
||||
|
||||
vgui.Register("anterg0_Guitar:Menu", PANEL, "DFrame")
|
||||
|
||||
net.Receive("anterg0_guitarTab", function()
|
||||
if(IsValid(guitPanel)) then return end
|
||||
guitPanel = vgui.Create("anterg0_Guitar:Menu")
|
||||
end)
|
||||
|
||||
// MUSIC
|
||||
local PANEL = {}
|
||||
|
||||
function PANEL:Init()
|
||||
local x,y = self:GetParent():GetSize()
|
||||
self:SetSize(x, y + 60)
|
||||
self:SetPos(0, 30)
|
||||
|
||||
--Modify Scroll Bar--
|
||||
local sbar = self:GetVBar()
|
||||
sbar:SetHideButtons(true)
|
||||
sbar.Paint = function(_, w, h)
|
||||
draw.RoundedBox(0, 0, 0, (w/2), h, Color(0, 0, 0, 225))
|
||||
end
|
||||
|
||||
sbar.btnGrip.Paint = function(_, w, h)
|
||||
draw.RoundedBox(0, 0, 0, (w/2), h, Color(255, 255, 255, 255))
|
||||
end
|
||||
|
||||
self.Paint = function(_, w, h)
|
||||
draw.RoundedBox(0, 0, 0, w, h, Color(0, 0, 0, 0))
|
||||
end
|
||||
|
||||
for k, v in ipairs(songsTbl) do
|
||||
local btn = self:Add("DButton")
|
||||
btn:Dock(TOP)
|
||||
btn:DockMargin(10, 0, 10, 10)
|
||||
btn:SetSize(0, 25)
|
||||
btn:SetText("")
|
||||
btn.HoverLerp = 0
|
||||
btn.Paint = function(_, w, h)
|
||||
if btn:IsHovered() then
|
||||
btn.HoverLerp = Lerp( FrameTime() * 10, btn.HoverLerp, 1 )
|
||||
else
|
||||
btn.HoverLerp = Lerp( FrameTime() * 3, btn.HoverLerp, 0.1)
|
||||
end
|
||||
draw.RoundedBox(0, 0, 0, w, h, Color(50,50,50,255*btn.HoverLerp))
|
||||
draw.SimpleText(v[1], "Trebuchet18", w/2, 2, Color(255,255,255, 255), 1, 0)
|
||||
end
|
||||
|
||||
btn.PaintOver = function(_, w, h)
|
||||
surface.SetDrawColor(Color(255, 255, 255, 125), 1, 1)
|
||||
surface.DrawOutlinedRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
btn.DoClick = function()
|
||||
local wep = LocalPlayer():GetActiveWeapon()
|
||||
if(wep ~= nil or IsValid(wep)) then
|
||||
LocalPlayer():EmitSound(Sound("weapons/guitar/squak2.mp3") )
|
||||
wep:EmitSound( v[2], 100, 100, 1, CHAN_SWEP )
|
||||
end
|
||||
net.Start("anterg0_guitarTab")
|
||||
net.WriteFloat(k)
|
||||
net.SendToServer()
|
||||
|
||||
self:GetParent():Close()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self:Dock(FILL)
|
||||
self:DockMargin(0, 0, 0, 10)
|
||||
end
|
||||
|
||||
vgui.Register("anterg0_Guitar:DScroll", PANEL, "DScrollPanel")
|
||||
end
|
||||
@@ -0,0 +1,195 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
SWEP.Base = "weapon_base"
|
||||
|
||||
if CLIENT then
|
||||
SWEP.DrawWeaponInfoBox = false
|
||||
SWEP.BounceWeaponIcon = false
|
||||
end
|
||||
|
||||
SWEP.PrintName = "Consumable"
|
||||
SWEP.Author = "Helix"
|
||||
SWEP.Purpose = "Base consumable SWEP with animations"
|
||||
SWEP.Category = "Helix"
|
||||
|
||||
SWEP.ViewModelFOV = 70
|
||||
SWEP.ViewModel = "models/weapons/v_hands.mdl"
|
||||
SWEP.WorldModel = ""
|
||||
SWEP.UseHands = true
|
||||
SWEP.DrawCrosshair = false
|
||||
|
||||
SWEP.Spawnable = false
|
||||
SWEP.AutoSwitchTo = false
|
||||
SWEP.AutoSwitchFrom = false
|
||||
SWEP.Slot = 5
|
||||
SWEP.SlotPos = 0
|
||||
|
||||
SWEP.SwayScale = 0
|
||||
SWEP.BobScale = 0
|
||||
|
||||
SWEP.Primary.ClipSize = -1
|
||||
SWEP.Primary.DefaultClip = -1
|
||||
SWEP.Primary.Automatic = false
|
||||
SWEP.Primary.Ammo = "none"
|
||||
|
||||
SWEP.Secondary.ClipSize = -1
|
||||
SWEP.Secondary.DefaultClip = -1
|
||||
SWEP.Secondary.Automatic = false
|
||||
SWEP.Secondary.Ammo = "none"
|
||||
|
||||
-- Параметры предмета (устанавливаются при выдаче)
|
||||
SWEP.ItemHunger = 0
|
||||
SWEP.ItemThirst = 0
|
||||
SWEP.ItemAlcohol = 0
|
||||
SWEP.ItemEmpty = false
|
||||
SWEP.ItemType = "food" -- "food", "drink", "consumable"
|
||||
|
||||
function SWEP:Initialize()
|
||||
self:SetHoldType("slam")
|
||||
self.Consuming = false
|
||||
end
|
||||
|
||||
function SWEP:SetItemData(hunger, thirst, alcohol, empty, itemType, viewModel)
|
||||
self.ItemHunger = hunger or 0
|
||||
self.ItemThirst = thirst or 0
|
||||
self.ItemAlcohol = alcohol or 0
|
||||
self.ItemEmpty = empty or false
|
||||
self.ItemType = itemType or "food"
|
||||
|
||||
-- Устанавливаем viewmodel, если указана
|
||||
if viewModel and viewModel != "" then
|
||||
self.ViewModel = viewModel
|
||||
end
|
||||
print(self.ViewModel)
|
||||
end
|
||||
|
||||
function SWEP:Deploy()
|
||||
local owner = self:GetOwner()
|
||||
|
||||
if not IsValid(owner) or not owner:IsPlayer() then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Проигрываем idle анимацию
|
||||
local vm = owner:GetViewModel()
|
||||
if IsValid(vm) then
|
||||
local idleSeq = vm:LookupSequence("idle")
|
||||
if idleSeq > 0 then
|
||||
vm:SendViewModelMatchingSequence(idleSeq)
|
||||
end
|
||||
end
|
||||
|
||||
-- Начинаем процесс употребления
|
||||
self.Consuming = true
|
||||
self:InitializeConsumable()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:InitializeConsumable()
|
||||
local owner = self:GetOwner()
|
||||
if not IsValid(self) or not IsValid(owner) or not owner:IsPlayer() then return end
|
||||
|
||||
-- Проигрываем анимацию use
|
||||
local vm = owner:GetViewModel()
|
||||
local sequenceDuration = 3
|
||||
|
||||
if IsValid(vm) then
|
||||
local useSeq = vm:LookupSequence("use")
|
||||
if useSeq > 0 then
|
||||
vm:SendViewModelMatchingSequence(useSeq)
|
||||
sequenceDuration = vm:SequenceDuration(useSeq)
|
||||
end
|
||||
end
|
||||
|
||||
-- Применяем эффекты в середине анимации
|
||||
timer.Simple(sequenceDuration * 0.5, function()
|
||||
if IsValid(self) and IsValid(owner) and owner:Alive() then
|
||||
self:ApplyEffects(owner)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Завершаем употребление и удаляем оружие
|
||||
timer.Simple(sequenceDuration, function()
|
||||
if IsValid(self) and IsValid(owner) and owner:Alive() then
|
||||
self.Consuming = false
|
||||
|
||||
if SERVER then
|
||||
owner:StripWeapon(self:GetClass())
|
||||
|
||||
local prev = owner:GetPreviousWeapon() or ""
|
||||
if isentity(prev) and IsValid(prev) then
|
||||
owner:SelectWeapon(prev:GetClass())
|
||||
elseif isstring(prev) and prev != "" then
|
||||
owner:SelectWeapon(prev)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function SWEP:ApplyEffects(owner)
|
||||
if not SERVER then return end
|
||||
if not IsValid(owner) then return end
|
||||
|
||||
local char = owner:GetCharacter()
|
||||
if not char then return end
|
||||
|
||||
-- Получаем текущие значения
|
||||
local hunger = char:GetData("hunger", 100)
|
||||
local thirst = char:GetData("thirst", 100)
|
||||
|
||||
-- Применяем изменения (SetHunger и SetThirst автоматически обновляют состояние)
|
||||
owner:SetHunger(hunger + self.ItemHunger)
|
||||
owner:SetThirst(thirst + self.ItemThirst)
|
||||
|
||||
-- Алкоголь
|
||||
if self.ItemAlcohol > 0 then
|
||||
owner:IncreaseDrunkLevel(self.ItemAlcohol)
|
||||
end
|
||||
|
||||
-- Пустая тара
|
||||
if self.ItemEmpty then
|
||||
local inv = char:GetInventory()
|
||||
if inv then
|
||||
inv:Add(self.ItemEmpty)
|
||||
end
|
||||
end
|
||||
|
||||
-- Звук употребления из STALKER 2 Consumables
|
||||
if self.ItemType == "drink" then
|
||||
owner:EmitSound("Stalker2.Drink")
|
||||
elseif self.ItemType == "food" then
|
||||
owner:EmitSound("Stalker2.Eat")
|
||||
elseif self.ItemType == "medical" then
|
||||
owner:EmitSound("Stalker2.Healing")
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
-- Ничего не делаем
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
-- Ничего не делаем
|
||||
end
|
||||
|
||||
function SWEP:Reload()
|
||||
-- Ничего не делаем
|
||||
end
|
||||
|
||||
function SWEP:Think()
|
||||
-- Можно добавить дополнительную логику
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
-- Блокируем переключение во время употребления
|
||||
if self.Consuming then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:OnRemove()
|
||||
-- Очистка
|
||||
end
|
||||
441
garrysmod/gamemodes/militaryrp/entities/weapons/ix_hands.lua
Normal file
441
garrysmod/gamemodes/militaryrp/entities/weapons/ix_hands.lua
Normal file
@@ -0,0 +1,441 @@
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
if (CLIENT) then
|
||||
SWEP.PrintName = "Hands"
|
||||
SWEP.Slot = 0
|
||||
SWEP.SlotPos = 1
|
||||
SWEP.DrawAmmo = false
|
||||
SWEP.DrawCrosshair = true
|
||||
end
|
||||
|
||||
SWEP.Author = "Chessnut"
|
||||
SWEP.Instructions = [[Primary Fire: Throw/Punch
|
||||
Secondary Fire: Knock/Pickup
|
||||
Secondary Fire + Mouse: Rotate Object
|
||||
Reload: Drop]]
|
||||
SWEP.Purpose = "Hitting things and knocking on doors."
|
||||
SWEP.Drop = false
|
||||
|
||||
SWEP.ViewModelFOV = 45
|
||||
SWEP.ViewModelFlip = false
|
||||
SWEP.AnimPrefix = "rpg"
|
||||
|
||||
SWEP.ViewTranslation = 4
|
||||
if CLIENT then
|
||||
SWEP.NextAllowedPlayRateChange = 0
|
||||
end
|
||||
|
||||
SWEP.Primary.ClipSize = -1
|
||||
SWEP.Primary.DefaultClip = -1
|
||||
SWEP.Primary.Automatic = false
|
||||
SWEP.Primary.Ammo = ""
|
||||
SWEP.Primary.Damage = 5
|
||||
SWEP.Primary.Delay = 0.75
|
||||
|
||||
SWEP.Secondary.ClipSize = -1
|
||||
SWEP.Secondary.DefaultClip = 0
|
||||
SWEP.Secondary.Automatic = false
|
||||
SWEP.Secondary.Ammo = ""
|
||||
SWEP.Secondary.Delay = 0.5
|
||||
|
||||
SWEP.ViewModel = ""
|
||||
SWEP.WorldModel = ""
|
||||
|
||||
SWEP.UseHands = true
|
||||
SWEP.LowerAngles = Angle(0, 5, -14)
|
||||
SWEP.LowerAngles2 = Angle(0, 5, -19)
|
||||
SWEP.KnockViewPunchAngle = Angle(-1.3, 1.8, 0)
|
||||
|
||||
SWEP.FireWhenLowered = true
|
||||
SWEP.HoldType = "normal"
|
||||
|
||||
SWEP.holdDistance = 64
|
||||
SWEP.maxHoldDistance = 96 -- how far away the held object is allowed to travel before forcefully dropping
|
||||
SWEP.maxHoldStress = 4000 -- how much stress the held object can undergo before forcefully dropping
|
||||
|
||||
-- luacheck: globals ACT_VM_FISTS_DRAW ACT_VM_FISTS_HOLSTER
|
||||
ACT_VM_FISTS_DRAW = 2
|
||||
ACT_VM_FISTS_HOLSTER = 1
|
||||
|
||||
function SWEP:Initialize()
|
||||
self:SetHoldType(self.HoldType)
|
||||
|
||||
self.lastHand = 0
|
||||
self.maxHoldDistanceSquared = self.maxHoldDistance ^ 2
|
||||
self.heldObjectAngle = Angle(angle_zero)
|
||||
end
|
||||
|
||||
if (CLIENT) then
|
||||
function SWEP:DoDrawCrosshair(x, y)
|
||||
surface.SetDrawColor(255, 255, 255, 66)
|
||||
surface.DrawRect(x - 2, y - 2, 4, 4)
|
||||
end
|
||||
|
||||
hook.Add("CreateMove", "ixHandsCreateMove", function(cmd)
|
||||
if (LocalPlayer():GetLocalVar("bIsHoldingObject", false) and cmd:KeyDown(IN_ATTACK2)) then
|
||||
cmd:ClearMovement()
|
||||
local angle = RenderAngles()
|
||||
angle.z = 0
|
||||
cmd:SetViewAngles(angle)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function SWEP:Deploy()
|
||||
if (!IsValid(self:GetOwner())) then
|
||||
return
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
local viewModel = self:GetOwner():GetViewModel()
|
||||
if IsValid(viewModel) then
|
||||
viewModel:SetNoDraw(true)
|
||||
end
|
||||
end
|
||||
|
||||
self:DropObject()
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:Precache()
|
||||
util.PrecacheSound("npc/vort/claw_swing1.wav")
|
||||
util.PrecacheSound("npc/vort/claw_swing2.wav")
|
||||
util.PrecacheSound("physics/plastic/plastic_box_impact_hard1.wav")
|
||||
util.PrecacheSound("physics/plastic/plastic_box_impact_hard2.wav")
|
||||
util.PrecacheSound("physics/plastic/plastic_box_impact_hard3.wav")
|
||||
util.PrecacheSound("physics/plastic/plastic_box_impact_hard4.wav")
|
||||
util.PrecacheSound("physics/wood/wood_crate_impact_hard2.wav")
|
||||
util.PrecacheSound("physics/wood/wood_crate_impact_hard3.wav")
|
||||
end
|
||||
|
||||
function SWEP:OnReloaded()
|
||||
self.maxHoldDistanceSquared = self.maxHoldDistance ^ 2
|
||||
self:DropObject()
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
if (!IsValid(self:GetOwner())) then
|
||||
return
|
||||
end
|
||||
|
||||
local viewModel = self:GetOwner():GetViewModel()
|
||||
|
||||
if (IsValid(viewModel)) then
|
||||
viewModel:SetPlaybackRate(1)
|
||||
viewModel:ResetSequence(ACT_VM_FISTS_HOLSTER)
|
||||
if CLIENT then
|
||||
self.NextAllowedPlayRateChange = CurTime() + viewModel:SequenceDuration()
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:Think()
|
||||
if (!IsValid(self:GetOwner())) then
|
||||
return
|
||||
end
|
||||
|
||||
if (CLIENT) then
|
||||
local viewModel = self:GetOwner():GetViewModel()
|
||||
|
||||
if (IsValid(viewModel) and self.NextAllowedPlayRateChange < CurTime()) then
|
||||
viewModel:SetPlaybackRate(1)
|
||||
end
|
||||
else
|
||||
if (self:IsHoldingObject()) then
|
||||
local physics = self:GetHeldPhysicsObject()
|
||||
local bIsRagdoll = self.heldEntity:IsRagdoll()
|
||||
local holdDistance = bIsRagdoll and self.holdDistance * 0.5 or self.holdDistance
|
||||
local targetLocation = self:GetOwner():GetShootPos() + self:GetOwner():GetForward() * holdDistance
|
||||
|
||||
if (bIsRagdoll) then
|
||||
targetLocation.z = math.min(targetLocation.z, self:GetOwner():GetShootPos().z - 32)
|
||||
end
|
||||
|
||||
if (!IsValid(physics)) then
|
||||
self:DropObject()
|
||||
return
|
||||
end
|
||||
|
||||
if (physics:GetPos():DistToSqr(targetLocation) > self.maxHoldDistanceSquared) then
|
||||
self:DropObject()
|
||||
else
|
||||
local physicsObject = self.holdEntity:GetPhysicsObject()
|
||||
local currentPlayerAngles = self:GetOwner():EyeAngles()
|
||||
local client = self:GetOwner()
|
||||
|
||||
if (client:KeyDown(IN_ATTACK2)) then
|
||||
local cmd = client:GetCurrentCommand()
|
||||
self.heldObjectAngle:RotateAroundAxis(currentPlayerAngles:Forward(), cmd:GetMouseX() / 15)
|
||||
self.heldObjectAngle:RotateAroundAxis(currentPlayerAngles:Right(), cmd:GetMouseY() / 15)
|
||||
end
|
||||
|
||||
self.lastPlayerAngles = self.lastPlayerAngles or currentPlayerAngles
|
||||
self.heldObjectAngle.y = self.heldObjectAngle.y - math.AngleDifference(self.lastPlayerAngles.y, currentPlayerAngles.y)
|
||||
self.lastPlayerAngles = currentPlayerAngles
|
||||
|
||||
physicsObject:Wake()
|
||||
physicsObject:ComputeShadowControl({
|
||||
secondstoarrive = 0.01,
|
||||
pos = targetLocation,
|
||||
angle = self.heldObjectAngle,
|
||||
maxangular = 256,
|
||||
maxangulardamp = 10000,
|
||||
maxspeed = 256,
|
||||
maxspeeddamp = 10000,
|
||||
dampfactor = 0.8,
|
||||
teleportdistance = self.maxHoldDistance * 0.75,
|
||||
deltatime = FrameTime()
|
||||
})
|
||||
|
||||
if (physics:GetStress() > self.maxHoldStress) then
|
||||
self:DropObject()
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Prevents the camera from getting stuck when the object that the client is holding gets deleted.
|
||||
if(!IsValid(self.heldEntity) and self:GetOwner():GetLocalVar("bIsHoldingObject", true)) then
|
||||
self:GetOwner():SetLocalVar("bIsHoldingObject", false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetHeldPhysicsObject()
|
||||
return IsValid(self.heldEntity) and self.heldEntity:GetPhysicsObject() or nil
|
||||
end
|
||||
|
||||
function SWEP:CanHoldObject(entity)
|
||||
local physics = entity:GetPhysicsObject()
|
||||
|
||||
return IsValid(physics) and
|
||||
(physics:GetMass() <= ix.config.Get("maxHoldWeight", 100) and physics:IsMoveable()) and
|
||||
!self:IsHoldingObject() and
|
||||
!IsValid(entity.ixHeldOwner) and
|
||||
hook.Run("CanPlayerHoldObject", self:GetOwner(), entity)
|
||||
end
|
||||
|
||||
function SWEP:IsHoldingObject()
|
||||
return IsValid(self.heldEntity) and
|
||||
IsValid(self.heldEntity.ixHeldOwner) and
|
||||
self.heldEntity.ixHeldOwner == self:GetOwner()
|
||||
end
|
||||
|
||||
function SWEP:PickupObject(entity)
|
||||
if (self:IsHoldingObject() or
|
||||
!IsValid(entity) or
|
||||
!IsValid(entity:GetPhysicsObject())) then
|
||||
return
|
||||
end
|
||||
|
||||
local physics = entity:GetPhysicsObject()
|
||||
physics:EnableGravity(false)
|
||||
physics:AddGameFlag(FVPHYSICS_PLAYER_HELD)
|
||||
|
||||
entity.ixHeldOwner = self:GetOwner()
|
||||
entity.ixCollisionGroup = entity:GetCollisionGroup()
|
||||
entity:StartMotionController()
|
||||
entity:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
|
||||
self.heldObjectAngle = entity:GetAngles()
|
||||
self.heldEntity = entity
|
||||
|
||||
self.holdEntity = ents.Create("prop_physics")
|
||||
self.holdEntity:SetPos(self.heldEntity:LocalToWorld(self.heldEntity:OBBCenter()))
|
||||
self.holdEntity:SetAngles(self.heldEntity:GetAngles())
|
||||
self.holdEntity:SetModel("models/weapons/w_bugbait.mdl")
|
||||
self.holdEntity:SetOwner(self:GetOwner())
|
||||
|
||||
self.holdEntity:SetNoDraw(true)
|
||||
self.holdEntity:SetNotSolid(true)
|
||||
self.holdEntity:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
self.holdEntity:DrawShadow(false)
|
||||
|
||||
self.holdEntity:Spawn()
|
||||
|
||||
local trace = self:GetOwner():GetEyeTrace()
|
||||
local physicsObject = self.holdEntity:GetPhysicsObject()
|
||||
|
||||
if (IsValid(physicsObject)) then
|
||||
physicsObject:SetMass(2048)
|
||||
physicsObject:SetDamping(0, 1000)
|
||||
physicsObject:EnableGravity(false)
|
||||
physicsObject:EnableCollisions(false)
|
||||
physicsObject:EnableMotion(false)
|
||||
end
|
||||
|
||||
if (trace.Entity:IsRagdoll()) then
|
||||
local tracedEnt = trace.Entity
|
||||
self.holdEntity:SetPos(tracedEnt:GetBonePosition(tracedEnt:TranslatePhysBoneToBone(trace.PhysicsBone)))
|
||||
end
|
||||
|
||||
self.constraint = constraint.Weld(self.holdEntity, self.heldEntity, 0,
|
||||
trace.Entity:IsRagdoll() and trace.PhysicsBone or 0, 0, true, true)
|
||||
end
|
||||
|
||||
function SWEP:DropObject(bThrow)
|
||||
if (!IsValid(self.heldEntity) or self.heldEntity.ixHeldOwner != self:GetOwner()) then
|
||||
return
|
||||
end
|
||||
|
||||
self.lastPlayerAngles = nil
|
||||
self:GetOwner():SetLocalVar("bIsHoldingObject", false)
|
||||
|
||||
self.constraint:Remove()
|
||||
self.holdEntity:Remove()
|
||||
|
||||
self.heldEntity:StopMotionController()
|
||||
self.heldEntity:SetCollisionGroup(self.heldEntity.ixCollisionGroup or COLLISION_GROUP_NONE)
|
||||
|
||||
local physics = self:GetHeldPhysicsObject()
|
||||
physics:EnableGravity(true)
|
||||
physics:Wake()
|
||||
physics:ClearGameFlag(FVPHYSICS_PLAYER_HELD)
|
||||
|
||||
if (bThrow) then
|
||||
timer.Simple(0, function()
|
||||
if (IsValid(physics) and IsValid(self:GetOwner())) then
|
||||
physics:AddGameFlag(FVPHYSICS_WAS_THROWN)
|
||||
physics:ApplyForceCenter(self:GetOwner():GetAimVector() * ix.config.Get("throwForce", 732))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
self.heldEntity.ixHeldOwner = nil
|
||||
self.heldEntity.ixCollisionGroup = nil
|
||||
self.heldEntity = nil
|
||||
end
|
||||
|
||||
function SWEP:PlayPickupSound(surfaceProperty)
|
||||
local result = "Flesh.ImpactSoft"
|
||||
|
||||
if (surfaceProperty != nil) then
|
||||
local surfaceName = util.GetSurfacePropName(surfaceProperty)
|
||||
local soundName = surfaceName:gsub("^metal$", "SolidMetal") .. ".ImpactSoft"
|
||||
|
||||
if (sound.GetProperties(soundName)) then
|
||||
result = soundName
|
||||
end
|
||||
end
|
||||
|
||||
self:GetOwner():EmitSound(result, 75, 100, 40)
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
if (!IsFirstTimePredicted() or CLIENT) then
|
||||
return
|
||||
end
|
||||
|
||||
self:DropObject()
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:OnRemove()
|
||||
if (SERVER) then
|
||||
self:DropObject()
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:OwnerChanged()
|
||||
if (SERVER) then
|
||||
self:DropObject()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function SWEP:DoPunchAnimation()
|
||||
self.lastHand = math.abs(1 - self.lastHand)
|
||||
local sequence = 3 + self.lastHand -- punch anims
|
||||
local viewModel = self:GetOwner():GetViewModel()
|
||||
if (IsValid(viewModel)) then
|
||||
viewModel:SetPlaybackRate(0.5)
|
||||
viewModel:SetSequence(sequence)
|
||||
if CLIENT then
|
||||
self.NextAllowedPlayRateChange = CurTime() + viewModel:SequenceDuration() * 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
if (!IsFirstTimePredicted()) then
|
||||
return
|
||||
end
|
||||
|
||||
if (SERVER and self:IsHoldingObject()) then
|
||||
self:DropObject(true)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
if (!IsFirstTimePredicted()) then
|
||||
return
|
||||
end
|
||||
|
||||
local data = {}
|
||||
data.start = self:GetOwner():GetShootPos()
|
||||
data.endpos = data.start + self:GetOwner():GetAimVector() * 84
|
||||
data.filter = {self, self:GetOwner()}
|
||||
local trace = util.TraceLine(data)
|
||||
local entity = trace.Entity
|
||||
|
||||
if CLIENT then
|
||||
local viewModel = self:GetOwner():GetViewModel()
|
||||
|
||||
if (IsValid(viewModel)) then
|
||||
viewModel:SetPlaybackRate(0.5)
|
||||
if CLIENT then
|
||||
self.NextAllowedPlayRateChange = CurTime() + viewModel:SequenceDuration() * 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
if (self:IsHoldingObject()) then
|
||||
self:DropObject()
|
||||
return
|
||||
end
|
||||
|
||||
if (IsValid(entity)) then
|
||||
if (entity:IsDoor()) then
|
||||
if (hook.Run("CanPlayerKnock", self:GetOwner(), entity) == false) then
|
||||
return
|
||||
end
|
||||
|
||||
self:GetOwner():ViewPunch(self.KnockViewPunchAngle)
|
||||
self:GetOwner():EmitSound("physics/wood/wood_crate_impact_hard"..math.random(2, 3)..".wav")
|
||||
self:GetOwner():SetAnimation(PLAYER_ATTACK1)
|
||||
|
||||
self:DoPunchAnimation()
|
||||
self:SetNextSecondaryFire(CurTime() + 0.4)
|
||||
self:SetNextPrimaryFire(CurTime() + 1)
|
||||
elseif (entity:IsPlayer() and ix.config.Get("allowPush", true)) then
|
||||
local direction = self:GetOwner():GetAimVector() * (300 + (self:GetOwner():GetCharacter():GetAttribute("str", 0) * 3))
|
||||
direction.z = 0
|
||||
entity:SetVelocity(direction)
|
||||
|
||||
self:GetOwner():EmitSound("Weapon_Crossbow.BoltHitBody")
|
||||
self:SetNextSecondaryFire(CurTime() + 1.5)
|
||||
self:SetNextPrimaryFire(CurTime() + 1.5)
|
||||
elseif (!entity:IsNPC() and self:CanHoldObject(entity)) then
|
||||
self:GetOwner():SetLocalVar("bIsHoldingObject", true)
|
||||
self:PickupObject(entity)
|
||||
self:PlayPickupSound(trace.SurfaceProps)
|
||||
self:SetNextSecondaryFire(CurTime() + self.Secondary.Delay)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:Reload()
|
||||
if (!IsFirstTimePredicted()) then
|
||||
return
|
||||
end
|
||||
|
||||
if (SERVER and IsValid(self.heldEntity)) then
|
||||
self:DropObject()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,514 @@
|
||||
SWEP.Base = "tacrp_base"
|
||||
SWEP.Spawnable = true
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
// names and stuff
|
||||
SWEP.PrintName = "Infantry First Aid Kit"
|
||||
SWEP.AbbrevName = "IFAK"
|
||||
SWEP.Category = "[FT] Медицина"
|
||||
|
||||
SWEP.SubCatTier = "9Special"
|
||||
SWEP.SubCatType = "9Special"
|
||||
|
||||
SWEP.Description = "Индивидуальная аптечка первой помощи. Содержит бинты, гемостаты и порошки QuikClot для остановки кровотечений."
|
||||
SWEP.Description_Quote = "Поддержка жизни в полевых условиях."
|
||||
|
||||
SWEP.Trivia_Manufacturer = "Military Issue"
|
||||
SWEP.Trivia_Year = "2000s"
|
||||
|
||||
SWEP.Faction = TacRP.FACTION_NEUTRAL
|
||||
SWEP.Credits = "Original: Firearms Source 2\nPort: TacRP"
|
||||
|
||||
SWEP.ViewModel = "models/weapons/v_ifak.mdl"
|
||||
SWEP.WorldModel = "models/Items/HealthKit.mdl"
|
||||
|
||||
SWEP.Slot = 4
|
||||
|
||||
SWEP.NoRanger = true
|
||||
SWEP.NoStatBox = true
|
||||
|
||||
// handling
|
||||
|
||||
SWEP.MoveSpeedMult = 1
|
||||
SWEP.ShootingSpeedMult = 1
|
||||
SWEP.SightedSpeedMult = 1
|
||||
|
||||
SWEP.AimDownSightsTime = 0.25
|
||||
SWEP.SprintToFireTime = 0.25
|
||||
|
||||
SWEP.Sway = 0
|
||||
SWEP.FreeAimMaxAngle = 0
|
||||
|
||||
// hold types
|
||||
|
||||
SWEP.HoldType = "slam"
|
||||
SWEP.HoldTypeSprint = "normal"
|
||||
SWEP.HoldTypeBlindFire = false
|
||||
|
||||
SWEP.GestureShoot = ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL
|
||||
SWEP.GestureReload = ACT_HL2MP_GESTURE_RELOAD_PISTOL
|
||||
|
||||
SWEP.PassiveAng = Angle(0, 0, 0)
|
||||
SWEP.PassivePos = Vector(0, -2, -4)
|
||||
|
||||
SWEP.BlindFireAng = Angle(0, 0, 0)
|
||||
SWEP.BlindFirePos = Vector(0, 0, 0)
|
||||
|
||||
SWEP.SprintAng = Angle(0, 30, 0)
|
||||
SWEP.SprintPos = Vector(2, 0, -12)
|
||||
|
||||
SWEP.SightAng = Angle(-0.5, 0, 0)
|
||||
SWEP.SightPos = Vector(-3.412, -6.4, -2.238)
|
||||
|
||||
SWEP.CorrectivePos = Vector(0, 0, 0)
|
||||
SWEP.CorrectiveAng = Angle(0, 0, 0)
|
||||
|
||||
SWEP.HolsterVisible = true
|
||||
SWEP.HolsterSlot = TacRP.HOLSTER_SLOT_GEAR
|
||||
SWEP.HolsterPos = Vector(2, 0, 0)
|
||||
SWEP.HolsterAng = Angle(-90, 0, 0)
|
||||
|
||||
// reload
|
||||
|
||||
SWEP.ClipSize = -1
|
||||
SWEP.Ammo = "none"
|
||||
|
||||
// sounds
|
||||
|
||||
SWEP.Sounds = {}
|
||||
SWEP.Sounds["bandage"] = {
|
||||
{time = 0.4, sound = "FAS2_Bandage.Retrieve"},
|
||||
{time = 1.25, sound = "FAS2_Bandage.Open"},
|
||||
{time = 2.15, sound = "FAS2_Hemostat.Retrieve"}
|
||||
}
|
||||
|
||||
SWEP.Sounds["quikclot"] = {
|
||||
{time = 0.3, sound = "FAS2_QuikClot.Retrieve"},
|
||||
{time = 1.45, sound = "FAS2_QuikClot.Loosen"},
|
||||
{time = 2.55, sound = "FAS2_QuikClot.Open"}
|
||||
}
|
||||
|
||||
SWEP.Sounds["suture"] = {
|
||||
{time = 0.3, sound = "FAS2_Hemostat.Retrieve"},
|
||||
{time = 3.5, sound = "FAS2_Hemostat.Close"}
|
||||
}
|
||||
|
||||
// attachments
|
||||
|
||||
SWEP.Attachments = {
|
||||
[1] = {
|
||||
PrintName = "Аксессуар",
|
||||
Category = "acc",
|
||||
AttachSound = "TacRP/weapons/flashlight_on.wav",
|
||||
DetachSound = "TacRP/weapons/flashlight_off.wav",
|
||||
},
|
||||
}
|
||||
|
||||
SWEP.FreeAim = false
|
||||
SWEP.Scope = false
|
||||
|
||||
SWEP.DrawCrosshair = true
|
||||
SWEP.DrawCrosshairInSprint = true
|
||||
|
||||
// Custom vars
|
||||
SWEP.EasterWait = 0
|
||||
|
||||
function SWEP:Initialize()
|
||||
self:SetHoldType(self.HoldType)
|
||||
|
||||
if CLIENT then
|
||||
self.SoundTime = 0
|
||||
self.SoundEntry = 1
|
||||
self.CurrentSoundTable = nil
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:Deploy()
|
||||
local owner = self:GetOwner()
|
||||
if SERVER and IsValid(owner) then
|
||||
owner:GiveAmmo(4, "Bandages", true)
|
||||
owner:GiveAmmo(3, "Quikclots", true)
|
||||
owner:GiveAmmo(2, "Hemostats", true)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
if self.HealTime and CurTime() < self.HealTime then
|
||||
return false
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
self.CurrentSoundTable = nil
|
||||
self.SoundEntry = 1
|
||||
self.SoundTime = 0
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
local Mins, Maxs = Vector(-8, -8, -8), Vector(8, 8, 8)
|
||||
|
||||
function SWEP:FindHealTarget()
|
||||
local owner = self:GetOwner()
|
||||
if not IsValid(owner) then return owner end
|
||||
|
||||
local tr = util.TraceHull({
|
||||
start = owner:GetShootPos(),
|
||||
endpos = owner:GetShootPos() + owner:GetAimVector() * 50,
|
||||
filter = owner,
|
||||
mins = Mins,
|
||||
maxs = Maxs
|
||||
})
|
||||
|
||||
if tr.Hit and IsValid(tr.Entity) and tr.Entity:IsPlayer() then
|
||||
return tr.Entity
|
||||
end
|
||||
|
||||
return owner
|
||||
end
|
||||
|
||||
function SWEP:PlaySounds(soundTable)
|
||||
if not self.Sounds[soundTable] then return end
|
||||
|
||||
self.CurrentSoundTable = soundTable
|
||||
self.SoundEntry = 1
|
||||
self.SoundTime = CurTime()
|
||||
end
|
||||
|
||||
function SWEP:Think()
|
||||
local CT = CurTime()
|
||||
|
||||
-- Sound system
|
||||
if CLIENT and self.CurrentSoundTable then
|
||||
local sounds = self.Sounds[self.CurrentSoundTable]
|
||||
if sounds and sounds[self.SoundEntry] then
|
||||
local snd = sounds[self.SoundEntry]
|
||||
if CT >= self.SoundTime + snd.time then
|
||||
self:EmitSound(snd.sound, 70, 100)
|
||||
|
||||
if sounds[self.SoundEntry + 1] then
|
||||
self.SoundEntry = self.SoundEntry + 1
|
||||
else
|
||||
self.CurrentSoundTable = nil
|
||||
self.SoundEntry = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Healing process
|
||||
if self.CurrentHeal and CT >= self.HealTime then
|
||||
self:EndHealingProcess()
|
||||
end
|
||||
|
||||
-- Update viewmodel bodygroups
|
||||
if CLIENT and not self.CurrentHeal then
|
||||
self:UpdateBodygroups()
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:UpdateBodygroups()
|
||||
local owner = self:GetOwner()
|
||||
if not IsValid(owner) then return end
|
||||
|
||||
local vm = owner:GetViewModel()
|
||||
if not IsValid(vm) then return end
|
||||
|
||||
-- Bodygroup 2 - бинты (0-2)
|
||||
vm:SetBodygroup(2, math.Clamp(owner:GetAmmoCount("Bandages"), 0, 2))
|
||||
|
||||
-- Bodygroup 3 - гемостаты/квикклоты
|
||||
local hemostats = owner:GetAmmoCount("Hemostats")
|
||||
|
||||
if hemostats > 0 then
|
||||
vm:SetBodygroup(3, hemostats == 1 and 2 or 3)
|
||||
else
|
||||
local quikclots = owner:GetAmmoCount("Quikclots")
|
||||
vm:SetBodygroup(3, quikclots > 0 and 1 or 0)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:EndHealingProcess()
|
||||
local owner = self:GetOwner()
|
||||
if not IsValid(owner) then return end
|
||||
|
||||
-- Play end animation
|
||||
local vm = owner:GetViewModel()
|
||||
if IsValid(vm) then
|
||||
local anim = "idle"
|
||||
if self.CurrentHeal == "suture" and owner:GetAmmoCount("Hemostats") == 1 then
|
||||
anim = "bandage_end"
|
||||
else
|
||||
anim = self.CurrentHeal .. "_end"
|
||||
end
|
||||
|
||||
local seq = vm:LookupSequence(anim)
|
||||
if seq > 0 then
|
||||
vm:SendViewModelMatchingSequence(seq)
|
||||
end
|
||||
end
|
||||
|
||||
owner:RemoveAmmo(1, self.AmmoType)
|
||||
|
||||
if CLIENT then
|
||||
self:UpdateBodygroups()
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
if self.OwnHeal then
|
||||
owner:SetHealth(math.Clamp(owner:Health() + self.HealAmount, 0, owner:GetMaxHealth()))
|
||||
else
|
||||
if IsValid(self.Target) then
|
||||
self.Target:SetHealth(math.Clamp(self.Target:Health() + self.HealAmount, 0, self.Target:GetMaxHealth()))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.CurrentHeal = nil
|
||||
self.HealTime = nil
|
||||
self.HealAmount = nil
|
||||
self.Target = nil
|
||||
self.OwnHeal = false
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
if not IsFirstTimePredicted() then return end
|
||||
|
||||
local owner = self:GetOwner()
|
||||
if not IsValid(owner) then return end
|
||||
|
||||
local bandages = owner:GetAmmoCount("Bandages")
|
||||
if bandages <= 0 then return end
|
||||
|
||||
local target = self:FindHealTarget()
|
||||
if not IsValid(target) then return end
|
||||
|
||||
-- Проверка здоровья
|
||||
if CLIENT then
|
||||
if target:Health() >= 100 then return end
|
||||
else
|
||||
if target:Health() >= target:GetMaxHealth() then return end
|
||||
end
|
||||
|
||||
local CT = CurTime()
|
||||
|
||||
self:SetNextPrimaryFire(CT + 2.95)
|
||||
self:SetNextSecondaryFire(CT + 2.95)
|
||||
self.HealTime = CT + 2.5
|
||||
self.CurrentHeal = "bandage"
|
||||
self.AmmoType = "Bandages"
|
||||
self.HealAmount = 10
|
||||
self.Target = target
|
||||
self.OwnHeal = (target == owner)
|
||||
|
||||
-- Анимация
|
||||
local vm = owner:GetViewModel()
|
||||
if IsValid(vm) then
|
||||
local seq = vm:LookupSequence("bandage")
|
||||
if seq > 0 then
|
||||
vm:SendViewModelMatchingSequence(seq)
|
||||
end
|
||||
end
|
||||
|
||||
-- Звуки
|
||||
self:PlaySounds("bandage")
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
if not IsFirstTimePredicted() then return end
|
||||
|
||||
local owner = self:GetOwner()
|
||||
if not IsValid(owner) then return end
|
||||
|
||||
local hemostats = owner:GetAmmoCount("Hemostats")
|
||||
local quikclots = owner:GetAmmoCount("Quikclots")
|
||||
|
||||
if hemostats <= 0 and quikclots <= 0 then return end
|
||||
|
||||
local target = self:FindHealTarget()
|
||||
if not IsValid(target) then return end
|
||||
|
||||
-- Проверка здоровья
|
||||
if CLIENT then
|
||||
if target:Health() >= 100 then return end
|
||||
else
|
||||
if target:Health() >= target:GetMaxHealth() then return end
|
||||
end
|
||||
|
||||
local CT = CurTime()
|
||||
|
||||
if hemostats > 0 then
|
||||
-- Гемостат
|
||||
self:SetNextPrimaryFire(CT + 5.5)
|
||||
self:SetNextSecondaryFire(CT + 5.5)
|
||||
self.HealTime = CT + 4.5
|
||||
self.CurrentHeal = "suture"
|
||||
self.AmmoType = "Hemostats"
|
||||
self.HealAmount = 30
|
||||
|
||||
local vm = owner:GetViewModel()
|
||||
if IsValid(vm) then
|
||||
local seq = vm:LookupSequence("suture")
|
||||
if seq > 0 then
|
||||
vm:SendViewModelMatchingSequence(seq)
|
||||
end
|
||||
end
|
||||
|
||||
self:PlaySounds("suture")
|
||||
else
|
||||
-- QuikClot
|
||||
self:SetNextPrimaryFire(CT + 4.65)
|
||||
self:SetNextSecondaryFire(CT + 4.65)
|
||||
self.HealTime = CT + 4.2
|
||||
self.CurrentHeal = "quikclot"
|
||||
self.AmmoType = "Quikclots"
|
||||
self.HealAmount = 20
|
||||
|
||||
local vm = owner:GetViewModel()
|
||||
if IsValid(vm) then
|
||||
local seq = vm:LookupSequence("quikclot")
|
||||
if seq > 0 then
|
||||
vm:SendViewModelMatchingSequence(seq)
|
||||
end
|
||||
end
|
||||
|
||||
self:PlaySounds("quikclot")
|
||||
end
|
||||
|
||||
self.Target = target
|
||||
self.OwnHeal = (target == owner)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
local White = Color(255, 255, 255, 255)
|
||||
local Black = Color(0, 0, 0, 255)
|
||||
local Green = Color(202, 255, 163, 255)
|
||||
local Grey = Color(200, 200, 200, 255)
|
||||
|
||||
surface.CreateFont("IFAK_HUD24", {
|
||||
font = "Arial",
|
||||
size = 24,
|
||||
weight = 700,
|
||||
antialias = true
|
||||
})
|
||||
|
||||
surface.CreateFont("IFAK_HUD36", {
|
||||
font = "Arial",
|
||||
size = 36,
|
||||
weight = 700,
|
||||
antialias = true
|
||||
})
|
||||
|
||||
function SWEP:DrawHUD()
|
||||
local owner = self:GetOwner()
|
||||
if not IsValid(owner) then return end
|
||||
|
||||
local x, y = ScrW() / 2, ScrH() / 2
|
||||
|
||||
local target = self:FindHealTarget()
|
||||
local targetName = "СЕБЯ"
|
||||
if IsValid(target) and target != owner then
|
||||
targetName = target:Nick()
|
||||
end
|
||||
|
||||
draw.SimpleTextOutlined(
|
||||
"ЦЕЛЬ ЛЕЧЕНИЯ: " .. targetName,
|
||||
"IFAK_HUD24",
|
||||
x, y + 200,
|
||||
White, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER,
|
||||
2, Black
|
||||
)
|
||||
|
||||
-- Информация о расходниках
|
||||
local bandages = owner:GetAmmoCount("Bandages")
|
||||
local hemostats = owner:GetAmmoCount("Hemostats")
|
||||
local quikclots = owner:GetAmmoCount("Quikclots")
|
||||
|
||||
-- Левая сторона - Бинты
|
||||
draw.SimpleTextOutlined(
|
||||
"БИНТЫ: " .. bandages,
|
||||
"IFAK_HUD36",
|
||||
x - 100, y + 125,
|
||||
White, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP,
|
||||
2, Black
|
||||
)
|
||||
|
||||
if bandages > 0 then
|
||||
draw.SimpleTextOutlined(
|
||||
"ЛКМ - БИНТ",
|
||||
"IFAK_HUD24",
|
||||
x - 100, y + 100,
|
||||
Green, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP,
|
||||
2, Black
|
||||
)
|
||||
|
||||
draw.SimpleTextOutlined(
|
||||
"+10 HP",
|
||||
"IFAK_HUD24",
|
||||
x - 100, y + 75,
|
||||
Green, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP,
|
||||
2, Black
|
||||
)
|
||||
end
|
||||
|
||||
-- Правая сторона - Гемостаты/QuikClot
|
||||
if hemostats > 0 then
|
||||
draw.SimpleTextOutlined(
|
||||
"ГЕМОСТАТЫ: " .. hemostats,
|
||||
"IFAK_HUD36",
|
||||
x + 100, y + 125,
|
||||
White, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP,
|
||||
2, Black
|
||||
)
|
||||
|
||||
draw.SimpleTextOutlined(
|
||||
"ПКМ - ГЕМОСТАТ",
|
||||
"IFAK_HUD24",
|
||||
x + 100, y + 100,
|
||||
Green, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP,
|
||||
2, Black
|
||||
)
|
||||
|
||||
draw.SimpleTextOutlined(
|
||||
"+30 HP",
|
||||
"IFAK_HUD24",
|
||||
x + 100, y + 75,
|
||||
Green, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP,
|
||||
2, Black
|
||||
)
|
||||
else
|
||||
draw.SimpleTextOutlined(
|
||||
"QUIKCLOTS: " .. quikclots,
|
||||
"IFAK_HUD36",
|
||||
x + 100, y + 125,
|
||||
White, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP,
|
||||
2, Black
|
||||
)
|
||||
|
||||
if quikclots > 0 then
|
||||
draw.SimpleTextOutlined(
|
||||
"ПКМ - QUIKCLOT",
|
||||
"IFAK_HUD24",
|
||||
x + 100, y + 100,
|
||||
Green, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP,
|
||||
2, Black
|
||||
)
|
||||
|
||||
draw.SimpleTextOutlined(
|
||||
"+20 HP",
|
||||
"IFAK_HUD24",
|
||||
x + 100, y + 75,
|
||||
Green, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP,
|
||||
2, Black
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,615 @@
|
||||
include('shared.lua')
|
||||
|
||||
if not cigaParticleEmitter then cigaParticleEmitter = ParticleEmitter(Vector(0,0,0)) end
|
||||
|
||||
function SWEP:DrawWorldModel()
|
||||
local ply = self:GetOwner()
|
||||
|
||||
local cigaScale = self.cigaScale or 1
|
||||
self:SetModelScale(cigaScale, 0)
|
||||
self:SetSubMaterial()
|
||||
|
||||
if IsValid(ply) then
|
||||
local modelStr = ply:GetModel():sub(1,17)
|
||||
local isPony = modelStr=="models/ppm/player" or modelStr=="models/mlp/player" or modelStr=="models/cppm/playe"
|
||||
|
||||
local bn = isPony and "LrigScull" or "ValveBiped.Bip01_R_Hand"
|
||||
if ply.cigaArmFullyUp then bn ="ValveBiped.Bip01_Head1" end
|
||||
local bon = ply:LookupBone(bn) or 0
|
||||
|
||||
local opos = self:GetPos()
|
||||
local oang = self:GetAngles()
|
||||
local bp,ba = ply:GetBonePosition(bon)
|
||||
if bp then opos = bp end
|
||||
if ba then oang = ba end
|
||||
|
||||
if ply.cigaArmFullyUp then
|
||||
--head position
|
||||
opos = opos + (oang:Forward()*0.95) + (oang:Right()*7) + (oang:Up()*0.035)
|
||||
oang:RotateAroundAxis(oang:Forward(),-100)
|
||||
oang:RotateAroundAxis(oang:Up(),100)
|
||||
opos = opos + (oang:Up()*(cigaScale-1)*-10.25)
|
||||
else
|
||||
--hand position
|
||||
oang:RotateAroundAxis(oang:Forward(),50)
|
||||
oang:RotateAroundAxis(oang:Right(),90)
|
||||
opos = opos + (oang:Forward()*2) + (oang:Up()*-4.5) + (oang:Right()*-2)
|
||||
oang:RotateAroundAxis(oang:Forward(),90)
|
||||
oang:RotateAroundAxis(oang:Up(),10)
|
||||
opos = opos + (oang:Up()*(cigaScale-1)*-10.25)
|
||||
opos = opos + (oang:Up() * 2)
|
||||
opos = opos + (oang:Right() * 0.5)
|
||||
opos = opos + (oang:Forward() * -1.5)
|
||||
end
|
||||
self:SetupBones()
|
||||
|
||||
local mrt = self:GetBoneMatrix(0)
|
||||
if mrt then
|
||||
mrt:SetTranslation(opos)
|
||||
mrt:SetAngles(oang)
|
||||
|
||||
self:SetBoneMatrix(0, mrt)
|
||||
end
|
||||
end
|
||||
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
function SWEP:GetViewModelPosition(pos, ang)
|
||||
--mouth pos
|
||||
local vmpos1=self.cigaVMPos1 or Vector(18.5,-3.4,-3.25)
|
||||
local vmang1=self.cigaVMAng1 or Vector(170,-180,20)
|
||||
--hand pos
|
||||
local vmpos2=self.cigaVMPos2 or Vector(24,-8,-11.2)
|
||||
local vmang2=self.cigaVMAng2 or Vector(120,-180,150)
|
||||
|
||||
if not LocalPlayer().cigaArmTime then LocalPlayer().cigaArmTime=0 end
|
||||
local lerp = math.Clamp((os.clock()-LocalPlayer().cigaArmTime)*3,0,1)
|
||||
if LocalPlayer().cigaArm then lerp = 1-lerp end
|
||||
/*
|
||||
local newpos = LerpVector(lerp,vmpos1,vmpos2)
|
||||
local newang = LerpVector(lerp,vmang1,vmang2)
|
||||
--I have a good reason for doing it like this
|
||||
newang = Angle(newang.x,newang.y,newang.z)
|
||||
|
||||
pos,ang = LocalToWorld(newpos,newang,pos,ang)*/
|
||||
local difvec = Vector(-10,-3.5,-12)--vmpos1 - vmpos2
|
||||
local orig = Vector(0,0,0)
|
||||
local topos = orig+difvec
|
||||
|
||||
local difang = Vector(-30,0,0)--vmang1 - vmang2
|
||||
local origang = Vector(0,0,0)
|
||||
local toang = origang+difang
|
||||
|
||||
|
||||
|
||||
local newpos = LerpVector(lerp,topos,orig)
|
||||
local newang = LerpVector(lerp,toang,origang)
|
||||
|
||||
newang = Angle(newang.x, newang.y, newang.z)
|
||||
|
||||
|
||||
pos,ang = LocalToWorld(newpos,newang,pos,ang)
|
||||
return pos, ang
|
||||
end
|
||||
|
||||
sound.Add({
|
||||
name = "ciga_inhale",
|
||||
channel = CHAN_WEAPON,
|
||||
volume = 0.24,
|
||||
level = 60,
|
||||
pitch = { 95 },
|
||||
sound = "cigainhale.wav"
|
||||
})
|
||||
|
||||
net.Receive("ciga",function()
|
||||
local ply = net.ReadEntity()
|
||||
local amt = net.ReadInt(8)
|
||||
local fx = net.ReadInt(8)
|
||||
if !IsValid(ply) then return end
|
||||
|
||||
if amt>=50 then
|
||||
ply:EmitSound("cigacough1.wav",90)
|
||||
|
||||
for i=1,200 do
|
||||
local d=i+10
|
||||
if i>140 then d=d+150 end
|
||||
timer.Simple((d-1)*0.003,function() ciga_do_pulse(ply, 1, 100, fx) end)
|
||||
end
|
||||
|
||||
return
|
||||
elseif amt>=35 then
|
||||
ply:EmitSound("cigabreath2.wav",75,100,0.7)
|
||||
elseif amt>=10 then
|
||||
ply:EmitSound("cigabreath1.wav",70,130-math.min(100,amt*2),0.4+(amt*0.005))
|
||||
end
|
||||
|
||||
for i=1,amt*2 do
|
||||
timer.Simple((i-1)*0.02,function() ciga_do_pulse(ply,math.floor(((amt*2)-i)/10), fx==2 and 100 or 0, fx) end)
|
||||
end
|
||||
end)
|
||||
|
||||
net.Receive("cigaArm",function()
|
||||
local ply = net.ReadEntity()
|
||||
local z = net.ReadBool()
|
||||
if !IsValid(ply) then return end
|
||||
if ply.cigaArm != z then
|
||||
if z then
|
||||
timer.Simple(0.3, function()
|
||||
if !IsValid(ply) then return end
|
||||
if ply.cigaArm then ply:EmitSound("ciga_inhale") end
|
||||
end)
|
||||
else
|
||||
ply:StopSound("ciga_inhale")
|
||||
end
|
||||
ply.cigaArm = z
|
||||
ply.cigaArmTime = os.clock()
|
||||
local m = 0
|
||||
if z then m = 1 end
|
||||
|
||||
for i=0,9 do
|
||||
timer.Simple(i/30,function() ciga_interpolate_arm(ply,math.abs(m-((9-i)/10)),z and 0 or 0.2) end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
net.Receive("cigaTalking",function()
|
||||
local ply = net.ReadEntity()
|
||||
if IsValid(ply) then ply.cigaTalkingEndtime = net.ReadFloat() end
|
||||
end)
|
||||
|
||||
function ciga_interpolate_arm(ply, mult, mouth_delay)
|
||||
if !IsValid(ply) then return end
|
||||
|
||||
if mouth_delay>0 then
|
||||
timer.Simple(mouth_delay,function() if IsValid(ply) then ply.cigaMouthOpenAmt = mult end end)
|
||||
else
|
||||
ply.cigaMouthOpenAmt = mult
|
||||
end
|
||||
|
||||
local b1 = ply:LookupBone("ValveBiped.Bip01_R_Upperarm")
|
||||
local b2 = ply:LookupBone("ValveBiped.Bip01_R_Forearm")
|
||||
if (not b1) or (not b2) then return end
|
||||
ply:ManipulateBoneAngles(b1,Angle(20*mult,-62*mult,10*mult))
|
||||
ply:ManipulateBoneAngles(b2,Angle(-5*mult,-10*mult,0))
|
||||
if mult==1 then ply.cigaArmFullyUp=true else ply.cigaArmFullyUp=false end
|
||||
end
|
||||
|
||||
--this makes the mouth opening work without clobbering other addons
|
||||
hook.Add("InitPostEntity", "cigaMouthMoveSetup", function()
|
||||
timer.Simple(1, function()
|
||||
if ciga_OriginalMouthMove ~= nil then return end
|
||||
|
||||
ciga_OriginalMouthMove = GAMEMODE.MouthMoveAnimation
|
||||
|
||||
function GAMEMODE:MouthMoveAnimation(ply)
|
||||
--run the base MouthMoveAnimation if player isn't vaping/cigatalking
|
||||
if ((ply.cigaMouthOpenAmt or 0) == 0) and ((ply.cigaTalkingEndtime or 0) < CurTime()) then
|
||||
return ciga_OriginalMouthMove(GAMEMODE, ply)
|
||||
end
|
||||
|
||||
local FlexNum = ply:GetFlexNum() - 1
|
||||
if ( FlexNum <= 0 ) then return end
|
||||
for i = 0, FlexNum - 1 do
|
||||
local Name = ply:GetFlexName(i)
|
||||
if ( Name == "jaw_drop" || Name == "right_part" || Name == "left_part" || Name == "right_mouth_drop" || Name == "left_mouth_drop" ) then
|
||||
ply:SetFlexWeight(i, math.max(((ply.cigaMouthOpenAmt or 0)*0.5), math.Clamp(((ply.cigaTalkingEndtime or 0)-CurTime())*3.0, 0, 1)*math.Rand(0.1,0.8) ))
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
function ciga_do_pulse(ply, amt, spreadadd, fx)
|
||||
if !IsValid(ply) then return end
|
||||
|
||||
if ply:WaterLevel()==3 then return end
|
||||
|
||||
if not spreadadd then spreadadd=0 end
|
||||
|
||||
local attachid = ply:LookupAttachment("eyes")
|
||||
cigaParticleEmitter:SetPos(LocalPlayer():GetPos())
|
||||
|
||||
local angpos = ply:GetAttachment(attachid) or {Ang=Angle(0,0,0), Pos=Vector(0,0,0)}
|
||||
local fwd
|
||||
local pos
|
||||
|
||||
if (ply != LocalPlayer()) then
|
||||
fwd = (angpos.Ang:Forward()-angpos.Ang:Up()):GetNormalized()
|
||||
pos = angpos.Pos + (fwd*3.5)
|
||||
else
|
||||
fwd = ply:GetAimVector():GetNormalized()
|
||||
pos = ply:GetShootPos() + fwd*1.5 + gui.ScreenToVector( ScrW()/2, ScrH() )*5
|
||||
end
|
||||
|
||||
fwd = ply:GetAimVector():GetNormalized()
|
||||
|
||||
for i = 1,amt do
|
||||
if !IsValid(ply) then return end
|
||||
local particle = cigaParticleEmitter:Add(string.format("particle/smokesprites_00%02d",math.random(7,16)), pos )
|
||||
if particle then
|
||||
local dir = VectorRand():GetNormalized() * ((amt+5)/10)
|
||||
ciga_do_particle(particle, (ply:GetVelocity()*0.25)+(((fwd*9)+dir):GetNormalized() * math.Rand(50,80) * (amt + 1) * 0.2), fx)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ciga_do_particle(particle, vel, fx)
|
||||
particle:SetColor(255,255,255,255)
|
||||
if fx == 3 then particle:SetColor(100,100,100,100) end
|
||||
if fx >= 4 then
|
||||
local c = JuicycigaJuices[fx-3].color
|
||||
if c == nil then c = HSVToColor(math.random(0,359),1,1) end
|
||||
particle:SetColor(c.r, c.g, c.b, 255)
|
||||
end
|
||||
|
||||
local mega = 1
|
||||
if fx == 2 then mega = 4 end
|
||||
mega = mega * 0.3
|
||||
|
||||
particle:SetVelocity( vel * mega )
|
||||
particle:SetGravity( Vector(0,0,1.5) )
|
||||
particle:SetLifeTime(0)
|
||||
particle:SetDieTime(math.Rand(80,100)*0.11*mega)
|
||||
particle:SetStartSize(3*mega)
|
||||
particle:SetEndSize(40*mega*mega)
|
||||
particle:SetStartAlpha(150)
|
||||
particle:SetEndAlpha(0)
|
||||
particle:SetCollide(true)
|
||||
particle:SetBounce(0.25)
|
||||
particle:SetRoll(math.Rand(0,360))
|
||||
particle:SetRollDelta(0.01*math.Rand(-40,40))
|
||||
particle:SetAirResistance(50)
|
||||
end
|
||||
|
||||
matproxy.Add({
|
||||
name = "cigaTankColor",
|
||||
init = function( self, mat, values )
|
||||
self.ResultTo = values.resultvar
|
||||
end,
|
||||
bind = function( self, mat, ent )
|
||||
if ( !IsValid( ent ) ) then return end
|
||||
if ent:GetClass()=="viewmodel" then
|
||||
ent=ent:GetOwner()
|
||||
if ( !IsValid( ent ) or !ent:IsPlayer() ) then return end
|
||||
ent=ent:GetActiveWeapon()
|
||||
if ( !IsValid( ent ) ) then return end
|
||||
end
|
||||
local v = ent.cigaTankColor or Vector(0.3,0.3,0.3)
|
||||
if v==Vector(-1,-1,-1) then
|
||||
local c = HSVToColor((CurTime()*60)%360,0.9,0.9)
|
||||
v = Vector(c.r,c.g,c.b)/255.0
|
||||
end
|
||||
mat:SetVector(self.ResultTo, v)
|
||||
end
|
||||
})
|
||||
|
||||
matproxy.Add({
|
||||
name = "cigaAccentColor",
|
||||
init = function( self, mat, values )
|
||||
self.ResultTo = values.resultvar
|
||||
end,
|
||||
bind = function( self, mat, ent )
|
||||
if ( !IsValid( ent ) ) then return end
|
||||
local o = ent:GetOwner()
|
||||
if ent:GetClass()=="viewmodel" then
|
||||
if (!IsValid(o)) or (!o:IsPlayer()) then return end
|
||||
ent=o:GetActiveWeapon()
|
||||
if ( !IsValid( ent ) ) then return end
|
||||
end
|
||||
local special = false
|
||||
local col = ent.cigaAccentColor or special and Vector(1,0.8,0) or Vector(1,1,1)
|
||||
if col==Vector(-1,-1,-1) then
|
||||
col=Vector(1,1,1)
|
||||
if IsValid(o) then col=o:GetWeaponColor() end
|
||||
end
|
||||
mat:SetVector(self.ResultTo, col)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
--Swep Construction Kit code--
|
||||
|
||||
if CLIENT then
|
||||
|
||||
SWEP.vRenderOrder = nil
|
||||
function SWEP:ViewModelDrawn()
|
||||
|
||||
local vm = self.Owner:GetViewModel()
|
||||
if !IsValid(vm) then return end
|
||||
|
||||
if (!self.VElements) then return end
|
||||
|
||||
self:UpdateBonePositions(vm)
|
||||
|
||||
if (!self.vRenderOrder) then
|
||||
|
||||
// we build a render order because sprites need to be drawn after models
|
||||
self.vRenderOrder = {}
|
||||
|
||||
for k, v in pairs( self.VElements ) do
|
||||
if (v.type == "Model") then
|
||||
table.insert(self.vRenderOrder, 1, k)
|
||||
elseif (v.type == "Sprite" or v.type == "Quad") then
|
||||
table.insert(self.vRenderOrder, k)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
for k, name in ipairs( self.vRenderOrder ) do
|
||||
|
||||
local v = self.VElements[name]
|
||||
if (!v) then self.vRenderOrder = nil break end
|
||||
if (v.hide) then continue end
|
||||
|
||||
local model = v.modelEnt
|
||||
local sprite = v.spriteMaterial
|
||||
|
||||
if (!v.bone) then continue end
|
||||
|
||||
local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
|
||||
|
||||
if (!pos) then continue end
|
||||
|
||||
if (v.type == "Model" and IsValid(model)) then
|
||||
|
||||
model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
|
||||
ang:RotateAroundAxis(ang:Up(), v.angle.y)
|
||||
ang:RotateAroundAxis(ang:Right(), v.angle.p)
|
||||
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
|
||||
|
||||
model:SetAngles(ang)
|
||||
//model:SetModelScale(v.size)
|
||||
local matrix = Matrix()
|
||||
matrix:Scale(v.size)
|
||||
model:EnableMatrix( "RenderMultiply", matrix )
|
||||
|
||||
if (v.material == "") then
|
||||
model:SetMaterial("")
|
||||
elseif (model:GetMaterial() != v.material) then
|
||||
model:SetMaterial( v.material )
|
||||
end
|
||||
|
||||
if (v.skin and v.skin != model:GetSkin()) then
|
||||
model:SetSkin(v.skin)
|
||||
end
|
||||
|
||||
if (v.bodygroup) then
|
||||
for k, v in pairs( v.bodygroup ) do
|
||||
if (model:GetBodygroup(k) != v) then
|
||||
model:SetBodygroup(k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (v.surpresslightning) then
|
||||
render.SuppressEngineLighting(true)
|
||||
end
|
||||
|
||||
render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
|
||||
render.SetBlend(v.color.a/255)
|
||||
model:DrawModel()
|
||||
render.SetBlend(1)
|
||||
render.SetColorModulation(1, 1, 1)
|
||||
|
||||
if (v.surpresslightning) then
|
||||
render.SuppressEngineLighting(false)
|
||||
end
|
||||
|
||||
elseif (v.type == "Sprite" and sprite) then
|
||||
|
||||
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
|
||||
render.SetMaterial(sprite)
|
||||
render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
|
||||
|
||||
elseif (v.type == "Quad" and v.draw_func) then
|
||||
|
||||
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
|
||||
ang:RotateAroundAxis(ang:Up(), v.angle.y)
|
||||
ang:RotateAroundAxis(ang:Right(), v.angle.p)
|
||||
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
|
||||
|
||||
cam.Start3D2D(drawpos, ang, v.size)
|
||||
v.draw_func( self )
|
||||
cam.End3D2D()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
|
||||
|
||||
local bone, pos, ang
|
||||
if (tab.rel and tab.rel != "") then
|
||||
|
||||
local v = basetab[tab.rel]
|
||||
|
||||
if (!v) then return end
|
||||
|
||||
// Technically, if there exists an element with the same name as a bone
|
||||
// you can get in an infinite loop. Let's just hope nobody's that stupid.
|
||||
pos, ang = self:GetBoneOrientation( basetab, v, ent )
|
||||
|
||||
if (!pos) then return end
|
||||
|
||||
pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
|
||||
ang:RotateAroundAxis(ang:Up(), v.angle.y)
|
||||
ang:RotateAroundAxis(ang:Right(), v.angle.p)
|
||||
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
|
||||
|
||||
else
|
||||
|
||||
bone = ent:LookupBone(bone_override or tab.bone)
|
||||
|
||||
if (!bone) then return end
|
||||
|
||||
pos, ang = Vector(0,0,0), Angle(0,0,0)
|
||||
local m = ent:GetBoneMatrix(bone)
|
||||
if (m) then
|
||||
pos, ang = m:GetTranslation(), m:GetAngles()
|
||||
end
|
||||
|
||||
if (IsValid(self.Owner) and self.Owner:IsPlayer() and
|
||||
ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
|
||||
ang.r = -ang.r // Fixes mirrored models
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return pos, ang
|
||||
end
|
||||
|
||||
function SWEP:CreateModels( tab )
|
||||
|
||||
if (!tab) then return end
|
||||
|
||||
// Create the clientside models here because Garry says we can't do it in the render hook
|
||||
for k, v in pairs( tab ) do
|
||||
if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
|
||||
string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
|
||||
|
||||
v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
|
||||
if (IsValid(v.modelEnt)) then
|
||||
v.modelEnt:SetPos(self:GetPos())
|
||||
v.modelEnt:SetAngles(self:GetAngles())
|
||||
v.modelEnt:SetParent(self)
|
||||
v.modelEnt:SetNoDraw(true)
|
||||
v.createdModel = v.model
|
||||
else
|
||||
v.modelEnt = nil
|
||||
end
|
||||
|
||||
elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
|
||||
and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
|
||||
|
||||
local name = v.sprite.."-"
|
||||
local params = { ["$basetexture"] = v.sprite }
|
||||
// make sure we create a unique name based on the selected options
|
||||
local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
|
||||
for i, j in pairs( tocheck ) do
|
||||
if (v[j]) then
|
||||
params["$"..j] = 1
|
||||
name = name.."1"
|
||||
else
|
||||
name = name.."0"
|
||||
end
|
||||
end
|
||||
|
||||
v.createdSprite = v.sprite
|
||||
v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local allbones
|
||||
local hasGarryFixedBoneScalingYet = false
|
||||
|
||||
function SWEP:UpdateBonePositions(vm)
|
||||
|
||||
if self.ViewModelBoneMods then
|
||||
|
||||
if (!vm:GetBoneCount()) then return end
|
||||
|
||||
// !! WORKAROUND !! //
|
||||
// We need to check all model names :/
|
||||
local loopthrough = self.ViewModelBoneMods
|
||||
if (!hasGarryFixedBoneScalingYet) then
|
||||
allbones = {}
|
||||
for i=0, vm:GetBoneCount() do
|
||||
local bonename = vm:GetBoneName(i)
|
||||
if (self.ViewModelBoneMods[bonename]) then
|
||||
allbones[bonename] = self.ViewModelBoneMods[bonename]
|
||||
else
|
||||
allbones[bonename] = {
|
||||
scale = Vector(1,1,1),
|
||||
pos = Vector(0,0,0),
|
||||
angle = Angle(0,0,0)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
loopthrough = allbones
|
||||
end
|
||||
// !! ----------- !! //
|
||||
|
||||
for k, v in pairs( loopthrough ) do
|
||||
local bone = vm:LookupBone(k)
|
||||
if (!bone) then continue end
|
||||
|
||||
// !! WORKAROUND !! //
|
||||
local s = Vector(v.scale.x,v.scale.y,v.scale.z)
|
||||
local p = Vector(v.pos.x,v.pos.y,v.pos.z)
|
||||
local ms = Vector(1,1,1)
|
||||
if (!hasGarryFixedBoneScalingYet) then
|
||||
local cur = vm:GetBoneParent(bone)
|
||||
while(cur >= 0) do
|
||||
local pscale = loopthrough[vm:GetBoneName(cur)].scale
|
||||
ms = ms * pscale
|
||||
cur = vm:GetBoneParent(cur)
|
||||
end
|
||||
end
|
||||
|
||||
s = s * ms
|
||||
// !! ----------- !! //
|
||||
|
||||
if vm:GetManipulateBoneScale(bone) != s then
|
||||
vm:ManipulateBoneScale( bone, s )
|
||||
end
|
||||
if vm:GetManipulateBoneAngles(bone) != v.angle then
|
||||
vm:ManipulateBoneAngles( bone, v.angle )
|
||||
end
|
||||
if vm:GetManipulateBonePosition(bone) != p then
|
||||
vm:ManipulateBonePosition( bone, p )
|
||||
end
|
||||
end
|
||||
else
|
||||
self:ResetBonePositions(vm)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SWEP:ResetBonePositions(vm)
|
||||
|
||||
if (!vm:GetBoneCount()) then return end
|
||||
for i=0, vm:GetBoneCount() do
|
||||
vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
|
||||
vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
|
||||
vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
/**************************
|
||||
Global utility code
|
||||
**************************/
|
||||
|
||||
// Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
|
||||
// Does not copy entities of course, only copies their reference.
|
||||
// WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
|
||||
function table.FullCopy( tab )
|
||||
|
||||
if (!tab) then return nil end
|
||||
|
||||
local res = {}
|
||||
for k, v in pairs( tab ) do
|
||||
if (type(v) == "table") then
|
||||
res[k] = table.FullCopy(v) // recursion ho!
|
||||
elseif (type(v) == "Vector") then
|
||||
res[k] = Vector(v.x, v.y, v.z)
|
||||
elseif (type(v) == "Angle") then
|
||||
res[k] = Angle(v.p, v.y, v.r)
|
||||
else
|
||||
res[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,55 @@
|
||||
AddCSLuaFile ("cl_init.lua")
|
||||
AddCSLuaFile ("shared.lua")
|
||||
include ("shared.lua")
|
||||
|
||||
util.AddNetworkString("ciga")
|
||||
util.AddNetworkString("cigaArm")
|
||||
util.AddNetworkString("cigaTalking")
|
||||
|
||||
function cigaUpdate(ply, cigaID)
|
||||
if not ply.cigaCount then ply.cigaCount = 0 end
|
||||
if not ply.cantStartciga then ply.cantStartciga=false end
|
||||
if ply.cigaCount == 0 and ply.cantStartciga then return end
|
||||
|
||||
ply.cigaID = cigaID
|
||||
ply.cigaCount = ply.cigaCount + 1
|
||||
if ply.cigaCount == 1 then
|
||||
ply.cigaArm = true
|
||||
net.Start("cigaArm")
|
||||
net.WriteEntity(ply)
|
||||
net.WriteBool(true)
|
||||
net.Broadcast()
|
||||
end
|
||||
if ply.cigaCount >= 50 then
|
||||
ply.cantStartciga = true
|
||||
Releaseciga(ply)
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("KeyRelease","DocigaHook",function(ply, key)
|
||||
if key == IN_ATTACK then
|
||||
Releaseciga(ply)
|
||||
ply.cantStartciga=false
|
||||
end
|
||||
end)
|
||||
|
||||
function Releaseciga(ply)
|
||||
if not ply.cigaCount then ply.cigaCount = 0 end
|
||||
if IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():GetClass():sub(1,11) == "weapon_ciga" then
|
||||
if ply.cigaCount >= 5 then
|
||||
net.Start("ciga")
|
||||
net.WriteEntity(ply)
|
||||
net.WriteInt(ply.cigaCount, 8)
|
||||
net.WriteInt(ply.cigaID + (ply:GetActiveWeapon().juiceID or 0), 8)
|
||||
net.Broadcast()
|
||||
end
|
||||
end
|
||||
if ply.cigaArm then
|
||||
ply.cigaArm = false
|
||||
net.Start("cigaArm")
|
||||
net.WriteEntity(ply)
|
||||
net.WriteBool(false)
|
||||
net.Broadcast()
|
||||
end
|
||||
ply.cigaCount=0
|
||||
end
|
||||
@@ -0,0 +1,131 @@
|
||||
SWEP.PrintName = "Marlboro"
|
||||
|
||||
SWEP.IconLetter = ""
|
||||
SWEP.Author = "AeroMatix"
|
||||
SWEP.Category = "[FT] Атмосфера" -- Support the author by not changing this.
|
||||
SWEP.Slot = 1
|
||||
SWEP.SlotPos = 0
|
||||
|
||||
SWEP.ViewModelFOV = 62 --default
|
||||
|
||||
SWEP.BounceWeaponIcon = false
|
||||
|
||||
SWEP.ViewModel = "models/oldcigshib.mdl"
|
||||
SWEP.WorldModel = "models/oldcigshib.mdl"
|
||||
SWEP.Spawnable = true
|
||||
SWEP.AdminOnly = false
|
||||
|
||||
SWEP.Primary.Clipsize = -1
|
||||
SWEP.Primary.DefaultClip = -1
|
||||
SWEP.Primary.Automatic = true
|
||||
SWEP.Primary.Ammo = "none"
|
||||
|
||||
SWEP.Secondary.Clipsize = -1
|
||||
SWEP.Secondary.DefaultClip = -1
|
||||
SWEP.Secondary.Automatic = false
|
||||
SWEP.Secondary.Ammo = "none"
|
||||
|
||||
SWEP.DrawAmmo = false
|
||||
SWEP.HoldType = "slam"
|
||||
|
||||
SWEP.cigaID = 1
|
||||
|
||||
function SWEP:Deploy()
|
||||
self:SetHoldType("slam")
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
end
|
||||
|
||||
function SWEP:Initialize()
|
||||
|
||||
if !self.CigaInitialized then
|
||||
self.CigaInitialized = true
|
||||
self.VElements = {
|
||||
["ciga"] = { type = "Model", model = self.ViewModel, bone = "ValveBiped.Bip01_Spine4", rel = "", pos = Vector(-7.1, -2.401, 23.377), angle = Angle(111.039, 10.519, 0), size = Vector(1, 1, 1), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
|
||||
}
|
||||
--self.VElements["ciga"].model = self.ViewModel
|
||||
self.OldCigaModel = self.ViewModel
|
||||
self.ViewModel = "models/weapons/c_slam.mdl"
|
||||
self.UseHands = true
|
||||
self.ViewModelFlip = true
|
||||
self.ShowViewModel = true
|
||||
self.ShowWorldModel = true
|
||||
self.ViewModelBoneMods = {
|
||||
["ValveBiped.Bip01_L_Finger1"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(-23.334, -12.223, -32.223) },
|
||||
["ValveBiped.Bip01_L_Finger12"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, -21.112, 0) },
|
||||
["ValveBiped.Bip01_L_Finger4"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, -65.556, 0) },
|
||||
["ValveBiped.Bip01_R_UpperArm"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, 72.222, -41.112) },
|
||||
["ValveBiped.Bip01_L_Finger0"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(10, 1.11, -1.111) },
|
||||
["Detonator"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
|
||||
["ValveBiped.Bip01_L_Hand"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(-27.778, 1.11, -7.778) },
|
||||
["Slam_panel"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
|
||||
["ValveBiped.Bip01_L_Finger2"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, -47.778, 0) },
|
||||
["ValveBiped.Bip01_L_Finger3"] = { scale = Vector(1, 1, 1), pos = Vector(0, 0, 0), angle = Angle(0, -43.334, 0) },
|
||||
["Slam_base"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) },
|
||||
["ValveBiped.Bip01_R_Hand"] = { scale = Vector(0.009, 0.009, 0.009), pos = Vector(0, 0, 0), angle = Angle(0, 0, 0) }
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
|
||||
// Create a new table for every weapon instance
|
||||
self.VElements = table.FullCopy( self.VElements )
|
||||
self.WElements = table.FullCopy( self.WElements )
|
||||
self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
|
||||
|
||||
self:CreateModels(self.VElements) // create viewmodels
|
||||
self:CreateModels(self.WElements) // create worldmodels
|
||||
|
||||
// init view model bone build function
|
||||
if IsValid(self.Owner) then
|
||||
local vm = self.Owner:GetViewModel()
|
||||
if IsValid(vm) then
|
||||
self:ResetBonePositions(vm)
|
||||
|
||||
// Init viewmodel visibility
|
||||
if (self.ShowViewModel == nil or self.ShowViewModel) then
|
||||
vm:SetColor(Color(255,255,255,255))
|
||||
else
|
||||
// we set the alpha to 1 instead of 0 because else ViewModelDrawn stops being called
|
||||
vm:SetColor(Color(255,255,255,1))
|
||||
// ^ stopped working in GMod 13 because you have to do Entity:SetRenderMode(1) for translucency to kick in
|
||||
// however for some reason the view model resets to render mode 0 every frame so we just apply a debug material to prevent it from drawing
|
||||
vm:SetMaterial("Debug/hsv")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
if self.Initialize2 then self:Initialize2() end
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
if SERVER then
|
||||
cigaUpdate(self.Owner, self.cigaID)
|
||||
end
|
||||
self.Weapon:SetNextPrimaryFire(CurTime() + 0.1)
|
||||
end
|
||||
|
||||
function SWEP:Reload()
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
if SERVER and IsValid(self.Owner) then
|
||||
Releaseciga(self.Owner)
|
||||
end
|
||||
|
||||
if CLIENT and IsValid(self.Owner) then
|
||||
local vm = self.Owner:GetViewModel()
|
||||
if IsValid(vm) then
|
||||
self:ResetBonePositions(vm)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
SWEP.OnDrop = SWEP.Holster
|
||||
SWEP.OnRemove = SWEP.Holster
|
||||
@@ -0,0 +1,17 @@
|
||||
if CLIENT then
|
||||
include('weapon_ciga/cl_init.lua')
|
||||
else
|
||||
include('weapon_ciga/shared.lua')
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
end
|
||||
|
||||
SWEP.PrintName = "Camel"
|
||||
|
||||
SWEP.ViewModel = "models/oldcigshib.mdl"
|
||||
SWEP.WorldModel = "models/oldcigshib.mdl"
|
||||
|
||||
SWEP.cigaID = 3
|
||||
|
||||
SWEP.cigaAccentColor = Vector(1,1,1.1)
|
||||
@@ -0,0 +1,89 @@
|
||||
if CLIENT then
|
||||
include('weapon_ciga/cl_init.lua')
|
||||
else
|
||||
include('weapon_ciga/shared.lua')
|
||||
end
|
||||
|
||||
SWEP.PrintName = "Newport"
|
||||
|
||||
SWEP.cigaAccentColor = nil
|
||||
|
||||
SWEP.cigaID = 4
|
||||
SWEP.ViewModel = "models/ciga.mdl"
|
||||
SWEP.WorldModel = "models/ciga.mdl"
|
||||
|
||||
--Add your own flavors here, obviously
|
||||
JuicycigaJuices = {
|
||||
{name = "without filter", color = Color(40,40,40,255)},
|
||||
{name = "with filter", color = Color(210,180,140,255)},
|
||||
}
|
||||
|
||||
if SERVER then
|
||||
function SWEP:Initialize2()
|
||||
self.juiceID = 0
|
||||
timer.Simple(0.1, function() SendcigaJuice(self, JuicycigaJuices[self.juiceID+1]) end)
|
||||
end
|
||||
|
||||
util.AddNetworkString("cigaTankColor")
|
||||
util.AddNetworkString("cigaMessage")
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
if SERVER then
|
||||
if not self.juiceID then self.juiceID = 0 end
|
||||
self.juiceID = (self.juiceID + 1) % (#JuicycigaJuices)
|
||||
SendcigaJuice(self, JuicycigaJuices[self.juiceID+1])
|
||||
|
||||
--Client hook isn't called in singleplayer
|
||||
if game.SinglePlayer() then self.Owner:SendLua([[surface.PlaySound("weapons/smg1/switch_single.wav")]]) end
|
||||
else
|
||||
if IsFirstTimePredicted() then
|
||||
surface.PlaySound("weapons/smg1/switch_single.wav")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
function SendcigaJuice(ent, tab)
|
||||
local col = tab.color
|
||||
if col then
|
||||
local min = math.min(col.r,col.g,col.b)*0.8
|
||||
col = (Vector(col.r-min, col.g-min, col.b-min)*1.0)/255.0
|
||||
else
|
||||
col = Vector(-1,-1,-1)
|
||||
end
|
||||
net.Start("cigaTankColor")
|
||||
net.WriteEntity(ent)
|
||||
net.WriteVector(col)
|
||||
net.Broadcast()
|
||||
|
||||
if IsValid(ent.Owner) then
|
||||
net.Start("cigaMessage")
|
||||
net.WriteString("Loaded "..tab.name.."")
|
||||
net.Send(ent.Owner)
|
||||
end
|
||||
end
|
||||
else
|
||||
net.Receive("cigaTankColor", function()
|
||||
local ent = net.ReadEntity()
|
||||
local col = net.ReadVector()
|
||||
if IsValid(ent) then ent.cigaTankColor = col end
|
||||
end)
|
||||
|
||||
cigaMessageDisplay = ""
|
||||
cigaMessageDisplayTime = 0
|
||||
|
||||
net.Receive("cigaMessage", function()
|
||||
cigaMessageDisplay = net.ReadString()
|
||||
cigaMessageDisplayTime = CurTime()
|
||||
end)
|
||||
|
||||
hook.Add("HUDPaint", "cigaDrawJuiceMessage", function()
|
||||
local alpha = math.Clamp((cigaMessageDisplayTime+3-CurTime())*1.5,0,1)
|
||||
if alpha == 0 then return end
|
||||
|
||||
surface.SetFont("Trebuchet24")
|
||||
local w,h = surface.GetTextSize(cigaMessageDisplay)
|
||||
draw.WordBox(8, ((ScrW() - w)/2)-8, ScrH() - (h + 24), cigaMessageDisplay, "Trebuchet24", Color(0,0,0,128*alpha), Color(255,255,255,255*alpha))
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,830 @@
|
||||
CreateConVar( "lordi_sledge_break_doors", "1", { FCVAR_REPLICATED, FCVAR_NOTIFY }, "Should people be able to break down doors using the sledgehammer? 1 for true, 0 for false" )
|
||||
CreateConVar( "lordi_sledge_break_doors_chance", "5", { FCVAR_REPLICATED, FCVAR_NOTIFY }, "What should the 1/<command> chance be before a door breaks? The higher this is, the harder it is. 1 makes it break immediadly" )
|
||||
|
||||
SWEP.WElements = {
|
||||
["sledge"] = { type = "Model", model = "models/weapons/lordi/c_sledgehammer.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(-16.33, -3.294, -16.605), angle = Angle(8.395, 0, -115.988), size = Vector(1, 1, 1), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
|
||||
}
|
||||
|
||||
SWEP.ViewModelFOV = 70
|
||||
SWEP.ViewModel = "models/weapons/lordi/c_sledgehammer.mdl"
|
||||
SWEP.WorldModel = "models/weapons/w_crowbar.mdl"
|
||||
SWEP.UseHands = true
|
||||
SWEP.AutoSwitchTo = true
|
||||
SWEP.Slot = 0
|
||||
SWEP.HoldType = "passive"
|
||||
SWEP.Spawnable = true
|
||||
SWEP.AdminSpawnable = false
|
||||
SWEP.DrawCrosshair = false
|
||||
SWEP.Category = "[FT] Специальное Оружие"
|
||||
SWEP.SlotPos = 0
|
||||
SWEP.DrawAmmo = true
|
||||
SWEP.PrintName = "Sledgehammer"
|
||||
SWEP.Author = "LordiAnders"
|
||||
SWEP.Instructions = "Bash heads in! Or if they are afar, throw the thing after them!"
|
||||
SWEP.ShowViewModel = true
|
||||
SWEP.ShowWorldModel = true
|
||||
|
||||
SWEP.Primary.ClipSize = -1
|
||||
SWEP.Primary.DefaultClip = -1
|
||||
SWEP.Primary.Ammo = "none"
|
||||
SWEP.Primary.Automatic = true
|
||||
|
||||
SWEP.Secondary.ClipSize = -1
|
||||
SWEP.Secondary.Ammo = "none"
|
||||
SWEP.Secondary.Automatic = true
|
||||
|
||||
SWEP.AboutToSwing = false
|
||||
SWEP.IsSwinging = false
|
||||
|
||||
SWEP.AboutToSwing2 = false
|
||||
SWEP.IsSwinging2 = false
|
||||
|
||||
if CLIENT then
|
||||
SWEP.WepSelectIcon = surface.GetTextureID("vgui/entities/weapon_lordi_sledgehammer")
|
||||
killicon.Add("weapon_lordi_sledgehammer","vgui/entities/weapon_lordi_sledgehammer",Color(255,255,255,255))
|
||||
killicon.Add("ent_lordi_sledgehammer","vgui/entities/weapon_lordi_sledgehammer",Color(255,255,255,255))
|
||||
SWEP.BounceWeaponIcon = false
|
||||
end
|
||||
|
||||
function SWEP:VerifyAndSet(bone,data)
|
||||
if not IsValid(self.Owner) then return end
|
||||
local bone = self.Owner:LookupBone(bone)
|
||||
if bone then
|
||||
self.Owner:ManipulateBoneAngles(bone,data)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:SetPassiveHoldType()
|
||||
if not IsValid(self.Owner) then return end
|
||||
if CLIENT then return end
|
||||
|
||||
self:SetHoldType("passive")
|
||||
|
||||
self:VerifyAndSet('ValveBiped.Bip01_R_UpperArm',Angle(13.8940719901227,12.334109775164,14.597405385818))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_R_Hand',Angle(17,30,9))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_L_Forearm',Angle(-16.224373259067,-24.886877720213,7.8929222269922))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_L_UpperArm',Angle(-32.017127057138,-35.637168682527,16))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_L_Hand',Angle(0.17154435310358,0,0))
|
||||
end
|
||||
|
||||
function SWEP:SetMelee2HoldType()
|
||||
if not IsValid(self.Owner) then return end
|
||||
if CLIENT then return end
|
||||
|
||||
self:SetHoldType("melee2")
|
||||
|
||||
self:VerifyAndSet('ValveBiped.Bip01_R_UpperArm',Angle(0,0,0))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_R_Hand',Angle(0,0,0))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_L_Forearm',Angle(0,0,0))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_L_UpperArm',Angle(0,0,0))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_L_Hand',Angle(0,0,0))
|
||||
end
|
||||
|
||||
function SWEP:Deploy()
|
||||
self.Weapon:SendWeaponAnim(ACT_VM_DRAW)
|
||||
self:SetDeploySpeed(self.Owner:GetViewModel():SequenceDuration())
|
||||
self.Weapon:SetNextPrimaryFire( CurTime() + self.Owner:GetViewModel():SequenceDuration() )
|
||||
self.Weapon:SetNextSecondaryFire( CurTime() + self.Owner:GetViewModel():SequenceDuration() )
|
||||
|
||||
self.AboutToSwing = true --Just to disable holstering
|
||||
|
||||
self:SetPassiveHoldType()
|
||||
|
||||
if SERVER then
|
||||
timer.Simple(0.9,function()
|
||||
if not self:IsValid() then return end
|
||||
self:EmitSound("npc/combine_soldier/gear6.wav")
|
||||
self.Owner:ViewPunch( Angle(-2,0,1) )
|
||||
end)
|
||||
timer.Simple(2,function()
|
||||
if not self:IsValid() then return end
|
||||
self.Owner:ViewPunch( Angle(5,0,-5) )
|
||||
self:EmitSound("physics/flesh/flesh_impact_hard2.wav",75,180)
|
||||
self.AboutToSwing = false
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:Think()
|
||||
if self.IsSwinging and not self.Owner:KeyDown(IN_ATTACK) then
|
||||
self:PrimaryAttack()
|
||||
elseif self.IsSwinging2 and not self.Owner:KeyDown(IN_ATTACK2) then
|
||||
self:SecondaryAttack()
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
if self.IsSwinging2 or self.AboutToSwing2 then return end
|
||||
if not self.IsSwinging then
|
||||
self.AboutToSwing = true
|
||||
self:SetMelee2HoldType()
|
||||
self.Weapon:SetNextPrimaryFire( CurTime() + 5000 )
|
||||
self.Weapon:SendWeaponAnim(ACT_VM_PRIMARYATTACK)
|
||||
timer.Simple(self.Owner:GetViewModel():SequenceDuration(),function()
|
||||
self.AboutToSwing = false
|
||||
self.IsSwinging = true
|
||||
end)
|
||||
end
|
||||
|
||||
if self.IsSwinging then
|
||||
--Trace shit from weapon_fists.lua packed with Gmod
|
||||
self.Owner:SetAnimation( PLAYER_ATTACK1 )
|
||||
timer.Simple(0.25,function() if not self:IsValid() then return end self:SetPassiveHoldType() end)
|
||||
local trace = util.TraceLine( {
|
||||
start = self.Owner:GetShootPos(),
|
||||
endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * 105,
|
||||
filter = self.Owner
|
||||
} )
|
||||
|
||||
if ( !IsValid( trace.Entity ) ) then
|
||||
trace = util.TraceHull( {
|
||||
start = self.Owner:GetShootPos(),
|
||||
endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * 105,
|
||||
filter = self.Owner,
|
||||
mins = Vector( -10, -10, -8 ),
|
||||
maxs = Vector( 10, 10, 8 )
|
||||
} )
|
||||
end
|
||||
|
||||
if trace.Entity:IsValid() or trace.HitWorld then
|
||||
self.Weapon:SendWeaponAnim(ACT_VM_HITKILL)
|
||||
self.Owner:ViewPunch( Angle(-10,0,0) )
|
||||
timer.Simple(0.1,function()
|
||||
if not self:IsValid() then return end
|
||||
self.Owner:ViewPunch( Angle(15,0,0) )
|
||||
end)
|
||||
if trace.Entity:IsValid() then
|
||||
if trace.Entity:IsPlayer() or trace.Entity:IsNPC() then
|
||||
if SERVER then trace.Entity:EmitSound("physics/body/body_medium_break"..math.random(2,4)..".wav",75,math.random(70,90)) end
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin(trace.HitPos)
|
||||
effectdata:SetEntity(trace.Entity)
|
||||
util.Effect( "BloodImpact", effectdata )
|
||||
elseif trace.Entity:GetClass() == "prop_door_rotating" and GetConVarNumber( "lordi_sledge_break_doors" ) == 1 then
|
||||
if SERVER and math.random(1,GetConVarNumber( "lordi_sledge_break_doors_chance" )) == 1 then
|
||||
trace.Entity:Fire("unlock")
|
||||
trace.Entity:Fire("open")
|
||||
|
||||
trace.Entity:SetNotSolid(true)
|
||||
trace.Entity:SetNoDraw(true)
|
||||
|
||||
--Bit of madcow stuff here... :L
|
||||
|
||||
local ent = ents.Create("prop_physics")
|
||||
|
||||
trace.Entity:EmitSound("physics/wood/wood_furniture_break1.wav")
|
||||
|
||||
ent:SetPos(trace.Entity:GetPos())
|
||||
ent:SetAngles(trace.Entity:GetAngles())
|
||||
ent:SetModel(trace.Entity:GetModel())
|
||||
|
||||
if trace.Entity:GetSkin() then
|
||||
ent:SetSkin(trace.Entity:GetSkin())
|
||||
end
|
||||
|
||||
ent:Spawn()
|
||||
|
||||
ent:GetPhysicsObject():ApplyForceCenter( self.Owner:GetAimVector() * 10000 )
|
||||
|
||||
timer.Simple(25,function()
|
||||
if ent:IsValid() then
|
||||
ent:Remove()
|
||||
end
|
||||
trace.Entity:SetNotSolid(false)
|
||||
trace.Entity:SetNoDraw(false)
|
||||
end)
|
||||
elseif SERVER then
|
||||
trace.Entity:EmitSound("physics/wood/wood_box_break"..math.random(1,2)..".wav",75,math.random(50,150))
|
||||
end
|
||||
end
|
||||
if SERVER then trace.Entity:TakeDamage(math.random(70,120),self.Owner) end
|
||||
end
|
||||
if trace.HitWorld then
|
||||
local trace = self.Owner:GetEyeTrace()
|
||||
|
||||
if self.Owner:GetShootPos():Distance(trace.HitPos) <= 105 then
|
||||
util.Decal("Impact.Sand",trace.HitPos + trace.HitNormal,trace.HitPos - trace.HitNormal)
|
||||
end
|
||||
end
|
||||
if SERVER then timer.Simple(0,function() if not self:IsValid() then return end self:EmitSound("physics/metal/metal_canister_impact_hard"..math.random(1,3)..".wav",75,math.random(90,110)) end) end
|
||||
else
|
||||
self.Weapon:SendWeaponAnim(ACT_VM_MISSCENTER)
|
||||
if SERVER then timer.Simple(0,function() if not self:IsValid() then return end self:EmitSound("npc/zombie/claw_miss1.wav",75,60) end) end
|
||||
self.Owner:ViewPunch( Angle(-10,0,0) )
|
||||
timer.Simple(0.1,function()
|
||||
if not self:IsValid() then return end
|
||||
self.Owner:ViewPunch( Angle(30,0,0) )
|
||||
end)
|
||||
end
|
||||
self.IsSwinging = false
|
||||
self.Weapon:SetNextPrimaryFire( CurTime() + 1 )
|
||||
self.Weapon:SetNextSecondaryFire( CurTime() + 1 )
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetViewModelPosition(pos, ang)
|
||||
if self.IsSwinging then
|
||||
pos = pos + (math.random(-1,1) / 40) * ang:Right()
|
||||
pos = pos + (math.random(-1,1) / 40) * ang:Forward()
|
||||
pos = pos + (math.random(-1,1) / 40) * ang:Up()
|
||||
end
|
||||
|
||||
return pos, ang
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
if self.IsSwinging or self.AboutToSwing then return end
|
||||
if not self.IsSwinging2 then
|
||||
self.AboutToSwing2 = true
|
||||
self:SetMelee2HoldType()
|
||||
self.Weapon:SetNextSecondaryFire( CurTime() + 5000 )
|
||||
self.Weapon:SendWeaponAnim(ACT_VM_PRIMARYATTACK)
|
||||
timer.Simple(self.Owner:GetViewModel():SequenceDuration(),function()
|
||||
self.AboutToSwing2 = false
|
||||
self.IsSwinging2 = true
|
||||
end)
|
||||
end
|
||||
|
||||
if self.IsSwinging2 then
|
||||
self.IsSwinging2 = false
|
||||
self.Weapon:SendWeaponAnim(ACT_VM_MISSCENTER)
|
||||
timer.Simple(0.1,function()
|
||||
if SERVER then
|
||||
local sledge = ents.Create("ent_lordi_sledgehammer")
|
||||
sledge:SetOwner(self.Owner)
|
||||
sledge:SetPos(self.Owner:EyePos() + self.Owner:GetAimVector())
|
||||
sledge:SetAngles(self.Owner:GetAngles())
|
||||
sledge:Spawn()
|
||||
sledge:Activate()
|
||||
|
||||
sledge:GetPhysicsObject():ApplyForceCenter( self.Owner:GetAimVector() * 7000 )
|
||||
|
||||
timer.Simple(0.25,function() self.Owner:StripWeapon(self:GetClass()) end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:Reload() end
|
||||
|
||||
function SWEP:OnRemove()
|
||||
if IsValid(self.Owner) then
|
||||
self:VerifyAndSet('ValveBiped.Bip01_R_UpperArm',Angle(0,0,0))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_R_Hand',Angle(0,0,0))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_L_Forearm',Angle(0,0,0))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_L_UpperArm',Angle(0,0,0))
|
||||
self:VerifyAndSet('ValveBiped.Bip01_L_Hand',Angle(0,0,0))
|
||||
local vm = self.Owner:GetViewModel()
|
||||
if IsValid(vm) then vm:SetMaterial("") end
|
||||
end
|
||||
if CLIENT and IsValid(self.Owner) then
|
||||
local vm = self.Owner:GetViewModel()
|
||||
if IsValid(vm) then
|
||||
self:ResetBonePositions(vm)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
/********************************************************
|
||||
SWEP Construction Kit base code
|
||||
Created by Clavus
|
||||
Available for public use, thread at:
|
||||
facepunch.com/threads/1032378
|
||||
|
||||
|
||||
DESCRIPTION:
|
||||
This script is meant for experienced scripters
|
||||
that KNOW WHAT THEY ARE DOING. Don't come to me
|
||||
with basic Lua questions.
|
||||
|
||||
Just copy into your SWEP or SWEP base of choice
|
||||
and merge with your own code.
|
||||
|
||||
The SWEP.VElements, SWEP.WElements and
|
||||
SWEP.ViewModelBoneMods tables are all optional
|
||||
and only have to be visible to the client.
|
||||
********************************************************/
|
||||
|
||||
function SWEP:Initialize()
|
||||
self:SetHoldType(self.HoldType)
|
||||
|
||||
// other initialize code goes here
|
||||
|
||||
if CLIENT then
|
||||
|
||||
// Create a new table for every weapon instance
|
||||
self.VElements = table.FullCopy( self.VElements )
|
||||
self.WElements = table.FullCopy( self.WElements )
|
||||
self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
|
||||
|
||||
self:CreateModels(self.VElements) // create viewmodels
|
||||
self:CreateModels(self.WElements) // create worldmodels
|
||||
|
||||
// init view model bone build function
|
||||
if IsValid(self.Owner) then
|
||||
local vm = self.Owner:GetViewModel()
|
||||
if IsValid(vm) then
|
||||
self:ResetBonePositions(vm)
|
||||
end
|
||||
|
||||
// Init viewmodel visibility
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
|
||||
if self.AboutToSwing or self.IsSwinging or self.IsSwinging2 or self.AboutToSwing2 then return end
|
||||
|
||||
self:OnRemove()
|
||||
|
||||
if CLIENT and IsValid(self.Owner) then
|
||||
local vm = self.Owner:GetViewModel()
|
||||
if IsValid(vm) then
|
||||
self:ResetBonePositions(vm)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
|
||||
SWEP.vRenderOrder = nil
|
||||
function SWEP:ViewModelDrawn()
|
||||
|
||||
local vm = self.Owner:GetViewModel()
|
||||
if !IsValid(vm) then return end
|
||||
|
||||
if (!self.VElements) then return end
|
||||
|
||||
self:UpdateBonePositions(vm)
|
||||
|
||||
if (!self.vRenderOrder) then
|
||||
|
||||
// we build a render order because sprites need to be drawn after models
|
||||
self.vRenderOrder = {}
|
||||
|
||||
for k, v in pairs( self.VElements ) do
|
||||
if (v.type == "Model") then
|
||||
table.insert(self.vRenderOrder, 1, k)
|
||||
elseif (v.type == "Sprite" or v.type == "Quad") then
|
||||
table.insert(self.vRenderOrder, k)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
for k, name in ipairs( self.vRenderOrder ) do
|
||||
|
||||
local v = self.VElements[name]
|
||||
if (!v) then self.vRenderOrder = nil break end
|
||||
if (v.hide) then continue end
|
||||
|
||||
local model = v.modelEnt
|
||||
local sprite = v.spriteMaterial
|
||||
|
||||
if (!v.bone) then continue end
|
||||
|
||||
local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
|
||||
|
||||
if (!pos) then continue end
|
||||
|
||||
if (v.type == "Model" and IsValid(model)) then
|
||||
|
||||
model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
|
||||
ang:RotateAroundAxis(ang:Up(), v.angle.y)
|
||||
ang:RotateAroundAxis(ang:Right(), v.angle.p)
|
||||
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
|
||||
|
||||
model:SetAngles(ang)
|
||||
//model:SetModelScale(v.size)
|
||||
local matrix = Matrix()
|
||||
matrix:Scale(v.size)
|
||||
model:EnableMatrix( "RenderMultiply", matrix )
|
||||
|
||||
if (v.material == "") then
|
||||
model:SetMaterial("")
|
||||
elseif (model:GetMaterial() != v.material) then
|
||||
model:SetMaterial( v.material )
|
||||
end
|
||||
|
||||
if (v.skin and v.skin != model:GetSkin()) then
|
||||
model:SetSkin(v.skin)
|
||||
end
|
||||
|
||||
if (v.bodygroup) then
|
||||
for k, v in pairs( v.bodygroup ) do
|
||||
if (model:GetBodygroup(k) != v) then
|
||||
model:SetBodygroup(k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (v.surpresslightning) then
|
||||
render.SuppressEngineLighting(true)
|
||||
end
|
||||
|
||||
render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
|
||||
render.SetBlend(v.color.a/255)
|
||||
model:DrawModel()
|
||||
render.SetBlend(1)
|
||||
render.SetColorModulation(1, 1, 1)
|
||||
|
||||
if (v.surpresslightning) then
|
||||
render.SuppressEngineLighting(false)
|
||||
end
|
||||
|
||||
elseif (v.type == "Sprite" and sprite) then
|
||||
|
||||
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
|
||||
render.SetMaterial(sprite)
|
||||
render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
|
||||
|
||||
elseif (v.type == "Quad" and v.draw_func) then
|
||||
|
||||
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
|
||||
ang:RotateAroundAxis(ang:Up(), v.angle.y)
|
||||
ang:RotateAroundAxis(ang:Right(), v.angle.p)
|
||||
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
|
||||
|
||||
cam.Start3D2D(drawpos, ang, v.size)
|
||||
v.draw_func( self )
|
||||
cam.End3D2D()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
SWEP.wRenderOrder = nil
|
||||
function SWEP:DrawWorldModel()
|
||||
|
||||
self:DrawModel()
|
||||
self:SetMaterial( "engine/occlusionproxy" )
|
||||
|
||||
if (!self.WElements) then return end
|
||||
|
||||
if (!self.wRenderOrder) then
|
||||
|
||||
self.wRenderOrder = {}
|
||||
|
||||
for k, v in pairs( self.WElements ) do
|
||||
if (v.type == "Model") then
|
||||
table.insert(self.wRenderOrder, 1, k)
|
||||
elseif (v.type == "Sprite" or v.type == "Quad") then
|
||||
table.insert(self.wRenderOrder, k)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if (IsValid(self.Owner)) then
|
||||
bone_ent = self.Owner
|
||||
else
|
||||
// when the weapon is dropped
|
||||
bone_ent = self
|
||||
end
|
||||
|
||||
for k, name in pairs( self.wRenderOrder ) do
|
||||
|
||||
local v = self.WElements[name]
|
||||
if (!v) then self.wRenderOrder = nil break end
|
||||
if (v.hide) then continue end
|
||||
|
||||
local pos, ang
|
||||
|
||||
if (v.bone) then
|
||||
pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
|
||||
else
|
||||
pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
|
||||
end
|
||||
|
||||
if (!pos) then continue end
|
||||
|
||||
local model = v.modelEnt
|
||||
local sprite = v.spriteMaterial
|
||||
|
||||
if (v.type == "Model" and IsValid(model)) then
|
||||
|
||||
model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
|
||||
ang:RotateAroundAxis(ang:Up(), v.angle.y)
|
||||
ang:RotateAroundAxis(ang:Right(), v.angle.p)
|
||||
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
|
||||
|
||||
model:SetAngles(ang)
|
||||
//model:SetModelScale(v.size)
|
||||
local matrix = Matrix()
|
||||
matrix:Scale(v.size)
|
||||
model:EnableMatrix( "RenderMultiply", matrix )
|
||||
|
||||
if (v.material == "") then
|
||||
model:SetMaterial("")
|
||||
elseif (model:GetMaterial() != v.material) then
|
||||
model:SetMaterial( v.material )
|
||||
end
|
||||
|
||||
if (v.skin and v.skin != model:GetSkin()) then
|
||||
model:SetSkin(v.skin)
|
||||
end
|
||||
|
||||
if (v.bodygroup) then
|
||||
for k, v in pairs( v.bodygroup ) do
|
||||
if (model:GetBodygroup(k) != v) then
|
||||
model:SetBodygroup(k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (v.surpresslightning) then
|
||||
render.SuppressEngineLighting(true)
|
||||
end
|
||||
|
||||
render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
|
||||
render.SetBlend(v.color.a/255)
|
||||
model:DrawModel()
|
||||
render.SetBlend(1)
|
||||
render.SetColorModulation(1, 1, 1)
|
||||
|
||||
if (v.surpresslightning) then
|
||||
render.SuppressEngineLighting(false)
|
||||
end
|
||||
|
||||
elseif (v.type == "Sprite" and sprite) then
|
||||
|
||||
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
|
||||
render.SetMaterial(sprite)
|
||||
render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
|
||||
|
||||
elseif (v.type == "Quad" and v.draw_func) then
|
||||
|
||||
local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
|
||||
ang:RotateAroundAxis(ang:Up(), v.angle.y)
|
||||
ang:RotateAroundAxis(ang:Right(), v.angle.p)
|
||||
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
|
||||
|
||||
cam.Start3D2D(drawpos, ang, v.size)
|
||||
v.draw_func( self )
|
||||
cam.End3D2D()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
|
||||
|
||||
local bone, pos, ang
|
||||
if (tab.rel and tab.rel != "") then
|
||||
|
||||
local v = basetab[tab.rel]
|
||||
|
||||
if (!v) then return end
|
||||
|
||||
// Technically, if there exists an element with the same name as a bone
|
||||
// you can get in an infinite loop. Let's just hope nobody's that stupid.
|
||||
pos, ang = self:GetBoneOrientation( basetab, v, ent )
|
||||
|
||||
if (!pos) then return end
|
||||
|
||||
pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
|
||||
ang:RotateAroundAxis(ang:Up(), v.angle.y)
|
||||
ang:RotateAroundAxis(ang:Right(), v.angle.p)
|
||||
ang:RotateAroundAxis(ang:Forward(), v.angle.r)
|
||||
|
||||
else
|
||||
|
||||
bone = ent:LookupBone(bone_override or tab.bone)
|
||||
|
||||
if (!bone) then return end
|
||||
|
||||
pos, ang = Vector(0,0,0), Angle(0,0,0)
|
||||
local m = ent:GetBoneMatrix(bone)
|
||||
if (m) then
|
||||
pos, ang = m:GetTranslation(), m:GetAngles()
|
||||
end
|
||||
|
||||
if (IsValid(self.Owner) and self.Owner:IsPlayer() and
|
||||
ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
|
||||
ang.r = -ang.r // Fixes mirrored models
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return pos, ang
|
||||
end
|
||||
|
||||
function SWEP:CreateModels( tab )
|
||||
|
||||
if (!tab) then return end
|
||||
|
||||
// Create the clientside models here because Garry says we can't do it in the render hook
|
||||
for k, v in pairs( tab ) do
|
||||
if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
|
||||
string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
|
||||
|
||||
v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
|
||||
if (IsValid(v.modelEnt)) then
|
||||
v.modelEnt:SetPos(self:GetPos())
|
||||
v.modelEnt:SetAngles(self:GetAngles())
|
||||
v.modelEnt:SetParent(self)
|
||||
v.modelEnt:SetNoDraw(true)
|
||||
v.createdModel = v.model
|
||||
else
|
||||
v.modelEnt = nil
|
||||
end
|
||||
|
||||
elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
|
||||
and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
|
||||
|
||||
local name = v.sprite.."-"
|
||||
local params = { ["$basetexture"] = v.sprite }
|
||||
// make sure we create a unique name based on the selected options
|
||||
local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
|
||||
for i, j in pairs( tocheck ) do
|
||||
if (v[j]) then
|
||||
params["$"..j] = 1
|
||||
name = name.."1"
|
||||
else
|
||||
name = name.."0"
|
||||
end
|
||||
end
|
||||
|
||||
v.createdSprite = v.sprite
|
||||
v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local allbones
|
||||
local hasGarryFixedBoneScalingYet = false
|
||||
|
||||
function SWEP:UpdateBonePositions2(vm)
|
||||
|
||||
if self.GrenadeThrowBoneMods then
|
||||
|
||||
if (!vm:GetBoneCount()) then return end
|
||||
|
||||
local loopthrough = self.GrenadeThrowBoneMods
|
||||
if (!hasGarryFixedBoneScalingYet) then
|
||||
allbones = {}
|
||||
for i=0, vm:GetBoneCount() do
|
||||
local bonename = vm:GetBoneName(i)
|
||||
if (self.GrenadeThrowBoneMods[bonename]) then
|
||||
allbones[bonename] = self.GrenadeThrowBoneMods[bonename]
|
||||
else
|
||||
allbones[bonename] = {
|
||||
scale = Vector(1,1,1),
|
||||
pos = Vector(0,0,0),
|
||||
angle = Angle(0,0,0)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
loopthrough = allbones
|
||||
end
|
||||
|
||||
for k, v in pairs( loopthrough ) do
|
||||
local bone = vm:LookupBone(k)
|
||||
if (!bone) then continue end
|
||||
|
||||
local s = Vector(v.scale.x,v.scale.y,v.scale.z)
|
||||
local p = Vector(v.pos.x,v.pos.y,v.pos.z)
|
||||
local ms = Vector(1,1,1)
|
||||
if (!hasGarryFixedBoneScalingYet) then
|
||||
local cur = vm:GetBoneParent(bone)
|
||||
while(cur >= 0) do
|
||||
local pscale = loopthrough[vm:GetBoneName(cur)].scale
|
||||
ms = ms * pscale
|
||||
cur = vm:GetBoneParent(cur)
|
||||
end
|
||||
end
|
||||
|
||||
s = s * ms
|
||||
|
||||
if vm:GetManipulateBoneScale(bone) != s then
|
||||
vm:ManipulateBoneScale( bone, s )
|
||||
end
|
||||
if vm:GetManipulateBoneAngles(bone) != v.angle then
|
||||
vm:ManipulateBoneAngles( bone, v.angle )
|
||||
end
|
||||
if vm:GetManipulateBonePosition(bone) != p then
|
||||
vm:ManipulateBonePosition( bone, p )
|
||||
end
|
||||
end
|
||||
else
|
||||
self:ResetBonePositions(vm)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SWEP:UpdateBonePositions(vm)
|
||||
|
||||
if self.ViewModelBoneMods then
|
||||
|
||||
if (!vm:GetBoneCount()) then return end
|
||||
|
||||
// !! WORKAROUND !! //
|
||||
// We need to check all model names :/
|
||||
local loopthrough = self.ViewModelBoneMods
|
||||
if (!hasGarryFixedBoneScalingYet) then
|
||||
allbones = {}
|
||||
for i=0, vm:GetBoneCount() do
|
||||
local bonename = vm:GetBoneName(i)
|
||||
if (self.ViewModelBoneMods[bonename]) then
|
||||
allbones[bonename] = self.ViewModelBoneMods[bonename]
|
||||
else
|
||||
allbones[bonename] = {
|
||||
scale = Vector(1,1,1),
|
||||
pos = Vector(0,0,0),
|
||||
angle = Angle(0,0,0)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
loopthrough = allbones
|
||||
end
|
||||
// !! ----------- !! //
|
||||
|
||||
for k, v in pairs( loopthrough ) do
|
||||
local bone = vm:LookupBone(k)
|
||||
if (!bone) then continue end
|
||||
|
||||
// !! WORKAROUND !! //
|
||||
local s = Vector(v.scale.x,v.scale.y,v.scale.z)
|
||||
local p = Vector(v.pos.x,v.pos.y,v.pos.z)
|
||||
local ms = Vector(1,1,1)
|
||||
if (!hasGarryFixedBoneScalingYet) then
|
||||
local cur = vm:GetBoneParent(bone)
|
||||
while(cur >= 0) do
|
||||
local pscale = loopthrough[vm:GetBoneName(cur)].scale
|
||||
ms = ms * pscale
|
||||
cur = vm:GetBoneParent(cur)
|
||||
end
|
||||
end
|
||||
|
||||
s = s * ms
|
||||
// !! ----------- !! //
|
||||
|
||||
if vm:GetManipulateBoneScale(bone) != s then
|
||||
vm:ManipulateBoneScale( bone, s )
|
||||
end
|
||||
if vm:GetManipulateBoneAngles(bone) != v.angle then
|
||||
vm:ManipulateBoneAngles( bone, v.angle )
|
||||
end
|
||||
if vm:GetManipulateBonePosition(bone) != p then
|
||||
vm:ManipulateBonePosition( bone, p )
|
||||
end
|
||||
end
|
||||
else
|
||||
self:ResetBonePositions(vm)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SWEP:ResetBonePositions(vm)
|
||||
|
||||
if (!vm:GetBoneCount()) then return end
|
||||
for i=0, vm:GetBoneCount() do
|
||||
vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
|
||||
vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
|
||||
vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
/**************************
|
||||
Global utility code
|
||||
**************************/
|
||||
|
||||
// Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
|
||||
// Does not copy entities of course, only copies their reference.
|
||||
// WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
|
||||
function table.FullCopy( tab )
|
||||
|
||||
if (!tab) then return nil end
|
||||
|
||||
local res = {}
|
||||
for k, v in pairs( tab ) do
|
||||
if (type(v) == "table") then
|
||||
res[k] = table.FullCopy(v) // recursion ho!
|
||||
elseif (type(v) == "Vector") then
|
||||
res[k] = Vector(v.x, v.y, v.z)
|
||||
elseif (type(v) == "Angle") then
|
||||
res[k] = Angle(v.p, v.y, v.r)
|
||||
else
|
||||
res[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user