Skip to content

Commit

Permalink
Add seamless Freecam integration
Browse files Browse the repository at this point in the history
  • Loading branch information
EddieEldridge committed Oct 2, 2024
1 parent 0f5d682 commit 2a522ca
Show file tree
Hide file tree
Showing 23 changed files with 1,567 additions and 27 deletions.
2 changes: 1 addition & 1 deletion M2TWEOP Code/M2TWEOP GUI/dataG.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class dataG
// Freecam Integration
string freecamExeName = "Freecam.exe";
bool freecamIntegration = false;
string freecamFolder = "<folder_with_freecam.exe>";
bool freecamStarted = false;

string exeName;
string gameArgs;
Expand Down
32 changes: 20 additions & 12 deletions M2TWEOP Code/M2TWEOP GUI/gameRunnerUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ namespace gameRunnerUI
exit(0);
}
}
// Open Freecam if we are using the integration after waiting a bit for the game to start
std::this_thread::sleep_for(std::chrono::seconds(5));
if (dataG::data.gameData.freecamIntegration == true && dataG::data.gameData.freecamStarted == false)
{
string currentFolder;
string freecamFolder;
string exePath;
helpers::getCurrentPath(currentFolder);

exePath = currentFolder + ".\\eopData\\resources\\tools\\freecam\\Freecam.exe";
freecamFolder = currentFolder + ".\\eopData\\resources\\tools\\freecam";

std::wstring wideFolderPath = helpers::stringToWstring(freecamFolder);
std::wstring wideExePath = helpers::stringToWstring(exePath);

LPSTR lpstr = helpers::ConvertWideStringToLPSTR(wideExePath);
LPSTR lpstr_folder = helpers::ConvertWideStringToLPSTR(wideFolderPath);
helpers::openProcess(lpstr, lpstr_folder);
dataG::data.gameData.freecamStarted = true;
}
}

int drawUI(bool *isOpen)
Expand Down Expand Up @@ -165,18 +185,6 @@ namespace gameRunnerUI
runGameThread, std::ref(startProcess.isRunStarted), std::ref(startProcess.isRunEnded), std::ref(startProcess.isGetResponse), std::ref(startProcess.exePath), std::ref(startProcess.exeArgs), std::ref(startProcess.eopArgs), startProcess.isEopNeeded);
thrUrl.detach();

// Open Freecam if we are using the integration
if (dataG::data.gameData.freecamIntegration == true)
{
std::string exePath = dataG::data.gameData.freecamFolder + "\\Freecam.exe";

std::wstring wideFolderPath = helpers::stringToWstring(dataG::data.gameData.freecamFolder);
std::wstring wideExePath = helpers::stringToWstring(exePath);

LPSTR lpstr = helpers::ConvertWideStringToLPSTR(wideExePath);
LPSTR lpstr_folder = helpers::ConvertWideStringToLPSTR(wideFolderPath);
helpers::openProcess(lpstr, lpstr_folder);
}
// Stop the launcher background music if Rich Presence is enabled and the launcher will stay open
if (dataG::data.gameData.isDiscordRichPresenceEnabled == true && dataG::data.audio.bkgMusic.isMusicNeeded == true)
{
Expand Down
2 changes: 1 addition & 1 deletion M2TWEOP Code/M2TWEOP GUI/mainUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ namespace mainUI
}
return 0;
}
else if (childs.isDiscordUIOpen == true)
else if (childs.isDiscordUIOpen == true || dataG::data.gameData.freecamIntegration == true)
{
gameRunnerUI::maintainGUI();
return 0;
Expand Down
5 changes: 0 additions & 5 deletions M2TWEOP Code/M2TWEOP GUI/managerG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,6 @@ namespace managerG
{
getJson(dataG::data.gameData.freecamIntegration, "isFreecamIntegrationEnabled");
}
if (json.contains("freecamFolder"))
{
getJson(dataG::data.gameData.freecamFolder, "freecamFolder");
}
}
catch (jsn::json::type_error& e)
{
Expand Down Expand Up @@ -238,7 +234,6 @@ namespace managerG
setJson("IsOverrideBattleCamera", dataG::data.gameData.IsOverrideBattleCamera);
setJson("isDiscordRichPresenceEnabled", dataG::data.gameData.isDiscordRichPresenceEnabled);
setJson("isFreecamIntegrationEnabled", dataG::data.gameData.freecamIntegration);
setJson("freecamFolder", dataG::data.gameData.freecamFolder);
writeJsonToFile(fPath, json);
json.clear();

Expand Down
6 changes: 0 additions & 6 deletions M2TWEOP Code/M2TWEOP GUI/modSettingsUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,12 +245,6 @@ namespace modSettingsUI
// Freecam Settings
ImGui::Checkbox("Freecam Integration", &dataG::data.gameData.freecamIntegration);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { ImGui::SetTooltip("Automatically start and close the Freecam application when the game is launched");}

ImGui::Text("Freecam Folder");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { ImGui::SetTooltip("Path to where you have Freecam installed (e.g C:\\Users\\stead\\Documents\\Modding Tools\\Med2 Modding Tools\\Freecam)");}
ImGui::InputText("", &dataG::data.gameData.freecamFolder);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { ImGui::SetTooltip("Path to where you have Freecam installed (e.g C:\\Users\\stead\\Documents\\Modding Tools\\Med2 Modding Tools\\Freecam)");}
ImGui::NewLine();
}

