Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions sql/base/auth_database.sql
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,7 @@ INSERT INTO `rbac_linked_permissions` VALUES
(196,870),
(196,871),
(196,872),
(196,873),
(197,232),
(197,236),
(197,237),
Expand Down Expand Up @@ -1714,7 +1715,8 @@ INSERT INTO `rbac_permissions` VALUES
(867,'Command: reload quest_greeting_locale'),
(870,'Command: debug threatinfo'),
(871,'Command: debug instancespawn'),
(872,'Command: server debug');
(872,'Command: server debug'),
(873,'Command: reload creature_movement_override');
/*!40000 ALTER TABLE `rbac_permissions` ENABLE KEYS */;
UNLOCK TABLES;

Expand Down Expand Up @@ -1836,7 +1838,8 @@ INSERT INTO `updates` VALUES
('2018_01_09_00_auth.sql','A5D4EC8FCFAB4F2DCE70EDCAD1ACBFB484FD68D5','ARCHIVED','2018-01-09 00:00:00',69),
('2018_01_24_00_auth.sql','167B17D8A253D62A8112F8A7EB21C6E99CAEF1E4','ARCHIVED','2018-01-24 00:00:00',73),
('2018_02_19_00_auth.sql','80E50F9C7F1EE7BA62789EA4C4F009170B79E6C9','RELEASED','2018-02-18 19:49:37',62),
('2018_03_06_00_auth.sql','2D71E93DF7419A30D0D21D8A80CF05698302575A','RELEASED','2018-03-06 00:00:00',0);
('2018_03_06_00_auth.sql','2D71E93DF7419A30D0D21D8A80CF05698302575A','RELEASED','2018-03-06 00:00:00',0),
('2018_03_08_00_auth.sql','624C58A07E0B4DDC4C1347E8BA8EFEEFD5B43DA7','RELEASED','2018-01-12 15:10:11',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;

Expand Down
7 changes: 7 additions & 0 deletions sql/updates/auth/3.3.5/2018_03_08_00_auth.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
DELETE FROM `rbac_permissions` WHERE `id` = 873;
INSERT INTO `rbac_permissions` (`id`,`name`) VALUES
(873, 'Command: reload creature_movement_override');

DELETE FROM `rbac_linked_permissions` WHERE `linkedId` = 873;
INSERT INTO `rbac_linked_permissions` (`id`,`linkedId`) VALUES
(196, 873);
34 changes: 34 additions & 0 deletions sql/updates/world/3.3.5/2018_03_08_11_world.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
DROP TABLE IF EXISTS `creature_template_movement`;
CREATE TABLE `creature_template_movement` (
`CreatureId` int(10) unsigned NOT NULL DEFAULT '0',
`Ground` tinyint(3) unsigned NOT NULL DEFAULT '1',
`Swim` tinyint(3) unsigned NOT NULL DEFAULT '1',
`Flight` tinyint(3) unsigned NOT NULL DEFAULT '0',
`Rooted` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`CreatureId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `creature_movement_override`;
CREATE TABLE `creature_movement_override` (
`SpawnId` int(10) unsigned NOT NULL DEFAULT '0',
`Ground` tinyint(3) unsigned NOT NULL DEFAULT '1',
`Swim` tinyint(3) unsigned NOT NULL DEFAULT '1',
`Flight` tinyint(3) unsigned NOT NULL DEFAULT '0',
`Rooted` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`SpawnId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `creature_template_movement` SELECT `entry`,0,0,0,0 FROM `creature_template` WHERE `InhabitType`!=3;
UPDATE `creature_template_movement` SET `Ground`=1 WHERE `CreatureId` IN (SELECT `entry` FROM `creature_template` WHERE `InhabitType` & 1);
UPDATE `creature_template_movement` SET `Swim`=1 WHERE `CreatureId` IN (SELECT `entry` FROM `creature_template` WHERE `InhabitType` & 2);
UPDATE `creature_template_movement` SET `Flight`=1 WHERE `CreatureId` IN (SELECT `entry` FROM `creature_template` WHERE (`InhabitType` & 5) = 4);
UPDATE `creature_template_movement` SET `Flight`=2 WHERE `CreatureId` IN (SELECT `entry` FROM `creature_template` WHERE (`InhabitType` & 5) = 5);
UPDATE `creature_template_movement` SET `Rooted`=1 WHERE `CreatureId` IN (SELECT `entry` FROM `creature_template` WHERE `InhabitType` & 8);

ALTER TABLE `creature_template` DROP `InhabitType`;

UPDATE `trinity_string` SET `content_default`='Movement type: %s' WHERE `entry`=11008;

DELETE FROM `command` WHERE `name`='reload creature_movement_override';
INSERT INTO `command` (`name`,`permission`,`help`) VALUES
('reload creature_movement_override',873,'Syntax: .reload creature_movement_override\nReload creature_movement_override table.');
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, permission, help FROM command", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, scale, rank, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, scale, rank, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
Expand Down
1 change: 1 addition & 0 deletions src/server/game/Accounts/RBAC.h
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_DEBUG_THREATINFO = 870,
RBAC_PERM_COMMAND_DEBUG_INSTANCESPAWN = 871,
RBAC_PERM_COMMAND_SERVER_DEBUG = 872,
RBAC_PERM_COMMAND_RELOAD_CREATURE_MOVEMENT_OVERRIDE = 873,
//
// IF YOU ADD NEW PERMISSIONS, ADD THEM IN MASTER BRANCH AS WELL!
//
Expand Down
64 changes: 44 additions & 20 deletions src/server/game/Entities/Creature/Creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,22 @@
#include "WorldPacket.h"
#include <G3D/g3dmath.h>

std::string CreatureMovementData::ToString() const
{
char const* const GroundStates[] = { "None", "Run", "Hover" };
char const* const FlightStates[] = { "None", "DisableGravity", "CanFly" };

std::ostringstream str;
str << std::boolalpha
<< "Ground: " << GroundStates[AsUnderlyingType(Ground)]
<< ", Swim: " << Swim
<< ", Flight: " << FlightStates[AsUnderlyingType(Flight)];
if (Rooted)
str << ", Rooted";

return str.str();
}

VendorItemCount::VendorItemCount(uint32 _item, uint32 _count)
: itemId(_item), count(_count), lastIncrementTime(GameTime::GetGameTime()) { }

Expand Down Expand Up @@ -404,6 +420,7 @@ void Creature::RemoveCorpse(bool setSpawnTime, bool destroyForNearbyPlayers)
transport->CalculatePassengerPosition(x, y, z, &o);
}

UpdateAllowedPositionZ(x, y, z);
SetHomePosition(x, y, z, o);
GetMap()->CreatureRelocation(this, x, y, z, o);
}
Expand Down Expand Up @@ -609,7 +626,7 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
}

if (cInfo->InhabitType & INHABIT_ROOT)
if (GetMovementTemplate().IsRooted())
SetControlled(true, UNIT_STATE_ROOT);

UpdateMovementFlags();
Expand Down Expand Up @@ -1096,11 +1113,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u
}

//! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there
if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
{
//! Relocate again with updated Z coord
m_positionZ += GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
}
m_positionZ += GetHoverOffset();

LastUsedScriptID = GetScriptId();

Expand Down Expand Up @@ -1631,7 +1644,7 @@ bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap,
return false;

//We should set first home position, because then AI calls home movement
SetHomePosition(data->spawnPoint);
SetHomePosition(*this);

m_deathState = ALIVE;

Expand Down Expand Up @@ -1979,7 +1992,10 @@ void Creature::setDeathState(DeathState s)
if (m_formation && m_formation->GetLeader() == this)
m_formation->FormationReset(true);

if ((CanFly() || IsFlying()))
bool needsFalling = IsFlying() || IsHovering();
SetHover(false);

if (needsFalling)
GetMotionMaster()->MoveFall();

Unit::setDeathState(CORPSE);
Expand Down Expand Up @@ -2457,7 +2473,7 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const
dist += GetCombatReach() + victim->GetCombatReach();

// to prevent creatures in air ignore attacks because distance is already too high...
if (GetCreatureTemplate()->InhabitType & INHABIT_AIR)
if (GetMovementTemplate().IsFlightAllowed())
return victim->IsInDist2d(&m_homePosition, dist);
else
return victim->IsInDist(&m_homePosition, dist);
Expand Down Expand Up @@ -2504,7 +2520,7 @@ bool Creature::LoadCreaturesAddon()
//! Check using InhabitType as movement flags are assigned dynamically
//! basing on whether the creature is in air or not
//! Set MovementFlag_Hover. Otherwise do nothing.
if (GetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER) & UNIT_BYTE1_FLAG_HOVER && !(GetCreatureTemplate()->InhabitType & INHABIT_AIR))
if (CanHover())
AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
}

Expand Down Expand Up @@ -2615,6 +2631,14 @@ void Creature::GetRespawnPosition(float &x, float &y, float &z, float* ori, floa
}
}

CreatureMovementData const& Creature::GetMovementTemplate() const
{
if (CreatureMovementData const* movementOverride = sObjectMgr->GetCreatureMovementOverride(m_spawnId))
return *movementOverride;

return GetCreatureTemplate()->Movement;
}

void Creature::AllLootRemovedFromCorpse()
{
if (loot.loot_type != LOOT_SKINNING && !IsPet() && GetCreatureTemplate()->SkinLootId && hasLootRecipient())
Expand Down Expand Up @@ -2882,12 +2906,6 @@ bool Creature::SetHover(bool enable, bool packetOnly /*= false*/)
if (!packetOnly && !Unit::SetHover(enable))
return false;

//! Unconfirmed for players:
if (enable)
SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_HOVER);
else
RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_HOVER);

