Update von Konstruktionen - SimpleProposal

Willkommen in der Transport Fever Community

Welcome to the fan community of Transport Fever and Train Fever, the economic simulators of Urban Games. The community is free for you to share and inform yourself about the game. We cultivate a friendly and objective interaction with each other and our team will be happy to answer any questions you may have.

 

Registration and use is of course free for you.

 

We wish you a lot of fun and hope for active participation.

The Team of the Transport-Fever Community

  • Meine Bemühungen, Objekte in einer Map global auszutauschen/zu verändern, wachsen und gedeihen. Bei Straßen und Schienen klappt's schon mal, jetzt bin ich bei Konstruktionen, und da hakt es noch. Für die Funktion SimpleProposal in Bezug auf Objekte habe ich keine Beispiele gefunden, womöglich hat noch nie jemand damit gearbeitet. Im Wiki steht im schönsten Schweizerdeutsch ^^ (oder ist es Fachchinesisch?):

    Und jetzt frage ich mich, was ich machen muss, um innerhalb eines Game Scripts (also nicht im Spiel über die normale Dialogeingabe) Konstruktionen zu ersetzen/upzudaten? proposal.old2new ist mir noch ein Rätsel. Dort werden offenbar zwei Zahlen in einer Tabelle erwartet, und ich hätte getippt, eine davon ist die EntityID der zu ersetzenden Konstruktion, und die andere -1, sofern es nur eine einzige neue Konstruktion gibt. Analog zum Ersetzen von Edges. Klappt aber scheinbar nicht. Oder muss da vielleicht gar nicht die EntityID, sondern die ID der Konstruktion selbst rein? Auch vergeblich versucht. :( Ich kann mir auch versuchsweise eine Tabelle ConstructionEntity mit passenden Parametern basteln, aber wie kriege ich die dann mit der neuen ID verknüpft? Bei Streets und Tracks gibt es api.type.SegmentAndEntity.new(), aber etwas Vergleichbares für Konstruktionen gibt es scheinbar nicht. ConstructionsToRemove klappt schon mal perfekt mit der aktuellen EntityID, aber was bei ConstructionsToAdd rein muss, ist mir völlig unklar. Zahlenwerte wurden jedenfalls abgelehnt, -1 geht nicht, auch Tabellen mag es nicht, gefragt ist nach Userdata, aber welche, und wie setze ich einen Zeiger darauf? Brauche ich überhaupt Add/Remove für die ganze Aktion? Fragen über Fragen. :rolleyes:


    Versteht jemand die Anleitung? Irgendjemand ne Idee? :/:?::?::?::?:

  • Hab mich ja bei Track/Street Info schon damit beschäftigen müssen. Wobei lesen natürlich einfacher ist als schreiben.


    Ich glaube aber es ist sinnvoll, sich die proposals vom Spiel anzuschauen. Dazu kann ich auf jeden Fall die CommonAPI mit dem Event Inspector empfehlen. Dann muss man sich nicht die stdout mit debugPrint vollschreiben ;)


    Wenn es um den Datentyp geht, kriegt man den Luatyp natürlich mit type(...)

    Bei userdata sind es dann api types und den genauen TPF Type findet man über getmetatable raus. Das sieht man aber auch mit commonapi.dmp und im Inspector.

  • So wie ich die API Doku gelesen habe, müssen alle neuen Edges eindeutige Ids im Negativen Vorzeichen haben, überall -1 zu nehmen wird wohl nicht gehen.


    old2new würde sagen, = { { alteEntityid, constructionsToAddIndex }}

    constructionsToAddIndex kann ggf bei 0 anfangen, weil die C API das so will...


    PS: Schön das ich anderen Moddern die Arbeit erleichtern kann, es wäre nett wenn das öfter Erwähnung findet, dann kann ich auch besser Prioritäten bei der Entwicklung setzen. :)


    Ich habe auf meiner Todoliste ne Funktion für die CommonAPI2 um kurze Schienenstücke ohne Elektrifizierung zu finden. Aber dann kommt UG mit ner neuen Beta um die Ecke und dann hab ich erst mal wieder Zeit zum reparieren verbraten...

  • Quote

    So wie ich die API Doku gelesen habe, müssen alle neuen Edges eindeutige Ids im Negativen Vorzeichen haben, überall -1 zu nehmen wird wohl nicht gehen.

    Ich schrieb ja auch, dass es in meinem Testfall nur eine Konstruktion gibt. Das dürfte analog zum Straßen-Ersetzen-Beispiel (im Wiki) funktionieren. Der Rest aber leider nicht.

    Quote

    old2new würde sagen, = { { alteEntityid, constructionsToAddIndex }}

    Das hieße, da käme irgendein beliebiger ganzzahliger positiver Wert rein, der dann auch wieder bei constructionsToAdd auftauchen müsste. Ich fürchte nur, dann sagt mir die Fehlermeldung wieder, sie bräuchte "Userdata" (was immer das auch ist) und keine Nummer. Und wo käme dann der negative Wert rein, der mit Sicherheit auch irgendwo stehen muss? Bei Straßen gibt es noch einen Key in der entsprechenden Tabelle dafür, aber bei Konstruktionen eben nicht ... :/

    Quote

    PS: Schön das ich anderen Moddern die Arbeit erleichtern kann, es wäre nett wenn das öfter Erwähnung findet, dann kann ich auch besser Prioritäten bei der Entwicklung setzen. :)

    Ich persönlich finde, es bringt letztendlich alle weiter, wenn sich die Modder angesichts der eher dürftigen offiziellen Doku gegenseitig helfen, da gibt es für mich auch kein Konkurrenzdenken. Ich will es vermeiden, die Leute von UG mit Anfragen zu nerven, weiß auch nicht, ob sie antworten. Ja, und deswegen ist deine Arbeit und deine Unterstützung auf jeden Fall zu würdigen [Bauchpinsel on :):):):):)]

  • Ich glaube aber es ist sinnvoll, sich die proposals vom Spiel anzuschauen. Dazu kann ich auf jeden Fall die CommonAPI mit dem Event Inspector empfehlen. Dann muss man sich nicht die stdout mit debugPrint vollschreiben ;)

    Das Problem dürfte sein, dass es momentan keine CommonAPI gibt, und ich auch nicht weiß, ob es noch mit einer alten ginge (die ich auch nicht mehr habe). Oder geht das auch mit der Dummy-Version? Für commonapi.dmp dürfte dasselbe gelten.


    Den Rest schau ich mir mal in Ruhe an.

  • Links zur aktuellen Version mit Beta funktionierend (bis UG heute Abend wieder ne neue Beta herausbringt )

    CommonAPI2 - Neue Versionen und wichtige Informationen


    Der Event Inspector und commonapi.dmp funktionieren auch ohne nativen dll/so Teil.

    Es muss commonapi im Savegame als Mod geladen sein, dann gibt es unten einen API Knopf mit neuen Menü.

  • At least you
    can use game.interface.upgradeConstruction and game.interface.bulldoze which comes from tpf1 (and documented in tpf1
    wiki)
    For a removal example of Simple Proposal I did one in track design pattern mod. For modifying or creating, I think it's more or less the same to edges, you just create a similar proposal like what you see in the guievent

  • Nice to hear of you ;). If one could know the solution the one would be you because you have done so many similar things. So I have already cribbed from your source codes ;), and I have found out how to manage street and track poposals (I worked on it very long, because UG conceals that the type for tracks is 1 and not 0 8o), but construction proposals seem to be a different thing. No modder did use this before, not even you. ;) Anyway, I succeeded in removing a construction. This is very simple, you only have to insert the Entity ID and that's it! But I was not lucky with the "Add" proposal. I tried things like below, I think proposal.old2new could be right, because there is no error message, but I'm not sure. In proposal.constructionsToAdd there is absolutely a big error! I don't know how to associate the table with the entity ID. The example below will not work, newConstr is rejected. The function wants userdata, but I still don't know how to associate. :(


    By the way, I only want to update a single construction with each step, so I used -1. This should work as it does for streets and tracks. I also tried the constructionType ID instead of -1 or a construction entity, but all trials didn't work. :(

  • Did some attempt and I succed to remove a station then bring it back via api.


    There are some key things:


    I retrived the old params by:

    Code
    1. params = game.interface.getEntity(id).params

    then create the construction proposal by

    Code
    1. po = api.type.SimpleProposal.ConstructionEntity.new()


    I need also copy the old tranfs by

    Code
    1. co = api.engine.getComponent(id, api.type.ComponentType.CONSTRUCTION)
    2. for i = 1, 16 do
    3. po.transf[i] = co.transf[i]
    4. end

    then create a simple proposal and make the cmd of it then send it


    However, it seems the command is send directly to the updateFn of the construction so you need to change the module table to change things such as number of tracks etc..


    I think the way above is too complicated comparing to game.interface, which you can do thing in the fly, the only drawback is you can call the game.interface functions only from engine loop not gui loop.

  • At last I have contacted UG and received an answer. This here is not the original code they gave me, but my own adaption - and - big surprise - it works! It should not be a secret, it is useful for all modders, so I publish it here:

    There were some mistakes in my own code. But the decisive one was proposal.old2new. The proposal entities start at 0! Who could know this?! And also the syntax is different from what UG has written in the wiki. And I had to guess where to get the params from: There are several possibilities, but some of them are wrong. I think the official documentation is a little poor. :|


    But just having finished this, I face a new problem: If you have got constructions with edges and nodes, the nodes will be cut. There is no more connection with the neighboring edges. This happens only with constructions with rigid edges, not with normal edges. So I'm looking for the cause, but I have no idea. Remove and insert the edges without their constructions is no good idea - it will crash the mod.


    Now I am searching for a structure which describes the connections between neighboring edges and a mechanism to reconnect them. Any idea?


    If you ask me why I need so difficult things: My project is to replace objects by themselves to update e.g. track styles. If you install a new track/street or track/street modifying mod, you normally don't have any chance to update already laid tracks/streets. So you have to replace them manually. :( I want to create a mod which does this work for me. ;) But you also can imagine other applications. You could create tools to cut - copy - paste streets, tracks end even whole cities - or repair maps which you have created with no more available mods.

  • I think the decisive one is api.type.SimpleProposal.ConstructionEntity.new(), since in last week replay you showed you constructed a construction proposal in lua, and the transf required in fact is a POD array, you would never get it work. Also the way you assign the playerId was not correct, but it should not be blocking since that just blocks you from editing a construction


    for nodes thing, if in construction node is marked as snapNodes it should catch the neighboring edges (at least it works for game.interface.buildConstruction and game.interface.upgradeConstruction), if you try to modify edges in a construction via api, it will crash (sometimes when your cursors points at it). Normally you should not touche edges in a construction


    The notion of connection is just node, if two edges share the same node they are connected if not they are not connected.


    And I feel disapointed that you didn't do any comment on my last replay, since I took two hours last weekend to find you a working solution and summerize the essential part.


    Doesn't track/street upgrading tool exist in vanilla game? of course you can replace street/tracks without a mod, why do you want to double the function? or you just don't know that exists already?

    This guy is too lazy to create a signature. 8o

    Edited 2 times, last by Enzojz ().

  • Ok, now I will answer immediately. ;) Excuse me, that I did not answer, but I did not want to admit that I did not succeed with your suggestion and did not want to ask you too much. I was a little frustrated after I had tried out already so many things. And I did not know that you had invested so much time in helping me. Once more - I'm very sorry for this! :rolleyes: Anyhow, we all have got a solution and learned a lot :), although it is still not perfect. But I hope it could be useful for you, too. Still I do not know why I have to use proposal.old2new at all. It also works without this. :/ I tried out other values than 0, but it always crashed.


    I also noticed that changing edges in a construction is no good idea. So I think changing the construction as a whole is the royal road to handle it - with the disadvantage of destroying the connections. I found out that this happens because the edges get completely new IDs - in opposite to free tracks updated as single edges. I already had the idea that two nodes with the same ID could be connected so I have to thank you for saving a little time instead of a lot of trials.


    Track/street upgrading does exist in vanilla game, but not completely. :( For example, I wrote a mod for lowering the pavements of all streets using a modifier. At a glimpse it seemed to look very good, but if I looked once more I saw all pedestrians and bus shelters hanging in the air, because the engine does only notice optical changes, but not functional. So you would have to update every edge manually with the magic wand or so (I hope this is what you mean). I wrote another mod to reduce the too high track cornering speeds. For new tracks it works very good. But the old tracks keep their old speed coeffs.


    I did not find any better solution than removing every edge and replacing it by itself. Only new tracks are updated correctly! :( If I should have found out a better way, please tell me how.

  • If I had game.interface as an alternative I would be happy. But I tested it once more. I am a simple thinker :), so I thought that this would perhaps work:

    Code
    1. params = game.interface.getEntity(constrId).params
    2. game.interface.upgradeConstruction(constrId, constr.fileName, params)

    Ok, I didn't do this transf thing, but if the params are the same I think it has not to be done ...


    I got this nice short error message ;):

    I do not know what it means but I think I have inserted the wrong params. :D


    But this is what drives me crazy - and this is the reason why I have almost given up this way. :(


    So I will go on with the other method and try to find out if and how I could reconnect the nodes. The question is if I am allowed to write directly into some param structures - and which. I think not ... my last chance is to find some examples elsewhere. Otherwise the changing of the constructions is not so important for the things I want to do.


    [OT] A very simple way to understand my project is to replace the vanilla track types by such with reduced top speed by a mod or a modifier. Now load an old map with already laid tracks. If you press [NUM]-[4] you will see that the top speed has not changed. :(. But if you lay new tracks, you get the right speed for them. So you would have to replace every single laid track by itself. For certain things (like streets with no developement) even the magic wand will not work! :( And this is exactly what I want to have automatized by a mod - but I cannot yet do it for stations, switch modules and so on ... I would be glad if I did not have to write such a difficult mod if the game would at least offer something like the F5-"update"-key in browsers or windows. ;):D If someone could tell me there is a hidden key I would be very happy because then I could program other much more exciting stuff. :S


    But my work won't be useless anyway. It's also a kind of "basic research" ;).

  • Recently, I found this in Lollus Town Tuning Mod:

    Code
    1. local oldConstruction = game.interface.getEntity(oldConstructionId)
    2. local newId = game.interface.upgradeConstruction(
    3. oldConstruction.id,
    4. oldConstruction.fileName,
    5. -- leadingStation.params -- NO!
    6. arrayUtils.cloneOmittingFields(oldConstruction.params, {'seed'})
    7. )

    Maybe seed must be omitted.

    Clone shouldn't be needed, I would just try params.seed = nil

  • So?

    Code
    1. local oldConstruction = game.interface.getEntity(constrId)
    2. oldConstruction.params.seed = nil
    3. local newId = game.interface.upgradeConstruction(oldConstruction.id, constr.fileName, oldConstruction.params)

    Doesn't work. :(


    I got the error message "attempt to call field 'upgradeConstruction' (a nil value)"


    Now I have inserted the complete code. Doesn't work either. There is always this error message "Assertion `pr.second' failed". I think this routine doesn't like constructions with edges. :(

  • You need to remove seed from the params, for upgradeContrsuction and buildConstruction, i've been doing it since tpf1 and it works always like this

    I don't know if params.seed = nil works sometimes you may get read only variables (not sure) so better to check it before use


    the following code comes from my underground station:


    local pure = function(pa)
        local params = {}
        for key, value in pairs(pa) do
            if (key ~= "seed") then
                params[key] = value
            end
        end
        return params
    end

    local script = {
        handleEvent = function(src, id, name, param)
            if (id == "__musEvent__") then
                if (name == "new") then
                    local id = param.id
                    local e = game.interface.getEntity(id)
                    game.interface.upgradeConstruction(
                        id,
                        "station/rail/mus.con",
                        pure(e.params)
    )
                end
            end
        end,
        guiHandleEvent = function(id, name, param)
            if name == "builder.apply" then
                local toAdd = param.proposal.toAdd
                if toAdd and #toAdd > 0 then
                    for i = 1, #toAdd do
                        local con = toAdd[i]
                        if (con.fileName == [[station/rail/mus_cargo.con]]) then
                            if(con.params.isFinalized == 0) then
                                game.interface.sendScriptEvent("__musEvent__", "new", {id = param.result[1]})
                                game.interface.sendScriptEvent("__underpassEvent__", "new", {id = param.result[1], isStation = true})
                            end
                        end
                    end
                end
            end
        end
    }

    function data()
        return script
    end


    Quote


    So I will go on with the other method and try to find out if and how I could reconnect the nodes. The question is if I am allowed to write directly into some param structures - and which. I think not ... my last chance is to find some examples elsewhere. Otherwise the changing of the constructions is not so important for the things I want to do.

    You may keep the nodes from construction side and rebuild edges from free side and using the nodes from construction side so they should get connected.


    Quote


    [OT] A very simple way to understand my project is to replace the vanilla track types by such with reduced top speed by a mod or a modifier. Now load an old map with already laid tracks. If you press [NUM]-[4] you will see that the top speed has not changed. :(. But if you lay new tracks, you get the right speed for them. So you would have to replace every single laid track by itself. For certain things (like streets with no developement) even the magic wand will not work! :( And this is exactly what I want to have automatized by a mod - but I cannot yet do it for stations, switch modules and so on ... I would be glad if I did not have to write such a difficult mod if the game would at least offer something like the F5-"update"-key in browsers or windows. ;):D If someone could tell me there is a hidden key I would be very happy because then I could program other much more exciting stuff. :S

    More likely a bug of the game, have you reported to UG first?

    This guy is too lazy to create a signature. 8o

    Edited 3 times, last by Enzojz ().

  • Dont know in which thread you are, but upgradeConstruction is only available in Script Thread.


    If seed is in params, I get pr.second' failed

    If not, upgradeConstruction works for me, just tried it with an industry.


    Now something with edges?

    Road Depot? Has no params


    What about "asset/wk_switch_kit_de_at.con" ;)

    Code
    1. p=game.interface.getEntity(5261).params
    2. p.seed=irgendwasmitnil
    3. p.wkskTrackDistFactor=2
    4. game.interface.upgradeConstruction(5261,"asset/wk_switch_kit_de_at.con",p)


    Now, it may be more complicated with connection nodes...