Jump to content

[Lua] Import Script Into Multiple Other Scripts


Phodex Games
 Share

Recommended Posts

Hi,

 

I have a small problem. I am currently working on a spellsystem. For this I created a "Spell Effects Library.lua" file, which contains any possible effect that a spell could cast to easily access the effects. I have two types of spells. Spells on target and on self.

 

The "on self" spells get casted in the player script:

import "Scripts/Spell Effects Library.lua"
.
.
.
if KeyHit then self:CastSpell(something) end

 

The script for the Library looks like this:

function Script:CastSpell(something)
.
.
.
end

 

So far so good. For the "on target" kind of spells the shooten projectile casts the effect on hit. Those code is just for visualization:

 

import "Scripts/Spell Effects Library.lua"
.
.
.
if hit then self:CastSpell(something) end

 

So If I shoot a projectile now and it hits its target it says "attempt to call method 'CastEffect' (a nil value)". BUT if I delete the import line at the player script it works just fine. It does not seem to be possible to import the same script into two other scripts? So could you help me please? How to manage this?

Link to comment
Share on other sites

Yes, it's not possible that way. I had the same question here: http://www.leadwerks.com/werkspace/topic/10616-importing-one-script-into-two-different-scripts/

Take a look how default AnimationManager script functions. You can do the same thing.

 

Or maybe just use global table with all your effects, this will be simpler actually. And you won't need to import any scripts anywhere.

Link to comment
Share on other sites

There really are 2 kinds of scripts. There are Leadwerks scripts and user scripts. Leadwerks scripts are the ones that have: function Script: in them. These are the scripts you attach to entities on the editor or in code at runtime via Entity:SetScript. The user scripts is something like Gene mentions in the AnimationManager script. It's like this because Josh removed the ability to attach multiple Leadwerks scripts to an entity (it's a sensitive subject for some). So now if you want to share some functionality between multiple Leadwerks scripts you either copy/paste the code (gross) or you create a "class" script like AnimationManager and put your code in there. Then in your Leadwerks script you import it, create and instance of the class, and call functions on it. There are other options but this is the basics of object oriented programming which Leadwerks sort of uses in various places so it's easier to recommend that way because you have examples of it in Leadwerks.

 

Would just be a lot easier if we could attach multiple Leadwerks scripts to entities wouldn't it

 

There really are 2 kinds of scripts. There are Leadwerks scripts and user scripts. Leadwerks scripts are the ones that have: function Script: in them. These are the scripts you attach to entities on the editor or in code at runtime via Entity:SetScript. The user scripts is something like Gene mentions in the AnimationManager script. It's like this because Josh removed the ability to attach multiple Leadwerks scripts to an entity (it's a sensitive subject for some). So now if you want to share some functionality between multiple Leadwerks scripts you either copy/paste the code (gross) or you create a "class" script like AnimationManager and put your code in there. Then in your Leadwerks script you import it, create and instance of the class, and call functions on it. There are other options but this is the basics of object oriented programming which Leadwerks sort of uses in various places so it's easier to recommend that way because you have examples of it in Leadwerks.

 

Would just be a lot easier if we could attach multiple Leadwerks scripts to entities wouldn't it

Link to comment
Share on other sites

The reason we use one script per entity is so that there is always a single unambiguous function or member for the value you are looking for. During development I tried both approaches, and found that when using multiple scripts you basically end up breaking off every script variable that multiple scripts access into its own script. Then you need a unique prefix to identify that script, so instead of just calling script.health you have to call script.HealthManager.health, or some such thing.

 

When we have a 1:1 entity/script relationship it is easy to check if a function exists and call it if it does. Many scripts tend to have similar functions like TakeDamage() which results in scripts magically working together, even when they weren't developed to work in unison.

 

With multiple scripts you either have an extra namespace to guess to get the right function, so scripts tend to stop spontaneously working together as they did before.. You can also have problems with multiple scripts containing the same function or member, and not knowing which should be considered the "real" value.

 

After having worked with both of these approaches during development of Leadwerks 3.0 I am confident the single-script approach was the right way to go.

 

This design decision will not be changed.

 

For your question above, I believe you can do this:

Import "CastSpell.lua"

function Script:Start()
self.CastSpell = CastSpell
end

function Script:Update()
self:CastSpell()--passes self in as first argument
end

 

CastSpell.lua:

function CastSpell(script)
script.DoSomething()--"script" is like "self"
end

 

Lua is very flexible and there are probably several ways of handling this:

https://www.lua.org/pil/16.html

  • Upvote 2

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

In fact, this actually works:

--Create a table and add a value
local mytable = {}
mytable.value = "Hello"

--Create a global table function
local dummytable = {}

function dummytable:SomeFunction()
print(self.value)
end

--Assign the function from one table to another
mytable.SomeFunction = dummytable.SomeFunction

--Call the function
mytable:SomeFunction()

 

Even better. This uses the secret global table (standard Lua thing) in which all variables are stored so you don't even need the dummy table:

--Create a table and add a value
local mytable = {}
mytable.value = "Hello"

--Create a global table function
function _G:SomeFunction()
print(self.value)
end

--Assign the function from one table to another
mytable.SomeFunction = _G.SomeFunction

--Call the function
mytable:SomeFunction()

 

I think the above is a good solution to the situations where you want some amount of code reuse across scripts.

  • Upvote 2

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

That was really informative, thank you for the very detailed description smile.png. I always love to learn new stuff to sweeten and shorten my code. And I understand the thing about the two scripts per entity. I know that as a user of a software you often don't think as far as the developers did and for me this feature isnt that kind of a big deal. There are other and also very cool ways to get the same effect. Can't wait to try out the newly learnt method ^^

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...