Work in progress for 0.9.9 so far (making its own branch for now)
- Fixed a repeated rubberband like behavior that Spawn's would run forward toward their target in combat or on their return run to their starting point. - WS_HearCastSpell for 546-561 version has an extra byte at the end of the packet we were missing (might be in later clients too have to confirm) - PlayerScripts support added, new function calls, AddTimer support for Players. - Static Zones / Special Zones will now silently check to startup zones without reporting the log message, log message only on startup or taking on peer leadership. - Broadcast and Global Announcement are now supported through peering. - Fix #22 identified a number of loose spawn pointers and changed to int32 spawn id reference. - Fix #1 support for all known chat codes for various channels, spell casting and damage. - In conjunction with Fix #1 spell combat messages are fixed, no longer 'YOU cast' when another spawn casts, added last_tell_name to track the chat code %RT server side. - size_mod added to InfoStruct Float, supports shrinking and growing Non Player's. InfoStruct also has a UINT ignore_size_mod_calc set to 0 by default, when 1 it will let you set the size_mod and items/spells will not override it from stat calculation. - XP Table is now static (global) in the Player class so we do not constantly call the database each time the player needs to know a level's XP requirement. - Removal of duplicate spell cast success and effect messages. - Fix #21 blue xp bar for KoS and DoF displays properly now. - GetExpRequiredByLevel(level) added to return the EXP required for to reach the level. - Fix #25 teleporters cleaned up during /reload spawns to avoid crash - Fix #16 /reload items supported in peering mode.
This commit is contained in:
parent
4e43c73f9c
commit
82a5e96000
@ -3712,6 +3712,12 @@ to zero and treated like placeholders." />
|
|||||||
<Data ElementName="damage" Type="int16" />
|
<Data ElementName="damage" Type="int16" />
|
||||||
<Data ElementName="spell_name" Type="EQ2_8Bit_String" Size="1" />
|
<Data ElementName="spell_name" Type="EQ2_8Bit_String" Size="1" />
|
||||||
</Struct>
|
</Struct>
|
||||||
|
<Struct Name="WS_SetSocialMsg" ClientVersion="1" OpcodeName="OP_SetSocialMsg">
|
||||||
|
<Data ElementName="num_socials" Type="int8" />
|
||||||
|
<Data ElementName="social_array" Type="Array" ArraySizeVariable="num_socials">
|
||||||
|
<Data ElementName="social_name" Type="EQ2_8Bit_String" Size="1" />
|
||||||
|
</Data>
|
||||||
|
</Struct>
|
||||||
<Struct Name="WS_HearMultipleDamage" ClientVersion="1" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqHearCombatCmd">
|
<Struct Name="WS_HearMultipleDamage" ClientVersion="1" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqHearCombatCmd">
|
||||||
<Data ElementName="header" Substruct="WS_HearDamage_Header" Size="1" />
|
<Data ElementName="header" Substruct="WS_HearDamage_Header" Size="1" />
|
||||||
<Data ElementName="num_dmg" Type="int8" />
|
<Data ElementName="num_dmg" Type="int8" />
|
||||||
@ -7642,6 +7648,7 @@ to zero and treated like placeholders." />
|
|||||||
<Data ElementName="spell_visual" Type="int16" />
|
<Data ElementName="spell_visual" Type="int16" />
|
||||||
<Data ElementName="cast_time" Type="float" />
|
<Data ElementName="cast_time" Type="float" />
|
||||||
<Data ElementName="spell_level" Type="int8" />
|
<Data ElementName="spell_level" Type="int8" />
|
||||||
|
<Data ElementName="spell_crit" Type="int8" />
|
||||||
</Struct>
|
</Struct>
|
||||||
<Struct Name="WS_HearCastSpell" ClientVersion="562" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqHearSpellCastCmd">
|
<Struct Name="WS_HearCastSpell" ClientVersion="562" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqHearSpellCastCmd">
|
||||||
<Data ElementName="spawn_id" Type="int32" />
|
<Data ElementName="spawn_id" Type="int32" />
|
||||||
@ -21034,4 +21041,11 @@ to zero and treated like placeholders." />
|
|||||||
<Struct Name="WS_CreateBoatTransportMsg" ClientVersion="1" OpcodeName="OP_CreateBoatTransportsMsg">
|
<Struct Name="WS_CreateBoatTransportMsg" ClientVersion="1" OpcodeName="OP_CreateBoatTransportsMsg">
|
||||||
<Data ElementName="path_id" Type="int8" />
|
<Data ElementName="path_id" Type="int8" />
|
||||||
</Struct>
|
</Struct>
|
||||||
|
<Struct Name="WS_SetSocialMsg" ClientVersion="1" OpcodeName="OP_SetSocialMsg">
|
||||||
|
<Data ElementName="num_socials" Type="int8" />
|
||||||
|
<Data ElementName="social_array" Type="Array" ArraySizeVariable="num_socials">
|
||||||
|
<Data ElementName="social_name" Type="EQ2_8Bit_String" Size="1" />
|
||||||
|
<Data ElementName="social_message" Type="EQ2_8Bit_String" Size="1" />
|
||||||
|
</Data>
|
||||||
|
</Struct>
|
||||||
</EQ2Emulator>
|
</EQ2Emulator>
|
||||||
|
@ -140,6 +140,10 @@ bool Entity::AttackAllowed(Entity* target, float distance, bool range_attack) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(attacker->IsNPC() && target->IsNPC() && attacker->GetFactionID() > 10 && attacker->GetFactionID() == target->GetFactionID()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (attacker->IsPlayer() && target->IsPlayer())
|
if (attacker->IsPlayer() && target->IsPlayer())
|
||||||
{
|
{
|
||||||
@ -495,26 +499,6 @@ bool Entity::SpellAttack(Spawn* victim, float distance, LuaSpell* luaspell, int8
|
|||||||
|
|
||||||
CheckProcs(PROC_TYPE_OFFENSIVE, victim);
|
CheckProcs(PROC_TYPE_OFFENSIVE, victim);
|
||||||
CheckProcs(PROC_TYPE_MAGICAL_OFFENSIVE, victim);
|
CheckProcs(PROC_TYPE_MAGICAL_OFFENSIVE, victim);
|
||||||
|
|
||||||
if(spell->GetSpellData()->success_message.length() > 0){
|
|
||||||
Client* client = nullptr;
|
|
||||||
if(IsPlayer())
|
|
||||||
client = ((Player*)this)->GetClient();
|
|
||||||
if(client){
|
|
||||||
string success_message = spell->GetSpellData()->success_message;
|
|
||||||
if(success_message.find("%t") < 0xFFFFFFFF)
|
|
||||||
success_message.replace(success_message.find("%t"), 2, victim->GetName());
|
|
||||||
client->Message(CHANNEL_YOU_CAST, success_message.c_str());
|
|
||||||
//commented out the following line as it was causing a duplicate message EmemJR 5/4/2019
|
|
||||||
//GetZone()->SendDamagePacket(this, victim, DAMAGE_PACKET_TYPE_SPELL_DAMAGE, hit_result, damage_type, 0, spell->GetName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(spell->GetSpellData()->effect_message.length() > 0){
|
|
||||||
string effect_message = spell->GetSpellData()->effect_message;
|
|
||||||
if(effect_message.find("%t") < 0xFFFFFFFF)
|
|
||||||
effect_message.replace(effect_message.find("%t"), 2, victim->GetName());
|
|
||||||
GetZone()->SimpleMessage(CHANNEL_SPELLS, effect_message.c_str(), victim, 50);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
successful_hit = false;
|
successful_hit = false;
|
||||||
@ -603,15 +587,15 @@ bool Entity::ProcAttack(Spawn* victim, int8 damage_type, int32 low_damage, int32
|
|||||||
if(IsPlayer())
|
if(IsPlayer())
|
||||||
client = ((Player*)this)->GetClient();
|
client = ((Player*)this)->GetClient();
|
||||||
if(client) {
|
if(client) {
|
||||||
if(success_msg.find("%t") < 0xFFFFFFFF)
|
std::string castMsg = std::string(success_msg);
|
||||||
success_msg.replace(success_msg.find("%t"), 2, victim->GetName());
|
SpellProcess::ReplaceEffectTokens(castMsg, (Spawn*)this, victim);
|
||||||
client->Message(CHANNEL_YOU_CAST, success_msg.c_str());
|
client->Message(CHANNEL_YOU_CAST, castMsg.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (effect_msg.length() > 0) {
|
if (effect_msg.length() > 0) {
|
||||||
if(effect_msg.find("%t") < 0xFFFFFFFF)
|
std::string effectMsg = std::string(effect_msg);
|
||||||
effect_msg.replace(effect_msg.find("%t"), 2, victim->GetName());
|
SpellProcess::ReplaceEffectTokens(effectMsg, (Spawn*)this, victim);
|
||||||
GetZone()->SimpleMessage(CHANNEL_SPELLS, effect_msg.c_str(), victim, 50);
|
GetZone()->SimpleMessage(CHANNEL_SPELLS, effectMsg.c_str(), victim, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
EQ2Emulator: Everquest II Server Emulator
|
EQ2Emulator: Everquest II Server Emulator
|
||||||
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
|
Copyright (C) 2005 - 2025 EQ2EMulator Development Team (http://www.eq2emu.com formerly http://www.eq2emulator.net)
|
||||||
|
|
||||||
This file is part of EQ2Emulator.
|
This file is part of EQ2Emulator.
|
||||||
|
|
||||||
EQ2Emulator is free software: you can redistribute it and/or modify
|
EQ2Emulator is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
EQ2Emulator is distributed in the hope that it will be useful,
|
EQ2Emulator is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
@ -1987,6 +1988,18 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case COMMAND_RELOAD_PLAYERSCRIPTS: {
|
||||||
|
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Player Scripts...");
|
||||||
|
world.SetReloadingSubsystem("PlayerScripts");
|
||||||
|
world.ResetPlayerScripts();
|
||||||
|
world.LoadPlayerScripts();
|
||||||
|
if (lua_interface)
|
||||||
|
lua_interface->DestroyPlayerScripts();
|
||||||
|
world.RemoveReloadingSubSystem("PlayerScripts");
|
||||||
|
peer_manager.sendPeersMessage("/reloadcommand", command->handler);
|
||||||
|
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
case COMMAND_RELOAD_ENTITYCOMMANDS: {
|
case COMMAND_RELOAD_ENTITYCOMMANDS: {
|
||||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Entity Commands...");
|
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Entity Commands...");
|
||||||
world.SetReloadingSubsystem("EntityCommands");
|
world.SetReloadingSubsystem("EntityCommands");
|
||||||
@ -2679,7 +2692,8 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COMMAND_BANK_DEPOSIT:{
|
case COMMAND_BANK_DEPOSIT:{
|
||||||
if(client->GetBanker() && sep && sep->arg[0]){
|
Spawn* banker = client->GetCurrentZone()->GetSpawnByID(client->GetBanker());
|
||||||
|
if(banker && sep && sep->arg[0]){
|
||||||
int64 amount = 0;
|
int64 amount = 0;
|
||||||
string deposit = string(sep->arg[0]);
|
string deposit = string(sep->arg[0]);
|
||||||
amount = atoi64(deposit.c_str());
|
amount = atoi64(deposit.c_str());
|
||||||
@ -2688,7 +2702,8 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COMMAND_BANK_WITHDRAWAL:{
|
case COMMAND_BANK_WITHDRAWAL:{
|
||||||
if(client->GetBanker() && sep && sep->arg[0] && sep->IsNumber(0)){
|
Spawn* banker = client->GetCurrentZone()->GetSpawnByID(client->GetBanker());
|
||||||
|
if(banker && sep && sep->arg[0] && sep->IsNumber(0)){
|
||||||
int64 amount = 0;
|
int64 amount = 0;
|
||||||
string deposit = string(sep->arg[0]);
|
string deposit = string(sep->arg[0]);
|
||||||
amount = atoi64(deposit.c_str());
|
amount = atoi64(deposit.c_str());
|
||||||
@ -2891,7 +2906,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||||||
}
|
}
|
||||||
case COMMAND_CLASS:{
|
case COMMAND_CLASS:{
|
||||||
if(sep && sep->arg[ndx][0]){
|
if(sep && sep->arg[ndx][0]){
|
||||||
client->GetPlayer()->SetPlayerAdventureClass(atoi(sep->arg[ndx]));
|
client->GetPlayer()->SetPlayerAdventureClass(atoi(sep->arg[ndx]), true);
|
||||||
}else
|
}else
|
||||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage: /class {class_id}");
|
client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage: /class {class_id}");
|
||||||
break;
|
break;
|
||||||
@ -3137,6 +3152,9 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||||||
|
|
||||||
world.ResetZoneScripts();
|
world.ResetZoneScripts();
|
||||||
database.LoadZoneScriptData();
|
database.LoadZoneScriptData();
|
||||||
|
|
||||||
|
world.ResetPlayerScripts();
|
||||||
|
world.LoadPlayerScripts();
|
||||||
|
|
||||||
if(lua_interface) {
|
if(lua_interface) {
|
||||||
lua_interface->DestroySpawnScripts();
|
lua_interface->DestroySpawnScripts();
|
||||||
@ -3144,6 +3162,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||||||
lua_interface->DestroyQuests();
|
lua_interface->DestroyQuests();
|
||||||
lua_interface->DestroyItemScripts();
|
lua_interface->DestroyItemScripts();
|
||||||
lua_interface->DestroyZoneScripts();
|
lua_interface->DestroyZoneScripts();
|
||||||
|
lua_interface->DestroyPlayerScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 quest_count = database.LoadQuests();
|
int32 quest_count = database.LoadQuests();
|
||||||
@ -5372,14 +5391,14 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||||||
}
|
}
|
||||||
case COMMAND_BROADCAST: {
|
case COMMAND_BROADCAST: {
|
||||||
if (sep && sep->arg[0])
|
if (sep && sep->arg[0])
|
||||||
zone_list.HandleGlobalBroadcast(sep->argplus[0]);
|
zone_list.TransmitBroadcast(sep->argplus[0]);
|
||||||
else
|
else
|
||||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Usage: /broadcast {message}");
|
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Usage: /broadcast {message}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COMMAND_ANNOUNCE: {
|
case COMMAND_ANNOUNCE: {
|
||||||
if (sep && sep->arg[0])
|
if (sep && sep->arg[0])
|
||||||
zone_list.HandleGlobalAnnouncement(sep->argplus[0]);
|
zone_list.TransmitGlobalAnnouncement(sep->argplus[0]);
|
||||||
else
|
else
|
||||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Usage: /announce {message}");
|
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Usage: /announce {message}");
|
||||||
break;
|
break;
|
||||||
@ -5401,6 +5420,8 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||||||
database.LoadMerchantInformation(); // we skip if there is only a reload of single item not all items
|
database.LoadMerchantInformation(); // we skip if there is only a reload of single item not all items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peer_manager.sendPeersMessage("/reloadcommand", command->handler, item_id);
|
||||||
|
|
||||||
if(item_id > 0) {
|
if(item_id > 0) {
|
||||||
client->Message(CHANNEL_COLOR_YELLOW, "Reloaded item %u.", item_id);
|
client->Message(CHANNEL_COLOR_YELLOW, "Reloaded item %u.", item_id);
|
||||||
}
|
}
|
||||||
@ -6184,11 +6205,6 @@ void Commands::Command_DuelSurrender(Client* client, Seperator* sep)
|
|||||||
PrintSep(sep, "COMMAND_DUEL_SURRENDER");
|
PrintSep(sep, "COMMAND_DUEL_SURRENDER");
|
||||||
LogWrite(MISC__TODO, 1, "Command", "TODO-Command: Surrender Duel Command");
|
LogWrite(MISC__TODO, 1, "Command", "TODO-Command: Surrender Duel Command");
|
||||||
client->Message(CHANNEL_COLOR_YELLOW, "You cannot duel other players (Not Implemented)");
|
client->Message(CHANNEL_COLOR_YELLOW, "You cannot duel other players (Not Implemented)");
|
||||||
|
|
||||||
// JA, just messin around ;)
|
|
||||||
char surrender[64];
|
|
||||||
sprintf(surrender, "%s surrendered like a cowardly dog!", client->GetPlayer()->GetName());
|
|
||||||
zone_list.HandleGlobalAnnouncement(surrender);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
EQ2Emulator: Everquest II Server Emulator
|
EQ2Emulator: Everquest II Server Emulator
|
||||||
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
|
Copyright (C) 2005 - 2025 EQ2EMulator Development Team (http://www.eq2emu.com formerly http://www.eq2emulator.net)
|
||||||
|
|
||||||
This file is part of EQ2Emulator.
|
This file is part of EQ2Emulator.
|
||||||
|
|
||||||
@ -17,6 +17,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __EQ2_COMMANDS__
|
#ifndef __EQ2_COMMANDS__
|
||||||
#define __EQ2_COMMANDS__
|
#define __EQ2_COMMANDS__
|
||||||
#include "../../common/DataBuffer.h"
|
#include "../../common/DataBuffer.h"
|
||||||
@ -981,8 +982,8 @@ private:
|
|||||||
#define CANCEL_AA_PROFILE 757
|
#define CANCEL_AA_PROFILE 757
|
||||||
#define SAVE_AA_PROFILE 758
|
#define SAVE_AA_PROFILE 758
|
||||||
|
|
||||||
#define COMMAND_MOOD 800
|
#define COMMAND_MOOD 800
|
||||||
|
#define COMMAND_RELOAD_PLAYERSCRIPTS 801
|
||||||
|
|
||||||
#define COMMAND_MODIFY 1000 // INSERT INTO `commands`(`id`,`type`,`command`,`subcommand`,`handler`,`required_status`) VALUES ( NULL,'1','modify','','1000','200');
|
#define COMMAND_MODIFY 1000 // INSERT INTO `commands`(`id`,`type`,`command`,`subcommand`,`handler`,`required_status`) VALUES ( NULL,'1','modify','','1000','200');
|
||||||
#define COMMAND_MODIFY_CHARACTER 1001
|
#define COMMAND_MODIFY_CHARACTER 1001
|
||||||
|
@ -291,6 +291,7 @@ void Entity::MapInfoStruct()
|
|||||||
get_float_funcs["spell_reuse_speed"] = l::bind(&InfoStruct::get_spell_reuse_speed, &info_struct);
|
get_float_funcs["spell_reuse_speed"] = l::bind(&InfoStruct::get_spell_reuse_speed, &info_struct);
|
||||||
get_float_funcs["spell_multi_attack"] = l::bind(&InfoStruct::get_spell_multi_attack, &info_struct);
|
get_float_funcs["spell_multi_attack"] = l::bind(&InfoStruct::get_spell_multi_attack, &info_struct);
|
||||||
get_float_funcs["size_mod"] = l::bind(&InfoStruct::get_size_mod, &info_struct);
|
get_float_funcs["size_mod"] = l::bind(&InfoStruct::get_size_mod, &info_struct);
|
||||||
|
get_int8_funcs["ignore_size_mod_calc"] = l::bind(&InfoStruct::get_ignore_size_mod_calc, &info_struct);
|
||||||
get_float_funcs["dps"] = l::bind(&InfoStruct::get_dps, &info_struct);
|
get_float_funcs["dps"] = l::bind(&InfoStruct::get_dps, &info_struct);
|
||||||
get_float_funcs["dps_multiplier"] = l::bind(&InfoStruct::get_dps_multiplier, &info_struct);
|
get_float_funcs["dps_multiplier"] = l::bind(&InfoStruct::get_dps_multiplier, &info_struct);
|
||||||
get_float_funcs["attackspeed"] = l::bind(&InfoStruct::get_attackspeed, &info_struct);
|
get_float_funcs["attackspeed"] = l::bind(&InfoStruct::get_attackspeed, &info_struct);
|
||||||
@ -500,6 +501,7 @@ void Entity::MapInfoStruct()
|
|||||||
set_float_funcs["spell_reuse_speed"] = l::bind(&InfoStruct::set_spell_reuse_speed, &info_struct, l::_1);
|
set_float_funcs["spell_reuse_speed"] = l::bind(&InfoStruct::set_spell_reuse_speed, &info_struct, l::_1);
|
||||||
set_float_funcs["spell_multi_attack"] = l::bind(&InfoStruct::set_spell_multi_attack, &info_struct, l::_1);
|
set_float_funcs["spell_multi_attack"] = l::bind(&InfoStruct::set_spell_multi_attack, &info_struct, l::_1);
|
||||||
set_float_funcs["size_mod"] = l::bind(&InfoStruct::set_size_mod, &info_struct, l::_1);
|
set_float_funcs["size_mod"] = l::bind(&InfoStruct::set_size_mod, &info_struct, l::_1);
|
||||||
|
set_int8_funcs["ignore_size_mod_calc"] = l::bind(&InfoStruct::set_ignore_size_mod_calc, &info_struct, l::_1);
|
||||||
set_float_funcs["dps"] = l::bind(&InfoStruct::set_dps, &info_struct, l::_1);
|
set_float_funcs["dps"] = l::bind(&InfoStruct::set_dps, &info_struct, l::_1);
|
||||||
set_float_funcs["dps_multiplier"] = l::bind(&InfoStruct::set_dps_multiplier, &info_struct, l::_1);
|
set_float_funcs["dps_multiplier"] = l::bind(&InfoStruct::set_dps_multiplier, &info_struct, l::_1);
|
||||||
set_float_funcs["attackspeed"] = l::bind(&InfoStruct::set_attackspeed, &info_struct, l::_1);
|
set_float_funcs["attackspeed"] = l::bind(&InfoStruct::set_attackspeed, &info_struct, l::_1);
|
||||||
@ -1462,7 +1464,9 @@ void Entity::CalculateBonuses(){
|
|||||||
info->set_spell_multi_attack(0);
|
info->set_spell_multi_attack(0);
|
||||||
|
|
||||||
float previous_size_mod = info->get_size_mod();
|
float previous_size_mod = info->get_size_mod();
|
||||||
info->set_size_mod(0.0f);
|
|
||||||
|
if(!info->get_ignore_size_mod_calc())
|
||||||
|
info->set_size_mod(0.0f);
|
||||||
info->set_dps(0);
|
info->set_dps(0);
|
||||||
info->set_dps_multiplier(0);
|
info->set_dps_multiplier(0);
|
||||||
info->set_haste(0);
|
info->set_haste(0);
|
||||||
@ -1548,7 +1552,8 @@ void Entity::CalculateBonuses(){
|
|||||||
info->add_recovery_speed(values->abilityrecoveryspeed);
|
info->add_recovery_speed(values->abilityrecoveryspeed);
|
||||||
info->add_spell_reuse_speed(values->spellreusespeed);
|
info->add_spell_reuse_speed(values->spellreusespeed);
|
||||||
info->add_spell_multi_attack(values->spellmultiattackchance);
|
info->add_spell_multi_attack(values->spellmultiattackchance);
|
||||||
info->add_size_mod(values->size_mod);
|
if(!info->get_ignore_size_mod_calc())
|
||||||
|
info->add_size_mod(values->size_mod);
|
||||||
info->add_dps(values->dps);
|
info->add_dps(values->dps);
|
||||||
info->add_dps_multiplier(CalculateDPSMultiplier());
|
info->add_dps_multiplier(CalculateDPSMultiplier());
|
||||||
info->add_haste(values->attackspeed);
|
info->add_haste(values->attackspeed);
|
||||||
|
@ -210,6 +210,8 @@ struct InfoStruct{
|
|||||||
recovery_speed_ = 0;
|
recovery_speed_ = 0;
|
||||||
spell_reuse_speed_ = 0;
|
spell_reuse_speed_ = 0;
|
||||||
spell_multi_attack_ = 0;
|
spell_multi_attack_ = 0;
|
||||||
|
size_mod_ = 0.0f;
|
||||||
|
ignore_size_mod_calc_ = 0;
|
||||||
dps_ = 0;
|
dps_ = 0;
|
||||||
dps_multiplier_ = 0;
|
dps_multiplier_ = 0;
|
||||||
attackspeed_ = 0;
|
attackspeed_ = 0;
|
||||||
@ -420,6 +422,10 @@ struct InfoStruct{
|
|||||||
spell_reuse_speed_ = oldStruct->get_spell_reuse_speed();
|
spell_reuse_speed_ = oldStruct->get_spell_reuse_speed();
|
||||||
spell_multi_attack_ = oldStruct->get_spell_multi_attack();
|
spell_multi_attack_ = oldStruct->get_spell_multi_attack();
|
||||||
dps_ = oldStruct->get_dps();
|
dps_ = oldStruct->get_dps();
|
||||||
|
|
||||||
|
size_mod_ = oldStruct->get_size_mod();
|
||||||
|
ignore_size_mod_calc_ = oldStruct->get_ignore_size_mod_calc();
|
||||||
|
|
||||||
dps_multiplier_ = oldStruct->get_dps_multiplier();
|
dps_multiplier_ = oldStruct->get_dps_multiplier();
|
||||||
attackspeed_ = oldStruct->get_attackspeed();
|
attackspeed_ = oldStruct->get_attackspeed();
|
||||||
haste_ = oldStruct->get_haste();
|
haste_ = oldStruct->get_haste();
|
||||||
@ -637,6 +643,7 @@ struct InfoStruct{
|
|||||||
float get_spell_reuse_speed() { std::lock_guard<std::mutex> lk(classMutex); return spell_reuse_speed_; }
|
float get_spell_reuse_speed() { std::lock_guard<std::mutex> lk(classMutex); return spell_reuse_speed_; }
|
||||||
float get_spell_multi_attack() { std::lock_guard<std::mutex> lk(classMutex); return spell_multi_attack_; }
|
float get_spell_multi_attack() { std::lock_guard<std::mutex> lk(classMutex); return spell_multi_attack_; }
|
||||||
float get_size_mod() { std::lock_guard<std::mutex> lk(classMutex); return size_mod_; }
|
float get_size_mod() { std::lock_guard<std::mutex> lk(classMutex); return size_mod_; }
|
||||||
|
int8 get_ignore_size_mod_calc() { std::lock_guard<std::mutex> lk(classMutex); return ignore_size_mod_calc_; }
|
||||||
float get_dps() { std::lock_guard<std::mutex> lk(classMutex); return dps_; }
|
float get_dps() { std::lock_guard<std::mutex> lk(classMutex); return dps_; }
|
||||||
float get_dps_multiplier() { std::lock_guard<std::mutex> lk(classMutex); return dps_multiplier_; }
|
float get_dps_multiplier() { std::lock_guard<std::mutex> lk(classMutex); return dps_multiplier_; }
|
||||||
float get_attackspeed() { std::lock_guard<std::mutex> lk(classMutex); return attackspeed_; }
|
float get_attackspeed() { std::lock_guard<std::mutex> lk(classMutex); return attackspeed_; }
|
||||||
@ -917,6 +924,7 @@ struct InfoStruct{
|
|||||||
void set_spell_reuse_speed(float value) { std::lock_guard<std::mutex> lk(classMutex); spell_reuse_speed_ = value; }
|
void set_spell_reuse_speed(float value) { std::lock_guard<std::mutex> lk(classMutex); spell_reuse_speed_ = value; }
|
||||||
void set_spell_multi_attack(float value) { std::lock_guard<std::mutex> lk(classMutex); spell_multi_attack_ = value; }
|
void set_spell_multi_attack(float value) { std::lock_guard<std::mutex> lk(classMutex); spell_multi_attack_ = value; }
|
||||||
void set_size_mod(float value) { std::lock_guard<std::mutex> lk(classMutex); size_mod_ = value; }
|
void set_size_mod(float value) { std::lock_guard<std::mutex> lk(classMutex); size_mod_ = value; }
|
||||||
|
void set_ignore_size_mod_calc(int8 value) { std::lock_guard<std::mutex> lk(classMutex); ignore_size_mod_calc_ = value; }
|
||||||
void set_dps(float value) { std::lock_guard<std::mutex> lk(classMutex); dps_ = value; }
|
void set_dps(float value) { std::lock_guard<std::mutex> lk(classMutex); dps_ = value; }
|
||||||
void set_dps_multiplier(float value) { std::lock_guard<std::mutex> lk(classMutex); dps_multiplier_ = value; }
|
void set_dps_multiplier(float value) { std::lock_guard<std::mutex> lk(classMutex); dps_multiplier_ = value; }
|
||||||
void set_attackspeed(float value) { std::lock_guard<std::mutex> lk(classMutex); attackspeed_ = value; }
|
void set_attackspeed(float value) { std::lock_guard<std::mutex> lk(classMutex); attackspeed_ = value; }
|
||||||
@ -1191,6 +1199,7 @@ private:
|
|||||||
float spell_reuse_speed_;
|
float spell_reuse_speed_;
|
||||||
float spell_multi_attack_;
|
float spell_multi_attack_;
|
||||||
float size_mod_;
|
float size_mod_;
|
||||||
|
int8 ignore_size_mod_calc_;
|
||||||
float dps_;
|
float dps_;
|
||||||
float dps_multiplier_;
|
float dps_multiplier_;
|
||||||
float attackspeed_;
|
float attackspeed_;
|
||||||
|
@ -187,7 +187,7 @@ void Guild::AddEXPCurrent(sint64 exp, bool send_packet) {
|
|||||||
else
|
else
|
||||||
strncpy(adjective, "too uber for cheerios", sizeof(adjective) - 1);
|
strncpy(adjective, "too uber for cheerios", sizeof(adjective) - 1);
|
||||||
sprintf(message, "The %s guild <%s> has attained level %u", adjective, name, level);
|
sprintf(message, "The %s guild <%s> has attained level %u", adjective, name, level);
|
||||||
zone_list.HandleGlobalAnnouncement(message);
|
zone_list.TransmitGlobalAnnouncement(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
save_needed = true;
|
save_needed = true;
|
||||||
|
@ -14652,4 +14652,14 @@ int EQ2Emu_lua_GetSpellRequiredLevel(lua_State* state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int EQ2Emu_lua_GetExpRequiredByLevel(lua_State* state) {
|
||||||
|
int8 level = lua_interface->GetInt16Value(state);
|
||||||
|
lua_interface->ResetFunctionStack(state);
|
||||||
|
|
||||||
|
int32 exp_required = Player::GetNeededXPByLevel(level);
|
||||||
|
|
||||||
|
lua_interface->SetInt32Value(state, exp_required);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@ -680,4 +680,6 @@ int EQ2Emu_lua_GetZonePlayerAvgLevel(lua_State* state);
|
|||||||
int EQ2Emu_lua_GetZonePlayerFirstLevel(lua_State* state);
|
int EQ2Emu_lua_GetZonePlayerFirstLevel(lua_State* state);
|
||||||
|
|
||||||
int EQ2Emu_lua_GetSpellRequiredLevel(lua_State* state);
|
int EQ2Emu_lua_GetSpellRequiredLevel(lua_State* state);
|
||||||
|
|
||||||
|
int EQ2Emu_lua_GetExpRequiredByLevel(lua_State* state);
|
||||||
#endif
|
#endif
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
EQ2Emulator: Everquest II Server Emulator
|
EQ2Emulator: Everquest II Server Emulator
|
||||||
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
|
Copyright (C) 2005 - 2025 EQ2EMulator Development Team (http://www.eq2emu.com formerly http://www.eq2emulator.net)
|
||||||
|
|
||||||
This file is part of EQ2Emulator.
|
This file is part of EQ2Emulator.
|
||||||
|
|
||||||
@ -17,6 +17,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "LuaInterface.h"
|
#include "LuaInterface.h"
|
||||||
#include "LuaFunctions.h"
|
#include "LuaFunctions.h"
|
||||||
#include "WorldDatabase.h"
|
#include "WorldDatabase.h"
|
||||||
@ -45,6 +46,7 @@ LuaInterface::LuaInterface() {
|
|||||||
MSpells.SetName("LuaInterface::MSpells");
|
MSpells.SetName("LuaInterface::MSpells");
|
||||||
MSpawnScripts.SetName("LuaInterface::MSpawnScripts");
|
MSpawnScripts.SetName("LuaInterface::MSpawnScripts");
|
||||||
MZoneScripts.SetName("LuaInterface::MZoneScripts");
|
MZoneScripts.SetName("LuaInterface::MZoneScripts");
|
||||||
|
MPlayerScripts.SetName("LuaInterface::MPlayerScripts");
|
||||||
MQuests.SetName("LuaInterface::MQuests");
|
MQuests.SetName("LuaInterface::MQuests");
|
||||||
MLUAMain.SetName("LuaInterface::MLUAMain");
|
MLUAMain.SetName("LuaInterface::MLUAMain");
|
||||||
MItemScripts.SetName("LuaInterface::MItemScripts");
|
MItemScripts.SetName("LuaInterface::MItemScripts");
|
||||||
@ -119,6 +121,7 @@ LuaInterface::~LuaInterface() {
|
|||||||
DestroyQuests();
|
DestroyQuests();
|
||||||
DestroyItemScripts();
|
DestroyItemScripts();
|
||||||
DestroyZoneScripts();
|
DestroyZoneScripts();
|
||||||
|
DestroyPlayerScripts();
|
||||||
DestroyRegionScripts();
|
DestroyRegionScripts();
|
||||||
DeleteUserDataPtrs(true);
|
DeleteUserDataPtrs(true);
|
||||||
DeletePendingSpells(true);
|
DeletePendingSpells(true);
|
||||||
@ -241,6 +244,25 @@ void LuaInterface::DestroyZoneScripts() {
|
|||||||
MZoneScripts.releasewritelock(__FUNCTION__, __LINE__);
|
MZoneScripts.releasewritelock(__FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaInterface::DestroyPlayerScripts() {
|
||||||
|
map<string, map<lua_State*, bool> >::iterator itr;
|
||||||
|
map<lua_State*, bool>::iterator state_itr;
|
||||||
|
Mutex* mutex = 0;
|
||||||
|
MPlayerScripts.writelock(__FUNCTION__, __LINE__);
|
||||||
|
for (itr = player_scripts.begin(); itr != player_scripts.end(); itr++){
|
||||||
|
mutex = GetPlayerScriptMutex(itr->first.c_str());
|
||||||
|
mutex->writelock(__FUNCTION__, __LINE__);
|
||||||
|
for(state_itr = itr->second.begin(); state_itr != itr->second.end(); state_itr++)
|
||||||
|
lua_close(state_itr->first);
|
||||||
|
mutex->releasewritelock(__FUNCTION__, __LINE__);
|
||||||
|
safe_delete(mutex);
|
||||||
|
}
|
||||||
|
player_scripts.clear();
|
||||||
|
player_inverse_scripts.clear();
|
||||||
|
player_scripts_mutex.clear();
|
||||||
|
MPlayerScripts.releasewritelock(__FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
void LuaInterface::DestroyRegionScripts() {
|
void LuaInterface::DestroyRegionScripts() {
|
||||||
map<string, map<lua_State*, bool> >::iterator itr;
|
map<string, map<lua_State*, bool> >::iterator itr;
|
||||||
map<lua_State*, bool>::iterator state_itr;
|
map<lua_State*, bool>::iterator state_itr;
|
||||||
@ -306,6 +328,20 @@ bool LuaInterface::LoadZoneScript(const char* name) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LuaInterface::LoadPlayerScript(const char* name) {
|
||||||
|
bool ret = false;
|
||||||
|
if (name) {
|
||||||
|
lua_State* state = LoadLuaFile(name);
|
||||||
|
if (state) {
|
||||||
|
MPlayerScripts.writelock(__FUNCTION__, __LINE__);
|
||||||
|
player_scripts[name][state] = false;
|
||||||
|
MPlayerScripts.releasewritelock(__FUNCTION__, __LINE__);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool LuaInterface::LoadRegionScript(const char* name) {
|
bool LuaInterface::LoadRegionScript(const char* name) {
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if (name) {
|
if (name) {
|
||||||
@ -469,6 +505,16 @@ const char* LuaInterface::GetScriptName(lua_State* state)
|
|||||||
}
|
}
|
||||||
MZoneScripts.releasewritelock(__FUNCTION__, __LINE__);
|
MZoneScripts.releasewritelock(__FUNCTION__, __LINE__);
|
||||||
|
|
||||||
|
MPlayerScripts.writelock(__FUNCTION__, __LINE__);
|
||||||
|
itr = player_inverse_scripts.find(state);
|
||||||
|
if (itr != player_inverse_scripts.end())
|
||||||
|
{
|
||||||
|
const char* scriptName = itr->second.c_str();
|
||||||
|
MPlayerScripts.releasewritelock(__FUNCTION__, __LINE__);
|
||||||
|
return scriptName;
|
||||||
|
}
|
||||||
|
MPlayerScripts.releasewritelock(__FUNCTION__, __LINE__);
|
||||||
|
|
||||||
MRegionScripts.writelock(__FUNCTION__, __LINE__);
|
MRegionScripts.writelock(__FUNCTION__, __LINE__);
|
||||||
itr = region_inverse_scripts.find(state);
|
itr = region_inverse_scripts.find(state);
|
||||||
if (itr != region_inverse_scripts.end())
|
if (itr != region_inverse_scripts.end())
|
||||||
@ -500,6 +546,10 @@ bool LuaInterface::LoadZoneScript(string name) {
|
|||||||
return LoadZoneScript(name.c_str());
|
return LoadZoneScript(name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LuaInterface::LoadPlayerScript(string name) {
|
||||||
|
return LoadPlayerScript(name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
bool LuaInterface::LoadRegionScript(string name) {
|
bool LuaInterface::LoadRegionScript(string name) {
|
||||||
return LoadRegionScript(name.c_str());
|
return LoadRegionScript(name.c_str());
|
||||||
}
|
}
|
||||||
@ -1632,6 +1682,7 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||||||
lua_register(state,"GetZonePlayerFirstLevel", EQ2Emu_lua_GetZonePlayerFirstLevel);
|
lua_register(state,"GetZonePlayerFirstLevel", EQ2Emu_lua_GetZonePlayerFirstLevel);
|
||||||
|
|
||||||
lua_register(state,"GetSpellRequiredLevel", EQ2Emu_lua_GetSpellRequiredLevel);
|
lua_register(state,"GetSpellRequiredLevel", EQ2Emu_lua_GetSpellRequiredLevel);
|
||||||
|
lua_register(state,"GetExpRequiredByLevel", EQ2Emu_lua_GetExpRequiredByLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaInterface::LogError(const char* error, ...) {
|
void LuaInterface::LogError(const char* error, ...) {
|
||||||
@ -2172,6 +2223,17 @@ Mutex* LuaInterface::GetZoneScriptMutex(const char* name) {
|
|||||||
return mutex;
|
return mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Mutex* LuaInterface::GetPlayerScriptMutex(const char* name) {
|
||||||
|
Mutex* mutex = 0;
|
||||||
|
if(player_scripts_mutex.count(name) > 0)
|
||||||
|
mutex = player_scripts_mutex[name];
|
||||||
|
if(!mutex){
|
||||||
|
mutex = new Mutex();
|
||||||
|
player_scripts_mutex[name] = mutex;
|
||||||
|
}
|
||||||
|
return mutex;
|
||||||
|
}
|
||||||
|
|
||||||
Mutex* LuaInterface::GetRegionScriptMutex(const char* name) {
|
Mutex* LuaInterface::GetRegionScriptMutex(const char* name) {
|
||||||
Mutex* mutex = 0;
|
Mutex* mutex = 0;
|
||||||
if(region_scripts_mutex.count(name) > 0)
|
if(region_scripts_mutex.count(name) > 0)
|
||||||
@ -2216,6 +2278,14 @@ void LuaInterface::UseZoneScript(const char* name, lua_State* state, bool val) {
|
|||||||
MZoneScripts.releasewritelock(__FUNCTION__, __LINE__);
|
MZoneScripts.releasewritelock(__FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaInterface::UsePlayerScript(const char* name, lua_State* state, bool val) {
|
||||||
|
|
||||||
|
MPlayerScripts.writelock(__FUNCTION__, __LINE__);
|
||||||
|
player_scripts[name][state] = val;
|
||||||
|
player_inverse_scripts[state] = name;
|
||||||
|
MPlayerScripts.releasewritelock(__FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
void LuaInterface::UseRegionScript(const char* name, lua_State* state, bool val) {
|
void LuaInterface::UseRegionScript(const char* name, lua_State* state, bool val) {
|
||||||
|
|
||||||
MRegionScripts.writelock(__FUNCTION__, __LINE__);
|
MRegionScripts.writelock(__FUNCTION__, __LINE__);
|
||||||
@ -2328,6 +2398,40 @@ lua_State* LuaInterface::GetZoneScript(const char* name, bool create_new, bool u
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lua_State* LuaInterface::GetPlayerScript(const char* name, bool create_new, bool use) {
|
||||||
|
map<string, map<lua_State*, bool> >::iterator itr;
|
||||||
|
map<lua_State*, bool>::iterator zone_script_itr;
|
||||||
|
lua_State* ret = 0;
|
||||||
|
Mutex* mutex = 0;
|
||||||
|
|
||||||
|
itr = player_scripts.find(name);
|
||||||
|
if(itr != player_scripts.end()) {
|
||||||
|
mutex = GetPlayerScriptMutex(name);
|
||||||
|
mutex->readlock(__FUNCTION__, __LINE__);
|
||||||
|
for(zone_script_itr = itr->second.begin(); zone_script_itr != itr->second.end(); zone_script_itr++){
|
||||||
|
if(!zone_script_itr->second){ //not in use
|
||||||
|
ret = zone_script_itr->first;
|
||||||
|
|
||||||
|
if (use)
|
||||||
|
{
|
||||||
|
zone_script_itr->second = true;
|
||||||
|
break; // don't keep iterating, we already have our result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex->releasereadlock(__FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
|
if(!ret && create_new){
|
||||||
|
if(name && LoadPlayerScript(name))
|
||||||
|
ret = GetPlayerScript(name, create_new, use);
|
||||||
|
else{
|
||||||
|
LogError("Error LUA Zone Script '%s'", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
lua_State* LuaInterface::GetRegionScript(const char* name, bool create_new, bool use) {
|
lua_State* LuaInterface::GetRegionScript(const char* name, bool create_new, bool use) {
|
||||||
map<string, map<lua_State*, bool> >::iterator itr;
|
map<string, map<lua_State*, bool> >::iterator itr;
|
||||||
map<lua_State*, bool>::iterator region_script_itr;
|
map<lua_State*, bool>::iterator region_script_itr;
|
||||||
@ -2699,6 +2803,57 @@ bool LuaInterface::RunZoneScriptWithReturn(string script_name, const char* funct
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LuaInterface::RunPlayerScriptWithReturn(const string script_name, const char* function_name, const std::vector<LuaArg>& args, sint32* returnValue) {
|
||||||
|
lua_State* state = GetPlayerScript(script_name.c_str(), true, true);
|
||||||
|
if (state) {
|
||||||
|
Mutex* mutex = GetPlayerScriptMutex(script_name.c_str());
|
||||||
|
if (mutex)
|
||||||
|
mutex->readlock(__FUNCTION__, __LINE__);
|
||||||
|
else {
|
||||||
|
LogError("Error getting lock for '%s'", script_name.c_str());
|
||||||
|
UsePlayerScript(script_name.c_str(), state, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lua_getglobal(state, function_name);
|
||||||
|
if (!lua_isfunction(state, lua_gettop(state))) {
|
||||||
|
lua_pop(state, 1);
|
||||||
|
mutex->releasereadlock(__FUNCTION__);
|
||||||
|
UsePlayerScript(script_name.c_str(), state, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int8 num_params = 0;
|
||||||
|
for (const LuaArg& arg : args) {
|
||||||
|
switch (arg.type) {
|
||||||
|
case LuaArgType::SINT64: SetSInt64Value(state, arg.si); num_params++; break;
|
||||||
|
case LuaArgType::SINT: SetSInt32Value(state, arg.low_si); num_params++; break;
|
||||||
|
case LuaArgType::INT64: SetInt64Value(state, arg.i); num_params++; break;
|
||||||
|
case LuaArgType::INT: SetInt32Value(state, arg.low_i); num_params++; break;
|
||||||
|
case LuaArgType::FLOAT: SetFloatValue(state, arg.f); num_params++; break;
|
||||||
|
case LuaArgType::STRING: SetStringValue(state, arg.s.c_str()); num_params++; break;
|
||||||
|
case LuaArgType::BOOL: SetBooleanValue(state, arg.b); num_params++; break;
|
||||||
|
case LuaArgType::SPAWN: SetSpawnValue(state, arg.spawn); num_params++; break;
|
||||||
|
case LuaArgType::ZONE: SetZoneValue(state, arg.zone); num_params++; break;
|
||||||
|
case LuaArgType::SKILL: SetSkillValue(state, arg.skill); num_params++; break;
|
||||||
|
case LuaArgType::ITEM: SetItemValue(state, arg.item); num_params++; break;
|
||||||
|
case LuaArgType::QUEST: SetQuestValue(state, arg.quest); num_params++; break;
|
||||||
|
case LuaArgType::SPELL: SetSpellValue(state, arg.spell); num_params++; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!CallScriptSInt32(state, num_params, returnValue)) {
|
||||||
|
if (mutex)
|
||||||
|
mutex->releasereadlock(__FUNCTION__, __LINE__);
|
||||||
|
UsePlayerScript(script_name.c_str(), state, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mutex)
|
||||||
|
mutex->releasereadlock(__FUNCTION__, __LINE__);
|
||||||
|
UsePlayerScript(script_name.c_str(), state, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LuaInterface::RunRegionScript(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn, sint32 int32_arg1, int32* returnValue) {
|
bool LuaInterface::RunRegionScript(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn, sint32 int32_arg1, int32* returnValue) {
|
||||||
if (!zone)
|
if (!zone)
|
||||||
|
@ -108,6 +108,45 @@ struct LuaSpell{
|
|||||||
int16 initial_caster_level;
|
int16 initial_caster_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class LuaArgType { SINT64, INT64, SINT, INT, FLOAT, STRING, BOOL, SPAWN, ZONE, SKILL, ITEM, QUEST, SPELL /* etc */ };
|
||||||
|
|
||||||
|
struct LuaArg {
|
||||||
|
LuaArgType type;
|
||||||
|
union {
|
||||||
|
sint64 si;
|
||||||
|
sint64 i;
|
||||||
|
int32 low_i;
|
||||||
|
sint32 low_si;
|
||||||
|
float f;
|
||||||
|
bool b;
|
||||||
|
};
|
||||||
|
std::string s;
|
||||||
|
Spawn* spawn = nullptr;
|
||||||
|
ZoneServer* zone = nullptr;
|
||||||
|
Skill* skill = nullptr;
|
||||||
|
Item* item = nullptr;
|
||||||
|
Quest* quest = nullptr;
|
||||||
|
LuaSpell* spell = nullptr;
|
||||||
|
|
||||||
|
LuaArg(sint64 val) : type(LuaArgType::SINT64), si(val) {}
|
||||||
|
LuaArg(sint32 val) : type(LuaArgType::SINT), low_si(val) {}
|
||||||
|
LuaArg(sint16 val) : type(LuaArgType::SINT), low_si(val) {}
|
||||||
|
LuaArg(sint8 val) : type(LuaArgType::SINT), low_si(val) {}
|
||||||
|
LuaArg(int64 val) : type(LuaArgType::INT64), i(val) {}
|
||||||
|
LuaArg(int32 val) : type(LuaArgType::INT), low_i(val) {}
|
||||||
|
LuaArg(int16 val) : type(LuaArgType::INT), low_i(val) {}
|
||||||
|
LuaArg(int8 val) : type(LuaArgType::INT), low_i(val) {}
|
||||||
|
LuaArg(float val) : type(LuaArgType::FLOAT), f(val) {}
|
||||||
|
LuaArg(bool val) : type(LuaArgType::BOOL), b(val) {}
|
||||||
|
LuaArg(const std::string& val) : type(LuaArgType::STRING), s(val) {}
|
||||||
|
LuaArg(Spawn* val) : type(LuaArgType::SPAWN), spawn(val) {}
|
||||||
|
LuaArg(ZoneServer* val) : type(LuaArgType::ZONE), zone(val) {}
|
||||||
|
LuaArg(Skill* val) : type(LuaArgType::SKILL), skill(val) {}
|
||||||
|
LuaArg(Item* val) : type(LuaArgType::ITEM), item(val) {}
|
||||||
|
LuaArg(Quest* val) : type(LuaArgType::QUEST), quest(val) {}
|
||||||
|
LuaArg(LuaSpell* val) : type(LuaArgType::SPELL), spell(val) {}
|
||||||
|
};
|
||||||
|
|
||||||
class LUAUserData{
|
class LUAUserData{
|
||||||
public:
|
public:
|
||||||
LUAUserData();
|
LUAUserData();
|
||||||
@ -192,6 +231,8 @@ public:
|
|||||||
bool LoadSpawnScript(const char* name);
|
bool LoadSpawnScript(const char* name);
|
||||||
bool LoadZoneScript(string name);
|
bool LoadZoneScript(string name);
|
||||||
bool LoadZoneScript(const char* name);
|
bool LoadZoneScript(const char* name);
|
||||||
|
bool LoadPlayerScript(string name);
|
||||||
|
bool LoadPlayerScript(const char* name);
|
||||||
bool LoadRegionScript(string name);
|
bool LoadRegionScript(string name);
|
||||||
bool LoadRegionScript(const char* name);
|
bool LoadRegionScript(const char* name);
|
||||||
LuaSpell* LoadSpellScript(string name);
|
LuaSpell* LoadSpellScript(string name);
|
||||||
@ -242,10 +283,12 @@ public:
|
|||||||
void UseItemScript(const char* name, lua_State* state, bool val);
|
void UseItemScript(const char* name, lua_State* state, bool val);
|
||||||
void UseSpawnScript(const char* name, lua_State* state, bool val);
|
void UseSpawnScript(const char* name, lua_State* state, bool val);
|
||||||
void UseZoneScript(const char* name, lua_State* state, bool val);
|
void UseZoneScript(const char* name, lua_State* state, bool val);
|
||||||
|
void UsePlayerScript(const char* name, lua_State* state, bool val);
|
||||||
void UseRegionScript(const char* name, lua_State* state, bool val);
|
void UseRegionScript(const char* name, lua_State* state, bool val);
|
||||||
lua_State* GetItemScript(const char* name, bool create_new = true, bool use = false);
|
lua_State* GetItemScript(const char* name, bool create_new = true, bool use = false);
|
||||||
lua_State* GetSpawnScript(const char* name, bool create_new = true, bool use = false);
|
lua_State* GetSpawnScript(const char* name, bool create_new = true, bool use = false);
|
||||||
lua_State* GetZoneScript(const char* name, bool create_new = true, bool use = false);
|
lua_State* GetZoneScript(const char* name, bool create_new = true, bool use = false);
|
||||||
|
lua_State* GetPlayerScript(const char* name, bool create_new = true, bool use = false);
|
||||||
lua_State* GetRegionScript(const char* name, bool create_new = true, bool use = false);
|
lua_State* GetRegionScript(const char* name, bool create_new = true, bool use = false);
|
||||||
LuaSpell* GetSpellScript(const char* name, bool create_new = true, bool use = true);
|
LuaSpell* GetSpellScript(const char* name, bool create_new = true, bool use = true);
|
||||||
LuaSpell* CreateSpellScript(const char* name, lua_State* existState);
|
LuaSpell* CreateSpellScript(const char* name, lua_State* existState);
|
||||||
@ -263,6 +306,7 @@ public:
|
|||||||
bool CallSpawnScript(lua_State* state, int8 num_parameters);
|
bool CallSpawnScript(lua_State* state, int8 num_parameters);
|
||||||
bool RunZoneScript(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn = 0, int32 int32_arg1 = 0, const char* str_arg1 = 0, Spawn* spawn_arg1 = 0, int32 int32_arg2 = 0, const char* str_arg2 = 0, Spawn* spawn_arg2 = 0);
|
bool RunZoneScript(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn = 0, int32 int32_arg1 = 0, const char* str_arg1 = 0, Spawn* spawn_arg1 = 0, int32 int32_arg2 = 0, const char* str_arg2 = 0, Spawn* spawn_arg2 = 0);
|
||||||
bool RunZoneScriptWithReturn(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn, int32 int32_arg1, int32 int32_arg2, int32 int32_arg3, int32* returnValue = 0);
|
bool RunZoneScriptWithReturn(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn, int32 int32_arg1, int32 int32_arg2, int32 int32_arg3, int32* returnValue = 0);
|
||||||
|
bool RunPlayerScriptWithReturn(const string script_name, const char* function_name, const std::vector<LuaArg>& args, sint32* returnValue = 0);
|
||||||
bool CallScriptInt32(lua_State* state, int8 num_parameters, int32* returnValue = 0);
|
bool CallScriptInt32(lua_State* state, int8 num_parameters, int32* returnValue = 0);
|
||||||
bool CallScriptSInt32(lua_State* state, int8 num_parameters, sint32* returnValue = 0);
|
bool CallScriptSInt32(lua_State* state, int8 num_parameters, sint32* returnValue = 0);
|
||||||
bool RunRegionScript(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn = 0, sint32 int32_arg1 = 0, int32* returnValue = 0);
|
bool RunRegionScript(string script_name, const char* function_name, ZoneServer* zone, Spawn* spawn = 0, sint32 int32_arg1 = 0, int32* returnValue = 0);
|
||||||
@ -273,6 +317,7 @@ public:
|
|||||||
void DestroyItemScripts();
|
void DestroyItemScripts();
|
||||||
void DestroyQuests(bool reload = false);
|
void DestroyQuests(bool reload = false);
|
||||||
void DestroyZoneScripts();
|
void DestroyZoneScripts();
|
||||||
|
void DestroyPlayerScripts();
|
||||||
void DestroyRegionScripts();
|
void DestroyRegionScripts();
|
||||||
void SimpleLogError(const char* error);
|
void SimpleLogError(const char* error);
|
||||||
void LogError(const char* error, ...);
|
void LogError(const char* error, ...);
|
||||||
@ -290,6 +335,7 @@ public:
|
|||||||
Mutex* GetSpawnScriptMutex(const char* name);
|
Mutex* GetSpawnScriptMutex(const char* name);
|
||||||
Mutex* GetItemScriptMutex(const char* name);
|
Mutex* GetItemScriptMutex(const char* name);
|
||||||
Mutex* GetZoneScriptMutex(const char* name);
|
Mutex* GetZoneScriptMutex(const char* name);
|
||||||
|
Mutex* GetPlayerScriptMutex(const char* name);
|
||||||
Mutex* GetRegionScriptMutex(const char* name);
|
Mutex* GetRegionScriptMutex(const char* name);
|
||||||
Mutex* GetSpellScriptMutex(const char* name);
|
Mutex* GetSpellScriptMutex(const char* name);
|
||||||
Mutex* GetQuestMutex(Quest* quest);
|
Mutex* GetQuestMutex(Quest* quest);
|
||||||
@ -330,6 +376,7 @@ private:
|
|||||||
map<string, map<lua_State*, bool> > item_scripts;
|
map<string, map<lua_State*, bool> > item_scripts;
|
||||||
map<string, map<lua_State*, bool> > spawn_scripts;
|
map<string, map<lua_State*, bool> > spawn_scripts;
|
||||||
map<string, map<lua_State*, bool> > zone_scripts;
|
map<string, map<lua_State*, bool> > zone_scripts;
|
||||||
|
map<string, map<lua_State*, bool> > player_scripts;
|
||||||
map<string, map<lua_State*, bool> > region_scripts;
|
map<string, map<lua_State*, bool> > region_scripts;
|
||||||
map<string, map<lua_State*, LuaSpell*> > spell_scripts;
|
map<string, map<lua_State*, LuaSpell*> > spell_scripts;
|
||||||
|
|
||||||
@ -339,11 +386,13 @@ private:
|
|||||||
map<lua_State*, string> item_inverse_scripts;
|
map<lua_State*, string> item_inverse_scripts;
|
||||||
map<lua_State*, string> spawn_inverse_scripts;
|
map<lua_State*, string> spawn_inverse_scripts;
|
||||||
map<lua_State*, string> zone_inverse_scripts;
|
map<lua_State*, string> zone_inverse_scripts;
|
||||||
|
map<lua_State*, string> player_inverse_scripts;
|
||||||
map<lua_State*, string> region_inverse_scripts;
|
map<lua_State*, string> region_inverse_scripts;
|
||||||
|
|
||||||
map<string, Mutex*> item_scripts_mutex;
|
map<string, Mutex*> item_scripts_mutex;
|
||||||
map<string, Mutex*> spawn_scripts_mutex;
|
map<string, Mutex*> spawn_scripts_mutex;
|
||||||
map<string, Mutex*> zone_scripts_mutex;
|
map<string, Mutex*> zone_scripts_mutex;
|
||||||
|
map<string, Mutex*> player_scripts_mutex;
|
||||||
map<int32, Mutex*> quests_mutex;
|
map<int32, Mutex*> quests_mutex;
|
||||||
map<string, Mutex*> region_scripts_mutex;
|
map<string, Mutex*> region_scripts_mutex;
|
||||||
map<string, Mutex*> spell_scripts_mutex;
|
map<string, Mutex*> spell_scripts_mutex;
|
||||||
@ -353,6 +402,7 @@ private:
|
|||||||
Mutex MSpawnScripts;
|
Mutex MSpawnScripts;
|
||||||
Mutex MItemScripts;
|
Mutex MItemScripts;
|
||||||
Mutex MZoneScripts;
|
Mutex MZoneScripts;
|
||||||
|
Mutex MPlayerScripts;
|
||||||
Mutex MQuests;
|
Mutex MQuests;
|
||||||
Mutex MLUAMain;
|
Mutex MLUAMain;
|
||||||
Mutex MSpellDelete;
|
Mutex MSpellDelete;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
EQ2Emulator: Everquest II Server Emulator
|
EQ2Emulator: Everquest II Server Emulator
|
||||||
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
|
Copyright (C) 2005 - 2025 EQ2EMulator Development Team (http://www.eq2emu.com formerly http://www.eq2emulator.net)
|
||||||
|
|
||||||
This file is part of EQ2Emulator.
|
This file is part of EQ2Emulator.
|
||||||
|
|
||||||
@ -17,6 +17,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "../common/MiscFunctions.h"
|
#include "../common/MiscFunctions.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
@ -46,6 +47,7 @@ extern MasterItemList master_item_list;
|
|||||||
extern RuleManager rule_manager;
|
extern RuleManager rule_manager;
|
||||||
extern MasterTitlesList master_titles_list;
|
extern MasterTitlesList master_titles_list;
|
||||||
extern MasterLanguagesList master_languages_list;
|
extern MasterLanguagesList master_languages_list;
|
||||||
|
std::map<int8, int32> Player::m_levelXPReq;
|
||||||
|
|
||||||
Player::Player(){
|
Player::Player(){
|
||||||
tutorial_step = 0;
|
tutorial_step = 0;
|
||||||
@ -998,8 +1000,8 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
|
|||||||
packet->setDataByName("decrease_falling_dmg", 169);
|
packet->setDataByName("decrease_falling_dmg", 169);
|
||||||
|
|
||||||
if (version <= 561) {
|
if (version <= 561) {
|
||||||
packet->setDataByName("exp_yellow", info_struct->get_xp_yellow() / 10);
|
packet->setDataByName("exp_yellow", info_struct->get_xp_yellow() / 10);
|
||||||
packet->setDataByName("exp_blue", info_struct->get_xp_blue()/100);
|
packet->setDataByName("exp_blue", ((int16)info_struct->get_xp_yellow() % 100) + (info_struct->get_xp_blue() / 100));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
packet->setDataByName("exp_yellow", info_struct->get_xp_yellow());
|
packet->setDataByName("exp_yellow", info_struct->get_xp_yellow());
|
||||||
@ -2136,7 +2138,7 @@ bool Player::AddItemToBank(Item* item) {
|
|||||||
}
|
}
|
||||||
EQ2Packet* Player::SendInventoryUpdate(int16 version) {
|
EQ2Packet* Player::SendInventoryUpdate(int16 version) {
|
||||||
// assure any inventory updates are reflected in sell window
|
// assure any inventory updates are reflected in sell window
|
||||||
if(GetClient() && GetClient()->GetMerchantTransaction())
|
if(GetClient() && GetClient()->GetMerchantTransactionID())
|
||||||
GetClient()->SendSellMerchantList();
|
GetClient()->SendSellMerchantList();
|
||||||
|
|
||||||
return item_list.serialize(this, version);
|
return item_list.serialize(this, version);
|
||||||
@ -4419,11 +4421,20 @@ void Player::SetNeededXP(){
|
|||||||
//GetInfoStruct()->xp_needed = GetLevel() * 100;
|
//GetInfoStruct()->xp_needed = GetLevel() * 100;
|
||||||
// Get xp needed to get to the next level
|
// Get xp needed to get to the next level
|
||||||
int16 level = GetLevel() + 1;
|
int16 level = GetLevel() + 1;
|
||||||
// If next level is beyond what we have in the map multiply the last value we have by how many levels we are over plus one
|
SetNeededXP(GetNeededXPByLevel(level));
|
||||||
if (level > 95)
|
}
|
||||||
SetNeededXP(database.GetMysqlExpCurve(95)* ((level - 95) + 1));
|
|
||||||
|
int32 Player::GetNeededXPByLevel(int8 level) {
|
||||||
|
int32 exp_required = 0;
|
||||||
|
if (!Player::m_levelXPReq.count(level) && level > 95 && Player::m_levelXPReq.count(95)) {
|
||||||
|
exp_required = (Player::m_levelXPReq[95] * ((level - 95) + 1));
|
||||||
|
}
|
||||||
|
else if(Player::m_levelXPReq.count(level))
|
||||||
|
exp_required = Player::m_levelXPReq[level];
|
||||||
else
|
else
|
||||||
SetNeededXP(database.GetMysqlExpCurve(level));
|
exp_required = 0;
|
||||||
|
|
||||||
|
return exp_required;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SetXP(int32 val){
|
void Player::SetXP(int32 val){
|
||||||
@ -4519,10 +4530,24 @@ bool Player::AddXP(int32 xp_amount){
|
|||||||
SetCharSheetChanged(true);
|
SetCharSheetChanged(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
int32 prev_xp_amount = xp_amount;
|
||||||
xp_amount -= GetNeededXP() - GetXP();
|
xp_amount -= GetNeededXP() - GetXP();
|
||||||
SetLevel(GetLevel() + 1);
|
if(GetClient()->ChangeLevel(GetLevel(), GetLevel()+1, prev_xp_amount))
|
||||||
|
SetLevel(GetLevel() + 1);
|
||||||
|
else {
|
||||||
|
SetXP(GetXP() + prev_xp_amount);
|
||||||
|
SetCharSheetChanged(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the actual end xp_amount result
|
||||||
SetXP(GetXP() + xp_amount);
|
SetXP(GetXP() + xp_amount);
|
||||||
|
|
||||||
|
if(GetClient()) {
|
||||||
|
GetClient()->Message(CHANNEL_REWARD, "You gain %u experience!", (int32)xp_amount);
|
||||||
|
}
|
||||||
|
|
||||||
GetPlayerInfo()->CalculateXPPercentages();
|
GetPlayerInfo()->CalculateXPPercentages();
|
||||||
current_xp_percent = ((float)GetXP()/(float)GetNeededXP())*100;
|
current_xp_percent = ((float)GetXP()/(float)GetNeededXP())*100;
|
||||||
if(miniding_min_percent > 0.0f && current_xp_percent >= miniding_min_percent){
|
if(miniding_min_percent > 0.0f && current_xp_percent >= miniding_min_percent){
|
||||||
@ -4532,15 +4557,8 @@ bool Player::AddXP(int32 xp_amount){
|
|||||||
SetPower(GetTotalPower());
|
SetPower(GetTotalPower());
|
||||||
GetZone()->SendCastSpellPacket(332, this, this); //send mini level up spell effect
|
GetZone()->SendCastSpellPacket(332, this, this); //send mini level up spell effect
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetClient()) {
|
|
||||||
GetClient()->Message(CHANNEL_REWARD, "You gain %u experience!", (int32)xp_amount);
|
|
||||||
|
|
||||||
if (prev_level != GetLevel())
|
|
||||||
GetClient()->ChangeLevel(prev_level, GetLevel());
|
|
||||||
}
|
|
||||||
|
|
||||||
SetCharSheetChanged(true);
|
SetCharSheetChanged(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4550,7 +4568,16 @@ bool Player::AddTSXP(int32 xp_amount){
|
|||||||
MStats.unlock();
|
MStats.unlock();
|
||||||
|
|
||||||
float current_xp_percent = ((float)GetTSXP()/(float)GetNeededTSXP())*100;
|
float current_xp_percent = ((float)GetTSXP()/(float)GetNeededTSXP())*100;
|
||||||
float miniding_min_percent = ((int)(current_xp_percent/10)+1)*10;
|
|
||||||
|
int32 mini_ding_pct = rule_manager.GetGlobalRule(R_Player, MiniDingPercentage)->GetInt32();
|
||||||
|
float miniding_min_percent = 0.0f;
|
||||||
|
if(mini_ding_pct < 10 || mini_ding_pct > 50) {
|
||||||
|
mini_ding_pct = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
miniding_min_percent = ((int)(current_xp_percent/mini_ding_pct)+1)*mini_ding_pct;
|
||||||
|
}
|
||||||
|
|
||||||
while((xp_amount + GetTSXP()) >= GetNeededTSXP()){
|
while((xp_amount + GetTSXP()) >= GetNeededTSXP()){
|
||||||
if (!CheckLevelStatus(GetTSLevel() + 1)) {
|
if (!CheckLevelStatus(GetTSLevel() + 1)) {
|
||||||
if(GetClient()) {
|
if(GetClient()) {
|
||||||
@ -4558,10 +4585,18 @@ bool Player::AddTSXP(int32 xp_amount){
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
int32 prev_xp_amount = xp_amount;
|
||||||
xp_amount -= GetNeededTSXP() - GetTSXP();
|
xp_amount -= GetNeededTSXP() - GetTSXP();
|
||||||
SetTSLevel(GetTSLevel() + 1);
|
if(GetClient()->ChangeTSLevel(GetLevel(), GetLevel()+1, prev_xp_amount)) {
|
||||||
SetTSXP(0);
|
SetTSLevel(GetTSLevel() + 1);
|
||||||
SetNeededTSXP();
|
SetTSXP(0);
|
||||||
|
SetNeededTSXP();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SetTSXP(GetTSXP() + prev_xp_amount);
|
||||||
|
SetCharSheetChanged(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SetTSXP(GetTSXP() + xp_amount);
|
SetTSXP(GetTSXP() + xp_amount);
|
||||||
GetPlayerInfo()->CalculateXPPercentages();
|
GetPlayerInfo()->CalculateXPPercentages();
|
||||||
@ -4577,6 +4612,8 @@ bool Player::AddTSXP(int32 xp_amount){
|
|||||||
GetInfoStruct()->set_tradeskill_class2(1);
|
GetInfoStruct()->set_tradeskill_class2(1);
|
||||||
GetInfoStruct()->set_tradeskill_class3(1);
|
GetInfoStruct()->set_tradeskill_class3(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetCharSheetChanged(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6423,7 +6460,8 @@ int32 CharacterInstances::GetInstanceCount() {
|
|||||||
return instanceList.size();
|
return instanceList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SetPlayerAdventureClass(int8 new_class){
|
void Player::SetPlayerAdventureClass(int8 new_class, bool set_by_gm_command ){
|
||||||
|
int8 old_class = GetAdventureClass();
|
||||||
SetAdventureClass(new_class);
|
SetAdventureClass(new_class);
|
||||||
GetInfoStruct()->set_class1(classes.GetBaseClass(new_class));
|
GetInfoStruct()->set_class1(classes.GetBaseClass(new_class));
|
||||||
GetInfoStruct()->set_class2(classes.GetSecondaryBaseClass(new_class));
|
GetInfoStruct()->set_class2(classes.GetSecondaryBaseClass(new_class));
|
||||||
@ -6433,6 +6471,23 @@ void Player::SetPlayerAdventureClass(int8 new_class){
|
|||||||
GetZone()->TriggerCharSheetTimer();
|
GetZone()->TriggerCharSheetTimer();
|
||||||
if(GetClient())
|
if(GetClient())
|
||||||
GetClient()->UpdateTimeStampFlag ( CLASS_UPDATE_FLAG );
|
GetClient()->UpdateTimeStampFlag ( CLASS_UPDATE_FLAG );
|
||||||
|
|
||||||
|
const char* playerScript = world.GetPlayerScript(0); // 0 = global script
|
||||||
|
const char* playerZoneScript = world.GetPlayerScript(GetZoneID()); // zone script
|
||||||
|
if(playerScript || playerZoneScript) {
|
||||||
|
std::vector<LuaArg> args = {
|
||||||
|
LuaArg(GetZone()),
|
||||||
|
LuaArg(this),
|
||||||
|
LuaArg(old_class),
|
||||||
|
LuaArg(new_class)
|
||||||
|
};
|
||||||
|
if(playerScript) {
|
||||||
|
lua_interface->RunPlayerScriptWithReturn(playerScript, "on_class_change", args);
|
||||||
|
}
|
||||||
|
if(playerZoneScript) {
|
||||||
|
lua_interface->RunPlayerScriptWithReturn(playerZoneScript, "on_class_change", args);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::AddSkillBonus(int32 spell_id, int32 skill_id, float value) {
|
void Player::AddSkillBonus(int32 spell_id, int32 skill_id, float value) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
EQ2Emulator: Everquest II Server Emulator
|
EQ2Emulator: Everquest II Server Emulator
|
||||||
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
|
Copyright (C) 2005 - 2025 EQ2EMulator Development Team (http://www.eq2emu.com formerly http://www.eq2emulator.net)
|
||||||
|
|
||||||
This file is part of EQ2Emulator.
|
This file is part of EQ2Emulator.
|
||||||
|
|
||||||
@ -17,6 +17,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __EQ2_PLAYER__
|
#ifndef __EQ2_PLAYER__
|
||||||
#define __EQ2_PLAYER__
|
#define __EQ2_PLAYER__
|
||||||
|
|
||||||
@ -608,6 +609,7 @@ public:
|
|||||||
bool TradeskillXPEnabled();
|
bool TradeskillXPEnabled();
|
||||||
void SetNeededXP(int32 val);
|
void SetNeededXP(int32 val);
|
||||||
void SetNeededXP();
|
void SetNeededXP();
|
||||||
|
static int32 GetNeededXPByLevel(int8 level);
|
||||||
void SetXP(int32 val);
|
void SetXP(int32 val);
|
||||||
void SetNeededTSXP(int32 val);
|
void SetNeededTSXP(int32 val);
|
||||||
void SetNeededTSXP();
|
void SetNeededTSXP();
|
||||||
@ -789,7 +791,7 @@ public:
|
|||||||
bool GetIsTracking() const { return is_tracking; }
|
bool GetIsTracking() const { return is_tracking; }
|
||||||
void SetBiography(string new_biography) { biography = new_biography; }
|
void SetBiography(string new_biography) { biography = new_biography; }
|
||||||
string GetBiography() const { return biography; }
|
string GetBiography() const { return biography; }
|
||||||
void SetPlayerAdventureClass(int8 new_class);
|
void SetPlayerAdventureClass(int8 new_class, bool set_by_gm_command = false);
|
||||||
void SetGuild(Guild* new_guild) { guild = new_guild; }
|
void SetGuild(Guild* new_guild) { guild = new_guild; }
|
||||||
Guild* GetGuild() { return guild; }
|
Guild* GetGuild() { return guild; }
|
||||||
void AddSkillBonus(int32 spell_id, int32 skill_id, float value);
|
void AddSkillBonus(int32 spell_id, int32 skill_id, float value);
|
||||||
@ -1112,8 +1114,8 @@ public:
|
|||||||
mutable std::shared_mutex trait_mutex;
|
mutable std::shared_mutex trait_mutex;
|
||||||
std::atomic<bool> need_trait_update;
|
std::atomic<bool> need_trait_update;
|
||||||
|
|
||||||
void InitXPTable();
|
static void InitXPTable();
|
||||||
map<int8, int32> m_levelXPReq;
|
static map<int8, int32> m_levelXPReq;
|
||||||
|
|
||||||
mutable std::shared_mutex spell_packet_update_mutex;
|
mutable std::shared_mutex spell_packet_update_mutex;
|
||||||
mutable std::shared_mutex raid_update_mutex;
|
mutable std::shared_mutex raid_update_mutex;
|
||||||
@ -1214,8 +1216,6 @@ private:
|
|||||||
void AddSpellStatus(SpellBookEntry* spell, sint16 value, bool modify_recast = true, int16 recast = 0);
|
void AddSpellStatus(SpellBookEntry* spell, sint16 value, bool modify_recast = true, int16 recast = 0);
|
||||||
void RemoveSpellStatus(SpellBookEntry* spell, sint16 value, bool modify_recast = true, int16 recast = 0);
|
void RemoveSpellStatus(SpellBookEntry* spell, sint16 value, bool modify_recast = true, int16 recast = 0);
|
||||||
void SetSpellEntryRecast(SpellBookEntry* spell, bool modify_recast, int16 recast);
|
void SetSpellEntryRecast(SpellBookEntry* spell, bool modify_recast, int16 recast);
|
||||||
// void InitXPTable();
|
|
||||||
// map<int8, int32> m_levelXPReq;
|
|
||||||
|
|
||||||
//The following variables are for serializing spawn packets
|
//The following variables are for serializing spawn packets
|
||||||
PacketStruct* spawn_pos_struct;
|
PacketStruct* spawn_pos_struct;
|
||||||
|
@ -2197,18 +2197,25 @@ void Spawn::InitializePosPacketData(Player* player, PacketStruct* packet, bool b
|
|||||||
if (size == 0)
|
if (size == 0)
|
||||||
size = 32;
|
size = 32;
|
||||||
|
|
||||||
|
float scaled = 0.0f;
|
||||||
|
|
||||||
|
sint16 new_size = size;
|
||||||
|
if(IsEntity() && !IsPlayer()) { // doesn't work correctly for Player, only non-Player (NPC/Object/etc)
|
||||||
|
scaled = static_cast<float>(size) + (((Entity*)this)->GetInfoStruct()->get_size_mod() * size);
|
||||||
|
// Round and cast to sint16
|
||||||
|
new_size = static_cast<sint16>(std::round(scaled));
|
||||||
|
// Enforce minimum size of 1
|
||||||
|
new_size = std::max<sint16>(new_size, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (version <= 910) {
|
if (version <= 910) {
|
||||||
packet->setDataByName("pos_collision_radius", appearance.pos.collision_radius > 0 ? appearance.pos.collision_radius : 32);
|
packet->setDataByName("pos_collision_radius", appearance.pos.collision_radius > 0 ? appearance.pos.collision_radius : 32);
|
||||||
packet->setDataByName("pos_size", size > 0 ? size : 32);
|
packet->setDataByName("pos_size", new_size > 0 ? new_size : 32);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
packet->setDataByName("pos_collision_radius", appearance.pos.collision_radius > 0 ? appearance.pos.collision_radius : 32);
|
packet->setDataByName("pos_collision_radius", appearance.pos.collision_radius > 0 ? appearance.pos.collision_radius : 32);
|
||||||
|
packet->setDataByName("pos_size", new_size > 0 ? (((float)new_size) / 32.0f) : 1.0f); // float not an integer
|
||||||
|
|
||||||
if(!IsPlayer())
|
|
||||||
packet->setDataByName("pos_size", size > 0 ? (((float)size) / 32.0f) : 1.0f); // float not an integer
|
|
||||||
else
|
|
||||||
packet->setDataByName("pos_size", 1.0f);
|
|
||||||
|
|
||||||
// please do not remove! This makes it so NPCs for example do not resize large/small when you are in combat with them!
|
// please do not remove! This makes it so NPCs for example do not resize large/small when you are in combat with them!
|
||||||
packet->setDataByName("pos_size_ratio", 1.0f);
|
packet->setDataByName("pos_size_ratio", 1.0f);
|
||||||
}
|
}
|
||||||
@ -2487,11 +2494,6 @@ void Spawn::InitializeInfoPacketData(Player* spawn, PacketStruct* packet) {
|
|||||||
packet->setDataByName("npc", 1);
|
packet->setDataByName("npc", 1);
|
||||||
if (GetMerchantID() > 0)
|
if (GetMerchantID() > 0)
|
||||||
packet->setDataByName("merchant", 1);
|
packet->setDataByName("merchant", 1);
|
||||||
|
|
||||||
if(IsEntity() && ((Entity*)this)->GetInfoStruct()->get_size_mod() != 0.0f) {
|
|
||||||
float mod = ((Entity*)this)->GetInfoStruct()->get_size_mod(); // e.g., -0.25 or +0.25
|
|
||||||
//packet->setDataByName("temporary_scale", mod); //TODO: Understand what these mod values should be, anything we send makes the client shrink to nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
packet->setDataByName("effective_level", IsEntity() && ((Entity*)this)->GetInfoStruct()->get_effective_level() != 0 ? (int8)((Entity*)this)->GetInfoStruct()->get_effective_level() : (int8)GetLevel());
|
packet->setDataByName("effective_level", IsEntity() && ((Entity*)this)->GetInfoStruct()->get_effective_level() != 0 ? (int8)((Entity*)this)->GetInfoStruct()->get_effective_level() : (int8)GetLevel());
|
||||||
packet->setDataByName("level", (int8)GetLevel());
|
packet->setDataByName("level", (int8)GetLevel());
|
||||||
@ -3360,8 +3362,9 @@ void Spawn::ProcessMovement(bool isSpawnListLocked){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!movementCase && IsRunning() && !IsPauseMovementTimerActive()) {
|
if (!movementCase && IsRunning() && !IsPauseMovementTimerActive()) {
|
||||||
CalculateRunningLocation();
|
// 6/7/2025: Fixes glitchy movement when spawns are close together and keep warping forward and back to the original position
|
||||||
//last_movement_update = Timer::GetCurrentTime2();
|
CalculateRunningLocation(true);
|
||||||
|
last_movement_update = Timer::GetCurrentTime2();
|
||||||
}
|
}
|
||||||
else if(movementCase)
|
else if(movementCase)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "Tradeskills/Tradeskills.h"
|
#include "Tradeskills/Tradeskills.h"
|
||||||
#include "ClientPacketFunctions.h"
|
#include "ClientPacketFunctions.h"
|
||||||
#include "Rules/Rules.h"
|
#include "Rules/Rules.h"
|
||||||
|
#include "races.h"
|
||||||
|
|
||||||
extern MasterSpellList master_spell_list;
|
extern MasterSpellList master_spell_list;
|
||||||
extern MasterSkillList master_skill_list;
|
extern MasterSkillList master_skill_list;
|
||||||
@ -30,6 +31,7 @@ extern LuaInterface* lua_interface;
|
|||||||
extern Commands commands;
|
extern Commands commands;
|
||||||
extern World world;
|
extern World world;
|
||||||
extern RuleManager rule_manager;
|
extern RuleManager rule_manager;
|
||||||
|
extern Races races;
|
||||||
|
|
||||||
SpellProcess::SpellProcess(){
|
SpellProcess::SpellProcess(){
|
||||||
last_checked_time = 0;
|
last_checked_time = 0;
|
||||||
@ -510,32 +512,18 @@ bool SpellProcess::DeleteCasterSpell(LuaSpell* spell, string reason, bool removi
|
|||||||
if(target && target->IsPlayer() && spell->spell->GetSpellData()->fade_message.length() > 0){
|
if(target && target->IsPlayer() && spell->spell->GetSpellData()->fade_message.length() > 0){
|
||||||
Client* client = ((Player*)target)->GetClient();
|
Client* client = ((Player*)target)->GetClient();
|
||||||
if(client){
|
if(client){
|
||||||
bool send_to_sender = true;
|
|
||||||
string fade_message = spell->spell->GetSpellData()->fade_message;
|
string fade_message = spell->spell->GetSpellData()->fade_message;
|
||||||
if(fade_message.find("%t") != string::npos)
|
ReplaceEffectTokens(fade_message, spell->caster, target);
|
||||||
fade_message.replace(fade_message.find("%t"), 2, target->GetName());
|
|
||||||
client->Message(CHANNEL_SPELLS_OTHER, fade_message.c_str());
|
client->Message(CHANNEL_SPELLS_OTHER, fade_message.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (target && target->IsPlayer() && spell->spell->GetSpellData()->fade_message.length() > 0) {
|
if (target && target->IsPlayer() && spell->spell->GetSpellData()->fade_message_others.length() > 0) {
|
||||||
Client* client = ((Player*)target)->GetClient();
|
Client* client = ((Player*)target)->GetClient();
|
||||||
if (client) {
|
if (client) {
|
||||||
bool send_to_sender = true;
|
|
||||||
string fade_message_others = spell->spell->GetSpellData()->fade_message_others;
|
string fade_message_others = spell->spell->GetSpellData()->fade_message_others;
|
||||||
if (fade_message_others.find("%t") != string::npos)
|
ReplaceEffectTokens(fade_message_others, spell->caster, target);
|
||||||
fade_message_others.replace(fade_message_others.find("%t"), 2, target->GetName());
|
|
||||||
if (fade_message_others.find("%c") != string::npos)
|
|
||||||
fade_message_others.replace(fade_message_others.find("%c"), 2, spell->caster->GetName());
|
|
||||||
if (fade_message_others.find("%T") != string::npos) {
|
|
||||||
fade_message_others.replace(fade_message_others.find("%T"), 2, target->GetName());
|
|
||||||
send_to_sender = false;
|
|
||||||
}
|
|
||||||
if (fade_message_others.find("%C") != string::npos) {
|
|
||||||
fade_message_others.replace(fade_message_others.find("%C"), 2, spell->caster->GetName());
|
|
||||||
send_to_sender = false;
|
|
||||||
}
|
|
||||||
if(spell->caster->GetZone()) {
|
if(spell->caster->GetZone()) {
|
||||||
spell->caster->GetZone()->SimpleMessage(CHANNEL_SPELLS_OTHER, fade_message_others.c_str(), target, 50, send_to_sender);
|
spell->caster->GetZone()->SimpleMessage(CHANNEL_SPELLS_OTHER, fade_message_others.c_str(), target, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1803,29 +1791,16 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her
|
|||||||
if(spell->spell->GetSpellData()->success_message.length() > 0){
|
if(spell->spell->GetSpellData()->success_message.length() > 0){
|
||||||
if(client){
|
if(client){
|
||||||
string success_message = spell->spell->GetSpellData()->success_message;
|
string success_message = spell->spell->GetSpellData()->success_message;
|
||||||
if(success_message.find("%t") != string::npos)
|
ReplaceEffectTokens(success_message, spell->caster, target);
|
||||||
success_message.replace(success_message.find("%t"), 2, spell->caster->GetName());
|
|
||||||
client->Message(CHANNEL_SPELLS, success_message.c_str());
|
client->Message(CHANNEL_SPELLS, success_message.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(spell->spell->GetSpellData()->effect_message.length() > 0){
|
if(spell->spell->GetSpellData()->effect_message.length() > 0){
|
||||||
string effect_message = spell->spell->GetSpellData()->effect_message;
|
string effect_message = spell->spell->GetSpellData()->effect_message;
|
||||||
bool send_to_sender = true;
|
ReplaceEffectTokens(effect_message, spell->caster, target);
|
||||||
if(effect_message.find("%t") != string::npos)
|
|
||||||
effect_message.replace(effect_message.find("%t"), 2, target->GetName());
|
|
||||||
if (effect_message.find("%c") != string::npos)
|
|
||||||
effect_message.replace(effect_message.find("%c"), 2, spell->caster->GetName());
|
|
||||||
if (effect_message.find("%T") != string::npos) {
|
|
||||||
effect_message.replace(effect_message.find("%T"), 2, target->GetName());
|
|
||||||
send_to_sender = false;
|
|
||||||
}
|
|
||||||
if (effect_message.find("%C") != string::npos) {
|
|
||||||
effect_message.replace(effect_message.find("%C"), 2, spell->caster->GetName());
|
|
||||||
send_to_sender = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(spell->caster && spell->caster->GetZone()) {
|
if(spell->caster && spell->caster->GetZone()) {
|
||||||
spell->caster->GetZone()->SimpleMessage(CHANNEL_SPELLS_OTHER, effect_message.c_str(), target, 50, send_to_sender);
|
spell->caster->GetZone()->SimpleMessage(CHANNEL_SPELLS_OTHER, effect_message.c_str(), target, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(target->GetZone()) {
|
if(target->GetZone()) {
|
||||||
@ -3099,4 +3074,193 @@ bool SpellProcess::AddLuaSpellTarget(LuaSpell* lua_spell, int32 id, bool lock_sp
|
|||||||
lua_spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__);
|
lua_spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpellProcess::ReplaceEffectTokens(std::string& message, Spawn* in_caster, Spawn* in_target) {
|
||||||
|
std::string caster = in_caster ? std::string(in_caster->GetName()) : "Unknown";
|
||||||
|
std::string target = in_target ? std::string(in_target->GetName()) : "Unknown";
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
|
if(message.find("%", 0) == std::string::npos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Replace all %C and suppress send
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%C", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, caster);
|
||||||
|
pos += caster.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %c (no suppression)
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%c", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, caster);
|
||||||
|
pos += caster.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %T and suppress send
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%T", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, target);
|
||||||
|
pos += target.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %t (no suppression)
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%t", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, target);
|
||||||
|
pos += target.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string target_assist = in_target && in_target->GetTarget() ? std::string(in_target->GetTarget()->GetName()) : "Unknown";
|
||||||
|
|
||||||
|
if(target_assist == "Unknown" && target != "Unknown")
|
||||||
|
target_assist = target;
|
||||||
|
// Replace all %T and suppress send
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%A", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, target_assist);
|
||||||
|
pos += target_assist.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %t (no suppression)
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%a", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, target_assist);
|
||||||
|
pos += target_assist.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string gender_name = "Unknown";
|
||||||
|
std::string gender_oname = "It";
|
||||||
|
std::string gender_sname = "It";
|
||||||
|
std::string gender_pname = "Its";
|
||||||
|
|
||||||
|
if(in_target) {
|
||||||
|
if(in_target->GetGender() == 1) {
|
||||||
|
gender_name = "Male";
|
||||||
|
gender_oname = "Him";
|
||||||
|
gender_sname = "He";
|
||||||
|
gender_pname = "His";
|
||||||
|
}
|
||||||
|
else if(in_target->GetGender() == 0) {
|
||||||
|
gender_name = "Female";
|
||||||
|
gender_oname = "Her";
|
||||||
|
gender_sname = "She";
|
||||||
|
gender_pname = "Her";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %T and suppress send
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%G", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, gender_name);
|
||||||
|
pos += gender_name.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %t (no suppression)
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%g", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, gender_name);
|
||||||
|
pos += gender_name.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%O", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, gender_oname);
|
||||||
|
pos += gender_oname.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %t (no suppression)
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%o", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, gender_oname);
|
||||||
|
pos += gender_oname.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%S", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, gender_sname);
|
||||||
|
pos += gender_sname.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %t (no suppression)
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%s", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, gender_sname);
|
||||||
|
pos += gender_sname.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%P", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, gender_pname);
|
||||||
|
pos += gender_pname.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %t (no suppression)
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%p", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, gender_pname);
|
||||||
|
pos += gender_pname.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string raceName = "Unknown";
|
||||||
|
if(in_target) {
|
||||||
|
const char* raceCaseName = races.GetRaceNameCase(in_target->GetRace());
|
||||||
|
if(raceCaseName)
|
||||||
|
raceName = std::string(raceCaseName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string tell_name = "Unknown";
|
||||||
|
if(in_caster && in_caster->IsPlayer()) {
|
||||||
|
if(((Player*)in_caster)->GetClient() && ((Player*)in_caster)->GetClient()->GetLastTellName().size() > 0)
|
||||||
|
tell_name = ((Player*)in_caster)->GetClient()->GetLastTellName();
|
||||||
|
}
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%RT", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 3, tell_name);
|
||||||
|
pos += tell_name.length();
|
||||||
|
}
|
||||||
|
// Replace all %t (no suppression)
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%rt", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 3, tell_name);
|
||||||
|
pos += tell_name.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%R", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, raceName);
|
||||||
|
pos += raceName.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %t (no suppression)
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%r", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, raceName);
|
||||||
|
pos += raceName.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::string petName = "Unknown";
|
||||||
|
if(in_caster && in_caster->IsEntity() && ((Entity*)in_caster)->GetPet()) {
|
||||||
|
petName = std::string(((Entity*)in_caster)->GetPet()->GetName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%M", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, petName);
|
||||||
|
pos += petName.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all %t (no suppression)
|
||||||
|
pos = 0;
|
||||||
|
while ((pos = message.find("%m", pos)) != std::string::npos) {
|
||||||
|
message.replace(pos, 2, petName);
|
||||||
|
pos += petName.length();
|
||||||
|
}
|
||||||
}
|
}
|
@ -401,6 +401,8 @@ public:
|
|||||||
void DeleteActiveSpell(LuaSpell* spell, bool skipRemoveCurrent = false);
|
void DeleteActiveSpell(LuaSpell* spell, bool skipRemoveCurrent = false);
|
||||||
static bool AddLuaSpellTarget(LuaSpell* lua_spell, int32 id, bool lock_spell_targets = true);
|
static bool AddLuaSpellTarget(LuaSpell* lua_spell, int32 id, bool lock_spell_targets = true);
|
||||||
mutable std::shared_mutex MSpellProcess;
|
mutable std::shared_mutex MSpellProcess;
|
||||||
|
|
||||||
|
static void ReplaceEffectTokens(std::string& message, Spawn* in_caster, Spawn* in_target);
|
||||||
private:
|
private:
|
||||||
MutexMap<Entity*,Spell*> spell_que;
|
MutexMap<Entity*,Spell*> spell_que;
|
||||||
MutexList<LuaSpell*> active_spells;
|
MutexList<LuaSpell*> active_spells;
|
||||||
|
@ -178,8 +178,8 @@ public:
|
|||||||
int16 minLevel, int16 maxLevel, int16 minVersion, int32 defaultLockoutTime, int32 defaultReenterTime, int8 instanceType, int32 numPlayers, bool isCityZone, void* zonePtr = nullptr);
|
int16 minLevel, int16 maxLevel, int16 minVersion, int32 defaultLockoutTime, int32 defaultReenterTime, int8 instanceType, int32 numPlayers, bool isCityZone, void* zonePtr = nullptr);
|
||||||
bool IsClientConnectedPeer(int32 account_id);
|
bool IsClientConnectedPeer(int32 account_id);
|
||||||
std::string GetCharacterPeerId(std::string charName);
|
std::string GetCharacterPeerId(std::string charName);
|
||||||
void SendPeersChannelMessage(int32 group_id, std::string fromName, std::string message, int16 channel, int32 language_id = 0);
|
void SendPeersChannelMessage(int32 group_id, std::string fromName, std::string message, int16 channel, int32 language_id = 0, int8 custom_type = 0);
|
||||||
void SendPeersGuildChannelMessage(int32 guild_id, std::string fromName, std::string message, int16 channel, int32 language_id = 0);
|
void SendPeersGuildChannelMessage(int32 guild_id, std::string fromName, std::string message, int16 channel, int32 language_id = 0, int8 custom_type = 0);
|
||||||
void sendZonePeerList(Client* client);
|
void sendZonePeerList(Client* client);
|
||||||
std::string getZonePeerId(const std::string& inc_zone_name, int32 inc_zone_id, int32 inc_instance_id, ZoneChangeDetails* opt_details = nullptr, bool only_always_loaded = false, int32 matchDuplicatedId = 0);
|
std::string getZonePeerId(const std::string& inc_zone_name, int32 inc_zone_id, int32 inc_instance_id, ZoneChangeDetails* opt_details = nullptr, bool only_always_loaded = false, int32 matchDuplicatedId = 0);
|
||||||
int32 getZoneHighestDuplicateId(const std::string& inc_zone_name, int32 inc_zone_id, bool increment_new_value = true);
|
int32 getZoneHighestDuplicateId(const std::string& inc_zone_name, int32 inc_zone_id, bool increment_new_value = true);
|
||||||
|
@ -273,6 +273,15 @@ void World::Web_worldhandle_reloadcommand(const http::request<http::string_body>
|
|||||||
world.RemoveReloadingSubSystem("ZoneScripts");
|
world.RemoveReloadingSubSystem("ZoneScripts");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case COMMAND_RELOAD_PLAYERSCRIPTS: {
|
||||||
|
world.SetReloadingSubsystem("PlayerScripts");
|
||||||
|
world.ResetPlayerScripts();
|
||||||
|
world.LoadPlayerScripts();
|
||||||
|
if (lua_interface)
|
||||||
|
lua_interface->DestroyPlayerScripts();
|
||||||
|
world.RemoveReloadingSubSystem("PlayerScripts");
|
||||||
|
break;
|
||||||
|
}
|
||||||
case COMMAND_RELOAD_FACTIONS: {
|
case COMMAND_RELOAD_FACTIONS: {
|
||||||
world.SetReloadingSubsystem("Factions");
|
world.SetReloadingSubsystem("Factions");
|
||||||
master_faction_list.Clear();
|
master_faction_list.Clear();
|
||||||
@ -368,6 +377,16 @@ void World::Web_worldhandle_reloadcommand(const http::request<http::string_body>
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case COMMAND_RELOAD_ITEMS: {
|
||||||
|
LogWrite(COMMAND__INFO, 0, "Command", "Reloading items..");
|
||||||
|
|
||||||
|
database.ReloadItemList(sub_command);
|
||||||
|
|
||||||
|
if(!item_id) {
|
||||||
|
database.LoadMerchantInformation(); // we skip if there is only a reload of single item not all items
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
success = 0;
|
success = 0;
|
||||||
break;
|
break;
|
||||||
@ -723,6 +742,7 @@ void World::Web_worldhandle_sendglobalmessage(const http::request<http::string_b
|
|||||||
std::string toName(""), fromName(""), msg("");
|
std::string toName(""), fromName(""), msg("");
|
||||||
int32 group_id = 0;
|
int32 group_id = 0;
|
||||||
int32 guild_id = 0;
|
int32 guild_id = 0;
|
||||||
|
int8 custom_type = 0;
|
||||||
if (auto name = json_tree.get_optional<std::string>("to_name")) {
|
if (auto name = json_tree.get_optional<std::string>("to_name")) {
|
||||||
toName = name.get();
|
toName = name.get();
|
||||||
}
|
}
|
||||||
@ -744,6 +764,9 @@ void World::Web_worldhandle_sendglobalmessage(const http::request<http::string_b
|
|||||||
if (auto guildID = json_tree.get_optional<int32>("guild_id")) {
|
if (auto guildID = json_tree.get_optional<int32>("guild_id")) {
|
||||||
guild_id = guildID.get();
|
guild_id = guildID.get();
|
||||||
}
|
}
|
||||||
|
if (auto customType = json_tree.get_optional<int8>("custom_type")) {
|
||||||
|
custom_type = customType.get();
|
||||||
|
}
|
||||||
|
|
||||||
Client* find_client = zone_list.GetClientByCharName(toName.c_str());
|
Client* find_client = zone_list.GetClientByCharName(toName.c_str());
|
||||||
if (find_client && find_client->GetPlayer()->IsIgnored(fromName.c_str()))
|
if (find_client && find_client->GetPlayer()->IsIgnored(fromName.c_str()))
|
||||||
@ -754,6 +777,7 @@ void World::Web_worldhandle_sendglobalmessage(const http::request<http::string_b
|
|||||||
if (find_client && find_client->GetPlayer()) {
|
if (find_client && find_client->GetPlayer()) {
|
||||||
success = 1;
|
success = 1;
|
||||||
toName = std::string(find_client->GetPlayer()->GetName());
|
toName = std::string(find_client->GetPlayer()->GetName());
|
||||||
|
find_client->SetLastTellName(fromName);
|
||||||
find_client->HandleTellMessage(fromName.c_str(), msg.c_str(), toName.c_str(), language);
|
find_client->HandleTellMessage(fromName.c_str(), msg.c_str(), toName.c_str(), language);
|
||||||
if (find_client->GetPlayer()->get_character_flag(CF_AFK)) {
|
if (find_client->GetPlayer()->get_character_flag(CF_AFK)) {
|
||||||
find_client->HandleTellMessage(toName.c_str(), find_client->GetPlayer()->GetAwayMessage().c_str(), fromName.c_str(), find_client->GetPlayer()->GetCurrentLanguage());
|
find_client->HandleTellMessage(toName.c_str(), find_client->GetPlayer()->GetAwayMessage().c_str(), fromName.c_str(), find_client->GetPlayer()->GetCurrentLanguage());
|
||||||
@ -819,6 +843,17 @@ void World::Web_worldhandle_sendglobalmessage(const http::request<http::string_b
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CHANNEL_BROADCAST: {
|
||||||
|
switch(custom_type) {
|
||||||
|
case 0:
|
||||||
|
zone_list.HandleGlobalBroadcast(msg.c_str());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
zone_list.HandleGlobalAnnouncement(msg.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -827,6 +862,7 @@ void World::Web_worldhandle_sendglobalmessage(const http::request<http::string_b
|
|||||||
pt.put("to_name", toName);
|
pt.put("to_name", toName);
|
||||||
pt.put("message", msg);
|
pt.put("message", msg);
|
||||||
pt.put("from_language", language);
|
pt.put("from_language", language);
|
||||||
|
pt.put("custom_type", custom_type);
|
||||||
pt.put("channel", in_channel);
|
pt.put("channel", in_channel);
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
boost::property_tree::write_json(oss, pt);
|
boost::property_tree::write_json(oss, pt);
|
||||||
|
@ -17,6 +17,12 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <vector>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "Items/Items.h"
|
#include "Items/Items.h"
|
||||||
@ -44,10 +50,10 @@
|
|||||||
#include "Chat/Chat.h"
|
#include "Chat/Chat.h"
|
||||||
#include "Tradeskills/Tradeskills.h"
|
#include "Tradeskills/Tradeskills.h"
|
||||||
#include "AltAdvancement/AltAdvancement.h"
|
#include "AltAdvancement/AltAdvancement.h"
|
||||||
#include "LuaInterface.h"
|
|
||||||
#include "HeroicOp/HeroicOp.h"
|
#include "HeroicOp/HeroicOp.h"
|
||||||
#include "RaceTypes/RaceTypes.h"
|
#include "RaceTypes/RaceTypes.h"
|
||||||
#include "LuaInterface.h"
|
#include "LuaInterface.h"
|
||||||
|
#include "SpellProcess.h"
|
||||||
#include "../common/version.h"
|
#include "../common/version.h"
|
||||||
|
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
@ -55,10 +61,6 @@
|
|||||||
#include "Web/PeerManager.h"
|
#include "Web/PeerManager.h"
|
||||||
#include "Web/HTTPSClientPool.h"
|
#include "Web/HTTPSClientPool.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
MasterQuestList master_quest_list;
|
MasterQuestList master_quest_list;
|
||||||
MasterItemList master_item_list;
|
MasterItemList master_item_list;
|
||||||
MasterSpellList master_spell_list;
|
MasterSpellList master_spell_list;
|
||||||
@ -90,7 +92,6 @@ map<int16, int16> EQOpcodeVersions;
|
|||||||
WorldDatabase database;
|
WorldDatabase database;
|
||||||
GuildList guild_list;
|
GuildList guild_list;
|
||||||
Chat chat;
|
Chat chat;
|
||||||
Player player;
|
|
||||||
|
|
||||||
extern ConfigReader configReader;
|
extern ConfigReader configReader;
|
||||||
extern LoginServer loginserver;
|
extern LoginServer loginserver;
|
||||||
@ -103,6 +104,8 @@ extern sint32 numclients;
|
|||||||
extern PeerManager peer_manager;
|
extern PeerManager peer_manager;
|
||||||
extern HTTPSClientPool peer_https_pool;
|
extern HTTPSClientPool peer_https_pool;
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
World::World() : save_time_timer(300000), time_tick_timer(3000), vitality_timer(3600000), player_stats_timer(60000), server_stats_timer(60000), /*remove_grouped_player(30000),*/ guilds_timer(60000), lotto_players_timer(500), watchdog_timer(10000) {
|
World::World() : save_time_timer(300000), time_tick_timer(3000), vitality_timer(3600000), player_stats_timer(60000), server_stats_timer(60000), /*remove_grouped_player(30000),*/ guilds_timer(60000), lotto_players_timer(500), watchdog_timer(10000) {
|
||||||
save_time_timer.Start();
|
save_time_timer.Start();
|
||||||
time_tick_timer.Start();
|
time_tick_timer.Start();
|
||||||
@ -195,7 +198,7 @@ void World::init(std::string web_ipaddr, int16 web_port, std::string cert_file,
|
|||||||
LoadVoiceOvers();
|
LoadVoiceOvers();
|
||||||
|
|
||||||
LogWrite(WORLD__DEBUG, 1, "World", "-Loading EXP Curve From DB...");
|
LogWrite(WORLD__DEBUG, 1, "World", "-Loading EXP Curve From DB...");
|
||||||
player.InitXPTable();
|
Player::InitXPTable();
|
||||||
LogWrite(WORLD__DEBUG, 1, "World", "-Loading EXP Curve From DB Complete!");
|
LogWrite(WORLD__DEBUG, 1, "World", "-Loading EXP Curve From DB Complete!");
|
||||||
|
|
||||||
LogWrite(WORLD__DEBUG, 1, "World", "-Setting system parameters...");
|
LogWrite(WORLD__DEBUG, 1, "World", "-Setting system parameters...");
|
||||||
@ -537,6 +540,9 @@ bool ZoneList::HandleGlobalChatMessage(Client* from, char* to, int16 channel, co
|
|||||||
LogWrite(WORLD__ERROR, 0, "World", "HandleGlobalChatMessage() called with an invalid client");
|
LogWrite(WORLD__ERROR, 0, "World", "HandleGlobalChatMessage() called with an invalid client");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string tokenedMsg = std::string(message);
|
||||||
|
SpellProcess::ReplaceEffectTokens(tokenedMsg, from->GetPlayer(), from->GetPlayer()->GetTarget());
|
||||||
if(channel == CHANNEL_PRIVATE_TELL){
|
if(channel == CHANNEL_PRIVATE_TELL){
|
||||||
Client* find_client = zone_list.GetClientByCharName(to);
|
Client* find_client = zone_list.GetClientByCharName(to);
|
||||||
if(find_client && find_client->GetPlayer()->IsIgnored(from->GetPlayer()->GetName()))
|
if(find_client && find_client->GetPlayer()->IsIgnored(from->GetPlayer()->GetName()))
|
||||||
@ -549,7 +555,7 @@ bool ZoneList::HandleGlobalChatMessage(Client* from, char* to, int16 channel, co
|
|||||||
boost::property_tree::ptree root;
|
boost::property_tree::ptree root;
|
||||||
root.put("from_name", from->GetPlayer()->GetName());
|
root.put("from_name", from->GetPlayer()->GetName());
|
||||||
root.put("to_name", to);
|
root.put("to_name", to);
|
||||||
root.put("message", message);
|
root.put("message", tokenedMsg.c_str());
|
||||||
root.put("from_language", current_language_id);
|
root.put("from_language", current_language_id);
|
||||||
root.put("channel", channel);
|
root.put("channel", channel);
|
||||||
std::ostringstream jsonStream;
|
std::ostringstream jsonStream;
|
||||||
@ -572,8 +578,9 @@ bool ZoneList::HandleGlobalChatMessage(Client* from, char* to, int16 channel, co
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char* whoto = find_client->GetPlayer()->GetName();
|
const char* whoto = find_client->GetPlayer()->GetName();
|
||||||
find_client->HandleTellMessage(from->GetPlayer()->GetName(), message, whoto, from->GetPlayer()->GetCurrentLanguage());
|
find_client->SetLastTellName(std::string(from->GetPlayer()->GetName()));
|
||||||
from->HandleTellMessage(from->GetPlayer()->GetName(), message, whoto, from->GetPlayer()->GetCurrentLanguage());
|
find_client->HandleTellMessage(from->GetPlayer()->GetName(), tokenedMsg.c_str(), whoto, from->GetPlayer()->GetCurrentLanguage());
|
||||||
|
from->HandleTellMessage(from->GetPlayer()->GetName(), tokenedMsg.c_str(), whoto, from->GetPlayer()->GetCurrentLanguage());
|
||||||
if (find_client->GetPlayer()->get_character_flag(CF_AFK)) {
|
if (find_client->GetPlayer()->get_character_flag(CF_AFK)) {
|
||||||
find_client->HandleTellMessage(find_client->GetPlayer()->GetName(), find_client->GetPlayer()->GetAwayMessage().c_str(),whoto, from->GetPlayer()->GetCurrentLanguage());
|
find_client->HandleTellMessage(find_client->GetPlayer()->GetName(), find_client->GetPlayer()->GetAwayMessage().c_str(),whoto, from->GetPlayer()->GetCurrentLanguage());
|
||||||
from->HandleTellMessage(find_client->GetPlayer()->GetName(), find_client->GetPlayer()->GetAwayMessage().c_str(),whoto, from->GetPlayer()->GetCurrentLanguage());
|
from->HandleTellMessage(find_client->GetPlayer()->GetName(), find_client->GetPlayer()->GetAwayMessage().c_str(),whoto, from->GetPlayer()->GetCurrentLanguage());
|
||||||
@ -641,6 +648,11 @@ void ZoneList::DeleteSpellProcess(){
|
|||||||
MZoneList.releasereadlock(__FUNCTION__, __LINE__);
|
MZoneList.releasereadlock(__FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZoneList::TransmitBroadcast(const char* message) {
|
||||||
|
HandleGlobalBroadcast(message);
|
||||||
|
peer_manager.SendPeersChannelMessage(0, "", std::string(message), CHANNEL_BROADCAST, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void ZoneList::HandleGlobalBroadcast(const char* message) {
|
void ZoneList::HandleGlobalBroadcast(const char* message) {
|
||||||
list<ZoneServer*>::iterator zone_iter;
|
list<ZoneServer*>::iterator zone_iter;
|
||||||
ZoneServer* zone = 0;
|
ZoneServer* zone = 0;
|
||||||
@ -653,6 +665,11 @@ void ZoneList::HandleGlobalBroadcast(const char* message) {
|
|||||||
MZoneList.releasereadlock(__FUNCTION__, __LINE__);
|
MZoneList.releasereadlock(__FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZoneList::TransmitGlobalAnnouncement(const char* message) {
|
||||||
|
HandleGlobalAnnouncement(message);
|
||||||
|
peer_manager.SendPeersChannelMessage(0, "", std::string(message), CHANNEL_BROADCAST, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void ZoneList::HandleGlobalAnnouncement(const char* message) {
|
void ZoneList::HandleGlobalAnnouncement(const char* message) {
|
||||||
list<ZoneServer*>::iterator zone_iter;
|
list<ZoneServer*>::iterator zone_iter;
|
||||||
ZoneServer* zone = 0;
|
ZoneServer* zone = 0;
|
||||||
@ -945,12 +962,13 @@ std::string PeerManager::GetCharacterPeerId(std::string charName) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerManager::SendPeersChannelMessage(int32 group_id, std::string fromName, std::string message, int16 channel, int32 language_id) {
|
void PeerManager::SendPeersChannelMessage(int32 group_id, std::string fromName, std::string message, int16 channel, int32 language_id, int8 custom_type) {
|
||||||
boost::property_tree::ptree root;
|
boost::property_tree::ptree root;
|
||||||
root.put("message", message);
|
root.put("message", message);
|
||||||
root.put("channel", channel);
|
root.put("channel", channel);
|
||||||
root.put("group_id", group_id);
|
root.put("group_id", group_id);
|
||||||
root.put("from_language", language_id);
|
root.put("from_language", language_id);
|
||||||
|
root.put("custom_type", custom_type);
|
||||||
root.put("from_name", fromName);
|
root.put("from_name", fromName);
|
||||||
std::ostringstream jsonStream;
|
std::ostringstream jsonStream;
|
||||||
boost::property_tree::write_json(jsonStream, root);
|
boost::property_tree::write_json(jsonStream, root);
|
||||||
@ -979,13 +997,14 @@ void PeerManager::SendPeersChannelMessage(int32 group_id, std::string fromName,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerManager::SendPeersGuildChannelMessage(int32 guild_id, std::string fromName, std::string message, int16 channel, int32 language_id) {
|
void PeerManager::SendPeersGuildChannelMessage(int32 guild_id, std::string fromName, std::string message, int16 channel, int32 language_id, int8 custom_type) {
|
||||||
boost::property_tree::ptree root;
|
boost::property_tree::ptree root;
|
||||||
root.put("message", message);
|
root.put("message", message);
|
||||||
root.put("channel", channel);
|
root.put("channel", channel);
|
||||||
root.put("guild_id", guild_id);
|
root.put("guild_id", guild_id);
|
||||||
root.put("from_language", language_id);
|
root.put("from_language", language_id);
|
||||||
root.put("from_name", fromName);
|
root.put("from_name", fromName);
|
||||||
|
root.put("custom_type", custom_type);
|
||||||
std::ostringstream jsonStream;
|
std::ostringstream jsonStream;
|
||||||
boost::property_tree::write_json(jsonStream, root);
|
boost::property_tree::write_json(jsonStream, root);
|
||||||
std::string jsonPayload = jsonStream.str();
|
std::string jsonPayload = jsonStream.str();
|
||||||
@ -1794,6 +1813,39 @@ void World::AddZoneScript(int32 id, const char* name) {
|
|||||||
MZoneScripts.unlock();
|
MZoneScripts.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::LoadPlayerScripts() {
|
||||||
|
const fs::path scriptDir = "PlayerScripts";
|
||||||
|
bool hasGlobalLua = false;
|
||||||
|
|
||||||
|
if (!fs::exists(scriptDir) || !fs::is_directory(scriptDir)) {
|
||||||
|
std::cerr << "Directory does not exist: " << scriptDir << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& entry : fs::directory_iterator(scriptDir)) {
|
||||||
|
if (entry.is_regular_file() && entry.path().extension() == ".lua") {
|
||||||
|
std::string baseName = entry.path().stem().string(); // Strips extension
|
||||||
|
const std::string filename = entry.path().string();
|
||||||
|
int32 zoneID = database.GetZoneID(filename.c_str());
|
||||||
|
std::cout << " - Load File " << filename << " with base name: " << baseName << "\n";
|
||||||
|
if(zoneID) {
|
||||||
|
AddPlayerScript(zoneID, filename.c_str());
|
||||||
|
}
|
||||||
|
else if (baseName == "global") {
|
||||||
|
AddPlayerScript(0, filename.c_str());
|
||||||
|
hasGlobalLua = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::AddPlayerScript(int32 zone_id, const char* zone_name) {
|
||||||
|
MPlayerScripts.lock();
|
||||||
|
if (zone_name)
|
||||||
|
player_scripts[zone_id] = string(zone_name);
|
||||||
|
MPlayerScripts.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
const char* World::GetSpawnScript(int32 id){
|
const char* World::GetSpawnScript(int32 id){
|
||||||
LogWrite(SPAWN__TRACE, 1, "Spawn", "Enter %s", __FUNCTION__);
|
LogWrite(SPAWN__TRACE, 1, "Spawn", "Enter %s", __FUNCTION__);
|
||||||
const char* ret = 0;
|
const char* ret = 0;
|
||||||
@ -1836,6 +1888,15 @@ const char* World::GetZoneScript(int32 id) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* World::GetPlayerScript(int32 zone_id) {
|
||||||
|
const char* ret = 0;
|
||||||
|
MPlayerScripts.lock();
|
||||||
|
if (player_scripts.count(zone_id) > 0)
|
||||||
|
ret = player_scripts[zone_id].c_str();
|
||||||
|
MPlayerScripts.unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void World::ResetSpawnScripts(){
|
void World::ResetSpawnScripts(){
|
||||||
MSpawnScripts.lock();
|
MSpawnScripts.lock();
|
||||||
spawn_scripts.clear();
|
spawn_scripts.clear();
|
||||||
@ -1850,7 +1911,11 @@ void World::ResetZoneScripts() {
|
|||||||
MZoneScripts.unlock();
|
MZoneScripts.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::ResetPlayerScripts() {
|
||||||
|
MPlayerScripts.lock();
|
||||||
|
player_scripts.clear();
|
||||||
|
MPlayerScripts.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
vector<MerchantItemInfo>* World::GetMerchantItemList(int32 merchant_id, int8 merchant_type, Player* player)
|
vector<MerchantItemInfo>* World::GetMerchantItemList(int32 merchant_id, int8 merchant_type, Player* player)
|
||||||
{
|
{
|
||||||
@ -2595,10 +2660,10 @@ void World::CheckLottoPlayers() {
|
|||||||
memset(announcement, 0, sizeof(announcement));
|
memset(announcement, 0, sizeof(announcement));
|
||||||
sprintf(coin_message, "%s", client->GetCoinMessage(jackpot).c_str());
|
sprintf(coin_message, "%s", client->GetCoinMessage(jackpot).c_str());
|
||||||
sprintf(message, "Congratulations! You have won %s!", coin_message);
|
sprintf(message, "Congratulations! You have won %s!", coin_message);
|
||||||
sprintf(announcement, "%s as won the jackpot containing a total of %s!", client->GetPlayer()->GetName(), coin_message);
|
sprintf(announcement, "%s has won the jackpot containing a total of %s!", client->GetPlayer()->GetName(), coin_message);
|
||||||
client->Message(CHANNEL_COLOR_YELLOW, "You receive %s.", coin_message);
|
client->Message(CHANNEL_COLOR_YELLOW, "You receive %s.", coin_message);
|
||||||
client->SendPopupMessage(0, message, "", 2, 0xFF, 0xFF, 0x99);
|
client->SendPopupMessage(0, message, "", 2, 0xFF, 0xFF, 0x99);
|
||||||
zone_list.HandleGlobalAnnouncement(announcement);
|
zone_list.TransmitGlobalAnnouncement(announcement);
|
||||||
client->GetPlayer()->AddCoins(jackpot);
|
client->GetPlayer()->AddCoins(jackpot);
|
||||||
client->GetPlayer()->GetZone()->SendCastSpellPacket(843, client->GetPlayer());
|
client->GetPlayer()->GetZone()->SendCastSpellPacket(843, client->GetPlayer());
|
||||||
client->GetPlayer()->GetZone()->SendCastSpellPacket(1413, client->GetPlayer());
|
client->GetPlayer()->GetZone()->SendCastSpellPacket(1413, client->GetPlayer());
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
EQ2Emulator: Everquest II Server Emulator
|
EQ2Emulator: Everquest II Server Emulator
|
||||||
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
|
Copyright (C) 2005 - 2025 EQ2EMulator Development Team (http://www.eq2emu.com formerly http://www.eq2emulator.net)
|
||||||
|
|
||||||
This file is part of EQ2Emulator.
|
This file is part of EQ2Emulator.
|
||||||
|
|
||||||
@ -17,6 +17,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQ2_WORLD_H
|
#ifndef EQ2_WORLD_H
|
||||||
#define EQ2_WORLD_H
|
#define EQ2_WORLD_H
|
||||||
|
|
||||||
@ -476,6 +477,10 @@ class ZoneList {
|
|||||||
void CheckFriendZoned(Client* client);
|
void CheckFriendZoned(Client* client);
|
||||||
|
|
||||||
// move to Chat/Chat.h?
|
// move to Chat/Chat.h?
|
||||||
|
void TransmitBroadcast(const char* message);
|
||||||
|
void TransmitGlobalAnnouncement(const char* message);
|
||||||
|
|
||||||
|
// these are handled internally by the transmit and peering
|
||||||
bool HandleGlobalChatMessage(Client* from, char* to, int16 channel, const char* message, const char* channel_name = 0, int32 current_language_id = 0);
|
bool HandleGlobalChatMessage(Client* from, char* to, int16 channel, const char* message, const char* channel_name = 0, int32 current_language_id = 0);
|
||||||
void HandleGlobalBroadcast(const char* message);
|
void HandleGlobalBroadcast(const char* message);
|
||||||
void HandleGlobalAnnouncement(const char* message);
|
void HandleGlobalAnnouncement(const char* message);
|
||||||
@ -589,12 +594,16 @@ public:
|
|||||||
void AddSpawnEntryScript(int32 id, const char* name);
|
void AddSpawnEntryScript(int32 id, const char* name);
|
||||||
void AddSpawnLocationScript(int32 id, const char* name);
|
void AddSpawnLocationScript(int32 id, const char* name);
|
||||||
void AddZoneScript(int32 id, const char* name);
|
void AddZoneScript(int32 id, const char* name);
|
||||||
|
void LoadPlayerScripts();
|
||||||
|
void AddPlayerScript(int32 zone_id, const char* zone_name);
|
||||||
const char* GetSpawnScript(int32 id);
|
const char* GetSpawnScript(int32 id);
|
||||||
const char* GetSpawnEntryScript(int32 id);
|
const char* GetSpawnEntryScript(int32 id);
|
||||||
const char* GetSpawnLocationScript(int32 id);
|
const char* GetSpawnLocationScript(int32 id);
|
||||||
const char* GetZoneScript(int32 id);
|
const char* GetZoneScript(int32 id);
|
||||||
|
const char* GetPlayerScript(int32 zone_id);
|
||||||
void ResetSpawnScripts();
|
void ResetSpawnScripts();
|
||||||
void ResetZoneScripts();
|
void ResetZoneScripts();
|
||||||
|
void ResetPlayerScripts();
|
||||||
int16 GetMerchantItemQuantity(int32 merchant_id, int32 item_id);
|
int16 GetMerchantItemQuantity(int32 merchant_id, int32 item_id);
|
||||||
void DecreaseMerchantQuantity(int32 merchant_id, int32 item_id, int16 amount);
|
void DecreaseMerchantQuantity(int32 merchant_id, int32 item_id, int16 amount);
|
||||||
int32 GetInventoryID(int32 merchant_id, int32 item_id);
|
int32 GetInventoryID(int32 merchant_id, int32 item_id);
|
||||||
@ -765,6 +774,7 @@ private:
|
|||||||
Mutex MMerchantList;
|
Mutex MMerchantList;
|
||||||
Mutex MSpawnScripts;
|
Mutex MSpawnScripts;
|
||||||
Mutex MZoneScripts;
|
Mutex MZoneScripts;
|
||||||
|
Mutex MPlayerScripts;
|
||||||
//Mutex MGroups;
|
//Mutex MGroups;
|
||||||
|
|
||||||
mutable std::shared_mutex MNPCSpells;
|
mutable std::shared_mutex MNPCSpells;
|
||||||
@ -783,6 +793,7 @@ private:
|
|||||||
map<int32, string> spawnentry_scripts;
|
map<int32, string> spawnentry_scripts;
|
||||||
map<int32, string> spawnlocation_scripts;
|
map<int32, string> spawnlocation_scripts;
|
||||||
map<int32, string> zone_scripts;
|
map<int32, string> zone_scripts;
|
||||||
|
map<int32, string> player_scripts;
|
||||||
//vector<PlayerGroup*> player_groups;
|
//vector<PlayerGroup*> player_groups;
|
||||||
//map<GroupMemberInfo*, int32> group_removal_pending;
|
//map<GroupMemberInfo*, int32> group_removal_pending;
|
||||||
//map<string, string> pending_groups;
|
//map<string, string> pending_groups;
|
||||||
|
@ -3251,8 +3251,9 @@ string WorldDatabase::GetExpansionIDByVersion(int16 version)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WorldDatabase::LoadSpecialZones(){
|
void WorldDatabase::LoadSpecialZones(bool silent){
|
||||||
LogWrite(ZONE__INFO, 0, "Zone", "Starting static zones...");
|
if(!silent)
|
||||||
|
LogWrite(ZONE__INFO, 0, "Zone", "Starting static zones...");
|
||||||
Query query;
|
Query query;
|
||||||
ZoneServer* zone = 0;
|
ZoneServer* zone = 0;
|
||||||
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT id, name, always_loaded, peer_priority FROM zones where always_loaded = 1");
|
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT id, name, always_loaded, peer_priority FROM zones where always_loaded = 1");
|
||||||
@ -5589,6 +5590,7 @@ string WorldDatabase::GetMerchantDescription(int32 merchant_id) {
|
|||||||
|
|
||||||
void WorldDatabase::LoadTransporters(ZoneServer* zone){
|
void WorldDatabase::LoadTransporters(ZoneServer* zone){
|
||||||
int32 total = 0;
|
int32 total = 0;
|
||||||
|
zone->DeleteTransporters();
|
||||||
zone->DeleteGlobalTransporters();
|
zone->DeleteGlobalTransporters();
|
||||||
Query query;
|
Query query;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
|
@ -208,7 +208,7 @@ public:
|
|||||||
int32 SaveCharacter(PacketStruct* create, int32 loginID);
|
int32 SaveCharacter(PacketStruct* create, int32 loginID);
|
||||||
int32 LoadNPCAppearanceEquipmentData(ZoneServer* zone);
|
int32 LoadNPCAppearanceEquipmentData(ZoneServer* zone);
|
||||||
void SaveNPCAppearanceEquipment(int32 spawn_id, int8 slot_id, int16 type, int8 red=0, int8 green=0, int8 blue=0, int8 hred=0, int8 hgreen=0, int8 hblue=0);
|
void SaveNPCAppearanceEquipment(int32 spawn_id, int8 slot_id, int16 type, int8 red=0, int8 green=0, int8 blue=0, int8 hred=0, int8 hgreen=0, int8 hblue=0);
|
||||||
void LoadSpecialZones();
|
void LoadSpecialZones(bool silent=false);
|
||||||
void SaveCharacterSkills(Client* client);
|
void SaveCharacterSkills(Client* client);
|
||||||
void SaveCharacterQuests(Client* client);
|
void SaveCharacterQuests(Client* client);
|
||||||
void SaveCharacterQuestProgress(Client* client, Quest* quest);
|
void SaveCharacterQuestProgress(Client* client, Quest* quest);
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
EQ2Emulator: Everquest II Server Emulator
|
EQ2Emulator: Everquest II Server Emulator
|
||||||
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
|
Copyright (C) 2005 - 2025 EQ2EMulator Development Team (http://www.eq2emu.com formerly http://www.eq2emulator.net)
|
||||||
|
|
||||||
This file is part of EQ2Emulator.
|
This file is part of EQ2Emulator.
|
||||||
|
|
||||||
EQ2Emulator is free software: you can redistribute it and/or modify
|
EQ2Emulator is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
EQ2Emulator is distributed in the hope that it will be useful,
|
EQ2Emulator is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../common/debug.h"
|
#include "../common/debug.h"
|
||||||
#include "../common/Log.h"
|
#include "../common/Log.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -136,7 +137,7 @@ Client::Client(EQStream* ieqs) : underworld_cooldown_timer(5000), pos_update(125
|
|||||||
eqs = ieqs;
|
eqs = ieqs;
|
||||||
ip = eqs->GetrIP();
|
ip = eqs->GetrIP();
|
||||||
port = ntohs(eqs->GetrPort());
|
port = ntohs(eqs->GetrPort());
|
||||||
merchant_transaction = nullptr;
|
merchant_transaction_id = 0;
|
||||||
mail_window.item = nullptr; // don't want this to be set(loose ptr) when using ResetSendMail to provide rest of the defaults
|
mail_window.item = nullptr; // don't want this to be set(loose ptr) when using ResetSendMail to provide rest of the defaults
|
||||||
ResetSendMail(false);
|
ResetSendMail(false);
|
||||||
timestamp_flag = 0;
|
timestamp_flag = 0;
|
||||||
@ -190,7 +191,7 @@ Client::Client(EQStream* ieqs) : underworld_cooldown_timer(5000), pos_update(125
|
|||||||
dead_z = 0.0f;
|
dead_z = 0.0f;
|
||||||
dead_h = 0.0f;
|
dead_h = 0.0f;
|
||||||
lua_debug_timer.Disable();
|
lua_debug_timer.Disable();
|
||||||
transport_spawn = 0;
|
transport_spawn_id = 0;
|
||||||
MBuyBack.SetName("Client::MBuyBack");
|
MBuyBack.SetName("Client::MBuyBack");
|
||||||
MDeletePlayer.SetName("Client::MDeletePlayer");
|
MDeletePlayer.SetName("Client::MDeletePlayer");
|
||||||
MQuestPendingUpdates.SetName("Client::MQuestPendingUpdates");
|
MQuestPendingUpdates.SetName("Client::MQuestPendingUpdates");
|
||||||
@ -5428,12 +5429,29 @@ void Client::SendPopupMessage(int8 unknown, const char* text, const char* type,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ChangeLevel(int16 old_level, int16 new_level) {
|
bool Client::ChangeLevel(int16 old_level, int16 new_level, int32 xp_earned) {
|
||||||
if (new_level < 1) {
|
if (new_level < 1) {
|
||||||
SimpleMessage(CHANNEL_COLOR_RED, "You cannot be lower than level 1!");
|
SimpleMessage(CHANNEL_COLOR_RED, "You cannot be lower than level 1!");
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
const char* playerScript = world.GetPlayerScript(0); // 0 = global script
|
||||||
|
const char* playerZoneScript = world.GetPlayerScript(GetCurrentZoneID()); // zone script
|
||||||
|
sint32 returnValue = 0;
|
||||||
|
if(playerScript || playerZoneScript) {
|
||||||
|
std::vector<LuaArg> args = {
|
||||||
|
LuaArg(GetPlayer()->GetZone()),
|
||||||
|
LuaArg(GetPlayer()),
|
||||||
|
LuaArg(old_level),
|
||||||
|
LuaArg(new_level),
|
||||||
|
LuaArg(xp_earned)
|
||||||
|
};
|
||||||
|
if(playerScript && lua_interface->RunPlayerScriptWithReturn(playerScript, "on_level_up", args, &returnValue) && returnValue == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(playerZoneScript && lua_interface->RunPlayerScriptWithReturn(playerZoneScript, "on_level_up", args, &returnValue) && returnValue == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->GetLevel() != new_level) {
|
if (player->GetLevel() != new_level) {
|
||||||
player->SetLevel(new_level);
|
player->SetLevel(new_level);
|
||||||
if (player->GetGroupMemberInfo()) {
|
if (player->GetGroupMemberInfo()) {
|
||||||
@ -5625,17 +5643,38 @@ void Client::ChangeLevel(int16 old_level, int16 new_level) {
|
|||||||
|
|
||||||
if (GetPlayer()->GetHP() < GetPlayer()->GetTotalHP() || GetPlayer()->GetPower() < GetPlayer()->GetTotalPower())
|
if (GetPlayer()->GetHP() < GetPlayer()->GetTotalHP() || GetPlayer()->GetPower() < GetPlayer()->GetTotalPower())
|
||||||
GetPlayer()->GetZone()->AddDamagedSpawn(GetPlayer());
|
GetPlayer()->GetZone()->AddDamagedSpawn(GetPlayer());
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ChangeTSLevel(int16 old_level, int16 new_level) {
|
bool Client::ChangeTSLevel(int16 old_level, int16 new_level, int32 xp_earned) {
|
||||||
if (new_level < 1) {
|
if (new_level < 1) {
|
||||||
SimpleMessage(CHANNEL_COLOR_RED, "You cannot be lower than level 1!");
|
SimpleMessage(CHANNEL_COLOR_RED, "You cannot be lower than level 1!");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if ((player->GetTSLevel() >= 9 && player->GetTradeskillClass() == 1) || (player->GetTSLevel() >= 19 && (player->GetTradeskillClass() == 1 || player->GetTradeskillClass() == 2 || player->GetTradeskillClass() == 6 || player->GetTradeskillClass() == 10))) {
|
if ((player->GetTSLevel() >= 9 && player->GetTradeskillClass() == 1) || (player->GetTSLevel() >= 19 && (player->GetTradeskillClass() == 1 || player->GetTradeskillClass() == 2 || player->GetTradeskillClass() == 6 || player->GetTradeskillClass() == 10))) {
|
||||||
SimpleMessage(CHANNEL_COLOR_YELLOW, "You can not gain levels until you select your next class!");
|
SimpleMessage(CHANNEL_COLOR_YELLOW, "You can not gain levels until you select your next class!");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
const char* playerScript = world.GetPlayerScript(0); // 0 = global script
|
||||||
|
const char* playerZoneScript = world.GetPlayerScript(GetCurrentZoneID()); // zone script
|
||||||
|
sint32 returnValue = 0;
|
||||||
|
if(playerScript || playerZoneScript) {
|
||||||
|
std::vector<LuaArg> args = {
|
||||||
|
LuaArg(GetPlayer()->GetZone()),
|
||||||
|
LuaArg(GetPlayer()),
|
||||||
|
LuaArg(old_level),
|
||||||
|
LuaArg(new_level),
|
||||||
|
LuaArg(xp_earned)
|
||||||
|
};
|
||||||
|
if(playerScript && lua_interface->RunPlayerScriptWithReturn(playerScript, "on_tradeskill_level_up", args, &returnValue) && returnValue == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(playerZoneScript && lua_interface->RunPlayerScriptWithReturn(playerZoneScript, "on_tradeskill_level_up", args, &returnValue) && returnValue == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (new_level > old_level)
|
if (new_level > old_level)
|
||||||
player->UpdatePlayerHistory(HISTORY_TYPE_XP, HISTORY_SUBTYPE_TRADESKILL, new_level, player->GetTradeskillClass());
|
player->UpdatePlayerHistory(HISTORY_TYPE_XP, HISTORY_SUBTYPE_TRADESKILL, new_level, player->GetTradeskillClass());
|
||||||
@ -5820,6 +5859,7 @@ void Client::ChangeTSLevel(int16 old_level, int16 new_level) {
|
|||||||
// to when you are actually able to select traits.
|
// to when you are actually able to select traits.
|
||||||
QueuePacket(GetPlayer()->GetPlayerInfo()->serialize(GetVersion()));
|
QueuePacket(GetPlayer()->GetPlayerInfo()->serialize(GetVersion()));
|
||||||
QueuePacket(master_trait_list.GetTraitListPacket(this));
|
QueuePacket(master_trait_list.GetTraitListPacket(this));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::CloseLoot(int32 spawn_id) {
|
void Client::CloseLoot(int32 spawn_id) {
|
||||||
@ -6381,19 +6421,18 @@ void Client::CastGroupOrSelf(Entity* source, uint32 spellID, uint32 spellTier, f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spawn* Client::GetBanker() {
|
int32 Client::GetBanker() {
|
||||||
return banker;
|
return banker_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SetBanker(Spawn* in_banker) {
|
void Client::SetBanker(int32 in_banker) {
|
||||||
banker = in_banker;
|
banker_id = in_banker;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::Bank(Spawn* banker, bool cancel) {
|
void Client::Bank(Spawn* banker, bool cancel) {
|
||||||
if (banker && banker->primary_command_list.size() > 0 && banker->primary_command_list[0]->command == "bank") {
|
if (banker && banker->primary_command_list.size() > 0 && banker->primary_command_list[0]->command == "bank") {
|
||||||
if (!cancel)
|
if (!cancel)
|
||||||
SetBanker(banker);
|
SetBanker(banker->GetID());
|
||||||
else
|
else
|
||||||
SetBanker(0);
|
SetBanker(0);
|
||||||
PacketStruct* packet = configReader.getStruct("WS_UpdateBank", GetVersion());
|
PacketStruct* packet = configReader.getStruct("WS_UpdateBank", GetVersion());
|
||||||
@ -6550,7 +6589,8 @@ bool Client::BankWithdrawalNoBanker(int64 amount) {
|
|||||||
|
|
||||||
void Client::BankWithdrawal(int64 amount) {
|
void Client::BankWithdrawal(int64 amount) {
|
||||||
bool cheater = false;
|
bool cheater = false;
|
||||||
if (GetBanker() && amount > 0) {
|
Spawn* banker = GetCurrentZone()->GetSpawnByID(GetBanker());
|
||||||
|
if (banker && amount > 0) {
|
||||||
string withdrawal = "";
|
string withdrawal = "";
|
||||||
char withdrawal_data[512] = { 0 };
|
char withdrawal_data[512] = { 0 };
|
||||||
int32 tmp = 0;
|
int32 tmp = 0;
|
||||||
@ -6638,7 +6678,8 @@ void Client::BankWithdrawal(int64 amount) {
|
|||||||
|
|
||||||
void Client::BankDeposit(int64 amount) {
|
void Client::BankDeposit(int64 amount) {
|
||||||
bool cheater = false;
|
bool cheater = false;
|
||||||
if (GetBanker() && amount > 0) {
|
Spawn* banker = GetCurrentZone()->GetSpawnByID(GetBanker());
|
||||||
|
if (banker && amount > 0) {
|
||||||
int32 tmp = 0;
|
int32 tmp = 0;
|
||||||
char deposit_data[512] = { 0 };
|
char deposit_data[512] = { 0 };
|
||||||
string deposit = "";
|
string deposit = "";
|
||||||
@ -8129,12 +8170,17 @@ void Client::SetLuaDebugClient(bool val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::SetMerchantTransaction(Spawn* spawn) {
|
void Client::SetMerchantTransaction(Spawn* spawn) {
|
||||||
merchant_transaction = spawn;
|
if(spawn) {
|
||||||
|
merchant_transaction_id = spawn->GetID();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
merchant_transaction_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spawn* Client::GetMerchantTransaction() {
|
int32 Client::GetMerchantTransactionID() {
|
||||||
return merchant_transaction;
|
return merchant_transaction_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SetMailTransaction(Spawn* spawn) {
|
void Client::SetMailTransaction(Spawn* spawn) {
|
||||||
@ -8199,7 +8245,7 @@ float Client::CalculateSellMultiplier(int32 merchant_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::SellItem(int32 item_id, int16 quantity, int32 unique_id) {
|
void Client::SellItem(int32 item_id, int16 quantity, int32 unique_id) {
|
||||||
Spawn* spawn = GetMerchantTransaction();
|
Spawn* spawn = GetCurrentZone()->GetSpawnByID(GetMerchantTransactionID());
|
||||||
Guild* guild = GetPlayer()->GetGuild();
|
Guild* guild = GetPlayer()->GetGuild();
|
||||||
if (spawn && spawn->GetMerchantID() > 0 && (!(spawn->GetMerchantType() & MERCHANT_TYPE_NO_BUY)) &&
|
if (spawn && spawn->GetMerchantID() > 0 && (!(spawn->GetMerchantType() & MERCHANT_TYPE_NO_BUY)) &&
|
||||||
spawn->IsClientInMerchantLevelRange(this)) {
|
spawn->IsClientInMerchantLevelRange(this)) {
|
||||||
@ -8317,7 +8363,7 @@ void Client::SellItem(int32 item_id, int16 quantity, int32 unique_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::BuyBack(int32 item_id, int16 quantity) {
|
void Client::BuyBack(int32 item_id, int16 quantity) {
|
||||||
Spawn* spawn = GetMerchantTransaction();
|
Spawn* spawn = GetCurrentZone()->GetSpawnByID(GetMerchantTransactionID());
|
||||||
if (spawn && spawn->GetMerchantID() > 0 && (!(spawn->GetMerchantType() & MERCHANT_TYPE_NO_BUY_BACK)) &&
|
if (spawn && spawn->GetMerchantID() > 0 && (!(spawn->GetMerchantType() & MERCHANT_TYPE_NO_BUY_BACK)) &&
|
||||||
spawn->IsClientInMerchantLevelRange(this)) {
|
spawn->IsClientInMerchantLevelRange(this)) {
|
||||||
deque<BuyBackItem*>::iterator itr;
|
deque<BuyBackItem*>::iterator itr;
|
||||||
@ -8391,7 +8437,7 @@ void Client::BuyBack(int32 item_id, int16 quantity) {
|
|||||||
|
|
||||||
void Client::BuyItem(int32 item_id, int16 quantity) {
|
void Client::BuyItem(int32 item_id, int16 quantity) {
|
||||||
// Get the merchant we are buying from
|
// Get the merchant we are buying from
|
||||||
Spawn* spawn = GetMerchantTransaction();
|
Spawn* spawn = GetCurrentZone()->GetSpawnByID(GetMerchantTransactionID());
|
||||||
// Make sure the spawn has a merchant list
|
// Make sure the spawn has a merchant list
|
||||||
if (spawn && spawn->GetMerchantID() > 0 && spawn->IsClientInMerchantLevelRange(this)) {
|
if (spawn && spawn->GetMerchantID() > 0 && spawn->IsClientInMerchantLevelRange(this)) {
|
||||||
int32 total_buy_price = 0;
|
int32 total_buy_price = 0;
|
||||||
@ -8585,7 +8631,7 @@ void Client::BuyItem(int32 item_id, int16 quantity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::RepairItem(int32 item_id) {
|
void Client::RepairItem(int32 item_id) {
|
||||||
Spawn* spawn = GetMerchantTransaction();
|
Spawn* spawn = GetCurrentZone()->GetSpawnByID(GetMerchantTransactionID());
|
||||||
if (spawn && (spawn->GetMerchantType() & MERCHANT_TYPE_REPAIR)) {
|
if (spawn && (spawn->GetMerchantType() & MERCHANT_TYPE_REPAIR)) {
|
||||||
Item* item = player->item_list.GetItemFromID(item_id);
|
Item* item = player->item_list.GetItemFromID(item_id);
|
||||||
if (!item)
|
if (!item)
|
||||||
@ -8623,7 +8669,7 @@ void Client::RepairItem(int32 item_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::RepairAllItems() {
|
void Client::RepairAllItems() {
|
||||||
Spawn* spawn = GetMerchantTransaction();
|
Spawn* spawn = GetCurrentZone()->GetSpawnByID(GetMerchantTransactionID());
|
||||||
if (spawn && (spawn->GetMerchantType() & MERCHANT_TYPE_REPAIR)) {
|
if (spawn && (spawn->GetMerchantType() & MERCHANT_TYPE_REPAIR)) {
|
||||||
vector<Item*>* repairable_items = GetRepairableItems();
|
vector<Item*>* repairable_items = GetRepairableItems();
|
||||||
if (repairable_items && repairable_items->size() > 0) {
|
if (repairable_items && repairable_items->size() > 0) {
|
||||||
@ -8771,7 +8817,7 @@ void Client::SendAchievementUpdate(bool first_login) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::SendBuyMerchantList(bool sell) {
|
void Client::SendBuyMerchantList(bool sell) {
|
||||||
Spawn* spawn = GetMerchantTransaction();
|
Spawn* spawn = GetCurrentZone()->GetSpawnByID(GetMerchantTransactionID());
|
||||||
if (spawn && spawn->GetMerchantID() > 0 && spawn->IsClientInMerchantLevelRange(this)) {
|
if (spawn && spawn->GetMerchantID() > 0 && spawn->IsClientInMerchantLevelRange(this)) {
|
||||||
vector<MerchantItemInfo>* items = world.GetMerchantItemList(spawn->GetMerchantID(), spawn->GetMerchantType(), player);
|
vector<MerchantItemInfo>* items = world.GetMerchantItemList(spawn->GetMerchantID(), spawn->GetMerchantType(), player);
|
||||||
if (items) {
|
if (items) {
|
||||||
@ -8918,7 +8964,7 @@ void Client::SendBuyMerchantList(bool sell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::SendSellMerchantList(bool sell) {
|
void Client::SendSellMerchantList(bool sell) {
|
||||||
Spawn* spawn = GetMerchantTransaction();
|
Spawn* spawn = GetCurrentZone()->GetSpawnByID(GetMerchantTransactionID());
|
||||||
if (!spawn || (spawn->GetMerchantType() & MERCHANT_TYPE_NO_BUY) || (spawn->GetMerchantType() & MERCHANT_TYPE_LOTTO))
|
if (!spawn || (spawn->GetMerchantType() & MERCHANT_TYPE_NO_BUY) || (spawn->GetMerchantType() & MERCHANT_TYPE_LOTTO))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -9054,7 +9100,7 @@ void Client::SendSellMerchantList(bool sell) {
|
|||||||
void Client::SendBuyBackList(bool sell) {
|
void Client::SendBuyBackList(bool sell) {
|
||||||
if (GetVersion() <= 561) //this wasn't added until LU37 on July 31st 2007, well after the DoF client
|
if (GetVersion() <= 561) //this wasn't added until LU37 on July 31st 2007, well after the DoF client
|
||||||
return;
|
return;
|
||||||
Spawn* spawn = GetMerchantTransaction();
|
Spawn* spawn = GetCurrentZone()->GetSpawnByID(GetMerchantTransactionID());
|
||||||
if (spawn && spawn->GetMerchantID() > 0 && spawn->IsClientInMerchantLevelRange(this)) {
|
if (spawn && spawn->GetMerchantID() > 0 && spawn->IsClientInMerchantLevelRange(this)) {
|
||||||
deque<BuyBackItem*>::iterator itr;
|
deque<BuyBackItem*>::iterator itr;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -9127,7 +9173,7 @@ void Client::SendBuyBackList(bool sell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::SendRepairList() {
|
void Client::SendRepairList() {
|
||||||
Spawn* spawn = GetMerchantTransaction();
|
Spawn* spawn = GetCurrentZone()->GetSpawnByID(GetMerchantTransactionID());
|
||||||
if (spawn) {
|
if (spawn) {
|
||||||
vector<Item*>* repairable_items = GetRepairableItems();
|
vector<Item*>* repairable_items = GetRepairableItems();
|
||||||
PacketStruct* packet = configReader.getStruct("WS_UpdateMerchant", GetVersion());
|
PacketStruct* packet = configReader.getStruct("WS_UpdateMerchant", GetVersion());
|
||||||
@ -9202,7 +9248,7 @@ void Client::ShowLottoWindow() {
|
|||||||
SimpleMessage(CHANNEL_COLOR_RED, "This client does not support the gambler UI, only Desert of Flames or later client.");
|
SimpleMessage(CHANNEL_COLOR_RED, "This client does not support the gambler UI, only Desert of Flames or later client.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Spawn* spawn = GetMerchantTransaction();
|
Spawn* spawn = GetCurrentZone()->GetSpawnByID(GetMerchantTransactionID());
|
||||||
if (spawn) {
|
if (spawn) {
|
||||||
|
|
||||||
int32 item_id = rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, GamblingTokenItemID)->GetInt32();
|
int32 item_id = rule_manager.GetZoneRule(GetCurrentZoneID(), R_World, GamblingTokenItemID)->GetInt32();
|
||||||
@ -9554,6 +9600,25 @@ void Client::DisplayMailMessage(int32 mail_id) {
|
|||||||
safe_delete(update);
|
safe_delete(update);
|
||||||
}
|
}
|
||||||
if (!mail->already_read) {
|
if (!mail->already_read) {
|
||||||
|
const char* playerScript = world.GetPlayerScript(0); // 0 = global script
|
||||||
|
const char* playerZoneScript = world.GetPlayerScript(GetCurrentZoneID()); // zone script
|
||||||
|
if(playerScript || playerZoneScript) {
|
||||||
|
std::vector<LuaArg> args = {
|
||||||
|
LuaArg(GetCurrentZone()),
|
||||||
|
LuaArg(GetPlayer()),
|
||||||
|
LuaArg(GetMailTransaction()),
|
||||||
|
LuaArg(mail->player_from),
|
||||||
|
LuaArg(mail->subject),
|
||||||
|
LuaArg(mail->mail_body),
|
||||||
|
LuaArg(mail->char_item_id)
|
||||||
|
};
|
||||||
|
if(playerScript) {
|
||||||
|
lua_interface->RunPlayerScriptWithReturn(playerScript, "on_mail_first_read", args);
|
||||||
|
}
|
||||||
|
if(playerZoneScript) {
|
||||||
|
lua_interface->RunPlayerScriptWithReturn(playerZoneScript, "on_mail_first_read", args);
|
||||||
|
}
|
||||||
|
}
|
||||||
mail->already_read = true;
|
mail->already_read = true;
|
||||||
SendMailList();
|
SendMailList();
|
||||||
}
|
}
|
||||||
@ -9577,13 +9642,15 @@ void Client::DisplayMailMessage(int32 mail_id) {
|
|||||||
if (mail->stack || mail->char_item_id)
|
if (mail->stack || mail->char_item_id)
|
||||||
{
|
{
|
||||||
Item* item = master_item_list.GetItem(mail->char_item_id);
|
Item* item = master_item_list.GetItem(mail->char_item_id);
|
||||||
item->stack_count = mail->stack > 1 ? mail->stack : 0;
|
if(item) {
|
||||||
if (version < 860)
|
item->stack_count = mail->stack > 1 ? mail->stack : 0;
|
||||||
packet->setItemByName("item", item, player, 0, version <= 373 ? -2 : -1);
|
if (version < 860)
|
||||||
else if (version < 1193)
|
packet->setItemByName("item", item, player, 0, version <= 373 ? -2 : -1);
|
||||||
packet->setItemByName("item", item, player, 0, 0);
|
else if (version < 1193)
|
||||||
else
|
packet->setItemByName("item", item, player, 0, 0);
|
||||||
packet->setItemByName("item", item, player, 0, 2);
|
else
|
||||||
|
packet->setItemByName("item", item, player, 0, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -10033,7 +10100,7 @@ void Client::ProcessTeleport(Spawn* spawn, vector<TransportDestination*>* destin
|
|||||||
if (transport_id > 0)
|
if (transport_id > 0)
|
||||||
has_map = GetCurrentZone()->TransportHasMap(transport_id);
|
has_map = GetCurrentZone()->TransportHasMap(transport_id);
|
||||||
|
|
||||||
transport_spawn = spawn;
|
transport_spawn_id = spawn->GetID();
|
||||||
vector<TransportDestination*> transport_list;
|
vector<TransportDestination*> transport_list;
|
||||||
vector<TransportDestination*>::iterator itr;
|
vector<TransportDestination*>::iterator itr;
|
||||||
TransportDestination* destination = 0;
|
TransportDestination* destination = 0;
|
||||||
@ -10190,7 +10257,7 @@ void Client::ProcessTeleportLocation(EQApplicationPacket* app) {
|
|||||||
zone_name = zone_name.substr(0, lastSpacePos);
|
zone_name = zone_name.substr(0, lastSpacePos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this->GetTemporaryTransportID() || (spawn && spawn == transport_spawn && spawn->GetTransporterID()))
|
if (this->GetTemporaryTransportID() || (spawn && spawn->GetID() == transport_spawn_id && spawn->GetTransporterID()))
|
||||||
GetCurrentZone()->GetTransporters(&destinations, this, this->GetTemporaryTransportID() ? this->GetTemporaryTransportID() : spawn->GetTransporterID());
|
GetCurrentZone()->GetTransporters(&destinations, this, this->GetTemporaryTransportID() ? this->GetTemporaryTransportID() : spawn->GetTransporterID());
|
||||||
vector<TransportDestination*>::iterator itr;
|
vector<TransportDestination*>::iterator itr;
|
||||||
for (itr = destinations.begin(); itr != destinations.end(); itr++) {
|
for (itr = destinations.begin(); itr != destinations.end(); itr++) {
|
||||||
|
@ -285,8 +285,8 @@ public:
|
|||||||
void HandleQuickbarUpdateRequest(EQApplicationPacket* app);
|
void HandleQuickbarUpdateRequest(EQApplicationPacket* app);
|
||||||
void SendPopupMessage(int8 unknown, const char* text, const char* type, float size, int8 red, int8 green, int8 blue);
|
void SendPopupMessage(int8 unknown, const char* text, const char* type, float size, int8 red, int8 green, int8 blue);
|
||||||
void PopulateSkillMap();
|
void PopulateSkillMap();
|
||||||
void ChangeLevel(int16 old_level, int16 new_level);
|
bool ChangeLevel(int16 old_level, int16 new_level, int32 xp_earned = 0);
|
||||||
void ChangeTSLevel(int16 old_level, int16 new_level);
|
bool ChangeTSLevel(int16 old_level, int16 new_level, int32 xp_earned = 0);
|
||||||
bool Summon(const char* search_name);
|
bool Summon(const char* search_name);
|
||||||
std::string IdentifyInstanceLockout(int32 zoneID, bool displayClient = true);
|
std::string IdentifyInstanceLockout(int32 zoneID, bool displayClient = true);
|
||||||
bool IdentifyInstance(ZoneChangeDetails* zone_details, int32 zoneID);
|
bool IdentifyInstance(ZoneChangeDetails* zone_details, int32 zoneID);
|
||||||
@ -299,8 +299,8 @@ public:
|
|||||||
bool BankWithdrawalNoBanker(int64 amount);
|
bool BankWithdrawalNoBanker(int64 amount);
|
||||||
bool BankHasCoin(int64 amount);
|
bool BankHasCoin(int64 amount);
|
||||||
void BankDeposit(int64 amount);
|
void BankDeposit(int64 amount);
|
||||||
Spawn* GetBanker();
|
int32 GetBanker();
|
||||||
void SetBanker(Spawn* in_banker);
|
void SetBanker(int32 in_banker);
|
||||||
bool AddItem(int32 item_id, int16 quantity = 0, AddItemType type = AddItemType::NOT_SET);
|
bool AddItem(int32 item_id, int16 quantity = 0, AddItemType type = AddItemType::NOT_SET);
|
||||||
bool AddItem(Item* item, bool* item_deleted = 0, AddItemType type = AddItemType::NOT_SET);
|
bool AddItem(Item* item, bool* item_deleted = 0, AddItemType type = AddItemType::NOT_SET);
|
||||||
bool AddItemToBank(int32 item_id, int16 quantity = 0);
|
bool AddItemToBank(int32 item_id, int16 quantity = 0);
|
||||||
@ -401,13 +401,14 @@ public:
|
|||||||
void RemoveCombineSpawn(Spawn* spawn);
|
void RemoveCombineSpawn(Spawn* spawn);
|
||||||
void SaveCombineSpawns(const char* name = 0);
|
void SaveCombineSpawns(const char* name = 0);
|
||||||
Spawn* GetCombineSpawn();
|
Spawn* GetCombineSpawn();
|
||||||
|
void SetCombineSpawn(Spawn* spawn) { combine_spawn = spawn; }
|
||||||
bool ShouldTarget();
|
bool ShouldTarget();
|
||||||
void TargetSpawn(Spawn* spawn);
|
void TargetSpawn(Spawn* spawn);
|
||||||
void ReloadQuests();
|
void ReloadQuests();
|
||||||
int32 GetCurrentQuestID() { return current_quest_id; }
|
int32 GetCurrentQuestID() { return current_quest_id; }
|
||||||
void SetLuaDebugClient(bool val);
|
void SetLuaDebugClient(bool val);
|
||||||
void SetMerchantTransaction(Spawn* spawn);
|
void SetMerchantTransaction(Spawn* spawn);
|
||||||
Spawn* GetMerchantTransaction();
|
int32 GetMerchantTransactionID();
|
||||||
void SetMailTransaction(Spawn* spawn);
|
void SetMailTransaction(Spawn* spawn);
|
||||||
Spawn* GetMailTransaction();
|
Spawn* GetMailTransaction();
|
||||||
void PlaySound(const char* name);
|
void PlaySound(const char* name);
|
||||||
@ -715,6 +716,12 @@ public:
|
|||||||
void SendReceiveOffer(Client* client_target, int8 type, std::string name, int8 unknown2);
|
void SendReceiveOffer(Client* client_target, int8 type, std::string name, int8 unknown2);
|
||||||
|
|
||||||
bool SendDialogChoice(int32 spawnID, const std::string& windowTextPrompt, const std::string& acceptText, const std::string& acceptCommand, const std::string& declineText, const std::string& declineCommand, int32 time, int8 textBox, int8 textBoxRequired, int32 maxLength);
|
bool SendDialogChoice(int32 spawnID, const std::string& windowTextPrompt, const std::string& acceptText, const std::string& acceptCommand, const std::string& declineText, const std::string& declineCommand, int32 time, int8 textBox, int8 textBoxRequired, int32 maxLength);
|
||||||
|
|
||||||
|
void SetTransportSpawnID(int32 id) { transport_spawn_id = id; }
|
||||||
|
int32 GetTransportSpawnID() { return transport_spawn_id; }
|
||||||
|
|
||||||
|
void SetLastTellName(std::string tellName) { last_tell_name = tellName; }
|
||||||
|
std::string GetLastTellName() { return last_tell_name; }
|
||||||
DialogManager dialog_manager;
|
DialogManager dialog_manager;
|
||||||
private:
|
private:
|
||||||
void AddRecipeToPlayerPack(Recipe* recipe, PacketStruct* packet, int16* i);
|
void AddRecipeToPlayerPack(Recipe* recipe, PacketStruct* packet, int16* i);
|
||||||
@ -737,10 +744,10 @@ private:
|
|||||||
vector<Item*>* search_items;
|
vector<Item*>* search_items;
|
||||||
int32 waypoint_id = 0;
|
int32 waypoint_id = 0;
|
||||||
map<string, WaypointInfo> waypoints;
|
map<string, WaypointInfo> waypoints;
|
||||||
Spawn* transport_spawn;
|
int32 transport_spawn_id;
|
||||||
Mutex MBuyBack;
|
Mutex MBuyBack;
|
||||||
deque<BuyBackItem*> buy_back_items;
|
deque<BuyBackItem*> buy_back_items;
|
||||||
Spawn* merchant_transaction;
|
int32 merchant_transaction_id;
|
||||||
Spawn* mail_transaction;
|
Spawn* mail_transaction;
|
||||||
mutable std::shared_mutex MPendingQuestAccept;
|
mutable std::shared_mutex MPendingQuestAccept;
|
||||||
vector<int32> pending_quest_accept;
|
vector<int32> pending_quest_accept;
|
||||||
@ -754,7 +761,7 @@ private:
|
|||||||
mutable std::shared_mutex MConversation;
|
mutable std::shared_mutex MConversation;
|
||||||
map<int32, map<int8, string> > conversation_map;
|
map<int32, map<int8, string> > conversation_map;
|
||||||
int32 current_quest_id;
|
int32 current_quest_id;
|
||||||
Spawn* banker;
|
int32 banker_id;
|
||||||
map<int32, int32> sent_spell_details;
|
map<int32, int32> sent_spell_details;
|
||||||
map<int32, bool> sent_item_details;
|
map<int32, bool> sent_item_details;
|
||||||
Player* player;
|
Player* player;
|
||||||
@ -879,6 +886,8 @@ private:
|
|||||||
uchar* recipe_xor_packet;
|
uchar* recipe_xor_packet;
|
||||||
int recipe_packet_count;
|
int recipe_packet_count;
|
||||||
int recipe_orig_packet_size;
|
int recipe_orig_packet_size;
|
||||||
|
|
||||||
|
std::string last_tell_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClientList {
|
class ClientList {
|
||||||
|
@ -339,6 +339,9 @@ int main(int argc, char** argv) {
|
|||||||
LogWrite(LUA__INFO, 0, "LUA", "Loading Zone Scripts...");
|
LogWrite(LUA__INFO, 0, "LUA", "Loading Zone Scripts...");
|
||||||
database.LoadZoneScriptData();
|
database.LoadZoneScriptData();
|
||||||
|
|
||||||
|
LogWrite(LUA__INFO, 0, "LUA", "Loading Player Scripts...");
|
||||||
|
world.LoadPlayerScripts();
|
||||||
|
|
||||||
LogWrite(WORLD__INFO, 0, "World", "Loading House Zone Data...");
|
LogWrite(WORLD__INFO, 0, "World", "Loading House Zone Data...");
|
||||||
database.LoadHouseZones();
|
database.LoadHouseZones();
|
||||||
database.LoadPlayerHouses();
|
database.LoadPlayerHouses();
|
||||||
@ -642,7 +645,7 @@ ThreadReturnType StartPeerPoll (void* tmp)
|
|||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||||
if(check_zone > 60) {
|
if(check_zone > 60) {
|
||||||
check_zone = 0;
|
check_zone = 0;
|
||||||
database.LoadSpecialZones();
|
database.LoadSpecialZones(true);
|
||||||
}
|
}
|
||||||
check_zone++;
|
check_zone++;
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
EQ2Emulator: Everquest II Server Emulator
|
EQ2Emulator: Everquest II Server Emulator
|
||||||
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
|
Copyright (C) 2005 - 2025 EQ2EMulator Development Team (http://www.eq2emu.com formerly http://www.eq2emulator.net)
|
||||||
|
|
||||||
This file is part of EQ2Emulator.
|
This file is part of EQ2Emulator.
|
||||||
EQ2Emulator 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
EQ2Emulator is distributed in the hope that it will be useful,
|
EQ2Emulator is free software: you can redistribute it and/or modify
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
it under the terms of the GNU General Public License as published by
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
GNU General Public License for more details.
|
(at your option) any later version.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
EQ2Emulator is distributed in the hope that it will be useful,
|
||||||
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../common/debug.h"
|
#include "../common/debug.h"
|
||||||
@ -810,6 +811,7 @@ void ZoneServer::ProcessDepop(bool respawns_allowed, bool repop) {
|
|||||||
if(!client)
|
if(!client)
|
||||||
continue;
|
continue;
|
||||||
client->GetPlayer()->SetTarget(0);
|
client->GetPlayer()->SetTarget(0);
|
||||||
|
client->SetMailTransaction(0);
|
||||||
if(repop)
|
if(repop)
|
||||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Zone Repop in progress...");
|
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Zone Repop in progress...");
|
||||||
else{
|
else{
|
||||||
@ -3910,12 +3912,14 @@ void ZoneServer::HandleChatMessage(Client* client, std::string fromName, const c
|
|||||||
void ZoneServer::HandleChatMessage(Spawn* from, const char* to, int16 channel, const char* message, float distance, const char* channel_name, bool show_bubble, int32 language){
|
void ZoneServer::HandleChatMessage(Spawn* from, const char* to, int16 channel, const char* message, float distance, const char* channel_name, bool show_bubble, int32 language){
|
||||||
vector<Client*>::iterator client_itr;
|
vector<Client*>::iterator client_itr;
|
||||||
Client* client = 0;
|
Client* client = 0;
|
||||||
|
std::string tokenedMsg = std::string(message);
|
||||||
|
SpellProcess::ReplaceEffectTokens(tokenedMsg, from, from->GetTarget());
|
||||||
|
|
||||||
MClientList.readlock(__FUNCTION__, __LINE__);
|
MClientList.readlock(__FUNCTION__, __LINE__);
|
||||||
for (client_itr = clients.begin(); client_itr != clients.end(); client_itr++) {
|
for (client_itr = clients.begin(); client_itr != clients.end(); client_itr++) {
|
||||||
client = *client_itr;
|
client = *client_itr;
|
||||||
if(client && client->IsConnected())
|
if(client && client->IsConnected())
|
||||||
HandleChatMessage(client, from, to, channel, message, distance, channel_name, show_bubble, language);
|
HandleChatMessage(client, from, to, channel, tokenedMsg.c_str(), distance, channel_name, show_bubble, language);
|
||||||
}
|
}
|
||||||
MClientList.releasereadlock(__FUNCTION__, __LINE__);
|
MClientList.releasereadlock(__FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
@ -4607,7 +4611,33 @@ void ZoneServer::CheckSpawnScriptTimers(){
|
|||||||
vector<SpawnScriptTimer>::iterator itr;
|
vector<SpawnScriptTimer>::iterator itr;
|
||||||
for(itr = call_timers.begin(); itr != call_timers.end(); itr++){
|
for(itr = call_timers.begin(); itr != call_timers.end(); itr++){
|
||||||
SpawnScriptTimer tmpTimer = (SpawnScriptTimer)*itr;
|
SpawnScriptTimer tmpTimer = (SpawnScriptTimer)*itr;
|
||||||
CallSpawnScript(GetSpawnByID(tmpTimer.spawn), SPAWN_SCRIPT_TIMER, tmpTimer.player > 0 ? GetSpawnByID(tmpTimer.player) : 0, tmpTimer.function.c_str());
|
Spawn* callSpawn = GetSpawnByID(tmpTimer.spawn);
|
||||||
|
Spawn* target = nullptr;
|
||||||
|
if(tmpTimer.player) {
|
||||||
|
target = GetSpawnByID(tmpTimer.player);
|
||||||
|
}
|
||||||
|
if(callSpawn) {
|
||||||
|
if(!callSpawn->IsPlayer()) {
|
||||||
|
CallSpawnScript(GetSpawnByID(tmpTimer.spawn), SPAWN_SCRIPT_TIMER, target, tmpTimer.function.c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const char* playerScript = world.GetPlayerScript(0); // 0 = global script
|
||||||
|
const char* playerZoneScript = world.GetPlayerScript(GetZoneID()); // zone script
|
||||||
|
if(playerScript || playerZoneScript) {
|
||||||
|
std::vector<LuaArg> args = {
|
||||||
|
LuaArg(this),
|
||||||
|
LuaArg(callSpawn),
|
||||||
|
LuaArg(target)
|
||||||
|
};
|
||||||
|
if(playerScript) {
|
||||||
|
lua_interface->RunPlayerScriptWithReturn(playerScript, tmpTimer.function.c_str(), args);
|
||||||
|
}
|
||||||
|
if(playerZoneScript) {
|
||||||
|
lua_interface->RunPlayerScriptWithReturn(playerZoneScript, tmpTimer.function.c_str(), args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4714,11 +4744,24 @@ void ZoneServer::RemoveSpawn(Spawn* spawn, bool delete_spawn, bool respawn, bool
|
|||||||
for (client_itr = clients.begin(); client_itr != clients.end(); client_itr++) {
|
for (client_itr = clients.begin(); client_itr != clients.end(); client_itr++) {
|
||||||
client = *client_itr;
|
client = *client_itr;
|
||||||
|
|
||||||
if (client && (client->GetVersion() > 373 || !client->IsZoning() || client->GetPlayer() != spawn)) { //don't send destroy ghost of 283 client when zoning
|
if (client && (!client->IsZoning() || client->GetPlayer() != spawn)) {
|
||||||
if (client->GetPlayer()->HasTarget() && client->GetPlayer()->GetTarget() == spawn)
|
if (client->GetPlayer()->HasTarget() && client->GetPlayer()->GetTarget() == spawn)
|
||||||
client->GetPlayer()->SetTarget(0);
|
client->GetPlayer()->SetTarget(0);
|
||||||
if(client->GetPlayer()->WasSentSpawn(spawn->GetID()) || client->GetPlayer()->IsSendingSpawn(spawn->GetID()))
|
if(client->GetMailTransaction() == spawn)
|
||||||
|
client->SetMailTransaction(0);
|
||||||
|
if(client->GetBanker() == spawn->GetID())
|
||||||
|
client->SetBanker(0);
|
||||||
|
if(client->GetTransportSpawnID() == spawn->GetID())
|
||||||
|
client->SetTransportSpawnID(0);
|
||||||
|
if(client->GetTempPlacementSpawn() == spawn)
|
||||||
|
client->SetTempPlacementSpawn(nullptr);
|
||||||
|
if(client->GetCombineSpawn() == spawn)
|
||||||
|
client->SetCombineSpawn(nullptr);
|
||||||
|
|
||||||
|
//don't send destroy ghost of 283 client when zoning
|
||||||
|
if((client->GetVersion() > 373 || !client->IsZoning()) && (client->GetPlayer()->WasSentSpawn(spawn->GetID()) || client->GetPlayer()->IsSendingSpawn(spawn->GetID())))
|
||||||
SendRemoveSpawn(client, spawn, packet, delete_spawn);
|
SendRemoveSpawn(client, spawn, packet, delete_spawn);
|
||||||
|
|
||||||
if (spawn_range_map.count(client) > 0)
|
if (spawn_range_map.count(client) > 0)
|
||||||
spawn_range_map.Get(client)->erase(spawn->GetID());
|
spawn_range_map.Get(client)->erase(spawn->GetID());
|
||||||
}
|
}
|
||||||
@ -5375,6 +5418,29 @@ void ZoneServer::KillSpawn(bool spawnListLocked, Spawn* dead, Spawn* killer, boo
|
|||||||
((NPC*)dead)->Brain()->ClearHate();
|
((NPC*)dead)->Brain()->ClearHate();
|
||||||
|
|
||||||
safe_delete(encounter);
|
safe_delete(encounter);
|
||||||
|
|
||||||
|
const char* functionToCall = "on_player_death";
|
||||||
|
bool isPlayerDead = true;
|
||||||
|
if(dead->IsPlayer() || (killer && killer->IsPlayer() && (isPlayerDead = false))) {
|
||||||
|
if(!isPlayerDead) {
|
||||||
|
functionToCall = "on_player_kill";
|
||||||
|
}
|
||||||
|
const char* playerScript = world.GetPlayerScript(0); // 0 = global script
|
||||||
|
const char* playerZoneScript = world.GetPlayerScript(GetZoneID()); // zone script
|
||||||
|
if(playerScript || playerZoneScript) {
|
||||||
|
std::vector<LuaArg> args = {
|
||||||
|
LuaArg(this),
|
||||||
|
LuaArg(dead),
|
||||||
|
LuaArg(killer)
|
||||||
|
};
|
||||||
|
if(playerScript) {
|
||||||
|
lua_interface->RunPlayerScriptWithReturn(playerScript, functionToCall, args);
|
||||||
|
}
|
||||||
|
if(playerZoneScript) {
|
||||||
|
lua_interface->RunPlayerScriptWithReturn(playerZoneScript, functionToCall, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneServer::SendDamagePacket(Spawn* attacker, Spawn* victim, int8 type1, int8 type2, int8 damage_type, int16 damage, const char* spell_name) {
|
void ZoneServer::SendDamagePacket(Spawn* attacker, Spawn* victim, int8 type1, int8 type2, int8 damage_type, int16 damage, const char* spell_name) {
|
||||||
@ -8658,6 +8724,7 @@ void ZoneServer::DeleteGlobalSpawns() {
|
|||||||
ClearEntityCommands();
|
ClearEntityCommands();
|
||||||
|
|
||||||
DeleteGroundSpawnItems();
|
DeleteGroundSpawnItems();
|
||||||
|
DeleteTransporters();
|
||||||
DeleteGlobalTransporters();
|
DeleteGlobalTransporters();
|
||||||
DeleteTransporterMaps();
|
DeleteTransporterMaps();
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LOGIN)
|
#if defined(LOGIN)
|
||||||
#define CURRENT_VERSION "0.9.8-thetascorpii-DR1"
|
#define CURRENT_VERSION "0.9.9-Nebula"
|
||||||
#elif defined(WORLD)
|
#elif defined(WORLD)
|
||||||
#define CURRENT_VERSION "0.9.8-thetascorpii-DR1"
|
#define CURRENT_VERSION "0.9.9-Nebula"
|
||||||
#else
|
#else
|
||||||
#define CURRENT_VERSION "0.9.8-thetascorpii-DR1"
|
#define CURRENT_VERSION "0.9.9-Nebula"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define COMPILE_DATE __DATE__
|
#define COMPILE_DATE __DATE__
|
||||||
|
Loading…
x
Reference in New Issue
Block a user