static int att_modification(const unit * u, skill_t sk) { double result = 0; static bool init = false; static const curse_type *skillmod_ct, *gbdream_ct, *worse_ct; curse *c; if (!init) { init = true; skillmod_ct = ct_find("skillmod"); gbdream_ct = ct_find("gbdream"); worse_ct = ct_find("worse"); } c = get_curse(u->attribs, worse_ct); if (c != NULL) result += curse_geteffect(c); if (skillmod_ct) { attrib *a = a_find(u->attribs, &at_curse); while (a && a->type == &at_curse) { curse *c = (curse *) a->data.v; if (c->type == skillmod_ct && c->data.i == sk) { result += curse_geteffect(c); break; } a = a->next; } } /* TODO hier kann nicht mit get/iscursed gearbeitet werden, da nur der * jeweils erste vom Typ C_GBDREAM zurückgegen wird, wir aber alle * durchsuchen und aufaddieren müssen */ if (u->region) { double bonus = 0, malus = 0; attrib *a = a_find(u->region->attribs, &at_curse); while (a && a->type == &at_curse) { curse *c = (curse *) a->data.v; if (curse_active(c) && c->type == gbdream_ct) { double mod = curse_geteffect(c); unit *mage = c->magician; /* wir suchen jeweils den größten Bonus und den größten Malus */ if (mod > bonus) { if (mage == NULL || mage->number == 0 || alliedunit(mage, u->faction, HELP_GUARD)) { bonus = mod; } } else if (mod < malus) { if (mage == NULL || !alliedunit(mage, u->faction, HELP_GUARD)) { malus = mod; } } } a = a->next; } result = result + bonus + malus; } return (int)result; }
int production(const region * r) { /* muß rterrain(r) sein, nicht rterrain() wegen rekursion */ int p = r->terrain->size; if (curse_active(get_curse(r->attribs, ct_find("drought")))) p /= 2; return p; }
bool can_survive(const unit * u, const region * r) { if ((fval(r->terrain, WALK_INTO) && (u_race(u)->flags & RCF_WALK)) || (fval(r->terrain, SWIM_INTO) && (u_race(u)->flags & RCF_SWIM)) || (fval(r->terrain, FLY_INTO) && (u_race(u)->flags & RCF_FLY))) { static const curse_type *ctype = NULL; if (has_horses(u) && !fval(r->terrain, WALK_INTO)) return false; if (!ctype) ctype = ct_find("holyground"); if (fval(u_race(u), RCF_UNDEAD) && curse_active(get_curse(r->attribs, ctype))) return false; return true; } return false; }
void deathcounts(region * r, int fallen) { attrib *a; static const curse_type *ctype = NULL; if (fallen == 0) return; if (!ctype) ctype = ct_find("holyground"); if (ctype && curse_active(get_curse(r->attribs, ctype))) return; a = a_find(r->attribs, &at_deathcount); if (!a) a = a_add(&r->attribs, a_new(&at_deathcount)); a->data.i += fallen; if (a->data.i <= 0) a_remove(&r->attribs, a); }
static curse *shipcurse_flyingship(ship * sh, unit * mage, double power, int duration) { curse *c; if (sh->attribs) { if (curse_active(get_curse(sh->attribs, &ct_flyingship))) { return NULL; } if (is_cursed(sh->attribs, &ct_shipspeedup)) { return NULL; } } /* mit C_SHIP_NODRIFT haben wir kein Problem */ c = create_curse(mage, &sh->attribs, &ct_flyingship, power, duration, 0.0, 0); if (c) { c->data.v = sh; if (c->duration > 0) { sh->flags |= SF_FLYING; } } return c; }
int shipspeed(const ship * sh, const unit * u) { attrib *a; struct curse *c; int k, bonus; assert(sh); if (!u) u = ship_owner(sh); if (!u) return 0; assert(u->ship == sh); assert(u == ship_owner(sh)); assert(sh->type->construction); k = sh->type->range; if (sh->size != sh->type->construction->maxsize) return 0; if (sh->attribs) { if (curse_active(get_curse(sh->attribs, &ct_stormwind))) { k *= 2; } if (curse_active(get_curse(sh->attribs, &ct_nodrift))) { k += 1; } } if (u->faction->race == u_race(u)) { /* race bonus for this faction? */ if (fval(u_race(u), RCF_SHIPSPEED)) { k += 1; } } bonus = ShipSpeedBonus(u); if (bonus > 0 && sh->type->range_max > sh->type->range) { int crew = crew_skill(sh); int crew_bonus = (crew / sh->type->sumskill / 2) - 1; if (crew_bonus > 0) { int sbonus = sh->type->range_max - sh->type->range; if (bonus > sbonus) bonus = sbonus; if (bonus > crew_bonus) bonus = crew_bonus; } else { bonus = 0; } } k += bonus; a = a_find(sh->attribs, &at_speedup); while (a != NULL && a->type == &at_speedup) { k += a->data.sa[0]; a = a->next; } c = get_curse(sh->attribs, &ct_shipspeedup); while (c) { k += curse_geteffect_int(c); c = c->nexthash; } if (sh->damage > 0) { int size = sh->size * DAMAGE_SCALE; k *= (size - sh->damage); k = (k + size - 1) / size; } return k; }
/** Untote können entstehen */ void spawn_undead(void) { region *r; faction *monsters = get_monsters(); for (r = regions; r; r = r->next) { int unburied = deathcount(r); static const curse_type *ctype = NULL; if (!ctype) ctype = ct_find("holyground"); if (ctype && curse_active(get_curse(r->attribs, ctype))) continue; /* Chance 0.1% * chaosfactor */ if (r->land && unburied > r->land->peasants / 20 && rng_int() % 10000 < (100 + 100 * chaosfactor(r))) { message *msg; unit *u; /* es ist sinnfrei, wenn irgendwo im Wald 3er-Einheiten Untote entstehen. * Lieber sammeln lassen, bis sie mindestens 5% der Bevölkerung sind, und * dann erst auferstehen. */ int undead = unburied / (rng_int() % 2 + 1); const race *rc = NULL; int i; if (r->age < 100) undead = undead * r->age / 100; /* newbie-regionen kriegen weniger ab */ if (!undead || r->age < 20) continue; switch (rng_int() % 3) { case 0: rc = get_race(RC_SKELETON); break; case 1: rc = get_race(RC_ZOMBIE); break; default: rc = get_race(RC_GHOUL); break; } u = create_unit(r, monsters, undead, rc, 0, NULL, NULL); fset(u, UFL_ISNEW | UFL_MOVED); if ((rc == get_race(RC_SKELETON) || rc == get_race(RC_ZOMBIE)) && rng_int() % 10 < 4) { equip_unit(u, get_equipment("rising_undead")); } for (i = 0; i < MAXSKILLS; i++) { if (rc->bonus[i] >= 1) { set_level(u, (skill_t)i, 1); } } u->hp = unit_max_hp(u) * u->number; deathcounts(r, -undead); name_unit(u); log_debug("spawning %d %s in %s.\n", u->number, LOC(default_locale, rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL)), regionname(r, NULL)); msg = msg_message("undeadrise", "region", r); add_message(&r->msgs, msg); for (u = r->units; u; u = u->next) freset(u->faction, FFL_SELECT); for (u = r->units; u; u = u->next) { if (fval(u->faction, FFL_SELECT)) continue; fset(u->faction, FFL_SELECT); add_message(&u->faction->msgs, msg); } msg_release(msg); } else { int i = deathcount(r); if (i) { /* Gräber verwittern, 3% der Untoten finden die ewige Ruhe */ deathcounts(r, (int)(-i * 0.03)); } } } }
int shipspeed(const ship * sh, const unit * u) { int k = sh->type->range; static const struct curse_type *stormwind_ct, *nodrift_ct; static bool init; attrib *a; struct curse *c; int bonus; assert(sh); if (!u) u = ship_owner(sh); if (!u) return 0; assert(u->ship == sh); assert(u == ship_owner(sh)); assert(sh->type->construction); assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ if (!init) { init = true; stormwind_ct = ct_find("stormwind"); nodrift_ct = ct_find("nodrift"); } if (sh->size != sh->type->construction->maxsize) return 0; if (curse_active(get_curse(sh->attribs, stormwind_ct))) k *= 2; if (curse_active(get_curse(sh->attribs, nodrift_ct))) k += 1; if (u->faction->race == u_race(u)) { /* race bonus for this faction? */ if (fval(u_race(u), RCF_SHIPSPEED)) { k += 1; } } bonus = ShipSpeedBonus(u); if (bonus > 0 && sh->type->range_max>sh->type->range) { int crew = crew_skill(sh); int crew_bonus = (crew / sh->type->sumskill / 2) - 1; if (crew_bonus > 0) { bonus = _min(bonus, crew_bonus); bonus = _min(bonus, sh->type->range_max - sh->type->range); } else { bonus = 0; } } k += bonus; a = a_find(sh->attribs, &at_speedup); while (a != NULL && a->type == &at_speedup) { k += a->data.sa[0]; a = a->next; } c = get_curse(sh->attribs, ct_find("shipspeedup")); while (c) { k += curse_geteffect_int(c); c = c->nexthash; } if (sh->damage>0) { int size = sh->size * DAMAGE_SCALE; k *= (size - sh->damage); k = (k + size - 1) / size; } return k; }