C++/Lua Request Thread

Is there a way to force settlers to found a city on turn 0? Basically, I want it so when you start a game, everyone's capital is immediately founded by one of their settlers.
Edit: Nevermind, did it myself.
 
How would I implement the following UA?
Lords of Ulthuan: +1 :c5food: Food from Coast tiles. +5 :c5culture: Culture from Mountain tiles.

I did something similar for my Moriya Shrine civilization. I didn't have the exact code handy to reference, but working off some code LastSword posted in another thread I'm hoping this would do the trick?

Code:
function LordsofUlthuanPlotCheck(iPlayer)
	local pPlayer = Players[iPlayer]
	if pPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_LORDS_OF_ULTHUAN"] and pPlayer:IsAlive() then	
		for pCity in pPlayer:Cities() do
			iNumMountains = 0
			iNumCoast = 0
			for cityPlot = 0, pCity:GetNumCityPlots()-1, 1 do
				local plot = pCity:GetCityIndexPlot(cityPlot)
				if plot then
					if plot:IsMountain() and plot:GetOwner() == iPlayer then
						iNumMountains = iNumMountains + 1
					end
					if plot:IsCoastalLand() and plot:GetOwner() == iPlayer then
						iNumCoast = iNumCoast + 1
					end
				end
			end
			pCity:SetNumRealBuilding(GameInfoTypes["BUILDING_ULTHUAN_MOUNTAIN_BONUS"], iNumMountains) 
			pCity:SetNumRealBuilding(GameInfoTypes["BUILDING_ULTHUAN_COAST_BONUS"], iNumCoast) 
		end
	end
end
GameEvents.PlayerDoTurn.Add(LordsofUlthuanPlotCheck)

You'd want to chance "CIVILIZATION_LORDS_OF_ULTHUAN" to whichever tag you actually used for the civ, though.
 
So the gains are actually done through the dummy buildings at the bottom, then?
Wouldn't that just give a flat amount of culture for each city that has a mountain in its territory or food for a city that is coastal?
I really want to give the bonus to each tile, so each mountain tile gives 5 culture and each coast tile gives an extra 1 food.
Thanks for being willing to help!
 
So the gains are actually done through the dummy buildings at the bottom, then?
Wouldn't that just give a flat amount of culture for each city that has a mountain in its territory or food for a city that is coastal?
I really want to give the bonus to each tile, so each mountain tile gives 5 culture and each coast tile gives an extra 1 food.
Thanks for being willing to help!

No, the loop counts up the number of mountains and coastal tiles in the city's territory, and then spawns a number of dummy buildings equal to that number in the city. Note that the BuildingClass for the dummy buildings will need to be set <NoLimit>true</NoLimit> for this to work, so that the code will spawn more than one per city:

Code:
	<BuildingClasses>
		<Row>
			<Type>BUILDINGCLASS_ULTHUAN_MOUNTAIN_BONUS</Type>
			<DefaultBuilding>BUILDING_ULTHUAN_MOUNTAIN_BONUS</DefaultBuilding>
			<Description>TXT_KEY_BUILDING_ULTHUAN_MOUNTAIN_BONUS</Description>
			<NoLimit>true</NoLimit>
		</Row>
		<Row>
			<Type>BUILDINGCLASS_ULTHUAN_COAST_BONUS</Type>
			<DefaultBuilding>BUILDING_ULTHUAN_COAST_BONUS</DefaultBuilding>
			<Description>TXT_KEY_BUILDING_ULTHUAN_COAST_BONUS</Description>
			<NoLimit>true</NoLimit>
		</Row>
	</BuildingClasses>
 
Awesome! Thanks a ton, Bouncymischa.
The yields won't display on the map though will they?
(Not that it matters, but if possible I'd prefer to have "extra yields" actually display on the tile they're supposedly coming from)
 
Awesome! Thanks a ton, Bouncymischa.
The yields won't display on the map though will they?
(Not that it matters, but if possible I'd prefer to have "extra yields" actually display on the tile they're supposedly coming from)

The yields won't display on the map using this method, unfortunately. There was a method some people used in the past which replaced the existing mountains with an identical mountain feature, that allowed them to be worked for yields like other terrain, but there were some issues with it. (Among others, if you had multiple different mods that replaced mountains with different features, they'd overwrite each other... although since I think the Warhammer is a complete mod that may not be an issue for you.)

There may be a way to modify the yield of the coast on its own so that it'd appear on the map, but I'm not sure how one would do it.
 
I was wondering If someone would be able to make me some Lua for the following trait?

UA: Fortress Island
For every 25 Combat Strength a city has, a city produces 1 Culture. Immediately enter a Golden Age if a Peace Treaty is signed between yourself and another Civilization.
 
Uhm, sorry, I'm having a bit of trouble. I'm trying to make Great Works of Writing generate +2 Faith. The plan currently is to have a dummy building that generates +2 Faith, and spawns/is removed whenever a Great Work is moved from one city to another.

