[Sdk] Change city artstyle if you have specific civic

Zlatko

CIW
Joined
Apr 1, 2010
Messages
713
Location
Solar System
I move all my posts here and all answers from other members, because its easier to debate in new thread then in Quick Modding Questions, my current progress in next posts below this correspondence.

Zlatko said:
I want to share my code with community and i have one question.
This code correct work and allow you to only once choose your civic from one civicoption (You can only choose once your affinity, choose wise between Harmony, Purity and Supremacy).
Solved idea from THIS post.
CvGameUtils.py:
Code:
	def cannotDoCivic(self,argsList):
		ePlayer = argsList[0]
		eCivic = argsList[1]
		pPlayer = gc.getPlayer(ePlayer)
		if(pPlayer.isCivic(gc.getInfoTypeForString("CIVIC_HARMONY")) == true):
			if(str(gc.getInfoTypeForString("CIVIC_NO_AFFINITY")) == str(eCivic) or str(gc.getInfoTypeForString("CIVIC_PURITY")) == str(eCivic) or str(gc.getInfoTypeForString("CIVIC_SUPREMACY")) == str(eCivic)):
				return True
		elif(pPlayer.isCivic(gc.getInfoTypeForString("CIVIC_PURITY")) == true):
			if(str(gc.getInfoTypeForString("CIVIC_NO_AFFINITY")) == str(eCivic) or str(gc.getInfoTypeForString("CIVIC_HARMONY")) == str(eCivic) or str(gc.getInfoTypeForString("CIVIC_SUPREMACY")) == str(eCivic)):
				return True
		elif(pPlayer.isCivic(gc.getInfoTypeForString("CIVIC_SUPREMACY")) == true):
			if(str(gc.getInfoTypeForString("CIVIC_NO_AFFINITY")) == str(eCivic) or str(gc.getInfoTypeForString("CIVIC_HARMONY")) == str(eCivic) or str(gc.getInfoTypeForString("CIVIC_PURITY")) == str(eCivic)):
				return True
		return False

This demand,
PythonCallbackDefines.py:
Code:
	<Define>
		<DefineName>USE_CANNOT_DO_CIVIC_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
QUESTIONS:

1) Where is event, function, method or whatever, which trigger when i switch to some civic ?

2) I want to change cityart when some player switch to some civic, example:
ARABIA, (Saladin) have ARTSTYLE_ARABIA,
if Saladin switch to CIVIC_HARMONY, i want to ARABIA have ARTSTYLE_HARMONY,
if switch to CIVIC_PURITY it will have ARTSTYLE_PURITY,
if switch to CIVIC_SUPREMACY it will have ARTSTYLE_SUPREMACY.
here is some code improvisation / prototype but of course its not work and give a error (and if this code successful up and running, i want to put it in place from question 1)):
Code:
	def cannotDoCivic(self,argsList):
		ePlayer = argsList[0]
		eCivic = argsList[1]
		pPlayer = gc.getPlayer(ePlayer)
		if(pPlayer.isCivic(gc.getInfoTypeForString("CIVIC_HEREDITARY_RULE")) == true):
			(loopCity, iter) = pPlayer.firstCity(false)
			while(loopCity):
				loopCity.setArtStyleType(0)
				(loopCity, iter) = pPlayer.nextCity(iter, false)
Do i must change artstyle of every city from player in this case ARABIA (Saladin) or it only enough to change civilization artstyle in game.

1) There is none.
2) There is no setArtStyleType in python unless you exposed it.

P.S.
If there are only 4 civics, you might as well just simply write:

Code:
	def cannotDoCivic(self,argsList):
		ePlayer = argsList[0]
		eCivic = argsList[1]
		pPlayer = gc.getPlayer(ePlayer)
		if pPlayer.isCivic(gc.getInfoTypeForString("CIVIC_NO_AFFINITY")):
			return False
		return True
Why so troublesome.

1) dll - start with CvPlayer::canDoCivics

2) dll only - start here or here or here or here or here or there (prepare food supply for a week) ;)

Zlatko said:
1) There is none.
2) There is no setArtStyleType in python unless you exposed it.

P.S.
If there are only 4 civics, you might as well just simply write:

