Resource icon

C3X: EXE Mod including Bug Fixes, Stack Bombard, and Much More Release 22

Thank you all for your kind words.
1. Forbid to place a city near enemy city, a request from Civinator, makes total sense.
2. Option to limit railroad speed to at least 16 tiles/turn, preferably 12. This is my personal pet peeve. But I remember a lot of people were opting for that as well.
There is just not enough space in the code to replace zeroing of movement points for railroad movement for a quick fix, and going Antal way to implement a workaround through clean space is the only option, but I suck with assembler coding).
I'll look into changing the rules for city placement at some point, maybe even for version 4. Changing railroad movement might be difficult but I can't say for sure without investigating it deeply. What worries me is that there might be some part of the AI logic or pathfinding that assume railroads have infinite movement.

I don't have any problems with space or writing assembler. I've built the mod infrastructure up to the point where I can easily program in C code referring to structs and functions in the base EXE then compile and inject it into the EXE. The injector writes the new code into a new PE section so there's no problem with space. It's all open source, I encourage you to have a look at how it works if you're interested in this sort of thing.
Oh, and I have a list of all changes in EXE for Antal/Scryer patches if anyone needed, attaching a file.
Thanks for posting this. I went ahead and integrated the fix for the pink line in the civilopedia background. Also it's interesting to see that Antal's fix for the science age bug is quite different from mine.
Your work around of the stealth attack problem is sounding very interesting.
Well, unfortunately it didn't work. I was hoping that I could get the top unit on a tile simply by iterating over the tile's units the normal way and picking out the first one but sadly it doesn't work that way. So instead I implemented a more basic fix for this issue, just patching a check for "> 1" into ">= 1". This way you get the stealth attack choice popup even when there's only one option. It's not ideal IMO but it's good enough for now. I did some testing and the AI doesn't seem to have any problems with this.
Is there any possibility of a similar fix for smart-stacking Worker-actions?
I don't see any reason why stack worker actions would be impossible, it's just a matter of the time necessary to program it. Thinking a bit about how this would work, something like stack-railroad-to could be implemented the same way as stack bombard since it's also a mode action. For the normal worker actions, you'd CTRL+click the button to have all the workers in a stack do it, that's definitely easier than adding a bunch of extra buttons and avoids cluttering the UI. Removing the redundant confirmation popups should be easy and I've added it to the list for the next release after the one tomorrow (and hopefully I won't forget).
 
I completely agree with Tsubasanut that instant rail travel is extremely annoying for both players and mod authors. (Dreamily) and you can also suggest inserting one or more intermediate positions between the road and the railway with different travel speeds (for example, a road paved with stone, a road with an asphalt surface, a highway).

Also, in the later stages of the game, it would be, in my opinion, good to get buildings that give additional food or multiply the food produced in the city radius. Cannery, greenhouse, hydroponics, artificial meat production - why not?

However, I suspect that this will not be easy to implement.
 
I don't have any problems with space or writing assembler. I've built the mod infrastructure up to the point where I can easily program in C code referring to structs and functions in the base EXE then compile and inject it into the EXE. The injector writes the new code into a new PE section so there's no problem with space. It's all open source, I encourage you to have a look at how it works if you're interested in this sort of thing.
I definitely will look into your work. I also spend quite a lot of time with Civ3 C code and a reason it was easy to locate the place, where move points got zeroed for railroad - there is not many calls for railroad check function. I can easily now just switch off the railroads, I just can't modify it. I was thinking of just using variable for roads and multiply it by say 4.
So I think I can check if AI is affected by that - create a scenario with railroads and roads, place a worker, place some improvable square or pollution and see if AI will select correct path to it.

Tsubasanut, thank you very much for the No Raze - No Unit Limit - fix of the SGL- and graphical civilopedia issues biq you have created. :thanx:
In the current testgames of the next version of SOE, running with the next version of the CCM2.50 expansion, your biq seems to work very well. In the next version of SOE there is a small town of honour for you on the SOE map (of course at no strategic place in WW 2, so other gamers will not be irritated).

This is too much honor for too little work honestly. I do like the idea, so can you instead name the city after my hometown - Samarkand (it was part of USSR back then)? It is not represented in any Nation and it deserve a place in scenario.
 
C3X Release 3
New in this release:
  • Ability to install mod into the Civ executable
  • Disorder warnings
  • Fix for 'pedia pink line bug. Thanks to Antal for the fix and Tsubasanut for conveying it to me.
  • Stealth attack activates even when there's only one target
Full readme:
Spoiler :

C3X: Executable Mod for Civ 3 Complete
Release 3

INCLUDES (* = new this release):
* Ability to install mod into the Civ executable
* Ability to dynamically change mod settings based on text config file
* Disorder warning
* Fix for 'pedia pink line bug. Thanks to Antal for the fix and Tsubasanut for conveying it to me.
* Stealth attack activates even when there's only one target
Stack bombard
Fix for science age bug
Fix for submarine bug
Option to prevent autoraze and razing by AIs

INSTALLATION AND USAGE:
Begin by extracting the mod and copying its folder into the Civ install directory (that is, the folder containing
Civ3Conquests.exe). Then activate the mod by double-clicking the RUN.bat or INSTALL.bat scripts. RUN.bat will launch Civ 3 then
apply the mod to the program in memory. INSTALL.bat will write the changes into the Civ EXE file permanently.

When installing, the original executable will be copied over to "Civ3Conquests-Unmodded.exe". To uninstall the mod, delete the
modded EXE then rename Civ3Conquests-Unmodded.exe to Civ3Conquests.exe

Mod features can be toggled on or off by editing a text configuration file. It is named "default.c3x_config.ini".

COMPATIBILITY:
The mod is only officially compatible with the GOG and Steam versions of Civ 3 Complete. It may be compatible with other
versions if they use the same executable as one of those two.

STACK BOMBARD:
Activate stack bombard on any unit capable of bombarding by clicking the stack bombard button or by activating normal bombard then
CTRL+clicking the target tile. The selected unit will bombard the tile, then all other units of the same type on the same tile
will automatically bombard the target as well. Stack bombard is pretty smart and will stop bombarding once it can no longer do any
damage, and it knows about lethal bombard, that you can't damage air units in an airfield, etc.

DISORDER WARNING:
If you try to end the turn with unhappy cities, the domestic advisor will pop up to warn you and give you the option to continue
that turn. One minor annoyance is that the game does not recompute city happiness when you sign a deal to import a luxury, so
doing so won't remove the warnings. To make the game recompute city happiness, simply bump the luxury slider back and forth. I
hope to fix this annoyance for the next version.

NO-RAZE:
NoRaze has been re-implemented inside C3X but is not enabled by default. To enable it, edit the config file mentioned above.

HOW IT WORKS:
Some parts of the mod (bug fixes, no-raze) are really just hex edits that are applied to the Civ program code. The real secret
sauce is a system to compile and inject arbitrary C code into the process which makes it practical to implement new features in
the game. The heart of the system is TCC (Tiny C Compiler) and much work puzzling out the functions and structs inside the
executable (and thanks to Antal1987 for figuring out most of the structs years before I came along).

The injected code, along with the rest of the mod, is fully open source. If you're curious how stack bombard was implemented,
check out "patch_Main_Screen_Form_perform_action_on_tile" in "injected_code.c", I assure you the code is quite readable.

MORE INFO, QUESTIONS, COMMENTS:
See my thread on CivFanatics: https://forums.civfanatics.com/threads/sub-bug-fix-and-other-adventures-in-exe-modding.666881/

SPECIAL THANKS to Antal1987 for his work reverse engineering Civ3. See: https://github.com/Antal1987/C3CPatchFramework

Mod is now stored in the CFC downloads area (which I only found out about a few days ago). Here's the link:
https://forums.civfanatics.com/resources/c3x.28759/
 
Magnificent work, it is wonderful. The stacked Bombardment solution is an encouragement for the management of various pieces of artillery and Bombers. I immediately remembered Civ4, a feature that I really like. And now also with Civ3 ... Wow ... now I'm going to finish playing ... I would also like to humbly request the possibility of including the ability to circumvent the maximum limit of units allowed on the map. I did several tests and noticed that when there is no unit limit, AI builds Workers to correct pollution and rebuild terrain improvements (and also change it to frequently build workers). In this post "https://forums.civfanatics.com/threads/city-limits.327919/", which was started by Knuckles even has an exe that breaks this unit limit, along with the city limit. It may be interesting to look at this exe to streamline the study of the implementation of this feature. Thanks again for sharing with us.
 
I immediately remembered Civ4, a feature that I really like. And now also with Civ3 ... Wow ... now I'm going to finish playing ... I would also like to humbly request the possibility of including the ability to circumvent the maximum limit of units allowed on the map.
Yeah, the ultimate form of stack bombard would be basically Civ 4's unit controls. I don't know if I'll ever get that far but it's something I have been thinking about. Every time I right click on a tile and have to scroll past 200 units to get to the one I want, I think, wouldn't it be nice if all these units were icons in a grid? Then the next step from there would be unit multi-selection, etc.

About the unit limit, I've gotten several requests now to remove that so it's something I'll definitely look into.
I think an interesting addition would be getting an Advisor Popup whenever another civilization enters a new era. That way you don't have to look at the leaderhead to know what Era a civ is in.
I'll add this to the list.



Lastly, check out what I've been working on the past few days:
 
Yeah, the ultimate form of stack bombard would be basically Civ 4's unit controls. I don't know if I'll ever get that far but it's something I have been thinking about. Every time I right click on a tile and have to scroll past 200 units to get to the one I want, I think, wouldn't it be nice if all these units were icons in a grid? Then the next step from there would be unit multi-selection, etc.

About the unit limit, I've gotten several requests now to remove that so it's something I'll definitely look into.

I'll add this to the list.



Lastly, check out what I've been working on the past few days:

This City Production info is exactly stuff I've been wanting!
 
I think, wouldn't it be nice if all these units were icons in a grid? Then the next step from there would be unit multi-selection, etc.
When the stack-list goes off the bottom of the screen, if I want to selectively wake some of the fortified/sentried units (e.g. only the vets, or only the elites), what I always find really annoying is that when I shift-click on a unit in the lower part of the list, not only does the list often get partly rearranged, but I also get bounced back up to the top of it, forcing me to scroll back down again.

So from my POV, rather than a grid, a summary of the stack, sorted primarily by unit-type and then combat-experience and/or remaining hit-points (and/or movement-points -- or at least, excluding all units with 0 MP remaining?), would be more helpful — if that would be possible?

i.e. instead of seeing:

Wake Elite Cavalry (5/5)
Wake Veteran Cavalry (4/4)
Wake Elite Cavalry (5/5)
Wake Veteran Cavalry (4/4)
Wake Veteran Cavalry (4/4)
Wake Elite Cavalry (5/5)
Wake Veteran Cavalry (4/4)
Wake Veteran Cavalry (4/4)
Wake Veteran Infantry (4/4)
Wake Elite Infantry (5/5)
Wake Veteran Infantry (4/4)
Wake Elite Infantry (5/5)
Wake Veteran Infantry (4/4)
Wake Veteran Infantry (4/4)
Wake Veteran Infantry (4/4)
...
[20+ other assorted units!]
...
Wake Artillery
Wake Artillery(Foreign)
Wake Artillery
Wake Artillery
Wake Artillery(Foreign)

...we would see

Wake Elite Cavalry (5/5) (x3)
Wake Veteran Cavalry (4/4) (x10)
Wake Regular Cavalry (3/3) (x3)
Wake Elite Infantry (5/5) (x2)
Wake Veteran Infantry (4/4) (x5)
Wake Regular Infantry (3/3) (x3)
...
Wake Artillery (x12)
Wake Artillery(Foreign) (x12)
Lastly, check out what I've been working on the past few days:
That is frankly awesome!

Does it require any editing of the script.txt file, or has that information been inserted de novo?
 
I don't have any problems with space or writing assembler. I've built the mod infrastructure up to the point where I can easily program in C code referring to structs and functions in the base EXE then compile and inject it into the EXE. The injector writes the new code into a new PE section so there's no problem with space. It's all open source, I encourage you to have a look at how it works if you're interested in this sort of thing.
I've checked you code, but my meager knowledge of C and Asm doesn't let me to fully grasp how it works. I will keep trying though.

As for railroad fix.
I edited EXE and canceled the railroad effect, making railroad equal to normal road. Then checked the AI pathfinding. It correctly started treating RR tiles a roads.
This is a proc that is responsible (quote from Antal decompilation)

//----- (0057F0C0) --------------------------------------------------------
int __thiscall class_Trade_Net::f6(class_Trade_Net *this, signed int X, int Y, signed int a4, int a5, class_Unit *Unit, int a7, unsigned int a8, signed int a9, int arg20)

I'm giving both hex locations for 1.21 and 1.22 version of Conquest with "/"
at 17f310/1801B0 you have 33 FF (XOR edi edi), which zero the cost of RR movement. A bit later in the code there is a part, that takes this multiplier and use it with "BIC_Data.General.RoadsMovementRate" to calculate leftover movement point.
So I wonder if a reroute can be made here to get the new multiplier, recalculate movement and then jump to ... somewhere later, need to check IDA for that...
 
I made a first test with the C3X R3 and my GOG Civ 3 Complete installation.

1. The 'run-bat' of C3X R3 didn´t work for me. I received the following error (but this is no problem cause of 2.):

Runerror.jpg



2. After creating a safety copy of the C3C exe, I tested the 'installation bat' of C3X R3 and it worked like charm!

The boosted C3C exe can start a new game without the GOG launcher and even when it is renamed (in my case I renamed it to Civ3Conquests-Flintlock). :bounce:
Flintlock, in my eyes you have done a very clever solution, as everybody who wants to use C3X R3 must have an original C3C exe to install that boost. :hatsoff:

In first tests the stealth attack against a single unit as assigned stealth attack target in a stack worked very well! :woohoo:

Edited: The boosted C3C exe is even working when being transfered to my Civ Chronicles installation of Civ 3 Complete, but it is necessairy, that a copy of the C3X R3 folder is installed in the Civ Chronicles Civ 3 Complete C3C folder, too. I first thought that the transfered boosted exe will not work in that installation until I found out, that the boosted exe alone was not enough and an additional copy of the C3X R3 folder here is needed, too.

3. I had a first look at the configuration INI of C3X R3, so until now I didn´t have the time to test it:

Autorazing.jpg


The INI not only contains the normal no raze patch, but also a function to prevent autorazing if set to true. Does this function stop autorazing of cities (even by the human player) if the culture level of this city is below 10 in standard C3C ?

Flintlock, you have done a phantastic job ! :goodjob:
 
Last edited:
So from my POV, rather than a grid, a summary of the stack, sorted primarily by unit-type and then combat-experience and/or remaining hit-points (and/or movement-points -- or at least, excluding all units with 0 MP remaining?), would be more helpful — if that would be possible?
I don't know how easy it would be to change the contents of the right click menu, I haven't looked into that sort of thing yet. I'll keep your suggestion in mind about grouping units in the menu.
That is frankly awesome!

Does it require any editing of the script.txt file, or has that information been inserted de novo?
Thanks. Adding those details doesn't involve scripts.txt, I just added some extra code to the function that draws the city screen to print that stuff out. However, the disorder warning popups are based on new scripts.txt entries, but the mod doesn't replace the game's scripts.txt, instead it uses its own. That's very convenient and didn't even require any work on my part, the way the engine is designed you can just say show popup with [whatever key] from [whatever file] and it does all the file loading and processing on its own.
I've checked you code, but my meager knowledge of C and Asm doesn't let me to fully grasp how it works. I will keep trying though.
The patching process isn't very complicated. Basically, you can replace a function by compiling another with the same signature then write a jump instruction into the original function pointing to the replacement. That's simple and obvious but the catch is that you destroy the original function in the process. The solution is something I've called "inleads" which are small bits of code that copy the first few instructions from some function then jump to the rest of it. Specifically, they copy the instructions that overlap the first 5 bytes, which is the size of a basic jump instruction. So you create an inlead for a function you want to replace then the replacement can still run the original by calling the inlead. That's the jist of it, there are complications in the fact that when you copy code from one location to another you have to adjust the offsets of any calls (b/c calls in x86 are typically done relative to the instruction pointer). If you have some specific questions, go ahead and ask.
int __thiscall class_Trade_Net::f6(class_Trade_Net *this, signed int X, int Y, signed int a4, int a5, class_Unit *Unit, int a7, unsigned int a8, signed int a9, int arg20)
I had a look at that function. It looks like it calculates the cost to move between neighboring tiles, was that your conclusion too? If so the easiest way to adjust movement would be to replace the function like I describe above then alter its return value based on some additional logic.

BTW, a question to you and anyone else who wants this feature: do you want railroads to act like fast roads or do you want them to provide a certain number of moves independent of a unit's movement points? As I recall that's how it worked in Civ 4 and it makes sense from a realism perspective that a horse and an infantryman riding on a train move at the same speed.
I made a first test with the C3X R3 and my GOG Civ 3 Complete installation.

1. The 'run-bat' of C3X R3 didn´t work for me. I received the following error (but this is no problem cause of 2.):
Neat coincidence that you're just checking out my mod now, I was just checking out CCM a couple of days ago. I don't know why you're getting that error, it looks it originates in ReadProcessMemory, a Windows function. Installing the mod is more reliable since it's fundamentally just writing some stuff to a file unlike hot patching the Civ process in memory which depends on the caprices of Windows.
Edited: The boosted C3C exe is even working when being transfered to my Civ Chronicles installation of Civ 3 Complete, but it is necessairy, that a copy of the C3X R3 folder is installed in the Civ Chronicles Civ 3 Complete C3C folder, too.
Even when the mod is installed it still depends on the config file and the Art and Text folders inside the mod folder. I'll make a note of that in the README (unless I forget).
The INI not only contains the normal no raze patch, but also a function to prevent autorazing if set to true. Does this function stop autorazing of cities (even by the human player) if the culture level of this city is below 10 in standard C3C ?
Yes, the autoraze removal patches the code that checks if a city is eligible to be autorazed to make it so that no city is ever eligible. It works for both the human and AI.
 
BTW, a question to you and anyone else who wants this feature: do you want railroads to act like fast roads or do you want them to provide a certain number of moves independent of a unit's movement points? As I recall that's how it worked in Civ 4 and it makes sense from a realism perspective that a horse and an infantryman riding on a train move at the same speed.

In my eyes the limitation of railroad movement in C3C is urgently needed, especially for historical scenarios. I agree, that a certain number of tiles that can be moved on railroads in a turn is the much better solution. As with a road movement factor of 3, units with 3 MV points should be the normal limit, even on bigger maps, in my eyes a movement restriction on railroads to 12 - 15 tiles in a turn could be a good solution compared to a road movement of 9 tiles (3 x 3) for the fastest units. It would be great, if the number of tiles that can be moved on railroads in a turn could be configurable.

Yes, the autoraze removal patches the code that checks if a city is eligible to be autorazed to make it so that no city is ever eligible. It works for both the human and AI.

This is absolutely great! :)
 
