/*
  Created By: Lilivati  02.09.2004
  Updated By: Jaysyn 2022.11.19

  This script has a commander issuing orders to a group of trainees.  I use it in the OnHeartbeat
    event for an area.

  The demo mod uses 6 trainees, but any number will do.
  You can change the existing case statement actions to whatever you want the trainees to do,
     but if you want to add more actions, you have to change line 35 to a different die.

  Important Info:
  1) In Case 1, you need to set the direction in the last line before break to whatever
     direction your trainees were originally facing.
  2) Case 1 (Attack!) tends to break up orderly trainee lines.  I tried to compensate for
     this, but I'm only moderately happy with the result.  Check out the demo mod to see
     what I mean.  Widely spacing the trainees also seems to help.  (This would have been
     much cleaner if combat animations were available as constants...)
  3) Make sure your invisible objects are outside of the trainee's "space" or it won't look
     nice in the module
  4) To demonstrate Case 4, my trainees have artificially high hide skill ranks, and the
     Hide In Plain Sight feat.  Normal trainees will fail to hide from most PCs. (Note: if
     your trainees do not have this feat, you might want to comment out (//) line 75)

  Objects needed:
    Commander: NPC, tag "COMMANDER"
    Trainee: NPC, tag "TRAINEE"
    An invisible object placed in front of each trainee, useable, plot object, with faction set to Hostile
    A waypoint where each trainee is standing
*/