Code:
	def cannotDoCivic(self,argsList):
		ePlayer = argsList[0]
		eCivic = argsList[1]
		pPlayer = gc.getPlayer(ePlayer)
		if pPlayer.isCivic(gc.getInfoTypeForString("CIVIC_NO_AFFINITY")):
			return False
		return True
Why so troublesome.

No, i don't have only 4 civics, i have several CIVICOPTION_... and i in every CIVICOPTION_... i have several CIVIC_...

I must in C++ code expose setArtStyleType in python ?

1) dll - start with CvPlayer::canDoCivics

2) dll only - start here or here or here or here or here or there (prepare food supply for a week) ;)

1) in CvPlayer::canDoCivics i must hardcode my idea ?

2) :(

I was once asked to implement 2) in RaR (colo mod, but this part of the code is the same), but due to complexity and since it wasn't actually my mod, I wasn't sure if it would even be accepted in it. Still I figured out that there are two ways to do it.

A: the DLL has a unit function the exe calls to get the art string. Edit that one to return whatever art string you want. You need getOwnerINLINE() and get the civic for that player to determine which one you have. Add more art tags to xml, which can then be used as return values. You may have to mark the screen dirty in CvPlayer::doCivic() to force the exe to ask the dll for unit art for all units again. The exe is quite good at caching data like that, which is good for performance, but it can prevent your graphical changes from being visible.

B: big hack. Alter the art in the info class. I'm not recommending it, but Age Of Discovery II use that approach when declaring revolution. Likewise you could change the info class from CvPlayer::doCivic(). However doing that would ensure your ticket to programmer hell. One issue is that it doesn't reset on load or new game, but there are several other issues as well. Changing the info classes after game start is generally not a good idea.

If you have the skill to make A, then it should be fine and releasing a standalone modcomp for it would be nice as other people could benefit from it. If you have to resort to B, then I would recommend that you stop for a moment and think if you really want this feature badly enough to violate the info class concept.

Looks like Zlatko posted before I was done writing :(

I must in C++ code expose setArtStyleType in python ?

C++ is way better for this than python is. If you aren't ready to make this in C++, I would say you aren't ready to make this at all. I know it's a bit harsh to say it like that, but really, it's part of the graphic drawing system. You don't want to introduce python execution speed.

Well I guess you could edit the dll to cache the art strings in CvPlayer and then set the strings from python. I would consider that a poor design though.

Zlatko,

1) didn't say that you have to hardcode things there, you just asked where was the trigger.

2) maybe check this Captured City Art mod comp for ideas on how to do it

Why me always think of some crazy ideas in modding ?

@Nightinggale
I will try to make this, something i maybe don't said, i want to change city artstyle, not units.

@isenchine
I will check.

DoC has conditional city art styles (based on majority culture instead of owner, but that can be easily changed to civics or anything else really) in the DLL, including caching (no need to waste performance every time the screen is redrawn). I ran into some pitfalls you could avoid, the source code is here. Just work your way backwards from the CvCity::getArtStyle() method.

@Nightinggale
I will try to make this, something i maybe don't said, i want to change city artstyle, not units.

Oops, didn't read your first post correctly. However cities work the same way. You most likely want to edit CvCity::getArtStyleType(). Maybe it would be best to call CvPlayer::getCityArtStyleType() and then write that new function to do precisely what you want. That way you have access to the player data rather than the city data.

Something like (pseudo code)
PHP:
CivilizationTypes& kCiv = GC.getCivilizationInfo();
if (hasCivic(CIVIC_HARMONY) && kCiv.getCityStyle(CIVIC_HARMONY).size > 0)
    return kCiv.getCityStyle(CIVIC_HARMONY)
else if (hasCivic(CIVIC_PURITY) && kCiv.getCityStyle(CIVIC_PURITY).size > 0)
    return kCiv.getCityStyle(CIVIC_PURITY)

(more checks)

// fallback in case nothing triggers 
return getArtStyleType();
I think that should do it as long as you add CvCivilizationInfo::getCityStyle, which will return strings from xml. It even has check for valid strings and a fallback, which mean you don't have to fill out the xml data for all civs for this to work. If you just want it for a single one, fill it out for a single one and the rest will be unaffected.

