Game Development Community

Trying to get Swinging Door to work

by Jason Campbell · in Torque 3D Beginner · 04/09/2014 (9:06 pm) · 13 replies

Hey everyone,

I really wanted to figure this out on my own. I'm using Ken Finney's Door Swing code and trying to figure out why it won't work after three days, I decided to ask for help. The code is originally for TGE 1.3 and I have it running without errors in T3D 3.5 and I can add the scripted object to the world. Ken uses a StaticShape and just changes the z-axis rotation. He uses %theDataBlock instead of %this and %whichDoor instead of %obj. Examining the code it really looks like it should work but it doesn't get to the "Increment" function nor "decrement" for that matter because it doesn't rotate. It plays the opening sound then moves the door to Transform 0 0 0.Using echo, it appears that %whichdoor.currentRotation, which starts as 0 is actually an empty space.
I know I could use a different approach, such a an animated door with a trigger or onCollision but I really like Ken's Operator function and the simplicity of this dataBlock.

Any help would be appreciated.

Thanks,
Jason


$DOORS::RADIANS_PER_DEGREE = 0.017444;
$DOORS::XY_UNIT_VECTORS = "0 0";
$DOORS::PLAYER_REACH = 4.5;
$DOORS::OPEN_INCREMENT = 0.02;
$DOORS::CLOSE_INCREMENT = 0.04;
$DOORS::OPEN_TIMER = 20;
$DOORS::CLOSE_TIMER = 10;
$DOORS::HOLD_TIMER = 2000;
$DOORS::MAX_ANGLE = 90; //  degrees

datablock SFXProfile(doorStartOpenSwingSnd)
{
   fileName = "art/sound/doors/doorswingopen.ogg";
   description = AudioClose3d;
   preload = true;
};

datablock SFXProfile(doorSwingClosedSnd)
{
   fileName = "art/sound/doors/doorswingclosed.ogg";
   description = AudioClose3d;
   preload = true;
};

datablock SFXProfile(doorSlamSnd)
{
   fileName = "art/sound/doors/doorslam.ogg";
   description = AudioClose3d;
   preload = true;
};

datablock StaticShapeData(ADoor)
{
   category = "Doors";
   shapeFile = "art/shapes/doors/door.DAE";
   cameraMaxDist = "1";
   shadowEnable = "1";
   
  
};

function ADoor::OnAdd(%theDatablock, %whichDoor)
{
  if(!%whichDoor.doorOpenFlag)
      %whichDoor.doorOpenFlag = false;
  if(!%whichDoor.rotationDirection)
      %whichDoor.rotationDirection = 1;
  if(!%whichDoor.maxOpenAngle)
      %whichDoor.maxOpenAngle = $DOORS::MAX_ANGLE;

  %whichDoor.currentRotation = 0;
  %whichDoor.originalRotation = 0;
  %whichDoor.partialTransform = "";
  echo(%whichDoor.maxOpenAngle);
  echo("door added");
}

function serverCmdOperate(%client)
{
   %player = %client.player;
   %eye = %player.getEyeVector();
   %vec = vectorScale(%eye, $DOORS::PLAYER_REACH);
   %start = %player.getEyeTransform();
   %end = VectorAdd(%start,%vec);
   %found = ContainerRayCast (%start, %end, $TypeMasks::StaticObjectType, %player);
   if(%found)
      %found.getDataBlock().Operate(%found);
}

function ADoor::Operate(%theDatablock, %whichDoor)
{
  if (%whichDoor.doorOpenFlag == false)
  {
    %theDatablock.StartOpenSwing(%whichDoor);
  }
}

