Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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);
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
/** 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));
            }
        }
    }
}
Example #8
0
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;
}