This should work, at least in theory. It's quite possible that it could be written a bit better than this. I just wrote this quickly without any real checks other than how city arty style works. It's more of a concept than actual code.

EDIT
Once again somebody writes while I'm typing.

including caching (no need to waste performance every time the screen is redrawn). I ran into some pitfalls you could avoid

I thought about caching as well. However I decided to keep it simple. Maybe the best solution is to cache the city style string in CvPlayer and get CvCity to read that string. It's just a matter of a single string, which can only be changed by doCivic as the style is the same for all cities. DoC appears to have one style for each city (possibly), which mean a single style cache for each player wouldn't work. However with the option of copy pasting existing code, it might still be the way to go, even if the cache isn't the best suited for your needs.

How i can see m_iArtStyleType from CvInfos.cpp is main responsible for city art style,
because in CvCity.cpp has ArtStyleTypes CvCity::getArtStyleType() const, which return PLAYER'S .getArtStyleType() from CvPlayer.cpp
from this method ArtStyleTypes CvPlayer::getArtStyleType() const and here return m_iArtStyleType this line 'return ((ArtStyleTypes)(GC.getCivilizationInfo(getCivilizationType()).getArtStyleType()));' from CvInfos.cpp


CvInfos.cpp:
Code:
int CvCivilizationInfo::getArtStyleType() const
{
	return m_iArtStyleType;
}

On begging he get value here:
CvInfos.cpp:
Code:
	pXML->GetChildXmlValByName(szTextVal, "ArtStyleType");
	m_iArtStyleType = GC.getTypesEnum(szTextVal);

CvInfos.h
Code:
[COLOR="Blue"]protected:[/COLOR]
	...
	int m_iArtStyleType;

CvCity.cpp
Code:
ArtStyleTypes CvCity::getArtStyleType() const
{
	return GET_PLAYER(getOwnerINLINE()).getArtStyleType();
}

CvPlayer.cpp
Code:
ArtStyleTypes CvPlayer::getArtStyleType() const
{
	if (GC.getInitCore().getArtStyle(getID()) == NO_ARTSTYLE)
	{
		return ((ArtStyleTypes)(GC.getCivilizationInfo(getCivilizationType()).getArtStyleType()));
	}
	else
	{
		return GC.getInitCore().getArtStyle(getID());
	}
}

1) if change m_iArtStyleType in CvInfos.cpp during the game, is that affect on all cities from that player in game ?

2) I am little bit confused, i already asked for trigger when and where player change CIVIC in .cpp ? I must in the moment when player switch to another civic, then i must change m_iArtStyleType. And in that part of code i can implement @Nightinggale pseudo code.

3) Player and civilization get ArtStyleType from XML, i must change that ArtStyleType, it same like when you make map in world builder and change artstyle for players or change name etc, example:

Code:
BeginPlayer
	Team=12
	LeaderType=LEADER_MANSA_MUSA
	LeaderName=TXT_KEY_LEADER_MANSA_MUSA
	CivDesc=TXT_KEY_CIV_MALI_DESC
	CivShortDesc=TXT_KEY_CIV_MALI_SHORT_DESC
	CivAdjective=TXT_KEY_CIV_MALI_ADJECTIVE
	FlagDecal=Art/Interface/TeamColor/FlagDECAL_Mask.dds
	WhiteFlag=0
	CivType=CIVILIZATION_MALI
	Color=PLAYERCOLOR_PEACH
	[B][COLOR="Red"]ArtStyle=ARTSTYLE_AFRICA[/COLOR][/B]
	PlayableCiv=1
	MinorNationStatus=0
	StartingGold=0
	StartingX=85, StartingY=51
	StateReligion=
	StartingEra=ERA_ANCIENT
	RandomStartLocation=false
	CivicOption=CIVICOPTION_GOVERNMENT, Civic=CIVIC_DESPOTISM
	CivicOption=CIVICOPTION_LEGAL, Civic=CIVIC_BARBARISM
	CivicOption=CIVICOPTION_LABOR, Civic=CIVIC_TRIBALISM
	CivicOption=CIVICOPTION_ECONOMY, Civic=CIVIC_DECENTRALIZATION
	CivicOption=CIVICOPTION_RELIGION, Civic=CIVIC_PAGANISM
	CivicOption=CIVICOPTION_POLITICAL_PARTY, Civic=CIVIC_NO_POLITICAL_PARTY
	Handicap=HANDICAP_NOBLE
