commit 122d0ab95fb20a7a8bebae8250467fa56c21e1e8 Author: Flerp Date: Sun Nov 16 17:48:40 2025 -0800 Initial fork diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..259148f --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d0882e0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 AzerothCore + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec3d1d4 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# mod-noclip +This mod allows noclip with a command noclip. on / off +(IT's still WIP but it works mostly, btw. you can help me to correcting something with it if you want. Just contact me. diff --git a/apps/ci/ci-codestyle.sh b/apps/ci/ci-codestyle.sh new file mode 100644 index 0000000..c96a31d --- /dev/null +++ b/apps/ci/ci-codestyle.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -e + +echo "Codestyle check script:" +echo + +declare -A singleLineRegexChecks=( + ["LOG_.+GetCounter"]="Use ObjectGuid::ToString().c_str() method instead of ObjectGuid::GetCounter() when logging. Check the lines above" + ["[[:blank:]]$"]="Remove whitespace at the end of the lines above" + ["\t"]="Replace tabs with 4 spaces in the lines above" +) + +for check in ${!singleLineRegexChecks[@]}; do + echo " Checking RegEx: '${check}'" + + if grep -P -r -I -n ${check} src; then + echo + echo "${singleLineRegexChecks[$check]}" + exit 1 + fi +done + +declare -A multiLineRegexChecks=( + ["LOG_[^;]+GetCounter"]="Use ObjectGuid::ToString().c_str() method instead of ObjectGuid::GetCounter() when logging. Check the lines above" + ["\n\n\n"]="Multiple blank lines detected, keep only one. Check the files above" +) + +for check in ${!multiLineRegexChecks[@]}; do + echo " Checking RegEx: '${check}'" + + if grep -Pzo -r -I ${check} src; then + echo + echo + echo "${multiLineRegexChecks[$check]}" + exit 1 + fi +done + +echo +echo "Everything looks good" diff --git a/conf/mod-noclip.conf.dist b/conf/mod-noclip.conf.dist new file mode 100644 index 0000000..3e36c4d --- /dev/null +++ b/conf/mod-noclip.conf.dist @@ -0,0 +1,44 @@ +[worldserver] + +######################################## +# Mod-NoClip +######################################## + +# +# Module.Enabled +# Description: Enable/Disable the module +# Default: 1 - Enabled +# 0 - Disabled +# + +Module.Enabled = 1 + +# +# Module.Announce.Enabled +# Description: Enable/Disable for module-announcement at players-login +# Default: 1 - Enabled +# 0 - Disabled +# + +Module.Announce.Enabled = 1 + +# +# Module.AllowedAccountTypeMax +# Description: Specifies which account types can use the command .noclip on/off +# If the value is set to 2 as example, all accounts of type SEC_ADMINISTRATOR also can use this command +# 0 = SEC_PLAYER +# 1 = SEC_MODERATOR +# 2 = SEC_GAMEMASTER +# 3 = SEC_ADMINISTRATOR +# Default: 2 +# + +Module.AllowedAccountTypeMax = 2 + +# +# Module.TeleportDistance +# Description: Specifies the teleport-range (to go through objects or under the ground) +# Default: 2.0 +# + +Module.TeleportDistance = 2.0 \ No newline at end of file diff --git a/include.sh b/include.sh new file mode 100644 index 0000000..e69de29 diff --git a/pull_request_template.md b/pull_request_template.md new file mode 100644 index 0000000..21c9245 --- /dev/null +++ b/pull_request_template.md @@ -0,0 +1,25 @@ + + +## Changes Proposed: +- +- + +## Issues Addressed: + +- Closes + +## SOURCE: + + +## Tests Performed: + +- +- + + +## How to Test the Changes: + + +1. +2. +3. diff --git a/src/NoClip.cpp b/src/NoClip.cpp new file mode 100644 index 0000000..cd3ced5 --- /dev/null +++ b/src/NoClip.cpp @@ -0,0 +1,463 @@ +#include "NoClip.h" + +/* Class: CustomPlayerInformation */ + +CustomPlayerInformation::CustomPlayerInformation() +{ + this->IsNoClipEnabled = false; +} +CustomPlayerInformation::CustomPlayerInformation(Player* APlayer) +{ + if (APlayer) + { + this->player = APlayer; + } + + this->IsNoClipEnabled = false; +} + +void CustomPlayerInformation::SetPlayer(Player* APlayer) +{ + if (APlayer) + { + this->player = APlayer; + } + return; +} +Player* CustomPlayerInformation::GetMyPlayer() const +{ + return this->player; +} + +void CustomPlayerInformation::SetTeleportDistance(float ATeleportDistance) +{ + if (ATeleportDistance > 0.0f) + { + { + std::lock_guard lockGuard(NoClipMutex); + this->TeleportDistance = ATeleportDistance; + } + } + + return; +} +float CustomPlayerInformation::GetTeleportDistance() const +{ + return this->TeleportDistance; +} + +void CustomPlayerInformation::SetFlagNoClipEnabled(bool AIsNoClipEnabled) +{ + this->IsNoClipEnabled = AIsNoClipEnabled; + + return; +} +bool CustomPlayerInformation::GetFlagNoClipEnabled() const +{ + return this->IsNoClipEnabled; +} + +bool CustomPlayerInformation::SetThreadHandlerState(int AState) +{ + bool xResult = false; + + if (this->player) + { + switch (AState) + { + case 1: + { + if (!this->IsNoClipEnabled) + { + { + std::lock_guard lockGuard(NoClipMutex); + + this->IsNoClipEnabled = true; + + ThreadHandler = std::thread([this]() + { + while (this->IsNoClipEnabled) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + CustomPlayerInformation::HandleNoClipMovement(); + } + }); + ThreadHandler.detach(); + + NoClipThread = std::thread([this]() + { + while (this->IsNoClipEnabled) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + CustomPlayerInformation::HandleNoClipThread(); + } + }); + NoClipThread.detach(); + + xResult = true; + } + } + break; + } + case 2: + { + if (this->IsNoClipEnabled) + { + { + std::lock_guard lockGuard(NoClipMutex); + + this->IsNoClipEnabled = false; + + xResult = true; + } + } + break; + } + default: + { + xResult = false; + break; + } + } + } + + return xResult; +} +void CustomPlayerInformation::HandleNoClipMovement() +{ + if (this->player && NC_Enable && this->IsNoClipEnabled) + { + if (!this->player->CanFly()) + { + this->player->SetCanFly(true); + } + + while (this->IsNoClipEnabled) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + if (this->player->CanFly()) + { + this->player->SetCanFly(false); + } + } +} +void CustomPlayerInformation::HandleNoClipThread() +{ + while (this->player && NC_Enable && this->IsNoClipEnabled) + { + if (this->TeleportDistance < 0.0f) + { + this->TeleportDistance = NC_TeleportDistance; + } + + float xOrientation = this->player->GetOrientation(); + float xPosX = this->player->GetPositionX(); + float xPosY = this->player->GetPositionY(); + float xPosZ = this->player->GetPositionZ(); + uint32 xMapId = this->player->GetMapId(); + + float xNewPosX = xPosX; + float xNewPosY = xPosY; + float xNewPosZ = xPosZ; + + if (IsPlayerMovingOrFlying()) + { + xNewPosX += this->TeleportDistance * cos(xOrientation); + xNewPosY += this->TeleportDistance * sin(xOrientation); + Position xCollisionPos = player->GetFirstCollisionPosition(xPosX, xPosY, xPosZ, xNewPosX, xNewPosY); + Position xPlayerPos = Position(xPosX, xPosY, xPosZ, xOrientation); + + if (this->player->isMoving() || IsPlayerFlyingDirections() || IsPlayerFlyingDown() || IsPlayerFlyingUp()) + { + if ((IsObstacleInFront() || (!PathGenerator::IsWalkableClimb(xPosX, xPosY, xPosZ, xNewPosX, xNewPosY, xPosZ, this->player->GetCollisionHeight()) || + (CollisionInFront(xPlayerPos, xCollisionPos))))) + { + this->player->TeleportTo(xMapId, xNewPosX, xNewPosY, xPosZ, xOrientation); + } + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + return; +} + +bool CustomPlayerInformation::IsPlayerMovingOrFlying() +{ + //if (player && NC_Enable && NoClipActivated) + if (this->player && NC_Enable && this->IsNoClipEnabled) + { + return (IsPlayerFlyingDirections() || IsPlayerFlyingDown() || IsPlayerFlyingUp()) || + player->isMoving(); + } + return false; +} +bool CustomPlayerInformation::IsPlayerFlyingUp() +{ + //if (player && NC_Enable && NoClipActivated) + if (this->player && NC_Enable && this->IsNoClipEnabled) + { + return player->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_ASCENDING) || + player->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_PITCH_UP) || + player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_ASCENDING) || + player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_PITCH_UP); + } + return false; +} +bool CustomPlayerInformation::IsPlayerFlyingDown() +{ + //if (player && NC_Enable && NoClipActivated) + if (this->player && NC_Enable && this->IsNoClipEnabled) + { + return player->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DESCENDING) || + player->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_PITCH_DOWN) || + player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_DESCENDING) || + player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_PITCH_DOWN); + } + return false; +} +bool CustomPlayerInformation::IsPlayerFlyingDirections() +{ + //if (player && NC_Enable && NoClipActivated) + if (this->player && NC_Enable && this->IsNoClipEnabled) + { + return player->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_FORWARD) || + player->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_BACKWARD) || + player->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_LEFT) || + player->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_RIGHT) || + player->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_STRAFE_LEFT) || + player->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_STRAFE_RIGHT) || + player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FORWARD) || + player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_BACKWARD) || + player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEFT) || + player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_RIGHT) || + player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_STRAFE_LEFT) || + player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_STRAFE_RIGHT); + } + return false; +} + +bool CustomPlayerInformation::IsInvisibleWallInFront(Player* player, float distance) +{ + /*float playerX, playerY, playerZ; + player->GetPosition(playerX, playerY, playerZ); + + float orientation = player->GetOrientation(); + float checkX = playerX + distance * cos(orientation); + float checkY = playerY + distance * sin(orientation); + + float distanceToPoint = player->GetDistance2d(checkX, checkY); + return (distanceToPoint < distance); // Falls die Distanz kleiner als erwartet ist, könnte etwas im Weg sein*/ + return false; +} +bool CustomPlayerInformation::CollisionInFront(Position xPosPlayer, Position xPosCollision) +{ + if (this->player) + { + float xPosPlayerX = xPosPlayer.GetPositionX(); + float xPosPlayerY = xPosPlayer.GetPositionY(); + float xPosPlayerZ = xPosPlayer.GetPositionZ(); + float xPosPlayerOrientation = xPosPlayer.GetOrientation(); + + float xPosCollisionX = xPosCollision.GetPositionX(); + float xPosCollisionY = xPosCollision.GetPositionY(); + float xPosCollisionZ = xPosCollision.GetPositionZ(); + float xPosCollisionOrientation = xPosCollision.GetOrientation(); + + bool isWaterNext = player->GetMap()->IsInWater(this->player->GetPhaseMask(), xPosPlayerX, xPosPlayerY, xPosPlayerZ, this->player->GetCollisionHeight()); + + PathGenerator path(this->player); + path.SetUseRaycast(true); + + bool result = path.CalculatePath(xPosPlayerX, xPosPlayerY, xPosPlayerZ, + xPosCollisionX, xPosCollisionY, xPosCollisionZ, false); + + bool notOnGround = path.GetPathType() & PATHFIND_NOT_USING_PATH + || isWaterNext || (this->player && this->player->IsFlying()); + + // Check for valid path types before we proceed + if (!result || (!notOnGround && path.GetPathType() & ~(PATHFIND_NORMAL | PATHFIND_SHORTCUT | PATHFIND_INCOMPLETE | PATHFIND_FARFROMPOLY_END))) + { + return true; + } + + G3D::Vector3 endPos = path.GetPath().back(); + xPosCollisionX = endPos.x; + xPosCollisionY = endPos.y; + xPosCollisionZ = endPos.z; + + // check static LOS + float halfHeight = this->player->GetCollisionHeight() * 0.5f; + + bool col = VMAP::VMapFactory::createOrGetVMapMgr()->GetObjectHitPos(this->player->GetMapId(), + xPosPlayerX, xPosPlayerY, xPosPlayerZ + halfHeight, + xPosCollisionX, xPosCollisionY, xPosCollisionZ + halfHeight, + xPosCollisionX, xPosCollisionY, xPosCollisionZ, -CONTACT_DISTANCE); + + // Collided with static LOS object, move back to collision point + if (col) + { + return true; + } + xPosCollisionZ -= halfHeight; + + // check dynamic collision + col = this->player->GetMap()->GetObjectHitPos(this->player->GetPhaseMask(), + xPosPlayerX, xPosPlayerY, xPosPlayerZ + halfHeight, + xPosCollisionX, xPosCollisionY, xPosCollisionZ + halfHeight, + xPosCollisionX, xPosCollisionY, xPosCollisionZ, -CONTACT_DISTANCE); + + xPosCollisionZ -= halfHeight; + + // Collided with a gameobject, move back to collision point + if (col) + { + return true; + } + + float xCurMapHeight = this->player->GetMapHeight(xPosPlayerX, xPosPlayerY, xPosPlayerZ); + float xNewMapHeight = this->player->GetMapHeight(xPosCollisionX, xPosCollisionY, xPosCollisionZ); + + if (xCurMapHeight != xNewMapHeight) + { + if (this->player->isMoving() && !(IsPlayerFlyingDirections() || IsPlayerFlyingDown() || IsPlayerFlyingUp())) + { + return true; + } + } + } + + return false; +} +bool CustomPlayerInformation::IsObstacleInFront() +{ + //if (player && NC_Enable && NoClipActivated) + if (this->player && NC_Enable && this->IsNoClipEnabled) + { + float xOrientation = player->GetOrientation(); + float xPosX = player->GetPositionX(); + float xPosY = player->GetPositionY(); + float xPosZ = player->GetPositionZ(); + float xCheckPosX = xPosX + cos(xOrientation); + float xCheckPosY = xPosY + sin(xOrientation); + + return (!player->IsWithinLOS(xCheckPosX, xCheckPosY, xPosZ, VMAP::ModelIgnoreFlags::Nothing, LINEOFSIGHT_ALL_CHECKS)); + } + return false; +} + +/* Class: NoClipConfigLoader */ + +void NoClipConfigLoader::OnBeforeConfigLoad(bool /*reload*/) +{ + SetInitialWorldSettings(); + + return; +} +void NoClipConfigLoader::SetInitialWorldSettings() +{ + NC_Enable = sConfigMgr->GetOption("Module.Enable", true); + NC_Announce_Enable = sConfigMgr->GetOption("Module.Announce.Enable", true && NC_Enable); + NC_AllowedAccountTypeMax = sConfigMgr->GetOption("Module.AllowedAccountTypeMax", NC_AllowedAccountTypeMax); + NC_TeleportDistance = sConfigMgr->GetOption("Module.TeleportDistance", NC_TeleportDistance); + + return; +} + +/* Class: NoClipCommand */ + +bool NoClipCommand::HandleSetTeleportDistanceCommand(ChatHandler* AChatHandler, float ATeleportDistance) +{ + if (AChatHandler && NC_Enable && ATeleportDistance > 0.0f) + { + WorldSession* xPlayerSession = AChatHandler->GetSession(); + if (xPlayerSession) + { + Player* xPlayer = xPlayerSession->GetPlayer(); + if (xPlayer) + { + xPlayer->CustomData.GetDefault("NoClip")->SetTeleportDistance(ATeleportDistance); + + return true; + } + } + } + return false; +} +bool NoClipCommand::HandleNoClipCommand(ChatHandler* AChatHandler) +{ + //if (handler && NC_Enable && !NoClipActivated) + if (AChatHandler && NC_Enable) + { + WorldSession* xPlayerSession = AChatHandler->GetSession(); + if (xPlayerSession) + { + Player* xPlayer = xPlayerSession->GetPlayer(); + if (xPlayer) + { + if (!xPlayer->CustomData.GetDefault("NoClip")->GetFlagNoClipEnabled()) + { + if (xPlayer->CustomData.GetDefault("NoClip")->SetThreadHandlerState(1)) + { + AChatHandler->SendSysMessage("NoClip is now enabled!"); + return true; + } + return false; + + } + } + } + } + return false; +} +bool NoClipCommand::HandleClipCommand(ChatHandler* AChatHandler) +{ + if (AChatHandler && NC_Enable) + { + WorldSession* xPlayerSession = AChatHandler->GetSession(); + if (xPlayerSession) + { + Player* xPlayer = xPlayerSession->GetPlayer(); + if (xPlayer) + { + if (xPlayer->CustomData.GetDefault("NoClip")->GetFlagNoClipEnabled()) + { + if (xPlayer->CustomData.GetDefault("NoClip")->SetThreadHandlerState(2)) + { + AChatHandler->SendSysMessage("NoClip is now disabled!"); + return true; + } + return false; + } + } + } + } + return false; +} + +/* Class: NoClipPlayer */ + +void NoClipPlayer::OnLogin(Player* APlayer) +{ + if (APlayer && NC_Enable && NC_Announce_Enable) + { + WorldSession* xPlayerSession = APlayer->GetSession(); + if (xPlayerSession) + { + APlayer->CustomData.Set("NoClip", new CustomPlayerInformation(APlayer)); + ChatHandler(xPlayerSession).SendSysMessage("This server is running the |cff4CFF00NoClip |rmodule."); + } + } +} +void NoClipPlayer::OnBeforeLogout(Player* APlayer) +{ + if (APlayer && NC_Enable && APlayer->CustomData.GetDefault("NoClip")->GetFlagNoClipEnabled()) + { + APlayer->CustomData.GetDefault("NoClip")->SetFlagNoClipEnabled(false); + + APlayer->SetCanFly(false); + + APlayer->CustomData.GetDefault("NoClip")->SetThreadHandlerState(2); + } +} diff --git a/src/NoClip.h b/src/NoClip.h new file mode 100644 index 0000000..021dfd0 --- /dev/null +++ b/src/NoClip.h @@ -0,0 +1,126 @@ +#include "ScriptMgr.h" +#include "Player.h" +#include "Config.h" +#include "Chat.h" +#include "World.h" +#include "VMapFactory.h" +#include "VMapMgr2.h" +#include "Geometry.h" +#include "Timer.h" +#include "Object.h" +#include "MapMgr.h" +#include "Creature.h" +#include "Transport.h" +#include "World.h" +#include "Util.h" +#include "GridDefines.h" +#include "condition_variable" +#include "iostream" +#include "mutex" +#include "chrono" +#include "thread" +#include "atomic" +#include "functional" + + +bool NC_Enable = true; +bool NC_Announce_Enable = false; +uint32 NC_AllowedAccountTypeMax = 2; +float NC_TeleportDistance = 1.0f; + +class CustomPlayerInformation : public DataMap::Base +{ +public: + CustomPlayerInformation(); + CustomPlayerInformation(Player* APlayer); + + void SetPlayer(Player* APlayer); + Player* GetMyPlayer() const; + + void SetTeleportDistance(float ATeleportDistance); + float GetTeleportDistance() const; + + void SetFlagNoClipEnabled(bool AIsNoClipEnabled); + bool GetFlagNoClipEnabled() const; + + bool SetThreadHandlerState(int AState); +private: + Player* player = nullptr; + float TeleportDistance = 1.0f; + + std::mutex NoClipMutex; + std::thread NoClipThread; + std::thread ThreadHandler; + + std::atomic IsNoClipEnabled = false; + + void HandleNoClipMovement(); + void HandleNoClipThread(); + + bool IsPlayerMovingOrFlying(); + bool IsPlayerFlyingUp(); + bool IsPlayerFlyingDown(); + bool IsPlayerFlyingDirections(); + + bool IsInvisibleWallInFront(Player* player, float distance); + bool CollisionInFront(Position xPosPlayer, Position xPosCollision); + bool IsObstacleInFront(); +}; + +class NoClipConfigLoader : public WorldScript +{ +public: + NoClipConfigLoader() : WorldScript("NoClipConfig") {} + + void OnBeforeConfigLoad(bool /*reload*/) override; + void SetInitialWorldSettings(); +}; + +class NoClipCommand : public CommandScript +{ +public: + NoClipCommand() : CommandScript("NoClipCommand") {} + + /* Command-Handler */ + Acore::ChatCommands::ChatCommandTable GetCommands() const override + { + if (NC_Enable) + { + static Acore::ChatCommands::ChatCommandTable xNoClipCommandTable = + { + { "on", NoClipCommand::HandleNoClipCommand, NC_AllowedAccountTypeMax, Acore::ChatCommands::Console::No }, + { "off", NoClipCommand::HandleClipCommand, NC_AllowedAccountTypeMax, Acore::ChatCommands::Console::No }, + { "set TeleportDistance", NoClipCommand::HandleSetTeleportDistanceCommand, NC_AllowedAccountTypeMax, Acore::ChatCommands::Console::No } + + }; + + static Acore::ChatCommands::ChatCommandTable xNoClipIndividualBaseTable = + { + { "noclip", xNoClipCommandTable } + }; + + return xNoClipIndividualBaseTable; + } + return Acore::ChatCommands::ChatCommandTable(); + } + static bool HandleSetTeleportDistanceCommand(ChatHandler* AChatHandler, float ATeleportDistance); + static bool HandleNoClipCommand(ChatHandler* AChatHandler); + static bool HandleClipCommand(ChatHandler* AChatHandler); + +}; + +class NoClipPlayer : public PlayerScript +{ +public: + NoClipPlayer() : PlayerScript("NoClipPlayer") {} + + void OnLogin(Player* APlayer) override; + void OnBeforeLogout(Player* APlayer) override; +}; + +void AddNoClipScripts() +{ + new NoClipConfigLoader(); + new NoClipCommand(); + new NoClipPlayer(); +} diff --git a/src/NoClip_loader.cpp b/src/NoClip_loader.cpp new file mode 100644 index 0000000..62b5ce7 --- /dev/null +++ b/src/NoClip_loader.cpp @@ -0,0 +1,6 @@ +void AddNoClipScripts(); + +void Addmod_noclipScripts() +{ + AddNoClipScripts(); +}