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