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/Player.cpp

    r168 r174  
    470470            itr->second.save->RemovePlayer(this); 
    471471 
     472    if (isPossessing()) 
     473        RemovePossess(false); 
     474 
    472475    delete m_declinedname; 
    473476} 
     
    12541257 
    12551258    Pet* pet = GetPet(); 
    1256     if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE)) 
     1259    if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE) && !pet->isPossessed()) 
    12571260    { 
    12581261        RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true); 
     
    15351538    SetSemaphoreTeleport(true); 
    15361539 
     1540    // Remove any possession on the player before teleporting 
     1541    if (isPossessedByPlayer()) 
     1542        ((Player*)GetCharmer())->RemovePossess(); 
     1543 
    15371544    // The player was ported to another map and looses the duel immediatly. 
    15381545    // We have to perform this check before the teleport, otherwise the 
     
    17481755    { 
    17491756        ///- Release charmed creatures, unsummon totems and remove pets/guardians 
     1757        RemovePossess(false); 
    17501758        Uncharm(); 
    17511759        UnsummonAllTotems(); 
     
    52675275} 
    52685276 
    5269 void Player::SendMessageToSet(WorldPacket *data, bool self) 
    5270 { 
    5271     MapManager::Instance().GetMap(GetMapId(), this)->MessageBroadcast(this, data, self); 
    5272 } 
    5273  
    5274 void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self) 
    5275 { 
    5276     MapManager::Instance().GetMap(GetMapId(), this)->MessageDistBroadcast(this, data, dist, self); 
    5277 } 
    5278  
    5279 void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool own_team_only) 
    5280 { 
    5281     MapManager::Instance().GetMap(GetMapId(), this)->MessageDistBroadcast(this, data, dist, self,own_team_only); 
     5277void Player::SendMessageToSet(WorldPacket *data, bool self, bool to_possessor) 
     5278{ 
     5279    MapManager::Instance().GetMap(GetMapId(), this)->MessageBroadcast(this, data, self, to_possessor); 
     5280} 
     5281 
     5282void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool to_possessor) 
     5283{ 
     5284    MapManager::Instance().GetMap(GetMapId(), this)->MessageDistBroadcast(this, data, dist, self, to_possessor); 
     5285} 
     5286 
     5287void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool own_team_only, bool to_possessor) 
     5288{ 
     5289    MapManager::Instance().GetMap(GetMapId(), this)->MessageDistBroadcast(this, data, dist, self, to_possessor, own_team_only); 
    52825290} 
    52835291 
     
    1597415982 
    1597515983    charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_CHARM); 
    15976     charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_POSSESS); 
    1597715984} 
    1597815985 
     
    1600716014    WorldPacket data(SMSG_MESSAGECHAT, 200); 
    1600816015    BuildPlayerChat(&data, CHAT_MSG_EMOTE, text, LANG_UNIVERSAL); 
    16009     SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true, !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) ); 
     16016    SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true, !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT), true ); 
    1601016017} 
    1601116018 
     
    1850618513} 
    1850718514 
    18508 bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const 
    18509 { 
    18510     for(ItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr) 
    18511         if(itr->pos == this->pos) 
    18512             return true; 
    18513  
    18514     return false; 
     18515void Player::HandleFallDamage(MovementInfo& movementInfo) 
     18516{ 
     18517    //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored 
     18518    if (!isInFlight() && movementInfo.fallTime > 1100 && !isDead() && !isGameMaster() && 
     18519        !HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) && 
     18520        !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) ) 
     18521    { 
     18522        //Safe fall, fall time reduction 
     18523        int32 safe_fall = GetTotalAuraModifier(SPELL_AURA_SAFE_FALL); 
     18524        uint32 fall_time = (movementInfo.fallTime > (safe_fall*10)) ? movementInfo.fallTime - (safe_fall*10) : 0; 
     18525 
     18526        if(fall_time > 1100)                            //Prevent damage if fall time < 1100 
     18527        { 
     18528            //Fall Damage calculation 
     18529            float fallperc = float(fall_time)/1100; 
     18530            uint32 damage = (uint32)(((fallperc*fallperc -1) / 9 * GetMaxHealth())*sWorld.getRate(RATE_DAMAGE_FALL)); 
     18531 
     18532            float height = movementInfo.z; 
     18533            UpdateGroundPositionZ(movementInfo.x,movementInfo.y,height); 
     18534 
     18535            if (damage > 0) 
     18536            { 
     18537                //Prevent fall damage from being more than the player maximum health 
     18538                if (damage > GetMaxHealth()) 
     18539                    damage = GetMaxHealth(); 
     18540 
     18541                // Gust of Wind 
     18542                if (GetDummyAura(43621)) 
     18543                    damage = GetMaxHealth()/2; 
     18544 
     18545                EnvironmentalDamage(GetGUID(), DAMAGE_FALL, damage); 
     18546            } 
     18547 
     18548            //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction 
     18549            DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall); 
     18550        } 
     18551    } 
     18552} 
     18553 
     18554void Player::HandleFallUnderMap() 
     18555{ 
     18556    if(InBattleGround() && GetBattleGround()  
     18557        && GetBattleGround()->HandlePlayerUnderMap(this)) 
     18558    { 
     18559        // do nothing, the handle already did if returned true 
     18560    } 
     18561    else 
     18562    { 
     18563        // NOTE: this is actually called many times while falling 
     18564        // even after the player has been teleported away 
     18565        // TODO: discard movement packets after the player is rooted 
     18566        if(isAlive()) 
     18567        { 
     18568            EnvironmentalDamage(GetGUID(),DAMAGE_FALL_TO_VOID, GetMaxHealth()); 
     18569            // change the death state to CORPSE to prevent the death timer from 
     18570            // starting in the next player update 
     18571            KillPlayer(); 
     18572            BuildPlayerRepop(); 
     18573        } 
     18574 
     18575        // cancel the death timer here if started 
     18576        RepopAtGraveyard(); 
     18577    } 
     18578} 
     18579 
     18580void Player::Possess(Unit *target) 
     18581{ 
     18582    if(!target || target == this) 
     18583        return; 
     18584 
     18585    // Don't allow possession of someone else's pet 
     18586    if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && target != GetPet()) 
     18587        return; 
     18588 
     18589    // Don't allow possession on transports or when in flight; also remove possession from the now-to-be-possessed 
     18590    if (target->GetTypeId() == TYPEID_PLAYER) 
     18591    { 
     18592        if (((Player*)target)->m_transport || ((Player*)target)->isInFlight()) 
     18593            return; 
     18594        if (target->isPossessing()) 
     18595            ((Player*)target)->RemovePossess(true); 
     18596    } 
     18597 
     18598    // Remove any previous possession from the target 
     18599    if (target->isPossessedByPlayer()) 
     18600        ((Player*)target->GetCharmer())->RemovePossess(false); 
     18601    else if (target->isCharmed())  
     18602        target->UncharmSelf();  // Target isn't possessed, but charmed; uncharm before possessing 
     18603 
     18604    // Remove our previous possession 
     18605    if (isPossessing()) 
     18606        RemovePossess(true); 
     18607    else if (GetCharm()) // We are charming a creature, not possessing it; uncharm ourself first 
     18608        Uncharm(); 
     18609 
     18610    // Interrupt any current casting of the target 
     18611    if(target->IsNonMeleeSpellCasted(true)) 
     18612        target->InterruptNonMeleeSpells(true); 
     18613 
     18614    // Update the proper unit fields 
     18615    SetPossessedTarget(target); 
     18616 
     18617    target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction()); 
     18618    target->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); 
     18619    target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); 
     18620    target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); 
     18621    SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); 
     18622    SetUInt64Value(PLAYER_FARSIGHT, target->GetGUID()); 
     18623 
     18624    if(target->GetTypeId() == TYPEID_UNIT) 
     18625    { 
     18626        // Set target to active in the grid and place it in the world container to be picked up by all regular player cell visits 
     18627        Map* map = target->GetMap(); 
     18628        map->SwitchGridContainers((Creature*)target, true); 
     18629        target->setActive(true); 
     18630 
     18631        ((Creature*)target)->InitPossessedAI(); // Initialize the possessed AI 
     18632        target->StopMoving(); 
     18633        target->GetMotionMaster()->Clear(false); 
     18634        target->GetMotionMaster()->MoveIdle(); 
     18635    } 
     18636 
     18637    target->CombatStop(); 
     18638    target->DeleteThreatList(); 
     18639 
     18640    // Pets already have a properly initialized CharmInfo, don't overwrite it. 
     18641    if(target->GetTypeId() == TYPEID_PLAYER || (target->GetTypeId() == TYPEID_UNIT && !((Creature*)target)->isPet())) 
     18642    { 
     18643        CharmInfo* charmInfo = target->InitCharmInfo(target); 
     18644        charmInfo->InitPossessCreateSpells(); 
     18645    } 
     18646 
     18647    // Disable control for target player and remove AFK 
     18648    if(target->GetTypeId() == TYPEID_PLAYER) 
     18649    { 
     18650        if(((Player*)target)->isAFK()) 
     18651            ((Player*)target)->ToggleAFK(); 
     18652        ((Player*)target)->SetViewport(target->GetGUID(), false); 
     18653    } 
     18654 
     18655    // Set current viewport to target unit, controllable 
     18656    SetViewport(target->GetGUID(), true); 
     18657 
     18658    PossessSpellInitialize(); 
     18659} 
     18660 
     18661void Player::RemovePossess(bool attack) 
     18662{ 
     18663    Unit* target = GetCharm(); 
     18664    if(!target || !target->isPossessed()) 
     18665        return; 
     18666 
     18667    // Remove area auras from possessed 
     18668    Unit::AuraMap& tAuras = target->GetAuras(); 
     18669    for(Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();) 
     18670    { 
     18671        if(itr->second && itr->second->IsAreaAura()) 
     18672            target->RemoveAura(itr); 
     18673        else 
     18674            ++itr; 
     18675    } 
     18676 
     18677    RemovePossessedTarget(); 
     18678 
     18679    if(target->GetTypeId() == TYPEID_PLAYER) 
     18680        ((Player*)target)->setFactionForRace(target->getRace()); 
     18681    else if(target->GetTypeId() == TYPEID_UNIT) 
     18682    { 
     18683        // Set creature to inactive in grid and place it back into the grid container 
     18684        Map* map = target->GetMap(); 
     18685        target->setActive(false); 
     18686        map->SwitchGridContainers((Creature*)target, false); 
     18687 
     18688        if(((Creature*)target)->isPet()) 
     18689        { 
     18690            if(Unit* owner = target->GetOwner()) 
     18691                target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction()); 
     18692        } else 
     18693        { 
     18694            if(CreatureInfo const* cInfo = ((Creature*)target)->GetCreatureInfo()) 
     18695                target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, cInfo->faction_A); 
     18696        } 
     18697    } 
     18698 
     18699    target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); 
     18700    target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); 
     18701    RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); 
     18702    SetUInt64Value(PLAYER_FARSIGHT, 0); 
     18703 
     18704    // Remove pet spell action bar 
     18705    WorldPacket data(SMSG_PET_SPELLS, 8); 
     18706    data << uint64(0); 
     18707    m_session->SendPacket(&data); 
     18708 
     18709    // Restore original view 
     18710    SetViewport(GetGUID(), true); 
     18711    if(target->GetTypeId() == TYPEID_PLAYER) 
     18712        ((Player*)target)->SetViewport(target->GetGUID(), true); 
     18713    else 
     18714    { 
     18715        if(((Creature*)target)->isPet()) 
     18716        { 
     18717            ((Pet*)target)->InitPetCreateSpells(); 
     18718            PetSpellInitialize(); 
     18719        } 
     18720 
     18721        if (target->isAlive()) 
     18722        { 
     18723            // If we're still hostile to our target, continue attacking otherwise reset threat and go home 
     18724            if (target->getVictim()) 
     18725            { 
     18726                Unit* victim = target->getVictim(); 
     18727                FactionTemplateEntry const* t_faction = target->getFactionTemplateEntry(); 
     18728                FactionTemplateEntry const* v_faction = victim->getFactionTemplateEntry(); 
     18729                // Unit::IsHostileTo will always return true since the unit is always hostile to its victim 
     18730                if (t_faction && v_faction && !t_faction->IsHostileTo(*v_faction)) 
     18731                { 
     18732                    // Stop combat and remove the target from the threat lists of all its victims 
     18733                    target->CombatStop(); 
     18734                    target->getHostilRefManager().deleteReferences(); 
     18735                    target->DeleteThreatList(); 
     18736                    target->GetMotionMaster()->Clear(); 
     18737                    target->GetMotionMaster()->MoveTargetedHome(); 
     18738                } 
     18739            }  
     18740            else if (target->GetTypeId() == TYPEID_UNIT) 
     18741            { 
     18742                target->GetMotionMaster()->Clear(); 
     18743                target->GetMotionMaster()->MoveTargetedHome(); 
     18744            } 
     18745             
     18746            // Add high amount of threat on the player 
     18747            if(target != GetPet() && attack) 
     18748                target->AddThreat(this, 1000000.0f); 
     18749        } 
     18750        // Delete the assigned possessed AI 
     18751        ((Creature*)target)->DeletePossessedAI(); 
     18752    } 
     18753} 
     18754 
     18755void Player::SetViewport(uint64 guid, bool moveable) 
     18756{ 
     18757    WorldPacket data(SMSG_CLIENT_CONTROL_UPDATE, 8+1); 
     18758    data.appendPackGUID(guid); // Packed guid of object to set client's view to 
     18759    data << (moveable ? uint8(0x01) : uint8(0x00)); // 0 - can't move; 1 - can move 
     18760    m_session->SendPacket(&data); 
     18761    sLog.outDetail("Viewport for "I64FMT" (%s) changed to "I64FMT, GetGUID(), GetName(), guid); 
    1851518762} 
    1851618763 
     
    1852518772           ); 
    1852618773} 
     18774 
     18775bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const 
     18776{ 
     18777    for(ItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr) 
     18778        if(itr->pos == this->pos) 
     18779            return true; 
     18780 
     18781    return false; 
     18782}