mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-05-23 07:12:24 +00:00
Initial work on LUA scripting.
This LUA scripting implementation uses the sol header only C++ wrapper for the native LUA libraries. The API does not follow the original LU scripting. Each instance of a script is in its own LUA-State, and has 'self' as a global. There are hooks to all the implemented CppScript methods, as well as a subset of the entity functionallity. Has to be expanded upon. This is local work which has been sitting for awhile; thought someone might like to take a look at it.
This commit is contained in:
parent
a0a9936e47
commit
5f689104af
@ -209,6 +209,14 @@ include_directories(${PROJECT_SOURCE_DIR}/thirdparty/cpplinq/)
|
|||||||
include_directories(${PROJECT_SOURCE_DIR}/dNet/)
|
include_directories(${PROJECT_SOURCE_DIR}/dNet/)
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dScripts/)
|
include_directories(${PROJECT_SOURCE_DIR}/dScripts/)
|
||||||
|
|
||||||
|
# Link dGame to LUA
|
||||||
|
if(__include_lua__)
|
||||||
|
find_package(Lua REQUIRED)
|
||||||
|
|
||||||
|
include_directories(/usr/include ${LUA_INCLUDE_DIR})
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/dLua/)
|
||||||
|
endif(UNIX)
|
||||||
|
|
||||||
# Default to linking to libmysql
|
# Default to linking to libmysql
|
||||||
set(MYSQL_LIB mysql)
|
set(MYSQL_LIB mysql)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
@ -355,6 +363,19 @@ ${PROJECT_SOURCE_DIR}/dGame/dUtilities/*.cpp
|
|||||||
${PROJECT_SOURCE_DIR}/dScripts/*.cpp
|
${PROJECT_SOURCE_DIR}/dScripts/*.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# If we are including LUA, include the dLua files in dGame
|
||||||
|
if(__include_lua__)
|
||||||
|
file(
|
||||||
|
GLOB SOURCES_DLUA
|
||||||
|
LIST_DIRECTORIES false
|
||||||
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
${PROJECT_SOURCE_DIR}/dLua/*.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Append the dLua files to the dGame files
|
||||||
|
set(SOURCES_DGAME ${SOURCES_DGAME} ${SOURCES_DLUA})
|
||||||
|
endif(__include_lua__)
|
||||||
|
|
||||||
# Source Code for dZoneManager
|
# Source Code for dZoneManager
|
||||||
file(
|
file(
|
||||||
GLOB SOURCES_DZM
|
GLOB SOURCES_DZM
|
||||||
@ -466,6 +487,15 @@ target_link_libraries(ChatServer pthread)
|
|||||||
target_link_libraries(ChatServer dl)
|
target_link_libraries(ChatServer dl)
|
||||||
endif(UNIX)
|
endif(UNIX)
|
||||||
|
|
||||||
|
# Link dGame to LUA
|
||||||
|
if(__include_lua__)
|
||||||
|
find_package(Lua REQUIRED)
|
||||||
|
|
||||||
|
target_link_libraries(dGame ${LUA_LIBRARIES})
|
||||||
|
|
||||||
|
message(STATUS "Linking dGame to LUA " ${LUA_LIBRARIES})
|
||||||
|
endif(UNIX)
|
||||||
|
|
||||||
# Compiler flags:
|
# Compiler flags:
|
||||||
# Disabled deprecated warnings as the MySQL includes have deprecated code in them.
|
# Disabled deprecated warnings as the MySQL includes have deprecated code in them.
|
||||||
# Disabled misleading indentation as DL_LinkedList from RakNet has a weird indent.
|
# Disabled misleading indentation as DL_LinkedList from RakNet has a weird indent.
|
||||||
|
@ -63,6 +63,12 @@
|
|||||||
#include "GameConfig.h"
|
#include "GameConfig.h"
|
||||||
#include "ScriptedActivityComponent.h"
|
#include "ScriptedActivityComponent.h"
|
||||||
|
|
||||||
|
#if __include_lua__ == 1
|
||||||
|
#include "LuaScript.h"
|
||||||
|
#include "ScriptComponent.h"
|
||||||
|
#include <filesystem>
|
||||||
|
#endif
|
||||||
|
|
||||||
void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr) {
|
void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr) {
|
||||||
std::string chatCommand;
|
std::string chatCommand;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
@ -614,6 +620,78 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __include_lua__ == 1
|
||||||
|
if (chatCommand == "lua" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() >= 1) {
|
||||||
|
std::string input = "";
|
||||||
|
|
||||||
|
// If the first argument is "load", load the file
|
||||||
|
bool isFile = false;
|
||||||
|
if (args[0] == "load") {
|
||||||
|
isFile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join the args
|
||||||
|
for (size_t i = 0; i < args.size(); i++) {
|
||||||
|
if (i == 0 && isFile) continue;
|
||||||
|
input += args[i] + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// If isFile is true, load the file
|
||||||
|
if (isFile) {
|
||||||
|
// Trim last space
|
||||||
|
input.pop_back();
|
||||||
|
|
||||||
|
std::string path = input;
|
||||||
|
|
||||||
|
std::ifstream infile(path);
|
||||||
|
|
||||||
|
std::stringstream buffer;
|
||||||
|
|
||||||
|
if (infile.is_open()) {
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(infile, line)) {
|
||||||
|
buffer << line << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ChatPackets::SendSystemMessage(sysAddr, u"Could not open file " + GeneralUtils::ASCIIToUTF16(path));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input = buffer.str();
|
||||||
|
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaScript* lua = new LuaScript(LuaTerminateBehavior::ResetScriptAndDelete);
|
||||||
|
|
||||||
|
ScriptComponent* script = entity->GetComponent<ScriptComponent>();
|
||||||
|
|
||||||
|
if (script == nullptr) {
|
||||||
|
script = new ScriptComponent(entity, false);
|
||||||
|
|
||||||
|
entity->AddComponent(ScriptComponent::ComponentType, script);
|
||||||
|
}
|
||||||
|
|
||||||
|
script->SetScript(lua);
|
||||||
|
|
||||||
|
lua->SetEntity(entity);
|
||||||
|
|
||||||
|
// Run the code, and print any errors
|
||||||
|
try {
|
||||||
|
lua->Script(input);
|
||||||
|
}
|
||||||
|
// Catch sol::error
|
||||||
|
catch (const sol::error& e) {
|
||||||
|
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(e.what()));
|
||||||
|
}
|
||||||
|
// Catch *any* error
|
||||||
|
catch (...) {
|
||||||
|
ChatPackets::SendSystemMessage(sysAddr, u"Unknown error!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (chatCommand == "addmission" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
|
if (chatCommand == "addmission" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
|
||||||
if (args.size() == 0) return;
|
if (args.size() == 0) return;
|
||||||
|
|
||||||
|
135
dLua/LuaScript.cpp
Normal file
135
dLua/LuaScript.cpp
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#include "LuaScript.h"
|
||||||
|
|
||||||
|
#include "Entity.h"
|
||||||
|
#include "lCommonTypes.h"
|
||||||
|
#include "lEntity.h"
|
||||||
|
#include "ChatPackets.h"
|
||||||
|
#include "CppScripts.h"
|
||||||
|
#include "ScriptComponent.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
|
||||||
|
LuaScript::LuaScript(LuaTerminateBehavior terminateBehavior)
|
||||||
|
{
|
||||||
|
m_TerminateBehavior = terminateBehavior;
|
||||||
|
m_Hooks = 0;
|
||||||
|
m_Terminating = false;
|
||||||
|
|
||||||
|
m_State = sol::state();
|
||||||
|
|
||||||
|
m_State.open_libraries(sol::lib::base, sol::lib::package);
|
||||||
|
|
||||||
|
lCommonTypes::RegisterClass(this);
|
||||||
|
lEntity::RegisterClass(this);
|
||||||
|
|
||||||
|
// Register a function to print to log
|
||||||
|
m_State.set_function("print", [](const std::string& message) {
|
||||||
|
Game::logger->Log("dLua", "%s\n", message.c_str());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register a function to terminate the script
|
||||||
|
m_State.set_function("terminate", [this]() {
|
||||||
|
m_Terminating = true;
|
||||||
|
|
||||||
|
auto* scriptComponent = GetEntity()->GetComponent<ScriptComponent>();
|
||||||
|
|
||||||
|
if (scriptComponent == nullptr || scriptComponent->GetScript() != this)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_TerminateBehavior)
|
||||||
|
{
|
||||||
|
case LuaTerminateBehavior::None:
|
||||||
|
break;
|
||||||
|
case LuaTerminateBehavior::ResetScript:
|
||||||
|
case LuaTerminateBehavior::ResetScriptAndDelete:
|
||||||
|
scriptComponent->SetScript(CppScripts::GetInvalidScript());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register a function to add a callback timer
|
||||||
|
m_State.set_function("addCallbackTimer", [this](float seconds, sol::function callback) {
|
||||||
|
AddCallbackTimer(seconds, callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::state& LuaScript::GetState()
|
||||||
|
{
|
||||||
|
return m_State;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaScript::Script(const std::string& script)
|
||||||
|
{
|
||||||
|
m_State.script(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaScript::SetEntity(Entity* entity)
|
||||||
|
{
|
||||||
|
m_State["self"] = lEntity(entity->GetObjectID());
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* LuaScript::GetEntity()
|
||||||
|
{
|
||||||
|
lEntity entity = m_State["self"];
|
||||||
|
|
||||||
|
return dLua::GetEntityOrThrow(entity.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaScript::AddCallbackTimer(float seconds, sol::function callback) {
|
||||||
|
if (m_Terminating) {
|
||||||
|
Game::logger->Log("LuaScript", "Script is terminating, ignoring addCallbackTimer\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Hooks++;
|
||||||
|
|
||||||
|
GetEntity()->AddCallbackTimer(seconds, [this, callback]() {
|
||||||
|
m_Hooks--;
|
||||||
|
|
||||||
|
CheckHooks();
|
||||||
|
|
||||||
|
if (m_Terminating) {
|
||||||
|
Game::logger->Log("LuaScript", "Script is terminating, ignoring callback\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
catch (sol::error& e) {
|
||||||
|
Game::logger->Log("LuaScript", "Error in callback: %s\n", e.what());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaScript::CheckHooks()
|
||||||
|
{
|
||||||
|
if (m_Hooks != 0 || m_AttemptingToFinalize || !m_Terminating) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_AttemptingToFinalize = true;
|
||||||
|
|
||||||
|
// Attempt to finalize the script in 1 second
|
||||||
|
GetEntity()->AddCallbackTimer(1.0f, [this]() {
|
||||||
|
AttemptToFinalize();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaScript::AttemptToFinalize()
|
||||||
|
{
|
||||||
|
if (m_Hooks != 0) {
|
||||||
|
m_AttemptingToFinalize = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_TerminateBehavior)
|
||||||
|
{
|
||||||
|
case LuaTerminateBehavior::ResetScriptAndDelete:
|
||||||
|
Game::logger->Log("LuaScript", "Deleting script\n");
|
||||||
|
delete this;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
426
dLua/LuaScript.h
Normal file
426
dLua/LuaScript.h
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
#include "dLua.h"
|
||||||
|
|
||||||
|
#include "CppScripts.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
#include "LuaTerminateBehavior.h"
|
||||||
|
#include "lEntity.h"
|
||||||
|
|
||||||
|
class Entity;
|
||||||
|
|
||||||
|
class LuaScript : public CppScripts::Script
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
sol::state m_State;
|
||||||
|
|
||||||
|
LuaTerminateBehavior m_TerminateBehavior;
|
||||||
|
|
||||||
|
int32_t m_Hooks;
|
||||||
|
|
||||||
|
bool m_Terminating;
|
||||||
|
|
||||||
|
bool m_AttemptingToFinalize;
|
||||||
|
|
||||||
|
void CheckHooks();
|
||||||
|
|
||||||
|
void AttemptToFinalize();
|
||||||
|
|
||||||
|
public:
|
||||||
|
LuaScript(LuaTerminateBehavior terminateBehavior);
|
||||||
|
|
||||||
|
sol::state& GetState();
|
||||||
|
|
||||||
|
void Script(const std::string& script);
|
||||||
|
|
||||||
|
void SetEntity(Entity* entity);
|
||||||
|
|
||||||
|
Entity* GetEntity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a callback timer.
|
||||||
|
*/
|
||||||
|
void AddCallbackTimer(float seconds, sol::function callback);
|
||||||
|
|
||||||
|
template <typename F, typename ...Types>
|
||||||
|
void Invoke(F function, Types... args)
|
||||||
|
{
|
||||||
|
sol::function func = m_State[function];
|
||||||
|
|
||||||
|
if (!func.valid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
func(std::forward<Types>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======================================================================
|
||||||
|
// CppScripts::Script overrides
|
||||||
|
// ======================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked one frame after the script is loaded.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onStartup(self)'
|
||||||
|
*/
|
||||||
|
void OnStartup(Entity* self) override {
|
||||||
|
Invoke("onStartup");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked upon an entity entering the phantom collider on self.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onCollisionPhantom(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnCollisionPhantom(Entity* self, Entity* target) override {
|
||||||
|
Invoke("onCollisionPhantom", lEntity(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player accepted a mission.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onMissionDialogueOK(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) override {
|
||||||
|
Invoke("onMissionDialogueOK", lEntity(target), missionID, (int32_t) missionState);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when the client or the server invoked an event server-side.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onFireEventServerSide(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override {
|
||||||
|
Invoke("onFireEventServerSide", lEntity(sender), args, param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked upon sending a object notification.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onNotifyObject(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnNotifyObject(Entity *self, Entity *sender, const std::string& name, int32_t param1 = 0, int32_t param2 = 0) override {
|
||||||
|
Invoke("onNotifyObject", lEntity(sender), name, param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked upon a player exiting the modular build minigame.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onModularBuildExit(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnModularBuildExit(Entity* self, Entity* player, bool bCompleted, std::vector<LOT> modules) override {
|
||||||
|
Invoke("onModularBuildExit", lEntity(player), bCompleted, modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has loaded into the zone.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onPlayerLoaded(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnPlayerLoaded(Entity* self, Entity* player) override {
|
||||||
|
Invoke("onPlayerLoaded", lEntity(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has died.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onPlayerDied(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnPlayerDied(Entity* self, Entity* player) override {
|
||||||
|
Invoke("onPlayerDied", lEntity(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has resurrected.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onPlayerResurrected(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnPlayerResurrected(Entity* self, Entity* player) override {
|
||||||
|
Invoke("onPlayerResurrected", lEntity(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has left the zone.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onPlayerExit(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnPlayerExit(Entity* self, Entity* player) override {
|
||||||
|
Invoke("onPlayerExit", lEntity(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has interacted with the proximity collider on self.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onProximityUpdate(self, msg)'
|
||||||
|
*
|
||||||
|
* @param name The name of the proximity collider recviving an interaction.
|
||||||
|
* @param status "ENTER" if a player has entered the proximity collider; "LEAVE" if a player has left the proximity collider
|
||||||
|
*/
|
||||||
|
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override {
|
||||||
|
Invoke("onProximityUpdate", lEntity(entering), name, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a timer on self has expired.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onTimerDone(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnTimerDone(Entity* self, std::string timerName) override {
|
||||||
|
Invoke("onTimerDone", timerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player interactions with self.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onUse(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnUse(Entity* self, Entity* user) override {
|
||||||
|
Invoke("onUse", lEntity(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when self has died.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onDie(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnDie(Entity* self, Entity* killer) override {
|
||||||
|
Invoke("onDie", lEntity(killer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when self has received a hit.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onHit(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnHit(Entity* self, Entity* attacker) override {
|
||||||
|
Invoke("onHit", lEntity(attacker));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when self has received an emote from a player.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onEmoteReceived(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnEmoteReceived(Entity* self, int32_t emote, Entity* target) override {
|
||||||
|
Invoke("onEmoteReceived", emote, lEntity(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has started building this quickbuild.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onRebuildStart(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnRebuildStart(Entity* self, Entity* target) override {
|
||||||
|
Invoke("onRebuildStart", lEntity(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when this quickbuild has changed state.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onRebuildNotifyState(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnRebuildNotifyState(Entity* self, eRebuildState state) override {
|
||||||
|
Invoke("onRebuildNotifyState", (int32_t) state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when this quickbuild has been completed.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onRebuildComplete(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnRebuildComplete(Entity* self, Entity* target) override {
|
||||||
|
Invoke("onRebuildComplete", lEntity(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when self has received either a hit or heal.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onHitOrHealResult(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override {
|
||||||
|
Invoke("onHitOrHealResult", lEntity(attacker), damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has responsed to a mission.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onRespondToMission(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnRespondToMission(Entity* self, int missionID, Entity* player, int reward) override {
|
||||||
|
Invoke("onRespondToMission", missionID, lEntity(player), reward);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked once per frame.
|
||||||
|
*
|
||||||
|
* No LUA eqivalent.
|
||||||
|
*/
|
||||||
|
void OnUpdate(Entity* self) override {
|
||||||
|
Invoke("onUpdate");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when this property has been rented.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onZonePropertyRented(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnZonePropertyRented(Entity* self, Entity* renter) override {
|
||||||
|
Invoke("onZonePropertyRented", lEntity(renter));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has begun to edit this property.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onZonePropertyEditBegin(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnZonePropertyEditBegin(Entity* self) override {
|
||||||
|
Invoke("onZonePropertyEditBegin");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has concluded editing this property.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onZonePropertyEditEnd(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnZonePropertyEditEnd(Entity* self) override {
|
||||||
|
Invoke("onZonePropertyEditEnd");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has equipped a model while editing this property.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onZonePropertyModelEquipped(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnZonePropertyModelEquipped(Entity* self) override {
|
||||||
|
Invoke("onZonePropertyModelEquipped");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has placed a model while editing this property.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onZonePropertyModelPlaced(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnZonePropertyModelPlaced(Entity* self, Entity* player) override {
|
||||||
|
Invoke("onZonePropertyModelPlaced", lEntity(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player has picked up a model while editing this property.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onZonePropertyModelPickedUp(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnZonePropertyModelPickedUp(Entity* self, Entity* player) override {
|
||||||
|
Invoke("onZonePropertyModelPickedUp", lEntity(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player removed a model while editing this property.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onZonePropertyModelRemoved(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnZonePropertyModelRemoved(Entity* self, Entity* player) override {
|
||||||
|
Invoke("onZonePropertyModelRemoved", lEntity(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player removed a model while holding it when editing this property.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onZonePropertyModelRemoved(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnZonePropertyModelRemovedWhileEquipped(Entity* self, Entity* player) override {
|
||||||
|
Invoke("onZonePropertyModelRemovedWhileEquipped", lEntity(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player rotated a model while editing this property.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onZonePropertyModelRotated(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnZonePropertyModelRotated(Entity* self, Entity* player) override {
|
||||||
|
Invoke("onZonePropertyModelRotated", lEntity(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when the pet taming minigame encounted an event.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onNotifyPetTamingMinigame(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnNotifyPetTamingMinigame(Entity* self, Entity* tamer, eNotifyType type) override {
|
||||||
|
Invoke("onNotifyPetTamingMinigame", lEntity(tamer), (int32_t) type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player responded to a message box.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onMessageBoxResponse(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) override {
|
||||||
|
Invoke("onMessageBoxResponse", lEntity(sender), button, GeneralUtils::UTF16ToWTF8(identifier), GeneralUtils::UTF16ToWTF8(userData));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player responded to a choice box.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onChoiceBoxResponse(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnChoiceBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier) override {
|
||||||
|
Invoke("onChoiceBoxResponse", lEntity(sender), button, GeneralUtils::UTF16ToWTF8(buttonIdentifier), GeneralUtils::UTF16ToWTF8(identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when self arrived at a moving platform waypoint.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onWaypointReached(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnWaypointReached(Entity* self, uint32_t waypointIndex) override {
|
||||||
|
Invoke("onWaypointReached", waypointIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player fired a skill event on self.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onSkillEventFired(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnSkillEventFired(Entity* self, Entity* caster, const std::string& message) override {
|
||||||
|
Invoke("onSkillEventFired", lEntity(caster), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when self casted a skill.
|
||||||
|
*
|
||||||
|
* Equivalent to 'function onSkillCast(self, msg)'
|
||||||
|
*/
|
||||||
|
void OnSkillCast(Entity* self, uint32_t skillID) override {
|
||||||
|
Invoke("onSkillCast", skillID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a player on a rail reaches a waypoint
|
||||||
|
* Equivalent to: 'onPlayerRailArrivedNotification(self, msg)'
|
||||||
|
* @param self the parent of the script
|
||||||
|
* @param sender the entity that sent the event
|
||||||
|
* @param pathName the name of the path the entity was on
|
||||||
|
* @param waypoint the waypoint number of the path the entity was on
|
||||||
|
*/
|
||||||
|
void OnPlayerRailArrived(Entity* self, Entity* sender, const std::u16string& pathName, int32_t waypoint) override {
|
||||||
|
Invoke("onPlayerRailArrived", lEntity(sender), GeneralUtils::UTF16ToWTF8(pathName), waypoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by legacy minigames to indicate something has changed about the activity
|
||||||
|
* @param self the entity the script belongs to
|
||||||
|
* @param senderID the sender of the message
|
||||||
|
* @param value1 some value to represent the change
|
||||||
|
* @param value2 some other value to represent the change
|
||||||
|
* @param stringValue some string value to represent the change
|
||||||
|
*/
|
||||||
|
void OnActivityStateChangeRequest(Entity* self, const LWOOBJID senderID, const int32_t value1,
|
||||||
|
const int32_t value2, const std::u16string& stringValue) override {
|
||||||
|
Invoke("onActivityStateChangeRequest", senderID, value1, value2, GeneralUtils::UTF16ToWTF8(stringValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCinematicUpdate(Entity* self, Entity* sender, eCinematicEvent event, const std::u16string& pathName,
|
||||||
|
float_t pathTime, float_t totalTime, int32_t waypoint) override {
|
||||||
|
Invoke("onCinematicUpdate", lEntity(sender), (int32_t) event, GeneralUtils::UTF16ToWTF8(pathName), pathTime, totalTime, waypoint);
|
||||||
|
}
|
||||||
|
};
|
8
dLua/LuaTerminateBehavior.h
Normal file
8
dLua/LuaTerminateBehavior.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum class LuaTerminateBehavior
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
ResetScript,
|
||||||
|
ResetScriptAndDelete,
|
||||||
|
};
|
155
dLua/dLua.cpp
Normal file
155
dLua/dLua.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#include "dLua.h"
|
||||||
|
|
||||||
|
#include "lEntity.h"
|
||||||
|
#include "EntityManager.h"
|
||||||
|
#include "LuaScript.h"
|
||||||
|
#include "LuaTerminateBehavior.h"
|
||||||
|
#include "ScriptComponent.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
|
||||||
|
namespace dLua
|
||||||
|
{
|
||||||
|
void LoadScript(Entity* entity, const std::string& name)
|
||||||
|
{
|
||||||
|
// Read the script from the file.
|
||||||
|
std::stringstream input;
|
||||||
|
|
||||||
|
std::ifstream file(name);
|
||||||
|
|
||||||
|
if (!file.is_open())
|
||||||
|
throw std::runtime_error("LoadScript: Failed to open file");
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
input << line << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaScript* lua = new LuaScript(LuaTerminateBehavior::ResetScriptAndDelete);
|
||||||
|
|
||||||
|
ScriptComponent* script = entity->GetComponent<ScriptComponent>();
|
||||||
|
|
||||||
|
if (script == nullptr) {
|
||||||
|
script = new ScriptComponent(entity, false);
|
||||||
|
|
||||||
|
entity->AddComponent(ScriptComponent::ComponentType, script);
|
||||||
|
}
|
||||||
|
|
||||||
|
script->SetScript(lua);
|
||||||
|
|
||||||
|
lua->SetEntity(entity);
|
||||||
|
|
||||||
|
// Run the code, and print any errors
|
||||||
|
try {
|
||||||
|
lua->Script(input.str());
|
||||||
|
}
|
||||||
|
// Catch sol::error
|
||||||
|
catch (const sol::error& e) {
|
||||||
|
Game::logger->Log("dLua", std::string(e.what()));
|
||||||
|
}
|
||||||
|
// Catch *any* error
|
||||||
|
catch (...) {
|
||||||
|
Game::logger->Log("dLua", "Unknown error loading script!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* GetEntity(const sol::state& lua, const std::string& key)
|
||||||
|
{
|
||||||
|
sol::object object = lua[key];
|
||||||
|
|
||||||
|
if (!object.is<lEntity>())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return object.as<lEntity>().GetEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* GetEntityOrThrow(const sol::state& lua, const std::string& key)
|
||||||
|
{
|
||||||
|
sol::object object = lua[key];
|
||||||
|
|
||||||
|
if (!object.is<lEntity>())
|
||||||
|
throw std::runtime_error("GetEntityOrThrow: Invalid key");
|
||||||
|
|
||||||
|
lEntity entity = object.as<lEntity>();
|
||||||
|
|
||||||
|
if (!entity.IsValid())
|
||||||
|
throw std::runtime_error("GetEntityOrThrow: Invalid entity");
|
||||||
|
|
||||||
|
return entity.GetEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* GetEntity(const LWOOBJID& id)
|
||||||
|
{
|
||||||
|
return EntityManager::Instance()->GetEntity(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* GetEntityOrThrow(const LWOOBJID& id)
|
||||||
|
{
|
||||||
|
Entity* entity = EntityManager::Instance()->GetEntity(id);
|
||||||
|
|
||||||
|
if (!entity)
|
||||||
|
{
|
||||||
|
throw sol::error("Entity not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* GetEntity(sol::object object)
|
||||||
|
{
|
||||||
|
LWOOBJID id = LWOOBJID_EMPTY;
|
||||||
|
|
||||||
|
if (object.is<lEntity>()) {
|
||||||
|
id = object.as<lEntity>().GetID();
|
||||||
|
} else if (object.is<LWOOBJID>()) {
|
||||||
|
id = object.as<LWOOBJID>();
|
||||||
|
} else if (object.is<std::string>()) {
|
||||||
|
id = atol(object.as<std::string>().c_str());
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetEntity(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* GetEntityOrThrow(sol::object object)
|
||||||
|
{
|
||||||
|
Entity* entity = GetEntity(object);
|
||||||
|
|
||||||
|
if (!entity)
|
||||||
|
{
|
||||||
|
throw sol::error("Entity not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
LWOOBJID GetEntityID(sol::object object)
|
||||||
|
{
|
||||||
|
LWOOBJID id = LWOOBJID_EMPTY;
|
||||||
|
|
||||||
|
if (object.is<lEntity>()) {
|
||||||
|
id = object.as<lEntity>().GetID();
|
||||||
|
} else if (object.is<LWOOBJID>()) {
|
||||||
|
id = object.as<LWOOBJID>();
|
||||||
|
} else if (object.is<std::string>()) {
|
||||||
|
id = atol(object.as<std::string>().c_str());
|
||||||
|
} else {
|
||||||
|
return LWOOBJID_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
LWOOBJID GetEntityIDOrThrow(sol::object object)
|
||||||
|
{
|
||||||
|
LWOOBJID id = GetEntityID(object);
|
||||||
|
|
||||||
|
if (id == LWOOBJID_EMPTY)
|
||||||
|
{
|
||||||
|
throw sol::error("Entity not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
61
dLua/dLua.h
Normal file
61
dLua/dLua.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sol/sol.hpp"
|
||||||
|
#include "dCommonVars.h"
|
||||||
|
|
||||||
|
class Entity;
|
||||||
|
|
||||||
|
namespace dLua
|
||||||
|
{
|
||||||
|
void LoadScript(Entity* entity, const std::string& name);
|
||||||
|
|
||||||
|
Entity* GetEntity(const sol::state& lua, const std::string& key);
|
||||||
|
|
||||||
|
Entity* GetEntityOrThrow(const sol::state& lua, const std::string& key);
|
||||||
|
|
||||||
|
Entity* GetEntity(const LWOOBJID& id);
|
||||||
|
|
||||||
|
Entity* GetEntityOrThrow(const LWOOBJID& id);
|
||||||
|
|
||||||
|
Entity* GetEntity(sol::object object);
|
||||||
|
|
||||||
|
Entity* GetEntityOrThrow(sol::object object);
|
||||||
|
|
||||||
|
LWOOBJID GetEntityID(sol::object object);
|
||||||
|
|
||||||
|
LWOOBJID GetEntityIDOrThrow(sol::object object);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T TableGet(const sol::table& table, const std::string& key)
|
||||||
|
{
|
||||||
|
sol::object object = table[key];
|
||||||
|
if (!object.valid())
|
||||||
|
throw std::runtime_error("TableGet: Missing key");
|
||||||
|
if (!object.is<T>())
|
||||||
|
throw std::runtime_error("TableGet: Invalid key");
|
||||||
|
return object.as<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T TableGet(const sol::table& table, const std::string& key, const T& defaultValue)
|
||||||
|
{
|
||||||
|
sol::object object = table[key];
|
||||||
|
if (!object.valid())
|
||||||
|
return defaultValue;
|
||||||
|
if (!object.is<T>())
|
||||||
|
throw std::runtime_error("TableGet: Invalid key");
|
||||||
|
return object.as<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool TryTableGet(const sol::table& table, const std::string& key, T& out)
|
||||||
|
{
|
||||||
|
sol::object object = table[key];
|
||||||
|
if (!object.valid())
|
||||||
|
return false;
|
||||||
|
if (!object.is<T>())
|
||||||
|
throw std::runtime_error("TableGet: Invalid key");
|
||||||
|
out = object.as<T>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
80
dLua/lCommonTypes.cpp
Normal file
80
dLua/lCommonTypes.cpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#include "lCommonTypes.h"
|
||||||
|
|
||||||
|
#include "NiPoint3.h"
|
||||||
|
#include "NiQuaternion.h"
|
||||||
|
#include "LuaScript.h"
|
||||||
|
|
||||||
|
void lCommonTypes::RegisterClass(LuaScript* script)
|
||||||
|
{
|
||||||
|
sol::state& lua = script->GetState();
|
||||||
|
|
||||||
|
lua.new_usertype<NiPoint3>(
|
||||||
|
"Vector3",
|
||||||
|
sol::constructors<NiPoint3(), NiPoint3(float, float, float)>(),
|
||||||
|
"x", &NiPoint3::x,
|
||||||
|
"y", &NiPoint3::y,
|
||||||
|
"z", &NiPoint3::z,
|
||||||
|
"dot", &NiPoint3::DotProduct,
|
||||||
|
"cross", &NiPoint3::CrossProduct,
|
||||||
|
"length", &NiPoint3::Length,
|
||||||
|
"squaredLength", &NiPoint3::SquaredLength,
|
||||||
|
"unitize", &NiPoint3::Unitize,
|
||||||
|
"normalize", &NiPoint3::Unitize,
|
||||||
|
"distance", &NiPoint3::Distance,
|
||||||
|
"distanceSquared", &NiPoint3::DistanceSquared,
|
||||||
|
"getX", &NiPoint3::GetX,
|
||||||
|
"getY", &NiPoint3::GetY,
|
||||||
|
"getZ", &NiPoint3::GetZ,
|
||||||
|
"setX", &NiPoint3::SetX,
|
||||||
|
"setY", &NiPoint3::SetY,
|
||||||
|
"setZ", &NiPoint3::SetZ,
|
||||||
|
sol::meta_function::to_string, [](const NiPoint3& vector) {
|
||||||
|
return "Vector3(" + std::to_string(vector.x) + ", " + std::to_string(vector.y) + ", " + std::to_string(vector.z) + ")";
|
||||||
|
},
|
||||||
|
sol::meta_function::addition, [](const NiPoint3& lhs, const NiPoint3& rhs) {
|
||||||
|
return lhs + rhs;
|
||||||
|
},
|
||||||
|
sol::meta_function::subtraction, [](const NiPoint3& lhs, const NiPoint3& rhs) {
|
||||||
|
return lhs - rhs;
|
||||||
|
},
|
||||||
|
sol::meta_function::multiplication, [](const NiPoint3& lhs, const float& rhs) {
|
||||||
|
return lhs * rhs;
|
||||||
|
},
|
||||||
|
sol::meta_function::division, [](const NiPoint3& lhs, const float& rhs) {
|
||||||
|
return lhs / rhs;
|
||||||
|
},
|
||||||
|
sol::meta_function::unary_minus, [](const NiPoint3& lhs) {
|
||||||
|
return lhs * -1.0f;
|
||||||
|
},
|
||||||
|
sol::meta_function::equal_to, [](const NiPoint3& lhs, const NiPoint3& rhs) {
|
||||||
|
return lhs == rhs;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.new_usertype<NiQuaternion>(
|
||||||
|
"Quaternion",
|
||||||
|
sol::constructors<NiQuaternion(), NiQuaternion(float, float, float, float)>(),
|
||||||
|
"x", &NiQuaternion::x,
|
||||||
|
"y", &NiQuaternion::y,
|
||||||
|
"z", &NiQuaternion::z,
|
||||||
|
"w", &NiQuaternion::w,
|
||||||
|
"getForwardVector", &NiQuaternion::GetForwardVector,
|
||||||
|
"getUpVector", &NiQuaternion::GetUpVector,
|
||||||
|
"getRightVector", &NiQuaternion::GetRightVector,
|
||||||
|
"getEulerAngles", &NiQuaternion::GetEulerAngles,
|
||||||
|
"getX", &NiQuaternion::GetX,
|
||||||
|
"getY", &NiQuaternion::GetY,
|
||||||
|
"getZ", &NiQuaternion::GetZ,
|
||||||
|
"getW", &NiQuaternion::GetW,
|
||||||
|
"setX", &NiQuaternion::SetX,
|
||||||
|
"setY", &NiQuaternion::SetY,
|
||||||
|
"setZ", &NiQuaternion::SetZ,
|
||||||
|
"setW", &NiQuaternion::SetW,
|
||||||
|
sol::meta_function::to_string, [](const NiQuaternion& quaternion) {
|
||||||
|
return "Quaternion(" + std::to_string(quaternion.x) + ", " + std::to_string(quaternion.y) + ", " + std::to_string(quaternion.z) + ", " + std::to_string(quaternion.w) + ")";
|
||||||
|
},
|
||||||
|
sol::meta_function::equal_to, [](const NiQuaternion& lhs, const NiQuaternion& rhs) {
|
||||||
|
return lhs == rhs;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
12
dLua/lCommonTypes.h
Normal file
12
dLua/lCommonTypes.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dLua.h"
|
||||||
|
|
||||||
|
class LuaScript;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A struct for wrapping a Position in Lua.
|
||||||
|
*/
|
||||||
|
struct lCommonTypes {
|
||||||
|
static void RegisterClass(LuaScript* script);
|
||||||
|
};
|
406
dLua/lEntity.cpp
Normal file
406
dLua/lEntity.cpp
Normal file
@ -0,0 +1,406 @@
|
|||||||
|
#include "lEntity.h"
|
||||||
|
|
||||||
|
#include "EntityManager.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
#include "LuaScript.h"
|
||||||
|
#include "DestroyableComponent.h"
|
||||||
|
#include "BaseCombatAIComponent.h"
|
||||||
|
#include "MovementAIComponent.h"
|
||||||
|
#include "GameMessages.h"
|
||||||
|
|
||||||
|
void lEntity::RegisterClass(LuaScript* script)
|
||||||
|
{
|
||||||
|
sol::state& lua = script->GetState();
|
||||||
|
|
||||||
|
lua.new_usertype<lEntity>("Entity",
|
||||||
|
sol::constructors<lEntity(LWOOBJID)>(),
|
||||||
|
"IsValid", &lEntity::IsValid,
|
||||||
|
"GetID", &lEntity::GetID,
|
||||||
|
"GetLOT", &lEntity::GetLOT,
|
||||||
|
"GetPosition", &lEntity::GetPosition,
|
||||||
|
"GetRotation", &lEntity::GetRotation,
|
||||||
|
"SetPosition", &lEntity::SetPosition,
|
||||||
|
"SetRotation", &lEntity::SetRotation,
|
||||||
|
"AddTimer", &lEntity::AddTimer,
|
||||||
|
"Smash", &lEntity::Smash,
|
||||||
|
"LoadScript", &lEntity::LoadScript,
|
||||||
|
"SetVar", &lEntity::SetVar,
|
||||||
|
"GetVar", [script](lEntity& entity, const std::string& key) {
|
||||||
|
return entity.GetVar(script, key);
|
||||||
|
},
|
||||||
|
|
||||||
|
#pragma region DestroyableComponent
|
||||||
|
"GetHealth", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetHealth();
|
||||||
|
},
|
||||||
|
"GetArmor", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetArmor();
|
||||||
|
},
|
||||||
|
"GetImagination", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetImagination();
|
||||||
|
},
|
||||||
|
"GetMaxHealth", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetMaxHealth();
|
||||||
|
},
|
||||||
|
"GetMaxArmor", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetMaxArmor();
|
||||||
|
},
|
||||||
|
"GetMaxImagination", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetMaxImagination();
|
||||||
|
},
|
||||||
|
"SetHealth", [](lEntity& entity, int32_t health) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetHealth(health);
|
||||||
|
},
|
||||||
|
"SetArmor", [](lEntity& entity, int32_t armor) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetArmor(armor);
|
||||||
|
},
|
||||||
|
"SetImagination", [](lEntity& entity, int32_t imagination) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetImagination(imagination);
|
||||||
|
},
|
||||||
|
"SetMaxHealth", [](lEntity& entity, float maxHealth) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetMaxHealth(maxHealth);
|
||||||
|
},
|
||||||
|
"SetMaxArmor", [](lEntity& entity, float maxArmor) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetMaxArmor(maxArmor);
|
||||||
|
},
|
||||||
|
"SetMaxImagination", [](lEntity& entity, float maxImagination) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetMaxImagination(maxImagination);
|
||||||
|
},
|
||||||
|
"Damage", [](lEntity& entity, int32_t damage, sol::object origin) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->Damage(damage, dLua::GetEntityID(origin));
|
||||||
|
},
|
||||||
|
"Heal", [](lEntity& entity, int32_t heal) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->Heal(heal);
|
||||||
|
},
|
||||||
|
"Repair", [](lEntity& entity, int32_t repair) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->Repair(repair);
|
||||||
|
},
|
||||||
|
"Imagine", [](lEntity& entity, int32_t imagine) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->Imagine(imagine);
|
||||||
|
},
|
||||||
|
"GetDamageToAbsorb", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetDamageToAbsorb();
|
||||||
|
},
|
||||||
|
"SetDamageToAbsorb", [](lEntity& entity, int32_t damageToAbsorb) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetDamageToAbsorb(damageToAbsorb);
|
||||||
|
},
|
||||||
|
"GetDamageReduction", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetDamageReduction();
|
||||||
|
},
|
||||||
|
"SetDamageReduction", [](lEntity& entity, int32_t damageReduction) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetDamageReduction(damageReduction);
|
||||||
|
},
|
||||||
|
"GetIsImmune", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->IsImmune();
|
||||||
|
},
|
||||||
|
"SetIsImmune", [](lEntity& entity, bool immune) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetIsImmune(immune);
|
||||||
|
},
|
||||||
|
"GetIsShielded", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetIsShielded();
|
||||||
|
},
|
||||||
|
"SetIsShielded", [](lEntity& entity, bool shielded) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetIsShielded(shielded);
|
||||||
|
},
|
||||||
|
"AddFaction", [](lEntity& entity, int32_t faction) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->AddFaction(faction);
|
||||||
|
},
|
||||||
|
"AddEnemyFaction", [](lEntity& entity, int32_t faction) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->AddEnemyFaction(faction);
|
||||||
|
},
|
||||||
|
"GetAttacksToBlock", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetAttacksToBlock();
|
||||||
|
},
|
||||||
|
"SetAttacksToBlock", [](lEntity& entity, int32_t attacksToBlock) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetAttacksToBlock(attacksToBlock);
|
||||||
|
},
|
||||||
|
"SetFaction", [](lEntity& entity, int32_t faction) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetFaction(faction);
|
||||||
|
},
|
||||||
|
"HasFaction", [](lEntity& entity, int32_t faction) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->HasFaction(faction);
|
||||||
|
},
|
||||||
|
"GetLootMatrixID", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetLootMatrixID();
|
||||||
|
},
|
||||||
|
"SetLootMatrixID", [](lEntity& entity, int32_t lootMatrixID) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetLootMatrixID(lootMatrixID);
|
||||||
|
},
|
||||||
|
"PushImmunity", [](lEntity& entity, int32_t immunity) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->PushImmunity(immunity);
|
||||||
|
},
|
||||||
|
"PopImmunity", [](lEntity& entity) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->PopImmunity();
|
||||||
|
},
|
||||||
|
"GetIsSmashable", [](lEntity& entity) {
|
||||||
|
AssertComponent<DestroyableComponent>(entity);
|
||||||
|
return entity->GetComponent<DestroyableComponent>()->GetIsSmashable();
|
||||||
|
},
|
||||||
|
"SetIsSmashable", [](lEntity& entity, bool smashable) {
|
||||||
|
GetComponent<DestroyableComponent>(entity)->SetIsSmashable(smashable);
|
||||||
|
},
|
||||||
|
|
||||||
|
#pragma endregion DestroyableComponent
|
||||||
|
|
||||||
|
#pragma region BaseCombatAIComponent
|
||||||
|
"GetStunned", [](lEntity& entity) {
|
||||||
|
AssertComponent<BaseCombatAIComponent>(entity);
|
||||||
|
return entity->GetComponent<BaseCombatAIComponent>()->GetStunned();
|
||||||
|
},
|
||||||
|
"SetStunned", [](lEntity& entity, bool stunned) {
|
||||||
|
AssertComponent<BaseCombatAIComponent>(entity);
|
||||||
|
entity->GetComponent<BaseCombatAIComponent>()->SetStunned(stunned);
|
||||||
|
},
|
||||||
|
"Stun", [](lEntity& entity, float duration) {
|
||||||
|
AssertComponent<BaseCombatAIComponent>(entity);
|
||||||
|
entity->GetComponent<BaseCombatAIComponent>()->Stun(duration);
|
||||||
|
},
|
||||||
|
"GetAIDisabled", [](lEntity& entity) {
|
||||||
|
AssertComponent<BaseCombatAIComponent>(entity);
|
||||||
|
return entity->GetComponent<BaseCombatAIComponent>()->GetDistabled();
|
||||||
|
},
|
||||||
|
"SetAIDisabled", [](lEntity& entity, bool disabled) {
|
||||||
|
AssertComponent<BaseCombatAIComponent>(entity);
|
||||||
|
entity->GetComponent<BaseCombatAIComponent>()->SetDisabled(disabled);
|
||||||
|
},
|
||||||
|
#pragma endregion BaseCombatAIComponent
|
||||||
|
|
||||||
|
#pragma region MovementAIComponent
|
||||||
|
|
||||||
|
"GetDestination", [](lEntity& entity) {
|
||||||
|
GetComponent<MovementAIComponent>(entity)->GetDestination();
|
||||||
|
},
|
||||||
|
"SetDestination", [](lEntity& entity, const NiPoint3& destination) {
|
||||||
|
GetComponent<MovementAIComponent>(entity)->SetDestination(destination);
|
||||||
|
},
|
||||||
|
"Warp", [](lEntity& entity, const NiPoint3& point) {
|
||||||
|
GetComponent<MovementAIComponent>(entity)->Warp(point);
|
||||||
|
},
|
||||||
|
|
||||||
|
#pragma endregion MovementAIComponent
|
||||||
|
|
||||||
|
#pragma region GameMessages
|
||||||
|
"PlayAnimation", [](lEntity& entity, const std::string& animation) {
|
||||||
|
GameMessages::SendPlayAnimation(entity.GetEntityOrThrow(), GeneralUtils::ASCIIToUTF16(animation));
|
||||||
|
},
|
||||||
|
"PlayFX", [](lEntity& entity, int32_t effectID, const std::string& effectType, const std::string& name) {
|
||||||
|
GameMessages::SendPlayFXEffect(entity.GetID(), effectID, GeneralUtils::ASCIIToUTF16(effectType), name);
|
||||||
|
},
|
||||||
|
"StopFX", [](lEntity& entity, const std::string& name, bool killImmediate) {
|
||||||
|
GameMessages::SendStopFXEffect(entity.GetEntityOrThrow(), killImmediate, name);
|
||||||
|
}
|
||||||
|
#pragma endregion GameMessages
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register a function create a new entity
|
||||||
|
// Takes a table with the following fields:
|
||||||
|
// - lot: number
|
||||||
|
// - position: Vector3 (optional)
|
||||||
|
// - rotation: Quaternion (optional)
|
||||||
|
// - spawner: lEntity (optional)
|
||||||
|
lua.set_function("spawn", [script](sol::table entityData) {
|
||||||
|
sol::state& lua = script->GetState();
|
||||||
|
|
||||||
|
// Get the lot
|
||||||
|
LOT lot = dLua::TableGet<LOT>(entityData, "lot");
|
||||||
|
|
||||||
|
// Use the state entity's position and rotation if none is provided
|
||||||
|
Entity* stateEntity = script->GetEntity();
|
||||||
|
|
||||||
|
// Get the position
|
||||||
|
NiPoint3 position;
|
||||||
|
|
||||||
|
if (!dLua::TryTableGet(entityData, "position", position))
|
||||||
|
position = stateEntity->GetPosition();
|
||||||
|
|
||||||
|
// Get the rotation
|
||||||
|
NiQuaternion rotation;
|
||||||
|
|
||||||
|
if (!dLua::TryTableGet(entityData, "rotation", rotation))
|
||||||
|
rotation = stateEntity->GetRotation();
|
||||||
|
|
||||||
|
// Get the spawner
|
||||||
|
Entity* spawner = nullptr;
|
||||||
|
|
||||||
|
lEntity spawnerEntity;
|
||||||
|
if (dLua::TryTableGet(entityData, "spawner", spawnerEntity)) {
|
||||||
|
spawner = dLua::GetEntityOrThrow(spawnerEntity.id);
|
||||||
|
} else {
|
||||||
|
spawner = stateEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the entity
|
||||||
|
EntityInfo info {};
|
||||||
|
info.lot = lot;
|
||||||
|
info.pos = position;
|
||||||
|
info.rot = rotation;
|
||||||
|
info.spawnerID = spawner->GetObjectID();
|
||||||
|
|
||||||
|
Entity* entity = EntityManager::Instance()->CreateEntity(info);
|
||||||
|
|
||||||
|
EntityManager::Instance()->ConstructEntity(entity);
|
||||||
|
|
||||||
|
// Return the entity
|
||||||
|
return lEntity(entity->GetObjectID());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
lEntity::lEntity(Entity* entity) {
|
||||||
|
if (entity == nullptr) {
|
||||||
|
this->id = LWOOBJID_EMPTY;
|
||||||
|
} else {
|
||||||
|
this->id = entity->GetObjectID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lEntity::IsValid() const {
|
||||||
|
return GetEntity() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LWOOBJID lEntity::GetID() const {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOT lEntity::GetLOT() const {
|
||||||
|
return GetEntityOrThrow()->GetLOT();
|
||||||
|
}
|
||||||
|
|
||||||
|
NiPoint3 lEntity::GetPosition() const {
|
||||||
|
return GetEntityOrThrow()->GetPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
NiQuaternion lEntity::GetRotation() const {
|
||||||
|
return GetEntityOrThrow()->GetRotation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lEntity::SetPosition(const NiPoint3& pos) {
|
||||||
|
GetEntityOrThrow()->SetPosition(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lEntity::SetRotation(const NiQuaternion& rot) {
|
||||||
|
GetEntityOrThrow()->SetRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lEntity::SetVar(const std::string& key, sol::object value) {
|
||||||
|
const std::u16string key16 = GeneralUtils::ASCIIToUTF16(key);
|
||||||
|
|
||||||
|
Entity* entity = GetEntityOrThrow();
|
||||||
|
|
||||||
|
sol::type type = value.get_type();
|
||||||
|
|
||||||
|
if (value.is<lEntity>()) {
|
||||||
|
LWOOBJID entityID = value.as<lEntity>().GetID();
|
||||||
|
|
||||||
|
entity->SetVar(key16, entityID);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case sol::type::boolean:
|
||||||
|
entity->SetVar(key16, value.as<bool>());
|
||||||
|
break;
|
||||||
|
case sol::type::number:
|
||||||
|
entity->SetVar(key16, value.as<float>());
|
||||||
|
break;
|
||||||
|
case sol::type::string:
|
||||||
|
entity->SetVar(key16, GeneralUtils::ASCIIToUTF16(value.as<std::string>()));
|
||||||
|
break;
|
||||||
|
case sol::type::nil:
|
||||||
|
entity->SetVar(key16, value); // Maybe store nil some other way?
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Game::logger->Log("lEntity", "Unknown type for SetVar: %i\n", type);
|
||||||
|
entity->SetVar(key16, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::object lEntity::GetVar(LuaScript* script, const std::string& key) {
|
||||||
|
const std::u16string key16 = GeneralUtils::ASCIIToUTF16(key);
|
||||||
|
|
||||||
|
Entity* entity = GetEntityOrThrow();
|
||||||
|
|
||||||
|
LDFBaseData* value = entity->GetVarData(key16);
|
||||||
|
|
||||||
|
if (value == nullptr) {
|
||||||
|
return sol::make_object(script->GetState(), sol::nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
eLDFType type = value->GetValueType();
|
||||||
|
|
||||||
|
sol::state& lua = script->GetState();
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case LDF_TYPE_UTF_16:
|
||||||
|
return sol::make_object(lua, GeneralUtils::UTF16ToWTF8(entity->GetVar<std::u16string>(key16)));
|
||||||
|
case LDF_TYPE_S32:
|
||||||
|
return sol::make_object(lua, entity->GetVar<int32_t>(key16));
|
||||||
|
case LDF_TYPE_FLOAT:
|
||||||
|
return sol::make_object(lua, entity->GetVar<float>(key16));
|
||||||
|
case LDF_TYPE_DOUBLE:
|
||||||
|
return sol::make_object(lua, entity->GetVar<double>(key16));
|
||||||
|
case LDF_TYPE_U32:
|
||||||
|
return sol::make_object(lua, entity->GetVar<uint32_t>(key16));
|
||||||
|
case LDF_TYPE_BOOLEAN:
|
||||||
|
return sol::make_object(lua, entity->GetVar<bool>(key16));
|
||||||
|
case LDF_TYPE_U64:
|
||||||
|
return sol::make_object(lua, entity->GetVar<uint64_t>(key16));
|
||||||
|
case LDF_TYPE_OBJID:
|
||||||
|
return sol::make_object(lua, lEntity(entity->GetVar<LWOOBJID>(key16)));
|
||||||
|
case LDF_TYPE_UTF_8:
|
||||||
|
return sol::make_object(lua, entity->GetVar<std::string>(key16));
|
||||||
|
default:
|
||||||
|
Game::logger->Log("lEntity", "Unknown type for GetVar: %i\n", type);
|
||||||
|
return entity->GetVar<sol::object>(key16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lEntity::Smash(sol::object smasher) {
|
||||||
|
Entity* entity = GetEntityOrThrow();
|
||||||
|
|
||||||
|
LWOOBJID smasherEntity = dLua::GetEntityID(smasher);
|
||||||
|
|
||||||
|
entity->Smash(smasherEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lEntity::AddTimer(const std::string& name, float seconds) {
|
||||||
|
GetEntityOrThrow()->AddTimer(name, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lEntity::LoadScript(const std::string& name) {
|
||||||
|
dLua::LoadScript(GetEntityOrThrow(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lEntity::Serialize() {
|
||||||
|
EntityManager::Instance()->SerializeEntity(GetEntityOrThrow());
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* lEntity::GetEntity() const
|
||||||
|
{
|
||||||
|
return dLua::GetEntity(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* lEntity::GetEntityOrThrow() const
|
||||||
|
{
|
||||||
|
return dLua::GetEntityOrThrow(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* lEntity::operator->() const
|
||||||
|
{
|
||||||
|
return GetEntity();
|
||||||
|
}
|
122
dLua/lEntity.h
Normal file
122
dLua/lEntity.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dLua.h"
|
||||||
|
|
||||||
|
#include "Entity.h"
|
||||||
|
|
||||||
|
class LuaScript;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A struct for wrapping an Entity in Lua.
|
||||||
|
*/
|
||||||
|
struct lEntity {
|
||||||
|
static void RegisterClass(LuaScript* script);
|
||||||
|
|
||||||
|
LWOOBJID id;
|
||||||
|
|
||||||
|
lEntity() : id(LWOOBJID_EMPTY) {}
|
||||||
|
|
||||||
|
lEntity(LWOOBJID id) : id(id) {}
|
||||||
|
|
||||||
|
lEntity(Entity* entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this entity is valid.
|
||||||
|
*/
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the entity's ID.
|
||||||
|
*/
|
||||||
|
LWOOBJID GetID() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the entity's lot.
|
||||||
|
*/
|
||||||
|
LOT GetLOT() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the entity's position.
|
||||||
|
*/
|
||||||
|
NiPoint3 GetPosition() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the entity's rotation.
|
||||||
|
*/
|
||||||
|
NiQuaternion GetRotation() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the entit's position.
|
||||||
|
*/
|
||||||
|
void SetPosition(const NiPoint3& pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the entity's rotation.
|
||||||
|
*/
|
||||||
|
void SetRotation(const NiQuaternion& rot);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a variable in the entity's data table.
|
||||||
|
*/
|
||||||
|
void SetVar(const std::string& key, sol::object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a variable from the entity's data table.
|
||||||
|
*/
|
||||||
|
sol::object GetVar(LuaScript* script, const std::string& key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Smash this entity.
|
||||||
|
*/
|
||||||
|
void Smash(sol::object smasher);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a timer.
|
||||||
|
*/
|
||||||
|
void AddTimer(const std::string& name, float seconds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a LUA script and attach it to this entity.
|
||||||
|
*/
|
||||||
|
void LoadScript(const std::string& name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this entity.
|
||||||
|
*/
|
||||||
|
void Serialize();
|
||||||
|
|
||||||
|
Entity* GetEntity() const;
|
||||||
|
|
||||||
|
Entity* GetEntityOrThrow() const;
|
||||||
|
|
||||||
|
Entity* operator->() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assets that this entity has a specific component.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
void AssertComponent() {
|
||||||
|
if (!GetEntity()->HasComponent(T::ComponentType)) {
|
||||||
|
throw std::runtime_error("Entity does not have component " + std::to_string(T::ComponentType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assets that an entity has a specific component.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
static inline void AssertComponent(lEntity entity) {
|
||||||
|
if (!entity->HasComponent(T::ComponentType)) {
|
||||||
|
throw std::runtime_error("Entity does not have component " + std::to_string(T::ComponentType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility for getting a component, asserting it exists
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
static inline T* GetComponent(lEntity entity) {
|
||||||
|
entity.AssertComponent<T>();
|
||||||
|
return entity->GetComponent<T>();
|
||||||
|
}
|
||||||
|
};
|
53
dLua/sol/config.hpp
Normal file
53
dLua/sol/config.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
// This file was generated with a script.
|
||||||
|
// Generated 2022-04-03 15:48:33.302370 UTC
|
||||||
|
// This header was generated with sol v4.0.0-alpha (revision 50b62c93)
|
||||||
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
|
#ifndef SOL_SINGLE_CONFIG_HPP
|
||||||
|
#define SOL_SINGLE_CONFIG_HPP
|
||||||
|
|
||||||
|
// beginning of sol/config.hpp
|
||||||
|
|
||||||
|
/* Base, empty configuration file!
|
||||||
|
|
||||||
|
To override, place a file in your include paths of the form:
|
||||||
|
|
||||||
|
. (your include path here)
|
||||||
|
| sol (directory, or equivalent)
|
||||||
|
| config.hpp (your config.hpp file)
|
||||||
|
|
||||||
|
So that when sol2 includes the file
|
||||||
|
|
||||||
|
#include <sol/config.hpp>
|
||||||
|
|
||||||
|
it gives you the configuration values you desire. Configuration values can be
|
||||||
|
seen in the safety.rst of the doc/src, or at
|
||||||
|
https://sol2.readthedocs.io/en/latest/safety.html ! You can also pass them through
|
||||||
|
the build system, or the command line options of your compiler.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// end of sol/config.hpp
|
||||||
|
|
||||||
|
#endif // SOL_SINGLE_CONFIG_HPP
|
1310
dLua/sol/forward.hpp
Normal file
1310
dLua/sol/forward.hpp
Normal file
File diff suppressed because it is too large
Load Diff
28843
dLua/sol/sol.hpp
Normal file
28843
dLua/sol/sol.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -812,6 +812,10 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr
|
|||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CppScripts::Script* CppScripts::GetInvalidScript() {
|
||||||
|
return invalidToReturn;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<CppScripts::Script*> CppScripts::GetEntityScripts(Entity* entity) {
|
std::vector<CppScripts::Script*> CppScripts::GetEntityScripts(Entity* entity) {
|
||||||
std::vector<CppScripts::Script*> scripts;
|
std::vector<CppScripts::Script*> scripts;
|
||||||
std::vector<ScriptComponent*> comps = entity->GetScriptComponents();
|
std::vector<ScriptComponent*> comps = entity->GetScriptComponents();
|
||||||
|
@ -320,6 +320,7 @@ namespace CppScripts {
|
|||||||
float_t pathTime, float_t totalTime, int32_t waypoint) {};
|
float_t pathTime, float_t totalTime, int32_t waypoint) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Script* GetInvalidScript();
|
||||||
Script* GetScript(Entity* parent, const std::string& scriptName);
|
Script* GetScript(Entity* parent, const std::string& scriptName);
|
||||||
std::vector<Script*> GetEntityScripts(Entity* entity);
|
std::vector<Script*> GetEntityScripts(Entity* entity);
|
||||||
};
|
};
|
@ -14,11 +14,22 @@ ScriptComponent::ScriptComponent(Entity* parent, std::string scriptName, bool se
|
|||||||
SetScript(scriptName);
|
SetScript(scriptName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScriptComponent::ScriptComponent(Entity* parent, bool serialized, bool client) : Component(parent) {
|
||||||
|
m_Serialized = serialized;
|
||||||
|
m_Client = client;
|
||||||
|
|
||||||
|
m_Script = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ScriptComponent::~ScriptComponent() {
|
ScriptComponent::~ScriptComponent() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void ScriptComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
||||||
|
if (!m_Serialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (bIsInitialUpdate) {
|
if (bIsInitialUpdate) {
|
||||||
const auto& networkSettings = m_Parent->GetNetworkSettings();
|
const auto& networkSettings = m_Parent->GetNetworkSettings();
|
||||||
auto hasNetworkSettings = !networkSettings.empty();
|
auto hasNetworkSettings = !networkSettings.empty();
|
||||||
@ -55,3 +66,7 @@ void ScriptComponent::SetScript(const std::string& scriptName) {
|
|||||||
|
|
||||||
m_Script = CppScripts::GetScript(m_Parent, scriptName);
|
m_Script = CppScripts::GetScript(m_Parent, scriptName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptComponent::SetScript(CppScripts::Script* script) {
|
||||||
|
m_Script = script;
|
||||||
|
}
|
||||||
|
@ -20,7 +20,8 @@ class Entity;
|
|||||||
class ScriptComponent : public Component {
|
class ScriptComponent : public Component {
|
||||||
public:
|
public:
|
||||||
static const uint32_t ComponentType = COMPONENT_TYPE_SCRIPT;
|
static const uint32_t ComponentType = COMPONENT_TYPE_SCRIPT;
|
||||||
|
|
||||||
|
ScriptComponent(Entity* parent, bool serialized, bool client = false);
|
||||||
ScriptComponent(Entity* parent, std::string scriptName, bool serialized, bool client = false);
|
ScriptComponent(Entity* parent, std::string scriptName, bool serialized, bool client = false);
|
||||||
~ScriptComponent() override;
|
~ScriptComponent() override;
|
||||||
|
|
||||||
@ -44,6 +45,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
void SetScript(const std::string& scriptName);
|
void SetScript(const std::string& scriptName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the script directly
|
||||||
|
* @param script the script to set
|
||||||
|
*/
|
||||||
|
void SetScript(CppScripts::Script* script);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user