Skip to content
This repository was archived by the owner on Oct 14, 2024. It is now read-only.

Commit 6992003

Browse files
committed
Initial commit
0 parents  commit 6992003

20 files changed

+995
-0
lines changed

.gitattributes

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

EU4Lib.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#This will need to be updated. Currently for 1.28
2+
from PIL import Image, ImageDraw
3+
4+
def province():
5+
pass
6+
def flag(tag):
7+
index = open("src\\flagfiles.txt", "r")
8+
line = index.read()
9+
a = line.partition(tag) #Separate into a 3-tuple around tag
10+
flagnum = a[0].count(".tga") #Get image number starting at 0
11+
#Each flag file is 16x16 so a total of 256 each
12+
#Each flag icon is 128x128 pixels
13+
flagfile = Image.open("src\\flagfiles_" + str(int(flagnum/256)) + ".tga")
14+
x = 128*((flagnum%256)%16)
15+
y = 128*int((flagnum%256)/16)
16+
flagimg = flagfile.crop((x, y, x+127, y+127))
17+
flagimg.load()
18+
return flagimg

EU4img.py

+280
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
from PIL import Image, ImageDraw, ImageFont
2+
import os
3+
import EU4Lib
4+
srcFile = open(input(".EU4 file name: ").strip('"\n'), "r")
5+
imgPolitical = Image.open(input(".png political mapmode name: ").strip('"\n'))
6+
imgPlayers = Image.open(input(".png players mapmode name: ").strip('"\n'))
7+
8+
imgFinal = Image.open("src//finalTemplate.png")
9+
mapFinal = imgPolitical.copy()
10+
11+
#Clears terminal
12+
def clear():
13+
#print(chr(27) + "[2J")
14+
os.system('cls' if os.name == 'nt' else 'clear')
15+
16+
class Nation:
17+
def __init__(self, player):
18+
self.player = player
19+
self.tag = None
20+
self.development = None
21+
self.prestige = None
22+
self.stability = None
23+
#self.manpower = None
24+
#self.maxManpower = None
25+
self.army = 0.0
26+
self.navy = 0
27+
self.debt = 0
28+
self.treasury = 0.0
29+
self.totalIncome = 0.0
30+
self.scorePlace = None
31+
32+
#Start Data Selection
33+
countries = []
34+
playertags = []
35+
dlc = []
36+
GP = []
37+
lines = srcFile.readlines()
38+
brackets = []
39+
print("Reading save file...")
40+
for line in lines:
41+
if "{" in line:
42+
if line.strip("\n ").endswith("}"):
43+
continue
44+
else:
45+
brackets.append(line.rstrip("\n "))
46+
#print("{")
47+
elif "}" in line:
48+
brackets.pop()
49+
#print("}")
50+
#Get rid of long, useless sections
51+
#Possible to use sections:
52+
#Provinces
53+
elif len(brackets) < 0 and ("trade={" == brackets[1] or "provinces={" == brackets[0] or "rebel_faction={" == brackets[0] or (len(brackets) < 1 and "\tledger_data={" == brackets[1]) or "_area={" in brackets[0] or "change_price={" == brackets[0]):
54+
continue
55+
#Ignoring all but player / GP
56+
#Possible to use: HRE / pope / crusade / china
57+
58+
#elif len(brackets) < 0 and ("countries={" == brackets[0] and not (line.strip("\t={\n") in GP or line.strip("\t={\n") in playertags)):
59+
#print("HI" + line.strip("\t={\n"))
60+
#continue
61+
else:
62+
#This is where we do stuff
63+
#Get current gamedate
64+
if line.startswith("date=") and brackets == []:
65+
date = line.strip('date=\n')
66+
#Get save DLC (not sure if we use this...)
67+
elif brackets == ["dlc_enabled={"]:
68+
dlc.append(line.strip('\t"\n'))
69+
#Check if game is mp
70+
elif "multi_player=" in line and brackets == []:
71+
if "yes" in line:
72+
mp = True
73+
else:
74+
mp = False
75+
#Get player names and country tags
76+
elif brackets == ["players_countries={"]:
77+
#In the file, the format is like this:
78+
#players_countries={
79+
# "playername"
80+
# "SWE"
81+
#
82+
#Where " " is a tab
83+
#This v adds a new country object and player name if there is none open.
84+
#print("Found a line in players_countries")
85+
if len(countries) == 0 or countries[len(countries)-1].tag is not None:
86+
print("Adding: ", line.strip('\t"\n'))
87+
countries.append(Nation(line.strip('\t"\n')))
88+
#Add country code to most recent country (which, because of ^ cannot have a tag)
89+
else:
90+
for x in countries:
91+
if x.tag == line.strip('\t"\n'): #Players are added later to the list as they join, so we remove all previous players
92+
countries.remove(x)
93+
countries[len(countries)-1].tag = line.strip('\t"\n')
94+
playertags.append(line.strip('\t"\n'))
95+
print("Country: ", line.strip('\t"\n'))
96+
#Get current age
97+
elif "current_age=" in line and brackets == []:
98+
age = line[12:].strip('"\n')
99+
print("\nAge: " + age)
100+
#Get top 8
101+
elif "country=" in line and brackets == ["great_powers={", "\toriginal={"]:
102+
if len(GP) < 8: #Make sure to not include leaving GPs
103+
GP.append(line.strip('\tcountry="\n'))
104+
print("Found GP: " + line.strip('\tcountry="\n'))
105+
#Get HRE emperor tag
106+
elif "\temperor=" in line and brackets == ["empire={"]:
107+
HRETag = line.strip('\temperor="\n')
108+
print("Found HRE Emperor: " + HRETag)
109+
#Get Celestial emperor tag
110+
elif "emperor=" in line and brackets == ["celestial_empire={"]:
111+
chinaTag = line.strip('\temperor="\n')
112+
print("Found Celestial Empire: " + chinaTag)
113+
#Get target of crusade ('---' if none)
114+
elif "crusade_target=" in line and brackets == ["religion_instance_data={", "\tcatholic={", "\t\tpapacy={"]:
115+
crusade = line.strip('\tcrusade_target="\n')
116+
print("Found crusade target: " + crusade)
117+
#Get papal controller
118+
elif "previous_controller=" in line and brackets == ["religion_instance_data={", "\tcatholic={", "\t\tpapacy={"]:
119+
continue
120+
#Country-specific for players
121+
#TODO: Not sure if this need optimization
122+
elif len(brackets) > 1 and brackets[0] == "countries={" and brackets[1].strip("\t={\n") in playertags:
123+
for x in countries:
124+
if x.tag in brackets[1]:
125+
#Here we have all the stats for country x on the players list
126+
if len(brackets) == 2:
127+
if "raw_development=" in line:
128+
x.development = round(float(line.strip("\traw_devlopmnt=\n")))
129+
elif "score_place=" in line:
130+
x.scorePlace = round(float(line.strip("\tscore_place=\n")))
131+
elif "prestige=" in line:
132+
x.prestige = round(float(line.strip("\tprestige=\n")))
133+
elif "stability=" in line:
134+
x.stability = round(float(line.strip("\tstability=\n")))
135+
elif "treasury=" in line:
136+
x.treasury = round(float(line.strip("\ttreasury=\n")))
137+
elif "estimated_monthly_income=" in line:
138+
x.totalIncome = round(float(line.strip("\testimated_monthly_income=\n")))
139+
#elif "\tmanpower=" in line:
140+
#x.manpower = round(float(line.strip("\tmanpower=\n")))
141+
#elif "max_manpower=" in line:
142+
#x.maxManpower = round(float(line.strip("\tmax_manpower=\n")))
143+
else: continue
144+
elif len(brackets) == 3:
145+
#Get size of each loan
146+
if brackets[2] == "\t\tloan={" and "amount=" in line:
147+
x.debt += round(float(line.strip("\tamount=\n")))
148+
elif len(brackets) == 4:
149+
#Add 1 to army size for each regiment
150+
if brackets[2] == "\t\tarmy={" and "regiment={" in brackets[3] and "morale=" in line:
151+
x.army = x.army + 1000
152+
#Subtract damage done to units from army size
153+
#This needs to be separate from ^ because for full regiments there is no "strength=" tag
154+
elif brackets[2] == "\t\tarmy={" and "regiment={" in brackets[3] and "strength=" in line:
155+
try:
156+
x.army = round(x.army - 1000 + 1000*float(line.strip("\tstrength=\n")))
157+
except ValueError:
158+
continue
159+
elif brackets[2] == "\t\tnavy={" and brackets[3] == "\t\t\tship={" and "\thome=" in line:
160+
x.navy += 1
161+
162+
for x in countries: #Remove dead countries
163+
if x.development is None or x.development == None or x.development == 0:
164+
countries.remove(x)
165+
#Sort Data:
166+
countries.sort(key=lambda x: x.development, reverse=True)
167+
168+
169+
print("Finished extracting save data.")
170+
print("\nPlayer nations: "+ str(len(countries)))
171+
print(mp)
172+
print(date)
173+
print(dlc)
174+
for x in countries:
175+
print("\n"+x.tag+ ": "+ x.player)
176+
print("Army:", x.army)
177+
print("Navy:", x.navy)
178+
print("Dev:", x.development)
179+
print("Stab:", x.stability)
180+
print("Treasury:", x.treasury)
181+
print("Debt:", x.debt)
182+
#print("Manpower: "+ x.manpower)
183+
#print("Max Manpower: "+ x.maxManpower)
184+
print("Prestige:", x.prestige)
185+
186+
#End Data Selection
187+
print("")
188+
#Start Map Creation
189+
#print("Showing political mapmode...")
190+
#totalPixels = mapFinal.size[0] * mapFinal.size[1]
191+
#mapFinal.show()
192+
print("Preparing map editing...")
193+
mapDraw = ImageDraw.Draw(mapFinal)
194+
print("Drawing player country borders...")
195+
for x in range(mapFinal.size[0]):
196+
for y in range(mapFinal.size[1]):
197+
#Get color for each pixel
198+
#In EU4 player mapmode screenshots,
199+
#Water: (68, 107, 163)
200+
#AI: (127, 127, 127)
201+
#Wasteland: (94, 94, 94)
202+
color = imgPlayers.getpixel((x, y))
203+
if color == (68, 107, 163) or color == (127, 127, 127) or color == (94, 94, 94):
204+
#print(round(100*x*y/totalPixels, 2), "% Done (", x, ", ", y, ")")
205+
continue
206+
else:
207+
#All pixels on the edge should be water and wasteland so not get past ^ if, although custom games may break this by not being real pixels
208+
#TODO: Make no borders for wasteland
209+
if color != imgPlayers.getpixel((x - 1, y - 1)) or color != imgPlayers.getpixel((x - 1, y)) or color != imgPlayers.getpixel((x - 1, y + 1)) or color != imgPlayers.getpixel((x, y - 1)) or color != imgPlayers.getpixel((x, y + 1)) or color != imgPlayers.getpixel((x + 1, y - 1)) or color != imgPlayers.getpixel((x + 1, y)) or color != imgPlayers.getpixel((x + 1, y + 1)):
210+
#Black for player borders
211+
mapDraw.point((x, y), (255-color[0], 255-color[1], 255-color[2]))
212+
#print(round(100*x*y/totalPixels, 2), "% Done (", x, ", ", y, ")")
213+
print("Map editing done.")
214+
#End Map Creation
215+
#mapFinal.show()
216+
#print("Saving map in 'map.png'...")
217+
#mapFinal.save("map.png", "PNG")
218+
219+
#Start Final Img Creation
220+
print("Copying map into final image...")
221+
imgFinal.paste(mapFinal, (0, imgFinal.size[1]-mapFinal.size[1])) #Copy map into bottom of final image
222+
print("Preparing final image editing...")
223+
#The top has 5632x1119
224+
font = ImageFont.load_default()
225+
fontbig = ImageFont.load_default()
226+
try:
227+
font = ImageFont.truetype("FONT.TTF", 100)
228+
fontbig = ImageFont.truetype("FONT.TTF", 180)
229+
print("Found font. Size:", font.getsize)
230+
except(FileNotFoundError, IOError):
231+
try:
232+
font = ImageFont.truetype("GARA.TTF", 100)
233+
fontbig = ImageFont.truetype("GARA.TTF",180)
234+
print("Found EU4 font.")
235+
except(FileNotFoundError, IOError):
236+
font = ImageFont.load_default()
237+
fontbig = ImageFont.load_default()
238+
print("Could not find font. Using default. Size:", font.getsize)
239+
#Players section from (20,30) to (4710, 1100) half way is x=2345
240+
#So start with yborder = 38, yheight = 128 for each player row. x just make it half or maybe thirds depending on how it goes
241+
imgDraw = ImageDraw.Draw(imgFinal)
242+
for nat in countries:
243+
natnum = countries.index(nat)
244+
x = 38 + 2000*int(natnum/8)
245+
y = 38 + 128*(natnum%8)
246+
if (natnum < 16):
247+
print(nat.tag + " adding")
248+
#x: Country
249+
imgFinal.paste(EU4Lib.flag(nat.tag), (x, y))
250+
#x+128: Player
251+
imgDraw.text((x+128, y), nat.player, (255, 255, 255), font)
252+
#x+760: Army
253+
imgFinal.paste(Image.open("src//army.png"), (x+760, y))
254+
armydisplay = str(round(nat.army/1000, 1))
255+
if armydisplay.endswith(".0") or ("." in armydisplay and len(armydisplay) > 4):
256+
armydisplay = armydisplay.partition(".")[0]
257+
armydisplay = armydisplay + "k"
258+
imgDraw.text((x+760+128, y), armydisplay, (255, 255, 255), font)
259+
#x+1100: Navy
260+
imgFinal.paste(Image.open("src//navy.png"), (x+1100, y))
261+
imgDraw.text((x+1100+128, y), str(nat.navy), (255, 255, 255), font)
262+
#x+1440: Development
263+
imgFinal.paste(Image.open("src//development.png"), (x+1440, y))
264+
imgDraw.text((x+1440+128, y), str(nat.development), (255, 255, 255), font)
265+
#x+1780:
266+
else:
267+
print(nat.tag + " does not fit!")
268+
269+
270+
#Date
271+
imgDraw.text((4800,85), date, (255, 255, 255), fontbig)
272+
273+
274+
print("Final image editing done.")
275+
imgFinal.show()
276+
print("Saving final image...")
277+
imgFinal.save("final.png", "PNG")
278+
#End Final Img Creation
279+
280+
end = input("Done!") #Press enter to end

0 commit comments

Comments
 (0)