adapt a script

There's a religionFounded event in Python that receives the ID of the founding player (iFounder). The DLL creates this event after assigning the Holy City, probably while processing new tech at the end of a player's or team's turn (in most cases). Declaring a war at that point probably won't cause any chaos. If it did, the war declaration could instead be handled in on BeginPlayerTurn. But let's try in in response to 'religionFounded':
Python:
iReligion, iFounder = argsList
iTarget = gc.getPlayer(iFounder).getTeam()
for iTeam in range(gc.getMAX_CIV_TEAMS()):
	if gc.getTeam(iTeam).canDeclareWar(iTarget):
		gc.getTeam(iTeam).declareWar(iTarget, False, WarPlanTypes.WARPLAN_DOGPILE)
Untested as usual, hopefully I got the syntax right. canDeclareWar should take care of all the sanity tests. It'll also mean that peace treaties prevent the war (even if the peace treaties is just 1 turn from expiring). DOGPILE should be the most heplful (for the AI) war plan type, which iirc is also used for the wars caused by the Apostolic Palace. The number 1 in your code would correspond to a defensively oriented WARPLAN_ATTACKED_RECENT. "False" for bNewDiplo should mean that there's no diplo popup.

Edit: MAX_CIV_PLAYERS corrected to MAX_CIV_TEAMS
 
Last edited:
could this be good?I did 2 tests Thanks for your availability as always
 

Attachments

  • 123.jpg
    123.jpg
    43.8 KB · Views: 15
  • 123.jpg
    123.jpg
    62.5 KB · Views: 11
Last edited:
So the aim is that only a particular pair of "warring" religions causes these declarations of war? In that case, I would check whether iReligion – the religion just founded – is the one religion and whether iTeam in the loop has at least one player of the second religion.
Spoiler :
Python:
iReligion, iFounder = argsList
if iReligion != gc.getInfoTypeForString("RELIGION_VICTIM"):
	return
iTarget = gc.getPlayer(iFounder).getTeam()
iAggressorReligion = gc.getInfoTypeForString("RELIGION_AGGRESSOR")
for iPlayer in range(gc.getMAX_CIV_PLAYERS()):
	if gc.getPlayer(iPlayer).getStateReligion() != iAggressorReligion:
		continue
	iTeam = gc.getPlayer(iPlayer).getTeam()
	if gc.getTeam(iTeam).canDeclareWar(iTarget):
		gc.getTeam(iTeam).declareWar(iTarget, False, WarPlanTypes.WARPLAN_DOGPILE)
This does not wait for the target to actually adopt the new religion. Just founding it is sufficient cause. Edit: And, yes, this is for an onReligionFounded handler like in your first screenshot.
 
Last edited:
yes, practically just founding religion "x" causes those who have religion y to declare war on it
this voice
if gc.getPlayer(iPlayer).getStateReligion() != iAggressorReligion:

If I understood correctly, it says that if the victim adopts religion x as the state religion, he is attacked by the founder of religion y. did I understand correctly?
perhaps it should then be the opposite, the founder of x must be the victim of the aggressor who has religion y as his state religion
this would already be fine, if the script obliged the founder of the religion "x" to make it the state religion.

edit: perhaps you have already translated well what I intended to read it well, it is practically the founder who declares war
 
Last edited:
So the aim is that only a particular pair of "warring" religions causes these declarations of war? In that case, I would check whether iReligion – the religion just founded – is the one religion and whether iTeam in the loop has at least one player of the second religion.
Spoiler :
Python:
iReligion, iFounder = argsList
if iReligion != gc.getInfoTypeForString("RELIGION_VICTIM"):
    return
iTarget = gc.getPlayer(iFounder).getTeam()
iAggressorReligion = gc.getInfoTypeForString("RELIGION_AGGRESSOR")
for iPlayer in range(gc.getMAX_CIV_PLAYERS()):
    if gc.getPlayer(iPlayer).getStateReligion() != iAggressorReligion:
        continue
    iTeam = gc.getPlayer(iPlayer).getTeam()
    if gc.getTeam(iTeam).canDeclareWar(iTarget):
        gc.getTeam(iTeam).declareWar(iTarget, False, WarPlanTypes.WARPLAN_DOGPILE)
This does not wait for the target to actually adopt the new religion. Just founding it is sufficient cause. Edit: And, yes, this is for an onReligionFounded handler like in your first screenshot.
thank you for your availability, it works perfectly, without your help I would never have succeeded
 
HI. I tried to make this script, do you think it would work to limit the movement of a unit with this promotion only within its own borders?with the right tabulations(numbers)
def onUnitMove(argsList):
12345678'unit move'
12345678pPlot,pUnit,pOldPlot = argsList
12345678if (pUnit is not None and
(pUnit.isHasPromotion(gc.getInfoTypeForString('PROMOTION_HUNTER')))):
1234567890123456if pPlot.isOwned()==True:
12345678901234567890return True
 
Last edited:
In the unitMove event handler, the unit has already moved, so it's really too late to stop it. To modify the movement rules, you need to add a handler for unitCannotMoveInto. If USE_UNIT_CANNOT_MOVE_INTO_CALLBACK isn't enabled yet, enabling it could hurt performance noticeably because that'll add a DLL-to-Python call for each unit path considered by the AI. Returning True from your unitCannotMoveInto handler will prevent the unit from entering (iPlotX, iPlotY), and the AI and UI (overlayed pathfinder waypoints) will be aware of that rule change too. To check the tile owner, gc.getMap().sPlot(iPlotX, iPlotY).getOwner() == ePlayer should work. The plot being given as a pair of coordinates is a little annoying; makes it necessary to look up the CvPlot object – hence the CyMap.sPlot call.
 
