diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 1788af924..dd5f09297 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2891,6 +2891,101 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } break; } + case SMART_ACTION_FOLLOW_GROUP: + { + if (!e.action.followGroup.followState) + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToCreature()->GetMotionMaster()->MoveIdle(); + + break; + } + + uint8 membCount = targets.size(); + uint8 itr = 1; + float dist = float(e.action.followGroup.dist / 100); + switch (e.action.followGroup.followType) + { + case FOLLOW_TYPE_CIRCLE: + { + float angle = (membCount > 4 ? (M_PI * 2)/membCount : (M_PI / 2)); // 90 degrees is the maximum angle + for (WorldObject* target : targets) + { + if (IsCreature(target)) + { + target->ToCreature()->GetMotionMaster()->MoveFollow(me, dist, angle * itr); + itr++; + } + } + break; + } + case FOLLOW_TYPE_SEMI_CIRCLE_BEHIND: + { + for (WorldObject* target : targets) + { + if (IsCreature(target)) + { + target->ToCreature()->GetMotionMaster()->MoveFollow(me, dist, (M_PI / 2.0f) + (M_PI / membCount) * (itr - 1)); + itr++; + } + } + break; + } + case FOLLOW_TYPE_SEMI_CIRCLE_FRONT: + { + for (WorldObject* target : targets) + { + if (IsCreature(target)) + { + target->ToCreature()->GetMotionMaster()->MoveFollow(me, dist, (M_PI + (M_PI / 2.0f) + (M_PI / membCount) * (itr - 1))); + itr++; + } + } + break; + } + case FOLLOW_TYPE_LINE: + { + for (WorldObject* target : targets) + { + if (IsCreature(target)) + { + target->ToCreature()->GetMotionMaster()->MoveFollow(me, dist * (((itr - 1) / 2) + 1), itr % 2 ? 0.f : M_PI); + itr++; + } + } + break; + } + case FOLLOW_TYPE_COLUMN: + { + for (WorldObject* target : targets) + { + if (IsCreature(target)) + { + target->ToCreature()->GetMotionMaster()->MoveFollow(me, dist * (((itr - 1) / 2) + 1), itr % 2 ? (M_PI / 2) : (M_PI * 1.5f)); + itr++; + } + } + break; + } + case FOLLOW_TYPE_ANGULAR: + { + for (WorldObject* target : targets) + { + if (IsCreature(target)) + { + target->ToCreature()->GetMotionMaster()->MoveFollow(me, dist * (((itr - 1) / 2) + 1), itr % 2 ? M_PI - (M_PI / 4) : M_PI + (M_PI / 4)); + itr++; + } + } + break; + } + default: + break; + } + + break; + } default: LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); break; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 0df5fc909..5142145b8 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -782,6 +782,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_SET_SCALE: return sizeof(SmartAction::setScale); case SMART_ACTION_SUMMON_RADIAL: return sizeof(SmartAction::radialSummon); case SMART_ACTION_PLAY_SPELL_VISUAL: return sizeof(SmartAction::spellVisual); + case SMART_ACTION_FOLLOW_GROUP: return sizeof(SmartAction::followGroup); default: LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); @@ -1971,6 +1972,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_SET_SCALE: case SMART_ACTION_SUMMON_RADIAL: case SMART_ACTION_PLAY_SPELL_VISUAL: + case SMART_ACTION_FOLLOW_GROUP: break; default: LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 87ad374d5..b822ae989 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -742,8 +742,9 @@ enum SMART_ACTION SMART_ACTION_SET_SCALE = 227, // scale SMART_ACTION_SUMMON_RADIAL = 228, // summonEntry, summonDuration, repetitions, startAngle, stepAngle, dist SMART_ACTION_PLAY_SPELL_VISUAL = 229, // visualId, visualIdImpact + SMART_ACTION_FOLLOW_GROUP = 230, // followState, followType, dist - SMART_ACTION_AC_END = 230, // placeholder + SMART_ACTION_AC_END = 231, // placeholder }; enum class SmartActionSummonCreatureFlags @@ -1445,6 +1446,13 @@ struct SmartAction { uint32 visualId; } spellVisual; + + struct + { + uint32 followState; + uint32 followType; + uint32 dist; + } followGroup; //! Note for any new future actions //! All parameters must have type uint32 @@ -1883,6 +1891,16 @@ enum SmartCastFlags SMARTCAST_THREATLIST_NOT_SINGLE = 0x80 //Only cast if the source's threatlist is higher than one. This includes pets (see Skeram's True Fulfillment) }; +enum SmartFollowType +{ + FOLLOW_TYPE_CIRCLE = 1, // 360 degrees around leader, 90 degrees is the maximum angle + FOLLOW_TYPE_SEMI_CIRCLE_BEHIND = 2, // 180 degrees behind leader + FOLLOW_TYPE_SEMI_CIRCLE_FRONT = 3, // 180 degrees in front of leader + FOLLOW_TYPE_LINE = 4, // front -> back -> front -> back + FOLLOW_TYPE_COLUMN = 5, // left -> right -> left -> right + FOLLOW_TYPE_ANGULAR = 6 // geese-like formation 135 and 225 degrees behind leader +}; + // one line in DB is one event struct SmartScriptHolder {