17c776faec
-> !wants -> !orgs info -> special cmd's -> !assist -> "afk" for players without active account -> !loot add <item_ref> <count> => nolonger breaks !account Changes: -> grouped !tara, !gaunt, .. into !wb -> Display the most recent news entry on logon (default: enabled) -> improved grouping of !items -> Added the option to authentificate WS connections (Datanet module). This is used in special cases, where the Websocket Server requires the clien tto authentificate itself. (Server sends "#auth", client responds with the auth string) -> Add main name to relaying (priv <-> org) [default: disabled] -> Added logon/logoff messages back -> restricted default access to "dangerous" commands to moderator -> Added optional logging (Private Channel, Org Channel, Tells, ... disabled by default) Rewrite of the Tower Module. -> More verbosity, if enabled in config. by default, GAS and Hot timer only. -> !hot displays currently hot (and in penalty) sites, and these which go hot in < 60 minutes -> !attacks filterable by PF and Site -> display current contract QL's grouped by org: !contracts (requires managed cache)
167 lines
8.1 KiB
Python
167 lines
8.1 KiB
Python
import time
|
|
|
|
from core.aochat.BaseModule import BaseModule
|
|
from core.command_alias_service import CommandAliasService
|
|
from core.command_param_types import Options, Int, Any, NamedParameters
|
|
from core.db import DB
|
|
from core.decorators import instance, command, event
|
|
from core.dict_object import DictObject
|
|
from core.event_service import EventService
|
|
from core.igncore import IgnCore
|
|
from core.lookup.pork_service import PorkService
|
|
from core.public_channel_service import PublicChannelService
|
|
from core.text import Text
|
|
from core.util import Util
|
|
from modules.standard.helpbot.playfield_controller import PlayfieldController
|
|
from modules.standard.tower.tower_events import TowerEventController
|
|
|
|
|
|
@instance()
|
|
class TowerHotController(BaseModule):
|
|
PAGE_SIZE = 30
|
|
|
|
# noinspection DuplicatedCode
|
|
|
|
def inject(self, registry):
|
|
self.bot: IgnCore = registry.get_instance("bot")
|
|
self.db: DB = registry.get_instance("db")
|
|
self.util: Util = registry.get_instance("util")
|
|
self.text: Text = registry.get_instance("text")
|
|
self.event_service: EventService = registry.get_instance("event_service")
|
|
self.pork_service: PorkService = registry.get_instance("pork_service")
|
|
self.playfield_controller: PlayfieldController = registry.get_instance("playfield_controller")
|
|
self.public_channel_service: PublicChannelService = registry.get_instance("public_channel_service")
|
|
self.command_alias_service: CommandAliasService = registry.get_instance("command_alias_service")
|
|
|
|
@event(event_type=TowerEventController.TOWER_ATTACK_EVENT, description="Mark Sites in penalty as in penalty",
|
|
is_enabled=False)
|
|
def tower_victory_event(self, _, event_data):
|
|
if event_data.attacker.org_id:
|
|
self.db.exec("UPDATE towers SET penalty_until=? where org_id=?",
|
|
[time.time() + 60 * 60, event_data.attacker.org_id])
|
|
|
|
@command(command="hot",
|
|
params=[Options(['tl1', 'tl2', 'tl3', 'tl4', 'tl5', 'tl6', 'tl7']), Any('faction', is_optional=True),
|
|
NamedParameters(["page"])],
|
|
access_level="member",
|
|
description="Shows hot playfields")
|
|
def hot_tl(self, _, tl, faction: str, named_params):
|
|
if faction:
|
|
if faction.startswith("--page="):
|
|
named_params = DictObject({'page': faction[7:]})
|
|
faction = None
|
|
if faction is not None and faction.lower() not in ['omni', 'clan', 'neut', 'neutral']:
|
|
return f"Unknown faction: {faction}"
|
|
tl = tl[2:]
|
|
page = int(named_params.page or "1")
|
|
offset = (page - 1) * self.PAGE_SIZE
|
|
towers = self.get_hot_sites_tl(int(tl), faction)
|
|
return self.text.format_pagination(towers, offset, page, self.formatter, f"Hot Sites TL{tl} ({len(towers)})",
|
|
f"There are no hot sites for TL <highlight>{tl}</highlight>.",
|
|
f'hot tl{tl} {faction or ""}', self.PAGE_SIZE)
|
|
|
|
def formatter(self, row, index, data):
|
|
d = {}
|
|
if index > 1:
|
|
d = data[index - 2]
|
|
status = ""
|
|
if row.status_time <= 3600:
|
|
status += f"<red>5%</red> (closes in {self.util.time_to_readable(row.status_time)})"
|
|
elif row.status_time <= (3600 * 6):
|
|
status += f"<orange>25%</orange> (closes in {self.util.time_to_readable(row.status_time)})"
|
|
else:
|
|
status += f"<green>75%</green> (opens in {self.util.time_to_readable(row.status_time - (3600 * 6))})"
|
|
if row.penalty_until > time.time():
|
|
status += f" <red>In Penalty for: {self.util.time_to_readable(row.penalty_until - time.time())}</red>"
|
|
blob = ""
|
|
if self.get_ct_type(d.get("ql", 0)) < (tl := self.get_ct_type(row.ql)):
|
|
blob += f"<notice>TL{tl}</notice><br>"
|
|
space = f"{row.short_name} x{row.site_number}"
|
|
place = "_" * (7 - len(space))
|
|
return blob + "<tab>" + self.text.make_tellcmd(space,
|
|
f'lc {row.short_name} {row.site_number}') + \
|
|
f"<black>{place}</black> QL {row.min_ql}/<highlight>{row.ql}</highlight>/{row.max_ql} - " \
|
|
f"{self.text.get_formatted_faction(row.faction, row.org_name)}, {status}\n"
|
|
|
|
@command(command="hot",
|
|
params=[Int('level', is_optional=True), Any('faction', is_optional=True), NamedParameters(["page"])],
|
|
access_level="member",
|
|
description="Shows hot playfields by level")
|
|
def hot_level(self, _, level, faction, named_params):
|
|
if faction:
|
|
if faction.startswith("--page="):
|
|
named_params = DictObject({'page': faction[7:]})
|
|
faction = None
|
|
if faction is not None and faction.lower() not in ['omni', 'clan', 'neut', 'neutral']:
|
|
return f"Unknown faction: {faction}"
|
|
if level:
|
|
if level < 0 | level > 220:
|
|
return f"Level out of range: {level}"
|
|
page = int(named_params.page or "1")
|
|
offset = (page - 1) * self.PAGE_SIZE
|
|
towers = self.get_hot_sites(level, faction)
|
|
level = f"{level}" if level else ""
|
|
faction = f"{faction} " if faction else ""
|
|
return self.text.format_pagination(towers, offset, page, self.formatter, f"Hot Towersites ({len(towers)})",
|
|
f"There are no hot sites.", f'hot {level}{faction}', self.PAGE_SIZE)
|
|
|
|
def get_hot_sites(self, level=None, faction=None):
|
|
where = ""
|
|
now = time.time() % 86400
|
|
params = [now, now, now]
|
|
if level:
|
|
where += " AND l.pvp_min <=? and pvp_max >= ? "
|
|
params.append(level)
|
|
params.append(level)
|
|
if faction:
|
|
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) "
|
|
" AS status_time FROM tower_sites b "
|
|
"LEFT JOIN towers a ON a.pf_id = b.playfield_id AND a.site_number = b.site_number "
|
|
"LEFT JOIN level l on a.ql = l.level "
|
|
"LEFT JOIN playfields f on a.pf_id = f.id "
|
|
f"LEFT JOIN all_orgs c ON a.org_id = c.org_id WHERE close_time IS NOT NULL {where} ORDER BY a.ql",
|
|
params)
|
|
return [x for x in data if x.status_time - (3600 * 6) < 60 * 60 or x.penalty_until > time.time()]
|
|
|
|
def get_hot_sites_tl(self, tl=7, faction=None):
|
|
min_ql, max_ql = self.util.get_level_range_tl(tl)
|
|
where = ""
|
|
now = time.time() % 86400
|
|
params = [now, now, now]
|
|
where += " AND ql between ? and ? "
|
|
params.append(min_ql)
|
|
params.append(max_ql)
|
|
if faction:
|
|
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) "
|
|
" AS status_time FROM tower_sites b "
|
|
"LEFT JOIN towers a ON a.pf_id = b.playfield_id AND a.site_number = b.site_number "
|
|
"LEFT JOIN level l on a.ql = l.level "
|
|
"LEFT JOIN playfields f on a.pf_id = f.id "
|
|
f"LEFT JOIN all_orgs c ON a.org_id = c.org_id WHERE close_time IS NOT NULL {where} ORDER BY a.ql",
|
|
params)
|
|
return [x for x in data if x.status_time - (3600 * 6) < 60 * 60 or x.penalty_until > time.time()]
|
|
|
|
def get_ct_type(self, ql):
|
|
if ql == 0:
|
|
return 0
|
|
elif ql < 34:
|
|
return 1
|
|
elif ql < 82:
|
|
return 2
|
|
elif ql < 129:
|
|
return 3
|
|
elif ql < 177:
|
|
return 4
|
|
elif ql < 201:
|
|
return 5
|
|
elif ql < 226:
|
|
return 6
|
|
else:
|
|
return 7
|