EndPlayer
changed to HARMONY
Code:
BeginPlayer
	Team=12
	LeaderType=LEADER_MANSA_MUSA
	LeaderName=TXT_KEY_LEADER_MANSA_MUSA
	CivDesc=TXT_KEY_CIV_MALI_DESC
	CivShortDesc=TXT_KEY_CIV_MALI_SHORT_DESC
	CivAdjective=TXT_KEY_CIV_MALI_ADJECTIVE
	FlagDecal=Art/Interface/TeamColor/FlagDECAL_Mask.dds
	WhiteFlag=0
	CivType=CIVILIZATION_MALI
	Color=PLAYERCOLOR_PEACH
	[B][COLOR="Red"]ArtStyle=ARTSTYLE_HARMONY[/COLOR][/B]
	PlayableCiv=1
	MinorNationStatus=0
	StartingGold=0
	StartingX=85, StartingY=51
	StateReligion=
	StartingEra=ERA_ANCIENT
	RandomStartLocation=false
	CivicOption=CIVICOPTION_GOVERNMENT, Civic=CIVIC_DESPOTISM
	CivicOption=CIVICOPTION_LEGAL, Civic=CIVIC_BARBARISM
	CivicOption=CIVICOPTION_LABOR, Civic=CIVIC_TRIBALISM
	CivicOption=CIVICOPTION_ECONOMY, Civic=CIVIC_DECENTRALIZATION
	CivicOption=CIVICOPTION_RELIGION, Civic=CIVIC_PAGANISM
	CivicOption=CIVICOPTION_POLITICAL_PARTY, Civic=CIVIC_NO_POLITICAL_PARTY
	Handicap=HANDICAP_NOBLE
EndPlayer
and Mansa Musa of Mali will now have ARTSTYLE_HARMONY instead ARTSTYLE_AFRICA, and i must change that variable 'ArtStyle=' in the moment during player switch to another civic, somewhere in source code.

I make what i want, but its work on way on which i don't want to work. And of course this is just prototype version. Civilization get new city art when player switch to any civic (that is for now), but this new city art stay for that civilization, for example:

- I play with CHINA, and CHINA have ASIAN city style, when i switch to any civic, CHINA get ARABIAN city style, if i return to main menu and again start some new game with CHINA, CHINA have ARABIAN city style, instead of ASIAN.

- If i save game when CHINA have ASIAN city style, and change my civic, and CHINA get ARABIAN city style, and i go to load game, CHINA now have ARABIAN city style instead of ASIAN city style.

- CHINA only again get their default city style (ASIAN), if i exit from my mod, and load my mod again.

NEW CODE

