diff --git a/src/combat_ai.cc b/src/combat_ai.cc index 5bb9275..84d3e1b 100644 --- a/src/combat_ai.cc +++ b/src/combat_ai.cc @@ -1745,7 +1745,7 @@ static bool aiHaveAmmo(Object* critter, Object* weapon, Object** ammoPtr) } if (weapon->pid == PROTO_ID_SOLAR_SCORCHER) { - return lightGetLightLevel() > 62259; + return lightGetAmbientIntensity() > LIGHT_INTENSITY_MAX * 0.95; } int inventoryItemIndex = -1; @@ -2879,7 +2879,7 @@ static int _ai_try_attack(Object* a1, Object* a2) // 0x42AE90 int _cAIPrepWeaponItem(Object* critter, Object* item) { - if (item != NULL && critterGetStat(critter, STAT_INTELLIGENCE) >= 3 && item->pid == PROTO_ID_FLARE && lightGetLightLevel() < 55705) { + if (item != NULL && critterGetStat(critter, STAT_INTELLIGENCE) >= 3 && item->pid == PROTO_ID_FLARE && lightGetAmbientIntensity() < LIGHT_INTENSITY_MAX * 0.85) { _protinst_use_item(critter, item); } return 0; diff --git a/src/interpreter_extra.cc b/src/interpreter_extra.cc index 8000f43..f790004 100644 --- a/src/interpreter_extra.cc +++ b/src/interpreter_extra.cc @@ -343,21 +343,6 @@ static void opGetPcStat(Program* program); // 0x504B0C static char _aCritter[] = ""; -// Maps light level to light intensity. -// -// Middle value is mapped one-to-one which corresponds to 50% light level -// (cavern lighting). Light levels above (51-100%) and below (0-49) is -// calculated as percentage from two adjacent light values. -// -// See [opSetLightLevel] for math. -// -// 0x453F90 -static const int dword_453F90[3] = { - 0x4000, - 0xA000, - 0x10000, -}; - // 0x453FC0 static Rect stru_453FC0 = { 0, 0, 640, 480 }; @@ -2234,23 +2219,36 @@ static void opCritterHeal(Program* program) // 0x457934 static void opSetLightLevel(Program* program) { + // Maps light level to light intensity. + // + // Middle value is mapped one-to-one which corresponds to 50% light level + // (cavern lighting). Light levels above (51-100%) and below (0-49%) is + // calculated as percentage from two adjacent light values. + // + // 0x453F90 + static const int intensities[3] = { + LIGHT_INTENSITY_MIN, + (LIGHT_INTENSITY_MIN + LIGHT_INTENSITY_MAX) / 2, + LIGHT_INTENSITY_MAX, + }; + int data = programStackPopInteger(program); int lightLevel = data; if (data == 50) { - lightSetLightLevel(dword_453F90[1], true); + lightSetAmbientIntensity(intensities[1], true); return; } int lightIntensity; if (data > 50) { - lightIntensity = dword_453F90[1] + data * (dword_453F90[2] - dword_453F90[1]) / 100; + lightIntensity = intensities[1] + data * (intensities[2] - intensities[1]) / 100; } else { - lightIntensity = dword_453F90[0] + data * (dword_453F90[1] - dword_453F90[0]) / 100; + lightIntensity = intensities[0] + data * (intensities[1] - intensities[0]) / 100; } - lightSetLightLevel(lightIntensity, true); + lightSetAmbientIntensity(lightIntensity, true); } // game_time diff --git a/src/inventory.cc b/src/inventory.cc index bf44d3c..2d1b832 100644 --- a/src/inventory.cc +++ b/src/inventory.cc @@ -3315,7 +3315,7 @@ int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4) int lightIntensity; int lightDistance; if (critter == gDude) { - lightIntensity = LIGHT_LEVEL_MAX; + lightIntensity = LIGHT_INTENSITY_MAX; lightDistance = 4; } else { Proto* proto; diff --git a/src/item.cc b/src/item.cc index 4c363fe..9f29d36 100644 --- a/src/item.cc +++ b/src/item.cc @@ -1494,7 +1494,7 @@ bool weaponCanBeReloadedWith(Object* weapon, Object* ammo) { if (weapon->pid == PROTO_ID_SOLAR_SCORCHER) { // Check light level to recharge solar scorcher. - if (lightGetLightLevel() > 62259) { + if (lightGetAmbientIntensity() > LIGHT_INTENSITY_MAX * 0.95) { return true; } diff --git a/src/light.cc b/src/light.cc index 1077b89..60bd80d 100644 --- a/src/light.cc +++ b/src/light.cc @@ -13,50 +13,55 @@ namespace fallout { #define LIGHT_LEVEL_NIGHT_VISION_BONUS (65536 / 5) // 0x51923C -static int gLightLevel = LIGHT_LEVEL_MAX; +static int gAmbientIntensity = LIGHT_INTENSITY_MAX; // light intensity per elevation per tile // 0x59E994 -static int gLightIntensity[ELEVATION_COUNT][HEX_GRID_SIZE]; +static int gTileIntensity[ELEVATION_COUNT][HEX_GRID_SIZE]; // 0x47A8F0 int lightInit() { - lightResetIntensity(); + lightResetTileIntensity(); return 0; } -// 0x47A8F8 -int lightGetLightLevel() +// 0x47A8F0 +void lightReset() { - return gLightLevel; + lightResetTileIntensity(); +} + +// 0x47A8F0 +void lightExit() +{ + lightResetTileIntensity(); +} + +// 0x47A8F8 +int lightGetAmbientIntensity() +{ + return gAmbientIntensity; } // 0x47A908 -void lightSetLightLevel(int lightLevel, bool shouldUpdateScreen) +void lightSetAmbientIntensity(int intensity, bool shouldUpdateScreen) { - int normalizedLightLevel = lightLevel + perkGetRank(gDude, PERK_NIGHT_VISION) * LIGHT_LEVEL_NIGHT_VISION_BONUS; + int adjustedIntensity = intensity + perkGetRank(gDude, PERK_NIGHT_VISION) * LIGHT_LEVEL_NIGHT_VISION_BONUS; + int normalizedIntensity = std::clamp(adjustedIntensity, LIGHT_INTENSITY_MIN, LIGHT_INTENSITY_MAX); - if (normalizedLightLevel < LIGHT_LEVEL_MIN) { - normalizedLightLevel = LIGHT_LEVEL_MIN; - } - - if (normalizedLightLevel > LIGHT_LEVEL_MAX) { - normalizedLightLevel = LIGHT_LEVEL_MAX; - } - - int oldLightLevel = gLightLevel; - gLightLevel = normalizedLightLevel; + int oldAmbientIntensity = gAmbientIntensity; + gAmbientIntensity = normalizedIntensity; if (shouldUpdateScreen) { - if (oldLightLevel != normalizedLightLevel) { + if (oldAmbientIntensity != normalizedIntensity) { tileWindowRefresh(); } } } // 0x47A980 -int _light_get_tile(int elevation, int tile) +int lightGetTileIntensity(int elevation, int tile) { if (!elevationIsValid(elevation)) { return 0; @@ -66,11 +71,11 @@ int _light_get_tile(int elevation, int tile) return 0; } - return std::min(gLightIntensity[elevation][tile], LIGHT_LEVEL_MAX); + return std::min(gTileIntensity[elevation][tile], LIGHT_INTENSITY_MAX); } // 0x47A9C4 -int lightGetIntensity(int elevation, int tile) +int lightGetTrueTileIntensity(int elevation, int tile) { if (!elevationIsValid(elevation)) { return 0; @@ -80,11 +85,11 @@ int lightGetIntensity(int elevation, int tile) return 0; } - return gLightIntensity[elevation][tile]; + return gTileIntensity[elevation][tile]; } // 0x47A9EC -void lightSetIntensity(int elevation, int tile, int lightIntensity) +void lightSetTileIntensity(int elevation, int tile, int intensity) { if (!elevationIsValid(elevation)) { return; @@ -94,11 +99,11 @@ void lightSetIntensity(int elevation, int tile, int lightIntensity) return; } - gLightIntensity[elevation][tile] = lightIntensity; + gTileIntensity[elevation][tile] = intensity; } // 0x47AA10 -void lightIncreaseIntensity(int elevation, int tile, int lightIntensity) +void lightIncreaseTileIntensity(int elevation, int tile, int intensity) { if (!elevationIsValid(elevation)) { return; @@ -108,11 +113,11 @@ void lightIncreaseIntensity(int elevation, int tile, int lightIntensity) return; } - gLightIntensity[elevation][tile] += lightIntensity; + gTileIntensity[elevation][tile] += intensity; } // 0x47AA48 -void lightDecreaseIntensity(int elevation, int tile, int lightIntensity) +void lightDecreaseTileIntensity(int elevation, int tile, int intensity) { if (!elevationIsValid(elevation)) { return; @@ -122,15 +127,15 @@ void lightDecreaseIntensity(int elevation, int tile, int lightIntensity) return; } - gLightIntensity[elevation][tile] -= lightIntensity; + gTileIntensity[elevation][tile] -= intensity; } // 0x47AA84 -void lightResetIntensity() +void lightResetTileIntensity() { for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) { for (int tile = 0; tile < HEX_GRID_SIZE; tile++) { - gLightIntensity[elevation][tile] = 655; + gTileIntensity[elevation][tile] = 655; } } } diff --git a/src/light.h b/src/light.h index 414754e..d52930a 100644 --- a/src/light.h +++ b/src/light.h @@ -3,20 +3,22 @@ namespace fallout { -#define LIGHT_LEVEL_MIN (65536 / 4) -#define LIGHT_LEVEL_MAX 65536 +#define LIGHT_INTENSITY_MIN (65536 / 4) +#define LIGHT_INTENSITY_MAX 65536 typedef void AdjustLightIntensityProc(int elevation, int tile, int intensity); int lightInit(); -int lightGetLightLevel(); -void lightSetLightLevel(int lightLevel, bool shouldUpdateScreen); -int _light_get_tile(int elevation, int tile); -int lightGetIntensity(int elevation, int tile); -void lightSetIntensity(int elevation, int tile, int intensity); -void lightIncreaseIntensity(int elevation, int tile, int intensity); -void lightDecreaseIntensity(int elevation, int tile, int intensity); -void lightResetIntensity(); +void lightReset(); +void lightExit(); +int lightGetAmbientIntensity(); +void lightSetAmbientIntensity(int intensity, bool shouldUpdateScreen); +int lightGetTileIntensity(int elevation, int tile); +int lightGetTrueTileIntensity(int elevation, int tile); +void lightSetTileIntensity(int elevation, int tile, int intensity); +void lightIncreaseTileIntensity(int elevation, int tile, int intensity); +void lightDecreaseTileIntensity(int elevation, int tile, int intensity); +void lightResetTileIntensity(); } // namespace fallout diff --git a/src/map.cc b/src/map.cc index 5269ec7..4166e60 100644 --- a/src/map.cc +++ b/src/map.cc @@ -924,7 +924,7 @@ static int mapLoad(File* stream) goto err; } - lightSetLightLevel(LIGHT_LEVEL_MAX, false); + lightSetAmbientIntensity(LIGHT_INTENSITY_MAX, false); objectSetLocation(gDude, gCenterTile, gElevation, NULL); objectSetRotation(gDude, gEnteringRotation, NULL); gMapHeader.field_34 = wmMapMatchNameToIdx(gMapHeader.name); diff --git a/src/object.cc b/src/object.cc index 71861ac..0b3fb40 100644 --- a/src/object.cc +++ b/src/object.cc @@ -379,7 +379,7 @@ void objectsReset() textObjectsReset(); _obj_remove_all(); memset(_obj_seen, 0, 5001); - lightResetIntensity(); + lightReset(); } } @@ -396,7 +396,7 @@ void objectsExit() // NOTE: Uninline. _obj_blend_table_exit(); - lightResetIntensity(); + lightExit(); // NOTE: Uninline. _obj_render_table_exit(); @@ -763,7 +763,7 @@ void _obj_render_pre_roof(Rect* rect, int elevation) return; } - int ambientLight = lightGetLightLevel(); + int ambientIntensity = lightGetAmbientIntensity(); int minX = updatedRect.left - 320; int minY = updatedRect.top - 240; int maxX = updatedRect.right + 320; @@ -804,14 +804,14 @@ void _obj_render_pre_roof(Rect* rect, int elevation) for (int i = 0; i < gObjectsUpdateAreaHexSize; i++) { int offsetIndex = *orders++; if (updateAreaHexHeight > _offsetDivTable[offsetIndex] && updateAreaHexWidth > _offsetModTable[offsetIndex]) { - int light; + int lightIntensity; ObjectListNode* objectListNode = hexGridTileIsValid(topLeftTile + offsets[offsetIndex]) ? gObjectListHeadByTile[topLeftTile + offsets[offsetIndex]] : NULL; if (objectListNode != NULL) { - // NOTE: Calls `_light_get_tile` twice. - light = std::max(ambientLight, _light_get_tile(elevation, objectListNode->obj->tile)); + // NOTE: Calls `lightGetTileIntensity` twice. + lightIntensity = std::max(ambientIntensity, lightGetTileIntensity(elevation, objectListNode->obj->tile)); } while (objectListNode != NULL) { @@ -825,7 +825,7 @@ void _obj_render_pre_roof(Rect* rect, int elevation) } if ((objectListNode->obj->flags & OBJECT_HIDDEN) == 0) { - _obj_render_object(objectListNode->obj, &updatedRect, light); + _obj_render_object(objectListNode->obj, &updatedRect, lightIntensity); if ((objectListNode->obj->outline & OUTLINE_TYPE_MASK) != 0) { if ((objectListNode->obj->outline & OUTLINE_DISABLED) == 0 && _outlineCount < 100) { @@ -845,12 +845,12 @@ void _obj_render_pre_roof(Rect* rect, int elevation) } for (int i = 0; i < renderCount; i++) { - int light; + int lightIntensity; ObjectListNode* objectListNode = _renderTable[i]; if (objectListNode != NULL) { - // NOTE: Calls `_light_get_tile` twice. - light = std::max(ambientLight, _light_get_tile(elevation, objectListNode->obj->tile)); + // NOTE: Calls `lightGetTileIntensity` twice. + lightIntensity = std::max(ambientIntensity, lightGetTileIntensity(elevation, objectListNode->obj->tile)); } while (objectListNode != NULL) { @@ -861,7 +861,7 @@ void _obj_render_pre_roof(Rect* rect, int elevation) if (elevation == objectListNode->obj->elevation) { if ((objectListNode->obj->flags & OBJECT_HIDDEN) == 0) { - _obj_render_object(object, &updatedRect, light); + _obj_render_object(object, &updatedRect, lightIntensity); if ((objectListNode->obj->outline & OUTLINE_TYPE_MASK) != 0) { if ((objectListNode->obj->outline & OUTLINE_DISABLED) == 0 && _outlineCount < 100) { @@ -1721,7 +1721,7 @@ int objectRotateCounterClockwise(Object* obj, Rect* dirtyRect) // 0x48AC54 void _obj_rebuild_all_light() { - lightResetIntensity(); + lightResetTileIntensity(); for (int tile = 0; tile < HEX_GRID_SIZE; tile++) { ObjectListNode* objectListNode = gObjectListHeadByTile[tile]; @@ -1762,22 +1762,22 @@ int objectSetLight(Object* obj, int lightDistance, int lightIntensity, Rect* rec // 0x48AD04 int objectGetLightIntensity(Object* obj) { - int lightLevel = lightGetLightLevel(); - int lightIntensity = lightGetIntensity(obj->elevation, obj->tile); + int ambientIntensity = lightGetAmbientIntensity(); + int tileIntensity = lightGetTrueTileIntensity(obj->elevation, obj->tile); if (obj == gDude) { - lightIntensity -= gDude->lightIntensity; + tileIntensity -= gDude->lightIntensity; } - if (lightIntensity >= lightLevel) { - if (lightIntensity > 0x10000) { - lightIntensity = 0x10000; + if (tileIntensity >= ambientIntensity) { + if (tileIntensity > LIGHT_INTENSITY_MAX) { + tileIntensity = LIGHT_INTENSITY_MAX; } } else { - lightIntensity = lightLevel; + tileIntensity = ambientIntensity; } - return lightIntensity; + return tileIntensity; } // 0x48AD48 @@ -3993,7 +3993,7 @@ static int _obj_adjust_light(Object* obj, int a2, Rect* rect) return -1; } - AdjustLightIntensityProc* adjustLightIntensity = a2 ? lightDecreaseIntensity : lightIncreaseIntensity; + AdjustLightIntensityProc* adjustLightIntensity = a2 ? lightDecreaseTileIntensity : lightIncreaseTileIntensity; adjustLightIntensity(obj->elevation, obj->tile, obj->lightIntensity); Rect objectRect; diff --git a/src/tile.cc b/src/tile.cc index c3a9e9b..f52705a 100644 --- a/src/tile.cc +++ b/src/tile.cc @@ -1226,7 +1226,7 @@ void tileRenderRoofsInRect(Rect* rect, int elevation) minY = gSquareGridHeight - 1; } - int light = lightGetLightLevel(); + int light = lightGetAmbientIntensity(); int baseSquareTile = gSquareGridWidth * minY; @@ -1449,7 +1449,7 @@ void tileRenderFloorsInRect(Rect* rect, int elevation) minY = gSquareGridHeight - 1; } - lightGetLightLevel(); + lightGetAmbientIntensity(); int baseSquareTile = gSquareGridWidth * minY; @@ -1660,10 +1660,10 @@ static void tileRenderFloor(int fid, int x, int y, Rect* rect) tile = tileFromScreenXY(savedX, savedY + 13, gElevation); if (tile != -1) { int parity = tile & 1; - int ambientIntensity = lightGetLightLevel(); + int ambientIntensity = lightGetAmbientIntensity(); for (int i = 0; i < 10; i++) { - // NOTE: Calls `_light_get_tile` twice. - _verticies[i].intensity = std::max(_light_get_tile(elev, tile + _verticies[i].offsets[parity]), ambientIntensity); + // NOTE: Calls `lightGetTileIntensity` twice. + _verticies[i].intensity = std::max(lightGetTileIntensity(elev, tile + _verticies[i].offsets[parity]), ambientIntensity); } int v23 = 0;