mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
[Spells] SPA 299 Wake the Dead updates and crash fixes. SPA 306 Army of Dead implemented. (#1929)
* start * wtd fix v1 * Update aa.cpp * rework done, army of dead supported * debugs * Update aa.cpp * Update spdat.h
This commit is contained in:
parent
5f482a9b30
commit
5ebbbf647b
@ -1017,14 +1017,14 @@ typedef enum {
|
||||
#define SE_FcSpellVulnerability 296 // implemented, @Fc, On Target, spell damage taken mod pct, base: min pct, limit: max pct
|
||||
#define SE_FcDamageAmtIncoming 297 // implemetned, @Fc, On Target, damage taken flat amt, base: amt
|
||||
#define SE_ChangeHeight 298 // implemented
|
||||
#define SE_WakeTheDead 299 // implemented
|
||||
#define SE_WakeTheDead 299 // implemented, @Pets, summon one temporary pet from nearby corpses that last a set duration, base: none, limit: none, max: duration (seconds). Note: max range of corpse is 250.
|
||||
#define SE_Doppelganger 300 // implemented
|
||||
#define SE_ArcheryDamageModifier 301 // implemented[AA] - increase archery damage by percent
|
||||
#define SE_FcDamagePctCrit 302 // implemented, @Fc, On Caster, spell damage mod pct, base: min pct, limit: max pct, Note: applied after critical hits has been calculated.
|
||||
#define SE_FcDamageAmtCrit 303 // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt
|
||||
#define SE_OffhandRiposteFail 304 // implemented as bonus - enemy cannot riposte offhand attacks
|
||||
#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_ArmyOfTheDead 306 // implemented, @Pets, summon multiple temporary pets from nearby corpses that last a set duration, base: amount of corpses that a pet can summon from, limit: none, max: duration (seconds). Note: max range of corpse is 250.
|
||||
//#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_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
|
||||
|
||||
297
zone/aa.cpp
297
zone/aa.cpp
@ -213,7 +213,7 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
|
||||
glm::vec2(5, 5), glm::vec2(-5, 5), glm::vec2(5, -5), glm::vec2(-5, -5),
|
||||
glm::vec2(10, 10), glm::vec2(-10, 10), glm::vec2(10, -10), glm::vec2(-10, -10),
|
||||
glm::vec2(8, 8), glm::vec2(-8, 8), glm::vec2(8, -8), glm::vec2(-8, -8)
|
||||
};;
|
||||
};
|
||||
|
||||
while(summon_count > 0) {
|
||||
int pet_duration = pet.duration;
|
||||
@ -273,63 +273,94 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
|
||||
delete made_npc;
|
||||
}
|
||||
|
||||
void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
|
||||
{
|
||||
Corpse *CorpseToUse = nullptr;
|
||||
CorpseToUse = entity_list.GetClosestCorpse(this, nullptr);
|
||||
void Mob::WakeTheDead(uint16 spell_id, Corpse *corpse_to_use, Mob *target, uint32 duration) {
|
||||
|
||||
if(!CorpseToUse)
|
||||
/*
|
||||
SPA 299 Wake The Dead, 'animateDead' should be temp pet, always spawns 1 pet from corpse, max value is duration
|
||||
SPA 306 Wake The Dead, 'animateDead#' should be temp pet, base is amount of pets from indivual corpses, max value is duration
|
||||
Max range for closet corpse is 250 units.
|
||||
TODO: Should use temp pets
|
||||
*/
|
||||
|
||||
if (!corpse_to_use) {
|
||||
return;
|
||||
}
|
||||
|
||||
//assuming we have pets in our table; we take the first pet as a base type.
|
||||
const NPCType *base_type = content_db.LoadNPCTypesData(500);
|
||||
auto make_npc = new NPCType;
|
||||
memcpy(make_npc, base_type, sizeof(NPCType));
|
||||
/* TODO: Does WTD use pet focus?
|
||||
int act_power = 0;
|
||||
|
||||
//combat stats
|
||||
make_npc->AC = ((GetLevel() * 7) + 550);
|
||||
make_npc->ATK = GetLevel();
|
||||
make_npc->max_dmg = (GetLevel() * 4) + 2;
|
||||
make_npc->min_dmg = 1;
|
||||
if (IsClient()) {
|
||||
act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id);
|
||||
act_power = CastToClient()->mod_pet_power(act_power, spell_id);
|
||||
}
|
||||
*/
|
||||
|
||||
//base stats
|
||||
make_npc->current_hp = (GetLevel() * 55);
|
||||
make_npc->max_hp = (GetLevel() * 55);
|
||||
make_npc->STR = 85 + (GetLevel() * 3);
|
||||
make_npc->STA = 85 + (GetLevel() * 3);
|
||||
make_npc->DEX = 85 + (GetLevel() * 3);
|
||||
make_npc->AGI = 85 + (GetLevel() * 3);
|
||||
make_npc->INT = 85 + (GetLevel() * 3);
|
||||
make_npc->WIS = 85 + (GetLevel() * 3);
|
||||
make_npc->CHA = 85 + (GetLevel() * 3);
|
||||
make_npc->MR = 25;
|
||||
make_npc->FR = 25;
|
||||
make_npc->CR = 25;
|
||||
make_npc->DR = 25;
|
||||
make_npc->PR = 25;
|
||||
SwarmPet_Struct pet;
|
||||
pet.count = 1;
|
||||
pet.duration = 1;
|
||||
|
||||
//pet.duration += GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000; //TODO: Does WTD use pet focus?
|
||||
|
||||
pet.npc_id = WAKE_THE_DEAD_NPCTYPEID;
|
||||
|
||||
NPCType *made_npc = nullptr;
|
||||
|
||||
const NPCType *npc_type = content_db.LoadNPCTypesData(WAKE_THE_DEAD_NPCTYPEID);
|
||||
if (npc_type == nullptr) {
|
||||
//log write
|
||||
LogError("Unknown npc type for 'Wake the Dead' swarm pet spell id: [{}]", spell_id);
|
||||
Message(0, "Unable to find pet!");
|
||||
return;
|
||||
}
|
||||
|
||||
made_npc = new NPCType;
|
||||
memcpy(made_npc, npc_type, sizeof(NPCType));
|
||||
|
||||
//level class and gender
|
||||
make_npc->level = GetLevel();
|
||||
make_npc->class_ = CorpseToUse->class_;
|
||||
make_npc->race = CorpseToUse->race;
|
||||
make_npc->gender = CorpseToUse->gender;
|
||||
make_npc->loottable_id = 0;
|
||||
//name
|
||||
char NewName[64];
|
||||
sprintf(NewName, "%s`s Animated Corpse", GetCleanName());
|
||||
strcpy(make_npc->name, NewName);
|
||||
strcpy(made_npc->name, NewName);
|
||||
npc_type = made_npc;
|
||||
|
||||
//combat stats
|
||||
made_npc->AC = ((GetLevel() * 7) + 550);
|
||||
made_npc->ATK = GetLevel();
|
||||
made_npc->max_dmg = (GetLevel() * 4) + 2;
|
||||
made_npc->min_dmg = 1;
|
||||
|
||||
//base stats
|
||||
made_npc->current_hp = (GetLevel() * 55);
|
||||
made_npc->max_hp = (GetLevel() * 55);
|
||||
made_npc->STR = 85 + (GetLevel() * 3);
|
||||
made_npc->STA = 85 + (GetLevel() * 3);
|
||||
made_npc->DEX = 85 + (GetLevel() * 3);
|
||||
made_npc->AGI = 85 + (GetLevel() * 3);
|
||||
made_npc->INT = 85 + (GetLevel() * 3);
|
||||
made_npc->WIS = 85 + (GetLevel() * 3);
|
||||
made_npc->CHA = 85 + (GetLevel() * 3);
|
||||
made_npc->MR = 25;
|
||||
made_npc->FR = 25;
|
||||
made_npc->CR = 25;
|
||||
made_npc->DR = 25;
|
||||
made_npc->PR = 25;
|
||||
|
||||
//level class and gender
|
||||
made_npc->level = GetLevel();
|
||||
made_npc->class_ = corpse_to_use->class_;
|
||||
made_npc->race = corpse_to_use->race;
|
||||
made_npc->gender = corpse_to_use->gender;
|
||||
made_npc->loottable_id = 0;
|
||||
|
||||
//appearance
|
||||
make_npc->beard = CorpseToUse->beard;
|
||||
make_npc->beardcolor = CorpseToUse->beardcolor;
|
||||
make_npc->eyecolor1 = CorpseToUse->eyecolor1;
|
||||
make_npc->eyecolor2 = CorpseToUse->eyecolor2;
|
||||
make_npc->haircolor = CorpseToUse->haircolor;
|
||||
make_npc->hairstyle = CorpseToUse->hairstyle;
|
||||
make_npc->helmtexture = CorpseToUse->helmtexture;
|
||||
make_npc->luclinface = CorpseToUse->luclinface;
|
||||
make_npc->size = CorpseToUse->size;
|
||||
make_npc->texture = CorpseToUse->texture;
|
||||
made_npc->beard = corpse_to_use->beard;
|
||||
made_npc->beardcolor = corpse_to_use->beardcolor;
|
||||
made_npc->eyecolor1 = corpse_to_use->eyecolor1;
|
||||
made_npc->eyecolor2 = corpse_to_use->eyecolor2;
|
||||
made_npc->haircolor = corpse_to_use->haircolor;
|
||||
made_npc->hairstyle = corpse_to_use->hairstyle;
|
||||
made_npc->helmtexture = corpse_to_use->helmtexture;
|
||||
made_npc->luclinface = corpse_to_use->luclinface;
|
||||
made_npc->size = corpse_to_use->size;
|
||||
made_npc->texture = corpse_to_use->texture;
|
||||
|
||||
//cast stuff.. based off of PEQ's if you want to change
|
||||
//it you'll have to mod this code, but most likely
|
||||
@ -337,130 +368,144 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
|
||||
//part of their spell list; can't think of any smooth
|
||||
//way to do this
|
||||
//some basic combat mods here too since it's convienent
|
||||
switch(CorpseToUse->class_)
|
||||
switch (corpse_to_use->class_)
|
||||
{
|
||||
case CLERIC:
|
||||
make_npc->npc_spells_id = 1;
|
||||
made_npc->npc_spells_id = 1;
|
||||
break;
|
||||
case WIZARD:
|
||||
make_npc->npc_spells_id = 2;
|
||||
made_npc->npc_spells_id = 2;
|
||||
break;
|
||||
case NECROMANCER:
|
||||
make_npc->npc_spells_id = 3;
|
||||
made_npc->npc_spells_id = 3;
|
||||
break;
|
||||
case MAGICIAN:
|
||||
make_npc->npc_spells_id = 4;
|
||||
made_npc->npc_spells_id = 4;
|
||||
break;
|
||||
case ENCHANTER:
|
||||
make_npc->npc_spells_id = 5;
|
||||
made_npc->npc_spells_id = 5;
|
||||
break;
|
||||
case SHAMAN:
|
||||
make_npc->npc_spells_id = 6;
|
||||
made_npc->npc_spells_id = 6;
|
||||
break;
|
||||
case DRUID:
|
||||
make_npc->npc_spells_id = 7;
|
||||
made_npc->npc_spells_id = 7;
|
||||
break;
|
||||
case PALADIN:
|
||||
//SPECATK_TRIPLE
|
||||
strcpy(make_npc->special_abilities, "6,1");
|
||||
make_npc->current_hp = make_npc->current_hp * 150 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 150 / 100;
|
||||
make_npc->npc_spells_id = 8;
|
||||
strcpy(made_npc->special_abilities, "6,1");
|
||||
made_npc->current_hp = made_npc->current_hp * 150 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 150 / 100;
|
||||
made_npc->npc_spells_id = 8;
|
||||
break;
|
||||
case SHADOWKNIGHT:
|
||||
strcpy(make_npc->special_abilities, "6,1");
|
||||
make_npc->current_hp = make_npc->current_hp * 150 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 150 / 100;
|
||||
make_npc->npc_spells_id = 9;
|
||||
strcpy(made_npc->special_abilities, "6,1");
|
||||
made_npc->current_hp = made_npc->current_hp * 150 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 150 / 100;
|
||||
made_npc->npc_spells_id = 9;
|
||||
break;
|
||||
case RANGER:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->current_hp = make_npc->current_hp * 135 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 135 / 100;
|
||||
make_npc->npc_spells_id = 10;
|
||||
strcpy(made_npc->special_abilities, "7,1");
|
||||
made_npc->current_hp = made_npc->current_hp * 135 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 135 / 100;
|
||||
made_npc->npc_spells_id = 10;
|
||||
break;
|
||||
case BARD:
|
||||
strcpy(make_npc->special_abilities, "6,1");
|
||||
make_npc->current_hp = make_npc->current_hp * 110 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 110 / 100;
|
||||
make_npc->npc_spells_id = 11;
|
||||
strcpy(made_npc->special_abilities, "6,1");
|
||||
made_npc->current_hp = made_npc->current_hp * 110 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 110 / 100;
|
||||
made_npc->npc_spells_id = 11;
|
||||
break;
|
||||
case BEASTLORD:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->current_hp = make_npc->current_hp * 110 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 110 / 100;
|
||||
make_npc->npc_spells_id = 12;
|
||||
strcpy(made_npc->special_abilities, "7,1");
|
||||
made_npc->current_hp = made_npc->current_hp * 110 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 110 / 100;
|
||||
made_npc->npc_spells_id = 12;
|
||||
break;
|
||||
case ROGUE:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->max_dmg = make_npc->max_dmg * 150 /100;
|
||||
make_npc->current_hp = make_npc->current_hp * 110 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 110 / 100;
|
||||
strcpy(made_npc->special_abilities, "7,1");
|
||||
made_npc->max_dmg = made_npc->max_dmg * 150 / 100;
|
||||
made_npc->current_hp = made_npc->current_hp * 110 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 110 / 100;
|
||||
break;
|
||||
case MONK:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->max_dmg = make_npc->max_dmg * 150 /100;
|
||||
make_npc->current_hp = make_npc->current_hp * 135 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 135 / 100;
|
||||
strcpy(made_npc->special_abilities, "7,1");
|
||||
made_npc->max_dmg = made_npc->max_dmg * 150 / 100;
|
||||
made_npc->current_hp = made_npc->current_hp * 135 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 135 / 100;
|
||||
break;
|
||||
case WARRIOR:
|
||||
case BERSERKER:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->max_dmg = make_npc->max_dmg * 150 /100;
|
||||
make_npc->current_hp = make_npc->current_hp * 175 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 175 / 100;
|
||||
strcpy(made_npc->special_abilities, "7,1");
|
||||
made_npc->max_dmg = made_npc->max_dmg * 150 / 100;
|
||||
made_npc->current_hp = made_npc->current_hp * 175 / 100;
|
||||
made_npc->max_hp = made_npc->max_hp * 175 / 100;
|
||||
break;
|
||||
default:
|
||||
make_npc->npc_spells_id = 0;
|
||||
made_npc->npc_spells_id = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
make_npc->loottable_id = 0;
|
||||
make_npc->merchanttype = 0;
|
||||
make_npc->d_melee_texture1 = 0;
|
||||
make_npc->d_melee_texture2 = 0;
|
||||
made_npc->loottable_id = 0;
|
||||
made_npc->merchanttype = 0;
|
||||
made_npc->d_melee_texture1 = 0;
|
||||
made_npc->d_melee_texture2 = 0;
|
||||
|
||||
auto npca = new NPC(make_npc, 0, GetPosition(), GravityBehavior::Water);
|
||||
|
||||
if(!npca->GetSwarmInfo()){
|
||||
auto nSI = new SwarmPet;
|
||||
npca->SetSwarmInfo(nSI);
|
||||
npca->GetSwarmInfo()->duration = new Timer(duration*1000);
|
||||
}
|
||||
else{
|
||||
npca->GetSwarmInfo()->duration->Start(duration*1000);
|
||||
}
|
||||
int summon_count = 0;
|
||||
summon_count = pet.count;
|
||||
|
||||
npca->StartSwarmTimer(duration * 1000);
|
||||
npca->GetSwarmInfo()->owner_id = GetID();
|
||||
NPC* swarm_pet_npc = nullptr;
|
||||
//TODO: potenitally add support for multiple pets per corpse
|
||||
while (summon_count > 0) {
|
||||
int pet_duration = duration;
|
||||
|
||||
//give the pet somebody to "love"
|
||||
if(target != nullptr){
|
||||
npca->AddToHateList(target, 100000);
|
||||
npca->GetSwarmInfo()->target = target->GetID();
|
||||
}
|
||||
|
||||
//gear stuff, need to make sure there's
|
||||
//no situation where this stuff can be duped
|
||||
for (int x = EQ::invslot::EQUIPMENT_BEGIN; x <= EQ::invslot::EQUIPMENT_END; x++)
|
||||
{
|
||||
uint32 sitem = 0;
|
||||
sitem = CorpseToUse->GetWornItem(x);
|
||||
if(sitem){
|
||||
const EQ::ItemData * itm = database.GetItem(sitem);
|
||||
npca->AddLootDrop(itm, &npca->itemlist, NPC::NewLootDropEntry(), true);
|
||||
NPCType *npc_dup = nullptr;
|
||||
if (made_npc != nullptr) {
|
||||
npc_dup = new NPCType;
|
||||
memcpy(npc_dup, made_npc, sizeof(NPCType));
|
||||
}
|
||||
|
||||
swarm_pet_npc = new NPC(
|
||||
(npc_dup != nullptr) ? npc_dup : npc_type,
|
||||
0, corpse_to_use->GetPosition(),GravityBehavior::Water);
|
||||
|
||||
swarm_pet_npc->SetFollowID(GetID());
|
||||
|
||||
if (!swarm_pet_npc->GetSwarmInfo()) {
|
||||
auto nSI = new SwarmPet;
|
||||
swarm_pet_npc->SetSwarmInfo(nSI);
|
||||
swarm_pet_npc->GetSwarmInfo()->duration = new Timer(pet_duration * 1000);
|
||||
}
|
||||
else {
|
||||
swarm_pet_npc->GetSwarmInfo()->duration->Start(pet_duration * 1000);
|
||||
}
|
||||
|
||||
swarm_pet_npc->StartSwarmTimer(pet_duration * 1000);
|
||||
|
||||
//removing this prevents the pet from attacking
|
||||
swarm_pet_npc->GetSwarmInfo()->owner_id = GetID();
|
||||
|
||||
//give the pets somebody to "love"
|
||||
if (target != nullptr) {
|
||||
swarm_pet_npc->AddToHateList(target, 10000, 1000);
|
||||
swarm_pet_npc->GetSwarmInfo()->target = 0;
|
||||
}
|
||||
|
||||
//we allocated a new NPC type object, give the NPC ownership of that memory
|
||||
if (npc_dup != nullptr)
|
||||
swarm_pet_npc->GiveNPCTypeData(npc_dup);
|
||||
|
||||
entity_list.AddNPC(swarm_pet_npc, true, true);
|
||||
summon_count--;
|
||||
}
|
||||
|
||||
//we allocated a new NPC type object, give the NPC ownership of that memory
|
||||
if(make_npc != nullptr)
|
||||
npca->GiveNPCTypeData(make_npc);
|
||||
|
||||
entity_list.AddNPC(npca, true, true);
|
||||
|
||||
//the target of these swarm pets will take offense to being cast on...
|
||||
if(target != nullptr)
|
||||
if (target != nullptr)
|
||||
target->AddToHateList(this, 1, 0);
|
||||
|
||||
// The other pointers we make are handled elsewhere.
|
||||
delete made_npc;
|
||||
}
|
||||
|
||||
void Client::ResetAA() {
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#define AA_H
|
||||
|
||||
#define MAX_SWARM_PETS 12 //this can change as long as you make more coords (swarm_pet_x/swarm_pet_y)
|
||||
#define WAKE_THE_DEAD_NPCTYPEID 500 //We use first pet in pets table as a template
|
||||
|
||||
typedef enum {
|
||||
aaActionNone = 0,
|
||||
|
||||
@ -2915,8 +2915,9 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
}
|
||||
}
|
||||
|
||||
if (other->GetTempPetCount())
|
||||
if (other->GetTempPetCount()) {
|
||||
entity_list.AddTempPetsToHateList(other, this, bFrenzy);
|
||||
}
|
||||
|
||||
if (!wasengaged) {
|
||||
if (IsNPC() && other->IsClient() && other->CastToClient())
|
||||
|
||||
@ -4329,6 +4329,56 @@ Corpse *EntityList::GetClosestCorpse(Mob *sender, const char *Name)
|
||||
return ClosestCorpse;
|
||||
}
|
||||
|
||||
void EntityList::TryWakeTheDead(Mob *sender, Mob *target, int32 spell_id, uint32 max_distance, uint32 duration, uint32 amount_pets)
|
||||
{
|
||||
if (!sender) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> used_corpse_list;
|
||||
|
||||
for (int i = 0; i < amount_pets; i++)
|
||||
{
|
||||
uint32 CurrentDistance, ClosestDistance = 4294967295u;
|
||||
Corpse *CurrentCorpse, *ClosestCorpse = nullptr;
|
||||
|
||||
auto it = corpse_list.begin();
|
||||
while (it != corpse_list.end()) {
|
||||
CurrentCorpse = it->second;
|
||||
|
||||
++it;
|
||||
|
||||
bool corpse_already_used = false;
|
||||
for (auto itr = used_corpse_list.begin(); itr != used_corpse_list.end(); ++itr) {
|
||||
if ((*itr) && (*itr) == CurrentCorpse->GetID()) {
|
||||
corpse_already_used = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (corpse_already_used) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CurrentDistance = static_cast<uint32>(sender->CalculateDistance(CurrentCorpse->GetX(), CurrentCorpse->GetY(), CurrentCorpse->GetZ()));
|
||||
|
||||
if (max_distance && CurrentDistance > max_distance) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CurrentDistance < ClosestDistance) {
|
||||
ClosestDistance = CurrentDistance;
|
||||
ClosestCorpse = CurrentCorpse;
|
||||
}
|
||||
}
|
||||
|
||||
if (ClosestCorpse) {
|
||||
sender->WakeTheDead(spell_id, ClosestCorpse, target, duration);
|
||||
used_corpse_list.push_back(ClosestCorpse->GetID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::ForceGroupUpdate(uint32 gid)
|
||||
{
|
||||
auto it = client_list.begin();
|
||||
|
||||
@ -478,6 +478,7 @@ public:
|
||||
uint32 CheckNPCsClose(Mob *center);
|
||||
|
||||
Corpse* GetClosestCorpse(Mob* sender, const char *Name);
|
||||
void TryWakeTheDead(Mob* sender, Mob* target, int32 spell_id, uint32 max_distance, uint32 duration, uint32 amount_pets);
|
||||
NPC* GetClosestBanker(Mob* sender, uint32 &distance);
|
||||
void CameraEffect(uint32 duration, uint32 intensity);
|
||||
Mob* GetClosestMobByBodyType(Mob* sender, bodyType BodyType, bool skip_client_pets=false);
|
||||
|
||||
@ -800,7 +800,7 @@ public:
|
||||
inline void Amnesia(bool newval) { amnesiad = newval; }
|
||||
void TemporaryPets(uint16 spell_id, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0, bool followme=true, bool sticktarg=false, uint16 *controlled_pet_id = nullptr);
|
||||
void TypesTemporaryPets(uint32 typesid, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0, bool followme=true, bool sticktarg=false);
|
||||
void WakeTheDead(uint16 spell_id, Mob *target, uint32 duration);
|
||||
void WakeTheDead(uint16 spell_id, Corpse *corpse_to_use, Mob *target, uint32 duration);
|
||||
void Spin();
|
||||
void Kill();
|
||||
bool PassCharismaCheck(Mob* caster, uint16 spell_id);
|
||||
|
||||
10
zone/npc.cpp
10
zone/npc.cpp
@ -3082,25 +3082,23 @@ void NPC::ClearLastName()
|
||||
|
||||
void NPC::DepopSwarmPets()
|
||||
{
|
||||
|
||||
if (GetSwarmInfo()) {
|
||||
if (GetSwarmInfo()->duration->Check(false)){
|
||||
Mob* owner = entity_list.GetMobID(GetSwarmInfo()->owner_id);
|
||||
if (owner)
|
||||
if (owner) {
|
||||
owner->SetTempPetCount(owner->GetTempPetCount() - 1);
|
||||
|
||||
}
|
||||
Depop();
|
||||
return;
|
||||
}
|
||||
|
||||
//This is only used for optional quest or rule derived behavior now if you force a temp pet on a specific target.
|
||||
if (GetSwarmInfo()->target) {
|
||||
Mob *targMob = entity_list.GetMob(GetSwarmInfo()->target);
|
||||
if(!targMob || (targMob && targMob->IsCorpse())){
|
||||
Mob* owner = entity_list.GetMobID(GetSwarmInfo()->owner_id);
|
||||
if (owner)
|
||||
if (owner) {
|
||||
owner->SetTempPetCount(owner->GetTempPetCount() - 1);
|
||||
|
||||
}
|
||||
Depop();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2295,10 +2295,35 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
//meh dupe issue with npc casting this
|
||||
if(caster && caster->IsClient()){
|
||||
int dur = spells[spell_id].max_value[i];
|
||||
if (!dur)
|
||||
if (!dur) {
|
||||
dur = 60;
|
||||
}
|
||||
|
||||
caster->WakeTheDead(spell_id, caster->GetTarget(), dur);
|
||||
Mob* m_target = caster->GetTarget();
|
||||
if (m_target) {
|
||||
entity_list.TryWakeTheDead(caster, m_target, spell_id, 250, dur, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_ArmyOfTheDead:
|
||||
{
|
||||
if (caster && caster->IsClient()) {
|
||||
int dur = spells[spell_id].max_value[i];
|
||||
if (!dur) {
|
||||
dur = 60;
|
||||
}
|
||||
|
||||
int amount = spells[spell_id].base_value[i];
|
||||
if (!amount) {
|
||||
amount = 1;
|
||||
}
|
||||
|
||||
Mob* m_target = caster->GetTarget();
|
||||
if (m_target) {
|
||||
entity_list.TryWakeTheDead(caster, m_target, spell_id, 250, dur, amount);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user