totaler rewrite von sp_deathcloud

This commit is contained in:
Enno Rehling 2004-03-18 23:48:40 +00:00
parent 97eb1eb81d
commit 0139fb99e6
4 changed files with 149 additions and 68 deletions

View File

@ -80,9 +80,6 @@
#include <attributes/targetregion.h> #include <attributes/targetregion.h>
#include <attributes/hate.h> #include <attributes/hate.h>
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
attrib_type at_deathcloud = {
"zauber_todeswolke", NULL, NULL, NULL, NULL, NULL
};
attrib_type at_unitdissolve = { attrib_type at_unitdissolve = {
"unitdissolve", NULL, NULL, NULL, a_writedefault, a_readdefault "unitdissolve", NULL, NULL, NULL, a_writedefault, a_readdefault
@ -3311,52 +3308,129 @@ sp_unholypower(castorder *co)
* (FARCASTING | REGIONSPELL | TESTRESISTANCE) * (FARCASTING | REGIONSPELL | TESTRESISTANCE)
*/ */
typedef struct dc_data {
region * r;
unit * mage;
double strength;
int countdown;
boolean active;
} dc_data;
static void
dc_initialize(struct attrib *a)
{
dc_data * data = (dc_data *)malloc(sizeof(dc_data));
a->data.v = data;
data->active = true;
}
static void
dc_finalize(struct attrib * a)
{
free(a->data.v);
}
static int
dc_age(struct attrib * a)
/* age returns 0 if the attribute needs to be removed, !=0 otherwise */
{
dc_data * data = (dc_data *)a->data.v;
region * r = data->r;
unit ** up = &r->units;
unit * mage = data->mage;
unit * u;
if (mage==NULL) {
/* if the mage disappears, so does the spell. */
return 0;
}
if (data->active) while (*up!=NULL) {
unit * u = *up;
double damage = data->strength * u->number;
freset(u->faction, FL_DH);
if (target_resists_magic(mage, u, TYP_UNIT, 0)){
continue;
}
/* Reduziert durch Magieresistenz */
damage *= (1.0 - magic_resistance(u));
change_hitpoints(u, -(int)damage);
if (*up==u) up=&u->next;
}
/* melden, 1x pro Partei */
for (u = r->units; u; u = u->next ) {
if (!fval(u->faction, FL_DH) ) {
fset(u->faction, FL_DH);
ADDMSG(&u->faction->msgs, msg_message("deathcloud_effect",
"mage region", cansee(u->faction, r, mage, 0) ? mage : NULL, r));
}
}
if (!fval(mage->faction, FL_DH)){
ADDMSG(&mage->faction->msgs, msg_message("deathcloud_effect",
"mage region", mage, r));
}
return --data->countdown;
}
static void
dc_write(const struct attrib * a, FILE* F)
{
const dc_data * data = (const dc_data *)a->data.v;
fprintf(F, "%d %lf ", data->countdown, data->strength);
write_unit_reference(data->mage, F);
write_region_reference(data->r, F);
}
static int
dc_read(struct attrib * a, FILE* F)
/* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */
{
dc_data * data = (dc_data *)a->data.v;
fscanf(F, "%d %lf ", &data->countdown, &data->strength);
read_unit_reference(&data->mage, F);
return read_region_reference(&data->r, F);
}
attrib_type at_deathcloud = {
"zauber_todeswolke", dc_initialize, dc_finalize, dc_age, dc_write, dc_read
};
static attrib *
mk_deathcloud(unit * mage, region * r, double strength, int duration)
{
attrib * a = a_new(&at_deathcloud);
dc_data * data = (dc_data *)a->data.v;
data->countdown = duration;
data->r = r;
data->mage = mage;
data->strength = strength;
data->active = false;
return a;
}
static int static int
sp_deathcloud(castorder *co) sp_deathcloud(castorder *co)
{ {
unit *u; region *r = co->rt;
double damage; unit *mage = (unit *)co->magician;
region *r = co->rt;
unit *mage = (unit *)co->magician;
int cast_level = co->level;
attrib *a = a_find(r->attribs, &at_deathcloud); attrib *a = a_find(r->attribs, &at_deathcloud);
if(a){ if (a!=NULL) {
report_failure(mage, co->order); report_failure(mage, co->order);
return 0; return 0;
} }
for (u = r->units; u; u = u->next){ a_add(&r->attribs, mk_deathcloud(mage, r, co->force/2, co->level));
if (target_resists_magic(mage, u, TYP_UNIT, 0)){
continue;
}
/* Jede Person verliert 18 HP */
damage = 18 * u->number;
/* Reduziert durch Magieresistenz */
damage *= (1.0 - magic_resistance(u));
change_hitpoints(u, -(int)damage);
}
a = a_add(&r->attribs, a_new(&at_deathcloud)); return co->level;
/* melden, 1x pro Partei */
for (u = r->units; u; u = u->next) freset(u->faction, FL_DH);
for(u = r->units; u; u = u->next ) {
if(!fval(u->faction, FL_DH) ) {
fset(u->faction, FL_DH);
add_message(&u->faction->msgs, new_message(u->faction,
"deathcloud_effect%u:mage%r:region",
cansee(u->faction, r, mage, 0) ? mage:NULL, r));
}
}
if(!fval(mage->faction, FL_DH)){
add_message(&mage->faction->msgs, new_message(mage->faction,
"deathcloud_effect%u:mage%r:region", mage, r));
}
return cast_level;
} }
void void

View File

@ -465,20 +465,17 @@ write_unit_reference(const unit * u, FILE * F)
int int
read_unit_reference(unit ** up, FILE * F) read_unit_reference(unit ** up, FILE * F)
{ {
char zId[10]; char zId[10];
int i; int i;
fscanf(F, "%s", zId);
if (up==NULL) { assert(up!=NULL);
return AT_READ_FAIL; fscanf(F, "%s", zId);
} i = atoi36(zId);
i = atoi36(zId); assert(i!=0);
if (i==0) {
*up = NULL; *up = findunit(i);
return AT_READ_FAIL; if (*up==NULL) ur_add((void*)i, (void**)up, resolve_unit);
} return AT_READ_OK;
*up = findunit(i);
if (*up==NULL) ur_add((void*)i, (void**)up, resolve_unit);
return AT_READ_OK;
} }
attrib_type at_stealth = { attrib_type at_stealth = {

View File

@ -40,19 +40,22 @@ __at_hashkey(const char* s)
void void
at_register(attrib_type * at) at_register(attrib_type * at)
{ {
attrib_type * find; attrib_type * find;
at->hashkey = __at_hashkey(at->name); if (at->read==NULL) {
find = at_hash[at->hashkey % MAXATHASH]; log_warning(("registering non-persistent attribute %s.\n", at->name));
while (find && at->hashkey!=find->hashkey) find = find->nexthash; }
if (find && find==at) { at->hashkey = __at_hashkey(at->name);
log_warning(("attribute '%s' was registered more than once\n", at->name)); find = at_hash[at->hashkey % MAXATHASH];
return; while (find && at->hashkey!=find->hashkey) find = find->nexthash;
} else { if (find && find==at) {
assert(!find || !"hashkey is already in use"); log_warning(("attribute '%s' was registered more than once\n", at->name));
} return;
at->nexthash = at_hash[at->hashkey % MAXATHASH]; } else {
at_hash[at->hashkey % MAXATHASH] = at; assert(!find || !"hashkey is already in use");
}
at->nexthash = at_hash[at->hashkey % MAXATHASH];
at_hash[at->hashkey % MAXATHASH] = at;
} }
static attrib_type * static attrib_type *

View File

@ -178,6 +178,11 @@ unit_removespell(unit& u, const spell * sp)
} }
} }
static int
unit_hpmax(const unit& u)
{
return unit_max_hp(&u);
}
void void
bind_unit(lua_State * L) bind_unit(lua_State * L)
@ -192,6 +197,8 @@ bind_unit(lua_State * L)
.def_readonly("region", &unit::region) .def_readonly("region", &unit::region)
.def_readonly("faction", &unit::faction) .def_readonly("faction", &unit::faction)
.def_readonly("id", &unit::no) .def_readonly("id", &unit::no)
.def_readwrite("hp", &unit::hp)
.def("hp_max", &unit_hpmax)
.def("get_item", &unit_getitem) .def("get_item", &unit_getitem)
.def("add_item", &unit_additem) .def("add_item", &unit_additem)
.def("get_skill", &unit_getskill) .def("get_skill", &unit_getskill)