bool can_construct( const construction &con, const tripoint &p ) { // see if the special pre-function checks out bool place_okay = con.pre_special( p ); // see if the terrain type checks out if( !con.pre_terrain.empty() ) { if( con.pre_is_furniture ) { furn_id f = furn_id( con.pre_terrain ); place_okay &= g->m.furn( p ) == f; } else { ter_id t = ter_id( con.pre_terrain ); place_okay &= g->m.ter( p ) == t; } } // see if the flags check out place_okay &= std::all_of( con.pre_flags.begin(), con.pre_flags.end(), [&p] ( const std::string &flag ) { return g->m.has_flag( flag, p ); }); // make sure the construction would actually do something if( !con.post_terrain.empty() ) { if( con.post_is_furniture ) { furn_id f = furn_id( con.post_terrain ); place_okay &= g->m.furn( p ) != f; } else { ter_id t = ter_id( con.post_terrain ); place_okay &= g->m.ter( p ) != t; } } return place_okay; }
void prepare_test() { player &dummy = g->u; // Remove first worn item until there are none left. std::list<item> temp; while( dummy.takeoff( dummy.i_at( -2 ), &temp ) ); for( trait_id tr : dummy.get_mutations() ) { dummy.unset_mutation( tr ); } // Prevent spilling, but don't cause encumbrance if( !dummy.has_trait( trait_id( "DEBUG_STORAGE" ) ) ) { dummy.set_mutation( trait_id( "DEBUG_STORAGE" ) ); } // Make stats nominal. dummy.str_cur = 8; dummy.dex_cur = 8; dummy.int_cur = 8; dummy.per_cur = 8; const tripoint spot( 60, 60, 0 ); dummy.setpos( spot ); g->m.ter_set( spot, ter_id( "t_dirt" ) ); g->m.furn_set( spot, furn_id( "f_null" ) ); g->m.i_clear( spot ); }
statistics find_inner( std::string type, std::string terrain, int delay, bool smooth ) { statistics efficiency; for( int i = 0; i < 10; i++) { efficiency.add( test_efficiency( vproto_id( type ), ter_id( terrain ), delay, -1, smooth ) ); } return efficiency; }
efficiency_stat find_inner( const std::string &type, int &expected_mass, const std::string &terrain, const int delay, const bool smooth, const bool test_mass = false ) { efficiency_stat efficiency; for( int i = 0; i < 10; i++ ) { efficiency.add( test_efficiency( vproto_id( type ), expected_mass, ter_id( terrain ), delay, -1, smooth, test_mass ) ); } return efficiency; }
vehicle *setup_drag_test( const vproto_id &veh_id ) { clear_game_drag( ter_id( "t_pavement" ) ); const tripoint map_starting_point( 60, 60, 0 ); vehicle *veh_ptr = g->m.add_vehicle( veh_id, map_starting_point, -90, 100, 0 ); REQUIRE( veh_ptr != nullptr ); if( veh_ptr == nullptr ) { return nullptr; } // start the engines, close the doors veh_ptr->start_engines(); const auto doors = veh_ptr->get_avail_parts( "OPENABLE" ); for( const vpart_reference vp : doors ) { const size_t door = vp.part_index(); veh_ptr->close( door ); } veh_ptr->refresh_insides(); return veh_ptr; }
ter_t null_terrain_t() { ter_t new_terrain; new_terrain.id = "t_null"; new_terrain.name = _("nothing"); new_terrain.sym = ' '; new_terrain.color = c_white; new_terrain.movecost = 2; new_terrain.trap = tr_null; new_terrain.trap_id_str = ""; new_terrain.transparent = true; new_terrain.set_flag("TRANSPARENT"); new_terrain.set_flag("DIGGABLE"); new_terrain.examine = iexamine_function_from_string("none"); new_terrain.harvest_season = 0; new_terrain.harvestable = ""; new_terrain.transforms_into = "t_null"; new_terrain.roof = "t_null"; new_terrain.loadid = ter_id( 0 ); new_terrain.open = ""; new_terrain.close = ""; new_terrain.max_volume = MAX_VOLUME_IN_SQUARE; return new_terrain; }
void mapbuffer::load() { if (!master_game) { debugmsg("Can't load mapbuffer without a master_game"); return; } std::map<tripoint, submap*>::iterator it; std::ifstream fin; fin.open("save/maps.txt"); if (!fin.is_open()) return; int itx, ity, t, d, a, num_submaps, num_loaded = 0; item it_tmp; std::string databuff; fin >> num_submaps; while (!fin.eof()) { if (num_loaded % 100 == 0) popup_nowait(_("Please wait as the map loads [%d/%d]"), num_loaded, num_submaps); int locx, locy, locz, turn; submap* sm = new submap; fin >> locx >> locy >> locz >> turn; sm->turn_last_touched = turn; int turndif = (master_game ? int(master_game->turn) - turn : 0); if (turndif < 0) turndif = 0; // Load terrain for (int j = 0; j < SEEY; j++) { for (int i = 0; i < SEEX; i++) { int tmpter; fin >> tmpter; sm->ter[i][j] = ter_id(tmpter); sm->frn[i][j] = f_null; sm->itm[i][j].clear(); sm->trp[i][j] = tr_null; //sm->fld[i][j] = field(); //not needed now sm->graf[i][j] = graffiti(); } } // Load irradiation for (int j = 0; j < SEEY; j++) { for (int i = 0; i < SEEX; i++) { int radtmp; fin >> radtmp; radtmp -= int(turndif / 100); // Radiation slowly decays if (radtmp < 0) radtmp = 0; sm->rad[i][j] = radtmp; } } // Load items and traps and fields and spawn points and vehicles std::string string_identifier; do { fin >> string_identifier; // "----" indicates end of this submap t = 0; if (string_identifier == "I") { fin >> itx >> ity; getline(fin, databuff); // Clear out the endline getline(fin, databuff); it_tmp.load_info(databuff, master_game); sm->itm[itx][ity].push_back(it_tmp); if (it_tmp.active) sm->active_item_count++; } else if (string_identifier == "C") { getline(fin, databuff); // Clear out the endline getline(fin, databuff); int index = sm->itm[itx][ity].size() - 1; it_tmp.load_info(databuff, master_game); sm->itm[itx][ity][index].put_in(it_tmp); if (it_tmp.active) sm->active_item_count++; } else if (string_identifier == "T") { fin >> itx >> ity >> t; sm->trp[itx][ity] = trap_id(t); } else if (string_identifier == "f") {
void set_ter_ids() { t_null = ter_id( "t_null" ); t_hole = ter_id( "t_hole" ); t_dirt = ter_id( "t_dirt" ); t_sand = ter_id( "t_sand" ); t_clay = ter_id( "t_clay" ); t_dirtmound = ter_id( "t_dirtmound" ); t_pit_shallow = ter_id( "t_pit_shallow" ); t_pit = ter_id( "t_pit" ); t_pit_corpsed = ter_id( "t_pit_corpsed" ); t_pit_covered = ter_id( "t_pit_covered" ); t_pit_spiked = ter_id( "t_pit_spiked" ); t_pit_spiked_covered = ter_id( "t_pit_spiked_covered" ); t_pit_glass = ter_id( "t_pit_glass" ); t_pit_glass_covered = ter_id( "t_pit_glass_covered" ); t_rock_floor = ter_id( "t_rock_floor" ); t_grass = ter_id( "t_grass" ); t_metal_floor = ter_id( "t_metal_floor" ); t_pavement = ter_id( "t_pavement" ); t_pavement_y = ter_id( "t_pavement_y" ); t_sidewalk = ter_id( "t_sidewalk" ); t_concrete = ter_id( "t_concrete" ); t_thconc_floor = ter_id( "t_thconc_floor" ); t_thconc_floor_olight = ter_id( "t_thconc_floor_olight" ); t_strconc_floor = ter_id( "t_strconc_floor" ); t_floor = ter_id( "t_floor" ); t_floor_waxed = ter_id( "t_floor_waxed" ); t_dirtfloor = ter_id( "t_dirtfloor" ); t_carpet_red = ter_id( "t_carpet_red" ); t_carpet_yellow = ter_id( "t_carpet_yellow" ); t_carpet_purple = ter_id( "t_carpet_purple" ); t_carpet_green = ter_id( "t_carpet_green" ); t_linoleum_white = ter_id( "t_linoleum_white" ); t_linoleum_gray = ter_id( "t_linoleum_gray" ); t_grate = ter_id( "t_grate" ); t_slime = ter_id( "t_slime" ); t_bridge = ter_id( "t_bridge" ); t_utility_light = ter_id( "t_utility_light" ); t_wall_log_half = ter_id( "t_wall_log_half" ); t_wall_log = ter_id( "t_wall_log" ); t_wall_log_chipped = ter_id( "t_wall_log_chipped" ); t_wall_log_broken = ter_id( "t_wall_log_broken" ); t_palisade = ter_id( "t_palisade" ); t_palisade_gate = ter_id( "t_palisade_gate" ); t_palisade_gate_o = ter_id( "t_palisade_gate_o" ); t_wall_half = ter_id( "t_wall_half" ); t_wall_wood = ter_id( "t_wall_wood" ); t_wall_wood_chipped = ter_id( "t_wall_wood_chipped" ); t_wall_wood_broken = ter_id( "t_wall_wood_broken" ); t_wall = ter_id( "t_wall" ); t_concrete_wall = ter_id( "t_concrete_wall" ); t_brick_wall = ter_id( "t_brick_wall" ); t_wall_metal = ter_id( "t_wall_metal" ); t_wall_glass = ter_id( "t_wall_glass" ); t_wall_glass_alarm = ter_id( "t_wall_glass_alarm" ); t_reinforced_glass = ter_id( "t_reinforced_glass" ); t_reinforced_door_glass_c = ter_id( "t_reinforced_door_glass_c" ); t_reinforced_door_glass_o = ter_id( "t_reinforced_door_glass_o" ); t_bars = ter_id( "t_bars" ); t_reb_cage = ter_id( "t_reb_cage" ); t_wall_b = ter_id( "t_wall_b" ); t_wall_g = ter_id( "t_wall_g" ); t_wall_p = ter_id( "t_wall_p" ); t_wall_r = ter_id( "t_wall_r" ); t_wall_w = ter_id( "t_wall_w" ); t_door_c = ter_id( "t_door_c" ); t_door_c_peep = ter_id( "t_door_c_peep" ); t_door_b = ter_id( "t_door_b" ); t_door_b_peep = ter_id( "t_door_b_peep" ); t_door_o = ter_id( "t_door_o" ); t_door_o_peep = ter_id( "t_door_o_peep" ); t_rdoor_c = ter_id( "t_rdoor_c" ); t_rdoor_b = ter_id( "t_rdoor_b" ); t_rdoor_o = ter_id( "t_rdoor_o" ); t_door_locked_interior = ter_id( "t_door_locked_interior" ); t_door_locked = ter_id( "t_door_locked" ); t_door_locked_peep = ter_id( "t_door_locked_peep" ); t_door_locked_alarm = ter_id( "t_door_locked_alarm" ); t_door_frame = ter_id( "t_door_frame" ); t_mdoor_frame = ter_id( "t_mdoor_frame" ); t_chaingate_l = ter_id( "t_chaingate_l" ); t_fencegate_c = ter_id( "t_fencegate_c" ); t_fencegate_o = ter_id( "t_fencegate_o" ); t_chaingate_c = ter_id( "t_chaingate_c" ); t_chaingate_o = ter_id( "t_chaingate_o" ); t_door_boarded = ter_id( "t_door_boarded" ); t_door_boarded_damaged = ter_id( "t_door_boarded_damaged" ); t_door_boarded_peep = ter_id( "t_door_boarded_peep" ); t_rdoor_boarded = ter_id( "t_rdoor_boarded" ); t_rdoor_boarded_damaged = ter_id( "t_rdoor_boarded_damaged" ); t_door_boarded_damaged_peep = ter_id( "t_door_boarded_damaged_peep" ); t_door_metal_c = ter_id( "t_door_metal_c" ); t_door_metal_o = ter_id( "t_door_metal_o" ); t_door_metal_locked = ter_id( "t_door_metal_locked" ); t_door_metal_pickable = ter_id( "t_door_metal_pickable" ); t_door_bar_c = ter_id( "t_door_bar_c" ); t_door_bar_o = ter_id( "t_door_bar_o" ); t_door_bar_locked = ter_id( "t_door_bar_locked" ); t_door_glass_c = ter_id( "t_door_glass_c" ); t_door_glass_o = ter_id( "t_door_glass_o" ); t_door_glass_frosted_c = ter_id( "t_door_glass_frosted_c" ); t_door_glass_frosted_o = ter_id( "t_door_glass_frosted_o" ); t_portcullis = ter_id( "t_portcullis" ); t_recycler = ter_id( "t_recycler" ); t_window = ter_id( "t_window" ); t_window_taped = ter_id( "t_window_taped" ); t_window_domestic = ter_id( "t_window_domestic" ); t_window_domestic_taped = ter_id( "t_window_domestic_taped" ); t_window_open = ter_id( "t_window_open" ); t_curtains = ter_id( "t_curtains" ); t_window_alarm = ter_id( "t_window_alarm" ); t_window_alarm_taped = ter_id( "t_window_alarm_taped" ); t_window_empty = ter_id( "t_window_empty" ); t_window_frame = ter_id( "t_window_frame" ); t_window_boarded = ter_id( "t_window_boarded" ); t_window_boarded_noglass = ter_id( "t_window_boarded_noglass" ); t_window_reinforced = ter_id( "t_window_reinforced" ); t_window_reinforced_noglass = ter_id( "t_window_reinforced_noglass" ); t_window_enhanced = ter_id( "t_window_enhanced" ); t_window_enhanced_noglass = ter_id( "t_window_enhanced_noglass" ); t_window_bars_alarm = ter_id( "t_window_bars_alarm" ); t_window_bars = ter_id( "t_window_bars" ); t_window_stained_green = ter_id( "t_window_stained_green" ); t_window_stained_red = ter_id( "t_window_stained_red" ); t_window_stained_blue = ter_id( "t_window_stained_blue" ); t_window_no_curtains = ter_id( "t_window_no_curtains" ); t_window_no_curtains_open = ter_id( "t_window_no_curtains_open" ); t_window_no_curtains_taped = ter_id( "t_window_no_curtains_taped" ); t_rock = ter_id( "t_rock" ); t_fault = ter_id( "t_fault" ); t_paper = ter_id( "t_paper" ); t_rock_wall = ter_id( "t_rock_wall" ); t_rock_wall_half = ter_id( "t_rock_wall_half" ); t_tree = ter_id( "t_tree" ); t_tree_young = ter_id( "t_tree_young" ); t_tree_apple = ter_id( "t_tree_apple" ); t_tree_apple_harvested = ter_id( "t_tree_apple_harvested" ); t_tree_coffee = ter_id( "t_tree_coffee" ); t_tree_coffee_harvested = ter_id( "t_tree_coffee_harvested" ); t_tree_pear = ter_id( "t_tree_pear" ); t_tree_pear_harvested = ter_id( "t_tree_pear_harvested" ); t_tree_cherry = ter_id( "t_tree_cherry" ); t_tree_cherry_harvested = ter_id( "t_tree_cherry_harvested" ); t_tree_peach = ter_id( "t_tree_peach" ); t_tree_peach_harvested = ter_id( "t_tree_peach_harvested" ); t_tree_apricot = ter_id( "t_tree_apricot" ); t_tree_apricot_harvested = ter_id( "t_tree_apricot_harvested" ); t_tree_plum = ter_id( "t_tree_plum" ); t_tree_plum_harvested = ter_id( "t_tree_plum_harvested" ); t_tree_pine = ter_id( "t_tree_pine" ); t_tree_blackjack = ter_id( "t_tree_blackjack" ); t_tree_birch = ter_id( "t_tree_birch" ); t_tree_willow = ter_id( "t_tree_willow" ); t_tree_maple = ter_id( "t_tree_maple" ); t_tree_maple_tapped = ter_id( "t_tree_maple_tapped" ); t_tree_deadpine = ter_id( "t_tree_deadpine" ); t_tree_hickory = ter_id( "t_tree_hickory" ); t_tree_hickory_dead = ter_id( "t_tree_hickory_dead" ); t_tree_hickory_harvested = ter_id( "t_tree_hickory_harvested" ); t_underbrush = ter_id( "t_underbrush" ); t_shrub = ter_id( "t_shrub" ); t_shrub_blueberry = ter_id( "t_shrub_blueberry" ); t_shrub_strawberry = ter_id( "t_shrub_strawberry" ); t_trunk = ter_id( "t_trunk" ); t_stump = ter_id( "t_stump" ); t_root_wall = ter_id( "t_root_wall" ); t_wax = ter_id( "t_wax" ); t_floor_wax = ter_id( "t_floor_wax" ); t_fence = ter_id( "t_fence" ); t_chainfence = ter_id( "t_chainfence" ); t_chainfence_posts = ter_id( "t_chainfence_posts" ); t_fence_post = ter_id( "t_fence_post" ); t_fence_wire = ter_id( "t_fence_wire" ); t_fence_barbed = ter_id( "t_fence_barbed" ); t_fence_rope = ter_id( "t_fence_rope" ); t_railing = ter_id( "t_railing" ); t_marloss = ter_id( "t_marloss" ); t_fungus_floor_in = ter_id( "t_fungus_floor_in" ); t_fungus_floor_sup = ter_id( "t_fungus_floor_sup" ); t_fungus_floor_out = ter_id( "t_fungus_floor_out" ); t_fungus_wall = ter_id( "t_fungus_wall" ); t_fungus_mound = ter_id( "t_fungus_mound" ); t_fungus = ter_id( "t_fungus" ); t_shrub_fungal = ter_id( "t_shrub_fungal" ); t_tree_fungal = ter_id( "t_tree_fungal" ); t_tree_fungal_young = ter_id( "t_tree_fungal_young" ); t_marloss_tree = ter_id( "t_marloss_tree" ); t_water_sh = ter_id( "t_water_sh" ); t_water_dp = ter_id( "t_water_dp" ); t_swater_sh = ter_id( "t_swater_sh" ); t_swater_dp = ter_id( "t_swater_dp" ); t_water_pool = ter_id( "t_water_pool" ); t_sewage = ter_id( "t_sewage" ); t_lava = ter_id( "t_lava" ); t_sandbox = ter_id( "t_sandbox" ); t_slide = ter_id( "t_slide" ); t_monkey_bars = ter_id( "t_monkey_bars" ); t_backboard = ter_id( "t_backboard" ); t_gas_pump = ter_id( "t_gas_pump" ); t_gas_pump_smashed = ter_id( "t_gas_pump_smashed" ); t_diesel_pump = ter_id( "t_diesel_pump" ); t_diesel_pump_smashed = ter_id( "t_diesel_pump_smashed" ); t_atm = ter_id( "t_atm" ); t_generator_broken = ter_id( "t_generator_broken" ); t_missile = ter_id( "t_missile" ); t_missile_exploded = ter_id( "t_missile_exploded" ); t_radio_tower = ter_id( "t_radio_tower" ); t_radio_controls = ter_id( "t_radio_controls" ); t_console_broken = ter_id( "t_console_broken" ); t_console = ter_id( "t_console" ); t_gates_mech_control = ter_id( "t_gates_mech_control" ); t_gates_control_brick = ter_id( "t_gates_control_brick" ); t_gates_control_concrete = ter_id( "t_gates_control_concrete" ); t_barndoor = ter_id( "t_barndoor" ); t_palisade_pulley = ter_id( "t_palisade_pulley" ); t_gates_control_metal = ter_id( "t_gates_control_metal" ); t_sewage_pipe = ter_id( "t_sewage_pipe" ); t_sewage_pump = ter_id( "t_sewage_pump" ); t_centrifuge = ter_id( "t_centrifuge" ); t_column = ter_id( "t_column" ); t_vat = ter_id( "t_vat" ); t_rootcellar = ter_id( "t_rootcellar" ); t_cvdbody = ter_id( "t_cvdbody" ); t_cvdmachine = ter_id( "t_cvdmachine" ); t_stairs_down = ter_id( "t_stairs_down" ); t_stairs_up = ter_id( "t_stairs_up" ); t_manhole = ter_id( "t_manhole" ); t_ladder_up = ter_id( "t_ladder_up" ); t_ladder_down = ter_id( "t_ladder_down" ); t_slope_down = ter_id( "t_slope_down" ); t_slope_up = ter_id( "t_slope_up" ); t_rope_up = ter_id( "t_rope_up" ); t_manhole_cover = ter_id( "t_manhole_cover" ); t_card_science = ter_id( "t_card_science" ); t_card_military = ter_id( "t_card_military" ); t_card_reader_broken = ter_id( "t_card_reader_broken" ); t_slot_machine = ter_id( "t_slot_machine" ); t_elevator_control = ter_id( "t_elevator_control" ); t_elevator_control_off = ter_id( "t_elevator_control_off" ); t_elevator = ter_id( "t_elevator" ); t_pedestal_wyrm = ter_id( "t_pedestal_wyrm" ); t_pedestal_temple = ter_id( "t_pedestal_temple" ); t_rock_red = ter_id( "t_rock_red" ); t_rock_green = ter_id( "t_rock_green" ); t_rock_blue = ter_id( "t_rock_blue" ); t_floor_red = ter_id( "t_floor_red" ); t_floor_green = ter_id( "t_floor_green" ); t_floor_blue = ter_id( "t_floor_blue" ); t_switch_rg = ter_id( "t_switch_rg" ); t_switch_gb = ter_id( "t_switch_gb" ); t_switch_rb = ter_id( "t_switch_rb" ); t_switch_even = ter_id( "t_switch_even" ); t_covered_well = ter_id( "t_covered_well" ); t_water_pump = ter_id( "t_water_pump" ); t_conveyor = ter_id( "t_conveyor" ); t_machinery_light = ter_id( "t_machinery_light" ); t_machinery_heavy = ter_id( "t_machinery_heavy" ); t_machinery_old = ter_id( "t_machinery_old" ); t_machinery_electronic = ter_id( "t_machinery_electronic" ); t_open_air = ter_id( "t_open_air" ); t_plut_generator = ter_id( "t_plut_generator" ); t_pavement_bg_dp = ter_id( "t_pavement_bg_dp" ); t_pavement_y_bg_dp = ter_id( "t_pavement_y_bg_dp" ); t_sidewalk_bg_dp = ter_id( "t_sidewalk_bg_dp" ); t_guardrail_bg_dp = ter_id( "t_guardrail_bg_dp" ); t_improvised_shelter = ter_id( "t_improvised_shelter" ); t_railroad_rubble = ter_id( "t_railroad_rubble" ); t_buffer_stop = ter_id( "t_buffer_stop" ); t_railroad_crossing_signal = ter_id( "t_railroad_crossing_signal" ); t_crossbuck_metal = ter_id( "t_crossbuck_metal" ); t_crossbuck_wood = ter_id( "t_crossbuck_wood" ); t_railroad_tie = ter_id( "t_railroad_tie" ); t_railroad_tie_h = ter_id( "t_railroad_tie_h" ); t_railroad_tie_v = ter_id( "t_railroad_tie_v" ); t_railroad_tie_d = ter_id( "t_railroad_tie_d" ); t_railroad_track = ter_id( "t_railroad_track" ); t_railroad_track_h = ter_id( "t_railroad_track_h" ); t_railroad_track_v = ter_id( "t_railroad_track_v" ); t_railroad_track_d = ter_id( "t_railroad_track_d" ); t_railroad_track_d1 = ter_id( "t_railroad_track_d1" ); t_railroad_track_d2 = ter_id( "t_railroad_track_d2" ); t_railroad_track_on_tie = ter_id( "t_railroad_track_on_tie" ); t_railroad_track_h_on_tie = ter_id( "t_railroad_track_h_on_tie" ); t_railroad_track_v_on_tie = ter_id( "t_railroad_track_v_on_tie" ); t_railroad_track_d_on_tie = ter_id( "t_railroad_track_d_on_tie" ); for( auto &elem : terrain_data.get_all() ) { ter_t &ter = const_cast<ter_t&>( elem ); if( ter.trap_id_str.empty() ) { ter.trap = tr_null; } else { ter.trap = trap_str_id( ter.trap_id_str ); } } }
bool map::process_fields_in_submap(game *g, int gridn) { bool found_field = false; field *cur; field_id curtype; for (int locx = 0; locx < SEEX; locx++) { for (int locy = 0; locy < SEEY; locy++) { cur = &(grid[gridn].fld[locx][locy]); int x = locx + SEEX * (gridn % my_MAPSIZE), y = locy + SEEY * int(gridn / my_MAPSIZE); curtype = cur->type; if (!found_field && curtype != fd_null) found_field = true; if (cur->density > 3 || cur->density < 1) debugmsg("Whoooooa density of %d", cur->density); if (cur->age == 0) // Don't process "newborn" fields curtype = fd_null; int part; vehicle *veh; switch (curtype) { case fd_null: break; // Do nothing, obviously. OBVIOUSLY. case fd_blood: case fd_bile: if (has_flag(swimmable, x, y)) // Dissipate faster in water cur->age += 250; break; case fd_acid: if (has_flag(swimmable, x, y)) // Dissipate faster in water cur->age += 20; for (int i = 0; i < i_at(x, y).size(); i++) { item *melting = &(i_at(x, y)[i]); if (melting->made_of(LIQUID) || melting->made_of(VEGGY) || melting->made_of(FLESH) || melting->made_of(POWDER) || melting->made_of(COTTON) || melting->made_of(WOOL) || melting->made_of(PAPER) || melting->made_of(PLASTIC) || (melting->made_of(GLASS) && !one_in(3)) || one_in(4)) { // Acid destructable objects here melting->damage++; if (melting->damage >= 5 || (melting->made_of(PAPER) && melting->damage >= 3)) { cur->age += melting->volume(); for (int m = 0; m < i_at(x, y)[i].contents.size(); m++) i_at(x, y).push_back( i_at(x, y)[i].contents[m] ); i_at(x, y).erase(i_at(x, y).begin() + i); i--; } } } break; case fd_sap: break; // It doesn't do anything. case fd_fire: { // Consume items as fuel to help us grow/last longer. bool destroyed = false; int vol = 0, smoke = 0, consumed = 0; for (int i = 0; i < i_at(x, y).size() && consumed < cur->density * 2; i++) { destroyed = false; vol = i_at(x, y)[i].volume(); item *it = &(i_at(x, y)[i]); if (it->is_ammo() && it->ammo_type() != AT_BATT && it->ammo_type() != AT_NAIL && it->ammo_type() != AT_BB && it->ammo_type() != AT_BOLT && it->ammo_type() != AT_ARROW) { cur->age /= 2; cur->age -= 600; destroyed = true; smoke += 6; consumed++; } else if (it->made_of(PAPER)) { destroyed = it->burn(cur->density * 3); consumed++; if (cur->density == 1) cur->age -= vol * 10; if (vol >= 4) smoke++; } else if ((it->made_of(WOOD) || it->made_of(VEGGY))) { if (vol <= cur->density * 10 || cur->density == 3) { cur->age -= 4; destroyed = it->burn(cur->density); smoke++; consumed++; } else if (it->burnt < cur->density) { destroyed = it->burn(1); smoke++; } } else if ((it->made_of(COTTON) || it->made_of(WOOL))) { if (vol <= cur->density * 5 || cur->density == 3) { cur->age--; destroyed = it->burn(cur->density); smoke++; consumed++; } else if (it->burnt < cur->density) { destroyed = it->burn(1); smoke++; } } else if (it->made_of(FLESH)) { if (vol <= cur->density * 5 || (cur->density == 3 && one_in(vol / 20))) { cur->age--; destroyed = it->burn(cur->density); smoke += 3; consumed++; } else if (it->burnt < cur->density * 5 || cur->density >= 2) { destroyed = it->burn(1); smoke++; } } else if (it->made_of(LIQUID)) { switch (it->type->id) { // TODO: Make this be not a hack. case itm_whiskey: case itm_vodka: case itm_rum: case itm_tequila: cur->age -= 300; smoke += 6; break; default: cur->age += rng(80 * vol, 300 * vol); smoke++; } destroyed = true; consumed++; } else if (it->made_of(POWDER)) { cur->age -= vol; destroyed = true; smoke += 2; } else if (it->made_of(PLASTIC)) { smoke += 3; if (it->burnt <= cur->density * 2 || (cur->density == 3 && one_in(vol))) { destroyed = it->burn(cur->density); if (one_in(vol + it->burnt)) cur->age--; } } if (destroyed) { for (int m = 0; m < i_at(x, y)[i].contents.size(); m++) i_at(x, y).push_back( i_at(x, y)[i].contents[m] ); i_at(x, y).erase(i_at(x, y).begin() + i); i--; } } veh = &(veh_at(x, y, part)); if (veh->type != veh_null && (veh->parts[part].flags & VHP_FUEL_TANK) && veh->fuel_type == AT_GAS) { if (cur->density > 1 && one_in (8) && veh->fuel > 0) veh->explode (g, x, y); } // Consume the terrain we're on if (has_flag(explodes, x, y)) { ter(x, y) = ter_id(int(ter(x, y)) + 1); cur->age = 0; cur->density = 3; g->explosion(x, y, 40, 0, true); } else if (has_flag(inflammable, x, y) && one_in(32 - cur->density * 10)) { cur->age -= cur->density * cur->density * 40; smoke += 15; if (cur->density == 3) ter(x, y) = t_ash; } else if (has_flag(flammable, x, y) && one_in(32 - cur->density * 10)) { cur->age -= cur->density * cur->density * 40; smoke += 15; if (cur->density == 3) ter(x, y) = t_rubble; } else if (has_flag(meltable, x, y) && one_in(32 - cur->density * 10)) { cur->age -= cur->density * cur->density * 40; if (cur->density == 3) ter(x, y) = t_b_metal; } else if (terlist[ter(x, y)].flags & mfb(swimmable)) cur->age += 800; // Flames die quickly on water // If we consumed a lot, the flames grow higher while (cur->density < 3 && cur->age < 0) { cur->age += 300; cur->density++; } // If the flames are in a pit, it can't spread to non-pit bool in_pit = (ter(x, y) == t_pit); // If the flames are REALLY big, they contribute to adjacent flames if (cur->density == 3 && cur->age < 0) { // Randomly offset our x/y shifts by 0-2, to randomly pick a square to spread to int starti = rng(0, 2); int startj = rng(0, 2); for (int i = 0; i < 3 && cur->age < 0; i++) { for (int j = 0; j < 3 && cur->age < 0; j++) { int fx = x + ((i + starti) % 3) - 1, fy = y + ((j + startj) % 3) - 1; if (field_at(fx, fy).type == fd_fire && field_at(fx, fy).density < 3 && (!in_pit || ter(fx, fy) == t_pit)) { field_at(fx, fy).density++; field_at(fx, fy).age = 0; cur->age = 0; } } } } // Consume adjacent fuel / terrain to spread. // Randomly offset our x/y shifts by 0-2, to randomly pick a square to spread to int starti = rng(0, 2); int startj = rng(0, 2); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { int fx = x + ((i + starti) % 3) - 1, fy = y + ((j + startj) % 3) - 1; if (INBOUNDS(fx, fy)) { int spread_chance = 20 * (cur->density - 1) + 10 * smoke; if (has_flag(explodes, fx, fy) && one_in(8 - cur->density)) { ter(fx, fy) = ter_id(int(ter(fx, fy)) + 1); g->explosion(fx, fy, 40, 0, true); } else if ((i != 0 || j != 0) && rng(1, 100) < spread_chance && (!in_pit || ter(fx, fy) == t_pit) && ((cur->density == 3 && (has_flag(flammable, fx, fy) || one_in(20))) || flammable_items_at(fx, fy) || field_at(fx, fy).type == fd_web)) { if (field_at(fx, fy).type == fd_smoke || field_at(fx, fy).type == fd_web) field_at(fx, fy) = field(fd_fire, 1, 0); else add_field(g, fx, fy, fd_fire, 1); } else { bool nosmoke = true; for (int ii = -1; ii <= 1; ii++) { for (int jj = -1; jj <= 1; jj++) { if (field_at(x+ii, y+jj).type == fd_fire && field_at(x+ii, y+jj).density == 3) smoke++; else if (field_at(x+ii, y+jj).type == fd_smoke) nosmoke = false; } } // If we're not spreading, maybe we'll stick out some smoke, huh? if (move_cost(fx, fy) > 0 && (!one_in(smoke) || (nosmoke && one_in(40))) && rng(3, 35) < cur->density * 10 && cur->age < 1000) { smoke--; add_field(g, fx, fy, fd_smoke, rng(1, cur->density)); } } } } } } break; case fd_smoke: for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) g->scent(x+i, y+j) = 0; } if (is_outside(x, y)) cur->age += 50; if (one_in(2)) { std::vector <point> spread; for (int a = -1; a <= 1; a++) { for (int b = -1; b <= 1; b++) { if ((field_at(x+a, y+b).type == fd_smoke && field_at(x+a, y+b).density < 3 ) || (field_at(x+a, y+b).is_null() && move_cost(x+a, y+b) > 0)) spread.push_back(point(x+a, y+b)); } } if (cur->density > 0 && cur->age > 0 && spread.size() > 0) { point p = spread[rng(0, spread.size() - 1)]; if (field_at(p.x, p.y).type == fd_smoke && field_at(p.x, p.y).density < 3) { field_at(p.x, p.y).density++; cur->density--; } else if (cur->density > 0 && move_cost(p.x, p.y) > 0 && add_field(g, p.x, p.y, fd_smoke, 1)){ cur->density--; field_at(p.x, p.y).age = cur->age; } } } break; case fd_tear_gas: // Reset nearby scents to zero for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) g->scent(x+i, y+j) = 0; } if (is_outside(x, y)) cur->age += 30; // One in three chance that it spreads (less than smoke!) if (one_in(3)) { std::vector <point> spread; // Pick all eligible points to spread to for (int a = -1; a <= 1; a++) { for (int b = -1; b <= 1; b++) { if (((field_at(x+a, y+b).type == fd_smoke || field_at(x+a, y+b).type == fd_tear_gas) && field_at(x+a, y+b).density < 3 ) || (field_at(x+a, y+b).is_null() && move_cost(x+a, y+b) > 0)) spread.push_back(point(x+a, y+b)); } } // Then, spread to a nearby point if (cur->density > 0 && cur->age > 0 && spread.size() > 0) { point p = spread[rng(0, spread.size() - 1)]; // Nearby teargas grows thicker if (field_at(p.x, p.y).type == fd_tear_gas && field_at(p.x, p.y).density < 3) { field_at(p.x, p.y).density++; cur->density--; // Nearby smoke is converted into teargas } else if (field_at(p.x, p.y).type == fd_smoke) { field_at(p.x, p.y).type = fd_tear_gas; // Or, just create a new field. } else if (cur->density > 0 && move_cost(p.x, p.y) > 0 && add_field(g, p.x, p.y, fd_tear_gas, 1)) { cur->density--; field_at(p.x, p.y).age = cur->age; } } } break; case fd_toxic_gas: // Reset nearby scents to zero for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) g->scent(x+i, y+j) = 0; } if (is_outside(x, y)) cur->age += 40; if (one_in(2)) { std::vector <point> spread; // Pick all eligible points to spread to for (int a = -1; a <= 1; a++) { for (int b = -1; b <= 1; b++) { if (((field_at(x+a, y+b).type == fd_smoke || field_at(x+a, y+b).type == fd_tear_gas || field_at(x+a, y+b).type == fd_toxic_gas || field_at(x+a, y+b).type == fd_nuke_gas ) && field_at(x+a, y+b).density < 3 ) || (field_at(x+a, y+b).is_null() && move_cost(x+a, y+b) > 0)) spread.push_back(point(x+a, y+b)); } } // Then, spread to a nearby point if (cur->density > 0 && cur->age > 0 && spread.size() > 0) { point p = spread[rng(0, spread.size() - 1)]; // Nearby toxic gas grows thicker if (field_at(p.x, p.y).type == fd_toxic_gas && field_at(p.x, p.y).density < 3) { field_at(p.x, p.y).density++; cur->density--; // Nearby smoke & teargas is converted into toxic gas } else if (field_at(p.x, p.y).type == fd_smoke || field_at(p.x, p.y).type == fd_tear_gas) { field_at(p.x, p.y).type = fd_toxic_gas; // Or, just create a new field. } else if (cur->density > 0 && move_cost(p.x, p.y) > 0 && add_field(g, p.x, p.y, fd_toxic_gas, 1)) { cur->density--; field_at(p.x, p.y).age = cur->age; } } } break; case fd_nuke_gas: // Reset nearby scents to zero for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) g->scent(x+i, y+j) = 0; } if (is_outside(x, y)) cur->age += 40; // Increase long-term radiation in the land underneath radiation(x, y) += rng(0, cur->density); if (one_in(2)) { std::vector <point> spread; // Pick all eligible points to spread to for (int a = -1; a <= 1; a++) { for (int b = -1; b <= 1; b++) { if (((field_at(x+a, y+b).type == fd_smoke || field_at(x+a, y+b).type == fd_tear_gas || field_at(x+a, y+b).type == fd_toxic_gas || field_at(x+a, y+b).type == fd_nuke_gas ) && field_at(x+a, y+b).density < 3 ) || (field_at(x+a, y+b).is_null() && move_cost(x+a, y+b) > 0)) spread.push_back(point(x+a, y+b)); } } // Then, spread to a nearby point if (cur->density > 0 && cur->age > 0 && spread.size() > 0) { point p = spread[rng(0, spread.size() - 1)]; // Nearby nukegas grows thicker if (field_at(p.x, p.y).type == fd_nuke_gas && field_at(p.x, p.y).density < 3) { field_at(p.x, p.y).density++; cur->density--; // Nearby smoke, tear, and toxic gas is converted into nukegas } else if (field_at(p.x, p.y).type == fd_smoke || field_at(p.x, p.y).type == fd_toxic_gas || field_at(p.x, p.y).type == fd_tear_gas) { field_at(p.x, p.y).type = fd_nuke_gas; // Or, just create a new field. } else if (cur->density > 0 && move_cost(p.x, p.y) > 0 && add_field(g, p.x, p.y, fd_nuke_gas, 1)) { cur->density--; field_at(p.x, p.y).age = cur->age; } } } break; case fd_gas_vent: for (int i = x - 1; i <= x + 1; i++) { for (int j = y - 1; j <= y + 1; j++) { if (field_at(i, j).type == fd_toxic_gas && field_at(i, j).density < 3) field_at(i, j).density++; else add_field(g, i, j, fd_toxic_gas, 3); } } break; case fd_fire_vent: if (cur->density > 1) { if (one_in(3)) cur->density--; } else { cur->type = fd_flame_burst; cur->density = 3; } break; case fd_flame_burst: if (cur->density > 1) cur->density--; else { cur->type = fd_fire_vent; cur->density = 3; } break; case fd_electricity: if (!one_in(5)) { // 4 in 5 chance to spread std::vector<point> valid; if (move_cost(x, y) == 0 && cur->density > 1) { // We're grounded int tries = 0; while (tries < 10 && cur->age < 50) { int cx = x + rng(-1, 1), cy = y + rng(-1, 1); if (move_cost(cx, cy) != 0 && field_at(cx, cy).is_null()) { add_field(g, cx, cy, fd_electricity, 1); cur->density--; tries = 0; } else tries++; } } else { // We're not grounded; attempt to ground for (int a = -1; a <= 1; a++) { for (int b = -1; b <= 1; b++) { if (move_cost(x + a, y + b) == 0 && // Grounded tiles first field_at(x + a, y + b).is_null()) valid.push_back(point(x + a, y + b)); } } if (valid.size() == 0) { // Spread to adjacent space, then int px = x + rng(-1, 1), py = y + rng(-1, 1); if (move_cost(px, py) > 0 && field_at(px, py).type == fd_electricity && field_at(px, py).density < 3) field_at(px, py).density++; else if (move_cost(px, py) > 0) add_field(g, px, py, fd_electricity, 1); cur->density--; } while (valid.size() > 0 && cur->density > 0) { int index = rng(0, valid.size() - 1); add_field(g, valid[index].x, valid[index].y, fd_electricity, 1); cur->density--; valid.erase(valid.begin() + index); } } } break; case fd_fatigue: if (cur->density < 3 && int(g->turn) % 3600 == 0 && one_in(10)) cur->density++; else if (cur->density == 3 && one_in(600)) { // Spawn nether creature! mon_id type = mon_id(rng(mon_flying_polyp, mon_blank)); monster creature(g->mtypes[type]); creature.spawn(x + rng(-3, 3), y + rng(-3, 3)); g->z.push_back(creature); } break; } cur->age++; if (fieldlist[cur->type].halflife > 0) { if (cur->age > 0 && dice(3, cur->age) > dice(3, fieldlist[cur->type].halflife)) { cur->age = 0; cur->density--; } if (cur->density <= 0) { // Totally dissapated. grid[gridn].field_count--; grid[gridn].fld[locx][locy] = field(); } } } } return found_field; }
swap_invlet_test( dummy, loc ); \ } #define merge_invlet_test_autoletter_off( name, dummy, from ) \ SECTION( std::string( name ) + " (auto letter off)" ) { \ get_options().get_option( "AUTO_INV_ASSIGN" ).setValue( "false" ); \ merge_invlet_test( dummy, from ); \ } TEST_CASE( "Inventory letter test", "[invlet]" ) { player &dummy = g->u; const tripoint spot( 60, 60, 0 ); clear_map(); dummy.setpos( spot ); g->m.ter_set( spot, ter_id( "t_dirt" ) ); g->m.furn_set( spot, furn_id( "f_null" ) ); if( !dummy.has_trait( trait_debug_storage ) ) { dummy.set_mutation( trait_debug_storage ); } invlet_test_autoletter_off( "Picking up items from the ground", dummy, GROUND, INVENTORY ); invlet_test_autoletter_off( "Wearing items from the ground", dummy, GROUND, WORN ); invlet_test_autoletter_off( "Wielding and wearing items from the ground", dummy, GROUND, WIELDED_OR_WORN ); invlet_test_autoletter_off( "Wearing items from inventory", dummy, INVENTORY, WORN ); stack_invlet_test_autoletter_off( "Wearing item from a stack in inventory", dummy, INVENTORY, WORN ); stack_invlet_test_autoletter_off( "Wielding item from a stack in inventory", dummy, INVENTORY, WIELDED_OR_WORN );
void load_terrain(JsonObject &jsobj) { if ( terlist.empty() ) { ter_t new_null = null_terrain_t(); termap[new_null.id] = new_null; terlist.push_back(new_null); } ter_t new_terrain; new_terrain.id = jsobj.get_string("id"); if ( new_terrain.id == "t_null" ) { return; } new_terrain.name = _(jsobj.get_string("name").c_str()); //Special case for the LINE_ symbols std::string symbol = jsobj.get_string("symbol"); if("LINE_XOXO" == symbol) { new_terrain.sym = LINE_XOXO; } else if("LINE_OXOX" == symbol) { new_terrain.sym = LINE_OXOX; } else { new_terrain.sym = symbol.c_str()[0]; } new_terrain.color = color_from_string(jsobj.get_string("color")); new_terrain.movecost = jsobj.get_int("move_cost"); if(jsobj.has_member("trap")) { // Store the string representation of the trap id. // Overwrites the trap field in set_trap_ids() once ids are assigned.. new_terrain.trap_id_str = jsobj.get_string("trap"); } new_terrain.trap = tr_null; new_terrain.max_volume = jsobj.get_int("max_volume", MAX_VOLUME_IN_SQUARE); new_terrain.transparent = false; for( auto & flag : jsobj.get_string_array( "flags" ) ) { new_terrain.set_flag( flag ); } if(jsobj.has_member("examine_action")) { std::string function_name = jsobj.get_string("examine_action"); new_terrain.examine = iexamine_function_from_string(function_name); } else { // if not specified, default to no action new_terrain.examine = iexamine_function_from_string("none"); } // if the terrain has something harvestable if (jsobj.has_member("harvestable")) { new_terrain.harvestable = jsobj.get_string("harvestable"); // get the harvestable } if (jsobj.has_member("transforms_into")) { new_terrain.transforms_into = jsobj.get_string("transforms_into"); // get the terrain to transform into later on } if (jsobj.has_member("roof")) { new_terrain.roof = jsobj.get_string("roof"); // Get the terrain to create above this one if there would be open air otherwise } if (jsobj.has_member("harvest_season")) { //get the harvest season if (jsobj.get_string("harvest_season") == "SPRING") {new_terrain.harvest_season = 0;} // convert the season to int for calendar compare else if (jsobj.get_string("harvest_season") == "SUMMER") {new_terrain.harvest_season = 1;} else if (jsobj.get_string("harvest_season") == "AUTUMN") {new_terrain.harvest_season = 2;} else {new_terrain.harvest_season = 3;} } new_terrain.open = ""; if ( jsobj.has_member("open") ) { new_terrain.open = jsobj.get_string("open"); } new_terrain.close = ""; if ( jsobj.has_member("close") ) { new_terrain.close = jsobj.get_string("close"); } new_terrain.bash.load(jsobj, "bash", false); new_terrain.deconstruct.load(jsobj, "deconstruct", false); new_terrain.loadid = ter_id( terlist.size() ); termap[new_terrain.id]=new_terrain; terlist.push_back(new_terrain); }
bool map::process_fields(game *g) { bool found_field = false; field *cur; field_id curtype; for (int x = 0; x < SEEX * 3; x++) { for (int y = 0; y < SEEY * 3; y++) { cur = &field_at(x, y); curtype = cur->type; if (!found_field && curtype != fd_null) found_field = true; if (cur->density > 3) debugmsg("Whoooooa density of %d", cur->density); if (cur->age == 0) // Don't process "newborn" fields curtype = fd_null; switch (curtype) { case fd_null: break; // Do nothing, obviously. OBVIOUSLY. case fd_blood: case fd_bile: if (has_flag(swimmable, x, y)) // Dissipate faster in water cur->age += 250; break; case fd_acid: if (has_flag(swimmable, x, y)) // Dissipate faster in water cur->age += 20; for (int i = 0; i < i_at(x, y).size(); i++) { item *melting = &(i_at(x, y)[i]); if (melting->made_of(LIQUID) || melting->made_of(VEGGY) || melting->made_of(FLESH) || melting->made_of(POWDER) || melting->made_of(COTTON) || melting->made_of(WOOL) || melting->made_of(PAPER) || melting->made_of(PLASTIC) || (melting->made_of(GLASS) && !one_in(3)) || one_in(4)) { // Acid destructable objects here melting->damage++; if (melting->damage >= 5 || (melting->made_of(PAPER) && melting->damage >= 3)) { cur->age += melting->volume(); for (int m = 0; m < i_at(x, y)[i].contents.size(); m++) i_at(x, y).push_back( i_at(x, y)[i].contents[m] ); i_at(x, y).erase(i_at(x, y).begin() + i); i--; } } } break; case fd_fire: // Consume items as fuel to help us grow/last longer. bool destroyed; int vol; for (int i = 0; i < i_at(x, y).size(); i++) { destroyed = false; vol = i_at(x, y)[i].volume(); if (i_at(x, y)[i].is_ammo()) { cur->age /= 2; cur->age -= 300; destroyed = true; } else if (i_at(x, y)[i].made_of(PAPER)) { cur->age -= vol * 10; destroyed = true; } else if ((i_at(x, y)[i].made_of(WOOD) || i_at(x, y)[i].made_of(VEGGY)) && (vol <= cur->density*10-(cur->age>0 ? rng(0,cur->age/10) : 0) || cur->density == 3)) { cur->age -= vol * 10; destroyed = true; } else if ((i_at(x, y)[i].made_of(COTTON) || i_at(x, y)[i].made_of(FLESH)|| i_at(x, y)[i].made_of(WOOL)) && (vol <= cur->density*2 || (cur->density == 3 && one_in(vol)))) { cur->age -= vol * 5; destroyed = true; } else if (i_at(x, y)[i].made_of(LIQUID) || i_at(x, y)[i].made_of(POWDER)|| i_at(x, y)[i].made_of(PLASTIC)|| (cur->density >= 2 && i_at(x, y)[i].made_of(GLASS)) || (cur->density == 3 && i_at(x, y)[i].made_of(IRON))) { switch (i_at(x, y)[i].type->id) { // TODO: Make this be not a hack. case itm_whiskey: case itm_vodka: case itm_rum: case itm_tequila: cur->age -= 220; break; } destroyed = true; } if (destroyed) { for (int m = 0; m < i_at(x, y)[i].contents.size(); m++) i_at(x, y).push_back( i_at(x, y)[i].contents[m] ); i_at(x, y).erase(i_at(x, y).begin() + i); i--; } } // Consume the terrain we're on if (terlist[ter(x, y)].flags & mfb(flammable) && one_in(8 - cur->density)) { cur->age -= cur->density * cur->density * 40; if (cur->density == 3) ter(x, y) = t_rubble; } else if (terlist[ter(x, y)].flags & mfb(explodes)) { ter(x, y) = ter_id(int(ter(x, y)) + 1); cur->age = 0; cur->density = 3; g->explosion(x, y, 40, 0, true); } else if (terlist[ter(x, y)].flags & mfb(swimmable)) cur->age += 800; // Flames die quickly on water // If we consumed a lot, the flames grow higher while (cur->density < 3 && cur->age < 0) { cur->age += 300; cur->density++; } // If the flames are REALLY big, they contribute to adjacent flames if (cur->density == 3 && cur->age < 0) { // If the flames are in a pit, it can't spread to non-pit bool in_pit = (ter(x, y) == t_pit); // Randomly offset our x/y shifts by 0-2, to randomly pick a square to spread to int starti = rng(0, 2); int startj = rng(0, 2); for (int i = 0; i < 3 && cur->age < 0; i++) { for (int j = 0; j < 3 && cur->age < 0; j++) { if (field_at(x+((i+starti)%3), y+((j+startj)%3)).type == fd_fire && field_at(x+((i+starti)%3), y+((j+startj)%3)).density < 3 && (!in_pit || ter(x+((i+starti)%3), y+((j+startj)%3)) == t_pit)) { field_at(x+((i+starti)%3), y+((j+startj)%3)).density++; field_at(x+((i+starti)%3), y+((j+startj)%3)).age = 0; cur->age = 0; } } } } // Consume adjacent fuel / terrain to spread. for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (x+i >= 0 && y+j >= 0 && x+i < SEEX * 3 && y+j <= SEEY * 3) { if (has_flag(explodes, x + i, y + j) && one_in(8 - cur->density)) { ter(x + i, y + i) = ter_id(int(ter(x + i, y + i)) + 1); g->explosion(x+i, y+j, 40, 0, true); } else if ((i != 0 || j != 0) && (i_at(x+i, y+j).size() > 0 || rng(15, 120) < cur->density * 10)) { if (field_at(x+i, y+j).type == fd_smoke) field_at(x+i, y+j) = field(fd_fire, 1, 0); // Fire in pits can only spread to adjacent pits else if (ter(x, y) != t_pit || ter(x + i, y + j) == t_pit) add_field(g, x+i, y+j, fd_fire, 1); // If we're not spreading, maybe we'll stick out some smoke, huh? } else if (move_cost(x+i, y+j) > 0 && rng(7, 40) < cur->density * 10 && cur->age < 1000) { add_field(g, x+i, y+j, fd_smoke, rng(1, cur->density)); } } } } break; case fd_smoke: for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) g->scent(x+i, y+j) = 0; } if (is_outside(x, y)) cur->age += 50; if (one_in(2)) { std::vector <point> spread; for (int a = -1; a <= 1; a++) { for (int b = -1; b <= 1; b++) { if ((field_at(x+a, y+b).type == fd_smoke && field_at(x+a, y+b).density < 3) || (field_at(x+a, y+b).is_null() && move_cost(x+a, y+b) > 0)) spread.push_back(point(x+a, y+b)); } } if (cur->density > 0 && cur->age > 0 && spread.size() > 0) { point p = spread[rng(0, spread.size() - 1)]; if (field_at(p.x, p.y).type == fd_smoke && field_at(p.x, p.y).density < 3) { field_at(p.x, p.y).density++; cur->density--; } else if (cur->density > 0 && move_cost(p.x, p.y) > 0 && add_field(g, p.x, p.y, fd_smoke, 1)){ cur->density--; field_at(p.x, p.y).age = cur->age; } } } break; case fd_tear_gas: // Reset nearby scents to zero for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) g->scent(x+i, y+j) = 0; } if (is_outside(x, y)) cur->age += 30; // One in three chance that it spreads (less than smoke!) if (one_in(3)) { std::vector <point> spread; // Pick all eligible points to spread to for (int a = -1; a <= 1; a++) { for (int b = -1; b <= 1; b++) { if (((field_at(x+a, y+b).type == fd_smoke || field_at(x+a, y+b).type == fd_tear_gas) && field_at(x+a, y+b).density < 3 ) || (field_at(x+a, y+b).is_null() && move_cost(x+a, y+b) > 0)) spread.push_back(point(x+a, y+b)); } } // Then, spread to a nearby point if (cur->density > 0 && cur->age > 0 && spread.size() > 0) { point p = spread[rng(0, spread.size() - 1)]; // Nearby teargas grows thicker if (field_at(p.x, p.y).type == fd_tear_gas && field_at(p.x, p.y).density < 3) { field_at(p.x, p.y).density++; cur->density--; // Nearby smoke is converted into teargas } else if (field_at(p.x, p.y).type == fd_smoke) { field_at(p.x, p.y).type = fd_tear_gas; // Or, just create a new field. } else if (cur->density > 0 && move_cost(p.x, p.y) > 0 && add_field(g, p.x, p.y, fd_tear_gas, 1)) { cur->density--; field_at(p.x, p.y).age = cur->age; } } } break; case fd_nuke_gas: // Reset nearby scents to zero for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) g->scent(x+i, y+j) = 0; } if (is_outside(x, y)) cur->age += 40; // Increase long-term radiation in the land underneath radiation(x, y) += rng(0, cur->density); if (one_in(2)) { std::vector <point> spread; // Pick all eligible points to spread to for (int a = -1; a <= 1; a++) { for (int b = -1; b <= 1; b++) { if (((field_at(x+a, y+b).type == fd_smoke || field_at(x+a, y+b).type == fd_tear_gas || field_at(x+a, y+b).type == fd_nuke_gas ) && field_at(x+a, y+b).density < 3 ) || (field_at(x+a, y+b).is_null() && move_cost(x+a, y+b) > 0)) spread.push_back(point(x+a, y+b)); } } // Then, spread to a nearby point if (cur->density > 0 && cur->age > 0 && spread.size() > 0) { point p = spread[rng(0, spread.size() - 1)]; // Nearby nukegas grows thicker if (field_at(p.x, p.y).type == fd_nuke_gas && field_at(p.x, p.y).density < 3) { field_at(p.x, p.y).density++; cur->density--; // Nearby smoke & teargas is converted into nukegas } else if (field_at(p.x, p.y).type == fd_smoke || field_at(p.x, p.y).type == fd_tear_gas) { field_at(p.x, p.y).type = fd_nuke_gas; // Or, just create a new field. } else if (cur->density > 0 && move_cost(p.x, p.y) > 0 && add_field(g, p.x, p.y, fd_nuke_gas, 1)) { cur->density--; field_at(p.x, p.y).age = cur->age; } } } break; case fd_electricity: if (!one_in(5)) { // 4 in 5 chance to spread std::vector<point> valid; if (move_cost(x, y) == 0 && cur->density > 1) { // We're grounded int tries = 0; while (tries < 10 && cur->age < 50) { int cx = x + rng(-1, 1), cy = y + rng(-1, 1); if (move_cost(cx, cy) != 0 && field_at(cx, cy).is_null()) { add_field(g, cx, cy, fd_electricity, 1); cur->density--; tries = 0; } else tries++; } } else { // We're not grounded; attempt to ground for (int a = -1; a <= 1; a++) { for (int b = -1; b <= 1; b++) { if (move_cost(x + a, y + b) == 0 && // Grounded tiles first field_at(x + a, y + b).is_null()) valid.push_back(point(x + a, y + b)); } } if (valid.size() == 0) { // Spread to adjacent space, then int px = x + rng(-1, 1), py = y + rng(-1, 1); if (move_cost(px, py) > 0 && field_at(px, py).type == fd_electricity && field_at(px, py).density < 3) field_at(px, py).density++; else if (move_cost(px, py) > 0) add_field(g, px, py, fd_electricity, 1); cur->density--; } while (valid.size() > 0 && cur->density > 0) { int index = rng(0, valid.size() - 1); add_field(g, valid[index].x, valid[index].y, fd_electricity, 1); cur->density--; valid.erase(valid.begin() + index); } } } break; case fd_fatigue: if (cur->density < 3 && g->turn % 3600 == 0 && one_in(10)) cur->density++; else if (cur->density == 3 && one_in(3600)) { // Spawn nether creature! mon_id type = mon_id(rng(mon_flying_polyp, mon_blank)); monster creature(g->mtypes[type]); creature.spawn(x + rng(-3, 3), y + rng(-3, 3)); g->z.push_back(creature); } break; } if (fieldlist[cur->type].halflife > 0) { cur->age++; if (cur->age > 0 && dice(3, cur->age) > dice(3, fieldlist[cur->type].halflife)) { cur->age = 0; cur->density--; } if (cur->density <= 0) // Totally dissapated. field_at(x, y) = field(); } } } return found_field; }
void load_terrain(JsonObject &jsobj) { if ( terlist.empty() ) { ter_t new_null = null_terrain_t(); termap[new_null.id] = new_null; terlist.push_back(new_null); } ter_t new_terrain; new_terrain.id = jsobj.get_string("id"); if ( new_terrain.id == "t_null" ) { return; } new_terrain.name = _(jsobj.get_string("name").c_str()); new_terrain.load_symbol( jsobj ); new_terrain.movecost = jsobj.get_int("move_cost"); if(jsobj.has_member("trap")) { // Store the string representation of the trap id. // Overwrites the trap field in set_trap_ids() once ids are assigned.. new_terrain.trap_id_str = jsobj.get_string("trap"); } new_terrain.trap = tr_null; new_terrain.max_volume = jsobj.get_int("max_volume", MAX_VOLUME_IN_SQUARE); new_terrain.transparent = false; new_terrain.connect_group = TERCONN_NONE; for( auto & flag : jsobj.get_string_array( "flags" ) ) { new_terrain.set_flag( flag ); } // connect_group is initialised to none, then terrain flags are set, then finally // connections from JSON are set. This is so that wall flags can set wall connections // but can be overridden by explicit connections in JSON. if(jsobj.has_member("connects_to")) { new_terrain.set_connects( jsobj.get_string("connects_to") ); } if(jsobj.has_member("examine_action")) { std::string function_name = jsobj.get_string("examine_action"); new_terrain.examine = iexamine_function_from_string(function_name); } else { // if not specified, default to no action new_terrain.examine = iexamine_function_from_string("none"); } // if the terrain has something harvestable if (jsobj.has_member("harvestable")) { new_terrain.harvestable = jsobj.get_string("harvestable"); // get the harvestable } if (jsobj.has_member("transforms_into")) { new_terrain.transforms_into = jsobj.get_string("transforms_into"); // get the terrain to transform into later on } if (jsobj.has_member("roof")) { new_terrain.roof = jsobj.get_string("roof"); // Get the terrain to create above this one if there would be open air otherwise } if (jsobj.has_member("harvest_season")) { //get the harvest season if (jsobj.get_string("harvest_season") == "SPRING") {new_terrain.harvest_season = 0;} // convert the season to int for calendar compare else if (jsobj.get_string("harvest_season") == "SUMMER") {new_terrain.harvest_season = 1;} else if (jsobj.get_string("harvest_season") == "AUTUMN") {new_terrain.harvest_season = 2;} else {new_terrain.harvest_season = 3;} } new_terrain.open = ""; if ( jsobj.has_member("open") ) { new_terrain.open = jsobj.get_string("open"); } new_terrain.close = ""; if ( jsobj.has_member("close") ) { new_terrain.close = jsobj.get_string("close"); } new_terrain.bash.load(jsobj, "bash", false); new_terrain.deconstruct.load(jsobj, "deconstruct", false); new_terrain.loadid = ter_id( terlist.size() ); termap[new_terrain.id]=new_terrain; terlist.push_back(new_terrain); }