Small Questions Thread

came to put nose in
"civ.scen.onResolveCombat(function (defaultResolutionFunction, attacker, defender)",
first testing only with two "prints" to see if I could take the attacker location from here (rather than onUnitKilled)
quite your tricky boy if I may say :)

May you confirm the order above is the right one (as it seemed to result from experiments)

FYI,

In my testing, it seems first of all that the "attacker" and "defender" parameters are reversed -- the first unit seems to be the defending one.

You seem to be re-creating a lot of stuff that is in the template. I define the 'aggressorLocation' outside of any function, so it can be used and changed both with onResolveCombat and onUnitKilled.

Code:
-- used to determine whether or not it is the first round of combat in the
-- civ.scen.onResolveCombat function
local firstRoundOfCombat = true
-- saves the location of the aggressor, since if an attacker loses, its location
-- is no longer available for use in a function
local aggressorLocation = nil
-- saves the veteran status of the combatants before combat, since promotion
-- happens between combat and the unit killed event
local aggressorVetStatus = false
local victimVetStatus = false
local aggressor = nil
local victim = nil

civ.scen.onUnitKilled(function (loser,winner)
    --legacy.doUnitKilledEvents(loser,winner)
    firstRoundOfCombat = true
    local loserLocation = nil
    -- vet status of the combatants before combat
    local winnerVetStatus = nil
    local loserVetStatus = nil
    if loser == aggressor then
        loserLocation = aggressorLocation
        winnerVetStatus = victimVetStatus
        loserVetStatus = aggressorVetStatus
    else
        loserLocation = loser.location
        winnerVetStatus = aggressorVetStatus
        loserVetStatus = victimVetStatus
    end
    promotion.customVetChance(loser,winner,aggressor,victim,loserLocation,victimVetStatus,aggressorVetStatus,promotionSettings.promotionChanceFunction)
    doOnUnitDefeatedInCombat(loser,winner,aggressor,victim,loserLocation,winnerVetStatus,loserVetStatus)
    local survivor = doOnUnitDefeated(loser,winner,aggressor,victim,loserLocation,winnerVetStatus,loserVetStatus)
    if not survivor then
        doOnUnitDeath(loser)
    end
    doOnUnitDeletion(loser,survivor)

end)


civ.scen.onResolveCombat(function(defaultResolutionFunction,defender,attacker)
    if firstRoundOfCombat then
        aggressor = attacker
        victim = defender
        aggressorVetStatus = aggressor.veteran
        aggressorLocation = aggressor.location
        victimVetStatus = victim.veteran
        firstRoundOfCombat = false
        return (combatResolution.firstRound(defaultResolutionFunction,defender,attacker) and
                combatResolution.everyRound(defaultResolutionFunction,defender,attacker))
    else
        return combatResolution.everyRound(defaultResolutionFunction,defender,attacker)
    end
end)

I don't understand what else you are asking.
 
I have a small question, albeit not a technical one.

Ages ago Sarsstock was working on a Star Wars scenario called Siege of Cydonia. I don't know if it was ever finished, but having watched Mandalorian and re-watched most of the Clone Wars series, I was wondering..
.. would it be possible to get my hands on it? Even a test version? If it still exists that is, and isn't lost to the ages.

Its been ages since I played a Star Wars scenario, and there are few enough of them around.
 
According to the log, Curt had requested that this scenario entry gets deleted here, July last year :dunno:.
Could be restored, if he wanted, but I don't know what his original reason was :dunno:.

Me neither. Curt did say over in the reorganization thread that he didn't want any of his stuff in the CFC Downloads area and presumably only wants them on the Scenario League wiki site, but maybe he didn't know some of his scenarios on the SL wiki are redirects to the CFC downloads area and that they're broken and lost? As I ran into a similar problem with some of his old scenarios a while back and even he didn't have a copy anymore! Fortunately eventually a collector contacted me who had copies of them so I was able to to remove the redirects and upload them directly to the SL wiki site (it has it's own uploader) using the admin access Garfield gave me.

I don't have the Zarklaw ones though. So I guess if Curt is still okay with his scenarios being hosted on the SL wiki site we could temporarily restore the CFC copy, download it, then re-delete the CFC copy, then I can upload the copies directly to the SL wiki and replace those broken links to CFC with local SL wiki downloads. However it's his work & his call obviously and maybe he wants them gone from the net completely? Be a shame though as they look cool and like something I'll wanna showcase in my ToT video one day!

Ages ago Sarsstock was working on a Star Wars scenario called Siege of Cydonia

I can't seem to find anything on that sadly, do you know where the original thread was? I have found a lot of other old Star Wars scenarios though and have been posting them in my search and rescue thread. There's a few more I've found that I haven't posted there yet but hopefully will get to them soon!

.
 
Last edited:
New small question: I found a Scenario League article that talks about Caravan Delivery Payoffs. But it seems to focus exclusively on the initial bonus received when a caravan first arrives. Does anyone know where I could find the formula for determining how many arrows a trade route will generate every turn -- the ongoing benefit?
 
This is surprisingly difficult to find. Upon reflection, the delivery bonus was probably considered much more important to know, because it was so much larger than the ongoing bonus, and there are more variables. The best I found was from here:

https://codehappy.net/apolyton/threads/92-1.htm

Supposedly the per-turn trade benefit of a route is:

Route = ((raw trade arrows of City A) + (raw trade arrows of City B)+ 4)*modifiers)/8

Both cities are yours -50%
Airports in both cities +50%
Superhighways in home city +50%
*Cities connected by road +50%
Cities connected by rail +50%
**Freight instead of caravan +50%
**Cities on different continents +100%

* - I think this is just the individual square benefit

** - I think these are actually applied just to the one time bonus.

I'm not sure what the line "* - I think this is just the individual square benefit" is supposed to mean. I do know that the road and rail bonus happens only if the two cities are connected along a specific route, sometimes called the "critical path." I'll try to find more information about that.

I'm pretty sure the freight and continent bonuses are, indeed, only applicable to the initial delivery bonuses.

I think that the airport bonus is 100% if the cities are not on the same continent. Also, I'm pretty sure that both cities having a highway increases the trade route by 100%, (but if your city doesn't have a highway, there is no 50% bonus from the other city's highway -- but, of course, you still benefit from the increased trade arrow collection).

I don't think that there is a technology modification like there is for caravan deliveries, but that would be easy to verify by just giving all technologies to the tribe in question.

The base trade values do not include corrupted trade. https://forums.civfanatics.com/threads/corruption-affects-trade-routes.108800/#post-2455153 I suppose that strictly speaking, what I wrote there only proves that corrupted trade doesn't count for 100% of the value, but I would bet that it really is 0.

As long as this formula is correct:
Route = ((raw trade arrows of City A) + (raw trade arrows of City B)+ 4)*modifiers)/8
the rest should be easy to test and verify. I'm confident that there isn't some other thing I haven't mentioned.

I'll try to find more on the road/railroad path finding.
 
Some more information. From the GL archive https://forums.civfanatics.com/threads/the-fate-of-apolytons-archived-threads.394957/#post-9869652

File: Interesting Observations on the effects of roads on trade: (samson)

A few clarifications.

Rivers do NOT create a connection between cities or provide a trade route bonus. Neither do they form a barrier to trade routes. Both of those statements appear to be misinterpretations of other effects.

Intervening cities can have a variety of effects. They can form part of the road/rail connection, they can prevent the connection from ever being achieved, or they can create the bonus in one city (to which they are connected) even though there is NO connection at all to the destination city.

Airports (in both cities) act as a 50% road bonus. But if either a road or rail connection exists, that bonus (50% for road, 100% for rail) replaces the airport bonus. (emphasis added by Prof Garfield)

Non-allied foreign units on the road/rail connection (even non-military units) disrupt the trade bonus. Allied foreign units do not.

Also, a terrain square changed to Ocean via the CHEAT MENU may not function the same as an original Ocean square as it effects road/rail connections. So tests conducted using that technique, may be suspect.

File: Trade Roads – Determination of the Bonus Road and Railroad Connection: (Zenon)

Trade Roads – Determination of the Bonus Road and Railroad Connection
It is well known that a qualified trade road adds to the trade bonuses, both to the permanent trade bonuses (source to destination trade road) and to the delivery bonus (destination to source city). The source to destination trade roads are the most valuable especially when connecting a SSC.
It is also well known that a (bonus) trade route connection can be determined by sending a unit that disregards terrain (one move unit or explorer) with the go to order to the destination city and back. The best way usually is to send a settler building the road on the way. This does not work if there are already other road connections on the way. The unit takes the fastest way, the trade road does not. It would also be helpful to know in advance if the trade road has to be build on easy or on difficult terrain or if it crosses a river field that needs bridge building. An explorer not only needs resources to build but also needs seafaring. To determine a trade road from an AI city to your source city you also have to know at which field the trade road leaves the AI city.
Searching for advice I found only a few known facts like a direct diagonal path between two cities giving a qualified trade route. Therefore I did a little research to find out how these traderoutes could be known. This is what I found:

I. General Rule

The following rules always describe the trade road from the source city to the destination city, which gives the additional permanent trade route bonus. To determine the way back which triggers the delivery bonus, just exchange source city and destination city and repeat the rules.

1. Shortest Way

The trade route is always on the shortest way (measured in steps without regard of terrain). If there is only one shortest way (e.g. two cities on opposite sides of a bay) this is the trade route.


2. Direct Paths (step 2)

If there is a

- direct diagonal path
- direct straight (nondiagonal) path from South West to North East

from the source city to the destination city this is the trade route.

3. One crossroad (step 3)

If step one and step two do not give a trade route a crossroad point is needed. It is helpful to remind that trade roads in these cases usually go clockwise around a fictitious center point between the two cities. This is not a general rule, though, as there are exceptions.

The possible (destination city) Crossroad Points are on a diagonal path leading out of the destination city. This destination diagonal is determined by the diagonal field adjacent to the destination city that is next (measured in steps) to the source city.

If there are two possible diagonals it is – seen from the destination city – the one determined by the first crossroad point on the righthand side. Exception: if a direct path from South West to North East from the Source city or from the source city diagonal to the other possible crossrad points (on the „left“ diagonal) is possible it is the left point that determines the destination diagonal.

The crossroad points are only at uneven numbers on the diagonal seen from the destination city (1,3,5,...)

The source city diagonal leaves the source city on the diagonal field that is next to the destination city. If there are two possibilities it is – seen from the source city – the one on the left side.

3.1 regular connection (no SouthWest to North East path possible)

3.1.1 If there is a direct straight (non diagonal) path from the source city to one of the destination city crossroad points and this crossrad point is left of the source city diagonal (seen from the source city) the trade route is determined by connecting the source city with this crossroad point and the destination city.
3.1.2 If there is a source city diagonal that leads to the first diagonal crossroad point of the destination city this determines the trade route
3.1.3 if 3.1.1 and 3.1.2 don´t give a trade route a possible secondary crossroad point has to be checked: it is the nondiagonal field adjacent to the destination city, that is next to the source city. If there is a source city diagonal that leads to a non diagonal field adjacent to the destination city and the destination city is right of the diagonal (seen from the source city) a one crossroad trade route connection can be established.

3.2 Irregular path (Southwest to Northwest connection possible)

3.2.1 If there is a direct straight path from the source city to one of the destination city crossroad points (on a „left“ diagonal) the trade route is determined by connecting the source city with this crossroad point and the destination city.
3.2.2 3.1.2 does not apply if any (even a two crossroad) South West/North East connection is available.
3.2.3 3.1.3 does not apply if any (even a two crossroad) South West/North East connection is available.

