Initial Release of IGNCore version 2.5

This commit is contained in:
2021-08-09 13:18:56 +02:00
commit a83d98c47e
910 changed files with 224171 additions and 0 deletions
+139
View File
@@ -0,0 +1,139 @@
import re
from core.command_param_types import Const, Options, Int, Any, Time
from core.db import DB
from core.decorators import command, instance, setting
from core.setting_types import TimeSettingType
from core.tyrbot import Tyrbot
from modules.standard.loot.auction_strategy.auction_strategy import AuctionStrategy
@instance()
class AuctionController:
def __init__(self):
# noinspection PyTypeChecker
self.auction: AuctionStrategy = None
self.prepared = []
def inject(self, registry):
self.db: DB = registry.get_instance("db")
self.bot: Tyrbot = registry.get_instance("bot")
def pre_start(self):
self.db.shared.exec("CREATE TABLE IF NOT EXISTS auction_log ("
"auction_id INT PRIMARY KEY AUTO_INCREMENT, "
"item_ref VARCHAR(255) NOT NULL, "
"item_name VARCHAR(255) NOT NULL, "
"winner_id BIGINT NOT NULL, "
"auctioneer_id BIGINT NOT NULL, "
"time INT NOT NULL, "
"winning_bid INT NOT NULL, "
"second_highest_bid INT NOT NULL)")
self.db.create_view("auction_log")
@setting(name="auction_length", value="90s", description="Regular auction length in seconds")
def auction_length(self):
return TimeSettingType()
@setting(name="auction_announce_interval", value="15s", description="Auction announce interval")
def auction_announce_interval(self):
return TimeSettingType()
@command(command="auction", params=[], description="Show auction status",
access_level="guest")
def auction_cmd(self, _):
if not self.is_auction_running():
return "No auction running."
return self.auction.get_auction_list()
@command(command="auction",
params=[Const("prepare"), Const("clear")],
description="Clear the list of prepared items",
access_level="moderator", sub_command="modify")
def auction_prepare_clear(self, _, _1, _2):
self.prepared = []
return "The List has been cleared. Currently there are no prepared items."
@command(command="auction",
params=[Const("prepare"), Any("items")],
description="Prepare items for an auction",
access_level="moderator", sub_command="modify")
def auction_prepare(self, _, _1, items):
items = items.replace("'", '"')
items2 = re.findall(r"(([^<]+)?<a href=[\"\']itemref://(\d+)/(\d+)/(\d+)[\"\']>([^<]+)</a>([^<]+)?)", items)
if items2:
for item in items2:
self.prepared.append(item)
else:
self.prepared.append(items)
prep = ""
for item in self.prepared:
if prep == "":
if isinstance(item, tuple):
prep = item[0]
else:
prep = item
else:
if isinstance(item, tuple):
prep += ", " + item[0]
else:
prep += ", " + item
return "Currently prepared items: " + prep
@command(command="auction",
params=[Const("start"), Time("duration", is_optional=True)],
description="Start an auction, with the items added by auction prepare",
access_level="moderator", sub_command="modify")
def auction_start_cmd(self, request, _, duration):
if self.is_auction_running():
return "Auction already running."
if not self.prepared:
return "You prepared no items"
self.auction = AuctionStrategy()
for item in self.prepared:
if isinstance(item, tuple):
self.auction.add_item(item[0])
else:
self.auction.add_item(item)
self.prepared = []
auction_length = duration or self.auction_length().get_value()
announce_interval = self.auction_announce_interval().get_value()
return self.auction.start(request.sender, auction_length, announce_interval)
@command(command="auction", params=[Options(["cancel"])], description="Cancel ongoing auction",
access_level="moderator", sub_command="modify")
def auction_cancel_cmd(self, request, _):
if not self.is_auction_running():
return "No auction running."
result = self.auction.cancel(request.sender)
self.auction = None
return result
@command(command="auction", params=[Options(["end"])], description="end ongoing auction",
access_level="moderator", sub_command="modify")
def auction_cancel_cmd(self, request, _):
if not self.is_auction_running():
return "No auction running."
result = self.auction.cancel(request.sender)
self.auction = None
return result
@command(command="auction", params=[Const("bid"),
Int("amount", is_optional=True),
Const("all", is_optional=True),
Int("item_index", is_optional=True)],
description="Bid on an item", access_level="guest")
def auction_bid_cmd(self, request, _, amount, all_amount, item_index):
if not self.is_auction_running():
return "No auction running."
self.bot.send_mass_message(request.sender.char_id,
self.auction.add_bid(request.sender, all_amount or amount, item_index, request))
def is_auction_running(self):
return self.auction and self.auction.is_running
@@ -0,0 +1,342 @@
import re
import time
from core.chat_blob import ChatBlob
from core.db import DB
from core.registry import Registry
from core.sender_obj import SenderObj
from core.text import Text
from modules.core.accounting.services.account_service import AccountService
from modules.raidbot.raid.raidbot_controller import Raider
class AuctionBid:
def __init__(self, sender: SenderObj, account, current_amount, max_amount):
self.sender = sender
self.account = account
self.current_amount = current_amount
self.max_amount = max_amount
def __str__(self):
return self.__dict__.__str__()
class AuctionStrategy:
def __init__(self):
self.bot = Registry.get_instance("bot")
self.db: DB = Registry.get_instance("db")
self.text: Text = Registry.get_instance("text")
self.account_service: AccountService = Registry.get_instance("account_service")
self.job_scheduler = Registry.get_instance("job_scheduler")
self.raid_controller = None
self.raid_controller = Registry.get_instance("raidbot_controller", is_optional=True)
self.auction_start_time = None
self.auction_end_time = None
self.announce_interval = None
self.is_started = False
self.items = dict()
self.winning_bids = dict()
self.next_item_index = 1
# noinspection PyTypeChecker
self.auctioneer: SenderObj = None
self.job_id = None
self.is_running = False
def start(self, sender: SenderObj, duration, announce_interval):
if not self.items:
return "Could not find any items to start auction."
self.is_started = True
self.auction_start_time = int(time.time())
self.auctioneer = sender
self.auction_end_time = self.auction_start_time + duration
self.is_running = True
self.announce_interval = announce_interval
if len(self.items) > 1:
items = ""
for i, item in self.items.items():
winning = ""
if self.winning_bids.get(i, None):
winning = f"(<highlight>{self.winning_bids[i].current_amount}</highlight>)"
items += f"{i}. {item} {winning}\n"
msg = self.format_auction(f"{items}\n"
f"» {self.text.paginate_single(self.get_auction_list())}")
self.spam_raid_message(msg)
else:
item_index = list(self.items.keys())[0]
item = self.items[item_index]
sql = "SELECT winning_bid FROM auction_log WHERE item_name LIKE ? ORDER BY time DESC LIMIT 5"
bids = self.db.query(sql, [item])
if bids:
avg_win_bid = int(sum(map(lambda x: x.winning_bid, bids)) / len(bids))
else:
avg_win_bid = 0
bid_link = self.get_auction_list()
bid_link = self.text.paginate_single(ChatBlob("Click to bid", bid_link.msg))
msg = self.format_auction(f"1. {item}\n"
f"Average winning bid: <highlight>{avg_win_bid}<end>\n"
f"» {bid_link}")
self.spam_raid_message(msg)
self.create_next_announce_job()
def cancel(self, _):
self.cancel_job()
self.is_running = False
return "The Auction got cancelled."
def add_item(self, item):
self.items[self.next_item_index] = item
self.next_item_index += 1
return self.next_item_index
def remove_item(self, item_id):
del self.items[item_id]
del self.winning_bids[item_id]
def add_bid(self, sender: SenderObj, bid_amount, item_index, request):
item_index = item_index or 1
item = self.items.get(item_index, None)
if not item:
return "No item at given index."
if bid_amount == 0:
return "You tried to bid 0 points. seriously?"
account = self.account_service.get_account(sender.char_id)
main = account.main
if self.raid_controller:
raider: Raider = self.raid_controller.is_in_raid(main)
if type(raider) == Raider:
if not raider.is_active:
self.bot.send_mass_message(request.sender.char_id,
"You are not participating in the raid, and cannot add to the loot.")
return
elif raider is None:
self.bot.send_mass_message(request.sender.char_id,
"You are not participating in the raid, and cannot add to the loot.")
return
if not account:
return "You do not have an active account with this bot."
elif account.disabled:
return "Your account has been frozen. Contact an admin."
points_used = self.get_points_used(main, item_index)
points_available = account.points - points_used
if points_available == 0:
return "You got 0 points... no bids for you."
if not bid_amount:
return "You must specify an amount to bid."
if isinstance(bid_amount, str) and bid_amount.lower() == "all":
bid_amount = points_available
if bid_amount > points_available:
request.reply(f"You dont have enough points. Using {points_available:d} (All points you have)")
bid_amount = points_available
current_amount = 0
winning_bid = self.winning_bids.get(item_index, None)
if winning_bid:
if winning_bid.sender.char_id == sender.char_id:
return "You're already holding the highest bid."
if bid_amount <= winning_bid.current_amount:
return f"Your bid of <highlight>{bid_amount:d}<end> points was not enough. " \
f"<highlight>{winning_bid.sender.name}<end> is currently winning with a " \
f"bid of <highlight>{winning_bid.current_amount:d}<end>."
elif bid_amount <= winning_bid.max_amount:
winning_bid.current_amount = bid_amount
return f"Your bid of <highlight>{bid_amount}<end> points was not enough. " \
f"<highlight>{winning_bid.sender.name}<end> is currently " \
f"winning with a bid of <highlight>{winning_bid.current_amount}<end>."
else:
current_amount = winning_bid.max_amount
self.bot.send_private_message(winning_bid.sender.char_id,
f"Your bid on {item} has been "
f"overtaken by <highlight>{sender.name}<end>.")
# increment 1 past current max bid
current_amount += 1
self.winning_bids[item_index] = AuctionBid(sender, account, current_amount, bid_amount)
if self.auction_end_time - time.time() < 10:
self.auction_end_time += 10
self.spam_raid_message(
f"<highlight>{sender.name}<end> now holds the leading "
f"bid for {item} with a bid of <highlight>{current_amount:d}<end>. [AS: +10 seconds]")
else:
self.spam_raid_message(
f"<highlight>{sender.name}<end> now holds the leading bid for {item} "
f"with a bid of <highlight>{current_amount:d}<end>.")
return f"Your max bid of <highlight>{bid_amount:d}<end> points for {item} has put you in the lead. " \
f"You have <highlight>{points_available - bid_amount:d}<end> points left for bidding."
def end(self):
self.cancel_job()
self.is_running = False
blob = ""
t = int(time.time())
# noinspection SqlInsertValues
sql = "INSERT INTO auction_log (" \
"item_ref, item_name, winner_id, auctioneer_id, " \
"time, winning_bid, second_highest_bid) " \
"VALUES (?,?,?,?,?,?,?)"
items = ""
for i, item in self.items.items():
winning_bid = self.winning_bids.get(i, None)
if winning_bid:
self.db.exec(sql, [item, item, winning_bid.sender.char_id, self.auctioneer.char_id, t,
winning_bid.current_amount, 0])
items += f"{i}. <highlight>{item}</highlight> (<highlight>{winning_bid.sender.name} » " \
f"{winning_bid.current_amount}P</highlight>)\n"
blob += "%d. %s, won by <highlight>%s<end> with <green>%d<end> points\n" % (
i, item, winning_bid.sender.name, winning_bid.current_amount)
main_id = self.account_service.get_main(winning_bid.sender.char_id).char_id
self.account_service.rem_pts(main_id,
winning_bid.current_amount,
f"won {item}",
self.auctioneer.char_id)
else:
items += f"{i}. <highlight>{item}</highlight> (<red>FFA</red>)\n"
blob += "%d. %s, no bids made\n" % (i, item)
result_blob = self.text.paginate_single(ChatBlob("The Auction results", blob))
msg = self.format_auction(f"{items}"
f"» {result_blob}")
self.spam_raid_message(msg)
def remove_bid(self, char_id, item_id):
pass
def spam_raid_message(self, message):
self.bot.send_private_channel_message(message, fire_outgoing_event=False)
def get_auction_list(self):
blob = ""
for i, item in self.items.items():
if item[:2] == "<a" and item[-4:] == "</a>":
item = re.findall(r"(([^<]+)?<a href=[\"\']itemref://(\d+)/(\d+)/(\d+)[\"\']>([^<]+)</a>([^<]+)?)",
item)
img = ""
if isinstance(item[0], tuple):
imgid = self.db.query_single("SELECT icon from aodb where lowid=? and highid=?",
[item[0][2], item[0][3]])
if imgid is not None:
img = self.text.make_image(imgid.get("icon")) + " - "
blob += "%d. %s%s" % (i, img, item[0][0])
else:
img = ""
blob += f"{i:d}. {img}{item}"
winning_bid = self.winning_bids.get(i, None)
if winning_bid:
blob += f"<br><tab><highlight>{winning_bid.sender.name}<end> has the " \
f"winning bid of <highlight>{winning_bid.current_amount:d}<end>\n["
blob += self.text.make_chatcmd("bid +1", f"/tell <myname> bid {winning_bid.current_amount + 1} {i}")
blob += "]<tab>["
blob += self.text.make_chatcmd("bid +10", f"/tell <myname> bid {winning_bid.current_amount + 10} {i}")
blob += "]<tab>["
blob += self.text.make_chatcmd("bid +25", f"/tell <myname> bid {winning_bid.current_amount + 25} {i}")
blob += "]<tab>["
blob += self.text.make_chatcmd("bid +100", f"/tell <myname> bid {winning_bid.current_amount + 100} {i}")
blob += "]<tab>["
blob += self.text.make_chatcmd("bid +500", f"/tell <myname> bid {winning_bid.current_amount + 500} {i}")
blob += "]<tab>["
blob += self.text.make_chatcmd("bid Max", f"/tell <myname> bid all {i}")
blob += "]\n────────────────────────────────\n"
else:
blob += "<br><tab><green>No bidders<end>\n["
blob += self.text.make_chatcmd("bid 1", f"/tell <myname> bid 1 {i:d}")
blob += "]<tab>["
blob += self.text.make_chatcmd("bid 10", f"/tell <myname> bid 10 {i:d}")
blob += "]<tab>["
blob += self.text.make_chatcmd("bid 25", f"/tell <myname> bid 25 {i:d}")
blob += "]<tab>["
blob += self.text.make_chatcmd("bid 100", f"/tell <myname> bid 100 {i:d}")
blob += "]<tab>["
blob += self.text.make_chatcmd("bid 500", f"/tell <myname> bid 500 {i:d}")
blob += "]<tab>["
blob += self.text.make_chatcmd("bid Max", f"/tell <myname> bid all {i:d}")
blob += "]\n────────────────────────────────\n"
return ChatBlob(f"The Auction list ({len(self.items):d})", blob)
def get_points_used(self, main_id, item_index):
points_used = 0
for index, bid in self.winning_bids.items():
if index != item_index and bid.account.char_id == main_id:
points_used += bid.max_amount
return points_used
def auction_announce(self, _):
time_left = self.time_left()
if time_left <= 0:
self.end()
return
item_count = len(self.items)
if item_count > 1:
items = ""
for i, item in self.items.items():
winning = ""
if self.winning_bids.get(i, None):
winning = f"(<highlight>{self.winning_bids[i].sender.name} » " \
f"{self.winning_bids[i].current_amount}P</highlight>)"
items += f"{i}. {item} {winning}\n"
msg = self.format_auction(f"{items}\n"
f"» {self.text.paginate_single(self.get_auction_list())}\n"
f"<highlight>{time_left}</highlight> seconds left")
else:
item_index = list(self.items.keys())[0]
item = self.items[item_index]
winning_bid = self.winning_bids.get(item_index, None)
if winning_bid:
winner = f"<highlight>{winning_bid.sender.name}<end> now holds the " \
f"leading bid with a bid of <highlight>{winning_bid.current_amount:d}<end>."
else:
winner = "No bids made."
msg = self.format_auction(f"1. {item}\n"
f"{winner}\n"
f"» {self.text.paginate_single(self.get_auction_list())}\n"
f"<highlight>{time_left}</highlight> seconds left")
self.spam_raid_message(msg)
self.create_next_announce_job()
def time_left(self):
t = int(time.time())
time_left = self.auction_end_time - t
if time_left < 0:
time_left = 0
return time_left
def create_next_announce_job(self):
t = int(time.time())
time_remaining = self.auction_end_time - t
mod = time_remaining % self.announce_interval
if mod == 0:
mod = self.announce_interval
next_job_t = t + mod
self.job_id = self.job_scheduler.scheduled_job(self.auction_announce, next_job_t)
def cancel_job(self):
if self.job_id:
self.job_scheduler.cancel_job(self.job_id)
self.job_id = None
def format_auction(self, message):
return f"<yellow>\n" \
f"────────[ Auction ]────────\n" \
f"{message}\n" \
f"────────[ Auction ]────────</yellow>"
+31
View File
@@ -0,0 +1,31 @@
from core.dict_object import DictObject
from core.registry import Registry
class LootItem:
def __init__(self, item, comment, count=1):
self.item = item
self.comment = comment
self.bidders = []
self.count = count
def get_item_str(self):
if isinstance(self.item, DictObject):
item_name = "%s (%s)" % (self.item.name, self.comment) if self.comment else self.item.name
text = Registry.get_instance("text")
return text.make_item(self.item.low_id, self.item.high_id, self.item.ql, item_name)
else:
item_name = "%s (%s)" % (self.item, self.comment) if self.comment else self.item
return item_name
def __str__(self):
return "%s %d" % (self.get_item_str(), self.count)
class AuctionItem(LootItem):
def __init__(self, item, comment, auctioneer_id, count=1):
super().__init__(item, comment, count)
self.auctioneer_id = auctioneer_id
self.winner_id = None
self.winning_bid = 0
self.second_highest = 0
+403
View File
@@ -0,0 +1,403 @@
import re
import secrets
import time
from collections import OrderedDict
from core.chat_blob import ChatBlob
from core.command_alias_service import CommandAliasService
from core.command_param_types import Const, Int, Any
from core.db import DB
from core.decorators import instance, command, timerevent
from core.setting_service import SettingService
from core.text import Text
from core.tyrbot import Tyrbot
from modules.core.accounting.services.account_service import AccountService
from modules.raidbot.raid.raidbot_controller import Raider
from modules.standard.items.items_controller import ItemsController
from modules.standard.loot.item_types import LootItem
from modules.standard.raid.leader_controller import LeaderController
@instance()
class LootController:
NOT_LEADER_MSG = "Error! You must be raid leader, or have higher access " \
"level than the raid leader to use this command."
def __init__(self):
self.loot_list = OrderedDict()
self.last_modify = None
def inject(self, registry):
self.bot: Tyrbot = registry.get_instance("bot")
self.db: DB = registry.get_instance("db")
self.text: Text = registry.get_instance("text")
self.leader_controller: LeaderController = registry.get_instance("leader_controller", is_optional=True)
self.setting_service: SettingService = registry.get_instance("setting_service")
self.items_controller: ItemsController = registry.get_instance("items_controller")
self.raid_controller = None
self.raid_controller = registry.get_instance("raidbot_controller", is_optional=True)
self.account_service: AccountService = registry.get_instance("account_service")
self.alts_service: AccountService = registry.get_instance("account_service")
self.alias: CommandAliasService = registry.get_instance("command_alias_service")
def pre_start(self):
self.db.load_sql_file(self.module_dir + "/raid_loot.sql", pre_optimized=True)
self.db.create_view("raid_loot")
self.alias.add_alias("add", "loot add")
self.alias.add_alias("rem", "loot rem")
self.alias.add_alias("remove", "loot remo")
self.alias.add_alias("flatroll", "loot roll")
self.alias.add_alias("result", "loot roll")
self.alias.add_alias("results", "loot roll")
self.alias.add_alias("win", "loot roll")
@command(command="loot", params=[], description="Show the list of added items", access_level="member")
def loot_cmd(self, _):
if not self.loot_list:
return "Loot list is empty."
return self.get_loot_list()
@command(command="loot", params=[Const("edit")], description="Show the list of added items", access_level="leader",
sub_command="modify")
def loot_edit_cmd(self, _, _1):
if not self.loot_list:
return "Loot list is empty."
return self.get_loot_list(edit=True)
@command(command="loot", params=[Const("clear")], description="Clear all loot", access_level="leader",
sub_command="modify")
def loot_clear_cmd(self, request, _):
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
return LeaderController.NOT_LEADER_MSG
if self.loot_list:
self.loot_list.clear()
self.last_modify = None
self.bot.send_private_channel_message("Loot list cleared.")
else:
return "Loot list is already empty."
@command(command="loot", params=[Const("remitem"), Int("item_index")],
description="Remove an existing loot item", access_level="leader", sub_command="modify")
def loot_rem_item_cmd(self, request, _, item_index: int):
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
return LeaderController.NOT_LEADER_MSG
if not self.loot_list:
return "Loot list is empty."
try:
if self.loot_list[item_index]:
self.last_modify = int(time.time())
self.bot.send_private_channel_message(
"Removed %s from loot list." % self.loot_list.pop(item_index).get_item_str())
else:
return "Item error."
except KeyError:
return "Wrong index given."
@command(command="loot", params=[Const("increase"), Int("item_index")], description="Increase item count",
access_level="leader", sub_command="modify")
def loot_increase_item_cmd(self, request, _, item_index: int):
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
return LeaderController.NOT_LEADER_MSG
if not self.loot_list:
return "Loot list is empty."
try:
loot_item = self.loot_list[item_index]
if loot_item:
loot_item.count += 1
self.last_modify = int(time.time())
self.bot.send_private_channel_message(
"Increased item count for %s to %d." % (loot_item.get_item_str(), loot_item.count))
else:
return "Item error."
except KeyError:
return "Wrong index given."
@command(command="loot", params=[Const("decrease"), Int("item_index")], description="Decrease item count",
access_level="leader", sub_command="modify")
def loot_decrease_item_cmd(self, request, _, item_index: int):
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
return LeaderController.NOT_LEADER_MSG
if not self.loot_list:
return "Loot list is empty."
try:
loot_item = self.loot_list[item_index]
if loot_item:
loot_item.count = loot_item.count - 1 if loot_item.count > 1 else 1
self.last_modify = int(time.time())
self.bot.send_private_channel_message(
"Decreased item count for %s to %d." % (loot_item.get_item_str(), loot_item.count))
else:
return "Item error."
except KeyError:
return "Wrong index given."
@command(command="loot", params=[Const("add"), Int("item_index")], description="Add yourself to item",
access_level="member")
def loot_add_to_cmd(self, request, _, item_index: int):
main = self.alts_service.get_account(request.sender.char_id)
if self.raid_controller:
raider: Raider = self.raid_controller.is_in_raid(main.char_id)
if type(raider) == Raider:
if not raider.is_active:
self.bot.send_mass_message(request.sender.char_id,
"You are not participating in the raid, and cannot add to the loot.")
return
elif raider is None:
self.bot.send_mass_message(request.sender.char_id,
"You are not participating in the raid, and cannot add to the loot.")
return
try:
loot_item = self.loot_list[item_index]
old_item = self.is_already_added(request.sender.name)
if old_item:
if old_item.get_item_str() == loot_item.get_item_str():
name = "You have" if request.channel == "msg" else request.sender.name
self.bot.send_mass_message(request.sender.char_id,
"%s already added to %s." % (name, loot_item.get_item_str()))
old_item.bidders.remove(request.sender.name)
loot_item.bidders.append(request.sender.name)
self.last_modify = int(time.time())
if old_item is not None:
text = "moved from %s to %s." % (old_item.get_item_str(), loot_item.get_item_str())
self.bot.send_mass_message(request.sender.char_id, "You have %s" % text)
self.bot.send_private_channel_message(request.sender.name + " " + text)
else:
text = "added to %s." % loot_item.get_item_str()
self.bot.send_mass_message(request.sender.char_id, "You have %s" % text)
self.bot.send_private_channel_message(request.sender.name + " " + text)
except KeyError:
return "Wrong index given."
@command(command="loot", params=[Const("rem")], description="Remove yourself from item", access_level="member")
def loot_rem_from_cmd(self, request, _):
try:
loot_item = self.is_already_added(request.sender.name)
if loot_item is not None:
loot_item.bidders.remove(request.sender.name)
self.last_modify = int(time.time())
text = "removed from %s." % loot_item.get_item_str()
self.bot.send_private_message(request.sender.char_id, "You were %s" % text)
self.bot.send_private_channel_message(request.sender.name + " was " + text)
else:
return "You are not added to any loot."
except KeyError:
return "Wrong index given."
@command(command="loot", params=[Const("roll")], description="Roll all loot", access_level="leader",
sub_command="modify")
def loot_roll_cmd(self, request, _):
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
return LeaderController.NOT_LEADER_MSG
if self.loot_list:
blob = ""
remove = []
for i, loot_item in self.loot_list.items():
winners = []
if loot_item.bidders:
if len(loot_item.bidders) <= loot_item.count:
winners = loot_item.bidders.copy()
loot_item.count -= len(loot_item.bidders)
loot_item.bidders = []
else:
for j in range(0, loot_item.count):
winner = secrets.choice(loot_item.bidders)
winners.append(winner)
loot_item.bidders.remove(winner)
loot_item.count = loot_item.count - 1 if loot_item.count > 0 else 0
for user in winners:
self.account_service.add_log(self.account_service.character_service.resolve_char_to_id(user),
"loot",
f"{loot_item.get_item_str()}",
request.sender.char_id)
blob += "%d. %s\n" % (i, loot_item.get_item_str())
blob += " | Winners: <red>%s<end>\n\n" % '<end>, <red>'.join(winners)
if loot_item.count == 0:
remove.append(i)
for i in remove:
self.loot_list.pop(i)
msg = ChatBlob("Roll results", blob)
msg.page_prefix = "Time is up! "
self.bot.send_private_channel_message(msg if len(blob) > 0 else "No one was added to any loot")
if self.loot_list:
count = 1
for key in sorted(list(self.loot_list.keys())):
if self.loot_list[key].count <= 0:
del self.loot_list[key]
else:
loot_item = self.loot_list[key]
del self.loot_list[key]
self.loot_list[count] = loot_item
count += 1
else:
return "No loot to roll."
@command(command="loot", params=[Const("addraiditem"), Int("raid_item_id"), Int("item_count")],
description="Add item from pre-defined raid to loot list", access_level="leader", sub_command="modify")
def loot_add_raid_item(self, request, _, raid_item_id: int, item_count: int):
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
return LeaderController.NOT_LEADER_MSG
sql = "SELECT r.name, r.comment, r.ql, a.lowid AS low_id, a.highid AS high_id FROM aodb a " \
"LEFT JOIN raid_loot r ON (a.name = r.name AND a.highql >= r.ql) " \
"WHERE r.id = ? LIMIT 1"
item = self.db.query_single(sql, [raid_item_id])
if item:
self.add_item_to_loot(item, item.comment, item_count)
self.bot.send_private_channel_message("Added %s to loot list." % item.name)
else:
return "Failed to add item with ID %s." % raid_item_id
@command(command="loot", params=[Const("addraid"), Any("raid"), Any("category")],
description="Add all loot from pre-defined raid", access_level="leader", sub_command="modify")
def loot_add_raid_loot(self, request, _, raid: str, category: str):
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
return LeaderController.NOT_LEADER_MSG
items = self.db.query(
"SELECT r.raid, r.category, r.id, r.ql, r.name, r.comment, r.multiloot, "
"a.lowid AS low_id, "
"a.highid AS high_id, a.icon "
"FROM raid_loot r "
"LEFT JOIN aodb a "
"ON (r.name = a.name AND r.ql <= a.highql) "
"WHERE r.raid = ? AND r.category = ? "
"ORDER BY r.name",
[raid, category]
)
if items:
for item in items:
self.add_item_to_loot(item, item.comment, item.multiloot)
self.bot.send_private_channel_message("%s table was added to loot." % category)
else:
return "%s does not have any items registered in loot table." % category
@command(command="loot",
params=[Const("additem", is_optional=True), Int("item"), Int("item_count", is_optional=True)],
description="Add an item to loot list by item id", access_level="leader", sub_command="modify")
def loot_add_item_id_cmd(self, request, _, item_id, item_count: int):
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
return LeaderController.NOT_LEADER_MSG
if item_count is None:
item_count = 1
item = self.items_controller.get_by_item_id(item_id)
if not item:
return "Could not find item with ID <highlight>%d<end>." % item_id
self.add_item_to_loot(item, item_count=item_count)
self.bot.send_private_channel_message("%s was added to loot list." % item.name)
@command(command="loot",
params=[Const("additem", is_optional=True), Any("item"), Int("item_count", is_optional=True)],
description="Add an item to loot list", access_level="leader", sub_command="modify")
def loot_add_item_cmd(self, request, _, item, item_count: int):
if not self.leader_controller.can_use_command(request.sender.char_id) if self.leader_controller else False:
return LeaderController.NOT_LEADER_MSG
loot = ""
if item_count is None:
item_count = 1
item = item.replace("&#39;", "'")
items = re.findall(r"(([^<]+)?<a href=[\"\']itemref://(\d+)/(\d+)/(\d+)[\"\']>([^<]+)</a>([^<]+)?)", item)
if items and item_count == 1:
for item in items:
item = self.text.make_item(int(item[2]), int(item[3]), int(item[4]), item[5])
if loot != "":
loot += ", " + item
else:
loot += item
self.add_item_to_loot(item)
else:
loot += item
self.add_item_to_loot(item, item_count=item_count)
self.bot.send_private_channel_message("<highlight>%s<end> was added to loot list." % loot)
@timerevent(budatime="1h",
description="Periodically check when loot list was last modified, and clear it "
"if last modification was done 1+ hours ago")
def loot_clear_event(self, _1, _2):
if self.loot_list and self.last_modify:
if int(time.time()) - self.last_modify > 3600 and self.loot_list:
self.last_modify = None
self.loot_list = OrderedDict()
self.bot.send_org_message("Loot was last modified more than 1 hour ago, list has been cleared.")
self.bot.send_private_channel_message(
"Loot was last modified more than 1 hour ago, list has been cleared.")
def is_already_added(self, name: str):
for i, loot_item in self.loot_list.items():
if name in loot_item.bidders:
return loot_item
return None
def add_item_to_loot(self, item, comment=None, item_count=1):
existing_item = next((loot_item for x, loot_item in self.loot_list.items() if loot_item.item == item), None)
if existing_item:
existing_item.count += 1
else:
# this prevents loot items from being re-numbered when items are removed
end_index = list(self.loot_list.keys())[-1] + 1 if len(self.loot_list) > 0 else 1
self.loot_list[end_index] = LootItem(item, comment, item_count)
self.last_modify = int(time.time())
def get_loot_list(self, edit=False):
blob = ""
remove = self.text.make_chatcmd("Remove from rolls", "/tell <myname> loot rem")
blob += f"[{remove}]\n\n"
for i, loot_item in self.loot_list.items():
bidders = loot_item.bidders
img = ""
if loot_item.get_item_str()[:2] == "<a" and loot_item.get_item_str()[-4:] == "</a>":
item = re.findall(r"(([^<]+)?<a href=[\"\']itemref://(\d+)/(\d+)/(\d+)[\"\']>([^<]+)</a>([^<]+)?)",
loot_item.get_item_str())
imgid = self.db.query_single("SELECT icon from aodb where lowid=? or highid=?",
[item[0][2], item[0][3]])
if imgid is not None:
img = self.text.make_image(imgid.get("icon")) + " - "
blob += "%d. %s%s " % (i, img, item[0][0])
else:
blob += "%d. %s " % (i, loot_item.get_item_str())
blob += f"x{loot_item.count} [{self.text.make_chatcmd('Add', f'/tell <myname> loot add {i}')}]\n"
blob += ""
if edit:
blob += f"<yellow>[ {self.text.make_tellcmd('+1', f'loot increase {i}')} | " \
f"{self.text.make_tellcmd('-1', f'loot decrease {i}')} ]" \
f"[ {self.text.make_tellcmd('REM', f'loot remitem {i}')} ]</yellow>\n\n"
else:
if len(bidders) > 0:
blob += "<yellow>%s<end>\n\n" % ', '.join(bidders)
else:
blob += "<yellow>None added<end>\n\n"
return ChatBlob("Loot (%d)" % len(self.loot_list), blob)
@@ -0,0 +1,398 @@
from core.chat_blob import ChatBlob
from core.command_param_types import Options
from core.db import DB
from core.decorators import instance, command, setting
from core.setting_service import SettingService
from core.setting_types import BooleanSettingType
from core.text import Text
@instance()
class LootListsController:
def __init__(self):
self.categories = {
"s7": "Sector 7",
"s13": "Sector 13",
"s28": "Sector 28",
"s35": "Sector 35",
"s42": "Sector 42",
"db": "DustBrigade",
"aquarius": "Aquarius",
"sagittarius": "Sagittarius",
"taurus": "Taurus",
"libra": "Libra",
"capricorn": "Capricorn",
"gemini": "Gemini",
"virgo": "Virgo",
"cancer": "Cancer",
"pisces": "Pisces",
"scorpio": "Scorpio",
"aries": "Aries",
"leo": "Leo",
"tnh": "The Night Heart",
"barmor": "Beast Armor",
"bweapons": "Beast Weapons",
"bstars": "Stars",
"sb": "Shadowbreeds",
"alba": "Albtraum",
"samples": "Samples",
"ancients": "Ancients",
"c&cm": "Crystals & Crystalised Memories",
"pbc": "Pocket Boss Crystals",
"r&pu": "Rings and Preservation Units",
"symbs": "Symbiants",
"spirits": "Spirits",
"pgems": "Profession Gems",
"gen": "General",
"db1": "DB1",
"db2": "DB2",
"db3": "DB3",
"ncu": "HUD/NCU",
"gaunt": "Bastion",
"mitaar": "Mitaar",
"12m": "12Man",
"vortexx": "Vortexx",
"dbarmor": "DB Armor",
"util": "Util",
"poh": "Pyramid of Home",
"totwh": "Temple of Three Winds (HL)",
"binyacht": "Binyacht the Faithful",
"guardian": "Guardian of the Three",
"summoner": "The Immortal Summoner",
"lien": "Lien the Memory-Devourer",
"loremaster": "The Loremaster",
"nematet": "Nematet the Subjugator of Time",
"aegis": "Aegis of Tomorrow",
"gartua": "Gartua the Gate Guardian",
"aztur": "Aztur the Immortal",
"khalum": "Khalum the Weaver of Flesh",
"uklesh": "Uklesh the Beguiling",
"subh": "Condemned Subway (HL)",
"shiro": "Eliminator Shiro",
"eumen": "Eumenides",
"qets": "Queen of the Slums",
"psion": "The Psion",
"pbcr": "Primal Bloodcreeper",
"aneid": "Vergil Aeneid",
"abmouth": "Abmouth Supremus",
}
def inject(self, registry):
self.db: DB = registry.get_instance("db")
self.text: Text = registry.get_instance("text")
self.setting_service: SettingService = registry.get_instance("setting_service")
self.command_alias_service = registry.get_instance("command_alias_service")
def start(self):
self.command_alias_service.add_alias("aries", "pande aries")
self.command_alias_service.add_alias("aquarius", "pande aquarius")
self.command_alias_service.add_alias("leo", "pande leo")
self.command_alias_service.add_alias("virgo", "pande virgo")
self.command_alias_service.add_alias("cancer", "pande cancer")
self.command_alias_service.add_alias("gemini", "pande gemini")
self.command_alias_service.add_alias("libra", "pande libra")
self.command_alias_service.add_alias("pisces", "pande pisces")
self.command_alias_service.add_alias("capricorn", "pande capricorn")
self.command_alias_service.add_alias("scorpio", "pande scorpio")
self.command_alias_service.add_alias("taurus", "pande taurus")
self.command_alias_service.add_alias("sagittarius", "pande sagittarius")
self.command_alias_service.add_alias("tnh", "pande tnh")
self.command_alias_service.add_alias("s7", "apf s7")
self.command_alias_service.add_alias("s13", "apf s13")
self.command_alias_service.add_alias("s28", "apf s28")
self.command_alias_service.add_alias("s35", "apf s35")
self.command_alias_service.add_alias("s42", "apf s35")
self.command_alias_service.add_alias("mitaar", "xan mitaar")
self.command_alias_service.add_alias("12m", "xan 12m")
self.command_alias_service.add_alias("vortexx", "xan vortexx")
self.command_alias_service.add_alias("alba", "albtraum")
self.command_alias_service.add_alias("lt", "loottables")
self.command_alias_service.add_alias("raids", "loottables")
self.command_alias_service.add_alias("ltables", "loottables")
self.command_alias_service.add_alias("loots", "loottables")
@setting(name="use_item_icons", value="True", description="Use icons when building loot list")
def use_item_icons(self):
return BooleanSettingType()
@command(command="loottables", params=[], description="Show all Loottables", access_level="member")
def loottables_cmd(self, _):
return ChatBlob("Loot Tables", self.build_overview())
# #
# APF #
# #
@command(command="apf",
params=[Options(["s7", "s13", "s28", "s35", "s42"])],
description="Get list of items from APF", access_level="member")
def apf_loot_cmd(self, _, category):
add_all = True if category not in ["s7", "s42"] else False
category = self.get_real_category_name(category)
items = self.get_items("APF", category)
if items:
return ChatBlob("%s loot table" % category, self.build_list(items, "APF", category, add_all))
else:
return "No loot registered for <highlight>%s<end>." % category
@command(command="apf", params=[], description="Get list of items from APF", access_level="member")
def apf_tables_cmd(self, _):
return ChatBlob("APF loot tables", self.build_overview("APF", "apf"))
# #
# Albtraum #
# #
@command(command="albtraum", params=[],
description="Get list of items from Albtraum", access_level="member")
def albtraum_loot_cmd(self, _):
return ChatBlob("Albtraum loot tables", self.build_overview("Albtraum", "albtraum"))
@command(command="albtraum", params=[Options(["c&cm", "pbc", "r&pu", "ancients", "samples"])],
description="Get list of items from Albtraum", access_level="member")
def albtraum_tables_cmd(self, _, category):
category = self.get_real_category_name(category)
items = self.get_items("Albtraum", category)
if items:
return ChatBlob("%s loot table" % category, self.build_list(items, "Albtraum", category))
else:
return "No loot registered for <highlight>%s<end>." % category
# #
# Pandemonium #
# #
@command(command="pande",
params=[Options(["bweapons", "barmor", "bstars", "aries", "aquarius", "leo",
"virgo", "cancer", "gemini", "libra", "pisces", "capricorn",
"scorpio", "taurus", "sagittarius", "tnh", "gaunt", "sb"])],
description="Get list of items from Pandemonium", access_level="member")
def pande_loot_cmd(self, _, category_name):
category = self.get_real_category_name(category_name)
items = self.get_items("Pande", category)
if items:
return ChatBlob("%s loot table" % category, self.build_list(items, "Pande", category))
else:
return "No loot registered for <highlight>%s<end>." % category_name
@command(command="pande", params=[], description="Get list of items from Pandemonium", access_level="member")
def pande_tables_cmd(self, _):
return ChatBlob("Pandemonium loot tables", self.build_overview("Pande", "pande"))
# #
# Dust Brigade #
# #
@command(command="db", params=[Options(["db1", "db2", "db3", "dbarmor", "util"])],
description="Get list of items from DustBrigade", access_level="member")
def db_loot_cmd(self, _, category):
category = self.get_real_category_name(category)
items = self.get_items("DustBrigade", category)
if items:
return ChatBlob("%s loot table" % category, self.build_list(items, "DustBrigade", category))
else:
return "No loot registered for <highlight>%s<end>." % category
@command(command="db", params=[], description="Get list of items from DustBrigade", access_level="member")
def db_tables_cmd(self, _):
return ChatBlob("DustBrigade loot tables", self.build_overview("DustBrigade", "db"))
# #
# Xan #
# #
@command(command="xan", params=[Options(["mitaar", "12m", "vortexx"]),
Options(["gen", "symbs", "spirits", "gem"], is_optional=True)],
description="Get list of items from Xan", access_level="member")
def xan_loot_cmd(self, _, category, sub):
category = self.get_real_category_name(category)
sub = self.get_real_category_name(sub)
blob = ""
if not sub:
blob += self.build_list(self.get_items(category, "General"), category, "General")
blob += self.build_list(self.get_items(category, "Symbiants"), category, "Symbiants")
blob += self.build_list(self.get_items(category, "Spirits"), category, "Spirits")
else:
blob += self.build_list(self.get_items(category, sub), category, sub)
return ChatBlob("%s loot table" % category, blob)
@command(command="xan", params=[], description="Get list of items from Xan", access_level="member")
def xan_tables_cmd(self, _):
blob = ""
raids = ["Mitaar", "Vortexx", "12Man"]
for raid in raids:
show_loot = self.text.make_chatcmd(
"Loot table", "/tell <myname> xan %s" % self.get_real_category_name(raid, True))
sql = "SELECT COUNT(*) AS count FROM raid_loot WHERE raid = ?"
count = self.db.query_single(sql, [raid]).count
blob += "%s - %s items\n" % (raid, count)
blob += " └ [%s]\n\n" % show_loot
return ChatBlob("Xan loot tables", blob)
# #
# Pyramid of Home#
# #
@command(command="poh", params=[Options(["gen", "ncu"])],
description="Get list of items from Pyramid of Home", access_level="member")
def poh_loot_cmd(self, _, category_name):
category = self.get_real_category_name(category_name)
items = self.get_items("Pyramid of Home", category)
if items:
return ChatBlob("%s loot table" % category, self.build_list(items, "poh", category))
else:
return "No loot registered for <highlight>%s<end>." % category_name
@command(command="poh", params=[], description="Get list of items from Pyramid of Home", access_level="member")
def poh_tables_cmd(self, _):
return ChatBlob("Pyramid of Home loot tables", self.build_overview("Pyramid of Home", "poh"))
#########################################
# Temple of Three Winds (Highlevel) #
#########################################
@command(command="totwh", params=[Options(
["binyacht", "guardian", "summoner", "loremaster", "nematet", "aegis", "lien", "gartua", "aztur", "khalum",
"uklesh", "gen", "armor"])],
description="Get list of items from Temple of Three Winds", access_level="all")
def totwh_loot_cmd(self, _, category_name):
category = self.get_real_category_name(category_name)
items = self.get_items("Temple of Three Winds (HL)", category)
if items:
return ChatBlob("%s loot table" % category, self.build_list(items, "totwh", category))
else:
return "No loot registered for <highlight>%s<end>." % category_name
@command(command="totwh", params=[], description="Get list of items from Temple of Three Winds", access_level="all")
def totwh_tables_cmd(self, _):
return ChatBlob("Temple of Three Winds (HL) loot tables",
self.build_overview("Temple of Three Winds (HL)", "totwh"))
###############################
# Condemned Subway (raid) #
###############################
@command(command="subh", params=[Options(["shiro", "eumen", "qets", "psion", "pbcr", "aneid", "abmouth", "gen"])],
description="Get list of items from Condemned Subway (HL)", access_level="member")
def subh_loot_cmd(self, _, category_name):
category = self.get_real_category_name(category_name)
items = self.get_items("Condemned Subway (HL)", category)
if items:
return ChatBlob("%s loot table" % category, self.build_list(items, "subh", category))
else:
return "No loot registered for <highlight>%s<end>." % category_name
@command(command="subh", params=[], description="Get list of items from Condemned Subway (HL)",
access_level="member")
def subh_tables_cmd(self, _):
return ChatBlob("Condemned Subway (HL) loot tables", self.build_overview("Condemned Subway (HL)", "subh"))
def build_overview(self, name=None, cmd=None):
blob = ""
if name and cmd:
sql = "SELECT category FROM raid_loot WHERE raid = ? GROUP BY category"
raids = self.db.query(sql, [name])
for raid in raids:
show_loot = self.text.make_chatcmd(
"Loot table", "/tell <myname> %s %s" % (cmd, self.get_real_category_name(raid.category, True)))
sql = "SELECT COUNT(*) AS count FROM raid_loot WHERE category = ? and raid=?"
count = self.db.query_single(sql, [raid.category, name]).count
blob += "<highlight>%s<end> - %s items\n" % (raid.category, count)
blob += " └ [%s]\n\n" % show_loot
blob += "<pagebreak>"
if not name and not cmd:
raids = [
("Condemned Subway (HL)", "subh"),
("Temple of Three Winds (HL)", "totwh"),
("12Man", "xan 12m"),
("Vortexx", "xan vortexx"),
("Mitaar", "xan mitaar"),
(("APF", "Sector 7"), "apf s7"),
(("APF", "Sector 13"), "apf s13"),
(("APF", "Sector 28"), "apf s28"),
(("APF", "Sector 35"), "apf s35"),
("Albtraum", "albtraum"),
("DustBrigade", "db"),
("Pande", "pande"),
("Pyramid of Home", "poh")
]
for raid in raids:
title = raid[0][1] if isinstance(raid[0], tuple) else raid[0]
cmd = raid[1]
show_loot = self.text.make_chatcmd("Loot table", "/tell <myname> %s" % cmd)
blob += "<highlight>%s<end>\n" % title
blob += " └ [%s]\n\n" % show_loot
blob += "<pagebreak>"
return blob
# Raids available in AO:
# s7, s10, s13, s28, s35, s42, aquarius, virgo, sagittarius, beastweapons, beastarmor,
# beaststars, tnh, aries, leo, cancer, gemini, libra, pisces, taurus,
# capricorn, scorpio, tara, vortexx, mitaar, 12m, db1, db2, db3, poh,
# biodome, manex (collector), hollow islands, mercenaries
def build_list(self, items, raid=None, category=None, add_all=False):
blob = ""
if add_all:
blob += "%s items to loot list\n\n" % self.text.make_chatcmd(
"Add all", "/tell <myname> loot addraid %s %s" % (raid, category))
blob += "<header2>%s<end>\n" % category if category is not None else ""
for item in items:
item.id = self.text.make_item(item.low_id, item.high_id, item.ql, item.name)
if item.multiloot > 1:
single_link = self.text.make_chatcmd("Add to loot", "/tell <myname> loot %s 1" % item.id)
single_link1 = self.text.make_chatcmd("Add to auction", "/tell <myname> auction prepare %s " % item.id)
multi_link = self.text.make_chatcmd(
"Add x%d to loot" % item.multiloot, "/tell <myname> loot %s %d" % (item.id, item.multiloot))
multi_link2 = self.text.make_chatcmd(
"Add x%d to auction" % item.multiloot, "/tell <myname> auction prepare %s (ALL)" % item.id)
add_links = "└ [%s] [%s]<br> └ [%s] [%s (ALL) - One Winner]" % (
single_link, multi_link, single_link1, multi_link2)
else:
add_links = "└ [%s]<br> └ [%s]" % (
self.text.make_chatcmd("Add to loot", "/tell <myname> loot %s 1" % item.id),
self.text.make_chatcmd("Add to auction", "/tell <myname> auction prepare %s" % item.id))
comment = " (%s)" % item.comment if item.comment != "" else ""
if self.setting_service.get("use_item_icons").get_value():
item_link = self.text.make_item(item.low_id, item.high_id, item.ql, "<img src=rdb://%s>" % item.icon)
blob += "%s%s%s\n %s\n\n" % (item_link, item.name, comment, add_links)
else:
item_link = self.text.make_item(item.low_id, item.high_id, item.ql, item.name)
blob += "%s%s\n %s\n\n" % (item_link, comment, add_links)
blob += "<pagebreak>"
return blob
def get_items(self, raid, category):
return self.db.query(
"SELECT r.raid, r.category, r.id, r.ql, r.name, r.comment, "
"r.multiloot, a.lowid AS low_id, a.highid AS high_id, a.icon "
"FROM raid_loot r "
"LEFT JOIN aodb a "
"ON (r.high_id = a.highid OR (r.high_id = 0 AND r.name = a.name AND r.ql <= a.highql)) "
"WHERE r.raid = ? AND r.category = ? "
"ORDER BY r.name",
[raid, category]
)
def get_real_category_name(self, category, reverse=False):
if reverse:
return next((name for name, real_name in self.categories.items() if real_name == category), None)
else:
return self.categories[category] if category in list(self.categories.keys()) else None
+585
View File
@@ -0,0 +1,585 @@
# noinspection LongLineForFile
# noinspection LongLineForFile
# noinspection LongLineForFile
DROP TABLE IF EXISTS raid_loot;
CREATE TABLE raid_loot
(
id INT PRIMARY KEY AUTO_INCREMENT,
raid VARCHAR(30) NOT NULL,
category VARCHAR(50) NOT NULL,
ql INT NOT NULL,
name VARCHAR(255) NOT NULL,
high_id int default 0,
comment VARCHAR(255) NOT NULL,
multiloot INT NOT NULL
);
INSERT INTO raid_loot (raid, category, ql, name, comment, multiloot)
VALUES ('Vortexx', 'General', 300, 'Base NCU - Type 00 (0/6)', '', 1),
('Vortexx', 'General', 300, 'Nanodeck Activation Device', '', 1),
('Vortexx', 'General', 1, 'Multi Colored Xan Belt Tuning Device', '', 1),
('Vortexx', 'General', 1, 'Green Xan Belt Tuning Device', '', 1),
('Vortexx', 'General', 300, 'Xan Weapon Upgrade Device', '', 1),
('Vortexx', 'General', 1, 'Xan Defense Merit Board Base', '', 1),
('Vortexx', 'General', 1, 'Xan Combat Merit Board Base', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Waist Symbiant, Artillery Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Waist Symbiant, Control Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Waist Symbiant, Extermination Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Waist Symbiant, Infantry Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Waist Symbiant, Support Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Left Arm Symbiant, Artillery Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Left Arm Symbiant, Control Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Left Arm Symbiant, Extermination Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Left Arm Symbiant, Infantry Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Left Arm Symbiant, Support Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Right Wrist Symbiant, Artillery Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Right Wrist Symbiant, Control Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Right Wrist Symbiant, Extermination Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Right Wrist Symbiant, Infantry Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Right Wrist Symbiant, Support Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Ocular Symbiant, Artillery Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Ocular Symbiant, Control Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Ocular Symbiant, Extermination Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Ocular Symbiant, Infantry Unit Beta', '', 1),
('Vortexx', 'Symbiants', 300, 'Xan Ocular Symbiant, Support Unit Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Spirit of Right Wrist Offence - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Spirit of Right Wrist Weakness - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Left Limb Spirit of Essence - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Left Limb Spirit of Strength - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Left Limb Spirit of Understanding - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Left Limb Spirit of Weakness - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Midriff Spirit of Essence - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Midriff Spirit of Knowledge - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Midriff Spirit of Strength - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Midriff Spirit of Weakness - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Spirit of Essence - Beta', '', 1),
('Vortexx', 'Spirits', 250, 'Xan Spirit of Discerning Weakness - Beta', '', 1),
('Mitaar', 'General', 300, 'Base NCU - Type 00 (0/6)', '', 1),
('Mitaar', 'General', 300, 'Nanodeck Activation Device', '', 1),
('Mitaar', 'General', 1, 'Multi Colored Xan Belt Tuning Device', '', 1),
('Mitaar', 'General', 1, 'Green Xan Belt Tuning Device', '', 1),
('Mitaar', 'General', 300, 'Xan Weapon Upgrade Device', '', 1),
('Mitaar', 'General', 1, 'Xan Defense Merit Board Base', '', 1),
('Mitaar', 'General', 1, 'Xan Combat Merit Board Base', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Brain Symbiant, Artillery Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Brain Symbiant, Control Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Brain Symbiant, Extermination Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Brain Symbiant, Infantry Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Brain Symbiant, Support Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Chest Symbiant, Artillery Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Chest Symbiant, Control Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Chest Symbiant, Extermination Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Chest Symbiant, Infantry Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Chest Symbiant, Support Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Left Hand Symbiant, Artillery Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Left Hand Symbiant, Control Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Left Hand Symbiant, Extermination Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Left Hand Symbiant, Infantry Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Left Hand Symbiant, Support Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Left Wrist Symbiant, Artillery Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Left Wrist Symbiant, Control Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Left Wrist Symbiant, Extermination Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Left Wrist Symbiant, Infantry Unit Beta', '', 1),
('Mitaar', 'Symbiants', 300, 'Xan Left Wrist Symbiant, Support Unit Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Brain Spirit of Computer Skill - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Brain Spirit of Offence - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Essence Brain Spirit - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Left Hand Spirit of Defence - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Left Hand Spirit of Strength - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Spirit of Left Wrist Defense - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Spirit of Left Wrist Strength - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Heart Spirit of Essence - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Heart Spirit of Knowledge - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Heart Spirit of Strength - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Heart Spirit of Weakness - Beta', '', 1),
('Mitaar', 'Spirits', 250, 'Xan Spirit of Clear Thought - Beta', '', 1),
('12Man', 'General', 1, 'Unknown Mixture', '', 1),
('12Man', 'General', 1, 'A piece of cloth', '', 1),
('12Man', 'General', 300, 'Base NCU - Type 00 (0/6)', '', 1),
('12Man', 'General', 300, 'Nanodeck Activation Device', '', 1),
('12Man', 'General', 1, 'Multi Colored Xan Belt Tuning Device', '', 1),
('12Man', 'General', 1, 'Green Xan Belt Tuning Device', '', 1),
('12Man', 'General', 300, 'Xan Weapon Upgrade Device', '', 1),
('12Man', 'General', 1, 'Xan Defense Merit Board Base', '', 1),
('12Man', 'General', 1, 'Xan Combat Merit Board Base', '', 1),
('12Man', 'Symbiants', 300, 'Xan Ear Symbiant, Artillery Unit Beta',
'NODROP, right click to change prof requirement', 1),
('12Man', 'Symbiants', 300, 'Xan Thigh Symbiant, Artillery Unit Beta',
'NODROP, right click to change prof requirement', 1),
('12Man', 'Symbiants', 300, 'Xan Right Arm Symbiant, Artillery Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Right Arm Symbiant, Control Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Right Arm Symbiant, Extermination Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Right Arm Symbiant, Infantry Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Right Arm Symbiant, Support Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Right Hand Symbiant, Artillery Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Right Hand Symbiant, Control Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Right Hand Symbiant, Extermination Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Right Hand Symbiant, Infantry Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Right Hand Symbiant, Support Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Feet Symbiant, Artillery Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Feet Symbiant, Control Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Feet Symbiant, Extermination Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Feet Symbiant, Infantry Unit Beta', '', 1),
('12Man', 'Symbiants', 300, 'Xan Feet Symbiant, Support Unit Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Right Limb Spirit of Essence - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Right Limb Spirit of Strength - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Right Limb Spirit of Weakness - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Right Hand Defensive Spirit - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Right Hand Strength Spirit - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Spirit of Insight - Right Hand - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Spirit of Feet Defense - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Spirit of Feet Strength - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Spirit of Defense - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Spirit of Essence - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Spirit of Essence Whispered - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Spirit of Knowledge Whispered - Beta', '', 1),
('12Man', 'Spirits', 250, 'Xan Spirit of Strength Whispered - Beta', '', 1),
('12Man', 'Profession Gems', 1, 'Brute''s Gem', 'Enf', 1),
('12Man', 'Profession Gems', 1, 'Builder''s Gem', 'Eng', 1),
('12Man', 'Profession Gems', 1, 'Dictator''s Gem', 'Crat', 1),
('12Man', 'Profession Gems', 1, 'Explorer''s Gem', 'Adv', 1),
('12Man', 'Profession Gems', 1, 'Hacker''s Gem', 'Fix', 1),
('12Man', 'Profession Gems', 1, 'Healer''s Gem', 'Doc', 1),
('12Man', 'Profession Gems', 1, 'Master''s Gem', 'MA', 1),
('12Man', 'Profession Gems', 1, 'Merchant''s Gem', 'Trad', 1),
('12Man', 'Profession Gems', 1, 'Protecter''s Gem', 'Keep', 1),
('12Man', 'Profession Gems', 1, 'Sniper''s Gem', 'Agent', 1),
('12Man', 'Profession Gems', 1, 'Spirit''s Gem', 'Shade', 1),
('12Man', 'Profession Gems', 1, 'Techno Wizard''s Gem', 'NT', 1),
('12Man', 'Profession Gems', 1, 'Warrior''s Gem', 'Sol', 1),
('12Man', 'Profession Gems', 1, 'Worshipper''s Gem', 'MP', 1),
('APF', 'Sector 7', 300, 'Cell Templates', '', 1),
('APF', 'Sector 7', 300, 'Mitochondria Samples', '', 1),
('APF', 'Sector 7', 300, 'Plasmid Cultures', '', 1),
('APF', 'Sector 7', 1, 'Power Core Mainboard', '', 1),
('APF', 'Sector 7', 1, 'Power Core Stabilizer', '', 1),
('APF', 'Sector 7', 1, 'Inactive Power Core', '', 1),
('APF', 'Sector 7', 200, 'Basic Belt', '', 1),
('APF', 'Sector 7', 200, 'Viral Belt Control Component', '', 1),
('APF', 'Sector 7', 200, 'Viral Belt NCU Slots', '', 1),
('APF', 'Sector 7', 200, 'Viral Belt Nanobot Power Unit', '', 1),
('APF', 'Sector 7', 200, 'Active Viral CPU Upgrade', '', 1),
('APF', 'Sector 7', 200, 'Active Viral Computer Deck Range Increaser', '', 1),
('APF', 'Sector 7', 200, 'Active Viral NCU Coolant Sink', '', 1),
('APF', 'Sector 7', 150, 'Viral Memory Storage Unit (Damage)', '', 1),
('APF', 'Sector 7', 200, 'Passive Viral CPU Upgrade', '', 1),
('APF', 'Sector 7', 200, 'Passive Viral Computer Deck Range Increaser', '', 1),
('APF', 'Sector 7', 200, 'Passive Viral NCU Coolant Sink', '', 1),
('APF', 'Sector 7', 150, 'Viral Memory Storage Unit (XP)', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Axe', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Cannon', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Carbine', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Crossbow', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Energy Pistol', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Energy Rapier', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Grenade Gun', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Hammer', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Nunchacko', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Pistol', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Rapier', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Rifle', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Shotgun', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Sledgehammer', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Submachine Gun', '', 1),
('APF', 'Sector 7', 150, 'Special Edition Kyr''Ozch Sword', '', 1),
('APF', 'Sector 7', 1, 'Kyr''Ozch Storage Box', '', 1),
('APF', 'Sector 7', 1, 'Kyr''Ozch Storage Container', '', 1),
('APF', 'Sector 7', 300, 'Arithmetic Lead Viralbots', '', 1),
('APF', 'Sector 7', 300, 'Enduring Lead Viralbots', '', 1),
('APF', 'Sector 7', 300, 'Observant Lead Viralbots', '', 1),
('APF', 'Sector 7', 300, 'Strong Lead Viralbots', '', 1),
('APF', 'Sector 7', 300, 'Supple Lead Viralbots', '', 1),
('APF', 'Sector 13', 1, 'Gelatinous Lump', '', 3),
('APF', 'Sector 13', 1, 'Biotech Matrix', '', 3),
('APF', 'Sector 13', 250, 'Action Probability Estimator', '', 1),
('APF', 'Sector 13', 250, 'Dynamic Gas Redistribution Valves', '', 1),
('APF', 'Sector 13', 1, 'Kyr''Ozch Video Processing Unit', 'All Bounties', 1),
('APF', 'Sector 13', 1, 'Hacker ICE-Breaker Source', 'All ICE', 1),
('APF', 'Sector 13', 1, 'Kyr''Ozch Helmet', '2500 Token board', 1),
('APF', 'Sector 28', 1, 'Crystalline Matrix', '', 3),
('APF', 'Sector 28', 1, 'Kyr''ozch Circuitry', '', 3),
('APF', 'Sector 28', 250, 'Inertial Adjustment Processing Unit', '', 1),
('APF', 'Sector 28', 250, 'Notum Amplification Coil', '', 1),
('APF', 'Sector 28', 1, 'Kyr''Ozch Video Processing Unit', 'All Bounties', 1),
('APF', 'Sector 28', 1, 'Hacker ICE-Breaker Source', 'All ICE', 1),
('APF', 'Sector 28', 1, 'Kyr''Ozch Helmet', '2500 Token board', 1),
('APF', 'Sector 35', 1, 'Alpha Program Chip', '', 3),
('APF', 'Sector 35', 1, 'Beta Program Chip', '', 3),
('APF', 'Sector 35', 1, 'Odd Kyr''ozch Nanobots', '', 3),
('APF', 'Sector 35', 1, 'Kyr''ozch Processing Unit', '', 3),
('APF', 'Sector 35', 250, 'Energy Redistribution Unit', '', 1),
('APF', 'Sector 35', 250, 'Visible Light Remodulation Device', '', 1),
('APF', 'Sector 35', 1, 'Kyr''Ozch Video Processing Unit', 'All Bounties', 1),
('APF', 'Sector 35', 1, 'Hacker ICE-Breaker Source', 'All ICE', 1),
('APF', 'Sector 35', 1, 'Kyr''Ozch Helmet', '2500 Token board', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Inert Knowledge Crystal', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Energy Infused Crystal', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of a Sniper', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of a Defender', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of a Technician', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of a Mechanic', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of a Surgeon', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of a Engineer', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of an Instructor', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of a Doctor', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of a Warrior', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of an Archer', '', 1),
('Albtraum', 'Crystals & Crystalised Memories', 250, 'Crystalised Memories of a Scientist', '', 1),
('Albtraum', 'Samples', 250, 'Radioactive Gland Sample', '', 1),
('Albtraum', 'Samples', 250, 'Venom Gland Sample', '', 1),
('Albtraum', 'Samples', 250, 'Frost Gland Sample', '', 1),
('Albtraum', 'Samples', 250, 'Acid Gland Sample', '', 1),
('Albtraum', 'Samples', 250, 'Fire Gland Sample', '', 1),
('Albtraum', 'Pocket Boss Crystals', 250, 'Xan Essence Crystal - Summoned Terror', '', 1),
('Albtraum', 'Pocket Boss Crystals', 250, 'Xan Essence Crystal - Gruesome Misery', '', 1),
('Albtraum', 'Pocket Boss Crystals', 250, 'Xan Essence Crystal - Sister Pestilence', '', 1),
('Albtraum', 'Pocket Boss Crystals', 250, 'Xan Essence Crystal - Sister Merciless', '', 1),
('Albtraum', 'Pocket Boss Crystals', 250, 'Xan Essence Crystal - Divided Loyalty', '', 1),
('Albtraum', 'Rings and Preservation Units', 250, 'Ancient Speed Preservation Unit', '', 1),
('Albtraum', 'Rings and Preservation Units', 250, 'Ancient Vision Preservation Unit', '', 1),
('Albtraum', 'Rings and Preservation Units', 250, 'Ring of Divided Loyalty', '', 1),
('Albtraum', 'Rings and Preservation Units', 250, 'Ring of Gruesome Misery', '', 1),
('Albtraum', 'Rings and Preservation Units', 250, 'Ring of Sister Pestilence', '', 1),
('Albtraum', 'Rings and Preservation Units', 250, 'Ring of Sister Merciless', '', 1),
('Albtraum', 'Rings and Preservation Units', 250, 'Ring of Summoned Terror', '', 1),
('Albtraum', 'Ancients', 250, 'Dormant Ancient Circuit', '', 1),
('Albtraum', 'Ancients', 250, 'Empty Ancient Device', '', 1),
('Albtraum', 'Ancients', 250, 'Inactive Ancient Bracer', '', 1),
('Albtraum', 'Ancients', 250, 'Ancient Scrap of Spirit Knowledge', '', 1),
('Albtraum', 'Ancients', 250, 'Ancient Scrap of Saturated Spirit Knowledge', '', 1),
('Albtraum', 'Ancients', 250, 'Ancient Damage Generation Device', '', 1),
('Albtraum', 'Ancients', 250, 'Inactive Ancient Medical Device', '', 1),
('Albtraum', 'Ancients', 250, 'Inactive Ancient Engineering Device', '', 1),
('DustBrigade', 'DB Armor', 200, 'Enhanced Dustbrigade Combat Chestpiece', '', 1),
('DustBrigade', 'DB Armor', 200, 'Enhanced Dustbrigade Spirit-tech Chestpiece', '', 1),
('DustBrigade', 'DB Armor', 200, 'Enhanced Dustbrigade Sleeves', '', 1),
('DustBrigade', 'DB Armor', 200, 'Enhanced Dustbrigade Notum Gloves', '', 1),
('DustBrigade', 'DB Armor', 200, 'Enhanced Dustbrigade Chemist Gloves', '', 1),
('DustBrigade', 'DB Armor', 200, 'Enhanced Dustbrigade Covering', '', 1),
('DustBrigade', 'DB Armor', 200, 'Enhanced Dustbrigade Flexible Boots', '', 1),
('DustBrigade', 'DB1', 200, 'Enhanced Safeguarded NCU Memory Unit', '', 1),
('DustBrigade', 'DB1', 200, 'Protected Safeguarded NCU Memory Unit', 'evades', 1),
('DustBrigade', 'DB1', 250, 'Master Melee Program', 'Alappaa Pad Upgrade', 1),
('DustBrigade', 'DB1', 250, 'Master Combat Program', 'Alappaa Pad Upgrade', 1),
('DustBrigade', 'DB1', 250, 'Master Nano Technology Program', 'Alappaa Pad Upgrade', 1),
('DustBrigade', 'DB2', 250, 'Basic Infused Dust Brigade Bracer', '', 1),
('DustBrigade', 'DB2', 250, 'Dust Brigade Notum Infuser', 'DB Bracer/Alb Item Upgrade', 1),
('DustBrigade', 'DB2', 250, 'White Molybdenum-Matrix of Xan',
'All Molybdenum-Matrix of Xan (2 Black, 6 White Kegern/Jathos Upgrades)', 2),
('DustBrigade', 'DB2', 300, 'Dust Brigade Engineer Pistol', '', 1),
('DustBrigade', 'DB2', 250, 'Dust Brigade Solar Notum Infuser', 'Engineer Solar Pistol Upgrade', 1),
('DustBrigade', 'DB3', 250, 'Dust Brigade Special Ops Helmet', '', 1),
('DustBrigade', 'DB3', 250, 'Dust Brigade Bracer - First Edition', '', 1),
('DustBrigade', 'DB3', 250, 'Advanced Dust Brigade Notum Infuser', 'Upgrades First Edition bracers', 1),
('DustBrigade', 'Util', 250, 'Dust Brigade Barrier Module', '', 1),
('DustBrigade', 'Util', 250, 'Dust Brigade Assault Module', '', 1),
('DustBrigade', 'Util', 250, 'Dust Brigade Protector Module', '', 1),
('DustBrigade', 'Util', 250, 'Dust Brigade Creator Module', '', 1),
('DustBrigade', 'Util', 250, 'Dust Brigade Grunt Module', '', 1),
('DustBrigade', 'Util', 250, 'Dust Brigade Escape Module', '', 1),
('Pande', 'Beast Armor', 300, 'Sigil of Bahomet', '', 1),
('Pande', 'Beast Armor', 300, 'Helmet of Hypocrisy', '', 1),
('Pande', 'Beast Armor', 300, 'Burden of Competence', '', 1),
('Pande', 'Beast Armor', 300, 'Shoulderplates of Sabotage', '', 1),
('Pande', 'Beast Armor', 300, 'Cuirass of Obstinacy', '', 1),
('Pande', 'Beast Armor', 300, 'Sleeves of Senseless Violence', '', 1),
('Pande', 'Beast Armor', 300, 'Gauntlets of Deformation', '', 1),
('Pande', 'Beast Armor', 300, 'Armplates of Elimination', '', 1),
('Pande', 'Beast Armor', 300, 'Greaves of Malfeasance', '', 1),
('Pande', 'Beast Armor', 300, 'Boots of Concourse', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Abandonment', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Abandonment', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Anger', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Anger', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Angst', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Angst', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Chaos', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Chaos', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Deceit', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Deceit', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Envy', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Envy', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Gluttony', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Gluttony', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Greed', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Greed', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Hatred', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Hatred', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Lust', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Lust', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Pride', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Pride', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Sloth', '', 1),
('Pande', 'Beast Weapons', 299, 'Lady of Sloth', '', 1),
('Pande', 'Beast Weapons', 200, 'Sunrise Hilt', '', 1),
('Pande', 'Beast Weapons', 200, 'Sunset Hilt', '', 1),
('Pande', 'Beast Weapons', 300, 'Lady of Wisdom', '', 1),
('Pande', 'Beast Weapons', 300, 'Lord of Wisdom', '', 1),
('Pande', 'Stars', 250, 'Star of Ardency', 'NT', 1),
('Pande', 'Stars', 250, 'Star of Enterprice', 'Fix', 1),
('Pande', 'Stars', 250, 'Star of Enticement', 'Shade', 1),
('Pande', 'Stars', 250, 'Star of Equanimity', 'MA', 1),
('Pande', 'Stars', 250, 'Star of Faith', 'Keep', 1),
('Pande', 'Stars', 250, 'Star of Fidelity', 'Sol', 1),
('Pande', 'Stars', 250, 'Star of Fortitude', 'End', 1),
('Pande', 'Stars', 250, 'Star of Freedom', 'Adv', 1),
('Pande', 'Stars', 250, 'Star of Ingenuity', 'Eng', 1),
('Pande', 'Stars', 250, 'Star of Interchange', 'Trad', 1),
('Pande', 'Stars', 250, 'Star of Management', 'Crat', 1),
('Pande', 'Stars', 250, 'Star of Moral', 'MP', 1),
('Pande', 'Stars', 250, 'Star of Recovery', 'Doc', 1),
('Pande', 'Stars', 250, 'Star of Stealth', 'Agent', 1),
('Pande', 'Shadowbreeds', 1, 'The Lighter Side', 'Clan SB', 1),
('Pande', 'Shadowbreeds', 1, 'The Darker Side', 'Omni SB', 1),
('Pande', 'Shadowbreeds', 1, 'The Unknown Path', 'Neutral SB', 1),
('Pande', 'The Night Heart', 300, 'Maar''s Blue Belt of Double Prudence', '', 1),
('Pande', 'The Night Heart', 300, 'Maar''s Red Belt of Double Power', '', 1),
('Pande', 'The Night Heart', 300, 'Maar''s Yellow Belt of Double Speed', '', 1),
('Pande', 'The Night Heart', 200, 'Notum Seed', '', 1),
('Pande', 'The Night Heart', 200, 'Novictum Seed', '', 1),
('Pande', 'Aries', 250, 'Dynamic Sleeve of Aries', '', 1),
('Pande', 'Aries', 250, 'Aries'' Tiara of the Quick Witted', '', 1),
('Pande', 'Aries', 250, 'Quick-Draw Holster of Aries', '', 1),
('Pande', 'Aries', 250, 'Boon of Aries', '', 1),
('Pande', 'Leo', 250, 'Enthusiastic Spirit Helper of the Leo', '', 1),
('Pande', 'Leo', 250, 'Leo''s Faithful Boots of Ancient Gold', '', 1),
('Pande', 'Leo', 250, 'Leo''s Grandiose Gold Armband of Plenty', '', 1),
('Pande', 'Leo', 250, 'Leo''s Mellow Gold Pad of Auto-Support', '', 1),
('Pande', 'Virgo', 250, 'Virgo''s Arrow Guide', '', 1),
('Pande', 'Virgo', 250, 'Virgo''s Analytical Spirit Helper', '', 1),
('Pande', 'Virgo', 250, 'Virgo''s Practical Spirit Helper', '', 1),
('Pande', 'Virgo', 250, 'Virgo''s Modest Spirit of Faith', '', 1),
('Pande', 'Aquarius', 250, 'Aquarius'' Boots of Small Steps', '', 1),
('Pande', 'Aquarius', 250, 'Mediative Gloves of the Aquarius', '', 1),
('Pande', 'Aquarius', 250, 'Intuitive Memory of the Aquarius', '', 1),
('Pande', 'Aquarius', 250, 'Aquarius''s Multitask Calculator', '', 1),
('Pande', 'Cancer', 250, 'Cancer''s Gloves of Automatic Knowledge', '', 1),
('Pande', 'Cancer', 250, 'Cancer''s Silver Boots of the Autodidact', '', 1),
('Pande', 'Cancer', 250, 'Cancer''s Ring of Circumspection', '', 1),
('Pande', 'Cancer', 250, 'Cancer''s Time-Saving Memory', '', 1),
('Pande', 'Gemini', 250, 'Collector Pants of Gemini', '', 1),
('Pande', 'Gemini', 250, 'Gemini''s Double Band of Linked Information', '', 1),
('Pande', 'Gemini', 250, 'Cross Dimensional Gyro of Gemini', '', 1),
('Pande', 'Gemini', 250, 'Gemini''s Green Scope of Variety', '', 1),
('Pande', 'Libra', 250, 'Libra''s Charming Assistant', '', 1),
('Pande', 'Libra', 250, 'Urbane Pants of Libra', '', 1),
('Pande', 'Libra', 250, 'Aim of Libra', '', 1),
('Pande', 'Libra', 250, 'Well Balanced Spirit Helper of Libra', '', 1),
('Pande', 'Libra', 1, 'Activation Code', '', 1),
('Pande', 'Pisces', 250, 'Cosmic Guide of the Pisces', '', 1),
('Pande', 'Pisces', 250, 'Octopus Contraption of the Pisces', '', 1),
('Pande', 'Pisces', 250, 'Soul Mark of Pisces', '', 1),
('Pande', 'Pisces', 250, 'Mystery of Pisces', '', 1),
('Pande', 'Taurus', 250, 'Taurus'' Ring of the Heart', '', 1),
('Pande', 'Taurus', 250, 'Taurus'' Spirit of Patience', '', 1),
('Pande', 'Taurus', 250, 'Taurus'' Swordmaster Spirit', '', 1),
('Pande', 'Taurus', 250, 'Taurus'' Spirit of Reflection', '', 1),
('Pande', 'Capricorn', 250, 'Capricorn Bracer of Toxication', '', 1),
('Pande', 'Capricorn', 250, 'Gloves of the Caring Capricorn', '', 1),
('Pande', 'Capricorn', 250, 'Capricorn''s Reliable Memory', '', 1),
('Pande', 'Capricorn', 250, 'Capricorn''s Guide to Alchemy', '', 1),
('Pande', 'Sagittarius', 250, 'Comfort of the Sagittarius', '', 1),
('Pande', 'Sagittarius', 250, 'First Creation of the Sagittarius', '', 1),
('Pande', 'Sagittarius', 250, 'Sagittarius''s Hearty Spirit Helper', '', 1),
('Pande', 'Sagittarius', 250, 'Strong Mittens of the Sagittarius', '', 1),
('Pande', 'Scorpio', 250, 'Punters of the Scorpio', '', 1),
('Pande', 'Scorpio', 250, 'Scorpio''s Shell of Change', '', 1),
('Pande', 'Scorpio', 250, 'Scorpio''s Aim of Anger', '', 1),
('Pande', 'Scorpio', 250, 'Sash of Scorpio Strength', '', 1),
('Pande', 'Bastion', 1, 'SSC "Bastion" Back Armor - Inactive', '', 1),
('Pande', 'Bastion', 1, 'SSC "Bastion" Left Shoulder Armor - Inactive', '', 1),
('Pande', 'Bastion', 1, 'SSC "Bastion" Right Shoulder Armor - Inactive', '', 1),
('Pande', 'Bastion', 250, 'NCU Infuser', '', 1),
('Pande', 'Bastion', 1, 'Collatz Upgrade Plate', '', 1),
('Pande', 'Bastion', 1, 'Fatou Upgrade Plate', '', 1),
('Pande', 'Bastion', 1, 'Mandelbrot Upgrade Plate', '', 1),
('Pande', 'Bastion', 1, 'A Single Strand of Glowing Dark Energy', '', 1),
('Pande', 'Bastion', 1, 'Inert Bacteriophage', '', 1),
('Pande', 'Bastion', 1, 'Pattern Conversion Device', '', 1),
('Pande', 'Bastion', 1, 'Nickel-Cobalt Ferrous Alloy', '', 1),
('Pande', 'Bastion', 1, 'Dacite Fiber', '', 1),
('Pande', 'Bastion', 1, 'Sealed Packet of Bilayer Graphene Sheets', '', 1),
('Pande', 'Bastion', 1, 'Mu-Negative Novictum Enriched Metamaterial', '', 1),
('Pande', 'Bastion', 1, 'Compressed Silane', '', 1),
('Pande', 'Bastion', 1, 'Potassium Nitrate', '', 1),
('Pande', 'Bastion', 1, 'VLS Synthesis Catalyst', '', 1),
('Pande', 'Bastion', 1, 'Bi-Isotropic Nano Media', '', 1),
('Pande', 'Bastion', 1, 'Synchotronic Recombinator - Pocket Edition (Empty)', '', 1),
('Pande', 'Bastion', 1, 'Red Data Crystal', '', 1),
('Pande', 'Bastion', 1, 'Blue Data Crystal', '', 1),
('Pande', 'Bastion', 1, 'Green Data Crystal', '', 1),
('Pande', 'Bastion', 1, 'Virus Programming: Bacteriophage Phi X 3957', '', 1),
('Pande', 'Bastion', 1, 'Virus Programming: Bacteriophage M73', '', 1),
('Pande', 'Bastion', 1, 'Virus Programming: Bacteriophage F9', '', 1),
('Pyramid of Home', 'General', 300, 'Inert Sigil of Alighieri',
'Drops from Cybernetic Daemon, Azdaja the Joyous and Maiden', 1),
('Pyramid of Home', 'General', 300, 'Inert Sigil of Machiavelli', 'Drops from Phobettor', 1),
('Pyramid of Home', 'General', 300, 'Portable Notum Infusion Device',
'Chance of dropping from Cybernetic Daemon, Azdaja the Joyous and Maiden. 100% drop rate from Phobettor.', 1),
('Pyramid of Home', 'General', 1, 'Laughing Spirit Capsule', 'Cybernetic Daemon', 3),
('Pyramid of Home', 'General', 1, 'Crying Spirit Capsule', 'Azdaja the Joyous', 3),
('Pyramid of Home', 'General', 1, 'Screaming Spirit Capsule', 'Maiden', 3),
('Pyramid of Home', 'HUD/NCU', 100, 'Ancient Resorative Fungus', '', 1),
('Pyramid of Home', 'HUD/NCU', 300, 'Sluggish Notum Lens', '', 1),
('Pyramid of Home', 'HUD/NCU', 100, 'Ancient Aggressive Webbing', '', 1),
('Pyramid of Home', 'HUD/NCU', 300, 'Dense Nanite Aegis', '', 1),
('Pyramid of Home', 'HUD/NCU', 100, 'Ancient Protective Drone', '', 1),
('APF', 'Sector 42', 250, 'Inertial Adjustment Processing Unit', 'WEST', 1),
('APF', 'Sector 42', 250, 'Notum Amplification Coil', 'WEST', 1),
('APF', 'Sector 42', 250, 'Action Probability Estimator', 'WEST', 1),
('APF', 'Sector 42', 250, 'Dynamic Gas Redistribution Valves', 'NORTH', 1),
('APF', 'Sector 42', 250, 'Energy Redistribution Unit', 'EAST', 1),
('APF', 'Sector 42', 250, 'Visible Light Remodulation Device', 'EAST', 1),
('APF', 'Sector 42', 1, 'Hacker ICE-Breaker Source', 'All ICE', 1),
('APF', 'Sector 42', 1, 'Kyr''Ozch Invasion Plan', 'ACDC - All Sides', 1),
('APF', 'Sector 42', 1, 'Unlearning Device', 'IPR - All Sides', 4),
('APF', 'Sector 42', 215, 'Alien Matrix Alpha Box', '3 per side', 3),
('APF', 'Sector 42', 215, 'Alien Matrix Beta Box', '3 per side', 3),
('Temple of Three Winds (HL)', 'Binyacht the Faithful', 300, 'Corrupted Edge', '', 1),
('Temple of Three Winds (HL)', 'Binyacht the Faithful', 1, 'Purified Hood of the Faithful', '', 1),
('Temple of Three Winds (HL)', 'Binyacht the Faithful', 1, 'Purified Robe of the Faithful', '', 1),
('Temple of Three Winds (HL)', 'Binyacht the Faithful', 1, 'Tattered book: Sting of the Viper (section 5)', '',
1),
('Temple of Three Winds (HL)', 'Guardian of the Three', 1, 'Bloodthrall Ring', '', 1),
('Temple of Three Winds (HL)', 'Guardian of the Three', 1, 'Ring of Purifying Flame', '', 1),
('Temple of Three Winds (HL)', 'Guardian of the Three', 1, 'Sanguine Vambrace', '', 1),
('Temple of Three Winds (HL)', 'Guardian of the Three', 1, 'Tattered book: Stampede of the Boar (section 1)', '',
1),
('Temple of Three Winds (HL)', 'Guardian of the Three', 1, 'Tattered book: Sting of the Viper (section 1)', '',
1),
('Temple of Three Winds (HL)', 'Guardian of the Three', 1, 'Tattered book: Sting of the Viper (section 5)', '',
1),
('Temple of Three Winds (HL)', 'The Immortal Summoner', 1, 'Bloodthrall Ring', '', 1),
('Temple of Three Winds (HL)', 'The Immortal Summoner', 1, 'Bone Staff of The Immortal Summoner', '', 1),
('Temple of Three Winds (HL)', 'The Immortal Summoner', 1, 'Ornate Funeral Urn', '', 1),
('Temple of Three Winds (HL)', 'The Immortal Summoner', 1, 'Ring of Purifying Flame', '', 1),
('Temple of Three Winds (HL)', 'The Immortal Summoner', 1, 'Tattered book: Stampede of the Boar (section 2)', '',
1),
('Temple of Three Winds (HL)', 'The Immortal Summoner', 1, 'Tattered book: Sting of the Viper (section 5)', '',
1),
('Temple of Three Winds (HL)', 'Lien the Memory-Devourer', 1, 'Lucid Nightmares', '', 1),
('Temple of Three Winds (HL)', 'Lien the Memory-Devourer', 1, 'Memory of Future Events', '', 1),
('Temple of Three Winds (HL)', 'Lien the Memory-Devourer', 1, 'Mnemonic Shard', '', 1),
('Temple of Three Winds (HL)', 'Lien the Memory-Devourer', 1, 'Ring of the Coiled Serpent', '', 1),
('Temple of Three Winds (HL)', 'Lien the Memory-Devourer', 1, 'Tattered book: Stampede of the Boar (section 4)',
'', 1),
('Temple of Three Winds (HL)', 'The Loremaster', 1, 'Blessing of the Gripper', '', 1),
('Temple of Three Winds (HL)', 'The Loremaster', 1, 'Bloodthrall Ring', '', 1),
('Temple of Three Winds (HL)', 'The Loremaster', 1, 'Knowledge of the Immortal One', '', 1),
('Temple of Three Winds (HL)', 'The Loremaster', 1, 'Mountain Razing Gauntlets', '', 1),
('Temple of Three Winds (HL)', 'The Loremaster', 1, 'Sanguine Vambrace', '', 1),
('Temple of Three Winds (HL)', 'The Loremaster', 1, 'Tattered book: Sting of the Viper (section 2)', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Ceremonial Blade', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Desecrated Flesh', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Envoy to Chaos', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Ethereal Embrace', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Grasp of the Immortal', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Nematet''s Third Eye', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Notum Graft', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Ring of Blighted Flesh', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Ring of Purifying Flame', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Sacred Chalice', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Strength of the Immortal', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1,
'Tattered book: Stampede of the Boar (section 3)', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1,
'Tattered book: Stampede of the Boar (section 5)', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Vision of the Heretic', '', 1),
('Temple of Three Winds (HL)', 'Nematet the Subjugator of Time', 1, 'Wit of the Immortal', '', 1),
('Temple of Three Winds (HL)', 'Aegis of Tomorrow', 1, 'Aegis Circuit Board', '', 1),
('Temple of Three Winds (HL)', 'Aegis of Tomorrow', 1, 'Bloodthrall Ring', '', 1),
('Temple of Three Winds (HL)', 'Aegis of Tomorrow', 1, 'Guardian Heavy Tank Armor', '', 1),
('Temple of Three Winds (HL)', 'Aegis of Tomorrow', 1, 'Ring of Purifying Flame', '', 1),
('Temple of Three Winds (HL)', 'Aegis of Tomorrow', 1, 'Sanguine Vambrace', '', 1),
('Temple of Three Winds (HL)', 'Aegis of Tomorrow', 1, 'Tattered book: Sting of the Viper (section 5)', '', 1),
('Temple of Three Winds (HL)', 'Gartua the Gate Guardian', 1, 'Gartua''s Second Coat', '', 1),
('Temple of Three Winds (HL)', 'Gartua the Gate Guardian', 1, 'Inner Peace', '', 1),
('Temple of Three Winds (HL)', 'Gartua the Gate Guardian', 1, 'Keeper''s Vigor', '', 1),
('Temple of Three Winds (HL)', 'Gartua the Gate Guardian', 1, 'Ring of Purifying Flame', '', 1),
('Temple of Three Winds (HL)', 'Gartua the Gate Guardian', 1, 'Tattered book: Sting of the Viper (section 5)',
'', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Bloodthrall Ring', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Ceremonial Blade', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Desecrated Flesh', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Envoy to Chaos', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Obsidian Desecrator', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Ring of Blighted Flesh', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Ring of Purifying Flame', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Sacred Chalice', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Sacred Text of the Immortal One', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Sanguine Vambrace', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Strength of the Immortal', '', 1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Tattered book: Stampede of the Boar (section 5)', '',
1),
('Temple of Three Winds (HL)', 'Aztur the Immortal', 1, 'Tattered book: Stampede of the Boar (section 6)', '',
1),
('Temple of Three Winds (HL)', 'Khalum the Weaver of Flesh', 1, 'Fist of Heavens', '', 1),
('Temple of Three Winds (HL)', 'Khalum the Weaver of Flesh', 1, 'Summoner''s Staff of Dismissal', '', 1),
('Temple of Three Winds (HL)', 'Khalum the Weaver of Flesh', 1, 'Tattered book: Sting of the Viper (section 6)',
'', 1),
('Temple of Three Winds (HL)', 'Uklesh the Beguiling', 1, 'Fist of Heavens', '', 1),
('Temple of Three Winds (HL)', 'Uklesh the Beguiling', 1, 'Uklesh''s Talon', '', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Rod of Dismissal', '', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Corrupted Bloodmark', '', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Corrupted Soulmark', '', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Twilight Entreatment Armor (Helmet)', '', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Twilight Entreatment Armor (Gloves)', '', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Twilight Entreatment Armor (Pants)', '', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Twilight Entreatment Armor (Sleeves)', '', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Twilight Entreatment Armor (Body)', '', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Twilight Entreatment Armor (Boots)', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Counterfeit fr00b T-shirt', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Fetid Vagabond Cloak', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Fortified Construction Sleeves', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Purification Stim', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Reinforced Bau Cyber Body Armor', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Reinforced Bau Cyber Female Body Armor', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Reinforced Bau Cyber Armor Helmet', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Reinforced Bau Cyber Armor Pants', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Reinforced Bau Cyber Armor Sleeves', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Reinforced Bau Cyber Armor Gloves', '', 1),
('Condemned Subway (HL)', 'General', 1, 'Reinforced Bau Cyber Armor Boots', '', 1),
('Condemned Subway (HL)', 'Eliminator Shiro', 1, 'Combat Assist Wen-Wen', '', 1),
('Condemned Subway (HL)', 'Eliminator Shiro', 1, 'Distraction Rifle', '', 1),
('Condemned Subway (HL)', 'Eliminator Shiro', 1, 'Notum-Infused Wool Balaclava Mask', '', 1),
('Condemned Subway (HL)', 'Eliminator Shiro', 1, 'Unstable Damage Augmentation Device', '', 1),
('Condemned Subway (HL)', 'Eumenides', 1, 'BBI Faithful 1000', '', 1),
('Condemned Subway (HL)', 'Eumenides', 1, 'Eumenides''s Omni-Pol Forest Body Armor', '', 1),
('Condemned Subway (HL)', 'Eumenides', 1, 'Superior Ring of the Nucleus Basalis', '', 1),
('Condemned Subway (HL)', 'Eumenides', 1, 'Supreme Office Worker Suit', '', 1),
('Condemned Subway (HL)', 'Eumenides', 1, 'Technical Guidance Personal Terminal', '', 1),
('Condemned Subway (HL)', 'Queen of the Slums', 1, 'Amalgamated Research Attunement Device', '', 1),
('Condemned Subway (HL)', 'Queen of the Slums', 1, 'Aspect of Paralyzing Fear', '', 1),
('Condemned Subway (HL)', 'Queen of the Slums', 1, 'Illegally Augmented Ofab Mongoose', '', 1),
('Condemned Subway (HL)', 'Queen of the Slums', 1, 'Survivalist Leather Armor Legwear', '', 1),
('Condemned Subway (HL)', 'The Psion', 1, 'Aspect of Paralyzing Fear', '', 1),
('Condemned Subway (HL)', 'The Psion', 1, 'Eye of The Psion', '', 1),
('Condemned Subway (HL)', 'The Psion', 1, 'Illegally Modified Dreadloch Panther', '', 1),
('Condemned Subway (HL)', 'The Psion', 1, 'Illegally-Modified Dreadloch Tigress', '', 1),
('Condemned Subway (HL)', 'The Psion', 1, 'Symbiotic Nanite Gloves', '', 1),
('Condemned Subway (HL)', 'Primal Bloodcreeper', 1, 'Mark of the Bloodless', '', 1),
('Condemned Subway (HL)', 'Vergil Aeneid', 1, 'Boots of Gridspace Distortion', '', 1),
('Condemned Subway (HL)', 'Vergil Aeneid', 1, 'Illegally Modified Dreadloch Remodulator', '', 1),
('Condemned Subway (HL)', 'Vergil Aeneid', 1, 'Illegally Modified Dreadloch Thrasher', '', 1),
('Condemned Subway (HL)', 'Vergil Aeneid', 1, 'Lost Blade of Elder Tsunayoshi', '', 1),
('Condemned Subway (HL)', 'Vergil Aeneid', 1, 'Vergil''s Black Trenchcoat', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Aspect of Paralyzing Fear', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'BBI Faithful 1000', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Belt of Great Justice', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Condemned Bulwark', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Eumenides''s Omni-Pol Forest Body Armor', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Eye of The Psion', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Illegally Modified Dreadloch Obliterator', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Illegally Modified Dreadloch Panther', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Illegally Modified Dreadloch Modified Shark', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Jester''s Gift', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Patchwork Defensive Drone', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Technical Guidance Personal Terminal', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Vergil''s Black Trenchcoat', '', 1),
('Condemned Subway (HL)', 'Abmouth Supremus', 1, 'Vicious Support Beam of Malice', '', 1);
INSERT INTO raid_loot (raid, category, ql, name, high_id, comment, multiloot)
VALUES ('Temple of Three Winds (HL)', 'General', 1, 'Notum Ring of the Three', 305488, 'green', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Notum Ring of the Three', 305489, 'red', 1),
('Temple of Three Winds (HL)', 'General', 1, 'Notum Ring of the Three', 305490, 'yellow', 1);