Enumify terrain blockage and generalize the line of sight function

This should probably be two separate commits, but they're tangled together and I don't want to spend the effort to disentangle them.
This commit is contained in:
2014-12-01 19:50:19 -05:00
parent afd45b3774
commit d900c7edef
19 changed files with 150 additions and 300 deletions

View File

@@ -976,7 +976,7 @@ bool handle_action(sf::Event event)
}else if(overall_mode == MODE_DROP_TOWN) { }else if(overall_mode == MODE_DROP_TOWN) {
if (adjacent(univ.town.p_loc,destination) == false) if (adjacent(univ.town.p_loc,destination) == false)
add_string_to_buf("Drop: must be adjacent."); add_string_to_buf("Drop: must be adjacent.");
else if (get_obscurity(destination.x,destination.y) == 5) else if(sight_obscurity(destination.x,destination.y) == 5)
ASB("Drop: Space is blocked."); ASB("Drop: Space is blocked.");
else drop_item(current_pc,store_drop_item,destination); else drop_item(current_pc,store_drop_item,destination);
} }
@@ -2206,7 +2206,7 @@ void increase_age()////
if (PSD[SDF_PARTY_FLIGHT] == 2) if (PSD[SDF_PARTY_FLIGHT] == 2)
add_string_to_buf("You are starting to descend."); add_string_to_buf("You are starting to descend.");
if (PSD[SDF_PARTY_FLIGHT] == 1) { if (PSD[SDF_PARTY_FLIGHT] == 1) {
if (scenario.ter_types[univ.out[univ.party.p_loc.x][univ.party.p_loc.y]].blockage > 2) { if(blocksMove(scenario.ter_types[univ.out[univ.party.p_loc.x][univ.party.p_loc.y]].blockage)) {
add_string_to_buf(" You plummet to your deaths. "); add_string_to_buf(" You plummet to your deaths. ");
slay_party(MAIN_STATUS_DEAD); slay_party(MAIN_STATUS_DEAD);
print_buf(); print_buf();

View File

@@ -868,7 +868,7 @@ void place_target(location target)
add_string_to_buf(" Target out of range."); add_string_to_buf(" Target out of range.");
return; return;
} }
if ((get_obscurity(target.x,target.y) == 5) && (spell_being_cast != 41)) { if(sight_obscurity(target.x,target.y) == 5 && spell_being_cast != 41) {
add_string_to_buf(" Target space obstructed. "); add_string_to_buf(" Target space obstructed. ");
return; return;
} }
@@ -988,7 +988,7 @@ void do_combat_cast(location target)////
} }
else if (dist(pc_pos[current_pc],target) > ((spell_being_cast >= 100) ? priest_range[spell_being_cast - 100] : mage_range[spell_being_cast])) else if (dist(pc_pos[current_pc],target) > ((spell_being_cast >= 100) ? priest_range[spell_being_cast - 100] : mage_range[spell_being_cast]))
add_string_to_buf(" Target out of range."); add_string_to_buf(" Target out of range.");
else if ((get_obscurity(target.x,target.y) == 5) && (spell_being_cast != 41)) else if(sight_obscurity(target.x,target.y) == 5 && spell_being_cast != 41)
add_string_to_buf(" Target space obstructed. "); add_string_to_buf(" Target space obstructed. ");
else if (univ.town.is_antimagic(target.x,target.y)) else if (univ.town.is_antimagic(target.x,target.y))
add_string_to_buf(" Target in antimagic field."); add_string_to_buf(" Target in antimagic field.");
@@ -3515,7 +3515,7 @@ location find_fireball_loc(location where,short radius,short mode,short *m)
for (check_loc.x = 1; check_loc.x < univ.town->max_dim() - 1; check_loc.x ++) for (check_loc.x = 1; check_loc.x < univ.town->max_dim() - 1; check_loc.x ++)
for (check_loc.y = 1; check_loc.y < univ.town->max_dim() - 1; check_loc.y ++) for (check_loc.y = 1; check_loc.y < univ.town->max_dim() - 1; check_loc.y ++)
if ((dist(where,check_loc) <= 8) && (can_see(where,check_loc,2) < 5) && (get_obscurity(check_loc.x,check_loc.y) < 5)) { if(dist(where,check_loc) <= 8 && can_see(where,check_loc,sight_obscurity) < 5 && sight_obscurity(check_loc.x,check_loc.y) < 5) {
{ {
cur_lev = count_levels(check_loc,radius); cur_lev = count_levels(check_loc,radius);
if (mode == 1) if (mode == 1)
@@ -3560,7 +3560,7 @@ short count_levels(location where,short radius)
store = store + 10; store = store + 10;
} }
if (is_town()) if (is_town())
if ((vdist(where,univ.town.p_loc) <= radius) && (can_see(where,univ.town.p_loc,2) < 5)) if(vdist(where,univ.town.p_loc) <= radius && can_see(where,univ.town.p_loc,sight_obscurity) < 5)
store += 20; store += 20;
return store; return store;
@@ -3641,7 +3641,7 @@ void place_spell_pattern(effect_pat_type pat,location center,short type,bool pre
// First actually make barriers, then draw them, then inflict damaging effects. // First actually make barriers, then draw them, then inflict damaging effects.
for (i = minmax(0,univ.town->max_dim() - 1,center.x - 4); i <= minmax(0,univ.town->max_dim() - 1,center.x + 4); i++) for (i = minmax(0,univ.town->max_dim() - 1,center.x - 4); i <= minmax(0,univ.town->max_dim() - 1,center.x + 4); i++)
for (j = minmax(0,univ.town->max_dim() - 1,center.y - 4); j <= minmax(0,univ.town->max_dim() - 1,center.y + 4); j++) for (j = minmax(0,univ.town->max_dim() - 1,center.y - 4); j <= minmax(0,univ.town->max_dim() - 1,center.y + 4); j++)
if (get_obscurity(i,j) < 5) { if(sight_obscurity(i,j) < 5) {
effect = pat.pattern[i - center.x + 4][j - center.y + 4]; effect = pat.pattern[i - center.x + 4][j - center.y + 4];
switch (effect) { switch (effect) {
case 1: web_space(i,j); break; case 1: web_space(i,j); break;
@@ -3673,7 +3673,7 @@ void place_spell_pattern(effect_pat_type pat,location center,short type,bool pre
for (j = minmax(0,univ.town->max_dim() - 1,center.y - 4); j <= minmax(0,univ.town->max_dim() - 1,center.y + 4); j++) { for (j = minmax(0,univ.town->max_dim() - 1,center.y - 4); j <= minmax(0,univ.town->max_dim() - 1,center.y + 4); j++) {
spot_hit.x = i; spot_hit.x = i;
spot_hit.y = j; spot_hit.y = j;
if ((get_obscurity(i,j) < 5) && (univ.party[k].main_status == 1) if(sight_obscurity(i,j) < 5 && univ.party[k].main_status == 1
&& (((is_combat()) && (pc_pos[k] == spot_hit)) || && (((is_combat()) && (pc_pos[k] == spot_hit)) ||
((is_town()) && (univ.town.p_loc == spot_hit)))) { ((is_town()) && (univ.town.p_loc == spot_hit)))) {
effect = pat.pattern[i - center.x + 4][j - center.y + 4]; effect = pat.pattern[i - center.x + 4][j - center.y + 4];
@@ -3724,7 +3724,7 @@ void place_spell_pattern(effect_pat_type pat,location center,short type,bool pre
spot_hit.x = i; spot_hit.x = i;
spot_hit.y = j; spot_hit.y = j;
if ((monster_hit == false) && (get_obscurity(i,j) < 5) && (monst_on_space(spot_hit,k) > 0)) { if(!monster_hit && sight_obscurity(i,j) < 5 && monst_on_space(spot_hit,k) > 0) {
if (pat.pattern[i - center.x + 4][j - center.y + 4] > 0) if (pat.pattern[i - center.x + 4][j - center.y + 4] > 0)
monster_hit = true; monster_hit = true;

View File

@@ -192,9 +192,10 @@ void make_quickfire(short i,short j)
// if ((is_force_barrier(i,j)) || (is_fire_barrier(i,j))) // if ((is_force_barrier(i,j)) || (is_fire_barrier(i,j)))
// return; // return;
ter = coord_to_ter(i,j); ter = coord_to_ter(i,j);
if (scenario.ter_types[ter].blockage == 1) if(scenario.ter_types[ter].blockage == eTerObstruct::BLOCK_SIGHT)
return; return;
if (scenario.ter_types[ter].blockage == 5) // TODO: Isn't it a little odd that BLOCK_MOVE_AND_SHOOT isn't included here?
if(scenario.ter_types[ter].blockage == eTerObstruct::BLOCK_MOVE_AND_SIGHT)
return; return;
// univ.town.explored[i][j] = univ.town.explored[i][j] & 1; // univ.town.explored[i][j] = univ.town.explored[i][j] & 1;
// univ.out.misc_i[i][j] = univ.out.misc_i[i][j] & 3; // univ.out.misc_i[i][j] = univ.out.misc_i[i][j] & 3;
@@ -388,10 +389,10 @@ void make_sfx(short i,short j, short type)
{ {
ter_num_t ter; ter_num_t ter;
if (get_obscurity(i,j) > 0) if(sight_obscurity(i,j) > 0)
return; return;
ter = coord_to_ter(i,j); ter = coord_to_ter(i,j);
if (scenario.ter_types[ter].blockage != 0) if(scenario.ter_types[ter].blockage != eTerObstruct::CLEAR)
return; return;
switch (type) { switch (type) {
// case 1: case 2: // case 1: case 2:

View File

@@ -1050,7 +1050,7 @@ void draw_terrain(short mode)
static ter_num_t get_ground_for_shore(ter_num_t ter){ static ter_num_t get_ground_for_shore(ter_num_t ter){
if(scenario.ter_types[ter].block_horse) return current_ground; if(scenario.ter_types[ter].block_horse) return current_ground;
else if(scenario.ter_types[ter].blockage > 2) return current_ground; else if(blocksMove(scenario.ter_types[ter].blockage)) return current_ground;
else return ter; else return ter;
} }

View File

@@ -153,116 +153,19 @@ bool is_lava(short x,short y)////
else return false; else return false;
} }
short can_see(location p1,location p2,short mode) short can_see_light(location p1, location p2, std::function<short(short,short)> get_obscurity) {
//short mode; // 0 - normal 1 - counts 1 for blocked spaces or lava (used for party placement in if(is_combat() && !combat_pt_in_light(p2)) return 6;
// town combat) else if(is_town() && !pt_in_light(p1,p2)) return 6;
// 2 - no light check return can_see(p1, p2, get_obscurity);
{
short dx,dy,count,storage = 0;
if (is_combat()) { // Light check
if ((mode != 2) && (combat_pt_in_light(p2) == false)) {
return 6;
}
}
else if(is_town()) {
if ((mode != 2) && (pt_in_light(p1,p2) == false)) {
return 6;
}
}
if (p1.y == p2.y) {
if (p1.x > p2.x) {
for (count = p2.x + 1; count < p1.x; count++) {
storage = storage + get_obscurity(count, p1.y);
if (((scenario.ter_types[coord_to_ter(count,p1.y)].blockage > 2) || (is_lava(count,p1.y) == true)) && (mode == 1))
return 5;
}
}
else {
for (count = p1.x + 1; count < p2.x; count++) {
storage = storage + get_obscurity(count, p1.y);
if (((scenario.ter_types[coord_to_ter(count,p1.y)].blockage > 2) || (is_lava(count,p1.y) == true)) && (mode == 1))
return 5;
}
}
return storage;
}
if (p1.x == p2.x) {
if (p1.y > p2.y) {
for (count = p1.y - 1; count > p2.y; count--) {
storage = storage + get_obscurity(p1.x, count);
if (((scenario.ter_types[coord_to_ter(p1.x,count)].blockage > 2) || (is_lava(p1.x,count) == true)) && (mode == 1))
return 5;
}
}
else {
for (count = p1.y + 1; count < p2.y; count++) {
storage = storage + get_obscurity(p1.x, count);
if (((scenario.ter_types[coord_to_ter(p1.x,count)].blockage > 2) || (is_lava(p1.x,count) == true)) && (mode == 1))
return 5;
}
}
return storage;
}
dx = p2.x - p1.x;
dy = p2.y - p1.y;
if (abs(dy) > abs(dx)) {
if (p2.y > p1.y) {
for (count = 1; count < dy; count++) {
storage = storage + get_obscurity(p1.x + (count * dx) / dy, p1.y + count);
if ( ((scenario.ter_types[coord_to_ter(p1.x + (count * dx) / dy,p1.y + count)].blockage > 2) ||
(is_lava(p1.x + (count * dx) / dy,p1.y + count) == true))
&& (mode == 1))
return 5;
}
}
else {
for (count = -1; count > dy; count--) {
storage = storage + get_obscurity(p1.x + (count * dx) / dy, p1.y + count);
if ( ((scenario.ter_types[coord_to_ter(p1.x + (count * dx) / dy, p1.y + count)].blockage > 2) ||
(is_lava(p1.x + (count * dx) / dy, p1.y + count) == true))
&& (mode == 1))
return 5;
}
}
return storage;
}
if (abs(dy) <= abs(dx)) {
if (p2.x > p1.x) {
for (count = 1; count < dx; count++) {
storage = storage + get_obscurity(p1.x + count, p1.y + (count * dy) / dx);
if (((scenario.ter_types[coord_to_ter(p1.x + count,p1.y + (count * dy) / dx)].blockage > 2) ||
(is_lava(p1.x + count,p1.y + (count * dy) / dx) == true))
&& (mode == 1))
return 5;
}
}
else {
for (count = -1; count > dx; count--) {
storage = storage + get_obscurity(p1.x + count, p1.y + (count * dy) / dx);
if ( ((scenario.ter_types[coord_to_ter(p1.x + count,p1.y + (count * dy) / dx)].blockage > 2) ||
(is_lava(p1.x + count,p1.y + (count * dy) / dx) == true))
&& (mode == 1))
return 5;
}
}
return storage;
}
if (storage > 5)
return 5;
else return storage;
} }
short get_obscurity(short x,short y) short sight_obscurity(short x,short y) {
{
ter_num_t what_terrain; ter_num_t what_terrain;
short store; short store;
what_terrain = coord_to_ter(x,y); what_terrain = coord_to_ter(x,y);
// TODO: This should not be hard-coded!
if ((what_terrain >= 237) && (what_terrain <= 242)) if ((what_terrain >= 237) && (what_terrain <= 242))
return 1; return 1;
@@ -285,6 +188,12 @@ short get_obscurity(short x,short y)
return store; return store;
} }
short combat_obscurity(short x, short y) {
if(blocksMove(scenario.ter_types[coord_to_ter(x,y)].blockage)) return 5;
if(is_lava(x,y)) return 5;
return sight_obscurity(x,y);
}
ter_num_t coord_to_ter(short x,short y) ter_num_t coord_to_ter(short x,short y)
{ {
ter_num_t what_terrain; ter_num_t what_terrain;
@@ -329,7 +238,7 @@ void update_explored(location dest)
for (look.y = shortdest.y - 4; look.y < shortdest.y + 5; look.y++) { for (look.y = shortdest.y - 4; look.y < shortdest.y + 5; look.y++) {
if (univ.out.out_e[look.x][look.y] == 0) if (univ.out.out_e[look.x][look.y] == 0)
if (can_see(shortdest, look) < 5) if(can_see_light(shortdest, look, sight_obscurity) < 5)
univ.out.out_e[look.x][look.y] = 1; univ.out.out_e[look.x][look.y] = 1;
} }
@@ -526,7 +435,7 @@ bool outd_is_blocked(location to_check)
bool special_which_blocks_monst(location to_check) bool special_which_blocks_monst(location to_check)
{ {
if (scenario.ter_types[coord_to_ter(to_check.x,to_check.y)].blockage == 2) if(scenario.ter_types[coord_to_ter(to_check.x,to_check.y)].blockage == eTerObstruct::BLOCK_MONSTERS)
return true; return true;
else return false; else return false;
} }
@@ -539,7 +448,7 @@ bool is_special(location to_check)
if (special_which_blocks_monst(to_check) == false) if (special_which_blocks_monst(to_check) == false)
return false; return false;
which_ter = coord_to_ter(to_check.x,to_check.y); which_ter = coord_to_ter(to_check.x,to_check.y);
if (scenario.ter_types[which_ter].blockage == 2) if(scenario.ter_types[which_ter].blockage == eTerObstruct::BLOCK_MONSTERS)
return true; return true;
else return false; else return false;
} }
@@ -547,7 +456,7 @@ bool is_special(location to_check)
bool outd_is_special(location to_check) bool outd_is_special(location to_check)
{ {
if (overall_mode == MODE_OUTDOORS) { if (overall_mode == MODE_OUTDOORS) {
if (scenario.ter_types[univ.out[to_check.x][to_check.y]].blockage == 2) { if(scenario.ter_types[univ.out[to_check.x][to_check.y]].blockage == eTerObstruct::BLOCK_MONSTERS) {
return true; return true;
} }
else return false; else return false;
@@ -557,20 +466,23 @@ bool outd_is_special(location to_check)
bool impassable(ter_num_t terrain_to_check) bool impassable(ter_num_t terrain_to_check)
{ {
if (scenario.ter_types[terrain_to_check].blockage > 2) if(blocksMove(scenario.ter_types[terrain_to_check].blockage))
return true; return true;
else return false; else return false;
} }
// TODO: What on earth is this and why does it mangle the blockage? // TODO: What on earth is this and why does it mangle the blockage?
// NOTE: Seems to return 5 for "blocks sight", 1 for "obstructs missiles", 0 otherwise
// So it should probably be called something like "get_opacity" instead.
short get_blockage(ter_num_t terrain_type) short get_blockage(ter_num_t terrain_type)
{ {
// little kludgy in here for pits // little kludgy in here for pits
if ((terrain_type == 90) && (is_combat()) && (which_combat_type == 0)) if ((terrain_type == 90) && (is_combat()) && (which_combat_type == 0))
return 5; return 5;
if ((scenario.ter_types[terrain_type].blockage == 5) || (scenario.ter_types[terrain_type].blockage == 1)) if(scenario.ter_types[terrain_type].blockage == eTerObstruct::BLOCK_MOVE_AND_SIGHT ||
scenario.ter_types[terrain_type].blockage == eTerObstruct::BLOCK_SIGHT)
return 5; return 5;
else if (scenario.ter_types[terrain_type].blockage > 3) else if(scenario.ter_types[terrain_type].blockage == eTerObstruct::BLOCK_MOVE_AND_SHOOT)
return 1; return 1;
else { else {
return 0; return 0;
@@ -693,8 +605,8 @@ location push_loc(location from_where,location to_where)
loc_to_try.x = 0; loc_to_try.x = 0;
return loc_to_try; return loc_to_try;
} }
if ((get_obscurity((short) loc_to_try.x,(short) loc_to_try.y) > 0) || if(sight_obscurity(loc_to_try.x,loc_to_try.y) > 0 ||
(scenario.ter_types[univ.town->terrain(loc_to_try.x,loc_to_try.y)].blockage > 0) || scenario.ter_types[univ.town->terrain(loc_to_try.x,loc_to_try.y)].blockage != eTerObstruct::CLEAR ||
(loc_off_act_area(loc_to_try) == true) || (loc_off_act_area(loc_to_try) == true) ||
(monst_there(loc_to_try) < 90) || (monst_there(loc_to_try) < 90) ||
(pc_there(loc_to_try) < 6)) (pc_there(loc_to_try) < 6))
@@ -703,13 +615,13 @@ location push_loc(location from_where,location to_where)
} }
// TODO: This seems to be wrong; aren't 3 and 4 also impassable? // TODO: This seems to be wrong; impassable implies "blocks movement", which two other blockages also do
bool spot_impassable(short i,short j) bool spot_impassable(short i,short j)
{ {
ter_num_t ter; ter_num_t ter;
ter = coord_to_ter(i,j); ter = coord_to_ter(i,j);
if (scenario.ter_types[ter].blockage == 5) if(scenario.ter_types[ter].blockage == eTerObstruct::BLOCK_MOVE_AND_SIGHT)
return true; return true;
else return false; else return false;
} }

View File

@@ -11,9 +11,9 @@ bool loc_off_world(location p1);
bool loc_off_act_area(location p1); bool loc_off_act_area(location p1);
location get_cur_loc(); location get_cur_loc();
bool is_lava(short x,short y); bool is_lava(short x,short y);
// TODO: Introduce enum for this mode short sight_obscurity(short x,short y);
short can_see(location p1,location p2,short mode = 0); short can_see_light(location p1, location p2, std::function<short(short,short)> get_obscurity);
short get_obscurity(short x,short y); short combat_obscurity(short x,short y);
ter_num_t coord_to_ter(short x,short y); ter_num_t coord_to_ter(short x,short y);
bool is_container(location loc); bool is_container(location loc);
void update_explored(location dest); void update_explored(location dest);

View File

@@ -781,7 +781,7 @@ location find_clear_spot(location from_where,short mode)
r1 = get_ran(1,-2,2); r1 = get_ran(1,-2,2);
loc.y = loc.y + r1; loc.y = loc.y + r1;
if ((loc_off_act_area(loc) == false) && (is_blocked(loc) == false) if ((loc_off_act_area(loc) == false) && (is_blocked(loc) == false)
&& (can_see(from_where,loc,1) == 0) && can_see_light(from_where,loc,combat_obscurity) == 0
&& (!(is_combat()) || (pc_there(loc) == 6)) && (!(is_combat()) || (pc_there(loc) == 6))
&& (!(is_town()) || (loc != univ.town.p_loc)) && (!(is_town()) || (loc != univ.town.p_loc))
&& (!(univ.town.misc_i(loc.x,loc.y) & 248)) && // check for crate, barrel, barrier, quickfire && (!(univ.town.misc_i(loc.x,loc.y) & 248)) && // check for crate, barrel, barrier, quickfire

View File

@@ -1722,7 +1722,7 @@ void cast_town_spell(location where) ////
update_explored(univ.town.p_loc); update_explored(univ.town.p_loc);
break; break;
case 42: case 42:
if ((get_obscurity(where.x,where.y) == 5) || (monst_there(where) < 90)) { if(sight_obscurity(where.x,where.y) == 5 || monst_there(where) < 90) {
add_string_to_buf(" Target space obstructed."); add_string_to_buf(" Target space obstructed.");
break; break;
} }
@@ -1732,7 +1732,7 @@ void cast_town_spell(location where) ////
else add_string_to_buf(" Failed."); else add_string_to_buf(" Failed.");
break; break;
case 59: case 59:
if ((get_obscurity(where.x,where.y) == 5) || (monst_there(where) < 90)) { if(sight_obscurity(where.x,where.y) == 5 || monst_there(where) < 90) {
add_string_to_buf(" Target space obstructed."); add_string_to_buf(" Target space obstructed.");
break; break;
} }
@@ -1752,7 +1752,7 @@ void cast_town_spell(location where) ////
add_string_to_buf(" You create an antimagic cloud. "); add_string_to_buf(" You create an antimagic cloud. ");
for (loc.x = 0; loc.x < univ.town->max_dim(); loc.x++) for (loc.x = 0; loc.x < univ.town->max_dim(); loc.x++)
for (loc.y = 0; loc.y < univ.town->max_dim(); loc.y++) for (loc.y = 0; loc.y < univ.town->max_dim(); loc.y++)
if ((dist(where,loc) <= 2) && (can_see(where,loc,2) < 5) && if(dist(where,loc) <= 2 && can_see(where,loc,sight_obscurity) < 5 &&
((abs(loc.x - where.x) < 2) || (abs(loc.y - where.y) < 2))) ((abs(loc.x - where.x) < 2) || (abs(loc.y - where.y) < 2)))
make_antimagic(loc.x,loc.y); make_antimagic(loc.x,loc.y);
break; break;

View File

@@ -294,7 +294,7 @@ bool check_special_terrain(location where_check,short mode,short which_pc,short
play_sound(-1 * ter_flag2.u); play_sound(-1 * ter_flag2.u);
} }
give_help(47,65); give_help(47,65);
if (scenario.ter_types[ter].blockage > 2) if(blocksMove(scenario.ter_types[ter].blockage))
can_enter = false; can_enter = false;
break; break;
case TER_SPEC_DAMAGING: case TER_SPEC_DAMAGING:

View File

@@ -839,8 +839,8 @@ void place_party(short direction)
check_loc.y -= y_adj; check_loc.y -= y_adj;
pos_locs[i] = check_loc; pos_locs[i] = check_loc;
if ((is_blocked(check_loc) == false) && (is_special(check_loc) == false) && (get_obscurity(check_loc.x,check_loc.y) == 0) if(!is_blocked(check_loc) && !is_special(check_loc) && sight_obscurity(check_loc.x,check_loc.y) == 0
&& (can_see(univ.town.p_loc,check_loc,1) < 1) && (loc_off_act_area(check_loc) == false)) { && can_see_light(univ.town.p_loc,check_loc,combat_obscurity) < 1 && !loc_off_act_area(check_loc)) {
spot_ok[i] = true; spot_ok[i] = true;
how_many_ok += (i > 1) ? 1 : 0; how_many_ok += (i > 1) ? 1 : 0;
} }

View File

@@ -240,6 +240,20 @@ enum eTrimType {
TRIM_CITY = 18, // the game will join roads up to this space but not draw roads on the space TRIM_CITY = 18, // the game will join roads up to this space but not draw roads on the space
}; };
/* terrain type blockage */
enum class eTerObstruct {
CLEAR = 0,
BLOCK_SIGHT = 1,
BLOCK_MONSTERS = 2,
BLOCK_MOVE = 3,
BLOCK_MOVE_AND_SHOOT = 4,
BLOCK_MOVE_AND_SIGHT = 5,
};
inline bool blocksMove(eTerObstruct block) {
int code = (int) block;
return code > 2;
}
/* items[i].type a.k.a type of weapon */ /* items[i].type a.k.a type of weapon */
enum class eWeapType { enum class eWeapType {

View File

@@ -95,7 +95,7 @@ cTerrain& cTerrain::operator = (legacy::terrain_type_type& old){
99,99,99,99,99,2, 99,99,99,99, 99,99,99,99, 99,99,99,99,99,2, 99,99,99,99, 99,99,99,99,
}; };
picture = old.picture; picture = old.picture;
blockage = old.blockage; blockage = (eTerObstruct) old.blockage;
if(picture < 260){ if(picture < 260){
combat_arena = arenas[picture]; combat_arena = arenas[picture];
ground_type = ground[picture]; ground_type = ground[picture];
@@ -365,3 +365,16 @@ std::istream& operator >> (std::istream& in, eTerSpec& e){
else e = TER_SPEC_NONE; else e = TER_SPEC_NONE;
return in; return in;
} }
std::ostream& operator << (std::ostream& out, eTerObstruct& e){
return out << (int) e;
}
std::istream& operator >> (std::istream& in, eTerObstruct& e){
int i;
in >> i;
if(i > 0 && i < 6)
e = (eTerObstruct) i;
else e = eTerObstruct::CLEAR;
return in;
}

View File

@@ -24,7 +24,7 @@ class cTerrain {
public: public:
std::string name; std::string name;
pic_num_t picture; pic_num_t picture;
unsigned char blockage; eTerObstruct blockage;
ter_flag_t flag1; ter_flag_t flag1;
ter_flag_t flag2; ter_flag_t flag2;
ter_flag_t flag3; // new additional flag for special properties ter_flag_t flag3; // new additional flag for special properties
@@ -52,5 +52,7 @@ public:
std::ostream& operator << (std::ostream& out, eTerSpec& e); std::ostream& operator << (std::ostream& out, eTerSpec& e);
std::istream& operator >> (std::istream& in, eTerSpec& e); std::istream& operator >> (std::istream& in, eTerSpec& e);
std::ostream& operator << (std::ostream& out, eTerObstruct& e);
std::istream& operator >> (std::istream& in, eTerObstruct& e);
#endif #endif

View File

@@ -117,7 +117,6 @@ short special_to_paste = -1;
extern std::string get_str(std::string list, short j); extern std::string get_str(std::string list, short j);
bool monst_on_space(location loc,short m_num); bool monst_on_space(location loc,short m_num);
short can_see(location p1,location p2,short mode);
void init_current_terrain() { void init_current_terrain() {
// short i,j; // short i,j;
@@ -1467,52 +1466,6 @@ void handle_keystroke(char chr,char chr2,sf::Event event) {
//void set_info_strings() { //void set_info_strings() {
//} //}
void modify_lists() {
/* unsigned char terrain_to_do;
char i,j, k;
short sign_count = 0, exit_count = 0, special_count = 0;
unsigned char specials[10] = {237,238,239,240,241, 242,243,244,78,78};
unsigned char signs[6] = {110,127,142,213,214,252};
bool is_this_type = false;
location null_point = {0,0};
for (i = 0; i < town->max_dim(); i++)
for (j = 0; j < town->max_dim(); j++) {
is_this_type = false;
terrain_to_do = (unsigned char) town->terrain(i,j);
for (k = 0; k < 10; k++)
if (terrain_to_do == specials[k])
is_this_type = true;
if ((is_this_type == true) && (special_count < 40)) {
make_special(i,j);
special_count++;
is_this_type = true;
}
if (is_this_type == false) {
for (k = 0; k < 6; k++)
if (terrain_to_do == signs[k])
is_this_type = true;
if ((is_this_type == true) && (sign_count < 12)) {
town.sign_locs[sign_count].x = i;
town.sign_locs[sign_count].y = j;
sign_count++;
}
}
}
for (i = sign_count; i < 12; i++)
town.sign_locs[i] = null_point;
*/
set_up_lights();
}
void set_up_lights() { void set_up_lights() {
short i,j,rad; short i,j,rad;
location where,l; location where,l;
@@ -3463,7 +3416,7 @@ bool save_check(std::string which_dlog) {
return true; return true;
else if(choice == "cancel") else if(choice == "cancel")
return false; return false;
modify_lists(); set_up_lights();
save_scenario(); save_scenario();
return true; return true;
} }
@@ -3474,16 +3427,16 @@ bool is_lava(short x,short y) {
else return false; else return false;
} }
short get_obscurity(short x,short y) { short light_obscurity(short x,short y) {
ter_num_t what_terrain; ter_num_t what_terrain;
short store; eTerObstruct store;
what_terrain = coord_to_ter(x,y); what_terrain = coord_to_ter(x,y);
store = scenario.ter_types[what_terrain].blockage; store = scenario.ter_types[what_terrain].blockage;
if ((store == 1) || (store == 5)) if(store == eTerObstruct::BLOCK_SIGHT || store == eTerObstruct::BLOCK_MOVE_AND_SIGHT)
return 5; return 5;
if (store == 4) if(store == eTerObstruct::BLOCK_MOVE_AND_SHOOT)
return 1; return 1;
return 0; return 0;
} }
@@ -3498,98 +3451,6 @@ ter_num_t coord_to_ter(short x,short y) {
return what_terrain; return what_terrain;
} }
short can_see(location p1,location p2,short mode) {
//mode; // 0 - normal 1 - counts 1 for blocked spaces or lava (used for party placement in
// town combat)
// 2 - no light check
short dx,dy,count,storage = 0;
if (p1.y == p2.y) {
if (p1.x > p2.x) {
for (count = p2.x + 1; count < p1.x; count++) {
storage = storage + get_obscurity(count, p1.y);
if (((scenario.ter_types[coord_to_ter(count,p1.y)].blockage > 2) || (is_lava(count,p1.y) == true)) && (mode == 1))
return 5;
}
}
else {
for (count = p1.x + 1; count < p2.x; count++) {
storage = storage + get_obscurity(count, p1.y);
if (((scenario.ter_types[coord_to_ter(count,p1.y)].blockage > 2) || (is_lava(count,p1.y) == true)) && (mode == 1))
return 5;
}
}
return storage;
}
if (p1.x == p2.x) {
if (p1.y > p2.y) {
for (count = p1.y - 1; count > p2.y; count--) {
storage = storage + get_obscurity(p1.x, count);
if (((scenario.ter_types[coord_to_ter(p1.x,count)].blockage > 2) || (is_lava(p1.x,count) == true)) && (mode == 1))
return 5;
}
}
else {
for (count = p1.y + 1; count < p2.y; count++) {
storage = storage + get_obscurity(p1.x, count);
if (((scenario.ter_types[coord_to_ter(p1.x,count)].blockage > 2) || (is_lava(p1.x,count) == true)) && (mode == 1))
return 5;
}
}
return storage;
}
dx = p2.x - p1.x;
dy = p2.y - p1.y;
if (abs(dy) > abs(dx)) {
if (p2.y > p1.y) {
for (count = 1; count < dy; count++) {
storage = storage + get_obscurity(p1.x + (count * dx) / dy, p1.y + count);
if ( ((scenario.ter_types[coord_to_ter(p1.x + (count * dx) / dy,p1.y + count)].blockage > 2) ||
(is_lava(p1.x + (count * dx) / dy,p1.y + count) == true))
&& (mode == 1))
return 5;
}
}
else {
for (count = -1; count > dy; count--) {
storage = storage + get_obscurity(p1.x + (count * dx) / dy, p1.y + count);
if ( ((scenario.ter_types[coord_to_ter(p1.x + (count * dx) / dy, p1.y + count)].blockage > 2) ||
(is_lava(p1.x + (count * dx) / dy, p1.y + count) == true))
&& (mode == 1))
return 5;
}
}
return storage;
}
if (abs(dy) <= abs(dx)) {
if (p2.x > p1.x) {
for (count = 1; count < dx; count++) {
storage = storage + get_obscurity(p1.x + count, p1.y + (count * dy) / dx);
if (((scenario.ter_types[coord_to_ter(p1.x + count,p1.y + (count * dy) / dx)].blockage > 2) ||
(is_lava(p1.x + count,p1.y + (count * dy) / dx) == true))
&& (mode == 1))
return 5;
}
}
else {
for (count = -1; count > dx; count--) {
storage = storage + get_obscurity(p1.x + count, p1.y + (count * dy) / dx);
if ( ((scenario.ter_types[coord_to_ter(p1.x + count,p1.y + (count * dy) / dx)].blockage > 2) ||
(is_lava(p1.x + count,p1.y + (count * dy) / dx) == true))
&& (mode == 1))
return 5;
}
}
return storage;
}
if (storage > 5)
return 5;
else return storage;
}
bool monst_on_space(location loc,short m_num) { bool monst_on_space(location loc,short m_num) {
if (editing_town == false) if (editing_town == false)
return false; return false;

View File

@@ -10,7 +10,6 @@ void get_town_info();
void get_sign_resource(); void get_sign_resource();
void set_info_strings(); void set_info_strings();
cTown::cItem edit_item(cTown::cItem item); cTown::cItem edit_item(cTown::cItem item);
void modify_lists();
void set_up_lights(); void set_up_lights();
bool is_wall(short i,short j); bool is_wall(short i,short j);
bool is_correctable_wall(short i,short j); bool is_correctable_wall(short i,short j);
@@ -41,8 +40,7 @@ bool out_fix_water(location l);
void adjust_space(location l); void adjust_space(location l);
bool is_lava(short x,short y); bool is_lava(short x,short y);
ter_num_t coord_to_ter(short x,short y); ter_num_t coord_to_ter(short x,short y);
short get_obscurity(short x,short y); short light_obscurity(short x,short y);
short can_see(location p1,location p2,short mode);
bool place_item(location spot_hit,short which_item,short property,short always,short odds); bool place_item(location spot_hit,short which_item,short property,short always,short odds);
void place_items_in_town(); void place_items_in_town();
void set_up_start_screen(); void set_up_start_screen();

View File

@@ -133,12 +133,12 @@ bool save_ter_info(cDialog& me, cTerrain& store_ter) {
// TODO: Should somehow verify the pict number is valid // TODO: Should somehow verify the pict number is valid
std::string blockage = dynamic_cast<cLedGroup&>(me["blockage"]).getSelected(); std::string blockage = dynamic_cast<cLedGroup&>(me["blockage"]).getSelected();
if(blockage == "clear") store_ter.blockage = 0; if(blockage == "clear") store_ter.blockage = eTerObstruct::CLEAR;
else if(blockage == "curtain") store_ter.blockage = 1; else if(blockage == "curtain") store_ter.blockage = eTerObstruct::BLOCK_SIGHT;
else if(blockage == "special") store_ter.blockage = 2; else if(blockage == "special") store_ter.blockage = eTerObstruct::BLOCK_MONSTERS;
else if(blockage == "window") store_ter.blockage = 3; else if(blockage == "window") store_ter.blockage = eTerObstruct::BLOCK_MOVE;
else if(blockage == "obstructed") store_ter.blockage = 4; else if(blockage == "obstructed") store_ter.blockage = eTerObstruct::BLOCK_MOVE_AND_SHOOT;
else if(blockage == "opaque") store_ter.blockage = 5; else if(blockage == "opaque") store_ter.blockage = eTerObstruct::BLOCK_MOVE_AND_SIGHT;
store_ter.special = (eTerSpec) boost::lexical_cast<short>(dynamic_cast<cLedGroup&>(me["prop"]).getSelected().substr(4)); store_ter.special = (eTerSpec) boost::lexical_cast<short>(dynamic_cast<cLedGroup&>(me["prop"]).getSelected().substr(4));
/* /*
i = CDGN(813,6); i = CDGN(813,6);
@@ -335,22 +335,22 @@ void fill_ter_info(cDialog& me, short ter){
{ {
cLedGroup& led_ctrl = dynamic_cast<cLedGroup&>(me["blockage"]); cLedGroup& led_ctrl = dynamic_cast<cLedGroup&>(me["blockage"]);
switch(ter_type.blockage){ switch(ter_type.blockage){
case 0: case eTerObstruct::CLEAR:
led_ctrl.setSelected("clear"); led_ctrl.setSelected("clear");
break; break;
case 1: case eTerObstruct::BLOCK_SIGHT:
led_ctrl.setSelected("curtain"); led_ctrl.setSelected("curtain");
break; break;
case 2: case eTerObstruct::BLOCK_MONSTERS:
led_ctrl.setSelected("special"); led_ctrl.setSelected("special");
break; break;
case 3: case eTerObstruct::BLOCK_MOVE:
led_ctrl.setSelected("window"); led_ctrl.setSelected("window");
break; break;
case 4: case eTerObstruct::BLOCK_MOVE_AND_SHOOT:
led_ctrl.setSelected("obstructed"); led_ctrl.setSelected("obstructed");
break; break;
case 5: case eTerObstruct::BLOCK_MOVE_AND_SIGHT:
led_ctrl.setSelected("opaque"); led_ctrl.setSelected("opaque");
break; break;
} }

View File

@@ -257,7 +257,7 @@ void handle_file_menu(int item_hit) {
} }
break; break;
case 2: // save case 2: // save
modify_lists(); set_up_lights();
save_scenario(); save_scenario();
break; break;
case 3: // new scen case 3: // new scen

View File

@@ -1203,3 +1203,48 @@ void tileImage(RgnHandle area, GWorldPtr img, RECT srcRect, short mode){
} }
} }
#endif #endif
short can_see(location p1,location p2,std::function<short(short,short)> get_obscurity) {
short storage = 0;
if(p1.y == p2.y) {
if(p1.x > p2.x) {
for(short count = p2.x + 1; count < p1.x; count++)
storage += get_obscurity(count, p1.y);
} else {
for(short count = p1.x + 1; count < p2.x; count++)
storage += get_obscurity(count, p1.y);
}
} else if(p1.x == p2.x) {
if(p1.y > p2.y) {
for(short count = p1.y - 1; count > p2.y; count--)
storage += get_obscurity(p1.x, count);
} else {
for(short count = p1.y + 1; count < p2.y; count++)
storage += get_obscurity(p1.x, count);
}
} else {
short dx = p2.x - p1.x;
short dy = p2.y - p1.y;
if(abs(dy) > abs(dx)) {
if(p2.y > p1.y) {
for(short count = 1; count < dy; count++)
storage += get_obscurity(p1.x + (count * dx) / dy, p1.y + count);
} else {
for(short count = -1; count > dy; count--)
storage += get_obscurity(p1.x + (count * dx) / dy, p1.y + count);
}
}
if(abs(dy) <= abs(dx)) {
if(p2.x > p1.x) {
for(short count = 1; count < dx; count++)
storage += get_obscurity(p1.x + count, p1.y + (count * dy) / dx);
} else {
for(short count = -1; count > dx; count--)
storage += get_obscurity(p1.x + count, p1.y + (count * dy) / dx);
}
}
}
return storage;
}

View File

@@ -10,6 +10,7 @@
#define GRAPHTOOL_H #define GRAPHTOOL_H
#include <string> #include <string>
#include <functional>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include "location.h" #include "location.h"
@@ -121,6 +122,9 @@ void clip_rect(sf::RenderTarget& where, RECT rect);
void clip_region(sf::RenderWindow& where, Region& region); void clip_region(sf::RenderWindow& where, Region& region);
void undo_clip(sf::RenderTarget& where); void undo_clip(sf::RenderTarget& where);
// This probably doesn't quite fit here, but it fits worse pretty much everywhere else in the common sources
short can_see(location p1,location p2,std::function<short(short,short)> get_obscurity);
#ifndef GRAPHTOOL_CPP #ifndef GRAPHTOOL_CPP
extern m_pic_index_t m_pic_index[200]; extern m_pic_index_t m_pic_index[200];
extern RECT bg[]; extern RECT bg[];