if (!movespline->Initialized())
return true;

Expand Down Expand Up @@ -2975,25 +2993,31 @@ void Creature::UpdateMovementFlags()
// Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc)
float ground = GetFloorZ();

bool isInAir = (G3D::fuzzyGt(GetPositionZMinusOffset(), ground + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetPositionZMinusOffset(), ground - GROUND_HEIGHT_TOLERANCE)); // Can be underground too, prevent the falling
bool canHover = CanHover();
bool isInAir = (G3D::fuzzyGt(GetPositionZ(), ground + (canHover ? GetFloatValue(UNIT_FIELD_HOVERHEIGHT) : 0.0f) + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetPositionZ(), ground - GROUND_HEIGHT_TOLERANCE)); // Can be underground too, prevent the falling

if (GetCreatureTemplate()->InhabitType & INHABIT_AIR && isInAir && !IsFalling())
if (GetMovementTemplate().IsFlightAllowed() && isInAir && !IsFalling())
{
if (GetCreatureTemplate()->InhabitType & INHABIT_GROUND)
if (GetMovementTemplate().Flight == CreatureFlightMovementType::CanFly)
SetCanFly(true);
else
SetDisableGravity(true);

if (!HasAuraType(SPELL_AURA_HOVER))
SetHover(false);
}
else
{
SetCanFly(false);
SetDisableGravity(false);
if (IsAlive() && (CanHover() || HasAuraType(SPELL_AURA_HOVER)))
SetHover(true);
}

if (!isInAir)
RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING);

SetSwim(GetCreatureTemplate()->InhabitType & INHABIT_WATER && IsInWater());
SetSwim(GetMovementTemplate().IsSwimAllowed() && IsInWater());
}

void Creature::SetObjectScale(float scale)
Expand Down
9 changes: 6 additions & 3 deletions src/server/game/Entities/Creature/Creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,12 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool IsCivilian() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_CIVILIAN) != 0; }
bool IsTrigger() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER) != 0; }
bool IsGuard() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_GUARD) != 0; }
bool CanWalk() const { return (GetCreatureTemplate()->InhabitType & INHABIT_GROUND) != 0; }
bool CanSwim() const override { return (GetCreatureTemplate()->InhabitType & INHABIT_WATER) != 0 || IsPet(); }
bool CanFly() const override { return (GetCreatureTemplate()->InhabitType & INHABIT_AIR) != 0; }
CreatureMovementData const& GetMovementTemplate() const;
bool CanWalk() const { return GetMovementTemplate().IsGroundAllowed(); }
bool CanSwim() const override { return GetMovementTemplate().IsSwimAllowed() || IsPet(); }
bool CanFly() const override { return GetMovementTemplate().IsFlightAllowed(); }
bool CanHover() const { return GetMovementTemplate().Ground == CreatureGroundMovementType::Hover; }

bool IsDungeonBoss() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_DUNGEON_BOSS) != 0; }
bool IsAffectedByDiminishingReturns() const override { return Unit::IsAffectedByDiminishingReturns() || (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH) != 0; }

Expand Down
37 changes: 36 additions & 1 deletion src/server/game/Entities/Creature/CreatureData.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,41 @@ enum CreatureFlagsExtra : uint32
CREATURE_FLAG_EXTRA_DB_ALLOWED = (0xFFFFFFFF & ~(CREATURE_FLAG_EXTRA_UNUSED | CREATURE_FLAG_EXTRA_DUNGEON_BOSS))
};

enum class CreatureGroundMovementType : uint8
{
None,
Run,
Hover,

Max
};

enum class CreatureFlightMovementType : uint8
{
None,
DisableGravity,
CanFly,

Max
};

struct TC_GAME_API CreatureMovementData
{
CreatureMovementData() : Ground(CreatureGroundMovementType::Run), Flight(CreatureFlightMovementType::None), Swim(true), Rooted(false) { }

CreatureGroundMovementType Ground;
CreatureFlightMovementType Flight;
bool Swim;
bool Rooted;

bool IsGroundAllowed() const { return Ground != CreatureGroundMovementType::None; }
bool IsSwimAllowed() const { return Swim; }
bool IsFlightAllowed() const { return Flight != CreatureFlightMovementType::None; }
bool IsRooted() const { return Rooted; }

std::string ToString() const;
};

static const uint32 CREATURE_REGEN_INTERVAL = 2 * IN_MILLISECONDS;
static const uint32 PET_FOCUS_REGEN_INTERVAL = 4 * IN_MILLISECONDS;
static const uint32 CREATURE_NOPATH_EVADE_TIME = 5 * IN_MILLISECONDS;
Expand Down Expand Up @@ -133,7 +168,7 @@ struct TC_GAME_API CreatureTemplate
uint32 maxgold;
std::string AIName;
uint32 MovementType;
uint32 InhabitType;
CreatureMovementData Movement;
float HoverHeight;
float ModHealth;
float ModMana;
Expand Down
Loading