Combos: cooldown labels on the skill bar, steps follow the arts' current levels
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
5a0db24b83
commit
075f9e2c8a
6 files changed
+199
-4
No files matched your search
@@ -156,6 +156,59 @@ inline ArtCooldown GetArtCooldown(void* creature, uint16_t art) {
|
||||
return {remaining, Float(entry, kCooldownTotal), perSecond > 0.0f ? remaining / perSecond : 0.0f};
|
||||
}
|
||||
|
||||
// Combos (made at the Kombomeister): a vector of 0x26-byte entries at +0x10e /
|
||||
// +0x112 of cCreatureArts, at most 4 (cCreatureArts::FindCombo 0x5819a0):
|
||||
// +0 u16 combo id (0x200..0x204, definitions FindComboDef 0x4d2970)
|
||||
// +2 u32[4] art of each step (0: empty)
|
||||
// +0x12 u16[4] level of each step's art, stored when the combo was made
|
||||
// +0x1a float total (sum of the arts' regeneration at those levels)
|
||||
// +0x1e float charge rate, recomputed each update while charging:
|
||||
// 1 + average of the arts' regeneration speed % / 100
|
||||
// +0x22 float charge: counts up to the total (ready at total,
|
||||
// cCreatureArts::IsComboReady 0x581920); using the combo
|
||||
// lowers it (cCreatureArts::AddGroupRegen, combo branch)
|
||||
// cCreatureArts::SetCombo (0x581290, (index, arts[4], levels[4], id), ret
|
||||
// 0x10) fills an entry and computes the total; the charge starts at 0.
|
||||
// A taskbar slot of type 4 holds combo 0x200 + index.
|
||||
constexpr size_t kCombosBegin = 0x10e;
|
||||
constexpr size_t kCombosEnd = 0x112;
|
||||
constexpr size_t kComboSize = 0x26;
|
||||
constexpr size_t kComboId = 0x0;
|
||||
constexpr size_t kComboArts = 0x2;
|
||||
constexpr size_t kComboLevels = 0x12;
|
||||
constexpr size_t kComboTotal = 0x1a;
|
||||
constexpr size_t kComboRate = 0x1e;
|
||||
constexpr size_t kComboCharge = 0x22;
|
||||
constexpr unsigned kComboSteps = 4;
|
||||
constexpr uint32_t kComboRefBase = 0x200;
|
||||
constexpr uint32_t kArtSlotTypeCombo = 4;
|
||||
|
||||
// Entry `index` of the combo vector of cCreatureArts `arts`, or null.
|
||||
inline uint8_t* ComboEntry(uint8_t* arts, unsigned index) {
|
||||
auto* begin = *reinterpret_cast<uint8_t**>(arts + kCombosBegin);
|
||||
auto* end = *reinterpret_cast<uint8_t**>(arts + kCombosEnd);
|
||||
if (!begin || index >= static_cast<unsigned>(end - begin) / kComboSize) {
|
||||
return nullptr;
|
||||
}
|
||||
return begin + index * kComboSize;
|
||||
}
|
||||
|
||||
// The cooldown of the combo in a taskbar slot (reference 0x200 + index).
|
||||
inline ArtCooldown GetComboCooldown(void* creature, uint32_t slotRef) {
|
||||
auto* arts = static_cast<uint8_t*>(creature) + kCreatureArts;
|
||||
uint8_t* entry = slotRef >= kComboRefBase ? ComboEntry(arts, slotRef - kComboRefBase) : nullptr;
|
||||
if (!entry) {
|
||||
return {};
|
||||
}
|
||||
const float total = Float(entry, kComboTotal);
|
||||
const float remaining = total - Float(entry, kComboCharge);
|
||||
if (remaining <= 0.0f) {
|
||||
return {0.0f, total, 0.0f};
|
||||
}
|
||||
const float rate = Float(entry, kComboRate);
|
||||
return {remaining, total, rate > 0.0f ? remaining / rate : 0.0f};
|
||||
}
|
||||
|
||||
// cCreature::IsAlly (0x548f20): whether object `id` is an ally of `creature`.
|
||||
inline bool IsAlly(void* creature, uint32_t id) {
|
||||
using Fn = char(__fastcall*)(void*, void*, uint32_t);
|
||||
|
||||
Reference in new issue
Block a user