void drawModSettingsUI(bool* isOpen)
Expand Down
1 change: 0 additions & 1 deletion M2TWEOP DataFiles/eopData/config/gameCfg.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"isBlockLaunchWithoutEop": false,
"isDiscordRichPresenceEnabled": false,
"isFreecamIntegrationEnabled": false,
"freecamFolder": "",
"isDeveloperModeNeeded": true,
"isTacticalMapViewerNeeded": true,
"isContextMenuNeeded": true,
Expand Down
Binary file not shown.
119 changes: 119 additions & 0 deletions M2TWEOP DataFiles/eopData/resources/tools/freecam/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@

FREECAM -Bugis_Duckis
This version of FREECAM most likely not perfect and weirdness may happen! I have included the source code for anyone who wants it. It's probably
not very good, but I'll add that I'm not very accustomed to C++. Use it as you wish, no need to credit!


What does this program actually do?
Freecam is for all intents and purposes a hack. It essentially hijacks game variables and writes its own values to them. With version 1.0 it
even edits the machine code of medieval 2 in real-time to stop jitteryness and make the program less CPU demanding. Due to the hacky nature
of the program, IT IS IMPORTANT THAT YOU ONLY RUN THIS FOR THE CORRECT VERSION OF THE GAME, or else it will crash. Have fun!


REQUIREMENTS:
Windows 10/11 64bit, other versions of windows have not been tested.
Medieval 2 total war (Definitive edition V1.5.2.0/1.52), as for now gold edition has not been tested.
Microsoft Visual c++ 2022.


How to use?
step 1: launch the game.
step 2: Make sure you use "total war" camera style ingame.
step 3: Go into conf.txt and make sure that the controls match those ingame.
step 4: tab out of the game and start Freecam.exe.
step 5: tab into the game and enjoy!

Recommendations:
Turn off restrict camera.
Unbind alt-s in the ingame settings (It mutes sound). You can do this by binding alt-s to a useless bind such as getting rid of advisor.

Notes:
If you want to turn off freecam, then it is very important that you do so through the exit bind (END by default) and not the X button
in the corner. Else camera will be frozen in place until you restart the game!
You do not need to place the executable in any specific place or mod folder, it can be run from anywhere!
If you momentarily want vanilla controls, freecam can be paused with the the pause key (INSERT by default)
Save often, crashing though rare may occur.


Questions:
Where should i place the program? Anywhere you want! It doesn't not be in any place or modfolder, just make sure that it's next to the files it comes with!
Does this work with the DLC:s? Yes!
Does this work with mods? Yes!
Does this work on multiplayer? Yes!
Does this work with any other total war games? No!
Can I use the code to develop my own projects/fix this one? Absolutely!


Known Issues:
Camera going below game when double clicking on units, causing the game to freeze.
There is a small chance of crashing currently (As for now it has only occurred when tabbing).


Troubleshooting:
General Issues.
Try starting freecam as administrator.


-----------------------------------------------------------------------------------------------------------
Changelog:
1.2.2:
Additions:
Added an option for controlling the delay when the program gives or releases control of the camera.
1.2.1:
Fixes:
Fixed an error with the config file. Where the program would mix up the binds for rotate_up and up.

Changes:
Changed the name of the FORWARD, BACKWARD, etc... to MOVE_FORWARD, MOVE_BACKWARD, etc...

1.2:
Fixes:
VERTICAL_SPEED now functions properly.
Fixed a typo in the code that stopped ROTATION_CONTROLS from working.

Additions:
Added UPS, allows you to set how many updates per second the program will be running at. for users with 60fps+ monitors. You will need to
tweak the variables in config.txt. As UPS simply changes how fast the program will run, camera will therefor appear to be twice as fast if you set it to 120 rather than the default 60 as an example.
Added an Icon for the executable.

1.1:
Fixes:
Fixed inconsitency in speed when pressing forward and touching the top of the screen.
Fixed EDGEPAN_SPEED so it has similar speeds as camera sensitivity.

