Rebase of Hvy Metal I final version
Straightforward forward port. Drop the code to reset track on startup. It's not necessary, and it breaks linking of empdump.
This commit is contained in:
parent
abd64835c7
commit
5d0f5e69ee
25 changed files with 349 additions and 25 deletions
|
@ -161,6 +161,8 @@ EMPCF_OPT("INTERDICT_ATT", opt_INTERDICT_ATT,
|
||||||
"Interdict post-attack move in")
|
"Interdict post-attack move in")
|
||||||
EMPCF_OPT("LANDSPIES", opt_LANDSPIES,
|
EMPCF_OPT("LANDSPIES", opt_LANDSPIES,
|
||||||
"Enable the land unit type spies")
|
"Enable the land unit type spies")
|
||||||
|
EMPCF_OPT("LIMBER", opt_LIMBER,
|
||||||
|
"Artillery requires mobility to start firing")
|
||||||
EMPCF_OPT("LOANS", opt_LOANS,
|
EMPCF_OPT("LOANS", opt_LOANS,
|
||||||
"Allow bailing out of other countries via S&L scandals")
|
"Allow bailing out of other countries via S&L scandals")
|
||||||
EMPCF_OPT("LOSE_CONTACT", opt_LOSE_CONTACT,
|
EMPCF_OPT("LOSE_CONTACT", opt_LOSE_CONTACT,
|
||||||
|
@ -179,6 +181,8 @@ EMPCF_OPT("NO_PLAGUE", opt_NO_PLAGUE,
|
||||||
"Disable plague")
|
"Disable plague")
|
||||||
EMPCF_OPT("PINPOINTMISSILE", opt_PINPOINTMISSILE,
|
EMPCF_OPT("PINPOINTMISSILE", opt_PINPOINTMISSILE,
|
||||||
"Enable marine missiles")
|
"Enable marine missiles")
|
||||||
|
EMPCF_OPT("RAILWAYS", opt_RAILWAYS,
|
||||||
|
"Highways double as rail")
|
||||||
EMPCF_OPT("RES_POP", opt_RES_POP,
|
EMPCF_OPT("RES_POP", opt_RES_POP,
|
||||||
"Population is limited by research")
|
"Population is limited by research")
|
||||||
EMPCF_OPT("SAIL", opt_SAIL,
|
EMPCF_OPT("SAIL", opt_SAIL,
|
||||||
|
|
|
@ -190,6 +190,7 @@ extern int lnd_hardtarget(struct lndstr *);
|
||||||
extern int lnd_mar_one_sector(struct emp_qelem *, int, natid, int);
|
extern int lnd_mar_one_sector(struct emp_qelem *, int, natid, int);
|
||||||
extern int lnd_support(natid, natid, coord, coord, int);
|
extern int lnd_support(natid, natid, coord, coord, int);
|
||||||
extern int lnd_can_attack(struct lndstr *);
|
extern int lnd_can_attack(struct lndstr *);
|
||||||
|
extern void lnd_unlimber(struct lndstr *lp);
|
||||||
extern int lnd_fortify (struct lndstr *lp, int hard_amt);
|
extern int lnd_fortify (struct lndstr *lp, int hard_amt);
|
||||||
extern void lnd_set_tech(struct lndstr *, int);
|
extern void lnd_set_tech(struct lndstr *, int);
|
||||||
|
|
||||||
|
|
|
@ -627,6 +627,7 @@ extern void sathead(void);
|
||||||
extern int sct_postread(int, void *);
|
extern int sct_postread(int, void *);
|
||||||
extern int sct_prewrite(int, void *);
|
extern int sct_prewrite(int, void *);
|
||||||
extern void item_prewrite(short *);
|
extern void item_prewrite(short *);
|
||||||
|
extern void set_railway(struct sctstr *);
|
||||||
extern int issector(char *);
|
extern int issector(char *);
|
||||||
/* sectdamage.c */
|
/* sectdamage.c */
|
||||||
extern int sect_damage(struct sctstr *, int);
|
extern int sect_damage(struct sctstr *, int);
|
||||||
|
@ -710,6 +711,7 @@ extern int wu(natid, natid, char *, ...) ATTRIBUTE((format (printf, 3, 4)));
|
||||||
* src/lib/update/ *.c
|
* src/lib/update/ *.c
|
||||||
*/
|
*/
|
||||||
/* age.c */
|
/* age.c */
|
||||||
|
extern int age_people(int, int);
|
||||||
extern void age_levels(int);
|
extern void age_levels(int);
|
||||||
/* anno.c */
|
/* anno.c */
|
||||||
extern void delete_old_announcements(void);
|
extern void delete_old_announcements(void);
|
||||||
|
|
|
@ -76,6 +76,7 @@ struct sctstr {
|
||||||
natid sct_oldown; /* old owner of sector (for liberation) */
|
natid sct_oldown; /* old owner of sector (for liberation) */
|
||||||
unsigned char sct_updated; /* Has this sect been updated? */
|
unsigned char sct_updated; /* Has this sect been updated? */
|
||||||
unsigned char sct_off; /* Should this sector produce? */
|
unsigned char sct_off; /* Should this sector produce? */
|
||||||
|
unsigned char sct_track; /* nearby railways (RAILWAYS) */
|
||||||
short sct_item[I_MAX+1]; /* amount of items stored here */
|
short sct_item[I_MAX+1]; /* amount of items stored here */
|
||||||
short sct_del[I_MAX+1]; /* delivieries */
|
short sct_del[I_MAX+1]; /* delivieries */
|
||||||
short sct_dist[I_MAX+1]; /* distribution thresholds */
|
short sct_dist[I_MAX+1]; /* distribution thresholds */
|
||||||
|
@ -181,6 +182,11 @@ extern struct dchrstr bigcity_dchr;
|
||||||
|
|
||||||
#define FORTEFF 5 /* forts must be 5% efficient to fire. */
|
#define FORTEFF 5 /* forts must be 5% efficient to fire. */
|
||||||
|
|
||||||
|
/* Can trains enter sector SP? */
|
||||||
|
#define SCT_HAS_RAIL(sp) \
|
||||||
|
(opt_RAILWAYS ? (sp)->sct_track != 0 \
|
||||||
|
: intrchr[INT_RAIL].in_enable && (sp)->sct_rail != 0)
|
||||||
|
|
||||||
#define MOB_MOVE 0
|
#define MOB_MOVE 0
|
||||||
#define MOB_MARCH 1
|
#define MOB_MARCH 1
|
||||||
#define MOB_RAIL 2
|
#define MOB_RAIL 2
|
||||||
|
|
97
info/Hvy-Metal.t
Normal file
97
info/Hvy-Metal.t
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
.TH Concept "Hvy-Metal"
|
||||||
|
.NA Hvy-Metal "Special rules for Hvy Metal"
|
||||||
|
.LV Basic
|
||||||
|
.s1
|
||||||
|
Ship types are customized. Better check show for the details.
|
||||||
|
.s1
|
||||||
|
Dreadnoughts are more heavily armored. Frigates are more fragile.
|
||||||
|
.s1
|
||||||
|
More ships can carry choppers, and jf2 count as choppers. Some ships
|
||||||
|
are not ideal for this, and this is reflected by the lack of large
|
||||||
|
petrol and shell storage. But it gives players yet another
|
||||||
|
interesting avenue to explore, and reflects the ships better. Also
|
||||||
|
helps simulate irregular forces desperately equipping what they can for
|
||||||
|
a role. A chance for a creative player to spring surprises.
|
||||||
|
.s1
|
||||||
|
New assault ship type: Think Tarawa or Io Jima class ships. These put
|
||||||
|
the ASSAULT back into landings. Huge mil capacity, can operate
|
||||||
|
choppers and Harriers. Able to drop 12 marine units and a horde of
|
||||||
|
mil onto a shore, or sustain para drops and air strikes inland with
|
||||||
|
its aircraft. Go ashore in a hurry, Big Time. A fat target too, so
|
||||||
|
guard it carefully.
|
||||||
|
.s1
|
||||||
|
Land unit types are heavily customized. Better check show for the
|
||||||
|
details. Non-mechanized units are slower and more vulnerable,
|
||||||
|
infantry units have capability security, marines have amtraks,
|
||||||
|
artilley firing ranges differ, few units are light (but troop
|
||||||
|
transports and landing ships can carry non-light units), food
|
||||||
|
capacities are reduced.
|
||||||
|
.s1
|
||||||
|
Tanks and AAA can fire. \*QHey guys, why don't we shoot this big gun
|
||||||
|
on this tank at those d*mn elves on that hill instead of hanging our
|
||||||
|
laundry on it\*U? Don't expect the range of an artillery unit, which
|
||||||
|
specializes in this and has forward observers built in to the unit
|
||||||
|
cost. Watch your magazines too!
|
||||||
|
.s1
|
||||||
|
Artillery units with capability heavy can only fire at sectors and
|
||||||
|
fire offensive support. They can't target ships, return fire,
|
||||||
|
interdict, or fire defensive support.
|
||||||
|
.s1
|
||||||
|
Artillery units in mountains receive a range bonus of +0.5.
|
||||||
|
.s1
|
||||||
|
New experimental option RAILWAYS is enabled: trains run on highways
|
||||||
|
and sectors next to highways. Use sinfra to find out mobility costs.
|
||||||
|
Try sect # ?track>0 to visualize your track. Check \*Qinfo
|
||||||
|
Railroad\*U for details.
|
||||||
|
.s1
|
||||||
|
There are more train types, BIG siege guns, etc. And we got the
|
||||||
|
Mother Of All Guns: something like what was attempted a few times in
|
||||||
|
history, a huge costly gun with incredible range. It CAN be moved.
|
||||||
|
Slowly. Has all the problems fixed positions have. If these are not
|
||||||
|
obvious, any experienced player will gladly demonstrate them for you.
|
||||||
|
.s1
|
||||||
|
Infrastructure is disabled.
|
||||||
|
.s1
|
||||||
|
New experimental option LIMBER is enabled: slow guns and heavy railway
|
||||||
|
guns use mobility to unlimber. Limbering and unlimbering is
|
||||||
|
completely automatic. See info \*QUnit-types\*U for details.
|
||||||
|
.s1
|
||||||
|
Planes are tweaked somewhat. show is your friend.
|
||||||
|
.s1
|
||||||
|
Che age just like military reserves: 1% decay per 24 ETUs. In
|
||||||
|
sufficiently loyal sectors you don't own, however, a full half of them
|
||||||
|
(rounded up) vanish each update. The anti command is disabled.
|
||||||
|
.s1
|
||||||
|
Mountains, fortresses and cities provide a respectable defensive
|
||||||
|
bonus. Cities cost real money to build. Banks need construction
|
||||||
|
materials to build efficiency. Ever seen Fort Knox? Bridges are
|
||||||
|
cheaper than usual.
|
||||||
|
.s1
|
||||||
|
Food is much harder to grow. Expect 20% of your population to be
|
||||||
|
farmers.
|
||||||
|
.s1
|
||||||
|
Natural resources gold, oil and uran deplete much slower than usual.
|
||||||
|
Fully depleting a sector will take you several updates. Oil
|
||||||
|
production does not depend on tech; you don't have to micro-manage to
|
||||||
|
conserve oil. Resources are scarce. Expect to fight over them.
|
||||||
|
.s1
|
||||||
|
Oil derricks need to set up shop before they produce: no production
|
||||||
|
while mobility is below maximum.
|
||||||
|
.s1
|
||||||
|
New experimental option AUTO_POWER is enabled: the power report is
|
||||||
|
only updated automatically, at the update. No more tactical abuse.
|
||||||
|
.s1
|
||||||
|
Missed updates due to server problems will be forced if caught within
|
||||||
|
15 minutes of planned update time or skipped otherwise.
|
||||||
|
.s1
|
||||||
|
Everything you do in this game is logged by the deities for their own
|
||||||
|
nefarious purposes. However, the logs are treated confidentially.
|
||||||
|
.s1
|
||||||
|
Make the deities laugh and get up to 5 gold bars. 5 bars per week up
|
||||||
|
for grabs.
|
||||||
|
.s1
|
||||||
|
Source code and configuration is available from
|
||||||
|
.br
|
||||||
|
http://www.stdio.com/~rhyatt/empire/hvy_metal/
|
||||||
|
.s1
|
||||||
|
.SA "Introduction, Server"
|
|
@ -48,6 +48,11 @@ TECH_POP: Technology costs more to make as your civilian population
|
||||||
grows past 50,000 civilians.
|
grows past 50,000 civilians.
|
||||||
TREATIES: Sign treaties with your friends and enemies, and breaking of
|
TREATIES: Sign treaties with your friends and enemies, and breaking of
|
||||||
them is reported in the news.
|
them is reported in the news.
|
||||||
|
|
||||||
|
The following options are new in Hvy Metal:
|
||||||
|
|
||||||
|
LIMBER Artillery requires mobility to start firing
|
||||||
|
RAILWAYS Highways double as rail
|
||||||
.fi
|
.fi
|
||||||
|
|
||||||
.SA "Hidden, Server, version"
|
.SA "Hidden, Server, version"
|
||||||
|
|
25
info/Railroad.t
Normal file
25
info/Railroad.t
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
.TH Concept "Railroad"
|
||||||
|
.NA Railroad "How railroads work"
|
||||||
|
.LV Expert
|
||||||
|
Trains are land units with capability \*Qtrain\*U.
|
||||||
|
.s1
|
||||||
|
Unlike other units, trains can enter a sector only if it has
|
||||||
|
(operational) railroad track.
|
||||||
|
.s1
|
||||||
|
If option RAILWAYS is disabled, a sector has railroad track as long as
|
||||||
|
its rail infrastructure efficiency is non-zero. Train mobility cost
|
||||||
|
depends on rail infrastructure efficiency (see \*Qinfo Mobility\*U).
|
||||||
|
Spy reports show the rail infrastructure efficiency in colum \*Qrl
|
||||||
|
eff\*U.
|
||||||
|
.s1
|
||||||
|
If option RAILWAYS is enabled, all highway-like sectors are railways,
|
||||||
|
and the track is operational as long as the sector is at least 5%
|
||||||
|
efficient. A sector is highway-like if its mobility cost at 100% is
|
||||||
|
zero (column mob cost in \*Qshow sect s\*u). Operational railways
|
||||||
|
additionally extend track into adjacent sectors that are at least 60%
|
||||||
|
efficient. Sector selector track gives the number of operational
|
||||||
|
railways within one sector range. This number is also shown by spy
|
||||||
|
report column \*Qrl eff\*U. To visualize your railway network, try
|
||||||
|
\*Qsect # ?track#0\*U.
|
||||||
|
.s1
|
||||||
|
.SA "LandUnits"
|
|
@ -163,6 +163,15 @@ The number of extra-light planes the land unit can carry.
|
||||||
The number of land units the unit can carry (no 'heavy' units)
|
The number of land units the unit can carry (no 'heavy' units)
|
||||||
.in
|
.in
|
||||||
.s1
|
.s1
|
||||||
|
If option LIMBER is enabled, guns need to be \*Qlimbered\*U to march
|
||||||
|
and \*Qunlimbered\*U to fire or fortify. Limbering and unlimbering is
|
||||||
|
completely automatic. Limbering is free, but unlimbering can cost
|
||||||
|
mobility, depending on the type of artillery unit: heavy railway
|
||||||
|
artillery and any artillery with a speed below 22 pay unlimber
|
||||||
|
mobility equivalent to a march with path cost 0.2, plus 1. This gains
|
||||||
|
one point of fortification. Presence of engineer units in the same
|
||||||
|
sector cut the cost by a third.
|
||||||
|
.s1
|
||||||
Each land unit can carry a certain amount of products and has certain
|
Each land unit can carry a certain amount of products and has certain
|
||||||
capabilities. These are listed under the cargoes & abilities section.
|
capabilities. These are listed under the cargoes & abilities section.
|
||||||
The cargoes give the number of each product that can be carried.
|
The cargoes give the number of each product that can be carried.
|
||||||
|
@ -196,6 +205,7 @@ the unit can fire 'general unit flak' (see "info Flak")
|
||||||
the unit is a spy
|
the unit is a spy
|
||||||
.L train
|
.L train
|
||||||
the unit is a train, and can't be loaded on land units
|
the unit is a train, and can't be loaded on land units
|
||||||
|
(see "info Railroad")
|
||||||
.L heavy
|
.L heavy
|
||||||
the unit cannot be carried on land units or ships, not even supply ships
|
the unit cannot be carried on land units or ships, not even supply ships
|
||||||
.in
|
.in
|
||||||
|
@ -238,4 +248,3 @@ marines 1 5f 10s xlight light marine
|
||||||
.FI
|
.FI
|
||||||
.s1
|
.s1
|
||||||
.SA "land, LandUnits"
|
.SA "land, LandUnits"
|
||||||
|
|
||||||
|
|
|
@ -330,6 +330,12 @@ multifire(void)
|
||||||
pr("Unit %d cannot fire!\n", fland.lnd_uid);
|
pr("Unit %d cannot fire!\n", fland.lnd_uid);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (lchr[(int)fland.lnd_type].l_flags & L_HEAVY
|
||||||
|
&& target != targ_land) {
|
||||||
|
pr("%s is too ponderous to target ships!\n",
|
||||||
|
prland(&fland));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (fland.lnd_item[I_GUN] == 0) {
|
if (fland.lnd_item[I_GUN] == 0) {
|
||||||
pr("%s -- not enough guns\n", prland(&fland));
|
pr("%s -- not enough guns\n", prland(&fland));
|
||||||
continue;
|
continue;
|
||||||
|
@ -349,6 +355,8 @@ multifire(void)
|
||||||
pr("Klick! ...\n");
|
pr("Klick! ...\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lnd_unlimber(&fland);
|
||||||
if (target == targ_ship) {
|
if (target == targ_ship) {
|
||||||
if (chance(lnd_acc(&fland) / 100.0))
|
if (chance(lnd_acc(&fland) / 100.0))
|
||||||
dam = ldround(dam / 2.0, 1);
|
dam = ldround(dam / 2.0, 1);
|
||||||
|
@ -687,6 +695,9 @@ quiet_bigdef(int type, struct emp_qelem *list, natid own, natid aown,
|
||||||
/* Don't shoot yourself */
|
/* Don't shoot yourself */
|
||||||
if (land.lnd_own == aown)
|
if (land.lnd_own == aown)
|
||||||
continue;
|
continue;
|
||||||
|
/* Too ponderous for counter-battery fire */
|
||||||
|
if (lchr[(int)land.lnd_type].l_flags & L_HEAVY)
|
||||||
|
continue;
|
||||||
|
|
||||||
rel = getrel(getnatp(land.lnd_own), own);
|
rel = getrel(getnatp(land.lnd_own), own);
|
||||||
rel2 = getrel(getnatp(land.lnd_own), aown);
|
rel2 = getrel(getnatp(land.lnd_own), aown);
|
||||||
|
@ -708,6 +719,7 @@ quiet_bigdef(int type, struct emp_qelem *list, natid own, natid aown,
|
||||||
if (dam2 < 0)
|
if (dam2 < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
lnd_unlimber(&land);
|
||||||
(*nfiring)++;
|
(*nfiring)++;
|
||||||
if (!fp)
|
if (!fp)
|
||||||
add_to_flist(list, (struct empobj *)&land, dam2, 0);
|
add_to_flist(list, (struct empobj *)&land, dam2, 0);
|
||||||
|
|
|
@ -226,11 +226,16 @@ mission(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mission == MI_INTERDICT) && (type == EF_LAND))
|
if ((mission == MI_INTERDICT) && (type == EF_LAND)) {
|
||||||
if (lchr[(int)gp->type].l_dam == 0) {
|
if (lchr[(int)gp->type].l_dam == 0) {
|
||||||
pr("%s: cannot fire at range!\n", obj_nameof(gp));
|
pr("%s: cannot fire at range!\n", obj_nameof(gp));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (lchr[(int)gp->type].l_flags & L_HEAVY) {
|
||||||
|
pr("%s: too ponderous to interdict!\n", obj_nameof(gp));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((mission == MI_INTERDICT) && (type == EF_PLANE)) {
|
if ((mission == MI_INTERDICT) && (type == EF_PLANE)) {
|
||||||
struct plchrstr *pcp;
|
struct plchrstr *pcp;
|
||||||
|
|
|
@ -73,7 +73,10 @@ sinfra(void)
|
||||||
pr("%4d%% ", sect.sct_effic);
|
pr("%4d%% ", sect.sct_effic);
|
||||||
pr("%4d%% ", sect.sct_road);
|
pr("%4d%% ", sect.sct_road);
|
||||||
prmobcost(§, MOB_MOVE);
|
prmobcost(§, MOB_MOVE);
|
||||||
pr("%4d%% ", sect.sct_rail);
|
if (opt_RAILWAYS)
|
||||||
|
pr(sect.sct_track ? " yes " : " no ");
|
||||||
|
else
|
||||||
|
pr("%4d%% ", sect.sct_rail);
|
||||||
prmobcost(§, MOB_RAIL);
|
prmobcost(§, MOB_RAIL);
|
||||||
pr("%4d%% ", SCT_DEFENSE(§));
|
pr("%4d%% ", SCT_DEFENSE(§));
|
||||||
pr("%5.2f\n", sector_strength(§));
|
pr("%5.2f\n", sector_strength(§));
|
||||||
|
|
|
@ -224,7 +224,7 @@ spyline(struct sctstr *sp)
|
||||||
sp->sct_oldown,
|
sp->sct_oldown,
|
||||||
roundintby((int)sp->sct_effic, 10),
|
roundintby((int)sp->sct_effic, 10),
|
||||||
roundintby((int)sp->sct_road, 10),
|
roundintby((int)sp->sct_road, 10),
|
||||||
roundintby((int)sp->sct_rail, 10),
|
opt_RAILWAYS ? !!sp->sct_track : roundintby(sp->sct_rail, 10),
|
||||||
roundintby((int)sp->sct_defense, 10),
|
roundintby((int)sp->sct_defense, 10),
|
||||||
roundintby(sp->sct_item[I_CIVIL], 10),
|
roundintby(sp->sct_item[I_CIVIL], 10),
|
||||||
roundintby(sp->sct_item[I_MILIT], 10),
|
roundintby(sp->sct_item[I_MILIT], 10),
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "nat.h"
|
#include "nat.h"
|
||||||
|
#include "optlist.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "sect.h"
|
#include "sect.h"
|
||||||
#include "xy.h"
|
#include "xy.h"
|
||||||
|
@ -48,6 +49,12 @@ sector_mcost(struct sctstr *sp, int mobtype)
|
||||||
if (base < 0)
|
if (base < 0)
|
||||||
return -1.0;
|
return -1.0;
|
||||||
|
|
||||||
|
if (mobtype == MOB_RAIL && opt_RAILWAYS) {
|
||||||
|
if (!SCT_HAS_RAIL(sp))
|
||||||
|
return -1;
|
||||||
|
mobtype = MOB_MARCH;
|
||||||
|
}
|
||||||
|
|
||||||
/* linear function in eff, d_mob0 at 0%, d_mob1 at 100% */
|
/* linear function in eff, d_mob0 at 0%, d_mob1 at 100% */
|
||||||
base += (dchr[sp->sct_type].d_mob1 - base) * sp->sct_effic / 100;
|
base += (dchr[sp->sct_type].d_mob1 - base) * sp->sct_effic / 100;
|
||||||
if (CANT_HAPPEN(base < 0))
|
if (CANT_HAPPEN(base < 0))
|
||||||
|
|
|
@ -218,8 +218,7 @@ bp_neighbors(struct as_coord c, struct as_coord *cp, void *pp)
|
||||||
move through it. We calculate it later. */
|
move through it. We calculate it later. */
|
||||||
if (dchr[sp->sct_type].d_mob0 < 0)
|
if (dchr[sp->sct_type].d_mob0 < 0)
|
||||||
continue;
|
continue;
|
||||||
if (bp->bp_mobtype == MOB_RAIL
|
if (bp->bp_mobtype == MOB_RAIL && !SCT_HAS_RAIL(sp))
|
||||||
&& (!intrchr[INT_RAIL].in_enable || sp->sct_rail == 0))
|
|
||||||
continue;
|
continue;
|
||||||
if (sp->sct_own != from->sct_own)
|
if (sp->sct_own != from->sct_own)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -153,6 +153,7 @@ struct castr sect_ca[] = {
|
||||||
{"uran", fldoff(sct_uran), NSC_UCHAR, 0, NULL, EF_BAD, 0},
|
{"uran", fldoff(sct_uran), NSC_UCHAR, 0, NULL, EF_BAD, 0},
|
||||||
{"oldown", fldoff(sct_oldown), NSC_NATID, 0, NULL, EF_NATION, 0},
|
{"oldown", fldoff(sct_oldown), NSC_NATID, 0, NULL, EF_NATION, 0},
|
||||||
{"off", fldoff(sct_off), NSC_UCHAR, 0, NULL, EF_BAD, 0},
|
{"off", fldoff(sct_off), NSC_UCHAR, 0, NULL, EF_BAD, 0},
|
||||||
|
{"track", fldoff(sct_track), NSC_UCHAR, 0, NULL, EF_BAD, NSC_EXTRA},
|
||||||
NSC_IVEC(fldoff(sct_item), ""),
|
NSC_IVEC(fldoff(sct_item), ""),
|
||||||
NSC_IVEC(fldoff(sct_dist), "_dist"),
|
NSC_IVEC(fldoff(sct_dist), "_dist"),
|
||||||
NSC_IVEC(fldoff(sct_del), "_del"),
|
NSC_IVEC(fldoff(sct_del), "_del"),
|
||||||
|
|
|
@ -49,6 +49,7 @@ int opt_GUINEA_PIGS = 0;
|
||||||
int opt_HIDDEN = 0;
|
int opt_HIDDEN = 0;
|
||||||
int opt_INTERDICT_ATT = 1;
|
int opt_INTERDICT_ATT = 1;
|
||||||
int opt_LANDSPIES = 1;
|
int opt_LANDSPIES = 1;
|
||||||
|
int opt_LIMBER = 0;
|
||||||
int opt_LOANS = 1;
|
int opt_LOANS = 1;
|
||||||
int opt_LOSE_CONTACT = 0;
|
int opt_LOSE_CONTACT = 0;
|
||||||
int opt_MARKET = 0;
|
int opt_MARKET = 0;
|
||||||
|
@ -58,6 +59,7 @@ int opt_NOMOBCOST = 1;
|
||||||
int opt_NO_FORT_FIRE = 0;
|
int opt_NO_FORT_FIRE = 0;
|
||||||
int opt_NO_PLAGUE = 1;
|
int opt_NO_PLAGUE = 1;
|
||||||
int opt_PINPOINTMISSILE = 1;
|
int opt_PINPOINTMISSILE = 1;
|
||||||
|
int opt_RAILWAYS = 0;
|
||||||
int opt_RES_POP = 0;
|
int opt_RES_POP = 0;
|
||||||
int opt_SAIL = 1;
|
int opt_SAIL = 1;
|
||||||
int opt_SHOWPLANE = 1;
|
int opt_SHOWPLANE = 1;
|
||||||
|
|
|
@ -287,7 +287,11 @@ shp_torp_hitchance(struct shpstr *sp, int range)
|
||||||
double
|
double
|
||||||
lnd_fire_range(struct lndstr *lp)
|
lnd_fire_range(struct lndstr *lp)
|
||||||
{
|
{
|
||||||
return effrange(lnd_frg(lp), lp->lnd_tech);
|
struct sctstr sect;
|
||||||
|
|
||||||
|
getsect(lp->lnd_x, lp->lnd_y, §);
|
||||||
|
return effrange(lnd_frg(lp), lp->lnd_tech)
|
||||||
|
+ (sect.sct_type == SCT_MOUNT ? 0.5 : 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -991,7 +991,7 @@ lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((!intrchr[INT_RAIL].in_enable || sect.sct_rail == 0)
|
if (!SCT_HAS_RAIL(§)
|
||||||
&& lnd_mobtype(&llp->unit.land) == MOB_RAIL) {
|
&& lnd_mobtype(&llp->unit.land) == MOB_RAIL) {
|
||||||
if (together) {
|
if (together) {
|
||||||
pr("no rail system in %s\n", xyas(newx, newy, actor));
|
pr("no rail system in %s\n", xyas(newx, newy, actor));
|
||||||
|
@ -1126,6 +1126,9 @@ lnd_support(natid victim, natid attacker, coord x, coord y, int defending)
|
||||||
while (nxtitem(&ni, &land)) {
|
while (nxtitem(&ni, &land)) {
|
||||||
if ((land.lnd_x == x) && (land.lnd_y == y))
|
if ((land.lnd_x == x) && (land.lnd_y == y))
|
||||||
continue;
|
continue;
|
||||||
|
/* Too ponderous for defensive support */
|
||||||
|
if (defending && (lchr[(int)land.lnd_type].l_flags & L_HEAVY))
|
||||||
|
continue;
|
||||||
rel = getrel(getnatp(land.lnd_own), attacker);
|
rel = getrel(getnatp(land.lnd_own), attacker);
|
||||||
rel2 = getrel(getnatp(land.lnd_own), victim);
|
rel2 = getrel(getnatp(land.lnd_own), victim);
|
||||||
if ((land.lnd_own != attacker) &&
|
if ((land.lnd_own != attacker) &&
|
||||||
|
@ -1144,6 +1147,7 @@ lnd_support(natid victim, natid attacker, coord x, coord y, int defending)
|
||||||
if (dam2 < 0)
|
if (dam2 < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
lnd_unlimber(&land);
|
||||||
if (defending)
|
if (defending)
|
||||||
nreport(land.lnd_own, N_FIRE_BACK, victim, 1);
|
nreport(land.lnd_own, N_FIRE_BACK, victim, 1);
|
||||||
else
|
else
|
||||||
|
@ -1170,31 +1174,81 @@ lnd_can_attack(struct lndstr *lp)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return mobility required to unlimber LP.
|
||||||
|
*/
|
||||||
|
static double
|
||||||
|
lnd_mob_to_unlimber(struct lndstr *lp)
|
||||||
|
{
|
||||||
|
struct lchrstr *lcp = &lchr[(int)lp->lnd_type];
|
||||||
|
|
||||||
|
if (!opt_LIMBER || lcp->l_dam == 0 || lp->lnd_harden != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (lnd_spd(lp) < 22
|
||||||
|
|| (lcp->l_flags & (L_HEAVY | L_TRAIN)) == (L_HEAVY | L_TRAIN)) {
|
||||||
|
/*
|
||||||
|
* Slow artillery is towed and needs to be unlimbered.
|
||||||
|
* Heavy railway guns need to be assembled.
|
||||||
|
*/
|
||||||
|
return lnd_pathcost(lp, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unlimber land unit LP.
|
||||||
|
* No effect unless LP is limbered artillery.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
lnd_unlimber(struct lndstr *lp)
|
||||||
|
{
|
||||||
|
double unlimber_mob, mult, newmob;
|
||||||
|
|
||||||
|
unlimber_mob = lnd_mob_to_unlimber(lp);
|
||||||
|
if (unlimber_mob == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mult = has_helpful_engineer(lp->lnd_x, lp->lnd_y, lp->lnd_own)
|
||||||
|
? 1.5 : 1.0;
|
||||||
|
newmob = lp->lnd_mobil - (1 + unlimber_mob) / mult;
|
||||||
|
lp->lnd_mobil = (signed char)MAX(-127, floor(newmob));
|
||||||
|
CANT_HAPPEN(lp->lnd_harden != 0);
|
||||||
|
lp->lnd_harden = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Increase fortification value of LP.
|
* Increase fortification value of LP.
|
||||||
* Fortification costs mobility. Use up to MOB mobility.
|
* Fortification costs mobility. Use up to MOB mobility.
|
||||||
|
* Automatically unlimbers.
|
||||||
* Return actual fortification increase.
|
* Return actual fortification increase.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lnd_fortify(struct lndstr *lp, int mob)
|
lnd_fortify(struct lndstr *lp, int mob)
|
||||||
{
|
{
|
||||||
int hard_amt;
|
int hard_amt;
|
||||||
double mob_used, mult;
|
double mob_used, unlimber_mob, mult;
|
||||||
|
|
||||||
if (lp->lnd_ship >= 0 || lp->lnd_land >= 0)
|
if (lp->lnd_ship >= 0 || lp->lnd_land >= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mob_used = MIN(lp->lnd_mobil, mob);
|
mob_used = MIN(lp->lnd_mobil, mob);
|
||||||
if (mob_used < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
mult = has_helpful_engineer(lp->lnd_x, lp->lnd_y, lp->lnd_own)
|
mult = has_helpful_engineer(lp->lnd_x, lp->lnd_y, lp->lnd_own)
|
||||||
? 1.5 : 1.0;
|
? 1.5 : 1.0;
|
||||||
|
unlimber_mob = lnd_mob_to_unlimber(lp);
|
||||||
|
|
||||||
|
hard_amt = (int)(mob_used * mult - unlimber_mob);
|
||||||
|
if (hard_amt < 1)
|
||||||
|
/*
|
||||||
|
* FIXME unlimber_mob > land_mob_max breaks fortify command
|
||||||
|
* FIXME > etu_per_update * land_mob_scale breaks auto-fort. at update
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
|
||||||
hard_amt = (int)(mob_used * mult);
|
|
||||||
if (lp->lnd_harden + hard_amt > land_mob_max) {
|
if (lp->lnd_harden + hard_amt > land_mob_max) {
|
||||||
hard_amt = land_mob_max - lp->lnd_harden;
|
hard_amt = land_mob_max - lp->lnd_harden;
|
||||||
mob_used = ceil(hard_amt / mult);
|
mob_used = ceil((hard_amt + unlimber_mob) / mult);
|
||||||
}
|
}
|
||||||
|
|
||||||
lp->lnd_mobil -= (int)mob_used;
|
lp->lnd_mobil -= (int)mob_used;
|
||||||
|
|
|
@ -436,6 +436,10 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
|
||||||
(md > land_max_interdiction_range))
|
(md > land_max_interdiction_range))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Too ponderous for interdiction fire */
|
||||||
|
if (lchr[(int)lp->lnd_type].l_flags & L_HEAVY)
|
||||||
|
continue;
|
||||||
|
|
||||||
range = roundrange(lnd_fire_range(lp));
|
range = roundrange(lnd_fire_range(lp));
|
||||||
if (md > range)
|
if (md > range)
|
||||||
continue;
|
continue;
|
||||||
|
@ -445,6 +449,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
|
||||||
if (dam2 < 0)
|
if (dam2 < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
lnd_unlimber(lp);
|
||||||
if (sect.sct_type == SCT_WATER) {
|
if (sect.sct_type == SCT_WATER) {
|
||||||
if (chance(lnd_acc(lp) / 100.0))
|
if (chance(lnd_acc(lp) / 100.0))
|
||||||
dam2 = ldround(dam2 / 2.0, 1);
|
dam2 = ldround(dam2 / 2.0, 1);
|
||||||
|
|
|
@ -285,7 +285,7 @@ satdisp_sect(struct sctstr *sp, int acc)
|
||||||
dchr[sp->sct_type].d_mnem,
|
dchr[sp->sct_type].d_mnem,
|
||||||
sp->sct_own, roundintby((int)sp->sct_effic, acc / 2),
|
sp->sct_own, roundintby((int)sp->sct_effic, acc / 2),
|
||||||
roundintby((int)sp->sct_road, acc / 2),
|
roundintby((int)sp->sct_road, acc / 2),
|
||||||
roundintby((int)sp->sct_rail, acc / 2),
|
opt_RAILWAYS ? !!sp->sct_track : roundintby(sp->sct_rail, acc / 2),
|
||||||
roundintby((int)sp->sct_defense, acc / 2),
|
roundintby((int)sp->sct_defense, acc / 2),
|
||||||
roundintby(sp->sct_item[I_CIVIL], acc),
|
roundintby(sp->sct_item[I_CIVIL], acc),
|
||||||
roundintby(sp->sct_item[I_MILIT], acc),
|
roundintby(sp->sct_item[I_MILIT], acc),
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "nat.h"
|
#include "nat.h"
|
||||||
#include "nsc.h"
|
#include "nsc.h"
|
||||||
#include "optlist.h"
|
#include "optlist.h"
|
||||||
|
#include "path.h"
|
||||||
#include "plane.h"
|
#include "plane.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
#include "xy.h"
|
#include "xy.h"
|
||||||
|
|
||||||
static int checksect(struct sctstr *);
|
static int checksect(struct sctstr *);
|
||||||
|
static void update_railway(struct sctstr *, struct sctstr *);
|
||||||
|
|
||||||
int
|
int
|
||||||
sct_postread(int id, void *ptr)
|
sct_postread(int id, void *ptr)
|
||||||
|
@ -71,6 +73,8 @@ sct_prewrite(int id, void *ptr)
|
||||||
bridge_damaged(sp);
|
bridge_damaged(sp);
|
||||||
checksect(sp);
|
checksect(sp);
|
||||||
getsect(sp->sct_x, sp->sct_y, §);
|
getsect(sp->sct_x, sp->sct_y, §);
|
||||||
|
if (opt_RAILWAYS)
|
||||||
|
update_railway(sp, §);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +132,69 @@ checksect(struct sctstr *sp)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Minimal efficiency for railway and railway extension (opt_RAILWAYS) */
|
||||||
|
#define SCT_RAIL_EFF 5
|
||||||
|
#define SCT_RAIL_EXT_EFF 60
|
||||||
|
|
||||||
|
/* Is sector SP a railway? */
|
||||||
|
#define SCT_IS_RAILWAY(sp) \
|
||||||
|
(dchr[(sp)->sct_type].d_mob1 == 0 && (sp)->sct_effic >= SCT_RAIL_EFF)
|
||||||
|
/* May sector SP have a railway extension? */
|
||||||
|
#define SCT_MAY_HAVE_RAIL_EXT(sp) \
|
||||||
|
((sp)->sct_effic >= SCT_RAIL_EXT_EFF)
|
||||||
|
/* Does railway sector SP extend railway track into sector TOSP? */
|
||||||
|
#define SCT_EXTENDS_RAIL(sp, tosp) \
|
||||||
|
((sp)->sct_own == (tosp)->sct_own && SCT_MAY_HAVE_RAIL_EXT(tosp))
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_railway(struct sctstr *sp, struct sctstr *oldsp)
|
||||||
|
{
|
||||||
|
struct sctstr sect;
|
||||||
|
int was_railway = SCT_IS_RAILWAY(oldsp);
|
||||||
|
int is_railway = SCT_IS_RAILWAY(sp);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (was_railway == is_railway
|
||||||
|
&& sp->sct_own == oldsp->sct_own
|
||||||
|
&& SCT_MAY_HAVE_RAIL_EXT(sp) == SCT_MAY_HAVE_RAIL_EXT(oldsp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (was_railway)
|
||||||
|
sp->sct_track--;
|
||||||
|
if (is_railway)
|
||||||
|
sp->sct_track++;
|
||||||
|
|
||||||
|
for (i = DIR_FIRST; i <= DIR_LAST; i++) {
|
||||||
|
getsect(sp->sct_x + diroff[i][0],
|
||||||
|
sp->sct_y + diroff[i][1],
|
||||||
|
§);
|
||||||
|
if (SCT_IS_RAILWAY(§) && SCT_EXTENDS_RAIL(§, oldsp))
|
||||||
|
sp->sct_track--;
|
||||||
|
if (SCT_IS_RAILWAY(§) && SCT_EXTENDS_RAIL(§, sp))
|
||||||
|
sp->sct_track++;
|
||||||
|
if (was_railway && SCT_EXTENDS_RAIL(oldsp, §))
|
||||||
|
sect.sct_track--;
|
||||||
|
if (is_railway && SCT_EXTENDS_RAIL(sp, §))
|
||||||
|
sect.sct_track++;
|
||||||
|
putsect(§);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_railway(struct sctstr *sp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct sctstr *nsp;
|
||||||
|
|
||||||
|
sp->sct_track = !!SCT_IS_RAILWAY(sp);
|
||||||
|
for (i = DIR_FIRST; i <= DIR_LAST; i++) {
|
||||||
|
nsp = getsectp(sp->sct_x + diroff[i][0],
|
||||||
|
sp->sct_y + diroff[i][1]);
|
||||||
|
if (SCT_IS_RAILWAY(nsp) && SCT_EXTENDS_RAIL(nsp, sp))
|
||||||
|
sp->sct_track++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
issector(char *arg)
|
issector(char *arg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,13 @@
|
||||||
|
|
||||||
#include "update.h"
|
#include "update.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
age_people(int n, int etu)
|
||||||
|
{
|
||||||
|
/* age by 1% per 24 etus */
|
||||||
|
return roundavg(n * (1.0 - etu / 2400.0));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
age_levels(int etu)
|
age_levels(int etu)
|
||||||
{
|
{
|
||||||
|
@ -43,7 +50,6 @@ age_levels(int etu)
|
||||||
int i;
|
int i;
|
||||||
double level;
|
double level;
|
||||||
double delta;
|
double delta;
|
||||||
int deltares;
|
|
||||||
|
|
||||||
best_tech = 0.0;
|
best_tech = 0.0;
|
||||||
best_res = 0.0;
|
best_res = 0.0;
|
||||||
|
@ -61,14 +67,7 @@ age_levels(int etu)
|
||||||
delta = np->nat_level[NAT_TLEV] * etu / (100 * level_age_rate);
|
delta = np->nat_level[NAT_TLEV] * etu / (100 * level_age_rate);
|
||||||
np->nat_level[NAT_TLEV] -= delta;
|
np->nat_level[NAT_TLEV] -= delta;
|
||||||
}
|
}
|
||||||
/*
|
np->nat_reserve = age_people(np->nat_reserve, etu);
|
||||||
* age reserves by 1% per every 24 etus
|
|
||||||
*/
|
|
||||||
deltares = -roundavg(np->nat_reserve * etu / 2400.0);
|
|
||||||
if (deltares != 0)
|
|
||||||
np->nat_reserve += deltares;
|
|
||||||
/* Chad Zabel - above number is negative ( was a -= there
|
|
||||||
which was wrong. */
|
|
||||||
}
|
}
|
||||||
best_tech /= 5;
|
best_tech /= 5;
|
||||||
best_res /= 5;
|
best_res /= 5;
|
||||||
|
|
|
@ -87,6 +87,11 @@ finish_sects(int etu)
|
||||||
/* Wipe it clean */
|
/* Wipe it clean */
|
||||||
memset(g_distptrs, 0, WORLD_SZ() * sizeof(*g_distptrs));
|
memset(g_distptrs, 0, WORLD_SZ() * sizeof(*g_distptrs));
|
||||||
|
|
||||||
|
if (opt_RAILWAYS) {
|
||||||
|
for (n = 0; NULL != (sp = getsectid(n)); n++)
|
||||||
|
set_railway(sp);
|
||||||
|
}
|
||||||
|
|
||||||
logerror("delivering...\n");
|
logerror("delivering...\n");
|
||||||
/* Do deliveries */
|
/* Do deliveries */
|
||||||
for (n = 0; NULL != (sp = getsectid(n)); n++) {
|
for (n = 0; NULL != (sp = getsectid(n)); n++) {
|
||||||
|
|
|
@ -109,6 +109,17 @@ do_feed(struct sctstr *sp, struct natstr *np, short *vec,
|
||||||
if (!player->simulation)
|
if (!player->simulation)
|
||||||
sp->sct_work = sctwork;
|
sp->sct_work = sctwork;
|
||||||
grow_people(sp, etu, np, &work_avail, sctwork, vec);
|
grow_people(sp, etu, np, &work_avail, sctwork, vec);
|
||||||
|
/* age che */
|
||||||
|
if (!player->simulation) {
|
||||||
|
int oldche = sp->sct_che;
|
||||||
|
sp->sct_che = age_people(sp->sct_che, etu);
|
||||||
|
if (sp->sct_che_target == sp->sct_own && sp->sct_loyal < 40)
|
||||||
|
/* make them fade away eventually, for playability */
|
||||||
|
sp->sct_che /= 2;
|
||||||
|
if (sp->sct_che != oldche)
|
||||||
|
logerror("che in %d,%d aged from %d to %d",
|
||||||
|
sp->sct_x, sp->sct_y, oldche, sp->sct_che);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
sctwork = sp->sct_work = 100;
|
sctwork = sp->sct_work = 100;
|
||||||
|
|
|
@ -157,7 +157,8 @@ upd_ship(struct shpstr *sp, int etus,
|
||||||
|
|
||||||
/* produce oil */
|
/* produce oil */
|
||||||
if (np->nat_money >= 0
|
if (np->nat_money >= 0
|
||||||
&& (mp->m_flags & M_OIL) && sectp->sct_type == SCT_WATER) {
|
&& (mp->m_flags & M_OIL) && sectp->sct_type == SCT_WATER
|
||||||
|
&& sp->shp_mobil >= ship_mob_max) {
|
||||||
product = &pchr[dchr[SCT_OIL].d_prd];
|
product = &pchr[dchr[SCT_OIL].d_prd];
|
||||||
oil_gained = roundavg(total_work(100, etus,
|
oil_gained = roundavg(total_work(100, etus,
|
||||||
sp->shp_item[I_CIVIL],
|
sp->shp_item[I_CIVIL],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue