Jump to content

Steve_Yorkshire

Contributor
  • Posts

    353
  • Joined

  • Last visited

Posts posted by Steve_Yorkshire

  1. Had another look at it with a clear head and realised why it's not working.


    The "onlyCollideWithTarget" var is set to teleport the projectile to the target at the end of it's lifetime and does not actually collide with it ... which is ... er ... odd. Might have been useful for whatever you originally envisioned but ... odd ... for general projectile use. The "onlyCollideWithTarget" var doesn't feature anywhere else except as a negative with collision checking.

    void FXProjectile::simulate( F32 dt )
    {
    	if ( isServerObject() && mCurrTick >= mDataBlock->lifetime )
    	{
    		if(mTargetObject && mOnlyCollideWithTarget && mHoming)
    		{
    			VectorF normal = -getVelocity();
    			normal.normalize();
    			onCollision( getPosition(), normal, mTargetObject );
    			explode( getPosition(), normal, mTargetObject->getTypeMask() );
    		}
    		deleteObject();
    		return;
    	}

     

    So I commented that out and put in a positive check for targetObject, OnlyCollideWithTarget and homing vars. Nothing fancy, just working as normies would expect projectile to. So here's what the new simulate function looks like.

    void FXProjectile::simulate( F32 dt )
    {
    	/* //yorks out - why Lucas why!? :P
    	if ( isServerObject() && mCurrTick >= mDataBlock->lifetime )
    	{
    		if(mTargetObject && mOnlyCollideWithTarget && mHoming)
    		{
    			VectorF normal = -getVelocity();
    			normal.normalize();
    			onCollision( getPosition(), normal, mTargetObject );
    			explode( getPosition(), normal, mTargetObject->getTypeMask() );
    		}
    		deleteObject();
    		return;
    	}
    	*/
     
    	if ( mHasExploded )
    		return;
     
    	// ... otherwise, we have to do some simulation work.
    	RayInfo rInfo;
    	Point3F oldPosition;
    	Point3F newPosition;
     
    	updatePosition(dt, oldPosition, newPosition);
     
    	if(!(mTargetObject && mOnlyCollideWithTarget && mHoming))
    	{
    		// disable the source objects collision reponse for a short time while we
    		// determine if the projectile is capable of moving from the old position
    		// to the new position, otherwise we'll hit ourself
    		bool disableSourceObjCollision = (mSourceObject.isValid() && mCurrTick <= SourceIdTimeoutTicks);
     
    		if ( disableSourceObjCollision )
    			mSourceObject->disableCollision();
     
    		disableCollision();
     
    		// Determine if the projectile is going to hit any object between the previous
    		// position and the new position. This code is executed both on the server
    		// and on the client (for prediction purposes). It is possible that the server
    		// will have registered a collision while the client prediction has not. If this
    		// happens the client will be corrected in the next packet update.
    		// Raycast the abstract PhysicsWorld if a PhysicsPlugin exists.
    		bool hit = false;
     
    		if ( mPhysicsWorld )
    			hit = mPhysicsWorld->castRay( oldPosition, newPosition, &rInfo, Point3F( newPosition - oldPosition) * mDataBlock->impactForce );
    		else
    			hit = getContainer()->castRay(oldPosition, newPosition, csmDynamicCollisionMask | csmStaticCollisionMask, &rInfo);
     
    		if ( hit )
    		{
    			// make sure the client knows to bounce
    			if ( isServerObject() && ( rInfo.object->getTypeMask() & csmStaticCollisionMask ) == 0 )
    				setMaskBits( BounceMask );
     
    			// Next order of business: do we explode on this hit?
    			if ( mCurrTick > mDataBlock->armingDelay || mDataBlock->armingDelay == 0 )
    			{
    				if(!(mTargetObject && mOnlyCollideWithTarget && rInfo.object != mTargetObject) || !mOnlyCollideWithTarget)
    				{
    					MatrixF xform( true );
    					xform.setColumn( 3, rInfo.point );
    					setTransform( xform );
    					mCurrPosition = rInfo.point;
    					mCurrVelocity = Point3F::Zero;
     
    					// Get the object type before the onCollision call, in case
    					// the object is destroyed.
    					U32 objectType = rInfo.object->getTypeMask();
     
    					// re-enable the collision response on the source object since
    					// we need to process the onCollision and explode calls
    					if ( disableSourceObjCollision )
    						mSourceObject->enableCollision();
     
    					// Ok, here is how this works:
    					// onCollision is called to notify the server scripts that a collision has occurred, then
    					// a call to explode is made to start the explosion process. The call to explode is made
    					// twice, once on the server and once on the client.
    					// The server process is responsible for two things:
    					// 1) setting the ExplosionMask network bit to guarantee that the client calls explode
    					// 2) initiate the explosion process on the server scripts
    					// The client process is responsible for only one thing:
    					// 1) drawing the appropriate explosion
     
    					// It is possible that during the processTick the server may have decided that a hit
    					// has occurred while the client prediction has decided that a hit has not occurred.
    					// In this particular scenario the client will have failed to call onCollision and
    					// explode during the processTick. However, the explode function will be called
    					// during the next packet update, due to the ExplosionMask network bit being set.
    					// onCollision will remain uncalled on the client however, therefore no client
    					// specific code should be placed inside the function!
    					onCollision( rInfo.point, rInfo.normal, rInfo.object );
    					explode( rInfo.point, rInfo.normal, objectType );
    					// break out of the collision check, since we've exploded
    					// we don't want to mess with the position and velocity
    				}
    			}
    			else
    			{
    				if ( mDataBlock->isBallistic )
    				{
    					// Otherwise, this represents a bounce. First, reflect our velocity
    					// around the normal...
    					Point3F bounceVel = mCurrVelocity - rInfo.normal * (mDot( mCurrVelocity, rInfo.normal ) * 2.0);
    					mCurrVelocity = bounceVel;
     
    					// Add in surface friction...
    					Point3F tangent = bounceVel - rInfo.normal * mDot(bounceVel, rInfo.normal);
    					mCurrVelocity -= tangent * mDataBlock->bounceFriction;
     
    					// Now, take elasticity into account for modulating the speed of the grenade
    					mCurrVelocity *= mDataBlock->bounceElasticity;
     
    					// Set the new position to the impact and the bounce
    					// will apply on the next frame.
    					//F32 timeLeft = 1.0f - rInfo.t;
    					newPosition = oldPosition = rInfo.point + rInfo.normal * 0.05f;
    				}
    			}
    		}
     
    		// re-enable the collision response on the source object now
    		// that we are done processing the ballistic movement
    		if ( disableSourceObjCollision )
    		mSourceObject->enableCollision();
    		enableCollision();
    	}
    	else//yorks new down here for testing onlyCollideWithTarget when homing and there is a targetObject
    	{
    		bool disableSourceObjCollision = (mSourceObject.isValid() && mCurrTick <= SourceIdTimeoutTicks);
     
    		if (disableSourceObjCollision)
    			mSourceObject->disableCollision();
     
    		disableCollision();
     
    		bool hit = false;
     
    		if (mPhysicsWorld)
    			hit = mPhysicsWorld->castRay(oldPosition, newPosition, &rInfo, Point3F(newPosition - oldPosition) * mDataBlock->impactForce);
    		else
    			hit = getContainer()->castRay(oldPosition, newPosition, csmDynamicCollisionMask | csmStaticCollisionMask, &rInfo);
     
    		if (hit)
    		{
    			// make sure the client knows to bounce
    			if (isServerObject() && (rInfo.object->getTypeMask() & csmStaticCollisionMask) == 0)
    				setMaskBits(BounceMask);
     
    			// Next order of business: do we explode on this hit?
    			if (mCurrTick > mDataBlock->armingDelay || mDataBlock->armingDelay == 0)
    			{
    				if (mTargetObject && mOnlyCollideWithTarget && rInfo.object == mTargetObject)
    				{
    					MatrixF xform(true);
    					xform.setColumn(3, rInfo.point);
    					setTransform(xform);
    					mCurrPosition = rInfo.point;
    					mCurrVelocity = Point3F::Zero;
     
    					// Get the object type before the onCollision call, in case
    					// the object is destroyed.
    					U32 objectType = rInfo.object->getTypeMask();
     
    					// re-enable the collision response on the source object since
    					// we need to process the onCollision and explode calls
    					if (disableSourceObjCollision)
    						mSourceObject->enableCollision();
     
    					onCollision(rInfo.point, rInfo.normal, rInfo.object);
    					explode(rInfo.point, rInfo.normal, objectType);
    				}
    			}
    			else
    			{
    				if (mDataBlock->isBallistic)
    				{
    					Point3F bounceVel = mCurrVelocity - rInfo.normal * (mDot(mCurrVelocity, rInfo.normal) * 2.0);
    					mCurrVelocity = bounceVel;
     
    					Point3F tangent = bounceVel - rInfo.normal * mDot(bounceVel, rInfo.normal);
    					mCurrVelocity -= tangent * mDataBlock->bounceFriction;
     
    					mCurrVelocity *= mDataBlock->bounceElasticity;
     
    					newPosition = oldPosition = rInfo.point + rInfo.normal * 0.05f;
    				}
    			}
    		}
     
    		if (disableSourceObjCollision)
    			mSourceObject->enableCollision();
    		enableCollision();
    	}//end of yorks
     
    	if ( isClientObject() )
    	{
    		emitParticles( mCurrPosition, newPosition, mCurrVelocity, U32( dt * 1000.0f ) );
    		updateSound();
    	}
     
    	mCurrDeltaBase = newPosition;
    	mCurrBackDelta = mCurrPosition - newPosition;
    	mCurrPosition = newPosition;
     
    	MatrixF xform( true );
    	xform.setColumn( 3, mCurrPosition );
    	setTransform( xform );
    }

     

    And here's a video of some of it in action! :D

    tog-HlPvBlM

  2. Noticed a small "jitter" on collision when using FXProjectile with homing, targetObject and onlyCollideWithTarget. Doesn't seem to do anything else, just doesn't delete/vanish on impact. Did look at the code but couldn't see an obvious reason.

  3. It's best to create convex collision boxes for non-player models. Multiple convex collision boxes are needed for vehicles. In editor you can choose the type of collision, like "collision mesh" for you collision boxes or "visible collision" for having all meshes collide, but this should only be done on simplish models.


    Scroll down for "collision geometry" http://docs.garagegames.com/torque-3d/official/index.html?content/documentation/Artist%20Guide/Primer/torque_art_primer.html


    Here is an old template I made using Blender:

    http://farm4.static.flickr.com/3262/3972904908_781d062598_o.png

  4. After a fair bit hunting around I discovered T3D\gameBase\std\stdGameProcess.cpp is where moves to all objects are passed using:

    void StdClientProcessList::onTickObject( ProcessObject *obj )

    and

    void StdServerProcessList::onTickObject( ProcessObject *pobj )

     

    From here I could call the cameraObject when it was not the controlObject by adding:

    if  ( con && con->getCameraObject() == obj )

     

    Changing camera.cpp to take camyaw and campitch instead of yaw/pitch, I was a bit out of my depth to put it mildly and still didn't seem to get any results.

    Think I might abandon this one and stick with my rubbishy hack :?

  5. I was wondering if anyone had any experience with separating camera control (specifically orbitObject or Third Person) from inheriting the player (controlObject) head rotation?


    I thought that creating a new move trigger group to get input would be best, but then was not sure exactly how to pass it over to the camera. If the player is the controlObject the camera's process tick doesn't get "move" called on it (as it would if it was the controlObject) and I from there I baffled myself with science and math ... :?


    The new input code is based off existing rotation input:

    MoveManager.h

    struct Move
    {
       enum { ChecksumBits = 16, ChecksumMask = ((1<
    //...
       U32 checksum;
     
       U32 pcamyaw, pcampitch, pcamroll;//yorks cam in
       F32 camyaw, campitch, camroll;//yorks cam in
     
       bool deviceIsKeyboardMouse;
    //...
    };
    //.............
    class MoveManager
    {
    public:
       static bool mDeviceIsKeyboardMouse;
    //...
       static F32 mYAxis_R;
     
       //yorks cam start
       static F32 mCamPitch;
       static F32 mCamYaw;
       static F32 mCamRoll;
     
       static F32 mCamPitchUpSpeed;
       static F32 mCamPitchDownSpeed;
       static F32 mCamYawLeftSpeed;
       static F32 mCamYawRightSpeed;
       static F32 mCamRollLeftSpeed;
       static F32 mCamRollRightSpeed;
       //yorks cam end
     
       static U32 mTriggerCount[MaxTriggerKeys];
    //...

     

    MoveManager.cpp

    //...
    F32 MoveManager::mYAxis_R = 0;
     
    //yorks cam start
    F32 MoveManager::mCamPitch = 0;
    F32 MoveManager::mCamYaw = 0;
    F32 MoveManager::mCamRoll = 0;
     
    F32 MoveManager::mCamPitchUpSpeed = 0;
    F32 MoveManager::mCamPitchDownSpeed = 0;
    F32 MoveManager::mCamYawLeftSpeed = 0;
    F32 MoveManager::mCamYawRightSpeed = 0;
    F32 MoveManager::mCamRollLeftSpeed = 0;
    F32 MoveManager::mCamRollRightSpeed = 0;
    //yorks cam end
     
    U32 MoveManager::mTriggerCount[MaxTriggerKeys] = { 0, };
    //...
     
    void MoveManager::init()
    {
    //...
       Con::addVariable("mvRollRightSpeed", TypeF32, &mRollRightSpeed, 
          "Right roll speed.\n"
    	   "@ingroup Game");
     
       //yorks cam start
       Con::addVariable("mvCamPitch", TypeF32, &mCamPitch,
    	   "Current pitch value, typically applied through input devices, such as a mouse.\n"
    	   "@ingroup Game");
       Con::addVariable("mvCamYaw", TypeF32, &mCamYaw,
    	   "Current yaw value, typically applied through input devices, such as a mouse.\n"
    	   "@ingroup Game");
       Con::addVariable("mvCamRoll", TypeF32, &mCamRoll,
    	   "Current roll value, typically applied through input devices, such as a mouse.\n"
    	   "@ingroup Game");
       Con::addVariable("mvCamPitchUpSpeed", TypeF32, &mCamPitchUpSpeed,
    	   "Upwards pitch speed.\n"
    	   "@ingroup Game");
       Con::addVariable("mvCamPitchDownSpeed", TypeF32, &mCamPitchDownSpeed,
    	   "Downwards pitch speed.\n"
    	   "@ingroup Game");
       Con::addVariable("mvCamYawLeftSpeed", TypeF32, &mCamYawLeftSpeed,
    	   "Left Yaw speed.\n"
    	   "@ingroup Game");
       Con::addVariable("mvCamYawRightSpeed", TypeF32, &mCamYawRightSpeed,
    	   "Right Yaw speed.\n"
    	   "@ingroup Game");
       Con::addVariable("mvCamRollLeftSpeed", TypeF32, &mCamRollLeftSpeed,
    	   "Left roll speed.\n"
    	   "@ingroup Game");
       Con::addVariable("mvCamRollRightSpeed", TypeF32, &mCamRollRightSpeed,
    	   "Right roll speed.\n"
    	   "@ingroup Game");
       //yorks cam end
     
       // Dual-analog
       Con::addVariable( "mvXAxis_L", TypeF32, &mXAxis_L, 
          "Left thumbstick X axis position on a dual-analog gamepad.\n"
    	   "@ingroup Game" );
    //...
    }
     
    Move::Move()
    {
    //...
       sendCount=0;
       pcamyaw = 0; pcampitch = 0; pcamroll = 0;//yorks cam in
       camyaw = 0; campitch = 0; camroll = 0;//yorks cam in
     
       checksum = false;
    //...
    }
     
    void Move::unclamp()
    {
    //...
       z = (pz - 16) / F32(16);
     
       //yorks cam start
       camyaw = IANG2FANG(pcamyaw);
       campitch = IANG2FANG(pcampitch);
       camroll = IANG2FANG(pcamroll);
       //yorks cam end
    }
     
    void Move::clamp()
    {
    //...
       proll = FANG2IANG(roll);
     
       //yorks cam start
       camyaw = clampAngleClamp(camyaw);
       campitch = clampAngleClamp(campitch);
       camroll = clampAngleClamp(camroll);
     
       // angles are all 16 bit.
       pcamyaw = FANG2IANG(camyaw);
       pcampitch = FANG2IANG(campitch);
       pcamroll = FANG2IANG(camroll);
       //yorks cam end
     
       px = clampRangeClamp(x);
    //...
    }
     
    bool Move::packMove(BitStream *stream, const Move* basemove, bool alwaysWriteAll)
    {
    //...
                                 (pz!=basemove->pz)         ||
    							 //yorks cam start
    							 (pcamyaw != basemove->pcamyaw) ||
    							 (pcampitch != basemove->pcampitch) ||
    							 (pcamroll != basemove->pcamroll) ||
    							 //yorks cam end
                                 (deviceIsKeyboardMouse!=basemove->deviceIsKeyboardMouse) ||
                                 (freeLook!=basemove->freeLook) ||
                                 triggerDifferent;
     
    /...
          if(stream->writeFlag(proll != basemove->proll))
          stream->writeInt(proll, 16);
     
    	  //yorks cam start
    	  if (stream->writeFlag(pcamyaw != basemove->pcamyaw))
    		  stream->writeInt(pcamyaw, 16);
    	  if (stream->writeFlag(pcampitch != basemove->pcampitch))
    		  stream->writeInt(pcampitch, 16);
    	  if (stream->writeFlag(pcamroll != basemove->pcamroll))
    		  stream->writeInt(pcamroll, 16);
    	  //yorks cam end
     
          if (stream->writeFlag(px != basemove->px))
             stream->writeInt(px, 6);
    //...
     
    bool Move::unpackMove(BitStream *stream, const Move* basemove, bool alwaysReadAll)
    {
    //...
          proll = stream->readFlag() ? stream->readInt(16) : basemove->proll;
     
    	  //yorks cam start
    	  pcamyaw = stream->readFlag() ? stream->readInt(16) : basemove->pcamyaw;
    	  pcampitch = stream->readFlag() ? stream->readInt(16) : basemove->pcampitch;
    	  pcamroll = stream->readFlag() ? stream->readInt(16) : basemove->pcamroll;
    	  //yorks cam end
     
          px = stream->readFlag() ? stream->readInt(6) : basemove->px;
    //...
    }

     

    MoveList.h

    bool MoveList::getNextMove(Move &curMove)
    {
    /...
       MoveManager::mRoll = 0;
     
       //yorks cam start
       F32 campitchAdd = MoveManager::mCamPitchUpSpeed - MoveManager::mCamPitchDownSpeed;
       F32 camyawAdd = MoveManager::mCamYawLeftSpeed - MoveManager::mCamYawRightSpeed;
       F32 camrollAdd = MoveManager::mCamRollRightSpeed - MoveManager::mCamRollLeftSpeed;
     
       curMove.campitch = MoveManager::mCamPitch + campitchAdd;
       curMove.camyaw = MoveManager::mCamYaw + camyawAdd;
       curMove.camroll = MoveManager::mCamRoll + camrollAdd;
     
       MoveManager::mCamPitch = 0;
       MoveManager::mCamYaw = 0;
       MoveManager::mCamRoll = 0;
       //yorks cam end
     
       curMove.x = MoveManager::mRightAction - MoveManager::mLeftAction + MoveManager::mXAxis_L;
    /..
    }

     

    TorqueScript: game/scripts/client/default.bind.cs - change mouse yaw/pitch to take the new inputs for testing

    function yaw(%val)
    {
    //...
     
       $mvCamYaw += %yawAdj;//yorks was $mvYaw
    }
     
    function pitch(%val)
    {
    //...
     
       $mvCamPitch += %pitchAdj;//yorks was $mvPitch
    }

     

    That all works as hoped and can be tested in Player.cpp UpdateMove() - just above move->pitch etc:

    //yorks cam start
    			F32 pcam = move->campitch;
    			if (pcam > M_PI_F)
    				pcam -= M_2PI_F;
    			F32 ycam = move->camyaw;
    			if (ycam > M_PI_F)
    				ycam -= M_2PI_F;
     
    			if (!mIsZero(ycam) || !mIsZero(pcam))
    			{
    				Con::printf("camRotation Yaw '%d' ", ycam);
    				Con::printf("camRotation Pitch '%d' ", pcam);
    			}
    			//yorks cam end

     

    Unfortunately after that I'm unsure how to proceed to affect the camera's rotation with it, and camera processTick(constMove *move) does not get the move passed as it is not the controlObject. I was thinking maybe get the controlObject/Player camera and thenget/set rotation like that but it seems like an ugly hack and I already have another ugly hack in TorqueScript to rotate it which I'm trying to get rid of.


    Anyhow, any bright ideas welcome.

  6. http://www.payneful.co.uk/blogsplosion/wp-content/uploads/clouseau.jpg

    The case is solv-ed

     

    Thanks to @doc for the tip, I just needed the getTransform().toEuler() for local X and Y. I'd tried that on the master object but to no avail.

     

    Point3F masterVec = mMaster->getTransform().getForwardVector();
     
    	   F32 xDiff = masterVec.x - getTransform().toEuler().x; //forward.x;
    	   F32 yDiff = masterVec.y - getTransform().toEuler().y;//forward.y;
     
    	   //do we need this? It works with it so leave alone
    	   if (mFabs(xDiff) < 0.001f)
    		   xDiff = 0.0f;
    	   if (mFabs(yDiff) < 0.001f)
    		   yDiff = 0.0f;
     
    	   if (!mIsZero(xDiff) || !mIsZero(yDiff))
    	   {
    		   //Con::errorf("Follower has master '%d'.", mMaster);
     
    		   // First do Yaw
    		   // use the cur yaw between -Pi and Pi
    		   F32 curYaw = rotation.z;
    		   while (curYaw > M_2PI_F)
    			   curYaw -= M_2PI_F;
    		   while (curYaw < -M_2PI_F)
    			   curYaw += M_2PI_F;
     
    		   // find the yaw offset
    		   F32 newYaw = mAtan2(xDiff, yDiff);
    		   F32 yawDiff = newYaw - curYaw;
     
    		   // make it between 0 and 2PI
    		   if (yawDiff < 0.0f)
    			   yawDiff += M_2PI_F;
    		   else if (yawDiff >= M_2PI_F)
    			   yawDiff -= M_2PI_F;
     
    		   // now make sure we take the short way around the circle
    		   if (yawDiff > M_PI_F)
    			   yawDiff -= M_2PI_F;
    		   else if (yawDiff < -M_PI_F)
    			   yawDiff += M_2PI_F;
     
    		   movePtr->yaw = yawDiff;
            }

     

    XvPKU3CNgt8

  7. MoveTrigger's are all simulated in the AIPlayer.cpp getAIMove() function. You'd have to write a function (and expose it to TS) to activate the jetting moveTrigger. Navmeshes do the same with the "jump" moveTrigger in AiPlayer.cpp line ~585 and I wrote some functions for AI to use the "pose" moveTrigger.

  8. Apologies about having gone swanning off for a few days ...


    Here's a vid to illustrate the issue.


    ZdJE5QsL2Q8


    I also tested feeding the follower an xyz position (the player's so it constantly updates when moving) and this worked fine without the delerium tremors ... so maybe the solution I should be looking for is to extrapolate the a position in space from scaling the player's forward vector ... or something ...


    I guess also I could get the player's rotation and just force it into the follower's transform (though that doesn't sound terribly glamourous)

  9. It's late and I've been staring at this for too long and my brain has turned to mush ... :?


    I have an object (Aiplayer) which inherits it's rotation from the player. It kinda works except it causes the object to shake like a washing machine on spin cycle, which isn't good for shooting as projectiles go everywhere. Retrieving the initial transform via getForwardVector.

     

    //...
       Point3F forward = eye.getForwardVector();
    //...
    	   Point3F masterVec = mMaster->getTransform().getForwardVector();
     
    	   F32 xDiff = masterVec.x - forward.x;
    	   F32 yDiff = masterVec.y - forward.y;
     
    	   //can we stop the shakes? Not like this we can't :/
    	   if (mFabs(xDiff) < 0.001f)
    		   xDiff = 0.0f;
    	   if (mFabs(yDiff) < 0.001f)
    		   yDiff = 0.0f;
     
    	   if (!mIsZero(xDiff) || !mIsZero(yDiff))
    	   {
    		   // First do Yaw
    		   // use the cur yaw between -Pi and Pi
    		   F32 curYaw = rotation.z;
    		   while (curYaw > M_2PI_F)
    			   curYaw -= M_2PI_F;
    		   while (curYaw < -M_2PI_F)
    			   curYaw += M_2PI_F;
     
    		   // find the yaw offset
    		   F32 newYaw = mAtan2(xDiff, yDiff);
    		   F32 yawDiff = newYaw - curYaw;
     
    		   // make it between 0 and 2PI
    		   if (yawDiff < 0.0f)
    			   yawDiff += M_2PI_F;
    		   else if (yawDiff >= M_2PI_F)
    			   yawDiff -= M_2PI_F;
     
    		   // now make sure we take the short way around the circle
    		   if (yawDiff > M_PI_F)
    			   yawDiff -= M_2PI_F;
    		   else if (yawDiff < -M_PI_F)
    			   yawDiff += M_2PI_F;
     
    		   movePtr->yaw = yawDiff;
    	   }
    //...

     

    Off the top of my head suppose I could drop getForwardVector() and try either getTransform().toEuler() or try and force the rotation with a setTransform update but they hardly count nice methods. :oops:


    Any feedback appreciated.

  10. Getting lag on ribbons following projectiles? Create the ribbon first. Here's some of my last game's script.

     

    //.......
         if(isObject(%ribbontype))
            %ribbon = createRibbon(%ribbontype, %obj.getMuzzlePoint(%slot));
         else
            %ribbon = 0;
    
         //spawn that projectile  
         %p = new (%this.projectileType)()
         {
            dataBlock = %projectile;//now from above
            initialVelocity = %muzzleVelocity;
            initialPosition = %obj.getMuzzlePoint(%slot);
            sourceObject = %obj;
            sourceSlot = %slot;
            client = %obj.client;
            firedBy = %name;
            ribbon = %ribbon;
         };
         MissionCleanup.add(%p);
    
         if(%ribbon)
            %p.mountObject(%ribbon, 0);
         return %p;
    

  11. If you log into GG and then TDN (through the documentation page, TDN section) there's some old but still useful basic information on using AI. http://tdn.garagegames.com/wiki/Torque/Script/Tutorials/Using_Basic_AI_Commands


    There's also a load of old tutorials and game examples (by yours truly) in the GG resources section.

    Simple SInglePlayer FPS http://www.garagegames.com/community/resources/view/20829

    3rd Person Tactics-Action http://www.garagegames.com/community/resources/view/20995

    Singleplayer Deathmatch using Chinatown http://www.garagegames.com/community/resources/view/21604


    These are all from previous versions of T3D so some of the $typemasks may need updating and stuff like Recast is already in the engine.

×
×
  • Create New...