Beispiel #1
0
void age_dragon(unit * u)
{
  if (u->number > 0 && rng_int() % 100 < age_chance(u->age, WYRMAGE, 1)) {
    double q = (double)u->hp / (double)(unit_max_hp(u) * u->number);
    u_setrace(u, new_race[RC_WYRM]);
    u->irace = NULL;
    u->hp = (int)(unit_max_hp(u) * u->number * q);
  }
}
Beispiel #2
0
void age_firedragon(unit * u)
{
  if (u->number > 0 && rng_int() % 100 < age_chance(u->age, DRAGONAGE, 1)) {
    double q = (double)u->hp / (double)(unit_max_hp(u) * u->number);
    u_setrace(u, new_race[RC_DRAGON]);
    u->irace = NULL;
    scale_number(u, 1);
    u->hp = (int)(unit_max_hp(u) * u->number * q);
  }
}
Beispiel #3
0
static int do_potion(unit * u, region *r, const potion_type * ptype, int amount)
{
  if (ptype == oldpotiontype[P_LIFE]) {
    int holz = 0;
    static int tree_type = -1;
    static int tree_count = -1;
    if (tree_type < 0) {
      tree_type = get_param_int(global.parameters, "rules.magic.wol_type", 1);
      tree_count =
        get_param_int(global.parameters, "rules.magic.wol_effect", 10);
    }
    /* mallorn is required to make mallorn forests, wood for regular ones */
    if (fval(r, RF_MALLORN)) {
      holz = use_pooled(u, rt_find("mallorn"),
        GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, tree_count * amount);
    } else {
      holz = use_pooled(u, rt_find("log"),
        GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, tree_count * amount);
    }
    if (r->land == 0)
      holz = 0;
    if (holz < tree_count * amount) {
      int x = holz / tree_count;
      if (holz % tree_count)
        ++x;
      if (x < amount)
        amount = x;
    }
    rsettrees(r, tree_type, rtrees(r, tree_type) + holz);
    ADDMSG(&u->faction->msgs, msg_message("growtree_effect",
        "mage amount", u, holz));
  } else if (ptype == oldpotiontype[P_HEILWASSER]) {
    u->hp = _min(unit_max_hp(u) * u->number, u->hp + 400 * amount);
  } else if (ptype == oldpotiontype[P_PEOPLE]) {
    attrib *a = (attrib *) a_find(r->attribs, &at_peasantluck);
    if (!a)
      a = a_add(&r->attribs, a_new(&at_peasantluck));
    a->data.i += amount;
  } else if (ptype == oldpotiontype[P_HORSE]) {
    attrib *a = (attrib *) a_find(r->attribs, &at_horseluck);
    if (!a)
      a = a_add(&r->attribs, a_new(&at_horseluck));
    a->data.i += amount;
  } else if (ptype == oldpotiontype[P_WAHRHEIT]) {
    fset(u, UFL_DISBELIEVES);
    amount = 1;
  } else if (ptype == oldpotiontype[P_MACHT]) {
    /* Verfünffacht die HP von max. 10 Personen in der Einheit */
    u->hp += _min(u->number, 10 * amount) * unit_max_hp(u) * 4;
  } else {
    change_effect(u, ptype, 10 * amount);
  }
  return amount;
}
Beispiel #4
0
void age_ghoul(unit * u)
{
  if (is_monsters(u->faction) && rng_int() % 100 < age_chance(u->age, 27, 1)) {
    int n = _max(1, u->number / 2);
    double q = (double)u->hp / (double)(unit_max_hp(u) * u->number);
    u_setrace(u, get_race(RC_GHOUL_LORD));
    u->irace = NULL;
    scale_number(u, n);
    u->hp = (int)(unit_max_hp(u) * u->number * q);
  }
}
Beispiel #5
0
void age_zombie(unit * u)
{
    if (is_monsters(u->faction) && rng_int() % 100 < age_chance(u->age, 27, 1)) {
        int n = u->number / 2;
        double q = (double)u->hp / (double)(unit_max_hp(u) * u->number);
        if (n < 1) n = 1;
        u_setrace(u, get_race(RC_ZOMBIE_LORD));
        u->irace = NULL;
        scale_number(u, n);
        u->hp = (int)(unit_max_hp(u) * u->number * q);
    }
}
Beispiel #6
0
static fighter *summon_allies(const fighter *fi, const race *rc, int number) {
    attrib *a;
    unit *mage = fi->unit;
    side *si = fi->side;
    battle *b = si->battle;
    region *r = b->region;
    message *msg;
    unit *u =
        create_unit(r, mage->faction, number, rc, 0, NULL, mage);
    leave(u, true);
    unit_setstatus(u, ST_FIGHT);
    
    u->hp = u->number * unit_max_hp(u);
    
    if (mage->flags & UFL_ANON_FACTION) {
        u->flags |= UFL_ANON_FACTION;
    }
    
    a = a_new(&at_unitdissolve);
    a->data.ca[0] = 0;
    a->data.ca[1] = 100;
    a_add(&u->attribs, a);
    
    msg = msg_message("sp_wolfhowl_effect", "mage amount race", mage, u->number, rc);
    message_all(b, msg);
    msg_release(msg);

    return make_fighter(b, u, si, is_attacker(fi));
}
Beispiel #7
0
unit *addplayer(region * r, faction * f)
{
    unit *u;
    const char * name;

    assert(r->land);
    if (rpeasants(r) < PEASANT_MIN) {
        rsetpeasants(r, PEASANT_MIN + rng_int() % (PEASANT_MAX - PEASANT_MIN));
    }

    assert(f->units == NULL);
    faction_setorigin(f, 0, r->x, r->y);
    u = create_unit(r, f, 1, f->race, 0, NULL, NULL);
    u->thisorder = default_order(f->locale);
    unit_addorder(u, copy_order(u->thisorder));
    name = config_get("rules.equip_first");
    if (!equip_unit(u, name ? name : "first_unit")) {
        /* give every unit enough money to survive the first turn */
        i_change(&u->items, get_resourcetype(R_SILVER)->itype, maintenance_cost(u));
    }
    u->hp = unit_max_hp(u) * u->number;
    fset(u, UFL_ISNEW);
    if (f->race == get_race(RC_DAEMON)) {
        race_t urc;
        const race *rc;
        do {
            urc = (race_t)(rng_int() % MAXRACES);
            rc = get_race(urc);
        } while (rc == NULL || urc == RC_DAEMON || !playerrace(rc));
        u->irace = rc;
    }
    f->lastorders = 0;
    return u;
}
Beispiel #8
0
int sp_shadowcall(struct castorder * co)
{
    fighter * fi = co->magician.fig;
    int level = co->level;
    double power = co->force;
    battle *b = fi->side->battle;
    region *r = b->region;
    unit *mage = fi->unit;
    attrib *a;
    int force = (int)(get_force(power, 3) / 2);
    unit *u;
    const char *races[3] = { "shadowbat", "nightmare", "vampunicorn" };
    const race *rc = rc_find(races[rng_int() % 3]);
    message *msg;

    u = create_unit(r, mage->faction, force, rc, 0, NULL, mage);
    setstatus(u, ST_FIGHT);

    set_level(u, SK_WEAPONLESS, (int)(power / 2));
    set_level(u, SK_STAMINA, (int)(power / 2));
    u->hp = u->number * unit_max_hp(u);

    a = a_new(&at_unitdissolve);
    a->data.ca[0] = 0;
    a->data.ca[1] = 100;
    a_add(&u->attribs, a);

    make_fighter(b, u, fi->side, is_attacker(fi));
    msg =
        msg_message("sp_shadowcall_effect", "mage amount race", mage, u->number,
        u_race(u));
    message_all(b, msg);
    msg_release(msg);
    return level;
}
Beispiel #9
0
void make_zombie(unit * u)
{
    u_setfaction(u, get_monsters());
    scale_number(u, 1);
    u->hp = unit_max_hp(u) * u->number;
    u_setrace(u, get_race(RC_ZOMBIE));
    u->irace = NULL;
}
Beispiel #10
0
int sp_wolfhowl(castorder * co)
{
    fighter * fi = co->magician.fig;
    int level = co->level;
    double power = co->force;
    int force = (int)(get_force(power, 3) / 2);
    const race * rc = get_race(RC_WOLF);
    if (force > 0) {
        unit *u;
        int skills = (int)(power/3);
        fi = summon_allies(fi, rc, force);
        u = fi->unit;
        set_level(u, SK_WEAPONLESS, skills);
        set_level(u, SK_STAMINA, skills);
        u->hp = u->number * unit_max_hp(u);
    }
    return level;
}
Beispiel #11
0
int sp_wolfhowl(struct castorder * co)
{
  fighter * fi = co->magician.fig;
  int level = co->level;
  double power = co->force;
  battle *b = fi->side->battle;
  region *r = b->region;
  unit *mage = fi->unit;
  attrib *a;
  message *msg;
  int force = (int)(get_force(power, 3) / 2);
  const race * rc = new_race[RC_WOLF];
  if (force>0) {
    unit *u =
      create_unit(r, mage->faction, force, rc, 0, NULL, mage);
    leave(u, true);
    setstatus(u, ST_FIGHT);

    set_level(u, SK_WEAPONLESS, (int)(power / 3));
    set_level(u, SK_STAMINA, (int)(power / 3));
    u->hp = u->number * unit_max_hp(u);
    
    if (fval(mage, UFL_ANON_FACTION)) {
      fset(u, UFL_ANON_FACTION);
    }

    a = a_new(&at_unitdissolve);
    a->data.ca[0] = 0;
    a->data.ca[1] = 100;
    a_add(&u->attribs, a);

    make_fighter(b, u, fi->side, is_attacker(fi));
  }
  msg =
    msg_message("sp_wolfhowl_effect", "mage amount race", mage, force, rc);
  message_all(b, msg);
  msg_release(msg);

  return level;
}
Beispiel #12
0
int sp_shadowknights(struct castorder * co)
{
    fighter * fi = co->magician.fig;
    int level = co->level;
    double power = co->force;
    unit *u;
    battle *b = fi->side->battle;
    region *r = b->region;
    unit *mage = fi->unit;
    attrib *a;
    int force = (int)fmax(1, get_force(power, 3));
    message *msg;

    u =
        create_unit(r, mage->faction, force, get_race(RC_SHADOWKNIGHT), 0, NULL,
        mage);
    unit_setstatus(u, ST_FIGHT);

    u->hp = u->number * unit_max_hp(u);

    if (mage->flags & UFL_ANON_FACTION) {
        u->flags |= UFL_ANON_FACTION;
    }

    a = a_new(&at_unitdissolve);
    a->data.ca[0] = 0;
    a->data.ca[1] = 100;
    a_add(&u->attribs, a);

    make_fighter(b, u, fi->side, is_attacker(fi));

    msg = msg_message("sp_shadowknights_effect", "mage", mage);
    message_all(b, msg);
    msg_release(msg);

    return level;
}
Beispiel #13
0
static void do_shock(unit * u, const char *reason)
{
  int i;

  if (u->number > 0) {
    /* HP - Verlust */
    u->hp = (unit_max_hp(u) * u->number) / 10;
    u->hp = _max(1, u->hp);
  }

  /* Aura - Verlust */
  if (is_mage(u)) {
    set_spellpoints(u, max_spellpoints(u->region, u) / 10);
  }

  /* Evt. Talenttageverlust */
  for (i = 0; i != u->skill_size; ++i)
    if (rng_int() % 5 == 0) {
      skill *sv = u->skills + i;
      int weeks = (sv->level * sv->level - sv->level) / 2;
      int change = (weeks + 9) / 10;
      reduce_skill(u, sv, change);
    }

  /* Dies ist ein Hack, um das skillmod und familiar-Attribut beim Mage
   * zu löschen wenn der Familiar getötet wird. Da sollten wir über eine
   * saubere Implementation nachdenken. */

  if (strcmp(reason, "trigger") == 0) {
    remove_familiar(u);
  }
  if (u->faction != NULL) {
    ADDMSG(&u->faction->msgs, msg_message("shock",
        "mage reason", u, _strdup(reason)));
  }
}
Beispiel #14
0
int sp_undeadhero(struct castorder * co)
{
  fighter * fi = co->magician.fig;
  int level = co->level;
  double power = co->force;
  battle *b = fi->side->battle;
  unit *mage = fi->unit;
  region *r = b->region;
  quicklist *fgs, *ql;
  int qi, n, undead = 0;
  message *msg;
  int force = (int)get_force(power, 0);
  double c = 0.50 + 0.02 * power;

  /* Liste aus allen Kämpfern */
  fgs = fighters(b, fi->side, FIGHT_ROW, AVOID_ROW, FS_ENEMY | FS_HELP);
  scramble_fighters(fgs);

  for (qi = 0, ql = fgs; ql; ql_advance(&ql, &qi, 1)) {
    fighter *df = (fighter *) ql_get(ql, qi);
    unit *du = df->unit;

    if (force <= 0)
      break;

    /* keine Monster */
    if (!playerrace(u_race(du)))
      continue;

    if (df->alive + df->run.number < du->number) {
      int j = 0;

      /* Wieviele Untote können wir aus dieser Einheit wecken? */
      for (n = df->alive + df->run.number; n != du->number; n++) {
        if (chance(c)) {
          ++j;
          if (--force <= 0)
            break;
        }
      }

      if (j > 0) {
        unit *u =
          create_unit(r, mage->faction, 0, new_race[RC_UNDEAD], 0, du->name,
          du);

        /* new units gets some stats from old unit */

        if (du->display) {
          unit_setinfo(u, du->display);
        } else {
          unit_setinfo(u, NULL);
        }
        setstatus(u, du->status);
        setguard(u, GUARD_NONE);

        /* inherit stealth from magician */
        if (fval(mage, UFL_ANON_FACTION)) {
          fset(u, UFL_ANON_FACTION);
        }

        /* transfer dead people to new unit, set hitpoints to those of old unit */
        transfermen(du, u, j);
        u->hp = u->number * unit_max_hp(du);
        assert(j <= df->side->casualties);
        df->side->casualties -= j;
        df->side->dead -= j;

        /* counting total number of undead */
        undead += j;
      }
    }
  }
  ql_free(fgs);

  level = _min(level, undead);
  if (undead == 0) {
    msg =
      msg_message("summonundead_effect_0", "mage region", mage, mage->region);
  } else {
    msg =
      msg_message("summonundead_effect_1", "mage region amount", mage,
      mage->region, undead);
  }

  message_all(b, msg);
  msg_release(msg);
  return level;
}
Beispiel #15
0
/** creates a new unit.
*
* @param dname: name, set to NULL to get a default.
* @param creator: unit to inherit stealth, group, building, ship, etc. from
*/
unit *create_unit(region * r, faction * f, int number, const struct race *urace,
  int id, const char *dname, unit * creator)
{
  unit *u = (unit *)calloc(1, sizeof(unit));

  assert(urace);
  if (f) {
    assert(f->alive);
    u_setfaction(u, f);

    if (f->locale) {
      order *deford = default_order(f->locale);
      if (deford) {
        set_order(&u->thisorder, NULL);
        addlist(&u->orders, deford);
      }
    }
  }
  u_seteffstealth(u, -1);
  u_setrace(u, urace);
  u->irace = NULL;

  set_number(u, number);

  /* die nummer der neuen einheit muss vor name_unit generiert werden,
   * da der default name immer noch 'Nummer u->no' ist */
  createunitid(u, id);

  /* zuerst in die Region setzen, da zb Drachennamen den Regionsnamen
   * enthalten */
  if (r)
    move_unit(u, r, NULL);

  /* u->race muss bereits gesetzt sein, wird für default-hp gebraucht */
  /* u->region auch */
  u->hp = unit_max_hp(u) * number;

  if (!dname) {
    name_unit(u);
  } else {
    u->name = _strdup(dname);
  }

  if (creator) {
    attrib *a;

    /* erbt Kampfstatus */
    setstatus(u, creator->status);

    /* erbt Gebäude/Schiff */
    if (creator->region == r) {
      if (creator->building) {
        u_set_building(u, creator->building);
      }
      if (creator->ship && fval(u_race(u), RCF_CANSAIL)) {
        u_set_ship(u, creator->ship);
      }
    }

    /* Tarnlimit wird vererbt */
    if (fval(creator, UFL_STEALTH)) {
      attrib *a = a_find(creator->attribs, &at_stealth);
      if (a) {
        int stealth = a->data.i;
        a = a_add(&u->attribs, a_new(&at_stealth));
        a->data.i = stealth;
      }
    }

    /* Temps von parteigetarnten Einheiten sind wieder parteigetarnt */
    if (fval(creator, UFL_ANON_FACTION)) {
      fset(u, UFL_ANON_FACTION);
    }
    /* Daemonentarnung */
    set_racename(&u->attribs, get_racename(creator->attribs));
    if (fval(u_race(u), RCF_SHAPESHIFT) && fval(u_race(creator), RCF_SHAPESHIFT)) {
      u->irace = creator->irace;
    }

    /* Gruppen */
    if (creator->faction == f && fval(creator, UFL_GROUP)) {
      a = a_find(creator->attribs, &at_group);
      if (a) {
        group *g = (group *) a->data.v;
        set_group(u, g);
      }
    }
    a = a_find(creator->attribs, &at_otherfaction);
    if (a) {
      a_add(&u->attribs, make_otherfaction(get_otherfaction(a)));
    }

    a = a_add(&u->attribs, a_new(&at_creator));
    a->data.v = creator;
  }

  return u;
}
Beispiel #16
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));
            }
        }
    }
}
Beispiel #17
0
int sp_undeadhero(struct castorder * co)
{
    fighter * fi = co->magician.fig;
    int level = co->level;
    double power = co->force;
    battle *b = fi->side->battle;
    unit *mage = fi->unit;
    region *r = b->region;
    selist *fgs, *ql;
    int qi, n, undead = 0;
    message *msg;
    int force = (int)get_force(power, 0);
    double c = 0.50 + 0.02 * power;

    /* Liste aus allen Kaempfern */
    fgs = select_fighters(b, fi->side, FS_ENEMY | FS_HELP, select_hero, NULL);
    scramble_fighters(fgs);

    for (qi = 0, ql = fgs; ql && force>0; selist_advance(&ql, &qi, 1)) {
        fighter *df = (fighter *)selist_get(ql, qi);
        unit *du = df->unit;
        int j = 0;

        /* Wieviele Untote koennen wir aus dieser Einheit wecken? */
        for (n = df->alive + df->run.number; force>0 && n != du->number; n++) {
            if (chance(c)) {
                ++j;
                --force;
            }
        }

        if (j > 0) {
            item **ilist;
            unit *u =
                create_unit(r, mage->faction, 0, get_race(RC_UNDEAD), 0, unit_getname(du),
                du);

            /* new units gets some stats from old unit */

            unit_setinfo(u, unit_getinfo(du));
            unit_setstatus(u, du->status);
            setguard(u, false);
            for (ilist = &du->items; *ilist;) {
                item *itm = *ilist;
                int loot = itm->number * j / du->number;
                if (loot != itm->number) {
                    int split = itm->number * j % du->number;
                    if (split > 0 && (rng_int() % du->number) < split) {
                        ++loot;
                    }
                }
                i_change(&u->items, itm->type, loot);
                i_change(ilist, itm->type, -loot);
                if (*ilist == itm) {
                    ilist = &itm->next;
                }
            }

            /* inherit stealth from magician */
            if (mage->flags & UFL_ANON_FACTION) {
                u->flags |= UFL_ANON_FACTION;
            }

            /* transfer dead people to new unit, set hitpoints to those of old unit */
            transfermen(du, u, j);
            u->hp = u->number * unit_max_hp(du);
            assert(j <= df->side->casualties);
            df->side->casualties -= j;
            df->side->dead -= j;

            /* counting total number of undead */
            undead += j;
        }
    }
    selist_free(fgs);

    if (level > undead) {
        level = undead;
    }
    if (undead == 0) {
        msg =
            msg_message("summonundead_effect_0", "mage region", mage, mage->region);
    }
    else {
        msg =
            msg_message("summonundead_effect_1", "mage region amount", mage,
            mage->region, undead);
    }

    message_all(b, msg);
    msg_release(msg);
    return level;
}