Fix acceptmessages, added exp hooks to luamods

This commit is contained in:
KimLS 2017-06-10 15:12:31 -07:00
parent c83810be36
commit 31d8336b4b
17 changed files with 530 additions and 20 deletions

View File

@ -25,6 +25,23 @@ void EQ::Net::ConsoleServer::RegisterLogin(ConsoleServerLoginCallback fn)
m_login = fn;
}
EQ::Net::ConsoleServerConnection *EQ::Net::ConsoleServer::FindByAccountName(const std::string &acct_name) {
for (auto &iter : m_connections) {
if (iter.second->UserName().compare(acct_name) == 0) {
return iter.second.get();
}
}
return nullptr;
}
void EQ::Net::ConsoleServer::SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function<void(void)> onTell) {
for (auto &iter : m_connections) {
iter.second->SendChannelMessage(scm, onTell);
}
}
void EQ::Net::ConsoleServer::ConnectionDisconnected(ConsoleServerConnection *c)
{
auto iter = m_connections.find(c->GetUUID());

View File

@ -25,7 +25,8 @@ namespace EQ
void RegisterCall(const std::string& command, int status_required, const std::string& help_definition, ConsoleServerCallback fn);
void RegisterLogin(ConsoleServerLoginCallback fn);
ConsoleServerConnection *FindByAccountName(const std::string &acct_name);
void SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function<void(void)> onTell);
private:
void ConnectionDisconnected(ConsoleServerConnection *c);
void ProcessCommand(ConsoleServerConnection *c, const std::string& cmd);

View File

