Leaving ZKR starting fort through the south gate (by abnormal means) and traveling a few steps south leads to a crash
The issue was identifies as trying to check if the tile has a road in a next sector to the south.
Save attached - move 1 tile south.
Backtrace:
Thread 1 "Blades of Exile" received signal SIGSEGV, Segmentation fault.
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000EA9 RBX: 0x000000000000000F RCX: 0x0000000000000000 RDX: 0x000000000000000E o d I t s z a P c
RSI: 0x00000000000000C1 RDI: 0x000055555598AE20 RBP: 0x00007FFFFFFFA580 RSP: 0x00007FFFFFFFA540 RIP: 0x000055555570D6A0
R8 : 0x000000000000000F R9 : 0x0000555556BF01E0 R10: 0x0000000000000006 R11: 0x000055555652FD50 R12: 0x000055555557CE10
R13: 0x0000000000000000 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x55555570d6a0 <cCurOut::is_road(int, int)+192>: movzx eax,BYTE PTR [rax]
0x55555570d6a3 <cCurOut::is_road(int, int)+195>: add rsp,0x38
0x55555570d6a7 <cCurOut::is_road(int, int)+199>: pop rbx
0x55555570d6a8 <cCurOut::is_road(int, int)+200>: pop rbp
0x55555570d6a9 <cCurOut::is_road(int, int)+201>: ret
0x55555570d6aa <cUniverse::cUniverse(long)>: push rbp
0x55555570d6ab <cUniverse::cUniverse(long)+1>: mov rbp,rsp
0x55555570d6ae <cUniverse::cUniverse(long)+4>: push rbx
-----------------------------------------------------------------------------------------------------------------------------
0x000055555570d6a0 in cCurOut::is_road (this=0x55555599fa98 <univ+87256>, x=0xe, y=0x0) at src/universe/universe.cpp:904
904 return univ.scenario.outdoors[sector_x][sector_y]->roads[x][y];
gdb$ bt full
#0 0x000055555570d6a0 in cCurOut::is_road (this=0x55555599fa98 <univ+87256>, x=0xe, y=0x0) at src/universe/universe.cpp:904
sector_x = 0x0
sector_y = 0xf
#1 0x0000555555602669 in draw_terrain (mode=0x0) at build/obj/game/boe.graphics.cpp:901
r = 0x8
q = 0x0
where_draw = {x = 0xe, y = 0x30}
sector_p_in = {x = 0x0, y = 0xe}
view_loc = {x = 0x0, y = 0x0}
can_draw = 0x1
spec_terrain = 0x0
off_terrain = 0x0
draw_frills = 0x1
frills_on = 0x1
#2 0x00005555555848f3 in handle_action (event=...) at build/obj/game/boe.actions.cpp:1420
s1 = 0x0
s2 = 0x0
s3 = 0x0
item_hit = 0x0
are_done = 0x0
need_redraw = 0x1
did_something = 0x1
need_reprint = 0x0
pc_delayed = 0x0
cur_loc = {x = 0x12, y = 0x2b}
loc_in_sec = {x = 0x0, y = 0x0}
cur_direction = {x = 0x0, y = 0x1}
button_hit = 0xc
right_button = 0x0
previous_mode = 3208677224
world_screen = {top = 0x14, left = 0x20, bottom = 0x159, right = 0x11d}
str = <incomplete type>
the_point = {x = 0x95, y = 0xd7}
point_in_area = {x = 0x0, y = 0x0}
#3 0x00005555555860ff in handle_keystroke (event=...) at build/obj/game/boe.actions.cpp:1680
i = 0x2
are_done = 0x0
pass_point = {x = 0x12b, y = 0x1ae}
sout = <incomplete type>
keypad = {sf::Keyboard::Numpad0, sf::Keyboard::Numpad1, sf::Keyboard::Numpad2, sf::Keyboard::Numpad3, sf::Keyboard::Numpad4, sf::Keyboard::Numpad5, sf::Keyboard::Numpad6, sf::Keyboard::Numpad7, sf::Keyboard::Numpad8, sf::Keyboard::Numpad9}
terrain_click = {{x = 0x96, y = 0xb9}, {x = 0x78, y = 0xd7}, {x = 0x96, y = 0xd7}, {x = 0xb4, y = 0xd7}, {x = 0x78, y = 0xb9}, {x = 0x96, y = 0xb9}, {x = 0xb4, y = 0xb9}, {x = 0x78, y = 0x9b}, {x = 0x96, y = 0x9b}, {x = 0xb4, y = 0x87}}
talk_chars = {sf::Keyboard::L, sf::Keyboard::N, sf::Keyboard::J, sf::Keyboard::B, sf::Keyboard::S, sf::Keyboard::R, sf::Keyboard::D, sf::Keyboard::G, sf::Keyboard::A}
shop_chars = {sf::Keyboard::A, sf::Keyboard::B, sf::Keyboard::C, sf::Keyboard::D, sf::Keyboard::E, sf::Keyboard::F, sf::Keyboard::G, sf::Keyboard::H}
chr2 = sf::Keyboard::Numpad2
pass_event = {type = sf::Event::MouseButtonPressed, {size = {width = 0x0, height = 0x12b}, key = {code = sf::Keyboard::A, alt = 0x2b, control = 0x1, shift = 0x0, system = 0x0}, text = {unicode = 0x0}, mouseMove = {x = 0x0, y = 0x12b}, mouseButton = {button = sf::Mouse::Left, x = 0x12b, y = 0x1ae}, mouseWheel = {delta = 0x0, x = 0x12b, y = 0x1ae}, mouseWheelScroll = {wheel = sf::Mouse::VerticalWheel, delta = 4.18988241e-43, x = 0x1ae, y = 0x0}, joystickMove = {joystickId = 0x0, axis = 299, position = 6.0255834e-43}, joystickButton = {joystickId = 0x0, button = 0x12b}, joystickConnect = {joystickId = 0x0}, touch = {finger = 0x0, x = 0x12b, y = 0x1ae}, sensor = {type = sf::Sensor::Accelerometer, x = 4.18988241e-43, y = 6.0255834e-43, z = 0}}}
chr = 0xa2
#4 0x00005555556336e1 in Handle_One_Event () at build/obj/game/boe.main.cpp:257
twentyTicks = 0x14d
fortyTicks = 0x29a
#5 0x0000555555632bc0 in main (argc=0x1, argv=0x7fffffffde78) at build/obj/game/boe.main.cpp:137
remaining_time_budget_in_us = 0x38bc
framerate_clock = {m_startTime = {static Zero = {static Zero = <same as static member of an already seen type>, m_microseconds = 0x0}, m_microseconds = 0x2884dd32b}}
desired_microseconds_per_frame = 0x411a
gdb$
More precisely, it's trying to access the next sector to the south, which doesn't exist. We either need to enable "dummy" values if the view scrolls off the edge of the map, or have some special case so that it doesn't scroll at all when you're at the edge.
You could also use a system like what Realmz does here: setting invalid map sectors to ID -1, and checking for that ID before attempting to load an adjacent section. If there’s no sector there, don’t scroll the map past what would be the transition point.
I think that's basically the sort of idea I meant here:
have some special case so that it doesn't scroll at all when you're at the edge.
The other method is probably easier, but then you'd see blackness or something beyond the edge. On the other hand, that might be okay - scenarios are supposed to be structured so you can't get that close, anyway. As long as it doesn't crash…
Loading this save file and moving south in the current build, I don't get a crash.
Responding to what you said on IRC…
[01:45am] NQNStudios: celticminstrel did outdoor sections used to be 96x96 tiles? [01:46am] NQNStudios: I reproduced this bug by making a scenario with no walls blocking the south boundary https://github.com/calref/cboe/issues/240 [01:46am] NQNStudios: it's boundary checking for 96, but the outdoor section is actually 48x48 [02:02am] NQNStudios: ohhhhh would it be 96 because multiple sections could be in the vector it's checking?
The original game loads 4 outdoor sections into a 96x96 combined grid, shifting them as you move around the outdoors. I don't think I remember altering that aspect.