Under the Comanche Moon (dev thread)

This is for peace treaties. If I set a flag ("6 month peace treaty,") how do I set a timer on the flag, so that the peace treaty is cancelled after 6 turns?
You could use a delayed action for 6 turns into the future to cancel the peace treaty.

Or, you could use a counter from the data module in a way similar to how you "retired" units in your last mod.

You may also want to use diplomacy.disableEndogenousTreatyChanges to stop the treaty from being cancelled early.
 
For "unit.location.baseTerrain.type", how do I log whether or not a tile has a resource (specifically, resource 2)?
I tried (0,15,2), but that did not work.
 
For "unit.location.baseTerrain.type", how do I log whether or not a tile has a resource (specifically, resource 2)?
I tried (0,15,2), but that did not work.
The terrainObject has information about the resource, the baseTerrainObject doesn't.

unit.location.terrain will give the terrain object. terrain.type is the same as baseTerrain.type, but the terrainObject also has terrain.resource. You can make two checks, or you can use

Code:
unit.location.terrain == civ.getTerrain(0,15,2)

Let me know if you need more explanation.
 
You could use a delayed action for 6 turns into the future to cancel the peace treaty.

Or, you could use a counter from the data module in a way similar to how you "retired" units in your last mod.

You may also want to use diplomacy.disableEndogenousTreatyChanges to stop the treaty from being cancelled early.

In my onUnitDefeated.lua, I tried this code. Not getting an error, but the effects I want after 6 turns are not launching:

Spoiler :
Code:
    -- City raided (Mexico)
    
        if loser.type == unitAliases.City and loser.owner == civ.getTribe(4) then
            loser.location.terrainType = 6
            local newDisorder = nearestMexicanCity(winner.location,civ.getTribe(4))
            gen.setCivilDisorder(newDisorder)
            local newCityFire = civ.createUnit(unitAliases.Fire,civ.getTribe(4),loser.location)
                unitData.counterSetValue(newCityFire,"restoredMexicanCityTurn",civ.getTurn()+6)
            civ.ui.text("We have raided "..newDisorder.name..", Chief. Our braves ran wild in the streets, looting what they could.")
            winner.owner.money = winner.owner.money +cityRaidHorsesTable[math.random()]
            winner.moveSpent = 255
            data.counterAdd("MexicoAnger",2)
        end
                    for unit in civ.iterateUnits() do
                        local turn = civ.getTurn()
                            if unit.type == unitAliases.Fire and unitData.counterGetValue(unit,"restoredMexicanCityTurn") <= turn then
                                civ.createUnit(unitAliases.City,civ.getTribe(4),unit.location)
                                civ.createUnit(unitAliases.MexMilitia,civ.getTribe(4),unit.location)
                                civ.createUnit(unitAliases.MexSoldiers,civ.getTribe(4),unit.location)
                                gen.killUnit(unit)
                            end
                    end
 
The terrainObject has information about the resource, the baseTerrainObject doesn't.

unit.location.terrain will give the terrain object. terrain.type is the same as baseTerrain.type, but the terrainObject also has terrain.resource. You can make two checks, or you can use

Code:
unit.location.terrain == civ.getTerrain(0,15,2)

Let me know if you need more explanation.
Very clear, thank you!
 
Did you put this section of code within the unitKilled event?
Code:
                    for unit in civ.iterateUnits() do
                        local turn = civ.getTurn()
                            if unit.type == unitAliases.Fire and unitData.counterGetValue(unit,"restoredMexicanCityTurn") <= turn then
                                civ.createUnit(unitAliases.City,civ.getTribe(4),unit.location)
                                civ.createUnit(unitAliases.MexMilitia,civ.getTribe(4),unit.location)
                                civ.createUnit(unitAliases.MexSoldiers,civ.getTribe(4),unit.location)
                                gen.killUnit(unit)
                            end
                    end
If so, the city won't be restored until a unit is killed after the six turns have passed. You should put this section of code in one of onTurn/onTribeTurnBegin/onCityProcessingComplete/onTribeTurnEnds.
 
Did you put this section of code within the unitKilled event?
Code:
                    for unit in civ.iterateUnits() do
                        local turn = civ.getTurn()
                            if unit.type == unitAliases.Fire and unitData.counterGetValue(unit,"restoredMexicanCityTurn") <= turn then
                                civ.createUnit(unitAliases.City,civ.getTribe(4),unit.location)
                                civ.createUnit(unitAliases.MexMilitia,civ.getTribe(4),unit.location)
                                civ.createUnit(unitAliases.MexSoldiers,civ.getTribe(4),unit.location)
                                gen.killUnit(unit)
                            end
                    end
If so, the city won't be restored until a unit is killed after the six turns have passed. You should put this section of code in one of onTurn/onTribeTurnBegin/onCityProcessingComplete/onTribeTurnEnds.
Aha, got it. I created a new discreteEvent referencing one of those, and it works perfectly now! Thank you!
 
Full of Qs today! Really chipping away at this thing.

I made a keyPress to bring up various counters that the player can see throughout the game. I waffled behind keeping things like "Anger" and "Relations" on the back end, but thought it would be great to show the player so they can devise strategies. It also represents rumors on the trails.

