diff options
Diffstat (limited to '')
41 files changed, 1182 insertions, 45 deletions
diff --git a/src/Camera.cpp b/src/Camera.cpp index 1b4b1db6..3af5d953 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "Draw.h" #include "World.h" #include "Vehicle.h" diff --git a/src/FileLoader.cpp b/src/FileLoader.cpp new file mode 100644 index 00000000..dc70234d --- /dev/null +++ b/src/FileLoader.cpp @@ -0,0 +1,936 @@ +#include "common.h" +#include "main.h" +#include "patcher.h" +#include "ModelInfo.h" +#include "ModelIndices.h" +#include "TempColModels.h" +#include "HandlingDataMgr.h" +#include "CarCtrl.h" +#include "PedType.h" +#include "PedStats.h" +#include "AnimManager.h" +#include "Game.h" +#include "RwHelper.h" +#include "NodeName.h" +#include "TxdStore.h" +#include "PathFind.h" +#include "VisibilityPlugins.h" +#include "FileMgr.h" +#include "FileLoader.h" + +char CFileLoader::ms_line[256]; + +const char* +GetFilename(const char *filename) +{ + char *s = strrchr((char*)filename, '\\'); + return s ? s+1 : filename; +} + +void +LoadingScreenLoadingFile(const char *filename) +{ + sprintf(gString, "Loading %s", GetFilename(filename)); + LoadingScreen("Loading the Game", gString, 0); +} + +void +CFileLoader::LoadLevel(const char *filename) +{ + int fd; + RwTexDictionary *savedTxd; + int savedLevel; + bool objectsLoaded; + char *line; + char txdname[64]; + + savedTxd = RwTexDictionaryGetCurrent(); + objectsLoaded = false; + savedLevel = CGame::currLevel; + if(savedTxd == nil){ + savedTxd = RwTexDictionaryCreate(); + RwTexDictionarySetCurrent(savedTxd); + } + fd = CFileMgr::OpenFile(filename, "r"); + assert(fd > 0); + + for(line = LoadLine(fd); line; line = LoadLine(fd)){ + if(*line == '#') + continue; + + if(strncmp(line, "EXIT", 9) == 0) // BUG: 9? + break; + + if(strncmp(line, "IMAGEPATH", 9) == 0){ + RwImageSetPath(line + 10); + }else if(strncmp(line, "TEXDICTION", 10) == 0){ + strcpy(txdname, line+11); + LoadingScreenLoadingFile(txdname); + RwTexDictionary *txd = LoadTexDictionary(txdname); + AddTexDictionaries(savedTxd, txd); + RwTexDictionaryDestroy(txd); + }else if(strncmp(line, "COLFILE", 7) == 0){ + int level; + sscanf(line+8, "%d", &level); + CGame::currLevel = level; + LoadingScreenLoadingFile(line+10); + LoadCollisionFile(line+10); + CGame::currLevel = savedLevel; + }else if(strncmp(line, "MODELFILE", 9) == 0){ + LoadingScreenLoadingFile(line + 10); + LoadModelFile(line + 10); + }else if(strncmp(line, "HIERFILE", 8) == 0){ + LoadingScreenLoadingFile(line + 9); + LoadClumpFile(line + 9); + }else if(strncmp(line, "IDE", 3) == 0){ + LoadingScreenLoadingFile(line + 4); + LoadObjectTypes(line + 4); + } + } + + CFileMgr::CloseFile(fd); + RwTexDictionarySetCurrent(savedTxd); +} + +void +CFileLoader::LoadCollisionFromDatFile(int currlevel) +{ + int fd; + char *line; + + fd = CFileMgr::OpenFile(CGame::aDatFile, "r"); + assert(fd > 0); + + for(line = LoadLine(fd); line; line = LoadLine(fd)){ + if(*line == '#') + continue; + + if(strncmp(line, "COLFILE", 7) == 0){ + int level; + sscanf(line+8, "%d", &level); + if(currlevel == level) + LoadCollisionFile(line+10); + } + } + + CFileMgr::CloseFile(fd); +} + +char* +CFileLoader::LoadLine(int fd) +{ + int i; + char *line; + + if(CFileMgr::ReadLine(fd, ms_line, 256) == nil) + return nil; + for(i = 0; ms_line[i] != '\0'; i++) + if(ms_line[i] < ' ' || ms_line[i] == ',') + ms_line[i] = ' '; + for(line = ms_line; *line <= ' ' && *line != '\0'; line++); + return line; +} + +RwTexDictionary* +CFileLoader::LoadTexDictionary(const char *filename) +{ + RwTexDictionary *txd; + RwStream *stream; + + txd = nil; + stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename); + debug("Loading texture dictionary file %s\n", filename); + if(stream){ + if(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil)) + txd = RwTexDictionaryGtaStreamRead(stream); + RwStreamClose(stream, nil); + } + if(txd == nil) + txd = RwTexDictionaryCreate(); + return txd; +} + +void +CFileLoader::LoadCollisionFile(const char *filename) +{ + int fd; + char modelname[24]; + CBaseModelInfo *mi; + struct { + char ident[4]; + uint32 size; + } header; + + debug("Loading collision file %s\n", filename); + fd = CFileMgr::OpenFile(filename, "rb"); + + while(CFileMgr::Read(fd, (char*)&header, sizeof(header))){ + assert(strncmp(header.ident, "COLL", 4) == 0); + CFileMgr::Read(fd, (char*)work_buff, header.size); + memcpy(modelname, work_buff, 24); + + mi = CModelInfo::GetModelInfo(modelname, nil); + if(mi){ + if(mi->GetColModel()){ + LoadCollisionModel(work_buff+24, *mi->GetColModel(), modelname); + }else{ + CColModel *model = new CColModel; + LoadCollisionModel(work_buff+24, *model, modelname); + mi->SetColModel(model, true); + } + }else{ + debug("colmodel %s can't find a modelinfo\n", modelname); + } + } + + CFileMgr::CloseFile(fd); +} + +void +CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) +{ + int i; + + model.boundingSphere.radius = *(float*)(buf); + model.boundingSphere.center.x = *(float*)(buf+4); + model.boundingSphere.center.y = *(float*)(buf+8); + model.boundingSphere.center.z = *(float*)(buf+12); + model.boundingBox.min.x = *(float*)(buf+16); + model.boundingBox.min.y = *(float*)(buf+20); + model.boundingBox.min.z = *(float*)(buf+24); + model.boundingBox.max.x = *(float*)(buf+28); + model.boundingBox.max.y = *(float*)(buf+32); + model.boundingBox.max.z = *(float*)(buf+36); + model.numSpheres = *(int16*)(buf+40); + buf += 44; + if(model.numSpheres > 0){ + model.spheres = (CColSphere*)RwMalloc(model.numSpheres*sizeof(CColSphere)); + for(i = 0; i < model.numSpheres; i++){ + model.spheres[i].Set(*(float*)buf, *(CVector*)(buf+4), buf[16], buf[17]); + buf += 20; + } + }else + model.spheres = nil; + + model.numLines = *(int16*)buf; + buf += 4; + if(model.numLines > 0){ + model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine)); + for(i = 0; i < model.numLines; i++){ + model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12)); + buf += 24; + } + }else + model.lines = nil; + + model.numBoxes = *(int16*)buf; + buf += 4; + if(model.numBoxes > 0){ + model.boxes = (CColBox*)RwMalloc(model.numBoxes*sizeof(CColBox)); + for(i = 0; i < model.numBoxes; i++){ + model.boxes[i].Set(*(CVector*)buf, *(CVector*)(buf+12), buf[24], buf[25]); + buf += 28; + } + }else + model.boxes = nil; + + int32 numVertices = *(int16*)buf; + buf += 4; + if(numVertices > 0){ + model.vertices = (CVector*)RwMalloc(numVertices*sizeof(CVector)); + for(i = 0; i < numVertices; i++){ + model.vertices[i] = *(CVector*)buf; + if(fabs(model.vertices[i].x) >= 256.0f || + fabs(model.vertices[i].y) >= 256.0f || + fabs(model.vertices[i].z) >= 256.0f) + printf("%s:Collision volume too big\n", modelname); + buf += 12; + } + }else + model.vertices = nil; + + model.numTriangles = *(int16*)buf; + buf += 4; + if(model.numTriangles > 0){ + model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle)); + for(i = 0; i < model.numTriangles; i++){ + model.triangles[i].Set(model.vertices, *(int32*)buf, *(int32*)(buf+4), *(int32*)(buf+8), buf[12], buf[13]); + buf += 16; + } + }else + model.triangles = nil; +} + +static void +GetNameAndLOD(char *nodename, char *name, int *n) +{ + char *underscore = nil; + for(char *s = nodename; *s != '\0'; s++){ + if(s[0] == '_' && (s[1] == 'l' || s[1] == 'L')) + underscore = s; + } + if(underscore){ + strncpy(name, nodename, underscore - nodename); + name[underscore - nodename] = '\0'; + *n = atoi(underscore + 2); + }else{ + strncpy(name, nodename, 24); + *n = 0; + } +} + +RpAtomic* +CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data) +{ + CSimpleModelInfo *mi; + char *nodename, name[24]; + int n; + RpClump *clump = (RpClump*)data; + + nodename = GetFrameNodeName(RpClumpGetFrame(atomic)); + GetNameAndLOD(nodename, name, &n); + mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(name, 0); + if(mi){ + assert(mi->IsSimple()); + mi->SetAtomic(n, atomic); + RpClumpRemoveAtomic(clump, atomic); + RpAtomicSetFrame(atomic, RwFrameCreate()); + CVisibilityPlugins::SetAtomicModelInfo(atomic, mi); + CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); + }else{ + debug("Can't find Atomic %s\n", name); + } + + return atomic; +} + +void +CFileLoader::LoadModelFile(const char *filename) +{ + RwStream *stream; + RpClump *clump; + + debug("Loading model file %s\n", filename); + stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename); + if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){ + clump = RpClumpStreamRead(stream); + if(clump){ + RpClumpForAllAtomics(clump, FindRelatedModelInfoCB, clump); + RpClumpDestroy(clump); + } + } + RwStreamClose(stream, nil); +} + +void +CFileLoader::LoadClumpFile(const char *filename) +{ + RwStream *stream; + RpClump *clump; + char *nodename, name[24]; + int n; + CClumpModelInfo *mi; + + debug("Loading model file %s\n", filename); + stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename); + while(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){ + clump = RpClumpStreamRead(stream); + if(clump){ + nodename = GetFrameNodeName(RpClumpGetFrame(clump)); + GetNameAndLOD(nodename, name, &n); + mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(name, 0); + assert(mi->IsClump()); + if(mi) + mi->SetClump(clump); + else + RpClumpDestroy(clump); + } + } + RwStreamClose(stream, nil); +} + +bool +CFileLoader::LoadClumpFile(RwStream *stream, uint32 id) +{ + RpClump *clump; + CClumpModelInfo *mi; + + if(!RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) + return false; + clump = RpClumpStreamRead(stream); + if(clump == nil) + return false; + mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id); + mi->SetClump(clump); + if(mi->m_type == MITYPE_PED && id != 0 && RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){ + // Read LOD ped + clump = RpClumpStreamRead(stream); + if(clump){ + ((CPedModelInfo*)mi)->SetLowDetailClump(clump); + RpClumpDestroy(clump); + } + } + return true; +} + +bool +CFileLoader::StartLoadClumpFile(RwStream *stream, uint32 id) +{ + if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){ + printf("Start loading %s\n", CModelInfo::GetModelInfo(id)->GetName()); + return RpClumpGtaStreamRead1(stream); + }else{ + printf("FAILED\n"); + return false; + } +} + +bool +CFileLoader::FinishLoadClumpFile(RwStream *stream, uint32 id) +{ + RpClump *clump; + CClumpModelInfo *mi; + + printf("Finish loading %s\n", CModelInfo::GetModelInfo(id)->GetName()); + clump = RpClumpGtaStreamRead2(stream); + + if(clump){ + mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id); + mi->SetClump(clump); + return true; + }else{ + printf("FAILED\n"); + return false; + } +} + +CSimpleModelInfo *gpRelatedModelInfo; + +bool +CFileLoader::LoadAtomicFile(RwStream *stream, uint32 id) +{ + RpClump *clump; + + if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){ + clump = RpClumpStreamRead(stream); + if(clump == nil) + return false; + gpRelatedModelInfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); + RpClumpForAllAtomics(clump, SetRelatedModelInfoCB, clump); + RpClumpDestroy(clump); + } + return true; +} + +RpAtomic* +CFileLoader::SetRelatedModelInfoCB(RpAtomic *atomic, void *data) +{ + char *nodename, name[24]; + int n; + RpClump *clump = (RpClump*)data; + + nodename = GetFrameNodeName(RpAtomicGetFrame(atomic)); + GetNameAndLOD(nodename, name, &n); + gpRelatedModelInfo->SetAtomic(n, atomic); + RpClumpRemoveAtomic(clump, atomic); + RpAtomicSetFrame(atomic, RwFrameCreate()); + CVisibilityPlugins::SetAtomicModelInfo(atomic, gpRelatedModelInfo); + CVisibilityPlugins::SetAtomicRenderCallback(atomic, 0); + return atomic; +} + +RpClump* +CFileLoader::LoadAtomicFile2Return(const char *filename) +{ + RwStream *stream; + RpClump *clump; + + clump = nil; + debug("Loading model file %s\n", filename); + stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename); + if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) + clump = RpClumpStreamRead(stream); + RwStreamClose(stream, nil); + return clump; +} + +static RwTexture* +MoveTexturesCB(RwTexture *texture, void *pData) +{ + RwTexDictionaryAddTexture((RwTexDictionary*)pData, texture); + return texture; +} + +void +CFileLoader::AddTexDictionaries(RwTexDictionary *dst, RwTexDictionary *src) +{ + RwTexDictionaryForAllTextures(src, MoveTexturesCB, dst); +} + +void +CFileLoader::LoadObjectTypes(const char *filename) +{ + enum { + NONE, + OBJS, + MLO, + TOBJ, + HIER, + CARS, + PEDS, + PATH, + TWO2FX + }; + char *line; + int fd; + int section; + int pathIndex; + char pathTypeStr[20]; + int id, pathType; +// int mlo; + + section = 0; + pathIndex = -1; +// mlo = 0; + debug("Loading object types from %s...\n", filename); + + fd = CFileMgr::OpenFile(filename, "rb"); + for(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){ + if(*line == '\0' || *line == '#') + continue; + + if(section == NONE){ + if(strncmp(line, "objs", 4) == 0) section = OBJS; + else if(strncmp(line, "tobj", 4) == 0) section = TOBJ; + else if(strncmp(line, "hier", 4) == 0) section = HIER; + else if(strncmp(line, "cars", 4) == 0) section = CARS; + else if(strncmp(line, "peds", 4) == 0) section = PEDS; + else if(strncmp(line, "path", 4) == 0) section = PATH; + else if(strncmp(line, "2dfx", 4) == 0) section = TWO2FX; + }else if(strncmp(line, "end", 3) == 0){ + section = section == MLO ? OBJS : NONE; + }else switch(section){ + case OBJS: + if(strncmp(line, "sta", 3) == 0) + assert(0); // LoadMLO + else + LoadObject(line); + break; + case MLO: + assert(0); // LoadMLOInstance + break; + case TOBJ: + LoadTimeObject(line); + break; + case HIER: + LoadClumpObject(line); + break; + case CARS: + LoadVehicleObject(line); + break; + case PEDS: + LoadPedObject(line); + break; + case PATH: + if(pathIndex == -1){ + id = LoadPathHeader(line, pathTypeStr); + if(strncmp(pathTypeStr, "ped", 4) == 0) + pathType = 1; + else if(strncmp(pathTypeStr, "car", 4) == 0) + pathType = 0; + pathIndex = 0; + }else{ + if(pathType == 1) + LoadPedPathNode(line, id, pathIndex); + else if(pathType == 0) + LoadCarPathNode(line, id, pathIndex); + pathIndex++; + if(pathIndex == 12) + pathIndex = -1; + } + break; + case TWO2FX: + Load2dEffect(line); + break; + } + } + CFileMgr::CloseFile(fd); + + for(id = 0; id < MODELINFOSIZE; id++){ + CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); + if(mi && mi->IsSimple()) + mi->SetupBigBuilding(); + } +} + +void +SetModelInfoFlags(CSimpleModelInfo *mi, uint32 flags) +{ + mi->m_normalCull = !!(flags & 1); + mi->m_noFade = !!(flags & 2); + mi->m_drawLast = !!(flags & (4|8)); + mi->m_additive = !!(flags & 8); + mi->m_isSubway = !!(flags & 0x10); + mi->m_ignoreLight = !!(flags & 0x20); + mi->m_noZwrite = !!(flags & 0x40); +} + +void +CFileLoader::LoadObject(const char *line) +{ + int id, numObjs; + char model[24], txd[24]; + float dist[3]; + uint32 flags; + int damaged; + CSimpleModelInfo *mi; + + if(sscanf(line, "%d %s %s %d", &id, model, txd, &numObjs) != 4) + return; + + switch(numObjs){ + case 1: + sscanf(line, "%d %s %s %d %f %d", + &id, model, txd, &numObjs, &dist[0], &flags); + damaged = 0; + break; + case 2: + sscanf(line, "%d %s %s %d %f %f %d", + &id, model, txd, &numObjs, &dist[0], &dist[1], &flags); + damaged = dist[0] < dist[1] ? // Are distances increasing? + 0 : // Yes, no damage model + 1; // No, 1 is damaged + break; + case 3: + sscanf(line, "%d %s %s %d %f %f %f %d", + &id, model, txd, &numObjs, &dist[0], &dist[1], &dist[2], &flags); + damaged = dist[0] < dist[1] ? // Are distances increasing? + (dist[1] < dist[2] ? 0 : 2) : // Yes, only 2 can still be a damage model + 1; // No, 1 and 2 are damaged + break; + } + + mi = CModelInfo::AddSimpleModel(id); + mi->SetName(model); + mi->SetNumAtomics(numObjs); + mi->SetLodDistances(dist); + SetModelInfoFlags(mi, flags); + mi->m_firstDamaged = damaged; + mi->SetTexDictionary(txd); + MatchModelString(model, id); +} + +void +CFileLoader::LoadTimeObject(const char *line) +{ + int id, numObjs; + char model[24], txd[24]; + float dist[3]; + uint32 flags; + int timeOn, timeOff; + int damaged; + CTimeModelInfo *mi, *other; + + if(sscanf(line, "%d %s %s %d", &id, model, txd, &numObjs) != 4) + return; + + switch(numObjs){ + case 1: + sscanf(line, "%d %s %s %d %f %d %d %d", + &id, model, txd, &numObjs, &dist[0], &flags, &timeOn, &timeOff); + damaged = 0; + break; + case 2: + sscanf(line, "%d %s %s %d %f %f %d %d %d", + &id, model, txd, &numObjs, &dist[0], &dist[1], &flags, &timeOn, &timeOff); + damaged = dist[0] < dist[1] ? // Are distances increasing? + 0 : // Yes, no damage model + 1; // No, 1 is damaged + break; + case 3: + sscanf(line, "%d %s %s %d %f %f %f %d %d %d", + &id, model, txd, &numObjs, &dist[0], &dist[1], &dist[2], &flags, &timeOn, &timeOff); + damaged = dist[0] < dist[1] ? // Are distances increasing? + (dist[1] < dist[2] ? 0 : 2) : // Yes, only 2 can still be a damage model + 1; // No, 1 and 2 are damaged + break; + } + + mi = CModelInfo::AddTimeModel(id); + mi->SetName(model); + mi->SetNumAtomics(numObjs); + mi->SetLodDistances(dist); + SetModelInfoFlags(mi, flags); + mi->m_firstDamaged = damaged; + mi->SetTimes(timeOn, timeOff); + mi->SetTexDictionary(txd); + other = mi->FindOtherTimeModel(); + if(other) + other->SetOtherTimeModel(id); + MatchModelString(model, id); +} + +void +CFileLoader::LoadClumpObject(const char *line) +{ + int id; + char model[24], txd[24]; + CClumpModelInfo *mi; + + if(sscanf(line, "%d %s %s", &id, &model, &txd) == 3){ + mi = CModelInfo::AddClumpModel(id); + mi->SetName(model); + mi->SetTexDictionary(txd); + mi->SetColModel(&CTempColModels::ms_colModelBBox); + } +} + +void +CFileLoader::LoadVehicleObject(const char *line) +{ + int id; + char model[24], txd[24]; + char type[8], handlingId[16], gamename[32], vehclass[12]; + uint32 frequency, comprules; + int32 level, misc; + float wheelScale; + CVehicleModelInfo *mi; + char *p; + + sscanf(line, "%d %s %s %s %s %s %s %d %d %x %d %f", + &id, model, txd, + type, handlingId, gamename, vehclass, + &frequency, &level, &comprules, &misc, &wheelScale); + + mi = CModelInfo::AddVehicleModel(id); + mi->SetName(model); + mi->SetTexDictionary(txd); + for(p = gamename; *p; p++) + if(*p == '_') *p = ' '; + strncpy(mi->m_gameName, gamename, 32); + mi->m_level = level; + mi->m_compRules = comprules; + + if(strncmp(type, "car", 4) == 0){ + mi->m_wheelId = misc; + mi->m_wheelScale = wheelScale; + mi->m_vehicleType = VEHICLE_TYPE_CAR; + }else if(strncmp(type, "boat", 5) == 0){ + mi->m_vehicleType = VEHICLE_TYPE_BOAT; + }else if(strncmp(type, "train", 6) == 0){ + mi->m_vehicleType = VEHICLE_TYPE_TRAIN; + }else if(strncmp(type, "heli", 5) == 0){ + mi->m_vehicleType = VEHICLE_TYPE_HELI; + }else if(strncmp(type, "plane", 6) == 0){ + mi->m_wheelId = misc; + mi->m_wheelScale = 1.0f; + mi->m_vehicleType = VEHICLE_TYPE_PLANE; + }else if(strncmp(type, "bike", 5) == 0){ + mi->m_bikeSteerAngle = misc; + mi->m_wheelScale = wheelScale; + mi->m_vehicleType = VEHICLE_TYPE_BIKE; + }else + assert(0); + + mi->m_handlingId = mod_HandlingManager.GetHandlingId(handlingId); + + // Well this is kinda dumb.... + if(strncmp(vehclass, "poorfamily", 11) == 0){ + mi->m_vehicleClass = VEHICLE_CLASS_POOR; + while(frequency-- > 0) + CCarCtrl::AddToCarArray(id, VEHICLE_CLASS_POOR); + }else if(strncmp(vehclass, "richfamily", 11) == 0){ + mi->m_vehicleClass = VEHICLE_CLASS_RICH; + while(frequency-- > 0) + CCarCtrl::AddToCarArray(id, VEHICLE_CLASS_RICH); + }else if(strncmp(vehclass, "executive", 10) == 0){ + mi->m_vehicleClass = VEHICLE_CLASS_EXECUTIVE; + while(frequency-- > 0) + CCarCtrl::AddToCarArray(id, VEHICLE_CLASS_EXECUTIVE); + }else if(strncmp(vehclass, "worker", 7) == 0){ + mi->m_vehicleClass = VEHICLE_CLASS_WORKER; + while(frequency-- > 0) + CCarCtrl::AddToCarArray(id, VEHICLE_CLASS_WORKER); + }else if(strncmp(vehclass, "special", 8) == 0){ + mi->m_vehicleClass = VEHICLE_CLASS_SPECIAL; + while(frequency-- > 0) + CCarCtrl::AddToCarArray(id, VEHICLE_CLASS_SPECIAL); + }else if(strncmp(vehclass, "big", 4) == 0){ + mi->m_vehicleClass = VEHICLE_CLASS_BIG; + while(frequency-- > 0) + CCarCtrl::AddToCarArray(id, VEHICLE_CLASS_BIG); + }else if(strncmp(vehclass, "taxi", 5) == 0){ + mi->m_vehicleClass = VEHICLE_CLASS_TAXI; + while(frequency-- > 0) + CCarCtrl::AddToCarArray(id, VEHICLE_CLASS_TAXI); + } +} + +void +CFileLoader::LoadPedObject(const char *line) +{ + int id; + char model[24], txd[24]; + char pedType[24], pedStats[24], animGroup[24]; + int carsCanDrive; + CPedModelInfo *mi; + int animGroupId; + + if(sscanf(line, "%d %s %s %s %s %s %x", + &id, model, txd, + pedType, pedStats, animGroup, &carsCanDrive) != 7) + return; + + mi = CModelInfo::AddPedModel(id); + mi->SetName(model); + mi->SetTexDictionary(txd); + mi->SetColModel(&CTempColModels::ms_colModelPed1); + mi->m_pedType = CPedType::FindPedType(pedType); + mi->m_pedStatType = CPedStats::GetPedStatType(pedStats); + for(animGroupId = 0; animGroupId < NUM_ANIM_ASSOC_GROUPS; animGroupId++) + if(strcmp(animGroup, CAnimManager::GetAnimGroupName((AssocGroupId)animGroupId)) == 0) + break; + mi->m_animGroup = animGroupId; + + // ??? + CModelInfo::GetModelInfo(MI_LOPOLYGUY)->SetColModel(&CTempColModels::ms_colModelPed1); +} + +int +CFileLoader::LoadPathHeader(const char *line, char *type) +{ + int id; + char modelname[32]; + + sscanf(line, "%s %d %s", type, &id, modelname); + return id; +} + +void +CFileLoader::LoadPedPathNode(const char *line, int id, int node) +{ + int type, next, cross; + float x, y, z, width; + + sscanf(line, "%d %d %d %f %f %f %f", &type, &next, &cross, &x, &y, &z, &width); + ThePaths.StoreNodeInfoPed(id, node, type, next, x, y, z, 0, !!cross); +} + +void +CFileLoader::LoadCarPathNode(const char *line, int id, int node) +{ + int type, next, cross, numLeft, numRight; + float x, y, z, width; + + sscanf(line, "%d %d %d %f %f %f %f %d %d", &type, &next, &cross, &x, &y, &z, &width, &numLeft, &numRight); + ThePaths.StoreNodeInfoCar(id, node, type, next, x, y, z, 0, numLeft, numRight); +} + +void +CFileLoader::Load2dEffect(const char *line) +{ + int id, r, g, b, a, type; + float x, y, z; + char corona[32], shadow[32]; + int shadowIntens, flash, roadReflection, flare, flags, probability; + CBaseModelInfo *mi; + C2dEffect *effect; + char *p; + + sscanf(line, "%d %f %f %f %d %d %d %d %d", &id, &x, &y, &z, &r, &g, &b, &a, &type); + + CTxdStore::PushCurrentTxd(); + CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("particle")); + + mi = CModelInfo::GetModelInfo(id); + effect = CModelInfo::Get2dEffectStore().alloc(); + mi->Add2dEffect(effect); + effect->pos = CVector(x, y, z); + effect->col = CRGBA(r, g, b, a); + effect->type = type; + + switch(effect->type){ + case EFFECT_LIGHT: + while(*line++ != '"'); + p = corona; + while(*line != '"') *p++ = *line++; + *p = '\0'; + line++; + + while(*line++ != '"'); + p = shadow; + while(*line != '"') *p++ = *line++; + *p = '\0'; + line++; + + sscanf(line, "%f %f %f %f %d %d %d %d %d", + &effect->light.dist, + &effect->light.outerRange, + &effect->light.size, + &effect->light.innerRange, + &shadowIntens, &flash, &roadReflection, &flare, &flags); + effect->light.corona = RwTextureRead(corona, nil); + effect->light.shadow = RwTextureRead(shadow, nil); + effect->light.shadowIntensity = shadowIntens; + effect->light.flash = flash; + effect->light.roadReflection = roadReflection; + effect->light.flareType = flare; + // TODO: check out the flags + if(flags & 4) + flags &= ~2; + effect->light.flags = flags; + break; + + case EFFECT_PARTICLE: + sscanf(line, "%d %f %f %f %d %d %d %d %d %d %f %f %f %f", + &id, &x, &y, &z, &r, &g, &b, &a, &type, + &effect->particle.particleType, + &effect->particle.dir.x, + &effect->particle.dir.y, + &effect->particle.dir.z, + &effect->particle.scale); + break; + + case EFFECT_ATTRACTOR: + sscanf(line, "%d %f %f %f %d %d %d %d %d %d %f %f %f %d", + &id, &x, &y, &z, &r, &g, &b, &a, &type, + &flags, + &effect->attractor.dir.x, + &effect->attractor.dir.y, + &effect->attractor.dir.z, + &probability); + effect->attractor.flags = flags; + effect->attractor.probability = probability; + break; + } + + CTxdStore::PopCurrentTxd(); +} + + +STARTPATCHES + InjectHook(0x476520, CFileLoader::LoadCollisionFromDatFile, PATCH_JUMP); + InjectHook(0x4761D0, CFileLoader::LoadLine, PATCH_JUMP); + InjectHook(0x4765B0, CFileLoader::LoadTexDictionary, PATCH_JUMP); + InjectHook(0x478B20, CFileLoader::LoadCollisionFile, PATCH_JUMP); + InjectHook(0x478C20, CFileLoader::LoadCollisionModel, PATCH_JUMP); + InjectHook(0x476750, CFileLoader::LoadModelFile, PATCH_JUMP); + InjectHook(0x476810, (void (*)(const char*))CFileLoader::LoadClumpFile, PATCH_JUMP); + InjectHook(0x476990, (bool (*)(RwStream*,uint32))CFileLoader::LoadClumpFile, PATCH_JUMP); + InjectHook(0x476A20, CFileLoader::StartLoadClumpFile, PATCH_JUMP); + InjectHook(0x476A70, CFileLoader::FinishLoadClumpFile, PATCH_JUMP); + InjectHook(0x476930, CFileLoader::LoadAtomicFile, PATCH_JUMP); + InjectHook(0x4767C0, CFileLoader::LoadAtomicFile2Return, PATCH_JUMP); + InjectHook(0x476630, CFileLoader::AddTexDictionaries, PATCH_JUMP); + + InjectHook(0x476AC0, CFileLoader::LoadObjectTypes, PATCH_JUMP); + InjectHook(0x477040, CFileLoader::LoadObject, PATCH_JUMP); + InjectHook(0x4774B0, CFileLoader::LoadTimeObject, PATCH_JUMP); + InjectHook(0x477920, CFileLoader::LoadClumpObject, PATCH_JUMP); + InjectHook(0x477990, CFileLoader::LoadVehicleObject, PATCH_JUMP); + InjectHook(0x477DE0, CFileLoader::LoadPedObject, PATCH_JUMP); + InjectHook(0x477ED0, CFileLoader::LoadPathHeader, PATCH_JUMP); + InjectHook(0x477FF0, CFileLoader::LoadCarPathNode, PATCH_JUMP); + InjectHook(0x477F00, CFileLoader::LoadPedPathNode, PATCH_JUMP); + InjectHook(0x4780E0, CFileLoader::Load2dEffect, PATCH_JUMP); +ENDPATCHES diff --git a/src/FileLoader.h b/src/FileLoader.h new file mode 100644 index 00000000..0aad884d --- /dev/null +++ b/src/FileLoader.h @@ -0,0 +1,34 @@ +#pragma once + +class CFileLoader +{ + static char ms_line[256]; +public: + static void LoadLevel(const char *filename); + static void LoadCollisionFromDatFile(int currlevel); + static char *LoadLine(int fd); + static RwTexDictionary *LoadTexDictionary(const char *filename); + static void LoadCollisionFile(const char *filename); + static void LoadCollisionModel(uint8 *buf, CColModel &model, char *name); + static void LoadModelFile(const char *filename); + static RpAtomic *FindRelatedModelInfoCB(RpAtomic *atomic, void *data); + static void LoadClumpFile(const char *filename); + static bool LoadClumpFile(RwStream *stream, uint32 id); + static bool StartLoadClumpFile(RwStream *stream, uint32 id); + static bool FinishLoadClumpFile(RwStream *stream, uint32 id); + static bool LoadAtomicFile(RwStream *stream, uint32 id); + static RpAtomic *SetRelatedModelInfoCB(RpAtomic *atomic, void *data); + static RpClump *LoadAtomicFile2Return(const char *filename); + static void AddTexDictionaries(RwTexDictionary *dst, RwTexDictionary *src); + + static void LoadObjectTypes(const char *filename); + static void LoadObject(const char *line); + static void LoadTimeObject(const char *line); + static void LoadClumpObject(const char *line); + static void LoadVehicleObject(const char *line); + static void LoadPedObject(const char *line); + static int LoadPathHeader(const char *line, char *type); + static void LoadPedPathNode(const char *line, int id, int node); + static void LoadCarPathNode(const char *line, int id, int node); + static void Load2dEffect(const char *line); +}; diff --git a/src/Game.cpp b/src/Game.cpp index 5073eed1..f158e9db 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -9,6 +9,7 @@ bool &CGame::frenchGame = *(bool*)0x95CDCB; bool &CGame::germanGame = *(bool*)0x95CD1E; bool &CGame::noProstitutes = *(bool*)0x95CDCF; bool &CGame::playingIntro = *(bool*)0x95CDC2; +char *CGame::aDatFile = (char*)0x773A48; WRAPPER void CGame::Process(void) { EAXJMP(0x48C850); } WRAPPER bool CGame::InitialiseOnceBeforeRW(void) { EAXJMP(0x48BB80); } @@ -18,6 +18,7 @@ public: static bool &germanGame; static bool &noProstitutes; static bool &playingIntro; + static char *aDatFile; //[32]; static void Process(void); static bool InitialiseOnceBeforeRW(void); diff --git a/src/Timecycle.cpp b/src/Timecycle.cpp index 56341e32..c04295dd 100644 --- a/src/Timecycle.cpp +++ b/src/Timecycle.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "Clock.h" #include "Weather.h" #include "Camera.h" diff --git a/src/common.h b/src/common.h index ee6ceadd..46c22c20 100644 --- a/src/common.h +++ b/src/common.h @@ -76,13 +76,6 @@ extern void **rwengine; #define HUD_FROM_RIGHT(a) (SCREEN_WIDTH - HUD_STRETCH_X(a)) #define HUD_FROM_BOTTOM(a) (SCREEN_HEIGHT - HUD_STRETCH_Y(a)) -struct GlobalScene -{ - RpWorld *world; - RwCamera *camera; -}; -extern GlobalScene &Scene; - #include "math/Vector.h" #include "math/Vector2D.h" #include "math/Matrix.h" @@ -136,10 +129,6 @@ inline float sq(float x) { return x*x; } int myrand(void); void mysrand(unsigned int seed); -extern uint8 work_buff[55000]; -extern char gString[256]; -extern wchar *gUString; - void re3_debug(char *format, ...); void re3_trace(const char *filename, unsigned int lineno, const char *func, char *format, ...); void re3_assert(const char *expr, const char *filename, unsigned int lineno, const char *func); diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 54491cd2..d59ae2d0 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -2,4 +2,5 @@ #include "patcher.h" #include "CarCtrl.h" -WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); }
\ No newline at end of file +WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); } +WRAPPER void CCarCtrl::AddToCarArray(int id, int vehclass) { EAXJMP(0x4182F0); } diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index fbe36f28..1f468475 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -6,4 +6,5 @@ class CCarCtrl { public: static void SwitchVehicleToRealPhysics(CVehicle*); + static void AddToCarArray(int id, int vehclass); }; diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 2994eb49..b8469e5f 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "ModelIndices.h" #include "Garages.h" #include "Timer.h" diff --git a/src/control/HandlingDataMgr.cpp b/src/control/HandlingDataMgr.cpp new file mode 100644 index 00000000..94824358 --- /dev/null +++ b/src/control/HandlingDataMgr.cpp @@ -0,0 +1,7 @@ +#include "common.h" +#include "patcher.h" +#include "HandlingDatamgr.h" + +cHandlingDataMgr &mod_HandlingManager = *(cHandlingDataMgr*)0x728060; + +WRAPPER int32 cHandlingDataMgr::GetHandlingId(const char *name){ EAXJMP(0x546B70); } diff --git a/src/control/HandlingDataMgr.h b/src/control/HandlingDataMgr.h new file mode 100644 index 00000000..00e62b59 --- /dev/null +++ b/src/control/HandlingDataMgr.h @@ -0,0 +1,8 @@ +#pragma once + +class cHandlingDataMgr +{ +public: + int32 GetHandlingId(const char *name); +}; +extern cHandlingDataMgr &mod_HandlingManager; diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 8857f8c9..8cfc17e7 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -46,6 +46,37 @@ CTempDetachedNode *&DetachedNodesCars = *(CTempDetachedNode**)0x8E2824; CTempDetachedNode *&DetachedNodesPeds = *(CTempDetachedNode**)0x8E28A0; void +CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing) +{ + int i; + + i = id*12 + node; + InfoForTilePeds[i].type = type; + InfoForTilePeds[i].next = next; + InfoForTilePeds[i].x = x; + InfoForTilePeds[i].y = y; + InfoForTilePeds[i].z = z; + InfoForTilePeds[i].numLeftLanes = 0; + InfoForTilePeds[i].numRightLanes = 0; + InfoForTilePeds[i].crossing = crossing; +} + +void +CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight) +{ + int i; + + i = id*12 + node; + InfoForTileCars[i].type = type; + InfoForTileCars[i].next = next; + InfoForTileCars[i].x = x; + InfoForTileCars[i].y = y; + InfoForTileCars[i].z = z; + InfoForTileCars[i].numLeftLanes = numLeft; + InfoForTileCars[i].numRightLanes = numRight; +} + +void CPathFind::PreparePathData(void) { int i, j, k; @@ -457,8 +488,8 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor } }else{ // Crosses road - if(objectpathinfo[istart + iseg].next == jseg && objectpathinfo[istart + iseg].flag & 1 || - objectpathinfo[jstart + jseg].next == iseg && objectpathinfo[jstart + jseg].flag & 1) + if(objectpathinfo[istart + iseg].next == jseg && objectpathinfo[istart + iseg].crossing || + objectpathinfo[jstart + jseg].next == iseg && objectpathinfo[jstart + jseg].crossing) m_connectionFlags[m_numConnections] |= ConnectionCrossRoad; else m_connectionFlags[m_numConnections] &= ~ConnectionCrossRoad; diff --git a/src/control/PathFind.h b/src/control/PathFind.h index 495c4a73..ed3c7e9f 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -65,7 +65,7 @@ struct CPathInfoForObject int8 next; int8 numLeftLanes; int8 numRightLanes; - uint8 flag; + uint8 crossing : 1; }; struct CTempNode @@ -123,6 +123,8 @@ public: void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo, float unk, CTempDetachedNode *detachednodes, int unused); void CalcNodeCoors(int16 x, int16 y, int16 z, int32 id, CVector *out); + void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing); + void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight); }; static_assert(sizeof(CPathFind) == 0x4c8f4, "CPathFind: error"); diff --git a/src/control/PedStats.cpp b/src/control/PedStats.cpp new file mode 100644 index 00000000..3cb40d76 --- /dev/null +++ b/src/control/PedStats.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "PedStats.h" + +WRAPPER int32 CPedStats::GetPedStatType(char *type) { EAXJMP(0x4EF780); } diff --git a/src/PedStat.h b/src/control/PedStats.h index 3045e494..12ebdbc2 100644 --- a/src/PedStat.h +++ b/src/control/PedStats.h @@ -15,3 +15,9 @@ struct PedStat int16 m_flags; }; static_assert(sizeof(PedStat) == 0x34, "PedStat: error"); + +class CPedStats +{ +public: + static int32 GetPedStatType(char *type); +}; diff --git a/src/control/PedType.cpp b/src/control/PedType.cpp new file mode 100644 index 00000000..587aa815 --- /dev/null +++ b/src/control/PedType.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "PedType.h" + +WRAPPER int32 CPedType::FindPedType(char *type) { EAXJMP(0x4EEC10); } diff --git a/src/control/PedType.h b/src/control/PedType.h new file mode 100644 index 00000000..563dc294 --- /dev/null +++ b/src/control/PedType.h @@ -0,0 +1,7 @@ +#pragma once + +class CPedType +{ +public: + static int32 FindPedType(char *type); +}; diff --git a/src/entities/CutsceneHead.cpp b/src/entities/CutsceneHead.cpp index 766befb0..a9c47777 100644 --- a/src/entities/CutsceneHead.cpp +++ b/src/entities/CutsceneHead.cpp @@ -1,6 +1,7 @@ #include "common.h" #include <rpskin.h> #include "patcher.h" +#include "main.h" #include "RwHelper.h" #include "RpAnimBlend.h" #include "AnimBlendClumpData.h" diff --git a/src/entities/CutsceneObject.cpp b/src/entities/CutsceneObject.cpp index d00a668b..1e665dd6 100644 --- a/src/entities/CutsceneObject.cpp +++ b/src/entities/CutsceneObject.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "lights.h" #include "PointLights.h" #include "RpAnimBlend.h" diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index ccb07d46..df92dd26 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -4,7 +4,6 @@ #include "Particle.h" #include "Stats.h" #include "World.h" -#include "PedStat.h" #include "DMaudio.h" #include "Ped.h" diff --git a/src/main.cpp b/src/main.cpp index 655cc106..8f6a9b29 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "RwHelper.h" #include "Clouds.h" #include "Draw.h" @@ -55,6 +56,8 @@ #endif +GlobalScene &Scene = *(GlobalScene*)0x726768; + uint8 work_buff[55000]; char gString[256]; wchar *gUString = (wchar*)0x74B018; diff --git a/src/modelinfo/BaseModelInfo.h b/src/modelinfo/BaseModelInfo.h index fadea18a..b6c6c62e 100644 --- a/src/modelinfo/BaseModelInfo.h +++ b/src/modelinfo/BaseModelInfo.h @@ -41,6 +41,9 @@ public: virtual RwObject *GetRwObject(void) = 0; bool IsSimple(void) { return m_type == MITYPE_SIMPLE || m_type == MITYPE_TIME; } + bool IsClump(void) { return m_type == MITYPE_CLUMP || m_type == MITYPE_PED || m_type == MITYPE_VEHICLE || + m_type == MITYPE_MLO || m_type == MITYPE_XTRACOMPS; // unused but what the heck + } char *GetName(void) { return m_name; } void SetName(const char *name) { strncpy(m_name, name, 24); } void SetColModel(CColModel *col, bool free = false){ diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 7567c0db..be091e9b 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -320,9 +320,12 @@ enum MI_CAR_PANEL, MI_CAR_BONNET, MI_CAR_BOOT, - MI_CAR_WEEL, + MI_CAR_WHEEL, MI_BODYPARTA, MI_BODYPARTB, + + MI_AIRTRAIN_VLO = 198, + MI_LOPOLYGUY, }; void InitModelIndices(void); diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp index 89fcdee5..ca36aa61 100644 --- a/src/modelinfo/ModelInfo.cpp +++ b/src/modelinfo/ModelInfo.cpp @@ -1,5 +1,7 @@ #include "common.h" #include "patcher.h" +#include "TempColModels.h" +#include "ModelIndices.h" #include "ModelInfo.h" CBaseModelInfo **CModelInfo::ms_modelInfoPtrs = (CBaseModelInfo**)0x83D408; @@ -18,6 +20,8 @@ void CModelInfo::Initialise(void) { int i; + CSimpleModelInfo *m; + for(i = 0; i < MODELINFOSIZE; i++) ms_modelInfoPtrs[i] = nil; ms_2dEffectStore.clear(); @@ -26,10 +30,58 @@ CModelInfo::Initialise(void) ms_clumpModelStore.clear(); ms_pedModelStore.clear(); ms_vehicleModelStore.clear(); + + m = AddSimpleModel(MI_CAR_DOOR); + m->SetColModel(&CTempColModels::ms_colModelDoor1); + m->SetTexDictionary("generic"); + m->SetNumAtomics(1); + m->m_lodDistances[0] = 80.0f; + + m = AddSimpleModel(MI_CAR_BUMPER); + m->SetColModel(&CTempColModels::ms_colModelBumper1); + m->SetTexDictionary("generic"); + m->SetNumAtomics(1); + m->m_lodDistances[0] = 80.0f; + + m = AddSimpleModel(MI_CAR_PANEL); + m->SetColModel(&CTempColModels::ms_colModelPanel1); + m->SetTexDictionary("generic"); + m->SetNumAtomics(1); + m->m_lodDistances[0] = 80.0f; + + m = AddSimpleModel(MI_CAR_BONNET); + m->SetColModel(&CTempColModels::ms_colModelBonnet1); + m->SetTexDictionary("generic"); + m->SetNumAtomics(1); + m->m_lodDistances[0] = 80.0f; + + m = AddSimpleModel(MI_CAR_BOOT); + m->SetColModel(&CTempColModels::ms_colModelBoot1); + m->SetTexDictionary("generic"); + m->SetNumAtomics(1); + m->m_lodDistances[0] = 80.0f; + + m = AddSimpleModel(MI_CAR_WHEEL); + m->SetColModel(&CTempColModels::ms_colModelWheel1); + m->SetTexDictionary("generic"); + m->SetNumAtomics(1); + m->m_lodDistances[0] = 80.0f; + + m = AddSimpleModel(MI_BODYPARTA); + m->SetColModel(&CTempColModels::ms_colModelBodyPart1); + m->SetTexDictionary("generic"); + m->SetNumAtomics(1); + m->m_lodDistances[0] = 80.0f; + + m = AddSimpleModel(MI_BODYPARTB); + m->SetColModel(&CTempColModels::ms_colModelBodyPart2); + m->SetTexDictionary("generic"); + m->SetNumAtomics(1); + m->m_lodDistances[0] = 80.0f; } void -CModelInfo::Shutdown(void) +CModelInfo::ShutDown(void) { int i; for(i = 0; i < ms_simpleModelStore.allocPtr; i++) @@ -42,6 +94,8 @@ CModelInfo::Shutdown(void) ms_pedModelStore.store[i].Shutdown(); for(i = 0; i < ms_vehicleModelStore.allocPtr; i++) ms_vehicleModelStore.store[i].Shutdown(); + for(i = 0; i < ms_2dEffectStore.allocPtr; i++) + ms_2dEffectStore.store[i].Shutdown(); } CSimpleModelInfo* @@ -115,10 +169,12 @@ CModelInfo::GetModelInfo(const char *name, int *id) } STARTPATCHES -// InjectHook(0x50B920, CModelInfo::AddSimpleModel, PATCH_JUMP); -// InjectHook(0x50B9C0, CModelInfo::AddTimeModel, PATCH_JUMP); -// InjectHook(0x50BA10, CModelInfo::AddClumpModel, PATCH_JUMP); -// InjectHook(0x50BAD0, CModelInfo::AddPedModel, PATCH_JUMP); -// InjectHook(0x50BA60, CModelInfo::AddPedModel, PATCH_JUMP); + InjectHook(0x50B310, CModelInfo::Initialise, PATCH_JUMP); + InjectHook(0x50B5B0, CModelInfo::ShutDown, PATCH_JUMP); + InjectHook(0x50B920, CModelInfo::AddSimpleModel, PATCH_JUMP); + InjectHook(0x50B9C0, CModelInfo::AddTimeModel, PATCH_JUMP); + InjectHook(0x50BA10, CModelInfo::AddClumpModel, PATCH_JUMP); + InjectHook(0x50BAD0, CModelInfo::AddPedModel, PATCH_JUMP); + InjectHook(0x50BA60, CModelInfo::AddVehicleModel, PATCH_JUMP); InjectHook(0x50B860, (CBaseModelInfo *(*)(const char*, int*))CModelInfo::GetModelInfo, PATCH_JUMP); ENDPATCHES diff --git a/src/modelinfo/ModelInfo.h b/src/modelinfo/ModelInfo.h index a0d30dea..4ab633bf 100644 --- a/src/modelinfo/ModelInfo.h +++ b/src/modelinfo/ModelInfo.h @@ -20,7 +20,7 @@ class CModelInfo public: static void Initialise(void); - static void Shutdown(void); + static void ShutDown(void); static CSimpleModelInfo *AddSimpleModel(int id); static CTimeModelInfo *AddTimeModel(int id); @@ -28,6 +28,8 @@ public: static CPedModelInfo *AddPedModel(int id); static CVehicleModelInfo *AddVehicleModel(int id); + static CStore<C2dEffect, TWODFXSIZE> &Get2dEffectStore(void) { return ms_2dEffectStore; } + static CBaseModelInfo *GetModelInfo(const char *name, int *id); static CBaseModelInfo *GetModelInfo(int id){ return ms_modelInfoPtrs[id]; diff --git a/src/modelinfo/PedModelInfo.h b/src/modelinfo/PedModelInfo.h index 95d49090..d0b93323 100644 --- a/src/modelinfo/PedModelInfo.h +++ b/src/modelinfo/PedModelInfo.h @@ -21,7 +21,7 @@ enum PedNode { class CPedModelInfo : public CClumpModelInfo { public: - void *m_animGroup; // TODO + int32 m_animGroup; int32 m_pedType; int32 m_pedStatType; uint32 m_carsCanDrive; diff --git a/src/modelinfo/SimpleModelInfo.cpp b/src/modelinfo/SimpleModelInfo.cpp index a5853d6f..ea7a3f9e 100644 --- a/src/modelinfo/SimpleModelInfo.cpp +++ b/src/modelinfo/SimpleModelInfo.cpp @@ -53,7 +53,7 @@ CSimpleModelInfo::Init(void) m_atomics[1] = nil; m_atomics[2] = nil; m_numAtomics = 0; - m_furthest = 0; + m_firstDamaged = 0; m_normalCull = 0; m_isDamaged = 0; m_isBigBuilding = 0; @@ -103,11 +103,10 @@ float CSimpleModelInfo::GetLargestLodDistance(void) { float d; - // TODO: what exactly is going on here? - if(m_furthest != 0 && !m_isDamaged) - d = m_lodDistances[m_furthest-1]; - else + if(m_firstDamaged == 0 || m_isDamaged) d = m_lodDistances[m_numAtomics-1]; + else + d = m_lodDistances[m_firstDamaged-1]; return d * TheCamera.LODDistMultiplier; } @@ -116,9 +115,8 @@ CSimpleModelInfo::GetAtomicFromDistance(float dist) { int i; i = 0; - // TODO: what exactly is going on here? if(m_isDamaged) - i = m_furthest; + i = m_firstDamaged; for(; i < m_numAtomics; i++) if(dist < m_lodDistances[i] *TheCamera.LODDistMultiplier) return m_atomics[i]; diff --git a/src/modelinfo/SimpleModelInfo.h b/src/modelinfo/SimpleModelInfo.h index 186a517c..d5b572a6 100644 --- a/src/modelinfo/SimpleModelInfo.h +++ b/src/modelinfo/SimpleModelInfo.h @@ -11,9 +11,9 @@ public: float m_lodDistances[3]; uint8 m_numAtomics; uint8 m_alpha; - uint16 m_furthest : 2; // 0: numAtomics-1 is furthest visible - // 1: atomic 0 is furthest - // 2: atomic 1 is furthest + uint16 m_firstDamaged : 2; // 0: no damage model + // 1: 1 and 2 are damage models + // 2: 2 is damage model uint16 m_normalCull : 1; uint16 m_isDamaged : 1; uint16 m_isBigBuilding : 1; diff --git a/src/modelinfo/TimeModelInfo.h b/src/modelinfo/TimeModelInfo.h index 08e46bd3..f8b7c8ff 100644 --- a/src/modelinfo/TimeModelInfo.h +++ b/src/modelinfo/TimeModelInfo.h @@ -12,7 +12,9 @@ public: int32 GetTimeOn(void) { return m_timeOn; } int32 GetTimeOff(void) { return m_timeOff; } + void SetTimes(int32 on, int32 off) { m_timeOn = on; m_timeOff = off; } int32 GetOtherTimeModel(void) { return m_otherTimeModelID; } + void SetOtherTimeModel(int32 other) { m_otherTimeModelID = other; } CTimeModelInfo *FindOtherTimeModel(void); }; static_assert(sizeof(CTimeModelInfo) == 0x58, "CTimeModelInfo: error"); diff --git a/src/modelinfo/VehicleModelInfo.h b/src/modelinfo/VehicleModelInfo.h index f69760b8..3f89414d 100644 --- a/src/modelinfo/VehicleModelInfo.h +++ b/src/modelinfo/VehicleModelInfo.h @@ -35,6 +35,17 @@ enum { NUM_VEHICLE_TYPES }; +enum { + VEHICLE_CLASS_POOR, + VEHICLE_CLASS_RICH, + VEHICLE_CLASS_EXECUTIVE, + VEHICLE_CLASS_WORKER, + VEHICLE_CLASS_SPECIAL, + VEHICLE_CLASS_BIG, + VEHICLE_CLASS_TAXI, + NUM_VEHICLE_CLASSES +}; + class CVehicleModelInfo : public CClumpModelInfo { public: diff --git a/src/re3.cpp b/src/re3.cpp index 905aa992..7fa9eedb 100644 --- a/src/re3.cpp +++ b/src/re3.cpp @@ -10,8 +10,6 @@ void **rwengine = *(void***)0x5A10E1; -GlobalScene &Scene = *(GlobalScene*)0x726768; - DebugMenuAPI gDebugMenuAPI; WRAPPER void *gtanew(uint32 sz) { EAXJMP(0x5A0690); } diff --git a/src/render/2dEffect.h b/src/render/2dEffect.h index 6cba85d1..780d9b4f 100644 --- a/src/render/2dEffect.h +++ b/src/render/2dEffect.h @@ -1,3 +1,9 @@ +enum { + EFFECT_LIGHT, + EFFECT_PARTICLE, + EFFECT_ATTRACTOR +}; + class C2dEffect { public: @@ -7,26 +13,26 @@ public: float size; float innerRange; uint8 flash; - uint8 wet; - uint8 flare; - uint8 shadowIntens; - uint8 flag; + uint8 roadReflection; + uint8 flareType; + uint8 shadowIntensity; + uint8 flags; RwTexture *corona; RwTexture *shadow; }; struct Particle { int particleType; - float dir[3]; + CVector dir; float scale; }; struct Attractor { CVector dir; - uint8 flag; + uint8 flags; uint8 probability; }; CVector pos; - RwRGBA col; + CRGBA col; uint8 type; union { Light light; @@ -35,5 +41,13 @@ public: }; C2dEffect(void) {} + void Shutdown(void){ + if(type == 0){ // TODO: enum + if(light.corona) + RwTextureDestroy(light.corona); + if(light.shadow) + RwTextureDestroy(light.shadow); + } + } }; static_assert(sizeof(C2dEffect) == 0x34, "C2dEffect: error"); diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index 5947a77f..64053007 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "General.h" #include "TxdStore.h" #include "Camera.h" diff --git a/src/render/ParticleMgr.cpp b/src/render/ParticleMgr.cpp index 15370b47..440ea9cb 100644 --- a/src/render/ParticleMgr.cpp +++ b/src/render/ParticleMgr.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "FileMgr.h" #include "ParticleMgr.h" diff --git a/src/render/PointLights.cpp b/src/render/PointLights.cpp index 0eb41821..2b840314 100644 --- a/src/render/PointLights.cpp +++ b/src/render/PointLights.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "Lights.h" #include "Camera.h" #include "Weather.h" diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 5a27ab32..bd16922c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "Lights.h" #include "ModelInfo.h" #include "Treadable.h" diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp index 92c3e8a6..57a8a22f 100644 --- a/src/render/Sprite.cpp +++ b/src/render/Sprite.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "Draw.h" #include "Camera.h" #include "Sprite.h" diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index 3dc1d989..4ed27fa1 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -1,5 +1,6 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "Draw.h" #include "Camera.h" #include "Sprite2d.h" diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index e1090f72..a8abe1dd 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -83,6 +83,7 @@ static psGlobalType &PsGlobal = *(psGlobalType*)0x72CF60; #include "common.h" #include "patcher.h" +#include "main.h" #include "FileMgr.h" #include "Text.h" #include "Pad.h" diff --git a/src/templates.h b/src/templates.h index 03e41a64..3ac0bc90 100644 --- a/src/templates.h +++ b/src/templates.h @@ -8,8 +8,10 @@ public: T store[n]; T *alloc(void){ - if(this->allocPtr >= n) + if(this->allocPtr >= n){ printf("Size of this thing:%d needs increasing\n", n); + assert(0); + } return &this->store[this->allocPtr++]; } void clear(void){ |