Turn-based combat - turn starts for two allies

I am making a turn-based RPG game in UE5 with C++ (with 2D sprites). Think of something like Darkest Dungeon but with memes and no procedural generation. For the most part my combat system works, but sometimes the turn triggers for an allied character that isn’t even in the party (another ally performs their attack) and sometimes the turn triggers for two allies at once - when one attacks, the other does too, same with using an items.
For my allies I have two arrays - AlvailableAllies that stores all allies regardless of whether they’re in the party or not and AlliedParty - the actual party.
For fight encounters I have an actor class - AFightEncounter that spawns enemies and deals with what happens after the fight and a regular object UFight that is created when the fight is started and handles the fight itself.
I’ve tried debugging - looks like StartTurn() (and Use Item() as well when we choose to use an item) is called twice for different allies, I suspect it might be ralated to my timers - one that introduces a bit of delay between turns, the other that prevents the enemy from being stuck on their turn when they can’t use any skill. I honestly don’t have any idea what to do about it.

Here’s the code on pastebin, because I don’t know if there’s a character limit here:

If it’s not very readible lket me know if i should split each source file into separate link. Thank you in advance.

in Fight.cpp you seem to have pasted a header file. There are no implementations inside of Fight.cpp of any of the functions just a clone of Fight.h

1 Like

oh, sorry for that, edited it out

Unfortunately there is too little information to dig into the problem.
I’m guessing that maybe the building of AlliedParty inside of your CurrentGameMode may be the source of the problem. I don’t have access to the function that builds the allied party but maybe you are duplicating the pointer to a specific character (maybe a bad for loop?)

Maybe consider using AddUnique for your TArray to not add duplicates.

Fight->AlliedParty = CurrentGameMode->AlliedParty;

inside of AFightEncounter::SetupAllies()

This is the variable that really dictates how the turns pan out as it takes in the allied party and then enemies to build the turn order in void UFight::BuildTurnOrder(){}.

I pasted my DefaultGameMode class here: DefaultGameMode - Pastebin.com
Although I don’t understand how it could cause starting a turn twice with different allies. If you explained it a bit I’d really appreciate it.
Edit: Oh, and i’m actually using AddUnique both for Available allies and AlliedParty, completely forgot that as it was couple of months ago

Well it’s just causing more missing files at this point. Try putting a break-point durning the turn build process (in visual studio F9) and then try stepping through the code (F10) to see where the errors are occurring

You can disable code optimizations with this:

It will help you evaluate the contents of TArrays while the code is running (usually optimizations will obstruct the code)

Other than this on the screenshot I don’t see anything weird (it just is like that at the end, when I’m enqueueing the tail is the first character from BothParties, then it disappears). BothParies array is fine, nothing unexpected here.


Maybe it’s garbage collected somehow, but when I try set it as a Uproperty it won’t compile. Maybe i can ditch the queue and make it a regular array that i remove the last element from at the beggining of the turn so i can make it a uproperty but I don’t know if it’ll make it any better

Ok, when it built turn order the second time there was an ally that is not in my party and it’s the one that i swaped out before the fight

Maybe you should consider isolating the queue for the fight & it’s logic to a separate fight manager. Right now you seem to have the logic for building and managing the flow of battle spread out to many areas.

Sometimes the game mode, other times the in AFightEncounter.

Anything that happens during the battle is handled in UFight. I have to have my party in the game mode as I need it in the exploration and dialogues

The funny thing is it doesn’t happen when staring new game or loading from save, only after adding new ally to party/replacing one ally with another, I change how I handle that but it still happens

Could it be that 2 allies always just have a higher speed that dictate that they start the turn?
Maybe the speed calculation is somehow influencing the outcome?

but that just sorts the array and it seems to be sorting it fine from what I’ve seen in the debugger

I’ve noticed that the Fight has it’s own timer and each character internally also has their own timer.
you use
CurrentCharacter->TurnTimer at one point but do not ever clear or reset it. Is this done internally through ACombatCharacter::BeginTurn function?

No, everthing is inside UFight, the TurnTimer handle exist only in UFight, I used characters because only Actors have access to the world timer manager

EDIT: I completely forgot the characters have their own turn timer as well lol

I pushed my sourcecode to github as I plan to release the game free on itch anyway. i made some changes to the classes I included in the pastebin file but those issues still persist GitHub - WKogut98/WirSprawiedliwosci: Turn-based RPG based on proboscis monkey meme

Copilot suggested checking if TurnQueue is empty at the start of a turn, to my surprise it might have worked, because I played 3 fights like I did before and haven’t encountered those problems. Obviously the sample size is a bit too small to know for sure and that solution seem random but I’ll take whatever I can get