2024-08-19 20:32:19 +02:00
|
|
|
using Godot;
|
2024-08-20 16:17:44 +02:00
|
|
|
using System;
|
2024-08-19 20:32:19 +02:00
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
namespace Gmtk24 {
|
2024-08-19 22:27:26 +02:00
|
|
|
public partial class Table : Interactible {
|
2024-08-20 01:28:22 +02:00
|
|
|
[Export]
|
|
|
|
public Hud Hud;
|
|
|
|
|
2024-08-19 20:32:19 +02:00
|
|
|
[Export(PropertyHint.NodeType, "FuncGodotMap")]
|
|
|
|
public Node3D TrenchbroomMap;
|
2024-08-20 15:16:57 +02:00
|
|
|
[ExportCategory("Spawn Options")]
|
2024-08-20 01:20:14 +02:00
|
|
|
[Export]
|
2024-08-19 20:32:19 +02:00
|
|
|
public float RelativeScale = 0.05f;
|
|
|
|
[Export]
|
2024-08-20 01:20:52 +02:00
|
|
|
public Node3D SpawnPoint;
|
|
|
|
[Export(PropertyHint.LayersAvoidance)]
|
|
|
|
public uint BlockMask;
|
2024-08-20 02:29:32 +02:00
|
|
|
[Export(PropertyHint.LayersAvoidance)]
|
|
|
|
public uint GhostOnlyMask = 0b100000;
|
2024-08-20 15:16:57 +02:00
|
|
|
[Export(PropertyHint.LayersAvoidance)]
|
|
|
|
public uint PlaneOnlyLayer = 0b1000000;
|
|
|
|
[ExportCategory("Block Materials")]
|
2024-08-20 01:20:52 +02:00
|
|
|
[Export]
|
2024-08-19 20:32:19 +02:00
|
|
|
public ShaderMaterial BlockMaterial;
|
|
|
|
[Export]
|
2024-08-19 23:33:24 +02:00
|
|
|
public ShaderMaterial BlockHoverMaterial;
|
|
|
|
[Export]
|
2024-08-20 01:20:52 +02:00
|
|
|
public ShaderMaterial BlockGhostMaterial;
|
2024-08-19 20:32:19 +02:00
|
|
|
|
2024-08-20 15:16:57 +02:00
|
|
|
[ExportCategory("Scene Items")]
|
2024-08-19 23:33:24 +02:00
|
|
|
[Export]
|
|
|
|
public Orbit Orbit;
|
2024-08-20 15:16:57 +02:00
|
|
|
[Export]
|
|
|
|
public StaticBody3D Plane;
|
2024-08-19 23:33:24 +02:00
|
|
|
|
2024-08-20 01:20:52 +02:00
|
|
|
public BuildingBlock GhostBlock;
|
2024-08-20 15:16:57 +02:00
|
|
|
private Vector3 GhostBlockNormal;
|
2024-08-20 01:20:52 +02:00
|
|
|
|
2024-08-20 16:17:44 +02:00
|
|
|
public bool IsEnabled { get => Visible == true; }
|
|
|
|
|
2024-08-19 20:32:19 +02:00
|
|
|
// Called when the node enters the scene tree for the first time.
|
|
|
|
public override void _Ready() {
|
2024-08-20 15:58:22 +02:00
|
|
|
Orbit.Hud = Hud;
|
|
|
|
|
2024-08-19 20:32:19 +02:00
|
|
|
Vector3 SpawnPos = Vector3.Zero;
|
|
|
|
|
|
|
|
if (SpawnPoint != null)
|
|
|
|
SpawnPos = SpawnPoint.GlobalPosition - GlobalPosition;
|
|
|
|
|
|
|
|
SpawnBlocks(SpawnPos);
|
2024-08-20 01:20:52 +02:00
|
|
|
|
|
|
|
Orbit.BlockRelease += OnBlockRelease;
|
2024-08-20 15:16:57 +02:00
|
|
|
Orbit.DraggingHeldBlock += OnBlockDrag;
|
|
|
|
|
|
|
|
Plane.CollisionLayer = PlaneOnlyLayer;
|
|
|
|
Plane.CollisionMask = PlaneOnlyLayer;
|
|
|
|
DisablePlane();
|
2024-08-19 20:32:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void SpawnBlocks(Vector3 position) {
|
|
|
|
var rng = new RandomNumberGenerator();
|
|
|
|
|
|
|
|
var children = TrenchbroomMap.FindChildren("*_buildingblock");
|
|
|
|
foreach (StaticBody3D buildingBlockStaticBody in children.Cast<StaticBody3D>()) {
|
|
|
|
|
|
|
|
var baseBlock = new BuildingBlock.BaseBlock(buildingBlockStaticBody);
|
|
|
|
|
|
|
|
var block = new BuildingBlock() {
|
|
|
|
Base = baseBlock,
|
|
|
|
Material = BlockMaterial,
|
2024-08-19 23:33:24 +02:00
|
|
|
HoverMaterial = BlockHoverMaterial,
|
2024-08-19 20:32:19 +02:00
|
|
|
Position = position + Vector3.One * (rng.Randf() * 0.5f - 0.25f) + Vector3.Up * rng.Randf(),
|
2024-08-20 00:50:55 +02:00
|
|
|
PhysicalModeLayer = BlockMask,
|
2024-08-19 20:32:19 +02:00
|
|
|
RelativeScale = RelativeScale,
|
|
|
|
};
|
|
|
|
|
|
|
|
AddChild(block);
|
2024-08-20 00:50:55 +02:00
|
|
|
|
|
|
|
block.PickUp += OnBlockPickup;
|
2024-08-19 20:32:19 +02:00
|
|
|
}
|
|
|
|
}
|
2024-08-19 22:27:26 +02:00
|
|
|
|
2024-08-19 23:33:24 +02:00
|
|
|
public void Interact(InputEvent _) {
|
|
|
|
Orbit.SetEnabled(true);
|
|
|
|
}
|
|
|
|
|
2024-08-20 01:20:52 +02:00
|
|
|
public override void _Process(double delta) {
|
2024-08-20 15:16:57 +02:00
|
|
|
GhostBlockNormal = Vector3.Up;
|
|
|
|
|
2024-08-20 01:20:52 +02:00
|
|
|
if (GhostBlock != null) {
|
2024-08-20 15:16:57 +02:00
|
|
|
var res = Util.RaycastFromMouse(Orbit.Camera, 0b10100 | PlaneOnlyLayer);
|
2024-08-20 01:20:52 +02:00
|
|
|
if (res is RaycastResult results) {
|
2024-08-20 02:29:32 +02:00
|
|
|
Vector3 LocalPos = results.Position - GlobalPosition;
|
2024-08-20 15:58:22 +02:00
|
|
|
GhostBlockNormal = results.Normal;
|
|
|
|
Vector3 offset = GhostBlock.OffsetFrom(results.Normal, GhostOnlyMask);
|
|
|
|
LocalPos += offset;
|
2024-08-20 02:29:32 +02:00
|
|
|
GhostBlock.Position = LocalPos * Basis;
|
2024-08-20 01:20:52 +02:00
|
|
|
}
|
2024-08-20 02:47:18 +02:00
|
|
|
|
|
|
|
if (Orbit.HeldBlock != null)
|
|
|
|
GhostBlock.Rotation = Orbit.HeldBlock.Rotation;
|
2024-08-20 01:20:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-20 00:50:55 +02:00
|
|
|
public void OnBlockPickup(BuildingBlock block) {
|
|
|
|
Orbit.HoldBlock(block);
|
2024-08-20 01:20:52 +02:00
|
|
|
Vector3 LocalPos = Vector3.Zero;
|
|
|
|
GhostBlock = new BuildingBlock() {
|
|
|
|
Base = block.Base,
|
|
|
|
Material = BlockGhostMaterial,
|
|
|
|
PhysicalModeLayer = 0,
|
2024-08-20 02:29:32 +02:00
|
|
|
NonPhysicalModeLayer = GhostOnlyMask,
|
2024-08-20 01:20:52 +02:00
|
|
|
RelativeScale = RelativeScale,
|
|
|
|
Position = LocalPos,
|
|
|
|
Mode = BuildingBlock.BlockMode.NonPhysical,
|
|
|
|
};
|
|
|
|
AddChild(GhostBlock);
|
2024-08-20 01:28:22 +02:00
|
|
|
|
2024-08-20 01:39:05 +02:00
|
|
|
Hud.InteractionPaused = true;
|
2024-08-20 01:20:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void OnBlockRelease(BuildingBlock block, uint typeUint) {
|
2024-08-20 01:39:05 +02:00
|
|
|
Hud.InteractionPaused = false;
|
|
|
|
BlockReleaseType type = (BlockReleaseType)typeUint;
|
2024-08-20 01:28:22 +02:00
|
|
|
|
2024-08-20 15:16:57 +02:00
|
|
|
DisablePlane();
|
2024-08-20 01:39:05 +02:00
|
|
|
block.Reparent(this);
|
2024-08-20 01:20:52 +02:00
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case BlockReleaseType.Throw: {
|
|
|
|
block.SetMode(BuildingBlock.BlockMode.Physical);
|
|
|
|
var normal = Orbit.Camera.ProjectRayNormal(Orbit.Camera.GetViewport().GetMousePosition());
|
|
|
|
var direction = normal * 10;
|
|
|
|
|
|
|
|
var res = Util.RaycastFromMouse(Orbit.Camera, 0b1111);
|
|
|
|
if (res is RaycastResult results) {
|
|
|
|
direction = (results.Position - block.GlobalPosition + Vector3.Up * 0.5f) * 3;
|
|
|
|
}
|
|
|
|
block.ApplyImpulse(direction);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case BlockReleaseType.Place: {
|
2024-08-20 01:39:05 +02:00
|
|
|
block.SetMode(BuildingBlock.BlockMode.Placed);
|
|
|
|
block.Transform = GhostBlock.Transform;
|
2024-08-20 01:20:52 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: break;
|
|
|
|
}
|
2024-08-20 01:39:05 +02:00
|
|
|
|
|
|
|
if (GhostBlock != null) {
|
|
|
|
GhostBlock.QueueFree();
|
|
|
|
GhostBlock = null;
|
|
|
|
}
|
2024-08-20 00:50:55 +02:00
|
|
|
}
|
|
|
|
|
2024-08-20 15:16:57 +02:00
|
|
|
private void OnBlockDrag(BuildingBlock _) {
|
|
|
|
var offset = GhostBlock.OffsetFrom(GhostBlockNormal);
|
|
|
|
EnablePlane(GhostBlock.Position - offset, new Quaternion(Vector3.Up, GhostBlockNormal));
|
|
|
|
}
|
|
|
|
|
|
|
|
private void EnablePlane(Vector3 pos, Quaternion rot) {
|
|
|
|
Plane.Visible = true;
|
|
|
|
Plane.ProcessMode = ProcessModeEnum.Pausable;
|
|
|
|
Plane.Position = pos;
|
|
|
|
Plane.Quaternion = rot;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void DisablePlane() {
|
|
|
|
Plane.Visible = false;
|
|
|
|
Plane.ProcessMode = ProcessModeEnum.Disabled;
|
|
|
|
}
|
2024-08-20 16:17:44 +02:00
|
|
|
|
|
|
|
public void DisableTable() {
|
|
|
|
Visible = false;
|
|
|
|
ProcessMode = ProcessModeEnum.Disabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SpawnTable(Vector3 position, Vector3 lookAt) {
|
|
|
|
if (IsEnabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Visible = true;
|
|
|
|
ProcessMode = ProcessModeEnum.Pausable;
|
|
|
|
Position = position;
|
|
|
|
lookAt.Y = 0;
|
|
|
|
LookAt(lookAt);
|
|
|
|
Rotate(Vector3.Up, (float)Math.PI / 2);
|
|
|
|
}
|
2024-08-19 20:32:19 +02:00
|
|
|
}
|
2024-08-19 23:33:24 +02:00
|
|
|
}
|