Flintlock... Outstanding Work! :clap:

BTW, a question to you and anyone else who wants this feature: do you want railroads to act like fast roads or do you want them to provide a certain number of moves independent of a unit's movement points? As I recall that's how it worked in Civ 4 and it makes sense from a realism perspective that a horse and an infantryman riding on a train move at the same speed.

For most Units, I agree with Civinator, 12 to 15 tiles a turn, However, it would be excellent to have the ability to set the number of moves independently for each Unit so for example if a Train or Rail Cart is used they could move farther. If possible, a flag to set all units to a specified number of moves as well as having the ability to set each Unit with different numbers of moves.
Now if only we could get the AI to use Land Transports such as Vehicles and Trains :mischief:

Balthasar would have been ecstatic as we were adding a Transcontinental Railroad to the Old West Mod.
 
I figured people would want railroad movement to be independent of the unit's movement points. I agree it makes more sense. I went ahead and implemented what I mentioned in my previous post, patching that function then altering what it returns. After some basic testing, it appears to work. @Tsubasanut or anyone else who wants to follow along at home, the basic patch is really simple. The replacement function is:
Code:
int __fastcall
patch_Trade_Net_get_movement_cost (Trade_Net * this, int edx, int from_x, int from_y, int to_x, int to_y, Unit * unit, int civ_id, unsigned param_7, int neighbor_index, int param_9)
{
    int road_move_rate = 3;
    int railroad_moves = 15;
    p_bic_data->General.RoadsMovementRate = road_move_rate * railroad_moves;
    int base_cost = Trade_Net_get_movement_cost (this, __, from_x, from_y, to_x, to_y, unit, civ_id, param_7, neighbor_index, param_9);
    if ((unit != NULL) && (base_cost == 0))
        return Unit_get_max_move_points (unit) / railroad_moves;
    else if (base_cost == 1)
        return p_bic_data->General.RoadsMovementRate / road_move_rate;
    else
        return base_cost;
}
This must be placed in injected_code.c then to create an inlead and apply the patch, insert the following entry to the array civ_prog_objects in the file with the same name (note this won't work for the Steam version b/c I haven't found the offset yet):
Code:
{OJ_INLEAD, "Trade_Net_get_movement_cost", "int (__fastcall *) (Trade_Net * this, int edx, int from_x, int from_y, int to_x, int to_y, Unit * unit, int civ_id, unsigned param_7, int neighbor_index, int param_9)", 0x57F360, 0x0},
Edit: I realized I never said exactly what this patch does. It limits movement on railroads to 15 tiles for all units.
Edit 2: Already found a bug. This can be called with unit == NULL, need to check for that because Unit_get_max_move_points will crash if it's passed a null pointer.
If possible, a flag to set all units to a specified number of moves as well as having the ability to set each Unit with different numbers of moves.
Now if only we could get the AI to use Land Transports such as Vehicles and Trains :mischief:
Giving some units extra movement along railroads is another complication but not a major one. As for changing the AI's behavior, I don't know, that's another part of the code that I haven't yet looked at. But I'd like to at some point, e.g. to give the AI the courage to take its artillery outside of its cities.
Balthasar would have been ecstatic as we were adding a Transcontinental Railroad to the Old West Mod.
Balthasar. I've never met him but I've only read good things about him. RIP.
 
Last edited:
Flintlock... Really Happy you are looking into many desirable additions/changes we have wanted for years!

Already, you have made many Happy Faces around here :)

I can say if our Forum is looked upon as a Civilization, our population is experiencing "We Love The King" :goodjob:
 
BTW, a question to you and anyone else who wants this feature: do you want railroads to act like fast roads or do you want them to provide a certain number of moves independent of a unit's movement points? As I recall that's how it worked in Civ 4 and it makes sense from a realism perspective that a horse and an infantryman riding on a train move at the same speed.

Maybe, just maybe... if we could just change the number in the ini file? ;) Thank you for your work!
 
I don't know if anybody already mentioned it, but it would be cool to investigate how the AI chooses to build units and if there is a chance to put some kind of ratio to it. For example, if I had 3 WW2 bombers on the same tech, the AI would usually only build the unit with the greatest range - which is pretty lame. It would be interesting if there was some kind of RNG to it, for example if there are multiple unit choices on one tech, the AI could build its preferred unit to - let's say - 75 %, but otherwise would pick one of the other choices. This would enable more diverse armies, as they have been in RL.
 
Back
Top Bottom