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;
    }
}
Example #10
0
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;
}
Example #11
0
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;
}