Various Fixes.
generified the Worldboss module; removed the spammy-section as of currently, will be readded at a later stage.
This commit is contained in:
@@ -141,4 +141,4 @@ class WhatBuffsController:
|
||||
return ChatBlob(f"Whatbuffs - {skill.name} {item_type} ({len(data):d})", blob)
|
||||
|
||||
def get_footer(self):
|
||||
return "\nItem DB Extraction Info provided by Unk"
|
||||
return "\nItem DB Extraction Info provided by IGNCore"
|
||||
|
||||
@@ -45,7 +45,7 @@ class LevelController:
|
||||
|
||||
@command(command="mission", params=[Int("mission_level")], access_level="member",
|
||||
description="Show what character levels can roll a specified mission level",
|
||||
extended_description="Updated mission levels provided by Lucier")
|
||||
extended_description="Updated mission levels provided by Zetabyte")
|
||||
def mission_cmd(self, _, level):
|
||||
if 1 <= level <= 250:
|
||||
levels = self.get_mission_levels(level)
|
||||
|
||||
@@ -134,10 +134,7 @@ hh:mm - DD.MM.YYYY
|
||||
out += f"[Starts in {self.util.time_to_readable(next_event.start - time.time())}] " \
|
||||
f"[by <highlight>{name}</highlight>]\n"
|
||||
|
||||
for timer in self.worldboss.timer_data:
|
||||
msg = self.worldboss.show_user(timer)
|
||||
if msg != "No timers cached; please try again later.":
|
||||
out += " " + msg + "\n"
|
||||
out += self.worldboss.getWBTimer()
|
||||
return out
|
||||
|
||||
def get_next_event(self):
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import time
|
||||
import datetime
|
||||
from typing import Union
|
||||
|
||||
from core.chat_blob import ChatBlob
|
||||
from core.command_alias_service import CommandAliasService
|
||||
from core.command_param_types import Any
|
||||
from core.decorators import instance, command, event, setting
|
||||
from core.dict_object import DictObject
|
||||
from core.command_param_types import Any, Const
|
||||
from core.decorators import instance, command, event
|
||||
from core.igncore import IgnCore
|
||||
from core.job_scheduler import JobScheduler
|
||||
from core.logger import Logger
|
||||
@@ -16,17 +16,66 @@ from core.util import Util
|
||||
from modules.standard.datanet.ws_controller import WebsocketRelayController
|
||||
|
||||
|
||||
class TimerObj:
|
||||
name: str = ""
|
||||
spawn: int = 0
|
||||
mortal: int = 0
|
||||
time: int = 0
|
||||
spam: int = 0
|
||||
|
||||
def __init__(self, obj):
|
||||
self.name = obj.name
|
||||
self.spawn = obj.spawn
|
||||
self.mortal = obj.mortal
|
||||
self.time = obj.time
|
||||
|
||||
def update(self, obj):
|
||||
self.spawn = obj.spawn
|
||||
self.time = obj.time
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} " \
|
||||
f"\n\tspawn: {datetime.datetime.fromtimestamp(self.spawn, tz=datetime.timezone.utc).strftime('%H:%M:%S')}" \
|
||||
f"\n\tmortal delta: {self.mortal}" \
|
||||
f"\n\tmortal: {datetime.datetime.fromtimestamp(self.time, tz=datetime.timezone.utc).strftime('%H:%M:%S')}" \
|
||||
f"\n\tImmortal: {self.alive_immortal()}" \
|
||||
f"\n\tMortal killable: {self.alive_mortal()}"\
|
||||
f"\n\t{self.name} - {self.spawn} - {self.mortal} - {self.time} - {self.spam} - {self.getTime()}"
|
||||
|
||||
def alive_immortal(self, spam=False) -> bool:
|
||||
if spam:
|
||||
return self.spam < self.spawn < self.time and self.time > self.getTime()
|
||||
return self.time > self.getTime()
|
||||
|
||||
def alive_mortal(self, spam=False) -> bool:
|
||||
if spam:
|
||||
return self.spam < self.time < (self.getTime()) and (self.time+60) > self.getTime()
|
||||
return self.time < self.getTime()
|
||||
|
||||
@classmethod
|
||||
def getTime(cls) -> int:
|
||||
return int(datetime.datetime.now().timestamp())
|
||||
|
||||
def get_respawn_timer(self):
|
||||
if self.name in ["Tarasque", "Loren Warr", "The Hollow Reaper", "Cerubin The Reborn"]:
|
||||
return 9*60*60
|
||||
elif self.name in ["Vizaresh"]:
|
||||
return 17*60*60
|
||||
elif self.name in ["Atma"]:
|
||||
return 3 * 60 * 60
|
||||
elif self.name in ["T.A.M.", "Zaal The Immortal"]:
|
||||
return 6 * 60 * 60
|
||||
elif self.name in ["Abmouth Indomitus"]:
|
||||
return 0
|
||||
|
||||
|
||||
@instance()
|
||||
class WorldBossController:
|
||||
# Timers are provided through a local websocket relay, which gets fed by an external API.
|
||||
# example timer data:
|
||||
# [{"name":"Tarasque","time": <mortal time>},
|
||||
# {"name":"Vizaresh","time": <mortal time>}]
|
||||
timer_data = []
|
||||
|
||||
alerts = [480 * 60, 360 * 60, 240 * 60, 120 * 60, 60 * 60, 60 * 15,
|
||||
60 * 5, 60 * 3, 60 * 2, 60, 30, 15, 5, 0]
|
||||
jobs = []
|
||||
jobs = {}
|
||||
|
||||
def inject(self, registry):
|
||||
self.logger = Logger(__name__)
|
||||
@@ -48,80 +97,46 @@ class WorldBossController:
|
||||
self.command_alias_service.add_alias("loren", "wb loren")
|
||||
self.command_alias_service.add_alias("reaper", "wb reaper")
|
||||
|
||||
def spam_timer(self, time, mob, msg):
|
||||
self.send_warn(msg)
|
||||
self.jobs.pop(mob, 0)
|
||||
|
||||
@event(WebsocketRelayController.WS_RELAY, "save most current local_timers")
|
||||
def get_timer(self, _, data):
|
||||
# print(data)
|
||||
if data.type != "timer":
|
||||
return
|
||||
local_timers = {}
|
||||
spam = True if self.setting_service.get_value("timer_spam") == "1" else False
|
||||
local = {}
|
||||
for x in data.payload:
|
||||
found = False
|
||||
for y in self.timer_data:
|
||||
if y.name == x.name and not found:
|
||||
y.update(x)
|
||||
found = True
|
||||
if not found:
|
||||
self.timer_data.append(TimerObj(x))
|
||||
# print("-"*50)
|
||||
for x in self.timer_data:
|
||||
local_timers[x['name']] = x['time']
|
||||
for row in data.payload:
|
||||
spawn = self.get_spawn(row)
|
||||
if not spawn:
|
||||
continue
|
||||
if row['name'] not in local_timers:
|
||||
self.timer_data.append(row)
|
||||
if spam:
|
||||
for x in self.jobs:
|
||||
if x['name'] == row['name']:
|
||||
self.job_scheduler.cancel_job(x['id'])
|
||||
self.jobs.append(
|
||||
{'name': row['name'], 'id': self.job_scheduler.delayed_job(self.timer_alert, 2, spawn)})
|
||||
continue
|
||||
elif (local_timers[row['name']] + 1) < row['time']:
|
||||
for timer in self.timer_data:
|
||||
if timer['name'] == row['name']:
|
||||
timer['time'] = row['time']
|
||||
if spam:
|
||||
for job in self.jobs:
|
||||
if job['name'] == row['name']:
|
||||
self.job_scheduler.cancel_job(job['id'])
|
||||
alert_duration = self.get_next_alert(spawn.at - time.time())
|
||||
job_id = self.job_scheduler.scheduled_job(self.timer_alert, 2,
|
||||
spawn)
|
||||
job['id'] = job_id
|
||||
|
||||
def get_spawn(self, timer):
|
||||
timer = DictObject(timer)
|
||||
if timer.name == "Loren Warr":
|
||||
data = self.calc_spawn_mortal(timer.time, 9 * 60 * 60, 15 * 60)
|
||||
elif timer.name == "Tarasque":
|
||||
data = self.calc_spawn_mortal(timer.time, 9 * 60 * 60, 30 * 60)
|
||||
elif timer.name == "The Hollow Reaper":
|
||||
data = self.calc_spawn_mortal(timer.time, 9 * 60 * 60, 15 * 60)
|
||||
elif timer.name == "Vizaresh":
|
||||
data = self.calc_spawn_mortal(timer.time, 17 * 60 * 60, 6 * 60)
|
||||
else:
|
||||
return None
|
||||
if not data:
|
||||
return
|
||||
if data.spawn < time.time():
|
||||
if data.mortal > time.time():
|
||||
return DictObject(
|
||||
{'name': timer.name, 'type': 'mortal', 'time': data.mortal - time.time(), 'at': data.mortal,
|
||||
'data': data})
|
||||
return DictObject(
|
||||
{'name': timer.name, 'type': 'spawn', 'time': data.spawn - time.time(), 'at': data.spawn, 'data': data})
|
||||
|
||||
def calc_spawn_mortal(self, last, respawn, immortal):
|
||||
pop = last + respawn
|
||||
attackable = pop + immortal
|
||||
now = time.time()
|
||||
|
||||
# Mortal
|
||||
if immortal > attackable - now > 0:
|
||||
return DictObject({'spawn': pop, 'mortal': attackable})
|
||||
elif immortal > attackable + respawn - now > 0:
|
||||
return DictObject({'spawn': pop + respawn, 'mortal': attackable + respawn})
|
||||
|
||||
# Spawn
|
||||
elif respawn > (pop - now) > 0:
|
||||
return DictObject({'spawn': pop, 'mortal': pop})
|
||||
elif respawn > pop + respawn - now > 0:
|
||||
return DictObject({'spawn': attackable + respawn, 'mortal': attackable + respawn + immortal})
|
||||
elif last - now > 0:
|
||||
return DictObject({'spawn': last - immortal, 'mortal': last})
|
||||
x: TimerObj
|
||||
# print(x.__str__())
|
||||
if x.alive_immortal(True):
|
||||
x.spam = x.getTime()
|
||||
job = self.jobs.pop(x.name, None)
|
||||
if job:
|
||||
self.job_scheduler.cancel_job(job)
|
||||
self.send_warn(f"<highlight>{x.name}</highlight> has spawned.")
|
||||
i = self.job_scheduler.scheduled_job(self.spam_timer, x.time-1, mob=x.name, msg=f"<highlight>{x.name}</highlight> is now mortal.")
|
||||
self.jobs[x.name] = i
|
||||
elif x.alive_mortal(True):
|
||||
x.spam = x.getTime()
|
||||
job = self.jobs.pop(x.name, None)
|
||||
if job:
|
||||
self.job_scheduler.cancel_job(job)
|
||||
self.send_warn(f"<highlight>{x.name}</highlight> is now mortal.")
|
||||
if x.get_respawn_timer() != 0:
|
||||
i = self.job_scheduler.scheduled_job(self.spam_timer, x.time+x.get_respawn_timer(), mob=x.name, msg=f"<highlight>{x.name}</highlight> should spawn soon.")
|
||||
self.jobs[x.name] = i
|
||||
# print("-"*50)
|
||||
|
||||
def send_warn(self, msg):
|
||||
self.relay_hub.send_message("timers", None, f"[<red>WB</red>] {msg}", f"[<red>WB</red>] {msg}")
|
||||
@@ -135,65 +150,76 @@ class WorldBossController:
|
||||
@command(command="wb", params=[Any("worldboss", is_optional=True)],
|
||||
description="Displays the next worldboss spawns", access_level="member")
|
||||
def show_worldboss(self, request, boss: str):
|
||||
if boss:
|
||||
boss = boss.lower()
|
||||
if boss in ["tara", "tarasque"]:
|
||||
boss = "Tarasque"
|
||||
elif boss in ["viza", "vizaresh", "gaunt", "gauntlet"]:
|
||||
boss = "Vizaresh"
|
||||
elif boss in ["loren", "loren warr", "loren war", "lw"]:
|
||||
boss = "Loren Warr"
|
||||
elif boss in ["thr", "the hollow", "the hollow reaper", "reaper"]:
|
||||
boss = "The Hollow Reaper"
|
||||
for x in self.timer_data:
|
||||
if x['name'] == boss:
|
||||
return self.show_user(x)
|
||||
else:
|
||||
blob = "\n".join([self.show_user(x) for x in self.timer_data if
|
||||
self.show_user(x) != "No timers cached; please try again later."])
|
||||
return ChatBlob("Next Worldboss spawns", blob)
|
||||
return ChatBlob("Next Worldboss spawns", self.getWBTimer())
|
||||
|
||||
@command(command="wb", params=[Const("settings")],
|
||||
description="Worldboss Settings", access_level="moderator", sub_command="mod")
|
||||
def wb_settings_cmd(self, request, boss: str):
|
||||
pass
|
||||
|
||||
def show_user(self, timer):
|
||||
timer = self.get_spawn(timer)
|
||||
timer = self.getWBTimer(timer)
|
||||
if not timer:
|
||||
return "No timers cached; please try again later."
|
||||
if timer.type == "mortal":
|
||||
return f"<highlight>{timer.name}</highlight> :: mortal in {self.util.format_time(timer.time)}"
|
||||
elif timer.type == "spawn":
|
||||
return f"<highlight>{timer.name}</highlight> :: spawn in {self.util.format_time(timer.time)}"
|
||||
if timer.spawn < timer.getTime() < timer.time:
|
||||
return f"<highlight>{timer.name}</highlight> :: mortal in {self.util.format_time(timer.time-timer.spawn)}"
|
||||
elif timer.time < timer.getTime():
|
||||
rt = timer.get_respawn_timer()
|
||||
|
||||
return f"<highlight>{timer.name}</highlight> :: spawn in {self.util.format_time(timer.time + timer.get_respawn_timer())}"
|
||||
|
||||
def getWBTimer(self, name=None) -> Union[TimerObj, list[TimerObj]]:
|
||||
if not name:
|
||||
blob = ""
|
||||
for x in self.timer_data:
|
||||
x: TimerObj
|
||||
if x.alive_immortal():
|
||||
blob += f" <highlight>{x.name}</highlight> :: mortal in {self.util.format_time(x.time - x.getTime())}\n"
|
||||
else:
|
||||
rt = x.get_respawn_timer()
|
||||
if rt != 0:
|
||||
if (x.time + rt) < x.getTime() < (x.time + 2 * rt):
|
||||
blob += f" <highlight>{x.name}</highlight> :: should have spawned <highlight>{self.util.format_time(abs(x.getTime() - (x.time + rt)))}</highlight> ago\n"
|
||||
continue
|
||||
blob += f" <highlight>{x.name}</highlight> :: spawn in {self.util.format_time(x.time + rt - x.getTime())}\n"
|
||||
return blob
|
||||
for x in self.timer_data:
|
||||
if x.name == name:
|
||||
return x
|
||||
|
||||
def timer_alert(self, t, timer):
|
||||
if self.setting_service.get_value("timer_spam") == "0":
|
||||
return
|
||||
for row in self.timer_data:
|
||||
if row["name"] == timer.name:
|
||||
timer = self.get_spawn(row)
|
||||
if not timer.at:
|
||||
return
|
||||
alert_duration = self.get_next_alert(timer.at - time.time())
|
||||
if timer.at - time.time() < 1:
|
||||
if timer.type == "mortal":
|
||||
self.send_warn(f"<highlight>{timer.name}</highlight> :: is now mortal")
|
||||
self.jobs = [x for x in self.jobs if x['name'] != timer.name]
|
||||
elif timer.type == "spawn":
|
||||
self.send_warn(f"<highlight>{timer.name}</highlight> :: has just spawned")
|
||||
self.jobs = [x for x in self.jobs if x['name'] != timer.name]
|
||||
else:
|
||||
if timer.type == "mortal":
|
||||
self.send_warn(f"<highlight>{timer.name}</highlight> :: mortal in {self.util.format_time(timer.time)}")
|
||||
elif timer.type == "spawn":
|
||||
if alert_duration > 60 * 2:
|
||||
self.send_warn(
|
||||
f"<highlight>{timer.name}</highlight> :: spawn in {self.util.format_time(timer.time)}")
|
||||
for row in self.timer_data:
|
||||
if row["name"] == timer.name:
|
||||
timer = self.get_spawn(row)
|
||||
job_id = self.job_scheduler.scheduled_job(self.timer_alert, time.time() + alert_duration, timer)
|
||||
for job in self.jobs:
|
||||
if job['name'] == timer.name:
|
||||
job['id'] = job_id
|
||||
return
|
||||
self.jobs.append({'name': timer.name, 'id': job_id})
|
||||
pass
|
||||
# if self.setting_service.get_value("timer_spam") == "0":
|
||||
# return
|
||||
# for row in self.timer_data:
|
||||
# if row["name"] == timer.name:
|
||||
# timer = self.get_spawn(row)
|
||||
# if not timer.at:
|
||||
# return
|
||||
# alert_duration = self.get_next_alert(timer.at - time.time())
|
||||
# if timer.at - time.time() < 1:
|
||||
# if timer.type == "mortal":
|
||||
# self.send_warn(f"<highlight>{timer.name}</highlight> :: is now mortal")
|
||||
# self.jobs = [x for x in self.jobs if x['name'] != timer.name]
|
||||
# elif timer.type == "spawn":
|
||||
# self.send_warn(f"<highlight>{timer.name}</highlight> :: has just spawned")
|
||||
# self.jobs = [x for x in self.jobs if x['name'] != timer.name]
|
||||
# else:
|
||||
# if timer.type == "mortal":
|
||||
# self.send_warn(f"<highlight>{timer.name}</highlight> :: mortal in {self.util.format_time(timer.time)}")
|
||||
# elif timer.type == "spawn":
|
||||
# if alert_duration > 60 * 2:
|
||||
# self.send_warn(
|
||||
# f"<highlight>{timer.name}</highlight> :: spawn in {self.util.format_time(timer.time)}")
|
||||
# for row in self.timer_data:
|
||||
# if row["name"] == timer.name:
|
||||
# timer = self.get_spawn(row)
|
||||
# job_id = self.job_scheduler.scheduled_job(self.timer_alert, time.time() + alert_duration, timer)
|
||||
# for job in self.jobs:
|
||||
# if job['name'] == timer.name:
|
||||
# job['id'] = job_id
|
||||
# return
|
||||
# self.jobs.append({'name': timer.name, 'id': job_id})
|
||||
|
||||
# @setting('alert_times', '[480 * 60, 360 * 60, 240 * 60, 120 * 60, 60 * 60, 60 * 15, 60 * 5, 60 * 3, 60 * 2, 60, 30, 15, 5, 0]', 'Worldboss timer spam messages (ETA and actual)')
|
||||
# def alert_times(self):
|
||||
|
||||
@@ -10,6 +10,7 @@ from core.command_request import CommandRequest
|
||||
from core.db import DB
|
||||
from core.decorators import instance, event, command
|
||||
from core.dict_object import DictObject
|
||||
from core.event_service import EventService
|
||||
from core.fifo_queue import FifoQueue
|
||||
from core.igncore import IgnCore
|
||||
from core.logger import Logger
|
||||
@@ -49,6 +50,7 @@ class OnlineController:
|
||||
self.online_display: OnlineDisplay = OnlineDisplay(self.text, self.util, self.db, self.afk_list)
|
||||
self.account_service: AccountService = registry.get_instance("account_service")
|
||||
self.character_service: CharacterService = registry.get_instance("character_service")
|
||||
self.event_service: EventService = registry.get_instance("event_service")
|
||||
|
||||
def pre_start(self):
|
||||
self.db.exec("DROP TABLE IF EXISTS online")
|
||||
@@ -92,7 +94,7 @@ class OnlineController:
|
||||
while self.bot.status != BotStatus.SHUTDOWN:
|
||||
data, channel, logged = self.awaiting_data.get()
|
||||
buddy = (self.buddy_service.get_buddy(data.packet.char_id) or {}).get("types", [])
|
||||
if ("org_member" in buddy) or ("member" in buddy):
|
||||
if ("org_member" in buddy) or ("member" in buddy) or ("darknet" in buddy):
|
||||
if logged:
|
||||
self.db.exec("INSERT IGNORE INTO online VALUES(?, ?, ?)",
|
||||
[data.packet.char_id, channel, self.bot.get_char_id()])
|
||||
|
||||
@@ -5,7 +5,7 @@ from core.command_param_types import Any, Const, Time, Options
|
||||
from core.decorators import instance, command
|
||||
from core.igncore import IgnCore
|
||||
from core.registry import Registry
|
||||
from modules.standard.news.worldboss_controller import WorldBossController
|
||||
from modules.standard.news.worldboss_controller import WorldBossController, TimerObj
|
||||
|
||||
|
||||
class TimerTime(Time):
|
||||
@@ -83,10 +83,9 @@ class TimerController:
|
||||
blob = ""
|
||||
if self.worldboss.timer_data:
|
||||
blob += "<header>Automatic Timers</header>\n"
|
||||
for row in self.worldboss.timer_data:
|
||||
msg, cnt = getmsg(self.worldboss.show_user(row))
|
||||
blob += msg
|
||||
count += cnt
|
||||
blob += self.worldboss.getWBTimer()
|
||||
x: TimerObj = None
|
||||
count += len([x for x in self.worldboss.timer_data if (x.time+x.get_respawn_timer()) < x.getTime()])
|
||||
blob += "\n\n<header>Manual Timers</header>\n"
|
||||
for timer in data:
|
||||
repeats = ""
|
||||
|
||||
@@ -147,7 +147,7 @@ class TowerHotController(BaseModule):
|
||||
params.append(min_ql)
|
||||
params.append(max_ql)
|
||||
if faction:
|
||||
where += " AND c.faction LIKE "
|
||||
where += " AND c.faction LIKE ?"
|
||||
params.append("%" + faction.capitalize() + "%")
|
||||
data = self.db.query("SELECT a.*, f.short_name, c.org_name, b.min_ql, b.max_ql, "
|
||||
"(CASE WHEN (a.close_time-?) < 0 THEN a.close_time-? +86400 ELSE a.close_time-? END) "
|
||||
|
||||
Reference in New Issue
Block a user