Skip to content

Commit

Permalink
Use collision data to assist Sendificator tracing
Browse files Browse the repository at this point in the history
This fixes #2966 and fixes #1609. Might help with #1074.
  • Loading branch information
TeamSpen210 committed Mar 18, 2024
1 parent 1a650dd commit edd3fa6
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 25 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
* Fix #4406: Centered Overgrown laser catcher doesn't output.
* Fix #4403: Missing palette icon for voxel logic gates.
* Fix an issue where Clean and Overgrown cube droppers could be tricked into dropping two cubes, if a spawning cube is pushed against the iris.
* Sendificators will fizzle cubes if transported past the exit door fizzler.
* Sendificators are now blocked by Closed Solid Fields.

------------------------------------------

Expand Down
7 changes: 4 additions & 3 deletions packages/sendificator/items/sendtor_all.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,15 @@
"Filename" "hmw/sendtor_cube_data.nut"
"Cube" "<sphere>"
}
"Pack" "PACK_HMW_SENDTOR_LOGIC"
// Export out these collision types for the VScript to check against.
"VScriptCollide" "GLASS OOB"
"addGlobal"
{
"File" "instances/bee2/logic/hmw/sendtor_manager.vmf"
"Name" "sendtor_ents"
}
"Has" "NeedsPortalMan" // Ensure the portalgun logic is added to the map, which tracks portals.
"NextCondition" "" // Don't do more than once.
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ ripple_fx <- Entities.FindByName(null, "@sendtor_ripple_e");

// BEE addition: If cube teleports outside max bounds, fizzle it. This can
// happen if you hit a laser cube inside a portal.
map_bounds_min <- -128.0;
map_bounds_max <- 26 * 128.0;
map_bounds_min <- -1024.0;
map_bounds_max <- 28 * 128.0;


// static variables
Expand Down Expand Up @@ -472,13 +472,20 @@ function trace()
}

if (hit == 0) {
// No more cubes and portals. We might still be hitting glass,
// so check the thickness.
if (place_laser_for_glass()) {
schedule_call("trace_glass();");
}
else {
reset_lasers();
// No more cubes and portals.

// First check if glass is here, via dumped BEE info.
if (::BEE_PointCollide(current_pos, ::BEECollide.GLASS, 0.5)) {
// Glass is here, check if it's thin enough for passage.
if (place_laser_for_glass()) {
schedule_call("trace_glass();");
}
else { // Can't place laser, fail.
reset_lasers();
}
} else {
// Not glass, place the cube.
teleport_cube();
}
return;
}
Expand Down Expand Up @@ -511,20 +518,22 @@ function trace_glass()
// Not glass, so this is the endpoint.
// Turn off the glass-tracing laser.
reset_laser_for_glass();

// Calculate the teleport destination
local cargo = find_cube_to_send(::sendtor_platform.GetOrigin());
local dest_offset = teleport_dest_offset;
if (cargo != null && is_monster_cube(cargo)) {
dest_offset = teleport_dest_offset_mon;
}
pos = backtrack_dest(dest_offset, index);
dest_confirm(cargo, pos);

teleport_cube();
return;
}
}

function teleport_cube() {
// Calculate the teleport destination
local cargo = find_cube_to_send(::sendtor_platform.GetOrigin());
local dest_offset = teleport_dest_offset;
if (cargo != null && is_monster_cube(cargo)) {
dest_offset = teleport_dest_offset_mon;
}
local pos = backtrack_dest(dest_offset, index);
dest_confirm(cargo, pos);
}


function trace_cubes()
{
Expand Down Expand Up @@ -702,13 +711,18 @@ function dest_confirm(cargo, location)
freeze_time = 0.1;
}

if (
if (::BEE_PointCollide(current_pos, ::BEECollide.OOB, 0.1)) {
// Placed in an OOB area - exit, obs rooms, etc.
// Fizzle the cube.
printl("Cube sendificated out of bounds, fizzling.");
EntFireByHandle(cargo, "Dissolve", "", 0.5, self, self);
} else if (
map_bounds_min > location.x || location.y > map_bounds_max ||
map_bounds_min > location.y || location.x > map_bounds_max ||
map_bounds_min > location.z || location.z > map_bounds_max
) {
// Outside the map, force a fizzle.
printl("Cube sendificated out of bounds, fizzling.");
// Fully outside the map, force a fizzle.
printl("Cube sendificated out of the map, fizzling.");
EntFireByHandle(cargo, "SilentDissolve", "", 0.1, self, self);
EntFireByHandle(cargo, "Dissolve", "", 0.25, self, self);
// Play fizzling sound globally, to let players know what happened.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Provides an interface to allow querying BEE's collision data.

::BEECollide <- {
// Must match Python constants!
NOTHING = 0,
SOLID = 1,
DECORATION = 2,
GRATING = 4,
GLASS = 8,
BRIDGE = 16,
FIZZLER = 32,
TEMPORARY = 64,
ANTLINES = 128,
OOB = 256,
}

class Plane {
norm = null;
dist = 0.0;
constructor(x, y, z, distance) {
norm = Vector(x, y, z);
dist = distance;
}
}

class Volume {
mins = null;
maxes = null;
planes = null; // List of planes
constructor(min_x, min_y, min_z, max_x, max_y, max_z, plane_list) {
mins = Vector(min_x, min_y, min_z);
maxes = Vector(max_x, max_y, max_z);
planes = plane_list;
}

function point_inside(point, tol) {
if (point.x < mins.x - tol || point.x > maxes.x + tol) {
return false;
}
if (point.y < mins.y - tol || point.y > maxes.y + tol) {
return false;
}
if (point.z < mins.z - tol || point.z > maxes.z + tol) {
return false;
}
if (planes == null) {
return true;
}
foreach(plane in planes) {
if (plane.norm.Dot(point) < plane.dist + tol) {
return false;
}
}
return true;
}
}

class Entry {
mask = 0;
volumes = null;
constructor(m, v) {
mask = m;
volumes = v;
}
}

function point_collide(point, mask, tolerance) {
foreach(entry in VOLUMES) {
if ((entry.mask & mask) == 0) {
continue;
}
foreach(volume in entry.volumes) {
local center = (volume.mins + volume.maxes) * 0.5;
if (volume.point_inside(point, tolerance)) {
return true;
}
}
}
return false;
}


::BEE_PointCollide <- point_collide.bindenv(this);

function Display() {
printl("Dump collisions:")
foreach(entry in VOLUMES) {
printl("- " + entry.mask + " = [");
foreach(volume in entry.volumes) {
local center = (volume.mins + volume.maxes) * 0.5;
DebugDrawBox(center, volume.mins - center, volume.maxes - center, 255, 128, 64, 255, 1);
printl(" center=" + center + ", " + (volume.mins - center) + " <-> " + (volume.maxes - center));
}
}
}

0 comments on commit edd3fa6

Please sign in to comment.