forked from github/server
resolve cansee and cansee_unit code-duplication
This commit is contained in:
parent
aeed92fa80
commit
407de0db20
4 changed files with 91 additions and 109 deletions
190
src/laws.c
190
src/laws.c
|
@ -4021,10 +4021,79 @@ void turn_end(void)
|
||||||
update_spells();
|
update_spells();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum cansee_t {
|
||||||
|
CANSEE_DETECTED,
|
||||||
|
CANSEE_HIDDEN,
|
||||||
|
CANSEE_INVISIBLE
|
||||||
|
} cansee_t;
|
||||||
|
|
||||||
|
static enum cansee_t cansee_ex(const unit *u, const region *r, const unit *target, int stealth, int rings)
|
||||||
|
{
|
||||||
|
enum cansee_t result = CANSEE_HIDDEN;
|
||||||
|
if (rings >= target->number) {
|
||||||
|
const resource_type *rtype = get_resourcetype(R_AMULET_OF_TRUE_SEEING);
|
||||||
|
int amulet = i_get(u->items, rtype->itype);
|
||||||
|
if (amulet <= 0) {
|
||||||
|
return CANSEE_INVISIBLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skill_enabled(SK_PERCEPTION)) {
|
||||||
|
int watch = effskill(u, SK_PERCEPTION, r);
|
||||||
|
if (stealth > watch) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CANSEE_DETECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_exposed(const unit *u) {
|
||||||
|
return u->building || u->ship || is_guard(u) || leftship(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool big_sea_monster(const unit *u, const region *r) {
|
||||||
|
return ((r->terrain->flags & SEA_REGION) && (u_race(u)->weight >= 5000));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
cansee_unit(const unit * u, const region *r, const unit * target, int modifier)
|
||||||
|
/* r kann != u->region sein, wenn es um durchreisen geht */
|
||||||
|
{
|
||||||
|
int stealth, rings;
|
||||||
|
enum cansee_t see;
|
||||||
|
if (target->number == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (target->faction == u->faction || omniscient(u->faction)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (is_exposed(target)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (target->number == 0) {
|
||||||
|
attrib *a = a_find(target->attribs, &at_creator);
|
||||||
|
if (a) {
|
||||||
|
/* u is an empty temporary unit. In this special case we look at the creating unit. */
|
||||||
|
target = (unit *)a->data.v;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stealth = eff_stealth(target, r) - modifier;
|
||||||
|
rings = invisible(target, NULL);
|
||||||
|
see = cansee_ex(u, r, target, stealth, rings);
|
||||||
|
if (CANSEE_HIDDEN == see) {
|
||||||
|
/* bug 2763 and 2754: can see sea serpents on oceans */
|
||||||
|
return big_sea_monster(u, r);
|
||||||
|
}
|
||||||
|
return CANSEE_DETECTED == see;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if unit can be seen by faction.
|
* Determine if unit can be seen by faction.
|
||||||
*
|
*
|
||||||
* @param f -- the observiong faction
|
* @param f -- the observing faction
|
||||||
* @param u -- the unit that is observed
|
* @param u -- the unit that is observed
|
||||||
* @param r -- the region that u is obesrved from (see below)
|
* @param r -- the region that u is obesrved from (see below)
|
||||||
* @param m -- terrain modifier to stealth
|
* @param m -- terrain modifier to stealth
|
||||||
|
@ -4034,15 +4103,18 @@ void turn_end(void)
|
||||||
* Es muss auch niemand aus f in der region sein, wenn sie vom Turm
|
* Es muss auch niemand aus f in der region sein, wenn sie vom Turm
|
||||||
* erblickt wird.
|
* erblickt wird.
|
||||||
*/
|
*/
|
||||||
bool cansee(const faction * f, const region * r, const unit * u, int modifier)
|
bool cansee(const faction *f, const region *r, const unit *u, int modifier)
|
||||||
{
|
{
|
||||||
unit *u2;
|
unit *u2;
|
||||||
int stealth, rings;
|
int rings, stealth;
|
||||||
|
bool bsm, result;
|
||||||
|
|
||||||
|
/* quick exits: */
|
||||||
if (u->faction == f || omniscient(f)) {
|
if (u->faction == f || omniscient(f)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (u->number == 0) {
|
else if (u->number == 0) {
|
||||||
|
/* no need to do this in each cansee_unit: */
|
||||||
attrib *a = a_find(u->attribs, &at_creator);
|
attrib *a = a_find(u->attribs, &at_creator);
|
||||||
if (a) {
|
if (a) {
|
||||||
/* u is an empty temporary unit. In this special case we look at the creating unit. */
|
/* u is an empty temporary unit. In this special case we look at the creating unit. */
|
||||||
|
@ -4052,9 +4124,8 @@ bool cansee(const faction * f, const region * r, const unit * u, int modifier)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_exposed(u)) {
|
||||||
/* simple visibility, just gotta have a viewer in the region to see 'em */
|
/* obviosuly visibile, we only need a viewer in the region */
|
||||||
if (leftship(u) || is_guard(u) || u->building || u->ship) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4065,117 +4136,30 @@ bool cansee(const faction * f, const region * r, const unit * u, int modifier)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = bsm = big_sea_monster(u, r);
|
||||||
for (u2 = r->units; u2; u2 = u2->next) {
|
for (u2 = r->units; u2; u2 = u2->next) {
|
||||||
if (u2->faction == f) {
|
if (u2->faction == f) {
|
||||||
if (rings < u->number || invisible(u, u2) < u->number) {
|
enum cansee_t see = cansee_ex(u2, r, u, stealth, rings);
|
||||||
if (skill_enabled(SK_PERCEPTION)) {
|
if (see == CANSEE_DETECTED) {
|
||||||
int observation = effskill(u2, SK_PERCEPTION, NULL);
|
|
||||||
|
|
||||||
if (observation >= stealth) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* bug 2763 and 2754: sea serpents are visible on oceans */
|
|
||||||
if ((u->region->terrain->flags & SEA_REGION) && (u_race(u)->weight >= 5000)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cansee_unit(const unit * u, const unit * target, int modifier)
|
|
||||||
/* target->region kann != u->region sein, wenn es um durchreisen geht */
|
|
||||||
{
|
|
||||||
if (target->number == 0)
|
|
||||||
return false;
|
|
||||||
else if (target->faction == u->faction)
|
|
||||||
return true;
|
|
||||||
else {
|
|
||||||
int n, rings;
|
|
||||||
|
|
||||||
if (is_guard(target) || target->building
|
|
||||||
|| target->ship) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = eff_stealth(target, target->region) - modifier;
|
|
||||||
rings = invisible(target, NULL);
|
|
||||||
if (rings == 0 && n <= 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rings && invisible(target, u) >= target->number) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (skill_enabled(SK_PERCEPTION)) {
|
|
||||||
int o = effskill(u, SK_PERCEPTION, target->region);
|
|
||||||
if (o >= n) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
else if (see == CANSEE_HIDDEN && bsm) {
|
||||||
else {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
cansee_durchgezogen(const faction * f, const region * r, const unit * u,
|
|
||||||
int modifier)
|
|
||||||
/* r kann != u->region sein, wenn es um durchreisen geht */
|
|
||||||
/* und es muss niemand aus f in der region sein, wenn sie vom Turm
|
|
||||||
* erblickt wird */
|
|
||||||
{
|
|
||||||
unit *u2;
|
|
||||||
|
|
||||||
if (u->number == 0)
|
|
||||||
return false;
|
|
||||||
else if (u->faction == f)
|
|
||||||
return true;
|
|
||||||
else {
|
|
||||||
int rings, n;
|
|
||||||
|
|
||||||
if (is_guard(u) || u->building || u->ship) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = eff_stealth(u, r) - modifier;
|
|
||||||
rings = invisible(u, NULL);
|
|
||||||
if (rings == 0 && n <= 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u2 = r->units; u2; u2 = u2->next) {
|
|
||||||
if (u2->faction == f) {
|
|
||||||
int o;
|
|
||||||
|
|
||||||
if (rings && invisible(u, u2) >= u->number)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
o = effskill(u2, SK_PERCEPTION, NULL);
|
|
||||||
|
|
||||||
if (o >= n) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* still invisible to all: */
|
||||||
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
seefaction(const faction * f, const region * r, const unit * u, int modifier)
|
seefaction(const faction * f, const region * r, const unit * u, int modifier)
|
||||||
{
|
{
|
||||||
if (((f == u->faction) || !fval(u, UFL_ANON_FACTION))
|
if (((f == u->faction) || !fval(u, UFL_ANON_FACTION))
|
||||||
&& cansee(f, r, u, modifier))
|
&& cansee(f, r, u, modifier)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,9 +86,7 @@ extern "C" {
|
||||||
|
|
||||||
bool cansee(const struct faction * f, const struct region * r,
|
bool cansee(const struct faction * f, const struct region * r,
|
||||||
const struct unit *u, int modifier);
|
const struct unit *u, int modifier);
|
||||||
bool cansee_durchgezogen(const struct faction *f, const struct region *r,
|
bool cansee_unit(const struct unit *u, const struct region *r, const struct unit *who,
|
||||||
const struct unit *u, int modifier);
|
|
||||||
bool cansee_unit(const struct unit *u, const struct unit *target,
|
|
||||||
int modifier);
|
int modifier);
|
||||||
bool seefaction(const struct faction *f, const struct region *r,
|
bool seefaction(const struct faction *f, const struct region *r,
|
||||||
const struct unit *u, int modifier);
|
const struct unit *u, int modifier);
|
||||||
|
|
|
@ -1045,7 +1045,7 @@ static void cb_add_address(region *r, unit *ut, void *cbdata) {
|
||||||
for (u = r->units; u; u = u->next) {
|
for (u = r->units; u; u = u->next) {
|
||||||
faction *sf = visible_faction(f, u);
|
faction *sf = visible_faction(f, u);
|
||||||
assert(u->faction != f); /* if this is see_travel only, then I shouldn't be here. */
|
assert(u->faction != f); /* if this is see_travel only, then I shouldn't be here. */
|
||||||
if (data->lastf != sf && cansee_unit(ut, u, data->stealthmod)) {
|
if (data->lastf != sf && cansee_unit(ut, r, u, data->stealthmod)) {
|
||||||
add_seen_faction_i(data->flist, sf);
|
add_seen_faction_i(data->flist, sf);
|
||||||
data->lastf = sf;
|
data->lastf = sf;
|
||||||
}
|
}
|
||||||
|
@ -2361,7 +2361,7 @@ static void count_cb(region *r, unit *u, void *cbdata) {
|
||||||
count_data *data = (count_data *)cbdata;
|
count_data *data = (count_data *)cbdata;
|
||||||
const struct faction *f = data->f;
|
const struct faction *f = data->f;
|
||||||
if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) {
|
if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) {
|
||||||
if (cansee_durchgezogen(f, r, u, 0)) {
|
if (cansee(f, r, u, 0)) {
|
||||||
++data->n;
|
++data->n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ void travelthru_add(region * r, unit * u)
|
||||||
|
|
||||||
bool travelthru_cansee(const struct region *r, const struct faction *f, const struct unit *u) {
|
bool travelthru_cansee(const struct region *r, const struct faction *f, const struct unit *u) {
|
||||||
if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) {
|
if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) {
|
||||||
return cansee_durchgezogen(f, r, u, 0);
|
return cansee(f, r, u, 0);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue