diff --git a/project.godot b/project.godot index 05a9202d..fd4110b3 100644 --- a/project.godot +++ b/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="GameJamDungeon" -run/main_scene="uid://bc1sp6xwe0j65" +run/main_scene="uid://d1gjaijijd5ot" run/print_header=false config/features=PackedStringArray("4.4", "C#", "GL Compatibility") boot_splash/show_image=false diff --git a/src/enemy/Enemy.cs b/src/enemy/Enemy.cs index 7803bfb8..33623020 100644 --- a/src/enemy/Enemy.cs +++ b/src/enemy/Enemy.cs @@ -165,7 +165,13 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide public void StopAttackTimer() { _attackTimer.Timeout -= OnAttackTimeout; + } + public Vector3 EnemyGlobalPosition => GlobalPosition; + + public void SetEnemyGlobalPosition(Vector3 target) + { + GlobalPosition = target; } private void OnAttackTimeout() diff --git a/src/enemy/IEnemy.cs b/src/enemy/IEnemy.cs index 82e7e841..eed74c30 100644 --- a/src/enemy/IEnemy.cs +++ b/src/enemy/IEnemy.cs @@ -19,4 +19,6 @@ public interface IEnemy : IKillable public void StopAttackTimer(); public abstract void SetTarget(Vector3 target); + + public void SetEnemyGlobalPosition(Vector3 target); } diff --git a/src/enemy/enemy_types/07. chinthe/ChinteModelView.tscn b/src/enemy/enemy_types/07. chinthe/ChinteModelView.tscn index 82f9516f..eb592bc9 100644 --- a/src/enemy/enemy_types/07. chinthe/ChinteModelView.tscn +++ b/src/enemy/enemy_types/07. chinthe/ChinteModelView.tscn @@ -1054,6 +1054,36 @@ tracks/3/keys = { "values": [false, true, false] } +[sub_resource type="Animation" id="Animation_hr7xb"] +resource_name = "idle_left" +length = 0.0833417 +loop_mode = 1 +step = 0.0833333 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:animation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [&"idle_left"] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:frame") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [0] +} + [sub_resource type="Animation" id="Animation_sodds"] resource_name = "idle_left_walk" length = 1.41668 @@ -1276,36 +1306,6 @@ tracks/1/keys = { "values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] } -[sub_resource type="Animation" id="Animation_hr7xb"] -resource_name = "idle_left" -length = 0.0833417 -loop_mode = 1 -step = 0.0833333 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:animation") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 1, -"values": [&"idle_left"] -} -tracks/1/type = "value" -tracks/1/imported = false -tracks/1/enabled = true -tracks/1/path = NodePath("Sprite3D/SubViewportContainer/SubViewport/AnimatedSprite:frame") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 1, -"values": [0] -} - [sub_resource type="AnimationLibrary" id="AnimationLibrary_46p8q"] _data = { &"RESET": SubResource("Animation_46p8q"), diff --git a/src/game/Game.cs b/src/game/Game.cs index cacb9ab0..43a837fe 100644 --- a/src/game/Game.cs +++ b/src/game/Game.cs @@ -5,6 +5,7 @@ using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; using System; +using System.Collections.Immutable; [Meta(typeof(IAutoNode))] public partial class Game : Node3D, IGame @@ -179,6 +180,8 @@ public partial class Game : Node3D, IGame InGameUI.PlayerInfoUI.DisplayMessage(message); } + public IDungeonFloor CurrentFloor => Map.CurrentFloor; + private void OnEnemyDefeated(Vector3 vector, EnemyStatResource resource) { Player.GainExp(resource.ExpFromDefeat * GameRepo.EXPRate); diff --git a/src/game/IGame.cs b/src/game/IGame.cs index ad305415..7e752b26 100644 --- a/src/game/IGame.cs +++ b/src/game/IGame.cs @@ -11,6 +11,8 @@ public interface IGame : IProvide, IProvide, IProvid public RescuedItemDatabase RescuedItems { get; } + public IDungeonFloor CurrentFloor { get; } + public void DropItem(IInventoryItem item); public void ThrowItem(IInventoryItem item); diff --git a/src/items/throwable/ThrowableItem.cs b/src/items/throwable/ThrowableItem.cs index 34658bb7..eb311cf1 100644 --- a/src/items/throwable/ThrowableItem.cs +++ b/src/items/throwable/ThrowableItem.cs @@ -3,6 +3,7 @@ using Chickensoft.Introspection; using Godot; using System; using System.Collections.Immutable; +using System.Linq; namespace GameJamDungeon; @@ -74,6 +75,33 @@ public partial class ThrowableItem : Node3D, IUsableItem ChangeAffinity(); } + public void TeleportToRandomRoom(IEnemy enemy) + { + var currentFloor = Game.CurrentFloor; + var rooms = currentFloor.Rooms; + + var rng = new RandomNumberGenerator(); + rng.Randomize(); + var randomRoom = rooms[rng.RandiRange(0, rooms.Count - 1)]; + var spawnPoints = randomRoom.EnemySpawnPoints.GetChildren().OfType().ToList(); + + var randomSpawnPoint = spawnPoints[rng.RandiRange(0, spawnPoints.Count - 1)]; + + enemy.SetEnemyGlobalPosition(randomSpawnPoint.GlobalPosition); + } + + public void TeleportToRandomRoom(IPlayer player) + { + var currentFloor = Game.CurrentFloor; + var rooms = currentFloor.Rooms; + + var rng = new RandomNumberGenerator(); + rng.Randomize(); + var randomRoom = rooms[rng.RandiRange(0, rooms.Count - 1)]; + var spawnPoint = randomRoom.PlayerSpawn; + player.TeleportPlayer(spawnPoint.GlobalPosition); + } + private void ChangeAffinity() { var maximumElements = Enum.GetNames(typeof(ElementType)).Length; diff --git a/src/items/throwable/ThrowableItemTag.cs b/src/items/throwable/ThrowableItemTag.cs index 559af4f3..03454b74 100644 --- a/src/items/throwable/ThrowableItemTag.cs +++ b/src/items/throwable/ThrowableItemTag.cs @@ -3,7 +3,8 @@ public enum ThrowableItemTag { LowerTargetTo1HP, - CanChangeAffinity + CanChangeAffinity, + TeleportToRandomLocation } public enum UsableItemTag diff --git a/src/items/throwable/resources/Gospel of Dimension.tres b/src/items/throwable/resources/Gospel of Dimension.tres new file mode 100644 index 00000000..51ce6ae7 --- /dev/null +++ b/src/items/throwable/resources/Gospel of Dimension.tres @@ -0,0 +1,19 @@ +[gd_resource type="Resource" script_class="ThrowableItemStats" load_steps=3 format=3 uid="uid://lo37qfyxlhx1"] + +[ext_resource type="Texture2D" uid="uid://cagebvc1lp28y" path="res://src/items/throwable/textures/tablet.PNG" id="1_xt2mp"] +[ext_resource type="Script" uid="uid://d3wlunkcuv2w2" path="res://src/items/throwable/ThrowableItemStats.cs" id="2_m680r"] + +[resource] +script = ExtResource("2_m680r") +ThrowableItemTags = Array[int]([2]) +ElementType = 0 +UsableItemTags = Array[int]([]) +Name = "Gospel of Dimension" +Description = "Teleports target to a random location." +Texture = ExtResource("1_xt2mp") +SpawnRate = 0.1 +ThrowSpeed = 20.0 +HealHPAmount = 0 +HealVTAmount = 0 +ThrowDamage = 20 +ItemTags = Array[int]([]) diff --git a/src/items/throwable/textures/tablet.PNG b/src/items/throwable/textures/tablet.PNG new file mode 100644 index 00000000..970df9f4 Binary files /dev/null and b/src/items/throwable/textures/tablet.PNG differ diff --git a/src/items/throwable/textures/tablet.PNG.import b/src/items/throwable/textures/tablet.PNG.import new file mode 100644 index 00000000..dc3f7a06 --- /dev/null +++ b/src/items/throwable/textures/tablet.PNG.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cagebvc1lp28y" +path="res://.godot/imported/tablet.PNG-95771620877422607611342ad4de8709.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://src/items/throwable/textures/tablet.PNG" +dest_files=["res://.godot/imported/tablet.PNG-95771620877422607611342ad4de8709.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 diff --git a/src/items/thrown/ThrownItem.cs b/src/items/thrown/ThrownItem.cs index b6ddbf40..730009c1 100644 --- a/src/items/thrown/ThrownItem.cs +++ b/src/items/thrown/ThrownItem.cs @@ -1,6 +1,7 @@ using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; +using System.Linq; namespace GameJamDungeon; @@ -39,8 +40,20 @@ public partial class ThrownItem : RigidBody3D { if (ItemThatIsThrown is ThrowableItem throwableItem) { + switch (throwableItem.ThrowableItemTags.Single()) + { + case ThrowableItemTag.LowerTargetTo1HP: + enemy.TakeDamage(enemy.CurrentHP - 1, ignoreDefense: true, ignoreElementalResistance: true); + break; + case ThrowableItemTag.TeleportToRandomLocation: + throwableItem.TeleportToRandomRoom(enemy); + break; + } if (throwableItem.ThrowableItemTags.Contains(ThrowableItemTag.LowerTargetTo1HP)) enemy.TakeDamage(enemy.CurrentHP - 1, ignoreDefense: true, ignoreElementalResistance: true); + else if (throwableItem.ThrowableItemTags.Contains(ThrowableItemTag.TeleportToRandomLocation)) + //enemy teleport + return; else enemy.TakeDamage(throwableItem.ThrowDamage, throwableItem.ElementType); } diff --git a/src/map/Map.cs b/src/map/Map.cs index f8f30757..308b85a3 100644 --- a/src/map/Map.cs +++ b/src/map/Map.cs @@ -10,6 +10,8 @@ public interface IMap : INode3D { public Godot.Collections.Array Floors { get; } + public IDungeonFloor CurrentFloor { get; } + public void SpawnNextFloor(); public Transform3D GetPlayerSpawnPosition(); @@ -27,7 +29,7 @@ public partial class Map : Node3D, IMap [Export] public Godot.Collections.Array Floors { get; set; } = default!; - private IDungeonFloor _currentFloor; + public IDungeonFloor CurrentFloor { get; private set; } public void Setup() { @@ -36,14 +38,14 @@ public partial class Map : Node3D, IMap public void SpawnNextFloor() { - var oldFloor = _currentFloor; + var oldFloor = CurrentFloor; oldFloor.CallDeferred(MethodName.QueueFree, []); LoadFloor(); - _currentFloor.InitializeDungeon(); + CurrentFloor.InitializeDungeon(); Game.NextFloorLoaded(); } - public Transform3D GetPlayerSpawnPosition() => _currentFloor.GetPlayerSpawnPoint(); + public Transform3D GetPlayerSpawnPosition() => CurrentFloor.GetPlayerSpawnPoint(); private void LoadFloor() { @@ -51,7 +53,7 @@ public partial class Map : Node3D, IMap var instantiator = new Instantiator(GetTree()); var loadedScene = instantiator.LoadAndInstantiate(currentFloorScene.ResourcePath); AddChild(loadedScene); - _currentFloor = (IDungeonFloor)loadedScene; + CurrentFloor = (IDungeonFloor)loadedScene; Floors.Remove(currentFloorScene); } } diff --git a/src/map/dungeon/code/BossFloor.cs b/src/map/dungeon/code/BossFloor.cs index 0ca2858e..9d2a5c54 100644 --- a/src/map/dungeon/code/BossFloor.cs +++ b/src/map/dungeon/code/BossFloor.cs @@ -1,6 +1,7 @@ using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; +using System.Collections.Immutable; namespace GameJamDungeon; @@ -11,6 +12,8 @@ public partial class BossFloor : Node3D, IDungeonFloor private BossRoomA BossRoom; + public ImmutableList Rooms => []; + public void InitializeDungeon() { var bossRoomScene = GD.Load($"res://src/map/dungeon/scenes/BossRoom.tscn"); diff --git a/src/map/dungeon/code/DungeonFloor.cs b/src/map/dungeon/code/DungeonFloor.cs index d7110b1d..42553193 100644 --- a/src/map/dungeon/code/DungeonFloor.cs +++ b/src/map/dungeon/code/DungeonFloor.cs @@ -2,6 +2,7 @@ using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; namespace GameJamDungeon @@ -17,7 +18,7 @@ namespace GameJamDungeon private Transform3D _playerSpawnPoint; - internal List Rooms { get; private set; } + public ImmutableList Rooms { get; private set; } public void InitializeDungeon() { @@ -43,7 +44,7 @@ namespace GameJamDungeon return result.GlobalTransform; } - private static List FindAllDungeonRooms(List nodesToSearch, List roomsFound) + private static ImmutableList FindAllDungeonRooms(List nodesToSearch, ImmutableList roomsFound) { if (nodesToSearch.Count == 0) return roomsFound; @@ -51,7 +52,7 @@ namespace GameJamDungeon foreach (var node in nodesToSearch) { if (node is MonsterRoom dungeonRoom) - roomsFound.Add(dungeonRoom); + roomsFound = roomsFound.Add(dungeonRoom); if (node.HasSignal("dungeon_done_generating")) node.EmitSignal("dungeon_done_generating"); diff --git a/src/map/dungeon/code/Floor0.cs b/src/map/dungeon/code/Floor0.cs index d4770f87..edec826c 100644 --- a/src/map/dungeon/code/Floor0.cs +++ b/src/map/dungeon/code/Floor0.cs @@ -1,6 +1,7 @@ using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; +using System.Collections.Immutable; namespace GameJamDungeon; @@ -15,6 +16,8 @@ public partial class Floor0 : Node3D, IDungeonFloor, IExitRoom [Node] private Marker3D PlayerSpawnPoint { get; set; } = default!; + public ImmutableList Rooms => []; + public void Setup() { Show(); diff --git a/src/map/dungeon/code/IDungeonFloor.cs b/src/map/dungeon/code/IDungeonFloor.cs index dd877c3e..eb2e23e8 100644 --- a/src/map/dungeon/code/IDungeonFloor.cs +++ b/src/map/dungeon/code/IDungeonFloor.cs @@ -1,5 +1,6 @@ using Chickensoft.GodotNodeInterfaces; using Godot; +using System.Collections.Immutable; namespace GameJamDungeon; public interface IDungeonFloor : INode3D @@ -7,4 +8,6 @@ public interface IDungeonFloor : INode3D void InitializeDungeon(); public Transform3D GetPlayerSpawnPoint(); + + public ImmutableList Rooms { get; } } diff --git a/src/map/dungeon/code/Overworld.cs b/src/map/dungeon/code/Overworld.cs index ef289cb5..72c11b7a 100644 --- a/src/map/dungeon/code/Overworld.cs +++ b/src/map/dungeon/code/Overworld.cs @@ -1,6 +1,7 @@ using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; +using System.Collections.Immutable; namespace GameJamDungeon; [Meta(typeof(IAutoNode))] @@ -12,6 +13,8 @@ public partial class Overworld : Node3D, IDungeonFloor [Node] public Marker3D ExitSpawnPoint { get; set; } = default!; + public ImmutableList Rooms => []; + public void InitializeDungeon() { Show(); diff --git a/src/map/dungeon/floors/Floor00.tscn b/src/map/dungeon/floors/Floor00.tscn index f9eff1dc..fe809927 100644 --- a/src/map/dungeon/floors/Floor00.tscn +++ b/src/map/dungeon/floors/Floor00.tscn @@ -16,7 +16,7 @@ [ext_resource type="Texture2D" uid="uid://4k6vtn4oip5f" path="res://src/map/dungeon/models/Set A/02. Altar/02_ALTAR_FLOOR_ZER0_VER_TILE4.png" id="14_qqc7i"] [ext_resource type="Texture2D" uid="uid://cururtxtgylxf" path="res://src/map/dungeon/models/Set A/02. Altar/02_ALTAR_FLOOR_ZER0_VER_COLUMN.jpg" id="15_ojbcg"] [ext_resource type="PackedScene" uid="uid://1fl6s352e2ej" path="res://src/items/throwable/ThrowableItem.tscn" id="16_db2o3"] -[ext_resource type="Resource" uid="uid://bph8c6by4s047" path="res://src/items/throwable/resources/GeomanticDice.tres" id="17_ntxe5"] +[ext_resource type="Resource" uid="uid://lo37qfyxlhx1" path="res://src/items/throwable/resources/Gospel of Dimension.tres" id="17_db2o3"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_3ubi4"] shading_mode = 0 @@ -856,7 +856,7 @@ shape = SubResource("BoxShape3D_xh2ej") [node name="ThrowableItem" parent="." instance=ExtResource("16_db2o3")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.469, -2.5, 0) -_throwableItemStats = ExtResource("17_ntxe5") +_throwableItemStats = ExtResource("17_db2o3") [node name="CSGBox3D" type="CSGBox3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2.22379, 0) diff --git a/src/map/dungeon/floors/Floor01.tscn b/src/map/dungeon/floors/Floor01.tscn index c6e74b9a..044476a3 100644 --- a/src/map/dungeon/floors/Floor01.tscn +++ b/src/map/dungeon/floors/Floor01.tscn @@ -1,12 +1,9 @@ -[gd_scene load_steps=15 format=3 uid="uid://bc1sp6xwe0j65"] +[gd_scene load_steps=12 format=3 uid="uid://bc1sp6xwe0j65"] [ext_resource type="Script" uid="uid://dwt6302nsf4vq" path="res://src/map/dungeon/code/DungeonFloor.cs" id="1_0ecnn"] [ext_resource type="Script" uid="uid://b1x125h0tya2w" path="res://addons/SimpleDungeons/DungeonGenerator3D.gd" id="2_cxmwa"] [ext_resource type="PackedScene" uid="uid://dpec2lbt83dhe" path="res://src/map/dungeon/rooms/Set A/03. Antechamber A.tscn" id="3_gkkr3"] [ext_resource type="PackedScene" uid="uid://b82dx66mgs2d7" path="res://src/map/dungeon/rooms/Set A/08. Basin Room.tscn" id="8_5rblf"] -[ext_resource type="PackedScene" uid="uid://cmvimr0pvsgqy" path="res://src/enemy/enemy_types/10. Eden Pillar/Eden Pillar.tscn" id="10_atq1f"] -[ext_resource type="PackedScene" uid="uid://cfecvvav8kkp6" path="res://src/player/Player.tscn" id="11_sdyti"] -[ext_resource type="PackedScene" uid="uid://c6tqt27ql8s35" path="res://src/enemy/enemy_types/07. chinthe/Chinthe.tscn" id="12_1l8yt"] [ext_resource type="PackedScene" uid="uid://dbvr8ewajja6a" path="res://src/enemy/EnemyDatabase.tscn" id="12_aw26s"] [ext_resource type="PackedScene" uid="uid://cihbmyo0ltq4m" path="res://src/map/dungeon/rooms/Set A/19. Floor Exit A.tscn" id="12_n02rw"] [ext_resource type="PackedScene" uid="uid://bksq62muhk3h5" path="res://src/enemy/enemy_types/01. sproingy/Sproingy.tscn" id="13_kwaga"] @@ -175,16 +172,3 @@ shape = SubResource("BoxShape3D_xw4dv") [node name="EnemyDatabase" parent="." instance=ExtResource("12_aw26s")] unique_name_in_owner = true EnemyList = Array[PackedScene]([ExtResource("13_kwaga"), ExtResource("14_gkkr3")]) - -[node name="Eden Pillar" parent="." instance=ExtResource("10_atq1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -29.7976, -1.33866, 30.3232) - -[node name="Player" parent="." instance=ExtResource("11_sdyti")] -unique_name_in_owner = true -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.07588, -1.71359, 12.7507) - -[node name="Chinthe" parent="." instance=ExtResource("12_1l8yt")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.2934, -0.81355, 21.6535) -PrimaryAttackElementalType = 0 -PrimaryAttackElementalDamageBonus = 1.0 -_movementSpeed = 2.0