forked from github/server
Bug 2684 Astraler Blick
Old implementation was bad, using set_observer is better. Still missing a test, but improved the one for sp_viewreality, which is almost doing the same thing - adaptation should be easy. Fixes https://bugs.eressea.de/view.php?id=2684
This commit is contained in:
parent
9a4bc1ede1
commit
b06f3cf0e2
7 changed files with 56 additions and 91 deletions
|
@ -79,7 +79,7 @@ static void free_nodes(node * root)
|
|||
}
|
||||
}
|
||||
|
||||
struct selist *regions_in_range(struct region *handle_start, int maxdist,
|
||||
struct selist *path_regions_in_range(struct region *handle_start, int maxdist,
|
||||
bool(*allowed) (const struct region *, const struct region *))
|
||||
{
|
||||
selist * rlist = NULL;
|
||||
|
|
|
@ -8,15 +8,10 @@ extern "C" {
|
|||
const struct region *target, int maxlen,
|
||||
bool(*allowed) (const struct region *, const struct region *));
|
||||
extern bool path_exists(struct region *handle_start, const struct region *target,
|
||||
int maxlen, bool(*allowed) (const struct region *,
|
||||
const struct region *));
|
||||
extern bool allowed_swim(const struct region *src,
|
||||
const struct region *target);
|
||||
extern bool allowed_fly(const struct region *src,
|
||||
const struct region *target);
|
||||
extern bool allowed_walk(const struct region *src,
|
||||
const struct region *target);
|
||||
extern struct selist *regions_in_range(struct region *src, int maxdist,
|
||||
int maxlen, bool(*allowed) (const struct region *, const struct region *));
|
||||
extern bool allowed_fly(const struct region *src, const struct region *target);
|
||||
extern bool allowed_walk(const struct region *src, const struct region *target);
|
||||
extern struct selist *path_regions_in_range(struct region *src, int maxdist,
|
||||
bool(*allowed) (const struct region *, const struct region *));
|
||||
|
||||
extern void pathfinder_cleanup(void);
|
||||
|
|
|
@ -497,7 +497,7 @@ static attrib *set_new_dragon_target(unit * u, region * r, int range)
|
|||
{
|
||||
int max_affinity = 0;
|
||||
region *max_region = NULL;
|
||||
selist *ql, *rlist = regions_in_range(r, range, allowed_dragon);
|
||||
selist *ql, *rlist = path_regions_in_range(r, range, allowed_dragon);
|
||||
int qi;
|
||||
|
||||
for (qi = 0, ql = rlist; ql; selist_advance(&ql, &qi, 1)) {
|
||||
|
|
74
src/spells.c
74
src/spells.c
|
@ -5423,19 +5423,22 @@ int sp_fetchastral(castorder * co)
|
|||
return cast_level;
|
||||
}
|
||||
|
||||
#define SHOWASTRAL_IS_BORKED
|
||||
static bool cb_not_astral_blocked(const struct region *rt) {
|
||||
return !is_cursed(rt->attribs, &ct_astralblock);
|
||||
}
|
||||
|
||||
#undef SHOWASTRAL_IS_BORKED
|
||||
#ifndef SHOWASTRAL_IS_BORKED
|
||||
#define SHOWASTRAL_MAX_RADIUS 5
|
||||
int sp_showastral(castorder * co)
|
||||
{
|
||||
unit *u;
|
||||
region *rt;
|
||||
int n = 0;
|
||||
int c = 0;
|
||||
region_list *rl, *rl2;
|
||||
region *r = co_get_region(co);
|
||||
unit *mage = co_get_caster(co);
|
||||
int cast_level = co->level;
|
||||
double power = co->force;
|
||||
int force = (int) co->force;
|
||||
int radius = (force < SHOWASTRAL_MAX_RADIUS) ? force : SHOWASTRAL_MAX_RADIUS;
|
||||
region *targets[4 * SHOWASTRAL_MAX_RADIUS * SHOWASTRAL_MAX_RADIUS];
|
||||
|
||||
switch (getplaneid(r)) {
|
||||
case 0:
|
||||
|
@ -5455,62 +5458,21 @@ int sp_showastral(castorder * co)
|
|||
return 0;
|
||||
}
|
||||
|
||||
rl = all_in_range(rt, power / 5);
|
||||
|
||||
/* Erst Einheiten zaehlen, fuer die Grammatik. */
|
||||
|
||||
for (rl2 = rl; rl2; rl2 = rl2->next) {
|
||||
region *r2 = rl2->data;
|
||||
if (!is_cursed(r2->attribs, &ct_astralblock)) {
|
||||
for (u = r2->units; u; u = u->next) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n = regions_in_range(rt, radius, cb_not_astral_blocked, targets);
|
||||
if (n == 0) {
|
||||
/* sprintf(buf, "%s kann niemanden im astralen Nebel entdecken.",
|
||||
unitname(mage)); */
|
||||
cmistake(mage, co->order, 220, MSG_MAGIC);
|
||||
}
|
||||
else {
|
||||
|
||||
/* Ausgeben */
|
||||
|
||||
sprintf(buf, "%s hat eine Vision der astralen Ebene. Im astralen "
|
||||
"Nebel zu erkennen sind ", unitname(mage));
|
||||
|
||||
for (rl2 = rl; rl2; rl2 = rl2->next) {
|
||||
if (!is_cursed(rl2->data->attribs, &ct_astralblock)) {
|
||||
for (u = rl2->data->units; u; u = u->next) {
|
||||
c++;
|
||||
scat(unitname(u));
|
||||
scat(" (");
|
||||
if (!fval(u, UFL_ANON_FACTION)) {
|
||||
scat(factionname(u->faction));
|
||||
scat(", ");
|
||||
int i;
|
||||
for (i = 0; i != n; ++i) {
|
||||
region *rt = targets[i];
|
||||
set_observer(rt, mage->faction, (int)(co->force / 2), 2);
|
||||
}
|
||||
icat(u->number);
|
||||
scat(" ");
|
||||
scat(LOC(mage->faction->locale, rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL)));
|
||||
scat(", Entfernung ");
|
||||
icat(distance(rl2->data, rt));
|
||||
scat(")");
|
||||
if (c == n - 1) {
|
||||
scat(" und ");
|
||||
}
|
||||
else if (c < n - 1) {
|
||||
scat(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scat(".");
|
||||
addmessage(r, mage->faction, buf, MSG_MAGIC, ML_INFO);
|
||||
}
|
||||
|
||||
free_regionlist(rl);
|
||||
return cast_level;
|
||||
return co->level;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -5519,7 +5481,7 @@ int sp_viewreality(castorder * co)
|
|||
{
|
||||
region *r = co_get_region(co);
|
||||
unit *mage = co_get_caster(co);
|
||||
int cast_level = co->level;
|
||||
int force = (int)co->force;
|
||||
message *m;
|
||||
region *rl[MAX_SCHEMES];
|
||||
int num;
|
||||
|
@ -5537,7 +5499,7 @@ int sp_viewreality(castorder * co)
|
|||
for (i = 0; i != num; ++i) {
|
||||
region *rt = rl[i];
|
||||
if (!is_cursed(rt->attribs, &ct_astralblock)) {
|
||||
set_observer(rt, mage->faction, co->level / 2, 2);
|
||||
set_observer(rt, mage->faction, force / 2, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5546,7 +5508,7 @@ int sp_viewreality(castorder * co)
|
|||
r_addmessage(r, mage->faction, m);
|
||||
msg_release(m);
|
||||
|
||||
return cast_level;
|
||||
return co->level;
|
||||
}
|
||||
|
||||
static void cb_disrupt_astral(region *r2, void *cbdata) {
|
||||
|
|
|
@ -116,7 +116,7 @@ static void test_bad_dreams(CuTest *tc) {
|
|||
}
|
||||
|
||||
static void test_view_reality(CuTest *tc) {
|
||||
region *r, *ra;
|
||||
region *r, *ra, *rx;
|
||||
faction *f;
|
||||
unit *u;
|
||||
castorder co;
|
||||
|
@ -127,12 +127,13 @@ static void test_view_reality(CuTest *tc) {
|
|||
mt_create_va(mt_new("viewreality_effect", NULL),
|
||||
"unit:unit", MT_NEW_END);
|
||||
r = test_create_region(0, 0, NULL);
|
||||
rx = test_create_region(0, TP_RADIUS+1, NULL);
|
||||
ra = test_create_region(real2tp(r->x), real2tp(r->y), NULL);
|
||||
ra->_plane = get_astralplane();
|
||||
f = test_create_faction(NULL);
|
||||
u = test_create_unit(f, r);
|
||||
|
||||
test_create_castorder(&co, u, 10, 10., 0, NULL);
|
||||
test_create_castorder(&co, u, 10, 10.0, 0, NULL);
|
||||
CuAssertIntEquals(tc, -1, get_observer(r, f));
|
||||
CuAssertIntEquals(tc, 0, sp_viewreality(&co));
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "spell_astral_only"));
|
||||
|
@ -141,11 +142,12 @@ static void test_view_reality(CuTest *tc) {
|
|||
test_clear_messagelist(&f->msgs);
|
||||
move_unit(u, ra, NULL);
|
||||
|
||||
test_create_castorder(&co, u, 9, 10., 0, NULL);
|
||||
test_create_castorder(&co, u, 9, 10.0, 0, NULL);
|
||||
CuAssertIntEquals(tc, -1, get_observer(r, f));
|
||||
CuAssertIntEquals(tc, 9, sp_viewreality(&co));
|
||||
CuAssertPtrEquals(tc, NULL, test_find_messagetype(f->msgs, "spell_astral_only"));
|
||||
CuAssertIntEquals(tc, 4, get_observer(r, f));
|
||||
CuAssertIntEquals(tc, 5, get_observer(r, f));
|
||||
CuAssertIntEquals(tc, -1, get_observer(rx, f));
|
||||
CuAssertPtrEquals(tc, f, (void *)ra->individual_messages->viewer);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(ra->individual_messages->msgs, "viewreality_effect"));
|
||||
free_castorder(&co);
|
||||
|
|
|
@ -43,21 +43,18 @@ static region *tpregion(const region * r)
|
|||
return rt;
|
||||
}
|
||||
|
||||
|
||||
int get_astralregions(const region * r, bool(*valid) (const region *), region *result[])
|
||||
int regions_in_range(const region * r, int radius, bool(*valid) (const region *), region *result[])
|
||||
{
|
||||
assert(is_astral(r));
|
||||
r = r_astral_to_standard(r);
|
||||
if (r) {
|
||||
int x, y, num = 0;
|
||||
for (x = -TP_RADIUS; x <= +TP_RADIUS; ++x) {
|
||||
for (y = -TP_RADIUS; y <= +TP_RADIUS; ++y) {
|
||||
region *rn;
|
||||
const struct plane *pl = rplane(r);
|
||||
for (x = -radius; x <= +radius; ++x) {
|
||||
for (y = -radius; y <= radius; ++y) {
|
||||
int dist = koor_distance(0, 0, x, y);
|
||||
|
||||
if (dist <= TP_RADIUS) {
|
||||
if (dist <= radius) {
|
||||
region *rn;
|
||||
int nx = r->x + x, ny = r->y + y;
|
||||
pnormalize(&nx, &ny, rplane(r));
|
||||
pnormalize(&nx, &ny, pl);
|
||||
rn = findregion(nx, ny);
|
||||
if (rn != NULL && (valid == NULL || valid(rn))) {
|
||||
if (result) {
|
||||
|
@ -70,6 +67,14 @@ int get_astralregions(const region * r, bool(*valid) (const region *), region *r
|
|||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
int get_astralregions(const region * r, bool(*valid) (const region *), region *result[])
|
||||
{
|
||||
assert(is_astral(r));
|
||||
r = r_astral_to_standard(r);
|
||||
if (r) {
|
||||
return regions_in_range(r, TP_RADIUS, valid, result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ extern "C" {
|
|||
bool is_astral(const struct region *r);
|
||||
struct plane *get_astralplane(void);
|
||||
int get_astralregions(const struct region * r, bool(*valid) (const struct region *), struct region *result[]);
|
||||
int regions_in_range(const struct region * r, int radius, bool(*valid) (const struct region *), struct region *result[]);
|
||||
|
||||
void create_teleport_plane(void);
|
||||
void spawn_braineaters(float chance);
|
||||
|
|
Loading…
Reference in a new issue