I've located how water electrolysis is handled in elements/SPRK.cpp and holy shit what a bigass update function.
Is it even possible to add electrolytic reactions in Lua? Or I have to suck it, get a C compiler setup correctly and build a whole modded TPT (which I frankly prefer not to)?
I guess I could set the update function of the element I want to split to watch its boundaries for sparked iron. How could I do that? How can I check the ctype of an element?
I've seen others mods here using tpt.element_func() to modify the update function. Is that the correct way to do it still?
And that's enough questions for now. :P
elements.property()function with it (somewhat preferred to the legacy methods under
tpt.*!)
-- create a function that accepts the parameters:
-- index (integer, particle index, used to refer to the particle in other function calls)
-- partx (integer, particle's X coordinate from left edge, used to find out what the particle's position is)
-- party (integer, particle's Y coordinate from the top edge, used to find out what the particle's position is)
-- surround_space (integer, tells you how many empty spaces are around this particle's Moore neighbourhood)
-- nt (integer, tells you how many particles of both empty space and not-this-element are around this particle)
function updatemyparticle(index, partx, party, surround_space, nt)
if nt > 0 then
for ri, rx, ry in sim.neighbours(partx, party, 1)
local ctype = sim.partProperty(ri, "ctype")
if ctype == elements.DEFAULT_PT_IRON then
-- gotcha!
elif ctype == elements.DEFAULT_PT_METL then
-- gotcha!
else
-- idk
end
end
end
end
-- every element has an "Update" property that keeps its update function.
-- elem.DEFAULT_PT_WATR keeps the element ID of water, and can be used forever to refer to
-- water as an element.
-- same thing could be done with tpt.element_func (id, callback)
elements.property(elem.DEFAULT_PT_WATR, "Update", updatemyparticle)
Quite helpful, thanks!
But now I have a quite odd behaviour:
local function salt_Update(index, partx, party, surround_space, nt)
if nt > 0 then
for fx = -1, 1, 1 do
for fy = -1, 1, 1 do
if sim.partProperty(sim.partID(partx + fx, party + fy), 'type') == elements.DEFAULT_PT_GOLD then
sim.partChangeType(index, elements.DEFAULT_PT_CNCT)
end
end
end
--[[
for i in sim.neighbors(partx, party) do
if sim.partProperty(i, 'type') == elements.DEFAULT_PT_GOLD then
sim.partChangeType(index, elements.DEFAULT_PT_CNCT)
end
end
]]
end
end
elements.property(elements.DEFAULT_PT_SALT, "Update", salt_Update)
(What a chore to indent that, god)
The first method works.
Unless I put some gold before adding any salt. If I do that, any salt will change instantly into concrete, regardless of distance with gold.
However, if I put salt/saltwater before adding gold, it works as it should.
Also, it's freaking slow.
The second method is funky. Adding a pile of salt on top of some gold does nothing, but drawing an horizontal line of gold half screen away changes a whole column of salt into concrete.
I am messing up with the index and coordinates here, but I can't get it right.
You have discovered two previously unknown bugs in the Lua API. (Although I'm amazed no-one's noticed them before... maybe this shows how few people are attempting to use the new API functions)
First, in sim.partID. The return value of sim.partID doesn't indicate whether there is a particle in that location or not - if it returns 0 then either there is no particle there, or particle 0 is there. So if no particle exists in the location partx+fx, party+fy then your code will check the type of particle 0 (the first particle drawn). To make the first method work, you may have to go back to the old API with tpt.get_property("type",x,y) until a fix for sim.partID is released.
Second, in sim.neighbours(). sim.neighbours is completely broken, and is looking in completely the wrong place for particles: basically partx+fx, partx+fy. There isn't really any chance of getting this working until sim.neighbours is fixed.
This seems to work:
local function salt_Update(index, partx, party, surround_space, nt)
if nt > 0 then
for fx = -1, 1, 1 do
for fy = -1, 1, 1 do
if tpt.get_property('type',partx+fx,party+fy) == elements.DEFAULT_PT_GOLD then
sim.partChangeType(index, elements.DEFAULT_PT_CNCT)
end
end
end
end
end
elements.property(elements.DEFAULT_PT_SALT, "Update", salt_Update)
Edit: actually, one alternative in the first method might be sim.pmap, which does almost exactly the same thing as sim.partID but with the important difference that it works. It returns nil if no particle exists in that location.
local i = sim.pmap(partx + fx, party + fy)
if i~=nil and sim.partProperty(i, 'type') == elements.DEFAULT_PT_GOLD then
sim.partCreate(x, y, type) does weird things too. Instead of creating the particle where it's told, it erases particles far away.
Script tested:
Screen showing result:
tpt.create() works as expected, though.