Differentiated veteran systems

What would you like to see in Freeciv? Do you have a good idea what should be improved or how?
Ignatus
Hardened
Posts: 271
Joined: Mon Nov 06, 2017 12:05 pm
Location: St.Petersburg, Russia
Contact:

Differentiated veteran systems

Postby Ignatus » Sat Dec 07, 2019 9:28 pm

Currently, any unit type has only one veteran system, either common or individual, that is used for all means (we can set "NoCombatVeteran" flag for units that are promoted only by working). I propose a feature (influenced by CivIV) that a unit may get veterancies in different businesses that will influence in the future these businesses only. For example, a worker unit can rise from apprentice to journeyman only by working hard while it can also get combat experience while attacked, but the latter won't help to work.

Technically, we use int field for unit veteranship while there is at maximum 20 levels you can define, so we have 32 - 5 = 27 bits to place other systems (but better restrict it to 16 - 5 = 11 for not resizing universals, the other half may store experience). Example of what units.ruleset may look like:

Code: Select all

;default (unnamed) vet. system, 3 bits
[veteran_system]
veteran_names = _("green"), _("veteran"), _("hardened"), _("elite")
veteran_actions = "Attack", "Defend" ; can obtain veteranship and get the bonus
veteran_used_at = "Bombard", "Bombarded" ; can only get the bonus
veteran_raise_chance = 50, 33, 20, 0
veteran_power_fact = 100, 150, 175, 200
veteran_move_bonus        = 2, 4, 6 ; move bonuses are additive
veteran_default = TRUE
;for workers and engineers, 2 bits
[veteran_system_work]
veteran_names = _("?worker_level:apprentice"),  _("?worker_level:journeyman"),  _("?worker_level:master")
veteran_actions = "Work" ; can obtain veteranship and get the bonus
veteran_work_raise_chance = 2, 1, 0
veteran_power_fact        = 100, 125, 150
veteran_move_bonus        = 2, 4, 6 ; move bonuses are additive
;for diplomats, 3 bits
[veteran_system_diplomat]
veteran_names = _("?diplomatic_rank:attaché"),  _("?diplomatic_rank:secretary"),
     _("?diplomatic_rank:envoy"),  _("?diplomatic_rank:ambassador")
veteran_actions = "DiplomaticBattle"
veteran_raise_chance = 50, 33, 20, 0
veteran_power_fact = 100, 105, 110, 115
veteran_move_bonus = 2, 4, 6, 8
; for spies, THE SAME 3 bits
[veteran_system_spy]
veteran_overrides = "diplomat"
veteran_names = _("?spy_level:informant"),  _("?spy_level:handler"),
  _("?spy_level:agent"), _("?spy_level:spymaster")
veteran_actions = "Diplomatic", "DiplomaticBattle"
veteran_raise_chance = 50, 33, 20, 0
veteran_power_fact = 100, 105, 110, 115
veteran_move_bonus = 2, 4, 6, 8
[unit_worker]
;...
veteran_system = "", "work"; if not specified, default ones are used
;...

Veteran_Build effect should have a bitwise way to define its value:

Code: Select all

[effect_barracks_I]
type = "Veteran_Build"
value = veteran("", 1)
reqs   =
    { "type", "name", "range", "present"
      "Building", "Barracks", "City", TRUE
      "UnitClass", "Land", "Local", TRUE
      "UnitFlag", "NonMil", "Local", FALSE
      "UnitFlag", "NoVeteran", "Local", FALSE
    }

Then, we use it in requirements, for example, let only a veteran spy can incite a democratic city:

Code: Select all

[actionenabler_incite_city_spy2]
action = "Incite City Escape"
actor_reqs    =
    { "type",         "name",          "range", "present"
      "UnitFlag",     "Spy",           "Local", TRUE
      "DiplRel",      "Alliance",      "Local", FALSE
      "UnitState",    "Transported", "Local", FALSE
      "MinMoveFrags", "1",             "Local", TRUE
      "DiplRel",      "Foreign",       "Local", TRUE
      "MinVeteran", veteran("spy", "handler"), "Local", TRUE
    }
target_reqs    =
    { "type",     "name",      "range",  "present"
      "Gov",      "Democracy", "Player", TRUE
      "Building", "Palace",    "City",   FALSE
    }