mirror of
https://github.com/ErikasKontenis/SabrehavenServer.git
synced 2025-05-01 01:59:21 +02:00
827 lines
24 KiB
C++
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();
|
|
} |