|
|
|
@ -454,17 +454,20 @@ travelthru(const unit * u, region * r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
leave_trail(unit * u, region **route, region * to)
|
|
|
|
|
leave_trail(unit * u, region * from, region_list *route)
|
|
|
|
|
{
|
|
|
|
|
region **ri = route;
|
|
|
|
|
ship * sh = u->ship;
|
|
|
|
|
region * r = from;
|
|
|
|
|
|
|
|
|
|
while (*ri) {
|
|
|
|
|
region * r = *ri++;
|
|
|
|
|
region * rn = *ri?*ri:to;
|
|
|
|
|
while (route!=NULL) {
|
|
|
|
|
region * rn = route->data;
|
|
|
|
|
direction_t dir = reldirection(r, rn);
|
|
|
|
|
attrib * a = a_find(r->attribs, &at_traveldir_new);
|
|
|
|
|
|
|
|
|
|
/* TODO: we cannot leave a trail into special directions
|
|
|
|
|
* if we use this kind of direction-attribute */
|
|
|
|
|
if (dir<MAXDIRECTIONS && dir>=0) {
|
|
|
|
|
traveldir * td = NULL;
|
|
|
|
|
attrib * a = a_find(r->attribs, &at_traveldir_new);
|
|
|
|
|
|
|
|
|
|
while (a!=NULL) {
|
|
|
|
|
td = (traveldir *)a->data.v;
|
|
|
|
@ -479,23 +482,25 @@ leave_trail(unit * u, region **route, region * to)
|
|
|
|
|
}
|
|
|
|
|
td->dir = dir;
|
|
|
|
|
td->age = 2;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
route = route->next;
|
|
|
|
|
r = rn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
travel_route(const unit * u, region ** route)
|
|
|
|
|
travel_route(const unit * u, region_list * route)
|
|
|
|
|
{
|
|
|
|
|
region **ri = route;
|
|
|
|
|
|
|
|
|
|
while (*ri) {
|
|
|
|
|
region * r = *ri++;
|
|
|
|
|
/* kein travelthru in der letzten region! */
|
|
|
|
|
while (route && route->next) {
|
|
|
|
|
region * r = route->data;
|
|
|
|
|
travelthru(u, r);
|
|
|
|
|
route = route->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ship *
|
|
|
|
|
move_ship(ship * sh, region * from, region * to, region ** route)
|
|
|
|
|
move_ship(ship * sh, region * from, region * to, region_list * route)
|
|
|
|
|
{
|
|
|
|
|
unit **iunit = &from->units;
|
|
|
|
|
unit **ulist = &to->units;
|
|
|
|
@ -512,8 +517,8 @@ move_ship(ship * sh, region * from, region * to, region ** route)
|
|
|
|
|
|
|
|
|
|
if (u->ship == sh) {
|
|
|
|
|
if (!trail) {
|
|
|
|
|
leave_trail(u, route, to);
|
|
|
|
|
trail=true;
|
|
|
|
|
leave_trail(u, from, route);
|
|
|
|
|
trail = true;
|
|
|
|
|
}
|
|
|
|
|
if (route!=NULL) travel_route(u, route);
|
|
|
|
|
if (from!=to) {
|
|
|
|
@ -537,7 +542,6 @@ drifting_ships(region * r)
|
|
|
|
|
direction_t d;
|
|
|
|
|
ship *sh, *sh2;
|
|
|
|
|
unit *captain;
|
|
|
|
|
region * route[2] = { 0, 0 };
|
|
|
|
|
|
|
|
|
|
if (rterrain(r) == T_OCEAN) {
|
|
|
|
|
for (sh = r->ships; sh;) {
|
|
|
|
@ -602,15 +606,14 @@ drifting_ships(region * r)
|
|
|
|
|
|
|
|
|
|
/* Das Schiff und alle Einheiten darin werden nun von r
|
|
|
|
|
* nach rconnect(r, d) verschoben. Danach eine Meldung. */
|
|
|
|
|
#if 0
|
|
|
|
|
/* ich bin fast sicher, das man das nicht braucht. (enno) */
|
|
|
|
|
for (f = factions; f; f = f->next)
|
|
|
|
|
freset(f, FL_DH);
|
|
|
|
|
#endif
|
|
|
|
|
if (fval(sh, SF_DRIFTED)) {
|
|
|
|
|
region_list * route = NULL;
|
|
|
|
|
region * to = rconnect(r, d);
|
|
|
|
|
/* wenn schon einmal abgetrieben, dann durchreise eintragen */
|
|
|
|
|
route[0] = r;
|
|
|
|
|
sh = move_ship(sh, r, rconnect(r, d), route);
|
|
|
|
|
add_regionlist(&route, r);
|
|
|
|
|
add_regionlist(&route, to);
|
|
|
|
|
sh = move_ship(sh, r, to, route);
|
|
|
|
|
free_regionlist(route);
|
|
|
|
|
} else sh = move_ship(sh, r, rconnect(r, d), NULL);
|
|
|
|
|
if (!sh) {
|
|
|
|
|
sh = sh2;
|
|
|
|
@ -623,7 +626,7 @@ drifting_ships(region * r)
|
|
|
|
|
/* Alle Attribute
|
|
|
|
|
* sicherheitshalber loeschen und
|
|
|
|
|
* gegebenenfalls neu setzen. */
|
|
|
|
|
sh->coast = back[d];
|
|
|
|
|
sh->coast = dir_invert(d);
|
|
|
|
|
}
|
|
|
|
|
damage_ship(sh, 0.02);
|
|
|
|
|
|
|
|
|
@ -910,41 +913,40 @@ cantravel(const unit *u, const region *from, const region * to, boolean (*allowe
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
roadto(const region * r, const region * r2)
|
|
|
|
|
roadto(const region * r, direction_t dir)
|
|
|
|
|
{
|
|
|
|
|
/* wenn es hier genug strassen gibt, und verbunden ist, und es dort
|
|
|
|
|
* genug strassen gibt, dann existiert eine strasse in diese richtung */
|
|
|
|
|
region * r2;
|
|
|
|
|
|
|
|
|
|
direction_t i;
|
|
|
|
|
if (dir>=MAXDIRECTIONS || dir<0) return false;
|
|
|
|
|
r2 = rconnect(r, dir);
|
|
|
|
|
if (r==NULL || r2==NULL) return false;
|
|
|
|
|
|
|
|
|
|
if (!r || !r2) return false;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i != MAXDIRECTIONS; i++)
|
|
|
|
|
if (rconnect(r, i) == r2) {
|
|
|
|
|
if (terrain[rterrain(r)].roadreq==0) return false;
|
|
|
|
|
if (terrain[rterrain(r2)].roadreq==0) return false;
|
|
|
|
|
if (rroad(r, i) < terrain[rterrain(r)].roadreq) return false;
|
|
|
|
|
if (rroad(r2, back[i]) < terrain[rterrain(r2)].roadreq) return false;
|
|
|
|
|
if (rroad(r, dir) < terrain[rterrain(r)].roadreq) return false;
|
|
|
|
|
if (rroad(r2, dir_invert(dir)) < terrain[rterrain(r2)].roadreq) return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
direction_t *
|
|
|
|
|
travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
void
|
|
|
|
|
travel(unit * u, region * next, int flucht, region_list ** routep)
|
|
|
|
|
{
|
|
|
|
|
region *current = first;
|
|
|
|
|
int k, m, i, dh;
|
|
|
|
|
region *first = u->region;
|
|
|
|
|
region *current = u->region;
|
|
|
|
|
int k, m = 0;
|
|
|
|
|
double dk;
|
|
|
|
|
unit *wache;
|
|
|
|
|
region *rv[MAXSPEED];
|
|
|
|
|
strlist *S;
|
|
|
|
|
unit *ut, *u2;
|
|
|
|
|
int gereist = 0;
|
|
|
|
|
static direction_t route[MAXSPEED];
|
|
|
|
|
region_list *route = NULL;
|
|
|
|
|
region_list **iroute = &route;
|
|
|
|
|
static boolean init = false;
|
|
|
|
|
static const curse_type * speed_ct;
|
|
|
|
|
static const curse_type * fogtrap_ct;
|
|
|
|
|
|
|
|
|
|
if (routep) *routep = NULL;
|
|
|
|
|
if (!init) {
|
|
|
|
|
init = true;
|
|
|
|
|
speed_ct = ct_find("speed");
|
|
|
|
@ -965,45 +967,43 @@ travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
{ /* Die Einheit kann nicht fliegen, ist im Ozean, und will an Land */
|
|
|
|
|
if (!(u->race->flags & RCF_SWIM) && old_race(u->race) != RC_AQUARIAN) {
|
|
|
|
|
cmistake(u, findorder(u, u->thisorder), 44, MSG_MOVE);
|
|
|
|
|
return NULL;
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
if (u->ship && get_item(u, I_HORSE) > 0) {
|
|
|
|
|
cmistake(u, findorder(u, u->thisorder), 67, MSG_MOVE);
|
|
|
|
|
return NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (rterrain(current)!=T_OCEAN) {
|
|
|
|
|
/* An Land kein NACH wenn in dieser Runde Schiff VERLASSEN! */
|
|
|
|
|
if (leftship(u) && is_guarded(current, u, GUARD_LANDING)) {
|
|
|
|
|
cmistake(u, findorder(u, u->thisorder), 70, MSG_MOVE);
|
|
|
|
|
return NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (u->ship && !flucht && u->race->flags & RCF_SWIM) {
|
|
|
|
|
cmistake(u, findorder(u, u->thisorder), 143, MSG_MOVE);
|
|
|
|
|
return NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else if (rterrain(next) == T_OCEAN && u->ship && fval(u->ship, SF_MOVED)) {
|
|
|
|
|
cmistake(u, findorder(u, u->thisorder), 13, MSG_MOVE);
|
|
|
|
|
return NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (canwalk(u)) {
|
|
|
|
|
case 1:
|
|
|
|
|
cmistake(u, findorder(u, u->thisorder), 57, MSG_MOVE);
|
|
|
|
|
return NULL;
|
|
|
|
|
return;
|
|
|
|
|
case 2:
|
|
|
|
|
cmistake(u, findorder(u, u->thisorder), 56, MSG_MOVE);
|
|
|
|
|
return NULL;
|
|
|
|
|
return;
|
|
|
|
|
case 3:
|
|
|
|
|
cmistake(u, findorder(u, u->thisorder), 42, MSG_MOVE);
|
|
|
|
|
return NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* wir suchen so lange nach neuen Richtungen, wie es geht. Diese werden
|
|
|
|
|
* dann nacheinander ausgeführt. */
|
|
|
|
|
|
|
|
|
|
/* im array rv[] speichern wir die Regionen ab, durch die wir wandern. */
|
|
|
|
|
|
|
|
|
|
dk = u->race->speed;
|
|
|
|
|
|
|
|
|
|
if (speed_ct) {
|
|
|
|
@ -1061,8 +1061,6 @@ travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
k = BP_DRAGON;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m = 0;
|
|
|
|
|
|
|
|
|
|
/* die nächste Region, in die man wandert, wird durch movewhere() aus
|
|
|
|
|
* der letzten Region bestimmt.
|
|
|
|
|
*
|
|
|
|
@ -1071,15 +1069,18 @@ travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
* die noch möglichen Schritte, r3 die letzte gültige, befahrene Region. */
|
|
|
|
|
|
|
|
|
|
while (next) {
|
|
|
|
|
direction_t dir = reldirection(current, next);
|
|
|
|
|
border * b = get_borders(current, next);
|
|
|
|
|
direction_t reldir = reldirection(current, next);
|
|
|
|
|
|
|
|
|
|
while (b!=NULL) {
|
|
|
|
|
if (b->type==&bt_wisps) {
|
|
|
|
|
wall_data * wd = (wall_data*)b->data;
|
|
|
|
|
assert(reldir!=D_SPECIAL);
|
|
|
|
|
|
|
|
|
|
if (wd->active) {
|
|
|
|
|
region * rl = rconnect(current, (direction_t)((dir+MAXDIRECTIONS-1)%MAXDIRECTIONS));
|
|
|
|
|
region * rr = rconnect(current, (direction_t)((dir+1)%MAXDIRECTIONS));
|
|
|
|
|
/* pick left and right region: */
|
|
|
|
|
region * rl = rconnect(current, (direction_t)((reldir+MAXDIRECTIONS-1)%MAXDIRECTIONS));
|
|
|
|
|
region * rr = rconnect(current, (direction_t)((reldir+1)%MAXDIRECTIONS));
|
|
|
|
|
int j = rand() % 3;
|
|
|
|
|
if (j==0) break;
|
|
|
|
|
else if (j==1 && rl && landregion(rterrain(rl))==landregion(rterrain(next))) next = rl;
|
|
|
|
@ -1091,33 +1092,29 @@ travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
b = b->next;
|
|
|
|
|
}
|
|
|
|
|
if (current!=next) { /* !pause */
|
|
|
|
|
if (roadto(current, next))
|
|
|
|
|
k -= BP_ROAD;
|
|
|
|
|
else
|
|
|
|
|
k -= BP_NORMAL;
|
|
|
|
|
if (roadto(current, reldir)) k-=BP_ROAD;
|
|
|
|
|
else k-=BP_NORMAL;
|
|
|
|
|
if (k<0) break;
|
|
|
|
|
/* r2 -> Zielregion, r3 -> Momentane Region */
|
|
|
|
|
if ((dir>=0 && move_blocked(u, current, dir))
|
|
|
|
|
|
|
|
|
|
if ((reldir>=0 && move_blocked(u, current, reldir))
|
|
|
|
|
|| curse_active(get_curse(current->attribs, fogtrap_ct)))
|
|
|
|
|
{
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("leavefail",
|
|
|
|
|
"unit region",
|
|
|
|
|
u, next));
|
|
|
|
|
"unit region", u, next));
|
|
|
|
|
}
|
|
|
|
|
if (!entrance_allowed(u, next)) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("regionowned",
|
|
|
|
|
"unit region target",
|
|
|
|
|
u, current, next));
|
|
|
|
|
"unit region target", u, current, next));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((wache = bewegung_blockiert_von(u, current)) != (unit *) NULL
|
|
|
|
|
&& gereist != 0)
|
|
|
|
|
{
|
|
|
|
|
if (gereist) {
|
|
|
|
|
unit * wache = bewegung_blockiert_von(u, current);
|
|
|
|
|
if (wache!=NULL) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("moveblockedbyguard",
|
|
|
|
|
"unit region guard", u, current,
|
|
|
|
|
wache));
|
|
|
|
|
"unit region guard", u, current, wache));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fval(u->race, RCF_ILLUSIONARY)) {
|
|
|
|
|
curse * c = get_curse(next->attribs, ct_find("antimagiczone"));
|
|
|
|
@ -1126,7 +1123,9 @@ travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"illusionantimagic%u:unit", u));
|
|
|
|
|
destroy_unit(u);
|
|
|
|
|
return route;
|
|
|
|
|
if (routep) *routep = route;
|
|
|
|
|
else free_regionlist(route);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne
|
|
|
|
@ -1134,36 +1133,36 @@ travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
|
|
|
|
|
if (rterrain(next) == T_OCEAN && !canswim(u)) {
|
|
|
|
|
plane *pl = getplane(next);
|
|
|
|
|
if (pl!=NULL && fval(pl, PFL_NOCOORDS)) {
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"detectoceandir%u:unit%i:direction", u, dir));
|
|
|
|
|
if (reldir<MAXDIRECTIONS && pl!=NULL && fval(pl, PFL_NOCOORDS)) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("detectoceandir",
|
|
|
|
|
"unit direction", u, reldir));
|
|
|
|
|
} else {
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"detectocean%u:unit%r:region", u, next));
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("detectocean",
|
|
|
|
|
"unit region", u, next));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (terrain[rterrain(next)].flags & FORBIDDEN_LAND) {
|
|
|
|
|
plane *pl = getplane(next);
|
|
|
|
|
if(pl && fval(pl, PFL_NOCOORDS)) {
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"detectforbiddendir%u:unit%i:direction", u, dir));
|
|
|
|
|
if (reldir<MAXDIRECTIONS && pl!=NULL && fval(pl, PFL_NOCOORDS)) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("detectforbiddendir",
|
|
|
|
|
"unit direction", u, reldir));
|
|
|
|
|
} else {
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"detectforbidden%u:unit%r:region", u, next));
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("detectforbidden",
|
|
|
|
|
"unit region", u, next));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (old_race(u->race) == RC_INSECT && r_insectstalled(next) &&
|
|
|
|
|
!is_cursed(u->attribs, C_KAELTESCHUTZ,0)) {
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"detectforbidden%u:unit%r:region", u, next));
|
|
|
|
|
if (old_race(u->race) == RC_INSECT && r_insectstalled(next) && !is_cursed(u->attribs, C_KAELTESCHUTZ,0))
|
|
|
|
|
{
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("detectforbidden",
|
|
|
|
|
"unit region", u, next));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
rv[m] = next;
|
|
|
|
|
route[m] = dir;
|
|
|
|
|
add_regionlist(iroute, next);
|
|
|
|
|
iroute = &(*iroute)->next;
|
|
|
|
|
m++;
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
@ -1176,7 +1175,6 @@ travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
next = movewhere(current, u);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
route[m] = NODIRECTION;
|
|
|
|
|
|
|
|
|
|
if (gereist) {
|
|
|
|
|
int mode;
|
|
|
|
@ -1206,20 +1204,20 @@ travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
|
|
|
|
|
m--;
|
|
|
|
|
if (m > 0) {
|
|
|
|
|
dh = 0;
|
|
|
|
|
region_list *rlist;
|
|
|
|
|
|
|
|
|
|
travelthru(u, first);
|
|
|
|
|
for (i = 0; i != m; i++) {
|
|
|
|
|
for (rlist = route;rlist!=NULL;rlist=rlist->next) {
|
|
|
|
|
char * p;
|
|
|
|
|
if (dh) {
|
|
|
|
|
if (i == m - 1)
|
|
|
|
|
scat(" und ");
|
|
|
|
|
else
|
|
|
|
|
scat(", ");
|
|
|
|
|
|
|
|
|
|
if (rlist!=route) {
|
|
|
|
|
if (rlist->next==NULL) scat(" und ");
|
|
|
|
|
else scat(", ");
|
|
|
|
|
}
|
|
|
|
|
dh = 1;
|
|
|
|
|
travelthru(u, rv[i]);
|
|
|
|
|
travelthru(u, rlist->data);
|
|
|
|
|
|
|
|
|
|
p = buf+strlen(buf);
|
|
|
|
|
MSG(("travelthru_trail", "region", rv[i]), p, sizeof(buf)-strlen(buf), u->faction->locale, u->faction);
|
|
|
|
|
MSG(("travelthru_trail", "region", rlist->data), p, sizeof(buf)-strlen(buf), u->faction->locale, u->faction);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
add_message(&u->faction->msgs, new_message(
|
|
|
|
@ -1247,9 +1245,8 @@ travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
cmistake(ut, ut->thisorder, 67, MSG_MOVE);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(can_survive(ut, current)) {
|
|
|
|
|
for (i = 0; i != m; i++)
|
|
|
|
|
travelthru(ut, rv[i]);
|
|
|
|
|
if (can_survive(ut, current)) {
|
|
|
|
|
travel_route(ut, route);
|
|
|
|
|
move_unit(ut, current, NULL);
|
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, u->thisorder, 287, MSG_MOVE);
|
|
|
|
@ -1283,7 +1280,9 @@ travel(region * first, unit * u, region * next, int flucht)
|
|
|
|
|
setguard(u, GUARD_NONE);
|
|
|
|
|
|
|
|
|
|
if (fval(u, UFL_FOLLOWING)) caught_target(current, u);
|
|
|
|
|
return route;
|
|
|
|
|
if (routep) *routep = route;
|
|
|
|
|
else free_regionlist(route);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
@ -1376,18 +1375,14 @@ check_working_buildingtype(const region * r, const building_type * bt)
|
|
|
|
|
static boolean
|
|
|
|
|
check_takeoff(ship *sh, region *from, region *to)
|
|
|
|
|
{
|
|
|
|
|
direction_t dir;
|
|
|
|
|
direction_t coast, coastl, coastr;
|
|
|
|
|
|
|
|
|
|
if (rterrain(from)!=T_OCEAN && sh->coast != NODIRECTION) {
|
|
|
|
|
coast = sh->coast;
|
|
|
|
|
dir = reldirection(from, to);
|
|
|
|
|
direction_t coast = sh->coast;
|
|
|
|
|
direction_t dir = reldirection(from, to);
|
|
|
|
|
direction_t coastr = (direction_t)((coast+1) % MAXDIRECTIONS);
|
|
|
|
|
direction_t coastl = (direction_t)((coast+MAXDIRECTIONS-1) % MAXDIRECTIONS);
|
|
|
|
|
|
|
|
|
|
coastr = (direction_t)((coast+1) % MAXDIRECTIONS);
|
|
|
|
|
coastl = (direction_t)((coast+MAXDIRECTIONS-1) % MAXDIRECTIONS);
|
|
|
|
|
|
|
|
|
|
if(dir != coast && dir != coastl && dir != coastr
|
|
|
|
|
&& check_working_buildingtype(from, bt_find("harbour")) == false)
|
|
|
|
|
if (dir!=coast && dir!=coastl && dir!=coastr
|
|
|
|
|
&& !check_working_buildingtype(from, bt_find("harbour")))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -1407,18 +1402,18 @@ ship_allowed(const struct ship_type * type, region * r)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static direction_t *
|
|
|
|
|
sail(region * starting_point, unit * u, region * next_point, boolean move_on_land)
|
|
|
|
|
static region_list *
|
|
|
|
|
sail(unit * u, region * next_point, boolean move_on_land)
|
|
|
|
|
{
|
|
|
|
|
region * starting_point = u->region;
|
|
|
|
|
region *current_point, *last_point;
|
|
|
|
|
unit *u2, *hafenmeister;
|
|
|
|
|
item * trans = NULL;
|
|
|
|
|
int st, first = 1;
|
|
|
|
|
int k, m, l, i, step = 0;
|
|
|
|
|
int k, step = 0;
|
|
|
|
|
int stormchance;
|
|
|
|
|
region *rv[MAXSPEED + 1];
|
|
|
|
|
region *tt[MAXSPEED + 1]; /* travelthru */
|
|
|
|
|
static direction_t route[MAXSPEED+1]; /* route[i] := direction from tt[i] to tt[i-1] */
|
|
|
|
|
region_list *route = NULL;
|
|
|
|
|
region_list **iroute = &route;
|
|
|
|
|
static boolean init = false;
|
|
|
|
|
static const curse_type * fogtrap_ct;
|
|
|
|
|
if (!init) {
|
|
|
|
@ -1434,9 +1429,6 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
|
|
|
|
|
|
|
|
|
|
k = shipspeed(u->ship, u);
|
|
|
|
|
|
|
|
|
|
l = 0;
|
|
|
|
|
m = 0;
|
|
|
|
|
|
|
|
|
|
last_point = starting_point;
|
|
|
|
|
current_point = starting_point;
|
|
|
|
|
|
|
|
|
@ -1444,25 +1436,21 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
|
|
|
|
|
* letzten Region bestimmt.
|
|
|
|
|
*
|
|
|
|
|
* Anfangen tun wir bei starting_point. next_point ist beim ersten
|
|
|
|
|
* Durchlauf schon gesetzt (Parameter!). l zählt gesichtete
|
|
|
|
|
* Küstenstreifen, rv[] speichert die gesichteten Küstenstreifen, m
|
|
|
|
|
* zählt befahrene Felder, current_point ist die letzte gültige,
|
|
|
|
|
* Durchlauf schon gesetzt (Parameter!). current_point ist die letzte gültige,
|
|
|
|
|
* befahrene Region. */
|
|
|
|
|
tt[step] = starting_point;
|
|
|
|
|
|
|
|
|
|
while (current_point!=next_point && m < k && next_point)
|
|
|
|
|
while (current_point!=next_point && step < k && next_point)
|
|
|
|
|
{
|
|
|
|
|
direction_t dir = reldirection(current_point, next_point);
|
|
|
|
|
|
|
|
|
|
if(terrain[rterrain(next_point)].flags & FORBIDDEN_LAND) {
|
|
|
|
|
plane *pl = getplane(next_point);
|
|
|
|
|
if(pl && fval(pl, PFL_NOCOORDS)) {
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"sailforbiddendir%h:ship%i:direction",
|
|
|
|
|
u->ship, reldirection(current_point,next_point)));
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("sailforbiddendir",
|
|
|
|
|
"ship direction", u->ship, dir));
|
|
|
|
|
} else {
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"sailforbidden%h:ship%r:region", u->ship, next_point));
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("sailforbidden",
|
|
|
|
|
"ship region", u->ship, next_point));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -1472,7 +1460,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
|
|
|
|
|
if (rterrain(current_point) != T_OCEAN
|
|
|
|
|
&& rterrain(next_point) != T_OCEAN) {
|
|
|
|
|
plane *pl = getplane(next_point);
|
|
|
|
|
if(pl && fval(pl, PFL_NOCOORDS)) {
|
|
|
|
|
if (dir<MAXDIRECTIONS && pl && fval(pl, PFL_NOCOORDS)) {
|
|
|
|
|
sprintf(buf, "Die %s entdeckt, daß im %s Festland ist.",
|
|
|
|
|
shipname(u->ship), locale_string(u->faction->locale, directions[dir]));
|
|
|
|
|
} else {
|
|
|
|
@ -1510,7 +1498,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
|
|
|
|
|
|
|
|
|
|
/* Falls Blockade, endet die Seglerei hier */
|
|
|
|
|
|
|
|
|
|
if (move_blocked(u, current_point, reldirection(current_point, next_point))
|
|
|
|
|
if (move_blocked(u, current_point, dir)
|
|
|
|
|
|| curse_active(get_curse(current_point->attribs, fogtrap_ct))) {
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"sailfail%h:ship%r:region", u->ship, current_point));
|
|
|
|
@ -1543,8 +1531,8 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
|
|
|
|
|
if(pl && fval(pl, PFL_NOCOORDS)) {
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"sailforbiddendir%h:ship%i:direction",
|
|
|
|
|
u->ship, reldirection(current_point,next_point)));
|
|
|
|
|
/* sprintf(buf, "Die Mannschaft der %s weigert sich, in die Feuerwand "
|
|
|
|
|
u->ship, dir));
|
|
|
|
|
/* sprintf(buf, "Die Mannschaft der %s weigert sich, in die Feuerwand "
|
|
|
|
|
"im %s zu fahren.",
|
|
|
|
|
shipname(u->ship), directions[dir]); */
|
|
|
|
|
} else {
|
|
|
|
@ -1580,29 +1568,18 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
|
|
|
|
|
} /* endif !flying */
|
|
|
|
|
|
|
|
|
|
/* Falls kein Problem, eines weiter ziehen */
|
|
|
|
|
route[step] = dir;
|
|
|
|
|
tt[step] = current_point; /* travelthrough */
|
|
|
|
|
fset(u->ship, SF_MOVED);
|
|
|
|
|
add_regionlist(iroute, next_point);
|
|
|
|
|
iroute = &(*iroute)->next;
|
|
|
|
|
step++;
|
|
|
|
|
m++;
|
|
|
|
|
|
|
|
|
|
last_point = current_point;
|
|
|
|
|
current_point = next_point;
|
|
|
|
|
|
|
|
|
|
/* Falls eine Küstenregion, dann in rv[] aufnehmen (die letzte
|
|
|
|
|
* Küste wird nachher nicht aufgelistet werden, wenn das
|
|
|
|
|
* Schiff dort seine Runde beendent!). */
|
|
|
|
|
if (rterrain(current_point) != T_OCEAN) {
|
|
|
|
|
rv[l] = current_point;
|
|
|
|
|
l++;
|
|
|
|
|
}
|
|
|
|
|
if (rterrain(current_point) != T_OCEAN && !is_cursed(u->ship->attribs, C_SHIP_FLYING, 0)) break;
|
|
|
|
|
next_point = movewhere(current_point, u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
route[step] = NODIRECTION;
|
|
|
|
|
/* at this point, step is the number of steps made. tt[step] is the final region. */
|
|
|
|
|
|
|
|
|
|
/* Nun enthält current_point die Region, in der das Schiff seine Runde
|
|
|
|
|
* beendet hat. Wir generieren hier ein Ereignis für den Spieler, das
|
|
|
|
|
* ihm sagt, bis wohin er gesegelt ist, falls er überhaupt vom Fleck
|
|
|
|
@ -1630,38 +1607,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
|
|
|
|
|
scat(regionid(starting_point));
|
|
|
|
|
scat(" nach ");
|
|
|
|
|
scat(regionid(current_point));
|
|
|
|
|
|
|
|
|
|
/* Falls es Kuesten gibt, denen man entlang gefahren ist,
|
|
|
|
|
* sollen sie aufgefuehrt werden. Falls wir aber unseren Zug in
|
|
|
|
|
* einer Kuestenregion beendet haben, fuehren wir sie nicht mit
|
|
|
|
|
* auf - sie wird sowieso in allen Details im Report erwaehnt
|
|
|
|
|
* werden. */
|
|
|
|
|
|
|
|
|
|
if (rterrain(current_point) != T_OCEAN)
|
|
|
|
|
l--;
|
|
|
|
|
|
|
|
|
|
if (l > 0) {
|
|
|
|
|
if( is_cursed(sh->attribs, C_SHIP_FLYING, 0) )
|
|
|
|
|
scat(". Dabei flog es über ");
|
|
|
|
|
else {
|
|
|
|
|
scat(". Dabei segelte es entlang der ");
|
|
|
|
|
if (l > 1)
|
|
|
|
|
scat("Küsten");
|
|
|
|
|
else
|
|
|
|
|
scat("Küste");
|
|
|
|
|
scat(" von ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i != l; i++) {
|
|
|
|
|
scat(regionid(rv[i]));
|
|
|
|
|
if (i < l - 2)
|
|
|
|
|
scat(", ");
|
|
|
|
|
else if (i == l - 2)
|
|
|
|
|
scat(" und ");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
scat(".");
|
|
|
|
|
|
|
|
|
|
addmessage(0, u->faction, buf, MSG_MOVE, ML_INFO);
|
|
|
|
|
|
|
|
|
|
/* Das Schiff und alle Einheiten darin werden nun von
|
|
|
|
@ -1670,8 +1616,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan
|
|
|
|
|
/* Verfolgungen melden */
|
|
|
|
|
if (fval(u, UFL_FOLLOWING)) caught_target(current_point, u);
|
|
|
|
|
|
|
|
|
|
tt[step] = NULL;
|
|
|
|
|
sh = move_ship(sh, starting_point, current_point, tt);
|
|
|
|
|
sh = move_ship(sh, starting_point, current_point, route);
|
|
|
|
|
|
|
|
|
|
/* Hafengebühren ? */
|
|
|
|
|
|
|
|
|
@ -1745,6 +1690,19 @@ kapitaen(region * r, ship * sh)
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
direction_name(const region * from, const region * to, const struct locale * lang)
|
|
|
|
|
{
|
|
|
|
|
direction_t dir = reldirection(from, to);
|
|
|
|
|
if (dir<MAXDIRECTIONS && dir>=0) return locale_string(lang, directions[dir]);
|
|
|
|
|
if (dir==D_SPECIAL) {
|
|
|
|
|
spec_direction *sd = special_direction(from, to);
|
|
|
|
|
return sd->keyword;
|
|
|
|
|
}
|
|
|
|
|
assert(!"invalid direction");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Segeln, Wandern, Reiten
|
|
|
|
|
* when this routine returns a non-zero value, movement for the region needs
|
|
|
|
|
* to be done again because of followers that got new MOVE orders.
|
|
|
|
@ -1752,21 +1710,21 @@ kapitaen(region * r, ship * sh)
|
|
|
|
|
* by this routine
|
|
|
|
|
*/
|
|
|
|
|
static int
|
|
|
|
|
move(region * r, unit * u, boolean move_on_land)
|
|
|
|
|
move(unit * u, boolean move_on_land)
|
|
|
|
|
{
|
|
|
|
|
region *r2;
|
|
|
|
|
direction_t * route;
|
|
|
|
|
region * r = u->region;
|
|
|
|
|
region_list * route = NULL;
|
|
|
|
|
region * r2 = movewhere(r, u);
|
|
|
|
|
|
|
|
|
|
r2 = movewhere(r, u);
|
|
|
|
|
|
|
|
|
|
if (!r2) {
|
|
|
|
|
if (r2==NULL) {
|
|
|
|
|
cmistake(u, findorder(u, u->thisorder), 71, MSG_MOVE);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else if (u->ship && fval(u, UFL_OWNER))
|
|
|
|
|
route = sail(r, u, r2, move_on_land);
|
|
|
|
|
else
|
|
|
|
|
route = travel(r, u, r2, 0);
|
|
|
|
|
else if (u->ship && fval(u, UFL_OWNER)) {
|
|
|
|
|
route = sail(u, r2, move_on_land);
|
|
|
|
|
} else {
|
|
|
|
|
travel(u, r2, 0, &route);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i_get(u->items, &it_demonseye)) {
|
|
|
|
|
direction_t d;
|
|
|
|
@ -1774,7 +1732,7 @@ move(region * r, unit * u, boolean move_on_land)
|
|
|
|
|
region * rc = rconnect(r2,d);
|
|
|
|
|
if (rc) {
|
|
|
|
|
sprintf(buf, "Im %s ist eine ungeheure magische Präsenz zu verspüren.",
|
|
|
|
|
locale_string(u->faction->locale, directions[back[d]]));
|
|
|
|
|
locale_string(u->faction->locale, directions[dir_invert(d)]));
|
|
|
|
|
addmessage(rc, NULL, buf, MSG_EVENT, ML_IMPORTANT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1783,7 +1741,7 @@ move(region * r, unit * u, boolean move_on_land)
|
|
|
|
|
if (u->region!=r) fset(u, UFL_LONGACTION);
|
|
|
|
|
set_string(&u->thisorder, "");
|
|
|
|
|
|
|
|
|
|
if (fval(u, UFL_FOLLOWED) && route && route[0]!=NODIRECTION) {
|
|
|
|
|
if (fval(u, UFL_FOLLOWED) && route!=NULL) {
|
|
|
|
|
int followers = 0;
|
|
|
|
|
unit *up;
|
|
|
|
|
for (up=r->units;up;up=up->next) {
|
|
|
|
@ -1791,10 +1749,16 @@ move(region * r, unit * u, boolean move_on_land)
|
|
|
|
|
const attrib * a = a_findc(up->attribs, &at_follow);
|
|
|
|
|
if (a && a->data.v==u) {
|
|
|
|
|
/* wir basteln ihm ein NACH */
|
|
|
|
|
int k, i = 0;
|
|
|
|
|
int k;
|
|
|
|
|
region_list * rlist = route;
|
|
|
|
|
region * from = u->region;
|
|
|
|
|
|
|
|
|
|
strcpy(buf, locale_string(up->faction->locale, keywords[K_MOVE]));
|
|
|
|
|
while (route[i]!=NODIRECTION)
|
|
|
|
|
strcat(strcat(buf, " "), locale_string(up->faction->locale, directions[route[i++]]));
|
|
|
|
|
while (rlist!=NULL) {
|
|
|
|
|
strcat(strcat(buf, " "), direction_name(from, rlist->data, up->faction->locale));
|
|
|
|
|
from = rlist->data;
|
|
|
|
|
rlist = rlist->next;
|
|
|
|
|
}
|
|
|
|
|
set_string(&up->thisorder, buf);
|
|
|
|
|
k = igetkeyword(up->thisorder, up->faction->locale);
|
|
|
|
|
assert(k==K_MOVE);
|
|
|
|
@ -1804,6 +1768,7 @@ move(region * r, unit * u, boolean move_on_land)
|
|
|
|
|
}
|
|
|
|
|
return followers;
|
|
|
|
|
}
|
|
|
|
|
if (route!=NULL) free_regionlist(route);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1944,7 +1909,7 @@ piracy(unit *u)
|
|
|
|
|
|
|
|
|
|
/* Bewegung ausführen */
|
|
|
|
|
igetkeyword(u->thisorder, u->faction->locale); /* NACH ignorieren */
|
|
|
|
|
return move(r, u, true);
|
|
|
|
|
return move(u, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
@ -2043,7 +2008,7 @@ hunt(unit *u)
|
|
|
|
|
igetkeyword(command, u->faction->locale); /* NACH ignorieren und Parsing initialisieren. */
|
|
|
|
|
|
|
|
|
|
/* NACH ausführen */
|
|
|
|
|
if (move(u->region, u, false)!=0) {
|
|
|
|
|
if (move(u, false)!=0) {
|
|
|
|
|
/* niemand sollte auf einen kapitän direkt ein folge haben, oder? */
|
|
|
|
|
assert(1==0);
|
|
|
|
|
}
|
|
|
|
@ -2250,11 +2215,11 @@ movement(void)
|
|
|
|
|
} else {
|
|
|
|
|
if (ships) {
|
|
|
|
|
if (u->ship && fval(u, UFL_OWNER)) {
|
|
|
|
|
if (move(r, u, true)!=0) repeat = true;
|
|
|
|
|
if (move(u, true)!=0) repeat = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (u->ship==NULL || !fval(u, UFL_OWNER)) {
|
|
|
|
|
if (move(r, u, true)!=0) repeat = true;
|
|
|
|
|
if (move(u, true)!=0) repeat = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|