mirror of
https://github.com/araxiaonline/ets-module-collection.git
synced 2026-06-13 02:52:20 -04:00
Updated to add stats v1
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
import { BotData } from './botmgr.server';
|
||||
import { Equipment } from './botmgr.server';
|
||||
|
||||
type ItemInHand = {
|
||||
entry: number | undefined,
|
||||
link: string | undefined,
|
||||
bot: number | undefined,
|
||||
slot: number | undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the UI bot data manager class to make it easier
|
||||
* to managed bot data in the UI.
|
||||
@@ -9,6 +16,8 @@ export class BotStorage {
|
||||
|
||||
private storage: Map<number, BotData> = new Map();
|
||||
private active: number = null;
|
||||
private pickedUp: boolean = false;
|
||||
private itemInHand: ItemInHand = { entry: undefined, link: undefined, bot: undefined, slot: undefined };
|
||||
|
||||
public GetBotData(entry: number): BotData | undefined {
|
||||
return this.storage.get(entry);
|
||||
@@ -22,14 +31,16 @@ export class BotStorage {
|
||||
}
|
||||
|
||||
SetBotData(entry: number, data: BotData): void {
|
||||
|
||||
this.storage.set(entry, data);
|
||||
}
|
||||
|
||||
SetBotItem(botId: number, slot: BotEquipmentSlotNum, item: Equipment): void {
|
||||
const bot = this.GetBotData(botId);
|
||||
if(bot) {
|
||||
bot.equipment[slot] = item;
|
||||
const botData = this.GetBotData(botId);
|
||||
if(botData) {
|
||||
botData.equipment[slot] = item;
|
||||
}
|
||||
|
||||
this.SetBotData(botId, botData);
|
||||
}
|
||||
|
||||
UpdateBotData(entry: number, data: BotData): void {
|
||||
@@ -48,4 +59,44 @@ export class BotStorage {
|
||||
this.active = null;
|
||||
}
|
||||
|
||||
IsPickedUp(): boolean {
|
||||
return this.pickedUp;
|
||||
}
|
||||
|
||||
BotItemPickedUp(botId: number, entry: number, link: string): void {
|
||||
const bot = this.GetBotData(botId);
|
||||
if(bot) {
|
||||
this.itemInHand.entry = entry;
|
||||
this.itemInHand.link = link;
|
||||
this.itemInHand.bot = botId;
|
||||
this.itemInHand.slot = this.GetSlotByItemId(entry);
|
||||
}
|
||||
this.pickedUp = true;
|
||||
|
||||
}
|
||||
|
||||
GetItemInHand(): ItemInHand {
|
||||
return this.itemInHand;
|
||||
}
|
||||
|
||||
BotItemCursorClear(): void {
|
||||
this.itemInHand.entry = undefined;
|
||||
this.itemInHand.link = undefined;
|
||||
this.itemInHand.bot = undefined;
|
||||
this.itemInHand.slot = undefined;
|
||||
this.pickedUp = false;
|
||||
}
|
||||
|
||||
GetSlotByItemId(entry: number): number | undefined {
|
||||
const botData = this.GetBotData(this.GetActive());
|
||||
const allItems = Object.entries(botData.equipment)
|
||||
for(const [slot, item] of allItems) {
|
||||
if(item.entry === entry) {
|
||||
return parseInt(slot);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as Common from '../../constants/idmaps';
|
||||
import { Equipment, EquipmentList } from './botmgr.server';
|
||||
import { BotData, Equipment, EquipmentList } from './botmgr.server';
|
||||
|
||||
type CharInfo = {
|
||||
name: string,
|
||||
@@ -10,19 +10,32 @@ type CharInfo = {
|
||||
raceId: keyof typeof Common.RacesMapping
|
||||
}
|
||||
|
||||
type CharStats = Record<keyof typeof Common.BotStat, number>;
|
||||
type CharTalentSpec = typeof Common.BotTalentSpecs[keyof typeof Common.BotTalentSpecs];
|
||||
type CharRoles = typeof Common.BotRoles[keyof typeof Common.BotRoles];
|
||||
type CharStats = Partial<Record<keyof typeof Common.BotStat, number>>;
|
||||
|
||||
function humanizeTalentName(input: string): string {
|
||||
if (input.length === 0) {
|
||||
return input; // Return unchanged if the input is an empty string
|
||||
}
|
||||
|
||||
const parts = input.split("_");
|
||||
parts[0] = parts[0].toLowerCase();
|
||||
parts[0] = parts[0].charAt(0).toUpperCase() + parts[0].slice(1);
|
||||
parts[1] = parts[1].toLowerCase();
|
||||
parts[1] = parts[1].charAt(0).toUpperCase() + parts[1].slice(1);
|
||||
|
||||
return `${parts[1]} ${parts[0]}`;
|
||||
}
|
||||
export class BotUnit {
|
||||
|
||||
protected myself: Creature;
|
||||
protected myOwner: Player;
|
||||
protected charinfo: CharInfo;
|
||||
protected equipment: EquipmentList;
|
||||
protected stats: CharStats;
|
||||
protected talentSpecId: CharTalentSpec;
|
||||
protected roles: CharRoles;
|
||||
protected statsLeft: Record<string, string>[];
|
||||
protected statsRight: Record<string, string>[];
|
||||
protected talentSpecId: number;
|
||||
protected roles: number;
|
||||
protected allStats: Record<string, string> = {};
|
||||
|
||||
constructor(creature: Creature) {
|
||||
if(!creature.IsNPCBot()) {
|
||||
@@ -30,7 +43,7 @@ export class BotUnit {
|
||||
}
|
||||
|
||||
this.myself = creature;
|
||||
this.myOwner = <Player>creature.GetOwner();
|
||||
this.myOwner = creature.GetBotOwner();
|
||||
this.charinfo = {
|
||||
name: creature.GetName(),
|
||||
level: creature.GetLevel(),
|
||||
@@ -40,20 +53,188 @@ export class BotUnit {
|
||||
raceId: creature.GetRace()
|
||||
};
|
||||
this.equipment = this._lookupEquipment();
|
||||
this.talentSpecId = creature.GetTalentSpec();
|
||||
this.parseStats(creature.GetBotDump());
|
||||
this.statsLeft = this._lookupStats('left');
|
||||
this.statsRight = this._lookupStats('right');
|
||||
this.roles = creature.GetBotRoles();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// public isMeleeDps(): boolean {
|
||||
// const meleeClassMap = [
|
||||
// Common.Characte
|
||||
public toBotData(): BotData {
|
||||
return {
|
||||
name: this.charinfo.name,
|
||||
entry: this.myself.GetEntry(),
|
||||
owner: this.myOwner.GetName(),
|
||||
level: this.charinfo.level,
|
||||
class: this.charinfo.className,
|
||||
classId: this.charinfo.classId,
|
||||
race: this.charinfo.raceName,
|
||||
raceId: this.charinfo.raceId,
|
||||
talentSpec: this.talentSpecId,
|
||||
talentSpecName: humanizeTalentName(this.talentSpecName()),
|
||||
roles: this.roles,
|
||||
equipment: this.equipment,
|
||||
leftStats: this.statsLeft,
|
||||
rightStats: this.statsRight,
|
||||
allStats: this.allStats
|
||||
}
|
||||
}
|
||||
|
||||
// ]
|
||||
public isHealer(): boolean {
|
||||
if(this.talentSpecId == Common.TalentSpecs.SHAMAN_RESTORATION ||
|
||||
this.talentSpecId == Common.TalentSpecs.PRIEST_DISCIPLINE ||
|
||||
this.talentSpecId == Common.TalentSpecs.PRIEST_HOLY ||
|
||||
this.talentSpecId == Common.TalentSpecs.PALADIN_HOLY ||
|
||||
this.talentSpecId == Common.TalentSpecs.DRUID_RESTORATION) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// if(this.charinfo.classId)
|
||||
public isDualWield(): boolean {
|
||||
if(this.talentSpecId == Common.TalentSpecs.ROGUE_COMBAT ||
|
||||
this.talentSpecId == Common.TalentSpecs.ROGUE_SUBTLETY ||
|
||||
this.talentSpecId == Common.TalentSpecs.ROGUE_ASSASSINATION ||
|
||||
this.talentSpecId == Common.TalentSpecs.SHAMAN_ENHANCEMENT ||
|
||||
this.talentSpecId == Common.TalentSpecs.WARRIOR_FURY) {
|
||||
if(this.equipment[Common.BotEquipSlot.MAINHAND] &&
|
||||
this.equipment[Common.BotEquipSlot.OFFHAND]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// // return this.roles === Common.BotRoles.MeleeDps;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public GetMeleeStats (): Record<string, Common.BotStatName[]>{
|
||||
const botStatValues = Object.values(Common.BotStatLabel);
|
||||
type BotStatValues = typeof botStatValues[number];
|
||||
|
||||
return {
|
||||
left: [
|
||||
"Strength",
|
||||
"Agility",
|
||||
"Dmg Main",
|
||||
"Power",
|
||||
"Hit Rating",
|
||||
"Crit %",
|
||||
"Expertise",
|
||||
"Armor Pen"
|
||||
],
|
||||
right: [
|
||||
"Haste Rating",
|
||||
"Armor",
|
||||
"Stamina",
|
||||
"Defense",
|
||||
"Dodge",
|
||||
"Parry",
|
||||
"Block",
|
||||
"Physical Resist"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
public GetRangedStats (): Record<string, Common.BotStatName[]>{
|
||||
return {
|
||||
left: [
|
||||
"Strength",
|
||||
"Agility",
|
||||
"Dmg Range",
|
||||
"Speed",
|
||||
"Power",
|
||||
"Hit Rating",
|
||||
"Crit %",
|
||||
"Armor Pen"
|
||||
],
|
||||
right: [
|
||||
"Expertise",
|
||||
"Haste Rating",
|
||||
"Armor",
|
||||
"Stamina",
|
||||
"Defense",
|
||||
"Dodge",
|
||||
"Parry",
|
||||
"Block",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
public GetCasterStats (): Record<string, Common.BotStatName[]> {
|
||||
return {
|
||||
left: [
|
||||
"Intellect",
|
||||
"Spirit",
|
||||
"Stamina",
|
||||
"Bonus Dmg",
|
||||
"Crit %",
|
||||
"Hit Rating",
|
||||
"Spell Pen"
|
||||
],
|
||||
right: [
|
||||
"Haste Rating",
|
||||
"Spell Resist",
|
||||
"MP5",
|
||||
"Dodge",
|
||||
"Armor",
|
||||
"Parry",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
public GetStatMappings() {
|
||||
|
||||
switch(this.talentSpecId) {
|
||||
case Common.TalentSpecs.WARRIOR_ARMS:
|
||||
case Common.TalentSpecs.WARRIOR_FURY:
|
||||
case Common.TalentSpecs.WARRIOR_PROTECTION:
|
||||
case Common.TalentSpecs.PALADIN_PROTECTION:
|
||||
case Common.TalentSpecs.PALADIN_RETRIBUTION:
|
||||
case Common.TalentSpecs.DK_BLOOD:
|
||||
case Common.TalentSpecs.DK_FROST:
|
||||
case Common.TalentSpecs.DK_UNHOLY:
|
||||
case Common.TalentSpecs.ROGUE_ASSASSINATION:
|
||||
case Common.TalentSpecs.ROGUE_COMBAT:
|
||||
case Common.TalentSpecs.ROGUE_SUBTLETY:
|
||||
case Common.TalentSpecs.SHAMAN_ENHANCEMENT:
|
||||
case Common.TalentSpecs.DRUID_FERAL:
|
||||
return this.GetMeleeStats();
|
||||
|
||||
case Common.TalentSpecs.HUNTER_SURVIVAL:
|
||||
case Common.TalentSpecs.HUNTER_MARKSMANSHIP:
|
||||
case Common.TalentSpecs.HUNTER_BEASTMASTERY:
|
||||
return this.GetRangedStats();
|
||||
|
||||
case Common.TalentSpecs.MAGE_ARCANE:
|
||||
case Common.TalentSpecs.MAGE_FIRE:
|
||||
case Common.TalentSpecs.MAGE_FROST:
|
||||
case Common.TalentSpecs.WARLOCK_AFFLICTION:
|
||||
case Common.TalentSpecs.WARLOCK_DEMONOLOGY:
|
||||
case Common.TalentSpecs.WARLOCK_DESTRUCTION:
|
||||
case Common.TalentSpecs.PRIEST_DISCIPLINE:
|
||||
case Common.TalentSpecs.PRIEST_HOLY:
|
||||
case Common.TalentSpecs.PRIEST_SHADOW:
|
||||
case Common.TalentSpecs.SHAMAN_ELEMENTAL:
|
||||
case Common.TalentSpecs.SHAMAN_RESTORATION:
|
||||
case Common.TalentSpecs.DRUID_BALANCE:
|
||||
case Common.TalentSpecs.DRUID_RESTORATION:
|
||||
return this.GetCasterStats();
|
||||
|
||||
default:
|
||||
print(`Unknown Talent Spec: ${this.talentSpecId}`);
|
||||
}
|
||||
}
|
||||
|
||||
public talentSpecName() {
|
||||
// print(`Talent Spec: ${this.talentSpecId}`);
|
||||
const keys = Object.keys(Common.TalentSpecs);
|
||||
for(let i=0; i < keys.length; i++) {
|
||||
if(Common.TalentSpecs[keys[i]] === this.talentSpecId) {
|
||||
return keys[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _lookupEquipment(): EquipmentList {
|
||||
const myEquipment = {} as EquipmentList;
|
||||
@@ -75,4 +256,92 @@ export class BotUnit {
|
||||
|
||||
return myEquipment;
|
||||
}
|
||||
|
||||
private _lookupStats(panel: 'left' | 'right'): Record<string, string>[] {
|
||||
const statMappings = this.GetStatMappings();
|
||||
const classStats: Record<string, string>[] = []
|
||||
|
||||
for(let stat = 0; stat < statMappings[panel].length; stat++) {
|
||||
const statName = statMappings[panel][stat];
|
||||
let statValue = this.allStats[statName];
|
||||
const statRecord= {};
|
||||
|
||||
// handle some special cases for stats
|
||||
if(statName === 'Dmg Main' || statName === 'Dmg Range' || statName == 'Dmg Off') {
|
||||
statValue = statValue.replace(" min: ", "").replace(", max: ", "-");
|
||||
statRecord[statName] = statValue;
|
||||
classStats.push(statRecord);
|
||||
|
||||
// Go ahead and add dual wield damage also
|
||||
if(this.isDualWield()) {
|
||||
const offhand = this.allStats['Damage Range (Offhand)'];
|
||||
statRecord['Damage Range (Offhand)'] = offhand.replace(" min: ", "").replace(", max: ", "-");
|
||||
classStats.push(statRecord);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(this.isHealer() && statName === 'Bonus Dmg') {
|
||||
statRecord['Bonus Heals'] = statValue;
|
||||
classStats.push(statRecord);
|
||||
print(`Stat: Bonus Heals = ${statValue}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(statName && statValue) {
|
||||
statRecord[statName] = statValue;
|
||||
classStats.push(statRecord);
|
||||
print(`Stat: ${statName} = ${statValue}`);
|
||||
} else {
|
||||
print("failed to get stat: " + statName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return classStats;
|
||||
}
|
||||
|
||||
private parseStats(botdump: string) {
|
||||
const stats = botdump.split('\n');
|
||||
for(let i=0; i<stats.length; i++) {
|
||||
const parts = stats[i].split(':');
|
||||
|
||||
if(parts[0] == "Resistance") {
|
||||
parts[0] = parts[0] + ":" + parts[1];
|
||||
this.allStats[parts[0]] = parts[2];
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!Common.BotStatLabel[parts[0]]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
parts[1] = parts[1].replace("(-0.00 pct)", "");
|
||||
parts[1] = parts[1].replace("pct", "%");
|
||||
parts[1] = parts[1].replace("+", "");
|
||||
|
||||
const statName = Common.BotStatLabel[parts[0]];
|
||||
if(statName == "Dmg Main" || statName == "Dmg Off" || statName == "Dmg Range") {
|
||||
parts[1] = parts[2].split(",")[0].trim() + "-" + parts[3].trim();
|
||||
|
||||
}
|
||||
|
||||
if(statName == "Physical Resist" || statName == "Spell Resist") {
|
||||
parts[1] = 1 - parseInt(parts[1]) + "%";
|
||||
}
|
||||
|
||||
if(statName == "Dodge" || statName == "Parry" || statName == "Block" ||
|
||||
statName == "Crit Chance" ) {
|
||||
parts[1] = parts[1] + " %";
|
||||
}
|
||||
|
||||
if(statName == "Strength" || statName == "Agility" || statName == "Intellect" ||
|
||||
statName == "Spirit" || statName == "Stamina") {
|
||||
parts[1] = "" + Math.round(parseInt(parts[1]));
|
||||
}
|
||||
|
||||
this.allStats[statName] = parts[1].trim();
|
||||
print("Parsed Stat: " + statName + " = " + parts[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
/** @ts-expect-error */
|
||||
let aio: AIO = {};
|
||||
|
||||
|
||||
/**
|
||||
* @todo Add all equipment slots for the bot onload - done
|
||||
* @todo Create frames for bot status
|
||||
@@ -19,14 +18,19 @@ let aio: AIO = {};
|
||||
*/
|
||||
|
||||
|
||||
import { UIInvSlot, BotEquipSlot, BotSlotName, BotStat } from "../../constants/idmaps";
|
||||
import { UIInvSlot, BotEquipSlot, BotSlotName, BotStat, BotStatLabel } from "../../constants/idmaps";
|
||||
import { BotData, Equipment } from "./botmgr.server";
|
||||
import { BotStorage } from "./bot";
|
||||
import { colors } from "../../classes/ui-utils";
|
||||
|
||||
// Helper functions to create unique ids for frames and components
|
||||
const id = (name: string, entry: number = null) => `BotMgr${name}` + (entry ? entry : '');
|
||||
const compId = (botId: number, name: string) => `${botId}:BotMgr${name}`;
|
||||
|
||||
// includes of global polyfills in main file for submodules
|
||||
let incObjectEntries = { 1: 'inlude'}; Object.entries(incObjectEntries);
|
||||
let incParseInt = parseInt('1');
|
||||
|
||||
function ucase(input: string): string {
|
||||
if (input.length === 0) {
|
||||
return input; // Return unchanged if the input is an empty string
|
||||
@@ -41,29 +45,38 @@ function ucase(input: string): string {
|
||||
return firstLetter + restOfTheString;
|
||||
}
|
||||
|
||||
function humanizeName(input: string): string {
|
||||
if (input.length === 0) {
|
||||
return input; // Return unchanged if the input is an empty string
|
||||
}
|
||||
|
||||
const parts = input.split("_");
|
||||
parts[0] = parts[0].toLowerCase();
|
||||
parts[0] = parts[0].charAt(0).toUpperCase() + parts[0].slice(1);
|
||||
parts[1] = parts[1].toLowerCase();
|
||||
parts[1] = parts[1].charAt(0).toUpperCase() + parts[1].slice(1);
|
||||
|
||||
return `${parts[1]} ${parts[0]}`;
|
||||
}
|
||||
|
||||
// If we are a client file. aio.AddAddon() will return false and this file will be serialized and sent to client.
|
||||
if(!aio.AddAddon()) {
|
||||
|
||||
const botMgrHandlers = aio.AddHandlers('BotMgr', {});
|
||||
const InfoFramePool: Map<number, WoWAPI.Frame> = new Map();
|
||||
const ComponentsPool: Map<string, unknown> = new Map(); // key botId + ":" + componentid
|
||||
const ItemClickFuncs: Map<string, any> = new Map(); // containerid (1-13):itemslotId (1-36) => click function
|
||||
const botStorage: BotStorage = new BotStorage();
|
||||
|
||||
let BotItemTooltip: WoWAPI.GameTooltip;
|
||||
|
||||
/**
|
||||
* All Resists for the bot
|
||||
* Is a SubFrame as well as children.
|
||||
* @param parent
|
||||
* @param resists
|
||||
*/
|
||||
function AddResistFrame(parent: WoWAPI.Frame, resists: any = {}) {
|
||||
function AddResistFrame(parent: WoWAPI.Frame, botData: BotData) {
|
||||
const resistFrame = CreateFrame("Frame", id("ResistsFrame"), parent);
|
||||
resistFrame.SetSize(32, 160);
|
||||
resistFrame.SetPoint("TOPRIGHT", parent, "TOPLEFT", 297, -77);
|
||||
|
||||
const magicRes1 = CreateFrame("Frame", id("MagicResFrame1"), resistFrame, "MagicResistanceFrameTemplate", 6);
|
||||
magicRes1.SetPoint("TOP", resistFrame, "TOP", 0, 0);
|
||||
const magicRes1 = CreateFrame("Frame", id("MagicResFrame1"), resistFrame, "MagicResistanceFrameTemplate", 1);
|
||||
magicRes1.SetPoint("TOP", 0, 0);
|
||||
magicRes1.SetSize(32, 32);
|
||||
|
||||
const magResBack1 = magicRes1.CreateTexture(id("MagicResTexture1"), "BACKGROUND");
|
||||
@@ -71,15 +84,78 @@ if(!aio.AddAddon()) {
|
||||
magResBack1.SetTexCoord(0, 1, 0.2265, 0.3398);
|
||||
magResBack1.SetAllPoints(magicRes1);
|
||||
|
||||
const magResFont1 = magicRes1.CreateFontString(id("MagicResFont1"), "BACKGROUND", "GameFontHighlightSmall");
|
||||
magResFont1.SetPoint("BOTTOM", magicRes1, null, 0, 3);
|
||||
magResFont1.SetText("X");
|
||||
const magResFont1 = magicRes1.CreateFontString(id("Resist2"), "BACKGROUND", "GameFontHighlightSmall");
|
||||
magResFont1.SetPoint("BOTTOM", magResBack1, null, 0, 3);
|
||||
magResFont1.SetText(`${GREEN_FONT_COLOR_CODE}${botData.allStats["Resistance: arcane"]}`);
|
||||
ComponentsPool.set(compId(botData.entry, "Resist1"), magResFont1);
|
||||
|
||||
// End Arcance Resistance
|
||||
|
||||
const magicRes2 = CreateFrame("Frame", id("MagicResFrame2"), resistFrame, "MagicResistanceFrameTemplate", 2);
|
||||
magicRes2.SetPoint("TOP", magicRes1, "BOTTOM", 0, 0);
|
||||
magicRes2.SetSize(32, 32);
|
||||
|
||||
const magResBack2 = magicRes2.CreateTexture(id("MagicResTexture2"), "BACKGROUND");
|
||||
magResBack2.SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ResistanceIcons");
|
||||
magResBack2.SetTexCoord(0, 1, 0, 0.11328125);
|
||||
magResBack2.SetAllPoints(magicRes2);
|
||||
|
||||
const magResFont2 = magicRes1.CreateFontString(id("Resist2"), "BACKGROUND", "GameFontHighlightSmall");
|
||||
magResFont2.SetPoint("BOTTOM", magicRes2, null, 0, 3);
|
||||
magResFont2.SetText(`${GREEN_FONT_COLOR_CODE}${botData.allStats["Resistance: fire"]}`);
|
||||
ComponentsPool.set(compId(botData.entry, "Resist2"), magResFont2);
|
||||
|
||||
// end fire resistance
|
||||
|
||||
const magicRes3 = CreateFrame("Frame", id("MagicResFrame3"), resistFrame, "MagicResistanceFrameTemplate", 3);
|
||||
magicRes3.SetPoint("TOP", magicRes2, "BOTTOM", 0, 0);
|
||||
magicRes3.SetSize(32, 32);
|
||||
|
||||
const magResBack3 = magicRes3.CreateTexture(id("MagicResTexture3"), "BACKGROUND");
|
||||
magResBack3.SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ResistanceIcons");
|
||||
magResBack3.SetTexCoord(0, 1, 0.11328125, 0.2265625);
|
||||
magResBack3.SetAllPoints(magicRes3);
|
||||
3
|
||||
const magResFont3 = magicRes3.CreateFontString(id("Resist3"), "BACKGROUND", "GameFontHighlightSmall");
|
||||
magResFont3.SetPoint("BOTTOM", magicRes3, null, 0, 3);
|
||||
magResFont3.SetText(`${GREEN_FONT_COLOR_CODE}${botData.allStats["Resistance: nature"]}`);
|
||||
ComponentsPool.set(compId(botData.entry, "Resist3"), magResFont3);
|
||||
|
||||
// end nature resistance
|
||||
|
||||
const magicRes4 = CreateFrame("Frame", id("MagicResFrame4"), resistFrame, "MagicResistanceFrameTemplate", 4);
|
||||
magicRes4.SetPoint("TOP", magicRes3, "BOTTOM", 0, 0);
|
||||
magicRes4.SetSize(32, 32);
|
||||
|
||||
const magResBack4 = magicRes4.CreateTexture(id("MagicResTexture4"), "BACKGROUND");
|
||||
magResBack4.SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ResistanceIcons");
|
||||
magResBack4.SetTexCoord(0, 1, 0.33984375, 0.453125);
|
||||
magResBack4.SetAllPoints(magicRes4);
|
||||
3
|
||||
const magResFont4 = magicRes4.CreateFontString(id("Resist4"), "BACKGROUND", "GameFontHighlightSmall");
|
||||
magResFont4.SetPoint("BOTTOM", magicRes4, null, 0, 3);
|
||||
magResFont4.SetText(`${GREEN_FONT_COLOR_CODE}${botData.allStats["Resistance: frost"]}`);
|
||||
ComponentsPool.set(compId(botData.entry, "Resist4"), magResFont4);
|
||||
|
||||
// end frost resistance
|
||||
|
||||
const magicRes5 = CreateFrame("Frame", id("MagicResFrame5"), resistFrame, "MagicResistanceFrameTemplate", 5);
|
||||
magicRes5.SetPoint("TOP", magicRes4, "BOTTOM", 0, 0);
|
||||
magicRes5.SetSize(32, 32);
|
||||
|
||||
const magResBack5 = magicRes5.CreateTexture(id("MagicResTexture5"), "BACKGROUND");
|
||||
magResBack5.SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ResistanceIcons");
|
||||
magResBack5.SetTexCoord(0, 1, 0.453125, 0.56640625);
|
||||
magResBack5.SetAllPoints(magicRes5);
|
||||
3
|
||||
const magResFont5 = magicRes5.CreateFontString(id("Resist5"), "BACKGROUND", "GameFontHighlightSmall");
|
||||
magResFont5.SetPoint("BOTTOM", magicRes5, null, 0, 3);
|
||||
magResFont5.SetText(`${GREEN_FONT_COLOR_CODE}${botData.allStats["Resistance: shadow"]}`);
|
||||
ComponentsPool.set(compId(botData.entry, "Resist5"), magResFont5);
|
||||
|
||||
// end shadow resistance
|
||||
}
|
||||
|
||||
/**
|
||||
* This is for the Characters left picture and class,race, name details.
|
||||
* Only created once per bot panel.
|
||||
*/
|
||||
function AddPortrait(parent: WoWAPI.Frame, botData: BotData) {
|
||||
const portrait = parent.CreateTexture(id("Portrait", botData.entry), "ARTWORK");
|
||||
portrait.SetPoint("TOPLEFT", 10, -7);
|
||||
@@ -114,6 +190,11 @@ if(!aio.AddAddon()) {
|
||||
infoTextFont.SetText(`${YELLOW_FONT_COLOR_CODE} Level ${UnitLevel("target")} ${botData.race} ${botData.class}`);
|
||||
}
|
||||
|
||||
const spec = infoTextFrame.CreateFontString(id("SpecFont", botData.entry), "BACKGROUND", "GameFontHighlightSmall");
|
||||
spec.SetText(`${botData.talentSpecName}`);
|
||||
spec.SetPoint("TOP", infoTextFont, "BOTTOM", 0, -2);
|
||||
ComponentsPool.set(compId(botData.entry, "SpecFont"), spec);
|
||||
|
||||
infoTextFont.SetSize(300,12);
|
||||
infoTextFont.SetPoint("CENTER",0,0);
|
||||
|
||||
@@ -223,35 +304,60 @@ if(!aio.AddAddon()) {
|
||||
equipFrame = CreateFrame("Frame", id("RightEquipment"), parent, null, 2);
|
||||
equipFrame.SetPoint("TOPRIGHT", -40, -73);
|
||||
equipFrame.SetSize(40, 330);
|
||||
ComponentsPool.set(compId(botData.entry, "RightEquipment"), equipFrame);
|
||||
UpdateEquipFrame('right', equipFrame, botData);
|
||||
|
||||
ComponentsPool.set(compId(botData.entry, "RightEquipment"), equipFrame);
|
||||
}
|
||||
|
||||
if(!frames.weapons) {
|
||||
equipFrame = CreateFrame("Frame", id("WeaponEquipment"), parent, null, 3);
|
||||
equipFrame.SetPoint("CENTER", -10, -147);
|
||||
equipFrame.SetSize(129, 40);
|
||||
ComponentsPool.set(compId(botData.entry, "WeaponsEquipment"), equipFrame);
|
||||
UpdateEquipFrame('weapons', equipFrame, botData);
|
||||
// const placeholder = equipFrame.CreateTexture(id("RightEquipmentPlaceholder"), "OVERLAY");
|
||||
// placeholder.SetAllPoints(equipFrame);
|
||||
// placeholder.SetTexture(0,0,0,0.8);
|
||||
ComponentsPool.set(compId(botData.entry, "WeaponsEquipment"), equipFrame);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function CreateStats(parent: WoWAPI.Frame, botData: BotData) {
|
||||
|
||||
const reverseObject = (obj: { [key: string]: any }): { [key: string]: string } =>
|
||||
Object.fromEntries(Object.entries(obj).map(([k, v]) => [v, k]));
|
||||
const lookup = reverseObject(BotStat);
|
||||
|
||||
function AddStats(parent: WoWAPI.Frame, botData: BotData) {
|
||||
const leftStats = botData.leftStats;
|
||||
const rightStats = botData.rightStats;
|
||||
for(let i =0; i < leftStats.length; i++) {
|
||||
const statName = Object.keys(leftStats[i])[0];
|
||||
const statLabel = parent.CreateFontString(id(`StatName-${statName}`), "ARTWORK", "GameFontNormalSmall");
|
||||
statLabel.SetPoint("TOPLEFT", parent, "TOPLEFT", 5, -7 - (i * 14));
|
||||
statLabel.SetText(`${statName}:`);
|
||||
statLabel.SetJustifyH("LEFT");
|
||||
|
||||
const statValue = parent.CreateFontString(id(`StatValue-${statName}`), "ARTWORK", "GameFontNormalSmall");
|
||||
statValue.SetPoint("TOPRIGHT", parent, "TOP", -4, -5 - (i * 14));
|
||||
statValue.SetSize(50, 14);
|
||||
statValue.SetText(`${colors('white')}${leftStats[i][statName]}`);
|
||||
statValue.SetJustifyH("RIGHT");
|
||||
|
||||
}
|
||||
|
||||
for(let i =0; i < rightStats.length; i++) {
|
||||
const statName = Object.keys(rightStats[i])[0];
|
||||
const statLabel = parent.CreateFontString(id(`StatName-${statName}`), "ARTWORK", "GameFontNormalSmall");
|
||||
statLabel.SetPoint("TOPLEFT", parent, "TOPLEFT", 118, -7 - (i * 14));
|
||||
statLabel.SetText(`${statName}:`);
|
||||
statLabel.SetJustifyH("LEFT");
|
||||
|
||||
const statValue = parent.CreateFontString(id(`StatValue-${statName}`), "ARTWORK", "GameFontNormalSmall");
|
||||
statValue.SetPoint("TOPRIGHT", parent, "TOPRIGHT", -4, -5 - (i * 14));
|
||||
statValue.SetSize(50, 14);
|
||||
statValue.SetText(`${colors('white')}${rightStats[i][statName]}`);
|
||||
statValue.SetJustifyH("RIGHT");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function CreateStats(parent: WoWAPI.Frame, botData: BotData) {
|
||||
|
||||
const statsFrame = CreateFrame("Frame", id("CharacterAttr"), parent, null, 1);
|
||||
statsFrame.SetSize(230,78);
|
||||
statsFrame.SetPoint("TOPLEFT", 67, -231);
|
||||
statsFrame.SetPoint("TOPLEFT", 67, -251);
|
||||
statsFrame.SetFrameStrata("HIGH");
|
||||
statsFrame.SetAlpha(1.0);
|
||||
statsFrame.SetBackdropColor(0,0,0,1.0);
|
||||
@@ -264,7 +370,7 @@ if(!aio.AddAddon()) {
|
||||
|
||||
const leftmiddle = statsFrame.CreateTexture(id("StatLeftMiddle"), "BACKGROUND");
|
||||
leftmiddle.SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-StatBackground");
|
||||
leftmiddle.SetSize(115,113);
|
||||
leftmiddle.SetSize(115,95);
|
||||
leftmiddle.SetPoint("TOPLEFT", leftTop, "BOTTOMLEFT", 0, 0);
|
||||
leftmiddle.SetTexCoord(0, 0.8984375, 0.125, 0.1953125);
|
||||
|
||||
@@ -282,7 +388,7 @@ if(!aio.AddAddon()) {
|
||||
|
||||
const rightMiddle = statsFrame.CreateTexture(id("StatRightMiddle"), "BACKGROUND");
|
||||
rightMiddle.SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-StatBackground");
|
||||
rightMiddle.SetSize(115,113);
|
||||
rightMiddle.SetSize(115,95);
|
||||
rightMiddle.SetPoint("TOPLEFT", leftmiddle, "TOPRIGHT", 0, 0);
|
||||
rightMiddle.SetTexCoord(0, 0.8984375, 0.125, 0.1953125);
|
||||
|
||||
@@ -292,14 +398,7 @@ if(!aio.AddAddon()) {
|
||||
rightBottom.SetPoint("TOPLEFT", leftBottom, "TOPRIGHT", 0, 0);
|
||||
rightBottom.SetTexCoord(0, 0.8984375, 0.484375, 0.609375);
|
||||
|
||||
let counter = 0;
|
||||
// for(const stats in botData.stats.left) {
|
||||
// const stat = statsFrame.CreateFontString(id(`Stat-${stats}`), "ARTWORK", "GameFontNormalSmall");
|
||||
// stat.SetPoint("TOPLEFT", statsFrame, "TOPLEFT", 10, -10 - (counter * 14));
|
||||
// stat.SetText(lookup[stats] + " " + botData.stats[stats]);
|
||||
// counter++;
|
||||
// }
|
||||
|
||||
AddStats(statsFrame, botData);
|
||||
}
|
||||
|
||||
function SetBackground(parent: WoWAPI.Frame) {
|
||||
@@ -388,31 +487,65 @@ if(!aio.AddAddon()) {
|
||||
|
||||
function ItemSlotOnClick(frame: WoWAPI.Button, button: string) {
|
||||
const botId = botStorage.GetActive();
|
||||
|
||||
print(botId);
|
||||
const theItem = botStorage.GetBotItem(botId, <BotEquipmentSlotNum>frame.GetID());
|
||||
|
||||
const [compItem, compItemId, compItemLink] = GetCursorInfo();
|
||||
print(`CursorHasItem: ${compItemLink}`);
|
||||
const [compItem, compItemId, compItemLink] = GetCursorInfo();
|
||||
|
||||
if(theItem && !compItem) {
|
||||
if(button == "LeftButton") {
|
||||
PickupItem(theItem.link);
|
||||
print('Set Bot Pickup Item', botId, theItem.entry, theItem.link);
|
||||
botStorage.BotItemPickedUp(botId, theItem.entry, theItem.link);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(compItem) {
|
||||
const slot = frame.GetID();
|
||||
|
||||
aio.Handle("BotMgr", "EquipTheItem", GetUnitName("player", false), botId, slot, compItemId, compItemLink);
|
||||
|
||||
// if we have a bot virtual item in hand
|
||||
if(botStorage.IsPickedUp()) {
|
||||
const botItemInHand = botStorage.GetItemInHand();
|
||||
// first unequip item on target bot
|
||||
aio.Handle("BotMgr", "UnequipTheItem", GetUnitName("player", false), slot, botItemInHand.bot);
|
||||
aio.Handle("BotMgr", "EquipTheItem", GetUnitName("player", false), botId, slot, compItemId, compItemLink);
|
||||
} else {
|
||||
aio.Handle("BotMgr", "EquipTheItem", GetUnitName("player", false), botId, slot, compItemId, compItemLink);
|
||||
}
|
||||
|
||||
// Attempt to equip the item.
|
||||
PlaySound("INTERFACESOUND_CURSORDROPOBJECT");
|
||||
ClearCursor();
|
||||
}
|
||||
}
|
||||
|
||||
botMgrHandlers.OnEquipSuccess = (botId: number, slot: BotEquipmentSlotNum, itemId: number, itemLink: string) => {
|
||||
botMgrHandlers.OnEquipSuccess = (botId: number, slot: BotEquipmentSlotNum, item: Equipment) => {
|
||||
const itemTexture = <WoWAPI.Texture>ComponentsPool.get(compId(botId, `ItemSlotTexture-${slot}`));
|
||||
itemTexture.SetTexture(GetItemIcon(itemId));
|
||||
itemTexture.SetTexture(GetItemIcon(item.entry));
|
||||
|
||||
// Hide Tooltips otherwise it will show old item.
|
||||
const BotTooltip = <WoWAPI.GameTooltip>ComponentsPool.get(compId(botId, "tooltip"));
|
||||
botStorage.SetBotItem(botId, slot, item);
|
||||
|
||||
BotTooltip.Hide();
|
||||
GameTooltip.Hide();
|
||||
}
|
||||
|
||||
botMgrHandlers.OnUnEquipSuccess = (slot: BotEquipmentSlotNum, botId: number) => {
|
||||
const itemTexture = <WoWAPI.Texture>ComponentsPool.get(compId(botId, `ItemSlotTexture-${slot}`));
|
||||
/** TO DO move to generic function for getting textures right now is copy/paste */
|
||||
let slotName: string = BotSlotName[slot];
|
||||
|
||||
if(slot === BotEquipSlot.FINGER1) slotName = "FINGER0";
|
||||
if(slot === BotEquipSlot.FINGER2) slotName = "FINGER1";
|
||||
if(slot === BotEquipSlot.TRINKET1) slotName = "TRINKET0";
|
||||
if(slot === BotEquipSlot.TRINKET2) slotName = "TRINKET1";
|
||||
if(slot === BotEquipSlot.OFFHAND) slotName = "SECONDARYHAND";
|
||||
|
||||
const [, itemIcon] = GetInventorySlotInfo(UIInvSlot[`${slotName}SLOT`]);
|
||||
itemTexture.SetTexture(itemIcon);
|
||||
|
||||
// Hide Tooltips otherwise it will show old item.
|
||||
const BotTooltip = <WoWAPI.GameTooltip>ComponentsPool.get(compId(botId, "tooltip"));
|
||||
@@ -422,10 +555,87 @@ if(!aio.AddAddon()) {
|
||||
|
||||
botMgrHandlers.OnEquipFail = (botId: number, slot: BotEquipmentSlotNum, itemId: number, itemLink: string) => {
|
||||
PlaySound("ITEMGENERICSOUND");
|
||||
botStorage.BotItemCursorClear();
|
||||
ClearCursor();
|
||||
}
|
||||
|
||||
|
||||
botMgrHandlers.OnUnEquipFail = (botId: number, slot: BotEquipmentSlotNum) => {
|
||||
PlaySound("ITEMGENERICSOUND");
|
||||
botStorage.BotItemCursorClear();
|
||||
ClearCursor();
|
||||
}
|
||||
|
||||
function HandleUnequipItem(itemButton: WoWAPI.Button, isBankSlot: boolean = false): void {
|
||||
|
||||
const slotNum = itemButton.GetID();
|
||||
const bagId = itemButton.GetParent().GetID();
|
||||
print(`Is Item Picked Up: ${botStorage.IsPickedUp()}`);
|
||||
if(!GetContainerItemLink((isBankSlot) ? -1 : bagId, slotNum)) {
|
||||
if(botStorage.IsPickedUp()) {
|
||||
const item = botStorage.GetItemInHand();
|
||||
aio.Handle("BotMgr", "UnequipTheItem", GetUnitName("player", false), item.slot, item.bot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This handles listening on Bot Items being dragged to the bag. Attaches
|
||||
* to the default handler before run and handles bot items specifically.
|
||||
*/
|
||||
function StoreItemSlotHandlers(): void {
|
||||
|
||||
// Intercept Bags Item Slots Click Event
|
||||
for(let container = 1; container <= 13; container++) {
|
||||
for(let slot = 1; slot <= 36; slot++) {
|
||||
ItemClickFuncs.set(`${container}:${slot}`, _G[`ContainerFrame${container}Item${slot}`].GetScript("OnClick"));
|
||||
|
||||
_G[`ContainerFrame${container}Item${slot}`].SetScript("OnClick", (frame: WoWAPI.Button, ...args) => {
|
||||
|
||||
const bagId = frame.GetParent().GetID();
|
||||
const slotNum = frame.GetID();
|
||||
HandleUnequipItem(frame);
|
||||
print(`Unequipped - BagId: ${bagId} Slot: ${slotNum}`);
|
||||
const callback = ItemClickFuncs.get(`${bagId}:${slotNum}`);
|
||||
(callback) ? callback(frame, ...args) : print(`No callback for ${bagId}:${slotNum}`);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Intercept Bank Item Slots Click Event
|
||||
for(let bankSlot = 1; bankSlot <= _G[`NUM_BANKGENERIC_SLOTS`]; bankSlot++) {
|
||||
ItemClickFuncs.set(`bank:${bankSlot}`, _G[`BankFrameItem${bankSlot}`].GetScript("OnClick"));
|
||||
|
||||
_G[`BankFrameItem${bankSlot}`].SetScript("OnClick", (frame: WoWAPI.Button, ...args) => {
|
||||
|
||||
HandleUnequipItem(frame, true);
|
||||
const callback = ItemClickFuncs.get(`bank:${frame.GetID()}`);
|
||||
(callback) ? callback(frame, ...args) : print(`No callback for bank:${bankSlot}`)
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function UpdateBotFrame(botData: BotData) {
|
||||
// Set the new Talent Spec
|
||||
const talentSpec = <WoWAPI.FontString>ComponentsPool.get(compId(botData.entry, "SpecFont"));
|
||||
talentSpec.SetText(botData.talentSpecName);
|
||||
|
||||
// Update Resist Frames
|
||||
let resist = <WoWAPI.FontString>ComponentsPool.get(compId(botData.entry, "Resist1"));
|
||||
// resist.SetText(botData.allStats['Resistance: arcane']);
|
||||
resist = <WoWAPI.FontString>ComponentsPool.get(compId(botData.entry, "Resist2"));
|
||||
// resist.SetText(botData.allStats['Resistance: fire']);
|
||||
resist = <WoWAPI.FontString>ComponentsPool.get(compId(botData.entry, "Resist3"));
|
||||
// resist.SetText(botData.allStats['Resistance: nature']);
|
||||
resist = <WoWAPI.FontString>ComponentsPool.get(compId(botData.entry, "Resist4"));
|
||||
// resist.SetText(botData.allStats['Resistance: frost']);
|
||||
resist = <WoWAPI.FontString>ComponentsPool.get(compId(botData.entry, "Resist5"));
|
||||
// resist.SetText(botData.allStats['Resistance: shadow']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows or Creates a new Bot Equipment Management Frame
|
||||
* Every NPC Bot that is requested to be managed will get their own unique frame. This
|
||||
@@ -445,7 +655,7 @@ if(!aio.AddAddon()) {
|
||||
|
||||
mainFrame = InfoFramePool.get(botData.entry);
|
||||
|
||||
if(mainFrame) { print('main frame already created'); }
|
||||
// if(mainFrame) { print('main frame already created'); }
|
||||
// Build the complete frame if we do not already have one in the pool.
|
||||
if(!mainFrame) {
|
||||
mainFrame = CreateFrame("Frame", id("MainFrame"+botData.entry), UIParent, null, botData.entry);
|
||||
@@ -467,22 +677,12 @@ if(!aio.AddAddon()) {
|
||||
});
|
||||
|
||||
mainFrame.RegisterEvent("CURSOR_UPDATE");
|
||||
mainFrame.RegisterEvent("ITEM_LOCK_CHANGED");
|
||||
mainFrame.RegisterEvent("ITEM_UNLOCKED");
|
||||
// mainFrame.RegisterEvent("ITEM_LOCK_CHANGED");
|
||||
// mainFrame.RegisterEvent("ITEM_UNLOCKED");
|
||||
|
||||
mainFrame.SetScript("OnEvent", (frame: WoWAPI.Frame, eventName: WoWAPI.Event, ...args) => {
|
||||
if(eventName == "ITEM_LOCKED") {
|
||||
GetCursorInfo()
|
||||
print(args);
|
||||
for(const arg of args) {
|
||||
print(arg);
|
||||
}
|
||||
}
|
||||
mainFrame.SetScript("OnEvent", (frame: WoWAPI.Frame, eventName: WoWAPI.Event, ...args) => {
|
||||
});
|
||||
|
||||
|
||||
|
||||
// mainFrame.Hide();
|
||||
|
||||
BotItemTooltip = CreateFrame("GameTooltip", id("ItemToolTip"+botData.entry), mainFrame, "GameTooltipTemplate", botData.entry);
|
||||
BotItemTooltip.SetOwner(mainFrame, "ANCHOR_NONE");
|
||||
@@ -492,109 +692,31 @@ if(!aio.AddAddon()) {
|
||||
SetBackground(mainFrame);
|
||||
AddPortrait(mainFrame, botData);
|
||||
AddCharacterModel(mainFrame, botData);
|
||||
AddResistFrame(mainFrame);
|
||||
AddResistFrame(mainFrame, botData);
|
||||
AddEquipmentFrames(mainFrame, botData);
|
||||
CreateStats(mainFrame, botData);
|
||||
AddSoundEffects(mainFrame);
|
||||
|
||||
|
||||
InfoFramePool.set(botData.entry, mainFrame);
|
||||
ComponentsPool.set(compId(botData.entry, "tooltip"), <WoWAPI.GameTooltip>BotItemTooltip);
|
||||
mainFrame.Show();
|
||||
} else {
|
||||
mainFrame.Show();
|
||||
print("updating bot data");
|
||||
print(botData.talentSpecName);
|
||||
UpdateBotFrame(botData);
|
||||
}
|
||||
|
||||
// const button2 = CreateFrame("Button", id("CharacterNeckSlot"), mainFrame, "ItemButtonTemplate");
|
||||
// button2.SetPoint("TOP", button, "BOTTOM", 0, -3);
|
||||
// button2.SetSize(40,40);
|
||||
|
||||
// const [itemId, texture] = GetInventorySlotInfo(UIInvSlot.NECKSLOT);
|
||||
|
||||
// const itemTexture2 = button2.CreateTexture(id("ItemTextureNeck"), "OVERLAY");
|
||||
// itemTexture2.SetTexture(texture);
|
||||
// itemTexture2.SetPoint("CENTER", 0, 0);
|
||||
// itemTexture2.SetSize(38,38);
|
||||
|
||||
|
||||
|
||||
// const leftEquipment = CreateFrame("Frame", id("LeftEquipment"), mainFrame);
|
||||
// leftEquipment.SetPoint("TOPLEFT", 20, -73);
|
||||
// leftEquipment.SetSize(40, 330);
|
||||
|
||||
// const background = leftEquipment.CreateTexture(id("Background"), "OVERLAY");
|
||||
// background.SetTexture(0,0,0,0.7);
|
||||
// background.SetAllPoints(leftEquipment);
|
||||
|
||||
// const button = CreateFrame("Button", id("CharacterHeadSlot"), leftEquipment, "ItemButtonTemplate");
|
||||
// button.SetPoint("TOPLEFT", 0, 0);
|
||||
// button.SetSize(40,40);
|
||||
|
||||
// const itemTexture = button.CreateTexture(id("ItemTextureHead"), "OVERLAY");
|
||||
// itemTexture.SetTexture(GetItemIcon(botData.equipment[BotEquipSlot.HEAD]));
|
||||
// itemTexture.SetPoint("CENTER", 0, 0);
|
||||
// itemTexture.SetSize(36,36);
|
||||
|
||||
}
|
||||
|
||||
mainFrame.Show();
|
||||
|
||||
|
||||
// aio.Handle("BotMgr", "ParseBotEntry", UnitGUID("target"));
|
||||
// aio.Handle("BotMgr", "ShowComplexArray", { "one": 1, "two": 2, "three": 3 });
|
||||
|
||||
|
||||
// const headTex = GetItemIcon(botdetails.equipment[BotEquipSlot.HEAD]);
|
||||
// print(headTex);
|
||||
|
||||
|
||||
|
||||
|
||||
// const testTexture = itemFrame.CreateTexture(id("TestTexture"), "OVERLAY");
|
||||
// testTexture.SetTexture(GetItemIcon(2194));
|
||||
// // testTexture.SetSize(64,64);
|
||||
// testTexture.SetAllPoints(button);
|
||||
// testTexture.SetPoint("TOPLEFT", 0, 0);
|
||||
|
||||
|
||||
// SetItemButtonTexture(button, texture);
|
||||
|
||||
// button.SetScript("OnLoad", (frame) => {
|
||||
// const head = frame.CreateTexture("CharacterHeadSlotTexture", "ARTWORK");
|
||||
// head.SetAllPoints(button);
|
||||
// head.SetTexture(1,0,0,1);
|
||||
// });
|
||||
|
||||
|
||||
|
||||
|
||||
//button.SetName("CharacterHeadSlot");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// const frameCore = CreateFrame("Frame", "BotMgrCoreFrame", mainFrame);
|
||||
// frameCore.SetSize(600, 440);
|
||||
// frameCore.SetPoint("TOPLEFT", 0, 0);
|
||||
|
||||
// const mainTexture = frameCore.CreateTexture("BotMgrMainFrameTexture", "BACKGROUND");
|
||||
// mainTexture.SetAllPoints(frameCore);
|
||||
|
||||
// const titleText = frameCore.CreateFontString("BotMgrTitle", "ARTWORK");
|
||||
// titleText.SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE");
|
||||
// titleText.SetPoint("TOP", 0, -5);
|
||||
// titleText.SetText(GetUnitName("target", false));
|
||||
|
||||
// const unitTexture = frameChar.CreateTexture("BotMgrCharTexture", "BACKGROUND");
|
||||
// unitTexture.SetTexture(0, 0, 0);
|
||||
// unitTexture.SetAllPoints(frameChar);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
botMgrHandlers.ShowFrame = (botData: BotData) =>{
|
||||
botMgrHandlers.ShowFrame = (botData: BotData) => {
|
||||
botStorage.UpdateBotData(botData.entry, botData);
|
||||
ShowBotFrame(botData);
|
||||
}
|
||||
ShowBotFrame(botData);
|
||||
}
|
||||
|
||||
// Global calls to set things up
|
||||
StoreItemSlotHandlers();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3,19 +3,16 @@ let aio: AIO = {};
|
||||
|
||||
const SCRIPT_NAME = 'BotMgr';
|
||||
import { Logger } from "../../classes/logger";
|
||||
import { BotUnit } from "./botUnit";
|
||||
const log = new Logger(SCRIPT_NAME);
|
||||
|
||||
import {
|
||||
BotStat,
|
||||
BotEquipSlot,
|
||||
BotSlotName,
|
||||
BotEquipLast,
|
||||
BotStatLast,
|
||||
BotStat,
|
||||
BotEquipLast,
|
||||
ClassesMapping,
|
||||
CharacterClass,
|
||||
RacesMapping,
|
||||
CharacterRace,
|
||||
ItemQuality,
|
||||
CharacterRace,
|
||||
QualityType
|
||||
} from "../../constants/idmaps";
|
||||
|
||||
@@ -35,13 +32,19 @@ export type EquipmentList = Record<BotEquipmentSlotNum, Equipment>;
|
||||
export type BotData = {
|
||||
owner: string,
|
||||
name: string,
|
||||
level: number,
|
||||
talentSpec: number,
|
||||
talentSpecName: string,
|
||||
roles: number,
|
||||
entry: number,
|
||||
class: CharacterClass,
|
||||
classId: number,
|
||||
race: CharacterRace,
|
||||
raceId: number,
|
||||
equipment?: EquipmentList, // SlotName - ItemId See BotEquipSlot
|
||||
stats?: Record<number, number>, // StatId - Value
|
||||
leftStats?: Record<string, string>[],
|
||||
rightStats?: Record<string, string>[],
|
||||
allStats?: Record<string, string> // StatId - Value
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -90,89 +93,17 @@ function TargetIsEligible(player: Player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function GetMeleeStats () {
|
||||
return {
|
||||
left: [
|
||||
BotStat.STRENGTH,
|
||||
BotStat.AGILITY,
|
||||
BotStat.DAMAGE_MIN,
|
||||
BotStat.DAMAGE_MAX,
|
||||
BotStat.ATTACK_POWER,
|
||||
BotStat.HIT_RATING,
|
||||
BotStat.CRIT_RATING,
|
||||
BotStat.EXPERTISE,
|
||||
BotStat.ARMOR_PENETRATION_RATING,
|
||||
],
|
||||
right: [
|
||||
BotStat.HASTE_RATING,
|
||||
BotStat.ARMOR,
|
||||
BotStat.STAMINA,
|
||||
BotStat.DEFENSE_SKILL_RATING,
|
||||
BotStat.DODGE_RATING,
|
||||
BotStat.PARRY_RATING,
|
||||
BotStat.BLOCK_RATING,
|
||||
BotStat.BLOCK_VALUE
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function GetCasterStats() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @noSelf
|
||||
*/
|
||||
function GetBotDetails(bot: Creature): BotData {
|
||||
|
||||
const owner = bot.GetBotOwner();
|
||||
|
||||
// We can use bot entrys since they are 1:1 with GUIDs for shorter storage keys
|
||||
NpcDetailStorage[bot.GetEntry()] = {
|
||||
owner: owner.GetName(),
|
||||
name: bot.GetName(),
|
||||
entry: bot.GetEntry(),
|
||||
class: ClassesMapping[bot.GetBotClass()],
|
||||
classId: bot.GetBotClass(),
|
||||
race: RacesMapping[bot.GetRace()],
|
||||
raceId: bot.GetRace(),
|
||||
equipment: {} as EquipmentList,
|
||||
stats: {},
|
||||
};
|
||||
|
||||
print(bot.GetBotRoles());
|
||||
|
||||
|
||||
// Get all the equipment
|
||||
for(let slot=0; slot <= BotEquipLast; slot++) {
|
||||
const equipment = bot.GetBotEquipment(<BotEquipmentSlotNum>slot);
|
||||
|
||||
if(equipment) {
|
||||
NpcDetailStorage[bot.GetEntry()].equipment[slot] = {
|
||||
entry: equipment.GetEntry(),
|
||||
link: equipment.GetItemLink(),
|
||||
quality: <QualityType>equipment.GetQuality(),
|
||||
itemLevel: equipment.GetItemLevel(),
|
||||
enchantmentId: equipment.GetEnchantmentId(0),
|
||||
}
|
||||
} else {
|
||||
NpcDetailStorage[bot.GetEntry()].equipment[slot] = undefined;
|
||||
}
|
||||
try {
|
||||
const botUnit = new BotUnit(bot);
|
||||
NpcDetailStorage[bot.GetEntry()] = botUnit.toBotData();
|
||||
} catch (e) {
|
||||
log.error(`Could not get bot details: ${e}`);
|
||||
}
|
||||
|
||||
// get the stats we care about by Class
|
||||
// This will determine what stats to lookup for the bot.
|
||||
const lookups = GetMeleeStats();
|
||||
|
||||
|
||||
lookups.left.forEach(stat => {
|
||||
const result = bot.GetBotStat(stat);
|
||||
NpcDetailStorage[bot.GetEntry()].stats[stat] = result;
|
||||
});
|
||||
lookups.right.forEach(stat => {
|
||||
const result = bot.GetBotStat(stat);
|
||||
NpcDetailStorage[bot.GetEntry()].stats[stat] = result;
|
||||
});
|
||||
|
||||
return NpcDetailStorage[bot.GetEntry()];
|
||||
}
|
||||
@@ -189,26 +120,52 @@ function EquipTheItem(player: string, botEntry: number, slot: BotEquipmentSlotNu
|
||||
return;
|
||||
}
|
||||
|
||||
const owner = GetPlayerByName(player);
|
||||
const creatures = owner.GetCreaturesInRange(60, botEntry) as Creature[];
|
||||
const bot = creatures[0];
|
||||
try {
|
||||
const owner = GetPlayerByName(player);
|
||||
const creatures = owner.GetCreaturesInRange(300, botEntry) as Creature[];
|
||||
const bot = creatures[0];
|
||||
let data;
|
||||
|
||||
const isEligible = bot.BotCanEquipItem(item, slot);
|
||||
if(!isEligible) {
|
||||
log.error(`Bot cannot equip item: ${item} in slot: ${slot}`);
|
||||
return;
|
||||
}
|
||||
// already equipped
|
||||
|
||||
if(bot.BotEquipItem(item, slot)) {
|
||||
data = GetBotDetails(bot);
|
||||
// log.log(`Bot successfully equipped item: ${item} in slot: ${slot}`);
|
||||
aio.Handle(bot.GetBotOwner(), 'BotMgr', 'OnEquipSuccess',botEntry, slot, data.equipment[slot]);
|
||||
} else {
|
||||
// log.error(`Bot failed to equip item: ${item} in slot: ${slot}`);
|
||||
aio.Handle(bot.GetBotOwner(), 'BotMgr', 'OnEquipFail', botEntry, slot, item, link);
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(`Error equipping item: ${error}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const isEligible = bot.BotCanEquipItem(item, slot);
|
||||
if(!isEligible) {
|
||||
log.error(`Bot cannot equip item: ${item} in slot: ${slot}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if(bot.BotEquipItem(item, slot)) {
|
||||
function UnequipTheItem(player: string, slot: number, botEntry: number): void {
|
||||
try {
|
||||
const owner = GetPlayerByName(player);
|
||||
const creatures = owner.GetCreaturesInRange(60, botEntry) as Creature[];
|
||||
const bot = creatures[0];
|
||||
|
||||
if(bot.BotUnequipBotItem(slot)) {
|
||||
GetBotDetails(bot);
|
||||
log.log(`Bot successfully equipped item: ${item} in slot: ${slot}`);
|
||||
aio.Handle(bot.GetBotOwner(), 'BotMgr', 'OnEquipSuccess',botEntry, slot, item, link);
|
||||
log.log(`Bot successfully unequipped item at slot: ${slot}`);
|
||||
aio.Handle(bot.GetBotOwner(), 'BotMgr', 'OnUnEquipSuccess',slot, botEntry, );
|
||||
} else {
|
||||
log.error(`Bot failed to equip item: ${item} in slot: ${slot}`);
|
||||
aio.Handle(bot.GetBotOwner(), 'BotMgr', 'OnEquipFail', botEntry, slot, item, link);
|
||||
log.error(`Bot failed to equip item in slot: ${slot}`);
|
||||
aio.Handle(bot.GetBotOwner(), 'BotMgr', 'OnUnEquipFail', slot, botEntry);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
log.error(`Error unequipping item: ${error}`);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -217,11 +174,6 @@ const ShowBotMgr: player_event_on_command = (event: number,player: Player, comma
|
||||
|
||||
if(TargetIsEligible(player)) {
|
||||
const botdetails = GetBotDetails(GetBotNpc(player));
|
||||
|
||||
// loop through bot details and print the key value pair
|
||||
for (const [key, value] of Object.entries(botdetails.equipment)) {
|
||||
print(`${key}: ${value}`);
|
||||
}
|
||||
|
||||
aio.Handle(player, 'BotMgr', 'ShowFrame', botdetails);
|
||||
return false;
|
||||
@@ -264,7 +216,8 @@ function GetBotPanelInfo(player: Player): void {
|
||||
const botMgrHandlers = aio.AddHandlers('BotMgr', {
|
||||
TargetIsEligible,
|
||||
GetBotPanelInfo,
|
||||
"EquipTheItem": EquipTheItem
|
||||
"EquipTheItem": EquipTheItem,
|
||||
"UnequipTheItem": UnequipTheItem,
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -41,7 +41,54 @@ export const BotSlotName = {
|
||||
} as const;
|
||||
|
||||
export const BotEquipLast = 17;
|
||||
|
||||
export const BotStatLabel = {
|
||||
"total str": "Strength",
|
||||
"total agi": "Agility",
|
||||
"total sta": "Stamina",
|
||||
"total int": "Intellect",
|
||||
"total spi": "Spirit",
|
||||
"Melee AP": "Power",
|
||||
"Ranged AP": "Power",
|
||||
"armor": "Armor",
|
||||
"crit": "Crit %",
|
||||
"defense": "Defense",
|
||||
"miss": "Miss",
|
||||
"dodge": "Dodge",
|
||||
"parry": "Parry",
|
||||
"block": "Block",
|
||||
"block value": "Block Value",
|
||||
"Damage taken melee": "Physical Resist",
|
||||
"Damage taken spell": "Spell Resist",
|
||||
"Damage range mainhand": "Dmg Main",
|
||||
"Damage range offhand": "Dmg Off",
|
||||
"Attack time offhand": "Speed Off",
|
||||
"Damage mult mainhand": "Damage Multiplier (Mainhand)",
|
||||
"Attack time mainhand": "Speed Main",
|
||||
"Damage range ranged": "Dmg Range",
|
||||
"Damage mult ranged": "Damage Multiplier (Ranged)",
|
||||
"Attack time ranged": "Speed",
|
||||
"base hp": "Base Health",
|
||||
"total hp": "Total Health",
|
||||
"base mana": "Base Mana",
|
||||
"total mana": "Total Mana",
|
||||
"spell power": "Bonus Dmg",
|
||||
"health regen_5 bonus": "Health Regen (5s Bonus)",
|
||||
"haste": "Haste Rating",
|
||||
"hit": "Hit Rating",
|
||||
"expertise": "Expertise",
|
||||
"mana regen_5 casting": "MP5",
|
||||
"armor penetration": "Armor Pen",
|
||||
"spell penetration": "Spell Pen",
|
||||
"Resistance: holy": "Resist Holy",
|
||||
"Resistance: fire": "Resist Fire",
|
||||
"Resistance: nature": "Resist Nature",
|
||||
"Resistance: frost": "Resist Frost",
|
||||
"Resistance: shadow": "Resist Shadow",
|
||||
"Resistance: arcane": "Resist Arcane",
|
||||
} as const;
|
||||
|
||||
export type BotStatName = Partial<typeof BotStatLabel[keyof typeof BotStatLabel]>;
|
||||
|
||||
export const BotStat = {
|
||||
MANA: 0,
|
||||
HEALTH: 1,
|
||||
@@ -100,7 +147,7 @@ export const BotStat = {
|
||||
MAX_BOT_ITEM_MOD: 59,
|
||||
BOT_STAT_MOD_RESISTANCE_START: 51, // Assuming BOT_STAT_MOD_ARMOR is defined somewhere
|
||||
} as const;
|
||||
|
||||
|
||||
export const BotStatLast = 58;
|
||||
|
||||
export const UIInvSlot = {
|
||||
@@ -167,7 +214,7 @@ export const RacesMapping: Record<number, string> = {
|
||||
|
||||
export type CharacterRace = typeof RacesMapping[keyof typeof RacesMapping];
|
||||
|
||||
export const BotTalentSpecs = {
|
||||
export const TalentSpecs = {
|
||||
WARRIOR_ARMS : 1,
|
||||
WARRIOR_FURY : 2,
|
||||
WARRIOR_PROTECTION : 3,
|
||||
@@ -203,10 +250,6 @@ export const BotTalentSpecs = {
|
||||
END : 31
|
||||
} as const;
|
||||
|
||||
export function talentSpecName(id: number) {
|
||||
return Object.keys(BotTalentSpecs).find(key => BotTalentSpecs[key] === id);
|
||||
}
|
||||
|
||||
export const BotRoles = {
|
||||
NONE : 0,
|
||||
TANK : 1,
|
||||
@@ -226,10 +269,10 @@ export const BotRoles = {
|
||||
AUTOLOOT_RARE : 16384,
|
||||
AUTOLOOT_EPIC : 32768,
|
||||
AUTOLOOT_LEGENDARY : 65536,
|
||||
MASK_MAIN : (1 | 2 | 4 | 8 | 16),
|
||||
MASK_GATHERING : (64 | 128 | 256 | 512),
|
||||
MASK_LOOTING : (2048 | 4096 | 8192 | 16384 | 32768 | 65536),
|
||||
BOT_MAX_ROLE : 131072,
|
||||
// MASK_MAIN : (1 | 2 | 4 | 8 | 16),
|
||||
// MASK_GATHERING : (64 | 128 | 256 | 512),
|
||||
// MASK_LOOTING : (2048 | 4096 | 8192 | 16384 | 32768 | 65536),
|
||||
// BOT_MAX_ROLE : 131072,
|
||||
} as const;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user