mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 14:41:28 +00:00
Merge branch 'master' into crosszonesignalplayerbygroupid
This commit is contained in:
commit
dc9bd031ff
@ -328,7 +328,10 @@ IF(UNIX)
|
||||
IF(NOT DARWIN)
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "rt")
|
||||
ENDIF()
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "uuid")
|
||||
# Freebsd provides uuids in the C library
|
||||
IF(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "uuid")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(EQEMU_BUILD_LOGIN AND NOT TLS_LIBRARY_ENABLED)
|
||||
|
||||
@ -118,6 +118,11 @@ void set_exception_handler() {
|
||||
#include <unistd.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
void print_trace()
|
||||
{
|
||||
auto uid = geteuid();
|
||||
|
||||
@ -4804,8 +4804,8 @@ struct ItemQuaternaryBodyStruct
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
int32 Clairvoyance;
|
||||
uint8 unknown18; //Power Source Capacity or evolve filename?
|
||||
uint32 evolve_string; // Some String, but being evolution related is just a guess
|
||||
int32 SubType;
|
||||
uint8 evolve_string; // Some String, but being evolution related is just a guess
|
||||
uint8 unknown19;
|
||||
uint16 unknown20;
|
||||
uint8 unknown21;
|
||||
|
||||
@ -4744,8 +4744,8 @@ struct ItemQuaternaryBodyStruct
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
int32 Clairvoyance;
|
||||
uint8 unknown18; //Power Source Capacity or evolve filename?
|
||||
uint32 evolve_string; // Some String, but being evolution related is just a guess
|
||||
int32 SubType;
|
||||
uint8 evolve_string; // Some String, but being evolution related is just a guess
|
||||
uint8 unknown19;
|
||||
uint32 unknown20; // Bard Stuff?
|
||||
//uint32 unknown21;
|
||||
|
||||
@ -4215,8 +4215,8 @@ struct ItemQuaternaryBodyStruct
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
int32 Clairvoyance;
|
||||
uint8 unknown18; //Power Source Capacity or evolve filename?
|
||||
uint32 evolve_string; // Some String, but being evolution related is just a guess
|
||||
int32 SubType;
|
||||
uint8 evolve_string; // Some String, but being evolution related is just a guess
|
||||
uint8 unknown19;
|
||||
uint32 unknown20; // Bard Stuff?
|
||||
uint32 unknown21;
|
||||
|
||||
@ -24,6 +24,10 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
//I forced this object to become a singleton because it registers its
|
||||
//signal handler for UNIX
|
||||
class ProcLauncher {
|
||||
|
||||
@ -280,6 +280,7 @@ RULE_BOOL(Zone, UseZoneController, true, "Enables the ability to use persistent
|
||||
RULE_BOOL(Zone, EnableZoneControllerGlobals, false, "Enables the ability to use quest globals with the zone controller NPC")
|
||||
RULE_INT(Zone, GlobalLootMultiplier, 1, "Sets Global Loot drop multiplier for database based drops, useful for double, triple loot etc")
|
||||
RULE_BOOL(Zone, KillProcessOnDynamicShutdown, true, "When process has booted a zone and has hit its zone shut down timer, it will hard kill the process to free memory back to the OS")
|
||||
RULE_INT(Zone, SecondsBeforeIdle, 60, "Seconds before IDLE_WHEN_EMPTY define kicks in")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Map)
|
||||
|
||||
@ -199,6 +199,7 @@
|
||||
#define ServerOP_UCSServerStatusReply 0x4014
|
||||
#define ServerOP_HotReloadQuests 0x4015
|
||||
#define ServerOP_CZSignalGroup 0x4016
|
||||
#define ServerOP_CZMessageGuild 0x4021
|
||||
|
||||
/**
|
||||
* QueryServer
|
||||
@ -1340,6 +1341,12 @@ struct CZMessagePlayer_Struct {
|
||||
char Message[512];
|
||||
};
|
||||
|
||||
struct CZMessageGuild_Struct {
|
||||
uint32 Type;
|
||||
int GuildID;
|
||||
char Message[512];
|
||||
};
|
||||
|
||||
struct WWMarquee_Struct {
|
||||
uint32 Type;
|
||||
uint32 Priority;
|
||||
|
||||
@ -14,6 +14,10 @@
|
||||
#include <CoreFoundation/CFUUID.h>
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <uuid.h>
|
||||
#endif
|
||||
|
||||
unsigned char hexDigitToChar(char ch)
|
||||
{
|
||||
if (ch > 47 && ch < 58)
|
||||
@ -126,6 +130,15 @@ EQ::Util::UUID EQ::Util::UUID::Generate()
|
||||
|
||||
return buffer;
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
uuid_t l_id;
|
||||
char l_uuid[37];
|
||||
uint32_t l_ignored;
|
||||
uuid_create(&l_id, &l_ignored);
|
||||
uuid_to_string(&l_id, (char**) &l_uuid, &l_ignored);
|
||||
return FromString(l_uuid);
|
||||
#endif
|
||||
}
|
||||
|
||||
EQ::Util::UUID EQ::Util::UUID::FromString(const std::string &str)
|
||||
|
||||
@ -1238,6 +1238,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
}
|
||||
case ServerOP_CZSignalClientByName:
|
||||
case ServerOP_CZMessagePlayer:
|
||||
case ServerOP_CZMessageGuild:
|
||||
case ServerOP_CZSignalNPC:
|
||||
case ServerOP_CZSetEntityVariableByNPCTypeID:
|
||||
case ServerOP_CZSignalClient:
|
||||
|
||||
@ -3775,6 +3775,23 @@ XS(XS__crosszonemessageplayerbyname) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__crosszonemessageplayerbyguildid);
|
||||
XS(XS__crosszonemessageplayerbyguildid) {
|
||||
dXSARGS;
|
||||
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: quest::crosszonemessageplayerbyguildid(int typ, int guild_id, string message)");
|
||||
|
||||
if (items == 3) {
|
||||
uint32 type = (uint32) SvIV(ST(0));
|
||||
int guild_id = (int) SvIV(ST(1));
|
||||
char *message = (char *) SvPV_nolen(ST(2));
|
||||
quest_manager.CrossZoneMessagePlayerByGuildID(type, guild_id, message);
|
||||
}
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__enablerecipe);
|
||||
XS(XS__enablerecipe) {
|
||||
dXSARGS;
|
||||
@ -4191,6 +4208,7 @@ EXTERN_C XS(boot_quest) {
|
||||
newXS(strcpy(buf, "creategroundobjectfrommodel"), XS__CreateGroundObjectFromModel, file);
|
||||
newXS(strcpy(buf, "createguild"), XS__createguild, file);
|
||||
newXS(strcpy(buf, "crosszonemessageplayerbyname"), XS__crosszonemessageplayerbyname, file);
|
||||
newXS(strcpy(buf, "crosszonemessageplayerbyguildid"), XS__crosszonemessageplayerbyguildid, file);
|
||||
newXS(strcpy(buf, "crosszonesetentityvariablebynpctypeid"), XS__crosszonesetentityvariablebynpctypeid, file);
|
||||
newXS(strcpy(buf, "crosszonesetentityvariablebyclientname"), XS__crosszonesetentityvariablebyclientname, file);
|
||||
newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file);
|
||||
|
||||
@ -498,11 +498,30 @@ void EntityList::MobProcess()
|
||||
size_t sz = mob_list.size();
|
||||
|
||||
#ifdef IDLE_WHEN_EMPTY
|
||||
static int old_client_count=0;
|
||||
static Timer *mob_settle_timer = new Timer();
|
||||
|
||||
if (numclients == 0 && old_client_count > 0 &&
|
||||
RuleI(Zone, SecondsBeforeIdle) > 0) {
|
||||
// Start Timer to allow any mobs that chased chars from zone
|
||||
// to return home.
|
||||
mob_settle_timer->Start(RuleI(Zone, SecondsBeforeIdle) * 1000);
|
||||
}
|
||||
|
||||
old_client_count = numclients;
|
||||
|
||||
// Disable settle timer if someone zones into empty zone
|
||||
if (numclients > 0 || mob_settle_timer->Check()) {
|
||||
mob_settle_timer->Disable();
|
||||
}
|
||||
|
||||
if (numclients > 0 ||
|
||||
mob->GetWanderType() == 4 || mob->GetWanderType() == 6) {
|
||||
mob->GetWanderType() == 4 || mob->GetWanderType() == 6 ||
|
||||
mob_settle_timer->Enabled()) {
|
||||
// Normal processing, or assuring that spawns that should
|
||||
// path and depop do that. Otherwise all of these type mobs
|
||||
// will be up and at starting positions when idle zone wakes up.
|
||||
// will be up and at starting positions, or waiting at the zoneline
|
||||
// if they chased the PCs when idle zone wakes up.
|
||||
mob_dead = !mob->Process();
|
||||
}
|
||||
else {
|
||||
|
||||
@ -1210,6 +1210,11 @@ void Lua_Client::OpenLFGuildWindow() {
|
||||
self->OpenLFGuildWindow();
|
||||
}
|
||||
|
||||
void Lua_Client::NotifyNewTitlesAvailable() {
|
||||
Lua_Safe_Call_Void();
|
||||
self->NotifyNewTitlesAvailable();
|
||||
}
|
||||
|
||||
void Lua_Client::Signal(uint32 id) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->Signal(id);
|
||||
@ -1820,6 +1825,7 @@ luabind::scope lua_register_client() {
|
||||
.def("GetAllMoney", (uint64(Lua_Client::*)(void))&Lua_Client::GetAllMoney)
|
||||
.def("GetMoney", (uint32(Lua_Client::*)(uint8, uint8))&Lua_Client::GetMoney)
|
||||
.def("OpenLFGuildWindow", (void(Lua_Client::*)(void))&Lua_Client::OpenLFGuildWindow)
|
||||
.def("NotifyNewTitlesAvailable", (void(Lua_Client::*)(void))&Lua_Client::NotifyNewTitlesAvailable)
|
||||
.def("Signal", (void(Lua_Client::*)(uint32))&Lua_Client::Signal)
|
||||
.def("AddAlternateCurrencyValue", (void(Lua_Client::*)(uint32,int))&Lua_Client::AddAlternateCurrencyValue)
|
||||
.def("SetAlternateCurrencyValue", (void(Lua_Client::*)(uint32,int))&Lua_Client::SetAlternateCurrencyValue)
|
||||
|
||||
@ -269,6 +269,7 @@ public:
|
||||
uint64 GetAllMoney();
|
||||
uint32 GetMoney(uint8 type, uint8 subtype);
|
||||
void OpenLFGuildWindow();
|
||||
void NotifyNewTitlesAvailable();
|
||||
void Signal(uint32 id);
|
||||
void AddAlternateCurrencyValue(uint32 currency, int amount);
|
||||
void SetAlternateCurrencyValue(uint32 currency, int amount);
|
||||
|
||||
@ -1038,6 +1038,10 @@ void lua_cross_zone_message_player_by_name(uint32 type, const char *player, cons
|
||||
quest_manager.CrossZoneMessagePlayerByName(type, player, message);
|
||||
}
|
||||
|
||||
void lua_cross_zone_message_player_by_guild_id(uint32 type, int guild_id, const char *message) {
|
||||
quest_manager.CrossZoneMessagePlayerByGuildID(type, guild_id, message);
|
||||
}
|
||||
|
||||
void lua_cross_zone_set_entity_variable_by_client_name(const char *player, const char *id, const char *m_var) {
|
||||
quest_manager.CrossZoneSetEntityVariableByClientName(player, id, m_var);
|
||||
}
|
||||
@ -1846,6 +1850,7 @@ luabind::scope lua_register_general() {
|
||||
luabind::def("cross_zone_signal_client_by_group_id", &lua_cross_zone_signal_client_by_group_id),
|
||||
luabind::def("cross_zone_signal_client_by_name", &lua_cross_zone_signal_client_by_name),
|
||||
luabind::def("cross_zone_message_player_by_name", &lua_cross_zone_message_player_by_name),
|
||||
luabind::def("cross_zone_message_player_by_guild_id", &lua_cross_zone_message_player_by_guild_id),
|
||||
luabind::def("cross_zone_set_entity_variable_by_client_name", &lua_cross_zone_set_entity_variable_by_client_name),
|
||||
luabind::def("world_wide_marquee", &lua_world_wide_marquee),
|
||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals),
|
||||
|
||||
@ -92,6 +92,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/unix.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
extern volatile bool is_zone_loaded;
|
||||
|
||||
EntityList entity_list;
|
||||
@ -431,8 +435,10 @@ int main(int argc, char** argv) {
|
||||
EQStreamIdentifier stream_identifier;
|
||||
RegisterAllPatches(stream_identifier);
|
||||
|
||||
#ifndef WIN32
|
||||
#ifdef __linux__
|
||||
LogDebug("Main thread running with thread id [{}]", pthread_self());
|
||||
#elif defined(__FreeBSD__)
|
||||
LogDebug("Main thread running with thread id [{}]", pthread_getthreadid_np());
|
||||
#endif
|
||||
|
||||
bool worldwasconnected = worldserver.Connected();
|
||||
|
||||
@ -263,6 +263,146 @@ protected:
|
||||
double m_total_v_dist;
|
||||
};
|
||||
|
||||
class FlyToCommand : public IMovementCommand {
|
||||
public:
|
||||
FlyToCommand(float x, float y, float z, MobMovementMode mob_movement_mode)
|
||||
{
|
||||
m_distance_moved_since_correction = 0.0;
|
||||
m_move_to_x = x;
|
||||
m_move_to_y = y;
|
||||
m_move_to_z = z;
|
||||
m_move_to_mode = mob_movement_mode;
|
||||
m_last_sent_time = 0.0;
|
||||
m_last_sent_speed = 0;
|
||||
m_started = false;
|
||||
m_total_h_dist = 0.0;
|
||||
m_total_v_dist = 0.0;
|
||||
}
|
||||
|
||||
virtual ~FlyToCommand()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mob_movement_manager
|
||||
* @param mob
|
||||
* @return
|
||||
*/
|
||||
virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob)
|
||||
{
|
||||
if (!mob->IsAIControlled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Send a movement packet when you start moving
|
||||
double current_time = static_cast<double>(Timer::GetCurrentTime()) / 1000.0;
|
||||
int current_speed = 0;
|
||||
|
||||
if (m_move_to_mode == MovementRunning) {
|
||||
if (mob->IsFeared()) {
|
||||
current_speed = mob->GetFearSpeed();
|
||||
}
|
||||
else {
|
||||
current_speed = mob->GetRunspeed();
|
||||
}
|
||||
}
|
||||
else {
|
||||
current_speed = mob->GetWalkspeed();
|
||||
}
|
||||
|
||||
if (!m_started) {
|
||||
m_started = true;
|
||||
//rotate to the point
|
||||
mob->SetMoving(true);
|
||||
mob->SetHeading(mob->CalculateHeadingToTarget(m_move_to_x, m_move_to_y));
|
||||
|
||||
m_last_sent_speed = current_speed;
|
||||
m_last_sent_time = current_time;
|
||||
m_total_h_dist = DistanceNoZ(mob->GetPosition(), glm::vec4(m_move_to_x, m_move_to_y, 0.0f, 0.0f));
|
||||
m_total_v_dist = m_move_to_z - mob->GetZ();
|
||||
mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
|
||||
}
|
||||
|
||||
//When speed changes
|
||||
if (current_speed != m_last_sent_speed) {
|
||||
m_distance_moved_since_correction = 0.0;
|
||||
m_last_sent_speed = current_speed;
|
||||
m_last_sent_time = current_time;
|
||||
mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
|
||||
}
|
||||
|
||||
//If x seconds have passed without sending an update.
|
||||
if (current_time - m_last_sent_time >= 0.5) {
|
||||
m_distance_moved_since_correction = 0.0;
|
||||
m_last_sent_speed = current_speed;
|
||||
m_last_sent_time = current_time;
|
||||
mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
|
||||
}
|
||||
|
||||
auto &p = mob->GetPosition();
|
||||
glm::vec2 tar(m_move_to_x, m_move_to_y);
|
||||
glm::vec2 pos(p.x, p.y);
|
||||
double len = glm::distance(pos, tar);
|
||||
if (len == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mob->SetMoved(true);
|
||||
|
||||
glm::vec2 dir = tar - pos;
|
||||
glm::vec2 ndir = glm::normalize(dir);
|
||||
double distance_moved = frame_time * current_speed * 0.4f * 1.45f;
|
||||
|
||||
if (distance_moved > len) {
|
||||
if (mob->IsNPC()) {
|
||||
entity_list.ProcessMove(mob->CastToNPC(), m_move_to_x, m_move_to_y, m_move_to_z);
|
||||
}
|
||||
|
||||
mob->SetPosition(m_move_to_x, m_move_to_y, m_move_to_z);
|
||||
|
||||
if (RuleB(Map, FixZWhenPathing)) {
|
||||
mob->FixZ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
glm::vec2 npos = pos + (ndir * static_cast<float>(distance_moved));
|
||||
|
||||
len -= distance_moved;
|
||||
double total_distance_traveled = m_total_h_dist - len;
|
||||
double start_z = m_move_to_z - m_total_v_dist;
|
||||
double z_at_pos = start_z + (m_total_v_dist * (total_distance_traveled / m_total_h_dist));
|
||||
|
||||
if (mob->IsNPC()) {
|
||||
entity_list.ProcessMove(mob->CastToNPC(), npos.x, npos.y, z_at_pos);
|
||||
}
|
||||
|
||||
mob->SetPosition(npos.x, npos.y, z_at_pos);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool Started() const
|
||||
{
|
||||
return m_started;
|
||||
}
|
||||
|
||||
protected:
|
||||
double m_distance_moved_since_correction;
|
||||
double m_move_to_x;
|
||||
double m_move_to_y;
|
||||
double m_move_to_z;
|
||||
MobMovementMode m_move_to_mode;
|
||||
bool m_started;
|
||||
|
||||
double m_last_sent_time;
|
||||
int m_last_sent_speed;
|
||||
double m_total_h_dist;
|
||||
double m_total_v_dist;
|
||||
};
|
||||
|
||||
class SwimToCommand : public MoveToCommand {
|
||||
public:
|
||||
SwimToCommand(float x, float y, float z, MobMovementMode mob_movement_mode) : MoveToCommand(x, y, z, mob_movement_mode)
|
||||
@ -921,6 +1061,8 @@ void MobMovementManager::FillCommandStruct(
|
||||
*/
|
||||
void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode)
|
||||
{
|
||||
Mob *target=who->GetTarget();
|
||||
|
||||
if (!zone->HasMap() || !zone->HasWaterMap()) {
|
||||
auto iter = _impl->Entries.find(who);
|
||||
auto &ent = (*iter);
|
||||
@ -936,6 +1078,16 @@ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMove
|
||||
else if (who->IsUnderwaterOnly()) {
|
||||
UpdatePathUnderwater(who, x, y, z, mob_movement_mode);
|
||||
}
|
||||
// If we can fly, and we have a target and we have LoS, simply fly to them.
|
||||
// if we ever lose LoS we go back to mesh run mode.
|
||||
else if (target && who->GetFlyMode() == GravityBehavior::Flying &&
|
||||
who->CheckLosFN(x,y,z,target->GetSize())) {
|
||||
auto iter = _impl->Entries.find(who);
|
||||
auto &ent = (*iter);
|
||||
|
||||
PushFlyTo(ent.second, x, y, z, mob_movement_mode);
|
||||
PushStopMoving(ent.second);
|
||||
}
|
||||
else {
|
||||
UpdatePathGround(who, x, y, z, mob_movement_mode);
|
||||
}
|
||||
@ -1275,6 +1427,18 @@ void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to,
|
||||
ent.Commands.push_back(std::unique_ptr<IMovementCommand>(new RotateToCommand(to, diff > 0 ? 1.0 : -1.0, mob_movement_mode)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ent
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param mob_movement_mode
|
||||
*/
|
||||
void MobMovementManager::PushFlyTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode)
|
||||
{
|
||||
ent.Commands.push_back(std::unique_ptr<IMovementCommand>(new FlyToCommand(x, y, z, mob_movement_mode)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mob_movement_entry
|
||||
*/
|
||||
|
||||
@ -85,6 +85,7 @@ private:
|
||||
void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading);
|
||||
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||
void PushFlyTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||
void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mob_movement_mode);
|
||||
void PushStopMoving(MobMovementEntry &mob_movement_entry);
|
||||
void PushEvadeCombat(MobMovementEntry &mob_movement_entry);
|
||||
|
||||
31
zone/npc.cpp
31
zone/npc.cpp
@ -2443,18 +2443,27 @@ void NPC::LevelScale() {
|
||||
|
||||
if (RuleB(NPC, NewLevelScaling)) {
|
||||
if (scalerate == 0 || maxlevel <= 25) {
|
||||
// pre-pop seems to scale by 20 HP increments while newer by 100
|
||||
// We also don't want 100 increments on newer noobie zones, check level
|
||||
if (zone->GetZoneID() < 200 || level < 48) {
|
||||
max_hp += (random_level - level) * 20;
|
||||
base_hp += (random_level - level) * 20;
|
||||
} else {
|
||||
max_hp += (random_level - level) * 100;
|
||||
base_hp += (random_level - level) * 100;
|
||||
// Don't add HP to dynamically scaled NPCs since this will be calculated later
|
||||
if (max_hp > 0 || skip_auto_scale)
|
||||
{
|
||||
// pre-pop seems to scale by 20 HP increments while newer by 100
|
||||
// We also don't want 100 increments on newer noobie zones, check level
|
||||
if (zone->GetZoneID() < 200 || level < 48) {
|
||||
max_hp += (random_level - level) * 20;
|
||||
base_hp += (random_level - level) * 20;
|
||||
} else {
|
||||
max_hp += (random_level - level) * 100;
|
||||
base_hp += (random_level - level) * 100;
|
||||
}
|
||||
|
||||
current_hp = max_hp;
|
||||
}
|
||||
|
||||
// Don't add max_dmg to dynamically scaled NPCs since this will be calculated later
|
||||
if (max_dmg > 0 || skip_auto_scale)
|
||||
{
|
||||
max_dmg += (random_level - level) * 2;
|
||||
}
|
||||
|
||||
current_hp = max_hp;
|
||||
max_dmg += (random_level - level) * 2;
|
||||
} else {
|
||||
uint8 scale_adjust = 1;
|
||||
|
||||
|
||||
@ -5522,6 +5522,27 @@ XS(XS_Client_OpenLFGuildWindow) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Client_NotifyNewTitlesAvailable); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_NotifyNewTitlesAvailable) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Client::NotifyNewTitlesAvailable(THIS)");
|
||||
{
|
||||
Client *THIS;
|
||||
|
||||
if (sv_derived_from(ST(0), "Client")) {
|
||||
IV tmp = SvIV((SV *) SvRV(ST(0)));
|
||||
THIS = INT2PTR(Client *, tmp);
|
||||
} else
|
||||
Perl_croak(aTHX_ "THIS is not of type Client");
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
THIS->NotifyNewTitlesAvailable();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Client_SignalClient); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_SignalClient) {
|
||||
dXSARGS;
|
||||
@ -6568,6 +6589,7 @@ XS(boot_Client) {
|
||||
newXSproto(strcpy(buf, "NPCSpawn"), XS_Client_NPCSpawn, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "NukeItem"), XS_Client_NukeItem, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "OpenLFGuildWindow"), XS_Client_OpenLFGuildWindow, file, "$");
|
||||
newXSproto(strcpy(buf, "NotifyNewTitlesAvailable"), XS_Client_NotifyNewTitlesAvailable, file, "$");
|
||||
newXSproto(strcpy(buf, "PlayMP3"), XS_Client_PlayMP3, file, "$;$");
|
||||
newXSproto(strcpy(buf, "Popup2"), XS_Client_Popup2, file, "$$$;$$$$$$$");
|
||||
newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$");
|
||||
|
||||
@ -3243,6 +3243,17 @@ void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharNam
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
void QuestManager::CrossZoneMessagePlayerByGuildID(uint32 Type, int GuildID, const char *Message){
|
||||
uint32 message_len = strlen(Message) + 1;
|
||||
auto pack = new ServerPacket(ServerOP_CZMessageGuild, sizeof(CZMessageGuild_Struct) + message_len);
|
||||
CZMessageGuild_Struct* CZGM = (CZMessageGuild_Struct*) pack->pBuffer;
|
||||
CZGM->Type = Type;
|
||||
CZGM->GuildID = GuildID;
|
||||
strn0cpy(CZGM->Message, Message, 512);
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
void QuestManager::CrossZoneSetEntityVariableByClientName(const char *CharName, const char *id, const char *m_var){
|
||||
uint32 message_len = strlen(id) + 1;
|
||||
uint32 message_len2 = strlen(m_var) + 1;
|
||||
|
||||
@ -285,6 +285,7 @@ public:
|
||||
void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var);
|
||||
void CrossZoneSetEntityVariableByClientName(const char *CharName, const char *id, const char *m_var);
|
||||
void CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message);
|
||||
void CrossZoneMessagePlayerByGuildID(uint32 Type, int GuildID, const char *Message);
|
||||
void WorldWideMarquee(uint32 Type, uint32 Priority, uint32 FadeIn, uint32 FadeOut, uint32 Duration, const char *Message);
|
||||
bool EnableRecipe(uint32 recipe_id);
|
||||
bool DisableRecipe(uint32 recipe_id);
|
||||
|
||||
@ -1944,6 +1944,17 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_CZMessageGuild:
|
||||
{
|
||||
CZMessageGuild_Struct* CZGM = (CZMessageGuild_Struct*)pack->pBuffer;
|
||||
auto client_list = entity_list.GetClientList();
|
||||
for (auto client : client_list) {
|
||||
if (client.second->GuildID() > 0 && client.second->GuildID() == CZGM->GuildID) {
|
||||
client.second->Message(CZGM->Type, CZGM->Message);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_CZSetEntityVariableByClientName:
|
||||
{
|
||||
CZSetEntVarByClientName_Struct* CZCS = (CZSetEntVarByClientName_Struct*)pack->pBuffer;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user