diff --git a/.gitignore b/.gitignore index 49f18f2..aeba468 100644 --- a/.gitignore +++ b/.gitignore @@ -301,3 +301,4 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk +/libs/SignalR-Client-Cpp/cpprest_2_10.lib diff --git a/ArkBotLink/ApiExtensions.h b/ArkBotLink/ApiExtensions.h index 94f338c..960f8e7 100644 --- a/ArkBotLink/ApiExtensions.h +++ b/ArkBotLink/ApiExtensions.h @@ -20,4 +20,13 @@ namespace ArkExtensions float& LongitudeOriginField() { return *GetNativePointerField(this, "APrimalWorldSettings.LongitudeOrigin"); } float& LatitudeOriginField() { return *GetNativePointerField(this, "APrimalWorldSettings.LatitudeOrigin"); } }; + + inline bool IsPointInside2dCircle(FVector point, float circleX, float circleY, float circleRadius) + { + long double x = point.X - circleX; + long double y = point.Y - circleY; + + long double distancesq = x * x + y * y; + return distancesq < circleRadius * circleRadius; + } } \ No newline at end of file diff --git a/ArkBotLink/ArkBotLink.vcxproj b/ArkBotLink/ArkBotLink.vcxproj index bbaf39b..5a2d7ec 100644 --- a/ArkBotLink/ArkBotLink.vcxproj +++ b/ArkBotLink/ArkBotLink.vcxproj @@ -19,6 +19,9 @@ + + + @@ -31,6 +34,9 @@ + + + @@ -104,8 +110,8 @@ false - ../libs/SignalR-Client-Cpp/includes;C:\Users\Tobias\Downloads\ARK-Server-API-3.2-986ce4a871cf4f4edd92b79ff94ae1d7093cedfd\version\Core\Public;$(IncludePath) - C:\Users\Tobias\Downloads\ARK-Server-API-3.2-986ce4a871cf4f4edd92b79ff94ae1d7093cedfd\out_lib;$(LibraryPath) + ../libs/SignalR-Client-Cpp/includes;C:\Users\avtoj\Desktop\arkServer\API 3.2\version\Core\Public;$(IncludePath) + C:\Users\avtoj\Desktop\arkServer\API 3.2\out_lib;$(LibraryPath) diff --git a/ArkBotLink/DestroyDinosForTeamId.cpp b/ArkBotLink/DestroyDinosForTeamId.cpp new file mode 100644 index 0000000..57d5829 --- /dev/null +++ b/ArkBotLink/DestroyDinosForTeamId.cpp @@ -0,0 +1,59 @@ +#include "DestroyDinosForTeamId.h" + +std::string DestroyDinosForTeamIdInternal(FString* cmd) +{ + TArray Parsed; + cmd->ParseIntoArray(Parsed, L" ", true); + + if (Parsed.IsValidIndex(1)) + { + int teamId; + + try + { + teamId = std::stoi(*Parsed[1]); + } + catch (const std::exception&) + { + return {}; + } + + if (teamId < 10000) return {}; + + UWorld* world = ArkApi::GetApiUtils().GetWorld(); + if (!world) return {}; + + TArray FoundActors; + UGameplayStatics::GetAllActorsOfClass(world, APrimalDinoCharacter::GetPrivateStaticClass(), &FoundActors); + + int num = 0; + for (const auto& actor : FoundActors) + { + APrimalDinoCharacter* dino = static_cast(actor); + + int dinoTeam = dino->TargetingTeamField(); + if (dinoTeam == teamId) + { + dino->Suicide(); + num++; + } + } + std::string response = fmt::format("Destroyed {} dinos belonging to team {}", num, teamId); + + return response; + } + + return {}; +} + +void DestroyDinosForTeamIdRconCommand(RCONClientConnection* rconClientConnection, RCONPacket* rconPacket, UWorld* uWorld) +{ + FString msg = rconPacket->Body; + + auto result = DestroyDinosForTeamIdInternal(&msg); + if (result.length() == 0) return; + + FString reply(result.c_str()); + reply.AppendChar(L'\n'); + rconClientConnection->SendMessageW(rconPacket->Id, 0, &reply); +} \ No newline at end of file diff --git a/ArkBotLink/DestroyDinosForTeamId.h b/ArkBotLink/DestroyDinosForTeamId.h new file mode 100644 index 0000000..9e5fe6c --- /dev/null +++ b/ArkBotLink/DestroyDinosForTeamId.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +std::string DestroyDinosForTeamIdInternal(FString* cmd); +void DestroyDinosForTeamIdRconCommand(RCONClientConnection* rconClientConnection, RCONPacket* rconPacket, UWorld* uWorld); \ No newline at end of file diff --git a/ArkBotLink/DestroyStructuresForTeamId.cpp b/ArkBotLink/DestroyStructuresForTeamId.cpp new file mode 100644 index 0000000..4a583bd --- /dev/null +++ b/ArkBotLink/DestroyStructuresForTeamId.cpp @@ -0,0 +1,65 @@ +#include "DestroyStructuresForTeamId.h" + +std::string DestroyAllStructuresForTeamIdInternal(FString* cmd) +{ + TArray Parsed; + cmd->ParseIntoArray(Parsed, L" ", true); + + if (Parsed.IsValidIndex(1)) + { + int teamId; + + try + { + teamId = std::stoi(*Parsed[1]); + } + catch (const std::exception&) + { + return {}; + } + + if (teamId < 10000) return {}; + + UWorld* world = ArkApi::GetApiUtils().GetWorld(); + if (!world) return {}; + + TArray FoundActors; + + UGameplayStatics::GetAllActorsOfClass(world, APrimalStructure::GetPrivateStaticClass(), &FoundActors); + + //todo: maybe destroy rafts aswell? + int num = 0; + for (const auto& actor : FoundActors) + { + APrimalStructure* structure = static_cast(actor); + + int structureTeam = structure->TargetingTeamField(); + if (structureTeam == teamId) + { + APrimalStructureItemContainer* StructInv = static_cast(structure); + //UPrimalInventoryComponent* inventory = StructInv->MyInventoryComponentField(); + if (StructInv) StructInv->bDropInventoryOnDestruction() = false; + + structure->Suicide(); + num++; + } + } + std::string response = fmt::format("Destroyed {} structures belonging to team {}", num, teamId); + + return response; + } + + return {}; +} + +void DestroyAllStructuresForTeamIdRconCommand(RCONClientConnection* rconClientConnection, RCONPacket* rconPacket, UWorld* uWorld) +{ + FString msg = rconPacket->Body; + + auto result = DestroyAllStructuresForTeamIdInternal(&msg); + if (result.length() == 0) return; + + FString reply(result.c_str()); + reply.AppendChar(L'\n'); + rconClientConnection->SendMessageW(rconPacket->Id, 0, &reply); +} \ No newline at end of file diff --git a/ArkBotLink/DestroyStructuresForTeamId.h b/ArkBotLink/DestroyStructuresForTeamId.h new file mode 100644 index 0000000..04137ef --- /dev/null +++ b/ArkBotLink/DestroyStructuresForTeamId.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +std::string DestroyAllStructuresForTeamIdInternal(FString* cmd); +void DestroyAllStructuresForTeamIdRconCommand(RCONClientConnection* rconClientConnection, RCONPacket* rconPacket, UWorld* uWorld); diff --git a/ArkBotLink/DestroyStructuresForTeamIdAtPos.cpp b/ArkBotLink/DestroyStructuresForTeamIdAtPos.cpp new file mode 100644 index 0000000..0770e8a --- /dev/null +++ b/ArkBotLink/DestroyStructuresForTeamIdAtPos.cpp @@ -0,0 +1,107 @@ +#include "DestroyStructuresForTeamIdAtPos.h" + +std::string DestroyStructuresForTeamIdAtPositionInternal(FString* cmd) +{ + TArray Parsed; + cmd->ParseIntoArray(Parsed, L" ", true); + + if (Parsed.IsValidIndex(5)) + { + int teamId; + float x; + float y; + //float z; + float radius; + bool rafts; + + try + { + teamId = std::stoi(*Parsed[1]); + x = std::stof(*Parsed[2]); + y = std::stof(*Parsed[3]); + radius = std::stof(*Parsed[4]); + rafts = (bool)std::stoi(*Parsed[5]); + //z = std::stof(*Parsed[4]); + } + catch (const std::exception&) + { + return {}; + } + + if (teamId < 10000) return {}; + if (radius <= 0) return {}; + + UWorld* world = ArkApi::GetApiUtils().GetWorld(); + if (!world) return {}; + + int num = 0; + FVector pos; + + TArray FoundActors; + UGameplayStatics::GetAllActorsOfClass(world, APrimalStructure::GetPrivateStaticClass(), &FoundActors); + + for (const auto& actor : FoundActors) + { + APrimalStructure* structure = static_cast(actor); + + int structureTeam = structure->TargetingTeamField(); + structure->RootComponentField()->GetCustomLocation(&pos); + //if (structureTeam == teamId && ArkLibrary::IsPointInsideSphere(pos, x, y, z, radius)) + if (structureTeam == teamId && ArkExtensions::IsPointInside2dCircle(pos, x, y, radius)) + { + APrimalStructureItemContainer* StructInv = static_cast(structure); + //UPrimalInventoryComponent* inventory = StructInv->MyInventoryComponentField(); + if (StructInv) StructInv->bDropInventoryOnDestruction() = false; + + structure->Suicide(); + num++; + } + } + + if (rafts) { + TArray FoundActors; + UGameplayStatics::GetAllActorsOfClass(world, APrimalDinoCharacter::GetPrivateStaticClass(), &FoundActors); + + for (const auto& actor : FoundActors) + { + APrimalDinoCharacter* dino = static_cast(actor); + + int dinoTeam = dino->TargetingTeamField(); + + dino->RootComponentField()->GetCustomLocation(&pos); + //if (structureTeam == teamId && ArkLibrary::IsPointInsideSphere(pos, x, y, z, radius)) + if (dinoTeam == teamId && ArkExtensions::IsPointInside2dCircle(pos, x, y, radius)) + { + FString className; + FName bp = actor->NameField(); + bp.ToString(&className); + + if (className.Contains("Raft_BP_C") || className.Contains("MotorRaft_BP_C")) { + dino->Destroy(false, true); + num++; + } + + } + } + } + + //ss << "Destroyed " << num << " structures belonging to team " << teamId << " at position (x: " << x << ", y: " << y << ", z: " << z << ", r: " << radius << ")"; + std::string response = fmt::format("Destroyed {} structures belonging to team {} at position (x={}, y={}, r={}, rafts={})", num, teamId, x, y, radius, rafts); + + return response; + } + + return {}; +} + +void DestroyStructuresForTeamIdAtPositionRconCommand(RCONClientConnection* rconClientConnection, RCONPacket* rconPacket, UWorld* uWorld) +{ + FString msg = rconPacket->Body; + + auto result = DestroyStructuresForTeamIdAtPositionInternal(&msg); + if (result.length() == 0) return; + + FString reply(result.c_str()); + reply.AppendChar(L'\n'); + rconClientConnection->SendMessageW(rconPacket->Id, 0, &reply); +} \ No newline at end of file diff --git a/ArkBotLink/DestroyStructuresForTeamIdAtPos.h b/ArkBotLink/DestroyStructuresForTeamIdAtPos.h new file mode 100644 index 0000000..2d9d2a7 --- /dev/null +++ b/ArkBotLink/DestroyStructuresForTeamIdAtPos.h @@ -0,0 +1,6 @@ +#pragma once + +#include "ApiExtensions.h" + +std::string DestroyStructuresForTeamIdAtPositionInternal(FString* cmd); +void DestroyStructuresForTeamIdAtPositionRconCommand(RCONClientConnection* rconClientConnection, RCONPacket* rconPacket, UWorld* uWorld); diff --git a/ArkBotLink/Main.cpp b/ArkBotLink/Main.cpp index 2fab95f..8f3ffcf 100644 --- a/ArkBotLink/Main.cpp +++ b/ArkBotLink/Main.cpp @@ -3,6 +3,9 @@ #include "Hooks.h" #include "Timers.h" #include "CrossServerChat.h" +#include "DestroyDinosForTeamId.h" +#include "DestroyStructuresForTeamId.h" +#include "DestroyStructuresForTeamIdAtPos.h" #include #pragma comment(lib, "ArkApi.lib") @@ -99,6 +102,10 @@ void Load() //} commands.AddOnChatMessageCallback("ChatMessageCallback", &ChatMessageCallback); + + commands.AddRconCommand("DestroyAllStructuresForTeamId", &DestroyAllStructuresForTeamIdRconCommand); + commands.AddRconCommand("DestroyStructuresForTeamIdAtPosition", &DestroyStructuresForTeamIdAtPositionRconCommand); + commands.AddRconCommand("DestroyDinosForTeamId", &DestroyDinosForTeamIdRconCommand); } void Unload() @@ -114,6 +121,10 @@ void Unload() Timers::Unload(); ArkApi::GetCommands().RemoveOnChatMessageCallback("ChatMessageCallback"); + + ArkApi::GetCommands().RemoveRconCommand("DestroyAllStructuresForTeamId"); + ArkApi::GetCommands().RemoveRconCommand("DestroyStructuresForTeamIdAtPosition"); + ArkApi::GetCommands().RemoveRconCommand("DestroyDinosForTeamId"); } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)