A couple questions

ThichN

Prince
Joined
Aug 15, 2022
Messages
304
Hello, I thought I would post a new thread as I was unsure of where else these questions go. Some of these are lua-related or perhaps lua-adjacent.

Here goes!

1. How do I totally prevent diplomacy in a scenario? @JPetroski did this in the Gallic Wars scenario, wherein you cannot enter diplomatic negotiations with any other tribe. I'd like to do this.

2. In Lua, when I place a city or a unit on the map at exact coordinates, what happens in the event that a unit is already in those coordinates? Will it automatically be displaced and deleted, or should I somehow move the unit?

This is it for now, but thought I'd have this thread going in case more Qs pop up. Many continued thanks to this wonderful community!
 
1. How do I totally prevent diplomacy in a scenario? @JPetroski did this in the Gallic Wars scenario, wherein you cannot enter diplomatic negotiations with any other tribe. I'd like to do this.
In the template, in EventsFiles\onNegotiation.lua, change
Code:
return true
to
Code:
return false
You could do the same thing in consolidatedEvents.lua or discreteEvents.lua (If false is returned for a pair of tribes in any of these situations, the tribes can't negotiate.)

2. In Lua, when I place a city or a unit on the map at exact coordinates, what happens in the event that a unit is already in those coordinates? Will it automatically be displaced and deleted, or should I somehow move the unit?
I'm not sure about placing a city. However, placing a unit depends on how you do it.

If you're using civ.createUnit, the unit will still be created on the tile.

If you're using gen.createUnit, the unit will not be created (unless you use the overrideDefender option).
 
Sort of a solution on my own, but wondering if there is a more elegant way to: stop scientific research from all tribes. My thought now is to use lua to reduce all beakers to 0 every turn. I know you can increase the tech paradigm, but this is not totally helping my issue.
 
Sort of a solution on my own, but wondering if there is a more elegant way to: stop scientific research from all tribes. My thought now is to use lua to reduce all beakers to 0 every turn. I know you can increase the tech paradigm, but this is not totally helping my issue.
I don't have any better idea than removing accumulated beakers periodically. I guess you change the tech group of most techs to something the tribes can't research, and let them just research future tech.
 
@Prof. Garfield
I am having amazing success with the landCargo module, and the keyPress + munitions.
In the munitions file, where it stipulates "canGenerateFunction," I want the munition to not generate unless another unit type is also present in that tile. Is this possible, and if so, how would I write such a line for that part?
 
In the munitions file, where it stipulates "canGenerateFunction," I want the munition to not generate unless another unit type is also present in that tile. Is this possible, and if so, how would I write such a line for that part?
Here is an (untested!!) example for an artillery attack. The artillery unit can only generate a munition if there is an undamaged supply truck on the tile, and the process of generating the munition damages a supply truck.

Note: I don't damage the truck during the canGenerateFunction call, because the unit might fail to generate a munition due to another condition (though that is not possible in this particular example). That's why the generateUnitFunction is used instead of the built in options.

Code:
local function healthySupplyTruckOnTile(unit)
    local tile = unit.location
    for possibleSupplyTruck in tile.units do
        if possibleSupplyTruck.type == object.uSupplyTruck and
            possibleSupplyTruck.damage == 0 then
            return true
        end
    end
    return false
end

-- We must use a generateUnitFunction to damage the
-- supply truck.
local function generateShell(unit)
    for possibleSupplyTruck in unit.location.units do
        if possibleSupplyTruck.type == object.uSupplyTruck and
            possibleSupplyTruck.damage == 0 then
            possibleSupplyTruck.damage = 5
            break
        end
    end
    return gen.createUnit(object.uArtilleryShell,unit.owner,unit.location, {homeCity = nil, veteran = unit.veteran})
end

primaryAttackTable[object.uArtillery.id] = {
    moveCost = 1,
    canGenerateFunction = healthySupplyTruckOnTile,
    generateUnitFunction = generateShell,
    activate = true,
}

Let me know if you have any questions or run into trouble.
 
This worked excellently, @Prof. Garfield . Thank you!
I'm wondering now four questions:

1. How can I register it so that the created munition unit, when created, has already moved? Furthermore, if it is created, and has already moved, could it possibly automatically "sleep," so that when the unit that created it moves, it carries it with it using landCargo?

Example: Archer makes arrows. Does not use the arrow that turn, but wants to use them the next turn ("load" them). When archer moves, it can carry the arrow.

2. Separate from the above, could the unit required (supplyTruck, in your example) then be deleted when the munition is created? (a one-use supply truck)

3. I successfully tested this, as well, using two units required to create a munition (two unit types). Wondering then: what about 2 of the same unit required?

4. Any way to create an error message for generateUnitFunction? (e.g., if the required unit(s) are not present in the tile, it gives a message)
 
1. How can I register it so that the created munition unit, when created, has already moved? Furthermore, if it is created, and has already moved, could it possibly automatically "sleep," so that when the unit that created it moves, it carries it with it using landCargo?
Replace
Code:
return gen.createUnit(object.uArtilleryShell,unit.owner,unit.location, {homeCity = nil, veteran = unit.veteran})
with
Code:
    local munitionList = gen.createUnit(object.uArtilleryShell,unit.owner,unit.location, {homeCity = nil, veteran = unit.veteran})
    for _,munition in pairs(munitionList) do
        munition.moveSpent = 255
        gen.setToSleeping(munition)
    end
    return munitionList
Note: If you're sure you're only going to produce 1 munition, you could just use munitionList[1] instead of pairs.
2. Separate from the above, could the unit required (supplyTruck, in your example) then be deleted when the munition is created? (a one-use supply truck)
Sure, just change the line that damages the truck to one that kills or deletes it. (gen.killUnit/gen.deleteUnit)
3. I successfully tested this, as well, using two units required to create a munition (two unit types). Wondering then: what about 2 of the same unit required?
You'd have to count the number of units of the type on the tile, and return true if there were enough.

4. Any way to create an error message for generateUnitFunction? (e.g., if the required unit(s) are not present in the tile, it gives a message)
Before the canGenerateFunction returns false, create a text box message explaining the missing component.
 
Many thanks! Will look into these and report back. :salute:

Question for all or whoever is reading:
I am having a curious issue in my scenario wherein units past a certain number (in this case, numbers, say, 70-114) are showing up correctly from my units.bmp. Then, however, all units before that revert to either the Original or Fantasy units! Why would the game be reading only certain units from my units.bmp and not others? How is it even reading multiple units.bmp files? Very strange.
 
Why would the game be reading only certain units from my units.bmp and not others?
sprites.

See in rules.txt / @UNITS_ADVANCED :

; G) General flags
; 10000000 override .SPR file for this unit: 1 - don't use .SPR
 
