Add a New Unit, for a specific Civilization

ZeeroHell

Chieftain
Joined
Aug 12, 2015
Messages
5
Hello everyone, I'm starting modding Civ this week, and I got to grips with lua fastly, but I'm unable to manage on how could I add a Complete New Unit (With new UNITCLASS), that could be built only by my Civ.

Right now, my completely new unit is unlocked to built for every civ, but I want it do be built just by my civ.

I wanna help on how could I code that, I preffer LUA, but may be SQL, I've tought about using Player.CanTrain or City.CanTrain or GameEvents.PlayerCanTrain, but

I can't manage on how to work with these to do what I want, the max I got is that just my civ is able to built units, other civs can't build ANY other unit :sad:
 
Player.CanTrain would work just fine (you can post what you have so far if you'd like help with that method), but why not just make it a unique unit (by adding an entry to the Civilization_UnitClassOverrides table)?
 
Code:
Events.SerialEventStartGame.Add(
GameEvents.PlayerCanTrain.Add(
function(playerID, unitTypeID)
	if (glPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_MYCIV) then
		if (GameInfo.Units[unitTypeID] == GameInfo.Units["UNIT_SACRIFICE"]) then
			return true;
		end
		return true;
	else
		if (GameInfo.Units[unitTypeID] == GameInfo.Units["UNIT_SACRIFICE"]) then
			return false;
		end
		return false;
	end
end))

It is not to do with overwritting any unit, its a completely new specific unit, related to the trait.

Right now every civ may Train it :sad:
 
You can set the override for the class to blank for all other civs, but you'd need a SQL trigger so it applied to mod civs that are activated after your mod, as well.

As for your Lua, first, you needn't put the event add inside another event add. However, the problem is that glPlayer is never defined. You need it to be set to Players[playerID].
 
Currently, glPlayer is set by:
Code:
local glPlayer = Players[0];
for mPlayer=0, GameDefines.MAX_MAJOR_CIVS-1 do
	local pPlayer = Players[mPlayer];
	if (pPlayer:IsAlive()) then
		if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_MYCIV) then
			glPlayer = Players[mPlayer];
		end
	end
end
 
Thanks for your help, helped me to solve this, if anyone wants it, here is it:
Code:
GameEvents.PlayerCanTrain.Add(
function(playerID, unitTypeID)
	
	local glPlayer = Players[playerID]

	if (glPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_MYCIV"]) then
		if (GameInfo.Units[unitTypeID] == GameInfo.Units["UNIT_SACRIFICE"]) then
			return true
		else
			return true
		end
	end
	if (glPlayer:GetCivilizationType() ~= GameInfoTypes["CIVILIZATION_MYCIV"]) then
		if (GameInfo.Units[unitTypeID] == GameInfo.Units["UNIT_SACRIFICE"]) then
			return false
		else
			return true
		end
	end
end)

There was a problem with an else, on where it isn't the specified CIV, it was not entering this codeline, so I had to put a new if, and also the double .Add was sending true/false to the Events.SerialEventStartGame.
 
In general, comparing complex types, eg
Code:
GameInfo.Units[unitTypeID] == GameInfo.Units["UNIT_SACRIFICE"]
is not recommended.

Both GameInfo.Units[unitTypeID] and GameInfo.Units["UNIT_SACRIFICE"] are tables (eg something like {a=1, b=2}) and you are relying on how complex types are compared

c = {a=1, b=2};
d = {a=1, b=2};

If the comparison is done "by reference", c == d will return false. If the comparison is done by value, c == d will be true.

You would be better using
Code:
unitTypeID == GameInfoTypes["UNIT_SACRIFICE"]
as it will be both faster and is unambiguous

It would be even better to cache GameInfoTypes["UNIT_SACRIFICE"] as a file global (where it will be evaluated once) and then do the comparison to that, eg

Code:
local iUnitSacrifice = GameInfoTypes["UNIT_SACRIFICE"];

...

function ...

... unitTypeID == iUnitSacrifice ...
 
Back
Top Bottom