2023-02-18 20:10:02 -03:00
|
|
|
// Copyright 2023 The Forgotten Server Authors. All rights reserved.
|
2022-02-22 15:41:21 -03:00
|
|
|
// Use of this source code is governed by the GPL-2.0 License that can be found in the LICENSE file.
|
2013-07-07 02:30:08 +02:00
|
|
|
|
|
|
|
|
#include "otpch.h"
|
|
|
|
|
|
|
|
|
|
#include "creatureevent.h"
|
2022-03-18 21:20:02 +01:00
|
|
|
|
|
|
|
|
#include "item.h"
|
2013-07-07 02:30:08 +02:00
|
|
|
#include "tools.h"
|
|
|
|
|
|
2022-04-13 14:06:08 +00:00
|
|
|
CreatureEvents::CreatureEvents() : scriptInterface("CreatureScript Interface") { scriptInterface.initState(); }
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2019-04-26 14:22:33 +02:00
|
|
|
void CreatureEvents::clear(bool fromLua)
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2019-08-09 00:16:11 +02:00
|
|
|
for (auto it = creatureEvents.begin(); it != creatureEvents.end(); ++it) {
|
2019-04-26 14:22:33 +02:00
|
|
|
if (fromLua == it->second.fromLua) {
|
2019-08-09 00:16:11 +02:00
|
|
|
it->second.clearEvent();
|
2019-04-26 14:22:33 +02:00
|
|
|
}
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2019-04-26 14:22:33 +02:00
|
|
|
reInitState(fromLua);
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-18 01:38:04 -04:00
|
|
|
void CreatureEvents::removeInvalidEvents()
|
|
|
|
|
{
|
2024-05-07 12:57:58 +02:00
|
|
|
for (auto it = creatureEvents.begin(); it != creatureEvents.end();) {
|
2020-04-18 01:38:04 -04:00
|
|
|
if (it->second.getScriptId() == 0) {
|
2024-05-07 12:57:58 +02:00
|
|
|
it = creatureEvents.erase(it);
|
|
|
|
|
} else {
|
|
|
|
|
++it;
|
2020-04-18 01:38:04 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-13 14:06:08 +00:00
|
|
|
LuaScriptInterface& CreatureEvents::getScriptInterface() { return scriptInterface; }
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2018-01-02 02:03:10 -02:00
|
|
|
Event_ptr CreatureEvents::getEvent(const std::string& nodeName)
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-03-17 20:15:08 +01:00
|
|
|
if (!caseInsensitiveEqual(nodeName, "event")) {
|
2014-12-30 02:41:09 +01:00
|
|
|
return nullptr;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
2018-01-02 02:03:10 -02:00
|
|
|
return Event_ptr(new CreatureEvent(&scriptInterface));
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2018-01-02 02:03:10 -02:00
|
|
|
bool CreatureEvents::registerEvent(Event_ptr event, const pugi::xml_node&)
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
CreatureEvent_ptr creatureEvent{
|
|
|
|
|
static_cast<CreatureEvent*>(event.release())}; // event is guaranteed to be a CreatureEvent
|
2013-07-07 02:30:08 +02:00
|
|
|
if (creatureEvent->getEventType() == CREATURE_EVENT_NONE) {
|
|
|
|
|
std::cout << "Error: [CreatureEvents::registerEvent] Trying to register event without type!" << std::endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-09 00:16:11 +02:00
|
|
|
CreatureEvent* oldEvent = getEventByName(creatureEvent->getName(), false);
|
|
|
|
|
if (oldEvent) {
|
2022-04-13 14:06:08 +00:00
|
|
|
// if there was an event with the same that is not loaded
|
2021-02-22 00:34:23 -03:00
|
|
|
//(happens when reloading), it is reused
|
2019-08-09 00:16:11 +02:00
|
|
|
if (!oldEvent->isLoaded() && oldEvent->getEventType() == creatureEvent->getEventType()) {
|
|
|
|
|
oldEvent->copyEvent(creatureEvent.get());
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-09-25 11:24:03 -03:00
|
|
|
|
|
|
|
|
// if not, register it normally
|
2024-10-31 21:00:00 -03:00
|
|
|
creatureEvents.emplace(boost::algorithm::to_lower_copy(creatureEvent->getName()), std::move(*creatureEvent));
|
2021-09-25 11:24:03 -03:00
|
|
|
return true;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2019-04-26 14:22:33 +02:00
|
|
|
bool CreatureEvents::registerLuaEvent(CreatureEvent* event)
|
revscriptsys (#2558)
* initial revscriptsys
creates a new folder called 'scripts' in the data folder.
lua files placed in the 'scripts' or sub folders will automaticly get registered on load with the right setup ofcourse.
Registering happens in the lua file itself, doesn't require xml settings.
lua files can be deactivated by placing a '#' infront of the filename ex: '#positions.lua' it wont get loaded then.
Currently it supports:
-Actions
-TalkActions
-CreatureEvents
-GlobalEvents
-MoveEvents
There is still stuff on the todo list but they'll get added sooner or later.
Co-Authored-By: Sam <thesumm@users.noreply.github.com>
* compiler fixes
added boost-filesystem to appveyor.yml
fixed a few more compiler errors.
* cleanup on script.cpp
removed using namespace for std / boost filesystem
* some fixes
had to make adjustment so lua callbacks and xml settings work alongside and don't crash the server
* small fixes on movements & function additions
Have to revert the function + callback for stepin/stepout & additem/removeitem as it doesn't make sense on the second look and might cause a stackoverflow
I've also reworked the equip/dequip so it doesn't get double calls.
It'll first check if functions return true if not it won't bother to read the callback
accidently used an old spellbook.lua
added :aid(ids) :uid(ids) functions for MoveEvents
* revert to 'using' functions and suggestion of Djarek
Could revert most of movements.h
made the declaration of the static functions more clear
Co-Authored-By: Damian Jarek <djarek@users.noreply.github.com>
* small fixes
removed commentary from movement.cpp
added newline for position.lua
reworked spellbook.lua with table.concat
* Monster handler & other stuff
- MonsterType's can now be created through lua functions.
- added an interface to create MonsterType's easily through lua files (register_monster_type.lua)
- added #example.lua in 'scripts\monsters\'
- renamed action vector functions for a better standard
- renamed _lib folder to lib, this folder gets now loaded when the other lib folder gets loaded aswell
- moved loading lua scripts out of the scriptfilemanager, we need to load everything after monsters etc. is loaded so MonsterType script manipulation does work
- added Loot() & MonsterSpell() metatables
* fix compiler error
* forgot to remove test code
removed test outfit from MonsterType
* small changes
- added createFunctions(class) it virtually creates the get/set functions for the class passed on
- 'events' folder in monsters is excluded from auto parsing files, as we load callbacks for specific monsters which have an eventFile set to 'true' or 'filename' in this folder.
* compiler error fix
* minor change on createFunctions
* stripping path string
* added Game.createMonsterType(name) and small fixes
- added Game.createMonsterType(name)
- reworked MonsterType(name) to return nil if the MonsterType does not exist, so we don't suddenly create a MonsterType if we do not even want to.
- changed reinterpret_cast to static_cast
* config.lua option for console
- added an option to disable scripts console logging, it can be disabled by placing 'showScriptsLogInConsole = false' into config.lua
* initial revscriptsys
creates a new folder called 'scripts' in the data folder.
lua files placed in the 'scripts' or sub folders will automaticly get registered on load with the right setup ofcourse.
Registering happens in the lua file itself, doesn't require xml settings.
lua files can be deactivated by placing a '#' infront of the filename ex: '#positions.lua' it wont get loaded then.
Currently it supports:
-Actions
-TalkActions
-CreatureEvents
-GlobalEvents
-MoveEvents
There is still stuff on the todo list but they'll get added sooner or later.
Co-Authored-By: Sam <thesumm@users.noreply.github.com>
cleanup on script.cpp
removed using namespace for std / boost filesystem
small fixes on movements & function additions
Have to revert the function + callback for stepin/stepout & additem/removeitem as it doesn't make sense on the second look and might cause a stackoverflow
I've also reworked the equip/dequip so it doesn't get double calls.
It'll first check if functions return true if not it won't bother to read the callback
accidently used an old spellbook.lua
added :aid(ids) :uid(ids) functions for MoveEvents
Monster handler & other stuff
- MonsterType's can now be created through lua functions.
- added an interface to create MonsterType's easily through lua files (register_monster_type.lua)
- added #example.lua in 'scripts\monsters\'
- renamed action vector functions for a better standard
- renamed _lib folder to lib, this folder gets now loaded when the other lib folder gets loaded aswell
- moved loading lua scripts out of the scriptfilemanager, we need to load everything after monsters etc. is loaded so MonsterType script manipulation does work
- added Loot() & MonsterSpell() metatables
small changes
- added createFunctions(class) it virtually creates the get/set functions for the class passed on
- 'events' folder in monsters is excluded from auto parsing files, as we load callbacks for specific monsters which have an eventFile set to 'true' or 'filename' in this folder.
stripping path string
added Game.createMonsterType(name) and small fixes
- added Game.createMonsterType(name)
- reworked MonsterType(name) to return nil if the MonsterType does not exist, so we don't suddenly create a MonsterType if we do not even want to.
- changed reinterpret_cast to static_cast
config.lua option for console
- added an option to disable scripts console logging, it can be disabled by placing 'showScriptsLogInConsole = false' into config.lua
2019-04-16 16:33:38 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
CreatureEvent_ptr creatureEvent{event};
|
revscriptsys (#2558)
* initial revscriptsys
creates a new folder called 'scripts' in the data folder.
lua files placed in the 'scripts' or sub folders will automaticly get registered on load with the right setup ofcourse.
Registering happens in the lua file itself, doesn't require xml settings.
lua files can be deactivated by placing a '#' infront of the filename ex: '#positions.lua' it wont get loaded then.
Currently it supports:
-Actions
-TalkActions
-CreatureEvents
-GlobalEvents
-MoveEvents
There is still stuff on the todo list but they'll get added sooner or later.
Co-Authored-By: Sam <thesumm@users.noreply.github.com>
* compiler fixes
added boost-filesystem to appveyor.yml
fixed a few more compiler errors.
* cleanup on script.cpp
removed using namespace for std / boost filesystem
* some fixes
had to make adjustment so lua callbacks and xml settings work alongside and don't crash the server
* small fixes on movements & function additions
Have to revert the function + callback for stepin/stepout & additem/removeitem as it doesn't make sense on the second look and might cause a stackoverflow
I've also reworked the equip/dequip so it doesn't get double calls.
It'll first check if functions return true if not it won't bother to read the callback
accidently used an old spellbook.lua
added :aid(ids) :uid(ids) functions for MoveEvents
* revert to 'using' functions and suggestion of Djarek
Could revert most of movements.h
made the declaration of the static functions more clear
Co-Authored-By: Damian Jarek <djarek@users.noreply.github.com>
* small fixes
removed commentary from movement.cpp
added newline for position.lua
reworked spellbook.lua with table.concat
* Monster handler & other stuff
- MonsterType's can now be created through lua functions.
- added an interface to create MonsterType's easily through lua files (register_monster_type.lua)
- added #example.lua in 'scripts\monsters\'
- renamed action vector functions for a better standard
- renamed _lib folder to lib, this folder gets now loaded when the other lib folder gets loaded aswell
- moved loading lua scripts out of the scriptfilemanager, we need to load everything after monsters etc. is loaded so MonsterType script manipulation does work
- added Loot() & MonsterSpell() metatables
* fix compiler error
* forgot to remove test code
removed test outfit from MonsterType
* small changes
- added createFunctions(class) it virtually creates the get/set functions for the class passed on
- 'events' folder in monsters is excluded from auto parsing files, as we load callbacks for specific monsters which have an eventFile set to 'true' or 'filename' in this folder.
* compiler error fix
* minor change on createFunctions
* stripping path string
* added Game.createMonsterType(name) and small fixes
- added Game.createMonsterType(name)
- reworked MonsterType(name) to return nil if the MonsterType does not exist, so we don't suddenly create a MonsterType if we do not even want to.
- changed reinterpret_cast to static_cast
* config.lua option for console
- added an option to disable scripts console logging, it can be disabled by placing 'showScriptsLogInConsole = false' into config.lua
* initial revscriptsys
creates a new folder called 'scripts' in the data folder.
lua files placed in the 'scripts' or sub folders will automaticly get registered on load with the right setup ofcourse.
Registering happens in the lua file itself, doesn't require xml settings.
lua files can be deactivated by placing a '#' infront of the filename ex: '#positions.lua' it wont get loaded then.
Currently it supports:
-Actions
-TalkActions
-CreatureEvents
-GlobalEvents
-MoveEvents
There is still stuff on the todo list but they'll get added sooner or later.
Co-Authored-By: Sam <thesumm@users.noreply.github.com>
cleanup on script.cpp
removed using namespace for std / boost filesystem
small fixes on movements & function additions
Have to revert the function + callback for stepin/stepout & additem/removeitem as it doesn't make sense on the second look and might cause a stackoverflow
I've also reworked the equip/dequip so it doesn't get double calls.
It'll first check if functions return true if not it won't bother to read the callback
accidently used an old spellbook.lua
added :aid(ids) :uid(ids) functions for MoveEvents
Monster handler & other stuff
- MonsterType's can now be created through lua functions.
- added an interface to create MonsterType's easily through lua files (register_monster_type.lua)
- added #example.lua in 'scripts\monsters\'
- renamed action vector functions for a better standard
- renamed _lib folder to lib, this folder gets now loaded when the other lib folder gets loaded aswell
- moved loading lua scripts out of the scriptfilemanager, we need to load everything after monsters etc. is loaded so MonsterType script manipulation does work
- added Loot() & MonsterSpell() metatables
small changes
- added createFunctions(class) it virtually creates the get/set functions for the class passed on
- 'events' folder in monsters is excluded from auto parsing files, as we load callbacks for specific monsters which have an eventFile set to 'true' or 'filename' in this folder.
stripping path string
added Game.createMonsterType(name) and small fixes
- added Game.createMonsterType(name)
- reworked MonsterType(name) to return nil if the MonsterType does not exist, so we don't suddenly create a MonsterType if we do not even want to.
- changed reinterpret_cast to static_cast
config.lua option for console
- added an option to disable scripts console logging, it can be disabled by placing 'showScriptsLogInConsole = false' into config.lua
2019-04-16 16:33:38 +02:00
|
|
|
if (creatureEvent->getEventType() == CREATURE_EVENT_NONE) {
|
|
|
|
|
std::cout << "Error: [CreatureEvents::registerLuaEvent] Trying to register event without type!" << std::endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-09 00:16:11 +02:00
|
|
|
CreatureEvent* oldEvent = getEventByName(creatureEvent->getName(), false);
|
|
|
|
|
if (oldEvent) {
|
2022-04-13 14:06:08 +00:00
|
|
|
// if there was an event with the same that is not loaded
|
2021-02-22 00:34:23 -03:00
|
|
|
//(happens when reloading), it is reused
|
2019-08-09 00:16:11 +02:00
|
|
|
if (!oldEvent->isLoaded() && oldEvent->getEventType() == creatureEvent->getEventType()) {
|
|
|
|
|
oldEvent->copyEvent(creatureEvent.get());
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-09-25 11:24:03 -03:00
|
|
|
|
|
|
|
|
// if not, register it normally
|
2024-10-31 21:00:00 -03:00
|
|
|
creatureEvents.emplace(boost::algorithm::to_lower_copy(creatureEvent->getName()), std::move(*creatureEvent));
|
2021-09-25 11:24:03 -03:00
|
|
|
return true;
|
revscriptsys (#2558)
* initial revscriptsys
creates a new folder called 'scripts' in the data folder.
lua files placed in the 'scripts' or sub folders will automaticly get registered on load with the right setup ofcourse.
Registering happens in the lua file itself, doesn't require xml settings.
lua files can be deactivated by placing a '#' infront of the filename ex: '#positions.lua' it wont get loaded then.
Currently it supports:
-Actions
-TalkActions
-CreatureEvents
-GlobalEvents
-MoveEvents
There is still stuff on the todo list but they'll get added sooner or later.
Co-Authored-By: Sam <thesumm@users.noreply.github.com>
* compiler fixes
added boost-filesystem to appveyor.yml
fixed a few more compiler errors.
* cleanup on script.cpp
removed using namespace for std / boost filesystem
* some fixes
had to make adjustment so lua callbacks and xml settings work alongside and don't crash the server
* small fixes on movements & function additions
Have to revert the function + callback for stepin/stepout & additem/removeitem as it doesn't make sense on the second look and might cause a stackoverflow
I've also reworked the equip/dequip so it doesn't get double calls.
It'll first check if functions return true if not it won't bother to read the callback
accidently used an old spellbook.lua
added :aid(ids) :uid(ids) functions for MoveEvents
* revert to 'using' functions and suggestion of Djarek
Could revert most of movements.h
made the declaration of the static functions more clear
Co-Authored-By: Damian Jarek <djarek@users.noreply.github.com>
* small fixes
removed commentary from movement.cpp
added newline for position.lua
reworked spellbook.lua with table.concat
* Monster handler & other stuff
- MonsterType's can now be created through lua functions.
- added an interface to create MonsterType's easily through lua files (register_monster_type.lua)
- added #example.lua in 'scripts\monsters\'
- renamed action vector functions for a better standard
- renamed _lib folder to lib, this folder gets now loaded when the other lib folder gets loaded aswell
- moved loading lua scripts out of the scriptfilemanager, we need to load everything after monsters etc. is loaded so MonsterType script manipulation does work
- added Loot() & MonsterSpell() metatables
* fix compiler error
* forgot to remove test code
removed test outfit from MonsterType
* small changes
- added createFunctions(class) it virtually creates the get/set functions for the class passed on
- 'events' folder in monsters is excluded from auto parsing files, as we load callbacks for specific monsters which have an eventFile set to 'true' or 'filename' in this folder.
* compiler error fix
* minor change on createFunctions
* stripping path string
* added Game.createMonsterType(name) and small fixes
- added Game.createMonsterType(name)
- reworked MonsterType(name) to return nil if the MonsterType does not exist, so we don't suddenly create a MonsterType if we do not even want to.
- changed reinterpret_cast to static_cast
* config.lua option for console
- added an option to disable scripts console logging, it can be disabled by placing 'showScriptsLogInConsole = false' into config.lua
* initial revscriptsys
creates a new folder called 'scripts' in the data folder.
lua files placed in the 'scripts' or sub folders will automaticly get registered on load with the right setup ofcourse.
Registering happens in the lua file itself, doesn't require xml settings.
lua files can be deactivated by placing a '#' infront of the filename ex: '#positions.lua' it wont get loaded then.
Currently it supports:
-Actions
-TalkActions
-CreatureEvents
-GlobalEvents
-MoveEvents
There is still stuff on the todo list but they'll get added sooner or later.
Co-Authored-By: Sam <thesumm@users.noreply.github.com>
cleanup on script.cpp
removed using namespace for std / boost filesystem
small fixes on movements & function additions
Have to revert the function + callback for stepin/stepout & additem/removeitem as it doesn't make sense on the second look and might cause a stackoverflow
I've also reworked the equip/dequip so it doesn't get double calls.
It'll first check if functions return true if not it won't bother to read the callback
accidently used an old spellbook.lua
added :aid(ids) :uid(ids) functions for MoveEvents
Monster handler & other stuff
- MonsterType's can now be created through lua functions.
- added an interface to create MonsterType's easily through lua files (register_monster_type.lua)
- added #example.lua in 'scripts\monsters\'
- renamed action vector functions for a better standard
- renamed _lib folder to lib, this folder gets now loaded when the other lib folder gets loaded aswell
- moved loading lua scripts out of the scriptfilemanager, we need to load everything after monsters etc. is loaded so MonsterType script manipulation does work
- added Loot() & MonsterSpell() metatables
small changes
- added createFunctions(class) it virtually creates the get/set functions for the class passed on
- 'events' folder in monsters is excluded from auto parsing files, as we load callbacks for specific monsters which have an eventFile set to 'true' or 'filename' in this folder.
stripping path string
added Game.createMonsterType(name) and small fixes
- added Game.createMonsterType(name)
- reworked MonsterType(name) to return nil if the MonsterType does not exist, so we don't suddenly create a MonsterType if we do not even want to.
- changed reinterpret_cast to static_cast
config.lua option for console
- added an option to disable scripts console logging, it can be disabled by placing 'showScriptsLogInConsole = false' into config.lua
2019-04-16 16:33:38 +02:00
|
|
|
}
|
|
|
|
|
|
2013-07-07 02:30:08 +02:00
|
|
|
CreatureEvent* CreatureEvents::getEventByName(const std::string& name, bool forceLoaded /*= true*/)
|
|
|
|
|
{
|
2024-10-31 21:00:00 -03:00
|
|
|
auto it = creatureEvents.find(boost::algorithm::to_lower_copy(name));
|
2016-02-06 21:15:41 -08:00
|
|
|
if (it != creatureEvents.end()) {
|
2018-01-02 02:03:10 -02:00
|
|
|
if (!forceLoaded || it->second.isLoaded()) {
|
|
|
|
|
return &it->second;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
2013-09-22 02:02:19 +02:00
|
|
|
return nullptr;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2013-11-03 03:47:47 +01:00
|
|
|
bool CreatureEvents::playerLogin(Player* player) const
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// fire global event if is registered
|
2016-02-06 21:15:41 -08:00
|
|
|
for (const auto& it : creatureEvents) {
|
2018-01-02 02:03:10 -02:00
|
|
|
if (it.second.getEventType() == CREATURE_EVENT_LOGIN) {
|
|
|
|
|
if (!it.second.executeOnLogin(player)) {
|
2013-07-24 20:48:22 +02:00
|
|
|
return false;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-07-24 20:48:22 +02:00
|
|
|
return true;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2013-11-03 03:47:47 +01:00
|
|
|
bool CreatureEvents::playerLogout(Player* player) const
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// fire global event if is registered
|
2016-02-06 21:15:41 -08:00
|
|
|
for (const auto& it : creatureEvents) {
|
2018-01-02 02:03:10 -02:00
|
|
|
if (it.second.getEventType() == CREATURE_EVENT_LOGOUT) {
|
|
|
|
|
if (!it.second.executeOnLogout(player)) {
|
2013-07-24 20:48:22 +02:00
|
|
|
return false;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-07-24 20:48:22 +02:00
|
|
|
return true;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2024-11-17 13:53:22 -03:00
|
|
|
void CreatureEvents::playerReconnect(Player* player) const
|
|
|
|
|
{
|
|
|
|
|
// fire global event if is registered
|
|
|
|
|
for (const auto& it : creatureEvents) {
|
|
|
|
|
if (it.second.getEventType() == CREATURE_EVENT_RECONNECT) {
|
|
|
|
|
it.second.executeOnReconnect(player);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-13 14:06:08 +00:00
|
|
|
bool CreatureEvents::playerAdvance(Player* player, skills_t skill, uint32_t oldLevel, uint32_t newLevel)
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2024-11-17 13:53:22 -03:00
|
|
|
// fire global event if is registered
|
2018-01-02 02:03:10 -02:00
|
|
|
for (auto& it : creatureEvents) {
|
|
|
|
|
if (it.second.getEventType() == CREATURE_EVENT_ADVANCE) {
|
|
|
|
|
if (!it.second.executeAdvance(player, skill, oldLevel, newLevel)) {
|
2013-07-24 20:48:22 +02:00
|
|
|
return false;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-07-24 20:48:22 +02:00
|
|
|
return true;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////
|
|
|
|
|
|
2022-04-13 14:06:08 +00:00
|
|
|
CreatureEvent::CreatureEvent(LuaScriptInterface* interface) : Event(interface), type(CREATURE_EVENT_NONE), loaded(false)
|
|
|
|
|
{}
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2013-09-19 05:49:19 +02:00
|
|
|
bool CreatureEvent::configureEvent(const pugi::xml_node& node)
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// Name that will be used in monster xml files and lua function to register events to reference this event
|
2013-09-19 05:49:19 +02:00
|
|
|
pugi::xml_attribute nameAttribute = node.attribute("name");
|
|
|
|
|
if (!nameAttribute) {
|
|
|
|
|
std::cout << "[Error - CreatureEvent::configureEvent] Missing name for creature event" << std::endl;
|
2013-07-07 02:30:08 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
eventName = nameAttribute.as_string();
|
2013-09-19 05:49:19 +02:00
|
|
|
|
|
|
|
|
pugi::xml_attribute typeAttribute = node.attribute("type");
|
|
|
|
|
if (!typeAttribute) {
|
2022-04-13 14:06:08 +00:00
|
|
|
std::cout << "[Error - CreatureEvent::configureEvent] Missing type for creature event: " << eventName
|
|
|
|
|
<< std::endl;
|
2013-09-19 05:49:19 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-22 02:54:08 +01:00
|
|
|
std::string tmpStr = boost::algorithm::to_lower_copy<std::string>(typeAttribute.as_string());
|
2013-09-19 05:49:19 +02:00
|
|
|
if (tmpStr == "login") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_LOGIN;
|
2013-09-19 05:49:19 +02:00
|
|
|
} else if (tmpStr == "logout") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_LOGOUT;
|
2024-11-17 13:53:22 -03:00
|
|
|
} else if (tmpStr == "reconnect") {
|
|
|
|
|
type = CREATURE_EVENT_RECONNECT;
|
2013-09-19 05:49:19 +02:00
|
|
|
} else if (tmpStr == "think") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_THINK;
|
2013-09-19 05:49:19 +02:00
|
|
|
} else if (tmpStr == "preparedeath") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_PREPAREDEATH;
|
2013-09-19 05:49:19 +02:00
|
|
|
} else if (tmpStr == "death") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_DEATH;
|
2013-09-19 05:49:19 +02:00
|
|
|
} else if (tmpStr == "kill") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_KILL;
|
2013-09-19 05:49:19 +02:00
|
|
|
} else if (tmpStr == "advance") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_ADVANCE;
|
2013-09-19 05:49:19 +02:00
|
|
|
} else if (tmpStr == "modalwindow") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_MODALWINDOW;
|
2013-09-19 05:49:19 +02:00
|
|
|
} else if (tmpStr == "textedit") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_TEXTEDIT;
|
2014-08-19 15:37:56 +02:00
|
|
|
} else if (tmpStr == "healthchange") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_HEALTHCHANGE;
|
2014-08-19 15:37:56 +02:00
|
|
|
} else if (tmpStr == "manachange") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_MANACHANGE;
|
2013-11-07 23:49:36 +01:00
|
|
|
} else if (tmpStr == "extendedopcode") {
|
2016-02-06 21:15:41 -08:00
|
|
|
type = CREATURE_EVENT_EXTENDED_OPCODE;
|
2013-07-07 02:30:08 +02:00
|
|
|
} else {
|
2022-04-13 14:06:08 +00:00
|
|
|
std::cout << "[Error - CreatureEvent::configureEvent] Invalid type for creature event: " << eventName
|
|
|
|
|
<< std::endl;
|
2013-07-07 02:30:08 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
loaded = true;
|
2013-07-07 02:30:08 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-09 01:49:18 +01:00
|
|
|
std::string_view CreatureEvent::getScriptEventName() const
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// Depending on the type script event name is different
|
2016-02-06 21:15:41 -08:00
|
|
|
switch (type) {
|
2013-07-07 02:30:08 +02:00
|
|
|
case CREATURE_EVENT_LOGIN:
|
|
|
|
|
return "onLogin";
|
|
|
|
|
|
|
|
|
|
case CREATURE_EVENT_LOGOUT:
|
|
|
|
|
return "onLogout";
|
|
|
|
|
|
2024-11-17 13:53:22 -03:00
|
|
|
case CREATURE_EVENT_RECONNECT:
|
|
|
|
|
return "onReconnect";
|
|
|
|
|
|
2013-07-07 02:30:08 +02:00
|
|
|
case CREATURE_EVENT_THINK:
|
|
|
|
|
return "onThink";
|
|
|
|
|
|
|
|
|
|
case CREATURE_EVENT_PREPAREDEATH:
|
|
|
|
|
return "onPrepareDeath";
|
|
|
|
|
|
|
|
|
|
case CREATURE_EVENT_DEATH:
|
|
|
|
|
return "onDeath";
|
|
|
|
|
|
|
|
|
|
case CREATURE_EVENT_KILL:
|
|
|
|
|
return "onKill";
|
|
|
|
|
|
|
|
|
|
case CREATURE_EVENT_ADVANCE:
|
|
|
|
|
return "onAdvance";
|
2013-11-10 02:13:09 +01:00
|
|
|
|
2013-08-06 23:02:52 +02:00
|
|
|
case CREATURE_EVENT_MODALWINDOW:
|
|
|
|
|
return "onModalWindow";
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2013-08-07 12:00:15 +02:00
|
|
|
case CREATURE_EVENT_TEXTEDIT:
|
|
|
|
|
return "onTextEdit";
|
|
|
|
|
|
2014-08-19 15:37:56 +02:00
|
|
|
case CREATURE_EVENT_HEALTHCHANGE:
|
|
|
|
|
return "onHealthChange";
|
2013-10-20 18:20:33 +02:00
|
|
|
|
2014-08-19 15:37:56 +02:00
|
|
|
case CREATURE_EVENT_MANACHANGE:
|
|
|
|
|
return "onManaChange";
|
2013-10-20 18:20:33 +02:00
|
|
|
|
2013-11-07 23:49:36 +01:00
|
|
|
case CREATURE_EVENT_EXTENDED_OPCODE:
|
|
|
|
|
return "onExtendedOpcode";
|
|
|
|
|
|
2013-07-07 02:30:08 +02:00
|
|
|
case CREATURE_EVENT_NONE:
|
|
|
|
|
default:
|
2023-03-09 01:49:18 +01:00
|
|
|
return "";
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CreatureEvent::copyEvent(CreatureEvent* creatureEvent)
|
|
|
|
|
{
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptId = creatureEvent->scriptId;
|
|
|
|
|
scriptInterface = creatureEvent->scriptInterface;
|
|
|
|
|
scripted = creatureEvent->scripted;
|
|
|
|
|
loaded = creatureEvent->loaded;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CreatureEvent::clearEvent()
|
|
|
|
|
{
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptId = 0;
|
|
|
|
|
scriptInterface = nullptr;
|
|
|
|
|
scripted = false;
|
|
|
|
|
loaded = false;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2018-01-02 02:03:10 -02:00
|
|
|
bool CreatureEvent::executeOnLogin(Player* player) const
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// onLogin(player)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2013-08-12 00:09:14 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeOnLogin] Call stack overflow" << std::endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->pushFunction(scriptId);
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, player);
|
|
|
|
|
tfs::lua::setMetatable(L, -1, "Player");
|
2016-02-06 21:15:41 -08:00
|
|
|
return scriptInterface->callFunction(1);
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2018-01-02 02:03:10 -02:00
|
|
|
bool CreatureEvent::executeOnLogout(Player* player) const
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// onLogout(player)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2013-08-12 00:09:14 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeOnLogout] Call stack overflow" << std::endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->pushFunction(scriptId);
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, player);
|
|
|
|
|
tfs::lua::setMetatable(L, -1, "Player");
|
2016-02-06 21:15:41 -08:00
|
|
|
return scriptInterface->callFunction(1);
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2024-11-17 13:53:22 -03:00
|
|
|
void CreatureEvent::executeOnReconnect(Player* player) const
|
|
|
|
|
{
|
|
|
|
|
// onReconnect(player)
|
|
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
|
|
|
|
std::cout << "[Error - CreatureEvent::executeOnReconnect] Call stack overflow" << std::endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
|
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
|
|
|
|
|
|
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
|
|
|
|
|
|
|
|
|
scriptInterface->pushFunction(scriptId);
|
|
|
|
|
tfs::lua::pushUserdata(L, player);
|
|
|
|
|
tfs::lua::setMetatable(L, -1, "Player");
|
|
|
|
|
scriptInterface->callFunction(1);
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-07 21:31:40 +02:00
|
|
|
bool CreatureEvent::executeOnThink(Creature* creature, uint32_t interval)
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// onThink(creature, interval)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2013-08-12 00:09:14 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeOnThink] Call stack overflow" << std::endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->pushFunction(scriptId);
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, creature);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, creature);
|
2013-08-07 21:31:40 +02:00
|
|
|
lua_pushnumber(L, interval);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
return scriptInterface->callFunction(2);
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-07 21:31:40 +02:00
|
|
|
bool CreatureEvent::executeOnPrepareDeath(Creature* creature, Creature* killer)
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// onPrepareDeath(creature, killer)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2013-08-12 00:09:14 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeOnPrepareDeath] Call stack overflow" << std::endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->pushFunction(scriptId);
|
2014-11-03 19:10:51 +01:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, creature);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, creature);
|
2014-11-03 19:10:51 +01:00
|
|
|
|
|
|
|
|
if (killer) {
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, killer);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, killer);
|
2014-11-03 19:10:51 +01:00
|
|
|
} else {
|
|
|
|
|
lua_pushnil(L);
|
|
|
|
|
}
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
return scriptInterface->callFunction(2);
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-13 14:06:08 +00:00
|
|
|
bool CreatureEvent::executeOnDeath(Creature* creature, Item* corpse, Creature* killer, Creature* mostDamageKiller,
|
|
|
|
|
bool lastHitUnjustified, bool mostDamageUnjustified)
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2013-08-12 00:09:14 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeOnDeath] Call stack overflow" << std::endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
2014-11-03 19:10:51 +01:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->pushFunction(scriptId);
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, creature);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, creature);
|
2015-03-15 14:26:38 +01:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushThing(L, corpse);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2013-08-07 21:31:40 +02:00
|
|
|
if (killer) {
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, killer);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, killer);
|
2013-08-07 21:31:40 +02:00
|
|
|
} else {
|
2014-11-03 19:10:51 +01:00
|
|
|
lua_pushnil(L);
|
2013-08-07 21:31:40 +02:00
|
|
|
}
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2013-08-07 21:31:40 +02:00
|
|
|
if (mostDamageKiller) {
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, mostDamageKiller);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, mostDamageKiller);
|
2013-07-07 02:30:08 +02:00
|
|
|
} else {
|
2014-11-03 19:10:51 +01:00
|
|
|
lua_pushnil(L);
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
2013-08-07 21:31:40 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushBoolean(L, lastHitUnjustified);
|
|
|
|
|
tfs::lua::pushBoolean(L, mostDamageUnjustified);
|
2013-08-07 21:31:40 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
return scriptInterface->callFunction(6);
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-13 14:06:08 +00:00
|
|
|
bool CreatureEvent::executeAdvance(Player* player, skills_t skill, uint32_t oldLevel, uint32_t newLevel)
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// onAdvance(player, skill, oldLevel, newLevel)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2013-08-12 00:09:14 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeAdvance] Call stack overflow" << std::endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->pushFunction(scriptId);
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, player);
|
|
|
|
|
tfs::lua::setMetatable(L, -1, "Player");
|
2013-08-07 21:31:40 +02:00
|
|
|
lua_pushnumber(L, static_cast<uint32_t>(skill));
|
|
|
|
|
lua_pushnumber(L, oldLevel);
|
|
|
|
|
lua_pushnumber(L, newLevel);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
return scriptInterface->callFunction(4);
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-05 14:10:38 +02:00
|
|
|
void CreatureEvent::executeOnKill(Creature* creature, Creature* target)
|
2013-07-07 02:30:08 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// onKill(creature, target)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2013-08-12 00:09:14 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeOnKill] Call stack overflow" << std::endl;
|
2015-06-05 14:10:38 +02:00
|
|
|
return;
|
2013-08-12 00:09:14 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->pushFunction(scriptId);
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, creature);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, creature);
|
|
|
|
|
tfs::lua::pushUserdata(L, target);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, target);
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->callVoidFunction(2);
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
2013-08-06 23:02:52 +02:00
|
|
|
|
2014-07-08 20:39:58 +02:00
|
|
|
void CreatureEvent::executeModalWindow(Player* player, uint32_t modalWindowId, uint8_t buttonId, uint8_t choiceId)
|
2013-08-06 23:02:52 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// onModalWindow(player, modalWindowId, buttonId, choiceId)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2013-08-12 00:09:14 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeModalWindow] Call stack overflow" << std::endl;
|
2014-07-08 20:39:58 +02:00
|
|
|
return;
|
2013-08-12 00:09:14 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-08-06 23:02:52 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
|
|
|
|
scriptInterface->pushFunction(scriptId);
|
2014-07-08 20:39:58 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, player);
|
|
|
|
|
tfs::lua::setMetatable(L, -1, "Player");
|
2014-07-08 20:39:58 +02:00
|
|
|
|
2014-03-19 13:20:54 -04:00
|
|
|
lua_pushnumber(L, modalWindowId);
|
|
|
|
|
lua_pushnumber(L, buttonId);
|
|
|
|
|
lua_pushnumber(L, choiceId);
|
2013-08-06 23:02:52 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->callVoidFunction(4);
|
2013-08-06 23:02:52 +02:00
|
|
|
}
|
2013-08-07 12:00:15 +02:00
|
|
|
|
2023-08-30 18:17:12 -04:00
|
|
|
bool CreatureEvent::executeTextEdit(Player* player, Item* item, std::string_view text, const uint32_t windowTextId)
|
2013-08-07 12:00:15 +02:00
|
|
|
{
|
2023-08-30 18:17:12 -04:00
|
|
|
// onTextEdit(player, item, text, windowTextId)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2013-08-12 00:09:14 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeTextEdit] Call stack overflow" << std::endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-08-07 12:00:15 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
|
|
|
|
scriptInterface->pushFunction(scriptId);
|
2014-07-08 20:39:58 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, player);
|
|
|
|
|
tfs::lua::setMetatable(L, -1, "Player");
|
2014-07-08 20:39:58 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushThing(L, item);
|
|
|
|
|
tfs::lua::pushString(L, text);
|
2013-08-07 12:00:15 +02:00
|
|
|
|
2023-08-30 18:17:12 -04:00
|
|
|
lua_pushinteger(L, windowTextId);
|
|
|
|
|
|
|
|
|
|
return scriptInterface->callFunction(4);
|
2013-08-07 12:00:15 +02:00
|
|
|
}
|
2013-10-20 18:20:33 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
void pushCombatDamage(lua_State* L, const CombatDamage& damage)
|
|
|
|
|
{
|
|
|
|
|
lua_pushnumber(L, damage.primary.value);
|
|
|
|
|
lua_pushnumber(L, damage.primary.type);
|
|
|
|
|
lua_pushnumber(L, damage.secondary.value);
|
|
|
|
|
lua_pushnumber(L, damage.secondary.type);
|
|
|
|
|
lua_pushnumber(L, damage.origin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
2014-08-19 15:37:56 +02:00
|
|
|
void CreatureEvent::executeHealthChange(Creature* creature, Creature* attacker, CombatDamage& damage)
|
2013-10-20 18:20:33 +02:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2014-08-19 15:37:56 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeHealthChange] Call stack overflow" << std::endl;
|
2014-07-08 20:39:58 +02:00
|
|
|
return;
|
2013-10-20 18:20:33 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-10-20 18:20:33 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
|
|
|
|
scriptInterface->pushFunction(scriptId);
|
2014-07-08 20:39:58 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, creature);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, creature);
|
2013-10-20 18:20:33 +02:00
|
|
|
if (attacker) {
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, attacker);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, attacker);
|
2013-10-20 18:20:33 +02:00
|
|
|
} else {
|
2014-07-08 20:39:58 +02:00
|
|
|
lua_pushnil(L);
|
2013-10-20 18:20:33 +02:00
|
|
|
}
|
2014-08-19 15:37:56 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
pushCombatDamage(L, damage);
|
2013-10-20 18:20:33 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
if (tfs::lua::protectedCall(L, 7, 4) != 0) {
|
|
|
|
|
reportErrorFunc(nullptr, tfs::lua::popString(L));
|
2014-07-08 20:39:58 +02:00
|
|
|
} else {
|
2024-05-27 15:49:32 +02:00
|
|
|
damage.primary.value = std::abs(tfs::lua::getNumber<int32_t>(L, -4));
|
|
|
|
|
damage.primary.type = tfs::lua::getNumber<CombatType_t>(L, -3);
|
|
|
|
|
damage.secondary.value = std::abs(tfs::lua::getNumber<int32_t>(L, -2));
|
|
|
|
|
damage.secondary.type = tfs::lua::getNumber<CombatType_t>(L, -1);
|
2014-07-08 21:30:05 +02:00
|
|
|
|
2014-07-08 20:39:58 +02:00
|
|
|
lua_pop(L, 4);
|
2014-07-08 21:30:05 +02:00
|
|
|
if (damage.primary.type != COMBAT_HEALING) {
|
|
|
|
|
damage.primary.value = -damage.primary.value;
|
|
|
|
|
damage.secondary.value = -damage.secondary.value;
|
|
|
|
|
}
|
2014-07-08 20:39:58 +02:00
|
|
|
}
|
2014-08-19 15:37:56 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::resetScriptEnv();
|
2013-10-20 18:20:33 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-13 14:06:08 +00:00
|
|
|
void CreatureEvent::executeManaChange(Creature* creature, Creature* attacker, CombatDamage& damage)
|
|
|
|
|
{
|
|
|
|
|
// onManaChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2014-08-19 15:37:56 +02:00
|
|
|
std::cout << "[Error - CreatureEvent::executeManaChange] Call stack overflow" << std::endl;
|
2014-07-08 20:39:58 +02:00
|
|
|
return;
|
2013-10-20 18:20:33 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-10-20 18:20:33 +02:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
|
|
|
|
scriptInterface->pushFunction(scriptId);
|
2014-07-08 20:39:58 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, creature);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, creature);
|
2013-10-20 18:20:33 +02:00
|
|
|
if (attacker) {
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, attacker);
|
|
|
|
|
tfs::lua::setCreatureMetatable(L, -1, attacker);
|
2013-10-20 18:20:33 +02:00
|
|
|
} else {
|
2014-07-08 20:39:58 +02:00
|
|
|
lua_pushnil(L);
|
2013-10-20 18:20:33 +02:00
|
|
|
}
|
2014-08-19 15:37:56 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
pushCombatDamage(L, damage);
|
2013-10-20 18:20:33 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
if (tfs::lua::protectedCall(L, 7, 4) != 0) {
|
|
|
|
|
reportErrorFunc(nullptr, tfs::lua::popString(L));
|
2014-07-08 20:39:58 +02:00
|
|
|
} else {
|
2024-05-27 15:49:32 +02:00
|
|
|
damage.primary.value = tfs::lua::getNumber<int32_t>(L, -4);
|
|
|
|
|
damage.primary.type = tfs::lua::getNumber<CombatType_t>(L, -3);
|
|
|
|
|
damage.secondary.value = tfs::lua::getNumber<int32_t>(L, -2);
|
|
|
|
|
damage.secondary.type = tfs::lua::getNumber<CombatType_t>(L, -1);
|
2019-02-27 08:26:55 +01:00
|
|
|
lua_pop(L, 4);
|
2014-07-08 20:39:58 +02:00
|
|
|
}
|
2014-08-19 15:37:56 +02:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::resetScriptEnv();
|
2013-10-20 18:20:33 +02:00
|
|
|
}
|
2013-11-07 23:49:36 +01:00
|
|
|
|
2014-07-08 20:39:58 +02:00
|
|
|
void CreatureEvent::executeExtendedOpcode(Player* player, uint8_t opcode, const std::string& buffer)
|
2013-11-07 23:49:36 +01:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// onExtendedOpcode(player, opcode, buffer)
|
2024-05-27 15:49:32 +02:00
|
|
|
if (!tfs::lua::reserveScriptEnv()) {
|
2013-11-07 23:49:36 +01:00
|
|
|
std::cout << "[Error - CreatureEvent::executeExtendedOpcode] Call stack overflow" << std::endl;
|
2014-07-08 20:39:58 +02:00
|
|
|
return;
|
2013-11-07 23:49:36 +01:00
|
|
|
}
|
|
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
ScriptEnvironment* env = tfs::lua::getScriptEnv();
|
2016-02-06 21:15:41 -08:00
|
|
|
env->setScriptId(scriptId, scriptInterface);
|
2013-11-07 23:49:36 +01:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
lua_State* L = scriptInterface->getLuaState();
|
2013-11-07 23:49:36 +01:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->pushFunction(scriptId);
|
2013-11-12 18:44:39 +01:00
|
|
|
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushUserdata(L, player);
|
|
|
|
|
tfs::lua::setMetatable(L, -1, "Player");
|
2013-11-12 18:44:39 +01:00
|
|
|
|
2014-03-19 13:20:54 -04:00
|
|
|
lua_pushnumber(L, opcode);
|
2024-05-27 15:49:32 +02:00
|
|
|
tfs::lua::pushString(L, buffer);
|
2013-11-07 23:49:36 +01:00
|
|
|
|
2016-02-06 21:15:41 -08:00
|
|
|
scriptInterface->callVoidFunction(3);
|
2013-11-07 23:49:36 +01:00
|
|
|
}
|