/*============================================================================= Name : ShipView.c Purpose : Render a specific ship to a window. Created 7/27/1998 by pgrant Copyright Relic Entertainment, Inc. All rights reserved. =============================================================================*/ #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include "types.h" #include "objtypes.h" #include "strings.h" #include "shipview.h" #include "camera.h" #include "feflow.h" #include "fereg.h" #include "glinc.h" #include "glcaps.h" #include "render.h" #include "universe.h" #include "light.h" #include "mouse.h" #include "font.h" #include "fontreg.h" #include "soundevent.h" #include "consmgr.h" #include "options.h" #include "FEColour.h" #include "gun.h" #include "glcompat.h" #include "probe.h" /*============================================================================= Private Types: =============================================================================*/ #define SV_ShipViewName "SV_ShipView" #define SV_FirepowerName "SV_Firepower" #define SV_CoverageName "SV_Coverage" #define SV_ManeuverName "SV_Maneuver" #define SV_ArmorName "SV_Armor" #define SV_TopSpeedName "SV_TopSpeed" #define SV_MassName "SV_Mass" #define SV_InitialCameraDistance 900.0f #define SV_FontNameLength 64 #define SV_DefaultFont "default.hff" #define SV_StatFont "HW_EuroseCond_11.hff" //"Small_Fonts_8.hff" #define SV_ViewMargin 8 regionhandle svShipViewRegion = NULL; regionhandle svFirepowerRegion = NULL; regionhandle svCoverageRegion = NULL; regionhandle svManeuverRegion = NULL; regionhandle svArmorRegion = NULL; regionhandle svTopSpeedRegion = NULL; regionhandle svMassRegion = NULL; fonthandle svShipViewFont = 0; fonthandle svShipStatFont = 0; bool ReZoom=TRUE; real32 savecamMouseX = 0.0f; char svShipViewFontName[SV_FontNameLength] = SV_DefaultFont; char svShipStatFontName[SV_FontNameLength] = SV_StatFont; //for printing numbers char buf[20]; /*============================================================================= Data: =============================================================================*/ /* real32 svScaleAdvanceSupportFrigate = 3.0; real32 svScaleAttackBomber = 10.0; real32 svScaleCarrier = 0.5; real32 svScaleCloakedFighter = 10.0; real32 svScaleCloakGenerator = 4.0; real32 svScaleDDDFrigate = 2.0; real32 svScaleDefenseFighter = 6.0; real32 svScaleDFGFrigate = 2.0; real32 svScaleGravWellGenerator = 2.0; real32 svScaleHeavyCorvette = 9.0; real32 svScaleHeavyCruiser = 0.5; real32 svScaleHeavyDefender = 10.0; real32 svScaleHeavyInterceptor = 10.0; real32 svScaleIonCannonFrigate = 2.5; real32 svScaleLightCorvette = 9.0; real32 svScaleLightDefender = 10.0; real32 svScaleLightInterceptor = 10.0; real32 svScaleMinelayerCorvette = 6.0; real32 svScaleMissileDestroyer = 1.0; real32 svScaleMothership = 4.0; //not used but here because of enumeration dependancy real32 svScaleMultiGunCorvette = 8.0; real32 svScaleProbe = 6.0; real32 svScaleProximitySensor = 8.0; real32 svScaleRepairCorvette = 8.0; real32 svScaleResearchShip = 3.0; real32 svScaleResourceCollector = 3.0; real32 svScaleResourceController = 1.0; real32 svScaleSalCapCorvette = 8.0; real32 svScaleSensorArray = 1.0; real32 svScaleStandardDestroyer = 1.0; real32 svScaleStandardFrigate = 3.0; real32 svMinZoomAdvanceSupportFrigate = 500.0; real32 svMinZoomAttackBomber = 500.0; real32 svMinZoomCarrier = 500.0; real32 svMinZoomCloakedFighter = 500.0; real32 svMinZoomCloakGenerator = 500.0; real32 svMinZoomDDDFrigate = 500.0; real32 svMinZoomDefenseFighter = 500.0; real32 svMinZoomDFGFrigate = 500.0; real32 svMinZoomGravWellGenerator = 500.0; real32 svMinZoomHeavyCorvette = 500.0; real32 svMinZoomHeavyCruiser = 500.0; real32 svMinZoomHeavyDefender = 500.0; real32 svMinZoomHeavyInterceptor = 500.0; real32 svMinZoomIonCannonFrigate = 500.0; real32 svMinZoomLightCorvette = 500.0; real32 svMinZoomLightDefender = 500.0; real32 svMinZoomLightInterceptor = 500.0; real32 svMinZoomMinelayerCorvette = 500.0; real32 svMinZoomMissileDestroyer = 500.0; real32 svMinZoomMothership = 500.0; //not used but here because of enumeration dependancy real32 svMinZoomMultiGunCorvette = 500.0; real32 svMinZoomProbe = 500.0; real32 svMinZoomProximitySensor = 500.0; real32 svMinZoomRepairCorvette = 500.0; real32 svMinZoomResearchShip = 500.0; real32 svMinZoomResourceCollector = 500.0; real32 svMinZoomResourceController = 500.0; real32 svMinZoomSalCapCorvette = 500.0; real32 svMinZoomSensorArray = 500.0; real32 svMinZoomStandardDestroyer = 500.0; real32 svMinZoomStandardFrigate = 500.0; real32 svMaxZoomAdvanceSupportFrigate = 1000.0; real32 svMaxZoomAttackBomber = 1000.0; real32 svMaxZoomCarrier = 1000.0; real32 svMaxZoomCloakedFighter = 1000.0; real32 svMaxZoomCloakGenerator = 1000.0; real32 svMaxZoomDDDFrigate = 1000.0; real32 svMaxZoomDefenseFighter = 1000.0; real32 svMaxZoomDFGFrigate = 1000.0; real32 svMaxZoomGravWellGenerator = 1000.0; real32 svMaxZoomHeavyCorvette = 1000.0; real32 svMaxZoomHeavyCruiser = 1000.0; real32 svMaxZoomHeavyDefender = 1000.0; real32 svMaxZoomHeavyInterceptor = 1000.0; real32 svMaxZoomIonCannonFrigate = 1000.0; real32 svMaxZoomLightCorvette = 1000.0; real32 svMaxZoomLightDefender = 1000.0; real32 svMaxZoomLightInterceptor = 1000.0; real32 svMaxZoomMinelayerCorvette = 1000.0; real32 svMaxZoomMissileDestroyer = 1000.0; real32 svMaxZoomMothership = 1000.0; //not used but here because of enumeration dependancy real32 svMaxZoomMultiGunCorvette = 1000.0; real32 svMaxZoomProbe = 1000.0; real32 svMaxZoomProximitySensor = 1000.0; real32 svMaxZoomRepairCorvette = 1000.0; real32 svMaxZoomResearchShip = 1000.0; real32 svMaxZoomResourceCollector = 1000.0; real32 svMaxZoomResourceController = 1000.0; real32 svMaxZoomSalCapCorvette = 1000.0; real32 svMaxZoomSensorArray = 1000.0; real32 svMaxZoomStandardDestroyer = 1000.0; real32 svMaxZoomStandardFrigate = 1000.0; */ Camera svCamera; real32 svAngle = -150.0; real32 svDeclination = -20; real32 svZoomOutScalar=1.1f; real32 svZoomInScalar=1.05f; scriptEntry ShipViewTweaks[] = { makeEntry(svAngle, scriptSetReal32CB), makeEntry(svDeclination, scriptSetReal32CB), makeEntry(svZoomInScalar, scriptSetReal32CB), makeEntry(svZoomOutScalar,scriptSetReal32CB), endEntry }; /* makeEntry(svScaleAdvanceSupportFrigate, scriptSetReal32CB), makeEntry(svScaleAttackBomber, scriptSetReal32CB), makeEntry(svScaleCarrier, scriptSetReal32CB), makeEntry(svScaleCloakedFighter, scriptSetReal32CB), makeEntry(svScaleCloakGenerator, scriptSetReal32CB), makeEntry(svScaleDDDFrigate, scriptSetReal32CB), makeEntry(svScaleDefenseFighter, scriptSetReal32CB), makeEntry(svScaleDFGFrigate, scriptSetReal32CB), makeEntry(svScaleGravWellGenerator, scriptSetReal32CB), makeEntry(svScaleHeavyCorvette, scriptSetReal32CB), makeEntry(svScaleHeavyCruiser, scriptSetReal32CB), makeEntry(svScaleHeavyDefender, scriptSetReal32CB), makeEntry(svScaleHeavyInterceptor, scriptSetReal32CB), makeEntry(svScaleIonCannonFrigate, scriptSetReal32CB), makeEntry(svScaleLightCorvette, scriptSetReal32CB), makeEntry(svScaleLightDefender, scriptSetReal32CB), makeEntry(svScaleLightInterceptor, scriptSetReal32CB), makeEntry(svScaleMinelayerCorvette, scriptSetReal32CB), makeEntry(svScaleMissileDestroyer, scriptSetReal32CB), makeEntry(svScaleMothership, scriptSetReal32CB), makeEntry(svScaleMultiGunCorvette, scriptSetReal32CB), makeEntry(svScaleProbe, scriptSetReal32CB), makeEntry(svScaleProximitySensor, scriptSetReal32CB), makeEntry(svScaleRepairCorvette, scriptSetReal32CB), makeEntry(svScaleResearchShip, scriptSetReal32CB), makeEntry(svScaleResourceCollector, scriptSetReal32CB), makeEntry(svScaleResourceController, scriptSetReal32CB), makeEntry(svScaleSalCapCorvette, scriptSetReal32CB), makeEntry(svScaleSensorArray, scriptSetReal32CB), makeEntry(svScaleStandardDestroyer, scriptSetReal32CB), makeEntry(svScaleStandardFrigate, scriptSetReal32CB), makeEntry(svMinZoomAdvanceSupportFrigate, scriptSetReal32CB), makeEntry(svMinZoomAttackBomber, scriptSetReal32CB), makeEntry(svMinZoomCarrier, scriptSetReal32CB), makeEntry(svMinZoomCloakedFighter, scriptSetReal32CB), makeEntry(svMinZoomCloakGenerator, scriptSetReal32CB), makeEntry(svMinZoomDDDFrigate, scriptSetReal32CB), makeEntry(svMinZoomDefenseFighter, scriptSetReal32CB), makeEntry(svMinZoomDFGFrigate, scriptSetReal32CB), makeEntry(svMinZoomGravWellGenerator, scriptSetReal32CB), makeEntry(svMinZoomHeavyCorvette, scriptSetReal32CB), makeEntry(svMinZoomHeavyCruiser, scriptSetReal32CB), makeEntry(svMinZoomHeavyDefender, scriptSetReal32CB), makeEntry(svMinZoomHeavyInterceptor, scriptSetReal32CB), makeEntry(svMinZoomIonCannonFrigate, scriptSetReal32CB), makeEntry(svMinZoomLightCorvette, scriptSetReal32CB), makeEntry(svMinZoomLightDefender, scriptSetReal32CB), makeEntry(svMinZoomLightInterceptor, scriptSetReal32CB), makeEntry(svMinZoomMinelayerCorvette, scriptSetReal32CB), makeEntry(svMinZoomMissileDestroyer, scriptSetReal32CB), makeEntry(svMinZoomMothership, scriptSetReal32CB), makeEntry(svMinZoomMultiGunCorvette, scriptSetReal32CB), makeEntry(svMinZoomProbe, scriptSetReal32CB), makeEntry(svMinZoomProximitySensor, scriptSetReal32CB), makeEntry(svMinZoomRepairCorvette, scriptSetReal32CB), makeEntry(svMinZoomResearchShip, scriptSetReal32CB), makeEntry(svMinZoomResourceCollector, scriptSetReal32CB), makeEntry(svMinZoomResourceController, scriptSetReal32CB), makeEntry(svMinZoomSalCapCorvette, scriptSetReal32CB), makeEntry(svMinZoomSensorArray, scriptSetReal32CB), makeEntry(svMinZoomStandardDestroyer, scriptSetReal32CB), makeEntry(svMinZoomStandardFrigate, scriptSetReal32CB), makeEntry(svMaxZoomAdvanceSupportFrigate, scriptSetReal32CB), makeEntry(svMaxZoomAttackBomber, scriptSetReal32CB), makeEntry(svMaxZoomCarrier, scriptSetReal32CB), makeEntry(svMaxZoomCloakedFighter, scriptSetReal32CB), makeEntry(svMaxZoomCloakGenerator, scriptSetReal32CB), makeEntry(svMaxZoomDDDFrigate, scriptSetReal32CB), makeEntry(svMaxZoomDefenseFighter, scriptSetReal32CB), makeEntry(svMaxZoomDFGFrigate, scriptSetReal32CB), makeEntry(svMaxZoomGravWellGenerator, scriptSetReal32CB), makeEntry(svMaxZoomHeavyCorvette, scriptSetReal32CB), makeEntry(svMaxZoomHeavyCruiser, scriptSetReal32CB), makeEntry(svMaxZoomHeavyDefender, scriptSetReal32CB), makeEntry(svMaxZoomHeavyInterceptor, scriptSetReal32CB), makeEntry(svMaxZoomIonCannonFrigate, scriptSetReal32CB), makeEntry(svMaxZoomLightCorvette, scriptSetReal32CB), makeEntry(svMaxZoomLightDefender, scriptSetReal32CB), makeEntry(svMaxZoomLightInterceptor, scriptSetReal32CB), makeEntry(svMaxZoomMinelayerCorvette, scriptSetReal32CB), makeEntry(svMaxZoomMissileDestroyer, scriptSetReal32CB), makeEntry(svMaxZoomMothership, scriptSetReal32CB), makeEntry(svMaxZoomMultiGunCorvette, scriptSetReal32CB), makeEntry(svMaxZoomProbe, scriptSetReal32CB), makeEntry(svMaxZoomProximitySensor, scriptSetReal32CB), makeEntry(svMaxZoomRepairCorvette, scriptSetReal32CB), makeEntry(svMaxZoomResearchShip, scriptSetReal32CB), makeEntry(svMaxZoomResourceCollector, scriptSetReal32CB), makeEntry(svMaxZoomResourceController, scriptSetReal32CB), makeEntry(svMaxZoomSalCapCorvette, scriptSetReal32CB), makeEntry(svMaxZoomSensorArray, scriptSetReal32CB), makeEntry(svMaxZoomStandardDestroyer, scriptSetReal32CB), makeEntry(svMaxZoomStandardFrigate, scriptSetReal32CB), endEntry }; */ /* real32* svScale[31] = { &svScaleAdvanceSupportFrigate, &svScaleAttackBomber, &svScaleCarrier, &svScaleCloakedFighter, &svScaleCloakGenerator, &svScaleDDDFrigate, &svScaleDefenseFighter, &svScaleDFGFrigate, &svScaleGravWellGenerator, &svScaleHeavyCorvette, &svScaleHeavyCruiser, &svScaleHeavyDefender, &svScaleHeavyInterceptor, &svScaleIonCannonFrigate, &svScaleLightCorvette, &svScaleLightDefender, &svScaleLightInterceptor, &svScaleMinelayerCorvette, &svScaleMissileDestroyer, &svScaleMothership, &svScaleMultiGunCorvette, &svScaleProbe, &svScaleProximitySensor, &svScaleRepairCorvette, &svScaleResearchShip, &svScaleResourceCollector, &svScaleResourceController, &svScaleSalCapCorvette, &svScaleSensorArray, &svScaleStandardDestroyer, &svScaleStandardFrigate }; real32* svMinZoom[31] = { &svMinZoomAdvanceSupportFrigate, &svMinZoomAttackBomber, &svMinZoomCarrier, &svMinZoomCloakedFighter, &svMinZoomCloakGenerator, &svMinZoomDDDFrigate, &svMinZoomDefenseFighter, &svMinZoomDFGFrigate, &svMinZoomGravWellGenerator, &svMinZoomHeavyCorvette, &svMinZoomHeavyCruiser, &svMinZoomHeavyDefender, &svMinZoomHeavyInterceptor, &svMinZoomIonCannonFrigate, &svMinZoomLightCorvette, &svMinZoomLightDefender, &svMinZoomLightInterceptor, &svMinZoomMinelayerCorvette, &svMinZoomMissileDestroyer, &svMinZoomMothership, &svMinZoomMultiGunCorvette, &svMinZoomProbe, &svMinZoomProximitySensor, &svMinZoomRepairCorvette, &svMinZoomResearchShip, &svMinZoomResourceCollector, &svMinZoomResourceController, &svMinZoomSalCapCorvette, &svMinZoomSensorArray, &svMinZoomStandardDestroyer, &svMinZoomStandardFrigate }; real32* svMaxZoom[31] = { &svMaxZoomAdvanceSupportFrigate, &svMaxZoomAttackBomber, &svMaxZoomCarrier, &svMaxZoomCloakedFighter, &svMaxZoomCloakGenerator, &svMaxZoomDDDFrigate, &svMaxZoomDefenseFighter, &svMaxZoomDFGFrigate, &svMaxZoomGravWellGenerator, &svMaxZoomHeavyCorvette, &svMaxZoomHeavyCruiser, &svMaxZoomHeavyDefender, &svMaxZoomHeavyInterceptor, &svMaxZoomIonCannonFrigate, &svMaxZoomLightCorvette, &svMaxZoomLightDefender, &svMaxZoomLightInterceptor, &svMaxZoomMinelayerCorvette, &svMaxZoomMissileDestroyer, &svMaxZoomMothership, &svMaxZoomMultiGunCorvette, &svMaxZoomProbe, &svMaxZoomProximitySensor, &svMaxZoomRepairCorvette, &svMaxZoomResearchShip, &svMaxZoomResourceCollector, &svMaxZoomResourceController, &svMaxZoomSalCapCorvette, &svMaxZoomSensorArray, &svMaxZoomStandardDestroyer, &svMaxZoomStandardFrigate }; */ ShipType svShipType = DefaultShip; sdword svMouseCentreX = 0; sdword svMouseCentreY = 0; sdword svMouseLastX = 0; sdword svMouseLastY = 0; bool8 svMouseInside = FALSE; bool8 svMousePressLeft = FALSE; bool8 svMousePressRight = FALSE; static GLfloat lightPosition0[] = {10000.0f, 1.0f, 1.0f, 0.1f}; //for callback from glcPageFlip, if glcompat module is active static featom* _glcAtom; static regionhandle _glcRegion; bool _svRender = FALSE; /*============================================================================= Function Prototypes =============================================================================*/ uword svShipCoverage(ShipStaticInfo *statinfo); void svShipManeuverability(ShipStaticInfo *statinfo,char *name); /*============================================================================= Functions: =============================================================================*/ /*----------------------------------------------------------------------------- Name : svDirtyShipView Description : Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void svDirtyShipView(void) { if (svShipViewRegion != NULL) { #ifdef DEBUG_STOMP regVerify(svShipViewRegion); #endif svShipViewRegion->status |= RSF_DrawThisFrame; } if (svFirepowerRegion != NULL) { #ifdef DEBUG_STOMP regVerify(svFirepowerRegion); #endif svFirepowerRegion->status |= RSF_DrawThisFrame; } if (svCoverageRegion != NULL) { #ifdef DEBUG_STOMP regVerify(svCoverageRegion); #endif svCoverageRegion->status |= RSF_DrawThisFrame; } if (svManeuverRegion != NULL) { #ifdef DEBUG_STOMP regVerify(svManeuverRegion); #endif svManeuverRegion->status |= RSF_DrawThisFrame; } if (svArmorRegion != NULL) { #ifdef DEBUG_STOMP regVerify(svArmorRegion); #endif svArmorRegion->status |= RSF_DrawThisFrame; } if (svTopSpeedRegion != NULL) { #ifdef DEBUG_STOMP regVerify(svTopSpeedRegion); #endif svTopSpeedRegion->status |= RSF_DrawThisFrame; } if (svMassRegion != NULL) { #ifdef DEBUG_STOMP regVerify(svMassRegion); #endif svMassRegion->status |= RSF_DrawThisFrame; } } /*----------------------------------------------------------------------------- Name : svSelectShip Description : Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void svSelectShip(ShipType type) { svShipType = type; ReZoom=TRUE; } /*----------------------------------------------------------------------------- Name : svClose Description : Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void svClose(void) { svShipViewRegion = NULL; svFirepowerRegion = NULL; svCoverageRegion = NULL; svManeuverRegion = NULL; svArmorRegion = NULL; svTopSpeedRegion = NULL; svMassRegion = NULL; svShipType = DefaultShip; } /*----------------------------------------------------------------------------- Name : svReadMouseEvent Description : Callback for reading mouse events for use by svShipViewRender Inputs : standard region callback Outputs : Return : ----------------------------------------------------------------------------*/ sdword svReadMouseEvent(regionhandle region, sdword ID, udword event, udword data) { rectangle *rect = ®ion->rect; rectangle defaultRect = {0, 0, MAIN_WindowWidth, MAIN_WindowHeight}; switch(event) { case RPE_WheelUp: wheel_up = TRUE; break; case RPE_WheelDown: wheel_down = TRUE; break; case RPE_Enter: svMouseInside = TRUE; break; case RPE_Exit: svMouseInside = FALSE; svMousePressRight = FALSE; svMousePressLeft = FALSE; break; case RPE_PressRight: // Save last known position of cursor svMouseLastX = mouseCursorX(); svMouseLastY = mouseCursorY(); // Centre mouse svMouseCentreX = (rect->x0 + rect->x1) >> 1; svMouseCentreY = (rect->y0 + rect->y1) >> 1; mousePositionSet(svMouseCentreX, svMouseCentreY); mouseClipToRect(rect); svMousePressRight = TRUE; break; case RPE_PressLeft: svMousePressLeft = TRUE; break; case RPE_ReleaseRight: mousePositionSet(svMouseLastX, svMouseLastY); mouseClipToRect(&defaultRect); svMousePressRight = FALSE; break; case RPE_ReleaseLeft: svMousePressLeft = FALSE; break; } return 0; } #define SPIN_FEEDBACK 0.5 /*----------------------------------------------------------------------------- Name : svShipViewRender Description : Callback which draws the main ship view. Inputs : standard FE callback Outputs : .. Return : void ----------------------------------------------------------------------------*/ void svShipViewRender(featom* atom, regionhandle region) { rectangle drawRect; rectangle* rect; rectangle viewRect; fonthandle currentFont; GLint viewPort[4]; GLint box[4]; ShipStaticInfo* info; real32 scale; sdword width, height; sdword x, y; keyindex key; char* keystring; bool resetRender; char temp[100]; resetRender = FALSE; //test if we'll need a mesh callback from glcPageFlip later if (glcActive()) { if (_svRender) { atom = _glcAtom; region = _glcRegion; resetRender = TRUE; } else { _glcAtom = atom; _glcRegion = region; _svRender = TRUE; } } rect = ®ion->rect; viewRect.x0 = 0; viewRect.y0 = 0; viewRect.x1 = MAIN_WindowWidth - 1; viewRect.y1 = MAIN_WindowHeight - 1; info = NULL; if (svShipType != DefaultShip) { if (universe.curPlayerPtr) { info = GetShipStaticInfoSafe(svShipType, universe.curPlayerPtr->race); } if (info == NULL) { info = GetShipStaticInfoSafe(svShipType, GetValidRaceForShipType(svShipType)); } if (info == NULL) { return; } } svShipViewRegion = region; if (!resetRender) { if (svMouseInside) { ferDrawFocusWindow(region, lw_focus); } else { ferDrawFocusWindow(region, lw_normal); } } soundEventUpdate(); currentFont = fontMakeCurrent(svShipViewFont); if (region->flags == 0 || region->flags == RPE_DrawFunctionAdded) { //if region not processed yet region->flags = RPE_Enter | RPE_Exit | RPE_WheelDown | RPE_WheelUp | RPE_PressLeft | RPE_ReleaseLeft | RPE_PressRight | RPE_ReleaseRight; regFunctionSet(region, (regionfunction) svReadMouseEvent); //set new region handler function } //scale = *svScale[svShipType]; //svCamera.closestZoom = *svMinZoom[svShipType]; //svCamera.farthestZoom = *svMaxZoom[svShipType]; scale = 1.0f; //*svScale[svShipType]; if(svShipType != DefaultShip) { svCamera.closestZoom = info->minimumZoomDistance*svZoomInScalar; svCamera.farthestZoom = (svCamera.closestZoom+info->staticheader.staticCollInfo.approxcollspheresize)*svZoomOutScalar; if(ReZoom) { ReZoom=FALSE; cameraZoom(&svCamera,1.0f,FALSE); } if (svMouseInside && (wheel_down || wheel_up)) { cameraControl(&svCamera, FALSE); } else if (svMouseInside && svMousePressRight) { camMouseX = (svMouseCentreX - mouseCursorX()) * 4; //was 2 camMouseY = (svMouseCentreY - mouseCursorY()) * 4; savecamMouseX = savecamMouseX * SPIN_FEEDBACK + (real32)camMouseX * (1.0f - SPIN_FEEDBACK); cameraControl(&svCamera, FALSE); //update the camera mouseCursorHide(); mousePositionSet(svMouseCentreX, svMouseCentreY); // Reset position so it doesn't walk off region } else { // Default rotation and return declination to normal //uncomment for free rotation //svCamera.angle += 0.001f*savecamMouseX; if (svMouseInside) mouseCursorShow(); } } //rotation drawRect.x0 = rect->x0 + SV_ViewMargin; drawRect.y0 = rect->y0 + SV_ViewMargin; drawRect.x1 = rect->x1 - SV_ViewMargin; drawRect.y1 = rect->y1 - SV_ViewMargin; width = drawRect.x1 - drawRect.x0; height = drawRect.y1 - drawRect.y0; glGetIntegerv(GL_VIEWPORT, viewPort); glViewport(drawRect.x0, MAIN_WindowHeight - drawRect.y1, width, height); primModeSet2(); if (!resetRender) { primRectSolid2(glcActive() ? &drawRect : &viewRect, FEC_Background); } primModeClear2(); glEnable(GL_SCISSOR_TEST); glGetIntegerv(GL_SCISSOR_BOX, box); glScissor(drawRect.x0, MAIN_WindowHeight - drawRect.y1, width, height); glClear(GL_DEPTH_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); rndPerspectiveCorrection(TRUE); //svCamera.lookatpoint.x = -info->staticheader.staticCollInfo.collsphereoffset.z * scale; //svCamera.lookatpoint.y = -info->staticheader.staticCollInfo.collsphereoffset.x * scale; //svCamera.lookatpoint.z = -info->staticheader.staticCollInfo.collsphereoffset.y * scale; if (svShipType == DefaultShip) { svCamera.lookatpoint.x=0.0f; svCamera.lookatpoint.y=0.0f; svCamera.lookatpoint.z=0.0f; } else { svCamera.lookatpoint.x = -info->staticheader.staticCollInfo.collsphereoffset.z; svCamera.lookatpoint.y = -info->staticheader.staticCollInfo.collsphereoffset.x; svCamera.lookatpoint.z = -info->staticheader.staticCollInfo.collsphereoffset.y; } cameraSetEyePosition(&svCamera); rndLightingEnable(TRUE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); rgluPerspective( svCamera.fieldofview, (float)(width) / (float)(height) /*rndAspectRatio*/, //set projection matrix svCamera.clipPlaneNear, svCamera.clipPlaneFar); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); rgluLookAt( svCamera.eyeposition.x, svCamera.eyeposition.y, svCamera.eyeposition.z, svCamera.lookatpoint.x, svCamera.lookatpoint.y, svCamera.lookatpoint.z, svCamera.upvector.x, svCamera.upvector.y, svCamera.upvector.z); glPushMatrix(); glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)(&rndCameraMatrix)); glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)(&rndProjectionMatrix)); glEnable(GL_NORMALIZE); glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0); //position light(s) within world glScalef(scale, scale, scale); if (svShipType != DefaultShip) { if (resetRender || !_svRender) { sdword index; //try player index colours first index = universe.curPlayerIndex; if (info->teamColor[index] == 0) { //colour scheme doesn't exist, search for something valid for (index = 0; index < MAX_MULTIPLAYER_PLAYERS; index++) { if (info->teamColor[index] != 0) { break; } } if (index == MAX_MULTIPLAYER_PLAYERS) { //this ship doesn't have any colour info, //at least avoid a GPF index = universe.curPlayerIndex; } } meshRender((meshdata *)info->staticheader.LOD->level[0].pData, index); } } glDisable(GL_NORMALIZE); glPopMatrix(); primModeSet2(); glScissor(box[0], box[1], box[2], box[3]); glViewport(viewPort[0], viewPort[1], viewPort[2], viewPort[3]); rndLightingEnable(FALSE); rndPerspectiveCorrection(FALSE); x = rect->x0 + 2 + SV_ViewMargin; y = rect->y0 + 2 + SV_ViewMargin; if (svShipType != DefaultShip && !resetRender) { fontPrintf( x, y, FEC_ListItemStandard, "%s", ShipTypeToNiceStr(svShipType)); y += fontHeight(" "); sprintf(temp, "%s %d %s",strGetString(strSVCost),info->buildCost, strGetString(strSVRUs)); fontPrintf( x, y, FEC_ListItemStandard, temp); if (cmPrintHotKey) { x = rect->x1 - 2 - SV_ViewMargin; y = rect->y0 + 2 + SV_ViewMargin; key = cmShipTypeToKey(svShipType); keystring = opKeyToNiceString((keyindex)(key & 0x00ff)); if (key & CM_SHIFT) { width = fontWidthf("[SHIFT-%s]",keystring); fontPrintf( x-width, y, FEC_ListItemStandard, "[SHIFT-%s]", keystring); } else if (key) { width = fontWidthf("[%s]",keystring); fontPrintf( x-width, y, FEC_ListItemStandard, "[%s]", keystring); } } } fontMakeCurrent(currentFont); svDirtyShipView(); if (resetRender) { _svRender = FALSE; } } /*----------------------------------------------------------------------------- Name : svFirepowerRender Description : Callback which draws the firepower stat in ship view. Inputs : standard FE callback Outputs : .. Return : void ----------------------------------------------------------------------------*/ void svFirepowerRender(featom *atom, regionhandle region) { rectangle *rect = ®ion->rect; fonthandle currentFont; uword firepower; char buftemp[50]; ShipStaticInfo *info = GetShipStaticInfoSafe(svShipType, universe.curPlayerPtr->race); svFirepowerRegion = region; if (FELASTCALL(atom)) { svFirepowerRegion = NULL; return; } if(svShipType == DefaultShip) { return; } if (info == NULL) { info = GetShipStaticInfoSafe(svShipType, GetValidRaceForShipType(svShipType)); } if (info == NULL) { return; } currentFont = fontMakeCurrent(svShipStatFont); if (RGLtype == SWtype || glcActive()) primRectSolid2(®ion->rect, FEC_Background); if(info->svFirePower !=0) { firepower = (uword) info->svFirePower; } else { firepower = (uword) gunShipFirePower(info, Neutral); } if(firepower != 0) { sprintf(buftemp,"%d",firepower); } else { sprintf(buftemp,"%s","-"); } sprintf(buf,ShipStatToNiceStr(Firepower),buftemp); fontPrintf( rect->x0, rect->y0, FEC_ListItemStandard, "%s", buf); fontMakeCurrent(currentFont); } /*----------------------------------------------------------------------------- Name : svCoverageRender Description : Callback which draws the coverage stat in ship view. Inputs : standard FE callback Outputs : .. Return : void ----------------------------------------------------------------------------*/ void svCoverageRender(featom *atom, regionhandle region) { rectangle *rect = ®ion->rect; sdword width; fonthandle currentFont; char buftemp[50]; uword coverage; ShipStaticInfo *info = GetShipStaticInfoSafe(svShipType, universe.curPlayerPtr->race); svCoverageRegion = region; if (FELASTCALL(atom)) { svCoverageRegion = NULL; return; } if(svShipType == DefaultShip) { return; } if (info == NULL) { info = GetShipStaticInfoSafe(svShipType, GetValidRaceForShipType(svShipType)); } if (info == NULL) { return; //maybe print UNKNOWN! } currentFont = fontMakeCurrent(svShipStatFont); coverage = svShipCoverage(info); if(coverage != 0) { sprintf(buftemp,"%d %s",coverage,ShipStatToNiceStr(CoverageUnits)); } else { sprintf(buftemp,"%s","-"); } sprintf(buf,ShipStatToNiceStr(Coverage),buftemp); width = fontWidthf("%s",buf); if (RGLtype == SWtype || glcActive()) primRectSolid2(®ion->rect, FEC_Background); fontPrintf( rect->x0,//rect->x1 - width, rect->y0, FEC_ListItemStandard, "%s",buf); fontMakeCurrent(currentFont); } /*----------------------------------------------------------------------------- Name : svManeuverRender Description : Callback which draws the maneuver stat in ship view. Inputs : standard FE callback Outputs : .. Return : void ----------------------------------------------------------------------------*/ void svManeuverRender(featom *atom, regionhandle region) { rectangle *rect = ®ion->rect; fonthandle currentFont; char maneuverability[100]; ShipStaticInfo *info = GetShipStaticInfoSafe(svShipType, universe.curPlayerPtr->race); svManeuverRegion = region; if (FELASTCALL(atom)) { svManeuverRegion = NULL; return; } if (svShipType == DefaultShip) { return; } if (info == NULL) { info = GetShipStaticInfoSafe(svShipType, GetValidRaceForShipType(svShipType)); } if (info == NULL) { return; } currentFont = fontMakeCurrent(svShipStatFont); if (RGLtype == SWtype || glcActive()) primRectSolid2(®ion->rect, FEC_Background); svShipManeuverability(info,maneuverability); sprintf(buf,ShipStatToNiceStr(Maneuver),maneuverability); fontPrintf( rect->x0, rect->y0, FEC_ListItemStandard, "%s",buf); fontMakeCurrent(currentFont); } /*----------------------------------------------------------------------------- Name : svArmorRender Description : Callback which draws the armor stat in ship view. Inputs : standard FE callback Outputs : .. Return : void ----------------------------------------------------------------------------*/ void svArmorRender(featom *atom, regionhandle region) { rectangle *rect = ®ion->rect; sdword width; char buftemp[50]; fonthandle currentFont; ShipStaticInfo *info = GetShipStaticInfoSafe(svShipType, universe.curPlayerPtr->race); svArmorRegion = region; if (FELASTCALL(atom)) { svArmorRegion = NULL; return; } if(svShipType == DefaultShip) { return; } if (info == NULL) { info = GetShipStaticInfoSafe(svShipType, GetValidRaceForShipType(svShipType)); } if (info == NULL) { return; } svArmorRegion = region; currentFont = fontMakeCurrent(svShipStatFont); sprintf(buftemp,"%d",(udword) info->maxhealth); sprintf(buf,ShipStatToNiceStr(Armor),buftemp); width = fontWidthf("%s",buf); if (RGLtype == SWtype || glcActive()) primRectSolid2(®ion->rect, FEC_Background); fontPrintf( rect->x0,//rect->x1 - width, rect->y0, FEC_ListItemStandard, "%s",buf); fontMakeCurrent(currentFont); } /*----------------------------------------------------------------------------- Name : svTopSpeedRender Description : Callback which draws the top speed stat in ship view. Inputs : standard FE callback Outputs : .. Return : void ----------------------------------------------------------------------------*/ void svTopSpeedRender(featom *atom, regionhandle region) { rectangle *rect = ®ion->rect; fonthandle currentFont; char buftemp[50]; ShipStaticInfo *info = GetShipStaticInfoSafe(svShipType, universe.curPlayerPtr->race); svTopSpeedRegion = region; if (FELASTCALL(atom)) { svTopSpeedRegion = NULL; return; } if(svShipType == DefaultShip) { return; } if (info == NULL) { info = GetShipStaticInfoSafe(svShipType, GetValidRaceForShipType(svShipType)); } if (info == NULL) { return; } currentFont = fontMakeCurrent(svShipStatFont); if (RGLtype == SWtype || glcActive()) primRectSolid2(®ion->rect, FEC_Background); //sprintf(buf,"%d", (uword)info->staticheader.maxvelocity); //topspeed contains a %d for the numerical location of the maxvelocity if(info->shiptype == Probe) { sprintf(buftemp,"%d",(udword) ((ProbeStatics *) info->custstatinfo)->ProbeDispatchMaxVelocity); sprintf(buf,ShipStatToNiceStr(TopSpeed),buftemp); } else { sprintf(buftemp,"%d",(udword) info->staticheader.maxvelocity); sprintf(buf,ShipStatToNiceStr(TopSpeed),buftemp); } fontPrintf( rect->x0, rect->y0, FEC_ListItemStandard, "%s", buf); fontMakeCurrent(currentFont); } /*----------------------------------------------------------------------------- Name : svMassRender Description : Callback which draws the mass stat in ship view. Inputs : standard FE callback Outputs : .. Return : void ----------------------------------------------------------------------------*/ void svMassRender(featom *atom, regionhandle region) { rectangle *rect = ®ion->rect; fonthandle currentFont; sdword width; char buftemp[50]; ShipStaticInfo *info = GetShipStaticInfoSafe(svShipType, universe.curPlayerPtr->race); svMassRegion = region; if (FELASTCALL(atom)) { svMassRegion = NULL; return; } if(svShipType == DefaultShip) { return; } if (info == NULL) { info = GetShipStaticInfoSafe(svShipType, GetValidRaceForShipType(svShipType)); } if (info == NULL) { return; } currentFont = fontMakeCurrent(svShipStatFont); //sprintf(buf, "%d", (uword)info->staticheader.mass); //Mass str contains a %d for the mass to expand into sprintf(buftemp,"%d",(udword)info->staticheader.mass); sprintf(buf,ShipStatToNiceStr(Mass),buftemp); width = fontWidthf("%s", buf); //width of number //ShipTypeStatToNiceStr(svShipType, Mass));//width of number if (RGLtype == SWtype || glcActive()) primRectSolid2(®ion->rect, FEC_Background); fontPrintf( rect->x0,//rect->x1 - width, rect->y0, FEC_ListItemStandard, "%s", buf); //ShipTypeStatToNiceStr(svShipType, Mass)); fontMakeCurrent(currentFont); } /*----------------------------------------------------------------------------- Name : svStartup() Description : Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void svStartup(void) { cameraInit(&svCamera, SV_InitialCameraDistance); svCamera.angle = DEG_TO_RAD(svAngle); svCamera.declination = DEG_TO_RAD(svDeclination); feDrawCallbackAdd(SV_ShipViewName, svShipViewRender); //add render callbacks feDrawCallbackAdd(SV_FirepowerName, svFirepowerRender); feDrawCallbackAdd(SV_CoverageName, svCoverageRender); feDrawCallbackAdd(SV_ManeuverName, svManeuverRender); feDrawCallbackAdd(SV_ArmorName, svArmorRender); feDrawCallbackAdd(SV_TopSpeedName, svTopSpeedRender); feDrawCallbackAdd(SV_MassName, svMassRender); svMouseInside = FALSE; svMousePressLeft = FALSE; svMousePressRight = FALSE; svShipViewFont = frFontRegister(svShipViewFontName); svShipStatFont = frFontRegister(svShipStatFontName); } /*----------------------------------------------------------------------------- Name : svShutdown() Description : Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void svShutdown(void) { } uword svShipCoverage(ShipStaticInfo *statinfo) { GunStaticInfo *guninfo = statinfo->gunStaticInfo; GunStatic *gun,*gun2; sdword i,j,numGuns; real32 coverage=0; real32 gunvalue,gunangledif; if(guninfo == NULL) { return(0); } numGuns = guninfo->numGuns; for(i=0;igunstatics[i]; switch(gun->guntype) { case GUN_Fixed: //fixed guns don't really increase by anything.. //but we'll make it feel better by giving it +1; coverage+=0.1f; break; case GUN_Gimble: gunvalue = (acos(gun->cosmaxAngleFromNorm))*2.0f; for(j=i+1;jgunstatics[i]; //angle difference between normals of two guns. gunangledif = acos(vecDotProduct(gun->gunnormal,gun2->gunnormal)); gunangledif = gunangledif - acos(gun->cosmaxAngleFromNorm) - acos(gun2->cosmaxAngleFromNorm); if(gunangledif < 0.0f) gunvalue+=gunangledif; if(gunvalue <= 0.0f) break; } coverage+=max(gunvalue,0.0f); break; case GUN_NewGimble: coverage = coverage + (min(2*gun->maxturnangle,2*gun->maxdeclination)); break; case GUN_MissileLauncher: case GUN_MineLauncher: coverage=2*PI; goto donecoveragecalc; break; } } donecoveragecalc: coverage = 100.0*coverage/(2*PI); return(min(((uword) coverage),100)); } void svShipManeuverability(ShipStaticInfo *statinfo,char *name) { sdword man=0; real32 turnspeed; if(statinfo->svManeuverability != 0) { man = statinfo->svManeuverability; calcmanjump: switch (man) { case 1: //very low sprintf(name,"%s",ShipStatToNiceStr(VeryLow)); break; case 2: //low sprintf(name,"%s",ShipStatToNiceStr(Low)); break; case 3: //medium sprintf(name,"%s",ShipStatToNiceStr(Medium)); break; case 4: //high sprintf(name,"%s",ShipStatToNiceStr(High)); break; case 5: //Very High sprintf(name,"%s",ShipStatToNiceStr(VeryHigh)); break; default: dbgFatalf(DBG_Loc,"Error Calculating Maneuverability"); } return; } //calculate maneuverability turnspeed = statinfo->turnspeedstat[TURN_YAW]+ statinfo->turnspeedstat[TURN_PITCH]+ statinfo->turnspeedstat[TURN_ROLL]; if(turnspeed < TW_SV_MAN_VERY_LOW) man=1; else if(turnspeed < TW_SV_MAN_LOW) man=2; else if(turnspeed < TW_SV_MAN_MEDIUM) man=3; else if(turnspeed < TW_SV_MAN_HIGH) man=4; else man=5; goto calcmanjump; }