forked from aya/aya
Initial commit
This commit is contained in:
136
client/common/AppSettings.cpp
Normal file
136
client/common/AppSettings.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#include "AppSettings.hpp"
|
||||
#include <QString>
|
||||
|
||||
#ifndef SKIP_APP_SETTINGS_LOADING
|
||||
#include "Utility/StandardOut.hpp"
|
||||
#include "Utility/Statistics.hpp"
|
||||
#endif // SKIP_APP_SETTINGS_LOADING
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
static const char* kAppSettingsFileName = "AppSettings.ini";
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
AppSettings::AppSettings(const std::string& appDir)
|
||||
: m_pSettings(nullptr)
|
||||
{
|
||||
this->appDir = appDir;
|
||||
}
|
||||
|
||||
AppSettings::~AppSettings()
|
||||
{
|
||||
delete m_pSettings;
|
||||
}
|
||||
|
||||
bool AppSettings::load()
|
||||
{
|
||||
if (appDir.empty())
|
||||
return false;
|
||||
|
||||
delete m_pSettings;
|
||||
|
||||
std::string path = appDir + "/" + kAppSettingsFileName;
|
||||
|
||||
#ifndef SKIP_APP_SETTINGS_LOADING
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_SYSTEM, "Loading AppSettings from %s", path.c_str());
|
||||
#endif
|
||||
|
||||
m_pSettings = new QSettings(QString::fromStdString(appDir + "/" + kAppSettingsFileName), QSettings::IniFormat);
|
||||
|
||||
bool success = m_pSettings->status() == QSettings::NoError;
|
||||
|
||||
if (success)
|
||||
{
|
||||
m_pSettings->sync();
|
||||
m_pSettings->setFallbacksEnabled(true);
|
||||
|
||||
// hack for bootstrapper who can't deal with allat
|
||||
#ifndef SKIP_APP_SETTINGS_LOADING
|
||||
std::string assetFolder = get("Aya", "ContentFolder").value_or(appDir + "/content");
|
||||
SetAssetFolder(assetFolder);
|
||||
SetTrustCheckURL(get("Aya", "TrustCheckUrl").value_or(""));
|
||||
|
||||
if (GetTrustCheckURL().empty())
|
||||
SetUsingTrustCheck(false);
|
||||
|
||||
if (has("Aya", "InsecureMode"))
|
||||
{
|
||||
std::string insecureMode = get("Aya", "InsecureMode").value_or("false");
|
||||
boost::algorithm::to_lower(insecureMode);
|
||||
SetInsecureMode(insecureMode == "true" || insecureMode == "1" || insecureMode == "yes");
|
||||
}
|
||||
|
||||
if (has("Aya", "VerboseLogging"))
|
||||
{
|
||||
std::string verboseLogging = get("Aya", "VerboseLogging").value_or("false");
|
||||
boost::algorithm::to_lower(verboseLogging);
|
||||
SetVerboseLogging(verboseLogging == "true" || verboseLogging == "1" || verboseLogging == "yes");
|
||||
}
|
||||
|
||||
if (hasGroup("Instance"))
|
||||
{
|
||||
SetBaseURL(get("Instance", "BaseUrl").value_or(""));
|
||||
SetInstanceAccessKey(get("Instance", "AccessKey").value_or(""));
|
||||
}
|
||||
|
||||
if (GetBaseURL().empty())
|
||||
{
|
||||
SetUsingInstance(false);
|
||||
SetFetchLocalClientSettings(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetUsingInstance(true);
|
||||
SetFetchLocalClientSettings(false);
|
||||
}
|
||||
|
||||
if (hasGroup("MasterServer"))
|
||||
{
|
||||
SetMasterServerURL(get("MasterServer", "BaseUrl").value_or(""));
|
||||
SetMasterServerKey(get("MasterServer", "AccessKey").value_or(""));
|
||||
}
|
||||
|
||||
SetUsingMasterServer(!GetMasterServerURL().empty());
|
||||
#endif // SKIP_APP_SETTINGS_LOADING
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
std::optional<std::string> AppSettings::get(const std::string& group, const std::string& key) const
|
||||
{
|
||||
m_pSettings->beginGroup(QString::fromStdString(group));
|
||||
QVariant value = m_pSettings->value(QString::fromStdString(key));
|
||||
m_pSettings->endGroup();
|
||||
|
||||
if (value.isValid() && value.type() == QVariant::String)
|
||||
return value.toString().toStdString();
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool AppSettings::hasGroup(const std::string& group)
|
||||
{
|
||||
return m_pSettings->childGroups().contains(QString::fromStdString(group));
|
||||
}
|
||||
|
||||
bool AppSettings::has(const std::string& group, const std::string& key)
|
||||
{
|
||||
if (!this->hasGroup(group))
|
||||
return false;
|
||||
|
||||
m_pSettings->beginGroup(QString::fromStdString(group));
|
||||
QVariant value = m_pSettings->value(QString::fromStdString(key));
|
||||
m_pSettings->endGroup();
|
||||
|
||||
return value.isValid();
|
||||
}
|
||||
|
||||
void AppSettings::set(const std::string& group, const std::string& key, const std::string& value)
|
||||
{
|
||||
m_pSettings->beginGroup(QString::fromStdString(group));
|
||||
m_pSettings->setValue(QString::fromStdString(key), QString::fromStdString(value));
|
||||
m_pSettings->endGroup();
|
||||
}
|
||||
21
client/common/AppSettings.hpp
Normal file
21
client/common/AppSettings.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include <QSettings>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
class AppSettings
|
||||
{
|
||||
public:
|
||||
AppSettings(const std::string& appDir);
|
||||
virtual ~AppSettings();
|
||||
|
||||
bool load();
|
||||
std::optional<std::string> get(const std::string& group, const std::string& key) const;
|
||||
bool hasGroup(const std::string& group);
|
||||
bool has(const std::string& group, const std::string& key);
|
||||
void set(const std::string& group, const std::string& key, const std::string& value);
|
||||
|
||||
protected:
|
||||
QSettings* m_pSettings;
|
||||
std::string appDir;
|
||||
};
|
||||
0
client/common/AppView.cpp
Normal file
0
client/common/AppView.cpp
Normal file
0
client/common/AppView.hpp
Normal file
0
client/common/AppView.hpp
Normal file
635
client/common/CrashManager.cpp
Normal file
635
client/common/CrashManager.cpp
Normal file
@@ -0,0 +1,635 @@
|
||||
#ifndef AYA_STUDIO
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#include "format_string.hpp"
|
||||
#include "AyaFormat.hpp"
|
||||
#include "Debug.hpp"
|
||||
#include "boost.hpp"
|
||||
#include "Utility/StandardOut.hpp"
|
||||
#include "Utility/FileSystem.hpp"
|
||||
#include "Utility/Guid.hpp"
|
||||
#include "Utility/Http.hpp"
|
||||
#include "Utility/Statistics.hpp"
|
||||
|
||||
#include "debugAssert.hpp"
|
||||
#include <direct.h>
|
||||
|
||||
#include "atltime.h"
|
||||
#include "atlfile.h"
|
||||
|
||||
#include "TaskScheduler.hpp"
|
||||
#include "DumpErrorUploader.hpp"
|
||||
#include "Log.hpp"
|
||||
#include "FastLog.hpp"
|
||||
#include <Windows.h>
|
||||
#include <DbgHelp.h>
|
||||
#include <string.h>
|
||||
#include <atlbase.h>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
LOGGROUP(CrashReporterInit)
|
||||
|
||||
bool LogManager::logsEnabled = false; // to be honest we only really need crash dmps & the logs outputted are not working
|
||||
|
||||
MainLogManager* LogManager::mainLogManager = NULL;
|
||||
|
||||
Aya::mutex MainLogManager::fastLogChannelsLock;
|
||||
|
||||
static const ATL::CPath& DoGetPath()
|
||||
{
|
||||
static ATL::CPath path(CString(Aya::FileSystem::getUserDirectory(true, Aya::DirAppData, "logs").native().c_str()));
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
void InitPath()
|
||||
{
|
||||
DoGetPath();
|
||||
}
|
||||
|
||||
std::string GetAppVersion()
|
||||
{
|
||||
CVersionInfo vi;
|
||||
FASTLOG1(FLog::CrashReporterInit, "Getting app version, module handle: %p", _AtlBaseModule.m_hInst);
|
||||
vi.Load(_AtlBaseModule.m_hInst);
|
||||
return vi.GetFileVersionAsString();
|
||||
}
|
||||
|
||||
const ATL::CPath& LogManager::GetLogPath() const
|
||||
{
|
||||
static boost::once_flag flag = BOOST_ONCE_INIT;
|
||||
boost::call_once(&InitPath, flag);
|
||||
return DoGetPath();
|
||||
}
|
||||
|
||||
const std::string LogManager::GetLogPathString() const
|
||||
{
|
||||
CStringA path = (LPCTSTR)GetLogPath();
|
||||
return std::string(path.GetString());
|
||||
}
|
||||
|
||||
void MainLogManager::fastLogMessage(FLog::Channel id, const char* message)
|
||||
{
|
||||
Aya::mutex::scoped_lock lock(fastLogChannelsLock);
|
||||
|
||||
if (mainLogManager)
|
||||
{
|
||||
if (id >= mainLogManager->fastLogChannels.size())
|
||||
mainLogManager->fastLogChannels.resize(id + 1, NULL);
|
||||
|
||||
if (mainLogManager->fastLogChannels[id] == NULL)
|
||||
{
|
||||
|
||||
mainLogManager->fastLogChannels[id] = new Aya::Log(mainLogManager->getFastLogFileName(id).c_str(), "Log Channel");
|
||||
}
|
||||
|
||||
mainLogManager->fastLogChannels[id]->writeEntry(Aya::Log::Information, message);
|
||||
}
|
||||
}
|
||||
|
||||
std::string MainLogManager::getSessionId()
|
||||
{
|
||||
std::string id = guid;
|
||||
return id;
|
||||
}
|
||||
|
||||
std::string MainLogManager::getCrashEventName()
|
||||
{
|
||||
#ifdef WIN32
|
||||
FASTLOG(FLog::CrashReporterInit, "Getting crash event name");
|
||||
std::string path = GetLogPathString();
|
||||
|
||||
std::string fileName = "log_";
|
||||
fileName += getSessionId();
|
||||
fileName += " ";
|
||||
|
||||
fileName += GetAppVersion();
|
||||
fileName += crashEventExtention;
|
||||
|
||||
path.append(fileName);
|
||||
|
||||
return path;
|
||||
#endif
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string MainLogManager::getLogFileName()
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::string path = GetLogPathString();
|
||||
|
||||
std::string fileName = "log_";
|
||||
fileName += getSessionId();
|
||||
fileName += ".txt";
|
||||
|
||||
path.append(fileName);
|
||||
|
||||
return path;
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string MainLogManager::getFastLogFileName(FLog::Channel channelId)
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::string path = GetLogPathString();
|
||||
std::string filename = Aya::format("log_%s_%d.txt", getSessionId().c_str(), channelId);
|
||||
|
||||
path.append(filename);
|
||||
|
||||
return path;
|
||||
#endif
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
std::string MainLogManager::MakeLogFileName(const char* postfix)
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::string path = GetLogPathString();
|
||||
|
||||
std::string fileName = "log_";
|
||||
fileName += getSessionId();
|
||||
fileName += postfix;
|
||||
fileName += ".txt";
|
||||
|
||||
path.append(fileName);
|
||||
|
||||
return path;
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string ThreadLogManager::getLogFileName()
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::string fileName = mainLogManager->getLogFileName();
|
||||
std::string id = Aya::format("_%s_%d", name.c_str(), threadID);
|
||||
fileName.insert(fileName.size() - 4, id);
|
||||
return fileName;
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
Aya::Log* LogManager::getLog()
|
||||
{
|
||||
if (!logsEnabled)
|
||||
return NULL;
|
||||
if (log == NULL)
|
||||
{
|
||||
log = new Aya::Log(getLogFileName().c_str(), name.c_str());
|
||||
// TODO: delete an old log that isn't in use
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
|
||||
Aya::Log* MainLogManager::provideLog()
|
||||
{
|
||||
if (GetCurrentThreadId() == threadID)
|
||||
return this->getLog();
|
||||
|
||||
return ThreadLogManager::getCurrent()->getLog();
|
||||
}
|
||||
|
||||
|
||||
#include <process.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
|
||||
#define MAX_CONSOLE_LINES 250;
|
||||
|
||||
HANDLE g_hConsoleOut; // Handle to debug console
|
||||
|
||||
|
||||
|
||||
RobloxCrashReporter::RobloxCrashReporter(const char* outputPath, const char* appName, const char* crashExtention)
|
||||
{
|
||||
controls.minidumpType = MiniDumpWithDataSegs;
|
||||
|
||||
controls.minidumpType |= MiniDumpWithIndirectlyReferencedMemory;
|
||||
|
||||
// null terminate just in case long paths & make safe
|
||||
strncpy(controls.pathToMinidump, outputPath, sizeof(controls.pathToMinidump) - 1);
|
||||
controls.pathToMinidump[sizeof(controls.pathToMinidump) - 1] = '\0';
|
||||
|
||||
strncpy(controls.appName, appName, sizeof(controls.appName) - 1);
|
||||
controls.appName[sizeof(controls.appName) - 1] = '\0';
|
||||
|
||||
strncpy(controls.appVersion, GetAppVersion().c_str(), sizeof(controls.appVersion) - 1);
|
||||
controls.appVersion[sizeof(controls.appVersion) - 1] = '\0';
|
||||
|
||||
strncpy(controls.crashExtention, crashExtention, sizeof(controls.crashExtention) - 1);
|
||||
controls.crashExtention[sizeof(controls.crashExtention) - 1] = '\0';
|
||||
}
|
||||
|
||||
bool RobloxCrashReporter::silent;
|
||||
|
||||
LONG RobloxCrashReporter::ProcessException(struct _EXCEPTION_POINTERS* info, bool noMsg)
|
||||
{
|
||||
LogManager::ReportEvent(EVENTLOG_INFORMATION_TYPE, "StartProcessException...");
|
||||
|
||||
LONG result = __super::ProcessException(info, noMsg);
|
||||
static bool showedMessage = silent;
|
||||
if (!showedMessage && !noMsg)
|
||||
{
|
||||
showedMessage = true;
|
||||
::MessageBoxA(NULL, "An unexpected error occurred and " AYA_PROJECT_NAME " needs to quit. We're sorry!", AYA_PROJECT_NAME " Crash", MB_OK);
|
||||
}
|
||||
|
||||
LogManager::ReportEvent(EVENTLOG_INFORMATION_TYPE, "DoneProcessException");
|
||||
|
||||
LogManager::ReportEvent(EVENTLOG_INFORMATION_TYPE, "Uploading .crashevent...");
|
||||
DumpErrorUploader::UploadCrashEventFile(info);
|
||||
LogManager::ReportEvent(EVENTLOG_INFORMATION_TYPE, "Done uploading .crashevent...");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void RobloxCrashReporter::logEvent(const char* msg)
|
||||
{
|
||||
LogManager::ReportEvent(EVENTLOG_INFORMATION_TYPE, msg);
|
||||
}
|
||||
|
||||
void MainLogManager::WriteCrashDump()
|
||||
{
|
||||
std::string appName = "log_";
|
||||
appName += getSessionId();
|
||||
crashReporter.reset(new RobloxCrashReporter(GetLogPathString().c_str(), appName.c_str(), crashExtention));
|
||||
crashReporter->Start();
|
||||
};
|
||||
|
||||
bool MainLogManager::CreateFakeCrashDump()
|
||||
{
|
||||
if (!crashReporter)
|
||||
{
|
||||
// start the service if not started.
|
||||
WriteCrashDump();
|
||||
}
|
||||
|
||||
// First, write FastLog
|
||||
char dumpFilepath[_MAX_PATH];
|
||||
if (FAILED(crashReporter->GenerateDmpFileName(dumpFilepath, _MAX_PATH, true)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FLog::WriteFastLogDump(dumpFilepath, 2000);
|
||||
|
||||
if (FAILED(crashReporter->GenerateDmpFileName(dumpFilepath, _MAX_PATH)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE hFile = CreateFileA(dumpFilepath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD cb;
|
||||
WriteFile(hFile, "Fake", 5, &cb, NULL);
|
||||
|
||||
CloseHandle(hFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainLogManager::EnableImmediateCrashUpload(bool enabled)
|
||||
{
|
||||
if (crashReporter)
|
||||
{
|
||||
crashReporter->EnableImmediateUpload(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void MainLogManager::DisableHangReporting()
|
||||
{
|
||||
if (crashReporter)
|
||||
{
|
||||
crashReporter->DisableHangReporting();
|
||||
}
|
||||
}
|
||||
|
||||
void MainLogManager::NotifyFGThreadAlive()
|
||||
{
|
||||
if (crashReporter)
|
||||
{
|
||||
#if 0
|
||||
// for debugging only:
|
||||
static int alivecount = 0;
|
||||
if(alivecount++ % 60 == 0)
|
||||
{
|
||||
CString eventMessage;
|
||||
eventMessage.Format("FGAlive %d", alivecount);
|
||||
LogManager::ReportEvent(EVENTLOG_INFORMATION_TYPE, eventMessage);
|
||||
}
|
||||
#endif
|
||||
|
||||
crashReporter->NotifyAlive();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void purecallHandler(void)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
_CrtDbgBreak();
|
||||
#endif
|
||||
// Cause a crash
|
||||
AYACRASH();
|
||||
}
|
||||
|
||||
MainLogManager::MainLogManager(LPCTSTR productName, const char* crashExtention, const char* crashEventExtention)
|
||||
: LogManager("Aya")
|
||||
, crashExtention(crashExtention)
|
||||
, crashEventExtention(crashEventExtention)
|
||||
, gameState(MainLogManager::GameState::UN_INITIALIZED)
|
||||
{
|
||||
Aya::Guid::generateRBXGUID(guid);
|
||||
|
||||
AYAASSERT(mainLogManager == NULL);
|
||||
mainLogManager = this;
|
||||
|
||||
Aya::Log::setLogProvider(this);
|
||||
|
||||
Aya::setAssertionHook(&MainLogManager::handleDebugAssert);
|
||||
Aya::setFailureHook(&MainLogManager::handleFailure);
|
||||
|
||||
_set_purecall_handler(purecallHandler);
|
||||
|
||||
FLog::SetExternalLogFunc(fastLogMessage);
|
||||
}
|
||||
|
||||
MainLogManager* LogManager::getMainLogManager()
|
||||
{
|
||||
return mainLogManager;
|
||||
}
|
||||
|
||||
|
||||
ThreadLogManager::ThreadLogManager()
|
||||
: LogManager(Aya::get_thread_name())
|
||||
{
|
||||
}
|
||||
|
||||
ThreadLogManager::~ThreadLogManager() {}
|
||||
|
||||
static float getThisYearTimeInMinutes(SYSTEMTIME time)
|
||||
{
|
||||
return (time.wMonth * 43829.0639f) + (time.wDay * 1440) + (time.wHour * 60) + time.wMinute;
|
||||
}
|
||||
|
||||
MainLogManager::~MainLogManager()
|
||||
{
|
||||
Aya::mutex::scoped_lock lock(fastLogChannelsLock);
|
||||
|
||||
FLog::SetExternalLogFunc(NULL);
|
||||
|
||||
for (std::size_t i = 0; i < fastLogChannels.size(); i++)
|
||||
delete fastLogChannels[i];
|
||||
|
||||
mainLogManager = NULL;
|
||||
}
|
||||
|
||||
|
||||
LogManager::~LogManager()
|
||||
{
|
||||
if (log != NULL)
|
||||
{
|
||||
std::string logFile = log->logFile;
|
||||
delete log; // this will close the file so that we can move it
|
||||
log = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inline HRESULT WINAPI RbxReportError(
|
||||
const CLSID& clsid, LPCSTR lpszDesc, DWORD dwHelpID, LPCSTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0)
|
||||
{
|
||||
ATLASSERT(lpszDesc != NULL);
|
||||
if (lpszDesc == NULL)
|
||||
return E_POINTER;
|
||||
|
||||
USES_CONVERSION_EX;
|
||||
CString strDesc(lpszDesc);
|
||||
CComBSTR desc = strDesc.AllocSysString(); // Convert CString to BSTR
|
||||
if (desc == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
CComBSTR helpFile = NULL;
|
||||
if (lpszHelpFile != NULL)
|
||||
{
|
||||
CString strHelpFile(lpszHelpFile);
|
||||
helpFile = strHelpFile.AllocSysString(); // Convert CString to BSTR
|
||||
if (helpFile == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
return AtlSetErrorInfo(clsid, desc.Detach(), dwHelpID, helpFile.Detach(), iid, hRes, NULL);
|
||||
}
|
||||
|
||||
inline HRESULT WINAPI RbxReportError(
|
||||
const CLSID& clsid, UINT nID, const IID& iid = GUID_NULL, HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance())
|
||||
{
|
||||
return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), 0, NULL, iid, hRes, hInst);
|
||||
}
|
||||
|
||||
inline HRESULT WINAPI RbxReportError(const CLSID& clsid, UINT nID, DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL,
|
||||
HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance())
|
||||
{
|
||||
return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), dwHelpID, lpszHelpFile, iid, hRes, hInst);
|
||||
}
|
||||
|
||||
inline HRESULT WINAPI RbxReportError(const CLSID& clsid, LPCSTR lpszDesc, const IID& iid = GUID_NULL, HRESULT hRes = 0)
|
||||
{
|
||||
return RbxReportError(clsid, lpszDesc, 0, NULL, iid, hRes);
|
||||
}
|
||||
|
||||
inline HRESULT WINAPI RbxReportError(const CLSID& clsid, LPCOLESTR lpszDesc, const IID& iid = GUID_NULL, HRESULT hRes = 0)
|
||||
{
|
||||
return AtlSetErrorInfo(clsid, lpszDesc, 0, NULL, iid, hRes, NULL);
|
||||
}
|
||||
|
||||
inline HRESULT WINAPI RbxReportError(
|
||||
const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0)
|
||||
{
|
||||
return AtlSetErrorInfo(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes, NULL);
|
||||
}
|
||||
|
||||
HRESULT LogManager::ReportCOMError(const CLSID& clsid, LPCOLESTR lpszDesc, HRESULT hRes)
|
||||
{
|
||||
return RbxReportError(clsid, lpszDesc, GUID_NULL, hRes);
|
||||
}
|
||||
|
||||
HRESULT LogManager::ReportCOMError(const CLSID& clsid, LPCSTR lpszDesc, HRESULT hRes)
|
||||
{
|
||||
return RbxReportError(clsid, lpszDesc, GUID_NULL, hRes);
|
||||
}
|
||||
|
||||
HRESULT LogManager::ReportCOMError(const CLSID& clsid, HRESULT hRes)
|
||||
{
|
||||
std::string message = Aya::format("HRESULT 0x%X", hRes);
|
||||
LogManager::ReportEvent(EVENTLOG_ERROR_TYPE, message.c_str());
|
||||
return RbxReportError(clsid, message.c_str(), GUID_NULL, hRes);
|
||||
}
|
||||
|
||||
#ifdef _MFC_VER
|
||||
HRESULT LogManager::ReportCOMError(const CLSID& clsid, CException* exception)
|
||||
{
|
||||
CString fullError;
|
||||
HRESULT hr = COleException::Process(exception);
|
||||
CString sError;
|
||||
if (exception->GetErrorMessage(sError.GetBuffer(1024), 1023))
|
||||
{
|
||||
sError.ReleaseBuffer();
|
||||
fullError.Format("%s (0x%X)", sError, hr);
|
||||
}
|
||||
else
|
||||
fullError.Format("Error 0x%X", hr);
|
||||
|
||||
LogManager::ReportEvent(EVENTLOG_ERROR_TYPE, fullError);
|
||||
return RbxReportError(clsid, fullError, GUID_NULL, hr);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool MainLogManager::handleG3DDebugAssert(
|
||||
const char* _expression, const std::string& message, const char* filename, int lineNumber, bool useGuiPrompt)
|
||||
{
|
||||
return handleDebugAssert(_expression, filename, lineNumber);
|
||||
}
|
||||
|
||||
bool MainLogManager::handleDebugAssert(const char* expression, const char* filename, int lineNumber)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
LogManager::ReportEvent(EVENTLOG_WARNING_TYPE,
|
||||
std::string("Assertion failed: " + std::string(expression) + "\n" + std::string(filename) + "(" + std::to_string(lineNumber) + ")").c_str());
|
||||
AYACRASH();
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool MainLogManager::handleG3DFailure(const char* _expression, const std::string& message, const char* filename, int lineNumber, bool useGuiPrompt)
|
||||
{
|
||||
return handleFailure(_expression, filename, lineNumber);
|
||||
}
|
||||
bool MainLogManager::handleFailure(const char* expression, const char* filename, int lineNumber)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
_CrtDbgBreak();
|
||||
#endif
|
||||
// Cause a crash
|
||||
AYACRASH();
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT LogManager::ReportExceptionAsCOMError(const CLSID& clsid, std::exception const& exp)
|
||||
{
|
||||
return ReportCOMError(clsid, exp.what());
|
||||
}
|
||||
|
||||
void LogManager::ReportException(std::exception const& exp)
|
||||
{
|
||||
Aya::StandardOut::singleton()->print(Aya::MESSAGE_ERROR, exp);
|
||||
}
|
||||
|
||||
void LogManager::ReportLastError(LPCSTR message)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_ERROR, "%s, GetLastError=%d", message, error);
|
||||
}
|
||||
|
||||
void LogManager::ReportEvent(WORD type, LPCSTR message)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EVENTLOG_SUCCESS:
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_INFO, "%s", message);
|
||||
break;
|
||||
case EVENTLOG_ERROR_TYPE:
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_ERROR, "%s", message);
|
||||
break;
|
||||
case EVENTLOG_INFORMATION_TYPE:
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_INFO, "%s", message);
|
||||
break;
|
||||
case EVENTLOG_AUDIT_SUCCESS:
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_INFO, "%s", message);
|
||||
break;
|
||||
case EVENTLOG_AUDIT_FAILURE:
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_ERROR, "%s", message);
|
||||
break;
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
switch (type)
|
||||
{
|
||||
case EVENTLOG_SUCCESS:
|
||||
ATLTRACE("EVENTLOG_SUCCESS %s\n", message);
|
||||
break;
|
||||
case EVENTLOG_ERROR_TYPE:
|
||||
ATLTRACE("EVENTLOG_ERROR_TYPE %s\n", message);
|
||||
break;
|
||||
case EVENTLOG_INFORMATION_TYPE:
|
||||
ATLTRACE("EVENTLOG_INFORMATION_TYPE %s\n", message);
|
||||
break;
|
||||
case EVENTLOG_AUDIT_SUCCESS:
|
||||
ATLTRACE("EVENTLOG_AUDIT_SUCCESS %s\n", message);
|
||||
break;
|
||||
case EVENTLOG_AUDIT_FAILURE:
|
||||
ATLTRACE("EVENTLOG_AUDIT_FAILURE %s\n", message);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LogManager::ReportEvent(WORD type, LPCSTR message, LPCSTR fileName, int lineNumber)
|
||||
{
|
||||
// CString m;
|
||||
// m.Format(convert_s2w("%s\n%s(%d)"), message, fileName, lineNumber);
|
||||
// LogManager::ReportEvent(type, m);
|
||||
}
|
||||
|
||||
#ifdef _MFC_VER
|
||||
void LogManager::ReportEvent(WORD type, HRESULT hr, LPCSTR fileName, int lineNumber)
|
||||
{
|
||||
COleException e;
|
||||
e.m_sc = hr;
|
||||
TCHAR s[1024];
|
||||
e.GetErrorMessage(s, 1024);
|
||||
|
||||
CString m;
|
||||
m.Format("HRESULT = %d: %s\n%s(%d)", hr, s, fileName, lineNumber);
|
||||
LogManager::ReportEvent(type, m);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace log_detail
|
||||
{
|
||||
boost::once_flag once_init = BOOST_ONCE_INIT;
|
||||
static boost::thread_specific_ptr<ThreadLogManager>* ts;
|
||||
void init(void)
|
||||
{
|
||||
static boost::thread_specific_ptr<ThreadLogManager> value;
|
||||
ts = &value;
|
||||
}
|
||||
} // namespace log_detail
|
||||
|
||||
ThreadLogManager* ThreadLogManager::getCurrent()
|
||||
{
|
||||
boost::call_once(log_detail::init, log_detail::once_init);
|
||||
ThreadLogManager* logManager = log_detail::ts->get();
|
||||
if (!logManager)
|
||||
{
|
||||
logManager = new ThreadLogManager();
|
||||
log_detail::ts->reset(logManager);
|
||||
}
|
||||
return logManager;
|
||||
}
|
||||
|
||||
#endif
|
||||
157
client/common/CrashManager.hpp
Normal file
157
client/common/CrashManager.hpp
Normal file
@@ -0,0 +1,157 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
#include "intrusive_ptr_target.hpp"
|
||||
#include <Windows.h>
|
||||
#include <atlpath.h>
|
||||
#include "Log.hpp"
|
||||
#include "boost.hpp"
|
||||
#include "Utility/Exception.hpp"
|
||||
#include "CrashReporter.hpp"
|
||||
#include "boost/scoped_ptr.hpp"
|
||||
#include <vector>
|
||||
#include "threadsafe.hpp"
|
||||
|
||||
|
||||
|
||||
class LogManager
|
||||
{
|
||||
Aya::Log* log;
|
||||
static bool logsEnabled;
|
||||
|
||||
protected:
|
||||
const DWORD threadID;
|
||||
std::string name;
|
||||
static class MainLogManager* mainLogManager;
|
||||
|
||||
public:
|
||||
Aya::Log* getLog();
|
||||
|
||||
static MainLogManager* getMainLogManager();
|
||||
#ifdef _MFC_VER
|
||||
static HRESULT ReportCOMError(const CLSID& clsid, CException* exception);
|
||||
#endif
|
||||
static HRESULT ReportCOMError(const CLSID& clsid, HRESULT hRes);
|
||||
static HRESULT ReportCOMError(const CLSID& clsid, LPCOLESTR lpszDesc, HRESULT hRes = 0);
|
||||
static HRESULT ReportCOMError(const CLSID& clsid, LPCSTR lpszDesc, HRESULT hRes = 0);
|
||||
static HRESULT ReportExceptionAsCOMError(const CLSID& clsid, std::exception const& exp);
|
||||
static void ReportException(std::exception const& exp);
|
||||
static void ReportLastError(LPCSTR message);
|
||||
static void ReportEvent(WORD type, LPCSTR message);
|
||||
static void ReportEvent(WORD type, LPCSTR message, LPCSTR fileName, int lineNumber);
|
||||
static void ReportEvent(WORD type, HRESULT hr, LPCSTR fileName, int lineNumber);
|
||||
|
||||
const ATL::CPath& GetLogPath() const;
|
||||
const std::string GetLogPathString() const;
|
||||
|
||||
virtual ~LogManager();
|
||||
|
||||
virtual std::string getLogFileName() = 0;
|
||||
|
||||
protected:
|
||||
LogManager(const char* name)
|
||||
: log(NULL)
|
||||
, name(name)
|
||||
, threadID(GetCurrentThreadId()) {};
|
||||
};
|
||||
|
||||
|
||||
class RobloxCrashReporter : public CrashReporter
|
||||
{
|
||||
public:
|
||||
static bool silent;
|
||||
RobloxCrashReporter(const char* outputPath, const char* appName, const char* crashExtention);
|
||||
LONG ProcessException(struct _EXCEPTION_POINTERS* info, bool noMsg);
|
||||
|
||||
protected:
|
||||
/*override*/ void logEvent(const char* msg);
|
||||
};
|
||||
|
||||
class MainLogManager
|
||||
: public Aya::ILogProvider
|
||||
, public LogManager
|
||||
{
|
||||
boost::scoped_ptr<RobloxCrashReporter> crashReporter;
|
||||
std::vector<Aya::Log*> fastLogChannels;
|
||||
static Aya::mutex fastLogChannelsLock;
|
||||
const char* crashExtention;
|
||||
const char* crashEventExtention;
|
||||
|
||||
public:
|
||||
MainLogManager(LPCTSTR productName, const char* crashExtention, const char* crashEventExtention); // used for main thread
|
||||
~MainLogManager();
|
||||
|
||||
Aya::Log* provideLog();
|
||||
virtual std::string getLogFileName();
|
||||
std::string getFastLogFileName(FLog::Channel channelId);
|
||||
std::string MakeLogFileName(const char* postfix);
|
||||
|
||||
bool hasErrorLogs() const;
|
||||
|
||||
std::vector<std::string> gatherScriptCrashLogs();
|
||||
|
||||
void WriteCrashDump();
|
||||
|
||||
// triggers upload of log files on next start.
|
||||
bool CreateFakeCrashDump();
|
||||
|
||||
void NotifyFGThreadAlive(); // for deadlock reporting. call every second.
|
||||
void DisableHangReporting();
|
||||
|
||||
void EnableImmediateCrashUpload(bool enabled);
|
||||
|
||||
// returns HEX string that will be part of all the log/dumps output for this session.
|
||||
std::string getSessionId();
|
||||
|
||||
std::string getCrashEventName();
|
||||
|
||||
static void fastLogMessage(FLog::Channel id, const char* message);
|
||||
|
||||
enum GameState
|
||||
{
|
||||
UN_INITIALIZED = 0,
|
||||
IN_GAME,
|
||||
LEAVE_GAME
|
||||
};
|
||||
GameState getGameState()
|
||||
{
|
||||
return gameState;
|
||||
}
|
||||
void setGameLoaded()
|
||||
{
|
||||
gameState = GameState::IN_GAME;
|
||||
}
|
||||
void setLeaveGame()
|
||||
{
|
||||
gameState = GameState::LEAVE_GAME;
|
||||
};
|
||||
|
||||
private:
|
||||
GameState gameState;
|
||||
std::string guid;
|
||||
static bool handleDebugAssert(const char* expression, const char* filename, int lineNumber);
|
||||
static bool handleFailure(const char* expression, const char* filename, int lineNumber);
|
||||
|
||||
static bool handleG3DFailure(const char* _expression, const std::string& message, const char* filename, int lineNumber,
|
||||
/*bool& ignoreAlways,*/
|
||||
bool useGuiPrompt);
|
||||
|
||||
static bool handleG3DDebugAssert(const char* _expression, const std::string& message, const char* filename, int lineNumber,
|
||||
/*bool& ignoreAlways,*/
|
||||
bool useGuiPrompt);
|
||||
};
|
||||
|
||||
class ThreadLogManager : public LogManager
|
||||
{
|
||||
ThreadLogManager();
|
||||
|
||||
public:
|
||||
static ThreadLogManager* getCurrent();
|
||||
virtual ~ThreadLogManager();
|
||||
|
||||
protected:
|
||||
virtual std::string getLogFileName();
|
||||
};
|
||||
|
||||
#endif
|
||||
0
client/common/GfxView.cpp
Normal file
0
client/common/GfxView.cpp
Normal file
12
client/common/GfxView.hpp
Normal file
12
client/common/GfxView.hpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWindow>
|
||||
#include <QEvent>
|
||||
#include <QPoint>
|
||||
|
||||
class GfxView : public QWindow
|
||||
{
|
||||
private:
|
||||
QPoint lastMousePosition;
|
||||
QPoint lastMousePositionScaled;
|
||||
};
|
||||
87
client/common/GrayChatBar.cpp
Normal file
87
client/common/GrayChatBar.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "GrayChatBar.hpp"
|
||||
|
||||
#define PLACEHOLDER_TEXT "To chat click here or press the \"/\" key"
|
||||
|
||||
GrayChatBar::GrayChatBar(QWidget* parent) : QLineEdit(parent)
|
||||
{
|
||||
setText(PLACEHOLDER_TEXT);
|
||||
|
||||
// note: this uses segoe ui, may not work on linux?
|
||||
|
||||
// styles:
|
||||
// padding-left: 1px
|
||||
// border-bottom: 5px solid #404040
|
||||
// background-color: #404040 (#e6e6fa on active)
|
||||
// color: #ffffc8 (white on active)
|
||||
// font-weight: bold
|
||||
// font-family: 'Segoe UI'
|
||||
// fixed height: 21px
|
||||
|
||||
setStyleSheet("QLineEdit { background-color: #404040; color: #ffffc8; font-weight: bold; border-radius: 0 !important; padding: 0 !important; border: none; border-bottom: 5px solid #404040; margin: 0 !important; font-family: 'Segoe UI'; font-size: 12px; padding-left: 1px; }");
|
||||
setFixedHeight(21);
|
||||
setMinimumSize(QSize(0, 21));
|
||||
setVisible(false);
|
||||
|
||||
QFont font = this->font();
|
||||
font.setHintingPreference(QFont::PreferFullHinting); // for crappy aa
|
||||
setFont(font);
|
||||
}
|
||||
|
||||
void GrayChatBar::focus()
|
||||
{
|
||||
setFocus();
|
||||
}
|
||||
|
||||
void GrayChatBar::focusInEvent(QFocusEvent* e)
|
||||
{
|
||||
QLineEdit::focusInEvent(e);
|
||||
setStyleSheet("QLineEdit { background-color: #e6e6fa; color: black; font-weight: bold; border-radius: 0 !important; padding: 0 !important; border: none; border-bottom: 5px solid #404040; margin: 0 !important; font-family: 'Segoe UI'; font-size: 12px; padding-left: 1px; }");
|
||||
|
||||
if (text() == PLACEHOLDER_TEXT)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
void GrayChatBar::focusOutEvent(QFocusEvent* e)
|
||||
{
|
||||
QLineEdit::focusOutEvent(e);
|
||||
setStyleSheet("QLineEdit { background-color: #404040; color: #ffffc8; font-weight: bold; border-radius: 0 !important; padding: 0 !important; border: none; border-bottom: 5px solid #404040; margin: 0 !important; font-family: 'Segoe UI'; font-size: 12px; padding-left: 1px; }");
|
||||
|
||||
if (text() == "")
|
||||
{
|
||||
setText(PLACEHOLDER_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
void GrayChatBar::keyPressEvent(QKeyEvent* e)
|
||||
{
|
||||
if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter)
|
||||
{
|
||||
Q_EMIT returnPressed();
|
||||
handleEnteredText(text());
|
||||
setText(PLACEHOLDER_TEXT);
|
||||
clearFocus();
|
||||
}
|
||||
else
|
||||
{
|
||||
QLineEdit::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void GrayChatBar::handleEnteredText(const QString& txt) {
|
||||
Q_EMIT enteredText(txt);
|
||||
if (text() == "")
|
||||
{
|
||||
setText(PLACEHOLDER_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
void GrayChatBar::setVisibility(bool visible)
|
||||
{
|
||||
setVisible(visible);
|
||||
}
|
||||
|
||||
void GrayChatBar::mousePressEvent(QMouseEvent* e) {
|
||||
focus();
|
||||
}
|
||||
25
client/common/GrayChatBar.hpp
Normal file
25
client/common/GrayChatBar.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include <QLineEdit>
|
||||
#include <QVBoxLayout>
|
||||
#include <QKeyEvent>
|
||||
|
||||
class GrayChatBar : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GrayChatBar(QWidget* parent = nullptr);
|
||||
void focus();
|
||||
|
||||
protected:
|
||||
void focusInEvent(QFocusEvent* e) override;
|
||||
void focusOutEvent(QFocusEvent* e) override;
|
||||
void keyPressEvent(QKeyEvent* e) override;
|
||||
void mousePressEvent(QMouseEvent* e) override;
|
||||
void handleEnteredText(const QString& text);
|
||||
void setVisibility(bool visible);
|
||||
|
||||
Q_SIGNALS:
|
||||
void returnPressed();
|
||||
void enteredText(const QString& text);
|
||||
};
|
||||
668
client/common/SDLGameController.cpp
Normal file
668
client/common/SDLGameController.cpp
Normal file
@@ -0,0 +1,668 @@
|
||||
|
||||
#include "SDLGameController.hpp"
|
||||
|
||||
#include "DataModel/DataModel.hpp"
|
||||
#include "DataModel/GamepadService.hpp"
|
||||
#include "DataModel/UserInputService.hpp"
|
||||
#include "DataModel/ContentProvider.hpp"
|
||||
|
||||
#define MAX_AXIS_VALUE 32767.0f
|
||||
|
||||
SDLGameController::SDLGameController(shared_ptr<Aya::DataModel> newDM)
|
||||
{
|
||||
dataModel = newDM;
|
||||
initSDL();
|
||||
}
|
||||
|
||||
void SDLGameController::initSDL()
|
||||
{
|
||||
if (SDL_Init(SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC) != 0)
|
||||
{
|
||||
std::string error = SDL_GetError();
|
||||
fprintf(stderr, "\nUnable to initialize SDL: %s\n", error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
Aya::ContentId gameControllerDb = Aya::ContentId::fromAssets("fonts/gamecontrollerdb.txt");
|
||||
std::string filePath = Aya::ContentProvider::findAsset(gameControllerDb);
|
||||
|
||||
if (SDL_AddGamepadMappingsFromFile(filePath.c_str()) == -1)
|
||||
{
|
||||
std::string error = SDL_GetError();
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_ERROR, "Unable to add SDL controller mappings because %s", error.c_str());
|
||||
}
|
||||
|
||||
if (shared_ptr<Aya::DataModel> sharedDM = dataModel.lock())
|
||||
{
|
||||
sharedDM->submitTask(boost::bind(&SDLGameController::bindToDataModel, this), Aya::DataModelJob::Write);
|
||||
}
|
||||
}
|
||||
|
||||
void SDLGameController::bindToDataModel()
|
||||
{
|
||||
if (Aya::UserInputService* inputService = getUserInputService())
|
||||
{
|
||||
renderSteppedConnection = inputService->updateInputSignal.connect(boost::bind(&SDLGameController::updateControllers, this));
|
||||
getSupportedGamepadKeyCodesConnection =
|
||||
inputService->getSupportedGamepadKeyCodesSignal.connect(boost::bind(&SDLGameController::findAvailableGamepadKeyCodesAndSet, this, _1));
|
||||
}
|
||||
|
||||
if (Aya::HapticService* hapticService = getHapticService())
|
||||
{
|
||||
setEnabledVibrationMotorsConnection =
|
||||
hapticService->setEnabledVibrationMotorsSignal.connect(boost::bind(&SDLGameController::setVibrationMotorsEnabled, this, _1));
|
||||
setVibrationMotorConnection =
|
||||
hapticService->setVibrationMotorSignal.connect(boost::bind(&SDLGameController::setVibrationMotor, this, _1, _2, _3));
|
||||
}
|
||||
}
|
||||
|
||||
SDLGameController::~SDLGameController()
|
||||
{
|
||||
renderSteppedConnection.disconnect();
|
||||
getSupportedGamepadKeyCodesConnection.disconnect();
|
||||
|
||||
setEnabledVibrationMotorsConnection.disconnect();
|
||||
setVibrationMotorConnection.disconnect();
|
||||
|
||||
for (boost::unordered_map<int, HapticData>::iterator iter = hapticsFromGamepadId.begin(); iter != hapticsFromGamepadId.end(); ++iter)
|
||||
{
|
||||
SDL_Haptic* haptic = iter->second.hapticDevice;
|
||||
int hapticEffectId = iter->second.hapticEffectId;
|
||||
|
||||
SDL_HapticDestroyEffect(haptic, hapticEffectId);
|
||||
SDL_HapticClose(haptic);
|
||||
}
|
||||
hapticsFromGamepadId.clear();
|
||||
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
Aya::UserInputService* SDLGameController::getUserInputService()
|
||||
{
|
||||
if (shared_ptr<Aya::DataModel> sharedDM = dataModel.lock())
|
||||
{
|
||||
if (Aya::UserInputService* inputService = Aya::ServiceProvider::create<Aya::UserInputService>(sharedDM.get()))
|
||||
{
|
||||
return inputService;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Aya::HapticService* SDLGameController::getHapticService()
|
||||
{
|
||||
if (shared_ptr<Aya::DataModel> sharedDM = dataModel.lock())
|
||||
{
|
||||
if (Aya::HapticService* hapticService = Aya::ServiceProvider::create<Aya::HapticService>(sharedDM.get()))
|
||||
{
|
||||
return hapticService;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Aya::GamepadService* SDLGameController::getGamepadService()
|
||||
{
|
||||
if (shared_ptr<Aya::DataModel> sharedDM = dataModel.lock())
|
||||
{
|
||||
if (Aya::GamepadService* gamepadService = Aya::ServiceProvider::create<Aya::GamepadService>(sharedDM.get()))
|
||||
{
|
||||
return gamepadService;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_Gamepad* SDLGameController::removeControllerMapping(int joystickId)
|
||||
{
|
||||
SDL_Gamepad* gameController = NULL;
|
||||
Aya::UserInputService* inputService = getUserInputService();
|
||||
|
||||
if (joystickIdToGamepadId.find(joystickId) != joystickIdToGamepadId.end())
|
||||
{
|
||||
int gamepadId = joystickIdToGamepadId[joystickId];
|
||||
if (gamepadIdToGameController.find(gamepadId) != gamepadIdToGameController.end())
|
||||
{
|
||||
gameController = gamepadIdToGameController[gamepadId].second;
|
||||
gamepadIdToGameController.erase(gamepadId);
|
||||
|
||||
if (inputService)
|
||||
{
|
||||
inputService->safeFireGamepadDisconnected(Aya::GamepadService::getGamepadEnumForInt(gamepadId));
|
||||
}
|
||||
}
|
||||
|
||||
if (hapticsFromGamepadId.find(gamepadId) != hapticsFromGamepadId.end())
|
||||
{
|
||||
SDL_Haptic* haptic = hapticsFromGamepadId[gamepadId].hapticDevice;
|
||||
int hapticEffectId = hapticsFromGamepadId[gamepadId].hapticEffectId;
|
||||
|
||||
SDL_HapticDestroyEffect(haptic, hapticEffectId);
|
||||
SDL_HapticClose(haptic);
|
||||
|
||||
hapticsFromGamepadId.erase(gamepadId);
|
||||
}
|
||||
}
|
||||
|
||||
return gameController;
|
||||
}
|
||||
|
||||
void SDLGameController::setupControllerId(int joystickId, int gamepadId, SDL_Gamepad* pad)
|
||||
{
|
||||
gamepadIdToGameController[gamepadId] = std::pair<int, SDL_Gamepad*>(joystickId, pad);
|
||||
joystickIdToGamepadId[joystickId] = gamepadId;
|
||||
|
||||
if (Aya::UserInputService* inputService = getUserInputService())
|
||||
{
|
||||
inputService->safeFireGamepadConnected(Aya::GamepadService::getGamepadEnumForInt(gamepadId));
|
||||
}
|
||||
}
|
||||
|
||||
void SDLGameController::addController(int gamepadId)
|
||||
{
|
||||
if (SDL_IsGamepad(gamepadId))
|
||||
{
|
||||
SDL_Gamepad* pad = SDL_OpenGamepad(gamepadId);
|
||||
|
||||
if (pad)
|
||||
{
|
||||
SDL_Joystick* joy = SDL_GetGamepadJoystick(pad);
|
||||
int joystickId = SDL_GetJoystickID(joy);
|
||||
|
||||
setupControllerId(joystickId, gamepadId, pad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDLGameController::removeController(int joystickId)
|
||||
{
|
||||
if (SDL_Gamepad* pad = removeControllerMapping(joystickId))
|
||||
{
|
||||
SDL_CloseGamepad(pad);
|
||||
}
|
||||
}
|
||||
|
||||
Aya::Gamepad SDLGameController::getRbxGamepadFromJoystickId(int joystickId)
|
||||
{
|
||||
if (joystickIdToGamepadId.find(joystickId) != joystickIdToGamepadId.end())
|
||||
{
|
||||
if (Aya::GamepadService* gamepadService = getGamepadService())
|
||||
{
|
||||
int gamepadId = joystickIdToGamepadId[joystickId];
|
||||
return gamepadService->getGamepadState(gamepadId);
|
||||
}
|
||||
}
|
||||
|
||||
return Aya::Gamepad();
|
||||
}
|
||||
|
||||
Aya::KeyCode getKeyCodeFromSDLAxis(SDL_GamepadAxis sdlAxis, int& axisValueChanged)
|
||||
{
|
||||
switch (sdlAxis)
|
||||
{
|
||||
case SDL_GAMEPAD_AXIS_LEFTX:
|
||||
axisValueChanged = 0;
|
||||
return Aya::SDLK_GAMEPAD_THUMBSTICK1;
|
||||
case SDL_GAMEPAD_AXIS_LEFTY:
|
||||
axisValueChanged = 1;
|
||||
return Aya::SDLK_GAMEPAD_THUMBSTICK1;
|
||||
case SDL_GAMEPAD_AXIS_RIGHTX:
|
||||
axisValueChanged = 0;
|
||||
return Aya::SDLK_GAMEPAD_THUMBSTICK2;
|
||||
case SDL_GAMEPAD_AXIS_RIGHTY:
|
||||
axisValueChanged = 1;
|
||||
return Aya::SDLK_GAMEPAD_THUMBSTICK2;
|
||||
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER:
|
||||
axisValueChanged = 2;
|
||||
return Aya::SDLK_GAMEPAD_BUTTONL2;
|
||||
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER:
|
||||
axisValueChanged = 2;
|
||||
return Aya::SDLK_GAMEPAD_BUTTONR2;
|
||||
case SDL_GAMEPAD_AXIS_INVALID:
|
||||
case SDL_GAMEPAD_AXIS_MAX:
|
||||
return Aya::SDLK_UNKNOWN;
|
||||
}
|
||||
|
||||
return Aya::SDLK_UNKNOWN;
|
||||
}
|
||||
|
||||
Aya::KeyCode getKeyCodeFromSDLButton(SDL_GamepadButton sdlButton)
|
||||
{
|
||||
switch (sdlButton)
|
||||
{
|
||||
case SDL_GAMEPAD_BUTTON_SOUTH:
|
||||
return Aya::SDLK_GAMEPAD_BUTTONA;
|
||||
case SDL_GAMEPAD_BUTTON_EAST:
|
||||
return Aya::SDLK_GAMEPAD_BUTTONB;
|
||||
case SDL_GAMEPAD_BUTTON_WEST:
|
||||
return Aya::SDLK_GAMEPAD_BUTTONX;
|
||||
case SDL_GAMEPAD_BUTTON_NORTH:
|
||||
return Aya::SDLK_GAMEPAD_BUTTONY;
|
||||
|
||||
case SDL_GAMEPAD_BUTTON_START:
|
||||
return Aya::SDLK_GAMEPAD_BUTTONSTART;
|
||||
case SDL_GAMEPAD_BUTTON_BACK:
|
||||
return Aya::SDLK_GAMEPAD_BUTTONSELECT;
|
||||
|
||||
case SDL_GAMEPAD_BUTTON_DPAD_UP:
|
||||
return Aya::SDLK_GAMEPAD_DPADUP;
|
||||
case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
|
||||
return Aya::SDLK_GAMEPAD_DPADDOWN;
|
||||
case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
|
||||
return Aya::SDLK_GAMEPAD_DPADLEFT;
|
||||
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
|
||||
return Aya::SDLK_GAMEPAD_DPADRIGHT;
|
||||
|
||||
case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER:
|
||||
return Aya::SDLK_GAMEPAD_BUTTONL1;
|
||||
case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER:
|
||||
return Aya::SDLK_GAMEPAD_BUTTONR1;
|
||||
|
||||
case SDL_GAMEPAD_BUTTON_LEFT_STICK:
|
||||
return Aya::SDLK_GAMEPAD_BUTTONL3;
|
||||
case SDL_GAMEPAD_BUTTON_RIGHT_STICK:
|
||||
return Aya::SDLK_GAMEPAD_BUTTONR3;
|
||||
|
||||
case SDL_GAMEPAD_BUTTON_INVALID:
|
||||
case SDL_GAMEPAD_BUTTON_GUIDE:
|
||||
case SDL_GAMEPAD_BUTTON_MAX:
|
||||
return Aya::SDLK_UNKNOWN;
|
||||
}
|
||||
|
||||
return Aya::SDLK_UNKNOWN;
|
||||
}
|
||||
|
||||
bool SDLGameController::setupHapticsForDevice(int id)
|
||||
{
|
||||
// already set up
|
||||
if (hapticsFromGamepadId.find(id) != hapticsFromGamepadId.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
SDL_Haptic* haptic = NULL;
|
||||
|
||||
// Open the device
|
||||
haptic = SDL_HapticOpen(id);
|
||||
if (haptic)
|
||||
{
|
||||
HapticData hapticData;
|
||||
hapticData.hapticDevice = haptic;
|
||||
hapticData.hapticEffectId = -1;
|
||||
hapticData.currentLeftMotorValue = 0.0f;
|
||||
hapticData.currentRightMotorValue = 0.0f;
|
||||
|
||||
hapticsFromGamepadId[id] = hapticData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SDLGameController::setVibrationMotorsEnabled(Aya::InputObject::UserInputType gamepadType)
|
||||
{
|
||||
int gamepadId = getGamepadIntForEnum(gamepadType);
|
||||
if (!setupHapticsForDevice(gamepadId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Haptic* haptic = hapticsFromGamepadId[gamepadId].hapticDevice;
|
||||
if (haptic)
|
||||
{
|
||||
if (Aya::HapticService* hapticService = getHapticService())
|
||||
{
|
||||
hapticService->setEnabledVibrationMotors(gamepadType, Aya::HapticService::MOTOR_LARGE, true);
|
||||
hapticService->setEnabledVibrationMotors(gamepadType, Aya::HapticService::MOTOR_SMALL, true);
|
||||
hapticService->setEnabledVibrationMotors(gamepadType, Aya::HapticService::MOTOR_LEFTTRIGGER, false);
|
||||
hapticService->setEnabledVibrationMotors(gamepadType, Aya::HapticService::MOTOR_RIGHTTRIGGER, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDLGameController::setVibrationMotor(
|
||||
Aya::InputObject::UserInputType gamepadType, Aya::HapticService::VibrationMotor vibrationMotor, shared_ptr<const Aya::Reflection::Tuple> args)
|
||||
{
|
||||
int gamepadId = getGamepadIntForEnum(gamepadType);
|
||||
if (!setupHapticsForDevice(gamepadId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float newMotorValue = 0.0f;
|
||||
Aya::Reflection::Variant newValue = args->values[0];
|
||||
if (newValue.isFloat())
|
||||
{
|
||||
newMotorValue = newValue.get<float>();
|
||||
newMotorValue = G3D::clamp(newMotorValue, 0.0f, 1.0f);
|
||||
}
|
||||
else // no valid number in first position, lets bail
|
||||
{
|
||||
Aya::StandardOut::singleton()->printf(
|
||||
Aya::MESSAGE_ERROR, "First value to HapticService:SetMotor is not a valid number (must be a number between 0-1)");
|
||||
return;
|
||||
}
|
||||
|
||||
boost::unordered_map<int, HapticData>::iterator iter = hapticsFromGamepadId.find(gamepadId);
|
||||
|
||||
// make sure we grab old data so we set the motors that haven't changed value
|
||||
float leftMotorValue = iter->second.currentLeftMotorValue;
|
||||
float rightMotorValue = iter->second.currentRightMotorValue;
|
||||
|
||||
if (vibrationMotor == Aya::HapticService::MOTOR_LARGE)
|
||||
{
|
||||
leftMotorValue = newMotorValue;
|
||||
}
|
||||
else if (vibrationMotor == Aya::HapticService::MOTOR_SMALL)
|
||||
{
|
||||
rightMotorValue = newMotorValue;
|
||||
}
|
||||
|
||||
SDL_Haptic* haptic = iter->second.hapticDevice;
|
||||
int oldEffectId = iter->second.hapticEffectId;
|
||||
if (oldEffectId >= 0)
|
||||
{
|
||||
SDL_HapticDestroyEffect(haptic, oldEffectId);
|
||||
}
|
||||
|
||||
if (leftMotorValue <= 0.0f && rightMotorValue <= 0.0f)
|
||||
{
|
||||
HapticData hapticData;
|
||||
hapticData.hapticDevice = haptic;
|
||||
hapticData.hapticEffectId = -1;
|
||||
hapticData.currentLeftMotorValue = 0.0f;
|
||||
hapticData.currentRightMotorValue = 0.0f;
|
||||
|
||||
hapticsFromGamepadId[gamepadId] = hapticData;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the left/right effect
|
||||
SDL_HapticEffect effect;
|
||||
memset(&effect, 0, sizeof(SDL_HapticEffect)); // 0 is safe default
|
||||
effect.type = SDL_HAPTIC_LEFTRIGHT;
|
||||
effect.leftright.large_magnitude = 65535.0f * leftMotorValue;
|
||||
effect.leftright.small_magnitude = 65535.0f * rightMotorValue;
|
||||
effect.leftright.length = SDL_HAPTIC_INFINITY;
|
||||
|
||||
// Upload the effect
|
||||
int hapticEffectId = SDL_HapticNewEffect(haptic, &effect);
|
||||
|
||||
HapticData hapticData;
|
||||
hapticData.hapticDevice = haptic;
|
||||
hapticData.hapticEffectId = hapticEffectId;
|
||||
hapticData.currentLeftMotorValue = leftMotorValue;
|
||||
hapticData.currentRightMotorValue = rightMotorValue;
|
||||
|
||||
hapticsFromGamepadId[gamepadId] = hapticData;
|
||||
|
||||
if (haptic && hapticEffectId >= 0)
|
||||
{
|
||||
SDL_HapticRunEffect(haptic, hapticEffectId, SDL_HAPTIC_INFINITY);
|
||||
}
|
||||
}
|
||||
|
||||
void SDLGameController::refreshHapticEffects()
|
||||
{
|
||||
for (boost::unordered_map<int, HapticData>::iterator iter = hapticsFromGamepadId.begin(); iter != hapticsFromGamepadId.end(); ++iter)
|
||||
{
|
||||
SDL_Haptic* haptic = iter->second.hapticDevice;
|
||||
int hapticEffectId = iter->second.hapticEffectId;
|
||||
|
||||
if (haptic && hapticEffectId >= 0)
|
||||
{
|
||||
SDL_HapticRunEffect(haptic, hapticEffectId, SDL_HAPTIC_INFINITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDLGameController::onControllerButton(const SDL_GamepadButtonEvent sdlEvent)
|
||||
{
|
||||
const Aya::KeyCode buttonCode = getKeyCodeFromSDLButton((SDL_GamepadButton)sdlEvent.button);
|
||||
|
||||
if (buttonCode == Aya::SDLK_UNKNOWN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Aya::Gamepad gamepad = getRbxGamepadFromJoystickId(sdlEvent.which);
|
||||
const int buttonState = (sdlEvent.state == SDL_PRESSED) ? 1 : 0;
|
||||
Aya::InputObject::UserInputState newState = (buttonState == 1) ? Aya::InputObject::INPUT_STATE_BEGIN : Aya::InputObject::INPUT_STATE_END;
|
||||
|
||||
if (newState == gamepad[buttonCode]->getUserInputState())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const G3D::Vector3 lastPos = gamepad[buttonCode]->getPosition();
|
||||
|
||||
gamepad[buttonCode]->setPosition(G3D::Vector3(0, 0, buttonState));
|
||||
gamepad[buttonCode]->setDelta(gamepad[buttonCode]->getPosition() - lastPos);
|
||||
gamepad[buttonCode]->setInputState(newState);
|
||||
|
||||
if (Aya::UserInputService* inputService = getUserInputService())
|
||||
{
|
||||
inputService->dangerousFireInputEvent(gamepad[buttonCode], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void SDLGameController::onControllerAxis(const SDL_GamepadAxisEvent sdlEvent)
|
||||
{
|
||||
int axisValueChanged = -1;
|
||||
const Aya::KeyCode axisCode = getKeyCodeFromSDLAxis((SDL_GamepadAxis)sdlEvent.axis, axisValueChanged);
|
||||
|
||||
if (axisCode == Aya::SDLK_UNKNOWN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float axisValue = sdlEvent.value;
|
||||
axisValue /= MAX_AXIS_VALUE;
|
||||
axisValue = G3D::clamp(axisValue, -1.0f, 1.0f);
|
||||
|
||||
Aya::Gamepad gamepad = getRbxGamepadFromJoystickId(sdlEvent.which);
|
||||
G3D::Vector3 currentPosition = gamepad[axisCode]->getPosition();
|
||||
|
||||
switch (axisValueChanged)
|
||||
{
|
||||
case 0:
|
||||
currentPosition.x = axisValue;
|
||||
break;
|
||||
case 1:
|
||||
currentPosition.y = -axisValue;
|
||||
break;
|
||||
case 2:
|
||||
currentPosition.z = axisValue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
G3D::Vector3 lastPos = gamepad[axisCode]->getPosition();
|
||||
if (lastPos != currentPosition)
|
||||
{
|
||||
gamepad[axisCode]->setPosition(currentPosition);
|
||||
|
||||
Aya::InputObject::UserInputState currentState = Aya::InputObject::INPUT_STATE_CHANGE;
|
||||
if (currentPosition == G3D::Vector3::zero())
|
||||
{
|
||||
currentState = Aya::InputObject::INPUT_STATE_END;
|
||||
}
|
||||
else if (currentPosition.z >= 1.0f)
|
||||
{
|
||||
currentState = Aya::InputObject::INPUT_STATE_BEGIN;
|
||||
}
|
||||
|
||||
gamepad[axisCode]->setDelta(currentPosition - lastPos);
|
||||
gamepad[axisCode]->setInputState(currentState);
|
||||
|
||||
if (Aya::UserInputService* inputService = getUserInputService())
|
||||
{
|
||||
inputService->dangerousFireInputEvent(gamepad[axisCode], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDLGameController::updateControllers()
|
||||
{
|
||||
SDL_Event sdlEvent;
|
||||
|
||||
while (SDL_PollEvent(&sdlEvent))
|
||||
{
|
||||
switch (sdlEvent.type)
|
||||
{
|
||||
case SDL_EVENT_GAMEPAD_ADDED:
|
||||
addController(sdlEvent.gdevice.which);
|
||||
break;
|
||||
|
||||
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||
removeController(sdlEvent.gdevice.which);
|
||||
break;
|
||||
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
onControllerButton(sdlEvent.gbutton);
|
||||
break;
|
||||
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
onControllerAxis(sdlEvent.gaxis);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
refreshHapticEffects();
|
||||
}
|
||||
|
||||
Aya::KeyCode getKeyCodeFromSDLName(std::string sdlName)
|
||||
{
|
||||
if (sdlName.compare("a") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONA;
|
||||
if (sdlName.compare("b") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONB;
|
||||
if (sdlName.compare("x") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONX;
|
||||
if (sdlName.compare("y") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONY;
|
||||
|
||||
if (sdlName.compare("back") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONSELECT;
|
||||
if (sdlName.compare("start") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONSTART;
|
||||
|
||||
if (sdlName.compare("dpdown") == 0)
|
||||
return Aya::SDLK_GAMEPAD_DPADDOWN;
|
||||
if (sdlName.compare("dpleft") == 0)
|
||||
return Aya::SDLK_GAMEPAD_DPADLEFT;
|
||||
if (sdlName.compare("dpright") == 0)
|
||||
return Aya::SDLK_GAMEPAD_DPADRIGHT;
|
||||
if (sdlName.compare("dpup") == 0)
|
||||
return Aya::SDLK_GAMEPAD_DPADUP;
|
||||
|
||||
if (sdlName.compare("leftshoulder") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONL1;
|
||||
if (sdlName.compare("lefttrigger") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONL2;
|
||||
if (sdlName.compare("leftstick") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONL3;
|
||||
|
||||
if (sdlName.compare("rightshoulder") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONR1;
|
||||
if (sdlName.compare("righttrigger") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONR2;
|
||||
if (sdlName.compare("rightstick") == 0)
|
||||
return Aya::SDLK_GAMEPAD_BUTTONR3;
|
||||
|
||||
if (sdlName.compare("leftx") == 0 || sdlName.compare("lefty") == 0)
|
||||
return Aya::SDLK_GAMEPAD_THUMBSTICK1;
|
||||
|
||||
if (sdlName.compare("rightx") == 0 || sdlName.compare("righty") == 0)
|
||||
return Aya::SDLK_GAMEPAD_THUMBSTICK2;
|
||||
|
||||
return Aya::SDLK_UNKNOWN;
|
||||
}
|
||||
|
||||
int SDLGameController::getGamepadIntForEnum(Aya::InputObject::UserInputType gamepadType)
|
||||
{
|
||||
switch (gamepadType)
|
||||
{
|
||||
case Aya::InputObject::TYPE_GAMEPAD1:
|
||||
return 0;
|
||||
case Aya::InputObject::TYPE_GAMEPAD2:
|
||||
return 1;
|
||||
case Aya::InputObject::TYPE_GAMEPAD3:
|
||||
return 2;
|
||||
case Aya::InputObject::TYPE_GAMEPAD4:
|
||||
return 3;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SDLGameController::findAvailableGamepadKeyCodesAndSet(Aya::InputObject::UserInputType gamepadType)
|
||||
{
|
||||
shared_ptr<const Aya::Reflection::ValueArray> availableGamepadKeyCodes = getAvailableGamepadKeyCodes(gamepadType);
|
||||
if (Aya::UserInputService* inputService = getUserInputService())
|
||||
{
|
||||
inputService->setSupportedGamepadKeyCodes(gamepadType, availableGamepadKeyCodes);
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<const Aya::Reflection::ValueArray> SDLGameController::getAvailableGamepadKeyCodes(Aya::InputObject::UserInputType gamepadType)
|
||||
{
|
||||
int gamepadId = getGamepadIntForEnum(gamepadType);
|
||||
|
||||
if (gamepadId < 0 || (gamepadIdToGameController.find(gamepadId) == gamepadIdToGameController.end()))
|
||||
{
|
||||
return shared_ptr<const Aya::Reflection::ValueArray>();
|
||||
}
|
||||
|
||||
if (SDL_Gamepad* gameController = gamepadIdToGameController[gamepadId].second)
|
||||
{
|
||||
char* mappingStr = SDL_GetGamepadMapping(gameController);
|
||||
std::string gameControllerMapping(mappingStr ? mappingStr : "");
|
||||
if (mappingStr) SDL_free(mappingStr);
|
||||
|
||||
std::istringstream controllerMappingStream(gameControllerMapping);
|
||||
std::string mappingItem;
|
||||
|
||||
shared_ptr<Aya::Reflection::ValueArray> supportedGamepadFunctions(new Aya::Reflection::ValueArray());
|
||||
|
||||
int count = 0;
|
||||
while (std::getline(controllerMappingStream, mappingItem, ','))
|
||||
{
|
||||
// first two settings in mapping are hardware id and device name, don't need those
|
||||
if (count > 1)
|
||||
{
|
||||
std::istringstream mappingStream(mappingItem);
|
||||
std::string sdlName;
|
||||
std::getline(mappingStream, sdlName, ':');
|
||||
|
||||
// platform is always last thing defined in mappings, don't need it so we are done
|
||||
if (sdlName.compare("platform") == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Aya::KeyCode gamepadCode = getKeyCodeFromSDLName(sdlName);
|
||||
if (gamepadCode != Aya::SDLK_UNKNOWN)
|
||||
{
|
||||
supportedGamepadFunctions->push_back(gamepadCode);
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
return supportedGamepadFunctions;
|
||||
}
|
||||
|
||||
return shared_ptr<const Aya::Reflection::ValueArray>();
|
||||
}
|
||||
82
client/common/SDLGameController.hpp
Normal file
82
client/common/SDLGameController.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
|
||||
#include "SDL3/SDL.h"
|
||||
#include "SDL3/SDL_gamepad.h"
|
||||
|
||||
#include "Utility/KeyCode.hpp"
|
||||
#include "DataModel/InputObject.hpp"
|
||||
#include "DataModel/HapticService.hpp"
|
||||
|
||||
namespace Aya
|
||||
{
|
||||
class DataModel;
|
||||
class UserInputService;
|
||||
|
||||
class GamepadService;
|
||||
|
||||
typedef boost::unordered_map<Aya::KeyCode, boost::shared_ptr<Aya::InputObject>> Gamepad;
|
||||
} // namespace Aya
|
||||
|
||||
struct HapticData
|
||||
{
|
||||
int hapticEffectId;
|
||||
float currentLeftMotorValue;
|
||||
float currentRightMotorValue;
|
||||
SDL_Haptic* hapticDevice;
|
||||
};
|
||||
|
||||
class SDLGameController
|
||||
{
|
||||
private:
|
||||
boost::weak_ptr<Aya::DataModel> dataModel;
|
||||
boost::unordered_map<int, std::pair<int, SDL_Gamepad*>> gamepadIdToGameController;
|
||||
boost::unordered_map<int, HapticData> hapticsFromGamepadId;
|
||||
boost::unordered_map<int, int> joystickIdToGamepadId;
|
||||
|
||||
Aya::signals::scoped_connection renderSteppedConnection;
|
||||
Aya::signals::scoped_connection getSupportedGamepadKeyCodesConnection;
|
||||
|
||||
Aya::signals::scoped_connection setEnabledVibrationMotorsConnection;
|
||||
Aya::signals::scoped_connection setVibrationMotorConnection;
|
||||
|
||||
void initSDL();
|
||||
|
||||
Aya::UserInputService* getUserInputService();
|
||||
Aya::HapticService* getHapticService();
|
||||
|
||||
Aya::GamepadService* getGamepadService();
|
||||
Aya::Gamepad getRbxGamepadFromJoystickId(int joystickId);
|
||||
|
||||
void setupControllerId(int joystickId, int gamepadId, SDL_Gamepad* pad);
|
||||
SDL_Gamepad* removeControllerMapping(int joystickId);
|
||||
|
||||
int getGamepadIntForEnum(Aya::InputObject::UserInputType gamepadType);
|
||||
|
||||
void findAvailableGamepadKeyCodesAndSet(Aya::InputObject::UserInputType gamepadType);
|
||||
boost::shared_ptr<const Aya::Reflection::ValueArray> getAvailableGamepadKeyCodes(Aya::InputObject::UserInputType gamepadType);
|
||||
|
||||
void bindToDataModel();
|
||||
|
||||
// Haptic Functions
|
||||
void refreshHapticEffects();
|
||||
bool setupHapticsForDevice(int id);
|
||||
|
||||
void setVibrationMotorsEnabled(Aya::InputObject::UserInputType gamepadType);
|
||||
void setVibrationMotor(Aya::InputObject::UserInputType gamepadType, Aya::HapticService::VibrationMotor vibrationMotor,
|
||||
shared_ptr<const Aya::Reflection::Tuple> args);
|
||||
|
||||
public:
|
||||
SDLGameController(boost::shared_ptr<Aya::DataModel> newDM);
|
||||
~SDLGameController();
|
||||
|
||||
void updateControllers();
|
||||
|
||||
void onControllerAxis(const SDL_GamepadAxisEvent sdlEvent);
|
||||
void onControllerButton(const SDL_GamepadButtonEvent sdlEvent);
|
||||
void removeController(int joystickId);
|
||||
void addController(int gamepadId);
|
||||
};
|
||||
40
client/common/content/ChromiumFrame.html
Normal file
40
client/common/content/ChromiumFrame.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>ChromiumFrame Initialized</title>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "Source Sans Pro";
|
||||
font-style: normal;
|
||||
font-weight: 200 900;
|
||||
src: url("./fonts/SourceSansPro-Regular.ttf") format("ttf");
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
background-color: #111;
|
||||
color: #fff;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<p><img src="./textures/Aya.png" width="150" /></p>
|
||||
<h1>ChromiumFrame Initialized</h1>
|
||||
<p>Reference the Lua API for instructions on how to use ChromiumFrames.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
1305
client/common/content/FastFlags.json
Normal file
1305
client/common/content/FastFlags.json
Normal file
File diff suppressed because it is too large
Load Diff
8505
client/common/content/ReflectionMetadata.xml
Normal file
8505
client/common/content/ReflectionMetadata.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
client/common/content/avatar/animations/climb.rbxm
Normal file
BIN
client/common/content/avatar/animations/climb.rbxm
Normal file
Binary file not shown.
3115
client/common/content/avatar/animations/emotes/cheer.rbxm
Normal file
3115
client/common/content/avatar/animations/emotes/cheer.rbxm
Normal file
File diff suppressed because it is too large
Load Diff
BIN
client/common/content/avatar/animations/emotes/dance1_0.rbxm
Normal file
BIN
client/common/content/avatar/animations/emotes/dance1_0.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/animations/emotes/dance1_1.rbxm
Normal file
BIN
client/common/content/avatar/animations/emotes/dance1_1.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/animations/emotes/dance1_2.rbxm
Normal file
BIN
client/common/content/avatar/animations/emotes/dance1_2.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/animations/emotes/dance2_0.rbxm
Normal file
BIN
client/common/content/avatar/animations/emotes/dance2_0.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/animations/emotes/dance2_1.rbxm
Normal file
BIN
client/common/content/avatar/animations/emotes/dance2_1.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/animations/emotes/dance2_2.rbxm
Normal file
BIN
client/common/content/avatar/animations/emotes/dance2_2.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/animations/emotes/dance3_0.rbxm
Normal file
BIN
client/common/content/avatar/animations/emotes/dance3_0.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/animations/emotes/dance3_1.rbxm
Normal file
BIN
client/common/content/avatar/animations/emotes/dance3_1.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/animations/emotes/dance3_2.rbxm
Normal file
BIN
client/common/content/avatar/animations/emotes/dance3_2.rbxm
Normal file
Binary file not shown.
3309
client/common/content/avatar/animations/emotes/laugh.rbxm
Normal file
3309
client/common/content/avatar/animations/emotes/laugh.rbxm
Normal file
File diff suppressed because it is too large
Load Diff
3309
client/common/content/avatar/animations/emotes/point.rbxm
Normal file
3309
client/common/content/avatar/animations/emotes/point.rbxm
Normal file
File diff suppressed because it is too large
Load Diff
4570
client/common/content/avatar/animations/emotes/wave.rbxm
Normal file
4570
client/common/content/avatar/animations/emotes/wave.rbxm
Normal file
File diff suppressed because it is too large
Load Diff
BIN
client/common/content/avatar/animations/fall.rbxm
Normal file
BIN
client/common/content/avatar/animations/fall.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/animations/idle0.rbxm
Normal file
BIN
client/common/content/avatar/animations/idle0.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/animations/idle1.rbxm
Normal file
BIN
client/common/content/avatar/animations/idle1.rbxm
Normal file
Binary file not shown.
1854
client/common/content/avatar/animations/jump.rbxm
Normal file
1854
client/common/content/avatar/animations/jump.rbxm
Normal file
File diff suppressed because it is too large
Load Diff
BIN
client/common/content/avatar/animations/sit.rbxm
Normal file
BIN
client/common/content/avatar/animations/sit.rbxm
Normal file
Binary file not shown.
323
client/common/content/avatar/animations/toollunge.rbxm
Normal file
323
client/common/content/avatar/animations/toollunge.rbxm
Normal file
@@ -0,0 +1,323 @@
|
||||
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="4" assettype="animation">
|
||||
<External>null</External>
|
||||
<External>nil</External>
|
||||
<Item class="KeyframeSequence" referent="RBX0">
|
||||
<Properties>
|
||||
<bool name="Loop">false</bool>
|
||||
<string name="Name">Test</string>
|
||||
<token name="Priority">0</token>
|
||||
</Properties>
|
||||
<Item class="Keyframe" referent="RBX1">
|
||||
<Properties>
|
||||
<string name="Name">Keyframe</string>
|
||||
<float name="Time">0</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX2">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">HumanoidRootPart</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX3">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.999999881</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Torso</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX4">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>5.96046448e-008</X>
|
||||
<Y>-2.98023224e-008</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.0355361402</R00>
|
||||
<R01>-0.99936831</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.99936831</R10>
|
||||
<R11>0.0355361402</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Left Leg</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Pose" referent="RBX5">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.819770932</R00>
|
||||
<R01>-0.57269156</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.57269156</R10>
|
||||
<R11>0.819770932</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Right Leg</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Pose" referent="RBX6">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>-2.98023224e-008</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.815004945</R00>
|
||||
<R01>-0.579453945</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.579453945</R10>
|
||||
<R11>0.815004945</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Left Arm</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Pose" referent="RBX7">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>2.56113708e-008</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.00526433345</R00>
|
||||
<R01>-0.999986172</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.999986172</R10>
|
||||
<R11>0.00526433345</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Right Arm</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Pose" referent="RBX8">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.999999881</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Head</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="Keyframe" referent="RBX9">
|
||||
<Properties>
|
||||
<string name="Name">Keyframe</string>
|
||||
<float name="Time">1.49062502</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX10">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">HumanoidRootPart</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX11">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.999999881</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Torso</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX12">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>5.96046448e-008</X>
|
||||
<Y>-2.98023224e-008</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.0355361402</R00>
|
||||
<R01>-0.99936831</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.99936831</R10>
|
||||
<R11>0.0355361402</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Left Leg</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Pose" referent="RBX13">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.819770932</R00>
|
||||
<R01>-0.57269156</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.57269156</R10>
|
||||
<R11>0.819770932</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Right Leg</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Pose" referent="RBX14">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>-2.98023224e-008</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.815004945</R00>
|
||||
<R01>-0.579453945</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.579453945</R10>
|
||||
<R11>0.815004945</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Left Arm</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Pose" referent="RBX15">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>2.56113708e-008</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.00526433345</R00>
|
||||
<R01>-0.999986172</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.999986172</R10>
|
||||
<R11>0.00526433345</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Right Arm</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Pose" referent="RBX16">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.999999881</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Head</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="Keyframe" referent="RBX17">
|
||||
<Properties>
|
||||
<string name="Name">KF1.5</string>
|
||||
<float name="Time">1.5</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</roblox>
|
||||
BIN
client/common/content/avatar/animations/toolnone.rbxm
Normal file
BIN
client/common/content/avatar/animations/toolnone.rbxm
Normal file
Binary file not shown.
203
client/common/content/avatar/animations/toolslash.rbxm
Normal file
203
client/common/content/avatar/animations/toolslash.rbxm
Normal file
@@ -0,0 +1,203 @@
|
||||
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="4" assettype="animation">
|
||||
<External>null</External>
|
||||
<External>nil</External>
|
||||
<Item class="KeyframeSequence" referent="RBX0">
|
||||
<Properties>
|
||||
<bool name="Loop">false</bool>
|
||||
<string name="Name">Test</string>
|
||||
<token name="Priority">0</token>
|
||||
</Properties>
|
||||
<Item class="Keyframe" referent="RBX1">
|
||||
<Properties>
|
||||
<string name="Name">Keyframe</string>
|
||||
<float name="Time">0</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX3">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Torso</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX4">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>1.86264515e-009</Y>
|
||||
<Z>0</Z>
|
||||
<R00>-0.0374366008</R00>
|
||||
<R01>-0.99929899</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.99929899</R10>
|
||||
<R11>-0.0374366008</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Right Arm</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="Keyframe" referent="RBX5">
|
||||
<Properties>
|
||||
<string name="Name">Keyframe</string>
|
||||
<float name="Time">0.200000003</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX6">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Torso</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX7">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>3.25962901e-009</X>
|
||||
<Y>-5.96046448e-008</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.999995768</R00>
|
||||
<R01>-0.00290136319</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.00290136319</R10>
|
||||
<R11>0.999995768</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Right Arm</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="Keyframe" referent="RBX8">
|
||||
<Properties>
|
||||
<string name="Name">Keyframe</string>
|
||||
<float name="Time">0.300000012</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX9">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Torso</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX10">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>3.25962901e-009</X>
|
||||
<Y>-5.96046448e-008</Y>
|
||||
<Z>0</Z>
|
||||
<R00>0.999995768</R00>
|
||||
<R01>-0.00290136319</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.00290136319</R10>
|
||||
<R11>0.999995768</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Right Arm</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="Keyframe" referent="RBX11">
|
||||
<Properties>
|
||||
<string name="Name">Keyframe</string>
|
||||
<float name="Time">0.5</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX12">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Torso</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
<Item class="Pose" referent="RBX13">
|
||||
<Properties>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>1.86264515e-009</Y>
|
||||
<Z>0</Z>
|
||||
<R00>-0.0374366008</R00>
|
||||
<R01>-0.99929899</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0.99929899</R10>
|
||||
<R11>-0.0374366008</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<float name="MaskWeight">0</float>
|
||||
<string name="Name">Right Arm</string>
|
||||
<float name="Weight">1</float>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
</roblox>
|
||||
BIN
client/common/content/avatar/animations/walk.rbxm
Normal file
BIN
client/common/content/avatar/animations/walk.rbxm
Normal file
Binary file not shown.
606
client/common/content/avatar/character.rbxmx
Normal file
606
client/common/content/avatar/character.rbxmx
Normal file
@@ -0,0 +1,606 @@
|
||||
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="4">
|
||||
<External>null</External>
|
||||
<External>nil</External>
|
||||
<Item class="Model" referent="RBX0">
|
||||
<Properties>
|
||||
<token name="Controller">7</token>
|
||||
<bool name="ControllerFlagShown">true</bool>
|
||||
<CoordinateFrame name="ModelInPrimary">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
<R00>1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>1</R22>
|
||||
</CoordinateFrame>
|
||||
<string name="Name">erik.cassel</string>
|
||||
<Ref name="PrimaryPart">RBX1</Ref>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
<Item class="Part" referent="RBX1">
|
||||
<Properties>
|
||||
<bool name="Anchored">false</bool>
|
||||
<float name="BackParamA">-0.5</float>
|
||||
<float name="BackParamB">0.5</float>
|
||||
<token name="BackSurface">0</token>
|
||||
<token name="BackSurfaceInput">0</token>
|
||||
<float name="BottomParamA">-0.5</float>
|
||||
<float name="BottomParamB">0.5</float>
|
||||
<token name="BottomSurface">4</token>
|
||||
<token name="BottomSurfaceInput">0</token>
|
||||
<int name="BrickColor">24</int>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>4.5</Y>
|
||||
<Z>25.5</Z>
|
||||
<R00>-1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>-1</R22>
|
||||
</CoordinateFrame>
|
||||
<bool name="CanCollide">true</bool>
|
||||
<token name="Controller">0</token>
|
||||
<bool name="ControllerFlagShown">true</bool>
|
||||
<bool name="DraggingV1">false</bool>
|
||||
<float name="Elasticity">0.5</float>
|
||||
<token name="FormFactor">0</token>
|
||||
<float name="Friction">0.300000012</float>
|
||||
<float name="FrontParamA">-0.5</float>
|
||||
<float name="FrontParamB">0.5</float>
|
||||
<token name="FrontSurface">0</token>
|
||||
<token name="FrontSurfaceInput">0</token>
|
||||
<float name="LeftParamA">-0.5</float>
|
||||
<float name="LeftParamB">0.5</float>
|
||||
<token name="LeftSurface">0</token>
|
||||
<token name="LeftSurfaceInput">0</token>
|
||||
<bool name="Locked">true</bool>
|
||||
<string name="Name">Head</string>
|
||||
<float name="Reflectance">0</float>
|
||||
<float name="RightParamA">-0.5</float>
|
||||
<float name="RightParamB">0.5</float>
|
||||
<token name="RightSurface">0</token>
|
||||
<token name="RightSurfaceInput">0</token>
|
||||
<Vector3 name="RotVelocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<float name="TopParamA">-0.5</float>
|
||||
<float name="TopParamB">0.5</float>
|
||||
<token name="TopSurface">0</token>
|
||||
<token name="TopSurfaceInput">0</token>
|
||||
<float name="Transparency">0</float>
|
||||
<Vector3 name="Velocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<bool name="archivable">true</bool>
|
||||
<token name="shape">1</token>
|
||||
<Vector3 name="size">
|
||||
<X>2</X>
|
||||
<Y>1</Y>
|
||||
<Z>1</Z>
|
||||
</Vector3>
|
||||
</Properties>
|
||||
<Item class="SpecialMesh" referent="RBX2">
|
||||
<Properties>
|
||||
<Content name="MeshId">
|
||||
<null></null>
|
||||
</Content>
|
||||
<token name="MeshType">0</token>
|
||||
<string name="Name">Mesh</string>
|
||||
<Vector3 name="Scale">
|
||||
<X>1.25</X>
|
||||
<Y>1.25</Y>
|
||||
<Z>1.25</Z>
|
||||
</Vector3>
|
||||
<Content name="TextureId">
|
||||
<null></null>
|
||||
</Content>
|
||||
<Vector3 name="VertexColor">
|
||||
<X>1</X>
|
||||
<Y>1</Y>
|
||||
<Z>1</Z>
|
||||
</Vector3>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Decal" referent="RBX3">
|
||||
<Properties>
|
||||
<token name="Face">5</token>
|
||||
<string name="Name">face</string>
|
||||
<float name="Shiny">20</float>
|
||||
<float name="Specular">0</float>
|
||||
<Content name="Texture">
|
||||
<url>ayaasset://textures/face.png</url>
|
||||
</Content>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="Part" referent="RBX4">
|
||||
<Properties>
|
||||
<bool name="Anchored">false</bool>
|
||||
<float name="BackParamA">-0.5</float>
|
||||
<float name="BackParamB">0.5</float>
|
||||
<token name="BackSurface">0</token>
|
||||
<token name="BackSurfaceInput">0</token>
|
||||
<float name="BottomParamA">-0.5</float>
|
||||
<float name="BottomParamB">0.5</float>
|
||||
<token name="BottomSurface">4</token>
|
||||
<token name="BottomSurfaceInput">0</token>
|
||||
<int name="BrickColor">23</int>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>3</Y>
|
||||
<Z>25.5</Z>
|
||||
<R00>-1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>-0</R02>
|
||||
<R10>-0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>-0</R12>
|
||||
<R20>-0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>-1</R22>
|
||||
</CoordinateFrame>
|
||||
<bool name="CanCollide">true</bool>
|
||||
<token name="Controller">0</token>
|
||||
<bool name="ControllerFlagShown">true</bool>
|
||||
<bool name="DraggingV1">false</bool>
|
||||
<float name="Elasticity">0.5</float>
|
||||
<token name="FormFactor">0</token>
|
||||
<float name="Friction">0.300000012</float>
|
||||
<float name="FrontParamA">-0.5</float>
|
||||
<float name="FrontParamB">0.5</float>
|
||||
<token name="FrontSurface">0</token>
|
||||
<token name="FrontSurfaceInput">0</token>
|
||||
<float name="LeftParamA">0</float>
|
||||
<float name="LeftParamB">0</float>
|
||||
<token name="LeftSurface">2</token>
|
||||
<token name="LeftSurfaceInput">0</token>
|
||||
<bool name="Locked">true</bool>
|
||||
<string name="Name">Torso</string>
|
||||
<float name="Reflectance">0</float>
|
||||
<float name="RightParamA">0</float>
|
||||
<float name="RightParamB">0</float>
|
||||
<token name="RightSurface">2</token>
|
||||
<token name="RightSurfaceInput">0</token>
|
||||
<Vector3 name="RotVelocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<float name="TopParamA">-0.5</float>
|
||||
<float name="TopParamB">0.5</float>
|
||||
<token name="TopSurface">3</token>
|
||||
<token name="TopSurfaceInput">0</token>
|
||||
<float name="Transparency">0</float>
|
||||
<Vector3 name="Velocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<bool name="archivable">true</bool>
|
||||
<token name="shape">1</token>
|
||||
<Vector3 name="size">
|
||||
<X>2</X>
|
||||
<Y>2</Y>
|
||||
<Z>1</Z>
|
||||
</Vector3>
|
||||
</Properties>
|
||||
<Item class="Decal" referent="RBX5">
|
||||
<Properties>
|
||||
<token name="Face">5</token>
|
||||
<string name="Name">roblox</string>
|
||||
<float name="Shiny">20</float>
|
||||
<float name="Specular">0</float>
|
||||
<Content name="Texture">
|
||||
<null></null>
|
||||
</Content>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="Part" referent="RBX6">
|
||||
<Properties>
|
||||
<bool name="Anchored">false</bool>
|
||||
<float name="BackParamA">-0.5</float>
|
||||
<float name="BackParamB">0.5</float>
|
||||
<token name="BackSurface">0</token>
|
||||
<token name="BackSurfaceInput">0</token>
|
||||
<float name="BottomParamA">-0.5</float>
|
||||
<float name="BottomParamB">0.5</float>
|
||||
<token name="BottomSurface">4</token>
|
||||
<token name="BottomSurfaceInput">0</token>
|
||||
<int name="BrickColor">24</int>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>1.5</X>
|
||||
<Y>3</Y>
|
||||
<Z>25.5</Z>
|
||||
<R00>-1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>-1</R22>
|
||||
</CoordinateFrame>
|
||||
<bool name="CanCollide">false</bool>
|
||||
<token name="Controller">0</token>
|
||||
<bool name="ControllerFlagShown">true</bool>
|
||||
<bool name="DraggingV1">false</bool>
|
||||
<float name="Elasticity">0.5</float>
|
||||
<token name="FormFactor">0</token>
|
||||
<float name="Friction">0.300000012</float>
|
||||
<float name="FrontParamA">-0.5</float>
|
||||
<float name="FrontParamB">0.5</float>
|
||||
<token name="FrontSurface">0</token>
|
||||
<token name="FrontSurfaceInput">0</token>
|
||||
<float name="LeftParamA">-0.5</float>
|
||||
<float name="LeftParamB">0.5</float>
|
||||
<token name="LeftSurface">0</token>
|
||||
<token name="LeftSurfaceInput">0</token>
|
||||
<bool name="Locked">true</bool>
|
||||
<string name="Name">Left Arm</string>
|
||||
<float name="Reflectance">0</float>
|
||||
<float name="RightParamA">-0.5</float>
|
||||
<float name="RightParamB">0.5</float>
|
||||
<token name="RightSurface">0</token>
|
||||
<token name="RightSurfaceInput">0</token>
|
||||
<Vector3 name="RotVelocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<float name="TopParamA">-0.5</float>
|
||||
<float name="TopParamB">0.5</float>
|
||||
<token name="TopSurface">3</token>
|
||||
<token name="TopSurfaceInput">0</token>
|
||||
<float name="Transparency">0</float>
|
||||
<Vector3 name="Velocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<bool name="archivable">true</bool>
|
||||
<token name="shape">1</token>
|
||||
<Vector3 name="size">
|
||||
<X>1</X>
|
||||
<Y>2</Y>
|
||||
<Z>1</Z>
|
||||
</Vector3>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Part" referent="RBX7">
|
||||
<Properties>
|
||||
<bool name="Anchored">false</bool>
|
||||
<float name="BackParamA">-0.5</float>
|
||||
<float name="BackParamB">0.5</float>
|
||||
<token name="BackSurface">0</token>
|
||||
<token name="BackSurfaceInput">0</token>
|
||||
<float name="BottomParamA">-0.5</float>
|
||||
<float name="BottomParamB">0.5</float>
|
||||
<token name="BottomSurface">4</token>
|
||||
<token name="BottomSurfaceInput">0</token>
|
||||
<int name="BrickColor">24</int>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>-1.5</X>
|
||||
<Y>3</Y>
|
||||
<Z>25.5</Z>
|
||||
<R00>-1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>-1</R22>
|
||||
</CoordinateFrame>
|
||||
<bool name="CanCollide">false</bool>
|
||||
<token name="Controller">0</token>
|
||||
<bool name="ControllerFlagShown">true</bool>
|
||||
<bool name="DraggingV1">false</bool>
|
||||
<float name="Elasticity">0.5</float>
|
||||
<token name="FormFactor">0</token>
|
||||
<float name="Friction">0.300000012</float>
|
||||
<float name="FrontParamA">-0.5</float>
|
||||
<float name="FrontParamB">0.5</float>
|
||||
<token name="FrontSurface">0</token>
|
||||
<token name="FrontSurfaceInput">0</token>
|
||||
<float name="LeftParamA">-0.5</float>
|
||||
<float name="LeftParamB">0.5</float>
|
||||
<token name="LeftSurface">0</token>
|
||||
<token name="LeftSurfaceInput">0</token>
|
||||
<bool name="Locked">true</bool>
|
||||
<string name="Name">Right Arm</string>
|
||||
<float name="Reflectance">0</float>
|
||||
<float name="RightParamA">-0.5</float>
|
||||
<float name="RightParamB">0.5</float>
|
||||
<token name="RightSurface">0</token>
|
||||
<token name="RightSurfaceInput">0</token>
|
||||
<Vector3 name="RotVelocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<float name="TopParamA">-0.5</float>
|
||||
<float name="TopParamB">0.5</float>
|
||||
<token name="TopSurface">3</token>
|
||||
<token name="TopSurfaceInput">0</token>
|
||||
<float name="Transparency">0</float>
|
||||
<Vector3 name="Velocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<bool name="archivable">true</bool>
|
||||
<token name="shape">1</token>
|
||||
<Vector3 name="size">
|
||||
<X>1</X>
|
||||
<Y>2</Y>
|
||||
<Z>1</Z>
|
||||
</Vector3>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Part" referent="RBX8">
|
||||
<Properties>
|
||||
<bool name="Anchored">false</bool>
|
||||
<float name="BackParamA">-0.5</float>
|
||||
<float name="BackParamB">0.5</float>
|
||||
<token name="BackSurface">0</token>
|
||||
<token name="BackSurfaceInput">0</token>
|
||||
<float name="BottomParamA">-0.5</float>
|
||||
<float name="BottomParamB">0.5</float>
|
||||
<token name="BottomSurface">0</token>
|
||||
<token name="BottomSurfaceInput">0</token>
|
||||
<int name="BrickColor">119</int>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0.5</X>
|
||||
<Y>1</Y>
|
||||
<Z>25.5</Z>
|
||||
<R00>-1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>-1</R22>
|
||||
</CoordinateFrame>
|
||||
<bool name="CanCollide">false</bool>
|
||||
<token name="Controller">0</token>
|
||||
<bool name="ControllerFlagShown">true</bool>
|
||||
<bool name="DraggingV1">false</bool>
|
||||
<float name="Elasticity">0.5</float>
|
||||
<token name="FormFactor">0</token>
|
||||
<float name="Friction">0.300000012</float>
|
||||
<float name="FrontParamA">-0.5</float>
|
||||
<float name="FrontParamB">0.5</float>
|
||||
<token name="FrontSurface">0</token>
|
||||
<token name="FrontSurfaceInput">0</token>
|
||||
<float name="LeftParamA">-0.5</float>
|
||||
<float name="LeftParamB">0.5</float>
|
||||
<token name="LeftSurface">0</token>
|
||||
<token name="LeftSurfaceInput">0</token>
|
||||
<bool name="Locked">true</bool>
|
||||
<string name="Name">Left Leg</string>
|
||||
<float name="Reflectance">0</float>
|
||||
<float name="RightParamA">-0.5</float>
|
||||
<float name="RightParamB">0.5</float>
|
||||
<token name="RightSurface">0</token>
|
||||
<token name="RightSurfaceInput">0</token>
|
||||
<Vector3 name="RotVelocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<float name="TopParamA">-0.5</float>
|
||||
<float name="TopParamB">0.5</float>
|
||||
<token name="TopSurface">3</token>
|
||||
<token name="TopSurfaceInput">0</token>
|
||||
<float name="Transparency">0</float>
|
||||
<Vector3 name="Velocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<bool name="archivable">true</bool>
|
||||
<token name="shape">1</token>
|
||||
<Vector3 name="size">
|
||||
<X>1</X>
|
||||
<Y>2</Y>
|
||||
<Z>1</Z>
|
||||
</Vector3>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Part" referent="RBX9">
|
||||
<Properties>
|
||||
<bool name="Anchored">false</bool>
|
||||
<float name="BackParamA">-0.5</float>
|
||||
<float name="BackParamB">0.5</float>
|
||||
<token name="BackSurface">0</token>
|
||||
<token name="BackSurfaceInput">0</token>
|
||||
<float name="BottomParamA">-0.5</float>
|
||||
<float name="BottomParamB">0.5</float>
|
||||
<token name="BottomSurface">0</token>
|
||||
<token name="BottomSurfaceInput">0</token>
|
||||
<int name="BrickColor">119</int>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>-0.5</X>
|
||||
<Y>1</Y>
|
||||
<Z>25.5</Z>
|
||||
<R00>-1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>0</R02>
|
||||
<R10>0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>0</R12>
|
||||
<R20>0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>-1</R22>
|
||||
</CoordinateFrame>
|
||||
<bool name="CanCollide">false</bool>
|
||||
<token name="Controller">0</token>
|
||||
<bool name="ControllerFlagShown">true</bool>
|
||||
<bool name="DraggingV1">false</bool>
|
||||
<float name="Elasticity">0.5</float>
|
||||
<token name="FormFactor">0</token>
|
||||
<float name="Friction">0.300000012</float>
|
||||
<float name="FrontParamA">-0.5</float>
|
||||
<float name="FrontParamB">0.5</float>
|
||||
<token name="FrontSurface">0</token>
|
||||
<token name="FrontSurfaceInput">0</token>
|
||||
<float name="LeftParamA">-0.5</float>
|
||||
<float name="LeftParamB">0.5</float>
|
||||
<token name="LeftSurface">0</token>
|
||||
<token name="LeftSurfaceInput">0</token>
|
||||
<bool name="Locked">true</bool>
|
||||
<string name="Name">Right Leg</string>
|
||||
<float name="Reflectance">0</float>
|
||||
<float name="RightParamA">-0.5</float>
|
||||
<float name="RightParamB">0.5</float>
|
||||
<token name="RightSurface">0</token>
|
||||
<token name="RightSurfaceInput">0</token>
|
||||
<Vector3 name="RotVelocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<float name="TopParamA">-0.5</float>
|
||||
<float name="TopParamB">0.5</float>
|
||||
<token name="TopSurface">3</token>
|
||||
<token name="TopSurfaceInput">0</token>
|
||||
<float name="Transparency">0</float>
|
||||
<Vector3 name="Velocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<bool name="archivable">true</bool>
|
||||
<token name="shape">1</token>
|
||||
<Vector3 name="size">
|
||||
<X>1</X>
|
||||
<Y>2</Y>
|
||||
<Z>1</Z>
|
||||
</Vector3>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Humanoid" referent="RBX10">
|
||||
<Properties>
|
||||
<float name="Health">100</float>
|
||||
<bool name="Jump">false</bool>
|
||||
<float name="MaxHealth">100</float>
|
||||
<string name="Name">Humanoid</string>
|
||||
<bool name="Sit">false</bool>
|
||||
<Vector3 name="TargetPoint">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<Vector3 name="WalkDirection">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<float name="WalkRotationalVelocity">0</float>
|
||||
<Ref name="WalkToPart">null</Ref>
|
||||
<Vector3 name="WalkToPoint">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Part" referent="RBX11">
|
||||
<Properties>
|
||||
<bool name="Anchored">false</bool>
|
||||
<float name="BackParamA">-0.5</float>
|
||||
<float name="BackParamB">0.5</float>
|
||||
<token name="BackSurface">0</token>
|
||||
<token name="BackSurfaceInput">0</token>
|
||||
<float name="BottomParamA">-0.5</float>
|
||||
<float name="BottomParamB">0.5</float>
|
||||
<token name="BottomSurface">0</token>
|
||||
<token name="BottomSurfaceInput">0</token>
|
||||
<int name="BrickColor">23</int>
|
||||
<CoordinateFrame name="CFrame">
|
||||
<X>0</X>
|
||||
<Y>3</Y>
|
||||
<Z>25.5</Z>
|
||||
<R00>-1</R00>
|
||||
<R01>0</R01>
|
||||
<R02>-0</R02>
|
||||
<R10>-0</R10>
|
||||
<R11>1</R11>
|
||||
<R12>-0</R12>
|
||||
<R20>-0</R20>
|
||||
<R21>0</R21>
|
||||
<R22>-1</R22>
|
||||
</CoordinateFrame>
|
||||
<bool name="CanCollide">false</bool>
|
||||
<token name="Controller">0</token>
|
||||
<bool name="ControllerFlagShown">true</bool>
|
||||
<bool name="DraggingV1">false</bool>
|
||||
<float name="Elasticity">0.5</float>
|
||||
<token name="FormFactor">0</token>
|
||||
<float name="Friction">0.300000012</float>
|
||||
<float name="FrontParamA">-0.5</float>
|
||||
<float name="FrontParamB">0.5</float>
|
||||
<token name="FrontSurface">0</token>
|
||||
<token name="FrontSurfaceInput">0</token>
|
||||
<float name="LeftParamA">0</float>
|
||||
<float name="LeftParamB">0</float>
|
||||
<token name="LeftSurface">0</token>
|
||||
<token name="LeftSurfaceInput">0</token>
|
||||
<bool name="Locked">true</bool>
|
||||
<string name="Name">HumanoidRootPart</string>
|
||||
<float name="Reflectance">0</float>
|
||||
<float name="RightParamA">0</float>
|
||||
<float name="RightParamB">0</float>
|
||||
<token name="RightSurface">0</token>
|
||||
<token name="RightSurfaceInput">0</token>
|
||||
<Vector3 name="RotVelocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<float name="TopParamA">-0.5</float>
|
||||
<float name="TopParamB">0.5</float>
|
||||
<token name="TopSurface">0</token>
|
||||
<token name="TopSurfaceInput">0</token>
|
||||
<float name="Transparency">1</float>
|
||||
<Vector3 name="Velocity">
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
<Z>0</Z>
|
||||
</Vector3>
|
||||
<bool name="archivable">true</bool>
|
||||
<token name="shape">1</token>
|
||||
<Vector3 name="size">
|
||||
<X>2</X>
|
||||
<Y>2</Y>
|
||||
<Z>1</Z>
|
||||
</Vector3>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</roblox>
|
||||
BIN
client/common/content/avatar/characterR15.rbxm
Normal file
BIN
client/common/content/avatar/characterR15.rbxm
Normal file
Binary file not shown.
BIN
client/common/content/avatar/compositing/CompositExtraSlot0.mesh
Normal file
BIN
client/common/content/avatar/compositing/CompositExtraSlot0.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/compositing/CompositExtraSlot1.mesh
Normal file
BIN
client/common/content/avatar/compositing/CompositExtraSlot1.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/compositing/CompositExtraSlot2.mesh
Normal file
BIN
client/common/content/avatar/compositing/CompositExtraSlot2.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/compositing/CompositExtraSlot3.mesh
Normal file
BIN
client/common/content/avatar/compositing/CompositExtraSlot3.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/compositing/CompositExtraSlot4.mesh
Normal file
BIN
client/common/content/avatar/compositing/CompositExtraSlot4.mesh
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
client/common/content/avatar/compositing/CompositTShirt.mesh
Normal file
BIN
client/common/content/avatar/compositing/CompositTShirt.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/compositing/CompositTorsoBase.mesh
Normal file
BIN
client/common/content/avatar/compositing/CompositTorsoBase.mesh
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
client/common/content/avatar/heads/head.mesh
Normal file
BIN
client/common/content/avatar/heads/head.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headA.mesh
Normal file
BIN
client/common/content/avatar/heads/headA.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headB.mesh
Normal file
BIN
client/common/content/avatar/heads/headB.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headC.mesh
Normal file
BIN
client/common/content/avatar/heads/headC.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headD.mesh
Normal file
BIN
client/common/content/avatar/heads/headD.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headE.mesh
Normal file
BIN
client/common/content/avatar/heads/headE.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headF.mesh
Normal file
BIN
client/common/content/avatar/heads/headF.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headG.mesh
Normal file
BIN
client/common/content/avatar/heads/headG.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headH.mesh
Normal file
BIN
client/common/content/avatar/heads/headH.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headI.mesh
Normal file
BIN
client/common/content/avatar/heads/headI.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headJ.mesh
Normal file
BIN
client/common/content/avatar/heads/headJ.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headK.mesh
Normal file
BIN
client/common/content/avatar/heads/headK.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headL.mesh
Normal file
BIN
client/common/content/avatar/heads/headL.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headM.mesh
Normal file
BIN
client/common/content/avatar/heads/headM.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headN.mesh
Normal file
BIN
client/common/content/avatar/heads/headN.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headO.mesh
Normal file
BIN
client/common/content/avatar/heads/headO.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/heads/headP.mesh
Normal file
BIN
client/common/content/avatar/heads/headP.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/meshes/leftarm.mesh
Normal file
BIN
client/common/content/avatar/meshes/leftarm.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/meshes/leftleg.mesh
Normal file
BIN
client/common/content/avatar/meshes/leftleg.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/meshes/rightarm.mesh
Normal file
BIN
client/common/content/avatar/meshes/rightarm.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/meshes/rightleg.mesh
Normal file
BIN
client/common/content/avatar/meshes/rightleg.mesh
Normal file
Binary file not shown.
BIN
client/common/content/avatar/meshes/torso.mesh
Normal file
BIN
client/common/content/avatar/meshes/torso.mesh
Normal file
Binary file not shown.
4298
client/common/content/avatar/scripts/characterCameraScript.rbxmx
Normal file
4298
client/common/content/avatar/scripts/characterCameraScript.rbxmx
Normal file
File diff suppressed because it is too large
Load Diff
2067
client/common/content/avatar/scripts/characterControlScript.rbxmx
Normal file
2067
client/common/content/avatar/scripts/characterControlScript.rbxmx
Normal file
File diff suppressed because it is too large
Load Diff
34
client/common/content/avatar/scripts/dialogTimeout.rbxmx
Normal file
34
client/common/content/avatar/scripts/dialogTimeout.rbxmx
Normal file
@@ -0,0 +1,34 @@
|
||||
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="4">
|
||||
<External>null</External>
|
||||
<External>nil</External>
|
||||
<Item class="Script" referent="RBX0">
|
||||
<Properties>
|
||||
<bool name="Disabled">true</bool>
|
||||
<Content name="LinkedSource"><null></null></Content>
|
||||
<string name="Name">ReenableDialogScript</string>
|
||||
<ProtectedString name="Source">wait(5)
|
||||
local dialog = script.Parent
|
||||
if dialog:IsA("Dialog") then
|
||||
dialog.InUse = false
|
||||
end
|
||||
script:Remove()
|
||||
</ProtectedString>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="Script" referent="RBX1">
|
||||
<Properties>
|
||||
<bool name="Disabled">true</bool>
|
||||
<Content name="LinkedSource"><null></null></Content>
|
||||
<string name="Name">TimeoutScript</string>
|
||||
<ProtectedString name="Source">wait(15)
|
||||
local dialog = script.Parent
|
||||
if dialog:IsA("Dialog") then
|
||||
dialog.InUse = false
|
||||
end
|
||||
script:Remove()
|
||||
</ProtectedString>
|
||||
<bool name="archivable">true</bool>
|
||||
</Properties>
|
||||
</Item>
|
||||
</roblox>
|
||||
689
client/common/content/avatar/scripts/humanoidAnimate.rbxmx
Normal file
689
client/common/content/avatar/scripts/humanoidAnimate.rbxmx
Normal file
@@ -0,0 +1,689 @@
|
||||
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="4">
|
||||
<External>null</External>
|
||||
<External>nil</External>
|
||||
<Item class="LocalScript" referent="RBXC49238CC391A40B0B08D3C0989F85A53">
|
||||
<Properties>
|
||||
<bool name="Disabled">false</bool>
|
||||
<Content name="LinkedSource">
|
||||
<null></null>
|
||||
</Content>
|
||||
<string name="Name">Animate</string>
|
||||
<ProtectedString name="Source"><![CDATA[function waitForChild(parent, childName)
|
||||
local child = parent:findFirstChild(childName)
|
||||
if child then return child end
|
||||
while true do
|
||||
child = parent.ChildAdded:wait()
|
||||
if child.Name==childName then return child end
|
||||
end
|
||||
end
|
||||
|
||||
local Figure = script.Parent
|
||||
local Torso = waitForChild(Figure, "Torso")
|
||||
local RightShoulder = waitForChild(Torso, "Right Shoulder")
|
||||
local LeftShoulder = waitForChild(Torso, "Left Shoulder")
|
||||
local RightHip = waitForChild(Torso, "Right Hip")
|
||||
local LeftHip = waitForChild(Torso, "Left Hip")
|
||||
local Neck = waitForChild(Torso, "Neck")
|
||||
local Humanoid = waitForChild(Figure, "Humanoid")
|
||||
local pose = "Standing"
|
||||
|
||||
local currentAnim = ""
|
||||
local currentAnimInstance = nil
|
||||
local currentAnimTrack = nil
|
||||
local currentAnimKeyframeHandler = nil
|
||||
local currentAnimSpeed = 1.0
|
||||
local animTable = {}
|
||||
local animNames = {
|
||||
idle = {
|
||||
{ id = "ayaasset://avatar/animations/idle0.rbxm", weight = 9 },
|
||||
{ id = "ayaasset://avatar/animations/idle1.rbxm", weight = 1 }
|
||||
},
|
||||
walk = {
|
||||
{ id = "ayaasset://avatar/animations/walk.rbxm", weight = 10 }
|
||||
},
|
||||
run = {
|
||||
{ id = "ayaasset://avatar/animations/walk.rbxm", weight = 10 }
|
||||
},
|
||||
jump = {
|
||||
{ id = "ayaasset://avatar/animations/jump.rbxm", weight = 10 }
|
||||
},
|
||||
fall = {
|
||||
{ id = "ayaasset://avatar/animations/fall.rbxm", weight = 10 }
|
||||
},
|
||||
climb = {
|
||||
{ id = "ayaasset://avatar/animations/climb.rbxm", weight = 10 }
|
||||
},
|
||||
sit = {
|
||||
{ id = "ayaasset://avatar/animations/sit.rbxm", weight = 10 }
|
||||
},
|
||||
toolnone = {
|
||||
{ id = "ayaasset://avatar/animations/toolnone.rbxm", weight = 10 }
|
||||
},
|
||||
toolslash = {
|
||||
{ id = "ayaasset://avatar/animations/toolslash.rbxm", weight = 10 }
|
||||
},
|
||||
toollunge = {
|
||||
{ id = "ayaasset://avatar/animations/toollunge.rbxm", weight = 10 }
|
||||
},
|
||||
wave = {
|
||||
{ id = "ayaasset://avatar/animations/emotes/wave.rbxm", weight = 10 }
|
||||
},
|
||||
point = {
|
||||
{ id = "ayaasset://avatar/animations/emotes/point.rbxm", weight = 10 }
|
||||
},
|
||||
dance1 = {
|
||||
{ id = "ayaasset://avatar/animations/emotes/dance1_0.rbxm", weight = 10 },
|
||||
{ id = "ayaasset://avatar/animations/emotes/dance1_1.rbxm", weight = 10 },
|
||||
{ id = "ayaasset://avatar/animations/emotes/dance1_2.rbxm", weight = 10 }
|
||||
},
|
||||
dance2 = {
|
||||
{ id = "ayaasset://avatar/animations/emotes/dance2_0.rbxm", weight = 10 },
|
||||
{ id = "ayaasset://avatar/animations/emotes/dance2_1.rbxm", weight = 10 },
|
||||
{ id = "ayaasset://avatar/animations/emotes/dance2_2.rbxm", weight = 10 }
|
||||
},
|
||||
dance3 = {
|
||||
{ id = "ayaasset://avatar/animations/emotes/dance3_0.rbxm", weight = 10 },
|
||||
{ id = "ayaasset://avatar/animations/emotes/dance3_1.rbxm", weight = 10 },
|
||||
{ id = "ayaasset://avatar/animations/emotes/dance3_2.rbxm", weight = 10 }
|
||||
},
|
||||
laugh = {
|
||||
{ id = "ayaasset://avatar/animations/emotes/laugh.rbxm", weight = 10 }
|
||||
},
|
||||
cheer = {
|
||||
{ id = "ayaasset://avatar/animations/emotes/cheer.rbxm", weight = 10 }
|
||||
},
|
||||
}
|
||||
local dances = {"dance1", "dance2", "dance3"}
|
||||
|
||||
-- Existance in this list signifies that it is an emote, the value indicates if it is a looping emote
|
||||
local emoteNames = { wave = false, point = false, dance1 = true, dance2 = true, dance3 = true, laugh = false, cheer = false}
|
||||
|
||||
function configureAnimationSet(name, fileList)
|
||||
if (animTable[name] ~= nil) then
|
||||
for _, connection in pairs(animTable[name].connections) do
|
||||
connection:disconnect()
|
||||
end
|
||||
end
|
||||
animTable[name] = {}
|
||||
animTable[name].count = 0
|
||||
animTable[name].totalWeight = 0
|
||||
animTable[name].connections = {}
|
||||
|
||||
-- check for config values
|
||||
local config = script:FindFirstChild(name)
|
||||
if (config ~= nil) then
|
||||
-- print("Loading anims " .. name)
|
||||
table.insert(animTable[name].connections, config.ChildAdded:connect(function(child) configureAnimationSet(name, fileList) end))
|
||||
table.insert(animTable[name].connections, config.ChildRemoved:connect(function(child) configureAnimationSet(name, fileList) end))
|
||||
local idx = 1
|
||||
for _, childPart in pairs(config:GetChildren()) do
|
||||
if (childPart:IsA("Animation")) then
|
||||
table.insert(animTable[name].connections, childPart.Changed:connect(function(property) configureAnimationSet(name, fileList) end))
|
||||
animTable[name][idx] = {}
|
||||
animTable[name][idx].anim = childPart
|
||||
local weightObject = childPart:FindFirstChild("Weight")
|
||||
if (weightObject == nil) then
|
||||
animTable[name][idx].weight = 1
|
||||
else
|
||||
animTable[name][idx].weight = weightObject.Value
|
||||
end
|
||||
animTable[name].count = animTable[name].count + 1
|
||||
animTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight
|
||||
-- print(name .. " [" .. idx .. "] " .. animTable[name][idx].anim.AnimationId .. " (" .. animTable[name][idx].weight .. ")")
|
||||
idx = idx + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- fallback to defaults
|
||||
if (animTable[name].count <= 0) then
|
||||
for idx, anim in pairs(fileList) do
|
||||
animTable[name][idx] = {}
|
||||
animTable[name][idx].anim = Instance.new("Animation")
|
||||
animTable[name][idx].anim.Name = name
|
||||
animTable[name][idx].anim.AnimationId = anim.id
|
||||
animTable[name][idx].weight = anim.weight
|
||||
animTable[name].count = animTable[name].count + 1
|
||||
animTable[name].totalWeight = animTable[name].totalWeight + anim.weight
|
||||
-- print(name .. " [" .. idx .. "] " .. anim.id .. " (" .. anim.weight .. ")")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Setup animation objects
|
||||
function scriptChildModified(child)
|
||||
local fileList = animNames[child.Name]
|
||||
if (fileList ~= nil) then
|
||||
configureAnimationSet(child.Name, fileList)
|
||||
end
|
||||
end
|
||||
|
||||
script.ChildAdded:connect(scriptChildModified)
|
||||
script.ChildRemoved:connect(scriptChildModified)
|
||||
|
||||
|
||||
for name, fileList in pairs(animNames) do
|
||||
configureAnimationSet(name, fileList)
|
||||
end
|
||||
|
||||
-- ANIMATION
|
||||
|
||||
-- declarations
|
||||
local toolAnim = "None"
|
||||
local toolAnimTime = 0
|
||||
|
||||
local jumpAnimTime = 0
|
||||
local jumpAnimDuration = 0.3
|
||||
|
||||
local toolTransitionTime = 0.1
|
||||
local fallTransitionTime = 0.3
|
||||
local jumpMaxLimbVelocity = 0.75
|
||||
|
||||
-- functions
|
||||
|
||||
function stopAllAnimations()
|
||||
local oldAnim = currentAnim
|
||||
|
||||
-- return to idle if finishing an emote
|
||||
if (emoteNames[oldAnim] ~= nil and emoteNames[oldAnim] == false) then
|
||||
oldAnim = "idle"
|
||||
end
|
||||
|
||||
currentAnim = ""
|
||||
currentAnimInstance = nil
|
||||
if (currentAnimKeyframeHandler ~= nil) then
|
||||
currentAnimKeyframeHandler:disconnect()
|
||||
end
|
||||
|
||||
if (currentAnimTrack ~= nil) then
|
||||
currentAnimTrack:Stop()
|
||||
currentAnimTrack:Destroy()
|
||||
currentAnimTrack = nil
|
||||
end
|
||||
return oldAnim
|
||||
end
|
||||
|
||||
function setAnimationSpeed(speed)
|
||||
if speed ~= currentAnimSpeed then
|
||||
currentAnimSpeed = speed
|
||||
currentAnimTrack:AdjustSpeed(currentAnimSpeed)
|
||||
end
|
||||
end
|
||||
|
||||
function keyFrameReachedFunc(frameName)
|
||||
if (frameName == "End") then
|
||||
|
||||
local repeatAnim = currentAnim
|
||||
-- return to idle if finishing an emote
|
||||
if (emoteNames[repeatAnim] ~= nil and emoteNames[repeatAnim] == false) then
|
||||
repeatAnim = "idle"
|
||||
end
|
||||
|
||||
local animSpeed = currentAnimSpeed
|
||||
playAnimation(repeatAnim, 0.0, Humanoid)
|
||||
setAnimationSpeed(animSpeed)
|
||||
end
|
||||
end
|
||||
|
||||
-- Preload animations
|
||||
function playAnimation(animName, transitionTime, humanoid)
|
||||
|
||||
local roll = math.random(1, animTable[animName].totalWeight)
|
||||
local origRoll = roll
|
||||
local idx = 1
|
||||
while (roll > animTable[animName][idx].weight) do
|
||||
roll = roll - animTable[animName][idx].weight
|
||||
idx = idx + 1
|
||||
end
|
||||
-- print(animName .. " " .. idx .. " [" .. origRoll .. "]")
|
||||
local anim = animTable[animName][idx].anim
|
||||
|
||||
-- switch animation
|
||||
if (anim ~= currentAnimInstance) then
|
||||
|
||||
if (currentAnimTrack ~= nil) then
|
||||
currentAnimTrack:Stop(transitionTime)
|
||||
currentAnimTrack:Destroy()
|
||||
end
|
||||
|
||||
currentAnimSpeed = 1.0
|
||||
|
||||
-- load it to the humanoid; get AnimationTrack
|
||||
currentAnimTrack = humanoid:LoadAnimation(anim)
|
||||
|
||||
-- play the animation
|
||||
currentAnimTrack:Play(transitionTime)
|
||||
currentAnim = animName
|
||||
currentAnimInstance = anim
|
||||
|
||||
-- set up keyframe name triggers
|
||||
if (currentAnimKeyframeHandler ~= nil) then
|
||||
currentAnimKeyframeHandler:disconnect()
|
||||
end
|
||||
currentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:connect(keyFrameReachedFunc)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------
|
||||
|
||||
local toolAnimName = ""
|
||||
local toolAnimTrack = nil
|
||||
local toolAnimInstance = nil
|
||||
local currentToolAnimKeyframeHandler = nil
|
||||
|
||||
function toolKeyFrameReachedFunc(frameName)
|
||||
if (frameName == "End") then
|
||||
-- print("Keyframe : ".. frameName)
|
||||
playToolAnimation(toolAnimName, 0.0, Humanoid)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function playToolAnimation(animName, transitionTime, humanoid)
|
||||
|
||||
local roll = math.random(1, animTable[animName].totalWeight)
|
||||
local origRoll = roll
|
||||
local idx = 1
|
||||
while (roll > animTable[animName][idx].weight) do
|
||||
roll = roll - animTable[animName][idx].weight
|
||||
idx = idx + 1
|
||||
end
|
||||
-- print(animName .. " * " .. idx .. " [" .. origRoll .. "]")
|
||||
local anim = animTable[animName][idx].anim
|
||||
|
||||
if (toolAnimInstance ~= anim) then
|
||||
|
||||
if (toolAnimTrack ~= nil) then
|
||||
toolAnimTrack:Stop()
|
||||
toolAnimTrack:Destroy()
|
||||
transitionTime = 0
|
||||
end
|
||||
|
||||
-- load it to the humanoid; get AnimationTrack
|
||||
toolAnimTrack = humanoid:LoadAnimation(anim)
|
||||
|
||||
-- play the animation
|
||||
toolAnimTrack:Play(transitionTime)
|
||||
toolAnimName = animName
|
||||
toolAnimInstance = anim
|
||||
|
||||
currentToolAnimKeyframeHandler = toolAnimTrack.KeyframeReached:connect(toolKeyFrameReachedFunc)
|
||||
end
|
||||
end
|
||||
|
||||
function stopToolAnimations()
|
||||
local oldAnim = toolAnimName
|
||||
|
||||
if (currentToolAnimKeyframeHandler ~= nil) then
|
||||
currentToolAnimKeyframeHandler:disconnect()
|
||||
end
|
||||
|
||||
toolAnimName = ""
|
||||
toolAnimInstance = nil
|
||||
if (toolAnimTrack ~= nil) then
|
||||
toolAnimTrack:Stop()
|
||||
toolAnimTrack:Destroy()
|
||||
toolAnimTrack = nil
|
||||
end
|
||||
|
||||
|
||||
return oldAnim
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
function onRunning(speed)
|
||||
if speed>0.01 then
|
||||
playAnimation("walk", 0.1, Humanoid)
|
||||
if currentAnimInstance and currentAnimInstance.AnimationId == "ayaasset://avatar/animations/walk.rbxm" then
|
||||
setAnimationSpeed(speed / 14.5)
|
||||
end
|
||||
pose = "Running"
|
||||
else
|
||||
playAnimation("idle", 0.1, Humanoid)
|
||||
pose = "Standing"
|
||||
end
|
||||
end
|
||||
|
||||
function onDied()
|
||||
pose = "Dead"
|
||||
end
|
||||
|
||||
function onJumping()
|
||||
playAnimation("jump", 0.1, Humanoid)
|
||||
jumpAnimTime = jumpAnimDuration
|
||||
pose = "Jumping"
|
||||
end
|
||||
|
||||
function onClimbing(speed)
|
||||
playAnimation("climb", 0.1, Humanoid)
|
||||
setAnimationSpeed(speed / 12.0)
|
||||
pose = "Climbing"
|
||||
end
|
||||
|
||||
function onGettingUp()
|
||||
pose = "GettingUp"
|
||||
end
|
||||
|
||||
function onFreeFall()
|
||||
if (jumpAnimTime <= 0) then
|
||||
playAnimation("fall", fallTransitionTime, Humanoid)
|
||||
end
|
||||
pose = "FreeFall"
|
||||
end
|
||||
|
||||
function onFallingDown()
|
||||
pose = "FallingDown"
|
||||
end
|
||||
|
||||
function onSeated()
|
||||
pose = "Seated"
|
||||
end
|
||||
|
||||
function onPlatformStanding()
|
||||
pose = "PlatformStanding"
|
||||
end
|
||||
|
||||
function onSwimming(speed)
|
||||
if speed>0 then
|
||||
pose = "Running"
|
||||
else
|
||||
pose = "Standing"
|
||||
end
|
||||
end
|
||||
|
||||
function getTool()
|
||||
for _, kid in ipairs(Figure:GetChildren()) do
|
||||
if kid.className == "Tool" then return kid end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function getToolAnim(tool)
|
||||
for _, c in ipairs(tool:GetChildren()) do
|
||||
if c.Name == "toolanim" and c.className == "StringValue" then
|
||||
return c
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function animateTool()
|
||||
|
||||
if (toolAnim == "None") then
|
||||
playToolAnimation("toolnone", toolTransitionTime, Humanoid)
|
||||
return
|
||||
end
|
||||
|
||||
if (toolAnim == "Slash") then
|
||||
playToolAnimation("toolslash", 0, Humanoid)
|
||||
return
|
||||
end
|
||||
|
||||
if (toolAnim == "Lunge") then
|
||||
playToolAnimation("toollunge", 0, Humanoid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function moveSit()
|
||||
RightShoulder.MaxVelocity = 0.15
|
||||
LeftShoulder.MaxVelocity = 0.15
|
||||
RightShoulder:SetDesiredAngle(3.14 /2)
|
||||
LeftShoulder:SetDesiredAngle(-3.14 /2)
|
||||
RightHip:SetDesiredAngle(3.14 /2)
|
||||
LeftHip:SetDesiredAngle(-3.14 /2)
|
||||
end
|
||||
|
||||
local lastTick = 0
|
||||
|
||||
function move(time)
|
||||
local amplitude = 1
|
||||
local frequency = 1
|
||||
local deltaTime = time - lastTick
|
||||
lastTick = time
|
||||
|
||||
local climbFudge = 0
|
||||
local setAngles = false
|
||||
|
||||
if (jumpAnimTime > 0) then
|
||||
jumpAnimTime = jumpAnimTime - deltaTime
|
||||
end
|
||||
|
||||
if (pose == "FreeFall" and jumpAnimTime <= 0) then
|
||||
playAnimation("fall", fallTransitionTime, Humanoid)
|
||||
elseif (pose == "Seated") then
|
||||
playAnimation("sit", 0.5, Humanoid)
|
||||
return
|
||||
elseif (pose == "Running") then
|
||||
playAnimation("walk", 0.1, Humanoid)
|
||||
elseif (pose == "Dead" or pose == "GettingUp" or pose == "FallingDown" or pose == "Seated" or pose == "PlatformStanding") then
|
||||
-- print("Wha " .. pose)
|
||||
stopAllAnimations()
|
||||
amplitude = 0.1
|
||||
frequency = 1
|
||||
setAngles = true
|
||||
end
|
||||
|
||||
if (setAngles) then
|
||||
desiredAngle = amplitude * math.sin(time * frequency)
|
||||
|
||||
RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
|
||||
LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
|
||||
RightHip:SetDesiredAngle(-desiredAngle)
|
||||
LeftHip:SetDesiredAngle(-desiredAngle)
|
||||
end
|
||||
|
||||
-- Tool Animation handling
|
||||
local tool = getTool()
|
||||
if tool and tool:FindFirstChild("Handle") then
|
||||
|
||||
animStringValueObject = getToolAnim(tool)
|
||||
|
||||
if animStringValueObject then
|
||||
toolAnim = animStringValueObject.Value
|
||||
-- message recieved, delete StringValue
|
||||
animStringValueObject.Parent = nil
|
||||
toolAnimTime = time + .3
|
||||
end
|
||||
|
||||
if time > toolAnimTime then
|
||||
toolAnimTime = 0
|
||||
toolAnim = "None"
|
||||
end
|
||||
|
||||
animateTool()
|
||||
else
|
||||
stopToolAnimations()
|
||||
toolAnim = "None"
|
||||
toolAnimInstance = nil
|
||||
toolAnimTime = 0
|
||||
end
|
||||
end
|
||||
|
||||
-- connect events
|
||||
Humanoid.Died:connect(onDied)
|
||||
Humanoid.Running:connect(onRunning)
|
||||
Humanoid.Jumping:connect(onJumping)
|
||||
Humanoid.Climbing:connect(onClimbing)
|
||||
Humanoid.GettingUp:connect(onGettingUp)
|
||||
Humanoid.FreeFalling:connect(onFreeFall)
|
||||
Humanoid.FallingDown:connect(onFallingDown)
|
||||
Humanoid.Seated:connect(onSeated)
|
||||
Humanoid.PlatformStanding:connect(onPlatformStanding)
|
||||
Humanoid.Swimming:connect(onSwimming)
|
||||
|
||||
-- setup emote chat hook
|
||||
game.Players.LocalPlayer.Chatted:connect(function(msg)
|
||||
local emote = ""
|
||||
if msg == "/e dance" then
|
||||
emote = dances[math.random(1, #dances)]
|
||||
elseif (string.sub(msg, 1, 3) == "/e ") then
|
||||
emote = string.sub(msg, 4)
|
||||
elseif (string.sub(msg, 1, 7) == "/emote ") then
|
||||
emote = string.sub(msg, 8)
|
||||
end
|
||||
|
||||
if (pose == "Standing" and emoteNames[emote] ~= nil) then
|
||||
playAnimation(emote, 0.1, Humanoid)
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
|
||||
-- main program
|
||||
|
||||
local runService = game:service("RunService");
|
||||
|
||||
-- initialize to idle
|
||||
playAnimation("idle", 0.1, Humanoid)
|
||||
pose = "Standing"
|
||||
|
||||
while Figure.Parent~=nil do
|
||||
local _, time = wait(0.1)
|
||||
move(time)
|
||||
end
|
||||
|
||||
|
||||
]]> </ProtectedString>
|
||||
</Properties>
|
||||
<Item class="StringValue" referent="RBX3D115054235C475E9E23460AF948BD6F">
|
||||
<Properties>
|
||||
<string name="Name">idle</string>
|
||||
<string name="Value"></string>
|
||||
</Properties>
|
||||
<Item class="Animation" referent="RBXDB67065FB85E4931999CB515B5F2012A">
|
||||
<Properties>
|
||||
<Content name="AnimationId">
|
||||
<url>ayaasset://avatar/animations/idle0.rbxm</url>
|
||||
</Content>
|
||||
<string name="Name">Animation1</string>
|
||||
</Properties>
|
||||
<Item class="NumberValue" referent="RBX9C1D89D976924979BDD8B81DA97BE114">
|
||||
<Properties>
|
||||
<string name="Name">Weight</string>
|
||||
<double name="Value">9</double>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="Animation" referent="RBXEEE171AA4C1C4802A98EA849C0B0A8AC">
|
||||
<Properties>
|
||||
<Content name="AnimationId">
|
||||
<url>ayaasset://avatar/animations/idle1.rbxm</url>
|
||||
</Content>
|
||||
<string name="Name">Animation2</string>
|
||||
</Properties>
|
||||
<Item class="NumberValue" referent="RBX37B140D9414C4473A5F27F7880B0EC4E">
|
||||
<Properties>
|
||||
<string name="Name">Weight</string>
|
||||
<double name="Value">1</double>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="StringValue" referent="RBX6B0595F7D6464E039C6C20310AF91669">
|
||||
<Properties>
|
||||
<string name="Name">walk</string>
|
||||
<string name="Value"></string>
|
||||
</Properties>
|
||||
<Item class="Animation" referent="RBX45D6152C54FA4EF7B0F9CBF069550557">
|
||||
<Properties>
|
||||
<Content name="AnimationId">
|
||||
<url>ayaasset://avatar/animations/walk.rbxm</url>
|
||||
</Content>
|
||||
<string name="Name">WalkAnim</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="StringValue" referent="RBX304A801B2F904AA59F892145C3DA51F4">
|
||||
<Properties>
|
||||
<string name="Name">run</string>
|
||||
<string name="Value"></string>
|
||||
</Properties>
|
||||
<Item class="Animation" referent="RBXA37336981B6E454C90E45A7F01515966">
|
||||
<Properties>
|
||||
<Content name="AnimationId">
|
||||
<url>ayaasset://avatar/animations/walk.rbxm</url>
|
||||
</Content>
|
||||
<string name="Name">RunAnim</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="StringValue" referent="RBX992310CD075D4083AA3FC397200F0E12">
|
||||
<Properties>
|
||||
<string name="Name">jump</string>
|
||||
<string name="Value"></string>
|
||||
</Properties>
|
||||
<Item class="Animation" referent="RBXDB0FB6EAF0A94640AD7C222F7E4E39F4">
|
||||
<Properties>
|
||||
<Content name="AnimationId">
|
||||
<url>ayaasset://avatar/animations/jump.rbxm</url>
|
||||
</Content>
|
||||
<string name="Name">JumpAnim</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="StringValue" referent="RBXE784B068E17041EDBE1C80F73A8FB305">
|
||||
<Properties>
|
||||
<string name="Name">climb</string>
|
||||
<string name="Value"></string>
|
||||
</Properties>
|
||||
<Item class="Animation" referent="RBX94C1F5C954294A889B341487BAC89356">
|
||||
<Properties>
|
||||
<Content name="AnimationId">
|
||||
<url>ayaasset://avatar/animations/climb.rbxm</url>
|
||||
</Content>
|
||||
<string name="Name">ClimbAnim</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="StringValue" referent="RBX40FB7BAC1B514D918FD0D59D70A13401">
|
||||
<Properties>
|
||||
<string name="Name">toolnone</string>
|
||||
<string name="Value"></string>
|
||||
</Properties>
|
||||
<Item class="Animation" referent="RBX6B27C35810754C93915CA4FE34E8EB95">
|
||||
<Properties>
|
||||
<Content name="AnimationId">
|
||||
<url>ayaasset://avatar/animations/toolnone.rbxm</url>
|
||||
</Content>
|
||||
<string name="Name">ToolNoneAnim</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="StringValue" referent="RBX9D56FC8B85B240089A73C4C0BF994681">
|
||||
<Properties>
|
||||
<string name="Name">fall</string>
|
||||
<string name="Value"></string>
|
||||
</Properties>
|
||||
<Item class="Animation" referent="RBX0766704DC00944A88D7F0204B7AD2177">
|
||||
<Properties>
|
||||
<Content name="AnimationId">
|
||||
<url>ayaasset://avatar/animations/fall.rbxm</url>
|
||||
</Content>
|
||||
<string name="Name">FallAnim</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
<Item class="StringValue" referent="RBXCE77F4BD43F74ECE8CEC4CB497927D27">
|
||||
<Properties>
|
||||
<string name="Name">sit</string>
|
||||
<string name="Value"></string>
|
||||
</Properties>
|
||||
<Item class="Animation" referent="RBXBEBAA19B49FE45FB9D852B2290377C2C">
|
||||
<Properties>
|
||||
<Content name="AnimationId">
|
||||
<url>ayaasset://avatar/animations/sit.rbxm</url>
|
||||
</Content>
|
||||
<string name="Name">SitAnim</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</Item>
|
||||
</roblox>
|
||||
BIN
client/common/content/avatar/scripts/humanoidAnimateR15.rbxm
Normal file
BIN
client/common/content/avatar/scripts/humanoidAnimateR15.rbxm
Normal file
Binary file not shown.
466
client/common/content/avatar/scripts/humanoidSound.rbxmx
Normal file
466
client/common/content/avatar/scripts/humanoidSound.rbxmx
Normal file
@@ -0,0 +1,466 @@
|
||||
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="4">
|
||||
<External>null</External>
|
||||
<External>nil</External>
|
||||
<Item class="Script" referent="RBX440EE2113E074565A1C69E447652B15D">
|
||||
<Properties>
|
||||
<bool name="Disabled">false</bool>
|
||||
<Content name="LinkedSource">
|
||||
<null></null>
|
||||
</Content>
|
||||
<string name="Name">Sound</string>
|
||||
<ProtectedString name="Source"><![CDATA[---This server script creates the sounds and also exists so that it can be easily copied into an NPC and create sounds for that NPC.
|
||||
--Remove the local script if you copy this into an NPC.
|
||||
|
||||
function waitForChild(parent, childName)
|
||||
local child = parent:findFirstChild(childName)
|
||||
if child then return child end
|
||||
while true do
|
||||
child = parent.ChildAdded:wait()
|
||||
if child.Name==childName then return child end
|
||||
end
|
||||
end
|
||||
|
||||
function newSound(name, id)
|
||||
local sound = Instance.new("Sound")
|
||||
sound.SoundId = id
|
||||
sound.Name = name
|
||||
sound.archivable = false
|
||||
sound.Parent = script.Parent.Head
|
||||
return sound
|
||||
end
|
||||
|
||||
-- declarations
|
||||
|
||||
local sGettingUp = newSound("GettingUp", "ayaasset://sounds/action_get_up.mp3")
|
||||
local sDied = newSound("Died", "ayaasset://sounds/uuhhh.mp3")
|
||||
local sFreeFalling = newSound("FreeFalling", "ayaasset://sounds/action_falling.mp3")
|
||||
local sJumping = newSound("Jumping", "ayaasset://sounds/action_jump.mp3")
|
||||
local sLanding = newSound("Landing", "ayaasset://sounds/action_jump_land.mp3")
|
||||
local sSplash = newSound("Splash", "ayaasset://sounds/impact_water.mp3")
|
||||
local sRunning = newSound("Running", "ayaasset://sounds/action_footsteps_plastic.mp3")
|
||||
sRunning.Looped = true
|
||||
local sSwimming = newSound("Swimming", "ayaasset://sounds/action_swim.mp3")
|
||||
sSwimming.Looped = true
|
||||
local sClimbing = newSound("Climbing", "ayaasset://sounds/action_footsteps_plastic.mp3")
|
||||
sClimbing.Looped = true
|
||||
|
||||
local classic_sFallingDown = newSound("classic_FallingDown", "ayaasset://sounds/splat.mp3")
|
||||
local classic_sFreeFalling = newSound("classic_FreeFalling", "ayaasset://sounds/swoosh.mp3")
|
||||
local classic_sGettingUp = newSound("classic_GettingUp", "ayaasset://sounds/hit.mp3")
|
||||
local classic_sJumping = newSound("classic_Jumping", "ayaasset://sounds/button.mp3")
|
||||
local classic_sRunning = newSound("classic_Running", "ayaasset://sounds/bfsl-minifigfoots1.mp3")
|
||||
classic_sRunning.Looped = true
|
||||
|
||||
local GameSettings = UserSettings().GameSettings
|
||||
local useClassicSounds = GameSettings.VirtualVersion == Enum.VirtualVersion['2012'] or GameSettings.VirtualVersion == Enum.VirtualVersion['2013']
|
||||
|
||||
local Figure = script.Parent
|
||||
local Head = waitForChild(Figure, "Head")
|
||||
local Humanoid = waitForChild(Figure, "Humanoid")
|
||||
local hasPlayer = game.Players:GetPlayerFromCharacter(script.Parent)
|
||||
local filteringEnabled = game.Workspace.FilteringEnabled
|
||||
|
||||
local prevState = "None"
|
||||
|
||||
-- functions
|
||||
|
||||
function onDied()
|
||||
stopLoopedSounds()
|
||||
sDied:Play()
|
||||
end
|
||||
|
||||
local fallCount = 0
|
||||
local fallSpeed = 0
|
||||
function onStateFall(state, sound)
|
||||
fallCount = fallCount + 1
|
||||
if state then
|
||||
sound.Volume = 0
|
||||
sound:Play()
|
||||
Spawn( function()
|
||||
local t = 0
|
||||
local thisFall = fallCount
|
||||
while t < 1.5 and fallCount == thisFall do
|
||||
local vol = math.max(t - 0.3 , 0)
|
||||
sound.Volume = vol
|
||||
wait(0.1)
|
||||
t = t + 0.1
|
||||
end
|
||||
end)
|
||||
else
|
||||
sound:Stop()
|
||||
end
|
||||
fallSpeed = math.max(fallSpeed, math.abs(Head.Velocity.Y))
|
||||
end
|
||||
|
||||
|
||||
function onStateNoStop(state, sound)
|
||||
if state then
|
||||
sound:Play()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function onRunning(speed)
|
||||
if useClassicSounds then
|
||||
if speed > 0.01 then
|
||||
classic_sRunning:Play()
|
||||
else
|
||||
classic_sRunning:Pause()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
sClimbing:Stop()
|
||||
sSwimming:Stop()
|
||||
if (prevState == "FreeFall" and fallSpeed > 0.1) then
|
||||
local vol = math.min(1.0, math.max(0.0, (fallSpeed - 50) / 110))
|
||||
sLanding.Volume = vol
|
||||
sLanding:Play()
|
||||
fallSpeed = 0
|
||||
end
|
||||
if speed>0.5 then
|
||||
sRunning:Play()
|
||||
sRunning.Pitch = speed / 8.0
|
||||
else
|
||||
sRunning:Stop()
|
||||
end
|
||||
prevState = "Run"
|
||||
end
|
||||
|
||||
function onSwimming(speed)
|
||||
if (prevState ~= "Swim" and speed > 0.1) then
|
||||
local volume = math.min(1.0, speed / 350)
|
||||
sSplash.Volume = volume
|
||||
sSplash:Play()
|
||||
prevState = "Swim"
|
||||
end
|
||||
sClimbing:Stop()
|
||||
sRunning:Stop()
|
||||
sSwimming.Pitch = 1.6
|
||||
sSwimming:Play()
|
||||
end
|
||||
|
||||
function onClimbing(speed)
|
||||
sRunning:Stop()
|
||||
sSwimming:Stop()
|
||||
if speed>0.01 then
|
||||
sClimbing:Play()
|
||||
sClimbing.Pitch = speed / 5.5
|
||||
else
|
||||
sClimbing:Stop()
|
||||
end
|
||||
prevState = "Climb"
|
||||
end
|
||||
-- connect up
|
||||
|
||||
function stopLoopedSounds()
|
||||
sRunning:Stop()
|
||||
sClimbing:Stop()
|
||||
sSwimming:Stop()
|
||||
end
|
||||
|
||||
function onState(state, sound)
|
||||
if state then
|
||||
sound:Play()
|
||||
end
|
||||
end
|
||||
|
||||
if hasPlayer == nil then
|
||||
Humanoid.Died:connect(onDied)
|
||||
Humanoid.Running:connect(onRunning)
|
||||
Humanoid.Swimming:connect(onSwimming)
|
||||
Humanoid.Climbing:connect(onClimbing)
|
||||
Humanoid.Jumping:connect(function(state)
|
||||
if useClassicSounds then
|
||||
onState(state, classic_sJumping)
|
||||
else
|
||||
onStateNoStop(state, sJumping)
|
||||
prevState = "Jump"
|
||||
end
|
||||
end)
|
||||
|
||||
Humanoid.GettingUp:connect(function(state)
|
||||
if useClassicSounds then
|
||||
onState(state, classic_sGettingUp)
|
||||
else
|
||||
stopLoopedSounds()
|
||||
onStateNoStop(state, sGettingUp)
|
||||
prevState = "GetUp"
|
||||
end
|
||||
end)
|
||||
|
||||
Humanoid.FreeFalling:connect(function(state)
|
||||
if useClassicSounds then
|
||||
onState(state, classic_sFreeFalling)
|
||||
|
||||
if classic_sJumping.IsPlaying then
|
||||
classic_sJumping:Stop()
|
||||
end
|
||||
else
|
||||
stopLoopedSounds()
|
||||
onStateFall(state, sFreeFalling)
|
||||
prevState = "FreeFall"
|
||||
end
|
||||
end)
|
||||
|
||||
Humanoid.FallingDown:connect(function(state)
|
||||
if useClassicSounds then
|
||||
onState(state, classic_sFallingDown)
|
||||
else
|
||||
stopLoopedSounds()
|
||||
end
|
||||
end)
|
||||
|
||||
Humanoid.StateChanged:connect(function(old, new)
|
||||
if not (new.Name == "Dead" or
|
||||
new.Name == "Running" or
|
||||
new.Name == "RunningNoPhysics" or
|
||||
new.Name == "Swimming" or
|
||||
new.Name == "Jumping" or
|
||||
new.Name == "GettingUp" or
|
||||
new.Name == "Freefall" or
|
||||
new.Name == "FallingDown") and not useClassicSounds then
|
||||
stopLoopedSounds()
|
||||
end
|
||||
end)
|
||||
|
||||
GameSettings.Changed:connect(function(property)
|
||||
if property == "VirtualVersion" then
|
||||
useClassicSounds = GameSettings.VirtualVersion == Enum.VirtualVersion['2012'] or GameSettings.VirtualVersion == Enum.VirtualVersion['2013']
|
||||
if useClassicSounds then
|
||||
stopLoopedSounds()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
]]> </ProtectedString>
|
||||
</Properties>
|
||||
<Item class="LocalScript" referent="RBXACC3E7AAF68642CC9341039CBCE06F78">
|
||||
<Properties>
|
||||
<bool name="Disabled">false</bool>
|
||||
<Content name="LinkedSource">
|
||||
<null></null>
|
||||
</Content>
|
||||
<string name="Name">LocalSound</string>
|
||||
<ProtectedString name="Source"><![CDATA[--This local script will run only for the player whos character it is in. It's changes to the sounds will replicate as they are changes to the character.
|
||||
-- util
|
||||
|
||||
function waitForChild(parent, childName)
|
||||
local child = parent:findFirstChild(childName)
|
||||
if child then return child end
|
||||
while true do
|
||||
child = parent.ChildAdded:wait()
|
||||
if child.Name==childName then return child end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- declarations
|
||||
|
||||
local Figure = script.Parent.Parent
|
||||
local Head = waitForChild(Figure, "Head")
|
||||
local Humanoid = waitForChild(Figure, "Humanoid")
|
||||
|
||||
local sGettingUp = waitForChild(Head, "GettingUp")
|
||||
local sDied = waitForChild(Head, "Died")
|
||||
local sFreeFalling = waitForChild(Head, "FreeFalling")
|
||||
local sJumping = waitForChild(Head, "Jumping")
|
||||
local sLanding = waitForChild(Head, "Landing")
|
||||
local sSplash = waitForChild(Head, "Splash")
|
||||
local sRunning = waitForChild(Head, "Running")
|
||||
sRunning.Looped = true
|
||||
local sSwimming = waitForChild(Head, "Swimming")
|
||||
sSwimming.Looped = true
|
||||
local sClimbing =waitForChild(Head, "Climbing")
|
||||
sClimbing.Looped = true
|
||||
|
||||
local classic_sFallingDown = waitForChild(Head, "classic_FallingDown")
|
||||
local classic_sFreeFalling = waitForChild(Head, "classic_FreeFalling")
|
||||
local classic_sGettingUp = waitForChild(Head, "classic_GettingUp")
|
||||
local classic_sJumping = waitForChild(Head, "classic_Jumping")
|
||||
local classic_sRunning = waitForChild(Head, "classic_Running")
|
||||
classic_sRunning.Looped = true
|
||||
|
||||
local GameSettings = UserSettings().GameSettings
|
||||
local useClassicSounds = GameSettings.VirtualVersion == Enum.VirtualVersion['2012'] or GameSettings.VirtualVersion == Enum.VirtualVersion['2013']
|
||||
|
||||
local prevState = "None"
|
||||
|
||||
-- functions
|
||||
|
||||
function onDied()
|
||||
stopLoopedSounds()
|
||||
sDied:Play()
|
||||
end
|
||||
|
||||
local fallCount = 0
|
||||
local fallSpeed = 0
|
||||
function onStateFall(state, sound)
|
||||
fallCount = fallCount + 1
|
||||
if state then
|
||||
sound.Volume = 0
|
||||
sound:Play()
|
||||
Spawn( function()
|
||||
local t = 0
|
||||
local thisFall = fallCount
|
||||
while t < 1.5 and fallCount == thisFall do
|
||||
local vol = math.max(t - 0.3 , 0)
|
||||
sound.Volume = vol
|
||||
wait(0.1)
|
||||
t = t + 0.1
|
||||
end
|
||||
end)
|
||||
else
|
||||
sound:Stop()
|
||||
end
|
||||
fallSpeed = math.max(fallSpeed, math.abs(Head.Velocity.Y))
|
||||
end
|
||||
|
||||
|
||||
function onStateNoStop(state, sound)
|
||||
if state then
|
||||
sound:Play()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function onRunning(speed)
|
||||
if useClassicSounds then
|
||||
if speed > 0.01 then
|
||||
classic_sRunning:Play()
|
||||
else
|
||||
classic_sRunning:Pause()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
sClimbing:Stop()
|
||||
sSwimming:Stop()
|
||||
if (prevState == "FreeFall" and fallSpeed > 0.1) then
|
||||
local vol = math.min(1.0, math.max(0.0, (fallSpeed - 50) / 110))
|
||||
sLanding.Volume = vol
|
||||
sLanding:Play()
|
||||
fallSpeed = 0
|
||||
end
|
||||
if speed>0.5 then
|
||||
sRunning:Play()
|
||||
sRunning.Pitch = speed / 8.0
|
||||
else
|
||||
sRunning:Stop()
|
||||
end
|
||||
prevState = "Run"
|
||||
end
|
||||
|
||||
function onSwimming(speed)
|
||||
if (prevState ~= "Swim" and speed > 0.1) then
|
||||
local volume = math.min(1.0, speed / 350)
|
||||
sSplash.Volume = volume
|
||||
sSplash:Play()
|
||||
prevState = "Swim"
|
||||
end
|
||||
sClimbing:Stop()
|
||||
sRunning:Stop()
|
||||
sSwimming.Pitch = 1.6
|
||||
sSwimming:Play()
|
||||
end
|
||||
|
||||
function onClimbing(speed)
|
||||
sRunning:Stop()
|
||||
sSwimming:Stop()
|
||||
if speed>0.01 then
|
||||
sClimbing:Play()
|
||||
sClimbing.Pitch = speed / 5.5
|
||||
else
|
||||
sClimbing:Stop()
|
||||
end
|
||||
prevState = "Climb"
|
||||
end
|
||||
-- connect up
|
||||
|
||||
function stopLoopedSounds()
|
||||
sRunning:Stop()
|
||||
sClimbing:Stop()
|
||||
sSwimming:Stop()
|
||||
end
|
||||
|
||||
function onState(state, sound)
|
||||
if state then
|
||||
sound:Play()
|
||||
end
|
||||
end
|
||||
|
||||
Humanoid.Died:connect(onDied)
|
||||
Humanoid.Running:connect(onRunning)
|
||||
Humanoid.Swimming:connect(onSwimming)
|
||||
Humanoid.Climbing:connect(onClimbing)
|
||||
Humanoid.Jumping:connect(function(state)
|
||||
if useClassicSounds then
|
||||
onState(state, classic_sJumping)
|
||||
else
|
||||
onStateNoStop(state, sJumping)
|
||||
prevState = "Jump"
|
||||
end
|
||||
end)
|
||||
|
||||
Humanoid.GettingUp:connect(function(state)
|
||||
if useClassicSounds then
|
||||
onState(state, classic_sGettingUp)
|
||||
else
|
||||
stopLoopedSounds()
|
||||
onStateNoStop(state, sGettingUp)
|
||||
prevState = "GetUp"
|
||||
end
|
||||
end)
|
||||
|
||||
Humanoid.FreeFalling:connect(function(state)
|
||||
if useClassicSounds then
|
||||
if classic_sJumping.IsPlaying then
|
||||
classic_sJumping:Stop()
|
||||
end
|
||||
|
||||
onState(state, classic_sFreeFalling)
|
||||
else
|
||||
stopLoopedSounds()
|
||||
onStateFall(state, sFreeFalling)
|
||||
prevState = "FreeFall"
|
||||
end
|
||||
end)
|
||||
|
||||
Humanoid.FallingDown:connect(function(state)
|
||||
if useClassicSounds then
|
||||
onState(state, classic_sFallingDown)
|
||||
else
|
||||
stopLoopedSounds()
|
||||
end
|
||||
end)
|
||||
|
||||
Humanoid.StateChanged:connect(function(old, new)
|
||||
if not (new.Name == "Dead" or
|
||||
new.Name == "Running" or
|
||||
new.Name == "RunningNoPhysics" or
|
||||
new.Name == "Swimming" or
|
||||
new.Name == "Jumping" or
|
||||
new.Name == "GettingUp" or
|
||||
new.Name == "Freefall" or
|
||||
new.Name == "FallingDown") and not useClassicSounds then
|
||||
stopLoopedSounds()
|
||||
end
|
||||
end)
|
||||
|
||||
GameSettings.Changed:connect(function(property)
|
||||
if property == "VirtualVersion" then
|
||||
useClassicSounds = GameSettings.VirtualVersion == Enum.VirtualVersion['2012'] or GameSettings.VirtualVersion == Enum.VirtualVersion['2013']
|
||||
if useClassicSounds then
|
||||
stopLoopedSounds()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
]]> </ProtectedString>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</roblox>
|
||||
BIN
client/common/content/fonts/AccanthisADFStd-Regular.otf
Normal file
BIN
client/common/content/fonts/AccanthisADFStd-Regular.otf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/AmaticSC-Bold.ttf
Normal file
BIN
client/common/content/fonts/AmaticSC-Bold.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/AmaticSC-Regular.ttf
Normal file
BIN
client/common/content/fonts/AmaticSC-Regular.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/Balthazar-Regular.ttf
Normal file
BIN
client/common/content/fonts/Balthazar-Regular.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/Bangers-Regular.ttf
Normal file
BIN
client/common/content/fonts/Bangers-Regular.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/COMIC.ttf
Normal file
BIN
client/common/content/fonts/COMIC.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/CONSOLAS.TTF
Normal file
BIN
client/common/content/fonts/CONSOLAS.TTF
Normal file
Binary file not shown.
BIN
client/common/content/fonts/ComicNeue-Angular-Bold.ttf
Normal file
BIN
client/common/content/fonts/ComicNeue-Angular-Bold.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/Creepster-Regular.ttf
Normal file
BIN
client/common/content/fonts/Creepster-Regular.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/DenkOne-Regular.ttf
Normal file
BIN
client/common/content/fonts/DenkOne-Regular.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/Fondamento-Italic.ttf
Normal file
BIN
client/common/content/fonts/Fondamento-Italic.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/Fondamento-Regular.ttf
Normal file
BIN
client/common/content/fonts/Fondamento-Regular.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/FredokaOne-Regular.ttf
Normal file
BIN
client/common/content/fonts/FredokaOne-Regular.ttf
Normal file
Binary file not shown.
BIN
client/common/content/fonts/GothamSSm-Black.otf
Normal file
BIN
client/common/content/fonts/GothamSSm-Black.otf
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user