diff --git a/src/common/attributes/otherfaction.c b/src/common/attributes/otherfaction.c index f8cbb42b1..dd7ef4e2c 100644 --- a/src/common/attributes/otherfaction.c +++ b/src/common/attributes/otherfaction.c @@ -69,7 +69,7 @@ init_otherfaction(void) faction * visible_faction(const faction *f, const unit * u) { - if (!alliedunit(u, f, HELP_FSTEALTH)) { + if (f==NULL || !alliedunit(u, f, HELP_FSTEALTH)) { attrib *a = a_find(u->attribs, &at_otherfaction); if (a) { faction *fv = get_otherfaction(a); diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c index 60e3940ce..6d71baac8 100644 --- a/src/common/gamecode/creport.c +++ b/src/common/gamecode/creport.c @@ -773,7 +773,7 @@ cr_output_unit(FILE * F, const region * r, if (u->ship) fprintf(F, "%d;Schiff\n", u->ship->no); if (getguard(u)) - fprintf(F, "%d;bewacht\n", getguard(u)?1:0); + fprintf(F, "%d;bewacht\n", 1); if ((b=usiege(u))!=NULL) fprintf(F, "%d;belagert\n", b->no); diff --git a/src/common/gamecode/xmlreport.c b/src/common/gamecode/xmlreport.c index be1454e70..4fcacd550 100644 --- a/src/common/gamecode/xmlreport.c +++ b/src/common/gamecode/xmlreport.c @@ -21,6 +21,7 @@ #define RENDER_CRMESSAGES #define XML_ATL_NAMESPACE (const xmlChar *) "http://www.eressea.de/XML/2008/atlantis" +#define XML_XML_LANG (const xmlChar *) "lang" /* modules include */ #include @@ -62,10 +63,11 @@ #include /* util includes */ -#include -#include +#include #include +#include #include +#include #include /* libxml2 includes */ @@ -109,10 +111,22 @@ static const xmlChar * xml_i(double number) { static char buffer[128]; - sprintf(buffer, "%.0lf", number); + snprintf(buffer, sizeof(buffer), "%.0lf", number); return (const xmlChar *)buffer; } +static xmlNodePtr +xml_link(report_context * ctx, const xmlChar * rel, const xmlChar * ref) +{ + xml_context* xct = (xml_context*)ctx->userdata; + xmlNodePtr node = xmlNewNode(xct->ns_atl, BAD_CAST "link"); + + xmlNewNsProp(node, xct->ns_atl, BAD_CAST "rel", rel); + xmlNewNsProp(node, xct->ns_atl, BAD_CAST "ref", ref); + + return node; +} + static const xmlChar * xml_ref_unit(const unit * u) { @@ -129,6 +143,22 @@ xml_ref_faction(const faction * f) return (const xmlChar *)idbuf; } +static const xmlChar * +xml_ref_group(const group * g) +{ + static char idbuf[20]; + snprintf(idbuf, sizeof(idbuf), "grp_%d", g->gid); + return (const xmlChar *)idbuf; +} + +static const xmlChar * +xml_ref_prefix(const char * str) +{ + static char idbuf[20]; + snprintf(idbuf, sizeof(idbuf), "grp_%s", str); + return (const xmlChar *)idbuf; +} + static const xmlChar * xml_ref_building(const building * b) { @@ -161,14 +191,15 @@ xml_inventory(report_context * ctx, item * items, unit * u) item * itm; for (itm=items;itm;itm=itm->next) { - xmlNodePtr child = xmlNewNode(xct->ns_atl, BAD_CAST "item"); + xmlNodePtr child; const char * name; int n; + child = xmlNewNode(xct->ns_atl, BAD_CAST "item"); + xmlAddChild(node, child); report_item(u, itm, ctx->f, NULL, &name, &n, true); xmlNewNsProp(child, xct->ns_atl, BAD_CAST "type", (xmlChar *)name); xmlNodeAddContent(child, (xmlChar*)itoab(n, 10)); - xmlAddChild(node, child); } return node; } @@ -181,31 +212,162 @@ xml_unit(report_context * ctx, unit * u, int mode) static const curse_type * itemcloak_ct = 0; static boolean init = false; xmlNodePtr child; + const char * str, * rcname, * rcillusion; + boolean disclosure = (ctx->f == u->faction || omniscient(ctx->f)); xmlNewNsProp(node, xct->ns_xml, XML_XML_ID, xml_ref_unit(u)); xmlNewNsProp(node, xct->ns_atl, BAD_CAST "key", BAD_CAST itoa36(u->no)); xmlNewTextChild(node, xct->ns_atl, BAD_CAST "name", (const xmlChar *)u->name); + xmlNewTextChild(node, xct->ns_atl, BAD_CAST "number", (const xmlChar *)itoab(u->number, 10)); + /* optional description */ + str = u_description(u, ctx->f->locale); + if (str) { + child = xmlNewTextChild(node, xct->ns_atl, BAD_CAST "text", (const xmlChar *)str); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "public"); + if (str!=u->display) { + xmlNewNsProp(child, xct->ns_atl, XML_XML_LANG, BAD_CAST locale_name(ctx->f->locale)); + } + } + + /* possible info */ + if (getguard(u)) { + xmlAddChild(node, xmlNewNode(xct->ns_atl, BAD_CAST "guard")); + } + + /* siege */ + if (fval(u, UFL_SIEGE)) { + building * b = usiege(u); + if (b) { + xmlAddChild(node, xml_link(ctx, BAD_CAST "siege", xml_ref_building(b))); + } + } + + /* TODO: temp/alias */ + + /* race information */ + report_race(u, &rcname, &rcillusion); + if (disclosure) { + child = xmlNewNode(xct->ns_atl, BAD_CAST "race"); + xmlAddChild(node, child); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "true"); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (const xmlChar *)rcname); + if (rcillusion) { + child = xmlNewNode(xct->ns_atl, BAD_CAST "race"); + xmlAddChild(node, child); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "stealth"); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (const xmlChar *)rcillusion); + } + } else { + child = xmlNewNode(xct->ns_atl, BAD_CAST "race"); + xmlAddChild(node, child); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (const xmlChar *)(rcillusion?rcillusion:rcname)); + } + + /* group and prefix information. we only write the prefix if we really must */ + if (fval(u, UFL_GROUP)) { + attrib * a = a_find(u->attribs, &at_group); + if (a!=NULL) { + const group * g = (const group*)a->data.v; + if (disclosure) { + child = xmlNewNode(xct->ns_atl, BAD_CAST "group"); + xmlAddChild(node, child); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", xml_ref_group(g)); + } else { + const char * prefix = get_prefix(g->attribs); + child = xmlNewNode(xct->ns_atl, BAD_CAST "prefix"); + xmlAddChild(node, child); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", xml_ref_prefix(prefix)); + } + } + } + + if (disclosure) { + unit * mage; + + str = uprivate(u); + if (str) { + child = xmlNewTextChild(node, xct->ns_atl, BAD_CAST "text", (const xmlChar *)str); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "private"); + } + + /* familiar info */ + mage = get_familiar_mage(u); + if (mage) xmlAddChild(node, xml_link(ctx, BAD_CAST "familiar_of", xml_ref_unit(mage))); + + /* combat status */ + child = xmlNewNode(xct->ns_atl, BAD_CAST "status"); + xmlAddChild(node, child); + xmlSetNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "combat"); + xmlSetNsProp(child, xct->ns_atl, BAD_CAST "value", BAD_CAST combatstatus[u->status]); + + if (fval(u, UFL_NOAID)) { + child = xmlNewNode(xct->ns_atl, BAD_CAST "status"); + xmlAddChild(node, child); + xmlSetNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "aid"); + xmlSetNsProp(child, xct->ns_atl, BAD_CAST "value", BAD_CAST "false"); + } + + if (fval(u, UFL_STEALTH)) { + int i = u_geteffstealth(u); + if (i>=0) { + child = xmlNewNode(xct->ns_atl, BAD_CAST "status"); + xmlAddChild(node, child); + xmlSetNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "stealth"); + xmlSetNsProp(child, xct->ns_atl, BAD_CAST "value", BAD_CAST itoab(i, 10)); + } + } + if (fval(u, UFL_HERO)) { + child = xmlNewNode(xct->ns_atl, BAD_CAST "status"); + xmlAddChild(node, child); + xmlSetNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "hero"); + xmlSetNsProp(child, xct->ns_atl, BAD_CAST "value", BAD_CAST "true"); + } + + if (fval(u, UFL_HUNGER)) { + child = xmlNewNode(xct->ns_atl, BAD_CAST "status"); + xmlAddChild(node, child); + xmlSetNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "hunger"); + xmlSetNsProp(child, xct->ns_atl, BAD_CAST "value", BAD_CAST "true"); + } + + /* TODO: hitpoints, aura */ + + } + + /* faction information w/ visibiility */ child = xmlNewNode(xct->ns_atl, BAD_CAST "faction"); - if (ctx->f == u->faction || omniscient(ctx->f)) { + xmlAddChild(node, child); + if (disclosure) { xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "true"); xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", xml_ref_faction(u->faction)); + + if (fval(u, UFL_PARTEITARNUNG)) { + const faction * sf = visible_faction(NULL, u); + child = xmlNewNode(xct->ns_atl, BAD_CAST "faction"); + xmlAddChild(node, child); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "stealth"); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", xml_ref_faction(sf)); + } } else { const faction * sf = visible_faction(ctx->f, u); + if (sf==ctx->f) { + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "stealth"); + } xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", xml_ref_faction(sf)); } - xmlAddChild(node, child); - - if (!init) { - init = true; - itemcloak_ct = ct_find("itemcloak"); - } + /* the inventory */ if (u->items) { item result[MAX_INVENTORY]; item * show = NULL; - if (ctx->f == u->faction || omniscient(ctx->f)) { + if (!init) { + init = true; + itemcloak_ct = ct_find("itemcloak"); + } + + if (disclosure) { show = u->items; } else { boolean see_items = (mode >= see_unit); @@ -234,18 +396,6 @@ xml_unit(report_context * ctx, unit * u, int mode) return node; } -static xmlNodePtr -xml_link(report_context * ctx, const xmlChar * role, const xmlChar * ref) -{ - xml_context* xct = (xml_context*)ctx->userdata; - xmlNodePtr node = xmlNewNode(xct->ns_atl, BAD_CAST "link"); - - xmlNewNsProp(node, xct->ns_atl, BAD_CAST "role", role); - xmlNewNsProp(node, xct->ns_atl, BAD_CAST "ref", ref); - - return node; -} - static xmlNodePtr xml_resources(report_context * ctx, const seen_region * sr) { @@ -256,15 +406,15 @@ xml_resources(report_context * ctx, const seen_region * sr) for (n=0;n=0) { - xmlNodePtr child = xmlNewNode(xct->ns_atl, BAD_CAST "resource"); + xmlNodePtr child; + + child = xmlNewNode(xct->ns_atl, BAD_CAST "resource"); + xmlAddChild(node, child); xmlNewNsProp(child, xct->ns_atl, BAD_CAST "type", (xmlChar*)result[n].name); if (result[n].level>=0) { xmlNewNsProp(child, xct->ns_atl, BAD_CAST "level", (xmlChar*)itoab(result[n].level, 10)); } xmlNodeAddContent(child, (xmlChar*)itoab(result[n].number, 10)); - - /* TODO: the visibility logic from creport */ - xmlAddChild(node, child); } } return node; @@ -300,47 +450,70 @@ xml_building(report_context * ctx, seen_region * sr, const building * b, const u xmlNewTextChild(node, xct->ns_atl, BAD_CAST "name", (const xmlChar *)b->name); xmlNewTextChild(node, xct->ns_atl, BAD_CAST "size", (const xmlChar *)itoab(b->size, 10)); if (b->display && b->display[0]) { - xmlNewTextChild(node, xct->ns_atl, BAD_CAST "descr", (const xmlChar *)b->display); + child = xmlNewTextChild(node, xct->ns_atl, BAD_CAST "text", (const xmlChar *)b->display); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "public"); } if (b->besieged) { xmlNewTextChild(node, xct->ns_atl, BAD_CAST "siege", (const xmlChar *)itoab(b->besieged, 10)); } - if (owner) xml_link(ctx, BAD_CAST "owner", xml_ref_unit(owner)); + if (owner) xmlAddChild(node, xml_link(ctx, BAD_CAST "owner", xml_ref_unit(owner))); report_building(b, &bname, &billusion); if (owner && owner->faction==ctx->f) { child = xmlNewNode(xct->ns_atl, BAD_CAST "type"); + xmlAddChild(node, child); xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "true"); xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (const xmlChar *)bname); - xmlAddChild(node, child); if (billusion) { child = xmlNewNode(xct->ns_atl, BAD_CAST "type"); + xmlAddChild(node, child); xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "illusion"); xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (const xmlChar *)billusion); - xmlAddChild(node, child); } } else { child = xmlNewNode(xct->ns_atl, BAD_CAST "type"); - xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (const xmlChar *)(billusion?billusion:bname)); xmlAddChild(node, child); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (const xmlChar *)(billusion?billusion:bname)); } return node; } static xmlNodePtr -xml_ship(report_context * ctx, seen_region * sr, ship * sh) +xml_ship(report_context * ctx, const seen_region * sr, const ship * sh, const unit * owner) { xml_context* xct = (xml_context*)ctx->userdata; - xmlNodePtr node = xmlNewNode(xct->ns_atl, BAD_CAST "ship"); + xmlNodePtr child, node = xmlNewNode(xct->ns_atl, BAD_CAST "ship"); xmlNewNsProp(node, xct->ns_xml, XML_XML_ID, xml_ref_ship(sh)); xmlNewNsProp(node, xct->ns_atl, BAD_CAST "key", BAD_CAST itoa36(sh->no)); xmlNewTextChild(node, xct->ns_atl, BAD_CAST "name", (const xmlChar *)sh->name); - if (sh->display && sh->display[0]) { - xmlNewTextChild(node, xct->ns_atl, BAD_CAST "descr", (const xmlChar *)sh->display); + xmlNewTextChild(node, xct->ns_atl, BAD_CAST "size", (const xmlChar *)itoab(sh->size, 10)); + + if (sh->damage) { + xmlNewTextChild(node, xct->ns_atl, BAD_CAST "damage", (const xmlChar *)itoab(sh->damage, 10)); } + if (fval(sr->r->terrain, SEA_REGION) && sh->coast!=NODIRECTION) { + xmlNewTextChild(node, xct->ns_atl, BAD_CAST "coast", BAD_CAST directions[sh->coast]); + } + + child = xmlNewNode(xct->ns_atl, BAD_CAST "type"); + xmlAddChild(node, child); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (const xmlChar *)sh->type->name[0]); + + if (sh->display && sh->display[0]) { + child = xmlNewTextChild(node, xct->ns_atl, BAD_CAST "text", (const xmlChar *)sh->display); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "public"); + } + + if (owner) xmlAddChild(node, xml_link(ctx, BAD_CAST "owner", xml_ref_unit(owner))); + + if ((owner && owner->faction == ctx->f) || omniscient(ctx->f)) { + int n = 0, p = 0; + getshipweight(sh, &n, &p); + xmlNewTextChild(node, xct->ns_atl, BAD_CAST "cargo", (const xmlChar *)itoab(n, 10)); + } return node; } @@ -359,16 +532,16 @@ xml_region(report_context * ctx, seen_region * sr) xmlNewNsProp(node, xct->ns_xml, XML_XML_ID, xml_ref_region(r)); child = xmlNewNode(xct->ns_atl, BAD_CAST "coordinate"); + xmlAddChild(node, child); xmlNewNsProp(child, xct->ns_atl, BAD_CAST "x", xml_i(region_x(r, ctx->f))); xmlNewNsProp(child, xct->ns_atl, BAD_CAST "y", xml_i(region_y(r, ctx->f))); if (r->planep) { xmlNewNsProp(child, xct->ns_atl, BAD_CAST "plane", xml_s(r->planep->name)); } - xmlAddChild(node, child); child = xmlNewNode(xct->ns_atl, BAD_CAST "terrain"); - xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (xmlChar *)terrain_name(r)); xmlAddChild(node, child); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (xmlChar *)terrain_name(r)); if (r->land!=NULL) { child = xmlNewTextChild(node, xct->ns_atl, BAD_CAST "name", (const xmlChar *)r->land->name); @@ -376,6 +549,10 @@ xml_region(report_context * ctx, seen_region * sr) xmlAddChild(node, xml_inventory(ctx, r->land->items, NULL)); } } + if (r->display && r->display[0]) { + child = xmlNewTextChild(node, xct->ns_atl, BAD_CAST "text", (const xmlChar *)r->display); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "public"); + } xmlAddChild(node, xml_resources(ctx, sr)); child = xmlNewNode(xct->ns_atl, BAD_CAST "terrain"); @@ -391,13 +568,11 @@ xml_region(report_context * ctx, seen_region * sr) u = r->units; while (b) { while (b && (!u || u->building!=b)) { - child = xml_building(ctx, sr, b, NULL); - xmlAddChild(node, child); + xmlAddChild(node, xml_building(ctx, sr, b, NULL)); b = b->next; } if (b) { - child = xml_building(ctx, sr, b, u); - xmlAddChild(node, child); + xmlAddChild(node, xml_building(ctx, sr, b, u)); while (u && u->building==b) { xmlAddChild(child, xml_unit(ctx, u, sr->mode)); u = u->next; @@ -415,13 +590,11 @@ xml_region(report_context * ctx, seen_region * sr) } while (sh) { while (sh && (!u || u->ship!=sh)) { - child = xml_ship(ctx, sr, sh); - xmlAddChild(node, child); + xmlAddChild(node, xml_ship(ctx, sr, sh, NULL)); sh = sh->next; } if (sh) { - child = xml_ship(ctx, sr, sh); - xmlAddChild(node, child); + xmlAddChild(node, xml_ship(ctx, sr, sh, u)); while (u && u->ship==sh) { xmlAddChild(child, xml_unit(ctx, u, sr->mode)); u = u->next; diff --git a/src/common/kernel/reports.c b/src/common/kernel/reports.c index cae29161c..61ec7397a 100644 --- a/src/common/kernel/reports.c +++ b/src/common/kernel/reports.c @@ -112,22 +112,24 @@ groupid(const struct group * g, const struct faction * f) return buf; } +const char * combatstatus[] = { + "status_aggressive", "status_front", + "status_rear", "status_defensive", + "status_avoid", "status_flee" +}; + const char * report_kampfstatus(const unit * u, const struct locale * lang) { - static char fsbuf[64]; - static const char * azstatus[] = { - "status_aggressive", "status_front", - "status_rear", "status_defensive", - "status_avoid", "status_flee" }; + static char fsbuf[64]; - strlcpy(fsbuf, LOC(lang, azstatus[u->status]), sizeof(fsbuf)); - if (fval(u, UFL_NOAID)) { - strcat(fsbuf, ", "); - strcat(fsbuf, LOC(lang, "status_noaid")); - } + strlcpy(fsbuf, LOC(lang, combatstatus[u->status]), sizeof(fsbuf)); + if (fval(u, UFL_NOAID)) { + strcat(fsbuf, ", "); + strcat(fsbuf, LOC(lang, "status_noaid")); + } - return fsbuf; + return fsbuf; } const char * @@ -295,6 +297,26 @@ report_resource(resource_report * result, const char * name, int number, int lev result->level = level; } +void +report_race(const struct unit * u, const char ** name, const char ** illusion) +{ + if (illusion) { + if (u->irace && u->irace!=u->race) { + *illusion = u->irace->_name[0]; + } + else { + *illusion = NULL; + } + } + if (name) { + *name = u->race->_name[0]; + if (fval(u->race, RCF_SHAPESHIFTANY)) { + const char * str = get_racename(u->attribs); + if (str) *name = str; + } + } +} + void report_building(const struct building * b, const char ** name, const char ** illusion) { diff --git a/src/common/kernel/reports.h b/src/common/kernel/reports.h index 6f999665d..433e40043 100644 --- a/src/common/kernel/reports.h +++ b/src/common/kernel/reports.h @@ -124,9 +124,11 @@ extern const char * report_kampfstatus(const struct unit * u, const struct local int report_items(const struct item * items, struct item * result, int size, const struct unit * owner, const struct faction * viewer); void report_item(const struct unit * owner, const struct item * i, const struct faction * viewer, const char ** name, const char ** basename, int * number, boolean singular); void report_building(const struct building * b, const char ** btype, const char ** billusion); + void report_race(const struct unit * u, const char ** rcname, const char ** rcillusion); extern size_t f_regionid(const struct region * r, const struct faction * f, char * buffer, size_t size); + extern const char * combatstatus[]; #define GR_PLURAL 0x01 /* grammar: plural */ #define MAX_INVENTORY 64 /* maimum number of different items in an inventory */ #define MAX_RAWMATERIALS 8 /* maximum kinds of raw materials in a regions */ diff --git a/src/scripts/run-tests.lua b/src/scripts/run-tests.lua index 123a35e77..2766798a8 100644 --- a/src/scripts/run-tests.lua +++ b/src/scripts/run-tests.lua @@ -124,9 +124,14 @@ end function test_xml() read_game("572.dat", "binary") + init_reports() + f = get_faction(atoi36("ioen")) f.options = f.options + 8192 - init_reports() + write_report(f) + + f = get_faction(atoi36("777")) + f.options = f.options + 8192 write_report(f) end