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.
delete_old_news() and init_nreport() tested for non-zero nws_when,
which is breaks for news at the epoch. Not likely to happen, but
still wrong.
ncache() tested nws_uid, which breaks for the first entry in the news
file. This made ncache() overlook that entry in the cache, and create
a new news item instead of incrementing nws_ntm. Was always broken
that way.
Fix by testing nws_vrb instead.
The call of ef_ensure_space() serves no purpose: the blank records it
adds are ignored on read, and overwritten (not updated) by new news.
Get rid of it.
New struct emptypedstr to avoid depending on empobj.h there.
Remove now superfluous manual initializations elsewhere.
This doesn't fix any missing initializations.
The get_FOOp() macros are generally avoided outside the update,
because direct access to the sector cache needs synchronization to be
safe. unit_map() didn't access the cache directly until it was
converted from get_ship() & friends to get_empobjp() in commit
fec9878c. Switching to get_empobj() reverts the change to direct
access while keeping the simplification.
There's no technical reason for rejecting sector access by id. It's
unusual, but not wrong.
Also remove the superfluous test for EF_BAD; ef_ptr() covers that.
put_empobj() used struct empobj member uid, which is valid only for
units. Existing users pass only units, fortunately. Fix by making it
take type and uid parameters.
get_empobj_chr() and emp_obj_chr_name() access struct sctstr member
sct_type through struct empobj member type. This is technically
non-portable, because the two differ in signedness. It was also
undocumented. Fix by making sct_type signed. sct_newtype as well,
for consistency.
map_char() uses unsigned char for a sector type argument. Change that
to int. Matches how this is done elsewhere.
Always charge land units at least as much mobility for assaulting from
non-landing ships as for landing ships. Before, marines lost all
mobility when assaulting from a non-landing ship, which could be less
than what the same assault costs from a landing ship (half an update's
worth).
Actually, this isn't just simplification. When mobility gain per
update was configured to be greater than 128, mobility could go from 1
to less than -127 when assaulting from a landing ship, and thus
overflow. Make it saturate at -127. Note that you can expect plenty
of trouble elsewhere with such a silly configuration.
A bridge (span or tower) must be splashed when it gets damaged below
SCT_MINEFF. Likewise when its last supporting sector (bridge head or
tower) gets damaged below SCT_MINEFF, unless EASY_BRIDGES is enabled.
We need to check this whenever a bridge head, span or tower gets
damaged. This is done in three places, and all of them screw up:
* checksect() ignores damage to bridge heads. It also leaves writing
back the sector it checks to the caller, which never happens when
it's called from sct_postread().
Note that checksect() drowns all planes on bridges it splashes.
Functions that need to exempt flying planes from such a fate have to
splash bridges themselves.
* sect_damage() ignores damage to bridge towers, and damage to bridge
spans unless EASY_BRIDGES is enabled. It then runs checksect(),
which compensates for these omissions, but happily drowns the planes
sect_damage() attempts to protect.
* eff_bomb() ignores damage to bridge heads. Collateral damage makes
sect_damage() run, which compensates for the omission.
This causes the following bugs:
* Efficiency damage going through sect_damage() can drown planes it
shouldn't. This affects pinpoint bombing when collateral damage
splashes a bridge, and strategic bombing. The drowned planes then
crash and burn when they attempt to land at their (just splashed)
base.
* Efficiency damage to bridge heads not going through sect_damage()
fails to collapse unsupported bridges. This affects pin-bombing
efficiency without collateral damage, and ground combat. Also deity
commands edit, setsector and add, but that could be regarded as a
feature.
* If the sector file somehow ends up with an inefficient bridge span,
it collapses on every read again and again, until it collapses on a
write. Related problems exist with other actions of checksect(),
and they're not addressed here.
* If the sector file somehow ends up with adjacent inefficient bridge
towers, checksect() on any of them recurses infinitely:
- checksect() inefficient tower T1
- knockdown() T1, but don't write that back to the sector file
- bridgefall() T1; this reads all adjacent sectors, including
inefficient towert T2
- checksect() T2
- knockdown() T2, but don't write that back to the sector file
- bridgefall() T1; this reads adjacent sectors including T1
- checksect() T1
...
This commit creates a new function bridge_damaged() to splash any
bridges that became inefficient or unsupported after damage to a
sector. To avoid the inifinite recursion, we call it in
sct_prewrite() instead of checksect().
No uses knockdown() outside bridgefall.c remain, so give it internal
linkage.
Split ef_init() into two functions: empfile_init() for initialization,
and empfile_fixup() to fix it up for configuration. Put them next to
empfile[]. Move the call to empfile_init() from behind emp_config()
to before it.
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.
Move stuff to untangle the ugly cyclic dependencies between the
archives built for selected subdirectories of src/lib/:
* Move common/io.c to empthread/ because it requires empthread stuff
* Move parts of subs/nstr.c to common/nstreval.c to satisfy
common/ef_verify.o
* Move getstarg.c getstring.c onearg.c from gen/ to subs/ because they
require stuff from there
* Move bridgefall.c check.c damage.c empobj.c journal.c maps.c
sectdamage.c from common/ to subs/ because they require stuff from
there
* Move cnumb.c from subs/ to common/ to satisfy common/type.o
* Move log.c fsize.c from common/ to gen/ because they really belong
there
* Move emp_config.c mapdist.c from gen/ to common/ because they really
belong there, and require stuff from libglobal.a
Also package as/ as libas.a to satisfy common/path.o.
Remaining dependencies:
lib needs
--------------------------------------------
libas.a libglobal.a
libcommon.a libas.a libglobal.a libgen.a
libgen.a
libglobal.a
liblwp.a libgen.a
libw32.a[*] libgen.a
[*] Except for service.o, which can only be linked into the server
Link order now: liblwp.a libcommon.a libas.a libgen.a libglobal.a
libw32.a. The position of libw32.a is not quite right, but works
anyway.
The function that gave its name to this file is long gone, the file's
description is bogus, and it contains just one definition. Move that
to ../subs/border.c, and delete the file.
There are several files with land unit subroutines. This one is in an
awkward place: it depends on stuff from ../subs, which contributes to
libcommon.a's ugly dependencies. Move its contents to logical places
(use internal linkage where possible), and remove it.
in mission_pln_equip(), which is called from ac_intercept(). The
inconsistency appeared in Empire3, and had no ill effect then. But
rev. 1.42 screwed up the fuel test here: it made interceptors that
don't use fuel (SAMs) require petrol to be present to fly.
(carriersatxy, pln_onewaymission): Pass zero. No functional change.
(pln_airbase_ok): Pass whether the plane is a missile. This fixes
non-x-light missiles on ships without capability M_FLY. Broken in
rev. 1.76. Launch and interdict weren't affected. Air defense was,
but the stock game has only x-light SAMs.
(pln_onewaymission): Use it. No functional change.
(pln_airbase_ok): Use it to enforce capabilities. Before, a plane
could fly once it got on the ship. Because ships can load only planes
that can fly from them, this has no effect other than make that sanity
check redundant; remove it.
(pln_airbase_ok): Update land unit case to keep it similar to the ship
case.
Check player->cnum only when noisy. Update existing caller to pass 1.
No functional change.
(mission_pln_airbase_ok): Remove, use pln_airbase_ok() instead. No
functional change.
last, so when it was (no longer) allied, attempting to fly off it let
you test the conditions checked before that. Check owner first.
(mission_pln_airbase_ok): Matching change, to avoid diverging from
pln_airbase_ok().