Change affinity

This commit is contained in:
2025-01-19 12:59:24 -08:00
parent f3a51de28a
commit 4910ff7770
20 changed files with 272 additions and 89 deletions

View File

@@ -0,0 +1,78 @@
// Color range swap shader for Godot 4; Sprite3D version by Sithoid
// Based on 2D shader by nonunknown https://godotshaders.com/shader/color-range-swap/
// 3d lifehacks by Anonzs https://www.reddit.com/r/godot/comments/11dklv0/sprite3d_shader/
// Billboard projection by mrdunk https://ask.godotengine.org/152606/how-to-do-i-make-a-shader-a-billboard-face-the-player
shader_type spatial;
render_mode depth_draw_opaque, depth_prepass_alpha; // Prepass is needed to cast a shadow
// Set this parameter to your actual texture in script, e.g. with
// material_override.set_shader_parameter("sprite_texture", texture)
uniform sampler2D sprite_texture : source_color, filter_nearest;
// Hue on a HSV scale (0 to 1) that will be keyed out. Defaults are set to key out bright cyan
uniform float _min = 0.49;
uniform float _max = 0.5;
// Target color (RGBA) that will appear instead of the mask (it will respect brightness)
uniform vec4 color : source_color = vec4(0.59, 0.12, 0.32, 1.0); // Dark pink by default
uniform bool billboard = false; // Toggle billboard mode (set this in script)
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
// All components are in the range [0…1], including hue.
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
// ===== nonunknown got those from: https://gamedev.stackexchange.com/a/75928
vec4 to_gray(vec4 tex) {
float avg = (tex.r + tex.g + tex.b) / 3.0;
return vec4(vec3(avg),tex.a);
}
vec4 to_color(vec4 gray, vec4 col) {
return gray * col;
}
// ===== end
// == Billboard projection by mrdunk
void vertex() {
if (billboard) {
mat4 modified_model_view = VIEW_MATRIX * mat4(
INV_VIEW_MATRIX[0],
INV_VIEW_MATRIX[1],
INV_VIEW_MATRIX[2],
MODEL_MATRIX[3]
);
MODELVIEW_MATRIX = modified_model_view;
}
}
// end ===
void fragment() {
vec4 tex = texture(sprite_texture, UV);
vec3 hsv = rgb2hsv(tex.rgb);
// the .r here represents HUE, .g is SATURATION, .b is LUMINANCE
if (hsv.r >= _min && hsv.r <= _max) {
tex = to_gray(tex);
tex = to_color(tex, color);
}
// To replace multiple colors, just copy this "if" statement
// and repeat it with different variables (such as _min1, _min2 and color2)
ALBEDO = tex.rgb;
ALPHA = tex.a;
}

View File

@@ -0,0 +1 @@
uid://b1n357imav0y6

View File

@@ -3,16 +3,17 @@ using Chickensoft.Introspection;
using GameJamDungeon;
using Godot;
using System;
using System.ComponentModel;
[Meta(typeof(IAutoNode))]
public partial class ThrowableItem : Node3D, IUsableItem
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
[Dependency] public IGame Game => this.DependOn<IGame>();
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
public InventoryItemStats Info => ThrowableItemInfo;
public int Count { get; }
@@ -26,10 +27,23 @@ public partial class ThrowableItem : Node3D, IUsableItem
[Node] public Area3D Pickup { get; set; } = default!;
private ThrowableItemTag[] _affinityTypes;
private int _affinityIndex = 0;
public void OnResolved()
{
Sprite.Texture = ThrowableItemInfo.Texture;
Pickup.BodyEntered += OnEntered;
_affinityTypes =
[
ThrowableItemTag.InflictBaseDamage,
ThrowableItemTag.InflictHydricDamage,
ThrowableItemTag.InflictIgneousDamage,
ThrowableItemTag.InflictTelluricDamage,
ThrowableItemTag.InflictAeolicDamage,
ThrowableItemTag.InflictFerrumDamage
];
}
public void Use()
@@ -38,6 +52,24 @@ public partial class ThrowableItem : Node3D, IUsableItem
Game.HealHP(ThrowableItemInfo.HealHPAmount);
if (ThrowableItemInfo.HealVTAmount > 0)
Game.HealVT(ThrowableItemInfo.HealVTAmount);
if (ThrowableItemInfo.UsableItemTags.Contains(UsableItemTag.DoubleEXP))
Game.DoubleEXP(TimeSpan.FromSeconds(30));
if (ThrowableItemInfo.ThrowableItemTags.Contains(ThrowableItemTag.CanChangeAffinity))
ChangeAffinity();
}
private void ChangeAffinity()
{
ThrowableItemInfo.ThrowableItemTags.Remove(_affinityTypes[_affinityIndex]);
_affinityIndex = (_affinityIndex + 1) % (_affinityTypes.Length);
ThrowableItemInfo.ThrowableItemTags.Add(_affinityTypes[_affinityIndex]);
// TODO: Make this an inventory animation to cycle through elements.
ThrowableItemInfo.Description =
$"{GetDescription(_affinityTypes[_affinityIndex])} when thrown." +
$"{System.Environment.NewLine}Use item to change Affinity.";
}
public void OnEntered(Node3D body)
@@ -46,4 +78,19 @@ public partial class ThrowableItem : Node3D, IUsableItem
if (isAdded)
QueueFree();
}
private static string GetDescription(ThrowableItemTag enumValue)
{
var field = enumValue.GetType().GetField(enumValue.ToString());
if (field == null)
return enumValue.ToString();
var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute)
{
return attribute.Description;
}
return enumValue.ToString();
}
}

