[TOTPP] Lua Scenario Template

Sorry, it's me again @Prof. Garfield :)
Currently lua shows an error when I'm trying to move a naval unit. I'm using your latest lua template.
1661430266359.png
 
I believe this is the fix. I've updated the Template with this and a fix for gen.placePollutionForce, which @Pablostuka reported to me.
 

Attachments

Hello @Prof. Garfield,

would it be possible that the name of a city only changes if a certain group of conquerers captured the city? For example, I would like to change the name of the city 'Shekatika' to 'Ft. Hope' but only if the European civs capture the city.
I tried to use this code but unfortunatelly it didn't work. If the Mesoamericans captured the city, the name changed too.

Code:
if city == object.cShekatika and (object.pFrench.isHuman == false or object.pFrench.isHuman == true or object.pSpanishHabsburgEmpire.isHuman == false or object.pSpanishHabsburgEmpire.isHuman == true or
object.pIndependentNations.isHuman == false or object.pIndependentNations.isHuman == true or object.pProtestantLeague.isHuman == false or object.pProtestantLeague.isHuman == true) and defender == object.pRebels then
    gen.justOnce("Shekatika conquered",function ()
    object.cShekatika.name = "Ft. Hope"
    end)  
end
 
The problem here is that you're not checking if the city's new owner is European. Instead, you're checking if any of the European tribes are controlled either by the AI or by a Human. This will always be true. Use city.owner to check if the just captured city is now owned by a European tribe:

Code:
if city == object.cShekatika and (city.owner == object.pFrench or 
    city.owner == object.pSpanishHabsburgEmpire or 
    city.owner == object.pIndependentNations or 
    city.owner == object.pProtestantLeague) and defender == object.pRebels then
    gen.justOnce("Shekatika conquered",function ()
    object.cShekatika.name = "Ft. Hope"
    end)  
end
 
The problem here is that you're not checking if the city's new owner is European. Instead, you're checking if any of the European tribes are controlled either by the AI or by a Human. This will always be true. Use city.owner to check if the just captured city is now owned by a European tribe:

Code:
if city == object.cShekatika and (city.owner == object.pFrench or
    city.owner == object.pSpanishHabsburgEmpire or
    city.owner == object.pIndependentNations or
    city.owner == object.pProtestantLeague) and defender == object.pRebels then
    gen.justOnce("Shekatika conquered",function ()
    object.cShekatika.name = "Ft. Hope"
    end) 
end
Many thanks, this code works perfect
 
@Prof. Garfield, I would like to ask you for another support for a lua code.
I've several cities in the Caribbean Sea, which can be attacked by Barbarian Pirate Ships. Everytime, when the attack of the Barbarian vessel is successfully, the game tooks a certain amount of money from the players treasury.
I'm currently using this lua code for the event. Now I only have the problem, that the event only fires if the mentioned units in the lua code are defeated. Is it possible to use a code, which includes all player units as a whole?
Code:
if object.pSpanishHabsburgEmpire.isHuman == true and (loser.type == object.uTownMilitias or loser.type == object.uSpanishPikemen or loser.type == object.uSpanishPikemenI) and loserLocation == object.lSpecialPikemenTile
and winner.type == object.uPirateShip and winner.owner == object.pRebels then
    civ.ui.text("Pirates have made an raid on Havana and plundered gold worth of 200 ducats.")
    object.pSpanishHabsburgEmpire.money = object.pSpanishHabsburgEmpire.money - 200
 
Is it possible to use a code, which includes all player units as a whole?
Remove the check for the individual unit types, that is, remove
Code:
and (loser.type == object.uTownMilitias or loser.type == object.uSpanishPikemen or loser.type == object.uSpanishPikemenI)
In Lua, if you want something to happen for every unit type (or city, or whatever), all you do is not make a check for that unit type when specifying the conditions of the event.
 
@Prof. Garfield sorry again, the lua console shows me the following message:
1661885428489.jpeg


I tried a test with your piracy module you wrote some times ago for me and everytime when I try to enter the Barbary zone with a ship, lua shows me this error message.
If it would be ok for you I would like to send you my latest scenario files.
 
