diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index 0f5642c42..b4ce122c5 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -597,9 +597,6 @@ static void json_spells(cJSON *json) { else if (strcmp(item->string, "cast") == 0) { sp->cast = (spell_f)get_function(item->valuestring); } - else if (strcmp(item->string, "fumble") == 0) { - sp->fumble = (fumble_f)get_function(item->valuestring); - } else if (strcmp(item->string, "syntax") == 0) { sp->syntax = strdup(item->valuestring); } diff --git a/src/kernel/spell.c b/src/kernel/spell.c index 212b0a7d2..900f98ff0 100644 --- a/src/kernel/spell.c +++ b/src/kernel/spell.c @@ -33,6 +33,28 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +static critbit_tree cb_fumbles; +void add_fumble(const char *sname, fumble_f fun) +{ + size_t len; + char data[64]; + + len = cb_new_kv(sname, strlen(sname), &fun, sizeof(fun), data); + assert(len <= sizeof(data)); + cb_insert(&cb_fumbles, data, len); +} + +fumble_f get_fumble(const char *sname) +{ + void * match; + fumble_f result = NULL; + + if (cb_find_prefix(&cb_fumbles, sname, strlen(sname) + 1, &match, 1, 0)) { + cb_get_kv(match, &result, sizeof(result)); + } + return result; +} + static critbit_tree cb_spells; selist * spells; @@ -49,6 +71,7 @@ static void free_spell_cb(void *cbdata) { } void free_spells(void) { + cb_clear(&cb_fumbles); cb_clear(&cb_spells); selist_foreach(spells, free_spell_cb); selist_free(spells); diff --git a/src/kernel/spell.h b/src/kernel/spell.h index e7592f082..ae5322c9a 100644 --- a/src/kernel/spell.h +++ b/src/kernel/spell.h @@ -42,7 +42,6 @@ extern "C" { int rank; /* Reihenfolge der Zauber */ struct spell_component *components; spell_f cast; - fumble_f fumble; } spell; typedef struct spellref { @@ -50,6 +49,9 @@ extern "C" { struct spell *sp; } spellref; + void add_fumble(const char *sname, fumble_f fun); + fumble_f get_fumble(const char *sname); + struct spellref *spellref_create(struct spell *sp, const char *name); void spellref_free(struct spellref *spref); struct spell *spellref_get(struct spellref *spref); diff --git a/src/kernel/spell.test.c b/src/kernel/spell.test.c index b500f94cc..739be35da 100644 --- a/src/kernel/spell.test.c +++ b/src/kernel/spell.test.c @@ -86,10 +86,25 @@ static void test_spellref(CuTest *tc) test_cleanup(); } +void my_fumble(const struct castorder *co) { + UNUSED_ARG(co); +} + +static void test_fumbles(CuTest *tc) +{ + test_setup(); + CuAssertTrue(tc, NULL==get_fumble("hodor")); + add_fumble("hodor", my_fumble); + CuAssertTrue(tc, my_fumble==get_fumble("hodor")); + test_cleanup(); + CuAssertTrue(tc, NULL==get_fumble("hodor")); +} + CuSuite *get_spell_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_spellref); + SUITE_ADD_TEST(suite, test_fumbles); SUITE_ADD_TEST(suite, test_create_a_spell); SUITE_ADD_TEST(suite, test_create_duplicate_spell); SUITE_ADD_TEST(suite, test_create_spell_with_id); diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index e29f2811c..f9e62dc43 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -1312,11 +1312,8 @@ static int parse_spellbooks(xmlDocPtr doc) static int parse_spells(xmlDocPtr doc) { pf_generic cast = 0; - pf_generic fumble = 0; xmlXPathContextPtr xpath = xmlXPathNewContext(doc); xmlXPathObjectPtr spells; - char zText[32]; - strcpy(zText, "fumble_"); /* reading eressea/spells/spell */ spells = xmlXPathEvalExpression(BAD_CAST "/eressea/spells/spell", xpath); @@ -1404,8 +1401,6 @@ static int parse_spells(xmlDocPtr doc) if (!cast) { log_error("no spell cast function registered for '%s'\n", sp->sname); } - strlcpy(zText + 7, sp->sname, sizeof(zText) - 7); - fumble = get_function(zText); } else { for (k = 0; k != result->nodesetval->nodeNr; ++k) { @@ -1422,9 +1417,6 @@ static int parse_spells(xmlDocPtr doc) log_error("unknown function name '%s' for spell '%s'\n", (const char *)propValue, sp->sname); } } - else if (fun && strcmp((const char *)propValue, "fumble") == 0) { - fumble = fun; - } else { log_error("unknown function type '%s' for spell '%s'\n", (const char *)propValue, sp->sname); } @@ -1432,7 +1424,6 @@ static int parse_spells(xmlDocPtr doc) } } sp->cast = (spell_f)cast; - sp->fumble = (fumble_f)fumble; xmlXPathFreeObject(result); /* reading eressea/spells/spell/resource */ diff --git a/src/magic.c b/src/magic.c index 005f0ff94..5a6672db5 100644 --- a/src/magic.c +++ b/src/magic.c @@ -1370,14 +1370,16 @@ static void do_fumble(castorder * co) double effect; static const race *rc_toad; static int rc_cache; + fumble_f fun; ADDMSG(&u->faction->msgs, msg_message("patzer", "unit region spell", u, r, sp)); switch (rng_int() % 10) { case 0: /* wenn vorhanden spezieller Patzer, ansonsten nix */ - if (sp->fumble) { - sp->fumble(co); + fun = get_fumble(sp->sname); + if (fun) { + fun(co); } else { fumble_default(co); diff --git a/src/spells.c b/src/spells.c index 10815708d..8bf30de88 100644 --- a/src/spells.c +++ b/src/spells.c @@ -6622,8 +6622,7 @@ static void register_spelldata(void) register_function((pf_generic)data->cast, data->sname); } if (data->fumble) { - strlcpy(zText + 7, data->sname, sizeof(zText) - 7); - register_function((pf_generic)data->fumble, zText); + add_fumble(data->sname, data->fumble); } } }