server/src/curses.c

275 lines
6.6 KiB
C
Raw Normal View History

2010-08-08 09:40:42 +02:00
#include <platform.h>
#include <kernel/types.h>
#include "curses.h"
#include <kernel/connection.h>
#include <kernel/curse.h>
#include <kernel/config.h>
#include <kernel/faction.h>
#include <kernel/message.h>
#include <kernel/region.h>
#include <kernel/save.h>
#include <kernel/terrain.h>
#include <kernel/unit.h>
#include <kernel/version.h>
#include "spells/regioncurse.h"
#include "spells/unitcurse.h"
#include "spells/shipcurse.h"
#include "spells/buildingcurse.h"
#include <util/attrib.h>
#include <util/language.h>
#include <util/rand.h>
#include <util/rng.h>
#include <util/resolve.h>
#include <util/storage.h>
#include <assert.h>
typedef struct wallcurse {
2011-03-07 08:03:10 +01:00
curse *buddy;
connection *wall;
2010-08-08 09:40:42 +02:00
} wallcurse;
2011-03-07 08:03:10 +01:00
void cw_init(attrib * a)
{
curse *c;
2010-08-08 09:40:42 +02:00
curse_init(a);
2011-03-07 08:03:10 +01:00
c = (curse *) a->data.v;
2010-08-08 09:40:42 +02:00
c->data.v = calloc(sizeof(wallcurse), 1);
}
2011-03-07 08:03:10 +01:00
void cw_write(const attrib * a, const void *target, storage * store)
{
connection *b = ((wallcurse *) ((curse *) a->data.v)->data.v)->wall;
2010-08-08 09:40:42 +02:00
curse_write(a, target, store);
store->w_int(store, b->id);
}
typedef struct bresvole {
unsigned int id;
2011-03-07 08:03:10 +01:00
curse *self;
2010-08-08 09:40:42 +02:00
} bresolve;
2011-03-07 08:03:10 +01:00
static int resolve_buddy(variant data, void *addr);
2010-08-08 09:40:42 +02:00
2011-03-07 08:03:10 +01:00
static int cw_read(attrib * a, void *target, storage * store)
2010-08-08 09:40:42 +02:00
{
2011-03-07 08:03:10 +01:00
bresolve *br = calloc(sizeof(bresolve), 1);
curse *c = (curse *) a->data.v;
wallcurse *wc = (wallcurse *) c->data.v;
2010-08-08 09:40:42 +02:00
variant var;
curse_read(a, store, target);
br->self = c;
br->id = store->r_int(store);
var.i = br->id;
ur_add(var, &wc->wall, resolve_borderid);
var.v = br;
ur_add(var, &wc->buddy, resolve_buddy);
return AT_READ_OK;
}
2011-03-07 08:03:10 +01:00
attrib_type at_cursewall = {
2010-08-08 09:40:42 +02:00
"cursewall",
cw_init,
curse_done,
curse_age,
cw_write,
cw_read,
ATF_CURSE
};
2011-03-07 08:03:10 +01:00
static int resolve_buddy(variant data, void *addr)
2010-08-08 09:40:42 +02:00
{
2011-03-07 08:03:10 +01:00
curse *result = NULL;
bresolve *br = (bresolve *) data.v;
if (br->id >= 0) {
connection *b = find_border(br->id);
2010-08-08 09:40:42 +02:00
if (b && b->from && b->to) {
2011-03-07 08:03:10 +01:00
attrib *a = a_find(b->from->attribs, &at_cursewall);
while (a && a->data.v != br->self) {
curse *c = (curse *) a->data.v;
wallcurse *wc = (wallcurse *) c->data.v;
if (wc->wall->id == br->id)
break;
2010-08-08 09:40:42 +02:00
a = a->next;
}
2011-03-07 08:03:10 +01:00
if (!a || a->type != &at_cursewall) {
2010-08-08 09:40:42 +02:00
a = a_find(b->to->attribs, &at_cursewall);
2011-03-07 08:03:10 +01:00
while (a && a->type == &at_cursewall && a->data.v != br->self) {
curse *c = (curse *) a->data.v;
wallcurse *wc = (wallcurse *) c->data.v;
if (wc->wall->id == br->id)
break;
2010-08-08 09:40:42 +02:00
a = a->next;
}
}
2011-03-07 08:03:10 +01:00
if (a && a->type == &at_cursewall) {
curse *c = (curse *) a->data.v;
2010-08-08 09:40:42 +02:00
free(br);
result = c;
}
} else {
/* fail, object does not exist (but if you're still loading then
2011-03-07 08:03:10 +01:00
* you may want to try again later) */
*(curse **) addr = NULL;
2010-08-08 09:40:42 +02:00
return -1;
}
}
2011-03-07 08:03:10 +01:00
*(curse **) addr = result;
2010-08-08 09:40:42 +02:00
return 0;
}
2011-03-07 08:03:10 +01:00
static void wall_init(connection * b)
2010-08-08 09:40:42 +02:00
{
2011-03-07 08:03:10 +01:00
wall_data *fd = (wall_data *) calloc(sizeof(wall_data), 1);
fd->countdown = -1; /* infinite */
2010-08-08 09:40:42 +02:00
b->data.v = fd;
}
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);
}
2011-03-07 08:03:10 +01:00
static void wall_read(connection * b, storage * store)
2010-08-08 09:40:42 +02:00
{
static wall_data dummy;
wall_data *fd = b->data.v ? (wall_data *) b->data.v : &dummy;
2010-08-08 09:40:42 +02:00
variant mno;
2011-03-07 08:03:10 +01:00
if (store->version < STORAGE_VERSION) {
2010-08-08 09:40:42 +02:00
mno.i = store->r_int(store);
fd->mage = findunit(mno.i);
if (!fd->mage && b->data.v) {
2010-08-08 09:40:42 +02:00
ur_add(mno, &fd->mage, resolve_unit);
}
} else {
read_reference(&fd->mage, store, read_unit_reference, resolve_unit);
}
fd->force = store->r_int(store);
2011-03-07 08:03:10 +01:00
if (store->version >= NOBORDERATTRIBS_VERSION) {
2010-08-08 09:40:42 +02:00
fd->countdown = store->r_int(store);
}
fd->active = true;
}
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
{
2011-03-07 08:03:10 +01:00
wall_data *fd = (wall_data *) b->data.v;
2010-08-08 09:40:42 +02:00
write_unit_reference(fd->mage, store);
store->w_int(store, fd->force);
store->w_int(store, fd->countdown);
}
2011-03-07 08:03:10 +01:00
static int wall_age(connection * b)
2010-08-08 09:40:42 +02:00
{
2011-03-07 08:03:10 +01:00
wall_data *fd = (wall_data *) b->data.v;
2010-08-08 09:40:42 +02:00
--fd->countdown;
2011-03-07 08:03:10 +01:00
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, boolean routing)
2010-08-08 09:40:42 +02:00
{
2011-03-07 08:03:10 +01:00
wall_data *fd = (wall_data *) b->data.v;
2010-08-08 09:40:42 +02:00
if (!routing && fd->active) {
int hp = dice(3, fd->force) * u->number;
hp = MIN(u->hp, hp);
u->hp -= hp;
if (u->hp) {
ADDMSG(&u->faction->msgs, msg_message("firewall_damage",
2011-03-07 08:03:10 +01:00
"region unit", from, u));
} else
ADDMSG(&u->faction->msgs, msg_message("firewall_death", "region unit",
from, u));
if (u->number > u->hp) {
2010-08-08 09:40:42 +02:00
scale_number(u, u->hp);
u->hp = u->number;
}
}
return to;
}
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
{
2011-03-07 08:03:10 +01:00
const char *bname;
2010-08-08 09:40:42 +02:00
unused(f);
unused(r);
unused(b);
2011-03-07 08:03:10 +01:00
if (gflags & GF_ARTICLE)
bname = "a_firewall";
else
bname = "firewall";
2010-08-08 09:40:42 +02:00
2011-03-07 08:03:10 +01:00
if (gflags & GF_PURE)
return bname;
2010-08-08 09:40:42 +02:00
return LOC(f->locale, mkname("border", bname));
}
border_type bt_firewall = {
"firewall", VAR_VOIDPTR,
2011-03-07 08:03:10 +01:00
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 */
2010-08-08 09:40:42 +02:00
NULL,
wall_move,
wall_age
};
void convert_firewall_timeouts(connection * b, attrib * a)
{
while (a) {
2011-03-07 08:03:10 +01:00
if (b->type == &bt_firewall && a->type == &at_countdown) {
wall_data *fd = (wall_data *) b->data.v;
2010-08-08 09:40:42 +02:00
fd->countdown = a->data.i;
}
}
}
border_type bt_wisps = { /* only here for reading old data */
2010-08-08 09:40:42 +02:00
"wisps", VAR_VOIDPTR,
2011-03-07 08:03:10 +01:00
b_transparent, /* transparent */
0, /* init */
2011-03-07 08:03:10 +01:00
wall_destroy, /* destroy */
wall_read, /* read */
0, /* write */
2011-03-07 08:03:10 +01:00
b_blocknone, /* block */
0, /* name */
2011-03-07 08:03:10 +01:00
b_rvisible, /* rvisible */
b_fvisible, /* fvisible */
b_uvisible, /* uvisible */
NULL, /* visible */
0
2010-08-08 09:40:42 +02:00
};
2011-03-07 08:03:10 +01:00
void register_curses(void)
2010-08-08 09:40:42 +02:00
{
border_convert_cb = &convert_firewall_timeouts;
at_register(&at_cursewall);
register_bordertype(&bt_firewall);
register_bordertype(&bt_wisps);
register_bordertype(&bt_chaosgate);
2011-03-07 08:03:10 +01:00
2010-08-08 09:40:42 +02:00
register_unitcurse();
register_regioncurse();
register_shipcurse();
register_buildingcurse();
}