Event Every X Turns: No ASM!


#1

Do you want a turn event to be fancy and only happen… say… every five turns? Read on to learn how.

This can be achieved with conditional trees fairly easily.
For simplicity’s sake, I’m going to write this using FE7 conditional, but I will include FE8 near the end. I think FE7 conditional is a bit easier to read.

[details=Event Every Two Turns]

IFEF 0x01 0x10 //Insert events to occur here ENUT 0x10 ELSE 0x02 ENIF 0x01 ENUF 0x10 ENIF 0x02 [/details]

Simple. Right? Plus, I bet you’ve seen this before with a little ASM routine. What about every three turns, though?

[details=Event Every Three Turns] IFEF 0x01 0x10 IFEF 0x02 0x11 //Insert events to occur here ENUT 0x10 ENUT 0x11 ELSE 0x03 ENIF 0x02 ENUF 0x11 ENIF 0x03 ELSE 0x04 ENIF 0x01 ENUF 0x10 ENIF 0x04[/details]

Think about what happens each turn.
Assume that event IDs 0x10 and 0x11 are unused from the begining.

  1. Success. 0x10 and 0x11 are now used.
  2. Failure. 0x10 is now unused, and 0x11 is still used.
  3. Failure. 0x10 and 0x11 are now unused.
  4. Success. 0x10 and 0x11 are now used.

All you have to do is add another ‘level’ of conditional for every turn you want to skip. You could do every four, five, six, or however many your heart desires to skip. Well… I honestly don’t know if turn events work past turn 256, but if you want to do that many levels of conditional and make a chapter that big, good luck figuring out how to use that many event IDs!

But what if I told you that you could have an event every 256 turns with only eight levels of conditional? OK. That’s impractical. How about every four with two levels and eight with only three?
Here’s how.

[details=Event Every Four Turns] IFEF 0x01 0x10 IFEF 0x02 0x11 //Insert events to occur here ENUT 0x11 ELSE 0x03 ENIF 0x02 ENUF 0x11 ENIF 0x03 ENUT 0x10 ELSE 0x04 ENIF 0x01 ENUF 0x10 ENIF 0x04[/details]

This one works differently from the previous method.

  1. Success: 0x10 and 0x11 are now used
  2. Failure: 0x10 is now unused, but 0x11 is still used
  3. Failure: 0x10 is now used, but 0x11 is now unused
  4. Failiure: 0x10 is now unused, yet 0x11 is still unused
  5. Success: 0x10 and 0x11 are now used

Instead of having a linear relationship between levels of conditional and turns skipped, this works exponentially with the following function:

y=2^x where y is the number of turns in each cycle, and x is the number of conditional levels needed.
For example, if you have 8 turns per cycle, you would need three conditional levels.


Let me give an example on how to properly use this. Included is also an example of how you could alternate between calling three different events in this cycle.

[details=Every Three Turns Example][code]
Turn_events:
OpeningTurnEvent(Opening_event)
TURN Reinforcements [1,256] 0x0 0x0
END_MAIN

Reinforcements:
IFEF 0x01 0x10
IFEF 0x02 0x11
TEX1 [0x872]
LOU1 Meanies3
ENUT 0x10
ENUT 0x11
ELSE 0x03
ENIF 0x02
ENUF 0x11
LOU1 Meanies2
ENIF 0x03
ELSE 0x04
ENIF 0x01
ENUF 0x10
LOU1 Meanies1
ENIF 0x04
ENDA[/code][/details]

Just think about where you will be in the conditional tree in each turn and put your commands for each turn there.


Now, we like EA and buildfile, but we really like macros. Right?

[details=Macros][code]

#ifdef FE8
#define Every2Turns(CondID1,CondID2,EventID,Pointer) “CHECK_EVENTID EventID;BNE CondID1 0x0 0xC;CALL Pointer;ENUT EventID;GOTO CondID2;LABEL CondID1;ENUF EventID;LABEL CondID2”

#define Every3Turns(CondID1,CondID2,CondID3,EventID1,EventID2,Pointer) “CHECK_EVENTID EventID1;BNE CondID1 0x0 0xC;CHECK_EVENTID EventID2;BNE CondID2 0x0 0xC;CALL Pointer;ENUT EventID1;ENUT EventID2;GOTO CondID3;LABEL CondID2;ENUF EventID2;GOTO CondID3;LABEL CondID1;ENUF EventID1;LABEL CondID3”

#define Every4Turns(CondID1,CondID2,CondID3,EventID1,EventID2,Pointer) “CHECK_EVENTID EventID1;BNE CondID1 0x0 0xC;CHECK_EVENTID EventID2;BNE CondID2 0x0 0xC;CALL Pointer;ENUT EventID1;ENUT EventID2;GOTO CondID3;LABEL CondID2;ENUT EventID1;ENUF EventID2;GOTO CondID3;LABEL CondID1;ENUF EventID1;LABEL CondID3”

#else//Probably work in FE6 too, but untested.

#define Every2Turns(CondID1,CondID2,EventID,Pointer) “IFEF CondID1 EventID;CALL Pointer;ENUT EventID;ELSE CondID2;ENIF CondID1;ENUF EventID;ENIF CondID2”

#define Every3Turns(CondID1,CondID2,CondID3,CondID4,EventID1,EventID2,Pointer) “IFEF CondID1 EventID1;IFEF CondID2 EventID2;CALL Pointer;ENUT EventID1;ENUT EventID2;ELSE CondID3;ENIF CondID2;ENUF EventID2;ENIF CondID3;ELSE CondID4;ENIF CondID1;ENUF EventID1;ENIF CondID4”

#define Every4Turns(CondID1,CondID2,CondID3,CondID4,EventID1,EventID2,Pointer) “IFEF CondID1 EventID1;IFEF CondID2 EventID2;CALL Pointer;ENUT EventID2;ELSE CondID3;ENIF CondID2;ENUF EventID2;ENIF CondID3;ENUT EventID1;ELSE CondID4;ENIF CondID1;ENUF EventID1;ENIF CondID4”

#endif[/code][/details]

Macros are tested and do work. I can make more (Every 5 turns, etc.) upon request.

Be sure to not put these macros under turn events. Have a turn event point with a pointer with a label with the macro, then have the macro point to a label with the events that you wouldn’t want to happen each turn.

Skeptical? Here it is in action.

https://youtu.be/nacpxUAEpYE


#2

This is what i used for alternating between 5 different groups of units each turn in Shattered Stones:

SpawnReinforcements1:
  CHECK_TURNS //store current turn to slot c
  //Now get remainder mod 5
  SMOV r1 0x5
  SDIV slotsParam(r2, rC, r1) //r2 = rC/5
  SMUL slotsParam(r1, r2)     //r1 = r2*5
  SSUB slotsParam(r1, rC, r1)     //r1 -= rC, r1 = remainder
  BNE 0x0 r1 0
  ReinforcementEvent(Group5)    //Remainder was 0 (right)
  LABEL 0x0
  SMOV r2 1
  BNE 0x1 r1 r2
  ReinforcementEvent(Group3)
  LABEL 0x1
  SMOV r2 2
  BNE 0x2 r1 r2
  ReinforcementEvent(Group1)
  LABEL 0x2
  SMOV r2 3
  BNE 0x3 r1 r2
  ReinforcementEvent(Group2)
  LABEL 0x3
  ReinforcementEvent(Group4)
  NoFade
  ENDA

#3

Hey, circles. How would I make an FE8 equivalent to my turn skips using CHECK_EVENTID? This has eluded me.


#4

Basically CHECK_EVENTID will check the event ID in question and store either 1 or 0 into memory slot 0xC.
Then you check the result in memory slot 0xC and branch accordingly.

so like

Reinforcements:
CHECK_EVENTID 0x10
BNE 0x1 0xC 0x0 //if slot C != slot 0 (event ID set), branch to LABEL 0x1
  CHECK_EVENTID 0x11
  BNE 0x2 0xC 0x0 //if slot C != slot 0 (event ID set), branch to LABEL 0x2
    Text(something)
    LoadReinforcements(Meanies)
    ENUT 0x10 //set event ID
    ENUT 0x11 //set event ID
    GOTO 0x03 //go to label 0x03 (honestly you should just go to LABEL 0x04 here but i'm keeping the structure from your fe7 one)
  LABEL 0x02
    ENUF 0x11 //unset event ID
  LABEL 0x03
    GOTO 0x04
LABEL 0x01
  ENUF 0x10 //unset event ID
LABEL 0x04
NoFade
ENDA

#5

Ah. I didn’t know that you could add a byte to the CHECK_EVENTID code like the others. It didn’t look like you could in the EA library.
I learned FE7 conditional before GOTO_IFEF or anything like that came out, so I’m just now starting to learn that.

Thanks for your help, circles!