diff --git a/Encounters/BossPrototype.lua b/Encounters/BossPrototype.lua index dbb266f..6893442 100644 --- a/Encounters/BossPrototype.lua +++ b/Encounters/BossPrototype.lua @@ -93,10 +93,10 @@ end function EncounterPrototype:RegisterDatachronEvent(sSearchMessage, sMatch, fHandler) assert(type(sSearchMessage) == "string") assert(type(fHandler) == "function") - assert(sMatch == "MATCH" or sMatch == "FIND") + assert(sMatch == "MATCH" or sMatch == "FIND" or sMatch == "EQUAL") sSearchMessage = self.L[sSearchMessage] self.tDatachronEvents[sSearchMessage] = self.tDatachronEvents[sSearchMessage] or {} - table.insert(self.tDatachronEvents[sSearchMessage], {fHandler = fHandler, bMatch = sMatch == "MATCH"}) + table.insert(self.tDatachronEvents[sSearchMessage], {fHandler = fHandler, sMatch = sMatch }) end -- Register events to a single unit @@ -131,12 +131,13 @@ end -- @param sEnglishText English text to search in language dictionnary. -- @param nDuration Timer duration. -- @param bEmphasize Timer count down requested (nil take the default one). +-- @param sColor Color for the timer bar (nil take the default one).. -- @param fHandler function to call on timeout -- @param tClass Class used by callback action on timeout -- @param tData Data forwarded by callback action on timeout -- -- Note: If the English translation is not found, the current string will be used like that. -function EncounterPrototype:AddTimerBar(sKey, sEnglishText, nDuration, bEmphasize, fHandler, tClass, tData) +function EncounterPrototype:AddTimerBar(sKey, sEnglishText, nDuration, bEmphasize, sColor, fHandler, tClass, tData) local tOptions = nil local sLocalText = self.L[sEnglishText] if self.tDefaultTimerBarsOptions[sKey] then @@ -147,6 +148,10 @@ function EncounterPrototype:AddTimerBar(sKey, sEnglishText, nDuration, bEmphasiz if bEmphasize ~= nil then tOptions["bEmphasize"] = bEmphasize and true end + if sColor ~= nil then + assert(type(sColor) == "string") + tOptions["sColor"] = sColor + end local tCallback = nil if type(fHandler) == "function" then tCallback = { diff --git a/Encounters/RMT/Engineers.lua b/Encounters/RMT/Engineers.lua index d2a2299..fb10812 100644 --- a/Encounters/RMT/Engineers.lua +++ b/Encounters/RMT/Engineers.lua @@ -27,49 +27,229 @@ mod:RegisterEnglishLocale({ ["Cooling Turbine"] = "Cooling Turbine", ["Spark Plug"] = "Spark Plug", ["Lubricant Nozzle"] = "Lubricant Nozzle", - ["Head Engineer Orvulgh"] = "Head Engineer Orvulgh", - ["Chief Engineer Wilbargh"] = "Chief Engineer Wilbargh", + ["Head Engineer Orvulgh"] = "Head Engineer Orvulgh", -- Engineer + ["Chief Engineer Wilbargh"] = "Chief Engineer Wilbargh", -- Warrior ["Air Current"] = "Air Current", ["Friendly Invisible Unit for Fields"] = "Friendly Invisible Unit for Fields", ["Hostile Invisible Unit for Fields (0 hit radius)"] = "Hostile Invisible Unit for Fields (0 hit radius)", - -- Cast names + ["Discharged Plasma"] = "Discharged Plasma", -- Fire Orb + -- Cast names. ["Liquidate"] = "Liquidate", - -- Datachron - ["Hornious Eversong suffers from Electroshock"] = "", + ["Electroshock"] = "Electroshock", + -- Datachron. + ["([^%s]+%s[^%s]+) suffers from Electroshock"] = "([^%s]+%s[^%s]+) suffers from Electroshock", + -- Messages. + ["electroshock.next"] = "Next Electroshock in", + ["liquidate.next"] = "Next Liquidate in", + ["liquidate.stack"] = "Stack", + ["electroshock.swap.other"] = "%s SWAP TO WARRIOR", + ["electroshock.swap.you"] = "YOU SWAP TO WARRIOR", + ["fire_orb.next"] = "Next Fire Orb in", + ["fire_orb.you"] = "FIRE ORB ON YOU", + ["fire_orb.spawned"] = "Fire Orb spawned", + ["fire_orb.pop.timer"] = "Fire Orb is safe to pop in", + ["fire_orb.pop.msg"] = "Pop the Fire Orb!", + ["core.health.high.warning"] = "%s pillar at 85%%!", + ["core.health.low.warning"] = "%s pillar at 15%%!" }) ---------------------------------------------------------------------------------------------------- -- Constants. ---------------------------------------------------------------------------------------------------- +local DEBUFF_ION_CLASH = 84051 +local DEBUFF_UNSTABLE_VOLTAGE = 84045 +local DEBUFF_ELECTROSHOCK_VULNERABILITY = 83798 +local DEBUFF_DIMINISHING_FUSION_REACTION = 87214 +local BUFF_INSULATION = 83987 +-- Timers +local FIRST_ELECTROSHOCK_TIMER = 11 +local ELECTROSHOCK_TIMER = 18 +local JUMP_ELECTROSHOCK_TIMER = 12 +local NEXT_FIRE_ORB_TIMER = 24 +local FIRE_ORB_SAFE_TIMER = 14 + +local FIRST_LIQUIDATE_TIMER = 12 +local LIQUIDATE_TIMER = 22 + +local FUSION_CORE = 1 +local COOLING_TURBINE = 2 +local SPARK_PLUG = 3 +local LUBRICANT_NOZZLE = 4 +local CORE_NAMES = { + ["Fusion Core"] = FUSION_CORE, + ["Cooling Turbine"] = COOLING_TURBINE, + ["Spark Plug"] = SPARK_PLUG, + ["Lubricant Nozzle"] = LUBRICANT_NOZZLE +} +--shorten these +local CORE_NICKNAMES = { + [FUSION_CORE] = "Fusion Core", + [COOLING_TURBINE] = "Cooling Turbine", + [SPARK_PLUG] = "Spark Plug", + [LUBRICANT_NOZZLE] = "Lubricant Nozzle" +} + +local WARRIOR = 1 +local ENGINEER = 2 +local ENGINEER_NAMES = { + ["Chief Engineer Wilbargh"] = WARRIOR, + ["Head Engineer Orvulgh"] = ENGINEER, +} +local ENGINEER_START_LOCATION = { + [WARRIOR] = SPARK_PLUG, + [ENGINEER] = COOLING_TURBINE, +} +local ENGINEER_NICKNAMES = { + [WARRIOR] = "Warrior", + [ENGINEER] = "Engineer", +} ---------------------------------------------------------------------------------------------------- --- Locals. +-- Functions. ---------------------------------------------------------------------------------------------------- local GetUnitById = GameLib.GetUnitById -local GetPlayerUnit = GameLib.GetPlayerUnit local GetGameTime = GameLib.GetGameTime ---------------------------------------------------------------------------------------------------- +-- Locals. +---------------------------------------------------------------------------------------------------- +--Do not reset coreUnits since they don't get destroyed after each pull +local coreUnits = {} +local engineerUnits +local player +local orbUnits + +local fireOrbTargetTestTimer = ApolloTimer.Create(1, false, "RegisterOrbTarget", mod) +---------------------------------------------------------------------------------------------------- +-- Settings. +---------------------------------------------------------------------------------------------------- +mod:RegisterDefaultSetting("BarsCoreHealth", false) +mod:RegisterDefaultSetting("LineElectroshock") +mod:RegisterDefaultSetting("SoundLiquidate") +mod:RegisterDefaultSetting("SoundElectroshock") +mod:RegisterDefaultSetting("SoundElectroshockSwap") +mod:RegisterDefaultSetting("SoundElectroshockSwapYou") +mod:RegisterDefaultSetting("SoundFireOrb") +mod:RegisterDefaultSetting("SoundFireOrbAlt") +mod:RegisterDefaultSetting("SoundFireOrbPop") +mod:RegisterDefaultSetting("SoundCoreHealthWarning") +---------------------------------------------------------------------------------------------------- +-- Raw event handlers. +---------------------------------------------------------------------------------------------------- +Apollo.RegisterEventHandler("UnitDestroyed", "OnUnitDestroyedRaw", mod) +---------------------------------------------------------------------------------------------------- -- Encounter description. ---------------------------------------------------------------------------------------------------- function mod:OnBossEnable() + player = {} + player.unit = GameLib.GetPlayerUnit() + player.location = 0 + engineerUnits = {} + orbUnits = {} + --locales + for name, id in pairs(CORE_NAMES) do + CORE_NAMES[name] = nil + CORE_NAMES[self.L[name]] = id + end + for name, id in pairs(ENGINEER_NAMES) do + ENGINEER_NAMES[name] = nil + ENGINEER_NAMES[self.L[name]] = id + end + + for id, coreUnit in pairs(coreUnits) do + coreUnit.healthWarning = false + end + + mod:AddTimerBar("NEXT_ELEKTROSHOCK_TIMER", self.L["electroshock.next"], FIRST_ELECTROSHOCK_TIMER) + mod:AddTimerBar("NEXT_LIQUIDATE_TIMER", self.L["liquidate.next"], FIRST_LIQUIDATE_TIMER) +end +function mod:OnBossDisable() + mod:RemoveUnits() end -function mod:OnBuffAdd(nId, nSpellId, nStack, fTimeRemaining) +function mod:AddUnits() + for engineerId, engineer in pairs(engineerUnits) do + core:WatchUnit(engineer.unit) + core:AddUnit(engineer.unit) + end + for coreId, coreUnit in pairs(coreUnits) do + core:WatchUnit(coreUnit.unit) + if mod:GetSetting("BarsCoreHealth") then + core:AddUnit(coreUnit.unit) + end + end end -function mod:OnCastStart(nId, sCastName, nCastEndTime, sName) +function mod:RemoveUnits() + for engineerId, engineer in pairs(engineerUnits) do + core:RemoveUnit(engineer.unit) + end + for coreId, coreUnit in pairs(coreUnits) do + if mod:GetSetting("BarsCoreHealth") then + core:RemoveUnit(coreUnit.unit) + end + end end -function mod:OnDebuffAdd(nId, nSpellId, nStack, fTimeRemaining) +function mod:GetUnitPlatform(unit) + local shortestDistance = 100000 + local currentDistance + local location = 0 + for coreId, coreUnit in pairs(coreUnits) do + currentDistance = mod:GetDistanceBetweenUnits(unit, coreUnit.unit) + if shortestDistance > currentDistance then + shortestDistance = currentDistance + location = coreId + end + end + return location +end +function mod:OnEngiChangeLocation(engineerId, oldCoreId, newCoreId) end -function mod:OnUnitDestroyed(nId, tUnit, sName) +function mod:OnBuffRemove(id, spellId) + if spellId == BUFF_INSULATION then + for engineerId, engineer in pairs(engineerUnits) do + local oldLocation = engineerUnits[engineerId].location + local newLocation = mod:GetUnitPlatform(engineer.unit) + if newLocation ~= oldLocation then + engineerUnits[engineerId].location = newLocation + mod:OnEngiChangeLocation(engineerId, oldLocation, newLocation) + end + end + end +end +function mod:OnDebuffAdd(id, spellId, stack, timeRemaining) + if DEBUFF_ELECTROSHOCK_VULNERABILITY == spellId then + local target = GetUnitById(id) + local targetName = target:GetName() + local isOnMyself = targetName == player.unit:GetName() + local electroshockOnX = "" + local messageId = string.format("ELECTROSHOCK_MSG_%s", targetName) + local sound + if bIsOnMyself then + electroshockOnX = self.L["electroshock.swap.you"] + sound = mod:GetSetting("SoundElectroshockSwapYou") == true and "RunAway" + else + electroshockOnX = self.L["electroshock.swap.other"]:format(targetName) + sound = mod:GetSetting("SoundElectroshockSwap") == true and "Info" + end + + mod:AddMsg(messageId, electroshockOnX, 5, sound, "Red") + end end -function mod:OnUnitCreated(nId, unit, sName) +function mod:IsPlayerOnPlatform(coreId) + player.location = mod:GetUnitPlatform(player.unit) + return player.location == coreId +end +function mod:OnUnitDestroyedRaw(unit) + local name = unit:GetName() + if CORE_NAMES[name] ~= nil then + coreUnits[CORE_NAMES[name]] = nil + end end mod:RegisterUnitEvents({ @@ -79,28 +259,147 @@ mod:RegisterUnitEvents({ "Spark Plug", "Lubricant Nozzle" },{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) - core:AddUnit(tUnit) - core:WatchUnit(tUnit) + ["OnUnitCreated"] = function (self, id, unit, name) + if CORE_NAMES[name] ~= nil then + coreUnits[CORE_NAMES[name]] = { + unit = unit, + healthWarning = false, + } + elseif ENGINEER_NAMES[name] ~= nil then + local engineerId = ENGINEER_NAMES[name] + engineerUnits[engineerId] = { + unit = unit, + location = ENGINEER_START_LOCATION[engineerId], + } + end + if #coreUnits == 4 and #engineerUnits == 2 then + mod:AddUnits() + end end, } ) + +-- Cores +mod:RegisterUnitEvents({ + "Fusion Core", + "Cooling Turbine", + "Spark Plug", + "Lubricant Nozzle" + },{ + ["OnHealthChanged"] = function (self, id, percent, name) + local coreUnit = coreUnits[CORE_NAMES[name]] + if percent > 15 and percent < 85 then + coreUnit.healthWarning = false + elseif percent >= 85 and not coreUnit.healthWarning then + coreUnit.healthWarning = true + mod:AddMsg("CORE_HEALTH_HIGH_WARN", self.L["core.health.high.warning"]:format(name), 5, mod:GetSetting("SoundCoreHealthWarning") and "Info") + elseif percent <= 15 and not coreUnit.healthWarning then + coreUnit.healthWarning = true + mod:AddMsg("CORE_HEALTH_LOW_WARN", self.L["core.health.low.warning"]:format(name), 5, mod:GetSetting("SoundCoreHealthWarning") and "Info") + end + end + } +) + +-- Warrior mod:RegisterUnitEvents("Chief Engineer Wilbargh",{ - ["OnCastStart"] = function (self, nId, sCastName, nCastEndTime, sName) - if self.L["Liquidate"] == sCastName then - --Stack + ["OnCastStart"] = function (self, id, castName, castEndTime, name) + if self.L["Liquidate"] == castName then + if mod:IsPlayerOnPlatform(engineerUnits[WARRIOR].location) then + mod:AddMsg("LIQUIDATE_MSG", self.L["liquidate.stack"], 5, mod:GetSetting("SoundLiquidate") == true and "Info") + end + end + end, + ["OnCastEnd"] = function (self, id, castName, castEndTime, name) + if self.L["Rocket Jump"] == castName then + mod:RemoveTimerBar("NEXT_LIQUIDATE_TIMER") + end + if self.L["Liquidate"] == castName then + mod:RemoveTimerBar("NEXT_LIQUIDATE_TIMER") + mod:AddTimerBar("NEXT_LIQUIDATE_TIMER", self.L["liquidate.next"], LIQUIDATE_TIMER) + end + end, + } +) + +function mod:IsUnitFacingOtherUnit(unit, otherUnit) + local unitVector = Vector3.New(unit:GetPosition()) + local otherUnitVector = Vector3.New(otherUnit:GetPosition()) + local difference = otherUnitVector - unitVector + local normalized = difference:Normal() + normalized.y = 0 + local facing = Vector3.New(unit:GetFacing()) + local facingDifference = normalized - facing + + return math.abs(facingDifference.x) < 0.01 and math.abs(facingDifference.z) < 0.01 +end + +-- Engineer +mod:RegisterUnitEvents("Head Engineer Orvulgh",{ + ["OnCastStart"] = function (self, id, castName, castEndTime, name) + if self.L["Electroshock"] == castName then + if mod:GetSetting("LineElectroshock") then + core:AddPixie("ELECTROSHOCK_PIXIE", 2, engineerUnits[ENGINEER].unit, nil, "Red", 10, 80, 0) + end + if mod:IsPlayerOnPlatform(engineerUnits[ENGINEER].location) then + mod:AddMsg("ELECTROSHOCK_CAST_MSG", self.L["Electroshock"], 5, mod:GetSetting("SoundElectroshock") == true and "Beware") + end + end + end, + ["OnCastEnd"] = function (self, id, castName, castEndTime, name) + if self.L["Rocket Jump"] == castName then + mod:RemoveTimerBar("NEXT_ELEKTROSHOCK_TIMER") + mod:AddTimerBar("NEXT_ELEKTROSHOCK_TIMER", self.L["electroshock.next"], JUMP_ELECTROSHOCK_TIMER) end + if self.L["Electroshock"] == castName then + if mod:GetSetting("LineElectroshock") then + core:DropPixie("ELECTROSHOCK_PIXIE") + end + mod:RemoveTimerBar("NEXT_ELEKTROSHOCK_TIMER") + mod:AddTimerBar("NEXT_ELEKTROSHOCK_TIMER", self.L["electroshock.next"], ELECTROSHOCK_TIMER) + end + end, + } +) + +function mod:PopFireOrb() + if mod:IsPlayerOnPlatform(FUSION_CORE) then + mod:AddMsg("FIRE_ORB_POP_MSG", self.L["fire_orb.pop.msg"], 5, mod:GetSetting("SoundFireOrbPop") == true and "Alarm") + end +end + +mod:RegisterUnitEvents("Discharged Plasma",{ + ["OnUnitCreated"] = function (self, id, unit, name) + core:WatchUnit(unit) + mod:RemoveTimerBar("NEXT_FIRE_ORB_TIMER") + mod:AddTimerBar("NEXT_FIRE_ORB_TIMER", self.L["fire_orb.next"], NEXT_FIRE_ORB_TIMER) + mod:AddTimerBar(string.format("FIRE_ORB_SAFE_TIMER %d", id), self.L["fire_orb.pop.timer"], FIRE_ORB_SAFE_TIMER, false, "Red", mod.PopFireOrb, mod) + fireOrbTargetTestTimer:Start() + orbUnits[id] = { + unit = unit, + checkedTarget = false, + popMessageSent = false, + timer = testTimer + } + end, + ["OnUnitDestroyed"] = function (self, id, unit, name) + orbUnits[id] = nil + mod:RemoveTimerBar(string.format("FIRE_ORB_SAFE_TIMER %d", id)) end, } ) --- mod:RegisterUnitEvents({"Friendly Invisible Unit for Fields"},{ --- ["OnUnitCreated"] = function (self, nId, tUnit, sName) --- core:AddPixie(nId, 2, tUnit, nil, "Green", 10, 50, 0) --- core:AddPixie(nId, 2, tUnit, nil, "Green", 10, 20, 180) --- end, --- ["OnUnitDestroyed"] = function (self, nId, tUnit, sName) --- core:DropPixie(nId) --- end, --- } --- ) +function mod:RegisterOrbTarget() + for orbId, orbUnit in pairs(orbUnits) do + if not orbUnit.checkedTarget then + orbUnit.checkedTarget = true + local target = orbUnit.unit:GetTarget() + local isOnMyself = target == player.unit + if isOnMyself then + mod:AddMsg("DISCHARGED_PLASMA_MSG", self.L["fire_orb.you"], 5, mod:GetSetting("SoundFireOrb") == true and "RunAway") + elseif mod:IsPlayerOnPlatform(FUSION_CORE) then + mod:AddMsg("DISCHARGED_PLASMA_MSG", self.L["fire_orb.spawned"], 2, mod:GetSetting("SoundFireOrbAlt") == true and "Info") + end + end + end +end diff --git a/Encounters/RMT/Mordechai.lua b/Encounters/RMT/Mordechai.lua index 6fa3b85..51a3b36 100644 --- a/Encounters/RMT/Mordechai.lua +++ b/Encounters/RMT/Mordechai.lua @@ -16,6 +16,7 @@ if not mod then return end ---------------------------------------------------------------------------------------------------- mod:RegisterTrigMob("ALL", { "Mordechai Redmoon" }) mod:RegisterEnglishLocale({ + -- Unit names. ["Mordechai Redmoon"] = "Mordechai Redmoon" }) ---------------------------------------------------------------------------------------------------- @@ -36,28 +37,28 @@ function mod:OnBossEnable() end -function mod:OnBuffAdd(nId, nSpellId, nStack, fTimeRemaining) +function mod:OnBuffAdd(id, spellId, stack, timeRemaining) end -function mod:OnCastStart(nId, sCastName, nCastEndTime, sName) +function mod:OnCastStart(id, castName, castEndTime, name) end -function mod:OnDebuffAdd(nId, nSpellId, nStack, fTimeRemaining) +function mod:OnDebuffAdd(id, spellId, stack, timeRemaining) end -function mod:OnUnitDestroyed(nId, tUnit, sName) +function mod:OnUnitDestroyed(id, tUnit, name) end -function mod:OnUnitCreated(nId, unit, sName) +function mod:OnUnitCreated(id, unit, name) end mod:RegisterUnitEvents("Mordechai Redmoon",{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) - core:AddUnit(tUnit) - core:WatchUnit(tUnit) + ["OnUnitCreated"] = function (self, id, unit, name) + core:AddUnit(unit) + core:WatchUnit(unit) end, } ) diff --git a/Encounters/RMT/Robomination.lua b/Encounters/RMT/Robomination.lua index 22de6ad..a00f0c1 100644 --- a/Encounters/RMT/Robomination.lua +++ b/Encounters/RMT/Robomination.lua @@ -16,22 +16,22 @@ if not mod then return end ---------------------------------------------------------------------------------------------------- mod:RegisterTrigMob("ANY", { "Robomination" }) mod:RegisterEnglishLocale({ - --Unit names. + -- Unit names. ["Robomination"] = "Robomination", ["Trash Compactor"] = "Trash Compactor", ["Cannon Arm"] = "Cannon Arm", ["Flailing Arm"] = "Flailing Arm", ["Scanning Eye"] = "Scanning Eye", - --Casts + -- Cast names. ["Cannon Fire"] = "Cannon Fire", ["Incineration Laser"] = "Incineration Laser", ["Noxious Belch"] = "Noxious Belch", - --Datachron - ["Robomination tries to crush"] = "Robomination tries to crush", - ["The Robomination tries to incinerate"] = "The Robomination tries to incinerate", + -- Datachron. + ["Robomination tries to crush ([^%s]+%s[^!]+)!$"] = "Robomination tries to crush ([^%s]+%s[^!]+)!$", + ["Robomination tries to incinerate ([^%s]+%s.+)$"] = "Robomination tries to incinerate ([^%s]+%s.+)$", ["The Robomination sinks down into the trash."] = "The Robomination sinks down into the trash.", ["The Robomination erupts back into the fight!"] = "The Robomination erupts back into the fight!", - --Message bars + -- Messages. ["SNAKE ON %s"] = "SNAKE ON %s", ["SNAKE ON YOU"] = "SNAKE ON YOU", ["SNAKE NEAR ON %s"] = "SNAKE NEAR ON %s", @@ -50,19 +50,28 @@ mod:RegisterEnglishLocale({ ---------------------------------------------------------------------------------------------------- -- Constants. ---------------------------------------------------------------------------------------------------- -local NO_BREAK_SPACE = string.char(194, 160) +-- Spell ids. local DEBUFF_SNAKE = 75126 + +-- Phases. local DPS_PHASE = 1 local MAZE_PHASE = 2 local MID_MAZE_PHASE = 3 + +-- Timers. local FIRST_SNAKE_TIMER = 7.5 local SNAKE_TIMER = 17.5 + local FIRST_INCINERATE_TIMER = 18.5 local INCINERATE_TIMER = 42.5 + local FIRST_SPEW_TIMER = 15.6 local SPEW_TIMER = 31.75 local MAZE_SPEW_TIMER = 10 + local ARMS_TIMER = 45 + +-- Compactors. local COMPACTORS_EDGE = { { y = -203.4208984375, x = 0.71257400512695, z = -1349.8697509766 }, { y = -203.4208984375, x = 10.955376625061, z = -1339.6927490234 }, @@ -125,40 +134,40 @@ function mod:OnBossEnable() mod:DrawCompactorGrid() end -mod:RegisterDatachronEvent("Robomination tries to crush", "FIND", function (self, sMessage) - local sSnakeTarget = GetPlayerUnitByName(string.match(sMessage, self.L["Robomination tries to crush"].." ".."([^%s]+%s[^!]+)!$")) - local bIsOnMyself = sSnakeTarget == playerUnit - local bSnakeNearYou = not bIsOnMyself and mod:GetDistanceBetweenUnits(playerUnit, sSnakeTarget) < 10 - local sSound = nil - local sSnakeOnX = "" - if bIsOnMyself then - sSound = mod:GetSetting("SoundSnake") == true and "RunAway" - sSnakeOnX = self.L["SNAKE ON YOU"] - elseif bSnakeNearYou then +mod:RegisterDatachronEvent("Robomination tries to crush ([^%s]+%s[^!]+)!$", "MATCH", function (self, message, snakeTargetName) + local snakeTarget = GetPlayerUnitByName(snakeTargetName) + local isOnMyself = snakeTarget == playerUnit + local isSnakeNearYou = not isOnMyself and mod:GetDistanceBetweenUnits(playerUnit, snakeTarget) < 10 + local sound = nil + local snakeOnX = "" + if isOnMyself then + sound = mod:GetSetting("SoundSnake") == true and "RunAway" + snakeOnX = self.L["SNAKE ON YOU"] + elseif isSnakeNearYou then if mod:GetSetting("SoundSnakeNear") then if mod:GetSetting("SoundSnakeNearAlt") then - sSound = "Destruction" + sound = "Destruction" else - sSound = "RunAway" + sound = "RunAway" end end - sSnakeOnX = self.L["SNAKE NEAR ON %s"]:format(sSnakeTarget:GetName()) + snakeOnX = self.L["SNAKE NEAR ON %s"]:format(snakeTarget:GetName()) else - sSnakeOnX = self.L["SNAKE ON %s"]:format(sSnakeTarget:GetName()) + snakeOnX = self.L["SNAKE ON %s"]:format(snakeTarget:GetName()) end if mod:GetSetting("CrosshairSnake") then - core:AddPicture("SNAKE_CROSSHAIR", sSnakeTarget:GetId(), "Crosshair", 20) + core:AddPicture("SNAKE_CROSSHAIR", snakeTarget:GetId(), "Crosshair", 20) end mod:RemoveTimerBar("NEXT_SNAKE_TIMER") core:AddTimerBar("NEXT_SNAKE_TIMER", self.L["Next snake in"], SNAKE_TIMER, nil, { sColor = "xkcdBrown" }) - mod:AddMsg("SNAKE_MSG", sSnakeOnX, 5, sSound, "Blue") + mod:AddMsg("SNAKE_MSG", snakeOnX, 5, sound, "Blue") end ) -mod:RegisterDatachronEvent("The Robomination sinks down into the trash.", "MATCH", function (self, sMessage) +mod:RegisterDatachronEvent("The Robomination sinks down into the trash.", "EQUAL", function (self, message) phase = MAZE_PHASE core:RemoveMsg("ROBO_MAZE") mod:RemoveTimerBar("NEXT_SNAKE_TIMER") @@ -173,7 +182,7 @@ mod:RegisterDatachronEvent("The Robomination sinks down into the trash.", "MATCH end ) -mod:RegisterDatachronEvent("The Robomination erupts back into the fight!", "MATCH", function (self, sMessage) +mod:RegisterDatachronEvent("The Robomination erupts back into the fight!", "EQUAL", function (self, message) phase = DPS_PHASE core:RemoveLineBetweenUnits("ROBO_MAZE_LINE") core:AddTimerBar("NEXT_SNAKE_TIMER", self.L["Next snake in"], FIRST_SNAKE_TIMER, nil, { sColor = "xkcdBrown" }) @@ -184,24 +193,24 @@ mod:RegisterDatachronEvent("The Robomination erupts back into the fight!", "MATC end ) -mod:RegisterDatachronEvent("Robomination tries to incinerate", "FIND", function (self, sMessage) - local tLaserTarget = GetPlayerUnitByName(string.match(sMessage, self.L["Robomination tries to incinerate"].." ".."([^%s]+%s.+)$")) - local bIsOnMyself = tLaserTarget == playerUnit - local sSound = mod:GetSetting("SoundLaser") == true and "Burn" - local sLaserOnX = "" - if bIsOnMyself then - sLaserOnX = self.L["LASER ON YOU"] +mod:RegisterDatachronEvent("Robomination tries to incinerate ([^%s]+%s.+)$", "MATCH", function (self, message, laserTargetName) + local laserTarget = GetPlayerUnitByName(laserTargetName) + local isOnMyself = laserTarget == playerUnit + local sound = mod:GetSetting("SoundLaser") == true and "Burn" + local laserOnX = "" + if isOnMyself then + laserOnX = self.L["LASER ON YOU"] else - sLaserOnX = self.L["LASER ON %s"]:format(tLaserTarget:GetName()) + laserOnX = self.L["LASER ON %s"]:format(laserTarget:GetName()) end if mod:GetSetting("CrosshairLaser") then - core:AddPicture("LASER_CROSSHAIR", tLaserTarget:GetId(), "Crosshair", 30, 0, 0, nil, "Red") + core:AddPicture("LASER_CROSSHAIR", laserTarget:GetId(), "Crosshair", 30, 0, 0, nil, "Red") end mod:RemoveTimerBar("NEXT_INCINERATE_TIMER") core:AddTimerBar("NEXT_INCINERATE_TIMER", self.L["Next incinerate in"], INCINERATE_TIMER, nil, { sColor = "red", bEmphasize = mod:GetSetting("SoundLaser") }) - mod:AddMsg("LASER_MSG", sLaserOnX, 5, sSound, "Red") + mod:AddMsg("LASER_MSG", laserOnX, 5, sound, "Red") end ) @@ -232,8 +241,8 @@ function mod:HelperCompactorGrid(compactors, isCorner, isAdding) end end -function mod:OnDebuffRemove(nId, nSpellId, nStack, fTimeRemaining) - if nSpellId == DEBUFF_SNAKE then +function mod:OnDebuffRemove(id, spellId, stack, timeRemaining) + if spellId == DEBUFF_SNAKE then core:RemovePicture("SNAKE_CROSSHAIR") end end @@ -244,26 +253,26 @@ mod:RegisterUnitEvents({ "Robomination", "Scanning Eye", },{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) - core:AddUnit(tUnit) + ["OnUnitCreated"] = function (self, id, unit, name) + core:AddUnit(unit) end, } ) mod:RegisterUnitEvents("Scanning Eye",{ - ["OnUnitDestroyed"] = function (self, nId, tUnit, sName) + ["OnUnitDestroyed"] = function (self, id, unit, name) phase = MID_MAZE_PHASE end, } ) mod:RegisterUnitEvents({"Cannon Arm", "Flailing Arm"},{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) + ["OnUnitCreated"] = function (self, id, unit, name) if phase == MID_MAZE_PHASE then mazeArmCount = mazeArmCount + 1 end end, - ["OnUnitDestroyed"] = function (self, nId, tUnit, sName) + ["OnUnitDestroyed"] = function (self, id, unit, name) if phase == MID_MAZE_PHASE then mazeArmCount = mazeArmCount - 1 if mazeArmCount == 0 then @@ -279,65 +288,65 @@ mod:RegisterUnitEvents({"Cannon Arm", "Flailing Arm"},{ function mod:RedrawCannonArmLines() if mod:GetSetting("LineCannonArm") then - for nId, tUnit in pairs(cannonArms) do - core:AddLineBetweenUnits(string.format("CANNON_ARM_LINE %d", nId), playerUnit:GetId(), nId, 5) + for id, tUnit in pairs(cannonArms) do + core:AddLineBetweenUnits(string.format("CANNON_ARM_LINE %d", id), playerUnit:GetId(), id, 5) end end end function mod:RemoveCannonArmLines() if mod:GetSetting("LineCannonArm") then - for nId, tUnit in pairs(cannonArms) do - core:RemoveLineBetweenUnits(string.format("CANNON_ARM_LINE %d", nId)) + for id, tUnit in pairs(cannonArms) do + core:RemoveLineBetweenUnits(string.format("CANNON_ARM_LINE %d", id)) end end end mod:RegisterUnitEvents("Cannon Arm",{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) - cannonArms[nId] = tUnit - core:WatchUnit(tUnit) + ["OnUnitCreated"] = function (self, id, unit, name) + cannonArms[id] = unit + core:WatchUnit(unit) if mod:GetSetting("LineCannonArm") then - core:AddLineBetweenUnits(string.format("CANNON_ARM_LINE %d", nId), playerUnit:GetId(), nId, 5) + core:AddLineBetweenUnits(string.format("CANNON_ARM_LINE %d", id), playerUnit:GetId(), id, 5) end if phase == DPS_PHASE then mod:AddTimerBar("NEXT_ARMS_TIMER", self.L["Arms spawning in"], ARMS_TIMER) end mod:AddMsg("ARMS_MSG", self.L["Cannon arm spawned"], 5, mod:GetSetting("SoundArmSpawn") == true and "Info", "Red") end, - ["OnCastStart"] = function (self, nId, sCastName, nCastEndTime, sName) - if self.L["Cannon Fire"] == sCastName then - if mod:GetDistanceBetweenUnits(playerUnit, GetUnitById(nId)) < 45 then + ["OnCastStart"] = function (self, id, castName, castEndTime, name) + if self.L["Cannon Fire"] == castName then + if mod:GetDistanceBetweenUnits(playerUnit, GetUnitById(id)) < 45 then mod:AddMsg("ARMS_MSG", self.L["INTERRUPT CANNON!"], 2, mod:GetSetting("SoundCannonInterrupt") == true and "Inferno") end end end, - ["OnUnitDestroyed"] = function (self, nId, tUnit, sName) - cannonArms[nId] = nil - core:RemoveLineBetweenUnits(string.format("CANNON_ARM_LINE %d", nId)) + ["OnUnitDestroyed"] = function (self, id, unit, name) + cannonArms[id] = nil + core:RemoveLineBetweenUnits(string.format("CANNON_ARM_LINE %d", id)) end, } ) mod:RegisterUnitEvents("Robomination",{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) - core:WatchUnit(tUnit) - roboUnit = tUnit + ["OnUnitCreated"] = function (self, id, unit, name) + core:WatchUnit(unit) + roboUnit = unit end, - ["OnHealthChanged"] = function (self, nId, nPourcent, sName) - if nPourcent >= 75.5 and nPourcent <= 76.5 then + ["OnHealthChanged"] = function (self, id, percent, name) + if percent >= 75.5 and percent <= 76.5 then mod:AddMsg("ROBO_MAZE", self.L["MAZE SOON!"], 5, mod:GetSetting("SoundPhaseChangeClose") and "Info") end end, - ["OnCastStart"] = function (self, nId, sCastName, nCastEndTime, sName) - if self.L["Noxious Belch"] == sCastName then + ["OnCastStart"] = function (self, id, castName, castEndTime, name) + if self.L["Noxious Belch"] == castName then mod:RemoveTimerBar("NEXT_SPEW_TIMER") core:AddTimerBar("NEXT_SPEW_TIMER", self.L["Next spew in"], SPEW_TIMER, nil, { sColor = "green" }) mod:AddMsg("SPEW_MSG", self.L["Spew!"], 4, mod:GetSetting("SoundSpew") == true and "Beware") end end, - ["OnCastEnd"] = function (self, nId, sCastName, isInterrupted, nCastEndTime, sName) - if self.L["Incineration Laser"] == sCastName then + ["OnCastEnd"] = function (self, id, castName, isInterrupted, castEndTime, name) + if self.L["Incineration Laser"] == castName then core:RemovePicture("LASER_CROSSHAIR") end end, diff --git a/Encounters/RMT/Shredder.lua b/Encounters/RMT/Shredder.lua index 6c9a8f3..e491a4d 100644 --- a/Encounters/RMT/Shredder.lua +++ b/Encounters/RMT/Shredder.lua @@ -22,7 +22,7 @@ if not mod then return end ---------------------------------------------------------------------------------------------------- mod:RegisterTrigMob("ALL", { "Swabbie Ski'Li" }) mod:RegisterEnglishLocale({ - --Unit names + -- Unit names. ["Swabbie Ski'Li"] = "Swabbie Ski'Li", ["Sawblade"] = "Sawblade", -- big saw ["Saw"] = "Saw", -- little saw @@ -38,7 +38,7 @@ mod:RegisterEnglishLocale({ ["Junk Trap"] = "Junk Trap", -- Datachron messages. ["WARNING: THE SHREDDER IS STARTING!"] = "WARNING: THE SHREDDER IS STARTING!", - --Cast names + -- Cast names. ["Swabbie Swoop"] = "Swabbie Swoop", ["Risen Repellent"] = "Risen Repellent", ["Crush"] = "Crush", @@ -46,33 +46,13 @@ mod:RegisterEnglishLocale({ ["Deathwail"] = "Deathwail", ["Necrotic Lash"] = "Necrotic Lash", ["Swabbie Swoop"] = "Swabbie Swoop", - --Messages + -- Messages. ["%d BILE STACKS!"] = "%d BILE STACKS!", - }) - -mod:RegisterFrenchLocale({ - -- --Unit names - -- ["Swabbie Ski'Li"] = "Swabbie Ski'Li", - -- ["Sawblade"] = "Sawblade", -- big saw - -- ["Saw"] = "Saw", -- little saw - -- ["Noxious Nabber"] = "Noxious Nabber", - -- ["Risen Redmoon Grunt"] = "Risen Redmoon Grunt", - -- ["Regor the Rancid"] = "Regor the Rancid", - -- ["Braugh the Bloated"] = "Braugh the Bloated", - -- ["Bilious Brute"] = "Bilious Brute", - -- ["Putrid Pouncer"] = "Putrid Pouncer", - -- ["Risen Redmoon Plunderer"] = "Risen Redmoon Plunderer", - -- ["Risen Redmoon Cadet"] = "Risen Redmoon Cadet", - -- -- Datachron messages. - -- ["WARNING: THE SHREDDER IS STARTING!"] = "WARNING: THE SHREDDER IS STARTING!", - -- --Cast names - -- ["Swabbie Swoop"] = "Swabbie Swoop", - -- ["Risen Repellent"] = "Risen Repellent", - -- ["Crush"] = "Crush", - -- ["Gravedigger"] = "Gravedigger", - -- ["Deathwail"] = "Deathwail", - -- ["Necrotic Lash"] = "Necrotic Lash", - -- ["Swabbie Swoop"] = "Swabbie Swoop", + ["SAW IN MIDDLE"] = "SAW IN MIDDLE", + ["SAFE SPOT %s"] = "SAFE SPOT %s", + ["LEFT"] = "LEFT", + ["MIDDLE"] = "MIDDLE", + ["RIGHT"] = "RIGHT", }) ---------------------------------------------------------------------------------------------------- -- Settings @@ -87,6 +67,8 @@ mod:RegisterDefaultSetting("SoundMiniboss") mod:RegisterDefaultSetting("SoundNecroticLash") mod:RegisterDefaultSetting("SoundMinibossCast") mod:RegisterDefaultSetting("SoundOozeStacksWarning") +mod:RegisterDefaultSetting("SoundMidSawWarning") +mod:RegisterDefaultSetting("SoundSawSafeSpot") ---------------------------------------------------------------------------------------------------- -- Constants. ---------------------------------------------------------------------------------------------------- @@ -108,23 +90,46 @@ function circular(t) return setmetatable(t, lmt) end +-- Coordinates local START_POSITION = Vector3.New({x = -20.054916381836,y = 597.66021728516,z = -809.42694091797}) local END_POSITION = Vector3.New({x = -20.499969482422,y = 597.88836669922,z = -973.21472167969}) local WALKING_DISTANCE = (END_POSITION-START_POSITION):Length() -local NO_BREAK_SPACE = string.char(194, 160) + +-- Phases. local WALKING = 0 local SHREDDER = 1 local ADD_PHASES = circular{ 11, 45, 66, 0 } + +-- Spell ids. local DEBUFF_OOZING_BILE = 84321 + +-- Saw stuff. +local WEST_POSITION = -42 +local MIDDLE_WEST_POSITION = -28 +local MIDDLE_EAST_POSITION = -14 +local EAST_POSITION = 0 +local SAW_WEST = 1 +local SAW_MID = 2 +local SAW_WEST = 4 +local SAW_SAFESPOT = { + [3] = "LEFT", --SAW_WEST + SAW_MID + [5] = "MIDDLE", --SAW_WEST + SAW_EAST + [6] = "RIGHT", --SAW_MID + SAW_EAST +} ---------------------------------------------------------------------------------------------------- --- Locals. +-- Functions. ---------------------------------------------------------------------------------------------------- local GetUnitById = GameLib.GetUnitById local GetPlayerUnit = GameLib.GetPlayerUnit local GetGameTime = GameLib.GetGameTime +---------------------------------------------------------------------------------------------------- +-- Locals. +---------------------------------------------------------------------------------------------------- local phase local addPhase local previousAddPhase +local firstShredderSaw +local secondShredderSaw ---------------------------------------------------------------------------------------------------- -- Encounter description. ----------------------------------------------------------------------------------------------------- @@ -133,12 +138,14 @@ function mod:OnBossEnable() phase = WALKING addPhase = 4 previousAddPhase = 0 + firstShredderSaw = nil + secondShredderSaw = nil end -function mod:OnDebuffUpdate(nId, nSpellId, nStack, fTimeRemaining) - if DEBUFF_OOZING_BILE == nSpellId then - if GameLib.GetPlayerUnit():GetId() == nId and nStack >= 8 then - mod:AddMsg("OOZE_MSG", string.format(self.L["%d BILE STACKS!"], nStack), 5, nStack == 8 and mod:GetSetting("SoundOozeStacksWarning") and "Beware") +function mod:OnDebuffUpdate(id, spellId, stack, timeRemaining) + if DEBUFF_OOZING_BILE == spellId then + if GameLib.GetPlayerUnit():GetId() == id and stack >= 8 then + mod:AddMsg("OOZE_MSG", string.format(self.L["%d BILE STACKS!"], stack), 5, stack == 8 and mod:GetSetting("SoundOozeStacksWarning") and "Beware") end end end @@ -176,23 +183,25 @@ function mod:NextAddWave() end function mod:PhaseChange() - local sText = "Walking " + local text = "Walking " if phase == SHREDDER then phase = WALKING - sText = sText.." North" + text = text.." North" mod:NextAddWave() else - sText = sText.." South" + text = text.." South" phase = SHREDDER + firstShredderSaw = nil + secondShredderSaw = nil end - mod:AddProgressBar("WALKING_PROGRESS", sText, mod.GetWalkingProgress, mod, mod.PhaseChange) + mod:AddProgressBar("WALKING_PROGRESS", text, mod.GetWalkingProgress, mod, mod.PhaseChange) end function mod:StartProgressBar() mod:AddProgressBar("WALKING_PROGRESS", "Walking North", mod.GetWalkingProgress, mod, mod.PhaseChange) mod:NextAddWave() - _tStartProgressBar:Stop() - _tStartProgressBar = nil + startProgressBarTimer:Stop() + startProgressBarTimer = nil end mod:RegisterUnitEvents({ @@ -205,75 +214,110 @@ mod:RegisterUnitEvents({ "Risen Redmoon Plunderer", "Risen Redmoon Cadet" },{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) - core:WatchUnit(tUnit) + ["OnUnitCreated"] = function (self, id, unit, name) + core:WatchUnit(unit) end, - ["OnUnitDestroyed"] = function (self, nId, tUnit, sName) - core:RemovePicture(nId) + ["OnUnitDestroyed"] = function (self, id, unit, name) + core:RemovePicture(id) end, - ["OnHealthChanged"] = function (self, nId, nPourcent, sName) - if nPourcent <= 1 and mod:GetSetting("CrosshairAdds") then - core:AddPicture(nId, nId, "Crosshair", 20) + ["OnHealthChanged"] = function (self, id, percent, name) + if percent <= 1 and mod:GetSetting("CrosshairAdds") then + core:AddPicture(id, id, "Crosshair", 20) end end, } ) mod:RegisterUnitEvents({ "Bilious Brute", "Noxious Nabber" },{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) + ["OnUnitCreated"] = function (self, id, unit, name) if mod:GetSetting("CrosshairPriority") then - core:AddPicture(nId, nId, "Crosshair", 30, 0, 0, nil, "red") + core:AddPicture(id, id, "Crosshair", 30, 0, 0, nil, "red") end end, } ) mod:RegisterUnitEvents("Swabbie Ski'Li",{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) - core:AddUnit(tUnit) - core:WatchUnit(tUnit) - self.swabbieUnit = tUnit + ["OnUnitCreated"] = function (self, id, unit, name) + core:AddUnit(unit) + core:WatchUnit(unit) + self.swabbieUnit = unit end, - ["OnUnitDestroyed"] = function (self, nId, tUnit, sName) - core:RemoveUnit(tUnit) + ["OnUnitDestroyed"] = function (self, id, unit, name) + core:RemoveUnit(unit) self:RemoveProgressBar("WALKING_PROGRESS") self:RemoveProgressBar("ADDS_PROGRESS") end, - ["OnCastStart"] = function (self, nId, sCastName, nCastEndTime, sName) - if self.L["Risen Repellent"] == sCastName then + ["OnCastStart"] = function (self, id, castName, castEndTime, name) + if self.L["Risen Repellent"] == castName then mod:AddMsg("KNOCKBACK", "KNOCKBACK", 2) end end, - ["OnCastEnd"] = function (self, nId, sCastName, isInterrupted, nCastEndTime, sName) - if self.L["Swabbie Swoop"] == sCastName then - _tStartProgressBar = ApolloTimer.Create(1, true, "StartProgressBar", mod) - _tStartProgressBar:Start() + ["OnCastEnd"] = function (self, id, castName, isInterrupted, castEndTime, name) + if self.L["Swabbie Swoop"] == castName then + startProgressBarTimer = ApolloTimer.Create(1, true, "StartProgressBar", mod) + startProgressBarTimer:Start() end end, } ) +function mod:DetermineSawLocation(unit) + local x = unit:GetPosition().x + if WEST_POSITION < x and x < MIDDLE_WEST_POSITION then + return SAW_WEST + elseif MIDDLE_WEST_POSITION < x and x < MIDDLE_EAST_POSITION then + return SAW_MID + elseif MIDDLE_EAST_POSITION < x and x < EAST_POSITION then + return SAW_EAST + end +end + +function mod:HandleShredderSaw(sawLocation) + if firstShredderSaw == nil then + firstShredderSaw = sawLocation + return + elseif secondShredderSaw == nil then + secondShredderSaw = sawLocation + else + return + end + + local safeSpotLocation = SAW_SAFESPOT[firstShredderSaw + secondShredderSaw] + local message = string.format(self.L["SAFE SPOT %s"], self.L[safeSpotLocation]) + local sound = mod:GetSetting("SoundSawSafeSpot") == true and "Info" + mod:AddMsg("SAW_MSG", message, 5, sound) +end + mod:RegisterUnitEvents("Sawblade",{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) + ["OnUnitCreated"] = function (self, id, unit, name) if mod:GetSetting("LineSawblade") then - core:AddPixie(nId, 2, tUnit, nil, "Red", 10, 60, 0) + core:AddPixie(id, 2, unit, nil, "Red", 10, 60, 0) + end + local sawLocation = mod:DetermineSawLocation(unit) + if phase == WALKING and sawLocation == SAW_MID then + mod:AddMsg("SAW_MSG", self.L["SAW IN MIDDLE"], 5, + mod:GetSetting("SoundMidSawWarning") == true and "Beware" + ) + elseif phase == SHREDDER then + mod:HandleShredderSaw(sawLocation) end end, - ["OnUnitDestroyed"] = function (self, nId, tUnit, sName) - core:DropPixie(nId) + ["OnUnitDestroyed"] = function (self, id, unit, name) + core:DropPixie(id) end, } ) mod:RegisterUnitEvents("Noxious Nabber",{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) + ["OnUnitCreated"] = function (self, id, unit, name) core:RemoveMsg("ADDS_MSG") mod:AddMsg("ADDS_MSG", "NOXIOUS NABBER SPAWNED", 5, mod:GetSetting("SoundAdds") and "Info") end, - ["OnCastStart"] = function (self, nId, sCastName, nCastEndTime, sName) - if self.L["Necrotic Lash"] == sCastName then - local tUnit = GetUnitById(nId) - if mod:GetDistanceBetweenUnits(playerUnit, tUnit) < 45 and sSpellName == sCastName then + ["OnCastStart"] = function (self, id, castName, castEndTime, name) + if self.L["Necrotic Lash"] == castName then + local unit = GetUnitById(id) + if mod:GetDistanceBetweenUnits(playerUnit, unit) < 45 and sSpellName == castName then mod:AddMsg("NABBER", "INTERRUPT NECROTIC LASH!", 5, mod:GetSetting("SoundNecroticLash") == true and "Inferno") end end @@ -282,13 +326,13 @@ mod:RegisterUnitEvents("Noxious Nabber",{ ) mod:RegisterUnitEvents({"Regor the Rancid", "Braugh the Bloated"},{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) + ["OnUnitCreated"] = function (self, id, unit, name) mod:AddMsg("MINIBOSS", "MINIBOSS SPAWNED", 5, mod:GetSetting("SoundMiniboss") and "Info") end, - ["OnCastStart"] = function (self, nId, sCastName, nCastEndTime, sName) - if self.L["Gravedigger"] == sCastName or - self.L["Deathwail"] == sCastName or - self.L["Crush"] == sCastName then + ["OnCastStart"] = function (self, id, castName, castEndTime, name) + if self.L["Gravedigger"] == castName or + self.L["Deathwail"] == castName or + self.L["Crush"] == castName then core:RemoveMsg("MINIBOSS") mod:AddMsg("MINIBOSS", "INTERRUPT MINIBOSS!", 5, mod:GetSetting("SoundMinibossCast") and "Inferno") end @@ -297,25 +341,25 @@ mod:RegisterUnitEvents({"Regor the Rancid", "Braugh the Bloated"},{ ) mod:RegisterUnitEvents("Tether Anchor",{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) + ["OnUnitCreated"] = function (self, id, unit, name) if mod:GetSetting("CrosshairTether") then - core:AddPicture(nId, nId, "Crosshair", 25, 0, 0, nil, "FFFFF569") + core:AddPicture(id, id, "Crosshair", 25, 0, 0, nil, "FFFFF569") end end, - ["OnUnitDestroyed"] = function (self, nId, tUnit, sName) - core:RemovePicture(nId) + ["OnUnitDestroyed"] = function (self, id, unit, name) + core:RemovePicture(id) end, } ) mod:RegisterUnitEvents("Junk Trap",{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) + ["OnUnitCreated"] = function (self, id, unit, name) if mod:GetSetting("SquareTethers") then - core:AddPolygon(nId, nId, 5, 45, 6, nil, 4) + core:AddPolygon(id, id, 5, 45, 6, nil, 4) end end, - ["OnUnitDestroyed"] = function (self, nId, tUnit, sName) - core:RemovePolygon(nId) + ["OnUnitDestroyed"] = function (self, id, unit, name) + core:RemovePolygon(id) end, } ) diff --git a/Encounters/RMT/miniboss/Lockjaw.lua b/Encounters/RMT/miniboss/Lockjaw.lua index 49a3689..cdf42e3 100644 --- a/Encounters/RMT/miniboss/Lockjaw.lua +++ b/Encounters/RMT/miniboss/Lockjaw.lua @@ -16,37 +16,27 @@ if not mod then return end ---------------------------------------------------------------------------------------------------- mod:RegisterTrigMob("ALL", { "Chief Warden Lockjaw" }) mod:RegisterEnglishLocale({ + -- Unit names. ["Chief Warden Lockjaw"] = "Chief Warden Lockjaw", ["Hostile Invisible Unit for Fields (0 hit radius)"] = "Hostile Invisible Unit for Fields (0 hit radius)", ["Blaze Shackle"] = "Blaze Shackle", + -- Cast names. ["Blaze Shackles"] = "Blaze Shackles", }) ---------------------------------------------------------------------------------------------------- -- Settings. ---------------------------------------------------------------------------------------------------- mod:RegisterDefaultSetting("CrosshairTethers") ----------------------------------------------------------------------------------------------------- --- Constants. ----------------------------------------------------------------------------------------------------- - ----------------------------------------------------------------------------------------------------- --- Locals. ----------------------------------------------------------------------------------------------------- - ---------------------------------------------------------------------------------------------------- -- Encounter description. ---------------------------------------------------------------------------------------------------- -function mod:OnBossEnable() - -end - mod:RegisterUnitEvents("Chief Warden Lockjaw",{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) - core:AddUnit(tUnit) - core:WatchUnit(tUnit) + ["OnUnitCreated"] = function (self, id, unit, name) + core:AddUnit(unit) + core:WatchUnit(unit) end, - ["OnCastStart"] = function (self, nId, sCastName, nCastEndTime, sName) - if self.L["Blaze Shackles"] == sCastName then + ["OnCastStart"] = function (self, id, castName, castEndTime, name) + if self.L["Blaze Shackles"] == castName then mod:AddMsg("CIRCLES", "DODGE CIRCLES", 5, "Info") end end, @@ -54,13 +44,13 @@ mod:RegisterUnitEvents("Chief Warden Lockjaw",{ ) mod:RegisterUnitEvents("Blaze Shackle",{ - ["OnUnitCreated"] = function (self, nId, tUnit, sName) + ["OnUnitCreated"] = function (self, id, unit, name) if mod:GetSetting("CrosshairTethers") then - core:AddPicture(nId, nId, "Crosshair", 25) + core:AddPicture(id, id, "Crosshair", 25) end end, - ["OnUnitDestroyed"] = function (self, nId, tUnit, sName) - core:RemovePicture(nId) + ["OnUnitDestroyed"] = function (self, id, unit, name) + core:RemovePicture(id) end, } ) diff --git a/Encounters/RMT/miniboss/Skooty.lua b/Encounters/RMT/miniboss/Skooty.lua new file mode 100644 index 0000000..86c7309 --- /dev/null +++ b/Encounters/RMT/miniboss/Skooty.lua @@ -0,0 +1,75 @@ +---------------------------------------------------------------------------------------------------- +-- Client Lua Script for RaidCore Addon on WildStar Game. +-- +-- Copyright (C) 2015 RaidCore +---------------------------------------------------------------------------------------------------- +---------------------------------------------------------------------------------------------------- +-- Description: +-- TODO +---------------------------------------------------------------------------------------------------- +local core = Apollo.GetPackage("Gemini:Addon-1.1").tPackage:GetAddon("RaidCore") +local mod = core:NewEncounter("Skooty", 104, 548, 552) +if not mod then return end + +---------------------------------------------------------------------------------------------------- +-- Registering combat. +---------------------------------------------------------------------------------------------------- +mod:RegisterTrigMob("ALL", { "Assistant Technician Skooty" }) +mod:RegisterEnglishLocale({ + -- Unit names. + ["Assistant Technician Skooty"] = "Assistant Technician Skooty", + ["Hostile Invisible Unit for Fields (0 hit radius)"] = "Hostile Invisible Unit for Fields (0 hit radius)", + ["Jumpstart Charge"] = "Jumpstart Charge", + -- Cast names. + ["Pulse Cannon"] = "Pulse Cannon", + }) +---------------------------------------------------------------------------------------------------- +-- Settings. +---------------------------------------------------------------------------------------------------- +mod:RegisterDefaultSetting("PulseCannon") +mod:RegisterDefaultSetting("BombLines") +---------------------------------------------------------------------------------------------------- +-- Constants. +---------------------------------------------------------------------------------------------------- + +---------------------------------------------------------------------------------------------------- +-- Locals. +---------------------------------------------------------------------------------------------------- +local jumpStarts +local playerUnit +---------------------------------------------------------------------------------------------------- +-- Encounter description. +---------------------------------------------------------------------------------------------------- +function mod:OnBossEnable() + playerUnit = GameLib.GetPlayerUnit() +end + +mod:RegisterUnitEvents("Assistant Technician Skooty",{ + ["OnUnitCreated"] = function (self, id, unit, name) + core:AddUnit(unit) + core:WatchUnit(unit) + end, + ["OnCastStart"] = function (self, id, castName, castEndTime, name) + if self.L["Pulse Cannon"] == castName then + mod:AddMsg("PULSECANNON", "GET OUT", 5, mod:GetSetting("PulseCannon") == true and "RunAway") + end + end, + } +) + +mod:RegisterUnitEvents("Jumpstart Charge",{ + ["OnUnitCreated"] = function (self, id, unit, name) + jumpStarts[id] = unit + core:WatchUnit(unit) + if mod:GetSetting("BombLines") then + core:AddLineBetweenUnits(string.format("JUMP_START_LINE %d", id), playerUnit:GetId(), id, 5) + end + end, + ["OnUnitDestroyed"] = function (self, id, unit, name) + jumpStarts[id] = nil + if mod:GetSetting("BombLines") then + core:RemoveLineBetweenUnits(string.format("JUMP_START_LINE %d", id)) + end + end, + } +) diff --git a/Encounters/RMT/miniboss/Thrag.lua b/Encounters/RMT/miniboss/Thrag.lua new file mode 100644 index 0000000..f0bd6a3 --- /dev/null +++ b/Encounters/RMT/miniboss/Thrag.lua @@ -0,0 +1,75 @@ +---------------------------------------------------------------------------------------------------- +-- Client Lua Script for RaidCore Addon on WildStar Game. +-- +-- Copyright (C) 2015 RaidCore +---------------------------------------------------------------------------------------------------- +---------------------------------------------------------------------------------------------------- +-- Description: +-- TODO +---------------------------------------------------------------------------------------------------- +local core = Apollo.GetPackage("Gemini:Addon-1.1").tPackage:GetAddon("RaidCore") +local mod = core:NewEncounter("Thrag", 104, 548, 552) +if not mod then return end + +---------------------------------------------------------------------------------------------------- +-- Registering combat. +---------------------------------------------------------------------------------------------------- +mod:RegisterTrigMob("ALL", { "Chief Engine Scrubber Thrag" }) +mod:RegisterEnglishLocale({ + -- Unit names. + ["Chief Engine Scrubber Thrag"] = "Chief Engine Scrubber Thrag", + ["Hostile Invisible Unit for Fields (0 hit radius)"] = "Hostile Invisible Unit for Fields (0 hit radius)", + ["Jumpstart Charge"] = "Jumpstart Charge", + -- Cast names. + ["Gigavolt"] = "Gigavolt", + }) +---------------------------------------------------------------------------------------------------- +-- Settings. +---------------------------------------------------------------------------------------------------- +mod:RegisterDefaultSetting("Gigavolt") +mod:RegisterDefaultSetting("BombLines") +---------------------------------------------------------------------------------------------------- +-- Constants. +---------------------------------------------------------------------------------------------------- + +---------------------------------------------------------------------------------------------------- +-- Locals. +---------------------------------------------------------------------------------------------------- +local jumpStarts +local playerUnit +---------------------------------------------------------------------------------------------------- +-- Encounter description. +---------------------------------------------------------------------------------------------------- +function mod:OnBossEnable() + playerUnit = GameLib.GetPlayerUnit() +end + +mod:RegisterUnitEvents("Chief Engine Scrubber Thrag",{ + ["OnUnitCreated"] = function (self, id, unit, name) + core:AddUnit(unit) + core:WatchUnit(unit) + end, + ["OnCastStart"] = function (self, id, castName, castEndTime, name) + if self.L["Gigavolt"] == castName then + mod:AddMsg("GIGAVOLT", "GET OUT", 5, mod:GetSetting("Gigavolt") == true and "RunAway") + end + end, + } +) + +mod:RegisterUnitEvents("Jumpstart Charge",{ + ["OnUnitCreated"] = function (self, id, unit, name) + jumpStarts[id] = unit + core:WatchUnit(unit) + if mod:GetSetting("BombLines") then + core:AddLineBetweenUnits(string.format("JUMP_START_LINE %d", id), playerUnit:GetId(), id, 5) + end + end, + ["OnUnitDestroyed"] = function (self, id, unit, name) + jumpStarts[id] = nil + if mod:GetSetting("BombLines") then + core:RemoveLineBetweenUnits(string.format("JUMP_START_LINE %d", id)) + end + end, + } +) diff --git a/Encounters/TEST/GalerasTest.lua b/Encounters/TEST/GalerasTest.lua index 5aa07b2..a81b735 100644 --- a/Encounters/TEST/GalerasTest.lua +++ b/Encounters/TEST/GalerasTest.lua @@ -46,20 +46,20 @@ mod:RegisterDefaultTimerBarConfigs({ -- Locals. ---------------------------------------------------------------------------------------------------- local function InfiniteTimer2() - mod:AddTimerBar("INFINITE2", "Loop Timer outside", 10, nil, InfiniteTimer2) + mod:AddTimerBar("INFINITE2", "Loop Timer outside", 10, nil, nil, InfiniteTimer2) end ---------------------------------------------------------------------------------------------------- -- Encounter description. ---------------------------------------------------------------------------------------------------- function mod:OnBossEnable() - mod:AddTimerBar("INFINITE", "Timer in class", 12, false, mod.InfiniteTimer, mod) - mod:AddTimerBar("INFINITE2", "Timer outside", 12, nil, InfiniteTimer2) + mod:AddTimerBar("INFINITE", "Timer in class", 12, false, nil, mod.InfiniteTimer, mod) + mod:AddTimerBar("INFINITE2", "Timer outside", 12, nil, nil, InfiniteTimer2) mod:AddTimerBar("LONG", "Long long timer...", 1000) end function mod:InfiniteTimer() - mod:AddTimerBar("INFINITE", "Loop Timer in class", 10, false, mod.InfiniteTimer, mod) + mod:AddTimerBar("INFINITE", "Loop Timer in class", 10, false, nil, mod.InfiniteTimer, mod) end function mod:OnUnitCreated(nId, unit, sName) diff --git a/README.md b/README.md index 57cd006..e721024 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ RaidCore ================ Raidcore is a boss-mods addon for Wildstar game, it's intend to: - - Aid with fights in Genetic Archives, Datascape and Core-Y83 raids. + - Aid with fights in Genetic Archives, Datascape, Core-Y83 and Red Moon Terror Raids. - It supports the english and french game version, for german some translations are missing. Please open an issue if you notice problems, or if you have a idea of improvement. -All rights reserved. \ No newline at end of file +All rights reserved. diff --git a/RaidCore.lua b/RaidCore.lua index 84be361..3099d72 100644 --- a/RaidCore.lua +++ b/RaidCore.lua @@ -32,7 +32,7 @@ local next, pcall = next, pcall -- Should be 5.23 when replacement tokens will works (see #88 issue). local RAIDCORE_CURRENT_VERSION = "6" -- Should be deleted. -local ADDON_DATE_VERSION = 16082301 +local ADDON_DATE_VERSION = 16090417 -- Sometimes Carbine have inserted some no-break-space, for fun. -- Behavior seen with French language. This problem is not present in English. local NO_BREAK_SPACE = string.char(194, 160) @@ -89,6 +89,9 @@ local function OnEncounterUnitEvents(sMethod, ...) elseif sMethod == "OnHealthChanged" then local nId, nPourcent, sName = ... tEncounter = _tCurrentEncounter.tUnitEvents[sMethod][sName] + elseif sMethod == "OnEnteredCombat" then + local nId, tUnit, sName, bInCombat = ... + tEncounter = _tCurrentEncounter.tUnitEvents[sMethod][sName] end if tEncounter then @@ -107,11 +110,20 @@ local function OnEncounterDatachronEvents(sMethod, ...) for sSearchMessage, tEvents in pairs(_tCurrentEncounter.tDatachronEvents) do for _, tEvent in pairs(tEvents) do local sMessage = ... - local bMatch = tEvent.bMatch + local sMatch = tEvent.sMatch local fHandler = tEvent.fHandler - if (bMatch == true and sSearchMessage == sMessage) or - (bMatch == false and sMessage:find(sSearchMessage)) then - fHandler(_tCurrentEncounter, ...) + local result = nil + + if sMatch == "EQUAL" then + result = sSearchMessage == sMessage + elseif sMatch == "FIND" then + result = sMessage:find(sSearchMessage) + elseif sMatch == "MATCH" then + result = sMessage:match(sSearchMessage) + end + + if result ~= nil then + fHandler(_tCurrentEncounter, sMessage, result) end end end diff --git a/RaidCore.xml b/RaidCore.xml index ec1ed30..24c7e94 100644 --- a/RaidCore.xml +++ b/RaidCore.xml @@ -1544,10 +1544,34 @@ + + + + + + + + + + + + + + + + + + + + + + + +
- + @@ -1573,7 +1597,7 @@ - + @@ -1599,6 +1623,16 @@ + + + + + + + + + +
@@ -1623,7 +1657,7 @@ - + @@ -1682,7 +1716,7 @@ -
+ @@ -1691,4 +1725,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RaidCore_GUI.lua b/RaidCore_GUI.lua index 6dd79bf..1287538 100644 --- a/RaidCore_GUI.lua +++ b/RaidCore_GUI.lua @@ -269,6 +269,7 @@ function RaidCore:GUI_init(sVersion) Shredder = Apollo.LoadForm(self.xmlDoc, "ConfigForm_Shredder", self.wndEncounterTarget, self), MinibossesRedmoon = Apollo.LoadForm(self.xmlDoc, "ConfigForm_MinibossesRedmoon", self.wndEncounterTarget, self), Robomination = Apollo.LoadForm(self.xmlDoc, "ConfigForm_Robomination", self.wndEncounterTarget, self), + Engineers = Apollo.LoadForm(self.xmlDoc, "ConfigForm_Engineers", self.wndEncounterTarget, self), } -- Initialize Left Menu in Main RaidCore window. local wndGeneralButton = self.wndMain:FindChild("Static"):FindChild("General") diff --git a/toc.xml b/toc.xml index 2c38ec2..17fd49f 100644 --- a/toc.xml +++ b/toc.xml @@ -68,4 +68,6 @@