public void InitPostLoad() { switch (type) { // Fill these in after loading case DsgVarInfoEntry.DsgVarType.Perso: SuperObject so = SuperObject.FromOffset(valuePointer); if (so != null) { valuePerso = so.data as Perso; } break; case DsgVarInfoEntry.DsgVarType.Action: valueAction = State.FromOffset(valuePointer); break; case DsgVarInfoEntry.DsgVarType.SuperObject: valueSuperObject = SuperObject.FromOffset(valuePointer); break; } if (dsgMem != null) { RegisterReferences(dsgMem); } }
public void InitPostLoad() { switch (nodeType) { case NodeType.GraphRef: Graph graphRef = Graph.FromOffset(param_ptr); if (graphRef != null) { graphRef.References.referencedByNodes.Add(this); } else { Debug.LogWarning("Couldn't add ScriptNode reference to Graph offset " + param_ptr); } break; case NodeType.PersoRef: Perso persoRef = Perso.FromOffset(param_ptr); if (persoRef != null) { persoRef.References.referencedByNodes.Add(this); } else { Debug.LogWarning("Couldn't add ScriptNode reference to Perso offset " + param_ptr); } break; case NodeType.SectorRef: Sector sectorRef = Sector.FromOffset(param_ptr); if (sectorRef != null) { sectorRef.References.referencedByNodes.Add(this); } else { Debug.LogWarning("Couldn't add ScriptNode reference to Sector offset " + param_ptr); } break; case NodeType.SuperObjectRef: SuperObject superObjectRef = SuperObject.FromOffset(param_ptr); if (superObjectRef != null) { superObjectRef.References.referencedByNodes.Add(this); } else { Debug.LogWarning("Couldn't add ScriptNode reference to SuperObject offset " + param_ptr); } break; default: return; } }
public void Init() { if (MapLoader.Loader is OpenSpace.Loader.R3Loader) { MapLoader l = MapLoader.Loader; foreach (SuperObject so in l.superObjects) { if (so.type == SuperObject.Type.IPO_2) { //Debug.LogWarning("TYPE 2 " + so.Gao.name); Portal portal = new Portal() { containerSO = so, containerIPO = so.data as IPO }; portal.cameraSO = SuperObject.FromOffset(portal.containerIPO.off_portalCamera); GeometricObject geo = portal.containerIPO.data.visualSet[0].obj as GeometricObject; portal.geometricObject = geo; if (geo != null) { GeometricObjectElementTriangles el = geo.elements[0] as GeometricObjectElementTriangles; portal.meshElement = el; portal.material = el.Gao.GetComponent <Renderer>().sharedMaterial; //Debug.LogWarning(so.type + " - " + portal.containerIPO.offset + " - " + portal.containerIPO.off_portalCamera); if (portal.cameraSO != null) { GameObject camGao = new GameObject("Portal Camera - " + portal.containerIPO.Gao.name + " - " + portal.cameraSO.Gao.name); Camera camera = camGao.AddComponent <Camera>(); camGao.transform.position = portal.cameraSO.matrix.GetPosition(true); camGao.transform.rotation = portal.cameraSO.matrix.GetRotation(true) * Quaternion.Euler(-180, 0, 0); camGao.transform.localScale = portal.cameraSO.matrix.GetScale(true); camera.fieldOfView = Camera.main.fieldOfView; camera.enabled = false; camGao.transform.SetParent(transform); portal.camera = camera; portals.Add(portal); } else { // it's a mirror portal.isMirror = true; GameObject camGao = new GameObject("Mirror Camera - " + portal.containerIPO.Gao.name); Camera camera = camGao.AddComponent <Camera>(); camGao.transform.position = geo.vertices[0]; /*camGao.transform.rotation = portal.cameraSO.matrix.GetRotation(true) * Quaternion.Euler(-180, 0, 0); * camGao.transform.localScale = portal.cameraSO.matrix.GetScale(true);*/ camera.fieldOfView = Camera.main.fieldOfView; camera.enabled = false; camGao.transform.SetParent(transform); portal.camera = camera; portals.Add(portal); } el.Gao.layer = LayerMask.NameToLayer("VisualMirror"); PortalBehaviour pb = el.Gao.AddComponent <PortalBehaviour>(); pb.m_ReflectLayers = (1 << LayerMask.NameToLayer("Visual")) | (1 << LayerMask.NameToLayer("VisualOnlyInMirror")); pb.portal = portal; pb.textureIndex = portal.material.GetInt("_NumTextures"); portal.material.SetInt("_NumTextures", pb.textureIndex + 1); } } } } loaded = true; }
public string ToString(Perso perso, TranslatedScript.TranslationSettings ts, bool advanced = false) { MapLoader l = MapLoader.Loader; short mask = 0; AITypes aiTypes = Settings.s.aiTypes; Vector3 vector3 = new Vector3 { x = 0, y = 0, z = 0 }; switch (nodeType) { case ScriptNode.NodeType.KeyWord: // KeyWordFunctionPtr if (param < aiTypes.keywordTable.Length) { if (ts.exportMode) { if (aiTypes.keywordTable[param] == "Me") { return("this"); } if (aiTypes.keywordTable[param] == "MainActor") { return("Controller.MainActor"); } if (aiTypes.keywordTable[param] == "Nobody" || aiTypes.keywordTable[param] == "NoInput" || aiTypes.keywordTable[param] == "Nowhere" || aiTypes.keywordTable[param] == "NoGraph" || aiTypes.keywordTable[param] == "NoAction" || aiTypes.keywordTable[param] == "CapsNull") { return("null"); } } return(aiTypes.keywordTable[param]); } return("UnknownKeyword_" + param); case ScriptNode.NodeType.Condition: // GetConditionFunctionPtr if (param < aiTypes.conditionTable.Length) { return(aiTypes.conditionTable[param]); } return("UnknownCondition_" + param); case ScriptNode.NodeType.Operator: // GetOperatorFunctionPtr if (advanced) { if (param < aiTypes.operatorTable.Length) { return(aiTypes.operatorTable[param] + " (" + param + ")"); } } if (param < aiTypes.operatorTable.Length) { return(aiTypes.operatorTable[param]); } return("UnknownOperator_" + param); case ScriptNode.NodeType.Function: // GetFunctionFunctionPtr if (param < aiTypes.functionTable.Length) { return(aiTypes.functionTable[param]); } return("UnknownFunction_" + param); case ScriptNode.NodeType.Procedure: // ProcedureFunctionReturn if (param < aiTypes.procedureTable.Length) { return(aiTypes.procedureTable[param]); } return("UnknownProcedure_" + param); case ScriptNode.NodeType.MetaAction: // meta action if (param < aiTypes.metaActionTable.Length) { return(aiTypes.metaActionTable[param]); } return("UnknownMetaAction_" + param); case ScriptNode.NodeType.BeginMacro: return("BeginMacro"); case ScriptNode.NodeType.EndMacro: return("EndMacro"); case ScriptNode.NodeType.Field: if (param < aiTypes.fieldTable.Length) { return(aiTypes.fieldTable[param]); } return("UnknownField_" + param); case ScriptNode.NodeType.DsgVarRef: // Dsg Var if (perso != null && perso.brain != null && perso.brain.mind != null) { Mind mind = perso.brain.mind; if (mind.dsgMem != null && mind.dsgMem.dsgVar != null) { if (param < mind.dsgMem.dsgVar.dsgVarInfos.Length) { return(mind.dsgMem.dsgVar.dsgVarInfos[param].NiceVariableName); } } else if (mind.AI_model != null && mind.AI_model.dsgVar != null) { if (param < mind.AI_model.dsgVar.dsgVarInfos.Length) { return(mind.AI_model.dsgVar.dsgVarInfos[param].NiceVariableName); } } } return("dsgVar_" + param); case ScriptNode.NodeType.Constant: if (advanced) { return("Constant: " + BitConverter.ToInt32(BitConverter.GetBytes(param), 0)); } return(BitConverter.ToInt32(BitConverter.GetBytes(param), 0).ToString()); case ScriptNode.NodeType.Real: NumberFormatInfo nfi = new NumberFormatInfo() { NumberDecimalSeparator = "." }; if (advanced) { return("Real: " + BitConverter.ToSingle(BitConverter.GetBytes(param), 0).ToString(nfi)); } return(BitConverter.ToSingle(BitConverter.GetBytes(param), 0).ToString(nfi) + "f"); case ScriptNode.NodeType.Button: // Button/entryaction EntryAction ea = EntryAction.FromOffset(param_ptr); if (ea == null) { return("ERR_ENTRYACTION_NOTFOUND"); } string eaName = (advanced ? ea.ToString() : ea.ToBasicString()); if (advanced) { return("Button: " + eaName + "(" + param_ptr + ")"); } if (!ts.expandEntryActions && ea != null) { return("\"" + ea.ExportName + "\""); } return(eaName); case ScriptNode.NodeType.ConstantVector: return("Constant Vector: " + "0x" + param.ToString("x8")); // TODO: get from address case ScriptNode.NodeType.Vector: return("new Vector3"); // TODO: same case ScriptNode.NodeType.Mask: mask = (short)param; // TODO: as short if (advanced) { return("Mask: " + (mask).ToString("x4")); } if (ts.exportMode) { return("\"" + (mask).ToString("x4") + "\""); } return("Mask(" + (mask).ToString("x4") + ")"); case ScriptNode.NodeType.ModuleRef: if (advanced) { return("ModuleRef: " + "0x" + (param).ToString("x8")); } return("GetModule(" + (int)param + ")"); case ScriptNode.NodeType.DsgVarId: if (advanced) { return("DsgVarId: " + "0x" + (param).ToString("x8")); } return("DsgVarId(" + param + ")"); case ScriptNode.NodeType.String: string str = "ERR_STRING_NOTFOUND"; if (l.strings.ContainsKey(param_ptr)) { str = l.strings[param_ptr]; } if (advanced) { return("String: " + param_ptr + " (" + str + ")"); } return("\"" + str + "\""); case ScriptNode.NodeType.LipsSynchroRef: return("LipsSynchroRef: " + param_ptr); case ScriptNode.NodeType.FamilyRef: if (advanced) { return("FamilyRef: " + param_ptr); } Family f = Family.FromOffset(param_ptr); if (f != null) { return("GetFamily(\"" + f.name + "\")"); } else { return("Family.FromOffset(\"" + param_ptr + "\")"); } case ScriptNode.NodeType.PersoRef: Perso argPerso = Perso.FromOffset(param_ptr); if (argPerso != null && perso != null && argPerso.offset == perso.offset) { if (advanced) { return("PersoRef: this"); } return("this"); } string persoName = argPerso == null ? "ERR_PERSO_NOTFOUND" : argPerso.fullName; if (advanced) { return("PersoRef: " + param_ptr + " (" + persoName + ")"); } if (argPerso?.brain?.mind?.AI_model != null) { AIModel aiModel = argPerso.brain.mind.AI_model; // Make sure to add a cast in case the AI Model is accessed return("((" + aiModel.name + ")GetPerso(\"" + argPerso.namePerso + "\"))"); } return("GetPerso(\"" + argPerso.namePerso + "\")"); case ScriptNode.NodeType.ActionRef: State state = State.FromOffset(param_ptr); string stateName = state == null ? "ERR_STATE_NOTFOUND" : state.ShortName; if (advanced) { return("ActionRef: " + param_ptr + " " + stateName); } if (ts.useStateIndex) { return("GetAction(" + state.index.ToString() + ")"); } return(stateName); case ScriptNode.NodeType.SuperObjectRef: if (advanced) { return("SuperObjectRef: " + param_ptr); } SuperObject so = SuperObject.FromOffset(param_ptr); if (so != null) { return("GetSuperObject(\"" + so.Gao.name + "\")"); } else { return("SuperObject.FromOffset(\"" + param_ptr + "\")"); } case ScriptNode.NodeType.WayPointRef: if (advanced) { return("WayPointRef: " + param_ptr); } return("WayPoint.FromOffset(\"" + param_ptr + "\")"); case ScriptNode.NodeType.TextRef: if (l.localization == null) { return("TextRef"); } if (advanced) { return("TextRef: " + param + " (" + l.localization.GetTextForHandleAndLanguageID((int)param, 0) + ")"); } if (ts.expandStrings) { return("\"" + l.localization.GetTextForHandleAndLanguageID((int)param, 0) + "\""); // Preview in english } else { return("new TextReference(" + (int)param + ")"); } case ScriptNode.NodeType.ComportRef: Behavior comportRef = Behavior.FromOffset(param_ptr); if (comportRef == null) { if (advanced) { return("ComportRef: " + param_ptr + " (null)"); } return("null"); } else { return(comportRef.ShortName); //string type = comportRef.type == Behavior.BehaviorType.Normal ? "normalBehavior" : "reflexBehavior"; //return type + "[" + script.behaviorOrMacro.aiModel.GetBehaviorIndex(comportRef) + "]"; } case ScriptNode.NodeType.SoundEventRef: if (advanced) { return("SoundEventRef: " + (int)param); } return("SoundEvent.FromID(0x" + ((int)param).ToString("X8") + ")"); case ScriptNode.NodeType.ObjectTableRef: if (advanced) { return("ObjectTableRef: " + param_ptr); } if (ts.useHashIdentifiers) { string objectListJson = ObjectList.FromOffset(param_ptr).ToJSON(); string objectListHash = HashUtils.MD5Hash(objectListJson); return("ObjectList.FromHash(\"" + objectListHash + "\")"); } return("ObjectTable.FromOffset(\"" + param_ptr + "\")"); case ScriptNode.NodeType.GameMaterialRef: if (advanced) { return("GameMaterialRef: " + param_ptr); } if (ts.useHashIdentifiers) { string gmtJson = GameMaterial.FromOffset(param_ptr).ToJSON(); string gmtHash = HashUtils.MD5Hash(gmtJson); return("GameMaterial.FromHash(\"" + gmtHash + "\")"); } return("GameMaterial.FromOffset(\"" + param_ptr + "\")"); case ScriptNode.NodeType.ParticleGenerator: return("ParticleGenerator: " + "0x" + (param).ToString("x8")); case ScriptNode.NodeType.VisualMaterial: if (advanced) { return("VisualMaterial: " + param_ptr); } if (ts.useHashIdentifiers) { string vmtJson = VisualMaterial.FromOffset(param_ptr).ToJSON(); string vmtHash = HashUtils.MD5Hash(vmtJson); return("VisualMaterial.FromHash(\"" + vmtHash + "\")"); } return("VisualMaterial.FromOffset(\"" + param_ptr + "\")"); case ScriptNode.NodeType.ModelRef: // ModelCast if (advanced) { return("AIModel: " + param_ptr); } AIModel model = AIModel.FromOffset(param_ptr); return(model != null ? model.name : "null"); case ScriptNode.NodeType.DataType42: if (advanced) { return("EvalDataType42: " + "0x" + (param).ToString("x8")); } return("EvalDataType42(" + "0x" + (param).ToString("x8") + ")"); case ScriptNode.NodeType.CustomBits: if (advanced) { return("CustomBits: " + "0x" + (param).ToString("x8")); } if (ts.exportMode) { return("0x" + (param).ToString("x8")); } return("CustomBits(" + "0x" + (param).ToString("x8") + ")"); case ScriptNode.NodeType.Caps: if (advanced) { return("Caps: " + "0x" + (param).ToString("x8")); } if (ts.exportMode) { return("0x" + (param).ToString("x8")); } return("Caps(" + "0x" + (param).ToString("x8") + ")"); case ScriptNode.NodeType.SubRoutine: if (advanced) { return("Eval SubRoutine: " + param_ptr); } Macro macro = Macro.FromOffset(param_ptr); if (macro == null) { return("null"); } return("evalMacro(" + macro.ShortName + ");"); case ScriptNode.NodeType.Null: return("null"); case ScriptNode.NodeType.GraphRef: if (advanced) { return("Graph: " + "0x" + (param).ToString("x8")); } return("Graph.FromOffset(\"" + param_ptr + "\")"); } return("unknown"); }
private JSONObject GetDsgVarJSON(Perso perso, DsgVarComponent.DsgVarEditableEntry dsg) { JSONObject dsgObj = new JSONObject(); dsgObj["name"] = dsg.entry.NiceVariableName; dsgObj["type"] = dsg.entry.type.ToString(); switch (dsg.entry.type) { case DsgVarInfoEntry.DsgVarType.Boolean: dsgObj["value"] = dsg.valueAsBool; break; case DsgVarInfoEntry.DsgVarType.Int: dsgObj["value"] = dsg.valueAsInt; break; case DsgVarInfoEntry.DsgVarType.UInt: dsgObj["value"] = dsg.valueAsUInt; break; case DsgVarInfoEntry.DsgVarType.Short: dsgObj["value"] = dsg.valueAsShort; break; case DsgVarInfoEntry.DsgVarType.UShort: dsgObj["value"] = dsg.valueAsUShort; break; case DsgVarInfoEntry.DsgVarType.Byte: dsgObj["value"] = dsg.valueAsByte; break; case DsgVarInfoEntry.DsgVarType.UByte: dsgObj["value"] = dsg.valueAsByte; break; case DsgVarInfoEntry.DsgVarType.Float: dsgObj["value"] = dsg.valueAsFloat; break; case DsgVarInfoEntry.DsgVarType.Text: dsgObj["value"] = dsg.valueAsString; break; case DsgVarInfoEntry.DsgVarType.Vector: dsgObj["value"] = dsg.valueAsVector; break; case DsgVarInfoEntry.DsgVarType.Perso: if (dsg.entry.value != null) { SuperObject so = SuperObject.FromOffset(dsg.entry.value as Pointer); if (so != null && so.type == SuperObject.Type.Perso && so.data != null) { Perso p = so.data as Perso; if (p != null) { JSONObject persoJSON = new JSONObject(); persoJSON["offset"] = p.offset.ToString(); persoJSON["nameFamily"] = p.nameFamily; persoJSON["nameModel"] = p.nameModel; persoJSON["nameInstance"] = p.namePerso; dsgObj["value"] = persoJSON; } } } break; case DsgVarInfoEntry.DsgVarType.SuperObject: SuperObject spo = SuperObject.FromOffset(dsg.entry.value as Pointer); if (spo != null) { JSONObject soJSON = new JSONObject(); soJSON["offset"] = spo.offset.ToString(); soJSON["type"] = spo.type.ToString(); soJSON["offset"] = spo.offset.ToString(); if (spo.type == SuperObject.Type.Perso && spo.data != null) { Perso p = spo.data as Perso; if (p != null) { JSONObject persoJSON = new JSONObject(); persoJSON["offset"] = p.offset.ToString(); persoJSON["nameFamily"] = p.nameFamily; persoJSON["nameModel"] = p.nameModel; persoJSON["nameInstance"] = p.namePerso; soJSON["perso"] = persoJSON; } } dsgObj["value"] = soJSON; } break; } return(dsgObj); }
async Task LoadLVL() { loadingState = "Loading level memory"; await WaitIfNecessary(); files_array[Mem.Lvl].GotoHeader(); Reader reader = files_array[Mem.Lvl].reader; long totalSize = reader.BaseStream.Length; //reader.ReadUInt32(); if (Settings.s.game == Settings.Game.R3 && (Settings.s.platform == Settings.Platform.PC || Settings.s.platform == Settings.Platform.Xbox || Settings.s.platform == Settings.Platform.Xbox360 || Settings.s.platform == Settings.Platform.PS3)) { reader.ReadUInt32(); // fix checksum? } reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); if (Settings.s.platform == Settings.Platform.PC || Settings.s.platform == Settings.Platform.Xbox || Settings.s.platform == Settings.Platform.Xbox360 || Settings.s.platform == Settings.Platform.PS3) { if (Settings.s.game == Settings.Game.R3) { string timeStamp = reader.ReadString(0x18); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); } else if (Settings.s.game == Settings.Game.RM || Settings.s.game == Settings.Game.RA || Settings.s.game == Settings.Game.Dinosaur) { reader.ReadUInt32(); reader.ReadUInt32(); } } reader.ReadBytes(0x104); // vignette if (Settings.s.game != Settings.Game.Dinosaur) { reader.ReadUInt32(); } loadingState = "Loading level textures"; await ReadTexturesLvl(reader, Pointer.Current(reader)); if ((Settings.s.platform == Settings.Platform.PC || Settings.s.platform == Settings.Platform.Xbox || Settings.s.platform == Settings.Platform.Xbox360 || Settings.s.platform == Settings.Platform.PS3) && !hasTransit && Settings.s.game != Settings.Game.Dinosaur) { Pointer off_lightMapTexture = Pointer.Read(reader); // g_p_stLMTexture Pointer.DoAt(ref reader, off_lightMapTexture, () => { lightmapTexture = TextureInfo.Read(reader, off_lightMapTexture); }); if (Settings.s.game == Settings.Game.R3) { Pointer off_overlightTexture = Pointer.Read(reader); // *(_DWORD *)(GLI_BIG_GLOBALS + 370068) Pointer.DoAt(ref reader, off_overlightTexture, () => { overlightTexture = TextureInfo.Read(reader, off_overlightTexture); }); } } Pointer off_animBankLvl = null; if (Settings.s.game == Settings.Game.Dinosaur) { // animation bank is read right here. off_animBankLvl = Pointer.Current(reader); // Note: only one 0x104 bank in fix. print("Lvl animation bank address: " + off_animBankLvl); animationBanks = new AnimationBank[5]; AnimationBank[] banks = AnimationBank.Read(reader, off_animBankLvl, 0, 1, files_array[Mem.LvlKeyFrames]); animationBanks[0] = banks[0]; } loadingState = "Loading globals"; await WaitIfNecessary(); globals.off_transitDynamicWorld = null; globals.off_actualWorld = Pointer.Read(reader); globals.off_dynamicWorld = Pointer.Read(reader); if (Settings.s.game == Settings.Game.R3 && (Settings.s.platform == Settings.Platform.PC || Settings.s.platform == Settings.Platform.Xbox || Settings.s.platform == Settings.Platform.Xbox360 || Settings.s.platform == Settings.Platform.PS3)) { reader.ReadUInt32(); // ??? } globals.off_inactiveDynamicWorld = Pointer.Read(reader); globals.off_fatherSector = Pointer.Read(reader); // It is I, Father Sector. globals.off_firstSubMapPosition = Pointer.Read(reader); globals.num_always = reader.ReadUInt32(); globals.spawnablePersos = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double); globals.off_always_reusableSO = Pointer.Read(reader); // There are (num_always) empty SuperObjects starting with this one. globals.off_always_reusableUnknown1 = Pointer.Read(reader); // (num_always) * 0x2c blocks globals.off_always_reusableUnknown2 = Pointer.Read(reader); // (num_always) * 0x4 blocks // Read object types objectTypes = new ObjectType[3][]; for (uint i = 0; i < 3; i++) { Pointer off_names_header = Pointer.Current(reader); Pointer off_names_first = Pointer.Read(reader); Pointer off_names_last = Pointer.Read(reader); uint num_names = reader.ReadUInt32(); ReadObjectNamesTable(reader, off_names_first, num_names, i); } Pointer off_light = Pointer.Read(reader); // the offset of a light. It's just an ordinary light. Pointer off_characterLaunchingSoundEvents = Pointer.Read(reader); Pointer off_collisionGeoObj = Pointer.Read(reader); Pointer off_staticCollisionGeoObj = Pointer.Read(reader); if (!hasTransit) { reader.ReadUInt32(); // viewport related <--- cameras in here } Pointer off_unknown_first = Pointer.Read(reader); Pointer off_unknown_last = Pointer.Read(reader); uint num_unknown = reader.ReadUInt32(); families = LinkedList <Family> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double); Pointer off_alwaysActiveCharacters_first = Pointer.Read(reader); Pointer off_alwaysActiveCharacters_last = Pointer.Read(reader); uint num_alwaysActiveChars = reader.ReadUInt32(); if (!hasTransit) { Pointer off_mainCharacters_first = Pointer.Read(reader); Pointer off_mainCharacters_last = Pointer.Read(reader); uint num_mainCharacters_entries = reader.ReadUInt32(); } reader.ReadUInt32(); // only used if there was no transit in the previous lvl. Always 00165214 in R3GC? reader.ReadUInt32(); // related to "SOL". What is this? Good question. reader.ReadUInt32(); // same if (Settings.s.game != Settings.Game.Dinosaur) { reader.ReadUInt32(); // same } Pointer off_cineManager = Pointer.Read(reader); byte unk = reader.ReadByte(); byte IPO_numRLItables = reader.ReadByte(); reader.ReadUInt16(); Pointer off_COL_taggedFacesTable = Pointer.Read(reader); uint num_COL_maxTaggedFaces = reader.ReadUInt32(); off_collisionGeoObj = Pointer.Read(reader); off_staticCollisionGeoObj = Pointer.Read(reader); // The ptrsTable seems to be related to sound events. Perhaps cuuids. reader.ReadUInt32(); if (Settings.s.game == Settings.Game.Dinosaur) { for (int i = 0; i < 50; i++) { reader.ReadUInt32(); } // Actually, the previous uint is an amount for this array of uints, but it's padded to always be 50 long } uint num_ptrsTable = reader.ReadUInt32(); if (Settings.s.game == Settings.Game.R3) { uint bool_ptrsTable = reader.ReadUInt32(); } Pointer off_ptrsTable = Pointer.Read(reader); uint num_internalStructure = num_ptrsTable; if (Settings.s.mode == Settings.Mode.Rayman3GC) { reader.ReadUInt32(); } Pointer off_internalStructure_first = Pointer.Read(reader); Pointer off_internalStructure_last = Pointer.Read(reader); if (!hasTransit && Settings.s.game == Settings.Game.R3) { uint num_geometric = reader.ReadUInt32(); Pointer off_array_geometric = Pointer.Read(reader); Pointer off_array_geometric_RLI = Pointer.Read(reader); Pointer off_array_transition_flags = Pointer.Read(reader); } else if (Settings.s.game == Settings.Game.RA || Settings.s.game == Settings.Game.RM || Settings.s.game == Settings.Game.Dinosaur || Settings.s.game == Settings.Game.DDPK) { uint num_unk = reader.ReadUInt32(); Pointer unk_first = Pointer.Read(reader); if (Settings.s.game != Settings.Game.Dinosaur) { Pointer unk_last = Pointer.Read(reader); } } uint num_visual_materials = reader.ReadUInt32(); Pointer off_array_visual_materials = Pointer.Read(reader); if (Settings.s.mode != Settings.Mode.RaymanArenaGC && Settings.s.mode != Settings.Mode.RaymanArenaGCDemo && Settings.s.mode != Settings.Mode.DonaldDuckPKGC) { Pointer off_dynamic_so_list = Pointer.Read(reader); // Parse SO list Pointer.DoAt(ref reader, off_dynamic_so_list, () => { LinkedList <SuperObject> .ReadHeader(reader, off_dynamic_so_list); /*Pointer off_so_list_first = Pointer.Read(reader); * Pointer off_so_list_last = Pointer.Read(reader); * Pointer off_so_list_current = off_so_list_first; * uint num_so_list = reader.ReadUInt32();*/ /*if (experimentalObjectLoading) { * for (uint i = 0; i < num_so_list; i++) { * R3Pointer.Goto(ref reader, off_so_list_current); * R3Pointer off_so_list_next = R3Pointer.Read(reader); * R3Pointer off_so_list_prev = R3Pointer.Read(reader); * R3Pointer off_so_list_start = R3Pointer.Read(reader); * R3Pointer off_so = R3Pointer.Read(reader); * R3Pointer.Goto(ref reader, off_so); * ParseSuperObject(reader, off_so, true, true); * off_so_list_current = off_so_list_next; * } * }*/ }); } // Parse materials list loadingState = "Loading visual materials"; await WaitIfNecessary(); Pointer.DoAt(ref reader, off_array_visual_materials, () => { for (uint i = 0; i < num_visual_materials; i++) { Pointer off_material = Pointer.Read(reader); Pointer.DoAt(ref reader, off_material, () => { //print(Pointer.Current(reader)); visualMaterials.Add(VisualMaterial.Read(reader, off_material)); }); } }); if (hasTransit) { loadingState = "Loading transit memory"; await WaitIfNecessary(); Pointer off_transit = new Pointer(16, files_array[Mem.Transit]); // It's located at offset 20 in transit Pointer.DoAt(ref reader, off_transit, () => { if (Settings.s.platform == Settings.Platform.PC || Settings.s.platform == Settings.Platform.Xbox || Settings.s.platform == Settings.Platform.Xbox360 || Settings.s.platform == Settings.Platform.PS3) { Pointer off_lightMapTexture = Pointer.Read(reader); // g_p_stLMTexture Pointer.DoAt(ref reader, off_lightMapTexture, () => { lightmapTexture = TextureInfo.Read(reader, off_lightMapTexture); }); if (Settings.s.game == Settings.Game.R3) { Pointer off_overlightTexture = Pointer.Read(reader); // *(_DWORD *)(GLI_BIG_GLOBALS + 370068) Pointer.DoAt(ref reader, off_overlightTexture, () => { overlightTexture = TextureInfo.Read(reader, off_overlightTexture); }); } } globals.off_transitDynamicWorld = Pointer.Read(reader); globals.off_actualWorld = Pointer.Read(reader); globals.off_dynamicWorld = Pointer.Read(reader); globals.off_inactiveDynamicWorld = Pointer.Read(reader); }); } // Parse actual world & always structure loadingState = "Loading families"; await WaitIfNecessary(); ReadFamilies(reader); loadingState = "Loading superobject hierarchy"; await WaitIfNecessary(); ReadSuperObjects(reader); loadingState = "Loading always structure"; await WaitIfNecessary(); ReadAlways(reader); Pointer.DoAt(ref reader, off_cineManager, () => { cinematicsManager = CinematicsManager.Read(reader, off_cineManager); }); // off_current should be after the dynamic SO list positions. // Parse transformation matrices and other settings(state? :o) for fix characters loadingState = "Loading settings for persos in fix"; await WaitIfNecessary(); uint num_perso_with_settings_in_fix = (uint)persoInFix.Length; if (Settings.s.game == Settings.Game.R3) { num_perso_with_settings_in_fix = reader.ReadUInt32(); } for (int i = 0; i < num_perso_with_settings_in_fix; i++) { Pointer off_perso_so_with_settings_in_fix = null, off_matrix = null; SuperObject so = null; Matrix mat = null; if (Settings.s.game == Settings.Game.R3) { off_perso_so_with_settings_in_fix = Pointer.Read(reader); off_matrix = Pointer.Current(reader); mat = Matrix.Read(reader, off_matrix); reader.ReadUInt32(); // is one of these the state? doesn't appear to change tho reader.ReadUInt32(); so = SuperObject.FromOffset(off_perso_so_with_settings_in_fix); } else if (Settings.s.game == Settings.Game.RA || Settings.s.game == Settings.Game.RM || Settings.s.game == Settings.Game.Dinosaur) { off_matrix = Pointer.Current(reader); mat = Matrix.Read(reader, off_matrix); so = superObjects.FirstOrDefault(s => s.off_data == persoInFix[i]); } if (so != null) { so.off_matrix = off_matrix; so.matrix = mat; if (so.Gao != null) { so.Gao.transform.localPosition = mat.GetPosition(convertAxes: true); so.Gao.transform.localRotation = mat.GetRotation(convertAxes: true); so.Gao.transform.localScale = mat.GetScale(convertAxes: true); } } } if (Settings.s.platform == Settings.Platform.GC) { reader.ReadBytes(0x800); // floats } loadingState = "Loading animation banks"; await WaitIfNecessary(); if (Settings.s.game != Settings.Game.Dinosaur) { off_animBankLvl = Pointer.Read(reader); // Note: 4 0x104 banks in lvl. print("Lvl animation bank address: " + off_animBankLvl); animationBanks = new AnimationBank[5]; if (off_animBankFix != off_animBankLvl) { Pointer.DoAt(ref reader, off_animBankFix, () => { animationBanks[0] = AnimationBank.Read(reader, off_animBankFix, 0, 1, files_array[Mem.FixKeyFrames])[0]; }); } Pointer.DoAt(ref reader, off_animBankLvl, () => { AnimationBank[] banks = AnimationBank.Read(reader, off_animBankLvl, 1, 4, files_array[Mem.LvlKeyFrames]); for (int i = 0; i < 4; i++) { animationBanks[1 + i] = banks[i]; } }); if (off_animBankFix == off_animBankLvl) { animationBanks[0] = animationBanks[1]; } } // Load additional animation banks string extraAnimFolder = "Anim/"; if (Settings.s.mode == Settings.Mode.RaymanArenaGCDemo) { extraAnimFolder = lvlName + "/"; } for (int i = 0; i < families.Count; i++) { if (families[i] != null && families[i].animBank > 4 && objectTypes[0][families[i].family_index].id != 0xFF) { int animBank = families[i].animBank; loadingState = "Loading additional animation bank " + animBank; await WaitIfNecessary(); int animFileID = objectTypes[0][families[i].family_index].id; if (Settings.s.mode == Settings.Mode.RaymanArenaGCDemo) { animFileID = animBank - 5; } string animName = extraAnimFolder + "ani" + animFileID.ToString(); string kfName = extraAnimFolder + "key" + animFileID.ToString() + "kf"; //print(animBank + " - " + objectTypes[0][families[i].family_index].id); int fileID = animBank + 102; int kfFileID = animBank + 2; // Anim bank will start at 5, so this will start at 7 if (Settings.s.game == Settings.Game.RM) { fileID = animBank; } // Prepare files for WebGL await PrepareFile(gameDataBinFolder + animName + ".lvl"); if (FileSystem.FileExists(gameDataBinFolder + animName + ".lvl")) { await PrepareFile(gameDataBinFolder + animName + ".ptr"); } await PrepareFile(gameDataBinFolder + kfName + ".lvl"); if (FileSystem.FileExists(gameDataBinFolder + kfName + ".lvl")) { await PrepareFile(gameDataBinFolder + kfName + ".ptr"); } FileWithPointers animFile = InitExtraLVL(animName, fileID); FileWithPointers kfFile = InitExtraLVL(kfName, fileID); if (animFile != null) { if (animBank >= animationBanks.Length) { Array.Resize(ref animationBanks, animBank + 1); } Pointer off_animBankExtra = new Pointer(0, animFile); Pointer.DoAt(ref reader, off_animBankExtra, () => { int alignBytes = reader.ReadInt32(); if (alignBytes > 0) { reader.Align(4, alignBytes); } off_animBankExtra = Pointer.Current(reader); animationBanks[animBank] = AnimationBank.Read(reader, off_animBankExtra, (uint)animBank, 1, kfFile)[0]; }); } } } loadingState = "Filling in cross-references"; await WaitIfNecessary(); ReadCrossReferences(reader); }