@ -2,6 +2,8 @@
#include "../common/util/uuid.h"
#include "../common/net/packet.h"
#include "../common/eqemu_logsys.h"
#include "../common/servertalk.h"
#include "../common/rulesys.h"
EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection)
{
@ -107,6 +109,53 @@ void EQ::Net::ConsoleServerConnection::QueueMessage(const std::string &msg)
}
}
bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function<void(void)> onTell) {
if (!m_accept_messages) {
return false;
}
switch (scm->chan_num) {
if (RuleB(Chat, ServerWideAuction)) {
case 4: {
QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message));
break;
}
}
if (RuleB(Chat, ServerWideOOC)) {
case 5: {
QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message));
break;
}
}
case 6: {
QueueMessage(fmt::format("{0} BROADCASTS, '{1}'", scm->from, scm->message));
break;
}
case 7: {
QueueMessage(fmt::format("[{0}] tells you, '{1}'", scm->from, scm->message));
if (onTell) {
onTell();
}
break;
}
case 11: {
QueueMessage(fmt::format("{0} GMSAYS, '{1}'", scm->from, scm->message));
break;
}
default: {
return false;
}
}
return true;
}
void EQ::Net::ConsoleServerConnection::OnRead(TCPConnection *c, const unsigned char *data, size_t sz)
{
for (size_t i = 0; i < sz; ++i) {

View File

@ -4,6 +4,8 @@
#include <memory>
#include <map>
struct ServerChannelMessage_Struct;
namespace EQ
{
namespace Net
@ -42,6 +44,7 @@ namespace EQ
bool AcceptMessages() const { return m_accept_messages; }
void SetAcceptMessages(bool v) { m_accept_messages = v; }
void QueueMessage(const std::string &msg);
bool SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function<void(void)> onTell);
private:
void OnRead(TCPConnection* c, const unsigned char* data, size_t sz);
void OnDisconnect(TCPConnection* c);

View File

@ -0,0 +1,159 @@
--Mod file to demo changing the experience tables
--In this case I used some old wow tables (roughly it's not 100%)
function GetRequiredAAExperience(e)
e.level = 51;
return GetEXPForLevel(e);
end
function GetExperienceForKill(e)
local ML = e.other:GetLevel();
local CL = e.self:GetLevel();
if(ML > CL) then
local lmod = (ML - CL) * 0.05;
if(lmod > 1.0) then
lmod = 1.0;
end
e.ReturnValue = BaseXP(ML) * (1 + lmod);
elseif(ML < CL) then
local lmod = (CL - ML) * 0.05;
if(lmod > 1.0) then
lmod = 1.0;
end
e.ReturnValue = BaseXP(ML) * (1 - lmod);
else
e.ReturnValue = BaseXP(ML);
end
e.IgnoreDefault = true;
return e;
end
function BaseXP(L)
local base = L * 5;
if(L < 60) then
base = base + 45;
elseif(L < 70) then
base = base + 235;
elseif(L < 80) then
base = base + 580;
else
base = base + 1875;
end
return base;
end
function GetEXPForLevel(e)
local exp_table = {
0,
400,
900,
1400,
2100,
2800,
3600,
4500,
5400,
6500,
7600,
8700,
9800,
11000,
12300,
13600,
15000,
16400,
17800,
19300,
20800,
22400,
24000,
25500,
27200,
28900,
30500,
32200,
33900,
36300,
38800,
41600,
44600,
48000,
51400,
55000,
58700,
62400,
66200,
70200,
74300,
78500,
82800,
87100,
91600,
96300,
101000,
105800,
110700,
115700,
120900,
126100,
131500,
137000,
142500,
148200,
154000,
159900,
165800,
172000,
290000,
317000,
349000,
386000,
428000,
475000,
527000,
585000,
648000,
717000,
1523800,
1539000,
1555700,
1571800,
1587900,
1604200,
1620700,
1637400,
1653900,
1670800,
1670800,
1670800,
2121500,
2669000,
3469000,
4583000,
13000000,
15080000,
22600000,
27300000,
32800000
};
if(e.level < 1) then
e.ReturnValue = 0;
e.IgnoreDefault = true;
return e;
end
if(e.level > 91) then
e.ReturnValue = exp_table[91];
e.IgnoreDefault = true;
return e;
end
e.ReturnValue = exp_table[e.level];
e.IgnoreDefault = true;
return e;
end

View File

@ -392,12 +392,12 @@ int main(int argc, char** argv) {
server_connection->Listen(server_opts);
Log(Logs::General, Logs::World_Server, "Server (TCP) listener started.");
server_connection->OnConnectionIdentified("Zone", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
server_connection->OnConnectionIdentified("Zone", [&console](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
LogF(Logs::General, Logs::World_Server, "New Zone Server connection from {2} at {0}:{1}",
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
numzones++;
zoneserver_list.Add(new ZoneServer(connection));
zoneserver_list.Add(new ZoneServer(connection, console.get()));
});
server_connection->OnConnectionRemoved("Zone", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {

View File

@ -46,7 +46,7 @@ extern UCSConnection UCSLink;
extern QueryServConnection QSLink;
void CatchSignal(int sig_num);
ZoneServer::ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection)
ZoneServer::ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection, EQ::Net::ConsoleServer *console)
: tcpc(connection), zone_boot_timer(5000) {
/* Set Process tracking variable defaults */
@ -73,6 +73,8 @@ ZoneServer::ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> conn
zone_boot_timer.Disable();
}
}));
this->console = console;
}
ZoneServer::~ZoneServer() {
@ -412,6 +414,27 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
break;
}
if (scm->chan_num == 7 || scm->chan_num == 14) {
if (scm->deliverto[0] == '*') {
if (console) {
auto con = console->FindByAccountName(&scm->deliverto[1]);
if (((!con) || (!con->SendChannelMessage(scm, [&scm]() {
auto pack = new ServerPacket(ServerOP_ChannelMessage,
sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1);
memcpy(pack->pBuffer, scm, pack->size);
ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*)pack->pBuffer;
strcpy(scm2->deliverto, scm2->from);
scm2->noreply = true;
client_list.SendPacket(scm->from, pack);
safe_delete(pack);
}))) && (!scm->noreply))
{
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to);
}
}
break;
}
ClientListEntry* cle = client_list.FindCharacter(scm->deliverto);
if (cle == 0 || cle->Online() < CLE_Status_Zoning ||
(cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) {
@ -462,6 +485,20 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
cle->Server()->SendPacket(pack);
}
else {
if (scm->chan_num == 5 || scm->chan_num == 6 || scm->chan_num == 11) {
if (console) {
console->SendChannelMessage(scm, [&scm]() {
auto pack = new ServerPacket(ServerOP_ChannelMessage,
sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1);
memcpy(pack->pBuffer, scm, pack->size);
ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*)pack->pBuffer;
strcpy(scm2->deliverto, scm2->from);
scm2->noreply = true;
client_list.SendPacket(scm->from, pack);
safe_delete(pack);
});
}
}
zoneserver_list.SendPacket(pack);
}
break;

View File

@ -22,6 +22,7 @@
#include "../net/servertalk_server.h"
#include "../event/timer.h"
#include "../timer.h"
#include "console.h"
#include <string.h>
#include <string>
@ -31,7 +32,7 @@ class ServerPacket;
class ZoneServer : public WorldTCPConnection {
public:
ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection);
ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection, EQ::Net::ConsoleServer *console);
~ZoneServer();
virtual inline bool IsZoneServer() { return true; }
@ -97,6 +98,7 @@ private:
uint32 zone_os_process_id;
std::string launcher_name; //the launcher which started us
std::string launched_name; //the name of the zone we launched.
EQ::Net::ConsoleServer *console;
};
#endif

