diff options
Diffstat (limited to 'src/game')
| -rw-r--r-- | src/game/AuctionHouseBot.cpp | 39 | ||||
| -rw-r--r-- | src/game/CombatHandler.cpp | 10 | ||||
| -rw-r--r-- | src/game/CreatureAI.cpp | 36 | ||||
| -rw-r--r-- | src/game/DynamicObject.cpp | 2 | ||||
| -rw-r--r-- | src/game/GridNotifiersImpl.h | 2 | ||||
| -rw-r--r-- | src/game/NPCHandler.cpp | 17 | ||||
| -rw-r--r-- | src/game/PetHandler.cpp | 12 | ||||
| -rw-r--r-- | src/game/Player.cpp | 528 | ||||
| -rw-r--r-- | src/game/Player.h | 3 | ||||
| -rw-r--r-- | src/game/SharedDefines.h | 5 | ||||
| -rw-r--r-- | src/game/Spell.cpp | 52 | ||||
| -rw-r--r-- | src/game/Spell.h | 2 | ||||
| -rw-r--r-- | src/game/SpellEffects.cpp | 8 | ||||
| -rw-r--r-- | src/game/SpellHandler.cpp | 6 | ||||
| -rw-r--r-- | src/game/SpellMgr.cpp | 9 | ||||
| -rw-r--r-- | src/game/Unit.cpp | 54 | ||||
| -rw-r--r-- | src/game/Unit.h | 4 |
17 files changed, 400 insertions, 389 deletions
diff --git a/src/game/AuctionHouseBot.cpp b/src/game/AuctionHouseBot.cpp index b2b06faae84..08b4695125f 100644 --- a/src/game/AuctionHouseBot.cpp +++ b/src/game/AuctionHouseBot.cpp @@ -503,14 +503,25 @@ static void addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, World } } + uint32 bids = config->GetBidsPerInterval(); + for (uint32 count = 1;count <= bids;count++) + { + // Do we have anything to bid? If not, stop here. if(possibleBids.empty()) { + count = bids + 1; return; } // Choose random auction from possible auctions - uint32 auctionID = possibleBids[urand(0, possibleBids.size() - 1)]; + uint32 vectorPos = urand(0, possibleBids.size() - 1); + uint32 auctionID = possibleBids[vectorPos]; + + // Erase the auction from the vector to prevent bidding on item in next itteration. + vector<uint32>::iterator iter = possibleBids.begin(); + advance(iter, vectorPos); + possibleBids.erase(iter); // from auctionhousehandler.cpp, creates auction pointer & player pointer AuctionEntry* auction = auctionHouse->GetAuction(auctionID); @@ -758,7 +769,7 @@ static void addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, World auctionHouse->RemoveAuction(auction->Id); // Remove from database auction->DeleteFromDB(); - + } delete auction; } } @@ -781,33 +792,21 @@ void AuctionHouseBot() addNewAuctions(&_AHBplayer, &AllianceConfig); if (((_newrun - _lastrun_a) > (AllianceConfig.GetBiddingInterval() * 60)) && (AllianceConfig.GetBidsPerInterval() > 0)) { - uint32 bids = AllianceConfig.GetBidsPerInterval(); - for (uint32 count = 1;count <= bids;count++) - { - addNewAuctionBuyerBotBid(&_AHBplayer, &AllianceConfig, &_session); - _lastrun_a = _newrun; - } + addNewAuctionBuyerBotBid(&_AHBplayer, &AllianceConfig, &_session); + _lastrun_a = _newrun; } addNewAuctions(&_AHBplayer, &HordeConfig); if (((_newrun - _lastrun_h) > (HordeConfig.GetBiddingInterval() *60)) && (HordeConfig.GetBidsPerInterval() > 0)) { - uint32 bids = HordeConfig.GetBidsPerInterval(); - for (uint32 count = 1;count <= bids;count++) - { - addNewAuctionBuyerBotBid(&_AHBplayer, &HordeConfig, &_session); - _lastrun_h = _newrun; - } + addNewAuctionBuyerBotBid(&_AHBplayer, &HordeConfig, &_session); + _lastrun_h = _newrun; } } addNewAuctions(&_AHBplayer, &NeutralConfig); if (((_newrun - _lastrun_n) > (NeutralConfig.GetBiddingInterval() * 60)) && (NeutralConfig.GetBidsPerInterval() > 0)) { - uint32 bids = NeutralConfig.GetBidsPerInterval(); - for (uint32 count = 1;count <= bids;count++) - { - addNewAuctionBuyerBotBid(&_AHBplayer, &NeutralConfig, &_session); - _lastrun_n = _newrun; - } + addNewAuctionBuyerBotBid(&_AHBplayer, &NeutralConfig, &_session); + _lastrun_n = _newrun; } ObjectAccessor::Instance().RemoveObject(&_AHBplayer); } diff --git a/src/game/CombatHandler.cpp b/src/game/CombatHandler.cpp index 878d8e35648..f732f128fd0 100644 --- a/src/game/CombatHandler.cpp +++ b/src/game/CombatHandler.cpp @@ -49,7 +49,7 @@ void WorldSession::HandleAttackSwingOpcode( WorldPacket & recv_data ) return; } - if(_player->IsFriendlyTo(pEnemy) || pEnemy->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) + if(!_player->canAttack(pEnemy)) { sLog.outError( "WORLD: Enemy %s %u is friendly",(IS_PLAYER_GUID(guid) ? "player" : "creature"),GUID_LOPART(guid)); @@ -58,14 +58,6 @@ void WorldSession::HandleAttackSwingOpcode( WorldPacket & recv_data ) return; } - if(!pEnemy->isAlive()) - { - // client can generate swing to known dead target if autoswitch between autoshot and autohit is enabled in client options - // stop attack state at client - SendAttackStop(pEnemy); - return; - } - _player->Attack(pEnemy,true); } diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index 4668578c1be..6f0b5949236 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -71,26 +71,36 @@ void CreatureAI::OnCharmed(bool apply) me->IsAIEnabled = false; } -void CreatureAI::DoZoneInCombat(Creature* pUnit) +void CreatureAI::DoZoneInCombat(Creature* creature) { - if (!pUnit) - pUnit = me; - - Map *map = pUnit->GetMap(); + if (!creature) + creature = me; + Map *map = creature->GetMap(); if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated { - sLog.outError("DoZoneInCombat call for map that isn't an instance (pUnit entry = %d)", pUnit->GetTypeId() == TYPEID_UNIT ? ((Creature*)pUnit)->GetEntry() : 0); + sLog.outError("DoZoneInCombat call for map that isn't an instance (creature entry = %d)", creature->GetTypeId() == TYPEID_UNIT ? ((Creature*)creature)->GetEntry() : 0); return; } - if(!pUnit->getVictim()) - if(Unit *target = pUnit->SelectNearestTarget()) + if(!creature->getVictim()) + { + if(Unit *target = creature->SelectNearestTarget()) AttackStart(target); + else if(creature->isSummon()) + { + if(Unit *summoner = ((TempSummon*)creature)->GetSummoner()) + { + if(summoner->getVictim() + && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(summoner->getVictim()))) + AttackStart(summoner->getVictim()); + } + } + } - if (!pUnit->CanHaveThreatList() || pUnit->getThreatManager().isThreatListEmpty()) + if (!creature->CanHaveThreatList() || creature->getThreatManager().isThreatListEmpty()) { - sLog.outError("DoZoneInCombat called for creature that either cannot have threat list or has empty threat list (pUnit entry = %d)", pUnit->GetTypeId() == TYPEID_UNIT ? ((Creature*)pUnit)->GetEntry() : 0); + sLog.outError("DoZoneInCombat called for creature that either cannot have threat list or has empty threat list (creature entry = %d)", creature->GetTypeId() == TYPEID_UNIT ? ((Creature*)creature)->GetEntry() : 0); return; } @@ -100,9 +110,9 @@ void CreatureAI::DoZoneInCombat(Creature* pUnit) if (Player* i_pl = i->getSource()) if (i_pl->isAlive()) { - pUnit->SetInCombatWith(i_pl); - i_pl->SetInCombatWith(pUnit); - pUnit->AddThreat(i_pl, 0.0f); + creature->SetInCombatWith(i_pl); + i_pl->SetInCombatWith(creature); + creature->AddThreat(i_pl, 0.0f); } } } diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index d294886619c..8969e4dfe04 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -88,7 +88,7 @@ bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, uint32 SetUInt64Value( DYNAMICOBJECT_CASTER, caster->GetGUID() ); SetUInt32Value( DYNAMICOBJECT_BYTES, 0x00000001 ); SetUInt32Value( DYNAMICOBJECT_SPELLID, spellId ); - SetFloatValue( DYNAMICOBJECT_RADIUS, radius * 2); //diameter? + SetFloatValue( DYNAMICOBJECT_RADIUS, radius); SetFloatValue( DYNAMICOBJECT_POS_X, x ); SetFloatValue( DYNAMICOBJECT_POS_Y, y ); SetFloatValue( DYNAMICOBJECT_POS_Z, z ); diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index 7fc6c147f5b..54cbff2c7bb 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -180,7 +180,7 @@ inline void Trinity::DynamicObjectUpdater::VisitHelper(Unit* target) SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId()); uint32 eff_index = i_dynobject.GetEffIndex(); - if(spellInfo->EffectImplicitTargetB[eff_index] == TARGET_UNIT_AREA_ALLY_CHANNEL + if(spellInfo->EffectImplicitTargetB[eff_index] == TARGET_DEST_DYNOBJ_ALLY || spellInfo->EffectImplicitTargetB[eff_index] == TARGET_UNIT_AREA_ALLY_GROUND) { if(!i_check->IsFriendlyTo(target)) diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 7d2985c0643..30d316afd83 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -157,6 +157,7 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) // reputation discount float fDiscountMod = _player->GetReputationPriceDiscount(unit); + bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProffesionPoints() > 0; uint32 count = 0; for(TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) @@ -166,25 +167,27 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell)) continue; - ++count; - bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell); - SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->learnedSpell); uint32 req_spell = spellmgr.GetSpellRequired(tSpell->spell); + TrainerSpellState state = _player->GetTrainerSpellState(tSpell); data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) - data << uint8(_player->GetTrainerSpellState(tSpell)); + data << uint8(state==TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); data << uint32(floor(tSpell->spellCost * fDiscountMod)); - data << uint32(primary_prof_first_rank ? 1 : 0); // primary prof. learn confirmation dialog + data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0); + // primary prof. learn confirmation dialog data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state data << uint8(tSpell->reqLevel); data << uint32(tSpell->reqSkill); data << uint32(tSpell->reqSkillValue); - data << uint32(chain_node && chain_node->prev ? chain_node->prev : req_spell); - data << uint32(chain_node && chain_node->prev ? req_spell : 0); + //prev + req or req + 0 + data << uint32(!tSpell->IsCastable() && chain_node && chain_node->prev ? chain_node->prev : req_spell); + data << uint32(!tSpell->IsCastable() && chain_node && chain_node->prev ? req_spell : 0); data << uint32(0); + + ++count; } data << strTitle; diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index 79cb16e0637..71ae527e7d7 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -116,20 +116,20 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid //TODO: Send proper error message to client return; } + // only place where pet can be player - pet->clearUnitState(UNIT_STAT_FOLLOW); - const uint64& selguid = _player->GetSelection(); - Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, selguid); + Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, guid2); if(!TargetUnit) return; - // not let attack friendly units. - if(GetPlayer()->IsFriendlyTo(TargetUnit)) + if(!pet->canAttack(TargetUnit)) return; + // Not let attack through obstructions //if(!pet->IsWithinLOSInMap(TargetUnit)) // return; + pet->clearUnitState(UNIT_STAT_FOLLOW); // This is true if pet has no target or has target but targets differs. if(pet->getVictim() != TargetUnit) { @@ -209,7 +209,7 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid for(uint32 i = 0; i < 3;++i) { - if(spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED) + if(spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_DYNOBJ_ENEMY) return; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index c5325de71ab..a5a33c7d2fd 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3785,7 +3785,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell // check primary prof. limit if(spellmgr.IsPrimaryProfessionFirstRankSpell(spell->Id) && GetFreePrimaryProffesionPoints() == 0) - return TRAINER_SPELL_RED; + return TRAINER_SPELL_GREEN_DISABLED; return TRAINER_SPELL_GREEN; } @@ -11721,301 +11721,303 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a return; if (!item->IsBroken()) - for (int s=0; s<3; s++) { - uint32 enchant_display_type = pEnchant->type[s]; - uint32 enchant_amount = pEnchant->amount[s]; - uint32 enchant_spell_id = pEnchant->spellid[s]; - - switch(enchant_display_type) + for (int s=0; s<3; s++) { - case ITEM_ENCHANTMENT_TYPE_NONE: - break; - case ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL: - // processed in Player::CastItemCombatSpell - break; - case ITEM_ENCHANTMENT_TYPE_DAMAGE: - if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) - HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(enchant_amount), apply); - else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND) - HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(enchant_amount), apply); - else if (item->GetSlot() == EQUIPMENT_SLOT_RANGED) - HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(enchant_amount), apply); - break; - case ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL: - if(enchant_spell_id) - { - if(apply) + uint32 enchant_display_type = pEnchant->type[s]; + uint32 enchant_amount = pEnchant->amount[s]; + uint32 enchant_spell_id = pEnchant->spellid[s]; + + switch(enchant_display_type) + { + case ITEM_ENCHANTMENT_TYPE_NONE: + break; + case ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL: + // processed in Player::CastItemCombatSpell + break; + case ITEM_ENCHANTMENT_TYPE_DAMAGE: + if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) + HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(enchant_amount), apply); + else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND) + HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(enchant_amount), apply); + else if (item->GetSlot() == EQUIPMENT_SLOT_RANGED) + HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + break; + case ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL: + if(enchant_spell_id) { - int32 basepoints = 0; - // Random Property Exist - try found basepoints for spell (basepoints depends from item suffix factor) - if (item->GetItemRandomPropertyId()) + if(apply) { - ItemRandomSuffixEntry const *item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); - if (item_rand) + int32 basepoints = 0; + // Random Property Exist - try found basepoints for spell (basepoints depends from item suffix factor) + if (item->GetItemRandomPropertyId()) { - // Search enchant_amount - for (int k=0; k<3; k++) + ItemRandomSuffixEntry const *item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); + if (item_rand) { - if(item_rand->enchant_id[k] == enchant_id) + // Search enchant_amount + for (int k=0; k<3; k++) { - basepoints = int32((item_rand->prefix[k]*item->GetItemSuffixFactor()) / 10000 ); - break; + if(item_rand->enchant_id[k] == enchant_id) + { + basepoints = int32((item_rand->prefix[k]*item->GetItemSuffixFactor()) / 10000 ); + break; + } } } } + // Cast custom spell vs all equal basepoints getted from enchant_amount + if (basepoints) + CastCustomSpell(this,enchant_spell_id,&basepoints,&basepoints,&basepoints,true,item); + else + CastSpell(this,enchant_spell_id,true,item); } - // Cast custom spell vs all equal basepoints getted from enchant_amount - if (basepoints) - CastCustomSpell(this,enchant_spell_id,&basepoints,&basepoints,&basepoints,true,item); else - CastSpell(this,enchant_spell_id,true,item); + RemoveAurasDueToItemSpell(item,enchant_spell_id); } - else - RemoveAurasDueToItemSpell(item,enchant_spell_id); - } - break; - case ITEM_ENCHANTMENT_TYPE_RESISTANCE: - if (!enchant_amount) - { - ItemRandomSuffixEntry const *item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); - if(item_rand) + break; + case ITEM_ENCHANTMENT_TYPE_RESISTANCE: + if (!enchant_amount) { - for (int k=0; k<3; k++) + ItemRandomSuffixEntry const *item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); + if(item_rand) { - if(item_rand->enchant_id[k] == enchant_id) + for (int k=0; k<3; k++) { - enchant_amount = uint32((item_rand->prefix[k]*item->GetItemSuffixFactor()) / 10000 ); - break; + if(item_rand->enchant_id[k] == enchant_id) + { + enchant_amount = uint32((item_rand->prefix[k]*item->GetItemSuffixFactor()) / 10000 ); + break; + } } } } - } - HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply); - break; - case ITEM_ENCHANTMENT_TYPE_STAT: - { - if (!enchant_amount) + HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply); + break; + case ITEM_ENCHANTMENT_TYPE_STAT: { - ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); - if(item_rand_suffix) + if (!enchant_amount) { - for (int k=0; k<3; k++) + ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); + if(item_rand_suffix) { - if(item_rand_suffix->enchant_id[k] == enchant_id) + for (int k=0; k<3; k++) { - enchant_amount = uint32((item_rand_suffix->prefix[k]*item->GetItemSuffixFactor()) / 10000 ); - break; + if(item_rand_suffix->enchant_id[k] == enchant_id) + { + enchant_amount = uint32((item_rand_suffix->prefix[k]*item->GetItemSuffixFactor()) / 10000 ); + break; + } } } } - } - sLog.outDebug("Adding %u to stat nb %u",enchant_amount,enchant_spell_id); - switch (enchant_spell_id) - { - case ITEM_MOD_AGILITY: - sLog.outDebug("+ %u AGILITY",enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_AGILITY, enchant_amount, apply); - break; - case ITEM_MOD_STRENGTH: - sLog.outDebug("+ %u STRENGTH",enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_STRENGTH, enchant_amount, apply); - break; - case ITEM_MOD_INTELLECT: - sLog.outDebug("+ %u INTELLECT",enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_INTELLECT, enchant_amount, apply); - break; - case ITEM_MOD_SPIRIT: - sLog.outDebug("+ %u SPIRIT",enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_SPIRIT, enchant_amount, apply); - break; - case ITEM_MOD_STAMINA: - sLog.outDebug("+ %u STAMINA",enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_STAMINA, enchant_amount, apply); - break; - case ITEM_MOD_DEFENSE_SKILL_RATING: - ((Player*)this)->ApplyRatingMod(CR_DEFENSE_SKILL, enchant_amount, apply); - sLog.outDebug("+ %u DEFENCE", enchant_amount); - break; - case ITEM_MOD_DODGE_RATING: - ((Player*)this)->ApplyRatingMod(CR_DODGE, enchant_amount, apply); - sLog.outDebug("+ %u DODGE", enchant_amount); - break; - case ITEM_MOD_PARRY_RATING: - ((Player*)this)->ApplyRatingMod(CR_PARRY, enchant_amount, apply); - sLog.outDebug("+ %u PARRY", enchant_amount); - break; - case ITEM_MOD_BLOCK_RATING: - ((Player*)this)->ApplyRatingMod(CR_BLOCK, enchant_amount, apply); - sLog.outDebug("+ %u SHIELD_BLOCK", enchant_amount); - break; - case ITEM_MOD_HIT_MELEE_RATING: - ((Player*)this)->ApplyRatingMod(CR_HIT_MELEE, enchant_amount, apply); - sLog.outDebug("+ %u MELEE_HIT", enchant_amount); - break; - case ITEM_MOD_HIT_RANGED_RATING: - ((Player*)this)->ApplyRatingMod(CR_HIT_RANGED, enchant_amount, apply); - sLog.outDebug("+ %u RANGED_HIT", enchant_amount); - break; - case ITEM_MOD_HIT_SPELL_RATING: - ((Player*)this)->ApplyRatingMod(CR_HIT_SPELL, enchant_amount, apply); - sLog.outDebug("+ %u SPELL_HIT", enchant_amount); - break; - case ITEM_MOD_CRIT_MELEE_RATING: - ((Player*)this)->ApplyRatingMod(CR_CRIT_MELEE, enchant_amount, apply); - sLog.outDebug("+ %u MELEE_CRIT", enchant_amount); - break; - case ITEM_MOD_CRIT_RANGED_RATING: - ((Player*)this)->ApplyRatingMod(CR_CRIT_RANGED, enchant_amount, apply); - sLog.outDebug("+ %u RANGED_CRIT", enchant_amount); - break; - case ITEM_MOD_CRIT_SPELL_RATING: - ((Player*)this)->ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply); - sLog.outDebug("+ %u SPELL_CRIT", enchant_amount); - break; -// Values from ITEM_STAT_MELEE_HA_RATING to ITEM_MOD_HASTE_RANGED_RATING are never used -// in Enchantments -// case ITEM_MOD_HIT_TAKEN_MELEE_RATING: -// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply); -// break; -// case ITEM_MOD_HIT_TAKEN_RANGED_RATING: -// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply); -// break; -// case ITEM_MOD_HIT_TAKEN_SPELL_RATING: -// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply); -// break; -// case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: -// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); -// break; -// case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: -// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); -// break; -// case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: -// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); -// break; -// case ITEM_MOD_HASTE_MELEE_RATING: -// ((Player*)this)->ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply); -// break; -// case ITEM_MOD_HASTE_RANGED_RATING: -// ((Player*)this)->ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply); -// break; - case ITEM_MOD_HASTE_SPELL_RATING: - ((Player*)this)->ApplyRatingMod(CR_HASTE_SPELL, enchant_amount, apply); - break; - case ITEM_MOD_HIT_RATING: - ((Player*)this)->ApplyRatingMod(CR_HIT_MELEE, enchant_amount, apply); - ((Player*)this)->ApplyRatingMod(CR_HIT_RANGED, enchant_amount, apply); - ((Player*)this)->ApplyRatingMod(CR_HIT_SPELL, enchant_amount, apply); - sLog.outDebug("+ %u HIT", enchant_amount); - break; - case ITEM_MOD_CRIT_RATING: - ((Player*)this)->ApplyRatingMod(CR_CRIT_MELEE, enchant_amount, apply); - ((Player*)this)->ApplyRatingMod(CR_CRIT_RANGED, enchant_amount, apply); - ((Player*)this)->ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply); - sLog.outDebug("+ %u CRITICAL", enchant_amount); - break; -// Values ITEM_MOD_HIT_TAKEN_RATING and ITEM_MOD_CRIT_TAKEN_RATING are never used in Enchantment -// case ITEM_MOD_HIT_TAKEN_RATING: -// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply); -// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply); -// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply); -// break; -// case ITEM_MOD_CRIT_TAKEN_RATING: -// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); -// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); -// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); -// break; - case ITEM_MOD_RESILIENCE_RATING: - ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); - ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); - ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); - sLog.outDebug("+ %u RESILIENCE", enchant_amount); - break; - case ITEM_MOD_HASTE_RATING: - ((Player*)this)->ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply); - ((Player*)this)->ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply); - ((Player*)this)->ApplyRatingMod(CR_HASTE_SPELL, enchant_amount, apply); - sLog.outDebug("+ %u HASTE", enchant_amount); - break; - case ITEM_MOD_EXPERTISE_RATING: - ((Player*)this)->ApplyRatingMod(CR_EXPERTISE, enchant_amount, apply); - sLog.outDebug("+ %u EXPERTISE", enchant_amount); - break; - case ITEM_MOD_ATTACK_POWER: - HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply); - HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); - sLog.outDebug("+ %u ATTACK_POWER", enchant_amount); - break; - case ITEM_MOD_RANGED_ATTACK_POWER: - HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); - sLog.outDebug("+ %u RANGED_ATTACK_POWER", enchant_amount); - break; - case ITEM_MOD_FERAL_ATTACK_POWER: - ((Player*)this)->ApplyFeralAPBonus(enchant_amount, apply); - sLog.outDebug("+ %u FERAL_ATTACK_POWER", enchant_amount); - break; - case ITEM_MOD_SPELL_HEALING_DONE: - ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply); - sLog.outDebug("+ %u SPELL_HEALING_DONE", enchant_amount); - break; - case ITEM_MOD_SPELL_DAMAGE_DONE: - ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply); - sLog.outDebug("+ %u SPELL_DAMAGE_DONE", enchant_amount); - break; - case ITEM_MOD_MANA_REGENERATION: - ((Player*)this)->ApplyManaRegenBonus(enchant_amount, apply); - sLog.outDebug("+ %u MANA_REGENERATION", enchant_amount); - break; - case ITEM_MOD_ARMOR_PENETRATION_RATING: - ((Player*)this)->ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply); - sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount); - break; - case ITEM_MOD_SPELL_POWER: - ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply); - ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply); - sLog.outDebug("+ %u SPELL_POWER", enchant_amount); - break; - default: - break; - } - break; - } - case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon - { - if(getClass() == CLASS_SHAMAN) - { - float addValue = 0.0f; - if(item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) + sLog.outDebug("Adding %u to stat nb %u",enchant_amount,enchant_spell_id); + switch (enchant_spell_id) { - addValue = float(enchant_amount * item->GetProto()->Delay/1000.0f); - HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, addValue, apply); + case ITEM_MOD_AGILITY: + sLog.outDebug("+ %u AGILITY",enchant_amount); + HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply); + ApplyStatBuffMod(STAT_AGILITY, enchant_amount, apply); + break; + case ITEM_MOD_STRENGTH: + sLog.outDebug("+ %u STRENGTH",enchant_amount); + HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply); + ApplyStatBuffMod(STAT_STRENGTH, enchant_amount, apply); + break; + case ITEM_MOD_INTELLECT: + sLog.outDebug("+ %u INTELLECT",enchant_amount); + HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply); + ApplyStatBuffMod(STAT_INTELLECT, enchant_amount, apply); + break; + case ITEM_MOD_SPIRIT: + sLog.outDebug("+ %u SPIRIT",enchant_amount); + HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, float(enchant_amount), apply); + ApplyStatBuffMod(STAT_SPIRIT, enchant_amount, apply); + break; + case ITEM_MOD_STAMINA: + sLog.outDebug("+ %u STAMINA",enchant_amount); + HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply); + ApplyStatBuffMod(STAT_STAMINA, enchant_amount, apply); + break; + case ITEM_MOD_DEFENSE_SKILL_RATING: + ((Player*)this)->ApplyRatingMod(CR_DEFENSE_SKILL, enchant_amount, apply); + sLog.outDebug("+ %u DEFENCE", enchant_amount); + break; + case ITEM_MOD_DODGE_RATING: + ((Player*)this)->ApplyRatingMod(CR_DODGE, enchant_amount, apply); + sLog.outDebug("+ %u DODGE", enchant_amount); + break; + case ITEM_MOD_PARRY_RATING: + ((Player*)this)->ApplyRatingMod(CR_PARRY, enchant_amount, apply); + sLog.outDebug("+ %u PARRY", enchant_amount); + break; + case ITEM_MOD_BLOCK_RATING: + ((Player*)this)->ApplyRatingMod(CR_BLOCK, enchant_amount, apply); + sLog.outDebug("+ %u SHIELD_BLOCK", enchant_amount); + break; + case ITEM_MOD_HIT_MELEE_RATING: + ((Player*)this)->ApplyRatingMod(CR_HIT_MELEE, enchant_amount, apply); + sLog.outDebug("+ %u MELEE_HIT", enchant_amount); + break; + case ITEM_MOD_HIT_RANGED_RATING: + ((Player*)this)->ApplyRatingMod(CR_HIT_RANGED, enchant_amount, apply); + sLog.outDebug("+ %u RANGED_HIT", enchant_amount); + break; + case ITEM_MOD_HIT_SPELL_RATING: + ((Player*)this)->ApplyRatingMod(CR_HIT_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u SPELL_HIT", enchant_amount); + break; + case ITEM_MOD_CRIT_MELEE_RATING: + ((Player*)this)->ApplyRatingMod(CR_CRIT_MELEE, enchant_amount, apply); + sLog.outDebug("+ %u MELEE_CRIT", enchant_amount); + break; + case ITEM_MOD_CRIT_RANGED_RATING: + ((Player*)this)->ApplyRatingMod(CR_CRIT_RANGED, enchant_amount, apply); + sLog.outDebug("+ %u RANGED_CRIT", enchant_amount); + break; + case ITEM_MOD_CRIT_SPELL_RATING: + ((Player*)this)->ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u SPELL_CRIT", enchant_amount); + break; +// Values from ITEM_STAT_MELEE_HA_RATING to ITEM_MOD_HASTE_RANGED_RATING are never used +// in Enchantments +// case ITEM_MOD_HIT_TAKEN_MELEE_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply); +// break; +// case ITEM_MOD_HIT_TAKEN_RANGED_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply); +// break; +// case ITEM_MOD_HIT_TAKEN_SPELL_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); +// break; +// case ITEM_MOD_HASTE_MELEE_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply); +// break; +// case ITEM_MOD_HASTE_RANGED_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply); +// break; + case ITEM_MOD_HASTE_SPELL_RATING: + ((Player*)this)->ApplyRatingMod(CR_HASTE_SPELL, enchant_amount, apply); + break; + case ITEM_MOD_HIT_RATING: + ((Player*)this)->ApplyRatingMod(CR_HIT_MELEE, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_HIT_RANGED, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_HIT_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u HIT", enchant_amount); + break; + case ITEM_MOD_CRIT_RATING: + ((Player*)this)->ApplyRatingMod(CR_CRIT_MELEE, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_CRIT_RANGED, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u CRITICAL", enchant_amount); + break; +// Values ITEM_MOD_HIT_TAKEN_RATING and ITEM_MOD_CRIT_TAKEN_RATING are never used in Enchantment +// case ITEM_MOD_HIT_TAKEN_RATING: +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply); +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply); +// ((Player*)this)->ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_RATING: +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); +// ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); +// break; + case ITEM_MOD_RESILIENCE_RATING: + ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u RESILIENCE", enchant_amount); + break; + case ITEM_MOD_HASTE_RATING: + ((Player*)this)->ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply); + ((Player*)this)->ApplyRatingMod(CR_HASTE_SPELL, enchant_amount, apply); + sLog.outDebug("+ %u HASTE", enchant_amount); + break; + case ITEM_MOD_EXPERTISE_RATING: + ((Player*)this)->ApplyRatingMod(CR_EXPERTISE, enchant_amount, apply); + sLog.outDebug("+ %u EXPERTISE", enchant_amount); + break; + case ITEM_MOD_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply); + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + sLog.outDebug("+ %u ATTACK_POWER", enchant_amount); + break; + case ITEM_MOD_RANGED_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + sLog.outDebug("+ %u RANGED_ATTACK_POWER", enchant_amount); + break; + case ITEM_MOD_FERAL_ATTACK_POWER: + ((Player*)this)->ApplyFeralAPBonus(enchant_amount, apply); + sLog.outDebug("+ %u FERAL_ATTACK_POWER", enchant_amount); + break; + case ITEM_MOD_SPELL_HEALING_DONE: + ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply); + sLog.outDebug("+ %u SPELL_HEALING_DONE", enchant_amount); + break; + case ITEM_MOD_SPELL_DAMAGE_DONE: + ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply); + sLog.outDebug("+ %u SPELL_DAMAGE_DONE", enchant_amount); + break; + case ITEM_MOD_MANA_REGENERATION: + ((Player*)this)->ApplyManaRegenBonus(enchant_amount, apply); + sLog.outDebug("+ %u MANA_REGENERATION", enchant_amount); + break; + case ITEM_MOD_ARMOR_PENETRATION_RATING: + ((Player*)this)->ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply); + sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount); + break; + case ITEM_MOD_SPELL_POWER: + ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply); + ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply); + sLog.outDebug("+ %u SPELL_POWER", enchant_amount); + break; + default: + break; } - else if(item->GetSlot() == EQUIPMENT_SLOT_OFFHAND ) + break; + } + case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon + { + if(getClass() == CLASS_SHAMAN) { - addValue = float(enchant_amount * item->GetProto()->Delay/1000.0f); - HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, addValue, apply); + float addValue = 0.0f; + if(item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) + { + addValue = float(enchant_amount * item->GetProto()->Delay/1000.0f); + HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, addValue, apply); + } + else if(item->GetSlot() == EQUIPMENT_SLOT_OFFHAND ) + { + addValue = float(enchant_amount * item->GetProto()->Delay/1000.0f); + HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, addValue, apply); + } } + break; } - break; - } - case ITEM_ENCHANTMENT_TYPE_USE_SPELL: - // processed in Player::CastItemUseSpell - break; - case ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET: - // nothing do.. - break; - default: - sLog.outError("Unknown item enchantment (id = %d) display type: %d", enchant_id, enchant_display_type); - break; - } /*switch(enchant_display_type)*/ - } /*for*/ + case ITEM_ENCHANTMENT_TYPE_USE_SPELL: + // processed in Player::CastItemUseSpell + break; + case ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET: + // nothing do.. + break; + default: + sLog.outError("Unknown item enchantment (id = %d) display type: %d", enchant_id, enchant_display_type); + break; + } /*switch(enchant_display_type)*/ + } /*for*/ + } // visualize enchantment at player and equipped items if(slot < MAX_INSPECTED_ENCHANTMENT_SLOT) diff --git a/src/game/Player.h b/src/game/Player.h index a40a7f1c40c..6a0db61896d 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -122,7 +122,8 @@ enum TrainerSpellState { TRAINER_SPELL_GREEN = 0, TRAINER_SPELL_RED = 1, - TRAINER_SPELL_GRAY = 2 + TRAINER_SPELL_GRAY = 2, + TRAINER_SPELL_GREEN_DISABLED = 10 // custom value, not send to client: formally green but learn not allowed }; enum ActionButtonUpdateState diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index e6aaf8619bc..1cdf2359201 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -1032,9 +1032,8 @@ enum Targets TARGET_GAMEOBJECT_ITEM = 26, //TARGET_OBJECT_ITEM_PICKLOCK TARGET_UNIT_MASTER = 27, - TARGET_ALL_ENEMY_IN_AREA_CHANNELED = 28, - TARGET_UNIT_AREA_ENEMY_CHANNEL = 28, - TARGET_UNIT_AREA_ALLY_CHANNEL = 29, // 28,29 only used for effect 27, if interrupt channel, pstAA cancel + TARGET_DEST_DYNOBJ_ENEMY = 28, + TARGET_DEST_DYNOBJ_ALLY = 29, // only for effect 27 TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER = 30, // in TargetB used only with TARGET_ALL_AROUND_CASTER and in self casting range in TargetA TARGET_UNIT_AREA_ALLY = 30, TARGET_ALL_FRIENDLY_UNITS_IN_AREA = 31, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 5990c70a2e9..9590322617f 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -925,7 +925,16 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) spellHitTarget = m_caster; } - DoSpellHitOnUnit(spellHitTarget, mask); + if(spellHitTarget) + { + SpellMissInfo missInfo = DoSpellHitOnUnit(spellHitTarget, mask); + if(missInfo != SPELL_MISS_NONE) + { + m_caster->SendSpellMiss(unit, m_spellInfo->Id, missInfo); + m_damage = 0; + spellHitTarget = NULL; + } + } // Do not take combo points on dodge if (m_needComboPoints && m_targets.getUnitTargetGUID() == target->targetGUID) @@ -1034,19 +1043,17 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) } } -void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) +SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) { if(!unit || !effectMask) - return; + return SPELL_MISS_EVADE; // Recheck immune (only for delayed spells) if( m_spellInfo->speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo))) { - m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_IMMUNE); - m_damage = 0; - return; + return SPELL_MISS_IMMUNE; } if (unit->GetTypeId() == TYPEID_PLAYER) @@ -1067,9 +1074,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) && unit->GetCharmerOrOwnerGUID() != m_caster->GetGUID()) { - m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); - m_damage = 0; - return; + return SPELL_MISS_EVADE; } if( !m_caster->IsFriendlyTo(unit) ) @@ -1077,9 +1082,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) // for delayed spells ignore not visible explicit target if(m_spellInfo->speed > 0.0f && unit==m_targets.getUnitTarget() && !unit->isVisibleForOrDetect(m_caster,false)) { - m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); - m_damage = 0; - return; + return SPELL_MISS_EVADE; } unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL); @@ -1092,9 +1095,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) // TODO: this cause soul transfer bugged if(m_spellInfo->speed > 0.0f && unit->GetTypeId() == TYPEID_PLAYER && !IsPositiveSpell(m_spellInfo->Id)) { - m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); - m_damage = 0; - return; + return SPELL_MISS_EVADE; } // assisting case, healing and resurrection @@ -1165,6 +1166,8 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) if (unit->AddAura(Aur)) m_spellAura = Aur; } + + return SPELL_MISS_NONE; } void Spell::DoTriggersOnSpellHit(Unit *unit) @@ -1988,17 +1991,13 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) break; } - if(cur == TARGET_DEST_DEST) - break; - - float x, y, z, angle, dist; - - dist = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); - if (cur == TARGET_DEST_DEST_RANDOM) - dist *= rand_norm(); - + float angle; switch(cur) { + case TARGET_DEST_DYNOBJ_ENEMY: + case TARGET_DEST_DYNOBJ_ALLY: + case TARGET_DEST_DEST: + return; case TARGET_DEST_DEST_FRONT: angle = 0.0f; break; case TARGET_DEST_DEST_BACK: angle = M_PI; break; case TARGET_DEST_DEST_RIGHT: angle = M_PI/2; break; @@ -2010,6 +2009,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) default: angle = rand_norm()*2*M_PI; break; } + float dist, x, y, z; + dist = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + if (cur == TARGET_DEST_DEST_RANDOM) + dist *= rand_norm(); + x = m_targets.m_destX; y = m_targets.m_destY; z = m_targets.m_destZ; diff --git a/src/game/Spell.h b/src/game/Spell.h index d7bbc119572..64aa7f24eb0 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -588,7 +588,7 @@ class Spell void AddGOTarget(uint64 goGUID, uint32 effIndex); void AddItemTarget(Item* target, uint32 effIndex); void DoAllEffectOnTarget(TargetInfo *target); - void DoSpellHitOnUnit(Unit *unit, uint32 effectMask); + SpellMissInfo DoSpellHitOnUnit(Unit *unit, uint32 effectMask); void DoTriggersOnSpellHit(Unit *unit); void DoAllEffectOnTarget(GOTargetInfo *target); void DoAllEffectOnTarget(ItemTargetInfo *target); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 1cbd5f94772..a1ae00b17c8 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -372,7 +372,12 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) if(!radius) return; float distance = m_caster->GetDistance2d(unitTarget); damage = (distance > radius ) ? 0 : (int32)(m_spellInfo->EffectBasePoints[0]*((radius - distance)/radius)); - }break; + break; + } + // Cataclysmic Bolt + case 38441: + damage = unitTarget->GetMaxHealth() / 2; + break; } break; } @@ -2753,7 +2758,6 @@ void Spell::EffectPersistentAA(uint32 i) return; } dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65); - dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003); dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee); caster->AddDynObject(dynObj); dynObj->GetMap()->Add(dynObj); diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index b98d693c416..5cd5da67118 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -347,12 +347,8 @@ void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) recvPacket >> counter; recvPacket >> spellId; - //FIXME: hack, ignore unexpected client cancel Deadly Throw cast - if(spellId==26679) - return; - if(_player->IsNonMeleeSpellCasted(false)) - _player->InterruptNonMeleeSpells(false,spellId); + _player->InterruptNonMeleeSpells(false,spellId,false); } void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 6d93f292f8c..e4bee68d3a3 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -119,8 +119,6 @@ SpellMgr::SpellMgr() case TARGET_UNIT_AREA_ENTRY: case TARGET_UNIT_AREA_PARTY_GROUND: case TARGET_UNIT_AREA_PARTY: - //case TARGET_UNIT_AREA_ENEMY_CHANNEL: - //case TARGET_UNIT_AREA_ALLY_CHANNEL: SpellTargetType[i] = TARGET_TYPE_AREA_DEST; break; case TARGET_DEST_TARGET_ENEMY: @@ -153,6 +151,8 @@ SpellMgr::SpellMgr() case TARGET_DEST_CASTER_RADIUS: SpellTargetType[i] = TARGET_TYPE_DEST_CASTER; break; + case TARGET_DEST_DYNOBJ_ENEMY: + case TARGET_DEST_DYNOBJ_ALLY: case TARGET_DEST_DEST: case TARGET_DEST_DEST_FRONT_LEFT: case TARGET_DEST_DEST_BACK_LEFT: @@ -182,9 +182,6 @@ SpellMgr::SpellMgr() case TARGET_UNIT_AREA_ENTRY: case TARGET_UNIT_AREA_PARTY_GROUND: case TARGET_UNIT_AREA_PARTY: - //Check persistant aura seperately - //case TARGET_UNIT_AREA_ENEMY_CHANNEL: - //case TARGET_UNIT_AREA_ALLY_CHANNEL: case TARGET_UNIT_PARTY_TARGET: case TARGET_UNIT_PARTY_CASTER: case TARGET_UNIT_CONE_ENEMY: @@ -501,7 +498,7 @@ bool IsPositiveTarget(uint32 targetA, uint32 targetB) case TARGET_ALL_ENEMY_IN_AREA: case TARGET_ALL_ENEMY_IN_AREA_INSTANT: case TARGET_IN_FRONT_OF_CASTER: - case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: + case TARGET_DEST_DYNOBJ_ENEMY: case TARGET_CURRENT_ENEMY_COORDINATES: case TARGET_UNIT_CHANNEL: return false; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index f2f824481ad..b1a39c30cce 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3394,12 +3394,14 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell ) pSpell->SetReferencedFromCurrent(true); } -void Unit::InterruptSpell(uint32 spellType, bool withDelayed) +void Unit::InterruptSpell(uint32 spellType, bool withDelayed, bool withInstant) { assert(spellType < CURRENT_MAX_SPELL); Spell *spell = m_currentSpells[spellType]; - if(spell && (withDelayed || spell->getState() != SPELL_STATE_DELAYED) ) + if(spell + && (withDelayed || spell->getState() != SPELL_STATE_DELAYED) + && (withInstant || spell->GetCastTime() > 0)) { // for example, do not let self-stun aura interrupt itself if(!spell->IsInterruptable()) @@ -3443,19 +3445,19 @@ bool Unit::IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled, bool skip return(false); } -void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id) +void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id, bool withInstant) { // generic spells are interrupted if they are not finished or delayed if (m_currentSpells[CURRENT_GENERIC_SPELL] && (!spell_id || m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id==spell_id)) - InterruptSpell(CURRENT_GENERIC_SPELL,withDelayed); + InterruptSpell(CURRENT_GENERIC_SPELL,withDelayed,withInstant); // autorepeat spells are interrupted if they are not finished or delayed if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && (!spell_id || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id==spell_id)) - InterruptSpell(CURRENT_AUTOREPEAT_SPELL,withDelayed); + InterruptSpell(CURRENT_AUTOREPEAT_SPELL,withDelayed,withInstant); // channeled spells are interrupted if they are not finished, even if they are delayed if (m_currentSpells[CURRENT_CHANNELED_SPELL] && (!spell_id || m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id==spell_id)) - InterruptSpell(CURRENT_CHANNELED_SPELL,true); + InterruptSpell(CURRENT_CHANNELED_SPELL,true,true); } Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const @@ -3484,10 +3486,9 @@ bool Unit::isInBack(Unit const* target, float distance, float arc) const bool Unit::isInLine(Unit const* target, float distance) const { if(!HasInArc(M_PI, target) || !IsWithinDistInMap(target, distance)) return false; - float width = (GetObjectSize() / 2 + target->GetObjectSize()) / 2; - float angle = GetAngle(target); - angle -= GetOrientation(); - return abs(sin(angle)) * distance < width; + float width = GetObjectSize() + target->GetObjectSize() * 0.5f; + float angle = GetAngle(target) - GetOrientation(); + return abs(sin(angle)) * GetExactDistance2d(target->GetPositionX(), target->GetPositionY()) < width; } bool Unit::isInAccessiblePlaceFor(Creature const* c) const @@ -9336,10 +9337,13 @@ bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask) bool Unit::IsImmunedToDamage(SpellEntry const* spellInfo) { + if(spellInfo->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) + return false; + uint32 shoolMask = GetSpellSchoolMask(spellInfo); - if( !(spellInfo->AttributesEx & SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE) && // unaffected by school immunity - !(spellInfo->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) // can remove immune (by dispell or immune it) - && (spellInfo->Id != 42292)) + if(!(spellInfo->AttributesEx & + (SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE | SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)) // can remove immune (by dispell or immune it) + && spellInfo->Id != 42292) { //If m_immuneToSchool type contain this school type, IMMUNE damage. SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; @@ -9362,14 +9366,23 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo) if (!spellInfo) return false; + // Single spell immunity. + SpellImmuneList const& idList = m_spellImmune[IMMUNITY_ID]; + for(SpellImmuneList::const_iterator itr = idList.begin(); itr != idList.end(); ++itr) + if(itr->type == spellInfo->Id) + return true; + + if(spellInfo->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) + return false; + SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_DISPEL]; for(SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr) if(itr->type == spellInfo->Dispel) return true; - if( !(spellInfo->AttributesEx & SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE) && // unaffected by school immunity - !(spellInfo->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) // can remove immune (by dispell or immune it) - && (spellInfo->Id != 42292)) + if(!(spellInfo->AttributesEx & + (SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE | SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)) // can remove immune (by dispell or immune it) + && spellInfo->Id != 42292) { SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; for(SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr) @@ -9390,15 +9403,6 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo) } } - SpellImmuneList const& idList = m_spellImmune[IMMUNITY_ID]; - for(SpellImmuneList::const_iterator itr = idList.begin(); itr != idList.end(); ++itr) - { - if(itr->type == spellInfo->Id) - { - return true; - } - } - return false; } diff --git a/src/game/Unit.h b/src/game/Unit.h index 539d8859684..8e008e1357e 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1337,7 +1337,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void SetCurrentCastedSpell(Spell * pSpell); virtual void ProhibitSpellScholl(SpellSchoolMask /*idSchoolMask*/, uint32 /*unTimeMs*/ ) { } - void InterruptSpell(uint32 spellType, bool withDelayed = true); + void InterruptSpell(uint32 spellType, bool withDelayed = true, bool withInstant = true); // set withDelayed to true to account delayed spells as casted // delayed+channeled spells are always accounted as casted @@ -1346,7 +1346,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject // set withDelayed to true to interrupt delayed spells too // delayed+channeled spells are always interrupted - void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0); + void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0, bool withInstant = true); Spell* FindCurrentSpellBySpellId(uint32 spell_id) const; |
