forked from github/server
Merge pull request #66 from badgerman/getunit-refactor
refactoring getunit
This commit is contained in:
commit
5751a9b3a9
|
@ -4004,7 +4004,7 @@ static bool start_battle(region * r, battle ** bp)
|
||||||
|
|
||||||
init_order(ord);
|
init_order(ord);
|
||||||
/* attackierte Einheit ermitteln */
|
/* attackierte Einheit ermitteln */
|
||||||
u2 = getunit(r, u->faction);
|
getunit(r, u->faction, &u2);
|
||||||
|
|
||||||
/* Beginn Fehlerbehandlung */
|
/* Beginn Fehlerbehandlung */
|
||||||
/* Fehler: "Die Einheit wurde nicht gefunden" */
|
/* Fehler: "Die Einheit wurde nicht gefunden" */
|
||||||
|
|
|
@ -629,20 +629,18 @@ int give_control_cmd(unit * u, order * ord)
|
||||||
region *r = u->region;
|
region *r = u->region;
|
||||||
unit *u2;
|
unit *u2;
|
||||||
const char *s;
|
const char *s;
|
||||||
param_t p;
|
|
||||||
|
|
||||||
init_order(ord);
|
init_order(ord);
|
||||||
u2 = getunit(r, u->faction);
|
getunit(r, u->faction, &u2);
|
||||||
s = getstrtoken();
|
|
||||||
p = findparam(s, u->faction->locale);
|
|
||||||
|
|
||||||
/* first, do all the ones that do not require HELP_GIVE or CONTACT */
|
s = getstrtoken();
|
||||||
if (p == P_CONTROL) {
|
if (isparam(s, u->faction->locale, P_CONTROL)) {
|
||||||
message *msg = 0;
|
message *msg = 0;
|
||||||
|
|
||||||
if (!u2 || u2->number == 0) {
|
if (!can_give_to(u, u2)) {
|
||||||
msg = msg_feedback(u, ord, "feedback_unit_not_found", "");
|
ADDMSG(&u->faction->msgs,
|
||||||
ADDMSG(&u->faction->msgs, msg);
|
msg_feedback(u, ord, "feedback_unit_not_found", ""));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else if (!u->building && !u->ship) {
|
else if (!u->building && !u->ship) {
|
||||||
msg = cmistake(u, ord, 140, MSG_EVENT);
|
msg = cmistake(u, ord, 140, MSG_EVENT);
|
||||||
|
|
54
src/give.c
54
src/give.c
|
@ -434,7 +434,7 @@ void give_unit(unit * u, unit * u2, order * ord)
|
||||||
cmistake(u, ord, 152, MSG_COMMERCE);
|
cmistake(u, ord, 152, MSG_COMMERCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (getunitpeasants) {
|
else {
|
||||||
unit *u3;
|
unit *u3;
|
||||||
|
|
||||||
for (u3 = r->units; u3; u3 = u3->next)
|
for (u3 = r->units; u3; u3 = u3->next)
|
||||||
|
@ -461,10 +461,6 @@ void give_unit(unit * u, unit * u2, order * ord)
|
||||||
cmistake(u, ord, 153, MSG_COMMERCE);
|
cmistake(u, ord, 153, MSG_COMMERCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found",
|
|
||||||
""));
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,12 +516,25 @@ void give_unit(unit * u, unit * u2, order * ord)
|
||||||
u2->faction->newbies += n;
|
u2->faction->newbies += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool can_give_to(unit *u, unit *u2) {
|
||||||
|
/* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */
|
||||||
|
if (!u2 || u2->number == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (u2 && !alliedunit(u2, u->faction, HELP_GIVE)
|
||||||
|
&& !cansee(u->faction, u->region, u2, 0) && !ucontact(u2, u)
|
||||||
|
&& !fval(u2, UFL_TAKEALL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void give_cmd(unit * u, order * ord)
|
void give_cmd(unit * u, order * ord)
|
||||||
{
|
{
|
||||||
region *r = u->region;
|
region *r = u->region;
|
||||||
unit *u2;
|
unit *u2;
|
||||||
const char *s;
|
const char *s;
|
||||||
int n;
|
int err, n;
|
||||||
const item_type *itype;
|
const item_type *itype;
|
||||||
param_t p;
|
param_t p;
|
||||||
plane *pl;
|
plane *pl;
|
||||||
|
@ -534,7 +543,7 @@ void give_cmd(unit * u, order * ord)
|
||||||
|
|
||||||
kwd = init_order(ord);
|
kwd = init_order(ord);
|
||||||
assert(kwd == K_GIVE);
|
assert(kwd == K_GIVE);
|
||||||
u2 = getunit(r, u->faction);
|
err = getunit(r, u->faction, &u2);
|
||||||
s = getstrtoken();
|
s = getstrtoken();
|
||||||
n = s ? atoip(s) : 0;
|
n = s ? atoip(s) : 0;
|
||||||
p = (n > 0) ? NOPARAM : findparam(s, u->faction->locale);
|
p = (n > 0) ? NOPARAM : findparam(s, u->faction->locale);
|
||||||
|
@ -545,9 +554,13 @@ void give_cmd(unit * u, order * ord)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!u2 && !getunitpeasants) {
|
if (err == GET_NOTFOUND || (err != GET_PEASANTS && !can_give_to(u, u2))) {
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found",
|
ADDMSG(&u->faction->msgs,
|
||||||
""));
|
msg_feedback(u, ord, "feedback_unit_not_found", ""));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (u == u2) {
|
||||||
|
cmistake(u, ord, 8, MSG_COMMERCE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,19 +570,6 @@ void give_cmd(unit * u, order * ord)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */
|
|
||||||
if (u2 && !alliedunit(u2, u->faction, HELP_GIVE)
|
|
||||||
&& !cansee(u->faction, r, u2, 0) && !ucontact(u2, u)
|
|
||||||
&& !fval(u2, UFL_TAKEALL)) {
|
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found",
|
|
||||||
""));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (u == u2) {
|
|
||||||
cmistake(u, ord, 8, MSG_COMMERCE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht
|
/* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht
|
||||||
* wirklich einfach. */
|
* wirklich einfach. */
|
||||||
pl = rplane(r);
|
pl = rplane(r);
|
||||||
|
@ -605,11 +605,6 @@ void give_cmd(unit * u, order * ord)
|
||||||
msg_feedback(u, ord, "race_notake", "race", u_race(u2)));
|
msg_feedback(u, ord, "race_notake", "race", u_race(u2)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!u2 && !getunitpeasants) {
|
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord,
|
|
||||||
"feedback_unit_not_found", ""));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (u->items) {
|
if (u->items) {
|
||||||
item **itmp = &u->items;
|
item **itmp = &u->items;
|
||||||
while (*itmp) {
|
while (*itmp) {
|
||||||
|
@ -628,8 +623,9 @@ void give_cmd(unit * u, order * ord)
|
||||||
itmp = &itm->next;
|
itmp = &itm->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!given)
|
if (!given) {
|
||||||
cmistake(u, ord, 38, MSG_COMMERCE);
|
cmistake(u, ord, 38, MSG_COMMERCE);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ extern "C" {
|
||||||
void give_unit(struct unit *u, struct unit *u2, struct order *ord);
|
void give_unit(struct unit *u, struct unit *u2, struct order *ord);
|
||||||
void give_cmd(struct unit * u, struct order * ord);
|
void give_cmd(struct unit * u, struct order * ord);
|
||||||
struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord);
|
struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord);
|
||||||
|
bool can_give_to(struct unit *u, struct unit *u2);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,6 @@ static void test_give_unit_to_peasants(CuTest * tc) {
|
||||||
env.f2 = 0;
|
env.f2 = 0;
|
||||||
setup_give(&env);
|
setup_give(&env);
|
||||||
rsetpeasants(env.r, 0);
|
rsetpeasants(env.r, 0);
|
||||||
getunitpeasants = true;
|
|
||||||
give_unit(env.src, NULL, NULL);
|
give_unit(env.src, NULL, NULL);
|
||||||
CuAssertIntEquals(tc, 0, env.src->number);
|
CuAssertIntEquals(tc, 0, env.src->number);
|
||||||
CuAssertIntEquals(tc, 1, env.r->land->peasants);
|
CuAssertIntEquals(tc, 1, env.r->land->peasants);
|
||||||
|
@ -57,7 +56,6 @@ static void test_give_unit_in_ocean(CuTest * tc) {
|
||||||
env.f2 = 0;
|
env.f2 = 0;
|
||||||
setup_give(&env);
|
setup_give(&env);
|
||||||
env.r->terrain = test_create_terrain("ocean", SEA_REGION);
|
env.r->terrain = test_create_terrain("ocean", SEA_REGION);
|
||||||
getunitpeasants = true;
|
|
||||||
give_unit(env.src, NULL, NULL);
|
give_unit(env.src, NULL, NULL);
|
||||||
CuAssertIntEquals(tc, 0, env.src->number);
|
CuAssertIntEquals(tc, 0, env.src->number);
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
|
|
|
@ -1013,32 +1013,32 @@ int read_unitid(const faction * f, const region * r)
|
||||||
return atoi36((const char *)s);
|
return atoi36((const char *)s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* exported symbol */
|
int getunit(const region * r, const faction * f, unit **uresult)
|
||||||
bool getunitpeasants;
|
|
||||||
|
|
||||||
unit *getunit(const region * r, const faction * f)
|
|
||||||
{
|
{
|
||||||
int n = read_unitid(f, r);
|
int n = read_unitid(f, r);
|
||||||
unit *u2;
|
int result = GET_NOTFOUND;
|
||||||
|
unit *u2 = NULL;
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
getunitpeasants = 1;
|
result = GET_PEASANTS;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
getunitpeasants = 0;
|
else if (n>0) {
|
||||||
if (n < 0)
|
u2 = findunit(n);
|
||||||
return 0;
|
if (u2 != NULL && u2->region == r) {
|
||||||
|
/* there used to be a 'u2->flags & UFL_ISNEW || u2->number>0' condition
|
||||||
u2 = findunit(n);
|
* here, but it got removed because of a bug that made units disappear:
|
||||||
if (u2 != NULL && u2->region == r) {
|
* http://eressea.upb.de/mantis/bug_view_page.php?bug_id=0000172
|
||||||
/* there used to be a 'u2->flags & UFL_ISNEW || u2->number>0' condition
|
*/
|
||||||
* here, but it got removed because of a bug that made units disappear:
|
result = GET_UNIT;
|
||||||
* http://eressea.upb.de/mantis/bug_view_page.php?bug_id=0000172
|
}
|
||||||
*/
|
else {
|
||||||
return u2;
|
u2 = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (uresult) {
|
||||||
return NULL;
|
*uresult = u2;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - String Listen --------------------------------------------- */
|
/* - String Listen --------------------------------------------- */
|
||||||
|
|
|
@ -60,6 +60,11 @@ extern "C" {
|
||||||
#define PLAGUE_HEALCHANCE 0.25F /* Wahrscheinlichkeit Heilung */
|
#define PLAGUE_HEALCHANCE 0.25F /* Wahrscheinlichkeit Heilung */
|
||||||
#define PLAGUE_HEALCOST 30 /* Heilkosten */
|
#define PLAGUE_HEALCOST 30 /* Heilkosten */
|
||||||
|
|
||||||
|
|
||||||
|
/* getunit results: */
|
||||||
|
#define GET_UNIT 0
|
||||||
|
#define GET_NOTFOUND 1
|
||||||
|
#define GET_PEASANTS 2
|
||||||
/* Bewegungsweiten: */
|
/* Bewegungsweiten: */
|
||||||
#define BP_WALKING 4
|
#define BP_WALKING 4
|
||||||
#define BP_RIDING 6
|
#define BP_RIDING 6
|
||||||
|
@ -163,7 +168,7 @@ extern "C" {
|
||||||
struct unit *createunit(struct region *r, struct faction *f,
|
struct unit *createunit(struct region *r, struct faction *f,
|
||||||
int number, const struct race *rc);
|
int number, const struct race *rc);
|
||||||
void create_unitid(struct unit *u, int id);
|
void create_unitid(struct unit *u, int id);
|
||||||
struct unit *getunit(const struct region *r, const struct faction *f);
|
int getunit(const struct region * r, const struct faction * f, struct unit **uresult);
|
||||||
|
|
||||||
int read_unitid(const struct faction *f, const struct region *r);
|
int read_unitid(const struct faction *f, const struct region *r);
|
||||||
|
|
||||||
|
@ -371,7 +376,6 @@ extern "C" {
|
||||||
|
|
||||||
extern int turn;
|
extern int turn;
|
||||||
extern int verbosity;
|
extern int verbosity;
|
||||||
extern bool getunitpeasants;
|
|
||||||
|
|
||||||
/** report options **/
|
/** report options **/
|
||||||
extern const char *options[MAXOPTIONS];
|
extern const char *options[MAXOPTIONS];
|
||||||
|
|
|
@ -2,10 +2,68 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <kernel/config.h>
|
#include <kernel/config.h>
|
||||||
|
#include <kernel/terrain.h>
|
||||||
|
#include <kernel/unit.h>
|
||||||
|
#include <kernel/order.h>
|
||||||
|
#include <util/language.h>
|
||||||
|
#include <util/base36.h>
|
||||||
|
#include <util/attrib.h>
|
||||||
|
|
||||||
#include <CuTest.h>
|
#include <CuTest.h>
|
||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
|
|
||||||
|
struct critbit_tree;
|
||||||
|
|
||||||
|
static void test_getunit(CuTest *tc) {
|
||||||
|
unit *u, *u2;
|
||||||
|
order *ord;
|
||||||
|
attrib *a;
|
||||||
|
struct region *r;
|
||||||
|
struct locale *lang;
|
||||||
|
struct terrain_type *t_plain;
|
||||||
|
struct critbit_tree ** cb;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
lang = get_or_create_locale("de");
|
||||||
|
cb = (struct critbit_tree **)get_translations(lang, UT_PARAMS);
|
||||||
|
add_translation(cb, "TEMP", P_TEMP);
|
||||||
|
/* note that the english order is FIGHT, not COMBAT, so this is a poor example */
|
||||||
|
t_plain = test_create_terrain("plain", LAND_REGION);
|
||||||
|
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, t_plain));
|
||||||
|
a = a_add(&u->attribs, a_new(&at_alias));
|
||||||
|
a->data.i = atoi36("42"); /* this unit is also TEMP 42 */
|
||||||
|
r = test_create_region(1, 0, t_plain);
|
||||||
|
|
||||||
|
ord = create_order(K_GIVE, lang, itoa36(u->no));
|
||||||
|
init_order(ord);
|
||||||
|
CuAssertIntEquals(tc, GET_UNIT, getunit(u->region, u->faction, &u2));
|
||||||
|
CuAssertPtrEquals(tc, u, u2);
|
||||||
|
init_order(ord);
|
||||||
|
CuAssertIntEquals(tc, GET_NOTFOUND, getunit(r, u->faction, &u2));
|
||||||
|
CuAssertPtrEquals(tc, NULL, u2);
|
||||||
|
free_order(ord);
|
||||||
|
|
||||||
|
ord = create_order(K_GIVE, lang, itoa36(u->no+1));
|
||||||
|
init_order(ord);
|
||||||
|
CuAssertIntEquals(tc, GET_NOTFOUND, getunit(u->region, u->faction, &u2));
|
||||||
|
CuAssertPtrEquals(tc, NULL, u2);
|
||||||
|
free_order(ord);
|
||||||
|
|
||||||
|
ord = create_order(K_GIVE, lang, "0");
|
||||||
|
init_order(ord);
|
||||||
|
CuAssertIntEquals(tc, GET_PEASANTS, getunit(u->region, u->faction, &u2));
|
||||||
|
CuAssertPtrEquals(tc, NULL, u2);
|
||||||
|
free_order(ord);
|
||||||
|
|
||||||
|
ord = create_order(K_GIVE, lang, "TEMP 42");
|
||||||
|
init_order(ord);
|
||||||
|
CuAssertIntEquals(tc, GET_UNIT, getunit(u->region, u->faction, &u2));
|
||||||
|
CuAssertPtrEquals(tc, u, u2);
|
||||||
|
free_order(ord);
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
static void test_get_set_param(CuTest * tc)
|
static void test_get_set_param(CuTest * tc)
|
||||||
{
|
{
|
||||||
struct param *par = 0;
|
struct param *par = 0;
|
||||||
|
@ -42,6 +100,7 @@ static void test_param_flt(CuTest * tc)
|
||||||
CuSuite *get_config_suite(void)
|
CuSuite *get_config_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, test_getunit);
|
||||||
SUITE_ADD_TEST(suite, test_get_set_param);
|
SUITE_ADD_TEST(suite, test_get_set_param);
|
||||||
SUITE_ADD_TEST(suite, test_param_int);
|
SUITE_ADD_TEST(suite, test_param_int);
|
||||||
SUITE_ADD_TEST(suite, test_param_flt);
|
SUITE_ADD_TEST(suite, test_param_flt);
|
||||||
|
|
|
@ -1828,8 +1828,9 @@ int name_cmd(struct unit *u, struct order *ord)
|
||||||
|
|
||||||
case P_UNIT:
|
case P_UNIT:
|
||||||
if (foreign) {
|
if (foreign) {
|
||||||
unit *u2 = getunit(r, u->faction);
|
unit *u2 = 0;
|
||||||
|
|
||||||
|
getunit(r, u->faction, &u2);
|
||||||
if (!u2 || !cansee(u->faction, r, u2, 0)) {
|
if (!u2 || !cansee(u->faction, r, u2, 0)) {
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord,
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord,
|
||||||
"feedback_unit_not_found", ""));
|
"feedback_unit_not_found", ""));
|
||||||
|
|
32
src/move.c
32
src/move.c
|
@ -1247,8 +1247,10 @@ static bool transport(unit * ut, unit * u)
|
||||||
|
|
||||||
for (ord = ut->orders; ord; ord = ord->next) {
|
for (ord = ut->orders; ord; ord = ord->next) {
|
||||||
if (getkeyword(ord) == K_TRANSPORT) {
|
if (getkeyword(ord) == K_TRANSPORT) {
|
||||||
|
unit *u2;
|
||||||
init_order(ord);
|
init_order(ord);
|
||||||
if (getunit(ut->region, ut->faction) == u) {
|
getunit(ut->region, ut->faction, &u2);
|
||||||
|
if (u2 == u) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1278,11 +1280,10 @@ static void init_transportation(void)
|
||||||
for (u = r->units; u; u = u->next) {
|
for (u = r->units; u; u = u->next) {
|
||||||
if (getkeyword(u->thisorder) == K_DRIVE && can_move(u)
|
if (getkeyword(u->thisorder) == K_DRIVE && can_move(u)
|
||||||
&& !fval(u, UFL_NOTMOVING) && !LongHunger(u)) {
|
&& !fval(u, UFL_NOTMOVING) && !LongHunger(u)) {
|
||||||
unit *ut;
|
unit *ut = 0;
|
||||||
|
|
||||||
init_order(u->thisorder);
|
init_order(u->thisorder);
|
||||||
ut = getunit(r, u->faction);
|
if (getunit(r, u->faction, &ut) != GET_UNIT) {
|
||||||
if (ut == NULL) {
|
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder,
|
ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder,
|
||||||
"feedback_unit_not_found", ""));
|
"feedback_unit_not_found", ""));
|
||||||
continue;
|
continue;
|
||||||
|
@ -1312,14 +1313,18 @@ static void init_transportation(void)
|
||||||
if (getkeyword(ord) == K_TRANSPORT) {
|
if (getkeyword(ord) == K_TRANSPORT) {
|
||||||
init_order(ord);
|
init_order(ord);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
unit *ut = getunit(r, u->faction);
|
unit *ut = 0;
|
||||||
|
|
||||||
if (ut == NULL)
|
if (getunit(r, u->faction, &ut) != GET_UNIT) {
|
||||||
break;
|
break;
|
||||||
if (getkeyword(ut->thisorder) == K_DRIVE && can_move(ut)
|
}
|
||||||
&& !fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) {
|
if (getkeyword(ut->thisorder) == K_DRIVE &&
|
||||||
|
can_move(ut) && !fval(ut, UFL_NOTMOVING) &&
|
||||||
|
!LongHunger(ut)) {
|
||||||
|
unit *u2;
|
||||||
init_order(ut->thisorder);
|
init_order(ut->thisorder);
|
||||||
if (getunit(r, ut->faction) == u) {
|
getunit(r, ut->faction, &u2);
|
||||||
|
if (u2 == u) {
|
||||||
w += weight(ut);
|
w += weight(ut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2198,14 +2203,13 @@ static const region_list *travel_i(unit * u, const region_list * route_begin,
|
||||||
|
|
||||||
/* transportation */
|
/* transportation */
|
||||||
for (ord = u->orders; ord; ord = ord->next) {
|
for (ord = u->orders; ord; ord = ord->next) {
|
||||||
unit *ut;
|
unit *ut = 0;
|
||||||
|
|
||||||
if (getkeyword(ord) != K_TRANSPORT)
|
if (getkeyword(ord) != K_TRANSPORT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
init_order(ord);
|
init_order(ord);
|
||||||
ut = getunit(r, u->faction);
|
if (getunit(r, u->faction, &ut) == GET_UNIT) {
|
||||||
if (ut != NULL) {
|
|
||||||
if (getkeyword(ut->thisorder) == K_DRIVE) {
|
if (getkeyword(ut->thisorder) == K_DRIVE) {
|
||||||
if (ut->building && !can_leave(ut)) {
|
if (ut->building && !can_leave(ut)) {
|
||||||
cmistake(ut, ut->thisorder, 150, MSG_MOVE);
|
cmistake(ut, ut->thisorder, 150, MSG_MOVE);
|
||||||
|
@ -2218,8 +2222,10 @@ static const region_list *travel_i(unit * u, const region_list * route_begin,
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
if (!fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) {
|
if (!fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) {
|
||||||
|
unit *u2;
|
||||||
init_order(ut->thisorder);
|
init_order(ut->thisorder);
|
||||||
if (getunit(u->region, ut->faction) == u) {
|
getunit(u->region, ut->faction, &u2);
|
||||||
|
if (u2 == u) {
|
||||||
const region_list *route_to =
|
const region_list *route_to =
|
||||||
travel_route(ut, route_begin, route_end, ord,
|
travel_route(ut, route_begin, route_end, ord,
|
||||||
TRAVEL_TRANSPORTED);
|
TRAVEL_TRANSPORTED);
|
||||||
|
|
779
src/spy.c
779
src/spy.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de>
|
Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de>
|
||||||
Katja Zedel <katze@felidae.kn-bremen.de
|
Katja Zedel <katze@felidae.kn-bremen.de
|
||||||
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -58,453 +58,464 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
* Spionage des Spions */
|
* Spionage des Spions */
|
||||||
void spy_message(int spy, const unit * u, const unit * target)
|
void spy_message(int spy, const unit * u, const unit * target)
|
||||||
{
|
{
|
||||||
const char *str = report_kampfstatus(target, u->faction->locale);
|
const char *str = report_kampfstatus(target, u->faction->locale);
|
||||||
|
|
||||||
ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target status", u,
|
ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target status", u,
|
||||||
target, str));
|
target, str));
|
||||||
if (spy > 20) {
|
if (spy > 20) {
|
||||||
sc_mage *mage = get_mage(target);
|
sc_mage *mage = get_mage(target);
|
||||||
/* for mages, spells and magic school */
|
/* for mages, spells and magic school */
|
||||||
if (mage) {
|
if (mage) {
|
||||||
ADDMSG(&u->faction->msgs, msg_message("spyreport_mage", "target type",
|
ADDMSG(&u->faction->msgs, msg_message("spyreport_mage", "target type",
|
||||||
target, magic_school[mage->magietyp]));
|
target, magic_school[mage->magietyp]));
|
||||||
}
|
|
||||||
}
|
|
||||||
if (spy > 6) {
|
|
||||||
faction *fv = visible_faction(u->faction, target);
|
|
||||||
if (fv && fv != target->faction) {
|
|
||||||
/* true faction */
|
|
||||||
ADDMSG(&u->faction->msgs, msg_message("spyreport_faction",
|
|
||||||
"target faction", target, target->faction));
|
|
||||||
add_seen_faction(u->faction, target->faction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (spy > 0) {
|
|
||||||
int first = 1;
|
|
||||||
int found = 0;
|
|
||||||
skill *sv;
|
|
||||||
char buf[4096];
|
|
||||||
|
|
||||||
buf[0] = 0;
|
|
||||||
for (sv = target->skills; sv != target->skills + target->skill_size; ++sv) {
|
|
||||||
if (sv->level > 0) {
|
|
||||||
found++;
|
|
||||||
if (first == 1) {
|
|
||||||
first = 0;
|
|
||||||
} else {
|
|
||||||
strncat(buf, ", ", sizeof(buf)-1);
|
|
||||||
}
|
}
|
||||||
strncat(buf, (const char *)skillname((skill_t)sv->id, u->faction->locale),
|
|
||||||
sizeof(buf)-1);
|
|
||||||
strncat(buf, " ", sizeof(buf)-1);
|
|
||||||
strncat(buf, itoa10(eff_skill(target, (skill_t)sv->id, target->region)),
|
|
||||||
sizeof(buf)-1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (found) {
|
if (spy > 6) {
|
||||||
ADDMSG(&u->faction->msgs, msg_message("spyreport_skills", "target skills",
|
faction *fv = visible_faction(u->faction, target);
|
||||||
target, buf));
|
if (fv && fv != target->faction) {
|
||||||
|
/* true faction */
|
||||||
|
ADDMSG(&u->faction->msgs, msg_message("spyreport_faction",
|
||||||
|
"target faction", target, target->faction));
|
||||||
|
add_seen_faction(u->faction, target->faction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (spy > 0) {
|
||||||
|
int first = 1;
|
||||||
|
int found = 0;
|
||||||
|
skill *sv;
|
||||||
|
char buf[4096];
|
||||||
|
|
||||||
if (target->items) {
|
buf[0] = 0;
|
||||||
ADDMSG(&u->faction->msgs, msg_message("spyreport_items", "target items",
|
for (sv = target->skills; sv != target->skills + target->skill_size; ++sv) {
|
||||||
target, target->items));
|
if (sv->level > 0) {
|
||||||
|
found++;
|
||||||
|
if (first == 1) {
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strncat(buf, ", ", sizeof(buf) - 1);
|
||||||
|
}
|
||||||
|
strncat(buf, (const char *)skillname((skill_t)sv->id, u->faction->locale),
|
||||||
|
sizeof(buf) - 1);
|
||||||
|
strncat(buf, " ", sizeof(buf) - 1);
|
||||||
|
strncat(buf, itoa10(eff_skill(target, (skill_t)sv->id, target->region)),
|
||||||
|
sizeof(buf) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
ADDMSG(&u->faction->msgs, msg_message("spyreport_skills", "target skills",
|
||||||
|
target, buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target->items) {
|
||||||
|
ADDMSG(&u->faction->msgs, msg_message("spyreport_items", "target items",
|
||||||
|
target, target->items));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int spy_cmd(unit * u, struct order *ord)
|
int spy_cmd(unit * u, struct order *ord)
|
||||||
{
|
{
|
||||||
unit *target;
|
unit *target;
|
||||||
int spy, observe;
|
int spy, observe;
|
||||||
double spychance, observechance;
|
double spychance, observechance;
|
||||||
region *r = u->region;
|
region *r = u->region;
|
||||||
|
|
||||||
init_order(ord);
|
init_order(ord);
|
||||||
target = getunit(r, u->faction);
|
getunit(r, u->faction, &target);
|
||||||
|
|
||||||
if (!target) {
|
if (!target) {
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder,
|
ADDMSG(&u->faction->msgs,
|
||||||
"feedback_unit_not_found", ""));
|
msg_feedback(u, u->thisorder, "feedback_unit_not_found", ""));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!can_contact(r, u, target)) {
|
||||||
|
cmistake(u, u->thisorder, 24, MSG_EVENT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (eff_skill(u, SK_SPY, r) < 1) {
|
||||||
|
cmistake(u, u->thisorder, 39, MSG_EVENT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Die Grundchance fuer einen erfolgreichen Spionage-Versuch ist 10%.
|
||||||
|
* Fuer jeden Talentpunkt, den das Spionagetalent das Tarnungstalent
|
||||||
|
* des Opfers uebersteigt, erhoeht sich dieses um 5%*/
|
||||||
|
spy = eff_skill(u, SK_SPY, r) - eff_skill(target, SK_STEALTH, r);
|
||||||
|
spychance = 0.1 + _max(spy * 0.05, 0.0);
|
||||||
|
|
||||||
|
if (chance(spychance)) {
|
||||||
|
produceexp(u, SK_SPY, u->number);
|
||||||
|
spy_message(spy, u, target);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ADDMSG(&u->faction->msgs, msg_message("spyfail", "spy target", u, target));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* der Spion kann identifiziert werden, wenn das Opfer bessere
|
||||||
|
* Wahrnehmung als das Ziel Tarnung + Spionage/2 hat */
|
||||||
|
observe = eff_skill(target, SK_PERCEPTION, r)
|
||||||
|
- (effskill(u, SK_STEALTH) + eff_skill(u, SK_SPY, r) / 2);
|
||||||
|
|
||||||
|
if (invisible(u, target) >= u->number) {
|
||||||
|
observe = _min(observe, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Anschliessend wird - unabhaengig vom Erfolg - gewuerfelt, ob der
|
||||||
|
* Spionageversuch bemerkt wurde. Die Wahrscheinlich dafuer ist (100 -
|
||||||
|
* SpionageSpion*5 + WahrnehmungOpfer*2)%. */
|
||||||
|
observechance = 1.0 - (eff_skill(u, SK_SPY, r) * 0.05)
|
||||||
|
+ (eff_skill(target, SK_PERCEPTION, r) * 0.02);
|
||||||
|
|
||||||
|
if (chance(observechance)) {
|
||||||
|
ADDMSG(&target->faction->msgs, msg_message("spydetect",
|
||||||
|
"spy target", observe > 0 ? u : NULL, target));
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (!can_contact(r, u, target)) {
|
|
||||||
cmistake(u, u->thisorder, 24, MSG_EVENT);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (eff_skill(u, SK_SPY, r) < 1) {
|
|
||||||
cmistake(u, u->thisorder, 39, MSG_EVENT);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Die Grundchance fuer einen erfolgreichen Spionage-Versuch ist 10%.
|
|
||||||
* Fuer jeden Talentpunkt, den das Spionagetalent das Tarnungstalent
|
|
||||||
* des Opfers uebersteigt, erhoeht sich dieses um 5%*/
|
|
||||||
spy = eff_skill(u, SK_SPY, r) - eff_skill(target, SK_STEALTH, r);
|
|
||||||
spychance = 0.1 + _max(spy * 0.05, 0.0);
|
|
||||||
|
|
||||||
if (chance(spychance)) {
|
|
||||||
produceexp(u, SK_SPY, u->number);
|
|
||||||
spy_message(spy, u, target);
|
|
||||||
} else {
|
|
||||||
ADDMSG(&u->faction->msgs, msg_message("spyfail", "spy target", u, target));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* der Spion kann identifiziert werden, wenn das Opfer bessere
|
|
||||||
* Wahrnehmung als das Ziel Tarnung + Spionage/2 hat */
|
|
||||||
observe = eff_skill(target, SK_PERCEPTION, r)
|
|
||||||
- (effskill(u, SK_STEALTH) + eff_skill(u, SK_SPY, r) / 2);
|
|
||||||
|
|
||||||
if (invisible(u, target) >= u->number) {
|
|
||||||
observe = _min(observe, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Anschliessend wird - unabhaengig vom Erfolg - gewuerfelt, ob der
|
|
||||||
* Spionageversuch bemerkt wurde. Die Wahrscheinlich dafuer ist (100 -
|
|
||||||
* SpionageSpion*5 + WahrnehmungOpfer*2)%. */
|
|
||||||
observechance = 1.0 - (eff_skill(u, SK_SPY, r) * 0.05)
|
|
||||||
+ (eff_skill(target, SK_PERCEPTION, r) * 0.02);
|
|
||||||
|
|
||||||
if (chance(observechance)) {
|
|
||||||
ADDMSG(&target->faction->msgs, msg_message("spydetect",
|
|
||||||
"spy target", observe > 0 ? u : NULL, target));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_factionstealth(unit * u, faction * f)
|
void set_factionstealth(unit * u, faction * f)
|
||||||
{
|
{
|
||||||
region *lastr = NULL;
|
region *lastr = NULL;
|
||||||
/* for all units mu of our faction, check all the units in the region
|
/* for all units mu of our faction, check all the units in the region
|
||||||
* they are in, if their visible faction is f, it's ok. use lastr to
|
* they are in, if their visible faction is f, it's ok. use lastr to
|
||||||
* avoid testing the same region twice in a row. */
|
* avoid testing the same region twice in a row. */
|
||||||
unit *mu = u->faction->units;
|
unit *mu = u->faction->units;
|
||||||
while (mu != NULL) {
|
while (mu != NULL) {
|
||||||
if (mu->number && mu->region != lastr) {
|
if (mu->number && mu->region != lastr) {
|
||||||
unit *ru = mu->region->units;
|
unit *ru = mu->region->units;
|
||||||
lastr = mu->region;
|
lastr = mu->region;
|
||||||
while (ru != NULL) {
|
while (ru != NULL) {
|
||||||
if (ru->number) {
|
if (ru->number) {
|
||||||
faction *fv = visible_faction(f, ru);
|
faction *fv = visible_faction(f, ru);
|
||||||
if (fv == f) {
|
if (fv == f) {
|
||||||
if (cansee(f, lastr, ru, 0))
|
if (cansee(f, lastr, ru, 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
ru = ru->next;
|
||||||
|
}
|
||||||
|
if (ru != NULL)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
ru = ru->next;
|
mu = mu->nextF;
|
||||||
}
|
}
|
||||||
if (ru != NULL)
|
if (mu != NULL) {
|
||||||
break;
|
attrib *a = a_find(u->attribs, &at_otherfaction);
|
||||||
|
if (!a)
|
||||||
|
a = a_add(&u->attribs, make_otherfaction(f));
|
||||||
|
else
|
||||||
|
a->data.v = f;
|
||||||
}
|
}
|
||||||
mu = mu->nextF;
|
|
||||||
}
|
|
||||||
if (mu != NULL) {
|
|
||||||
attrib *a = a_find(u->attribs, &at_otherfaction);
|
|
||||||
if (!a)
|
|
||||||
a = a_add(&u->attribs, make_otherfaction(f));
|
|
||||||
else
|
|
||||||
a->data.v = f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int setstealth_cmd(unit * u, struct order *ord)
|
int setstealth_cmd(unit * u, struct order *ord)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
int level, rule;
|
int level, rule;
|
||||||
const race *trace;
|
const race *trace;
|
||||||
|
|
||||||
init_order(ord);
|
init_order(ord);
|
||||||
s = getstrtoken();
|
s = getstrtoken();
|
||||||
|
|
||||||
/* Tarne ohne Parameter: Setzt maximale Tarnung */
|
/* Tarne ohne Parameter: Setzt maximale Tarnung */
|
||||||
|
|
||||||
if (s == NULL || *s == 0) {
|
if (s == NULL || *s == 0) {
|
||||||
u_seteffstealth(u, -1);
|
u_seteffstealth(u, -1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (isdigit(s[0])) {
|
|
||||||
/* Tarnungslevel setzen */
|
|
||||||
level = atoi((const char *)s);
|
|
||||||
if (level > effskill(u, SK_STEALTH)) {
|
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_lowstealth", ""));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
u_seteffstealth(u, level);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
trace = findrace(s, u->faction->locale);
|
|
||||||
if (trace) {
|
|
||||||
/* demons can cloak as other player-races */
|
|
||||||
if (u_race(u) == get_race(RC_DAEMON)) {
|
|
||||||
race_t allowed[] = { RC_DWARF, RC_ELF, RC_ORC, RC_GOBLIN, RC_HUMAN,
|
|
||||||
RC_TROLL, RC_DAEMON, RC_INSECT, RC_HALFLING, RC_CAT, RC_AQUARIAN,
|
|
||||||
NORACE
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
for (i = 0; allowed[i] != NORACE; ++i)
|
|
||||||
if (get_race(allowed[i]) == trace)
|
|
||||||
break;
|
|
||||||
if (get_race(allowed[i]) == trace) {
|
|
||||||
u->irace = trace;
|
|
||||||
if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs))
|
|
||||||
set_racename(&u->attribs, NULL);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Singdrachen koennen sich nur als Drachen tarnen */
|
if (isdigit(s[0])) {
|
||||||
if (u_race(u) == get_race(RC_SONGDRAGON)
|
/* Tarnungslevel setzen */
|
||||||
|| u_race(u) == get_race(RC_BIRTHDAYDRAGON)) {
|
level = atoi((const char *)s);
|
||||||
if (trace == get_race(RC_SONGDRAGON) || trace == get_race(RC_FIREDRAGON)
|
if (level > effskill(u, SK_STEALTH)) {
|
||||||
|| trace == get_race(RC_DRAGON) || trace == get_race(RC_WYRM)) {
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_lowstealth", ""));
|
||||||
u->irace = trace;
|
return 0;
|
||||||
if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs))
|
|
||||||
set_racename(&u->attribs, NULL);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Daemomen und Illusionsparteien koennen sich als andere race tarnen */
|
|
||||||
if (u_race(u)->flags & RCF_SHAPESHIFT) {
|
|
||||||
if (playerrace(trace)) {
|
|
||||||
u->irace = trace;
|
|
||||||
if ((u_race(u)->flags & RCF_SHAPESHIFTANY) && get_racename(u->attribs))
|
|
||||||
set_racename(&u->attribs, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (findparam(s, u->faction->locale)) {
|
|
||||||
case P_FACTION:
|
|
||||||
/* TARNE PARTEI [NICHT|NUMMER abcd] */
|
|
||||||
rule = rule_stealth_faction();
|
|
||||||
if (!rule) {
|
|
||||||
/* TARNE PARTEI is disabled */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
s = getstrtoken();
|
|
||||||
if (rule&1) {
|
|
||||||
if (!s || *s == 0) {
|
|
||||||
fset(u, UFL_ANON_FACTION);
|
|
||||||
break;
|
|
||||||
} else if (findparam(s, u->faction->locale) == P_NOT) {
|
|
||||||
freset(u, UFL_ANON_FACTION);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
u_seteffstealth(u, level);
|
||||||
if (rule&2) {
|
return 0;
|
||||||
if (get_keyword(s, u->faction->locale) == K_NUMBER) {
|
}
|
||||||
const char *s2 = getstrtoken();
|
|
||||||
int nr = -1;
|
|
||||||
|
|
||||||
if (s2) {
|
trace = findrace(s, u->faction->locale);
|
||||||
nr = atoi36(s2);
|
if (trace) {
|
||||||
}
|
/* demons can cloak as other player-races */
|
||||||
if (!s2 || *s2 == 0 || nr == u->faction->no) {
|
if (u_race(u) == get_race(RC_DAEMON)) {
|
||||||
a_removeall(&u->attribs, &at_otherfaction);
|
race_t allowed[] = { RC_DWARF, RC_ELF, RC_ORC, RC_GOBLIN, RC_HUMAN,
|
||||||
break;
|
RC_TROLL, RC_DAEMON, RC_INSECT, RC_HALFLING, RC_CAT, RC_AQUARIAN,
|
||||||
} else {
|
NORACE
|
||||||
struct faction *f = findfaction(nr);
|
};
|
||||||
if (f == NULL) {
|
int i;
|
||||||
cmistake(u, ord, 66, MSG_EVENT);
|
for (i = 0; allowed[i] != NORACE; ++i)
|
||||||
break;
|
if (get_race(allowed[i]) == trace)
|
||||||
} else {
|
break;
|
||||||
set_factionstealth(u, f);
|
if (get_race(allowed[i]) == trace) {
|
||||||
break;
|
u->irace = trace;
|
||||||
|
if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs))
|
||||||
|
set_racename(&u->attribs, NULL);
|
||||||
}
|
}
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cmistake(u, ord, 289, MSG_EVENT);
|
/* Singdrachen koennen sich nur als Drachen tarnen */
|
||||||
break;
|
if (u_race(u) == get_race(RC_SONGDRAGON)
|
||||||
|
|| u_race(u) == get_race(RC_BIRTHDAYDRAGON)) {
|
||||||
|
if (trace == get_race(RC_SONGDRAGON) || trace == get_race(RC_FIREDRAGON)
|
||||||
|
|| trace == get_race(RC_DRAGON) || trace == get_race(RC_WYRM)) {
|
||||||
|
u->irace = trace;
|
||||||
|
if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs))
|
||||||
|
set_racename(&u->attribs, NULL);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Daemomen und Illusionsparteien koennen sich als andere race tarnen */
|
||||||
|
if (u_race(u)->flags & RCF_SHAPESHIFT) {
|
||||||
|
if (playerrace(trace)) {
|
||||||
|
u->irace = trace;
|
||||||
|
if ((u_race(u)->flags & RCF_SHAPESHIFTANY) && get_racename(u->attribs))
|
||||||
|
set_racename(&u->attribs, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (findparam(s, u->faction->locale)) {
|
||||||
|
case P_FACTION:
|
||||||
|
/* TARNE PARTEI [NICHT|NUMMER abcd] */
|
||||||
|
rule = rule_stealth_faction();
|
||||||
|
if (!rule) {
|
||||||
|
/* TARNE PARTEI is disabled */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s = getstrtoken();
|
||||||
|
if (rule & 1) {
|
||||||
|
if (!s || *s == 0) {
|
||||||
|
fset(u, UFL_ANON_FACTION);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (findparam(s, u->faction->locale) == P_NOT) {
|
||||||
|
freset(u, UFL_ANON_FACTION);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rule & 2) {
|
||||||
|
if (get_keyword(s, u->faction->locale) == K_NUMBER) {
|
||||||
|
const char *s2 = getstrtoken();
|
||||||
|
int nr = -1;
|
||||||
|
|
||||||
|
if (s2) {
|
||||||
|
nr = atoi36(s2);
|
||||||
|
}
|
||||||
|
if (!s2 || *s2 == 0 || nr == u->faction->no) {
|
||||||
|
a_removeall(&u->attribs, &at_otherfaction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct faction *f = findfaction(nr);
|
||||||
|
if (f == NULL) {
|
||||||
|
cmistake(u, ord, 66, MSG_EVENT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
set_factionstealth(u, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmistake(u, ord, 289, MSG_EVENT);
|
||||||
|
break;
|
||||||
case P_ANY:
|
case P_ANY:
|
||||||
case P_NOT:
|
case P_NOT:
|
||||||
/* TARNE ALLES (was nicht so alles geht?) */
|
/* TARNE ALLES (was nicht so alles geht?) */
|
||||||
u_seteffstealth(u, -1);
|
u_seteffstealth(u, -1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (u_race(u)->flags & RCF_SHAPESHIFTANY) {
|
if (u_race(u)->flags & RCF_SHAPESHIFTANY) {
|
||||||
set_racename(&u->attribs, s);
|
set_racename(&u->attribs, s);
|
||||||
} else {
|
}
|
||||||
cmistake(u, ord, 289, MSG_EVENT);
|
else {
|
||||||
}
|
cmistake(u, ord, 289, MSG_EVENT);
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int crew_skill(region * r, faction * f, ship * sh, skill_t sk)
|
static int crew_skill(region * r, faction * f, ship * sh, skill_t sk)
|
||||||
{
|
{
|
||||||
int value = 0;
|
int value = 0;
|
||||||
unit *u;
|
unit *u;
|
||||||
|
|
||||||
for (u = r->units; u; u = u->next) {
|
for (u = r->units; u; u = u->next) {
|
||||||
if (u->ship == sh && u->faction == f) {
|
if (u->ship == sh && u->faction == f) {
|
||||||
int s = eff_skill(u, sk, r);
|
int s = eff_skill(u, sk, r);
|
||||||
value = _max(s, value);
|
value = _max(s, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return value;
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int try_destruction(unit * u, unit * u2, const ship * sh, int skilldiff)
|
static int try_destruction(unit * u, unit * u2, const ship * sh, int skilldiff)
|
||||||
{
|
{
|
||||||
const char *destruction_success_msg = "destroy_ship_0";
|
const char *destruction_success_msg = "destroy_ship_0";
|
||||||
const char *destruction_failed_msg = "destroy_ship_1";
|
const char *destruction_failed_msg = "destroy_ship_1";
|
||||||
const char *destruction_detected_msg = "destroy_ship_2";
|
const char *destruction_detected_msg = "destroy_ship_2";
|
||||||
const char *detect_failure_msg = "destroy_ship_3";
|
const char *detect_failure_msg = "destroy_ship_3";
|
||||||
const char *object_destroyed_msg = "destroy_ship_4";
|
const char *object_destroyed_msg = "destroy_ship_4";
|
||||||
|
|
||||||
if (skilldiff == 0) {
|
if (skilldiff == 0) {
|
||||||
/* tell the unit that the attempt failed: */
|
/* tell the unit that the attempt failed: */
|
||||||
ADDMSG(&u->faction->msgs, msg_message(destruction_failed_msg, "ship unit",
|
ADDMSG(&u->faction->msgs, msg_message(destruction_failed_msg, "ship unit",
|
||||||
sh, u));
|
sh, u));
|
||||||
/* tell the enemy about the attempt: */
|
/* tell the enemy about the attempt: */
|
||||||
if (u2) {
|
if (u2) {
|
||||||
ADDMSG(&u2->faction->msgs, msg_message(detect_failure_msg, "ship", sh));
|
ADDMSG(&u2->faction->msgs, msg_message(detect_failure_msg, "ship", sh));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
else if (skilldiff < 0) {
|
||||||
} else if (skilldiff < 0) {
|
/* tell the unit that the attempt was detected: */
|
||||||
/* tell the unit that the attempt was detected: */
|
ADDMSG(&u2->faction->msgs, msg_message(destruction_detected_msg,
|
||||||
ADDMSG(&u2->faction->msgs, msg_message(destruction_detected_msg,
|
"ship unit", sh, u));
|
||||||
"ship unit", sh, u));
|
/* tell the enemy whodunit: */
|
||||||
/* tell the enemy whodunit: */
|
if (u2) {
|
||||||
if (u2) {
|
ADDMSG(&u2->faction->msgs, msg_message(detect_failure_msg, "ship", sh));
|
||||||
ADDMSG(&u2->faction->msgs, msg_message(detect_failure_msg, "ship", sh));
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
else {
|
||||||
} else {
|
/* tell the unit that the attempt succeeded */
|
||||||
/* tell the unit that the attempt succeeded */
|
ADDMSG(&u->faction->msgs, msg_message(destruction_success_msg, "ship unit",
|
||||||
ADDMSG(&u->faction->msgs, msg_message(destruction_success_msg, "ship unit",
|
sh, u));
|
||||||
sh, u));
|
if (u2) {
|
||||||
if (u2) {
|
ADDMSG(&u2->faction->msgs, msg_message(object_destroyed_msg, "ship", sh));
|
||||||
ADDMSG(&u2->faction->msgs, msg_message(object_destroyed_msg, "ship", sh));
|
}
|
||||||
}
|
}
|
||||||
}
|
return 1; /* success */
|
||||||
return 1; /* success */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
|
static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
|
||||||
{
|
{
|
||||||
unit **ui, *u;
|
unit **ui, *u;
|
||||||
region *safety = r;
|
region *safety = r;
|
||||||
int i;
|
int i;
|
||||||
direction_t d;
|
direction_t d;
|
||||||
double probability = 0.0;
|
double probability = 0.0;
|
||||||
message *sink_msg = NULL;
|
message *sink_msg = NULL;
|
||||||
faction *f;
|
faction *f;
|
||||||
|
|
||||||
for (f = NULL, u = r->units; u; u = u->next) {
|
for (f = NULL, u = r->units; u; u = u->next) {
|
||||||
/* slight optimization to avoid dereferencing u->faction each time */
|
/* slight optimization to avoid dereferencing u->faction each time */
|
||||||
if (f != u->faction) {
|
if (f != u->faction) {
|
||||||
f = u->faction;
|
f = u->faction;
|
||||||
freset(f, FFL_SELECT);
|
freset(f, FFL_SELECT);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* figure out what a unit's chances of survival are: */
|
|
||||||
if (!fval(r->terrain, SEA_REGION)) {
|
|
||||||
probability = CANAL_SWIMMER_CHANCE;
|
|
||||||
} else {
|
|
||||||
for (d = 0; d != MAXDIRECTIONS; ++d) {
|
|
||||||
region *rn = rconnect(r, d);
|
|
||||||
if (!fval(rn->terrain, SEA_REGION) && !move_blocked(NULL, r, rn)) {
|
|
||||||
safety = rn;
|
|
||||||
probability = OCEAN_SWIMMER_CHANCE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ui = &r->units; *ui; ui = &(*ui)->next) {
|
|
||||||
unit *u = *ui;
|
|
||||||
|
|
||||||
/* inform this faction about the sinking ship: */
|
|
||||||
if (!fval(u->faction, FFL_SELECT)) {
|
|
||||||
fset(u->faction, FFL_SELECT);
|
|
||||||
if (sink_msg == NULL) {
|
|
||||||
sink_msg = msg_message("sink_msg", "ship region", sh, r);
|
|
||||||
}
|
|
||||||
add_message(&f->msgs, sink_msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (u->ship == sh) {
|
/* figure out what a unit's chances of survival are: */
|
||||||
int dead = 0;
|
if (!fval(r->terrain, SEA_REGION)) {
|
||||||
message *msg;
|
probability = CANAL_SWIMMER_CHANCE;
|
||||||
|
|
||||||
/* if this fails, I misunderstood something: */
|
|
||||||
for (i = 0; i != u->number; ++i)
|
|
||||||
if (chance(probability))
|
|
||||||
++dead;
|
|
||||||
|
|
||||||
if (dead != u->number) {
|
|
||||||
/* she will live. but her items get stripped */
|
|
||||||
if (dead > 0) {
|
|
||||||
msg =
|
|
||||||
msg_message("sink_lost_msg", "dead region unit", dead, safety, u);
|
|
||||||
} else {
|
|
||||||
msg = msg_message("sink_saved_msg", "region unit", safety, u);
|
|
||||||
}
|
|
||||||
leave_ship(u);
|
|
||||||
if (r != safety) {
|
|
||||||
setguard(u, GUARD_NONE);
|
|
||||||
}
|
|
||||||
while (u->items) {
|
|
||||||
i_remove(&u->items, u->items);
|
|
||||||
}
|
|
||||||
move_unit(u, safety, NULL);
|
|
||||||
} else {
|
|
||||||
msg = msg_message("sink_lost_msg", "dead region unit", dead, NULL, u);
|
|
||||||
}
|
|
||||||
add_message(&u->faction->msgs, msg);
|
|
||||||
msg_release(msg);
|
|
||||||
if (dead == u->number) {
|
|
||||||
/* the poor creature, she dies */
|
|
||||||
if (remove_unit(ui, u) != 0) {
|
|
||||||
ui = &u->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
if (sink_msg)
|
for (d = 0; d != MAXDIRECTIONS; ++d) {
|
||||||
msg_release(sink_msg);
|
region *rn = rconnect(r, d);
|
||||||
/* finally, get rid of the ship */
|
if (!fval(rn->terrain, SEA_REGION) && !move_blocked(NULL, r, rn)) {
|
||||||
remove_ship(&sh->region->ships, sh);
|
safety = rn;
|
||||||
|
probability = OCEAN_SWIMMER_CHANCE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ui = &r->units; *ui; ui = &(*ui)->next) {
|
||||||
|
unit *u = *ui;
|
||||||
|
|
||||||
|
/* inform this faction about the sinking ship: */
|
||||||
|
if (!fval(u->faction, FFL_SELECT)) {
|
||||||
|
fset(u->faction, FFL_SELECT);
|
||||||
|
if (sink_msg == NULL) {
|
||||||
|
sink_msg = msg_message("sink_msg", "ship region", sh, r);
|
||||||
|
}
|
||||||
|
add_message(&f->msgs, sink_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u->ship == sh) {
|
||||||
|
int dead = 0;
|
||||||
|
message *msg;
|
||||||
|
|
||||||
|
/* if this fails, I misunderstood something: */
|
||||||
|
for (i = 0; i != u->number; ++i)
|
||||||
|
if (chance(probability))
|
||||||
|
++dead;
|
||||||
|
|
||||||
|
if (dead != u->number) {
|
||||||
|
/* she will live. but her items get stripped */
|
||||||
|
if (dead > 0) {
|
||||||
|
msg =
|
||||||
|
msg_message("sink_lost_msg", "dead region unit", dead, safety, u);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = msg_message("sink_saved_msg", "region unit", safety, u);
|
||||||
|
}
|
||||||
|
leave_ship(u);
|
||||||
|
if (r != safety) {
|
||||||
|
setguard(u, GUARD_NONE);
|
||||||
|
}
|
||||||
|
while (u->items) {
|
||||||
|
i_remove(&u->items, u->items);
|
||||||
|
}
|
||||||
|
move_unit(u, safety, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = msg_message("sink_lost_msg", "dead region unit", dead, NULL, u);
|
||||||
|
}
|
||||||
|
add_message(&u->faction->msgs, msg);
|
||||||
|
msg_release(msg);
|
||||||
|
if (dead == u->number) {
|
||||||
|
/* the poor creature, she dies */
|
||||||
|
if (remove_unit(ui, u) != 0) {
|
||||||
|
ui = &u->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sink_msg)
|
||||||
|
msg_release(sink_msg);
|
||||||
|
/* finally, get rid of the ship */
|
||||||
|
remove_ship(&sh->region->ships, sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sabotage_cmd(unit * u, struct order *ord)
|
int sabotage_cmd(unit * u, struct order *ord)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
int i;
|
int i;
|
||||||
ship *sh;
|
ship *sh;
|
||||||
unit *u2;
|
unit *u2;
|
||||||
char buffer[DISPLAYSIZE];
|
char buffer[DISPLAYSIZE];
|
||||||
region *r = u->region;
|
region *r = u->region;
|
||||||
int skdiff;
|
int skdiff;
|
||||||
|
|
||||||
init_order(ord);
|
init_order(ord);
|
||||||
s = getstrtoken();
|
s = getstrtoken();
|
||||||
|
|
||||||
i = findparam(s, u->faction->locale);
|
i = findparam(s, u->faction->locale);
|
||||||
|
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case P_SHIP:
|
case P_SHIP:
|
||||||
sh = u->ship;
|
sh = u->ship;
|
||||||
if (!sh) {
|
if (!sh) {
|
||||||
cmistake(u, u->thisorder, 144, MSG_EVENT);
|
cmistake(u, u->thisorder, 144, MSG_EVENT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
u2 = ship_owner(sh);
|
u2 = ship_owner(sh);
|
||||||
skdiff =
|
skdiff =
|
||||||
eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION);
|
eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION);
|
||||||
if (try_destruction(u, u2, sh, skdiff)) {
|
if (try_destruction(u, u2, sh, skdiff)) {
|
||||||
sink_ship(r, sh, buffer, u);
|
sink_ship(r, sh, buffer, u);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cmistake(u, u->thisorder, 9, MSG_EVENT);
|
cmistake(u, u->thisorder, 9, MSG_EVENT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,8 +380,10 @@ int teach_cmd(unit * u, struct order *ord)
|
||||||
init_order(ord);
|
init_order(ord);
|
||||||
|
|
||||||
while (!parser_end()) {
|
while (!parser_end()) {
|
||||||
unit *u2 = getunit(r, u->faction);
|
unit *u2;
|
||||||
bool feedback;
|
bool feedback;
|
||||||
|
|
||||||
|
getunit(r, u->faction, &u2);
|
||||||
++count;
|
++count;
|
||||||
|
|
||||||
/* Falls die Unit nicht gefunden wird, Fehler melden */
|
/* Falls die Unit nicht gefunden wird, Fehler melden */
|
||||||
|
@ -396,7 +398,7 @@ int teach_cmd(unit * u, struct order *ord)
|
||||||
|
|
||||||
for (j = 0; j != count - 1; ++j) {
|
for (j = 0; j != count - 1; ++j) {
|
||||||
/* skip over the first 'count' units */
|
/* skip over the first 'count' units */
|
||||||
getunit(r, u->faction);
|
getunit(r, u->faction, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
token = getstrtoken();
|
token = getstrtoken();
|
||||||
|
|
Loading…
Reference in New Issue