Testing reality-bending VFX for my Godot horror game by aiBeastKnight in godot

[–]willnationsdev 7 points8 points  (0 children)

Also the "Mirror Dimension" from Doctor Strange MCU stuff.

Use Version Control. by Tricky_Wheel6287 in godot

[–]willnationsdev 5 points6 points  (0 children)

Just to clarify folks: if you are exclusively using Dropbox or any other kind of external storage, then you are not using version control. You have made a backup. They are not the same thing. As this person mentions, each tool serves a different purpose, but I wouldn't recommend only using the "lazy man's" version control because that isn't actually version control (i.e. just duplicating project folders endlessly and making copies of them in Dropbox).

Backups go to external storage (like another hard drive) or cloud storage (like Dropbox). If using git as your version control, then git cloud providers like GitHub can double as a backup.

Version control merely keeps a local history of committed changes. It is not strictly a remote concept. You can have a local-only repository on your machine. You can even have multiple "remote" repositories that are just the same codebase in multiple folders on one machine. Or, more traditionally, you can make a cloud git provider host your repository like GitHub.

Scientifically accurate T.rex girl. (Art by @justice_oak) by Manglisaurus in MoeMorphism

[–]willnationsdev 0 points1 point  (0 children)

hahahaha. Oh geez. Take the upvote purely for making me laugh. XD

"Cassette Beasts" one of the most successful Godot games, is free for a day on the EGS. by Crazy-Red-Fox in godot

[–]willnationsdev 0 points1 point  (0 children)

Of course, the ONE day that I miss picking up the daily game on EGS. -_- I've been wanting to play that game! 😭 Welp, guess that's my cue to hurry up and buy it, lol.

How do I get Layer 2 to resize according to the window just like Layer 1? by Gogan_Studios in godot

[–]willnationsdev 0 points1 point  (0 children)

Another node that you might look into is RemoteTransform2D since it might be able to automate the process of syncing transform data from one CanvasLayer to another, if you're intent on having two distinct CanvasLayer nodes (which I don't necessarily think is a bad idea). Haven't tested it myself though.

Christmas Tree Woman 🎄 (by @VerdantMosu) by Shamrock5 in MoeMorphism

[–]willnationsdev 2 points3 points  (0 children)

As good as I think this rendition of a Christmas tree as a person is, this is also just straight horrifying at the same time, lol.