function ADoor::StartOpenSwing(%theDatablock, %whichDoor)
{
   echo("door start swing");
   echo(%theDatablock);
  %whichDoor.doorOpenFlag=true;
  %whichDoor.currentRotation = 0;
  %whichDoor.originalRotation = getword(%whichDoor.GetTransform(),6);
  %z_unit_vector = getword(%whichDoor.GetTransform(),5);
  if ( %z_unit_vector == 0 )
    %z_unit_vector = "1";
  %whichDoor.partialTransform = getwords(%whichDoor.GetTransform(),0,2) SPC $DOORS::XY_UNIT_VECTORS SPC %z_unit_vector;
  
  //echo(getwords(%whichDoor.GetTransform(),0,2) SPC $DOORS::XY_UNIT_VECTORS SPC %z_unit_vector);
  
  %whichDoor.openSnd = %whichDoor.playAudio(0,doorStartOpenSwingSnd);
  %theDatablock.IncrementSwing(%whichDoor);
}

function ADoor::IncrementSwing(%theDatablock, %whichDoor)
{
   echo("increment");
   echo(%whichDoor.currentRotation);
  if ( %whichDoor.currentRotation < (%whichDoor.maxOpenAngle*$DOORS::RADIANS_PER_DEGREE))
  {
      %whichDoor.currentRotation  += ( $DOORS::OPEN_INCREMENT * %whichDoor.rotationDirection);
      %newrot = %whichDoor.originalRotation + %whichDoor.currentRotation;
      %whichDoor.settransform(%whichDoor.partialTransform SPC %newrot);
      %theDatablock.schedule($DOORS::OPEN_TIMER,"IncrementSwing", %whichDoor);
   }
  else
  {
    %theDatablock.schedule($DOORS::HOLD_TIMER,"StartCloseSwing",%whichDoor);
  }
  
}

function ADoor::StartCloseSwing(%theDatablock, %whichDoor)
{
   echo("start close");
  %whichDoor.stopAudio(openSnd);
  %whichDoor.closeSnd = %whichDoor.playAudio(0,doorSwingClosedSnd);
  %theDatablock.schedule($DOORS::CLOSE_TIMER,"DecrementSwing", %whichDoor);
}

function ADoor::DecrementSwing(%theDatablock, %whichDoor)
{
   echo("decrement started");
  if ( %whichDoor.currentRotation > 0)
  {
     echo("decrement actually started"):
    %whichDoor.currentRotation  -= ($DOORS::CLOSE_INCREMENT * %whichDoor.rotationDirection);
    %newrot = %whichDoor.originalRotation + %whichDoor.currentRotation;
    %whichDoor.settransform(%whichDoor.partialTransform SPC %newrot);
    %theDatablock.schedule($DOORS::CLOSE_TIMER,"DecrementSwing", %whichDoor);
  }
  else
  {
    %whichDoor.doorOpenFlag=false;
    %whichDoor.settransform(%whichDoor.partialTransform SPC %whichDoor.originalRotation);
    %whichDoor.stopAudio(closeSnd);
    %whichDoor.slamSnd = %whichDoor.playAudio(0,doorSlamSnd);
    %whichDoor.currentRotation = 0;
    %whichDoor.dump();
  }
  
}

#1
04/10/2014 (10:50 am)
%found = ContainerRayCast (%start, %end, $TypeMasks::StaticObjectType, %player);  
   if(%found)  
      %found.getDataBlock().Operate(%found);

replace with:

%found = firstWord(ContainerRayCast (%start, %end, $TypeMasks::StaticObjectType, %player));  
   if(%found)  
      %found.getDataBlock().Operate(%found);

ContainerRayCast returns a word separated string of results, with the object ID being the first word.

Let me know if that works, if it doesn't, I'll look into it more.
#2
04/10/2014 (9:20 pm)
Thanks for the reply Jeff.

The Operate function actually works. I can operate the door again and again but thanks for the suggestion.

I placed some more echo statements around and found that after the initial ADoor::onAdd none of the variables such as,%whichDoor.maxOpenAngle,%whichDoor.currentRotation,%whichDoor.originalRotation, contain anything. No void, no numbers, nothing.

The if-else statements can't compare anything because there is nothing to compare.

should I be returning the values in each function?

edit: It appears that StartOpenSwing works(I get the opening sound), so %whichDoor.openSnd must contain something in that function. Is it the Handle or Names fault? I can't figure what is happening to %whichDoor after that.

