Yes, I think I may have. Trying to jog my memory, but it's very possible.Thanks. Did you happen to try the leader bonus code using 'General' as a rank, and then change it later? If so, then I've recreated your error and can fix it.
Yes, I think I may have. Trying to jog my memory, but it's very possible.Thanks. Did you happen to try the leader bonus code using 'General' as a rank, and then change it later? If so, then I've recreated your error and can fix it.
Well, try this replacement file. You should get a message that the "general" rank has been removed when you load the game. Let me know if you still generate errors.Yes, I think I may have. Trying to jog my memory, but it's very possible.
This works, Prof.! And I got the message, as well. Brilliant. Many thanks!Well, try this replacement file. You should get a message that the "general" rank has been removed when you load the game. Let me know if you still generate errors.
cityObject.shields = cityObject.shields + 8
local cityData = require("cityData")
-- A counter for the bonus shields that a city receives each turn.
--Default is 0, and minimum number is 0, no maximum number.
cityData.defineCounter("bonusShields",0,0)
-- A counter for the number of turns during which extra shields will be
-- received. Default is 0, minimum is 0, no maximum.
-- This counter will be decremented manually each turn, during the
-- onCityProduction event, and when it reaches 0, the bonusShields
-- counter will be reset to 0.
cityData.defineCounter("remainingTurnsForBonusShields",0,0)
-- bonus decrementing event.
discreteEvents.onCityProcessingComplete(function (turn, tribe)
for city in civ.iterateCities() do
if city.owner == tribe then
if cityData.counterGetValue(city,"remainingTurnsForBonusShields") > 0 then
cityData.counterSubtract(city,"remainingTurnsForBonusShields",1)
end
if cityData.get(city,"remainingTurnsForBonusShields") == 0 then
-- you may wish to add a message here, to draw
-- attention to the fact that the city's prodction
-- has changed.
cityData.counterReset(city,"bonusShields")
cityData.counterReset(city,"remainingTurnsForBonusShields")
end
end
end
end)
-- line for MechanicsFiles\calculateCityYield.lua
-- to be placed after the line
-- local shieldChangeAfterWaste = 0
shieldChangeAfterWaste = shieldChangeAfterWaste + cityData.counterGetValue(city,"bonusShields")
local shieldChangeAfterWaste = 0
---Adds a bonus to the city's shield production for a number of turns.
---If the city already has a bonus, the new bonus replaces the old one.
---@param city cityObject
---@param bonus integer
---@param turns integer
local function bestowShieldBonus(city,bonus,turns)
cityData.counterSetValue(city,"bonusShields",bonus)
cityData.counterSetValue(city,"remainingTurnsForBonusShields",turns)
end
function(nearestFriendlyCity)
bestCitySoFar.cityObject.shields = bestCitySoFar.cityObject.shields + 8
local function nearestFriendlyCity(tile,tribe)
local bestCity = nil
local bestDistance = 1000000
for city in civ.iterateCities() do
if city.owner == tribe then
local distance = gen.distance(city.location,tile)
if distance < bestDistance then
bestCity = city
bestDistance = distance
end
end
end
return bestCity
end
local function addShieldsToNearestCity(tile,tribe,shields)
local city = nearestFriendlyCity(tile,tribe)
if city then
city.shields = city.shields + shields
-- could also do something with bestowShieldBonus
end
end
addShieldsToNearestCity(winner.location,winner.owner,8)
discreteEvents.onEnterTile(function (unit, previousTile, previousDomainSpec)
if math.random() < 0.67 then
if unit == unitAliases.Shepherd and unit.location.terrainType == 0 then do
addFoodToNearestCity(unit.location,unit.owner,10)
end
end
end
end)
If you define 2 functions with the same name in the same file, only the last one will work. (Unless you use the first one outside of a function before the second one is defined.) I'd have to see the code to know what was wrong.This is great Prof, thanks. The last bit worked well. For some reason it messed with my nearestFriendlyCity local function. It had an issue with "tileB." So I removed those two parts, and it works great even without tileB. It has found the nearest city and added shields without flaw, yet. That's curious, though.
The lineFor the first code you posted, the first three lines seem to need to be in the cityYield lua file near the top.
local cityData = require("cityData")
Here is my latest. I tried this and a few iterations. How does the onEnterTile function work? I'm trying to enable this unit to have a chance of addFood when it enters certain terrain types.
No console error, just nothing happening. (I defined the addFoodToNearestCity earlier, and it works with other functions! So that's been cool.)
unit == unitAliases.Shepherd
unit.type == unitAliases.Shepherd
if unit == unitAliases.Shepherd and unit.location.terrainType == 0 then do
addFoodToNearestCity(unit.location,unit.owner,10)
end
end
if unit.type == unitAliases.Shepherd and unit.location.terrainType == 0 then
addFoodToNearestCity(unit.location,unit.owner,10)
end
local FirstChoice = civ.ui.loadImage("Images/firstchoice.bmp")
discreteEvents.onCityFounded(function(city)
gen.justOnce("FirstChoice",function()
local choice = nil
if city.owner.isHuman then
local dialog = civ.ui.createDialog()
dialog.title = "Your first choice..."
dialog.width = 500
dialog:addImage(FirstChoice)
local multiLineText = "You have unified several nomadic tribes in the vicinity, and now seek to settle down.\n^ \n^Your people have many talents. As you settle down, what would you like to focus on?"
text.addMultiLineTextToDialog(multiLineText,dialog)
dialog:addOption("We will need more food in the coming years.", 1)
dialog:addOption("Ore and timber are of the utmost importance.", 2)
choice = dialog:show()
else
choice = math.random(1,2)
end
if choice == 1 then
gen.createUnit(unitAliases.Shepherd,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
elseif choice == 2 then
gen.createUnit(unitAliases.Ranger,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
end
end)
end)
gen.justOnce makes sure that the enclosed function (2nd argument) is run only once per game. This is determined by the first key, in this instance, "FirstChoice". Once gen.justOnce has been executed for the "FirstChoice" key, the "FirstChoice" is stored in a table, and so gen.justOnce will never execute again when the first argument is "FirstChoice", even if the second argument is a different function in a different part of code. If you want this to be once per tribe, the way to do it is to have a different key per tribe, like this:gen.justOnce("FirstChoice",function()
gen.justOnce("FirstChoice"..tostring(city.owner.id),function()
I'd like to verify that the scenario template is active in my ToTPP mod, but I'm having trouble accessing the Lua console. I'm running ToT in Wineskin on macOS. I've tried Ctrl+Shift+(Fn+)F3 and Cmd+Shift+(Fn+)F3 in cheat mode. Neither seems to have any effect
Is there another way to access it, such as through a menu?
I'm on ToTPP 0.18.4
You can use tile.river to place/remove rivers. My Lua lessons were written before TNO gave us that functionality.How does the system code rivers, and how would it revert them back?
I'm not entirely sure what you want to do, but perhaps these functions will help you:Quick question: How do I draw rivers into a function, if they are not a terrain object?
E.g., if I wanted to register river base terrain and all adjacent base terrains to rivers (excluding ocean), and then morph those terrain for, say, X# of turns, and then morph them back to their original terrain. (but keeping the rivers on top of their own terrain)
How does the system code rivers, and how would it revert them back?
local tileData = require("tileData")
tileData.defineCounter("originalBaseTerrainID",-1)
local function riverNearby(tile)
if tile.river then
return true
end
for _,adjacentTile in pairs(gen.getAdjacentTiles(tile)) do
if adjacentTile.river then
return true
end
end
return false
end
local newTerrain = civ.getBaseTerrain(0,0)
local function changeRiverNeighbours()
for tile in civ.iterateTiles() do
if riverNearby then
tileData.counterSetValue(tile,"originalBaseTerrainType",tile.baseTerrain.type)
tile.baseTerrain = newTerrain
end
end
end
local function restoreRiverTerrain()
for tile in civ.iterateTiles() do
if not tileData.counterIsNil(tile,"originalBaseTerrainID") then
local baseTerrainType = tileData.counterGetValue(tile,"originalBaseTerrainID")
tile.baseTerrain = civ.getBaseTerrain(tile.z,baseTerrainType)
tileData.counterReset(tile,"originalBaseTerrainID")
end
end
end
discreteEvents.onEnterTile(function (unit, previousTile, previousDomainSpec)
if math.random() < 0.25 then
if unit.type == unitAliases.Shepherd and unit.location.terrainType == 1 then
addFoodToNearestCity(unit.location,unit.owner,shepherdFoodTable[math.random()])
if unit.owner.isHuman then
civ.playSound("Food.wav")
end
end
end
if math.random() < 0.25 then
if unit.type == unitAliases.Shepherd and unit.location.terrainType == 0 then
addFoodToNearestCity(unit.location,unit.owner,shepherdFoodTable[math.random()])
if unit.owner.isHuman then
civ.playSound("Food.wav")
end
end
end
if math.random() < 0.25 then
if unit.type == unitAliases.Ranger and unit.location.terrainType == 3 then
addShieldsToNearestCity(unit.location,unit.owner,rangerShieldsTable[math.random()])
if unit.owner.isHuman then
civ.playSound("Production.wav")
end
end
end
if math.random() < 0.25 then
if unit.type == unitAliases.Ranger and unit.location.terrainType == 4 then
addShieldsToNearestCity(unit.location,unit.owner,rangerShieldsTable[math.random()])
if unit.owner.isHuman then
civ.playSound("Production.wav")
end
end
end
if math.random() < 0.25 then
if unit.type == unitAliases.Statesman1 and unit.location.improvements then
unit.owner.money = unit.owner.money + titheTable[math.random()]
end
end
end)
Have you called the function civ.scen.onActivateUnit anywhere? That function is only supposed to be called once, and onEnterTile works by using the call I defined in events.lua (and doing some other stuff I won't get into). If you called civ.scen.onActivateUnit, that would erase the other function registered to it.Here is something strange. This code I wrote was working really well earlier today, and now it isn't. No errors, just nothing happening. I tried parsing them into their own discreteEvent, but that also did not work.
That did it! And then where I had the civ.scen.onActivateUnit, I replaced with a discreteEvent, which covered my tracks. Now all is well. Thank you!Have you called the function civ.scen.onActivateUnit anywhere? That function is only supposed to be called once, and onEnterTile works by using the call I defined in events.lua (and doing some other stuff I won't get into). If you called civ.scen.onActivateUnit, that would erase the other function registered to it.
If you haven't done this, I'd try putting in some print statements to check if the code is being called. You may simply have been a bit unlucky.