Guild icon
Ark Server Api
โ”€โ”€ ( Promote | Content ) โ”€โ”€ / ใ€๐Ÿคนใ€‘ส€แด‡๊œฐแด‡ส€แด‡ษดแด„แด‡๊œฑ
7:21 AM
7:21 AM
(ignore the images atm it doesnt include dino ones)
7:22 AM
7:22 AM
7:22 AM
7:22 AM
7:22 AM
7:22 AM
7:22 AM
7:22 AM
7:23 AM
7:23 AM
7:23 AM
slowly getting close to completion of this webshop for ArkShop Plugin, theres a lot more to do me and Michidu want to add cross syncing so you can sync from the json file to the webstore and visa versa. (edited)
Avatar
GSH | MrOwlSky 11/23/2018 6:06 PM
That's epic! @OwnProx If it's public or paid we'll use it for sure. Looks solid!
Avatar
it will be public but be limited to how much can be earned via selling coins
6:24 PM
but there will be a simple monthly fee that will waive that limit
6:24 PM
but yeah its still will be free
6:25 PM
i think we were gonna cap it like 100-200 euros a month
6:25 PM
for a free user
6:25 PM
and like 3000 for a pro user
6:25 PM
at like 10-20$ a month
6:25 PM
not too sure yet
6:25 PM
but something similar to (edited)
6:26 PM
this is a joint project me and michidu are working on atm, im doing website / backend he will do the plugin support, i saw others made ark web shop and wanted to get in on the action and turns out Michidu wanted to do something similar for ArkShop so combining them was the best choice (edited)
6:28 PM
but yeah we will host your shops for you and all you do is just add a key code to arkshop config file
6:28 PM
then login admin panel and add stuff and link people
6:28 PM
payment methods planned so far: Paypal and Paygol
6:28 PM
more to come soon
Avatar
that is quite nice considering the only competitor you guys have is tebex and they dont support a wide range of commands which means most of the commands have to be routed through arkshop anyways (or at least that is how i do it)
Avatar
ah its not based on commands at all
6:30 PM
its more automatic than that
6:30 PM
a user will buy items then type /webclaim or something
6:30 PM
and it will automatically give the items
6:30 PM
with no limits and it will support custom mod items
Avatar
that sounds amazing
6:31 PM
a suggestion would be to add basic discord support maybe
Avatar
i pretty much got the shop side of things done
6:31 PM
i can buy stuff
Avatar
a message when someone purchases an item maybe
Avatar
why though ?
6:31 PM
to let the admin know ?
Avatar
ye
Avatar
there would be purchase logs in admin panel
6:32 PM
but yeah could be a possibility to add too
Avatar
i would assume it would require self hosting ?
Avatar
but i dout i would release it with that feature
6:32 PM
no we host it for you
6:33 PM
exampe
Avatar
oh awesome
Avatar
thats store id 4
Avatar
ye but wouldnโ€™t it be easier if you guys let people self host ?
6:34 PM
that would reduce server costs
Avatar
they could also bypass the limitations
6:34 PM
if they self hosted
6:34 PM
meaning my hole payment scheme wouldnt work
6:35 PM
if they edited 1 php file
6:35 PM
thats why id host the stores
6:35 PM
it would be cheaper sure
6:35 PM
but hosting is quite costless
6:35 PM
i wont need some super machine
6:35 PM
to host it
6:35 PM
only like 3-4 gb ram
6:35 PM
3-4 core
6:36 PM
at about 10 euros a month or less
6:36 PM
will do fine
Avatar
best of luck, this looks awesome
Avatar
yeah im bad a gfx so im trying my best
6:37 PM
and looking at many examples of shops ect
6:37 PM
i dont know what it is most really good programmers are shit at graphics / visual work (edited)
6:38 PM
im one of them
6:40 PM
it should be done in a week or 2 max
6:40 PM
depending how much time i spent on it daily
6:40 PM
i could have it ready to be released today
6:41 PM
but it wouldnt have all the features i want
6:41 PM
๐Ÿ˜ƒ
6:41 PM
i want it to support michidu's lucky box's
6:41 PM
and my gamble box's
6:42 PM
and it doesnt have support for mod items yet gotta add that (edited)
6:43 PM
then once released
6:43 PM
ill eventually expand it allowing player based market
Avatar
Oo i was considering building something like this
Avatar
GSH | MrOwlSky 11/23/2018 6:43 PM
That's amazing
Avatar
if the owner wants to include that
Avatar
currently working on authentication between steam account and discord
Avatar
i made one already
6:43 PM
ingame
Avatar
rather, ark account/character and discord
Avatar
and then pushing clan chat to specific clan channels on discord
Avatar
my webshop has steam auth too
6:44 PM
its the main way of knowing who bought what item
6:44 PM
^^ if you login it will take you to admin panel
Avatar
GSH | MrOwlSky 11/23/2018 6:45 PM
How does that lootbox system work?
6:45 PM
Is that a custom lootbox plugin you coded?
Avatar
well there will be 2 types
6:45 PM
mich made one based on groups
6:45 PM
like you add groups of items
Avatar
GSH | MrOwlSky 11/23/2018 6:45 PM
That's a private one?
Avatar
and then set a proability on the group
6:46 PM
but my one
6:46 PM
i wanted it to be possible to have multiple box's
๐Ÿ˜ฎ 1
6:46 PM
with probability per item
6:46 PM
so that you can make your own box add items then you can a super rare one
6:46 PM
and its like a gamble
Avatar
GSH | MrOwlSky 11/23/2018 6:46 PM
That's epic
Avatar
people will buy it and 90% of the time
6:47 PM
get shit stuff
6:47 PM
you added to it
6:47 PM
depending on the probability values you gave the items
6:47 PM
so you put like 20 items in
6:47 PM
put them all at 100 probability
6:47 PM
and 1 item at 1
6:48 PM
it will be like 1 win every 2 weeks
6:48 PM
chance of getting that super rare item
6:48 PM
out of like 100-500 buys
6:48 PM
lol
6:49 PM
so you could be a super nice owner and give good probability's
6:49 PM
or be a cunt haha
6:49 PM
i will list the chance of getting each item
6:49 PM
so its not like the players can get scammed
6:49 PM
they will know their chances
6:51 PM
6:51 PM
6:52 PM
6:52 PM
supports mobiles too
6:52 PM
6:53 PM
still got a bit of css / html to do to make it look nicer
Avatar
I can help if you'd like
Avatar
Damn, all those spreadsheets i made to set up my shop and lootboxes are going to be useless XD
Avatar
https://youtu.be/Qj9TR5aUnPg Example how nicely ArkApi plays with Mod. Backbone is a MySqlDB (thanks michidu for your MySQL Permission Stuff) Communication between ArkApi & Mod is over HttpGetRequests / HttpPostRequests Playerlist on Firstpage is Clusterwide, IngameShop is a ported version of ArkShop to MySql and heavily costumized to our needs Next Project: Sell System for the UI :)
๐Ÿ˜ 5
Avatar
GSH | MrOwlSky 11/26/2018 4:52 PM
That's epic!
Avatar
pretty cool Toma i just hate ark devkit myself its really nice job you did though
Avatar
That is super cool Toma, been wondering for quite some time how well the API would play with mods
๐Ÿ‘ 1
Avatar
GSH | MrOwlSky 11/28/2018 3:53 AM
Good to see you around @Haragon
Avatar
void SuicideCMD(AShooterPlayerController* AttackerShooterController, FString* message, int mode) { if (!AttackerShooterController || !AttackerShooterController->PlayerStateField() || !AttackerShooterController->GetPlayerCharacter() || AttackerShooterController->GetPlayerCharacter()->IsDead() || !AttackerShooterController->GetPlayerCharacter()->IsConscious() || AttackerShooterController->GetPlayerCharacter()->IsSitting(false)) return; if (AttackerShooterController && AttackerShooterController->PlayerStateField() && AttackerShooterController->GetPlayerCharacter() && AttackerShooterController->GetPlayerCharacter()->CurrentWeaponField() && AttackerShooterController->GetPlayerCharacter()->CurrentWeaponField()->AssociatedPrimalItemField()) { FString WeaponName; AttackerShooterController->GetPlayerCharacter()->CurrentWeaponField()->AssociatedPrimalItemField()->GetItemName(&WeaponName, false, true, nullptr); if (WeaponName.Contains(L"Handcuffs")) return; } if (!ArkApi::GetApiUtils().IsRidingDino(AttackerShooterController)) AttackerShooterController->GetPlayerCharacter()->Suicide(); }
4:24 PM
a very simple addon to any plugin that replaces any suicide potion mod with a server side /suicide command, also contains a check to see if a player is knocked out/riding a dino/handcuffed/already dead (thanks to @OwnProx )
4:24 PM
dont forget to add ArkApi::GetCommands().AddChatCommand("/suicide", &SuicideCMD); to your void load
4:24 PM
and add ArkApi::GetCommands().RemoveChatCommand("/suicide"); to your void unload
Avatar
since i dont do anything with it i mind aswell release a base for you guys ๐Ÿ˜„ Base for increasing flyer's speed by a plugin so without lvling it up same as classic flyers DECLARE_HOOK(APrimalDinoCharacter_BeginPlay, void, APrimalDinoCharacter*); void Hook_APrimalDinoCharacter_BeginPlay(APrimalDinoCharacter* dino) { UPrimalCharacterStatusComponent* charStatus = dino->GetCharacterStatusComponent(); FString dino_name; dino->GetDinoDescriptiveName(&dino_name); if (dino_name.Contains("Pteranodon") || dino_name.Contains("Argentavis") || dino_name.Contains("Quetzal")) { const int dino_team = dino->TargetingTeamField(); float* speed5 = charStatus->CurrentStatusValuesField()() + 9; if (dino_team == 1) return APrimalDinoCharacter_BeginPlay_original(dino); if (dino_team == 6) return APrimalDinoCharacter_BeginPlay_original(dino); if (dino_name.Contains("Pteranodon"))//&& dino_team == 1726483630 *speed5 = 0.40; if (dino_name.Contains("Argentavis")) *speed5 = 0.30; if (dino_name.Contains("Quetzal")) *speed5 = 2.00; } return APrimalDinoCharacter_BeginPlay_original(dino); } void Load() { Log::Get().Init("FlyerSpeed"); ArkApi::GetHooks().SetHook("APrimalDinoCharacter.BeginPlay", &Hook_APrimalDinoCharacter_BeginPlay, reinterpret_cast<LPVOID*>(&APrimalDinoCharacter_BeginPlay_original)); } (edited)
Avatar
@Natsu
1:00 PM
not bad nice
1:00 PM
but
1:00 PM
1 tip
1:01 PM
reinterpret_cast<LPVOID*>( (edited)
1:01 PM
is not needed anymore
1:01 PM
2nd tip use my api hook generator:
Avatar
@OwnProx i havent used it in a long time
Avatar
haha cool figured that
1:03 PM
if (dino_team == 1 || dino_team == 6) return APrimalDinoCharacter_BeginPlay_original(dino); (edited)
Avatar
WoolyPenguin 2/26/2019 9:06 PM
for anyone wanting to find Atlas Grid information : UShooterGameInstance *instance = static_cast<UShooterGameInstance*>(ArkApi::GetApiUtils().GetWorld()->OwningGameInstanceField()); if (instance) { auto gridinfo = instance->GridInfoField(); int grid_X = gridinfo->GetCurrentServerInfo()->gridXField(); int grid_Y = gridinfo->GetCurrentServerInfo()->gridYField(); } (edited)
Avatar
nice work!
9:11 PM
so there indeed was a way to get server info ๐Ÿ˜„
Avatar
@OwnProx this link is not available anymore https://ark-server-api.com/threads/arkapi-c-hook-generator-tool.761/post-6374 and the current version keeps crashing when using the search for the last dropdown and then going back. (edited)
5:11 AM
Other than that great tool thanks
5:11 AM
๐Ÿ‘Œ
Avatar
ty ill fix it when i get around to it thanks its probs just some syntax error
2:29 PM
from a header
2:29 PM
something new might of got added it can't handle not sure will verify
2:30 PM
Server Api Creator Tool Source Overview: this tool allows you to quickly generate hooks for in game server functions saving you a lot of time of having to lookup the argument's / structure's / class's manually. Features: Ark & Atlas Api...
2:30 PM
u got the latest one from here?
2:31 PM
i moved it since Michidu added the Tools section
2:33 PM
nevermind i see your reply
Avatar
GSH | MrOwlSky 4/4/2019 8:06 PM
You're alive SkeleWhy
Avatar
lol good to know dev's link to the arkserverapi ๐Ÿ˜‚ https://i.imgur.com/JDJAPDy.png
Avatar
@Michidu what are the - Added new requests functions ?
Avatar
quick and dirty dump of all craftables and requirements void dumpCraftables() { nlohmann::json json; json["Craftables"] = nullptr; // Get all blueprint crafting requirements TArray<UObject*> types; Globals::GetObjectsOfClass(UPrimalItem::GetPrivateStaticClass(NULL), &types, true, EObjectFlags::RF_NoFlags); for (auto object : types) { auto n = static_cast<UPrimalItem*> (object); if (n->IsValidForCrafting()) { FString name; n->GetItemName(&name, false, false, NULL); for (auto res : n->BaseCraftingResourceRequirementsField()) { if (res.ResourceItemType.uClass) { if (res.ResourceItemType.uClass->ClassDefaultObjectField()) { auto pi = static_cast<UPrimalItem*> (res.ResourceItemType.uClass->ClassDefaultObjectField()); FString type; pi->GetItemName(&type, false, false, NULL); json["Craftables"][name.ToString()][type.ToString()] = res.BaseResourceRequirement; } } } } } std::filesystem::create_directory("resources"); std::ofstream file("resources/craftables.json"); file << json; file.flush(); file.close(); }
Avatar
WoolyPenguin 4/3/2020 2:32 PM
Unloading multithreaded plugins: #ifdef __cplusplus extern "C" { #endif __declspec(dllexport) void Plugin_Unload() { // Stop threads here } #ifdef __cplusplus } #endif
Avatar
WoolyPenguin 4/19/2020 4:33 PM
you can unload the thread in Plugin_Unload()
Avatar
WoolyPenguin 4/19/2020 4:42 PM
closing a thread is done same way one would always do it in any C++ program ๐Ÿ™‚
Avatar
spawning a dino inside a cryopod, credits to @jraServerAPI and @Pelayori
๐Ÿคž 2
Avatar
std::pair<float, float> FVectorToCoords(FVector ActorPosition) { AWorldSettings* WorldSettings = ArkApi::GetApiUtils().GetWorld()->GetWorldSettings(false, true); APrimalWorldSettings* PWorldSettings = static_cast<APrimalWorldSettings*>(WorldSettings); float LatScale = PWorldSettings->LatitudeScaleField() != 0 ? PWorldSettings->LatitudeScaleField() : 800.0f; float LongScale = PWorldSettings->LongitudeScaleField() != 0 ? PWorldSettings->LongitudeScaleField() : 800.0f; float LatOrigin = PWorldSettings->LatitudeOriginField() != 0 ? PWorldSettings->LatitudeOriginField() : -400000.0f; float LongOrigin = PWorldSettings->LongitudeOriginField() != 0 ? PWorldSettings->LongitudeOriginField() : -400000.0f; float LatDiv = 100.f / LatScale; float Lat = (LatDiv * ActorPosition.Y + LatDiv * abs(LatOrigin)) / 1000.f; float LongDiv = 100.f / LongScale; float Long = (LongDiv * ActorPosition.X + LongDiv * abs(LongOrigin)) / 1000.f; return std::make_pair<float, float>(std::floor(Lat * 10.) / 10., std::floor(Long * 10.) / 10.); }
๐Ÿป 6
9:55 PM
how to convert FVector to GPS coordinates, updated to account for maps that do not provide scales
Avatar
Last Ark Api update included the necessary stuff to loop the global objects array, making it easy to find any class/object as long as it's valid and it exists on the world. Find a class like this: static UClass* object_class = Globals::FindClass("Class /Script/CoreUObject.Class"); static UClass* script_struct_class = Globals::FindClass("Class /Script/CoreUObject.ScriptStruct"); Alternatively, you can iterate it manually like this: for (auto i = 0; i < GUObjectArray()().ObjObjects.NumElements; i++) { auto obj = GUObjectArray()().ObjObjects.GetObjectPtr(i)->Object; if (obj != nullptr) { // Do something with the object reference } } This would mainly be used to find classes or objects which don't have a function to get the static class. It is recommended to declare those class variables as static so they only init once. Credits to @dougy and @substitute who made this originally (edited)
๐Ÿ‘ 3
ThankYou 2
Avatar
How to destroy foliage in given radius: void DestroyFoliageInRadius(FVector position, int radius) { TArray<FOverlappedFoliageElement> out; UVictoryCore::ServerSearchFoliage( ArkApi::GetApiUtils().GetWorld(), &position, radius, &out, true, true, true, false, false ); static FString DmgTypeBpPath(FString("Blueprint'/Game/PrimalEarth/CoreBlueprints/DamageTypes/DmgType_MiningDrill_Harvest.DmgType_MiningDrill_Harvest'")); static UClass* DmgType = UVictoryCore::BPLoadClass(&DmgTypeBpPath); for (FOverlappedFoliageElement& elem : out) { if (!elem.HarvestLocation.IsNearlyZero()) { elem.InstancedStaticMeshComponent->DealDirectDamage(nullptr, 999999, DmgType, elem.HitBodyIndex); } } } FOverlappedFoliageElement struct FOverlappedFoliageElement { AActor* HarvestActor; UInstancedStaticMeshComponent* InstancedStaticMeshComponent; UPrimalHarvestingComponent* HarvestingComponent; FVector HarvestLocation; int HitBodyIndex; float MaxHarvestHealth; float CurrentHarvestHealth; __int8 bIsUnharvestable : 1; __int8 bIsVisibleAndActive : 1; }; UInstancedStaticMeshComponent struct UInstancedStaticMeshComponent : UStaticMeshComponent { void DealDirectDamage(APlayerController* ForPC, float DamageAmount, TSubclassOf<UDamageType> DamageTypeClass, int hitBodyIndex) { NativeCall<void, APlayerController*, float, TSubclassOf<UDamageType>, int>(this, "UInstancedStaticMeshComponent.DealDirectDamage", ForPC, DamageAmount, DamageTypeClass, hitBodyIndex); } }; If not there already, add this to UVictoryCore static void ServerSearchFoliage(UObject* WorldContextObject, FVector* Origin, float Radius, TArray<FOverlappedFoliageElement>* OutFoliage, bool bVisibleAndActiveOnly, bool bIncludeUsableFoliage, bool bIncludeMeshFoliage, bool bSortByDistance, bool bReverseSort) { NativeCall<void, UObject*, FVector*, float, TArray<FOverlappedFoliageElement>*, bool, bool, bool, bool, bool>(nullptr, "UVictoryCore.ServerSearchFoliage", WorldContextObject, Origin, Radius, OutFoliage, bVisibleAndActiveOnly, bIncludeUsableFoliage, bIncludeMeshFoliage, bSortByDistance, bReverseSort); } (edited)
๐Ÿ‘ 5
Avatar
Simple function to Remove a single buff on a Dino: void RemoveDinoBuff(APrimalDinoCharacter* dino) { if (dino != nullptr) { TArray<APrimalBuff*> dino_buffs; dino->GetAllBuffs(&dino_buffs); for (APrimalBuff* dino_buff : dino_buffs) { const FString dino_bp_buff = ArkApi::GetApiUtils().GetBlueprint(dino_buff); if (dino_bp_buff.Contains("Insert_Buff_Path_Here")) { dino_buff->Destroy(true, false); return; } } } } (edited)
๐Ÿ‘ 2
Avatar
Tip: Cautious on using AShooterPlayerController::GetPlayerCharacter. This method seem to crash the server if it's called on a valid controller that is just connecting/disconnecting to/from the server and the character takes any damage (turrets, dinos, etc...) Prefer to use something like AShooterPlayerController.LastControlledPlayerCharacterField, or the traditional AShooterPlayerController.CharacterField, but this one can return the dino being ridden if player is currently riding a dino (edited)
๐Ÿ‘ 5
Avatar
Recent addition to the API (must have latest headers, Fields.h one specifically): Function to get size (in bytes) of some game structs. GetStructSize<T>() - For game structs (classes that start with F, such as FTribeData GetObjectClassSize<T>() - For classes inherited from UObject, such as AActor Example of usage: Loading a tribe data pointer: static int tribeDataStructSize = GetStructSize<FTribeData>(); FTribeData* data = static_cast<FTribeData*>(FMemory::Malloc(tribeDataStructSize)); RtlSecureZeroMemory(data, tribeDataStructSize); ArkApi::GetApiUtils().GetShooterGameMode()->GetOrLoadTribeData(team, data); // use the tribe data // don't forget to free the memory! FMemory::Free(data); This will ensure you don't allocate a lot of memory that won't be used, since it was a common method to allocate 0x200, around 512 bytes when some structs needed less (or even more!) than that. That function ensures the correct size is allocated. (edited)
lethalclap 2
pepehype 1
๐Ÿ‘ 1
Avatar
Change some command line settings at runtime I found myself in the case where I had starter the server with -NoDinos on the command line, and I came up with a dirty plugin to solve it without restarting the server: DECLARE_HOOK(FCommandLine_Get, wchar_t*); wchar_t* Hook_FCommandLine_Get() { wchar_t* ret = FCommandLine_Get_original(); FString fret(ret); if (fret.Contains(L"-NoDinos")) fret.Replace(L"-NoDinos", L""); else fret.Replace(L"-NoDinos", L""); (*ret) = **fret; return ((wchar_t*)*fret); } void Load() { Log::Get().Init("TestPlugin"); ArkApi::GetHooks().SetHook("FCommandLine.Get", &Hook_FCommandLine_Get, &FCommandLine_Get_original); ArkApi::GetCommands().AddConsoleCommand("dinos.enable", [](APlayerController*, FString*, bool) { TArray<AActor*> out; UGameplayStatics::GetAllActorsOfClass(ArkApi::GetApiUtils().GetWorld(), ANPCZoneManager::GetPrivateStaticClass(), &out); for (auto* a : out) if (a && a->IsA(ANPCZoneManager::GetPrivateStaticClass())) { ((ANPCZoneManager*)a)->BeginPlay(); } }); } void Unload() { ArkApi::GetHooks().DisableHook("FCommandLine.Get", &Hook_FCommandLine_Get); ArkApi::GetCommands().RemoveConsoleCommand("dinos.enable"); }
9791_pepe 1
๐Ÿ‘ 5
Avatar
Finally got around to playing with IDA because I needed a hook to catch when Genesis missions start so I could block it if I wanted, Figured I would share my findings here since this community has been a huge help to me starting out. DECLARE_HOOK(AMissionType_CanStartMission, bool, TSubclassOf<AMissionType>, APlayerController*, FString*, AActor**); bool Hook_AMissionType_CanStartMission(TSubclassOf<AMissionType> MissionType, APlayerController* Controller, FString* OutClientFailureReason, AActor** OutMissionDispatcher) { return AMissionType_CanStartMission_original(MissionType, Controller, OutClientFailureReason, OutMissionDispatcher); } ArkApi::GetHooks().SetHook("AMissionType.CanStartMission", &Hook_AMissionType_CanStartMission, &AMissionType_CanStartMission_original); ArkApi::GetHooks().DisableHook("AMissionType.CanStartMission", &Hook_AMissionType_CanStartMission); (edited)
๐Ÿ‘ 2
Avatar
My own version of timers, with high precision clock with on tick callback (doing it on tick reduces precision, though) Can add tasks async that will execute on the main thread Use at your own risk, for reference Open to suggestion on improvements #pragma once #include "API/ARK/Ark.h" namespace Tools { class Timer { public: Timer() { ArkApi::GetCommands().AddOnTickCallback("Plugin.HelperTimer.Update", std::bind(&Tools::Timer::Update, this, std::placeholders::_1)); } ~Timer() { ArkApi::GetCommands().RemoveOnTickCallback("Plugin.HelperTimer.Update"); } template <class func, class... arguments> void DelayExec(func&& f, int ms_after, bool async, arguments&&... args) { if (!async) { std::lock_guard<std::mutex> lg(tasks_mtx_); tasks_.push_back(std::make_shared<Task>(std::bind(f, std::forward<arguments>(args)...), ms_after)); } else { auto function = std::bind(f, std::forward<arguments>(args)...); std::thread([&function, ms_after]() { std::this_thread::sleep_for(std::chrono::milliseconds(ms_after)); function(); } ).detach(); } } void Update(float) { const auto now = std::chrono::high_resolution_clock::now(); tasks_mtx_.lock(); const auto tasks = tasks_; tasks_mtx_.unlock(); for (const auto& function : tasks) { if (function && function->execTime <= now && function->callback) { function->callback(); tasks_mtx_.lock(); tasks_.erase(std::find(tasks_.begin(), tasks_.end(), function)); tasks_mtx_.unlock(); } } } static Timer& Get() { static Timer instance; return instance; } private: struct Task { Task(std::function<void()> cbk, int after) : callback(std::move(cbk)) { execTime = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(after); } std::function<void()> callback; std::chrono::high_resolution_clock::time_point execTime; }; std::mutex tasks_mtx_; std::vector<std::shared_ptr<Task>> tasks_; }; }
๐Ÿ‘ 4
Avatar
Small guide on how to send data from your plugin to your own mod. This might not be the best way to do it, but this is how I started doing it and since it took me a bit of leg work to find I figured I would share it with others as a base to get started. You can also send more variables if you set it up as a struct, but you can do some searching for that as this is just an example to get your started. Plugin: TWeakObjectPtr<AActor> singleCCA; FString MyCCA = "My_CCA_C"; //This line is just a variable incase you want to set it by config or change it later Must be the same name as your CCA class. //This function finds your CCA (Central Control Actor) and sets it as a weak object. This is done because in some examples of CCA's from the mod community the CCA is set to update or replace iteself from time to time, using a weak object will always check to make sure it still exists in the world, if it does not, it will set a new one. void setCCA() { auto Gengine = Globals::GEngine(); auto primalglobals = static_cast<UPrimalGlobals*>(Gengine()->GameSingletonField()); auto gamedata = primalglobals->PrimalGameDataOverrideField(); auto singletons = gamedata->ServerExtraWorldSingletonActorClassesField(); for (auto singleton : singletons) { if (singleton.uClass) { FString className; singleton.uClass->GetDescription(&className); if (className == MyCCA) { TArray<AActor*> SingletonActors; UGameplayStatics::GetAllActorsOfClass(reinterpret_cast<UObject*>(ArkApi::GetApiUtils().GetWorld()), singleton, &SingletonActors); if (!SingletonActors[0]) return; singleCCA = GetWeakReference(SingletonActors[0]); } } } } //This is the function you call to push information to the mod, in this example it is just a single string, but you can use whatever you want. void SendToMod(FString info) { if (singleCCA.Get() == nullptr) //Check to see if the CCA is still in the world. setCCA(); //If its not, make a new reference to it. AActor* Function_CCA = singleCCA.Get(); //Set your weak reference to an Actor. if (!Function_CCA) //Make sure the actor is valid. return; //If not return. UFunction* cca_Function = Function_CCA->FindFunctionChecked(FName("SetModInfo", EFindName::FNAME_Add)); //Looks for the function name in your CCA actor. if (!cca_Function) return; //If the function is not found return; Function_CCA->ProcessEvent(cca_Function, &info); //Sends the info to the function in the CCA actor. } Mod: (edited)
Exported 186 message(s)
Timezone: UTC+1