Land unit reactions are overly complex because we have two different
concepts controlling them: reaction radius (set with lrange) and
reserve mission (set with mission). You need to deal with both to set
up or query reactions.
Commit 8d0e1af5 "fixed" this by making reserve missions meaningless.
The previous commit made reserve missions meaningful again: they
support an op-area now. This brought back the problem of having to
deal with two separate commands to accomplish one thing.
Fix this for good by removing non-mission land unit reaction
alltogether. The only feature we lose by that is the ability to order
land units to react until the order is explicitely cancelled. That's
because missions are implicitely cleared by many commands and events,
while non-mission reaction wasn't. Closes#858121 and #858122.
Remove the non-mission reaction case from att_reacting_units().
Don't limit reserve missions to the land unit's reaction radius: make
lnd_reaction_range() return the type's maximum radius instead of
lnd_rad_max.
The reaction radius is now useless. Remove the lrange command, and
struct lndstr member lnd_rad_max along with its selector react.
Remove land command's column rd. Make ldump show column react as
zero. Deprecate edit key 'P' in dounit(), and don't show it in
pr_land().
Before, they always reacted to their maximum range, and the op-area
was unused. Change mission() to define the op-area for reserve
missions as well. Remove the special-case for showing reserve
missions from mission() and show_mission(). New lnd_reaction_range()
factored out of att_reacting_units(). Use it in oprange() to cover
reserve missions. Pass the mission as separate parameter to oprange()
for now, because miss() doesn't set it in the object until later.
Load counters are redundant; they can be computed from the carrier
uids. Keeping them up-to-date as the carriers change is a pain, and
we never got that quite complete.
Computing load counters straight from the carrier uids every time we
need them would be rather inefficient, but computing them from cargo
lists is not. So do that.
Remove the load counters: struct shpstr members shp_nplane,
shp_nchoppers, shp_nxlight, shp_nland, and struct lndstr members
lnd_nxlight and lnd_nland.
Don't compute/update load counters in build_ship(), build_land(),
land(), ldump(), load_plane_ship(), load_land_ship(),
load_plane_land(), load_land_land(), lstat(), sdump(), shi(), sstat(),
tend_land(), check_trade(), put_combat(), pln_oneway_to_carrier_ok),
pln_newlanding(), fit_plane_on_ship(), fit_plane_on_land(),
unit_list().
Nothing left in fit_plane_off_ship(), fit_plane_off_land(), so remove
them.
load_land_ship(), load_land_land(), check_trade(), pln_newlanding(),
put_plane_on_ship(), take_plane_off_ship(), put_plane_on_land(),
take_plane_off_land() no longer change the carrier, so don't put it.
Remove functions to recompute the load counters from carrier uids:
count_units(), lnd_count_units(), count_planes(), count_land_planes(),
pln_fixup() and lnd_fixup(), along with the latter two's private
copies of fit_plane_on_ship() and fit_plane_on_land().
New cargo list functions to compute load counts: unit_cargo_count()
and unit_nplane(), with convenience wrappers shp_nplane(),
shp_nland(), lnd_nxlight(), lnd_nland().
Use them to make ship selectors nplane, nchoppers, nxlight, nland
virtual. They now reflect what is loaded, not how the load uses the
available slots. This makes a difference when x-light planes or
choppers use plane slots.
Use them to make land unit selectors nxlight and nland virtual.
Use them to get load counts in land(), ldump(), load_plane_ship(),
load_land_ship(), load_plane_land(), load_land_land(), sdump(), shi(),
tend_land(), fit_plane_on_land(), trade_desc(), unit_list().
Rewrite fit_plane_on_ship() and could_be_on_ship() to use
shp_nplane(). could_be_on_ship() now takes load count arguments, as
computed by shp_nplane(), so it can be used for checking against an
existing load as well.
Persistent game state encodes "who carries what" by storing the
carrier uid in the cargo. Cargo lists augment that: they store lists
of cargo for each carrier. They are not persistent.
New unit_cargo_init() to compute the cargo lists from game state.
Call it in ef_init_srv() and at the end of update_main().
New unit_onresize() to resize the cargo list data structure.
Installed as units' struct empfile callback onresize to make them
resize automatically with the unit files.
New unit_carrier_change() to update cargo lists when carriers change
in game state. Convenience wrappers pln_carrier_change(),
lnd_carrier_change() and nuk_carrier_change(). Call them from
prewrite callbacks to keep cargo lists in sync with game state.
To make that work, unused units must not point to a carrier. Add new
pln_oninit(), lnd_oninit() and nuk_oninit() take care of newly created
units. Change lnd_prewrite() and nuk_prewrite() to take dead land
units and nukes off their carrier. pln_prewrite() did that already.
New unit_cargo_first(), unit_cargo_next() to traverse cargo lists.
Convenience wrappers lnd_first_on_ship(), lnd_first_on_land(),
lnd_next_on_unit(), pln_first_on_ship(), pln_first_on_land(),
pln_next_on_unit() and nuk_on_plane(). The latter is disabled for now
because it clashes with an existing function.
The values in these columns were computed by count_sect_units() and
count_sect_planes(), which included land units and planes in the count
that aren't shown by prunits() and prplanes(), namely own and embarked
units. Confusing. Moreover, count_sect_planes() and prunits() rolled
dice separately for spy units. This could leak the presence of spies
even when prunits() didn't show them.
All fixable, but not worth the trouble; just remove the counts.
This oopses on output dependency violations, e.g. two threads doing a
read-modify-write without synchronization, or the one thread nesting
several read-modify-writes. Such bugs are difficult to spot, and tend
to be abusable. I figure we have quite a few of them.
New struct emptypedstr member seqno. Make sure all members of unit
empobj_storage share it. Initialize it in files: main() and
file_sct_init(). Set it in ef_blank() and new ef_set_uid() by calling
new get_seqno(). Use ef_set_uid() when copying objects: swaps(),
doland(), doship(), doplane(), dounit(), delete_old_news(). Step it
in ef_write() by calling new new_seqno().
Factor do_read() out of fillcache() to make it available for
get_seqno().
The abstract idea of tying ships and land units to a logistical tether
is sound, the concrete implementation as option FUEL is flawed. It
adds too much busy-work to the game to be enjoyable. It hasn't been
enabled in a public game for years. The code implementing it is ugly,
repetitive, and a burden to maintain.
Remove selector fuel from ship_ca[] and land_ca[], and selectors
fuelc, fuelu from mchr_ca[] and lchr_ca[]. Remove fields fuelc, fuelu
from ship.config and land.config.
Remove command fuel from player_coms[].
Deprecate edit key 'B' in doship(), dounit(), and don't show it in
pr_ship(), pr_land().
Drop opt_FUEL code from build_ship(), shi(), sdump(), ship_damage(),
show_ship_stats(), do_mob_ship(), nav_ship(), build_land(), land(),
ldump(), land_damage(), show_land_stats(), do_mob_land(),
resupply_all(), resupply_commod(), get_minimum(), has_supply(),
unit_list(), vers().
Remove opt_FUEL, fuel_mult, struct shpstr member shp_fuel, struct
mchrstr members m_fuelc and m_fuelu, M_OILER, struct lndstr member
lnd_fuel, struct lchrstr members l_fuelc and l_fuelu, fuel(), and
auto_fuel_ship().
Make sure all members of unit empobj_storage share it.
Add matching timestamp member to struct comstr, struct empobj, struct
gamestr, struct lonstr, struct natstr, struct nwsstr, struct trdstr,
struct trtstr. The timestamp isn't yet set for these. To be fixed.
Move the timestamp member to the right place in struct lndstr, struct
loststr, struct realmstr, struct nukstr, struct plnstr, struct sctstr,
struct shpstr.
struct lndstr members lnd_spy, lnd_rad, lnd_ammo, lnd_fuelc,
lnd_fuelu, lnd_maxlight, lnd_maxlight are mere copies of struct
lchrstr members l_spy, l_rad, l_ammo, l_fuelc, l_fuelu, l_nxlight,
l_nland. Remove them.
Make land unit selectors spy, rmax, ammo, fuelc, fuelu, maxlight
virtual.
New lnd_att(), lnd_def(), lnd_vul(), lnd_spd(), lnd_vis(), lnd_frg(),
lnd_acc(), lnd_dam(), lnd_aaf() replace the struct lndstr members with
the same names.
Make land unit selectors att, def, vul, spd, vis, frg, acc, dam, aaf
virtual.
This takes care of a number of bugs / inconsistencies:
* Resupply before fire: fire command did not require unit to be in
supply, and resupplied shells. Everywhere else (return fire,
support and interdiction) the land unit had to be in supply after
resupply of everything. Unify not to resupply anything and not to
require being in supply. This is consistent with ships and sectors.
* Resupply after fire: fire command resupplied shells after active
fire. Unify not to do that. This is consistent with ships and
sectors.
* When a land unit returned fire to multiple attackers, quiet_bigdef()
charged it ammo for each one. Finally, it was charged one shell
more by use_ammo(). Except only the first land unit got charged
there in fact, because buggy add_to_fired_queue() entered only the
first land unit into the defender list. Fix add_to_fired_queue()
and change quiet_bigdef() not to charge ammo, just like for ships
and sectors. This charges only one shell instead of the true ammo
use, which is wrong, but consistent with ships.
* lnd_support() tallied support damage unrounded. Unify to round
before tally.
The macros defining unit stat development in tech are somewhat
inconvenient to use. Define more convenient functions, and hide away
the macros near the function definitions.
Make sure all members of unit empobj_storage share uid in addition to
ef_type.
Add matching uid member to struct gamestr, struct natstr and struct
sctstr, and set them.
Swap struct empobj members uid and own to make that easier, and update
struct comstr, struct lndstr, struct lonstr, struct loststr, struct
nwsstr, struct nukstr, struct plnstr, struct realmstr, struct shpstr,
struct trdstr, struct trtstr accordingly.
Note that the uid isn't properly set for struct nwsstr, struct lonstr,
struct trdstr, struct comstr and struct loststr. To be fixed.
Mil are not required for building units since 4.0.0. l_mil was still
initialized to l_item[I_MILIT], and used instead of that in a couple
of places. Fix those, and remove the initialization.
(lndstr, plnstr, sctstr, shpstr): Change timestamp members lnd_access,
pln_access, sct_access, shp_access from real time (time_t) to ETUs
within a turn (short).
(land_ca, plane_ca, sect_ca, ship_ca): Update accordingly.
(build_ship, build_land, build_bridge, build_plane, build_tower)
(explore, check_trade, bsanct, takeover, takeover_ship)
(takeover_land): Use game_tick_to_now() instead of time() to update
the timestamp. Change check_trade(), takeover_ship(), takeover_land()
to do that only when MOB_ACCESS is enabled, for consistency.
(lupgr, supgr, pupgr, takeover_ship): Don't touch the timestamp where
mobility isn't touched either.
(sct_do_upd_mob, shp_do_upd_mob, lnd_do_upd_mob, pln_do_upd_mob): Use
game_tick_to_now() instead of increase_mob() to compute ETUs since
the timestamp and update the timestamp. Closes#1012699.
(increase_mob): Remove.
(mob_sect, mob_ship, mob_land, mob_plane): sct_do_upd_mob() & friends
no longer do the right thing at the update. Use game_reset_tick() and
pass its result directly to do_mob_sect() & friends. This is only
correct when argument is etu_per_update, which it always is. Remove
parameter. Callers changed.
(do_mob_sect, do_mob_ship, do_mob_land, do_mob_plane): Oops on
negative argument.
(mob_acc_globals, timestampfil, mobupdate, updating_mob)
(update_all_mob, timestamp_fixing, update_timestamps, mobility_check):
The mobupdate command was important to let deities manually
synchronize mobility updating with updates. That's no longer needed.
The code behind it is somewhat hairy and ugly, and updating it to work
with the Empire clock is just not worth it. Remove. Users changed.
(player_coms): Update accordingly.
(upda): Remove display of mobility updating state.
(mobility_init): No need to fix up mobility on startup, as the Empire
clock runs normally even when the server is down. Remove. Caller
changed.
other. Ensure headers in include/ can be included in any order
(except for econfig-spec.h, which is special). New header types.h to
help avoid inclusion cycles. Sort include directives. Remove some
superflous includes.
is non-zero; actual value of non-zero l_ammo was unimportant. Side
effect: it substantially increased ammunition consumption at high
tech, because the change made the value increase with tech. Back out
4.2.3's change, just use l_ammo. This lets deities customize
ammunition consumption independent of damage. Remove second
parameter. Callers changed.
oprange, show_mission, nameofitem, build_mission_list_type,
unit_map, xdvisible, trdswitchown, ontradingblock, trad, check_trade,
unit_type_name, start_stop_unit, scut, scra, mission, multifire,
perform_mission, fuel, NSC_GENITEM): Replace struct genitem with
struct empobj. Remove genitem.h and create a new file empobj.h.
Replace multiple instances of unions of ef_type structures with
one standard union empobj_storage which is a superset of the individual
instances.
(lnd_path): Use it.
(lnd_mobcost): Use it, remove last parameter. Callers changed. This
fixes mobility use of trains when retreating, both for retreat orders
and for failed morale checks.
(retreat_land1): Fix test for impassable terrain. Before, trains
could retreat off rail.
(lnd_take_casualty): Test for impassable terrain. Before, trains
could retreat off rail.
(att_reacting_units): Use it. Fixes overcharging of inefficient
units. Broken when Empire3 changed land unit mobility use not to
depend on efficiency, except for supply units.
(lnd_sweep): Use it. No functional change.
(speed_factor): New, factored out of lnd_pathcost() and shp_mobcost().
short, to match shp_item and lnd_item.
(mchr_ca, lchr_ca): Replace selector item by selectors for the items.
lchr_ca's item selector was incorrect and worked only by accident.