Changes:
Higher sensitivty values now actually makes the camera more sensitive rather than less.

Additions:
Added OVERRIDE_MOVEMENT, which makes the movement and scrolling controls provided by freecam optional.
Added untested Gold Edition addresses. I have no way to test these as I dont own gold edition, only use
on custom battles until it has been confirmed that they infact do work. You might otherwise risk
losing progress on your save due to crashes.
Added keybinds for rotating camera.


1.0:
Due to this version being completely seperate, earlier versions will not be included in this changelog as to avoid missinformation.
Due to reports of instability from many users, I have decided to rewrite the entire project. While the general idea remains the same,
some new features have been added to greatly improve stability and decrease CPU usage. The biggest of which is the fact that the
program now will delete lines of machine-code straight from the games process memory while it's running, which stops the game
from writing data to the camera position variables. In earlier versions, the program was essentially having a battle to death over
control of the variables, and for some systems the game was winning that battle. In this version the games hands got chopped off.
This only happens in RAM memory so you don't need to worry about game files, however the game might crash if you're running an
incompatible version of the game.

Hopefully this version will run better! Sadly I cant make this work for gold edition as I dont own that version, if someone manages
to translate all of the addresses to gold edition then I'll be greatful! Otherwise I'll try to come with some solution in the future.

Additions:
- Greatly improved stability.
- Decreased CPU usage.
- Smoother camera movements.
- More user friendly config file.
- Custom memory addresses.
- Pausing.

Not included:
- Control of camera orientation with keyboard (Kinda defeats the point of having freecam).
- Gold Edition support, I will try do something for this in the future.
- Some configuration regarding camera speed. This can be readded if people want it.
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Just put all the assembly memory addresses that write to camera coords in here, so that the program can remove them.

#Definitive Edition addresses
#CAMERA_X
0x008F8E10 #Tabbing
0x008F8B50 #Cutscene
0x00E7EF6A #Cutscene2
0x0094FCDC #Constant / restrictor
0x008FAC69 #restrictor
0x008F8C6C #Movement
0x008F9439 #Movement2
0x0095B40E #Map click pan
0x0095B7F4 #Unit pan
0x008F8E8B #Unit zoom
0x008F6F29 #???
0x0095B3B0 #???
0x0094E996 #???
0x008F9050 #???

#CAMERA_Y
0x008F8E1C #Tabbing
0x008F8B5C #Cutscene
0x00E7EF7F #Cutscene2
0x0094FCE5 #Constant / restrictor
0x008FAC72 #restrictor
0x008F8C76 #Movement
0x008F9443 #Movement2
0x0095B429 #Map click pan
0x0095B805 #Unit pan
0x008F8E97 #Unit zoom
0x008F6F39 #???
0x0095B3BB #???
0x0094E9DF #???
0x008F905A #???

#CAMERA_Z
0x008F8E16 #Tabbing
0x008F8B56 #Cutscene
0x00E7EF74 #Cutscene2
0x0094FCE0 #Constant / restrictor RTS
0x0094FD2D #Constant / restrictor2 RTS
0x008FAC6D #restrictor TWC
0x008F8C71 #Movement TWC
0x008F943E #Movement2 TWC
0x0095B41B #Map click pan
0x0095B499 #Map click pan2
0x0095B7FC #Unit pan
0x008F8E91 #Unit zoom
0x008F6F2F #???
0x0095B3B5 #???
0x008F9011 #???

# Gold Edition addresses (These have not been tested, they might cause the game to crash!)
# Use a simple regex replace to quickly use these, replace "#0x" with "0x", make sure to remove or comment the previous defintive edition addresses!
#CAMERA_X
#0x00941f60
#0x00941ca0
#0x00ec80ba
#0x00998e2c
#0x00943db9
#0x00941dbc
#0x00942589
#0x009a455e
#0x009a4944
#0x00941fdb
#0x00940079
#0x009a4500
#0x00997ae6
#0x009421a0

#CAMERA_Y
#0x00941f6c
#0x00941cac
#0x00ec80cf
#0x00998e35
#0x00943dc2
#0x00941dc6
#0x00942593
#0x009a4579
#0x009a4955
#0x00941fe7
#0x00940089
#0x009a450b
#0x00997b2f
#0x009421aa

#CAMERA_Z
#0x00941f66
#0x00941ca6
#0x00ec80c4
#0x00998e30
#0x00998e7d
#0x00943dbd
#0x00941dc1
#0x0094258e
#0x009a456b
#0x009a45e9
#0x009a494c
#0x00941fe1
#0x0094007f
#0x009a4505
#0x00942161
Loading

0 comments on commit 2a522ca

Please sign in to comment.