diff --git a/src/entities/Vehicle.h b/src/entities/Vehicle.h index c62605c9..16f11763 100644 --- a/src/entities/Vehicle.h +++ b/src/entities/Vehicle.h @@ -8,7 +8,11 @@ class CVehicle : public CPhysical { public: // 0x128 - uint8 stuff1[120]; + uint8 stuff1[116]; + uint8 m_currentColour1; + uint8 m_currentColour2; +uint8 m_extra1; +uint8 m_extra2; int16 m_nAlarmState; CPed *pDriver; CPed *pPassengers[8]; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index d64cf939..8b188345 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -203,6 +203,7 @@ enum MI_FATFEMALE01, MI_FATFEMALE02, + MI_FIRETRUCK = 97, MI_PREDATOR = 120, MI_RHINO = 122, MI_TRAIN = 124, diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp index 575d0360..5e3a77fe 100644 --- a/src/modelinfo/VehicleModelInfo.cpp +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -7,6 +7,10 @@ #include "TxdStore.h" #include "Weather.h" #include "VisibilityPlugins.h" +#include "FileMgr.h" +#include "World.h" +#include "Vehicle.h" +#include "ModelIndices.h" #include "ModelInfo.h" int8 *CVehicleModelInfo::ms_compsToUse = (int8*)0x5FF2EC; // -2, -2 @@ -280,6 +284,16 @@ CVehicleModelInfo::HideDamagedAtomicCB(RpAtomic *atomic, void *data) return atomic; } +RpAtomic* +CVehicleModelInfo::HideAllComponentsAtomicCB(RpAtomic *atomic, void *data) +{ + if(CVisibilityPlugins::GetAtomicId(atomic) & (int)data) + RpAtomicSetFlags(atomic, 0); + else + RpAtomicSetFlags(atomic, rpATOMICRENDER); + return atomic; +} + RpMaterial* CVehicleModelInfo::HasAlphaMaterialCB(RpMaterial *material, void *data) { @@ -758,6 +772,183 @@ CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2) } } +void +CVehicleModelInfo::ChooseVehicleColour(uint8 &col1, uint8 &col2) +{ + if(m_numColours == 0){ + col1 = 0; + col2 = 0; + }else{ + m_lastColorVariation = (m_lastColorVariation+1) % m_numColours; + col1 = m_colours1[m_lastColorVariation]; + col2 = m_colours2[m_lastColorVariation]; + if(m_numColours > 1){ + CVehicle *veh = FindPlayerVehicle(); + if(veh && CModelInfo::GetModelInfo(veh->GetModelIndex()) == this && + veh->m_currentColour1 == col1 && + veh->m_currentColour2 == col2){ + m_lastColorVariation = (m_lastColorVariation+1) % m_numColours; + col1 = m_colours1[m_lastColorVariation]; + col2 = m_colours2[m_lastColorVariation]; + } + } + } +} + +void +CVehicleModelInfo::AvoidSameVehicleColour(uint8 *col1, uint8 *col2) +{ + int i, n; + + if(m_numColours > 1) + for(i = 0; i < 8; i++){ + if(*col1 != m_lastColour1 || *col2 != m_lastColour2) + break; + n = CGeneral::GetRandomNumberInRange(0, m_numColours); + *col1 = m_colours1[n]; + *col2 = m_colours2[n]; + } + m_lastColour1 = *col1; + m_lastColour2 = *col2; +} + +RwTexture* +CreateCarColourTexture(uint8 r, uint8 g, uint8 b) +{ + RwImage *img; + RwRaster *ras; + RwTexture *tex; + RwUInt8 *pixels; + RwInt32 width, height, depth, format; + + img = RwImageCreate(2, 2, 32); + pixels = (RwUInt8*)RwMalloc(2*2*4); + pixels[0] = r; + pixels[1] = g; + pixels[2] = b; + pixels[3] = 0xFF; + pixels[4] = r; + pixels[5] = g; + pixels[6] = b; + pixels[7] = 0xFF; + pixels[8] = r; + pixels[9] = g; + pixels[10] = b; + pixels[11] = 0xFF; + pixels[12] = r; + pixels[13] = g; + pixels[14] = b; + pixels[15] = 0xFF; + RwImageSetPixels(img, pixels); + RwImageSetPalette(img, nil); + RwImageFindRasterFormat(img, rwRASTERTYPETEXTURE, &width, &height, &depth, &format); + ras = RwRasterCreate(width, height, depth, format); + RwRasterSetFromImage(ras, img); + RwImageDestroy(img); + RwFree(pixels); + tex = RwTextureCreate(ras); + tex->name[0] = '@'; + return tex; +} + +void +CVehicleModelInfo::LoadVehicleColours(void) +{ + int fd; + int i; + char line[1024]; + int start, end; + int section, numCols; + enum { + NONE, + COLOURS, + CARS + }; + int r, g, b; + char name[64]; + int colors[16]; + int n; + + CFileMgr::ChangeDir("\\DATA\\"); + fd = CFileMgr::OpenFile("CARCOLS.DAT", "r"); + CFileMgr::ChangeDir("\\"); + + for(i = 0; i < 256; i++) + ms_colourTextureTable[i] = nil; + + section = 0; + numCols = 0; + while(CFileMgr::ReadLine(fd, line, sizeof(line))){ + // find first valid character in line + for(start = 0; ; start++) + if(line[start] > ' ' || line[start] == '\0' || line[start] == '\n') + break; + // find end of line + for(end = start; ; end++){ + if(line[end] == '\0' || line[end] == '\n') + break; + if(line[end] == ',' || line[end] == '\r') + line[end] = ' '; + } + line[end] = '\0'; + + // empty line + if(line[start] == '#' || line[start] == '\0') + continue; + + if(section == NONE){ + if(strncmp(&line[start], "col", 3) == 0) + section = COLOURS; + else if(strncmp(&line[start], "car", 3) == 0) + section = CARS; + }else if(strncmp(&line[start], "end", 3) == 0){ + section = NONE; + }else if(section == COLOURS){ + sscanf(&line[start], // BUG: games doesn't add start + "%d %d %d", &r, &g, &b); + ms_vehicleColourTable[numCols].red = r; + ms_vehicleColourTable[numCols].green = g; + ms_vehicleColourTable[numCols].blue = b; + ms_vehicleColourTable[numCols].alpha = 0xFF; + ms_colourTextureTable[numCols] = CreateCarColourTexture(r, g, b); + numCols++; + }else if(section == CARS){ + n = sscanf(&line[start], // BUG: games doesn't add start + "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", + name, + &colors[0], &colors[1], + &colors[2], &colors[3], + &colors[4], &colors[5], + &colors[6], &colors[7], + &colors[8], &colors[9], + &colors[10], &colors[11], + &colors[12], &colors[13], + &colors[14], &colors[15]); + CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(name, nil); + assert(mi); + mi->m_numColours = (n-1)/2; + for(i = 0; i < mi->m_numColours; i++){ + mi->m_colours1[i] = colors[i*2 + 0]; + mi->m_colours2[i] = colors[i*2 + 1]; + } + } + } + + CFileMgr::CloseFile(fd); +} + +void +CVehicleModelInfo::DeleteVehicleColourTextures(void) +{ + int i; + + for(i = 0; i < 256; i++){ + if(ms_colourTextureTable[i]){ + RwTextureDestroy(ms_colourTextureTable[i]); + ms_colourTextureTable[i] = nil; + } + } +} RpMaterial* CVehicleModelInfo::HasSpecularMaterialCB(RpMaterial *material, void *data) @@ -872,6 +1063,31 @@ CVehicleModelInfo::ShutdownEnvironmentMaps(void) pMatFxIdentityFrame = nil; } +int +CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(int id) +{ + int n; + + switch(id){ + case MI_TRAIN: + n = 3; + break; + case MI_FIRETRUCK: + n = 2; + break; + default: + n = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(id))->m_numDoors; + } + + if(n == 0) + return id == MI_RCBANDIT ? 0 : 1; + + if(id == MI_COACH) + return 8; + + return n - 1; +} + STARTPATCHES InjectHook(0x51FDC0, &CVehicleModelInfo::DeleteRwObject_, PATCH_JUMP); InjectHook(0x51FCB0, &CVehicleModelInfo::CreateInstance_, PATCH_JUMP); @@ -880,6 +1096,7 @@ STARTPATCHES InjectHook(0x51FE10, &CVehicleModelInfo::CollapseFramesCB, PATCH_JUMP); InjectHook(0x51FE50, &CVehicleModelInfo::MoveObjectsCB, PATCH_JUMP); InjectHook(0x51FE70, &CVehicleModelInfo::HideDamagedAtomicCB, PATCH_JUMP); + InjectHook(0x51FED0, &CVehicleModelInfo::HideAllComponentsAtomicCB, PATCH_JUMP); InjectHook(0x51FEF0, &CVehicleModelInfo::HasAlphaMaterialCB, PATCH_JUMP); InjectHook(0x51FF10, &CVehicleModelInfo::SetAtomicRendererCB, PATCH_JUMP); @@ -907,6 +1124,12 @@ STARTPATCHES InjectHook(0x520D30, (RpMaterial *(*)(RpMaterial*, void*))CVehicleModelInfo::GetEditableMaterialListCB, PATCH_JUMP); InjectHook(0x520DE0, &CVehicleModelInfo::FindEditableMaterialList, PATCH_JUMP); InjectHook(0x520E70, &CVehicleModelInfo::SetVehicleColour, PATCH_JUMP); + InjectHook(0x520FD0, &CVehicleModelInfo::ChooseVehicleColour, PATCH_JUMP); + InjectHook(0x5210A0, &CVehicleModelInfo::AvoidSameVehicleColour, PATCH_JUMP); + InjectHook(0x521260, &CVehicleModelInfo::LoadVehicleColours, PATCH_JUMP); + InjectHook(0x521650, &CVehicleModelInfo::DeleteVehicleColourTextures, PATCH_JUMP); + + InjectHook(0x5219D0, &CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors, PATCH_JUMP); InjectHook(0x521820, (RpAtomic *(*)(RpAtomic*, void*))CVehicleModelInfo::SetEnvironmentMapCB, PATCH_JUMP); InjectHook(0x5217A0, (RpMaterial *(*)(RpMaterial*, void*))CVehicleModelInfo::SetEnvironmentMapCB, PATCH_JUMP); diff --git a/src/modelinfo/VehicleModelInfo.h b/src/modelinfo/VehicleModelInfo.h index ccc46f73..f69760b8 100644 --- a/src/modelinfo/VehicleModelInfo.h +++ b/src/modelinfo/VehicleModelInfo.h @@ -56,7 +56,7 @@ public: uint8 m_colours1[NUM_VEHICLE_COLOURS]; uint8 m_colours2[NUM_VEHICLE_COLOURS]; uint8 m_numColours; - uint8 m_bLastColorVariation; // + uint8 m_lastColorVariation; uint8 m_currentColour1; uint8 m_currentColour2; RwTexture *m_envMap; @@ -78,6 +78,7 @@ public: static RwFrame *CollapseFramesCB(RwFrame *frame, void *data); static RwObject *MoveObjectsCB(RwObject *object, void *data); static RpAtomic *HideDamagedAtomicCB(RpAtomic *atomic, void *data); + static RpAtomic *HideAllComponentsAtomicCB(RpAtomic *atomic, void *data); static RpMaterial *HasAlphaMaterialCB(RpMaterial *material, void *data); static RpAtomic *SetAtomicRendererCB(RpAtomic *atomic, void *data); @@ -100,6 +101,10 @@ public: static RpAtomic *GetEditableMaterialListCB(RpAtomic *atomic, void *data); void FindEditableMaterialList(void); void SetVehicleColour(uint8 c1, uint8 c2); + void ChooseVehicleColour(uint8 &col1, uint8 &col2); + void AvoidSameVehicleColour(uint8 *col1, uint8 *col2); + static void LoadVehicleColours(void); + static void DeleteVehicleColourTextures(void); static RpAtomic *SetEnvironmentMapCB(RpAtomic *atomic, void *data); static RpMaterial *SetEnvironmentMapCB(RpMaterial *material, void *data); @@ -108,6 +113,8 @@ public: static void LoadEnvironmentMaps(void); static void ShutdownEnvironmentMaps(void); + static int GetMaximumNumberOfPassengersFromNumberOfDoors(int id); + void DeleteRwObject_(void) { this->CVehicleModelInfo::DeleteRwObject(); } RwObject *CreateInstance_(void) { return this->CVehicleModelInfo::CreateInstance(); } void SetClump_(RpClump *clump) { this->CVehicleModelInfo::SetClump(clump); }