Also, you mentioned threshold tables before to cycle through a random selection of units. I'd like to learn more about those. Do you have resources you could point to or did you explain this elsewhere you could link to?
Here is my code...
Here is what I said elsewhere:
You could use a
threshold table to determine relative quantities.
Something like this:
Code:
local quantityChanceThresholdTable = gen.makeThresholdTable({
[0.85] = 6, -- 15%
[0.75] = 3, -- 10%
[0.5] = 2, -- 25%
[0.3] = 1, -- 20%
[0] = 0, -- 30
})
local function getQuantity()
return quantityChanceThresholdTable[math.random()]
end
Basically, a regular table only returns a (non-nil) value when the key you put into it is already in the table. The threshold table works by finding the largest index which is less than the submitted key. This can be used to choose between options randomly like shown above.
At the moment, I successfully made a dialog with 7 options, 6 of which will reduce the amount of money one has.
But how do I prevent this option from being shown / prevent it from "going through" if the player or AI does not have enough money for the cost?
Here is one way to do it (untested code). You'll have to fill in the rest of the optionsTable for this to work properly. Make sure you have an option for every index between 1 and 7, otherwise there could be a crash or an infinite loop.
Code:
local optionsTable = {}
optionsTable[1] = {
text = "Gutians (100 gold pieces)",
cost = 100,
unitType = unitAliases.GutianRiders,
}
optionsTable[2] = {
text = "Nabateans (150 gold pieces)",
cost = 150,
unitType = unitAliases.NabateanCamels,
}
optionsTable[7] = {
text = "Do nothing (clears this village for now)",
cost = 0,
unitType = nil,
specialEffect = function(loser,winner)
if winner.owner.isHuman then
civ.ui.text("Mercenaries from this tribe may return in the future.")
end
end,
}
optionsTable[8] = {
text = "Threaten them",
cost = 0,
unitType = nil,
specialEffect = function(loser,winner)
if math.random() < 0.6 then
-- do something with 60% chance
else
-- do something else with remaining 40% chance
end
end,
}
local function doWhenUnitKilled(loser,winner)
if loser.type == unitAliases.Village then
local choice = nil
if winner.owner.isHuman then
local dialog = civ.ui.createDialog()
dialog.title = "Hire Mercenaries"
dialog.width = 500
dialog:addImage(BarbarianCapture)
local multiLineText= "Which mercenaries would you like to hire?"
text.addMultiLineTextToDialog(multiLineText,dialog)
for choiceID,choiceInfo in pairs(optionsTable) do
if winner.owner.money >= choiceInfo.cost then
dialog:addOption(choiceInfo.text,choiceID)
end
end
choice = dialog:show()
else
repeat
choice = math.random(1,#optionsTable)
until winner.owner.money >= optionsTable[choice].cost
end
local choiceInfo = optionsTable[choice]
if choiceInfo and choiceInfo.unitType then
civ.createUnit(choiceInfo.unitType,winner.owner,winner.location)
winner.owner.money = winner.owner.money - choiceInfo.cost
else
if choiceInfo and choiceInfo.specialEffect then
choiceInfo.specialEffect(loser,winner)
end
if winner.owner.isHuman then
civ.ui.text("Mercenaries from this tribe may return in the future.")
end
end
end
end
The code gathers information from the optionsTable (which is a table of tables). This way, we don't have to repeat similar code over and over.
Here, for each option in the optionsTable, the game checks if the winner has enough money, and, if so, creates the option.
Code:
if winner.owner.money >= choiceInfo.cost then
dialog:addOption(choiceInfo.text,choiceID)
end
Here, rather than filtering choices and forcing a single choice among affordable options, I just let the game keep making choices until it chooses one that it can afford.
Code:
repeat
choice = math.random(1,#optionsTable)
until winner.owner.money >= optionsTable[choice].cost
Here, I separate the choice into two cases. The first case is that the choice has a unitType specified in the option, in which case that unit is created. Otherwise, the specialEffect function is run (if it exists).
Code:
local choiceInfo = optionsTable[choice]
if choiceInfo and choiceInfo.unitType then
civ.createUnit(choiceInfo.unitType,winner.owner,winner.location)
winner.owner.money = winner.owner.money - choiceInfo.cost
else
if choiceInfo and choiceInfo.specialEffect then
choiceInfo.specialEffect(loser,winner)
end
end
Note:
Code:
choice = math.random(1,2,3,4,5,6,7)
is the incorrect way to use math.random. math.random() returns a number between 0 and 1. math.random(n) returns an
integer between 1 and n (inclusive). math.random(m,n) returns an
integer between m and n (inclusive). So, your code would just choose an integer between 1 and 2. You should have written math.random(1,7)
I also wanted to add another option that says, "Threaten them!" and then gives a 50/50 chance of a "free unit" or a "hostile unit" ... I know how to add the chance with math.random, for it to do one thing vs do nothing, but don't know how to have it choose between 2 things randomly with a 50/50 chance. If that makes sense.
You can just use an 'else' statement. I didn't do anything here, but the first option has a 60% chance of happening, and the second has 40%. Changing the number changes the odds.
Code:
optionsTable[8] = {
text = "Threaten them",
cost = 0,
unitType = nil,
specialEffect = function(loser,winner)
if math.random() < 0.6 then
-- do something with 60% chance
else
-- do something else with remaining 40% chance
end
end,
}
Let me know if you need more help.