Fix traps due to invalid level data

`Descent 2: Counterstrike` level 9 specifies a control center trigger on
a side with no wall.  This is not valid.  In normal play, wall_toggle
silently ignored this, and newdemo_pop_ctrlcen_triggers had undefined
behavior.  Add a warning in wall_toggle to report levels like this.  Add
handling in newdemo_pop_ctrlcen_triggers to detect and suppress this
bogus data.

`Descent 2: Counterstrike` level 11 specifies a control center trigger
on a side with no child segment.  This is not valid, so
newdemo_pop_ctrlcen_triggers again had undefined behavior.  Add handling
to detect and suppress this bogus data.

Reported-by: Descender1032 <https://forum.dxx-rebirth.com/showthread.php?tid=992>
This commit is contained in:
Kp 2017-11-25 01:56:51 +00:00
parent c60c0352f0
commit 8ae4ef9eb5
2 changed files with 26 additions and 4 deletions

View file

@ -1937,9 +1937,29 @@ static void newdemo_pop_ctrlcen_triggers()
for (int i = 0; i < ControlCenterTriggers.num_links; i++) {
const auto &&seg = vmsegptridx(ControlCenterTriggers.seg[i]);
const auto side = ControlCenterTriggers.side[i];
const auto &&csegp = vmsegptr(seg->children[side]);
const auto csegi = seg->children[side];
if (csegi == segment_none)
{
/* Some levels specify control center triggers for
* segments/sides that have no wall. `Descent 2:
* Counterstrike` level 11, control center trigger 0 would
* fault without this test.
*/
continue;
}
const auto &&csegp = vmsegptr(csegi);
auto cside = find_connect_side(seg, csegp);
const auto anim_num = vcwallptr(seg->sides[side].wall_num)->clip_num;
const auto wall_num = seg->sides[side].wall_num;
if (wall_num == wall_none)
{
/* Some levels specify control center triggers for
* segments/sides that have no wall. `Descent 2:
* Counterstrike` level 9, control center trigger 2 would
* fault without this test.
*/
continue;
}
const auto anim_num = vcwallptr(wall_num)->clip_num;
const auto n = WallAnims[anim_num].num_frames;
const auto t = WallAnims[anim_num].flags & WCF_TMAP1
? &side::tmap_num

View file

@ -1071,8 +1071,10 @@ void wall_toggle(const vmsegptridx_t segp, unsigned side)
#endif
return;
}
auto wall_num = segp->sides[side].wall_num;
if (wall_num == wall_none) {
const auto wall_num = segp->sides[side].wall_num;
if (wall_num == wall_none)
{
LevelError("Ignoring attempt to toggle wall in segment %hu, side %u: no wall exists there.", segp.get_unchecked_index(), side);
return;
}