void LairObserverImplementation::notifyDestruction(TangibleObject* lair, TangibleObject* attacker, int condition) { ThreatMap* threatMap = lair->getThreatMap(); Reference<DisseminateExperienceTask*> deTask = new DisseminateExperienceTask(lair, threatMap, &spawnedCreatures); deTask->execute(); threatMap->removeObservers(); threatMap->removeAll(); // we can clear the original one if (lair->getZone() == NULL) { spawnedCreatures.removeAll(); return; } PlayClientEffectObjectMessage* explode = new PlayClientEffectObjectMessage(lair, "clienteffect/lair_damage_heavy.cef", ""); lair->broadcastMessage(explode, false); PlayClientEffectLoc* explodeLoc = new PlayClientEffectLoc("clienteffect/lair_damage_heavy.cef", lair->getZone()->getZoneName(), lair->getPositionX(), lair->getPositionZ(), lair->getPositionY()); lair->broadcastMessage(explodeLoc, false); lair->destroyObjectFromWorld(true); for (int i = 0; i < spawnedCreatures.size(); ++i) { CreatureObject* obj = spawnedCreatures.get(i); if (obj->isAiAgent()) (cast<AiAgent*>(obj))->setDespawnOnNoPlayerInRange(true); } spawnedCreatures.removeAll(); }
int CreatureManagerImplementation::notifyDestruction(TangibleObject* destructor, AiAgent* destructedObject, int condition) { if (destructedObject->isDead()) return 1; destructedObject->setPosture(CreaturePosture::DEAD, true); destructedObject->updateTimeOfDeath(); ManagedReference<PlayerManager*> playerManager = zoneServer->getPlayerManager(); // lets unlock destructor so we dont get into complicated deadlocks // lets copy the damage map before we remove it all ThreatMap* threatMap = destructedObject->getThreatMap(); ThreatMap copyThreatMap(*threatMap); threatMap->removeObservers(); threatMap->removeAll(); // we can clear the original one if (destructedObject != destructor) destructor->unlock(); bool shouldRescheduleCorpseDestruction = false; try { ManagedReference<CreatureObject*> player = copyThreatMap.getHighestDamageGroupLeader(); uint64 ownerID = 0; if (player != NULL) { if(player->isGrouped()) { ownerID = player->getGroupID(); } else { ownerID = player->getObjectID(); } if (player->isPlayerCreature()) { Locker locker(player, destructedObject); player->notifyObservers(ObserverEventType::KILLEDCREATURE, destructedObject); FactionManager* factionManager = FactionManager::instance(); if (!destructedObject->getPvPFaction().isEmpty() && !destructedObject->isEventMob()) { int level = destructedObject->getLevel(); if(!player->isGrouped()) factionManager->awardFactionStanding(player, destructedObject->getPvPFaction(), level); else factionManager->awardFactionStanding(copyThreatMap.getHighestDamagePlayer(), destructedObject->getPvPFaction(), level); } } } if (playerManager != NULL) playerManager->disseminateExperience(destructedObject, ©ThreatMap); SceneObject* creatureInventory = destructedObject->getSlottedObject("inventory"); if (creatureInventory != NULL && player != NULL && player->isPlayerCreature()) { LootManager* lootManager = zoneServer->getLootManager(); if (destructedObject->isNonPlayerCreatureObject() && !destructedObject->isEventMob()) destructedObject->setCashCredits(lootManager->calculateLootCredits(destructedObject->getLevel())); creatureInventory->setContainerOwnerID(ownerID); lootManager->createLoot(creatureInventory, destructedObject); } CombatManager::instance()->attemptPeace(destructedObject); // Check to see if we can expedite the despawn of this corpse // We can expedite the despawn when corpse has no loot, no credits, player cannot harvest, and no group members in range can harvest shouldRescheduleCorpseDestruction = playerManager->shouldRescheduleCorpseDestruction(player, destructedObject); } catch (...) { destructedObject->scheduleDespawn(); // now we can safely lock destructor again if (destructedObject != destructor) destructor->wlock(destructedObject); throw; } destructedObject->scheduleDespawn(); if (shouldRescheduleCorpseDestruction) { Reference<DespawnCreatureTask*> despawn = destructedObject->getPendingTask("despawn").castTo<DespawnCreatureTask*>(); if (despawn != NULL) { despawn->cancel(); despawn->reschedule(10000); } } // now we can safely lock destructor again if (destructedObject != destructor) destructor->wlock(destructedObject); return 1; }