View File

@@ -1,6 +1,6 @@
[gd_scene load_steps=3 format=3 uid="uid://1fl6s352e2ej"]
[ext_resource type="Script" path="res://src/items/throwable/ThrowableItem.cs" id="1_nac2l"]
[ext_resource type="Script" uid="uid://dj28ol2cpeiwm" path="res://src/items/throwable/ThrowableItem.cs" id="1_nac2l"]
[sub_resource type="BoxShape3D" id="BoxShape3D_03cqg"]
size = Vector3(0.778381, 0.929947, 0.731567)
@@ -20,6 +20,7 @@ shape = SubResource("BoxShape3D_03cqg")
[node name="Sprite" type="Sprite3D" parent="Pickup"]
unique_name_in_owner = true
transform = Transform3D(0.999973, 0.00489444, -0.00548299, -0.00488109, 0.999985, 0.00244357, 0.00549488, -0.00241672, 0.999982, 0, 0, 0)
pixel_size = 0.0005
billboard = 2
shaded = true

View File

@@ -7,4 +7,7 @@ public partial class ThrowableItemStats : InventoryItemStats
{
[Export]
public Godot.Collections.Array<ThrowableItemTag> ThrowableItemTags { get; set; } = new Godot.Collections.Array<ThrowableItemTag>();
[Export]
public Godot.Collections.Array<UsableItemTag> UsableItemTags { get; set; } = new Godot.Collections.Array<UsableItemTag>();
}

View File

@@ -1,11 +1,21 @@
public enum ThrowableItemTag
using System.ComponentModel;
public enum ThrowableItemTag
{
[Description("Inflicts basic damage")]
InflictBaseDamage,
[Description("Inflicts Telluric damage")]
InflictTelluricDamage,
[Description("Inflicts Aeolic damage")]
InflictAeolicDamage,
[Description("Inflicts Hydric damage")]
InflictHydricDamage,
[Description("Inflicts Igneous damage")]
InflictIgneousDamage,
[Description("Inflicts Ferrum damage")]
InflictFerrumDamage,
LowerTargetTo1HP,
CanChangeAffinity
}
public enum UsableItemTag

View File

@@ -1,13 +1,15 @@
[gd_resource type="Resource" script_class="ThrowableItemStats" load_steps=3 format=3 uid="uid://bph8c6by4s047"]
[ext_resource type="Script" path="res://src/items/throwable/ThrowableItemStats.cs" id="1_ewck5"]
[ext_resource type="Script" uid="uid://d3wlunkcuv2w2" path="res://src/items/throwable/ThrowableItemStats.cs" id="1_ewck5"]
[ext_resource type="Texture2D" uid="uid://mi70lolgtf3n" path="res://src/items/throwable/textures/GEOMANCER-DICE.png" id="1_jhits"]
[resource]
script = ExtResource("1_ewck5")
ThrowableItemTags = []
ThrowableItemTags = Array[int]([7])
UsableItemTags = Array[int]([])
Name = "Geomantic Dice"
Description = "Inflicts Affinity damage when thrown."
Description = "Inflicts base damage when thrown.
Use item to change Affinity."
Texture = ExtResource("1_jhits")
SpawnRate = 0.1
ThrowSpeed = 20.0

View File

@@ -1,13 +1,17 @@
[gd_resource type="Resource" script_class="ThrowableItemStats" load_steps=3 format=3 uid="uid://qqg0gdcb8fwg"]
[ext_resource type="Texture2D" uid="uid://dhfn51smm818x" path="res://src/items/throwable/textures/spell sign - luck.PNG" id="1_3605p"]
[ext_resource type="Script" path="res://src/items/throwable/ThrowableItemStats.cs" id="1_s3pq7"]
[ext_resource type="Script" uid="uid://d3wlunkcuv2w2" path="res://src/items/throwable/ThrowableItemStats.cs" id="1_s3pq7"]
[resource]
script = ExtResource("1_s3pq7")
Damage = 0
ThrowableItemTags = []
ThrowableItemTags = Array[int]([])
UsableItemTags = Array[int]([0])
Name = "Spell Sign: Knowledge"
Description = "Doubles experience points earned. Effect is temporary."
Texture = ExtResource("1_3605p")
SpawnRate = 0.1
ThrowSpeed = 12.0
HealHPAmount = 0
HealVTAmount = 0
ThrowDamage = 5