diff --git a/common/spdat.h b/common/spdat.h index 91bacaebf..b39ee4904 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -514,7 +514,7 @@ typedef enum { #define SE_StackingCommand_Block 148 // implemented? #define SE_StackingCommand_Overwrite 149 // implemented? #define SE_DeathSave 150 // implemented -#define SE_SuspendPet 151 // *not implemented as bonus +#define SE_SuspendPet 151 // implemented, @Pet, allow caster to have an extra suspended pet, base: 0=no buffs/items 1=buffs+items, limit: none, max: none #define SE_TemporaryPets 152 // implemented #define SE_BalanceHP 153 // implemented #define SE_DispelDetrimental 154 // implemented @@ -671,7 +671,7 @@ typedef enum { #define SE_MitigateDamageShield 305 // implemented - off hand attacks only (Shielding Resistance) //#define SE_ArmyOfTheDead 306 // *not implemented NecroAA - This ability calls up to five shades of nearby corpses back to life to serve the necromancer. The soulless abominations will mindlessly fight the target until called back to the afterlife some time later. The first rank summons up to three shades that serve for 60 seconds, and each additional rank adds one more possible shade and increases their duration by 15 seconds //#define SE_Appraisal 307 // *not implemented Rogue AA - This ability allows you to estimate the selling price of an item you are holding on your cursor. -#define SE_SuspendMinion 308 // implemented +#define SE_ZoneSuspendMinion 308 // implemented, @Pet, allow suspended pets to be resummoned upon zoning, base: 1, limit: none, max: none, Calc: Bool #define SE_GateCastersBindpoint 309 // implemented - Gate to casters bind point #define SE_ReduceReuseTimer 310 // implemented, @Fc, On Caster, disc reuse time mod, base: milliseconds #define SE_LimitCombatSkills 311 // implemented, @Ff, Include or exclude combat skills or procs (non-memorizable spells) from being focused, base1: 0=Exclude if proc 1=Allow only if proc diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 4b3d8e340..68e35a9bf 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1658,6 +1658,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->ItemEnduranceRegenCap += base1; break; + case SE_ZoneSuspendMinion: + newbon->ZoneSuspendMinion = base1; + break; + // to do case SE_PetDiscipline: break; @@ -3648,6 +3652,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } + case SE_ZoneSuspendMinion: + new_bonus->ZoneSuspendMinion = effect_value; + break; + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/client.cpp b/zone/client.cpp index 040601ad0..a90d424fa 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -5596,18 +5596,20 @@ void Client::AddLDoNWin(uint32 theme_id) } -void Client::SuspendMinion() +void Client::SuspendMinion(int value) { + /* + SPA 151 Allows an extra pet to be saved and resummoned later. + Casting with a pet but without a suspended pet will suspend the pet + Casting without a pet and with a suspended pet will unsuspend the pet + effect value 0 = save pet with no buffs or equipment + effect value 1 = save pet with buffs and equipment + effect value 2 = unknown + Note: SPA 308 allows for suspended pets to be resummoned after zoning. + */ + NPC *CurrentPet = GetPet()->CastToNPC(); - int AALevel = GetAA(aaSuspendedMinion); - - if(AALevel == 0) - return; - - if(GetLevel() < 62) - return; - if(!CurrentPet) { if(m_suspendedminion.SpellID > 0) @@ -5629,7 +5631,7 @@ void Client::SuspendMinion() return; } - if(AALevel >= 2) + if(value >= 1) { CurrentPet->SetPetState(m_suspendedminion.Buffs, m_suspendedminion.Items); @@ -5698,7 +5700,7 @@ void Client::SuspendMinion() m_suspendedminion.petpower = CurrentPet->GetPetPower(); m_suspendedminion.size = CurrentPet->GetSize(); - if(AALevel >= 2) + if(value >= 1) CurrentPet->GetPetState(m_suspendedminion.Buffs, m_suspendedminion.Items, m_suspendedminion.Name); else strn0cpy(m_suspendedminion.Name, CurrentPet->GetName(), 64); // Name stays even at rank 1 diff --git a/zone/client.h b/zone/client.h index ff80cebc7..004e905da 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1383,7 +1383,7 @@ public: uint32 GetCorpseCount() { return database.GetCharacterCorpseCount(CharacterID()); } uint32 GetCorpseID(int corpse) { return database.GetCharacterCorpseID(CharacterID(), corpse); } uint32 GetCorpseItemAt(int corpse_id, int slot_id) { return database.GetCharacterCorpseItemAt(corpse_id, slot_id); } - void SuspendMinion(); + void SuspendMinion(int value); void Doppelganger(uint16 spell_id, Mob *target, const char *name_override, int pet_count, int pet_duration); void NotifyNewTitlesAvailable(); void Signal(uint32 data); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 50d3cd375..64d45bb06 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1659,8 +1659,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_petinfo.SpellID = 0; } /* Moved here so it's after where we load the pet data. */ - if (!GetAA(aaPersistentMinion)) + if (!aabonuses.ZoneSuspendMinion && !spellbonuses.ZoneSuspendMinion && !itembonuses.ZoneSuspendMinion) { memset(&m_suspendedminion, 0, sizeof(PetInfo)); + } /* Server Zone Entry Packet */ outapp = new EQApplicationPacket(OP_ZoneEntry, sizeof(ServerZoneEntry_Struct)); diff --git a/zone/common.h b/zone/common.h index e107d0abe..0561ebb36 100644 --- a/zone/common.h +++ b/zone/common.h @@ -553,7 +553,7 @@ struct StatBonuses { int32 Pet_Add_Atk; // base = Pet ATK bonus from owner int32 ItemEnduranceRegenCap; // modify endurance regen cap int32 WeaponStance[WEAPON_STANCE_TYPE_MAX +1];// base = trigger spell id, base2 = 0 is 2h, 1 is shield, 2 is dual wield, [0]spid 2h, [1]spid shield, [2]spid DW - + bool ZoneSuspendMinion; // base 1 allows suspended minions to zone // AAs int32 ShieldDuration; // extends duration of /shield ability diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 793980c98..0284fd4c6 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2534,11 +2534,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SuspendMinion: case SE_SuspendPet: { if(IsClient()) - CastToClient()->SuspendMinion(); + CastToClient()->SuspendMinion(spell.base[i]); break; }