forked from github/server
FOLGE SCHIFF repariert.
https://bugs.eressea.de/view.php?id=2698 FOLGE generell verbessert, so daß man mehrere FOLGE Befehle setzen kann. Bugfix: findship findet auch "leere" Schiffe, der Caller muss jetzt auf sh->number testen. Schiffe und Burgen können ab sofort die selben IDs benutzen. Befehlsreihenfolge: FOLGE erst nach VERLASSE/GIB
This commit is contained in:
parent
d9a0bc7016
commit
712e1c3052
|
@ -232,7 +232,7 @@ void process_follow(void) {
|
|||
for (r = regions; r; r = r->next) {
|
||||
unit *u;
|
||||
for (u = r->units; u; u = u->next) {
|
||||
follow_unit(u);
|
||||
follow_cmds(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,17 +56,17 @@
|
|||
struct building *getbuilding(const struct region *r)
|
||||
{
|
||||
building *b = findbuilding(getid());
|
||||
if (b == NULL || r != b->region)
|
||||
return NULL;
|
||||
return b;
|
||||
if (b != NULL && r == b->region) {
|
||||
return b;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ship *getship(const struct region * r)
|
||||
{
|
||||
ship *sh, *sx = findship(getid());
|
||||
for (sh = r->ships; sh; sh = sh->next) {
|
||||
if (sh == sx)
|
||||
return sh;
|
||||
ship *sh = findship(getid());
|
||||
if (sh != NULL && sh->number > 0 && sh->region == r) {
|
||||
return sh;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <util/log.h>
|
||||
#include <util/param.h>
|
||||
#include <util/resolve.h>
|
||||
#include <util/rng.h>
|
||||
#include <util/strings.h>
|
||||
#include <util/umlaut.h>
|
||||
|
||||
|
@ -368,11 +369,30 @@ building *building_create(int id)
|
|||
return b;
|
||||
}
|
||||
|
||||
static int newbuildingid(void) {
|
||||
int random_no;
|
||||
int start_random_no;
|
||||
|
||||
random_no = 1 + (rng_int() % MAX_CONTAINER_NR);
|
||||
start_random_no = random_no;
|
||||
|
||||
while (findbuilding(random_no)) {
|
||||
random_no++;
|
||||
if (random_no == MAX_CONTAINER_NR + 1) {
|
||||
random_no = 1;
|
||||
}
|
||||
if (random_no == start_random_no) {
|
||||
random_no = (int)MAX_CONTAINER_NR + 1;
|
||||
}
|
||||
}
|
||||
return random_no;
|
||||
}
|
||||
|
||||
building *new_building(const struct building_type * btype, region * r,
|
||||
const struct locale * lang, int size)
|
||||
{
|
||||
building **bptr = &r->buildings;
|
||||
int id = newcontainerid();
|
||||
int id = newbuildingid();
|
||||
building *b = building_create(id);
|
||||
const char *bname;
|
||||
char buffer[32];
|
||||
|
|
|
@ -466,7 +466,7 @@ unit *read_unit(gamedata *data)
|
|||
|
||||
if (sn > 0) {
|
||||
ship * sh = findship(sn);
|
||||
if (sh) {
|
||||
if (sh && sh->number > 0) {
|
||||
u_set_ship(u, sh);
|
||||
if (fval(u, UFL_OWNER)) {
|
||||
ship_set_owner(u);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <util/lists.h>
|
||||
#include <util/log.h>
|
||||
#include <util/param.h>
|
||||
#include <util/rng.h>
|
||||
#include <util/strings.h>
|
||||
#include <util/umlaut.h>
|
||||
|
||||
|
@ -150,7 +151,7 @@ static ship *sfindhash(int i)
|
|||
|
||||
for (sh = shiphash[i % MAXSHIPHASH]; sh; sh = sh->nexthash) {
|
||||
if (sh->no == i) {
|
||||
return sh->number > 0 ? sh : NULL;
|
||||
return sh;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
@ -171,6 +172,25 @@ void damage_ship(ship * sh, double percent)
|
|||
/* Alte Schiffstypen: */
|
||||
static ship *deleted_ships;
|
||||
|
||||
static int newshipid(void) {
|
||||
int random_no;
|
||||
int start_random_no;
|
||||
|
||||
random_no = 1 + (rng_int() % MAX_CONTAINER_NR);
|
||||
start_random_no = random_no;
|
||||
|
||||
while (findship(random_no)) {
|
||||
random_no++;
|
||||
if (random_no == MAX_CONTAINER_NR + 1) {
|
||||
random_no = 1;
|
||||
}
|
||||
if (random_no == start_random_no) {
|
||||
random_no = (int)MAX_CONTAINER_NR + 1;
|
||||
}
|
||||
}
|
||||
return random_no;
|
||||
}
|
||||
|
||||
ship *new_ship(const ship_type * stype, region * r, const struct locale *lang)
|
||||
{
|
||||
static char buffer[32];
|
||||
|
@ -179,7 +199,7 @@ ship *new_ship(const ship_type * stype, region * r, const struct locale *lang)
|
|||
|
||||
if (!sh) abort();
|
||||
assert(stype);
|
||||
sh->no = newcontainerid();
|
||||
sh->no = newshipid();
|
||||
sh->coast = NODIRECTION;
|
||||
sh->type = stype;
|
||||
sh->region = r;
|
||||
|
|
|
@ -1066,7 +1066,7 @@ int enter_ship(unit * u, struct order *ord, int id, bool report)
|
|||
}
|
||||
|
||||
sh = findship(id);
|
||||
if (sh == NULL || sh->region != r) {
|
||||
if (sh == NULL || sh->number < 1 || sh->region != r) {
|
||||
if (report) {
|
||||
cmistake(u, ord, 20, MSG_MOVE);
|
||||
}
|
||||
|
@ -3914,7 +3914,6 @@ void init_processor(void)
|
|||
}
|
||||
add_proc_order(p, K_RESERVE, reserve_cmd, 0, "RESERVE (all)");
|
||||
add_proc_order(p, K_CLAIM, claim_cmd, 0, NULL);
|
||||
add_proc_unit(p, follow_unit, "Folge auf Einheiten setzen");
|
||||
|
||||
p += 10; /* rest rng again before economics */
|
||||
if (rule_force_leave(FORCE_LEAVE_ALL)) {
|
||||
|
@ -3923,6 +3922,7 @@ void init_processor(void)
|
|||
add_proc_region(p, economics, "Geben, Vergessen");
|
||||
add_proc_region(p+1, recruit, "Rekrutieren");
|
||||
add_proc_region(p+2, destroy, "Zerstoeren");
|
||||
add_proc_unit(p, follow_cmds, "Folge auf Einheiten setzen");
|
||||
add_proc_order(p, K_QUIT, quit_cmd, 0, "Stirb");
|
||||
|
||||
/* all recruitment must be finished before we can calculate
|
||||
|
|
|
@ -1499,12 +1499,12 @@ verify_ship(region * r, unit * mage, const spell * sp, spllprm * spobj,
|
|||
ship *sh = findship(spobj->data.i);
|
||||
|
||||
if (sh != NULL && sh->region != r && (sp->sptyp & GLOBALTARGET) == 0) {
|
||||
/* Burg muss in gleicher Region sein */
|
||||
/* Schiff muss in gleicher Region sein */
|
||||
sh = NULL;
|
||||
}
|
||||
|
||||
if (sh == NULL) {
|
||||
/* Burg nicht gefunden */
|
||||
if (sh == NULL || sh->number < 1) {
|
||||
/* Schiff nicht gefunden */
|
||||
spobj->flag = TARGET_NOTFOUND;
|
||||
ADDMSG(&mage->faction->msgs, msg_message("spellshipnotfound",
|
||||
"unit region command id", mage, mage->region, ord, spobj->data.i));
|
||||
|
|
138
src/move.c
138
src/move.c
|
@ -102,21 +102,28 @@ typedef struct follower {
|
|||
} follower;
|
||||
|
||||
static void
|
||||
get_followers(unit * target, region * r, const region_list * route_end,
|
||||
get_followers(unit * u, region * r, const region_list * route_end,
|
||||
follower ** followers)
|
||||
{
|
||||
unit *uf;
|
||||
for (uf = r->units; uf; uf = uf->next) {
|
||||
if (fval(uf, UFL_FOLLOWING) && !fval(uf, UFL_NOTMOVING)) {
|
||||
const attrib *a = a_find(uf->attribs, &at_follow);
|
||||
if (a && a->data.v == target) {
|
||||
follower *fnew = (follower *)malloc(sizeof(follower));
|
||||
assert_alloc(fnew);
|
||||
fnew->uf = uf;
|
||||
fnew->ut = target;
|
||||
fnew->route_end = route_end;
|
||||
fnew->next = *followers;
|
||||
*followers = fnew;
|
||||
while (a) {
|
||||
if (a->data.v == u) {
|
||||
follower *fnew = (follower *)malloc(sizeof(follower));
|
||||
assert_alloc(fnew);
|
||||
fnew->uf = uf;
|
||||
fnew->ut = u;
|
||||
fnew->route_end = route_end;
|
||||
fnew->next = *followers;
|
||||
*followers = fnew;
|
||||
break;
|
||||
}
|
||||
a = a->next;
|
||||
if (a && a->type != &at_follow) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2270,7 +2277,7 @@ int follow_ship(unit * u, order * ord)
|
|||
dir = hunted_dir(rc->attribs, id);
|
||||
|
||||
if (dir == NODIRECTION) {
|
||||
if (sh == NULL || sh->region != rc) {
|
||||
if (sh == NULL || sh->number < 1 || sh->region != rc) {
|
||||
cmistake(u, ord, 20, MSG_MOVE);
|
||||
}
|
||||
return 0;
|
||||
|
@ -2493,89 +2500,94 @@ void movement(void)
|
|||
move_pirates();
|
||||
}
|
||||
|
||||
/** Overrides long orders with a FOLLOW order if the target is moving.
|
||||
* BUGS: http://bugs.eressea.de/view.php?id=1444 (A folgt B folgt C)
|
||||
/**
|
||||
* Override long orders with a FOLLOW order if target seems to be moving.
|
||||
*/
|
||||
void follow_unit(unit * u)
|
||||
void follow_cmds(unit * u)
|
||||
{
|
||||
region *r = u->region;
|
||||
attrib *a = NULL;
|
||||
order *ord;
|
||||
order *ord, *o;
|
||||
|
||||
if (fval(u, UFL_NOTMOVING) || LongHunger(u))
|
||||
if (fval(u, UFL_MOVED | UFL_NOTMOVING) || LongHunger(u)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ord = u->orders; ord; ord = ord->next) {
|
||||
const struct locale *lang = u->faction->locale;
|
||||
|
||||
if (getkeyword(ord) == K_FOLLOW) {
|
||||
int id;
|
||||
unit *u2 = NULL;
|
||||
param_t p;
|
||||
init_order(ord, NULL);
|
||||
p = getparam(lang);
|
||||
if (p == P_UNIT) {
|
||||
id = read_unitid(u->faction, r);
|
||||
int id = read_unitid(u->faction, r);
|
||||
if (id == u->no) {
|
||||
ADDMSG(&u->faction->msgs, msg_message("followfail", "unit follower",
|
||||
u, u));
|
||||
continue;
|
||||
}
|
||||
if (a != NULL) {
|
||||
a = a_find(u->attribs, &at_follow);
|
||||
}
|
||||
|
||||
if (id > 0) {
|
||||
unit *uf = findunit(id);
|
||||
if (!a) {
|
||||
a = a_add(&u->attribs, make_follow(uf));
|
||||
u2 = findunit(id);
|
||||
}
|
||||
}
|
||||
else if (p == P_SHIP) {
|
||||
int id = getid();
|
||||
if (id <= 0) {
|
||||
cmistake(u, ord, 20, MSG_MOVE);
|
||||
}
|
||||
else {
|
||||
ship *sh = findship(id);
|
||||
if (sh == NULL || sh->number < 1 || (sh->region != r && hunted_dir(r->attribs, id) == NODIRECTION)) {
|
||||
cmistake(u, ord, 20, MSG_MOVE);
|
||||
}
|
||||
else if (!u->ship && !fval(u_race(u), RCF_FLY|RCF_SWIM)) {
|
||||
cmistake(u, ord, 144, MSG_MOVE);
|
||||
}
|
||||
else if (u->ship && u != ship_owner(u->ship)) {
|
||||
cmistake(u, ord, 146, MSG_MOVE);
|
||||
}
|
||||
else if (!can_move(u)) {
|
||||
cmistake(u, ord, 55, MSG_MOVE);
|
||||
}
|
||||
else {
|
||||
a->data.v = uf;
|
||||
u2 = ship_owner(sh);
|
||||
}
|
||||
}
|
||||
else if (a) {
|
||||
a_remove(&u->attribs, a);
|
||||
a = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (u2) {
|
||||
bool moving = false;
|
||||
if (u2->region != r || !cansee(u->faction, r, u2, 0)) {
|
||||
/* FIXME: u2 sollte hier keine TEMP Einheit sein. */
|
||||
ADDMSG(&u->faction->msgs, msg_message("unitnotfound_id",
|
||||
"unit region command id", u, r, ord, itoa36(u2->no)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (a && !fval(u, UFL_MOVED | UFL_NOTMOVING)) {
|
||||
bool follow = false;
|
||||
unit *u2 = a->data.v;
|
||||
|
||||
if (!u2 || u2->region != r || !cansee(u->faction, r, u2, 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (getkeyword(u2->thisorder)) {
|
||||
case K_MOVE:
|
||||
case K_ROUTE:
|
||||
case K_DRIVE:
|
||||
follow = true;
|
||||
break;
|
||||
default:
|
||||
for (ord = u2->orders; ord; ord = ord->next) {
|
||||
if (K_FOLLOW == getkeyword(ord)) {
|
||||
follow = true;
|
||||
switch (getkeyword(u2->thisorder)) {
|
||||
case K_MOVE:
|
||||
case K_ROUTE:
|
||||
case K_DRIVE:
|
||||
moving = true;
|
||||
break;
|
||||
default:
|
||||
for (o = u2->orders; o; o = o->next) {
|
||||
if (K_FOLLOW == getkeyword(o)) {
|
||||
moving = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (moving) {
|
||||
a_add(&u->attribs, make_follow(u2));
|
||||
fset(u2, UFL_FOLLOWED);
|
||||
/* FOLLOW unit on a (potentially) moving unit prevents long orders */
|
||||
fset(u, UFL_FOLLOWING | UFL_LONGACTION);
|
||||
set_order(&u->thisorder, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!follow) {
|
||||
attrib *a2 = a_find(u2->attribs, &at_follow);
|
||||
if (a2 != NULL) {
|
||||
unit *u3 = a2->data.v;
|
||||
follow = (u3 && u2->region == u3->region);
|
||||
}
|
||||
}
|
||||
if (follow) {
|
||||
fset(u2, UFL_FOLLOWED);
|
||||
/* FOLLOW unit on a (potentially) moving unit prevents long orders */
|
||||
fset(u, UFL_FOLLOWING | UFL_LONGACTION);
|
||||
set_order(&u->thisorder, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ extern "C" {
|
|||
struct region *to, struct region_list *route);
|
||||
int walkingcapacity(const struct unit *u);
|
||||
int movement_speed(const struct unit * u);
|
||||
void follow_unit(struct unit *u);
|
||||
void follow_cmds(struct unit *u);
|
||||
struct unit *owner_buildingtyp(const struct region *r,
|
||||
const struct building_type *bt);
|
||||
bool move_blocked(const struct unit *u, const struct region *src,
|
||||
|
|
|
@ -467,7 +467,7 @@ static void test_follow_unit(CuTest *tc) {
|
|||
u->thisorder = copy_order(ord);
|
||||
|
||||
/* Verfolger müssen ihre Ziele finden, ehe diese sich bewegen */
|
||||
follow_unit(u);
|
||||
follow_cmds(u);
|
||||
CuAssertPtrEquals(tc, &at_follow, (void *)u->attribs->type);
|
||||
CuAssertPtrEquals(tc, u2, u->attribs->data.v);
|
||||
CuAssertPtrEquals(tc, NULL, u->thisorder);
|
||||
|
@ -496,7 +496,7 @@ static void test_follow_unit_self(CuTest *tc) {
|
|||
u = test_create_unit(f, test_create_plain(0, 0));
|
||||
ord = create_order(K_FOLLOW, f->locale, "EINHEIT %s", itoa36(u->no));
|
||||
unit_addorder(u, ord);
|
||||
follow_unit(u);
|
||||
follow_cmds(u);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "followfail"));
|
||||
CuAssertIntEquals(tc, 0, fval(u, UFL_FOLLOWING | UFL_LONGACTION));
|
||||
test_teardown();
|
||||
|
|
|
@ -143,12 +143,14 @@ int renumber_cmd(unit * u, order * ord)
|
|||
i = newcontainerid();
|
||||
}
|
||||
else {
|
||||
ship *sh;
|
||||
i = atoi36((const char *)s);
|
||||
if (i <= 0 || i > MAX_CONTAINER_NR) {
|
||||
cmistake(u, ord, 114, MSG_EVENT);
|
||||
break;
|
||||
}
|
||||
if (findship(i)) {
|
||||
sh = findship(i);
|
||||
if (sh && sh->number > 0) {
|
||||
cmistake(u, ord, 115, MSG_EVENT);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue