forked from github/server
create a callback mechanism for equipment.
This commit is contained in:
parent
5c26155f2f
commit
7e6688552b
|
@ -399,7 +399,7 @@ static int tolua_equipunit(lua_State * L)
|
|||
const char *eqname = tolua_tostring(L, 2, 0);
|
||||
int mask = (int)tolua_tonumber(L, 3, EQUIP_ALL);
|
||||
assert(u && mask > 0);
|
||||
equip_unit_mask(u, get_equipment(eqname), mask);
|
||||
equip_unit_mask(u, eqname, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -263,7 +263,7 @@ void add_recruits(unit * u, int number, int wanted)
|
|||
|
||||
len = snprintf(equipment, sizeof(equipment), "new_%s", u_race(u)->_name);
|
||||
if (len > 0 && (size_t)len < sizeof(equipment)) {
|
||||
equip_unit(unew, get_equipment(equipment));
|
||||
equip_unit(unew, equipment);
|
||||
}
|
||||
if (unew != u) {
|
||||
transfermen(unew, u, unew->number);
|
||||
|
|
|
@ -19,6 +19,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#ifndef H_KRNL_CALLBACKS_H
|
||||
#define H_KRNL_CALLBACKS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -31,6 +33,7 @@ extern "C" {
|
|||
struct resource_type;
|
||||
|
||||
struct callback_struct {
|
||||
bool (*equip_unit)(struct unit *u, const char *eqname, int mask);
|
||||
int (*cast_spell)(struct castorder *co, const char *fname);
|
||||
int (*use_item)(struct unit *u, const struct item_type *itype,
|
||||
int amount, struct order *ord);
|
||||
|
|
|
@ -21,11 +21,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "equipment.h"
|
||||
|
||||
/* kernel includes */
|
||||
#include "item.h"
|
||||
#include "unit.h"
|
||||
#include "callbacks.h"
|
||||
#include "faction.h"
|
||||
#include "item.h"
|
||||
#include "race.h"
|
||||
#include "spell.h"
|
||||
#include "unit.h"
|
||||
|
||||
/* util includes */
|
||||
#include <selist.h>
|
||||
|
@ -88,80 +89,90 @@ equipment_setitem(equipment * eq, const item_type * itype, const char *value)
|
|||
}
|
||||
|
||||
void
|
||||
equipment_setcallback(struct equipment *eq,
|
||||
void(*callback) (const struct equipment *, struct unit *))
|
||||
equipment_setcallback(struct equipment *eq, equip_callback_fun callback)
|
||||
{
|
||||
eq->callback = callback;
|
||||
}
|
||||
|
||||
void equip_unit(struct unit *u, const struct equipment *eq)
|
||||
bool equip_unit(struct unit *u, const char *eqname)
|
||||
{
|
||||
equip_unit_mask(u, eq, EQUIP_ALL);
|
||||
return equip_unit_mask(u, eqname, EQUIP_ALL);
|
||||
}
|
||||
|
||||
void equip_unit_mask(struct unit *u, const struct equipment *eq, int mask)
|
||||
bool equip_unit_mask(struct unit *u, const char *eqname, int mask)
|
||||
{
|
||||
const equipment * eq = get_equipment(eqname);
|
||||
if (eq) {
|
||||
equip_unit_set(u, eq, mask);
|
||||
return true;
|
||||
}
|
||||
if (callbacks.equip_unit) {
|
||||
return callbacks.equip_unit(u, eqname, mask);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mask & EQUIP_SKILLS) {
|
||||
int sk;
|
||||
for (sk = 0; sk != MAXSKILLS; ++sk) {
|
||||
if (eq->skills[sk] != NULL) {
|
||||
int i = dice_rand(eq->skills[sk]);
|
||||
if (i > 0) {
|
||||
set_level(u, (skill_t)sk, i);
|
||||
if (sk == SK_STAMINA) {
|
||||
u->hp = unit_max_hp(u) * u->number;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & EQUIP_SPELLS) {
|
||||
if (eq->spells) {
|
||||
selist * ql = eq->spells;
|
||||
int qi;
|
||||
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);
|
||||
spell *sp = spellref_get(sbe->spref);
|
||||
unit_add_spell(u, mage, sp, sbe->level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & EQUIP_ITEMS) {
|
||||
itemdata *idata;
|
||||
for (idata = eq->items; idata != NULL; idata = idata->next) {
|
||||
int i = u->number * dice_rand(idata->value);
|
||||
void equip_unit_set(struct unit *u, const equipment *eq, int mask)
|
||||
{
|
||||
if (mask & EQUIP_SKILLS) {
|
||||
int sk;
|
||||
for (sk = 0; sk != MAXSKILLS; ++sk) {
|
||||
if (eq->skills[sk] != NULL) {
|
||||
int i = dice_rand(eq->skills[sk]);
|
||||
if (i > 0) {
|
||||
i_add(&u->items, i_new(idata->itype, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eq->subsets) {
|
||||
int i;
|
||||
for (i = 0; eq->subsets[i].sets; ++i) {
|
||||
if (chance(eq->subsets[i].chance)) {
|
||||
double rnd = (1 + rng_int() % 1000) / 1000.0;
|
||||
int k;
|
||||
for (k = 0; eq->subsets[i].sets[k].set; ++k) {
|
||||
if (rnd <= eq->subsets[i].sets[k].chance) {
|
||||
equip_unit_mask(u, eq->subsets[i].sets[k].set, mask);
|
||||
break;
|
||||
}
|
||||
rnd -= eq->subsets[i].sets[k].chance;
|
||||
set_level(u, (skill_t)sk, i);
|
||||
if (sk == SK_STAMINA) {
|
||||
u->hp = unit_max_hp(u) * u->number;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & EQUIP_SPECIAL) {
|
||||
if (eq->callback)
|
||||
eq->callback(eq, u);
|
||||
if (mask & EQUIP_SPELLS) {
|
||||
if (eq->spells) {
|
||||
selist * ql = eq->spells;
|
||||
int qi;
|
||||
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);
|
||||
spell *sp = spellref_get(sbe->spref);
|
||||
unit_add_spell(u, mage, sp, sbe->level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eq->items && mask & EQUIP_ITEMS) {
|
||||
itemdata *idata;
|
||||
for (idata = eq->items; idata != NULL; idata = idata->next) {
|
||||
int i = u->number * dice_rand(idata->value);
|
||||
if (i > 0) {
|
||||
i_add(&u->items, i_new(idata->itype, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eq->subsets) {
|
||||
int i;
|
||||
for (i = 0; eq->subsets[i].sets; ++i) {
|
||||
if (chance(eq->subsets[i].chance)) {
|
||||
double rnd = (1 + rng_int() % 1000) / 1000.0;
|
||||
int k;
|
||||
for (k = 0; eq->subsets[i].sets[k].set; ++k) {
|
||||
if (rnd <= eq->subsets[i].sets[k].chance) {
|
||||
equip_unit_set(u, eq->subsets[i].sets[k].set, mask);
|
||||
break;
|
||||
}
|
||||
rnd -= eq->subsets[i].sets[k].chance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & EQUIP_SPECIAL) {
|
||||
if (eq->callback) {
|
||||
eq->callback(eq, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
#include "skill.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -44,12 +46,14 @@ extern "C" {
|
|||
subsetitem *sets;
|
||||
} subset;
|
||||
|
||||
typedef void(*equip_callback_fun) (const struct equipment *, struct unit *);
|
||||
|
||||
typedef struct equipment {
|
||||
struct itemdata *items;
|
||||
char *skills[MAXSKILLS];
|
||||
struct selist *spells;
|
||||
struct subset *subsets;
|
||||
void(*callback) (const struct equipment *, struct unit *);
|
||||
equip_callback_fun callback;
|
||||
} equipment;
|
||||
|
||||
void equipment_done(void);
|
||||
|
@ -64,18 +68,17 @@ extern "C" {
|
|||
void equipment_setskill(struct equipment *eq, skill_t sk,
|
||||
const char *value);
|
||||
void equipment_addspell(struct equipment *eq, const char *name, int level);
|
||||
void equipment_setcallback(struct equipment *eq,
|
||||
void(*callback) (const struct equipment *, struct unit *));
|
||||
void equipment_setcallback(struct equipment *eq, equip_callback_fun callback);
|
||||
|
||||
void equip_unit(struct unit *u, const struct equipment *eq);
|
||||
#define EQUIP_SKILLS (1<<1)
|
||||
#define EQUIP_SPELLS (1<<2)
|
||||
#define EQUIP_ITEMS (1<<3)
|
||||
#define EQUIP_SPECIAL (1<<4)
|
||||
#define EQUIP_ALL (0xFF)
|
||||
void equip_unit_mask(struct unit *u, const struct equipment *eq,
|
||||
int mask);
|
||||
void equip_items(struct item **items, const struct equipment *eq);
|
||||
void equip_unit_set(struct unit *u, const struct equipment *eq, int mask);
|
||||
bool equip_unit_mask(struct unit *u, const char *eqname, int mask);
|
||||
bool equip_unit(struct unit *u, const char *eqname);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "magic.h"
|
||||
|
||||
#include <kernel/callbacks.h>
|
||||
#include <kernel/equipment.h>
|
||||
#include <kernel/item.h>
|
||||
#include <kernel/unit.h>
|
||||
|
@ -35,7 +36,7 @@ static void test_equipment(CuTest * tc)
|
|||
equipment_addspell(eq, sp->sname, 1);
|
||||
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||
equip_unit_mask(u, eq, EQUIP_ALL);
|
||||
equip_unit_set(u, eq, EQUIP_ALL);
|
||||
CuAssertIntEquals(tc, 1, i_get(u->items, it_horses));
|
||||
CuAssertIntEquals(tc, 5, get_level(u, SK_MAGIC));
|
||||
|
||||
|
@ -69,10 +70,35 @@ static void test_get_equipment(CuTest * tc)
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static bool equip_test(unit *u, const char *name, int mask) {
|
||||
if (mask & EQUIP_ITEMS) {
|
||||
i_change(&u->items, it_find("horse"), 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void test_equipment_callback(CuTest *tc) {
|
||||
unit *u;
|
||||
item_type *itype;
|
||||
test_setup();
|
||||
itype = test_create_horse();
|
||||
u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
|
||||
CuAssertTrue(tc, !equip_unit_mask(u, "horse", EQUIP_ITEMS));
|
||||
CuAssertPtrEquals(tc, NULL, u->items);
|
||||
callbacks.equip_unit = equip_test;
|
||||
CuAssertTrue(tc, equip_unit(u, "horse"));
|
||||
CuAssertIntEquals(tc, 1, i_get(u->items, itype));
|
||||
CuAssertTrue(tc, !equip_unit_mask(u, "horse", EQUIP_SPELLS));
|
||||
CuAssertIntEquals(tc, 1, i_get(u->items, itype));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
CuSuite *get_equipment_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_equipment);
|
||||
SUITE_ADD_TEST(suite, test_get_equipment);
|
||||
SUITE_ADD_TEST(suite, test_equipment_callback);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -1349,7 +1349,7 @@ static void fix_familiars(void) {
|
|||
log_error("%s seems to be a familiar with no spells.",
|
||||
unitname(u));
|
||||
/* magical familiar, no spells */
|
||||
equip_unit_mask(u, eq, EQUIP_SPELLS);
|
||||
equip_unit_set(u, eq, EQUIP_SPELLS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2181,18 +2181,13 @@ void remove_familiar(unit * mage)
|
|||
void create_newfamiliar(unit * mage, unit * fam)
|
||||
{
|
||||
/* skills and spells: */
|
||||
const struct equipment *eq;
|
||||
char eqname[64];
|
||||
const race *rc = u_race(fam);
|
||||
|
||||
set_familiar(mage, fam);
|
||||
|
||||
snprintf(eqname, sizeof(eqname), "fam_%s", rc->_name);
|
||||
eq = get_equipment(eqname);
|
||||
if (eq != NULL) {
|
||||
equip_unit(fam, eq);
|
||||
}
|
||||
else {
|
||||
if (!equip_unit(fam, eqname)) {
|
||||
log_info("could not perform initialization for familiar %s.\n", rc->_name);
|
||||
}
|
||||
/* TODO: Diese Attribute beim Tod des Familiars entfernen: */
|
||||
|
|
|
@ -612,7 +612,7 @@ static void recruit_dracoids(unit * dragon, int size)
|
|||
|
||||
name_unit(un);
|
||||
change_money(dragon, -un->number * 50);
|
||||
equip_unit(un, get_equipment("new_dracoid"));
|
||||
equip_unit(un, "new_dracoid");
|
||||
|
||||
unit_setstatus(un, ST_FIGHT);
|
||||
for (weapon = un->items; weapon; weapon = weapon->next) {
|
||||
|
@ -864,7 +864,7 @@ static int nrand(int start, int sub)
|
|||
unit *spawn_seaserpent(region *r, faction *f) {
|
||||
unit *u = create_unit(r, f, 1, get_race(RC_SEASERPENT), 0, NULL, NULL);
|
||||
fset(u, UFL_ISNEW | UFL_MOVED);
|
||||
equip_unit(u, get_equipment("seed_seaserpent"));
|
||||
equip_unit(u, "seed_seaserpent");
|
||||
return u;
|
||||
}
|
||||
|
||||
|
@ -903,7 +903,7 @@ void spawn_dragons(void)
|
|||
u = create_unit(r, monsters, nrand(30, 20) + 1, get_race(RC_DRAGON), 0, NULL, NULL);
|
||||
}
|
||||
fset(u, UFL_ISNEW | UFL_MOVED);
|
||||
equip_unit(u, get_equipment("seed_dragon"));
|
||||
equip_unit(u, "seed_dragon");
|
||||
|
||||
log_debug("spawning %d %s in %s.\n", u->number,
|
||||
LOC(default_locale,
|
||||
|
@ -965,7 +965,7 @@ void spawn_undead(void)
|
|||
fset(u, UFL_ISNEW | UFL_MOVED);
|
||||
if ((rc == get_race(RC_SKELETON) || rc == get_race(RC_ZOMBIE))
|
||||
&& rng_int() % 10 < 4) {
|
||||
equip_unit(u, get_equipment("rising_undead"));
|
||||
equip_unit(u, "rising_undead");
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXSKILLS; i++) {
|
||||
|
|
|
@ -265,7 +265,7 @@ static void get_villagers(region * r, unit * u)
|
|||
u);
|
||||
leave(newunit, true);
|
||||
fset(newunit, UFL_ISNEW | UFL_MOVED);
|
||||
equip_unit(newunit, get_equipment("rand_villagers"));
|
||||
equip_unit(newunit, "rand_villagers");
|
||||
}
|
||||
|
||||
static void get_allies(region * r, unit * u)
|
||||
|
@ -352,7 +352,7 @@ static void get_allies(region * r, unit * u)
|
|||
newunit =
|
||||
create_unit(r, u->faction, number, u->faction->race, 0,
|
||||
LOC(u->faction->locale, name), u);
|
||||
equip_unit(newunit, get_equipment(equip));
|
||||
equip_unit(newunit, equip);
|
||||
|
||||
u_setfaction(newunit, u->faction);
|
||||
set_racename(&newunit->attribs, get_racename(u->attribs));
|
||||
|
|
|
@ -181,7 +181,7 @@ void spawn_braineaters(float chance)
|
|||
if (next-- == 0) {
|
||||
u = create_unit(r, f, 1 + rng_int() % 10 + rng_int() % 10,
|
||||
rc_brain, 0, NULL, NULL);
|
||||
equip_unit(u, get_equipment("seed_braineater"));
|
||||
equip_unit(u, "seed_braineater");
|
||||
|
||||
next = rng_int() % (int)(chance * 100);
|
||||
}
|
||||
|
|
|
@ -875,8 +875,7 @@ static void add_callbacks(equipment * eq, xmlNodeSetPtr nsetItems)
|
|||
if (propValue != NULL) {
|
||||
fun = get_function((const char *)propValue);
|
||||
if (fun) {
|
||||
equipment_setcallback(eq, (void(*)(const struct equipment *,
|
||||
struct unit *))fun);
|
||||
equipment_setcallback(eq, (equip_callback_fun)fun);
|
||||
}
|
||||
xmlFree(propValue);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue