Initial commit

This commit is contained in:
2026-03-15 14:54:49 +03:00
commit 64f8029c06
4027 changed files with 254888 additions and 0 deletions

View 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

View 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)

View 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