C++/Lua Request Thread

Ran into a bit of a wall here, sorry - I'm trying to get a Civ that when it conquers a barbarian tile or a city, it gains Influence with all known City-States and Great Merchant points in the Capital.

I've tried so hard and yet I have failed to manage to get this to work. I desperately need help.
 
For conquering a Barb city you can simply use CityCaptureComplete GameEvent, for the barbarian camp, it is an improvement, so you would need to use a modified event (VMC/CPP's DLL have one of those) that intercepts changes to improvs.

I thought about iterating all neutral land plots in the map and storing those with a camp if you don't want to use a DLL, but that not only would cause tremendous lag issues but also has the problem of knowing who took the camp...

I can't think of much else right now. Sorry. :(
 
Is it possible using only lua to add a new conditional combat modifier that follows conditions not existing on existing promotions? (eg +10% combat strength if enemy unit has less health than you). I know I can on DLL, but the lua events I see seem to be after the damage is done.

Im thinking that MAYBE I could edit the lua that displays the combat preview to enhance the combat strength of the attacking unit if the conditions match, but in that case, if the Ai were to attack me, as the preview is not shown, the modifier would not work on defense, and also probably would bring desynch problems if multi as the UI only shows on the attacking player.

Also is it safe to keep an engine object pointer in LUA, or should I only keep ids and search for the objects at every sequential block execution? eg: local city = player:GetCapitalCity();, if I save city to a global to be used later (eg next turn, or in 20 turns), would it be safe to keep it for the duration of the session? or does the game do memory reallocation at "random" points as you play?
 
Is it possible using only lua to add a new conditional combat modifier that follows conditions not existing on existing promotions? (eg +10% combat strength if enemy unit has less health than you). I know I can on DLL, but the lua events I see seem to be after the damage is done.

Im thinking that MAYBE I could edit the lua that displays the combat preview to enhance the combat strength of the attacking unit if the conditions match, but in that case, if the Ai were to attack me, as the preview is not shown, the modifier would not work on defense, and also probably would bring desynch problems if multi as the UI only shows on the attacking player.
The answer is pretty much 'No' because lua events related to combat are either intended for graphical display, for combat-related UI panels, or only give info on what unit was killed as a result of combat. Graphical Display and Combat-Related UI 'events' don't fire except in certain pre-defined condiitons, and so are essentially useless. Some only are fired if the human player can see the action, some don't fire when the game is in strategic view, and some don't fire (as I recall) when Quick Combat is turned on.
Also is it safe to keep an engine object pointer in LUA, or should I only keep ids and search for the objects at every sequential block execution? eg: local city = player:GetCapitalCity();, if I save city to a global to be used later (eg next turn, or in 20 turns), would it be safe to keep it for the duration of the session? or does the game do memory reallocation at "random" points as you play?
I wouldn't do it not so much from a point of view of memory allocation issues as the fact that cities get conquered. If a city is not a player's original capital, it can be both captured and razed, which means that your pointer would then be nil. Nothing wrong really with caching data for the run of a game-session -- the problem is in doing so for data like pointer objects that can be nil or irrelevant by the time you get back to 'reading' this data again. I would probably cache the city's XY position as opposed to the city pointer, as an example, because the plot's XY isn't going to be affected by city ownership or city-razing.
 
Thank you, so that bonus is not possible :/

Yeah I was trying to avoid to cache more than one variable, to keep things simple, I can test for nil beforehand, wait... the lua variable doesnt have to know the c++ one is now nil right? I'm guessing no lol... anyway I'll be caching x,y and the id for now
 
Heed the warning in ProductionPopup.lua

Code:
-- NOTE: Storing the PlayerID/CityID for the city, it is not safe to store the pointer to a city
--       over multiple frames, the city could get removed by the game core thread
 
Hi, Is there in LUA-only, a way for a player to get open borders with another, skipping the trade logic? eg player:SetOpenBorders( otherplayer, finalturn ); I believe there is not, but maybe I missed it. Alternatively, is there a way to set a tile as impassable (or an impassable tile as passable).

Currently I believe I can only use the promotion Enter Rival Territory. Which I check on unit tile move, and if they enter I tile I dont want them to enter, I set moves to 0 and remove the promotion (and once they get kicked out I give the promotion back). That would work with human players, as they'd understand and avoid moving into terrain they are not "allowed" to. But I believe the AI would just keep trying and get stuck. In fact I myself had to babysit my unit movements once as the automated pathing kept trying to move units I had moved over a long distance through the "invalid" territory. If I didn't move them one tile at a time once I noticed, they'd have kept trying to run into this invalid territory and get pushed back to the beginning, getting stuck indefinitely :/
 
Hi, Is there in LUA-only, a way for a player to get open borders with another, skipping the trade logic? eg player:SetOpenBorders( otherplayer, finalturn );

Not directly. What you need to do is setup up a trade between the two players in Lua (see the trade deal UI code for how that's done) and then execute the deal via UI.DoFinalizePlayerDeal(...);
 
Not directly. What you need to do is setup up a trade between the two players in Lua (see the trade deal UI code for how that's done) and then execute the deal via UI.DoFinalizePlayerDeal(...);

Thank you, I've got a bad feeling about that (like if the AI hates me it wont accept no matter what), I will check the code, maybe it is not like I think atm and it forces the trade, that would be great.
 
Alright this is bugging me because I feel like I'm missing something completely obvious to get this working.

Essentially want a code that Generates +2 gold per Science Building (Library, Observatory, University, Research Lab, Public School) when the city has the civ's unique building built.
 
Alright this is bugging me because I feel like I'm missing something completely obvious to get this working.

Essentially want a code that Generates +2 gold per Science Building (Library, Observatory, University, Research Lab, Public School) when the city has the civ's unique building built.
Added directly to the treasury, or as a hidden building with YieldChange of +2 Gold ?

The hidden building allows the gold to be multiplied by Markets and the like, whereas the direct addition of gold to the treasury does not.
 
  1. As built, the code will add one (1) dummy building for every "Science" building existing in the same city that has "BUILDING_YOUR_UNIQUE_BUILDING"
  2. You just need to create and add into your mod's xml the definition of the dummy building, and make each copy of the dummy building give the desired +2 Gold per turn:
    Spoiler :
    Code:
    <GameData>
    	<Buildings>
    		<Row>
    			<Type>BUILDING_YOUR_DUMMY</Type>
    			<BuildingClass>BUILDINGCLASS_YOUR_DUMMY</BuildingClass>
    			<Cost>-1</Cost>
    			<FaithCost>-1</FaithCost>
    			<PrereqTech>NULL</PrereqTech>
    			<GreatWorkCount>-1</GreatWorkCount>
    			<ArtDefineTag>NONE</ArtDefineTag>
    			<MinAreaSize>-1</MinAreaSize>
    			<NeverCapture>true</NeverCapture>
    			<HurryCostModifier>-1</HurryCostModifier>
    			<IconAtlas>BW_ATLAS_1</IconAtlas>
    			<PortraitIndex>19</PortraitIndex>
    			<Description>TXT_KEY_BUILDING_YOUR_DUMMY</Description>
    			<NukeImmune>true</NukeImmune>
    		</Row>
    	</Buildings>
    	<BuildingClasses>
    		<Row>
    			<Type>BUILDINGCLASS_YOUR_DUMMY</Type>
    			<DefaultBuilding>BUILDING_YOUR_DUMMY</DefaultBuilding>
    			<Description>TXT_KEY_BUILDING_YOUR_DUMMY</Description>
    			<NoLimit>true</NoLimit>
    		</Row>
    	</BuildingClasses>
    	<Building_YieldChanges>
    		<Row>
    			<BuildingType>BUILDING_YOUR_DUMMY</BuildingType>
    			<YieldType>YIELD_GOLD</YieldType>
    			<Yield>2</Yield>
    		</Row>
    	</Building_YieldChanges>
    	<Language_en_US>
    		<Row Tag="TXT_KEY_BUILDING_YOUR_DUMMY">
    			<Text>Give Your Dummy A Name</Text>
    		</Row>
    	</Language_en_US>
    </GameData>
  3. The lua is written to that it will grab all buildings within the game's database that have effects registered within the following xml-tables:
    • Building_YieldChangesPerPop
    • Building_YieldModifiers
      This should cover all the standard 'science' buildings within the game, as well as any mod-added buildings that have effects within these two tables. So Libraries, Paper Makers, Universities, Wats, Public Schools, and Research Labs will all be covered, as well as anything that might be added by mods such as Enlightenment Era.
  4. You can make the lua account for anything else that might be in the Building_AreaYieldModifiers and Building_GlobalYieldModifiers tables by changing this line:
    Code:
    local bAddGlobalAndAreaYieldModifiers = false
    to
    Code:
    local bAddGlobalAndAreaYieldModifiers = true
  5. You can make the lua account for anything else that might be in the Building_FeatureYieldChanges table by changing this line:
    Code:
    local bAddFeatureYieldChanges = false
    to
    Code:
    local bAddFeatureYieldChanges = true
    Within the stock game's buildings, anything that is related to Science within this table is already handled by the Building_YieldModifiers table.
  6. You don't need to worry about Paper Makers or Wats getting accounted for by this code. Even though they will be added to the buildings the code will 'count', unless your civ can construct or purchase these unique buildings, none of your cities will ever have a Paper Maker or a Wat. It is simpler to let the code add them to the list of buildings to look for, and then let the code never find them in a city, than it is to "special-handle" all possible versions of a Library, or a University.
  7. Within the lua script, you will need to change "BUILDING_YOUR_DUMMY", "BUILDING_YOUR_UNIQUE_BUILDING", and "CIVILIZATION_YOUR_CIVILIZATION_NAME" to the correct appropriate info for your mod.
    • I would still rename "BUILDING_YOUR_DUMMY" to something a bit more unique even though the dummy building code uses the "BUILDING_YOUR_DUMMY" name. Change it in the xml and then make the lua look for the correct building name.
Lua Code:
Spoiler :
Code:
local iDummyBuilding = GameInfoTypes.BUILDING_YOUR_DUMMY
local iCivUniqueBuilding = GameInfoTypes.BUILDING_YOUR_UNIQUE_BUILDING
local iRequiredCivilization = GameInfoTypes.CIVILIZATION_YOUR_CIVILIZATION_NAME
local bAddGlobalAndAreaYieldModifiers = false
local bAddFeatureYieldChanges = false

-------------------------------------------------------------------------------------------------------
--DON'T CHANGE BELOW THIS LINE
-------------------------------------------------------------------------------------------------------

local tScienceBuildings = {}
for row in GameInfo.Building_YieldChangesPerPop("YieldType='YIELD_SCIENCE'") do
	if not tScienceBuildings[row.BuildingType] then
		tScienceBuildings[row.BuildingType] = GameInfoTypes[row.BuildingType]
	end
end
for row in GameInfo.Building_YieldModifiers("YieldType='YIELD_SCIENCE'") do
	if not tScienceBuildings[row.BuildingType] then
		tScienceBuildings[row.BuildingType] = GameInfoTypes[row.BuildingType]
	end
end
if bAddGlobalAndAreaYieldModifiers then
	for row in GameInfo.Building_AreaYieldModifiers("YieldType='YIELD_SCIENCE'") do
		if not tScienceBuildings[row.BuildingType] then
			tScienceBuildings[row.BuildingType] = GameInfoTypes[row.BuildingType]
		end
	end
	for row in GameInfo.Building_GlobalYieldModifiers("YieldType='YIELD_SCIENCE'") do
		if not tScienceBuildings[row.BuildingType] then
			tScienceBuildings[row.BuildingType] = GameInfoTypes[row.BuildingType]
		end
	end
end
if bAddFeatureYieldChanges then
	for row in GameInfo.Building_FeatureYieldChanges("YieldType='YIELD_SCIENCE'") do
		if not tScienceBuildings[row.BuildingType] then
			tScienceBuildings[row.BuildingType] = GameInfoTypes[row.BuildingType]
		end
	end
end
function GetNumberBuildingsInCity(pCity, tTable)
	local iNumBuildingsPresent = 0
	for Item,BuildingID in pairs(tTable) do
		if pCity:IsHasBuilding(BuildingID) then
			iNumBuildingsPresent = iNumBuildingsPresent + 1
		end 
	end
	return iNumBuildingsPresent
end
function UniqueBuilding_ScienceBuildingExtraYields(iPlayer)
	local pPlayer = Players[iPlayer]
	if pPlayer:GetCivilizationType() == iRequiredCivilization then
		if pPlayer:CountNumBuildings(iCivUniqueBuilding) > 0 then
			for pCity in pPlayer:Cities() do
				if pCity:IsHasBuilding(iCivUniqueBuilding) then
					pCity:SetNumRealBuilding(iDummyBuilding, GetNumberBuildingsInCity(pCity, tScienceBuildings))
				else
					pCity:SetNumRealBuilding(iDummyBuilding, 0)
				end
			end
		end
	end
end
function BuildingPurchasedOrConstructed(iPlayer, cityId, buildingType, bGold, bFaithOrCulture)
	if buildingType == iCivUniqueBuilding then
		local pPlayer = Players[iPlayer]
		if pPlayer:GetCivilizationType() == iRequiredCivilization then
			local pCity = pPlayer:GetCityByID(cityId);
			pCity:SetNumRealBuilding(iDummyBuilding, GetNumberBuildingsInCity(pCity, tScienceBuildings))
		end
	end
end
------------------------------------------------------------
---- WilliamHoward's IsCivInPlay
------------------------------------------------------------
function IsCivInPlay(iCivType)
  for iSlot = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
    local iSlotStatus = PreGame.GetSlotStatus(iSlot)
    if (iSlotStatus == SlotStatus.SS_TAKEN or iSlotStatus == SlotStatus.SS_COMPUTER) then
      if (PreGame.GetCivilization(iSlot) == iCivType) then
        return true
      end
    end
  end
  
  return false
end
------------------------------------------------------------
---- Game Event Hooks
------------------------------------------------------------
if IsCivInPlay(iRequiredCivilization) then
	GameEvents.CityConstructed.Add(BuildingPurchasedOrConstructed)
	GameEvents.PlayerDoTurn.Add(UniqueBuilding_ScienceBuildingExtraYields)
end
 
Thanks this is doing what I wanted. One very minor thing I noticed is that if you lose your Capital and the city that gains the palace and has the unique building will grant the +2 Gold since the Palace generates science. Very minor thing and it doesn't really matter.
 
Thanks this is doing what I wanted. One very minor thing I noticed is that if you lose your Capital and the city that gains the palace and has the unique building will grant the +2 Gold since the Palace generates science. Very minor thing and it doesn't really matter.
I don't see how this could be happening unless the Palace is being changed by a mod to make it give science via either of <Building_YieldChangesPerPop> or <Building_YieldModifiers>.

Are you sure it isn't a city with the National College? National College qualifies as a "Science" building under the definition of the way it is being used in the lua-code.

The Palace generates science via <Building_YieldChanges>, which the lua-script is specifically not looking at.
 
I don't see how this could be happening unless the Palace is being changed by a mod to make it give science via either of <Building_YieldChangesPerPop> or <Building_YieldModifiers>.

Are you sure it isn't a city with the National College? National College qualifies as a "Science" building under the definition of the way it is being used in the lua-code.

The Palace generates science via <Building_YieldChanges>, which the lua-script is specifically not looking at.

That's true, I don't actually know what caused it then, the Nation College wasn't built I had only the Unique in both cities plus and a library and university in the capital. I'll test it again later and see if I can figure out what was going on.
 
Is it possible to modify the Faith purchase cost of a specific unit? I want to make a civ get a Faith discount on ONLY Great Artists.

If this isn't possible in a relatively easy manner, may I please have some code for a promotion that would allow Missionaries to grant the capital a scaling amount of Great Artist points whenever they spread religion?
 
Hi, in LUA only, is there a way to tell a barbarian unit to aggro a city, a plot, an area, something to make them not run away right after you spawn them? (thinking about it I could give them the "cant go into forests and so on promotions, just to close their options worst case scenario)

I dont mind if they suicide on the city, just want them to give some grief, not just go away attack someone else
 
You should be able to achieve the effect by using
Code:
Players[63]:AddTemporaryDominanceZone (iX, iY)
as it's what the Firaxis scenarios use when setting up attacks
 
Back
Top Bottom