create a spellref structure.

use this when referring to spells that may not (yet) exist.
use it for race::precombatspell (rare use case).
This commit is contained in:
Enno Rehling 2017-01-28 19:42:20 +01:00
parent 0913336ef8
commit 6d15767a18
8 changed files with 78 additions and 6 deletions

2
clibs

@ -1 +1 @@
Subproject commit 27c8b3202b52766465743c3324fc0b52c5ba4b11
Subproject commit f91ef37f08c5244bf616f1836c0aa9caaf36805c

View file

@ -32,6 +32,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "region.h"
#include "ship.h"
#include "skill.h"
#include "spell.h"
#include "terrain.h"
#include "unit.h"
@ -182,6 +183,7 @@ void racelist_insert(struct race_list **rl, const struct race *r)
void free_races(void) {
while (races) {
race * rc = races->next;
spellref_free(races->precombatspell);
free_params(&races->parameters);
free(xrefs);
xrefs = 0;

View file

@ -45,6 +45,7 @@ extern "C" {
struct param;
struct spell;
struct spellref;
struct locale;
extern int num_races;
@ -137,7 +138,7 @@ extern "C" {
int at_bonus; /* Ver<65>ndert den Angriffsskill (default: 0) */
int df_bonus; /* Ver<65>ndert den Verteidigungskill (default: 0) */
struct param *parameters; // additional properties, for an example see natural_armor
const struct spell *precombatspell;
struct spellref *precombatspell;
signed char *study_speed; /* study-speed-bonus in points/turn (0=30 Tage) */
int flags;
int battle_flags;

View file

@ -145,3 +145,32 @@ spell *find_spellbyid(unsigned int id)
log_warning("cannot find spell by id: %u\n", id);
return NULL;
}
struct spellref *spellref_create(const char *name)
{
spellref *spref = malloc(sizeof(spellref));
spref->name = strdup(name);
spref->sp = NULL;
return spref;
}
void spellref_free(spellref *spref)
{
if (spref) {
free(spref->name);
free(spref);
}
}
struct spell *spellref_get(struct spellref *spref)
{
if (!spref->sp) {
spref->sp = find_spell(spref->name);
if (spref->sp) {
free(spref->name);
spref->name = NULL;
}
}
return spref->sp;
}

View file

@ -45,6 +45,15 @@ extern "C" {
fumble_f fumble;
} spell;
typedef struct spellref {
char * name;
struct spell *sp;
} spellref;
struct spellref *spellref_create(const char *name);
void spellref_free(struct spellref *spref);
struct spell *spellref_get(struct spellref *spref);
int sp_antimagiczone(struct castorder *co);
struct spell * create_spell(const char * name, unsigned int id);

View file

@ -69,9 +69,26 @@ static void test_create_spell_with_id(CuTest * tc)
test_cleanup();
}
static void test_spellref(CuTest *tc)
{
spellref *ref;
spell *sp;
test_setup();
ref = spellref_create("hodor");
CuAssertPtrNotNull(tc, ref);
CuAssertPtrEquals(tc, NULL, spellref_get(ref));
sp = create_spell("hodor", 0);
CuAssertPtrNotNull(tc, sp);
CuAssertPtrEquals(tc, sp, spellref_get(ref));
CuAssertPtrEquals(tc, NULL, ref->name);
spellref_free(ref);
test_cleanup();
}
CuSuite *get_spell_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_spellref);
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);

View file

@ -87,6 +87,17 @@ static const spell *xml_spell(xmlNode * node, const char *name)
return sp;
}
static spellref *xml_spellref(xmlNode * node, const char *name)
{
xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
if (propValue != NULL) {
spellref *ref = spellref_create((const char *)propValue);
xmlFree(propValue);
return ref;
}
return NULL;
}
static xmlChar *xml_cleanup_string(xmlChar * str)
{
xmlChar *read = str;
@ -1853,7 +1864,7 @@ static int parse_races(xmlDocPtr doc)
|| !"precombatspell is already initialized");
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k];
rc->precombatspell = xml_spell(node, "spell");
rc->precombatspell = xml_spellref(node, "spell");
}
xmlXPathFreeObject(result);
@ -2076,10 +2087,10 @@ void register_xmlreader(void)
xml_register_callback(parse_buildings); /* requires resources */
xml_register_callback(parse_ships); /* requires terrains */
xml_register_callback(parse_races); /* requires spells */
xml_register_callback(parse_spells); /* requires resources */
xml_register_callback(parse_spellbooks); /* requires spells */
xml_register_callback(parse_equipment); /* requires spells */
xml_register_callback(parse_races); /* requires spells */
xml_register_callback(parse_calendar);
}
#endif

View file

@ -560,8 +560,11 @@ const spell *get_combatspell(const unit * u, int nr)
if (m) {
return m->combatspells[nr].sp;
}
else if (u_race(u)->precombatspell != NULL) {
return u_race(u)->precombatspell;
else {
const race * rc = u_race(u);
if (rc->precombatspell) {
return spellref_get(rc->precombatspell);
}
}
return NULL;