Lua request - Jewelry resource upon connecting Gold/Silver/Gems/Copper

Hiram

XML Plebian
Joined
Dec 14, 2006
Messages
1,088
Location
Where The Streets Have No Name
Would anyone be able to make some Lua for me for my Oxus civ? I basically need some code that places a dummy building in a city with improved gold/silver/copper/gems in its limits (dummy building provides a copy of the Jewelry resource - can make this myself).

I'd originally planned to do this with XML but I think it'll work much better with Lua (and result in less stupid comments on workshop, haha)

Thanks!
 
Code:
local iOxusCiv = GameInfoTypes.CIVILIZATION_OXUS
local iOxusPlayer
local iMine = GameInfoTypes.IMPROVEMENT_MINE
local iGold = GameInfoTypes.RESOURCE_GOLD
local iSilver = GameInfoTypes.RESOURCE_SILVER
local iGems = GameInfoTypes.RESOURCE_GEMS
local iCopper = GameInfoTypes.RESOURCE_COPPER
local iDummyBuilding = GameInfoTypes.BUILDING_YOUR_MOD_NAME_DUMMY

local function OnBuildFinished( iPlayerID, x, y, iImprovementID )
	if iImprovementID == iMine and iPlayerID == iOxusPlayer then
		local pPlot = Map.GetPlot(x, y)
		local iResource = pPlot:GetResourceType()
		if iResource == iGold or iResource == iSilver or iResource == iGems or iResource == iCopper then
			local pCity = pPlot:GetWorkingCity()
			if pCity and pCity:GetNumRealBuilding(iDummyBuilding) == 0 then
				pCity:SetNumRealBuilding(iDummyBuilding, 1)
			end
		end
	end
end

for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
	local pPlayer = Players[iPlayer]
	if pPlayer:IsAlive() then and pPlayer:GetCivilizationType() == iOxusCiv then
		iOxusPlayer = iPlayer
		GameEvents.BuildFinished.Add(OnBuildFinished)
		break
	end
end
 
Would that code only work when the plot is being worked, or does Plot:GetWorkingCity() just mean the plot can be worked?
 
Plot:GetWorkingCity() returns pointer to the city that can work the plot.
 
Plot:GetWorkingCity() returns pointer to the city that can work the plot.

What happens if there are two cities that can work that same plot then?
 
  1. Plot:GetWorkingCity()
    • If two or more cities of the same player could work the same plot you get the city that first acquired the plot when no city is working the plot
    • If CityA acquired the plot, but CityB is working the plot, you get CityB
    • As I recall there is some quirky behavior when CityB worked the plot for a time but is no longer working the plot. My imperfect memory is that the method continues to return CityB in this case if no other city is now working the plot.
    • The real problem is when the user is also running a mod that removes the requirement for Mines, etc., to be created on tiles owned by the player (or when you adapt such a method to look at Road, Railroad, Fort, etc., Improvements). Then you have a very great potential to get "nil" for the city.
      • This will not cause the game to refuse your file's contents on game-loading, but it will cause runtime errors, that may or may not cause cascading issues depending on what you are attempting to do with the city-object you expected the method to return.
    • I generally don't use Plot:GetWorkingCity() without first checking that the plot is being worked.
      • If it is not being worked, and I am attempting to do something like this code, I then look for the same player's nearest city, and apply the effect to that city.
  2. BuildFinished is a BNW-only event, so if you were wanting a mod to be compatible to all game-expansions, you cannot use it
  3. The scan-method for running through players active in a game will only give valid data for the 1st such player encountered, and will create "non-implementation" for any players higher in the Players ID qeue than the first such player encountered that is using CIVILIZATION_OXUS.
    • It has become a thing not only to pit AI players against each other, but for people to set up games where every player in the game is Alex, or Catherine, or a Modded Civilization and its leader. Pregame is really the only method that ought to be used in order to be safe, and it ought to be done more like this routine William Howard wrote:
      Code:
      ------------------------------------------------------------
      ---- 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
      JFD has a nearly-identical one he uses.
    • There are also other conditons in which the game can auto-select to use the same civilization more than once for an AI in order to fill the specified number of player slots.
    • The problem with relying on a 'realtime status' when the game is loaded from a save or when starting new game is done is that on a saved reload a player may be 'dead' when the save reloads, but they then may be resurrected. For non-Multiplayer this only applies to an AI, but the method being used will strip the UA away from that AI during whatever portion of Gameplay is conducted after a Civ is resurrected and the next 'SaveGame' and exit is performed.
  4. Other than in very limited cases you want to use the data sent to game events directly by the gamecore within the event arguments. As a general rule you don't want to pre-save the player object and player ID because this leads inevitably to the limitiations mentioned in #3
 
Top Bottom