Refactor and fix takeover.c
Factor new takeover_unit() out of takeover_ship(), takeover_plane(),
takeover_land(). This fixes the following bugs in assault, attack,
board, lboard, paradrop and pboard:
* When the "land unit loaded on land unit" relation had a cycle,
takeover_land() went into an infinite recursion. Such cycles exist
only in a corrupt game state.
* Nukes armed on planes weren't taken over along with their plane.
Broken in commit 2e40a4bb
, v4.3.3.
* Taking over land units with negative mobility increased mobility to
zero. Ditto planes embarked on ships or land units.
* Taking over planes embarked on ships or land units didn't clear
their wing.
* Taking over planes and land units updated their MOB_ACCESS timestamp
(pln_access, lnd_access), except for planes not embarked on
anything. This had no effect.
This commit is contained in:
parent
94a3108b23
commit
5f6e27ff80
1 changed files with 53 additions and 76 deletions
|
@ -35,6 +35,7 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "empobj.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "land.h"
|
#include "land.h"
|
||||||
#include "lost.h"
|
#include "lost.h"
|
||||||
|
@ -48,6 +49,8 @@
|
||||||
#include "ship.h"
|
#include "ship.h"
|
||||||
#include "xy.h"
|
#include "xy.h"
|
||||||
|
|
||||||
|
static void takeover_unit(struct empobj *, natid);
|
||||||
|
|
||||||
void
|
void
|
||||||
takeover(struct sctstr *sp, natid newown)
|
takeover(struct sctstr *sp, natid newown)
|
||||||
{
|
{
|
||||||
|
@ -200,96 +203,70 @@ takeover_plane(struct plnstr *pp, natid newown)
|
||||||
prplane(pp),
|
prplane(pp),
|
||||||
cname(newown), xyas(pp->pln_x, pp->pln_y, pp->pln_own));
|
cname(newown), xyas(pp->pln_x, pp->pln_y, pp->pln_own));
|
||||||
}
|
}
|
||||||
if (opt_MARKET)
|
takeover_unit((struct empobj *)pp, newown);
|
||||||
trdswitchown(EF_PLANE, pp, newown);
|
|
||||||
if (pp->pln_mobil > 0)
|
|
||||||
pp->pln_mobil = 0;
|
|
||||||
pp->pln_own = newown;
|
|
||||||
pp->pln_mission = 0;
|
|
||||||
pp->pln_wing = 0;
|
|
||||||
putplane(pp->pln_uid, pp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
takeover_ship(struct shpstr *sp, natid newown)
|
takeover_ship(struct shpstr *sp, natid newown)
|
||||||
{
|
{
|
||||||
struct plnstr *pp;
|
takeover_unit((struct empobj *)sp, newown);
|
||||||
struct lndstr *lp;
|
|
||||||
struct nstr_item ni;
|
|
||||||
struct plnstr p;
|
|
||||||
struct lndstr llp;
|
|
||||||
|
|
||||||
if (opt_MARKET)
|
|
||||||
trdswitchown(EF_SHIP, sp, newown);
|
|
||||||
sp->shp_own = newown;
|
|
||||||
sp->shp_mission = 0;
|
|
||||||
sp->shp_fleet = 0;
|
|
||||||
sp->shp_rflags = 0;
|
|
||||||
memset(sp->shp_rpath, 0, sizeof(sp->shp_rpath));
|
|
||||||
pp = &p;
|
|
||||||
lp = &llp;
|
|
||||||
/* Take over planes */
|
|
||||||
snxtitem_cargo(&ni, EF_PLANE, EF_SHIP, sp->shp_uid);
|
|
||||||
while (nxtitem(&ni, pp)) {
|
|
||||||
if (pp->pln_effic > PLANE_MINEFF)
|
|
||||||
pp->pln_effic = PLANE_MINEFF;
|
|
||||||
pp->pln_mobil = 0;
|
|
||||||
if (opt_MOB_ACCESS)
|
|
||||||
game_tick_to_now(&pp->pln_access);
|
|
||||||
if (opt_MARKET)
|
|
||||||
trdswitchown(EF_PLANE, pp, newown);
|
|
||||||
pp->pln_mission = 0;
|
|
||||||
pp->pln_own = newown;
|
|
||||||
putplane(pp->pln_uid, pp);
|
|
||||||
}
|
|
||||||
/* Take over land units */
|
|
||||||
snxtitem_cargo(&ni, EF_LAND, EF_SHIP, sp->shp_uid);
|
|
||||||
while (nxtitem(&ni, lp))
|
|
||||||
takeover_land(lp, newown);
|
|
||||||
putship(sp->shp_uid, sp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
takeover_land(struct lndstr *landp, natid newown)
|
takeover_land(struct lndstr *landp, natid newown)
|
||||||
{
|
{
|
||||||
|
takeover_unit((struct empobj *)landp, newown);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
takeover_unit(struct empobj *unit, natid newown)
|
||||||
|
{
|
||||||
|
struct shpstr *sp;
|
||||||
struct plnstr *pp;
|
struct plnstr *pp;
|
||||||
struct lndstr *lp;
|
struct lndstr *lp;
|
||||||
|
int type;
|
||||||
struct nstr_item ni;
|
struct nstr_item ni;
|
||||||
struct plnstr p;
|
union empobj_storage cargo;
|
||||||
struct lndstr llp;
|
|
||||||
|
|
||||||
if (landp->lnd_effic < LAND_MINEFF) {
|
unit->own = newown;
|
||||||
putland(landp->lnd_uid, landp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
landp->lnd_army = 0;
|
|
||||||
landp->lnd_mobil = 0;
|
|
||||||
if (opt_MOB_ACCESS)
|
|
||||||
game_tick_to_now(&landp->lnd_access);
|
|
||||||
landp->lnd_harden = 0;
|
|
||||||
if (opt_MARKET)
|
if (opt_MARKET)
|
||||||
trdswitchown(EF_LAND, landp, newown);
|
trdswitchown(unit->ef_type, unit, newown);
|
||||||
landp->lnd_mission = 0;
|
unit->group = 0;
|
||||||
landp->lnd_own = newown;
|
unit->mission = 0;
|
||||||
pp = &p;
|
|
||||||
lp = &llp;
|
switch (unit->ef_type) {
|
||||||
/* Take over planes */
|
case EF_SHIP:
|
||||||
snxtitem_cargo(&ni, EF_PLANE, EF_LAND, landp->lnd_uid);
|
sp = (struct shpstr *)unit;
|
||||||
while (nxtitem(&ni, pp)) {
|
sp->shp_rflags = 0;
|
||||||
if (pp->pln_effic > PLANE_MINEFF)
|
memset(sp->shp_rpath, 0, sizeof(sp->shp_rpath));
|
||||||
pp->pln_effic = PLANE_MINEFF;
|
break;
|
||||||
pp->pln_mobil = 0;
|
case EF_PLANE:
|
||||||
if (opt_MOB_ACCESS)
|
pp = (struct plnstr *)unit;
|
||||||
game_tick_to_now(&pp->pln_access);
|
if (pp->pln_mobil > 0)
|
||||||
if (opt_MARKET)
|
pp->pln_mobil = 0;
|
||||||
trdswitchown(EF_PLANE, pp, newown);
|
break;
|
||||||
pp->pln_mission = 0;
|
case EF_LAND:
|
||||||
pp->pln_own = newown;
|
lp = (struct lndstr *)unit;
|
||||||
putplane(pp->pln_uid, pp);
|
if (lp->lnd_mobil > 0)
|
||||||
|
lp->lnd_mobil = 0;
|
||||||
|
lp->lnd_harden = 0;
|
||||||
|
break;
|
||||||
|
case EF_NUKE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
CANT_REACH();
|
||||||
|
}
|
||||||
|
|
||||||
|
put_empobj(unit->ef_type, unit->uid, unit);
|
||||||
|
|
||||||
|
for (type = EF_PLANE; type <= EF_NUKE; type++) {
|
||||||
|
snxtitem_cargo(&ni, type, unit->ef_type, unit->uid);
|
||||||
|
while (nxtitem(&ni, &cargo)) {
|
||||||
|
if (cargo.gen.own == newown)
|
||||||
|
continue;
|
||||||
|
if (type == EF_PLANE)
|
||||||
|
cargo.plane.pln_effic = PLANE_MINEFF;
|
||||||
|
takeover_unit(&cargo.gen, newown);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Take over land units */
|
|
||||||
snxtitem_cargo(&ni, EF_LAND, EF_LAND, landp->lnd_uid);
|
|
||||||
while (nxtitem(&ni, lp))
|
|
||||||
takeover_land(lp, newown);
|
|
||||||
putland(landp->lnd_uid, landp);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue