Pasta Mike 0 Posted June 14, 2023 Hello fellow scripters and modders! I am trying to make a script that allows the player to perform an action that will teleport them. I only made this far. It seems that SCR_PlayerController.SetPosition is not correct here, but I am not sure how to do it otherwise. Any suggestion? class SCR_Teleport : ScriptedUserAction { // References protected SCR_PlayerController m_PlayerController; protected ref array<vector> m_TargetPositions; //------------------------------------------------------------------------------------ void SCR_Teleport() { m_TargetPositions = new array<vector>; m_TargetPositions.Insert("5145 14.34 4015"); //m_TargetPositions.Insert("X2_Y2_Z2"); // More target positions here } //------------------------------------------------------------------------------------- override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity) { m_PlayerController = SCR_PlayerController.Cast(pUserEntity); if (!m_PlayerController) return; if (m_TargetPositions.Count() == 0) return; int randomIndex = Math.RandomInt(0, m_TargetPositions.Count()); vector targetPosition = m_TargetPositions.Get(randomIndex); m_PlayerController.SetPosition(targetPosition); } //-------------------------------------------------------------------------------------- override bool GetActionNameScript(out string outName) { outName = "Teleport"; return true; } }; Share this post Link to post Share on other sites
BigAndSloppy 0 Posted July 19, 2023 Maybe initialize the m_TargetPositions array directly: Instead of initializing the array in the constructor, you can declare and initialize it at the point of declaration. For example: protected ref array<vector> m_TargetPositions = { "5145 14.34 4015" }; Improve target position representation: Instead of storing target positions as strings, use actual vector objects. This will allow for easier manipulation and use of the positions. For example: m_TargetPositions.Insert(Vector(5145, 14.34, 4015)); Validate target positions: Add a validation step to ensure that the target positions are valid before teleporting the player. You can check if the array contains at least one valid position and handle the error case accordingly. Randomize target positions more effectively: Instead of using Math.RandomInt(), which can produce duplicate indices, consider using the Math.RandomFloat() function to generate a random float value and then multiply it by the size of the array to obtain a random index. This will give you a more uniform distribution of random positions. Add error handling: Currently, if the player controller is not found or there are no target positions, the script silently returns. Consider adding error messages or logging to help with debugging and informing the player about any issues. Implement a cooldown system: If you want to limit the frequency of teleportation, you can add a cooldown mechanism. Track the last teleportation time and check it against a predefined cooldown period before allowing another teleport. Here's an updated version of the script incorporating these improvements: class TeleportAction : ScriptedUserAction { // References protected SCR_PlayerController m_PlayerController; protected ref array<vector> m_TargetPositions = { Vector(5145, 14.34, 4015) // Additional target positions here }; protected float m_LastTeleportTime; protected float m_TeleportCooldown = 10.0; // Cooldown period in seconds //------------------------------------------------------------------------------------ override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity) { m_PlayerController = SCR_PlayerController.Cast(pUserEntity); if (!m_PlayerController) { Print("TeleportAction: Failed to get player controller."); return; } if (m_TargetPositions.Count() == 0) { Print("TeleportAction: No target positions defined."); return; } if (GetGame().GetTime() < m_LastTeleportTime + m_TeleportCooldown) { Print("TeleportAction: Teleport on cooldown."); return; } int randomIndex = Math.Floor(Math.RandomFloat() * m_TargetPositions.Count()); vector targetPosition = m_TargetPositions.Get(randomIndex); m_PlayerController.SetPosition(targetPosition); m_LastTeleportTime = GetGame().GetTime(); } //-------------------------------------------------------------------------------------- override bool GetActionNameScript(out string outName) { outName = "Teleport"; return true; } }; class TeleportAction : ScriptedUserAction { // References protected SCR_PlayerController m_PlayerController; protected ref array<vector> m_TargetPositions = { Vector(5145, 14.34, 4015) // Additional target positions here }; protected float m_LastTeleportTime; protected float m_TeleportCooldown = 10.0; // Cooldown period in seconds //------------------------------------------------------------------------------------ override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity) { m_PlayerController = SCR_PlayerController.Cast(pUserEntity); if (!m_PlayerController) { Print("TeleportAction: Failed to get player controller."); return; } if (m_TargetPositions.Count() == 0) { Print("TeleportAction: No target positions defined."); return; } if (GetGame().GetTime() < m_LastTeleportTime + m_TeleportCooldown) { Print("TeleportAction: Teleport on cooldown."); return; } int randomIndex = Math.Floor(Math.RandomFloat() * m_TargetPositions.Count()); vector targetPosition = m_TargetPositions.Get(randomIndex); m_PlayerController.SetPosition(targetPosition); m_LastTeleportTime = GetGame().GetTime(); } //-------------------------------------------------------------------------------------- override bool GetActionNameScript(out string outName) { outName = "Teleport"; return true; } }; maybe this second one would work better, however I'm just printing out C++ to show how i'd do it you might change for enforce as I havne't delved too much into it yet. Share this post Link to post Share on other sites