Sending ONE msg.post() but received COUPLE of messages (SOLVED)

Hey there.

I am sending via msg.post() a message from one to another script. now I have an example where it looks like the receiving script is getting a couple of messages sometimes.

This is the sending script:

	for v,i in ipairs(GLOBAL.units) do 
		msg.post(GLOBAL.units[v].id, "upgrade", {researchNo = self.isresearching})
		print("STRUCTURE: Sending upgrade to unit " .. GLOBAL.units[v].id)
	end

This is the receiving script:

	if message_id == hash("upgrade") then		
		GLOBAL.researchType[message.researchNo].exec(self)
		msg.post("main:/gamecam#playerstats", "floatingtext", {text = GLOBAL.researchType[message.researchNo].name .. "\n+ " .. GLOBAL.researchType[message.researchNo].researchValue, pos = self.pos, color = GLOBAL.COLOR_ORANGE, fadespeed = 0.5})
		print(self.unit.instanceID .. " " .. self.unit.name .. " upgraded " .. GLOBAL.researchType[message.researchNo].name)
	end

The function() called at the receiving script is from a table (GLOBAL.researchType) like this:

	{
	hash = hash("moreAmmo"),
	name = "Increase unit magazine",
	description = "Increases ammount of ammo for each unit",
	researchResource = "iron",
	researchCost = 400,
	researchTime = 3, -- Seconds
	researchValue = 5,
	researchGroup = "unit",
	exec = function(self) 
		self.unit.ammoMagazine = self.unit.ammoMagazine + 5
	end
	}

Dont have an idea why this happens. If I just got a few units it works. But if I have -lets say- more than 10 this happens:

DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance17]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance18]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance19]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance20]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance21]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance22]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance23]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance24]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance25]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance26]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance27]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance28]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance29]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance30]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance31]
DEBUG:SCRIPT: STRUCTURE: Sending upgrade to unit [/instance32]
DEBUG:SCRIPT: [/instance17] Buggy upgraded More unit movespeed
DEBUG:SCRIPT: [/instance28] EMP Launcher upgraded More unit movespeed
DEBUG:SCRIPT: [/instance29] Constructor upgraded More unit movespeed
DEBUG:SCRIPT: [/instance27] Tank upgraded More unit movespeed
DEBUG:SCRIPT: [/instance21] Rocketlauncher upgraded More unit movespeed
DEBUG:SCRIPT: [/instance25] Collector upgraded More unit movespeed
DEBUG:SCRIPT: [/instance25] Collector upgraded More unit movespeed
DEBUG:SCRIPT: [/instance27] Tank upgraded More unit movespeed
DEBUG:SCRIPT: [/instance25] Collector upgraded More unit movespeed
DEBUG:SCRIPT: [/instance32] Tank upgraded More unit movespeed
DEBUG:SCRIPT: [/instance27] Tank upgraded More unit movespeed
DEBUG:SCRIPT: [/instance28] EMP Launcher upgraded More unit movespeed
DEBUG:SCRIPT: [/instance29] Constructor upgraded More unit movespeed
DEBUG:SCRIPT: [/instance30] Agent upgraded More unit movespeed
DEBUG:SCRIPT: [/instance32] Tank upgraded More unit movespeed
DEBUG:SCRIPT: [/instance32] Tank upgraded More unit movespeed

The first lines are ok, these are the SENDING lines, but why the hell are some units / instances are upgrading more than one time (f.e. /instance25 are 3 times)?
Any ideas? how to fix this?

It might be that the self.unit table is messed up. E.g. different units share the same table.
You can print out direct values of the instances bypassing the unit table. Like

print(self)
--or
print(go.get_id(self))

See how it correlates with the self.unit.instanceID.

1 Like

Thanks.

Hm… good point. I guess its like this…

The code :slight_smile:

self.unit = GLOBAL.unitType[v]

IMHO I thought its instancing. Not using the GLOBAL values. I just want the GLOBAL.unit-values as a template.
Does that mean EVERY same unit with same type is SHARING all values?

//EDIT. Yes. seems like all same types (f.e. collector) is using the same values :frowning:

How to instanciate the variables to the units?

In Lua tables are passed by reference, which means when you do

local a = {value = 1}
local b = a
print(a, b)

b would be the same table as a, it would just have two names.
If you want to explicitly create a new table and keep the old one, you should copy it.

local a = {value = 1}
local b = {}
for k, v in pairs(a) do
  b[k] = v
end
print(a, b, a.value, b.value)

This way a and b are independent. This loop performs shallow copy, if you want to copy inner tables, you should use one of the many table.deepcopy() functions you can find online.

1 Like

Yes, like @sergey.lerg has already pointed out, this would assign the same table to every self.unit variable. You need to copy the table somehow. Google for lua copy table for a bunch of different examples of this.

1 Like

Thanks to both of you.

Its the same like often… the “shadow-variables-trap”. Damn. always the same thing.
I’ve googled it already. There are many ways of “copying”. Wondering why there is no command to do so.

For all the others, here are some examples:
http://lua-users.org/wiki/CopyTable

The deepcopy example from that page seems to work well:

function deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[deepcopy(orig_key)] = deepcopy(orig_value)
        end
        setmetatable(copy, deepcopy(getmetatable(orig)))
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end

This is typical Lua. There are often more than one way of solving a problem in Lua, and if there was a built in way of copying a table it might not do what everyone wants. Should it be a deep or shallow copy? Should it copy meta tables or not? What about user data? Nested tables? That’s why it’s better to use your own copy function.

Every programming-languages has commands. there will be always stuff to code by yourself.
But, if I would prefer having just a view commands and do everything by hand I would code assembler :wink:

Copying a table is - IMHO - a major thing. There should be a (or some) command (s).

In these cases I think it’s more common to arrange the data differently, so that you don’t have to do costly deep copies.

What you mean concretely? Any suggestions @Mathias_Westerdahl?

Is there a better/faster way to deal with? I may post more of the templates if you need.

I thought it is a good idea to handle the main things in a global lua file. There are some game variables and some tables.

Actually I am working on this project https://forum.defold.com/t/abandoned-force-top-view-strategy-game/8200/21 and there I have tables for units, structures, weapons etc.

If I spawn anything (using the factory) I have to give the new GO all his values. Of cause I could do that in the attached script, but I thought handling it by a global lua gives me more possabilities. For example access to (standard-) values of any of that table.