From 2539c28fe2b11d5b4d7afadf914e01cecf22eb1b Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Sun, 22 Jan 2023 13:39:50 -0500 Subject: [PATCH] Prefer to call is_on_map() for terrain bounds checking whenever possible Fix some cCurTown field functions not having bound checking Scenario editor now takes better advantage of cTown and cOutdoors sharing a superclass --- src/game/boe.graphics.cpp | 10 ++- src/game/boe.locutils.cpp | 28 +++----- src/game/boe.specials.cpp | 2 +- src/scenedit/scen.actions.cpp | 120 +++++++++++++------------------- src/scenedit/scen.core.cpp | 5 ++ src/scenedit/scen.core.hpp | 1 + src/scenedit/scen.graphics.cpp | 2 +- src/universe/universe.cpp | 121 +++++++++++++++++++-------------- src/universe/universe.hpp | 2 + 9 files changed, 142 insertions(+), 149 deletions(-) diff --git a/src/game/boe.graphics.cpp b/src/game/boe.graphics.cpp index 6799a6da..1c1292d7 100644 --- a/src/game/boe.graphics.cpp +++ b/src/game/boe.graphics.cpp @@ -738,8 +738,7 @@ void draw_terrain(short mode) { where_draw.y += j - 6; if(!(is_out())) light_area[i][j] = (is_town()) ? pt_in_light(view_loc,where_draw) : combat_pt_in_light(where_draw); - if(!(is_out()) && ((where_draw.x < 0) || (where_draw.x > univ.town->max_dim - 1) - || (where_draw.y < 0) || (where_draw.y > univ.town->max_dim - 1))) + if(!is_out() && !univ.town.is_on_map(where_draw.x, where_draw.y)) unexplored_area[i][j] = 0; else unexplored_area[i][j] = 1 - is_explored(where_draw.x,where_draw.y); } @@ -753,8 +752,7 @@ void draw_terrain(short mode) { off_terrain = false; draw_frills = true; - if(!(is_out()) && ((where_draw.x < 0) || (where_draw.x > univ.town->max_dim - 1) - || (where_draw.y < 0) || (where_draw.y > univ.town->max_dim - 1))) { + if(!is_out() && !univ.town.is_on_map(where_draw.x, where_draw.y)) { draw_frills = false; // Warning - this section changes where_draw if(where_draw.x < 0) @@ -771,8 +769,7 @@ void draw_terrain(short mode) { spec_terrain = 0; } else if(is_out()) { - if((where_draw.x < 0) || (where_draw.x > 95) - || (where_draw.y < 0) || (where_draw.y > 95)) + if(!univ.out.is_on_map(where_draw.x, where_draw.y)) can_draw = 0; else { spec_terrain = univ.out[where_draw.x][where_draw.y]; @@ -962,6 +959,7 @@ void place_trim(short q,short r,location where,ter_num_t ter_type) { } else { // TODO: Shouldn't we subtract one here? + // The outdoors case (above) does subtract 1, so one of them must be wrong... if(where.x == univ.town->max_dim) at_right = true; if(where.y == univ.town->max_dim) diff --git a/src/game/boe.locutils.cpp b/src/game/boe.locutils.cpp index c65b8d63..346c3005 100644 --- a/src/game/boe.locutils.cpp +++ b/src/game/boe.locutils.cpp @@ -134,9 +134,7 @@ location local_to_global(location local) { return global; } bool loc_off_world(location p1) { - if((p1.x < 0) || (p1.x > univ.town->max_dim) || (p1.y < 0) || (p1.y > univ.town->max_dim)) - return true; - else return false; + return !univ.town.is_on_map(p1.x, p1.y); } bool loc_off_act_area(location p1) { @@ -215,16 +213,11 @@ short combat_obscurity(short x, short y) { } ter_num_t coord_to_ter(short x,short y) { - if(x < 0 || y < 0) return 0; if(is_out()) { - if(x >= univ.out.max_dim || y >= univ.out.max_dim) { - return 0; - } + if(!univ.out.is_on_map(x, y)) return 0; return univ.out[x][y]; } - if(x >= univ.town->max_dim || y >= univ.town->max_dim) { - return 0; - } + if(!univ.town.is_on_map(x, y)) return 0; return univ.town->terrain(x,y); } @@ -250,7 +243,7 @@ void update_explored(const location dest) { univ.out.out_e[dest.x][dest.y] = 2; for(look.x = dest.x - 4; look.x < dest.x + 5; look.x++) for(look.y = dest.y - 4; look.y < dest.y + 5; look.y++) { - if((look.x == minmax(0,univ.out.max_dim-1,(int)look.x)) && (look.y == minmax(0,univ.out.max_dim-1,(int)look.y))) { + if(univ.out.is_on_map(look.x, look.y)) { if(univ.out.out_e[look.x][look.y] == 0) { if(can_see_light(dest, look, sight_obscurity) < 5) { univ.out.out_e[look.x][look.y] = 1; @@ -271,9 +264,8 @@ void update_explored(const location dest) { // All purpose function to check is spot is free for travel into. bool is_blocked(location to_check) { - if(to_check.x < 0 || to_check.y < 0) return true; if(is_out()) { - if(to_check.x >= univ.out.max_dim || to_check.y >= univ.out.max_dim) + if(!univ.out.is_on_map(to_check.x, to_check.y)) return true; if(impassable(univ.out[to_check.x][to_check.y])) { return true; @@ -288,7 +280,7 @@ bool is_blocked(location to_check) { } if((is_town()) || (is_combat())) { - if(to_check.x >= univ.town->max_dim || to_check.y >= univ.town->max_dim) + if(!univ.town.is_on_map(to_check.x, to_check.y)) return true; ter_num_t ter = univ.town->terrain(to_check.x,to_check.y); @@ -404,7 +396,7 @@ bool can_see_monst(location l,short m_num) { bool outd_is_blocked(location to_check) { if(overall_mode == MODE_OUTDOORS) { - if(to_check.x < 0 || to_check.y < 0 || to_check.x >= univ.out.max_dim || to_check.y >= univ.out.max_dim) + if(!univ.out.is_on_map(to_check.x, to_check.y)) return true; if(impassable(univ.out[to_check.x][to_check.y])) { return true; @@ -484,8 +476,7 @@ bool pt_in_light(location from_where,location to_where) { // Assumes, of course, if(univ.town->lighting_type == 0) return true; - if((to_where.x < 0) || (to_where.x >= univ.town->max_dim) - || (to_where.y < 0) || (to_where.y >= univ.town->max_dim)) + if(!univ.town.is_on_map(to_where.x, to_where.y)) return true; if(univ.town->lighting[to_where.x][to_where.y]) return true; @@ -501,8 +492,7 @@ bool combat_pt_in_light(location to_where) { if((univ.town->lighting_type == 0) || (which_combat_type == 0)) return true; - if((to_where.x < 0) || (to_where.x >= univ.town->max_dim) - || (to_where.y < 0) || (to_where.y >= univ.town->max_dim)) + if(!univ.town.is_on_map(to_where.x, to_where.y)) return true; if(univ.town->lighting[to_where.x][to_where.y]) return true; diff --git a/src/game/boe.specials.cpp b/src/game/boe.specials.cpp index be714468..db25e0e4 100644 --- a/src/game/boe.specials.cpp +++ b/src/game/boe.specials.cpp @@ -4248,7 +4248,7 @@ void townmode_spec(const runtime_state& ctx) { if(x == 0 && y == 0) continue; location next(l.x+x,l.y+y); - if(next.x < 0 || next.y < 0 || next.x >= univ.town->max_dim || next.y >= univ.town->max_dim) + if(!univ.town.is_on_map(next.x, next.y)) continue; if(!checked.count(next)) to_check.push(next); diff --git a/src/scenedit/scen.actions.cpp b/src/scenedit/scen.actions.cpp index f027b022..3ee2b3db 100644 --- a/src/scenedit/scen.actions.cpp +++ b/src/scenedit/scen.actions.cpp @@ -681,6 +681,7 @@ static bool handle_rb_action(location the_point, bool option_hit) { } static bool handle_terrain_action(location the_point, bool ctrl_hit) { + cArea* cur_area = get_current_area(); if(mouse_spot.x >= 0 && mouse_spot.y >= 0) { if(cur_viewing_mode == 0) { spot_hit.x = cen_x + mouse_spot.x - 4; @@ -713,8 +714,7 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) { eScenMode old_mode = overall_mode; change_made = true; - if((spot_hit.x < 0) || (spot_hit.x > ((editing_town) ? town->max_dim - 1 : 47)) || - (spot_hit.y < 0) || (spot_hit.y > ((editing_town) ? town->max_dim - 1 : 47))) ; + if(!cur_area->is_on_map(spot_hit)) ; else switch(overall_mode) { case MODE_DRAWING: if((!mouse_button_held && terrain_matches(spot_hit.x,spot_hit.y,current_terrain_type)) || @@ -1167,17 +1167,19 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) { need_redraw = true; mouse_button_held = true; } - if((the_point.in(border_rect[2])) & (cen_y < (editing_town ? town->max_dim - 5 : 44))) { + auto max_dim = cur_area->max_dim - 5; + if(!editing_town) max_dim++; + if((the_point.in(border_rect[2])) && (cen_y < max_dim)) { cen_y++; if(ctrl_hit) - cen_y = (editing_town) ? town->max_dim - 5 : 44; + cen_y = max_dim; need_redraw = true; mouse_button_held = true; } - if((the_point.in(border_rect[3])) & (cen_x < (editing_town ? town->max_dim - 5 : 44))) { + if((the_point.in(border_rect[3])) && (cen_x < max_dim)) { cen_x++; if(ctrl_hit) - cen_x = (editing_town) ? town->max_dim - 5 : 44; + cen_x = max_dim; need_redraw = true; mouse_button_held = true; } @@ -1587,14 +1589,13 @@ void swap_terrain() { ter_num_t ter; if(!change_ter(a,b,c)) return; + cArea* cur_area = get_current_area(); - for(short i = 0; i < ((editing_town) ? town->max_dim : 48); i++) - for(short j = 0; j < ((editing_town) ? town->max_dim : 48); j++) { - ter = editing_town ? town->terrain(i,j) : current_terrain->terrain[i][j]; + for(short i = 0; i < cur_area->max_dim; i++) + for(short j = 0; j < cur_area->max_dim; j++) { + ter = cur_area->terrain(i,j); if((ter == a) && (get_ran(1,1,100) <= c)) { - if(editing_town) - town->terrain(i,j) = b; - else current_terrain->terrain[i][j] = b; + cur_area->terrain(i,j) = b; } } @@ -1791,9 +1792,10 @@ void handle_scroll(const sf::Event& event) { void change_circle_terrain(location center,short radius,ter_num_t terrain_type,short probability) { // prob is 0 - 20, 0 no, 20 always location l; + cArea* cur_area = get_current_area(); - for(short i = 0; i < ((editing_town) ? town->max_dim : 48); i++) - for(short j = 0; j < ((editing_town) ? town->max_dim : 48); j++) { + for(short i = 0; i < cur_area->max_dim; i++) + for(short j = 0; j < cur_area->max_dim; j++) { l.x = i; l.y = j; if((dist(center,l) <= radius) && (get_ran(1,1,20) <= probability)) @@ -1804,9 +1806,10 @@ void change_circle_terrain(location center,short radius,ter_num_t terrain_type,s void change_rect_terrain(rectangle r,ter_num_t terrain_type,short probability,bool hollow) { // prob is 0 - 20, 0 no, 20 always location l; + cArea* cur_area = get_current_area(); - for(short i = 0; i < ((editing_town) ? town->max_dim : 48); i++) - for(short j = 0; j < ((editing_town) ? town->max_dim : 48); j++) { + for(short i = 0; i < cur_area->max_dim; i++) + for(short j = 0; j < cur_area->max_dim; j++) { l.x = i; l.y = j; if((i >= r.left) && (i <= r.right) && (j >= r.top) && (j <= r.bottom) @@ -1823,7 +1826,7 @@ void flood_fill_terrain(location start, ter_num_t terrain_type) { std::stack to_visit; std::set visited; to_visit.push(start); - int max_dim = editing_town ? town->max_dim : current_terrain->max_dim; + cArea* cur_area = get_current_area(); while(!to_visit.empty()) { location this_loc = to_visit.top(); @@ -1833,24 +1836,23 @@ void flood_fill_terrain(location start, ter_num_t terrain_type) { location adj_loc = this_loc; adj_loc.x += dx[i]; adj_loc.y += dy[i]; - if(adj_loc.x < 0 || adj_loc.x >= max_dim || adj_loc.y < 0 || adj_loc.y >= max_dim) + if(!cur_area->is_on_map(adj_loc)) continue; - ter_num_t check = editing_town ? town->terrain(adj_loc.x, adj_loc.y) : current_terrain->terrain[adj_loc.x][adj_loc.y]; + ter_num_t check = cur_area->terrain(adj_loc.x, adj_loc.y); if(check == to_replace && !visited.count(adj_loc)) to_visit.push(adj_loc); } - if(editing_town) - town->terrain(this_loc.x, this_loc.y) = terrain_type; - else current_terrain->terrain[this_loc.x][this_loc.y] = terrain_type; + cur_area->terrain(this_loc.x, this_loc.y) = terrain_type; } } void frill_up_terrain() { ter_num_t terrain_type; + cArea* cur_area = get_current_area(); - for(short i = 0; i < ((editing_town) ? town->max_dim : 48); i++) - for(short j = 0; j < ((editing_town) ? town->max_dim : 48); j++) { - terrain_type = editing_town ? town->terrain(i,j) : current_terrain->terrain[i][j]; + for(short i = 0; i < cur_area->max_dim; i++) + for(short j = 0; j < cur_area->max_dim; j++) { + terrain_type = cur_area->terrain(i,j); for(size_t k = 0; k < scenario.ter_types.size(); k++) { if(terrain_type == k) continue; @@ -1859,27 +1861,24 @@ void frill_up_terrain() { terrain_type = k; } - if(editing_town) - town->terrain(i,j) = terrain_type; - else current_terrain->terrain[i][j] = terrain_type; + cur_area->terrain(i,j) = terrain_type; } draw_terrain(); } void unfrill_terrain() { ter_num_t terrain_type; + cArea* cur_area = get_current_area(); - for(short i = 0; i < ((editing_town) ? town->max_dim : 48); i++) - for(short j = 0; j < ((editing_town) ? town->max_dim : 48); j++) { - terrain_type = editing_town ? town->terrain(i,j) : current_terrain->terrain[i][j]; + for(short i = 0; i < cur_area->max_dim; i++) + for(short j = 0; j < cur_area->max_dim; j++) { + terrain_type = cur_area->terrain(i,j); cTerrain& ter = scenario.ter_types[terrain_type]; if(ter.frill_for >= 0) terrain_type = ter.frill_for; - if(editing_town) - town->terrain(i,j) = terrain_type; - else current_terrain->terrain[i][j] = terrain_type; + cur_area->terrain(i,j) = terrain_type; } draw_terrain(); } @@ -1922,15 +1921,11 @@ static const std::array trim_diffs = {{ void set_terrain(location l,ter_num_t terrain_type) { location l2; + cArea* cur_area = get_current_area(); - if((editing_town) && ((l.x < 0) || (l.x > town->max_dim - 1) || (l.y < 0) || (l.y > town->max_dim - 1))) - return ; - if(!editing_town && ((l.x < 0) || (l.x > 47) || (l.y < 0) || (l.y > 47))) - return ; + if(!cur_area->is_on_map(l)) return; - if(editing_town) - town->terrain(l.x,l.y) = terrain_type; - else current_terrain->terrain[l.x][l.y] = terrain_type; + cur_area->terrain(l.x,l.y) = terrain_type; l2 = l; // Large objects (eg rubble) @@ -1942,9 +1937,7 @@ void set_terrain(location l,ter_num_t terrain_type) { while(obj_loc.y > 0) l2.y-- , obj_loc.y--; for(short i = 0; i < obj_dim.x; i++) for(short j = 0; j < obj_dim.y; j++){ - if(editing_town) - town->terrain(l2.x + i,l2.y + j) = find_object_part(q,i,j,terrain_type); - else current_terrain->terrain[l2.x + i][l2.y + j] = find_object_part(q,i,j,terrain_type); + cur_area->terrain(l2.x + i,l2.y + j) = find_object_part(q,i,j,terrain_type); } } @@ -1967,9 +1960,7 @@ void set_terrain(location l,ter_num_t terrain_type) { // Otherwise it might overwrite important things, like buildings or forests. if(ter_there != scenario.get_ter_from_ground(ter_type.trim_ter)) continue; - if(editing_town) - town->terrain(l3.x,l3.y) = new_ter; - else current_terrain->terrain[l3.x][l3.y] = new_ter; + cur_area->terrain(l3.x,l3.y) = new_ter; } } } @@ -1986,12 +1977,12 @@ void set_terrain(location l,ter_num_t terrain_type) { mouse_button_held = false; return; } - auto& signs = editing_town ? town->sign_locs : current_terrain->sign_locs; + auto& signs = cur_area->sign_locs; auto iter = std::find(signs.begin(), signs.end(), l); if(iter == signs.end()) { - iter = std::find_if(signs.begin(), signs.end(), [](const sign_loc_t& sign) { + iter = std::find_if(signs.begin(), signs.end(), [cur_area](const sign_loc_t& sign) { if(sign.x == 100) return true; - ter_num_t ter = editing_town ? town->terrain(sign.x,sign.y) : current_terrain->terrain[sign.x][sign.y]; + ter_num_t ter = cur_area->terrain(sign.x,sign.y); return scenario.ter_types[ter].special != eTerSpec::IS_A_SIGN; }); if(iter == signs.end()) { @@ -2000,7 +1991,7 @@ void set_terrain(location l,ter_num_t terrain_type) { } } static_cast(*iter) = l; - ter_num_t terrain_type = editing_town ? town->terrain(iter->x,iter->y) : current_terrain->terrain[iter->x][iter->y]; + ter_num_t terrain_type = cur_area->terrain(iter->x,iter->y); edit_sign(*iter, iter - signs.begin(), scenario.ter_types[terrain_type].picture); mouse_button_held = false; } @@ -2009,15 +2000,10 @@ void set_terrain(location l,ter_num_t terrain_type) { void adjust_space(location l) { bool needed_change = false; location l2; - short i,j; + cArea* cur_area = get_current_area(); - i = l.x; - j = l.y; - if((editing_town) && ((i < 0) || (i > town->max_dim - 1) || (j < 0) || (j > town->max_dim - 1))) - return ; - if(!editing_town && ((i < 0) || (i > 47) || (j < 0) || (j > 47))) - return ; - size_t size = editing_town ? town->max_dim : 48; + if(!cur_area->is_on_map(l)) return; + size_t size = cur_area->max_dim; ter_num_t off_map = -1; ter_num_t store_ter[3][3]; @@ -2026,7 +2012,7 @@ void adjust_space(location l) { eTrimType store_trim[3][3]; for(int dx = -1; dx <= 1; dx++) { for(int dy = -1; dy <= 1; dy++) { - int x = i + dx, y = j + dy; + int x = l.x + dx, y = l.y + dy; if(x < 0 || x >= size || y < 0 || y >= size) { store_ter[dx+1][dy+1] = off_map; continue; @@ -2097,9 +2083,7 @@ void adjust_space(location l) { ter_num_t replace = scenario.get_trim_terrain(main_ground, trim_ground, need_trim); if(replace != 90) { // If we got 90 back, the required trim doesn't exist. needed_change = true; - if(editing_town) - town->terrain(i,j) = replace; - else current_terrain->terrain[i][j] = replace; + cur_area->terrain(l.x,l.y) = replace; } } @@ -2707,14 +2691,8 @@ bool is_lava(short x,short y) { } ter_num_t coord_to_ter(short x,short y) { - if(x < 0 || y < 0) return 0; - if(editing_town) { - if(x >= town->max_dim || y >= town->max_dim) return 0; - return town->terrain(x,y); - } else { - if(x >= current_terrain->max_dim || y >= current_terrain->max_dim) return 0; - return current_terrain->terrain[x][y]; - } + if(!get_current_area()->is_on_map(loc(x,y))) return 0; + return get_current_area()->terrain(x,y); } bool monst_on_space(location loc,short m_num) { diff --git a/src/scenedit/scen.core.cpp b/src/scenedit/scen.core.cpp index 38262f3d..a1c49bf2 100644 --- a/src/scenedit/scen.core.cpp +++ b/src/scenedit/scen.core.cpp @@ -55,6 +55,11 @@ const std::set items_no_strength = { eItemAbil::QUICKFIRE, }; +cArea* get_current_area() { + if(editing_town) return town; + else return current_terrain; +} + static bool save_ter_info(cDialog& me, cTerrain& ter) { eTerSpec prop = eTerSpec(boost::lexical_cast(dynamic_cast(me["prop"]).getSelected().substr(4))); int spec_type = me["flag2"].getTextAsNum(); diff --git a/src/scenedit/scen.core.hpp b/src/scenedit/scen.core.hpp index 897e4f3f..a5cafbf7 100644 --- a/src/scenedit/scen.core.hpp +++ b/src/scenedit/scen.core.hpp @@ -21,6 +21,7 @@ bool edit_make_scen_1(std::string& filename,std::string& title,bool& grass); void edit_scenario_events(); bool build_scenario(); bool edit_vehicle(class cVehicle& what, int num, bool is_boat); +class cArea* get_current_area(); bool check_range_msg(cDialog& me,std::string id,bool losing,long min_val,long max_val,std::string fld_name,std::string xtra); bool check_range(cDialog& me,std::string id,bool losing,long min_val,long max_val,std::string fld_name); diff --git a/src/scenedit/scen.graphics.cpp b/src/scenedit/scen.graphics.cpp index 4154a260..b0870b1d 100644 --- a/src/scenedit/scen.graphics.cpp +++ b/src/scenedit/scen.graphics.cpp @@ -966,7 +966,7 @@ void draw_terrain(){ // Width available: 64 4x4 tiles, 42 6x6 tiles, or 21 12x12 tiles -- 256 pixels // Height available: 81 4x4 tiles, 54 6x6 tiles, or 27 12x12 tiles -- 324 pixels short size = mini_map_scales[cur_viewing_mode - 1]; - int max_dim = (editing_town ? town->max_dim : 48); + int max_dim = get_current_area()->max_dim; int xMin = 0, yMin = 0, xMax = max_dim, yMax = max_dim; if(cen_x + 5 > 256 / size) { xMin = cen_x + 5 - (256 / size); diff --git a/src/universe/universe.cpp b/src/universe/universe.cpp index 4339f7e9..e2e88385 100644 --- a/src/universe/universe.cpp +++ b/src/universe/universe.cpp @@ -223,67 +223,69 @@ cTown*const cCurTown::record() const { } bool cCurTown::is_summon_safe(short x, short y) const { - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; // Here 254 indicates the low byte of the town fields, minus explored spaces (which is lowest bit). static const unsigned long blocking_fields = SPECIAL_SPOT | OBJECT_CRATE | OBJECT_BARREL | OBJECT_BLOCK | FIELD_QUICKFIRE | 254; return fields[x][y] & blocking_fields; } bool cCurTown::is_explored(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & SPECIAL_EXPLORED; } bool cCurTown::is_force_wall(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & WALL_FORCE; } bool cCurTown::is_fire_wall(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & WALL_FIRE; } bool cCurTown::is_antimagic(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & FIELD_ANTIMAGIC; } bool cCurTown::is_scloud(short x, short y) const{ // stinking cloud - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & CLOUD_STINK; } bool cCurTown::is_ice_wall(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & WALL_ICE; } bool cCurTown::is_blade_wall(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & WALL_BLADES; } bool cCurTown::is_sleep_cloud(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & CLOUD_SLEEP; } bool cCurTown::is_block(short x, short y) const{ // currently unused - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & OBJECT_BLOCK; } bool cCurTown::is_spot(short x, short y) const{ + if(!is_on_map(x, y)) return false; return fields[x][y] & SPECIAL_SPOT; } bool cCurTown::is_road(short x, short y) const{ + if(!is_on_map(x, y)) return false; return fields[x][y] & SPECIAL_ROAD; } bool cCurTown::is_special(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; location check(x,y); for(int i = 0; i < record()->special_locs.size(); i++) if(check == record()->special_locs[i] && record()->special_locs[i].spec >= 0) @@ -292,89 +294,89 @@ bool cCurTown::is_special(short x, short y) const{ } bool cCurTown::is_web(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & FIELD_WEB; } bool cCurTown::is_crate(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & OBJECT_CRATE; } bool cCurTown::is_barrel(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & OBJECT_BARREL; } bool cCurTown::is_fire_barr(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & BARRIER_FIRE; } bool cCurTown::is_force_barr(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & BARRIER_FORCE; } bool cCurTown::is_quickfire(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & FIELD_QUICKFIRE; } bool cCurTown::is_sm_blood(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & SFX_SMALL_BLOOD; } bool cCurTown::is_med_blood(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & SFX_MEDIUM_BLOOD; } bool cCurTown::is_lg_blood(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & SFX_LARGE_BLOOD; } bool cCurTown::is_sm_slime(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & SFX_SMALL_SLIME; } bool cCurTown::is_lg_slime(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & SFX_LARGE_SLIME; } bool cCurTown::is_ash(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & SFX_ASH; } bool cCurTown::is_bones(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & SFX_BONES; } bool cCurTown::is_rubble(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & SFX_RUBBLE; } bool cCurTown::is_force_cage(short x, short y) const{ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; return fields[x][y] & BARRIER_CAGE; } bool cCurTown::set_explored(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b) fields[x][y] |= SPECIAL_EXPLORED; else fields[x][y] &= ~SPECIAL_EXPLORED; return true; } bool cCurTown::set_force_wall(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on space, there's no room for field. if(is_impassable(x,y)) return false; @@ -391,7 +393,7 @@ bool cCurTown::set_force_wall(short x, short y, bool b){ } bool cCurTown::set_fire_wall(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on space, there's no room for field. if(is_impassable(x,y)) return false; @@ -410,7 +412,7 @@ bool cCurTown::set_fire_wall(short x, short y, bool b){ } bool cCurTown::set_antimagic(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on space, there's no room for a field. if(is_impassable(x,y)) return false; @@ -430,7 +432,7 @@ bool cCurTown::set_antimagic(short x, short y, bool b){ } bool cCurTown::set_scloud(short x, short y, bool b){ // stinking cloud - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on space, there's no room for cloud. if(is_impassable(x,y)) return false; @@ -447,7 +449,7 @@ bool cCurTown::set_scloud(short x, short y, bool b){ // stinking cloud } bool cCurTown::set_ice_wall(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on space, ther's no room for a field. if(is_impassable(x,y)) return false; @@ -466,7 +468,7 @@ bool cCurTown::set_ice_wall(short x, short y, bool b){ } bool cCurTown::set_blade_wall(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // if certain things are on space, there's no room for a field. if(is_impassable(x,y)) return false; @@ -481,7 +483,7 @@ bool cCurTown::set_blade_wall(short x, short y, bool b){ } bool cCurTown::set_sleep_cloud(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // if certain things are on space, there's no room for cloud. if(is_impassable(x,y)) return false; @@ -496,28 +498,28 @@ bool cCurTown::set_sleep_cloud(short x, short y, bool b){ } bool cCurTown::set_block(short x, short y, bool b){ // currently unused - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b) fields[x][y] |= OBJECT_BLOCK; else fields[x][y] &= ~OBJECT_BLOCK; return true; } bool cCurTown::set_spot(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b) fields[x][y] |= SPECIAL_SPOT; else fields[x][y] &= ~SPECIAL_SPOT; return true; } bool cCurTown::set_road(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b) fields[x][y] |= SPECIAL_ROAD; else fields[x][y] &= ~SPECIAL_ROAD; return true; } bool cCurTown::set_web(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on the space, there's no room for webs if(is_impassable(x,y)) return false; @@ -534,7 +536,7 @@ bool cCurTown::set_web(short x, short y, bool b){ } bool cCurTown::set_crate(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on the space, there's no room for a crate. if(is_fire_barr(x,y) || is_force_barr(x,y) || is_quickfire(x,y) || is_barrel(x,y)) return false; @@ -545,7 +547,7 @@ bool cCurTown::set_crate(short x, short y, bool b){ } bool cCurTown::set_barrel(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on the space, there's no room for a crate. if(is_fire_barr(x,y) || is_force_barr(x,y) || is_quickfire(x,y) || is_crate(x,y)) return false; @@ -556,7 +558,7 @@ bool cCurTown::set_barrel(short x, short y, bool b){ } bool cCurTown::set_fire_barr(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on the space, there's no room for a barrier. if(is_barrel(x,y) || is_force_barr(x,y) || is_quickfire(x,y) || is_crate(x,y)) return false; @@ -578,7 +580,7 @@ bool cCurTown::set_fire_barr(short x, short y, bool b){ } bool cCurTown::set_force_barr(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on the space, there's no room for a barrier. if(is_fire_barr(x,y) || is_barrel(x,y) || is_quickfire(x,y) || is_crate(x,y)) return false; @@ -600,7 +602,7 @@ bool cCurTown::set_force_barr(short x, short y, bool b){ } bool cCurTown::set_quickfire(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ // If certain things are on space, there's no room for quickfire. ter_num_t ter = record()->terrain(x,y); if(univ.scenario.ter_types[ter].blockage == eTerObstruct::BLOCK_SIGHT) @@ -632,6 +634,7 @@ bool cCurTown::set_quickfire(short x, short y, bool b){ } bool cCurTown::free_for_sfx(short x, short y) { + if(!is_on_map(x, y)) return false; ter_num_t ter; ter = record()->terrain(x,y); if(univ.scenario.ter_types[ter].blockage != eTerObstruct::CLEAR) @@ -640,7 +643,7 @@ bool cCurTown::free_for_sfx(short x, short y) { } bool cCurTown::set_sm_blood(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ if(!free_for_sfx(x,y)) return false; if(is_med_blood(x,y) || is_lg_blood(x,y)) @@ -657,7 +660,7 @@ bool cCurTown::set_sm_blood(short x, short y, bool b){ } bool cCurTown::set_med_blood(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ if(!free_for_sfx(x,y)) return false; if(is_lg_blood(x,y)) @@ -675,7 +678,7 @@ bool cCurTown::set_med_blood(short x, short y, bool b){ } bool cCurTown::set_lg_blood(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ if(!free_for_sfx(x,y)) return false; set_sm_blood(x,y,false); @@ -692,6 +695,7 @@ bool cCurTown::set_lg_blood(short x, short y, bool b){ } bool cCurTown::set_sm_slime(short x, short y, bool b){ + if(!is_on_map(x, y)) return false; if(b){ if(!free_for_sfx(x,y)) return false; if(is_lg_slime(x,y)) @@ -709,7 +713,7 @@ bool cCurTown::set_sm_slime(short x, short y, bool b){ } bool cCurTown::set_lg_slime(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ if(!free_for_sfx(x,y)) return false; set_sm_blood(x,y,false); @@ -726,7 +730,7 @@ bool cCurTown::set_lg_slime(short x, short y, bool b){ } bool cCurTown::set_ash(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ if(!free_for_sfx(x,y)) return false; set_sm_blood(x,y,false); @@ -743,7 +747,7 @@ bool cCurTown::set_ash(short x, short y, bool b){ } bool cCurTown::set_bones(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ if(!free_for_sfx(x,y)) return false; set_sm_blood(x,y,false); @@ -760,7 +764,7 @@ bool cCurTown::set_bones(short x, short y, bool b){ } bool cCurTown::set_rubble(short x, short y, bool b){ - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b){ if(!free_for_sfx(x,y)) return false; set_sm_blood(x,y,false); @@ -779,7 +783,7 @@ bool cCurTown::set_rubble(short x, short y, bool b){ bool cCurTown::set_force_cage(short x, short y, bool b){ // TODO: Consider whether placing a forcecage should erase anything already present, or fail due to something already present // TODO: Also consider checking for forcecage in some of the other placement functions. - if(x > record()->max_dim || y > record()->max_dim) return false; + if(!is_on_map(x, y)) return false; if(b) fields[x][y] |= BARRIER_CAGE; else fields[x][y] &= ~BARRIER_CAGE; return true; @@ -787,6 +791,7 @@ bool cCurTown::set_force_cage(short x, short y, bool b){ // TODO: This seems to be wrong; impassable implies "blocks movement", which two other blockages also do bool cCurTown::is_impassable(short i,short j) { + if(!is_on_map(i, j)) return false; ter_num_t ter; ter = record()->terrain(i,j); @@ -795,6 +800,13 @@ bool cCurTown::is_impassable(short i,short j) { else return false; } +bool cCurTown::is_on_map(short x, short y) const { + if(x < 0 || y < 0) return false; + if(x >= record()->max_dim) return false; + if(y >= record()->max_dim) return false; + return true; +} + auto cCurOut::operator [] (size_t i) -> arr_96& { return out[i]; } @@ -926,6 +938,13 @@ bool cCurOut::is_road(int x, int y) { return univ.scenario.outdoors[sector_x][sector_y]->roads[x][y]; } +bool cCurOut::is_on_map(int x, int y) { + if(x < 0 || y < 0) return false; + if(x >= max_dim) return false; + if(y >= max_dim) return false; + return true; +} + cUniverse::cUniverse(ePartyPreset party_type) : party(party_type), out(*this), town(*this) {} cUniverse::cUniverse(const cUniverse& other) diff --git a/src/universe/universe.hpp b/src/universe/universe.hpp index b43dfb5c..c7328bb1 100644 --- a/src/universe/universe.hpp +++ b/src/universe/universe.hpp @@ -118,6 +118,7 @@ public: bool set_force_cage(short x, short y, bool b); bool set_road(short x, short y, bool b); bool is_impassable(short x, short y); + bool is_on_map(short x, short y) const; void writeTo(cTagFile& file) const; void readFrom(const cTagFile& file); @@ -145,6 +146,7 @@ public: // These take global coords (ie 0..95) bool is_spot(int x, int y); bool is_road(int x, int y); + bool is_on_map(int x, int y); void import_legacy(legacy::out_info_type& old);