Minor Race Advancement Project (old)

Minor Race Advancement; support/discussion/questions

Moderator: thunderchero

User avatar
DCER
Code Master
Code Master
Posts: 683
Joined: Sat Apr 26, 2008 2:00 am

Minor Race Advancement Project (old)

Post by DCER »

I've had some progress in making the minors grow normally.

sub_4528A0 is the routine that decides whether the race makes a jump. The code for deciding number of turns for the next jump is at 452962. The factor is 1/3 (Gowron, you were very colse with you observations) and is stored at 579538.

And routine sub_451F20 increases the population and likely also manages buildings and ships.

These changes will make the race make a jump on every turn, but should increase it's EL only periodically as before:

at 0x51D12:

Code: Select all

change 7D B1 to 7C 6B
at 0x51D27:

Code: Select all

change 7F 9C to 7E 56
at 0x51D5C:

Code: Select all

change 0F 8F 63 FF FF FF to 0F 8F 1D 00 00 00
at 0x1772B8 we need to change the 0.1 growth multiplier to 0.01 in order to slow minor race growth (otherwise with population of 200 you'll have growth of 20 mil * [race growth multiplier]):

Code: Select all

change 9A 99 99 99 99 99 B9 3F to 7B 14 AE 47 E1 7A 84 3F
If the system has low population it'll grow only on every second or third turn.

At 0x5141C

Code: Select all

change 66 8B 94 24 5E 01 00 00 to 66 8B 53 40 90 90 90 90
This will make botf calculate population growth from actual population, not IPN. Otherwise you would only be able to destroy a minor if you'd kill all of their population in one turn since it would always grow back to before and then some. :)

Known issues:

1. Orbitals:

If they can minor races build orbitals every turn. In a few turns I've seen minor having 100+ orbitals.

2. Limitless ship building:

If they can and they have enough population (the limit in the code seems to be 70) minor races build ships every turn. After some turns they had 40+ ships and continued building.
User avatar
DCER
Code Master
Code Master
Posts: 683
Joined: Sat Apr 26, 2008 2:00 am

Post by DCER »

I thought it was increasing. If you put 42 at 0x51420 instead of 90 it will increase population by 1 + whatever value the rest of the calculation gives.

We would need more space for anything more complicated - like testing if the population grew.

To fix ships, we would have to know how to get number of current ships and then cut of sub_4517D0 when max is reached.

EDIT:

It still wasn't working properly. At higher populations the growth started to jump again. In the code there's a loop, looks like it's repeating the calculation for each planet or something (the Ida debugger isn't working on Vista :( ). To normalize it, put 90909090 at 0x5146F
User avatar
Flocke
BORG Trouble Maker
BORG Trouble Maker
Posts: 3197
Joined: Sun Apr 27, 2008 2:00 am
Location: Hamburg, Germany
Contact:

Post by Flocke »

last weekend I got in need to mod the minors a little, I just hated them being that important on low tech.

So I searched the forum a little and found this topic. First I didn't care about the jumping population, but at least wanted to lessen it alot. race.rst did the job, thx Gowron, but still the evolution level seemed to be too high for my preferred difficulty settings. 8)


racetech.tec (reexploration)
-----------------------------
I thought of editing racetech.tec, didn't find much more about it than mentioned in this topic and started analysing it myself. Using UE to adjust all of them currently is a hell of a work and I just didn't realize it being in "Starting Conditions" tab. Cause I havn't found anything about it in the forum, I'll just post what I've figured and already was known. :roll:

A hex view width of 108 clarified the structure and having read about the bandi advancement bug I soon realized that on top of the file are just the addresses of all the contained entries stored. Having read about that already helped me alot! :)

With some analysing it came clear, that major races have 5 EvolutionLevel entries and minors have 10, like mentioned here by DCER as well.
Each entry has a length of 0x6C (=108 in dezimal as used for the view).
Relative to each entry, at position 0x00 comes the RaceID with length of 2bytes. The RaceID starts with value 0x00 and ends with 0x22, for all the 35 races. race.rst lists them in sequence without of the RaceID, but when searching for the corresponding line, race.rst will tell the race's name.

After the RaceID, the tech levels are following. Each research has a length of 8 bytes, the first two of them are for the actual level and the rest I dunno. Interestingly, they only matter for the initial buildings of the races, at least for the minors, cause I havn't tested the majors. I also realized that within my tests all minors initially have cardassian buildings and change them on first upgrade.

