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; }
static unit *random_unit(const region * r) { int c = 0; int n; unit *u; for (u = r->units; u; u = u->next) { if (u_race(u) != get_race(RC_SPELL)) { c += u->number; } } if (c == 0) { return NULL; } n = rng_int() % c; c = 0; u = r->units; while (u && c < n) { if (u_race(u) != get_race(RC_SPELL)) { c += u->number; } u = u->next; } return u; }
/* In general, the class index is given by player_type.pclass. However, for various * monster races, the "class" behavior is actually determined by the race, and we * encode this desire with race_t.pseudo_class_idx. As another twist, consider the * possessor. Here, the "class" behavior depends on the current body (see r_info.text). */ int get_class_idx(void) { int result = p_ptr->pclass; if (result == CLASS_MONSTER) { switch (p_ptr->prace) { case RACE_MON_POSSESSOR: case RACE_MON_MIMIC: if (p_ptr->current_r_idx) { result = r_info[p_ptr->current_r_idx].body.class_idx; break; } /* vvv Fall Through vvv */ default: { race_t *race_ptr = get_race(); /*if (race_ptr->pseudo_class_idx) Note: CLASS_WARRIOR = 0! */ result = race_ptr->pseudo_class_idx; } } } return result; }
int rc_skillmod(const struct race *rc, const region * r, skill_t sk) { int mods = 0; if (!skill_enabled(sk)) { return 0; } #ifdef FASTER_SKILLMOD unsigned int index = hashstring(rc->_name) % RCMODMAXHASH; struct skillmods **imods = &modhash[index]; while (*imods && (*imods)->race != rc) { imods = &(*imods)->next; } if (*imods == NULL) { *imods = init_skills(rc); } mods = (*imods)->mod[rterrain(r)].value[sk]; #else if (r) { mods = skill_mod(rc, sk, r->terrain); } #endif if (rc == get_race(RC_ELF) && r && r_isforest(r)) { if (sk == SK_PERCEPTION || sk == SK_STEALTH) { ++mods; } else if (sk == SK_TACTICS) { mods += 2; } } return mods; }
static void recruit_dracoids(unit * dragon, int size) { faction *f = dragon->faction; region *r = dragon->region; const struct item *weapon = NULL; order *new_order = NULL; unit *un = create_unit(r, f, size, get_race(RC_DRACOID), 0, NULL, NULL); fset(un, UFL_ISNEW | UFL_MOVED); name_unit(un); change_money(dragon, -un->number * 50); equip_unit(un, get_equipment("recruited_dracoid")); setstatus(un, ST_FIGHT); for (weapon = un->items; weapon; weapon = weapon->next) { const weapon_type *wtype = weapon->type->rtype->wtype; if (wtype && (wtype->flags & WTF_MISSILE)) { setstatus(un, ST_BEHIND); } new_order = create_order(K_STUDY, f->locale, "'%s'", skillname(weapon->type->rtype->wtype->skill, f->locale)); } if (new_order != NULL) { addlist(&un->orders, new_order); } }
int bt_effsize(const building_type * btype, const building * b, int bsize) { int i = bsize, n = 0; const construction *cons = btype->construction; /* TECH DEBT: simplest thing that works for E3 dwarf/halfling faction rules */ if (b && config_get_int("rules.dwarf_castles", 0) && strcmp(btype->_name, "castle") == 0) { unit *u = building_owner(b); if (u && u->faction->race == get_race(RC_HALFLING)) { i = bsize * 10 / 8; } } if (!cons || !cons->improvement) { return 0; } while (cons && cons->maxsize != -1 && i >= cons->maxsize) { i -= cons->maxsize; cons = cons->improvement; ++n; } return n; }
void save_special_items(unit *usrc) { unit *u; region *r = usrc->region; faction *fm = get_monsters(); static const race *rc_ghost; static int cache; if (rc_changed(&cache)) { rc_ghost = get_race(RC_TEMPLATE); } for (u = r->units; u; u = u->next) { if (u->faction == fm) { give_special_items(u, &usrc->items); return; } } u = create_unit(r, fm, 1, rc_ghost, 0, NULL, NULL); unit_setname(u, unit_getname(usrc)); if (usrc->number > 1) { /* some units have plural names, it would be neat if they aren't single: */ scale_number(u, 2); } set_racename(&u->attribs, "ghost"); give_special_items(u, &usrc->items); }
static void summarize_races(const summary *s, FILE *F, bool full) { int i; for (i = 0; i < MAXRACES; i++) { if (s->poprace[i] > 0) { const char *pad = " "; int lpad = (int)strlen(pad); const race *rc = get_race(i); const char *rcname = LOC(default_locale, rc_name_s(rc, NAME_PLURAL)); lpad -= count_umlaut(rcname); assert(lpad >= 0); if (full) { fputs(pad + lpad, F); fprintf(F, "%20s: ", rcname); fprintf(F, "%8d\n", s->poprace[i]); } else if (i != RC_TEMPLATE && i != RC_CLONE) { if (playerrace(rc)) { fputs(pad + lpad, F); fprintf(F, "%16s: ", rcname); fprintf(F, "%8d\n", s->poprace[i]); } } } } }
void drown(region * r) { if (fval(r->terrain, SEA_REGION)) { unit **up = up = &r->units; while (*up) { unit *u = *up; int amphibian_level = 0; if (u->ship || u_race(u) == get_race(RC_SPELL) || u->number == 0) { up = &u->next; continue; } if (amphibian_level) { int dead = damage_unit(u, "5d1", false, false); if (dead) { ADDMSG(&u->faction->msgs, msg_message("drown_amphibian_dead", "amount unit region", dead, u, r)); } else { ADDMSG(&u->faction->msgs, msg_message("drown_amphibian_nodead", "unit region", u, r)); } } else if (!(canswim(u) || canfly(u))) { scale_number(u, 0); ADDMSG(&u->faction->msgs, msg_message("drown", "unit region", u, r)); } if (*up == u) up = &u->next; } remove_empty_units_in_region(r); } }
/* wiederbeleben */ int sp_reanimate(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; int healable, j = 0; double c = 0.50 + 0.02 * power; double k = EFFECT_HEALING_SPELL * power; bool use_item = has_ao_healing(mage); message *msg; if (use_item) { k *= 2; c += 0.10; } healable = count_healable(b, fi); healable = (int)_min(k, healable); while (healable--) { fighter *tf = select_corpse(b, fi); if (tf != NULL && tf->side->casualties > 0 && u_race(tf->unit) != get_race(RC_DAEMON) && (chance(c))) { assert(tf->alive < tf->unit->number); /* t.fighter->person[].hp beginnt mit t.index = 0 zu z�hlen, * t.fighter->alive ist jedoch die Anzahl lebender in der Einheit, * also sind die hp von t.fighter->alive * t.fighter->hitpoints[t.fighter->alive-1] und der erste Tote * oder weggelaufene ist t.fighter->hitpoints[tf->alive] */ tf->person[tf->alive].hp = 2; ++tf->alive; ++tf->side->size[SUM_ROW]; ++tf->side->size[tf->unit->status + 1]; ++tf->side->healed; --tf->side->casualties; assert(tf->side->casualties >= 0); --tf->side->dead; assert(tf->side->dead >= 0); ++j; } } if (j <= 0) { level = j; } if (use_item) { msg = msg_message("reanimate_effect_1", "mage amount item", mage, j, get_resourcetype(R_AMULET_OF_HEALING)); } else { msg = msg_message("reanimate_effect_0", "mage amount", mage, j); } message_all(b, msg); msg_release(msg); return level; }
static void guardian_faction(plane * pl, int id) { region *r; faction *f = findfaction(id); if (!f) { f = calloc(1, sizeof(faction)); f->banner = _strdup("Sie dienen dem großen Wyrm"); f->passw = _strdup(itoa36(rng_int())); set_email(&f->email, "*****@*****.**"); f->name = _strdup("Igjarjuks Kundschafter"); f->race = get_race(RC_ILLUSION); f->age = turn; f->locale = get_locale("de"); f->options = want(O_COMPRESS) | want(O_REPORT) | want(O_COMPUTER) | want(O_ADRESSEN) | want(O_DEBUG); f->no = id; addlist(&factions, f); fhash(f); } if (f->race != get_race(RC_ILLUSION)) { assert(!"guardian id vergeben"); exit(0); } f->lastorders = turn; f->alive = true; for (r = regions; r; r = r->next) if (getplane(r) == pl && rterrain(r) != T_FIREWALL) { unit *u; freset(r, RF_ENCOUNTER); for (u = r->units; u; u = u->next) { if (u->faction == f) break; } if (u) continue; u = create_unit(r, f, 1, get_race(RC_GOBLIN), 0, NULL, NULL); set_string(&u->name, "Igjarjuks Auge"); i_change(&u->items, it_find("roi"), 1); set_order(&u->thisorder, NULL); fset(u, UFL_ANON_FACTION); set_money(u, 1000); } }
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; }
/* ------------------------------------------------------------- */ bool magic_lowskill(unit * u) { static const race *toad_rc; static int cache; if (rc_changed(&cache)) { toad_rc = get_race(RC_TOAD); } return u_race(u) == toad_rc; }
static order *monster_seeks_target(region * r, unit * u) { direction_t d; unit *target = NULL; int dist, dist2; direction_t i; region *nr; /* Das Monster sucht ein bestimmtes Opfer. Welches, steht * in einer Referenz/attribut * derzeit gibt es nur den alp */ switch (old_race(u_race(u))) { case RC_ALP: target = alp_target(u); break; default: assert(!"Seeker-Monster gibt kein Ziel an"); } /* TODO: prüfen, ob target überhaupt noch existiert... */ if (!target) { log_error("Monster '%s' hat kein Ziel!\n", unitname(u)); return NULL; /* this is a bug workaround! remove!! */ } if (r == target->region) { /* Wir haben ihn! */ if (u_race(u) == get_race(RC_ALP)) { alp_findet_opfer(u, r); } else { assert(!"Seeker-Monster hat keine Aktion fuer Ziel"); } return NULL; } /* Simpler Ansatz: Nachbarregion mit gerinster Distanz suchen. * Sinnvoll momentan nur bei Monstern, die sich nicht um das * Terrain kümmern. Nebelwände & Co machen derzeit auch nix... */ dist2 = distance(r, target->region); d = NODIRECTION; for (i = 0; i < MAXDIRECTIONS; i++) { nr = rconnect(r, i); assert(nr); dist = distance(nr, target->region); if (dist < dist2) { dist2 = dist; d = i; } } assert(d != NODIRECTION); return create_order(K_MOVE, u->faction->locale, "%s", LOC(u->faction->locale, directions[d])); }
static int _class_idx(void) { int result = p_ptr->pclass; if (result == CLASS_MONSTER) { race_t *race_ptr = get_race(); result = race_ptr->pseudo_class_idx; } return result; }
int sp_igjarjuk(castorder *co) { unit *u; fighter *fm = co->magician.fig, *fi; const race *rc = get_race(RC_WYRM); fi = summon_allies(fm, rc, 1); u = fi->unit; unit_setname(u, "Igjarjuk"); log_info("%s summons Igjarjuk in %s", unitname(fm->unit), regionname(u->region, 0)); return co->level; }
static int dragon_affinity_value(region * r, unit * u) { int m = all_money(r, u->faction); if (u_race(u) == get_race(RC_FIREDRAGON)) { return (int)(normalvariate(m, m / 2)); } else { return (int)(normalvariate(m, m / 4)); } }
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); } }
/** Talente von Dämonen verschieben sich. */ static void demon_skillchanges(void) { region *r; for (r = regions; r; r = r->next) { unit *u; for (u = r->units; u; u = u->next) { if (u_race(u) == get_race(RC_DAEMON)) { skill *sv = u->skills; int upchance = 15; int downchance = 10; if (fval(u, UFL_HUNGER)) { /* hungry demons only go down, never up in skill */ static int rule_hunger = -1; if (rule_hunger < 0) { rule_hunger = get_param_int(global.parameters, "hunger.demon.skill", 0); } if (rule_hunger) { upchance = 0; downchance = 15; } } while (sv != u->skills + u->skill_size) { int roll = rng_int() % 100; if (sv->level > 0 && roll < upchance + downchance) { int weeks = 1 + rng_int() % 3; if (roll < downchance) { reduce_skill(u, sv, weeks); if (sv->level < 1) { /* demons should never forget below 1 */ set_level(u, sv->id, 1); } } else { while (weeks--) learn_skill(u, sv->id, 1.0); } if (sv->old > sv->level) { if (verbosity >= 3) { log_printf(stdout, "%s dropped from %u to %u:%u in %s\n", unitname(u), sv->old, sv->level, sv->weeks, skillname(sv->id, NULL)); } } } ++sv; } } } } }
int skill_mod(const race * rc, skill_t sk, const struct terrain_type *terrain) { int result = 0; result = rc->bonus[sk]; if (rc == get_race(RC_DWARF)) { if (sk == SK_TACTICS) { if (terrain == newterrain(T_MOUNTAIN) || fval(terrain, ARCTIC_REGION)) ++result; } } else if (rc == get_race(RC_INSECT)) { if (terrain == newterrain(T_MOUNTAIN) || fval(terrain, ARCTIC_REGION)) --result; else if (terrain == newterrain(T_DESERT) || terrain == newterrain(T_SWAMP)) ++result; } return result; }
caster_info *get_caster_info(void) { caster_info *result = NULL; class_t *class_ptr = get_class(); race_t *race_ptr = get_race(); if (race_ptr->caster_info) /* Monster Races: Lich, Angel, Demon */ result = (race_ptr->caster_info)(); else if (class_ptr->caster_info) result = (class_ptr->caster_info)(); return result; }
/** Drachen und Seeschlangen können entstehen */ void spawn_dragons(void) { region *r; faction *monsters = get_or_create_monsters(); for (r = regions; r; r = r->next) { unit *u; if (fval(r->terrain, SEA_REGION) && rng_int() % 10000 < 1) { u = create_unit(r, monsters, 1, get_race(RC_SEASERPENT), 0, NULL, NULL); fset(u, UFL_ISNEW | UFL_MOVED); equip_unit(u, get_equipment("monster_seaserpent")); } if ((r->terrain == newterrain(T_GLACIER) || r->terrain == newterrain(T_SWAMP) || r->terrain == newterrain(T_DESERT)) && rng_int() % 10000 < (5 + 100 * chaosfactor(r))) { if (chance(0.80)) { u = create_unit(r, monsters, nrand(60, 20) + 1, get_race(RC_FIREDRAGON), 0, NULL, NULL); } else { u = create_unit(r, monsters, nrand(30, 20) + 1, get_race(RC_DRAGON), 0, NULL, NULL); } fset(u, UFL_ISNEW | UFL_MOVED); equip_unit(u, get_equipment("monster_dragon")); 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)); name_unit(u); /* add message to the region */ ADDMSG(&r->msgs, msg_message("sighting", "region race number", r, u_race(u), u->number)); } } }
/* familiars and toads are not migrants */ bool is_migrant(unit * u) { if (u_race(u) == u->faction->race) return false; if (fval(u_race(u), RCF_UNDEAD | RCF_ILLUSIONARY)) return false; if (is_familiar(u)) return false; if (u_race(u) == get_race(RC_TOAD)) return false; return true; }
static int _get_spell_table(spell_info* spells, int max) { int ct = 0; class_t *class_ptr = get_class(); race_t *race_ptr = get_race(); if (race_ptr->get_spells != NULL) /* Monster Races ... */ ct = (race_ptr->get_spells)(spells, max); else if (class_ptr->get_spells != NULL) ct = (class_ptr->get_spells)(spells, max); _add_extra_costs(spells, ct); return ct; }
void drown(region * r) { if (fval(r->terrain, SEA_REGION)) { unit **up = &r->units; while (*up) { unit *u = *up; if (!(u->ship || u_race(u) == get_race(RC_SPELL) || u->number == 0 || canswim(u) || canfly(u))) { scale_number(u, 0); ADDMSG(&u->faction->msgs, msg_message("drown", "unit region", u, r)); } up = &u->next; } remove_empty_units_in_region(r); } }
/* familiars and toads are not migrants */ bool is_migrant(unit * u) { static int cache; static const race *toad_rc; if (u_race(u) == u->faction->race) return false; if (fval(u_race(u), RCF_UNDEAD | RCF_ILLUSIONARY)) return false; if (is_familiar(u)) return false; if (rc_changed(&cache)) { toad_rc = get_race(RC_TOAD); } return u_race(u) != toad_rc; }
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 max_magicians(const faction * f) { static int rule, config, rc_cache; static const race *rc_elf; int m; if (config_changed(&config)) { rule = config_get_int("rules.maxskills.magic", 3); } m = rule; if (rc_changed(&rc_cache)) { rc_elf = get_race(RC_ELF); } if (f->race == rc_elf) { ++m; } return m; }
/** Talente von D�monen verschieben sich. */ static void demon_skillchanges(void) { region *r; static const race *rc_demon; static int rc_cache; if (rc_changed(&rc_cache)) { rc_demon = get_race(RC_DAEMON); } for (r = regions; r; r = r->next) { unit *u; for (u = r->units; u; u = u->next) { if (u_race(u) == rc_demon) { demon_skillchange(u); } } } }