Help with determining, executing, and updating turn order

Hey, everyone!

I’m currently hard at work on my title Estheria: A Realm Divided. While developing the combat system (turn-based RPG style ala FF/DQ), I openly admit that I’m not an engineer or coder, and have run into a bit of a mental snag/snafu.

In the title, the total party size is 4 (player + 3 party members). Currently, dexterity assists with determining the turn order (higher dex would mean that they’d go sooner than others). My issue comes both in having troubles building out/conceptualizing a system for determining, executing, and updating the turn order.

I can envision the first subroutine for determining partially. In this situation, the system would run through and scan (via multiple if/else statements (which I know is probably the poor way to code it), each party member and based on their dex assign them to a variable. As for how that assignment could be specific to a character, I’m at a bit of a loss.

From there, I’ve tried to skip ahead and conceptualize even executing upon the turn order, which should be the easy part. Ideally, should the first part (determination) be figured out, it should be as simple as having whatever variables go first and run through, though that also could be tricky as it has to be tied to specific people, again. (Same with enemies in encounters)

Lastly, my final issue would be updating this. Status-effects striking down dex might not be a big issue, but I would imagine running the first subroutine isn’t going to work again as that’s to determine the initial turn order. Say an enemy dies so there’s less people in combat, then the turn order wouldn’t be the initial one anymore.

I’m aware it’s complex, and is a conundrum. I was advised to come here and see if anyone from the community could assist before I seek outside help. If not, I fully understand and thank all of you for the time in looking over my post nonetheless. :slight_smile:

Kind regards,
~Zach

6 Likes

While not impossible to do this in Choicescript, the language is not designed with these kinds of operations in mind. Since you don’t have a coding background, I’ll try to explain the concepts you need to the best of my ability.

In other programming languages, you would create an object that encapsulates the attributes of each character (strength, dex, name, etc). I think I saw a library for CS that allows some kind of object creation, but I don’t recall if it works if you intend to publish it, so we have to find another solution.

First, you have to set the dexterity values in a data structure and sort it in descending order (the highest dexterity goes first). Since the only data structures available in Choicescript are arrays, you will have to create an array with all the dex values, then sort it. Sorting can be a bit tricky if you haven’t done it in another programming language before, but it is possible.

After you have sorted the dexterity values, you need to map them back to the characters, so you have a sorted array of character names/ identifiers instead of “meaningless numbers”. Here you will need a subroutine that goes through all of the dex values and through all of the character names and when a match is found, add the character name/ id into the new array. Repeat this step until you have a full array of characters. If two/more characters have the same dex value, you can add the first one to the array. When adding a new character to the array check if they weren’t added already.

The next step would be a lot easier with a data structure called a Queue, but since implementing one in ChoiceScript would be tedious, we will use the array. When you start a turn, you want to move the first value of the array to the last one and shift the other elements toward the start (this is for updating the turn order).

So if the start of the round the array looks like this: [Tim, Jack, Sarah, Jessica], after this operation it will look like this: [Jack, Sarah, Tim, Jessica]

After this step, you can run the subroutine for the character that does their turn, then repeat the previous step if combat has not ended.

If things happen that change a character’s dexterity, then you will have to redo the array dex sorting while keeping in mind which characters have already taken their turn this round and add them at the end of the array.

I would like to stress that while the above logic is possible, it’s a headache for a beginner to do in a more robust programming language and fairly challenging for an intermediate one. Doing it in Choicescript is tedious, and you probably will get frustrated if you try to implement it alone. IMO, the strength of interactive novels is the narrative part. The mechanics you are trying to implement work better in classic video games and idk if it’s worth the effort to do. But if that’s what you want to do, more power to you. Just keep in mind that you will have to learn some concepts of programming and data structures to truly understand the implementation and fix it when bugs occur (which may take anywhere from a few months to a year, depending on how talented you are when it comes to engineering/programming).

7 Likes

Hey Quartz!

I just want to take a moment to say thank you, a ton. This definitely poses the situation to be quite more complex than I originally planned/wanted.

I will most likely look to hire an outside engineer to assist with this. While I plan on creating a hefty narrative contribution to combat, my goal is to attempt a true RPG within the confines of the interactive narrative medium.

Should that come at a cost, I’m more than fine with doing so.

I can handle most of my other logical programming concepts, but I did assume (correctly) that combat would be extremely difficult with the way I prepared/planned.

Thank you again for your fantastic advice and assistance. It’s been of great help.

Kind regards,
~Zach.

6 Likes

Maybe try to contact @adrao as he has implemented something similar in Hero or Villain series and in Raiders of Icepeak mountain.

4 Likes

You can also look at the Shadowrun hobby project for initiative coding and how it is handled there.

4 Likes

Hi… I have a couple of games that use such systems, both based on old RPGs. The Hero or Villain series is based on the old Marvel RPG, but I removed the random rolls from it (i.e. it is deterministic). Raiders of Icepeak Mountains is based on the old Fighting Fantasy RPG, with random rolls. Let me know if you have any questions about how those work?

3 Likes

I will definitely take a look at those!

Thank you so much!

1 Like

Well, it is certainly laborious, and definitely a challenge for a beginner. But don’t be discouraged, it is not as difficult as it sounds.

My first advice is to break what you want to do into smaller tasks. This is, by the way, how professional developers write code. You already started doing that when you devised you needed to sort the order first. Great. Now break that into smaller pieces and then those pieces into smaller ones until it becomes something you can manage.

Getting familiar with ChoiceScript features will help a lot. You might also want to take a look at CSLIB, a collection of ready made subroutines for various purposes.


Here’s a starting solution, I’m writing it from the top of my head, so there’s bound to be bugs and improvements.

Combat System

Define Order
  • Sort party members by dexterity
    • Since this will be a piece of code you’ll use multiple times throughout the game, you want to keep it as a subroutine in a dedicated scene file. However, ChoiceScript does not have a way to return values from a subroutine, which means you’ll have to set up global variables to hold the value of any computation done through subroutines.
    • So, first, set up the variables that’ll hold the party order. If the party number is variable, create a list (array) considering the maximum size it can ever have. You can create each variable manually or use the new command *create_array (keep in mind that it may not be supported by CSIDE, DashingDon and other developer tools).
      *comment startup.txt
      
      *create party_1 ""
      *create party_2 ""
      *create party_3 ""
      *create party_4 ""
      
      *comment OR
      
      *create_array party 4 ""
      
    • Make sure the variables for each party member has consistency naming so it’ll be easier to refer to dynamically. For example:
      *create mc_dex 20
      *create phillipa_dex 20
      *create jordan_dex 20
      *create ariel_dex 20
      ...
      
    • Supposing you have many characters that could join the party at one point or another, save the id to the “active” party member in the party array, so it looks like this:
      *set party_1 "mc"
      *set party_2 "phillipa"
      *set party_3 "jordan"
      *set party_4 "ariel"
      
    • Then loop through the list sorting by attribute. Here’s a possible implementation. The empty comment lines inside the subroutine is to organize the code while preventing ChoiceScript from printing undesired empty lines int he output text.
      *comment ======
      *comment SORTBY
      *comment ======
      *comment This subroutine will sort the values in decreasing order
      *comment "in-place", meaning it will swap the values from one position
      *comment to another in the array.
      *comment 
      *comment It uses a simple selection sort algorithm adapted
      *comment to ChoiceScript. It loops through the array twice
      *comment comparing the values by reference.
      *comment 
      *comment It takes 3 mandatory parameters:
      *comment 
      *comment - attr (string): the name of the attribute to be checked
      *comment - array (string): the name of the array
      *comment - len (number): the length of the array, or maximum index
      *comment     to be checked
      *comment 
      *comment The array should not hold the values themselves, but a 
      *comment reference (id) to other variables. For example, "party_1"
      *comment has the values "mc" and the variable "mc_dex" has the 
      *comment actual dexterity value.
      *comment 
      *comment Usage example:
      *comment     *gosub sortBy "dex" "party" party_len
      *comment 
      *comment Considering the existing variables:
      *comment     *create mc_dex 55
      *comment     *create jordan_dex 40
      *comment     *create phillipa_dex 70
      *comment     *create ariel_dex 45
      *comment 
      *comment     *create party_len 4
      *comment     *create party_1 "mc"
      *comment     *create party_2 "jordan"
      *comment     *create party_3 "phillipa"
      *comment     *create party_4 "ariel"
      *label sortBy
      *params attr array len
      *temp i_ 1
      *label sortByOuterLoop
      *if (i_ > len)
          *goto endSortByOuterLoop
      *comment 
      *temp swapIndex i_
      *comment 
      *temp j_ (i_ + 1)
      *label sortByInnerLoop
      *if (j_ > len)
          *goto endSortByInnerLoop
      *comment 
      *if ({{"${array}_${j_}"}&"_${attr}"} > {{"${array}_${swapIndex}"}&"_${attr}"})
          *set swapIndex j_
      *comment 
      *set j_ (j_ + 1)
      *goto sortByInnerLoop
      *label endSortByInnerLoop
      *comment 
      *if (swapIndex != i_)
          *temp temp_ {"${array}_${i_}"}
          *set {"${array}_${i_}"} {"${array}_${swapIndex}"}
          *set {"${array}_${swapIndex}"} temp_
      *comment 
      *set i_ (i_ + 1)
      *goto sortByOuterLoop
      *label endSortByOuterLoop
      *return
      
Combat Loop
  • Now you have an array sorted by the desired attribute (dexterity) and by the previous example you can learn how to loop through an array and how to access values by reference. Write a subroutine that goes through the array and implement the specific combat mechanic you want. You don’t need a Queue or change the current order after sorting. Just loop over the array.
  • Remember to skip party members which have zero HP left.
3 Likes

CSIDE supports it, as long as you’re on the “Latest” update channel.

3 Likes

This topic was automatically closed 24 hours after the last reply. If you want to reopen your WiP, contact the moderators.