Fix casting beneath overhangs
This commit is contained in:
parent
40696b6bd9
commit
deab51a18a
4 changed files with 46 additions and 8 deletions
|
|
@ -56,6 +56,7 @@ var _rod: Node3D
|
||||||
var _rod_tip: Marker3D
|
var _rod_tip: Marker3D
|
||||||
var _rod_neutral_rotation: Vector3
|
var _rod_neutral_rotation: Vector3
|
||||||
var _cast_arrival_position: Vector3
|
var _cast_arrival_position: Vector3
|
||||||
|
var _active_cast_arc_height: float = 0.0
|
||||||
var _cast_tracks_water_surface: bool = false
|
var _cast_tracks_water_surface: bool = false
|
||||||
var _bobber_surface_position: Vector3
|
var _bobber_surface_position: Vector3
|
||||||
var _bobber_idle_elapsed: float = 0.0
|
var _bobber_idle_elapsed: float = 0.0
|
||||||
|
|
@ -153,6 +154,7 @@ func begin_cast(
|
||||||
target: Vector3,
|
target: Vector3,
|
||||||
blocked_landing_position: Vector3 = Vector3.ZERO,
|
blocked_landing_position: Vector3 = Vector3.ZERO,
|
||||||
cast_is_blocked: bool = false,
|
cast_is_blocked: bool = false,
|
||||||
|
resolved_arc_height: float = -1.0,
|
||||||
) -> void:
|
) -> void:
|
||||||
if _mode != VisualMode.AIMING or _rod_tip == null:
|
if _mode != VisualMode.AIMING or _rod_tip == null:
|
||||||
return
|
return
|
||||||
|
|
@ -165,6 +167,11 @@ func begin_cast(
|
||||||
_cast_arrival_position = (
|
_cast_arrival_position = (
|
||||||
blocked_landing_position if cast_is_blocked else target
|
blocked_landing_position if cast_is_blocked else target
|
||||||
)
|
)
|
||||||
|
_active_cast_arc_height = (
|
||||||
|
maxf(resolved_arc_height, 0.0)
|
||||||
|
if resolved_arc_height >= 0.0
|
||||||
|
else cast_arc_height
|
||||||
|
)
|
||||||
_cast_tracks_water_surface = not cast_is_blocked
|
_cast_tracks_water_surface = not cast_is_blocked
|
||||||
|
|
||||||
var cast_start: Vector3 = _rod_tip.global_position
|
var cast_start: Vector3 = _rod_tip.global_position
|
||||||
|
|
@ -302,6 +309,7 @@ func cleanup() -> void:
|
||||||
_bobber_base_scale = Vector3.ONE
|
_bobber_base_scale = Vector3.ONE
|
||||||
_bobber.rotation = Vector3.ZERO
|
_bobber.rotation = Vector3.ZERO
|
||||||
_cast_arrival_position = Vector3.ZERO
|
_cast_arrival_position = Vector3.ZERO
|
||||||
|
_active_cast_arc_height = 0.0
|
||||||
_cast_tracks_water_surface = false
|
_cast_tracks_water_surface = false
|
||||||
_bobber_surface_position = Vector3.ZERO
|
_bobber_surface_position = Vector3.ZERO
|
||||||
_bobber_idle_elapsed = 0.0
|
_bobber_idle_elapsed = 0.0
|
||||||
|
|
@ -319,7 +327,7 @@ func _set_cast_sample(
|
||||||
target: Vector3,
|
target: Vector3,
|
||||||
) -> void:
|
) -> void:
|
||||||
var sample: Vector3 = start.lerp(target, progress)
|
var sample: Vector3 = start.lerp(target, progress)
|
||||||
sample.y += sin(progress * PI) * cast_arc_height
|
sample.y += sin(progress * PI) * _active_cast_arc_height
|
||||||
if _cast_tracks_water_surface:
|
if _cast_tracks_water_surface:
|
||||||
sample.y += (
|
sample.y += (
|
||||||
WaterSurfaceMotionType.get_default_height_offset()
|
WaterSurfaceMotionType.get_default_height_offset()
|
||||||
|
|
|
||||||
|
|
@ -783,19 +783,31 @@ func _confirm_cast() -> void:
|
||||||
return
|
return
|
||||||
|
|
||||||
var cast_launch_position := _get_cast_launch_position()
|
var cast_launch_position := _get_cast_launch_position()
|
||||||
_cast_path_is_clear = is_cast_path_clear(
|
var resolved_cast_arc: Dictionary = _surface_resolver.resolve_cast_arc(
|
||||||
|
get_world_3d().direct_space_state,
|
||||||
cast_launch_position,
|
cast_launch_position,
|
||||||
_cast_target,
|
_cast_target,
|
||||||
|
_presentation.cast_arc_height,
|
||||||
)
|
)
|
||||||
|
var resolved_arc_height: float = float(
|
||||||
|
resolved_cast_arc.get("arc_height", _presentation.cast_arc_height)
|
||||||
|
)
|
||||||
|
var resolved_cast_collision: Dictionary = resolved_cast_arc.get(
|
||||||
|
"collision",
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
_cast_path_is_clear = resolved_cast_collision.is_empty()
|
||||||
var cast_is_invalid: bool = (
|
var cast_is_invalid: bool = (
|
||||||
not _aim_surface_sample.is_fishable() or not _cast_path_is_clear
|
not _aim_surface_sample.is_fishable() or not _cast_path_is_clear
|
||||||
)
|
)
|
||||||
var arrival_position: Vector3 = _cast_target
|
var arrival_position: Vector3 = _cast_target
|
||||||
if not _cast_path_is_clear:
|
if not _cast_path_is_clear:
|
||||||
arrival_position = _resolve_cast_impact_position(
|
var collision_position: Variant = resolved_cast_collision.get(
|
||||||
cast_launch_position,
|
"position",
|
||||||
_cast_target,
|
_cast_target,
|
||||||
)
|
)
|
||||||
|
if typeof(collision_position) == TYPE_VECTOR3:
|
||||||
|
arrival_position = collision_position
|
||||||
if _active_player != null:
|
if _active_player != null:
|
||||||
# Movement is available while aiming, then locks once the cast is
|
# Movement is available while aiming, then locks once the cast is
|
||||||
# released so the active bobber/fishing event remains anchored.
|
# released so the active bobber/fishing event remains anchored.
|
||||||
|
|
@ -806,6 +818,7 @@ func _confirm_cast() -> void:
|
||||||
_cast_target,
|
_cast_target,
|
||||||
arrival_position,
|
arrival_position,
|
||||||
cast_is_invalid,
|
cast_is_invalid,
|
||||||
|
resolved_arc_height,
|
||||||
)
|
)
|
||||||
_presentation.set_line_mode(FishingPresentationType.LineMode.TAUT)
|
_presentation.set_line_mode(FishingPresentationType.LineMode.TAUT)
|
||||||
|
|
||||||
|
|
@ -1410,6 +1423,7 @@ func resolve_fishing_surface(
|
||||||
get_world_3d().direct_space_state,
|
get_world_3d().direct_space_state,
|
||||||
target,
|
target,
|
||||||
resolved_reference_y,
|
resolved_reference_y,
|
||||||
|
water_occlusion_tolerance,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ func resolve_surface(
|
||||||
space_state: PhysicsDirectSpaceState3D,
|
space_state: PhysicsDirectSpaceState3D,
|
||||||
query_position: Vector3,
|
query_position: Vector3,
|
||||||
reference_y: float,
|
reference_y: float,
|
||||||
|
maximum_solid_rise: float = INF,
|
||||||
) -> FishingSurfaceSampleType:
|
) -> FishingSurfaceSampleType:
|
||||||
var sample := FishingSurfaceSampleType.new()
|
var sample := FishingSurfaceSampleType.new()
|
||||||
var ray_top: float = maxf(query_position.y, reference_y) + ray_start_height
|
var ray_top: float = maxf(query_position.y, reference_y) + ray_start_height
|
||||||
|
|
@ -33,12 +34,18 @@ func resolve_surface(
|
||||||
ray_top,
|
ray_top,
|
||||||
ray_bottom,
|
ray_bottom,
|
||||||
)
|
)
|
||||||
var solid_hit: Dictionary = _find_top_solid_surface(
|
var solid_ray_top: float = minf(
|
||||||
space_state,
|
|
||||||
query_position,
|
|
||||||
ray_top,
|
ray_top,
|
||||||
ray_bottom,
|
reference_y + maximum_solid_rise,
|
||||||
)
|
)
|
||||||
|
var solid_hit: Dictionary = {}
|
||||||
|
if solid_ray_top > ray_bottom:
|
||||||
|
solid_hit = _find_top_solid_surface(
|
||||||
|
space_state,
|
||||||
|
query_position,
|
||||||
|
solid_ray_top,
|
||||||
|
ray_bottom,
|
||||||
|
)
|
||||||
|
|
||||||
if water_region != null:
|
if water_region != null:
|
||||||
var water_height: float = water_region.get_surface_height()
|
var water_height: float = water_region.get_surface_height()
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ func _validate_resolver_layers() -> void:
|
||||||
_add_solid_box(world, Vector3(40.0, 2.0, 12.0), Vector3(10.0, -1.0, 0.0))
|
_add_solid_box(world, Vector3(40.0, 2.0, 12.0), Vector3(10.0, -1.0, 0.0))
|
||||||
_add_water_region(world, Vector3(0.0, 2.0, 0.0), Vector2(8.0, 8.0), PondPool)
|
_add_water_region(world, Vector3(0.0, 2.0, 0.0), Vector2(8.0, 8.0), PondPool)
|
||||||
_add_solid_box(world, Vector3(1.0, 1.0, 1.0), Vector3(2.0, 2.25, 0.0))
|
_add_solid_box(world, Vector3(1.0, 1.0, 1.0), Vector3(2.0, 2.25, 0.0))
|
||||||
|
_add_solid_box(world, Vector3(1.0, 1.0, 1.0), Vector3(-2.0, 6.0, 0.0))
|
||||||
_add_water_region(world, Vector3(10.0, 5.0, 0.0), Vector2(6.0, 6.0), PondPool)
|
_add_water_region(world, Vector3(10.0, 5.0, 0.0), Vector2(6.0, 6.0), PondPool)
|
||||||
_add_water_region(world, Vector3(20.0, 3.0, 0.0), Vector2(6.0, 6.0), null)
|
_add_water_region(world, Vector3(20.0, 3.0, 0.0), Vector2(6.0, 6.0), null)
|
||||||
await physics_frame
|
await physics_frame
|
||||||
|
|
@ -64,6 +65,14 @@ func _validate_resolver_layers() -> void:
|
||||||
)
|
)
|
||||||
assert(water.is_fishable())
|
assert(water.is_fishable())
|
||||||
assert(is_equal_approx(water.position.y, 2.0))
|
assert(is_equal_approx(water.position.y, 2.0))
|
||||||
|
var water_under_overhang: FishingSurfaceSampleType = resolver.resolve_surface(
|
||||||
|
space_state,
|
||||||
|
Vector3(-2.0, 4.0, 0.0),
|
||||||
|
4.0,
|
||||||
|
0.08,
|
||||||
|
)
|
||||||
|
assert(water_under_overhang.is_fishable())
|
||||||
|
assert(is_equal_approx(water_under_overhang.position.y, 2.0))
|
||||||
|
|
||||||
var covered_water: FishingSurfaceSampleType = resolver.resolve_surface(
|
var covered_water: FishingSurfaceSampleType = resolver.resolve_surface(
|
||||||
space_state,
|
space_state,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue