Checking all adjacent tiles

Proto_Noob

Chieftain
Joined
Jan 11, 2016
Messages
42
Simple question.

I am familiar with programming (vb.net, C#, xml, sql), but new to lua. I would like to know the best way to loop through all adjacent tiles and check for something. Can someone give me a code example that would actually run if placed in a lua file (i've seen enough 'something LIKE this but won't work' examples for a lifetime). It can be really simple (that may actually be better), but if you are interested in what I am trying to to and can give that code, all the better.

I am expanding the mod "Trading Posts Grow into Towns". I want to disallow Trading Posts (TPs) from being adjacent (and all later evolutions of trading posts). Normally, I could just flip the NoTwoAdjacent bit to true in xml, but if a trade post has grown into a town, the code behind that bit will not recognize them as the same 'class' of improvement. So, I would like to check to make sure there are no hamlets, villages, or towns adjacent to where a worker stands and prevent him from building a TP in much the same way you are prevented from building a city too close to another.

Thank you.
 
How do you intend to keep the worker from building the improvement even after you make the check for whether there is an adjacent 'Improvement X' ?

For bane_ it's easy, he just uses the PlayerCanBuild or PlotCanImprove game event :lol:

Without a modded DLL, it's going to be very, very hard (if even possible)
 
For bane_ it's easy, he just uses the PlayerCanBuild or PlotCanImprove game event :lol:

Without a modded DLL, it's going to be very, very hard (if even possible)
Well, VMC cures just about everything, don't it?1 :D

I was assuming Proto_Noob was thinking there was a method in the stock API (no custom DLL) that allowed "setting" whether Unit-X can Build improvement-Y at given plot. Unfortunately, as noted, there is not, so far as I recall.
  • I think I've lost count of the number of people new to Civ5's lua system who interpret Unit:CanBuild(blah, blah) as being a method that will work for this.


1and I see this morning there's even more stuff. :worship:
 
So, the consensus seems to be that I cannot prevent the worker from building the trade post without editing the dll.

Well, thank you all, and particularly bane for the code to check each of the adjacent tiles.
 
Hey everybody,

I have had some other projects that have pulled me away from Civ 5 modding but I have some more time so I would like to pic up the conversation again. Sorry for the absence.

bane_, I have read your basic tutorial and found it very helpful, and being a programmer I find the logic of the code quite simple to understand. However, I find that I lack even the basics of how to implement a lua mod for civ 5 from beginning to end. Kind of like with xml modding, there are things that you have to know outside of xml (like changing the properties of your mod buddy project to add actions, like OnModActivated, to actually get it to work). I have been unable to find any tutorial that covers such things. If there is no comprehensive tutorial for lua modding that includes such information on peripheral actions, answers to a few questions will help me get rolling.

1) You use the variable pPlot in the code above. I see that it is not assigned here, so it must be assigned elsewhere. Fine, but the function that this code will be embedded in needs to know the plot it is supposed to be working with. I do not know how to do this. I assume I just want to pass the plot in question to the function, and I can write the function to expect a plot, but I don't have access to the DLL code, so how do I pass the plot in question from the outside? I am assuming the DLL will be the one calling the function... is that right? All the lua examples I can find in other mods will have lines like...

GameEvents.PlayerDoTurn.Add(PolicyBuildings_RemoveBlockedBuildings)

but never inform the dll what values to pass to the method. Are we just accessing global variables all the time? This is probably the most confusing thing for me so far.

2) If I decided that this function was to look for rivers or roads that are [adjacent/on the same tile], what would be the function I am looking for? For instance, looking at whoward69's excel sheet for lua methods I would think pAdjacentPlot.IsRiver and pAdjacentPlot.IsRoute . Is this correct?

3) When the function is done and I return, let's say an integer, how do I then use that integer to modify say, the gold output of a trading post?

4) I guess what most of my questions boil down to is, "When I make a Lua mod, what are all the things I have to do on the OUTSIDE of my functions to get them to work?

5) Side Question: how do I format a post here to have a 'Code:' box. Or more generally, where is the guide on post formatting?

Thanks for any info you can give.
 
Last edited:
Conversely, if you think of a really good example mod that has both lua and xml that really illustrates the relationship between these and the dll, please let me know.
 
The code in post #2 was a snippet. He's assuming you've determined the plot already.

