diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c index 3f7ea48f7..b37a27c8b 100644 --- a/src/common/gamecode/economy.c +++ b/src/common/gamecode/economy.c @@ -1195,7 +1195,7 @@ can_guard(const unit * guard, const unit * u) { if (fval(guard, UFL_ISNEW)) return false; if (guard->number<=0 || !cansee(guard->faction, guard->region, u, 0)) return false; - if (besieged(guard) || !armedmen(guard)) return false; + if (besieged(guard) || !(fval(guard->race, RCF_UNARMEDGUARD) || armedmen(guard))) return false; return !alliedunit(guard, u->faction, HELP_GUARD); } @@ -1208,92 +1208,91 @@ enum { static void allocate_resource(unit * u, const resource_type * rtype, int want) { - const item_type * itype = resource2item(rtype); - region * r = u->region; - int busy = u->number; - int dm = 0; - allocation_list * alist; - allocation * al; + const item_type * itype = resource2item(rtype); + region * r = u->region; + int busy = u->number; + int dm = 0; + allocation_list * alist; + allocation * al; attrib * a = a_find(rtype->attribs, &at_resourcelimit); resource_limit * rdata = (resource_limit*)a->data.v; int amount, skill; - /* momentan kann man keine ressourcen abbauen, wenn man dafür - * Materialverbrauch hat: */ - assert(itype!=NULL && (itype->construction==NULL || itype->construction->materials==NULL)); + /* momentan kann man keine ressourcen abbauen, wenn man dafür + * Materialverbrauch hat: */ + assert(itype!=NULL && (itype->construction==NULL || itype->construction->materials==NULL)); assert(rdata!=NULL); - + if (rdata->limit!=NULL) { int avail = rdata->limit(r, rtype); if (avail<=0) { cmistake(u, u->thisorder, 121, MSG_PRODUCE); return; } - } - + if (itype == olditemtype[I_LAEN]) { - struct building * b = inside_building(u); - const struct building_type * btype = b?b->type:NULL; - if (btype != bt_find("mine")) { - cmistake(u, u->thisorder, 104, MSG_PRODUCE); - return; - } - } - - if (besieged(u)) { - cmistake(u, u->thisorder, 60, MSG_PRODUCE); - return; - } - + struct building * b = inside_building(u); + const struct building_type * btype = b?b->type:NULL; + if (btype != bt_find("mine")) { + cmistake(u, u->thisorder, 104, MSG_PRODUCE); + return; + } + } + + if (besieged(u)) { + cmistake(u, u->thisorder, 60, MSG_PRODUCE); + return; + } + if (rdata->guard!=0) { unit * u2; - for (u2 = r->units; u2; u2 = u2->next) { - if ((getguard(u2) & rdata->guard) && can_guard(u2, u)) { + for (u2 = r->units; u2; u2 = u2->next) { + if ((getguard(u2) & rdata->guard) && can_guard(u2, u)) { ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); + msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); return; } - } - } - - /* Bergwächter können Abbau von Eisen/Laen durch Bewachen verhindern. - * Als magische Wesen 'sehen' Bergwächter alles und werden durch - * Belagerung nicht aufgehalten. (Ansonsten wie oben bei Elfen anpassen). - */ - if (itype == olditemtype[I_IRON] || itype == olditemtype[I_LAEN]) { + } + } + + /* Bergwächter können Abbau von Eisen/Laen durch Bewachen verhindern. + * Als magische Wesen 'sehen' Bergwächter alles und werden durch + * Belagerung nicht aufgehalten. (Ansonsten wie oben bei Elfen anpassen). + */ + if (itype == olditemtype[I_IRON] || itype == olditemtype[I_LAEN]) { unit * u2; - for (u2 = r->units; u2; u2 = u2->next ) { - if (getguard(u) & GUARD_MINING - && !fval(u2, UFL_ISNEW) - && u2->number - && !alliedunit(u2, u->faction, HELP_GUARD)) - { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); - return; - } - } - } - - assert(itype->construction->skill!=0 || "limited resource needs a required skill for making it"); - skill = eff_skill(u, itype->construction->skill, u->region); - if (skill == 0) { - skill_t sk = itype->construction->skill; - add_message(&u->faction->msgs, - msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); - return; - } - if (skill < itype->construction->minskill) { - skill_t sk = itype->construction->skill; - add_message(&u->faction->msgs, - msg_feedback(u, u->thisorder, "manufacture_skills", "skill minskill product", - sk, itype->construction->minskill, itype->rtype)); - return; - } else { - struct building * b = inside_building(u); - const struct building_type * btype = b?b->type:NULL; - + for (u2 = r->units; u2; u2 = u2->next ) { + if (getguard(u) & GUARD_MINING + && !fval(u2, UFL_ISNEW) + && u2->number + && !alliedunit(u2, u->faction, HELP_GUARD)) + { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); + return; + } + } + } + + assert(itype->construction->skill!=0 || "limited resource needs a required skill for making it"); + skill = eff_skill(u, itype->construction->skill, u->region); + if (skill == 0) { + skill_t sk = itype->construction->skill; + add_message(&u->faction->msgs, + msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); + return; + } + if (skill < itype->construction->minskill) { + skill_t sk = itype->construction->skill; + add_message(&u->faction->msgs, + msg_feedback(u, u->thisorder, "manufacture_skills", "skill minskill product", + sk, itype->construction->minskill, itype->rtype)); + return; + } else { + struct building * b = inside_building(u); + const struct building_type * btype = b?b->type:NULL; + if (rdata->modifiers) { resource_mod * mod = rdata->modifiers; for (;mod->flags!=0;++mod) { @@ -1306,51 +1305,51 @@ allocate_resource(unit * u, const resource_type * rtype, int want) } } } else if (itype == olditemtype[I_IRON] && btype == bt_find("mine")) { - ++skill; - } - else if (itype == olditemtype[I_STONE] && btype == bt_find("quarry")) { - ++skill; - } - } - amount = skill * u->number; - /* nun ist amount die Gesamtproduktion der Einheit (in punkten) */ - - /* mit Flinkfingerring verzehnfacht sich die Produktion */ - amount += skill * min(u->number, get_item(u,I_RING_OF_NIMBLEFINGER)) * 9; - - /* Schaffenstrunk: */ - if ((dm = get_effect(u, oldpotiontype[P_DOMORE])) != 0) { - dm = min(dm, u->number); - change_effect(u, oldpotiontype[P_DOMORE], -dm); - amount += dm * skill; /* dm Personen produzieren doppelt */ - } - - amount /= itype->construction->minskill; - - /* Limitierung durch Parameter m. */ - if (want > 0 && want < amount) amount = want; - - busy = (amount + skill - 1) / skill; /* wieviel leute tun etwas? */ - - alist = allocations; - while (alist && alist->type!=rtype) alist = alist->next; - if (!alist) { - alist = calloc(sizeof(struct allocation_list), 1); - alist->next = allocations; - alist->type = rtype; - allocations = alist; - } - al = new_allocation(); - al->want = amount; - al->save = 1.0; - al->next = alist->data; - al->unit = u; - alist->data = al; - + ++skill; + } + else if (itype == olditemtype[I_STONE] && btype == bt_find("quarry")) { + ++skill; + } + } + amount = skill * u->number; + /* nun ist amount die Gesamtproduktion der Einheit (in punkten) */ + + /* mit Flinkfingerring verzehnfacht sich die Produktion */ + amount += skill * min(u->number, get_item(u,I_RING_OF_NIMBLEFINGER)) * 9; + + /* Schaffenstrunk: */ + if ((dm = get_effect(u, oldpotiontype[P_DOMORE])) != 0) { + dm = min(dm, u->number); + change_effect(u, oldpotiontype[P_DOMORE], -dm); + amount += dm * skill; /* dm Personen produzieren doppelt */ + } + + amount /= itype->construction->minskill; + + /* Limitierung durch Parameter m. */ + if (want > 0 && want < amount) amount = want; + + busy = (amount + skill - 1) / skill; /* wieviel leute tun etwas? */ + + alist = allocations; + while (alist && alist->type!=rtype) alist = alist->next; + if (!alist) { + alist = calloc(sizeof(struct allocation_list), 1); + alist->next = allocations; + alist->type = rtype; + allocations = alist; + } + al = new_allocation(); + al->want = amount; + al->save = 1.0; + al->next = alist->data; + al->unit = u; + alist->data = al; + if (rdata->modifiers) { struct building * b = inside_building(u); const struct building_type * btype = b?b->type:NULL; - + resource_mod * mod = rdata->modifiers; for (;mod->flags!=0;++mod) { if (mod->flags & RMF_SAVEMATERIAL) { @@ -1362,21 +1361,21 @@ allocate_resource(unit * u, const resource_type * rtype, int want) } } } else if (itype==olditemtype[I_IRON]) { - struct building * b = inside_building(u); - const struct building_type * btype = b?b->type:NULL; - if (btype==bt_find("mine")) - al->save *= 0.5; - if (u->race == new_race[RC_DWARF]) { - al->save *= 0.75; - } - } else if (itype==olditemtype[I_STONE]) { - struct building * b = inside_building(u); - const struct building_type * btype = b?b->type:NULL; - if (btype==bt_find("quarry")) - al->save = al->save*0.5; - if (u->race == new_race[RC_TROLL]) - al->save = al->save*0.75; - } + struct building * b = inside_building(u); + const struct building_type * btype = b?b->type:NULL; + if (btype==bt_find("mine")) + al->save *= 0.5; + if (u->race == new_race[RC_DWARF]) { + al->save *= 0.75; + } + } else if (itype==olditemtype[I_STONE]) { + struct building * b = inside_building(u); + const struct building_type * btype = b?b->type:NULL; + if (btype==bt_find("quarry")) + al->save = al->save*0.5; + if (u->race == new_race[RC_TROLL]) + al->save = al->save*0.75; + } } static int diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index d3e6cbb8d..007651682 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -2547,17 +2547,31 @@ combatspell_cmd(unit * u, struct order * ord) /* ------------------------------------------------------------- */ /* Beachten: einige Monster sollen auch unbewaffent die Region bewachen * können */ + +enum { E_GUARD_OK, E_GUARD_UNARMED, E_GUARD_NEWBIE }; + +static int +can_start_guarding(const unit * u) +{ + if (fval(u->race, RCF_UNARMEDGUARD)) return E_GUARD_OK; + if (!armedmen(u)) return E_GUARD_UNARMED; + if (u->faction->age < NewbieImmunity()) return E_GUARD_NEWBIE; + return E_GUARD_OK; +} + void update_guards(void) { - region *r; - unit *u; + const region *r; - for (r = regions; r; r = r->next) + for (r = regions; r; r = r->next) { + unit *u; for (u = r->units; u; u = u->next) { - if (getguard(u) && (!armedmen(u) || u->faction->age < NewbieImmunity())) + if (can_start_guarding(u)!=E_GUARD_OK) { setguard(u, GUARD_NONE); + } } + } } static int @@ -2582,12 +2596,15 @@ guard_on_cmd(unit * u, struct order * ord) /* Monster der Monsterpartei dürfen immer bewachen */ if (u->faction == findfaction(MONSTER_FACTION)) { guard(u, GUARD_ALL); - } else if (!armedmen(u)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unit_unarmed", "")); - } else if (u->faction->age < NewbieImmunity()) { - cmistake(u, ord, 304, MSG_EVENT); } else { - guard(u, GUARD_ALL); + int err = can_start_guarding(u); + if (err==E_GUARD_UNARMED) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unit_unarmed", "")); + } else if (err==E_GUARD_NEWBIE) { + cmistake(u, ord, 304, MSG_EVENT); + } else { + guard(u, GUARD_ALL); + } } } } diff --git a/src/common/kernel/movement.c b/src/common/kernel/movement.c index 523d75f3e..6826f2070 100644 --- a/src/common/kernel/movement.c +++ b/src/common/kernel/movement.c @@ -850,13 +850,13 @@ bewegung_blockiert_von(unit * reisender, region * r) static boolean is_guardian(unit * u2, unit *u, unsigned int mask) { - if (u2->faction == u->faction) return false; - if ((getguard(u2) & mask) == 0) return false; + if (u2->faction == u->faction) return false; + if ((getguard(u2) & mask) == 0) return false; if (u2->number == 0) return false; if (alliedunit(u2, u->faction, HELP_GUARD)) return false; if (ucontact(u2, u)) return false; if (besieged(u2)) return false; - if (!armedmen(u2)) return false; + if (!armedmen(u2) && !fval(u2->race, RCF_UNARMEDGUARD)) return false; if (!cansee(u2->faction, u->region, u, 0)) return false; return true; @@ -865,11 +865,11 @@ is_guardian(unit * u2, unit *u, unsigned int mask) unit * is_guarded(region * r, unit * u, unsigned int mask) { - unit *u2; + unit *u2; - for (u2 = r->units; u2; u2 = u2->next) - if (is_guardian(u2, u, mask)) return u2; - return NULL; + for (u2 = r->units; u2; u2 = u2->next) + if (is_guardian(u2, u, mask)) return u2; + return NULL; } static const char *shortdirections[MAXDIRECTIONS] = diff --git a/src/common/kernel/race.h b/src/common/kernel/race.h index 05232d895..731e9e340 100644 --- a/src/common/kernel/race.h +++ b/src/common/kernel/race.h @@ -118,23 +118,24 @@ extern int rc_specialdamage(const race *, const race *, const struct weapon_type #define RCF_MOVERANDOM (1<<4) #define RCF_CANNOTMOVE (1<<5) -#define RCF_LEARN (1<<6) /* Lernt automatisch wenn struct faction == 0 */ -#define RCF_FLY (1<<7) /* kann fliegen */ -#define RCF_SWIM (1<<8) /* kann schwimmen */ -#define RCF_WALK (1<<9) /* kann über Land gehen */ -#define RCF_NOLEARN (1<<10) /* kann nicht normal lernen */ -#define RCF_NOTEACH (1<<11) /* kann nicht lehren */ -#define RCF_HORSE (1<<12) /* Einheit ist Pferd, sozusagen */ -#define RCF_DESERT (1<<13) /* 5% Chance, das Einheit desertiert */ -#define RCF_ILLUSIONARY (1<<14) /* (Illusion & Spell) Does not drop items. */ -#define RCF_ABSORBPEASANTS (1<<15) /* Tötet und absorbiert Bauern */ -#define RCF_NOHEAL (1<<16) /* Einheit kann nicht geheilt werden */ -#define RCF_NOWEAPONS (1<<17) /* Einheit kann keine Waffen benutzen */ -#define RCF_SHAPESHIFT (1<<18) /* Kann TARNE RASSE benutzen. */ -#define RCF_SHAPESHIFTANY (1<<19) /* Kann TARNE RASSE "string" benutzen. */ -#define RCF_UNDEAD (1<<20) /* Undead. */ -#define RCF_DRAGON (1<<21) /* Drachenart (für Zauber)*/ -#define RCF_COASTAL (1<<22) /* kann in Landregionen an der Küste sein */ +#define RCF_LEARN (1<<6) /* Lernt automatisch wenn struct faction == 0 */ +#define RCF_FLY (1<<7) /* kann fliegen */ +#define RCF_SWIM (1<<8) /* kann schwimmen */ +#define RCF_WALK (1<<9) /* kann über Land gehen */ +#define RCF_NOLEARN (1<<10) /* kann nicht normal lernen */ +#define RCF_NOTEACH (1<<11) /* kann nicht lehren */ +#define RCF_HORSE (1<<12) /* Einheit ist Pferd, sozusagen */ +#define RCF_DESERT (1<<13) /* 5% Chance, das Einheit desertiert */ +#define RCF_ILLUSIONARY (1<<14) /* (Illusion & Spell) Does not drop items. */ +#define RCF_ABSORBPEASANTS (1<<15) /* Tötet und absorbiert Bauern */ +#define RCF_NOHEAL (1<<16) /* Einheit kann nicht geheilt werden */ +#define RCF_NOWEAPONS (1<<17) /* Einheit kann keine Waffen benutzen */ +#define RCF_SHAPESHIFT (1<<18) /* Kann TARNE RASSE benutzen. */ +#define RCF_SHAPESHIFTANY (1<<19) /* Kann TARNE RASSE "string" benutzen. */ +#define RCF_UNDEAD (1<<20) /* Undead. */ +#define RCF_DRAGON (1<<21) /* Drachenart (für Zauber)*/ +#define RCF_COASTAL (1<<22) /* kann in Landregionen an der Küste sein */ +#define RCF_UNARMEDGUARD (1<<23) /* kann ohne Waffen bewachen */ /* Economic flags */ #define NOGIVE (1<<0) /* gibt niemals nix */ diff --git a/src/common/kernel/xmlreader.c b/src/common/kernel/xmlreader.c index d4e571a09..5825327a3 100644 --- a/src/common/kernel/xmlreader.c +++ b/src/common/kernel/xmlreader.c @@ -1412,6 +1412,7 @@ parse_races(xmlDocPtr doc) if (xml_bvalue(node, "cannotmove", false)) rc->flags |= RCF_CANNOTMOVE; if (xml_bvalue(node, "fly", false)) rc->flags |= RCF_FLY; if (xml_bvalue(node, "coastal", false)) rc->flags |= RCF_COASTAL; + if (xml_bvalue(node, "unarmedguard", false)) rc->flags |= RCF_UNARMEDGUARD; if (xml_bvalue(node, "swim", false)) rc->flags |= RCF_SWIM; if (xml_bvalue(node, "walk", false)) rc->flags |= RCF_WALK; if (xml_bvalue(node, "nolearn", false)) rc->flags |= RCF_NOLEARN; diff --git a/src/eressea/lua/eressea.cpp b/src/eressea/lua/eressea.cpp index 0b5fe7a57..befeddda5 100644 --- a/src/eressea/lua/eressea.cpp +++ b/src/eressea/lua/eressea.cpp @@ -39,6 +39,7 @@ using namespace luabind; static int lua_addequipment(const char * eqname, const char * iname, const char * value) { + if (iname==NULL) return -1; const struct item_type * itype = it_find(iname); if (itype==NULL) return -1; equipment_setitem(create_equipment(eqname), itype, value); diff --git a/src/eressea/lua/faction.cpp b/src/eressea/lua/faction.cpp index 8381c5cad..570e76968 100644 --- a/src/eressea/lua/faction.cpp +++ b/src/eressea/lua/faction.cpp @@ -161,11 +161,13 @@ faction_delete_variable(faction& f, const char *key) static int faction_additem(faction& f, const char * iname, int number) { - const item_type * itype = it_find(iname); - if (itype!=NULL) { - item * i = i_change(&f.items, itype, number); - return i?i->number:0; - } // if (itype!=NULL) + if (iname!=NULL) { + const item_type * itype = it_find(iname); + if (itype!=NULL) { + item * i = i_change(&f.items, itype, number); + return i?i->number:0; + } // if (itype!=NULL) + } return -1; } diff --git a/src/eressea/lua/region.cpp b/src/eressea/lua/region.cpp index c77e13a3e..878421244 100644 --- a/src/eressea/lua/region.cpp +++ b/src/eressea/lua/region.cpp @@ -296,11 +296,13 @@ region_items(const region& r) { static int region_additem(region& r, const char * iname, int number) { - const item_type * itype = it_find(iname); - if (itype!=NULL && r.land) { - item * i = i_change(&r.land->items, itype, number); - return i?i->number:0; - } // if (itype!=NULL) + if (iname!=NULL) { + const item_type * itype = it_find(iname); + if (itype!=NULL && r.land) { + item * i = i_change(&r.land->items, itype, number); + return i?i->number:0; + } // if (itype!=NULL) + } return -1; } diff --git a/src/eressea/lua/unit.cpp b/src/eressea/lua/unit.cpp index efb039aa8..00ad5b6e3 100644 --- a/src/eressea/lua/unit.cpp +++ b/src/eressea/lua/unit.cpp @@ -114,9 +114,11 @@ unit_getnumber(const unit& u) static int unit_getitem(const unit& u, const char * iname) { - const item_type * itype = it_find(iname); - if (itype!=NULL) { - return i_get(u.items, itype); + if (iname!=NULL) { + const item_type * itype = it_find(iname); + if (itype!=NULL) { + return i_get(u.items, itype); + } } return -1; } @@ -124,6 +126,13 @@ unit_getitem(const unit& u, const char * iname) static int unit_additem(unit& u, const char * iname, int number) { + if (iname!=NULL) { + const item_type * itype = it_find(iname); + if (itype!=NULL) { + item * i = i_change(&u.items, itype, number); + return i?i->number:0; + } // if (itype!=NULL) + } const item_type * itype = it_find(iname); if (itype!=NULL) { item * i = i_change(&u.items, itype, number); diff --git a/src/res/races.xml b/src/res/races.xml index dac83c8a9..dd876a4be 100644 --- a/src/res/races.xml +++ b/src/res/races.xml @@ -644,7 +644,7 @@ - +