Prevent Barbarians from entering territory

IanYuy

Chieftain
Joined
Dec 25, 2014
Messages
7
Hey, I've searched for quite a bit (in the forums and within the game files itself) on how to achieve this...

I am trying to make a civilization whose trait prevents Barbarians from entering their borders. Pouring through the XML, I found the difficulty settings (but this is global and would prevent them from entering everyone's borders). I searched for anything Barbarian specific, but to no avail. I also tried to see if I could dig up anything related to Open Borders and whatnot, since Barbarians are sorta-kinda a civilization of their own. However, the longer I go over this, the more I'm seeing how limited XML and working with the existing tables in the database is.

I imagine this is a job for Lua scripting. However, the largest problem I have with that is, I don't know what variables there exist that I can modify. I'm confident I could try to slowly figure out how to mess with the code, but I don't actually know how to find out what specific commands I can tweak.

Can anyone point me in the right direction of what I'm looking for? (And if there is something I'm missing that shows me what the different Lua-tuneable variables there are, that would be great as well.)
 
XML is indeed very limited, as you're typically limited to what the game needed to do for the stock Civilizations, with few exceptions for "swapping out" certain resource types and such.

I'm not entirely sure how one would go about doing this off the top of my head, though. One possibility is to use the UnitSetXY event and manually shift Barbarians out of your territory as it detects them wandering in, but the AI will simply keep trying to enter fruitlessly, and it would also be pretty heavy-handed code.

With that said, if you would like to begin learning, a great reference is the Lua reference on the Modiki.
It takes some time to figure things out, but once you become accustomed to how things are laid out, it becomes pretty simple to find stuff on there.
 
Hey, I've searched for quite a bit (in the forums and within the game files itself) on how to achieve this...

I am trying to make a civilization whose trait prevents Barbarians from entering their borders. Pouring through the XML, I found the difficulty settings (but this is global and would prevent them from entering everyone's borders). I searched for anything Barbarian specific, but to no avail. I also tried to see if I could dig up anything related to Open Borders and whatnot, since Barbarians are sorta-kinda a civilization of their own. However, the longer I go over this, the more I'm seeing how limited XML and working with the existing tables in the database is.

I imagine this is a job for Lua scripting. However, the largest problem I have with that is, I don't know what variables there exist that I can modify. I'm confident I could try to slowly figure out how to mess with the code, but I don't actually know how to find out what specific commands I can tweak.

Can anyone point me in the right direction of what I'm looking for? (And if there is something I'm missing that shows me what the different Lua-tuneable variables there are, that would be great as well.)

I would highly suggest you'll check JFD's Germans. Or just ask JFD,
 
I would highly suggest you'll check JFD's Germans. Or just ask JFD,

Thanks for that. I looked at it and it seems to just trigger permanent peace, but somehow this all gave me an idea.

After thinking about it, I could use the difficulty level settings. I was thinking, since you can set difficulty level settings based per civilization in a game, that this would be possible. However, I don't want to make a new difficulty and override all the settings of whatever someone would choose.

Therefore, is it possible to have a script that changes part of the settings after they are chosen/during game loading, sort of deal? I was thinking of a script that would check for this civilization and then simply replace the EarliestBarbarianReleaseTurn row in the HandicapInfos table with a new value without changing the rest. (Since the rest should be populated after they chose a difficulty during pre-game) Or is this something not really possible, because it wouldn't update?
 
Pretty sure this is what the Great Wall does; though that also, of course, has a movement penalty for other civs.

I can't find anything about the Great Wall affecting Barbarians (I believe that was in Civ IV?), only the movement penalty to just 'enemies'.

I haven't had any luck with trying to update just the EarliestBarbarianReleaseTurn for a specific civ. If I have to, is there a method to make a certain civilization pull from only a specific set of difficulty levels? Obviously, I don't want to change the defaults but I can't seem to have it affect only one civ.
 
Pretty sure this is what the Great Wall does; though that also, of course, has a movement penalty for other civs.
Pretty sure Great Wall does not prevent entry by Barbarians. It does, as mentioned, make all enemies slow down in your territory. Finishing the Great Wall certainly doesn't eject any who are in your territory, Barbarians or otherwise.
 
The great wall prevents entry by Barbarians in Civ4 (and resulted in a cruise-control early game if you could snag it).

I would suggest you look inside the handicapinfos.xml (or whatever its called), and look for the variable that controls the turn-number in which barbarians can enter your territory.

Inside the DLL, search for the same variable, and trace the process that basically states "if turn number is less than X, barbarian cannot enter territory". Copy-paste-modify to your needs as an additional check, except this time checking for a trait instead of a turn-counter.
 
It might be worth looking at how the Ultrasonic Fences in Beyond Earth work.
 
Great Wall uses <BorderObstacle> to create the slow-down effect. There's also <PlayerBorderObstacle> but I have no idea if it works, and if so how. It may be one of those orphan columns that don't do anything.
 
The great wall prevents entry by Barbarians in Civ4 (and resulted in a cruise-control early game if you could snag it).

I would suggest you look inside the handicapinfos.xml (or whatever its called), and look for the variable that controls the turn-number in which barbarians can enter your territory.

Inside the DLL, search for the same variable, and trace the process that basically states "if turn number is less than X, barbarian cannot enter territory". Copy-paste-modify to your needs as an additional check, except this time checking for a trait instead of a turn-counter.


Your suggestion sort of just hit me on the head. The past day I've been doing just that. But, I guess I'm a mess with C++, as I don't know it, and tried to piece together something. I posted my query about the problem in my code in the SDK/LUA forums for now.
 
EDIT: Okay, the code prevents Barbarians from entering the civilization's territory--but only when I'm not the one playing the civ. When controlling another Civ with map exposed, the barbarians refused to enter its territory despite a worker and settler being right within their grasp.

Thanks for your suggestions thus far, guys. After messing with the DLL, I finally got it to compile. I no longer got errors in CvUnit, but continued to get them in CvTacticalAI, so I just commented it out of that one. Testing, Barbarians can still enter the territory.

In CvUnit, I put a check in the bool CvUnit::canMoveInto, right above the natural check for BarbarianRelease Turn. I know I'm doing something wrong here and my inclination is that I'm not checking for the owner of the plot correctly, but don't know how else to go about it.

Code:
if ((plot.getOwner() == (strcmp(getCivilizationInfo().GetType(), "CIVILIZATION_ALZADAAL"))) && isBarbarian())
	{
		return false;
	}

	// Original Code -- Barbarians have special restrictions early in the game
	if(isBarbarian() && (GC.getGame().getGameTurn() < GC.getGame().GetBarbarianReleaseTurn()) && (plot.isOwned()))
	{
		return false;
	}

This is my snippet of the code in CvTacticalAI, in the void CvTacticalAI::FindTacticalTargets section. I'm getting errors about the getCivilizationInfo isn't right, and while its the same as the code above, I think it has something to do with pLoopPlot.
Code:
if(pLoopPlot->isVisible(m_pPlayer->getTeam()))
		{
			//Attempt to make Alzadaal's UT work
			if((pLoopPlot->plot.getOwner() == (strcmp(getCivilizationInfo().GetType(), "CIVILIZATION_ALZADAAL")))  && !m_pPlayer->isBarbarian())
			{
				bValidPlot = false;
			} 
			// Original Code - Make sure I am not a barbarian who can not move into owned territory this early in the game
			if(!m_pPlayer->isBarbarian() || bBarbsAllowedYet)
				{
					bValidPlot = true;
				}

My biggest issue is just figuring out how to identify the owner of the targeted plot as my specific civilization. I can't seem to figure out how to do that.
 
Checking for the string if it matches the civilization name (aka "Hard Coding") is not an ideal approach (although if you can brute-force it to work, I guess it'll do :p).

I would suggest you look into how the GetPlayerTraits() is handled (as it supposedly processes and stores the various numerical and boolean attributes from the XML), it will allow you to add the no-barbarians-in-territory to other civilizations, along with causing you less headaches if you every decide to change your civ name.

Add a "NoBarbariansInTerritory" column (default to False or 0 or whatever) to the traits XML file. Then apply a "GetPlayerTraits()->GetIsBarbariansAllowed()" check on the player returned by plot.getOwner (note: may need to juggle around with converting between the player object/player abstract class).
 
Checking for the string if it matches the civilization name (aka "Hard Coding") is not an ideal approach (although if you can brute-force it to work, I guess it'll do :p).

I would suggest you look into how the GetPlayerTraits() is handled (as it supposedly processes and stores the various numerical and boolean attributes from the XML), it will allow you to add the no-barbarians-in-territory to other civilizations, along with causing you less headaches if you every decide to change your civ name.

Add a "NoBarbariansInTerritory" column (default to False or 0 or whatever) to the traits XML file. Then apply a "GetPlayerTraits()->GetIsBarbariansAllowed()" check on the player returned by plot.getOwner (note: may need to juggle around with converting between the player object/player abstract class).

Yeah, that all does seem a much better, modular method. So, I went in and added the trait. (I picked an existing one to track to make sure I was putting all the entries in where they were needed) I've triple checked to make sure all that is in there. If I comment out my code in Units and TacticalAi that tries to do the barbarian check, the game runs fine. I get a CTD now if I don't, so I've deduced its back to the issue of not calling the owner of the plot and then checking properly. (Debugging points the error stack at CvPlayer::GetPlayerTraits, return m_pTraits)

I've gone through a few iterations back and forth, trying to see which way to wiggle it. I'm left at this most recent one (that still doesn't work):
Code:
	if ((GET_PLAYER(plot.getOwner()).GetPlayerTraits()->IsBarbariansAllowed()) && isBarbarian())
	{
		return false;
	}

I don't... actually know C++, so this has been quite the experience. To my understanding, plot.getOwner will pull up a PlayerID number, so of course just attaching plot.getOwner to GetPlayerTraits doesn't work. That's why I thought GET_PLAYER would work. (At least, I only have other parts of the code and what I've seen other people do to go off of.)

Am I right to assume this has to be the part of the code that has the issue, if I don't get a CTD by commenting it out? (I mean, would the game give me errors if somehow I messed up putting in the trait, even if the trait isn't utilized by anything?)
 
Top Bottom