mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 13:41:31 +00:00
Merge branch 'master' of https://github.com/EQEmu/Server
This commit is contained in:
commit
9f039b47e9
@ -389,6 +389,7 @@ RULE_INT(Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing target
|
||||
RULE_INT(Spells, AI_IdleNoSpellMinRecast, 6000) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random)
|
||||
RULE_INT(Spells, AI_IdleNoSpellMaxRecast, 60000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random)
|
||||
RULE_INT(Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others.
|
||||
RULE_INT(Spells, AI_HealHPPct, 50) // HP Pct NPCs will start heals at (in and out of combat) if spell's max_hp is not set
|
||||
RULE_BOOL(Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false)
|
||||
RULE_BOOL(Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014
|
||||
RULE_BOOL(Spells, SwarmPetTargetLock, false) // Use old method of swarm pets target locking till target dies then despawning.
|
||||
|
||||
93
zone/mob.cpp
93
zone/mob.cpp
@ -253,7 +253,7 @@ Mob::Mob(const char* in_name,
|
||||
max_mana = 0;
|
||||
hp_regen = in_hp_regen;
|
||||
mana_regen = in_mana_regen;
|
||||
oocregen = RuleI(NPC, OOCRegen); //default Out of Combat Regen
|
||||
ooc_regen = RuleI(NPC, OOCRegen); //default Out of Combat Regen
|
||||
maxlevel = in_maxlevel;
|
||||
scalerate = in_scalerate;
|
||||
invisible = false;
|
||||
@ -1303,14 +1303,17 @@ void Mob::CreateHPPacket(EQApplicationPacket* app)
|
||||
}
|
||||
}
|
||||
|
||||
// sends hp update of this mob to people who might care
|
||||
void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= false*/)
|
||||
{
|
||||
void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= false*/) {
|
||||
|
||||
/* If our HP is different from last HP update call - let's update ourself */
|
||||
/**
|
||||
* If our HP is different from last HP update call - let's update selves
|
||||
*/
|
||||
if (IsClient()) {
|
||||
if (cur_hp != last_hp || force_update_all) {
|
||||
/* This is to prevent excessive packet sending under trains/fast combat */
|
||||
|
||||
/**
|
||||
* This is to prevent excessive packet sending under trains/fast combat
|
||||
*/
|
||||
if (this->CastToClient()->hp_self_update_throttle_timer.Check() || force_update_all) {
|
||||
Log(Logs::General, Logs::HP_Update,
|
||||
"Mob::SendHPUpdate :: Update HP of self (%s) HP: %i last: %i skip_self: %s",
|
||||
@ -1322,7 +1325,8 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
|
||||
|
||||
if (!skip_self || this->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) {
|
||||
auto client_packet = new EQApplicationPacket(OP_HPUpdate, sizeof(SpawnHPUpdate_Struct));
|
||||
SpawnHPUpdate_Struct* hp_packet_client = (SpawnHPUpdate_Struct*)client_packet->pBuffer;
|
||||
|
||||
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();
|
||||
@ -1335,7 +1339,9 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
|
||||
ResetHPUpdateTimer();
|
||||
}
|
||||
|
||||
/* Used to check if HP has changed to update self next round */
|
||||
/**
|
||||
* Used to check if HP has changed to update self next round
|
||||
*/
|
||||
last_hp = cur_hp;
|
||||
}
|
||||
}
|
||||
@ -1343,7 +1349,12 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
|
||||
|
||||
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);
|
||||
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 && !force_update_all) {
|
||||
Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: Same HP - skipping update");
|
||||
@ -1352,8 +1363,9 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
|
||||
}
|
||||
else {
|
||||
|
||||
if (IsClient() && RuleB(Character, MarqueeHPUpdates))
|
||||
if (IsClient() && RuleB(Character, MarqueeHPUpdates)) {
|
||||
this->CastToClient()->SendHPUpdateMarquee();
|
||||
}
|
||||
|
||||
Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: HP Changed - Send update");
|
||||
|
||||
@ -1365,48 +1377,65 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
|
||||
|
||||
CreateHPPacket(&hp_packet);
|
||||
|
||||
/* Update those who have us targeted */
|
||||
/**
|
||||
* Update those who have us targeted
|
||||
*/
|
||||
entity_list.QueueClientsByTarget(this, &hp_packet, false, 0, false, true, EQEmu::versions::bit_AllClients);
|
||||
|
||||
/* Update those who have us on x-target */
|
||||
/**
|
||||
* Update those who have us on x-target
|
||||
*/
|
||||
entity_list.QueueClientsByXTarget(this, &hp_packet, false);
|
||||
|
||||
/* Update groups using Group LAA health name tag counter */
|
||||
/**
|
||||
* Update groups using Group LAA health name tag counter
|
||||
*/
|
||||
entity_list.QueueToGroupsForNPCHealthAA(this, &hp_packet);
|
||||
|
||||
/* Update group */
|
||||
if(IsGrouped()) {
|
||||
/**
|
||||
* Group
|
||||
*/
|
||||
if (IsGrouped()) {
|
||||
group = entity_list.GetGroupByMob(this);
|
||||
if(group)
|
||||
if (group) {
|
||||
group->SendHPPacketsFrom(this);
|
||||
}
|
||||
|
||||
/* Update Raid */
|
||||
if(IsClient()){
|
||||
Raid *raid = entity_list.GetRaidByClient(CastToClient());
|
||||
if (raid)
|
||||
raid->SendHPManaEndPacketsFrom(this);
|
||||
}
|
||||
|
||||
/* Pet - Update master - group and raid if exists */
|
||||
if(GetOwner() && GetOwner()->IsClient()) {
|
||||
/**
|
||||
* Raid
|
||||
*/
|
||||
if (IsClient()) {
|
||||
Raid *raid = entity_list.GetRaidByClient(CastToClient());
|
||||
if (raid) {
|
||||
raid->SendHPManaEndPacketsFrom(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pet
|
||||
*/
|
||||
if (GetOwner() && GetOwner()->IsClient()) {
|
||||
GetOwner()->CastToClient()->QueuePacket(&hp_packet, false);
|
||||
group = entity_list.GetGroupByClient(GetOwner()->CastToClient());
|
||||
|
||||
if(group)
|
||||
if (group) {
|
||||
group->SendHPPacketsFrom(this);
|
||||
|
||||
Raid *raid = entity_list.GetRaidByClient(GetOwner()->CastToClient());
|
||||
if(raid)
|
||||
raid->SendHPManaEndPacketsFrom(this);
|
||||
}
|
||||
|
||||
/* Send to pet */
|
||||
if(GetPet() && GetPet()->IsClient()) {
|
||||
Raid *raid = entity_list.GetRaidByClient(GetOwner()->CastToClient());
|
||||
if (raid) {
|
||||
raid->SendHPManaEndPacketsFrom(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetPet() && GetPet()->IsClient()) {
|
||||
GetPet()->CastToClient()->QueuePacket(&hp_packet, false);
|
||||
}
|
||||
|
||||
/* Destructible objects */
|
||||
/**
|
||||
* Destructible objects
|
||||
*/
|
||||
if (IsNPC() && IsDestructibleObject()) {
|
||||
if (GetHPRatio() > 74) {
|
||||
if (GetAppearance() != eaStanding) {
|
||||
|
||||
@ -421,7 +421,7 @@ public:
|
||||
bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) = 0;
|
||||
inline virtual void SetHP(int32 hp) { if (hp >= max_hp) cur_hp = max_hp; else cur_hp = hp;}
|
||||
bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false);
|
||||
inline void SetOOCRegen(int32 newoocregen) {oocregen = newoocregen;}
|
||||
inline void SetOOCRegen(int32 newoocregen) {ooc_regen = newoocregen;}
|
||||
virtual void Heal();
|
||||
virtual void HealDamage(uint32 ammount, Mob* caster = nullptr, uint16 spell_id = SPELL_UNKNOWN);
|
||||
virtual void SetMaxHP() { cur_hp = max_hp; }
|
||||
@ -1223,7 +1223,7 @@ protected:
|
||||
int32 max_mana;
|
||||
int32 hp_regen;
|
||||
int32 mana_regen;
|
||||
int32 oocregen;
|
||||
int32 ooc_regen;
|
||||
uint8 maxlevel;
|
||||
uint32 scalerate;
|
||||
Buffs_Struct *buffs;
|
||||
|
||||
@ -97,10 +97,11 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AIspells[i].min_hp != 0 && GetIntHPRatio() < AIspells[i].min_hp)
|
||||
// we reuse these fields for heal overrides
|
||||
if (AIspells[i].type != SpellType_Heal && AIspells[i].min_hp != 0 && GetIntHPRatio() < AIspells[i].min_hp)
|
||||
continue;
|
||||
|
||||
if (AIspells[i].max_hp != 0 && GetIntHPRatio() > AIspells[i].max_hp)
|
||||
if (AIspells[i].type != SpellType_Heal && AIspells[i].max_hp != 0 && GetIntHPRatio() > AIspells[i].max_hp)
|
||||
continue;
|
||||
|
||||
if (iSpellTypes & AIspells[i].type) {
|
||||
@ -137,9 +138,13 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates
|
||||
&& tar->DontHealMeBefore() < Timer::GetCurrentTime()
|
||||
&& !(tar->IsPet() && tar->GetOwner()->IsClient()) //no buffing PC's pets
|
||||
) {
|
||||
uint8 hpr = (uint8)tar->GetHPRatio();
|
||||
|
||||
if(hpr <= 35 || (!IsEngaged() && hpr <= 50) || (tar->IsClient() && hpr <= 99)) {
|
||||
auto hp_ratio = tar->GetIntHPRatio();
|
||||
|
||||
int min_hp = AIspells[i].min_hp; // well 0 is default, so no special case here
|
||||
int max_hp = AIspells[i].max_hp ? AIspells[i].max_hp : RuleI(Spells, AI_HealHPPct);
|
||||
|
||||
if (EQEmu::ValueWithin(hp_ratio, min_hp, max_hp) || (tar->IsClient() && hp_ratio <= 99)) { // not sure about client bit, leaving it
|
||||
uint32 tempTime = 0;
|
||||
AIDoSpellCast(i, tar, mana_cost, &tempTime);
|
||||
tar->SetDontHealMeBefore(tempTime);
|
||||
|
||||
91
zone/npc.cpp
91
zone/npc.cpp
@ -667,77 +667,78 @@ bool NPC::Process()
|
||||
parse->EventNPC(EVENT_TICK, this, nullptr, "", 0);
|
||||
BuffProcess();
|
||||
|
||||
if (currently_fleeing)
|
||||
if (currently_fleeing) {
|
||||
ProcessFlee();
|
||||
|
||||
uint32 sitting_bonus = 0;
|
||||
uint32 petbonus = 0;
|
||||
uint32 bestregen = 0;
|
||||
int32 dbregen = GetNPCHPRegen();
|
||||
|
||||
if (GetAppearance() == eaSitting)
|
||||
sitting_bonus += 3;
|
||||
|
||||
int32 OOCRegen = 0;
|
||||
if (oocregen > 0) { //should pull from Mob class
|
||||
OOCRegen += GetMaxHP() * oocregen / 100;
|
||||
}
|
||||
|
||||
// Fixing NPC regen.NPCs should regen to full during
|
||||
// a set duration, not based on their HPs.Increase NPC's HPs by
|
||||
// % of total HPs / tick.
|
||||
//
|
||||
// If oocregen set in db, apply to pets as well.
|
||||
// This allows the obscene #s for pets in the db to be tweaked
|
||||
// while maintaining a decent ooc regen.
|
||||
uint32 npc_sitting_regen_bonus = 0;
|
||||
uint32 pet_regen_bonus = 0;
|
||||
uint32 npc_regen = 0;
|
||||
int32 npc_hp_regen = GetNPCHPRegen();
|
||||
|
||||
bestregen = std::max(dbregen,OOCRegen);
|
||||
if (GetAppearance() == eaSitting) {
|
||||
npc_sitting_regen_bonus += 3;
|
||||
}
|
||||
|
||||
int32 ooc_regen_calc = 0;
|
||||
if (ooc_regen > 0) { //should pull from Mob class
|
||||
ooc_regen_calc += GetMaxHP() * ooc_regen / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use max value between two values
|
||||
*/
|
||||
npc_regen = std::max(npc_hp_regen, ooc_regen_calc);
|
||||
|
||||
if ((GetHP() < GetMaxHP()) && !IsPet()) {
|
||||
if (!IsEngaged())
|
||||
SetHP(GetHP() + bestregen + sitting_bonus);
|
||||
else
|
||||
SetHP(GetHP() + dbregen);
|
||||
if (!IsEngaged()) {
|
||||
SetHP(GetHP() + npc_regen + npc_sitting_regen_bonus);
|
||||
}
|
||||
else {
|
||||
SetHP(GetHP() + npc_hp_regen);
|
||||
}
|
||||
}
|
||||
else if (GetHP() < GetMaxHP() && GetOwnerID() != 0) {
|
||||
if (!IsEngaged()) {
|
||||
if (oocregen > 0) {
|
||||
petbonus = std::max(OOCRegen,dbregen);
|
||||
if (ooc_regen > 0) {
|
||||
pet_regen_bonus = std::max(ooc_regen_calc, npc_hp_regen);
|
||||
}
|
||||
else {
|
||||
petbonus = dbregen + (GetLevel() / 5);
|
||||
pet_regen_bonus = npc_hp_regen + (GetLevel() / 5);
|
||||
}
|
||||
|
||||
SetHP(GetHP() + sitting_bonus + petbonus);
|
||||
SetHP(GetHP() + npc_sitting_regen_bonus + pet_regen_bonus);
|
||||
}
|
||||
else
|
||||
SetHP(GetHP() + dbregen);
|
||||
else {
|
||||
SetHP(GetHP() + npc_hp_regen);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
SetHP(GetHP() + npc_hp_regen + npc_sitting_regen_bonus);
|
||||
}
|
||||
else
|
||||
SetHP(GetHP() + dbregen + sitting_bonus);
|
||||
|
||||
if (GetMana() < GetMaxMana()) {
|
||||
SetMana(GetMana() + mana_regen + sitting_bonus);
|
||||
SetMana(GetMana() + mana_regen + npc_sitting_regen_bonus);
|
||||
}
|
||||
|
||||
SendHPUpdate();
|
||||
|
||||
if (zone->adv_data && !p_depop)
|
||||
{
|
||||
ServerZoneAdventureDataReply_Struct* ds = (ServerZoneAdventureDataReply_Struct*)zone->adv_data;
|
||||
if (ds->type == Adventure_Rescue && ds->data_id == GetNPCTypeID())
|
||||
{
|
||||
if (zone->adv_data && !p_depop) {
|
||||
ServerZoneAdventureDataReply_Struct *ds = (ServerZoneAdventureDataReply_Struct *) zone->adv_data;
|
||||
if (ds->type == Adventure_Rescue && ds->data_id == GetNPCTypeID()) {
|
||||
Mob *o = GetOwner();
|
||||
if (o && o->IsClient())
|
||||
{
|
||||
if (o && o->IsClient()) {
|
||||
float x_diff = ds->dest_x - GetX();
|
||||
float y_diff = ds->dest_y - GetY();
|
||||
float z_diff = ds->dest_z - GetZ();
|
||||
float dist = ((x_diff * x_diff) + (y_diff * y_diff) + (z_diff * z_diff));
|
||||
if (dist < RuleR(Adventure, DistanceForRescueComplete))
|
||||
{
|
||||
if (dist < RuleR(Adventure, DistanceForRescueComplete)) {
|
||||
zone->DoAdventureCountIncrease();
|
||||
Say("You don't know what this means to me. Thank you so much for finding and saving me from"
|
||||
" this wretched place. I'll find my way from here.");
|
||||
Say(
|
||||
"You don't know what this means to me. Thank you so much for finding and saving me from"
|
||||
" this wretched place. I'll find my way from here."
|
||||
);
|
||||
Depop();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user