1. I'm guessing that you're looking at it backward. When you use the .Add() method with an event, the DLL is calling your custom function when that event occurs before it performs its regular set of instructions. The modiki shows that PlayerDoTurn has one parameter, a "PlayerID" pseudotype integer. If you want to use that variable, your function's declaration would reference the parameter to give it a local variable name.
2. Yes, that is what those functions are designed to do.
3. Since PlayerDoTurn returns a void, let's change our example to an event from whoward69's DLL, GameEvents.PlayerCanBuild, which is pertinent to your question.
Code:
GameEvents.PlayerCanBuild.Add(function(iPlayer, iUnit, iX, iY, iBuild) return true end)
This event is called any time the game needs to decide whether a worker can build something and returns a bool to indicate whether it's allowed. If you return a false, it will pass that false value.on, and the game won't allow the worker to build the improvement in question (iBuild is the ID of the item in the Builds table of the database). If you return a true, note it will still go through the rest of the code to see if there might be another reason to return a false.
4. As for how to set up your Lua file in ModBuddy to be added to the game, it's going to be an InGameUIAddin. See whoward69's File Attributes tutorial.
5. "[ C O D E ] ... [ / C O D E ]" blocks are what you're looking for.

As for good examples, the scenarios that come with the game and its DLCs are a good place to start.
 
To follow on to what @Nutty explained, whenever an lua code has the statement:
Code:
GameEvents.PlayerDoTurn.Add(NewFunctionName)
this signals the gamecore to add this new function as an additional one to be run whenever the PlayerDoTurn game event is triggered. This event triggers for each player (including city states and barbarians) sequentially whenever the human player presses the NEXT TURN button as part of that processing into the next turn of the game. We use such a function in lua like as this (which is also showing the other way to add a function to a pre-defined game event):
Code:
function NewFunctionName(PlayerID)
     if PlayerID == 63 then
          print("Barbarians! Oh Noes!")
     end
end
GameEvents.PlayerDoTurn.Add(NewFunctionName)
The gamecore sends a PlayerID # to every event subscribed to PlayerDoTurn every time a player's turn is processed. So during the NEXT TURN processing the game will activate the PlayerDoTurn events for the 1st AI player and send "1" as the playerID argument to all such functions added to the PlayerDoTurn event. Then for the 2nd AI player it will activate all the PlayerDoTurn events and send "2" as the PlayerID, etc., until all active non-human players (including City-States and Barbarians) have been processed, and then the PlayerDoTurn events will fire for the human player, and all functions added for the PlayerDoTurn event will recieve a PlayerID argument of "0".

Player ID #'s always conform to the following for Single Player games. Multiplayer games are a bit different, but then Firaxis never properly created mod-support for multiplayer anyway. It's going to probably look a little kludgey since the new software no longer allows a table in a reply:

PlayerID.....PlayerType
0................Human (always)
1 - 21.........AI Major Civs
22 - 62.......City States
63..............Barbarians

Any lua event sending a Player ID # will send that integer Player ID # in conformance to that info.

See also: http://modiki.civfanatics.com/index.php?title=PlayerID_(Civ5_Type) PlayerID Info
(just bear in mind in the one example where they print out the ID's and player names in a chart it says "two" city states when in fact the chart of the print-out shows three city-states: Monaco, Geneva, and Warsaw. Also remember it was made before Poland was ever a civ in the game, and at that time Warsaw was a valid city-state.)​
And See: http://modiki.civfanatics.com/index.php?title=Lua_and_UI_Reference_(Civ5) Top Page of LUA Civ5 Reference
 
Last edited:
First off, thank you @Nutty and @LeeS, your responces have been helpful. I doubt I have a full understanding yet, but you have given me links to what look like good resources that I had not found yet. I am sure this is all probably laid out very well somewhere, but being a latecomer (as Civ 6 is already out) there is SO MUCH discussion and information out there I feel like I am trying to eat a hogie sideways (don't know where to begin). Just too much information to digest, and it is hard to find the basics. Yes... I have found a lot of bane_'s and Whoward69's lua stuff, but the vast majority of it seems to be either *just* beyond total beginner level or doesn't give the full pitcure. I feel like I am missing some 5 minute tutorial to put it all together.

Anyways, I will look into some of those links and if I have further questions I will come back here.
 
Back
Top Bottom