Tutorial for MOD installer

@PPQ_Purple so I can finally continue work on the easier to use mod installer, but I ran into a problem. So I know how to make Python read files, but I do not know how to make it read the second line, or third line only of a file! I made some research and it is not as easy as I would have thought.
So I was asking you, do you think it'll still be good if there is a folder called ModInstaller in which a bunch of files are created, 1 for title, 1 for icon, etc etc...?
So the end result of a mod installer will be the mod installer exe, the mod itself with all the assets next to it, and the ModInstaller file with all the files that the mod.exe reads.
 
Can't you just use the readlines and a foreach loop?
Should be something like:
Code:
myfile = open("filename", "r")
myline = myfile.readline()
while myline:
     do stuff with the line of text
    myline = myfile.readline()
myfile.close()
 
Can't you just use the readlines and a foreach loop?
Should be something like:
Code:
myfile = open("filename", "r")
myline = myfile.readline()
while myline:
     do stuff with the line of text
    myline = myfile.readline()
myfile.close()
Yeah I can make it read lines, but I can't make it read a specific line I want.
For example I can't make it read line 5 of a file, only the whole text or if I do file.readlines(5) it will read the first 5 words of it.
 
That's good. The last thing you want is to make your configuration files newline formatting specific. What happens when a careless mod maker adds an extra newline to your file? Or changes it so that the mod name is after instead of before the icon? The sane way to do it is to read each line of the file one at a time, split it by a token and than examine it as an expression.

Take for example the ini file format. You have a bunch of lines each consisting of a left segment a right segment and = in the middle.

Code:
; Modular XML Loading
ModularLoading = 0

SkipMainMenu = 0
NoCustomArt = 0

; Custom XML and Python from user folder are not loaded
NoCustomAssets = 0
; No Custom Scenario option in main menu
NoCustomScenario = 0

; Mod Image file
ImageFile = 0



Name = Generic Mod

; Description of Mod
Description = Generic Mod

The code to go through this is simply:
Code:
foreach(line)
     if( line does not contain ":") skip line
     else
     {
          token = line.split(":").left_side
          value  = line.split(":").right_side

         switch(token)
         {
               do stuff with each possible combination of token and value you want
          }
     }

Rule #1 when creating a parser is that you want to be as forgiving as humanly possible with regard to malformed files and data entry errors.
 
Last edited:
These past couple of days I just spent learning Tkinter even more and I learned some useful stuff, like how to make scrolling bars, canvases, add images, add checkboxes and that type of stuff.
I'm pretty close to finishing the mod installer, just need to add an option for desktop shortcut and make the optional modules actually work because for now they do nothing.
I also found a pretty big problem, the problem is that when you create an exe from a python script (I use pyinstaller) and distribute it most Anti-Virus programs think that it's a Trojan virus and remove it, sometimes google doesn't even let you download it and for me Avast just removes it so I have to go the virus chest and add it back. If you have any idea on how to make it not automatically remove the file saying its a Trojan that would be great! Otherwise it will probably still work but many people who download it might actually think its a Trojan and not trust it.
 
No idea honestly. But your program definitively should not be setting off most AV's. Like, I've had avast go off and scan an exe I made but newer declare it to be a virus. Have you tried googling it or asking on stackoverflow?
 
No idea honestly. But your program definitively should not be setting off most AV's. Like, I've had avast go off and scan an exe I made but newer declare it to be a virus. Have you tried googling it or asking on stackoverflow?
First I tried a scanner which sees how many anti viruses detect it as a virus and 8/68 programs detect it as a virus.
On stackoverflow some people suggesting adding an icon, and some other stuff, I'll try out all of it anyway.
 
Stackoverflow is the library of Alexandria when it comes to programming. Trust it. Use it. Become one with it.
 
That's the spirit. Also in case anyone is wondering I am just too buried with work IRL to work on anything. Haven't even had a chance to make a new model all month.
 
Ok very good news, so the mod installer will be ready today, sorry it took a month but I wasn't working on it and December and January are usually very busy months for me. I managed to finish the optional modules, so you can choose what modules you want. All I have to do now is add some finishing touches to make it look a bit nicer, convert it to an exe, make a thread, post it in the downloads, and everyone can use it!
And I will make a git repository for it so everyone can see the source code.
 
Last edited:
Hm this is very weird... so I converted both files into EXE's but the YourMod.exe which is the mod installer for your mod doesn't work. When I open the exe it just opens a terminal window, stays like that for 3 seconds, and then closes. Not even an error :\.
So for now until I figure out the problem the YourMod.exe will be YourMod.py, so you just have to run the python file instead of the exe file, everything else will work.
 
