2017-12-29 06:13:28 +01:00
|
|
|
#ifdef _MSC_VER
|
2010-08-08 09:40:42 +02:00
|
|
|
#include <platform.h>
|
2017-12-29 06:13:28 +01:00
|
|
|
#endif
|
2014-02-18 05:45:00 +01:00
|
|
|
#include "borders.h"
|
2017-08-25 21:07:23 +02:00
|
|
|
#include "vortex.h"
|
2010-08-08 09:40:42 +02:00
|
|
|
|
|
|
|
#include <kernel/connection.h>
|
|
|
|
#include <kernel/curse.h>
|
|
|
|
#include <kernel/config.h>
|
|
|
|
#include <kernel/faction.h>
|
2014-06-09 18:54:48 +02:00
|
|
|
#include <kernel/messages.h>
|
2010-08-08 09:40:42 +02:00
|
|
|
#include <kernel/region.h>
|
|
|
|
#include <kernel/terrain.h>
|
|
|
|
#include <kernel/unit.h>
|
|
|
|
|
2018-09-29 11:37:17 +02:00
|
|
|
#include <kernel/attrib.h>
|
2018-09-29 13:21:46 +02:00
|
|
|
#include <kernel/gamedata.h>
|
2010-08-08 09:40:42 +02:00
|
|
|
#include <util/language.h>
|
2017-12-29 06:13:28 +01:00
|
|
|
#include <util/macros.h>
|
2010-08-08 09:40:42 +02:00
|
|
|
#include <util/rand.h>
|
|
|
|
#include <util/rng.h>
|
|
|
|
#include <util/resolve.h>
|
2013-12-31 10:06:28 +01:00
|
|
|
|
|
|
|
#include <storage.h>
|
2010-08-08 09:40:42 +02:00
|
|
|
|
|
|
|
#include <assert.h>
|
2014-03-15 19:29:11 +01:00
|
|
|
#include <stdlib.h>
|
2010-08-08 09:40:42 +02:00
|
|
|
|
|
|
|
typedef struct wallcurse {
|
2015-01-30 20:37:14 +01:00
|
|
|
curse *buddy;
|
|
|
|
connection *wall;
|
2010-08-08 09:40:42 +02:00
|
|
|
} wallcurse;
|
|
|
|
|
2018-02-09 21:20:43 +01:00
|
|
|
static int cw_read_depr(variant *var, void *target, gamedata *data)
|
2010-08-08 09:40:42 +02:00
|
|
|
{
|
2016-02-13 13:42:02 +01:00
|
|
|
storage *store = data->store;
|
2010-08-08 09:40:42 +02:00
|
|
|
|
2018-02-09 21:20:43 +01:00
|
|
|
curse_init(var);
|
|
|
|
curse_read(var, store, target);
|
|
|
|
curse_done(var);
|
2017-08-25 21:03:04 +02:00
|
|
|
READ_INT(store, NULL);
|
|
|
|
return AT_READ_DEPR;
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|
|
|
|
|
2012-06-05 06:45:25 +02:00
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
/* Name: Feuerwand
|
|
|
|
* Stufe:
|
|
|
|
* Gebiet: Draig
|
|
|
|
* Kategorie: Region, negativ
|
|
|
|
* Flag:
|
|
|
|
* Kosten: SPC_LINEAR
|
|
|
|
* Aura:
|
|
|
|
* Komponenten:
|
|
|
|
*
|
|
|
|
* Wirkung:
|
|
|
|
* eine Wand aus Feuer entsteht in der angegebenen Richtung
|
|
|
|
*
|
|
|
|
* Was fuer eine Wirkung hat die?
|
|
|
|
*/
|
|
|
|
|
2015-07-12 14:24:46 +02:00
|
|
|
static void wall_vigour(curse * c, double delta)
|
2012-06-05 06:45:25 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
wallcurse *wc = (wallcurse *)c->data.v;
|
|
|
|
assert(wc->buddy->vigour == c->vigour);
|
|
|
|
wc->buddy->vigour += delta;
|
|
|
|
if (wc->buddy->vigour <= 0) {
|
|
|
|
erase_border(wc->wall);
|
|
|
|
wc->wall = NULL;
|
|
|
|
((wallcurse *)wc->buddy->data.v)->wall = NULL;
|
|
|
|
}
|
2012-06-05 06:45:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const curse_type ct_firewall = {
|
2015-01-30 20:37:14 +01:00
|
|
|
"Feuerwand",
|
|
|
|
CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR | NO_MERGE),
|
|
|
|
NULL, /* curseinfo */
|
|
|
|
wall_vigour /* change_vigour */
|
2012-06-05 06:45:25 +02:00
|
|
|
};
|
|
|
|
|
2011-03-07 08:03:10 +01:00
|
|
|
static void wall_init(connection * b)
|
2010-08-08 09:40:42 +02:00
|
|
|
{
|
2018-10-22 21:51:11 +02:00
|
|
|
wall_data *fd = (wall_data *)calloc(1, sizeof(wall_data));
|
2015-01-30 20:37:14 +01:00
|
|
|
fd->countdown = -1; /* infinite */
|
|
|
|
b->data.v = fd;
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:03:10 +01:00
|
|
|
static void wall_destroy(connection * b)
|
2010-08-08 09:40:42 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
free(b->data.v);
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|
|
|
|
|
2016-02-13 14:29:44 +01:00
|
|
|
static void wall_read(connection * b, gamedata * data)
|
2010-08-08 09:40:42 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
static wall_data dummy;
|
|
|
|
wall_data *fd = b->data.v ? (wall_data *)b->data.v : &dummy;
|
|
|
|
|
2017-09-21 16:26:53 +02:00
|
|
|
read_unit_reference(data, &fd->mage, NULL);
|
2016-02-13 14:29:44 +01:00
|
|
|
READ_INT(data->store, &fd->force);
|
2017-09-21 16:30:29 +02:00
|
|
|
READ_INT(data->store, &fd->countdown);
|
2015-01-30 20:37:14 +01:00
|
|
|
fd->active = true;
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:03:10 +01:00
|
|
|
static void wall_write(const connection * b, storage * store)
|
2010-08-08 09:40:42 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
wall_data *fd = (wall_data *)b->data.v;
|
|
|
|
write_unit_reference(fd->mage, store);
|
|
|
|
WRITE_INT(store, fd->force);
|
|
|
|
WRITE_INT(store, fd->countdown);
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:03:10 +01:00
|
|
|
static int wall_age(connection * b)
|
2010-08-08 09:40:42 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
wall_data *fd = (wall_data *)b->data.v;
|
|
|
|
--fd->countdown;
|
|
|
|
return (fd->countdown > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE;
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:03:10 +01:00
|
|
|
static region *wall_move(const connection * b, struct unit *u,
|
2015-01-30 20:37:14 +01:00
|
|
|
struct region *from, struct region *to, bool routing)
|
2010-08-08 09:40:42 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
wall_data *fd = (wall_data *)b->data.v;
|
|
|
|
if (!routing && fd->active) {
|
|
|
|
int hp = dice(3, fd->force) * u->number;
|
2017-12-29 06:13:28 +01:00
|
|
|
if (u->hp < hp) hp = u->hp;
|
2015-01-30 20:37:14 +01:00
|
|
|
u->hp -= hp;
|
|
|
|
if (u->hp) {
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("firewall_damage",
|
|
|
|
"region unit", from, u));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("firewall_death", "region unit",
|
|
|
|
from, u));
|
|
|
|
if (u->number > u->hp) {
|
|
|
|
scale_number(u, u->hp);
|
|
|
|
u->hp = u->number;
|
|
|
|
}
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|
2015-01-30 20:37:14 +01:00
|
|
|
return to;
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:03:10 +01:00
|
|
|
static const char *b_namefirewall(const connection * b, const region * r,
|
2015-01-30 20:37:14 +01:00
|
|
|
const faction * f, int gflags)
|
2010-08-08 09:40:42 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
const char *bname;
|
2017-01-10 16:31:05 +01:00
|
|
|
UNUSED_ARG(f);
|
|
|
|
UNUSED_ARG(r);
|
|
|
|
UNUSED_ARG(b);
|
2015-01-30 20:37:14 +01:00
|
|
|
if (gflags & GF_ARTICLE)
|
|
|
|
bname = "a_firewall";
|
|
|
|
else
|
|
|
|
bname = "firewall";
|
|
|
|
|
|
|
|
if (gflags & GF_PURE)
|
|
|
|
return bname;
|
|
|
|
return LOC(f->locale, mkname("border", bname));
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
border_type bt_firewall = {
|
2015-01-30 20:37:14 +01:00
|
|
|
"firewall", VAR_VOIDPTR,
|
|
|
|
b_transparent, /* transparent */
|
|
|
|
wall_init, /* init */
|
|
|
|
wall_destroy, /* destroy */
|
|
|
|
wall_read, /* read */
|
|
|
|
wall_write, /* write */
|
|
|
|
b_blocknone, /* block */
|
|
|
|
b_namefirewall, /* name */
|
|
|
|
b_rvisible, /* rvisible */
|
|
|
|
b_finvisible, /* fvisible */
|
|
|
|
b_uinvisible, /* uvisible */
|
|
|
|
NULL,
|
|
|
|
wall_move,
|
|
|
|
wall_age
|
2010-08-08 09:40:42 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
void convert_firewall_timeouts(connection * b, attrib * a)
|
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
while (a) {
|
|
|
|
if (b->type == &bt_firewall && a->type == &at_countdown) {
|
|
|
|
wall_data *fd = (wall_data *)b->data.v;
|
|
|
|
fd->countdown = a->data.i;
|
|
|
|
}
|
2015-11-05 11:17:31 +01:00
|
|
|
a = a->next;
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-12 21:39:49 +02:00
|
|
|
border_type bt_wisps = { /* only here for reading old data */
|
2015-01-30 20:37:14 +01:00
|
|
|
"wisps", VAR_VOIDPTR,
|
|
|
|
b_transparent, /* transparent */
|
|
|
|
0, /* init */
|
|
|
|
wall_destroy, /* destroy */
|
|
|
|
wall_read, /* read */
|
|
|
|
0, /* write */
|
|
|
|
b_blocknone, /* block */
|
|
|
|
0, /* name */
|
|
|
|
b_rvisible, /* rvisible */
|
|
|
|
b_fvisible, /* fvisible */
|
|
|
|
b_uvisible, /* uvisible */
|
|
|
|
NULL, /* visible */
|
|
|
|
0
|
2010-08-08 09:40:42 +02:00
|
|
|
};
|
|
|
|
|
2017-08-25 21:07:23 +02:00
|
|
|
static bool chaosgate_valid(const connection * b)
|
|
|
|
{
|
|
|
|
const attrib *a = a_find(b->from->attribs, &at_direction);
|
|
|
|
if (!a)
|
|
|
|
a = a_find(b->to->attribs, &at_direction);
|
|
|
|
if (!a)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct region *chaosgate_move(const connection * b, struct unit *u,
|
|
|
|
struct region *from, struct region *to, bool routing)
|
|
|
|
{
|
|
|
|
UNUSED_ARG(from);
|
|
|
|
UNUSED_ARG(b);
|
|
|
|
if (!routing) {
|
|
|
|
int maxhp = u->hp / 4;
|
|
|
|
if (maxhp < u->number)
|
|
|
|
maxhp = u->number;
|
|
|
|
u->hp = maxhp;
|
|
|
|
}
|
|
|
|
return to;
|
|
|
|
}
|
|
|
|
|
|
|
|
border_type bt_chaosgate = {
|
|
|
|
"chaosgate", VAR_NONE,
|
|
|
|
b_transparent, /* transparent */
|
|
|
|
NULL, /* init */
|
|
|
|
NULL, /* destroy */
|
|
|
|
NULL, /* read */
|
|
|
|
NULL, /* write */
|
|
|
|
b_blocknone, /* block */
|
|
|
|
NULL, /* name */
|
|
|
|
b_rinvisible, /* rvisible */
|
|
|
|
b_finvisible, /* fvisible */
|
|
|
|
b_uinvisible, /* uvisible */
|
|
|
|
chaosgate_valid,
|
|
|
|
chaosgate_move
|
|
|
|
};
|
|
|
|
|
2014-02-18 05:45:00 +01:00
|
|
|
void register_borders(void)
|
2010-08-08 09:40:42 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
border_convert_cb = &convert_firewall_timeouts;
|
2017-08-25 21:03:04 +02:00
|
|
|
at_deprecate("cursewall", cw_read_depr);
|
2010-08-08 09:40:42 +02:00
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
register_bordertype(&bt_firewall);
|
|
|
|
register_bordertype(&bt_wisps);
|
|
|
|
register_bordertype(&bt_chaosgate);
|
2010-08-08 09:40:42 +02:00
|
|
|
}
|