[Lua] Spawn a unit without AddFreeUnit?

Irkalla

ENTP POWWWEEEEEER
Joined
Sep 25, 2012
Messages
1,009
Location
Way down around Vicksburg
Basically, I want to spawn a unit that gets experience from Barracks and stuff. Any ideas?
 
What's wrong with InitUnit() and then Set/ChangeExperience()?
 
What's wrong with InitUnit() and then Set/ChangeExperience()?

InitUnit spawns a unit at the given coords apparently? Funny name they chose.

I take it, to spawn a booty warrior at Player 1's capital in this manner... Let's assume I've got a working function that looks at the city's military training buildings, if any, and returns a function... I do:

Code:
local pPlayer = Players[0];
local iUnitID = GameInfoTypes["UNIT_BOOTY_WARRIOR"];
local pCapital = pPlayer:GetCapitalCity();
local pCapitalPlot = pCapital:Plot();

pSoldier = pPlayer:InitUnit( iUnitID, pCapitalPlot.X, pCapitalPlot.Y ); 
pSoldier:JumpToNearestValidPlot(); 
pSoldier:SetExperience( fnGetMilitaryTrainingXP( pCapital )

Sounds right, anyway. Should I set Experience before Jumping to Nearest Plot?
 
Pretty much. Although if you want to use a city as the generation point, something like

Code:
local sUnitType = "UNIT_WARRIOR"
pUnit = pPlayer:InitUnit(GameInfoTypes[sUnitType], pCity:GetX(), pCity:GetY())
pUnit:SetExperience(pCity:GetDomainFreeExperience(pUnit:GetDomainType()))
-- Could also use pCity:GetFreePromotionCount() to text for any free promotions from Wonders
pUnit:JumpToNearestValidPlot()
-- TAKE CARE!!! The unit may have just been deleted if there is no valid plot
 
Pretty much. Although if you want to use a city as the generation point, something like

Code:
local sUnitType = "UNIT_WARRIOR"
pUnit = pPlayer:InitUnit(GameInfoTypes[sUnitType], pCity:GetX(), pCity:GetY())
pUnit:SetExperience(pCity:GetDomainFreeExperience(pUnit:GetDomainType()))
-- Could also use pCity:GetFreePromotionCount() to text for any free promotions from Wonders
pUnit:JumpToNearestValidPlot()
-- TAKE CARE!!! The unit may have just been deleted if there is no valid plot

Wow, you can do the experience thing? Well gently caress me!

Also, any idea as to in what situations JumpToNearestValidPlot() may fail?
 
Also, any idea as to in what situations JumpToNearestValidPlot() may fail?

It will only jump within the current area, so if you have a city on an island, and there are already units on every tile of that island it will fail.
 
It will only jump within the current area, so if you have a city on an island, and there are already units on every tile of that island it will fail.

So it won't put two units on the same tile then force you to move stacked unit? :T Sounds dumb.

Any alternatives for placing it that allows stacking?

Oh, also. Can I do that handle thing with AddFreeUnit instead of InitUnit?

Last thing, do you know anything about Notifications? Like, how can I change the icon of it and make it do that thing where you click it and it goes to a certain plot?
 
So it won't put two units on the same tile then force you to move stacked unit? :T Sounds dumb.

Any alternatives for placing it that allows stacking?
Just create the unit and don't use the Jump...() method - you'll end up with stacked units you'll have to move before you can end the turn - the problem is if the AI ends up with stacked units it can't move.

Oh, also. Can I do that handle thing with AddFreeUnit instead of InitUnit?
If you mean pUnit = Add... then yes

Last thing, do you know anything about Notifications? Like, how can I change the icon of it and make it do that thing where you click it and it goes to a certain plot?
Yes. To change the icon you'll need to use one of the notification replacing mods, to do the click to jump to a plot you'll either have to use a standard notification that does that (eg a unit or wonder one) or use one of the notification replacing mods
 
Just create the unit and don't use the Jump...() method - you'll end up with stacked units you'll have to move before you can end the turn - the problem is if the AI ends up with stacked units it can't move.


If you mean pUnit = Add... then yes


Yes. To change the icon you'll need to use one of the notification replacing mods, to do the click to jump to a plot you'll either have to use a standard notification that does that (eg a unit or wonder one) or use one of the notification replacing mods

Last thing... say I make a var pointing to a function (what are these actually called?)... How can I execute the function contained within? You know, so I can execute it then pass stuff on it.

Also, I'm thinking of doing this. A nice for loop that cycles through all cities. For each city, it counts all the player's units, initializes the unit meant to be created, jumps him to a valid plot, then counts all the player's units again. If second count == first count + 1, break.

In other words, check to see if it fails, then go to the next city and try it again until we get it.
 
Also, I'm thinking of doing this. A nice for loop that cycles through all cities. For each city, it counts all the player's units, initializes the unit meant to be created, jumps him to a valid plot, then counts all the player's units again. If second count == first count + 1, break.

In other words, check to see if it fails, then go to the next city and try it again until we get it.

JumpToNearestValidPlot() now returns a boolean, true if the unit was jumped, false if it was killed
 
Last thing... say I make a var pointing to a function (what are these actually called?)... How can I execute the function contained within? You know, so I can execute it then pass stuff on it.

Function pointers usually ;)

Code:
local pFunc = Players[iPlayer]:GetCapital -- Note the lack of brackets
local pCapital = pFunc() -- Note the brackets
 
Function pointers usually ;)

Code:
local pFunc = Players[iPlayer]:GetCapital -- Note the lack of brackets
local pCapital = pFunc() -- Note the brackets

The no brackets is so you state pass args using the pointer, right?

