Batch #1653 by ragnarok-clanker: 0 byte-identical, 2 confirmed by peer review. - fn_23876 CSession::IsSkillIdInRange6018: logic confirmed by peer review - fn_23877 CSession::IsSkillIdInRange6001: logic confirmed by peer review Peer-reviewed-by: eAthena Reviewed-by: ragnarok-clanker
206 lines
6.5 KiB
C++
206 lines
6.5 KiB
C++
#include "Client/Session.h"
|
|
#include "UI/Shortcuts/ShortcutCooldowns.h"
|
|
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
#include <windows.h>
|
|
#include <timeapi.h>
|
|
|
|
namespace {
|
|
// OFFSET: 0x00E1DCA0
|
|
// FUNCTION: fn_23875
|
|
bool IsFirstRange(unsigned id) {
|
|
return id - 8000u <= 60;
|
|
}
|
|
|
|
// OFFSET: 0x00E1DD20
|
|
// FUNCTION: fn_23878
|
|
bool IsOtherRange(unsigned id) {
|
|
return id - 8200u <= 41 || id - 8400u <= 57;
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00E1DCE0
|
|
// FUNCTION: fn_23876
|
|
int CSession::IsSkillIdInRange6018(unsigned id) const {
|
|
return id - 6018u <= 34;
|
|
}
|
|
|
|
// OFFSET: 0x00E1DD00
|
|
// FUNCTION: fn_23877
|
|
int CSession::IsSkillIdInRange6001(unsigned id) const {
|
|
return id - 6001u <= 51;
|
|
}
|
|
|
|
// OFFSET: 0x00D42070
|
|
// FUNCTION: fn_21827
|
|
void ShortcutCooldowns::LoadSnapshot(
|
|
const void* packet, const std::list<ShortcutCooldownIcon>& mainIcons, const std::list<ShortcutCooldownIcon>& alternateIcons, int replayMode,
|
|
const std::uint32_t& serverTick
|
|
) {
|
|
this->records.clear();
|
|
const auto* bytes = static_cast<const unsigned char*>(packet);
|
|
std::int16_t size;
|
|
std::memcpy(&size, bytes + 2, sizeof(size));
|
|
const int count = (size - 2) / 10;
|
|
|
|
for (int index = 0; index < count; ++index) {
|
|
const unsigned char* source = bytes + 4 + index * 10;
|
|
std::uint16_t id;
|
|
std::uint32_t duration;
|
|
std::uint32_t remaining;
|
|
std::memcpy(&id, source, sizeof(id));
|
|
std::memcpy(&duration, source + 2, sizeof(duration));
|
|
std::memcpy(&remaining, source + 6, sizeof(remaining));
|
|
const std::uint32_t now = replayMode == 1 ? serverTick : timeGetTime();
|
|
ShortcutCooldownRecord value{id, now + remaining, duration, {}, {}};
|
|
|
|
for (const ShortcutCooldownIcon& icon : mainIcons) {
|
|
if (icon.id == id) {
|
|
value.main.emplace_back(icon.slot, icon.x, icon.y, duration, now, duration - remaining, 0);
|
|
}
|
|
}
|
|
|
|
for (const ShortcutCooldownIcon& icon : alternateIcons) {
|
|
if (icon.id == id) {
|
|
value.alternate.emplace_back(icon.slot, icon.x, icon.y, duration, now, duration - remaining, 0);
|
|
}
|
|
}
|
|
|
|
this->records.push_back(value);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00D41990
|
|
// FUNCTION: fn_21826
|
|
void ShortcutCooldowns::ApplyStart(
|
|
const void* packet, const std::list<ShortcutCooldownIcon>& mainIcons, const std::list<ShortcutCooldownIcon>& alternateIcons, int replayMode,
|
|
const std::uint32_t& serverTick
|
|
) {
|
|
const auto* bytes = static_cast<const unsigned char*>(packet);
|
|
std::uint16_t id;
|
|
std::uint32_t duration;
|
|
std::memcpy(&id, bytes + 2, sizeof(id));
|
|
std::memcpy(&duration, bytes + 4, sizeof(duration));
|
|
const std::uint32_t now = replayMode == 1 ? serverTick : timeGetTime();
|
|
ShortcutCooldownRecord value{id, now + duration, duration, {}, {}};
|
|
const auto find = [&]() {
|
|
return std::find_if(this->records.begin(), this->records.end(), [&](const ShortcutCooldownRecord& record) { return record.id == id; });
|
|
};
|
|
|
|
for (const ShortcutCooldownIcon& icon : mainIcons) {
|
|
if (icon.id != id) {
|
|
continue;
|
|
}
|
|
|
|
const auto entry = find();
|
|
if (entry == this->records.end()) {
|
|
value.main.emplace_back(icon.slot, icon.x, icon.y, duration, now, 0, 0);
|
|
this->records.push_back(value);
|
|
} else {
|
|
const auto slot = std::find_if(entry->main.begin(), entry->main.end(), [&](const CooldownState& state) { return state.slot == icon.slot; });
|
|
if (slot == entry->main.end()) {
|
|
entry->main.emplace_back(icon.slot, icon.x, icon.y, duration, now, 0, 0);
|
|
} else {
|
|
this->records.erase(entry);
|
|
|
|
value.main.emplace_back(icon.slot, icon.x, icon.y, duration, now, 0, 0);
|
|
this->records.push_back(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const ShortcutCooldownIcon& icon : alternateIcons) {
|
|
if (icon.id == id && find() == this->records.end()) {
|
|
value.alternate.emplace_back(icon.slot, icon.x, icon.y, duration, now, 0, 0);
|
|
this->records.push_back(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
// INLINED
|
|
bool ShortcutCooldowns::RotateRows(int amount, int bank, int& rotation0, int& rotation1, const CooldownClock& clock) {
|
|
const int rows = amount < 4 ? amount : amount % 4;
|
|
if (rows <= 0) {
|
|
return false;
|
|
}
|
|
|
|
if (bank == 0 || bank == 1) {
|
|
int& rotation = bank == 0 ? rotation0 : rotation1;
|
|
rotation += rows;
|
|
if (rotation >= 4) {
|
|
rotation -= 4;
|
|
}
|
|
}
|
|
|
|
const std::uint32_t now = clock.Now();
|
|
|
|
for (auto entry = this->records.begin(); entry != this->records.end();) {
|
|
if (entry->end <= now) {
|
|
entry = this->records.erase(entry);
|
|
continue;
|
|
}
|
|
|
|
for (CooldownState& state : entry->main) {
|
|
state.slot -= 9 * rows;
|
|
state.y -= 33 * rows;
|
|
if (state.slot < 0) {
|
|
state.slot += 36;
|
|
state.y += 132;
|
|
}
|
|
}
|
|
|
|
++entry;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// INLINED
|
|
void ShortcutCooldowns::PaintMain(
|
|
const std::list<ShortcutCooldownIcon>& icons, int rows, int x, int y, CooldownDrawing& drawing, const CooldownClock& clock, RenderCommandPool& pool,
|
|
CRenderSystemBase& system
|
|
) {
|
|
const int limit = rows * 33 + 4;
|
|
this->Paint(icons, &ShortcutCooldownRecord::main, limit, x, y, drawing, clock, pool, system);
|
|
}
|
|
|
|
// INLINED
|
|
void ShortcutCooldowns::PaintAlternate(
|
|
const std::list<ShortcutCooldownIcon>& icons, int x, int y, CooldownDrawing& drawing, const CooldownClock& clock, RenderCommandPool& pool,
|
|
CRenderSystemBase& system
|
|
) {
|
|
this->Paint(icons, &ShortcutCooldownRecord::alternate, 0, x, y, drawing, clock, pool, system);
|
|
}
|
|
|
|
// INLINED
|
|
void ShortcutCooldowns::Paint(
|
|
const std::list<ShortcutCooldownIcon>& icons, std::list<CooldownState> ShortcutCooldownRecord::* values, int limit, int x, int y, CooldownDrawing& drawing,
|
|
const CooldownClock& clock, RenderCommandPool& pool, CRenderSystemBase& system
|
|
) {
|
|
const std::uint32_t now = clock.Now();
|
|
|
|
for (auto entry = this->records.begin(); entry != this->records.end();) {
|
|
if (entry->end <= now) {
|
|
entry = this->records.erase(entry);
|
|
continue;
|
|
}
|
|
|
|
std::list<CooldownState>& states = (*entry).*values;
|
|
|
|
for (const ShortcutCooldownIcon& icon : icons) {
|
|
if (entry->id == icon.id || (entry->id == 577 && !IsFirstRange(icon.id)) || (entry->id == 9999 && (IsFirstRange(icon.id) || IsOtherRange(icon.id)))) {
|
|
const auto previous = std::find_if(states.begin(), states.end(), [&](const CooldownState& state) { return state.slot == icon.slot; });
|
|
if (previous == states.end()) {
|
|
states.emplace_back(icon.slot, icon.x, icon.y, entry->duration, entry->end - entry->duration, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (CooldownState& state : states) {
|
|
drawing.Draw(0, 0, 12, 12, state, limit, x, y, clock, pool, system);
|
|
}
|
|
|
|
++entry;
|
|
}
|
|
}
|