--HG--
branch : trunk
This commit is contained in:
megamage
2009-01-27 14:54:54 -06:00
13 changed files with 244 additions and 184 deletions
+4 -6
View File
@@ -96,14 +96,12 @@ DestinationHolder<TRAVELLER>::StartTravel(TRAVELLER &traveller, bool sendMove)
else //Walking on the ground
dist = sqrt((dx*dx) + (dy*dy));
float speed;
if(traveller.GetTraveller().hasUnitState(UNIT_STAT_CHARGING))
i_totalTravelTime = 1000;
speed = 0.025f; // assume it is 25 yard per second
else
{
float speed = traveller.Speed();
speed *= 0.001f; // speed is in seconds so convert from second to millisecond
i_totalTravelTime = static_cast<uint32>(dist/speed);
}
speed = traveller.Speed() * 0.001f; // speed is in seconds so convert from second to millisecond
i_totalTravelTime = static_cast<uint32>(dist/speed);
i_timeElapsed = 0;
if(sendMove)
+1 -2
View File
@@ -867,8 +867,7 @@ enum Targets
TARGET_DEST_CASTER_BACK_LEFT = 42, //water totem
TARGET_DEST_CASTER_BACK_RIGHT = 43, //air totem
TARGET_DEST_CASTER_FRONT_RIGHT = 44, //fire totem
TARGET_CHAIN_HEAL = 45,
//TARGET_UNIT_CHAINHEAL
TARGET_UNIT_CHAINHEAL = 45,
TARGET_SCRIPT_COORDINATES = 46,
//TARGET_DEST_NEARBY_ENTRY
TARGET_DEST_CASTER_FRONT = 47,
+98 -135
View File
@@ -1215,6 +1215,7 @@ struct ChainHealingOrder : public std::binary_function<const Unit*, const Unit*,
{
return (ChainHealingHash(_Left) < ChainHealingHash(_Right));
}
int32 ChainHealingHash(Unit const* Target) const
{
if (Target == MainTarget)
@@ -1232,18 +1233,6 @@ struct ChainHealingOrder : public std::binary_function<const Unit*, const Unit*,
}
};
class ChainHealingFullHealth: std::unary_function<const Unit*, bool>
{
public:
const Unit* MainTarget;
ChainHealingFullHealth(const Unit* Target) : MainTarget(Target) {};
bool operator()(const Unit* Target)
{
return (Target != MainTarget && Target->GetHealth() == Target->GetMaxHealth());
}
};
// Helper for targets nearest to the spell target
// The spell target is always first unless there is a target at _completely_ the same position (unbelievable case)
struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit, bool>
@@ -1257,9 +1246,10 @@ struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit,
}
};
void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, Unit* pUnitTarget, float max_range, uint32 unMaxTargets)
void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uint32 num, SpellTargets TargetType)
{
if(!pUnitTarget)
Unit *cur = m_targets.getUnitTarget();
if(!cur)
return;
// Get spell max affected targets
@@ -1274,48 +1264,60 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, Unit* pUnitTarget, f
//FIXME: This very like horrible hack and wrong for most spells
if(m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE)
max_range += unMaxTargets * CHAIN_SPELL_JUMP_RADIUS;
max_range += num * CHAIN_SPELL_JUMP_RADIUS;
std::list<Unit *> tempUnitMap;
Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(pUnitTarget, m_caster, max_range);
Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(tempUnitMap, u_check);
m_caster->VisitNearbyObject(max_range, searcher);
tempUnitMap.sort(TargetDistanceOrder(pUnitTarget));
if(tempUnitMap.empty())
return;
uint32 t = unMaxTargets;
if(pUnitTarget != m_caster)
std::list<Unit*> tempUnitMap;
if(TargetType == SPELL_TARGETS_CHAINHEAL)
{
if(*tempUnitMap.begin() == pUnitTarget)
tempUnitMap.erase(tempUnitMap.begin());
TagUnitMap.push_back(pUnitTarget);
--t;
SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, SPELL_TARGETS_ALLY);
tempUnitMap.sort(ChainHealingOrder(m_caster));
if(cur->GetHealth() == cur->GetMaxHealth() && tempUnitMap.size())
cur = tempUnitMap.front();
}
Unit *prev = pUnitTarget;
else
SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, TargetType);
tempUnitMap.remove(cur);
std::list<Unit*>::iterator next = tempUnitMap.begin();
while(t && next != tempUnitMap.end())
while(num)
{
if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
TagUnitMap.push_back(cur);
--num;
if(tempUnitMap.empty())
break;
if(!prev->IsWithinLOSInMap(*next)
|| m_spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE && !m_caster->isInFront(*next, max_range))
std::list<Unit*>::iterator next;
if(TargetType == SPELL_TARGETS_CHAINHEAL)
{
++next;
continue;
next = tempUnitMap.begin();
while(cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS
|| !cur->IsWithinLOSInMap(*next))
{
++next;
if(next == tempUnitMap.end())
return;
}
}
else
{
tempUnitMap.sort(TargetDistanceOrder(cur));
next = tempUnitMap.begin();
if(cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
break;
while(!cur->IsWithinLOSInMap(*next)
|| m_spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE
&& !m_caster->isInFront(*next, max_range))
{
++next;
if(next == tempUnitMap.end() || cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
return;
}
}
prev = *next;
TagUnitMap.push_back(prev);
tempUnitMap.erase(next);
tempUnitMap.sort(TargetDistanceOrder(prev));
next = tempUnitMap.begin();
--t;
cur = *next;
tempUnitMap.erase(next);
}
}
@@ -1332,11 +1334,22 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const u
x = m_targets.m_destX;
y = m_targets.m_destY;
}
else
else if(type == PUSH_SELF_CENTER)
{
x = m_caster->GetPositionX();
y = m_caster->GetPositionY();
}
else if(type == PUSH_TARGET_CENTER)
{
Unit *target = m_targets.getUnitTarget();
if(!target)
{
sLog.outError( "SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id );
return;
}
x = target->GetPositionX();
y = target->GetPositionY();
}
Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, type, TargetType, entry);
if((m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY)
@@ -1368,13 +1381,13 @@ Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 en
}
}
default:
case SPELL_TARGETS_AOE_DAMAGE:
case SPELL_TARGETS_ENEMY:
{
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius);
Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, u_check);
m_caster->VisitNearbyObject(radius, searcher);
}break;
case SPELL_TARGETS_FRIENDLY:
case SPELL_TARGETS_ALLY:
{
Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius);
Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(target, u_check);
@@ -1467,13 +1480,16 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
target->GetPartyMember(TagUnitMap, radius);
break;
case TARGET_UNIT_TARGET_ENEMY:
if(Unit* pUnitTarget = SelectMagnetTarget())
{
if(EffectChainTarget <= 1)
TagUnitMap.push_back(pUnitTarget);
else //TODO: chain target should also use magnet target
SearchChainTarget(TagUnitMap, pUnitTarget, radius, EffectChainTarget);
}
if(EffectChainTarget <= 1)
TagUnitMap.push_back(SelectMagnetTarget());
else if(SelectMagnetTarget()) //TODO: chain target should also use magnet target
SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ENEMY);
break;
case TARGET_UNIT_CHAINHEAL:
if(EffectChainTarget <= 1)
TagUnitMap.push_back(target);
else
SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_CHAINHEAL);
break;
}
}break;
@@ -1520,12 +1536,12 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
case TARGET_UNIT_AREA_ENEMY_GROUND:
m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
case TARGET_UNIT_AREA_ENEMY:
SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE);
SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY);
break;
case TARGET_UNIT_AREA_ALLY_GROUND:
m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
case TARGET_UNIT_AREA_ALLY:
SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_FRIENDLY);
SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ALLY);
break;
case TARGET_UNIT_AREA_PARTY_GROUND:
m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
@@ -1540,7 +1556,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id);
if(lower==upper)
{
SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE);
SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY);
sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry());
break;
}
@@ -1599,33 +1615,40 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
case TARGET_IN_FRONT_OF_CASTER:
case TARGET_UNIT_CONE_ENEMY_UNKNOWN:
if(m_customAttr & SPELL_ATTR_CU_CONE_BACK)
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_BACK, SPELL_TARGETS_AOE_DAMAGE);
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_BACK, SPELL_TARGETS_ENEMY);
else if(m_customAttr & SPELL_ATTR_CU_CONE_LINE)
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_LINE, SPELL_TARGETS_AOE_DAMAGE);
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_LINE, SPELL_TARGETS_ENEMY);
else
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_AOE_DAMAGE);
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_ENEMY);
break;
case TARGET_UNIT_CONE_ALLY:
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_FRIENDLY);
SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_ALLY);
break;
// nearby target
case TARGET_UNIT_NEARBY_ALLY:
case TARGET_UNIT_NEARBY_ALLY_UNK:
{
if(Unit* pUnitTarget = SearchNearbyTarget(radius, SPELL_TARGETS_FRIENDLY))
TagUnitMap.push_back(pUnitTarget);
}break;
case TARGET_UNIT_NEARBY_ENEMY:
{
if(EffectChainTarget <= 1)
if(!m_targets.getUnitTarget())
m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ALLY));
if(m_targets.getUnitTarget())
{
if(Unit* pUnitTarget = SearchNearbyTarget(radius, SPELL_TARGETS_AOE_DAMAGE))
TagUnitMap.push_back(pUnitTarget);
if(EffectChainTarget <= 1)
TagUnitMap.push_back(m_targets.getUnitTarget());
else
SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ALLY);
}
else
SearchChainTarget(TagUnitMap, m_caster, radius, EffectChainTarget);
}break;
break;
case TARGET_UNIT_NEARBY_ENEMY:
if(!m_targets.getUnitTarget())
m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ENEMY));
if(m_targets.getUnitTarget())
{
if(EffectChainTarget <= 1)
TagUnitMap.push_back(m_targets.getUnitTarget());
else
SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ENEMY);
}
break;
case TARGET_SCRIPT:
case TARGET_SCRIPT_COORDINATES:
case TARGET_UNIT_AREA_SCRIPT:
@@ -1722,66 +1745,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
TagUnitMap.push_back(m_caster);
break;
}
case TARGET_CHAIN_HEAL:
{
Unit* pUnitTarget = m_targets.getUnitTarget();
if(!pUnitTarget)
break;
if (EffectChainTarget <= 1)
TagUnitMap.push_back(pUnitTarget);
else
{
unMaxTargets = EffectChainTarget;
float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS;
std::list<Unit *> tempUnitMap;
Trinity::SpellNotifierCreatureAndPlayer notifier(*this, tempUnitMap, max_range, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY);
m_caster->VisitNearbyObject(max_range, notifier);
if(m_caster != pUnitTarget && std::find(tempUnitMap.begin(),tempUnitMap.end(),m_caster) == tempUnitMap.end() )
tempUnitMap.push_front(m_caster);
tempUnitMap.sort(TargetDistanceOrder(pUnitTarget));
if(tempUnitMap.empty())
break;
if(*tempUnitMap.begin() == pUnitTarget)
tempUnitMap.erase(tempUnitMap.begin());
TagUnitMap.push_back(pUnitTarget);
uint32 t = unMaxTargets - 1;
Unit *prev = pUnitTarget;
std::list<Unit*>::iterator next = tempUnitMap.begin();
while(t && next != tempUnitMap.end() )
{
if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
break;
if(!prev->IsWithinLOSInMap(*next))
{
++next;
continue;
}
if((*next)->GetHealth() == (*next)->GetMaxHealth())
{
next = tempUnitMap.erase(next);
continue;
}
prev = *next;
TagUnitMap.push_back(prev);
tempUnitMap.erase(next);
tempUnitMap.sort(TargetDistanceOrder(prev));
next = tempUnitMap.begin();
--t;
}
}
}break;
case TARGET_AREAEFFECT_PARTY_AND_CLASS:
{
Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER
+10 -7
View File
@@ -108,6 +108,7 @@ enum SpellNotifyPushType
PUSH_IN_LINE,
PUSH_SELF_CENTER,
PUSH_DEST_CENTER,
PUSH_TARGET_CENTER,
};
bool IsQuestTameSpell(uint32 spellId);
@@ -228,9 +229,10 @@ enum ReplenishType
enum SpellTargets
{
SPELL_TARGETS_FRIENDLY,
SPELL_TARGETS_AOE_DAMAGE,
SPELL_TARGETS_ENTRY
SPELL_TARGETS_ALLY,
SPELL_TARGETS_ENEMY,
SPELL_TARGETS_ENTRY,
SPELL_TARGETS_CHAINHEAL,
};
#define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL 1000
@@ -579,8 +581,9 @@ class Spell
bool IsAliveUnitPresentInTargetList();
void SearchAreaTarget(std::list<Unit*> &data, float radius, const uint32 &type,
SpellTargets TargetType, uint32 entry = 0);
void SearchChainTarget(std::list<Unit*> &data, float radius, uint32 unMaxTargets,
SpellTargets TargetType);
Unit* SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry = 0);
void SearchChainTarget(std::list<Unit*> &data, Unit* pUnitTarget, float max_range, uint32 unMaxTargets);
bool IsValidSingleTargetEffect(Unit const* target, Targets type) const;
bool IsValidSingleTargetSpell(Unit const* target) const;
void CalculateDamageDoneForAllTargets();
@@ -624,7 +627,7 @@ namespace Trinity
uint32 i_entry;
SpellNotifierCreatureAndPlayer(Spell &spell, std::list<Unit*> &data, float radius, const uint32 &type,
SpellTargets TargetType = SPELL_TARGETS_AOE_DAMAGE, uint32 entry = 0)
SpellTargets TargetType = SPELL_TARGETS_ENEMY, uint32 entry = 0)
: i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType), i_entry(entry)
{
i_caster = spell.GetCaster();
@@ -644,11 +647,11 @@ namespace Trinity
switch (i_TargetType)
{
case SPELL_TARGETS_FRIENDLY:
case SPELL_TARGETS_ALLY:
if (!itr->getSource()->isAttackableByAOE() || !i_caster->IsFriendlyTo( itr->getSource() ))
continue;
break;
case SPELL_TARGETS_AOE_DAMAGE:
case SPELL_TARGETS_ENEMY:
{
if(itr->getSource()->GetTypeId()==TYPEID_UNIT && ((Creature*)itr->getSource())->isTotem())
continue;
+1
View File
@@ -106,6 +106,7 @@ SpellMgr::SpellMgr()
case TARGET_UNIT_TARGET_ENEMY:
case TARGET_UNIT_TARGET_PARTY:
case TARGET_UNIT_PARTY_TARGET:
case TARGET_UNIT_CHAINHEAL:
SpellTargetType[i] = TARGET_TYPE_UNIT_TARGET;
break;
case TARGET_UNIT_CHANNEL:
-5
View File
@@ -533,11 +533,6 @@ void World::LoadConfigSettings(bool reload)
///- Read other configuration items from the config file
///- Do we allow flying mounts in Azeroth/Outland and others (others being instances, BGs, arenas)?
m_configs[CONFIG_FLYING_MOUNTS_AZEROTH] = sConfig.GetBoolDefault("FlyingMounts.Azeroth", false);
m_configs[CONFIG_FLYING_MOUNTS_OUTLAND] = sConfig.GetBoolDefault("FlyingMounts.Outland", true);
m_configs[CONFIG_FLYING_MOUNTS_OTHERS] = sConfig.GetBoolDefault("FlyingMounts.Others", false);
m_configs[CONFIG_COMPRESSION] = sConfig.GetIntDefault("Compression", 1);
if(m_configs[CONFIG_COMPRESSION] < 1 || m_configs[CONFIG_COMPRESSION] > 9)
{
-4
View File
@@ -196,10 +196,6 @@ enum WorldConfigs
CONFIG_ARENA_SEASON_IN_PROGRESS,
CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
CONFIG_SKILL_MILLING,
CONFIG_FLYING_MOUNTS_AZEROTH,
CONFIG_FLYING_MOUNTS_OUTLAND,
CONFIG_FLYING_MOUNTS_OTHERS,
CONFIG_MAX_WHO,
CONFIG_BG_START_MUSIC,
CONFIG_START_ALL_SPELLS,