Check these two tables, and make sure that every unit type in corsairHealthPenalty also has an entry in corsairMaxDamage.

Code:
-- corsairHealthPenalty[unitType.id] = health penalty for unitType in the Corsair zone per turn
local corsairHealthPenalty = {
    [object.uCaravel.id] = 2,
    [object.uCarrack.id] = 3,
}

-- corsairMaxDamage[unitType.id] = the corsair health penalty won't lower 
-- unitTypes's health below this amount
local corsairMaxDamage = {
    [object.uCaravel.id] = math.floor(0.5*object.uCaravel.hitpoints), -- max 50% damage
    [object.uCarrack.id] = math.floor(0.33*object.uCarrack.hitpoints), -- max 33% damage, subject to rounding
}

The error says "attempt to compare number with nil", which means there is a comparison (>,>=,<,<=) between a number and a nil value. In the code I sent you,
Code:
        if unit.damage < corsairMaxDamage[unit.type.id] then
is at line 294, which could be 301 in your version if you've added some info to the tables. The code I wrote only checks if the unitType is in corsairHealthPenalty, so I'm guessing that corsairMaxDamage[unit.type.id] is nil, and therefore causing the error. If this isn't the cause of the error, please send me your version of the code, so I can see what line is triggering the error.
 
Admittedly this is a massive project and one that I haven't kept abreast on the past month or two, so apologies if I missed this.

One thing I would believe all scenario designers would love to have in terms of functionality would be the ability to toggle the behaviors of barracks, ports, and airports:

