Skip to content

Commit

Permalink
Improve autoplay and clear some initialization variables (#66)
Browse files Browse the repository at this point in the history
* Use direct location of constantinople

* Simplify building pref

* Add every fct

* Use handler for init vars

* Rename fct

* Add firstCity event

* Can't trade city with plague

* Move startingTurn in CvPlayer

* Players can still collapse after winning the game

* Add fct for year and turn given a scenario

* Rename fct

* Use getScenarioStartTurn fct in ::update

* Remove catapult autoplay

* Improve non autoplay message

* Bump version

* Update changelog

* Fix verifyAlive

* Add fct for dawn of man

* Rename module

* Move civ init functions

* Fix version

* Improve changelog

* Use handler for dynamic civ names

* Rename functions

* Use handler for rename cities on game start

* Improve changelog
  • Loading branch information
VDuchauffour authored Oct 6, 2024
1 parent e221b00 commit a8564cd
Show file tree
Hide file tree
Showing 43 changed files with 312 additions and 622 deletions.
Binary file modified Assets/CvGameCoreDLL.dll
Binary file not shown.
Empty file added Assets/Python/AIParameters.py
Empty file.
2 changes: 0 additions & 2 deletions Assets/Python/BUG/BugEventManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@
import BugCore
import BugData
import BugUtil
import Modifiers
import InputUtil
import types

Expand Down Expand Up @@ -432,7 +431,6 @@ def _handleInitBugEvent(self, eventType, argsList):
import BugInit

BugInit.init()
Modifiers.setup()
self._handleDefaultEvent(eventType, argsList)

def resetActiveTurn(self, argsList=None):
Expand Down
26 changes: 16 additions & 10 deletions Assets/Python/CityNameManager.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
# Rhye's and Fall of Civilization: Europe - City naming and renaming management

from CvPythonExtensions import *
from Core import civilizations, get_data_from_upside_down_map
from Core import civilizations, get_data_from_upside_down_map, cities
from CityMapData import CITIES_MAP
from Events import handler

gc = CyGlobalContext()


@handler("cityBuilt")
def onCityBuilt(city):
assignName(city)
def on_city_built(city):
assign_name(city)


@handler("cityAcquired")
def onCityAcquired(iOwner, iNewOwner, city):
renameCities(city, iNewOwner)
def on_city_acquired(iOwner, iNewOwner, city):
rename_cities(city, iNewOwner)


@handler("GameStart")
def on_game_start():
# the WB file cannot handle special chars and long names properly
# some of the cities intentionally have different names though (compared to the CNM), for example some Kievan cities
for city in cities.majors().entities():
rename_cities(city, city.getOwner())


def assignName(city):
def assign_name(city):
"""Names a city depending on its plot"""
iOwner = city.getOwner()
if iOwner < civilizations().majors().len():
Expand All @@ -27,15 +33,15 @@ def assignName(city):
city.setName(unicode(cityName), False)


def renameCities(city, iNewOwner):
def rename_cities(city, iNewOwner):
"""Renames a city depending on its owner"""
if iNewOwner < civilizations().majors().len():
cityName = get_data_from_upside_down_map(CITIES_MAP, iNewOwner, city)
if cityName != "-1":
city.setName(unicode(cityName), False)


def lookupName(city, iPlayer):
def lookup_name(city, iPlayer):
"""Looks up a city name in another player's map"""
if iPlayer < civilizations().majors().len():
cityName = get_data_from_upside_down_map(CITIES_MAP, iPlayer, city)
Expand Down
15 changes: 1 addition & 14 deletions Assets/Python/Civilizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,13 @@
from LocationsData import CIV_CAPITAL_LOCATIONS
from MiscData import REVEAL_DATE_TECHNOLOGY
from RFCUtils import change_attitude_extra_between_civ
from Events import handler
from TimelineData import TIMELINE_TECH_MODIFIER

gc = CyGlobalContext()


@handler("GameStart")
def setup():
set_starting_turns()
set_tech_timeline_date()


def set_starting_turns():
for civ in civilizations().drop(Civ.BARBARIAN):
gc.setStartingTurn(civ.id, civ.date.birth)


def set_tech_timeline_date():
for tech, turn in TIMELINE_TECH_MODIFIER:
gc.setTimelineTechDateForTech(tech, year(turn))
civ.player.setInitialBirthTurn(civ.date.birth)


def set_starting_gold():
Expand Down
6 changes: 5 additions & 1 deletion Assets/Python/Core.py
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,10 @@ def since(iTurn):
return turn() - iTurn


def every(interval):
return turn() % turns(interval) == 0


class InfoCollection(EntitiesCollection):
def __init__(self, info_class, *infos):
super(InfoCollection, self).__init__(*infos)
Expand Down Expand Up @@ -2323,7 +2327,7 @@ def get_scenario():
return Scenario.i1200AD


def get_scenario_start_years(scenario=None):
def get_scenario_start_year(scenario=None):
"""Return scenario start year given a scenario."""
if scenario is None:
scenario = get_scenario()
Expand Down
10 changes: 5 additions & 5 deletions Assets/Python/Crusades.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from Events import handler, popup_handler
from PyUtils import percentage, percentage_chance, rand, choice
from ProvinceMapData import PROVINCES_MAP
from CityNameManager import lookupName
from CityNameManager import lookup_name
from RFCUtils import convertPlotCulture, getMaster, getUniqueUnit, isAVassal
from StoredData import data
import random
Expand Down Expand Up @@ -1034,9 +1034,9 @@ def startCrusade():
if iTargetPlayer == iHuman:
underCrusadeAttackPopup(pTargetCity.getName(), iLeader)
elif player().isExisting():
sCityName = lookupName(pTargetCity, Civ.POPE)
sCityName = lookup_name(pTargetCity, Civ.POPE)
if sCityName == "Unknown":
sCityName = lookupName(pTargetCity, iLeader)
sCityName = lookup_name(pTargetCity, iLeader)
sText = text(
"TXT_KEY_CRUSADE_START",
player(iLeader).getCivilizationAdjectiveKey(),
Expand Down Expand Up @@ -1148,9 +1148,9 @@ def crusadeArrival(iActiveCrusade):
crusadeMakeUnits((iChosenX, iChosenY), iActiveCrusade)
if human() == iLeader:
pTargetCity = gc.getMap().plot(iTX, iTY).getPlotCity()
sCityName = lookupName(pTargetCity, Civ.POPE)
sCityName = lookup_name(pTargetCity, Civ.POPE)
if sCityName == "Unknown":
sCityName = lookupName(pTargetCity, iLeader)
sCityName = lookup_name(pTargetCity, iLeader)
message(
iLeader,
text("TXT_KEY_CRUSADE_ARRIVAL", sCityName) + "!",
Expand Down
15 changes: 12 additions & 3 deletions Assets/Python/DynamicCivs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@


@handler("BeginPlayerTurn")
def refresh_civ_name(iGameTurn, iPlayer):
if iPlayer < civilizations().majors().len():
player(iPlayer).processCivNames()
def on_begin_player_turn(gameturn, player_id):
refresh_civ_name(player_id)


@handler("GameStart")
def on_game_start():
for player_id in civilizations().majors():
refresh_civ_name(player_id)


def refresh_civ_name(player_id):
player(player_id).processCivNames()
23 changes: 19 additions & 4 deletions Assets/Python/Events.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,28 @@ def handler_func(args):
return handler_decorator


def noop(*args, **kwargs):
pass


def popup_handler(event_id):
def handler_decorator(func):
events.addCustomEvent(event_id, func.__name__, func, noop)
return func

return handler_decorator


def noop(*args, **kwargs):
pass


events.addEvent("firstCity")


@handler("cityAcquiredAndKept")
def firstCityOnCityAcquiredAndKept(iPlayer, city):
if city.isCapital():
events.fireEvent("firstCity", city)


@handler("cityBuilt")
def firstCityOnCityBuilt(city):
if city.isCapital():
events.fireEvent("firstCity", city)
4 changes: 3 additions & 1 deletion Assets/Python/Handlers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# ruff: noqa: F401
import ScreenHandler
import ScreensHandler

import CityNameManager
import DynamicCivs
import Civilizations
import History
import Messages
Expand All @@ -22,6 +23,7 @@
import Religions
import Resources
import Resurrection
import Rise
import RiseAndFall
import Secession
import Stability
Expand Down
50 changes: 27 additions & 23 deletions Assets/Python/Modifiers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from CvPythonExtensions import *
from Core import civilization, civilizations, log
from Core import civilizations, log, year
from CoreTypes import (
Modifier,
Building,
City,
Civ,
Civic,
Expand All @@ -20,22 +19,37 @@
FaithPointBonusCategory,
)
from MiscData import (
BUILDING_PREFERENCES,
DIPLOMACY_MODIFIERS,
HISTORICAL_ENEMIES,
GREAT_PROPHET_FAITH_POINT_BONUS,
PROSECUTOR_UNITCLASS,
)
from TimelineData import DateTurn
from TimelineData import TIMELINE_TECH_MODIFIER, DateTurn
from LocationsData import CITIES
from Events import handler

gc = CyGlobalContext()


@handler("GameStart")
def setup_gamestart():
log("RFCE: GameStart")
setup()


@handler("OnLoad")
def setup_on_load():
log("RFCE: OnLoad")
setup()


def setup():
set_modifiers()
set_diplomacy_modifier()
set_tech_timeline_modifier()
set_starting_workers_modifier()
set_tech_timeline_date()
set_starting_workers()
set_initial_building()
set_building_preferences()
set_unique_powers()
Expand Down Expand Up @@ -133,7 +147,7 @@ def set_diplomacy_modifier():
gc.setDiplomacyModifiers(civ1, civ2, value)


def set_starting_workers_modifier():
def set_starting_workers():
for civ in civilizations().majors():
gc.setStartingWorkers(civ.id, civ.initial.workers)

Expand Down Expand Up @@ -163,21 +177,8 @@ def set_building_preferences():
# the getUniqueBuilding function does not work, probably the util functions are not yet usable when these initial values are set
# but in the .dll these values are only used for the civ-specific building of the given buildingclass, so we can these add redundantly
for civ in civilizations().majors():
gc.setBuildingPref(civ.id, Building.WALLS, 5)
gc.setBuildingPref(civ.id, Building.CASTLE, 7)
gc.setBuildingPref(civ.id, Building.MANOR_HOUSE, 5)
gc.setBuildingPref(civ.id, Building.COURTHOUSE, 5)
gc.setBuildingPref(civ.id, Building.NIGHT_WATCH, 3)
gc.setBuildingPref(civ.id, Building.MOROCCO_KASBAH, 5)
gc.setBuildingPref(civ.id, Building.MOSCOW_KREMLIN, 7)
gc.setBuildingPref(civ.id, Building.HUNGARIAN_STRONGHOLD, 7)
gc.setBuildingPref(civ.id, Building.SPANISH_CITADEL, 7)
gc.setBuildingPref(civ.id, Building.FRENCH_CHATEAU, 5)
gc.setBuildingPref(civ.id, Building.VENICE_NAVAL_BASE, 5)
gc.setBuildingPref(civ.id, Building.KIEV_VECHE, 5)
gc.setBuildingPref(civ.id, Building.HOLY_ROMAN_RATHAUS, 5)
gc.setBuildingPref(civ.id, Building.LITHUANIAN_VOIVODESHIP, 5)
gc.setBuildingPref(civ.id, Building.SWEDISH_TENNANT, 3)
for building, preference in BUILDING_PREFERENCES:
gc.setBuildingPref(civ.id, building, preference)

for civ in civilizations():
ai_modifier = civ.ai.modifiers.get(Modifier.BUILDING_PREFERENCE)
Expand Down Expand Up @@ -354,6 +355,11 @@ def set_religion_spread_factor():
gc.setReligionSpread(civ.id, religion, threshold)


def set_tech_timeline_date():
for tech, turn in TIMELINE_TECH_MODIFIER:
gc.setTimelineTechDateForTech(tech, year(turn))


def set_religion_benefit():
# gc.setReligionBenefit( iReligion, iFP_(whatever it is), iParameter, iCap )
# note that for powers iParameter = -1 means that this religion doesn't have this power (-1 is the default)
Expand Down Expand Up @@ -427,7 +433,7 @@ def set_other_parameters():

# 3Miro: Psycho AI cheat, this will make Ottoman AI think it can win battles vs Constantinople at 90/100 rate
# it will also actually boost the Ottoman's odds (actually lower the defenders chance by 20 percent), but only when attacking Constantinople
gc.setPsychoAICheat(Civ.OTTOMAN, *civilization(Civ.BYZANTIUM).location.capital)
gc.setPsychoAICheat(Civ.OTTOMAN, *CITIES[City.CONSTANTINOPLE])

# 3Miro: this sets rules on how players can Vassalize, first two parameters are the players (we should probably keep this symmetric)
# if the third parameter is -1: cannot Vassalize, 0: has to satisfy a condition (default), 1 can Vassalize without conditions
Expand All @@ -453,7 +459,5 @@ def set_other_parameters():
)
gc.setPapalPlayer(Civ.POPE, Religion.CATHOLICISM)

gc.setAutorunHack(Unit.CATAPULT, 32, 0) # Autorun hack, sync with RNF module

# 3MiroMercs: set the merc promotion
gc.setMercPromotion(Promotion.MERC)
1 change: 1 addition & 0 deletions Assets/Python/RFCUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,7 @@ def ownedCityPlots(tCoords, argsList):
return False


# TODO replace with Stability.isImmune
def collapseImmune(iCiv):
# 3MiroUP: Emperor
if gc.hasUP(iCiv, UniquePower.NO_COLLAPSE_IN_CORE_AND_NORMAL_AREAS):
Expand Down
2 changes: 2 additions & 0 deletions Assets/Python/Resurrection.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ def resurectCiv(iDeadCiv):
# Absinthe: resetting the original potential provinces, and adding special province changes on respawn (Cordoba)
onRespawn(iDeadCiv)

pDeadCiv.setLastBirthTurn(iGameTurn)

# Absinthe: we shouldn't get a previous leader on respawn - would be changed to a newer one in a couple turns anyway
# instead we have a random chance to remain with the leader before the collapse, or to switch to the next one
leaders = civilization(iDeadCiv).leaders[LeaderType.LATE]
Expand Down
8 changes: 8 additions & 0 deletions Assets/Python/Rise.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from Core import get_scenario_start_turn, game
import CvScreensInterface


# @handler("BeginGameTurn")
def showDawnOfMan(iGameTurn):
if iGameTurn == get_scenario_start_turn() and game.getAIAutoPlay() > 0:
CvScreensInterface.dawnOfMan.interfaceScreen()
2 changes: 2 additions & 0 deletions Assets/Python/RiseAndFall.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
create_starting_workers,
set_starting_diplomacy_1200AD,
set_starting_faith,
set_starting_turns,
)
from Consts import MessageData
from Core import (
Expand Down Expand Up @@ -94,6 +95,7 @@

@handler("GameStart")
def setup():
set_starting_turns()
setEarlyLeaders()

if get_scenario() == Scenario.i500AD:
Expand Down
Loading

0 comments on commit a8564cd

Please sign in to comment.