This reverts commit f4d8d64bb3.
Breaks retreat after ship got sunk by bombs or missile.
ship_bomb() and launch_missile() pass .shp_own to retreat_ship().
Wrong after putship(), because putship() resets the owner when the
ship got sunk. retreat_ship() then oopses and fails to retreat the
surviving members of the group.
Other callers save the owner before putting the ship, and pass that.
We could change these two to do the same. But since we're trying to
get a release out, simply revert the broken commit instead.
boar() puts before retreating, the other callers afterwards. Subtle
difference, because putting resets the owner of the dead to POGO.
Until the commit before previous, retreat didn't fully work after put.
Now it does. The subtle difference between boar() and the other
callers still exists. It's better to do it the same everywhere, as
subtle differences invite bugs. Since changing boar() is not
practical, change the others.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Group retreat still doesn't work, because when boar() passes a sunk
ship to retreat_ship(), its owner has been reset to POGO already.
This makes it impossible to find the group to retreat. Instead, it
attempts to retreat ships that sank in the same sector with group
retreat orders and with the same fleet letter assigned. If any exist,
shp_may_nav() oopses, and prevents actual retreat of these ghosts.
The other retreat conditions don't have this problem, because they
call putship(), which resets the owner, only after retreat_ship().
Making boar() work the same is not practical. Instead, add an owner
parameter to retreat_ship(), and for symmetry also to retreat_land().
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Rather than after post-yield sanity checking. Just to make it obvious
that we are handling getstarg() failure.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
These commands report "sunk!" even when the ship survives the attack
but sinks during retreat. bomb even reports where on the retreat the
ship sinks. Has been that way since retreat was added in Chainsaw.
Report "sunk!" only when the attack sinks the ship directly.
Similar code exists for land units, but it doesn't report killings.
Change it anyway, to keep it consistent with the ship code.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Planes flying one-way with crew or cargo spread plague from their old
base to their new base. Planes dropping cargo spread plague from
their base to the drop's target sector.
msl_equip(), find_escorts() and perform_mission() memset() the plist,
then assign to all members but load. Just zero load instead, like
getilists(), msl_sel() and pln_sel() do.
Why upgrade? I'm not a lawyer, but here's my take on the differences
to version 2:
* Software patents: better protection against abuse of patents to
prevent users from exercising the rights under the GPL. I doubt
we'll get hit with a patent suit, but it's a good move just on
general principles.
* License compatibility: compatible with more free licenses, i.e. can
"steal" more free software for use in Empire. I don't expect to steal
much, but it's nice to have the option.
* Definition of "source code": modernization of some details for today's
networked world, to make it easier to distribute the software. Not
really relevant to us now, as we normally distribute full source code.
* Tivoization: this is about putting GPL-licensed software in hardware,
then make the hardware refuse to run modified software. "Neat" trick
to effectively deny its users their rights under the GPL. Abuse was
"pioneered" by TiVo (popular digital video recorders). GPLv3 forbids
it. Unlikely to become a problem for us.
* Internationalization: more careful wording, to harden the license
outside the US. The lawyers tell us it better be done that way.
* License violations: friendlier way to deal with license violations.
This has come out of past experience enforcing the GPL.
* Additional permissions: Probably not relevant to us.
Also include myself in the list of principal authors.
SLOW_WAR has issues:
* The check whether the attacker old-owns the attacked sector is
broken, because att_abort() uses sect.sct_oldown uninitialized.
Spotted by the Clang Static Analyzer.
* Its implementation in setrel() is somewhat scary. It's actually
okay, because that part of setrel() only runs within decl(). Other
callers don't reach it: update_main() because player->god != 0
there, and the rest because they never pass a rel < HOSTILE.
* Documentation is a bit vague.
SLOW_WAR hasn't been used in a public game in years. Fixing it is not
worth it, so remove it instead.
Launching ABMs updates their base, in mission_pln_equip(). The update
got wiped out when launch_missile() wrote back the target sector,
triggering a seqno mismatch oops. Harmless with the stock game's
ABMs, because they use neither shells nor petrol.
Fix by re-reading the target sector.
Ships can expend shells to defend against missiles, in
shp_missile_defense(). Any shell use by the target ship got wiped out
when launch_missile() wrote back the target ship, triggering a seqno
mismatch oops.
Fix by re-reading the target ship.
Collateral damage was disabled, because after msl_hit() reported a
miss, the missile may or may not have reached the target.
Fix by splitting msl_launch() off msl_hit().
Drop the disabled collateral damage code for sector targets, because
sectors can't be missed. Enable it for ships and land units.
Since msl_launch() returns whether the missile is sub-launched, drop
launch_missile() parameter sublaunch, and simplify its caller.
Keep only the common part in msl_intercept(), and give it internal
linkage. Wrap new msl_abm_intercept() and msl_asat_intercept() around
it. They are simpler to use.
Before Empire 2, nukes could be delivered only with bomb (special
mission 'n', airburst only) and launch (targeting sectors or
satellites only).
Empire 2 made nukes available for any kind of bombing, and for any
missile strike on sectors or ships. This included interdiction and
support missions. Nuclear-tipped anti-sats and bomb mission n were
removed.
Unfortunately, this was done in a messy way, which led to
inconsistencies and bugs. The problem is that ordinary damage affects
just the target, while nuke damage affects an area. Code dealing with
plane damage was designed for the former. Instead of rewriting it to
cope with area damage cleanly, nuke damage got shoehorned into
pln_damage(), the function to compute conventional plane damage, as a
side effect: computing damage blasted sectors in the area.
If the plane carried a nuke, pln_damage() returned zero (conventional)
damage. Without further logic, this simply bypassed the code to apply
damage to the target. This worked out okay when the target already
got damaged correctly by the side effect.
However, some targets are immune to the side effect: when interdicting
a move or explore command, the commodities being moved are not in any
sector.
For other targets, damage has effects other than damaging the target:
offensive and defensive support don't apply the (conventional) damage
to the target sector. Instead, they turn it into a combat bonus.
Without further logic, nuclear damage doesn't contribute to that.
To make all that work, pln_damage() returned the nuclear damage for
ground zero as well. Because a plane does either conventional or
nuclear damage, one of them is always zero.
Most callers simply ignored the nuclear damage, and applied only the
conventional damage.
Bug: land units and ships failed to retreat when pin-bombed or
missiled with a nuke. That's because they received zero conventional
damage.
The mission code flies planes and missiles and tallies their damage.
This mission damage included nuclear damage at ground zero (except for
missiles sometimes, see below), to make support and commodity
interdiction work. Unfortunately, this broke other things.
Bug: when bombers interdicted ships or land units, nukes first damaged
the ships or land units by the side effect, then again through mission
damage. Interdicting missiles had a special case to avoid this.
Bug: when interdicting move, explore or transport, nukes first damaged
the sector by the side effect, then again through mission damage's
collateral damage.
There may well be more bugs hiding in this mess.
The mess is not worth fixing. While the idea of interdicting and
supporting with nukes sounds kind of cool, I believe it's pretty
irrelevant in actual play.
Instead, go back to a variation of the original rules: nukes can be
delivered only through bomb mission 's' and launch at sectors.
Make arm reject marine missiles in addition to satellites, ABMs and
SAMs, and clear the mission. Make mission reject planes armed with
nukes. Oops when they show up in mission_pln_equip() anyway.
Make pln_equip() allow planes with nukes only for missions 's' and
't'.
Clean up pln_damage() to just compute damage, without side effect.
Change strat_bomb() and launch_missile() to detonate nukes. Simplify
the other callers. Parameter mission of msl_launch_mindam() is now
unused, remove it.
Missiles exploding on launch no longer set off their nukes. That was
pretty ridiculous anyway.
msl_equip() used mission_pln_equip(), which is for automatic defenses,
and therefore silent. Its users launch_as(), launch_missile() and
launch_sat() printed failure diagnostics based on assumptions on what
could go wrong.
Switch to the appropriate function for commands, pln_equip(), and
remove the guesswork. Implement mission 'i' there. When launching
from a foreign base, its owner now gets informed. Unimportant at this
time, as players can't easily deploy missiles in foreign bases.
This change also switches off automatic supply for launch. Consistent
with bomb.
When a manually launched anti-sat hits, it now always destroys the
satellite. This matches what it does when it intercepts
automatically. Before, it only damaged the satellite.
Before, it took a sector argument, and targeted the lowest-numbered
satellite there. Rather inconvenient when your own satellite masks
one of the enemy's.
Moreover, the command could be abused to find all sectors with
satellites. Now it can "only" be abused to find satellite ids, and
whether they're in range. Still not ideal, but tolerable.
launch_sat() failed to normalize the satellite's coordinates when it
added a random course deviation. Satellites with screwed up
coordinates were missed by skywatch, and possibly in other places.
The old code used getstarg() to get an argument with a different
prompt than snxtitem() uses, then passed the value to snxtitem()
unchecked. If the player aborts, getstarg() returns a null pointer,
and snxtitem() prompts again. Affected:
* load/lload plane/land third argument; load_plane_ship(),
load_land_ship(), load_plane_land(), load_land_land()
* bomb, drop, fly, paradrop, recon and sweep second argument;
get_planes()
* tend and ltend second and fourth argument; ltend(), tend(),
tend_land()
* mission second argument; mission()
Fix by making snxtitem() taking a prompt argument, null pointer
requests the old prompt.
Use that to simplify multifire() and torp(). Change the other callers
to pass NULL.
This outlaws launch from unowned sectors. Also, non-VTOL missiles
require an efficient airfield now, except that such missiles don't
exist currently, because init_plchr() makes all missiles VTOL.