@Prof. Garfield Trucking along on these new options you presented. Very fun indeed!

Another 2 questions: I've successfully gotten a cargo with a movement of 0 to automatically sleep when created, so it follows the land unit. What if, then, I want the land unit to automatically unload / wake up (without the player having to do it) on an airbase? Or does the player always have to automatically "wake" the unit to unload it?

Second, I tried to add a new unload function to the lua file: wherein the unit must be on a specific terrain type to unload. But it didn't work for me. Any ideas?
 
What if, then, I want the land unit to automatically unload / wake up (without the player having to do it) on an airbase? Or does the player always have to automatically "wake" the unit to unload it?
You want the cargo.unloadCargo function, and maybe some others
Code:
local cargo = require("landAirCargo")
cargo.unloadCargo(cargoUnit,carryingUnit)
cargo.isCarriedBy(cargoUnit,possibleCarrier)
cargo.getCarryingUnit(cargoUnit)
I haven't added that documentation to the website yet, so you'll have to look into landAirCargo.lua to get some details. (search for the function name you need) Let me know if you need more help.
Second, I tried to add a new unload function to the lua file: wherein the unit must be on a specific terrain type to unload. But it didn't work for me. Any ideas?
I'm going to need to see what you've tried to get any idea. Note that units can always unload in cities.
 
To landAirCargo.lua, I added:

Code:
function unloadFunctions.unloadTerrain(unit,partnerUnit)
    if unit.location.terrainType == 14 then
        return true
    end
end

