diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bindings/scripts/scripts/world/npcs_special.cpp | 13 | ||||
-rw-r--r-- | src/game/Creature.cpp | 4 | ||||
-rw-r--r-- | src/game/Creature.h | 2 | ||||
-rw-r--r-- | src/game/Group.cpp | 4 | ||||
-rw-r--r-- | src/game/GroupHandler.cpp | 9 | ||||
-rw-r--r-- | src/game/MovementHandler.cpp | 20 | ||||
-rw-r--r-- | src/game/Opcodes.cpp | 6 | ||||
-rw-r--r-- | src/game/Opcodes.h | 4 | ||||
-rw-r--r-- | src/game/Pet.cpp | 5 | ||||
-rw-r--r-- | src/game/PetHandler.cpp | 6 | ||||
-rw-r--r-- | src/game/Player.cpp | 89 | ||||
-rw-r--r-- | src/game/Player.h | 6 | ||||
-rw-r--r-- | src/game/SharedDefines.h | 2 | ||||
-rw-r--r-- | src/game/Spell.cpp | 64 | ||||
-rw-r--r-- | src/game/Spell.h | 1 | ||||
-rw-r--r-- | src/game/SpellAuraDefines.h | 2 | ||||
-rw-r--r-- | src/game/SpellAuraEffects.cpp | 55 | ||||
-rw-r--r-- | src/game/SpellAuraEffects.h | 1 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 38 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 3 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 1 | ||||
-rw-r--r-- | src/game/StatSystem.cpp | 2 | ||||
-rw-r--r-- | src/game/Totem.cpp | 4 | ||||
-rw-r--r-- | src/game/Totem.h | 2 | ||||
-rw-r--r-- | src/game/Unit.cpp | 206 | ||||
-rw-r--r-- | src/game/Unit.h | 6 | ||||
-rw-r--r-- | src/game/Vehicle.cpp | 48 | ||||
-rw-r--r-- | src/game/WorldSession.cpp | 34 | ||||
-rw-r--r-- | src/game/WorldSession.h | 2 |
29 files changed, 463 insertions, 176 deletions
diff --git a/src/bindings/scripts/scripts/world/npcs_special.cpp b/src/bindings/scripts/scripts/world/npcs_special.cpp index 375848da9e8..3b712af1320 100644 --- a/src/bindings/scripts/scripts/world/npcs_special.cpp +++ b/src/bindings/scripts/scripts/world/npcs_special.cpp @@ -1835,12 +1835,13 @@ struct TRINITY_DLL_DECL npc_ebon_gargoyleAI : CasterAI me->SetReactState(REACT_PASSIVE); // Fly Away - me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE); - me->SetSpeed(MOVE_FLIGHT, 0.25f, true); - me->SetSpeed(MOVE_RUN, 0.25f, true); - float x = me->GetPositionX() + 10 * cos(me->GetOrientation()); - float y = me->GetPositionY() + 10 * sin(me->GetOrientation()); - float z = me->GetPositionZ() + 25; + me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE|MOVEMENTFLAG_ASCEND|MOVEMENTFLAG_FLYING); + me->SetSpeed(MOVE_FLIGHT, 0.75f, true); + me->SetSpeed(MOVE_RUN, 0.75f, true); + float x = me->GetPositionX() + 20 * cos(me->GetOrientation()); + float y = me->GetPositionY() + 20 * sin(me->GetOrientation()); + float z = me->GetPositionZ() + 40; + me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->MovePoint(0, x, y, z); // Despawn as soon as possible diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 0a74b64d320..384eec4ebdb 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1598,12 +1598,12 @@ bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo) return Unit::IsImmunedToSpell(spellInfo); } -bool Creature::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const +bool Creature::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index, bool checkMechanic) const { if (GetCreatureInfo()->MechanicImmuneMask & (1 << (spellInfo->EffectMechanic[index] - 1))) return true; - return Unit::IsImmunedToSpellEffect(spellInfo, index); + return Unit::IsImmunedToSpellEffect(spellInfo, index, checkMechanic); } SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) diff --git a/src/game/Creature.h b/src/game/Creature.h index 6bad39de566..cd9f30f703a 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -448,7 +448,7 @@ class TRINITY_DLL_SPEC Creature : public Unit, public GridObject<Creature> bool canCreatureAttack(Unit const *pVictim, bool force = true) const; bool IsImmunedToSpell(SpellEntry const* spellInfo); // redefine Unit::IsImmunedToSpell - bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const; + bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index, bool checkMechanic) const; // redefine Unit::IsImmunedToSpellEffect bool isElite() const { diff --git a/src/game/Group.cpp b/src/game/Group.cpp index a1585acd41b..b2db3ed46a2 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -1499,7 +1499,9 @@ void Group::SetDungeonDifficulty(Difficulty difficulty) continue; player->SetDungeonDifficulty(difficulty); player->SendDungeonDifficulty(true); - //send player to recall positio nis a dungeon (to avoid an exploit) + // Send player to recall position is a dungeon (to avoid an exploit) + if (sMapStore.LookupEntry(player->GetMap()->IsDungeon())) + player->TeleportTo(player->m_recallMap, player->m_recallX, player->m_recallY, player->m_recallZ, player->m_recallO); } } diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index c074d275614..2864800c53c 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -31,6 +31,7 @@ #include "SocialMgr.h" #include "Util.h" #include "SpellAuras.h" +#include "Vehicle.h" class Aura; @@ -775,6 +776,14 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke *data << (uint16) 0; } + if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) + { + if(player->GetVehicle()){ + Vehicle* vv=player->GetVehicle(); + *data << (uint32) vv->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]; + } + } + if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if(pet) diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index d4388f3c7a4..def605bc8c7 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -307,7 +307,11 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) } if (!mover->GetTransport() && !mover->GetVehicle()) - movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; + { + GameObject *go = mover->GetMap()->GetGameObject(movementInfo.t_guid); + if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) + movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; + } } else if (plMover && plMover->GetTransport()) // if we were on a transport, leave { @@ -354,6 +358,20 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); plMover->UpdateFallInformationIfNeed(movementInfo, opcode); + // If on vehicle, update carried players + if (Vehicle *vehicle=plMover->GetVehicleKit()) + { + if (plMover->IsVehicle()) + { + for (int i=0; i < 8; ++i) + { + if (Unit *passenger = vehicle->GetPassenger(i)) + if (passenger != NULL && passenger->GetTypeId() == TYPEID_PLAYER) + ((Player*)passenger)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + } + } + } + if (movementInfo.z < -500.0f) { if (plMover->InBattleGround() diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 6dc88c9d37a..eda7c7f7173 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -1219,9 +1219,9 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x4A4*/ { "CMSG_QUERY_VEHICLE_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4A5*/ { "UMSG_UNKNOWN_1189", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4A6*/ { "SMSG_UNKNOWN_1190", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4A7*/ { "SMSG_UNKNOWN_1191", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4A8*/ { "CMSG_UNKNOWN_1192", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4A9*/ { "CMSG_EJECT_PASSENGER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A7*/ { "SMSG_PLAYER_VEHICLE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A8*/ { "CMSG_PLAYER_VEHICLE_ENTER", STATUS_LOGGEDIN, &WorldSession::HandleEnterPlayerVehicle },
+ /*0x4A9*/ { "CMSG_EJECT_PASSENGER", STATUS_LOGGEDIN, &WorldSession::HandleEjectPasenger }, /*0x4AA*/ { "SMSG_PET_GUIDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4AB*/ { "SMSG_CLIENTCACHE_VERSION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4AC*/ { "UMSG_UNKNOWN_1196", STATUS_NEVER, &WorldSession::Handle_NULL }, diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 007e17f1687..78da3483b57 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1227,8 +1227,8 @@ enum Opcodes CMSG_QUERY_VEHICLE_STATUS = 0x4A4, // not found UMSG_UNKNOWN_1189 = 0x4A5, // not found, old SMSG_PET_GUIDS SMSG_UNKNOWN_1190 = 0x4A6, // smsg unk, "You can't do that yet" - SMSG_UNKNOWN_1191 = 0x4A7, // smsg guid+uint32 (vehicle) - CMSG_UNKNOWN_1192 = 0x4A8, // cmsg uint64 + SMSG_PLAYER_VEHICLE_DATA = 0x4A7, // smsg guid+uint32 (vehicle) + CMSG_PLAYER_VEHICLE_ENTER = 0x4A8, // cmsg uint64 CMSG_EJECT_PASSENGER = 0x4A9, // cmsg uint64 SMSG_PET_GUIDS = 0x4AA, // shifted+5 SMSG_CLIENTCACHE_VERSION = 0x4AB, // shifted+5 diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index e9b1a2d0eac..261eca21701 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -498,7 +498,10 @@ void Pet::setDeathState(DeathState s) // overwrite virtual void Pet::Update(uint32 diff) { - if(m_removed) // pet already removed, just wait in remove queue, no updates + if (m_removed) // pet already removed, just wait in remove queue, no updates + return; + + if (m_loading) return; switch( m_deathState ) diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index ee8c02dfb43..edd3a9d4f2b 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -224,8 +224,6 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid case ACT_ENABLED: // 0xC1 spell { Unit* unit_target = NULL; - if (((Creature*)pet)->GetGlobalCooldown() > 0) - return; if(guid2) unit_target = ObjectAccessor::GetUnit(*_player,guid2); @@ -238,6 +236,10 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid return; } + if (spellInfo->StartRecoveryCategory > 0) + if (((Creature*)pet)->GetGlobalCooldown() > 0) + return; + for (uint32 i = 0; i < 3; ++i) { if(spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_SRC || spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_DST || spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_DYNOBJ_ENEMY) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 94d4387f8e7..732ec29ff0b 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1323,6 +1323,14 @@ void Player::Update( uint32 p_time ) m_zoneUpdateTimer -= p_time; } + if (m_timeSyncTimer > 0) + { + if(p_time >= m_timeSyncTimer) + SendTimeSync(); + else + m_timeSyncTimer -= p_time; + } + if (isAlive()) { m_regenTimer += p_time; @@ -3981,6 +3989,7 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(PLAYER_BYTES_3); updateVisualBits.SetBit(PLAYER_DUEL_TEAM); updateVisualBits.SetBit(PLAYER_GUILD_TIMESTAMP); + updateVisualBits.SetBit(UNIT_NPC_FLAGS); // PLAYER_QUEST_LOG_x also visible bit on official (but only on party/raid)... for (uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i += 4) @@ -5862,13 +5871,16 @@ void Player::SendActionButtons(uint32 state) const WorldPacket data(SMSG_ACTION_BUTTONS, 1+(MAX_ACTION_BUTTONS*4)); data << uint8(state); // can be 0, 1, 2 - for (uint16 button = 0; button < MAX_ACTION_BUTTONS; ++button) + if (state != 2) { - ActionButtonList::const_iterator itr = m_actionButtons.find(button); - if (itr != m_actionButtons.end() && itr->second.uState != ACTIONBUTTON_DELETED) - data << uint32(itr->second.packedData); - else - data << uint32(0); + for (uint16 button = 0; button < MAX_ACTION_BUTTONS; ++button) + { + ActionButtonList::const_iterator itr = m_actionButtons.find(button); + if (itr != m_actionButtons.end() && itr->second.uState != ACTIONBUTTON_DELETED) + data << uint32(itr->second.packedData); + else + data << uint32(0); + } } GetSession()->SendPacket(&data); @@ -7126,12 +7138,29 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl if (uint32 ssvarmor = ssv->getArmorMod(proto->ScalingStatValue)) armor = ssvarmor; } - // Add armor bonus from ArmorDamageModifier if > 0 - if (proto->ArmorDamageModifier > 0) - armor += uint32(proto->ArmorDamageModifier); if (armor) - HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply); + { + UnitModifierType modType = TOTAL_VALUE; + if (proto->Class == ITEM_CLASS_ARMOR) + { + switch (proto->SubClass) + { + case ITEM_SUBCLASS_ARMOR_CLOTH: + case ITEM_SUBCLASS_ARMOR_LEATHER: + case ITEM_SUBCLASS_ARMOR_MAIL: + case ITEM_SUBCLASS_ARMOR_PLATE: + case ITEM_SUBCLASS_ARMOR_SHIELD: + modType = BASE_VALUE; + break; + } + } + HandleStatModifier(UNIT_MOD_ARMOR, modType, float(armor), apply); + } + + // Add armor bonus from ArmorDamageModifier if > 0 + if (proto->ArmorDamageModifier > 0) + HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply); if (proto->Block) HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply); @@ -7291,7 +7320,14 @@ void Player::_ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType att } if (!item->IsBroken()&&item->IsFitToSpellRequirements(aura->GetSpellProto())) + { HandleStatModifier(unitMod, unitModType, float(aura->GetAmount()),apply); + + if (unitModType == TOTAL_PCT) + ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,aura->GetAmount()/100.0f,apply); + else + ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,aura->GetAmount(),apply); + } } void Player::ApplyItemEquipSpell(Item *item, bool apply, bool form_change) @@ -17016,15 +17052,11 @@ void Player::SaveToDB() sLog.outDebug("The value of player %s at save: ", m_name.c_str()); outDebugValues(); - CharacterDatabase.BeginTransaction(); - - CharacterDatabase.PExecute("DELETE FROM characters WHERE guid = '%u'",GetGUIDLow()); - std::string sql_name = m_name; CharacterDatabase.escape_string(sql_name); std::ostringstream ss; - ss << "INSERT INTO characters (guid,account,name,race,class,gender,level,xp,money,playerBytes,playerBytes2,playerFlags," + ss << "REPLACE INTO characters (guid,account,name,race,class,gender,level,xp,money,playerBytes,playerBytes2,playerFlags," "map, instance_id, dungeon_difficulty, position_x, position_y, position_z, orientation, data, " "taximask, online, cinematic, " "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " @@ -17116,6 +17148,8 @@ void Player::SaveToDB() ss << uint32(m_activeSpec); ss << ")"; + CharacterDatabase.BeginTransaction(); + CharacterDatabase.Execute( ss.str().c_str() ); if (m_mailsUpdated) //save mails only when needed @@ -20200,9 +20234,8 @@ void Player::SendInitialPacketsAfterAddToMap() GetZoneAndAreaId(newzone,newarea); UpdateZone(newzone,newarea); // also call SendInitWorldStates(); - WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement - data << uint32(0x00000000); // on blizz it increments periodically - GetSession()->SendPacket(&data); + ResetTimeSync(); + SendTimeSync(); CastSpell(this, SPELL_LOGINEFFECT_836, true); // LOGINEFFECT @@ -23006,8 +23039,8 @@ void Player::ActivateSpec(uint8 spec) m_usedTalentCount = spentTalents; InitTalentForLevel(); - _SaveSpells(); - + // Let client clear his current Actions + SendActionButtons(2); m_actionButtons.clear(); if (QueryResult *result = CharacterDatabase.PQuery("SELECT button,action,type FROM character_action WHERE guid = '%u' AND spec = '%u' ORDER BY button", GetGUIDLow(), m_activeSpec)) _LoadActions(result, false); @@ -23022,6 +23055,22 @@ void Player::ActivateSpec(uint8 spec) SetPower(pw, 0); } +void Player::ResetTimeSync() +{ + m_timeSyncCount = 0; + m_timeSyncTimer = 0; +} + +void Player::SendTimeSync() +{ + WorldPacket data(SMSG_TIME_SYNC_REQ, 4); + data << uint32(m_timeSyncCount++); + GetSession()->SendPacket(&data); + + // Send another opcode in 10s again + m_timeSyncTimer = 10000; +} + void Player::SetReputation(uint32 factionentry, uint32 value) { GetReputationMgr().SetReputation(sFactionStore.LookupEntry(factionentry),value); diff --git a/src/game/Player.h b/src/game/Player.h index cac6e889345..1067105d227 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2437,6 +2437,9 @@ Spell * m_spellModTakingSpell; EnchantDurationList m_enchantDuration; ItemDurationList m_itemDuration; + void ResetTimeSync(); + void SendTimeSync(); + uint64 m_resurrectGUID; uint32 m_resurrectMap; float m_resurrectX, m_resurrectY, m_resurrectZ; @@ -2572,6 +2575,9 @@ Spell * m_spellModTakingSpell; SpellCooldowns m_spellCooldowns; uint32 m_ChampioningFaction; + + uint32 m_timeSyncCount; + uint32 m_timeSyncTimer; }; void AddItemsSetItem(Player*player,Item *item); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index afccf854ee0..e80239b3574 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -678,7 +678,7 @@ enum SpellEffects SPELL_EFFECT_KILL_CREDIT = 90, SPELL_EFFECT_THREAT_ALL = 91, SPELL_EFFECT_ENCHANT_HELD_ITEM = 92, - SPELL_EFFECT_SUMMON_PHANTASM = 93, //unused + SPELL_EFFECT_FORCE_DESELECT = 93, SPELL_EFFECT_SELF_RESURRECT = 94, SPELL_EFFECT_SKINNING = 95, SPELL_EFFECT_CHARGE = 96, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index a6f47e63a3c..d0c7c7d549a 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1208,6 +1208,16 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge) if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT) caster->ProcDamageAndSpell(unit, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo, m_triggeredByAuraSpell); + + // Failed Pickpocket, reveal rogue + if (missInfo == SPELL_MISS_RESIST + && m_customAttr & SPELL_ATTR_CU_PICKPOCKET + && unitTarget->GetTypeId() == TYPEID_UNIT) + { + m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); + if (((Creature*)unitTarget)->IsAIEnabled) + ((Creature*)unitTarget)->AI()->AttackStart(m_caster); + } } if(m_caster && !m_caster->IsFriendlyTo(unit) && !IsPositiveSpell(m_spellInfo->Id)) @@ -1421,7 +1431,7 @@ void Spell::DoTriggersOnSpellHit(Unit *unit) // Cast Avenging Wrath Marker m_caster->CastSpell(unit,61987, true, m_CastItem); } - else + else if (sSpellStore.LookupEntry(m_preCastSpell)) m_caster->CastSpell(unit,m_preCastSpell, true, m_CastItem); } @@ -4114,14 +4124,14 @@ SpellCastResult Spell::CheckRuneCost(uint32 runeCostID) if(src->NoRuneCost()) return SPELL_CAST_OK; - // Freezing Fog makes Howling Blast cost no runes - if (m_caster->HasAura(59052) && m_spellInfo->SpellFamilyFlags[1] & 0x2) - return SPELL_CAST_OK; - int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death for (uint32 i = 0; i < RUNE_DEATH; ++i) + { runeCost[i] = src->RuneCost[i]; + if(Player* modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i], this); + } runeCost[RUNE_DEATH] = MAX_RUNES; // calculated later @@ -4441,6 +4451,39 @@ SpellCastResult Spell::CheckCast(bool strict) if (target->hasUnitState(UNIT_STAT_UNATTACKABLE)) return SPELL_FAILED_BAD_TARGETS; + if(!m_IsTriggeredSpell && (target->HasAuraType(SPELL_AURA_MOD_STEALTH) + || target->m_invisibilityMask) && !m_caster->canSeeOrDetect(target, true)) + return SPELL_FAILED_BAD_TARGETS; + + if (m_caster->GetTypeId() == TYPEID_PLAYER) + { + // Not allow banish not self target + if (m_spellInfo->Mechanic == MECHANIC_BANISH) + if (target->GetTypeId() == TYPEID_UNIT && + !((Player*)m_caster)->isAllowedToLoot((Creature*)target)) + return SPELL_FAILED_CANT_CAST_ON_TAPPED; + + if (m_customAttr & SPELL_ATTR_CU_PICKPOCKET) + { + if (target->GetTypeId() == TYPEID_PLAYER) + return SPELL_FAILED_BAD_TARGETS; + else if ((target->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0) + return SPELL_FAILED_TARGET_NO_POCKETS; + } + + // Not allow disarm unarmed player + if (m_spellInfo->Mechanic == MECHANIC_DISARM) + { + if (target->GetTypeId() == TYPEID_PLAYER) + { + if(!((Player*)target)->GetWeaponForAttack(BASE_ATTACK) || !((Player*)target)->IsUseEquipedWeapon(true)) + return SPELL_FAILED_TARGET_NO_WEAPONS; + } + else if (!target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID)) + return SPELL_FAILED_TARGET_NO_WEAPONS; + } + } + if(!m_IsTriggeredSpell && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOSInMap(target)) return SPELL_FAILED_LINE_OF_SIGHT; @@ -4995,17 +5038,6 @@ SpellCastResult Spell::CheckCast(bool strict) } break; } - // Not used for summon? - case SPELL_EFFECT_SUMMON_PHANTASM: - { - if(m_caster->GetPetGUID()) - return SPELL_FAILED_ALREADY_HAVE_SUMMON; - - if(m_caster->GetCharmGUID()) - return SPELL_FAILED_ALREADY_HAVE_CHARM; - - break; - } case SPELL_EFFECT_SUMMON_PET: { if(m_caster->GetPetGUID()) //let warlock do a replacement summon diff --git a/src/game/Spell.h b/src/game/Spell.h index 04f3984ed91..bda7ebbfaa3 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -322,6 +322,7 @@ class Spell void EffectFeedPet(uint32 i); void EffectDismissPet(uint32 i); void EffectReputation(uint32 i); + void EffectForceDeselect(uint32 i); void EffectSelfResurrect(uint32 i); void EffectSkinning(uint32 i); void EffectCharge(uint32 i); diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 3a3942e9840..9a79dafe1d9 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -287,7 +287,7 @@ enum AuraType SPELL_AURA_MOD_EXPERTISE = 240, SPELL_AURA_FORCE_MOVE_FORWARD = 241, SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING = 242, - SPELL_AURA_243 = 243, + SPELL_AURA_MOD_FACTION = 243, SPELL_AURA_COMPREHEND_LANGUAGE = 244, SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL = 245, SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK = 246, diff --git a/src/game/SpellAuraEffects.cpp b/src/game/SpellAuraEffects.cpp index 1492d586943..d9efa1771ed 100644 --- a/src/game/SpellAuraEffects.cpp +++ b/src/game/SpellAuraEffects.cpp @@ -298,7 +298,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE &AuraEffect::HandleForceMoveForward, //241 SPELL_AURA_FORCE_MOVE_FORWARD Forces the player to move forward &AuraEffect::HandleNULL, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING - 2 test spells: 44183 and 44182 - &AuraEffect::HandleNULL, //243 faction reaction override spells + &AuraEffect::HandleAuraModFaction, //243 SPELL_AURA_MOD_FACTION &AuraEffect::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE &AuraEffect::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL &AuraEffect::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK implemented in Spell::EffectApplyAura @@ -2288,6 +2288,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit * target, bool apply) const break; case FORM_MOONKIN: spellId = 24905; + spellId2 = 69366; break; case FORM_FLIGHT: spellId = 33948; @@ -3470,7 +3471,7 @@ void AuraEffect::HandleAuraMounted(AuraApplication const * aurApp, uint8 mode, b if(GetSpellProto()->Effect[i] == SPELL_EFFECT_SUMMON && GetSpellProto()->EffectMiscValue[i] == GetMiscValue()) display_id = 0; - target->Mount(display_id); + target->Mount(display_id,ci->VehicleId); } else { @@ -4755,7 +4756,7 @@ void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const * aurApp, return; for (int i = 0; i < MAX_ATTACK; ++i) - if(Item* pItem = ((Player*)target)->GetWeaponForAttack(WeaponAttackType(i))) + if(Item* pItem = ((Player*)target)->GetWeaponForAttack(WeaponAttackType(i), true)) ((Player*)target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply); // mods must be applied base at equipped weapon class and subclass comparison @@ -5076,7 +5077,7 @@ void AuraEffect::HandleModDamageDone(AuraApplication const * aurApp, uint8 mode, if(target->GetTypeId() == TYPEID_PLAYER) { for (int i = 0; i < MAX_ATTACK; ++i) - if(Item* pItem = ((Player*)target)->GetWeaponForAttack(WeaponAttackType(i))) + if(Item* pItem = ((Player*)target)->GetWeaponForAttack(WeaponAttackType(i), true)) ((Player*)target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); } @@ -5097,19 +5098,19 @@ void AuraEffect::HandleModDamageDone(AuraApplication const * aurApp, uint8 mode, target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply); target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply); target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply); + + if(target->GetTypeId() == TYPEID_PLAYER) + { + if(GetAmount() > 0) + target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,GetAmount(),apply); + else + target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,GetAmount(),apply); + } } else { // done in Player::_ApplyWeaponDependentAuraMods } - - if(target->GetTypeId() == TYPEID_PLAYER) - { - if(GetAmount() > 0) - target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,GetAmount(),apply); - else - target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,GetAmount(),apply); - } } // Skip non magic case for speedup @@ -5163,7 +5164,7 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const * aurApp, uint if(target->GetTypeId() == TYPEID_PLAYER) { for (int i = 0; i < MAX_ATTACK; ++i) - if(Item* pItem = ((Player*)target)->GetWeaponForAttack(WeaponAttackType(i))) + if(Item* pItem = ((Player*)target)->GetWeaponForAttack(WeaponAttackType(i), true)) ((Player*)target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); } @@ -5184,14 +5185,14 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const * aurApp, uint target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply); target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply); target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply); + // For show in client + if(target->GetTypeId() == TYPEID_PLAYER) + target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,GetAmount()/100.0f,apply); } else { // done in Player::_ApplyWeaponDependentAuraMods } - // For show in client - if(target->GetTypeId() == TYPEID_PLAYER) - target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,GetAmount()/100.0f,apply); } // Skip non magic case for speedup @@ -5996,6 +5997,28 @@ void AuraEffect::HandleAuraEmpathy(AuraApplication const * aurApp, uint8 mode, b target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply); } +void AuraEffect::HandleAuraModFaction(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + { + target->setFaction(GetMiscValue()); + if(target->GetTypeId()==TYPEID_PLAYER) + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + } + else + { + target->RestoreFaction(); + if(target->GetTypeId()==TYPEID_PLAYER) + target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + } +} + + void AuraEffect::HandleComprehendLanguage(AuraApplication const * aurApp, uint8 mode, bool apply) const { if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) diff --git a/src/game/SpellAuraEffects.h b/src/game/SpellAuraEffects.h index 75e061da5fe..3adf009e388 100644 --- a/src/game/SpellAuraEffects.h +++ b/src/game/SpellAuraEffects.h @@ -255,6 +255,7 @@ class TRINITY_DLL_SPEC AuraEffect void HandleBindSight(AuraApplication const * aurApp, uint8 mode, bool apply) const; void HandleForceReaction(AuraApplication const * aurApp, uint8 mode, bool apply) const; void HandleAuraEmpathy(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModFaction(AuraApplication const * aurApp, uint8 mode, bool apply) const; void HandleComprehendLanguage(AuraApplication const * aurApp, uint8 mode, bool apply) const; void HandleAuraConvertRune(AuraApplication const * aurApp, uint8 mode, bool apply) const; void HandleAuraLinked(AuraApplication const * aurApp, uint8 mode, bool apply) const; diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 47e47d1f119..2a7a45bfbee 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -159,7 +159,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectKillCreditPersonal, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM - &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM + &Spell::EffectForceDeselect, // 93 SPELL_EFFECT_FORCE_DESELECT &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE @@ -3884,22 +3884,7 @@ void Spell::EffectPickPocket(uint32 /*i*/) // victim have to be alive and humanoid or undead if (unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0) - { - int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel()); - - if (chance > irand(0, 19)) - { - // Stealing successful - //sLog.outDebug("Sending loot from pickpocket"); - ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING); - } - else - { - // Reveal action + get attack - m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); - m_caster->CombatStart(unitTarget); - } - } + ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING); } void Spell::EffectAddFarsight(uint32 i) @@ -4580,12 +4565,9 @@ void Spell::SpellDamageWeaponDmg(uint32 i) } case SPELLFAMILY_HUNTER: { - // Kill Shot + // Kill Shot - bonus damage from Ranged Attack Power if(m_spellInfo->SpellFamilyFlags[1] & 0x800000) - { - // Increase Weapon Damage by 200% (or Weapon Damage + Weapon Damage) - spell_bonus += m_caster->CalculateDamage(RANGED_ATTACK, false, true); - } + spell_bonus += int32(0.4f*m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)); break; } case SPELLFAMILY_DEATHKNIGHT: @@ -6607,10 +6589,9 @@ void Spell::EffectLeapForward(uint32 i) destz = fabs(ground - z) <= fabs(floor - z) ? ground:floor; } else break; } - if (j == 9) - return; - unitTarget->NearTeleportTo(destx, desty, destz + 0.07531, orientation, unitTarget==m_caster); + if(j < 10) + unitTarget->NearTeleportTo(destx, desty, destz + 0.07531, orientation, unitTarget==m_caster); } void Spell::EffectReputation(uint32 i) @@ -6643,6 +6624,13 @@ void Spell::EffectQuestComplete(uint32 i) _player->AreaExploredOrEventHappens(quest_id); } +void Spell::EffectForceDeselect(uint32 i) +{ + WorldPacket data(SMSG_CLEAR_TARGET, 8); + data << uint64(m_caster->GetGUID()); + m_caster->SendMessageToSet(&data, true); +} + void Spell::EffectSelfResurrect(uint32 i) { if(!unitTarget || unitTarget->isAlive()) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index d39b47a925d..35ccabd1c60 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -3542,6 +3542,9 @@ void SpellMgr::LoadSpellCustomAttr() mSpellCustomAttr[i] |= SPELL_ATTR_CU_CHARGE; count++; break; + case SPELL_EFFECT_PICKPOCKET: + mSpellCustomAttr[i] |= SPELL_ATTR_CU_PICKPOCKET; + break; case SPELL_EFFECT_TRIGGER_SPELL: if (IsPositionTarget(spellInfo->EffectImplicitTargetA[j]) || spellInfo->Targets & (TARGET_FLAG_SOURCE_LOCATION|TARGET_FLAG_DEST_LOCATION)) diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index a31c4c5434c..6f865ef30dc 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -825,6 +825,7 @@ inline bool IsProfessionSkill(uint32 skill) #define SPELL_ATTR_CU_LINK_HIT 0x00000800 #define SPELL_ATTR_CU_LINK_AURA 0x00001000 #define SPELL_ATTR_CU_LINK_REMOVE 0x00002000 +#define SPELL_ATTR_CU_PICKPOCKET 0x00004000 #define SPELL_ATTR_CU_EXCLUDE_SELF 0x00008000 #define SPELL_ATTR_CU_NEGATIVE_EFF0 0x00010000 #define SPELL_ATTR_CU_NEGATIVE_EFF1 0x00020000 diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index f5d8bf636f2..0a4f1472ff8 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -397,7 +397,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) UpdateDamagePhysical(BASE_ATTACK); if(CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); - if(getClass() == CLASS_SHAMAN) // mental quickness + if(getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness UpdateSpellDamageAndHealingBonus(); if(pet && pet->IsPetGhoul()) // At ranged attack change for hunter pet diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp index 282dc7678cb..a6e30ca09ae 100644 --- a/src/game/Totem.cpp +++ b/src/game/Totem.cpp @@ -145,7 +145,7 @@ void Totem::UnSummon() AddObjectToRemoveList(); } -bool Totem::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const +bool Totem::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index, bool checkMechanic) const { // TODO: possibly all negative auras immune? if(GetEntry() == 5925) @@ -160,5 +160,5 @@ bool Totem::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) co default: break; } - return Creature::IsImmunedToSpellEffect(spellInfo, index); + return Creature::IsImmunedToSpellEffect(spellInfo, index, checkMechanic); } diff --git a/src/game/Totem.h b/src/game/Totem.h index 6dbd699f1d2..535e39a58dd 100644 --- a/src/game/Totem.h +++ b/src/game/Totem.h @@ -54,7 +54,7 @@ class Totem : public Minion void UpdateAttackPowerAndDamage(bool /*ranged*/ ) {} void UpdateDamagePhysical(WeaponAttackType /*attType*/) {} - bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const; + bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index, bool checkMechanic) const; protected: TotemType m_type; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index b09e414e4ff..3e918396c0e 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -602,6 +602,42 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TAKE_DAMAGE, spellProto ? spellProto->Id : 0); } + + // Rage from Damage made (only from direct weapon damage) + if (cleanDamage && damagetype==DIRECT_DAMAGE && this != pVictim && getPowerType() == POWER_RAGE) + { + uint32 weaponSpeedHitFactor; + uint32 rage_damage = damage + cleanDamage->absorbed_damage; + + switch(cleanDamage->attackType) + { + case BASE_ATTACK: + { + if (cleanDamage->hitOutCome == MELEE_HIT_CRIT) + weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 7); + else + weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 3.5f); + + RewardRage(rage_damage, weaponSpeedHitFactor, true); + + break; + } + case OFF_ATTACK: + { + if (cleanDamage->hitOutCome == MELEE_HIT_CRIT) + weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 3.5f); + else + weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 1.75f); + + RewardRage(rage_damage, weaponSpeedHitFactor, true); + + break; + } + case RANGED_ATTACK: + break; + } + } + if (!damage) { // Rage from absorbed damage @@ -651,41 +687,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa duel_hasEnded = true; } - // Rage from Damage made (only from direct weapon damage) - if (cleanDamage && damagetype==DIRECT_DAMAGE && this != pVictim && getPowerType() == POWER_RAGE) - { - uint32 weaponSpeedHitFactor; - uint32 rage_damage = damage + cleanDamage->absorbed_damage; - - switch(cleanDamage->attackType) - { - case BASE_ATTACK: - { - if (cleanDamage->hitOutCome == MELEE_HIT_CRIT) - weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 7); - else - weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 3.5f); - - RewardRage(rage_damage, weaponSpeedHitFactor, true); - - break; - } - case OFF_ATTACK: - { - if (cleanDamage->hitOutCome == MELEE_HIT_CRIT) - weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 3.5f); - else - weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 1.75f); - - RewardRage(rage_damage, weaponSpeedHitFactor, true); - - break; - } - case RANGED_ATTACK: - break; - } - } - if (GetTypeId() == TYPEID_PLAYER && this != pVictim) { Player *killer = ((Player*)this); @@ -1849,6 +1850,14 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff RemainingDamage -= int32(currentAbsorb * pVictim->GetTotalAttackPowerValue(BASE_ATTACK) / 100); continue; } + // Moonkin Form passive + if (spellProto->Id == 69366) + { + //reduces all damage taken while Stunned + if (unitflag & UNIT_FLAG_STUNNED) + RemainingDamage -= RemainingDamage * currentAbsorb / 100; + continue; + } break; } case SPELLFAMILY_ROGUE: @@ -6557,7 +6566,20 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger // Sacred Shield if (dummySpell->SpellFamilyFlags[1]&0x00080000) { - triggered_spell_id = 58597; + if (procFlag & PROC_FLAG_TAKEN_POSITIVE_MAGIC_SPELL) + { + if (procSpell->SpellFamilyName == SPELLFAMILY_PALADIN + && (procSpell->SpellFamilyFlags[0] & 0x40000000)) + { + basepoints0 = int32(float(damage)/12.0f); + CastCustomSpell(this,66922,&basepoints0,NULL,NULL,true,0,triggeredByAura, pVictim->GetGUID()); + return true; + } + else + return false; + } + else + triggered_spell_id = 58597; target = this; break; } @@ -8556,11 +8578,14 @@ bool Unit::IsHostileTo(Unit const* unit) const //= PvP states // Green/Blue (can't attack) - if(pTester->GetTeam()==pTarget->GetTeam()) - return false; + if (!pTester->HasAuraType(SPELL_AURA_MOD_FACTION) && !pTarget->HasAuraType(SPELL_AURA_MOD_FACTION)) + { + if(pTester->GetTeam()==pTarget->GetTeam()) + return false; - // Red (can attack) if true, Blue/Yellow (can't attack) in another case - return pTester->IsPvP() && pTarget->IsPvP(); + // Red (can attack) if true, Blue/Yellow (can't attack) in another case + return pTester->IsPvP() && pTarget->IsPvP(); + } } // faction base cases @@ -8573,7 +8598,7 @@ bool Unit::IsHostileTo(Unit const* unit) const return true; // PvC forced reaction and reputation case - if(tester->GetTypeId() == TYPEID_PLAYER) + if(tester->GetTypeId() == TYPEID_PLAYER && !tester->HasAuraType(SPELL_AURA_MOD_FACTION)) { // forced reaction if(target_faction->faction) @@ -8588,7 +8613,7 @@ bool Unit::IsHostileTo(Unit const* unit) const } } // CvP forced reaction and reputation case - else if(target->GetTypeId() == TYPEID_PLAYER) + else if(target->GetTypeId() == TYPEID_PLAYER && !target->HasAuraType(SPELL_AURA_MOD_FACTION)) { // forced reaction if(tester_faction->faction) @@ -8668,11 +8693,14 @@ bool Unit::IsFriendlyTo(Unit const* unit) const //= PvP states // Green/Blue (non-attackable) - if(pTester->GetTeam()==pTarget->GetTeam()) - return true; + if (!pTester->HasAuraType(SPELL_AURA_MOD_FACTION) && !pTarget->HasAuraType(SPELL_AURA_MOD_FACTION)) + { + if(pTester->GetTeam()==pTarget->GetTeam()) + return true; - // Blue (friendly/non-attackable) if not PVP, or Yellow/Red in another case (attackable) - return !pTarget->IsPvP(); + // Blue (friendly/non-attackable) if not PVP, or Yellow/Red in another case (attackable) + return !pTarget->IsPvP(); + } } // faction base cases @@ -8685,7 +8713,7 @@ bool Unit::IsFriendlyTo(Unit const* unit) const return false; // PvC forced reaction and reputation case - if (tester->GetTypeId() == TYPEID_PLAYER) + if (tester->GetTypeId() == TYPEID_PLAYER && !tester->HasAuraType(SPELL_AURA_MOD_FACTION)) { // forced reaction if (target_faction->faction) @@ -8700,7 +8728,7 @@ bool Unit::IsFriendlyTo(Unit const* unit) const } } // CvP forced reaction and reputation case - else if (target->GetTypeId() == TYPEID_PLAYER) + else if (target->GetTypeId() == TYPEID_PLAYER && !target->HasAuraType(SPELL_AURA_MOD_FACTION)) { // forced reaction if (tester_faction->faction) @@ -9547,14 +9575,14 @@ void Unit::UnsummonAllTotems() void Unit::SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, uint32 OverHeal, bool critical) { // we guess size - WorldPacket data(SMSG_SPELLHEALLOG, (8+8+4+4+1)); + WorldPacket data(SMSG_SPELLHEALLOG, (8+8+4+4+4+4+1)); data.append(pVictim->GetPackGUID()); data.append(GetPackGUID()); data << uint32(SpellID); data << uint32(Damage); data << uint32(OverHeal); + data << uint32(0); // Absorb amount data << uint8(critical ? 1 : 0); - data << uint8(0); // unused in client? SendMessageToSet(&data, true); } @@ -10646,6 +10674,14 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo) return true; } + for (int i=0;i<3;++i) + { + // State/effect immunities applied by aura expect full spell immunity + // However function also check for mechanic, so ignore that for now + if (IsImmunedToSpellEffect(spellInfo, i, false)) + return true; + } + if (spellInfo->Id != 42292 && spellInfo->Id !=59752) { SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; @@ -10659,7 +10695,7 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo) return false; } -bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const +bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index, bool checkMechanic) const { if (!spellInfo) return false; @@ -10670,12 +10706,15 @@ bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) con if (itr->type == effect) return true; - if (uint32 mechanic = spellInfo->EffectMechanic[index]) + if (checkMechanic) { - SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; - for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) - if (itr->type == spellInfo->EffectMechanic[index]) - return true; + if (uint32 mechanic = spellInfo->EffectMechanic[index]) + { + SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; + for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) + if (itr->type == spellInfo->EffectMechanic[index]) + return true; + } } if (uint32 aura = spellInfo->EffectApplyAuraName[index]) @@ -11061,7 +11100,7 @@ float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellEntry * s return uint32((WeaponSpeed * PPM) / 600.0f); // result is chance in percents (probability = Speed_in_sec * (PPM / 60)) } -void Unit::Mount(uint32 mount) +void Unit::Mount(uint32 mount, uint32 VehicleId) { RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT); @@ -11083,6 +11122,27 @@ void Unit::Mount(uint32 mount) else ((Player*)this)->UnsummonPetTemporaryIfAny(); } + + if(VehicleId !=0) + { + if(VehicleEntry const *ve = sVehicleStore.LookupEntry(VehicleId)) + { + + if (CreateVehicleKit(VehicleId)) + { + GetVehicleKit()->Reset(); + + // Send others that we now have a vehicle + WorldPacket data( SMSG_PLAYER_VEHICLE_DATA, GetPackGUID().size()+4); + data.appendPackGUID(GetGUID()); + data << uint32(VehicleId); + SendMessageToSet( &data,true ); + + data.Initialize(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); + ((Player*)this)->GetSession()->SendPacket( &data ); + } + } + } } } @@ -11110,6 +11170,16 @@ void Unit::Unmount() else ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny(); } + if(GetTypeId()==TYPEID_PLAYER && GetVehicleKit()) + { + // Send other players that we are no longer a vehicle + WorldPacket data( SMSG_PLAYER_VEHICLE_DATA, 8+4 ); + data.appendPackGUID(GetGUID()); + data << uint32(0); + ((Player*)this)->SendMessageToSet(&data, true); + // Remove vehicle class from player + RemoveVehicleKit(); + } } void Unit::SetInCombatWith(Unit* enemy) @@ -11455,9 +11525,9 @@ bool Unit::canDetectStealthOf(Unit const* target, float distance) const return true; //Visible distance based on stealth value (stealth rank 4 300MOD, 10.5 - 3 = 7.5) - float visibleDistance = 10.5f - target->GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH) / 100.0f; + float visibleDistance = 7.5f; //Visible distance is modified by -Level Diff (every level diff = 1.0f in visible distance) - visibleDistance += int32(getLevelForTarget(target)) - int32(target->getLevelForTarget(this)); + visibleDistance += float(getLevelForTarget(target)) - target->GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH)/5.0f; //-Stealth Mod(positive like Master of Deception) and Stealth Detection(negative like paranoia) //based on wowwiki every 5 mod we have 1 more level diff in calculation visibleDistance += (float)(GetTotalAuraModifier(SPELL_AURA_MOD_DETECT) - target->GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH_LEVEL)) / 5.0f; @@ -12195,7 +12265,7 @@ void Unit::ModSpellCastTime(SpellEntry const* spellProto, int32 & castTime, Spel if (Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CASTING_TIME, castTime, spell); - if (!(spellProto->Attributes & (SPELL_ATTR_UNK4|SPELL_ATTR_TRADESPELL)) && spellProto->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && spellProto->SpellFamilyName) + if (!(spellProto->Attributes & (SPELL_ATTR_UNK4|SPELL_ATTR_TRADESPELL)) && spellProto->SpellFamilyName) castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); else { @@ -14918,6 +14988,22 @@ bool Unit::CreateVehicleKit(uint32 id) return true; } +void Unit::RemoveVehicleKit() +{ + if (!m_vehicleKit) + return; + + m_vehicleKit->Uninstall(); + delete m_vehicleKit; + + m_vehicleKit = NULL; + + m_updateFlag &= ~UPDATEFLAG_VEHICLE; + m_unitTypeMask &= ~UNIT_MASK_VEHICLE; + RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); +} + Unit *Unit::GetVehicleBase() const { return m_vehicle ? m_vehicle->GetBase() : NULL; diff --git a/src/game/Unit.h b/src/game/Unit.h index dba30f176f5..3c558c225a7 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -631,6 +631,7 @@ enum NPCFlags UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100% UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click), dynamic, set at loading and don't must be set in DB + UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set UNIT_NPC_FLAG_GUARD = 0x10000000, // custom flag for guards UNIT_NPC_FLAG_OUTDOORPVP = 0x20000000, // custom flag for outdoor pvp creatures }; @@ -1272,7 +1273,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); } uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); } - void Mount(uint32 mount); + void Mount(uint32 mount, uint32 vehicleId=0); void Unmount(); uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } @@ -1817,7 +1818,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject // redefined in Creature bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask); bool IsImmunedToDamage(SpellEntry const* spellInfo); - virtual bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const; + virtual bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index, bool checkMechanic=true) const; // redefined in Creature uint32 CalcNotIgnoreDamageRedunction( uint32 damage, SpellSchoolMask damageSchoolMask); uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType=MAX_ATTACK); @@ -1913,6 +1914,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject bool IsAIEnabled, NeedChangeAI; MovementInfo m_movementInfo; bool CreateVehicleKit(uint32 id); + void RemoveVehicleKit(); Vehicle *GetVehicleKit()const { return m_vehicleKit; } Vehicle *GetVehicle() const { return m_vehicle; } bool IsOnVehicle(const Unit *unit) const { return m_vehicle && m_vehicle == unit->GetVehicleKit(); } diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp index 567630a048e..a4a09389552 100644 --- a/src/game/Vehicle.cpp +++ b/src/game/Vehicle.cpp @@ -151,9 +151,18 @@ void Vehicle::Die() void Vehicle::Reset() { sLog.outDebug("Vehicle::Reset"); - InstallAllAccessories(); if(m_usableSeatNum) - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + { + if (me->GetTypeId() == TYPEID_PLAYER) + { + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); + } + else + { + InstallAllAccessories(); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + } + } } void Vehicle::RemoveAllPassengers() @@ -275,7 +284,12 @@ bool Vehicle::AddPassenger(Unit *unit, int8 seatId) assert(m_usableSeatNum); --m_usableSeatNum; if(!m_usableSeatNum) - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + { + if (me->GetTypeId() == TYPEID_PLAYER) + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); + else + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + } } if(seat->second.seatInfo->m_flags && !(seat->second.seatInfo->m_flags & 0x400)) @@ -292,21 +306,24 @@ bool Vehicle::AddPassenger(Unit *unit, int8 seatId) unit->m_movementInfo.t_time = 0; // 1 for player unit->m_movementInfo.t_seat = seat->first; - if(unit->GetTypeId() == TYPEID_PLAYER && seat->first == 0 && seat->second.seatInfo->m_flags & 0x800) // not right + if(me->GetTypeId() == TYPEID_UNIT + && unit->GetTypeId() == TYPEID_PLAYER + && seat->first == 0 && seat->second.seatInfo->m_flags & 0x800) // not right if (!me->SetCharmedBy(unit, CHARM_TYPE_VEHICLE)) assert(false); - if(me->GetTypeId() == TYPEID_UNIT) + if(me->IsInWorld()) { - if(me->IsInWorld()) + unit->SendMonsterMoveTransport(me); + + if(me->GetTypeId() == TYPEID_UNIT) { - unit->SendMonsterMoveTransport(me); + if(((Creature*)me)->IsAIEnabled) + ((Creature*)me)->AI()->PassengerBoarded(unit, seat->first, true); + // move self = move all passengers me->GetMap()->CreatureRelocation((Creature*)me, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); } - - if(((Creature*)me)->IsAIEnabled) - ((Creature*)me)->AI()->PassengerBoarded(unit, seat->first, true); } //if(unit->GetTypeId() == TYPEID_PLAYER) @@ -334,7 +351,12 @@ void Vehicle::RemovePassenger(Unit *unit) if(seat->second.seatInfo->IsUsable()) { if(!m_usableSeatNum) - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + { + if (me->GetTypeId() == TYPEID_PLAYER) + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); + else + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + } ++m_usableSeatNum; } @@ -342,7 +364,9 @@ void Vehicle::RemovePassenger(Unit *unit) //SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - if(unit->GetTypeId() == TYPEID_PLAYER && seat->first == 0 && seat->second.seatInfo->m_flags & 0x800) + if(me->GetTypeId() == TYPEID_UNIT + && unit->GetTypeId() == TYPEID_PLAYER + && seat->first == 0 && seat->second.seatInfo->m_flags & 0x800) me->RemoveCharmedBy(unit); if(me->GetTypeId() == TYPEID_UNIT && ((Creature*)me)->IsAIEnabled) diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 569c8fade62..d442d4c359e 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -30,6 +30,7 @@ #include "WorldPacket.h" #include "WorldSession.h" #include "Player.h" +#include "Vehicle.h" #include "ObjectMgr.h" #include "Group.h" #include "Guild.h" @@ -937,6 +938,39 @@ void WorldSession::SendAddonsInfo() SendPacket(&data); } + +void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data) +{ + // Read guid + uint64 guid; + data >> guid; + + if(Player* pl=ObjectAccessor::FindPlayer(guid)) + { + if (!pl->GetVehicleKit()) + return; + if (!pl->IsInRaidWith(_player)) + return; + if(!pl->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + return; + _player->EnterVehicle(pl); + } +} + +void WorldSession::HandleEjectPasenger(WorldPacket &data) +{ + if(data.GetOpcode()==CMSG_EJECT_PASSENGER) + { + if(Vehicle* Vv= _player->GetVehicleKit()) + { + uint64 guid; + data >> guid; + if(Player* Pl=ObjectAccessor::FindPlayer(guid)) + Pl->ExitVehicle(); + } + } + } + void WorldSession::SetPlayer( Player *plr ) { _player = plr; diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 7e81a3d338f..93c5529eddb 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -748,6 +748,8 @@ class TRINITY_DLL_SPEC WorldSession bool HandleOnItemOpen(Item *pItem); bool HandleOnGoClick(GameObject *pGameObject); void HandleOnCreatureKill(Creature *pCreature); + void HandleEjectPasenger(WorldPacket &data); + void HandleEnterPlayerVehicle(WorldPacket &data); private: // private trade methods void moveItems(Item* myItems[], Item* hisItems[]); |