Jump to content

Connection Issues With OrbitCamera


Steve_Yorkshire

Recommended Posts

Stock 3.9 - no code changes:


Does anyone have any ideas what is happening and/or why?


MYgGHilVb9I


I'm using orbitCamera to get a topdown/isometric view. When moving beyond levelInfo visibleDistance from starting position it appears to lose controlObject connection - but I actually still have control of the playerObject and can walk it back into range.


TS changes: scripts/server/gamecore.cs (function GameCore::spawnPlayer) My changes listed as //YORKS in caps

function GameCore::spawnPlayer(%game, %client, %spawnPoint, %noControl)
{
   //echo (%game @"\c4 -> "@ %game.class @" -> GameCore::spawnPlayer");
 
   if (isObject(%client.player))
   {
      // The client should not already have a player. Assigning
      // a new one could result in an uncontrolled player object.
      error("Attempting to create a player for a client that already has one!");
   }
 
   // Attempt to treat %spawnPoint as an object
   if (getWordCount(%spawnPoint) == 1 && isObject(%spawnPoint))
   {
      // Defaults
      %spawnClass      = $Game::DefaultPlayerClass;
      %spawnDataBlock  = $Game::DefaultPlayerDataBlock;
 
      // Overrides by the %spawnPoint
      if (isDefined("%spawnPoint.spawnClass"))
      {
         %spawnClass = %spawnPoint.spawnClass;
         %spawnDataBlock = %spawnPoint.spawnDatablock;
      }
      else if (isDefined("%spawnPoint.spawnDatablock"))
      {
         // This may seem redundant given the above but it allows
         // the SpawnSphere to override the datablock without
         // overriding the default player class
         %spawnDataBlock = %spawnPoint.spawnDatablock;
      }
 
      %spawnProperties = %spawnPoint.spawnProperties;
      %spawnScript     = %spawnPoint.spawnScript;
 
      // Spawn with the engine's Sim::spawnObject() function
      %player = spawnObject(%spawnClass, %spawnDatablock, "",
                            %spawnProperties, %spawnScript);
 
      // If we have an object do some initial setup
      if (isObject(%player))
      {
         // Pick a location within the spawn sphere.
         %spawnLocation = GameCore::pickPointInSpawnSphere(%player, %spawnPoint);
         %player.setTransform(%spawnLocation);
 
      }
      else
      {
         // If we weren't able to create the player object then warn the user
         // When the player clicks OK in one of these message boxes, we will fall through
         // to the "if (!isObject(%player))" check below.
         if (isDefined("%spawnDatablock"))
         {
               MessageBoxOK("Spawn Player Failed",
                             "Unable to create a player with class " @ %spawnClass @
                             " and datablock " @ %spawnDatablock @ ".\n\nStarting as an Observer instead.",
                             "");
         }
         else
         {
               MessageBoxOK("Spawn Player Failed",
                              "Unable to create a player with class " @ %spawnClass @
                              ".\n\nStarting as an Observer instead.",
                              "");
         }
      }
   }
   else
   {
 
      // Create a default player
      %player = spawnObject($Game::DefaultPlayerClass, $Game::DefaultPlayerDataBlock);
 
      if (!%player.isMemberOfClass("Player"))
         warn("Trying to spawn a class that does not derive from Player.");
 
      // Treat %spawnPoint as a transform
      %player.setTransform(%spawnPoint);
   }
 
   // If we didn't actually create a player object then bail
   if (!isObject(%player))
   {
      // Make sure we at least have a camera
      %client.spawnCamera(%spawnPoint);
 
      return;
   }
 
/* //YORKS OUT START
   // Update the default camera to start with the player
   if (isObject(%client.camera) && !isDefined("%noControl"))
   {
      if (%player.getClassname() $= "Player")
         %client.camera.setTransform(%player.getEyeTransform());
      else
         %client.camera.setTransform(%player.getTransform());
   }
*/ //YORKS OUT END
 
   // Add the player object to MissionCleanup so that it
   // won't get saved into the level files and will get
   // cleaned up properly
   MissionCleanup.add(%player);
 
   // Store the client object on the player object for
   // future reference
   %player.client = %client;
 
   // If the player's client has some owned turrets, make sure we let them
   // know that we're a friend too.
   if (%client.ownedTurrets)
   {
      for (%i=0; %i<%client.ownedTurrets.getCount(); %i++)
      {
         %turret = %client.ownedTurrets.getObject(%i);
         %turret.addToIgnoreList(%player);
      }
   }
 
   // Player setup...
   if (%player.isMethod("setShapeName"))
      %player.setShapeName(%client.playerName);
 
   if (%player.isMethod("setEnergyLevel"))
      %player.setEnergyLevel(%player.getDataBlock().maxEnergy);
 
   if (!isDefined("%client.skin"))
   {
      // Determine which character skins are not already in use
      %availableSkins = %player.getDatablock().availableSkins;             // TAB delimited list of skin names
      %count = ClientGroup.getCount();
      for (%cl = 0; %cl < %count; %cl++)
      {
         %other = ClientGroup.getObject(%cl);
         if (%other != %client)
         {
            %availableSkins = strreplace(%availableSkins, %other.skin, "");
            %availableSkins = strreplace(%availableSkins, "\t\t", "");     // remove empty fields
         }
      }
 
      // Choose a random, unique skin for this client
      %count = getFieldCount(%availableSkins);
      %client.skin = addTaggedString( getField(%availableSkins, getRandom(%count)) );
   }
 
   %player.setSkinName(%client.skin);
 
   // Give the client control of the player
   %client.player = %player;
   %camera = %client.camera;//YORKS
 
   //YORKS cheats for ease of use
   %player.setName("hero");
   %camera.setName("cam");
 
   // Give the client control of the camera if in the editor
   if( $startWorldEditor )
   {
      %control = %client.camera;
      %control.mode = "Fly";
      EditorGui.syncCameraGui();
   }
   else
      %control = %player;
 
//YORKS NEW START
   %client.camera.setOrbitObject(%control, "1.308996 0 0" , 5.0, 20.0, 20.0,true, "0 -3.2 0", false);
   %client.setControlObject(%control); //- Set the control object to the player
   %client.setCameraObject(%client.camera); //- Set the camera object to the camera
 
   toggleFirstPerson(1);
   echo("client and camera " @ %client SPC %client.camera);
//YORKS NEW END
 
   // Allow the player/camera to receive move data from the GameConnection.  Without this
   // the user is unable to control the player/camera.
   //if (!isDefined("%noControl"))//YORKS OUT
   //   %client.setControlObject(%control);//YORKS OUT
}

 