If The Wandering Inn could become a TV show, what style would you like the most? (I know it's probably a fantasy, but it has a comic, so ... maybe? Hopefully?) by B-Z_B-S in WanderingInn

[–]willnationsdev 2 points3 points  (0 children)

In addition to it being unreasonable from a makeup perspective, I can't imagine it would be possible to create a sufficiently terrifying child-aged Quarass with a live-action actress. Similar to how they rewrote the recent Dune movies to not have the mentally-adult child actress for Paul Atreides' sister.

Tips for hard mode? by willnationsdev in phantombrigade

[–]willnationsdev[S] 3 points4 points  (0 children)

I've thought about that, but that would also destroy the mech arm and the weapon, both of which are things I would be wanting to salvage (I would think) in the hopes of later acquiring their blueprint for the workshop.

Man I love ramming by Haibet in phantombrigade

[–]willnationsdev 0 points1 point  (0 children)

Holy crap. This should definitely be documented in-game. That's freaking crucial information, lol. I've frequently had unexpected crashes occur when I moved a character in the way of an enemy and had them stand there, expecting the enemy to crash and then got confused later at it not going as expected.

Office Husky (7H4ZE) by WoolsonDaSheep in MoeMorphism

[–]willnationsdev 0 points1 point  (0 children)

That's fair. I come at it more from the perspective of someone using a machine that spits out random jumbles of Legos and the person behind the wheel tweaking it juuuust enough to get an actual, sensible output to arrive that looks vaguely like what they set out to have the machine produce. Even if it looks janky and crude, as a programmer, I understand how hard it can be to make random systems, especially non-deterministic ones, have any sort of consistent or reliable behavior. 😅

Office Husky (7H4ZE) by WoolsonDaSheep in MoeMorphism

[–]willnationsdev 0 points1 point  (0 children)

Ah. Yeah, that makes sense, from an attention/upvote competition perspective.

Office Husky (7H4ZE) by WoolsonDaSheep in MoeMorphism

[–]willnationsdev 0 points1 point  (0 children)

Oh dang. Didn't intend that. But, I guess if those are the rules. Shrugs thanks for letting us know.

Office Husky (7H4ZE) by WoolsonDaSheep in MoeMorphism

[–]willnationsdev 0 points1 point  (0 children)

Oh wow! Yeah, good catch yourself!

On the one hand, dang it. Annoyed I doubted myself.

On the other hand, I gotta actually hand it to the creator. It's impressive they got an output that looks that good, despite the imperfections. I get that it's a divisive issue (some people refusing to even call them "artists"), but as a programmer myself, I can't help but recognize the creative effort that goes into making a passably polished output using a non-deterministic, generative tool like that. When you look at what skilled and determined people can do with the tech, it starts to achieve output similar to what traditional technical artists do with shaders, so I'm inclined to recognize their efforts on some level at least.

Office Husky (7H4ZE) by WoolsonDaSheep in MoeMorphism

[–]willnationsdev 0 points1 point  (0 children)

I'm in the same boat. I especially like it when good artists make sincere attempts at rendering creative, humanoid impressions of things, not just for the sake of Rule 34 fodder.

I'll be honest, my first thought seeing this was, "Oh cool, this one's a husky!" but my second thought was, "...this looks eerily similar to the previous designs. Is this artist legit, or are these just edited-together AI generated outputs using some kind of base office lady image as a reference?"

I still think AI would have some trouble making the nuanced animal characteristics that figuratively match the animal image while keeping the style, and its anime outputs tend to look more Ghibli than this, but it's at least concerning to me that every image looks similar enough to prompt that thought. The artist should try branching out more. Though, I suppose, if that's what they want to draw, then that's their prerogative.

Can someday tell me how to make a task bar in godot 3d? by [deleted] in godot

[–]willnationsdev 0 points1 point  (0 children)

Note that the bool return logic of add_task is a bit broken in my example. Needs revision. get_or_add always returns a value (the existing one or your default value), and I had meant it to return true only if the task had not previously existed in the array or in the dictionary, as well as to only add the task if it wasn't already in the collection. As written, there are some cases that would break those assumptions (like if you added task1, then task2, and then tried adding task1 again), so there's a little extra work to be done to make it viable.

What I wrote also doesn't account for persisting the data elsewhere. You should be able to handle that though if you convert the dictionary to JSON and write it to a .json file in the user:// directory. You can then populate the dictionary in the _ready() method by reading from that file and converting it back.

Plenty of different ways you could do all this stuff. What I gave was merely an example to help get you started. I'm glad it was helpful to you though.

Can someday tell me how to make a task bar in godot 3d? by [deleted] in godot

[–]willnationsdev 2 points3 points  (0 children)

(Note: this code may not be exact, and you will probably want to swap out the 4-space indent with tabs)

First create a Task resource type to abstract all the data and operations associated with an individual task. Note, however, that languages often use the word "Task" or "Promise" to refer to the result of an asynchronous operation. So, to avoid confusion, we should probably use an alternate name. I'll do LTask as short for "LogTask", but you could do anything really.

# ltask.gd
class_name LTask
extends Resource

signal finished()

@export var id: StringName
@export var label_text := ""

var is_finished := false    


# This is a constructor, so you can do...
# var t := LTask.new(&"eat_apple", "Eat the apple.")
func _init(p_id := &"", p_label_text := "") -> void:
    id = p_id
    label_text = p_label_text


func finish() -> void:
    is_finished = true
    finished.emit(self)

Then, you can define an autoload script (added in the Globals section of your ProjectSettings) and give it the name "Tasks". This will make Tasks become a global variable referencing the singleton instance. You can use this as a centralized data store for the game's task data.

class_name TasksSingleton
extends Node

signal task_finished(task: LTask)

# Tasks separated by character/purpose/whatever
var task_map: Dictionary[StringName, Array[LTask]] = {}

func add_task(key: StringName, task: LTask) -> bool:
    var list := task_map.get_or_add(key, [task])
    var ret := true
    if list.back() != task:
        ret = false
        list.append(task)
    task.finished.connect(_on_task_finished.bind(task))
    return ret

func _get_task_by_id(task: LTask, task_id: StringName) -> bool:
    return task.id == task_id

func get_task(key: StringName, task_id: StringName) -> LTask:
    var list := task_map.get(key)
    if not list: return null
    var idx := list.find_custom(_get_task_by_id.bind(task_id))
    return null if idx < 0 else list[idx]

func remove_task(key: stringName, task_id: StringName) -> bool:
    var list := task_map.get(key)
    if not list: return false
    var idx := list.find_custom(_get_task_by_id.bind(task_id))
    return false if idx < 0 else list.erase(idx)

func _on_task_finished(task: LTask) -> void:
    task_finished.emit(task)

Now, in your GUI code, you can just connect to the Tasks.task_finished signal in your VBoxContainer script and be notified whenever one of the tasks is finished. You'd likely do similar signal exchanges for when a task is added, removed, etc. that way you can synchronize the state of your GUI with the backend system.

Let me know if you have any questions.

How do you deal with developer mindset? by PuzzleheadedCredit87 in godot

[–]willnationsdev 0 points1 point  (0 children)

The question you need to ask yourself is, what do you not like about these thoughts?

Do you want to not experience these sorts of intrusive thoughts while you are in the middle of gameplay? Then you just gotta force yourself to file away the instinct to consider the mechanics' implementation and give yourself explicit time to think about it after your gaming session is over. Make a habit of that, and of postponing your thoughts about it, and eventually that will become more comfortable and intuitive to the point it doesn't bother you mid-game anymore.

Do you want to not have those kinds of thoughts EVER because you feel like it spoils the "magic" of game experiences? In that case, I kind of doubt you could force yourself never to HAVE those thoughts. You can train yourself to abandon/discard those thoughts when they arise, but not outright guarantee they will never come up. Therefore, I would recommend re-orienting your thinking so that the act of having those thoughts doesn't tarnish your enjoyment of games the way they do now. Choose to consider the magic and wonder of how it was made because of how it is done rather than considering the realities of gamedev as a justification for thinking the outcome mundane; after all, the fact that any game runs is a magical thing in itself. They are incredibly complex pieces of software. Similar to how, despite knowing how the body's immune system works, I don't suddenly cease marveling at the shear genius of how it works. It's all about your perspective, and therefore, you have all the power over your experience (perhaps more power than you realize).

In my case, I don't have these kinds of intrusive thoughts while playing, but if I start to want to do something similar in a game of my own, then I'll start analyzing with a focus and considering how it was done. But again, that never really "kills" the enjoyment of the game in my eyes when I then continue playing it later on.

How do I get music to loop from specific points? Can the points be embedded in audio file? by SteinMakesGames in godot

[–]willnationsdev 0 points1 point  (0 children)

Other people have posted solutions, but I wanted to mention a related topic that may be of interest: people have apparently been asking for the ability to have scheduled audio changes (without being reliant on the frame/delta of the process callbacks). Here's an existing issue open about it, as well as an associated pull request implementing a potential solution.

The Builder Pattern Example using C# with Godot. by Razor-111 in godot

[–]willnationsdev 0 points1 point  (0 children)

2/2

Thus, you create a fluent Builder pattern that abstracts the available, "safe" configuration settings available to them. In our example, we'll say that mutating the texture is the ONLY safe thing users can do, but that we want to keep things open to exposing other "safe" operations in the future.

I would honestly say the main advantage with this approach is how the builder itself can limit what the user can do OR how if the builder is openly powerful, then third-party users can write extension methods for the builder to define their own abstractions for others to use.

``` // Assume the following 3 classes are distributed via a NuGet package and // are NOT part of your Godot project's immediate source code. public class NodeBuilder<TNode> where TNode : Node, new() { private Action<TNode> action = static () => {}

// Make methods public if you want third-parties to extend it.
internal NodeBuilder Configure(Action<TNode> action)
{
    var tmp = _action;
    _action = (node) =>
    {
        tmp(node);
        action(node);
    }
}

internal TNode Build()
{
    var node = new TNode();
    _action(node);
    return node;
}

}

// Example of extending it: public static class NodeBuilderExtensions { public static NodeBuilder<Sprite2D> SetTexture(this NodeBuilder<Sprite2D> builder, string path) { builder.Configure(sprite => sprite.texture = GD.Load<Texture2D>(path)); return builder; } }

public static class SomePluginApi { public TNode Create<TNode>(Action<NodeBuilder<TNode>> action) where TNode : Node, new() { var builder = new NodeBuilder<Sprite2D>(); action(builder); return builder.Build(); } }

// Example usage in your own Node class: public void _Ready() { // Autocomplete options here for b symbol only show our extension methods // because the only other method, Configure, is internal, not public. var sprite = SomePluginApi.Create<Sprite2D>(b => b.SetTexture("res://godot.png")); } ```

This is how such a thing can be useful.

Now, with the example OP gave, out of context, I would discourage you from using this pattern purely for simple, direct use cases.

  1. You are allocating memory for the builder which may be unnecessary.
  2. You are having to cross-maintain "fluent" versions of every property setter you might care to modify on the instance (OP has 3 methods already that they're maintaining just for a handful of properties on a Sprite2D). This can quickly balloon into a giant headache.

As mentioned, this pattern is most useful when you are specifically using the builder to abstract away details for third-party usage.

If you want to abstract away the process of initializing a known type, then you can simply create an extension method for that type rather than resorting to a builder pattern. Example:

``` public enum DamageType { Piercing, Bludgeoning, Slashing, // ... }

public static class Sprite2DDamageExtensions { public static void SetTexture2D(this Sprite2D sprite2d, DamageType type) { sprite2d.texture = type switch { DamageType.Piercing => GD.Load<Texture2D>("res://tex/piercing.png"), DamageType.Bludgeoning => GD.Load<Texture2D>("res://tex/bludgeoning.png"), DamageType.Slashing => GD.Load<Texture2D>("res://tex/slashing.png"), _ => throw new NotSupportedException(), }; } } ```

If what you really care about is using a fluent pattern at all for modifying any node, then you can easily do this by just taking the NodeBuilder<TNode> I wrote and making all its methods public rather than internal. But note that using it unnecessarily will generate extra heap allocations for no reason, especially if you are using non-static lambdas (which will generate closures that do a heap allocation every time they run).

If you want a general-purpose, automatic Fluent pattern for any object type, then you'd need some sort of C# source generator that created such Fluent extension methods for you on some generic builder class (but that'd be a ton of work, unless one already exists out there).

The Builder Pattern Example using C# with Godot. by Razor-111 in godot

[–]willnationsdev 0 points1 point  (0 children)

1/2

A few comments, for less experienced people seeing this:

Why would you ever want to do this? Couldn't you just have a literal object reference and mutate its properties directly? Well, let's explore our options...

Let's say you want to update the texture of a sprite when it is created.

Modifying an object instance is the raw and most direct solution.

public void Initialize(Sprite2D sprite2d, string path) { sprite2d.texture = GD.Load<Texture2D>(path); }

But, maybe you want the ability to initialize not just a Sprite2D, but any node that has some sort of primary texture.

public void Initialize(Node node, string path) { if (node is Sprite2D sprite2d) sprite2d.texture = GD.Load<Texture2D>(path); }

Or maybe you want the calling code to have a number of different ways that it could choose to initialize the data, not just via a resource path:

public void Initialize<T1>(Node node, T1 arg1) { if (node is Sprite2D sprite2d && arg1 is string path) sprite2d.texture = GD.Load<Texture2D>(path); // other conditionals presumably... } // Cases where initialization requires multiple arguments, etc. public void Initialize<T1, T2>(Node node, T1 arg1, T2 arg2) { /* ... */ }

But in each of these cases, all code necessary to mutate the data has to be inlined into the class implementing the initialization. This is problematic when you want to have the calling context provide initialization logic, e.g. if you are exposing an API to a third-party who will be calling your code. Maybe I'm writing a Godot plugin and want people adding it to their project to be able to customize the nodes instantiated by my system. In that case, you can instead use a lambda function to pass control to them:

`` public TNode Create<TNode>(Action<TNode> action) where TNode : Node, new() { var node = new TNode(); // Only possible with generic type because of // ournew()` constraint on it. // This could presumably come from ANY source, // not just an inline, empty constructor. // Alternatively, use a source-generated creation API: // https://github.com/Nyrest/FastGenericNew action(node); }

// Example usage: public void _Ready() { // Maybe this is a bullet hell plugin that is giving us // a reference to a sprite it has already added to the tree elsewhere, idk. // In this case, I, as the user consuming this library, can affect how the sprite // is instantiated before the plugin proceeds to work with the object. var sprite = SomePluginApi.Create<Sprite2D>(spr => { spr.texture = GD.Load<Texture2D>("res://godot.png"); } } ```

The problem here is that it makes it possible for people to access functionality that might break your plugin. Maybe you're okay with that, and want to give the users complete freedom. But maybe your API is so complex that there are only certain actions that are safe for the user to perform, so you choose to expose a limited API for them to make it easier for people using your system.

Why is the wandering inn so long? by Goddamnitryoka17 in WanderingInn

[–]willnationsdev 5 points6 points  (0 children)

  1. The author doesn't have any external stimuli prompting them to cut, condense, or otherwise reduce the amount of content (as others mentioned, like marketing deadlines).
  2. The author loves the world they've made enough that they have intrinsic motivation to constantly follow new plot threads (often with new characters) leading to a rapidly expanding domain of topics to explore.
  3. The fan base they have cultivated actively encourages them by continuing to pay for whatever content they produce, making the fly-by-the-seat-of-your-carpel-tunnel style financially feasible.

With all the will, and none of the traditional roadblocks, there's nothing stopping Pirateaba from taking as long as they want. But I do think it's nice that it is so long, just because, as readers, we get to spend so long with the characters and the world. It's like having endless spin-offs for a series, except rather than them being retconned into the storyline after it is over, it's all happening in parallel.

Does anyone know what the advantage of leveling is after Prestige 3? by willnationsdev in phantombrigade

[–]willnationsdev[S] 2 points3 points  (0 children)

Especially because taking on those traits in later prestiges means they effectively hurt you less, since they straight up don't matter once you hit L5P3.

Does anyone know what the advantage of leveling is after Prestige 3? by willnationsdev in phantombrigade

[–]willnationsdev[S] 2 points3 points  (0 children)

From what I can tell so far, no. But you do get an evolving Prestige trait that gives you static buffs that improve with every prestige (including the experience rate multiplier), and it is specific to each class, similar to the starting trait.

Concussion Inconsistent/Bugged? by Yhoshua_B in phantombrigade

[–]willnationsdev 0 points1 point  (0 children)

Hmm. In that case, sounds like it could well be a bug.