server/src/spells/borders.c

252 lines
6.5 KiB
C
Raw Normal View History

#ifdef _MSC_VER
2010-08-08 09:40:42 +02:00
#include <platform.h>
#endif
#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>
#include <kernel/messages.h>
2010-08-08 09:40:42 +02:00
#include <kernel/region.h>
#include <kernel/terrain.h>
#include <kernel/unit.h>
#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>
#include <util/macros.h>
2010-08-08 09:40:42 +02:00
#include <util/rand.h>
#include <util/rng.h>
#include <util/resolve.h>
#include <storage.h>
2010-08-08 09:40:42 +02:00
#include <assert.h>
#include <stdlib.h>
2010-08-08 09:40:42 +02:00
typedef struct wallcurse {
curse *buddy;
connection *wall;
2010-08-08 09:40:42 +02:00
} wallcurse;
static int cw_read_depr(variant *var, void *target, gamedata *data)
2010-08-08 09:40:42 +02:00
{
storage *store = data->store;
2010-08-08 09:40:42 +02: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
}
/* ------------------------------------------------------------- */
/* 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?
*/
static void wall_vigour(curse * c, double delta)
{
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;
}
}
const curse_type ct_firewall = {
"Feuerwand",
CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR | NO_MERGE),
NULL, /* curseinfo */
wall_vigour /* change_vigour */
};
2011-03-07 08:03:10 +01:00
static void wall_init(connection * b)
2010-08-08 09:40:42 +02:00
{
wall_data *fd = (wall_data *)calloc(1, sizeof(wall_data));
2018-12-15 20:01:51 +01:00
if (!fd) abort();
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
{
free(b->data.v);
2010-08-08 09:40:42 +02:00
}
static void wall_read(connection * b, gamedata * data)
2010-08-08 09:40:42 +02: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);
READ_INT(data->store, &fd->force);
READ_INT(data->store, &fd->countdown);
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
{
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
{
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,
struct region *from, struct region *to, bool routing)
2010-08-08 09:40:42 +02:00
{
wall_data *fd = (wall_data *)b->data.v;
if (!routing && fd->active) {
int hp = dice(3, fd->force) * u->number;
if (u->hp < hp) hp = u->hp;
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
}
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,
const faction * f, int gflags)
2010-08-08 09:40:42 +02:00
{
const char *bname;
UNUSED_ARG(f);
UNUSED_ARG(r);
UNUSED_ARG(b);
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 = {
"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)
{
while (a) {
if (b->type == &bt_firewall && a->type == &at_countdown) {
wall_data *fd = (wall_data *)b->data.v;
fd->countdown = a->data.i;
}
a = a->next;
2010-08-08 09:40:42 +02:00
}
}
border_type bt_wisps = { /* only here for reading old data */
"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
};
void register_borders(void)
2010-08-08 09:40:42 +02: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
register_bordertype(&bt_firewall);
register_bordertype(&bt_wisps);
register_bordertype(&bt_chaosgate);
2010-08-08 09:40:42 +02:00
}