CvPlayer.cpp:
Code:
void CvPlayer::setCivics(CivicOptionTypes eIndex, CivicTypes eNewValue)
{
	CvWString szBuffer;
	CivicTypes eOldCivic;
	int iI;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumCivicOptionInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eNewValue >= 0, "eNewValue is expected to be non-negative (invalid Index)");
	FAssertMsg(eNewValue < GC.getNumCivicInfos(), "eNewValue is expected to be within maximum bounds (invalid Index)");

	eOldCivic = getCivics(eIndex);

	if (eOldCivic != eNewValue)
	{
		m_paeCivics[eIndex] = eNewValue;

		if (eOldCivic != NO_CIVIC)
		{
			processCivics(eOldCivic, -1);
		}
		if (getCivics(eIndex) != NO_CIVIC)
		{
			processCivics(getCivics(eIndex), 1);
		}

		GC.getGameINLINE().updateSecretaryGeneral();

		GC.getGameINLINE().AI_makeAssignWorkDirty();

		if (GC.getGameINLINE().isFinalInitialized())
		{
			if (gDLL->isDiplomacy() && (gDLL->getDiplomacyPlayer() == getID()))
			{
				gDLL->updateDiplomacyAttitude(true);
			}

/************************************************************************************************/
/* REVOLUTION_MOD                         04/28/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
			if (!isBarbarian())
*/
			// Silence announcement for civs that are not alive, ie rebel civs who may not be born
			// and also for minor civs
			if (!isBarbarian() && !isMinorCiv() && isAlive())
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
			{
				if (getCivics(eIndex) != NO_CIVIC)
				{
					if (getCivics(eIndex) != GC.getCivilizationInfo(getCivilizationType()).getCivilizationInitialCivics(eIndex))
					{
						for (iI = 0; iI < MAX_PLAYERS; iI++)
						{
							if (GET_PLAYER((PlayerTypes)iI).isAlive())
							{
								if (GET_TEAM(getTeam()).isHasMet(GET_PLAYER((PlayerTypes)iI).getTeam()))
								{
									szBuffer = gDLL->getText("TXT_KEY_MISC_PLAYER_ADOPTED_CIVIC", getNameKey(), GC.getCivicInfo(getCivics(eIndex)).getTextKeyWide());
									gDLL->getInterfaceIFace()->addMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MAJOR_EVENT);
								}
							}
						}

						szBuffer = gDLL->getText("TXT_KEY_MISC_PLAYER_ADOPTED_CIVIC", getNameKey(), GC.getCivicInfo(getCivics(eIndex)).getTextKeyWide());
						GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szBuffer);
					}
[COLOR="SeaGreen"]// < ZLATKO RECONSTRUCTION START > EXPERIMENT[/COLOR]
					[COLOR="Red"]GC.getCivilizationInfo(getCivilizationType()).setArtStyleType(2);[/COLOR]
[COLOR="SeaGreen"]// < ZLATKO RECONSTRUCTION END >[/COLOR]
				}
			}
		}

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      09/03/09                       poyuzhe & jdog5000     */
/*                                                                                              */
/* Efficiency                                                                                   */
/************************************************************************************************/
		// From Sanguo Mod Performance, ie the CAR Mod
		// Attitude cache
		for (int iI = 0; iI < MAX_PLAYERS; iI++)
		{
			GET_PLAYER(getID()).AI_invalidateAttitudeCache((PlayerTypes)iI);
			GET_PLAYER((PlayerTypes)iI).AI_invalidateAttitudeCache(getID());
		}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

	}
}

CvInfos.h:
Code:
class CvArtInfoCivilization;
class CvCivilizationInfo :
	public CvInfoBase
{
	//---------------------------------------PUBLIC INTERFACE---------------------------------
public:
	....
[COLOR="SeaGreen"]// < ZLATKO RECONSTRUCTION START > EXPERIMENT[/COLOR]
	[COLOR="Red"]void setArtStyleType(int m_iArtStyleType);[/COLOR]
[COLOR="SeaGreen"]// < ZLATKO RECONSTRUCTION END >[/COLOR]
	....
};

CvInfos.cpp:
Code:
// < ZLATKO RECONSTRUCTION START > EXPERIMENT
void CvCivilizationInfo::setArtStyleType(int m_iArtStyleType)
{
	this->m_iArtStyleType = m_iArtStyleType;
}
// < ZLATKO RECONSTRUCTION END >

What is it with me and posting together with other people today? Now it's the 3rd time in one day in the same thread :crazyeye:

- If i save game when CHINA have ASIAN city style, and change my civic, and CHINA get ARABIAN city style, and i go to load game, CHINA now have ARABIAN city style instead of ASIAN city style.

Sounds like you fail to save the variable. YOu need to add the new variable to CvPlayer::read() and write(). Order matters and you will break old savegames, unless you write some backward compatibility code using uiFlag.

Code:
GC.getCivilizationInfo(getCivilizationType()).setArtStyleType(2);

I would recommend using an enum if you want to hardcode numbers into the DLL and XML values if you want it to be modder friendly. Using numbers like 2 will not only make the code unreadable, it will also haunt you later on if you need to change something.
 
1) I switch to CIVIC which change city artstyle + improvements and entire my art changed, default artstyle for Serbia is European, but we now see Arabian, Image1


Image1

After that i switch to some another CIVIC which don't load this temporary city art and nothing happen, maybe because is civilization in ANARCHY (change only occur on city stagnation or city grow) Image2


