Add all files
This commit is contained in:
509
src/scripts/entities/world/pot.gd
Normal file
509
src/scripts/entities/world/pot.gd
Normal file
@@ -0,0 +1,509 @@
|
||||
extends CharacterBody2D
|
||||
|
||||
var tileParticleScene = preload("res://scripts/components/TileParticle.tscn")
|
||||
|
||||
var liftable = true
|
||||
var thrown_by = null
|
||||
var entity_id = ""
|
||||
var object_name = "bomb"
|
||||
|
||||
@export var is_being_thrown = false
|
||||
@export var is_being_lifted = false
|
||||
@export var is_being_put_down = false
|
||||
@export var is_being_grabbed = false
|
||||
@export var is_moving = false
|
||||
@export var is_spawning = false
|
||||
@export var is_fused = false
|
||||
|
||||
var throw_speed = 200
|
||||
var throw_height = 30
|
||||
var current_height = 0
|
||||
var gravity = 800
|
||||
var holder = null
|
||||
var flipFromWall = false
|
||||
|
||||
# Add Z-axis variables similar to loot.gd
|
||||
@export var positionZ = 0.0
|
||||
var velocityZ = 0.0
|
||||
var accelerationZ = -330.0 # Gravity
|
||||
var bounceRestitution = 0.3
|
||||
var minBounceVelocity = 60.0
|
||||
|
||||
var destroy_initiated = false
|
||||
@export var is_destroyed = false
|
||||
|
||||
# Smooth lifting variables
|
||||
var target_position = Vector2.ZERO
|
||||
var lift_height = 12.0 # Height above player's head
|
||||
var lift_speed = 10.0 # Speed of smooth movement
|
||||
var put_down_start_pos = Vector2.ZERO
|
||||
var put_down_target_pos = Vector2.ZERO
|
||||
@export var lift_progress = 0.0
|
||||
var re_enable_collision_after_time = 0.0
|
||||
var re_enable_time = 0.17
|
||||
var previousFrameVel = Vector2.ZERO
|
||||
var hasShownSmokePuffs = false
|
||||
|
||||
func _ready() -> void:
|
||||
if is_spawning:
|
||||
liftable = false
|
||||
$Area2DCollision.set_deferred("monitoring", false)
|
||||
self.set_collision_layer_value(8, false)
|
||||
self.set_collision_mask_value(9, false)
|
||||
self.set_collision_mask_value(10, false)
|
||||
self.set_collision_mask_value(8, false)
|
||||
update_sprite_scale()
|
||||
pass
|
||||
indicate(false)
|
||||
pass
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if multiplayer.is_server():
|
||||
if is_being_thrown:
|
||||
re_enable_collision_after_time -= delta
|
||||
if re_enable_collision_after_time <= 0.0:
|
||||
# enable collisions again
|
||||
self.set_collision_layer_value(8, true)
|
||||
self.set_collision_mask_value(9, true)
|
||||
self.set_collision_mask_value(10, true)
|
||||
self.set_collision_mask_value(8, true)
|
||||
re_enable_collision_after_time = 0
|
||||
|
||||
# Apply gravity to vertical movement
|
||||
velocityZ += accelerationZ * delta
|
||||
positionZ += velocityZ * delta
|
||||
|
||||
if positionZ <= 0:
|
||||
# Pot has hit the ground
|
||||
positionZ = 0
|
||||
|
||||
$SfxLand.play()
|
||||
$GPUParticles2D.emitting = true
|
||||
$GPUParticles2D/TimerSmokeParticles.start()
|
||||
if abs(velocityZ) > minBounceVelocity:
|
||||
velocityZ = -velocityZ * bounceRestitution
|
||||
else:
|
||||
velocityZ = 0
|
||||
is_being_thrown = false
|
||||
velocity = velocity.lerp(Vector2.ZERO, 0.5)
|
||||
if velocity.x == 0 and velocity.y == 0:
|
||||
thrown_by = null
|
||||
|
||||
# Move horizontally
|
||||
var collision = move_and_collide(velocity * delta)
|
||||
if collision:
|
||||
if positionZ == 0:
|
||||
is_being_thrown = false
|
||||
update_sprite_scale()
|
||||
elif is_being_put_down:
|
||||
lift_progress -= delta * lift_speed
|
||||
if lift_progress <= 0.0:
|
||||
$SfxLand.play()
|
||||
$GPUParticles2D.emitting = true
|
||||
$GPUParticles2D/TimerSmokeParticles.start()
|
||||
lift_progress = 0
|
||||
is_being_put_down = false
|
||||
is_being_lifted = false
|
||||
holder = null
|
||||
positionZ = 0
|
||||
# enable collisions again
|
||||
self.set_collision_layer_value(8, true)
|
||||
self.set_collision_mask_value(9, true)
|
||||
self.set_collision_mask_value(10, true)
|
||||
self.set_collision_mask_value(7, true)
|
||||
self.set_collision_mask_value(8, true)
|
||||
$Area2DCollision.set_deferred("monitoring", true)
|
||||
else:
|
||||
global_position = put_down_start_pos.lerp(put_down_target_pos, 1.0 - lift_progress)
|
||||
positionZ = lift_height * lift_progress
|
||||
update_sprite_scale()
|
||||
elif is_being_lifted:
|
||||
# Smooth lifting animation
|
||||
if holder:
|
||||
$GPUParticles2D.emitting = false
|
||||
target_position = holder.global_position
|
||||
#target_position.y -= 2
|
||||
if lift_progress < 1.0:
|
||||
lift_progress += delta * lift_speed
|
||||
lift_progress = min(lift_progress, 1.0)
|
||||
global_position = global_position.lerp(target_position, lift_progress)
|
||||
positionZ = lift_height * lift_progress
|
||||
else:
|
||||
lift_progress = 1.0
|
||||
global_position = target_position
|
||||
positionZ = lift_height
|
||||
update_sprite_scale()
|
||||
pass
|
||||
elif is_being_grabbed:
|
||||
#if velocity != Vector2.ZERO and velocity != previousFrameVel and hasShownSmokePuffs == false:
|
||||
if velocity != Vector2.ZERO:
|
||||
is_moving = true
|
||||
#hasShownSmokePuffs = true
|
||||
$GPUParticles2D.emitting = true
|
||||
$GPUParticles2D/TimerSmokeParticles.start()
|
||||
if !$SfxDrag2.playing:
|
||||
$SfxDrag2.play()
|
||||
else:
|
||||
is_moving = false
|
||||
if $SfxDrag2.playing:
|
||||
$SfxDrag2.stop()
|
||||
move_and_collide(velocity * delta)
|
||||
previousFrameVel = velocity
|
||||
pass
|
||||
else: # it just spawned:
|
||||
# Apply gravity to vertical movement
|
||||
velocityZ += accelerationZ * delta
|
||||
positionZ += velocityZ * delta
|
||||
|
||||
if positionZ <= 0:
|
||||
if is_spawning:
|
||||
is_spawning = false
|
||||
liftable = true
|
||||
$Area2DCollision.set_deferred("monitoring", true)
|
||||
self.set_collision_layer_value(8, true)
|
||||
self.set_collision_mask_value(9, true)
|
||||
self.set_collision_mask_value(10, true)
|
||||
self.set_collision_mask_value(8, true)
|
||||
# Pot has hit the ground
|
||||
positionZ = 0
|
||||
if abs(velocityZ) > 30:
|
||||
$SfxLand.play()
|
||||
$GPUParticles2D.emitting = true
|
||||
$GPUParticles2D/TimerSmokeParticles.start()
|
||||
if abs(velocityZ) > minBounceVelocity:
|
||||
velocityZ = -velocityZ * bounceRestitution
|
||||
else:
|
||||
velocityZ = 0
|
||||
velocity = velocity.lerp(Vector2.ZERO, 0.5)
|
||||
move_and_collide(velocity * delta)
|
||||
update_sprite_scale()
|
||||
pass
|
||||
else:
|
||||
if is_fused and $AnimationPlayer.current_animation == "idle":
|
||||
if $SfxBombFuse.playing:
|
||||
$SfxBombFuse.play()
|
||||
$AnimationPlayer.play("fused")
|
||||
# for client:'
|
||||
if is_being_thrown:
|
||||
if $SfxDrag2.playing:
|
||||
$SfxDrag2.stop()
|
||||
if positionZ <= 0:
|
||||
if !$SfxLand.playing:
|
||||
$SfxLand.play()
|
||||
$GPUParticles2D.emitting = true
|
||||
$GPUParticles2D/TimerSmokeParticles.start()
|
||||
elif is_being_put_down:
|
||||
if $SfxDrag2.playing:
|
||||
$SfxDrag2.stop()
|
||||
if !$SfxLand.playing:
|
||||
$SfxLand.play()
|
||||
$GPUParticles2D.emitting = true
|
||||
$GPUParticles2D/TimerSmokeParticles.start()
|
||||
elif is_being_lifted:
|
||||
if $SfxDrag2.playing:
|
||||
$SfxDrag2.stop()
|
||||
$GPUParticles2D.emitting = false
|
||||
elif is_being_grabbed:
|
||||
if is_moving:
|
||||
$GPUParticles2D.emitting = true
|
||||
$GPUParticles2D/TimerSmokeParticles.start()
|
||||
if !$SfxDrag2.playing:
|
||||
$SfxDrag2.play()
|
||||
else:
|
||||
if $SfxDrag2.playing:
|
||||
$SfxDrag2.stop()
|
||||
else:
|
||||
if is_spawning:
|
||||
if positionZ <= 0:
|
||||
$SfxLand.play()
|
||||
$GPUParticles2D.emitting = true
|
||||
$GPUParticles2D/TimerSmokeParticles.start()
|
||||
else:
|
||||
if $SfxLand.playing:
|
||||
$SfxLand.stop()
|
||||
if $SfxDrag2.playing:
|
||||
$SfxDrag2.stop()
|
||||
pass
|
||||
update_sprite_scale()
|
||||
if is_destroyed and !destroy_initiated:
|
||||
destroy_initiated = true
|
||||
show_destroy_effect()
|
||||
|
||||
pass
|
||||
pass
|
||||
func update_sprite_scale() -> void:
|
||||
# Calculate scale based on height
|
||||
# Maximum height will have scale 1.3, ground will have scale 1.0
|
||||
var height_factor = positionZ / 50.0 # Assuming 50 is max height
|
||||
var posY = positionZ # Direct mapping of Z to Y offset
|
||||
var sc = 1.0 + (0.1 * height_factor) # Slightly less scale change than loot (0.3 instead of 0.8)
|
||||
$Sprite2D.scale = Vector2(sc, sc)
|
||||
$Sprite2D.offset.y = -posY
|
||||
# Also update shadow position and scale
|
||||
if is_being_lifted:
|
||||
$Sprite2D.z_as_relative = false
|
||||
$Sprite2D.z_index = 12
|
||||
$Sprite2DShadow.offset.y = 0 # Base shadow position
|
||||
else:
|
||||
$Sprite2D.z_as_relative = true
|
||||
$Sprite2D.z_index = 0
|
||||
$Sprite2DShadow.offset.y = 0
|
||||
#$Sprite2DShadow.scale = Vector2(1.125 * sc, 0.5 * sc) # Scale shadow with height
|
||||
$Sprite2DShadow.scale = Vector2(1,1)
|
||||
#$Sprite2DShadow.modulate.
|
||||
|
||||
func throw(direction: Vector2, initial_velocity: float = 200):
|
||||
self.set_collision_mask_value(7, true)
|
||||
$Area2DCollision.set_deferred("monitoring", true)
|
||||
$SfxThrow.play()
|
||||
|
||||
is_being_lifted = false
|
||||
is_being_thrown = true
|
||||
is_being_put_down = false
|
||||
thrown_by = holder
|
||||
holder = null
|
||||
velocity = direction * initial_velocity
|
||||
velocityZ = throw_height
|
||||
positionZ = lift_height
|
||||
current_height = 0
|
||||
re_enable_collision_after_time = re_enable_time
|
||||
|
||||
func grab(new_holder: CharacterBody2D) -> bool:
|
||||
if positionZ <= 0 and holder == null: # only allow grab if no previous owner and position is 0
|
||||
$GPUParticles2D/TimerSmokeParticles.stop() #reset...
|
||||
holder = new_holder
|
||||
is_being_grabbed = true
|
||||
indicate(false)
|
||||
return true
|
||||
return false
|
||||
|
||||
func release():
|
||||
holder = null
|
||||
is_being_grabbed = false
|
||||
hasShownSmokePuffs = false
|
||||
indicate(true)
|
||||
if $SfxDrag2.playing:
|
||||
$SfxDrag2.stop()
|
||||
pass
|
||||
|
||||
func lift(new_holder: CharacterBody2D):
|
||||
if (new_holder != holder and holder != null) and "lose_held_entity" in holder:
|
||||
# steal from holder
|
||||
holder.lose_held_entity(self)
|
||||
indicate(false)
|
||||
$Area2DCollision.set_deferred("monitoring", false)
|
||||
thrown_by = null
|
||||
holder = new_holder
|
||||
# disable collisions
|
||||
self.set_collision_layer_value(8, false)
|
||||
self.set_collision_mask_value(7, false)
|
||||
self.set_collision_mask_value(8, false)
|
||||
self.set_collision_mask_value(9, false)
|
||||
self.set_collision_mask_value(10, false)
|
||||
is_being_lifted = true
|
||||
is_being_grabbed = false
|
||||
is_being_thrown = false
|
||||
is_being_put_down = false
|
||||
lift_progress = 0.0
|
||||
velocityZ = 0
|
||||
$SfxLand.play()
|
||||
|
||||
func put_down() -> bool:
|
||||
if not is_being_lifted or is_being_put_down:
|
||||
return false
|
||||
|
||||
var dropDir = holder.last_direction
|
||||
dropDir.x *= 12
|
||||
if dropDir.y > 0:
|
||||
dropDir.y *= 10
|
||||
else:
|
||||
dropDir.y *= 10
|
||||
put_down_target_pos = holder.global_position + dropDir
|
||||
|
||||
# First check: Direct space state query for walls
|
||||
var space_state = get_world_2d().direct_space_state
|
||||
var params = PhysicsPointQueryParameters2D.new()
|
||||
params.position = put_down_target_pos
|
||||
params.collision_mask = 64 # Layer for walls (usually layer 7)
|
||||
params.collide_with_areas = true
|
||||
params.collide_with_bodies = true
|
||||
|
||||
var results = space_state.intersect_point(params)
|
||||
if results.size() > 0:
|
||||
# Found overlapping walls at target position
|
||||
print("Cannot place pot: Wall in the way")
|
||||
return false
|
||||
|
||||
# Second check: Line of sight between player and target position
|
||||
var query = PhysicsRayQueryParameters2D.create(
|
||||
holder.global_position,
|
||||
put_down_target_pos,
|
||||
64 # Wall collision mask
|
||||
)
|
||||
query.collide_with_areas = true
|
||||
query.collide_with_bodies = true
|
||||
|
||||
var result = space_state.intersect_ray(query)
|
||||
if result:
|
||||
# Hit something between player and target position
|
||||
print("Cannot place pot: Path blocked")
|
||||
return false
|
||||
|
||||
# Third check: Make sure we're not placing on top of another pot or object
|
||||
params.collision_mask = 128 # Layer for pots/objects
|
||||
results = space_state.intersect_point(params)
|
||||
if results.size() > 0:
|
||||
# Found overlapping objects at target position
|
||||
print("Cannot place pot: Object in the way")
|
||||
return false
|
||||
$Area2DCollision.set_deferred("monitoring", false)
|
||||
|
||||
# Position is valid, proceed with putting down
|
||||
self.set_collision_mask_value(7, true) # instantly reenenable collision with wall
|
||||
is_being_put_down = true
|
||||
is_being_lifted = false
|
||||
put_down_start_pos = global_position
|
||||
thrown_by = null
|
||||
holder = null
|
||||
|
||||
indicate(true)
|
||||
|
||||
return true
|
||||
|
||||
func remove():
|
||||
|
||||
var fade_tween = create_tween()
|
||||
fade_tween.set_trans(Tween.TRANS_CUBIC)
|
||||
fade_tween.set_ease(Tween.EASE_OUT)
|
||||
fade_tween.tween_property($Sprite2D, "modulate:a", 0.0, 0.6)
|
||||
#await fade_tween.finished
|
||||
await $SfxShatter.finished
|
||||
if $SfxLand.playing:
|
||||
$SfxLand.stop()
|
||||
if $SfxDrag2.playing:
|
||||
$SfxDrag2.stop()
|
||||
$GPUParticles2D.emitting = false
|
||||
#$SfxShatter.stop()
|
||||
if multiplayer.is_server():
|
||||
call_deferred("queue_free")
|
||||
pass
|
||||
|
||||
|
||||
func create4TileParticles():
|
||||
var sprite_texture = $Sprite2D.texture
|
||||
var frame_width = sprite_texture.get_width() / $Sprite2D.hframes
|
||||
var frame_height = sprite_texture.get_height() / $Sprite2D.vframes
|
||||
var frame_x = ($Sprite2D.frame % $Sprite2D.hframes) * frame_width
|
||||
var frame_y = ($Sprite2D.frame / $Sprite2D.hframes) * frame_height
|
||||
|
||||
# Create 4 particles with different directions and different parts of the texture
|
||||
var directions = [
|
||||
Vector2(-1, -1).normalized(), # Top-left
|
||||
Vector2(1, -1).normalized(), # Top-right
|
||||
Vector2(-1, 1).normalized(), # Bottom-left
|
||||
Vector2(1, 1).normalized() # Bottom-right
|
||||
]
|
||||
|
||||
var regions = [
|
||||
Rect2(frame_x, frame_y, frame_width / 2, frame_height / 2), # Top-left
|
||||
Rect2(frame_x + frame_width / 2, frame_y, frame_width / 2, frame_height / 2), # Top-right
|
||||
Rect2(frame_x, frame_y + frame_height / 2, frame_width / 2, frame_height / 2), # Bottom-left
|
||||
Rect2(frame_x + frame_width / 2, frame_y + frame_height / 2, frame_width / 2, frame_height / 2) # Bottom-right
|
||||
]
|
||||
|
||||
for i in range(4):
|
||||
var tp = tileParticleScene.instantiate() as CharacterBody2D
|
||||
var spr2D = tp.get_node("Sprite2D") as Sprite2D
|
||||
tp.global_position = global_position
|
||||
|
||||
# Set up the sprite's texture and region
|
||||
spr2D.texture = sprite_texture
|
||||
spr2D.region_enabled = true
|
||||
spr2D.region_rect = regions[i]
|
||||
|
||||
# Add some randomness to the velocity
|
||||
var speed = randf_range(170, 200)
|
||||
var dir = directions[i] + Vector2(randf_range(-0.2, 0.2), randf_range(-0.2, 0.2))
|
||||
tp.velocity = dir * speed
|
||||
|
||||
# Add some rotation
|
||||
tp.angular_velocity = randf_range(-7, 7)
|
||||
|
||||
get_parent().call_deferred("add_child", tp)
|
||||
|
||||
func indicate(iIndicate: bool):
|
||||
$Indicator.visible = iIndicate
|
||||
if !liftable or is_being_lifted:
|
||||
$Indicator.visible = false
|
||||
pass
|
||||
|
||||
|
||||
func _on_area_2d_collision_body_entered(body: Node2D) -> void:
|
||||
if is_being_thrown == false or body == self or body == thrown_by:
|
||||
return
|
||||
if multiplayer.is_server():
|
||||
|
||||
var collision_shape = $Area2DCollision.get_overlapping_bodies()
|
||||
|
||||
if collision_shape.size() > 0:
|
||||
var collider = collision_shape[0]
|
||||
var normal = (global_position - collider.global_position).normalized()
|
||||
if abs(velocity.x) > 0.05 or abs(velocity.y) > 0.05:
|
||||
if "take_damage" in body or body is TileMapLayer or collider is TileMapLayer:
|
||||
if "take_damage" in body:
|
||||
body.take_damage(self, thrown_by)
|
||||
elif collider != self and "breakPot" in collider:
|
||||
collider.take_damage(self, thrown_by)
|
||||
# create particles from pot:
|
||||
print("ye body is:", body)
|
||||
|
||||
take_damage.rpc(null, null)
|
||||
pass
|
||||
normal = velocity.normalized()
|
||||
velocity = velocity.bounce(normal) * 0.4 # slow down
|
||||
pass # Replace with function body.
|
||||
|
||||
func show_destroy_effect():
|
||||
$GPUParticles2D.emitting = true
|
||||
$Sprite2D.frame = 13 + 19 + 19
|
||||
$Sprite2DShadow.visible = false
|
||||
liftable = false
|
||||
indicate(false)
|
||||
create4TileParticles()
|
||||
is_being_thrown = false
|
||||
$Sprite2DShadow.visible = false
|
||||
# Play shatter sound
|
||||
$SfxShatter.play()
|
||||
self.call_deferred("remove")
|
||||
pass
|
||||
|
||||
@rpc("call_local")
|
||||
func take_damage(_iBody: Node2D, _iByWhoOrWhat: Node2D) -> void:
|
||||
is_destroyed = true # will trigger show_destroy_effect for clients...
|
||||
show_destroy_effect()
|
||||
# remove all kind of collision since it's broken now...
|
||||
self.set_deferred("monitoring", false)
|
||||
self.set_collision_layer_value(8, false)
|
||||
self.set_collision_mask_value(7, false)
|
||||
self.set_collision_mask_value(8, false)
|
||||
self.set_collision_mask_value(9, false)
|
||||
self.set_collision_mask_value(10, false)
|
||||
pass
|
||||
|
||||
func _on_area_2d_collision_body_exited(_body: Node2D) -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
func _on_area_2d_pickup_body_entered(_body: Node2D) -> void:
|
||||
indicate(true)
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
func _on_area_2d_pickup_body_exited(_body: Node2D) -> void:
|
||||
indicate(false)
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
func _on_timer_smoke_particles_timeout() -> void:
|
||||
$GPUParticles2D.emitting = false
|
||||
pass # Replace with function body.
|
||||
Reference in New Issue
Block a user