Skip to content

Commit 1917e61

Browse files
committed
swars: Move to next non-until cmd when finishing a command
When "until" command is selected as active, we have limited ability to track the state of a person - we'd have to start iterating eact time we need to check which command is actually active. This should always keep the correct command as active.
1 parent 96f09c6 commit 1917e61

File tree

2 files changed

+36
-25
lines changed

2 files changed

+36
-25
lines changed

src/command.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,15 @@ enum PersonCommandFlags
283283
PCmdF_Unkn0001 = 0x0001,
284284
/** The command is executed only while condition is met in "UNTIL" command which comes next.
285285
* Note that the command is not repeated - if it returns it's finished, the until block ends.
286+
* If the command is "UNTIL" command, but the next one is another UNTIL, then failing any one
287+
* of the conditions will break the loop.
286288
*/
287289
PCmdF_RunUntil = 0x0002,
288290
/** The command is kind of a "UNTIL" command which allows to terminate previous command.
289291
* The previous command is executed until the additional condition is met. When the condition
290292
* resolves to false, previous command stops being executed even if it did not finished.
293+
* If a command is followed by multiple "UNTIL" conditions, only the last one should have
294+
* this flag set.
291295
*/
292296
PCmdF_IsUntil = 0x0004,
293297
/** The command has its function reverted.

src/people.c

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,19 +1578,30 @@ ushort person_command_until_check_condition(struct Thing *p_person, ushort cond_
15781578
{
15791579
struct Command *p_cmd;
15801580
ushort cmd;
1581-
TbBool until_met;
1581+
TbBool until_met, has_more_conditions;
15821582

15831583
p_cmd = &game_commands[cond_cmd];
15841584
cmd = p_cmd->Next;
15851585
until_met = false;
1586+
has_more_conditions = ((p_cmd->Flags & PCmdF_RunUntil) != 0);
15861587

15871588
while (1)
15881589
{
15891590
if (cmd == 0)
15901591
break;
15911592
p_cmd = &game_commands[cmd];
1592-
if ((p_cmd->Flags & PCmdF_IsUntil) == 0)
1593-
break;
1593+
if ((p_cmd->Flags & PCmdF_RunUntil) == 0)
1594+
has_more_conditions = false;
1595+
if (!has_more_conditions) {
1596+
if ((p_cmd->Flags & PCmdF_IsUntil) == 0)
1597+
break;
1598+
// After RunUntil commands and then IsUntil command, this loop should be broken
1599+
// If it is not, then something is wrong with flags of the commands.
1600+
if ((p_cmd->Flags & PCmdF_RunUntil) != 0) {
1601+
LOGWARN("Person %s %d command %d has broken chain of UNTIL commands at %d",
1602+
person_type_name(p_person->SubType), (int)p_person->ThingOffset, cond_cmd, cmd);
1603+
}
1604+
}
15941605
if (conditional_command_state_true(cmd, p_person, 3)) {
15951606
if (gameturn <= 1) {
15961607
LOGWARN("Person %s %d command %d end condition %d met just at start of the game",
@@ -1616,25 +1627,36 @@ ushort person_command_until_check_condition(struct Thing *p_person, ushort cond_
16161627
return cmd;
16171628
}
16181629

1619-
/** Gives the next command beyond conditions.
1630+
/** For given command, return the next command beyond any "until" conditions.
16201631
*
1621-
* @return Gives index of next command beyond "until" consitions, regardless
1632+
* @return Gives index of next command beyond "until" conditions, regardless
16221633
* whether any of the conditions is met or not.
16231634
*/
16241635
ushort person_command_until_skip_condition(struct Thing *p_person, ushort cond_cmd)
16251636
{
16261637
struct Command *p_cmd;
16271638
ushort cmd;
1639+
TbBool has_more_conditions;
16281640

1629-
cmd = cond_cmd;
1641+
p_cmd = &game_commands[cond_cmd];
1642+
cmd = p_cmd->Next;
1643+
has_more_conditions = ((p_cmd->Flags & PCmdF_RunUntil) != 0);
16301644

16311645
while (1)
16321646
{
16331647
if (cmd == 0)
16341648
break;
16351649
p_cmd = &game_commands[cmd];
1636-
if ((p_cmd->Flags & PCmdF_IsUntil) == 0)
1637-
break;
1650+
if ((p_cmd->Flags & PCmdF_RunUntil) == 0)
1651+
has_more_conditions = false;
1652+
if (!has_more_conditions) {
1653+
if ((p_cmd->Flags & PCmdF_IsUntil) == 0)
1654+
break;
1655+
if ((p_cmd->Flags & PCmdF_RunUntil) != 0) {
1656+
LOGWARN("Person %s %d command %d has broken chain of UNTIL commands at %d",
1657+
person_type_name(p_person->SubType), (int)p_person->ThingOffset, cond_cmd, cmd);
1658+
}
1659+
}
16381660
cmd = p_cmd->Next;
16391661
}
16401662

@@ -1645,31 +1667,27 @@ ushort person_command_until_skip_condition(struct Thing *p_person, ushort cond_c
16451667
*/
16461668
void person_command_select_next(struct Thing *p_person)
16471669
{
1648-
struct Command *p_cmd;
16491670
ushort cmd;
16501671

16511672
cmd = p_person->U.UPerson.ComCur;
16521673
if (cmd == 0)
16531674
return;
16541675

1655-
p_cmd = &game_commands[cmd];
1656-
p_person->U.UPerson.ComCur = person_command_until_skip_condition(p_person, p_cmd->Next);
1676+
p_person->U.UPerson.ComCur = person_command_until_skip_condition(p_person, cmd);
16571677
}
16581678

16591679
/** Discards a command at top of the person stack.
16601680
* The command is then never used again.
16611681
*/
16621682
void person_command_skip_at_start(struct Thing *p_person)
16631683
{
1664-
struct Command *p_cmd;
16651684
ushort cmd;
16661685

16671686
cmd = p_person->U.UPerson.ComHead;
16681687
if (cmd == 0)
16691688
return;
16701689

1671-
p_cmd = &game_commands[cmd];
1672-
p_person->U.UPerson.ComHead = person_command_until_skip_condition(p_person, p_cmd->Next);
1690+
p_person->U.UPerson.ComHead = person_command_until_skip_condition(p_person, cmd);
16731691
}
16741692

16751693
/** Jump to specific command on a person.
@@ -2766,17 +2784,6 @@ void person_init_command(struct Thing *p_person, ushort from)
27662784
break;
27672785
}
27682786

2769-
// Skip any detached "until" conditions for which we do not have a command
2770-
nxcmd = person_command_until_skip_condition(p_person, cmd);
2771-
if (nxcmd != cmd) {
2772-
// Currently this log would be too verbose - we switch states
2773-
// without skipping the follwing `until` in some places.
2774-
LOGNO("Person %s %d state %d.%d command %d is detached 'until'",
2775-
person_type_name(p_person->SubType), (int)p_person->ThingOffset,
2776-
p_person->State, p_person->SubState, cmd);
2777-
}
2778-
cmd = nxcmd;
2779-
27802787
if (cmd == 0)
27812788
{
27822789
if ((p_person->Flag2 & TgF2_Unkn0800) != 0)

0 commit comments

Comments
 (0)