Next I searched for setting the succeeding upgrade levels and found out that they are read from the succeeding evolution level entry. They are stored at 0x47, relative to the entry start offset.
They really made me some headaches, cause it just didn't came clear to me how they are stored. I should have taken a look to the source of UE, cause UE already supports setting them. However, now I wonder why I didn't realize that earlier, but they are stored bitwise as flags.
First come the cardassian buildings, then the federation, the ferengi, the klingon and the romulan (obviously when having a look at the entries of these races).
For the buildings of each race there are 10 bits for the farms, 9 for the factories, 9 for the energy buildings, 9 for the intel buildings and 9 for the laboratories. This is causing the weird diagonal regularity and is why there are only letters of 0-8. It's hard to read but with knowing this, it should be comprehensible.
Farms have one flag more than the others, cause farms of type 0 are set with the tenth flag and other buildings just don't have a type 0.

Modifying these flags can cause downgrades as well. Setting more flag than one seems to result in the highest bit flag being recognized, setting just zeros causes no upgrading.

Then, cause this still didn't satisfy me. Especially with not having the mood to modify all these entries by hexeditng as well, I continued studying this thread. But I must say, UE currently doesn't simplify setting the technology achievements by much, for me it seems even more work than hexediting and it's less clear cause of having to scroll that much and the tech levels being accessed through a scroll down tab. sry ;)
I would have prefferred ONE single page for each minor, listing all the EL entries in a table. Maybe two pages, one for the actual technology levels and one for the buildings. And buildings could be summed to just setting the level or disabling them cause a building can't have multiple tech levels at once. The energy buildings could have a third page cause, here setting all races at once seems to be a great future of UE cause you normally wouldn't want to have much differences.
A future to adjust multiple races would be great as well, but it'll be harder to implement this. Maybe by having a race selection scroll window on the left like it's available for the buildings in the building stats, but with multiple selection support. :roll:
Maybe you'll find time to improve it alittle, DCER. :)


asm tools
-----------------------------
I must say IDA free is a great tool, but it doesn't seem to support modifying or writing into the code at all. But I found OllyDbg that is free as well and supports editing the hexvalues as well as the asm code. Great tool, although the debugging crashes or freezes immediately after the intro on my vista laptop. Maybe I would just have to disable an automatic breakpoint, but with a frozen dx fullscreen window I can't get to see the debugger anyway. Havn't tested debugging with IDA, but DCER already mentioned it makes troubles on vista... :(

Anyway I can recommend OllyDbg, although I'm missing an option to save the code changes as well as the hex offsets. But OllyDbg automatically stores all modifications to an udd file, including added comments.
So I'm using OllyDbg for typing new asm commands plus writing comments, use IDA free for getting the hex position (cause every few times I miscalculate with doing it myself), and HxD for actually inserting the new hex values told by OllyDbg. If you have a better solution, please let me know.

So back to the topic. :P


EL prediction (nothing new)
-----------------------------
I totally disliked the EL (evolution level) prediction function sub_451970 and completely removed it. It's only called on initialization at asm 43D26C so I just replaced it with five 'nop's 0x9090909090. The EL prediction value 0x5A2B2B being set by that function is being read at the single position 4530AA asm or 0x524AA hex only anyway. I replaced loading the value [A02B2B5A00] by a xor and some nops [30C0909090] so it always is zero.
There are two other references, writing to 0x5A2B2B. I dunno what they are about, but havn't encountered any issues on testing.

If level seems to be too low, it's still possible to adjust the racetech.tec entries, but remember there are just 10 entries for the minors, so it's great having some more to be used. I wanted to have less important minors anyway and prefer having more upgrade steps.

Of course it should be possible to create a new function for calculating the start EL, but space seems to be a problem, right...


minor evolution (progressed analysing the functiones)
-----------------------------
Not enough, having read this topic I wanted to try continuing where this topic has stopped. I'm not sure if it's a great idea to use this single function for upgrading AND population growth. But, unluckily, placing the growth somewhere else means that the buildings count won't get adjusted. This is whithin the building upgrade code portions. :roll:

However, to split it or fix the issues DCER encountered, first there is need to analyse the code some more. I've spent quite some time on it the last days and found out alot about. Hopefully some helpful stuff, cause I'm currently not about to finish this job.