However, I have absolutely no idea of how to detect when a Great Work of Writing even exists.

Any tips?
 
I did something similar for my Moriya Shrine civilization. I didn't have the exact code handy to reference, but working off some code LastSword posted in another thread I'm hoping this would do the trick?

Code:
function LordsofUlthuanPlotCheck(iPlayer)
	local pPlayer = Players[iPlayer]
	if pPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_LORDS_OF_ULTHUAN"] and pPlayer:IsAlive() then	
		for pCity in pPlayer:Cities() do
			iNumMountains = 0
			iNumCoast = 0
			for cityPlot = 0, pCity:GetNumCityPlots()-1, 1 do
				local plot = pCity:GetCityIndexPlot(cityPlot)
				if plot then
					if plot:IsMountain() and plot:GetOwner() == iPlayer then
						iNumMountains = iNumMountains + 1
					end
					if plot:IsCoastalLand() and plot:GetOwner() == iPlayer then
						iNumCoast = iNumCoast + 1
					end
				end
			end
			pCity:SetNumRealBuilding(GameInfoTypes["BUILDING_ULTHUAN_MOUNTAIN_BONUS"], iNumMountains) 
			pCity:SetNumRealBuilding(GameInfoTypes["BUILDING_ULTHUAN_COAST_BONUS"], iNumCoast) 
		end
	end
end
GameEvents.PlayerDoTurn.Add(LordsofUlthuanPlotCheck)

You'd want to chance "CIVILIZATION_LORDS_OF_ULTHUAN" to whichever tag you actually used for the civ, though.

Awesome! Thanks a ton, Bouncymischa.
The yields won't display on the map though will they?
(Not that it matters, but if possible I'd prefer to have "extra yields" actually display on the tile they're supposedly coming from)
It wouldn't really be necessary to iterate through all the plots looking for coastal ones, or adding multiple dummy buildings for that matter if the definition of "coastal" is considered by Civitar as being equivalent to "is a sea plot as defined by the buildings table <Building_SeaPlotYieldChanges>". If this is acceptable, then all that is necessary is to add a dummy building to each city, where the dummy building has this as part of its code:
Code:
<Building_SeaPlotYieldChanges>
	<Row>
		<BuildingType>BUILDING_COASTAL_FOOD_DUMMY</BuildingType>
		<YieldType>YIELD_FOOD</YieldType>
		<Yield>1</Yield>
	</Row>
</Building_SeaPlotYieldChanges>
Tooltips and such will show the additional food from the tile. It does, however, require that the tile is actually being worked by the city just like any other tile-modifier building. But it actually does not matter if the city itself is built on a coast-line. Then you simply give the dummy building through a Traits <FreeBuilding> or you give it via lua through a GameEvents.PlayerCityFounded.Add(SomeFunctionName), and/or GameEvents.CityCaptureComplete.Add(SomeFunctionName). I can't remember whether you would also need one (for the lua method) for when the city is traded-off via diplomacy. Traits <FreeBuilding> is obviously way simpler.
 
Hi. I'm trying to make a promotion that grants a combat bonus vs barbarians. Would anyone be willing to help me out with that?
 
Alright, so if I was looking for an event/GameEvent/LuaEvent that only triggered once somewhat near the start of a game what would I look for?

Specifically I wish to forcibly cause some players to meet via Lua, but simi limited depending on civilization (this part I can do) but don't know any events I could tag this to. SerialEventStartGame happens too early, and things like CityCreated and DoTurn wayyyy too often.

Mayhaps obviously, Lua is not my strong point, is there another way to force a function to activate on turn 1? And only 1.

At Morpheus: It looks like BarbarianCombatBonus is only available for Policies and Difficulties, so you would have to do one of the following:
A: Duplicate the Difficulties and increase the BarbCB, and change the Diff via Lua dependent on Civ once in game, however this will be global for your units.
2: Make an unattainable Policy and grant it for free to the relevant civ via Lua, again global.
C: Make a DLL mod to add a functioning effects for a BarbCombBonus column in the Promotions table, then add said column via sql to the table. This would achieve what you seem to be talking about but may be more work than you are looking for. :P
-note: shouldn't be all that hard honestly, but will be if you don't know C++. Seeing how BarbCombBouns exists, it would only require small changes to unitCombat and adding the ties for reading a db value. (and promotion effects, but that can be easily scrap copy/pasted)
 
and DoTurn wayyyy too often.

Code outside of a function, will execute as the file loads (but that may be too early as well), otherwise just hook PlayerDoTurn and then remove the listener

Code:
function OnPlayerDoTurn(iPlayer)
  -- Defend against executing the code on subsequent game sessions (ie after load game)
  local bReallyFirstTime = IsThisNotALoadingSavedGame()

  if (bReallyFirstTime) then
    -- Do something once
  end

  -- Now remove the listener
  GameEvents.PlayerDoTurn.Remove(OnPlayerDoTurn)
end
GameEvents.PlayerDoTurn.Add(OnPlayerDoTurn)
 
Alright so while IsThisNotALoadingSavedGame() is not a real lua call, I figured out another reasonable approach, but ran into another problem.

(Btw, workaround for above was Globaly.checking() if the turn number was <= 1, this at least works as expected, as every game starts at turn 1.)

So the Wiki API lists player:Contact() but this also returns null (i.e. not existing in the lua methods) and browsing said methods I found nothing that would work for player!! Instead I have to switch to team [player:GetTeam()] but whatever this returns refuses to let me call any team:Methods() complaining about attempting to index a number value, which is frustrating as player:GetTeam() obviously must return a number, so what do I run/convert that to to actually call team:Methods()?!? :GetID() throws the error :Meet() [which is what I want to run] throws it, :HasMet(), a few others (I started copying random methods from LuaTeam.h) all just toss an error in the lua logs and fail. D:

I would presume, from what I can kidna see in the source that I need a TeamTypes but there isn't anything that looked like it would find that. Doesn't help that MsVisual is being difficult about finding declarations and dependencies D: It likes to claim that Classes just flat out don't exist :P

EDIT: Thanks a ton to both of you who helped! I didn't -really- realise that you have to refer to the DB every time you switch variable types. Well, now I know. Future headaches adverted. Now to see what breaks when I change Mountains to TERRAIN_TYPES and try calling them in the <CivTerrainBiases> :D

EDIT2: For those wishing to use the :Meet() method please take note: It can have 2 input variables (1 required, 1 optional), and must be called both ways to get the desired effects (otherwise weirdness or silent failures occur.)

-|- the Bool is for whether or not "FirstGreeting%" messages are sent (true = not sent).

Example: teamPlayer:Meet(teamAI); teamAI:Meet(teamPlayer, true);
 
Code:
function MeetAndGreet(iThisPlayer, iThatPlayer)
  local pThisPlayer = Players[iThisPlayer]
  local pThisTeam = Teams[pThisPlayer:GetTeam()]

  local pThatPlayer = Players[iThatPlayer]

  if (pThisTeam:IsHasMet(pThatPlayer:GetTeam()) then
    -- do stuff
  end
end
 
NVM, unearthed a thread that seems to have solved this so far. http://forums.civfanatics.com/showthread.php?t=525736

Spoiler :
Grr. Okay, so either Events.SerialEventUnitDestroyed doesn't forward a unitID and/or I can't grab a plot based on a deceased unit.

Code:
Spoiler :

function BarbWinFight (playerID, player2ID, unitID) --EDITED: it's (player, killer, unit), doesn't fix the issue tho.
local pOwner = Players[playerID];
local pDeadUnit = pOwner:GetUnitByID(unitID);
local pPlot = pDeadUnit:GetPlot();


EDIT: the error
[124752.018] Runtime Error: --path--.lua:84: attempt to index local 'pDeadUnit' (a nil value)

Whereupon the red is where my error appears. I assume either unitID isn't being imported (and thus null) or :GetUnits or :GetUnitByID returns null (tried both), as the unit is already dead.

So I need an Event that'll let me figure out if a fight was won (i.e. other unit was killed). AND I need a feasible way to get the relevant plot for both initiating and determining other effects. (The 'other effects' already work)


So new question: I need a GameEvent or Event that triggers when barbarians "sack" a city! Or, if someone knows where I can bloody find them, (and no, Civ Wiki is horrendously unreliable) the locations of all GameEvents/Events/ect. or tips on figuring them out.
 
At Morpheus: It looks like BarbarianCombatBonus is only available for Policies and Difficulties, so you would have to do one of the following:
A: Duplicate the Difficulties and increase the BarbCB, and change the Diff via Lua dependent on Civ once in game, however this will be global for your units.
2: Make an unattainable Policy and grant it for free to the relevant civ via Lua, again global.
C: Make a DLL mod to add a functioning effects for a BarbCombBonus column in the Promotions table, then add said column via sql to the table. This would achieve what you seem to be talking about but may be more work than you are looking for. :P
-note: shouldn't be all that hard honestly, but will be if you don't know C++. Seeing how BarbCombBouns exists, it would only require small changes to unitCombat and adding the ties for reading a db value. (and promotion effects, but that can be easily scrap copy/pasted)

@Inightshade Thanks man :)

Rather than modify the dll, however, wouldn't it be possible to use lua to grant a combat bonus promotion that a unit would receive when that unit was fighting a barbarian? All that would take it a hook that fires when a unit enters combat. Afterwards, you'd just have to remove that promotion via lua when the combat is resolved or upon the unit's next combat.

Does anyone know if there's a hook for when a unit enters combat, and if so, what its parameters are?

Edit: or even better, would there happen to be a hook that fires when a unit is targeting an enemy unit, so that the UI will recognize the promotion in the pre-battle summary?
 
Back
Top Bottom