Hey, it's been a long time.


Been busy with school, game dev, burn out.

But that's besides the point, you and I both know why you're here.
To get 100 Time Cowboy Steam Ke--

Joking, but this is more of a technical post about Time Cowboy.

A game about a stubborn, short tempered Cowboy blasting his way through different eras to figure out who's dragging him across time.

You can get more info on the game's itch.io page.

Now, enough stalling, let's get onto the post.


ModulAI


Oh boy, where do I start with this.

How about, the first Enemy/NPC AI I made called CubeAI.

The CubeAI Sob-Story

CubeAI was used for a old cancelled game of mine from late-2023 called CubeRPG.

It was a better version of my Enemy Code in my other 2023 game, Risen Dead, where the Zombie's AI in that game was atrocious.

Magic numbers everywhere, hard coded functions, values, properties. 

So with this AI, I wanted to make it easier for me, so I made it a State-Based AI.

A quick example of State-Based is pretty much like, if an Enemy is Angry, do this, if an Enemy is Idle, don't do anything.

While fine, the way I was doing it was also bad, as every Enemy state was in the base script and was not a separate node.

I would continue to use this AI for 2 years after, until early this year when I realized how bloated and jank the code is, especially after the upgrade from Godot 3.5 to 4.4.

This time, I made ModulAI, an Enemy AI made from scratch.

CubeAI, but better

With ModulAI, I made sure that all custom properties needed for Enemies were not included in the base script, unless necessary.

Instead, I went with using Godot's Resource System (Which is just Godot's version of a Data Class) and created EnemyProperties, which can contain an unlimited amount of custom scripts and allowed me to change pretty much everything about an enemy.

Sprites, Sound Effects, Speed, Attacks, Navigation, Fire Rate, Health, etc.

ModulAI just loads the values from the Properties and leaves the rest up to me or whoever is modding the game.

All it does after is just run the functions for the Navigation to work and store variables so the custom scripts can access them easily without the dreaded

get_parent().get_parent().get_node("random node we need")


To show how much better this AI is, for reference, Betrayed Fists uses CubeAI and the script for it is 1k lines long, while ModulAI is 287 lines long.

While it surpasses CubeAI in everything, it does have some issues like being a little janky with 3D Models as it was made for Billboarded Sprites and some minor ones that show occasionally, something CubeAI is better at.

Either way, I'm proud of the system and I think it's just a lot better for me and those who might mod the game.

And with that taken care of, let's get onto the Level Select.


Level Select


"Dude. It's just a Level Select. How hard can it be?"

Surprisingly, the Level Select was a little annoying to code.

For the sole reason of "Can't easily access variables from a PackedScene".

Some reason, we can't access variables from a PackedScene (file containing a compressed level), meaning you can't do this.

packed_scene.level_name

Normally, you'd think you could just access the variable directly, but you can't. Instead, you have to a dumb loop through all the properties, check each one's name and match it. Just adding unnecessary complexity.

It's just annoying and could've been made so much easier with a simple

packed_scene.get_property(0,"level_name")

And the worst part is that you cannot expect the variable to have the same index either.

Example (using fake variable names):

Default Values:
foo1 = false
foo2 = true
foo3 = 0


if you don't change foo2, this is how it'll be counted

foo1 = true (1)
foo2 = true (skipped)
foo3 = 1 (2)

Luckily, with that method, for as dumb as it is, I was able to get the Level Select to show the info properly

Gonna stop here before I burn out.

I'll make a follow up post sometime this week about Weapons and Mister Milton...
Either way,


Thank you for reading.


If you wanna see Time Cowboy in action, come check out my Youtube Channel!

Join the discord server if you want to see sneak peeks of the game or more frequent updates!