void cave_map_generator::cave_map_generator_job::place_passage(const passage& p) { const std::string& chance = p.cfg["chance"]; if(chance != "" && int(rng_()%100) < atoi(chance.c_str())) { return; } int windiness = p.cfg["windiness"]; double laziness = std::max<double>(1.0, p.cfg["laziness"].to_double()); passage_path_calculator calc(map_, params.wall_, laziness, windiness, rng_); pathfind::plain_route rt = a_star_search(p.src, p.dst, 10000.0, &calc, params.width_, params.height_); int width = std::max<int>(1, p.cfg["width"].to_int()); int jagged = p.cfg["jagged"]; for(std::vector<map_location>::const_iterator i = rt.steps.begin(); i != rt.steps.end(); ++i) { std::set<map_location> locs; build_chamber(*i,locs,width,jagged); for(std::set<map_location>::const_iterator j = locs.begin(); j != locs.end(); ++j) { set_terrain(*j, params.clear_); } } }
void cave_map_generator::place_castle(int starting_position, const map_location &loc) { if (starting_position != -1) { set_terrain(loc, keep_); t_translation::coordinate coord = { loc.x + gamemap::default_border, loc.y + gamemap::default_border }; starting_positions_[starting_position] = coord; } map_location adj[6]; get_adjacent_tiles(loc,adj); for(size_t n = 0; n != 6; ++n) { set_terrain(adj[n],castle_); } }
void cave_map_generator::cave_map_generator_job::place_chamber(const chamber& c) { for(std::set<map_location>::const_iterator i = c.locs.begin(); i != c.locs.end(); ++i) { set_terrain(*i,params.clear_); } if (c.items == nullptr || c.locs.empty()) return; size_t index = 0; for (const config::any_child &it : c.items->all_children_range()) { config cfg = it.cfg; config &filter = cfg.child("filter"); config* object_filter = nullptr; if (config &object = cfg.child("object")) { if (config &of = object.child("filter")) object_filter = &of; } if (!it.cfg["same_location_as_previous"].to_bool()) { index = rng_()%c.locs.size(); } std::string loc_var = it.cfg["store_location_as"]; std::set<map_location>::const_iterator loc = c.locs.begin(); std::advance(loc,index); cfg["x"] = loc->x + 1; cfg["y"] = loc->y + 1; if (filter) { filter["x"] = loc->x + 1; filter["y"] = loc->y + 1; } if (object_filter) { (*object_filter)["x"] = loc->x + 1; (*object_filter)["y"] = loc->y + 1; } // If this is a side, place a castle for the side if (it.key == "side" && !it.cfg["no_castle"].to_bool()) { place_castle(it.cfg["side"].to_int(-1), *loc); } res_.add_child(it.key, cfg); if(!loc_var.empty()) { config &temp = res_.add_child("event"); temp["name"] = "prestart"; config &xcfg = temp.add_child("set_variable"); xcfg["name"] = loc_var + "_x"; xcfg["value"] = loc->x + 1; config &ycfg = temp.add_child("set_variable"); ycfg["name"] = loc_var + "_y"; ycfg["value"] = loc->y + 1; } } }
void cave_map_generator::cave_map_generator_job::place_castle(int starting_position, const map_location &loc) { if (starting_position != -1) { set_terrain(loc, params.keep_); t_translation::coordinate coord( loc.x + gamemap::default_border , loc.y + gamemap::default_border); starting_positions_.insert(t_translation::tstarting_positions::value_type(std::to_string(starting_position), coord)); } map_location adj[6]; get_adjacent_tiles(loc,adj); for(size_t n = 0; n != 6; ++n) { set_terrain(adj[n], params.castle_); } }
void setup() { set_room_size( 20 ); set_terrain( "tutorial_mountain" ); set_short( "tree in the mountains" ); set_long( "This tree has defied all the odds, and grows straight and " "tall in the blustery wastes." ); add_extra_look( this_object() ); add_property( "climate", ({ -40, 50, 40 }) );
void setup() { set_terrain( "tutorial_mountain" ); set_short( "mountain cabin attic" ); set_long( "This is the second floor of a comfortable mountain cabin. " "The bed occupying most of this room would seem to indicate " "that this is a bedroom.\n" ); add_item( "bed", ({ "long", "A big king-sized bed with a nice, thick, comforter on top.", "position", "the bed" }), 0 );
bool xmove::stick_on_ground() { assert(m_agent->parent); xvec2f_t pos; wyc::xcollision_agent *collidee = _detect_stand_point(pos); if(!collidee) return false; m_agent->set_position(pos.x, pos.y); m_agent->update_aabb(); set_terrain(collidee); return true; }
void setup() { set_terrain( "tutorial_desert" ); set_short( "desert oasis" ); set_long( "The trees in this oasis provide welcome relief from the harsh " "sunlight of the desert.\n" ); add_item( "sand", "It's sand. There isn't much to say about it other than " "that it's much moister here than elsewhere in the desert." ); add_item( "tree", "The palm trees grow majestically all around you, " "providing all the shade you could want." ); add_property( "climate", ({ 10, -100, -100 }) );
void setup() { set_terrain( "tutorial_desert" ); set_short( "outside tent" ); set_long( "This is just outside the front flap of a canvas tent, set " "in the middle of a huge desert waste. Nothing but sand as far " "as the eye can see.\n" ); add_item( "sand", "It's sand. There isn't much to say about it." ); add_item( "tent", "This is a plain, white canvas tent, that reflects the harsh " "glare of the sun harmlessly away from its occupants." ); add_exit( "tent", PATH "foyer", "corridor" ); add_property( "climate", ({ 40, -100, -100 }) );
void gamemap::overlay(const gamemap& m, const config& rules_cfg, int xpos, int ypos, bool border) { const config::const_child_itors &rules = rules_cfg.child_range("rule"); int actual_border = (m.border_size() == border_size()) && border ? border_size() : 0; const int xstart = std::max<int>(-actual_border, -xpos - actual_border); const int ystart = std::max<int>(-actual_border, -ypos - actual_border - ((xpos & 1) ? 1 : 0)); const int xend = std::min<int>(m.w() + actual_border, w() + actual_border - xpos); const int yend = std::min<int>(m.h() + actual_border, h() + actual_border - ypos); for(int x1 = xstart; x1 < xend; ++x1) { for(int y1 = ystart; y1 < yend; ++y1) { const int x2 = x1 + xpos; const int y2 = y1 + ypos + ((xpos & 1) && (x1 & 1) ? 1 : 0); const t_translation::t_terrain t = m[x1][y1 + m.border_size_]; const t_translation::t_terrain current = (*this)[x2][y2 + border_size_]; if(t == t_translation::FOGGED || t == t_translation::VOID_TERRAIN) { continue; } // See if there is a matching rule config::const_child_iterator rule = rules.first; for( ; rule != rules.second; ++rule) { static const std::string src_key = "old", dst_key = "new"; const config &cfg = *rule; const t_translation::t_list& src = t_translation::read_list(cfg[src_key]); if(!src.empty() && t_translation::terrain_matches(current, src) == false) { continue; } const t_translation::t_list& dst = t_translation::read_list(cfg[dst_key]); if(!dst.empty() && t_translation::terrain_matches(t, dst) == false) { continue; } break; } if (rule != rules.second) { const config &cfg = *rule; const t_translation::t_list& terrain = t_translation::read_list(cfg["terrain"]); terrain_type_data::tmerge_mode mode = terrain_type_data::BOTH; if (cfg["layer"] == "base") { mode = terrain_type_data::BASE; } else if (cfg["layer"] == "overlay") { mode = terrain_type_data::OVERLAY; } t_translation::t_terrain new_terrain = t; if(!terrain.empty()) { new_terrain = terrain[0]; } if (!cfg["use_old"].to_bool()) { set_terrain(map_location(x2, y2), new_terrain, mode, cfg["replace_if_failed"].to_bool()); } } else { set_terrain(map_location(x2,y2),t); } } } for(const map_location* pos = m.startingPositions_; pos != m.startingPositions_ + sizeof(m.startingPositions_)/sizeof(*m.startingPositions_); ++pos) { if(pos->valid()) { startingPositions_[pos - m.startingPositions_] = *pos; } } }
xcollision_agent* xmove::fall (float &t, xvec2f_t &speed, float accy, unsigned extra_filter, unsigned max_iteration) { m_kpos.clear(); if( m_terrain || speed.y>0 || (speed.y==0 && accy==0) ) { return 0; } float tfall, tleft = 0; if(accy>0) { tfall = -speed.y / accy; if(tfall<t) { tleft = t-tfall; t = tfall; } } xvec2f_t pos = m_agent->get_position(), offset, collide_normal; float dt; xcollision_agent *collidee = 0; unsigned group_filter = ms_standon_filter | extra_filter; bool is_on_ground = false; for(unsigned iteration = 0; iteration<max_iteration; ++iteration) { offset.x = speed.x * t; offset.y = speed.y * t + 0.5f * accy * t * t; collidee = _detect_collision(offset,group_filter,dt,collide_normal,ms_platform_filter); if(collidee) { // hit something offset.x *= dt; offset.y *= dt; pos += offset; tfall = solve_quadratic(0.5f*accy, speed.y, -offset.y); t -= tfall; speed.y += accy * tfall; if(collidee->get_mask() & ms_standon_filter) { // hit terrain speed.x = 0; if(collide_normal.y < EPSILON) { pos.x += ms_drawback * collide_normal.x; pos.y += ms_drawback * collide_normal.y; m_agent->set_position(pos.x, pos.y); PUSH_KPOS_WITH_SPEED(m_kpos, tfall, pos.x, pos.y, speed.x, speed.y); continue; } // fall on ground pos.y += ms_drawback; speed.y= 0; is_on_ground = true; } } else { speed.y += accy * t; pos += offset; tfall = t; t = 0; } m_agent->set_position(pos.x,pos.y); if(is_on_ground) set_terrain(collidee); PUSH_KPOS_WITH_SPEED(m_kpos, tfall, pos.x, pos.y, speed.x, speed.y); break; } // for t += tleft; m_agent->update_aabb(); return collidee; }
xcollision_agent* xmove::walk (float &t, float speed, unsigned extra_filter, unsigned max_iteration) { m_kpos.clear(); if(!m_terrain || !speed) { // not on ground return 0; } char d, s; if(speed<0) { d = -1; s = -1; } else { d = 1; s = 0; } xvec2f_t kp = m_agent->get_position(); float spdx, spdy; xcollision_agent *collidee = 0; unsigned group_filter = ms_standon_filter | extra_filter; for(unsigned iteration = 0; iteration<max_iteration; ++iteration) { const xvec2f_t &terrain_normal = m_terrain->get_slope_normal(); if(m_apex>0 && m_cursec!=m_apex) // move on slope { spdx = terrain_normal.y * speed; spdy = -terrain_normal.x * speed; } else { spdx = speed; spdy = 0; } xvec2f_t offset; offset.set(m_inflections[m_cursec+s]-m_agent->get_position().x, 0); float tmove = offset.x/spdx; xvec2f_t collide_normal; float dt; if(tmove>0) { bool in_same_section = tmove>t; if(in_same_section) { tmove = t; offset.x = tmove * spdx; } offset.y = tmove * spdy; collidee = _detect_collision(offset, group_filter, dt, collide_normal); if(!collidee) { t -= tmove; kp.x += offset.x; kp.y += offset.y; m_agent->set_position(kp.x,kp.y); PUSH_KPOS_WALK(m_kpos, tmove, kp.x, kp.y); if(in_same_section) { break; } } } if(!collidee) { m_cursec += d; if(m_cursec == 0 || m_cursec == m_cntsec) // leave terrain { collidee = _detect_stand_point(kp); if(collidee && m_agent->get_position().y-kp.y<=ms_stair_height) { m_agent->set_position(kp.x, kp.y); PUSH_KPOS_WALK(m_kpos, 0, kp.x, kp.y); set_terrain(collidee); } else // falling { m_terrain = 0; collidee = 0; break; } } collidee = 0; continue; } tmove *= dt; t -= tmove; offset *= dt; kp.x += offset.x; kp.y += offset.y; // collide special objects if(collidee->get_mask() & extra_filter) { m_agent->set_position(kp.x,kp.y); PUSH_KPOS_WALK(m_kpos, tmove, kp.x, kp.y); break; } // collide terrain if(collide_normal.x && collide_normal.y/std::fabs(collide_normal.x)<ms_slope_can_stand) { // steep slope or stair float stair_y = collidee->get_upper().y; int type = collidee->agent_type(); if(type==AGENT_SLOPE_LEFT_BOTTOM || type==AGENT_SLOPE_RIGHT_BOTTOM) { const xvec2f_t &collidee_normal = collidee->get_slope_normal(); if((kp.x-collidee->get_position().x)*collidee_normal.x>0) stair_y = collidee->get_lower().y; } if(stair_y - (kp.y-m_agent->get_radius().y) > ms_stair_height) { kp.x -= ms_drawback*terrain_normal.y*d; kp.y += ms_drawback*terrain_normal.x*d; m_agent->set_position(kp.x,kp.y); PUSH_KPOS_WALK(m_kpos, tmove, kp.x, kp.y); break; } PUSH_KPOS_WALK(m_kpos, tmove, kp.x, kp.y); kp.x += ms_drawback*d; kp.y = stair_y+m_agent->get_radius().y+ms_drawback; } else { PUSH_KPOS_WALK(m_kpos, tmove, kp.x, kp.y); kp.y += ms_drawback; } m_agent->set_position(kp.x,kp.y); PUSH_KPOS_WALK(m_kpos, 0, kp.x, kp.y); set_terrain(collidee); collidee = 0; } // for m_agent->update_aabb(); return collidee; }