2010-08-08 10:06:34 +02:00
|
|
|
/*
|
2015-01-30 22:10:29 +01:00
|
|
|
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
|
2015-01-30 20:37:14 +01:00
|
|
|
Katja Zedel <katze@felidae.kn-bremen.de
|
|
|
|
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include <platform.h>
|
|
|
|
#include <kernel/config.h>
|
|
|
|
#include "monster.h"
|
|
|
|
|
|
|
|
/* gamecode includes */
|
|
|
|
#include "economy.h"
|
|
|
|
#include "give.h"
|
2014-08-27 06:40:18 +02:00
|
|
|
#include "move.h"
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
/* attributes includes */
|
|
|
|
#include <attributes/targetregion.h>
|
|
|
|
#include <attributes/hate.h>
|
|
|
|
|
|
|
|
/* kernel includes */
|
|
|
|
#include <kernel/build.h>
|
|
|
|
#include <kernel/equipment.h>
|
|
|
|
#include <kernel/faction.h>
|
|
|
|
#include <kernel/item.h>
|
2014-06-09 18:54:48 +02:00
|
|
|
#include <kernel/messages.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
#include <kernel/order.h>
|
|
|
|
#include <kernel/pathfinder.h>
|
|
|
|
#include <kernel/pool.h>
|
|
|
|
#include <kernel/race.h>
|
|
|
|
#include <kernel/region.h>
|
|
|
|
#include <kernel/terrain.h>
|
|
|
|
#include <kernel/terrainid.h>
|
|
|
|
#include <kernel/unit.h>
|
|
|
|
|
|
|
|
/* util includes */
|
|
|
|
#include <util/attrib.h>
|
|
|
|
#include <util/base36.h>
|
|
|
|
#include <util/bsdstring.h>
|
|
|
|
#include <util/event.h>
|
|
|
|
#include <util/language.h>
|
|
|
|
#include <util/lists.h>
|
|
|
|
#include <util/log.h>
|
|
|
|
#include <util/rand.h>
|
|
|
|
#include <util/rng.h>
|
|
|
|
|
|
|
|
/* libc includes */
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
#define MOVECHANCE 25 /* chance fuer bewegung */
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
#define MAXILLUSION_TEXTS 3
|
|
|
|
|
2012-06-24 07:41:07 +02:00
|
|
|
bool monster_is_waiting(const unit * u)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-11-17 11:25:58 +01:00
|
|
|
int test = fval(u_race(u), RCF_ATTACK_MOVED) ? UFL_ISNEW : UFL_ISNEW | UFL_MOVED;
|
|
|
|
if (fval(u, test))
|
2015-01-30 20:37:14 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
static void eaten_by_monster(unit * u)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-06-23 16:28:10 +02:00
|
|
|
/* adjustment for smaller worlds */
|
|
|
|
static double multi = 0.0;
|
|
|
|
int n = 0;
|
|
|
|
int horse = -1;
|
2014-06-25 07:44:05 +02:00
|
|
|
const resource_type *rhorse = get_resourcetype(R_HORSE);
|
2014-06-23 16:28:10 +02:00
|
|
|
if (multi == 0.0) {
|
|
|
|
multi = RESOURCE_QUANTITY * newterrain(T_PLAIN)->size / 10000.0;
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-06-23 16:28:10 +02:00
|
|
|
switch (old_race(u_race(u))) {
|
2010-08-08 10:06:34 +02:00
|
|
|
case RC_FIREDRAGON:
|
2014-06-23 16:28:10 +02:00
|
|
|
n = rng_int() % 80 * u->number;
|
|
|
|
break;
|
2010-08-08 10:06:34 +02:00
|
|
|
case RC_DRAGON:
|
2014-06-23 16:28:10 +02:00
|
|
|
n = rng_int() % 200 * u->number;
|
|
|
|
break;
|
2010-08-08 10:06:34 +02:00
|
|
|
case RC_WYRM:
|
2014-06-23 16:28:10 +02:00
|
|
|
n = rng_int() % 500 * u->number;
|
|
|
|
break;
|
2010-08-08 10:06:34 +02:00
|
|
|
default:
|
2014-06-23 16:28:10 +02:00
|
|
|
n = rng_int() % (u->number / 20 + 1);
|
|
|
|
horse = 0;
|
|
|
|
}
|
2014-06-25 07:44:05 +02:00
|
|
|
horse = horse ? i_get(u->items, rhorse->itype) : 0;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-06-23 16:28:10 +02:00
|
|
|
n = (int)(n * multi);
|
2010-08-08 10:06:34 +02:00
|
|
|
if (n > 0) {
|
2014-06-23 16:28:10 +02:00
|
|
|
n = lovar(n);
|
|
|
|
n = _min(rpeasants(u->region), n);
|
2015-01-30 20:37:14 +01:00
|
|
|
|
2014-06-23 16:28:10 +02:00
|
|
|
if (n > 0) {
|
|
|
|
deathcounts(u->region, n);
|
|
|
|
rsetpeasants(u->region, rpeasants(u->region) - n);
|
|
|
|
ADDMSG(&u->region->msgs, msg_message("eatpeasants", "unit amount", u, n));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (horse > 0) {
|
2014-06-25 07:44:05 +02:00
|
|
|
i_change(&u->items, rhorse->itype, -horse);
|
2014-06-23 16:28:10 +02:00
|
|
|
ADDMSG(&u->region->msgs, msg_message("eathorse", "unit amount", u, horse));
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
static void absorbed_by_monster(unit * u)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
int n;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
switch (old_race(u_race(u))) {
|
2010-08-08 10:06:34 +02:00
|
|
|
default:
|
2015-01-30 20:37:14 +01:00
|
|
|
n = rng_int() % (u->number / 20 + 1);
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
if (n > 0) {
|
2015-01-30 20:37:14 +01:00
|
|
|
n = lovar(n);
|
|
|
|
n = _min(rpeasants(u->region), n);
|
|
|
|
if (n > 0) {
|
|
|
|
rsetpeasants(u->region, rpeasants(u->region) - n);
|
|
|
|
scale_number(u, u->number + n);
|
|
|
|
ADDMSG(&u->region->msgs, msg_message("absorbpeasants",
|
|
|
|
"unit race amount", u, u_race(u), n));
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
static int scareaway(region * r, int anzahl)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
int n, p, diff = 0, emigrants[MAXDIRECTIONS];
|
|
|
|
direction_t d;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
anzahl = _min(_max(1, anzahl), rpeasants(r));
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
/* Wandern am Ende der Woche (normal) oder wegen Monster. Die
|
|
|
|
* Wanderung wird erst am Ende von demographics () ausgefuehrt.
|
|
|
|
* emigrants[] ist local, weil r->newpeasants durch die Monster
|
|
|
|
* vielleicht schon hochgezaehlt worden ist. */
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
for (d = 0; d != MAXDIRECTIONS; d++)
|
|
|
|
emigrants[d] = 0;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
p = rpeasants(r);
|
|
|
|
assert(p >= 0 && anzahl >= 0);
|
|
|
|
for (n = _min(p, anzahl); n; n--) {
|
|
|
|
direction_t dir = (direction_t)(rng_int() % MAXDIRECTIONS);
|
|
|
|
region *rc = rconnect(r, dir);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
if (rc && fval(rc->terrain, LAND_REGION)) {
|
|
|
|
++diff;
|
|
|
|
rc->land->newpeasants++;
|
|
|
|
emigrants[dir]++;
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2015-01-30 20:37:14 +01:00
|
|
|
rsetpeasants(r, p - diff);
|
|
|
|
assert(p >= diff);
|
|
|
|
return diff;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
static void scared_by_monster(unit * u)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
int n;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
switch (old_race(u_race(u))) {
|
2010-08-08 10:06:34 +02:00
|
|
|
case RC_FIREDRAGON:
|
2015-01-30 20:37:14 +01:00
|
|
|
n = rng_int() % 160 * u->number;
|
|
|
|
break;
|
2010-08-08 10:06:34 +02:00
|
|
|
case RC_DRAGON:
|
2015-01-30 20:37:14 +01:00
|
|
|
n = rng_int() % 400 * u->number;
|
|
|
|
break;
|
2010-08-08 10:06:34 +02:00
|
|
|
case RC_WYRM:
|
2015-01-30 20:37:14 +01:00
|
|
|
n = rng_int() % 1000 * u->number;
|
|
|
|
break;
|
2010-08-08 10:06:34 +02:00
|
|
|
default:
|
2015-01-30 20:37:14 +01:00
|
|
|
n = rng_int() % (u->number / 4 + 1);
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
if (n > 0) {
|
2015-01-30 20:37:14 +01:00
|
|
|
n = lovar(n);
|
|
|
|
n = _min(rpeasants(u->region), n);
|
|
|
|
if (n > 0) {
|
|
|
|
n = scareaway(u->region, n);
|
|
|
|
if (n > 0) {
|
|
|
|
ADDMSG(&u->region->msgs, msg_message("fleescared",
|
|
|
|
"amount unit", n, u));
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void monster_kills_peasants(unit * u)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
if (!monster_is_waiting(u)) {
|
|
|
|
if (u_race(u)->flags & RCF_SCAREPEASANTS) {
|
|
|
|
scared_by_monster(u);
|
|
|
|
}
|
|
|
|
if (u_race(u)->flags & RCF_KILLPEASANTS) {
|
|
|
|
eaten_by_monster(u);
|
|
|
|
}
|
|
|
|
if (u_race(u)->flags & RCF_ABSORBPEASANTS) {
|
|
|
|
absorbed_by_monster(u);
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
2014-11-11 16:53:56 +01:00
|
|
|
|
|
|
|
faction *get_or_create_monsters(void)
|
|
|
|
{
|
|
|
|
faction *f = findfaction(MONSTER_ID);
|
|
|
|
if (!f) {
|
|
|
|
const race *rc = rc_get_or_create("dragon");
|
2015-11-22 10:44:46 +01:00
|
|
|
const char *email = config_get("monster.email");
|
2014-11-23 15:50:22 +01:00
|
|
|
f = addfaction(email ? email : "noreply@eressea.de", NULL, rc, default_locale, 0);
|
2014-11-11 16:53:56 +01:00
|
|
|
renumber_faction(f, MONSTER_ID);
|
|
|
|
faction_setname(f, "Monster");
|
|
|
|
fset(f, FFL_NPC | FFL_NOIDLEOUT);
|
|
|
|
}
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
faction *get_monsters(void) {
|
|
|
|
return get_or_create_monsters();
|
|
|
|
}
|
|
|
|
|
|
|
|
void make_zombie(unit * u)
|
|
|
|
{
|
|
|
|
u_setfaction(u, get_monsters());
|
|
|
|
scale_number(u, 1);
|
2014-12-07 11:14:41 +01:00
|
|
|
u->hp = unit_max_hp(u) * u->number;
|
2014-11-11 16:53:56 +01:00
|
|
|
u_setrace(u, get_race(RC_ZOMBIE));
|
|
|
|
u->irace = NULL;
|
|
|
|
}
|