diff options
Diffstat (limited to 'src/game/MovementHandler.cpp')
-rw-r--r-- | src/game/MovementHandler.cpp | 153 |
1 files changed, 73 insertions, 80 deletions
diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index d2109561119..792db2e06f4 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -189,9 +189,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 4+1+4+4+4+4+4); - if(GetPlayer()->GetDontMove()) - return; - /* extract packet */ MovementInfo movementInfo; uint32 MovementFlags; @@ -204,9 +201,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) recv_data >> movementInfo.z; recv_data >> movementInfo.o; - //Save movement flags - _player->SetUnitMovementFlags(MovementFlags); - if(MovementFlags & MOVEMENTFLAG_ONTRANSPORT) { // recheck @@ -263,6 +257,20 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) if (!Trinity::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o)) return; + // Handle possessed unit movement separately + Unit* pos_unit = GetPlayer()->GetCharm(); + if (pos_unit && pos_unit->isPossessed()) // can be charmed but not possessed + { + HandlePossessedMovement(recv_data, movementInfo, MovementFlags); + return; + } + + if (GetPlayer()->GetDontMove()) + return; + + //Save movement flags + GetPlayer()->SetUnitMovementFlags(MovementFlags); + /* handle special cases */ if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT) { @@ -284,7 +292,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) if ((*iter)->GetGUID() == movementInfo.t_guid) { // unmount before boarding - _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); GetPlayer()->m_transport = (*iter); (*iter)->AddPassenger(GetPlayer()); @@ -304,60 +312,9 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) movementInfo.t_time = 0; } - // fall damage generation (ignore in flight case that can be triggred also at lags in moment teleportation to another map). - if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight()) - { - Player *target = GetPlayer(); - - //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored - if (movementInfo.fallTime > 1100 && !target->isDead() && !target->isGameMaster() && - !target->HasAuraType(SPELL_AURA_HOVER) && !target->HasAuraType(SPELL_AURA_FEATHER_FALL) && - !target->HasAuraType(SPELL_AURA_FLY) && !target->IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) ) - { - //Safe fall, fall time reduction - int32 safe_fall = target->GetTotalAuraModifier(SPELL_AURA_SAFE_FALL); - uint32 fall_time = (movementInfo.fallTime > (safe_fall*10)) ? movementInfo.fallTime - (safe_fall*10) : 0; - - if(fall_time > 1100) //Prevent damage if fall time < 1100 - { - //Fall Damage calculation - float fallperc = float(fall_time)/1100; - uint32 damage = (uint32)(((fallperc*fallperc -1) / 9 * target->GetMaxHealth())*sWorld.getRate(RATE_DAMAGE_FALL)); - - float height = movementInfo.z; - target->UpdateGroundPositionZ(movementInfo.x,movementInfo.y,height); - - if (damage > 0) - { - //Prevent fall damage from being more than the player maximum health - if (damage > target->GetMaxHealth()) - damage = target->GetMaxHealth(); - - // Gust of Wind - if (target->GetDummyAura(43621)) - damage = target->GetMaxHealth()/2; - - target->EnvironmentalDamage(target->GetGUID(), DAMAGE_FALL, damage); - } - - //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction - DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, target->GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall); - } - } - - //handle fall and logout at the same time (logout started before fall finished) - /* outdated and create problems with sit at stun sometime - if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE)) - { - target->SetStandState(PLAYER_STATE_SIT); - // Can't move - WorldPacket data( SMSG_FORCE_MOVE_ROOT, 12 ); - data.append(target->GetPackGUID()); - data << (uint32)2; - SendPacket( &data ); - } - */ - } + // handle fall damage + if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND) + GetPlayer()->HandleFallDamage(movementInfo); if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater()) { @@ -381,30 +338,66 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); if(movementInfo.z < -500.0f) + GetPlayer()->HandleFallUnderMap(); +} + +void WorldSession::HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& movementInfo, uint32& MovementFlags) +{ + // Whatever the client is controlling, it will send the GUID of the original player. + // If current player is controlling, it must be handled like the controlled player sent these opcodes + + Unit* pos_unit = GetPlayer()->GetCharm(); + + if (pos_unit->GetTypeId() == TYPEID_PLAYER && ((Player*)pos_unit)->GetDontMove()) + return; + + //Save movement flags + pos_unit->SetUnitMovementFlags(MovementFlags); + + // Remove possession if possessed unit enters a transport + if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT) { - if(GetPlayer()->InBattleGround() - && GetPlayer()->GetBattleGround() - && GetPlayer()->GetBattleGround()->HandlePlayerUnderMap(_player)) + GetPlayer()->RemovePossess(true); + return; + } + + recv_data.put<uint32>(5, getMSTime()); + WorldPacket data(recv_data.GetOpcode(), pos_unit->GetPackGUID().size()+recv_data.size()); + data.append(pos_unit->GetPackGUID()); + data.append(recv_data.contents(), recv_data.size()); + // Send the packet to self but not to the possessed player; for creatures the first bool is irrelevant + pos_unit->SendMessageToSet(&data, true, false); + + // Possessed is a player + if (pos_unit->GetTypeId() == TYPEID_PLAYER) + { + Player* plr = (Player*)pos_unit; + + if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND) + plr->HandleFallDamage(movementInfo); + + if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != plr->IsInWater()) { - // do nothing, the handle already did if returned true + // Now client not include swimming flag in case jumping under water + plr->SetInWater( !plr->IsInWater() || plr->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) ); } - else - { - // NOTE: this is actually called many times while falling - // even after the player has been teleported away - // TODO: discard movement packets after the player is rooted - if(GetPlayer()->isAlive()) - { - GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); - // change the death state to CORPSE to prevent the death timer from - // starting in the next player update - GetPlayer()->KillPlayer(); - GetPlayer()->BuildPlayerRepop(); - } + + plr->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o, false); + plr->m_movementInfo = movementInfo; - // cancel the death timer here if started - GetPlayer()->RepopAtGraveyard(); + if(plr->isMovingOrTurning()) + plr->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + if(movementInfo.z < -500.0f) + { + GetPlayer()->RemovePossess(false); + plr->HandleFallUnderMap(); } + } + else // Possessed unit is a creature + { + Map* map = MapManager::Instance().GetMap(pos_unit->GetMapId(), pos_unit); + map->CreatureRelocation((Creature*)pos_unit, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); } } |