View File

@ -916,7 +916,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) {
void Client::SendAlternateAdvancementStats() {
auto outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct));
AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer;
aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP);
aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)GetRequiredAAExperience());
aps->unspent = m_pp.aapoints;
aps->percentage = m_epp.perAA;
QueuePacket(outapp);

View File

@ -2222,7 +2222,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil
Group *kg = entity_list.GetGroupByClient(give_exp_client);
Raid *kr = entity_list.GetRaidByClient(give_exp_client);
int32 finalxp = EXP_FORMULA;
int32 finalxp = give_exp_client->GetExperienceForKill(this);
finalxp = give_exp_client->mod_client_xp(finalxp, this);
if (kr) {

View File

@ -571,6 +571,7 @@ public:
void AddCrystals(uint32 Radiant, uint32 Ebon);
void SendCrystalCounts();
uint32 GetExperienceForKill(Mob *against);
void AddEXP(uint32 in_add_exp, uint8 conlevel = 0xFF, bool resexp = false);
uint32 CalcEXP(uint8 conlevel = 0xFF);
void SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp=false);
@ -796,12 +797,12 @@ public:
void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); }
int GetAAPoints() { return m_pp.aapoints; }
int GetSpentAA() { return m_pp.aapoints_spent; }
uint32 GetRequiredAAExperience();
//old AA methods that we still use
void ResetAA();
void RefundAA();
void SendClearAA();
inline uint32 GetMaxAAXP(void) const { return max_AAXP; }
inline uint32 GetAAXP() const { return m_pp.expAA; }
inline uint32 GetAAPercent() const { return m_epp.perAA; }
int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id);
@ -1493,7 +1494,6 @@ private:
uint32 tribute_master_id;
uint32 max_AAXP;
bool npcflag;
uint8 npclevel;
bool feigned;

View File

@ -1355,8 +1355,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
/* Set Total Seconds Played */
TotalSecondsPlayed = m_pp.timePlayedMin * 60;
/* Set Max AA XP */
max_AAXP = RuleI(AA, ExpPerPoint);
/* If we can maintain intoxication across zones, check for it */
if (!RuleB(Character, MaintainIntoxicationAcrossZones))
m_pp.intoxication = 0;

View File

