This page is used for previewing and submitting scripts for use with the Script Manager
Available Scripts
(2) TPTMulti by LBPHacker
(3) set wifi v2 by jacob1
(4) Script Paste by jacob1
(5) Random Element by jacob1
(6) Magical Merge Master 3000 by nucular
(7) More Fuel Mod-heavy by jward212
(9) Breakpoints (BRPT) by boxmein
(10) Cockroaches! by boxmein
(11) Random tree by ssccsscc
(12) Element with random properties by ssccsscc
(15) Minimalistic Element Dehider by nucular
(16) FPS Gauge by mniip
(17) TPT Radio by jward212
(18) Print Debugger by FeynmanLogomaker
(19) Powered BHOL by jacob1
(20) Light and lamps by electronic_steve
(21) Extremely Durable TTAN by QuentinADay
(22) New Buttons by QuentinADay
(23) Pure Energy by QuentinADay
(25) RCA's HUD XV Update I by RCAProduction
(27) 123456787654 vols by mjpowder
(28) Singularity Bomb by QuentinADay
(29) ES wifi set by electronic_steve
(30) Lua Elements Pack by FeynmanLogomaker
(31) stkm gun by jward212
(32) space building materials by kjack1111
(34) Rust bomb by Damian97
(35) Simple command block by ssccsscc
(36) Everlasting Fusion by QuentinADay
(37) Screenshot Organiser by mecha-man
(38) Napalm mod by cccp3
(39) Rocket fuel mod v0.15 by cccp3
(41) Useful web links by jward212
(42) TPT Logic Gates Mod by iamdumb
(43) ESTools by electronic_steve
(44) Head Crabs-HL2 by jward212
(45) Procedural Save Generator by boxmein
(46) smooth colours for nametag by jward212
(47) ZAKPACK by zak03
(49) Performance Monitor by FeynmanLogomaker
(51) Texter by byzod
(52) Texter default fonts by byzod
(53) Schicko's Font Pack for Texter by Schicko
(54) Realistic Element Names by Atomic10
(55) TPT's Mod V.3 Update 1 by Amy
(56) Temporaryaccount-Decorator by Temporaryaccount
(57) random save loader by jward212
(58) Tmp gradient display by ssccsscc
(59) particle re-orderer by mniip
(60) Electric Glow by jacob1
(61) More Fuel Mod-lite by jward212
(63) Rythidium by janekbe04
(64) Simple FPS GUI by Sfsjunior
(65) Enhanced Element Dehider by ChargedCreeper
(66) Graph of average temp by ssccsscc
(67) Template save loader by jacob1
(68) Lua Text Generator by jBot-42
(70) Pixel's Freezer by Pixelguru26
(71) Thingy | Fusion For Ever by TheChosenEvilOne
(72) op explosions by zolly_bro
(73) Scar by DorkyBobster
(74) ScreenShotMod by lill74
(77) Useful Things by TheEvilChosenOne
(78) Alchemy Mod by _MrN_
(79) Nuke v2 by Fnaf65
(80) Compressor mod by TheChosenEvilOne
(81) Custom Render Mode Loader by jacob1
(82) Spacewars by JosephMA
(83) MOAR - Alpha 0.1 by TheChosenEvilOne
(86) Element Creator by cxi
(88) Soapworm by LBPHacker
(90) Pressure Bomb by God_Kra
(91) SMFB by wntjq69
(92) Potato by cxi
(93) Subatomic Pack (BDS) by TPT_PL
(94) Acidic Pack (BDS) by TPT_PL
(95) Starbound Building Materials by Sanpypr
(96) Factory problems by TPT_PL
(97) Gamma Ray-diation by Kostia4381
(98) Magic by livingfossil
(99) Cross-window Copy/Cut/Paste by LBPHacker
(100) Langton's Ant with variations by LBPHacker
(101) Remote particle creator/deleter by TPT_PL
(102) Force fields by electronic_steve
(103) Reinforced Concrete by 12Me21
(105) TPT_PL's Lua Mod by TPT_PL
(106) Nuke v4 by Fnaf65
(107) CHEMMOD V1 by KevAK
(108) Chemicals by Ligan
(109) VonDaniel's Template by VonDaniel
(110) The Inaccurate Radioactivity Toy Mod by TuDoR2007
(112) textmonsterPack by textmonster404
(113) Meteor by TheScienceKid
(114) Tgpm by TuDoR2007
(115) Civilizations by TPT_PL
(116) RAD-MOD 1.2.1B by Kev_AK
(117) MicroLua by RamiLego4Game
(118) Extra customizable HUD by djy0212
(119) Ingame brush editor by ssccsscc
(120) Window Maker by Paul_31415
(121) CHEM-MOD V1.2B by Kev_AK
(122) Rainbow PHOT by Mrprocom
(123) stronger stickmanv by yuval
(124) 3D Pressure Visualizer by mniip
(125) Arkadian Liquid by JanKaszanka
(126) Fuel by nukers473
(127) Immersive Radioactivity v2.1 by Potbelly
(128) ElementLaunchingTool by juh9870
(129) CHEM-MOD_v1.2.2b by KevAK
(130) Slingshot by Mrprocom
(131) Perlin Noise Generator by DoubleF
(132) Element Replace by TomW1605
(133) Flooder V2 by TheAwesomeMutant
(134) Link Sign GUI by QuanTech
(135) Element dehider by 4e616d65
(136) Subphoton ROM Builder by mad-cow
(137) Hardened Dust by Liftski
(138) Bio-Vir by TheAwesomeMutant
(140) Orbit Simulator by Mrprocom
(141) johnnyou's Font for Texter by johnnyou (49796346)
(142) auto_wifi by phisically
(143) Layering helper by ssccsscc
(144) Layering Helper Extended by LuaMaster
(145) TPT Remade by TuDoR2007
(146) All-seeing sampler by djy0212
(147) Layering helper remastered by ssccsscc
(148) Eraser by thepowdertoy12
(149) EXPLOSIONS by olix3001
(150) Simple rocket fuel mod by ArseniyPlotnikov2006
(151) Pure Fission by Fnaf65
(154) Graph by ssccsscc
(155) Little's Pack! by LittleProgramming
(156) Lead by LoftisGaming
(157) WIFI Tuner by ssccsscc
(158) Previous Brush by TomW1605
(159) HUD Auto-Hider by Tim
(161) Stack tool by thepowdertoy12
(162) Oil and plastic by ArseniyPlotnikov2006
(163) Colored Ember by DUC
(164) Timer by ssccsscc
(165) Bacteria Mod by TuDoR2007
(166) Noise filter by LBPHacker
(167) Future-proof element dehider by LBPHacker
(168) RadioactiveNuke by DreamingWarlord
(169) Only Hot Element by DreamingWarlord
(170) Philosopher's Stone by Godhydra
(171) Conic section generator by LBPHacker
(172) Interface API by ssccsscc
(173) Metals&Materials by Ferrous26
(174) tpt.all by LBPHacker
(175) The Visual Elements Pack by Goblin01, vvv331
(176) Layering Helper Reforged by PowderNotSolid
(177) SNOWified SING by LBPHacker
(178) FPS Chart by Goblin01
(179) TPT font writer by Goblin01
(180) Simple Ruler by PowderNotSolid
(181) Heat Modifier by DreamingWarlord
(182) TPT Remade II by TuDoR2007
(183) Gravity simulator by ArseniyPlotnikov2k6
(184) Unobtainium by christheboss894
(185) TPTMIDI noteblock in tpt by djy0212
(186) DreamingWarlord's Lua Tool by DreamingWarlord
(187) Elements Tooltip by Goblin01
(189) Explodium script by 0d15ea5ebe57c0debadc0ffee0ddf00d
(190) more powered force elements by 6nop6nop
(191) Yzaak1Scifire Modpack by Yzaak1Scifire
(194) Fluor and more modpack! by galaktor
(195) Hot Powder by lieve_blendi
(196) Star by TUANMINHVIETNAM
(197) Heat Powders by lieve_blendi
(200) Tangeriinium (thx 2 cxi 4 code) by LostEditor
(201) Freezer by lieve_blendi
(202) Powder Power! by TPTSortaGuy
(203) PowderPlus v1.4 by PowderPlus Team
(204) fire by ME
(205) Stacked Goo Animations by Maticzpl
(206) Stickman Control for Android Version by PhauloRiquelme
(207) Spark Removal Button by Xyz
(208) More HEAC's! by Maxhd1234
(209) Immersive Radioactivity v3.0 by Potbelly
(210) Subframe Chipmaker Script by Maticzpl
(211) Realistic Propellants by ArseniyPlotnikov2k6
(212) Mass Equals Gravity by Maticzpl
(213) PhiMod v1 by ArolaunTech
(214) PC Controls for Android by Cracker1000
(217) Single-pixel pipe configurator by LBPHacker
(218) Omega Death Laser Gun by Dogeoum
(219) Notifications by Maticzpl
(221) Powderizer by ArolaunTech
(222) ElemDehider 1.2 by Inventor70
(223) Unobtainum V2 by DoomKittyAttack
(224) Organics Mod v0.2B by PowderPlus Team
(225) Gravity distortion by Avolte55
(226) tmp Wifi by PhauloRiquelme
(227) Alchemagica Mod v1.0 by RebMiami
(228) Fan Elements Mod by RebMiami
(229) Impossibilities by ArolaunTech
(230) Realistic Explosives by ArseniyPlotnikov2k6
(231) libactivation by anamorphic
(232) Alloy Brushes by Maticzpl
(233) Gravity bender by pres
(234) Slow Tick by Pixel
(235) Paste ID by Maticzpl
(236) many things by jadenflp2
(237) Territect by Rebmiami
(238) Better Descriptions v1.0.5 by ashyboi2022
(239) LIGHTNING SPRK by GOLmaster10101
(240) Small Bombs by juh9870
(241) Save Shop by aaccbb
(242) Moving solids v1.3.0 Beta by ArolaunTech
(244) Alchemistry by rdococ
(245) ETRD (Formerly PowderIM) by aaccbb
(246) RadonX by Justadirtblock
(248) Water-X by deuterium_oxide
(250) Indestructible INSL by CheekyRand0m
(252) Console's Mod by Console/Compec
(255) Slow motion by LBPHacker
(256) Powered Repeller by Hythonia
(257) Zeta's Electric Tools. by Zetalasis
(258) Azure serum (AZSR) by ALumpOfPowderToy
(259) COLORFULSAND by xert
(260) Lightning Circle by defaultuser0
(261) Powder Future Tech by JonaHungary
(262) TPTGlowingSolids by DestinyDyson
(263) Volcano Bomb by I_am_the_NugsWorld
(264) Neon Lights by Rebmiami
(265) Radioactive Materials by xyz
(266) Eater mod by VIPERGAMEZ
(267) the biology mod by someone
(268) Atomic Physics by qe
(269) Pure Radiation by ronansb
(270) Fake Elements by That_PowderToy_Guy
(271) Tachyons and MISC by RamenNoods
(272) Exotic Particles by rdococ
(273) FPS Slider by aaccbb
(274) Enphosian's Radioactive mod pack by Enphosian
(276) ROM Builder by QnpfvTPz
(277) acb's Idea Generator by aaccbb
+ Submit new script!
Title:
Author:
Script:
---------------------------------------------------------------------------------
-- JSON parsing from https://gist.github.com/tylerneylon/59f4bcf316be525b30ab --
-- Credit to tylerneylon --
-- Stated to be public domain by the author (check comments in the link) --
---------------------------------------------------------------------------------
--#region
local json = {}
local function kind_of(obj)
if type(obj) ~= 'table' then return type(obj) end
local i = 1
for _ in pairs(obj) do
if obj[i] ~= nil then i = i + 1 else return 'table' end
end
if i == 1 then return 'table' else return 'array' end
end
local function escape_str(s)
local in_char = {'\\', '"', '/', '\b', '\f', '\n', '\r', '\t'}
local out_char = {'\\', '"', '/', 'b', 'f', 'n', 'r', 't'}
for i, c in ipairs(in_char) do
s = s:gsub(c, '\\' .. out_char[i])
end
return s
end
local function skip_delim(str, pos, delim, err_if_missing)
pos = pos + #str:match('^%s*', pos)
if str:sub(pos, pos) ~= delim then
if err_if_missing then
error('Expected ' .. delim .. ' near position ' .. pos)
end
return pos, false
end
return pos + 1, true
end
local function parse_str_val(str, pos, val)
val = val or ''
local early_end_error = 'End of input found while parsing string.'
if pos > #str then error(early_end_error) end
local c = str:sub(pos, pos)
if c == '"' then return val, pos + 1 end
if c ~= '\\' then return parse_str_val(str, pos + 1, val .. c) end
-- We must have a \ character.
local esc_map = {b = '\b', f = '\f', n = '\n', r = '\r', t = '\t'}
local nextc = str:sub(pos + 1, pos + 1)
if not nextc then error(early_end_error) end
return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))
end
local function parse_num_val(str, pos)
local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)
local val = tonumber(num_str)
if not val then error('Error parsing number at position ' .. pos .. '.') end
return val, pos + #num_str
end
function json.stringify(obj, as_key)
local s = {}
local kind = kind_of(obj)
if kind == 'array' then
if as_key then error('Can\'t encode array as key.') end
s[#s + 1] = '['
for i, val in ipairs(obj) do
if i > 1 then s[#s + 1] = ', ' end
s[#s + 1] = json.stringify(val)
end
s[#s + 1] = ']'
elseif kind == 'table' then
if as_key then error('Can\'t encode table as key.') end
s[#s + 1] = '{'
for k, v in pairs(obj) do
if #s > 1 then s[#s + 1] = ', ' end
s[#s + 1] = json.stringify(k, true)
s[#s + 1] = ':'
s[#s + 1] = json.stringify(v)
end
s[#s + 1] = '}'
elseif kind == 'string' then
return '"' .. escape_str(obj) .. '"'
elseif kind == 'number' then
if as_key then return '"' .. tostring(obj) .. '"' end
return tostring(obj)
elseif kind == 'boolean' then
return tostring(obj)
elseif kind == 'nil' then
return 'null'
else
error('Unjsonifiable type: ' .. kind .. '.')
end
return table.concat(s)
end
json.null = {}
function json.parse(str, pos, end_delim)
pos = pos or 1
if pos > #str then error('Reached unexpected end of input.') end
local pos = pos + #str:match('^%s*', pos)
local first = str:sub(pos, pos)
if first == '{' then
local obj, key, delim_found = {}, true, true
pos = pos + 1
while true do
key, pos = json.parse(str, pos, '}')
if key == nil then return obj, pos end
if not delim_found then error('Comma missing between object items.') end
pos = skip_delim(str, pos, ':', true)
obj[key], pos = json.parse(str, pos)
pos, delim_found = skip_delim(str, pos, ',')
end
elseif first == '[' then
local arr, val, delim_found = {}, true, true
pos = pos + 1
while true do
val, pos = json.parse(str, pos, ']')
if val == nil then return arr, pos end
if not delim_found then error('Comma missing between array items.') end
arr[#arr + 1] = val
pos, delim_found = skip_delim(str, pos, ',')
end
elseif first == '"' then
return parse_str_val(str, pos + 1)
elseif first == '-' or first:match('%d') then
return parse_num_val(str, pos)
elseif first == end_delim then
return nil, pos + 1
else
local literals = {['true'] = true, ['false'] = false, ['null'] = json.null}
for lit_str, lit_val in pairs(literals) do
local lit_end = pos + #lit_str - 1
if str:sub(pos, lit_end) == lit_str then return lit_val, lit_end + 1 end
end
local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)
error('Invalid json syntax starting at ' .. pos_info_str)
end
end
-- #endregion
-- Thanks @krftdnr#1652 for this rect code!
--#region
local function DrawRect(x1, y1, x2, y2, r,g,b,a,adjust)
if adjust then
x1, y1 = sim.adjustCoords(x1,y1)
x2, y2 = sim.adjustCoords(x2,y2)
end
local function isInZoom(x, y)
local zx, zy, zs = ren.zoomScope()
return ren.zoomEnabled() and
x >= zx and x < zx + zs and
y >= zy and y < zy + zs
end
local function calcOffset(x, y)
local ex, ey, scale, size = ren.zoomWindow()
local zx, zy, zs = ren.zoomScope()
return (x - zx) * scale + ex, (y - zy) * scale + ey
end
local startX = x1
local finalX = x2
if x2 < x1 then
finalX = x1
startX = x2
end
local ex, ey, scale, size = ren.zoomWindow()
for rx = startX, finalX do
local nx1, ny1 = calcOffset(rx, y1)
local nx2, ny2 = calcOffset(rx, y2)
if isInZoom(rx, y1) then
gfx.fillRect(nx1, ny1, scale - 1, scale - 1, r,g,b,a)
end
if isInZoom(rx, y2) then
gfx.fillRect(nx2, ny2, scale - 1, scale - 1, r,g,b,a)
end
end
local startY = y1
local finalY = y2
if y2 < y1 then
finalY = y1
startY = y2
end
for ry = startY + 1, finalY - 1 do
local nx1, ny1 = calcOffset(x1, ry)
local nx2, ny2 = calcOffset(x2, ry)
if isInZoom(x1, ry) then
gfx.fillRect(nx1, ny1, scale - 1, scale - 1, r,g,b,a)
end
if isInZoom(x2, ry) then
gfx.fillRect(nx2, ny2, scale - 1, scale - 1, r,g,b,a)
end
end
local sizeX = x2 - x1
local sizeY = y2 - y1
if x1 > x2 then
sizeX = x1 - x2
x1 = x2
end
if y1 > y2 then
sizeY = y1 - y2
y1 = y2
end
gfx.drawRect(x1, y1, sizeX, sizeY, r,g,b,a)
end
--#endregion
local MANAGER = rawget(_G, "MANAGER")
local tmp3name = "pavg0"
local tmp4name = "pavg1"
if sim.FIELD_TMP3 then
tmp3name = "tmp3"
tmp4name = "tmp4"
end
local alloys = {}
local function inBounds(x,y)
return x >= 0 and y >= 0 and x < sim.XRES and y < sim.YRES
end
local function colorCheck(color)
if color == nil then
return false
end
local r = bit.rshift(bit.band(0xFF0000,color), 16)
local g = bit.rshift(bit.band(0xFF00,color), 8)
local b = bit.band(0xFF,color)
return r >= 0 and r < 256 and g >= 0 and g < 256 and b >= 0 and b < 256
end
local function sectionCheck(section)
for k, v in pairs(elem) do
if string.sub(k, 1, 2) == "SC" then
if type(section) == "number" and v == section then
return v
end
if string.sub(k, 4) == section then
return v
end
end
end
return nil
end
local function saveAlloy(x, y, rx, ry, name, desc, color, menusection, struct)
desc = desc or "Custom alloy"
color = color or 0xFFFFFF
menusection = sectionCheck(menusection)
assert(#name > 0, "Name cannot be empty")
assert(inBounds(x,y), "Position out of bounds")
assert(inBounds(rx,ry), "Position out of bounds")
assert(colorCheck(color), "Wrong color")
assert(menusection ~= nil, "Wrong menu section")
local structure = {}
if struct then
structure = struct
else
for ix = x, rx do
for iy = y, ry do
local cx = ix - x + 1
local cy = iy - y + 1
structure[cy] = structure[cy] or {}
structure[cy][cx] = structure[cy][cx] or {}
for pt in sim.parts() do
local ptx, pty = sim.partPosition(pt)
ptx = math.floor(ptx + 0.5)
pty = math.floor(pty + 0.5)
if ptx == ix and pty == iy then
local ptdata = {}
ptdata.type = sim.partProperty(pt, 'type')
ptdata.temp = math.floor(sim.partProperty(pt, 'temp')*100 + 0.5)/100
if ptdata.temp == 295.15 then ptdata.temp = nil end
ptdata.ctype = sim.partProperty(pt, 'ctype')
if ptdata.ctype == 0 then ptdata.ctype = nil end
ptdata.tmp = sim.partProperty(pt, 'tmp')
if ptdata.tmp == 0 then ptdata.tmp = nil end
ptdata.tmp2 = sim.partProperty(pt, 'tmp2')
if ptdata.tmp2 == 0 then ptdata.tmp2 = nil end
ptdata.tmp3 = sim.partProperty(pt, tmp3name)
if ptdata.tmp3 == 0 then ptdata.tmp3 = nil end
ptdata.tmp4 = sim.partProperty(pt, tmp4name)
if ptdata.tmp4 == 0 then ptdata.tmp4 = nil end
ptdata.life = sim.partProperty(pt, 'life')
if ptdata.life == 0 then ptdata.life = nil end
ptdata.vx = sim.partProperty(pt, 'vx') -- lmao I'm keeping this
if ptdata.vx == 0 then ptdata.vx = nil end
ptdata.vy = sim.partProperty(pt, 'vy')
if ptdata.vy == 0 then ptdata.vy = nil end
ptdata.dcolour = sim.partProperty(pt, 'dcolour')
if ptdata.dcolour == 0 then ptdata.dcolour = nil end
ptdata.flags = sim.partProperty(pt, 'flags')
if ptdata.flags == 0 then ptdata.flags = nil end
table.insert(structure[cy][cx], ptdata)
end
end
end
end
end
local alloy = elements.allocate("MATICZPL-ALLOY", name)
elements.element(alloy, elements.element(elements.DEFAULT_PT_DMND))
elements.property(alloy, "Name", name)
elements.property(alloy, "Description", desc)
elements.property(alloy, "Colour", color)
elements.property(alloy, "MenuSection", menusection)
elements.property(alloy, "Create", function (i, x, y, t, v)
sim.partKill(i)
local row = structure[y % #structure + 1]
local stack = row[x % #row + 1]
for _, ptdata in ipairs(stack) do
local id = sim.partCreate(-3, x, y, ptdata.type)
sim.partProperty(id, 'temp', ptdata.temp or 295.15)
sim.partProperty(id, 'ctype', ptdata.ctype or 0)
sim.partProperty(id, 'tmp', ptdata.tmp or 0)
sim.partProperty(id, 'tmp2', ptdata.tmp2 or 0)
sim.partProperty(id, tmp3name, ptdata.tmp3 or 0)
sim.partProperty(id, tmp4name, ptdata.tmp4 or 0)
sim.partProperty(id, 'life', ptdata.life or 0)
sim.partProperty(id, 'vx', ptdata.vx or 0)
sim.partProperty(id, 'vy', ptdata.vy or 0)
sim.partProperty(id, 'dcolour', ptdata.dcolour or 0)
sim.partProperty(id, 'flags', ptdata.flags or 0)
end
end)
-- name, description, color, menusection, structure, handle
table.insert(alloys, {name = name, description = desc, color = color, menusection = menusection, structure = structure, handle = alloy})
local alloysJson = string.gsub(json.stringify(alloys), "\n", " ")
alloysJson = string.gsub(alloysJson, "\"", "\'")
MANAGER.savesetting("MaticzplAlloys","SavedAlloys", alloysJson)
end
local function loadAlloy(obj)
saveAlloy(0, 0, 0, 0, obj.name, obj.description, obj.color, obj.menusection, obj.structure)
end
local function reloadAlloys(remove)
local temp = json.parse(json.stringify(alloys)) -- please forgive me
alloys = {}
for i, obj in ipairs(temp) do
elem.free(obj.handle)
if i ~= remove then
loadAlloy(obj)
end
end
end
local saveData = MANAGER.getsetting("MaticzplAlloys","SavedAlloys") or "{}"
saveData = string.gsub(saveData, "\'", "\"")
local success, parsed = pcall(json.parse, saveData)
if success then
for _, alloy in ipairs(parsed) do
loadAlloy(alloy)
end
else
MANAGER.savesetting("MaticzplAlloys","SavedAlloys", "{}")
end
-- UI
local function promptAlloySettings(done, cancel, default)
local function hsvToRgb(h, s, v) --h, s and v are values from 0 to 255. The r g b values must be from 0 to 255
h = h / 255
s = s / 255
v = v / 255
local r, g, b
local i = math.floor(h * 6)
local f = h * 6 - i
local p = v * (1 - s)
local q = v * (1 - f * s)
local t = v * (1 - (1 - f) * s)
if i == 0 then r = v g = t b = p end
if i == 1 then r = q g = v b = p end
if i == 2 then r = p g = v b = t end
if i == 3 then r = p g = q b = v end
if i == 4 then r = t g = p b = v end
if i == 5 then r = v g = p b = q end
return math.floor(r * 255), math.floor(g * 255), math.floor(b * 255)
end
local function rgbToHsv(r, g, b)
r = r / 255
g = g / 255
b = b / 255
local max = math.max(r, g, b)
local min = math.min(r, g, b);
local h, s, v = max, max, max;
local d = max - min;
if max == 0 then
s = 0
else
s = d / max
end
if (max == min) then
h = 0;
else
if max == r then
local f = 0
if g < b then
f = 6
end
h = (g - b) / d + f;
end
if max == g then h = (b - r) / d + 2 end
if max == b then h = (r - g) / d + 4 end
h = h / 6;
end
return h, s, v
end
local winW = 300
local winH = 152
local winX = gfx.WIDTH / 2 - winW / 2
local winY = gfx.HEIGHT / 2 - winH / 2
local win = Window:new(winX, winY, winW, winH)
local name, desc, col, category
local color = {100, 255, 255}
if default then
name = default.name
desc = default.description
category = default.menusection
local h, s, v = rgbToHsv(bit.rshift(bit.band(0xFF0000, default.color),16), bit.rshift(bit.band(0xFF00, default.color),8), bit.band(0xFF, default.color))
color[1] = h * 255
color[2] = s * 255
color[3] = v * 255
end
local function doGfx()
local x = winX
local y = winY
-- convert color from HSV to RGB
local r, g, b = hsvToRgb(color[1], color[2], color[3])
col = bit.bor(bit.lshift(r, 16), bit.lshift(g, 8), b)
gfx.fillRect(x + 2, y + 2, 30, 30, r, g, b)
gfx.drawRect(x + 2, y + 2, 30, 30, 255, 255, 255)
end
win:onDraw(doGfx)
local y = 1
-- HSV sliders
--#region
local hSlider = Slider:new(34, y, winW - 37, 10)
hSlider:steps(254)
hSlider:value(color[1])
hSlider:onValueChanged(function (sender, value)
color[1] = value
end)
win:addComponent(hSlider)
y = y + 10
local sSlider = Slider:new(34, y, winW - 37, 10)
sSlider:steps(255)
sSlider:value(color[2])
sSlider:onValueChanged(function (sender,value)
color[2] = value
end)
win:addComponent(sSlider)
y = y + 10
local vSlider = Slider:new(34, y, winW - 37, 10)
vSlider:steps(255)
vSlider:value(color[3])
vSlider:onValueChanged(function (sender,value)
color[3] = value
end)
win:addComponent(vSlider)
y = y + 10
--#endregion
local txtbxName = Textbox:new(2, y + 2, 40, 15, name or "", "NAME")
txtbxName:onTextChanged(function (sender)
local text = sender:text()
if text == "" then
text = nil
end
name = text
end)
win:addComponent(txtbxName)
y = y + 17
local txtbxDesc = Textbox:new(2, y + 2, winW - 4, 15, desc or "", "DESCRIPTION")
txtbxDesc:onTextChanged(function (sender)
local text = sender:text()
desc = text
end)
win:addComponent(txtbxDesc)
y = y + 17
-- checkboxes
--#region
local checkboxes = {}
local sections = {
[9 ] = "SOLIDS",
[12] = "LIFE",
[10] = "NUCLEAR",
[1 ] = "ELEC",
[11] = "SPECIAL",
[6 ] = "GAS",
[5 ] = "EXPLOSIVE",
[2 ] = "POWERED",
[4 ] = "FORCE",
[13] = "TOOL",
[3 ] = "SENSOR",
[0 ] = "WALL",
[8 ] = "POWDERS",
[7 ] = "LIQUID",
}
local x = 2
for i = 0, 14 do
if i ~= 14 then
local w = 75
local checkbox = Checkbox:new(x, y + 2, w, 15, sections[i])
checkbox:checked(sectionCheck(category) == i)
table.insert(checkboxes, checkbox)
checkbox:action(function (sender, value)
for _, v in ipairs(checkboxes) do
v:checked(false)
end
sender:checked(value)
if value then
category = i
else
category = nil
end
end)
win:addComponent(checkbox)
x = x + w
if x + w > 298 then
x = 2
y = y + 17
end
table.insert(checkboxes, checkbox)
end
end
--#endregion
local saveButton = Button:new(winW - 29, winH - 17, 27, 15, "SAVE")
saveButton:action(function (sender)
if name == nil or name == "" then
return
end
if category == nil then
return
end
if desc == nil then
desc = ""
end
interface.closeWindow(win)
done(name, desc, col, category)
end)
win:addComponent(saveButton)
local cancelButton = Button:new(winW - 69, winH - 17, 39, 15, "CANCEL")
cancelButton:action(function (sender)
interface.closeWindow(win)
cancel()
end)
win:addComponent(cancelButton)
interface.showWindow(win)
end
local currentlySelecting = false
local selectStart = {}
local selectEnd = {}
local events = {}
local function defineAlloy()
currentlySelecting = true
table.insert(events, {event.mousedown, function (x, y, button)
if button == 1 then
x, y = sim.adjustCoords(x, y)
selectStart = {x, y}
end
return false
end})
table.insert(events, {event.mouseup, function (x, y, button, reason)
if button == 1 then
for _, ev in ipairs(events) do
event.unregister(ev[1], ev[2])
end
events = {}
promptAlloySettings(function (name, desc, col, category)
local leftTopX = math.min(selectStart[1], selectEnd[1])
local leftTopY = math.min(selectStart[2], selectEnd[2])
local rightBottomX = math.max(selectStart[1], selectEnd[1])
local rightBottomY = math.max(selectStart[2], selectEnd[2])
selectStart = {}
selectEnd = {}
saveAlloy(leftTopX, leftTopY, rightBottomX, rightBottomY, name, desc, col, category)
end, function ()
selectStart = {}
selectEnd = {}
end)
currentlySelecting = false
elseif button == 3 then
currentlySelecting = false
end
return false
end})
table.insert(events, {event.keyrelease, function (key, scan, rep, shift, ctrl, alt)
if key == 41 and not rep and not shift and not ctrl and not alt then
currentlySelecting = false
end
return false
end})
table.insert(events, {event.tick, function ()
if not currentlySelecting then
for _, ev in ipairs(events) do
event.unregister(ev[1], ev[2])
end
events = {}
selectStart = {}
selectEnd = {}
else
tpt.set_pause(1)
graphics.fillRect(0,0,sim.XRES,sim.YRES,0,0,0,128)
graphics.drawText(15,360,"Select alloy. (Right click to cancel)",252, 232, 3)
local x, y = sim.adjustCoords(tpt.mousex, tpt.mousey)
selectEnd = {x, y}
if selectStart[1] then
DrawRect(selectStart[1], selectStart[2], selectEnd[1], selectEnd[2], 255, 255, 255, 128)
end
end
end})
for _, ev in ipairs(events) do
event.register(ev[1], ev[2])
end
end
local scroll = 0
local function openGUI()
local winW = 447
local winH = 223
local win = Window:new(-1,87, winW, winH)
local winX = (gfx.WIDTH - winW) / 2
local winY = 87
local entryH = 21
local maxH = 200
--- @type Component[]
local scrollableComponents = {}
local oldX, oldY, oldW, oldH = gfx.setClipRect()
local function drawScrollbar()
local sbarX = winX + winW - 13
local sbarY = 109
local sbarW = 8
local sbarH = 196
local currentH = #alloys * entryH
local thmbX = sbarX + 2
local thmbW = sbarW - 4
local thmbH = sbarH - 4
local thmbY = sbarY + 2
thmbH = math.max(math.min(sbarH - 4, math.floor(sbarH * ((maxH - entryH) / currentH)) + 1), 20)
thmbY = sbarY + 2 + ((sbarH - 4) - thmbH) * (scroll / (currentH - maxH + entryH))
graphics.drawRect(sbarX, sbarY, sbarW, sbarH, 255, 255, 255, 255)
--draw scrollbar thumb
graphics.fillRect(thmbX, thmbY, thmbW, thmbH, 200, 200, 200, 255)
end
local function doGfx() --All the graphics that are drawn inside the window.
local sectionIcons = {
[9 ] = "\238\129\145", -- SOLIDS
[12] = "\238\129\146", -- LIFE
[10] = "\238\129\134", -- NUCLEAR
[1 ] = "\238\129\130", -- ELEC
[11] = "\238\129\140", -- SPECIAL
[6 ] = "\238\129\133", -- GAS
[5 ] = "\238\129\131", -- EXPLOSIVE
[2 ] = "\238\129\150", -- POWERED
[4 ] = "\238\129\162", -- FORCE
[13] = "\238\129\151", -- TOOL
[3 ] = "\238\128\153", -- SENSOR
[0 ] = "\238\129\129", -- WALL
[8 ] = "\238\129\144", -- POWDERS
[7 ] = "\238\129\132", -- LIQUID
}
gfx.setClipRect(oldX, oldY, oldW, oldH)
graphics.fillRect(0,0,gfx.WIDTH,gfx.HEIGHT,0,0,0)
graphics.drawRect(winX, winY, winW, winH, 255, 255, 255, 255)
local text = "Alloy Brushes by Maticzpl"
gfx.drawText(winX + 50,94,text,32,216,255,255)
text = "Thanks Cracker1000 for helping with GUI"
gfx.drawText(winX + 220,94,text,100,100,100,255)
gfx.fillRect(winX + 144,107,300,200,90,90,90,100)
gfx.drawRect(winX + 144,107,300,200,255,255,255,255)
drawScrollbar()
oldX, oldY, oldW, oldH = gfx.setClipRect(winX, 108, winW, 198)
for i, entry in ipairs(alloys) do
local x = winX + 146
local y = winY + 22 + (i - 1) * entryH - scroll
gfx.fillRect(x, y, 287, 20, 70, 70, 70, 255)
gfx.drawRect(x, y, 287, 20, 255, 255, 255, 255)
-- Color
gfx.fillRect(x + 2, y + 2, 16, 16, bit.rshift(bit.band(0xFF0000, entry.color),16), bit.rshift(bit.band(0xFF00, entry.color),8), bit.band(0xFF, entry.color), 255)
gfx.drawRect(x + 2, y + 2, 16, 16, 255, 255, 255, 255)
-- make 2 nexted forloop to itterate a 16x16 matrix
gfx.fillRect(x + 20, y + 2, 16, 16, 0, 0, 0, 255)
local zoom = math.max(math.min(8 / math.max(#entry.structure, #entry.structure[1]), 4),0.5)
for rj = 1, math.floor(15 / zoom), math.floor(15 / zoom) / 16 do
for rk = 1, math.floor(15 / zoom), math.floor(15 / zoom) / 16 do
local j = math.floor(rj + 0.5)
local k = math.floor(rk + 0.5)
if entry.structure[j] and entry.structure[j][k] and entry.structure[j][k][1] then
local type = entry.structure[j][k][1].type
local deco = entry.structure[j][k][1].dcolour or 0
local col = elem.property(type, "Color")
if deco ~= 0 then
col = deco
end
gfx.fillRect(x + 20 + k * zoom, y + 2 + j * zoom, math.floor(zoom + 0.5), math.floor(zoom + 0.5), bit.rshift(bit.band(0xFF0000, col),16), bit.rshift(bit.band(0xFF00, col),8), bit.band(0xFF, col), 255)
end
end
end
gfx.drawRect(x + 20, y + 2, 16, 16, 255, 255, 255, 255)
gfx.drawText(x + 40, y + 2, sectionIcons[entry.menusection] .. " " .. entry.name, 255, 255, 255, 255)
local desc = entry.description
while gfx.textSize(desc) > 170 do
desc = desc:sub(1, -2)
end
gfx.drawText(x + 55, y + 10, desc, 200, 200, 200, 255)
end
end
win:onDraw(doGfx) -- Enables drawing stuff into windows
win:onMouseWheel(function(x,y,d)
local prevScroll = scroll
scroll = scroll - d * 4
if scroll < 0 then
scroll = 0
end
if scroll > math.max(0, #alloys * entryH - maxH + entryH) then
scroll = math.max(0, #alloys * entryH - maxH + entryH)
end
local diff = prevScroll - scroll
for _, component in ipairs(scrollableComponents) do
local x, y = component:position()
component:position(x, y + diff)
end
end)
-- Left side buttons
--#region
local y = 21
local btnNew = Button:new(3, y, 140, 20, "New Alloy")
btnNew:action(function(sender)
defineAlloy()
interface.closeWindow(win)
end)
win:addComponent(btnNew)
y = y + 20
local helpLbl = Label:new(3, y, 140, winH - y, "Welcome to Alloy Brushes!\n\nChangelog:\n1.0 - Initial Release\n1.1 - Fixed scrolling")
win:addComponent(helpLbl)
--#endregion
-- Existing alloys buttons
--#region
for i, entry in ipairs(alloys) do
local x = 146
local y = 22 + (i - 1) * entryH - scroll
-- make a label to on top of the buttom below
local btnDel = Button:new(x + 287 - 17, y + 2, 16, 16)
btnDel:action(function(sender)
scroll = math.max(scroll - entryH, 0)
interface.closeWindow(win)
reloadAlloys(i)
openGUI()
end)
local btnDelLbl = Label:new(x + 287 - 17 + 8, y + 2 + 7, 0, 0, "\238\128\170")
win:addComponent(btnDel)
win:addComponent(btnDelLbl)
table.insert(scrollableComponents, btnDel)
table.insert(scrollableComponents, btnDelLbl)
local btnUp = Button:new(x + 287 - 34, y + 2, 16, 16)
btnUp:action(function(sender)
if i > 1 then
table.insert(alloys, i - 1, table.remove(alloys, i))
interface.closeWindow(win)
openGUI()
end
end)
btnUp:enabled(i ~= 1)
local btnUpLbl = Label:new(x + 287 - 34 + 7, y + 2 + 7, 0, 0, "\238\129\139")
win:addComponent(btnUp)
win:addComponent(btnUpLbl)
table.insert(scrollableComponents, btnUp)
table.insert(scrollableComponents, btnUpLbl)
local btnDown = Button:new(x + 287 - 51, y + 2, 16, 16)
btnDown:action(function(sender)
if i < #alloys then
table.insert(alloys, i + 1, table.remove(alloys, i))
interface.closeWindow(win)
openGUI()
end
end)
btnDown:enabled(i ~= #alloys)
local btnDownLbl = Label:new(x + 287 - 51 + 7, y + 2 + 5, 0, 0, "\238\129\138")
win:addComponent(btnDown)
win:addComponent(btnDownLbl)
table.insert(scrollableComponents, btnDown)
table.insert(scrollableComponents, btnDownLbl)
local btnEdit = Button:new(x + 287 - 68, y + 2, 16, 16)
btnEdit:action(function(sender)
interface.closeWindow(win)
promptAlloySettings(function (name, desc, col, category)
alloys[i].name = name
alloys[i].description = desc
alloys[i].color = col
alloys[i].menusection = category
reloadAlloys()
openGUI()
end, function ()
openGUI()
end, entry)
end)
local btnEditLbl = Label:new(x + 287 - 68 + 7, y + 2 + 6, 0, 0, "\238\128\131")
win:addComponent(btnEdit)
win:addComponent(btnEditLbl)
table.insert(scrollableComponents, btnEdit)
table.insert(scrollableComponents, btnEditLbl)
end
--#endregion
win:onTryExit(function()
scroll = 0
gfx.setClipRect(oldX, oldY, oldW, oldH) -- This is CURSED af Just pray this wont break another mod
reloadAlloys() -- This is needed to save in case position in list changed
interface.closeWindow(win)
end)
interface.showWindow(win)
end
local alloyTool = elements.allocate("MATICZPL","ALOY")
elements.element( alloyTool, elements.element(elements.DEFAULT_PT_DMND))
elements.property(alloyTool, "Name", "ALOY")
elements.property(alloyTool, "Description", "Manage your custom alloys")
elements.property(alloyTool, "Colour", 0x257ebe)
elements.property(alloyTool, "MenuSection", elem.SC_TOOL)
elements.property(alloyTool, "Create", function (i, x, y, t, v)
sim.partKill(i)
end)
local lastSelected = {
l = 0, a = 0, r = 0, rep = 0
}
event.register(event.tick, function ()
if tpt.selectedl == "MATICZPL_PT_ALOY" or
tpt.selecteda == "MATICZPL_PT_ALOY" or
tpt.selectedr == "MATICZPL_PT_ALOY" or
tpt.selectedreplace == "MATICZPL_PT_ALOY" then
openGUI()
tpt.selectedl = lastSelected.l
tpt.selecteda = lastSelected.a
tpt.selectedr = lastSelected.r
tpt.selectedreplace = lastSelected.rep
end
lastSelected.l = tpt.selectedl
lastSelected.a = tpt.selecteda
lastSelected.r = tpt.selectedr
lastSelected.rep = tpt.selectedreplace
end)