diff --git a/CityBannerManager.lua.cuc b/CityBannerManager.lua.cuc index 41e1049b6af71af42a6fa060740f2d9189eba0b9..57302215225a21ae7db5bd05d6ee51cf0f2ae3a2 100644 --- a/CityBannerManager.lua.cuc +++ b/CityBannerManager.lua.cuc @@ -420,6 +420,7 @@ local TeamCityTooltips = { CityIsPuppet = "EUI_ItemTooltip", CityIsRazing = "EUI_ItemTooltip", CityIsResistance = "EUI_ItemTooltip", + CityResistanceTurns = "EUI_ItemTooltip", CityIsConnected = "EUI_ItemTooltip", CityIsBlockaded = "EUI_ItemTooltip", CityIsOccupied = "EUI_ItemTooltip", @@ -580,7 +581,7 @@ function RefreshCityBanner( city ) instance.CityIsRazing:SetHide( not isRazing ) -- In Resistance ? - instance.CityIsResistance:SetHide( not isResistance ) + instance.CityIsResistance:SetHide( not isResistance or isRazing ) -- Puppet ? instance.CityIsPuppet:SetHide( not isPuppet ) @@ -606,17 +607,23 @@ function RefreshCityBanner( city ) -- Update Growth local foodStored100 = city:GetFoodTimes100() - local foodThreshold100 = city:GrowthThreshold() * 100 local foodPerTurn100 = city:FoodDifferenceTimes100( true ) local foodStoredPercent = 0 local foodStoredNextTurnPercent = 0 - if foodThreshold100 > 0 then - foodStoredPercent = foodStored100 / foodThreshold100 - foodStoredNextTurnPercent = ( foodStored100 + foodPerTurn100 ) / foodThreshold100 - if foodPerTurn100 < 0 then - foodStoredPercent, foodStoredNextTurnPercent = foodStoredNextTurnPercent, foodStoredPercent + + if isRazing then + foodPerTurn100 = -1 + else + local foodThreshold100 = city:GrowthThreshold() * 100 + if foodThreshold100 > 0 then + foodStoredPercent = foodStored100 / foodThreshold100 + foodStoredNextTurnPercent = ( foodStored100 + foodPerTurn100 ) / foodThreshold100 + if foodPerTurn100 < 0 then + foodStoredPercent, foodStoredNextTurnPercent = foodStoredNextTurnPercent, foodStoredPercent + end end end + instance.CityResistanceTurns:SetText( isRazing and city:GetRazingTurns() or isResistance and city:GetResistanceTurns() ) -- Update Growth Meter instance.GrowthBar:SetPercent( max(min( foodStoredPercent, 1),0)) @@ -624,18 +631,16 @@ function RefreshCityBanner( city ) instance.GrowthBarStarve:SetHide( foodPerTurn100 >= 0 ) -- Update Growth Time - local turnsToCityGrowth = city:GetFoodTurnsLeft() local growthText if foodPerTurn100 < 0 then - turnsToCityGrowth = floor( foodStored100 / -foodPerTurn100 ) + 1 - growthText = "[COLOR_WARNING_TEXT]" .. turnsToCityGrowth .. "[ENDCOLOR]" + growthText = "[COLOR_WARNING_TEXT]" .. min( floor( foodStored100 / -foodPerTurn100 ) + 1, 99 ) .. "[ENDCOLOR]" elseif city:IsForcedAvoidGrowth() then growthText = "[ICON_LOCKED]" elseif foodPerTurn100 == 0 then growthText = "-" else - growthText = min(turnsToCityGrowth,99) + growthText = min( city:GetFoodTurnsLeft(),99 ) end instance.CityGrowth:SetText( growthText ) @@ -670,7 +675,7 @@ function RefreshCityBanner( city ) local projectProductionID = city:GetProductionProject() local processProductionID = city:GetProductionProcess() local portraitIndex, portraitAtlas - local item = nil + local item if unitProductionID ~= -1 then item = GameInfo.Units[unitProductionID] @@ -682,10 +687,13 @@ function RefreshCityBanner( city ) elseif processProductionID ~= -1 then item = GameInfo.Processes[processProductionID] end - -- really should have an error texture - instance.CityProduction:SetHide( not( item and - IconHookup( portraitIndex or item.PortraitIndex, 45, portraitAtlas or item.IconAtlas, instance.CityProduction ))) + if item then + instance.CityProduction:SetHide( not( item and IconHookup( portraitIndex or item.PortraitIndex, 45, portraitAtlas or item.IconAtlas, instance.CityProduction ))) + else + instance.CityProduction:SetTexture( "CityBannerGrowthBackground.dds" )--"yieldproduction64.dds" "CityBannerProductionImage.dds" + instance.CityProduction:SetTextureOffsetVal( -6, 10 ) --9, 9 ) + end -- Focus? if isRazing or isResistance or isPuppet then diff --git a/CityView.lua.cuc b/CityView.lua.cuc index 9411c02ae8d3c98a32a3c44d4891f18fcde2a453..04c23e717045d9fd4f3d5bcece23db60fa4a2452 100644 --- a/CityView.lua.cuc +++ b/CityView.lua.cuc @@ -34,9 +34,6 @@ local StackInstanceManager = StackInstanceManager include "ShowProgress" local ShowProgress = ShowProgress -include "SupportFunctions" -local TruncateString = TruncateString - if IsCiv5BNW then include "GreatPeopleIcons" end @@ -134,7 +131,7 @@ local g_GreatWorksIM = StackInstanceManager( "Work", "Button", false ) local g_SpecialistsIM = StackInstanceManager( "Slot", "Button", false ) local g_ProdQueueIM, g_SpecialBuildingsIM, g_GreatWorkIM, g_WondersIM, g_BuildingsIM, g_GreatPeopleIM, g_SlackerIM, g_UnitSelectIM, g_BuildingSelectIM, g_WonderSelectIM, g_ProcessSelectIM, g_FocusSelectIM -local g_queuedItemNumber, g_isDebugMode, g_BuyPlotMode, g_previousCity, g_isButtonPopupChooseProduction, g_isScreenAutoClose, g_isResetCityPlotPurchase +local g_queuedItemNumber, g_isDebugMode, g_BuyPlotMode, g_previousCity, g_isButtonPopupChooseProduction, g_isScreenAutoClose, g_isResetCityPlotPurchase, g_isNextCityProduction local g_citySpecialists = {} @@ -503,6 +500,7 @@ local function OnSlackersSelected( buildingID, slotID ) for _=1, slotID<=0 and city:GetSpecialistCount( GameDefines.DEFAULT_SPECIALIST ) or 1 do Network.SendDoTask( city:GetID(), TaskTypes.TASK_REMOVE_SLACKER, 0, -1, false ) end + return Network.SendUpdateCityCitizens( city:GetID() ) end end @@ -525,12 +523,14 @@ local function ToggleSpecialist( buildingID, slotID ) if city:GetNumSpecialistsInBuilding(buildingID) > 0 then specialistTable[slotID] = false specialistTable.n = specialistTable.n - 1 - return Game.SelectedCitiesGameNetMessage( GameMessageTypes.GAMEMESSAGE_DO_TASK, TaskTypes.TASK_REMOVE_SPECIALIST, specialistID, buildingID ) + Game.SelectedCitiesGameNetMessage( GameMessageTypes.GAMEMESSAGE_DO_TASK, TaskTypes.TASK_REMOVE_SPECIALIST, specialistID, buildingID ) + return Network.SendUpdateCityCitizens( city:GetID() ) end elseif city:IsCanAddSpecialistToBuilding(buildingID) then specialistTable[slotID] = true specialistTable.n = specialistTable.n + 1 - return Game.SelectedCitiesGameNetMessage( GameMessageTypes.GAMEMESSAGE_DO_TASK, TaskTypes.TASK_ADD_SPECIALIST, specialistID, buildingID ) + Game.SelectedCitiesGameNetMessage( GameMessageTypes.GAMEMESSAGE_DO_TASK, TaskTypes.TASK_ADD_SPECIALIST, specialistID, buildingID ) + return Network.SendUpdateCityCitizens( city:GetID() ) end end end @@ -943,14 +943,17 @@ local g_SelectionListCallBacks = { Events.SpecificCityInfoDirty( cityOwnerID, city:GetID(), CityUpdateTypes.CITY_UPDATE_TYPE_PRODUCTION ) if g_isButtonPopupChooseProduction then -- is there another city without production order ? - for cityX in g_activePlayer:Cities() do - if cityX ~= city and not cityX:IsPuppet() and cityX:GetOrderQueueLength() < 1 then - UI.SelectCity( cityX ) - return UI.LookAtSelectionPlot() + if g_isNextCityProduction then + for cityX in g_activePlayer:Cities() do + if cityX ~= city and not cityX:IsPuppet() and cityX:GetOrderQueueLength() < 1 then + UI.SelectCity( cityX ) + return UI.LookAtSelectionPlot() + end end end - -- all cities are producing... - return ExitCityScreen() + if g_isScreenAutoClose then + return ExitCityScreen() + end end end end @@ -1277,7 +1280,7 @@ local function BuyPlotAnchorButtonClicked( plotIndex ) local plot = city:GetCityIndexPlot( plotIndex ) local plotX = plot:GetX() local plotY = plot:GetY() - Network.SendCityBuyPlot(city:GetID(), plotX, plotY) + Network.SendCityBuyPlot( city:GetID(), plotX, plotY ) Network.SendUpdateCityCitizens( city:GetID() ) UI.UpdateCityScreen() Events.AudioPlay2DSound("AS2D_INTERFACE_BUY_TILE") @@ -1519,7 +1522,6 @@ local function UpdateCityView() ------------------------------------------- local isCapital = city:IsCapital() - Controls.CityCapitalIcon:SetHide( not isCapital ) Controls.CityIsConnected:SetHide( isCapital or city:IsBlockaded() or not cityOwner:IsCapitalConnectedToCity(city) or city:GetTeam() ~= Game.GetActiveTeam() ) @@ -1545,14 +1547,14 @@ local function UpdateCityView() Controls.CityIsOccupied:SetHide( not( IsCiv5 and city:IsOccupied() and not city:IsNoOccupiedUnhappiness() ) ) local cityName = Locale.ToUpper( city:GetName() ) - + if isCapital then + cityName = "[ICON_CAPITAL]" .. cityName + end if city:IsRazing() then cityName = cityName .. " (" .. L"TXT_KEY_BURNING" .. ")" end - local size = isCapital and Controls.CityCapitalIcon:GetSizeX() or 0 - Controls.CityNameTitleBarLabel:SetOffsetX( size / 2 ) - TruncateString( Controls.CityNameTitleBarLabel, abs(Controls.NextCityButton:GetOffsetX()) * 2 - Controls.NextCityButton:GetSizeX() - size, cityName ) + Controls.CityNameTitleBarLabel:SetText( cityName ) Controls.Defense:SetText( floor( city:GetStrengthValue() / 100 ) ) @@ -1980,7 +1982,8 @@ end local function UpdateOptionsAndCityView() g_isAdvisor = UserInterfaceSettings.CityAdvisor ~= 0 - g_isScreenAutoClose = UserInterfaceSettings.ScreenAutoClose ~= 0 + g_isScreenAutoClose = UserInterfaceSettings.CityScreenAutoClose ~= 0 + g_isNextCityProduction = UserInterfaceSettings.NextCityProduction ~= 0 g_isResetCityPlotPurchase = UserInterfaceSettings.ResetCityPlotPurchase ~= 0 g_FocusSelectIM.Collapse( not OptionsManager.IsNoCitizenWarning() ) return UpdateCityView() @@ -2205,7 +2208,7 @@ AddSerialEventGameMessagePopup( function( popupInfo ) if orderID >= 0 and itemID >= 0 then g_finishedItems[ cityID ] = { orderID, itemID } end - g_isButtonPopupChooseProduction = g_isScreenAutoClose + g_isButtonPopupChooseProduction = true return UI.DoSelectCityAtPlot( city:Plot() ) -- open city screen end end diff --git a/EUI_Modpack_Converter/EUI_Modpack_Converter.pyproj b/EUI_Modpack_Converter/EUI_Modpack_Converter.pyproj index 6c019408018caa1edd164633563ecd27a6742ee5..29f55684e59659e850f990541cc54fb0712fc998 100644 --- a/EUI_Modpack_Converter/EUI_Modpack_Converter.pyproj +++ b/EUI_Modpack_Converter/EUI_Modpack_Converter.pyproj @@ -4,7 +4,7 @@ <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>ea28d07f-cd43-45d1-b01d-1eeeb360d215</ProjectGuid> <ProjectHome>.</ProjectHome> - <StartupFile>converter.py</StartupFile> + <StartupFile>converter_new_WIP.py</StartupFile> <SearchPath> </SearchPath> <WorkingDirectory>.</WorkingDirectory> @@ -24,7 +24,8 @@ <Content Include="Process.txt" /> </ItemGroup> <ItemGroup> - <Compile Include="converter.py" /> + <Compile Include="converter_new_WIP.py" /> + <Compile Include="converter_legacy.py" /> </ItemGroup> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" /> <!-- Uncomment the CoreCompile target to enable the Build command in diff --git a/EUI_Modpack_Converter/converter.py b/EUI_Modpack_Converter/converter_legacy.py similarity index 52% rename from EUI_Modpack_Converter/converter.py rename to EUI_Modpack_Converter/converter_legacy.py index 4d23dc7abdb8ccf56b0030876d0b561e576da110..e4a2878d72f3e35c5ca92f4c37cc8b2a0e8c39bf 100644 --- a/EUI_Modpack_Converter/converter.py +++ b/EUI_Modpack_Converter/converter_legacy.py @@ -1,121 +1,78 @@ -####################################################### -# # -# © 2022 - MPL 2.0 - Rsge - v2.0.1 # -# https://github.com/Rsge/Civ-V-EUI-Modpack-Converter # -# # -# WINDOWS ONLY! # -# # -####################################################### - -# TODO Auto-detection of unit UI changing elements in mods possible? +######################################################################## +# # +# © 2021 - MPL 2.0 - Rsge - v1.0.0 # +# https://github.com/Rsge/Civ-V-EUI-Modpack-Converter # +# # +# WINDOWS ONLY! # +# 7-ZIP NEEDED! # +# If you want to use WinRar you'll have to change the methods yourself # +# (or just download 7-zip =P) # +# # +######################################################################## # Imports import os -import winreg as wr from os.path import join as j from glob import glob as g import subprocess import shutil import re + ## Global Values print("Configuring variables...") # Names +# Customize these according to your setup # +vanilla_eui_zip = "!EUI.7z" # Vanilla EUI file (in vanilla_packs_folder) +modded_eui_zip = "!EUI_CUC.7z" # CUC-version file name of EUI +modsave_folder = "zzz_Modsaves" # Folder containing this scripts project folder and it's needed edited files +vanilla_packs_folder = "zz_Vanilla_Versions" # Folder containing the vanilla packs +# Ignore these # modpack_folder_name = "MP_MODSPACK" eui_cuc_file_names = ["CityBannerManager.lua", - "CityView.lua", - "Highlights.xml"] + "CityView.lua", + "Highlights.xml"] load_tag = "ContextPtr:LoadNewContext" unit_panel_file_name = "UnitPanel.lua" ige_compat_file_name = "IGE_Window.lua" - -########################################### -# Customize these according to your setup # -########################################### -vanilla_eui_zip = "!EUI.7z" # Vanilla EUI file (in vanilla_packs_folder) -modded_eui_zip = "!EUI_CUC.7z" # CUC-version file name of EUI -vanilla_packs_folder = "zz_Vanilla_Versions" # Folder containing the vanilla packs in DLC folder +# Maybe you also need to add to these lists # +delete_file_names = ["CivilopediaScreen.lua", # Mod files overwriting original UI files, conflicting with EUI + "CityView.lua", + "TechTree.lua", + "TechButtonInclude.lua", + unit_panel_file_name] unit_panel_modcompat_file_names = ["EvilSpiritsMission.lua", # Mod files adding new actions to units "THTanukiMission.lua"] -################################################################################################### -# Don't change after here [except if you know what you're doing of cause ;)] # -# # -# YOU'LL NEED 7-ZIP! # -# If you want to use WinRar you'll have to change the methods yourself - or just download 7zip =P # -################################################################################################### +# Don't change from here [if you don't really know what you're doing that is of cause ;)] # -# Closing functions -null = open(os.devnull, 'w') -def quit(): - null.close() - print("Done.\n") - input("Press Enter to exit. . .") - exit(0) -def error(msg): - null.close() - print("Error!\n{}\n".format(msg)) - input("Press Enter to exit. . .") - exit(1) - -# Get file name -def get_file_name(file, get_folder = False): - return file.split(os.sep)[-1] - -# Get 7-zip install dir -def get_szip_dir(): - key_location = r"SOFTWARE\7-Zip" - value = "Path" - try: - key = wr.OpenKey(wr.HKEY_LOCAL_MACHINE, key_location) - install_dir = wr.QueryValueEx(key, value)[0] - wr.CloseKey(key) - except: - error("No 7-zip installation found!\nIf you insist on using WinRar, change the script yourself ¯\_(ツ)_/¯") - return install_dir - -# Get Civ V install dir -def get_civ_install_dir(): - key_location = r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\steam app 8930" - value = "installlocation" - try: - key = wr.OpenKey(wr.HKEY_LOCAL_MACHINE, key_location) - install_dir = wr.QueryValueEx(key, value)[0] - wr.CloseKey(key) - except: - error("No Civ 5 installation found!") - return install_dir +# This only runs with 7zip. If you want to use WinRar you'll have to change the methods yourself - or just download 7zip =P +szip = r"C:\Program Files\7-Zip\7z.exe" # Paths -szip = j(get_szip_dir(), "7z.exe") -modsave_path = j(os.getcwd(), "..") -base_path = j(get_civ_install_dir(), "Assets", "DLC") -vanilla_packs_path = j(base_path, vanilla_packs_folder) -eui_folder_path = j(base_path, "UI_bc1") +# Change to base DLC directory +os.chdir("../..") +base_path = os.getcwd() +modsave_path = j(base_path, modsave_folder) modpack_path = j(base_path, modpack_folder_name) -ui_folder_path = j(modpack_path, "UI") +vanilla_packs_path = j(base_path, vanilla_packs_folder) +ui_path = j(modpack_path, "UI") +eui_path = j(base_path, "UI_bc1") # Files -files_ext = j("**", "*.lua") -base_ui_files = j(base_path, "..", "UI", files_ext) -gnk_ui_files = j(base_path, "Expansion", "UI", files_ext) -bnw_ui_files = j(base_path, "Expansion2", "UI", files_ext) -vanilla_eui_zip_path = j(vanilla_packs_path, vanilla_eui_zip) +base_eui_zip_path = j(vanilla_packs_path, vanilla_eui_zip) modded_eui_zip_path = j(base_path, modded_eui_zip) -mod_files = j(modpack_path, "Mods", files_ext) -ui_files = j(ui_folder_path, files_ext) -eui_files = j(eui_folder_path, files_ext) +mod_files = j(modpack_path, "Mods", "**", "*.lua") +ui_files = j(ui_path, "*.lua") +eui_files = j(eui_path, "*", "*.lua") # Global Variables -eui_only = False -vanilla_ui_files = [] load_tags = {} unit_panel_modcompat_needed = False +null = open(os.devnull, 'w') +eui_only = False -# Change working dir to base path -os.chdir(base_path) - # Get modpack zip while True: modpack_name = input("\nWhich pack should be converted?\n(Type 'EUI' to just convert EUI)\n") @@ -130,31 +87,35 @@ while True: # Remove previous modpack -print("\nRemoving previous modpack and EUI leftovers...") +print("Removing previous modpack leftovers...") if os.path.isdir(modpack_path): shutil.rmtree(modpack_path) -if os.path.isdir(eui_folder_path): - shutil.rmtree(eui_folder_path) - +if os.path.isdir(eui_path): + shutil.rmtree(eui_path) # Compile EUI with colored unlocked citizens if not os.path.isfile(modded_eui_zip_path): - print("Creating colored unlocked citizens EUI...") - subprocess.run([szip, 'x', vanilla_eui_zip_path], stdout=null, stderr=null) + print("Creating colored unlocked Citizens EUI...") + subprocess.run([szip, 'x', base_eui_zip_path], stdout=null, stderr=null) + #shutil.move(j(vanilla_packs_path, eui_file_name), eui_path) for eui_cuc_file_name in eui_cuc_file_names: eui_cuc_file = g(j(modsave_path, eui_cuc_file_name + "*"))[0] - orig_eui_file = g(j(eui_folder_path, "*", eui_cuc_file_name))[0] + orig_eui_file = g(j(eui_path, "*", eui_cuc_file_name))[0] shutil.move(orig_eui_file, orig_eui_file + ".orig") shutil.copyfile(eui_cuc_file, orig_eui_file) - subprocess.run([szip, 'a', modded_eui_zip, eui_folder_path], stdout=null, stderr=null) -else: + subprocess.run([szip, 'a', modded_eui_zip, eui_path], stdout=null, stderr=null) +elif not eui_only: # Unzip EUI print("Unzipping EUI...") subprocess.run([szip, 'x', modded_eui_zip_path], stdout=null, stderr=null) # Stop here if only EUI should be converted if eui_only: - quit() + if os.path.isdir(eui_path): + shutil.rmtree(eui_path) + null.close() + print("Done.\n") + exit(0) # Unzip modpack zip @@ -162,58 +123,58 @@ print("Unzipping Modpack...") subprocess.run([szip, 'x', j(vanilla_packs_path, modpack_zip)], stdout=null, stderr=null) -# Get vanilla UI files -print("Gathering Vanilla UI file list...") -globbed = g(base_ui_files, recursive=True) -globbed.extend(g(gnk_ui_files, recursive=True)) -globbed.extend(g(bnw_ui_files, recursive=True)) -for file in globbed: - file_name = get_file_name(file) - if not file_name in ui_files: - vanilla_ui_files.append(file_name) - # Manage mod files for mod_file in g(mod_files, recursive = True): - mod_file_name = get_file_name(mod_file) - mod_file_folder = os.sep.join(mod_file.split(os.sep)[-3:-1]) + mod_file_path = mod_file.split(os.sep) + mod_file_name = mod_file_path[len(mod_file_path) - 1] + # IGE UI compat file if mod_file_name == ige_compat_file_name: print("Providing IGE-EUI-compat...") shutil.move(mod_file, mod_file + ".orig") shutil.copyfile(g(j(modsave_path, ige_compat_file_name + "*"))[0], mod_file) - # Find out if modcompat unit panel needed - elif mod_file_name in unit_panel_modcompat_file_names: - print("UnitPanel modcompat need detected...") - unit_panel_modcompat_needed = True + # Delete UI overwrite duplicates - elif mod_file_name in vanilla_ui_files: - print("Removing overwriting file {}...".format(j(mod_file_folder, mod_file_name))) + if mod_file_name in delete_file_names: + print("Removing overwriting file " + mod_file_name + "...") os.remove(mod_file) + # Find out if modcompat unit panel needed + if mod_file_name in unit_panel_modcompat_file_names: + print("UnitPanel modcompat need detected...") + unit_panel_modcompat_needed = True # Delete useless desktop.ini (Thanks True...) ini_files = re.sub(r"\.\w+$", ".ini", mod_files) for ini_file in g(ini_files, recursive = True): - ini_file_name = get_file_name(ini_file) + ini_file_path = ini_file.split(os.sep) + ini_file_name = ini_file_path[len(ini_file_path) - 1] if ini_file_name == "desktop.ini": print("Removing useless desktop.ini (Thanks True)...") os.remove(mod_file) # Get stuff from UI files -for ui_file in g(ui_files): - ui_file_name = get_file_name(ui_file) - print("Getting tags from " + ui_file_name + "...") - load_tags[ui_file_name] = [] +for ui_file in g(ui_files): with open(ui_file, 'r') as file: lines = file.readlines() + + ui_file_path = ui_file.split(os.sep) + ui_file_name = ui_file_path[len(ui_file_path) - 1] + + print("Getting tags from " + ui_file_name + "...") + + load_tags[ui_file_name] = [] + for line in lines: if line.startswith(load_tag): load_tags[ui_file_name].append(line) # Insert stuff into EUI files for eui_file in g(eui_files): - eui_file_name = get_file_name(eui_file) + eui_file_path = eui_file.split(os.sep) + eui_file_name = eui_file_path[len(eui_file_path) - 1] + # Base UI files if eui_file_name in load_tags.keys(): print("Writing tags to " + eui_file_name + "...") @@ -230,13 +191,20 @@ for eui_file in g(eui_files): # Move EUI folder print("Moving EUI folder...") -shutil.move(eui_folder_path, modpack_path) +shutil.move(eui_path, modpack_path) print("Removing UI folder...") -shutil.rmtree(ui_folder_path) +shutil.rmtree(ui_path) # Zip modpack folder print("Zipping Modpack...") subprocess.run([szip, 'a', modpack_name + "_EUI.7z", modpack_path], stdout=null, stderr=null) +## Move modpack folder +#print("Moving Modspack folder") +#shutil.move(modpack_path, j(base_path, modpack_folder_name)) + #Finishing up -quit() \ No newline at end of file +null.close() +print("Done.\n") +input("Press Enter to exit. . .") +exit(0) \ No newline at end of file diff --git a/EUI_Modpack_Converter/converter_new_WIP.py b/EUI_Modpack_Converter/converter_new_WIP.py new file mode 100644 index 0000000000000000000000000000000000000000..0bbbf6df6b10cf6e11794beaf035fb2625b93299 --- /dev/null +++ b/EUI_Modpack_Converter/converter_new_WIP.py @@ -0,0 +1,255 @@ +######################################################################## +# # +# © 2021 - MPL 2.0 - Rsge - v2.0.1 # +# https://github.com/Rsge/Civ-V-EUI-Modpack-Converter # +# # +# WINDOWS ONLY! # +# 7-ZIP NEEDED! # +# If you want to use WinRar you'll have to change the methods yourself # +# (or just download 7-zip =P) # +# # +######################################################################## + + +#-----------------------------------------# +# Customize these according to your setup # +#-----------------------------------------# + +# Vanilla EUI file (in vanilla_packs_folder) +vanilla_eui_zip = "!EUI.7z" + +# CUC-version file name of EUI +modded_eui_zip = "!EUI_CUC.7z" + +# Folder containing the vanilla packs in DLC folder +# (Sid Meier's Civilization V\Assets\DLC\ThisVariableAsFolderName) +vanilla_packs_folder = "zz_Vanilla_Versions" + +#----------------------------------------------------# +# Don't change anything after here # +# [except if you know what you're doing of cause ;)] # +#----------------------------------------------------# + +# Imports +import os +import winreg as wr +from os.path import join as j +from glob import glob as g +import subprocess +import shutil +import re + +## Functions +print("Defining functions...") +# Closing functions +null = open(os.devnull, 'w') +def quit(): + null.close() + print("Done.\n") + input("Press Enter to exit. . .") + exit(0) +def error(msg): + null.close() + print("Error!\n{}\n".format(msg)) + input("Press Enter to exit. . .") + exit(1) + +# Get file name +def get_file_name(file, get_folder = False): + return file.split(os.sep)[-1] + +# Get 7-zip install dir +def get_szip_dir(): + key_location = r"SOFTWARE\7-Zip" + value = "Path" + try: + key = wr.OpenKey(wr.HKEY_LOCAL_MACHINE, key_location) + install_dir = wr.QueryValueEx(key, value)[0] + wr.CloseKey(key) + except: + error("No 7-zip installation found!\nIf you insist on using WinRar, change the script yourself ¯\_(ツ)_/¯") + return install_dir + +# Get Civ V install dir +def get_civ_install_dir(): + key_location = r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\steam app 8930" + value = "installlocation" + try: + key = wr.OpenKey(wr.HKEY_LOCAL_MACHINE, key_location) + install_dir = wr.QueryValueEx(key, value)[0] + wr.CloseKey(key) + except: + error("No Civ 5 installation found!") + return install_dir + +## Global values +print("Configuring variables...") +# Names +modpack_folder_name = "MP_MODSPACK" +eui_cuc_file_names = ["CityBannerManager.lua", + "CityView.lua", + "Highlights.xml"] +load_tag = "ContextPtr:LoadNewContext" +unit_panel_tag = "LuaEvents.UnitPanelActionAddin" +unit_panel_file_name = "UnitPanel.lua" +ige_compat_file_name = "IGE_Window.lua" +# Paths +szip = j(get_szip_dir(), "7z.exe") +modsave_path = j(os.getcwd(), "..") +base_path = j(get_civ_install_dir(), "Assets", "DLC") +vanilla_packs_path = j(base_path, vanilla_packs_folder) +eui_folder_path = j(base_path, "UI_bc1") +modpack_path = j(base_path, modpack_folder_name) +mods_path = j(modpack_path, "Mods") +ui_folder_path = j(modpack_path, "UI") +# Files +files_ext = j("**", "*.lua") +base_ui_files = j(base_path, "..", "UI", files_ext) +gnk_ui_files = j(base_path, "Expansion", "UI", files_ext) +bnw_ui_files = j(base_path, "Expansion2", "UI", files_ext) +vanilla_eui_zip_path = j(vanilla_packs_path, vanilla_eui_zip) +modded_eui_zip_path = j(base_path, modded_eui_zip) +mod_files = j(mods_path, files_ext) +ui_files = j(ui_folder_path, files_ext) +eui_files = j(eui_folder_path, files_ext) + +# Global variables +eui_only = False +vanilla_ui_files = [] +unit_panel_files = [] +load_tags = {} + + +# Change working dir to base path +os.chdir(base_path) + +# Get modpack zip +while True: + modpack_name = input("\nWhich pack should be converted?\n(Type 'EUI' to just convert EUI)\n") + if modpack_name == "EUI": + eui_only = True + break + modpack_zips = g(j(vanilla_packs_path, modpack_name + ".*")) + if len(modpack_zips) > 0: + modpack_zip = modpack_zips[0] + break + print("This file doesn't exist, try again.") +print("") + +## Remove previous modpack +#print("Removing previous modpack and EUI leftovers...") +#if os.path.isdir(modpack_path): +# shutil.rmtree(modpack_path) +#if os.path.isdir(eui_folder_path): +# shutil.rmtree(eui_folder_path) + + +## Compile EUI with colored unlocked citizens +#if not os.path.isfile(modded_eui_zip_path): +# print("Creating colored unlocked citizens EUI...") +# subprocess.run([szip, 'x', vanilla_eui_zip_path], stdout=null, stderr=null) +# for eui_cuc_file_name in eui_cuc_file_names: +# eui_cuc_file = g(j(modsave_path, eui_cuc_file_name + "*"))[0] +# orig_eui_file = g(j(eui_folder_path, "*", eui_cuc_file_name))[0] +# shutil.move(orig_eui_file, orig_eui_file + ".orig") +# shutil.copyfile(eui_cuc_file, orig_eui_file) +# subprocess.run([szip, 'a', modded_eui_zip, eui_folder_path], stdout=null, stderr=null) +#else: +# # Unzip EUI +# print("Unzipping EUI...") +# subprocess.run([szip, 'x', modded_eui_zip_path], stdout=null, stderr=null) + +## Stop here if only EUI should be converted +#if eui_only: +# quit() + + +## Unzip modpack zip +#print("Unzipping Modpack...") +#subprocess.run([szip, 'x', j(vanilla_packs_path, modpack_zip)], stdout=null, stderr=null) + + +# Get vanilla UI files +print("Gathering Vanilla UI file list...") +globbed = g(base_ui_files, recursive=True) +globbed.extend(g(gnk_ui_files, recursive=True)) +globbed.extend(g(bnw_ui_files, recursive=True)) +for file in globbed: + file_name = get_file_name(file) + if not file_name in ui_files: + vanilla_ui_files.append(file_name) + +# Manage mod files +print("Managing mod's files:") +for mod_file in g(mod_files, recursive = True): + mod_file_name = get_file_name(mod_file) + mod_file_short_path = mod_file.removeprefix(mods_path + os.sep) + # IGE UI compat file + if mod_file_name == ige_compat_file_name: + print("\tProviding IGE-EUI-compat...") + #shutil.move(mod_file, mod_file + ".orig") + #shutil.copyfile(g(j(modsave_path, ige_compat_file_name + "*"))[0], mod_file) + # Delete UI overwrite duplicates + elif mod_file_name in vanilla_ui_files: + print("\tRemoving overwriting file \"{}\"...".format(mod_file_short_path)) + #os.remove(mod_file) + # Get unit panel addon files + else: + with open(mod_file, 'r') as file: + lines = file.readlines() + for line in lines: + if unit_panel_tag in line: + print("\tDetecting unit panel addon in file \"{}\"...".format(mod_file_short_path)) + unit_panel_files.append(mod_file_name) + break + + +## Delete useless desktop.ini (Thanks True...) +#ini_files = re.sub(r"\.\w+$", ".ini", mod_files) +#for ini_file in g(ini_files, recursive = True): +# ini_file_name = get_file_name(ini_file) +# if ini_file_name == "desktop.ini": +# print("Removing useless desktop.ini (Thanks True)...") +# os.remove(mod_file) + + +## Get stuff from UI files +#for ui_file in g(ui_files): +# ui_file_name = get_file_name(ui_file) +# print("Getting tags from " + ui_file_name + "...") +# load_tags[ui_file_name] = [] +# with open(ui_file, 'r') as file: +# lines = file.readlines() +# for line in lines: +# if line.startswith(load_tag): +# load_tags[ui_file_name].append(line) + +## Insert stuff into EUI files +#for eui_file in g(eui_files): +# eui_file_name = get_file_name(eui_file) +# # Base UI files +# if eui_file_name in load_tags.keys(): +# print("Writing tags to " + eui_file_name + "...") +# with open(eui_file, 'a') as file: +# file.write('\n') +# for load_tag in load_tags[eui_file_name]: +# file.write(load_tag) +# # Modcompat unit panel +# elif eui_file_name == unit_panel_file_name and unit_panel_modcompat_needed: +# print("Providing EUI-UnitPanel-Modcompat...") +# shutil.move(eui_file, eui_file + ".orig") +# shutil.copyfile(g(j(modsave_path, unit_panel_file_name + "*"))[0], eui_file) + + +## Move EUI folder +#print("Moving EUI folder...") +#shutil.move(eui_folder_path, modpack_path) +#print("Removing UI folder...") +#shutil.rmtree(ui_folder_path) + +## Zip modpack folder +#print("Zipping Modpack...") +#subprocess.run([szip, 'a', modpack_name + "_EUI.7z", modpack_path], stdout=null, stderr=null) + +#Finishing up +quit() \ No newline at end of file diff --git a/Highlights.xml.cuc b/Highlights.xml.cuc index efcb992d049ee7a2e6d31263cdc9f287b86f61a2..8a3200db7e78000046a754e09edd94bc0d041428 100644 --- a/Highlights.xml.cuc +++ b/Highlights.xml.cuc @@ -27,9 +27,9 @@ <style name="WorkedFill" type="FilledHex" width ="1" color="0,255,0,50" /> <style name="WorkedOutline" type="SplineBorder" width ="7" texture="hex_contour1.dds" color="0,255,0,164" /> - - <style name="UnlockedFill" type="FilledHex" width ="1" color="7,107,0,50" /> - <style name="UnlockedOutline" type="SplineBorder" width ="7" texture="hex_contour1.dds" color="7,107,0,164" /> + + <style name="UnlockedFill" type="FilledHex" width ="1" color="0,255,255,50" /> + <style name="UnlockedOutline" type="SplineBorder" width ="7" texture="hex_contour1.dds" color="0,255,255,164" /> <style name="OwnedFill" type="FilledHex" width ="1" color="0,140,255,50" /> <style name="OwnedOutline" type="SplineBorder" width ="7" texture="hex_contour1.dds" color="0,140,255,164" /> diff --git a/README.md b/README.md index 92cf95badc6411788011b7220c1499608b80a17e..7e8dd1b02d9ca44b424418863c3d72643d6b98c2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Civilization V EUI Modpack Converter -A script for Civilization V to add Colored Unlocked Citizens (CUC) to Enhanced User Interface (EUI) and EUI to MPMPM modpacks. +A script for Civilization V to add Enhanced User Interface (EUI) to MPMPM modpacks. +Also adds EUI compatibility for the InGameEditor (IGE) mod and + The following things are assumed when running the script without changes: * Having [7-zip](https://www.7-zip.org/) installed in the standard programs directory. * Every pack being saved as a .7z or .rar archive. @@ -16,6 +18,6 @@ The following things are assumed when running the script without changes: ### Credits * [*Enhanced User Interface*](https://forums.civfanatics.com/resources/civ5-enhanced-user-interface.24303/) by bc1 * [*Improved Enhanced User Interface*](https://www.reddit.com/r/civ/comments/3i46rk/update_improved_enhanced_user_interface/) (*Colored Unlocked Citizens*) by Dushku \ - (Changed color from culture expansion magenta to a dark green) + (Changed color from the culture expansion magenta to yellow) * [*Ingame Editor compat for EUI*](https://forums.civfanatics.com/resources/ingame-editor-compatibility-file-for-eui.24647/) by bc1 * [*MPMPM - Multiplayer Mod DLC-hack*](https://forums.civfanatics.com/threads/mpmpm-multiplayer-mod-dlc-hack-updated.533238/) by cicero225 diff --git a/UnitPanel.lua.eui.modcompat b/UnitPanel.lua.eui.modcompat index ad4ff3647a81379e59fa20a434068853cba6e99b..6d47c534d3e99206b23d48ee6c4270d1e134e581 100644 --- a/UnitPanel.lua.eui.modcompat +++ b/UnitPanel.lua.eui.modcompat @@ -31,11 +31,11 @@ local bnw_mode = Game.GetActiveLeague ~= nil local ceil = math.ceil local floor = math.floor +local min = math.min local max = math.max local pairs = pairs --local print = print local format = string.format -local concat = table.concat local insert = table.insert local remove = table.remove local tostring = tostring @@ -123,10 +123,10 @@ local g_cityFocusIcons = { local g_UnitTypeOrder = {} do - local i = 1 + local i = 0 for unit in GameInfo.Units() do + i = i + 65536 g_UnitTypeOrder[ unit.ID ] = i - i = i + 1 end end @@ -258,6 +258,11 @@ end local function UpdateCity( city, instance ) if city and instance then + local isNotPuppet = not city:IsPuppet() + local isRazing = city:IsRazing() + local isResistance = city:IsResistance() + local isCapital = city:IsCapital() + local itemInfo, portraitOffset, portraitAtlas, buildPercent local turnsRemaining = city:GetProductionTurnsLeft() local productionNeeded = city:GetProductionNeeded() @@ -280,47 +285,40 @@ local function UpdateCity( city, instance ) itemInfo = IconHookup( portraitOffset or itemInfo.PortraitIndex, 64, portraitAtlas or itemInfo.IconAtlas, instance.CityProduction ) if productionNeeded > 0 then buildPercent = 1 - max( 0, storedProduction/productionNeeded ) - else - buildPercent = 0 end - instance.BuildMeter:SetPercents( 0, buildPercent ) - else - turnsRemaining = nil + instance.BuildMeter:SetPercents( 0, buildPercent or 0 ) end instance.CityProduction:SetHide( not itemInfo ) - instance.BuildGrowth:SetString( turnsRemaining ) + instance.BuildGrowth:SetString( itemInfo and not isResistance and not isRazing and turnsRemaining ) instance.CityPopulation:SetString( city:GetPopulation() ) local foodPerTurnTimes100 = city:FoodDifferenceTimes100() - if foodPerTurnTimes100 < 0 then - instance.CityGrowth:SetString( " [COLOR_RED]" .. (floor( city:GetFoodTimes100() / -foodPerTurnTimes100 ) + 1) .. "[ENDCOLOR] " ) + if isRazing or foodPerTurnTimes100 < 0 then + instance.CityGrowth:SetString( "[COLOR_RED]" .. (isRazing and 1 or min( floor( ( city:GetFoodTimes100() ) / -foodPerTurnTimes100 ) + 1, 99 ) ) .. "[ENDCOLOR]" ) elseif city:IsForcedAvoidGrowth() then instance.CityGrowth:SetString( "[ICON_LOCKED]" ) elseif city:IsFoodProduction() or foodPerTurnTimes100 == 0 then instance.CityGrowth:SetString() else - instance.CityGrowth:SetString( " "..city:GetFoodTurnsLeft().." " ) + instance.CityGrowth:SetString( min( city:GetFoodTurnsLeft(), 99 ) ) end - local isNotPuppet = not city:IsPuppet() - local isNotRazing = not city:IsRazing() - local isNotResistance = not city:IsResistance() - local isCapital = city:IsCapital() - instance.CityIsCapital:SetHide( not isCapital ) instance.CityIsPuppet:SetHide( isNotPuppet ) - instance.CityFocus:SetText( isNotRazing and isNotPuppet and g_cityFocusIcons[city:GetFocusType()] ) + instance.CityFocus:SetText( not isRazing and isNotPuppet and g_cityFocusIcons[city:GetFocusType()] ) instance.CityQuests:SetText( city:GetWeLoveTheKingDayCounter() > 0 and "[ICON_HAPPINESS_1]" or (GameInfo.Resources[city:GetResourceDemanded()] or {}).IconString ) - instance.CityIsRazing:SetHide( isNotRazing ) - instance.CityIsResistance:SetHide( isNotResistance ) + instance.CityIsRazing:SetHide( not isRazing ) + instance.CityIsResistance:SetHide( not isResistance ) + instance.CityResistanceTurns:SetText( isRazing and city:GetRazingTurns() or isResistance and city:GetResistanceTurns() ) instance.CityIsConnected:SetHide( isCapital or not g_activePlayer:IsCapitalConnectedToCity( city ) ) instance.CityIsBlockaded:SetHide( not city:IsBlockaded() ) instance.CityIsOccupied:SetHide( not city:IsOccupied() or city:IsNoOccupiedUnhappiness() ) - instance.Name:SetString( city:GetName() ) - + instance.CityName:SetString( city:GetName() ) + local religion = city.GetReligiousMajority and GameInfo.Religions[city:GetReligiousMajority()] + instance.CityReligion:SetString( religion and religion.IconString ) local culturePerTurn = city:GetJONSCulturePerTurn() instance.BorderGrowth:SetString( culturePerTurn > 0 and ceil( (city:GetJONSCultureThreshold() - city:GetJONSCultureStored()) / culturePerTurn ) ) - local percent = 1 - city:GetDamage() / ( gk_mode and city:GetMaxHitPoints() or GameDefines.MAX_CITY_HIT_POINTS ) + local percent = 1 - city:GetDamage() / ( city.GetMaxHitPoints and city:GetMaxHitPoints() or GameDefines.MAX_CITY_HIT_POINTS ) instance.Button:SetColor( Color( 1, percent, percent, 1 ) ) end end @@ -426,7 +424,7 @@ g_unitsIM, g_units = g_RibbonManager( "UnitInstance", Controls.UnitStack, Contro for unit in g_activePlayer:Units() do if FilterUnit( unit ) then unitID = unit:GetID() - Create( unit, unitID, g_UnitTypeOrder[unit:GetUnitType()] * 65536 + unitID % 65536 ) + Create( unit, unitID, g_UnitTypeOrder[unit:GetUnitType()] + unitID % 65536 ) end end Controls.UnitStack:SortChildren( SortByVoid2 ) @@ -503,6 +501,7 @@ g_citiesIM, g_cities = g_RibbonManager( "CityInstance", Controls.CityStack, Cont CityIsRazing = "EUI_ItemTooltip", CityIsConnected = "EUI_ItemTooltip", CityIsBlockaded = "EUI_ItemTooltip", + CityReligion = "EUI_ItemTooltip", CityFocus = "EUI_ItemTooltip", CityGrowth = "EUI_ItemTooltip", CityQuests = "EUI_ItemTooltip", @@ -652,6 +651,7 @@ local function ResizeCityUnitRibbons() Controls.CityStack:ChangeParent( Controls.CityPanel ) end Controls.CityPanel:ReprocessAnchoring() + Controls.DarkBorders:SetSizeY( cityStackHeight+g_topOffset ) -- Controls.CityPanel:SetSizeY( cityStackHeight ) Controls.UnitScrollPanel:SetHide( not unitStackHeight ) @@ -768,7 +768,7 @@ local function CreateUnit( playerID, unitID ) --hexVec, unitType, cultureType, c if unit then AddUnitType( unit, unitID ) if FilterUnit( unit ) then - g_unitsIM.Create( unit, unitID, g_UnitTypeOrder[unit:GetUnitType()] + unitID / 65536 ) + g_unitsIM.Create( unit, unitID, g_UnitTypeOrder[unit:GetUnitType()] + unitID % 65536 ) Controls.UnitStack:SortChildren( SortByVoid2 ) return ResizeCityUnitRibbons() end @@ -864,7 +864,6 @@ local function UnitActionToolTip( button ) end local function UpdateUnitPanel() - actionIM:ResetInstances() -- Retrieve the currently selected unit. local unit = GetHeadSelectedUnit() -- Events.GameplayAlertMessage( "SerialEventUnitInfoDirty, GetHeadSelectedUnit=".. tostring(unit and unit:GetName())..", last unit="..tostring(g_lastUnit and g_lastUnit:GetName()) ) @@ -1007,6 +1006,7 @@ local function UpdateUnitPanel() --========================================================== + for actionID = 0, #GameInfoActions do action = GameInfoActions[ actionID ] if action and action.Visible ~= false then @@ -1111,7 +1111,7 @@ local function UpdateUnitPanel() end -- Unit XP - if unit:IsCombatUnit() or unit:GetDomainType() == DomainTypes.DOMAIN_AIR then + if unit:IsCombatUnit() or unit:CanAirAttack() then local iLevel = unit:GetLevel() local iExperience = unit:GetExperience() local iExperienceNeeded = unit:ExperienceNeeded() @@ -1310,6 +1310,7 @@ local function UpdateOptions() end g_citiesIM.Initialize( option ) Controls.CityPanel:SetHide( option ) + Controls.DarkBorders:SetHide( option ) UpdateUnitPanel() ResizeCityUnitRibbons() @@ -1464,7 +1465,6 @@ ContextPtr:SetShowHideHandler( end end) ContextPtr:SetHide( false ) +Controls.DarkBorders:ChangeParent( LookUpControl( "/Ingame/WorldViewControls" ) ) end) -ContextPtr:LoadNewContext("EvilSpiritsMission") -ContextPtr:LoadNewContext("THTanukiMission") \ No newline at end of file