EDIT: visibleDistance and ghost distance thingy work fine in "normal" third person.

Link to comment
Share on other sites

Hey Steve, try this:


in Camera::processTick, you have the main block of code that does most of the updating of position/rot stuff, contained within the if(move){ --- } block.


After that block, try adding this:

 

else
   {
      //We may just be acting as a dummy camera and observing, rather than being controlled. Make sure to update stuff in this case, as well
      CameraMotionMode virtualMode = mMode;
 
      VectorF posVec(0, 0, 0);
      bool mustValidateEyePoint = false;
      bool serverInterpolate = false;
 
      // process input/determine translation vector
      if (virtualMode == OrbitObjectMode)
      {
         if (virtualMode == OrbitObjectMode && bool(mOrbitObject))
         {
            // If this is a shapebase, use its render eye transform
            // to avoid jittering.
            GameBase *castObj = mOrbitObject;
            ShapeBase* shape = dynamic_cast(castObj);
            if (shape != NULL)
            {
               MatrixF ret;
               shape->getRenderEyeTransform(&ret);
               mPosition = ret.getPosition();
            }
            else
            {
               // Hopefully this is a static object that doesn't move,
               // because the worldbox doesn't get updated between ticks.
               mOrbitObject->getWorldBox().getCenter(&mPosition);
            }
 
            setPosition(mPosition);
         }
      }
   }

 

The issue basically is that the camera isn't the control object, so it doesn't get a move struct. It doesn't get a move struct, so it doesn't update it's position on the server. It doesn't update it's position on the server(even though the actual rendered position is updated on the client) meaning that the scope distance calculations never change because the camera hasn't 'moved'. So when the player moves too far from the camera, we leave scope.


The above code will make sure to update the camera's position if we're using ObjectOrbit mode, even in the event that the camera isn't directly controlled.


Let me know if that works for you and I'll get it PR'd in.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...