@ -28,6 +28,7 @@
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "lua_parser.h"
#include "string_ids.h"
#ifdef BOTS
@ -153,6 +154,26 @@ uint32 Client::CalcEXP(uint8 conlevel) {
return in_add_exp;
}
uint32 Client::GetExperienceForKill(Mob *against)
{
#ifdef LUA_EQEMU
uint32 lua_ret = 0;
bool ignoreDefault = false;
lua_ret = LuaParser::Instance()->GetExperienceForKill(this, against, ignoreDefault);
if (ignoreDefault) {
return lua_ret;
}
#endif
if (against && against->IsNPC()) {
uint32 level = (uint32)against->GetLevel();
return EXP_FORMULA;
}
return 0;
}
void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
this->EVENT_ITEM_ScriptStopReturn();
@ -339,8 +360,8 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
Log(Logs::Detail, Logs::None, "Attempting to Set Exp for %s (XP: %u, AAXP: %u, Rez: %s)", this->GetCleanName(), set_exp, set_aaxp, isrezzexp ? "true" : "false");
//max_AAXP = GetEXPForLevel(52) - GetEXPForLevel(51); //GetEXPForLevel() doesn't depend on class/race, just level, so it shouldn't change between Clients
max_AAXP = RuleI(AA, ExpPerPoint); //this may be redundant since we're doing this in Client::FinishConnState2()
auto max_AAXP = GetRequiredAAExperience();
if (max_AAXP == 0 || GetEXPForLevel(GetLevel()) == 0xFFFFFFFF) {
Message(13, "Error in Client::SetEXP. EXP not set.");
return; // Must be invalid class/race
@ -460,14 +481,13 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
//add in how many points we had
m_pp.aapoints += last_unspentAA;
//set_aaxp = m_pp.expAA % max_AAXP;
//figure out how many points were actually gained
/*uint32 gained = m_pp.aapoints - last_unspentAA;*/ //unused
//Message(15, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA);
char val1[20]={0};
Message_StringID(MT_Experience, GAIN_ABILITY_POINT,ConvertArray(m_pp.aapoints, val1),m_pp.aapoints == 1 ? "" : "(s)"); //You have gained an ability point! You now have %1 ability point%2.
Message_StringID(MT_Experience, GAIN_ABILITY_POINT, ConvertArray(m_pp.aapoints, val1),m_pp.aapoints == 1 ? "" : "(s)"); //You have gained an ability point! You now have %1 ability point%2.
/* QS: PlayerLogAARate */
if (RuleB(QueryServ, PlayerLogAARate)){
@ -571,8 +591,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
char val1[20]={0};
char val2[20]={0};
char val3[20]={0};
Message_StringID(MT_Experience, GM_GAINXP,ConvertArray(set_aaxp,val1),ConvertArray(set_exp,val2),ConvertArray(GetEXPForLevel(GetLevel()+1),val3)); //[GM] You have gained %1 AXP and %2 EXP (%3).
//Message(15, "[GM] You now have %d / %d EXP and %d / %d AA exp.", set_exp, GetEXPForLevel(GetLevel()+1), set_aaxp, max_AAXP);
Message_StringID(MT_Experience, GM_GAINXP, ConvertArray(set_aaxp,val1),ConvertArray(set_exp,val2),ConvertArray(GetEXPForLevel(GetLevel()+1),val3)); //[GM] You have gained %1 AXP and %2 EXP (%3).
}
}
@ -664,6 +683,15 @@ void Client::SetLevel(uint8 set_level, bool command)
// Add: You can set the values you want now, client will be always sync :) - Merkur
uint32 Client::GetEXPForLevel(uint16 check_level)
{
#ifdef LUA_EQEMU
uint32 lua_ret = 0;
bool ignoreDefault = false;
lua_ret = LuaParser::Instance()->GetEXPForLevel(this, check_level, ignoreDefault);
if (ignoreDefault) {
return lua_ret;
}
#endif
uint16 check_levelm1 = check_level-1;
float mod;
@ -933,3 +961,17 @@ uint32 Client::GetCharMaxLevelFromQGlobal() {
return false;
}
uint32 Client::GetRequiredAAExperience() {
#ifdef LUA_EQEMU
uint32 lua_ret = 0;
bool ignoreDefault = false;
lua_ret = LuaParser::Instance()->GetRequiredAAExperience(this, ignoreDefault);
if (ignoreDefault) {
return lua_ret;
}
#endif
return RuleI(AA, ExpPerPoint);
}

View File

@ -39,6 +39,9 @@ void LuaMod::Init()
m_has_avoid_damage = parser_->HasFunction("AvoidDamage", package_name_);
m_has_check_hit_chance = parser_->HasFunction("CheckHitChance", package_name_);
m_has_try_critical_hit = parser_->HasFunction("TryCriticalHit", package_name_);
m_has_get_required_aa_experience = parser_->HasFunction("GetRequiredAAExperience", package_name_);
m_has_get_exp_for_level = parser_->HasFunction("GetEXPForLevel", package_name_);
m_has_get_experience_for_kill = parser_->HasFunction("GetExperienceForKill", package_name_);
}
void PutDamageHitInfo(lua_State *L, luabind::adl::object &e, DamageHitInfo &hit) {
@ -388,8 +391,6 @@ bool LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ign
return retval;
}
//void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault);
void LuaMod::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) {
int start = lua_gettop(L);
ignoreDefault = false;
@ -440,3 +441,161 @@ void LuaMod::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraA
lua_pop(L, n);
}
}
uint32 LuaMod::GetRequiredAAExperience(Client *self, bool &ignoreDefault)
{
int start = lua_gettop(L);
ignoreDefault = false;
uint32 retval = 0;
try {
if (!m_has_get_required_aa_experience) {
return retval;
}
lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str());
lua_getfield(L, -1, "GetRequiredAAExperience");
Lua_Client l_self(self);
luabind::adl::object e = luabind::newtable(L);
e["self"] = l_self;
e.push(L);
if (lua_pcall(L, 1, 1, 0)) {
std::string error = lua_tostring(L, -1);
parser_->AddError(error);
lua_pop(L, 1);
return retval;
}
if (lua_type(L, -1) == LUA_TTABLE) {
luabind::adl::object ret(luabind::from_stack(L, -1));
auto IgnoreDefaultObj = ret["IgnoreDefault"];
if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) {
ignoreDefault = ignoreDefault || luabind::object_cast<bool>(IgnoreDefaultObj);
}
auto returnValueObj = ret["ReturnValue"];
if (luabind::type(returnValueObj) == LUA_TNUMBER) {
retval = luabind::object_cast<uint32>(returnValueObj);
}
}
}
catch (std::exception &ex) {
parser_->AddError(ex.what());
}
int end = lua_gettop(L);
int n = end - start;
if (n > 0) {
lua_pop(L, n);
}
return retval;
}
uint32 LuaMod::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault) {
int start = lua_gettop(L);
ignoreDefault = false;
uint32 retval = 0;
try {
if (!m_has_get_exp_for_level) {
return retval;
}
lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str());
lua_getfield(L, -1, "GetEXPForLevel");
Lua_Client l_self(self);
luabind::adl::object e = luabind::newtable(L);
e["self"] = l_self;
e["level"] = level;
e.push(L);
if (lua_pcall(L, 1, 1, 0)) {
std::string error = lua_tostring(L, -1);
parser_->AddError(error);
lua_pop(L, 1);
return retval;
}
if (lua_type(L, -1) == LUA_TTABLE) {
luabind::adl::object ret(luabind::from_stack(L, -1));
auto IgnoreDefaultObj = ret["IgnoreDefault"];
if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) {
ignoreDefault = ignoreDefault || luabind::object_cast<bool>(IgnoreDefaultObj);
}
auto returnValueObj = ret["ReturnValue"];
if (luabind::type(returnValueObj) == LUA_TNUMBER) {
retval = luabind::object_cast<uint32>(returnValueObj);
}
}
}
catch (std::exception &ex) {
parser_->AddError(ex.what());
}
int end = lua_gettop(L);
int n = end - start;
if (n > 0) {
lua_pop(L, n);
}
return retval;
}
uint32 LuaMod::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault)
{
int start = lua_gettop(L);
ignoreDefault = false;
uint32 retval = 0;
try {
if (!m_has_get_experience_for_kill) {
return retval;
}
lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str());
lua_getfield(L, -1, "GetExperienceForKill");
Lua_Client l_self(self);
Lua_Mob l_other(against);
luabind::adl::object e = luabind::newtable(L);
e["self"] = l_self;
e["other"] = l_other;
e.push(L);
if (lua_pcall(L, 1, 1, 0)) {
std::string error = lua_tostring(L, -1);
parser_->AddError(error);
lua_pop(L, 1);
return retval;
}
if (lua_type(L, -1) == LUA_TTABLE) {
luabind::adl::object ret(luabind::from_stack(L, -1));
auto IgnoreDefaultObj = ret["IgnoreDefault"];
if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) {
ignoreDefault = ignoreDefault || luabind::object_cast<bool>(IgnoreDefaultObj);
}
auto returnValueObj = ret["ReturnValue"];
if (luabind::type(returnValueObj) == LUA_TNUMBER) {
retval = luabind::object_cast<uint32>(returnValueObj);
}
}
}
catch (std::exception &ex) {
parser_->AddError(ex.what());
}
int end = lua_gettop(L);
int n = end - start;
if (n > 0) {
lua_pop(L, n);
}
return retval;
}

