Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/ModelExtrasAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ void ME_SetFogLights(CVehicle *pVeh, bool on) {
}
}

bool ME_GetHighBeam(CVehicle *pVeh) {
if (!pVeh) return false;
auto &data = LightManager::m_VehData.Get(pVeh);
return data.bLongLightsOn;
}

void ME_SetHighBeam(CVehicle *pVeh, bool on) {
if (!pVeh) return;
auto &data = LightManager::m_VehData.Get(pVeh);
data.bLongLightsOn = on;
data.fHighBeamFactor = on ? 1.0f : 0.0f;
}

float ME_GetLightInertia(CVehicle *pVeh, ME_LightID lightId) {
if (!pVeh) return 0.0f;
Expand Down Expand Up @@ -211,10 +223,10 @@ bool ME_IsLightDamaged(CVehicle *pVeh, ME_LightID lightId, int dummyIndex) {
if (dummyIndex >= 0 && dummyIndex < static_cast<int>(data.dummies[matType].size())) {
return CarUtil::IsDummyDamaged(pVeh, data.dummies[matType][dummyIndex]->GetRef());
}
if (matType == eMaterialType::HeadLightLeft) return CarUtil::IsLightDamaged(pVeh, eLights::LIGHT_FRONT_LEFT);
if (matType == eMaterialType::HeadLightRight) return CarUtil::IsLightDamaged(pVeh, eLights::LIGHT_FRONT_RIGHT);
if (matType == eMaterialType::TailLightLeft || matType == eMaterialType::BrakeLightLeft) return CarUtil::IsLightDamaged(pVeh, eLights::LIGHT_REAR_LEFT);
if (matType == eMaterialType::TailLightRight || matType == eMaterialType::BrakeLightRight) return CarUtil::IsLightDamaged(pVeh, eLights::LIGHT_REAR_RIGHT);
if (matType == eMaterialType::HeadLightLeft || matType == eMaterialType::HighBeamLeft) return CarUtil::IsLightDamaged(pVeh, eLights::LIGHT_FRONT_LEFT) || CarUtil::IsPanelDamaged(pVeh, ePanels::WING_FRONT_LEFT);
if (matType == eMaterialType::HeadLightRight || matType == eMaterialType::HighBeamRight) return CarUtil::IsLightDamaged(pVeh, eLights::LIGHT_FRONT_RIGHT) || CarUtil::IsPanelDamaged(pVeh, ePanels::WING_FRONT_RIGHT);
if (matType == eMaterialType::TailLightLeft || matType == eMaterialType::BrakeLightLeft || matType == eMaterialType::ReverseLightLeft) return CarUtil::IsLightDamaged(pVeh, eLights::LIGHT_REAR_LEFT) || CarUtil::IsPanelDamaged(pVeh, ePanels::WING_REAR_LEFT);
if (matType == eMaterialType::TailLightRight || matType == eMaterialType::BrakeLightRight || matType == eMaterialType::ReverseLightRight) return CarUtil::IsLightDamaged(pVeh, eLights::LIGHT_REAR_RIGHT) || CarUtil::IsPanelDamaged(pVeh, ePanels::WING_REAR_RIGHT);
return false;
}

Expand Down Expand Up @@ -956,6 +968,9 @@ float ME_GetLightShadowDistance() {
return RenderUtil::GetLightShadowDistance();
}

float ME_GetHighBeamPointLightMul() {
return LightsConfig::Get().fHighBeamPointLightMul;
}

float ME_GetSirenPointLightMul() {
return LightsConfig::Get().fSirenPointLightMul;
Expand Down
5 changes: 5 additions & 0 deletions src/ModelExtrasAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ enum ME_LightID
ME_ReverseLightRight,
ME_BrakeLightLeft,
ME_BrakeLightRight,
ME_HighBeamLeft,
ME_HighBeamRight,
ME_AllDayLight,
ME_DayLight,
ME_NightLight,
Expand Down Expand Up @@ -162,6 +164,8 @@ extern "C"
ME_WRAPPER void ME_SetLightOverride(CVehicle *pVeh, int overrideMode);
ME_WRAPPER bool ME_GetFogLights(CVehicle *pVeh);
ME_WRAPPER void ME_SetFogLights(CVehicle *pVeh, bool on);
ME_WRAPPER bool ME_GetHighBeam(CVehicle *pVeh);
ME_WRAPPER void ME_SetHighBeam(CVehicle *pVeh, bool on);
ME_WRAPPER float ME_GetLightInertia(CVehicle *pVeh, ME_LightID lightId);
ME_WRAPPER bool ME_GetLightColor(CVehicle *pVeh, ME_LightID lightId, ME_Color *onColor, ME_Color *offColor);
ME_WRAPPER float ME_GetLightFactor(CVehicle *pVeh, ME_LightID lightId);
Expand Down Expand Up @@ -301,6 +305,7 @@ extern "C"
ME_WRAPPER float ME_GetCoronaDistanceMul();
ME_WRAPPER float ME_GetCoronaNearClip();
ME_WRAPPER float ME_GetLightShadowDistance();
ME_WRAPPER float ME_GetHighBeamPointLightMul();
ME_WRAPPER float ME_GetSirenPointLightMul();
ME_WRAPPER float ME_GetPointLightIntensity();
ME_WRAPPER bool ME_IsAutoIndicatorsOnSteerEnabled();
Expand Down
2 changes: 2 additions & 0 deletions src/enums/materialtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ enum eMaterialType
ReverseLightRight,
BrakeLightLeft,
BrakeLightRight,
HighBeamLeft,
HighBeamRight,
AllDayLight,
DayLight,
NightLight,
Expand Down
3 changes: 3 additions & 0 deletions src/features/core/colors.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#define VEHCOL_HEADLIGHT_LEFT CRGBA(255, 175, 0, 255)
#define VEHCOL_HEADLIGHT_RIGHT CRGBA(0, 255, 200, 255)

#define VEHCOL_HIGHBEAM_LEFT CRGBA(255, 172, 0, 255)
#define VEHCOL_HIGHBEAM_RIGHT CRGBA(0, 255, 197, 255)

#define VEHCOL_TAILLIGHT_LEFT CRGBA(185, 255, 0, 255)
#define VEHCOL_TAILLIGHT_RIGHT CRGBA(255, 60, 0, 255)

Expand Down
126 changes: 91 additions & 35 deletions src/features/lights/components/headlight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@
#include "utils/audiomgr.h"
#include "utils/render.h"
#include "../damage.h"
#include "defines.h"
#include <CWeather.h>

extern bool gbProperShadersDetected;

void HeadlightComponent::RegisterMaterials(std::unordered_map<uint32_t, eMaterialType>& matMap) {
matMap[VEHCOL_HEADLIGHT_LEFT.ToInt()] = eMaterialType::HeadLightLeft;
matMap[VEHCOL_HEADLIGHT_RIGHT.ToInt()] = eMaterialType::HeadLightRight;
matMap[VEHCOL_HIGHBEAM_LEFT.ToInt()] = eMaterialType::HighBeamLeft;
matMap[VEHCOL_HIGHBEAM_RIGHT.ToInt()] = eMaterialType::HighBeamRight;
}

eMaterialType HeadlightComponent::GetMatType(CRGBA matCol) {
if (matCol == VEHCOL_HEADLIGHT_LEFT) return eMaterialType::HeadLightLeft;
if (matCol == VEHCOL_HEADLIGHT_RIGHT) return eMaterialType::HeadLightRight;
if (matCol == VEHCOL_HIGHBEAM_LEFT) return eMaterialType::HighBeamLeft;
if (matCol == VEHCOL_HIGHBEAM_RIGHT) return eMaterialType::HighBeamRight;
return eMaterialType::UnknownMaterial;
}

Expand Down Expand Up @@ -61,7 +66,6 @@ bool HeadlightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const
}
DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame);
c.dummyPos = eDummyPos::Front;
c.lightType = eMaterialType::HeadLightLeft;
c.corona.size = LightsConfig::Get().gfHeadLightCoronaSize;
c.corona.color = {250, 250, 250, static_cast<unsigned char>(LightsConfig::Get().gHeadLightCoronaIntensity)};
c.shadow.color = {250, 250, 250, static_cast<unsigned char>(LightsConfig::Get().gHeadLightShadowIntensity)};
Expand All @@ -77,13 +81,13 @@ bool HeadlightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const
data.dummies[c.lightType].push_back(VehicleDummy(c));
} else {
bool dummyIsLeft = (c.frame->modelling.pos.x < 0.0f);
c.mirroredX = dummyIsLeft;
c.mirroredX = !dummyIsLeft;
c.lightType = eMaterialType::HeadLightLeft;
data.dummies[c.lightType].push_back(VehicleDummy(c));
data.dummies[eMaterialType::HeadLightLeft].push_back(VehicleDummy(c));

c.mirroredX = !dummyIsLeft;
c.mirroredX = dummyIsLeft;
c.lightType = eMaterialType::HeadLightRight;
data.dummies[c.lightType].push_back(VehicleDummy(c));
data.dummies[eMaterialType::HeadLightRight].push_back(VehicleDummy(c));
}
return true;
}
Expand All @@ -108,6 +112,58 @@ bool HeadlightComponent::TryRegisterDummy(CVehicle* pVeh, RwFrame* pFrame, const
return true;
}

