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; } } } }
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; }
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 ); } }
void EclUpdate () { // // Update all windows for ( int i = 0; i < windows.Size(); ++i ) { EclWindow *window = windows.GetData(i); window->Update(); } }
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; }
EclWindow *EclGetWindow ( char *name ) { int index = EclGetWindowIndex (name); if ( index == -1 ) { return NULL; } else { return windows.GetData(index); } }
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 { } }
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(); }
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 ); }
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 ); }