Return to “Scripting & Modding”


I got to thinking about this when reading a completely different thread and train of thought.
Spoiler:      SHOW
I was reading about Wormholes and Jumpdrives viewtopic.php?f=5&t=2799&start=285

Which led to a similar post on FTL Drives
This last page is the source of query for this topic.
Despite my best efforts – it seems I’ve written code-poison. I can’t figure out why the algorithm is failing – it constantly gets locked into picking the same two stars in a route, despite being told to ignore any star it’s previously picked.
The source and context of the above quote is given in the spoiler, but this is specifically an LTSL query.

Thank you.

With that out of the way, I wanted to raise the question on how (global) variables are handled across multiple mods.
(where one mod uses a function from another script, which in turn has used that function from another script.)
Our wonderful Josh has shown us the light on how a function can be programmed within LTSL and re-used ( :thumbup: ).

However, in the specific instance where multiple mods/script files have been implemented with LTSL, how can we avoid the instances of "code-poison" where we know the script we programmed works fine (ie. in vanilla LT), but doesn't work with a specific set of mods?

I know in DOS, I merely turn off {@Echo off}, and place a couple of {pause} statements to debug the code.

To all programmers (Josh included :D), what options/opinions do you all have on this?

Note1: I am of the understanding in this example that we are dealing with over a dozen script files that each have created their own reusable code, and I can only surmise that the code might look like this:

Code: Select all

  <calls function from script8>

  <function from script8>
    <calls function from script10>

    <function from script10>
      <calls function from script11>

      <function from script11>
        <calls function from script3>

P.S. I have been known to have improperly elucidated (lovely word, ty Josh) this idea in previous posts.. so please ask away if you are unsure and I will hopefully direct us both towards enlightenment.

P.P.S. I think this falls under code obfuscation, where we cannot see were code is being called by a different script (otherwise it would be a simple case of calling "script3" yada yada).
The idea is that we cannot see why our function in LTSL fails, or keeps resolving the same results, even though we code it differently on each iteration.

In Josh We Trust

Re: Code-Poison

To further expand my first post (and help people understand where I am coming from), I shall quote the master himself:

from viewtopic.php?f=28&t=3306#p58906

JoshParnell wrote: Parameters are passed by (non-const) reference. This makes LTSL powerful, dangerous, and simple all at the same time :D


So the end result is that yes, functions can modify the values of their parameters in LTSL.
If that value happens to be an L-value (in other words, it was passed via a variable or member of a variable), then the value will actually be modified.
If the value is not an L-value, the assigment will have no lasting effect outside of the function (contrast this to c++, which (for reasons that are either arbitrary or not understood by myself) restricts pass-by-nonconst-reference to L-values).
and viewtopic.php?f=12&t=3687#p68868
JoshParnell wrote: the first LT mod was born
he can override any of the numerous pieces of the game that live as external resources
He can override specific scripts

The mechanism behind modding is fairly simple: instead of loading resources directly by file path, the LT engine now creates a 'map' of resources that takes into account mods. It first populates the map with all of the default resources, but then loads all mods in the 'mod' directory, which may add new resources to the map or override the paths of existing ones (e.g., replacing the default LT resources with new, modded ones).

In Josh We Trust

Re: Code-Poison

Let me try paraphrasing. If I get this wrong, please correct me.

Imagine a function called TheFunction. Because of mods, there are two versions of TheFunction: Josh's default Version A, and another modder's Version X. When LT is loaded, Version X overrides Josh's default Version A. So when my code calls TheFunction, it's actually the modder's Version X that gets executed, not Josh's Version A.

Unfortunately there's some visible error that's apparently related to this function. My calling code seems to be correct, and Josh's version of TheFunction seems to be correct. But I can't find the source of the error because I have no way to see that when my code calls TheFunction, I'm actually getting the buggy Version X from some mod, rather than the pristine Version A from Josh's default code.

Is this an accurate depiction of the possible debugging problem you have in mind?

Re: Code-Poison

A register which contains all changes to "global" functions would be nice.

A listing on how that changes tickle through the code of other mods would be the nonplusultra for this, but us unfeasible, as the interpreter would likely need tons of time to analyse the code.
If it would be possible at all without human intervention.
(Mod A has changed function A, mod B uses function A and the change affects function B etc)

Re: Code-Poison

Would this option be a solution:

Each script runs in their own namespace, and is only allowed to hook into/copy LTSL functions. The LTSL engine registers this, and executes the script's function when an action for this script is needed.
For instance: you create a script that changes how ships handle incoming missiles. When this situation happens, LTSL will use all functions that hooked into this event.

Namespaces (at least how I use them in TCL) are fun, because they keep their variables from messing with other scripts, and other scripts can be made to expand on the namespace. Person X could use person Y's script and extend it with their own functionality.

An obvious problem here is when multiple scripts are hooked into the same event, some scripts might override another's behaviour. My view on this is that modders will need to compartmentalize their scripts, and take care of loading order.
Sadly, there's no way of knowing if two scripts using the same event will mess with each other (though they're bound to somehow). Perhaps one script that changes the response to missiles makes the pilot manoeuvre more effectively, while another might also have added special anti-missile weaponry and is trying to optimize the response of the pilot to use these weapons.
It's unclear how these two would interact. Perhaps they work well together, perhaps not.

In the end, I'm proposing a debug screen, where the player is allowed to link hooks to certain (modded) actions. This screen contains a list of all events LTSL can use, and displays how many functions are hooked into these events. The player would be able to then unlink hooks that are interfering with his particular mod combination. This is where the compartmentalization comes in, unless speaking about total conversions of course.

Another example:
Two scripts change the way the universe is layed out, one also changes sector layout (mod "A"). The player could unhook mod A from the debug screen, which will cause mod B to do the universe generation and mod A to do the sector layout. Because of the way the mod is written, mod A will still do its job, because it doesn't rely on its own universe generation.
Beware of he who would deny you access to information, for in his heart he dreams himself your master.

Re: Code-Poison

Flatfingers wrote:Will it be possible to visually inspect the LTSL code using a nodal editor?
That probably wouldn't even be that hard to mod. :D

I'm not sure how you see a nodal editor though. Would it have to have links from a function to all functions that call it?
Beware of he who would deny you access to information, for in his heart he dreams himself your master.

Re: Code-Poison

Katorone wrote: I'm not sure how you see a nodal editor though. Would it have to have links from a function to all functions that call it?
i'd do it on a per-file basis, and the called functions are the connections.

so per function that gets called from another file you have one small line going from the file where the function is defined to the file from where it was called from

Re: Code-Poison

Cornflakes_91 wrote:
theStormWeaver wrote:Returning a stack trace with source files on error would be the ideal solution.
That would require that the engine actually recognises it as an error.

But how should the engine know that better_planets shall override the planet code from better_universe?
Maybe it doesn't. If properties of a given object are modified by multiple mods the program should flag the overlap and report it to the user. The report would include the names of the mods that are in conflict and describe what property is causing the report.

Online Now

Users browsing this forum: No registered users and 2 guests