forked from github/server
2079db13cf
Rekrutieren und div. andere Dinge waren möglich, weil HELFE GIB ein automatisches KONTAKTIERE setzte. Ich habe den Code nach anderen Vorkommen aehnlicher Bugs untersucht und repariert.
378 lines
10 KiB
C
378 lines
10 KiB
C
/* vi: set ts=2:
|
||
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||
| | Enno Rehling <enno@eressea-pbem.de>
|
||
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
|
||
| (c) 1998 - 2003 | Henning Peters <faroul@beyond.kn-bremen.de>
|
||
| | Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
|
||
+-------------------+ Stefan Reich <reich@halbling.de>
|
||
|
||
This program may not be used, modified or distributed
|
||
without prior permission by the authors of Eressea.
|
||
|
||
*/
|
||
#include <config.h>
|
||
#include "eressea.h"
|
||
|
||
#include "give.h"
|
||
|
||
/* kernel includes */
|
||
#include "faction.h"
|
||
#include "item.h"
|
||
#include "magic.h"
|
||
#include "message.h"
|
||
#include "order.h"
|
||
#include "pool.h"
|
||
#include "race.h"
|
||
#include "region.h"
|
||
#include "reports.h"
|
||
#include "ship.h"
|
||
#include "skill.h"
|
||
#include "unit.h"
|
||
|
||
/* attributes includes */
|
||
#include <attributes/racename.h>
|
||
#include <attributes/orcification.h>
|
||
|
||
/* util includes */
|
||
#include <util/event.h>
|
||
#include <util/base36.h>
|
||
|
||
/* libc includes */
|
||
#include <limits.h>
|
||
#include <stdlib.h>
|
||
|
||
/* Wieviel Fremde eine Partei pro Woche aufnehmen kann */
|
||
#define MAXNEWBIES 5
|
||
#define RESERVE_DONATIONS /* shall we reserve objects given to us by other factions? */
|
||
#define RESERVE_GIVE /* reserve anything that's given from one unit to another? */
|
||
|
||
|
||
static int
|
||
GiveRestriction(void) {
|
||
static int value = -1;
|
||
if (value<0) {
|
||
const char * str = get_param(global.parameters, "GiveRestriction");
|
||
value = str?atoi(str):0;
|
||
}
|
||
return value;
|
||
}
|
||
|
||
static void
|
||
add_give(unit * u, unit * u2, int n, const resource_type * rtype, struct order * ord, int error)
|
||
{
|
||
if (error) {
|
||
cmistake(u, ord, error, MSG_COMMERCE);
|
||
}
|
||
else if (!u2 || u2->faction!=u->faction) {
|
||
assert(rtype);
|
||
add_message(&u->faction->msgs,
|
||
msg_message("give", "unit target resource amount",
|
||
u, u2?ucansee(u->faction, u2, u_unknown()):u_peasants(), rtype, n));
|
||
if (u2) {
|
||
add_message(&u2->faction->msgs,
|
||
msg_message("give", "unit target resource amount",
|
||
ucansee(u2->faction, u, u_unknown()), u2, rtype, n));
|
||
}
|
||
}
|
||
}
|
||
|
||
static void
|
||
give_peasants(int n, const item_type * itype, unit * src)
|
||
{
|
||
region *r = src->region;
|
||
|
||
/* horses are given to the region via itype->give! */
|
||
|
||
if (itype->rtype==r_silver) {
|
||
rsetmoney(r, rmoney(r) + n);
|
||
}
|
||
}
|
||
|
||
int
|
||
give_item(int want, const item_type * itype, unit * src, unit * dest, struct order * ord)
|
||
{
|
||
short error = 0;
|
||
int n;
|
||
|
||
assert(itype!=NULL);
|
||
n = new_get_pooled(src, item2resource(itype), GET_DEFAULT);
|
||
n = min(want, n);
|
||
if (dest && src->faction != dest->faction && src->faction->age < GiveRestriction()) {
|
||
if (ord!=NULL) {
|
||
ADDMSG(&src->faction->msgs, msg_feedback(src, ord, "giverestriction",
|
||
"turns", GiveRestriction()));
|
||
}
|
||
return -1;
|
||
} else if (n == 0) {
|
||
error = 36;
|
||
} else if (itype->flags & ITF_CURSED) {
|
||
error = 25;
|
||
} else if (itype->give && !itype->give(src, dest, itype, n, ord)) {
|
||
return -1;
|
||
} else {
|
||
int use = new_use_pooled(src, item2resource(itype), GET_SLACK, n);
|
||
if (use<n) use += new_use_pooled(src, item2resource(itype), GET_RESERVE|GET_POOLED_SLACK, n-use);
|
||
if (dest) {
|
||
i_change(&dest->items, itype, n);
|
||
#ifdef RESERVE_GIVE
|
||
#ifdef RESERVE_DONATIONS
|
||
new_change_resvalue(dest, item2resource(itype), n);
|
||
#else
|
||
if (src->faction==dest->faction) {
|
||
new_change_resvalue(dest, item2resource(itype), n);
|
||
}
|
||
#endif
|
||
#endif
|
||
handle_event(&src->attribs, "give", dest);
|
||
handle_event(&dest->attribs, "receive", src);
|
||
#if defined(MUSEUM_MODULE) && defined(TODO)
|
||
/* TODO: Einen Trigger f<>r den museums-warden benutzen! */
|
||
if (a_find(dest->attribs, &at_warden)) {
|
||
/* warden_add_give(src, dest, itype, n); */
|
||
}
|
||
#endif
|
||
}else{
|
||
/* gib bauern */
|
||
give_peasants(use, itype, src);
|
||
}
|
||
}
|
||
add_give(src, dest, n, item2resource(itype), ord, error);
|
||
if (error) return -1;
|
||
return 0;
|
||
}
|
||
|
||
void
|
||
give_men(int n, unit * u, unit * u2, struct order * ord)
|
||
{
|
||
ship *sh;
|
||
int k = 0;
|
||
int error = 0;
|
||
|
||
if (u2 && u->faction != u2->faction && u->faction->age < GiveRestriction()) {
|
||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "giverestriction",
|
||
"turns", GiveRestriction()));
|
||
return;
|
||
} else if (u == u2) {
|
||
error = 10;
|
||
#if RACE_ADJUSTMENTS
|
||
} else if (!u2 && u->race == new_race[RC_SNOTLING]) {
|
||
/* Snotlings k<>nnen nicht an Bauern <20>bergeben werden. */
|
||
error = 307;
|
||
#endif
|
||
#ifdef HEROES
|
||
} else if (u2 && u2->number>0 && fval(u, UFL_HERO)!=fval(u2, UFL_HERO)) {
|
||
error = 75;
|
||
#endif
|
||
} else if ((u && unit_has_cursed_item(u)) || (u2 && unit_has_cursed_item(u2))) {
|
||
error = 78;
|
||
} else if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER) || is_cursed(u->attribs, C_SLAVE, 0)) {
|
||
error = 74;
|
||
} else if (u2 && (fval(u2, UFL_LOCKED)|| is_cursed(u2->attribs, C_SLAVE, 0))) {
|
||
error = 75;
|
||
} else if (u2 && u2->faction != u->faction && !alliedunit(u2, u->faction, HELP_GIVE) && !ucontact(u2, u)) {
|
||
|
||
error = 73;
|
||
} else if (u2 && (has_skill(u, SK_MAGIC) || has_skill(u2, SK_MAGIC))) {
|
||
error = 158;
|
||
} else if (u2 && fval(u, UFL_WERE) != fval(u2, UFL_WERE)) {
|
||
error = 312;
|
||
} else if (u2 && u2->number!=0 && u2->race != u->race) {
|
||
log_warning(("Partei %s versucht %s an %s zu <20>bergeben.\n",
|
||
itoa36(u->faction->no), u->race->_name[0],
|
||
u2->race->_name[1]));
|
||
error = 139;
|
||
} else if (u2!=NULL && (get_racename(u2->attribs) || get_racename(u->attribs))) {
|
||
error = 139;
|
||
} else {
|
||
if (n > u->number) n = u->number;
|
||
if (n == 0) {
|
||
error = 96;
|
||
} else if (u2 && u->faction != u2->faction) {
|
||
if (u2->faction->newbies + n > MAXNEWBIES) {
|
||
error = 129;
|
||
} else if (u->race != u2->faction->race) {
|
||
if (u2->faction->race != new_race[RC_HUMAN]) {
|
||
error = 120;
|
||
} else if (count_migrants(u2->faction) + n > count_maxmigrants(u2->faction)) {
|
||
error = 128;
|
||
}
|
||
else if (teure_talente(u) || teure_talente(u2)) {
|
||
error = 154;
|
||
} else if (u2->number!=0) {
|
||
error = 139;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (u2 && (has_skill(u, SK_ALCHEMY) || has_skill(u2, SK_ALCHEMY))) {
|
||
k = count_skill(u2->faction, SK_ALCHEMY);
|
||
|
||
/* Falls die Zieleinheit keine Alchemisten sind, werden sie nun
|
||
* welche. */
|
||
if (!has_skill(u2, SK_ALCHEMY) && has_skill(u, SK_ALCHEMY))
|
||
k += u2->number;
|
||
|
||
/* Wenn in eine Alchemisteneinheit Personen verschoben werden */
|
||
if (has_skill(u2, SK_ALCHEMY) && !has_skill(u, SK_ALCHEMY))
|
||
k += n;
|
||
|
||
/* Wenn Parteigrenzen <20>berschritten werden */
|
||
if (u2->faction != u->faction)
|
||
k += n;
|
||
|
||
/* wird das Alchemistenmaximum ueberschritten ? */
|
||
|
||
if (k > max_skill(u2->faction, SK_ALCHEMY)) {
|
||
error = 156;
|
||
}
|
||
}
|
||
|
||
if (error==0) {
|
||
if (u2 && u2->number == 0) {
|
||
set_racename(&u2->attribs, get_racename(u->attribs));
|
||
u2->race = u->race;
|
||
u2->irace = u->irace;
|
||
#ifdef HEROES
|
||
if (fval(u, UFL_HERO)) fset(u2, UFL_HERO);
|
||
else freset(u2, UFL_HERO);
|
||
#endif
|
||
}
|
||
|
||
if (u2) {
|
||
/* Einheiten von Schiffen k<>nnen nicht NACH in von
|
||
* Nicht-alliierten bewachten Regionen ausf<73>hren */
|
||
sh = leftship(u);
|
||
if (sh) set_leftship(u2, sh);
|
||
|
||
transfermen(u, u2, n);
|
||
if (u->faction != u2->faction) {
|
||
u2->faction->newbies += n;
|
||
}
|
||
} else {
|
||
if (getunitpeasants) {
|
||
#ifdef ORCIFICATION
|
||
if (u->race == new_race[RC_ORC] && !fval(u->region, RF_ORCIFIED)) {
|
||
attrib *a = a_find(u->region->attribs, &at_orcification);
|
||
if (!a) a = a_add(&u->region->attribs, a_new(&at_orcification));
|
||
a->data.i += n;
|
||
}
|
||
#endif
|
||
transfermen(u, NULL, n);
|
||
} else {
|
||
error = 159;
|
||
}
|
||
}
|
||
}
|
||
if (error) {
|
||
cmistake(u, ord, error, MSG_COMMERCE);
|
||
}
|
||
else if (!u2 || u2->faction!=u->faction) {
|
||
ADDMSG(&u->faction->msgs, msg_message("give_person", "unit target amount",
|
||
u, u2?ucansee(u->faction, u2, u_unknown()):u_peasants(), n));
|
||
if (u2) {
|
||
ADDMSG(&u2->faction->msgs, msg_message("give_person", "unit target amount",
|
||
ucansee(u2->faction, u, u_unknown()), u2, n));
|
||
}
|
||
}
|
||
}
|
||
|
||
void
|
||
give_unit(unit * u, unit * u2, order * ord)
|
||
{
|
||
region * r = u->region;
|
||
int n = u->number;
|
||
|
||
if (u && unit_has_cursed_item(u)) {
|
||
cmistake(u, ord, 78, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
|
||
#ifdef HEROES
|
||
if (fval(u, UFL_HERO)) {
|
||
cmistake(u, ord, 75, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
#endif
|
||
if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) {
|
||
cmistake(u, ord, 74, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
|
||
if (u2 == NULL) {
|
||
if (rterrain(r) == T_OCEAN) {
|
||
cmistake(u, ord, 152, MSG_COMMERCE);
|
||
} else if (getunitpeasants) {
|
||
unit *u3;
|
||
|
||
for(u3 = r->units; u3; u3 = u3->next)
|
||
if(u3->faction == u->faction && u != u3) break;
|
||
|
||
if(u3) {
|
||
while (u->items) {
|
||
item * iold = i_remove(&u->items, u->items);
|
||
item * inew = *i_find(&u3->items, iold->type);
|
||
if (inew==NULL) i_add(&u3->items, iold);
|
||
else {
|
||
inew->number += iold->number;
|
||
i_free(iold);
|
||
}
|
||
}
|
||
}
|
||
give_men(u->number, u, NULL, ord);
|
||
cmistake(u, ord, 153, MSG_COMMERCE);
|
||
} else {
|
||
cmistake(u, ord, 63, MSG_COMMERCE);
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (!alliedunit(u2, u->faction, HELP_GIVE) && ucontact(u2, u) == 0) {
|
||
cmistake(u, ord, 73, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
if (u->number == 0) {
|
||
cmistake(u, ord, 105, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
if (u2->faction->newbies + n > MAXNEWBIES) {
|
||
cmistake(u, ord, 129, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
if (u->race != u2->faction->race) {
|
||
if (u2->faction->race != new_race[RC_HUMAN]) {
|
||
cmistake(u, ord, 120, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
if (count_migrants(u2->faction) + u->number > count_maxmigrants(u2->faction)) {
|
||
cmistake(u, ord, 128, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
if (teure_talente(u)) {
|
||
cmistake(u, ord, 154, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
}
|
||
if (has_skill(u, SK_MAGIC)) {
|
||
if (count_skill(u2->faction, SK_MAGIC) + u->number >
|
||
max_skill(u2->faction, SK_MAGIC))
|
||
{
|
||
cmistake(u, ord, 155, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
if (u2->faction->magiegebiet != find_magetype(u)) {
|
||
cmistake(u, ord, 157, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
}
|
||
if (has_skill(u, SK_ALCHEMY)
|
||
&& count_skill(u2->faction, SK_ALCHEMY) + u->number >
|
||
max_skill(u2->faction, SK_ALCHEMY))
|
||
{
|
||
cmistake(u, ord, 156, MSG_COMMERCE);
|
||
return;
|
||
}
|
||
add_give(u, u2, 1, r_unit, ord, 0);
|
||
u_setfaction(u, u2->faction);
|
||
u2->faction->newbies += n;
|
||
}
|