Image2

And ANARCHY is over and we can see that Belgrade have their default artstyle (FROM XML) and improvements are again default, town(improvement) which is north-east from Belgrade have Arabian artstyle,
but i click on city and click to that plot (population already work on that plot), and when i clicked town get their default art, Image3


Image3

Now we see city of Novi Sad which still have ARABIAN artstyle instead of EUROPEAN, i already say that city artstyle change on city grow or city stagnation, Image4


Image4

And Novi Sad is grow and change their artstyle to default (EUROPEAN), Image5


Image5

Nothing special, Image6


Image6

I switch to CIVIC which again change my artstyle to ARABIAN, Belgrade grow and change artstyle from default to ARABIAN, and town(improvement) NORTH-EAST from Belgrade still have EUROPEAN
instead of ARABIAN artstyle, Novi Sad is not grow and still have EUROPEAN artstyle, but plantation (south-west from Novi Sad) which is under city of Novi Sad have ARABIAN artstyle, Image7


Image7

Very interesting, farms inside cultural border have ARABIAN artstyle, but farm outside have EUROPEAN and town(improvement) north-east from Belgrade still have EUROPEAN instead ARABIAN artstyle, Image8


Image8

I open World Builder, and town(improvement) north-east from Belgrade and all improvements outside from cultural borders are changed to ARABIAN artstyle (updated), Image9


Image9

2) I start with CHINA, Image10


Image10

I switch to CIVIC which change artstyle and open World Builder and all improvement are updated to this new ARTSTYLE, Image11


Image11

City change artstyle on stagnation, grow or building build, Image12


Image12

AND SOMETIMES WHEN I EXIT TO MAIN MENU, GAME CRUSH, but only when i start new game like from these images, and click exit to main menu, game crush then. This crush begin at the moment when i begin develop my HARMONY, PURITY and SUPREMACY CIVICs, and in the moment when i change in XML and Python, before SDK, but when i start experimenting and merge Captured City Art (this was i test, after that i delete all source files and use backup files) this became frequent, before this i merge some components from FFH2, this is now just doing with Debug DLL, i will test Release DLL now is to late, i go to sleep.
 
I think it's good that this now has a dedicated thread. There is so much info now that I lost track of it and it's nowhere near a quick question.

I kind of suspect there is an issue with city graphics not being marked dirty, hence the exe keeps on drawing them using the old style. It's perfectly fine to change the style in the DLL, but it will not work if the exe remembers the answer from the last time it asked for the style. This mean you have to tell it to ask again, which is done with marking it dirty. The question is, which of the dirty features is related to city style?
 
Captured City Art might not be stable and might not even work. It was to give you hints on where to start in the dll.

I have the old version by DPII in archive format (could not find it back in CFC), it's stable but I don't know if it really works.

I attach it here in case you're interested.

I'm not able to help you much with C++.
 
I think it's good that this now has a dedicated thread. There is so much info now that I lost track of it and it's nowhere near a quick question.

I kind of suspect there is an issue with city graphics not being marked dirty, hence the exe keeps on drawing them using the old style. It's perfectly fine to change the style in the DLL, but it will not work if the exe remembers the answer from the last time it asked for the style. This mean you have to tell it to ask again, which is done with marking it dirty. The question is, which of the dirty features is related to city style?

