SimObject* SpawnSphere::spawnObject(String additionalProps)
{
   SimObject* spawnObject = Sim::spawnObject(mSpawnClass, mSpawnDataBlock, mSpawnName,
                                             mSpawnProperties + " " + additionalProps, mSpawnScript);

   // If we have a spawnObject add it to the MissionCleanup group
   if (spawnObject)
   {
      if (mSpawnTransform)
      {
         if(SceneObject *s = dynamic_cast<SceneObject*>(spawnObject))
            s->setTransform(getTransform());
      }

      SimObject* cleanup = Sim::findObject("MissionCleanup");

      if (cleanup)
      {
         SimGroup* missionCleanup = dynamic_cast<SimGroup*>(cleanup);

         missionCleanup->addObject(spawnObject);
      }
   }

   return spawnObject;
}
示例#2
0
SimGroup* SimGroup::deepClone()
{
   // Clone the group object.
   
   SimObject* object = Parent::deepClone();
   SimGroup* group = dynamic_cast< SimGroup* >( object );
   if( !group )
   {
      object->deleteObject();
      return NULL;
   }
   
   // Clone all child objects.
   
   for( iterator iter = begin(); iter != end(); ++ iter )
      group->addObject( ( *iter )->deepClone() );
   
   return group;
}
void MissionLighting::createInteriorVolume()
{
   VolumeRWStream vol;

   // create the volume
   _assert( vol.createVolume( volumeFile.c_str() ), "Failed to create volume: %s\n",
      volumeFile.c_str() );
      
   SimGroup * group = NULL;
   
   // go through and see if the volume has been added alredy
   for( int i = 0; i < m_volumes.size(); i++ )
   {
      if( ( m_volumes[i]->getName() ) && ( !stricmp( m_volumes[i]->getName(), lightVolName ) ) )
      {
         // remove the volume
         print( V_LOW, "Removing MissionLighting volume.\n" );
         group = m_volumes[i]->getGroup();
         if( group )
            group->removeObject( m_volumes[i] );
      }
   }
   
   print( V_MEDIUM, "Adding SimVolume to mission ( %s )\n",
      volumeFile.c_str() );

   // add to the mission in the volumes group
   SimVolume * simVolume = new SimVolume;
   manager->addObject( simVolume, lightVolName );
   simVolume->open( stripPath( volumeFile.c_str() ) );
   
   // try and place in a volumes group
   if( !group )
   {
      group = dynamic_cast<SimGroup*>( mission->findObject( "Volumes" ) );
      if( !group )
         group = mission;
   }
   group->addObject( simVolume, lightVolName );
}
static const char *c_spawnPlayer(CMDConsole *, int, int argc, const char **argv)
{
   if(!sg.playerManager || !sg.manager || argc != 4)
      return "-1";

   Point3F pos(0, 0, 0), rot(0, 0, 0);
   sscanf( argv[2], "%f %f %f", &pos.x, &pos.y, &pos.z);
   sscanf( argv[3], "%f %f %f", &rot.x, &rot.y, &rot.z);

   Player *player = new Player();
   player->setInitInfo(argv[1], pos, rot);

   if(!sg.manager->registerObject(player))
   {
      delete player;
      return "-1";
   }

   SimGroup *cleanupGroup = (SimGroup *) sg.manager->findObject("MissionCleanup");
   if(cleanupGroup)
      cleanupGroup->addObject(player);
   return intToStr(player->getId());
}
示例#5
0
void GuiRoadEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
{
   if ( !isFirstResponder() )
      setFirstResponder();

   // Get the clicked terrain position.
   Point3F tPos;
   if ( !getTerrainPos( event, tPos ) )
      return;      

   mouseLock();

   // Find any road / node at the clicked position.
   // TODO: handle overlapping roads/nodes somehow, cycle through them.
   
   DecalRoad *roadPtr = NULL;
   S32 closestNodeIdx = -1;
   F32 closestDist = F32_MAX;
   DecalRoad *closestNodeRoad = NULL;

   // First, find the closest node in any road to the clicked position.
   for ( SimSetIterator iter(mRoadSet); *iter; ++iter )
   {
      roadPtr = static_cast<DecalRoad*>( *iter );
      U32 idx;
      if ( roadPtr->getClosestNode( tPos, idx ) )
      {
         Point3F nodePos = roadPtr->getNodePosition(idx);
         F32 dist = ( nodePos - tPos ).len();
         if ( dist < closestDist )
         {
            closestNodeIdx = idx;
            closestDist = dist;
            closestNodeRoad = roadPtr;
         }
      }
   }

   //
   // Second, determine if the screen-space node rectangle
   // contains the clicked position.

   bool nodeClicked = false;
   S32 clickedNodeIdx = -1;

   if ( closestNodeIdx != -1 )
   {
      Point3F nodePos = closestNodeRoad->getNodePosition( closestNodeIdx );

      Point3F temp;
      project( nodePos, &temp );
      Point2I screenPos( temp.x, temp.y );

      RectI nodeRect( screenPos - mNodeHalfSize, mNodeHalfSize * 2 );
      
      nodeClicked = nodeRect.pointInRect( event.mousePoint );
      if ( nodeClicked )
         clickedNodeIdx = closestNodeIdx;
   }

   //
   // Determine the clickedRoad
   //
   DecalRoad *clickedRoadPtr = NULL;
   U32 insertNodeIdx = 0;

   if ( nodeClicked && (mSelRoad == NULL || closestNodeRoad == mSelRoad) )
   {
      // If a node was clicked, the owning road is always
      // considered the clicked road.
      clickedRoadPtr = closestNodeRoad;
   }
   else
   {
      // check the selected road first
      if ( mSelRoad != NULL && mSelRoad->containsPoint( tPos, &insertNodeIdx ) )
      {
         clickedRoadPtr = mSelRoad;
         nodeClicked = false;
         clickedNodeIdx = -1;
      }
      else
      {
         // Otherwise, we must ask each road if it contains
         // the clicked pos.
         for ( SimSetIterator iter(mRoadSet); *iter; ++iter )
         {
            roadPtr = static_cast<DecalRoad*>( *iter );
            if ( roadPtr->containsPoint( tPos, &insertNodeIdx ) )
            {
               clickedRoadPtr = roadPtr;
               break;            
            }
         }
      }
   }

	// shortcuts
   bool dblClick = ( event.mouseClickCount > 1 );
	if( dblClick )
   { 
		if( mMode == mSelectRoadMode )
		{
			setMode( mAddRoadMode, true );
			return;
		}
		if( mMode == mAddNodeMode )
		{
			// Delete the node attached to the cursor.
			deleteSelectedNode();
			mMode = mAddRoadMode;
			return;
		}
	}

	//this check is here in order to bounce back from deleting a whole road with ctrl+z
	//this check places the editor back into addroadmode
	if ( mMode == mAddNodeMode )
	{
      if ( !mSelRoad )
         mMode = mAddRoadMode;
	}

	if ( mMode == mSelectRoadMode )
	{
      // Did not click on a road or a node.
      if ( !clickedRoadPtr  )
      {
         setSelectedRoad( NULL );
         setSelectedNode( -1 );
         
         return;
      }

      // Clicked on a road that wasn't the currently selected road.
      if ( clickedRoadPtr != mSelRoad )
      {
         setSelectedRoad( clickedRoadPtr );
         setSelectedNode( -1 );
         return;
      }

      // Clicked on a node in the currently selected road that wasn't
      // the currently selected node.
      if ( nodeClicked )
      {
         setSelectedNode( clickedNodeIdx );
         return;
      }

      
      // Clicked a position on the currently selected road
      // that did not contain a node.
      //U32 newNode = clickedRoadPtr->insertNode( tPos, mDefaultWidth, insertNodeIdx );                  
      //setSelectedNode( newNode );
	}
   else if ( mMode == mAddRoadMode )
   {
		if ( nodeClicked && clickedRoadPtr )
      {
			// A double-click on a node in Normal mode means set AddNode mode.  
         if ( clickedNodeIdx == 0 )
         {
				setSelectedRoad( clickedRoadPtr );
				setSelectedNode( clickedNodeIdx );

				mAddNodeIdx = clickedNodeIdx;
            mMode = mAddNodeMode;
            mSelNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx );
            mIsDirty = true;

				return;
         }
			else if ( clickedNodeIdx == clickedRoadPtr->mNodes.size() - 1 )
         {
				setSelectedRoad( clickedRoadPtr );
				setSelectedNode( clickedNodeIdx );

            mAddNodeIdx = U32_MAX;
            mMode = mAddNodeMode;
            mSelNode = mSelRoad->addNode( tPos, mDefaultWidth );
            mIsDirty = true;
				setSelectedNode( mSelNode );

				return;
         } 
		}

		DecalRoad *newRoad = new DecalRoad;
		

		newRoad->mMaterialName = mMaterialName;

      newRoad->registerObject();

      // Add to MissionGroup                              
      SimGroup *missionGroup;
      if ( !Sim::findObject( "MissionGroup", missionGroup ) )               
         Con::errorf( "GuiDecalRoadEditorCtrl - could not find MissionGroup to add new DecalRoad" );
      else
         missionGroup->addObject( newRoad );               

      newRoad->insertNode( tPos, mDefaultWidth, 0 );
      U32 newNode = newRoad->insertNode( tPos, mDefaultWidth, 1 );

      // Always add to the end of the road, the first node is the start.
      mAddNodeIdx = U32_MAX;
      
      setSelectedRoad( newRoad );      
      setSelectedNode( newNode );

      mMode = mAddNodeMode;

      // Disable the hover node while in addNodeMode, we
      // don't want some random node enlarged.
      mHoverNode = -1;

      // Grab the mission editor undo manager.
      UndoManager *undoMan = NULL;
      if ( !Sim::findObject( "EUndoManager", undoMan ) )
      {
         Con::errorf( "GuiRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
         return;           
      }

      // Create the UndoAction.
      MECreateUndoAction *action = new MECreateUndoAction("Create Road");
      action->addObject( newRoad );
      
      // Submit it.               
      undoMan->addAction( action );
		
		//send a callback to script after were done here if one exists
		if ( isMethod( "onRoadCreation" ) )
         Con::executef( this, "onRoadCreation" );

		return;
   }
	else if ( mMode == mAddNodeMode )
	{
		// Oops the road got deleted, maybe from an undo action?
      // Back to NormalMode.
      if ( mSelRoad )
      {
			// A double-click on a node in Normal mode means set AddNode mode.  
         if ( clickedNodeIdx == 0 )
         {
				submitUndo( "Add Node" );
				mAddNodeIdx = clickedNodeIdx;
            mMode = mAddNodeMode;
            mSelNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx );
            mIsDirty = true;
				setSelectedNode( mSelNode );

				return;
         }
			else
         {
				if( clickedRoadPtr && clickedNodeIdx == clickedRoadPtr->mNodes.size() - 1 )
				{
					submitUndo( "Add Node" );
					mAddNodeIdx = U32_MAX;
					mMode = mAddNodeMode;
					mSelNode = mSelRoad->addNode( tPos, mDefaultWidth );
               mIsDirty = true;
					setSelectedNode( mSelNode );

					return;
				}
				else
				{
					submitUndo( "Insert Node" );
					// A single-click on empty space while in
					// AddNode mode means insert / add a node.
					//submitUndo( "Add Node" );
					//F32 width = mSelRoad->getNodeWidth( mSelNode );
					U32 newNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx);
               mIsDirty = true;
					setSelectedNode( newNode );

					return;
				}
         } 
      }
	}
	else if ( mMode == mInsertPointMode  && mSelRoad != NULL)
	{
		if ( clickedRoadPtr == mSelRoad )
      {
			F32 w0 = mSelRoad->getNodeWidth( insertNodeIdx );
         F32 w1 = mSelRoad->getNodeWidth( insertNodeIdx + 1 );               
         F32 width = ( w0 + w1 ) * 0.5f;

         submitUndo( "Insert Node" );
         U32 newNode = mSelRoad->insertNode( tPos, width, insertNodeIdx + 1);  
         mIsDirty = true;
         setSelectedNode( newNode );

			return;
       }
	}
	else if ( mMode == mRemovePointMode  && mSelRoad != NULL)
	{
		if ( nodeClicked && clickedRoadPtr == mSelRoad )
      {
			setSelectedNode( clickedNodeIdx );
         deleteSelectedNode();
         return;
      }
	}
	else if ( mMode == mMovePointMode )
	{
		if ( nodeClicked && clickedRoadPtr == mSelRoad )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
	else if ( mMode == mScalePointMode )
	{
		if ( nodeClicked && clickedRoadPtr == mSelRoad )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
}
示例#6
0
const char * AIPlugin::consoleCallback(CMDConsole*,int id,int argc,const char *argv[])
{
   const char     * returnTxt = 0;
   HandleCmdFunc  listableCommand = 0;

   if( (aim = AIManager::it) == NULL )
   {
      if( sg.manager )
      {
         SimGroup * cleanupGroup = (SimGroup *) sg.manager->findObject(missionCleanup);
      
         if( cleanupGroup == NULL ){
            console->printf( "No cleanup group yet, can't install AI manager and, "
                     "therefore, cannot execute command %s", argv[0] );
            return returnTxt;
         }
         
         aim = new AIManager();
         AssertFatal( aim, "ai: couldn't new() the AIManager." );
         
         if( ! sg.manager->registerObject(aim) ){
            delete aim;
            aim = 0;
            console->printf( "Couldn't register AI manager...  "
                     "Cannot execute command %s", argv[0] );
            return returnTxt;
         }
         else{//success
            sg.manager->assignId(aim,AIManagerId);
            cleanupGroup->addObject(aim);
         }
      }
      else{
         console->printf("No server manager yet, can't install AI manager thus, "
                     "cannot execute command %s.", argv[0] );
         return returnTxt;
      }
   }

   switch( id )
   {
      onCommand(SpawnAI);                          // create an AI.  
      onCommand(List);                             // list all AIs in manager.  
      onCommand(GetAICount);                       // return list size.
      onCommand(GetId);                            // return rep Id.  
      onCommand(GetTarget);                        // return rep Id.  
      onCommand(FetchObject);                      // return SimObjectId

      onListableCommand(AttackPlayer);
      onListableCommand(DeleteAI);
      
      onListableCommand(CallWithId);
      onListableCommand(SetVariable);
      
      onListableCommand(FollowDirective);          // follow the specified player 
      onListableCommand(WaypointDirective);        // add waypoint to list
      onListableCommand(TargetDirective);          // add Target (player rep Id) to list.
      onListableCommand(TargetDirectiveLaser);     //    Use Laser as target (Pt Ok).  
      onListableCommand(TargetDirectivePoint);     //    Fire at given Point.
      //onListableCommand(GuardDirective);         // guard this point or player.  
      onListableCommand(RemoveDirective);          //    remove using order number.
      onListableCommand(ListDirectives);
      onListableCommand(DirectiveCallback1);
      onListableCommand(DirectiveCallback2);
      onListableCommand(DirectiveCallback3);
      onListableCommand(DirectiveCallback4);
      
      onListableCommand(CallbackDied);
      onListableCommand(CallbackPeriodic);
      onListableCommand(SetAutomaticTargets);
      onListableCommand(SetSciptedTargets);
      
#     if INCLUDE_AI_GRAPH_CODE
      onCommand(GraphAddNode);
      onCommand(GraphNodeCount);
      onCommand(GraphLoadNode);
      onCommand(GraphPrintNode);
#     endif
   }

   if( aim )
   {
      if( listableCommand )
      {
         if( argc > 1 )
         {
            // Execute command an all AIs which match the name spec.  
            AIManager::iterator itr;
            for( itr = aim->begin(); itr != aim->end(); itr++ )
               if( (*itr)->nameMatches( argv[1] ) )
                  returnTxt = (this->*listableCommand)( *itr, argc-2, argv+2 );
         }
         else
         {
            // Just give help:
            returnTxt = (this->*listableCommand)( NULL, 0, 0 );
         }
      }
   }
   
   return returnTxt;
}
示例#7
0
const char * AIPlugin::onSpawnAI(int argc, const char **argv)
{
   if ( argc < 4 )
   {
      console->printf(
         "AI::spawn: <AI name> <armor type> <position> [rotation] [display name] [voice]");
      console->printf( "Create an AI of the given name and armor type at position." );
      console->printf( "If not given, display name is the same as the AI name." );
      console->printf( "Voice defaults to male1 if not supplied here." );
      return falseTxt;
   }

   if( !sg.playerManager || !sg.manager )
   {
      console->printf("Requisite manager(s) not found.");
      return falseTxt;
   }
   
   SimGroup * cleanupGroup = (SimGroup *) sg.manager->findObject(missionCleanup);
   AssertFatal( cleanupGroup, "ai: should know there's a cleanup group by the time." );
   
   if( getAI( argv[1] ) != NULL )
   {
      console->printf("An AI named %s already exists!", argv[1] );
      return falseTxt;
   }

   const char * displayName = NULL;
   const char * voice = stringTable.insert("male1");
   Point3F pos(0, 0, 0), rot(0, 0, 0);
   sscanf( argv[3], scan3fTxt, &pos.x, &pos.y, &pos.z);
   if( argc > 4 ){
      sscanf( argv[4], scan3fTxt, &rot.x, &rot.y, &rot.z);
      if( argc > 5 ){
         displayName = argv[5];
         if( argc > 6 ){
            voice = stringTable.insert( argv[6] );
         }
      }
   }

   Player * player = new Player();
   player->setInitInfo( argv[2], pos, rot );
   player->setAIControlled(true);
   
   player->assignName( displayName ? displayName : argv[1] );
   
   if(!sg.manager->registerObject(player))
      return falseTxt;
   
   // GameBase method, sets map name.  
   player->setName( displayName ? displayName : argv[1] );
   
   AIObj * ai = new AIObj();
   strncpy ( ai->name, argv[1], AIObj::MaxNameLen );
   ai->player = player;
   ai->voice = voice;
   
   if( !sg.manager->registerObject(ai))
   {
      player->deleteObject();
      return falseTxt;
   }
   
   ai->deleteNotify ( player );
   aim->deleteNotify ( ai );
   aim->push_back( ai );
   
   ai->addVariables( console );
   
   cleanupGroup->addObject(ai->player);
   cleanupGroup->addObject(ai);
   
   return trueTxt;
}
void GuiRiverEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
{
   mGizmo->on3DMouseDown( event );

   if ( !isFirstResponder() )
      setFirstResponder();
	
	// Get the raycast collision position
   Point3F tPos;
   if ( !getStaticPos( event, tPos ) )
		return;  

   // Construct a LineSegment from the camera position to 1000 meters away in
   // the direction clicked.
   // If that segment hits the terrain, truncate the ray to only be that length.

   // We will use a LineSegment/Sphere intersection test to determine if a RiverNode
   // was clicked.   

   Point3F startPnt = event.pos;
   Point3F endPnt = event.pos + event.vec * 1000.0f;

   RayInfo ri;   

   if ( gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri) )
      endPnt = ri.point;

   River *riverPtr = NULL;
   River *clickedRiverPtr = NULL;

   // Did we click on a river? check current selection first
   U32 insertNodeIdx = -1;
   Point3F collisionPnt;
   if ( mSelRiver != NULL && mSelRiver->collideRay( event.pos, event.vec, &insertNodeIdx, &collisionPnt ) )
   {
      clickedRiverPtr = mSelRiver;
   }
   else
   {
      for ( SimSetIterator iter(mRiverSet); *iter; ++iter )
      {
         riverPtr = static_cast<River*>( *iter );
         if ( riverPtr->collideRay( event.pos, event.vec, &insertNodeIdx, &collisionPnt ) )
         {
            clickedRiverPtr = riverPtr;
            break;
         }
      }
   }

   // Did we click on a riverNode?
   bool nodeClicked = false;   
   S32 clickedNodeIdx = -1;
   F32 clickedNodeDist = mNodeSphereRadius;

   // If we clicked on the currently selected river, only scan its nodes
   if ( mSelRiver != NULL && clickedRiverPtr == mSelRiver )
   {
      for ( U32 i = 0; i < mSelRiver->mNodes.size(); i++ )
      {
         const Point3F &nodePos = mSelRiver->mNodes[i].point;

         Point3F screenPos;
         project( nodePos, &screenPos );

         F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len();
         if ( dist < clickedNodeDist )
         {
            clickedNodeDist = dist;
            clickedNodeIdx = i;
            nodeClicked = true;
         }
      }
   }
   else
   {
      for ( SimSetIterator iter(mRiverSet); *iter; ++iter )
      {
         riverPtr = static_cast<River*>( *iter );
         
         for ( U32 i = 0; i < riverPtr->mNodes.size(); i++ )
         {
            const Point3F &nodePos = riverPtr->mNodes[i].point;

            Point3F screenPos;
            project( nodePos, &screenPos );

            F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len();
            if ( dist < clickedNodeDist )
            {
               // we found a hit!
               clickedNodeDist = dist;
               clickedNodeIdx = i;
               nodeClicked = true;
               clickedRiverPtr = riverPtr;
            }
         }
      }
   }
	
	// shortcuts
	bool dblClick = ( event.mouseClickCount > 1 );
	if( dblClick )
   { 
		if( mMode == mSelectRiverMode )
		{
			setMode( mAddRiverMode, true );
			return;
		}
		if( mMode == mAddNodeMode )
		{
			// Delete the node attached to the cursor.
			deleteSelectedNode();
			mMode = mAddRiverMode;
			return;
		}
	}

	//this check is here in order to bounce back from deleting a whole road with ctrl+z
	//this check places the editor back into addrivermode
	if ( mMode == mAddNodeMode )
	{
      if ( !mSelRiver )
         mMode = mAddRiverMode;
	}

	if ( mMode == mSelectRiverMode )
	{
      // Did not click on a River or a node.
      if ( !clickedRiverPtr  )
      {
         setSelectedRiver( NULL );
         setSelectedNode( -1 );
         
         return;
      }

      // Clicked on a River that wasn't the currently selected River.
      if ( clickedRiverPtr != mSelRiver )
      {
         setSelectedRiver( clickedRiverPtr );
         setSelectedNode( clickedNodeIdx );
         return;
      }

     // Clicked on a node in the currently selected River that wasn't
      // the currently selected node.
      if ( nodeClicked )
      {
         setSelectedNode( clickedNodeIdx );
         return;
      }
	}
   else if ( mMode == mAddRiverMode )
   {
		if ( nodeClicked )
      {
			// A double-click on a node in Normal mode means set AddNode mode.  
         if ( clickedNodeIdx == 0 )
         {
				setSelectedRiver( clickedRiverPtr );
				setSelectedNode( clickedNodeIdx );

				mAddNodeIdx = clickedNodeIdx;
            mMode = mAddNodeMode; 

            mSelNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx );
            mIsDirty = true;

				return;
         }
			else if ( clickedNodeIdx == clickedRiverPtr->mNodes.size() - 1 )
         {
				setSelectedRiver( clickedRiverPtr );
				setSelectedNode( clickedNodeIdx );

            mAddNodeIdx = U32_MAX;
				mMode = mAddNodeMode;

            mSelNode = mSelRiver->addNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal);
            mIsDirty = true;
				setSelectedNode( mSelNode );

				return;
         } 
		}

		if ( !isMethod( "createRiver" ) )
      {
			Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown - createRiver method does not exist." );
         return;
      }

      const char *res = Con::executef( this, "createRiver" );

      River *newRiver;
      if ( !Sim::findObject( res, newRiver ) )
      {
         Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown - createRiver method did not return a river object." );
         return;
      }                

      // Add to MissionGroup                              
      SimGroup *missionGroup;
      if ( !Sim::findObject( "MissionGroup", missionGroup ) )               
         Con::errorf( "GuiRiverEditorCtrl - could not find MissionGroup to add new River" );
      else
         missionGroup->addObject( newRiver );

      Point3F pos( endPnt );
      pos.z += mDefaultDepth * 0.5f;

      newRiver->insertNode( pos, mDefaultWidth, mDefaultDepth, mDefaultNormal, 0 );
      U32 newNode = newRiver->insertNode( pos, mDefaultWidth, mDefaultDepth, mDefaultNormal, 1 );

      // Always add to the end of the road, the first node is the start.
      mAddNodeIdx = U32_MAX;
      
      setSelectedRiver( newRiver );      
      setSelectedNode( newNode );

      mMode = mAddNodeMode;

      // Disable the hover node while in addNodeMode, we
      // don't want some random node enlarged.
      mHoverNode = -1;

      // Grab the mission editor undo manager.
      UndoManager *undoMan = NULL;
      if ( !Sim::findObject( "EUndoManager", undoMan ) )
      {
         Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
         return;           
      }

      // Create the UndoAction.
      MECreateUndoAction *action = new MECreateUndoAction("Create MeshRoad");
      action->addObject( newRiver );

      // Submit it.               
      undoMan->addAction( action );

		return;
   }
	else if ( mMode == mAddNodeMode )
	{
		// Oops the road got deleted, maybe from an undo action?
      // Back to NormalMode.
      if ( mSelRiver )
      {
			// A double-click on a node in Normal mode means set AddNode mode.  
         if ( clickedNodeIdx == 0 )
         {
				submitUndo( "Add Node" );
				mAddNodeIdx = clickedNodeIdx;
            mMode = mAddNodeMode;
            mSelNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx );
            mIsDirty = true;
				setSelectedNode( mSelNode );

				return;
         }
			else
         {
				if( clickedRiverPtr && clickedNodeIdx == clickedRiverPtr->mNodes.size() - 1 )
				{
					submitUndo( "Add Node" );
					mAddNodeIdx = U32_MAX;
					mMode = mAddNodeMode;
					U32 newNode = mSelRiver->addNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal);  
               mIsDirty = true;
					setSelectedNode( newNode );

					return;
				}
				else
				{
					submitUndo( "Insert Node" );
					// A single-click on empty space while in
					// AddNode mode means insert / add a node.
					//submitUndo( "Add Node" );
					//F32 width = mSelRiver->getNodeWidth( mSelNode );
					U32 newNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx);
               mIsDirty = true;
					setSelectedNode( newNode );

					return;
				}
			}
		}
	}
	else if ( mMode == mInsertPointMode && mSelRiver != NULL )
	{
		if ( clickedRiverPtr == mSelRiver )
      {
			// NOTE: I guess we have to determine the if the clicked ray intersects a road but not a specific node...
         // in order to handle inserting nodes in the same way as for DecalRoad

         U32 prevNodeIdx = insertNodeIdx;
         U32 nextNodeIdx = ( prevNodeIdx + 1 > mSelRiver->mNodes.size() - 1 ) ? prevNodeIdx : prevNodeIdx + 1;

         const RiverNode &prevNode = mSelRiver->mNodes[prevNodeIdx];
         const RiverNode &nextNode = mSelRiver->mNodes[nextNodeIdx];

         F32 width = ( prevNode.width + nextNode.width ) * 0.5f;
         F32 depth = ( prevNode.depth + nextNode.depth ) * 0.5f;
         Point3F normal = ( prevNode.normal + nextNode.normal ) * 0.5f;
         normal.normalize();

         submitUndo( "Insert Node" );
         U32 newNode = mSelRiver->insertNode( collisionPnt, width, depth, normal, insertNodeIdx + 1 );
         mIsDirty = true;
         setSelectedNode( newNode );

			return;
       }
	}
	else if ( mMode == mRemovePointMode && mSelRiver != NULL )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         deleteSelectedNode();
         return;
      }
	}
	else if ( mMode == mMovePointMode )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
	else if ( mMode == mScalePointMode )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
	else if ( mMode == mRotatePointMode )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
}
示例#9
0
void Turret::shoot (bool playerControlled, Player* targetPlayer)
{
   if (data && data->isSustained == false) {
	   if (data && data->projectile.type == -1)
	   	{
	   		if (!isGhost())
	   			if (const char* script = scriptName("onFire"))
	   				Console->executef(2, script, scriptThis());
	   	}
	   else
	   	{
	   		float energy = getEnergy();
	   		if (waitTime <= manager->getCurrentTime() && data && energy >= data->minGunEnergy && data->projectile.type != -1)
	   			{
                  TMat3F muzzleTransform;
	   				getMuzzleTransform(0, &muzzleTransform);
	   				Projectile* bullet = createProjectile(data->projectile);

	   				if (!playerControlled && data->deflection)
	   					{
	   						static Random random;
	   						EulerF angles;
	   					   muzzleTransform.angles (&angles);
	   						angles.x += (random.getFloat() - 0.5) * M_2PI * data->deflection;
	   						angles.z += (random.getFloat() - 0.5) * M_2PI * data->deflection;
	   						muzzleTransform.set (angles, muzzleTransform.p);
	   					}
	   				else
	   					if (playerControlled)
	   						{
	   							Point3F start = muzzleTransform.p;
	   							muzzleTransform = getEyeTransform ();
	   							aimedTransform (&muzzleTransform, start);
	   							muzzleTransform.p = start;
	   						}

	   				bullet->initProjectile (muzzleTransform, Point3F (0, 0, 0), getId());

	   	         if (bullet->isTargetable() == true) {
	   	            if (targetPlayer != NULL) {
	   						if (GameBase* mo = targetPlayer->getMountObject())
	   		               bullet->setTarget(static_cast<ShapeBase*>(mo));
	   						else
	   		               bullet->setTarget(targetPlayer);
                     } else if (playerControlled) {
                        ShapeBase* pClosest   = NULL;
                        Point3F    closeHisPos;
                        float      closestVal = -2.0f;
                        SimSet::iterator itr;
                     
                        Point3F lookDir;
                        getEyeTransform().getRow(1, &lookDir);
                        lookDir.normalize();

                        SimContainerQuery collisionQuery;
                        SimCollisionInfo  info;
                        collisionQuery.id     = getId();
                        collisionQuery.type   = -1;
                        collisionQuery.mask   = Projectile::csm_collisionMask;
                        collisionQuery.detail = SimContainerQuery::DefaultDetail;
                        collisionQuery.box.fMin = getEyeTransform().p;
                        SimContainer* pRoot = (SimContainer*)manager->findObject(SimRootContainerId);

                        SimSet* pSet = dynamic_cast<SimSet*>(manager->findObject(PlayerSetId));
                        AssertFatal(pSet != NULL, "No player set?");
                        for (itr = pSet->begin(); itr != pSet->end(); itr++) {
                           Player* pPlayer = dynamic_cast<Player*>(*itr);

                           if (!pPlayer || pPlayer->getVisibleToTeam(getTeam()) == false)
                              continue;

                           collisionQuery.box.fMax = pPlayer->getBoxCenter();
                           if (pRoot->findLOS(collisionQuery, &info, SimCollisionImageQuery::High) == true) {
                              if (info.object != (SimObject*)pPlayer)
                                 continue;
                           }

                           Point3F hisPos = pPlayer->getBoxCenter();
                           hisPos -= getLinearPosition();
                           hisPos.normalize();

                           float prod = m_dot(hisPos, lookDir);
                           if (prod > 0.0f && prod > closestVal) {
                              closestVal = prod;
                              pClosest   = pPlayer;
                              closeHisPos = hisPos;
                           }
                        }

                        pSet = dynamic_cast<SimSet*>(manager->findObject(MoveableSetId));
                        AssertFatal(pSet != NULL, "No moveable set?");
                        for (itr = pSet->begin(); itr != pSet->end(); itr++) {
                           if (((*itr)->getType() & VehicleObjectType) == 0)
                              continue;

                           ShapeBase* pObject = dynamic_cast<ShapeBase*>(*itr);
                           
                           if (pObject->getVisibleToTeam(getTeam()) == false)
                              continue;

                           collisionQuery.box.fMax = pObject->getBoxCenter();
                           if (pRoot->findLOS(collisionQuery, &info, SimCollisionImageQuery::High) == true) {
                              if (info.object != (SimObject*)pObject)
                                 continue;
                           }

                           Point3F hisPos = pObject->getBoxCenter();
                           hisPos -= getLinearPosition();
                           hisPos.normalize();

                           float prod = m_dot(hisPos, lookDir);
                           if (prod > 0.0f && prod > closestVal) {
                              closestVal = prod;
                              closeHisPos = hisPos;
                              pClosest   = pObject;
                           }
                        }

                        // We need to find the current FOV, and take the percentage of
                        //  it specified in the .dat file for this turret.  Only if the
                        //  do product is greater than this, do we allow the target to
                        //  be set...
                        //
                        float myFov   = (fov / 2.0) * data->targetableFovRatio;
                        float compCos = cos(myFov);
                        if (compCos > 0.996f)   // hack for single precision math.  It's very
                           compCos = 0.996;     // hard to get more precise answers from the dot prod.

                        if (pClosest != NULL && closestVal > compCos)
                           bullet->setTarget(pClosest);
                     }
                  }

	   				if (data->maxGunEnergy)
	   					{
	   						float e;
	   						e = energy > data->maxGunEnergy ? data->maxGunEnergy : energy;

                        float pofm = e / float(data->maxGunEnergy);

	   						bullet->setEnergy (e, pofm);

	   						energy -= e;
	   						setEnergy (energy);
	   					}

                  SimGroup *grp = NULL;
                  if(SimObject *obj = manager->findObject("MissionCleanup"))
                     grp = dynamic_cast<SimGroup*>(obj);
                  if(!manager->registerObject(bullet))
                     delete bullet;
                  else
                  {
                     if(grp)
                        grp->addObject(bullet);
                     else
                        manager->addObject(bullet);
                  }

	   				waitTime = manager->getCurrentTime() + data->reloadDelay;

	   				if (animThread)
	   					{
	   						setFireThread ();
	   						animThread->SetPosition (0.0);
	   					}
	   				
	   				fireCount++;
	   				setMaskBits (ShootingMask);
	   			}
	   	}
   } else {
      if (data && data->projectile.type == -1) {
         if (!isGhost())
            if (const char* script = scriptName("onFire"))
               Console->executef(2, script, scriptThis());
      }
      else {
         float energy = getEnergy();
         if (waitTime <= manager->getCurrentTime() && data && energy >= data->minGunEnergy && data->projectile.type != -1) {
            TMat3F muzzleTransform;
            getMuzzleTransform(0, &muzzleTransform);
            Projectile* bullet = createProjectile(data->projectile);

            if (!playerControlled && data->deflection) {
               static Random random;
               EulerF angles;
               muzzleTransform.angles (&angles);
               angles.x += (random.getFloat() - 0.5) * M_2PI * data->deflection;
               angles.z += (random.getFloat() - 0.5) * M_2PI * data->deflection;
               muzzleTransform.set (angles, muzzleTransform.p);
            } else if (playerControlled) {
               Point3F start = muzzleTransform.p;
               muzzleTransform = getEyeTransform ();
               aimedTransform (&muzzleTransform, start);
               muzzleTransform.p = start;
            }

            bullet->initProjectile (muzzleTransform, Point3F (0, 0, 0), getId());
            AssertFatal(bullet->isSustained() == true, "Error, must be sustained bullet");
            SimGroup *grp = NULL;
            if(SimObject *obj = manager->findObject("MissionCleanup"))
               grp = dynamic_cast<SimGroup*>(obj);
            if(!manager->registerObject(bullet))
               delete bullet;
            else
            {
               if(grp)
                  grp->addObject(bullet);
               else
                  manager->addObject(bullet);
            }

            if (animThread) {
               setFireThread ();
               animThread->SetPosition (0.0);
            }
            
            fireCount++;
            setMaskBits (ShootingMask);

            m_fireState  = Firing;
            m_beganState = wg->currentTime;

            m_pProjectile = bullet;
            m_pTarget     = targetPlayer;
            
            if (m_pTarget)
               deleteNotify(m_pTarget);
         }
      }
   }
}