Toggle chasecam/mouselook with custom player states?

Tue Jan 11, 2022 9:45 am

I've begun work on a nice 3rd-person WAD using a modified version of LordOZ's SRB2 chasecam script. My idea is the third-person view restricts the player to melee attacks, with a separate key to draw your gun, which ideally kills the chasecam and switches to a first-person view.

My thought is that when in 3rd-person, mouselook is disabled, but when in first-person aiming mode, the player can look up and down but cannot move until you put away your gun. Basically a bit like an old N64-era platformer - third-person but with a first-person "look" mode where the player is immobile, but can look in any direction to aim and fire his weapon.

I am still in the process of teaching myself what everything does in the ACS script for the chasecam. One idea I had is to define two custom cameras, one for the normal view and the other for the first-person aiming view, and swap between them depending on what state the player is currently in. As for toggling mouselook and player movement, I am less sure about that, or if it is even possible. Maybe player movement can be disabled by temporarily setting the player's speed to zero when he enters the aiming state, but I am not sure.

I'd love to hear some feedback on what can be done, or some good workarounds if not everything is possible.

Re: Toggle chasecam/mouselook with custom player states?

Wed Jan 12, 2022 9:02 am

You don't need two cameras for this, as the player actor itself is a camera.
In an ACS script you can use ChangeCamera to change the current camera to TID, or back to the player if the TID is 0.
Changing back to the player will also make it show the current weapon on the HUD.

For freezing player movement you can use SetPlayerProperty(PROP_FROZEN) and it will still allow the player to move the camera and interact with things.
For keeping the pitch in place in 3rd person, use ChangeActorPitch to keep it at 0. (centered)
Remember to make the chasecam not inherit the pitch with this solution, as it will be visibly jerking the camera back in place, but that shouldn't be an issue if the chasecam does not inherit player's pitch.

If I could see the code, I would be able to help more.

Re: Toggle chasecam/mouselook with custom player states?

Wed Jan 12, 2022 9:40 am

Thanks so much for getting back to me! I had no idea all three of those were possible, that is good news.

As for the code, there really is not much currently aside from adapting the SRB2 chasecam script. The result is rather nice though, albeit basic, when tested in vanilla Doom. You can see the Doom player just like you would a normal chasecam, but interestingly toggling the chasecam in the console seems to switch between the vanilla cam and the custom one defined in the script.

Anyways here's what I've got so far.

Code:
// ACS
#library "cam"
#include "zcommon.acs"
#include "GravityValues.acs"

// Original script by RomioTheBadass - aka LordOZ_98, based on
// the ArmyGuy's code
// Currently no modifications have been made, as I am still rather new to
// ACS and trying to figure out how it works compared to Decorate and ZScript

script 815 (void) NET CLIENTSIDE //Managing chasecam
{
  if(IsNetworkGame())
  {
  consolecommand("chase");
  }
  else
  if (GetCVar("chase_active") == true)
   {
   SetCVar("Chase_Active", False);
   }
  else
  if (GetCVar("chase_active") == False)
   {
   SetCVar("Chase_Active", True);
   }
}

// Scripts
Script "WaypointSpawn" (void)
{
   int tid = UniqueTID(-32768, 32767);
   Thing_ChangeTID(ActivatorTID(), tid);
   SetActivatorToTarget(tid);
   int playerNum = PlayerNumber();
   camWayTID[playerNum] = tid;
   SetActorProperty(camTID[playerNum], APROP_MasterTID, camWayTID[playerNum]);
   SetActorPosition(tid, GetActorX(tid), GetActorY(tid), GetActorZ(0) + GetActorProperty(0, APROP_Height) + GetCVar("chase_height"), false);
   GiveActorInventory(camTID[playerNum], "WarpToWaypoint", 1);
}

Script "CameraMain" ENTER
{
   // Set up the TID's and spawn the waypoint
   int tid, playerNum, plrInput, yawAdd, pitchAdd, plrRotType, a, p;
   int plrAngle = GetActorAngle(0);
   playerNum = PlayerNumber();
   tid = UniqueTID(-32768, 32767);
   camTID[playerNum] = tid;
   SpawnForced("ChaseCam", GetActorX(0), GetActorY(0), GetActorZ(0), tid, GetActorAngle(0));
   while (true)
   {
      plrInput = GetPlayerInput(-1, INPUT_BUTTONS);
        yawAdd = GetPlayerInput(-1, INPUT_YAW);
        pitchAdd = -GetPlayerInput(-1, INPUT_PITCH);
      a = a + yawAdd;
      p = p + pitchAdd;
      if (p > 0.23)
         p = 0.23;
      if (p < -0.23)
         p = -0.23;
      Thing_Remove(camWayTID[playerNum]);
      LineAttack(0, a + 0.5, -p, 0, "ChaseCamWaypoint", "", GetCVar("chase_dist"), FHF_NORANDOMPUFFZ);
      SetActorAngle(camWayTID[playerNum], a);
      SetActorPitch(camWayTID[playerNum], p);
      SetActorAngle(camTID[playerNum], a);
      SetActorPitch(camTID[playerNum], p);
      plrRotType = GetCVar("chase_rotateplr");
      if (plrRotType == 1)
         plrAngle = a;
      else if (plrRotType == 2)
      {
         if (plrInput & BT_FORWARD || plrInput & BT_BACK || plrInput & BT_MOVELEFT || plrInput & BT_MOVERIGHT || plrInput & BT_ATTACK || plrInput & BT_ALTATTACK)
            plrAngle = a;
      }
      If(IsNetworkGame())
      {
      terminate;
      }
      else
      if (GetCVar("chase_active"))
         ChangeCamera(camTID[playerNum], 0, 0);
      else
      {
         plrAngle = a;
         ChangeCamera(0, 0, 0);
      }
      SetActorAngle(0, plrAngle);
      SetActorPitch(0, p);
      Delay(1);
   }
}

script "coopchase" (void)
{
ConsoleCommand("chase");
}


And this is the code in GravityValues:
Code:
#DEFINE WATERGRAVITY 0.4
#DEFINE GLIDEGRAVITY 0.1
#DEFINE DEFAULTGRAVITY 0.90

int candrown = 0;
int nojump = 1;

int spinning[64];
int GlideState[64];

int monitorthrust[64];

#define MAXPLAYERS 64

#define PLAYER_TID_START 300

int camTID[MAXPLAYERS];
int camWayTID[MAXPLAYERS];


I believe learning more ACS is in order, and I will probably enjoy messing around with the functions you suggested.