Unfortunately I have not had any time to work on it. And likely won't have any time in the foreseeable future. This year has seen me have a greater workload than any before it. So if someone else wants to do it be my guest.
 
I have wondered about making an installer once in a while but always had something more important to do. Right now I'm hunting the cause of an OOS bug (I'm progressing. It's apparently unit related). That seems more important to get fixed than looking into making an installer.

Having said that I still plan to make one eventually.
 
Hello I would like to know if a person knows how to make an installation exe file with a multiple choice menu that allows to change the installation folder . I would like to make an installation file for the original game CD and the STEAM version

For the moment, I use the register keys to automatically install the game in the right place

Version CD :
Code:
#define MyAppName "Sid Meier's Civilization 4 - Beyond the Game"
#define MyAppVersion "2.22"
#define MyAppPublisher "Penny & Friends"
#define MyAppURL "https://www.moddb.com/mods/beyond-the-game"


[InstallDelete]
Type: filesandordirs; Name: {reg:HKLM\SOFTWARE\Firaxis Games\Sid Meier's Civilization 4,INSTALLDIR}\Beyond The Game\*
Type: filesandordirs; Name: {reg:HKLM\SOFTWARE\Firaxis Games\Sid Meier's Civilization 4,INSTALLDIR}\PublicMaps\*

[Setup]
AppId={{948BDE4A-45DC-4E98-BEBD-E11998DFA94E}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
UninstallDisplayName={#MyAppName}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={reg:HKLM\SOFTWARE\Firaxis Games\Sid Meier's Civilization 4,INSTALLDIR}\
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes

OutputDir=D:\Bureau\Installer Mod\
OutputBaseFilename=BeyondTheGame - Original Release
SetupIconFile=D:\Bureau\Installer Mod\Fichier du jeu\MOD\BTG.ico
Compression=lzma
SolidCompression=yes
WizardStyle=modern
DirExistsWarning=no
UninstallDisplayIcon={app}\BTG.exe

[Types]
Name: "full"; Description: "Default installation"

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
Name: "basque"; MessagesFile: "compiler:Languages\Basque.isl"
Name: "brazilianportuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
Name: "catalan"; MessagesFile: "compiler:Languages\Catalan.isl"
Name: "czech"; MessagesFile: "compiler:Languages\Czech.isl"
Name: "danish"; MessagesFile: "compiler:Languages\Danish.isl"
Name: "dutch"; MessagesFile: "compiler:Languages\Dutch.isl"
Name: "finnish"; MessagesFile: "compiler:Languages\Finnish.isl"
Name: "french"; MessagesFile: "compiler:Languages\French.isl"
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
Name: "hebrew"; MessagesFile: "compiler:Languages\Hebrew.isl"
Name: "hungarian"; MessagesFile: "compiler:Languages\Hungarian.isl"
Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
Name: "norwegian"; MessagesFile: "compiler:Languages\Norwegian.isl"
Name: "polish"; MessagesFile: "compiler:Languages\Polish.isl"
Name: "portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl"
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
Name: "slovak"; MessagesFile: "compiler:Languages\Slovak.isl"
Name: "slovenian"; MessagesFile: "compiler:Languages\Slovenian.isl"
Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags:

[Files]
Source: "D:\Bureau\Installer Mod\Fichier du jeu\MOD\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs

[Icons]
Name: "{userdesktop}\Beyond The Game - Original Release"; Filename: "{reg:HKLM\SOFTWARE\Firaxis Games\Sid Meier's Civilization 4,INSTALLDIR}\Beyond The Game\BTG.exe"; Tasks: desktopicon; IconFilename: "{app}\BTG.ico"

Version STEAM:
Code:
#define MyAppName "Sid Meier's Civilization IV Beyond the Game"
#define MyAppVersion "2.22"
#define MyAppPublisher "Penny & Friends"
#define MyAppURL "https://www.moddb.com/mods/beyond-the-game"

[InstallDelete]
Type: filesandordirs; Name: {reg:HKLM\SOFTWARE\WOW6432Node\Valve\Steam\,INSTALLPATH}\steamapps\common\Sid Meier's Civilization IV Beyond the Sword\Beyond The Game\*
Type: filesandordirs; Name: {reg:HKLM\SOFTWARE\WOW6432Node\Valve\Steam\,INSTALLPATH}\steamapps\common\Sid Meier's Civilization IV Beyond the Sword\PublicMaps\*

[Setup]
AppId={{7C83C135-5126-491A-9F35-031B5F62481D}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
UninstallDisplayName=Sid Meier's Civilization IV: Beyond the Game
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={reg:HKLM\SOFTWARE\WOW6432Node\Valve\Steam\,INSTALLPATH}\steamapps\common\Sid Meier's Civilization IV Beyond the Sword\
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
OutputDir=D:\Bureau\Installer Mod\
OutputBaseFilename=BeyondTheGame - STEAM
SetupIconFile=D:\Bureau\Installer Mod\Fichier du jeu\MOD\BTG.ico
Compression=lzma
SolidCompression=yes
WizardStyle=modern
DirExistsWarning=no
UninstallDisplayIcon={app}\BTG.exe

[Types]
Name: "full"; Description: "Default installation"

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
Name: "basque"; MessagesFile: "compiler:Languages\Basque.isl"
Name: "brazilianportuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
Name: "catalan"; MessagesFile: "compiler:Languages\Catalan.isl"
Name: "czech"; MessagesFile: "compiler:Languages\Czech.isl"
Name: "danish"; MessagesFile: "compiler:Languages\Danish.isl"
Name: "dutch"; MessagesFile: "compiler:Languages\Dutch.isl"
Name: "finnish"; MessagesFile: "compiler:Languages\Finnish.isl"
Name: "french"; MessagesFile: "compiler:Languages\French.isl"
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
Name: "hebrew"; MessagesFile: "compiler:Languages\Hebrew.isl"
Name: "hungarian"; MessagesFile: "compiler:Languages\Hungarian.isl"
Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
Name: "norwegian"; MessagesFile: "compiler:Languages\Norwegian.isl"
Name: "polish"; MessagesFile: "compiler:Languages\Polish.isl"
Name: "portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl"
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
Name: "slovak"; MessagesFile: "compiler:Languages\Slovak.isl"
Name: "slovenian"; MessagesFile: "compiler:Languages\Slovenian.isl"
Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags:

[Files]
Source: "D:\Bureau\Installer Mod\Fichier du jeu\MOD\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs

[Icons]
Name: "{userdesktop}\Beyond The Game - STEAM version"; Filename: "{reg:HKLM\SOFTWARE\WOW6432Node\Valve\Steam\,INSTALLPATH}\steamapps\common\Sid Meier's Civilization IV Beyond the Sword\Beyond The Game\BTG.exe"; Tasks: desktopicon; IconFilename: "{app}\BTG.ico"

I know you can do this by adding a [ code ] section with PASCAL coding.
Can anyone help me?

Thanks
 
I can't help you with the pascal coding, but I can add the path for the GOG version is:
Code:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\2K Games\Civilization IV Complete\Sid Meier's Civilization 4 - Beyond The Sword
If I get your code right, it means you should check
Code:
DefaultDirName={reg:HKLM\SOFTWARE\WOW6432Node\2K Games\Civilization IV Complete\Sid Meier's Civilization 4 - Beyond The Sword,InstallPath}\
For whatever reason, the field is called InstallPath, not INSTALLDIR.
 
Here's what I use in my Inno setup script to handle both retail and steam, without pascal:
Code:
#define BTSDIR "{reg:HKLM\SOFTWARE\Firaxis Games\Sid Meier's Civilization 4 - Beyond the Sword,INSTALLDIR|{reg:HKLM\SOFTWARE\WOW6432Node\Valve\Steam\,INSTALLPATH}\steamapps\common\Sid Meier's Civilization IV Beyond the Sword\Beyond the Sword}"

...

DefaultDirName={#BTSDIR}\Mods\<your-mod-name>

The "|" tells the installer to look for the the default value specified after it if the registry key does not exist, and it turns out that the "default value" can again be a registry key. I haven't tested it, but the following could make it work for GOG, too, based on Nightinggale's key:
Code:
#define BTSDIR "{reg:HKLM\SOFTWARE\Firaxis Games\Sid Meier's Civilization 4 - Beyond the Sword,INSTALLDIR|{reg:HKLM\SOFTWARE\WOW6432Node\2K Games\Civilization IV Complete\Sid Meier's Civilization 4 - Beyond The Sword,InstallPath|{reg:HKLM\SOFTWARE\WOW6432Node\Valve\Steam\,INSTALLPATH}\steamapps\common\Sid Meier's Civilization IV Beyond the Sword\Beyond the Sword}}"
 
Worst comes to worse you can design the program so that the user can drag a shortcut to civ4 onto it and it reads the path from there. :crazyeye:
 
Back
Top Bottom