115 lines
3.5 KiB
C++
115 lines
3.5 KiB
C++
|
#include "Achievements.h"
|
||
|
#include "skse64/GameMenus.h"
|
||
|
#include "skse64/GameEvents.h"
|
||
|
#include "steam\steam_api.h"
|
||
|
#include <string>
|
||
|
#include <processenv.h>
|
||
|
|
||
|
class InitSteamOnEvent : public BSTEventSink<MenuOpenCloseEvent> {
|
||
|
public:
|
||
|
virtual ~InitSteamOnEvent() {}
|
||
|
virtual EventResult ReceiveEvent(MenuOpenCloseEvent * evn, EventDispatcher<MenuOpenCloseEvent> * dispatcher) {
|
||
|
if (std::strcmp(evn->menuName.data, "Main Menu")) {
|
||
|
_MESSAGE("Main menu opened, trying to init steam API.");
|
||
|
Achievements::startSteam();
|
||
|
}
|
||
|
return EventResult::kEvent_Continue;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
namespace Achievements {
|
||
|
|
||
|
bool setAchievementUnlocked(StaticFunctionTag* tag, BSFixedString achievement)
|
||
|
{
|
||
|
return singleton->setAchievementUnlocked(achievement.data);
|
||
|
}
|
||
|
|
||
|
void registerMainMenuEvent() {
|
||
|
MenuManager * mm = MenuManager::GetSingleton();
|
||
|
if (mm) {
|
||
|
mm->MenuOpenCloseEventDispatcher()->AddEventSink(new InitSteamOnEvent());
|
||
|
}
|
||
|
else {
|
||
|
_MESSAGE("Failed to register SKSE menuEventHandler!");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void steamInit(StaticFunctionTag* tag) {
|
||
|
startSteam();
|
||
|
}
|
||
|
|
||
|
void startSteam()
|
||
|
{
|
||
|
try {
|
||
|
if (singleton.get() == nullptr) {
|
||
|
SteamAPI_Shutdown();
|
||
|
SetEnvironmentVariable("SteamAppID", "933480");
|
||
|
SetEnvironmentVariable("SteamGameId", "933480");
|
||
|
bool success = SteamAPI_Init();
|
||
|
if (success)
|
||
|
_MESSAGE("Steam api init was successfull");
|
||
|
else
|
||
|
_MESSAGE("Error while initializing the steam api");
|
||
|
|
||
|
singleton.swap(std::make_unique<AchievementHolder>());
|
||
|
singleton->start();
|
||
|
}
|
||
|
else {
|
||
|
_MESSAGE("Already initialized steam api, skipping it");
|
||
|
}
|
||
|
}
|
||
|
catch (const std::exception& ex) {
|
||
|
std::string msg = "Exception while initializing the Steam API, steam achievements will not be available: " + std::string(ex.what());
|
||
|
_MESSAGE(msg.c_str());
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
bool RegisterFuncs(VMClassRegistry * registry)
|
||
|
{
|
||
|
registry->RegisterFunction(new NativeFunction1<StaticFunctionTag, bool, BSFixedString>("UnlockAchievement", "Game", Achievements::setAchievementUnlocked, registry));
|
||
|
registry->RegisterFunction( new NativeFunction0<StaticFunctionTag, void>("SteamInit", "Game", Achievements::steamInit, registry));
|
||
|
Achievements::registerMainMenuEvent();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
AchievementHolder::AchievementHolder() : stats(SteamUserStats()), callback(this, &AchievementHolder::onUserStatsReceived)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void AchievementHolder::onUserStatsReceived(UserStatsReceived_t * event) {
|
||
|
try {
|
||
|
std::string msg = "User id: " + std::to_string(event->m_steamIDUser.ConvertToUint64()) + ", game id: " + std::to_string(event->m_nGameID) + ", success state: " + std::to_string(event->m_eResult);
|
||
|
_MESSAGE(msg.c_str());
|
||
|
|
||
|
uint32 achievementCount = this->stats->GetNumAchievements();
|
||
|
msg = "There are " + std::to_string(achievementCount) + " achievements";
|
||
|
_MESSAGE(msg.c_str());
|
||
|
}
|
||
|
catch (const std::exception& ex) {
|
||
|
std::string msg = "Exception during steam callback: onUserStatsReceived. Failed to print data: " + std::string(ex.what());
|
||
|
_MESSAGE(msg.c_str());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool AchievementHolder::setAchievementUnlocked(const char * achievementName)
|
||
|
{
|
||
|
std::string msg = "Unlocking achievement: " + std::string(achievementName);
|
||
|
_MESSAGE(msg.c_str());
|
||
|
bool success = this->stats->SetAchievement(achievementName);
|
||
|
if (!success) {
|
||
|
_MESSAGE("Error while unlocking achievement");
|
||
|
return false;
|
||
|
}
|
||
|
success = this->stats->StoreStats();
|
||
|
if (!success) {
|
||
|
_MESSAGE("Error while storing unlocked achievement");
|
||
|
}
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
void AchievementHolder::start()
|
||
|
{
|
||
|
this->stats->RequestCurrentStats();
|
||
|
}
|
||
|
}
|