📄 skill.cpp.svn-base
字号:
{
}
void SKILLS::FillTargetMap()
{
// TODO: ADD the correct target FILLS!!!!!!
for(uint32 i=0;i<3;i++)
{
// not call for empty effect.
// Also some SKILLSs use not used effect targets for store targets for dummy effect in triggered SKILLSs
if(m_SKILLSInfo->Effect[i]==0)
continue;
// targets for TARGET_SCRIPT filled in SKILLS::canCast call
if( m_SKILLSInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT || m_SKILLSInfo->EffectImplicitTargetB[i] == TARGET_SCRIPT )
continue;
std::list<Unit*> tmpUnitMap;
// TargetA/TargetB dependent from each other, we not switch to full support this dependences
// but need it support in some know cases
switch(m_SKILLSInfo->EffectImplicitTargetA[i])
{
case TARGET_ALL_AROUND_CASTER:
if( m_SKILLSInfo->EffectImplicitTargetB[i]==TARGET_ALL_PARTY ||
m_SKILLSInfo->EffectImplicitTargetB[i]==TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER ||
m_SKILLSInfo->EffectImplicitTargetB[i]==TARGET_RANDOM_RAID_MEMBER )
{
SetTargetMap(i,m_SKILLSInfo->EffectImplicitTargetB[i],tmpUnitMap);
}
// Note: this hack with search required until GO casting not implemented
// enviromenment damage SKILLSs already have around enemies targeting but this not help in case not existed GO casting support
// currently each eanemy selected explicitly and self cast damage
else if(m_SKILLSInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA && m_SKILLSInfo->Effect[i]==SKILLS_EFFECT_ENVIRONMENTAL_DAMAGE)
{
if(m_targets.getUnitTarget())
tmpUnitMap.push_back(m_targets.getUnitTarget());
}
else
{
SetTargetMap(i,m_SKILLSInfo->EffectImplicitTargetA[i],tmpUnitMap);
SetTargetMap(i,m_SKILLSInfo->EffectImplicitTargetB[i],tmpUnitMap);
}
break;
case TARGET_CURRENT_SELECTED_ENEMY:
SetTargetMap(i,m_SKILLSInfo->EffectImplicitTargetA[i],tmpUnitMap);
break;
default:
SetTargetMap(i,m_SKILLSInfo->EffectImplicitTargetA[i],tmpUnitMap);
SetTargetMap(i,m_SKILLSInfo->EffectImplicitTargetB[i],tmpUnitMap);
break;
}
if( (m_SKILLSInfo->EffectImplicitTargetA[i]==0 || m_SKILLSInfo->EffectImplicitTargetA[i]==TARGET_EFFECT_SELECT) &&
(m_SKILLSInfo->EffectImplicitTargetB[i]==0 || m_SKILLSInfo->EffectImplicitTargetB[i]==TARGET_EFFECT_SELECT) )
{
// add here custom effects that need default target.
// FOR EVERY TARGET TYPE THERE IS A DIFFERENT FILL!!
switch(m_SKILLSInfo->Effect[i])
{
//case SKILLS_EFFECT_PERSISTENT_AREA_AURA:
case SKILLS_EFFECT_RESURRECT:
case SKILLS_EFFECT_LEARN_SKILLS:
case SKILLS_EFFECT_SKILL_STEP:
case SKILLS_EFFECT_SELF_RESURRECT:
case SKILLS_EFFECT_PROFICIENCY:
case SKILLS_EFFECT_PARRY:
case SKILLS_EFFECT_CREATE_ITEM:
if(m_targets.getUnitTarget())
tmpUnitMap.push_back(m_targets.getUnitTarget());
break;
case SKILLS_EFFECT_DUMMY:
{
switch(m_SKILLSInfo->Id)
{
case 20577: // Cannibalize
{
// non-standard target selection
SKILLSRangeid const* srange = sSKILLSRangeStore.Lookupid(m_SKILLSInfo->rangeIndex);
float max_range = GetSKILLSMaxRange(srange);
CellPair p(VENICE::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
WorldObject* result = NULL;
VENICE::CannibalizeObjectCheck u_check(m_caster, max_range);
VENICE::WorldObjectSearcher<VENICE::CannibalizeObjectCheck > searcher(result, u_check);
TypeContainerVisitor<VENICE::WorldObjectSearcher<VENICE::CannibalizeObjectCheck >, GridTypeMapContainer > grid_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_searcher, *MapManager::AREA().GetMap(m_caster->GetMapId(), m_caster));
if(!result)
{
TypeContainerVisitor<VENICE::WorldObjectSearcher<VENICE::CannibalizeObjectCheck >, WorldTypeMapContainer > world_searcher(searcher);
cell_lock->Visit(cell_lock, world_searcher, *MapManager::AREA().GetMap(m_caster->GetMapId(), m_caster));
}
if(result)
{
switch(result->GetTypeId())
{
case TYPEID_UNIT:
case TYPEID_PLAYER:
tmpUnitMap.push_back((Unit*)result);
break;
case TYPEID_CORPSE:
m_targets.setCorpseTarget((Corpse*)result);
if(Player* owner = ObjectAccessor::FindPlayer(((Corpse*)result)->GetOwnerGUID()))
tmpUnitMap.push_back(owner);
break;
}
}
else
{
// clear cooldown at fail
if(m_caster->GetTypeId()==TYPEID_PLAYER)
{
((Player*)m_caster)->RemoveSKILLSCooldown(m_SKILLSInfo->Id);
WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
data << uint32(m_SKILLSInfo->Id);
data << uint64(m_caster->GetGUID());
((Player*)m_caster)->GetSession()->SendPacket(&data);
}
SendCastResult(SKILLS_FAILED_NO_EDIBLE_CORPSES);
finish(false);
}
break;
}
default:
if(m_targets.getUnitTarget())
tmpUnitMap.push_back(m_targets.getUnitTarget());
break;
}
break;
}
case SKILLS_EFFECT_SUMMON_PLAYER:
if(m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->GetSelection())
{
Player* target = objmgr.GetPlayer(((Player*)m_caster)->GetSelection());
if(target)
tmpUnitMap.push_back(target);
}
break;
case SKILLS_EFFECT_RESURRECT_NEW:
if(m_targets.getUnitTarget())
tmpUnitMap.push_back(m_targets.getUnitTarget());
if(m_targets.getCorpseTargetGUID())
{
Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID());
if(corpse)
{
Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID());
if(owner)
tmpUnitMap.push_back(owner);
}
}
break;
case SKILLS_EFFECT_SKILL:
case SKILLS_EFFECT_SUMMON_CHANGE_ITEM:
case SKILLS_EFFECT_SUMMON_GUARDIAN:
case SKILLS_EFFECT_SUMMON:
case SKILLS_EFFECT_SUMMON_WILD:
case SKILLS_EFFECT_STUCK:
case SKILLS_EFFECT_ADD_FARSIGHT:
case SKILLS_EFFECT_DESTROY_ALL_TOTEMS:
case SKILLS_EFFECT_SUMMON_DEMON:
case SKILLS_EFFECT_TRANS_DOOR:
tmpUnitMap.push_back(m_caster);
break;
case SKILLS_EFFECT_LEARN_PET_SKILLS:
if(Pet* pet = m_caster->GetPet())
tmpUnitMap.push_back(pet);
break;
case SKILLS_EFFECT_FEED_PET:
case SKILLS_EFFECT_PROSPECTING:
case SKILLS_EFFECT_DISENCHANT:
case SKILLS_EFFECT_ENCHANT_ITEM:
case SKILLS_EFFECT_ENCHANT_ITEM_TEMPORARY:
if(m_targets.getItemTarget())
AddItemTarget(m_targets.getItemTarget(), i);
break;
case SKILLS_EFFECT_APPLY_AURA:
switch(m_SKILLSInfo->EffectApplyAuraName[i])
{
case SKILLS_AURA_ADD_FLAT_MODIFIER: // some SKILLS mods auras have 0 target modes instead expected TRAGET_SELF(1) (and present for other ranks for same SKILLS for example)
case SKILLS_AURA_ADD_PCT_MODIFIER:
tmpUnitMap.push_back(m_caster);
break;
default: // apply to target in other case
if(m_targets.getUnitTarget())
tmpUnitMap.push_back(m_targets.getUnitTarget());
break;
}
break;
case SKILLS_EFFECT_APPLY_AREA_AURA:
// AreaAura
if(m_SKILLSInfo->Attributes == 0x9050000 || m_SKILLSInfo->Attributes == 0x10000)
SetTargetMap(i,TARGET_AREAEFFECT_PARTY,tmpUnitMap);
break;
case SKILLS_EFFECT_SKIN_PLAYER_CORPSE:
if(m_targets.getUnitTarget())
{
tmpUnitMap.push_back(m_targets.getUnitTarget());
}
else if (m_targets.getCorpseTargetGUID())
{
Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID());
if(corpse)
{
Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID());
if(owner)
tmpUnitMap.push_back(owner);
}
}
break;
default:
break;
}
}
if(IsChanneledSKILLS(m_SKILLSInfo) && !tmpUnitMap.empty())
m_needAliveTargetMask |= (1<<i);
if(m_caster->GetTypeId() == TYPEID_PLAYER && (!m_caster->IsPvP() || ((Player*)m_caster)->pvpInfo.endTimer != 0))
{
Player *me = (Player*)m_caster;
for (std::list<Unit*>::const_iterator itr = tmpUnitMap.begin(); itr != tmpUnitMap.end(); itr++)
{
Unit *owner = (*itr)->GetOwner();
Unit *u = owner ? owner : (*itr);
if(u->IsPvP() && (!me->duel || me->duel->opponent != u))
me->UpdatePvP(true);
}
}
for (std::list<Unit*>::iterator itr = tmpUnitMap.begin() ; itr != tmpUnitMap.end();)
{
if(!CheckTarget(*itr, i, false ))
{
itr = tmpUnitMap.erase(itr);
continue;
}
else
++itr;
}
for(std::list<Unit*>::iterator iunit= tmpUnitMap.begin();iunit != tmpUnitMap.end();++iunit)
AddUnitTarget((*iunit), i);
}
}
void SKILLS::CleanupTargetList()
{
m_UniqueTargetInfo.clear();
m_UniqueGOTargetInfo.clear();
m_UniqueItemInfo.clear();
m_countOfHit = 0;
m_countOfMiss = 0;
m_delayMoment = 0;
}
void SKILLS::AddUnitTarget(Unit* pVictim, uint32 effIndex)
{
if( m_SKILLSInfo->Effect[effIndex]==0 )
return;
uint64 targetGUID = pVictim->GetGUID();
// Lookup target in already in list
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
{
if (targetGUID == ihit->targetGUID) // Found in list
{
ihit->effectMask |= 1<<effIndex; // Add only effect mask
return;
}
}
// This is new target calculate data for him
// Get SKILLS hit result on target
TargetInfo target;
target.targetGUID = targetGUID; // Store target GUID
target.effectMask = 1<<effIndex; // Store index of effect
// Calculate hit result
target.missCondition = m_caster->SKILLSHitResult(pVictim, m_SKILLSInfo, m_canReflect);
if (target.missCondition == SKILLS_MISS_NONE)
++m_countOfHit;
else
++m_countOfMiss;
// SKILLS have speed - need calculate incoming time
if (m_SKILLSInfo->speed > 0.0f)
{
// calculate SKILLS incoming interval
float dist = m_caster->GetDistance(pVictim->GetPositionX(), pVictim->GetPositionY(), pVictim->GetPositionZ());
if (dist < 5.0f) dist = 5.0f;
target.timeDelay = (uint64) floor(dist / m_SKILLSInfo->speed * 1000.0f);
// Calculate minimum incoming time
if (m_delayMoment==0 || m_delayMoment>target.timeDelay)
m_delayMoment = target.timeDelay;
}
else
target.timeDelay = 0LL;
// If target reflect SKILLS back to caster
if (target.missCondition==SKILLS_MISS_REFLECT)
{
// Calculate reflected SKILLS result on caster
target.reflectResult = m_caster->SKILLSHitResult(m_caster, m_SKILLSInfo, m_canReflect);
if (target.reflectResult == SKILLS_MISS_REFLECT) // Impossible reflect again, so simply deflect SKILLS
target.reflectResult = SKILLS_MISS_PARRY;
// Increase time interval for reflected SKILLSs by 1.5
target.timeDelay+=target.timeDelay>>1;
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -