aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorVincent-Michael <Vincent_Michael@gmx.de>2014-06-27 19:39:23 +0200
committerVincent-Michael <Vincent_Michael@gmx.de>2014-06-27 19:39:23 +0200
commitf3de6f028403b6b6eb59b8cb59cb15419ea47932 (patch)
tree0b391c0e5c2c344bfb661e42cbd8a680735c9f8e /src/server/game
parenta2b860b7814ca216565a432e07579dd77f004a86 (diff)
parent52023b1e6b1fefaf4be95fa201fc1dd2ecca55a7 (diff)
Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp45
-rw-r--r--src/server/game/Entities/Creature/Creature.h3
-rw-r--r--src/server/game/Entities/Player/Player.cpp29
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp12
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp4
-rw-r--r--src/server/game/Handlers/LootHandler.cpp9
-rw-r--r--src/server/game/Handlers/MailHandler.cpp7
-rw-r--r--src/server/game/Loot/LootMgr.h3
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Spells/Spell.cpp22
-rw-r--r--src/server/game/Spells/SpellEffects.cpp18
11 files changed, 76 insertions, 78 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index fbbea8b38c4..d1148f6cfb2 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -142,8 +142,8 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
}
Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(),
-lootForPickPocketed(false), _pickpocketLootRestore(0), lootForBody(false), lootForSkinned(false), _skinner(0), m_groupLootTimer(0), lootingGroupLowGUID(0),
-m_PlayerDamageReq(0), m_lootRecipient(0), m_lootRecipientGroup(0), m_corpseRemoveTime(0), m_respawnTime(0),
+_pickpocketLootRestore(0), m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0),
+m_lootRecipient(0), m_lootRecipientGroup(0), _skinner(0), m_corpseRemoveTime(0), m_respawnTime(0),
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE),
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
@@ -551,9 +551,9 @@ void Creature::Update(uint32 diff)
time_t now = time(NULL);
// Check if we should refill the pickpocketing loot
- if (lootForPickPocketed && _pickpocketLootRestore && _pickpocketLootRestore <= now)
+ if (loot.loot_type == LOOT_PICKPOCKETING && _pickpocketLootRestore && _pickpocketLootRestore <= now)
{
- lootForPickPocketed = false;
+ loot.clear();
_pickpocketLootRestore = 0;
}
@@ -1485,11 +1485,6 @@ void Creature::setDeathState(DeathState s)
setActive(false);
- if (!IsPet() && GetCreatureTemplate()->SkinLootId)
- if (LootTemplates_Skinning.HaveLootFor(GetCreatureTemplate()->SkinLootId))
- if (hasLootRecipient())
- SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
-
if (HasSearchedAssistance())
{
SetNoSearchAssistance(false);
@@ -1548,9 +1543,7 @@ void Creature::Respawn(bool force)
GetName().c_str(), GetGUIDLow(), GetGUID(), GetEntry());
m_respawnTime = 0;
_pickpocketLootRestore = 0;
- lootForPickPocketed = false;
- lootForBody = false;
- lootForSkinned = false;
+ loot.clear();
if (m_originalEntry != GetEntry())
UpdateEntry(m_originalEntry);
@@ -2284,23 +2277,23 @@ void Creature::GetRespawnPosition(float &x, float &y, float &z, float* ori, floa
void Creature::AllLootRemovedFromCorpse()
{
- if (!HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE))
- {
- time_t now = time(NULL);
- if (m_corpseRemoveTime <= now)
- return;
+ if (loot.loot_type != LOOT_SKINNING && !IsPet() && GetCreatureTemplate()->SkinLootId && hasLootRecipient())
+ if (LootTemplates_Skinning.HaveLootFor(GetCreatureTemplate()->SkinLootId))
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
- float decayRate = sWorld->getRate(RATE_CORPSE_DECAY_LOOTED);
- CreatureTemplate const* cinfo = GetCreatureTemplate();
+ time_t now = time(NULL);
+ if (m_corpseRemoveTime <= now)
+ return;
- // corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update
- if (cinfo && cinfo->SkinLootId)
- m_corpseRemoveTime = time(NULL);
- else
- m_corpseRemoveTime = now + m_corpseDelay * decayRate;
+ float decayRate = sWorld->getRate(RATE_CORPSE_DECAY_LOOTED);
- m_respawnTime = m_corpseRemoveTime + m_respawnTime;
- }
+ // corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update
+ if (loot.loot_type == LOOT_SKINNING)
+ m_corpseRemoveTime = time(NULL);
+ else
+ m_corpseRemoveTime = now + m_corpseDelay * decayRate;
+
+ m_respawnTime = m_corpseRemoveTime + m_respawnTime;
}
uint8 Creature::getLevelForTarget(WorldObject const* target) const
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 85850170603..86fafb330a7 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -548,9 +548,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
virtual void DeleteFromDB(); // overriden in Pet
Loot loot;
- bool lootForPickPocketed;
- bool lootForBody;
- bool lootForSkinned;
void StartPickPocketRefillTimer();
void ResetPickPocketRefillTimer() { _pickpocketLootRestore = 0; }
void SetSkinner(uint64 guid) { _skinner = guid; }
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index e1a1b367b7b..cf6e94328b7 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -9182,9 +9182,8 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
if (loot_type == LOOT_PICKPOCKETING)
{
- if (!creature->lootForPickPocketed)
+ if (loot->loot_type != LOOT_PICKPOCKETING)
{
- creature->lootForPickPocketed = true;
creature->StartPickPocketRefillTimer();
loot->clear();
@@ -9205,12 +9204,9 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
if (!recipient)
return;
- if (!creature->lootForBody)
+ if (loot->loot_type == LOOT_NONE)
{
- creature->lootForBody = true;
-
// for creature, loot is filled when creature is killed.
-
if (Group* group = recipient->GetGroup())
{
switch (group->GetLootMethod())
@@ -9231,15 +9227,17 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
}
}
- // possible only if creature->lootForBody && loot->empty() at spell cast check
- if (loot_type == LOOT_SKINNING)
+ // if loot is already skinning loot then don't do anything else
+ if (loot->loot_type == LOOT_SKINNING)
{
- if (!creature->lootForSkinned)
- {
- creature->lootForSkinned = true;
- loot->clear();
- loot->FillLoot(creature->GetCreatureTemplate()->SkinLootId, LootTemplates_Skinning, this, true);
- }
+ loot_type = LOOT_SKINNING;
+ permission = creature->GetSkinner() == GetGUID() ? OWNER_PERMISSION : NONE_PERMISSION;
+ }
+ else if (loot_type == LOOT_SKINNING)
+ {
+ loot->clear();
+ loot->FillLoot(creature->GetCreatureTemplate()->SkinLootId, LootTemplates_Skinning, this, true);
+ creature->SetSkinner(GetGUID());
permission = OWNER_PERMISSION;
}
// set group rights only for loot_type != LOOT_SKINNING
@@ -17978,6 +17976,9 @@ bool Player::isAllowedToLoot(const Creature* creature)
if (loot->isLooted()) // nothing to loot or everything looted.
return false;
+ if (loot->loot_type == LOOT_SKINNING)
+ return creature->GetSkinner() == GetGUID();
+
Group* thisGroup = GetGroup();
if (!thisGroup)
return this == creature->GetLootRecipient();
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index e4eca6b970b..6c66e900be7 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -13669,11 +13669,8 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
if (creature)
{
Loot* loot = &creature->loot;
- if (creature->lootForPickPocketed)
- {
+ if (creature->loot.loot_type == LOOT_PICKPOCKETING)
creature->ResetPickPocketRefillTimer();
- creature->lootForPickPocketed = false;
- }
loot->clear();
if (uint32 lootid = creature->GetCreatureTemplate()->lootid)
@@ -13794,9 +13791,12 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
if (!creature->IsPet())
{
creature->DeleteThreatList();
- CreatureTemplate const* cInfo = creature->GetCreatureTemplate();
- if (cInfo && (cInfo->lootid || cInfo->maxgold > 0))
+
+ // must be after setDeathState which resets dynamic flags
+ if (!creature->loot.empty())
creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ else
+ creature->AllLootRemovedFromCorpse();
}
// Call KilledUnit for creatures, this needs to be called after the lootable flag is set
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 70547136bf8..70e01238663 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -775,9 +775,9 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
std::string IP_str = GetRemoteAddress();
TC_LOG_INFO("entities.player.character", "Account: %d, IP: %s deleted character: %s, GUID: %u, Level: %u", accountId, IP_str.c_str(), name.c_str(), GUID_LOPART(guid), level);
-
+
// To prevent hook failure, place hook before removing reference from DB
- sScriptMgr->OnPlayerDelete(guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete.
+ sScriptMgr->OnPlayerDelete(guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete.
// Shouldn't interfere with character deletion though
if (sLog->ShouldLog("entities.player.dump", LOG_LEVEL_INFO)) // optimize GetPlayerDump call
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index a4fde51b498..7c3d9e99eee 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -82,7 +82,7 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData)
{
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
- bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed);
+ bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
{
@@ -149,7 +149,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
case HIGHGUID_VEHICLE:
{
Creature* creature = player->GetMap()->GetCreature(guid);
- bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed);
+ bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE))
{
loot = &creature->loot;
@@ -357,7 +357,7 @@ void WorldSession::DoLootRelease(uint64 lguid)
{
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
- bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed);
+ bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
return;
@@ -365,9 +365,6 @@ void WorldSession::DoLootRelease(uint64 lguid)
if (loot->isLooted())
{
creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
-
- if (loot->loot_type == LOOT_SKINNING)
- creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
// skip pickpocketing loot for speed, skinning timer reduction is no-op in fact
if (!creature->IsAlive())
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index 536d6a7dc95..3c4e5feb771 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -181,6 +181,13 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
uint64 reqmoney = cost + money;
+ // Check for overflow
+ if (reqmoney < money)
+ {
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY);
+ return;
+ }
+
if (!player->HasEnoughMoney(reqmoney) && !player->IsGameMaster())
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY);
diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h
index 9be745e622d..cb3b9082c20 100644
--- a/src/server/game/Loot/LootMgr.h
+++ b/src/server/game/Loot/LootMgr.h
@@ -76,6 +76,8 @@ enum PermissionTypes
enum LootType
{
+ LOOT_NONE = 0,
+
LOOT_CORPSE = 1,
LOOT_PICKPOCKETING = 2,
LOOT_FISHING = 3,
@@ -341,6 +343,7 @@ struct Loot
gold = 0;
unlootedCount = 0;
roundRobinPlayer = 0;
+ loot_type = LOOT_NONE;
i_LootValidatorRefManager.clearReferences();
}
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 475e8ee3fa8..22b2d58585c 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -2987,7 +2987,7 @@ enum CreatureTypeFlags
CREATURE_TYPEFLAGS_EXOTIC = 0x00010000, // Can be tamed by hunter as exotic pet
CREATURE_TYPEFLAGS_UNK17 = 0x00020000, // ? Related to vehicles/pvp?
CREATURE_TYPEFLAGS_UNK18 = 0x00040000, // ? Related to vehicle/siege weapons?
- CREATURE_TYPEFLAGS_UNK19 = 0x00080000,
+ CREATURE_TYPEFLAGS_PROJECTILE_COLLISION = 0x00080000, // Projectiles can collide with this creature - interacts with TARGET_DEST_TRAJ
CREATURE_TYPEFLAGS_UNK20 = 0x00100000,
CREATURE_TYPEFLAGS_UNK21 = 0x00200000,
CREATURE_TYPEFLAGS_UNK22 = 0x00400000,
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 2a01a8046ed..56ae9061033 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1507,10 +1507,24 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
std::list<WorldObject*>::const_iterator itr = targets.begin();
for (; itr != targets.end(); ++itr)
{
+ if (!m_caster->HasInLine(*itr, 5.0f))
+ continue;
+
+ if (m_spellInfo->CheckTarget(m_caster, *itr, true) != SPELL_CAST_OK)
+ continue;
+
if (Unit* unitTarget = (*itr)->ToUnit())
- if (m_caster == *itr || m_caster->IsOnVehicle(unitTarget) || (unitTarget)->GetVehicle())//(*itr)->IsOnVehicle(m_caster))
+ {
+ if (m_caster == *itr || m_caster->IsOnVehicle(unitTarget) || unitTarget->GetVehicle())
continue;
+ if (Creature* creatureTarget = unitTarget->ToCreature())
+ {
+ if (!(creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PROJECTILE_COLLISION))
+ continue;
+ }
+ }
+
const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3)
/// @todo all calculation should be based on src instead of m_caster
const float objDist2d = m_targets.GetSrcPos()->GetExactDist2d(*itr) * std::cos(m_targets.GetSrcPos()->GetRelativeAngle(*itr));
@@ -5120,13 +5134,11 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_TARGET_UNSKINNABLE;
Creature* creature = m_targets.GetUnitTarget()->ToCreature();
- if (creature->GetCreatureType() != CREATURE_TYPE_CRITTER && creature->loot.loot_type != LOOT_SKINNING && !creature->loot.isLooted())
+ if (creature->GetCreatureType() != CREATURE_TYPE_CRITTER && !creature->loot.isLooted())
return SPELL_FAILED_TARGET_NOT_LOOTED;
uint32 skill = creature->GetCreatureTemplate()->GetRequiredLootSkill();
- bool alreadySkinned = creature->loot.loot_type == LOOT_SKINNING && creature->GetSkinner() == m_caster->GetGUID();
-
int32 skillValue = m_caster->ToPlayer()->GetSkillValue(skill);
int32 TargetLevel = m_targets.GetUnitTarget()->getLevel();
int32 ReqValue = (skillValue < 100 ? (TargetLevel-10) * 10 : TargetLevel * 5);
@@ -5136,7 +5148,7 @@ SpellCastResult Spell::CheckCast(bool strict)
// chance for fail at orange skinning attempt
if ((m_selfContainer && (*m_selfContainer) == this) &&
skillValue < sWorld->GetConfigMaxSkillValue() &&
- (ReqValue < 0 ? 0 : ReqValue) > irand(skillValue - 25, skillValue + 37) && !alreadySkinned)
+ (ReqValue < 0 ? 0 : ReqValue) > irand(skillValue - 25, skillValue + 37))
return SPELL_FAILED_TRY_AGAIN;
break;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 8d8abc9eb36..ebd0a269223 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -4435,28 +4435,16 @@ void Spell::EffectSkinning(SpellEffIndex /*effIndex*/)
uint32 skill = creature->GetCreatureTemplate()->GetRequiredLootSkill();
- bool awardPoints = true;
-
- // Check if a skinning loot table was already generated for this creature
- if (creature->loot.loot_type == LOOT_SKINNING)
- {
- if (creature->GetSkinner() != m_caster->GetGUID())
- return;
-
- awardPoints = false; // Do not grant skill points for this loot, they were already granted the first time.
- }
- else
- creature->SetSkinner(m_caster->GetGUID());
-
m_caster->ToPlayer()->SendLoot(creature->GetGUID(), LOOT_SKINNING);
+ creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
+ creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
int32 skillValue = m_caster->ToPlayer()->GetPureSkillValue(skill);
// Double chances for elites
- if (awardPoints)
- m_caster->ToPlayer()->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1);
+ m_caster->ToPlayer()->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1);
}
void Spell::EffectCharge(SpellEffIndex /*effIndex*/)