Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions src/player_features/loot-indicator/loot-indicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
UnitItemDrop
} from "./modules/unit-item-drops";
import {ItemClass} from "./modules/item-groups";
import {initItemsDB} from "./modules/items-db";
import {initItemsDB, getItemById} from "./modules/items-db";
import {
calcUnitHpBarPosition,
initIsReforgedUnitModelsEnabledLocal,
Expand Down Expand Up @@ -113,13 +113,6 @@ function enablePreviewFeatureToggleChatCommand() {
})
}

function getSingleGroupDrop(itemDropSets: ItemDropSet[]): RandomItemGroupDrop | undefined {
if (itemDropSets.length === 1 && itemDropSets[0].itemDrops.length === 1
&& itemDropSets[0].itemDrops[0] instanceof RandomItemGroupDrop) {
return itemDropSets[0].itemDrops[0];
}
}

function isTomeDrop(itemDrop: ItemDrop): boolean {
if (itemDrop instanceof RandomItemGroupDrop) {
const group = itemDrop.itemGroup;
Expand All @@ -130,6 +123,22 @@ function isTomeDrop(itemDrop: ItemDrop): boolean {
return false;
}

function areAllDropsTomes(itemDropSets: ItemDropSet[]): boolean {
for (const set of itemDropSets) {
for (const drop of set.itemDrops) {
if (drop instanceof RandomItemGroupDrop) {
if (!isTomeDrop(drop)) return false;
} else {
const item = getItemById(drop.getRawId());
if (!item) return false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't do those checks for items from drop sets - they are guaranteed to not be null anyway and it keeps it consistent with other code

if (item.classification !== ItemClass.Power_Up) return false;
if (item.level !== 1 && item.level !== 2) return false;
}
Comment on lines +129 to +136
Copy link
Copy Markdown
Contributor

@Psimage Psimage Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this to isTomeDrop (so it check for group tome drop and single item drop)

}
}
return true;
}

function enableLootTablePreviewUI() {
LootTableUI.init();

Expand Down Expand Up @@ -170,14 +179,14 @@ class UnitLootIndicator {
const itemDropSets = unitItemDrop.dropSets;
let e: Effect;

//In 99% of cases a unit has a single set (drops 1 item) with a single group item drop (can drop any item from that group)
const groupDrop = getSingleGroupDrop(itemDropSets);
if (groupDrop && isTomeDrop(groupDrop)) {
if (areAllDropsTomes(itemDropSets)) {
e = Effect.create("loot-indicator\\loot-indicator-tome.mdx", 0, 0)!;
} else {
e = Effect.create("loot-indicator\\loot-indicator-generic.mdx", 0, 0)!;
}

e.scale = 1.5;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check with @Kenshin on changes to indicator appearance. I think it looks better with this scale, but maybe too big? Like 1.3 - 1.4 maybe?


//For units with mana bar, we adjust the position of the effect model with animation
//We don't use Z offset for effect in the world, because that will affect "billboarding",
//and will lead to the effect slightly shifting relative to HP bar depending on the camera angle
Expand Down
2 changes: 1 addition & 1 deletion src/player_features/loot-indicator/modules/item-groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class ItemGroup {
export enum ItemClass {
Permanent = "Permanent",
Charged = "Charged",
Power_Up = "PowerUp",
Power_Up = "Power Up",
Artifact = "Artifact",
Purchasable = "Purchasable",
Campaign = "Campaign",
Expand Down
84 changes: 67 additions & 17 deletions src/player_features/loot-indicator/modules/loot-table-ui.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
import {Frame} from "w3ts";
import {getItemById} from "./items-db";
import {getAllItemIds, ItemDropSet, RandomItemGroupDrop} from "./unit-item-drops";
import { ItemClass } from "./item-groups";

const ITEM_CLASS_PRIORITY: Record<ItemClass, number> = {
[ItemClass.Permanent]: 0,
[ItemClass.Charged]: 1,
[ItemClass.Power_Up]: 2,
[ItemClass.Artifact]: 3,
[ItemClass.Purchasable]: 4,
[ItemClass.Campaign]: 5,
[ItemClass.Misc]: 6
};

function sortItems(itemIds: string[]): string[] {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do sorting ones in findMapInitialCreepsWithDrops(). No need to sort them every time we show them.

return itemIds
.map(id => getItemById(id)!)
.sort((a, b) => {
if (a.level !== b.level) return b.level - a.level;
const aPriority = ITEM_CLASS_PRIORITY[a.classification] ?? 999;
const bPriority = ITEM_CLASS_PRIORITY[b.classification] ?? 999;
if (aPriority !== bPriority) return aPriority - bPriority;
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
})
.map(i => i.id);
}

export class LootTableUI {
static INSTANCE: LootTableUI;
Expand Down Expand Up @@ -48,14 +72,31 @@ export class LootTableUI {
show(dropSets: ItemDropSet[]) {
this.mainParent.setVisible(true)

this.allDropsBtn.setTooltip(`|cffffff00Full loot table (${dropSets.length} drops)|r`, buildDropsInfoMsg(dropSets))
const dropWord = dropSets.length === 1 ? "drop" : "drops";
this.allDropsBtn.setTooltip(`|cffffff00Loot Table (${dropSets.length} ${dropWord})|r`, buildDropsInfoMsg(dropSets))

let itemIds = getAllItemIds(dropSets);
itemIds = Array.from(new Set(itemIds));
itemIds = sortItems(itemIds);

// Can't fit more than 12 right now.
if (itemIds.length > LootTableUI.MAX_ITEMS) {
itemIds = itemIds.slice(0, LootTableUI.MAX_ITEMS)
}

if (itemIds.length < LootTableUI.MAX_ITEMS) {
this.allDropsBtn.btn.setSize(0.04, 0.04)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 0.039 is more closer to the actual icon size

} else {
this.allDropsBtn.btn.setSize(0.02, 0.02)
}
this.allDropsBtn.btn.clearPoints()
this.allDropsBtn.btn.setPoint(
FRAMEPOINT_BOTTOMRIGHT,
Frame.fromOrigin(ORIGIN_FRAME_COMMAND_BUTTON, 11),
FRAMEPOINT_BOTTOMRIGHT,
0, 0
)
Comment on lines +92 to +98
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can remove this. The point is already set in constructor.


for (let i = 0; i < LootTableUI.MAX_ITEMS; i++) {
const itemBtn = this.itemBtnList[i];
const itemId = itemIds[i];
Expand Down Expand Up @@ -156,26 +197,35 @@ function buildDropsInfoMsg(sets: ItemDropSet[]): string {
return sets.map((set, i) => {
let m = `|cffffff00== Drop ${i + 1} `;

//Short most common form
// Short most common form
if (set.itemDrops.length === 1 && set.itemDrops[0] instanceof RandomItemGroupDrop) {
const drop = set.itemDrops[0] as RandomItemGroupDrop;
m += `|cff00ff00[${drop.itemGroup.itemClass}, Level ${drop.itemGroup.itemLevel}]|r\n`
m += set.itemDrops.flatMap(d => d.getDropItemIds())
.map(id => ` ${getItemById(id)!.name}`)
.join("\n")
//A set that contains a list of specific items or multiple GroupDrops, or a mix of both

const ids = Array.from(new Set(set.itemDrops.flatMap(d => d.getDropItemIds())));
const sortedIds = sortItems(ids);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do sorting ones in findMapInitialCreepsWithDrops(). No need to sort them every time we show them.


m += sortedIds.map(id => ` ${getItemById(id)!.name}`).join("\n");
// A set that contains a list of specific items or multiple GroupDrops, or a mix of both
} else {
m += `|cff00ff00[Custom drop pool]|r\n`
m += set.itemDrops.map(d => {
if (d instanceof RandomItemGroupDrop) {
return ` |cff00ff00[${d.itemGroup.itemClass}, Level ${d.itemGroup.itemLevel}]|r\n` +
d.getDropItemIds()
.map(id => ` - ${getItemById(id).name}`)
.join("\n")
} else {
return ` ${getItemById(d.getRawId()).name}`
}
}).join("\n")
m += `|cff00ff00[Custom]|r\n`

const allIds = Array.from(
new Set(
set.itemDrops.flatMap(d =>
d instanceof RandomItemGroupDrop
? d.getDropItemIds()
: [d.getRawId()]
)
)
);

const sortedIds = sortItems(allIds);

m += sortedIds.map(id => {
const item = getItemById(id)!;
return ` ${item.name} |cff00ff00[${item.classification}, Level ${item.level}]|r`;
}).join("\n");
Comment on lines 210 to +228
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes all "items" within a set clamped into one big chunk. I like the previous one better.

Old
Image

Now
Image

}

return m;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ export function findMapInitialCreepsWithDrops(): UnitItemDrop[] {
} else if (getItemById(itemOrGroupId) !== undefined) {
return [new SpecificItemDrop(itemOrGroupId)]
} else {
print(`Unknown item drop id "${itemOrGroupId}" for unit "${unit.name}" at (${unit.x}, ${unit.y}).`);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment instead. This might be useful in the future.
But im not even sure if this have to be disable, we could fix faster with this one enabled xD

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can for example have a creep with
Item Set 1 (Total Chance: 100%)

  • 100% - None
    That would still trigger the debug message.
    Debug message could still somewhat be acceptable for casual ladder games, but considering our triggers also get used for tournament games, I'd rather avoid them.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All current maps do not print this msg.

If new map is added. Would it be better to have this msg, temporarily disable the feature/or msg, fix the bug in the feature or a map, then enable it back.

Or its better to hide all the bugs?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a non-blocking issue, no? I would just print some warning messages when you run the script

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean by

I would just print some warning messages when you run the script

But, if you think it's an issue - you can comment it out instead of disabling.

Ideally i would like for print() to be toggleable at runtime and enabled for dev builds.
Like a logging system. Then we could take somebody's replay, enable logging - and there would be prints/writes to disk when watching the replay - may help with debugging when issue happens for end users.

return [] as ItemDrop[];
}
});
Expand Down