fix(Core/Spells): Blink. (#11663)

* fix(Core/Spells): Blink.

Fixes #6427
Fixes #7571

* Update.
This commit is contained in:
UltraNix
2022-05-10 22:37:53 +02:00
committed by GitHub
parent 763a521da8
commit 0d4adf5a3e
2 changed files with 206 additions and 11 deletions

View File

@@ -2257,9 +2257,9 @@ LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z,
// Get position delta
if (delta > collisionHeight)
liquidData.Status = LIQUID_MAP_UNDER_WATER;
if (delta > 0.0f)
else if (delta > 0.0f)
liquidData.Status = LIQUID_MAP_IN_WATER;
if (delta > -0.1f)
else if (delta > -0.1f)
liquidData.Status = LIQUID_MAP_WATER_WALK;
else
liquidData.Status = LIQUID_MAP_ABOVE_WATER;

View File

@@ -1407,19 +1407,214 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
}
case TARGET_DEST_CASTER_FRONT_LEAP:
{
Unit* unitCaster = m_caster->ToUnit();
if (!unitCaster)
float distance = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
Map* map = m_caster->GetMap();
uint32 mapid = m_caster->GetMapId();
uint32 phasemask = m_caster->GetPhaseMask();
float collisionHeight = m_caster->GetCollisionHeight();
float destx, desty, destz, ground, startx, starty, startz, starto;
Position pos;
Position lastpos;
m_caster->GetPosition(startx, starty, startz, starto);
pos.Relocate(startx, starty, startz, starto);
destx = pos.GetPositionX() + distance * cos(pos.GetOrientation());
desty = pos.GetPositionY() + distance * sin(pos.GetOrientation());
ground = map->GetHeight(phasemask, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
bool isCasterInWater = m_caster->IsInWater();
if (!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING) || (pos.GetPositionZ() - ground < distance))
{
break;
float tstX, tstY, tstZ, prevX, prevY, prevZ;
float tstZ1, tstZ2, tstZ3, destz1, destz2, destz3, srange, srange1, srange2, srange3;
float maxtravelDistZ = 2.65f;
float overdistance = 0.0f;
float totalpath = 0.0f;
float beforewaterz = 0.0f;
bool inwater = false;
bool wcol = false;
const float step = 2.0f;
const uint8 numChecks = ceil(fabs(distance / step));
const float DELTA_X = (destx - pos.GetPositionX()) / numChecks;
const float DELTA_Y = (desty - pos.GetPositionY()) / numChecks;
int j = 1;
for (; j < (numChecks + 1); j++)
{
prevX = pos.GetPositionX() + (float(j - 1) * DELTA_X);
prevY = pos.GetPositionY() + (float(j - 1) * DELTA_Y);
tstX = pos.GetPositionX() + (float(j) * DELTA_X);
tstY = pos.GetPositionY() + (float(j) * DELTA_Y);
if (j < 2)
{
prevZ = pos.GetPositionZ();
}
else
{
prevZ = tstZ;
}
tstZ = map->GetHeight(phasemask, tstX, tstY, prevZ + maxtravelDistZ, true);
ground = tstZ;
if (!isCasterInWater)
{
if (map->IsInWater(phasemask, tstX, tstY, tstZ, collisionHeight))
{
if (!(beforewaterz != 0.0f))
{
beforewaterz = prevZ;
}
tstZ = beforewaterz;
srange = sqrt((tstY - prevY) * (tstY - prevY) + (tstX - prevX) * (tstX - prevX));
//TC_LOG_ERROR("server", "(start was from land) step in water , number of cycle = %i , distance of step = %f, total path = %f, Z = %f", j, srange, totalpath, tstZ);
}
}
else if (map->IsInWater(phasemask, tstX, tstY, tstZ, collisionHeight))
{
prevZ = pos.GetPositionZ();
tstZ = pos.GetPositionZ();
srange = sqrt((tstY - prevY) * (tstY - prevY) + (tstX - prevX) * (tstX - prevX));
inwater = true;
if (inwater && (fabs(tstZ - ground) < 2.0f))
{
wcol = true;
//TC_LOG_ERROR("server", "step in water with collide and use standart check (for continue way after possible collide), number of cycle = %i ", j);
}
// if (j < 2)
// TC_LOG_ERROR("server", "(start in water) step in water, number of cycle = %i , distance of step = %f, total path = %f", j, srange, totalpath);
// else
// TC_LOG_ERROR("server", "step in water, number of cycle = %i , distance of step = %f, total path = %f", j, srange, totalpath);
}
bool IsInWater = map->IsInWater(phasemask, tstX, tstY, tstZ, collisionHeight);
if ((!IsInWater && tstZ != beforewaterz) || wcol) // second safety check z for blink way if on the ground
{
if (inwater && !IsInWater)
inwater = false;
// highest available point
tstZ1 = map->GetHeight(phasemask, tstX, tstY, prevZ + maxtravelDistZ, true, 25.0f);
// upper or floor
tstZ2 = map->GetHeight(phasemask, tstX, tstY, prevZ, true, 25.0f);
//lower than floor
tstZ3 = map->GetHeight(phasemask, tstX, tstY, prevZ - maxtravelDistZ / 2, true, 25.0f);
//distance of rays, will select the shortest in 3D
srange1 = sqrt((tstY - prevY) * (tstY - prevY) + (tstX - prevX) * (tstX - prevX) + (tstZ1 - prevZ) * (tstZ1 - prevZ));
//TC_LOG_ERROR("server", "step = %i, distance of ray1 = %f", j, srange1);
srange2 = sqrt((tstY - prevY) * (tstY - prevY) + (tstX - prevX) * (tstX - prevX) + (tstZ2 - prevZ) * (tstZ2 - prevZ));
//TC_LOG_ERROR("server", "step = %i, distance of ray2 = %f", j, srange2);
srange3 = sqrt((tstY - prevY) * (tstY - prevY) + (tstX - prevX) * (tstX - prevX) + (tstZ3 - prevZ) * (tstZ3 - prevZ));
//TC_LOG_ERROR("server", "step = %i, distance of ray3 = %f", j, srange3);
if (srange1 < srange2)
{
tstZ = tstZ1;
srange = srange1;
}
else if (srange3 < srange2)
{
tstZ = tstZ3;
srange = srange3;
}
else
{
tstZ = tstZ2;
srange = srange2;
}
//TC_LOG_ERROR("server", "step on ground, number of cycle = %i , distance of step = %f, total path = %f", j, srange, totalpath);
}
destx = tstX;
desty = tstY;
destz = tstZ;
totalpath += srange;
if (totalpath > distance)
{
overdistance = totalpath - distance;
//TC_LOG_ERROR("server", "total path > than distance in 3D , need to move back a bit for save distance, total path = %f, overdistance = %f", totalpath, overdistance);
}
bool col = VMAP::VMapFactory::createOrGetVMapMgr()->GetObjectHitPos(mapid, prevX, prevY, prevZ + 0.5f, tstX, tstY, tstZ + 0.5f, tstX, tstY, tstZ, -0.5f);
// check dynamic collision
bool dcol = m_caster->GetMap()->GetObjectHitPos(phasemask, prevX, prevY, prevZ + 0.5f, tstX, tstY, tstZ + 0.5f, tstX, tstY, tstZ, -0.5f);
// collision occured
if (col || dcol || (overdistance > 0.0f && !map->IsInWater(phasemask, tstX, tstY, ground, collisionHeight)) || (fabs(prevZ - tstZ) > maxtravelDistZ && (tstZ > prevZ)))
{
if ((overdistance > 0.0f) && (overdistance < step))
{
destx = prevX + overdistance * cos(pos.GetOrientation());
desty = prevY + overdistance * sin(pos.GetOrientation());
//TC_LOG_ERROR("server", "(collision) collision occured 1");
}
else
{
// move back a bit
destx = tstX - (0.6 * cos(pos.GetOrientation()));
desty = tstY - (0.6 * sin(pos.GetOrientation()));
//TC_LOG_ERROR("server", "(collision) collision occured 2");
}
// highest available point
destz1 = map->GetHeight(phasemask, destx, desty, prevZ + maxtravelDistZ, true, 25.0f);
// upper or floor
destz2 = map->GetHeight(phasemask, destx, desty, prevZ, true, 25.0f);
//lower than floor
destz3 = map->GetHeight(phasemask, destx, desty, prevZ - maxtravelDistZ / 2, true, 25.0f);
//distance of rays, will select the shortest in 3D
srange1 = sqrt((desty - prevY) * (desty - prevY) + (destx - prevX) * (destx - prevX) + (destz1 - prevZ) * (destz1 - prevZ));
srange2 = sqrt((desty - prevY) * (desty - prevY) + (destx - prevX) * (destx - prevX) + (destz2 - prevZ) * (destz2 - prevZ));
srange3 = sqrt((desty - prevY) * (desty - prevY) + (destx - prevX) * (destx - prevX) + (destz3 - prevZ) * (destz3 - prevZ));
if (srange1 < srange2)
destz = destz1;
else if (srange3 < srange2)
destz = destz3;
else
destz = destz2;
if (inwater && destz < prevZ && !wcol)
destz = prevZ;
//TC_LOG_ERROR("server", "(collision) destZ rewrited in prevZ");
break;
}
// we have correct destz now
}
//}
lastpos.Relocate(destx, desty, destz + 0.5f, pos.GetOrientation());
dest = SpellDestination(lastpos);
}
else
{
float z = pos.GetPositionZ();
bool col = VMAP::VMapFactory::createOrGetVMapMgr()->GetObjectHitPos(mapid, pos.GetPositionX(), pos.GetPositionY(), z + 0.5f, destx, desty, z + 0.5f, destx, desty, z, -0.5f);
// check dynamic collision
bool dcol = m_caster->GetMap()->GetObjectHitPos(phasemask, pos.GetPositionX(), pos.GetPositionY(), z + 0.5f, destx, desty, z + 0.5f, destx, desty, z, -0.5f);
float dist = m_spellInfo->Effects[effIndex].CalcRadius(unitCaster);
float angle = targetType.CalcDirectionAngle();
// collision occured
if (col || dcol)
{
// move back a bit
destx = destx - (0.6 * cos(pos.GetOrientation()));
desty = desty - (0.6 * sin(pos.GetOrientation()));
}
Position pos = dest._position;
unitCaster->MovePositionToFirstCollision(pos, dist, angle);
dest.Relocate(pos);
lastpos.Relocate(destx, desty, z, pos.GetOrientation());
dest = SpellDestination(lastpos);
//float range = sqrt((desty - pos.GetPositionY())*(desty - pos.GetPositionY()) + (destx - pos.GetPositionX())*(destx - pos.GetPositionX()));
//TC_LOG_ERROR("server", "Blink number 2, in falling but at a hight, distance of blink = %f", range);
}
break;
}
default: