--[[ Jamba - Jafula's Awesome Multi-Boxer Assistant Copyright 2008 - 2018 Michael "Jafula" Miller License: The MIT License ]]-- -- Create the addon using AceAddon-3.0 and embed some libraries. local AJM = LibStub( "AceAddon-3.0" ):NewAddon( "JambaFollow", "JambaModule-1.0", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0" ) -- Get the Jamba Utilities Library. local JambaUtilities = LibStub:GetLibrary( "JambaUtilities-1.0" ) local JambaHelperSettings = LibStub:GetLibrary( "JambaHelperSettings-1.0" ) -- Constants and Locale for this module. AJM.moduleName = "Jamba-Follow" AJM.settingsDatabaseName = "JambaFollowProfileDB" AJM.chatCommand = "jamba-follow" local L = LibStub( "AceLocale-3.0" ):GetLocale( AJM.moduleName ) AJM.parentDisplayName = L["Team"] AJM.moduleDisplayName = L["Follow"] -- Settings - the values to store and their defaults for the settings database. AJM.settings = { profile = { warnWhenFollowBreaks = true, followBrokenMessage = L["Follow Broken!"], autoFollowAfterCombat = false, useAfterCombatDelay = false, afterCombatDelay = "3", strobeFrequencySeconds = "1", strobeFrequencySecondsInCombat = "1", doNotWarnFollowBreakInCombat = false, doNotWarnFollowBreakMembersInCombat = false, doNotWarnFollowStrobing = false, strobePauseInCombat = false, strobePauseIfDrinking = false, strobePauseIfInVehicle = false, strobePauseTag = JambaApi.AllTag(), warningArea = JambaApi.DefaultWarningArea(), followMaster = "", useFollowMaster = false, overrideStrobeTargetWithMaster = false, onlyWarnIfOutOfFollowRange = false, }, } -- Configuration. function AJM:GetConfiguration() local configuration = { name = AJM.moduleDisplayName, handler = AJM, type = 'group', childGroups = "tab", get = "JambaConfigurationGetSetting", set = "JambaConfigurationSetSetting", args = { push = { type = "input", name = L["Push Settings"], desc = L["Push the follow settings to all characters in the team."], usage = "/jamba-follow push", get = false, set = "JambaSendSettings", }, master = { type = "input", name = L["Follow The Master"], desc = L["Follow the current master."], usage = "/jamba-follow master <tag>", get = false, set = "FollowMasterCommand", }, target = { type = "input", name = L["Follow A Target"], desc = L["Follow the target specified."], usage = "/jamba-follow target <target> <tag>", get = false, set = "FollowTargetCommand", }, afterCombat = { type = "input", name = L["Auto Follow After Combat"], desc = L["Automatically follow after combat."], usage = "/jamba-follow aftercombat <on|off> <tag>", }, strobeOn = { type = "input", name = L["Begin Follow Strobing Target."], desc = L["Begin a sequence of follow commands that strobe every second (configurable) a specified target."], usage = "/jamba-follow strobeon <target> <tag>", get = false, set = "FollowStrobeOnCommand", }, strobeOnMe = { type = "input", name = L["Begin Follow Strobing Me."], desc = L["Begin a sequence of follow commands that strobe every second (configurable) this character."], usage = "/jamba-follow strobeonme <tag>", get = false, set = "FollowStrobeOnMeCommand", }, strobeOnLast = { type = "input", name = L["Begin Follow Strobing Last Target."], desc = L["Begin a sequence of follow commands that strobe every second (configurable) the last follow target character."], usage = "/jamba-follow strobeonlast <tag>", get = false, set = "FollowStrobeOnLastCommand", }, strobeOff = { type = "input", name = L["End Follow Strobing."], desc = L["End the strobing of follow commands."], usage = "/jamba-follow strobeoff <tag>", get = false, set = "FollowStrobeOffCommand", }, setmaster = { type = "input", name = L["Master"], desc = L["Set the follow master character."], usage = "/jamba-follow setmaster <name> <tag>", get = false, set = "CommandSetFollowMaster", }, train = { type = "input", name = L["Train"], desc = L["Build a train of followers behind the master."], usage = "/jamba-follow train <tag>", get = false, set = "CommandFollowTrain", }, snw = { type = "input", name = L["Suppress Next Warning"], desc = L["When following, starting a new follow causes the current follow to end, this command before a follow will make sure the follow broken warning is not triggered."], usage = "/jamba-follow snw", get = false, set = "SuppressNextFollowWarningCommand", }, }, } return configuration end local function DebugMessage( ... ) --AJM:Print( ... ) end ------------------------------------------------------------------------------------------------------------- -- Command this module sends. ------------------------------------------------------------------------------------------------------------- AJM.COMMAND_FOLLOW_TARGET = "FollowTarget" AJM.COMMAND_AUTO_FOLLOW_AFTER_COMBAT = "AutoFollowAfterCombat" AJM.COMMAND_FOLLOW_STROBE_ON = "FollowStrobeOn" AJM.COMMAND_FOLLOW_STROBE_OFF = "FollowStrobeOff" AJM.COMMAND_SET_FOLLOW_MASTER = "FollowMaster" AJM.COMMAND_FOLLOW_TRAIN = "FollowTrain" ------------------------------------------------------------------------------------------------------------- -- Messages module sends. ------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------- -- Settings Dialogs. ------------------------------------------------------------------------------------------------------------- local function BuildAndSetTeamList() JambaUtilities:ClearTable( AJM.teamList ) for characterName, order in JambaApi.TeamList() do table.insert( AJM.teamList, characterName ) end AJM.settingsControl.dropdownFollowMaster:SetList( AJM.teamList ) end local function SettingsCreateDisplayOptions( top ) -- Get positions. local checkBoxHeight = JambaHelperSettings:GetCheckBoxHeight() local editBoxHeight = JambaHelperSettings:GetEditBoxHeight() local dropdownHeight = JambaHelperSettings:GetDropdownHeight() local labelHeight = JambaHelperSettings:GetLabelHeight() local left = JambaHelperSettings:LeftOfSettings() local headingHeight = JambaHelperSettings:HeadingHeight() local headingWidth = JambaHelperSettings:HeadingWidth( true ) local horizontalSpacing = JambaHelperSettings:GetHorizontalSpacing() local verticalSpacing = JambaHelperSettings:GetVerticalSpacing() local halfWidth = (headingWidth - horizontalSpacing) / 2 local thirdWidth = (headingWidth - (horizontalSpacing * 2)) / 3 local column2left = left + halfWidth local left2 = left + thirdWidth local left3 = left + (thirdWidth * 2) local movingTop = top JambaHelperSettings:CreateHeading( AJM.settingsControl, L["Follow After Combat"], movingTop, true ) movingTop = movingTop - headingHeight AJM.settingsControl.checkBoxAutoFollowAfterCombat = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, headingWidth, left, movingTop, L["Auto Follow After Combat"], AJM.SettingsToggleAutoFollowAfterCombat ) movingTop = movingTop - checkBoxHeight AJM.settingsControl.checkBoxDelayAutoFollowAfterCombat = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, headingWidth, left, movingTop, L["Delay Follow After Combat (s)"], AJM.SettingsToggleDelayAutoFollowAfterCombat ) movingTop = movingTop - checkBoxHeight AJM.settingsControl.editBoxFollowAfterCombatDelaySeconds = JambaHelperSettings:CreateEditBox( AJM.settingsControl, headingWidth, left, movingTop, L["Seconds To Delay Before Following After Combat"] ) AJM.settingsControl.editBoxFollowAfterCombatDelaySeconds:SetCallback( "OnEnterPressed", AJM.EditBoxChangedFollowAfterCombatDelaySeconds ) movingTop = movingTop - editBoxHeight JambaHelperSettings:CreateHeading( AJM.settingsControl, L["Follow Master"], movingTop, true ) movingTop = movingTop - headingHeight AJM.settingsControl.checkBoxUseFollowMaster = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, headingWidth, left, movingTop, L["Use Different Master For Follow"], AJM.SettingsToggleUseFollowMaster ) movingTop = movingTop - checkBoxHeight AJM.settingsControl.dropdownFollowMaster = JambaHelperSettings:CreateDropdown( AJM.settingsControl, halfWidth, left, movingTop, L["Follow Master"] ) BuildAndSetTeamList() AJM.settingsControl.dropdownFollowMaster:SetCallback( "OnValueChanged", AJM.SettingsSetFollowMaster ) movingTop = movingTop - dropdownHeight - verticalSpacing JambaHelperSettings:CreateHeading( AJM.settingsControl, L["Follow Broken Warning"], movingTop, true ) movingTop = movingTop - headingHeight AJM.settingsControl.checkBoxWarnWhenFollowBreaks = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, headingWidth, left, movingTop, L["Warn If I Stop Following"], AJM.SettingsToggleWarnWhenFollowBreaks ) movingTop = movingTop - checkBoxHeight AJM.settingsControl.checkBoxOnlyWarnIfOutOfFollowRange = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, headingWidth, left, movingTop, L["Only Warn If Outside Follow Range"], AJM.SettingsToggleOnlyWarnIfOutOfFollowRange ) movingTop = movingTop - checkBoxHeight AJM.settingsControl.editBoxFollowBrokenMessage = JambaHelperSettings:CreateEditBox( AJM.settingsControl, headingWidth, left, movingTop, L["Follow Broken Message"] ) AJM.settingsControl.editBoxFollowBrokenMessage:SetCallback( "OnEnterPressed", AJM.EditBoxChangedFollowBrokenMessage ) movingTop = movingTop - editBoxHeight AJM.settingsControl.dropdownWarningArea = JambaHelperSettings:CreateDropdown( AJM.settingsControl, headingWidth, left, movingTop, L["Send Warning Area"] ) AJM.settingsControl.dropdownWarningArea:SetList( JambaApi.MessageAreaList() ) AJM.settingsControl.dropdownWarningArea:SetCallback( "OnValueChanged", AJM.SettingsSetWarningArea ) movingTop = movingTop - dropdownHeight - verticalSpacing AJM.settingsControl.labelDoNotWarnIf = JambaHelperSettings:CreateLabel( AJM.settingsControl, headingWidth, left, movingTop, L["Do Not Warn If"] ) movingTop = movingTop - labelHeight AJM.settingsControl.checkBoxDoNotWarnInCombat = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, halfWidth, left, movingTop, L["In Combat"], AJM.SettingsToggleDoNotWarnInCombat ) AJM.settingsControl.checkBoxDoNotWarnMembersInCombat = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, halfWidth, column2left, movingTop, L["Any Member In Combat"], AJM.SettingsToggleDoNotWarnMembersInCombat ) movingTop = movingTop - checkBoxHeight AJM.settingsControl.checkBoxDoNotWarnFollowStrobing = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, halfWidth, left, movingTop, L["Follow Strobing"], AJM.SettingsToggleDoNotWarnFollowStrobing ) movingTop = movingTop - checkBoxHeight JambaHelperSettings:CreateHeading( AJM.settingsControl, L["Follow Strobing"], movingTop, true ) movingTop = movingTop - headingHeight AJM.settingsControl.labelStrobeHelp = JambaHelperSettings:CreateLabel( AJM.settingsControl, headingWidth, left, movingTop, L["Follow strobing is controlled by /jamba-follow commands."] ) movingTop = movingTop - labelHeight AJM.settingsControl.checkBoxOverrideStrobeTargetWithMaster = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, headingWidth, left, movingTop, L["Always Use Master As The Strobe Target"], AJM.SettingsToggleOverrideStrobeTargetWithMaster ) movingTop = movingTop - checkBoxHeight AJM.settingsControl.labelPauseStrobeHelp = JambaHelperSettings:CreateLabel( AJM.settingsControl, headingWidth, left, movingTop, L["Pause Follow Strobing If"] ) movingTop = movingTop - labelHeight AJM.settingsControl.checkBoxPauseInCombat = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, halfWidth, left, movingTop, L["In Combat"], AJM.SettingsTogglePauseInCombat ) AJM.settingsControl.checkBoxPauseDrinking = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, halfWidth, column2left, --left, movingTop, L["Drinking/Eating"], AJM.SettingsTogglePauseDrinking ) movingTop = movingTop - checkBoxHeight AJM.settingsControl.checkBoxPauseIfInVehicle = JambaHelperSettings:CreateCheckBox( AJM.settingsControl, halfWidth, left, movingTop, L["In A Vehicle"], AJM.SettingsTogglePauseIfInVehicle ) movingTop = movingTop - checkBoxHeight AJM.settingsControl.editBoxFollowStrobePauseTag = JambaHelperSettings:CreateEditBox( AJM.settingsControl, headingWidth, left, movingTop, L["Tag For Pause Follow Strobe"] ) AJM.settingsControl.editBoxFollowStrobePauseTag:SetCallback( "OnEnterPressed", AJM.EditBoxChangedFollowStrobePauseTag ) movingTop = movingTop - editBoxHeight AJM.settingsControl.editBoxFollowStrobeDelaySeconds = JambaHelperSettings:CreateEditBox( AJM.settingsControl, halfWidth, left, movingTop, L["Frequency (s)"] ) AJM.settingsControl.editBoxFollowStrobeDelaySeconds:SetCallback( "OnEnterPressed", AJM.EditBoxChangedFollowStrobeDelaySeconds ) AJM.settingsControl.editBoxFollowStrobeDelaySecondsInCombat = JambaHelperSettings:CreateEditBox( AJM.settingsControl, halfWidth, column2left, movingTop, L["Frequency In Combat (s)"] ) AJM.settingsControl.editBoxFollowStrobeDelaySecondsInCombat:SetCallback( "OnEnterPressed", AJM.EditBoxChangedFollowStrobeDelaySecondsInCombat ) movingTop = movingTop - editBoxHeight return movingTop end function AJM:OnMessageAreasChanged( message ) AJM.settingsControl.dropdownWarningArea:SetList( JambaApi.MessageAreaList() ) end local function SettingsCreate() AJM.settingsControl = {} -- Create the settings panel. JambaHelperSettings:CreateSettings( AJM.settingsControl, AJM.moduleDisplayName, AJM.parentDisplayName, AJM.SettingsPushSettingsClick ) local bottomOfDisplayOptions = SettingsCreateDisplayOptions( JambaHelperSettings:TopOfSettings() ) AJM.settingsControl.widgetSettings.content:SetHeight( -bottomOfDisplayOptions ) -- Help local helpTable = {} JambaHelperSettings:CreateHelp( AJM.settingsControl, helpTable, AJM:GetConfiguration() ) end ------------------------------------------------------------------------------------------------------------- -- Settings Populate. ------------------------------------------------------------------------------------------------------------- function AJM:BeforeJambaProfileChanged() end function AJM:OnJambaProfileChanged() AJM:SettingsRefresh() end function AJM:SettingsRefresh() -- Set values. AJM.settingsControl.checkBoxAutoFollowAfterCombat:SetValue( AJM.db.autoFollowAfterCombat ) AJM.settingsControl.checkBoxDelayAutoFollowAfterCombat:SetValue( AJM.db.useAfterCombatDelay ) AJM.settingsControl.editBoxFollowAfterCombatDelaySeconds:SetText( AJM.db.afterCombatDelay ) AJM.settingsControl.checkBoxWarnWhenFollowBreaks:SetValue( AJM.db.warnWhenFollowBreaks ) AJM.settingsControl.checkBoxOnlyWarnIfOutOfFollowRange:SetValue( AJM.db.onlyWarnIfOutOfFollowRange ) AJM.settingsControl.editBoxFollowBrokenMessage:SetText( AJM.db.followBrokenMessage ) AJM.settingsControl.checkBoxDoNotWarnInCombat:SetValue( AJM.db.doNotWarnFollowBreakInCombat ) AJM.settingsControl.checkBoxDoNotWarnMembersInCombat:SetValue( AJM.db.doNotWarnFollowBreakMembersInCombat ) AJM.settingsControl.checkBoxDoNotWarnFollowStrobing:SetValue( AJM.db.doNotWarnFollowStrobing ) AJM.settingsControl.checkBoxOverrideStrobeTargetWithMaster:SetValue( AJM.db.overrideStrobeTargetWithMaster ) AJM.settingsControl.checkBoxPauseInCombat:SetValue( AJM.db.strobePauseInCombat ) AJM.settingsControl.checkBoxPauseDrinking:SetValue( AJM.db.strobePauseIfDrinking ) AJM.settingsControl.checkBoxPauseIfInVehicle:SetValue( AJM.db.strobePauseIfInVehicle ) AJM.settingsControl.editBoxFollowStrobePauseTag:SetText( AJM.db.strobePauseTag ) AJM.settingsControl.editBoxFollowStrobeDelaySeconds:SetText( AJM.db.strobeFrequencySeconds ) AJM.settingsControl.editBoxFollowStrobeDelaySecondsInCombat:SetText( AJM.db.strobeFrequencySecondsInCombat ) AJM.settingsControl.dropdownWarningArea:SetValue( AJM.db.warningArea ) AJM.settingsControl.dropdownFollowMaster:SetValue( AJM.db.followMaster ) AJM.settingsControl.checkBoxUseFollowMaster:SetValue( AJM.db.useFollowMaster ) -- Set state. AJM.settingsControl.checkBoxDelayAutoFollowAfterCombat:SetDisabled( not AJM.db.autoFollowAfterCombat ) AJM.settingsControl.editBoxFollowAfterCombatDelaySeconds:SetDisabled( not AJM.db.autoFollowAfterCombat or not AJM.db.useAfterCombatDelay ) AJM.settingsControl.dropdownFollowMaster:SetDisabled( not AJM.db.useFollowMaster ) AJM.settingsControl.editBoxFollowBrokenMessage:SetDisabled( not AJM.db.warnWhenFollowBreaks ) AJM.settingsControl.checkBoxOnlyWarnIfOutOfFollowRange:SetDisabled( not AJM.db.warnWhenFollowBreaks ) AJM.settingsControl.checkBoxDoNotWarnInCombat:SetDisabled( not AJM.db.warnWhenFollowBreaks ) AJM.settingsControl.checkBoxDoNotWarnMembersInCombat:SetDisabled( not AJM.db.warnWhenFollowBreaks ) AJM.settingsControl.checkBoxDoNotWarnFollowStrobing:SetDisabled( not AJM.db.warnWhenFollowBreaks ) AJM.settingsControl.dropdownWarningArea:SetDisabled( not AJM.db.warnWhenFollowBreaks ) AJM.settingsControl.labelDoNotWarnIf:SetDisabled( not AJM.db.warnWhenFollowBreaks ) end function AJM:SettingsPushSettingsClick( event ) AJM:JambaSendSettings() end function AJM:SettingsToggleUseFollowMaster( event, checked ) AJM.db.useFollowMaster = checked AJM:SettingsRefresh() end function AJM:SettingsToggleAutoFollowAfterCombat( event, checked ) AJM.db.autoFollowAfterCombat = checked AJM:SettingsRefresh() end function AJM:SettingsToggleDelayAutoFollowAfterCombat( event, checked ) AJM.db.useAfterCombatDelay = checked AJM:SettingsRefresh() end function AJM:EditBoxChangedFollowAfterCombatDelaySeconds( event, text ) AJM.db.afterCombatDelay = tonumber( text ) AJM:SettingsRefresh() end function AJM:SettingsToggleWarnWhenFollowBreaks( event, checked ) AJM.db.warnWhenFollowBreaks = checked AJM:SettingsRefresh() end function AJM:SettingsToggleOnlyWarnIfOutOfFollowRange( event, checked ) AJM.db.onlyWarnIfOutOfFollowRange = checked AJM:SettingsRefresh() end function AJM:EditBoxChangedFollowBrokenMessage( event, text ) AJM.db.followBrokenMessage = text AJM:SettingsRefresh() end function AJM:SettingsToggleDoNotWarnInCombat( event, checked ) AJM.db.doNotWarnFollowBreakInCombat = checked AJM:SettingsRefresh() end function AJM:SettingsToggleDoNotWarnMembersInCombat( event, checked ) AJM.db.doNotWarnFollowBreakMembersInCombat = checked AJM:SettingsRefresh() end function AJM:SettingsToggleDoNotWarnFollowStrobing( event, checked ) AJM.db.doNotWarnFollowStrobing = checked AJM:SettingsRefresh() end function AJM:SettingsToggleOverrideStrobeTargetWithMaster( event, checked ) AJM.db.overrideStrobeTargetWithMaster = checked AJM:SettingsRefresh() end function AJM:SettingsTogglePauseInCombat( event, checked ) AJM.db.strobePauseInCombat = checked AJM:SettingsRefresh() end function AJM:SettingsTogglePauseDrinking( event, checked ) AJM.db.strobePauseIfDrinking = checked AJM:SettingsRefresh() end function AJM:SettingsTogglePauseIfInVehicle( event, checked ) AJM.db.strobePauseIfInVehicle = checked AJM:SettingsRefresh() end function AJM:EditBoxChangedFollowStrobePauseTag( event, text ) AJM.db.strobePauseTag = text AJM:SettingsRefresh() end function AJM:EditBoxChangedFollowStrobeDelaySeconds( event, text ) AJM.db.strobeFrequencySeconds = text AJM:SettingsRefresh() end function AJM:EditBoxChangedFollowStrobeDelaySecondsInCombat( event, text ) AJM.db.strobeFrequencySecondsInCombat = text AJM:SettingsRefresh() end function AJM:SettingsSetWarningArea( event, value ) AJM.db.warningArea = value AJM:SettingsRefresh() end function AJM:SettingsSetFollowMaster( event, value ) AJM.db.followMaster = value AJM:SettingsRefresh() end ------------------------------------------------------------------------------------------------------------- -- Addon initialization, enabling and disabling. ------------------------------------------------------------------------------------------------------------- -- Initialise the module. function AJM:OnInitialize() AJM.jambaExternalNoWarnNextBreak = false AJM.jambaExternalNoWarnNextSecondBreak = false -- An empty team list. AJM.teamList = {} -- Create the settings control. SettingsCreate() -- Initialise the JambaModule part of this module. AJM:JambaModuleInitialize( AJM.settingsControl.widgetSettings.frame ) -- Populate the settings. AJM:SettingsRefresh() -- Current follow target. AJM.currentFollowTarget = JambaApi.GetMasterName() AJM:UpdateFollowTargetToFollowMaster() -- Set to true if jamba initiated a follow. AJM.jambaSetFollowTarget = false -- Following flag. AJM.isFollowing = false -- Strobing follow. AJM.currentFollowStrobeTarget = JambaApi.GetMasterName() AJM.followingStrobing = false AJM.followStrobeTimer = nil AJM.followingStrobingPaused = false -- Not in combat flag. AJM.outOfCombat = true -- Character on taxi flag. AJM.characterIsOnTaxi = false end -- Called when the addon is enabled. function AJM:OnEnable() -- WoW events. AJM:RegisterEvent( "AUTOFOLLOW_BEGIN" ) AJM:RegisterEvent( "AUTOFOLLOW_END" ) AJM:RegisterEvent( "PLAYER_REGEN_DISABLED" ) AJM:RegisterEvent( "PLAYER_REGEN_ENABLED" ) AJM:RegisterEvent( "PLAYER_CONTROL_GAINED" ) AJM:RegisterEvent( "UNIT_ENTERING_VEHICLE" ) AJM:RegisterEvent( "UNIT_EXITING_VEHICLE" ) -- Jamba events. if JambaApi.Taxi ~= nil then AJM:RegisterMessage( JambaApi.Taxi.MESSAGE_TAXI_TAKEN, "CharacterOnTaxi" ) end AJM:RegisterMessage( JambaApi.MESSAGE_TEAM_MASTER_CHANGED, "OnMasterChanged" ) AJM:RegisterMessage( JambaApi.MESSAGE_TEAM_CHARACTER_ADDED, "OnTeamChanged" ) AJM:RegisterMessage( JambaApi.MESSAGE_TEAM_CHARACTER_REMOVED, "OnTeamChanged" ) AJM:RegisterMessage( JambaApi.MESSAGE_MESSAGE_AREAS_CHANGED, "OnMessageAreasChanged" ) end -- Called when the addon is disabled. function AJM:OnDisable() end -- Settings received. function AJM:JambaOnSettingsReceived( characterName, settings ) if characterName ~= AJM.characterName then -- Update the settings. AJM.db.warnWhenFollowBreaks = settings.warnWhenFollowBreaks AJM.db.followBrokenMessage = settings.followBrokenMessage AJM.db.autoFollowAfterCombat = settings.autoFollowAfterCombat AJM.db.strobeFrequencySeconds = settings.strobeFrequencySeconds AJM.db.strobeFrequencySecondsInCombat = settings.strobeFrequencySecondsInCombat AJM.db.doNotWarnFollowBreakInCombat = settings.doNotWarnFollowBreakInCombat AJM.db.doNotWarnFollowBreakMembersInCombat = settings.doNotWarnFollowBreakMembersInCombat AJM.db.strobePauseInCombat = settings.strobePauseInCombat AJM.db.strobePauseIfInVehicle = settings.strobePauseIfInVehicle AJM.db.strobePauseIfDrinking = settings.strobePauseIfDrinking AJM.db.strobePauseTag = settings.strobePauseTag AJM.db.doNotWarnFollowStrobing = settings.doNotWarnFollowStrobing AJM.db.warningArea = settings.warningArea AJM.db.followMaster = settings.followMaster AJM.db.useFollowMaster = settings.useFollowMaster AJM.db.overrideStrobeTargetWithMaster = settings.overrideStrobeTargetWithMaster AJM.db.useAfterCombatDelay = settings.useAfterCombatDelay AJM.db.afterCombatDelay = settings.afterCombatDelay AJM.db.onlyWarnIfOutOfFollowRange = settings.onlyWarnIfOutOfFollowRange -- Refresh the settings. AJM:SettingsRefresh() -- Tell the player. AJM:Print( L["Settings received from A."]( characterName ) ) -- Tell the team? --AJM:JambaSendMessageToTeam( AJM.db.messageArea, L["Settings received from A."]( characterName ), false ) end end ------------------------------------------------------------------------------------------------------------- -- JambaFollow functionality. ------------------------------------------------------------------------------------------------------------- function AJM:UNIT_ENTERING_VEHICLE() if AJM.db.strobePauseIfInVehicle == true then if AJM.followingStrobing == true then if AJM.followingStrobingPaused == false then AJM:FollowStrobingPause( true ) end end end end function AJM:UNIT_EXITING_VEHICLE() if AJM.db.strobePauseIfInVehicle == true then if AJM.followingStrobing == true then if AJM.followingStrobingPaused == true then AJM:FollowStrobingPause( false ) end end end end function AJM:AreTeamMembersInCombat() local inCombat = false for index, characterName in JambaApi.TeamListOrdered() do -- Is the team member online? if JambaApi.GetCharacterOnlineStatus( characterName ) == true then -- Yes, is the character in combat? if UnitAffectingCombat( Ambiguate( characterName, "none" ) ) then inCombat = true break end end end return inCombat end function AJM:IsFollowingStrobing() return AJM.followingStrobing end function AJM:IsFollowingStrobingPaused() return AJM.followingStrobingPaused end function AJM:CharacterOnTaxi() AJM:SetNoFollowBrokenWarningNextBreak() if AJM:IsFollowingStrobing() == true then if AJM:IsFollowingStrobingPaused() == false then AJM:FollowStrobingPause( true ) AJM.characterIsOnTaxi = true end end end function AJM:PLAYER_CONTROL_GAINED() if AJM.characterIsOnTaxi == true then AJM.characterIsOnTaxi = false if AJM:IsFollowingStrobing() == true then if AJM:IsFollowingStrobingPaused() == true then AJM:FollowStrobingPause( false ) end end end end function AJM:SuppressNextFollowWarningCommand( info, parameters ) AJM:SuppressNextFollowWarning() end function AJM:SuppressNextFollowWarning() -- Events are fired as follows for a /follow command. if AJM.isFollowing == true then AJM:SetNoFollowBrokenWarningNextBreak() AJM:SetNoFollowBrokenWarningNextSecondBreak() else AJM:SetNoFollowBrokenWarningNextBreak() end end function AJM:SetNoFollowBrokenWarningNextBreak() AJM.jambaExternalNoWarnNextBreak = true end function AJM:SetNoFollowBrokenWarningNextSecondBreak() AJM.jambaExternalNoWarnNextSecondBreak = true end function AJM:AUTOFOLLOW_BEGIN( event, target, ... ) AJM.currentFollowTarget = target AJM.isFollowing = true end function AJM:AUTOFOLLOW_END( event, ... ) AJM.isFollowing = false AJM:ScheduleTimer( "AutoFollowEndUpdate", 0.5 ) end -- checks the follow system Msg, is there under 1 always 1 unless it fadeing. function AJM:AutoFollowEndUpdate() local alpha = AutoFollowStatus:GetAlpha() --AJM:Print("updatetest", test) if alpha < 1 then --AJM:Print("canSend") AJM:AutoFollowEndSend() end end function AJM:AutoFollowEndSend() -- If warn if auto follow breaks is on... local canWarn = false if AJM.db.warnWhenFollowBreaks == true then if AJM.jambaSetFollowTarget == false then canWarn = true end end -- Do not warn if on Taxi if UnitOnTaxi("player") == true then --AJM:Print("taxi") canWarn = false end --Do not warn if in combat? if AJM.db.doNotWarnFollowBreakInCombat == true and AJM.outOfCombat == false then --AJM:Print("Do Not warn in comabt") canWarn = false end --Do not warn if a passenger in a vehicle. if UnitInVehicle("Player") == true and UnitControllingVehicle("player") == false then --AJM:Print("UnitInVehicle") canWarn = false end -- Do not warn if any other members in combat? if AJM.db.doNotWarnFollowBreakMembersInCombat == true and AJM:AreTeamMembersInCombat() == true or UnitAffectingCombat("player") == true then --AJM:Print("doNotWarnFollowBreakMembersInCombat") canWarn = false end -- Don't warn about follow breaking if follow strobing is on or paused. if AJM.db.doNotWarnFollowStrobing == true then if AJM.followingStrobing == true or AJM.followStrobingPaused == true then --AJM:Print("FollowStrobing") canWarn = false end end -- Check to see if range warning is in effect. This olny works in a party it seems!! if AJM.db.onlyWarnIfOutOfFollowRange == true then if CheckInteractDistance( AJM.currentFollowTarget, 4 ) then --AJM:Print("CheckInteractDistance") canWarn = false end end -- If allowed to warn, then warn. if canWarn == true then AJM:JambaSendMessageToTeam( AJM.db.warningArea, AJM.db.followBrokenMessage, false ) end AJM.jambaSetFollowTarget = false end function AJM:PLAYER_REGEN_ENABLED() AJM.outOfCombat = true -- Is auto follow after combat on? if AJM.db.autoFollowAfterCombat == true then if AJM.db.useAfterCombatDelay == false then AJM:FollowTarget( AJM.currentFollowTarget ) else AJM:ScheduleTimer( "FollowTarget", tonumber( AJM.db.afterCombatDelay ), AJM.currentFollowTarget ) end end -- Is follow strobing on? if AJM:IsFollowingStrobing() == true then -- Pause follow strobing while in combat? if AJM.db.strobePauseInCombat == true then -- Un-pause follow strobing. AJM:FollowStrobingPause( false ) else -- Not pausing, so check strobe rate. if AJM.db.strobeFrequencySeconds ~= AJM.db.strobeFrequencySecondsInCombat then AJM:FollowStrobeOn( AJM.currentFollowStrobeTarget ) end end end end function AJM:PLAYER_REGEN_DISABLED() AJM.outOfCombat = false -- Is follow strobing on? if AJM:IsFollowingStrobing() == true then -- Pause follow strobing while in combat? if AJM.db.strobePauseInCombat == true then -- Pause follow strobing. AJM:FollowStrobingPause( true ) else -- Not pausing, so check strobe rate. if AJM.db.strobeFrequencySeconds ~= AJM.db.strobeFrequencySecondsInCombat then AJM:FollowStrobeOn( AJM.currentFollowStrobeTarget ) end end end end function AJM:AutoFollowAfterCombatCommand( info, parameters ) -- Get the on/off state and the tag of who to send to. local state, tag = strsplit( " ", parameters ) if tag ~= nil and tag:trim() ~= "" then AJM:AutoFollowAfterCombatSendCommand( state, tag ) else AJM:DoToggleAutoFollowAfterCombat( state ) end end function AJM:AutoFollowAfterCombatSendCommand( state, tag ) AJM:JambaSendCommandToTeam( AJM.COMMAND_AUTO_FOLLOW_AFTER_COMBAT, state, tag ) end function AJM:AutoFollowAfterCombatReceiveCommand( state, tag ) -- If this character responds to this tag... if JambaApi.DoesCharacterHaveTag( AJM.characterName, tag ) then AJM:DoToggleAutoFollowAfterCombat( state ) end end function AJM:DoToggleAutoFollowAfterCombat( state ) -- Translate the on/off state from string to boolean/nil. local setToOn = JambaUtilities:GetOnOrOffFromCommand( state, L["on"], L["off"] ) -- If nil, then assume false. if setToOn == nil then setToOn = false end -- Then set the flag appropriately. AJM:SettingsToggleAutoFollowAfterCombat( nil, setToOn ) -- Refresh the settings. AJM:SettingsRefresh() end function AJM:GetCurrentFollowTarget() return AJM.currentFollowTarget end function AJM:GetCurrentFollowStrobeTarget() return AJM.currentFollowStrobeTarget end function AJM:UpdateFollowTargetToFollowMaster() if AJM.db.useFollowMaster == true then AJM.currentFollowTarget = JambaApi.GetMasterName() if AJM.db.followMaster ~= "" then if JambaApi.GetCharacterOnlineStatus( AJM.db.followMaster ) == true then AJM.currentFollowTarget = AJM.db.followMaster end end end end function AJM:OnMasterChanged() if AJM.db.autoFollowAfterCombat == true then AJM.currentFollowTarget = JambaApi.GetMasterName() AJM:UpdateFollowTargetToFollowMaster() end if AJM.followingStrobing == true then if AJM.db.overrideStrobeTargetWithMaster == true then AJM.currentFollowStrobeTarget = JambaApi.GetMasterName() AJM:FollowStrobeOn( AJM.currentFollowStrobeTarget ) end end end function AJM:OnTeamChanged() BuildAndSetTeamList() end function AJM:CommandFollowTrain( info, parameters ) local tag = parameters if tag ~= nil and tag:trim() ~= "" then AJM:JambaSendCommandToTeam( AJM.COMMAND_FOLLOW_TRAIN, tag ) end end function AJM:ReceiveCommandFollowTrain( tag ) if JambaApi.DoesCharacterHaveTag( AJM.characterName, tag ) then local characterInFront = nil for index, character in JambaApi.TeamListOrderedOnline() do if character == AJM.characterName then if characterInFront ~= nil then --FollowUnit( characterInFront ) FollowUnit( Ambiguate( characterInFront, "none" ) ) end return else if JambaApi.DoesCharacterHaveTag( character, tag ) then characterInFront = character end end end end end function AJM:CommandSetFollowMaster( info, parameters ) local target, tag = strsplit( " ", parameters ) if tag ~= nil and tag:trim() ~= "" then AJM:JambaSendCommandToTeam( AJM.COMMAND_SET_FOLLOW_MASTER, target, tag ) else AJM.db.followMaster = target AJM:UpdateFollowTargetToFollowMaster() end end function AJM:ReceiveCommandSetFollowMaster( target, tag ) if JambaPrivate.Tag.DoesCharacterHaveTag( AJM.characterName, tag ) then AJM.db.followMaster = target AJM:UpdateFollowTargetToFollowMaster() end end function AJM:FollowMasterCommand( info, parameters ) -- The only parameter for this command is tag. If there is a tag, send the command to all -- the members, otherwise just this character. local tag = parameters -- Set the current follow target to the master. AJM.currentFollowTarget = JambaApi.GetMasterName() AJM:UpdateFollowTargetToFollowMaster() if tag ~= nil and tag:trim() ~= "" then AJM:FollowTargetSendCommand( AJM.currentFollowTarget, tag ) else AJM:SuppressNextFollowWarning() AJM:FollowTarget( AJM.currentFollowTarget ) end end function AJM:FollowTargetCommand( info, parameters ) local target, tag = strsplit( " ", parameters ) if tag ~= nil and tag:trim() ~= "" then AJM:FollowTargetSendCommand( target, tag ) else AJM.currentFollowTarget = target AJM:SuppressNextFollowWarning() AJM:FollowTarget( AJM.currentFollowTarget ) end end function AJM:FollowTargetSendCommand( target, tag ) AJM:JambaSendCommandToTeam( AJM.COMMAND_FOLLOW_TARGET, target, tag ) end function AJM:FollowTargetReceiveCommand( target, tag ) -- If this character responds to this tag... if JambaApi.DoesCharacterHaveTag( AJM.characterName, tag ) then -- Then follow the target specified. AJM.currentFollowTarget = target AJM:SuppressNextFollowWarning() AJM:FollowTarget( AJM.currentFollowTarget ) end end function AJM:FollowStrobeOnMeCommand( info, parameters ) local tag = parameters if tag ~= nil and tag:trim() ~= "" then AJM:FollowStrobeOnSendCommand( AJM.characterName, tag ) else AJM:FollowStrobeOn( AJM.characterName ) end end function AJM:FollowStrobeOnLastCommand( info, parameters ) local tag = parameters if tag ~= nil and tag:trim() ~= "" then AJM:FollowStrobeOnSendCommand( AJM.currentFollowStrobeTarget, tag ) else AJM:FollowStrobeOn( AJM.currentFollowStrobeTarget ) end end function AJM:FollowStrobeOnCommand( info, parameters ) local target, tag = strsplit( " ", parameters ) if tag ~= nil and tag:trim() ~= "" then AJM:FollowStrobeOnSendCommand( target, tag ) else AJM:FollowStrobeOn( target ) end end function AJM:FollowStrobeOnSendCommand( target, tag ) AJM:JambaSendCommandToTeam( AJM.COMMAND_FOLLOW_STROBE_ON, target, tag ) end function AJM:FollowStrobeOnReceiveCommand( target, tag ) -- If this character responds to this tag... if JambaApi.DoesCharacterHaveTag( AJM.characterName, tag ) then -- Then follow the target specified - strobing. AJM:FollowStrobeOn( target ) end end function AJM:FollowStrobeOffCommand( info, parameters ) local tag = parameters if tag ~= nil and tag:trim() ~= "" then AJM:FollowStrobeOffSendCommand( tag ) else AJM:FollowStrobeOff() end end function AJM:FollowStrobeOffSendCommand( tag ) AJM:JambaSendCommandToTeam( AJM.COMMAND_FOLLOW_STROBE_OFF, tag ) end function AJM:FollowStrobeOffReceiveCommand( tag ) -- If this character responds to this tag... if JambaApi.DoesCharacterHaveTag( AJM.characterName, tag ) then -- Then follow the target specified - turn off strobing. AJM:FollowStrobeOff() end end function AJM:FollowTarget( target ) -- Attempting to follow self? Note: if target ever is party1, etc, then this will not catch the same character. if target == AJM.characterName then return end local canFollowTarget = true -- If follow strobing and pause strobing if drinking then... if AJM.followingStrobing == true and AJM.db.strobePauseIfDrinking == true then -- And the character has the pause tag... if JambaApi.DoesCharacterHaveTag( AJM.characterName, AJM.db.strobePauseTag ) == true then -- Check player for drinking buff. if JambaUtilities:DoesThisCharacterHaveBuff( L["Drink"] ) == true then -- Have drinking buff, do not allow follow. canFollowTarget = false end if JambaUtilities:DoesThisCharacterHaveBuff( L["Food"] ) == true then -- Have eating buff, do not allow follow. canFollowTarget = false end if JambaUtilities:DoesThisCharacterHaveBuff( L["Refreshment"] ) == true then -- Eating Mage food Yum Yum Yum. canFollowTarget = false end end end -- If follow strobing and strobing paused. if AJM.followingStrobing == true and AJM.followingStrobingPaused == true then -- Follow strobing is paused, do not follow target. canFollowTarget = false end -- If allowed to follow the target, then... if canFollowTarget == true then -- Set the jamba set this flag toggle, so not to complain about follow broken after combat. --if (AJM.db.autoFollowAfterCombat == true) or (AJM.followingStrobing == true) then if AJM.followingStrobing == true then AJM.jambaSetFollowTarget = true end --AJM:Print( target ) -- Follow unit only works when in a party or raid for resolving against player names. FollowUnit( Ambiguate( target, "none" ) ) end end function AJM:FollowStrobeOn( target ) AJM.currentFollowStrobeTarget = target -- Do the initial follow. AJM:FollowTarget( AJM.currentFollowStrobeTarget ) -- If the timer is running, then if AJM.followingStrobing == true then AJM:FollowStrobeOff() end -- Set up a timer to do another follow command. AJM.followingStrobing = true local seconds = AJM.db.strobeFrequencySeconds if InCombatLockdown() then seconds = AJM.db.strobeFrequencySecondsInCombat end AJM.followStrobeTimer = AJM:ScheduleRepeatingTimer( "FollowTarget", tonumber( seconds ), AJM.currentFollowStrobeTarget ) end function AJM:FollowStrobeOff() -- Stop the timer from doing another follow command. if AJM.followingStrobing == true then AJM.followingStrobing = false AJM:CancelTimer( AJM.followStrobeTimer ) end end function AJM:FollowStrobingPause( pause ) if pause == true then -- Is follow strobing on? if AJM.followingStrobing == true then -- Yes, turn it off, if this character has a tag that matches the pause follow strobe tag. if JambaApi.DoesCharacterHaveTag( AJM.characterName, AJM.db.strobePauseTag ) == true then AJM.followingStrobingPaused = true end end else -- Is follow strobing paused? if AJM.followingStrobingPaused == true then -- Yes, turn it on, if this character has a tag that matches the pause follow strobe tag. if JambaApi.DoesCharacterHaveTag( AJM.characterName, AJM.db.strobePauseTag ) == true then AJM.followingStrobingPaused = false end end end end -- A Jamba command has been recieved. function AJM:JambaOnCommandReceived( characterName, commandName, ... ) if commandName == AJM.COMMAND_FOLLOW_TARGET then AJM:FollowTargetReceiveCommand( ... ) end if commandName == AJM.COMMAND_AUTO_FOLLOW_AFTER_COMBAT then AJM:AutoFollowAfterCombatReceiveCommand( ... ) end if commandName == AJM.COMMAND_FOLLOW_STROBE_ON then AJM:FollowStrobeOnReceiveCommand( ... ) end if commandName == AJM.COMMAND_FOLLOW_STROBE_OFF then AJM:FollowStrobeOffReceiveCommand( ... ) end if commandName == AJM.COMMAND_SET_FOLLOW_MASTER then AJM:ReceiveCommandSetFollowMaster( ... ) end if commandName == AJM.COMMAND_FOLLOW_TRAIN then AJM:ReceiveCommandFollowTrain( ... ) end end JambaApi.Follow = {} JambaApi.Follow.IsFollowingStrobing = AJM.IsFollowingStrobing JambaApi.Follow.IsFollowingStrobingPaused = AJM.IsFollowingStrobingPaused JambaApi.Follow.GetCurrentFollowTarget = AJM.GetCurrentFollowTarget JambaApi.Follow.GetCurrentFollowStrobeTarget = AJM.GetCurrentFollowStrobeTarget JambaApi.Follow.SuppressNextFollowWarning = AJM.SuppressNextFollowWarning