I wanted to create a building that disappears after a certain number of turns, do you think this script I made would work?thanks as always
 

Attachments

  • 1.png
    1.png
    25.3 KB · Views: 11
I don't know if a per-building timer will be any easier to implement than the unhappiness timer previously discussed. The game turn modulo 10 will allow you to destroy buildings on every turn number divisible by 10, but this won't take into account the turn on which the building was constructed. (And such code would belong in an at-turn-start event handler, not in onBuildingBuilt; - you don't want to destroy a building directly after it has been constructed.)

Ah, - the game does store the game year on which each building has been constructed. This is used for the doubling of culture rates after 1000 years (CommerceChangeDoubleTimes in Civ4BuildingInfos.xml). So destroying a building after a specific number of years would be pretty straightforward in a BeginPlayerTurn event handler:
Python:
iGameTurn, iPlayer = argsList
eBuilding = gc.getInfoTypeForString('BUILDING_XX')
iGameYear = gc.getGame().getGameTurnYear()
iBuildingLifetime = 40
for city in PlayerUtil.playerCities(iPlayer):
	if iGameYear > city.getBuildingOriginalTime(eBuilding) + iBuildingLifetime:
		city.setNumRealBuilding(eBuilding, 0)
This uses BUG's PlayerUtil for a more readable iteration over the player's cities. So this post is for once on topic (Python scripting with BUG). Will need to import PlayerUtil. BuildingOriginalTime gets treated as MIN_INT when the building hasn't been constructed at all, so something like minus infinity. Well, it doesn't hurt to set the building count to 0 when it already is at 0; so no need for a separate check whether the building exists.

Probably you don't want to do this based on years – but rather on game turns. Calculating the number of turns from the years would seem complicated, but, fortunately, there's CvGame::getTurnYear(int iGameTurn), which provides the year of a particular game turn. So we can simply set
Python:
iBuildingLifetime = iGameYear - gc.getGame().getTurnYear(iGameTurn - 10)
instead of setting it to a constant. E.g. if the current year is 1800 and 10 turns ago was 1780, then the building's maximal age should be 20 years.
 
Thanks, I'll try it right away. Unfortunately I realize that translating what you are looking for into Phyton language is difficult, but thanks to your help, it is
becoming increasingly easier to get closer to the solution. :) even if I'm still far away
Edit; first try
 

Attachments

  • 1.jpg
    1.jpg
    86.3 KB · Views: 11
  • 2.jpg
    2.jpg
    80.5 KB · Views: 10
Last edited:
That looks quite reasonable. If the building's type is indeed named BUILDING_XX. Could well be that I made some mistake of course.
 
HI. I need help with this platy script, I would like to add a variable that improves the relationship only if you have the same state religion as the player who builds Taipei, I tried to add it myself but I don't know if I wrote it right. Thanks
 

Attachments

  • 1.jpg
    1.jpg
    84.3 KB · Views: 13
There is no variable iReligion (unless you define one). I think you'll want if pPlayerX.getStateReligion() == pPlayerY.getStateReligion():. pPlayerX is from the one team, pPlayerY from the other. The Platy code goes through all pairs of players belonging to the two teams that have come in contact. Maybe you should additionally check pPlayerX.getStateReligion != ReligionTypes.NO_RELIGION (connected with an and or as a separate if on a separate line); otherwise, the relations boost will also apply to pairs of players that both have no state religion.
 
no errors but nothing happens, then if I and another team have the same state religion it should increase my aptitude from +2 to +5, but nothing changes, not if I understood correctly what the script does, Maybe it only works if I build the walls before meeting him for the first time?
edit: pPlayerY is not defined
edit 2: i add
pPlayerY = gc.getPlayer(iPlayerY) look attach 3
 

Attachments

  • 1.jpg
    1.jpg
    145.8 KB · Views: 9
  • 6.jpg
    6.jpg
    50.5 KB · Views: 9
  • 6.png
    6.png
    34.4 KB · Views: 6
Last edited:
I had seen pPlayerY referenced in Platy's code (pPlayerY.isAlive etc.), so I had assumed that it's properly defined. Seems, then, that Platy's code was already erroneous. Hm ... looking at his Gigapack, the pPlayerY = gc.getPlayer(iPlayerY) is present just where you have it now. Perhaps you had deleted it when you inserted your religion check. Anyway, yes, this should fix the error.
 
I tried to use the script, but I think it only works if I haven't met you yet, now I tried with buildingbuild, but I don't find the attitude penalty once built, in my case, the gretat wall, the script I attach, no errors. I don't understand why, maybe I didn't understand the change in attitude as a function
 

Attachments

  • 1.jpg
    1.jpg
    64.7 KB · Views: 12
Maybe it only works if I build the walls before meeting him for the first time?
Oh, yes, onFirstContact only gets called when two teams meet for the first time. I thought that was the intention, but, come to think of it, it doesn't make much sense. Of course you want the relations boost to occur upon completion of the wonder – for all civs whom the city owner has met at that time. Your new code doesn't check isHasMet (will need to be checked on the corresponding teams) and also doesn't check for NO_RELIGION, but it looks syntactically correct and should result in visible "Past events" relations modifiers. You could put print statements (e.g. print "Calling AI_changeAttitudeExtra"; or better: print "changing attitude of player " + str(iLoopPlayer) + " toward " + str(iPlayer)) just above your AI_changeAttitudeExtra calls and then check PythonDbg.log to verify that the logic is working as expected. Ending the turn after construction of the wonder might also be worth a try. K-Mod (and Realism Invictus) cache AI relations values for performance reasons, and changes to relations don't take effect until the cache is updated. That being said, AI_changeAttitudeExtra should already (immediately) update the cache; so it's a long shot that ending the turn will make a difference.
 
Back
Top Bottom