void FaceDirection::Execute() { Unit * target = group.GetUnit(); if (target==NULL){ done = finish; return; } Vector face (target->GetTransformation().getR()); if ((parent->Position()-target->Position()).Magnitude()-parent->rSize()-target->rSize()>dist) { SetDest (target->Position()); }else { SetDest(parent->Position()+face.Cast()); //VSFileSystem::vs_fprintf (stderr,"facing...cool"); } ChangeHeading::Execute(); if (!finish) { ResetDone(); } }
void FaceTarget::Execute() { Unit * target = parent->Target(); if (target==NULL){ done = finish; return; } SetDest(target->isSubUnit()?target->Position():target->LocalPosition()); ChangeHeading::Execute(); if (!finish) { ResetDone(); } }
static void FaceTarget (Unit * un) { Unit * targ = un->Target(); if (targ) { QVector dir (targ->Position()-un->Position()); dir.Normalize(); Vector p,q,r; un->GetOrientation(p,q,r); QVector qq(q.Cast()); qq = qq+QVector (.001,.001,.001); un->SetOrientation (qq,dir); } }
Unit * DockToSavedBases( int playernum, QVector &safevec ) { string str = game_options.startDockedTo; Unit *plr = _Universe->AccessCockpit( playernum )->GetParent(); if ( !plr || !plr->getStarSystem() ) { safevec = QVector( 0, 0, 0 ); return NULL; } vector< string >strs = loadStringList( playernum, mission_key ); if ( strs.size() ) str = strs[0]; Unit *closestUnit = NULL; float lastdist = 0; float dist = 0; Unit *un; QVector dock_position( plr->curr_physical_state.position ); for (un_iter iter = plr->getStarSystem()->getUnitList().createIterator(); (un = *iter); ++iter) if (un->name == str || un->getFullname() == str) { dist = UnitUtil::getSignificantDistance( plr, un ); if (closestUnit == NULL || dist < lastdist) { lastdist = dist; closestUnit = un; } } if (closestUnit) { if (UnitUtil::getSignificantDistance( plr, closestUnit ) > 0 && closestUnit->isUnit() != PLANETPTR) dock_position = closestUnit->Position(); dock_position = UniverseUtil::SafeEntrancePoint( dock_position, plr->rSize() ); plr->SetPosAndCumPos( dock_position ); vector< DockingPorts >dprt = closestUnit->pImage->dockingports; unsigned int i; for (i = 0;; i++) { if ( i >= dprt.size() ) { safevec = QVector( 0, 0, 0 ); return NULL; } if (!dprt[i].IsOccupied()) break; } plr->ForceDock( closestUnit, i ); closestUnit->pImage->clearedunits.push_back( plr ); closestUnit->RequestPhysics(); _Universe->AccessCockpit( playernum )->retry_dock = 0; } else { if (_Universe->AccessCockpit( playernum )->retry_dock == 0) _Universe->AccessCockpit( playernum )->retry_dock = 128; else _Universe->AccessCockpit( playernum )->retry_dock -= 1; } safevec = dock_position; return ( closestUnit && closestUnit->isDocked( plr ) ) ? closestUnit : NULL; }
void GameUnit<UnitType>::Thrust(const Vector &amt1,bool afterburn){ if (this->afterburntype == 0) afterburn=afterburn&&this->energy>this->afterburnenergy*SIMULATION_ATOM; if (this->afterburntype == 1) afterburn=afterburn&&this->fuel>0; if (this->afterburntype == 2) afterburn=afterburn&&this->warpenergy>0; Unit::Thrust( amt1, afterburn); static bool must_afterburn_to_buzz=XMLSupport::parse_bool(vs_config->getVariable("audio","buzzing_needs_afterburner","false")); if (_Universe->isPlayerStarship(this)!=NULL) { static int playerengine = AUDCreateSound (vs_config->getVariable ("unitaudio","player_afterburner","sfx10.wav"),true); static float enginegain=XMLSupport::parse_float(vs_config->getVariable("audio","afterburner_gain",".5")); if (afterburn!=AUDIsPlaying (playerengine)) { if (afterburn) AUDPlay (playerengine,QVector(0,0,0),Vector(0,0,0),enginegain); else AUDStopPlaying (playerengine); } }else if (afterburn||!must_afterburn_to_buzz) { static float buzzingtime=XMLSupport::parse_float(vs_config->getVariable("audio","buzzing_time","5")); static float buzzingdistance=XMLSupport::parse_float(vs_config->getVariable("audio","buzzing_distance","5")); static float lastbuzz=getNewTime(); Unit * playa = _Universe->AccessCockpit()->GetParent(); if (playa) { Vector diff=this->Position()-playa->Position(); if (UnitUtil::getDistance(this,playa)<buzzingdistance&&playa->owner!=this&&this->owner!=playa&&this->owner!=playa->owner) { float ttime=getNewTime(); if (ttime-lastbuzz>buzzingtime) { Vector pvel=playa->GetVelocity(); Vector vel=this->GetVelocity(); pvel.Normalize(); vel.Normalize(); float dotprod=vel.Dot(pvel); if (dotprod<.86) { lastbuzz=ttime; AUDPlay(this->sound->engine,this->Position(),this->GetVelocity(),1); } else { } } } } } }
void GameStarSystem::DrawJumpStars() { for (unsigned int kk=0;kk<pendingjump.size();++kk) { int k=pendingjump[kk]->animation; if (k!=-1) { Unit * un = pendingjump[kk]->un.GetUnit(); if (un) { Vector p,q,r; un->GetOrientation (p,q,r); JumpAnimations[k].a->SetPosition (un->Position()+r.Cast()*un->rSize()*(pendingjump[kk]->delay+.25)); JumpAnimations[k].a->SetOrientation (p,q,r); float dd = un->rSize()*game_options.jumpgatesize*(un->GetJumpStatus().delay-pendingjump[kk]->delay)/(float)un->GetJumpStatus().delay; JumpAnimations[k].a->SetDimensions (dd,dd); } } } unsigned int i; for (i=0;i<JumpAnimations.size();++i) { if (JumpAnimations[i].a) JumpAnimations[i].a->Draw(); } for (i=0;i<VolatileJumpAnimations.size();++i) { if (VolatileJumpAnimations[i].a) { float hei, wid; VolatileJumpAnimations[i].a->GetDimensions(hei,wid); VolatileJumpAnimations[i].a->SetDimensions(VolatileJumpAnimations[i].percent*hei,VolatileJumpAnimations[i].percent*wid); if (VolatileJumpAnimations[i].a->Done()) { delete VolatileJumpAnimations[i].a; VolatileJumpAnimations.erase (VolatileJumpAnimations.begin()+i); --i; } else { VolatileJumpAnimations[i].a->Draw(); } } } }
void AIScript::LoadXML() { static int aidebug = XMLSupport::parse_int( vs_config->getVariable( "AI", "debug_level", "0" ) ); using namespace AiXml; using namespace VSFileSystem; string full_filename = filename; bool doroll = false; HardCodedMap::const_iterator iter = hard_coded_scripts.find( full_filename ); if (iter==hard_coded_scripts.end() && full_filename.length() > 5 && full_filename[0] == 'r' && full_filename[1] == 'o' && full_filename[2] == 'l' && full_filename[3] == 'l' && full_filename[4] == ' ') { doroll = true; full_filename = full_filename.substr( 5 ); iter = hard_coded_scripts.find( full_filename ); } if ( iter != hard_coded_scripts.end() ) { CCScript *myscript = (*iter).second; (*myscript)(this, parent); if (doroll) { unsigned int val = rand(); if (val < RAND_MAX/4) RollRightHard( this, parent ); else if (val < RAND_MAX/2) RollLeftHard( this, parent ); else RollLeft( this, parent ); } if (aidebug > 1) { VSFileSystem::vs_fprintf( stderr, "%f using hcs %s for %s threat %f\n", mission->getGametime(), filename, parent->name.get().c_str(), parent->GetComputerData().threatlevel ); } if ( _Universe->isPlayerStarship( parent->Target() ) ) { float value; static float game_speed = XMLSupport::parse_float( vs_config->getVariable( "physics", "game_speed", "1" ) ); static float game_accel = XMLSupport::parse_float( vs_config->getVariable( "physics", "game_accel", "1" ) ); { Unit *targ = parent->Target(); if (targ) { Vector PosDifference = ( targ->Position()-parent->Position() ).Cast(); float pdmag = PosDifference.Magnitude(); value = ( pdmag-parent->rSize()-targ->rSize() ); float myvel = pdmag > 0 ? PosDifference.Dot( parent->GetVelocity()-targ->GetVelocity() )/pdmag : 0; if (myvel > 0) value -= myvel*myvel/( 2*( parent->Limits().retro/parent->GetMass() ) ); } else { value = 10000; } value /= game_speed*game_accel; } if (aidebug > 0) { UniverseUtil::IOmessage( 0, parent->name, "all", string( "using script " )+string( filename )+" threat "+XMLSupport::tostring( parent->GetComputerData().threatlevel )+" dis " +XMLSupport::tostring( value ) ); } } return; } else { if (aidebug > 1) VSFileSystem::vs_fprintf( stderr, "using soft coded script %s", filename ); if (aidebug > 0) UniverseUtil::IOmessage( 0, parent->name, "all", string( "FAILED(or missile) script " )+string( filename )+" threat "+XMLSupport::tostring( parent->GetComputerData().threatlevel ) ); } #ifdef AIDBG VSFileSystem::vs_fprintf( stderr, "chd" ); #endif #ifdef AIDBG VSFileSystem::vs_fprintf( stderr, "echd" ); #endif VSFile f; VSError err = f.OpenReadOnly( filename, AiFile ); #ifdef AIDBG VSFileSystem::vs_fprintf( stderr, "backup " ); #endif if (err > Ok) { VSFileSystem::vs_fprintf( stderr, "cannot find AI script %s\n", filename ); if (hard_coded_scripts.find(filename)!=hard_coded_scripts.end()) { assert(0); } return; } #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "nxml" ); #endif xml = new AIScriptXML; xml->unitlevel = 0; xml->terminate = true; xml->afterburn = true; xml->acc = 2; xml->defaultvec = QVector( 0, 0, 0 ); xml->defaultf = 0; #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "parscrea" ); #endif XML_Parser parser = XML_ParserCreate( NULL ); #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "usdat %x", parser ); #endif XML_SetUserData( parser, this ); #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "elha" ); #endif XML_SetElementHandler( parser, &AIScript::beginElement, &AIScript::endElement ); #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "do" ); #endif XML_Parse( parser, ( f.ReadFull() ).c_str(), f.Size(), 1 ); #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "%xxml_free", parser ); fflush( stderr ); #endif XML_ParserFree( parser ); #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "xml_freed" ); #endif f.Close(); for (unsigned int i = 0; i < xml->orders.size(); i++) { #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "parset" ); #endif xml->orders[i]->SetParent( parent ); EnqueueOrder( xml->orders[i] ); #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "cachunkx" ); #endif } #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "xml%x", xml ); fflush( stderr ); #endif delete xml; #ifdef BIDBG VSFileSystem::vs_fprintf( stderr, "\\xml\n" ); fflush( stderr ); #endif }
void AIScript::beginElement( const string &name, const AttributeList &attributes ) { using namespace AiXml; xml->itts = false; Unit *tmp; #ifdef AIDBG VSFileSystem::vs_fprintf( stderr, "0" ); #endif Names elem = (Names) element_map.lookup( name ); #ifdef AIDBG VSFileSystem::vs_fprintf( stderr, "1%x ", &elem ); #endif AttributeList::const_iterator iter; switch (elem) { case DEFAULT: xml->unitlevel += 2; //pretend it's at a reasonable level break; case UNKNOWN: xml->unitlevel++; return; case SCRIPT: xml->unitlevel++; break; case LINEAR: xml->lin = 1; case ANGULAR: case VECTOR: xml->unitlevel++; xml->vectors.push( QVector( 0, 0, 0 ) ); for (iter = attributes.begin(); iter != attributes.end(); iter++) { switch ( attribute_map.lookup( (*iter).name ) ) { case X: topv().i = parse_float( (*iter).value ); break; case Y: topv().j = parse_float( (*iter).value ); break; case Z: topv().k = parse_float( (*iter).value ); break; case DUPLIC: #ifdef AIDBG VSFileSystem::vs_fprintf( stderr, "1%x ", &elem ); #endif xml->vectors.pop(); //get rid of dummy vector pushed on above xml->vectors.push( xml->vectors.top() ); break; case THREATPOS: if ( ( tmp = this->parent->Threat() ) ) { topv() = ( tmp->Position() ); } else { if ( ( tmp = this->parent->Target() ) ) topv() = ( tmp->Position() ); else topv() = (xml->defaultvec); } break; case TARGETPOS: if ( ( tmp = this->parent->Target() ) ) topv() = ( tmp->Position() ); else topv() = (xml->defaultvec); break; case YOURPOS: topv() = ( this->parent->Position() ); break; case THREATV: if ( ( tmp = this->parent->Threat() ) ) { topv() = ( tmp->GetVelocity() ); } else { if ( ( tmp = this->parent->Target() ) ) topv() = ( tmp->GetVelocity() ); else topv() = (xml->defaultvec); } break; case TARGETV: if ( ( tmp = this->parent->Target() ) ) topv() = ( tmp->GetVelocity() ); else topv() = (xml->defaultvec); break; case YOURV: topv() = ( this->parent->GetVelocity() ); break; } } break; case MOVETO: xml->unitlevel++; xml->acc = 2; xml->afterburn = true; for (iter = attributes.begin(); iter != attributes.end(); iter++) { switch ( attribute_map.lookup( (*iter).name ) ) { case AFTERBURN: xml->afterburn = parse_bool( (*iter).value ); case ACCURACY: xml->acc = parse_int( (*iter).value ); break; } } break; case FACETARGET: #ifdef AIDBG VSFileSystem::vs_fprintf( stderr, "ft" ); #endif xml->unitlevel++; xml->acc = 3; xml->itts = false; xml->afterburn = true; xml->terminate = true; for (iter = attributes.begin(); iter != attributes.end(); iter++) { switch ( attribute_map.lookup( (*iter).name ) ) { case TERMINATE: xml->terminate = parse_bool( (*iter).value ); break; case ACCURACY: xml->acc = parse_int( (*iter).value ); break; case ITTTS: xml->itts = parse_bool( (*iter).value ); break; } } #ifdef AIDBG VSFileSystem::vs_fprintf( stderr, "eft" ); #endif break; case CHANGEHEAD: xml->unitlevel++; xml->acc = 2; xml->afterburn = true; xml->terminate = true; for (iter = attributes.begin(); iter != attributes.end(); iter++) { switch ( attribute_map.lookup( (*iter).name ) ) { case TERMINATE: xml->terminate = parse_bool( (*iter).value ); break; case ACCURACY: xml->acc = parse_int( (*iter).value ); break; } } break; case YOURPOS: xml->unitlevel++; xml->vectors.push( this->parent->Position() ); break; case THREATWORLD: xml->unitlevel++; break; case TARGETWORLD: xml->unitlevel++; break; case THREATLOCAL: xml->unitlevel++; break; case TARGETLOCAL: xml->unitlevel++; break; case YOURLOCAL: xml->unitlevel++; break; case YOURWORLD: xml->unitlevel++; break; case NORMALIZE: case SCALE: case CROSS: case DOT: case MULTF: case ADDF: case FROMF: case TOF: case ADD: case SUB: case NEG: xml->unitlevel++; break; case FFLOAT: xml->unitlevel++; xml->floats.push( 0 ); for (iter = attributes.begin(); iter != attributes.end(); iter++) { switch ( attribute_map.lookup( (*iter).name ) ) { case VALUE: topf() = parse_float( (*iter).value ); break; case SIMATOM: topf() = SIMULATION_ATOM; case DUPLIC: xml->floats.pop(); //get rid of dummy vector pushed on above xml->floats.push( xml->floats.top() ); break; } } break; case MATCHLIN: case MATCHANG: case MATCHVEL: #ifdef AIDBG VSFileSystem::vs_fprintf( stderr, "mlv" ); #endif xml->unitlevel++; xml->acc = 0; xml->afterburn = false; xml->terminate = true; for (iter = attributes.begin(); iter != attributes.end(); iter++) { switch ( attribute_map.lookup( (*iter).name ) ) { case AFTERBURN: xml->afterburn = parse_bool( (*iter).value ); break; case TERMINATE: xml->terminate = parse_bool( (*iter).value ); break; case LOCAL: xml->acc = parse_bool( (*iter).value ); break; } } #ifdef AIDBG VSFileSystem::vs_fprintf( stderr, "emlv " ); #endif break; case CLOAKFOR: xml->unitlevel++; xml->executefor.push_back( 0 ); xml->terminate = true; for (iter = attributes.begin(); iter != attributes.end(); iter++) { switch ( attribute_map.lookup( (*iter).name ) ) { case TERMINATE: xml->terminate = parse_bool( (*iter).value ); break; case TIME: xml->executefor.back() = parse_float( (*iter).value ); break; } } break; case EXECUTEFOR: xml->unitlevel++; xml->executefor.push_back( 0 ); for (iter = attributes.begin(); iter != attributes.end(); iter++) { switch ( attribute_map.lookup( (*iter).name ) ) { case TIME: xml->executefor.back() = parse_float( (*iter).value ); break; } } break; default: break; } }
void TurretAI::Execute() { Unit *targ = parent->Target(); if (range == -1) { range = mrange = speed = 0; parent->getAverageGunSpeed( speed, range, mrange ); float tspeed, trange, tmrange; Unit *gun; if (parent->GetNumMounts() == 0) { speed = 1; range = 1; mrange = 1; //not much } for (un_iter i = parent->getSubUnits(); (gun = *i) != NULL; ++i) { (*i)->getAverageGunSpeed( tspeed, trange, tmrange ); if (trange > range) { speed = tspeed; range = trange; mrange = tmrange; } } if (range == 0) { range = mrange; speed = FLT_MAX; } } if (targ) { static float dot_cutoff = XMLSupport::parse_float( vs_config->getVariable( "AI", "Firing", "TurretDotCutoff", ".4" ) ); static float missile_prob = XMLSupport::parse_float( vs_config->getVariable( "AI", "Firing", "TurretMissileProbability", ".05" ) ); FaceTargetITTS::Execute(); if (parent->GetNumMounts() > 0) { Vector R( parent->GetTransformation().getR() ); QVector Pos( targ->Position()-parent->Position() ); double mag = Pos.Magnitude(); Pos = Pos/mag; float dot = R.Dot( Pos.Cast() ); int neu = FactionUtil::GetNeutralFaction(); int upg = FactionUtil::GetUpgradeFaction(); bool isplayerstarship = _Universe->isPlayerStarshipVoid( parent->owner ) != NULL; bool shouldfire = ( (mag-targ->rSize()-parent->rSize() < range && dot > dot_cutoff) && ( isplayerstarship == false || targ->faction == upg || ( isplayerstarship && (targ->getRelation( (Unit*) parent->owner ) < 0 /*now that it is a player, we know it's dereferencable*/ || targ->Target() == (Unit*) parent->owner) ) ) && targ->faction != neu ); parent->Fire( FireBitmask( parent, shouldfire, rand() < missile_prob*RAND_MAX*SIMULATION_ATOM ), true ); if (!shouldfire) parent->UnFire(); hadFired = shouldfire; } if (targ->hull < 0) parent->Target( NULL ); } else if (hadFired && parent->GetNumMounts() > 0) { // When we get a kill, we must stop firing parent->UnFire(); hadFired = false; } }
bool Unit::Collide( Unit *target ) { //now first OF ALL make sure they're within bubbles of each other... if ( ( Position()-target->Position() ).MagnitudeSquared() > mysqr( radial_size+target->radial_size ) ) return false; clsptr targetisUnit = target->isUnit(); clsptr thisisUnit = this->isUnit(); static float NEBULA_SPACE_DRAG = XMLSupport::parse_float( vs_config->getVariable( "physics", "nebula_space_drag", "0.01" ) ); if (targetisUnit == NEBULAPTR) //why? why not? this->Velocity *= (1-NEBULA_SPACE_DRAG); if ( target == this || ( (targetisUnit != NEBULAPTR && thisisUnit != NEBULAPTR) && ( owner == target || target->owner == this || (owner != NULL && target->owner == owner) ) ) || (Network != NULL && _Universe->isPlayerStarship( target ) == NULL && _Universe->isPlayerStarship( this ) == NULL) ) return false; if (targetisUnit == ASTEROIDPTR && thisisUnit == ASTEROIDPTR) return false; std::multimap< Unit*, Unit* > *last_collisions = &_Universe->activeStarSystem()->last_collisions; last_collisions->insert( std::pair< Unit*, Unit* > ( this, target ) ); //unit v unit? use point sampling? if ( ( this->DockedOrDocking()&(DOCKED_INSIDE|DOCKED) ) || ( target->DockedOrDocking()&(DOCKED_INSIDE|DOCKED) ) ) return false; //now do some serious checks Unit *bigger; Unit *smaller; if (radial_size < target->radial_size) { bigger = target; smaller = this; } else { bigger = this; smaller = target; } bool usecoltree = (this->colTrees && target->colTrees) ? this->colTrees->colTree( this, Vector( 0, 0, 0 ) ) && target->colTrees->colTree( this, Vector( 0, 0, 0 ) ) : false; if (usecoltree) { QVector bigpos, smallpos; Vector bigNormal, smallNormal; if ( bigger->InsideCollideTree( smaller, bigpos, bigNormal, smallpos, smallNormal ) ) { if ( !bigger->isDocked( smaller ) && !smaller->isDocked( bigger ) ) bigger->reactToCollision( smaller, bigpos, bigNormal, smallpos, smallNormal, 10 ); else return false; } else {return false; } } else { Vector normal( -1, -1, -1 ); float dist = 0.0; if ( bigger->Inside( smaller->Position(), smaller->rSize(), normal, dist ) ) { if ( !bigger->isDocked( smaller ) && !smaller->isDocked( bigger ) ) bigger->reactToCollision( smaller, bigger->Position(), normal, smaller->Position(), -normal, dist ); else return false; } else { return(false); } } return true; }
bool Unit::InsideCollideTree( Unit *smaller, QVector &bigpos, Vector &bigNormal, QVector &smallpos, Vector &smallNormal, bool bigasteroid, bool smallasteroid ) { if (smaller->colTrees == NULL || this->colTrees == NULL) return false; if (hull < 0) return false; if (smaller->colTrees->usingColTree() == false || this->colTrees->usingColTree() == false) return false; csOPCODECollider::ResetCollisionPairs(); Unit *bigger = this; csReversibleTransform bigtransform( bigger->cumulative_transformation_matrix ); csReversibleTransform smalltransform( smaller->cumulative_transformation_matrix ); smalltransform.SetO2TTranslation( csVector3( smaller->cumulative_transformation_matrix.p -bigger->cumulative_transformation_matrix.p ) ); bigtransform.SetO2TTranslation( csVector3( 0, 0, 0 ) ); //we're only gonna lerp the positions for speed here... gahh! // Check for shield collisions here prior to checking for mesh on mesh or ray collisions below. csOPCODECollider *tmpCol = smaller->colTrees->colTree( smaller, bigger->GetWarpVelocity() ); if ( tmpCol && ( tmpCol->Collide( *bigger->colTrees->colTree( bigger, smaller->GetWarpVelocity() ), &smalltransform, &bigtransform ) ) ) { csCollisionPair *mycollide = csOPCODECollider::GetCollisions(); unsigned int numHits = csOPCODECollider::GetCollisionPairCount(); if (numHits) { smallpos.Set( (mycollide[0].a1.x+mycollide[0].b1.x+mycollide[0].c1.x)/3.0f, (mycollide[0].a1.y+mycollide[0].b1.y+mycollide[0].c1.y)/3.0f, (mycollide[0].a1.z+mycollide[0].b1.z+mycollide[0].c1.z)/3.0f ); smallpos = Transform( smaller->cumulative_transformation_matrix, smallpos ); bigpos.Set( (mycollide[0].a2.x+mycollide[0].b2.x+mycollide[0].c2.x)/3.0f, (mycollide[0].a2.y+mycollide[0].b2.y+mycollide[0].c2.y)/3.0f, (mycollide[0].a2.z+mycollide[0].b2.z+mycollide[0].c2.z)/3.0f ); bigpos = Transform( bigger->cumulative_transformation_matrix, bigpos ); csVector3 sn, bn; sn.Cross( mycollide[0].b1-mycollide[0].a1, mycollide[0].c1-mycollide[0].a1 ); bn.Cross( mycollide[0].b2-mycollide[0].a2, mycollide[0].c2-mycollide[0].a2 ); sn.Normalize(); bn.Normalize(); smallNormal.Set( sn.x, sn.y, sn.z ); bigNormal.Set( bn.x, bn.y, bn.z ); smallNormal = TransformNormal( smaller->cumulative_transformation_matrix, smallNormal ); bigNormal = TransformNormal( bigger->cumulative_transformation_matrix, bigNormal ); return true; } } un_iter i; static float rsizelim = XMLSupport::parse_float( vs_config->getVariable( "physics", "smallest_subunit_to_collide", ".2" ) ); clsptr bigtype = bigasteroid ? ASTEROIDPTR : bigger->isUnit(); clsptr smalltype = smallasteroid ? ASTEROIDPTR : smaller->isUnit(); if ( bigger->SubUnits.empty() == false && (bigger->graphicOptions.RecurseIntoSubUnitsOnCollision == true || bigtype == ASTEROIDPTR) ) { i = bigger->getSubUnits(); float rad = smaller->rSize(); for (Unit *un; (un = *i); ++i) { float subrad = un->rSize(); if ( (bigtype != ASTEROIDPTR) && (subrad/bigger->rSize() < rsizelim) ) { break; } if ( ( un->Position()-smaller->Position() ).Magnitude() <= subrad+rad ) { if ( ( un->InsideCollideTree( smaller, bigpos, bigNormal, smallpos, smallNormal, bigtype == ASTEROIDPTR, smalltype == ASTEROIDPTR ) ) ) return true; } } } if ( smaller->SubUnits.empty() == false && (smaller->graphicOptions.RecurseIntoSubUnitsOnCollision == true || smalltype == ASTEROIDPTR) ) { i = smaller->getSubUnits(); float rad = bigger->rSize(); for (Unit *un; (un = *i); ++i) { float subrad = un->rSize(); if ( (smalltype != ASTEROIDPTR) && (subrad/smaller->rSize() < rsizelim) ) break; if ( ( un->Position()-bigger->Position() ).Magnitude() <= subrad+rad ) { if ( ( bigger->InsideCollideTree( un, bigpos, bigNormal, smallpos, smallNormal, bigtype == ASTEROIDPTR, smalltype == ASTEROIDPTR ) ) ) return true; } } } //FIXME //doesn't check all i*j options of subunits vs subunits return false; }
void AutoLongHaul::Execute() { Unit * target = group.GetUnit(); if (target==NULL){ group.SetUnit(parent->Target()); done = finish; parent->autopilotactive=false; return; } static bool compensate_for_interdiction=XMLSupport::parse_bool(vs_config->getVariable("physics","autopilot_compensate_for_interdiction","false")); static float enough_warp_for_cruise=XMLSupport::parse_float(vs_config->getVariable("physics","enough_warp_for_cruise","1000")); static float go_perpendicular_speed=XMLSupport::parse_float(vs_config->getVariable("physics","warp_perpendicular","80")); static float min_warp_orbit_radius=XMLSupport::parse_float(vs_config->getVariable("physics","min_warp_orbit_radius","100000000")); static float warp_orbit_multiplier=XMLSupport::parse_float(vs_config->getVariable("physics","warp_orbit_multiplier","4")); static float warp_behind_angle=cos(3.1415926536*XMLSupport::parse_float(vs_config->getVariable("physics","warp_behind_angle","150"))/180.); QVector myposition=parent->isSubUnit()?parent->Position():parent->LocalPosition();//get unit pos QVector destination = target->isSubUnit()?target->Position():target->LocalPosition();//get destination QVector destinationdirection=(destination-myposition);//find vector from us to destination double destinationdistance=destinationdirection.Magnitude(); destinationdirection=destinationdirection*(1./destinationdistance);//this is a direction, so it is normalize if (parent->graphicOptions.WarpFieldStrength<enough_warp_for_cruise&&parent->graphicOptions.InWarp) {//face target unless warp ramping is done and warp is less than some intolerable ammt Unit *obstacle=NULL; float maxmultiplier=CalculateNearestWarpUnit(parent,FLT_MAX,&obstacle,compensate_for_interdiction);//find the unit affecting our spec bool currently_inside_landing_zone=false; if (obstacle) { currently_inside_landing_zone=InsideLandingPort(obstacle); } if (currently_inside_landing_zone!=inside_landing_zone) { inside_landing_zone=currently_inside_landing_zone; MakeLinearVelocityOrder(); } if (maxmultiplier<enough_warp_for_cruise&&obstacle!=NULL&&obstacle!=target) {//if it exists and is not our destination QVector obstacledirection=(obstacle->LocalPosition()-myposition);//find vector from us to obstacle double obstacledistance=obstacledirection.Magnitude(); obstacledirection=obstacledirection*(1./obstacledistance);//normalize the obstacle direction as well float angle=obstacledirection.Dot(destinationdirection); if (obstacledistance-obstacle->rSize()<destinationdistance-target->rSize()&&angle>warp_behind_angle) {//if our obstacle is closer than obj and the obstacle is not behind us QVector planetdest=destination-obstacle->LocalPosition();//find the vector from planet to dest QVector planetme=-obstacledirection;//obstacle to me QVector planetperp=planetme.Cross(planetdest);//find vector out of that plane QVector detourvector=destinationdirection.Cross(planetperp);//find vector perpendicular to our desired course emerging from planet double renormalizedetour=detourvector.Magnitude(); if (renormalizedetour>.01) detourvector=detourvector*(1./renormalizedetour);//normalize it double finaldetourdistance=mymax(obstacle->rSize()*warp_orbit_multiplier,min_warp_orbit_radius);//scale that direction by some multiplier of obstacle size and a constant detourvector=detourvector*finaldetourdistance;//we want to go perpendicular to our transit direction by that ammt QVector newdestination=NewDestination(obstacle->LocalPosition()+detourvector,finaldetourdistance);// add to our position float weight=(maxmultiplier-go_perpendicular_speed)/(enough_warp_for_cruise-go_perpendicular_speed);//find out how close we are to our desired warp multiplier and weight our direction by that weight*=weight;// if (maxmultiplier<go_perpendicular_speed) { QVector perpendicular=myposition+planetme*(finaldetourdistance/planetme.Magnitude()); weight=(go_perpendicular_speed-maxmultiplier)/go_perpendicular_speed; destination=weight*perpendicular+(1-weight)*newdestination; }else { QVector olddestination=myposition+destinationdirection*finaldetourdistance;//destination direction in the same magnitude as the newdestination from the ship destination=newdestination*(1-weight)+olddestination*weight;//use the weight to combine our direction and the dest } StraightToTarget=false; }else StraightToTarget=true; }else StraightToTarget=true; }else if (parent->graphicOptions.WarpFieldStrength>=enough_warp_for_cruise) { StraightToTarget=true; } if(parent->graphicOptions.InWarp==0&&parent->graphicOptions.RampCounter==0) { deactivatewarp=false; } float mass=parent->GetMass(); float minaccel=mymin(parent->limits.lateral,mymin(parent->limits.vertical,mymin(parent->limits.forward,parent->limits.retro))); if (mass) minaccel/=mass; if (StraightToTarget&&useJitteryAutopilot(parent,target,minaccel)) { QVector cfacing=parent->cumulative_transformation_matrix.getR();//velocity.Cast(); float speed=cfacing.Magnitude(); if (speed>.01) cfacing=cfacing*(1./speed); static float dotLimit=cos(3.1415926536*XMLSupport::parse_float(vs_config->getVariable("physics","autopilot_spec_lining_up_angle","3"))/180.); if (cfacing.Dot(destinationdirection)<dotLimit) {//if wanting to face target but overshooting. deactivatewarp=true;//turn off drive } } static bool rampdown=XMLSupport::parse_bool(vs_config->getVariable("physics","autopilot_ramp_warp_down","true")); if (DistanceWarrantsWarpTo(parent,UnitUtil::getSignificantDistance(parent,target),false)&&deactivatewarp==false) {\ if (parent->graphicOptions.InWarp==0) { parent->graphicOptions.InWarp=1; parent->graphicOptions.WarpRamping=1; } }else { if (parent->graphicOptions.InWarp==1) { parent->graphicOptions.InWarp=0; if (rampdown) parent->graphicOptions.WarpRamping=1; } } SetDest(destination); bool combat_mode=parent->GetComputerData().combat_mode; parent->GetComputerData().combat_mode=!inside_landing_zone;//turn off limits in landing zone ChangeHeading::Execute(); parent->GetComputerData().combat_mode=combat_mode; if (!finish) { ResetDone(); } static float distance_to_stop=XMLSupport::parse_float(vs_config->getVariable("physics","auto_pilot_termination_distance","6000")); static float enemy_distance_to_stop=XMLSupport::parse_float(vs_config->getVariable("physics","auto_pilot_termination_distance_enemy","24000")); static bool do_auto_finish=XMLSupport::parse_bool(vs_config->getVariable("physics","autopilot_terminate","true")); double dis=UnitUtil::getSignificantDistance(parent,target); bool stopnow=false; float speed=parent->GetComputerData().max_combat_ab_speed; if (speed&&parent->limits.retro) { float time_to_destination=dis/speed;//conservative float time_to_stop=speed*mass/parent->limits.retro; if (time_to_destination<=time_to_stop) stopnow=true; } if (do_auto_finish&&(stopnow||dis<distance_to_stop||(target->Target()==parent&&dis<enemy_distance_to_stop))){ parent->autopilotactive=false; if (parent->graphicOptions.InWarp==1) { parent->graphicOptions.InWarp=0; if (rampdown){ parent->graphicOptions.WarpRamping=1; } } done=true; } }
void FaceTargetITTS::Execute() { Unit * target = parent->Target(); if (target==NULL){ done = finish; return; } if (speed == float(.00001)) { float mrange; float range; parent->getAverageGunSpeed(speed,range,mrange); if (speed ==float (.00001)) { speed = FLT_MAX; } } SetDest(useitts?target->PositionITTS(parent->Position(),parent->cumulative_velocity,speed,false):target->Position()); ChangeHeading::Execute(); if (!finish) { ResetDone(); } }
//#define UPDATEDEBUG //for hard to track down bugs void GameStarSystem::Draw(bool DrawCockpit) { double starttime=queryTime(); GFXEnable (DEPTHTEST); GFXEnable (DEPTHWRITE); saved_interpolation_blend_factor=interpolation_blend_factor = (1./PHY_NUM)*((PHY_NUM*time)/SIMULATION_ATOM+current_stage); GFXColor4f(1,1,1,1); if (DrawCockpit) { AnimatedTexture::UpdateAllFrame(); } for (unsigned int i=0;i<contterrains.size();++i) { contterrains[i]->AdjustTerrain(this); } Unit * par; bool alreadysetviewport=false; if ((par=_Universe->AccessCockpit()->GetParent())==NULL) { _Universe->AccessCamera()->UpdateGFX (GFXTRUE); } else { if (!par->isSubUnit()) { //now we can assume world is topps par-> cumulative_transformation = linear_interpolate (par->prev_physical_state,par->curr_physical_state,interpolation_blend_factor); Unit * targ = par->Target(); if (targ&&!targ->isSubUnit()) { targ-> cumulative_transformation = linear_interpolate (targ->prev_physical_state,targ->curr_physical_state,interpolation_blend_factor); } _Universe->AccessCockpit()->SetupViewPort(true); alreadysetviewport=true; } } double setupdrawtime=queryTime(); { cam_setup_phase=true; //int numships=0; Unit * saveparent=_Universe->AccessCockpit()->GetSaveParent(); Unit * targ=NULL; if (saveparent) { targ=saveparent->Target(); } //Array containing the two interesting units, so as not to have to copy-paste code Unit * camunits[2]={saveparent,targ}; float backup=SIMULATION_ATOM; unsigned int cur_sim_frame = _Universe->activeStarSystem()->getCurrentSimFrame(); for(int i=0;i<2;++i) { Unit *unit=camunits[i]; // Make sure unit is not null; if(unit&&!unit->isSubUnit()) { interpolation_blend_factor=calc_blend_factor(saved_interpolation_blend_factor,unit->sim_atom_multiplier,unit->cur_sim_queue_slot,cur_sim_frame); SIMULATION_ATOM = backup*unit->sim_atom_multiplier; ((GameUnit<Unit> *)unit)->GameUnit<Unit>::Draw(); } } interpolation_blend_factor=saved_interpolation_blend_factor; SIMULATION_ATOM=backup; //printf("Number of insystem ships: %d (%d FPS)\n",numships,(int)(1.f/GetElapsedTime())); ///this is the final, smoothly calculated cam _Universe->AccessCockpit()->SetupViewPort(true); cam_setup_phase=false; } setupdrawtime=queryTime()-setupdrawtime; GFXDisable (LIGHTING); bg->Draw(); double drawtime=queryTime(); double maxdrawtime=0; //Ballpark estimate of when an object of configurable size first becomes one pixel QVector drawstartpos=_Universe->AccessCamera()->GetPosition(); Collidable key_iterator(0,1,drawstartpos); UnitWithinRangeOfPosition<UnitDrawer> drawer(game_options.precull_dist,0,key_iterator); //Need to draw really big stuff (i.e. planets, deathstars, and other mind-bogglingly big things that shouldn't be culled despited extreme distance Unit* unit; if ((drawer.action.parent=_Universe->AccessCockpit()->GetParent())!=NULL) { drawer.action.parenttarget=drawer.action.parent->Target(); } for(un_iter iter=this->GravitationalUnits.createIterator();(unit=*iter)!=NULL;++iter) { float distance = (drawstartpos-unit->Position()).Magnitude()-unit->rSize(); if(distance < game_options.precull_dist) { drawer.action.grav_acquire(unit); } else { drawer.action.draw(unit); } } // Need to get iterator to approx camera position CollideMap::iterator parent=collidemap[Unit::UNIT_ONLY]->lower_bound(key_iterator); findObjectsFromPosition(this->collidemap[Unit::UNIT_ONLY],parent,&drawer,drawstartpos,0,true); drawer.action.drawParents();//draw units targeted by camera //FIXME maybe we could do bolts & units instead of unit only--and avoid bolt drawing step #if 0 for (unsigned int sim_counter=0;sim_counter<=SIM_QUEUE_SIZE;++sim_counter) { double tmp=queryTime(); Unit *unit; UnitCollection::UnitIterator iter = physics_buffer[sim_counter].createIterator(); float backup=SIMULATION_ATOM; unsigned int cur_sim_frame = _Universe->activeStarSystem()->getCurrentSimFrame(); while((unit = iter.current())!=NULL) { interpolation_blend_factor=calc_blend_factor(saved_interpolation_blend_factor,unit->sim_atom_multiplier,unit->cur_sim_queue_slot,cur_sim_frame); //if (par&&par->Target()==unit) { //printf ("i:%f s:%f m:%d c:%d l:%d\n",interpolation_blend_factor,saved_interpolation_blend_factor,unit->sim_atom_multiplier,sim_counter,current_sim_location); //} SIMULATION_ATOM = backup*unit->sim_atom_multiplier; ((GameUnit<Unit> *)unit)->Draw(); iter.advance(); } interpolation_blend_factor=saved_interpolation_blend_factor; SIMULATION_ATOM=backup; tmp=queryTime()-tmp; if (tmp>maxdrawtime)maxdrawtime=tmp; } #endif drawtime=queryTime()-drawtime; WarpTrailDraw(); GFXFogMode (FOG_OFF); GFXColor tmpcol (0,0,0,1); GFXGetLightContextAmbient(tmpcol); double processmesh=queryTime(); if (!game_options.draw_near_stars_in_front_of_planets) stars->Draw(); Mesh::ProcessZFarMeshes(); if (game_options.draw_near_stars_in_front_of_planets) stars->Draw(); GFXEnable (DEPTHTEST); GFXEnable (DEPTHWRITE); //need to wait for lights to finish GamePlanet::ProcessTerrains(); Terrain::RenderAll(); Mesh::ProcessUndrawnMeshes(true); processmesh=queryTime()-processmesh; Nebula * neb; Matrix ident; Identity(ident); //Atmosphere::ProcessDrawQueue(); GFXPopGlobalEffects(); GFXLightContextAmbient(tmpcol); if ((neb = _Universe->AccessCamera()->GetNebula())) { neb->SetFogState(); } Beam::ProcessDrawQueue(); Bolt::Draw(); // if (_Universe->AccessCamera()->GetNebula()!=NULL) GFXFogMode (FOG_OFF); Animation::ProcessDrawQueue(); Halo::ProcessDrawQueue(); particleTrail.DrawAndUpdate(); GameStarSystem::DrawJumpStars(); ConditionalCursorDraw(false); // static bool doInputDFA = XMLSupport::parse_bool (vs_config->getVariable ("graphics","MouseCursor","false")); if (DrawCockpit) { _Universe->AccessCockpit()->Draw(); // if (doInputDFA) { // GFXHudMode (true); // systemInputDFA->Draw(); // GFXHudMode (false); // } } double fintime=queryTime()-starttime; if (debugPerformance()) { printf("draw: %f setup %f units %f maxunit %f processmesh %f ",fintime,setupdrawtime,drawtime,maxdrawtime,processmesh); } }
bool Cockpit::Update() { if (retry_dock && !SERVER && Network == NULL) { QVector vec; DockToSavedBases( _Universe->CurrentCockpit(), vec ); } if (jumpok) jumpok++; if (jumpok > 5) jumpok = 0; UpdAutoPilot(); Unit *par = GetParent(); if (par != NULL) { static float minEnergyForShieldDownpower = XMLSupport::parse_float( vs_config->getVariable( "physics", "shield_energy_downpower", "-.125" ) ); static float minEnergyShieldTime = XMLSupport::parse_float( vs_config->getVariable( "physics", "shield_energy_downpower_time", "5" ) ); static float minEnergyShieldPercent = XMLSupport::parse_float( vs_config->getVariable( "physics", "shield_energy_downpower_percent", ".66666666666666" ) ); bool toolittleenergy = (par->EnergyData() <= minEnergyForShieldDownpower); if (toolittleenergy) { secondsWithZeroEnergy += SIMULATION_ATOM; if (secondsWithZeroEnergy > minEnergyShieldTime) { secondsWithZeroEnergy = 0; PowerDownShield( &par->shield, minEnergyShieldPercent ); } } else { secondsWithZeroEnergy = 0; } } if ( turretcontrol.size() > _Universe->CurrentCockpit() ) { if (turretcontrol[_Universe->CurrentCockpit()]) { turretcontrol[_Universe->CurrentCockpit()] = 0; Unit *par = GetParent(); //this being here, it will require poking the turret from the undock script if (par) { if (par->name == "return_to_cockpit") { //if (par->owner->isUnit()==UNITPTR ) this->SetParent(par->owner,GetUnitFileName().c_str(),this->unitmodname.c_str(),savegame->GetPlayerLocation()); // this warps back to the parent unit if we're eject-docking. in this position it also causes badness upon loading a game. Unit *temp = findUnitInStarsystem( par->owner ); if (temp) { SwitchUnits( NULL, temp ); this->SetParent( temp, GetUnitFileName().c_str(), this->unitmodname.c_str(), temp->Position() ); //this warps back to the parent unit if we're eject-docking. causes badness upon loading a game. } par->Kill(); } } if (par) { static int index = 0; int i = 0; bool tmp = false; bool tmpgot = false; if (parentturret.GetUnit() == NULL) { tmpgot = true; Unit *un; for (un_iter ui = par->getSubUnits(); (un = *ui);) { if ( _Universe->isPlayerStarship( un ) ) { ++ui; continue; } if (i++ == index) { //NOTE : this may have been a correction to the conditional bug ++index; if (un->name.get().find( "accessory" ) == string::npos) { tmp = true; SwitchUnitsTurret( par, un ); parentturret.SetUnit( par ); Unit *finalunit = GetFinalTurret( un ); this->SetParent( finalunit, GetUnitFileName().c_str(), this->unitmodname.c_str(), savegame->GetPlayerLocation() ); break; } } ++ui; } } if (tmp == false) { if (tmpgot) index = 0; Unit *un = parentturret.GetUnit(); if ( un && ( !_Universe->isPlayerStarship( un ) ) ) { SetParent( un, GetUnitFileName().c_str(), this->unitmodname.c_str(), savegame->GetPlayerLocation() ); SwitchUnits( NULL, un ); parentturret.SetUnit( NULL ); un->SetTurretAI(); un->DisableTurretAI(); } } } } } static bool autoclear = XMLSupport::parse_bool( vs_config->getVariable( "AI", "autodock", "false" ) ); if (autoclear && par) { Unit *targ = par->Target(); if (targ) { static float autopilot_term_distance = XMLSupport::parse_float( vs_config->getVariable( "physics", "auto_pilot_termination_distance", "6000" ) ); float doubled = dockingdistance( targ, par ); if ( ( (targ->isUnit() != PLANETPTR && doubled < autopilot_term_distance) || (UnitUtil::getSignificantDistance( targ, par ) <= 0) ) && ( !( par->IsCleared( targ ) || targ->IsCleared( par ) || par->isDocked( targ ) || targ->isDocked( par ) ) ) && (par->getRelation( targ ) >= 0) && (targ->getRelation( par ) >= 0) ) { if ( targ->isUnit() != PLANETPTR || targ->GetDestinations().empty() ) RequestClearence( par, targ, 0 ); //sex is always 0... don't know how to get it. } else if ( ( par->IsCleared( targ ) || targ->IsCleared( par ) ) && ( !( par->isDocked( targ ) ) || targ->isDocked( par ) ) && ( (targ->isUnit() == PLANETPTR && UnitUtil::getSignificantDistance( par, targ ) > 0) || ( ( targ->isUnit() != PLANETPTR && UnitUtil::getSignificantDistance( par, targ ) > ( targ->rSize()+par->rSize() ) ) && (doubled >= autopilot_term_distance) ) ) ) { if ( targ->isUnit() != PLANETPTR || targ->GetDestinations().empty() ) { par->EndRequestClearance( targ ); targ->EndRequestClearance( par ); } } } } if ( switchunit.size() > _Universe->CurrentCockpit() ) { if (switchunit[_Universe->CurrentCockpit()]) { parentturret.SetUnit( NULL ); static float initialzoom = XMLSupport::parse_float( vs_config->getVariable( "graphics", "inital_zoom_factor", "2.25" ) ); zoomfactor = initialzoom; static int index = 0; switchunit[_Universe->CurrentCockpit()] = 0; static bool switch_nonowned_units = XMLSupport::parse_bool( vs_config->getVariable( "AI", "switch_nonowned_units", "true" ) ); //switch_nonowned_units = true; //static bool switch_to_fac=XMLSupport::parse_bool(vs_config->getVariable("AI","switch_to_whole_faction","true")); Unit *un; bool found = false; int i = 0; for (un_iter ui = _Universe->activeStarSystem()->getUnitList().createIterator(); (un = *ui); ++ui) if (un->faction == this->unitfaction) { //this switches units UNLESS we're an ejected pilot. Instead, if we are an ejected //pilot, switch only if we're close enough. //the trigger is to allow switching only between ships that are actually owned by you, this prevents //stealing a ship from a hired wingman. if ( ( ( (par != NULL) && (i++) >= index ) || par == NULL ) && ( !_Universe->isPlayerStarship( un ) ) && ( switch_nonowned_units || (par != NULL && un->owner == par->owner) || (par != NULL && un == par->owner) || (par != NULL && un->owner == par) || (par == NULL && un->owner) ) && (un->name != "eject") && (un->name != "Pilot") && (un->isUnit() != MISSILEPTR) ) { found = true; ++index; Unit *k = GetParent(); bool proceed = true; if (k) if (k->name == "eject" || k->name == "Pilot" || k->name == "return_to_cockpit") proceed = false; //we are an ejected pilot, so, if we can get close enough to the related unit, jump into it and remove the seat. This said, always allow //switching from the "fake" ejection seat (ejectdock). if ( !proceed && k && ( k->Position()-un->Position() ).Magnitude() < ( un->rSize()+5*k->rSize() ) ) { if ( !(k->name == "return_to_cockpit") ) SwitchUnits( k, un ); //this refers to cockpit if ( !(k->name == "return_to_cockpit") ) this->SetParent( un, GetUnitFileName().c_str(), this->unitmodname.c_str(), savegame->GetPlayerLocation() ); if ( !(k->name == "return_to_cockpit") ) k->Kill(); //un->SetAI(new FireKeyboard ()) } if (proceed) { //k->PrimeOrdersLaunched(); //k->SetAI (new Orders::AggressiveAI ("interceptor.agg.xml")); //k->SetTurretAI(); //Flightgroup * fg = k->getFlightgroup(); //if (fg!=NULL) { // //un->SetFg (fg,fg->nr_ships++); //fg->nr_ships_left++; //fg->leader.SetUnit(un); //fg->directive="b"; //} SwitchUnits( k, un ); this->SetParent( un, GetUnitFileName().c_str(), this->unitmodname.c_str(), savegame->GetPlayerLocation() ); //un->SetAI(new FireKeyboard ()) } break; } } if (!found) index = 0; } } //this causes the physical ejecting. Check going_to_dock_screen in here, also. if (ejecting) { ejecting = false; //going_to_dock_screen=true; // NO, clear this only after we've UNDOCKED that way we know we don't have issues. Unit *un = GetParent(); if (un) { if (going_to_dock_screen == false) un->EjectCargo( (unsigned int) -1 ); if (going_to_dock_screen == true) { un->EjectCargo( (unsigned int) -2 ); going_to_dock_screen = false; } } } if (!par) { if ( respawnunit.size() > _Universe->CurrentCockpit() ) { if (respawnunit[_Universe->CurrentCockpit()]) { static float initialzoom = XMLSupport::parse_float( vs_config->getVariable( "graphics", "inital_zoom_factor", "2.25" ) ); zoomfactor = initialzoom; if (Network != NULL) { Network[_Universe->CurrentCockpit()].respawnRequest(); respawnunit[_Universe->CurrentCockpit()] = 0; } else { parentturret.SetUnit( NULL ); respawnunit[_Universe->CurrentCockpit()] = 0; std::string savegamefile = mission->getVariable( "savegame", "" ); unsigned int k; for (k = 0; k < _Universe->numPlayers(); ++k) if (_Universe->AccessCockpit( k ) == this) break; if ( k == _Universe->numPlayers() ) k = 0; if (active_missions.size() > 1) { for (int i = active_missions.size()-1; i > 0; --i) //don't terminate zeroth mission if (active_missions[i]->player_num == k) active_missions[i]->terminateMission(); } unsigned int whichcp = k; string newsystem; QVector pos; bool setplayerXloc; savegame->SetStarSystem( "" ); QVector tmpoldpos = savegame->GetPlayerLocation(); savegame->SetPlayerLocation( QVector( FLT_MAX, FLT_MAX, FLT_MAX ) ); vector< string > packedInfo; savegame->ParseSaveGame( savegamefile, newsystem, newsystem, pos, setplayerXloc, this->credits, packedInfo, k ); UnpackUnitInfo(packedInfo); if (pos.i == FLT_MAX && pos.j == FLT_MAX && pos.k == FLT_MAX) pos = tmpoldpos; savegame->SetPlayerLocation( pos ); CopySavedShips( savegame->GetCallsign(), whichcp, packedInfo, true ); bool actually_have_save = false; static bool persistent_on_load = XMLSupport::parse_bool( vs_config->getVariable( "physics", "persistent_on_load", "true" ) ); if (savegame->GetStarSystem() != "") { actually_have_save = true; newsystem = savegame->GetStarSystem()+".system"; } else { newsystem = _Universe->activeStarSystem()->getFileName(); if (newsystem.find( ".system" ) == string::npos) newsystem += ".system"; } Background::BackgroundClone savedtextures = { {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }; if (persistent_on_load) { _Universe->getActiveStarSystem( 0 )->SwapOut(); } else { Background *tmp = _Universe->activeStarSystem()->getBackground(); savedtextures = tmp->Cache(); _Universe->clearAllSystems(); } StarSystem *ss = _Universe->GenerateStarSystem( newsystem.c_str(), "", Vector( 0, 0, 0 ) ); if (!persistent_on_load) savedtextures.FreeClone(); this->activeStarSystem = ss; _Universe->pushActiveStarSystem( ss ); vector< StarSystem* >saved; while ( _Universe->getNumActiveStarSystem() ) { saved.push_back( _Universe->activeStarSystem() ); _Universe->popActiveStarSystem(); } if ( !saved.empty() ) saved.back() = ss; unsigned int mysize = saved.size(); for (unsigned int i = 0; i < mysize; i++) { _Universe->pushActiveStarSystem( saved.back() ); saved.pop_back(); } ss->SwapIn(); int fgsnumber = 0; if (fg) { fgsnumber = fg->flightgroup_nr++; fg->nr_ships++; fg->nr_ships_left++; } Unit *un = UnitFactory::createUnit( GetUnitFileName().c_str(), false, this->unitfaction, unitmodname, fg, fgsnumber ); un->SetCurPosition( UniverseUtil::SafeEntrancePoint( savegame->GetPlayerLocation() ) ); ss->AddUnit( un ); this->SetParent( un, GetUnitFileName().c_str(), unitmodname.c_str(), savegame->GetPlayerLocation() ); SwitchUnits( NULL, un ); this->credits = savegame->GetSavedCredits(); DoCockpitKeys(); _Universe->popActiveStarSystem(); _Universe->pushActiveStarSystem( ss ); savegame->ReloadPickledData(); savegame->LoadSavedMissions(); if (actually_have_save && !SERVER && Network == NULL) { QVector vec; DockToSavedBases( whichcp, vec ); } UniverseUtil::hideSplashScreen(); _Universe->popActiveStarSystem(); if (!persistent_on_load) _Universe->pushActiveStarSystem( ss ); return true; } } } } return false; }