Initial commit
This commit is contained in:
541
addons/nyxteam_printer/lua/entities/nyxteam_printer/cl_init.lua
Normal file
541
addons/nyxteam_printer/lua/entities/nyxteam_printer/cl_init.lua
Normal file
@@ -0,0 +1,541 @@
|
||||
--[[
|
||||
|
||||
_ ___ ____ __ _______ ______ __ __
|
||||
| \ | \ \ / /\ \ / / |__ __| ____| /\ | \/ |
|
||||
| \| |\ \_/ / \ V / | | | |__ / \ | \ / |
|
||||
| . ` | \ / > < | | | __| / /\ \ | |\/| |
|
||||
| |\ | | | / . \ | | | |____ / ____ \| | | |
|
||||
|_| \_| |_| /_/ \_\ |_| |______/_/ \_\_| |_|
|
||||
|
||||
JOIN DISCORD: https://discord.gg/rUEEz4mfXw
|
||||
BY NYX TEAM (MaryBlackfild lead)
|
||||
Copyrighted Nyx Team + YouGame.biz
|
||||
|
||||
--]]
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
local CSND = ENT.SND or {}
|
||||
local RNDX = _G.gSims_RNDX
|
||||
if not RNDX then RNDX = include("libnyx/lib/rndx.lua") end
|
||||
|
||||
local MAT_MONEY = Material("icon16/money.png")
|
||||
local MAT_STAR = Material("icon16/star.png")
|
||||
local MAT_GRAD = Material("gui/gradient_down")
|
||||
|
||||
local COL = {
|
||||
white = Color(255, 255, 255),
|
||||
text_dim = Color(255, 255, 255, 100),
|
||||
accent = Color(65, 120, 255),
|
||||
red = Color(255, 80, 80),
|
||||
green = Color(80, 220, 120),
|
||||
mint = Color(130, 235, 160),
|
||||
orange = Color(255, 160, 60),
|
||||
purple = Color(160, 100, 255),
|
||||
dark_bg = Color(12, 12, 18, 250),
|
||||
glass_top = Color(255, 255, 255, 10)
|
||||
}
|
||||
|
||||
local function DrawGrid(x, y, w, h, size, alpha)
|
||||
surface.SetDrawColor(255, 255, 255, alpha)
|
||||
for i = 0, w, size do surface.DrawLine(x + i, y, x + i, y + h) end
|
||||
for i = 0, h, size do surface.DrawLine(x, y + i, x + w, y + i) end
|
||||
end
|
||||
|
||||
local function SpawnParticles(pos, type)
|
||||
local em = ParticleEmitter(pos)
|
||||
local mat = (type == 1) and MAT_MONEY or MAT_STAR
|
||||
local col = (type == 1) and Color(255,255,255) or Color(255,220,100)
|
||||
for i = 1, 15 do
|
||||
local p = em:Add(mat, pos + VectorRand() * 5)
|
||||
p:SetVelocity(VectorRand() * 40 + Vector(0,0,60))
|
||||
p:SetDieTime(math.Rand(1.5, 2.5))
|
||||
p:SetStartAlpha(255)
|
||||
p:SetEndAlpha(0)
|
||||
p:SetStartSize(12)
|
||||
p:SetEndSize(0)
|
||||
p:SetRoll(math.Rand(0, 360))
|
||||
p:SetGravity(Vector(0,0,-150))
|
||||
p:SetColor(col.r, col.g, col.b)
|
||||
end
|
||||
em:Finish()
|
||||
end
|
||||
|
||||
local function CreateFonts()
|
||||
local sizes = {10, 12, 14, 16, 18, 20, 24, 32, 48, 54}
|
||||
for _, sz in ipairs(sizes) do
|
||||
surface.CreateFont("gSims.Manrope." .. sz, { font = "Manrope", size = sz, weight = 600, extended = true, antialias = true })
|
||||
end
|
||||
surface.CreateFont("gSims.Manrope.Bold", { font = "Manrope", size = 22, weight = 800, extended = true, antialias = true })
|
||||
surface.CreateFont("gSims.Manrope.Display", { font = "Manrope", size = 54, weight = 800, extended = true, antialias = true })
|
||||
end
|
||||
CreateFonts()
|
||||
|
||||
local function SendAct(ent, act, arg)
|
||||
net.Start("gsims_printer_action")
|
||||
net.WriteEntity(ent)
|
||||
net.WriteString(act)
|
||||
net.WriteString(arg or "")
|
||||
net.SendToServer()
|
||||
end
|
||||
|
||||
local function RegisterAnim(pnl, startTime, delay)
|
||||
local oldPaint = pnl.Paint
|
||||
pnl.Paint = function(s, w, h)
|
||||
local anim = math.ease.OutCubic(math.Clamp((SysTime() - startTime - delay) / 0.25, 0, 1))
|
||||
if anim <= 0 then return end
|
||||
s:SetAlpha(255 * anim)
|
||||
local m = Matrix()
|
||||
m:Translate(Vector(0, (1 - anim) * 15, 0))
|
||||
cam.PushModelMatrix(m)
|
||||
oldPaint(s, w, h)
|
||||
cam.PopModelMatrix()
|
||||
end
|
||||
end
|
||||
|
||||
local function CreateGlassButton(parent, x, y, w, h, textArg, font, colArg, onClick, extraPaint)
|
||||
local btn = vgui.Create("DButton", parent)
|
||||
btn:SetPos(x, y)
|
||||
btn:SetSize(w, h)
|
||||
btn:SetText("")
|
||||
local hov, ripple = 0, 0
|
||||
local rippleX, rippleY = 0, 0
|
||||
|
||||
btn.Paint = function(s, bw, bh)
|
||||
hov = math.Approach(hov, s:IsHovered() and 1 or 0, FrameTime() * 10)
|
||||
local col, txt = (isfunction(colArg) and colArg() or colArg), (isfunction(textArg) and textArg() or textArg)
|
||||
|
||||
RNDX().Liquid(0, 0, bw, bh)
|
||||
:Rad(12)
|
||||
:Tint(30, 30, 40)
|
||||
:TintStrength(0.6)
|
||||
:Saturation(1.06)
|
||||
:GlassBlur(0.1, 0)
|
||||
:EdgeSmooth(2)
|
||||
:Strength(0.019)
|
||||
:Speed(0.4)
|
||||
:Shimmer(25.7)
|
||||
:Grain(0.01)
|
||||
:Alpha(0.8 + (hov * 0.1))
|
||||
:Flags(RNDX.SHAPE_IOS)
|
||||
:Draw()
|
||||
|
||||
RNDX().Rect(0, 0, bw, bh):Rad(12):Outline(1):Color(col.r, col.g, col.b, 40 + hov * 50):Flags(RNDX.SHAPE_IOS):Draw()
|
||||
|
||||
if ripple > 0 then
|
||||
ripple = math.Approach(ripple, 0, FrameTime() * 1.5)
|
||||
local rw = bw * (1 - ripple) * 2.5
|
||||
local old = DisableClipping(false)
|
||||
surface.SetDrawColor(col.r, col.g, col.b, ripple * 150)
|
||||
draw.NoTexture()
|
||||
surface.DrawOutlinedRect(rippleX - rw/2, rippleY - rw/2, rw, rw, 2)
|
||||
DisableClipping(old)
|
||||
end
|
||||
|
||||
if extraPaint then extraPaint(s, bw, bh, hov) else
|
||||
draw.SimpleText(txt, font, bw / 2, bh / 2, Color(255, 255, 255, 220 + hov * 35), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
end
|
||||
end
|
||||
btn.DoClick = function(s) ripple = 1 rippleX, rippleY = s:CursorPos() if onClick then onClick() end end
|
||||
return btn
|
||||
end
|
||||
|
||||
local function CreateBar(parent, x, y, w, h, label, color, getter, ent, actName)
|
||||
local pnl = vgui.Create("DPanel", parent)
|
||||
pnl:SetPos(x, y)
|
||||
pnl:SetSize(w, h)
|
||||
pnl.Paint = function(s, bw, bh)
|
||||
local val = getter()
|
||||
local pct = math.Clamp(val / 100, 0, 1)
|
||||
RNDX().Rect(0, 18, bw, bh - 18):Rad(6):Color(0, 0, 0, 60):Draw()
|
||||
if pct > 0 then RNDX().Rect(0, 18, bw * pct, bh - 18):Rad(6):Color(color):Draw() end
|
||||
draw.SimpleText(label, "gSims.Manrope.14", 0, 0, COL.text_dim, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
|
||||
draw.SimpleText(math.floor(val) .. "%", "gSims.Manrope.14", bw, 0, COL.white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP)
|
||||
if s:IsHovered() then RNDX().Rect(0, 18, bw, bh - 18):Rad(6):Outline(1):Color(255, 255, 255, 50):Draw() end
|
||||
end
|
||||
pnl.NextAct = 0
|
||||
pnl.Think = function(s)
|
||||
if s:IsHovered() and input.IsMouseDown(MOUSE_LEFT) and CurTime() > s.NextAct then
|
||||
SendAct(ent, actName) s.NextAct = CurTime() + 0.1
|
||||
end
|
||||
end
|
||||
return pnl
|
||||
end
|
||||
|
||||
local function CreateSlotButton(parent, ent, slotId, x, y, size)
|
||||
local btn = vgui.Create("DButton", parent)
|
||||
btn:SetPos(x, y)
|
||||
btn:SetSize(size, size)
|
||||
btn:SetText("")
|
||||
local next_lab = {A="B", B="C", C="A"}
|
||||
local flipState, flipProgress = 0, 0
|
||||
local displayChar = ent.SLOTS[ent["GetSlot" .. slotId](ent)] or "A"
|
||||
|
||||
btn.Think = function(s)
|
||||
local realChar = ent.SLOTS[ent["GetSlot" .. slotId](ent)] or "A"
|
||||
if flipState == 1 then
|
||||
flipProgress = math.Approach(flipProgress, 1, FrameTime() * 4)
|
||||
if flipProgress >= 0.5 then displayChar = realChar end
|
||||
if flipProgress >= 1 then flipState, flipProgress = 0, 0 end
|
||||
else
|
||||
if displayChar ~= realChar then flipState, flipProgress = 1, 0 end
|
||||
end
|
||||
end
|
||||
|
||||
btn.Paint = function(s, w, h)
|
||||
local scaleY = flipState == 1 and math.abs(math.cos(flipProgress * math.pi)) or 1
|
||||
local m = Matrix()
|
||||
m:Translate(Vector(w/2, h/2, 0)) m:Scale(Vector(1, scaleY, 1)) m:Translate(-Vector(w/2, h/2, 0))
|
||||
cam.PushModelMatrix(m)
|
||||
|
||||
RNDX().Liquid(0, 0, w, h)
|
||||
:Rad(w/2)
|
||||
:Tint(30, 30, 40)
|
||||
:TintStrength(0.6)
|
||||
:Saturation(1.06)
|
||||
:GlassBlur(0.1, 0)
|
||||
:EdgeSmooth(2)
|
||||
:Strength(0.019)
|
||||
:Speed(0.4)
|
||||
:Shimmer(25.7)
|
||||
:Grain(0.01)
|
||||
:Alpha(0.8)
|
||||
:Flags(RNDX.SHAPE_CIRCLE)
|
||||
:Draw()
|
||||
|
||||
draw.SimpleText(displayChar, "gSims.Manrope.32", w/2, h/2, COL.white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
if s:IsHovered() then RNDX().Circle(w/2, h/2, w):Outline(2):Color(255, 255, 255, 100):Draw() end
|
||||
cam.PopModelMatrix()
|
||||
end
|
||||
|
||||
btn.DoClick = function()
|
||||
if CSND.Switch then surface.PlaySound(CSND.Switch) end
|
||||
SendAct(ent, "slot" .. slotId, next_lab[ent.SLOTS[ent["GetSlot" .. slotId](ent)] or "A"])
|
||||
end
|
||||
end
|
||||
|
||||
local Frame = nil
|
||||
local function OpenPrinterMenu(ent)
|
||||
if IsValid(Frame) then Frame:Remove() end
|
||||
if CSND.OpenUI then surface.PlaySound(CSND.OpenUI) end
|
||||
local w, h = 420, 640
|
||||
local startTime = SysTime()
|
||||
|
||||
Frame = vgui.Create("DFrame")
|
||||
Frame:SetSize(w, h)
|
||||
Frame:Center()
|
||||
Frame:MakePopup()
|
||||
Frame:SetTitle("")
|
||||
Frame:ShowCloseButton(false)
|
||||
|
||||
Frame.Paint = function(s, sw, sh)
|
||||
RNDX.EnsureFB()
|
||||
local anim = math.ease.OutBack(math.Clamp((SysTime() - startTime) / 0.3, 0, 1))
|
||||
local m = Matrix()
|
||||
m:Translate(Vector(sw/2, sh/2)) m:Scale(Vector(anim, anim, 1)) m:Translate(-Vector(sw/2, sh/2))
|
||||
s:SetAlpha(255 * math.min(1, anim * 2))
|
||||
|
||||
cam.PushModelMatrix(m)
|
||||
RNDX().Rect(0, 0, sw, sh):Rad(32):Color(COL.dark_bg):Flags(RNDX.SHAPE_IOS):Draw()
|
||||
|
||||
RNDX().Liquid(0, 0, sw, sh)
|
||||
:Rad(32):Color(255, 255, 255, 255)
|
||||
:Tint(20, 20, 30):TintStrength(0.6)
|
||||
:Saturation(1.06):GlassBlur(0.1, 0)
|
||||
:EdgeSmooth(2):Strength(0.019):Speed(0.4)
|
||||
:Shimmer(25.7):Grain(0.01):Alpha(0.8)
|
||||
:Shadow(40, 56):Flags(RNDX.SHAPE_IOS):Draw()
|
||||
|
||||
draw.NoTexture()
|
||||
DrawGrid(0, 0, sw, 80, 20, 5 * anim)
|
||||
draw.SimpleText("Принтер", "gSims.Manrope.Bold", 32, 28, COL.white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
|
||||
draw.SimpleText("Панель управления", "gSims.Manrope.16", 32, 50, COL.text_dim, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
|
||||
cam.PopModelMatrix()
|
||||
end
|
||||
|
||||
local btnClose = vgui.Create("DButton", Frame)
|
||||
btnClose:SetPos(w - 52, 28)
|
||||
btnClose:SetSize(24, 24)
|
||||
btnClose:SetText("")
|
||||
local closeHov = 0
|
||||
btnClose.Paint = function(s, bw, bh)
|
||||
closeHov = math.Approach(closeHov, s:IsHovered() and 1 or 0, FrameTime() * 10)
|
||||
draw.SimpleText("✕", "gSims.Manrope.20", bw/2, bh/2, Color(255, 255, 255, 150 + closeHov * 105), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
end
|
||||
btnClose.DoClick = function() if CSND.CloseUI then surface.PlaySound(CSND.CloseUI) end Frame:Remove() end
|
||||
RegisterAnim(btnClose, startTime, 0.2)
|
||||
|
||||
local btnProt = vgui.Create("DButton", Frame)
|
||||
btnProt:SetPos(w - 140, 30)
|
||||
btnProt:SetSize(80, 24)
|
||||
btnProt:SetText("")
|
||||
local protHov = 0
|
||||
btnProt.Paint = function(s, bw, bh)
|
||||
protHov = math.Approach(protHov, s:IsHovered() and 1 or 0, FrameTime() * 10)
|
||||
local isProt = ent:GetIsProtected()
|
||||
local col = isProt and COL.mint or COL.text_dim
|
||||
RNDX().Rect(0, 0, bw, bh):Rad(8):Color(col.r, col.g, col.b, 20 + protHov * 10):Draw()
|
||||
RNDX().Rect(0, 0, bw, bh):Rad(8):Outline(1):Color(col.r, col.g, col.b, 100):Draw()
|
||||
draw.SimpleText(isProt and "ЗАКРЫТО" or "ОТКРЫТО", "gSims.Manrope.12", bw/2, bh/2, col, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
end
|
||||
btnProt.DoClick = function() SendAct(ent, "protect") end
|
||||
RegisterAnim(btnProt, startTime, 0.2)
|
||||
|
||||
local InfoPanel = vgui.Create("DPanel", Frame)
|
||||
InfoPanel:SetPos(30, 90)
|
||||
InfoPanel:SetSize(w - 60, 160)
|
||||
InfoPanel.Paint = function(s, sw, sh)
|
||||
RNDX().Liquid(0, 0, sw, sh)
|
||||
:Rad(32)
|
||||
:Tint(200, 220, 255)
|
||||
:TintStrength(0.6)
|
||||
:Saturation(1.06)
|
||||
:GlassBlur(0.1, 0)
|
||||
:EdgeSmooth(2)
|
||||
:Strength(0.019)
|
||||
:Speed(0.4)
|
||||
:Shimmer(25.7)
|
||||
:Grain(0.01)
|
||||
:Alpha(0.8)
|
||||
:Flags(RNDX.SHAPE_IOS):Draw()
|
||||
|
||||
local temp, money, integ = ent:GetTemperature(), ent:GetMoney(), ent:GetIntegrity()
|
||||
local hpPct = math.Clamp(integ / ent.CFG.integrity, 0, 1)
|
||||
|
||||
draw.SimpleText("ТЕМП", "gSims.Manrope.12", 25, 24, COL.text_dim, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
|
||||
draw.SimpleText(temp .. "°C", "gSims.Manrope.32", 25, 42, temp > 80 and COL.red or COL.white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
|
||||
draw.SimpleText("БАЛАНС", "gSims.Manrope.12", sw/2, 24, COL.text_dim, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
|
||||
draw.SimpleText("$" .. string.Comma(money), "gSims.Manrope.48", sw/2, 34, COL.green, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
|
||||
draw.SimpleText("ЦЕЛОСТНОСТЬ", "gSims.Manrope.12", sw - 25, 24, COL.text_dim, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP)
|
||||
draw.SimpleText(math.ceil(hpPct * 100) .. "%", "gSims.Manrope.32", sw - 25, 42, COL.white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP)
|
||||
|
||||
local barW, barH, barY = 260, 10, 110
|
||||
local barX = (sw - barW) / 2
|
||||
local segs, gap = 20, 4
|
||||
local segW = (barW - (gap * (segs - 1))) / segs
|
||||
for i = 1, segs do
|
||||
local bx = barX + (i-1) * (segW + gap)
|
||||
draw.RoundedBox(2, bx, barY, segW, barH, Color(255, 255, 255, 10))
|
||||
if i <= math.floor(segs * hpPct) then draw.RoundedBox(2, bx, barY, segW, barH, COL.mint) end
|
||||
end
|
||||
if ent:GetMutatorID() > 0 then draw.SimpleText("МУТАТОР АКТИВЕН", "gSims.Manrope.12", sw/2, barY + 16, COL.purple, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP) end
|
||||
end
|
||||
RegisterAnim(InfoPanel, startTime, 0.25)
|
||||
|
||||
local barY, barW = 265, (w - 70) / 2
|
||||
local b1 = CreateBar(Frame, 30, barY, barW, 26, "ЗАГРЯЗНЕНИЕ", COL.orange, function() return ent:GetPollution() end, ent, "hold_pol")
|
||||
local b2 = CreateBar(Frame, 30 + barW + 10, barY, barW, 26, "ЭНЕРГИЯ", COL.green, function() return ent:GetPowerRes() end, ent, "hold_pow")
|
||||
RegisterAnim(b1, startTime, 0.3) RegisterAnim(b2, startTime, 0.3)
|
||||
|
||||
local upgY, upgW = 305, (w - 80) / 3
|
||||
local function CreateMiniUpgrade(x, lbl, type, act)
|
||||
local uBtn = vgui.Create("DButton", Frame)
|
||||
uBtn:SetPos(x, upgY) uBtn:SetSize(upgW, 35) uBtn:SetText("")
|
||||
local hov = 0
|
||||
uBtn.Paint = function(s, bw, bh)
|
||||
hov = math.Approach(hov, s:IsHovered() and 1 or 0, FrameTime() * 10)
|
||||
local lvl = ent["Get" .. (type == "eff" and "Eff" or (type == "cool" and "Cool" or "Luck")) .. "Level"](ent)
|
||||
|
||||
RNDX().Liquid(0, 0, bw, bh):Rad(8)
|
||||
:Tint(30, 30, 40)
|
||||
:TintStrength(0.6)
|
||||
:Saturation(1.06)
|
||||
:GlassBlur(0.1, 0)
|
||||
:EdgeSmooth(2)
|
||||
:Strength(0.019)
|
||||
:Speed(0.4)
|
||||
:Shimmer(25.7)
|
||||
:Grain(0.01)
|
||||
:Alpha(0.8)
|
||||
:Flags(RNDX.SHAPE_IOS):Draw()
|
||||
|
||||
RNDX().Rect(0, 0, bw, bh):Rad(8):Outline(1):Color(255, 255, 255, 30 + hov * 30):Flags(RNDX.SHAPE_IOS):Draw()
|
||||
local cost = ent:GetUpgradeCost(type, lvl)
|
||||
if hov > 0.5 and cost > 0 then draw.SimpleText("$" .. cost, "gSims.Manrope.Bold", bw/2, bh/2, COL.green, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
else draw.SimpleText(cost == 0 and "МАКС" or (lbl .. " " .. lvl), "gSims.Manrope.12", bw/2, bh/2, COL.white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) end
|
||||
end
|
||||
uBtn.DoClick = function() SendAct(ent, act) end
|
||||
RegisterAnim(uBtn, startTime, 0.35)
|
||||
end
|
||||
CreateMiniUpgrade(30, "ЭФФ.", "eff", "upgrade_eff")
|
||||
CreateMiniUpgrade(30 + upgW + 10, "ОХЛ.", "cool", "upgrade_cool")
|
||||
CreateMiniUpgrade(30 + (upgW + 10) * 2, "АЛГ.", "luck", "upgrade_luck")
|
||||
|
||||
local ySlot, slotSize, gap = 350, 64, 20
|
||||
local startX = (w - (slotSize * 3 + gap * 2)) / 2
|
||||
CreateSlotButton(Frame, ent, 1, startX, ySlot, slotSize)
|
||||
CreateSlotButton(Frame, ent, 2, startX + slotSize + gap, ySlot, slotSize)
|
||||
CreateSlotButton(Frame, ent, 3, startX + (slotSize + gap) * 2, ySlot, slotSize)
|
||||
for _, child in ipairs(Frame:GetChildren()) do if child:GetY() == ySlot then RegisterAnim(child, startTime, 0.4) end end
|
||||
|
||||
local btnApply = CreateGlassButton(Frame, 30, 430, w - 60, 45, "", "gSims.Manrope.18", COL.accent,
|
||||
function() SendAct(ent, "mods_apply") end,
|
||||
function(s, bw, bh, hov)
|
||||
local price = ent:GetApplyCost(ent:SortKey(ent.SLOTS[ent:GetSlot1()], ent.SLOTS[ent:GetSlot2()], ent.SLOTS[ent:GetSlot3()]))
|
||||
draw.SimpleText("Применить", "gSims.Manrope.18", bw / 2, bh / 2, Color(255, 255, 255, 255 * (1 - hov)), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
draw.SimpleText("Цена: $" .. price, "gSims.Manrope.Bold", bw / 2, bh / 2, Color(255, 255, 255, 255 * hov), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
end)
|
||||
RegisterAnim(btnApply, startTime, 0.45)
|
||||
|
||||
local gridY, btnW = 490, (w - 70) / 2
|
||||
local predPower = ent:GetPowered()
|
||||
local btnPower = CreateGlassButton(Frame, 30, gridY, btnW, 60,
|
||||
function() return predPower and "СТОП" or "ПУСК" end, "gSims.Manrope.Bold",
|
||||
function() return predPower and COL.red or COL.green end,
|
||||
function() if CSND.Click then surface.PlaySound(CSND.Click) end predPower = not predPower SendAct(ent, "toggle") end
|
||||
)
|
||||
btnPower.Think = function(s) if ent:GetPowered() ~= predPower then predPower = ent:GetPowered() end end
|
||||
RegisterAnim(btnPower, startTime, 0.5)
|
||||
|
||||
local btnVent = CreateGlassButton(Frame, 30 + btnW + 10, gridY, btnW, 60,
|
||||
function() return not ent:GetPowered() and "НЕТ ПИТ." or "ВЕНТ." end, "gSims.Manrope.Bold",
|
||||
function() return ent:GetPowered() and COL.white or COL.text_dim end,
|
||||
function() if ent:GetPowered() then if CSND.Click then surface.PlaySound(CSND.Click) end SendAct(ent, "vent") end end
|
||||
)
|
||||
RegisterAnim(btnVent, startTime, 0.5)
|
||||
|
||||
local btnCollect = CreateGlassButton(Frame, 30, gridY + 70, w - 60, 60, "СНЯТЬ", "gSims.Manrope.Bold", COL.green, function()
|
||||
if ent:GetMoney() > 0 and CSND.Cash then surface.PlaySound(CSND.Cash) end SendAct(ent, "collect")
|
||||
end)
|
||||
RegisterAnim(btnCollect, startTime, 0.55)
|
||||
end
|
||||
|
||||
net.Receive("gsims_printer_open", function()
|
||||
local ent = net.ReadEntity()
|
||||
if IsValid(ent) then OpenPrinterMenu(ent) end
|
||||
end)
|
||||
|
||||
net.Receive("gsims_printer_combo_fx", function()
|
||||
local key = net.ReadString()
|
||||
local ent = LocalPlayer():GetEyeTrace().Entity
|
||||
if IsValid(ent) then ent._comboKey = key ent._comboTime = CurTime() SpawnParticles(ent:GetPos() + Vector(0,0,10), 2) end
|
||||
|
||||
local rec = (IsValid(ent) and ent.GetRecipeByKey) and ent:GetRecipeByKey(key) or nil
|
||||
if not rec then return end
|
||||
|
||||
local stats = {}
|
||||
if rec.payout_add then table.insert(stats, string.format("ДОХОД: %s$", rec.payout_add > 0 and "+"..rec.payout_add or rec.payout_add)) end
|
||||
if rec.payout_mul then table.insert(stats, string.format("ДОХОД: %d%%", math.Round(rec.payout_mul * 100))) end
|
||||
if rec.heat_add then table.insert(stats, string.format("НАГРЕВ: %s/s", rec.heat_add > 0 and "+"..rec.heat_add or rec.heat_add)) end
|
||||
if rec.vent_bonus then table.insert(stats, string.format("ОХЛАЖДЕНИЕ: +%d", rec.vent_bonus)) end
|
||||
if rec.mute then table.insert(stats, "СТАТУС: ТИХИЙ") end
|
||||
if rec.collect_mul then table.insert(stats, string.format("ЩИТ: +%d%%", (rec.collect_mul - 1) * 100)) end
|
||||
if rec.passive_cool_add then table.insert(stats, string.format("ПАСС. ОХЛ: +%d", rec.passive_cool_add)) end
|
||||
if rec.fire_at_bonus then table.insert(stats, string.format("МАКС ТЕМП: +%d", rec.fire_at_bonus)) end
|
||||
|
||||
local pnl = vgui.Create("DPanel")
|
||||
pnl:SetSize(ScrW(), ScrH()) pnl:MakePopup() pnl:SetMouseInputEnabled(true)
|
||||
pnl.OnMousePressed = function(s) s:Remove() end
|
||||
local start = CurTime()
|
||||
pnl.Paint = function(s, w, h)
|
||||
local delta = CurTime() - start
|
||||
if delta > 4.0 then s:Remove() return end
|
||||
local alpha = delta < 0.5 and (delta/0.5)*255 or (delta > 3.5 and ((4.0-delta)/0.5)*255 or 255)
|
||||
RNDX.DrawBlur(0, 0, w, h, RNDX.BLUR, 0, 0, 0, 0, 5)
|
||||
surface.SetDrawColor(0, 0, 0, math.min(252, alpha)) surface.DrawRect(0, 0, w, h)
|
||||
|
||||
local textStr = utf8.sub(rec.name or "UNKNOWN", 1, math.min(utf8.len(rec.name or "UNKNOWN"), math.floor(delta * 20)))
|
||||
draw.SimpleText("РЕКОНФИГУРАЦИЯ СИСТЕМЫ", "gSims.Manrope.16", w/2, h/2 - 60, Color(100, 200, 255, alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
draw.SimpleText(textStr, "gSims.Manrope.48", w/2, h/2, Color(255, 255, 255, alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
|
||||
if delta > 0.5 then
|
||||
local statY = h/2 + 50
|
||||
for i, line in ipairs(stats) do
|
||||
if (delta - 0.5) > ((i - 1) * 0.2) then
|
||||
draw.SimpleText("> " .. line, "gSims.Manrope.24", w/2, statY, Color(200, 255, 200, alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
|
||||
statY = statY + 30
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
net.Receive("gsims_printer_fx_money", function()
|
||||
local ent = net.ReadEntity()
|
||||
if IsValid(ent) then SpawnParticles(ent:GetPos() + Vector(0,0,10), 1) end
|
||||
end)
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.WorkSound then self.WorkSound:Stop() self.WorkSound = nil end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if not self.WorkSound and CSND.Work then self.WorkSound = CreateSound(self, CSND.Work) end
|
||||
if not self.WorkSound then return end
|
||||
local ct = CurTime()
|
||||
if self:GetPowered() then
|
||||
if not self._sndNextLoop or ct >= self._sndNextLoop then
|
||||
self.WorkSound:Stop() self.WorkSound:Play() self.WorkSound:ChangeVolume(0, 0)
|
||||
self._sndNextLoop = ct + 16
|
||||
end
|
||||
local vol = 0.6 - (self:GetEffLevel() * 0.08) - (self:GetCoolLevel() * 0.04)
|
||||
self.WorkSound:ChangeVolume(math.Clamp(vol, 0.1, 1.0), 0.5)
|
||||
self.WorkSound:ChangePitch(100, 0)
|
||||
else
|
||||
if self._sndNextLoop then self.WorkSound:FadeOut(1.0) self._sndNextLoop = nil end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
RNDX.EnsureFB()
|
||||
self:DrawModel()
|
||||
local pos = self:GetPos()
|
||||
if pos:DistToSqr(LocalPlayer():GetPos()) > 600 * 600 then return end
|
||||
local offset = self:GetForward() * -6 + self:GetUp() * 3.1
|
||||
local rot = self:GetAngles()
|
||||
rot:RotateAroundAxis(rot:Up(), 90)
|
||||
|
||||
self._lerpMoney = Lerp(FrameTime() * 5, self._lerpMoney or 0, self:GetMoney())
|
||||
self._lerpTemp = Lerp(FrameTime() * 3, self._lerpTemp or 20, self:GetTemperature())
|
||||
|
||||
local tr = LocalPlayer():GetEyeTrace()
|
||||
self._hoverAlpha = math.Approach(self._hoverAlpha or 0, tr.Entity == self and 1 or 0, FrameTime() * 6)
|
||||
|
||||
cam.Start3D2D(pos + offset, rot, 0.05)
|
||||
local w, h = 380, 220
|
||||
local x, y = -w/2, 0
|
||||
|
||||
render.SetStencilEnable(true)
|
||||
render.SetStencilWriteMask(0xFF) render.SetStencilTestMask(0xFF)
|
||||
render.SetStencilReferenceValue(1) render.SetStencilCompareFunction(STENCIL_ALWAYS)
|
||||
render.SetStencilPassOperation(STENCIL_REPLACE) render.SetStencilFailOperation(STENCIL_KEEP) render.SetStencilZFailOperation(STENCIL_KEEP)
|
||||
RNDX().Rect(x, y, w, h):Rad(16):Draw()
|
||||
|
||||
render.SetStencilCompareFunction(STENCIL_EQUAL) render.SetStencilPassOperation(STENCIL_KEEP)
|
||||
surface.SetDrawColor(COL.dark_bg) surface.DrawRect(x, y, w, h)
|
||||
draw.NoTexture() DrawGrid(x, y, w, h, 20, 5)
|
||||
surface.SetMaterial(MAT_GRAD) surface.SetDrawColor(COL.glass_top) surface.DrawTexturedRect(x, y, w, h/2)
|
||||
|
||||
local shimmerPos = (CurTime() * 0.5) % 2.0
|
||||
if shimmerPos < 1.3 then
|
||||
surface.SetMaterial(MAT_GRAD) surface.SetDrawColor(255, 255, 255, 10)
|
||||
surface.DrawTexturedRectRotated(x + (w * shimmerPos) - 100, y + h/2, 100, h * 1.5, -20)
|
||||
end
|
||||
render.SetStencilEnable(false)
|
||||
|
||||
RNDX().Liquid(x, y, w, h):Rad(16):Tint(COL.accent.r, COL.accent.g, COL.accent.b):TintStrength(0.02):Alpha(0.1):Draw()
|
||||
local outlineCol = Color(Lerp(self._hoverAlpha, COL.accent.r, COL.green.r), Lerp(self._hoverAlpha, COL.accent.g, COL.green.g), Lerp(self._hoverAlpha, COL.accent.b, COL.green.b), 50 + self._hoverAlpha * 150)
|
||||
RNDX().Rect(x, y, w, h):Rad(16):Outline(2 + self._hoverAlpha * 2):Color(outlineCol):Draw()
|
||||
|
||||
draw.SimpleText("Ликвид-принтер", "gSims.Manrope.24", 0, y + 20, COL.text_dim, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
|
||||
|
||||
if self._comboKey then
|
||||
local anim = math.ease.OutBack(math.Clamp((CurTime() - (self._comboTime or CurTime())) / 0.5, 0, 1))
|
||||
if anim > 0 then
|
||||
local circleSize, gap = 42 * anim, 12
|
||||
local startX = -((circleSize * 3) + (gap * 2)) / 2 + circleSize / 2
|
||||
local circleY = y + 70
|
||||
for i = 1, 3 do
|
||||
local char = self._comboKey:sub(i, i) or "?"
|
||||
local cx = startX + (i-1) * (circleSize + gap)
|
||||
RNDX().Liquid(cx - circleSize/2, circleY - circleSize/2, circleSize, circleSize):Rad(circleSize/2):Tint(255, 255, 255):TintStrength(0.1):GlassBlur(0.1, 1.5):Alpha(0.9):Flags(RNDX.SHAPE_CIRCLE):Draw()
|
||||
draw.SimpleText(char, "gSims.Manrope.24", cx, circleY, Color(255, 255, 255, 255 * anim), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
draw.SimpleText("$" .. string.Comma(math.floor(self._lerpMoney)), "gSims.Manrope.Display", 0, y + 130, COL.green, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
local tempPct = math.Clamp((self._lerpTemp - 20) / 100, 0, 1)
|
||||
draw.SimpleText(math.floor(self._lerpTemp) .. "°C", "gSims.Manrope.32", 0, y + h - 45, Color(255, 255 * (1 - tempPct), 255 * (1 - tempPct)), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
cam.End3D2D()
|
||||
end
|
||||
457
addons/nyxteam_printer/lua/entities/nyxteam_printer/init.lua
Normal file
457
addons/nyxteam_printer/lua/entities/nyxteam_printer/init.lua
Normal file
@@ -0,0 +1,457 @@
|
||||
--[[
|
||||
|
||||
_ ___ ____ __ _______ ______ __ __
|
||||
| \ | \ \ / /\ \ / / |__ __| ____| /\ | \/ |
|
||||
| \| |\ \_/ / \ V / | | | |__ / \ | \ / |
|
||||
| . ` | \ / > < | | | __| / /\ \ | |\/| |
|
||||
| |\ | | | / . \ | | | |____ / ____ \| | | |
|
||||
|_| \_| |_| /_/ \_\ |_| |______/_/ \_\_| |_|
|
||||
|
||||
JOIN DISCORD: https://discord.gg/rUEEz4mfXw
|
||||
BY NYX TEAM (MaryBlackfild lead)
|
||||
Copyrighted Nyx Team + YouGame.biz
|
||||
|
||||
--]]
|
||||
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
include("shared.lua")
|
||||
|
||||
util.AddNetworkString("gsims_printer_open")
|
||||
util.AddNetworkString("gsims_printer_action")
|
||||
util.AddNetworkString("gsims_printer_combo_fx")
|
||||
util.AddNetworkString("gsims_printer_fx_money")
|
||||
|
||||
local MODEL = "models/props_lab/reciever01a.mdl"
|
||||
|
||||
local function isDarkRP()
|
||||
return DarkRP and isfunction(DarkRP.notify)
|
||||
end
|
||||
|
||||
local function clamp(n, a, b)
|
||||
if n < a then return a end
|
||||
if n > b then return b end
|
||||
return n
|
||||
end
|
||||
|
||||
local function inRange(ent, ply)
|
||||
return IsValid(ent) and IsValid(ply) and ent:GetPos():DistToSqr(ply:GetPos()) <= 200 * 200
|
||||
end
|
||||
|
||||
local function canAfford(ply, amt)
|
||||
if not DarkRP or not ply.canAfford then return true end
|
||||
return ply:canAfford(amt)
|
||||
end
|
||||
|
||||
local function takeMoney(ply, amt)
|
||||
if not DarkRP or not ply.addMoney then return true end
|
||||
ply:addMoney(-amt)
|
||||
return true
|
||||
end
|
||||
|
||||
local function giveMoney(ply, amt)
|
||||
if amt <= 0 then return end
|
||||
if DarkRP and ply.addMoney then ply:addMoney(amt) end
|
||||
end
|
||||
|
||||
local function notify(ply, msg, typ)
|
||||
if isDarkRP() then DarkRP.notify(ply, typ or 0, 4, msg) end
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel(MODEL)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if IsValid(phys) then phys:Wake() end
|
||||
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:SetTemperature(20)
|
||||
self:SetMoney(0)
|
||||
self:SetPowered(false)
|
||||
self:SetIntegrity(self.CFG.integrity)
|
||||
self:SetOnFireState(false)
|
||||
self:SetPollution(70)
|
||||
self:SetPowerRes(70)
|
||||
self:SetEffLevel(0)
|
||||
self:SetCoolLevel(0)
|
||||
self:SetLuckLevel(0)
|
||||
self:SetSlot1(0)
|
||||
self:SetSlot2(0)
|
||||
self:SetSlot3(0)
|
||||
|
||||
if self.SND.Vent then self._ventLoop = CreateSound(self, self.SND.Vent) end
|
||||
if self.SND.Alarm then self._alarm = CreateSound(self, self.SND.Alarm) end
|
||||
|
||||
local ct = CurTime()
|
||||
self._nextThink = ct
|
||||
self._nextHeat = ct + 2
|
||||
self._nextPayout = ct + 5
|
||||
self._barTime = ct
|
||||
self._modBuff = {}
|
||||
self._ventState = 0
|
||||
self._holdPol = {}
|
||||
self._holdPow = {}
|
||||
self.Exploding = false
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self._ventLoop then self._ventLoop:Stop() end
|
||||
if self._alarm then self._alarm:Stop() end
|
||||
end
|
||||
|
||||
local function withBuff(x, add)
|
||||
if not add then return x end
|
||||
return x + add
|
||||
end
|
||||
|
||||
function ENT:GetPayoutPerTick()
|
||||
local base = self.CFG.payout + self:GetEffLevel() * 2
|
||||
base = withBuff(base, self._modBuff.payout_add)
|
||||
local mul = self._modBuff.payout_mul or 1
|
||||
local polF = math.Clamp(self:GetPollution() / 100, 0, 1)
|
||||
return math.max(0, math.floor(base * mul * (0.5 + polF * 0.7)))
|
||||
end
|
||||
|
||||
function ENT:GetHeatGainNow()
|
||||
return withBuff(self.CFG.heat_gain, self._modBuff.heat_add)
|
||||
end
|
||||
|
||||
function ENT:GetPassiveCoolNow()
|
||||
return withBuff(self.CFG.cool_rate + (self:GetCoolLevel() * 0.6), self._modBuff.passive_cool_add)
|
||||
end
|
||||
|
||||
function ENT:GetFireAtNow()
|
||||
return self.CFG.fire_temp + (self._modBuff.fire_at_bonus or 0)
|
||||
end
|
||||
|
||||
local function effectiveInterval(ent)
|
||||
local powF = math.Clamp(ent:GetPowerRes() / 100, 0, 1)
|
||||
return ent.CFG.interval * (1 + (1 - powF) * 1.0)
|
||||
end
|
||||
|
||||
function ENT:TogglePower(on)
|
||||
if on == nil then on = not self:GetPowered() end
|
||||
self:SetPowered(on)
|
||||
if self.SND.Click then sound.Play(self.SND.Click, self:GetPos(), 65, 100, 0.6) end
|
||||
|
||||
if on then
|
||||
local ct = CurTime()
|
||||
self._nextHeat = ct + 2
|
||||
self._nextPayout = ct + effectiveInterval(self)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:CreditAndClear(ply)
|
||||
local amt = self:GetMoney()
|
||||
if amt <= 0 then return end
|
||||
|
||||
amt = math.floor(amt * (self._modBuff.collect_mul or 1))
|
||||
local mID = self:GetMutatorID()
|
||||
local mCharges = self:GetMutatorCharges()
|
||||
|
||||
if mID > 0 and mCharges > 0 then
|
||||
local luckLvl = self:GetLuckLevel()
|
||||
local stats = self.LUCK[luckLvl] or {multiplier = 1.0, chance = 0}
|
||||
|
||||
if math.random(100) <= stats.chance then
|
||||
amt = math.floor(amt * stats.multiplier)
|
||||
if self.SND.MutatorGood then sound.Play(self.SND.MutatorGood, self:GetPos(), 65, 100, 1) end
|
||||
notify(ply, "МУТАТОР: УДАЧА! x" .. stats.multiplier, 0)
|
||||
else
|
||||
amt = math.floor(amt * 0.8)
|
||||
if self.SND.MutatorBad then sound.Play(self.SND.MutatorBad, self:GetPos(), 65, 100, 1) end
|
||||
notify(ply, "МУТАТОР: НЕУДАЧА (-20%)", 1)
|
||||
end
|
||||
|
||||
mCharges = mCharges - 1
|
||||
self:SetMutatorCharges(mCharges)
|
||||
if mCharges <= 0 then self:SetMutatorID(0) end
|
||||
end
|
||||
|
||||
self:SetMoney(0)
|
||||
if IsValid(ply) then
|
||||
giveMoney(ply, amt)
|
||||
notify(ply, "Получено $" .. amt, 0)
|
||||
net.Start("gsims_printer_fx_money")
|
||||
net.WriteEntity(self)
|
||||
net.SendPVS(self:GetPos())
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:VentTap(ply)
|
||||
if not self:GetPowered() then return end
|
||||
if self.SND.Click then sound.Play(self.SND.Click, self:GetPos(), 65, 100, 0.5) end
|
||||
|
||||
local now = CurTime()
|
||||
if self._ventState == 0 then
|
||||
self._ventState = 1
|
||||
self:SetVentState(1)
|
||||
self._ventEnd = now + 4.0
|
||||
self._ventInc = 6.0
|
||||
self._ventClicks = 0
|
||||
self:SetVentFlow(-math.ceil(self._ventInc))
|
||||
if self._ventLoop then self._ventLoop:Stop() self._ventLoop:PlayEx(0.6, 95) end
|
||||
elseif self._ventState == 1 then
|
||||
self._ventClicks = (self._ventClicks or 0) + 1
|
||||
self._ventInc = math.max(0.5, self._ventInc - 0.6)
|
||||
self:SetVentFlow(-math.ceil(self._ventInc))
|
||||
if self._ventLoop then self._ventLoop:ChangePitch(100 + math.min(self._ventClicks * 2, 20), 0.1) end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:StartFireSequence()
|
||||
if self:GetOnFireState() then return end
|
||||
self:SetOnFireState(true)
|
||||
if self.SND.Ignite then sound.Play(self.SND.Ignite, self:GetPos(), 70, 100, 0.6) end
|
||||
self:Ignite(8, 16)
|
||||
if self._alarm then self._alarm:PlayEx(0.4, 100) end
|
||||
timer.Simple(8, function() if IsValid(self) then self:MaybeExplode() end end)
|
||||
end
|
||||
|
||||
function ENT:MaybeExplode()
|
||||
if not IsValid(self) or self.Exploding then return end
|
||||
if self:GetTemperature() < self.CFG.explode_temp then
|
||||
if self._alarm then self._alarm:Stop() end
|
||||
self:SetOnFireState(false)
|
||||
self:Extinguish()
|
||||
return
|
||||
end
|
||||
self.Exploding = true
|
||||
local pos = self:GetPos()
|
||||
util.BlastDamage(self, self, pos, 160, 120)
|
||||
local ef = EffectData()
|
||||
ef:SetOrigin(pos)
|
||||
util.Effect("Explosion", ef, true, true)
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(dmg)
|
||||
self:SetIntegrity(clamp(self:GetIntegrity() - dmg:GetDamage(), 0, self.CFG.integrity))
|
||||
if self:GetIntegrity() <= 0 then self:MaybeExplode() end
|
||||
end
|
||||
|
||||
function ENT:ApplyActiveRecipeFromSlots(ply)
|
||||
local k = self:SortKey(self.SLOTS[self:GetSlot1()], self.SLOTS[self:GetSlot2()], self.SLOTS[self:GetSlot3()])
|
||||
local rec = self:GetRecipeByKey(k)
|
||||
|
||||
if not rec then
|
||||
self._modBuff = {}
|
||||
self:SetActiveRecipeId(0)
|
||||
notify(ply, "Неверная комбинация", 1)
|
||||
return
|
||||
end
|
||||
|
||||
local cost = self:GetApplyCost(k)
|
||||
if not canAfford(ply, cost) then
|
||||
notify(ply, "Нужно: $" .. cost, 1)
|
||||
return
|
||||
end
|
||||
takeMoney(ply, cost)
|
||||
|
||||
self._modBuff = rec
|
||||
self:SetActiveRecipeId(rec.id or 0)
|
||||
|
||||
if self:GetLuckLevel() > 0 and math.random(100) <= 30 then
|
||||
self:SetMutatorID(1)
|
||||
self:SetMutatorCharges(3)
|
||||
notify(ply, "МУТАТОР: УМНОЖЕНИЕ (3 заряда)", 0)
|
||||
end
|
||||
|
||||
notify(ply, "Установлено: " .. (rec.name or ""), 0)
|
||||
local mute = (self:GetEffLevel() > 1) or (rec.mute)
|
||||
if self.SND.Combo then sound.Play(self.SND.Combo, self:GetPos(), mute and 55 or 75, 100, mute and 1.0 or 1.6) end
|
||||
if IsValid(ply) then
|
||||
net.Start("gsims_printer_combo_fx")
|
||||
net.WriteString(k)
|
||||
net.Send(ply)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:CheckOwner(ply)
|
||||
local owner = self:CPPIGetOwner() or self.dt.owning_ent
|
||||
if not IsValid(owner) then return true end
|
||||
return ply == owner
|
||||
end
|
||||
|
||||
function ENT:Use(ply)
|
||||
if not IsValid(ply) or not ply:IsPlayer() then return end
|
||||
if self:GetIsProtected() and not self:CheckOwner(ply) then
|
||||
if self.SND.Lock then sound.Play(self.SND.Lock, self:GetPos(), 60, 100, 1) end
|
||||
notify(ply, "Доступ запрещен (Защита)", 1)
|
||||
return
|
||||
end
|
||||
net.Start("gsims_printer_open")
|
||||
net.WriteEntity(self)
|
||||
net.Send(ply)
|
||||
end
|
||||
|
||||
local function activeHolders(map, ent, timeout)
|
||||
local now = CurTime()
|
||||
local n = 0
|
||||
for ply, t in pairs(map) do
|
||||
if not IsValid(ply) or not inRange(ent, ply) or (now - t) > timeout then map[ply] = nil else n = n + 1 end
|
||||
end
|
||||
return n
|
||||
end
|
||||
|
||||
function ENT:BarsThink(dt)
|
||||
local pol, pow = self:GetPollution(), self:GetPowerRes()
|
||||
local polD, powD = 0.0, 0.0
|
||||
|
||||
if self:GetPowered() then
|
||||
polD = -self.CFG.pol_work_decay * dt
|
||||
powD = -self.CFG.pow_work_decay * dt
|
||||
if activeHolders(self._holdPol, self, self.CFG.hold_timeout) > 0 then polD = polD + self.CFG.pol_hold_gain * dt end
|
||||
if activeHolders(self._holdPow, self, self.CFG.hold_timeout) > 0 then powD = powD + self.CFG.pow_hold_gain * dt end
|
||||
else
|
||||
polD = self.CFG.pol_rest_gain * dt
|
||||
powD = self.CFG.pow_rest_gain * dt
|
||||
end
|
||||
|
||||
self._polAcc = (self._polAcc or 0) + polD
|
||||
self._powAcc = (self._powAcc or 0) + powD
|
||||
|
||||
local aPol, aPow = math.floor(self._polAcc), math.floor(self._powAcc)
|
||||
if aPol ~= 0 then pol = clamp(pol + aPol, 0, 100) self._polAcc = self._polAcc - aPol end
|
||||
if aPow ~= 0 then pow = clamp(pow + aPow, 0, 100) self._powAcc = self._powAcc - aPow end
|
||||
|
||||
self:SetPollution(pol)
|
||||
self:SetPowerRes(pow)
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
local ct = CurTime()
|
||||
if ct < self._nextThink then return end
|
||||
local dt = ct - (self._barTime or ct)
|
||||
self._barTime = ct
|
||||
self._nextThink = ct + 0.1
|
||||
|
||||
self:BarsThink(dt)
|
||||
local powered = self:GetPowered()
|
||||
|
||||
if powered then
|
||||
while ct >= self._nextHeat do
|
||||
self:SetTemperature(clamp(self:GetTemperature() + math.floor(self:GetHeatGainNow()), 0, 120))
|
||||
self._nextHeat = self._nextHeat + 2
|
||||
end
|
||||
while ct >= self._nextPayout do
|
||||
self:SetMoney(self:GetMoney() + self:GetPayoutPerTick())
|
||||
if not self._modBuff.mute and self.SND.Btn then sound.Play(self.SND.Btn, self:GetPos(), 55, 120, 0.2) end
|
||||
self._nextPayout = self._nextPayout + effectiveInterval(self)
|
||||
end
|
||||
else
|
||||
local t = self:GetTemperature()
|
||||
if t > 20 then
|
||||
local cr = self:GetPassiveCoolNow()
|
||||
self._coolAcc = (self._coolAcc or 0) + (cr * dt)
|
||||
if self._coolAcc >= 1 then
|
||||
local d = math.floor(self._coolAcc)
|
||||
self:SetTemperature(math.max(20, t - d))
|
||||
self._coolAcc = self._coolAcc - d
|
||||
end
|
||||
else
|
||||
self._coolAcc = 0
|
||||
end
|
||||
end
|
||||
|
||||
if self._ventState > 0 then
|
||||
if not powered then
|
||||
self._ventState = 0
|
||||
self:SetVentState(0)
|
||||
self:SetVentFlow(0)
|
||||
if self._ventLoop then self._ventLoop:Stop() end
|
||||
else
|
||||
if self._ventState == 1 then
|
||||
self:SetVentState(1)
|
||||
self:SetTemperature(clamp(self:GetTemperature() + math.ceil(self._ventInc * 0.1), 0, 120))
|
||||
self:SetVentFlow(-math.ceil(self._ventInc))
|
||||
if ct >= self._ventEnd then
|
||||
self._ventState = 2
|
||||
self:SetVentState(2)
|
||||
self._ventTempStart = self:GetTemperature()
|
||||
self._ventCoolT0 = ct
|
||||
self._ventCoolT1 = ct + 3.0
|
||||
end
|
||||
elseif self._ventState == 2 then
|
||||
self:SetVentState(2)
|
||||
local k = math.Clamp((ct - self._ventCoolT0) / math.max(0.01, (self._ventCoolT1 - self._ventCoolT0)), 0, 1)
|
||||
local diff = math.max(0, self:GetTemperature() - math.max(20, math.floor(Lerp(k, self._ventTempStart, 20))))
|
||||
if diff > 0 then self:SetTemperature(self:GetTemperature() - diff) end
|
||||
self:SetVentFlow(math.ceil(diff))
|
||||
if k >= 1 then
|
||||
self:SetTemperature(20)
|
||||
self._ventState = 0
|
||||
self:SetVentState(0)
|
||||
self:SetVentFlow(0)
|
||||
if self._ventLoop then self._ventLoop:FadeOut(1.0) end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif self:GetVentFlow() ~= 0 then
|
||||
self:SetVentFlow(0)
|
||||
end
|
||||
|
||||
if self:GetTemperature() >= self:GetFireAtNow() then self:StartFireSequence() end
|
||||
self:NextThink(ct + 0.1)
|
||||
return true
|
||||
end
|
||||
|
||||
net.Receive("gsims_printer_action", function(_, ply)
|
||||
local ent = net.ReadEntity()
|
||||
local act = net.ReadString()
|
||||
local arg = net.ReadString() or ""
|
||||
|
||||
if not IsValid(ent) or not IsValid(ply) or not inRange(ent, ply) or not ent.GetPayoutPerTick then return end
|
||||
|
||||
if act == "toggle" then
|
||||
ent:TogglePower()
|
||||
elseif act == "vent" then
|
||||
ent:VentTap(ply)
|
||||
elseif act == "collect" then
|
||||
if ent:GetIsProtected() and not ent:CheckOwner(ply) then
|
||||
if ent.SND.Lock then sound.Play(ent.SND.Lock, ent:GetPos(), 60, 100, 1) end
|
||||
notify(ply, "Деньги защищены", 1)
|
||||
return
|
||||
end
|
||||
ent:CreditAndClear(ply)
|
||||
elseif act == "protect" then
|
||||
if not ent:CheckOwner(ply) then notify(ply, "Нет владельца", 1) return end
|
||||
if not ent:GetIsProtected() then
|
||||
local cost = ent.CFG.prot_cost
|
||||
if not canAfford(ply, cost) then notify(ply, "Нужно $" .. cost, 1) return end
|
||||
takeMoney(ply, cost)
|
||||
ent:SetIsProtected(true)
|
||||
notify(ply, "Защита активна", 0)
|
||||
if ent.SND.Upg then sound.Play(ent.SND.Upg, ent:GetPos(), 65, 100, 0.5) end
|
||||
else
|
||||
ent:SetIsProtected(false)
|
||||
notify(ply, "Защита отключена", 2)
|
||||
if ent.SND.Switch then sound.Play(ent.SND.Switch, ent:GetPos(), 65, 100, 0.5) end
|
||||
end
|
||||
elseif act == "upgrade_eff" or act == "upgrade_cool" or act == "upgrade_luck" then
|
||||
local typ = act:sub(9)
|
||||
local getter, setter = "Get" .. (typ == "eff" and "Eff" or (typ == "cool" and "Cool" or "Luck")) .. "Level", "Set" .. (typ == "eff" and "Eff" or (typ == "cool" and "Cool" or "Luck")) .. "Level"
|
||||
local lvl = ent[getter](ent)
|
||||
local cost = ent:GetUpgradeCost(typ, lvl)
|
||||
if cost == 0 then notify(ply, "Максимальный", 1) return end
|
||||
if not canAfford(ply, cost) then notify(ply, "Нужно $" .. cost, 1) return end
|
||||
takeMoney(ply, cost)
|
||||
ent[setter](ent, lvl + 1)
|
||||
if ent.SND.Upg then sound.Play(ent.SND.Upg, ent:GetPos(), 65, 100, 0.5) end
|
||||
notify(ply, "Улучшено", 0)
|
||||
elseif act:sub(1,4) == "slot" then
|
||||
local id = tonumber(act:sub(5,5))
|
||||
local val = ent.L2I[arg] or 0
|
||||
if id == 1 then ent:SetSlot1(val) elseif id == 2 then ent:SetSlot2(val) else ent:SetSlot3(val) end
|
||||
if ent.SND.Switch then sound.Play(ent.SND.Switch, ent:GetPos(), 60, 100, 0.6) end
|
||||
elseif act == "mods_apply" then
|
||||
ent:ApplyActiveRecipeFromSlots(ply)
|
||||
elseif act == "hold_pol" then
|
||||
ent._holdPol[ply] = CurTime()
|
||||
elseif act == "hold_pow" then
|
||||
ent._holdPow[ply] = CurTime()
|
||||
end
|
||||
end)
|
||||
135
addons/nyxteam_printer/lua/entities/nyxteam_printer/shared.lua
Normal file
135
addons/nyxteam_printer/lua/entities/nyxteam_printer/shared.lua
Normal file
@@ -0,0 +1,135 @@
|
||||
--[[
|
||||
|
||||
_ ___ ____ __ _______ ______ __ __
|
||||
| \ | \ \ / /\ \ / / |__ __| ____| /\ | \/ |
|
||||
| \| |\ \_/ / \ V / | | | |__ / \ | \ / |
|
||||
| . ` | \ / > < | | | __| / /\ \ | |\/| |
|
||||
| |\ | | | / . \ | | | |____ / ____ \| | | |
|
||||
|_| \_| |_| /_/ \_\ |_| |______/_/ \_\_| |_|
|
||||
|
||||
JOIN DISCORD: https://discord.gg/rUEEz4mfXw
|
||||
BY NYX TEAM (MaryBlackfild lead)
|
||||
Copyrighted Nyx Team + YouGame.biz
|
||||
|
||||
--]]
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_gmodentity"
|
||||
ENT.PrintName = "gSims Printer"
|
||||
ENT.Author = "Nyx Team"
|
||||
ENT.Category = "Nyx Team"
|
||||
ENT.Spawnable = true
|
||||
ENT.RenderGroup = RENDERGROUP_BOTH
|
||||
|
||||
ENT.CFG = {
|
||||
payout = 250,
|
||||
interval = 5,
|
||||
heat_gain = 2,
|
||||
cool_rate = 1.0,
|
||||
fire_temp = 90,
|
||||
explode_temp = 110,
|
||||
integrity = 175,
|
||||
apply_cost = 150,
|
||||
prot_cost = 500,
|
||||
pol_work_decay = 2.0,
|
||||
pow_work_decay = 2.0,
|
||||
pol_rest_gain = 6.0,
|
||||
pow_rest_gain = 6.0,
|
||||
pol_hold_gain = 8.0,
|
||||
pow_hold_gain = 8.0,
|
||||
hold_timeout = 0.45
|
||||
}
|
||||
|
||||
ENT.SND = {
|
||||
Work = "nyxteam/nyxteam_printer_working.mp3",
|
||||
Cash = "nyxteam/nyxteam_printer_cashout.mp3",
|
||||
Combo = "nyxteam/nyxteam_printer_combo.mp3",
|
||||
Alarm = "nyxteam/nyxteam_printer_alarm.mp3",
|
||||
Switch = "nyxteam/nyxteam_printer_switch.mp3",
|
||||
Vent = "nyxteam/nyxteam_printer_vent.mp3",
|
||||
Click = "nyxteam/nyxteam_printer_click.mp3",
|
||||
Ignite = "ambient/fire/ignite.wav",
|
||||
Upg = "buttons/button3.wav",
|
||||
Lock = "buttons/combine_button_locked.wav",
|
||||
OpenUI = "nyxteam/nyxteam_printer_open.mp3",
|
||||
CloseUI = "nyxteam/nyxteam_printer_lock.mp3",
|
||||
MutatorBad = "buttons/button8.wav",
|
||||
MutatorGood = "buttons/bell1.wav"
|
||||
}
|
||||
|
||||
ENT.RECIPES = {
|
||||
["AAA"] = { id = 1, name = "Разгон", payout_add = 1, heat_add = 1 },
|
||||
["AAB"] = { id = 2, name = "Эко-Буст", payout_add = 1, heat_add = 0, vent_bonus = 1 },
|
||||
["ABB"] = { id = 3, name = "Холодный Фокус", heat_add = -1, vent_bonus = 2 },
|
||||
["ABC"] = { id = 4, name = "Стелс", payout_mul = 0.9, heat_add = -1, mute = true },
|
||||
["BBB"] = { id = 5, name = "Крио-Цикл", payout_add = -1, heat_add = -2, vent_bonus = 1 },
|
||||
["BBC"] = { id = 6, name = "Радиатор", fire_at_bonus = 10, heat_add = -1 },
|
||||
["BCC"] = { id = 7, name = "Аккумулятор", payout_add = 1, passive_cool_add = 1 },
|
||||
["CCC"] = { id = 8, name = "Налоговый Щит", collect_mul = 1.25 },
|
||||
["ACC"] = { id = 9, name = "Риск-Профит", payout_add = 2, heat_add = 2 },
|
||||
}
|
||||
|
||||
ENT.UPGRADES = {
|
||||
eff = { max = 3, base = 250, step = 250 },
|
||||
cool = { max = 3, base = 200, step = 200 },
|
||||
luck = { max = 3, base = 500, step = 500 }
|
||||
}
|
||||
|
||||
ENT.LUCK = {
|
||||
[1] = { multiplier = 1.2, chance = 25 },
|
||||
[2] = { multiplier = 1.5, chance = 40 },
|
||||
[3] = { multiplier = 2.0, chance = 60 }
|
||||
}
|
||||
|
||||
ENT.SLOTS = { [0] = "A", [1] = "B", [2] = "C" }
|
||||
ENT.L2I = { A = 0, B = 1, C = 2 }
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Int", 0, "Temperature")
|
||||
self:NetworkVar("Int", 1, "Money")
|
||||
self:NetworkVar("Bool", 0, "Powered")
|
||||
self:NetworkVar("Int", 2, "Integrity")
|
||||
self:NetworkVar("Bool", 1, "OnFireState")
|
||||
self:NetworkVar("Int", 3, "EffLevel")
|
||||
self:NetworkVar("Int", 4, "CoolLevel")
|
||||
self:NetworkVar("Int", 5, "VentCombo")
|
||||
self:NetworkVar("Int", 6, "VentFlow")
|
||||
self:NetworkVar("Int", 7, "Slot1")
|
||||
self:NetworkVar("Int", 8, "Slot2")
|
||||
self:NetworkVar("Int", 9, "Slot3")
|
||||
self:NetworkVar("Int", 10, "ActiveRecipeId")
|
||||
self:NetworkVar("Int", 11, "VentState")
|
||||
self:NetworkVar("Int", 12, "Pollution")
|
||||
self:NetworkVar("Int", 13, "PowerRes")
|
||||
self:NetworkVar("Bool", 2, "IsProtected")
|
||||
self:NetworkVar("Int", 14, "LuckLevel")
|
||||
self:NetworkVar("Int", 15, "MutatorID")
|
||||
self:NetworkVar("Int", 16, "MutatorCharges")
|
||||
end
|
||||
|
||||
function ENT:GetRecipeByKey(key)
|
||||
return self.RECIPES[key]
|
||||
end
|
||||
|
||||
function ENT:SortKey(a, b, c)
|
||||
local t = { a, b, c }
|
||||
table.sort(t)
|
||||
return table.concat(t)
|
||||
end
|
||||
|
||||
function ENT:GetApplyCost(key)
|
||||
local base = self.CFG.apply_cost
|
||||
local uniq = {}
|
||||
for i = 1, #key do uniq[key:sub(i, i)] = true end
|
||||
local u = 0
|
||||
for _ in pairs(uniq) do u = u + 1 end
|
||||
local mult = 1.5
|
||||
if u == 1 then mult = 1.0 elseif u == 2 then mult = 1.2 end
|
||||
return math.floor(base * mult)
|
||||
end
|
||||
|
||||
function ENT:GetUpgradeCost(type, curLvl)
|
||||
local data = self.UPGRADES[type]
|
||||
if not data or curLvl >= data.max then return 0 end
|
||||
return data.base + (data.step * curLvl)
|
||||
end
|
||||
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_alarm.mp3
Normal file
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_alarm.mp3
Normal file
Binary file not shown.
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_cashout.mp3
Normal file
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_cashout.mp3
Normal file
Binary file not shown.
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_click.mp3
Normal file
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_click.mp3
Normal file
Binary file not shown.
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_combo.mp3
Normal file
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_combo.mp3
Normal file
Binary file not shown.
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_switch.mp3
Normal file
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_switch.mp3
Normal file
Binary file not shown.
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_vent.mp3
Normal file
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_vent.mp3
Normal file
Binary file not shown.
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_working.mp3
Normal file
BIN
addons/nyxteam_printer/sound/nyxteam/nyxteam_printer_working.mp3
Normal file
Binary file not shown.
Reference in New Issue
Block a user