forked from github/server
- recruiting secondary races
- some archetype changes - new looting rules
This commit is contained in:
parent
0181fa3c25
commit
43bf73a01b
|
@ -13,6 +13,7 @@
|
|||
#include <util/umlaut.h>
|
||||
#include <util/language.h>
|
||||
#include <util/xml.h>
|
||||
#include <util/functions.h>
|
||||
|
||||
/* libxml includes */
|
||||
#include <libxml/tree.h>
|
||||
|
@ -83,6 +84,7 @@ parse_archetypes(xmlDocPtr doc)
|
|||
int i;
|
||||
for (i=0;i!=nodes->nodeNr;++i) {
|
||||
xmlNodePtr node = nodes->nodeTab[i];
|
||||
xmlNodePtr child;
|
||||
archetype * arch = calloc(1, sizeof(archetype));
|
||||
xmlXPathObjectPtr sub;
|
||||
|
||||
|
@ -109,6 +111,18 @@ parse_archetypes(xmlDocPtr doc)
|
|||
|
||||
arch->size = xml_ivalue(node, "cost", 0);
|
||||
|
||||
for (child=node->children;child;child=child->next) {
|
||||
if (strcmp((const char *)child->name, "function")==0) {
|
||||
xmlChar * propName = xmlGetProp(child, BAD_CAST "name");
|
||||
xmlChar * propValue = xmlGetProp(child, BAD_CAST "value");
|
||||
if (strcmp((const char *)propName, "create")) {
|
||||
pf_generic foo = get_function((const char *)propValue);
|
||||
arch->exec = (archetype_function)foo;
|
||||
}
|
||||
xmlFree(propValue);
|
||||
xmlFree(propName);
|
||||
}
|
||||
}
|
||||
xpath->node = node;
|
||||
sub = xmlXPathEvalExpression(BAD_CAST "allow|deny", xpath);
|
||||
if (sub->nodesetval && sub->nodesetval->nodeNr) {
|
||||
|
|
|
@ -23,6 +23,8 @@ extern "C" {
|
|||
char * value;
|
||||
} rule;
|
||||
|
||||
typedef int (*archetype_function)(struct unit * u, const struct archetype *, int);
|
||||
|
||||
typedef struct archetype {
|
||||
struct archetype * next;
|
||||
char * name[2];
|
||||
|
@ -31,6 +33,7 @@ extern "C" {
|
|||
struct equipment * equip;
|
||||
struct construction * ctype;
|
||||
struct rule * rules;
|
||||
archetype_function exec;
|
||||
} archetype;
|
||||
|
||||
extern const struct archetype * find_archetype(const char * s, const struct locale * lang);
|
||||
|
|
|
@ -1109,7 +1109,7 @@ cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
|
|||
if (sr->mode!=see_unit) fprintf(F, "\"%s\";visibility\n", visibility[sr->mode]);
|
||||
|
||||
{
|
||||
faction * owner = get_region_owner(r);
|
||||
faction * owner = region_get_owner(r);
|
||||
if (owner) {
|
||||
fprintf(F, "%d;owner\n", owner->no);
|
||||
}
|
||||
|
|
|
@ -436,6 +436,20 @@ expandrecruit(region * r, request * recruitorders)
|
|||
assert(recruitorders==NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
recruit_cost(const faction * f, const race * rc)
|
||||
{
|
||||
if (is_monsters(f) || f->race==rc) {
|
||||
return rc->recruitcost;
|
||||
} else {
|
||||
const char * str = get_param(f->race->parameters, "other_race");
|
||||
if (str && strcmp(rc->_name[0], str)==0) {
|
||||
return get_param_int(f->race->parameters, "other_cost", -1);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
recruit(unit * u, struct order * ord, request ** recruitorders)
|
||||
{
|
||||
|
@ -446,16 +460,26 @@ recruit(unit * u, struct order * ord, request ** recruitorders)
|
|||
int recruitcost;
|
||||
const faction * f = u->faction;
|
||||
const struct race * rc = f->race;
|
||||
const char * str;
|
||||
|
||||
init_tokens(ord);
|
||||
skip_token();
|
||||
n = getuint();
|
||||
if (is_monsters(f)) {
|
||||
/* Monster dürfen REKRUTIERE 15 dracoid machen */
|
||||
const char * str = getstrtoken();
|
||||
|
||||
str = getstrtoken();
|
||||
if (str) {
|
||||
/* Monster dürfen REKRUTIERE 15 dracoid machen
|
||||
* also: secondary race */
|
||||
rc = findrace(str, f->locale);
|
||||
if (rc==NULL) rc = f->race;
|
||||
recruitcost = recruit_cost(f, rc);
|
||||
if ((u->number!=0 && rc!=f->race) || rc==NULL || recruitcost<0) {
|
||||
rc = f->race;
|
||||
recruitcost = recruit_cost(f, f->race);
|
||||
}
|
||||
} else {
|
||||
recruitcost = recruit_cost(f, f->race);
|
||||
}
|
||||
assert(recruitcost>=0);
|
||||
|
||||
#if GUARD_DISABLES_RECRUIT
|
||||
/* this is a very special case because the recruiting unit may be empty
|
||||
|
@ -507,7 +531,6 @@ recruit(unit * u, struct order * ord, request ** recruitorders)
|
|||
}
|
||||
}
|
||||
|
||||
recruitcost = rc->recruitcost;
|
||||
if (recruitcost) {
|
||||
pl = getplane(r);
|
||||
if (pl && fval(pl, PFL_NORECRUITS)) {
|
||||
|
@ -1066,12 +1089,31 @@ maintain_buildings(region * r, boolean crash)
|
|||
}
|
||||
}
|
||||
|
||||
#define RECRUIT_MERGE 1
|
||||
#define RECRUIT_CLASSIC 2
|
||||
#define RECRUIT_ARCHETYPES 4
|
||||
static int rules_recruit = -1;
|
||||
|
||||
static int
|
||||
recruit_archetype(unit * u, order * ord)
|
||||
{
|
||||
boolean merge = (u->number>0);
|
||||
int want;
|
||||
const char * s;
|
||||
|
||||
if (rules_recruit<0) {
|
||||
rules_recruit = 0;
|
||||
if (get_param_int(global.parameters, "recruit.allow_merge", 1)) {
|
||||
rules_recruit |= RECRUIT_MERGE;
|
||||
}
|
||||
if (get_param_int(global.parameters, "recruit.classic", 1)) {
|
||||
rules_recruit |= RECRUIT_CLASSIC;
|
||||
}
|
||||
if (get_param_int(global.parameters, "recruit.archetype", 0)) {
|
||||
rules_recruit |= RECRUIT_ARCHETYPES;
|
||||
}
|
||||
}
|
||||
|
||||
init_tokens(ord);
|
||||
skip_token();
|
||||
want = getuint();
|
||||
|
@ -1081,7 +1123,7 @@ recruit_archetype(unit * u, order * ord)
|
|||
const archetype * arch = find_archetype(s, u->faction->locale);
|
||||
attrib * a = NULL;
|
||||
|
||||
if (u->number>0) {
|
||||
if ((rules_recruit&RECRUIT_MERGE)==0 && merge) {
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unit_must_be_new", ""));
|
||||
/* TODO: error message */
|
||||
return 0;
|
||||
|
@ -1146,15 +1188,29 @@ recruit_archetype(unit * u, order * ord)
|
|||
|
||||
n = build(u, arch->ctype, 0, n);
|
||||
if (n>0) {
|
||||
set_number(u, n);
|
||||
equip_unit(u, arch->equip);
|
||||
u->hp = n * unit_max_hp(u);
|
||||
if (arch->size) {
|
||||
if (a==NULL) a = a_add(&u->building->attribs, a_new(&at_recruit));
|
||||
a->data.i += n*arch->size;
|
||||
unit * u2;
|
||||
if (merge) {
|
||||
u2 = create_unit(u->region, u->faction, 0, u->race, 0, 0, u);
|
||||
} else {
|
||||
u2 = u;
|
||||
}
|
||||
if (arch->exec) {
|
||||
n = arch->exec(u2, arch, n);
|
||||
}
|
||||
else {
|
||||
set_number(u2, n);
|
||||
equip_unit(u2, arch->equip);
|
||||
u2->hp = n * unit_max_hp(u2);
|
||||
if (arch->size) {
|
||||
if (a==NULL) a = a_add(&u->building->attribs, a_new(&at_recruit));
|
||||
a->data.i += n*arch->size;
|
||||
}
|
||||
}
|
||||
ADDMSG(&u->faction->msgs, msg_message("recruit_archetype",
|
||||
"unit amount archetype", u, n, arch->name[n==1]));
|
||||
if (u!=u2 && u->race==u2->race) {
|
||||
transfermen(u2, u, u2->number);
|
||||
}
|
||||
return n;
|
||||
} else switch(n) {
|
||||
case ENOMATERIALS:
|
||||
|
@ -1173,24 +1229,20 @@ recruit_archetype(unit * u, order * ord)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
recruit_classic(void)
|
||||
static void recruit_init(void)
|
||||
{
|
||||
static int value = -1;
|
||||
if (value<0) {
|
||||
value = get_param_int(global.parameters, "recruit.classic", 1);
|
||||
if (rules_recruit<0) {
|
||||
rules_recruit = 0;
|
||||
if (get_param_int(global.parameters, "recruit.allow_merge", 1)) {
|
||||
rules_recruit |= RECRUIT_MERGE;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int
|
||||
recruit_archetypes(void)
|
||||
int recruit_archetypes(void)
|
||||
{
|
||||
static int value = -1;
|
||||
if (value<0) {
|
||||
value = get_param_int(global.parameters, "recruit.archetypes", 0);
|
||||
}
|
||||
return value;
|
||||
if (rules_recruit<0) recruit_init();
|
||||
return (rules_recruit&RECRUIT_ARCHETYPES)!=0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1232,22 +1284,23 @@ economics(region *r)
|
|||
}
|
||||
/* RECRUIT orders */
|
||||
|
||||
if (rules_recruit<0) recruit_init();
|
||||
for (u = r->units; u; u = u->next) {
|
||||
order * ord;
|
||||
if (!recruit_classic()) {
|
||||
if (u->number>0) continue;
|
||||
}
|
||||
for (ord = u->orders; ord; ord = ord->next) {
|
||||
if (get_keyword(ord) == K_RECRUIT) {
|
||||
if (recruit_archetypes()) {
|
||||
if (recruit_archetype(u, ord)>=0) {
|
||||
continue;
|
||||
|
||||
if ((rules_recruit&RECRUIT_MERGE) || u->number==0) {
|
||||
for (ord = u->orders; ord; ord = ord->next) {
|
||||
if (get_keyword(ord) == K_RECRUIT) {
|
||||
if (rules_recruit&RECRUIT_ARCHETYPES) {
|
||||
if (recruit_archetype(u, ord)>=0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (rules_recruit&RECRUIT_CLASSIC) {
|
||||
recruit(u, ord, &recruitorders);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (recruit_classic()) {
|
||||
recruit(u, ord, &recruitorders);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3147,8 +3200,9 @@ peasant_taxes(region * r)
|
|||
building * b;
|
||||
int money;
|
||||
int maxsize;
|
||||
int morale;
|
||||
|
||||
f = get_region_owner(r);
|
||||
f = region_get_owner(r);
|
||||
if (f==NULL) return;
|
||||
|
||||
money = rmoney(r);
|
||||
|
@ -3161,8 +3215,9 @@ peasant_taxes(region * r)
|
|||
if (u==NULL || u->faction!=f) return;
|
||||
|
||||
maxsize = buildingeffsize(b, false);
|
||||
if (maxsize > r->land->morale) {
|
||||
maxsize = r->land->morale;
|
||||
morale = region_get_morale(r);
|
||||
if (maxsize > morale) {
|
||||
maxsize = morale;
|
||||
}
|
||||
|
||||
if (maxsize>0) {
|
||||
|
|
|
@ -54,7 +54,6 @@ void maintain_buildings(struct region * r, boolean crash);
|
|||
extern void add_spende(struct faction * f1, struct faction * f2, int betrag, struct region * r);
|
||||
extern int make_cmd(struct unit * u, struct order * ord);
|
||||
extern void split_allocations(struct region * r);
|
||||
extern int recruit_classic(void);
|
||||
extern int recruit_archetypes(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -187,7 +187,7 @@ get_food(region *r)
|
|||
{
|
||||
unit *u;
|
||||
int peasantfood = rpeasants(r)*10;
|
||||
faction * owner = get_region_owner(r);
|
||||
faction * owner = region_get_owner(r);
|
||||
|
||||
/* 1. Versorgung von eigenen Einheiten. Das vorhandene Silber
|
||||
* wird zunächst so auf die Einheiten aufgeteilt, dass idealerweise
|
||||
|
@ -2914,9 +2914,16 @@ age_building(building * b)
|
|||
return b;
|
||||
}
|
||||
|
||||
static void age_region(region * r)
|
||||
{
|
||||
a_age(&r->attribs);
|
||||
handle_event(r->attribs, "timer", r);
|
||||
}
|
||||
|
||||
static void
|
||||
ageing(void)
|
||||
{
|
||||
const building_type * bt_castle = bt_find("castle");
|
||||
faction *f;
|
||||
region *r;
|
||||
|
||||
|
@ -2960,9 +2967,9 @@ ageing(void)
|
|||
building ** bp;
|
||||
unit ** up;
|
||||
ship ** sp;
|
||||
building * blargest = NULL;
|
||||
|
||||
a_age(&r->attribs);
|
||||
handle_event(r->attribs, "timer", r);
|
||||
age_region(r);
|
||||
|
||||
/* Einheiten */
|
||||
for (up=&r->units;*up;) {
|
||||
|
@ -2985,7 +2992,24 @@ ageing(void)
|
|||
building * b = *bp;
|
||||
b = age_building(b);
|
||||
|
||||
if (b==*bp) bp = &(*bp)->next;
|
||||
if (b==*bp) {
|
||||
if (b->type==bt_castle) {
|
||||
if (blargest==NULL || b->size>blargest->size) {
|
||||
blargest = b;
|
||||
}
|
||||
}
|
||||
bp = &(*bp)->next;
|
||||
}
|
||||
if (blargest) {
|
||||
/* region owners update? */
|
||||
faction * f = region_get_owner(r);
|
||||
unit * u = buildingowner(r, blargest);
|
||||
if (u==NULL) {
|
||||
region_set_owner(r, NULL, turn);
|
||||
} else if (u->faction!=f) {
|
||||
region_set_owner(r, f, turn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -996,7 +996,7 @@ describe(FILE * F, const seen_region * sr, faction * f)
|
|||
}
|
||||
|
||||
{
|
||||
const faction * owner = get_region_owner(r);
|
||||
const faction * owner = region_get_owner(r);
|
||||
if (owner!=NULL) {
|
||||
bytes = snprintf(bufp, size, " Die Region ist im Besitz von %s.",
|
||||
factionname(owner));
|
||||
|
|
|
@ -117,11 +117,16 @@ const troop no_troop = {0, 0};
|
|||
|
||||
static int max_turns = 0;
|
||||
static int damage_rules = 0;
|
||||
static int loot_rules = 0;
|
||||
static int skill_formula = 0;
|
||||
|
||||
#define FORMULA_ORIG 0
|
||||
#define FORMULA_NEW 1
|
||||
|
||||
#define LOOT_MONSTERS (1<<0)
|
||||
#define LOOT_SELF (1<<1) /* code is mutually exclusive with LOOT_OTHERS */
|
||||
#define LOOT_OTHERS (1<<2)
|
||||
|
||||
#define DAMAGE_CRITICAL (1<<0)
|
||||
#define DAMAGE_MELEE_BONUS (1<<1)
|
||||
#define DAMAGE_MISSILE_BONUS (1<<2)
|
||||
|
@ -132,6 +137,7 @@ static int skill_formula = 0;
|
|||
static void
|
||||
static_rules(void)
|
||||
{
|
||||
loot_rules = get_param_int(global.parameters, "rules.combat.loot", LOOT_MONSTERS|LOOT_OTHERS);
|
||||
/* new formula to calculate to-hit-chance */
|
||||
skill_formula = get_param_int(global.parameters, "rules.combat.skill_formula", FORMULA_ORIG);
|
||||
/* maximum number of combat turns */
|
||||
|
@ -1279,16 +1285,17 @@ count_side(const side * s, const side * vs, int minrow, int maxrow, int select)
|
|||
* troops that are still alive, not those that are still fighting although
|
||||
* dead. */
|
||||
int
|
||||
count_allies(const side * as, int minrow, int maxrow, int select)
|
||||
count_allies(const side * as, int minrow, int maxrow, int select, int allytype)
|
||||
{
|
||||
battle *b = as->battle;
|
||||
side *s;
|
||||
side *ds;
|
||||
int count = 0;
|
||||
|
||||
for (s=b->sides;s!=b->sides+b->nsides;++s) {
|
||||
if (!helping(as, s)) continue;
|
||||
count += count_side(s, NULL, minrow, maxrow, select);
|
||||
if (count>0 && (select&SELECT_FIND)) break;
|
||||
for (ds=b->sides;ds!=b->sides+b->nsides;++ds) {
|
||||
if ((allytype==ALLY_ANY && helping(as, ds)) || (allytype==ALLY_SELF && as->faction==ds->faction)) {
|
||||
count += count_side(ds, NULL, minrow, maxrow, select);
|
||||
if (count>0 && (select&SELECT_FIND)) break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -1933,12 +1940,14 @@ attacks_per_round(troop t)
|
|||
return t.fighter->person[t.index].speed;
|
||||
}
|
||||
|
||||
|
||||
#define HERO_SPEED 10
|
||||
static void
|
||||
make_heroes(battle * b)
|
||||
{
|
||||
side * s;
|
||||
static int hero_speed = 0;
|
||||
if (hero_speed==0) {
|
||||
hero_speed = get_param_int(global.parameters, "rules.combat.herospeed", 10);
|
||||
}
|
||||
for (s=b->sides;s!=b->sides+b->nsides;++s) {
|
||||
fighter * fig;
|
||||
for (fig=s->fighters;fig;fig=fig->next) {
|
||||
|
@ -1947,7 +1956,7 @@ make_heroes(battle * b)
|
|||
int i;
|
||||
assert(playerrace(u->race));
|
||||
for (i=0;i!=u->number;++i) {
|
||||
fig->person[i].speed += (HERO_SPEED-1);
|
||||
fig->person[i].speed += (hero_speed-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2252,7 +2261,42 @@ make_side(battle * b, const faction * f, const group * g, unsigned int flags, co
|
|||
return s1;
|
||||
}
|
||||
|
||||
void
|
||||
troop
|
||||
select_ally(fighter * af, int minrow, int maxrow, int allytype)
|
||||
{
|
||||
side *as = af->side;
|
||||
battle *b = as->battle;
|
||||
side * ds;
|
||||
int allies = count_allies(as, minrow, maxrow, SELECT_ADVANCE, allytype);
|
||||
|
||||
if (!allies) {
|
||||
return no_troop;
|
||||
}
|
||||
allies = rng_int() % allies;
|
||||
|
||||
for (ds=b->sides;ds!=b->sides+b->nsides;++ds) {
|
||||
if ((allytype==ALLY_ANY && helping(as, ds)) || (allytype==ALLY_SELF && as->faction==ds->faction)) {
|
||||
fighter * df;
|
||||
for (df=ds->fighters; df; df=df->next) {
|
||||
int dr = get_unitrow(df, NULL);
|
||||
if (dr >= minrow && dr <= maxrow) {
|
||||
if (df->alive - df->removed > allies) {
|
||||
troop dt;
|
||||
assert(allies>=0);
|
||||
dt.index = allies;
|
||||
dt.fighter = df;
|
||||
return dt;
|
||||
}
|
||||
allies -= df->alive;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(!"we should never have gotten here");
|
||||
return no_troop;
|
||||
}
|
||||
|
||||
static void
|
||||
loot_items(fighter * corpse)
|
||||
{
|
||||
unit * u = corpse->unit;
|
||||
|
@ -2271,27 +2315,55 @@ loot_items(fighter * corpse)
|
|||
int loot = maxloot/i;
|
||||
|
||||
if (loot>0) {
|
||||
int maxrow = BEHIND_ROW;
|
||||
int lootchance = 50 + b->keeploot;
|
||||
fighter *fig = NULL;
|
||||
int looting = 0;
|
||||
int maxrow = 0;
|
||||
|
||||
if (itm->type->flags & (ITF_CURSED|ITF_NOTLOST)) maxrow = LAST_ROW;
|
||||
itm->number -= loot;
|
||||
maxloot -= loot;
|
||||
|
||||
if (maxrow == LAST_ROW || rng_int() % 100 < lootchance) {
|
||||
fighter *fig = select_enemy(corpse, FIGHT_ROW, maxrow, 0).fighter;
|
||||
if (fig) {
|
||||
item * l = fig->loot;
|
||||
while (l && l->type!=itm->type) l=l->next;
|
||||
if (!l) {
|
||||
l = calloc(sizeof(item), 1);
|
||||
l->next = fig->loot;
|
||||
fig->loot = l;
|
||||
l->type = itm->type;
|
||||
if (is_monsters(u->faction) && (loot_rules & LOOT_MONSTERS)) {
|
||||
looting = 1;
|
||||
} else if (loot_rules&LOOT_OTHERS) {
|
||||
looting = 1;
|
||||
} else if (loot_rules&LOOT_SELF) {
|
||||
looting = 2;
|
||||
}
|
||||
if (looting) {
|
||||
if (itm->type->flags & (ITF_CURSED|ITF_NOTLOST)) {
|
||||
maxrow = LAST_ROW;
|
||||
} else {
|
||||
int lootchance = 50 + b->keeploot;
|
||||
if (rng_int() % 100 < lootchance) {
|
||||
maxrow = BEHIND_ROW;
|
||||
}
|
||||
l->number += loot;
|
||||
}
|
||||
}
|
||||
if (maxrow>0) {
|
||||
if (looting==1) {
|
||||
fig = select_enemy(corpse, FIGHT_ROW, maxrow, 0).fighter;
|
||||
} else if (looting==2) {
|
||||
fig = select_ally(corpse, FIGHT_ROW, LAST_ROW, ALLY_SELF).fighter;
|
||||
} else if (itm->type->flags & (ITF_CURSED|ITF_NOTLOST)) {
|
||||
/* we absolutely, positively must have somebody loot this thing */
|
||||
fig = select_enemy(corpse, FIGHT_ROW, maxrow, 0).fighter;
|
||||
if (!fig) {
|
||||
fig = select_ally(corpse, FIGHT_ROW, LAST_ROW, ALLY_SELF).fighter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fig) {
|
||||
item * l = fig->loot;
|
||||
while (l && l->type!=itm->type) l=l->next;
|
||||
if (!l) {
|
||||
l = calloc(sizeof(item), 1);
|
||||
l->next = fig->loot;
|
||||
fig->loot = l;
|
||||
l->type = itm->type;
|
||||
}
|
||||
l->number += loot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -231,17 +231,20 @@ extern "C" {
|
|||
|
||||
extern void do_battle(struct region * r);
|
||||
|
||||
/* for combar spells and special attacks */
|
||||
/* for combat spells and special attacks */
|
||||
enum { SELECT_ADVANCE = 0x1, SELECT_DISTANCE = 0x2, SELECT_FIND = 0x4 };
|
||||
enum { ALLY_SELF, ALLY_ANY };
|
||||
|
||||
extern troop select_enemy(struct fighter * af, int minrow, int maxrow, int select);
|
||||
extern troop select_ally(struct fighter * af, int minrow, int maxrow, int allytype);
|
||||
|
||||
extern int count_enemies(struct battle * b, const struct fighter * af, int minrow, int maxrow, int select);
|
||||
extern boolean terminate(troop dt, troop at, int type, const char *damage, boolean missile);
|
||||
extern void message_all(battle * b, struct message * m);
|
||||
extern int hits(troop at, troop dt, weapon * awp);
|
||||
extern void damage_building(struct battle *b, struct building *bldg, int damage_abs);
|
||||
extern struct cvector * fighters(struct battle *b, const struct side * vs, int minrow, int maxrow, int mask);
|
||||
extern int count_allies(const struct side * as, int minrow, int maxrow, int select);
|
||||
extern int count_allies(const struct side * as, int minrow, int maxrow, int select, int allytype);
|
||||
extern int get_unitrow(const struct fighter * af, const struct side * vs);
|
||||
extern boolean helping(const struct side * as, const struct side * ds);
|
||||
extern void rmfighter(fighter *df, int i);
|
||||
|
|
|
@ -523,33 +523,36 @@ free_buildings(void)
|
|||
|
||||
extern struct attrib_type at_icastle;
|
||||
|
||||
/** returns the building's build stage (NOT size in people).
|
||||
* only makes sense for castles or similar buildings with multiple
|
||||
* stages */
|
||||
int
|
||||
buildingeffsize(const building * b, boolean img)
|
||||
{
|
||||
int i = b->size, n = 0;
|
||||
const construction * cons;
|
||||
static const struct building_type * bt_castle;
|
||||
if (!bt_castle) bt_castle = bt_find("castle");
|
||||
assert(bt_castle);
|
||||
int i = b->size, n = 0;
|
||||
const construction * cons;
|
||||
static const struct building_type * bt_castle;
|
||||
if (!bt_castle) bt_castle = bt_find("castle");
|
||||
assert(bt_castle);
|
||||
|
||||
if (b==NULL) return 0;
|
||||
if (b==NULL) return 0;
|
||||
|
||||
if (b->type!=bt_castle) {
|
||||
if (img) {
|
||||
const attrib * a = a_find(b->attribs, &at_icastle);
|
||||
if (!a || a->data.v != bt_castle) return 0;
|
||||
} else return 0;
|
||||
}
|
||||
cons = bt_castle->construction;
|
||||
assert(cons);
|
||||
if (b->type!=bt_castle) {
|
||||
if (img) {
|
||||
const attrib * a = a_find(b->attribs, &at_icastle);
|
||||
if (!a || a->data.v != bt_castle) return 0;
|
||||
} else return 0;
|
||||
}
|
||||
cons = bt_castle->construction;
|
||||
assert(cons);
|
||||
|
||||
while (cons && cons->maxsize != -1 && i>=cons->maxsize) {
|
||||
i-=cons->maxsize;
|
||||
cons = cons->improvement;
|
||||
++n;
|
||||
}
|
||||
while (cons && cons->maxsize != -1 && i>=cons->maxsize) {
|
||||
i-=cons->maxsize;
|
||||
cons = cons->improvement;
|
||||
++n;
|
||||
}
|
||||
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
const char *
|
||||
|
|
|
@ -583,7 +583,7 @@ int verbosity = 0;
|
|||
FILE *debug;
|
||||
|
||||
int
|
||||
shipspeed (const ship * sh, const unit * u)
|
||||
shipspeed(const ship * sh, const unit * u)
|
||||
{
|
||||
int k = sh->type->range;
|
||||
static const curse_type * stormwind_ct, * nodrift_ct;
|
||||
|
@ -606,9 +606,11 @@ shipspeed (const ship * sh, const unit * u)
|
|||
if( curse_active(get_curse(sh->attribs, nodrift_ct)))
|
||||
k += 1;
|
||||
|
||||
if (u->faction->race == new_race[RC_AQUARIAN]
|
||||
&& u->race == new_race[RC_AQUARIAN]) {
|
||||
k += 1;
|
||||
if (u->faction->race == u->race) {
|
||||
/* race bonus for this faction? */
|
||||
if (u->race == new_race[RC_AQUARIAN]) {
|
||||
k += 1;
|
||||
}
|
||||
}
|
||||
|
||||
a = a_find(sh->attribs, &at_speedup);
|
||||
|
@ -2098,8 +2100,6 @@ get_param_int(const struct param * p, const char * key, int def)
|
|||
return def;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
set_param(struct param ** p, const char * key, const char * data)
|
||||
{
|
||||
|
|
|
@ -198,7 +198,7 @@ static boolean
|
|||
entrance_allowed(const struct unit * u, const struct region * r)
|
||||
{
|
||||
#ifdef REGIONOWNERS
|
||||
faction * owner = get_region_owner(r);
|
||||
faction * owner = region_get_owner(r);
|
||||
if (owner == NULL || u->faction == owner) return true;
|
||||
if (alliedfaction(r->planep, owner, u->faction, HELP_TRAVEL)) return true;
|
||||
return false;
|
||||
|
|
|
@ -50,44 +50,47 @@ typedef struct att {
|
|||
int flags;
|
||||
} att;
|
||||
|
||||
struct param;
|
||||
|
||||
typedef struct race {
|
||||
const char *_name[4]; /* neu: name[4]völker */
|
||||
float magres;
|
||||
float maxaura; /* Faktor auf Maximale Aura */
|
||||
float regaura; /* Faktor auf Regeneration */
|
||||
int recruitcost;
|
||||
int maintenance;
|
||||
int splitsize;
|
||||
int weight;
|
||||
int capacity;
|
||||
float speed;
|
||||
struct param * parameters;
|
||||
const char *_name[4]; /* neu: name[4]völker */
|
||||
float magres;
|
||||
float maxaura; /* Faktor auf Maximale Aura */
|
||||
float regaura; /* Faktor auf Regeneration */
|
||||
int recruitcost;
|
||||
int maintenance;
|
||||
int splitsize;
|
||||
int weight;
|
||||
int capacity;
|
||||
float speed;
|
||||
float aggression; /* chance that a monster will attack */
|
||||
int hitpoints;
|
||||
const char *def_damage;
|
||||
char armor;
|
||||
char at_default; /* Angriffsskill Unbewaffnet (default: -2)*/
|
||||
char df_default; /* Verteidigungsskill Unbewaffnet (default: -2)*/
|
||||
char at_bonus; /* Verändert den Angriffsskill (default: 0)*/
|
||||
char df_bonus; /* Verändert den Verteidigungskill (default: 0)*/
|
||||
const spell * precombatspell;
|
||||
struct att attack[10];
|
||||
char bonus[MAXSKILLS];
|
||||
boolean __remove_me_nonplayer;
|
||||
int flags;
|
||||
int battle_flags;
|
||||
int ec_flags;
|
||||
race_t oldfamiliars[MAXMAGIETYP];
|
||||
int hitpoints;
|
||||
const char *def_damage;
|
||||
char armor;
|
||||
char at_default; /* Angriffsskill Unbewaffnet (default: -2)*/
|
||||
char df_default; /* Verteidigungsskill Unbewaffnet (default: -2)*/
|
||||
char at_bonus; /* Verändert den Angriffsskill (default: 0)*/
|
||||
char df_bonus; /* Verändert den Verteidigungskill (default: 0)*/
|
||||
const spell * precombatspell;
|
||||
struct att attack[10];
|
||||
char bonus[MAXSKILLS];
|
||||
boolean __remove_me_nonplayer;
|
||||
int flags;
|
||||
int battle_flags;
|
||||
int ec_flags;
|
||||
race_t oldfamiliars[MAXMAGIETYP];
|
||||
|
||||
const char *(*generate_name) (const struct unit *);
|
||||
const char *(*describe) (const struct unit *, const struct locale *);
|
||||
void (*age)(struct unit *u);
|
||||
boolean (*move_allowed)(const struct region *, const struct region *);
|
||||
struct item * (*itemdrop)(const struct race *, int size);
|
||||
void (*init_familiar)(struct unit *);
|
||||
const char *(*generate_name) (const struct unit *);
|
||||
const char *(*describe) (const struct unit *, const struct locale *);
|
||||
void (*age)(struct unit *u);
|
||||
boolean (*move_allowed)(const struct region *, const struct region *);
|
||||
struct item * (*itemdrop)(const struct race *, int size);
|
||||
void (*init_familiar)(struct unit *);
|
||||
|
||||
const struct race * familiars[MAXMAGIETYP];
|
||||
struct attrib * attribs;
|
||||
struct race * next;
|
||||
const struct race * familiars[MAXMAGIETYP];
|
||||
struct attrib * attribs;
|
||||
struct race * next;
|
||||
} race;
|
||||
|
||||
typedef struct race_list {
|
||||
|
|
|
@ -1326,7 +1326,7 @@ r_addmessage(struct region * r, const struct faction * viewer, struct message *
|
|||
}
|
||||
|
||||
struct faction *
|
||||
get_region_owner(const struct region * r)
|
||||
region_get_owner(const struct region * r)
|
||||
{
|
||||
if (r->land && r->land->ownership) {
|
||||
return r->land->ownership->owner;
|
||||
|
@ -1335,7 +1335,7 @@ get_region_owner(const struct region * r)
|
|||
}
|
||||
|
||||
void
|
||||
set_region_owner(struct region * r, struct faction * owner, int turn)
|
||||
region_set_owner(struct region * r, struct faction * owner, int turn)
|
||||
{
|
||||
if (r->land && r->land->ownership) {
|
||||
r->land->ownership->owner = owner;
|
||||
|
@ -1371,3 +1371,8 @@ region_getname(const region * r) {
|
|||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int region_get_morale(const region * r)
|
||||
{
|
||||
return r->land->morale;
|
||||
}
|
|
@ -79,7 +79,7 @@ typedef struct land_region {
|
|||
} * demands;
|
||||
const struct item_type * herbtype;
|
||||
short herbs;
|
||||
unsigned short morale;
|
||||
short morale;
|
||||
int trees[3]; /* 0 -> seeds, 1 -> shoots, 2 -> trees */
|
||||
int horses;
|
||||
int peasants;
|
||||
|
@ -232,8 +232,8 @@ extern const short delta_y[MAXDIRECTIONS];
|
|||
direction_t dir_invert(direction_t dir);
|
||||
int production(const struct region *r);
|
||||
|
||||
void set_region_owner(struct region * r, struct faction * owner, int turn);
|
||||
struct faction * get_region_owner(const struct region * r);
|
||||
void region_set_owner(struct region * r, struct faction * owner, int turn);
|
||||
struct faction * region_get_owner(const struct region * r);
|
||||
|
||||
struct region * r_connect(const struct region *, direction_t dir);
|
||||
#ifdef FAST_CONNECT
|
||||
|
@ -244,6 +244,8 @@ struct region * r_connect(const struct region *, direction_t dir);
|
|||
|
||||
void free_regions(void);
|
||||
|
||||
int region_get_morale(const region * r);
|
||||
|
||||
void write_region_reference(const struct region * r, struct storage * store);
|
||||
variant read_region_reference(struct storage * store);
|
||||
int resolve_region_coor(variant id, void * address);
|
||||
|
|
|
@ -588,6 +588,31 @@ write_items(struct storage * store, item *ilist)
|
|||
store->w_tok(store, "end");
|
||||
}
|
||||
|
||||
static void
|
||||
write_owner(struct storage * store, region_owner *owner)
|
||||
{
|
||||
if (owner) {
|
||||
store->w_int(store, owner->since_turn);
|
||||
write_faction_reference(owner->owner, store);
|
||||
} else {
|
||||
store->w_int(store, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
read_owner(struct storage * store, region_owner **powner)
|
||||
{
|
||||
int since_turn = store->r_int(store);
|
||||
if (since_turn>=0) {
|
||||
region_owner * owner = malloc(sizeof(region_owner));
|
||||
owner->since_turn = since_turn;
|
||||
read_reference(&owner->owner, store, read_faction_reference, resolve_faction);
|
||||
*powner = owner;
|
||||
} else {
|
||||
*powner = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
lastturn(void)
|
||||
{
|
||||
|
@ -990,6 +1015,10 @@ readregion(struct storage * store, short x, short y)
|
|||
if (store->version>=REGIONITEMS_VERSION) {
|
||||
read_items(store, &r->land->items);
|
||||
}
|
||||
if (store->version>=REGIONOWNER_VERSION) {
|
||||
r->land->morale = (short)store->r_int(store);
|
||||
read_owner(store, &r->land->ownership);
|
||||
}
|
||||
}
|
||||
a_read(store, &r->attribs);
|
||||
|
||||
|
@ -1046,6 +1075,11 @@ writeregion(struct storage * store, const region * r)
|
|||
#if RELEASE_VERSION>=REGIONITEMS_VERSION
|
||||
write_items(store, r->land->items);
|
||||
store->w_brk(store);
|
||||
#endif
|
||||
#if RELEASE_VERSION>=REGIONOWNER_VERSION
|
||||
store->w_int(store, r->land->morale);
|
||||
write_owner(store, r->land->ownership);
|
||||
store->w_brk(store);
|
||||
#endif
|
||||
}
|
||||
a_write(store, r->attribs);
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#define NOZEROIDS_VERSION 330 /* zero is not a valid ID for anything (including factions) */
|
||||
#define NOBORDERATTRIBS_VERSION 331 /* border::attribs has been moved to userdata */
|
||||
#define UIDHASH_VERSION 332 /* borders use the region.uid to store */
|
||||
#define REGIONOWNER_VERSION 333 /* regions have owners and morale */
|
||||
|
||||
#define MIN_VERSION CURSETYPE_VERSION /* minimal datafile we support */
|
||||
#define RELEASE_VERSION UIDHASH_VERSION /* current datafile */
|
||||
#define RELEASE_VERSION REGIONOWNER_VERSION /* current datafile */
|
||||
|
|
|
@ -293,7 +293,7 @@ parse_buildings(xmlDocPtr doc)
|
|||
}
|
||||
assert(propValue!=NULL);
|
||||
if (strcmp((const char*)propValue, "name")==0) {
|
||||
btype->name = (const char * (*)(const struct building_type*, int size))fun;
|
||||
btype->name = (const char * (*)(const struct building_type*, int))fun;
|
||||
} else if (strcmp((const char*)propValue, "init")==0) {
|
||||
btype->init = (void (*)(struct building_type*))fun;
|
||||
} else {
|
||||
|
@ -1487,6 +1487,28 @@ parse_spells(xmlDocPtr doc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_param(struct param ** params, xmlNodePtr node)
|
||||
{
|
||||
xmlChar * propName = xmlGetProp(node, BAD_CAST "name");
|
||||
xmlChar * propValue = xmlGetProp(node, BAD_CAST "value");
|
||||
|
||||
set_param(params, (const char*)propName, (const char*)propValue);
|
||||
|
||||
xmlFree(propName);
|
||||
xmlFree(propValue);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_ai(race * rc, xmlNodePtr node)
|
||||
{
|
||||
rc->splitsize = xml_ivalue(node, "splitsize", 0);
|
||||
rc->aggression = (float)xml_fvalue(node, "aggression", 0.04);
|
||||
if (xml_bvalue(node, "killpeasants", false)) rc->flags |= RCF_KILLPEASANTS;
|
||||
if (xml_bvalue(node, "moverandom", false)) rc->flags |= RCF_MOVERANDOM;
|
||||
if (xml_bvalue(node, "learn", false)) rc->flags |= RCF_LEARN;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_races(xmlDocPtr doc)
|
||||
{
|
||||
|
@ -1500,6 +1522,7 @@ parse_races(xmlDocPtr doc)
|
|||
nodes = races->nodesetval;
|
||||
for (i=0;i!=nodes->nodeNr;++i) {
|
||||
xmlNodePtr node = nodes->nodeTab[i];
|
||||
xmlNodePtr child;
|
||||
xmlChar * propValue;
|
||||
race * rc;
|
||||
xmlXPathObjectPtr result;
|
||||
|
@ -1573,19 +1596,13 @@ parse_races(xmlDocPtr doc)
|
|||
if (xml_bvalue(node, "resistpierce", false)) rc->battle_flags |= BF_RES_PIERCE;
|
||||
if (xml_bvalue(node, "canattack", true)) rc->battle_flags |= BF_CANATTACK;
|
||||
|
||||
/* reading eressea/races/race/ai */
|
||||
xpath->node = node;
|
||||
result = xmlXPathEvalExpression(BAD_CAST "ai", xpath);
|
||||
for (k=0;k!=result->nodesetval->nodeNr;++k) {
|
||||
xmlNodePtr node = result->nodesetval->nodeTab[k];
|
||||
|
||||
rc->splitsize = xml_ivalue(node, "splitsize", 0);
|
||||
rc->aggression = (float)xml_fvalue(node, "aggression", 0.04);
|
||||
if (xml_bvalue(node, "killpeasants", false)) rc->flags |= RCF_KILLPEASANTS;
|
||||
if (xml_bvalue(node, "moverandom", false)) rc->flags |= RCF_MOVERANDOM;
|
||||
if (xml_bvalue(node, "learn", false)) rc->flags |= RCF_LEARN;
|
||||
for (child=node->children;child;child=child->next) {
|
||||
if (strcmp((const char *)child->name, "ai")==0) {
|
||||
parse_ai(rc, child);
|
||||
} else if (strcmp((const char *)child->name, "param")==0) {
|
||||
parse_param(&rc->parameters, child);
|
||||
}
|
||||
}
|
||||
xmlXPathFreeObject(result);
|
||||
|
||||
/* reading eressea/races/race/skill */
|
||||
xpath->node = node;
|
||||
|
@ -2043,13 +2060,7 @@ parse_main(xmlDocPtr doc)
|
|||
nodes = result->nodesetval;
|
||||
for (i=0;i!=nodes->nodeNr;++i) {
|
||||
xmlNodePtr node = nodes->nodeTab[i];
|
||||
xmlChar * propName = xmlGetProp(node, BAD_CAST "name");
|
||||
xmlChar * propValue = xmlGetProp(node, BAD_CAST "value");
|
||||
|
||||
set_param(&global.parameters, (const char*)propName, (const char*)propValue);
|
||||
|
||||
xmlFree(propName);
|
||||
xmlFree(propValue);
|
||||
parse_param(&global.parameters, node);
|
||||
}
|
||||
|
||||
xmlXPathFreeObject(result);
|
||||
|
|
|
@ -61,3 +61,5 @@
|
|||
#else
|
||||
# define BINDINGS_TOLUA /* new default */
|
||||
#endif
|
||||
|
||||
#undef REGIONOWNERS /* (WIP) region-owner uses HELP_TRAVEL to control entry to region */
|
||||
|
|
|
@ -385,41 +385,6 @@ sp_sleep(fighter * fi, int level, double power, spell * sp)
|
|||
}
|
||||
|
||||
|
||||
static troop
|
||||
select_ally(fighter * af, int minrow, int maxrow)
|
||||
{
|
||||
side *as = af->side;
|
||||
battle *b = as->battle;
|
||||
side * ds;
|
||||
int allies = count_allies(as, minrow, maxrow, SELECT_ADVANCE);
|
||||
|
||||
if (!allies) {
|
||||
return no_troop;
|
||||
}
|
||||
allies = rng_int() % allies;
|
||||
|
||||
for (ds=b->sides;ds!=b->sides+b->nsides;++ds) {
|
||||
if (helping(as, ds)) {
|
||||
fighter * df;
|
||||
for (df=ds->fighters; df; df=df->next) {
|
||||
int dr = get_unitrow(df, NULL);
|
||||
if (dr >= minrow && dr <= maxrow) {
|
||||
if (df->alive - df->removed > allies) {
|
||||
troop dt;
|
||||
assert(allies>=0);
|
||||
dt.index = allies;
|
||||
dt.fighter = df;
|
||||
return dt;
|
||||
}
|
||||
allies -= df->alive;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(!"we should never have gotten here");
|
||||
return no_troop;
|
||||
}
|
||||
|
||||
int
|
||||
sp_speed(fighter * fi, int level, double power, spell * sp)
|
||||
{
|
||||
|
@ -431,13 +396,13 @@ sp_speed(fighter * fi, int level, double power, spell * sp)
|
|||
|
||||
force = lovar(power * power * 5);
|
||||
|
||||
allies = count_allies(fi->side, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
|
||||
allies = count_allies(fi->side, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE, ALLY_ANY);
|
||||
/* maximal 2*allies Versuche ein Opfer zu finden, ansonsten bestände
|
||||
* die Gefahr eine Endlosschleife*/
|
||||
allies *= 2;
|
||||
|
||||
while (force && allies) {
|
||||
troop dt = select_ally(fi, FIGHT_ROW, BEHIND_ROW);
|
||||
troop dt = select_ally(fi, FIGHT_ROW, BEHIND_ROW, ALLY_ANY);
|
||||
fighter *df = dt.fighter;
|
||||
--allies;
|
||||
|
||||
|
@ -1074,13 +1039,13 @@ sp_hero(fighter * fi, int level, double power, spell * sp)
|
|||
force = MAX(1, (int)power);
|
||||
}
|
||||
|
||||
allies = count_allies(fi->side, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
|
||||
allies = count_allies(fi->side, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE, ALLY_ANY);
|
||||
/* maximal 2*allies Versuche ein Opfer zu finden, ansonsten bestände
|
||||
* die Gefahr eine Endlosschleife*/
|
||||
allies *= 2;
|
||||
|
||||
while (force && allies) {
|
||||
troop dt = select_ally(fi, FIGHT_ROW, BEHIND_ROW);
|
||||
troop dt = select_ally(fi, FIGHT_ROW, BEHIND_ROW, ALLY_ANY);
|
||||
fighter *df = dt.fighter;
|
||||
--allies;
|
||||
|
||||
|
@ -1126,13 +1091,13 @@ sp_berserk(fighter * fi, int level, double power, spell * sp)
|
|||
force = (int)power;
|
||||
}
|
||||
|
||||
allies = count_allies(fi->side, FIGHT_ROW, BEHIND_ROW-1, SELECT_ADVANCE);
|
||||
allies = count_allies(fi->side, FIGHT_ROW, BEHIND_ROW-1, SELECT_ADVANCE, ALLY_ANY);
|
||||
/* maximal 2*allies Versuche ein Opfer zu finden, ansonsten bestände
|
||||
* die Gefahr eine Endlosschleife*/
|
||||
allies *= 2;
|
||||
|
||||
while (force && allies) {
|
||||
troop dt = select_ally(fi, FIGHT_ROW, BEHIND_ROW-1);
|
||||
troop dt = select_ally(fi, FIGHT_ROW, BEHIND_ROW-1, ALLY_ANY);
|
||||
fighter *df = dt.fighter;
|
||||
--allies;
|
||||
|
||||
|
|
|
@ -63,12 +63,12 @@ region_getterrain(const region * r) {
|
|||
|
||||
static void
|
||||
lua_region_setowner(region * r, faction * f) {
|
||||
set_region_owner(r, f, turn);
|
||||
region_set_owner(r, f, turn);
|
||||
}
|
||||
|
||||
static faction *
|
||||
lua_region_getowner(const region * r) {
|
||||
return get_region_owner(r);
|
||||
return region_get_owner(r);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -27,6 +27,8 @@ without prior permission by the authors of Eressea.
|
|||
#include <kernel/item.h>
|
||||
#include <kernel/region.h>
|
||||
|
||||
#include <gamecode/archetype.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <tolua.h>
|
||||
|
||||
|
@ -435,11 +437,43 @@ lua_useitem(struct unit * u, const struct item_type * itype, int amount, struct
|
|||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
lua_recruit(struct unit * u, const struct archetype * arch, int amount)
|
||||
{
|
||||
lua_State * L = (lua_State *)global.vm_state;
|
||||
int result = 0;
|
||||
char fname[64];
|
||||
snprintf(fname, sizeof(fname), "recruit_%s", arch->name[0]);
|
||||
|
||||
lua_pushstring(L, fname);
|
||||
lua_rawget(L, LUA_GLOBALSINDEX);
|
||||
if (lua_isfunction(L, 1)) {
|
||||
tolua_pushusertype(L, (void *)u, "unit");
|
||||
tolua_pushnumber(L, (lua_Number)amount);
|
||||
|
||||
if (lua_pcall(L, 2, 1, 0)!=0) {
|
||||
const char* error = lua_tostring(L, -1);
|
||||
log_error(("use(%s) calling '%s': %s.\n",
|
||||
unitname(u), fname, error));
|
||||
lua_pop(L, 1);
|
||||
} else {
|
||||
result = (int)lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else {
|
||||
log_error(("use(%s) calling '%s': not a function.\n",
|
||||
unitname(u), fname));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
register_tolua_helpers(void)
|
||||
{
|
||||
at_building_action.age = lc_age;
|
||||
|
||||
register_function((pf_generic)&lua_recruit, "lua_recruit");
|
||||
register_function((pf_generic)&lua_callspell, "lua_castspell");
|
||||
register_function((pf_generic)&lua_initfamiliar, "lua_initfamiliar");
|
||||
register_item_use(&lua_useitem, "lua_useitem");
|
||||
|
|
Loading…
Reference in New Issue