Jul. 6th, 2021

Work Post

Jul. 6th, 2021 02:05 am
relee: Picture of Relee Starbreeze, Wizard (Default)
1:54am - So my TTRPG game was postponed this week since one of my friends and players had family problems. That led to the night ending relatively early, but I'm still up and active. It's hot and my computer's having troubles dealing with the heat and playing video games without locking up, I still don't know if that's really the problem but it seems like a lot of coincidences so far. ^.^;;

Anyways I was saying earlier that the next thing I want to do is the AI scripting.

The idea is to have plug-in scripts for the AIs. That way, I can put in a PlayerAICore that takes its commands from the input and puts them in command stacks, and a BasicMonsterAICore that generates command stacks and returns them... And I can make more as needed. There'll be AIs for all the actor types. But I still need to figure out how they'll work logically. I've got a pretty general idea and I don't think it'll be a problem, but I want to make sure I do it right.

So! In order to be a pluginable AI script, there needs to be a base class for each of the AI scripts to inherit from, thus making them interchangable. The most basic thing the base class needs is a method that all the kids will overload, which returns an Array of commands.

Should it be called think() or get_commands() or what? I'm not sure.

The other thing I'm thinking about, should it directly access the Actor it's connected to's properties, or should it be passed a bundle of info? I know I was thinking of having the AI take a sort of SenseMap from the GameMap that showed what it could see. But I don't have something like that implemented yet. Well, maybe I could make a basic one pretty quick by just giving it a rectangle or square mini map version... Anyways I'm not entirely sure there.

The point is that the AI needs to analyze things outside of it.

I think that means I should pass it the Map that the AI haver is on, at the very least. And maybe a reference to itself as well. That way it'd have access to all the properties of the AI haver...

So it might be like, aicore.think(self, map) and that returns an array of Actions.

I think that's all it would need. Now let's go inside and see how it works...

In the case of the BasicMonsterAICore I think it would start by analyzing the Map to choose its action.

If an enemy is in sense range, attack or move towards them. If an enemy is not in sense range, random wander or idle.

In the first case, it returns a melee_attack or move action in an array.
In the second case, it returns a random move action or an idle action.


And now it occurs to me that these actions are going to have to have an action point cost as well, since that was how the energy system works. I'll have to figure that out as well.

Hmm... I suppose when the Actor runs its action methods, they'll have to include action point decreases.


Alright, that all makes sense. Now what about the PlayerAICore? It's not too hard to change where the input source is for the Monster AI, but the Player's input comes from a whole other system.

Hmm... Part of the reason I'm doing this is to open the game up for the potential of controlling more than one character in the game, so I should reconsider how input is handled.

I'm not really fond of the way the input works right now so I'll probably end up changing it too. It was kind of a kludge.

So let's see. There's a few ways I could make it work, but what's best? I want it to be reactive, but not do the wrong thing. Ideally the player should be able to hold down a movement key to move on subsequent turns. They can do that in the working version I had before, but I don't think that will work with the new Action system, and the AICore system.

Basically when the PlayerAICore gets its think() function run, it should wait for input, unless there's one already waiting, and there should be a delay on how fast it can take a new input. I've already got a Timer for the input like that, it shouldn't be hard to connect. Basically the tricky bit will be looping without locking the program while waiting for input.

I think this part I really need to look at the code for, but it's getting really late and my friends are chatting again, so I might stop here for the night.

3:03am - I think I've got some good ideas in here so far. I should be able to implement something next time.

Work Post

Jul. 6th, 2021 07:48 pm
relee: Picture of Relee Starbreeze, Wizard (Default)
7:48pm - Today's been kinda weird, but relaxing. I'm going to start working now, too.

I'm going over the logic for handling player input to see how I got it working before, and figure out how to move it into the AICore system.

It looks like right now in the _process function, it starts by checking if the action timer is stopped. That's a timer that runs after every turn to slow the action down to a speed the player can see.

Then, if it's not the player's turn, it pulls out the Actor on top of the actor_timing_list. It checks if that's a player controlled Actor and if it is, it sets the players_turn property to true, and updates the player's vision.

Then if it's not the player's turn after that, it runs through the current actor's on turn method.

If the current actor is still alive after its turn, it's put back on the actor_timing_list at the back.

Then if they're not still alive, and not the player, it removes them from the game.

Then it starts the action_timer, which counts down until the next turn.

So basically it just loops endlessly when it's the player's turn, until the player's Actor has less than or equal to zero action points.


That's not far from what I wanted it to be, but right now the _input function is setting properties of the Level class depending on what's recently been pressed or released, and then based on what's pressed, it runs a method on the player by a reference.

I want to get rid of that player reference since there is going to be potentially more than one player Actor. So how do I tell the PlayerAICore about input in order to get it to behave properly?

8:46pm - Took a short delay as our groceries were brought up, and read a bunch of documentation on Input in Godot to refresh myself.

One thing I noticed is that while I can handle input in the _input() function, I can also handle it elsewhere, like the _process function, by polling. So, I could make it so that when the player's turn comes up, it sends the input to the Actor, and the Actor can send it on to the AICore perhaps?

The way I've got it now I have to constantly change the state of internal properties for each input type, but I really only need to know the input that's being pressed at the time the process function is running for the Actor in question.

Heck I could put it in the Actor's process function; they're subclassed from Node, so they have one. But I don't think that's wise. I want to centralize my game inputs so I can see them all in one or two places. (Two if I've got UI elements)

So, what about if during the Level._process() function, I check the inputs, during the Player's Turn section? Right now it just loops until the Player's action_points run out. I could switch it from using the player reference to checking if the Actor has a PlayerAICore, and if it does, it passes that info up to the PlayerAICore...

Hmm...

Let's examine an example.

Actor List pops an Actor with a PlayerAICore!

PlayerAICore is detected, set players_turn to true!

Input detected "Move Left"!

Input value is passed to PlayerAICore?

...

Hang on. Maybe it IS a good idea to put the player controls in the PlayerAICore itself? Like, when the turn pump brings up an Actor with a PlayerAICore and runs its think() method, it tests the input in there. Then I'd have the input code localized in the PlayerAICore instead of in the Level, which makes a heck of a lot more sense. Plus, if it doesn't detect any input at all, it doesn't have to reduce action points, so it just returns to the player's turn again and again until they make a move.

That means I wouldn't have to make special exceptions for the player's turn in the turn pump, simpifying it a bit too.

I like this plan! I'm proud to be part of this plan. The part that came up with it and is going to implement it.

Hmm... Now that I think of it, when I implement SenseMap later on, I can use that to show the player what they can see through this system too. Everything is coming together.

Now I guess I just need to code up the AICore base class.

9:16pm - Okay base AICore class made. Next comes the AICore subclasses. But first, I realized that for the AICores to reference the Actions they either need class_name declarations or they need to be referenced in the AICore base class. So, I'm gonna do the former, and that'll take a minute or two...

9:22pm - Or six minutes I guess. Now onto the PlayerAICore.

Now the basic idea is that the think method will test each input action and output an array of Actions matching the player's input.

10:42pm - Well the guys call started suddenly while I was working, so I got in and that slowed me down a bit, but I managed to get the PlayerAICore made, I think. It'll require testing when all of this is ready. ^.^;;

For now I'm done 'cause the guys and I are gonna watch some shows together.

Profile

relee: Picture of Relee Starbreeze, Wizard (Default)
Relee Squirrel

July 2023

S M T W T F S
      1
23456 78
9101112131415
16171819202122
23242526272829
3031     

Most Popular Tags

Page Summary

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 8th, 2025 09:54 pm
Powered by Dreamwidth Studios