4. Two Crossroads (step 4)

If neither step 1 nor step 2 nor step 3 leads to a traderoute a second crossroad point has to be determined. This second crossroad point is on the source city diagonal.

It is determined by the shortest way (measured in steps on the source city diagonal) from the source city to a direct nondiagonal path that leads to a crossroad point of the destination city.


II. Obstacles

If the trade route according to the general rule is permanently not available (e.g. there are ocean fields on the way) there are the following rules:

1. Determination Point or crossroad point not available

If a determination or a crossroad point is not available (e.g. the one determining the destination city diagonal) it does not affect the General Rule. In a first step the trade road is calculated as if it was available.

2. Obstacles on the trade route

If there is an obstacle the trade route is regular until it reaches the obstacle. From there the next step goes
- to the field (measured in steps) next to the destination city
or if there is still a choice
- to the field that is next measured in trading distance
or if there is still a choice
- to the field on the left seen in direction to the destination city, unless there is a field to Northeast available. If a direct Southwest to Northeast route is blocked the righthand field is chosen.

From this point a new trade route to the destination city is determined according to the General Rule.

If there is - again - an obstacle on the (newly determined) trade route this set of rules is repeated.

I am not completely happy with this set of rules. I always thought that there should be an easier way to describe the trade route paths. But it seems that the creators of civ tried to cover the rules like in many other cases concerning trade. I can´t see a reason why something like a Northeast preference should be programmed.

However, they seem to work in the cases I found so far. It helps to keep the preferences in mind:
- shortest way
- Southwest to Northeast preference
- the trade routes usually go clockwise around a (fictitious) center point between the two cities.

I´ll try to add some examples in my next post.

Any comments are welcome.

Zenon
 
File: Trade Roads – Determination of the Bonus Road and Railroad Connection: (SlowThinker)

General algorithm (bug-free situations)

So I post my version of the goto algorothm. I'm not sure about everything, since only quick tests were done.