Now I am wanting something in between. Instead of showing a # next to, say, "Texas Relations," is there any way to define a descriptive word (e.g., through a table?) to show up if, say, "Texas Relations" is "5" or "10" or "20"? (So replace "5" with words, for example.)
 
I'd suggest using a threshold table to store strings which translate attitudes.

Then you'd do something like
Code:
message = " The "..tribe.name.." are "..attitudeTranslater[tribeData.counterGetValue(tribe,"attitudeToComanche")].." with us."
Let me know if you need this fleshed out some more.
 
I'd suggest using a threshold table to store strings which translate attitudes.

Then you'd do something like
Code:
message = " The "..tribe.name.." are "..attitudeTranslater[tribeData.counterGetValue(tribe,"attitudeToComanche")].." with us."
Let me know if you need this fleshed out some more.
I wrote something like
Code:
local multiLineText = "Our reputation among trading houses is "..attitudeTranslator[data.counterGetValue("TradeReputation")].."."

What I'm not sure how to do now is to turn the attitudeTranslator into the threshold table.

I tried something like this as a test (very over-simplified at the moment)... way off I assume.

Code:
local attitudeTranslator = gen.makeThresholdTable({
[5] = civ.ui.text("Good")
[0] = civ.ui.text("Bad")
)}
 
Wait! I figured it out.
Removed the "civ.ui.text." Of course. Agh.
Now it works great. :)
 
Is there a way to change the main menu options? I know how to change the text of these options in menu.txt, but not the actual window it brings up. For example, in the above reputation/relations list, could I bring that keypress up if someone also clicks "Advisors -> Foreign Minister"?
 
Is there a way to change the main menu options? I know how to change the text of these options in menu.txt, but not the actual window it brings up. For example, in the above reputation/relations list, could I bring that keypress up if someone also clicks "Advisors -> Foreign Minister"?
No, there isn't a way to tie an event to a menu choice. You'll have to tie it to a key press, and tell the player to press the key.

However, since you're talking about the foreign minister, you might be able to take advantage of the fact that the negotiation execution point to bring it up. The negotiation "event" is run when the human player opens the foreign minister window in order to determine who they can talk to. Use one of those in order to bring up the attitude menu.

Code:
discreteEvents.onNegotiation(function (talker, listener)
    if talker == object.pComanche and listener.id == 1 then
        -- Run attitude code
    end
    
    return true
end)

You might have to be a bit cleverer than this. I think that the game might check twice for some reason.
 
No, there isn't a way to tie an event to a menu choice. You'll have to tie it to a key press, and tell the player to press the key.

However, since you're talking about the foreign minister, you might be able to take advantage of the fact that the negotiation execution point to bring it up. The negotiation "event" is run when the human player opens the foreign minister window in order to determine who they can talk to. Use one of those in order to bring up the attitude menu.

Code:
discreteEvents.onNegotiation(function (talker, listener)
    if talker == object.pComanche and listener.id == 1 then
        -- Run attitude code
    end
   
    return true
end)

You might have to be a bit cleverer than this. I think that the game might check twice for some reason.
This is interesting! I'll see what I can do. I did edit the text of the menu to read "KEYPRESS OPTIONS" and then give a list of options, just for player reference. I've seen this done a few ways. Right now I have a good 5 keypress events that can run, so want to make sure the player doesn't forget one of them. I suppose I could tie them all together into one, and bring up a menu, too.

Unrelated Q: How on earth do I heal units with lua? I've tried unit.hitpoints = unit.hitpoints +XYZ, among other things. Am I missing something with this?
 
Unrelated Q: How on earth do I heal units with lua? I've tried unit.hitpoints = unit.hitpoints +XYZ, among other things. Am I missing something with this?
You change unit.damage. unit.hitpoints is a "get" command for convenience, while unit.damage is "get/set" and can actually be changed.
 
I did try unit.damage = unit.damage -XYZ, but it oddly took the unit's HP down to 1 / near-death.
 
I did try unit.damage = unit.damage -XYZ, but it oddly took the unit's HP down to 1 / near-death.
Try
Code:
unit.damage = math.max(0,unit.damage-XYZ)
You don't want to set to negative damage, since it starts counting back from 255.
 
Two questions coming up, one related to the "255" note:

1. For "moveSpent," how do I reduce 1 or 2 movement points, instead of all or none?

2. Is there any way to totally prevent pillaging?
 
1. For "moveSpent," how do I reduce 1 or 2 movement points, instead of all or none?
Use gen.spendMovementPoints . Or, you can add multiples of totpp.movementMultipliers.aggregate . gen.spendMovementPoints automatically takes things like unit range or the customCosmic module into account.

2. Is there any way to totally prevent pillaging?
I'll have to think about that one. It might be possible to detect if terrain improvements were pillaged and replace them.
 
Use gen.spendMovementPoints . Or, you can add multiples of totpp.movementMultipliers.aggregate . gen.spendMovementPoints automatically takes things like unit range or the customCosmic module into account.


I'll have to think about that one. It might be possible to detect if terrain improvements were pillaged and replace them.
Thanks Prof! The AI is not pillaging, which is good. I suppose I could have a house rule: No "basegame" pillaging! (There are other ways to pillage in this scenario that are more suited to the player.)
 
Top Bottom