if (name == "highbeam_l" || name == "highbeam_r" || name == "highbeams_l" || name == "highbeams_r") {
if (pFrame && !rwLinkListEmpty(&pFrame->objectList)) {
return false;
}
DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame);
c.dummyPos = eDummyPos::Front;
bool isLeft = (name == "highbeam_l" || name == "highbeams_l");
c.lightType = isLeft ? eMaterialType::HighBeamLeft : eMaterialType::HighBeamRight;
c.corona.size = LightsConfig::Get().gfHeadLightCoronaSize;
c.corona.color = {250, 250, 250, static_cast<unsigned char>(LightsConfig::Get().gHeadLightCoronaIntensity)};
c.shadow.color = {250, 250, 250, static_cast<unsigned char>(LightsConfig::Get().gHeadLightShadowIntensity)};
c.shadow.size = LightsConfig::Get().gfHeadLightShadowSize;
c.corona.lightingType = eLightingMode::Directional;
c.shadow.render = false;
c.mirroredX = false;

data.dummies[c.lightType].push_back(VehicleDummy(c));
return true;
}

if (name == "highbeam" || name == "highbeams") {
if (pFrame && !rwLinkListEmpty(&pFrame->objectList)) {
return false;
}
DummyConfig c = LightManager::CreateBaseConfig(pVeh, pFrame);
c.dummyPos = eDummyPos::Front;
c.corona.size = LightsConfig::Get().gfHeadLightCoronaSize;
c.corona.color = {250, 250, 250, static_cast<unsigned char>(LightsConfig::Get().gHeadLightCoronaIntensity)};
c.shadow.color = {250, 250, 250, static_cast<unsigned char>(LightsConfig::Get().gHeadLightShadowIntensity)};
c.shadow.size = LightsConfig::Get().gfHeadLightShadowSize;
c.corona.lightingType = eLightingMode::Directional;
c.shadow.render = false;

bool isBike = (pVeh->m_nVehicleSubClass == VEHICLE_BIKE);

if (isBike) {
c.mirroredX = false;
c.lightType = eMaterialType::HighBeamLeft;
data.dummies[c.lightType].push_back(VehicleDummy(c));
} else {
bool dummyIsLeft = (c.frame->modelling.pos.x < 0.0f);
c.mirroredX = !dummyIsLeft;
c.lightType = eMaterialType::HighBeamLeft;
data.dummies[eMaterialType::HighBeamLeft].push_back(VehicleDummy(c));

c.mirroredX = dummyIsLeft;
c.lightType = eMaterialType::HighBeamRight;
data.dummies[eMaterialType::HighBeamRight].push_back(VehicleDummy(c));
}
return true;
}

std::string lowerName;
lowerName.reserve(name.size());
for (char ch : name) {
Expand Down Expand Up @@ -171,26 +227,6 @@ void HeadlightComponent::Process(CVehicle* pVeh, VehLightData& data) {
data.bLongLightsOn = !data.bLongLightsOn;
AudioMgr::PlaySwitchSound(pVeh);
}
} else if (pVeh->m_fHealth > 0.0f) {
if (CarUtil::IsLightsForcedOff(pVeh) || (Util::IsEngineOff(pVeh) && !CarUtil::IsLightsForcedOn(pVeh) && !pVeh->bLightsOn && !isAlarmActive)) {
return;
}

if (CVector::Distance(pVeh->GetPosition(), TheCamera.GetPosition()) < 300.0f || pVeh->GetIsOnScreen()) {
bool isLeftFrontOk = !Util::IsLightDamaged(pVeh, eLights::LIGHT_FRONT_LEFT);
bool isRightFrontOk = !Util::IsLightDamaged(pVeh, eLights::LIGHT_FRONT_RIGHT);

if (isHeadlightsActive && AreHeadlightsOpen(pVeh, data)) {
bool isFoggy = Util::IsFoggy();
std::string texName = data.bLongLightsOn ? "headlight_long" : "headlight_short";
bool shadow = !gbProperShadersDetected;
bool highlight = isFoggy || data.bLongLightsOn;

LightManager::RenderLight(pVeh, data, eMaterialType::HeadLightLeft, isLeftFrontOk, shadow ? texName : "", LightsConfig::Get().headlightSz, highlight);
LightManager::RenderLight(pVeh, data, eMaterialType::HeadLightRight, isRightFrontOk, shadow ? texName : "", LightsConfig::Get().headlightSz, highlight);
data.nHeadlightTickFrame = CTimer::m_FrameCounter;
}
}
}
}

Expand All @@ -205,9 +241,8 @@ void HeadlightComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehL
bool isNightOrOn = (CarUtil::AreLightsOn(pControlVeh) || isAlarmLightOn);
if (isAlarmActive && !isAlarmLightOn) {
isNightOrOn = false;
pControlVeh->m_renderLights.m_bLeftFront = false;
pControlVeh->m_renderLights.m_bRightFront = false;
}

bool isOpen = AreHeadlightsOpen(pControlVeh, data);

auto damage = LightDamageState::Get(pControlVeh, pTowedVeh);
Expand All @@ -219,20 +254,21 @@ void HeadlightComponent::Render(CVehicle* pControlVeh, CVehicle* pTowedVeh, VehL

if (!isNightOrOn || !isOpen) return;

bool bTickRegistered = (data.nHeadlightTickFrame == CTimer::m_FrameCounter);
bool isFoggy = Util::IsFoggy();
std::string texName = data.bLongLightsOn ? "headlight_long" : "headlight_short";
bool shadow = !gbProperShadersDetected;
bool highlight = isFoggy || data.bLongLightsOn;

if (isHeadlightLeftOk || isHeadlightRightOk) {
pControlVeh->m_renderLights.m_bLeftFront = isHeadlightLeftOk;
pControlVeh->m_renderLights.m_bRightFront = isHeadlightRightOk;
if (isHeadlightLeftOk) {
LightManager::RenderLights(pControlVeh, pTowedVeh, data, eMaterialType::HeadLightLeft, true, shadow ? texName : "", LightsConfig::Get().headlightSz, highlight, true, bTickRegistered);
if (isHeadlightLeftOk) {
LightManager::RenderLights(pControlVeh, pTowedVeh, data, eMaterialType::HeadLightLeft, true, shadow ? texName : "", LightsConfig::Get().headlightSz, highlight, true);
if (data.bLongLightsOn) {
LightManager::RenderLights(pControlVeh, pTowedVeh, data, eMaterialType::HighBeamLeft, true, "", LightsConfig::Get().headlightSz, isFoggy, true);
}
if (isHeadlightRightOk) {
LightManager::RenderLights(pControlVeh, pTowedVeh, data, eMaterialType::HeadLightRight, true, shadow ? texName : "", LightsConfig::Get().headlightSz, highlight, true, bTickRegistered);
}
if (isHeadlightRightOk) {
LightManager::RenderLights(pControlVeh, pTowedVeh, data, eMaterialType::HeadLightRight, true, shadow ? texName : "", LightsConfig::Get().headlightSz, highlight, true);
if (data.bLongLightsOn) {
LightManager::RenderLights(pControlVeh, pTowedVeh, data, eMaterialType::HighBeamRight, true, "", LightsConfig::Get().headlightSz, isFoggy, true);
}
}
}
Expand Down Expand Up @@ -267,6 +303,26 @@ void HeadlightComponent::ProcessPointLights(CVehicle* pVeh, VehLightData& data)
RenderUtil::RegisterHeadlightPointLight(&e->Get(), rangeMul);
}
}

if (data.bLongLightsOn) {
for (eMaterialType type : {eMaterialType::HighBeamLeft, eMaterialType::HighBeamRight}) {
if (!LightManager::IsDummyAvailable(data, type) || !data.bLightStates[type]) {
continue;
}

bool isLeft = (type == eMaterialType::HighBeamLeft);
eLights lightEnum = isLeft ? eLights::LIGHT_FRONT_LEFT : eLights::LIGHT_FRONT_RIGHT;
ePanels wingEnum = isLeft ? ePanels::WING_FRONT_LEFT : ePanels::WING_FRONT_RIGHT;
if (Util::IsLightDamaged(pVeh, lightEnum) || Util::IsPanelDamaged(pVeh, wingEnum)) {
continue;
}

for (auto& e : data.dummies[type]) {
e->Update();
RenderUtil::RegisterHeadlightPointLight(&e->Get(), rangeMul);
}
}
}
}
}

