Spawnable requiring a Spawner

I encountered the following problem:

I have a NPC class simple example:

local npc = {} local npc\_mt = { \_\_index = npc } -- metatable local worldHelper = require("classes.modules.worldhelper") function npc.new(\_name) -- constructor local pc = { name = \_name } return setmetatable( pc, npc\_mt ) end function npc:spawnNPC2() worldHelper.spawn("NPC2") end

And a worldHelper (spawner)

local t = {} local npcClass = require("classes.npc") t.spawnNPC = function(name) npcClass.new(name) end return t 

As this is just a simple example it shows what I wanna do, I want the spawnable to access the worldHelper and spawn a new instance of the spawnable

But I get the following error when i do this: " loop or previous error loading module"

I know that it means it goes in an infinite loop requiring eachother, but is there any other way to achieve this?

I have a temp fix that requires the npc from my scene and puts it in an global var so the worldHelper can also access the npcClass without having to require it, but I dont like that solution

I’m not sure I completely follow what you’re trying to do, but I get the feeling that the functionality to spawn NPCs should remain only in the NPC class.

What is the purpose of having the spawn function in both the NPC class and WorldHelper?

Well thats not exactly what I am trying to do, let me try to explain

worldHelper is the class that can spawn like every Spawnable in the game (so also the NPC I use as an example)
If the NPC reaches a certain location, it does a worldHelper.spawn again so another Spawnable is spawned

But I get the error stated above because the NPC does a require worldHelper and the worldHelper does a require NPC
This is resulting in a “require” loop

So I need a Spawnable (ex: NPC) class and a Spawner (worldHelper) class
The Spawner class should require the Spawnable so he can make a new instance

and the Spawnable class should also require the Spawner so he can do a call to spawn another Spawnable

How should I code this?

Maybe you can create your own custom runtime listener instead.

Assuming you have an initialize function for worldhelper it would look something like this

local WorldHelper = {} function WorldHelper:initialize() self.npcClass = require("classes.npc") self.enemyClass = require("classes.enemy") --just as an example Runtime:addEventListener("spawnListener", self.spawnListener) end function WorldHelper:spawnListener( event ) local classToSpawn = event.target --string that identifies one of the classes above local params = event.params --this could be a table or whatever value self[classToSpawn].new(params) --this makes the call to npcClass.new or enemy.new end return WorldHelper

Later in your NPC class when the npc reaches the location you do

Runtime:dispatchEvent( { name="spawnListener", target="npcClass", params="NPC2" } )

This will allow you to execute code in the worldhelper class without having to require it in the NPC class, so you avoid that circular reference.

Keep in mind that when you create your own Runtime listeners you have to dispose of them manually.

Here’s a Corona tutorial for custom events

I’m running on very little sleep right now but I hope that makes sense!

The solution was easy and your code made it clear to me,

I always did a require in the top of the class, but when I only made the require local scope in the function it did work

For any references when someone encounters this problem later on and sees this topic: the working code.

local t = {} t.spawnSpawnable = function(options) local \_path = fileConstants.IMAGES\_PATH..options.path local \_levelPosX = options.levelPosX local \_levelPosY = options.levelPosY if(options.tileX) then \_levelPosX = convert.tileToPos(options.tileX) end if(options.tileY) then \_levelPosY = convert.tileToPos(options.tileY) end local class = require("classes.spawnables."..options.class) local spawnable = class.new({ name = options.name, path = \_path, file = options.file, layer = options.layer, levelPosX = \_levelPosX, levelPosY = \_levelPosY, extraOptions = options.extraOptions }) return spawnable end return t

I’m not sure I completely follow what you’re trying to do, but I get the feeling that the functionality to spawn NPCs should remain only in the NPC class.

What is the purpose of having the spawn function in both the NPC class and WorldHelper?

Well thats not exactly what I am trying to do, let me try to explain

worldHelper is the class that can spawn like every Spawnable in the game (so also the NPC I use as an example)
If the NPC reaches a certain location, it does a worldHelper.spawn again so another Spawnable is spawned

But I get the error stated above because the NPC does a require worldHelper and the worldHelper does a require NPC
This is resulting in a “require” loop

So I need a Spawnable (ex: NPC) class and a Spawner (worldHelper) class
The Spawner class should require the Spawnable so he can make a new instance

and the Spawnable class should also require the Spawner so he can do a call to spawn another Spawnable

How should I code this?

Maybe you can create your own custom runtime listener instead.

Assuming you have an initialize function for worldhelper it would look something like this

local WorldHelper = {} function WorldHelper:initialize() self.npcClass = require("classes.npc") self.enemyClass = require("classes.enemy") --just as an example Runtime:addEventListener("spawnListener", self.spawnListener) end function WorldHelper:spawnListener( event ) local classToSpawn = event.target --string that identifies one of the classes above local params = event.params --this could be a table or whatever value self[classToSpawn].new(params) --this makes the call to npcClass.new or enemy.new end return WorldHelper

Later in your NPC class when the npc reaches the location you do

Runtime:dispatchEvent( { name="spawnListener", target="npcClass", params="NPC2" } )

This will allow you to execute code in the worldhelper class without having to require it in the NPC class, so you avoid that circular reference.

Keep in mind that when you create your own Runtime listeners you have to dispose of them manually.

Here’s a Corona tutorial for custom events

I’m running on very little sleep right now but I hope that makes sense!

The solution was easy and your code made it clear to me,

I always did a require in the top of the class, but when I only made the require local scope in the function it did work

For any references when someone encounters this problem later on and sees this topic: the working code.

local t = {} t.spawnSpawnable = function(options) local \_path = fileConstants.IMAGES\_PATH..options.path local \_levelPosX = options.levelPosX local \_levelPosY = options.levelPosY if(options.tileX) then \_levelPosX = convert.tileToPos(options.tileX) end if(options.tileY) then \_levelPosY = convert.tileToPos(options.tileY) end local class = require("classes.spawnables."..options.class) local spawnable = class.new({ name = options.name, path = \_path, file = options.file, layer = options.layer, levelPosX = \_levelPosX, levelPosY = \_levelPosY, extraOptions = options.extraOptions }) return spawnable end return t