Scenerio Editor: try to allow to edit scenario with bogus terrain type or

bogus terrain picture nums.
This commit is contained in:
ALONSO Laurent
2021-10-18 10:05:52 +02:00
committed by Celtic Minstrel
parent e4d220799e
commit 1b7dcaab1f
10 changed files with 129 additions and 101 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -211,6 +211,26 @@ cScenario::cItemStorage::cItemStorage() : ter_type(-1), property(0) {
item_odds[i] = 0; item_odds[i] = 0;
} }
cTerrain const &cScenario::get_terrain(ter_num_t ter) const
{
if (ter<ter_types.size())
return ter_types[ter];
static cTerrain badTerrain;
badTerrain.picture = -3;
badTerrain.map_pic = -3;
return badTerrain;
}
cTerrain &cScenario::get_terrain(ter_num_t ter)
{
if (ter<ter_types.size())
return ter_types[ter];
static cTerrain badTerrain;
badTerrain.picture = -3;
badTerrain.map_pic = -3;
return badTerrain;
}
void cScenario::import_legacy(legacy::scenario_data_type const &old){ void cScenario::import_legacy(legacy::scenario_data_type const &old){
is_legacy = true; is_legacy = true;
difficulty = old.difficulty; difficulty = old.difficulty;

View File

@@ -49,6 +49,8 @@ public:
cItemStorage& operator = (legacy::item_storage_shortcut_type const &old); cItemStorage& operator = (legacy::item_storage_shortcut_type const &old);
}; };
void destroy_terrain(); void destroy_terrain();
cTerrain const &get_terrain(ter_num_t ter) const;
cTerrain &get_terrain(ter_num_t ter);
public: public:
unsigned short difficulty,intro_pic,default_ground; unsigned short difficulty,intro_pic,default_ground;
int bg_out, bg_fight, bg_town, bg_dungeon; int bg_out, bg_fight, bg_town, bg_dungeon;

View File

@@ -421,7 +421,7 @@ cPictNum cTerrain::get_picture_num_for_terrain(pic_num_t bigPicture)
else : PIC_CUSTOM_TER else : PIC_CUSTOM_TER
*/ */
if(bigPicture < 0) if(bigPicture < 0)
return cPictNum(-1,PIC_NONE); return cPictNum(bigPicture,PIC_NONE);
if(bigPicture < 960) if(bigPicture < 960)
return cPictNum(bigPicture,PIC_TER); return cPictNum(bigPicture,PIC_TER);
if(bigPicture < 1000) if(bigPicture < 1000)

View File

