private void HandleStrafing(Quaternion rotation, SuperObject *rayman, float strafeX, float strafeY) { float strafeSpeed = (float)Math.Sqrt(strafeX * strafeX + strafeY * strafeY); float *padAnalogForce = ((float *)0x4B9B78); *padAnalogForce = strafeSpeed; float *padTrueAnalogForce = ((float *)0x4B9B7C); *padTrueAnalogForce = strafeSpeed; float *padGlobalX = ((float *)0x4B9B68); float *padGlobalY = ((float *)0x4B9B6C); Vector3 rotationEuler = rotation.ToEuler(); double strafeAngle = Math.Atan2(strafeY, strafeX); if (double.IsNaN(strafeAngle) || double.IsInfinity(strafeAngle)) { strafeAngle = 0; } *padGlobalX = strafeSpeed * (float)Math.Sin(rotationEuler.Z - strafeAngle + quarterTau); *padGlobalY = strafeSpeed * -(float)Math.Cos(rotationEuler.Z - strafeAngle + quarterTau); float *padRotationAngle = ((float *)0x4B9B80); *padRotationAngle = (float)(strafeAngle * 180 / Math.PI); int *padSector = ((int *)0x4B9B84); *padSector = GetPadSector(strafeX, strafeY); }
public int MarioFunction(SuperObject *spo, int *nodeInterp) { RaymanState state = RaymanState.Inactive; byte dsgVar16_value = 0; int * idleTimer = null; if (spo->PersoData->GetModelName(w) == "YLT_RaymanModel") { var dsgVars = spo->PersoData->GetDsgVarList(); dsgVar16_value = *(byte *)dsgVars[16].valuePtrCurrent.ToPointer(); byte dsgVar9_value = *(byte *)dsgVars[9].valuePtrCurrent.ToPointer(); state = (RaymanState)dsgVar9_value; idleTimer = (int *)dsgVars[24].valuePtrCurrent; } bool strafing = InputStructure.GetInputStructure()->GetEntryAction(EntryActionNames.Action_Strafe)->IsValidated(); if (spo->PersoData->GetInstanceName(w) != "Rayman" || dsgVar16_value != 1 || !AllowTankControlState(state)) { currentSpeed = 0; return(EngineFunctions.fn_p_stReadAnalogJoystickMario.Call(spo, nodeInterp)); } int result = OriginalScript(spo, nodeInterp); DoTankControls(spo, state, strafing, idleTimer); return(result); }
private void RandomizeAllObjects(World world) { world.ReadObjectNames(); Dictionary <string, Pointer <SuperObject> > superObjects = world.GetActiveSuperObjects(); foreach (SuperObject *superObject in superObjects.Values) { Perso *perso = (Perso *)superObject->engineObjectPtr; int aiModelID = perso->stdGamePtr->modelID; string aiModelName = world.ObjectNames[ObjectSet.Model][aiModelID]; if (aiModelName == "DS1_GEN_PTC_GenCKS" || aiModelName == "DS1_GEN_PTC_GenBigFile") { perso->brain = null; continue; } RandomizeObject(superObject); } SuperObject *global = superObjects["global"]; DsgMem * dsgMem = ((Perso *)global->engineObjectPtr)->brain->mind->dsgMem; DsgVar * dsgVars = *dsgMem->dsgVar; DsgVarInfo info = dsgVars->dsgVarInfos[63]; bool *bool63 = (bool *)((int)dsgMem->memoryBufferCurrent + info.offsetInBuffer); *bool63 = false; }
public Dictionary <string, Pointer <SuperObject> > GetActiveSuperObjects() { const int offDynamWorld = 0x0500FD0; Dictionary <string, Pointer <SuperObject> > result = new Dictionary <string, Pointer <SuperObject> >(); SuperObject *superObject = (SuperObject *)Memory.GetPointerAtOffset(offDynamWorld, 0x8, 0x0); while (superObject != null) { Perso *perso = (Perso *)superObject->engineObjectPtr; if (perso != null) { StandardGame *offStdGame = perso->stdGamePtr; int nameIndex = offStdGame->instanceID; string name = $"unknown_{(int)superObject:X}"; if (nameIndex >= 0 && nameIndex < ObjectNames[ObjectSet.Instance].Length) { name = ObjectNames[ObjectSet.Instance][nameIndex]; } if (!result.ContainsKey(name)) { result.Add(name, superObject); } } superObject = superObject->nextBrother; } return(result); }
public TreeNode NewTreeNode(string text, IconId iconId, SuperObject *tag = null) { TreeNode node = new TreeNode(text, (int)iconId, (int)iconId); node.Name = text; node.Tag = tag == null ? null : (Pointer <SuperObject>)tag; return(node); }
private char PLA_fn_bSetNewState(SuperObject *persoSpo, LinkedList.ListElement_HHP <State> *state, char force, char withEvents, char setAnim) { if (persoSpo == rayman && playTurnAnimation) { int stateIndex = persoSpo->PersoData->GetStateIndex(state); if (stateIndex == 0) { return((char)0); } } return(EngineFunctions.PLA_fn_bSetNewState.Call(persoSpo, state, force, withEvents, setAnim)); }
private static int OriginalScript(SuperObject *spo, int *nodeInterp) { // This is necessary because the script calls this function as "StdCamer.PAD_ReadAnalogJoystickMarioMode", // and the scripting engine keeps track of which object is executing a function (two ultra operator functions) *(int *)(Offsets.Globals.g_hCurrentSuperObjPerso) = 0; int *param = (int *)Marshal.AllocHGlobal(512); int *v4 = (int *)EngineFunctions.fn_p_stEvalTree.Call(spo, nodeInterp, param); int *v5 = (int *)EngineFunctions.fn_p_stEvalTree.Call(spo, v4, param); int *v7 = (int *)EngineFunctions.fn_p_stEvalTree.Call(spo, v5, param); int *v8 = (int *)EngineFunctions.fn_p_stEvalTree.Call(spo, v7, param); int *v9 = (int *)EngineFunctions.fn_p_stEvalTree.Call(spo, v8, param); // dsgVar_16 ? 1f : 0f int *v10 = (int *)EngineFunctions.fn_p_stEvalTree.Call(spo, v9, param); return(EngineFunctions.fn_p_stEvalTree.Call(spo, v10, param)); }
public int GenerateAlwaysObject(SuperObject *spawnedBy, Perso *alwaysPerso, Vector3 position) { if (spawnedBy == null) { throw new NullReferenceException("GenerateAlwaysObject: spawnedBy is not allowed to be null!"); } int[] interp = { 0x00000042, // Func_GenerateObj 0x03020000, (int)alwaysPerso, // arg0, Perso to generate 0x17030000, // arg1, Vector3 0x00000000, 0x10030000, BitConverter.ToInt32(BitConverter.GetBytes(position.X), 0), // x 0x0D040000, BitConverter.ToInt32(BitConverter.GetBytes(position.Y), 0), // y 0x0D040000, BitConverter.ToInt32(BitConverter.GetBytes(position.Z), 0), // z 0x0D040000, }; // TODO: use ArrayPtr() IntPtr interpArray = Marshal.AllocHGlobal(interp.Length * 4); for (int i = 0; i < interp.Length; i++) { Marshal.WriteInt32(interpArray, i * 4, interp[i]); } IntPtr paramArray = Marshal.AllocHGlobal(0x20 * 4); IntPtr interpPtrStart = interpArray + 0x8; // we start at the second node of the interpreter tree EngineFunctions.MiscFunction.Call((int)spawnedBy, (int)interpPtrStart, (int)paramArray); return(*(int *)paramArray.ToPointer()); }
public static extern int XAI_fn_lEnumSpoDsgVars(SuperObject *p_stSpo, XAI_tdfnEnumDsgVarCallback p_fnCallback);
public static extern int XHIE_fn_lEnumSpoChildren(SuperObject *p_stSpo, XHIE_tdfnEnumSpoCallback p_fnCallback);
public static extern string XHIE_fn_szGetObjectName(SuperObject *p_stSpo, XHIE_OI_TYPE ulInfoType);
private void DoTankControls(SuperObject *spo, RaymanState state, bool strafing, int *idleTimer) { EntryAction *leftAction = *(EntryAction **)0x4B9B90; EntryAction *rightAction = *(EntryAction **)0x4B9B94; EntryAction *forwardAction = *(EntryAction **)0x4B9B88; EntryAction *backAction = *(EntryAction **)0x4B9B8C; EntryAction *shiftAction = *(EntryAction **)0x4B9B98; rayman = spo; var transformationMatrix = rayman->PersoData->dynam->DynamicsAsBigDynamics->matrixA.TransformationMatrix; var rotation = Quaternion.CreateFromRotationMatrix(transformationMatrix); float rotationSpeedTarget = ((leftAction->IsValidated() ? 1f : 0) + (rightAction->IsValidated() ? -1f : 0)) * maxRotationSpeed * (shiftAction->IsValidated()?0.75f:1f); if (state == RaymanState.Swimming || state == RaymanState.Sliding) { rotationSpeedTarget *= 8.0f; } // Interpolate to target speed rotationSpeed += (rotationSpeedTarget - rotationSpeed) * rotationSpeedLerp; if (state == RaymanState.LedgeGrab) { if (forwardAction->IsValidated()) { currentSpeed = 10; } else if (backAction->IsValidated()) { currentSpeed = -10; } else { currentSpeed = 0; } } else if (strafing && state != RaymanState.Swimming && state != RaymanState.Sliding) { float strafeX = ((leftAction->IsValidated() ? 1f : 0) + (rightAction->IsValidated() ? -1f : 0)); float strafeY = ((forwardAction->IsValidated() ? 1f : 0) + (backAction->IsValidated() ? -1f : 0)); float strafeMagnitude = (float)Math.Sqrt(strafeX * strafeX + strafeY * strafeY); if (strafeMagnitude == 0 || float.IsNaN(strafeMagnitude) || float.IsInfinity(strafeMagnitude)) { strafeMagnitude = 1.0f; } // Normalize and set length to 100 strafeX *= 100.0f / strafeMagnitude; strafeY *= 100.0f / strafeMagnitude; HandleStrafing(rotation, rayman, strafeX, strafeY); return; } else { // Can be turning? if (state == RaymanState.Idle) { var entryActions = InputStructure.GetInputStructure()->EntryActions; int[] bannedActions = new int[] { (int)EntryActionNames.Action_Tirer, (int)EntryActionNames.Action_Sauter }; bool usingBannedAction = bannedActions.Where(a => entryActions[a]->IsValidated()).Count() > 0; if (!usingBannedAction) { if (rightAction->IsValidated() && !leftAction->IsValidated()) { if (rayman->PersoData->GetStateIndex() != 70) { rayman->PersoData->SetState(70); } playTurnAnimation = true; } else if (leftAction->IsValidated() && !rightAction->IsValidated()) { if (rayman->PersoData->GetStateIndex() != 71) { rayman->PersoData->SetState(71); } playTurnAnimation = true; } else { playTurnAnimation = false; } } } rotation *= Quaternion.CreateFromYawPitchRoll(0, 0, rotationSpeed); // Add rotation float targetSpeed = (forwardAction->IsValidated() ? 100f : 0f) * (shiftAction->IsValidated() ? 0.5f : 1f); currentSpeed += (targetSpeed - currentSpeed) * 0.1f; } if (currentSpeed > 0 && currentSpeed < 0.5f) { currentSpeed = 0; } if (currentSpeed < 70 && Math.Abs(rotationSpeed) > 0.01f && state == RaymanState.Sliding) { currentSpeed = 70; } WriteVariables(rotation, rotationSpeed, transformationMatrix, rayman); }
private void WriteVariables(Quaternion rotation, float rotationDelta, Matrix4x4 transformationMatrix, SuperObject *rayman) { float *padAnalogForce = ((float *)0x4B9B78); *padAnalogForce = currentSpeed; float *padTrueAnalogForce = ((float *)0x4B9B7C); * padTrueAnalogForce = currentSpeed; float *padGlobalX = ((float *)0x4B9B68); float *padGlobalY = ((float *)0x4B9B6C); Vector3 rotationEuler = rotation.ToEuler(); *padGlobalX = currentSpeed * (float)Math.Sin(rotationEuler.Z); *padGlobalY = currentSpeed * -(float)Math.Cos(rotationEuler.Z); float *padRotationAngle = ((float *)0x4B9B80); *padRotationAngle = rotationDelta * 100.0f; var newMatrix = Matrix4x4.CreateFromQuaternion(rotation); newMatrix.Translation = transformationMatrix.Translation; rayman->PersoData->dynam->DynamicsAsBigDynamics->matrixA.TransformationMatrix = newMatrix; rayman->PersoData->dynam->DynamicsAsBigDynamics->matrixB.TransformationMatrix = newMatrix; }
public void Run(RemoteInterface remoteInterface) { Interface = remoteInterface; GlobalActions.Engine += CountFrames; random = new Random(); World world = new World(remoteInterface); List <TextOverlay> vars = new List <TextOverlay>(); GlobalInput.Actions['g'] = () => { foreach (TextOverlay overlay in vars) { overlay.Hide(); } vars = new List <TextOverlay>(); vars.Add(new TextOverlay("Rayman Dsgvars=".Red(), 6, 5, 0).Show()); world.ReadObjectNames(); Dictionary <string, Pointer <SuperObject> > superObjects = world.GetActiveSuperObjects(); Interface.Log("SUPEROBJECT NAMES:", LogType.Debug); foreach (KeyValuePair <string, Pointer <SuperObject> > o in superObjects) { Interface.Log($"{o.Key} {o.Value}", LogType.Debug); } SuperObject *rayman = superObjects["Rayman"]; Perso * perso = (Perso *)rayman->engineObjectPtr; DsgVar *dsgVars = *perso->brain->mind->dsgMem->dsgVar; Interface.Log("DSGVARS:", LogType.Debug); for (int i = 0; i < dsgVars->dsgVarInfosLength; i++) { DsgVarInfo info = dsgVars->dsgVarInfos[i]; DsgVarType type = info.type; Pointer <byte> buffer = perso->brain->mind->dsgMem->memoryBufferCurrent; int offset = info.offsetInBuffer; string name = $"{Enum.GetName(typeof(DsgVarType), type)}!{i}"; Func <object> value = buffer.GetDisplayReference(type, offset); if (value != null) { vars.Add(new TextOverlay(_ => $"{name.Yellow()}\\{value()}", 5, ((vars.Count + 1) * 5 * 2.6f + 5) < 1000 ? 5 : 505, (vars.Count * 5 * 2.6f + 5) % 980).Show()); } } }; GlobalInput.Actions['r'] = () => { RandomizeAllObjects(world); }; RandomizeMode mode = new RandomizeModeInterval(randomizeInterval); GlobalActions.Engine += () => { if (mode.ShouldRandomize()) { RandomizeAllObjects(world); } }; }
private void RandomizeObject(SuperObject *superObject) { Perso *perso = (Perso *)superObject->engineObjectPtr; Brain *brain = perso->brain; if (brain == null) { return; } DsgMem *dsgMem = brain->mind->dsgMem; if (dsgMem == null) { return; } DsgVar *dsgVars = *dsgMem->dsgVar; for (int i = 0; i < dsgVars->dsgVarInfosLength; i++) { if (random.NextDouble() > randomizeChance) { continue; } DsgVarInfo info = dsgVars->dsgVarInfos[i]; DsgVarType type = info.type; byte *buffer = dsgMem->memoryBufferCurrent; int ptr = (int)buffer + info.offsetInBuffer; switch (type) { case DsgVarType.Boolean: *(bool *)ptr = random.Next(0, 2) == 0; break; case DsgVarType.Byte: *(sbyte *)ptr = (sbyte)random.Next(-127, 128); break; case DsgVarType.UByte: *(byte *)ptr = (byte)random.Next(0, 256); break; case DsgVarType.Short: *(short *)ptr = (short)random.Next(); break; case DsgVarType.UShort: *(ushort *)ptr = (ushort)random.Next(); break; case DsgVarType.Int: *(int *)ptr = random.Next(); break; case DsgVarType.UInt: *(uint *)ptr = (uint)random.Next(); break; case DsgVarType.Float: *(float *)ptr += random.RandomFloat(-10f, 10f); break; case DsgVarType.Vector: Vector3 *vector = (Vector3 *)ptr; vector->X += random.RandomFloat(-10f, 10f); vector->Y += random.RandomFloat(-10f, 10f); vector->Z += random.RandomFloat(-10f, 10f); break; case DsgVarType.IntegerArray: int *array = brain->mind->GetDsgVar <int>(i, buffer, out byte size); for (int j = 0; j < size; j++) { array[j] = random.Next(); } break; } } }