I began with sub_4528A0 and labled it _updateMinorResearch. It takes the RaceID as argument compares it by 0x20 and splits the code sequence.
For races below 0x20 it loads address 5A2B50 and for races above it loads 5A2B54. It compares bitwise and returns if corresponding flag isn't set, so 0x5A2B50 and 0x5A2B54 must be the MinorPresenceTables. Didn't found anything about in the dyn key variable thread yet. ;)

At 45291A asm I wondered about loading address 5B4330. It is added to the previous loaded DifficultyLevel and compared with the current race EL. If the race's EL is too high, it breaks and returns. Might it be the PlayerEL or something? dunno :?

However, at 45295C last check will take place for evolving. I think DCER already mentioned that some kind of remaining turn value is being used.
So at 4529D9 a function is called to actually evolve and upgrade the system. I labled it _evolveMinorSystem and it's again taking the RaceID as parameter, passing through the eax register.

Within that function, as Spocks-cuddly-tribble told, at 45237B another function gets called to build new ships. But let's go back to the top of this function.

In the beginning, again the presence of the minor get's checked by the MinorPresenceTables already mentioned. This test ends at 451F59. The compiler placed some code for RaceIDs > 0x20 at 452114 but let's ignore this.

After storing the new population number at 45207C asm, which has been figured by DCER, the minor planet terraforming gets adjusted with the function call at 452084. Not calling this function will cause minors increasing population above currently terraformed population capacity within their system!
(btw, DCER, did you figure the population numbers by debugging or was it long testing and a portion of luck? could need a working asm debugger as well :mrgreen: maybe I should try vc++, think it had an asm debugger included as well :roll:)

Now, at 452090 asm, there begins the upgrading part. Here it becomes terrible cause of nested loops and a switch or something. Code that sometimes already get's hard to understand in high level language! :lol:
The first jump, the jge at 4520FD leads to a decision at 452143 that decides at 452157 weather upgrading of buildings is finished and it shall be progressed with ship building or weather the main loop, back at 452090 shall continue with new building type.
The second jump at 45210B instead tries to upgrade something.
It points to 4521B6, being part of a switch or a nested if/else construct.
In between, at 452104, there is a function call that determines the selected building's new tech level. It must be read out of racetech.rst within the called function.

At 4521C6 it decides if it's the right or the wrong type to upgrade and either jumps to the next case or breaks at 4521CA jumping to 452111 which is pointing back to 4520E4 cause there's nothing to upgrade, or calls function 452460 at 4521F7 to upgrade the farms and then going back to 4520E4. Placing nops at the farm upgrading function call causes them not to upgrade but doesn't affect anything else.

So if it hasn't been farms, it continues at 45220D, either jumping to 452241 if it's still the wrong building type or calling 452460 again but this time for upgrading the power plants and then jumping back to 4520E4.

In 452241, comes the research centers, being upgraded at 452279 by the call to function 452460. Interesingly, this time, it doesn't only get reffered to the next building type entry (at 45224A), but also, at 452269, it jumps to 4522BF.

But first to the last switch case 452284. This one is responsible for upgrading the factories by calling 452460 again at4522B4. I think we could call it the upgradeBuildingFunction. that function obviously must take the building type to upgrade as parameter.

Back to the interesting jump to 4522BF. I figured this to be the orbital building portion. At 4522F0 it actually calls function 445DF0 in a loop to build the orbitals. Placing nine nops can prevent this, BUT, that's not the only call to build orbitals! However, it is the main call to build orbitals.
Never would have figured in game that building orbitals is dependent on research facility upgrade for the minors. :roll:

When the building upgrade part is finished, going back to 45216C is another call to build ONE single orbital. Replacing it by nops as well as the looped call, totally prevents minors building additional orbitals!
It gets followed by a jump to 452173. This is the jump out of the main building upgrade loop. It gets us down to 452306, where the MinorPresenceTable get's controlled again. I'm not sure, but would think of it being checked for weather the race is a ship controlling race.

Anyhow, it get's followed by a call, testing for the number of ships to be build or something.
Then, finally, at 45237B the function to build ships gets invoked. It seems like it's taking register dx as parameter that reads in the RaceID that got stored somewhere in beginning. Havn't followed it further.

