Esempio n. 1
0
const char *FindCaseInsensitive ( const char *_fullPath )
{

    if ( !_fullPath )
        return NULL;

    static char retval[PATH_MAX];
    char *dir = NULL, *file = NULL;

    if ( (dir = GetDirectoryPart(_fullPath)) != NULL )
    {
        // Make our own copy of the result, since GetDirectoryPart
        // and GetFilenamePart use the same variable for temp
        // storage.
        dir = newStr(dir);
    }
    if ( !dir )
    {
        // No directory provided. Assume working directory.
        file = newStr(_fullPath);
    } else {
        // Kill the last slash
        dir[strlen(dir) - 1] = '\0';
        file = newStr(GetFilenamePart(_fullPath));
    }
    LList <char *> *files = ListDirectory(dir, file);

    delete [] dir; delete [] file; dir = file = NULL;

    // We shouldn't have found more than one match.
    AppAssert(files->Size() <= 1);

    // No results, so maybe the file does not exist.
    if ( files->Size() == 0 )
       return _fullPath;

    // Copy the corrected path back, and prepare to return it.
    memset ( retval, 0, sizeof ( retval ) );
    AppAssert ( strlen ( files->GetData(0) ) < PATH_MAX );
    strcpy ( retval, files->GetData(0) );

    // Negate the possibility of a memory access violation.
    // This way, we can simply strcpy the result inline without
    // worrying about a buffer overflow.
    AppAssert(strlen(retval) == strlen(_fullPath));

    while ( files->Size() )
	{
		char *data = files->GetData(0);
		files->RemoveData(0);
		delete [] data;
	}

    delete files;

    return retval;
}
void EclRender ()
{

    bool maximiseRender = false;

    //
    // Render any maximised Window?

    if( strcmp( maximisedWindow, "None" ) != 0 )
    {
        EclWindow *maximised = EclGetWindow( maximisedWindow );
        if( maximised )
        {
            clearDraw ( maximised->m_x, maximised->m_y, maximised->m_w, maximised->m_h );
            maximised->Render( true );
            maximiseRender = true;
        }
        else
        {
            EclUnMaximise();
        }
    }

    if( !maximiseRender )
    {

        //
        // Clear all dirty rectangle areas

        if ( clearDraw )
        {
            for( int i = 0; i < dirtyrects.Size(); ++i )
            {
                DirtyRect *dr = dirtyrects.GetData(i);
                clearDraw ( dr->m_x, dr->m_y, dr->m_width, dr->m_height );
            }
        }

        //
        // Draw all dirty buttons

        for ( int i = windows.Size() - 1; i >= 0; --i )
        {
            EclWindow *window = windows.GetData(i);
            if ( window->m_dirty ) {
                bool hasFocus = ( strcmp ( window->m_name, windowFocus ) == 0 );
                window->Render( hasFocus );
                //window->m_dirty = false;
            }
        }

    }

}
void EclResetDirtyRectangles ()
{
    while ( dirtyrects.GetData(0) )
    {
        DirtyRect *dr = dirtyrects.GetData(0);
        delete dr;
        dirtyrects.RemoveData(0);
    }    

    for ( int i = 0; i < windows.Size(); ++i )
    {
        EclWindow *window = windows.GetData(i);
        window->m_dirty = false;
    }
}
void LocationEditor::RenderModeCameraMount()
{
	RGBAColour bright(255,255,0);
	RGBAColour dim(90,90,0);

	LList <CameraAnimation*> *list = &g_app->m_location->m_levelFile->m_cameraAnimations;
	for (int i = 0; i < list->Size(); ++i)
	{
		CameraAnimation *anim = list->GetData(i);
		CamAnimNode *lastNode = anim->m_nodes.GetData(0);
		for (int j = 1; j < anim->m_nodes.Size(); ++j)
		{
			CamAnimNode *node = anim->m_nodes.GetData(j);
			if (stricmp(node->m_mountName, MAGIC_MOUNT_NAME_START_POS) == 0 ||
				stricmp(lastNode->m_mountName, MAGIC_MOUNT_NAME_START_POS) == 0)
			{
				continue;
			}

			CameraMount *mount1 = g_app->m_location->m_levelFile->GetCameraMount(lastNode->m_mountName);
			CameraMount *mount2 = g_app->m_location->m_levelFile->GetCameraMount(node->m_mountName);
			if (i == m_selectionId)
			{
				RenderArrow(mount1->m_pos, mount2->m_pos, 1.0, bright);
			}
			else
			{
				RenderArrow(mount1->m_pos, mount2->m_pos, 1.0, dim);
			}

			lastNode = node;
		}
	}
}
int	LocationEditor::IsPosInLandTile(Vector3 const &pos)
{
	Landscape *land = &g_app->m_location->m_landscape;
	LList<LandscapeTile *> *tiles = &g_app->m_location->m_levelFile->m_landscape.m_tiles;
	int smallestId = -1;
	int smallestSize = INT_MAX;

	for (int i = 0; i < tiles->Size(); ++i)
	{
		LandscapeTile *tile = tiles->GetData(i);
		float worldX = tile->m_posX;
		float worldZ = tile->m_posZ;
		float sizeX = tile->m_size;
		float sizeZ = tile->m_size;
		if (pos.x > worldX &&
			pos.x < worldX + sizeX &&
			pos.z > worldZ &&
			pos.z < worldZ + sizeZ) 
		{
			if (tile->m_size < smallestSize)
			{
				smallestId = i;
				smallestSize = tile->m_size;
			}
		}
	}

	return smallestId;
}
void Officer::SetWaypoint( Vector3 const &_wayPoint )
{
		m_wayPoint = _wayPoint;
		m_state = StateToWaypoint;

        //
        // If we clicked near a teleport, tell the officer to go into it
        m_wayPointTeleportId = -1;
        LList<int> *nearbyBuildings = g_app->m_location->m_obstructionGrid->GetBuildings( _wayPoint.x, _wayPoint.z );
        for( int i = 0; i < nearbyBuildings->Size(); ++i )
        {
            int buildingId = nearbyBuildings->GetData(i);
            Building *building = g_app->m_location->GetBuilding( buildingId );
            if( building->m_type == Building::TypeRadarDish ||
                building->m_type == Building::TypeBridge )
            {
                float distance = ( building->m_pos - _wayPoint ).Mag();
                Teleport *teleport = (Teleport *) building;
                if( distance < 5.0f && teleport->Connected() )
                {
                    m_wayPointTeleportId = building->m_id.GetUniqueId();
                    Vector3 entrancePos, entranceFront;
                    teleport->GetEntrance( entrancePos, entranceFront );
                    m_wayPoint = entrancePos;
                    break;
                }
            }
        }
}
Esempio n. 7
0
void EclRemoveWindow ( char *name )
{
    
    int index = EclGetWindowIndex(name);
    if ( index != -1 )
    {
    
        EclWindow *window = windows.GetData(index);

        if( strcmp( mouseDownWindow, name ) == 0 )
        {
            strcpy( mouseDownWindow, "None" );
        }

        if( strcmp( windowFocus, name ) == 0 )
        {
            strcpy( windowFocus, "None" );
        }

        window->Remove();

        windows.RemoveData(index);
        delete window;
    }
    else
    {
        AppDebugOut( "EclRemoveWindow failed on window %s\n", name );
    }
    
}
void EclRemoveWindow ( char *name )
{
    
    int index = EclGetWindowIndex(name);
    if ( index != -1 )
    {
    
        EclWindow *window = windows.GetData(index);
        EclDirtyRectangle ( window->m_x, window->m_y, window->m_w, window->m_h );
        windows.RemoveData(index);

        if( strcmp( mouseDownWindow, name ) == 0 )
        {
            strcpy( mouseDownWindow, "None" );
        }

        if( strcmp( windowFocus, name ) == 0 )
        {
            strcpy( windowFocus, "None" );
        }
		
		delete window;
    }
    else
    {
    }
    
}
void NewsScreenInterface::ClickNewsButton ( Button *button )
{

	int index;
	sscanf ( button->name, "news_story %d", &index );

	index += baseoffset;

	// Dirty the old button

	char oldname [128];
	UplinkSnprintf ( oldname, sizeof ( oldname ), "news_story %d", currentselect - baseoffset );
	EclDirtyButton ( oldname );

	CompanyUplink *cu = (CompanyUplink *) game->GetWorld ()->GetCompany ( "Uplink" );
	UplinkAssert ( cu );

	if ( cu->GetNews (index) ) {

		currentselect = index;
        
	    // Reset the offset so the player can read it from line 1
        ScrollBox *scrollBox = ScrollBox::GetScrollBox( "news_details" );
        if ( scrollBox ) {
            scrollBox->SetCurrentIndex( 0 );

            char *newDetails = cu->GetNews (index)->GetDetails();
            Button *detailsButton = EclGetButton ( "news_details box" );
            UplinkAssert (detailsButton);
        	LList <char *> *wrappedtext = wordwraptext ( newDetails, detailsButton->width );
			if ( wrappedtext ) {
				scrollBox->SetNumItems( wrappedtext->Size() );
				if ( wrappedtext->ValidIndex (0) && wrappedtext->GetData (0) )
					delete [] wrappedtext->GetData(0);
				delete wrappedtext;
			}
			else {
				scrollBox->SetNumItems( 0 );
			}
        }

		EclRegisterCaptionChange ( "news_details box", cu->GetNews (index)->GetDetails (), 2000 );

	}
	
}
void LanguageTable::LoadLanguages()
{
    //
    // Clear out all known languages

    m_languages.EmptyAndDelete();


    //
    // Explore the data/language directory, looking for languages

    LList<char *> *files = g_fileSystem->ListArchive( "data/language/", "*.txt", false );

    for( int i = 0; i < files->Size(); ++i )
    {
        char *thisFile = files->GetData(i);

        Language *lang = new Language();

		snprintf( lang->m_name, sizeof(lang->m_name), thisFile );
		lang->m_name[ sizeof(lang->m_name) - 1 ] = '\0';
		for( char *curName = lang->m_name; *curName; curName++ )
		{
			if( *curName == '.' )
			{
				*curName = '\0';
				break;
			}
		}
		strcpy( lang->m_caption, lang->m_name );

        snprintf( lang->m_path, sizeof(lang->m_path), "data/language/%s", thisFile );
		lang->m_path[ sizeof(lang->m_path) - 1 ] = '\0';

        LoadLanguageCaption( lang );

		if( m_onlyDefaultLanguageSelectable && stricmp( m_defaultLanguage, lang->m_name ) != 0 )
		{
			lang->m_selectable = false;
		}
		else
		{
			lang->m_selectable = true;
		}

        m_languages.PutData( lang );

        AppDebugOut( "Found language '%s' with caption '%s' in '%s'\n", 
                     lang->m_name, 
                     lang->m_caption, 
                     lang->m_path );
    }

    files->EmptyAndDelete();
    delete files;
}
Esempio n. 11
0
void EclRender ()
{

    bool maximiseRender = false;

    //
    // Render any maximised Window?

    if( strcmp( maximisedWindow, "None" ) != 0 )
    {
        EclWindow *maximised = EclGetWindow( maximisedWindow );
        if( maximised )
        {
            maximised->Render( true );
            maximiseRender = true;
        }
        else
        {
            EclUnMaximise();
        }
    }

    if( !maximiseRender )
    {
        for ( int i = windows.Size() - 1; i >= 0; --i )
        {
            EclWindow *window = windows.GetData(i);
            bool hasFocus = ( strcmp ( window->m_name, windowFocus ) == 0 );
            
            START_PROFILE( window->m_name );
            window->Render( hasFocus );
            END_PROFILE( window->m_name );
        }
    }


    //
    // Render the tooltip

    if( tooltipTimer > 0.0f && tooltipCallback )
    {
        EclWindow *window = EclGetWindow();
        if( window )
        {
            EclButton *button = window->GetButton( EclGetCurrentButton() );
            {
                if( button )
                {
                    float timer = GetHighResTime() - tooltipTimer;
                    tooltipCallback( window, button, timer );
                }
            }
        }
    }
}
int EclGetWindowIndex ( char *name )
{
    for ( int i = 0; i < windows.Size(); ++i )
    {
        EclWindow *window = windows.GetData(i);
        if ( strcmp ( window->m_name, name ) == 0 )
            return i;
    }

    return -1;
}
int Entity::EnterTeleports( int _requiredId )
{
    LList<int> *buildings = g_app->m_location->m_obstructionGrid->GetBuildings( m_pos.x, m_pos.z );
    
    for( int i = 0; i < buildings->Size(); ++i )
    {
        int buildingId = buildings->GetData(i);
        if( _requiredId != -1 && _requiredId != buildingId )
        {
            // We are only permitted to enter building with id _requiredId
            continue;
        }

        Building *building = g_app->m_location->GetBuilding( buildingId );
        AppDebugAssert( building );
        
        if( building->m_type == Building::TypeRadarDish  )
        {
            RadarDish *radarDish = (RadarDish *) building;
            Vector3 entrancePos, entranceFront;
            radarDish->GetEntrance( entrancePos, entranceFront );
            double range = ( m_pos - entrancePos ).Mag();
            if( radarDish->ReadyToSend() &&                             
                range < 15.0 &&
                m_front * entranceFront < 0.0 )
            {
                WorldObjectId id(m_id);
                radarDish->EnterTeleport( id );
                g_app->m_soundSystem->TriggerEntityEvent( this, "EnterTeleport" );
                return buildingId;
            }
        }
        else if( building->m_type == Building::TypeBridge )
        {
            Bridge *bridge = (Bridge *) building;
            Vector3 entrancePos, entranceFront;
            if( bridge->GetEntrance( entrancePos, entranceFront ) )
            {
                double range = ( m_pos - bridge->m_pos ).Mag();
                if( bridge->ReadyToSend() &&
                    range < 25.0 &&
                    m_front * entranceFront < 0.0 )
                {
                    WorldObjectId id( m_id );
                    bridge->EnterTeleport( id );
                    g_app->m_soundSystem->TriggerEntityEvent( this, "EnterTeleport" );
                    return buildingId;
                }
            }
        }        
    }

    return -1;
}
void EclDirtyRectangle ( int x, int y, int w, int h )
{
    DirtyRect *dr = new DirtyRect(x, y, w, h);
    dirtyrects.PutData( dr );

    for ( int i = 0; i < windows.Size(); ++i )
    {
        EclWindow *window = windows.GetData(i);
        if ( EclRectangleOverlap( x, y, w, h, window->m_x, window->m_y, window->m_w, window->m_h ) )
            EclDirtyWindow ( window );
    }
}
Esempio n. 15
0
void EclUpdate ()
{

    //
    // Update all windows

    for ( int i = 0; i < windows.Size(); ++i )
    {
        EclWindow *window = windows.GetData(i);
        window->Update();
    }

}
Esempio n. 16
0
void FileSystem::ParseArchives( const char *_dir, const char *_filter )
{
    LList<char *> *results = ListDirectory( _dir, _filter, false );
    for( int i = 0; i < results->Size(); ++i )
    {
        char fullFilename[512];
        snprintf( fullFilename, sizeof(fullFilename), "%s%s", _dir, results->GetData( i ) );
        fullFilename[ sizeof(fullFilename) - 1 ] = '\0';
        ParseArchive( fullFilename );
    }
    results->EmptyAndDelete();
    delete results;
}
Esempio n. 17
0
EclWindow *EclGetWindow ( char *name )
{
    
    int index = EclGetWindowIndex (name);
    if ( index == -1 )
    {
        return NULL;
    }
    else
    {
        return windows.GetData(index);
    }

}
Esempio n. 18
0
EclWindow *EclGetWindow ( int x, int y )
{

    for ( int i = 0; i < windows.Size(); ++i )
    {
        EclWindow *window = windows.GetData(i);
        if ( x >= window->m_x && x <= window->m_x + window->m_w &&
             y >= window->m_y && y <= window->m_y + window->m_h )
        {
            return window;
        }
    }

    return NULL;
}
void EclBringWindowToFront ( char *name )
{

    int index = EclGetWindowIndex(name);
    if ( index != -1 )
    {
        EclWindow *window = windows.GetData(index);
        windows.RemoveData(index);
        windows.PutDataAtStart(window);
        EclDirtyWindow( window );
    }
    else
    {
    }

}
Esempio n. 20
0
void EclBringWindowToFront ( char *name )
{

    int index = EclGetWindowIndex(name);
    if ( index != -1 )
    {
        EclWindow *window = windows.GetData(index);
        windows.RemoveData(index);
        windows.PutDataAtStart(window);
    }
    else
    {
        AppDebugOut( "EclBringWindowToFront failed on window %s\n", name );
    }

}
void GameMenu::CreateMenu()
{
    g_app->m_renderer->StartFadeIn(0.25f);
    // close all currently open windows
    LList<EclWindow *> *windows = EclGetWindows();
	while (windows->Size() > 0) {
		EclWindow *w = windows->GetData(0);
		EclRemoveWindow(w->m_name);
	}

    // create the actual menu window
    EclRegisterWindow( new GameMenuWindow() );

    // set the camera to a position with a good view of the internet
    g_app->m_camera->RequestMode(Camera::ModeMainMenu);
    g_app->m_camera->SetDebugMode(Camera::DebugModeNever);
    g_app->m_camera->SetTarget(Vector3(-900000, 3000000, 397000), Vector3(0,0.5f,-1));
    g_app->m_camera->CutToTarget();

    if( g_app->m_tutorial )
    {
        // its possible that the player has loaded the prologue, then returned to the main menu
        // if so, delete the tutorial
        delete g_app->m_tutorial;
        g_app->m_tutorial = NULL;
    }

    if( g_app->m_demoEndSequence )
    {
        delete g_app->m_demoEndSequence;
        g_app->m_demoEndSequence = NULL;
    }

    /*if( g_app->m_multiwinia )
    {
        delete g_app->m_multiwinia;
        g_app->m_multiwinia = NULL;
    }*/

    g_app->m_gameMode = App::GameModeNone;

    m_menuCreated = true;
}
void LocationEditor::RenderModeLandFlat()
{
	Vector3 mousePos3D = g_app->m_userInput->GetMousePos3d();
	Landscape *land = &g_app->m_location->m_landscape;

	// Highlight any flatten area under our mouse cursor
	LList<LandscapeFlattenArea *> *areas = &g_app->m_location->m_levelFile->m_landscape.m_flattenAreas;
	for (int i = 0; i < areas->Size(); ++i)
	{
		if (i == m_selectionId) continue;

		LandscapeFlattenArea *area = areas->GetData(i);
		float worldX = area->m_centre.x;
		float worldZ = area->m_centre.z;
		float sizeX = area->m_size;
		float sizeY = area->m_centre.y;
		float sizeZ = area->m_size;
		float x = area->m_centre.x;
		float y = area->m_centre.y;
		float z = area->m_centre.z;
		float s = area->m_size * 2.0;
		Vector3 centre(x, y, z);

		RenderCube(centre, s, y + 20, s, RGBAColour(128,255,128,99));
	}

	if (m_selectionId != -1)
	{
		LandscapeDef *landscapeDef = &(g_app->m_location->m_levelFile->m_landscape);
		LandscapeFlattenArea *areaDef = g_app->m_location->m_levelFile->m_landscape.m_flattenAreas.GetData(m_selectionId);
		float x = areaDef->m_centre.x;
		float y = areaDef->m_centre.y;
		float z = areaDef->m_centre.z;
		float s = areaDef->m_size * 2.0;
		Vector3 centre(x, y, z);

		RenderCube(centre, s, y + 20, s, RGBAColour(128,255,128,255));
	}
	
	CHECK_OPENGL_STATE();
}
Esempio n. 23
0
const char *FindCaseInsensitive( char *_fullPath )
{
    AppAssert(strlen(_fullPath) < PATH_MAX);
    
    static char pathSoFar[PATH_MAX];
    pathSoFar[0] = '\0';
    
    while (true) {
        char *delimiter;
        
        // Skip to the next / or end-of-string
        for (delimiter = (char *)_fullPath; *delimiter && *delimiter != '/'; delimiter++);
        
        char component[PATH_MAX];
        AppAssert ( strlen(_fullPath) < PATH_MAX );
        strcpy( component, _fullPath );
        component[delimiter - _fullPath] = '\0';
    
        // Search for a match
        LList<char *> *matches = ListDirectory( pathSoFar, component, true );
        bool found = false;
    
        if (matches->Size() > 0) {
            strcpy(pathSoFar, matches->GetData( 0 ));
            found = true;
        }
    
        matches->EmptyAndDelete();
    
        // Failed to find a match, just return the original
        if (!found)
            return _fullPath;
        
        // Got to the end of the path, return it
        if (!*delimiter) 
            return pathSoFar;
        
        _fullPath = delimiter + 1;
    }
}
int	LocationEditor::IsPosInFlattenArea(Vector3 const &pos)
{
	LList<LandscapeFlattenArea *> *areas = &g_app->m_location->m_levelFile->m_landscape.m_flattenAreas;
	Landscape *land = &g_app->m_location->m_landscape;

	for (int i = 0; i < areas->Size(); ++i)
	{
		LandscapeFlattenArea *area = areas->GetData(i);
		float halfSize = area->m_size;
		float size = halfSize * 2.0;
		float worldX = area->m_centre.x - halfSize;
		float worldZ = area->m_centre.z - halfSize;
		if (pos.x > worldX &&
			pos.x < worldX + size &&
			pos.z > worldZ &&
			pos.z < worldZ + size) 
		{
			return i;
		}
	}

	return -1;
}
void ParseMemoryLeakFile ( char *_inputFilename, char *_outputFilename )
{

    //
    // Start up
    //

    BTree <int> combined;
    BTree <int> frequency;
    int unrecognised = 0;

    //
    // Open the file and start parsing
    //

    ifstream memoryfile ( _inputFilename );

    while ( !memoryfile.eof () ) 
    {
        char thisline [256];
        memoryfile.getline ( thisline, 256 );

        if ( !strncmp ( thisline, " Data:", 6 ) == 0 &&         // This line is a data line - useless to us
              strchr ( thisline, ':' ) ) {                      // This line does not have a source file location - useless to us

            // Get the size

            char *lastcomma = strrchr ( thisline, ',' );
            char *ssize = lastcomma+2;
            int size;
            char unused [32];
            sscanf ( ssize, "%d %s", &size, unused );

            // Get the source file name

            char *sourcelocation = thisline;
            char *colon = strrchr ( thisline, ':' );
            *(colon-1) = '\x0';
            char *lowercasesourcelocation = LowerCaseString ( sourcelocation );
            
            // Put the result into our BTree

            BTree <int> *btree = combined.LookupTree ( lowercasesourcelocation );
            if ( btree ) ((int) btree->data) += size;
            else combined.PutData ( lowercasesourcelocation, size );
            
            BTree <int> *freq = frequency.LookupTree ( lowercasesourcelocation );
            if ( freq ) ((int) freq->data) ++;
            else frequency.PutData ( lowercasesourcelocation, 1 );

            delete lowercasesourcelocation;
        }
        else 
        {
            char *lastcomma = strrchr ( thisline, ',' );
            
            if ( lastcomma ) 
            {

                char *ssize = lastcomma+2;
                int size;
                char unused [32];
                if( sscanf ( ssize, "%d %s", &size, unused ) == 2 )
	                unrecognised += size;
            }
        }
    }

    memoryfile.close ();

    
    //
    // Sort the results into a list
    //

    DArray <int> *sizes = combined.ConvertToDArray ();
    DArray <char *> *sources = combined.ConvertIndexToDArray ();
    LList <char *> sorted;
    int totalsize = 0;

    for ( int i = 0; i < sources->Size (); ++i )
    {
        char *newsource = sources->GetData (i);
        int newsize = sizes->GetData (i);
        totalsize += newsize;
        bool inserted = false;

        for ( int j = 0; j < sorted.Size (); ++j ) {

            char *existingsource = sorted.GetData (j);
            int existingsize = combined.GetData ( existingsource );

            if ( newsize <= existingsize ) {

                sorted.PutDataAtIndex ( newsource, j );
                inserted = true;
                break;

            }

        }

        if ( !inserted ) sorted.PutDataAtEnd ( newsource );
    }


    //
    // Open the output file
    //

    FILE *output = fopen( _outputFilename, "wt" );

    //
    // Print out our sorted list
    // 

    fprintf ( output, "Total recognised memory leaks   : %d Kbytes\n", int(totalsize/1024)  );
    fprintf ( output, "Total unrecognised memory leaks : %d Kbytes\n\n", int(unrecognised/1024) );
    
    for ( int k = sorted.Size () - 1; k >= 0; --k ) 
    {

        char *source = sorted.GetData (k);
        int size = combined.GetData ( source );
        int freq = frequency.GetData ( source );

        if( size > 2048 )
        {
            fprintf ( output, "%-95s (%d Kbytes in %d leaks)\n", source, int(size/1024), freq );
        }
        else
        {
            fprintf ( output, "%-95s (%d  bytes in %d leaks)\n", source, size, freq );
        }
    }


    //
    // Clear up

    fclose( output );

    delete sources;
    delete sizes;
}
void LocationEditor::AdvanceModeLandTile()
{
	Vector3 mousePos3D = g_app->m_userInput->GetMousePos3d();

	int newSelectionId = -1;
	if ( g_inputManager->controlEvent( ControlTileSelect ) )
	{
		newSelectionId = IsPosInLandTile(mousePos3D);
	}

	if (m_selectionId == -1)
	{
		// No selection

		Landscape *land = &g_app->m_location->m_landscape;
		LList<LandscapeTile *> *tiles = &g_app->m_location->m_levelFile->m_landscape.m_tiles;
		
		// Has the user selected a tile
		if (newSelectionId != -1) 
		{
			LandscapeTile *tile = tiles->GetData(newSelectionId);
			m_tool = ToolMove;
			m_selectionId = newSelectionId;
			m_newLandscapeX = tile->m_posX;
			m_newLandscapeZ = tile->m_posZ;
			m_waitingForRelease = true;

			EclWindow *cw = EclGetWindow("editor_landscape");
			AppDebugAssert(cw);
			LandscapeTileEditWindow *ew = new LandscapeTileEditWindow("editor_landscapetile", newSelectionId);
			ew->m_w = cw->m_w;
			ew->m_h = 150;
			ew->m_x = cw->m_x;
			EclRegisterWindow(ew);
			ew->m_y = cw->m_y - ew->m_h - 10;
		}
	}
	
	if (m_selectionId != -1)
	{
		// There is a current selection

		if( g_inputManager->controlEvent( ControlTileDrop ) )
		{
			// Move the selected landscape to the new position and regenerate it
			LandscapeTile *tileDef = g_app->m_location->m_levelFile->m_landscape.m_tiles.GetData(m_selectionId);
			if( m_newLandscapeX != tileDef->m_posX ||
				m_newLandscapeZ != tileDef->m_posZ )
			{
                if( m_moveBuildingsWithLandscape )
                {
                    MoveBuildingsInTile( tileDef, m_newLandscapeX - tileDef->m_posX, m_newLandscapeZ - tileDef->m_posZ );
                }

				tileDef->m_posX = m_newLandscapeX;
				tileDef->m_posZ = m_newLandscapeZ;
				LandscapeDef *def = &g_app->m_location->m_levelFile->m_landscape;
				g_app->m_location->m_landscape.Init(def);
                delete g_app->m_location->m_water;
                g_app->m_location->m_water = new Water();
			}
		}
		if( g_inputManager->controlEvent( ControlTileSelect ) ) // TODO: Should this be ControlTileGrab?
		{
			if (newSelectionId == m_selectionId)
			{
				// The user "grabs" the landscape at this position
				LandscapeDef *landscapeDef = &(g_app->m_location->m_levelFile->m_landscape);
				LandscapeTile *tileDef = g_app->m_location->m_levelFile->m_landscape.m_tiles.GetData(m_selectionId);
				m_landscapeGrabX = mousePos3D.x - tileDef->m_posX;
				m_landscapeGrabZ = mousePos3D.z - tileDef->m_posZ;
			}
			else
			{
				// The user has deselected the landscape
				m_tool = ToolNone;
				m_selectionId = -1;
				m_waitingForRelease = true;
				EclRemoveWindow("editor_landscapetile");
                EclRemoveWindow("editor_guidegrid");
			}
		}
		else if ( g_inputManager->controlEvent( ControlTileDrag ) )
		{
			// The user "drags" the landscape around
			m_newLandscapeX = mousePos3D.x - m_landscapeGrabX;
			m_newLandscapeZ = mousePos3D.z - m_landscapeGrabZ;        
		}
	}
}
void LocationEditor::RenderModeLandTile()
{
	Vector3 mousePos3D = g_app->m_userInput->GetMousePos3d();
	Landscape *land = &g_app->m_location->m_landscape;

	// Highlight any tile under our mouse cursor
	LList<LandscapeTile *> *tiles = &g_app->m_location->m_levelFile->m_landscape.m_tiles;
	for (int i = 0; i < tiles->Size(); ++i)
	{
		if (i == m_selectionId) continue;

		LandscapeTile *tile = tiles->GetData(i);
		float worldX = tile->m_posX - tile->m_heightMap->m_cellSizeX;
		float worldZ = tile->m_posZ - tile->m_heightMap->m_cellSizeY;
		float sizeX = tile->m_size;
		float sizeY = tile->m_desiredHeight - tile->m_outsideHeight;
		float sizeZ = tile->m_size;
		if (mousePos3D.x > worldX &&
			mousePos3D.x < worldX + sizeX &&
			mousePos3D.z > worldZ &&
			mousePos3D.z < worldZ + sizeZ) 
		{
			Vector3 centre(worldX, tile->m_outsideHeight, worldZ);
			centre.x += sizeX * 0.5;
			centre.y += sizeY * 0.5;
			centre.z += sizeZ * 0.5;
			RenderCube(centre, sizeX, sizeY, sizeZ, RGBAColour(128,255,128,99));
		}
	}

    // Render guide grids

    if( EclGetWindow("editor_guidegrid") )
    {
        glEnable( GL_LINE_SMOOTH );
        glEnable( GL_BLEND );

	    if (m_selectionId != -1)
	    {
            LandscapeTile *tile = tiles->GetData(m_selectionId);

            if( tile->m_guideGrid &&
                tile->m_guideGrid->GetNumColumns() > 0 )
            {
                float gridCellSize = tile->m_size / (float) (tile->m_guideGrid->GetNumColumns()+1);
                for( int x = 0; x < tile->m_guideGrid->GetNumColumns()-1; ++x )
                {
                    for( int z = 0; z < tile->m_guideGrid->GetNumColumns()-1; ++z )
                    {                    
                        float value1 = tile->m_desiredHeight * (tile->m_guideGrid->GetData( x, z ) / 256.0);
                        float value2 = tile->m_desiredHeight * (tile->m_guideGrid->GetData( x+1, z ) / 256.0 );
                        float value3 = tile->m_desiredHeight * (tile->m_guideGrid->GetData( x+1, z+1 ) / 256.0 );
                        float value4 = tile->m_desiredHeight * (tile->m_guideGrid->GetData( x, z+1 ) / 256.0 );
                 
                        float tileX = tile->m_posX + (x+1) * gridCellSize;
                        float tileZ = tile->m_posZ + (z+1) * gridCellSize;
                        float tileW = gridCellSize;
                        float tileH = gridCellSize;

                        glDisable( GL_DEPTH_TEST );
                        glLineWidth( 1.0 );
                        glColor4f( 1.0, 0.0, 0.0, 0.2 );
                        glBegin( GL_LINE_LOOP );
                            glVertex3f( tileX, tile->m_posY + value1, tileZ );
                            glVertex3f( tileX + tileW, tile->m_posY + value2, tileZ );
                            glVertex3f( tileX + tileW, tile->m_posY + value3, tileZ + tileH );
                            glVertex3f( tileX, tile->m_posY + value4, tileZ + tileH );
                        glEnd();

                        glEnable( GL_DEPTH_TEST );
                        glColor4f( 1.0, 0.0, 0.0, 0.8 );
                        glLineWidth( 3.0 );
                        glBegin( GL_LINE_LOOP );
                            glVertex3f( tileX, tile->m_posY + value1, tileZ );
                            glVertex3f( tileX + tileW, tile->m_posY + value2, tileZ );
                            glVertex3f( tileX + tileW, tile->m_posY + value3, tileZ + tileH );
                            glVertex3f( tileX, tile->m_posY + value4, tileZ + tileH );
                        glEnd();

                    }
                }
            }
        }

        glDisable( GL_BLEND );
        glEnable( GL_DEPTH_TEST );
    }

    
	// Render a green box around the currently selected tile (if any)
	if (m_selectionId != -1)
	{
        LandscapeTile *tile = tiles->GetData(m_selectionId);
        float x = tile->m_posX - tile->m_heightMap->m_cellSizeX;
        float y = tile->m_outsideHeight;
        float z = tile->m_posZ - tile->m_heightMap->m_cellSizeY;
        float sX = tile->m_size;
        float sY = tile->m_desiredHeight - tile->m_outsideHeight;
		float sZ = tile->m_size;
		Vector3 centre(x, y, z);
		centre.x += sX * 0.5;
		centre.y += sY * 0.5;
		centre.z += sZ * 0.5;
		RenderCube(centre, sX, sY, sZ, RGBAColour(128,255,128));

        if( m_newLandscapeX != tile->m_posX ||
            m_newLandscapeZ != tile->m_posZ )
        {
            x = m_newLandscapeX;
			y = 1.0;
            z = m_newLandscapeZ;
            glColor3ub( 0, 0, 255 );
            glBegin( GL_LINE_LOOP );
                glVertex3f( x, y, z );
                glVertex3f( x + sX, y, z );
                glVertex3f( x + sX, y, z + sZ );
                glVertex3f( x, y, z + sZ );
            glEnd();
        }
	}
    
	CHECK_OPENGL_STATE();
}
void NewsScreenInterface::DrawDetails ( Button *button, bool highlighted, bool clicked )
{

	UplinkAssert (button);

	int screenheight = app->GetOptions ()->GetOptionValue ( "graphics_screenheight" );
	glScissor ( button->x, screenheight - (button->y + button->height), button->width, button->height );	
	glEnable ( GL_SCISSOR_TEST );

	// Get the offset

	char name_base [128];
	sscanf ( button->name, "%s", name_base );
    ScrollBox *scrollBox = ScrollBox::GetScrollBox( name_base );
    if ( !scrollBox ) return;
    int offset = scrollBox->currentIndex;
	
	// Draw the button

	glBegin ( GL_QUADS );
		SetColour ( "PanelBackgroundA" );       glVertex2i ( button->x, button->y + button->height );
		SetColour ( "PanelBackgroundB" );       glVertex2i ( button->x, button->y );
		SetColour ( "PanelBackgroundA" );       glVertex2i ( button->x + button->width, button->y );
		SetColour ( "PanelBackgroundB" );       glVertex2i ( button->x + button->width, button->y + button->height );
	glEnd ();

	SetColour ( "PanelBorder" );
	border_draw ( button );


	// Draw the text

	int maxnumlines = (button->height - 10 ) / 15;

	SetColour ( "DefaultText" );

	LList <char *> *wrappedtext = wordwraptext ( button->caption, button->width );

	if ( wrappedtext ) {

		for ( int i = offset; i < wrappedtext->Size (); ++i ) {

			if ( i > maxnumlines + offset )
				break;

			int xpos = button->x + 10;
			int	ypos = button->y + 10 + (i-offset) * 15;

			GciDrawText ( xpos, ypos, wrappedtext->GetData (i), HELVETICA_10 );

		}

		//DeleteLListData ( wrappedtext );							// Only delete first entry - since there is only one string really
		if ( wrappedtext->ValidIndex (0) && wrappedtext->GetData (0) )
			delete [] wrappedtext->GetData (0);
		delete wrappedtext;

	}

	glDisable ( GL_SCISSOR_TEST );
	
}
Esempio n. 29
0
bool ProcessServerLetters( Directory *letter )
{
    if( strcmp( letter->m_name, NET_DEFCON_MESSAGE ) != 0 ||
        !letter->HasData( NET_DEFCON_COMMAND ) )
    { 
        AppDebugOut( "Client received bogus message, discarded (4)\n" );
        return true;
    }


    char *cmd = letter->GetDataString( NET_DEFCON_COMMAND );


    if( strcmp( cmd, NET_DEFCON_CLIENTHELLO ) == 0 )
    {
        int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID);
        if( clientId == g_app->GetClientToServer()->m_clientId )
        {
            g_app->GetClientToServer()->m_connectionState = ClientToServer::StateConnected;
            AppDebugOut( "CLIENT : Received HelloClient from Server\n" );
            if( !g_app->GetTutorial() )
            {
                g_app->GetClientToServer()->RequestTeam( Team::TypeLocalPlayer );
            }
        }

        // If this is a Demo client, make a note of that
        if( letter->HasData( NET_DEFCON_CLIENTISDEMO ) )
        {
            g_app->GetClientToServer()->SetClientDemo( clientId );
        }

        // This might be a client rejoining the game
        // Need to give him his teams back
        g_app->GetWorld()->ReassignTeams( clientId );        

        return true;
    }
    else if( strcmp( cmd, NET_DEFCON_CLIENTGOODBYE ) == 0 )
    {
        int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID);
        int reason = letter->GetDataInt(NET_DEFCON_DISCONNECT);

        AppDebugOut( "CLIENT : Client %d left the game\n", clientId );
        g_app->GetWorld()->RemoveTeams( clientId, reason );
        g_app->GetWorld()->RemoveSpectator( clientId );
        g_app->GetClientToServer()->SetSyncState( clientId, true );
        return true;
    }
    else if( strcmp( cmd, NET_DEFCON_CLIENTID ) == 0 )
    {
        int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID);        
        AppDebugOut( "CLIENT : Received ClientID of %d\n", clientId );        

        if( g_app->GetClientToServer()->m_clientId != -1 )
        {
            AppAssert( g_app->GetClientToServer()->m_clientId == clientId );
            return true;
        }

        g_app->GetClientToServer()->m_clientId = clientId;
        g_app->GetClientToServer()->m_connectionState = ClientToServer::StateHandshaking;
        g_lastProcessedSequenceId = -1;

        if( letter->HasData( NET_DEFCON_VERSION, DIRECTORY_TYPE_STRING ) )
        {
            char *serverVersion = letter->GetDataString( NET_DEFCON_VERSION );
            strcpy( g_app->GetClientToServer()->m_serverVersion, serverVersion );
            AppDebugOut( "CLIENT : Server version is %s\n", serverVersion );
        }

        if( !VersionManager::DoesSupportModSystem( g_app->GetClientToServer()->m_serverVersion ) )
        {
            // This server is too old to support Mods, so make sure we de-activate any critical ones
            g_modSystem->DeActivateAllCriticalMods();
            if( g_modSystem->CommitRequired() )
            {
                g_modSystem->Commit();
				g_app->RestartAmbienceMusic();
            }
        }

        return true;
    }
    else if( strcmp( cmd, NET_DEFCON_TEAMASSIGN ) == 0 )
    {
        int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID);        
        int teamId   = letter->GetDataInt(NET_DEFCON_TEAMID);
        int teamType = letter->GetDataInt(NET_DEFCON_TEAMTYPE);

        if( teamType != Team::TypeAI &&
            clientId != g_app->GetClientToServer()->m_clientId )
        {
            teamType = Team::TypeRemotePlayer;
        }

        g_app->GetWorld()->InitialiseTeam(teamId, teamType, clientId );
        return true;
    }
    else if( strcmp( cmd, NET_DEFCON_SPECTATORASSIGN ) == 0 )
    {
        int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID);        
        g_app->GetWorld()->InitialiseSpectator(clientId);

        if( clientId == g_app->GetClientToServer()->m_clientId )
        {            
            AppDebugOut( "CLIENT: I am a spectator\n" );
        }
				
        return true;
    }
    else if( strcmp( cmd, NET_DEFCON_NETSYNCERROR ) == 0 )
    {
        int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID);        
        AppDebugOut( "SYNCERROR Server informed us that Client %d is out of Sync\n", clientId );

        g_app->GetClientToServer()->SetSyncState( clientId, false );

        char *syncId = letter->GetDataString( NET_DEFCON_SYNCERRORID );
        DumpSyncLogs(syncId);

        return true;
    }
    else if( strcmp( cmd, NET_DEFCON_NETSYNCFIXED ) == 0 )
    {
        int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID);        
        AppDebugOut( "SYNCFIXED Server informed us that Client %d has repaired his Sync Error\n", clientId );
        g_app->GetClientToServer()->SetSyncState( clientId, true );
        return true;
    }
    else if( strcmp( cmd, NET_DEFCON_DISCONNECT ) == 0 )
    {
        if( g_app->GetClientToServer()->m_connectionState > ClientToServer::StateDisconnected )
        {
            g_app->ShutdownCurrentGame();
            if ( EclGetWindow("LOBBY") )
				EclRemoveWindow( "LOBBY" );
			if ( EclGetWindow("Comms Window") )
				EclRemoveWindow( "Comms Window" );
			if ( EclGetWindow("Preparing Game...") )
				EclRemoveWindow("Preparing Game..." );

            g_app->GetInterface()->OpenSetupWindows();

            char *reason;
			char *reasonLanguagePhrase;
            int reasonDisconnectInt = letter->GetDataInt(NET_DEFCON_DISCONNECT);
            switch( reasonDisconnectInt )
            {
                case Disconnect_ClientLeave:            reason = "You have left the game";
					                                    reasonLanguagePhrase = "dialog_disconnect_client_leave";         break;
                case Disconnect_ServerShutdown:         reason = "The server has shutdown";
					                                    reasonLanguagePhrase = "dialog_disconnect_server_shutdown";      break;
                case Disconnect_InvalidKey:             reason = "You are using an invalid key";
					                                    reasonLanguagePhrase = "dialog_disconnect_invalid_key";          break;
                case Disconnect_DuplicateKey:           reason = "You are using a duplicate key";
					                                    reasonLanguagePhrase = "dialog_disconnect_duplicate_key";        break;
                case Disconnect_KeyAuthFailed:          reason = "Key authentication failed";
					                                    reasonLanguagePhrase = "dialog_disconnect_key_auth_failed";      break;
                case Disconnect_BadPassword:            reason = "Invalid Password Entered";
					                                    reasonLanguagePhrase = "dialog_disconnect_bad_password";         break;
                case Disconnect_GameFull:               reason = "Game is already full";
					                                    reasonLanguagePhrase = "dialog_disconnect_game_full";            break;
                case Disconnect_KickedFromGame:         reason = "Kicked by the Server";
					                                    reasonLanguagePhrase = "dialog_disconnect_kicked_from_game";     break;
                case Disconnect_DemoFull:               reason = "Too many Demo Players already";
					                                    reasonLanguagePhrase = "dialog_disconnect_demo_full";            break;
				default:                                reason = "Unknown";
					                                    reasonLanguagePhrase = "dialog_disconnect_unknown";              break;
            }

            if( reasonDisconnectInt == Disconnect_KeyAuthFailed ||
                reasonDisconnectInt == Disconnect_InvalidKey ||
                reasonDisconnectInt == Disconnect_DuplicateKey )
            {
                char authKey[256];
				if( Authentication_IsKeyFound() )
				{
					Authentication_GetKey( authKey );
				}
				else
				{
					sprintf( authKey, LANGUAGEPHRASE("dialog_authkey_not_found") );
				}

                BadKeyWindow *badKey = new BadKeyWindow();

				sprintf( badKey->m_extraMessage, LANGUAGEPHRASE("dialog_auth_error") );
				LPREPLACESTRINGFLAG( 'E', LANGUAGEPHRASE(reasonLanguagePhrase), badKey->m_extraMessage );
				LPREPLACESTRINGFLAG( 'K', authKey, badKey->m_extraMessage );

				EclRegisterWindow(badKey);
            }
            else if( reasonDisconnectInt == Disconnect_DemoFull )
            {
                int maxGameSize;
                int maxDemoPlayers;
                bool allowDemoServers;
                g_app->GetClientToServer()->GetDemoLimitations( maxGameSize, maxDemoPlayers, allowDemoServers );
                BadKeyWindow *badKey = new BadKeyWindow();

                sprintf( badKey->m_extraMessage, LANGUAGEPHRASE("dialog_server_demo_restricted") );
                LPREPLACEINTEGERFLAG( 'N', maxDemoPlayers, badKey->m_extraMessage );

                badKey->m_offerDemo = false;
                EclRegisterWindow(badKey);                
            }
            else
            {
                MessageDialog *dialog = new MessageDialog( "Disconnected", reasonLanguagePhrase, true, "dialog_disconnected", true );
                EclRegisterWindow( dialog );
            }

            AppDebugOut( "CLIENT : Received Disconnect from server : %s\n", reason );

#ifdef TESTBED
            if( letter->GetDataInt(NET_DEFCON_DISCONNECT) == Disconnect_ServerShutdown )
            {
                RestartTestBed(1, "Client Disconnect");
            }
#endif

        }
        return true;            
    }
    else if( strcmp( cmd, NET_DEFCON_SETMODPATH ) == 0 )
    {
        char *modPath = letter->GetDataString( NET_DEFCON_SETMODPATH );
        AppDebugOut( "Server has set the MOD path: '%s'\n", modPath );
        
        if( !g_modSystem->IsCriticalModPathSet( modPath ) )
        {
            if( g_modSystem->CanSetModPath( modPath ) )
            {
                g_modSystem->DeActivateAllCriticalMods();
                g_modSystem->SetModPath( modPath );
            }
            else
            {
                char reason[8192];
                sprintf( reason, LANGUAGEPHRASE("dialog_error_mod_path_caption") );

                char modPathCopy[4096];
                strcpy( modPathCopy, modPath );
                LList<char *> *tokens = g_modSystem->ParseModPath( modPathCopy );

                for( int i = 0; i < tokens->Size(); i+=2 )
                {
                    char *modName = tokens->GetData(i);
                    char *version = tokens->GetData(i+1);

                    strcat( reason, modName );
                    strcat( reason, " " );
                    strcat( reason, version );

                    if( !g_modSystem->IsModInstalled( modName, version ) )
                    {
                        strcat( reason, "    " );
                        strcat( reason, LANGUAGEPHRASE("dialog_mod_not_installed") );
                    }
                    
                    strcat( reason, "\n" );
                }

                delete tokens;
                
                MessageDialog *dialog = new MessageDialog( "Error setting MOD path", reason, false, "dialog_error_mod_path_title", true );
                EclRegisterWindow( dialog );
            }
        }

        return true;
    }
    else
    {
        return false;
    }
}
void RocketStatusPanel::Render()
{
    //
    // Determine our rocket status

    EscapeRocket *rocket = GetMyRocket();
    if( !rocket ) return;

    Team *team = g_app->m_location->m_teams[ m_teamId ];
    if( !team ) return;

    float fuelPercent = rocket->m_fuel / 100.0f;
    int darwiniansInside = rocket->m_passengers;

    if( rocket->m_damage > m_lastDamage )
    {
        m_damageTimer = GetHighResTime();
    }
    m_lastDamage = rocket->m_damage;

    if( fuelPercent > 1.0f ) fuelPercent = 1.0f;

    double refuelRate = rocket->m_fuel - m_previousFuelLevel;
    m_previousFuelLevel = rocket->m_fuel;

    float h = m_w * 1.5f;
    glShadeModel( GL_SMOOTH );


    //
    // Background team colour

    glColor4ub( team->m_colour.r*0.2f, team->m_colour.g*0.2f, team->m_colour.b*0.2f, 200 );

    glBegin( GL_QUADS );
        glVertex2f( m_x, m_y );
        glVertex2f( m_x + m_w, m_y );
        glVertex2f( m_x + m_w, m_y + h );
        glVertex2f( m_x, m_y + h );
    glEnd();


    //
    // Refueling effect

    float fuelBase = m_y + h * 0.97f;
    float fuelFullH = h * 0.95f;
    float fuelH = fuelFullH * fuelPercent;
    int refuelAlpha = 128;

    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

    glEnable        ( GL_TEXTURE_2D );
    glBindTexture   ( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "textures/laser.bmp" ) );
    glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
    glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );


    if( fuelPercent < 1.0f )
    {
        glColor4ub( team->m_colour.r, team->m_colour.g, team->m_colour.b, refuelAlpha );

        float texY = fuelPercent * -100 + 0.5f;
        float texH = 1.0f;

        glBegin( GL_QUADS );
            glTexCoord2f(0,texY);       glVertex2f( m_x, fuelBase );
            glTexCoord2f(1,texY);       glVertex2f( m_x + m_w, fuelBase );
            glTexCoord2f(1,texY+texH);  glVertex2f( m_x + m_w, fuelBase - fuelFullH );
            glTexCoord2f(0,texY+texH);  glVertex2f( m_x, fuelBase - fuelFullH );
        glEnd();

    }


    //
    // Fuel level

    glBindTexture   ( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "textures/laser-long.bmp" ) );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    int fuelAlpha = 200;

    glBegin( GL_QUADS );
        glColor4ub( 0,0,0, fuelAlpha );
        glTexCoord2f( 0, 0.3f );       glVertex2f( m_x, fuelBase );
        glTexCoord2f( 0, 0.7f );       glVertex2f( m_x + m_w, fuelBase );
        
        glColor4ub( team->m_colour.r, team->m_colour.g, team->m_colour.b, fuelAlpha );
        glTexCoord2f( 1, 0.7f );       glVertex2f( m_x + m_w, fuelBase - fuelH );
        glTexCoord2f( 1, 0.3f );       glVertex2f( m_x, fuelBase - fuelH );
    glEnd();

    glDisable( GL_TEXTURE_2D );


    //
    // Shadow above fuel level

    glBegin( GL_QUADS );
        glColor4ub( 0,0,0, fuelAlpha*0.5f );
        glVertex2f( m_x, fuelBase - fuelH );
        glVertex2f( m_x + m_w, fuelBase - fuelH );
        glColor4ub( 0,0,0, 0 );
        glVertex2f( m_x + m_w, fuelBase - fuelH - h * 0.05f );
        glVertex2f( m_x, fuelBase - fuelH - 10 - h * 0.05f );
    glEnd();


    //
    // Rocket bitmap overlay

    glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );

    glBlendFunc     ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    glEnable        ( GL_TEXTURE_2D );
    glBindTexture   ( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "icons/rocketstatuspanel.bmp" ) );
    
    glBegin( GL_QUADS );
        glTexCoord2i(0,1);      glVertex2f( m_x, m_y );
        glTexCoord2i(1,1);      glVertex2f( m_x + m_w, m_y );
        glTexCoord2i(1,0);      glVertex2f( m_x + m_w, m_y + h );
        glTexCoord2i(0,0);      glVertex2f( m_x, m_y + h );
    glEnd();
    
    glDisable       ( GL_TEXTURE_2D );



    //
    // Damage effect

    glColor4f( 1.0f, 1.0f, 1.0f, rocket->m_damage/100.0f );

    glBlendFunc     ( GL_SRC_ALPHA, GL_ONE );
    glEnable        ( GL_TEXTURE_2D );
    glBindTexture   ( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "icons/rocketcracked.bmp" ) );

    glBegin( GL_QUADS );
    glTexCoord2i(0,1);      glVertex2f( m_x, m_y );
    glTexCoord2i(1,1);      glVertex2f( m_x + m_w, m_y );
    glTexCoord2i(1,0);      glVertex2f( m_x + m_w, m_y + h );
    glTexCoord2i(0,0);      glVertex2f( m_x, m_y + h );
    glEnd();

    glDisable       ( GL_TEXTURE_2D );



    //
    // Darwinians inside
    
    glBlendFunc     ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

    if( fuelPercent >= 1.0f || darwiniansInside > 0 )
    {
        float dwX = m_x + m_w * 0.25f;
        float dwW = m_w * 0.45f;
        float dwY = m_y + h * 0.225f;
        float dwH = h * 0.55f;
        float s = h * 0.04f;
        int astronautAlpha = 255;

        glEnable        ( GL_TEXTURE_2D );
        glBindTexture   ( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "sprites/darwinian.bmp" ) );

        for( int i = 99; i >= 0; i-- )
        {
            int xIndex = ( i % 10 );
            int yIndex = 9 - int( i / 10 );
            float xPos = dwX + dwW * xIndex/10;
            float yPos = dwY + dwH * yIndex/10;

            if( yIndex % 2 == 0 ) xPos += dwW/20.0f;

            RGBAColour astronautCol = team->m_colour;
            astronautCol.AddWithClamp( RGBAColour(50,50,50,255) );
            astronautCol.a = astronautAlpha;

            if( i <  darwiniansInside )     glColor4ub( team->m_colour.r, team->m_colour.g, team->m_colour.b, astronautAlpha );
            else                            glColor4ub( team->m_colour.r*0.3f, team->m_colour.g*0.3f, team->m_colour.b*0.3f, astronautAlpha*0.2f );

            Vector3 pos( xPos+s/2.0f, yPos+s/2.0f, 0 );
            pos.x += sinf(i + GetHighResTime()) * 1.0f;
            pos.y += cosf(i + i + GetHighResTime()) * 1.0f;

            Vector3 offset( -s/2.0f, -s, 0 );
            
            glBegin( GL_QUADS );
                glTexCoord2f(0,1);      glVertex2dv( (pos+offset).GetData() );      offset.RotateAroundZ(0.5f * M_PI);
                glTexCoord2f(1,1);      glVertex2dv( (pos+offset).GetData() );      offset.RotateAroundZ(0.5f * M_PI);
                glTexCoord2f(1,0);      glVertex2dv( (pos+offset).GetData() );      offset.RotateAroundZ(0.5f * M_PI);
                glTexCoord2f(0,0);      glVertex2dv( (pos+offset).GetData() );      offset.RotateAroundZ(0.5f * M_PI);
            glEnd();
        }

        glDisable( GL_TEXTURE_2D );
    }


    //
    // Engine effect

    if( rocket->m_state == EscapeRocket::StateReady ||
        rocket->m_state == EscapeRocket::StateCountdown ||
        rocket->m_state == EscapeRocket::StateFlight)
    {
        float flameX = m_x + m_w * 0.35f;
        float flameY = m_y + h * 0.8f;
        float flameW = m_w * 0.3f;
        float flameH = m_w * 0.3f;

        glBlendFunc     ( GL_SRC_ALPHA, GL_ONE );

        glEnable( GL_TEXTURE_2D );
        glBindTexture( GL_TEXTURE_2D, g_app->m_resource->GetTexture("textures/muzzleflash.bmp" ) );

        if( fmodf( GetHighResTime()*30, 1.0f ) < 0.5f ) glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
        else                                             glColor4f( 1.0f, 1.0f, 1.0f, 0.2f );

        glBegin( GL_QUADS );
            glTexCoord2i(0,0);      glVertex2f( flameX, flameY );
            glTexCoord2i(0,1);      glVertex2f( flameX+flameW, flameY );
            glTexCoord2i(1,1);      glVertex2f( flameX+flameW, flameY+flameH );
            glTexCoord2i(1,0);      glVertex2f( flameX, flameY+flameH );
        glEnd();

        glDisable( GL_TEXTURE_2D );
    }


    //
    // Captions at the bottom
    // Determine our caption

    float mainCaptionY = m_y + h * 0.6f;
    float mainCaptionH = h * 0.05f;
    float mainCaptionG = mainCaptionH * 0.1f;

    bool timeFlashEffect = (fmodf( GetHighResTime() * 2, 1.0f ) > 0.55f);

    UnicodeString caption;
    RGBAColour captionColour(255,255,255,255);

    if( GetHighResTime() - m_damageTimer < 10.0f && 
        rocket->m_state != EscapeRocket::StateExploding )
    {
        char damage[256];
        sprintf( damage, "%d%%", int(rocket->m_damage) );
        caption = LANGUAGEPHRASE("multiwinia_rr_status_c");
        caption.ReplaceStringFlag( L'T', damage );

        captionColour.Set(255,0,0,255);  
        if( timeFlashEffect ) captionColour.a *= 0.5f;
    }
    else if( rocket->m_state == EscapeRocket::StateCountdown )
    {        
        char captionC[256];
        sprintf( captionC, "%d", (int)rocket->m_countdown + 1 );
        caption = captionC;
        mainCaptionH *= 4;
    }
    else if( rocket->m_state == EscapeRocket::StateFlight )
    {
        caption = LANGUAGEPHRASE("multiwinia_rr_status_d" );
        mainCaptionH *= 1.5f;
        if( timeFlashEffect ) captionColour.a *= 0.25f;
    }
    else if( rocket->m_state == EscapeRocket::StateExploding )
    {
        caption = LANGUAGEPHRASE("multiwinia_rr_status_e" );
        if( timeFlashEffect ) captionColour.a *= 0.25f;
    }
    else if( fuelPercent >= 1.0f && darwiniansInside < 5 )
    {
        caption = LANGUAGEPHRASE("multiwinia_rr_status_b");
        if( timeFlashEffect ) captionColour.a *= 0.25f;
    } 
    else if( rocket->m_refuelRate < 0.05f && fuelPercent < 0.01f )
    {
        caption = LANGUAGEPHRASE("multiwinia_rr_status_a");        
        if( timeFlashEffect ) captionColour.a *= 0.25f;
    }
    else if( fuelPercent < 1.0f )
    {
        char captionC[256];
        sprintf( captionC, "%2.1f%%", fuelPercent * 100 );
        
        caption = LANGUAGEPHRASE("multiwinia_rr_status_f");
        caption.ReplaceStringFlag( L'T', captionC );

        captionColour.a *= 0.75f;
    }
       


    //
    // Render our caption

    if( caption.Length() )
    {
        LList<UnicodeString *> *wrapped = WordWrapText( caption, 1000, mainCaptionH, false, false );

        for( int i = 0; i < wrapped->Size(); ++i )
        {
            UnicodeString *thisString = wrapped->GetData(i);

            glColor4ub( captionColour.a, captionColour.a, captionColour.a, 0 );
            g_titleFont.SetRenderOutline(true);
            g_titleFont.DrawText2DCentre( m_x + m_w/2, mainCaptionY, mainCaptionH, *thisString );

            glColor4ubv( captionColour.GetData() );
            g_titleFont.SetRenderOutline(false);
            g_titleFont.DrawText2DCentre( m_x + m_w/2, mainCaptionY, mainCaptionH, *thisString );

            mainCaptionY += mainCaptionH;
            mainCaptionY += mainCaptionG;
        }

        wrapped->EmptyAndDelete();
        delete wrapped;
    }


    //
    // White border

    glColor4f( 1.0f, 1.0f, 1.0f, 0.2f );

    glBegin( GL_LINE_LOOP );
        glVertex2f( m_x, m_y );
        glVertex2f( m_x + m_w, m_y );
        glVertex2f( m_x + m_w, m_y + h );
        glVertex2f( m_x, m_y + h );
    glEnd();

    glShadeModel( GL_FLAT );
}