r_rolo1
King of myself
CIV4EventInfos.XML
CIV4EventTriggerInfos.XML
CvEventManager.py
I was definitely not a fan of the pre-3.17 partisan event, especially of the bug that made the event appear regardless of the target civ having the Emancipation civic ( try to play a OCC-AW in 3.13 and you'll see what I mean ). And I thinked that it was fixed with 3.17 patch....
Unitl yesterday
What happened was that mystyfly IMed me asking about a strange phenomenon he had seen: he had razed a city of a civ and the partisans were of other civ that he was also warring and that the first civ had captured to the the second one 10 turns ago.
I decided to look to the code ( with the precious help of DanF ) and there are 2 things that, in spite of not conducting to a buggy behaviour most of the times, they can create highly irregular behaviour:
1- Regarding this event, the owner of the city is not the political owner, but the player that passes the city.findHighestCulture() check ( danF thinks the event not refering to the political owner was premeditaded, to avoid exploits ). All the later checks refer to that player, including the Emancipation check. This means that you can even raze a city of a civ that has not Emancipation as civic and get partisans of another civ that you war in war with, if that civ is in war with you and passes the city.findHighestCulture() check. This can happen easily ( but not only ) if you raze a city that belongs to the backward master of a advanced civ now, but that belonged to the advanced vassal ( Monty zerg rushing and vassaling Gandhi comes to mind )
2- Unlike I first thought, city.findHighestCulture() ( the check that decides who is the owner of the razed city in terms of this event ) does not get the plot culture of the city tile ( thanks DanF for this one ), but the actual city culture, that also includes the result of the espionage "spread culture" and that is not displayed in the interface. This means that you have absolutely no way of knowing what nationality the partisans will be ( and if they will appear ) without going to the debug. This also makes way to exploits regarding getting partisans out of foreign cities by using the espoinage culture spreading mission ( I can see that happening in MP easily )
Well, both of the situations are rare and I'm not even sure if 1 is a bug or not ( I'm inclined to being ). I thing this could be solved with getting the highest plot culture civ in city tile instead of the current culture check and making the Emancipation check to get the political owner of the city, regardless of who has the highest culture in city.
Thoughts?
Code:
<EventInfo>
<Type>EVENT_PARTISANS_1</Type>
<Description>TXT_KEY_EVENT_PARTISANS_1</Description>
<LocalInfoText/>
<WorldNewsTexts/>
<OtherPlayerPopup>TXT_KEY_EVENT_PARTISANS_OTHER_1</OtherPlayerPopup>
<QuestFailText/>
<bQuest>0</bQuest>
<bGlobal>0</bGlobal>
<bTeam>0</bTeam>
<bPickCity>0</bPickCity>
<bPickOtherPlayerCity>0</bPickOtherPlayerCity>
<bDeclareWar>0</bDeclareWar>
<iGold>0</iGold>
<bGoldToPlayer>0</bGoldToPlayer>
<iRandomGold>0</iRandomGold>
<iCulture>0</iCulture>
<iEspionagePoints>0</iEspionagePoints>
<bGoldenAge>0</bGoldenAge>
<iFreeUnitSupport>0</iFreeUnitSupport>
<iInflationMod>0</iInflationMod>
<iSpaceProductionMod>0</iSpaceProductionMod>
<Tech>NONE</Tech>
<TechFlavors/>
<iTechPercent>0</iTechPercent>
<iTechCostPercent>0</iTechCostPercent>
<iTechMinTurnsLeft>0</iTechMinTurnsLeft>
<PrereqTech>NONE</PrereqTech>
<UnitClass>NONE</UnitClass>
<iNumFreeUnits>0</iNumFreeUnits>
<bDisbandUnit>0</bDisbandUnit>
<iUnitExperience>0</iUnitExperience>
<iUnitImmobileTurns>0</iUnitImmobileTurns>
<UnitPromotion/>
<UnitName/>
<UnitCombatPromotions/>
<UnitClassPromotions/>
<BuildingClass>NONE</BuildingClass>
<iBuildingChange>0</iBuildingChange>
<BuildingExtraYields/>
<BuildingExtraCommerces/>
<BuildingExtraHappies/>
<BuildingExtraHealths/>
<iHappy>0</iHappy>
<iHealth>0</iHealth>
<iHurryAnger>0</iHurryAnger>
<iHappyTurns>0</iHappyTurns>
<iRevoltTurns>0</iRevoltTurns>
<iMinPillage>0</iMinPillage>
<iMaxPillage>0</iMaxPillage>
<iFood>0</iFood>
<iFoodPercent>0</iFoodPercent>
<FreeSpecialistCounts/>
<FeatureType>NONE</FeatureType>
<iFeatureChange>0</iFeatureChange>
<ImprovementType>NONE</ImprovementType>
<iImprovementChange>0</iImprovementChange>
<BonusType>NONE</BonusType>
<iBonusChange>0</iBonusChange>
<RouteType>NONE</RouteType>
<iRouteChange>0</iRouteChange>
<BonusRevealed>NONE</BonusRevealed>
<BonusGift>NONE</BonusGift>
<PlotExtraYields/>
<iConvertOwnCities>0</iConvertOwnCities>
<iConvertOtherCities>0</iConvertOtherCities>
<iMaxNumReligions>-1</iMaxNumReligions>
<iOurAttitudeModifier>0</iOurAttitudeModifier>
<iAttitudeModifier>0</iAttitudeModifier>
<iTheirEnemyAttitudeModifier>0</iTheirEnemyAttitudeModifier>
<iPopulationChange>0</iPopulationChange>
<AdditionalEvents/>
<EventTimes/>
<ClearEvents/>
<PythonCallback>applyPartisans1</PythonCallback>
<PythonExpireCheck/>
<PythonCanDo>canApplyPartisans1</PythonCanDo>
<PythonHelp>getHelpPartisans1</PythonHelp>
<Button>,Art/Interface/Buttons/Process/Blank.dds,Art/Interface/Buttons/Beyond_the_Sword_Atlas.dds,8,5</Button>
<iAIValue>1000</iAIValue>
</EventInfo>
<EventInfo>
<Type>EVENT_PARTISANS_2</Type>
<Description>TXT_KEY_EVENT_PARTISANS_2</Description>
<LocalInfoText/>
<WorldNewsTexts/>
<OtherPlayerPopup>TXT_KEY_EVENT_PARTISANS_OTHER_2</OtherPlayerPopup>
<QuestFailText/>
<bQuest>0</bQuest>
<bGlobal>0</bGlobal>
<bTeam>0</bTeam>
<bPickCity>0</bPickCity>
<bPickOtherPlayerCity>0</bPickOtherPlayerCity>
<bDeclareWar>0</bDeclareWar>
<iGold>0</iGold>
<bGoldToPlayer>0</bGoldToPlayer>
<iRandomGold>0</iRandomGold>
<iCulture>0</iCulture>
<iEspionagePoints>0</iEspionagePoints>
<bGoldenAge>0</bGoldenAge>
<iFreeUnitSupport>0</iFreeUnitSupport>
<iInflationMod>0</iInflationMod>
<iSpaceProductionMod>0</iSpaceProductionMod>
<Tech>NONE</Tech>
<TechFlavors/>
<iTechPercent>0</iTechPercent>
<iTechCostPercent>0</iTechCostPercent>
<iTechMinTurnsLeft>0</iTechMinTurnsLeft>
<PrereqTech>NONE</PrereqTech>
<UnitClass>NONE</UnitClass>
<iNumFreeUnits>0</iNumFreeUnits>
<bDisbandUnit>0</bDisbandUnit>
<iUnitExperience>0</iUnitExperience>
<iUnitImmobileTurns>0</iUnitImmobileTurns>
<UnitPromotion/>
<UnitName/>
<UnitCombatPromotions/>
<UnitClassPromotions/>
<BuildingClass>NONE</BuildingClass>
<iBuildingChange>0</iBuildingChange>
<BuildingExtraYields/>
<BuildingExtraCommerces/>
<BuildingExtraHappies/>
<BuildingExtraHealths/>
<iHappy>0</iHappy>
<iHealth>0</iHealth>
<iHurryAnger>0</iHurryAnger>
<iHappyTurns>0</iHappyTurns>
<iRevoltTurns>0</iRevoltTurns>
<iMinPillage>0</iMinPillage>
<iMaxPillage>0</iMaxPillage>
<iFood>0</iFood>
<iFoodPercent>0</iFoodPercent>
<FreeSpecialistCounts/>
<FeatureType>NONE</FeatureType>
<iFeatureChange>0</iFeatureChange>
<ImprovementType>NONE</ImprovementType>
<iImprovementChange>0</iImprovementChange>
<BonusType>NONE</BonusType>
<iBonusChange>0</iBonusChange>
<RouteType>NONE</RouteType>
<iRouteChange>0</iRouteChange>
<BonusRevealed>NONE</BonusRevealed>
<BonusGift>NONE</BonusGift>
<PlotExtraYields/>
<iConvertOwnCities>0</iConvertOwnCities>
<iConvertOtherCities>0</iConvertOtherCities>
<iMaxNumReligions>-1</iMaxNumReligions>
<iOurAttitudeModifier>0</iOurAttitudeModifier>
<iAttitudeModifier>0</iAttitudeModifier>
<iTheirEnemyAttitudeModifier>0</iTheirEnemyAttitudeModifier>
<iPopulationChange>0</iPopulationChange>
<AdditionalEvents/>
<EventTimes/>
<ClearEvents/>
<PythonCallback>applyPartisans2</PythonCallback>
<PythonExpireCheck/>
<PythonCanDo>canApplyPartisans2</PythonCanDo>
<PythonHelp>getHelpPartisans2</PythonHelp>
<Button>,Art/Interface/Buttons/Process/Blank.dds,Art/Interface/Buttons/Beyond_the_Sword_Atlas.dds,8,5</Button>
<iAIValue>1000</iAIValue>
</EventInfo>
Code:
<EventTriggerInfo>
<Type>EVENTTRIGGER_PARTISANS</Type>
<WorldNewsTexts>
<Text>TXT_KEY_EVENTTRIGGER_PARTISANS</Text>
</WorldNewsTexts>
<TriggerTexts>
<TriggerText>
<Text>TXT_KEY_EVENT_TRIGGER_PARTISANS_1</Text>
<Era>NONE</Era>
</TriggerText>
</TriggerTexts>
<bSinglePlayer>0</bSinglePlayer>
<iPercentGamesActive>100</iPercentGamesActive>
<iWeight>-2</iWeight>
<bProbabilityUnitMultiply>0</bProbabilityUnitMultiply>
<bProbabilityBuildingMultiply>0</bProbabilityBuildingMultiply>
<Civic>CIVIC_EMANCIPATION</Civic>
<iMinTreasury>0</iMinTreasury>
<iMinPopulation>0</iMinPopulation>
<iMaxPopulation>0</iMaxPopulation>
<iMinMapLandmass>0</iMinMapLandmass>
<iMinOurLandmass>0</iMinOurLandmass>
<iMaxOurLandmass>-1</iMaxOurLandmass>
<MinDifficulty>NONE</MinDifficulty>
<iAngry>0</iAngry>
<iUnhealthy>0</iUnhealthy>
<UnitsRequired/>
<iNumUnits>0</iNumUnits>
<iNumUnitsGlobal>0</iNumUnitsGlobal>
<iUnitDamagedWeight>0</iUnitDamagedWeight>
<iUnitDistanceWeight>0</iUnitDistanceWeight>
<iUnitExperienceWeight>0</iUnitExperienceWeight>
<bUnitsOnPlot>0</bUnitsOnPlot>
<BuildingsRequired/>
<iNumBuildings>0</iNumBuildings>
<iNumBuildingsGlobal>0</iNumBuildingsGlobal>
<iNumPlotsRequired>0</iNumPlotsRequired>
<bOwnPlot>0</bOwnPlot>
<iPlotType>-1</iPlotType>
<FeaturesRequired/>
<TerrainsRequired/>
<ImprovementsRequired/>
<BonusesRequired/>
<RoutesRequired/>
<ReligionsRequired/>
<iNumReligions>0</iNumReligions>
<CorporationsRequired/>
<iNumCorporations>0</iNumCorporations>
<bPickReligion>0</bPickReligion>
<bStateReligion>0</bStateReligion>
<bHolyCity>0</bHolyCity>
<bPickCorporation>0</bPickCorporation>
<bHeadquarters>0</bHeadquarters>
<Events>
<Event>EVENT_PARTISANS_1</Event>
<Event>EVENT_PARTISANS_2</Event>
</Events>
<PrereqEvents/>
<bPrereqEventPlot>0</bPrereqEventPlot>
<OrPreReqs/>
<AndPreReqs/>
<ObsoleteTechs/>
<bRecurring>1</bRecurring>
<bTeam>0</bTeam>
<bGlobal>0</bGlobal>
<bPickPlayer>0</bPickPlayer>
<bOtherPlayerWar>0</bOtherPlayerWar>
<bOtherPlayerHasReligion>0</bOtherPlayerHasReligion>
<bOtherPlayerHasOtherReligion>0</bOtherPlayerHasOtherReligion>
<bOtherPlayerAI>0</bOtherPlayerAI>
<iOtherPlayerShareBorders>0</iOtherPlayerShareBorders>
<OtherPlayerHasTech>NONE</OtherPlayerHasTech>
<bPickCity>0</bPickCity>
<bPickOtherPlayerCity>0</bPickOtherPlayerCity>
<bShowPlot>1</bShowPlot>
<iCityFoodWeight>0</iCityFoodWeight>
<PythonCanDo/>
<PythonCanDoCity/>
<PythonCanDoUnit/>
<PythonCallback/>
</EventTriggerInfo>
Code:
def onCityRazed(self, argsList):
'City Razed'
city, iPlayer = argsList
iOwner = city.findHighestCulture()
# Partisans!
if city.getPopulation > 1 and iOwner != -1 and iPlayer != -1:
owner = gc.getPlayer(iOwner)
if not owner.isBarbarian() and owner.getNumCities() > 0:
if gc.getTeam(owner.getTeam()).isAtWar(gc.getPlayer(iPlayer).getTeam()):
if gc.getNumEventTriggerInfos() > 0: # prevents mods that don't have events from getting an error
iEvent = CvUtil.findInfoTypeNum(gc.getEventTriggerInfo, gc.getNumEventTriggerInfos(),'EVENTTRIGGER_PARTISANS')
if iEvent != -1 and gc.getGame().isEventActive(iEvent) and owner.getEventTriggerWeight(iEvent) < 0:
triggerData = owner.initTriggeredData(iEvent, true, -1, city.getX(), city.getY(), iPlayer, city.getID(), -1, -1, -1, -1)
CvUtil.pyPrint("City Razed Event: %s" %(city.getName(),))
Unitl yesterday
What happened was that mystyfly IMed me asking about a strange phenomenon he had seen: he had razed a city of a civ and the partisans were of other civ that he was also warring and that the first civ had captured to the the second one 10 turns ago.
I decided to look to the code ( with the precious help of DanF ) and there are 2 things that, in spite of not conducting to a buggy behaviour most of the times, they can create highly irregular behaviour:
1- Regarding this event, the owner of the city is not the political owner, but the player that passes the city.findHighestCulture() check ( danF thinks the event not refering to the political owner was premeditaded, to avoid exploits ). All the later checks refer to that player, including the Emancipation check. This means that you can even raze a city of a civ that has not Emancipation as civic and get partisans of another civ that you war in war with, if that civ is in war with you and passes the city.findHighestCulture() check. This can happen easily ( but not only ) if you raze a city that belongs to the backward master of a advanced civ now, but that belonged to the advanced vassal ( Monty zerg rushing and vassaling Gandhi comes to mind )
2- Unlike I first thought, city.findHighestCulture() ( the check that decides who is the owner of the razed city in terms of this event ) does not get the plot culture of the city tile ( thanks DanF for this one ), but the actual city culture, that also includes the result of the espionage "spread culture" and that is not displayed in the interface. This means that you have absolutely no way of knowing what nationality the partisans will be ( and if they will appear ) without going to the debug. This also makes way to exploits regarding getting partisans out of foreign cities by using the espoinage culture spreading mission ( I can see that happening in MP easily )
Well, both of the situations are rare and I'm not even sure if 1 is a bug or not ( I'm inclined to being ). I thing this could be solved with getting the highest plot culture civ in city tile instead of the current culture check and making the Emancipation check to get the political owner of the city, regardless of who has the highest culture in city.
Thoughts?