mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-23 05:36:23 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -392,11 +392,13 @@ void Guardian::InitStats(uint32 duration)
|
||||
{
|
||||
Minion::InitStats(duration);
|
||||
|
||||
Unit* m_owner = GetOwner();
|
||||
InitStatsForLevel(m_owner->getLevel());
|
||||
if (Unit* m_owner = GetOwner())
|
||||
{
|
||||
InitStatsForLevel(m_owner->getLevel());
|
||||
|
||||
if (m_owner->GetTypeId() == TYPEID_PLAYER && HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
|
||||
m_charmInfo->InitCharmCreateSpells();
|
||||
if (m_owner->GetTypeId() == TYPEID_PLAYER && HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
|
||||
m_charmInfo->InitCharmCreateSpells();
|
||||
}
|
||||
|
||||
SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
@@ -349,14 +349,14 @@ public:
|
||||
m_flags = 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] T_FLAGS GetFlags() const { return m_flags; }
|
||||
[[nodiscard]] bool HasFlag(FLAG_TYPE flag) const { return m_flags & (1 << flag); }
|
||||
void AddFlag(FLAG_TYPE flag) { m_flags |= (1 << flag); }
|
||||
void DelFlag(FLAG_TYPE flag) { m_flags &= ~(1 << flag); }
|
||||
[[nodiscard]] T_FLAGS GetFlags() const { return m_flags; }
|
||||
[[nodiscard]] bool HasFlag(FLAG_TYPE flag) const { return m_flags & (1 << flag); }
|
||||
void AddFlag(FLAG_TYPE flag) { m_flags |= (1 << flag); }
|
||||
void DelFlag(FLAG_TYPE flag) { m_flags &= ~(1 << flag); }
|
||||
|
||||
[[nodiscard]] T_VALUES GetValue(FLAG_TYPE flag) const { return m_values[flag]; }
|
||||
void SetValue(FLAG_TYPE flag, T_VALUES value) { m_values[flag] = value; }
|
||||
void AddValue(FLAG_TYPE flag, T_VALUES value) { m_values[flag] += value; }
|
||||
void SetValue(FLAG_TYPE flag, T_VALUES value) { m_values[flag] = value; }
|
||||
void AddValue(FLAG_TYPE flag, T_VALUES value) { m_values[flag] += value; }
|
||||
|
||||
private:
|
||||
T_VALUES m_values[ARRAY_SIZE];
|
||||
|
||||
@@ -2947,7 +2947,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
|
||||
|
||||
// Check for attack from behind
|
||||
// xinef: if from behind or spell requires cast from behind
|
||||
if (!victim->HasInArc(M_PI, this) || spellInfo->HasAttribute(SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET))
|
||||
if (!victim->HasInArc(M_PI, this))
|
||||
{
|
||||
if (!victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION))
|
||||
{
|
||||
@@ -2958,6 +2958,11 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
|
||||
canParry = false;
|
||||
canBlock = false;
|
||||
}
|
||||
else // Only deterrence as of 3.3.5
|
||||
{
|
||||
if (spellInfo->HasAttribute(SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET))
|
||||
canParry = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check creatures flags_extra for disable parry
|
||||
|
||||
@@ -807,6 +807,14 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
|
||||
{
|
||||
if (pProto->SellPrice > 0)
|
||||
{
|
||||
uint32 money = pProto->SellPrice * count;
|
||||
if (_player->GetMoney() >= MAX_MONEY_AMOUNT - money) // prevent exceeding gold limit
|
||||
{
|
||||
_player->SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, nullptr, nullptr);
|
||||
_player->SendSellError(SELL_ERR_UNK, creature, itemguid, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_ITEMDELETE_VENDOR))
|
||||
recoveryItem(pItem);
|
||||
|
||||
@@ -839,7 +847,6 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
|
||||
_player->UpdateTitansGrip();
|
||||
}
|
||||
|
||||
uint32 money = pProto->SellPrice * count;
|
||||
_player->ModifyMoney(money);
|
||||
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money);
|
||||
}
|
||||
|
||||
@@ -1336,7 +1336,8 @@ GridMap::GridMap()
|
||||
_maxHeight = nullptr;
|
||||
_minHeight = nullptr;
|
||||
// Liquid data
|
||||
_liquidType = 0;
|
||||
_liquidGlobalEntry = 0;
|
||||
_liquidGlobalFlags = 0;
|
||||
_liquidOffX = 0;
|
||||
_liquidOffY = 0;
|
||||
_liquidWidth = 0;
|
||||
@@ -1513,7 +1514,8 @@ bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
|
||||
if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapLiquidMagic.asUInt)
|
||||
return false;
|
||||
|
||||
_liquidType = header.liquidType;
|
||||
_liquidGlobalEntry = header.liquidType;
|
||||
_liquidGlobalFlags = header.liquidFlags;
|
||||
_liquidOffX = header.offsetX;
|
||||
_liquidOffY = header.offsetY;
|
||||
_liquidWidth = header.width;
|
||||
@@ -1893,7 +1895,7 @@ inline LiquidData const GridMap::GetLiquidData(float x, float y, float z, float
|
||||
LiquidData liquidData;
|
||||
|
||||
// Check water type (if no water return)
|
||||
if (_liquidType || _liquidFlags)
|
||||
if (_liquidGlobalFlags || _liquidFlags)
|
||||
{
|
||||
// Get cell
|
||||
float cx = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
|
||||
@@ -1903,38 +1905,34 @@ inline LiquidData const GridMap::GetLiquidData(float x, float y, float z, float
|
||||
int y_int = (int) cy & (MAP_RESOLUTION - 1);
|
||||
|
||||
// Check water type in cell
|
||||
int idx = (x_int >> 3) * 16 + (y_int >> 3);
|
||||
uint8 type = _liquidFlags ? _liquidFlags[idx] : _liquidType;
|
||||
uint32 entry = 0;
|
||||
if (_liquidEntry)
|
||||
int idx=(x_int>>3)*16 + (y_int>>3);
|
||||
uint8 type = _liquidFlags ? _liquidFlags[idx] : _liquidGlobalFlags;
|
||||
uint32 entry = _liquidEntry ? _liquidEntry[idx] : _liquidGlobalEntry;
|
||||
if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(entry))
|
||||
{
|
||||
if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(_liquidEntry[idx]))
|
||||
type &= MAP_LIQUID_TYPE_DARK_WATER;
|
||||
uint32 liqTypeIdx = liquidEntry->Type;
|
||||
if (entry < 21)
|
||||
{
|
||||
entry = liquidEntry->Id;
|
||||
type &= MAP_LIQUID_TYPE_DARK_WATER;
|
||||
uint32 liqTypeIdx = liquidEntry->Type;
|
||||
if (entry < 21)
|
||||
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y)))
|
||||
{
|
||||
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y)))
|
||||
uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
|
||||
if (!overrideLiquid && area->zone)
|
||||
{
|
||||
uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
|
||||
if (!overrideLiquid && area->zone)
|
||||
{
|
||||
area = sAreaTableStore.LookupEntry(area->zone);
|
||||
if (area)
|
||||
overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
|
||||
}
|
||||
area = sAreaTableStore.LookupEntry(area->zone);
|
||||
if (area)
|
||||
overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
|
||||
}
|
||||
|
||||
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
|
||||
{
|
||||
entry = overrideLiquid;
|
||||
liqTypeIdx = liq->Type;
|
||||
}
|
||||
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
|
||||
{
|
||||
entry = overrideLiquid;
|
||||
liqTypeIdx = liq->Type;
|
||||
}
|
||||
}
|
||||
|
||||
type |= 1 << liqTypeIdx;
|
||||
}
|
||||
|
||||
type |= 1 << liqTypeIdx;
|
||||
}
|
||||
|
||||
// Check req liquid type mask
|
||||
|
||||
@@ -128,7 +128,8 @@ struct map_heightHeader
|
||||
struct map_liquidHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint8 flags;
|
||||
uint8 liquidFlags;
|
||||
uint16 liquidType;
|
||||
uint8 offsetX;
|
||||
uint8 offsetY;
|
||||
@@ -158,7 +159,6 @@ enum LiquidStatus
|
||||
#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)
|
||||
|
||||
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
|
||||
#define MAP_LIQUID_TYPE_WMO_WATER 0x20
|
||||
|
||||
#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface
|
||||
#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
|
||||
@@ -227,7 +227,8 @@ class GridMap
|
||||
uint8* _liquidFlags;
|
||||
float* _liquidMap;
|
||||
uint16 _gridArea;
|
||||
uint16 _liquidType;
|
||||
uint16 _liquidGlobalEntry;
|
||||
uint8 _liquidGlobalFlags;
|
||||
uint8 _liquidOffX;
|
||||
uint8 _liquidOffY;
|
||||
uint8 _liquidWidth;
|
||||
|
||||
@@ -608,11 +608,11 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id,
|
||||
}
|
||||
}
|
||||
|
||||
void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_CHARGE*/)
|
||||
void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_CHARGE*/, ObjectGuid targetGUID /*= ObjectGuid::Empty*/)
|
||||
{
|
||||
G3D::Vector3 dest = path.GetActualEndPosition();
|
||||
|
||||
MoveCharge(dest.x, dest.y, dest.z, speed, EVENT_CHARGE_PREPATH);
|
||||
MoveCharge(dest.x, dest.y, dest.z, speed, EVENT_CHARGE_PREPATH, nullptr, false, 0.0f, targetGUID);
|
||||
|
||||
// Charge movement is not started when using EVENT_CHARGE_PREPATH
|
||||
Movement::MoveSplineInit init(_owner);
|
||||
|
||||
@@ -219,7 +219,7 @@ public:
|
||||
void MoveTakeoff(uint32 id, float x, float y, float z, float speed = 0.0f); // pussywizard: added for easy calling by passing 3 floats x, y, z
|
||||
|
||||
void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, const Movement::PointsArray* path = nullptr, bool generatePath = false, float orientation = 0.0f, ObjectGuid targetGUID = ObjectGuid::Empty);
|
||||
void MoveCharge(PathGenerator const& path, float speed = SPEED_CHARGE);
|
||||
void MoveCharge(PathGenerator const& path, float speed = SPEED_CHARGE, ObjectGuid targetGUID = ObjectGuid::Empty);
|
||||
void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ);
|
||||
void MoveJumpTo(float angle, float speedXY, float speedZ);
|
||||
void MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id = 0)
|
||||
|
||||
@@ -27,304 +27,31 @@
|
||||
#define MIN_QUIET_DISTANCE 28.0f
|
||||
#define MAX_QUIET_DISTANCE 43.0f
|
||||
|
||||
template<class T>
|
||||
void FleeingMovementGenerator<T>::_setTargetLocation(T* owner)
|
||||
{
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_setMoveData(owner))
|
||||
return;
|
||||
|
||||
float x, y, z;
|
||||
if (!_getPoint(owner, x, y, z)) {
|
||||
i_nextCheckTime.Reset(100);
|
||||
return;
|
||||
}
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_FLEEING_MOVE);
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MoveTo(x, y, z, true);
|
||||
init.SetWalk(false);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool FleeingMovementGenerator<T>::_getPoint(T* owner, float& x, float& y, float& z)
|
||||
{
|
||||
if (!owner)
|
||||
return false;
|
||||
|
||||
const Map* _map = owner->GetMap();
|
||||
|
||||
x = owner->GetPositionX();
|
||||
y = owner->GetPositionY();
|
||||
z = owner->GetPositionZ();
|
||||
|
||||
float temp_x, temp_y, angle;
|
||||
// primitive path-finding
|
||||
for (uint8 i = 0; i < 18; ++i)
|
||||
{
|
||||
if (i_only_forward && i > 2)
|
||||
break;
|
||||
|
||||
float distance = 5.0f;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
angle = i_cur_angle;
|
||||
break;
|
||||
case 1:
|
||||
angle = i_cur_angle;
|
||||
distance /= 2;
|
||||
break;
|
||||
case 2:
|
||||
angle = i_cur_angle;
|
||||
distance /= 4;
|
||||
break;
|
||||
case 3:
|
||||
angle = i_cur_angle + static_cast<float>(M_PI / 4);
|
||||
break;
|
||||
case 4:
|
||||
angle = i_cur_angle - static_cast<float>(M_PI / 4);
|
||||
break;
|
||||
case 5:
|
||||
angle = i_cur_angle + static_cast<float>(M_PI / 4);
|
||||
distance /= 2;
|
||||
break;
|
||||
case 6:
|
||||
angle = i_cur_angle - static_cast<float>(M_PI / 4);
|
||||
distance /= 2;
|
||||
break;
|
||||
case 7:
|
||||
angle = i_cur_angle + static_cast<float>(M_PI / 2);
|
||||
break;
|
||||
case 8:
|
||||
angle = i_cur_angle - static_cast<float>(M_PI / 2);
|
||||
break;
|
||||
case 9:
|
||||
angle = i_cur_angle + static_cast<float>(M_PI / 2);
|
||||
distance /= 2;
|
||||
break;
|
||||
case 10:
|
||||
angle = i_cur_angle - static_cast<float>(M_PI / 2);
|
||||
distance /= 2;
|
||||
break;
|
||||
case 11:
|
||||
angle = i_cur_angle + static_cast<float>(M_PI / 4);
|
||||
distance /= 4;
|
||||
break;
|
||||
case 12:
|
||||
angle = i_cur_angle - static_cast<float>(M_PI / 4);
|
||||
distance /= 4;
|
||||
break;
|
||||
case 13:
|
||||
angle = i_cur_angle + static_cast<float>(M_PI / 2);
|
||||
distance /= 4;
|
||||
break;
|
||||
case 14:
|
||||
angle = i_cur_angle - static_cast<float>(M_PI / 2);
|
||||
distance /= 4;
|
||||
break;
|
||||
case 15:
|
||||
angle = i_cur_angle + static_cast<float>(3 * M_PI / 4);
|
||||
distance /= 2;
|
||||
break;
|
||||
case 16:
|
||||
angle = i_cur_angle - static_cast<float>(3 * M_PI / 4);
|
||||
distance /= 2;
|
||||
break;
|
||||
case 17:
|
||||
angle = i_cur_angle + static_cast<float>(M_PI);
|
||||
distance /= 2;
|
||||
break;
|
||||
default:
|
||||
angle = 0.0f;
|
||||
distance = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
temp_x = x + distance * cos(angle);
|
||||
temp_y = y + distance * std::sin(angle);
|
||||
float temp_z = z;
|
||||
|
||||
if (!_map->CanReachPositionAndGetValidCoords(owner, temp_x, temp_y, temp_z, true, true))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(temp_z - z) || distance / std::fabs(temp_z - z) > 1.0f)
|
||||
{
|
||||
float temp_z_left = _map->GetHeight(owner->GetPhaseMask(), temp_x + 1.0f * cos(angle + static_cast<float>(M_PI / 2)), temp_y + 1.0f * std::sin(angle + static_cast<float>(M_PI / 2)), z, true);
|
||||
float temp_z_right = _map->GetHeight(owner->GetPhaseMask(), temp_x + 1.0f * cos(angle - static_cast<float>(M_PI / 2)), temp_y + 1.0f * std::sin(angle - static_cast<float>(M_PI / 2)), z, true);
|
||||
if (std::fabs(temp_z_left - temp_z) < 1.2f && std::fabs(temp_z_right - temp_z) < 1.2f)
|
||||
{
|
||||
// use new values
|
||||
x = temp_x;
|
||||
y = temp_y;
|
||||
z = temp_z;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
i_nextCheckTime.Reset(urand(500, 1000));
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool FleeingMovementGenerator<T>::_setMoveData(T* owner)
|
||||
{
|
||||
float cur_dist_xyz = owner->GetDistance(i_caster_x, i_caster_y, i_caster_z);
|
||||
|
||||
if (i_to_distance_from_caster > 0.0f)
|
||||
{
|
||||
if ((i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz < i_to_distance_from_caster) ||
|
||||
// if we reach lower distance
|
||||
(i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz > i_last_distance_from_caster) ||
|
||||
// if we can't be close
|
||||
(i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) ||
|
||||
// if we reach bigger distance
|
||||
(cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far
|
||||
(i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE))
|
||||
// if we leave 'quiet zone'
|
||||
{
|
||||
// we are very far or too close, stopping
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
i_nextCheckTime.Reset(urand(500, 1000));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// now we are running, continue
|
||||
i_last_distance_from_caster = cur_dist_xyz;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
float cur_dist;
|
||||
float angle_to_caster;
|
||||
|
||||
if (Unit* fright = ObjectAccessor::GetUnit(*owner, i_frightGUID))
|
||||
{
|
||||
cur_dist = fright->GetDistance(owner);
|
||||
if (cur_dist < cur_dist_xyz)
|
||||
{
|
||||
i_caster_x = fright->GetPositionX();
|
||||
i_caster_y = fright->GetPositionY();
|
||||
i_caster_z = fright->GetPositionZ();
|
||||
angle_to_caster = fright->GetAngle(owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_dist = cur_dist_xyz;
|
||||
angle_to_caster = owner->GetAngle(i_caster_x, i_caster_y) + static_cast<float>(M_PI);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_dist = cur_dist_xyz;
|
||||
angle_to_caster = owner->GetAngle(i_caster_x, i_caster_y) + static_cast<float>(M_PI);
|
||||
}
|
||||
|
||||
// if we too close may use 'path-finding' else just stop
|
||||
i_only_forward = cur_dist >= MIN_QUIET_DISTANCE / 3;
|
||||
|
||||
//get angle and 'distance from caster' to run
|
||||
float angle;
|
||||
|
||||
if (i_cur_angle == 0.0f && i_last_distance_from_caster == 0.0f) //just started, first time
|
||||
{
|
||||
angle = (float)rand_norm() * (1.0f - cur_dist / MIN_QUIET_DISTANCE) * static_cast<float>(M_PI / 3) + (float)rand_norm() * static_cast<float>(M_PI * 2 / 3);
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE;
|
||||
i_only_forward = true;
|
||||
}
|
||||
else if (cur_dist < MIN_QUIET_DISTANCE)
|
||||
{
|
||||
angle = static_cast<float>(M_PI / 6) + (float)rand_norm() * static_cast<float>(M_PI * 2 / 3);
|
||||
i_to_distance_from_caster = cur_dist * 2 / 3 + (float)rand_norm() * (MIN_QUIET_DISTANCE - cur_dist * 2 / 3);
|
||||
}
|
||||
else if (cur_dist > MAX_QUIET_DISTANCE)
|
||||
{
|
||||
angle = (float)rand_norm() * static_cast<float>(M_PI / 3) + static_cast<float>(M_PI * 2 / 3);
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + (float)rand_norm() * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = (float)rand_norm() * static_cast<float>(M_PI);
|
||||
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + (float)rand_norm() * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
|
||||
}
|
||||
|
||||
int8 sign = (float)rand_norm() > 0.5f ? 1 : -1;
|
||||
i_cur_angle = sign * angle + angle_to_caster;
|
||||
|
||||
// current distance
|
||||
i_last_distance_from_caster = cur_dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void FleeingMovementGenerator<T>::DoInitialize(T* owner)
|
||||
{
|
||||
if (!owner)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_path = nullptr;
|
||||
owner->SetUnitFlag(UNIT_FLAG_FLEEING);
|
||||
owner->AddUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE);
|
||||
|
||||
_Init(owner);
|
||||
|
||||
if (Unit* fright = ObjectAccessor::GetUnit(*owner, i_frightGUID))
|
||||
{
|
||||
i_caster_x = fright->GetPositionX();
|
||||
i_caster_y = fright->GetPositionY();
|
||||
i_caster_z = fright->GetPositionZ();
|
||||
}
|
||||
else
|
||||
{
|
||||
i_caster_x = owner->GetPositionX();
|
||||
i_caster_y = owner->GetPositionY();
|
||||
i_caster_z = owner->GetPositionZ();
|
||||
}
|
||||
|
||||
i_only_forward = true;
|
||||
i_cur_angle = 0.0f;
|
||||
i_last_distance_from_caster = 0.0f;
|
||||
i_to_distance_from_caster = 0.0f;
|
||||
_setTargetLocation(owner);
|
||||
owner->AddUnitState(UNIT_STATE_FLEEING);
|
||||
SetTargetLocation(owner);
|
||||
}
|
||||
|
||||
template<>
|
||||
void FleeingMovementGenerator<Creature>::_Init(Creature* owner)
|
||||
template<class T>
|
||||
void FleeingMovementGenerator<T>::DoFinalize(T*)
|
||||
{
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
//owner->SetTargetGuid(ObjectGuid());
|
||||
is_water_ok = owner->CanEnterWater();
|
||||
is_land_ok = owner->CanWalk();
|
||||
}
|
||||
|
||||
template<>
|
||||
void FleeingMovementGenerator<Player>::_Init(Player* )
|
||||
{
|
||||
is_water_ok = true;
|
||||
is_land_ok = true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void FleeingMovementGenerator<Player>::DoFinalize(Player* owner)
|
||||
{
|
||||
owner->RemoveUnitFlag(UNIT_FLAG_FLEEING);
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE);
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING);
|
||||
owner->StopMoving();
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -332,8 +59,11 @@ void FleeingMovementGenerator<Creature>::DoFinalize(Creature* owner)
|
||||
{
|
||||
owner->RemoveUnitFlag(UNIT_FLAG_FLEEING);
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE);
|
||||
if (owner->GetVictim())
|
||||
owner->SetTarget(owner->GetVictim()->GetGUID());
|
||||
|
||||
if (Unit* victim = owner->GetVictim())
|
||||
{
|
||||
owner->SetTarget(victim->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -343,36 +73,140 @@ void FleeingMovementGenerator<T>::DoReset(T* owner)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool FleeingMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
||||
bool FleeingMovementGenerator<T>::DoUpdate(T* owner, uint32 diff)
|
||||
{
|
||||
if (!owner || !owner->IsAlive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
_path = nullptr;
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
_interrupt = false;
|
||||
|
||||
i_nextCheckTime.Update(time_diff);
|
||||
if (i_nextCheckTime.Passed() && owner->movespline->Finalized())
|
||||
_setTargetLocation(owner);
|
||||
_timer.Update(diff);
|
||||
if (!_interrupt && _timer.Passed() && owner->movespline->Finalized())
|
||||
{
|
||||
SetTargetLocation(owner);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void FleeingMovementGenerator<T>::SetTargetLocation(T* owner)
|
||||
{
|
||||
if (!owner)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
_path = nullptr;
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return;
|
||||
}
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_FLEEING_MOVE);
|
||||
|
||||
Position destination = owner->GetPosition();
|
||||
GetPoint(owner, destination);
|
||||
|
||||
// Add LOS check for target point
|
||||
if (!owner->IsWithinLOS(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()))
|
||||
{
|
||||
_timer.Reset(200);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_path)
|
||||
{
|
||||
_path = std::make_unique<PathGenerator>(owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
_path->Clear();
|
||||
}
|
||||
|
||||
_path->SetPathLengthLimit(30.0f);
|
||||
bool result = _path->CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());
|
||||
if (!result || (_path->GetPathType() & PathType(PATHFIND_NOPATH | PATHFIND_SHORTCUT | PATHFIND_FARFROMPOLY)))
|
||||
{
|
||||
_timer.Reset(100);
|
||||
return;
|
||||
}
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MovebyPath(_path->GetPath());
|
||||
init.SetWalk(false);
|
||||
int32 traveltime = init.Launch();
|
||||
_timer.Reset(traveltime + urand(800, 1500));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void FleeingMovementGenerator<T>::GetPoint(T* owner, Position& position)
|
||||
{
|
||||
float casterDistance, casterAngle;
|
||||
if (Unit* fleeTarget = ObjectAccessor::GetUnit(*owner, _fleeTargetGUID))
|
||||
{
|
||||
casterDistance = fleeTarget->GetDistance(owner);
|
||||
if (casterDistance > 0.2f)
|
||||
{
|
||||
casterAngle = fleeTarget->GetAngle(owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
casterAngle = frand(0.0f, 2.0f * float(M_PI));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
casterDistance = 0.0f;
|
||||
casterAngle = frand(0.0f, 2.0f * float(M_PI));
|
||||
}
|
||||
|
||||
float distance, angle;
|
||||
if (casterDistance < MIN_QUIET_DISTANCE)
|
||||
{
|
||||
distance = frand(0.4f, 1.3f) * (MIN_QUIET_DISTANCE - casterDistance);
|
||||
angle = casterAngle + frand(-float(M_PI) / 8.0f, float(M_PI) / 8.0f);
|
||||
}
|
||||
else if (casterDistance > MAX_QUIET_DISTANCE)
|
||||
{
|
||||
distance = frand(0.4f, 1.0f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE);
|
||||
angle = -casterAngle + frand(-float(M_PI) / 4.0f, float(M_PI) / 4.0f);
|
||||
}
|
||||
else // we are inside quiet range
|
||||
{
|
||||
distance = frand(0.6f, 1.2f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE);
|
||||
angle = frand(0.0f, 2.0f * float(M_PI));
|
||||
}
|
||||
|
||||
// In MovePositionToFirstCollision we have added owner's orientation
|
||||
// so now let's subtract it
|
||||
angle -= owner->GetOrientation();
|
||||
|
||||
owner->MovePositionToFirstCollision(position, distance, angle);
|
||||
}
|
||||
|
||||
template void FleeingMovementGenerator<Player>::DoInitialize(Player*);
|
||||
template void FleeingMovementGenerator<Creature>::DoInitialize(Creature*);
|
||||
template bool FleeingMovementGenerator<Player>::_setMoveData(Player*);
|
||||
template bool FleeingMovementGenerator<Creature>::_setMoveData(Creature*);
|
||||
template bool FleeingMovementGenerator<Player>::_getPoint(Player*, float&, float&, float&);
|
||||
template bool FleeingMovementGenerator<Creature>::_getPoint(Creature*, float&, float&, float&);
|
||||
template void FleeingMovementGenerator<Player>::_setTargetLocation(Player*);
|
||||
template void FleeingMovementGenerator<Creature>::_setTargetLocation(Creature*);
|
||||
template void FleeingMovementGenerator<Player>::DoReset(Player*);
|
||||
template void FleeingMovementGenerator<Creature>::DoReset(Creature*);
|
||||
template bool FleeingMovementGenerator<Player>::DoUpdate(Player*, uint32);
|
||||
template bool FleeingMovementGenerator<Creature>::DoUpdate(Creature*, uint32);
|
||||
template void FleeingMovementGenerator<Player>::SetTargetLocation(Player*);
|
||||
template void FleeingMovementGenerator<Creature>::SetTargetLocation(Creature*);
|
||||
template void FleeingMovementGenerator<Player>::GetPoint(Player*, Position&);
|
||||
template void FleeingMovementGenerator<Creature>::GetPoint(Creature*, Position&);
|
||||
|
||||
void TimedFleeingMovementGenerator::Finalize(Unit* owner)
|
||||
{
|
||||
|
||||
@@ -23,34 +23,24 @@
|
||||
template<class T>
|
||||
class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
FleeingMovementGenerator(ObjectGuid fright) : i_frightGUID(fright), i_nextCheckTime(0) {}
|
||||
public:
|
||||
explicit FleeingMovementGenerator(ObjectGuid fleeTargetGUID) : _path(nullptr), _fleeTargetGUID(fleeTargetGUID), _timer(0), _interrupt(false) {}
|
||||
|
||||
void DoInitialize(T*);
|
||||
void DoFinalize(T*);
|
||||
void DoReset(T*);
|
||||
bool DoUpdate(T*, uint32);
|
||||
MovementGeneratorType GetMovementGeneratorType() override { return FLEEING_MOTION_TYPE; }
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; }
|
||||
void DoInitialize(T*);
|
||||
void DoFinalize(T*);
|
||||
void DoReset(T*);
|
||||
bool DoUpdate(T*, uint32);
|
||||
|
||||
private:
|
||||
void _setTargetLocation(T*);
|
||||
bool _getPoint(T*, float& x, float& y, float& z);
|
||||
bool _setMoveData(T* owner);
|
||||
void _Init(T* );
|
||||
private:
|
||||
void SetTargetLocation(T*);
|
||||
void GetPoint(T*, Position& position);
|
||||
|
||||
bool is_water_ok : 1;
|
||||
bool is_land_ok : 1;
|
||||
bool i_only_forward: 1;
|
||||
|
||||
float i_caster_x;
|
||||
float i_caster_y;
|
||||
float i_caster_z;
|
||||
float i_last_distance_from_caster;
|
||||
float i_to_distance_from_caster;
|
||||
float i_cur_angle;
|
||||
ObjectGuid i_frightGUID;
|
||||
TimeTracker i_nextCheckTime;
|
||||
std::unique_ptr<PathGenerator> _path;
|
||||
ObjectGuid _fleeTargetGUID;
|
||||
TimeTracker _timer;
|
||||
bool _interrupt;
|
||||
};
|
||||
|
||||
class TimedFleeingMovementGenerator : public FleeingMovementGenerator<Creature>
|
||||
|
||||
@@ -1537,7 +1537,7 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode
|
||||
if (apply)
|
||||
{
|
||||
// apply glow vision
|
||||
if (target->GetTypeId() == TYPEID_PLAYER && type == INVISIBILITY_GENERAL)
|
||||
if (target->GetTypeId() == TYPEID_PLAYER && (type == INVISIBILITY_GENERAL || type == INVISIBILITY_UNK10))
|
||||
target->SetByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
|
||||
|
||||
target->m_invisibility.AddFlag(type);
|
||||
@@ -1568,14 +1568,14 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
target->m_invisibility.DelFlag(type);
|
||||
|
||||
// if not have invisibility auras of type INVISIBILITY_GENERAL
|
||||
// remove glow vision
|
||||
if (target->GetTypeId() == TYPEID_PLAYER && type == INVISIBILITY_GENERAL)
|
||||
if (target->GetTypeId() == TYPEID_PLAYER && !target->m_invisibility.HasFlag(INVISIBILITY_GENERAL) && !target->m_invisibility.HasFlag(INVISIBILITY_UNK10))
|
||||
{
|
||||
target->RemoveByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
|
||||
}
|
||||
|
||||
target->m_invisibility.DelFlag(type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4875,7 +4875,7 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
|
||||
if (!m_preGeneratedPath)
|
||||
{
|
||||
Position pos = unitTarget->GetFirstCollisionPosition(unitTarget->GetCombatReach(), unitTarget->GetRelativeAngle(m_caster));
|
||||
m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speed);
|
||||
m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speed, EVENT_CHARGE, nullptr, false, 0.0f, targetGUID);
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
@@ -4884,7 +4884,7 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_caster->GetMotionMaster()->MoveCharge(*m_preGeneratedPath, speed);
|
||||
m_caster->GetMotionMaster()->MoveCharge(*m_preGeneratedPath, speed, targetGUID);
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
|
||||
@@ -1360,14 +1360,6 @@ bool SpellInfo::IsSingleTarget() const
|
||||
if (AttributesEx5 & SPELL_ATTR5_LIMIT_N)
|
||||
return true;
|
||||
|
||||
switch (GetSpellSpecific())
|
||||
{
|
||||
case SPELL_SPECIFIC_JUDGEMENT:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -3672,8 +3672,8 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->Effects[EFFECT_0].BasePoints = 0;
|
||||
});
|
||||
|
||||
// Krolmir, Hammer of Storms (13010)
|
||||
ApplySpellFix({ 56606, 56541 }, [](SpellInfo* spellInfo)
|
||||
// Riding Jokkum
|
||||
ApplySpellFix({ 56606 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->Effects[EFFECT_0].BasePoints = 1;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user