(1) Calculate the combined ground combat strengths of the attacking task force and multiply by the race-specific ground combat factor. Square the result.
(2) Multiply the result of (1) by the empire-wide bonus factor of the attacking empire.
(3) Calculate the ground defense value of the defending star system, including all bonuses. Square the result.
(4) Add the results of (2) and (3).
(5) Divide the result of (2) by the result of (4).
The result of (5) is then compared to a randomly generated value between 0 and 1. This comparison decides if the invasion succeeds.
So the success probability depends on the ratio of the squares of the ground combat values (of attackers and defenders), with the squared ground combat strength of the attackers being multiplied by their empire-wide bonus factor (if present).
It is a little bit odd that the empire-wide bonus of the attackers is included in the calculation although it does not affect the (displayed) ground combat values of troop transports.
--------------------------------------------------
link to ground combat strength explanation:
viewtopic.php?name=Forums&file=viewtopic&t=56
link to ground combat tech level multiplier topic:
viewtopic.php?name=Forums&file=viewtopic&t=67
--------------------------------------------------
The corresponding assembler code is part of subroutine 466CF0. Although that subroutine is quite huge, I think I've identified most of the relevant code sections for ground combat calculation.
Surprisingly there does not seem to be a loop over the attacking task forces (if more than one task force attacks). It seems that they are processed one by one.
Although it's quite obvious that var_10C contains the race-specific ground combat factor for the attacking task force, I've still added question marks for this variable because it does not seem to be assigned within subroutine 466CF0.
Code: Select all
AUTO:0046706E mov eax, [esp+420h+var_20] ; data offset for attacking task force
AUTO:00467075 xor ecx, ecx
AUTO:00467077 mov ebx, [eax+4] ; ship count of attacking task force
AUTO:0046707A mov [esp+420h+var_18], ecx ; 0
AUTO:00467081 test ebx, ebx
AUTO:00467083 jle short loc_4670EB ; jump if attacking task force is empty
AUTO:00467085 mov ebx, eax ; data offset for attacking task force
AUTO:00467087
AUTO:00467087 mov eax, [ebx+6] ; start of loop over ships in attacking task force
AUTO:0046708A sar eax, 10h ; ship ID
AUTO:0046708D call sub_44A690 ; get data offset for current ship
AUTO:00467092 mov dl, [eax+58h]
AUTO:00467095 and dl, 0FEh
AUTO:00467098 mov esi, [eax+70h] ; base ground combat strength (= production value if TT) of current ship
AUTO:0046709B mov [eax+58h], dl
AUTO:0046709E test esi, esi
AUTO:004670A0 jbe loc_467449 ; jump if base ground combat strength is zero (not a TT)
AUTO:004670A6 xor ecx, ecx
AUTO:004670A8 mov dword ptr [esp+420h+var_B0], esi ; base ground combat strength of current ship
AUTO:004670AF mov dword ptr [esp+420h+var_B0+4], ecx ; 0
AUTO:004670B6 fild [esp+420h+var_B0] ; base ground combat strength of current ship
AUTO:004670BD fadd [esp+420h+var_100] ; add to base ground combat strength of task force
AUTO:004670C4 fstp [esp+420h+var_100] ; combined base ground combat strength of task force
AUTO:004670CB mov esi, [esp+420h+var_18] ; loop counter
AUTO:004670D2 mov edx, [esp+420h+var_20] ; data offset for attacking task force
AUTO:004670D9 add ebx, 4 ; increase data offset to get next ship
AUTO:004670DC inc esi ; loop counter
AUTO:004670DD mov edi, [edx+4] ; ship count of attacking task force
AUTO:004670E0 mov [esp+420h+var_18], esi ; loop counter
AUTO:004670E7 cmp esi, edi
AUTO:004670E9 jl short loc_467087 ; loop over ships of attacking task force
-------------
AUTO:00467562 mov edx, [esp+420h+var_28] ; data offset for defending system
AUTO:00467569 xor ah, ah
AUTO:0046756B mov al, [edx+4Ch] ; empire which controls defending system
AUTO:0046756E jmp loc_467289
-------------
AUTO:00467270 mov eax, [esp+420h+var_28] ; ID of defending system
AUTO:00467277 mov dh, [eax+4Ch] ; owner of defending system
AUTO:0046727A xor ebx, ebx
AUTO:0046727C cmp dh, 5 ; check if defending system belongs to a major empire
AUTO:0046727F jb loc_467562 ; use controlling race instead of inhabitant race if system belongs to an empire
AUTO:00467285 mov ax, [eax+44h] ; inhabitant race of defending system
AUTO:00467289 mov word ptr [esp+420h+var_8], ax ; defending race ID (empire resp. inhabitants)
AUTO:00467291 mov eax, [esp+420h+var_20] ; data offset for attacking task force
AUTO:00467298 mov cx, [eax+34h] ; race ID of attacking task force
AUTO:0046729C cmp cx, 5
AUTO:004672A0 jnb short loc_4672D4 ; jump if not a major empire
AUTO:004672A2 xor edx, edx
AUTO:004672A4 mov dx, cx
AUTO:004672A7 lea eax, ds:0[edx*8]
AUTO:004672AE add eax, edx
AUTO:004672B0 shl eax, 2
AUTO:004672B3 add eax, edx
AUTO:004672B5 shl eax, 2
AUTO:004672B8 mov edx, eax
AUTO:004672BA shl eax, 2
AUTO:004672BD sub eax, edx ; eax = 444 * (ID of attacking empire)
AUTO:004672BF add eax, offset st_empsInfo ; data offset for attacking empire
AUTO:004672C4 lea ebx, [eax+0F6h]
AUTO:004672CA mov bx, [ebx+18h] ; empire-wide ground combat bonus factor in percent
AUTO:004672CE and ebx, 0FFFFh
AUTO:004672D4 mov eax, [esp+420h+var_20] ; data offset for attacking task force
AUTO:004672DB xor ecx, ecx
AUTO:004672DD mov ax, [eax+34h] ; race ID of attacking task force
AUTO:004672E1 mov cx, ax ; race ID of attacking task force
AUTO:004672E4 lea esi, [esp+420h+var_174]
AUTO:004672EB mov eax, ecx ; race ID of attacking task force
AUTO:004672ED mov edx, 5 ; tech area "weapons"
AUTO:004672F2 call sub_4AED50
AUTO:004672F7 mov eax, ecx ; race ID of attacking task force
AUTO:004672F9 call GetTechLevel ; write weapon tech level of attackers to eax
AUTO:004672FE mov [esp+420h+var_10], eax ; weapon tech level of attackers
AUTO:00467305 fild [esp+420h+var_10] ; weapon tech level of attackers
AUTO:0046730C fmul ds:GrndCmbTechMul2 ; 0.1 (tech level bonus factor for attackers)
AUTO:00467312 fld1
AUTO:00467314 faddp st(1), st ; tech bonus = 1 + factor * (weapon tech level)
AUTO:00467316 fmul [esp+420h+var_10C] ; multiply by race-specific combat factor for attackers?
AUTO:0046731D fmul [esp+420h+var_100] ; multiply by combined base ground combat strength of attacking task force
AUTO:00467324 add ebx, 64h ; add 100 to empire-wide combat bonus
AUTO:00467327 fst [esp+420h+var_100] ; store result of multiplication
AUTO:0046732E fmul [esp+420h+var_100] ; square the above result
AUTO:00467335 mov [esp+420h+var_10], ebx ; 100 * (ground combat factor from empire-wide bonus) for attackers
AUTO:0046733C fstp [esp+420h+var_100]
AUTO:00467343 fild [esp+420h+var_10]
AUTO:0046734A fmul [esp+420h+var_100] ; apply empire-wide ground combat factor (not squared)
AUTO:00467351 mov eax, [esp+420h+var_28] ; ID of defending system
AUTO:00467358 fmul ds:dbl_57AC6C ; 0.01
AUTO:0046735E movsx eax, word ptr [eax] ; ID of defending system
AUTO:00467361 fstp [esp+420h+var_100]
AUTO:00467368 call GrndDefStrength ; get ground defense strength of defending system
AUTO:0046736D mov [esp+420h+var_10], eax ; ground defense strength of defending system
AUTO:00467374 fild [esp+420h+var_10] ; ground defense strength of defending system
AUTO:0046737B fmul st, st ; square ground defense strength of defending system
AUTO:0046737D fadd [esp+420h+var_100] ; calculate...
AUTO:00467384 fdivr [esp+420h+var_100] ; ... success chance of invasion
AUTO:0046738B mov edx, 1041h
AUTO:00467390 mov eax, offset a____SourceG_14 ; "..\\..\\source\\game\\military\\military.c"
AUTO:00467395 fstp [esp+420h+var_60] ; success chance of invasion
AUTO:0046739C call random2 ; loads a random value between 0 and 1 into the FPU
AUTO:004673A1 fld [esp+420h+var_60] ; success chance of invasion
AUTO:004673A8 fstp [esp+420h+var_C0] ; success chance of invasion
AUTO:004673AF fcomp [esp+420h+var_C0] ; check if invasion is successful (compare random value to success chance)
AUTO:004673B6 fnstsw ax
AUTO:004673B8 sahf
AUTO:004673B9 jnb loc_467573 ; jump if invasion is not successful