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; }
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()); }
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; } } }
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; }
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; } } }
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); } } } }