You are see all images, and i must force update all city graphic and improvement, city graphic change on city build, on city grow, on city stagnation and on building build in that city. Improvement change on player turn begin (but i don't sure) and 100% change when you click on city and click on city plot to move population to work on that plot, or remove and again move to work on that city plot and all improvement automatic update if you open World Builder. Below isenchine's answer i am post current source code.

Captured City Art might not be stable and might not even work. It was to give you hints on where to start in the dll.

I have the old version by DPII in archive format (could not find it back in CFC), it's stable but I don't know if it really works.

I attach it here in case you're interested.

I'm not able to help you much with C++.

Thank you isenchine, it's not problem i was made little strategy game in C++ for my final work on University, but I never go deeper in programming such as DLL.


CURRENT SOURCE CODE FOR THIS MOD COMPONENT (It's hard coded for now, but in future i will put XML tags, this is just a prototype for now):

How this work? Idea is to send a fake graphic to player and city, and this fake graphic can change value, original variable as m_iArtStyleType in CvInfos will forever keep their original value from XML, its important because if you again switch to another CIVIC which not change ARTSTYLE, you will get your original ARTSTYLE (China will again have their default ASIAN, Serbia will again have their default EUROPEAN). Current problem is force graphic update (i must found solution to force and instant update all cities graphics and improvements if you switch to CIVIC which change ARTSTYLE, no more waiting for city grow, stagnation or build).

CvInfos.h:
Code:
class CvArtInfoCivilization;
class CvCivilizationInfo :
	public CvInfoBase
{
	//---------------------------------------PUBLIC INTERFACE---------------------------------
public:
.....
	DllExport int getArtStyleType() const;				// Expose to Python
// < ZLATKO RECONSTRUCTION START > EXPERIMENT
	DllExport int getArtStyleTypeViaCivic() const;
// < ZLATKO RECONSTRUCTION END >
	DllExport int getUnitArtStyleType() const;         // Expose to Python
....

// < ZLATKO RECONSTRUCTION START > EXPERIMENT
	void setArtStyleType(int m_iArtStyleType);
	void setArtStyleTypeViaCivic(int m_iArtStyleTypeViaCivic);
// < ZLATKO RECONSTRUCTION END >
....
protected:

	int m_iDefaultPlayerColor;	
	int m_iArtStyleType;
// < ZLATKO RECONSTRUCTION START > EXPERIMENT
	int m_iArtStyleTypeViaCivic; // current ARTSTYLE which depend on CIVIC
// < ZLATKO RECONSTRUCTION END >
	int m_iUnitArtStyleType;  // FlavorUnits by Impaler[WrG]

CvInfos.cpp: (m_iArtStyleTypeViaCivic represent fake m_iArtStyleType, which cities and player get if have specific civic instead of to get m_iArtStyleType, m_iArtStyleTypeViaCivic have all methods as m_iArtStyleType, it's just duplicated variable which do good job)
Code:
.....
m_iDefaultPlayerColor(NO_PLAYERCOLOR),
m_iArtStyleType(NO_ARTSTYLE),
// < ZLATKO RECONSTRUCTION START > EXPERIMENT
m_iArtStyleTypeViaCivic(NO_ARTSTYLE),
// < ZLATKO RECONSTRUCTION END >
m_iUnitArtStyleType(NO_UNIT_ARTSTYLE),
.....

// < ZLATKO RECONSTRUCTION START > EXPERIMENT
int CvCivilizationInfo::getArtStyleTypeViaCivic() const
{
	return m_iArtStyleTypeViaCivic;
}
// < ZLATKO RECONSTRUCTION END >
.....
	stream->Read(&m_iArtStyleType);
// < ZLATKO RECONSTRUCTION START > EXPERIMENT
	stream->Read(&m_iArtStyleTypeViaCivic);
// < ZLATKO RECONSTRUCTION END >
	stream->Read(&m_iUnitArtStyleType);   // FlavorUnits by Impaler[WrG]
....
	stream->Write(m_iArtStyleType);
// < ZLATKO RECONSTRUCTION START > EXPERIMENT
	stream->Write(m_iArtStyleTypeViaCivic);
// < ZLATKO RECONSTRUCTION END >
	stream->Write(m_iUnitArtStyleType);
....

// < ZLATKO RECONSTRUCTION START > EXPERIMENT
	pXML->GetChildXmlValByName(szTextVal, "ArtStyleType");
	m_iArtStyleTypeViaCivic = GC.getTypesEnum(szTextVal);
// < ZLATKO RECONSTRUCTION END >
....
// < ZLATKO RECONSTRUCTION START > EXPERIMENT CONFLICT
	if ( getArtStyleType() == NO_ARTSTYLE ) // "ArtStyleType"
	{
		m_iArtStyleTypeViaCivic = (pClassInfo->getArtStyleType());
	}
// < ZLATKO RECONSTRUCTION END >
....
// < ZLATKO RECONSTRUCTION START > EXPERIMENT
void CvCivilizationInfo::setArtStyleType(int m_iArtStyleType)
{
	this->m_iArtStyleType = m_iArtStyleType;
}
void CvCivilizationInfo::setArtStyleTypeViaCivic(int m_iArtStyleTypeViaCivic)
{
	this->m_iArtStyleTypeViaCivic = m_iArtStyleTypeViaCivic;
}
// < ZLATKO RECONSTRUCTION END >

CvPlayer.cpp:
Code:
ArtStyleTypes CvPlayer::getArtStyleType() const
{
// < ZLATKO RECONSTRUCTION START > EXPERIMENT CONFLICT
	if(isCivic((CivicTypes)(GC.getInfoTypeForString("CIVIC_HEREDITARY_RULE"))) == true)
	{
		GC.getCivilizationInfo(getCivilizationType()).setArtStyleTypeViaCivic((ArtStyleTypes)(GC.getInfoTypeForString("ARTSTYLE_ARABIA")));
		return ((ArtStyleTypes)(GC.getCivilizationInfo(getCivilizationType()).getArtStyleTypeViaCivic()));
	}
// < ZLATKO RECONSTRUCTION END >
	if (GC.getInitCore().getArtStyle(getID()) == NO_ARTSTYLE)
	{
		return ((ArtStyleTypes)(GC.getCivilizationInfo(getCivilizationType()).getArtStyleType()));
	}
	else
	{
		return GC.getInitCore().getArtStyle(getID());
	}
}

CvCity.cpp:
Code:
ArtStyleTypes CvCity::getArtStyleType() const
{
// < ZLATKO RECONSTRUCTION START > EXPERIMENT
	if(GET_PLAYER(getOwnerINLINE()).isCivic((CivicTypes)(GC.getInfoTypeForString("CIVIC_HEREDITARY_RULE"))) == true)
	{
		GC.getCivilizationInfo(getCivilizationType()).setArtStyleTypeViaCivic((ArtStyleTypes)(GC.getInfoTypeForString("ARTSTYLE_ARABIA")));
		return ((ArtStyleTypes)(GC.getCivilizationInfo(getCivilizationType()).getArtStyleTypeViaCivic()));
	}
// < ZLATKO RECONSTRUCTION END >
	return GET_PLAYER(getOwnerINLINE()).getArtStyleType();
}

AND I DON'T GET APP CRUSH IN RELEASE DLL IF I RETURN TO MAIN MENU, I JUST GET IN DEBUG DLL.
 
FIXED:

All cities graphics and all improvements graphics (ARTSTYLE) are now instant update if player switch to CIVIC which change ARTSTYLE and if player switch to another CIVIC which is not specific CIVIC which change ARTSTYLE, artstyle of all cities and all improvements will instant update to default ARTSTYLE.
That is it, this component WORKS NOW and this is my FIRST SDK COMPONENT.
It's only need to make tag for user input, because this is hard coded for now.

Default ARTSTYLE:



New ARTSTYLE, instant update if you have specific CIVIC:

 
I have one problem and i really don't have idea how to fix it, in this hard-coded version all works great, and this is save/load game compatibility, but in version in which i add tags and when you change artstyle in tag, that works, all works and it's nice and interesting, but it's not save/load game compatibility, me really need some idea, how to fix this.
 
Hopefully you kept the hardcoded version because comparing those two would be interesting. In fact I would recommend you store your mod in git because it allows you to commit and as such set milestones where something works, which then allows you to revert to that point if you screw up. Setting up git on something like SourceForge also allows other people to read your code, which also helps in cases like this one.

My guess is that the tag system reads some data, sets the graphics and then reads some more. Try marking the city dirty as the last thing to do in CvCity::read() and see if that helps.
 
Where is place in code, in which Player (Human/AI) will be initialize (think on begging playing civilization on some map) ?

@Nightinggale
Thank you for advice.

@Tholal
Yes, i do that and all works fine in hard-coded version, but in version with XML tag that don't work and i must use different logic and different idea for that version.
 
CvPlayer has both reset() and init(). The latter is likely the one you need.

I see init(), but CvPlayer have
void initInGame(PlayerTypes eID, bool bSetAlive);
which is difference ?
 
Top Bottom