Yeah, and for the above example, say instead of InitUnit I used AddFreeunit. Can I spawn the unit by just doing pUnit, then give him experience by doing pUnit:SetExperience(iXP)?

JumpToNearestValidPlot() now returns a boolean, true if the unit was jumped, false if it was killed

Loving A! So I can just do if pUnit:JumpToNearestValidPlot() then pUnit:JumpToNearestValidPlot(); break, else loop over to next city. Or will comparing it also run the function?
 
Correct, so it's just

if pUnit:JumpToNearestValidPlot() then break; end

Does GetFreePromotionCount() with no args test for any (*) free promotion? Whereas I can specify an arg to test for a specific promotion?
 
Does GetFreePromotionCount() with no args test for any (*) free promotion? Whereas I can specify an arg to test for a specific promotion?

Nope.

GetFreePromotionCount() will tell you how many there are from the city (it returns an int), you then have to loop all possible promotions and then test IsFreePromotion(iPromotion) IIRC
 
Nope.

GetFreePromotionCount() will tell you how many there are from the city (it returns an int), you then have to loop all possible promotions and then test IsFreePromotion(iPromotion) IIRC


gotcha.
 
This is what I finally ended up with after I go around to doing it. I'm mainly concerned about line 36. Is that how it's done?

Code:
[LIST=1]
[*]GameEvents.SetPopulation.Add( 
[*]
[*]function( xOffset, yOffset, fOldPop, fNewPop )
[*]
[*]	-- BEGIN DEFINES
[*]	local pPlot				= Map.GetPlot( xOffset, yOffset )
[*]	local pCity  			= pPlot:GetPlotCity()
[*]	local iPlyID 			= pCity:GetOwner()
[*]	local pPly				= Players[ iPlyID ] -- Dat Datatype Mismatch, son
[*]	local iUnitMostCurrent	= nil
[*]	local pLeader			= GameInfo.Leaders[ pPly:GetLeaderType() ]
[*]	local iLeaderTrait		= GameInfo.Leader_Traits("LeaderType ='" .. pLeader.Type .. "'")()
[*]	local pTrait			= GameInfo.Traits[ iLeaderTrait.TraitType ]
[*]	local nTrait			= pTrait.UnitPerCapitalGrowths
[*]	local nZenith			= math.floor( pCity:GetHighestPopulation() )
[*]	local nGeneralCount		= pPly:GetGreatGeneralsCreated()
[*]	local pFreeUnit			= nil
[*]	-- END DEFINES
[*]
[*]	--[[ On every growth of every city, run through the following list of conditions:
[*]	1:  Does the city's owner have the trait, and is its population evenly divisible 
[*]	by the trait?  Have they yet to create a Great General?
[*]	2:  Is the city a capital?
[*]	3:  Has the city grown instead of shrinking, and is this the city's highest 
[*]	population?
[*]
[*]	If all of the above are true, get the best land infantry unit we can, and 
[*]	spawn it at the city. --]]
[*]
[*]	if ( ( nTrait > 0 ) and ( ( math.floor( fNewPop ) % nTrait ) == 0 ) and ( nGreatGeneralCount > 0 ) ) then 
[*]
[*]		if pCity:IsCapital() then
[*]
[*]			if ( ( fNewPop > fOldPop ) and ( fNewPop >= nZenith ) ) then
[*]
[*]				iUnitMostCurrent = fnReturnBestInfantryUnit( pPly, pCity )
[*]
[*]				for City in pPly:Cities() do
[*]					
[*]					pFreeUnit = pPly:InitUnit( iUnitMostCurrent, City:GetX(), City:GetY() )
[*]
[*]					if pFreeUnit:JumpToNearestPlot() then
[*]
[*]						local strNotificationText	= "The Agoge has produced a free " .. pFreeUnit:GetName() .. " in " .. City:GetName() .. "!"
[*]						local strNotificationTitle	= "New Unit from the Agoge!"
[*]						 
[*]						pFreeUnit:SetExperience( pCity:GetDomainFreeExperience( pFreeUnit:GetDomainType() ) )
[*]
[*]						if ( pCity:GetFreePromotionsCount() > 0 ) then
[*]
[*]							[COLOR="Red"]for iPromotion in GameInfo["UnitPromotions"] do[/COLOR]
[*]								
[*]								if pCity:IsFreePromotion( iPromotion ) then
[*]									
[*]									pFreeUnit:SetHasPromotion( iPromotion, true )
[*]
[*]								end
[*]
[*]							end
[*]
[*]						end
[*]
[*]						pPly:AddNotification( NotificationTypes["NOTIFICATION_GENERIC"], strNotificationText,
											  strNotificationTitle, pFreeUnit:GetX(), pFreeUnit:GetY() )
[*]						
[*]						break 
[*]					
[*]					end
[*]
[*]				end
[*]
[*]			end
[*]
[*]		end
[*]
[*]	end
[*]
[*]end )
[/LIST]
 
IIRC you'll need

for promotion in GameInfo.Promotions() do
local iPromotion = promotion.ID
-- other stuff
end
 
IIRC you'll need

for promotion in GameInfo.Promotions() do
local iPromotion = promotion.ID
-- other stuff
end

whoops. Still trying to get used to all this database structured query junk :lol:
 
I'm still hung up on this. Calling it a night.

Code:
if ( pCity:GetFreePromotionCount() > 0 ) then
    for promotion in GameInfo.UnitPromotions() do

	iPromotion = promotion.ID
								
	if pCity:IsFreePromotion( iPromotion ) then
		pFreeUnit:SetHasPromotion( iPromotion, true )
	end

    end

end
 
Back
Top Bottom