Lua module questions

Hello all,

I had a couple questions about using Lua modules in Defold.

  1. First, is this the recommended way of handling read-only data structures? I try to keep the data structure in a local table and return the individual items through functions. Or would this be a case for using the global scope?
local M = {}

local weapons = {
	{
		hash = hash("melee"),
		name = "Melee",
		sprite_id = "weapon-scalpel",
		fire_sound = "melee-swing",
		ammo_type = hash("melee"),
		player_props = {
			fire_interval = 0.5
		},
		enemy_props = {
			fire_interval = 1
		}
	},
	{
		hash = hash("rifle"),
		name = "Rifle",
		sprite_id = "weapon-rifle",
		fire_sound = "rifle-fire",
		ammo_type = hash("bullet"),
		player_props = {
			fire_interval = 1,
			magazine_size = 20,
			reload_time = 1.5,
			shot_speed = 940,
			shot_damage = 3,
			shot_range = 300,
			shot_spread = 10,
			shots = 1
		},
		enemy_props = {
			fire_interval = 1,
			shot_speed = 940,
			shot_damage = 1,
			shot_range = 300,
			shot_spread = 10,
			shots = 1
		}
	},
	{
		hash = hash("shotgun"),
		name = "Shotgun",
		sprite_id = "weapon-shotgun",
		fire_sound = "shotgun-fire",
		ammo_type = hash("bullet"),
		player_props = {
			fire_interval = 0.8,
			magazine_size = 10,
			reload_time = 1.2,
			shot_speed = 800,
			shot_damage = 2,
			shot_range = 200,
			shot_spread = 10,
			shots = 7
		},
		enemy_props = {
			fire_interval = 1,
			shot_speed = 800,
			shot_damage = 2,
			shot_range = 160,
			shot_spread = 10,
			shots = 5
		}
	},
}

function M.get_by_hash(hash)
	for k,v in pairs(weapons) do
		if v.hash == hash then
			return v
		end
	end
	return nil
end

function M.get_by_index(index)
	return weapons[index]
end

return M
  1. Second question: is there a way to callback to a gameobject script from a Lua Module? For example, if I wanted to attach a function called “fire_weapon” to my weapons in the module and have it trigger the bullet spawning from the enemy/player scripts - is that possible?

Thank you!

I would say yes. There are a few alternatives, but from looking at your example, I’d say that’s best.

You may want to look into message passing, that’s the best practice for getting one script to trigger something in another script. It’s a key part of defold. Good luck!

5 Likes

#1.

Generally this looks good, but keep in mind that the only read-only thing here is the “weapons” table itself. The individual weapon tables that you return from the getter functions can be modified by whatever gets them.

Not that this should be a problem. Personally I think it’s silly to try to reproduce many of the protections that other languages have, in lua. A bunch of them are possible, but a bit convoluted to do. I think the general idea with lua is: If you don’t want something to be modified, just don’t do it.

I don’t see any reason to use the global scope here. Globals are generally most useful for either a) things that are used all over the place but never modified, and b) things that are modified all over the place but only used in one or two places.

#2.

Yes, there are a bunch of different ways to do this. It’s hard to be specific without more details about how you want to use this. Functions are first class values in lua, so you can store them wherever you like.

From your code, the weapon tables look more like “Prototypes” or “Classes” rather than “Instances”, so I wouldn’t expect them to store things that are related to a specific enemy or player instance (but you could add an extra sub-table with data for multiple enemies using that weapon, etc.).

One possible sticking point, if you want to directly call a function on one script, from another script, is that the context will still be the context of whichever script runs the code. So even if you pass around the right “self”, doing things like “msg.url("#")” will still be relative to the original script. There is a Native Extension, “Lua Script Instance” that lets you get around this, but that is not necessary 90% of the time. Why add complexity where you don’t need it. You can use message passing to communicate between objects.

A script calling a different function on itself, through a module, works just fine without any issues.

7 Likes