8 changes: 4 additions & 4 deletions src/features/lights/damage.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ struct LightDamageState {

static LightDamageState Get(CVehicle* pControlVeh, CVehicle* pTowedVeh) {
LightDamageState state;
state.isHeadlightLeftOk = !(Util::IsLightDamaged(pControlVeh, eLights::LIGHT_FRONT_LEFT) || Util::IsPanelDamaged(pControlVeh, ePanels::WING_FRONT_LEFT));
state.isHeadlightRightOk = !(Util::IsLightDamaged(pControlVeh, eLights::LIGHT_FRONT_RIGHT) || Util::IsPanelDamaged(pControlVeh, ePanels::WING_FRONT_RIGHT));
state.isHeadlightLeftOk = !Util::IsLightDamaged(pControlVeh, eLights::LIGHT_FRONT_LEFT) && !Util::IsPanelDamaged(pControlVeh, ePanels::WING_FRONT_LEFT);
state.isHeadlightRightOk = !Util::IsLightDamaged(pControlVeh, eLights::LIGHT_FRONT_RIGHT) && !Util::IsPanelDamaged(pControlVeh, ePanels::WING_FRONT_RIGHT);
state.isFrontLeftOk = state.isHeadlightLeftOk || pControlVeh->bSirenOrAlarm;
state.isFrontRightOk = state.isHeadlightRightOk || pControlVeh->bSirenOrAlarm;
state.isRearLeftOk = !(Util::IsLightDamaged(pTowedVeh, eLights::LIGHT_REAR_LEFT) || Util::IsPanelDamaged(pTowedVeh, ePanels::WING_REAR_LEFT));
state.isRearRightOk = !(Util::IsLightDamaged(pTowedVeh, eLights::LIGHT_REAR_RIGHT) || Util::IsPanelDamaged(pTowedVeh, ePanels::WING_REAR_RIGHT));
state.isRearLeftOk = !Util::IsLightDamaged(pTowedVeh, eLights::LIGHT_REAR_LEFT) && !Util::IsPanelDamaged(pTowedVeh, ePanels::WING_REAR_LEFT);
state.isRearRightOk = !Util::IsLightDamaged(pTowedVeh, eLights::LIGHT_REAR_RIGHT) && !Util::IsPanelDamaged(pTowedVeh, ePanels::WING_REAR_RIGHT);
state.isMiddleLeftOk = !Util::IsPanelDamaged(pControlVeh, ePanels::WING_FRONT_LEFT);
state.isMiddleRightOk = !Util::IsPanelDamaged(pControlVeh, ePanels::WING_FRONT_RIGHT);
state.isFrontBumperOk = !Util::IsPanelDamaged(pControlVeh, ePanels::BUMP_FRONT);
Expand Down
2 changes: 0 additions & 2 deletions src/features/lights/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ struct VehLightData {
std::array<std::vector<VehicleDummy>, eMaterialType::TotalMaterial> dummies;

bool bLightStates[eMaterialType::TotalMaterial];
unsigned int nHeadlightTickFrame = 0;
bool bHasVehFuncsPopUp = false;
bool bAutoNightLights = false;
unsigned int nHeadlightsTurnedOnTime = 0;
Expand Down Expand Up @@ -179,7 +178,6 @@ struct VehLightData {
vec.clear();
}
std::copy(std::begin(other.bLightStates), std::end(other.bLightStates), std::begin(bLightStates));
nHeadlightTickFrame = other.nHeadlightTickFrame;
}
return *this;
}
Expand Down
Loading