Over the past several days I've been working on a queue system where the player, or another portion of code, can add an attack, action, or item to a queue and it will play them after a set delay. This could be used to set up attacks during a battle so you can focus your attention on strategies or your allies. It could also be used to receive function calls from code to handle them if more than one is called at once, for instance if two animations are called at the same time. It ended up being pretty easy to set up once I figured out what steps were needed.
When I first attempted this a couple weeks ago I ended up putting it down in frustration because I couldn't figure out how to get it to do what I wanted it to do. Earlier this week I remembered something from an article I read about coding, and it helped my out with this. The article suggested to write down the steps that the code needed to take before you even begin working on the computer. By doing this you are forcing yourself to think about the different components that make up the chunk of code that you are trying to create. I decided to do this and the breakdown ended up looking like this:
This really helped me get the order down on what needed to happen where. After that I could take each step and write them out, essentially creating three functions reflecting the outline above.
Here's what I came up with in Unrealscript. This is in my custom Pawn class:
//Struct used in the Action Array struct Actions { var string N; //Action Name var float D; //Action Delay }; //Delay playing another action var bool bDelay; //Holds the actions currently queued to run var Array<Actions> ActArray; function AddAction(string Action, float Delay) { local int i; //Set i to the current length i = ActArray.Length; //Add another element in the array ActArray.Length = ActArray.Length + 1; //Set the properties of the new element ActArray[i].N = Action; ActArray[i].D = Delay; PlayAction(); } function PlayAction() { local string TempN; local float TempD; //If an action is already playing if(bDelay == true) { //Place any action to run if an action is currently being ran. } //If not else if(bDelay == false) { bDelay = true; //Set the temporary variables TempN = ActArray[0].N; TempD = ActArray[0].D; //Check which action needs to be played switch(TempN) { case("sAttack"): //Standard Attack Played break; case("hAttack"): //Heavy Attack Played break; default: break; } //Remove the played action ActArray.Remove(0, 1); //Set bDelay = false after a set time SetTimer(TempD, false, 'ResetDelay'); //Output the time to the screen WorldInfo.Game.Broadcast(self, "PlayAction Time:" @ TempD); } } function ResetDelay() { bDelay = false; //If there is another action waiting if(ActArray.Length > 0) { PlayAction(); } } defaultproperties { bDelay = false }
And the functions that call it from my custom GFxMoviePlayer class:
function sAttack() { GP.AddAction("sAttack", 10.0); } function hAttack() { GP.AddAction("hAttack", 20.0); }
I'll go through and break down what is happening in each one starting in the Pawn class. The variables are pretty self explanatory. I chose to use an array consisting of the Actions structs I defined earlier, that way each action could have multiple properties assigned to it. In this case I just have the action name and how long its cooldown should be.
Next I'll go through the AddAction function. As you can see it takes two parameters when it is called, this was the easiest way I found to set up the different attacks. We'll then create a local int that will store what element number the action need to go into. Arrays use a base-0 numbering system, meaning they start at 0 and end at one less than the number of elements. I.e. if you have 4 elements the last one would be Element3. Since this is the case I set i equal to the current length of the array, then added one more element onto the array. This left i being the last element in the array. I then set the name and delay properties of that element equal to the parameters that were passed from the calling function. Last, I call the PlayAction function which actually calls the function to play the attack.
Onto the PlayAction function! Most of this is pretty easy to follow. Basically, if an action isn't cooling down(if bDelay is false) then check what the name of the action is and play the appropriate function.Then we're going to remove the first element from the array which will move the rest of them up one. I did this because it simulates a real queue, or line. Only one person can be helped at once. When the first person is done they move off and everyone moves forward, thus creating an organized system to handle multiple people. Finally, we set a timer to mark the system as ready to play another action. You might be able to use ActArray[0].N in the switch directly, or ActArray[0].D in the timer, but I ran into some issues previously with using array elements directly. I may give it a whirl later and see if I can, but I'm going to leave it for now.
Our last function in the Pawn class is resetting bDelay and calling PlayAction if there is another action waiting to be played.
The functions in the GFxMoviePlayer class simply call the AddAction function and declare what action needs to be set.
Well, there is a basic working queue system to use in a multitude of situations. You could even make a function for when an action is double clicked on your graphical display to remove that specific action. It could look something like this(though I haven't tried it)
RemoveAction(3); function RemoveAction(int ActNum) { ActArray.Remove(ActNum, 1); }
In this example it would remove 1 element at the 3rd slot, or whatever we pass into ActNum.
Anyway, that's all I have for today. Hope this was useful to someone. Once I figure out how I want the graphical display to look/work I'll post the code and such for that as well.
No comments:
Post a Comment