Jump to content

Entity():invokeFunction(script, args...) is not enough parameters?


Multirez

Recommended Posts

I'm not entirely sure what your question is, as the post title and the actual body of the post are incongruous. I'll attempt to answer both questions.

 

Entity():invokeFunction(script, args...) is not enough parameters?
Correct. Well, at face value, that is. invokeFunction(script, args...) has two arguments that can be passed to it if you first look at it. But the args... argument is in fact a shorthand for saying "zero or more" arguments, so you can pass it any amount of arguments you want, or none at all.

 

invokeFunction("scripts/entity/ShrooblordsScript.lua");

invokeFunction("scripts/entity/ShrooblordsScript.lua", 1); and

invokeFunction("scripts/entity/ShrooblordsScript.lua", "balls", true, Entity())

are all valid function calls.

 

The trick is to figure out how many arguments the script you're invoking actually wants or needs. You'll need to take a look at the function in-code to do this properly. The best is to investigate how it's used in vanilla to see how to best invoke that function.

 

If you're coding something yourself, you of course know what amount of arguments the function expects, so go with that.

 

Often Entity has more than one script with the same name/path.
Does it? Can you give some examples?

 

I've seen function overrides, if that's what you mean. The entity will inherit one library's function, but then also define that same function elsewhere in code, overriding the default provided by the library. Is this what you're hinting at?

 

How to call a function in a second or an another specific entity script?
I'm also not certain what you're asking here; if you know how to identify a specific entity, then you've already got your answer. Just pass that entity's identifier as the Entity() object. For example (PSEUDOCODE; CHECK THE GAME SCRIPTS TO SEE HOW TO PROPERLY DO THIS - IN FACT THE EXAMPLE IS REALLY A LITTLE MESSY ACTUALLY; BUT FOR PROOF-OF-CONCEPT, READ AHEAD):

 

Sector = require("Sector")
Traders = {}

local function getTraders()
    local allTraders = Sector():getEntitiesOfType("ship", "traders")
    table.insert("Traders", allTraders)
    return Traders
end

local function suicide()
    self:destroy()
end

--Somewhere else...
Traders = getTraders()
Traders():invokeFunction(suicide)

 

Even though the above pseudocode is basically crap and useless, I hope it illustrates the point: you collect the entities you want to run your script on somehow (again, not sure what you want to do exactly because you didn't specify), and then invoke the function you want to run on those entities.

 

----

 

Does this answer your questions? If not, please provide more information so we can more properly assist you.

Link to comment
Share on other sites

Well, I'll try to explain the situation less abstractly, sorry for my English

Often Entity has more than one script with the same name/path.

Does it? Can you give some examples?

 

If you install some upgrades on your ship and then try to Entity():getScripts() you can get something like this

...
9  :  data/scripts/systems/hyperspacebooster.lua
10  :  data/scripts/systems/hyperspacebooster.lua
11  :  data/scripts/systems/hyperspacebooster.lua
12  :  data/scripts/systems/batterybooster.lua
13  :  data/scripts/systems/batterybooster.lua
14  :  data/scripts/systems/energybooster.lua

 

How to invoke getSeed function from batterybooster.lua that is number 13 in script list???

    Entity():invokeFunction("data/scripts/systems/energybooster.lua", "getSeed") -- Always return seed for script #12

P.S.

I really thought to delete the script number 12, read the data for the 13th, and then restore the removed, but in this way the player will lose the accumulated energy in the batteries, shields, cargo, trade history and so on...

 

Link to comment
Share on other sites

I see what you mean now.

 

See this part of code in craftorders.lua:

 

local function removeSpecialOrders()

    local entity = Entity()

    for index, name in pairs(entity:getScripts()) do
        if string.match(name, "data/scripts/entity/ai/") then
            entity:removeScript(index)
        end
    end
end

 

As you can see, the script is iterating through all scripts of a certain entity, and removing some of them with a certain name.

 

You could use the same for index, name in pairs(entity:getScripts()) do ... end construction to get all scripts that are match batterybooster.lua, and then perform different operations on each index:

local entity = Entity()

for index, name in pairs(entity:getScripts()) do
    if string.match(name, "data/scripts/systems/energybooster.lua") then
        Entity():invokeFunction(name, "getSeed")
    end
end

 

I didn't test this, so I don't know if this exactly is what you need, but this should get you started, at least.

 

EDIT:

Ah, no I see now. That would still probably only return the getSeed result from the first script and not the next indeces. I'm not sure how to reference a script attached to an entity specifically by its index. It doesn't seem like any of the existing code does that, so I can't copy its example.

Link to comment
Share on other sites

I already broke my head over this issue, the only thing that came to my mind was to add a copy of the first script to the end of the list, and then delete it, replacing with a fictitious dummy component. And so on until I reach the position I need.

Then I can delete script by index, this will make it possible to reduce the number of dummies on the object. The only exception is trading systems, but they can also be put into the cache by calling the secure() function.

In any case, such solution will result in a lot of additions and deletions of scripts only to get the current state.

 

Maybe you have any other ideas?

Link to comment
Share on other sites

I think I have an idea.

We attach an additional script to the entity, that will act as a storage for our system upgrades info.

 

Then we modify our system upgrades. I think that will be no problem for you since you already did this (energybooster.lua doesn't have getSeed function by default).

So, we modify onInstalled function and invoke function of our storage script to 'register' it and pass upgrade info (seed, etc). There might be some issues with keeping the link which module is which, though.

 

In the end, you will invoke function of storage script to get what you need.

 

I'll try it in the next days to see if this will work.

Link to comment
Share on other sites

Thanks rinart73 for the proposed solution.

Initially, I did not want to modify the vanilla scripts in the systems folder to avoid possible incompatibility with other mods that add / modify systems.

But your solution looks like more attractive and it seems that I can do the modification of a basesystem.lua only.

 

EDIT: This does not eliminate the need in the ability to run invokeFunction on the script by its index, similar to Entity():removeScript().

Link to comment
Share on other sites

EDIT: This does not eliminate the need in the ability to run invokeFunction on the script by its index, similar to Entity():removeScript().

 

Your current problem is that invokeFunction addresses the first attached script with certain name.

If done correctly, my way will work a bit differently: instead of invoking upgrades functions, upgrades themselves will invoke function of storage script (which can be only one per entity). And then your script will successfully get info from storage.

Link to comment
Share on other sites

EDIT: This does not eliminate the need in the ability to run invokeFunction on the script by its index, similar to Entity():removeScript().

 

Your current problem is that invokeFunction addresses the first attached script with certain name.

If done correctly, my way will work a bit differently: instead of invoking upgrades functions, upgrades themselves will invoke function of storage script (which can be only one per entity). And then your script will successfully get info from storage.

 

I meant that such a function is necessary for the completeness of the API, and not in this particular example.

Link to comment
Share on other sites

I think I have an idea.

We attach an additional script to the entity, that will act as a storage for our system upgrades info.

(...)

So, we modify onInstalled function and invoke function of our storage script to 'register' it and pass upgrade info (seed, etc). There might be some issues with keeping the link which module is which, though.

 

In the end, you will invoke function of storage script to get what you need.

That is elegant. So you basically register and assign an index to the SMUs through an external script, rather than trying to get at the SMU scripts through another roundabout way. Then you can use that external script to reference them, since the new script knows which index points to which SMU, since that's how we programmed it to behave. Nice.
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...