ID:147629
 
Here is what I would like to do: when this proc() for turn-based combat gets to the part where it asks the player whose turn it is what they would like to do, I would also like it to send a "Waiting for opponent..." sleep() based message to their opponent so that they are locked until the person whose turn it is gives input. This is for a text-based game, BTW.

Here is what I have:

proc/RunCombat(mob/attacker,mob/defender)
attacker.incombat = 1
defender.incombat = 1
var/whoseturn = attacker
var/list/participants = list(attacker,defender)
var/fled = 0
CombatMenu1(participants)

{EMPHASIS FROM HERE...}
while(attacker.HP > 0 && defender.HP > 0 && fled == 0)
for(var/mob/M in participants)
var/mob/opponent = Opponent(M,participants)
if(M == whoseturn)
spawn() if(istype(M,/player))
CombatMenu2(M)
choices:
var/action = GetCombatAction(M)
switch(action)
if("a")
sendtxt("You swing at [opponent.name] and do [X] damage!",M,0)
sendtxt("[M] swings at you, and it HURTS!",opponent,0)
opponent.HP -= DAMAGE
whoseturn = opponent
if("f")
sendtxt("You run away successfully!",M,0)
sendtxt("[M] runs away from combat!",opponent,0)
fled = 1
if("c")
M.client.Command("status")
goto choices
else
sendtxt("That is not a valid choice...",M,0)
goto choices
else
sleep(25)
sendtxt("The greasy, generic AI NPC hits you wimpishly.",attacker,0)
attacker.HP -= 1
sleep(25)
whoseturn = opponent
else
sendtxt("Waiting for opponent...",M,0)
while(whoseturn != M || fled == 0)
sleep(1)
{...TO HERE}

if(attacker.HP <= 0)
sendtxt("[attacker] has had the CRAP beat out of them!",oview(attacker),0)
if(defender.HP <= 0)
sendtxt("[defender] has had the CRAP beat out of them!",oview(defender),0)
attacker.incombat = 0
defender.incombat = 0

The spawn and else procs I am trying to use for this purpose are hilighted to be easier to locate. If there is a totally different method to do what I am trying to, I am fine with that!

Yes, this is a very simple combat proc, but I need to get past this little dilemma before moving on to something more cplicated :-). The next step is to handle people trying to enter a combat two people are already in, and after that is handling group combat. Yay!

=$= Big J Money =$=
Sorry guys. It was late last night, and I didn't even post what my problem was!!

The problem is this: when it's the attacker's turn to make a combat choice, it does tell the other player "Waiting for opponent...". When the attacker is finished, it does end the "Waiting for opponent..." loop for the other player. After this, however, the whole proc simply stops and combat ends. Due to my first while loop, it SHOULD go to the next round, giving the defender a chance to make a move. If I get rid of the spawn, it works, but of course it doesn't tell the defender "Waiting for opponent..." and so they are allowed to type in regular MUD commands in the middle of combat (that is very bad).

Thanks

=$=
In response to BigJMoney
I would go with a slightly different system, centering around a datum to control the flow of battle. This is untested, but should give you a basic skeleton to work with:
mob
var
tmp/CombatControl/battle // for backwards compatability


CombatControl // combatcontrol obj for a specific fight.
var
list
participants = list()

mob/CurrentTurn
turn_counter = 0

proc
StartBattle()
// Tell all participants they are now fighting.
// and set anything that needs to be set on their mobs.

NextTurn()

EndBattle()
for(var/mob/M in participants)
RemoveFighter(M)

del src

AddParticipant(mob/M)
if(M in participants) return 0
participants.Add(M)
M.battle = src

RemParticipant(mob/M)
if(!(M in participants)) return 0
participants.Remove(M)
M.battle = null

NextTurn()
CurrentTurn = participants[++turn_counter]
if(turn_counter >= length(participants))
turn_counter = 0

// Tell CurrentTurn it is now their turn.
spawn()
Choices(M)

sleep(MAX_TURN_TIME)
NextTurn() // They used too much time - Next player!

Choices(mob/M)
// Your battle choices here.
// Remember to check if(CurrentTurn==M) every time you've asked
// M for input, since the time limit could've run out, or they could've
// disconnected from the game.


Whenever you need to check if a player is fighting, if(player.battle) will suffice. You will probably want a mob variable called 'target', storing who they originally initiated the fight against, just incase you need that later.

If you need to check if a player can do something, check if its their turn by comparing player.battle.CurrentTurn to player(ie if(player == player.battle.CurrentTurn) // Its their turn!)