Questions about Great People and AI

PawelS

Ancient Druid
Joined
Dec 11, 2003
Messages
2,811
Location
Poland
There are no Great Works in my mod (so far), and no Writers, Musicians or Tourism. So I'm going to give my version of the Great Artist two abilities: start a Golden Age (like Great Artist) or create a culture boost (like Great Writer). I have 3 questions:

1. Will such unit cause problems with the standard DLL?

2. Which UnitAI is best for it? UNITAI_ARTIST or UNITAI_WRITER (or both, but then which should be the default one)?

3. Is it possible to make the AI use any of the two abilities (depending on the AI's decision) or only to always use one of them? (Probably related to the above question about UnitAI type.)
 
All hail Firaxis, the gods of hard-coding-every-single-thing-in!!

Your proposed changes by themselves will not cause any DLL issues, but the new ability (culture blast) would not be used by the AI if left to its own devices (see the last point).

The code you're looking for is contained in:

Code:
GreatPeopleDirectiveTypes CvPlayerAI::GetDirectiveArtist(CvUnit* pGreatArtist)
and
Code:
GreatPeopleDirectiveTypes CvPlayerAI::GetDirectiveWriter(CvUnit* pGreatWriter)

Broadly speaking, you will need to copy-paste the eDirective from the Great Writer, such as

Code:
// Defend against ideology pressure if not going for culture win
	if (eDirective == NO_GREAT_PEOPLE_DIRECTIVE_TYPE && !GetDiplomacyAI()->IsGoingForCultureVictory() && GetCulture()->GetPublicOpinionUnhappiness() > 10)
	{
		eDirective = GREAT_PEOPLE_DIRECTIVE_CULTURE_BLAST;
	}
(note: Great Writer has 2 situations where it will culture-blast - defend from ideology pressure, and to get a policy).

Code:
void CvPlayerAI::ProcessGreatPeople(void)

is the function that controls which of the GetDirective functions are called, so you will need to set it to UNITAI_ARTIST if you want it processed as an artist. Assigning UNITAI_WRITER would cause it to only use the Directives that are assigned to Great Writers.
 
I'm not going to make changes in the DLL for now, but I have an idea: I can make two versions of the unit, one with UNITAI_ARTIST and one with UNITAI_WRITER. And when the AI gets this Great Person, it will be replaced with the other version with 50% probability (using Lua). So the AI will use one of the two abilities, chosen at random.

Edit: Or perhaps I don't have to make two versions of the unit, but instead I can delete the unit and replace it with the same unit but with a different AI type (UnitAIType is one of the parameters for Player:InitUnit). I will try to do it and report here if it works.
 
I don't have to delete the unit - as I learned here, there is a Unit.SetUnitAIType function, so using the Events.SerialEventUnitCreated I managed to make the Great Artist use a random AI (Artist or Writer). It seems to work properly so far - sometimes the AI uses them to start a Golden Age, sometimes to boost culture (I can distinguish between these situations by checking if the AI gets extra gold from its tiles due to a Golden Age or not).
 
You might want to double-check the Events.SerialEventUnitCreated does not re-fire for all the Great People when the game is loaded from a save and there are still Great People on the game-map. I seem to remember running into that problem for "regular" units, and I think it was one of the reasons for Machiavelli24's LuaEvents.SerialEventUnitCreatedGood system.
 
All my code that uses this event is constructed in a way that it doesn't matter how many times the event is fired. In this case it assigns one of the two AI types at random to the unit. So it can change the AI type when it's fired again, but it's still 50% chance for each AI type.
 
Give the base unit a different AI type to either of those desired, eg UNITAI_DEFENSE, and only flip it on the event if the unit still has that (invalid) default type
 
@whoward69: I thought about it, but I decided not to use such solution because assigning a default AI type that doesn't make sense for this kind of unit (like defense for a civilian unit) can potentially cause problems. The current solution works, so I'll keep it for now.
 
Top Bottom