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 "teleport.h"
|
|
|
|
|
|
|
|
/* kernel includes */
|
2016-01-28 12:25:16 +01:00
|
|
|
#include <kernel/equipment.h>
|
|
|
|
#include <kernel/unit.h>
|
|
|
|
#include <kernel/region.h>
|
|
|
|
#include <kernel/race.h>
|
|
|
|
#include <kernel/terrain.h>
|
|
|
|
#include <kernel/faction.h>
|
|
|
|
#include <kernel/plane.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
/* util includes */
|
|
|
|
#include <util/log.h>
|
|
|
|
#include <util/rng.h>
|
|
|
|
|
2016-01-28 12:25:16 +01:00
|
|
|
#include "skill.h"
|
2016-12-23 18:05:38 +01:00
|
|
|
#include "monsters.h"
|
2014-11-11 16:53:56 +01:00
|
|
|
|
2010-08-08 10:06:34 +02:00
|
|
|
/* libc includes */
|
|
|
|
#include <assert.h>
|
|
|
|
|
2017-10-10 18:45:44 +02:00
|
|
|
#define TE_CENTER 1000
|
2010-08-08 10:06:34 +02:00
|
|
|
#define TP_RADIUS 2
|
|
|
|
#define TP_DISTANCE 4
|
|
|
|
|
2017-10-10 18:45:44 +02:00
|
|
|
int real2tp(int rk)
|
2011-03-07 08:02:35 +01:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
/* in C:
|
|
|
|
* -4 / 5 = 0;
|
|
|
|
* +4 / 5 = 0;
|
|
|
|
* !!!!!!!!!!;
|
|
|
|
*/
|
2017-10-10 18:45:44 +02:00
|
|
|
return TE_CENTER + (rk + (TP_DISTANCE * 5000)) / TP_DISTANCE - 5000;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
static region *tpregion(const region * r)
|
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
region *rt =
|
2017-10-10 18:45:44 +02:00
|
|
|
findregion(real2tp(r->x), real2tp(r->y));
|
2015-01-30 20:37:14 +01:00
|
|
|
if (!is_astral(rt))
|
|
|
|
return NULL;
|
|
|
|
return rt;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2012-06-24 07:41:07 +02:00
|
|
|
region_list *astralregions(const region * r, bool(*valid) (const region *))
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
region_list *rlist = NULL;
|
|
|
|
int x, y;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
assert(is_astral(r));
|
|
|
|
if (!is_astral(r)) {
|
|
|
|
log_error("astralregions was called with a non-astral region.\n");
|
|
|
|
return NULL;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2015-01-30 20:37:14 +01:00
|
|
|
r = r_astral_to_standard(r);
|
|
|
|
if (r == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (x = -TP_RADIUS; x <= +TP_RADIUS; ++x) {
|
|
|
|
for (y = -TP_RADIUS; y <= +TP_RADIUS; ++y) {
|
|
|
|
region *rn;
|
|
|
|
int dist = koor_distance(0, 0, x, y);
|
|
|
|
int nx = r->x + x, ny = r->y + y;
|
|
|
|
|
|
|
|
if (dist > TP_RADIUS)
|
|
|
|
continue;
|
|
|
|
pnormalize(&nx, &ny, rplane(r));
|
|
|
|
rn = findregion(nx, ny);
|
|
|
|
if (rn != NULL && (valid == NULL || valid(rn)))
|
|
|
|
add_regionlist(&rlist, rn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rlist;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
region *r_standard_to_astral(const region * r)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2016-01-31 13:47:18 +01:00
|
|
|
assert(!is_astral(r));
|
2015-01-30 20:37:14 +01:00
|
|
|
return tpregion(r);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
region *r_astral_to_standard(const region * r)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
int x, y;
|
|
|
|
region *r2;
|
|
|
|
|
|
|
|
assert(is_astral(r));
|
2017-10-10 18:45:44 +02:00
|
|
|
x = (r->x - TE_CENTER) * TP_DISTANCE;
|
|
|
|
y = (r->y - TE_CENTER) * TP_DISTANCE;
|
2016-01-28 12:46:38 +01:00
|
|
|
pnormalize(&x, &y, NULL);
|
2015-01-30 20:37:14 +01:00
|
|
|
r2 = findregion(x, y);
|
2016-01-28 12:46:38 +01:00
|
|
|
if (r2 == NULL || rplane(r2))
|
2015-01-30 20:37:14 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return r2;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
region_list *all_in_range(const region * r, int n,
|
2015-01-30 20:37:14 +01:00
|
|
|
bool(*valid) (const region *))
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
int x, y;
|
|
|
|
region_list *rlist = NULL;
|
|
|
|
plane *pl = rplane(r);
|
2011-03-07 08:02:35 +01:00
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
if (r == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (x = r->x - n; x <= r->x + n; x++) {
|
|
|
|
for (y = r->y - n; y <= r->y + n; y++) {
|
|
|
|
if (koor_distance(r->x, r->y, x, y) <= n) {
|
|
|
|
region *r2;
|
|
|
|
int nx = x, ny = y;
|
|
|
|
pnormalize(&nx, &ny, pl);
|
|
|
|
r2 = findregion(nx, ny);
|
|
|
|
if (r2 != NULL && (valid == NULL || valid(r2)))
|
|
|
|
add_regionlist(&rlist, r2);
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
return rlist;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2018-02-04 19:13:04 +01:00
|
|
|
#define MAX_BRAIN_SIZE 100
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void spawn_braineaters(float chance)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2018-02-04 19:13:04 +01:00
|
|
|
const race * rc_brain = get_race(RC_HIRNTOETER);
|
2015-01-30 20:37:14 +01:00
|
|
|
region *r;
|
2018-02-04 19:13:04 +01:00
|
|
|
faction *f = get_monsters();
|
2015-01-30 20:37:14 +01:00
|
|
|
int next = rng_int() % (int)(chance * 100);
|
|
|
|
|
2018-02-04 19:13:04 +01:00
|
|
|
if (f == NULL || rc_brain == NULL) {
|
2015-01-30 20:37:14 +01:00
|
|
|
return;
|
2018-02-04 19:13:04 +01:00
|
|
|
}
|
2015-01-30 20:37:14 +01:00
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
2018-02-04 19:13:04 +01:00
|
|
|
unit *u, *ub = NULL;
|
2015-01-30 20:37:14 +01:00
|
|
|
if (!is_astral(r) || fval(r->terrain, FORBIDDEN_REGION))
|
|
|
|
continue;
|
|
|
|
|
2018-02-04 19:13:04 +01:00
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
if (u->_race == rc_brain) {
|
|
|
|
if (!ub) {
|
|
|
|
ub = u;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int n = u->number + ub->number;
|
|
|
|
if (n <= MAX_BRAIN_SIZE) {
|
|
|
|
scale_number(ub, n);
|
|
|
|
u->number = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ub = u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
/* Neues Monster ? */
|
|
|
|
if (next-- == 0) {
|
2018-02-04 19:13:04 +01:00
|
|
|
u = create_unit(r, f, 1 + rng_int() % 10 + rng_int() % 10,
|
|
|
|
rc_brain, 0, NULL, NULL);
|
2017-09-17 20:42:43 +02:00
|
|
|
equip_unit(u, get_equipment("seed_braineater"));
|
2015-01-30 20:37:14 +01:00
|
|
|
|
|
|
|
next = rng_int() % (int)(chance * 100);
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-24 07:41:07 +02:00
|
|
|
bool is_astral(const region * r)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
plane *pl = get_astralplane();
|
|
|
|
return (pl && rplane(r) == pl);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
plane *get_astralplane(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-11-21 12:28:20 +01:00
|
|
|
plane *astralspace = 0;
|
2016-09-23 20:36:57 +02:00
|
|
|
static int config;
|
|
|
|
static bool rule_astralplane;
|
|
|
|
|
|
|
|
if (config_changed(&config)) {
|
|
|
|
rule_astralplane = config_get_int("modules.astralspace", 1) != 0;
|
|
|
|
}
|
2015-01-30 20:37:14 +01:00
|
|
|
if (!rule_astralplane) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-11-19 15:19:23 +01:00
|
|
|
astralspace = getplanebyname("Astralraum");
|
2015-11-21 12:28:20 +01:00
|
|
|
if (!astralspace) {
|
2015-01-30 20:37:14 +01:00
|
|
|
astralspace = create_new_plane(1, "Astralraum",
|
2017-10-10 18:45:44 +02:00
|
|
|
TE_CENTER - 500, TE_CENTER + 500,
|
|
|
|
TE_CENTER - 500, TE_CENTER + 500, 0);
|
2015-01-30 20:37:14 +01:00
|
|
|
}
|
|
|
|
return astralspace;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void create_teleport_plane(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
region *r;
|
|
|
|
plane *hplane = get_homeplane();
|
|
|
|
plane *aplane = get_astralplane();
|
|
|
|
|
|
|
|
const terrain_type *fog = get_terrain("fog");
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
plane *pl = rplane(r);
|
|
|
|
if (pl == hplane) {
|
|
|
|
region *ra = tpregion(r);
|
|
|
|
|
|
|
|
if (ra == NULL) {
|
2017-10-10 18:45:44 +02:00
|
|
|
int x = real2tp(r->x);
|
|
|
|
int y = real2tp(r->y);
|
2015-01-30 20:37:14 +01:00
|
|
|
pnormalize(&x, &y, aplane);
|
|
|
|
|
|
|
|
ra = new_region(x, y, aplane, 0);
|
|
|
|
terraform_region(ra, fog);
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-24 07:41:07 +02:00
|
|
|
bool inhabitable(const region * r)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
return fval(r->terrain, LAND_REGION);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|