I will use the word Path in place of trade route, because Paths are important not only for caravan deliveries, but also for blocking barbs for example (see my post in partisan barbarians won't attack your partisans ).
First of all, I want to add rule 0. It looks it is self-evident but it is good to express it:

There is always just one Path from point A to point B.
If Path goes from A through B to C, then Path from B to C is the corresponding sub-Path. In other words, in order to understand the complete Paths between any pair of points A and B on a given map you need to know only the 'direction' from A to B (for any pair of points A and B), i.e. only one step from square A to B. Then if you want to know the whole Path between A and B you can construct it step by step.

Now we can suppose we have a general situation - point A is the starting point and B is the destination, and there may be obstructions on the map. Point A has 8 neighbours and the question is: which one represents the direction to B?

Step 1
Say the distance (the 'movement' distance - i.e. number of steps of a Warrior) from A to B is Dist. Candidates for the directon are all neighbours with distance to B equal to Dist-1. If there is only one such a neighbour then this one represents the direction.

(This is equal to Zenon's point '1. Shortest Way'. But I claim this is valid also for a map with obstacles (see paragraph 'Obstacles' at end of this post: I tested Ocean only). So I disagree with Zenon's sentence:
2. Obstacles on the trade route: If there is an obstacle the trade route is regular until it reaches the obstacle. )

Step 2
Otherwise (i.e. if there is more than 1 shortest direction) the direction is chosen in accordance with the Civ2 Pathways diagram.
If this square is obstructed a 'secondary' direction is chosen. 'Secondary directions' are defined firmly for each square - you can imagine there is a diagram of 'Civ2 Secondary directions' - analogous to the Civ2 Pathways diagram.
If secondary direction is obstructed then a tertiary direction is chosen (again you can imagine there is a diagram of 'Civ2 Tertiary directions') and so on.

(This step was not tested thorougly.
I didn't have time to be able to compare Step 2 with Zenon's paragraph 2.Obstacles on the trade route and to test differences)

Obstructions:
A square with an obstruction can be Ocean or enemy unit or enemy ZOC (any other?). I tested Ocean only: Civ2 counts with Ocean in advance, i.e. Civ2 chooses a shortest way with respect to Ocean squares. I have a feeling that enemy units are taken in advance also, but enemy ZOCs are ignored until they are reached by the unit. Can you confirm if this is true?
A note: I suppose enemy units don't destroy a Path (and a trade route with bonus) completely but they only redirect it. Is this true? It could be exploited: to block an AI unit on a specific square...

Bugs
The Paths don't always correspond to the algorithm in my last post. There are some bugs in the behavior of Civ2:

1. Civ2 remembers previous maps. If you reload a different map the Civ2 still 'thinks' about an old one:
Load the nolake.sav, GoTo Rome (5 steps are enough). Then load lake.sav and GoTo Rome again: The Warior will move as would be moving on a map without the lake.
Now quit Civ2 completely, run Civ2.exe again, GoTo with lake.sav first then GoTo with nolake.sav.

2. Civ2 remembers previous movements and adapt present movement to them.
(I wasn't able to repeat the test. I need more time or I was wrong.)

Warning: Also trade route are affected temporarily by these bugs.

File: Phantom Roads and Railroads: (samson)

Phantom Roads and Railroads
I don't know if this tactic is well-known or not. But it is consistent and quite exploitable.


The existence of a road or railroad between the Source and Destination cities of a Trade Route increases the value of that Trade Route by 50% or 100% respectively. Surprisingly, the road/railroad does not actually have to be complete in order for the Trade Route to receive this bonus.

If a city belonging to the same civ as the Source city exists along the qualified route between the Source and Destination city, the road/railroad needs only extend as far as the interposed city to earn the bonus. Apparently, the algorithm that checks for a qualified road/railroad route stops as soon as a city is encountered and never checks the remainder of the route to the Destination City.

This means that an SSC can reap the full benefit of road/railroad bonuses on its trade routes to a far-off foreign megalopolis by building a road/rail connection to a local 'station' a mere 2 or 3 squares away. The 'station' must be located along the qualified path between the two cities. This location can be found by using to GOTO command to send a settler to the remote city and then terminating its travel just outside the SSC's city radius and founding a new city. When the road/rail is complete to the 'station', the full bonus will apply on trade routes to the foreign city.

This tactic not only allows road/rail bonuses to be attained quickly and with much less effort, but also makes the trade route bonus less vulnerable to disruption by non-allied units or pillagers. Foreign troops interposed on the 'phantom' portion of the road/rail have no effect on the trade route.

Trade route bonuses achieved in this way still suffer from other limitations of the road/rail bonus. For example, the trading cities can still be no more than 22 squares apart and they cannot cross the '0' meridian.

This tactic will affect only the Source city's trade route. To obtain the bonuses for the Destination city, a second 'station' must be built near it along the reverse qualified route. It is also this 'return route' which is used in Caravan Delivery Bonus calculations.


Other samson post (Q&A):
debeest -


Quote:
Your last sentence puzzles me, though. For the delivery bonus, my understanding is that the route is unimportant; what matters is the distance, as calculated by Civ's odd methodology. Am I missing something?

Yes. The Delivery Payment has a variety of bonuses that can increase the base payment, among then a Road (50%) and Railroad (100%) bonus. What I'm saying here is that the route required for the Delivery Payment bonuses is the return route (the Destination-to-Source road) and not the Source-to-Destination route which the Trade Route bonus requires. For further information, see my post 'Calculating Caravan Delivery Payments'.

Solo -


Quote:
Can the road route connecting the "station" to the Destination city meander around, or must it also be along the optimal GOTO path?

No, it can't meander, it must follow the optimal GOTO path.

To clarify, for the Source City to receive the road/railroad trade route bonus, it needs connection to a station on the Source-to-Destination route. For the Destination City to receive the trade route bonus, it needs connection to a station on the Destination-to-Source path. Most often these two routes are different. The onetime Delivery Payment road/railroad bonus depends on the Destination-to-Source route.


Quote:
Also, will connecting this road to other Destination cities affect the railroad bonus for the Source city?

What do you mean by 'this road'?

Thoddy -

In your referenced post, you state:


Quote:
Yes, it seems so, that building roads on the opt. path outside the city radius is not neccessary.

This is not exactly correct. Merely building roads within the city radius is insufficient. The road must connect to one of your own cities which lies on the optimal path to the Destination City. If the interposed city lies well outside the city radius the road has to be built all the way to it.

SG2 -


Quote:
The rule of 22 squares - that means that no benefit can be obtained from any transport link greater than this distance? If so 22 seems a strange number ... any thoughts?

Correct. The 22 squares rule means than no Road or Railroad bonuses can be obtained if the two cities are more than 22 movement squares apart, no matter what route is involved. Two cities 22 squares apart connected by Railroad in a direct E-W line receive the 100% railroad bonus. If they are 23 squares apart, they do not.

I agree that it is a strange number and it is not the same as a 'distance' of 22. Distance in Civ2 (as measured by the rectangle method or the formula I posted under 'Caravan Delivery Payments') counts distance in the E-W and N-S direction as 1.5 and NW/NE/SW/SE direction as 1. But the 22 squares rule is based on 22 movement points.

I'm sure you're right about receiving the 'phantom road' bonus often in game play and not recognizing why the route is greater than expected.

In the attached picture, the newly founded city of Atlanta is a 'station' for Washington. It lies on the GOTO path from Washington to Paris, from Washington to Orleans and even on the Washington to London path. In Washington, trade routes to any of these cities will receive a 50% Road bonus by virtue of the short road from Washingon to Atlanta.
 
@Prof. Garfield Thank you very much for finding the general formula, and then for going way above and beyond to track down such extensive details about the "direct route" logic. That seems extraordinarily complex and I don't think it would be very easy at all to code into Lua -- I'm not going to attempt it at this point. Even without that, just knowing the basic formula is pretty interesting -- the fact that the value of a route isn't impacted at all by other routes present in the city, and that the distance to the destination city isn't relevant either. (Actually I guess it could prevent the road/rail bonus if it's more than 22 tiles away, which makes so little sense it feels like a bug.)

This is surprisingly difficult to find. Upon reflection, the delivery bonus was probably considered much more important to know, because it was so much larger than the ongoing bonus, and there are more variables.
The ongoing benefit seems relatively small, but in a game spanning hundreds of turns, the cumulative effect will eventually outweigh the initial delivery benefit. The earlier in the game the route is established, the more I think it makes sense to maximize the ongoing benefit even at the expense of the initial one.

In Medieval Millennium, I have the "TradeScienceMultiplier" entry in @ COSMIC2 set to 0 -- so there's no initial science gain at all, you only receive gold. That means that all of a trade route's science value comes from its ongoing benefit, and that might make it even more important to maximize that ongoing value.

As long as this formula is correct:
Route = ((raw trade arrows of City A) + (raw trade arrows of City B)+ 4)*modifiers)/8
the rest should be easy to test and verify. I'm confident that there isn't some other thing I haven't mentioned.
I tested this out in a game of MM which I'd already played for 400+ turns, and I'm 99% confident that it is indeed correct (if I use math.floor instead of traditional rounding). All of the variations I found between the expected route value (using this formula) and the actual in-game route value could reasonably be attributed to the road/rail bonuses.

Thanks again!
 
@Prof. Garfield Thank you very much for finding the general formula, and then for going way above and beyond to track down such extensive details about the "direct route" logic. That seems extraordinarily complex and I don't think it would be very easy at all to code into Lua -- I'm not going to attempt it at this point. Even without that, just knowing the basic formula is pretty interesting -- the fact that the value of a route isn't impacted at all by other routes present in the city, and that the distance to the destination city isn't relevant either. (Actually I guess it could prevent the road/rail bonus if it's more than 22 tiles away, which makes so little sense it feels like a bug.)

I'm pretty sure that the game just uses the regular pathfinding function for goto, which is easy to look into with the TOTPP move debug patch. There's probably a not too complicated algorithm governing path finding.

It turns out that the thread is still archived by Apolyton (or, they put the archive back up).

This image is provided for explanation. The city on the other end of the trade route goes in the centre square in order to find the path (assuming there is no water).

trade-path.png


Even if you don't need this, I'm interested now. I'll probably start another thread if I have more to say.

The ongoing benefit seems relatively small, but in a game spanning hundreds of turns, the cumulative effect will eventually outweigh the initial delivery benefit. The earlier in the game the route is established, the more I think it makes sense to maximize the ongoing benefit even at the expense of the initial one.

In Medieval Millennium, I have the "TradeScienceMultiplier" entry in @ COSMIC2 set to 0 -- so there's no initial science gain at all, you only receive gold. That means that all of a trade route's science value comes from its ongoing benefit, and that might make it even more important to maximize that ongoing value.

In the base game (especially the typical large map, deity, raging hordes barbarians), the delivery bonuses are large enough that variations typically outweigh a few arrows per turn, especially once you apply an "interest rate" to discount future funds.

Circumstances are different in Medieval Millennium, so when I played that (small map, one continent), I quickly figured out that I should be trading with adjacent cities, so I could take advantage of the road/rail bonus, since payouts are small. (It didn't help that the only tribe that built large prosperous cities was right next to me, although I did send some trade their way from time to time.)
 
Is this thread still active? I had a "small question" -- I thought I'd post here instead of in a message to Prof. Garfield, so others might benefit or weigh in.

This is the code in Prof. Garfield's exceptional Lua Scenario Template guide that was advised to put into the Rome scenario onUnitKilled.lua:

Code:
function
unitKilledEvents.unitKilledInCombat(loser,winner,aggressor,victim,loserLocation,winnerVetStatus,loserVetStatus)
loser.owner.money = math.max(loser.owner.money -campaignCost,0)
winner.owner.money = math.max(winner.owner.money-campaignCost,0)
end

However, this wasn't working for me with the latest lua template. So, I tried this:

Code:
function
onUnitKilled.onUnitKilled(loser,winner,aggressor,victim,loserLocation,winnerVetStatus,loserVetStatus)
    loser.owner.money = math.max(loser.owner.money -campaignCost,0)
    winner.owner.money = math.max(winner.owner.money -campaignCost,0)
    if _global.eventTesting then
        civ.ui.text(loser.type.name.." killed by "..winner.type.name.." separate file test killed in combat.")
    end
end

As you can see, I added the money part to the pre-existing function in the file. Anyway, it worked, as far as I can tell (taking 1 gold for every battle no matter the civ). I'm wondering why it worked, and if the unitKilledEvents / unitKilledInCombat should have worked or if I missed something there. It's also very possible this is working in its limited scope here, but there are unforeseen consequences! I'm unwilling to say, "If it works, it works," with such a web of code. I also do know that Prof. Garfield mentioned the guide itself is a WIP, so it may be that the lingo has been adjusted since it was written.

Oh, I'm also attaching an image of my console from my "Test of Time Tinkering" folder. :) So sorry, but for some reason my computer doesn't want to copy/paste from the console.

New to all of this and would appreciate any insight. Thanks in advance, and yet another thanks to Prof. Garfield for these amazing tutorials/resources.
 

Attachments

  • Screen Shot 2022-08-18 at 11.02.17 AM.png
    Screen Shot 2022-08-18 at 11.02.17 AM.png
    108.2 KB · Views: 14
As you can see, I added the money part to the pre-existing function in the file. Anyway, it worked, as far as I can tell (taking 1 gold for every battle no matter the civ). I'm wondering why it worked, and if the unitKilledEvents / unitKilledInCombat should have worked or if I missed something there. It's also very possible this is working in its limited scope here, but there are unforeseen consequences! I'm unwilling to say, "If it works, it works," with such a web of code. I also do know that Prof. Garfield mentioned the guide itself is a WIP, so it may be that the lingo has been adjusted since it was written.
Sorry. I forgot to mention that I reorganized the template a bit. You can get the template that I used for the lesson here. (This was mentioned in the installation part of the lesson, but that would be easy to miss.)

In any case, here's the explanation.

When a program is split into multiple files, each file has to provide some information/code to other files. The way Lua does this is to select one table to put all the information that is usable in other files into a table, and then have a line to 'return' that table. For example, in the object.lua file, a table called 'object' is created, a whole bunch of information is added to that table, and then the object table is returned at the end of the file.

Another file ('newFile.lua') can use this object table with the following line:
Code:
local newFileObject = require("object")
Then, if, for example, the warrior unit type was added to the object table in object.lua under the 'uWarrior' key,
Code:
object.uWarrior = civ.getUnitType(2)
The newFile.lua file can access the warrior (e.g. to get its defense value) using the same 'uWarrior' key, but its own name for the object table.
Code:
newFileObject.uWarrior.defense
In the case of the object table, the same name for the table is used in every file, but it doesn't have to be.

So, what has happened is that I changed the name of the returned table from 'unitKilledEvents' to 'onUnitKilled' as well as changing the expected key from unitKilledInCombat to onUnitKilled. I also moved some other unit killed related events to their own files. I can explain why these changes were made if you're interested, but they don't matter for using the template.

Also of note is that the syntax looks a bit different from say the object file, because we're adding functions as table values rather than other kinds of values.

The error you've received is an error that I programmed to occur when you try to use a global variable. (You can scroll up in the console to see the beginning of the error.) Probably the biggest 'problem' with Lua is that all variables are global (meaning they can be accessed from any file without having to use 'require' as described above) by default. This causes 2 issues. First is that you can get some weird bugs where 2 different parts of the code use variables with the same name, and therefore are using and changing the same variable.

The second issue is that Lua doesn't catch many typos when globals are enabled, since globals are implemented as keys in a table. Here's a simple example:
Code:
local activeUnit = civ.getActiveUnit()
if activeunit then
    civ.ui.text("The active unit type is "..activeUnit.type.name..".")
else
    civ.ui.text("There is no active unit.")
end
Note that in the second line, activeunit is a typo. It should be activeUnit. The way the code is supposed to work is that if there is a unit active, civ.getActiveUnit() returns that unit (which is truthy), and if there isn't it returns nil (which is falsy). So, if activeUnit is a unit, the if portion of the if-else statement is run, and if activeUnit is nil, the else portion is run. Since activeunit isn't defined anywhere, we want it to register an error, so we can find the typo.

However, the way the code works is that the lua interpreter sees activeunit, finds no local variable called activeunit, and therefore decides it is a global variable. Since global variables are stored as key-value pairs in a table, lua looks for the value associated with the 'activeunit' key in that table. We've never assigned anything to that key, so by the logic of Lua tables, nil is returned. So, instead of causing an error, the code 'works', but always shows "There is no active unit.". That's why I disabled global variables by default.

So sorry, but for some reason my computer doesn't want to copy/paste from the console.
That's odd. Can you highlight and use CTRL+C?
 
@Prof. Garfield The way you put all this is, as I've been repeating like a broken record, extremely easy to understand. Thank you for such a thorough reply, and apologies for missing that note about template version. I imagine I'll be back with more of these, but I think at this point I need to get in there and make the mistakes. Love the walkthru and the lessons! And I continue to be amazed by what is possible here. :worship:
 
Top Bottom