@@ -794,7 +794,7 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
break; break;
case 0: case 0:
overall_mode = MODE_DRAWING; overall_mode = MODE_DRAWING;
set_string("Drawing mode",scenario.ter_types[current_terrain_type].name); set_string("Drawing mode",scenario.get_terrain(current_terrain_type).name);
break; break;
} }
break; break;
@@ -983,7 +983,7 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
{ {
auto& signs = editing_town ? town->sign_locs : current_terrain->sign_locs; auto& signs = editing_town ? town->sign_locs : current_terrain->sign_locs;
auto iter = std::find(signs.begin(), signs.end(), spot_hit); auto iter = std::find(signs.begin(), signs.end(), spot_hit);
short picture = scenario.ter_types[editing_town ? town->terrain(spot_hit.x,spot_hit.y) : current_terrain->terrain[spot_hit.x][spot_hit.y]].picture; short picture = scenario.get_terrain(editing_town ? town->terrain(spot_hit.x,spot_hit.y) : current_terrain->terrain[spot_hit.x][spot_hit.y]).picture;
if(iter != signs.end()) { if(iter != signs.end()) {
edit_sign(*iter, iter - signs.begin(), picture); edit_sign(*iter, iter - signs.begin(), picture);
} else { } else {
@@ -1145,7 +1145,7 @@ static bool handle_terrain_action(location the_point, bool ctrl_hit) {
break; // Nothing to do here, of course. break; // Nothing to do here, of course.
} }
if((overall_mode == MODE_DRAWING) && (old_mode != MODE_DRAWING)) if((overall_mode == MODE_DRAWING) && (old_mode != MODE_DRAWING))
set_string("Drawing mode",scenario.ter_types[current_terrain_type].name); set_string("Drawing mode",scenario.get_terrain(current_terrain_type).name);
draw_terrain(); draw_terrain();
return true; return true;
} }
@@ -1228,10 +1228,10 @@ static bool handle_terpal_action(location cur_point, bool option_hit) {
else if(i == size_before) { else if(i == size_before) {
scenario.ter_types.resize(size_before + 16); scenario.ter_types.resize(size_before + 16);
for(; i < scenario.ter_types.size(); i++) for(; i < scenario.ter_types.size(); i++)
scenario.ter_types[i].name = "New Terrain"; scenario.get_terrain(i).name = "New Terrain";
} else { } else {
scenario.ter_types[i] = cTerrain(); scenario.get_terrain(i) = cTerrain();
scenario.ter_types[i].name = "Unused Terrain"; scenario.get_terrain(i).name = "Unused Terrain";
} }
} else { } else {
if(i == size_before) { if(i == size_before) {
@@ -1262,27 +1262,28 @@ static bool handle_toolpal_action(location cur_point2) {
rectangle temp_rect = palette_buttons[i][j]; rectangle temp_rect = palette_buttons[i][j];
temp_rect.offset(RIGHT_AREA_UL_X + 5, RIGHT_AREA_UL_Y + terrain_rects[255].bottom + 5); temp_rect.offset(RIGHT_AREA_UL_X + 5, RIGHT_AREA_UL_Y + terrain_rects[255].bottom + 5);
flash_rect(temp_rect); flash_rect(temp_rect);
auto const &ter_type=scenario.get_terrain(current_terrain_type);
switch(cur_palette_buttons[j][i]) { switch(cur_palette_buttons[j][i]) {
case PAL_ARROW_UP: case PAL_ARROW_DOWN: // These two might never be used. case PAL_ARROW_UP: case PAL_ARROW_DOWN: // These two might never be used.
case PAL_BLANK: break; case PAL_BLANK: break;
case PAL_PENCIL: case PAL_PENCIL:
set_string("Drawing mode",scenario.ter_types[current_terrain_type].name); set_string("Drawing mode",ter_type.name);
overall_mode = MODE_DRAWING; overall_mode = MODE_DRAWING;
break; break;
case PAL_BRUSH_LG: case PAL_BRUSH_LG:
set_string("Paintbrush (large)",scenario.ter_types[current_terrain_type].name); set_string("Paintbrush (large)",ter_type.name);
overall_mode = MODE_LARGE_PAINTBRUSH; overall_mode = MODE_LARGE_PAINTBRUSH;
break; break;
case PAL_BRUSH_SM: case PAL_BRUSH_SM:
set_string("Paintbrush (small)",scenario.ter_types[current_terrain_type].name); set_string("Paintbrush (small)",ter_type.name);
overall_mode = MODE_SMALL_PAINTBRUSH; overall_mode = MODE_SMALL_PAINTBRUSH;
break; break;
case PAL_SPRAY_LG: case PAL_SPRAY_LG:
set_string("Spraycan (large)",scenario.ter_types[current_terrain_type].name); set_string("Spraycan (large)",ter_type.name);
overall_mode = MODE_LARGE_SPRAYCAN; overall_mode = MODE_LARGE_SPRAYCAN;
break; break;
case PAL_SPRAY_SM: case PAL_SPRAY_SM:
set_string("Spraycan (small)",scenario.ter_types[current_terrain_type].name); set_string("Spraycan (small)",ter_type.name);
overall_mode = MODE_SMALL_SPRAYCAN; overall_mode = MODE_SMALL_SPRAYCAN;
break; break;
case PAL_DROPPER: case PAL_DROPPER:
@@ -1300,7 +1301,7 @@ static bool handle_toolpal_action(location cur_point2) {
break; break;
case PAL_BUCKET: case PAL_BUCKET:
overall_mode = MODE_FLOOD_FILL; overall_mode = MODE_FLOOD_FILL;
set_string("Flood fill", scenario.ter_types[current_terrain_type].name); set_string("Flood fill", ter_type.name);
break; break;
case PAL_ZOOM: // switch view case PAL_ZOOM: // switch view
cur_viewing_mode = (cur_viewing_mode + 1) % 4; cur_viewing_mode = (cur_viewing_mode + 1) % 4;
@@ -1602,15 +1603,15 @@ void set_new_terrain(ter_num_t selected_terrain) {
if(selected_terrain >= scenario.ter_types.size()) return; if(selected_terrain >= scenario.ter_types.size()) return;
current_terrain_type = selected_terrain; current_terrain_type = selected_terrain;
current_ground = scenario.get_ground_from_ter(selected_terrain); current_ground = scenario.get_ground_from_ter(selected_terrain);
cTerrain& ter = scenario.ter_types[current_terrain_type]; cTerrain const & ter = scenario.get_terrain(current_terrain_type);
cTerrain& gter = scenario.ter_types[current_ground]; cTerrain const &gter = scenario.get_terrain(current_ground);
if(gter.blockage >= eTerObstruct::BLOCK_MOVE || ter.trim_type == eTrimType::WALKWAY || /*current_ground == current_terrain_type ||*/ if(gter.blockage >= eTerObstruct::BLOCK_MOVE || ter.trim_type == eTrimType::WALKWAY || /*current_ground == current_terrain_type ||*/
(ter.trim_type >= eTrimType::S && ter.trim_type <= eTrimType::NW_INNER)) { (ter.trim_type >= eTrimType::S && ter.trim_type <= eTrimType::NW_INNER)) {
long trim = scenario.ter_types[current_ground].trim_ter; long trim = gter.trim_ter;
if(trim < 0) current_ground = 0; if(trim < 0) current_ground = 0;
else current_ground = scenario.get_ter_from_ground(trim); else current_ground = scenario.get_ter_from_ground(trim);
} }
set_string(current_string[0],scenario.ter_types[current_terrain_type].name); set_string(current_string[0],ter.name);
} }
void handle_keystroke(sf::Event event) { void handle_keystroke(sf::Event event) {
@@ -1870,7 +1871,7 @@ void unfrill_terrain() {
for(short i = 0; i < ((editing_town) ? town->max_dim : 48); i++) 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 j = 0; j < ((editing_town) ? town->max_dim : 48); j++) {
terrain_type = editing_town ? town->terrain(i,j) : current_terrain->terrain[i][j]; terrain_type = editing_town ? town->terrain(i,j) : current_terrain->terrain[i][j];
cTerrain& ter = scenario.ter_types[terrain_type]; cTerrain const &ter = scenario.get_terrain(terrain_type);
if(ter.frill_for >= 0) if(ter.frill_for >= 0)
terrain_type = ter.frill_for; terrain_type = ter.frill_for;
@@ -1896,21 +1897,19 @@ bool terrain_matches(unsigned char x, unsigned char y, ter_num_t ter) {
ter_num_t ter2; ter_num_t ter2;
if(editing_town) ter2 = town->terrain(x,y); else ter2 = current_terrain->terrain[x][y]; if(editing_town) ter2 = town->terrain(x,y); else ter2 = current_terrain->terrain[x][y];
if(ter2 == ter) return true; if(ter2 == ter) return true;
if(scenario.ter_types[ter2].ground_type != scenario.ter_types[ter].ground_type) auto const &ter_type=scenario.get_terrain(ter);
auto const &ter_type2=scenario.get_terrain(ter2);
if(ter_type2.ground_type != ter_type.ground_type)
return false; return false;
if(scenario.ter_types[ter].trim_type == eTrimType::NONE && if(ter_type.trim_type == eTrimType::NONE && ter_type2.trim_type >= eTrimType::S &&
scenario.ter_types[ter2].trim_type >= eTrimType::S && ter_type2.trim_type <= eTrimType::NW_INNER)
scenario.ter_types[ter2].trim_type <= eTrimType::NW_INNER)
return ter == scenario.get_ground_from_ter(ter); return ter == scenario.get_ground_from_ter(ter);
if(scenario.ter_types[ter2].trim_type == eTrimType::NONE && if(ter_type2.trim_type == eTrimType::NONE && ter_type.trim_type >= eTrimType::S &&
scenario.ter_types[ter].trim_type >= eTrimType::S && ter_type.trim_type <= eTrimType::NW_INNER)
scenario.ter_types[ter].trim_type <= eTrimType::NW_INNER)
return ter2 == scenario.get_ground_from_ter(ter2); return ter2 == scenario.get_ground_from_ter(ter2);
if(scenario.ter_types[ter2].trim_type >= eTrimType::S && if(ter_type2.trim_type >= eTrimType::S && ter_type2.trim_type <= eTrimType::NW_INNER &&
scenario.ter_types[ter2].trim_type <= eTrimType::NW_INNER && ter_type.trim_type >= eTrimType::S && ter_type.trim_type <= eTrimType::NW_INNER)
scenario.ter_types[ter].trim_type >= eTrimType::S && return ter_type.trim_type != ter_type2.trim_type;
scenario.ter_types[ter].trim_type <= eTrimType::NW_INNER)
return scenario.ter_types[ter].trim_type != scenario.ter_types[ter2].trim_type;
return false; return false;
} }
@@ -1932,10 +1931,11 @@ void set_terrain(location l,ter_num_t terrain_type) {
l2 = l; l2 = l;
// Large objects (eg rubble) // Large objects (eg rubble)
if(scenario.ter_types[terrain_type].obj_num > 0){ auto const &ter_type=scenario.get_terrain(terrain_type);
int q = scenario.ter_types[terrain_type].obj_num; if(ter_type.obj_num > 0){
location obj_loc = scenario.ter_types[terrain_type].obj_pos; int q = ter_type.obj_num;
location obj_dim = scenario.ter_types[terrain_type].obj_size; location obj_loc = ter_type.obj_pos;
location obj_dim = ter_type.obj_size;
while(obj_loc.x > 0) l2.x-- , obj_loc.x--; while(obj_loc.x > 0) l2.x-- , obj_loc.x--;
while(obj_loc.y > 0) l2.y-- , obj_loc.y--; while(obj_loc.y > 0) l2.y-- , obj_loc.y--;
for(short i = 0; i < obj_dim.x; i++) for(short i = 0; i < obj_dim.x; i++)
@@ -1948,17 +1948,18 @@ void set_terrain(location l,ter_num_t terrain_type) {
// First make sure surrounding spaces have the correct ground types. // First make sure surrounding spaces have the correct ground types.
// This should handle the case of placing hills around mountains. // This should handle the case of placing hills around mountains.
unsigned int main_ground = scenario.ter_types[terrain_type].ground_type; auto const &terrain_ground=scenario.get_terrain(terrain_type);
long trim_ground = scenario.ter_types[terrain_type].trim_ter; unsigned int main_ground = terrain_ground.ground_type;
long trim_ground = terrain_ground.trim_ter;
for(int x = -1; x <= 1; x++) { for(int x = -1; x <= 1; x++) {
for(int y = -1; y <= 1; y++) { for(int y = -1; y <= 1; y++) {
location l3(l.x+x,l.y+y); location l3(l.x+x,l.y+y);
ter_num_t ter_there = editing_town ? town->terrain(l3.x,l3.y) : current_terrain->terrain[l3.x][l3.y]; ter_num_t ter_there = editing_town ? town->terrain(l3.x,l3.y) : current_terrain->terrain[l3.x][l3.y];
unsigned int ground_there = scenario.ter_types[ter_there].ground_type; unsigned int ground_there = scenario.get_terrain(ter_there).ground_type;
if(ground_there != main_ground && ground_there != trim_ground) { if(ground_there != main_ground && ground_there != trim_ground) {
ter_num_t new_ter = scenario.get_ter_from_ground(trim_ground); ter_num_t new_ter = scenario.get_ter_from_ground(trim_ground);
if(new_ter > scenario.ter_types.size()) continue; if(new_ter > scenario.ter_types.size()) continue;
cTerrain& ter_type = scenario.ter_types[new_ter]; cTerrain const & ter_type = scenario.get_terrain(new_ter);
// We need to be very cautious here. // We need to be very cautious here.
// Only make the change if the terrain already there is the archetype for the ground type // Only make the change if the terrain already there is the archetype for the ground type
// that is the trim terrain of the terrain we're trying to place. // that is the trim terrain of the terrain we're trying to place.
@@ -1978,7 +1979,7 @@ void set_terrain(location l,ter_num_t terrain_type) {
adjust_space(l3); adjust_space(l3);
} }
if(scenario.ter_types[terrain_type].special == eTerSpec::IS_A_SIGN) { if(terrain_ground.special == eTerSpec::IS_A_SIGN) {
if(!editing_town && (l.x == 0 || l.x == 47 || l.y == 0 || l.y == 47)) { if(!editing_town && (l.x == 0 || l.x == 47 || l.y == 0 || l.y == 47)) {
cChoiceDlog("not-at-edge").show(); cChoiceDlog("not-at-edge").show();
mouse_button_held = false; mouse_button_held = false;
@@ -1990,7 +1991,7 @@ void set_terrain(location l,ter_num_t terrain_type) {
iter = std::find_if(signs.begin(), signs.end(), [](const sign_loc_t& sign) { iter = std::find_if(signs.begin(), signs.end(), [](const sign_loc_t& sign) {
if(sign.x == 100) return true; 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 = editing_town ? town->terrain(sign.x,sign.y) : current_terrain->terrain[sign.x][sign.y];
return scenario.ter_types[ter].special != eTerSpec::IS_A_SIGN; return scenario.get_terrain(ter).special != eTerSpec::IS_A_SIGN;
}); });
if(iter == signs.end()) { if(iter == signs.end()) {
signs.emplace_back(); signs.emplace_back();
@@ -1999,7 +2000,7 @@ void set_terrain(location l,ter_num_t terrain_type) {
} }
static_cast<location&>(*iter) = l; static_cast<location&>(*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 = editing_town ? town->terrain(iter->x,iter->y) : current_terrain->terrain[iter->x][iter->y];
edit_sign(*iter, iter - signs.begin(), scenario.ter_types[terrain_type].picture); edit_sign(*iter, iter - signs.begin(), scenario.get_terrain(terrain_type).picture);
mouse_button_held = false; mouse_button_held = false;
} }
} }
@@ -2030,7 +2031,7 @@ void adjust_space(location l) {
continue; continue;
} }
store_ter[dx+1][dy+1] = editing_town ? town->terrain(x,y) : current_terrain->terrain[x][y]; store_ter[dx+1][dy+1] = editing_town ? town->terrain(x,y) : current_terrain->terrain[x][y];
cTerrain& ter_type = scenario.ter_types[store_ter[dx+1][dy+1]]; cTerrain const &ter_type = scenario.get_terrain(store_ter[dx+1][dy+1]);
store_ter2[dx+1][dy+1] = ter_type.trim_ter; store_ter2[dx+1][dy+1] = ter_type.trim_ter;
store_ground[dx+1][dy+1] = ter_type.ground_type; store_ground[dx+1][dy+1] = ter_type.ground_type;
store_trim[dx+1][dy+1] = ter_type.trim_type; store_trim[dx+1][dy+1] = ter_type.trim_type;
@@ -2043,7 +2044,7 @@ void adjust_space(location l) {
if(store_trim[1][1] >= eTrimType::FRILLS || store_trim[1][1] == eTrimType::WALL) if(store_trim[1][1] >= eTrimType::FRILLS || store_trim[1][1] == eTrimType::WALL)
return; return;
bool have_wall = scenario.ter_types[store_ter[1][1]].blockage >= eTerObstruct::BLOCK_MOVE; bool have_wall = scenario.get_terrain(store_ter[1][1]).blockage >= eTerObstruct::BLOCK_MOVE;
unsigned int main_ground = store_ground[1][1]; unsigned int main_ground = store_ground[1][1];
long trim_ground = store_ter2[1][1]; long trim_ground = store_ter2[1][1];
@@ -2206,7 +2207,7 @@ void set_special(location spot_hit) {
void town_entry(location spot_hit) { void town_entry(location spot_hit) {
ter_num_t ter = current_terrain->terrain[spot_hit.x][spot_hit.y]; ter_num_t ter = current_terrain->terrain[spot_hit.x][spot_hit.y];
if(scenario.ter_types[ter].special != eTerSpec::TOWN_ENTRANCE) { if(scenario.get_terrain(ter).special != eTerSpec::TOWN_ENTRANCE) {
showError("This space isn't a town entrance. Town entrances are marked by a small brown castle icon."); showError("This space isn't a town entrance. Town entrances are marked by a small brown castle icon.");
return; return;
} }
@@ -2214,7 +2215,7 @@ void town_entry(location spot_hit) {
for(short x = 0; x < current_terrain->city_locs.size(); x++) for(short x = 0; x < current_terrain->city_locs.size(); x++)
if(current_terrain->city_locs[x].spec >= 0) { if(current_terrain->city_locs[x].spec >= 0) {
ter = current_terrain->terrain[current_terrain->city_locs[x].x][current_terrain->city_locs[x].y]; ter = current_terrain->terrain[current_terrain->city_locs[x].x][current_terrain->city_locs[x].y];
if(scenario.ter_types[ter].special != eTerSpec::TOWN_ENTRANCE) if(scenario.get_terrain(ter).special != eTerSpec::TOWN_ENTRANCE)
current_terrain->city_locs[x].spec = -1; current_terrain->city_locs[x].spec = -1;
} }
auto iter = std::find(current_terrain->city_locs.begin(), current_terrain->city_locs.end(), spot_hit); auto iter = std::find(current_terrain->city_locs.begin(), current_terrain->city_locs.end(), spot_hit);
@@ -2336,7 +2337,7 @@ void start_town_edit() {
shut_down_menus(2); shut_down_menus(2);
right_sbar->hide(); right_sbar->hide();
pal_sbar->show(); pal_sbar->show();
set_string("Drawing mode",scenario.ter_types[current_terrain_type].name); set_string("Drawing mode",scenario.get_terrain(current_terrain_type).name);
place_location(); place_location();
copied_spec = -1; copied_spec = -1;
for(short i = 0; i < town->max_dim; i++) for(short i = 0; i < town->max_dim; i++)
@@ -2367,7 +2368,7 @@ void start_out_edit() {
pal_sbar->show(); pal_sbar->show();
shut_down_menus(4); shut_down_menus(4);
shut_down_menus(1); shut_down_menus(1);
set_string("Drawing mode",scenario.ter_types[current_terrain_type].name); set_string("Drawing mode",scenario.get_terrain(current_terrain_type).name);
place_location(); place_location();
copied_spec = -1; copied_spec = -1;
for(short i = 0; i < 48; i++) for(short i = 0; i < 48; i++)

View File

@@ -349,38 +349,34 @@ static bool fill_ter_flag_info(cDialog& me, std::string id, bool losing){
return true; return true;
} }
// REMOVEME when setPict will not do fatal error
bool check_picture_num(cPictNum const &pic, bool noneIsOk)
try {
if (noneIsOk && pic.num==-1)
return true;
if (pic.num<0)
return false;
if (pic.type==ePicType::PIC_TER)
// REMOVEME when setPict will not do fatal error
*ResMgr::textures.get("ter" + std::to_string(1 + pic.num / 50));
return true;
}
catch(...) {
return false;
}
static void fill_ter_info(cDialog& me, short ter){ static void fill_ter_info(cDialog& me, short ter){
cTerrain& ter_type = scenario.ter_types[ter]; cTerrain const & ter_type = scenario.get_terrain(ter);
{ {
cPict& pic_ctrl = dynamic_cast<cPict&>(me["graphic"]); cPict& pic_ctrl = dynamic_cast<cPict&>(me["graphic"]);
bool bad=false; if (check_picture_num(ter_type.get_picture_num(), false)) // REMOVEME
if (ter_type.get_picture_num().type==ePicType::PIC_TER) {
// REMOVEME when setPict will not do fatal error
try {
*ResMgr::textures.get("ter" + std::to_string(1 + ter_type.get_picture_num().num / 50));
}
catch(...) {
bad=true;
}
}
if (!bad)
pic_ctrl.setPict(ter_type.get_picture_num()); pic_ctrl.setPict(ter_type.get_picture_num());
else else
pic_ctrl.setPict(cPictNum(1999,ePicType::PIC_CUSTOM_TER)); pic_ctrl.setPict(cPictNum(1999,ePicType::PIC_CUSTOM_TER));
me["pict"].setTextToNum(ter_type.picture); me["pict"].setTextToNum(ter_type.picture);
}{ }{
cPict& pic_ctrl = dynamic_cast<cPict&>(me["seemap"]); cPict& pic_ctrl = dynamic_cast<cPict&>(me["seemap"]);
bool bad=false; if (check_picture_num(ter_type.get_map_picture_num(), false)) // REMOVEME
if (ter_type.get_map_picture_num().type==ePicType::PIC_TER) {
// REMOVEME when setPict will not do fatal error
try {
*ResMgr::textures.get("ter" + std::to_string(1 + ter_type.get_map_picture_num().num / 50));
}
catch(...) {
bad=true;
}
}
if (!bad) // FIXME the picture size is bad if we revert to the main picture
pic_ctrl.setPict(ter_type.get_map_picture_num()); pic_ctrl.setPict(ter_type.get_map_picture_num());
else else
pic_ctrl.setPict(cPictNum(1999,ePicType::PIC_CUSTOM_TER)); pic_ctrl.setPict(cPictNum(1999,ePicType::PIC_CUSTOM_TER));
@@ -453,7 +449,7 @@ static void fill_ter_info(cDialog& me, short ter){
} }
static bool finish_editing_ter(cDialog& me, std::string id, ter_num_t& which) { static bool finish_editing_ter(cDialog& me, std::string id, ter_num_t& which) {
if(!save_ter_info(me, scenario.ter_types[which])) return true; if(!save_ter_info(me, scenario.get_terrain(which))) return true;
if(!me.toast(true)) return true; if(!me.toast(true)) return true;
if(id == "left") { if(id == "left") {
@@ -473,7 +469,7 @@ static bool finish_editing_ter(cDialog& me, std::string id, ter_num_t& which) {
} }
static bool edit_ter_obj(cDialog& me, ter_num_t which_ter) { static bool edit_ter_obj(cDialog& me, ter_num_t which_ter) {
cTerrain& ter = scenario.ter_types[which_ter]; cTerrain& ter = scenario.get_terrain(which_ter);
const pic_num_t pic = ter.picture; const pic_num_t pic = ter.picture;
cDialog obj_dlg("edit-ter-obj", &me); cDialog obj_dlg("edit-ter-obj", &me);
obj_dlg.attachFocusHandlers([&pic](cDialog& me, std::string fld, bool losing) -> bool { obj_dlg.attachFocusHandlers([&pic](cDialog& me, std::string fld, bool losing) -> bool {
@@ -507,7 +503,10 @@ static bool edit_ter_obj(cDialog& me, ter_num_t which_ter) {
for(int x = 0; x < 4; x++) { for(int x = 0; x < 4; x++) {
for(int y = 0; y < 4; y++) { for(int y = 0; y < 4; y++) {
std::string id = "x" + std::to_string(x) + "y" + std::to_string(y); std::string id = "x" + std::to_string(x) + "y" + std::to_string(y);
dynamic_cast<cPict&>(me[id]).setPict(cTerrain::get_picture_num_for_terrain(obj[x][y])); if (check_picture_num(cTerrain::get_picture_num_for_terrain(obj[x][y]), true))
dynamic_cast<cPict&>(me[id]).setPict(cTerrain::get_picture_num_for_terrain(obj[x][y]));
else
dynamic_cast<cPict&>(me[id]).setPict(cPictNum(1999,ePicType::PIC_CUSTOM_TER));
} }
} }
return true; return true;

View File

@@ -22,6 +22,7 @@ void edit_scenario_events();
bool build_scenario(); bool build_scenario();
bool edit_vehicle(class cVehicle& what, int num, bool is_boat); bool edit_vehicle(class cVehicle& what, int num, bool is_boat);
bool check_picture_num(cPictNum const &pic, bool noneIsOk);
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_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); bool check_range(cDialog& me,std::string id,bool losing,long min_val,long max_val,std::string fld_name);
bool pick_string(std::string from_file, cDialog& parent, std::string result_fld, std::string str_fld); bool pick_string(std::string from_file, cDialog& parent, std::string result_fld, std::string str_fld);

View File

@@ -88,15 +88,16 @@ extern bool small_any_drawn;
static short get_small_icon(ter_num_t ter){ static short get_small_icon(ter_num_t ter){
short icon = -1; short icon = -1;
switch(scenario.ter_types[ter].special){ auto const &ter_type=scenario.get_terrain(ter);
switch(ter_type.special){
case eTerSpec::NONE: case eTerSpec::NONE:
icon = scenario.ter_types[ter].flag1; icon = ter_type.flag1;
break; break;
case eTerSpec::CHANGE_WHEN_STEP_ON: case eTerSpec::CHANGE_WHEN_STEP_ON:
icon = 87; icon = 87;
break; break;
case eTerSpec::DAMAGING: case eTerSpec::DAMAGING:
switch(eDamageType(scenario.ter_types[ter].flag3)) { switch(eDamageType(ter_type.flag3)) {
case eDamageType::WEAPON: case eDamageType::WEAPON:
icon = 16; icon = 16;
break; break;
@@ -136,50 +137,50 @@ static short get_small_icon(ter_num_t ter){
break; break;
case eTerSpec::DANGEROUS: case eTerSpec::DANGEROUS:
icon = 12; icon = 12;
switch((eStatus)scenario.ter_types[ter].flag3){ switch((eStatus)ter_type.flag3){
case eStatus::POISONED_WEAPON: // TODO: Do something here case eStatus::POISONED_WEAPON: // TODO: Do something here
break; break;
case eStatus::BLESS_CURSE: case eStatus::BLESS_CURSE:
icon = scenario.ter_types[ter].flag1 > 0 ? 4 : 5; icon = ter_type.flag1 > 0 ? 4 : 5;
break; break;
case eStatus::POISON: case eStatus::POISON:
if(scenario.ter_types[ter].flag1 > 0) if(ter_type.flag1 > 0)
icon = 1; icon = 1;
break; break;
case eStatus::HASTE_SLOW: case eStatus::HASTE_SLOW:
icon = scenario.ter_types[ter].flag1 > 0 ? 6 : 7; icon = ter_type.flag1 > 0 ? 6 : 7;
break; break;
case eStatus::INVULNERABLE: // TODO: Do something here case eStatus::INVULNERABLE: // TODO: Do something here
break; break;
case eStatus::MAGIC_RESISTANCE: // TODO: Do something here case eStatus::MAGIC_RESISTANCE: // TODO: Do something here
break; break;
case eStatus::WEBS: case eStatus::WEBS:
if(scenario.ter_types[ter].flag1 > 0) if(ter_type.flag1 > 0)
icon = 52; icon = 52;
break; break;
case eStatus::DISEASE: case eStatus::DISEASE:
if(scenario.ter_types[ter].flag1 > 0) if(ter_type.flag1 > 0)
icon = 0; icon = 0;
break; break;
case eStatus::INVISIBLE: // TODO: Do something here case eStatus::INVISIBLE: // TODO: Do something here
break; break;
case eStatus::DUMB: case eStatus::DUMB:
icon = scenario.ter_types[ter].flag1 > 0 ? 8 : 9; icon = ter_type.flag1 > 0 ? 8 : 9;
break; break;
case eStatus::MARTYRS_SHIELD: // TODO: Do something here case eStatus::MARTYRS_SHIELD: // TODO: Do something here
break; break;
case eStatus::ASLEEP: case eStatus::ASLEEP:
if(scenario.ter_types[ter].flag1 > 0) if(ter_type.flag1 > 0)
icon = 3; icon = 3;
break; break;
case eStatus::PARALYZED: // TODO: Do something here case eStatus::PARALYZED: // TODO: Do something here
break; break;
case eStatus::ACID: case eStatus::ACID:
if(scenario.ter_types[ter].flag1 > 0) if(ter_type.flag1 > 0)
icon = 2; icon = 2;
break; break;
case eStatus::FORCECAGE: case eStatus::FORCECAGE:
if(scenario.ter_types[ter].flag1 > 0) if(ter_type.flag1 > 0)
icon = 43; icon = 43;
break; break;
case eStatus::MAIN: case eStatus::CHARM: case eStatus::MAIN: case eStatus::CHARM:
@@ -194,8 +195,8 @@ static short get_small_icon(ter_num_t ter){
icon = 94; icon = 94;
break; break;
case eTerSpec::UNLOCKABLE: case eTerSpec::UNLOCKABLE:
if(scenario.ter_types[ter].flag2 >= 5) if(ter_type.flag2 >= 5)
icon = (scenario.ter_types[ter].flag2 == 10) ? 96 : 95; icon = (ter_type.flag2 == 10) ? 96 : 95;
else icon = 94; else icon = 94;
break; break;
case eTerSpec::IS_A_SIGN: case eTerSpec::IS_A_SIGN:
@@ -203,7 +204,7 @@ static short get_small_icon(ter_num_t ter){
break; break;
case eTerSpec::CALL_SPECIAL: case eTerSpec::CALL_SPECIAL:
case eTerSpec::CALL_SPECIAL_WHEN_USED: case eTerSpec::CALL_SPECIAL_WHEN_USED:
icon = scenario.ter_types[ter].flag3; icon = ter_type.flag3;
break; break;
case eTerSpec::IS_A_CONTAINER: case eTerSpec::IS_A_CONTAINER:
icon = 93; icon = 93;
@@ -213,7 +214,7 @@ static short get_small_icon(ter_num_t ter){
icon = 91; icon = 91;
break; break;
case eTerSpec::CONVEYOR: case eTerSpec::CONVEYOR:
switch(scenario.ter_types[ter].flag1){ switch(ter_type.flag1){
case DIR_N: case DIR_N:
icon = 78; icon = 78;
break; break;
@@ -292,7 +293,7 @@ static std::vector<short> get_small_icons(location at, ter_num_t t_to_draw) {
else icons.push_back(88); else icons.push_back(88);
} }
if(editing_town) { if(editing_town) {
if(scenario.ter_types[t_to_draw].light_radius > 0) if(scenario.get_terrain(t_to_draw).light_radius > 0)
icons.push_back(83); icons.push_back(83);
for(size_t i = 0; i < town->start_locs.size(); i++) for(size_t i = 0; i < town->start_locs.size(); i++)
if(at == town->start_locs[i]) { if(at == town->start_locs[i]) {
@@ -363,7 +364,7 @@ try {
catch (...) { catch (...) {
if (pict.num==-1) // ok no picture if (pict.num==-1) // ok no picture
return false; return false;
std::cerr << "Error[get_terrain_picture]: can not find picture id=" << pict.num << "type=" << int(pict.type)<< "\n"; std::cerr << "Error[get_terrain_picture]: can not find picture id=" << pict.num << ", type=" << int(pict.type)<< "\n";
source = *ResMgr::textures.get("errors"); source = *ResMgr::textures.get("errors");
from_rect={0,0,40,40}; from_rect={0,0,40,40};
return true; return true;
@@ -584,7 +585,7 @@ void set_up_terrain_buttons(bool reset) {
break; break;
} }
Texture source_gworld; Texture source_gworld;
if (get_terrain_picture(scenario.ter_types[i].get_picture_num(), source_gworld, ter_from)) if (get_terrain_picture(scenario.get_terrain(i).get_picture_num(), source_gworld, ter_from))
rect_draw_some_item(source_gworld,ter_from, mainPtr, draw_rect); rect_draw_some_item(source_gworld,ter_from, mainPtr, draw_rect);
small_i = get_small_icon(i); small_i = get_small_icon(i);
tiny_from = base_small_button_from; tiny_from = base_small_button_from;
@@ -927,7 +928,7 @@ void draw_terrain(){
} }
} }
} else if(overall_mode == MODE_DRAWING) { } else if(overall_mode == MODE_DRAWING) {
cTerrain& ter = scenario.ter_types[current_terrain_type]; cTerrain& ter = scenario.get_terrain(current_terrain_type);
if(ter.obj_num > 0) { if(ter.obj_num > 0) {
// TODO: Don't do this if auto-completion of large terrain objects is disabled // TODO: Don't do this if auto-completion of large terrain objects is disabled
for(int x = 0; x < ter.obj_size.x; x++) { for(int x = 0; x < ter.obj_size.x; x++) {
@@ -1146,7 +1147,7 @@ void draw_one_terrain_spot (short i,short j,ter_num_t terrain_to_draw) {
rectangle source_rect; rectangle source_rect;
Texture source_gworld; Texture source_gworld;
if (!get_terrain_picture(scenario.ter_types[terrain_to_draw].get_picture_num(), source_gworld, source_rect)) if (!get_terrain_picture(scenario.get_terrain(terrain_to_draw).get_picture_num(), source_gworld, source_rect))
return; return;
location where_draw; location where_draw;
@@ -1167,7 +1168,7 @@ void draw_one_tiny_terrain_spot (short i,short j,ter_num_t terrain_to_draw,short
Texture source_gworld; Texture source_gworld;
rectangle dest_rect = {0,0,size,size}; rectangle dest_rect = {0,0,size,size};
dest_rect.offset(8 + TER_RECT_UL_X + size * i, 8 + TER_RECT_UL_Y + size * j); dest_rect.offset(8 + TER_RECT_UL_X + size * i, 8 + TER_RECT_UL_Y + size * j);
if (get_terrain_picture(scenario.ter_types[terrain_to_draw].get_map_picture_num(), source_gworld, from_rect)) if (get_terrain_picture(scenario.get_terrain(terrain_to_draw).get_map_picture_num(), source_gworld, from_rect))
rect_draw_some_item(source_gworld, from_rect, mainPtr, dest_rect); rect_draw_some_item(source_gworld, from_rect, mainPtr, dest_rect);
if(road) { if(road) {
rectangle road_rect = dest_rect; rectangle road_rect = dest_rect;
@@ -1206,7 +1207,7 @@ rectangle get_template_rect (unsigned short type_wanted) {
rectangle store_rect; rectangle store_rect;
short picture_wanted; short picture_wanted;
picture_wanted = scenario.ter_types[type_wanted].picture; picture_wanted = scenario.get_terrain(type_wanted).picture;
if(picture_wanted >= 1000) if(picture_wanted >= 1000)
picture_wanted = 0; picture_wanted = 0;
picture_wanted = picture_wanted % 50; picture_wanted = picture_wanted % 50;
@@ -1252,7 +1253,7 @@ void draw_frames() {
static void place_selected_terrain(ter_num_t ter, rectangle draw_rect) { static void place_selected_terrain(ter_num_t ter, rectangle draw_rect) {
rectangle source_rect; rectangle source_rect;
Texture source_gworld; Texture source_gworld;
if (get_terrain_picture(scenario.ter_types[ter].get_picture_num(), source_gworld, source_rect)) if (get_terrain_picture(scenario.get_terrain(ter).get_picture_num(), source_gworld, source_rect))
rect_draw_some_item(source_gworld,source_rect, mainPtr,draw_rect); rect_draw_some_item(source_gworld,source_rect, mainPtr,draw_rect);
short small_i = get_small_icon(ter); short small_i = get_small_icon(ter);
@@ -1289,7 +1290,7 @@ void place_location() {
int first = pal_sbar->getPosition() * 16; int first = pal_sbar->getPosition() * 16;
switch(draw_mode) { switch(draw_mode) {
case DRAW_TERRAIN: case DRAW_TERRAIN:
if(first + i < scenario.ter_types.size()) if(first+i >= 0 && first + i < scenario.ter_types.size())
sout << "Terrain: " << scenario.ter_types[first + i].name; sout << "Terrain: " << scenario.ter_types[first + i].name;
break; break;
case DRAW_ITEM: case DRAW_ITEM:
@@ -1578,7 +1579,7 @@ void take_field_type(short i,short j,eFieldType field_type) {
bool container_there(location l) { bool container_there(location l) {
if(!editing_town) if(!editing_town)
return false; return false;
if(scenario.ter_types[town->terrain(l.x,l.y)].special == eTerSpec::IS_A_CONTAINER) if(scenario.get_terrain(town->terrain(l.x,l.y)).special == eTerSpec::IS_A_CONTAINER)
return true; return true;
if(is_field_type(l.x,l.y, OBJECT_BARREL)) if(is_field_type(l.x,l.y, OBJECT_BARREL))
return true; return true;

View File

@@ -368,7 +368,11 @@ void edit_sign(sign_loc_t& which_sign,short num,short picture) {
cDialog sign_dlg("edit-sign"); cDialog sign_dlg("edit-sign");
sign_dlg["cancel"].attachClickHandler(std::bind(&cDialog::toast, &sign_dlg, false)); sign_dlg["cancel"].attachClickHandler(std::bind(&cDialog::toast, &sign_dlg, false));
sign_dlg["okay"].attachClickHandler(std::bind(edit_sign_event_filter, _1, std::ref(which_sign))); sign_dlg["okay"].attachClickHandler(std::bind(edit_sign_event_filter, _1, std::ref(which_sign)));
dynamic_cast<cPict&>(sign_dlg["pic"]).setPict(cTerrain::get_picture_num_for_terrain(picture)); // checkme: does this really need to be some terrain? if (check_picture_num(cTerrain::get_picture_num_for_terrain(picture), false)) // REMOVEME
dynamic_cast<cPict&>(sign_dlg["pic"]).setPict(cTerrain::get_picture_num_for_terrain(picture)); // checkme: does this really need to be some terrain?
else
dynamic_cast<cPict&>(sign_dlg["pic"]).setPict(cPictNum(1999,ePicType::PIC_CUSTOM_TER));
sign_dlg["num"].setTextToNum(num); sign_dlg["num"].setTextToNum(num);
sign_dlg["text"].setText(which_sign.text); sign_dlg["text"].setText(which_sign.text);