Repairing Units drains ManPower

PC/MAC : Commander the Great War is the latest release in the popular Commander series to bring the thrill, excitement and mind-breaking decision making of these difficult times to life.

Moderators: Slitherine Core, The Lordz

Post Reply
Historion
Corporal - 5 cm Pak 38
Corporal - 5 cm Pak 38
Posts: 31
Joined: Wed Jul 30, 2014 10:41 pm

Repairing Units drains ManPower

Post by Historion »

Everybody playing through a complete campaign probably has noticed the massive drain to ManPower (MP) reserves as the game advances. Building new units costs MP but it costs a lot more MP to keep units in the field by repairing them.

The function to calculate RepairCosts is located in file "game_repair.lua".

Code: Select all

gameplay.repairDiscountFactor = 0.7

function GetRepairCost(unit)

  local pointsRepaired= GetRepairPoints(unit)

  local PPcost = math.ceil(unit.prototype.costPP * (pointsRepaired) / 100 * gameplay.repairDiscountFactor)
  local MPcost = math.ceil(unit.prototype.costMP * (pointsRepaired) / 100)

  -- Repairing half supply doubles cost
  if unit.supply == 1 then
    PPcost = PPcost * 2
    MPcost = MPcost * 2
  end

  return PPcost, MPcost
end
(Note :
The game internally uses 100 hitpoints (hp) instead of the displayed 10 strength points for unit health. Repairing is done in steps of +10 hp / +20 hp respectively +1 / +2 Strength Points. GetRepairPoints(unit) returns hitpoints in range of 0..20.)

The problem is that MP costs for new units are rather small values between 1 MP and 12 MP so that effectively dividing by 10 (or more) and rounding up (ceil) has a very strong effect.

Code: Select all

Repairing from Strength 9 to 10 :

MP-cost of unit :                 unit                        : MP / 10 : Repair-Cost : Ratio (Repair-Cost / (MP/10))
----------------------------------------------------------------------------------------------------------------------------
01              : Armoured Car, Submarine                     : 0.1     : 1 MP        : 10
02              : Railroad Gun, Fighter, Airship, Cruiser     : 0.2     : 1 MP        :  5
03              : Armoured Train, Bomber                      : 0.3     : 1 MP        :  3.33
04              : Battleship                                  : 0.4     : 1 MP        :  2.5
05              : Artillery                                   : 0.5     : 1 MP        :  2
06              : Garrison, Cavalry                           : 0.6     : 1 MP        :  1.67
10              : Armour (Tank)                               : 1.0     : 1 MP        :  1
12              : Infantry                                    : 1.2     : 2 MP        :  1.67
Repairing an Armoured Car / Submarine by 1 Strength Point costs 1 MP, which is the same MP cost as for a complete new unit with 10 Strength Points. Repair costs (MP) for these units are 10 times higher than expected.

If you repair at half supply, the Repair-costs (after rounding up) are even doubled, so that repairing an Armoured Car by 1 Strength Point costs 2 MP while you get a new one for 1 MP.

If the high MP repair costs are not intended as a challenge / handicap (to increase game difficulty), an easy solution would be simply to scale MP unit costs and faction MP, MPmax by 10 or to skip the rounding and use MP as float rather than integer. (The displayed MP reserve should then be rounded to integer.)
PrinceMiskin
Lance Corporal - SdKfz 222
Lance Corporal - SdKfz 222
Posts: 21
Joined: Fri Aug 03, 2007 6:05 pm

Re: Repairing Units drains ManPower

Post by PrinceMiskin »

Hi historion,

Accidentally I have made a similar post on steam, but from a different point of view, which I attach. You can also use this to your advantage to gain manpower. Honestly, manpower needs to start working with digits; integer makes no sense.

"When dismantling units in home territory, or home port you gain back a significant manpower and half of the production points. Theoretically one could build a unit, only to disband it and build a new one to increase manpower (MP).

One could argue that it may sound odd, or not designed properly, or can be seen as an exploit. Anyway, since it's in the game mechanics, let's try to see how it works.

The following table shows the efficiency of disbanding in terms of MP/PP and MP/PP/turn.

Code: Select all

			                         Build Cost      Scrap Gain        Net          Efficiency	
		           Build Time |   PP   MP   |   PP   MP   |   PP   MP   |   MP/PP   MP/PP/turn
------------------------------------------------------------------------------------
Garrison              2	10	6	5	10	-5	4	0.80	0.40
Infantry              4	20	12	10	20	-10	8	0.80	0.20
Cavarly               5	20	6	10	20	-10	14	1.40	0.28
Artillery             7	50	5	25	50	-25	45	1.80	0.26
Armoured Car          3	8	1	4	8	-4	7	1.75	0.58
Armoured Train        7	35	3	8	17	-27	14	0.52	0.07
Armor                 9	60	10	30	60	-30	50	1.67	0.19
Fighter               7	30	2	15	30	-15	28	1.87	0.27
Airship               4	30	2	15	30	-15	28	1.87	0.47
Bomber                8	50	3	25	50	-25	47	1.88	0.24
Submarine             4	22	1	11	22	-11	21	1.91	0.48
Cruiser		         12 50	2	25	50	-25	48	1.92	0.16
Battleship*		     26 124	4	62	124	-62	120	1.94	0.07
*= Dismantling also comes with significant loss of National Morale (NM).

The matrix shows that the most efficient unit to gain manpower is the cruiser -in fact it is the battleship, but it also comes with a signifcant drop in NM, hence it's not an option.

The most efficient unit to dismantle in terms of production points and production time is the armored car, since you gain 0.58 per PP per turn of build time.

Overall one of the most cost effective units to disband is the submarine, which combines both MP/MPP and MP/MPP/turn efficiency.

I hope this guide helps you handle shortages in MP better."
Historion
Corporal - 5 cm Pak 38
Corporal - 5 cm Pak 38
Posts: 31
Joined: Wed Jul 30, 2014 10:41 pm

Re: Repairing Units drains ManPower

Post by Historion »

Gaining additional ManPower from building and disbanding units is exploiting a well known bug which should have been fixed for a long time ...

It looks like a simple copy and paste bug where the developer just forgot to change the unit.prototype.costPP to unit.prototype.costMP in those 3 lines where MPrefund is calculated, e.g. :

Code: Select all

 MPrefund = math.floor(unit.prototype.costPP * unit.hp * 100 / 10000)
It takes only a moment to fix it ... and I expect/hope it to be fixed with the new patch ...

see game_deployment.lua

code with bug :

Code: Select all

function GetDisbandRefund(unit)
  local PPrefund
  local MPrefund
  if unit.type  ~= Unit.NAVAL then
    if unit.hex.originalFaction.alliance.id == unit.faction.alliance.id then
      if unit.hex.originalFaction.id == unit.faction.id then
        PPrefund = math.floor(unit.prototype.costPP * unit.hp * 50 / 10000)
      else
        PPrefund = math.floor(unit.prototype.costPP * unit.hp * 25 / 10000)
      end
    else
      PPrefund = 0
    end
    if unit.hex.originalFaction.alliance.id == unit.faction.alliance.id then
      if unit.hex.originalFaction.id == unit.faction.id then
        MPrefund = math.floor(unit.prototype.costPP * unit.hp * 100 / 10000)
      else
        MPrefund = math.floor(unit.prototype.costPP * unit.hp * 50 / 10000)
      end
    else
      MPrefund = 0
    end
  else
    PPrefund = math.floor(unit.prototype.costPP * unit.hp * 50 / 10000)
    MPrefund = math.floor(unit.prototype.costPP * unit.hp * 100 / 10000)
  end
  return PPrefund, MPrefund
end
fixed code :

Code: Select all

function GetDisbandRefund(unit)
  local PPrefund
  local MPrefund
  if unit.type  ~= Unit.NAVAL then
    if unit.hex.originalFaction.alliance.id == unit.faction.alliance.id then
      if unit.hex.originalFaction.id == unit.faction.id then
        PPrefund = math.floor(unit.prototype.costPP * unit.hp * 50 / 10000)
      else
        PPrefund = math.floor(unit.prototype.costPP * unit.hp * 25 / 10000)
      end
    else
      PPrefund = 0
    end
    if unit.hex.originalFaction.alliance.id == unit.faction.alliance.id then
      if unit.hex.originalFaction.id == unit.faction.id then
        MPrefund = math.floor(unit.prototype.costMP * unit.hp * 100 / 10000)
      else
        MPrefund = math.floor(unit.prototype.costMP * unit.hp * 50 / 10000)
      end
    else
      MPrefund = 0
    end
  else
    PPrefund = math.floor(unit.prototype.costPP * unit.hp * 50 / 10000)
    MPrefund = math.floor(unit.prototype.costMP * unit.hp * 100 / 10000)
  end
  return PPrefund, MPrefund
end
PrinceMiskin
Lance Corporal - SdKfz 222
Lance Corporal - SdKfz 222
Posts: 21
Joined: Fri Aug 03, 2007 6:05 pm

Re: Repairing Units drains ManPower

Post by PrinceMiskin »

Did you read my mind?

I have also changed:

Code: Select all

 MPrefund = math.floor(unit.prototype.costPP * unit.hp * 100 / 10000)
to:

Code: Select all

 MPrefund = math.floor(unit.prototype.costMP * unit.hp * 100 / 10000)
I have also rescaled all MP costs, and now works like a charm!
PrinceMiskin
Lance Corporal - SdKfz 222
Lance Corporal - SdKfz 222
Posts: 21
Joined: Fri Aug 03, 2007 6:05 pm

Re: Repairing Units drains ManPower

Post by PrinceMiskin »

If we rescale MP by a factor of 10, we should also update the "convoy.lua" file, so allied MP from convoys gets count correctly.

Code: Select all

  -- Manage existing convoys
  gameplay.convoys = {}
  for faction in alliance.factions do
    for unit in faction.units do
      if unit.alive and unit.prototype.name == "convoy" then
        -- If convoy is in national port
        local arrived = false
        local hexes = game.map:GetHexesInRange(unit.hex, 1)
        for _, hex in pairs(hexes) do
          if hex.construction ~= nil and hex.construction.isPort and hex.construction.city.hex.faction.id == faction.id and hex.construction.city.hex.originalFaction.id == faction.id and hex.y < 45 then
            arrived = true
            if alliance.id == playerAlliance.id then
              --PopupInfoDialog("convoy_finished", unit.hex.x, unit.hex.y)
              ui.resourcesPanel:Refresh()
            end
            faction:ConsumeProductionPoints(-unit.hp)
            faction:ConsumeManpower(-unit.hp / 10)
            unit:Kill()
            break
          end
        end
        if not arrived then
          -- Move convoy automatically
          -- For player only! AI should do the same in AI scripts
          if alliance.id == playerAlliance.id then
            table.insert(gameplay.convoys, unit)
          end
        end
      end
    end
  end
Specifically the line:

Code: Select all

faction:ConsumeManpower(-unit.hp / 10)
should be updated to:

Code: Select all

faction:ConsumeManpower(-unit.hp)
lordzimoa
Lordz Games Studio
Lordz Games Studio
Posts: 2417
Joined: Fri Oct 27, 2006 4:20 pm
Contact:

Re: Repairing Units drains ManPower

Post by lordzimoa »

Thanks guys, this is already fixed and will be in the upcoming Beta patch 1.6 that is coming soon.

Cheers,

Tim
PrinceMiskin
Lance Corporal - SdKfz 222
Lance Corporal - SdKfz 222
Posts: 21
Joined: Fri Aug 03, 2007 6:05 pm

Re: Repairing Units drains ManPower

Post by PrinceMiskin »

Cheers

Code: Select all

function GetMPOutput(faction)
  local minimum = 50
  return minimum + math.min(minimum, math.ceil(faction.mp * minimum / data.factions[faction.id+1].manpowerMax))
end
Could someone explain to me what is the meaning of: [faction.id+1]

I am having some issues understanding if the "+1" is intended or not.
Historion
Corporal - 5 cm Pak 38
Corporal - 5 cm Pak 38
Posts: 31
Joined: Wed Jul 30, 2014 10:41 pm

Re: Repairing Units drains ManPower

Post by Historion »

I'm not a LUA-expert but it seems that in LUA the index of a table / array starts with '1' (while in C and most other languages it starts with '0').

data.factions is a table/array defined in "factions.lua". Each faction has an attribute "id" and these ids start with value '0', e.g.
France is the 1st faction (data.factions[1]) and has id = 0.

Code: Select all

data.factions =
{
  {
    name= "france",
    id = 0,
    manpowerMax = 1100,
    morale = 110,
    territory = 2,
    research = { ground = 1, artillery = 1, naval = 1, air = 1, armour = 1 },
    color = {34, 92, 136},
  },
...
So the table-index of a faction is "faction.id + 1" .
PrinceMiskin
Lance Corporal - SdKfz 222
Lance Corporal - SdKfz 222
Posts: 21
Joined: Fri Aug 03, 2007 6:05 pm

Re: Repairing Units drains ManPower

Post by PrinceMiskin »

This is great! Thanks!

You know, I have rescaled everything to x10 MP to avoid rounding issues. The problem now is the quality drop, when we MP falls below 90%, does not occur.

And yes, I have edited both manpowerMax in factions.lua and mp in 1914.lua.

I am struggling to see what could have gone wrong...
Post Reply

Return to “Commander - The Great War”