So that's my observations. I hope someone can use it and either seperate the population growth with adjusting building count or somehow fix the issues DCER encountered. I believe it wouldn't make troubles calling the building upgrading multiple times when moving the orbital upgrading out. It just seems to adjust to the current EL and population.
And depending the build of orbitals on research facility upgrades doesn't make much sense to me anyway.


make turn
-----------------------------
BTW, I noticed some promising ASCII notes within the function responsible for turn progress, that also calls a function for updating research, that is calling the function I've labled _updateMinorResearch which is calling the labled _evolveMinorSystem function we've talked about. I labled it _makeTurn, it's to be found at 458260 and I'm sure you coders know about.
Just am surprised about all the notes like "AIProcessTurn", "LaborProcessTurn", "_turnResolveEconomyPhase", "_turnResolveMilitary", "MonsterProcessTurn", "GameSave", "IncidentReportTurn",...
Not having known about, that's just fantastic to see all these notes within the make turn function! 8O

Oh, *hrm*, well, day over again. :? Tomorrow I must program again, although I really enjoy all this modding stuff. :lol:

cheers :!: 8)

Edit: sry, OllyDbg showed me much empty space where is none. Got trapped by the asm to hex conversion. :roll:
Last edited by Flocke on Fri Jul 17, 2009 7:02 pm, edited 1 time in total.
User avatar
Flocke
BORG Trouble Maker
BORG Trouble Maker
Posts: 3197
Joined: Sun Apr 27, 2008 2:00 am
Location: Hamburg, Germany
Contact:

Post by Flocke »

DCER wrote:It still wasn't working properly. At higher populations the growth started to jump again. In the code there's a loop, looks like it's repeating the calculation for each planet or something (the Ida debugger isn't working on Vista :( ). To normalize it, put 90909090 at 0x5146F
The asm code just doesn't get out of my mind yet and I kept a look again cause I want to test something. In meanwhile I thought about the population calculation again and after having searched for what these floating point instructions are for, I've decrypted it:

int currentTurn = dword ptr [5A2918]; //@asm452006
int population = word ptr [esp+15E]; //@asm45201C (the IPN)
float growth = qword ptr [esp+198]; //@asm452031
for(int turn = 0; //@asm45202B
turn < currentTurn; //@asm45202F, asm452071
turn++ /*@asm45205B*/)
{
float populationGrowth = growth * population; //@asm452057
population += populationGrowth; //@asm452059, asm452061, asm452062
}
dword ptr [ebx+40] = population; //@asm45207C

with knowing this, it's no wonder that in later turns it began to jump again. Loading current population instead of IPN will have an exponential influence on high population, cause this formula loops for each single turn played! :lol:
User avatar
Flocke
BORG Trouble Maker
BORG Trouble Maker
Posts: 3197
Joined: Sun Apr 27, 2008 2:00 am
Location: Hamburg, Germany
Contact:

Post by Flocke »

hm, did I say I'm not about to finish this one? I'm getting close :lol: can't stop :mrgreen:
I've removed the uneccessary race presence check in the _evolveMinorSystem function, changed a little code in the _updateMinorResearch function to add a parameter for the _evolveMinorSystem function if it shall just grow or if it shall make a complete upgrade. Next comes adding some checks for the additional parameter in the _evolveMinorSystem function, so it doesn't build endless ships and orbs!

I believe using a parameter is the best solution in terms of saving space.

When removing another check @asm 451f89 I felt useless cause of checking for majors or something, I experienced a greatful feature!
Removing this check causes minors that are conquered or membered to still keep upgrading and build orbs and ships!! The ships even have been added to the controlling empire *roflmao*
I think that'll be really great in game, having minors still building ships for you. I think I'll keep it, hehe.
User avatar
thunderchero
Site Administrator aka Fleet Admiral
Site  Administrator aka Fleet Admiral
Posts: 7851
Joined: Fri Apr 25, 2008 2:00 am
Location: On a three month training mission, in command of the USS Valiant.

Post by thunderchero »

This all sounds very interesting flocke, can't wait to see complete code for it. I am sure other like gowron will like to see it too :wink:

thunderchero
User avatar
DCER
Code Master
Code Master
Posts: 683
Joined: Sat Apr 26, 2008 2:00 am

Post by DCER »