...to try to get the cargo to unload only on certain terrain types (it's OK if it also unloads in a city).
 
To landAirCargo.lua, I added:

Code:
function unloadFunctions.unloadTerrain(unit,partnerUnit)
if unit.location.terrainType == 14 then
return true
end
end
...to try to get the cargo to unload only on certain terrain types (it's OK if it also unloads in a city).
No, you have to change the cargoSettings.lua. There are a bunch of commented examples in the bottom of that file. Here's a relevant one:
Code:
cargo.registerCargoSpec(gen.original.uBomber,{
    hold = 1,
    load = "ownCitiesAirfields",
    loadEffects = 1,
    unload = function(bomber,cargo)
        if gen.isParadrop(cargo.type) and cargo.location.type ~= gen.c.oceanBaseTerrainType then
            return true
        end
        return false
        end,
    unloadFailureMessage = "%NAME3 can't unload %NAME4 here",
    unloadEffects = 2,
})
In this example, a bomber can only unload if the unit's type has the "paradrop" flag, and the unit is not over the ocean. It can also unload in cities (since everything always can), but I probably should have also let it unload in airfields.

If you want to change everything, you can change the line near the top of the file
Code:
cargo.registerDefaultUnloadFunction("everywhere")
And register a function that does what you want.

The rule for everything in the LuaCore is look but don't touch. You may need to look in a file if you need information that isn't documented or if you need to diagnose a bug, but I've written all the modules so that anything that I expected you to change could be changed in the corresponding settings file. With the possible exception of adding some print statements to debug something, you shouldn't be changing things in those files unless you know what you're doing. If you've found a mistake in that code, let me know so I can update the template for everyone. (That's another reason not to change code in the LuaCore. I can easily offer an "update" that will not take your changes into account.)

For the above, too, when I have tried deleting the unit when the munition is created, it deletes the unit successfully, but the munition is not generated. Any ideas?
I will need to see what you've actually used as a setting.
 
Thank you, Prof. I've returned the file to its original state. It helps to start fresh on this template this time, rather than create a massive events.lua file! Finding the separations quite intuitive.

Here is what I wrote in munitionsSettings.
Without killing "Hides," I was able to create the Children unit. However, once I added the "kill hides" part, it does indeed delete a Hides unit (which I want, like spending a resource), but the Children are not created.

Spoiler :
Code:
local function hidesOnTile(unit)
    local tile = unit.location
    for possibleHides in tile.units do
        if possibleHides.type == unitAliases.Hides then
            return true
        end
    end
    return false
end

local function generateChild(unit)
    for possibleHides in unit.location.units do
        if possibleHides.type == unitAliases.Hides then
            gen.killUnit(possibleHides)
            break
        end
    end
    return gen.createUnit(unitAliases.Children, unit.owner, unit.location, {homeCity = nil, veteran = nil})
end

primaryAttackTable[unitAliases.Women.id] = {
    generatedUnitType = unitAliases.Children,
    moveCost = 4,
    allowedTerrainTypes = {14},
    canGenerateFunction = hidesOnTile,
    generateUnitFunction = generateChild,
    activate = true,
    terrainTypeFailMessage = "There are no tipis to dwell in here."
}
 
I copied your code, changed the terrain type from 14 to 1 , and defined unit aliases as seen at the top of this code. Pressing k with an active musketeer deletes a caravan and creates an archer, as expected. Since I can't re-create the situation, I don't have any advice.

Spoiler code :

Code:
local unitAliases = {}
unitAliases.Hides = gen.original.uCaravan
unitAliases.Children = gen.original.uArchers
unitAliases.Women = gen.original.uMusketeers

local function hidesOnTile(unit)
    local tile = unit.location
    for possibleHides in tile.units do
        if possibleHides.type == unitAliases.Hides then
            return true
        end
    end
    return false
end

local function generateChild(unit)
    for possibleHides in unit.location.units do
        if possibleHides.type == unitAliases.Hides then
            gen.killUnit(possibleHides)
            break
        end
    end
    return gen.createUnit(unitAliases.Children, unit.owner, unit.location, {homeCity = nil, veteran = nil})
end

primaryAttackTable[unitAliases.Women.id] = {
    generatedUnitType = unitAliases.Children,
    moveCost = 4,
    allowedTerrainTypes = {1},
    canGenerateFunction = hidesOnTile,
    generateUnitFunction = generateChild,
    activate = true,
    terrainTypeFailMessage = "There are no tipis to dwell in here."
}
 
Top Bottom