void main()
{
//:: Declare major variables
    int i = 0;
    object oComm = GetObjectByTag("RA_HU_M_DRILL01");
    object oNoob = GetObjectByTag("RA_HU_M_TRAIN01", i);
    object oDummy = GetObjectByTag("ra_plc_cmb_dummy");

    float fFacing = GetFacing(oNoob);

//:: this "if" statement is nice if you're using the commander in more than one area; if the "if"
//:: statement isn't present, wherever the commander is she'll be yelling "Attack!" "Duck!" etc.
    if(GetArea(GetFirstPC()) == GetObjectByTag("WarriorsGuild"))
    {
        int nRoll = d10(1);

        while(oNoob != OBJECT_INVALID)
        {
            switch (nRoll)
            {
            //:: trainees attack nearest invisible object and return to position of nearest waypoint
                case 1:
                AssignCommand(oComm,ActionSpeakString("Attack!"));
                DelayCommand(0.1f,AssignCommand(oNoob,SetFacing(DIRECTION_NORTH)));
                DelayCommand(1.0f,AssignCommand(oNoob,ActionAttack(oDummy, FALSE)));
                //DelayCommand(6.0f,AssignCommand(oNoob,ActionMoveToObject(GetNearestObjectToLocation(OBJECT_TYPE_WAYPOINT,GetLocation(oNoob)),TRUE,1.0f)));
                DelayCommand(7.0f,AssignCommand(oNoob,SetFacing(DIRECTION_NORTH)));
                break;

            //:: trainees execute duck animation
                case 2:
                AssignCommand(oComm,ActionSpeakString("Duck!"));
                DelayCommand(1.0f,AssignCommand(oNoob,ActionPlayAnimation(ANIMATION_FIREFORGET_DODGE_DUCK,1.0f)));
                DelayCommand(5.0f,AssignCommand(oNoob,ClearAllActions(TRUE)));
                break;

            //:: trainees execute dodge animation
                case 3:
                AssignCommand(oComm,ActionSpeakString("Dodge!"));
                DelayCommand(1.0f,AssignCommand(oNoob,ActionPlayAnimation(ANIMATION_FIREFORGET_DODGE_SIDE,1.0f)));
                DelayCommand(5.0f,AssignCommand(oNoob,ClearAllActions(TRUE)));
                break;

            //:: trainees attack nearest invisible object and return to position of nearest waypoint
                case 4:
                AssignCommand(oComm,ActionSpeakString("Attack!"));
                DelayCommand(0.1f,AssignCommand(oNoob,SetFacing(DIRECTION_NORTH)));
                DelayCommand(1.0f,AssignCommand(oNoob,ActionAttack(oDummy, FALSE)));
                //DelayCommand(6.0f,AssignCommand(oNoob,ActionMoveToObject(GetNearestObjectToLocation(OBJECT_TYPE_WAYPOINT,GetLocation(oNoob)),TRUE,1.0f)));
                DelayCommand(7.0f,AssignCommand(oNoob,SetFacing(DIRECTION_NORTH)));
                break;

            //:: trainees execute duck animation
                case 5:
                AssignCommand(oComm,ActionSpeakString("Duck!"));
                DelayCommand(1.0f,AssignCommand(oNoob,ActionPlayAnimation(ANIMATION_FIREFORGET_DODGE_DUCK,1.0f)));
                DelayCommand(5.0f,AssignCommand(oNoob,ClearAllActions(TRUE)));
                break;

            //:: trainees execute dodge animation
                case 6:
                AssignCommand(oComm,ActionSpeakString("Dodge!"));
                DelayCommand(1.0f,AssignCommand(oNoob,ActionPlayAnimation(ANIMATION_FIREFORGET_DODGE_SIDE,1.0f)));
                DelayCommand(5.0f,AssignCommand(oNoob,ClearAllActions(TRUE)));
                break;

            //:: trainees go into stealth mode and then leave stealth mode
                case 7:
                AssignCommand(oComm,ActionSpeakString("Hide!"));
                DelayCommand(1.0f,AssignCommand(oNoob,ActionUseSkill(SKILL_HIDE,GetFirstPC(),0,OBJECT_INVALID)));
                DelayCommand(2.0f,AssignCommand(oNoob,ActionUseFeat(FEAT_HIDE_IN_PLAIN_SIGHT,GetFirstPC())));
            //:: they're trainees so they're pretty bad at hiding :)
                DelayCommand(5.0f,AssignCommand(oComm,ActionSpeakString("Pitiful!")));
                DelayCommand(7.0f,AssignCommand(oNoob,ClearAllActions(TRUE)));
                break;

            //:: trainees attack nearest invisible object and return to position of nearest waypoint
                case 8:
                AssignCommand(oComm,ActionSpeakString("Attack!"));
                DelayCommand(0.1f,AssignCommand(oNoob,SetFacing(DIRECTION_NORTH)));
                DelayCommand(1.0f,AssignCommand(oNoob,ActionAttack(oDummy, FALSE)));
                //DelayCommand(5.0f,AssignCommand(oNoob,ClearAllActions(TRUE)));
                //DelayCommand(6.0f,AssignCommand(oNoob,ActionMoveToObject(GetNearestObjectToLocation(OBJECT_TYPE_WAYPOINT,GetLocation(oNoob)),TRUE,1.0f)));
                DelayCommand(7.0f,AssignCommand(oNoob,SetFacing(DIRECTION_NORTH)));
                break;

             //:: trainees execute salute animation
                case 9:
                AssignCommand(oComm,ActionSpeakString("Salute!"));
                DelayCommand(1.0f,AssignCommand(oNoob,ActionPlayAnimation(ANIMATION_FIREFORGET_SALUTE,1.0f)));
                DelayCommand(5.0f,AssignCommand(oNoob,ClearAllActions(TRUE)));
                break;

            //:: trainees sit on ground
                case 10:
                AssignCommand(oComm,ActionSpeakString("Alright, take a short break."));
                DelayCommand(1.0f,AssignCommand(oNoob,ActionSpeakString("Finally!")));
                DelayCommand(2.0f,AssignCommand(oNoob,ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS,1.0f,4.0f)));
                DelayCommand(7.0f,AssignCommand(oNoob,ClearAllActions(TRUE)));
                break;
            }

        i++;
        oNoob = GetObjectByTag("RA_HU_M_TRAIN01",i);
        }
    }
}