SabrehavenServer/src/events.cpp
2019-09-16 20:38:16 +03:00

827 lines
24 KiB
C++

/**
* The Forgotten Server - a free and open-source MMORPG server emulator
* Copyright (C) 2016 Mark Samman <mark.samman@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "otpch.h"
#include "events.h"
#include "tools.h"
#include "item.h"
#include "player.h"
#include <set>
Events::Events() :
scriptInterface("Event Interface")
{
clear();
scriptInterface.initState();
}
void Events::clear()
{
// Creature
creatureOnChangeOutfit = -1;
creatureOnAreaCombat = -1;
creatureOnTargetCombat = -1;
// Party
partyOnJoin = -1;
partyOnLeave = -1;
partyOnDisband = -1;
// Player
playerOnLook = -1;
playerOnLookInBattleList = -1;
playerOnLookInTrade = -1;
playerOnMoveItem = -1;
playerOnItemMoved = -1;
playerOnMoveCreature = -1;
playerOnTurn = -1;
playerOnTradeRequest = -1;
playerOnTradeAccept = -1;
playerOnGainExperience = -1;
playerOnLoseExperience = -1;
playerOnGainSkillTries = -1;
playerOnReportBug = -1;
}
bool Events::load()
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file("data/events/events.xml");
if (!result) {
printXMLError("Error - Events::load", "data/events/events.xml", result);
return false;
}
std::set<std::string> classes;
for (auto eventNode : doc.child("events").children()) {
if (!eventNode.attribute("enabled").as_bool()) {
continue;
}
const std::string& className = eventNode.attribute("class").as_string();
auto res = classes.insert(className);
if (res.second) {
const std::string& lowercase = asLowerCaseString(className);
if (scriptInterface.loadFile("data/events/scripts/" + lowercase + ".lua") != 0) {
std::cout << "[Warning - Events::load] Can not load script: " << lowercase << ".lua" << std::endl;
std::cout << scriptInterface.getLastLuaError() << std::endl;
}
}
const std::string& methodName = eventNode.attribute("method").as_string();
const int32_t event = scriptInterface.getMetaEvent(className, methodName);
if (className == "Creature") {
if (methodName == "onChangeOutfit") {
creatureOnChangeOutfit = event;
}
else if (methodName == "onAreaCombat") {
creatureOnAreaCombat = event;
}
else if (methodName == "onTargetCombat") {
creatureOnTargetCombat = event;
}
else {
std::cout << "[Warning - Events::load] Unknown creature method: " << methodName << std::endl;
}
}
else if (className == "Party") {
if (methodName == "onJoin") {
partyOnJoin = event;
}
else if (methodName == "onLeave") {
partyOnLeave = event;
}
else if (methodName == "onDisband") {
partyOnDisband = event;
}
else if (methodName == "onShareExperience") {
partyOnShareExperience = event;
}
else {
std::cout << "[Warning - Events::load] Unknown party method: " << methodName << std::endl;
}
}
else if (className == "Player") {
if (methodName == "onLook") {
playerOnLook = event;
}
else if (methodName == "onLookInBattleList") {
playerOnLookInBattleList = event;
}
else if (methodName == "onLookInTrade") {
playerOnLookInTrade = event;
}
else if (methodName == "onTradeRequest") {
playerOnTradeRequest = event;
}
else if (methodName == "onTradeAccept") {
playerOnTradeAccept = event;
}
else if (methodName == "onMoveItem") {
playerOnMoveItem = event;
}
else if (methodName == "onItemMoved") {
playerOnItemMoved = event;
}
else if (methodName == "onMoveCreature") {
playerOnMoveCreature = event;
}
else if (methodName == "onReportBug") {
playerOnReportBug = event;
}
else if (methodName == "onTurn") {
playerOnTurn = event;
}
else if (methodName == "onGainExperience") {
playerOnGainExperience = event;
}
else if (methodName == "onLoseExperience") {
playerOnLoseExperience = event;
}
else if (methodName == "onGainSkillTries") {
playerOnGainSkillTries = event;
}
else {
std::cout << "[Warning - Events::load] Unknown player method: " << methodName << std::endl;
}
}
else {
std::cout << "[Warning - Events::load] Unknown class: " << className << std::endl;
}
}
return true;
}
// Creature
bool Events::eventCreatureOnChangeOutfit(Creature* creature, const Outfit_t& outfit)
{
// Creature:onChangeOutfit(outfit) or Creature.onChangeOutfit(self, outfit)
if (creatureOnChangeOutfit == -1) {
return true;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventCreatureOnChangeOutfit] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(creatureOnChangeOutfit, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(creatureOnChangeOutfit);
LuaScriptInterface::pushUserdata<Creature>(L, creature);
LuaScriptInterface::setCreatureMetatable(L, -1, creature);
LuaScriptInterface::pushOutfit(L, outfit);
return scriptInterface.callFunction(2);
}
ReturnValue Events::eventCreatureOnAreaCombat(Creature* creature, Tile* tile, bool aggressive)
{
// Creature:onAreaCombat(tile, aggressive) or Creature.onAreaCombat(self, tile, aggressive)
if (creatureOnAreaCombat == -1) {
return RETURNVALUE_NOERROR;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventCreatureOnAreaCombat] Call stack overflow" << std::endl;
return RETURNVALUE_NOTPOSSIBLE;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(creatureOnAreaCombat, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(creatureOnAreaCombat);
if (creature) {
LuaScriptInterface::pushUserdata<Creature>(L, creature);
LuaScriptInterface::setCreatureMetatable(L, -1, creature);
}
else {
lua_pushnil(L);
}
LuaScriptInterface::pushUserdata<Tile>(L, tile);
LuaScriptInterface::setMetatable(L, -1, "Tile");
LuaScriptInterface::pushBoolean(L, aggressive);
ReturnValue returnValue;
if (scriptInterface.protectedCall(L, 3, 1) != 0) {
returnValue = RETURNVALUE_NOTPOSSIBLE;
LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L));
}
else {
returnValue = LuaScriptInterface::getNumber<ReturnValue>(L, -1);
lua_pop(L, 1);
}
scriptInterface.resetScriptEnv();
return returnValue;
}
ReturnValue Events::eventCreatureOnTargetCombat(Creature* creature, Creature* target)
{
// Creature:onTargetCombat(target) or Creature.onTargetCombat(self, target)
if (creatureOnTargetCombat == -1) {
return RETURNVALUE_NOERROR;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventCreatureOnTargetCombat] Call stack overflow" << std::endl;
return RETURNVALUE_NOTPOSSIBLE;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(creatureOnTargetCombat, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(creatureOnTargetCombat);
if (creature) {
LuaScriptInterface::pushUserdata<Creature>(L, creature);
LuaScriptInterface::setCreatureMetatable(L, -1, creature);
}
else {
lua_pushnil(L);
}
LuaScriptInterface::pushUserdata<Creature>(L, target);
LuaScriptInterface::setCreatureMetatable(L, -1, target);
ReturnValue returnValue;
if (scriptInterface.protectedCall(L, 2, 1) != 0) {
returnValue = RETURNVALUE_NOTPOSSIBLE;
LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L));
}
else {
returnValue = LuaScriptInterface::getNumber<ReturnValue>(L, -1);
lua_pop(L, 1);
}
scriptInterface.resetScriptEnv();
return returnValue;
}
// Party
bool Events::eventPartyOnJoin(Party* party, Player* player)
{
// Party:onJoin(player) or Party.onJoin(self, player)
if (partyOnJoin == -1) {
return true;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPartyOnJoin] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(partyOnJoin, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(partyOnJoin);
LuaScriptInterface::pushUserdata<Party>(L, party);
LuaScriptInterface::setMetatable(L, -1, "Party");
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
return scriptInterface.callFunction(2);
}
bool Events::eventPartyOnLeave(Party* party, Player* player)
{
// Party:onLeave(player) or Party.onLeave(self, player)
if (partyOnLeave == -1) {
return true;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPartyOnLeave] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(partyOnLeave, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(partyOnLeave);
LuaScriptInterface::pushUserdata<Party>(L, party);
LuaScriptInterface::setMetatable(L, -1, "Party");
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
return scriptInterface.callFunction(2);
}
bool Events::eventPartyOnDisband(Party* party)
{
// Party:onDisband() or Party.onDisband(self)
if (partyOnDisband == -1) {
return true;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPartyOnDisband] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(partyOnDisband, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(partyOnDisband);
LuaScriptInterface::pushUserdata<Party>(L, party);
LuaScriptInterface::setMetatable(L, -1, "Party");
return scriptInterface.callFunction(1);
}
void Events::eventPartyOnShareExperience(Party* party, uint64_t& exp)
{
// Party:onShareExperience(exp) or Party.onShareExperience(self, exp)
if (partyOnShareExperience == -1) {
return;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPartyOnShareExperience] Call stack overflow" << std::endl;
return;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(partyOnShareExperience, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(partyOnShareExperience);
LuaScriptInterface::pushUserdata<Party>(L, party);
LuaScriptInterface::setMetatable(L, -1, "Party");
lua_pushnumber(L, exp);
if (scriptInterface.protectedCall(L, 2, 1) != 0) {
LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L));
}
else {
exp = LuaScriptInterface::getNumber<uint64_t>(L, -1);
lua_pop(L, 1);
}
scriptInterface.resetScriptEnv();
}
void Events::eventPlayerOnLook(Player* player, const Position& position, Thing* thing, uint8_t stackpos, int32_t lookDistance)
{
// Player:onLook(thing, position, distance) or Player.onLook(self, thing, position, distance)
if (playerOnLook == -1) {
return;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnLook] Call stack overflow" << std::endl;
return;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnLook, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnLook);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
if (Creature* creature = thing->getCreature()) {
LuaScriptInterface::pushUserdata<Creature>(L, creature);
LuaScriptInterface::setCreatureMetatable(L, -1, creature);
}
else if (Item* item = thing->getItem()) {
LuaScriptInterface::pushUserdata<Item>(L, item);
LuaScriptInterface::setItemMetatable(L, -1, item);
}
else {
lua_pushnil(L);
}
LuaScriptInterface::pushPosition(L, position, stackpos);
lua_pushnumber(L, lookDistance);
scriptInterface.callVoidFunction(4);
}
void Events::eventPlayerOnLookInBattleList(Player* player, Creature* creature, int32_t lookDistance)
{
// Player:onLookInBattleList(creature, position, distance) or Player.onLookInBattleList(self, creature, position, distance)
if (playerOnLookInBattleList == -1) {
return;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnLookInBattleList] Call stack overflow" << std::endl;
return;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnLookInBattleList, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnLookInBattleList);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<Creature>(L, creature);
LuaScriptInterface::setCreatureMetatable(L, -1, creature);
lua_pushnumber(L, lookDistance);
scriptInterface.callVoidFunction(3);
}
void Events::eventPlayerOnLookInTrade(Player* player, Player* partner, Item* item, int32_t lookDistance)
{
// Player:onLookInTrade(partner, item, distance) or Player.onLookInTrade(self, partner, item, distance)
if (playerOnLookInTrade == -1) {
return;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnLookInTrade] Call stack overflow" << std::endl;
return;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnLookInTrade, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnLookInTrade);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<Player>(L, partner);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<Item>(L, item);
LuaScriptInterface::setItemMetatable(L, -1, item);
lua_pushnumber(L, lookDistance);
scriptInterface.callVoidFunction(4);
}
bool Events::eventPlayerOnMoveItem(Player* player, Item* item, uint16_t count, const Position& fromPosition, const Position& toPosition, Cylinder* fromCylinder, Cylinder* toCylinder)
{
// Player:onMoveItem(item, count, fromPosition, toPosition) or Player.onMoveItem(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
if (playerOnMoveItem == -1) {
return true;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnMoveItem] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnMoveItem, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnMoveItem);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<Item>(L, item);
LuaScriptInterface::setItemMetatable(L, -1, item);
lua_pushnumber(L, count);
LuaScriptInterface::pushPosition(L, fromPosition);
LuaScriptInterface::pushPosition(L, toPosition);
LuaScriptInterface::pushCylinder(L, fromCylinder);
LuaScriptInterface::pushCylinder(L, toCylinder);
return scriptInterface.callFunction(7);
}
void Events::eventPlayerOnItemMoved(Player* player, Item* item, uint16_t count, const Position& fromPosition, const Position& toPosition, Cylinder* fromCylinder, Cylinder* toCylinder)
{
// Player:onItemMoved(item, count, fromPosition, toPosition) or Player.onItemMoved(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
if (playerOnItemMoved == -1) {
return;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnItemMoved] Call stack overflow" << std::endl;
return;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnItemMoved, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnItemMoved);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<Item>(L, item);
LuaScriptInterface::setItemMetatable(L, -1, item);
lua_pushnumber(L, count);
LuaScriptInterface::pushPosition(L, fromPosition);
LuaScriptInterface::pushPosition(L, toPosition);
LuaScriptInterface::pushCylinder(L, fromCylinder);
LuaScriptInterface::pushCylinder(L, toCylinder);
scriptInterface.callVoidFunction(7);
}
bool Events::eventPlayerOnMoveCreature(Player* player, Creature* creature, const Position& fromPosition, const Position& toPosition)
{
// Player:onMoveCreature(creature, fromPosition, toPosition) or Player.onMoveCreature(self, creature, fromPosition, toPosition)
if (playerOnMoveCreature == -1) {
return true;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnMoveCreature] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnMoveCreature, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnMoveCreature);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<Creature>(L, creature);
LuaScriptInterface::setCreatureMetatable(L, -1, creature);
LuaScriptInterface::pushPosition(L, fromPosition);
LuaScriptInterface::pushPosition(L, toPosition);
return scriptInterface.callFunction(4);
}
bool Events::eventPlayerOnReportBug(Player* player, const std::string& message, const Position& position)
{
// Player:onReportBug(message, position, category)
if (playerOnReportBug == -1) {
return true;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnReportBug] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnReportBug, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnReportBug);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushString(L, message);
LuaScriptInterface::pushPosition(L, position);
return scriptInterface.callFunction(3);
}
bool Events::eventPlayerOnTurn(Player* player, Direction direction)
{
// Player:onTurn(direction) or Player.onTurn(self, direction)
if (playerOnTurn == -1) {
return true;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnTurn] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnTurn, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnTurn);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
lua_pushnumber(L, direction);
return scriptInterface.callFunction(2);
}
bool Events::eventPlayerOnTradeRequest(Player* player, Player* target, Item* item)
{
// Player:onTradeRequest(target, item)
if (playerOnTradeRequest == -1) {
return true;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnTradeRequest] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnTradeRequest, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnTradeRequest);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<Player>(L, target);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<Item>(L, item);
LuaScriptInterface::setItemMetatable(L, -1, item);
return scriptInterface.callFunction(3);
}
bool Events::eventPlayerOnTradeAccept(Player* player, Player* target, Item* item, Item* targetItem)
{
// Player:onTradeAccept(target, item, targetItem)
if (playerOnTradeAccept == -1) {
return true;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnTradeAccept] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnTradeAccept, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnTradeAccept);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<Player>(L, target);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<Item>(L, item);
LuaScriptInterface::setItemMetatable(L, -1, item);
LuaScriptInterface::pushUserdata<Item>(L, targetItem);
LuaScriptInterface::setItemMetatable(L, -1, targetItem);
return scriptInterface.callFunction(4);
}
void Events::eventPlayerOnGainExperience(Player* player, Creature* source, uint64_t& exp, uint64_t rawExp)
{
// Player:onGainExperience(source, exp, rawExp)
// rawExp gives the original exp which is not multiplied
if (playerOnGainExperience == -1) {
return;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnGainExperience] Call stack overflow" << std::endl;
return;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnGainExperience, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnGainExperience);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
if (source) {
LuaScriptInterface::pushUserdata<Creature>(L, source);
LuaScriptInterface::setCreatureMetatable(L, -1, source);
}
else {
lua_pushnil(L);
}
lua_pushnumber(L, exp);
lua_pushnumber(L, rawExp);
if (scriptInterface.protectedCall(L, 4, 1) != 0) {
LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L));
}
else {
exp = LuaScriptInterface::getNumber<uint64_t>(L, -1);
lua_pop(L, 1);
}
scriptInterface.resetScriptEnv();
}
void Events::eventPlayerOnLoseExperience(Player* player, uint64_t& exp)
{
// Player:onLoseExperience(exp)
if (playerOnLoseExperience == -1) {
return;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnLoseExperience] Call stack overflow" << std::endl;
return;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnLoseExperience, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnLoseExperience);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
lua_pushnumber(L, exp);
if (scriptInterface.protectedCall(L, 2, 1) != 0) {
LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L));
}
else {
exp = LuaScriptInterface::getNumber<uint64_t>(L, -1);
lua_pop(L, 1);
}
scriptInterface.resetScriptEnv();
}
void Events::eventPlayerOnGainSkillTries(Player* player, skills_t skill, uint64_t& tries)
{
// Player:onGainSkillTries(skill, tries)
if (playerOnGainSkillTries == -1) {
return;
}
if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnGainSkillTries] Call stack overflow" << std::endl;
return;
}
ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(playerOnGainSkillTries, &scriptInterface);
lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(playerOnGainSkillTries);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
lua_pushnumber(L, skill);
lua_pushnumber(L, tries);
if (scriptInterface.protectedCall(L, 3, 1) != 0) {
LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L));
}
else {
tries = LuaScriptInterface::getNumber<uint64_t>(L, -1);
lua_pop(L, 1);
}
scriptInterface.resetScriptEnv();
}