mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-17 18:41:29 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
0153726755
@ -1,6 +1,7 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
== 7/9/2017 ==
|
== 7/9/2017 ==
|
||||||
|
Akkadius: Fix HP update issues, rework logic for more accurate HP updates
|
||||||
Akkadius: Massive reductions in unnecessary network traffic especially during high spam combat fights
|
Akkadius: Massive reductions in unnecessary network traffic especially during high spam combat fights
|
||||||
- HP Updates now only send to others when HP percentage changes (0-100%)
|
- HP Updates now only send to others when HP percentage changes (0-100%)
|
||||||
- HP Updates were sending excessively even during idle zones when HP wasn't changing at all
|
- HP Updates were sending excessively even during idle zones when HP wasn't changing at all
|
||||||
|
|||||||
@ -134,7 +134,6 @@ RULE_INT(Character, TradeskillUpMakePoison, 2) // Make Poison skillup rate adjus
|
|||||||
RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lower is faster.
|
RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lower is faster.
|
||||||
RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster.
|
RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster.
|
||||||
RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster.
|
RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster.
|
||||||
RULE_BOOL(Character, SpamHPUpdates, false) // if your server has stupid amounts of HP that causes client display issues, turn this on!
|
|
||||||
RULE_BOOL(Character, MarqueeHPUpdates, false) // Will show Health % in center of screen < 100%
|
RULE_BOOL(Character, MarqueeHPUpdates, false) // Will show Health % in center of screen < 100%
|
||||||
RULE_INT(Character, IksarCommonTongue, 95) // 95 By default (live-like?)
|
RULE_INT(Character, IksarCommonTongue, 95) // 95 By default (live-like?)
|
||||||
RULE_INT(Character, OgreCommonTongue, 95) // 95 By default (live-like?)
|
RULE_INT(Character, OgreCommonTongue, 95) // 95 By default (live-like?)
|
||||||
@ -235,7 +234,6 @@ RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone AL
|
|||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Zone)
|
RULE_CATEGORY(Zone)
|
||||||
RULE_INT(Zone, NPCPositonUpdateTicCount, 32) //ms between intervals of sending a position update to the entire zone.
|
|
||||||
RULE_INT(Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection
|
RULE_INT(Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection
|
||||||
RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone
|
RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone
|
||||||
RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on.
|
RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on.
|
||||||
|
|||||||
@ -137,9 +137,7 @@ EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstanc
|
|||||||
if (Hand == EQEmu::inventory::slotSecondary) // DW anim
|
if (Hand == EQEmu::inventory::slotSecondary) // DW anim
|
||||||
type = animDualWield;
|
type = animDualWield;
|
||||||
|
|
||||||
if (attack_anim_timer.Check()) {
|
|
||||||
DoAnim(type, 0, false);
|
DoAnim(type, 0, false);
|
||||||
}
|
|
||||||
|
|
||||||
return skillinuse;
|
return skillinuse;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -158,7 +158,8 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f),
|
m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f),
|
||||||
last_region_type(RegionTypeUnsupported),
|
last_region_type(RegionTypeUnsupported),
|
||||||
m_dirtyautohaters(false),
|
m_dirtyautohaters(false),
|
||||||
npc_close_scan_timer(6000)
|
npc_close_scan_timer(6000),
|
||||||
|
hp_self_update_throttle_timer(500)
|
||||||
{
|
{
|
||||||
for(int cf=0; cf < _FilterCount; cf++)
|
for(int cf=0; cf < _FilterCount; cf++)
|
||||||
ClientFilters[cf] = FilterShow;
|
ClientFilters[cf] = FilterShow;
|
||||||
@ -357,7 +358,7 @@ Client::~Client() {
|
|||||||
m_tradeskill_object = nullptr;
|
m_tradeskill_object = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
close_npcs.clear();
|
close_mobs.clear();
|
||||||
|
|
||||||
if(IsDueling() && GetDuelTarget() != 0) {
|
if(IsDueling() && GetDuelTarget() != 0) {
|
||||||
Entity* entity = entity_list.GetID(GetDuelTarget());
|
Entity* entity = entity_list.GetID(GetDuelTarget());
|
||||||
@ -1832,13 +1833,13 @@ void Client::SendManaUpdatePacket() {
|
|||||||
if (!Connected())
|
if (!Connected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (last_reported_mana != cur_mana || last_reported_endur != cur_end) {
|
||||||
|
|
||||||
if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) {
|
if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) {
|
||||||
SendManaUpdate();
|
SendManaUpdate();
|
||||||
SendEnduranceUpdate();
|
SendEnduranceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_reported_mana != cur_mana || last_reported_endur != cur_end) {
|
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct));
|
auto outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct));
|
||||||
ManaChange_Struct* manachange = (ManaChange_Struct*)outapp->pBuffer;
|
ManaChange_Struct* manachange = (ManaChange_Struct*)outapp->pBuffer;
|
||||||
manachange->new_mana = cur_mana;
|
manachange->new_mana = cur_mana;
|
||||||
@ -8745,8 +8746,8 @@ void Client::SendHPUpdateMarquee(){
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Health Update Marquee Display: Custom*/
|
/* Health Update Marquee Display: Custom*/
|
||||||
int8 health_percentage = (int8)(this->cur_hp * 100 / this->max_hp);
|
uint8 health_percentage = (uint8)(this->cur_hp * 100 / this->max_hp);
|
||||||
if (health_percentage == 100)
|
if (health_percentage >= 100)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string health_update_notification = StringFormat("Health: %u%%", health_percentage);
|
std::string health_update_notification = StringFormat("Health: %u%%", health_percentage);
|
||||||
|
|||||||
@ -222,7 +222,7 @@ public:
|
|||||||
Client(EQStreamInterface * ieqs);
|
Client(EQStreamInterface * ieqs);
|
||||||
~Client();
|
~Client();
|
||||||
|
|
||||||
std::unordered_map<NPC *, float> close_npcs;
|
std::unordered_map<Mob *, float> close_mobs;
|
||||||
bool is_client_moving;
|
bool is_client_moving;
|
||||||
|
|
||||||
//abstract virtual function implementations required by base abstract class
|
//abstract virtual function implementations required by base abstract class
|
||||||
@ -1485,6 +1485,7 @@ private:
|
|||||||
Timer helm_toggle_timer;
|
Timer helm_toggle_timer;
|
||||||
Timer aggro_meter_timer;
|
Timer aggro_meter_timer;
|
||||||
Timer npc_close_scan_timer;
|
Timer npc_close_scan_timer;
|
||||||
|
Timer hp_self_update_throttle_timer;
|
||||||
|
|
||||||
glm::vec3 m_Proximity;
|
glm::vec3 m_Proximity;
|
||||||
|
|
||||||
|
|||||||
@ -583,8 +583,17 @@ void Client::CompleteConnect()
|
|||||||
|
|
||||||
if (raid->IsLocked())
|
if (raid->IsLocked())
|
||||||
raid->SendRaidLockTo(this);
|
raid->SendRaidLockTo(this);
|
||||||
|
|
||||||
|
raid->SendHPPacketsTo(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
Group *group = nullptr;
|
||||||
|
group = this->GetGroup();
|
||||||
|
if (group)
|
||||||
|
group->SendHPPacketsTo(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//bulk raid send in here eventually
|
//bulk raid send in here eventually
|
||||||
|
|
||||||
|
|||||||
@ -254,19 +254,31 @@ bool Client::Process() {
|
|||||||
/* Build a close range list of NPC's */
|
/* Build a close range list of NPC's */
|
||||||
if (npc_close_scan_timer.Check()) {
|
if (npc_close_scan_timer.Check()) {
|
||||||
|
|
||||||
close_npcs.clear();
|
close_mobs.clear();
|
||||||
|
|
||||||
auto &npc_list = entity_list.GetNPCList();
|
auto &mob_list = entity_list.GetMobList();
|
||||||
|
float scan_range = (RuleI(Range, ClientNPCScan) * RuleI(Range, ClientNPCScan));
|
||||||
|
float client_update_range = (RuleI(Range, MobPositionUpdates) * RuleI(Range, MobPositionUpdates));
|
||||||
|
|
||||||
float scan_range = RuleI(Range, ClientNPCScan);
|
for (auto itr = mob_list.begin(); itr != mob_list.end(); ++itr) {
|
||||||
for (auto itr = npc_list.begin(); itr != npc_list.end(); ++itr) {
|
Mob* mob = itr->second;
|
||||||
NPC* npc = itr->second;
|
float distance = DistanceSquared(m_Position, mob->GetPosition());
|
||||||
float distance = DistanceNoZ(m_Position, npc->GetPosition());
|
if (mob->IsNPC()) {
|
||||||
if(distance <= scan_range) {
|
if (distance <= scan_range) {
|
||||||
close_npcs.insert(std::pair<NPC *, float>(npc, distance));
|
close_mobs.insert(std::pair<Mob *, float>(mob, distance));
|
||||||
}
|
}
|
||||||
else if (npc->GetAggroRange() > scan_range) {
|
else if (mob->GetAggroRange() > scan_range) {
|
||||||
close_npcs.insert(std::pair<NPC *, float>(npc, distance));
|
close_mobs.insert(std::pair<Mob *, float>(mob, distance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clients need to be kept up to date for position updates more often otherwise they disappear */
|
||||||
|
if (mob->IsClient() && this != mob && distance <= client_update_range) {
|
||||||
|
auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||||
|
PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
|
||||||
|
mob->MakeSpawnUpdateNoDelta(spawn_update);
|
||||||
|
this->FastQueuePacket(&app, false);
|
||||||
|
safe_delete(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -455,7 +467,7 @@ bool Client::Process() {
|
|||||||
// Send a position packet every 8 seconds - if not done, other clients
|
// Send a position packet every 8 seconds - if not done, other clients
|
||||||
// see this char disappear after 10-12 seconds of inactivity
|
// see this char disappear after 10-12 seconds of inactivity
|
||||||
if (position_timer_counter >= 36) { // Approx. 4 ticks per second
|
if (position_timer_counter >= 36) { // Approx. 4 ticks per second
|
||||||
entity_list.SendPositionUpdates(this, pLastUpdateWZ, 500, GetTarget(), true);
|
entity_list.SendPositionUpdates(this, pLastUpdateWZ, RuleI(Range, MobPositionUpdates), GetTarget(), true);
|
||||||
pLastUpdate = Timer::GetCurrentTime();
|
pLastUpdate = Timer::GetCurrentTime();
|
||||||
pLastUpdateWZ = pLastUpdate;
|
pLastUpdateWZ = pLastUpdate;
|
||||||
position_timer_counter = 0;
|
position_timer_counter = 0;
|
||||||
@ -619,11 +631,17 @@ bool Client::Process() {
|
|||||||
// only if client is not feigned
|
// only if client is not feigned
|
||||||
if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) {
|
if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) {
|
||||||
int npc_scan_count = 0;
|
int npc_scan_count = 0;
|
||||||
for (auto it = close_npcs.begin(); it != close_npcs.end(); ++it) {
|
for (auto it = close_mobs.begin(); it != close_mobs.end(); ++it) {
|
||||||
NPC *npc = it->first;
|
Mob *mob = it->first;
|
||||||
|
|
||||||
if (npc->CheckWillAggro(this) && !npc->CheckAggro(this)) {
|
if (!mob)
|
||||||
npc->AddToHateList(this, 25);
|
continue;
|
||||||
|
|
||||||
|
if (mob->IsClient())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mob->CheckWillAggro(this) && !mob->CheckAggro(this)) {
|
||||||
|
mob->AddToHateList(this, 25);
|
||||||
}
|
}
|
||||||
npc_scan_count++;
|
npc_scan_count++;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2282,6 +2282,9 @@ bool EntityList::RemoveMob(uint16 delete_id)
|
|||||||
|
|
||||||
auto it = mob_list.find(delete_id);
|
auto it = mob_list.find(delete_id);
|
||||||
if (it != mob_list.end()) {
|
if (it != mob_list.end()) {
|
||||||
|
|
||||||
|
RemoveMobFromClientCloseLists(it->second);
|
||||||
|
|
||||||
if (npc_list.count(delete_id))
|
if (npc_list.count(delete_id))
|
||||||
entity_list.RemoveNPC(delete_id);
|
entity_list.RemoveNPC(delete_id);
|
||||||
else if (client_list.count(delete_id))
|
else if (client_list.count(delete_id))
|
||||||
@ -2304,6 +2307,8 @@ bool EntityList::RemoveMob(Mob *delete_mob)
|
|||||||
auto it = mob_list.begin();
|
auto it = mob_list.begin();
|
||||||
while (it != mob_list.end()) {
|
while (it != mob_list.end()) {
|
||||||
if (it->second == delete_mob) {
|
if (it->second == delete_mob) {
|
||||||
|
RemoveMobFromClientCloseLists(it->second);
|
||||||
|
|
||||||
safe_delete(it->second);
|
safe_delete(it->second);
|
||||||
if (!corpse_list.count(it->first))
|
if (!corpse_list.count(it->first))
|
||||||
free_ids.push(it->first);
|
free_ids.push(it->first);
|
||||||
@ -2323,11 +2328,10 @@ bool EntityList::RemoveNPC(uint16 delete_id)
|
|||||||
// make sure its proximity is removed
|
// make sure its proximity is removed
|
||||||
RemoveProximity(delete_id);
|
RemoveProximity(delete_id);
|
||||||
// remove from client close lists
|
// remove from client close lists
|
||||||
RemoveNPCFromClientCloseLists(npc);
|
RemoveMobFromClientCloseLists(npc->CastToMob());
|
||||||
// remove from the list
|
// remove from the list
|
||||||
npc_list.erase(it);
|
npc_list.erase(it);
|
||||||
|
|
||||||
|
|
||||||
// remove from limit list if needed
|
// remove from limit list if needed
|
||||||
if (npc_limit_list.count(delete_id))
|
if (npc_limit_list.count(delete_id))
|
||||||
npc_limit_list.erase(delete_id);
|
npc_limit_list.erase(delete_id);
|
||||||
@ -2336,11 +2340,11 @@ bool EntityList::RemoveNPC(uint16 delete_id)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityList::RemoveNPCFromClientCloseLists(NPC *npc)
|
bool EntityList::RemoveMobFromClientCloseLists(Mob *mob)
|
||||||
{
|
{
|
||||||
auto it = client_list.begin();
|
auto it = client_list.begin();
|
||||||
while (it != client_list.end()) {
|
while (it != client_list.end()) {
|
||||||
it->second->close_npcs.erase(npc);
|
it->second->close_mobs.erase(mob);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -2634,10 +2638,9 @@ void EntityList::RemoveDebuffs(Mob *caster)
|
|||||||
// Currently, a new packet is sent per entity.
|
// Currently, a new packet is sent per entity.
|
||||||
// @todo: Come back and use FLAG_COMBINED to pack
|
// @todo: Come back and use FLAG_COMBINED to pack
|
||||||
// all updates into one packet.
|
// all updates into one packet.
|
||||||
void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate,
|
void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate, float update_range, Entity *always_send, bool iSendEvenIfNotChanged)
|
||||||
float range, Entity *alwayssend, bool iSendEvenIfNotChanged)
|
|
||||||
{
|
{
|
||||||
range = range * range;
|
update_range = (update_range * update_range);
|
||||||
|
|
||||||
EQApplicationPacket *outapp = 0;
|
EQApplicationPacket *outapp = 0;
|
||||||
PlayerPositionUpdateServer_Struct *ppu = 0;
|
PlayerPositionUpdateServer_Struct *ppu = 0;
|
||||||
@ -2645,27 +2648,37 @@ void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate,
|
|||||||
|
|
||||||
auto it = mob_list.begin();
|
auto it = mob_list.begin();
|
||||||
while (it != mob_list.end()) {
|
while (it != mob_list.end()) {
|
||||||
|
|
||||||
|
mob = it->second;
|
||||||
|
|
||||||
|
if (
|
||||||
|
mob && !mob->IsCorpse()
|
||||||
|
&& (it->second != client)
|
||||||
|
&& (mob->IsClient() || iSendEvenIfNotChanged || (mob->LastChange() >= cLastUpdate))
|
||||||
|
&& (!it->second->IsClient() || !it->second->CastToClient()->GMHideMe(client))
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
update_range == 0
|
||||||
|
|| (it->second == always_send)
|
||||||
|
|| mob->IsClient()
|
||||||
|
|| (DistanceSquared(mob->GetPosition(), client->GetPosition()) <= update_range)
|
||||||
|
) {
|
||||||
|
if (mob && mob->IsClient() && mob->GetID() > 0) {
|
||||||
|
client->QueuePacket(outapp, false, Client::CLIENT_CONNECTED);
|
||||||
|
|
||||||
if (outapp == 0) {
|
if (outapp == 0) {
|
||||||
outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||||
ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer;
|
ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer;
|
||||||
}
|
}
|
||||||
mob = it->second;
|
|
||||||
if (mob && !mob->IsCorpse() && (it->second != client)
|
|
||||||
&& (mob->IsClient() || iSendEvenIfNotChanged || (mob->LastChange() >= cLastUpdate))
|
|
||||||
&& (!it->second->IsClient() || !it->second->CastToClient()->GMHideMe(client))) {
|
|
||||||
|
|
||||||
//bool Grouped = client->HasGroup() && mob->IsClient() && (client->GetGroup() == mob->CastToClient()->GetGroup());
|
|
||||||
|
|
||||||
//if (range == 0 || (iterator.GetData() == alwayssend) || Grouped || (mob->DistNoRootNoZ(*client) <= range)) {
|
|
||||||
if (range == 0 || (it->second == alwayssend) || mob->IsClient() || (DistanceSquared(mob->GetPosition(), client->GetPosition()) <= range)) {
|
|
||||||
mob->MakeSpawnUpdate(ppu);
|
mob->MakeSpawnUpdate(ppu);
|
||||||
}
|
|
||||||
if(mob && mob->IsClient() && mob->GetID()>0) {
|
|
||||||
client->QueuePacket(outapp, false, Client::CLIENT_CONNECTED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
outapp = 0;
|
outapp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -279,7 +279,7 @@ public:
|
|||||||
bool RemoveTrap(uint16 delete_id);
|
bool RemoveTrap(uint16 delete_id);
|
||||||
bool RemoveObject(uint16 delete_id);
|
bool RemoveObject(uint16 delete_id);
|
||||||
bool RemoveProximity(uint16 delete_npc_id);
|
bool RemoveProximity(uint16 delete_npc_id);
|
||||||
bool RemoveNPCFromClientCloseLists(NPC *npc);
|
bool RemoveMobFromClientCloseLists(Mob *mob);
|
||||||
void RemoveAllMobs();
|
void RemoveAllMobs();
|
||||||
void RemoveAllClients();
|
void RemoveAllClients();
|
||||||
void RemoveAllNPCs();
|
void RemoveAllNPCs();
|
||||||
@ -370,7 +370,7 @@ public:
|
|||||||
Mob* FindDefenseNPC(uint32 npcid);
|
Mob* FindDefenseNPC(uint32 npcid);
|
||||||
void OpenDoorsNear(NPC* opener);
|
void OpenDoorsNear(NPC* opener);
|
||||||
void UpdateWho(bool iSendFullUpdate = false);
|
void UpdateWho(bool iSendFullUpdate = false);
|
||||||
void SendPositionUpdates(Client* client, uint32 cLastUpdate = 0, float range = 0, Entity* alwayssend = 0, bool iSendEvenIfNotChanged = false);
|
void SendPositionUpdates(Client* client, uint32 cLastUpdate = 0, float update_range = 0, Entity* always_send = 0, bool iSendEvenIfNotChanged = false);
|
||||||
char* MakeNameUnique(char* name);
|
char* MakeNameUnique(char* name);
|
||||||
static char* RemoveNumbers(char* name);
|
static char* RemoveNumbers(char* name);
|
||||||
void SignalMobsByNPCID(uint32 npc_type, int signal_id);
|
void SignalMobsByNPCID(uint32 npc_type, int signal_id);
|
||||||
|
|||||||
@ -338,6 +338,13 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
|
|||||||
database.SetGroupID(NewMemberName, GetID(), owner->CharacterID(), true);
|
database.SetGroupID(NewMemberName, GetID(), owner->CharacterID(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Group* group = newmember->CastToClient()->GetGroup();
|
||||||
|
if (group) {
|
||||||
|
group->SendHPPacketsTo(newmember);
|
||||||
|
group->SendHPPacketsFrom(newmember);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -389,26 +396,25 @@ void Group::QueuePacket(const EQApplicationPacket *app, bool ack_req)
|
|||||||
// first joins a group, but otherwise there shouldn't be a need to call it
|
// first joins a group, but otherwise there shouldn't be a need to call it
|
||||||
void Group::SendHPPacketsTo(Mob *member)
|
void Group::SendHPPacketsTo(Mob *member)
|
||||||
{
|
{
|
||||||
if(member && member->IsClient())
|
if(member && member->IsClient()) {
|
||||||
{
|
|
||||||
EQApplicationPacket hpapp;
|
EQApplicationPacket hpapp;
|
||||||
EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct));
|
EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct));
|
||||||
|
|
||||||
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++)
|
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
||||||
{
|
if(members[i] && members[i] != member) {
|
||||||
if(members[i] && members[i] != member)
|
|
||||||
{
|
|
||||||
members[i]->CreateHPPacket(&hpapp);
|
members[i]->CreateHPPacket(&hpapp);
|
||||||
member->CastToClient()->QueuePacket(&hpapp, false);
|
member->CastToClient()->QueuePacket(&hpapp, false);
|
||||||
safe_delete_array(hpapp.pBuffer);
|
safe_delete_array(hpapp.pBuffer);
|
||||||
hpapp.size = 0;
|
hpapp.size = 0;
|
||||||
if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD)
|
|
||||||
{
|
if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) {
|
||||||
outapp.SetOpcode(OP_MobManaUpdate);
|
outapp.SetOpcode(OP_MobManaUpdate);
|
||||||
|
|
||||||
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer;
|
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer;
|
||||||
mmus->spawn_id = members[i]->GetID();
|
mmus->spawn_id = members[i]->GetID();
|
||||||
mmus->mana = members[i]->GetManaPercent();
|
mmus->mana = members[i]->GetManaPercent();
|
||||||
member->CastToClient()->QueuePacket(&outapp, false);
|
member->CastToClient()->QueuePacket(&outapp, false);
|
||||||
|
|
||||||
MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer;
|
MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer;
|
||||||
outapp.SetOpcode(OP_MobEnduranceUpdate);
|
outapp.SetOpcode(OP_MobEnduranceUpdate);
|
||||||
meus->endurance = members[i]->GetEndurancePercent();
|
meus->endurance = members[i]->GetEndurancePercent();
|
||||||
|
|||||||
175
zone/mob.cpp
175
zone/mob.cpp
@ -125,13 +125,12 @@ Mob::Mob(const char* in_name,
|
|||||||
|
|
||||||
last_z = 0;
|
last_z = 0;
|
||||||
|
|
||||||
last_hp = 100;
|
|
||||||
|
|
||||||
AI_Init();
|
AI_Init();
|
||||||
SetMoving(false);
|
SetMoving(false);
|
||||||
moved=false;
|
moved=false;
|
||||||
m_RewindLocation = glm::vec3();
|
m_RewindLocation = glm::vec3();
|
||||||
move_tic_count = 0;
|
|
||||||
|
|
||||||
_egnode = nullptr;
|
_egnode = nullptr;
|
||||||
name[0]=0;
|
name[0]=0;
|
||||||
@ -180,6 +179,8 @@ Mob::Mob(const char* in_name,
|
|||||||
fearspeed = ((float)base_fearspeed) * 0.025f;
|
fearspeed = ((float)base_fearspeed) * 0.025f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last_hp_percent = 0;
|
||||||
|
last_hp = 0;
|
||||||
|
|
||||||
current_speed = base_runspeed;
|
current_speed = base_runspeed;
|
||||||
|
|
||||||
@ -1304,122 +1305,135 @@ void Mob::CreateHPPacket(EQApplicationPacket* app)
|
|||||||
void Mob::SendHPUpdate(bool skip_self)
|
void Mob::SendHPUpdate(bool skip_self)
|
||||||
{
|
{
|
||||||
|
|
||||||
int8 current_hp = (max_hp == 0 ? 0 : static_cast<int>(cur_hp * 100 / max_hp));
|
/* If our HP is different from last HP update call - let's update ourself */
|
||||||
|
if (IsClient() && cur_hp != last_hp) {
|
||||||
|
/* This is to prevent excessive packet sending under trains/fast combat */
|
||||||
|
if (this->CastToClient()->hp_self_update_throttle_timer.Check()) {
|
||||||
|
Log(Logs::General, Logs::HP_Update,
|
||||||
|
"Mob::SendHPUpdate :: Update HP of self (%s) HP: %i last: %i skip_self: %s",
|
||||||
|
this->GetCleanName(),
|
||||||
|
cur_hp,
|
||||||
|
last_hp,
|
||||||
|
(skip_self ? "true" : "false")
|
||||||
|
);
|
||||||
|
|
||||||
Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: SendHPUpdate %s HP is %i last %i", this->GetCleanName(), current_hp, last_hp);
|
if (!skip_self || this->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::UF) {
|
||||||
if (current_hp == last_hp) {
|
auto client_packet = new EQApplicationPacket(OP_HPUpdate, sizeof(SpawnHPUpdate_Struct));
|
||||||
|
SpawnHPUpdate_Struct* hp_packet_client = (SpawnHPUpdate_Struct*)client_packet->pBuffer;
|
||||||
|
|
||||||
|
hp_packet_client->cur_hp = CastToClient()->GetHP() - itembonuses.HP;
|
||||||
|
hp_packet_client->spawn_id = GetID();
|
||||||
|
hp_packet_client->max_hp = CastToClient()->GetMaxHP() - itembonuses.HP;
|
||||||
|
|
||||||
|
CastToClient()->QueuePacket(client_packet);
|
||||||
|
|
||||||
|
safe_delete(client_packet);
|
||||||
|
|
||||||
|
ResetHPUpdateTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used to check if HP has changed to update self next round */
|
||||||
|
last_hp = cur_hp;
|
||||||
|
|
||||||
|
int8 current_hp_percent = (max_hp == 0 ? 0 : static_cast<int>(cur_hp * 100 / max_hp));
|
||||||
|
|
||||||
|
Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: SendHPUpdate %s HP is %i last %i", this->GetCleanName(), current_hp_percent, last_hp_percent);
|
||||||
|
|
||||||
|
if (current_hp_percent == last_hp_percent) {
|
||||||
Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: Same HP - skipping update");
|
Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: Same HP - skipping update");
|
||||||
ResetHPUpdateTimer();
|
ResetHPUpdateTimer();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
if (IsClient() && RuleB(Character, MarqueeHPUpdates))
|
||||||
|
this->CastToClient()->SendHPUpdateMarquee();
|
||||||
|
|
||||||
Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: HP Changed - Send update");
|
Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: HP Changed - Send update");
|
||||||
last_hp = current_hp;
|
|
||||||
|
last_hp_percent = current_hp_percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket hp_app;
|
EQApplicationPacket hp_app;
|
||||||
Group *group = nullptr;
|
Group *group = nullptr;
|
||||||
|
|
||||||
// destructor will free the pBuffer
|
|
||||||
CreateHPPacket(&hp_app);
|
CreateHPPacket(&hp_app);
|
||||||
|
|
||||||
// send to people who have us targeted
|
/* Update those who have use targeted */
|
||||||
entity_list.QueueClientsByTarget(this, &hp_app, false, 0, false, true, EQEmu::versions::bit_AllClients);
|
entity_list.QueueClientsByTarget(this, &hp_app, false, 0, false, true, EQEmu::versions::bit_AllClients);
|
||||||
|
|
||||||
|
/* Update those who have us on x-target */
|
||||||
entity_list.QueueClientsByXTarget(this, &hp_app, false);
|
entity_list.QueueClientsByXTarget(this, &hp_app, false);
|
||||||
|
|
||||||
|
/* Update groups using Group LAA health name tag counter */
|
||||||
entity_list.QueueToGroupsForNPCHealthAA(this, &hp_app);
|
entity_list.QueueToGroupsForNPCHealthAA(this, &hp_app);
|
||||||
|
|
||||||
// send to group
|
/* Update group */
|
||||||
if(IsGrouped())
|
if(IsGrouped()) {
|
||||||
{
|
|
||||||
group = entity_list.GetGroupByMob(this);
|
group = entity_list.GetGroupByMob(this);
|
||||||
if(group) //not sure why this might be null, but it happens
|
if(group) //not sure why this might be null, but it happens
|
||||||
group->SendHPPacketsFrom(this);
|
group->SendHPPacketsFrom(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update Raid */
|
||||||
if(IsClient()){
|
if(IsClient()){
|
||||||
Raid *r = entity_list.GetRaidByClient(CastToClient());
|
Raid *raid = entity_list.GetRaidByClient(CastToClient());
|
||||||
if(r){
|
if (raid)
|
||||||
r->SendHPPacketsFrom(this);
|
raid->SendHPPacketsFrom(this);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send to master
|
/* Pet - Update master - group and raid if exists */
|
||||||
if(GetOwner() && GetOwner()->IsClient())
|
if(GetOwner() && GetOwner()->IsClient()) {
|
||||||
{
|
|
||||||
GetOwner()->CastToClient()->QueuePacket(&hp_app, false);
|
GetOwner()->CastToClient()->QueuePacket(&hp_app, false);
|
||||||
group = entity_list.GetGroupByClient(GetOwner()->CastToClient());
|
group = entity_list.GetGroupByClient(GetOwner()->CastToClient());
|
||||||
|
|
||||||
if(group)
|
if(group)
|
||||||
group->SendHPPacketsFrom(this);
|
group->SendHPPacketsFrom(this);
|
||||||
Raid *r = entity_list.GetRaidByClient(GetOwner()->CastToClient());
|
|
||||||
if(r)
|
Raid *raid = entity_list.GetRaidByClient(GetOwner()->CastToClient());
|
||||||
r->SendHPPacketsFrom(this);
|
if(raid)
|
||||||
|
raid->SendHPPacketsFrom(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// send to pet
|
/* Send to pet */
|
||||||
if(GetPet() && GetPet()->IsClient())
|
if(GetPet() && GetPet()->IsClient()) {
|
||||||
{
|
|
||||||
GetPet()->CastToClient()->QueuePacket(&hp_app, false);
|
GetPet()->CastToClient()->QueuePacket(&hp_app, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the damage state of destructible objects
|
/* Destructible objects */
|
||||||
if(IsNPC() && IsDestructibleObject())
|
if (IsNPC() && IsDestructibleObject()) {
|
||||||
{
|
if (GetHPRatio() > 74) {
|
||||||
if (GetHPRatio() > 74)
|
if (GetAppearance() != eaStanding) {
|
||||||
{
|
|
||||||
if (GetAppearance() != eaStanding)
|
|
||||||
{
|
|
||||||
SendAppearancePacket(AT_DamageState, eaStanding);
|
SendAppearancePacket(AT_DamageState, eaStanding);
|
||||||
_appearance = eaStanding;
|
_appearance = eaStanding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (GetHPRatio() > 49)
|
else if (GetHPRatio() > 49) {
|
||||||
{
|
if (GetAppearance() != eaSitting) {
|
||||||
if (GetAppearance() != eaSitting)
|
|
||||||
{
|
|
||||||
SendAppearancePacket(AT_DamageState, eaSitting);
|
SendAppearancePacket(AT_DamageState, eaSitting);
|
||||||
_appearance = eaSitting;
|
_appearance = eaSitting;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (GetHPRatio() > 24)
|
else if (GetHPRatio() > 24) {
|
||||||
{
|
if (GetAppearance() != eaCrouching) {
|
||||||
if (GetAppearance() != eaCrouching)
|
|
||||||
{
|
|
||||||
SendAppearancePacket(AT_DamageState, eaCrouching);
|
SendAppearancePacket(AT_DamageState, eaCrouching);
|
||||||
_appearance = eaCrouching;
|
_appearance = eaCrouching;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (GetHPRatio() > 0)
|
else if (GetHPRatio() > 0) {
|
||||||
{
|
if (GetAppearance() != eaDead) {
|
||||||
if (GetAppearance() != eaDead)
|
|
||||||
{
|
|
||||||
SendAppearancePacket(AT_DamageState, eaDead);
|
SendAppearancePacket(AT_DamageState, eaDead);
|
||||||
_appearance = eaDead;
|
_appearance = eaDead;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (GetAppearance() != eaLooting)
|
else if (GetAppearance() != eaLooting) {
|
||||||
{
|
|
||||||
SendAppearancePacket(AT_DamageState, eaLooting);
|
SendAppearancePacket(AT_DamageState, eaLooting);
|
||||||
_appearance = eaLooting;
|
_appearance = eaLooting;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dospam = RuleB(Character, SpamHPUpdates);
|
|
||||||
// send to self - we need the actual hps here
|
|
||||||
if(IsClient() && (!skip_self || dospam)) {
|
|
||||||
|
|
||||||
if (RuleB(Character, MarqueeHPUpdates))
|
|
||||||
this->CastToClient()->SendHPUpdateMarquee();
|
|
||||||
|
|
||||||
auto hp_app2 = new EQApplicationPacket(OP_HPUpdate, sizeof(SpawnHPUpdate_Struct));
|
|
||||||
SpawnHPUpdate_Struct* ds = (SpawnHPUpdate_Struct*)hp_app2->pBuffer;
|
|
||||||
ds->cur_hp = CastToClient()->GetHP() - itembonuses.HP;
|
|
||||||
ds->spawn_id = GetID();
|
|
||||||
ds->max_hp = CastToClient()->GetMaxHP() - itembonuses.HP;
|
|
||||||
CastToClient()->QueuePacket(hp_app2);
|
|
||||||
safe_delete(hp_app2);
|
|
||||||
}
|
|
||||||
if (!dospam)
|
|
||||||
ResetHPUpdateTimer(); // delay the timer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this one just warps the mob to the current location
|
// this one just warps the mob to the current location
|
||||||
@ -1428,8 +1442,7 @@ void Mob::SendPosition()
|
|||||||
auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||||
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
|
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
|
||||||
MakeSpawnUpdateNoDelta(spu);
|
MakeSpawnUpdateNoDelta(spu);
|
||||||
move_tic_count = 0;
|
entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false);
|
||||||
entity_list.QueueClients(this, app, true);
|
|
||||||
safe_delete(app);
|
safe_delete(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1441,31 +1454,18 @@ void Mob::SendPosUpdate(uint8 iSendToSelf) {
|
|||||||
|
|
||||||
if (iSendToSelf == 2) {
|
if (iSendToSelf == 2) {
|
||||||
if (IsClient()) {
|
if (IsClient()) {
|
||||||
CastToClient()->FastQueuePacket(&app,false);
|
CastToClient()->FastQueuePacket(&app, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if(move_tic_count == RuleI(Zone, NPCPositonUpdateTicCount))
|
|
||||||
{
|
|
||||||
entity_list.QueueClients(this, app, (iSendToSelf == 0), false);
|
|
||||||
move_tic_count = 0;
|
|
||||||
}
|
|
||||||
else if(move_tic_count % 2 == 0)
|
|
||||||
{
|
|
||||||
entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false);
|
|
||||||
move_tic_count++;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
move_tic_count++;
|
entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
safe_delete(app);
|
safe_delete(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is for SendPosition()
|
// this is for SendPosition()
|
||||||
void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu){
|
void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu) {
|
||||||
memset(spu,0xff,sizeof(PlayerPositionUpdateServer_Struct));
|
memset(spu, 0xff, sizeof(PlayerPositionUpdateServer_Struct));
|
||||||
spu->spawn_id = GetID();
|
spu->spawn_id = GetID();
|
||||||
spu->x_pos = FloatToEQ19(m_Position.x);
|
spu->x_pos = FloatToEQ19(m_Position.x);
|
||||||
spu->y_pos = FloatToEQ19(m_Position.y);
|
spu->y_pos = FloatToEQ19(m_Position.y);
|
||||||
@ -1476,10 +1476,10 @@ void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu){
|
|||||||
spu->heading = FloatToEQ19(m_Position.w);
|
spu->heading = FloatToEQ19(m_Position.w);
|
||||||
spu->animation = 0;
|
spu->animation = 0;
|
||||||
spu->delta_heading = NewFloatToEQ13(0);
|
spu->delta_heading = NewFloatToEQ13(0);
|
||||||
spu->padding0002 =0;
|
spu->padding0002 = 0;
|
||||||
spu->padding0006 =7;
|
spu->padding0006 = 7;
|
||||||
spu->padding0014 =0x7f;
|
spu->padding0014 = 0x7f;
|
||||||
spu->padding0018 =0x5df27;
|
spu->padding0018 = 0x5df27;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1553,6 +1553,9 @@ void Mob::ShowStats(Client* client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) {
|
void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) {
|
||||||
|
if (!attack_anim_timer.Check())
|
||||||
|
return;
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct));
|
auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct));
|
||||||
Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer;
|
Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer;
|
||||||
anim->spawnid = GetID();
|
anim->spawnid = GetID();
|
||||||
|
|||||||
@ -1373,7 +1373,6 @@ protected:
|
|||||||
void ClearItemFactionBonuses();
|
void ClearItemFactionBonuses();
|
||||||
|
|
||||||
void CalculateFearPosition();
|
void CalculateFearPosition();
|
||||||
uint32 move_tic_count;
|
|
||||||
|
|
||||||
bool flee_mode;
|
bool flee_mode;
|
||||||
Timer flee_timer;
|
Timer flee_timer;
|
||||||
@ -1389,7 +1388,8 @@ protected:
|
|||||||
int wandertype;
|
int wandertype;
|
||||||
int pausetype;
|
int pausetype;
|
||||||
|
|
||||||
int8 last_hp;
|
int8 last_hp_percent;
|
||||||
|
int32 last_hp;
|
||||||
|
|
||||||
int cur_wp;
|
int cur_wp;
|
||||||
glm::vec4 m_CurrentWayPoint;
|
glm::vec4 m_CurrentWayPoint;
|
||||||
|
|||||||
@ -1454,7 +1454,10 @@ void PathManager::NodeInfo(Client *c)
|
|||||||
void PathManager::DumpPath(std::string filename)
|
void PathManager::DumpPath(std::string filename)
|
||||||
{
|
{
|
||||||
std::ofstream o_file;
|
std::ofstream o_file;
|
||||||
o_file.open(filename.c_str(), std::ios_base::binary | std::ios_base::trunc | std::ios_base::out);
|
|
||||||
|
std::string file_to_write = StringFormat("%s%s", Config->MapDir.c_str(), filename.c_str());
|
||||||
|
|
||||||
|
o_file.open(file_to_write.c_str(), std::ios_base::binary | std::ios_base::trunc | std::ios_base::out);
|
||||||
o_file.write("EQEMUPATH", 9);
|
o_file.write("EQEMUPATH", 9);
|
||||||
o_file.write((const char*)&Head, sizeof(Head));
|
o_file.write((const char*)&Head, sizeof(Head));
|
||||||
o_file.write((const char*)PathNodes, (sizeof(PathNode)*Head.PathNodeCount));
|
o_file.write((const char*)PathNodes, (sizeof(PathNode)*Head.PathNodeCount));
|
||||||
|
|||||||
@ -145,6 +145,13 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Group *group_update = nullptr;
|
||||||
|
group_update = c->GetGroup();
|
||||||
|
if (group_update) {
|
||||||
|
group_update->SendHPPacketsTo(c);
|
||||||
|
group_update->SendHPPacketsFrom(c);
|
||||||
|
}
|
||||||
|
|
||||||
auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct));
|
auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct));
|
||||||
ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
|
ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
|
||||||
rga->rid = GetID();
|
rga->rid = GetID();
|
||||||
@ -1539,35 +1546,37 @@ void Raid::MemberZoned(Client *c)
|
|||||||
group_mentor[gid].mentoree = nullptr;
|
group_mentor[gid].mentoree = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Raid::SendHPPacketsTo(Client *c)
|
void Raid::SendHPPacketsTo(Client *client)
|
||||||
{
|
{
|
||||||
if(!c)
|
if(!client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32 gid = this->GetGroup(c);
|
uint32 group_id = this->GetGroup(client);
|
||||||
EQApplicationPacket hpapp;
|
|
||||||
|
EQApplicationPacket hp_packet;
|
||||||
EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct));
|
EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct));
|
||||||
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
|
|
||||||
{
|
for(int x = 0; x < MAX_RAID_MEMBERS; x++) {
|
||||||
if(members[x].member)
|
if(members[x].member) {
|
||||||
{
|
if((members[x].member != client) && (members[x].GroupNumber == group_id)) {
|
||||||
if((members[x].member != c) && (members[x].GroupNumber == gid))
|
|
||||||
{
|
members[x].member->CreateHPPacket(&hp_packet);
|
||||||
members[x].member->CreateHPPacket(&hpapp);
|
client->QueuePacket(&hp_packet, false);
|
||||||
c->QueuePacket(&hpapp, false);
|
safe_delete_array(hp_packet.pBuffer);
|
||||||
safe_delete_array(hpapp.pBuffer);
|
|
||||||
hpapp.size = 0;
|
hp_packet.size = 0;
|
||||||
if (c->ClientVersion() >= EQEmu::versions::ClientVersion::SoD)
|
if (client->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) {
|
||||||
{
|
|
||||||
outapp.SetOpcode(OP_MobManaUpdate);
|
outapp.SetOpcode(OP_MobManaUpdate);
|
||||||
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer;
|
MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer;
|
||||||
mmus->spawn_id = members[x].member->GetID();
|
mana_update->spawn_id = members[x].member->GetID();
|
||||||
mmus->mana = members[x].member->GetManaPercent();
|
mana_update->mana = members[x].member->GetManaPercent();
|
||||||
c->QueuePacket(&outapp, false);
|
client->QueuePacket(&outapp, false);
|
||||||
|
|
||||||
outapp.SetOpcode(OP_MobEnduranceUpdate);
|
outapp.SetOpcode(OP_MobEnduranceUpdate);
|
||||||
MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer;
|
MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer;
|
||||||
meus->endurance = members[x].member->GetEndurancePercent();
|
endurance_update->endurance = members[x].member->GetEndurancePercent();
|
||||||
c->QueuePacket(&outapp, false);
|
client->QueuePacket(&outapp, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user