Add more NPCs, update dialogue manager to 4.4 compatible version
@@ -1,3 +1,11 @@
|
||||
~ start
|
||||
~ general
|
||||
Hi...
|
||||
=> END
|
||||
|
||||
~ introduction
|
||||
I haven't had a script added yet.
|
||||
=> END
|
||||
|
||||
~ hit
|
||||
Yep, hitting me does work though.
|
||||
=> END
|
||||
@@ -1,6 +1,6 @@
|
||||
[remap]
|
||||
|
||||
importer="dialogue_manager_compiler_12"
|
||||
importer="dialogue_manager_compiler_14"
|
||||
type="Resource"
|
||||
uid="uid://lao0opxww3ib"
|
||||
path="res://.godot/imported/Dialogue.dialogue-176033575bc12c347010f3a30b2e302a.tres"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
|
||||
@@ -31,105 +31,105 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
AnimationTree.AnimationFinished += AnimationTree_AnimationFinished;
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Start(IDLE_FORWARD);
|
||||
AnimationTree.AnimationFinished += AnimationTree_AnimationFinished;
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Start(IDLE_FORWARD);
|
||||
}
|
||||
|
||||
public void PlayPrimaryAttackAnimation()
|
||||
{
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_ATTACK);
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_ATTACK);
|
||||
}
|
||||
|
||||
public void PlaySecondaryAttackAnimation()
|
||||
{
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(SECONDARY_ATTACK);
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(SECONDARY_ATTACK);
|
||||
}
|
||||
|
||||
public void PlayPrimarySkillAnimation()
|
||||
{
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_SKILL);
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_SKILL);
|
||||
}
|
||||
|
||||
public void PlayHitAnimation()
|
||||
{
|
||||
LoadShader("res://src/vfx/shaders/DamageHit.gdshader");
|
||||
var tweener = GetTree().CreateTween();
|
||||
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 1.0f, 1.0f);
|
||||
LoadShader("res://src/vfx/shaders/DamageHit.gdshader");
|
||||
var tweener = GetTree().CreateTween();
|
||||
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
public void PlayDeathAnimation()
|
||||
{
|
||||
LoadShader("res://src/vfx/shaders/PixelMelt.gdshader");
|
||||
var tweener = GetTree().CreateTween();
|
||||
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 1.0f, 0.8f);
|
||||
tweener.TweenCallback(Callable.From(QueueFree));
|
||||
LoadShader("res://src/vfx/shaders/PixelMelt.gdshader");
|
||||
var tweener = GetTree().CreateTween();
|
||||
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 1.0f, 0.8f);
|
||||
tweener.TweenCallback(Callable.From(QueueFree));
|
||||
}
|
||||
|
||||
public void RotateModel(Basis enemyBasis, Vector3 cameraDirection, bool isWalking) => RotateModel(enemyBasis, cameraDirection, 0.55f, 0.45f, isWalking);
|
||||
|
||||
public virtual void RotateModel(
|
||||
Basis enemyBasis,
|
||||
Vector3 cameraDirection,
|
||||
float rotateUpperThreshold,
|
||||
float rotateLowerThreshold,
|
||||
bool isWalking)
|
||||
Basis enemyBasis,
|
||||
Vector3 cameraDirection,
|
||||
float rotateUpperThreshold,
|
||||
float rotateLowerThreshold,
|
||||
bool isWalking)
|
||||
{
|
||||
var enemyForwardDirection = enemyBasis.Z;
|
||||
var enemyLeftDirection = enemyBasis.X;
|
||||
var enemyForwardDirection = enemyBasis.Z;
|
||||
var enemyLeftDirection = enemyBasis.X;
|
||||
|
||||
var leftDotProduct = enemyLeftDirection.Dot(cameraDirection);
|
||||
var forwardDotProduct = enemyForwardDirection.Dot(cameraDirection);
|
||||
var leftDotProduct = enemyLeftDirection.Dot(cameraDirection);
|
||||
var forwardDotProduct = enemyForwardDirection.Dot(cameraDirection);
|
||||
|
||||
// Check if forward facing. If the dot product is -1, the enemy is facing the camera.
|
||||
if (forwardDotProduct < -rotateUpperThreshold)
|
||||
{
|
||||
if (isWalking)
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_FORWARD_WALK);
|
||||
else
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_FORWARD);
|
||||
}
|
||||
// Check if backward facing. If the dot product is 1, the enemy is facing the same direction as the camera.
|
||||
else if (forwardDotProduct > rotateUpperThreshold)
|
||||
{
|
||||
if (isWalking)
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_BACK_WALK);
|
||||
else
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_BACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the dot product of the perpendicular direction is positive (up to 1), the enemy is facing to the left (since it's mirrored).
|
||||
AnimatedSprite.FlipH = leftDotProduct > 0;
|
||||
// Check if side facing. If the dot product is close to zero in the positive or negative direction, its close to the threshold for turning.
|
||||
if (Mathf.Abs(forwardDotProduct) < rotateLowerThreshold)
|
||||
{
|
||||
if (isWalking)
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_LEFT_WALK);
|
||||
else
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_LEFT);
|
||||
}
|
||||
}
|
||||
// Check if forward facing. If the dot product is -1, the enemy is facing the camera.
|
||||
if (forwardDotProduct < -rotateUpperThreshold)
|
||||
{
|
||||
if (isWalking)
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_FORWARD_WALK);
|
||||
else
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_FORWARD);
|
||||
}
|
||||
// Check if backward facing. If the dot product is 1, the enemy is facing the same direction as the camera.
|
||||
else if (forwardDotProduct > rotateUpperThreshold)
|
||||
{
|
||||
if (isWalking)
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_BACK_WALK);
|
||||
else
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_BACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the dot product of the perpendicular direction is positive (up to 1), the enemy is facing to the left (since it's mirrored).
|
||||
AnimatedSprite.FlipH = leftDotProduct > 0;
|
||||
// Check if side facing. If the dot product is close to zero in the positive or negative direction, its close to the threshold for turning.
|
||||
if (Mathf.Abs(forwardDotProduct) < rotateLowerThreshold)
|
||||
{
|
||||
if (isWalking)
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_LEFT_WALK);
|
||||
else
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadShader(string shaderPath)
|
||||
{
|
||||
var shader = GD.Load<Shader>(shaderPath);
|
||||
AnimatedSprite.Material = new ShaderMaterial();
|
||||
var shaderMaterial = (ShaderMaterial)AnimatedSprite.Material;
|
||||
shaderMaterial.Shader = shader;
|
||||
var shader = GD.Load<Shader>(shaderPath);
|
||||
AnimatedSprite.Material = new ShaderMaterial();
|
||||
var shaderMaterial = (ShaderMaterial)AnimatedSprite.Material;
|
||||
shaderMaterial.Shader = shader;
|
||||
}
|
||||
|
||||
private void AnimationTree_AnimationFinished(StringName animName)
|
||||
{
|
||||
if (animName == PRIMARY_ATTACK || animName == SECONDARY_ATTACK || animName == PRIMARY_SKILL)
|
||||
{
|
||||
AnimationTree.Get("parameters/playback").As<AnimationNodeStateMachinePlayback>().Travel(IDLE_FORWARD);
|
||||
}
|
||||
if (animName == PRIMARY_ATTACK || animName == SECONDARY_ATTACK || animName == PRIMARY_SKILL)
|
||||
{
|
||||
AnimationTree.Get("parameters/playback").As<AnimationNodeStateMachinePlayback>().Travel(IDLE_FORWARD);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetShaderValue(float shaderValue)
|
||||
{
|
||||
var shaderMaterial = (ShaderMaterial)AnimatedSprite.Material;
|
||||
shaderMaterial.SetShaderParameter("progress", shaderValue);
|
||||
var shaderMaterial = (ShaderMaterial)AnimatedSprite.Material;
|
||||
shaderMaterial.SetShaderParameter("progress", shaderValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,46 +23,46 @@ public partial class Ballos : Enemy, IHasPrimaryAttack, IHasSecondaryAttack
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
SetPhysicsProcess(true);
|
||||
((EnemyModelView2D)_enemyModelView).Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
SetPhysicsProcess(true);
|
||||
((EnemyModelView2D)_enemyModelView).Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
}
|
||||
|
||||
public void OnPhysicsProcess(double delta)
|
||||
{
|
||||
_enemyLogic.Input(new EnemyLogic.Input.PhysicsTick(delta));
|
||||
_enemyLogic.Input(new EnemyLogic.Input.PhysicsTick(delta));
|
||||
|
||||
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer && GlobalPosition.DistanceTo(_player.CurrentPosition) < 2.5f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.StartAttacking());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer && GlobalPosition.DistanceTo(_player.CurrentPosition) > 45f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.LostPlayer());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.Attacking && GlobalPosition.DistanceTo(_player.CurrentPosition) > 2.5f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer && GlobalPosition.DistanceTo(_player.CurrentPosition) < 2.5f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.StartAttacking());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer && GlobalPosition.DistanceTo(_player.CurrentPosition) > 45f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.LostPlayer());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.Attacking && GlobalPosition.DistanceTo(_player.CurrentPosition) > 2.5f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||
}
|
||||
|
||||
public override void TakeAction()
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
var options = new List<Action>() { PrimaryAttack, SecondaryAttack };
|
||||
var selection = rng.RandWeighted([0.875f, 0.125f]);
|
||||
options[(int)selection].Invoke();
|
||||
var rng = new RandomNumberGenerator();
|
||||
var options = new List<Action>() { PrimaryAttack, SecondaryAttack };
|
||||
var selection = rng.RandWeighted([0.875f, 0.125f]);
|
||||
options[(int)selection].Invoke();
|
||||
}
|
||||
public void PrimaryAttack()
|
||||
{
|
||||
_enemyModelView.PlayPrimaryAttackAnimation();
|
||||
_enemyModelView.PlayPrimaryAttackAnimation();
|
||||
}
|
||||
|
||||
public void SecondaryAttack()
|
||||
{
|
||||
_enemyModelView.PlaySecondaryAttackAnimation();
|
||||
_enemyModelView.PlaySecondaryAttackAnimation();
|
||||
}
|
||||
|
||||
private void Hitbox_AreaEntered(Area3D area)
|
||||
{
|
||||
var target = area.GetOwner();
|
||||
if (target is IPlayer player)
|
||||
{
|
||||
var damage = _enemyStatResource.CurrentAttack * PrimaryAttackElementalDamageBonus;
|
||||
player.TakeDamage(damage, PrimaryAttackElementalType, BattleExtensions.IsCriticalHit(_enemyStatResource.Luck));
|
||||
}
|
||||
var target = area.GetOwner();
|
||||
if (target is IPlayer player)
|
||||
{
|
||||
var damage = _enemyStatResource.CurrentAttack * PrimaryAttackElementalDamageBonus;
|
||||
player.TakeDamage(damage, PrimaryAttackElementalType, BattleExtensions.IsCriticalHit(_enemyStatResource.Luck));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,27 @@
|
||||
[gd_scene load_steps=6 format=3 uid="uid://feegakykn3fv"]
|
||||
[gd_scene load_steps=8 format=3 uid="uid://feegakykn3fv"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dwfxs5yrf7i3v" path="res://src/enemy/enemy_types/05. ballos/Ballos.cs" id="1_v2urn"]
|
||||
[ext_resource type="Script" uid="uid://dnkmr0eq1sij0" path="res://src/enemy/EnemyStatResource.cs" id="2_iy2fp"]
|
||||
[ext_resource type="PackedScene" uid="uid://c5xijwxkg4pf6" path="res://src/enemy/enemy_types/05. ballos/BallosModelView.tscn" id="2_v2urn"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_ko6aj"]
|
||||
script = ExtResource("2_iy2fp")
|
||||
CurrentHP = 100.0
|
||||
MaximumHP = 100
|
||||
CurrentAttack = 20
|
||||
CurrentDefense = 12
|
||||
MaxAttack = 20
|
||||
MaxDefense = 12
|
||||
ExpFromDefeat = 50
|
||||
Luck = 0.05
|
||||
TelluricResistance = 0.0
|
||||
AeolicResistance = 0.0
|
||||
HydricResistance = 0.0
|
||||
IgneousResistance = 0.0
|
||||
FerrumResistance = 0.0
|
||||
DropsSoulGemChance = 0.75
|
||||
metadata/_custom_type_script = "uid://dnkmr0eq1sij0"
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_cwfph"]
|
||||
radius = 0.717471
|
||||
height = 2.02807
|
||||
@@ -16,12 +35,12 @@ radius = 1.20703
|
||||
|
||||
[node name="Ballos" type="CharacterBody3D"]
|
||||
process_mode = 1
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0)
|
||||
collision_layer = 10
|
||||
collision_mask = 11
|
||||
axis_lock_linear_y = true
|
||||
axis_lock_angular_x = true
|
||||
script = ExtResource("1_v2urn")
|
||||
_enemyStatResource = SubResource("Resource_ko6aj")
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape3D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
|
||||
@@ -796,6 +796,7 @@ size = Vector2i(400, 400)
|
||||
render_target_update_mode = 4
|
||||
|
||||
[node name="AnimatedSprite" type="AnimatedSprite2D" parent="Sprite3D/SubViewportContainer/SubViewport"]
|
||||
unique_name_in_owner = true
|
||||
sprite_frames = SubResource("SpriteFrames_mlptn")
|
||||
animation = &"idle_front_walk"
|
||||
offset = Vector2(200, 200)
|
||||
|
||||
@@ -13,18 +13,18 @@ public partial class DialogueController : Node
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
DialogueBalloon = GD.Load<PackedScene>("res://src/ui/dialogue/DialogueBalloon.tscn");
|
||||
DialogueBalloon = GD.Load<PackedScene>("res://src/ui/dialogue/DialogueBalloon.tscn");
|
||||
}
|
||||
|
||||
public static void ShowDialogue(Resource dialogueResource, string dialogueTitle)
|
||||
{
|
||||
Interrupt();
|
||||
_currentlyActiveDialogue = DialogueManager.ShowDialogueBalloonScene(DialogueBalloon, dialogueResource, dialogueTitle);
|
||||
Interrupt();
|
||||
_currentlyActiveDialogue = DialogueManager.ShowDialogueBalloonScene(DialogueBalloon, dialogueResource, dialogueTitle);
|
||||
}
|
||||
|
||||
public static void Interrupt()
|
||||
{
|
||||
if (IsInstanceValid(_currentlyActiveDialogue))
|
||||
_currentlyActiveDialogue.QueueFree();
|
||||
if (IsInstanceValid(_currentlyActiveDialogue))
|
||||
_currentlyActiveDialogue.QueueFree();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,201 +79,201 @@ public partial class Game : Node3D, IGame
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
_container = new SimpleInjector.Container();
|
||||
Module.Bootstrap(_container);
|
||||
_container.Verify();
|
||||
_container = new SimpleInjector.Container();
|
||||
Module.Bootstrap(_container);
|
||||
_container.Verify();
|
||||
|
||||
GameRepo = _container.GetInstance<IGameRepo>();
|
||||
GameLogic = _container.GetInstance<IGameLogic>();
|
||||
GameEventDepot = new GameEventDepot();
|
||||
GameLogic.Set(GameRepo);
|
||||
GameLogic.Set(AppRepo);
|
||||
GameLogic.Set(GameEventDepot);
|
||||
GameLogic.Set(Player);
|
||||
GameLogic.Set(Map);
|
||||
GameLogic.Set(InGameUI);
|
||||
Instantiator = new Instantiator(GetTree());
|
||||
RescuedItems = new RescuedItemDatabase();
|
||||
GameRepo = _container.GetInstance<IGameRepo>();
|
||||
GameLogic = _container.GetInstance<IGameLogic>();
|
||||
GameEventDepot = new GameEventDepot();
|
||||
GameLogic.Set(GameRepo);
|
||||
GameLogic.Set(AppRepo);
|
||||
GameLogic.Set(GameEventDepot);
|
||||
GameLogic.Set(Player);
|
||||
GameLogic.Set(Map);
|
||||
GameLogic.Set(InGameUI);
|
||||
Instantiator = new Instantiator(GetTree());
|
||||
RescuedItems = new RescuedItemDatabase();
|
||||
|
||||
GameChunk = new SaveChunk<GameData>(
|
||||
(chunk) =>
|
||||
{
|
||||
var gameData = new GameData()
|
||||
{
|
||||
PlayerData = new PlayerData()
|
||||
{
|
||||
PlayerStats = new PlayerStats()
|
||||
{
|
||||
CurrentHP = Player.Stats.CurrentHP.Value,
|
||||
MaximumHP = Player.Stats.MaximumHP.Value,
|
||||
CurrentVT = Player.Stats.CurrentVT.Value,
|
||||
MaximumVT = Player.Stats.MaximumVT.Value,
|
||||
CurrentAttack = Player.Stats.CurrentAttack.Value,
|
||||
BonusAttack = Player.Stats.BonusAttack.Value,
|
||||
MaxAttack = Player.Stats.MaxAttack.Value,
|
||||
CurrentDefense = Player.Stats.CurrentDefense.Value,
|
||||
BonusDefense = Player.Stats.BonusDefense.Value,
|
||||
MaxDefense = Player.Stats.MaxDefense.Value,
|
||||
CurrentExp = Player.Stats.CurrentExp.Value,
|
||||
CurrentLevel = Player.Stats.CurrentLevel.Value,
|
||||
ExpToNextLevel = Player.Stats.ExpToNextLevel.Value,
|
||||
Luck = Player.Stats.Luck.Value
|
||||
},
|
||||
Inventory = Player.Inventory
|
||||
},
|
||||
MapData = new MapData()
|
||||
{
|
||||
FloorScenes = Map.FloorScenes
|
||||
},
|
||||
RescuedItems = new RescuedItemDatabase() { Items = RescuedItems.Items }
|
||||
};
|
||||
GameChunk = new SaveChunk<GameData>(
|
||||
(chunk) =>
|
||||
{
|
||||
var gameData = new GameData()
|
||||
{
|
||||
PlayerData = new PlayerData()
|
||||
{
|
||||
PlayerStats = new PlayerStats()
|
||||
{
|
||||
CurrentHP = Player.Stats.CurrentHP.Value,
|
||||
MaximumHP = Player.Stats.MaximumHP.Value,
|
||||
CurrentVT = Player.Stats.CurrentVT.Value,
|
||||
MaximumVT = Player.Stats.MaximumVT.Value,
|
||||
CurrentAttack = Player.Stats.CurrentAttack.Value,
|
||||
BonusAttack = Player.Stats.BonusAttack.Value,
|
||||
MaxAttack = Player.Stats.MaxAttack.Value,
|
||||
CurrentDefense = Player.Stats.CurrentDefense.Value,
|
||||
BonusDefense = Player.Stats.BonusDefense.Value,
|
||||
MaxDefense = Player.Stats.MaxDefense.Value,
|
||||
CurrentExp = Player.Stats.CurrentExp.Value,
|
||||
CurrentLevel = Player.Stats.CurrentLevel.Value,
|
||||
ExpToNextLevel = Player.Stats.ExpToNextLevel.Value,
|
||||
Luck = Player.Stats.Luck.Value
|
||||
},
|
||||
Inventory = Player.Inventory
|
||||
},
|
||||
MapData = new MapData()
|
||||
{
|
||||
FloorScenes = Map.FloorScenes
|
||||
},
|
||||
RescuedItems = new RescuedItemDatabase() { Items = RescuedItems.Items }
|
||||
};
|
||||
|
||||
return gameData;
|
||||
},
|
||||
onLoad: (chunk, data) =>
|
||||
{
|
||||
RescuedItems = data.RescuedItems;
|
||||
chunk.LoadChunkSaveData(data.PlayerData);
|
||||
chunk.LoadChunkSaveData(data.MapData);
|
||||
}
|
||||
);
|
||||
return gameData;
|
||||
},
|
||||
onLoad: (chunk, data) =>
|
||||
{
|
||||
RescuedItems = data.RescuedItems;
|
||||
chunk.LoadChunkSaveData(data.PlayerData);
|
||||
chunk.LoadChunkSaveData(data.MapData);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void OnResolved()
|
||||
{
|
||||
var saveFileManager = _container.GetInstance<IMaSaveFileManager<GameData>>();
|
||||
SaveFile = new SaveFile<GameData>(
|
||||
root: GameChunk,
|
||||
onSave: saveFileManager.Save,
|
||||
onLoad: async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var gameData = await saveFileManager.Load();
|
||||
return gameData;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
GD.Print("No save file found.");
|
||||
}
|
||||
var saveFileManager = _container.GetInstance<IMaSaveFileManager<GameData>>();
|
||||
SaveFile = new SaveFile<GameData>(
|
||||
root: GameChunk,
|
||||
onSave: saveFileManager.Save,
|
||||
onLoad: async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var gameData = await saveFileManager.Load();
|
||||
return gameData;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
GD.Print("No save file found.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
GameBinding = GameLogic.Bind();
|
||||
GameBinding
|
||||
.Handle((in GameLogic.Output.StartGame _) =>
|
||||
{
|
||||
GameRepo.Resume();
|
||||
InGameUI.Show();
|
||||
})
|
||||
.Handle((in GameLogic.Output.GoToOverworld _) =>
|
||||
{
|
||||
GameEventDepot.OnOverworldEntered();
|
||||
})
|
||||
.Handle((in GameLogic.Output.SetPauseMode output) => CallDeferred(nameof(SetPauseMode), output.IsPaused))
|
||||
.Handle((in GameLogic.Output.ShowPauseMenu _) =>
|
||||
{
|
||||
PauseMenu.Show();
|
||||
PauseMenu.FadeIn();
|
||||
Input.MouseMode = Input.MouseModeEnum.Visible;
|
||||
PauseMenu.SetProcessUnhandledInput(true);
|
||||
})
|
||||
.Handle((in GameLogic.Output.HidePauseMenu _) => { PauseMenu.Hide(); })
|
||||
.Handle((in GameLogic.Output.ExitPauseMenu _) => { PauseMenu.FadeOut(); Input.MouseMode = Input.MouseModeEnum.Visible; PauseMenu.SetProcessUnhandledInput(false); })
|
||||
.Handle((in GameLogic.Output.LoadNextFloor _) => { Map.SpawnNextFloor(); })
|
||||
.Handle((in GameLogic.Output.LoadMap _) => { Map.LoadMap(); })
|
||||
.Handle((in GameLogic.Output.ShowFloorClearMenu _) => { FloorClearMenu.Show(); FloorClearMenu.FadeIn(); })
|
||||
.Handle((in GameLogic.Output.ExitFloorClearMenu _) => { FloorClearMenu.FadeOut(); })
|
||||
.Handle((in GameLogic.Output.ShowAskForTeleport _) => { GameRepo.Pause(); InGameUI.UseTeleportPrompt.FadeIn(); InGameUI.SetProcessInput(true); })
|
||||
.Handle((in GameLogic.Output.HideAskForTeleport _) => { GameRepo.Resume(); InGameUI.UseTeleportPrompt.FadeOut(); InGameUI.SetProcessInput(false); })
|
||||
.Handle((in GameLogic.Output.ShowLostScreen _) => { DeathMenu.Show(); DeathMenu.FadeIn(); })
|
||||
.Handle((in GameLogic.Output.ExitLostScreen _) => { DeathMenu.FadeOut(); })
|
||||
.Handle((in GameLogic.Output.DoubleExpTimeStart output) => { DoubleEXPTimer.WaitTime = output.lengthOfTimeInSeconds; DoubleEXPTimer.Start(); })
|
||||
.Handle((in GameLogic.Output.SaveGame _) =>
|
||||
{
|
||||
SaveFile.Save();
|
||||
AppRepo.OnExitGame();
|
||||
GetTree().Quit();
|
||||
// Back to title screen
|
||||
});
|
||||
GameLogic.Start();
|
||||
GameBinding = GameLogic.Bind();
|
||||
GameBinding
|
||||
.Handle((in GameLogic.Output.StartGame _) =>
|
||||
{
|
||||
GameRepo.Resume();
|
||||
InGameUI.Show();
|
||||
})
|
||||
.Handle((in GameLogic.Output.GoToOverworld _) =>
|
||||
{
|
||||
GameEventDepot.OnOverworldEntered();
|
||||
})
|
||||
.Handle((in GameLogic.Output.SetPauseMode output) => CallDeferred(nameof(SetPauseMode), output.IsPaused))
|
||||
.Handle((in GameLogic.Output.ShowPauseMenu _) =>
|
||||
{
|
||||
PauseMenu.Show();
|
||||
PauseMenu.FadeIn();
|
||||
Input.MouseMode = Input.MouseModeEnum.Visible;
|
||||
PauseMenu.SetProcessUnhandledInput(true);
|
||||
})
|
||||
.Handle((in GameLogic.Output.HidePauseMenu _) => { PauseMenu.Hide(); })
|
||||
.Handle((in GameLogic.Output.ExitPauseMenu _) => { PauseMenu.FadeOut(); Input.MouseMode = Input.MouseModeEnum.Visible; PauseMenu.SetProcessUnhandledInput(false); })
|
||||
.Handle((in GameLogic.Output.LoadNextFloor _) => { Map.SpawnNextFloor(); })
|
||||
.Handle((in GameLogic.Output.LoadMap _) => { Map.LoadMap(); })
|
||||
.Handle((in GameLogic.Output.ShowFloorClearMenu _) => { FloorClearMenu.Show(); FloorClearMenu.FadeIn(); })
|
||||
.Handle((in GameLogic.Output.ExitFloorClearMenu _) => { FloorClearMenu.FadeOut(); })
|
||||
.Handle((in GameLogic.Output.ShowAskForTeleport _) => { GameRepo.Pause(); InGameUI.UseTeleportPrompt.FadeIn(); InGameUI.SetProcessInput(true); })
|
||||
.Handle((in GameLogic.Output.HideAskForTeleport _) => { GameRepo.Resume(); InGameUI.UseTeleportPrompt.FadeOut(); InGameUI.SetProcessInput(false); })
|
||||
.Handle((in GameLogic.Output.ShowLostScreen _) => { DeathMenu.Show(); DeathMenu.FadeIn(); })
|
||||
.Handle((in GameLogic.Output.ExitLostScreen _) => { DeathMenu.FadeOut(); })
|
||||
.Handle((in GameLogic.Output.DoubleExpTimeStart output) => { DoubleEXPTimer.WaitTime = output.lengthOfTimeInSeconds; DoubleEXPTimer.Start(); })
|
||||
.Handle((in GameLogic.Output.SaveGame _) =>
|
||||
{
|
||||
SaveFile.Save();
|
||||
AppRepo.OnExitGame();
|
||||
GetTree().Quit();
|
||||
// Back to title screen
|
||||
});
|
||||
GameLogic.Start();
|
||||
|
||||
GameLogic.Input(new GameLogic.Input.Initialize());
|
||||
GameLogic.Input(new GameLogic.Input.Initialize());
|
||||
|
||||
this.Provide();
|
||||
this.Provide();
|
||||
|
||||
PauseMenu.TransitionCompleted += OnPauseMenuTransitioned;
|
||||
PauseMenu.UnpauseButtonPressed += PauseMenu_UnpauseButtonPressed;
|
||||
PauseMenu.TransitionCompleted += OnPauseMenuTransitioned;
|
||||
PauseMenu.UnpauseButtonPressed += PauseMenu_UnpauseButtonPressed;
|
||||
|
||||
InGameUI.UseTeleportPrompt.TeleportToNextFloor += UseTeleportPrompt_TeleportToNextFloor;
|
||||
InGameUI.UseTeleportPrompt.CloseTeleportPrompt += UseTeleportPrompt_CloseTeleportPrompt;
|
||||
InGameUI.UseTeleportPrompt.TeleportToNextFloor += UseTeleportPrompt_TeleportToNextFloor;
|
||||
InGameUI.UseTeleportPrompt.CloseTeleportPrompt += UseTeleportPrompt_CloseTeleportPrompt;
|
||||
|
||||
FloorClearMenu.GoToNextFloor += FloorClearMenu_GoToNextFloor;
|
||||
FloorClearMenu.SaveAndExit += FloorClearMenu_SaveAndExit;
|
||||
FloorClearMenu.TransitionCompleted += FloorClearMenu_TransitionCompleted;
|
||||
FloorClearMenu.GoToNextFloor += FloorClearMenu_GoToNextFloor;
|
||||
FloorClearMenu.SaveAndExit += FloorClearMenu_SaveAndExit;
|
||||
FloorClearMenu.TransitionCompleted += FloorClearMenu_TransitionCompleted;
|
||||
|
||||
GameEventDepot.RestorativePickedUp += GameEventDepot_RestorativePickedUp;
|
||||
GameEventDepot.RestorativePickedUp += GameEventDepot_RestorativePickedUp;
|
||||
|
||||
DoubleEXPTimer.Timeout += DoubleEXPTimer_Timeout;
|
||||
DoubleEXPTimer.Timeout += DoubleEXPTimer_Timeout;
|
||||
|
||||
_effectService = new EffectService(this, Player, Map);
|
||||
_effectService = new EffectService(this, Player, Map);
|
||||
}
|
||||
|
||||
public void LoadExistingGame() => SaveFile.Load().ContinueWith((_) => CallDeferred(nameof(FinishedLoadingSaveFile)));
|
||||
|
||||
public void TogglePause()
|
||||
{
|
||||
if (GameLogic.Value is GameLogic.State.Paused)
|
||||
GameLogic.Input(new GameLogic.Input.UnpauseGame());
|
||||
else
|
||||
GameLogic.Input(new GameLogic.Input.PauseGame());
|
||||
if (GameLogic.Value is GameLogic.State.Paused)
|
||||
GameLogic.Input(new GameLogic.Input.UnpauseGame());
|
||||
else
|
||||
GameLogic.Input(new GameLogic.Input.PauseGame());
|
||||
}
|
||||
|
||||
public void FloorExitReached()
|
||||
{
|
||||
GameLogic.Input(new GameLogic.Input.AskForTeleport());
|
||||
GameEventDepot.OnTeleportEntered();
|
||||
GameLogic.Input(new GameLogic.Input.AskForTeleport());
|
||||
GameEventDepot.OnTeleportEntered();
|
||||
}
|
||||
|
||||
public async Task UseItem(InventoryItem item)
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case ConsumableItem consumableItem:
|
||||
EnactConsumableItemEffects(consumableItem);
|
||||
break;
|
||||
case EffectItem effectItem:
|
||||
EnactEffectItemEffects(effectItem);
|
||||
break;
|
||||
case ThrowableItem throwableItem:
|
||||
EnactThrowableItemEffects(throwableItem);
|
||||
break;
|
||||
}
|
||||
switch (item)
|
||||
{
|
||||
case ConsumableItem consumableItem:
|
||||
EnactConsumableItemEffects(consumableItem);
|
||||
break;
|
||||
case EffectItem effectItem:
|
||||
EnactEffectItemEffects(effectItem);
|
||||
break;
|
||||
case ThrowableItem throwableItem:
|
||||
EnactThrowableItemEffects(throwableItem);
|
||||
break;
|
||||
}
|
||||
|
||||
await ToSignal(GetTree().CreateTimer(0.3f), "timeout");
|
||||
await ToSignal(GetTree().CreateTimer(0.3f), "timeout");
|
||||
|
||||
RemoveItemOrSubtractFromItemCount(item);
|
||||
RemoveItemOrSubtractFromItemCount(item);
|
||||
}
|
||||
|
||||
public void DropItem(InventoryItem item)
|
||||
{
|
||||
var droppedScene = GD.Load<PackedScene>("res://src/items/dropped/DroppedItem.tscn");
|
||||
var dropped = droppedScene.Instantiate<DroppedItem>();
|
||||
dropped.Item = item;
|
||||
AddChild(dropped);
|
||||
dropped.Drop();
|
||||
var droppedScene = GD.Load<PackedScene>("res://src/items/dropped/DroppedItem.tscn");
|
||||
var dropped = droppedScene.Instantiate<DroppedItem>();
|
||||
dropped.Item = item;
|
||||
AddChild(dropped);
|
||||
dropped.Drop();
|
||||
}
|
||||
|
||||
public void ThrowItem(InventoryItem item)
|
||||
{
|
||||
var thrownScene = GD.Load<PackedScene>("res://src/items/thrown/ThrownItem.tscn");
|
||||
var thrown = thrownScene.Instantiate<ThrownItem>();
|
||||
thrown.ItemThatIsThrown = (InventoryItem)item;
|
||||
AddChild(thrown);
|
||||
thrown.Position += new Vector3(0, 1.5f, 0);
|
||||
thrown.Throw(_effectService);
|
||||
var thrownScene = GD.Load<PackedScene>("res://src/items/thrown/ThrownItem.tscn");
|
||||
var thrown = thrownScene.Instantiate<ThrownItem>();
|
||||
thrown.ItemThatIsThrown = (InventoryItem)item;
|
||||
AddChild(thrown);
|
||||
thrown.Position += new Vector3(0, 1.5f, 0);
|
||||
thrown.Throw(_effectService);
|
||||
}
|
||||
|
||||
public IDungeonFloor CurrentFloor => Map.CurrentFloor;
|
||||
@@ -282,18 +282,18 @@ public partial class Game : Node3D, IGame
|
||||
|
||||
private void DropRestorative(Vector3 vector)
|
||||
{
|
||||
var restorativeScene = GD.Load<PackedScene>("res://src/items/restorative/Restorative.tscn");
|
||||
var restorative = restorativeScene.Instantiate<Restorative>();
|
||||
AddChild(restorative);
|
||||
restorative.GlobalPosition = vector;
|
||||
var restorativeScene = GD.Load<PackedScene>("res://src/items/restorative/Restorative.tscn");
|
||||
var restorative = restorativeScene.Instantiate<Restorative>();
|
||||
AddChild(restorative);
|
||||
restorative.GlobalPosition = vector;
|
||||
}
|
||||
|
||||
private void UseTeleportPrompt_CloseTeleportPrompt() => GameLogic.Input(new GameLogic.Input.HideAskForTeleport());
|
||||
|
||||
private void UseTeleportPrompt_TeleportToNextFloor()
|
||||
{
|
||||
GameLogic.Input(new GameLogic.Input.FloorExitReached());
|
||||
GameEventDepot.OnDungeonAThemeAreaEntered();
|
||||
GameLogic.Input(new GameLogic.Input.FloorExitReached());
|
||||
GameEventDepot.OnDungeonAThemeAreaEntered();
|
||||
}
|
||||
|
||||
private void PauseMenu_UnpauseButtonPressed() => GameLogic.Input(new GameLogic.Input.UnpauseGame());
|
||||
@@ -302,13 +302,13 @@ public partial class Game : Node3D, IGame
|
||||
|
||||
private void FloorClearMenu_TransitionCompleted()
|
||||
{
|
||||
GameRepo.Resume();
|
||||
if (Player.EquippedWeapon.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||
Player.Unequip(Player.EquippedWeapon.Value);
|
||||
if (Player.EquippedArmor.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||
Player.Unequip(Player.EquippedArmor.Value);
|
||||
if (Player.EquippedAccessory.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||
Player.Unequip(Player.EquippedAccessory.Value);
|
||||
GameRepo.Resume();
|
||||
if (Player.EquippedWeapon.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||
Player.Unequip(Player.EquippedWeapon.Value);
|
||||
if (Player.EquippedArmor.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||
Player.Unequip(Player.EquippedArmor.Value);
|
||||
if (Player.EquippedAccessory.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||
Player.Unequip(Player.EquippedAccessory.Value);
|
||||
}
|
||||
|
||||
private void FloorClearMenu_GoToNextFloor() => GameLogic.Input(new GameLogic.Input.GoToNextFloor());
|
||||
@@ -319,8 +319,8 @@ public partial class Game : Node3D, IGame
|
||||
|
||||
private void SetPauseMode(bool isPaused)
|
||||
{
|
||||
if (GetTree() != null)
|
||||
GetTree().Paused = isPaused;
|
||||
if (GetTree() != null)
|
||||
GetTree().Paused = isPaused;
|
||||
}
|
||||
|
||||
private void DoubleEXPTimer_Timeout() => GameRepo.EndDoubleExp();
|
||||
@@ -335,88 +335,88 @@ public partial class Game : Node3D, IGame
|
||||
|
||||
private void EnactConsumableItemEffects(ConsumableItem consumableItem)
|
||||
{
|
||||
if (Player.Stats.CurrentHP == Player.Stats.MaximumHP && consumableItem.RaiseHPAmount > 0)
|
||||
Player.RaiseHP(consumableItem.RaiseHPAmount);
|
||||
if (Player.Stats.CurrentVT == Player.Stats.MaximumVT && consumableItem.RaiseVTAmount > 0)
|
||||
Player.RaiseVT(consumableItem.RaiseVTAmount);
|
||||
if (Player.Stats.CurrentHP == Player.Stats.MaximumHP && consumableItem.RaiseHPAmount > 0)
|
||||
Player.RaiseHP(consumableItem.RaiseHPAmount);
|
||||
if (Player.Stats.CurrentVT == Player.Stats.MaximumVT && consumableItem.RaiseVTAmount > 0)
|
||||
Player.RaiseVT(consumableItem.RaiseVTAmount);
|
||||
|
||||
if (consumableItem.HealHPAmount > 0 && Player.Stats.CurrentHP != Player.Stats.MaximumHP)
|
||||
Player.HealHP(consumableItem.HealHPAmount);
|
||||
if (consumableItem.HealVTAmount > 0 && Player.Stats.CurrentVT != Player.Stats.MaximumVT)
|
||||
Player.HealVT(consumableItem.HealVTAmount);
|
||||
if (consumableItem.HealHPAmount > 0 && Player.Stats.CurrentHP != Player.Stats.MaximumHP)
|
||||
Player.HealHP(consumableItem.HealHPAmount);
|
||||
if (consumableItem.HealVTAmount > 0 && Player.Stats.CurrentVT != Player.Stats.MaximumVT)
|
||||
Player.HealVT(consumableItem.HealVTAmount);
|
||||
}
|
||||
|
||||
private void EnactEffectItemEffects(EffectItem effectItem)
|
||||
{
|
||||
switch (effectItem.UsableItemTag)
|
||||
{
|
||||
case UsableItemTag.TeleportAllEnemiesToRoom:
|
||||
_effectService.TeleportEnemiesToCurrentRoom();
|
||||
break;
|
||||
case UsableItemTag.KillHalfEnemiesInRoom:
|
||||
_effectService.KillHalfEnemiesInRoom();
|
||||
break;
|
||||
case UsableItemTag.TurnAllEnemiesIntoHealingItem:
|
||||
_effectService.TurnAllEnemiesInRoomIntoHealingItem();
|
||||
break;
|
||||
case UsableItemTag.HealsAllInRoomToMaxHP:
|
||||
_effectService.HealAllEnemiesAndPlayerInRoomToFull();
|
||||
break;
|
||||
case UsableItemTag.AbsorbHPFromAllEnemiesInRoom:
|
||||
_effectService.AbsorbHPFromAllEnemiesInRoom();
|
||||
break;
|
||||
case UsableItemTag.DealElementalDamageToAllEnemiesInRoom:
|
||||
_effectService.DealElementalDamageToAllEnemiesInRoom(ElementType.Hydric);
|
||||
break;
|
||||
case UsableItemTag.SwapHPAndVT:
|
||||
_effectService.SwapHPandVT();
|
||||
break;
|
||||
case UsableItemTag.RaiseCurrentWeaponAttack:
|
||||
_effectService.RaiseCurrentWeaponAttack();
|
||||
break;
|
||||
case UsableItemTag.RaiseCurrentDefenseArmor:
|
||||
_effectService.RaiseCurrentArmorDefense();
|
||||
break;
|
||||
case UsableItemTag.RaiseLevel:
|
||||
_effectService.RaiseLevel();
|
||||
break;
|
||||
case UsableItemTag.RandomEffect:
|
||||
_effectService.RandomEffect(effectItem);
|
||||
break;
|
||||
}
|
||||
switch (effectItem.UsableItemTag)
|
||||
{
|
||||
case UsableItemTag.TeleportAllEnemiesToRoom:
|
||||
_effectService.TeleportEnemiesToCurrentRoom();
|
||||
break;
|
||||
case UsableItemTag.KillHalfEnemiesInRoom:
|
||||
_effectService.KillHalfEnemiesInRoom();
|
||||
break;
|
||||
case UsableItemTag.TurnAllEnemiesIntoHealingItem:
|
||||
_effectService.TurnAllEnemiesInRoomIntoHealingItem();
|
||||
break;
|
||||
case UsableItemTag.HealsAllInRoomToMaxHP:
|
||||
_effectService.HealAllEnemiesAndPlayerInRoomToFull();
|
||||
break;
|
||||
case UsableItemTag.AbsorbHPFromAllEnemiesInRoom:
|
||||
_effectService.AbsorbHPFromAllEnemiesInRoom();
|
||||
break;
|
||||
case UsableItemTag.DealElementalDamageToAllEnemiesInRoom:
|
||||
_effectService.DealElementalDamageToAllEnemiesInRoom(ElementType.Hydric);
|
||||
break;
|
||||
case UsableItemTag.SwapHPAndVT:
|
||||
_effectService.SwapHPandVT();
|
||||
break;
|
||||
case UsableItemTag.RaiseCurrentWeaponAttack:
|
||||
_effectService.RaiseCurrentWeaponAttack();
|
||||
break;
|
||||
case UsableItemTag.RaiseCurrentDefenseArmor:
|
||||
_effectService.RaiseCurrentArmorDefense();
|
||||
break;
|
||||
case UsableItemTag.RaiseLevel:
|
||||
_effectService.RaiseLevel();
|
||||
break;
|
||||
case UsableItemTag.RandomEffect:
|
||||
_effectService.RandomEffect(effectItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnactThrowableItemEffects(ThrowableItem throwableItem)
|
||||
{
|
||||
switch (throwableItem.ThrowableItemTag)
|
||||
{
|
||||
case ThrowableItemTag.DoubleExp:
|
||||
GameRepo.StartDoubleEXP(TimeSpan.FromSeconds(30));
|
||||
break;
|
||||
case ThrowableItemTag.TeleportToRandomLocation:
|
||||
_effectService.TeleportToRandomRoom(Player);
|
||||
InGameUI.CloseInventory();
|
||||
break;
|
||||
case ThrowableItemTag.CanChangeAffinity:
|
||||
_effectService.ChangeAffinity(throwableItem);
|
||||
break;
|
||||
case ThrowableItemTag.WarpToExitIfFound:
|
||||
_effectService.WarpToExit(Player);
|
||||
InGameUI.CloseInventory();
|
||||
break;
|
||||
}
|
||||
switch (throwableItem.ThrowableItemTag)
|
||||
{
|
||||
case ThrowableItemTag.DoubleExp:
|
||||
GameRepo.StartDoubleEXP(TimeSpan.FromSeconds(30));
|
||||
break;
|
||||
case ThrowableItemTag.TeleportToRandomLocation:
|
||||
_effectService.TeleportToRandomRoom(Player);
|
||||
InGameUI.CloseInventory();
|
||||
break;
|
||||
case ThrowableItemTag.CanChangeAffinity:
|
||||
_effectService.ChangeAffinity(throwableItem);
|
||||
break;
|
||||
case ThrowableItemTag.WarpToExitIfFound:
|
||||
_effectService.WarpToExit(Player);
|
||||
InGameUI.CloseInventory();
|
||||
break;
|
||||
}
|
||||
|
||||
if (throwableItem.HealHPAmount > 0)
|
||||
Player.HealHP(throwableItem.HealHPAmount);
|
||||
if (throwableItem.HealVTAmount > 0)
|
||||
Player.HealVT(throwableItem.HealVTAmount);
|
||||
if (throwableItem.HealHPAmount > 0)
|
||||
Player.HealHP(throwableItem.HealHPAmount);
|
||||
if (throwableItem.HealVTAmount > 0)
|
||||
Player.HealVT(throwableItem.HealVTAmount);
|
||||
}
|
||||
|
||||
private void RemoveItemOrSubtractFromItemCount(InventoryItem item)
|
||||
{
|
||||
if (item is IStackable stackableItem && stackableItem.Count > 1)
|
||||
stackableItem.SetCount(stackableItem.Count - 1);
|
||||
else
|
||||
GameRepo.RemoveItemFromInventory(item);
|
||||
if (item is IStackable stackableItem && stackableItem.Count > 1)
|
||||
stackableItem.SetCount(stackableItem.Count - 1);
|
||||
else
|
||||
GameRepo.RemoveItemFromInventory(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +269,6 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
||||
|
||||
if (currentItem is EquipableItem equipable)
|
||||
{
|
||||
;
|
||||
UseButton.Text = equipable.IsEquipped ? "Unequip" : "Equip";
|
||||
ThrowButton.Disabled = equipable.IsEquipped ? true : false;
|
||||
ThrowButton.FocusMode = equipable.IsEquipped ? FocusModeEnum.None : FocusModeEnum.All;
|
||||
|
||||
@@ -43,54 +43,54 @@ public partial class ItemSlot : HBoxContainer, IItemSlot
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
ItemName.Text = Item.ItemName;
|
||||
ItemTexture.Texture = Item.GetTexture();
|
||||
Player.EquippedWeapon.Sync += EquipableItem_Sync;
|
||||
Player.EquippedArmor.Sync += EquipableItem_Sync;
|
||||
Player.EquippedAccessory.Sync += EquipableItem_Sync;
|
||||
ItemName.Text = Item.ItemName;
|
||||
ItemTexture.Texture = Item.GetTexture();
|
||||
Player.EquippedWeapon.Sync += EquipableItem_Sync;
|
||||
Player.EquippedArmor.Sync += EquipableItem_Sync;
|
||||
Player.EquippedAccessory.Sync += EquipableItem_Sync;
|
||||
|
||||
if (Item is IStackable stackableItem)
|
||||
{
|
||||
ItemCount.Text = $"{stackableItem.Count:D2}";
|
||||
ItemCount.Visible = true;
|
||||
}
|
||||
if (Item is IStackable stackableItem)
|
||||
{
|
||||
ItemCount.Text = $"{stackableItem.Count:D2}";
|
||||
ItemCount.Visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void EquipableItem_Sync(EquipableItem obj)
|
||||
{
|
||||
if (Item is EquipableItem equipableItem && equipableItem == obj)
|
||||
{
|
||||
SetEquippedSelectedItemStyle();
|
||||
}
|
||||
if (Item is EquipableItem unequippedItem && unequippedItem != obj)
|
||||
{
|
||||
SetItemStyle();
|
||||
}
|
||||
if (Item is EquipableItem equipableItem && equipableItem == obj)
|
||||
{
|
||||
SetEquippedSelectedItemStyle();
|
||||
}
|
||||
if (Item is EquipableItem unequippedItem && unequippedItem != obj)
|
||||
{
|
||||
SetItemStyle();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetItemStyle()
|
||||
{
|
||||
ItemName.LabelSettings = ItemFont;
|
||||
ItemName.LabelSettings = ItemFont;
|
||||
}
|
||||
public void SetSelectedItemStyle()
|
||||
{
|
||||
if (Item is EquipableItem equipableItem && equipableItem.IsEquipped)
|
||||
{
|
||||
ItemName.LabelSettings = SelectedEquippedItemFont;
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemName.LabelSettings = SelectedItemFont;
|
||||
}
|
||||
if (Item is EquipableItem equipableItem && equipableItem.IsEquipped)
|
||||
{
|
||||
ItemName.LabelSettings = SelectedEquippedItemFont;
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemName.LabelSettings = SelectedItemFont;
|
||||
}
|
||||
}
|
||||
public void SetEquippedItemStyle()
|
||||
{
|
||||
ItemName.LabelSettings = EquippedItemFont;
|
||||
ItemName.LabelSettings = EquippedItemFont;
|
||||
}
|
||||
|
||||
public void SetEquippedSelectedItemStyle()
|
||||
{
|
||||
ItemName.LabelSettings = SelectedEquippedItemFont;
|
||||
ItemName.LabelSettings = SelectedEquippedItemFont;
|
||||
}
|
||||
|
||||
public InventoryItem Item { get; set; } = default!;
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_yytis")
|
||||
UsableItemTag = 0
|
||||
Name = "Aeolic Caster"
|
||||
Description = "Deal Aeolic Damage to all enemies in the room."
|
||||
UsableItemTag = 9
|
||||
ElementalDamageType = 1
|
||||
Name = "Aeolic Caster"
|
||||
Description = "Deal Aeolic Damage to all enemies in the room."
|
||||
Texture = ExtResource("1_u0h2q")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_u0h2q")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_53wiy")
|
||||
UsableItemTag = 0
|
||||
Name = "Cloth Resolution"
|
||||
Description = "Raises currently equipped armor's defense by 1."
|
||||
UsableItemTag = 11
|
||||
ElementalDamageType = 0
|
||||
Name = "Cloth Resolution"
|
||||
Description = "Raises currently equipped armor's defense by 1."
|
||||
Texture = ExtResource("1_1mm10")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_1mm10")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_n1557")
|
||||
UsableItemTag = 0
|
||||
Name = "Cosmos"
|
||||
Description = "Raises current Level by 1."
|
||||
UsableItemTag = 12
|
||||
ElementalDamageType = 0
|
||||
Name = "Cosmos"
|
||||
Description = "Raises current Level by 1."
|
||||
Texture = ExtResource("1_dn5pk")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_dn5pk")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_50lqu")
|
||||
UsableItemTag = 0
|
||||
Name = "Devic Balance"
|
||||
Description = "Kill half of all enemies in current room."
|
||||
UsableItemTag = 6
|
||||
ElementalDamageType = 0
|
||||
Name = "Devic Balance"
|
||||
Description = "Kill half of all enemies in current room."
|
||||
Texture = ExtResource("1_j7j7j")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_j7j7j")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_0uaie")
|
||||
UsableItemTag = 0
|
||||
Name = "Devic Recall"
|
||||
Description = "Teleports all enemies to current room."
|
||||
UsableItemTag = 4
|
||||
ElementalDamageType = 0
|
||||
Name = "Devic Recall"
|
||||
Description = "Teleports all enemies to current room."
|
||||
Texture = ExtResource("1_j462p")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_j462p")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_3l06v")
|
||||
UsableItemTag = 0
|
||||
Name = "Entropic Seal"
|
||||
Description = "Random effect."
|
||||
UsableItemTag = 13
|
||||
ElementalDamageType = 0
|
||||
Name = "Entropic Seal"
|
||||
Description = "Random effect."
|
||||
Texture = ExtResource("1_dbua5")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_dbua5")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_uojwo")
|
||||
UsableItemTag = 0
|
||||
Name = "Ferrous Resolution"
|
||||
Description = "Raises currently equipped weapon's attack by 1."
|
||||
UsableItemTag = 10
|
||||
ElementalDamageType = 0
|
||||
Name = "Ferrous Resolution"
|
||||
Description = "Raises currently equipped weapon's attack by 1."
|
||||
Texture = ExtResource("1_6wt4w")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_6wt4w")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_i4na1")
|
||||
UsableItemTag = 0
|
||||
Name = "Ferrum Caster"
|
||||
Description = "Deal Ferrum Damage to all enemies in the room."
|
||||
UsableItemTag = 9
|
||||
ElementalDamageType = 5
|
||||
Name = "Ferrum Caster"
|
||||
Description = "Deal Ferrum Damage to all enemies in the room."
|
||||
Texture = ExtResource("1_xsfvc")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_xsfvc")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_drp30")
|
||||
UsableItemTag = 0
|
||||
Name = "Heaven's Rebellion"
|
||||
Description = "Heals self and all enemies in current room to maximum HP."
|
||||
UsableItemTag = 8
|
||||
ElementalDamageType = 0
|
||||
Name = "Heaven's Rebellion"
|
||||
Description = "Heals self and all enemies in current room to maximum HP."
|
||||
Texture = ExtResource("1_g0a3x")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_g0a3x")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_mj844")
|
||||
UsableItemTag = 0
|
||||
Name = "Hydric Caster"
|
||||
Description = "Deal Hydric Damage to all enemies in the room."
|
||||
UsableItemTag = 9
|
||||
ElementalDamageType = 3
|
||||
Name = "Hydric Caster"
|
||||
Description = "Deal Hydric Damage to all enemies in the room."
|
||||
Texture = ExtResource("1_8v5wn")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_8v5wn")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_cl8lc")
|
||||
UsableItemTag = 0
|
||||
Name = "Igneous Caster"
|
||||
Description = "Deal Igneous Damage to all enemies in the room."
|
||||
UsableItemTag = 9
|
||||
ElementalDamageType = 4
|
||||
Name = "Igneous Caster"
|
||||
Description = "Deal Igneous Damage to all enemies in the room."
|
||||
Texture = ExtResource("1_3iam5")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_3iam5")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,14 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_hxj1b")
|
||||
UsableItemTags = Array[int]([7])
|
||||
Name = "Kyuuketsuki"
|
||||
Description = "Absorbs HP from all enemies in the room."
|
||||
Texture = ExtResource("1_0tcgy")
|
||||
UsableItemTag = 7
|
||||
ElementalDamageType = 0
|
||||
Name = "Kyuuketsuki"
|
||||
Description = "Absorbs HP from all enemies in the room."
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTags = Array[int]([])
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_0tcgy")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_lq0bc")
|
||||
UsableItemTag = 0
|
||||
Name = "Perspective"
|
||||
Description = "Swap current HP and VT."
|
||||
UsableItemTag = 3
|
||||
ElementalDamageType = 0
|
||||
Name = "Perspective"
|
||||
Description = "Swap current HP and VT."
|
||||
Texture = ExtResource("1_31uf7")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_31uf7")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_ksb1c")
|
||||
UsableItemTag = 0
|
||||
Name = "Sine Morphization"
|
||||
Description = "Turns all enemies in room to healing item."
|
||||
UsableItemTag = 5
|
||||
ElementalDamageType = 0
|
||||
Name = "Sine Morphization"
|
||||
Description = "Turns all enemies in room to healing item."
|
||||
Texture = ExtResource("1_vqhky")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_vqhky")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_38yjb")
|
||||
UsableItemTag = 0
|
||||
Name = "Telluric Caster"
|
||||
Description = "Deal Telluric Damage to all enemies in the room."
|
||||
UsableItemTag = 9
|
||||
ElementalDamageType = 2
|
||||
Name = "Telluric Caster"
|
||||
Description = "Deal Telluric Damage to all enemies in the room."
|
||||
Texture = ExtResource("1_x62ct")
|
||||
SpawnRate = 0.5
|
||||
ThrowSpeed = 12.0
|
||||
HealHPAmount = 0
|
||||
HealVTAmount = 0
|
||||
ThrowDamage = 5
|
||||
ItemTag = 0
|
||||
Texture = ExtResource("1_x62ct")
|
||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||
|
||||
@@ -58,66 +58,66 @@ public partial class Map : Node3D, IMap
|
||||
|
||||
public void OnResolved()
|
||||
{
|
||||
FloorScenes = [];
|
||||
FloorScenes = [];
|
||||
|
||||
MapChunk = new SaveChunk<MapData>(
|
||||
onSave: (chunk) => new MapData()
|
||||
{
|
||||
FloorScenes = FloorScenes,
|
||||
},
|
||||
onLoad: (chunk, data) =>
|
||||
{
|
||||
FloorScenes = data.FloorScenes;
|
||||
}
|
||||
);
|
||||
MapChunk = new SaveChunk<MapData>(
|
||||
onSave: (chunk) => new MapData()
|
||||
{
|
||||
FloorScenes = FloorScenes,
|
||||
},
|
||||
onLoad: (chunk, data) =>
|
||||
{
|
||||
FloorScenes = data.FloorScenes;
|
||||
}
|
||||
);
|
||||
|
||||
GameChunk.AddChunk(MapChunk);
|
||||
GameChunk.AddChunk(MapChunk);
|
||||
|
||||
this.Provide();
|
||||
this.Provide();
|
||||
}
|
||||
|
||||
public void LoadMap()
|
||||
{
|
||||
foreach (var floor in _floors)
|
||||
FloorScenes.Add(floor.ResourcePath);
|
||||
foreach (var floor in _floors)
|
||||
FloorScenes.Add(floor.ResourcePath);
|
||||
|
||||
LoadFloor();
|
||||
CurrentFloor.InitializeDungeon();
|
||||
var transform = GetPlayerSpawnPosition();
|
||||
Player.TeleportPlayer(transform);
|
||||
CurrentFloor.FloorIsLoaded = true;
|
||||
Game.NextFloorLoaded();
|
||||
LoadFloor();
|
||||
CurrentFloor.InitializeDungeon();
|
||||
var transform = GetPlayerSpawnPosition();
|
||||
Player.TeleportPlayer(transform);
|
||||
CurrentFloor.FloorIsLoaded = true;
|
||||
Game.NextFloorLoaded();
|
||||
}
|
||||
|
||||
public void SpawnNextFloor()
|
||||
{
|
||||
var oldFloor = CurrentFloor;
|
||||
oldFloor.CallDeferred(MethodName.QueueFree, []);
|
||||
LoadFloor();
|
||||
CurrentFloor.InitializeDungeon();
|
||||
var transform = GetPlayerSpawnPosition();
|
||||
Player.TeleportPlayer(transform);
|
||||
CurrentFloor.FloorIsLoaded = true;
|
||||
Game.NextFloorLoaded();
|
||||
CurrentFloorNumber += 1;
|
||||
var oldFloor = CurrentFloor;
|
||||
oldFloor.CallDeferred(MethodName.QueueFree, []);
|
||||
LoadFloor();
|
||||
CurrentFloor.InitializeDungeon();
|
||||
var transform = GetPlayerSpawnPosition();
|
||||
Player.TeleportPlayer(transform);
|
||||
CurrentFloor.FloorIsLoaded = true;
|
||||
Game.NextFloorLoaded();
|
||||
CurrentFloorNumber += 1;
|
||||
}
|
||||
|
||||
public IDungeonRoom GetPlayersCurrentRoom()
|
||||
{
|
||||
var rooms = CurrentFloor.Rooms;
|
||||
var playersRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom);
|
||||
return playersRoom;
|
||||
var rooms = CurrentFloor.Rooms;
|
||||
var playersRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom);
|
||||
return playersRoom;
|
||||
}
|
||||
|
||||
public Transform3D GetPlayerSpawnPosition() => CurrentFloor.GetPlayerSpawnPoint();
|
||||
|
||||
private void LoadFloor()
|
||||
{
|
||||
var currentFloorScene = FloorScenes.First();
|
||||
var instantiator = new Instantiator(GetTree());
|
||||
var loadedScene = instantiator.LoadAndInstantiate<Node3D>(currentFloorScene);
|
||||
AddChild(loadedScene);
|
||||
CurrentFloor = (IDungeonFloor)loadedScene;
|
||||
FloorScenes.Remove(currentFloorScene);
|
||||
var currentFloorScene = FloorScenes.First();
|
||||
var instantiator = new Instantiator(GetTree());
|
||||
var loadedScene = instantiator.LoadAndInstantiate<Node3D>(currentFloorScene);
|
||||
AddChild(loadedScene);
|
||||
CurrentFloor = (IDungeonFloor)loadedScene;
|
||||
FloorScenes.Remove(currentFloorScene);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
|
||||
[node name="Map" type="Node3D"]
|
||||
script = ExtResource("1_bw70o")
|
||||
_floors = Array[PackedScene]([ExtResource("2_0m8h8"), ExtResource("2_merfv"), ExtResource("4_8y0oy"), ExtResource("5_uag72"), ExtResource("6_55rmo"), ExtResource("7_f6kwn"), ExtResource("8_ne2vg"), ExtResource("9_abpbr"), ExtResource("10_caf7v"), ExtResource("11_y74f3")])
|
||||
_floors = Array[PackedScene]([ExtResource("2_0m8h8"), ExtResource("11_y74f3"), ExtResource("2_merfv"), ExtResource("4_8y0oy"), ExtResource("5_uag72"), ExtResource("6_55rmo"), ExtResource("7_f6kwn"), ExtResource("8_ne2vg"), ExtResource("9_abpbr"), ExtResource("10_caf7v")])
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
@@ -24,41 +24,41 @@ public partial class DungeonFloor : Node3D, IDungeonFloor
|
||||
|
||||
public void InitializeDungeon()
|
||||
{
|
||||
Rooms = [];
|
||||
Rooms = FindAllDungeonRooms([.. GetChildren()], Rooms);
|
||||
_playerSpawnPoint = RandomizePlayerSpawnPoint();
|
||||
var monsterRooms = Rooms.OfType<MonsterRoom>();
|
||||
foreach (var room in monsterRooms)
|
||||
room.SpawnEnemies(EnemyDatabase);
|
||||
DungeonGenerator.EmitSignal("done_generating");
|
||||
Rooms = [];
|
||||
Rooms = FindAllDungeonRooms([.. GetChildren()], Rooms);
|
||||
_playerSpawnPoint = RandomizePlayerSpawnPoint();
|
||||
var monsterRooms = Rooms.OfType<MonsterRoom>();
|
||||
foreach (var room in monsterRooms)
|
||||
room.SpawnEnemies(EnemyDatabase);
|
||||
DungeonGenerator.EmitSignal("done_generating");
|
||||
}
|
||||
|
||||
public Transform3D GetPlayerSpawnPoint() => new Transform3D(_playerSpawnPoint.Basis, new Vector3(_playerSpawnPoint.Origin.X, -1.75f, _playerSpawnPoint.Origin.Z));
|
||||
|
||||
private Transform3D RandomizePlayerSpawnPoint()
|
||||
{
|
||||
var randomSpawnLocations = Rooms
|
||||
.OfType<MonsterRoom>()
|
||||
.Select(x => x.PlayerSpawn);
|
||||
var godotCollection = new Godot.Collections.Array<Marker3D>(randomSpawnLocations);
|
||||
var result = godotCollection.PickRandom();
|
||||
return result.GlobalTransform;
|
||||
var randomSpawnLocations = Rooms
|
||||
.OfType<MonsterRoom>()
|
||||
.Select(x => x.PlayerSpawn);
|
||||
var godotCollection = new Godot.Collections.Array<Marker3D>(randomSpawnLocations);
|
||||
var result = godotCollection.PickRandom();
|
||||
return result.GlobalTransform;
|
||||
}
|
||||
|
||||
private static ImmutableList<IDungeonRoom> FindAllDungeonRooms(List<Node> nodesToSearch, ImmutableList<IDungeonRoom> roomsFound)
|
||||
{
|
||||
if (nodesToSearch.Count == 0)
|
||||
return roomsFound;
|
||||
if (nodesToSearch.Count == 0)
|
||||
return roomsFound;
|
||||
|
||||
foreach (var node in nodesToSearch)
|
||||
{
|
||||
if (node is IDungeonRoom dungeonRoom)
|
||||
roomsFound = roomsFound.Add(dungeonRoom);
|
||||
foreach (var node in nodesToSearch)
|
||||
{
|
||||
if (node is IDungeonRoom dungeonRoom)
|
||||
roomsFound = roomsFound.Add(dungeonRoom);
|
||||
|
||||
if (node.HasSignal("dungeon_done_generating"))
|
||||
node.EmitSignal("dungeon_done_generating");
|
||||
}
|
||||
if (node.HasSignal("dungeon_done_generating"))
|
||||
node.EmitSignal("dungeon_done_generating");
|
||||
}
|
||||
|
||||
return FindAllDungeonRooms(nodesToSearch.SelectMany(x => x.GetChildren()).ToList(), roomsFound);
|
||||
return FindAllDungeonRooms(nodesToSearch.SelectMany(x => x.GetChildren()).ToList(), roomsFound);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=99 format=4 uid="uid://crf30tibwsnri"]
|
||||
[gd_scene load_steps=100 format=4 uid="uid://crf30tibwsnri"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ce73fuh74l81l" path="res://addons/SimpleDungeons/DungeonRoom3D.gd" id="1_bglxp"]
|
||||
[ext_resource type="Script" uid="uid://dhollu4j3pynq" path="res://src/map/dungeon/code/MonsterRoom.cs" id="2_5aadh"]
|
||||
@@ -30,6 +30,7 @@
|
||||
[ext_resource type="Texture2D" uid="uid://da42up4mv46kj" path="res://src/map/dungeon/models/Set A/16. Seshat's Room/16_A1_SESHATS_ROOM_claude-monet.jpg" id="24_t8nkf"]
|
||||
[ext_resource type="Material" uid="uid://bsafm3t4drpl" path="res://src/map/dungeon/textures/MinimapTexture.tres" id="25_25af7"]
|
||||
[ext_resource type="Texture2D" uid="uid://b5hbvxvxl8gn6" path="res://src/map/dungeon/models/Set A/16. Seshat's Room/16_A1_SESHATS_ROOM_Single-Peacock-Feather-Transparent-Free-PNG.png" id="25_77sl0"]
|
||||
[ext_resource type="Texture2D" uid="uid://bt1n54xtem20m" path="res://src/npc/Seshat/seshat.png" id="31_1cfoy"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_qg4wx"]
|
||||
resource_name = "Material.024"
|
||||
@@ -1073,6 +1074,7 @@ skeleton = NodePath("")
|
||||
|
||||
[node name="ROOM" type="MeshInstance3D" parent="Model/Seshat\'s Room/16_A1_SESHATS_ROOM"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7.18809, 14.7067, 47.3259)
|
||||
visible = false
|
||||
mesh = SubResource("ArrayMesh_1wv4u")
|
||||
skeleton = NodePath("")
|
||||
|
||||
@@ -1280,3 +1282,9 @@ mesh = SubResource("PlaneMesh_s0txx")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="NPC" type="Node3D" parent="."]
|
||||
|
||||
[node name="Sprite3D" type="Sprite3D" parent="NPC"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.967271, 0.0981301, -0.047853)
|
||||
pixel_size = 0.005
|
||||
billboard = 2
|
||||
texture = ExtResource("31_1cfoy")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=78 format=4 uid="uid://cw33vpar237pm"]
|
||||
[gd_scene load_steps=79 format=4 uid="uid://cw33vpar237pm"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ce73fuh74l81l" path="res://addons/SimpleDungeons/DungeonRoom3D.gd" id="1_m4la0"]
|
||||
[ext_resource type="Script" uid="uid://dhollu4j3pynq" path="res://src/map/dungeon/code/MonsterRoom.cs" id="2_56tk6"]
|
||||
@@ -28,6 +28,7 @@
|
||||
[ext_resource type="Texture2D" uid="uid://dgmxl2uu287k4" path="res://src/map/dungeon/models/Set A/17. Gesthemii's Room/17_A1_GESTHEMIIS_ROOM_outside_desert.png" id="21_6gfr6"]
|
||||
[ext_resource type="Texture2D" uid="uid://d0q55hxiafsye" path="res://src/map/dungeon/models/Set A/17. Gesthemii's Room/17_A1_GESTHEMIIS_ROOM_RUG_GETHSTEMI.png" id="22_uayj1"]
|
||||
[ext_resource type="Texture2D" uid="uid://dix6yhpcu52jv" path="res://src/map/dungeon/models/Set A/17. Gesthemii's Room/17_A1_GESTHEMIIS_ROOM_mottled.png" id="23_rrfdh"]
|
||||
[ext_resource type="PackedScene" uid="uid://b5tl2jawmvwtd" path="res://src/npc/Gesthesemii/Gesthemii.tscn" id="29_43nhx"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_loa1y"]
|
||||
resource_name = "Material.014"
|
||||
@@ -1036,3 +1037,8 @@ visible = false
|
||||
layers = 2
|
||||
mesh = SubResource("PlaneMesh_s0txx")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="NPC" type="Node3D" parent="."]
|
||||
|
||||
[node name="Gesthemii" parent="NPC" instance=ExtResource("29_43nhx")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0431279, -0.710172, 2.12679)
|
||||
|
||||
BIN
Zennysoft.Game.Ma/src/npc/Clalo/CLALO_ver.2.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
34
Zennysoft.Game.Ma/src/npc/Clalo/CLALO_ver.2.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://loeqa6twpa3q"
|
||||
path="res://.godot/imported/CLALO_ver.2.png-bd5f373ada3f179eabb413cfe6fbf703.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/npc/Clalo/CLALO_ver.2.png"
|
||||
dest_files=["res://.godot/imported/CLALO_ver.2.png-bd5f373ada3f179eabb413cfe6fbf703.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
|
||||
57
Zennysoft.Game.Ma/src/npc/Gesthesemii/Gesthemii.tscn
Normal file
@@ -0,0 +1,57 @@
|
||||
[gd_scene load_steps=7 format=3 uid="uid://b5tl2jawmvwtd"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dcqssoikr3pl7" path="res://src/npc/Npc.cs" id="1_d5tpe"]
|
||||
[ext_resource type="Resource" uid="uid://lao0opxww3ib" path="res://src/dialog/Dialogue.dialogue" id="2_xassj"]
|
||||
[ext_resource type="Texture2D" uid="uid://gtylrk5yxgnp" path="res://src/npc/Gesthesemii/gesthesemii2.png" id="3_xassj"]
|
||||
|
||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_wfhgc"]
|
||||
radius = 3.0
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_kg3qv"]
|
||||
radius = 0.837722
|
||||
height = 2.8375
|
||||
|
||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_nwuwj"]
|
||||
height = 2.24425
|
||||
radius = 1.941
|
||||
|
||||
[node name="Gesthemii" type="Node3D"]
|
||||
script = ExtResource("1_d5tpe")
|
||||
Dialogue = ExtResource("2_xassj")
|
||||
|
||||
[node name="Sprite" type="Sprite3D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0)
|
||||
gi_mode = 0
|
||||
pixel_size = 0.008
|
||||
billboard = 2
|
||||
double_sided = false
|
||||
alpha_cut = 2
|
||||
texture_filter = 0
|
||||
texture = ExtResource("3_xassj")
|
||||
|
||||
[node name="DialogueZone" type="Area3D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
collision_layer = 2
|
||||
collision_mask = 2
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="DialogueZone"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00131226, 0, -0.00723076)
|
||||
shape = SubResource("CylinderShape3D_wfhgc")
|
||||
|
||||
[node name="Collision" type="RigidBody3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.105047, -0.0490516, 0)
|
||||
collision_mask = 0
|
||||
gravity_scale = 0.0
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Collision"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.169075, 0, 0)
|
||||
shape = SubResource("CapsuleShape3D_kg3qv")
|
||||
|
||||
[node name="Hitbox" type="Area3D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
collision_layer = 16
|
||||
collision_mask = 16
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Hitbox"]
|
||||
shape = SubResource("CylinderShape3D_nwuwj")
|
||||
BIN
Zennysoft.Game.Ma/src/npc/Gesthesemii/gesthesemii2.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://gtylrk5yxgnp"
|
||||
path="res://.godot/imported/gesthesemii2.png-3d63416010cd48d84ed561821c69e40e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/npc/Gesthesemii/gesthesemii2.png"
|
||||
dest_files=["res://.godot/imported/gesthesemii2.png-3d63416010cd48d84ed561821c69e40e.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
|
||||
BIN
Zennysoft.Game.Ma/src/npc/Gesthesemii/gethesemii.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
34
Zennysoft.Game.Ma/src/npc/Gesthesemii/gethesemii.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b1mj13j2peypc"
|
||||
path="res://.godot/imported/gethesemii.png-8d75036e08b2192c219748544bae288b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/npc/Gesthesemii/gethesemii.png"
|
||||
dest_files=["res://.godot/imported/gethesemii.png-8d75036e08b2192c219748544bae288b.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
|
||||
|
After Width: | Height: | Size: 9.7 KiB |
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cojh7jjk70psy"
|
||||
path="res://.godot/imported/goddess-of-guidance.png-500677be7008aa69424d184c70c7ea1d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/npc/Goddess of Guidance/goddess-of-guidance.png"
|
||||
dest_files=["res://.godot/imported/goddess-of-guidance.png-500677be7008aa69424d184c70c7ea1d.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
|
||||
@@ -20,45 +20,45 @@ public partial class Npc : Node3D
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
SetPhysicsProcess(true);
|
||||
DialogueZone.BodyEntered += DialogueZone_BodyEntered;
|
||||
DialogueZone.BodyExited += DialogueZone_BodyExited;
|
||||
Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
SetPhysicsProcess(true);
|
||||
DialogueZone.BodyEntered += DialogueZone_BodyEntered;
|
||||
DialogueZone.BodyExited += DialogueZone_BodyExited;
|
||||
Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
|
||||
}
|
||||
|
||||
private void Hitbox_AreaEntered(Area3D area)
|
||||
{
|
||||
DialogueController.ShowDialogue(Dialogue, "hit");
|
||||
DialogueController.ShowDialogue(Dialogue, "hit");
|
||||
}
|
||||
|
||||
private void Hitbox_BodyEntered(Node body)
|
||||
{
|
||||
DialogueController.ShowDialogue(Dialogue, "hit");
|
||||
DialogueController.ShowDialogue(Dialogue, "hit");
|
||||
}
|
||||
|
||||
private void DialogueZone_BodyExited(Node3D body)
|
||||
{
|
||||
_isInDialogueZone = false;
|
||||
DialogueController.Interrupt();
|
||||
_isInDialogueZone = false;
|
||||
DialogueController.Interrupt();
|
||||
}
|
||||
|
||||
private void DialogueZone_BodyEntered(Node3D body)
|
||||
{
|
||||
_isInDialogueZone = true;
|
||||
_isInDialogueZone = true;
|
||||
}
|
||||
|
||||
public override void _UnhandledInput(InputEvent @event)
|
||||
{
|
||||
if (@event.IsActionPressed(GameInputs.Interact) && _isInDialogueZone)
|
||||
{
|
||||
if (_isIntroductionComplete)
|
||||
DialogueController.ShowDialogue(Dialogue, "general");
|
||||
else
|
||||
{
|
||||
DialogueController.ShowDialogue(Dialogue, "introduction");
|
||||
_isIntroductionComplete = true;
|
||||
}
|
||||
}
|
||||
if (@event.IsActionPressed(GameInputs.Interact) && _isInDialogueZone)
|
||||
{
|
||||
if (_isIntroductionComplete)
|
||||
DialogueController.ShowDialogue(Dialogue, "general");
|
||||
else
|
||||
{
|
||||
DialogueController.ShowDialogue(Dialogue, "introduction");
|
||||
_isIntroductionComplete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Zennysoft.Game.Ma/src/npc/Puer/PUER ver.2.PNG
Normal file
|
After Width: | Height: | Size: 16 KiB |
34
Zennysoft.Game.Ma/src/npc/Puer/PUER ver.2.PNG.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bdn7fs4ehxvf0"
|
||||
path="res://.godot/imported/PUER ver.2.PNG-d994334c306bcf9f2e5bdd3105f5e6d5.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/npc/Puer/PUER ver.2.PNG"
|
||||
dest_files=["res://.godot/imported/PUER ver.2.PNG-d994334c306bcf9f2e5bdd3105f5e6d5.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
|
||||
BIN
Zennysoft.Game.Ma/src/npc/Rat/rat_ver,2.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
34
Zennysoft.Game.Ma/src/npc/Rat/rat_ver,2.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dffyycokg2vcr"
|
||||
path="res://.godot/imported/rat_ver,2.png-f6e59ef09a403a1c5118efc205d6e0aa.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/npc/Rat/rat_ver,2.png"
|
||||
dest_files=["res://.godot/imported/rat_ver,2.png-f6e59ef09a403a1c5118efc205d6e0aa.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
|
||||
BIN
Zennysoft.Game.Ma/src/npc/Seshat/seshat.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
34
Zennysoft.Game.Ma/src/npc/Seshat/seshat.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bt1n54xtem20m"
|
||||
path="res://.godot/imported/seshat.png-02a4b362f584ce2171e108b824412341.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/npc/Seshat/seshat.png"
|
||||
dest_files=["res://.godot/imported/seshat.png-02a4b362f584ce2171e108b824412341.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
|
||||
@@ -20,7 +20,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
||||
|
||||
private PlayerLogic.IBinding PlayerBinding { get; set; } = default!;
|
||||
|
||||
[Dependency] private IGameRepo _gameRepo => this.DependOn<IGameRepo>();
|
||||
[Dependency] private IGameRepo _gameRepo => this.DependOn<IGameRepo>(() => new GameRepo());
|
||||
#endregion
|
||||
|
||||
#region Save
|
||||
@@ -106,508 +106,508 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
||||
#region Initialization
|
||||
public void Initialize()
|
||||
{
|
||||
AnimationPlayer.AnimationFinished += OnAnimationFinished;
|
||||
_expToNextLevel = new Dictionary<int, int>
|
||||
{
|
||||
{ 2, 12 },
|
||||
{ 3, 39 },
|
||||
{ 4, 87 },
|
||||
{ 5, 162 },
|
||||
{ 6, 270 },
|
||||
{ 7, 417 },
|
||||
{ 8, 609 }
|
||||
};
|
||||
AnimationPlayer.AnimationFinished += OnAnimationFinished;
|
||||
_expToNextLevel = new Dictionary<int, int>
|
||||
{
|
||||
{ 2, 12 },
|
||||
{ 3, 39 },
|
||||
{ 4, 87 },
|
||||
{ 5, 162 },
|
||||
{ 6, 270 },
|
||||
{ 7, 417 },
|
||||
{ 8, 609 }
|
||||
};
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
var container = new SimpleInjector.Container();
|
||||
container.Register<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton);
|
||||
container.Verify();
|
||||
var container = new SimpleInjector.Container();
|
||||
container.Register<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton);
|
||||
container.Verify();
|
||||
|
||||
Settings = new PlayerLogic.Settings() { RotationSpeed = PlayerStatResource.RotationSpeed, MoveSpeed = PlayerStatResource.MoveSpeed, Acceleration = PlayerStatResource.Acceleration };
|
||||
Stats = new PlayerStatController();
|
||||
Stats.Init(
|
||||
new PlayerStats
|
||||
{
|
||||
CurrentHP = PlayerStatResource.CurrentHP,
|
||||
MaximumHP = PlayerStatResource.MaximumHP,
|
||||
CurrentVT = PlayerStatResource.CurrentVT,
|
||||
MaximumVT = PlayerStatResource.MaximumVT,
|
||||
CurrentAttack = PlayerStatResource.CurrentAttack,
|
||||
BonusAttack = PlayerStatResource.BonusAttack,
|
||||
MaxAttack = PlayerStatResource.MaxAttack,
|
||||
CurrentDefense = PlayerStatResource.CurrentDefense,
|
||||
BonusDefense = PlayerStatResource.BonusDefense,
|
||||
MaxDefense = PlayerStatResource.MaxDefense,
|
||||
CurrentExp = PlayerStatResource.CurrentExp,
|
||||
CurrentLevel = PlayerStatResource.CurrentLevel,
|
||||
ExpToNextLevel = PlayerStatResource.ExpToNextLevel,
|
||||
Luck = PlayerStatResource.Luck
|
||||
});
|
||||
Settings = new PlayerLogic.Settings() { RotationSpeed = PlayerStatResource.RotationSpeed, MoveSpeed = PlayerStatResource.MoveSpeed, Acceleration = PlayerStatResource.Acceleration };
|
||||
Stats = new PlayerStatController();
|
||||
Stats.Init(
|
||||
new PlayerStats
|
||||
{
|
||||
CurrentHP = PlayerStatResource.CurrentHP,
|
||||
MaximumHP = PlayerStatResource.MaximumHP,
|
||||
CurrentVT = PlayerStatResource.CurrentVT,
|
||||
MaximumVT = PlayerStatResource.MaximumVT,
|
||||
CurrentAttack = PlayerStatResource.CurrentAttack,
|
||||
BonusAttack = PlayerStatResource.BonusAttack,
|
||||
MaxAttack = PlayerStatResource.MaxAttack,
|
||||
CurrentDefense = PlayerStatResource.CurrentDefense,
|
||||
BonusDefense = PlayerStatResource.BonusDefense,
|
||||
MaxDefense = PlayerStatResource.MaxDefense,
|
||||
CurrentExp = PlayerStatResource.CurrentExp,
|
||||
CurrentLevel = PlayerStatResource.CurrentLevel,
|
||||
ExpToNextLevel = PlayerStatResource.ExpToNextLevel,
|
||||
Luck = PlayerStatResource.Luck
|
||||
});
|
||||
|
||||
Inventory = new Inventory();
|
||||
Inventory = new Inventory();
|
||||
|
||||
PlayerLogic = container.GetInstance<IPlayerLogic>();
|
||||
PlayerLogic.Set(this as IPlayer);
|
||||
PlayerLogic.Set(Settings);
|
||||
PlayerLogic.Set(Stats);
|
||||
PlayerLogic.Set(_gameRepo);
|
||||
PlayerLogic = container.GetInstance<IPlayerLogic>();
|
||||
PlayerLogic.Set(this as IPlayer);
|
||||
PlayerLogic.Set(Settings);
|
||||
PlayerLogic.Set(Stats);
|
||||
PlayerLogic.Set(_gameRepo);
|
||||
|
||||
var defaultWeapon = new Weapon();
|
||||
defaultWeapon.Stats = _defaultWeapon;
|
||||
var defaultArmor = new Armor();
|
||||
defaultArmor.Stats = _defaultArmor;
|
||||
Inventory.TryAdd(defaultWeapon);
|
||||
Inventory.TryAdd(defaultArmor);
|
||||
var defaultWeapon = new Weapon();
|
||||
defaultWeapon.Stats = _defaultWeapon;
|
||||
var defaultArmor = new Armor();
|
||||
defaultArmor.Stats = _defaultArmor;
|
||||
Inventory.TryAdd(defaultWeapon);
|
||||
Inventory.TryAdd(defaultArmor);
|
||||
|
||||
EquippedWeapon.Sync += EquippedWeapon_Sync;
|
||||
EquippedArmor.Sync += EquippedArmor_Sync;
|
||||
EquippedAccessory.Sync += EquippedAccessory_Sync;
|
||||
Stats.CurrentHP.Sync += CurrentHP_Sync;
|
||||
Stats.CurrentExp.Sync += CurrentEXP_Sync;
|
||||
EquippedWeapon.Sync += EquippedWeapon_Sync;
|
||||
EquippedArmor.Sync += EquippedArmor_Sync;
|
||||
EquippedAccessory.Sync += EquippedAccessory_Sync;
|
||||
Stats.CurrentHP.Sync += CurrentHP_Sync;
|
||||
Stats.CurrentExp.Sync += CurrentEXP_Sync;
|
||||
|
||||
Equip(defaultWeapon);
|
||||
Equip(defaultArmor);
|
||||
Equip(defaultWeapon);
|
||||
Equip(defaultArmor);
|
||||
|
||||
HealthTimer.WaitTime = _healthTimerWaitTime;
|
||||
HealthTimer.Timeout += OnHealthTimerTimeout;
|
||||
Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
|
||||
HealthTimer.WaitTime = _healthTimerWaitTime;
|
||||
HealthTimer.Timeout += OnHealthTimerTimeout;
|
||||
Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
|
||||
}
|
||||
|
||||
public void OnResolved()
|
||||
{
|
||||
PlayerChunk = new SaveChunk<PlayerData>(
|
||||
onSave: (chunk) => new PlayerData()
|
||||
{
|
||||
PlayerStats = new PlayerStats()
|
||||
{
|
||||
CurrentHP = Stats.CurrentHP.Value,
|
||||
MaximumHP = Stats.MaximumHP.Value,
|
||||
CurrentVT = Stats.CurrentVT.Value,
|
||||
MaximumVT = Stats.MaximumVT.Value,
|
||||
CurrentAttack = Stats.CurrentAttack.Value,
|
||||
BonusAttack = Stats.BonusAttack.Value,
|
||||
MaxAttack = Stats.MaxAttack.Value,
|
||||
CurrentDefense = Stats.CurrentDefense.Value,
|
||||
BonusDefense = Stats.BonusDefense.Value,
|
||||
MaxDefense = Stats.MaxDefense.Value,
|
||||
CurrentExp = Stats.CurrentExp.Value,
|
||||
CurrentLevel = Stats.CurrentLevel.Value,
|
||||
ExpToNextLevel = Stats.ExpToNextLevel.Value,
|
||||
Luck = Stats.Luck.Value
|
||||
},
|
||||
Inventory = Inventory
|
||||
},
|
||||
onLoad: (chunk, data) =>
|
||||
{
|
||||
Stats.Init(data.PlayerStats);
|
||||
Inventory = data.Inventory;
|
||||
}
|
||||
);
|
||||
PlayerChunk = new SaveChunk<PlayerData>(
|
||||
onSave: (chunk) => new PlayerData()
|
||||
{
|
||||
PlayerStats = new PlayerStats()
|
||||
{
|
||||
CurrentHP = Stats.CurrentHP.Value,
|
||||
MaximumHP = Stats.MaximumHP.Value,
|
||||
CurrentVT = Stats.CurrentVT.Value,
|
||||
MaximumVT = Stats.MaximumVT.Value,
|
||||
CurrentAttack = Stats.CurrentAttack.Value,
|
||||
BonusAttack = Stats.BonusAttack.Value,
|
||||
MaxAttack = Stats.MaxAttack.Value,
|
||||
CurrentDefense = Stats.CurrentDefense.Value,
|
||||
BonusDefense = Stats.BonusDefense.Value,
|
||||
MaxDefense = Stats.MaxDefense.Value,
|
||||
CurrentExp = Stats.CurrentExp.Value,
|
||||
CurrentLevel = Stats.CurrentLevel.Value,
|
||||
ExpToNextLevel = Stats.ExpToNextLevel.Value,
|
||||
Luck = Stats.Luck.Value
|
||||
},
|
||||
Inventory = Inventory
|
||||
},
|
||||
onLoad: (chunk, data) =>
|
||||
{
|
||||
Stats.Init(data.PlayerStats);
|
||||
Inventory = data.Inventory;
|
||||
}
|
||||
);
|
||||
|
||||
PlayerBinding = PlayerLogic.Bind();
|
||||
PlayerBinding = PlayerLogic.Bind();
|
||||
|
||||
PlayerBinding
|
||||
.Handle((in PlayerLogic.Output.Animations.Attack output) =>
|
||||
{
|
||||
if (PlayerIsHittingGeometry())
|
||||
{
|
||||
AnimationPlayer.Play("hit_wall");
|
||||
_gameRepo.OnPlayerAttackedWall();
|
||||
}
|
||||
else
|
||||
{
|
||||
var attackSpeed = ((Weapon)EquippedWeapon.Value).AttackSpeed;
|
||||
AnimationPlayer.SetSpeedScale((float)attackSpeed);
|
||||
AnimationPlayer.Play("attack");
|
||||
_gameRepo.OnPlayerAttack();
|
||||
}
|
||||
})
|
||||
.Handle((in PlayerLogic.Output.ThrowItem output) =>
|
||||
{
|
||||
})
|
||||
.Handle((in PlayerLogic.Output.Move output) =>
|
||||
{
|
||||
Move(output.delta);
|
||||
});
|
||||
PlayerBinding
|
||||
.Handle((in PlayerLogic.Output.Animations.Attack output) =>
|
||||
{
|
||||
if (PlayerIsHittingGeometry())
|
||||
{
|
||||
AnimationPlayer.Play("hit_wall");
|
||||
_gameRepo.OnPlayerAttackedWall();
|
||||
}
|
||||
else
|
||||
{
|
||||
var attackSpeed = ((Weapon)EquippedWeapon.Value).AttackSpeed;
|
||||
AnimationPlayer.SetSpeedScale((float)attackSpeed);
|
||||
AnimationPlayer.Play("attack");
|
||||
_gameRepo.OnPlayerAttack();
|
||||
}
|
||||
})
|
||||
.Handle((in PlayerLogic.Output.ThrowItem output) =>
|
||||
{
|
||||
})
|
||||
.Handle((in PlayerLogic.Output.Move output) =>
|
||||
{
|
||||
Move(output.delta);
|
||||
});
|
||||
|
||||
GameChunk.AddChunk(PlayerChunk);
|
||||
GameChunk.AddChunk(PlayerChunk);
|
||||
|
||||
PlayerLogic.Start();
|
||||
this.Provide();
|
||||
PlayerLogic.Start();
|
||||
this.Provide();
|
||||
}
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
SetPhysicsProcess(true);
|
||||
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
|
||||
SetPhysicsProcess(true);
|
||||
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Attack()
|
||||
{
|
||||
PlayerLogic.Input(new PlayerLogic.Input.Attack());
|
||||
PlayerLogic.Input(new PlayerLogic.Input.Attack());
|
||||
}
|
||||
|
||||
public void PlayerPause()
|
||||
{
|
||||
Game.TogglePause();
|
||||
Game.TogglePause();
|
||||
}
|
||||
|
||||
public void RaiseHP(int amountToRaise)
|
||||
{
|
||||
Stats.SetMaximumHP(Stats.MaximumHP.Value + amountToRaise);
|
||||
Stats.SetCurrentHP(Stats.MaximumHP.Value);
|
||||
_gameRepo.AnnounceMessageInInventory($"{amountToRaise}MAXHP Up.");
|
||||
Stats.SetMaximumHP(Stats.MaximumHP.Value + amountToRaise);
|
||||
Stats.SetCurrentHP(Stats.MaximumHP.Value);
|
||||
_gameRepo.AnnounceMessageInInventory($"{amountToRaise}MAXHP Up.");
|
||||
}
|
||||
|
||||
public void HealHP(int amountToRestore)
|
||||
{
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value + amountToRestore);
|
||||
var raiseString = amountToRestore == 1000 ? "MAX" : $"{amountToRestore}";
|
||||
_gameRepo.AnnounceMessageInInventory($"{raiseString}HP Restored.");
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value + amountToRestore);
|
||||
var raiseString = amountToRestore == 1000 ? "MAX" : $"{amountToRestore}";
|
||||
_gameRepo.AnnounceMessageInInventory($"{raiseString}HP Restored.");
|
||||
}
|
||||
|
||||
public void RaiseVT(int amountToRaise)
|
||||
{
|
||||
if (Stats.CurrentVT == Stats.MaximumVT)
|
||||
{
|
||||
Stats.SetMaximumVT(Stats.MaximumVT.Value + amountToRaise);
|
||||
Stats.SetCurrentVT(Stats.MaximumVT.Value);
|
||||
_gameRepo.AnnounceMessageInInventory($"{amountToRaise}MAXVT Up.");
|
||||
}
|
||||
if (Stats.CurrentVT == Stats.MaximumVT)
|
||||
{
|
||||
Stats.SetMaximumVT(Stats.MaximumVT.Value + amountToRaise);
|
||||
Stats.SetCurrentVT(Stats.MaximumVT.Value);
|
||||
_gameRepo.AnnounceMessageInInventory($"{amountToRaise}MAXVT Up.");
|
||||
}
|
||||
}
|
||||
|
||||
public void HealVT(int amountToRestore)
|
||||
{
|
||||
Stats.SetCurrentVT(Stats.CurrentVT.Value + amountToRestore);
|
||||
var raiseString = amountToRestore == 1000 ? "MAX" : $"{amountToRestore}";
|
||||
_gameRepo.AnnounceMessageInInventory($"{raiseString}VT Restored.");
|
||||
Stats.SetCurrentVT(Stats.CurrentVT.Value + amountToRestore);
|
||||
var raiseString = amountToRestore == 1000 ? "MAX" : $"{amountToRestore}";
|
||||
_gameRepo.AnnounceMessageInInventory($"{raiseString}VT Restored.");
|
||||
}
|
||||
|
||||
public void ModifyBonusAttack(int amount)
|
||||
{
|
||||
Stats.SetBonusAttack(Stats.BonusAttack.Value + amount);
|
||||
Stats.SetBonusAttack(Stats.BonusAttack.Value + amount);
|
||||
}
|
||||
|
||||
public void ModifyBonusDefense(int amount)
|
||||
{
|
||||
Stats.SetBonusDefense(Stats.BonusDefense.Value + amount);
|
||||
Stats.SetBonusDefense(Stats.BonusDefense.Value + amount);
|
||||
}
|
||||
|
||||
public void ModifyMaximumHP(int amount)
|
||||
{
|
||||
Stats.SetMaximumHP(Stats.MaximumHP.Value + amount);
|
||||
Stats.SetMaximumHP(Stats.MaximumHP.Value + amount);
|
||||
}
|
||||
|
||||
public void ModifyMaximumVT(int amount)
|
||||
{
|
||||
Stats.SetMaximumVT(Stats.MaximumVT.Value + amount);
|
||||
Stats.SetMaximumVT(Stats.MaximumVT.Value + amount);
|
||||
}
|
||||
|
||||
public void ModifyBonusLuck(double amount)
|
||||
{
|
||||
Stats.SetLuck(Stats.Luck.Value + amount);
|
||||
Stats.SetLuck(Stats.Luck.Value + amount);
|
||||
}
|
||||
|
||||
public void Move(float delta)
|
||||
{
|
||||
var rawInput = GlobalInputVector;
|
||||
var strafeLeftInput = LeftStrafeInputVector;
|
||||
var strafeRightInput = RightStrafeInputVector;
|
||||
var rawInput = GlobalInputVector;
|
||||
var strafeLeftInput = LeftStrafeInputVector;
|
||||
var strafeRightInput = RightStrafeInputVector;
|
||||
|
||||
var transform = Transform;
|
||||
transform.Basis = new Basis(Vector3.Up, Settings.RotationSpeed * -rawInput.X * delta) * transform.Basis;
|
||||
var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z).Normalized();
|
||||
var velocity = Basis * moveDirection * Settings.MoveSpeed * Settings.Acceleration;
|
||||
_knockbackStrength = _knockbackStrength * 0.9f;
|
||||
Transform = Transform with { Basis = transform.Basis };
|
||||
Velocity = velocity + (_knockbackDirection * _knockbackStrength);
|
||||
MoveAndSlide();
|
||||
var transform = Transform;
|
||||
transform.Basis = new Basis(Vector3.Up, Settings.RotationSpeed * -rawInput.X * delta) * transform.Basis;
|
||||
var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z).Normalized();
|
||||
var velocity = Basis * moveDirection * Settings.MoveSpeed * Settings.Acceleration;
|
||||
_knockbackStrength = _knockbackStrength * 0.9f;
|
||||
Transform = Transform with { Basis = transform.Basis };
|
||||
Velocity = velocity + (_knockbackDirection * _knockbackStrength);
|
||||
MoveAndSlide();
|
||||
}
|
||||
|
||||
public void TeleportPlayer(Transform3D newTransform)
|
||||
{
|
||||
Transform = newTransform;
|
||||
Transform = newTransform;
|
||||
}
|
||||
|
||||
public void TakeDamage(double damage, ElementType elementType, bool isCriticalHit = false)
|
||||
{
|
||||
if (Stats.CurrentHP.Value > 0)
|
||||
{
|
||||
damage = CalculateDefenseResistance(damage);
|
||||
if (isCriticalHit)
|
||||
damage *= 2;
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value - (int)damage);
|
||||
}
|
||||
if (Stats.CurrentHP.Value > 0)
|
||||
{
|
||||
damage = CalculateDefenseResistance(damage);
|
||||
if (isCriticalHit)
|
||||
damage *= 2;
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value - (int)damage);
|
||||
}
|
||||
}
|
||||
|
||||
public void Knockback(float impulse)
|
||||
{
|
||||
_knockbackStrength = impulse;
|
||||
_knockbackDirection = GlobalBasis.Z.Normalized();
|
||||
_knockbackStrength = impulse;
|
||||
_knockbackDirection = GlobalBasis.Z.Normalized();
|
||||
}
|
||||
|
||||
public void GainExp(double expGained)
|
||||
{
|
||||
Stats.SetCurrentExp(Stats.CurrentExp.Value + expGained);
|
||||
Stats.SetCurrentExp(Stats.CurrentExp.Value + expGained);
|
||||
}
|
||||
|
||||
public void LevelUp()
|
||||
{
|
||||
var nextLevel = Stats.CurrentLevel.Value + 1;
|
||||
var expToNextLevel = _expToNextLevel[nextLevel];
|
||||
var newCurrentExp = Mathf.Max(Stats.CurrentExp.Value - Stats.ExpToNextLevel.Value, 0);
|
||||
Stats.SetCurrentLevel(nextLevel);
|
||||
Stats.SetExpToNextLevel(expToNextLevel);
|
||||
Stats.SetCurrentExp(newCurrentExp);
|
||||
var nextLevel = Stats.CurrentLevel.Value + 1;
|
||||
var expToNextLevel = _expToNextLevel[nextLevel];
|
||||
var newCurrentExp = Mathf.Max(Stats.CurrentExp.Value - Stats.ExpToNextLevel.Value, 0);
|
||||
Stats.SetCurrentLevel(nextLevel);
|
||||
Stats.SetExpToNextLevel(expToNextLevel);
|
||||
Stats.SetCurrentExp(newCurrentExp);
|
||||
}
|
||||
|
||||
public void Die() => PlayerLogic.Input(new PlayerLogic.Input.Die());
|
||||
|
||||
public override void _UnhandledInput(InputEvent @event)
|
||||
{
|
||||
if (@event.IsActionPressed(GameInputs.Pause))
|
||||
PlayerPause();
|
||||
if (@event.IsActionPressed(GameInputs.Pause))
|
||||
PlayerPause();
|
||||
|
||||
if (@event.IsActionPressed(GameInputs.Attack))
|
||||
Attack();
|
||||
if (@event.IsActionPressed(GameInputs.Attack))
|
||||
Attack();
|
||||
}
|
||||
|
||||
public void OnPhysicsProcess(double delta)
|
||||
{
|
||||
PlayerLogic.Input(new PlayerLogic.Input.PhysicsTick(delta));
|
||||
PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform));
|
||||
PlayerLogic.Input(new PlayerLogic.Input.PhysicsTick(delta));
|
||||
PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform));
|
||||
}
|
||||
|
||||
public void Equip(EquipableItem equipable)
|
||||
{
|
||||
if (equipable is Weapon weapon)
|
||||
{
|
||||
Unequip(_equippedWeapon.Value);
|
||||
weapon.IsEquipped = true;
|
||||
_equippedWeapon.OnNext(weapon);
|
||||
}
|
||||
else if (equipable is Armor armor)
|
||||
{
|
||||
Unequip(_equippedArmor.Value);
|
||||
armor.IsEquipped = true;
|
||||
_equippedArmor.OnNext(armor);
|
||||
}
|
||||
else if (equipable is Accessory accessory)
|
||||
{
|
||||
Unequip(_equippedAccessory.Value);
|
||||
accessory.IsEquipped = true;
|
||||
_equippedAccessory.OnNext(accessory);
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException("Item type is not supported.");
|
||||
if (equipable is Weapon weapon)
|
||||
{
|
||||
Unequip(_equippedWeapon.Value);
|
||||
weapon.IsEquipped = true;
|
||||
_equippedWeapon.OnNext(weapon);
|
||||
}
|
||||
else if (equipable is Armor armor)
|
||||
{
|
||||
Unequip(_equippedArmor.Value);
|
||||
armor.IsEquipped = true;
|
||||
_equippedArmor.OnNext(armor);
|
||||
}
|
||||
else if (equipable is Accessory accessory)
|
||||
{
|
||||
Unequip(_equippedAccessory.Value);
|
||||
accessory.IsEquipped = true;
|
||||
_equippedAccessory.OnNext(accessory);
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException("Item type is not supported.");
|
||||
}
|
||||
|
||||
public void Unequip(EquipableItem equipable)
|
||||
{
|
||||
if (equipable is Weapon weapon)
|
||||
{
|
||||
weapon.IsEquipped = false;
|
||||
ModifyBonusAttack(-weapon.Damage);
|
||||
_equippedWeapon.OnNext(new Weapon());
|
||||
}
|
||||
else if (equipable is Armor armor)
|
||||
{
|
||||
armor.IsEquipped = false;
|
||||
ModifyBonusDefense(-armor.Defense);
|
||||
_equippedArmor.OnNext(new Armor());
|
||||
}
|
||||
else if (equipable is Accessory accessory)
|
||||
{
|
||||
accessory.IsEquipped = false;
|
||||
ModifyMaximumHP(-accessory.MaxHPUp);
|
||||
ModifyMaximumVT(-accessory.MaxVTUp);
|
||||
ModifyBonusAttack(-accessory.ATKUp);
|
||||
ModifyBonusDefense(-accessory.DEFUp);
|
||||
ModifyBonusLuck(-accessory.LuckUp);
|
||||
_equippedAccessory.OnNext(new Accessory());
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException("Item type is not supported.");
|
||||
if (equipable is Weapon weapon)
|
||||
{
|
||||
weapon.IsEquipped = false;
|
||||
ModifyBonusAttack(-weapon.Damage);
|
||||
_equippedWeapon.OnNext(new Weapon());
|
||||
}
|
||||
else if (equipable is Armor armor)
|
||||
{
|
||||
armor.IsEquipped = false;
|
||||
ModifyBonusDefense(-armor.Defense);
|
||||
_equippedArmor.OnNext(new Armor());
|
||||
}
|
||||
else if (equipable is Accessory accessory)
|
||||
{
|
||||
accessory.IsEquipped = false;
|
||||
ModifyMaximumHP(-accessory.MaxHPUp);
|
||||
ModifyMaximumVT(-accessory.MaxVTUp);
|
||||
ModifyBonusAttack(-accessory.ATKUp);
|
||||
ModifyBonusDefense(-accessory.DEFUp);
|
||||
ModifyBonusLuck(-accessory.LuckUp);
|
||||
_equippedAccessory.OnNext(new Accessory());
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException("Item type is not supported.");
|
||||
|
||||
if (equipable.ItemTag == ItemTag.BreaksOnChange)
|
||||
Inventory.Remove(equipable);
|
||||
if (equipable.ItemTag == ItemTag.BreaksOnChange)
|
||||
Inventory.Remove(equipable);
|
||||
}
|
||||
|
||||
private static Vector3 GlobalInputVector
|
||||
{
|
||||
get
|
||||
{
|
||||
var rawInput = Input.GetVector(GameInputs.MoveLeft, GameInputs.MoveRight, GameInputs.MoveUp, GameInputs.MoveDown);
|
||||
var input = new Vector3
|
||||
{
|
||||
X = rawInput.X,
|
||||
Z = rawInput.Y
|
||||
};
|
||||
return input with { Y = 0f };
|
||||
}
|
||||
get
|
||||
{
|
||||
var rawInput = Input.GetVector(GameInputs.MoveLeft, GameInputs.MoveRight, GameInputs.MoveUp, GameInputs.MoveDown);
|
||||
var input = new Vector3
|
||||
{
|
||||
X = rawInput.X,
|
||||
Z = rawInput.Y
|
||||
};
|
||||
return input with { Y = 0f };
|
||||
}
|
||||
}
|
||||
|
||||
private static float LeftStrafeInputVector
|
||||
{
|
||||
get
|
||||
{
|
||||
return Input.GetActionStrength(GameInputs.StrafeLeft);
|
||||
}
|
||||
get
|
||||
{
|
||||
return Input.GetActionStrength(GameInputs.StrafeLeft);
|
||||
}
|
||||
}
|
||||
|
||||
private static float RightStrafeInputVector
|
||||
{
|
||||
get
|
||||
{
|
||||
return Input.GetActionStrength(GameInputs.StrafeRight);
|
||||
}
|
||||
get
|
||||
{
|
||||
return Input.GetActionStrength(GameInputs.StrafeRight);
|
||||
}
|
||||
}
|
||||
|
||||
private void ThrowItem()
|
||||
{
|
||||
var itemScene = GD.Load<PackedScene>("res://src/items/throwable/ThrowableItem.tscn");
|
||||
var throwItem = itemScene.Instantiate<ThrowableItem>();
|
||||
GetTree().Root.AddChildEx(throwItem);
|
||||
throwItem.GlobalPosition = CurrentPosition + new Vector3(0, 3.5f, 0);
|
||||
throwItem.GlobalRotation = GlobalRotation;
|
||||
var itemScene = GD.Load<PackedScene>("res://src/items/throwable/ThrowableItem.tscn");
|
||||
var throwItem = itemScene.Instantiate<ThrowableItem>();
|
||||
GetTree().Root.AddChildEx(throwItem);
|
||||
throwItem.GlobalPosition = CurrentPosition + new Vector3(0, 3.5f, 0);
|
||||
throwItem.GlobalRotation = GlobalRotation;
|
||||
}
|
||||
|
||||
private void OnAnimationFinished(StringName animation)
|
||||
{
|
||||
PlayerLogic.Input(new PlayerLogic.Input.AttackAnimationFinished());
|
||||
PlayerLogic.Input(new PlayerLogic.Input.AttackAnimationFinished());
|
||||
}
|
||||
|
||||
private void OnExitTree()
|
||||
{
|
||||
PlayerLogic.Stop();
|
||||
PlayerBinding.Dispose();
|
||||
AnimationPlayer.AnimationFinished -= OnAnimationFinished;
|
||||
PlayerLogic.Stop();
|
||||
PlayerBinding.Dispose();
|
||||
AnimationPlayer.AnimationFinished -= OnAnimationFinished;
|
||||
}
|
||||
|
||||
private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition;
|
||||
|
||||
private void OnHealthTimerTimeout()
|
||||
{
|
||||
if (Stats.CurrentHP.Value <= 0)
|
||||
return;
|
||||
if (Stats.CurrentHP.Value <= 0)
|
||||
return;
|
||||
|
||||
if (Stats.CurrentVT.Value > 0)
|
||||
{
|
||||
if (((Accessory)EquippedAccessory.Value).AccessoryTag == AccessoryTag.HalfVTConsumption)
|
||||
{
|
||||
reduceOnTick = !reduceOnTick;
|
||||
}
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value + 1);
|
||||
if (reduceOnTick)
|
||||
Stats.SetCurrentVT(Stats.CurrentVT.Value - 1);
|
||||
}
|
||||
else
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value - 1);
|
||||
if (Stats.CurrentVT.Value > 0)
|
||||
{
|
||||
if (((Accessory)EquippedAccessory.Value).AccessoryTag == AccessoryTag.HalfVTConsumption)
|
||||
{
|
||||
reduceOnTick = !reduceOnTick;
|
||||
}
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value + 1);
|
||||
if (reduceOnTick)
|
||||
Stats.SetCurrentVT(Stats.CurrentVT.Value - 1);
|
||||
}
|
||||
else
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value - 1);
|
||||
}
|
||||
|
||||
private void EquippedWeapon_Sync(EquipableItem obj)
|
||||
{
|
||||
ModifyBonusAttack(((Weapon)obj).Damage);
|
||||
ModifyBonusAttack(((Weapon)obj).Damage);
|
||||
}
|
||||
|
||||
private void EquippedArmor_Sync(EquipableItem obj)
|
||||
{
|
||||
ModifyBonusDefense(((Armor)obj).Defense);
|
||||
ModifyBonusDefense(((Armor)obj).Defense);
|
||||
}
|
||||
|
||||
private void EquippedAccessory_Sync(EquipableItem accessory)
|
||||
{
|
||||
ModifyMaximumHP(((Accessory)accessory).MaxHPUp);
|
||||
ModifyMaximumVT(((Accessory)accessory).MaxVTUp);
|
||||
ModifyBonusAttack(((Accessory)accessory).ATKUp);
|
||||
ModifyBonusDefense(((Accessory)accessory).DEFUp);
|
||||
ModifyBonusLuck(((Accessory)accessory).LuckUp);
|
||||
ModifyMaximumHP(((Accessory)accessory).MaxHPUp);
|
||||
ModifyMaximumVT(((Accessory)accessory).MaxVTUp);
|
||||
ModifyBonusAttack(((Accessory)accessory).ATKUp);
|
||||
ModifyBonusDefense(((Accessory)accessory).DEFUp);
|
||||
ModifyBonusLuck(((Accessory)accessory).LuckUp);
|
||||
}
|
||||
|
||||
private void CurrentHP_Sync(int newHealth)
|
||||
{
|
||||
if (newHealth <= 0)
|
||||
Die();
|
||||
if (newHealth <= 0)
|
||||
Die();
|
||||
}
|
||||
|
||||
private void CurrentEXP_Sync(double newExp)
|
||||
{
|
||||
if (Stats.CurrentExp.Value >= Stats.ExpToNextLevel.Value)
|
||||
LevelUp();
|
||||
if (Stats.CurrentExp.Value >= Stats.ExpToNextLevel.Value)
|
||||
LevelUp();
|
||||
}
|
||||
|
||||
private double CalculateDefenseResistance(double incomingDamage)
|
||||
{
|
||||
return Mathf.Max(incomingDamage - Stats.CurrentDefense.Value - Stats.BonusDefense.Value, 0.0);
|
||||
return Mathf.Max(incomingDamage - Stats.CurrentDefense.Value - Stats.BonusDefense.Value, 0.0);
|
||||
}
|
||||
|
||||
private void Hitbox_AreaEntered(Area3D area)
|
||||
{
|
||||
var target = area.GetOwner();
|
||||
if (target is IEnemy enemy)
|
||||
HitEnemy(enemy);
|
||||
var target = area.GetOwner();
|
||||
if (target is IEnemy enemy)
|
||||
HitEnemy(enemy);
|
||||
}
|
||||
|
||||
private void HitEnemy(IEnemy enemy)
|
||||
{
|
||||
var attackValue = Stats.CurrentAttack.Value + Stats.BonusAttack.Value;
|
||||
var ignoreElementalResistance = ((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.IgnoreAffinity;
|
||||
var isCriticalHit = BattleExtensions.IsCriticalHit(Stats.Luck.Value);
|
||||
var element = ((Weapon)EquippedWeapon.Value).WeaponElement;
|
||||
var attackValue = Stats.CurrentAttack.Value + Stats.BonusAttack.Value;
|
||||
var ignoreElementalResistance = ((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.IgnoreAffinity;
|
||||
var isCriticalHit = BattleExtensions.IsCriticalHit(Stats.Luck.Value);
|
||||
var element = ((Weapon)EquippedWeapon.Value).WeaponElement;
|
||||
|
||||
enemy.TakeDamage(
|
||||
attackValue * ((Weapon)EquippedWeapon.Value).ElementalDamageBonus,
|
||||
element,
|
||||
isCriticalHit,
|
||||
false,
|
||||
ignoreElementalResistance);
|
||||
enemy.TakeDamage(
|
||||
attackValue * ((Weapon)EquippedWeapon.Value).ElementalDamageBonus,
|
||||
element,
|
||||
isCriticalHit,
|
||||
false,
|
||||
ignoreElementalResistance);
|
||||
|
||||
if (((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.Knockback)
|
||||
enemy.Knockback(0.3f, -CurrentBasis.Z.Normalized());
|
||||
if (((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.Knockback)
|
||||
enemy.Knockback(0.3f, -CurrentBasis.Z.Normalized());
|
||||
|
||||
_gameRepo.OnPlayerAttackedEnemy();
|
||||
_gameRepo.OnPlayerAttackedEnemy();
|
||||
}
|
||||
|
||||
private void CollisionDetector_AreaEntered(Area3D area)
|
||||
{
|
||||
if (area.GetParent() is InventoryItem inventoryItem)
|
||||
{
|
||||
var isAdded = Inventory.TryAdd(inventoryItem);
|
||||
if (isAdded)
|
||||
{
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"{inventoryItem.ItemName} picked up.");
|
||||
inventoryItem.QueueFree();
|
||||
}
|
||||
else
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {inventoryItem.ItemName}.");
|
||||
}
|
||||
if (area.GetParent() is DroppedItem droppedItem)
|
||||
{
|
||||
var isAdded = Inventory.TryAdd(droppedItem.Item);
|
||||
if (isAdded)
|
||||
{
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"{droppedItem.Item.ItemName} picked up.");
|
||||
droppedItem.QueueFree();
|
||||
}
|
||||
else
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {droppedItem.Item.ItemName}.");
|
||||
}
|
||||
if (area.GetParent() is InventoryItem inventoryItem)
|
||||
{
|
||||
var isAdded = Inventory.TryAdd(inventoryItem);
|
||||
if (isAdded)
|
||||
{
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"{inventoryItem.ItemName} picked up.");
|
||||
inventoryItem.QueueFree();
|
||||
}
|
||||
else
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {inventoryItem.ItemName}.");
|
||||
}
|
||||
if (area.GetParent() is DroppedItem droppedItem)
|
||||
{
|
||||
var isAdded = Inventory.TryAdd(droppedItem.Item);
|
||||
if (isAdded)
|
||||
{
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"{droppedItem.Item.ItemName} picked up.");
|
||||
droppedItem.QueueFree();
|
||||
}
|
||||
else
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {droppedItem.Item.ItemName}.");
|
||||
}
|
||||
}
|
||||
|
||||
private bool PlayerIsHittingGeometry()
|
||||
{
|
||||
var collisions = WallCheck.GetCollidingBodies();
|
||||
return collisions.Count > 0;
|
||||
var collisions = WallCheck.GetCollidingBodies();
|
||||
return collisions.Count > 0;
|
||||
}
|
||||
|
||||
private void WallCheck_BodyEntered(Node body)
|
||||
{
|
||||
PlayerLogic.Input(new PlayerLogic.Input.AttackAnimationFinished());
|
||||
GD.Print("Hit wall");
|
||||
AnimationPlayer.Stop();
|
||||
PlayerLogic.Input(new PlayerLogic.Input.AttackAnimationFinished());
|
||||
GD.Print("Hit wall");
|
||||
AnimationPlayer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[ext_resource type="Script" uid="uid://c3iswacrgya7e" path="res://src/ui/dialogue/DialogueBalloon.cs" id="1_36de5"]
|
||||
[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_a8ve6"]
|
||||
[ext_resource type="FontFile" uid="uid://cb41qqmxqurj8" path="res://src/ui/fonts/FT88-Bold.ttf" id="2_fn8n4"]
|
||||
[ext_resource type="Script" uid="uid://bq8fntgcwiosq" path="res://addons/dialogue_manager/dialogue_reponses_menu.gd" id="3_72ixx"]
|
||||
[ext_resource type="Script" uid="uid://bq8fntgcwiosq" path="res://addons/dialogue_manager/dialogue_responses_menu.gd" id="3_72ixx"]
|
||||
[ext_resource type="Script" uid="uid://by6wev1st2yuh" path="res://src/ui/dialogue/ResponseExample.cs" id="5_0xrfp"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_hrxr4"]
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
[gd_scene load_steps=20 format=3 uid="uid://drrynjlwqt8wi"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/dialogue_manager/example_balloon/ExampleBalloon.cs" id="1_okfmu"]
|
||||
[ext_resource type="Script" uid="uid://5b3w40kwakl3" path="res://addons/dialogue_manager/example_balloon/ExampleBalloon.cs" id="1_okfmu"]
|
||||
[ext_resource type="FontFile" uid="uid://dit3vylt7hmmx" path="res://src/ui/fonts/FT88-Regular.ttf" id="2_c4c1f"]
|
||||
[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_jm6sr"]
|
||||
[ext_resource type="FontFile" uid="uid://cb41qqmxqurj8" path="res://src/ui/fonts/FT88-Bold.ttf" id="3_bc8ok"]
|
||||
[ext_resource type="Script" path="res://addons/dialogue_manager/dialogue_reponses_menu.gd" id="3_yiii3"]
|
||||
[ext_resource type="Script" uid="uid://bb52rsfwhkxbn" path="res://addons/dialogue_manager/dialogue_responses_menu.gd" id="3_yiii3"]
|
||||
[ext_resource type="FontFile" uid="uid://bohbd123672ea" path="res://src/ui/fonts/FT88-Italic.ttf" id="5_2dxvx"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_spyqn"]
|
||||
@@ -192,8 +192,8 @@ response_template = NodePath("ResponseExample")
|
||||
|
||||
[node name="ResponseExample" type="Button" parent="Balloon/CenterContainer/Responses/ResponsesMenu"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_focus_color = Color(1, 0.94902, 0, 1)
|
||||
theme_override_colors/font_color = Color(0.737255, 0.705882, 0.690196, 1)
|
||||
theme_override_colors/font_focus_color = Color(1, 0.94902, 0, 1)
|
||||
button_mask = 0
|
||||
text = "Response example"
|
||||
|
||||
|
||||