edit2: Just fired up the old demo of torque that came on the CD with AGP-AI1 and tried it in TGE. Of course it works perfectly...

Thanks again for your time,
Jason

#3
04/12/2014 (11:04 pm)
God, so many hours staring at this code, trying different things. It's really disparaging. I hate the thought of giving up on this. If I can't even figure this one out, what about really serious coding? None of the variables are holding anything. After examining the code running in TGE 1.3 Demo, I think it may be something to do with the dynamic fields.

I can't give up, though it is strange that there isn't more door resources.
#4
04/13/2014 (12:30 am)
Yeah, apparently nobody uses doors in Torque games :P. Were there engine modifications associated with this change, or was it all script? How are you calling StartOpenSwing?

The original raycast code was valid because when you use a string as an object ID, it just takes the first numerical part of the string and uses that as an object ID. So "3767blah blah".getPosition() returns the position of object ID 3767.
#5
04/13/2014 (5:44 am)
Thanks, Daniel. This is all in script. StartOpenSwing is called when the Operate function finds a door within the players reach, which is 4.5 units in front of the player. Operate is mapped to "e" and this works, no matter how many doors I have. Especially since OpenFlag is never true, since it doesn't hold anything.

function ADoor::Operate(%theDatablock, %whichDoor)  
{  
  if (%whichDoor.doorOpenFlag == false)  
  {  
    %theDatablock.StartOpenSwing(%whichDoor);  
  }  
}



So Jeff was on to something.

When I echo %theDatablock, I get the datablock ID(90). When I echo %whichDoor, it gives me the StaticShape's id, transform and rotation(6049 -3.3455 -220.233 7.02321 0 -1 0 0.53222).

You are saying in TGE %whichDoor would have just returned "6049" in the above case?

This would make sense and if that's the case, is there a way that I can just return the unique id(first word) of each Door StaticShape?
#6
04/13/2014 (7:35 am)
Try echoing %theDatablock.getName() to be sure you have the right datablock (pretty sure you do, it's playing the sound, right?).

I suppose you could try naming your doors (or at least one of them) to see what %whichDoor is pointing to, but again it should be a door or the other stuff wouldn't work at all.

I've been really busy (no days off since March 31st) but when I get a second I'll try to get this working and get back to you.
#7
04/13/2014 (8:02 am)
Thanks Richard. If you want, you can just grab the code and door.dts/door.png to test it. I will continue to work on this tonight.

www.mediafire.com/download/fqychbkj7zxzlu8/door_code.zip
#8
04/13/2014 (10:19 am)
Ok, I'll try to figure out what's going on when I have a minute.
#9
04/14/2014 (6:26 pm)
Hey - check out this bit:
function ADoor::DecrementSwing(%theDatablock, %whichDoor)
{
   echo("decrement started");
  if ( %whichDoor.currentRotation > 0)
  {
     echo("decrement actually started"); // << was a colon and not a semi-colon
hope that helps a little....
#10
04/14/2014 (6:54 pm)
Thanks Richard,

Sorry that was an older doors.cs I sent you.

However, I am elated. I just got it to work, just now!!

T3D MIT must not like the huge prefix caused by $whichDoor containing the id, transform and rotation. I added

%id = getword(%whichDoor,0);

to each function and replaced every instance of %whichDoor with %id other then the each original function/datablock call and in the schedules. Hopefully I can add as many doors as I want and it will still work because of each unique %id.

Thanks everyone, it feels good to finally figure this out. :)

I'm sure I'll be bugging you soon on some other problem.

Jason
#11
04/14/2014 (6:57 pm)
Hey sorry I didn't get around to helping ya again, i forgot about this thread and I feel really bad D:
#12
04/14/2014 (7:04 pm)
Don't feel bad, I like that I sort of figured it out myself, though the idea of just grabbing the first word for the id came from you and Daniel. This is most likely a good insight into getting other older code from TGE to run in T3D.

Also I just added a ton of doors and opened them all and everything works perfectly.

So happy!
#13
04/15/2014 (6:55 am)
Hurrah! Nice work :)