Default: Produces veteran units, repairs units that spend a turn in the city.
Desired Functionality: Can modify so that either of these effects (or both, though I don't know why someone would want to do that) of these effects can be disabled.

Business Case: Many scenarios forgo the use of barracks arguing that veterancy should be earned in combat. I agree with this for certain scenarios, but would like to retain the repair capacity. With ports especially it makes sense as coaling stations and naval bases have always been important. Just look at what's going on with the controversy over the Solomon Islands right now.

Airports have the added functionality of air lifts. Not sure if that can be disabled or not and perhaps it is beyond the scope, but disabling this would be beneficial to certain scenarios where it really doesn't make sense.

Likewise, adding the functionality to quickly move units between cities that have ports, or adding functionality to quickly move units between barracks (or another improvement) that have a land link would also be immensely helpful.

Anyway, I thought these would be useful and perhaps you've already included them and I simply missed it. If not, I think these are functions you'd see most if not all scenario designers appreciate.
 
One thing I would believe all scenario designers would love to have in terms of functionality would be the ability to toggle the behaviors of barracks, ports, and airports:

Default: Produces veteran units, repairs units that spend a turn in the city.
Desired Functionality: Can modify so that either of these effects (or both, though I don't know why someone would want to do that) of these effects can be disabled.

Business Case: Many scenarios forgo the use of barracks arguing that veterancy should be earned in combat. I agree with this for certain scenarios, but would like to retain the repair capacity. With ports especially it makes sense as coaling stations and naval bases have always been important. Just look at what's going on with the controversy over the Solomon Islands right now.
At the moment, the LST rules extension can eliminate (or reduce the chance of) veteran unit production from the barracks/port/airport. It can also add a chance for up to 2 other buildings, so if you want the veteran status, but not the healing, you could designate a different improvement as the barracks/port/airport.

Airports have the added functionality of air lifts. Not sure if that can be disabled or not and perhaps it is beyond the scope, but disabling this would be beneficial to certain scenarios where it really doesn't make sense.
Disabling airlifts is a straightforward event. Just go through every city periodically, and flip the "already conducted airlift" bit. I can see the value in adding this to simpleSettings.lua.
Likewise, adding the functionality to quickly move units between cities that have ports, or adding functionality to quickly move units between barracks (or another improvement) that have a land link would also be immensely helpful.
This was done with OTR trainlift, and I think the hard part was pathfinding, not the basic functionality.
 
At the moment, the LST rules extension can eliminate (or reduce the chance of) veteran unit production from the barracks/port/airport. It can also add a chance for up to 2 other buildings, so if you want the veteran status, but not the healing, you could designate a different improvement as the barracks/port/airport.

I apologize but I'm not sure what the LST rules extension is? Sorry for the dumb question, but glad to hear this is already completed!
 
The Lua Scenario Template has been updated.

New Features

Land and Sea units will now abide by range restrictions in the rules.txt if they are set above 0. (or, if the unit type range is changed after the fact in Lua) There is a line in simpleSettings.lua to enable this. By default, units restore their range in cities and airbases, but this can be changed with a function. This has only been tested for human players, and the AI does not have the restrictions unless specifically enabled.

A "radar" feature can be enabled in radarSettings.lua. The player's map (but not the underlying terrain) is given terrain improvements to "mark" radar contacts. (This marking feature is in the generalLibrary for other uses if desired.) The radar system has 2 separate classes "air" and "surface", but they don't actually have to distinguish between air units and surface units. There are more details in radarSettings.lua, and I can provide extra explanations if desired.

There is a new "execution point" implemented, onFinalOrderGiven(unit), which activates when the active unit changes, and the previously active unit is noted to no longer have any available movement points.

Other New Stuff

A notable new general library function is
Code:
-- gen.spendMovementPoints(unit,points,multiplier=totpp.movementMultipliers.aggregate) -> void
-- increases the expended movement points of the unit
-- by default, full unit movement points are used, but a different multiplier can be specified
-- e.g. 1 if you want to spend atomic movement points
-- If the unit has a range (either natural or through the land and sea extension) and
-- uses up all its movement for the current turn, its domainSpec is incremented by 1
-- and the unit is killed if it is out of range.
-- if points is negative, movement is restored to the unit
-- if points is a fraction, math.floor(points*multiplier) is used
-- final move spent is bound between 0 and 255
The main reason for writing it was to automatically handle domainSpec changes for units with ranges (which was also why I implemented range for land and sea in the middle of my radar work).

CTRL+SHIFT+F4 now activates a menu for most of the scripts associated with the template, such as the object.lua builder and the polygonScript. I deliberately left out the copyGamePieces.lua script, since you have to use the console for the second half of the procedure anyway.

Let me know if you run into trouble (there's probably something I forgot to test), or if you want to integrate a new feature into an existing scenario.
 
Updated text.lua with some functions suggested (and a few fully implemented) by @Pablostuka.

-- text.lpad(str,length,character) --> string | By Pablostuka
-- pad "character" to the left of string "str" to max of "lenght" by Pablostuka

-- text.rpad(str,length,character) --> string | By Pablostuka
-- pad "character" to the right of string "str" to max of "lenght"

-- text.pad(str,length,character) --> string | By Pablostuka
-- pad "character" on both sides of string "str" to max of "lenght"

-- text.international(string) --> string | inspired by Pablostuka,
-- text.i(string) --> string (alias for text.international)
-- substitutes extended ascii characters for the correct character
-- (I'm pretty sure this is a formatting issue, where the text editor
-- shows an extended ascii character, but records it as 2 characters,
-- so a formatting change might also be effective, but this is still
-- likely to be a quick fix in many circumstances)

-- text.upper(string) --> string
-- Makes string uppercase, including uppercasing the international characters
-- from the extended ASCII table
-- if you don't use international characters, string.upper is fine


-- text.lower(string) --> string
-- Makes string lowercase, including lowercasing the international characters
-- from the extended ASCII table
-- if you don't use international characters, string.lower is fine


-- text.iUpper(string) --> string
-- fixes international characters and makes string upper case

-- text.iLower(string) --> string
-- fixes international characters and makes string lower case

Many of these deal with non-English characters discussed here. text.international (text.i for short) deals with a formatting issue for some text editors. It seems that special characters are sometimes saved as 2 characters but shown as the single special character by the text editor. text.international converts those pairs of characters to the single correct character when the script is loaded (assuming all text editors behave the same way as mine). This function may be more convenient than a format change, and will certainly be easier to explain as a fix.

The text.lower and text.upper functions do the same thing as string.lower and string.upper, but also capitalise or lowercase the non-English special characters. text.iLower, and text.iUpper internationalise and upper/lower the string in one function, which some people may find useful.
 
Back
Top Bottom