Jump to content

Importing one script into two different scripts


Genebris
 Share

Recommended Posts

I have a script with a function that prints text to the console:

function Script:TestFunction()
System:Print("TEST PRINT")
end

When I import this script into player script and call this function in Script:Start everything works fine.

import "Scripts/Player/TestScript.lua"
...
function Script:Start()
self:TestFunction()
...

But when I also import this script into MonsterAI script calling this function from player script gives me error like this function doesn't exist there (attemt to call method 'TestFunction' (a nil value)).

 

I wanted my RPG related functions to be imported into player script and NPC script and be able to access their variables through these RPG functions. For example:

function Script:IncreaseSkill(skill, progress)
self.skills[skill]=self.skills[skill]+progress
if self.skills[skill]>100 then
self.skills[skill]=100
end
end

I noticed that default scripts like ReleaseTableObjects.lua use global functions and only variables passed to these functions. Do I have to do the same?

function IncreaseSkill(character, skill, progress)
character.skills[skill]=character.skills[skill]+progress
if character.skills[skill]>100 then
character.skills[skill]=100
end
end

Link to comment
Share on other sites

You can simulate classes. Look at the Animation script included in all projects to see how you do this. This gives you a more C++ feel and allows you to make "classes" for your functionality. It's a nice clean way to handle stuff like this.

 

If it's not too much trouble, could you explain this a little more? I've looked at both AnimationManager and SimpleAnimation scripts, and don't get which one you are referring to. The contents of AnimationManager are definitely beyond my current understanding. This would certainly prove useful for a variety of things, so I'd like to gain an understanding of this.

Link to comment
Share on other sites

I don't really understand it well myself, but here is my RPG script that I imported into player script and monsterAI script:

 

RPG={}
function RPG:Create(entity)
if entity==nil then Debug:Error("Entity cannot be nil.") end
local rpg = {}
rpg.entity = entity
local k,v
for k,v in pairs(RPG) do
rpg[k] = v
end
return rpg
end
function RPG:IncreaseSkill(skill, progress, calculateProgress)
local script=self.entity.script --self.entity is an entity I pass to the create function
script.skills[skill]=script.skills[skill]+progress
--cleared this function from unnecessary stuff
end

 

When this script is imported, I call

self.RPG=RPG:Create(self.entity)

in the Script:Start in the player script. Now I can use IncreaseSkill like this:

self.RPG:IncreaseSkill("Swords", 0.03)

And I can do the same in monsterAI script and IncreaseSkill function will increase monster's skill variable.

  • Upvote 1
Link to comment
Share on other sites

If it's not too much trouble, could you explain this a little more? I've looked at both AnimationManager and SimpleAnimation scripts, and don't get which one you are referring to. The contents of AnimationManager are definitely beyond my current understanding. This would certainly prove useful for a variety of things, so I'd like to gain an understanding of this.

 

Sure. The idea is to take the structure of AnimationManager and not really the code in it. The idea is to make a table that will act as your class "template". For example:

 

NPC = {}

 

This will make a global table although it's really only acting as a class template/blueprint if you will. It will hold default variables and functions that you will copy into a separate instance of another table and then return that table instead so that you can make many instances of an NPC (in this case). You do this with a function and we generally just call it Create() although it can be named anything.

 

function NPC:Create()
end

 

 

Now inside our Create() function we want to make another local table and that's what we return from this function so that when you call it inside your game code you get a new NPC table.

 

function NPC:Create()
  local obj = {}

  return obj
end

 

 

Now this obj table is just a normal table so it's not much use. We want it to represent an NPC since it's inside the NPC:Create() function. To do this we need to assign from variables to it and then copy the NPC functions to this new obj table so it can call the functions as well. To give it variables we just start assigning variables to it (since it's just a table). To get the NPC functions and assign them to this obj table we need to loop over all the functions and assign then to this obj table. In LUA it's important to know that everything is a variable. Even functions. So the below is equal in LUA:

 

Object = {}

-- this is one way to make a function part of a table and makes more sense to us generally
function Object:Update()
end

-- this is another way to make a function be part of a table. notice how it's just a variable named Update but the value is a function
Object.Update = function()
end

So you can see that any function we define for NPC, the function nmam

 

 

 

So you can see that any function we define for NPC, the function name ends up just being another variable of the NPC table. So that means we can just loop over all variables of the NPC table and copy it's name and value (which is a function) to our obj table and then the obj table will be a complete duplicate of the NPC table but it's own instance which means we can make many of these NPC objects in our game and they will be completely separate in terms of memory but share the exact same structure/functions.

 

function NPC:Create(name, type)
  local obj = {}

  -- this is a way to give NPC's values that you passed into the Create function to help make unique type NPC's
  obj.name = name
  obj.type = type

  -- loop over all NPC functions/variables and assign their name and values to our local obj table
  local k,v
  for key,value in pairs(NPC) do
     obj[key]  = value
  end

 return obj
end

-- just because these are defined after Create() doesn't mean anything. these are still functions that are part of the NPC table (remember that they are just variables where the variable name is the function name and the value is the function itself). We would
want all instances of NPC's to have this function so it can be called on it's data
function NPC:Update(window)
end

-- notice how we use self.name which refers to the calling instances name variable. we have to do this because the Draw() function is part of all instances of NPC so in order to work on that instances data it uses self to refer to itself.
function NPC:Draw(context)
  context:DrawText(self.name, 0, 0)
end

 

 

Using this style of coding is really good for things that don't fit the entity script way of doing things in LE. NPC might be a bad example because that fits the entity script way, but things that might make more sense using this style would be: if you didn't want to use the entity script way at all and just wanted to start right in App.lua. I did this for a 2D game I have where I made classes for a FiniteStateMachine and that I add to App:Start() to kick the entire game off, a GUI, inventory perhaps.

 

Sometimes entity scripts can get rather large and you find yourself lumping a lot of code that really isn't related all that much or should be separate so it can be reusable and mixed and matched with different entity scripts. Think if you make a player entity script. Inside the entity script you would have player movement, but the player also would need an inventory. Well the inventory logic is big enough that it warrants to be separated out into it's own class and then inside the player script you create 1 instanced of the inventory object and call it's functions. Now your player script stays nice and clean and you abstracted the inventory code out into it's own script. Imagine you then move onto another game that treats the player script way different (say FPS vs RTS), but the inventory idea is the same. You can just import your inventory class into different player entity scripts and it all works.

 

Hope this helped explain this more. Let me know if you have any more questions.

  • Upvote 3
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...