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); } }
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); } }
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; }
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); } }
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); } }
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)); }
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; }
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; }
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; }
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; }
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; }
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; }
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))); } }
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; }
/** 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; }
/** 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 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; }