mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-16 01:01:30 +00:00
[Spells] Implemented SPA 281 SE_PetFeignMinion (#1900)
* start * update * debugs in * test * clean up * debugs removed * Update mob_ai.cpp * Update spdat.h * [Spells] Implemented SPA 281 SE_PetFeignMinion debug remoevd * [Spells] Implemented SPA 281 SE_PetFeignMinion npc forget timer * [Spells] Implemented SPA 281 SE_PetFeignMinion
This commit is contained in:
parent
7f23c93ce5
commit
323b35989c
@ -26,6 +26,7 @@
|
||||
#define SPELLBOOK_UNKNOWN 0xFFFFFFFF //player profile spells are 32 bit
|
||||
|
||||
//some spell IDs which will prolly change, but are needed
|
||||
#define SPELL_LIFEBURN 2755
|
||||
#define SPELL_LEECH_TOUCH 2766
|
||||
#define SPELL_LAY_ON_HANDS 87
|
||||
#define SPELL_HARM_TOUCH 88
|
||||
@ -998,7 +999,7 @@ typedef enum {
|
||||
#define SE_FinishingBlow 278 // implemented[AA] - chance to do massive damage under 10% HP (base1 = chance, base2 = damage)
|
||||
#define SE_Flurry 279 // implemented
|
||||
#define SE_PetFlurry 280 // implemented[AA]
|
||||
#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance
|
||||
#define SE_FeignedMinion 281 // implemented, ability allows you to instruct your pet to feign death via the '/pet feign' command, base: succeed chance, limit: none, max: none, Note: Only implemented as an AA.
|
||||
#define SE_ImprovedBindWound 282 // implemented[AA] - increase bind wound amount by percent.
|
||||
#define SE_DoubleSpecialAttack 283 // implemented[AA] - Chance to perform second special attack as monk
|
||||
//#define SE_LoHSetHeal 284 // not used
|
||||
|
||||
@ -1402,45 +1402,62 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib
|
||||
return std::max(0, AggroAmount);
|
||||
}
|
||||
|
||||
void Mob::AddFeignMemory(Client* attacker) {
|
||||
if(feign_memory_list.empty() && AI_feign_remember_timer != nullptr)
|
||||
void Mob::AddFeignMemory(Mob* attacker) {
|
||||
if (feign_memory_list.empty() && AI_feign_remember_timer != nullptr) {
|
||||
AI_feign_remember_timer->Start(AIfeignremember_delay);
|
||||
feign_memory_list.insert(attacker->CharacterID());
|
||||
}
|
||||
|
||||
if (attacker) {
|
||||
feign_memory_list.insert(attacker->GetID());
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::RemoveFromFeignMemory(Client* attacker) {
|
||||
feign_memory_list.erase(attacker->CharacterID());
|
||||
if(feign_memory_list.empty() && AI_feign_remember_timer != nullptr)
|
||||
void Mob::RemoveFromFeignMemory(Mob* attacker) {
|
||||
|
||||
if (!attacker) {
|
||||
return;
|
||||
}
|
||||
|
||||
feign_memory_list.erase(attacker->GetID());
|
||||
if (feign_memory_list.empty() && AI_feign_remember_timer != nullptr) {
|
||||
AI_feign_remember_timer->Disable();
|
||||
}
|
||||
if(feign_memory_list.empty())
|
||||
{
|
||||
minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin);
|
||||
maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax);
|
||||
if(AI_feign_remember_timer != nullptr)
|
||||
if (AI_feign_remember_timer != nullptr) {
|
||||
AI_feign_remember_timer->Disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::ClearFeignMemory() {
|
||||
auto RememberedCharID = feign_memory_list.begin();
|
||||
while (RememberedCharID != feign_memory_list.end())
|
||||
auto remembered_feigned_mobid = feign_memory_list.begin();
|
||||
while (remembered_feigned_mobid != feign_memory_list.end())
|
||||
{
|
||||
Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID);
|
||||
if(remember_client != nullptr) //Still in zone
|
||||
remember_client->RemoveXTarget(this, false);
|
||||
++RememberedCharID;
|
||||
Mob* remembered_mob = entity_list.GetMob(*remembered_feigned_mobid);
|
||||
if (remembered_mob->IsClient() && remembered_mob != nullptr) { //Still in zone
|
||||
remembered_mob->CastToClient()->RemoveXTarget(this, false);
|
||||
}
|
||||
++remembered_feigned_mobid;
|
||||
}
|
||||
|
||||
feign_memory_list.clear();
|
||||
minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin);
|
||||
maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax);
|
||||
if(AI_feign_remember_timer != nullptr)
|
||||
if (AI_feign_remember_timer != nullptr) {
|
||||
AI_feign_remember_timer->Disable();
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::IsOnFeignMemory(Client *attacker) const
|
||||
bool Mob::IsOnFeignMemory(Mob *attacker) const
|
||||
{
|
||||
return feign_memory_list.find(attacker->CharacterID()) != feign_memory_list.end();
|
||||
if (!attacker) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return feign_memory_list.find(attacker->GetID()) != feign_memory_list.end();
|
||||
}
|
||||
|
||||
bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) {
|
||||
|
||||
@ -2813,7 +2813,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
|
||||
hate_list.AddEntToHateList(other, hate, damage, bFrenzy, !iBuffTic);
|
||||
|
||||
if (other->IsClient() && !on_hatelist && !IsOnFeignMemory(other->CastToClient()))
|
||||
if (other->IsClient() && !on_hatelist && !IsOnFeignMemory(other))
|
||||
other->CastToClient()->AddAutoXTarget(this);
|
||||
|
||||
#ifdef BOTS
|
||||
|
||||
@ -1571,8 +1571,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
break;
|
||||
|
||||
case SE_FeignedMinion:
|
||||
if (newbon->FeignedMinionChance < base_value)
|
||||
if (newbon->FeignedMinionChance < base_value) {
|
||||
newbon->FeignedMinionChance = base_value;
|
||||
}
|
||||
newbon->PetCommands[PET_FEIGN] = true;
|
||||
break;
|
||||
|
||||
case SE_AdditionalAura:
|
||||
|
||||
@ -145,7 +145,6 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
global_channel_timer(1000),
|
||||
fishing_timer(8000),
|
||||
endupkeep_timer(1000),
|
||||
forget_timer(0),
|
||||
autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000),
|
||||
client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckIdleInterval)),
|
||||
client_zone_wide_full_position_update_timer(5 * 60 * 1000),
|
||||
@ -186,7 +185,6 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
character_id = 0;
|
||||
conn_state = NoPacketsReceived;
|
||||
client_data_loaded = false;
|
||||
feigned = false;
|
||||
berserk = false;
|
||||
dead = false;
|
||||
eqs = ieqs;
|
||||
@ -2677,22 +2675,6 @@ void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing, uint32 re
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::SetFeigned(bool in_feigned) {
|
||||
if (in_feigned)
|
||||
{
|
||||
if(RuleB(Character, FeignKillsPet))
|
||||
{
|
||||
SetPet(0);
|
||||
}
|
||||
SetHorseId(0);
|
||||
entity_list.ClearFeignAggro(this);
|
||||
forget_timer.Start(FeignMemoryDuration);
|
||||
} else {
|
||||
forget_timer.Disable();
|
||||
}
|
||||
feigned=in_feigned;
|
||||
}
|
||||
|
||||
void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQ::ItemData* item, bool buying)
|
||||
{
|
||||
if(!player || !merchant || !item)
|
||||
|
||||
@ -835,9 +835,6 @@ public:
|
||||
inline uint8 GetBecomeNPCLevel() const { return npclevel; }
|
||||
inline void SetBecomeNPC(bool flag) { npcflag = flag; }
|
||||
inline void SetBecomeNPCLevel(uint8 level) { npclevel = level; }
|
||||
void SetFeigned(bool in_feigned);
|
||||
/// this cures timing issues cuz dead animation isn't done but server side feigning is?
|
||||
inline bool GetFeigned() const { return(feigned); }
|
||||
EQStreamInterface* Connection() { return eqs; }
|
||||
#ifdef PACKET_PROFILER
|
||||
void DumpPacketProfile() { if(eqs) eqs->DumpPacketProfile(); }
|
||||
@ -1850,7 +1847,6 @@ private:
|
||||
Timer global_channel_timer;
|
||||
Timer fishing_timer;
|
||||
Timer endupkeep_timer;
|
||||
Timer forget_timer; // our 2 min everybody forgets you timer
|
||||
Timer autosave_timer;
|
||||
Timer client_scan_npc_aggro_timer;
|
||||
Timer client_zone_wide_full_position_update_timer;
|
||||
@ -1890,7 +1886,6 @@ private:
|
||||
|
||||
bool npcflag;
|
||||
uint8 npclevel;
|
||||
bool feigned;
|
||||
bool bZoning;
|
||||
bool tgb;
|
||||
bool instalog;
|
||||
|
||||
@ -10255,6 +10255,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
|
||||
if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) {
|
||||
if (target != this && DistanceSquaredNoZ(mypet->GetPosition(), target->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) {
|
||||
mypet->SetFeigned(false);
|
||||
if (mypet->IsPetStop()) {
|
||||
mypet->SetPetStop(false);
|
||||
SetPetCommandState(PET_BUTTON_STOP, 0);
|
||||
@ -10301,6 +10302,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
|
||||
if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) {
|
||||
if (GetTarget() != this && DistanceSquaredNoZ(mypet->GetPosition(), GetTarget()->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) {
|
||||
mypet->SetFeigned(false);
|
||||
if (mypet->IsPetStop()) {
|
||||
mypet->SetPetStop(false);
|
||||
SetPetCommandState(PET_BUTTON_STOP, 0);
|
||||
@ -10376,6 +10378,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
if (mypet->IsNPC()) {
|
||||
|
||||
// Set Sit button to unpressed - send stand anim/end hpregen
|
||||
mypet->SetFeigned(false);
|
||||
SetPetCommandState(PET_BUTTON_SIT, 0);
|
||||
mypet->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
||||
|
||||
@ -10396,6 +10399,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF
|
||||
|
||||
if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) {
|
||||
mypet->SetFeigned(false);
|
||||
mypet->SayString(this, Chat::PetResponse, PET_FOLLOWING);
|
||||
mypet->SetPetOrder(SPO_Follow);
|
||||
|
||||
@ -10443,6 +10447,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF
|
||||
|
||||
if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) {
|
||||
mypet->SetFeigned(false);
|
||||
mypet->SayString(this, Chat::PetResponse, PET_GUARDME_STRING);
|
||||
mypet->SetPetOrder(SPO_Follow);
|
||||
|
||||
@ -10463,12 +10468,14 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) {
|
||||
if (mypet->GetPetOrder() == SPO_Sit)
|
||||
{
|
||||
mypet->SetFeigned(false);
|
||||
mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING);
|
||||
mypet->SetPetOrder(SPO_Follow);
|
||||
mypet->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
||||
}
|
||||
else
|
||||
{
|
||||
mypet->SetFeigned(false);
|
||||
mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING);
|
||||
mypet->SetPetOrder(SPO_Sit);
|
||||
mypet->SetRunAnimSpeed(0);
|
||||
@ -10483,6 +10490,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF
|
||||
|
||||
if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) {
|
||||
mypet->SetFeigned(false);
|
||||
mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING);
|
||||
SetPetCommandState(PET_BUTTON_SIT, 0);
|
||||
mypet->SetPetOrder(SPO_Follow);
|
||||
@ -10494,6 +10502,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF
|
||||
|
||||
if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) {
|
||||
mypet->SetFeigned(false);
|
||||
mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING);
|
||||
SetPetCommandState(PET_BUTTON_SIT, 1);
|
||||
mypet->SetPetOrder(SPO_Sit);
|
||||
@ -10687,6 +10696,38 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PET_FEIGN: {
|
||||
if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) {
|
||||
if (mypet->IsFeared())
|
||||
break;
|
||||
|
||||
int pet_fd_chance = aabonuses.FeignedMinionChance;
|
||||
if (zone->random.Int(0, 99) > pet_fd_chance) {
|
||||
mypet->SetFeigned(false);
|
||||
entity_list.MessageCloseString(this, false, 200, 10, STRING_FEIGNFAILED, mypet->GetCleanName());
|
||||
}
|
||||
else {
|
||||
bool immune_aggro = GetSpecialAbility(IMMUNE_AGGRO);
|
||||
mypet->SetSpecialAbility(IMMUNE_AGGRO, 1);
|
||||
mypet->WipeHateList();
|
||||
mypet->SetPetOrder(SPO_FeignDeath);
|
||||
mypet->SetRunAnimSpeed(0);
|
||||
mypet->StopNavigation();
|
||||
mypet->SendAppearancePacket(AT_Anim, ANIM_DEATH);
|
||||
mypet->SetFeigned(true);
|
||||
mypet->SetTarget(nullptr);
|
||||
if (!mypet->UseBardSpellLogic()) {
|
||||
mypet->InterruptSpell();
|
||||
}
|
||||
|
||||
if (!immune_aggro) {
|
||||
mypet->SetSpecialAbility(IMMUNE_AGGRO, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PET_STOP: {
|
||||
if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF
|
||||
|
||||
@ -10694,7 +10735,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
if (mypet->IsPetStop()) {
|
||||
mypet->SetPetStop(false);
|
||||
} else {
|
||||
mypet->SetPetStop(true);
|
||||
mypet->StopNavigation();
|
||||
mypet->SetTarget(nullptr);
|
||||
if (mypet->IsPetRegroup()) {
|
||||
|
||||
@ -1515,10 +1515,10 @@ void EntityList::RemoveFromTargets(Mob *mob, bool RemoveFromXTargets)
|
||||
continue;
|
||||
|
||||
if (RemoveFromXTargets) {
|
||||
if (m->IsClient() && (mob->CheckAggro(m) || mob->IsOnFeignMemory(m->CastToClient())))
|
||||
if (m->IsClient() && (mob->CheckAggro(m) || mob->IsOnFeignMemory(m)))
|
||||
m->CastToClient()->RemoveXTarget(mob, false);
|
||||
// FadingMemories calls this function passing the client.
|
||||
else if (mob->IsClient() && (m->CheckAggro(mob) || m->IsOnFeignMemory(mob->CastToClient())))
|
||||
else if (mob->IsClient() && (m->CheckAggro(mob) || m->IsOnFeignMemory(mob)))
|
||||
mob->CastToClient()->RemoveXTarget(m, false);
|
||||
}
|
||||
|
||||
@ -3488,7 +3488,7 @@ void EntityList::ClearFeignAggro(Mob *targ)
|
||||
auto it = npc_list.begin();
|
||||
while (it != npc_list.end()) {
|
||||
// add Feign Memory check because sometimes weird stuff happens
|
||||
if (it->second->CheckAggro(targ) || (targ->IsClient() && it->second->IsOnFeignMemory(targ->CastToClient()))) {
|
||||
if (it->second->CheckAggro(targ) || (targ->IsClient() && it->second->IsOnFeignMemory(targ))) {
|
||||
if (it->second->GetSpecialAbility(IMMUNE_FEIGN_DEATH)) {
|
||||
++it;
|
||||
continue;
|
||||
@ -3514,22 +3514,31 @@ void EntityList::ClearFeignAggro(Mob *targ)
|
||||
|
||||
it->second->RemoveFromHateList(targ);
|
||||
if (targ->IsClient()) {
|
||||
if (it->second->GetLevel() >= 35 && zone->random.Roll(60))
|
||||
it->second->AddFeignMemory(targ->CastToClient());
|
||||
else
|
||||
if (it->second->GetLevel() >= 35 && zone->random.Roll(60)) {
|
||||
it->second->AddFeignMemory(targ);
|
||||
}
|
||||
else {
|
||||
targ->CastToClient()->RemoveXTarget(it->second, false);
|
||||
}
|
||||
}
|
||||
else if (targ->IsPet()){
|
||||
if (it->second->GetLevel() >= 35 && zone->random.Roll(60)) {
|
||||
it->second->AddFeignMemory(targ);
|
||||
}
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::ClearZoneFeignAggro(Client *targ)
|
||||
void EntityList::ClearZoneFeignAggro(Mob *targ)
|
||||
{
|
||||
auto it = npc_list.begin();
|
||||
while (it != npc_list.end()) {
|
||||
it->second->RemoveFromFeignMemory(targ);
|
||||
targ->CastToClient()->RemoveXTarget(it->second, false);
|
||||
if (targ && targ->IsClient()) {
|
||||
targ->CastToClient()->RemoveXTarget(it->second, false);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,7 +455,7 @@ public:
|
||||
void ClearAggro(Mob* targ);
|
||||
void ClearWaterAggro(Mob* targ);
|
||||
void ClearFeignAggro(Mob* targ);
|
||||
void ClearZoneFeignAggro(Client* targ);
|
||||
void ClearZoneFeignAggro(Mob* targ);
|
||||
void AggroZone(Mob* who, uint32 hate = 0);
|
||||
|
||||
bool Fighting(Mob* targ);
|
||||
|
||||
21
zone/mob.cpp
21
zone/mob.cpp
@ -109,6 +109,7 @@ Mob::Mob(
|
||||
stunned_timer(0),
|
||||
spun_timer(0),
|
||||
bardsong_timer(6000),
|
||||
forget_timer(0),
|
||||
gravity_timer(1000),
|
||||
viral_timer(0),
|
||||
m_FearWalkTarget(-999999.0f, -999999.0f, -999999.0f),
|
||||
@ -282,6 +283,8 @@ Mob::Mob(
|
||||
|
||||
InitializeBuffSlots();
|
||||
|
||||
feigned = false;
|
||||
|
||||
// clear the proc arrays
|
||||
for (int j = 0; j < MAX_PROCS; j++) {
|
||||
PermaProcs[j].spellID = SPELL_UNKNOWN;
|
||||
@ -6505,6 +6508,24 @@ void Mob::ShieldAbilityClearVariables()
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::SetFeigned(bool in_feigned) {
|
||||
|
||||
if (in_feigned) {
|
||||
if (IsClient()) {
|
||||
if (RuleB(Character, FeignKillsPet)){
|
||||
SetPet(0);
|
||||
}
|
||||
CastToClient()->SetHorseId(0);
|
||||
}
|
||||
entity_list.ClearFeignAggro(this);
|
||||
forget_timer.Start(FeignMemoryDuration);
|
||||
}
|
||||
else {
|
||||
forget_timer.Disable();
|
||||
}
|
||||
feigned = in_feigned;
|
||||
}
|
||||
|
||||
#ifdef BOTS
|
||||
bool Mob::JoinHealRotationTargetPool(std::shared_ptr<HealRotation>* heal_rotation)
|
||||
{
|
||||
|
||||
17
zone/mob.h
17
zone/mob.h
@ -71,7 +71,7 @@ class Mob : public Entity {
|
||||
public:
|
||||
enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD,
|
||||
CLIENT_KICKED, DISCONNECTED, CLIENT_ERROR, CLIENT_CONNECTINGALL };
|
||||
enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard };
|
||||
enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath };
|
||||
|
||||
struct SpecialAbility {
|
||||
SpecialAbility() {
|
||||
@ -670,10 +670,10 @@ public:
|
||||
bool HateSummon();
|
||||
void FaceTarget(Mob* mob_to_face = 0);
|
||||
void WipeHateList();
|
||||
void AddFeignMemory(Client* attacker);
|
||||
void RemoveFromFeignMemory(Client* attacker);
|
||||
void AddFeignMemory(Mob* attacker);
|
||||
void RemoveFromFeignMemory(Mob* attacker);
|
||||
void ClearFeignMemory();
|
||||
bool IsOnFeignMemory(Client *attacker) const;
|
||||
bool IsOnFeignMemory(Mob *attacker) const;
|
||||
void PrintHateListToClient(Client *who) { hate_list.PrintHateListToClient(who); }
|
||||
std::list<struct_HateList*>& GetHateList() { return hate_list.GetHateList(); }
|
||||
std::list<struct_HateList*> GetHateListByDistance(int distance = 0) { return hate_list.GetHateListByDistance(distance); }
|
||||
@ -1296,6 +1296,10 @@ public:
|
||||
bool CanOpenDoors() const;
|
||||
void SetCanOpenDoors(bool can_open);
|
||||
|
||||
void SetFeigned(bool in_feigned);
|
||||
/// this cures timing issues cuz dead animation isn't done but server side feigning is?
|
||||
inline bool GetFeigned() const { return(feigned); }
|
||||
|
||||
void DeleteBucket(std::string bucket_name);
|
||||
std::string GetBucket(std::string bucket_name);
|
||||
std::string GetBucketExpires(std::string bucket_name);
|
||||
@ -1720,6 +1724,9 @@ protected:
|
||||
AuraMgr aura_mgr;
|
||||
AuraMgr trap_mgr;
|
||||
|
||||
bool feigned;
|
||||
Timer forget_timer; // our 2 min everybody forgets you timer
|
||||
|
||||
bool m_can_open_doors;
|
||||
|
||||
MobMovementManager *mMovementManager;
|
||||
@ -1727,7 +1734,7 @@ protected:
|
||||
private:
|
||||
void _StopSong(); //this is not what you think it is
|
||||
Mob* target;
|
||||
|
||||
|
||||
|
||||
#ifdef BOTS
|
||||
std::shared_ptr<HealRotation> m_target_of_heal_rotation;
|
||||
|
||||
@ -838,20 +838,21 @@ void Client::AI_Process()
|
||||
else
|
||||
{
|
||||
if(AI_feign_remember_timer->Check()) {
|
||||
std::set<uint32>::iterator RememberedCharID;
|
||||
RememberedCharID = feign_memory_list.begin();
|
||||
while (RememberedCharID != feign_memory_list.end()) {
|
||||
Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID);
|
||||
if (remember_client == nullptr) {
|
||||
std::set<uint32>::iterator remembered_feigned_mobid;
|
||||
remembered_feigned_mobid = feign_memory_list.begin();
|
||||
while (remembered_feigned_mobid != feign_memory_list.end()) {
|
||||
|
||||
Mob* remembered_mob = entity_list.GetMob(*remembered_feigned_mobid);
|
||||
if (remembered_mob == nullptr || remembered_mob->IsCorpse()) {
|
||||
//they are gone now...
|
||||
RememberedCharID = feign_memory_list.erase(RememberedCharID);
|
||||
} else if (!remember_client->GetFeigned()) {
|
||||
AddToHateList(remember_client->CastToMob(),1);
|
||||
RememberedCharID = feign_memory_list.erase(RememberedCharID);
|
||||
remembered_feigned_mobid = feign_memory_list.erase(remembered_feigned_mobid);
|
||||
} else if (!remembered_mob->GetFeigned()) {
|
||||
AddToHateList(remembered_mob,1);
|
||||
remembered_feigned_mobid = feign_memory_list.erase(remembered_feigned_mobid);
|
||||
break;
|
||||
} else {
|
||||
//they are still feigned, carry on...
|
||||
++RememberedCharID;
|
||||
++remembered_feigned_mobid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1373,22 +1374,22 @@ void Mob::AI_Process() {
|
||||
// 6/14/06
|
||||
// Improved Feign Death Memory
|
||||
// check to see if any of our previous feigned targets have gotten up.
|
||||
std::set<uint32>::iterator RememberedCharID;
|
||||
RememberedCharID = feign_memory_list.begin();
|
||||
while (RememberedCharID != feign_memory_list.end()) {
|
||||
Client *remember_client = entity_list.GetClientByCharID(*RememberedCharID);
|
||||
if (remember_client == nullptr) {
|
||||
std::set<uint32>::iterator remembered_feigned_mobid;
|
||||
remembered_feigned_mobid = feign_memory_list.begin();
|
||||
while (remembered_feigned_mobid != feign_memory_list.end()) {
|
||||
Mob *remembered_mob = entity_list.GetMob(*remembered_feigned_mobid);
|
||||
if (remembered_mob == nullptr || remembered_mob->IsCorpse()) {
|
||||
//they are gone now...
|
||||
RememberedCharID = feign_memory_list.erase(RememberedCharID);
|
||||
remembered_feigned_mobid = feign_memory_list.erase(remembered_feigned_mobid);
|
||||
}
|
||||
else if (!remember_client->GetFeigned()) {
|
||||
AddToHateList(remember_client->CastToMob(), 1);
|
||||
RememberedCharID = feign_memory_list.erase(RememberedCharID);
|
||||
else if (!remembered_mob->GetFeigned()) {
|
||||
AddToHateList(remembered_mob, 1);
|
||||
remembered_feigned_mobid = feign_memory_list.erase(remembered_feigned_mobid);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
//they are still feigned, carry on...
|
||||
++RememberedCharID;
|
||||
++remembered_feigned_mobid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1485,6 +1486,10 @@ void Mob::AI_Process() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPO_FeignDeath: {
|
||||
SetAppearance(eaDead, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (IsPetRegroup()) {
|
||||
return;
|
||||
@ -1557,6 +1562,11 @@ void Mob::AI_Process() {
|
||||
}
|
||||
}
|
||||
|
||||
if (forget_timer.Check()) {
|
||||
forget_timer.Disable();
|
||||
entity_list.ClearZoneFeignAggro(this);
|
||||
}
|
||||
|
||||
//Do Ranged attack here
|
||||
if (doranged) {
|
||||
RangedAttack(target);
|
||||
|
||||
@ -1557,18 +1557,17 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "Feign Death");
|
||||
#endif
|
||||
//todo, look up spell ID in DB
|
||||
if(spell_id == 2488) //Dook- Lifeburn fix
|
||||
if(spell_id == SPELL_LIFEBURN) //Dook- Lifeburn fix
|
||||
break;
|
||||
|
||||
if(IsClient()) {
|
||||
CastToClient()->SetHorseId(0); // dismount if have horse
|
||||
|
||||
if (zone->random.Int(0, 99) > spells[spell_id].base_value[i]) {
|
||||
CastToClient()->SetFeigned(false);
|
||||
SetFeigned(false);
|
||||
entity_list.MessageCloseString(this, false, 200, 10, STRING_FEIGNFAILED, GetName());
|
||||
} else {
|
||||
CastToClient()->SetFeigned(true);
|
||||
SetFeigned(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user