Some Lua for a Unique Unit

Harkodos

Warlord
Joined
Feb 9, 2016
Messages
197
I am currently working on adding a unique unit to a new civilization I'm working on and part of their ability is that they have a +33% combat bonus when fighting on Pastures and Camps within your own territory. This is very similar to The Boers' unique ability regarding Farms. Thus I was hoping someone could show me how to convert the following Lua script to suit the needs of my unit.

Code:
-- CommandoDefense
-- Author: ViceVirtuoso
-- DateCreated: 5/7/2014 9:42:58 AM
--------------------------------------------------------------
local iBoers = GameInfoTypes.CIVILIZATION_BOER
local iPromotion = GameInfoTypes.PROMOTION_BOER_UU_PROMOTION
local iImprovement = GameInfoTypes.IMPROVEMENT_FARM



function BoerUnitHeal(iPlayer, iUnitID)
	if iPlayer < GameDefines.MAX_MAJOR_CIVS then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnitID)
		if pPlayer:GetCivilizationType() == iBoers then
			local pPlot = pUnit:GetPlot()
			if pPlot:GetImprovementType() == iImprovement then
				pUnit:SetHasPromotion(iPromotion, true)
				return
			end
		end
		pUnit:SetHasPromotion(iPromotion, false)
	end
end

GameEvents.UnitSetXY.Add(BoerUnitHeal)

So specifically: I need a unit called the UNIT_SOUTH_PARK_GAME_HUNTER to receive the PROMOTION_ITCHY_TRIGGER promotion while they're stationed on top of IMPROVEMENT_PASTURE or IMPROVEMENT_CAMP, and for this to only work for the CIVILIZATION_SOUTH_PARK Civilization.
 
For changing the promotion and civilization, simply change the variable definitions at the top:
Code:
local iBoers = GameInfoTypes.CIVILIZATION_SOUTH_PARK
local iPromotion = GameInfoTypes.PROMOTION_ITCHY_TRIGGER

(you may also want to change 'iBoers' to e.g. 'iSouthPark' to be more readable; if you do so, be sure to change all other instances of 'iBoers' to match!)

To change it to fire on two different improvements, change
Code:
if pPlot:GetImprovementType() == iImprovement then
to
Code:
if pPlot:GetImprovementType() == GameInfoTypes.IMPROVEMENT_PASTURE or pPlot:GetImprovementType() == GameInfoTypes.IMPROVEMENT_CAMP then

Because the game will have to go into the database every time the function is run this way, it's not very efficient, so it'd good practice to define them in variables like ViceVirtuoso did in the original code, so replace:

Code:
local iImprovement = GameInfoTypes.IMPROVEMENT_FARM

with (e.g.; the variable names themselves are arbitrary)

Code:
local iImprovementPasture = GameInfoTypes.IMPROVEMENT_PASTURE
local iImprovementCamp = GameInfoTypes.IMPROVEMENT_CAMP

and then the line with the GetImprovementType()s becomes:
Code:
if pPlot:GetImprovementType() == iImprovementPasture or pPlot:GetImprovementType() == iImprovementCamp then

Finally, to make it be restricted to UNIT_SOUTH_PARK_GAME_HUNTER, you'd first, for the same reason, add a "local iGameHunter = GameInfoTypes.UNIT_SOUTH_PARK_GAME_HUNTER" to those "local iVariableName = GameInfoTypes.SOMETHING_OR_OTHER" lines. Then you add the check that the unit is actually a game hunter (i.e., "pUnit:GetUnitType() == iGameHunter"), to somewhere after the 'local pUnit = pPlayer:GetUnitByID(iUnitID)' (so the game knows which unit you're referencing); you could change

Code:
if pPlayer:GetCivilizationType() == iBoers then

to

Code:
if pPlayer:GetCivilizationType() == iSouthPark and pUnit:GetUnitType() == iGameHunter then

or alternatively (no need for both of these, as that'll just uselessly have the game check the unit's type twice)

Code:
if pPlot:GetImprovementType() == iImprovement then

to

Code:
if (pPlot:GetImprovementType() == iImprovementPasture or pPlot:GetImprovementType() == iImprovementCamp) and pUnit:GetUnitType() == iGameHunter then
 
The code works like a charm, thanks for the help!

However, with the code as-is I am presented with a problem. When upgrading the Unit, the upgraded version will be able to retain the Itchy Trigger Finger (I decided to finish the name) promotion if it is upgraded while standing over a Pasture or Camp, but loses it hereafter once the unit moves off.

I am considering either allowing the unit to keep the ability when upgraded, or having a fix so the ability is not retained when upgrading while standing over the Pasture or Camp. I would assume the former is more difficult to code than the latter, especially since I wouldn't want new infantry units that aren't the Game Hunter to have this ability, but would probably also make having the Game Hunter unit to upgrade would be more desirable.

For the sake of curiosity, would you mind showing me both circumstances? (I'd probably prefer for upgraded versions to retain the ability, if I had to choose).
 
For the sake of curiosity, would you mind showing me both circumstances? (I'd probably prefer for upgraded versions to retain the ability, if I had to choose).

If I'm reading your post correctly, I believe the problem you're having is that you want this particular unit (the Game Hunter) to fight better on Pastures or Camps, but currently if you upgrade the Game Hunter to a unit replacing it, it retains the upgrade until it moves off of the tile?

The solution to this is actually fairly simple: in the promotion definition, there is a field called <LostWithUpgrade>. If you set it true, like so:
Code:
<UnitPromotions>
	<Row>
		<Type>PROMOTION_GAME_HUNTER</Type>
		--snip--
		<LostWithUpgrade>true</LostWithUpgrade>
		--snip--
	</Row>
</UnitPromotions>
...then the promotion will automatically be lost whenever you upgrade your Game Hunter (and, assuming the code is checking for Game Hunters to give the promotion, it won't be giving it to your new upgraded unit).

As for your preference of allowing the upgraded unit to keep the promotion... well, there's no way I can think of to do that. The game can't distinguish what a unit is upgraded from, so there's no way you can search specifically for units that were upgraded from Game Hunters and allow them to obtain the promotion as well.
 
I had considered LostWithUpgrade as a possibility, but I wasn't sure given the circumstances of how the unit acquires the Promotion (it only has it while it's on a Pasture or Camp).

I figured that might've been the case. I suppose making the Unit unable to keep the promotion will have to do then.
 
You could create a second promotion that does nothing by itself, but have the Game Hunter start with it; then replace the check in the Lua for if the unit is a Game Hunter for if it has the free promotion, e.g.

Code:
if pPlayer:GetCivilizationType() == iSouthPark and pUnit:IsHasPromotion(iDummyPromotion) then
 
It's funny that you should mention a concept like that. I was actually pondering an idea like that while I was writing my previous response. However, I couldn't for the life of me figure out how to put the two together. That's much clearer than in my head!

I'll try that out and see what I can get.

-EDIT-

Well, that seemed to do the trick. Thanks for the assist!
 
I thought I'd bump this because I'm currently working on a Civ with a UA similar to what this does, except instead of the combat bonus activating while the unit is on top of an improvement, I want to work it so it activates when the unit is on top of a particular resource.

I tried rigging this together with guess-work to see if I could achieve the desired result, but it doesn't seem to want to work that way:
Code:
-- Ariad_Improvements
-- Author: Harkodos, with help from Klisz
-- Base: ViceVirtuoso
--------------------------------------------------------------
local iSudanya = GameInfoTypes.CIVILIZATION_AMERICA
local iPromotion = GameInfoTypes.PROMOTION_PROTECT_THE_SPOILS
local iDummyPromotion = GameInfoTypes.PROMOTION_GREEDY
local iResourceArtifacts = GameInfoTypes.RESOURCE_ARTIFACTS
local iResourceHiddenArtifacts = GameInfoTypes.RESOURCE_HIDDEN_ARTIFACTS

function SudanyaUnitHeal(iPlayer, iUnitID)
	if iPlayer < GameDefines.MAX_MAJOR_CIVS then
		local pPlayer = Players[iPlayer]
		local pUnit = pPlayer:GetUnitByID(iUnitID)
		if pPlayer:GetCivilizationType() == iSudanya then
			local pPlot = pUnit:GetPlot()
			if (pPlot:GetResourceType() == iResourceArtifacts or pPlot:GetResourceType() == iResourceHiddenArtifacts) and pUnit:IsHasPromotion(iDummyPromotion) then
				pUnit:SetHasPromotion(iPromotion, true)
				return
			end
		end
		pUnit:SetHasPromotion(iPromotion, false)
	end
end

GameEvents.UnitSetXY.Add(AriadUnitHeal)

One alternative I considered if this ability cannot work, is if instead the Civilization's units receive a 1% ~ 3% combat bonus for every great work they possess (up to a maximum of 20% ~ 33%).
 
Back
Top Bottom