Make roads an overlay instead of a terrain trim type
Game: - Roads now show on the automap again! - Possible fix for undetected issue in displaying outdoor special spots - Road conversion code for legacy scenarios now applied in towns too Editor: - New tool for placing roads, works the same as special dots - Roads appear at all zoom levels Other: - Removed all terrain graphics that used the small road dot, replacing them with blank (white) space - Make obvious out-of-bounds array accesses an error in the project settings
This commit is contained in:
@@ -512,6 +512,7 @@ std::string uAbility::to_string(eMonstAbil key) const {
|
||||
switch(gen.fld) {
|
||||
case eFieldType::SPECIAL_EXPLORED:
|
||||
case eFieldType::SPECIAL_SPOT:
|
||||
case eFieldType::SPECIAL_ROAD:
|
||||
break; // These are invalid field types
|
||||
case eFieldType::CLOUD_SLEEP: sout << "Sleep"; break;
|
||||
case eFieldType::CLOUD_STINK: sout << "Foul"; break;
|
||||
@@ -694,6 +695,7 @@ std::string uAbility::to_string(eMonstAbil key) const {
|
||||
switch(radiate.type) {
|
||||
case eFieldType::SPECIAL_EXPLORED:
|
||||
case eFieldType::SPECIAL_SPOT:
|
||||
case eFieldType::SPECIAL_ROAD:
|
||||
break; // These are invalid field types
|
||||
case eFieldType::WALL_BLADES: sout << "blade fields"; break;
|
||||
case eFieldType::WALL_FIRE: sout << "fire fields"; break;
|
||||
|
||||
@@ -38,6 +38,9 @@ void cOutdoors::append(legacy::outdoor_record_type& old){
|
||||
if(scenario->ter_types[terrain[i][j]].i == 3000) // marker to indicate it used to be a special spot
|
||||
special_spot[i][j] = true;
|
||||
else special_spot[i][j] = false;
|
||||
if(scenario->ter_types[terrain[i][j]].i == 3001) // marker to indicate it used to be a road
|
||||
roads[i][j] = true;
|
||||
else roads[i][j] = false;
|
||||
// Convert roads that crossed grass/hill boundaries
|
||||
// It won't catch ones that sit exactly at the edge, though; in that case they'd need manual fixing
|
||||
// For simplicity we assume the non-hill space is either a city or a grass road
|
||||
@@ -45,7 +48,6 @@ void cOutdoors::append(legacy::outdoor_record_type& old){
|
||||
// 80 - grass road 81 - hill road
|
||||
// 38 - hill/grass 40 - hill|grass 42 - grass/hill 44 - grass|hill
|
||||
// where / means "over" and | means "beside"
|
||||
// Not going to do it for town since roads in town are uncommon. Maybe later.
|
||||
if(old.terrain[i][j] == 81 && i > 0 && i < 47 && j > 0 && j < 47) {
|
||||
if(old.terrain[i+1][j] == 81) {
|
||||
ter_num_t connect = old.terrain[i-1][j];
|
||||
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
std::string comment;
|
||||
std::vector<std::string> spec_strs;
|
||||
bool special_spot[48][48];
|
||||
bool roads[48][48];
|
||||
eAmbientSound ambient_sound;
|
||||
snd_num_t out_sound;
|
||||
int bg_out, bg_fight, bg_town, bg_dungeon;
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
#include "oldstructs.hpp"
|
||||
#include "fileio.hpp"
|
||||
|
||||
void cTinyTown::append(legacy::tiny_tr_type& old, int town_num){
|
||||
void cTinyTown::append(legacy::tiny_tr_type& old, int){
|
||||
int i,j;
|
||||
cField the_field;
|
||||
(void)town_num;
|
||||
cField the_field, the_road;
|
||||
the_field.type = SPECIAL_SPOT;
|
||||
the_road.type = SPECIAL_ROAD;
|
||||
// Collect a list of unused special nodes, to be used for fixing specials that could be triggered in a boat.
|
||||
std::vector<int> unused_special_slots;
|
||||
for(i = 0; i < 100; i++) {
|
||||
@@ -44,6 +44,37 @@ void cTinyTown::append(legacy::tiny_tr_type& old, int town_num){
|
||||
the_field.loc.y = j;
|
||||
preset_fields.push_back(the_field);
|
||||
}
|
||||
if(scenario->ter_types[ter[i][j]].i == 3001) { // marker to indicate it used to be a road
|
||||
the_road.loc.x = i;
|
||||
the_road.loc.y = j;
|
||||
preset_fields.push_back(the_road);
|
||||
}
|
||||
// Convert roads that crossed grass/hill boundaries
|
||||
// It won't catch ones that sit exactly at the edge, though; in that case they'd need manual fixing
|
||||
// For simplicity we assume the non-hill space is either a city or a grass road
|
||||
// Terrain types used here:
|
||||
// 80 - grass road 81 - hill road
|
||||
// 38 - hill/grass 40 - hill|grass 42 - grass/hill 44 - grass|hill
|
||||
// where / means "over" and | means "beside"
|
||||
if(old.terrain[i][j] == 81 && i > 0 && i < 47 && j > 0 && j < 47) {
|
||||
if(old.terrain[i+1][j] == 81) {
|
||||
ter_num_t connect = old.terrain[i-1][j];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 44;
|
||||
} else if(old.terrain[i-1][j] == 81) {
|
||||
ter_num_t connect = old.terrain[i+1][j];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 40;
|
||||
} else if(old.terrain[i][j+1] == 81) {
|
||||
ter_num_t connect = old.terrain[i][j-1];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 42;
|
||||
} else if(old.terrain[i][j-1] == 81) {
|
||||
ter_num_t connect = old.terrain[i][j+1];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 38;
|
||||
}
|
||||
}
|
||||
if(scenario->ter_types[ter[i][j]].boat_over) {
|
||||
// Try to fix specials that could be triggered while in a boat
|
||||
// (Boats never triggered specials in the old BoE, so we probably don't want them to trigger.)
|
||||
@@ -87,11 +118,11 @@ void cTinyTown::append(legacy::tiny_tr_type& old, int town_num){
|
||||
}
|
||||
}
|
||||
|
||||
void cMedTown::append(legacy::ave_tr_type& old, int town_num){
|
||||
void cMedTown::append(legacy::ave_tr_type& old, int){
|
||||
int i,j;
|
||||
cField the_field;
|
||||
(void)town_num; // Silencing Warnings until towns have numbers
|
||||
cField the_field, the_road;
|
||||
the_field.type = SPECIAL_SPOT;
|
||||
the_road.type = SPECIAL_ROAD;
|
||||
// Collect a list of unused special nodes, to be used for fixing specials that could be triggered in a boat.
|
||||
std::vector<int> unused_special_slots;
|
||||
for(i = 0; i < 100; i++) {
|
||||
@@ -113,6 +144,37 @@ void cMedTown::append(legacy::ave_tr_type& old, int town_num){
|
||||
the_field.loc.y = j;
|
||||
preset_fields.push_back(the_field);
|
||||
}
|
||||
if(scenario->ter_types[ter[i][j]].i == 3001) { // marker to indicate it used to be a road
|
||||
the_road.loc.x = i;
|
||||
the_road.loc.y = j;
|
||||
preset_fields.push_back(the_road);
|
||||
}
|
||||
// Convert roads that crossed grass/hill boundaries
|
||||
// It won't catch ones that sit exactly at the edge, though; in that case they'd need manual fixing
|
||||
// For simplicity we assume the non-hill space is either a city or a grass road
|
||||
// Terrain types used here:
|
||||
// 80 - grass road 81 - hill road
|
||||
// 38 - hill/grass 40 - hill|grass 42 - grass/hill 44 - grass|hill
|
||||
// where / means "over" and | means "beside"
|
||||
if(old.terrain[i][j] == 81 && i > 0 && i < 47 && j > 0 && j < 47) {
|
||||
if(old.terrain[i+1][j] == 81) {
|
||||
ter_num_t connect = old.terrain[i-1][j];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 44;
|
||||
} else if(old.terrain[i-1][j] == 81) {
|
||||
ter_num_t connect = old.terrain[i+1][j];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 40;
|
||||
} else if(old.terrain[i][j+1] == 81) {
|
||||
ter_num_t connect = old.terrain[i][j-1];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 42;
|
||||
} else if(old.terrain[i][j-1] == 81) {
|
||||
ter_num_t connect = old.terrain[i][j+1];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 38;
|
||||
}
|
||||
}
|
||||
if(scenario->ter_types[ter[i][j]].boat_over) {
|
||||
// Try to fix specials that could be triggered while in a boat
|
||||
// (Boats never triggered specials in the old BoE, so we probably don't want them to trigger.)
|
||||
@@ -156,11 +218,11 @@ void cMedTown::append(legacy::ave_tr_type& old, int town_num){
|
||||
}
|
||||
}
|
||||
|
||||
void cBigTown::append(legacy::big_tr_type& old, int town_num){
|
||||
void cBigTown::append(legacy::big_tr_type& old, int){
|
||||
int i,j;
|
||||
(void)town_num;
|
||||
cField the_field;
|
||||
cField the_field, the_road;
|
||||
the_field.type = SPECIAL_SPOT;
|
||||
the_road.type = SPECIAL_ROAD;
|
||||
// Collect a list of unused special nodes, to be used for fixing specials that could be triggered in a boat.
|
||||
std::vector<int> unused_special_slots;
|
||||
for(i = 0; i < 100; i++) {
|
||||
@@ -182,6 +244,37 @@ void cBigTown::append(legacy::big_tr_type& old, int town_num){
|
||||
the_field.loc.y = j;
|
||||
preset_fields.push_back(the_field);
|
||||
}
|
||||
if(scenario->ter_types[ter[i][j]].i == 3001) { // marker to indicate it used to be a road
|
||||
the_road.loc.x = i;
|
||||
the_road.loc.y = j;
|
||||
preset_fields.push_back(the_road);
|
||||
}
|
||||
// Convert roads that crossed grass/hill boundaries
|
||||
// It won't catch ones that sit exactly at the edge, though; in that case they'd need manual fixing
|
||||
// For simplicity we assume the non-hill space is either a city or a grass road
|
||||
// Terrain types used here:
|
||||
// 80 - grass road 81 - hill road
|
||||
// 38 - hill/grass 40 - hill|grass 42 - grass/hill 44 - grass|hill
|
||||
// where / means "over" and | means "beside"
|
||||
if(old.terrain[i][j] == 81 && i > 0 && i < 47 && j > 0 && j < 47) {
|
||||
if(old.terrain[i+1][j] == 81) {
|
||||
ter_num_t connect = old.terrain[i-1][j];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 44;
|
||||
} else if(old.terrain[i-1][j] == 81) {
|
||||
ter_num_t connect = old.terrain[i+1][j];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 40;
|
||||
} else if(old.terrain[i][j+1] == 81) {
|
||||
ter_num_t connect = old.terrain[i][j-1];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 42;
|
||||
} else if(old.terrain[i][j-1] == 81) {
|
||||
ter_num_t connect = old.terrain[i][j+1];
|
||||
if(connect == 80 || scenario->ter_types[connect].trim_type == eTrimType::CITY)
|
||||
ter[i][j] = 38;
|
||||
}
|
||||
}
|
||||
if(scenario->ter_types[ter[i][j]].boat_over) {
|
||||
// Try to fix specials that could be triggered while in a boat
|
||||
// (Boats never triggered specials in the old BoE, so we probably don't want them to trigger.)
|
||||
|
||||
@@ -301,7 +301,6 @@ enum class eTrimType {
|
||||
S, SE, E, NE, N, NW, W, SW,
|
||||
NE_INNER, SE_INNER, SW_INNER, NW_INNER,
|
||||
FRILLS = 14, // like on lava and underground water; no trim_ter required
|
||||
ROAD = 15, // the game will treat it like a road space and draw roads; no trim_ter required
|
||||
WALKWAY = 16, // the game will draw walkway corners; trim_ter is base terrain to draw on
|
||||
WATERFALL = 17, // special case for waterfalls
|
||||
CITY = 18, // the game will join roads up to this space but not draw roads on the space
|
||||
@@ -872,6 +871,7 @@ enum eFieldType {
|
||||
SFX_BONES = 22,
|
||||
SFX_RUBBLE = 23,
|
||||
BARRIER_CAGE = 24,
|
||||
SPECIAL_ROAD = 25,
|
||||
// From here on are special values that don't index anything.
|
||||
// Thus, they start at 32.
|
||||
FIELD_DISPEL = 32, // Dispel field
|
||||
|
||||
@@ -85,7 +85,7 @@ void cTerrain::append(legacy::terrain_type_type& old){
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 18,18,18, 18,18,18,18,18,18,18,18,0, 0,
|
||||
18,18,15,15,15,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,16,0, 16,16,
|
||||
18,18,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,16,0, 16,16,
|
||||
16,16,16,16,16,16,0, 0, 0, 0, 0, 0, 18,0, 0, 0, 18,18,18,18,
|
||||
18,18,18,18,18,18,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
14,14,14,14,14,17,18,0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -332,6 +332,19 @@ void cTerrain::append(legacy::terrain_type_type& old){
|
||||
obj_size.x = 2;
|
||||
obj_size.y = 2;
|
||||
break;
|
||||
// Roads
|
||||
case 202:
|
||||
picture = 0;
|
||||
i = 3001;
|
||||
break;
|
||||
case 203:
|
||||
picture = 2;
|
||||
i = 3001;
|
||||
break;
|
||||
case 204:
|
||||
picture = 32;
|
||||
i = 3001;
|
||||
break;
|
||||
// Special spaces
|
||||
case 207:
|
||||
picture = 0;
|
||||
|
||||
@@ -104,11 +104,14 @@ void cCurTown::place_preset_fields() {
|
||||
for(size_t i = 0; i < record()->preset_fields.size(); i++) {
|
||||
switch(record()->preset_fields[i].type){
|
||||
case OBJECT_BLOCK:
|
||||
univ.town.set_block(record()->preset_fields[i].loc.x,record()->preset_fields[i].loc.y,true);
|
||||
set_block(record()->preset_fields[i].loc.x,record()->preset_fields[i].loc.y,true);
|
||||
break;
|
||||
case SPECIAL_SPOT:
|
||||
set_spot(record()->preset_fields[i].loc.x,record()->preset_fields[i].loc.y,true);
|
||||
break;
|
||||
case SPECIAL_ROAD:
|
||||
set_road(record()->preset_fields[i].loc.x,record()->preset_fields[i].loc.y,true);
|
||||
break;
|
||||
case FIELD_WEB:
|
||||
set_web(record()->preset_fields[i].loc.x,record()->preset_fields[i].loc.y,true);
|
||||
break;
|
||||
@@ -236,6 +239,10 @@ bool cCurTown::is_spot(short x, short y) const{
|
||||
return fields[x][y] & SPECIAL_SPOT;
|
||||
}
|
||||
|
||||
bool cCurTown::is_road(short x, short y) const{
|
||||
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;
|
||||
location check(x,y);
|
||||
@@ -463,6 +470,13 @@ bool cCurTown::set_spot(short x, short y, bool b){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cCurTown::set_road(short x, short y, bool b){
|
||||
if(x > record()->max_dim() || y > record()->max_dim()) 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(b){ // If certain things are on the space, there's no room for webs
|
||||
@@ -864,6 +878,24 @@ cOutdoors* cCurOut::operator->() {
|
||||
return univ.scenario.outdoors[x][y];
|
||||
}
|
||||
|
||||
bool cCurOut::is_spot(int x, int y) {
|
||||
int sector_x = 0, sector_y = 0;
|
||||
if(x >= 48) sector_x++, x -= 48;
|
||||
if(y >= 48) sector_y++, y -= 48;
|
||||
sector_x += univ.party.outdoor_corner.x;
|
||||
sector_y += univ.party.outdoor_corner.y;
|
||||
return univ.scenario.outdoors[sector_x][sector_y]->special_spot[x][y];
|
||||
}
|
||||
|
||||
bool cCurOut::is_road(int x, int y) {
|
||||
int sector_x = 0, sector_y = 0;
|
||||
if(x >= 48) sector_x++, x -= 48;
|
||||
if(y >= 48) sector_y++, y -= 48;
|
||||
sector_x += univ.party.outdoor_corner.x;
|
||||
sector_y += univ.party.outdoor_corner.y;
|
||||
return univ.scenario.outdoors[sector_x][sector_y]->roads[x][y];
|
||||
}
|
||||
|
||||
cUniverse::cUniverse(long party_type) : party(*this, party_type), out(*this), town(*this) {}
|
||||
|
||||
void cUniverse::check_monst(cMonster& monst) {
|
||||
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
bool is_bones(short x, short y) const;
|
||||
bool is_rubble(short x, short y) const;
|
||||
bool is_force_cage(short x, short y) const;
|
||||
// bool is_trim(short x, short y, char t) const;
|
||||
bool is_road(short x, short y) const;
|
||||
bool set_explored(short x, short y, bool b);
|
||||
bool set_force_wall(short x, short y, bool b);
|
||||
bool set_fire_wall(short x, short y, bool b);
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
bool set_bones(short x, short y, bool b);
|
||||
bool set_rubble(short x, short y, bool b);
|
||||
bool set_force_cage(short x, short y, bool b);
|
||||
// bool set_trim(short x, short y, char t, bool b);
|
||||
bool set_road(short x, short y, bool b);
|
||||
bool is_impassable(short x, short y);
|
||||
void writeTo(std::ostream& file) const;
|
||||
void readFrom(std::istream& file);
|
||||
@@ -133,6 +133,10 @@ public:
|
||||
ter_num_t out[96][96];
|
||||
unsigned char out_e[96][96];
|
||||
|
||||
// These take global coords (ie 0..95)
|
||||
bool is_spot(int x, int y);
|
||||
bool is_road(int x, int y);
|
||||
|
||||
void append(legacy::out_info_type& old);
|
||||
|
||||
typedef ter_num_t arr_96[96];
|
||||
|
||||
Reference in New Issue
Block a user