static int limit_resource(const region * r, const resource_type * rtype) { char fname[64]; int result = -1; lua_State *L = (lua_State *)global.vm_state; strlcpy(fname, rtype->_name, sizeof(fname)); strlcat(fname, "_limit", sizeof(fname)); lua_getglobal(L, fname); if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)r, TOLUA_CAST "region"); if (lua_pcall(L, 1, 1, 0) != 0) { const char *error = lua_tostring(L, -1); log_error("limit(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error); lua_pop(L, 1); } else { result = (int)lua_tonumber(L, -1); lua_pop(L, 1); } } else { log_error("limit(%s) calling '%s': not a function.\n", regionname(r, NULL), fname); lua_pop(L, 1); } return result; }
static int lua_wage(const region * r, const faction * f, const race * rc, int in_turn) { lua_State *L = (lua_State *)global.vm_state; const char *fname = "wage"; int result = -1; lua_getglobal(L, fname); if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)r, TOLUA_CAST "region"); tolua_pushusertype(L, (void *)f, TOLUA_CAST "faction"); tolua_pushstring(L, rc ? rc->_name : 0); lua_pushinteger(L, in_turn); if (lua_pcall(L, 3, 1, 0) != 0) { const char *error = lua_tostring(L, -1); log_error("wage(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error); lua_pop(L, 1); } else { result = (int)lua_tonumber(L, -1); lua_pop(L, 1); } } else { log_error("wage(%s) calling '%s': not a function.\n", regionname(r, NULL), fname); lua_pop(L, 1); } return result; }
static void produce_resource(region * r, const resource_type * rtype, int norders) { lua_State *L = (lua_State *)global.vm_state; char fname[64]; strlcpy(fname, rtype->_name, sizeof(fname)); strlcat(fname, "_produce", sizeof(fname)); lua_getglobal(L, fname); if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)r, TOLUA_CAST "region"); lua_pushinteger(L, norders); if (lua_pcall(L, 2, 0, 0) != 0) { const char *error = lua_tostring(L, -1); log_error("produce(%s) calling '%s': %s.\n", regionname(r, NULL), fname, error); lua_pop(L, 1); } } else { log_error("produce(%s) calling '%s': not a function.\n", regionname(r, NULL), fname); lua_pop(L, 1); } }
region *new_region(int x, int y, struct plane *pl, int uid) { region *r; pnormalize(&x, &y, pl); r = rfindhash(x, y); if (r) { log_error("duplicate region discovered: %s(%d,%d)\n", regionname(r, NULL), x, y); if (r->units) log_error("duplicate region contains units\n"); return r; } r = calloc(1, sizeof(region)); r->x = x; r->y = y; r->uid = uid; r->age = 1; r->_plane = pl; rhash(r); hash_uid(r); if (last) addlist(&last, r); else addlist(®ions, r); last = r; assert(r->next == NULL); r->index = ++max_index; return r; }
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 tolua_region_tostring(lua_State * L) { region *self = (region *)tolua_tousertype(L, 1, 0); lua_pushstring(L, regionname(self, NULL)); return 1; }
/** 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)); } } } }
/** 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)); } } }
int read_borders(gamedata *data) { struct storage *store = data->store; for (;;) { int bid = 0; char zText[32]; region *from, *to; border_type *type; READ_TOK(store, zText, sizeof(zText)); if (!strcmp(zText, "end")) break; READ_INT(store, &bid); if (data->version < UIDHASH_VERSION) { int fx, fy, tx, ty; READ_INT(store, &fx); READ_INT(store, &fy); READ_INT(store, &tx); READ_INT(store, &ty); from = findregion(fx, fy); to = findregion(tx, ty); } else { int fid, tid; READ_INT(store, &fid); READ_INT(store, &tid); from = findregionbyid(fid); to = findregionbyid(tid); if (!to || !from) { log_warning("%s connection between incomplete regions %d and %d", zText, fid, tid); continue; } } type = find_bordertype(zText); if (type == NULL) { log_error("[read_borders] unknown connection type '%s' in %s\n", zText, regionname(from, NULL)); assert(type || !"connection type not registered"); } if (to == from && type && from) { direction_t dir = (direction_t)(rng_int() % MAXDIRECTIONS); region *r = rconnect(from, dir); log_error("[read_borders] invalid %s in %s\n", type->__name, regionname(from, NULL)); if (r != NULL) to = r; } if ((type->read && !type->write)) { log_warning("ignore invalid border '%s' between '%s' and '%s'\n", zText, regionname(from, 0), regionname(to, 0)); } else { connection *b = new_border(type, from, to); nextborder--; /* new_border erhöht den Wert */ b->id = bid; assert(bid <= nextborder); if (type->read) { type->read(b, data); } if (data->version < NOBORDERATTRIBS_VERSION) { attrib *a = NULL; int result = read_attribs(data, &a, b); if (border_convert_cb) { border_convert_cb(b, a); } while (a) { a_remove(&a, a); } if (result < 0) { return result; } } } } return 0; }