[11446] Reimplement corpse enter to instance.

* Resurrect player _before_ enter to instance with corpse
* In case corpse in more deep instance teleport to corpse instance inner entrance.
* If by some reason player can't enter to corpse instance it will just resurrected before entrance.

Original patch and research done by Den.
This commit is contained in:
VladimirMangos 2011-05-09 00:53:21 +04:00
parent 6d28c7dfd0
commit 605fb79847
4 changed files with 65 additions and 69 deletions

View file

@ -194,38 +194,6 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player)
return false; return false;
} }
if (!player->isAlive())
{
if(Corpse *corpse = player->GetCorpse())
{
// let enter in ghost mode in instance that connected to inner instance with corpse
uint32 instance_map = corpse->GetMapId();
do
{
if(instance_map==mapid)
break;
InstanceTemplate const* instance = ObjectMgr::GetInstanceTemplate(instance_map);
instance_map = instance ? instance->parent : 0;
}
while (instance_map);
if (!instance_map)
{
WorldPacket data(SMSG_AREA_TRIGGER_NO_CORPSE);
player->GetSession()->SendPacket(&data);
DEBUG_LOG("MAP: Player '%s' doesn't has a corpse in instance '%s' and can't enter", player->GetName(), mapName);
return false;
}
DEBUG_LOG("MAP: Player '%s' has corpse in instance '%s' and can enter", player->GetName(), mapName);
}
else
{
DEBUG_LOG("Map::CanEnter - player '%s' is dead but doesn't have a corpse!", player->GetName());
}
}
// TODO: move this to a map dependent location // TODO: move this to a map dependent location
/*if(i_data && i_data->IsEncounterInProgress()) /*if(i_data && i_data->IsEncounterInProgress())
{ {

View file

@ -714,7 +714,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
return; return;
uint32 quest_id = sObjectMgr.GetQuestForAreaTrigger( Trigger_ID ); uint32 quest_id = sObjectMgr.GetQuestForAreaTrigger( Trigger_ID );
if( quest_id && pl->isAlive() && pl->IsActiveQuest(quest_id) ) if ( quest_id && pl->isAlive() && pl->IsActiveQuest(quest_id) )
{ {
Quest const* pQuest = sObjectMgr.GetQuestTemplate(quest_id); Quest const* pQuest = sObjectMgr.GetQuestTemplate(quest_id);
if( pQuest ) if( pQuest )
@ -725,7 +725,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
} }
// enter to tavern, not overwrite city rest // enter to tavern, not overwrite city rest
if(sObjectMgr.IsTavernAreaTrigger(Trigger_ID)) if (sObjectMgr.IsTavernAreaTrigger(Trigger_ID))
{ {
// set resting flag we are in the inn // set resting flag we are in the inn
if (pl->GetRestType() != REST_TYPE_IN_CITY) if (pl->GetRestType() != REST_TYPE_IN_CITY)
@ -733,7 +733,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
return; return;
} }
if(pl->InBattleGround()) if (pl->InBattleGround())
{ {
if (BattleGround* bg = pl->GetBattleGround()) if (BattleGround* bg = pl->GetBattleGround())
bg->HandleAreaTrigger(pl, Trigger_ID); bg->HandleAreaTrigger(pl, Trigger_ID);
@ -742,69 +742,108 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
// NULL if all values default (non teleport trigger) // NULL if all values default (non teleport trigger)
AreaTrigger const* at = sObjectMgr.GetAreaTrigger(Trigger_ID); AreaTrigger const* at = sObjectMgr.GetAreaTrigger(Trigger_ID);
if(!at) if (!at)
return; return;
if(!GetPlayer()->isGameMaster()) MapEntry const* targetMapEntry = sMapStore.LookupEntry(at->target_mapId);
if (!targetMapEntry)
return;
if (!pl->isGameMaster())
{ {
// ghost resurrected at enter attempt to dungeon with corpse (including fail enter cases)
if (!pl->isAlive() && targetMapEntry->IsDungeon())
{
int32 corpseMapId = 0;
if (Corpse *corpse = pl->GetCorpse())
corpseMapId = corpse->GetMapId();
// check back way from corpse to entrance
uint32 instance_map = corpseMapId;
do
{
// most often fast case
if (instance_map==targetMapEntry->MapID)
break;
InstanceTemplate const* instance = ObjectMgr::GetInstanceTemplate(instance_map);
instance_map = instance ? instance->parent : 0;
}
while (instance_map);
// corpse not in dungeon or some linked deep dungeons
if (!instance_map)
{
WorldPacket data(SMSG_AREA_TRIGGER_NO_CORPSE);
pl->GetSession()->SendPacket(&data);
return;
}
// need find areatrigger to inner dungeon for landing point
if (at->target_mapId != corpseMapId)
if (AreaTrigger const* corpseAt = sObjectMgr.GetMapEntranceTrigger(corpseMapId))
at = corpseAt;
// now we can resurrect player, and then check teleport requirements
pl->ResurrectPlayer(0.5f);
pl->SpawnCorpseBones();
}
// check trigger requirements
bool missingItem = false; bool missingItem = false;
bool missingLevel = false; bool missingLevel = false;
bool missingQuest = false; bool missingQuest = false;
if(GetPlayer()->getLevel() < at->requiredLevel && !sWorld.getConfig(CONFIG_BOOL_INSTANCE_IGNORE_LEVEL)) if (pl->getLevel() < at->requiredLevel && !sWorld.getConfig(CONFIG_BOOL_INSTANCE_IGNORE_LEVEL))
missingLevel = true; missingLevel = true;
// must have one or the other, report the first one that's missing // must have one or the other, report the first one that's missing
if(at->requiredItem) if (at->requiredItem)
{ {
if(!GetPlayer()->HasItemCount(at->requiredItem, 1) && if (!pl->HasItemCount(at->requiredItem, 1) &&
(!at->requiredItem2 || !GetPlayer()->HasItemCount(at->requiredItem2, 1))) (!at->requiredItem2 || !GetPlayer()->HasItemCount(at->requiredItem2, 1)))
missingItem = true; missingItem = true;
} }
else if(at->requiredItem2 && !GetPlayer()->HasItemCount(at->requiredItem2, 1)) else if (at->requiredItem2 && !pl->HasItemCount(at->requiredItem2, 1))
missingItem = true; missingItem = true;
MapEntry const* mapEntry = sMapStore.LookupEntry(at->target_mapId); bool isRegularTargetMap = !targetMapEntry->IsDungeon() || pl->GetDifficulty(targetMapEntry->IsRaid()) == REGULAR_DIFFICULTY;
if(!mapEntry)
return;
bool isRegularTargetMap = !mapEntry->IsDungeon() || GetPlayer()->GetDifficulty(mapEntry->IsRaid()) == REGULAR_DIFFICULTY;
if (!isRegularTargetMap) if (!isRegularTargetMap)
{ {
if(at->heroicKey) if (at->heroicKey)
{ {
if(!GetPlayer()->HasItemCount(at->heroicKey, 1) && if (!pl->HasItemCount(at->heroicKey, 1) &&
(!at->heroicKey2 || !GetPlayer()->HasItemCount(at->heroicKey2, 1))) (!at->heroicKey2 || !pl->HasItemCount(at->heroicKey2, 1)))
missingItem = true; missingItem = true;
} }
else if(at->heroicKey2 && !GetPlayer()->HasItemCount(at->heroicKey2, 1)) else if (at->heroicKey2 && !pl->HasItemCount(at->heroicKey2, 1))
missingItem = true; missingItem = true;
} }
if (!isRegularTargetMap) if (!isRegularTargetMap)
{ {
if (at->requiredQuestHeroic && !GetPlayer()->GetQuestRewardStatus(at->requiredQuestHeroic)) if (at->requiredQuestHeroic && !pl->GetQuestRewardStatus(at->requiredQuestHeroic))
missingQuest = true; missingQuest = true;
} }
else else
{ {
if (at->requiredQuest && !GetPlayer()->GetQuestRewardStatus(at->requiredQuest)) if (at->requiredQuest && !pl->GetQuestRewardStatus(at->requiredQuest))
missingQuest = true; missingQuest = true;
} }
if(missingItem || missingLevel || missingQuest) if (missingItem || missingLevel || missingQuest)
{ {
// hack for "Opening of the Dark Portal" // hack for "Opening of the Dark Portal"
if(missingQuest && at->target_mapId == 269) if (missingQuest && at->target_mapId == 269)
SendAreaTriggerMessage("%s", at->requiredFailedText.c_str()); SendAreaTriggerMessage("%s", at->requiredFailedText.c_str());
else if(missingQuest && mapEntry->IsContinent())// do not report anything for quest areatriggers else if (missingQuest && targetMapEntry->IsContinent())// do not report anything for quest areatriggers
return; return;
// hack for TBC heroics // hack for TBC heroics
else if(missingLevel && !mapEntry->IsRaid() && GetPlayer()->GetDifficulty(false) == DUNGEON_DIFFICULTY_HEROIC && mapEntry->addon == 1) else if (missingLevel && !targetMapEntry->IsRaid() && GetPlayer()->GetDifficulty(false) == DUNGEON_DIFFICULTY_HEROIC && targetMapEntry->addon == 1)
SendAreaTriggerMessage(GetMangosString(LANG_LEVEL_MINREQUIRED), at->requiredLevel); SendAreaTriggerMessage(GetMangosString(LANG_LEVEL_MINREQUIRED), at->requiredLevel);
else else
GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, GetPlayer()->GetDifficulty(mapEntry->IsRaid())); pl->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, pl->GetDifficulty(targetMapEntry->IsRaid()));
return; return;
} }
} }

View file

@ -169,17 +169,6 @@ void WorldSession::HandleMoveWorldportAckOpcode()
GetPlayer()->m_taxi.ClearTaxiDestinations(); GetPlayer()->m_taxi.ClearTaxiDestinations();
} }
// resurrect character at enter into instance where his corpse exist after add to map
Corpse *corpse = GetPlayer()->GetCorpse();
if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId())
{
if( mEntry->IsDungeon() )
{
GetPlayer()->ResurrectPlayer(0.5f);
GetPlayer()->SpawnCorpseBones();
}
}
if (mInstance) if (mInstance)
{ {
Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid()); Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid());

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "11445" #define REVISION_NR "11446"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__