View File

@ -22,7 +22,9 @@ public:
bool AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignoreDefault);
bool CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ignoreDefault);
void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault);
uint32 GetRequiredAAExperience(Client *self, bool &ignoreDefault);
uint32 GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault);
uint32 GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault);
private:
LuaParser *parser_;
lua_State *L;
@ -33,4 +35,7 @@ private:
bool m_has_avoid_damage;
bool m_has_check_hit_chance;
bool m_has_try_critical_hit;
bool m_has_get_required_aa_experience;
bool m_has_get_exp_for_level;
bool m_has_get_experience_for_kill;
};

View File

@ -959,6 +959,13 @@ void LuaParser::ReloadQuests() {
if (load_order) {
char file_name[256] = { 0 };
while (fgets(file_name, 256, load_order) != nullptr) {
for (int i = 0; i < 256; ++i) {
if (file_name[i] == '\n') {
file_name[i] = 0;
break;
}
}
LoadScript("mods/" + std::string(file_name), file_name);
mods_.push_back(LuaMod(L, this, file_name));
}
@ -1324,3 +1331,30 @@ void LuaParser::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, Ext
mod.TryCriticalHit(self, defender, hit, opts, ignoreDefault);
}
}
uint32 LuaParser::GetRequiredAAExperience(Client *self, bool &ignoreDefault)
{
uint32 retval = false;
for (auto &mod : mods_) {
retval = mod.GetRequiredAAExperience(self, ignoreDefault);
}
return retval;
}
uint32 LuaParser::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault)
{
uint32 retval = false;
for (auto &mod : mods_) {
retval = mod.GetEXPForLevel(self, level, ignoreDefault);
}
return retval;
}
uint32 LuaParser::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault)
{
uint32 retval = false;
for (auto &mod : mods_) {
retval = mod.GetExperienceForKill(self, against, ignoreDefault);
}
return retval;
}

View File

@ -95,6 +95,9 @@ public:
bool AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignoreDefault);
bool CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ignoreDefault);
void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault);
uint32 GetRequiredAAExperience(Client *self, bool &ignoreDefault);
uint32 GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault);
uint32 GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault);
private:
LuaParser();