Show
Ignore:
Timestamp:
11/19/08 13:43:15 (17 years ago)
Author:
yumileroy
Message:

[svn] Implemented player on player and player on creature possession:
* Implemented packet and vision forwarding through possessed units
* Added new OnPossess? script call alerting scripts on when possession is applied/removed
* Moved fall damage and fall under map calculations into the Player class
* Added new PossessedAI that is applied only while possession on creature is active
* Implemented summon possessed spell effect
* Fixed Eyes of the Beast

Original author: gvcoman
Date: 2008-11-05 20:51:05-06:00

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/game/MovementHandler.cpp

    r102 r174  
    190190    CHECK_PACKET_SIZE(recv_data, 4+1+4+4+4+4+4); 
    191191 
    192     if(GetPlayer()->GetDontMove()) 
    193         return; 
    194  
    195192    /* extract packet */ 
    196193    MovementInfo movementInfo; 
     
    205202    recv_data >> movementInfo.o; 
    206203 
    207     //Save movement flags 
    208     _player->SetUnitMovementFlags(MovementFlags); 
    209  
    210204    if(MovementFlags & MOVEMENTFLAG_ONTRANSPORT) 
    211205    { 
     
    264258        return; 
    265259 
     260    // Handle possessed unit movement separately 
     261    Unit* pos_unit = GetPlayer()->GetCharm(); 
     262    if (pos_unit && pos_unit->isPossessed()) // can be charmed but not possessed 
     263    { 
     264        HandlePossessedMovement(recv_data, movementInfo, MovementFlags); 
     265        return; 
     266    } 
     267 
     268    if (GetPlayer()->GetDontMove()) 
     269        return; 
     270 
     271    //Save movement flags 
     272    GetPlayer()->SetUnitMovementFlags(MovementFlags); 
     273 
    266274    /* handle special cases */ 
    267275    if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT) 
     
    285293                { 
    286294                    // unmount before boarding 
    287                     _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); 
     295                    GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); 
    288296 
    289297                    GetPlayer()->m_transport = (*iter); 
     
    305313    } 
    306314 
    307     // fall damage generation (ignore in flight case that can be triggred also at lags in moment teleportation to another map). 
    308     if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight()) 
    309     { 
    310         Player *target = GetPlayer(); 
    311  
    312         //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored 
    313         if (movementInfo.fallTime > 1100 && !target->isDead() && !target->isGameMaster() && 
    314             !target->HasAuraType(SPELL_AURA_HOVER) && !target->HasAuraType(SPELL_AURA_FEATHER_FALL) && 
    315             !target->HasAuraType(SPELL_AURA_FLY) && !target->IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) ) 
    316         { 
    317             //Safe fall, fall time reduction 
    318             int32 safe_fall = target->GetTotalAuraModifier(SPELL_AURA_SAFE_FALL); 
    319             uint32 fall_time = (movementInfo.fallTime > (safe_fall*10)) ? movementInfo.fallTime - (safe_fall*10) : 0; 
    320  
    321             if(fall_time > 1100)                            //Prevent damage if fall time < 1100 
    322             { 
    323                 //Fall Damage calculation 
    324                 float fallperc = float(fall_time)/1100; 
    325                 uint32 damage = (uint32)(((fallperc*fallperc -1) / 9 * target->GetMaxHealth())*sWorld.getRate(RATE_DAMAGE_FALL)); 
    326  
    327                 float height = movementInfo.z; 
    328                 target->UpdateGroundPositionZ(movementInfo.x,movementInfo.y,height); 
    329  
    330                 if (damage > 0) 
    331                 { 
    332                     //Prevent fall damage from being more than the player maximum health 
    333                     if (damage > target->GetMaxHealth()) 
    334                         damage = target->GetMaxHealth(); 
    335  
    336                     // Gust of Wind 
    337                     if (target->GetDummyAura(43621)) 
    338                         damage = target->GetMaxHealth()/2; 
    339  
    340                     target->EnvironmentalDamage(target->GetGUID(), DAMAGE_FALL, damage); 
    341                 } 
    342  
    343                 //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction 
    344                 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); 
    345             } 
    346         } 
    347  
    348         //handle fall and logout at the same time (logout started before fall finished) 
    349         /* outdated and create problems with sit at stun sometime 
    350         if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE)) 
    351         { 
    352             target->SetStandState(PLAYER_STATE_SIT); 
    353             // Can't move 
    354             WorldPacket data( SMSG_FORCE_MOVE_ROOT, 12 ); 
    355             data.append(target->GetPackGUID()); 
    356             data << (uint32)2; 
    357             SendPacket( &data ); 
    358         } 
    359         */ 
    360     } 
     315    // handle fall damage 
     316    if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND) 
     317        GetPlayer()->HandleFallDamage(movementInfo); 
    361318 
    362319    if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater()) 
     
    382339 
    383340    if(movementInfo.z < -500.0f) 
    384     { 
    385         if(GetPlayer()->InBattleGround()  
    386             && GetPlayer()->GetBattleGround()  
    387             && GetPlayer()->GetBattleGround()->HandlePlayerUnderMap(_player)) 
    388         { 
    389             // do nothing, the handle already did if returned true 
    390         } 
    391         else 
    392         { 
    393             // NOTE: this is actually called many times while falling 
    394             // even after the player has been teleported away 
    395             // TODO: discard movement packets after the player is rooted 
    396             if(GetPlayer()->isAlive()) 
    397             { 
    398                 GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); 
    399                 // change the death state to CORPSE to prevent the death timer from 
    400                 // starting in the next player update 
    401                 GetPlayer()->KillPlayer(); 
    402                 GetPlayer()->BuildPlayerRepop(); 
    403             } 
    404  
    405             // cancel the death timer here if started 
    406             GetPlayer()->RepopAtGraveyard(); 
    407         } 
     341        GetPlayer()->HandleFallUnderMap(); 
     342} 
     343 
     344void WorldSession::HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& movementInfo, uint32& MovementFlags) 
     345{ 
     346    // Whatever the client is controlling, it will send the GUID of the original player. 
     347    // If current player is controlling, it must be handled like the controlled player sent these opcodes 
     348 
     349    Unit* pos_unit = GetPlayer()->GetCharm(); 
     350 
     351    if (pos_unit->GetTypeId() == TYPEID_PLAYER && ((Player*)pos_unit)->GetDontMove()) 
     352        return; 
     353 
     354    //Save movement flags 
     355    pos_unit->SetUnitMovementFlags(MovementFlags); 
     356 
     357    // Remove possession if possessed unit enters a transport 
     358    if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT) 
     359    { 
     360        GetPlayer()->RemovePossess(true); 
     361        return; 
     362    } 
     363 
     364    recv_data.put<uint32>(5, getMSTime()); 
     365    WorldPacket data(recv_data.GetOpcode(), pos_unit->GetPackGUID().size()+recv_data.size()); 
     366    data.append(pos_unit->GetPackGUID()); 
     367    data.append(recv_data.contents(), recv_data.size()); 
     368    // Send the packet to self but not to the possessed player; for creatures the first bool is irrelevant 
     369    pos_unit->SendMessageToSet(&data, true, false); 
     370 
     371    // Possessed is a player 
     372    if (pos_unit->GetTypeId() == TYPEID_PLAYER) 
     373    { 
     374        Player* plr = (Player*)pos_unit; 
     375         
     376        if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND) 
     377            plr->HandleFallDamage(movementInfo); 
     378 
     379        if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != plr->IsInWater()) 
     380        { 
     381            // Now client not include swimming flag in case jumping under water 
     382            plr->SetInWater( !plr->IsInWater() || plr->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) ); 
     383        } 
     384         
     385        plr->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o, false); 
     386        plr->m_movementInfo = movementInfo; 
     387 
     388        if(plr->isMovingOrTurning()) 
     389            plr->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); 
     390 
     391        if(movementInfo.z < -500.0f) 
     392        { 
     393            GetPlayer()->RemovePossess(false); 
     394            plr->HandleFallUnderMap(); 
     395        } 
     396    }  
     397    else // Possessed unit is a creature 
     398    { 
     399        Map* map = MapManager::Instance().GetMap(pos_unit->GetMapId(), pos_unit); 
     400        map->CreatureRelocation((Creature*)pos_unit, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); 
    408401    } 
    409402}