How to add new electrolytic reactions?

  • Faerindel
    3rd Mar 2014 Member 0 Permalink

     

    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

    Edited once by Faerindel. Last: 3rd Mar 2014
  • boxmein
    3rd Mar 2014 Former Staff 0 Permalink
    @Faerindel (View Post)
    Honestly if you intend on being a longer-time modder, the extra effort to set up
    MinGW is fairly nothing compared to the benefits you'll get. Only do this if you intend on programming a lot though, lol. You can do this stuff anyway via Lua.

    And, to answer your questions, yes you can definitely add new reactions (even electrolytic ones!) via Lua. Get a head start here. It's fairly simple, just create a function and call the
    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)


    ALSO GUYS 5000TH POST
    Edited 2 times by boxmein. Last: 3rd Mar 2014
  • Faerindel
    4th Mar 2014 Member 0 Permalink

    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.

  • jacksonmj
    4th Mar 2014 Developer 0 Permalink

    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

    Edited 3 times by jacksonmj. Last: 4th Mar 2014
  • Faerindel
    5th Mar 2014 Member 0 Permalink

    Not one but two! I already suspected that neighbors() was buggy, but partID()'s description was simple enough to trust it. :P

     

    I'll use the tpt.get_property() way, it seems to run a bit faster than pmap.

  • Faerindel
    6th Mar 2014 Member 0 Permalink

    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:

    http://pastebin.com/esqQxPGs

     

    Screen showing result:

    http://imgur.com/JRo0CUt

     

    tpt.create() works as expected, though.

     

    Edited once by Faerindel. Last: 6th Mar 2014
  • jacksonmj
    7th Mar 2014 Developer 0 Permalink

    Description of sim.partCreate has now been added to the wiki.

     

    sim.partCreate(-1, x, y, type)

  • Faerindel
    7th Mar 2014 Member 0 Permalink

    So I was using it wrongly, no wonder it didn't work. I'll try it later.

     

    I'll assume that if index >= 0, x and y parameters are ignored, right?

  • jacob1
    7th Mar 2014 Developer 0 Permalink
    @Faerindel (View Post)
    That's not something I ever considered, I always just make sure to pass in the x and y of the old particle when using that. Looking at the source, I guess you have to, if not it will move the particle to where the new x and y are.
  • Faerindel
    8th Mar 2014 Member 0 Permalink

    That may be worth putting it in the wiki.

     

    Tried with index -1, it works. Couldn't be bothered to do a decent test, so I don't know which API is faster.