forked from github/server
Merge pull request #731 from ennorehling/develop
BUG 2367, 2368: familiars
This commit is contained in:
commit
0ca0543c6e
2
clibs
2
clibs
|
@ -1 +1 @@
|
|||
Subproject commit da2c0cc39b27c98ed8d31b0503426788fc236bd8
|
||||
Subproject commit 147584ad70b220abf6a4e97ca76e785729b9ac32
|
|
@ -273,7 +273,7 @@ static int tolua_unit_set_guard(lua_State * L)
|
|||
|
||||
static const char *unit_getmagic(const unit * u)
|
||||
{
|
||||
sc_mage *mage = get_mage(u);
|
||||
sc_mage *mage = get_mage_depr(u);
|
||||
return mage ? magic_school[mage->magietyp] : NULL;
|
||||
}
|
||||
|
||||
|
@ -286,7 +286,7 @@ static int tolua_unit_get_magic(lua_State * L)
|
|||
|
||||
static void unit_setmagic(unit * u, const char *type)
|
||||
{
|
||||
sc_mage *mage = get_mage(u);
|
||||
sc_mage *mage = get_mage_depr(u);
|
||||
int mtype;
|
||||
for (mtype = 0; mtype != MAXMAGIETYP; ++mtype) {
|
||||
if (strcmp(magic_school[mtype], type) == 0)
|
||||
|
@ -638,8 +638,14 @@ static int tolua_unit_get_familiar(lua_State * L)
|
|||
|
||||
static int tolua_unit_set_familiar(lua_State * L)
|
||||
{
|
||||
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
||||
create_newfamiliar(self, (unit *)tolua_tousertype(L, 2, 0));
|
||||
unit *mag = (unit *)tolua_tousertype(L, 1, NULL);
|
||||
unit *fam = (unit *)tolua_tousertype(L, 2, NULL);
|
||||
if (fam) {
|
||||
set_familiar(mag, fam);
|
||||
}
|
||||
else {
|
||||
remove_familiar(mag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -747,7 +753,7 @@ static int tolua_unit_get_items(lua_State * L)
|
|||
static int tolua_unit_get_spells(lua_State * L)
|
||||
{
|
||||
unit *self = (unit *) tolua_tousertype(L, 1, 0);
|
||||
sc_mage *mage = self ? get_mage(self) : 0;
|
||||
sc_mage *mage = self ? get_mage_depr(self) : 0;
|
||||
spellbook *sb = mage ? mage->spellbook : 0;
|
||||
selist *slist = 0;
|
||||
if (sb) {
|
||||
|
|
|
@ -954,7 +954,7 @@ void cr_output_unit(stream *out, const region * r, const faction * f,
|
|||
}
|
||||
|
||||
/* spells that this unit can cast */
|
||||
mage = get_mage(u);
|
||||
mage = get_mage_depr(u);
|
||||
if (mage) {
|
||||
int i, maxlevel = effskill(u, SK_MAGIC, 0);
|
||||
cr_output_spells(out, u, maxlevel);
|
||||
|
|
|
@ -591,7 +591,7 @@ void give_unit(unit * u, unit * u2, order * ord)
|
|||
cmistake(u, ord, 155, MSG_COMMERCE);
|
||||
return;
|
||||
}
|
||||
mage = get_mage(u);
|
||||
mage = get_mage_depr(u);
|
||||
if (!mage || u2->faction->magiegebiet != mage->magietyp) {
|
||||
cmistake(u, ord, 157, MSG_COMMERCE);
|
||||
return;
|
||||
|
|
|
@ -121,7 +121,7 @@ void equip_unit_mask(struct unit *u, const struct equipment *eq, int mask)
|
|||
if (eq->spells) {
|
||||
selist * ql = eq->spells;
|
||||
int qi;
|
||||
sc_mage * mage = get_mage(u);
|
||||
sc_mage * mage = get_mage_depr(u);
|
||||
|
||||
for (qi = 0; ql; selist_advance(&ql, &qi, 1)) {
|
||||
lazy_spell *sbe = (lazy_spell *)selist_get(ql, qi);
|
||||
|
|
|
@ -39,7 +39,7 @@ static void test_equipment(CuTest * tc)
|
|||
CuAssertIntEquals(tc, 1, i_get(u->items, it_horses));
|
||||
CuAssertIntEquals(tc, 5, get_level(u, SK_MAGIC));
|
||||
|
||||
mage = get_mage(u);
|
||||
mage = get_mage_depr(u);
|
||||
CuAssertPtrNotNull(tc, mage);
|
||||
CuAssertPtrNotNull(tc, mage->spellbook);
|
||||
CuAssertTrue(tc, u_hasspell(u, sp));
|
||||
|
|
|
@ -83,7 +83,7 @@ struct message *msg_feedback(const struct unit *u, struct order *ord,
|
|||
variant var;
|
||||
memset(args, 0, sizeof(args));
|
||||
|
||||
if (ord && ord->_noerror) {
|
||||
if (ord && is_silent(ord)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,8 +79,8 @@ static void test_noerror(CuTest *tc) {
|
|||
lang = test_create_locale();
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||
u->thisorder = parse_order("!@move", lang);
|
||||
CuAssertTrue(tc, u->thisorder->_persistent);
|
||||
CuAssertTrue(tc, u->thisorder->_noerror);
|
||||
CuAssertIntEquals(tc, K_MOVE | CMD_QUIET | CMD_PERSIST, u->thisorder->command);
|
||||
CuAssertTrue(tc, !is_persistent(u->thisorder));
|
||||
CuAssertPtrEquals(tc, NULL, msg_error(u, u->thisorder, 100));
|
||||
CuAssertPtrEquals(tc, NULL, msg_feedback(u, u->thisorder, "error_unit_not_found", NULL));
|
||||
test_cleanup();
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
# define ORD_KEYWORD(ord) (ord)->data->_keyword
|
||||
# define ORD_KEYWORD(ord) (keyword_t)((ord)->command & 0xFFFF)
|
||||
# define ORD_LOCALE(ord) locale_array[(ord)->data->_lindex]->lang
|
||||
# define ORD_STRING(ord) (ord)->data->_str
|
||||
|
||||
typedef struct locale_data {
|
||||
struct order_data *short_orders[MAXKEYWORDS];
|
||||
struct order_data *short_orders;
|
||||
struct order_data *study_orders[MAXSKILLS];
|
||||
const struct locale *lang;
|
||||
} locale_data;
|
||||
|
@ -46,7 +46,6 @@ typedef struct order_data {
|
|||
const char *_str;
|
||||
int _refcount;
|
||||
int _lindex;
|
||||
keyword_t _keyword;
|
||||
} order_data;
|
||||
|
||||
static void release_data(order_data * data)
|
||||
|
@ -94,7 +93,7 @@ char* get_command(const order *ord, char *sbuffer, size_t size) {
|
|||
keyword_t kwd = ORD_KEYWORD(ord);
|
||||
int bytes;
|
||||
|
||||
if (ord->_noerror) {
|
||||
if (ord->command & CMD_QUIET) {
|
||||
if (size > 0) {
|
||||
*bufp++ = '!';
|
||||
--size;
|
||||
|
@ -103,7 +102,7 @@ char* get_command(const order *ord, char *sbuffer, size_t size) {
|
|||
WARN_STATIC_BUFFER();
|
||||
}
|
||||
}
|
||||
if (ord->_persistent) {
|
||||
if (ord->command & CMD_PERSIST) {
|
||||
if (size > 0) {
|
||||
*bufp++ = '@';
|
||||
--size;
|
||||
|
@ -162,8 +161,7 @@ order *copy_order(const order * src)
|
|||
if (src != NULL) {
|
||||
order *ord = (order *)malloc(sizeof(order));
|
||||
ord->next = NULL;
|
||||
ord->_persistent = src->_persistent;
|
||||
ord->_noerror = src->_noerror;
|
||||
ord->command = src->command;
|
||||
ord->data = src->data;
|
||||
++ord->data->_refcount;
|
||||
return ord;
|
||||
|
@ -189,13 +187,12 @@ void free_orders(order ** olist)
|
|||
}
|
||||
}
|
||||
|
||||
static char *mkdata(order_data **pdata, size_t len, keyword_t kwd, int lindex, const char *str)
|
||||
static char *mkdata(order_data **pdata, size_t len, int lindex, const char *str)
|
||||
{
|
||||
order_data *data;
|
||||
char *result;
|
||||
data = malloc(sizeof(order_data) + len + 1);
|
||||
result = (char *)(data + 1);
|
||||
data->_keyword = kwd;
|
||||
data->_lindex = lindex;
|
||||
data->_refcount = 0;
|
||||
data->_str = 0;
|
||||
|
@ -229,7 +226,7 @@ static order_data *create_data(keyword_t kwd, const char *sptr, int lindex)
|
|||
const char *skname = skillname(sk, lang);
|
||||
const char *spc = strchr(skname, ' ');
|
||||
size_t len = strlen(skname);
|
||||
char *dst = mkdata(&data, len + (spc ? 3 : 0), kwd, lindex, spc ? 0 : skname);
|
||||
char *dst = mkdata(&data, len + (spc ? 3 : 0), lindex, spc ? 0 : skname);
|
||||
locale_array[lindex]->study_orders[sk] = data;
|
||||
if (spc) {
|
||||
dst[0] = '\"';
|
||||
|
@ -246,26 +243,24 @@ static order_data *create_data(keyword_t kwd, const char *sptr, int lindex)
|
|||
|
||||
/* orders with no parameter, only one order_data per order required */
|
||||
else if (kwd != NOKEYWORD && *sptr == 0) {
|
||||
data = locale_array[lindex]->short_orders[kwd];
|
||||
data = locale_array[lindex]->short_orders;
|
||||
if (data == NULL) {
|
||||
mkdata(&data, 0, kwd, lindex, 0);
|
||||
mkdata(&data, 0, lindex, 0);
|
||||
data->_refcount = 1;
|
||||
locale_array[lindex]->short_orders[kwd] = data;
|
||||
locale_array[lindex]->short_orders = data;
|
||||
}
|
||||
++data->_refcount;
|
||||
return data;
|
||||
}
|
||||
mkdata(&data, s ? strlen(s) : 0, kwd, lindex, s);
|
||||
mkdata(&data, s ? strlen(s) : 0, lindex, s);
|
||||
data->_refcount = 1;
|
||||
return data;
|
||||
}
|
||||
|
||||
static void clear_localedata(int lindex) {
|
||||
int i;
|
||||
for (i = 0; i != MAXKEYWORDS; ++i) {
|
||||
release_data(locale_array[lindex]->short_orders[i]);
|
||||
locale_array[lindex]->short_orders[i] = 0;
|
||||
}
|
||||
release_data(locale_array[lindex]->short_orders);
|
||||
locale_array[lindex]->short_orders = NULL;
|
||||
for (i = 0; i != MAXSKILLS; ++i) {
|
||||
release_data(locale_array[lindex]->study_orders[i]);
|
||||
locale_array[lindex]->study_orders[i] = 0;
|
||||
|
@ -284,12 +279,12 @@ void close_orders(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static order *create_order_i(keyword_t kwd, const char *sptr, bool persistent,
|
||||
static order *create_order_i(order *ord, keyword_t kwd, const char *sptr, bool persistent,
|
||||
bool noerror, const struct locale *lang)
|
||||
{
|
||||
order *ord = NULL;
|
||||
int lindex;
|
||||
|
||||
assert(ord);
|
||||
if (kwd == NOKEYWORD || keyword_disabled(kwd)) {
|
||||
log_error("trying to create an order for disabled keyword %s.", keyword(kwd));
|
||||
return NULL;
|
||||
|
@ -316,11 +311,12 @@ static order *create_order_i(keyword_t kwd, const char *sptr, bool persistent,
|
|||
}
|
||||
locale_array[lindex]->lang = lang;
|
||||
|
||||
ord = (order *)malloc(sizeof(order));
|
||||
ord->_persistent = persistent;
|
||||
ord->_noerror = noerror;
|
||||
ord->command = (int)kwd;
|
||||
if (persistent) ord->command |= CMD_PERSIST;
|
||||
if (noerror) ord->command |= CMD_QUIET;
|
||||
ord->next = NULL;
|
||||
|
||||
while (isspace(*(unsigned char *)sptr)) ++sptr;
|
||||
ord->data = create_data(kwd, sptr, lindex);
|
||||
|
||||
return ord;
|
||||
|
@ -329,6 +325,7 @@ static order *create_order_i(keyword_t kwd, const char *sptr, bool persistent,
|
|||
order *create_order(keyword_t kwd, const struct locale * lang,
|
||||
const char *params, ...)
|
||||
{
|
||||
order *ord;
|
||||
char zBuffer[DISPLAYSIZE];
|
||||
if (params) {
|
||||
char *bufp = zBuffer;
|
||||
|
@ -379,42 +376,40 @@ order *create_order(keyword_t kwd, const struct locale * lang,
|
|||
else {
|
||||
zBuffer[0] = 0;
|
||||
}
|
||||
return create_order_i(kwd, zBuffer, false, false, lang);
|
||||
ord = (order *)malloc(sizeof(order));
|
||||
return create_order_i(ord, kwd, zBuffer, false, false, lang);
|
||||
}
|
||||
|
||||
order *parse_order(const char *s, const struct locale * lang)
|
||||
{
|
||||
assert(lang);
|
||||
assert(s);
|
||||
while (*s && !isalnum(*(unsigned char *)s) && !ispunct(*(unsigned char *)s)) {
|
||||
++s;
|
||||
}
|
||||
if (*s != 0) {
|
||||
keyword_t kwd;
|
||||
const char *sptr;
|
||||
keyword_t kwd = NOKEYWORD;
|
||||
const char *sptr = s;
|
||||
bool persistent = false, noerror = false;
|
||||
const char * p;
|
||||
|
||||
while (*s == '!' || *s=='@') {
|
||||
if (*s=='!') noerror = true;
|
||||
else if (*s == '@') persistent = true;
|
||||
++s;
|
||||
}
|
||||
sptr = s;
|
||||
p = *sptr ? parse_token_depr(&sptr) : 0;
|
||||
kwd = p ? get_keyword(p, lang) : NOKEYWORD;
|
||||
if (p) {
|
||||
while (*p == '!' || *p == '@') {
|
||||
if (*p == '!') noerror = true;
|
||||
else if (*p == '@') persistent = true;
|
||||
++p;
|
||||
}
|
||||
kwd = get_keyword(p, lang);
|
||||
}
|
||||
if (kwd == K_MAKE) {
|
||||
const char *s, *sp = sptr;
|
||||
s = parse_token_depr(&sp);
|
||||
if (s && isparam(s, lang, P_TEMP)) {
|
||||
const char *sp = sptr;
|
||||
p = parse_token_depr(&sp);
|
||||
if (p && isparam(p, lang, P_TEMP)) {
|
||||
kwd = K_MAKETEMP;
|
||||
sptr = sp;
|
||||
}
|
||||
}
|
||||
if (kwd != NOKEYWORD) {
|
||||
while (isspace(*(unsigned char *)sptr)) ++sptr;
|
||||
s = sptr;
|
||||
return create_order_i(kwd, s, persistent, noerror, lang);
|
||||
order *ord = (order *)malloc(sizeof(order));
|
||||
return create_order_i(ord, kwd, sptr, persistent, noerror, lang);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
@ -561,10 +556,15 @@ bool is_persistent(const order * ord)
|
|||
case K_KOMMENTAR:
|
||||
return true;
|
||||
default:
|
||||
return ord->_persistent || is_repeated(kwd);
|
||||
return (ord->command & CMD_PERSIST) || is_repeated(kwd);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_silent(const order * ord)
|
||||
{
|
||||
return (ord->command & CMD_QUIET) != 0;
|
||||
}
|
||||
|
||||
char *write_order(const order * ord, char *buffer, size_t size)
|
||||
{
|
||||
if (ord == 0) {
|
||||
|
@ -595,5 +595,5 @@ keyword_t init_order(const struct order *ord)
|
|||
{
|
||||
assert(ord && ord->data);
|
||||
init_tokens_str(ord->data->_str);
|
||||
return ord->data->_keyword;
|
||||
return ORD_KEYWORD(ord);
|
||||
}
|
||||
|
|
|
@ -32,32 +32,36 @@ extern "C" {
|
|||
|
||||
struct order_data;
|
||||
|
||||
#define CMD_QUIET 0x010000
|
||||
#define CMD_PERSIST 0x020000
|
||||
#define CMD_DEFAULT 0x040000
|
||||
|
||||
typedef struct order {
|
||||
struct order *next;
|
||||
/* do not access this data: */
|
||||
struct order_data *data;
|
||||
bool _persistent;
|
||||
bool _noerror;
|
||||
int command;
|
||||
} order;
|
||||
|
||||
/* constructor */
|
||||
extern order *create_order(keyword_t kwd, const struct locale *lang,
|
||||
order *create_order(keyword_t kwd, const struct locale *lang,
|
||||
const char *params, ...);
|
||||
extern order *parse_order(const char *s, const struct locale *lang);
|
||||
extern void replace_order(order ** dst, order * orig, const order * src);
|
||||
order *parse_order(const char *s, const struct locale *lang);
|
||||
void replace_order(order ** dst, order * orig, const order * src);
|
||||
|
||||
/* reference counted copies of orders: */
|
||||
extern order *copy_order(const order * ord);
|
||||
extern void free_order(order * ord);
|
||||
extern void free_orders(order ** olist);
|
||||
order *copy_order(const order * ord);
|
||||
void free_order(order * ord);
|
||||
void free_orders(order ** olist);
|
||||
|
||||
extern void push_order(struct order **olist, struct order *ord);
|
||||
void push_order(struct order **olist, struct order *ord);
|
||||
|
||||
/* access functions for orders */
|
||||
keyword_t getkeyword(const order * ord);
|
||||
void set_order(order ** destp, order * src);
|
||||
char* get_command(const order *ord, char *buffer, size_t size);
|
||||
bool is_persistent(const order * ord);
|
||||
bool is_silent(const order * ord);
|
||||
bool is_exclusive(const order * ord);
|
||||
bool is_repeated(keyword_t kwd);
|
||||
bool is_long(keyword_t kwd);
|
||||
|
|
|
@ -38,8 +38,7 @@ static void test_parse_order(CuTest *tc) {
|
|||
|
||||
ord = parse_order("MOVE NORTH", lang);
|
||||
CuAssertPtrNotNull(tc, ord);
|
||||
CuAssertTrue(tc, !ord->_noerror);
|
||||
CuAssertTrue(tc, !ord->_persistent);
|
||||
CuAssertIntEquals(tc, K_MOVE, ord->command);
|
||||
CuAssertIntEquals(tc, K_MOVE, getkeyword(ord));
|
||||
CuAssertStrEquals(tc, "move NORTH", get_command(ord, cmd, sizeof(cmd)));
|
||||
|
||||
|
@ -49,26 +48,37 @@ static void test_parse_order(CuTest *tc) {
|
|||
|
||||
ord = parse_order("!MOVE NORTH", lang);
|
||||
CuAssertPtrNotNull(tc, ord);
|
||||
CuAssertTrue(tc, ord->_noerror);
|
||||
CuAssertTrue(tc, !ord->_persistent);
|
||||
CuAssertPtrNotNull(tc, ord->data);
|
||||
CuAssertIntEquals(tc, K_MOVE, getkeyword(ord));
|
||||
CuAssertIntEquals(tc, K_MOVE | CMD_QUIET, ord->command);
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order("@MOVE NORTH", lang);
|
||||
CuAssertPtrNotNull(tc, ord);
|
||||
CuAssertTrue(tc, !ord->_noerror);
|
||||
CuAssertTrue(tc, ord->_persistent);
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order("@!MOVE NORTH", lang);
|
||||
CuAssertPtrNotNull(tc, ord);
|
||||
CuAssertTrue(tc, ord->_noerror);
|
||||
CuAssertTrue(tc, ord->_persistent);
|
||||
CuAssertPtrNotNull(tc, ord->data);
|
||||
CuAssertIntEquals(tc, K_MOVE, getkeyword(ord));
|
||||
CuAssertIntEquals(tc, K_MOVE | CMD_PERSIST, ord->command);
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order("!@MOVE NORTH", lang);
|
||||
CuAssertPtrNotNull(tc, ord);
|
||||
CuAssertTrue(tc, ord->_noerror);
|
||||
CuAssertTrue(tc, ord->_persistent);
|
||||
CuAssertPtrNotNull(tc, ord->data);
|
||||
CuAssertIntEquals(tc, K_MOVE, getkeyword(ord));
|
||||
CuAssertIntEquals(tc, K_MOVE | CMD_PERSIST | CMD_QUIET, ord->command);
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order("@!MOVE NORTH", lang);
|
||||
CuAssertPtrNotNull(tc, ord);
|
||||
CuAssertPtrNotNull(tc, ord->data);
|
||||
CuAssertIntEquals(tc, K_MOVE, getkeyword(ord));
|
||||
CuAssertIntEquals(tc, K_MOVE | CMD_PERSIST | CMD_QUIET, ord->command);
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order(" !@MOVE NORTH", lang);
|
||||
CuAssertPtrNotNull(tc, ord);
|
||||
CuAssertPtrNotNull(tc, ord->data);
|
||||
CuAssertIntEquals(tc, K_MOVE, getkeyword(ord));
|
||||
CuAssertIntEquals(tc, K_MOVE | CMD_PERSIST | CMD_QUIET, ord->command);
|
||||
free_order(ord);
|
||||
|
||||
test_cleanup();
|
||||
|
@ -204,16 +214,84 @@ static void test_get_command(CuTest *tc) {
|
|||
lang = test_create_locale();
|
||||
ord = create_order(K_MAKE, lang, "iron");
|
||||
CuAssertStrEquals(tc, "make iron", get_command(ord, buf, sizeof(buf)));
|
||||
ord->_noerror = true;
|
||||
ord->command |= CMD_QUIET;
|
||||
CuAssertStrEquals(tc, "!make iron", get_command(ord, buf, sizeof(buf)));
|
||||
ord->_persistent = true;
|
||||
ord->command |= CMD_PERSIST;
|
||||
CuAssertStrEquals(tc, "!@make iron", get_command(ord, buf, sizeof(buf)));
|
||||
ord->_noerror = false;
|
||||
ord->command = K_MAKE | CMD_PERSIST;
|
||||
CuAssertStrEquals(tc, "@make iron", get_command(ord, buf, sizeof(buf)));
|
||||
free_order(ord);
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_is_persistent(CuTest *tc) {
|
||||
order *ord;
|
||||
struct locale *lang;
|
||||
|
||||
test_setup();
|
||||
lang = test_create_locale();
|
||||
|
||||
ord = parse_order("@invalid", lang);
|
||||
CuAssertPtrEquals(tc, NULL, ord);
|
||||
|
||||
ord = parse_order("give", lang);
|
||||
CuAssertIntEquals(tc, K_GIVE, ord->command);
|
||||
CuAssertTrue(tc, !is_persistent(ord));
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order("@give", lang);
|
||||
CuAssertTrue(tc, !is_repeated(K_GIVE));
|
||||
CuAssertIntEquals(tc, K_GIVE | CMD_PERSIST, ord->command);
|
||||
CuAssertTrue(tc, is_persistent(ord));
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order("make", lang);
|
||||
CuAssertTrue(tc, is_repeated(K_MAKE));
|
||||
CuAssertIntEquals(tc, K_MAKE , ord->command);
|
||||
CuAssertTrue(tc, is_persistent(ord));
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order("@move", lang);
|
||||
CuAssertIntEquals(tc, K_MOVE | CMD_PERSIST, ord->command);
|
||||
CuAssertTrue(tc, !is_persistent(ord));
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order("// comment", lang);
|
||||
CuAssertTrue(tc, is_persistent(ord));
|
||||
CuAssertIntEquals(tc, K_KOMMENTAR, ord->command);
|
||||
free_order(ord);
|
||||
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
|
||||
static void test_is_silent(CuTest *tc) {
|
||||
order *ord;
|
||||
struct locale *lang;
|
||||
|
||||
test_setup();
|
||||
lang = test_create_locale();
|
||||
|
||||
ord = parse_order("make", lang);
|
||||
CuAssertIntEquals(tc, K_MAKE, ord->command);
|
||||
CuAssertTrue(tc, !is_silent(ord));
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order("!make", lang);
|
||||
CuAssertIntEquals(tc, K_MAKE | CMD_QUIET, ord->command);
|
||||
CuAssertTrue(tc, is_silent(ord));
|
||||
free_order(ord);
|
||||
|
||||
ord = parse_order("@invalid", lang);
|
||||
CuAssertPtrEquals(tc, NULL, ord);
|
||||
|
||||
ord = parse_order("// comment", lang);
|
||||
CuAssertTrue(tc, is_persistent(ord));
|
||||
CuAssertIntEquals(tc, K_KOMMENTAR, ord->command);
|
||||
free_order(ord);
|
||||
|
||||
test_cleanup();
|
||||
}
|
||||
CuSuite *get_order_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
@ -227,5 +305,7 @@ CuSuite *get_order_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_skip_token);
|
||||
SUITE_ADD_TEST(suite, test_getstrtoken);
|
||||
SUITE_ADD_TEST(suite, test_get_command);
|
||||
SUITE_ADD_TEST(suite, test_is_persistent);
|
||||
SUITE_ADD_TEST(suite, test_is_silent);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "alchemy.h"
|
||||
#include "alliance.h"
|
||||
#include "ally.h"
|
||||
#include "connection.h"
|
||||
#include "building.h"
|
||||
#include "connection.h"
|
||||
#include "equipment.h"
|
||||
#include "faction.h"
|
||||
#include "group.h"
|
||||
#include "item.h"
|
||||
|
@ -1599,41 +1600,60 @@ static void fix_familiars(void) {
|
|||
if (u->_race != u->faction->race && (u->_race->flags & RCF_FAMILIAR)) {
|
||||
/* unit is potentially a familiar */
|
||||
attrib * a = a_find(u->attribs, &at_mage);
|
||||
if (a) {
|
||||
/* unit is magical */
|
||||
attrib * am = a_find(u->attribs, &at_familiarmage);
|
||||
if (!am) {
|
||||
/* but it is not a familiar? */
|
||||
attrib * ae = a_find(u->attribs, &at_eventhandler);
|
||||
if (ae) {
|
||||
trigger **tlist;
|
||||
tlist = get_triggers(ae, "destroy");
|
||||
if (tlist) {
|
||||
trigger *t;
|
||||
unit *um = NULL;
|
||||
for (t = *tlist; t; t = t->next) {
|
||||
if (t->type == &tt_shock) {
|
||||
um = (unit *)t->data.v;
|
||||
break;
|
||||
}
|
||||
attrib * am = a_find(u->attribs, &at_familiarmage);
|
||||
if (am) {
|
||||
sc_mage *mage = a ? (sc_mage *)a->data.v : NULL;
|
||||
/* a familiar */
|
||||
if (!mage) {
|
||||
log_error("%s seems to be a familiar with no magic.",
|
||||
unitname(u));
|
||||
mage = create_mage(u, M_GRAY);
|
||||
}
|
||||
if (!mage->spellbook) {
|
||||
char eqname[32];
|
||||
equipment *eq;
|
||||
|
||||
snprintf(eqname, sizeof(eqname), "fam_%s", u->_race->_name);
|
||||
eq = get_equipment(eqname);
|
||||
if (eq && eq->spells) {
|
||||
log_error("%s seems to be a familiar with no spells.",
|
||||
unitname(u));
|
||||
/* magical familiar, no spells */
|
||||
equip_unit_mask(u, eq, EQUIP_SPELLS);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (a) {
|
||||
/* not a familiar, but magical */
|
||||
attrib * ae = a_find(u->attribs, &at_eventhandler);
|
||||
if (ae) {
|
||||
trigger **tlist;
|
||||
tlist = get_triggers(ae, "destroy");
|
||||
if (tlist) {
|
||||
trigger *t;
|
||||
unit *um = NULL;
|
||||
for (t = *tlist; t; t = t->next) {
|
||||
if (t->type == &tt_shock) {
|
||||
um = (unit *)t->data.v;
|
||||
break;
|
||||
}
|
||||
if (um) {
|
||||
attrib *af = a_find(um->attribs, &at_familiar);
|
||||
log_error("%s seems to be a broken familiar of %s.",
|
||||
unitname(u), unitname(um));
|
||||
if (af) {
|
||||
unit * uf = (unit *)af->data.v;
|
||||
log_error("%s already has a familiar: %s.",
|
||||
unitname(um), unitname(uf));
|
||||
}
|
||||
else {
|
||||
set_familiar(um, u);
|
||||
}
|
||||
}
|
||||
if (um) {
|
||||
attrib *af = a_find(um->attribs, &at_familiar);
|
||||
log_error("%s seems to be a broken familiar of %s.",
|
||||
unitname(u), unitname(um));
|
||||
if (af) {
|
||||
unit * uf = (unit *)af->data.v;
|
||||
log_error("%s already has a familiar: %s.",
|
||||
unitname(um), unitname(uf));
|
||||
}
|
||||
else {
|
||||
log_error("%s seems to be a broken familiar with no trigger.", unitname(u));
|
||||
set_familiar(um, u);
|
||||
}
|
||||
}
|
||||
else {
|
||||
log_error("%s seems to be a broken familiar with no trigger.", unitname(u));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1790,7 +1810,7 @@ int read_game(gamedata *data)
|
|||
else {
|
||||
for (u = f->units; u; u = u->nextF) {
|
||||
if (data->version < SPELL_LEVEL_VERSION) {
|
||||
sc_mage *mage = get_mage(u);
|
||||
sc_mage *mage = get_mage_depr(u);
|
||||
if (mage) {
|
||||
faction *f = u->faction;
|
||||
int skl = effskill(u, SK_MAGIC, 0);
|
||||
|
|
|
@ -1492,14 +1492,6 @@ unit *create_unit(region * r, faction * f, int number, const struct race *urace,
|
|||
if (f) {
|
||||
assert(faction_alive(f));
|
||||
u_setfaction(u, f);
|
||||
|
||||
if (f->locale) {
|
||||
order *deford = default_order(f->locale);
|
||||
if (deford) {
|
||||
set_order(&u->thisorder, NULL);
|
||||
addlist(&u->orders, deford);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_number(u, number);
|
||||
|
@ -1822,7 +1814,7 @@ void u_setrace(struct unit *u, const struct race *rc)
|
|||
|
||||
void unit_add_spell(unit * u, sc_mage * m, struct spell * sp, int level)
|
||||
{
|
||||
sc_mage *mage = m ? m : get_mage(u);
|
||||
sc_mage *mage = m ? m : get_mage_depr(u);
|
||||
|
||||
if (!mage) {
|
||||
log_debug("adding new spell %s to a previously non-mage unit %s\n", sp->sname, unitname(u));
|
||||
|
@ -1836,7 +1828,7 @@ void unit_add_spell(unit * u, sc_mage * m, struct spell * sp, int level)
|
|||
|
||||
struct spellbook * unit_get_spellbook(const struct unit * u)
|
||||
{
|
||||
sc_mage * mage = get_mage(u);
|
||||
sc_mage * mage = get_mage_depr(u);
|
||||
if (mage) {
|
||||
if (mage->spellbook) {
|
||||
return mage->spellbook;
|
||||
|
|
|
@ -274,7 +274,7 @@ static void test_skill_familiar(CuTest *tc) {
|
|||
CuAssertIntEquals(tc, 6, effskill(mag, SK_PERCEPTION, 0));
|
||||
|
||||
/* make them mage and familiar to each other */
|
||||
CuAssertIntEquals(tc, true, create_newfamiliar(mag, fam));
|
||||
create_newfamiliar(mag, fam);
|
||||
|
||||
/* when they are in the same region, the mage gets half their skill as a bonus */
|
||||
CuAssertIntEquals(tc, 6, effskill(fam, SK_PERCEPTION, 0));
|
||||
|
@ -287,33 +287,11 @@ static void test_skill_familiar(CuTest *tc) {
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_age_familiar(CuTest *tc) {
|
||||
unit *mag, *fam;
|
||||
|
||||
test_cleanup();
|
||||
|
||||
mag = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||
fam = test_create_unit(mag->faction, test_create_region(0, 0, 0));
|
||||
CuAssertPtrEquals(tc, 0, get_familiar(mag));
|
||||
CuAssertPtrEquals(tc, 0, get_familiar_mage(fam));
|
||||
CuAssertIntEquals(tc, true, create_newfamiliar(mag, fam));
|
||||
CuAssertPtrEquals(tc, fam, get_familiar(mag));
|
||||
CuAssertPtrEquals(tc, mag, get_familiar_mage(fam));
|
||||
a_age(&fam->attribs, fam);
|
||||
a_age(&mag->attribs, mag);
|
||||
CuAssertPtrEquals(tc, fam, get_familiar(mag));
|
||||
CuAssertPtrEquals(tc, mag, get_familiar_mage(fam));
|
||||
set_number(fam, 0);
|
||||
a_age(&mag->attribs, mag);
|
||||
CuAssertPtrEquals(tc, 0, get_familiar(mag));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_inside_building(CuTest *tc) {
|
||||
unit *u;
|
||||
building *b;
|
||||
|
||||
test_cleanup();
|
||||
test_setup();
|
||||
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||
b = test_create_building(u->region, 0);
|
||||
|
||||
|
@ -631,7 +609,6 @@ CuSuite *get_unit_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_skillmod);
|
||||
SUITE_ADD_TEST(suite, test_skill_hunger);
|
||||
SUITE_ADD_TEST(suite, test_skill_familiar);
|
||||
SUITE_ADD_TEST(suite, test_age_familiar);
|
||||
SUITE_ADD_TEST(suite, test_inside_building);
|
||||
SUITE_ADD_TEST(suite, test_skills);
|
||||
SUITE_ADD_TEST(suite, test_limited_skills);
|
||||
|
|
168
src/laws.c
168
src/laws.c
|
@ -3007,10 +3007,100 @@ int checkunitnumber(const faction * f, int add)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void maketemp_cmd(unit *u, order **olist)
|
||||
{
|
||||
order *makeord;
|
||||
int err = checkunitnumber(u->faction, 1);
|
||||
|
||||
makeord = *olist;
|
||||
if (err) {
|
||||
if (err == 1) {
|
||||
ADDMSG(&u->faction->msgs,
|
||||
msg_feedback(u, makeord,
|
||||
"too_many_units_in_alliance",
|
||||
"allowed", maxunits(u->faction)));
|
||||
}
|
||||
else {
|
||||
ADDMSG(&u->faction->msgs,
|
||||
msg_feedback(u, makeord,
|
||||
"too_many_units_in_faction",
|
||||
"allowed", maxunits(u->faction)));
|
||||
}
|
||||
*olist = makeord->next;
|
||||
makeord->next = NULL;
|
||||
free_order(makeord);
|
||||
while (*olist) {
|
||||
keyword_t kwd;
|
||||
order * ord = *olist;
|
||||
*olist = ord->next;
|
||||
ord->next = NULL;
|
||||
kwd = getkeyword(ord);
|
||||
free_order(ord);
|
||||
if (kwd == K_END) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
char token[128];
|
||||
const char *s;
|
||||
int alias;
|
||||
ship *sh;
|
||||
unit *u2;
|
||||
order **ordp, **oinsert;
|
||||
#ifndef NDEBUG
|
||||
keyword_t kwd = init_order(makeord);
|
||||
assert(kwd == K_MAKETEMP);
|
||||
#endif
|
||||
alias = getid();
|
||||
s = gettoken(token, sizeof(token));
|
||||
if (s && s[0] == '\0') {
|
||||
/* empty name? => generate one */
|
||||
s = NULL;
|
||||
}
|
||||
u2 = create_unit(u->region, u->faction, 0, u->faction->race, alias, s, u);
|
||||
fset(u2, UFL_ISNEW);
|
||||
a_add(&u2->attribs, a_new(&at_alias))->data.i = alias;
|
||||
sh = leftship(u);
|
||||
if (sh) {
|
||||
set_leftship(u2, sh);
|
||||
}
|
||||
setstatus(u2, u->status);
|
||||
|
||||
/* copy orders until K_END from u to u2 */
|
||||
ordp = &makeord->next;
|
||||
oinsert = &u2->orders;
|
||||
|
||||
while (*ordp) {
|
||||
order *ord = *ordp;
|
||||
*ordp = ord->next;
|
||||
if (getkeyword(ord) == K_END) {
|
||||
ord->next = NULL;
|
||||
free_order(ord);
|
||||
break;
|
||||
}
|
||||
*oinsert = ord;
|
||||
oinsert = &ord->next;
|
||||
*oinsert = NULL;
|
||||
}
|
||||
*olist = *ordp;
|
||||
makeord->next = NULL;
|
||||
free_order(makeord);
|
||||
|
||||
if (!u2->orders) {
|
||||
order *deford = default_order(u2->faction->locale);
|
||||
if (deford) {
|
||||
set_order(&u2->thisorder, NULL);
|
||||
addlist(&u2->orders, deford);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void new_units(void)
|
||||
{
|
||||
region *r;
|
||||
unit *u, *u2;
|
||||
unit *u;
|
||||
|
||||
/* neue einheiten werden gemacht und ihre befehle (bis zum "ende" zu
|
||||
* ihnen rueberkopiert, damit diese einheiten genauso wie die alten
|
||||
|
@ -3028,73 +3118,13 @@ void new_units(void)
|
|||
}
|
||||
|
||||
while (*ordp) {
|
||||
order *makeord = *ordp;
|
||||
if (getkeyword(makeord) == K_MAKETEMP) {
|
||||
char token[128], *name = NULL;
|
||||
const char *s;
|
||||
int alias;
|
||||
ship *sh;
|
||||
order **newordersp;
|
||||
int err = checkunitnumber(u->faction, 1);
|
||||
|
||||
if (err) {
|
||||
if (err == 1) {
|
||||
ADDMSG(&u->faction->msgs,
|
||||
msg_feedback(u, makeord,
|
||||
"too_many_units_in_alliance",
|
||||
"allowed", maxunits(u->faction)));
|
||||
}
|
||||
else {
|
||||
ADDMSG(&u->faction->msgs,
|
||||
msg_feedback(u, makeord,
|
||||
"too_many_units_in_faction",
|
||||
"allowed", maxunits(u->faction)));
|
||||
}
|
||||
ordp = &makeord->next;
|
||||
|
||||
while (*ordp) {
|
||||
order *ord = *ordp;
|
||||
if (getkeyword(ord) == K_END)
|
||||
break;
|
||||
*ordp = ord->next;
|
||||
ord->next = NULL;
|
||||
free_order(ord);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
init_order(makeord);
|
||||
alias = getid();
|
||||
|
||||
s = gettoken(token, sizeof(token));
|
||||
if (s && s[0]) {
|
||||
name = strdup(s);
|
||||
}
|
||||
u2 = create_unit(r, u->faction, 0, u->faction->race, alias, name, u);
|
||||
if (name != NULL)
|
||||
free(name); /* TODO: use a buffer on the stack instead? */
|
||||
fset(u2, UFL_ISNEW);
|
||||
|
||||
a_add(&u2->attribs, a_new(&at_alias))->data.i = alias;
|
||||
sh = leftship(u);
|
||||
if (sh) {
|
||||
set_leftship(u2, sh);
|
||||
}
|
||||
setstatus(u2, u->status);
|
||||
|
||||
ordp = &makeord->next;
|
||||
newordersp = &u2->orders;
|
||||
while (*ordp) {
|
||||
order *ord = *ordp;
|
||||
if (getkeyword(ord) == K_END)
|
||||
break;
|
||||
*ordp = ord->next;
|
||||
ord->next = NULL;
|
||||
*newordersp = ord;
|
||||
newordersp = &ord->next;
|
||||
}
|
||||
order *ord = *ordp;
|
||||
if (getkeyword(ord) == K_MAKETEMP) {
|
||||
maketemp_cmd(u, ordp);
|
||||
}
|
||||
else {
|
||||
ordp = &ord->next;
|
||||
}
|
||||
if (*ordp == makeord)
|
||||
ordp = &makeord->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3357,7 +3387,7 @@ static int faction_getmages(faction * f, unit ** results, int numresults)
|
|||
|
||||
for (u = f->units; u; u = u->nextF) {
|
||||
if (u->number > 0) {
|
||||
sc_mage *mage = get_mage(u);
|
||||
sc_mage *mage = get_mage_depr(u);
|
||||
if (mage) {
|
||||
int level = effskill(u, SK_MAGIC, 0);
|
||||
if (level > maxlevel) {
|
||||
|
@ -3416,7 +3446,7 @@ static void update_spells(void)
|
|||
show_new_spells(f, maxlevel, faction_get_spellbook(f));
|
||||
for (i = 0; i != MAXMAGES && mages[i]; ++i) {
|
||||
unit * u = mages[i];
|
||||
sc_mage *mage = get_mage(u);
|
||||
sc_mage *mage = get_mage_depr(u);
|
||||
if (mage && mage->spellbook) {
|
||||
int level = effskill(u, SK_MAGIC, 0);
|
||||
show_new_spells(f, level, mage->spellbook);
|
||||
|
|
|
@ -428,6 +428,63 @@ static void test_unit_limit(CuTest * tc)
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_maketemp(CuTest * tc)
|
||||
{
|
||||
faction *f;
|
||||
unit *u, *u2;
|
||||
|
||||
test_setup();
|
||||
f = test_create_faction(NULL);
|
||||
u = test_create_unit(f, test_create_region(0, 0, NULL));
|
||||
|
||||
u->orders = create_order(K_MAKETEMP, f->locale, "1");
|
||||
u->orders->next = create_order(K_ENTERTAIN, f->locale, NULL);
|
||||
u->orders->next->next = create_order(K_END, f->locale, NULL);
|
||||
u->orders->next->next->next = create_order(K_TAX, f->locale, NULL);
|
||||
|
||||
new_units();
|
||||
CuAssertIntEquals(tc, 2, f->num_units);
|
||||
CuAssertPtrNotNull(tc, u2 = u->next);
|
||||
CuAssertPtrNotNull(tc, u2->orders);
|
||||
CuAssertPtrEquals(tc, NULL, u2->orders->next);
|
||||
CuAssertIntEquals(tc, K_ENTERTAIN, getkeyword(u2->orders));
|
||||
|
||||
CuAssertPtrNotNull(tc, u->orders);
|
||||
CuAssertPtrEquals(tc, NULL, u->orders->next);
|
||||
CuAssertIntEquals(tc, K_TAX, getkeyword(u->orders));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_maketemp_default_order(CuTest * tc)
|
||||
{
|
||||
faction *f;
|
||||
unit *u, *u2;
|
||||
|
||||
test_setup();
|
||||
config_set("orders.default", "work");
|
||||
f = test_create_faction(NULL);
|
||||
u = test_create_unit(f, test_create_region(0, 0, NULL));
|
||||
|
||||
new_units();
|
||||
CuAssertIntEquals(tc, 1, f->num_units);
|
||||
|
||||
u->orders = create_order(K_MAKETEMP, f->locale, "1");
|
||||
u->orders->next = create_order(K_END, f->locale, NULL);
|
||||
u->orders->next->next = create_order(K_TAX, f->locale, NULL);
|
||||
|
||||
new_units();
|
||||
CuAssertIntEquals(tc, 2, f->num_units);
|
||||
CuAssertPtrNotNull(tc, u2 = u->next);
|
||||
CuAssertPtrNotNull(tc, u2->orders);
|
||||
CuAssertPtrEquals(tc, NULL, u2->orders->next);
|
||||
CuAssertIntEquals(tc, K_WORK, getkeyword(u2->orders));
|
||||
|
||||
CuAssertPtrNotNull(tc, u->orders);
|
||||
CuAssertPtrEquals(tc, NULL, u->orders->next);
|
||||
CuAssertIntEquals(tc, K_TAX, getkeyword(u->orders));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_limit_new_units(CuTest * tc)
|
||||
{
|
||||
faction *f;
|
||||
|
@ -449,6 +506,8 @@ static void test_limit_new_units(CuTest * tc)
|
|||
CuAssertPtrNotNull(tc, u->next);
|
||||
CuAssertIntEquals(tc, 2, f->num_units);
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, u->orders);
|
||||
u->orders = create_order(K_MAKETEMP, f->locale, "1");
|
||||
new_units();
|
||||
CuAssertIntEquals(tc, 2, f->num_units);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "too_many_units_in_faction"));
|
||||
|
@ -458,6 +517,8 @@ static void test_limit_new_units(CuTest * tc)
|
|||
config_set("rules.limit.faction", "3");
|
||||
config_set("rules.limit.alliance", "2");
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, u->orders);
|
||||
u->orders = create_order(K_MAKETEMP, f->locale, "1");
|
||||
new_units();
|
||||
CuAssertIntEquals(tc, 2, f->num_units);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "too_many_units_in_alliance"));
|
||||
|
@ -466,6 +527,8 @@ static void test_limit_new_units(CuTest * tc)
|
|||
u = test_create_unit(test_create_faction(NULL), u->region);
|
||||
setalliance(u->faction, al);
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, u->orders);
|
||||
u->orders = create_order(K_MAKETEMP, f->locale, "1");
|
||||
new_units();
|
||||
CuAssertIntEquals(tc, 2, f->num_units);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "too_many_units_in_alliance"));
|
||||
|
@ -1555,6 +1618,8 @@ static void test_armedmen(CuTest *tc) {
|
|||
CuSuite *get_laws_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_maketemp_default_order);
|
||||
SUITE_ADD_TEST(suite, test_maketemp);
|
||||
SUITE_ADD_TEST(suite, test_nmr_warnings);
|
||||
SUITE_ADD_TEST(suite, test_ally_cmd);
|
||||
SUITE_ADD_TEST(suite, test_name_cmd);
|
||||
|
|
99
src/magic.c
99
src/magic.c
|
@ -42,6 +42,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <kernel/building.h>
|
||||
#include <kernel/callbacks.h>
|
||||
#include <kernel/curse.h>
|
||||
#include <kernel/equipment.h>
|
||||
#include <kernel/faction.h>
|
||||
#include <kernel/item.h>
|
||||
#include <kernel/messages.h>
|
||||
|
@ -322,10 +323,19 @@ attrib_type at_mage = {
|
|||
|
||||
bool is_mage(const unit * u)
|
||||
{
|
||||
return get_mage(u) != NULL;
|
||||
return get_mage_depr(u) != NULL;
|
||||
}
|
||||
|
||||
sc_mage *get_mage(const unit * u)
|
||||
{
|
||||
attrib *a = a_find(u->attribs, &at_mage);
|
||||
if (a) {
|
||||
return (sc_mage *)a->data.v;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sc_mage *get_mage_depr(const unit * u)
|
||||
{
|
||||
if (has_skill(u, SK_MAGIC)) {
|
||||
attrib *a = a_find(u->attribs, &at_mage);
|
||||
|
@ -333,7 +343,7 @@ sc_mage *get_mage(const unit * u)
|
|||
return (sc_mage *)a->data.v;
|
||||
}
|
||||
}
|
||||
return (sc_mage *)NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
@ -506,7 +516,7 @@ int u_hasspell(const unit *u, const struct spell *sp)
|
|||
|
||||
int get_combatspelllevel(const unit * u, int nr)
|
||||
{
|
||||
sc_mage *m = get_mage(u);
|
||||
sc_mage *m = get_mage_depr(u);
|
||||
|
||||
assert(nr < MAXCOMBATSPELLS);
|
||||
if (m) {
|
||||
|
@ -524,7 +534,7 @@ const spell *get_combatspell(const unit * u, int nr)
|
|||
sc_mage *m;
|
||||
|
||||
assert(nr < MAXCOMBATSPELLS);
|
||||
m = get_mage(u);
|
||||
m = get_mage_depr(u);
|
||||
if (m) {
|
||||
return m->combatspells[nr].sp;
|
||||
}
|
||||
|
@ -533,7 +543,7 @@ const spell *get_combatspell(const unit * u, int nr)
|
|||
|
||||
void set_combatspell(unit * u, spell * sp, struct order *ord, int level)
|
||||
{
|
||||
sc_mage *mage = get_mage(u);
|
||||
sc_mage *mage = get_mage_depr(u);
|
||||
int i = -1;
|
||||
|
||||
assert(mage || !"trying to set a combat spell for non-mage");
|
||||
|
@ -573,7 +583,7 @@ void unset_combatspell(unit * u, spell * sp)
|
|||
int nr = 0;
|
||||
int i;
|
||||
|
||||
m = get_mage(u);
|
||||
m = get_mage_depr(u);
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
|
@ -609,7 +619,7 @@ int get_spellpoints(const unit * u)
|
|||
{
|
||||
sc_mage *m;
|
||||
|
||||
m = get_mage(u);
|
||||
m = get_mage_depr(u);
|
||||
if (!m)
|
||||
return 0;
|
||||
|
||||
|
@ -620,7 +630,7 @@ void set_spellpoints(unit * u, int sp)
|
|||
{
|
||||
sc_mage *m;
|
||||
|
||||
m = get_mage(u);
|
||||
m = get_mage_depr(u);
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
|
@ -637,7 +647,7 @@ int change_spellpoints(unit * u, int mp)
|
|||
sc_mage *m;
|
||||
int sp;
|
||||
|
||||
m = get_mage(u);
|
||||
m = get_mage_depr(u);
|
||||
if (!m) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -656,7 +666,7 @@ static int get_spchange(const unit * u)
|
|||
{
|
||||
sc_mage *m;
|
||||
|
||||
m = get_mage(u);
|
||||
m = get_mage_depr(u);
|
||||
if (!m)
|
||||
return 0;
|
||||
|
||||
|
@ -710,7 +720,7 @@ int change_maxspellpoints(unit * u, int csp)
|
|||
{
|
||||
sc_mage *m;
|
||||
|
||||
m = get_mage(u);
|
||||
m = get_mage_depr(u);
|
||||
if (!m) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -728,7 +738,7 @@ int countspells(unit * u, int step)
|
|||
sc_mage *m;
|
||||
int count;
|
||||
|
||||
m = get_mage(u);
|
||||
m = get_mage_depr(u);
|
||||
if (!m)
|
||||
return 0;
|
||||
|
||||
|
@ -1312,7 +1322,7 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade)
|
|||
}
|
||||
|
||||
/* CHAOSPATZERCHANCE 10 : +10% Chance zu Patzern */
|
||||
mage = get_mage(u);
|
||||
mage = get_mage_depr(u);
|
||||
if (mage->magietyp == M_DRAIG) {
|
||||
fumble_chance += CHAOSPATZERCHANCE;
|
||||
}
|
||||
|
@ -2181,10 +2191,8 @@ void set_familiar(unit * mage, unit * familiar)
|
|||
a = a->next;
|
||||
}
|
||||
if (a == NULL) {
|
||||
attrib *an = a_add(&mage->attribs, a_new(&at_skillmod));
|
||||
skillmod_data *smd = (skillmod_data *)an->data.v;
|
||||
smd->special = sm_familiar;
|
||||
smd->skill = NOSKILL;
|
||||
a = make_skillmod(NOSKILL, sm_familiar, 0.0, 0);
|
||||
a_add(&mage->attribs, a);
|
||||
}
|
||||
|
||||
a = a_find(mage->attribs, &at_familiar);
|
||||
|
@ -2192,17 +2200,19 @@ void set_familiar(unit * mage, unit * familiar)
|
|||
a = a_add(&mage->attribs, a_new(&at_familiar));
|
||||
a->data.v = familiar;
|
||||
}
|
||||
else
|
||||
else {
|
||||
assert(!a->data.v || a->data.v == familiar);
|
||||
/* TODO: Diese Attribute beim Tod des Familiars entfernen: */
|
||||
}
|
||||
|
||||
/* TODO: Diese Attribute beim Tod des Familiars entfernen: */
|
||||
a = a_find(familiar->attribs, &at_familiarmage);
|
||||
if (a == NULL) {
|
||||
a = a_add(&familiar->attribs, a_new(&at_familiarmage));
|
||||
a->data.v = mage;
|
||||
}
|
||||
else
|
||||
else {
|
||||
assert(!a->data.v || a->data.v == mage);
|
||||
}
|
||||
}
|
||||
|
||||
void remove_familiar(unit * mage)
|
||||
|
@ -2218,48 +2228,35 @@ void remove_familiar(unit * mage)
|
|||
while (a && a->type == &at_skillmod) {
|
||||
an = a->next;
|
||||
smd = (skillmod_data *)a->data.v;
|
||||
if (smd->special == sm_familiar)
|
||||
if (smd->special == sm_familiar) {
|
||||
a_remove(&mage->attribs, a);
|
||||
}
|
||||
a = an;
|
||||
}
|
||||
}
|
||||
|
||||
bool create_newfamiliar(unit * mage, unit * familiar)
|
||||
void create_newfamiliar(unit * mage, unit * fam)
|
||||
{
|
||||
/* if the skill modifier for the mage does not yet exist, add it */
|
||||
attrib *a;
|
||||
attrib *afam = a_find(mage->attribs, &at_familiar);
|
||||
attrib *amage = a_find(familiar->attribs, &at_familiarmage);
|
||||
/* skills and spells: */
|
||||
const struct equipment *eq;
|
||||
char eqname[64];
|
||||
const race *rc = u_race(fam);
|
||||
|
||||
if (afam == NULL) {
|
||||
afam = a_add(&mage->attribs, a_new(&at_familiar));
|
||||
}
|
||||
afam->data.v = familiar;
|
||||
if (amage == NULL) {
|
||||
amage = a_add(&familiar->attribs, a_new(&at_familiarmage));
|
||||
}
|
||||
amage->data.v = mage;
|
||||
set_familiar(mage, fam);
|
||||
|
||||
snprintf(eqname, sizeof(eqname), "fam_%s", rc->_name);
|
||||
eq = get_equipment(eqname);
|
||||
if (eq != NULL) {
|
||||
equip_unit(fam, eq);
|
||||
}
|
||||
else {
|
||||
log_info("could not perform initialization for familiar %s.\n", rc->_name);
|
||||
}
|
||||
/* TODO: Diese Attribute beim Tod des Familiars entfernen: */
|
||||
/* Wenn der Magier stirbt, dann auch der Vertraute */
|
||||
add_trigger(&mage->attribs, "destroy", trigger_killunit(familiar));
|
||||
add_trigger(&mage->attribs, "destroy", trigger_killunit(fam));
|
||||
/* Wenn der Vertraute stirbt, dann bekommt der Magier einen Schock */
|
||||
add_trigger(&familiar->attribs, "destroy", trigger_shock(mage));
|
||||
|
||||
a = a_find(mage->attribs, &at_skillmod);
|
||||
while (a && a->type == &at_skillmod) {
|
||||
skillmod_data *smd = (skillmod_data *)a->data.v;
|
||||
if (smd->special == sm_familiar)
|
||||
break;
|
||||
a = a->next;
|
||||
}
|
||||
if (a == NULL) {
|
||||
attrib *an = a_add(&mage->attribs, a_new(&at_skillmod));
|
||||
skillmod_data *smd = (skillmod_data *)an->data.v;
|
||||
smd->special = sm_familiar;
|
||||
smd->skill = NOSKILL;
|
||||
}
|
||||
return true;
|
||||
add_trigger(&fam->attribs, "destroy", trigger_shock(mage));
|
||||
}
|
||||
|
||||
static void * resolve_familiar(int id, void *data) {
|
||||
|
|
|
@ -221,6 +221,7 @@ extern "C" {
|
|||
/* macht die struct unit zu einem neuen Magier: legt die struct u->mage an
|
||||
* und initialisiert den Magiertypus mit mtyp. */
|
||||
sc_mage *get_mage(const struct unit *u);
|
||||
sc_mage *get_mage_depr(const struct unit *u);
|
||||
/* gibt u->mage zurück, bei nicht-Magiern *NULL */
|
||||
bool is_mage(const struct unit *u);
|
||||
/* gibt true, wenn u->mage gesetzt. */
|
||||
|
@ -329,7 +330,7 @@ extern "C" {
|
|||
struct unit *get_clone(const struct unit *u);
|
||||
struct unit *get_clone_mage(const struct unit *u);
|
||||
void remove_familiar(struct unit *mage);
|
||||
bool create_newfamiliar(struct unit *mage, struct unit *familiar);
|
||||
void create_newfamiliar(struct unit *mage, struct unit *familiar);
|
||||
void create_newclone(struct unit *mage, struct unit *familiar);
|
||||
struct unit *has_clone(struct unit *mage);
|
||||
|
||||
|
|
123
src/magic.test.c
123
src/magic.test.c
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <kernel/building.h>
|
||||
#include <kernel/race.h>
|
||||
#include <kernel/equipment.h>
|
||||
#include <kernel/faction.h>
|
||||
#include <kernel/order.h>
|
||||
#include <kernel/item.h>
|
||||
|
@ -477,9 +478,131 @@ static void test_illusioncastle(CuTest *tc)
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_is_mage(CuTest *tc) {
|
||||
unit *u;
|
||||
sc_mage *mage;
|
||||
|
||||
test_setup();
|
||||
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||
CuAssertPtrEquals(tc, NULL, get_mage(u));
|
||||
CuAssertTrue(tc, !is_mage(u));
|
||||
set_level(u, SK_MAGIC, 1);
|
||||
CuAssertTrue(tc, !is_mage(u));
|
||||
CuAssertPtrEquals(tc, NULL, get_mage(u));
|
||||
CuAssertPtrNotNull(tc, mage = create_mage(u, M_CERDDOR));
|
||||
CuAssertPtrEquals(tc, mage, get_mage(u));
|
||||
CuAssertTrue(tc, is_mage(u));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_get_mage(CuTest *tc) {
|
||||
unit *u;
|
||||
sc_mage *mage;
|
||||
|
||||
test_setup();
|
||||
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||
CuAssertPtrEquals(tc, NULL, get_mage(u));
|
||||
CuAssertPtrEquals(tc, NULL, get_mage_depr(u));
|
||||
CuAssertPtrNotNull(tc, mage = create_mage(u, M_CERDDOR));
|
||||
CuAssertPtrEquals(tc, mage, get_mage(u));
|
||||
CuAssertPtrEquals(tc, NULL, get_mage_depr(u));
|
||||
set_level(u, SK_MAGIC, 1);
|
||||
CuAssertPtrEquals(tc, mage, get_mage(u));
|
||||
CuAssertPtrEquals(tc, mage, get_mage_depr(u));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_familiar_set(CuTest *tc) {
|
||||
unit *mag, *fam;
|
||||
|
||||
test_setup();
|
||||
|
||||
mag = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||
fam = test_create_unit(mag->faction, test_create_region(0, 0, 0));
|
||||
CuAssertPtrEquals(tc, NULL, get_familiar(mag));
|
||||
CuAssertPtrEquals(tc, NULL, get_familiar_mage(fam));
|
||||
CuAssertPtrEquals(tc, NULL, a_find(mag->attribs, &at_skillmod));
|
||||
set_familiar(mag, fam);
|
||||
CuAssertPtrEquals(tc, fam, get_familiar(mag));
|
||||
CuAssertPtrEquals(tc, mag, get_familiar_mage(fam));
|
||||
CuAssertPtrNotNull(tc, a_find(mag->attribs, &at_skillmod));
|
||||
remove_familiar(mag);
|
||||
CuAssertPtrEquals(tc, NULL, get_familiar(mag));
|
||||
CuAssertPtrEquals(tc, NULL, a_find(mag->attribs, &at_skillmod));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_familiar_age(CuTest *tc) {
|
||||
unit *mag, *fam;
|
||||
|
||||
test_setup();
|
||||
|
||||
mag = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||
fam = test_create_unit(mag->faction, test_create_region(0, 0, 0));
|
||||
set_familiar(mag, fam);
|
||||
CuAssertPtrEquals(tc, fam, get_familiar(mag));
|
||||
CuAssertPtrEquals(tc, mag, get_familiar_mage(fam));
|
||||
a_age(&fam->attribs, fam);
|
||||
a_age(&mag->attribs, mag);
|
||||
CuAssertPtrEquals(tc, fam, get_familiar(mag));
|
||||
CuAssertPtrEquals(tc, mag, get_familiar_mage(fam));
|
||||
set_number(fam, 0);
|
||||
a_age(&mag->attribs, mag);
|
||||
CuAssertPtrEquals(tc, NULL, get_familiar(mag));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_familiar_equip(CuTest *tc) {
|
||||
unit *mag, *u;
|
||||
equipment *eq;
|
||||
const item_type * itype;
|
||||
spell *sp;
|
||||
sc_mage * mage;
|
||||
|
||||
test_setup();
|
||||
|
||||
itype = test_create_itemtype("horse");
|
||||
CuAssertPtrNotNull(tc, itype);
|
||||
sp = create_spell("testspell");
|
||||
CuAssertPtrNotNull(tc, sp);
|
||||
|
||||
eq = get_or_create_equipment("fam_human");
|
||||
equipment_setitem(eq, itype, "1");
|
||||
equipment_setskill(eq, SK_ENTERTAINMENT, "5");
|
||||
equipment_addspell(eq, sp->sname, 1);
|
||||
|
||||
mag = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||
u = test_create_unit(mag->faction, test_create_region(0, 0, 0));
|
||||
set_familiar(mag, u);
|
||||
create_newfamiliar(mag, u);
|
||||
CuAssertIntEquals(tc, 1, i_get(u->items, itype));
|
||||
CuAssertIntEquals(tc, 5, get_level(u, SK_ENTERTAINMENT));
|
||||
CuAssertIntEquals(tc, 0, get_level(u, SK_MAGIC));
|
||||
|
||||
mage = get_mage(u);
|
||||
CuAssertPtrNotNull(tc, mage);
|
||||
CuAssertPtrNotNull(tc, mage->spellbook);
|
||||
set_level(u, SK_MAGIC, 1);
|
||||
CuAssertPtrEquals(tc, mage, get_mage_depr(u));
|
||||
CuAssertTrue(tc, u_hasspell(u, sp));
|
||||
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
CuSuite *get_familiar_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_familiar_equip);
|
||||
SUITE_ADD_TEST(suite, test_familiar_set);
|
||||
SUITE_ADD_TEST(suite, test_familiar_age);
|
||||
return suite;
|
||||
}
|
||||
|
||||
CuSuite *get_magic_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_is_mage);
|
||||
SUITE_ADD_TEST(suite, test_get_mage);
|
||||
SUITE_ADD_TEST(suite, test_multi_cast);
|
||||
SUITE_ADD_TEST(suite, test_updatespells);
|
||||
SUITE_ADD_TEST(suite, test_spellbooks);
|
||||
|
|
|
@ -147,8 +147,7 @@ newfaction *read_newfactions(const char *filename)
|
|||
faction *f;
|
||||
char race[20], email[64], lang[8], password[16];
|
||||
newfaction *nf, **nfi;
|
||||
int bonus = 0, subscription = 0;
|
||||
int alliance = 0;
|
||||
int alliance = 0, subscription = 0;
|
||||
|
||||
if (fgets(buf, sizeof(buf), F) == NULL)
|
||||
break;
|
||||
|
@ -156,8 +155,8 @@ newfaction *read_newfactions(const char *filename)
|
|||
email[0] = '\0';
|
||||
password[0] = '\0';
|
||||
|
||||
if (sscanf(buf, "%54s %20s %8s %d %d %16s %d", email, race, lang, &bonus,
|
||||
&subscription, password, &alliance) < 3) {
|
||||
if (sscanf(buf, "%54s %20s %8s %16s %d %d", email, race, lang,
|
||||
password, &subscription, &alliance) < 3) {
|
||||
break;
|
||||
}
|
||||
if (email[0] == '#') {
|
||||
|
@ -228,7 +227,6 @@ newfaction *read_newfactions(const char *filename)
|
|||
}
|
||||
}
|
||||
nf->lang = get_locale(lang);
|
||||
nf->bonus = bonus;
|
||||
assert(nf->race && nf->email && nf->lang);
|
||||
nfi = &newfactions;
|
||||
while (*nfi) {
|
||||
|
|
|
@ -24,7 +24,6 @@ extern "C" {
|
|||
char *password;
|
||||
const struct locale *lang;
|
||||
const struct race *race;
|
||||
int bonus;
|
||||
int subscription;
|
||||
bool oldregions;
|
||||
struct alliance *allies;
|
||||
|
|
78
src/move.c
78
src/move.c
|
@ -89,14 +89,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <limits.h>
|
||||
#include <float.h>
|
||||
|
||||
/* Bewegungsweiten: */
|
||||
#define BP_WALKING 4
|
||||
#define BP_RIDING 6
|
||||
#define BP_UNICORN 9
|
||||
#define BP_DRAGON 4
|
||||
#define BP_NORMAL 3
|
||||
#define BP_ROAD 2
|
||||
|
||||
int *storms;
|
||||
|
||||
typedef struct traveldir {
|
||||
|
@ -265,7 +257,7 @@ get_transporters(const item * itm, int *p_animals, int *p_acap, int *p_vehicles,
|
|||
*p_acap = acap;
|
||||
}
|
||||
|
||||
static int ridingcapacity(unit * u)
|
||||
static int ridingcapacity(const unit * u)
|
||||
{
|
||||
int vehicles = 0, vcap = 0;
|
||||
int animals = 0, acap = 0;
|
||||
|
@ -433,7 +425,7 @@ bool canswim(unit * u)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int canride(unit * u)
|
||||
static int canride(const unit * u)
|
||||
{
|
||||
int horses = 0, maxhorses, unicorns = 0, maxunicorns;
|
||||
int skill = effskill(u, SK_RIDING, 0);
|
||||
|
@ -460,17 +452,17 @@ static int canride(unit * u)
|
|||
if (!(u_race(u)->flags & RCF_HORSE)
|
||||
&& ((horses == 0 && unicorns == 0)
|
||||
|| horses > maxhorses || unicorns > maxunicorns)) {
|
||||
return 0;
|
||||
return BP_WALKING;
|
||||
}
|
||||
|
||||
if (ridingcapacity(u) - eff_weight(u) >= 0) {
|
||||
if (horses == 0 && unicorns >= u->number && !(u_race(u)->flags & RCF_HORSE)) {
|
||||
return 2;
|
||||
return BP_UNICORN;
|
||||
}
|
||||
return 1;
|
||||
return BP_RIDING;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return BP_WALKING;
|
||||
}
|
||||
|
||||
static bool cansail(const region * r, ship * sh)
|
||||
|
@ -1399,9 +1391,9 @@ static void make_route(unit * u, order * ord, region_list ** routep)
|
|||
* Normalerweise verliert man 3 BP pro Region, bei Straßen nur 2 BP.
|
||||
* Außerdem: Wenn Einheit transportiert, nur halbe BP
|
||||
*/
|
||||
static int movement_speed(unit * u)
|
||||
int movement_speed(const unit * u)
|
||||
{
|
||||
int mp = BP_WALKING;
|
||||
int mp = 0;
|
||||
const race *rc = u_race(u);
|
||||
double dk = rc->speed;
|
||||
assert(u->number);
|
||||
|
@ -1415,6 +1407,10 @@ static int movement_speed(unit * u)
|
|||
mp = BP_DRAGON;
|
||||
break;
|
||||
default:
|
||||
mp = canride(u);
|
||||
if (mp>=BP_RIDING) {
|
||||
dk = 1.0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1426,38 +1422,22 @@ static int movement_speed(unit * u)
|
|||
}
|
||||
}
|
||||
|
||||
switch (canride(u)) {
|
||||
case 1: /* Pferd */
|
||||
mp = BP_RIDING;
|
||||
break;
|
||||
/* unicorn in inventory */
|
||||
if (u->number <= i_get(u->items, it_find("fairyboot"))) {
|
||||
mp *= 2;
|
||||
}
|
||||
|
||||
case 2: /* Einhorn */
|
||||
mp = BP_UNICORN;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Siebenmeilentee */
|
||||
if (get_effect(u, oldpotiontype[P_FAST]) >= u->number) {
|
||||
mp *= 2;
|
||||
change_effect(u, oldpotiontype[P_FAST], -u->number);
|
||||
}
|
||||
|
||||
/* unicorn in inventory */
|
||||
if (u->number <= i_get(u->items, it_find("fairyboot"))) {
|
||||
mp *= 2;
|
||||
}
|
||||
|
||||
/* Im Astralraum sind Tyb und Ill-Magier doppelt so schnell.
|
||||
* Nicht kumulativ mit anderen Beschleunigungen! */
|
||||
if (mp * dk <= BP_WALKING * u_race(u)->speed && is_astral(u->region)
|
||||
&& is_mage(u)) {
|
||||
sc_mage *mage = get_mage(u);
|
||||
if (mage->magietyp == M_TYBIED || mage->magietyp == M_ILLAUN) {
|
||||
/* Im Astralraum sind Tyb und Ill-Magier doppelt so schnell.
|
||||
* Nicht kumulativ mit anderen Beschleunigungen! */
|
||||
if (mp * dk <= BP_WALKING * u_race(u)->speed && is_astral(u->region)) {
|
||||
sc_mage *mage = get_mage(u);
|
||||
if (mage && (mage->magietyp == M_TYBIED || mage->magietyp == M_ILLAUN)) {
|
||||
if (has_skill(u, SK_MAGIC)) {
|
||||
mp *= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (int)(dk * mp);
|
||||
}
|
||||
|
||||
|
@ -2044,7 +2024,7 @@ static const region_list *travel_i(unit * u, const region_list * route_begin,
|
|||
const region_list * route_end, order * ord, int mode, follower ** followers)
|
||||
{
|
||||
region *r = u->region;
|
||||
|
||||
int mp;
|
||||
if (u->building && !can_leave(u)) {
|
||||
cmistake(u, u->thisorder, 150, MSG_MOVE);
|
||||
return route_begin;
|
||||
|
@ -2060,7 +2040,15 @@ static const region_list *travel_i(unit * u, const region_list * route_begin,
|
|||
cmistake(u, ord, 42, MSG_MOVE);
|
||||
return route_begin;
|
||||
}
|
||||
route_end = cap_route(r, route_begin, route_end, movement_speed(u));
|
||||
|
||||
mp = movement_speed(u);
|
||||
/* Siebenmeilentee */
|
||||
if (get_effect(u, oldpotiontype[P_FAST]) >= u->number) {
|
||||
mp *= 2;
|
||||
change_effect(u, oldpotiontype[P_FAST], -u->number);
|
||||
}
|
||||
|
||||
route_end = cap_route(r, route_begin, route_end, mp);
|
||||
|
||||
route_end = travel_route(u, route_begin, route_end, ord, mode);
|
||||
if (u->flags&UFL_FOLLOWED) {
|
||||
|
|
|
@ -36,6 +36,14 @@ extern "C" {
|
|||
extern struct attrib_type at_shiptrail;
|
||||
extern int *storms;
|
||||
|
||||
/* Bewegungsweiten: */
|
||||
#define BP_WALKING 4
|
||||
#define BP_RIDING 6
|
||||
#define BP_UNICORN 9
|
||||
#define BP_DRAGON 4
|
||||
#define BP_NORMAL 3
|
||||
#define BP_ROAD 2
|
||||
|
||||
/* die Zahlen sind genau äquivalent zu den race Flags */
|
||||
#define MV_CANNOTMOVE (1<<5)
|
||||
#define MV_FLY (1<<7) /* kann fliegen */
|
||||
|
@ -70,6 +78,7 @@ extern "C" {
|
|||
struct ship *move_ship(struct ship *sh, struct region *from,
|
||||
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);
|
||||
struct unit *owner_buildingtyp(const struct region *r,
|
||||
const struct building_type *bt);
|
||||
|
|
|
@ -522,9 +522,33 @@ static void test_ship_leave_trail(CuTest *tc) {
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_movement_speed(CuTest *tc) {
|
||||
unit * u;
|
||||
race * rc;
|
||||
const struct item_type *it_horse;
|
||||
|
||||
test_setup();
|
||||
it_horse = test_create_horse();
|
||||
rc = test_create_race(NULL);
|
||||
u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, NULL));
|
||||
|
||||
rc->speed = 1.0;
|
||||
CuAssertIntEquals(tc, BP_WALKING, movement_speed(u));
|
||||
|
||||
rc->speed = 2.0;
|
||||
CuAssertIntEquals(tc, 2 * BP_WALKING, movement_speed(u));
|
||||
|
||||
set_level(u, SK_RIDING, 1);
|
||||
i_change(&u->items, it_horse, 1);
|
||||
CuAssertIntEquals(tc, BP_RIDING, movement_speed(u));
|
||||
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
CuSuite *get_move_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_movement_speed);
|
||||
SUITE_ADD_TEST(suite, test_walkingcapacity);
|
||||
SUITE_ADD_TEST(suite, test_ship_not_allowed_in_coast);
|
||||
SUITE_ADD_TEST(suite, test_ship_leave_trail);
|
||||
|
|
|
@ -1090,6 +1090,9 @@ void report_region(struct stream *out, const region * r, faction * f)
|
|||
message *msg;
|
||||
|
||||
if (owner != NULL) {
|
||||
bytes = (int)strlcpy(bufp, " ", size);
|
||||
if (wrptr(&bufp, &size, bytes) != 0)
|
||||
WARN_STATIC_BUFFER();
|
||||
msg = msg_message("nr_region_owner", "faction", owner);
|
||||
bytes = (int)nr_render(msg, f->locale, bufp, size, f);
|
||||
msg_release(msg);
|
||||
|
|
|
@ -819,8 +819,9 @@ spskill(char *buffer, size_t size, const struct locale * lang,
|
|||
bufp = STRLCPY(bufp, " ", size);
|
||||
|
||||
if (sv->id == SK_MAGIC) {
|
||||
sc_mage *mage = get_mage(u);
|
||||
if (mage && mage->magietyp != M_GRAY) {
|
||||
sc_mage *mage = get_mage_depr(u);
|
||||
assert(mage);
|
||||
if (mage->magietyp != M_GRAY) {
|
||||
bufp = STRLCPY(bufp, LOC(lang, mkname("school",
|
||||
magic_school[mage->magietyp])), size);
|
||||
bufp = STRLCPY(bufp, " ", size);
|
||||
|
|
46
src/spells.c
46
src/spells.c
|
@ -39,7 +39,6 @@
|
|||
#include <kernel/building.h>
|
||||
#include <kernel/curse.h>
|
||||
#include <kernel/connection.h>
|
||||
#include <kernel/equipment.h>
|
||||
#include <kernel/faction.h>
|
||||
#include <kernel/item.h>
|
||||
#include <kernel/messages.h>
|
||||
|
@ -513,32 +512,26 @@ static const race *select_familiar(const race * magerace, magic_t magiegebiet)
|
|||
/* ------------------------------------------------------------- */
|
||||
/* der Vertraue des Magiers */
|
||||
|
||||
static void make_familiar(unit * familiar, unit * mage)
|
||||
static unit * make_familiar(unit * mage, region *r, const race *rc, const char *name)
|
||||
{
|
||||
/* skills and spells: */
|
||||
const struct equipment *eq;
|
||||
char eqname[64];
|
||||
const race * rc = u_race(familiar);
|
||||
snprintf(eqname, sizeof(eqname), "fam_%s", rc->_name);
|
||||
eq = get_equipment(eqname);
|
||||
if (eq != NULL) {
|
||||
equip_items(&familiar->items, eq);
|
||||
}
|
||||
else {
|
||||
log_info("could not perform initialization for familiar %s.\n", rc->_name);
|
||||
}
|
||||
unit *fam;
|
||||
|
||||
fam = create_unit(r, mage->faction, 1, rc, 0, name, mage);
|
||||
setstatus(fam, ST_FLEE);
|
||||
fset(fam, UFL_LOCKED);
|
||||
|
||||
/* triggers: */
|
||||
create_newfamiliar(mage, familiar);
|
||||
create_newfamiliar(mage, fam);
|
||||
|
||||
/* Hitpoints nach Talenten korrigieren, sonst starten vertraute
|
||||
* mit Ausdauerbonus verwundet */
|
||||
familiar->hp = unit_max_hp(familiar);
|
||||
fam->hp = unit_max_hp(fam);
|
||||
|
||||
return fam;
|
||||
}
|
||||
|
||||
static int sp_summon_familiar(castorder * co)
|
||||
{
|
||||
unit *familiar;
|
||||
region *r = co_get_region(co);
|
||||
unit *mage = co->magician.u;
|
||||
int cast_level = co->level;
|
||||
|
@ -586,10 +579,7 @@ static int sp_summon_familiar(castorder * co)
|
|||
msg = msg_message("familiar_name", "unit", mage);
|
||||
nr_render(msg, mage->faction->locale, zText, sizeof(zText), mage->faction);
|
||||
msg_release(msg);
|
||||
familiar = create_unit(r, mage->faction, 1, rc, 0, zText, mage);
|
||||
setstatus(familiar, ST_FLEE);
|
||||
fset(familiar, UFL_LOCKED);
|
||||
make_familiar(familiar, mage);
|
||||
make_familiar(mage, r, rc, zText);
|
||||
|
||||
dh = 0;
|
||||
dh1 = 0;
|
||||
|
@ -740,7 +730,7 @@ static int sp_transferaura(castorder * co)
|
|||
int cast_level = co->level;
|
||||
spellparameter *pa = co->par;
|
||||
unit *u;
|
||||
sc_mage *scm_dst, *scm_src = get_mage(mage);
|
||||
sc_mage *scm_dst, *scm_src = get_mage_depr(mage);
|
||||
|
||||
/* wenn kein Ziel gefunden, Zauber abbrechen */
|
||||
if (pa->param[0]->flag == TARGET_NOTFOUND)
|
||||
|
@ -754,7 +744,7 @@ static int sp_transferaura(castorder * co)
|
|||
/* Wieviel Transferieren? */
|
||||
aura = pa->param[1]->data.i;
|
||||
u = pa->param[0]->data.u;
|
||||
scm_dst = get_mage(u);
|
||||
scm_dst = get_mage_depr(u);
|
||||
|
||||
if (scm_dst == NULL) {
|
||||
/* "Zu dieser Einheit kann ich keine Aura uebertragen." */
|
||||
|
@ -5822,7 +5812,7 @@ int sp_permtransfer(castorder * co)
|
|||
change_maxspellpoints(mage, -aura);
|
||||
change_spellpoints(mage, -aura);
|
||||
|
||||
if (get_mage(tu)->magietyp == get_mage(mage)->magietyp) {
|
||||
if (get_mage_depr(tu)->magietyp == get_mage_depr(mage)->magietyp) {
|
||||
change_maxspellpoints(tu, aura / 2);
|
||||
}
|
||||
else {
|
||||
|
@ -5945,18 +5935,18 @@ int sp_stealaura(castorder * co)
|
|||
/* Zieleinheit */
|
||||
u = pa->param[0]->data.u;
|
||||
|
||||
if (!get_mage(u)) {
|
||||
if (!get_mage_depr(u)) {
|
||||
ADDMSG(&mage->faction->msgs, msg_message("stealaura_fail", "unit target",
|
||||
mage, u));
|
||||
ADDMSG(&u->faction->msgs, msg_message("stealaura_fail_detect", "unit", u));
|
||||
return 0;
|
||||
}
|
||||
|
||||
taura = (get_mage(u)->spellpoints * (rng_int() % (int)(3 * power) + 1)) / 100;
|
||||
taura = (get_mage_depr(u)->spellpoints * (rng_int() % (int)(3 * power) + 1)) / 100;
|
||||
|
||||
if (taura > 0) {
|
||||
get_mage(u)->spellpoints -= taura;
|
||||
get_mage(mage)->spellpoints += taura;
|
||||
get_mage_depr(u)->spellpoints -= taura;
|
||||
get_mage_depr(mage)->spellpoints += taura;
|
||||
/* sprintf(buf, "%s entzieht %s %d Aura.", unitname(mage), unitname(u),
|
||||
taura); */
|
||||
ADDMSG(&mage->faction->msgs, msg_message("stealaura_success",
|
||||
|
|
|
@ -68,7 +68,7 @@ void spy_message(int spy, const unit * u, const unit * target)
|
|||
ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target status", u,
|
||||
target, status));
|
||||
if (spy > 20) {
|
||||
sc_mage *mage = get_mage(target);
|
||||
sc_mage *mage = get_mage_depr(target);
|
||||
/* for mages, spells and magic school */
|
||||
if (mage) {
|
||||
ADDMSG(&u->faction->msgs, msg_message("spyreport_mage", "spy target type", u,
|
||||
|
|
|
@ -427,8 +427,8 @@ int teach_cmd(unit * teacher, struct order *ord)
|
|||
if (sk == SK_MAGIC) {
|
||||
/* ist der Magier schon spezialisiert, so versteht er nur noch
|
||||
* Lehrer seines Gebietes */
|
||||
sc_mage *mage1 = get_mage(teacher);
|
||||
sc_mage *mage2 = get_mage(student);
|
||||
sc_mage *mage1 = get_mage_depr(teacher);
|
||||
sc_mage *mage2 = get_mage_depr(student);
|
||||
if (mage2 && mage1 && mage2->magietyp != M_GRAY
|
||||
&& mage1->magietyp != mage2->magietyp) {
|
||||
if (feedback) {
|
||||
|
@ -782,7 +782,7 @@ int study_cmd(unit * u, order * ord)
|
|||
}
|
||||
}
|
||||
else if (sk == SK_MAGIC) {
|
||||
sc_mage *mage = get_mage(u);
|
||||
sc_mage *mage = get_mage_depr(u);
|
||||
if (!mage) {
|
||||
mage = create_mage(u, u->faction->magiegebiet);
|
||||
}
|
||||
|
|
|
@ -409,11 +409,11 @@ static void test_study_magic(CuTest *tc) {
|
|||
study_cmd(u, u->thisorder);
|
||||
CuAssertIntEquals(tc, M_GWYRRD, f->magiegebiet);
|
||||
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
|
||||
CuAssertPtrNotNull(tc, get_mage(u));
|
||||
CuAssertPtrNotNull(tc, get_mage_depr(u));
|
||||
CuAssertPtrEquals(tc, 0, test_find_messagetype(f->msgs, "error65"));
|
||||
CuAssertIntEquals(tc, M_GWYRRD, get_mage(u)->magietyp);
|
||||
CuAssertIntEquals(tc, M_GWYRRD, get_mage_depr(u)->magietyp);
|
||||
|
||||
/* the static cost array in study_cost prevents this test:
|
||||
/* TODO: the static cost array in study_cost prevents this test:
|
||||
test_clear_messages(f);
|
||||
config_set("skills.cost.magic", "50");
|
||||
i_change(&u->items, rtype->itype, 50);
|
||||
|
|
|
@ -101,6 +101,7 @@ int RunAllTests(int argc, char *argv[])
|
|||
ADD_SUITE(pool);
|
||||
ADD_SUITE(curse);
|
||||
ADD_SUITE(equipment);
|
||||
ADD_SUITE(familiar);
|
||||
ADD_SUITE(item);
|
||||
ADD_SUITE(magic);
|
||||
ADD_SUITE(alchemy);
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
struct race *test_create_race(const char *name)
|
||||
{
|
||||
race *rc = rc_get_or_create(name);
|
||||
race *rc = rc_get_or_create(name ? name : "smurf");
|
||||
rc->maintenance = 10;
|
||||
rc->hitpoints = 20;
|
||||
rc->maxaura = 100;
|
||||
|
|
|
@ -396,7 +396,6 @@ int a_age(attrib ** p, void *owner)
|
|||
|
||||
static critbit_tree cb_deprecated = { 0 };
|
||||
|
||||
|
||||
typedef struct deprecated_s {
|
||||
unsigned int hash;
|
||||
int(*reader)(attrib *, void *, struct gamedata *);
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
/* unfinished: */
|
||||
#define CRYPT_VERSION 400 /* passwords are encrypted */
|
||||
|
||||
#define RELEASE_VERSION SKILLSORT_VERSION /* current datafile */
|
||||
#define RELEASE_VERSION LANDDISPLAY_VERSION /* current datafile */
|
||||
#define MIN_VERSION UIDHASH_VERSION /* minimal datafile we support */
|
||||
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ assert_grep_count() {
|
|||
file=$1
|
||||
expr=$2
|
||||
expect=$3
|
||||
count=`grep -cE $expr $file`
|
||||
count=`grep -cE "$expr" $file`
|
||||
[ $count -eq $expect ] || quit 1 "expected $expect counts of $expr in $file, got $count"
|
||||
echo "PASS: $expr is $expect"
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ setup
|
|||
cleanup
|
||||
VALGRIND=`which valgrind`
|
||||
SERVER=../Debug/eressea/eressea
|
||||
set -e
|
||||
#set -e
|
||||
if [ -n "$VALGRIND" ]; then
|
||||
SUPP=../share/ubuntu-12_04.supp
|
||||
SERVER="$VALGRIND --track-origins=yes --gen-suppressions=all --suppressions=$SUPP --error-exitcode=1 --leak-check=no $SERVER"
|
||||
|
@ -62,5 +62,6 @@ assert_grep_count reports/185-heg.cr '"lighthouse";visibility' 6
|
|||
assert_grep_count reports/185-heg.cr '"neighbour";visibility' 11
|
||||
assert_grep_count reports/185-6rLo.cr '^EINHEIT' 2
|
||||
assert_grep_count reports/185-6rLo.cr '^REGION' 13
|
||||
assert_grep_count reports/185-6rLo.cr "Befehl ist unbekannt" 0
|
||||
echo "integration tests: PASS"
|
||||
cleanup
|
||||
|
|
Loading…
Reference in New Issue