Flocke wrote: Loading current population instead of IPN will have an exponential influence on high population, cause this formula loops for each single turn played! :lol:
Ah, that explains it :)

The problem with the additional parameter is that minors will build ships and orbitals only in jumps, it would be nicer if it were also in "real time" like pop growth.

Maybe you could set the parameter randomly on each turn for each minor, if it's 0 skip building ships, orbitals and buildings. If it's 1 build a ship and so on. Though I think setting some limit to the number of ships and orbitals would be wise to add, so the minor doesn't end up with to many ships and orbitals. And doing nothing should have a higher percentage than the other options.

EDIT: or don't have the do nothing option and do nothing only if you hit a limit for the thing you're building
User avatar
DCER
Code Master
Code Master
Posts: 683
Joined: Sat Apr 26, 2008 2:00 am

Post by DCER »

Flocke wrote:(btw, DCER, did you figure the population numbers by debugging or was it long testing and a portion of luck? could need a working asm debugger as well :mrgreen: maybe I should try vc++, think it had an asm debugger included as well :roll:)
Yes, with a debugger. Funny thing - this was on linux, where IDA works well enough using wine. But on Vista the debugger won't come in front of botf when execution stops at a break point. I end up with a frozen screen and unable to do anything.
Flocke wrote: When the building upgrade part is finished, going back to 45216C is another call to build ONE single orbital. Replacing it by nops as well as the looped call, totally prevents minors building additional orbitals!
Very interesting :D
User avatar
Flocke
BORG Trouble Maker
BORG Trouble Maker
Posts: 3197
Joined: Sun Apr 27, 2008 2:00 am
Location: Hamburg, Germany
Contact:

Post by Flocke »

DCER wrote:Maybe you could set the parameter randomly
Tell me how! You might have some more experience on this than me, I just made some faults, causing some crashes and damaging my botf installation, partially lost my changes by this and the fact that I had to restart OllyDbg and it didn't save the changes. These asm tools are absolutely not user friendly.
Will have to redo alot and there are still some troubles to solve. :?
Additionally I encountered some issues with executing the upgrades. It seemed to downgrade the farms and build endless of them, quite strange but maybe just a simple fault.

I'll be pleased if you give it a try as well. BTW, is it IDA free you're using? How can I use it to enter/edit asm instructions?
User avatar
Flocke
BORG Trouble Maker
BORG Trouble Maker
Posts: 3197
Joined: Sun Apr 27, 2008 2:00 am
Location: Hamburg, Germany
Contact:

Post by Flocke »

Before I loose my changes again, I'll better begin posting them here.

First change that I've already redone several times by now cause of this buggy OllyDbg (ok, I'm using the new beta, maybe I should have kept 1.1.0 but now it's too late cause I can't export the comments *grrr*) is in the _updateMinorResearch function @asm4528AE to 4528F1 / hex51CAE to 51CF1 replacing:
old wrote:73 1E 89 C1 B8 01 00 00 00 D3 E0 8B 35 50 2B 5A
00 89 C1 21 F1 74 2D 83 C4 0C 5F 5E 5A 59 5B C3
31 C9 66 89 C1 B8 01 00 00 00 83 E9 20 D3 E0 8B
15 54 2B 5A 00 89 C1 21 D1 74 09 83 C4 0C 5F 5E
5A 59 5B C3
with
new wrote:73 08 8B 35 50 2B 5A 00 EB 09 83 E8 20 8B 35 54
2B 5A 00 89 C1 B8 01 00 00 00 D3 E0 21 F0 74 24
E9 0B 01 00 00 E9 06 01 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00
new code wrote:004528AE jnb short 004528B8 ; if(RaceID >= 0x20) jmp
004528B0 esi, dword ptr ds:[MinorPresenceTable]
004528B6 jmp short 004528C1
004528B8 sub eax, 20
004528BB mov esi, dword ptr ds:[MinorPresenceTable2]
004528C1 mov ecx, eax
004528C3 mov eax, 1
004528C8 shl eax, cl
004528CA and eax, esi
004528CC je short 004528F2
004528CE jmp 004529DE
004528D3 jmp 004529DE
and adjusting the three dependent jump calls:
asm452912 hex51D12 wrote:7D B1 by 7D BF
asm452927 hex51D27 wrote:7F 9C by 7F AA
asm45295C hex51D5C wrote:8F 63 FF FF FF by 8F 71 FF FF FF
to get some few space.
The jmp E9 06 01 00 00 @004528D3 now pointed to by these three cases as well as the zeros afterwards can be replaced by code to solve the case of having no EL jump.

This is changing no behavior at all, but space is rare over there. ;)

Edit: sry, but somehow bbcode didn't like my brackets or something...
Last edited by Flocke on Sat Jul 18, 2009 4:08 pm, edited 5 times in total.
User avatar
DCER
Code Master
Code Master
Posts: 683
Joined: Sat Apr 26, 2008 2:00 am

Post by DCER »

Sorry to hear that :(

At 546B4C asm is the rand function. Call that to get a random number to eax, then divide it by the number of options and read the remainder from edx or dx (depends on the div instruction). It's basically % on a random number, but this means all options have the same chance to be selected.

You could also divide it by 100 and then base the value on percentages. If lower than 30 set it to 0 etc...

Ideally we would build either one building, ship or orbital per turn.
Flocke wrote:BTW, is it IDA free you're using? How can I use it to enter/edit asm instructions?
I'm using IDA Pro, don't think it allows editing asm instructions or at least it makes it very difficult to do. I use a hex-editor and add the codes manually.

I'll give OllyDbg a try :)

EDIT: I'll try the changes you posted :)
User avatar
DCER
Code Master
Code Master
Posts: 683
Joined: Sat Apr 26, 2008 2:00 am

Post by DCER »

Ok, after a quick look I saw you have two jumps to the exit.

If you change:

0x51D12 to 7D BA

0x51D27 to 7F A5

0x51D5C to 0F 8F 6C FF FF FF

You can zero out the extra jump at 0x51CD3, giving you another 5 free bytes.

It's not much but could give you another instruction to place there :)

EDIT: fixed jumps 7D and 7F
User avatar
Flocke
BORG Trouble Maker
BORG Trouble Maker
Posts: 3197
Joined: Sun Apr 27, 2008 2:00 am
Location: Hamburg, Germany
Contact:

Post by Flocke »

you code in hex? 8O

well, next change I've made is removing the check for race being in race table in the _evolveMinorSystem function that already has been checked in the _updateMinorResearch function. There's just no need to do it twice cause this function is only a sub call of the otherone.

just place nops(90) from asm451F3C to asm451F5E / hex5133C to hex5135E and zeros(00) from asm452114 to asm452131 / hex51514 to hex51531 (nops: still in use, zeros: never called):
replace by nops wrote:66 3D 20 00 0F 83 CE 01 00 00 89 C1 B8 01 00 00 00 D3 E0 8B 35 50 2B 5A 00 89 C1 21 F1 0F 85 70 04 00 00
replace by zeros wrote:31 C9 66 89 C1 B8 01 00 00 00 83 E9 20 D3 E0 8B 1D 54 2B 5A 00 89 C1 21 D9 E9 27 FE FF FF
P.S.: you may have read over, but the 2nd jump was intended to be replaced lateron ;)
It's the case of having no EL upgrade but normal turn progress, I dunno yet how to solve the issues but just want to share info on where to get some free space. :)

Edit: forgot to mention, the nops are near top and above function starts is still some space that can be used as well. The function entry point and the code before the nops can easily be moved cause they don't include any near distance refernces. Moving the function entry point of course requires adjusting the call in _updateMinorResearch. ^^
User avatar
DCER
Code Master
Code Master
Posts: 683
Joined: Sat Apr 26, 2008 2:00 am

Post by DCER »

Flocke wrote:P.S.: you may have read over, but the 2nd jump was intended to be replaced lateron ;)
It's the case of having no EL upgrade but normal turn progress, I dunno yet how to solve the issues but just want to share info on where to get some free space. :)
Ah, I see :)
User avatar
Flocke
BORG Trouble Maker
BORG Trouble Maker
Posts: 3197
Joined: Sun Apr 27, 2008 2:00 am
Location: Hamburg, Germany
Contact:

Post by Flocke »

I think the troubles I've had come from the population calculation or something dependent. I absolutely don't understand the call to 51D6D4 at 45205C. Changing the population calculation has strange effects on upgrading... :?

Maybe you give it a try again, think I've posted everything important I figured. :roll:
Post Reply

Return to “Minor Race Advancement”