#include "framework.h" #include "health.h" #include "draw.h" #include "pickup.h" #include "lara.h" #include "camera.h" #include "level.h" #include "control.h" using namespace T5M::Renderer; short PickupX; short PickupY; short CurrentPickup; DISPLAY_PICKUP Pickups[MAX_COLLECTED_PICKUPS]; short PickupVel; int OldHitPoints = 1000; int HealthBarTimer = 40; float HealthBar = OldHitPoints; float MutateAmount = 0; int FlashState = 0; int FlashCount = 0; int PoisonFlag = 0; int DashTimer = 0; extern RendererHUDBar* g_HealthBar; extern RendererHUDBar* g_DashBar; extern RendererHUDBar* g_AirBar; bool EnableSmoothHealthBar = true; void DrawHealthBarOverlay(int value) { if (CurrentLevel) { int color2 = 0; if (Lara.poisoned || Lara.gassed) color2 = 0xA0A000; else color2 = 0xA00000; g_Renderer.DrawBar(value, ::g_HealthBar); } } void DrawHealthBar(float value) { if (CurrentLevel) { g_Renderer.DrawBar(value, ::g_HealthBar); } } void UpdateHealthBar(int flash) { int hitPoints = LaraItem->hitPoints; if (hitPoints < 0) hitPoints = 0; else if (hitPoints > 1000) hitPoints = 1000; // OPT: smoothly transition health bar display. if (EnableSmoothHealthBar) { if (OldHitPoints != hitPoints) { MutateAmount += OldHitPoints - hitPoints; OldHitPoints = hitPoints; HealthBarTimer = 40; } if (HealthBar - MutateAmount < 0) MutateAmount = HealthBar; else if (HealthBar - MutateAmount > 1000) MutateAmount = HealthBar - 1000; HealthBar -= MutateAmount / 3; MutateAmount -= MutateAmount / 3; if (MutateAmount > -0.5f && MutateAmount < 0.5f) { MutateAmount = 0; HealthBar = hitPoints; } } // OG: discretely transition health bar display. else { if (OldHitPoints != hitPoints) { OldHitPoints = hitPoints; HealthBar = hitPoints; HealthBarTimer = 40; } } if (HealthBarTimer < 0) HealthBarTimer = 0; // Flash when at 1/4 capacity AND HP bar is not transitioning. if (HealthBar <= 1000 / 4 && MutateAmount == 0) { if (!BinocularRange) { if (flash) DrawHealthBar(HealthBar / 1000.0f); else DrawHealthBar(0); } else { if (flash) DrawHealthBarOverlay(HealthBar / 1000.0f); else DrawHealthBarOverlay(0); } } else if ((HealthBarTimer > 0) || (HealthBar <= 0) || (Lara.gunStatus == LG_READY && Lara.gunType != WEAPON_TORCH) || (Lara.poisoned >= 256)) { if (!BinocularRange && !SniperOverlay) { DrawHealthBar(HealthBar / 1000.0f); } else { DrawHealthBarOverlay(HealthBar / 1000.0f); } } if (PoisonFlag) PoisonFlag--; } void DrawAirBar(float value) { if (CurrentLevel) { g_Renderer.DrawBar(value, ::g_AirBar); } } void UpdateAirBar(int flash) { if (Lara.air == 1800 || LaraItem->hitPoints <= 0) return; if ((Lara.Vehicle == NO_ITEM) || (g_Level.Items[Lara.Vehicle].objectNumber != ID_UPV)) { if ((Lara.waterStatus != LW_UNDERWATER) && (Lara.waterStatus != LW_SURFACE) && (!((g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_SWAMP) && (Lara.waterSurfaceDist < -775)))) return; } int air = Lara.air; if (air < 0) air = 0; else if (air > 1800) air = 1800; if (air <= 450) { if (flash) DrawAirBar(air / 1800.0f); else DrawAirBar(0); } else DrawAirBar(air / 1800.0f); if (Lara.gassed) { if (Lara.dpoisoned < 2048) Lara.dpoisoned += 2; Lara.gassed = false; } } void DrawDashBar(int value) { if (CurrentLevel) { g_Renderer.DrawBar(value, ::g_DashBar); } } int DrawAllPickups() { if (Pickups[CurrentPickup].life > 0) { if (PickupX > 0) { PickupX += -PickupX >> 5; return g_Renderer.DrawPickup(Pickups[CurrentPickup].objectNumber); } else { Pickups[CurrentPickup].life--; return g_Renderer.DrawPickup(Pickups[CurrentPickup].objectNumber); } } else if (Pickups[CurrentPickup].life == 0) { if (PickupX < 128) { if (PickupVel < 16) PickupVel++; PickupX += PickupVel >> 2; return g_Renderer.DrawPickup(Pickups[CurrentPickup].objectNumber); } else { Pickups[CurrentPickup].life = -1; PickupVel = 0; return g_Renderer.DrawPickup(Pickups[CurrentPickup].objectNumber); } } int pickupIndex = CurrentPickup; int i; for (i = 0; i < MAX_COLLECTED_PICKUPS; ++i) { if (Pickups[pickupIndex].life > 0) break; pickupIndex = pickupIndex + 1 & MAX_COLLECTED_PICKUPS - 1; } CurrentPickup = pickupIndex; if (i != MAX_COLLECTED_PICKUPS) return g_Renderer.DrawPickup(Pickups[CurrentPickup].objectNumber); CurrentPickup = 0; return 0; } void AddDisplayPickup(short objectNumber) { for (int i = 0; i < MAX_COLLECTED_PICKUPS; i++) { DISPLAY_PICKUP* pickup = &Pickups[i]; if (pickup->life < 0) { pickup->life = 45; pickup->objectNumber = objectNumber; PickedUpObject(objectNumber); return; } } // No free slot found, so just pickup the object ithout displaying it PickedUpObject(objectNumber); } void InitialisePickupDisplay() { for (int i = 0; i < MAX_COLLECTED_PICKUPS; i++) { DISPLAY_PICKUP* pickup = &Pickups[i]; pickup->life = -1; } PickupX = 128; PickupY = 128; PickupVel = 0; CurrentPickup = 0; } int FlashIt() { if (FlashCount) FlashCount--; else { FlashState ^= 1; FlashCount = 5; } return FlashState; }