Merge branch 'main' of https://clank.rodecomp.online/git/clank/rodecomp
This commit is contained in:
commit
41b839b378
41 changed files with 2250 additions and 218 deletions
|
|
@ -3,13 +3,16 @@
|
|||
#include "Resource/ResourceMgr.h"
|
||||
#include "Resource/SkinPalette.h"
|
||||
#include "Resource/TextureNames.h"
|
||||
#include "UI/Buttons/UIBitmapButton.h"
|
||||
#include "UI/Buttons/UICashEmotionSprBtn.h"
|
||||
#include "UI/CashEmotion/UICashEmotionPack.h"
|
||||
#include "UI/CashEmotion/UICashEmotionPiece.h"
|
||||
#include "UI/Chat/ChatSuggestions.h"
|
||||
#include "UI/Edit/UIEditCtrl.h"
|
||||
#include "UI/Window/WindowBorder.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
|
|
@ -23,22 +26,34 @@ CCashEmotionMgr* g_cashEmotionMgr = nullptr;
|
|||
// GLOBAL: gl_24484
|
||||
ChatSuggestions* g_chatSuggestions = nullptr;
|
||||
|
||||
class ICashEmotionAction {
|
||||
public:
|
||||
virtual ~ICashEmotionAction();
|
||||
virtual void Execute(int packId, int argument) = 0;
|
||||
};
|
||||
|
||||
class UICashEmotionMiniWnd : public UIWindow {
|
||||
public:
|
||||
// OFFSET: 0x007C9200
|
||||
void Slot15(int width, int height) override;
|
||||
void Paint() override;
|
||||
int SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) override;
|
||||
|
||||
unsigned int Select(int actionId);
|
||||
void Select(CashEmotionCommand* command);
|
||||
void Previous();
|
||||
void Refresh(int first);
|
||||
void Next();
|
||||
void SetIndex(int index);
|
||||
|
||||
protected:
|
||||
/* 007C */ CashEmotionCommand* m_selected;
|
||||
/* 0080 */ UICashEmotionPiece* m_first;
|
||||
/* 0084 */ UICashEmotionPiece* m_second;
|
||||
/* 0088 */ UICashEmotionPiece* m_third;
|
||||
/* 008C */ UIButton* m_previous;
|
||||
/* 0090 */ UIButton* m_next;
|
||||
/* 0094 */ void* unknown_0094;
|
||||
/* 0080 */ std::array<UICashEmotionPiece*, 3> m_pieces;
|
||||
/* 008C */ UIBitmapButton* m_previous;
|
||||
/* 0090 */ UIBitmapButton* m_next;
|
||||
/* 0094 */ ICashEmotionAction* m_action;
|
||||
/* 0098 */ int m_page;
|
||||
/* 009C */ int m_selectedIndex;
|
||||
UICashEmotionPieceContext* m_controls;
|
||||
};
|
||||
|
||||
// OFFSET: 0x00592290
|
||||
|
|
@ -608,7 +623,7 @@ void CCashEmotionMgr::SetOwnedPack(int packId, unsigned int expiry) {
|
|||
for (auto it = this->m_expiry.begin(); it != this->m_expiry.end(); ++it) {
|
||||
if (it->first == packId) {
|
||||
if (expiry) {
|
||||
it->second.seconds = expiry;
|
||||
it->second.Set(expiry);
|
||||
} else {
|
||||
this->m_expiry.erase(it);
|
||||
}
|
||||
|
|
@ -617,7 +632,7 @@ void CCashEmotionMgr::SetOwnedPack(int packId, unsigned int expiry) {
|
|||
}
|
||||
|
||||
if (expiry > 0) {
|
||||
this->m_expiry.emplace_back(packId, Timestamp{static_cast<__time32_t>(expiry)});
|
||||
this->m_expiry.emplace_back(packId, expiry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -648,42 +663,238 @@ bool CCashEmotionMgr::IsOwnedPack(int packId) {
|
|||
return std::find(this->m_ownedPacks.begin(), this->m_ownedPacks.end(), packId) != this->m_ownedPacks.end();
|
||||
}
|
||||
|
||||
// OFFSET: 0x007C9200
|
||||
// FUNCTION: fn_09428
|
||||
void UICashEmotionMiniWnd::Select(CashEmotionCommand* command) {
|
||||
this->m_selected = command;
|
||||
this->m_page = 0;
|
||||
this->m_selectedIndex = 0;
|
||||
this->Refresh(0);
|
||||
|
||||
if (this->m_previous) {
|
||||
this->m_previous->Enable(0);
|
||||
}
|
||||
|
||||
if (this->m_selected && this->m_selected->Count() > 3) {
|
||||
if (this->m_next) {
|
||||
this->m_next->Enable(1);
|
||||
}
|
||||
} else if (this->m_next) {
|
||||
this->m_next->Enable(0);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x007C9290
|
||||
// FUNCTION: fn_09429
|
||||
void UICashEmotionMiniWnd::Previous() {
|
||||
if (this->m_selectedIndex != 0) {
|
||||
this->SetIndex(this->m_selectedIndex - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x007C92B0
|
||||
// FUNCTION: fn_09430
|
||||
void UICashEmotionMiniWnd::Refresh(int first) {
|
||||
if (this->m_first) {
|
||||
if (this->m_pieces[0]) {
|
||||
if (this->m_selected) {
|
||||
std::pair<int, int> entry = this->m_selected->Get(first);
|
||||
bool owned = entry.first == g_cashEmotionMgr->BasePackId() || g_cashEmotionMgr->IsOwnedPack(entry.first);
|
||||
this->m_first->Set(entry.first, entry.second, false, false, !owned);
|
||||
this->m_pieces[0]->Set(entry.first, entry.second, false, false, !owned);
|
||||
} else {
|
||||
this->m_first->Set(-1, -1, false, false, false);
|
||||
this->m_pieces[0]->Set(-1, -1, false, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_second) {
|
||||
if (this->m_pieces[1]) {
|
||||
if (this->m_selected) {
|
||||
std::pair<int, int> entry = this->m_selected->Get(first + 1);
|
||||
bool owned = entry.first == g_cashEmotionMgr->BasePackId() || g_cashEmotionMgr->IsOwnedPack(entry.first);
|
||||
this->m_second->Set(entry.first, entry.second, false, false, !owned);
|
||||
this->m_pieces[1]->Set(entry.first, entry.second, false, false, !owned);
|
||||
} else {
|
||||
this->m_second->Set(-1, -1, false, false, false);
|
||||
this->m_pieces[1]->Set(-1, -1, false, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_third) {
|
||||
if (this->m_pieces[2]) {
|
||||
if (this->m_selected) {
|
||||
std::pair<int, int> entry = this->m_selected->Get(first + 2);
|
||||
bool owned = entry.first == g_cashEmotionMgr->BasePackId() || g_cashEmotionMgr->IsOwnedPack(entry.first);
|
||||
this->m_third->Set(entry.first, entry.second, false, false, !owned);
|
||||
this->m_pieces[2]->Set(entry.first, entry.second, false, false, !owned);
|
||||
} else {
|
||||
this->m_third->Set(-1, -1, false, false, false);
|
||||
this->m_pieces[2]->Set(-1, -1, false, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
this->Invalidate();
|
||||
}
|
||||
|
||||
// OFFSET: 0x007C94A0
|
||||
// FUNCTION: fn_09431
|
||||
void UICashEmotionMiniWnd::Slot15(int width, int height) {
|
||||
int x = 24;
|
||||
for (UICashEmotionPiece*& piece : this->m_pieces) {
|
||||
piece = new (std::nothrow) UICashEmotionPiece(*this->m_context, *this->m_controls);
|
||||
if (piece) {
|
||||
piece->SetSize(42, 42);
|
||||
piece->Move(x, 1);
|
||||
this->AddChild(piece);
|
||||
x += 49;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_previous = new (std::nothrow) UIBitmapButton(*this->m_context, this->m_controls->buttons);
|
||||
if (this->m_previous) {
|
||||
this->m_previous->SetBitmap("유저인터페이스\\cashemotion\\btn_arrow_l_normal.bmp", 0, 0);
|
||||
this->m_previous->SetBitmap("유저인터페이스\\cashemotion\\btn_arrow_l_over.bmp", 1, 0);
|
||||
this->m_previous->SetBitmap("유저인터페이스\\cashemotion\\btn_arrow_l_press.bmp", 2, 0);
|
||||
this->m_previous->SetSize(this->m_previous->BitmapWidth(), this->m_previous->BitmapHeight());
|
||||
this->m_previous->Move(0, 0);
|
||||
this->m_previous->SetId(1);
|
||||
this->AddChild(this->m_previous);
|
||||
}
|
||||
|
||||
this->m_next = new (std::nothrow) UIBitmapButton(*this->m_context, this->m_controls->buttons);
|
||||
if (this->m_next) {
|
||||
this->m_next->SetBitmap("유저인터페이스\\cashemotion\\bth_arrow_r_normal.bmp", 0, 0);
|
||||
this->m_next->SetBitmap("유저인터페이스\\cashemotion\\bth_arrow_r_over.bmp", 1, 0);
|
||||
this->m_next->SetBitmap("유저인터페이스\\cashemotion\\bth_arrow_r_press.bmp", 2, 0);
|
||||
int buttonWidth = this->m_next->BitmapWidth();
|
||||
this->m_next->SetSize(buttonWidth, this->m_next->BitmapHeight());
|
||||
this->m_next->Move(this->geometry.width - buttonWidth, 0);
|
||||
this->m_next->SetId(2);
|
||||
this->AddChild(this->m_next);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x007C96E0
|
||||
// FUNCTION: fn_09432
|
||||
void UICashEmotionMiniWnd::Paint() {
|
||||
this->ClearSurface(0xFFFF00FF);
|
||||
|
||||
auto* background = static_cast<CBitmapRes*>(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\cashemotion\\bg_preview.bmp")));
|
||||
if (background) {
|
||||
this->DrawBitmap(0, 0, &background->image, false);
|
||||
}
|
||||
|
||||
if (this->m_selectedIndex == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int slot = this->m_selectedIndex - this->m_page;
|
||||
if (slot <= -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
UICashEmotionPiece* piece = this->m_pieces.at(slot);
|
||||
if (!piece) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* highlight = static_cast<CBitmapRes*>(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\cashemotion\\bg_preview_select.bmp")));
|
||||
if (highlight) {
|
||||
this->DrawBitmap(piece->geometry.x - 3, 0, &highlight->image, false);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x007C9790
|
||||
// FUNCTION: fn_09433
|
||||
void UICashEmotionMiniWnd::Next() {
|
||||
if (this->m_selected && this->m_selected->Count() > this->m_selectedIndex + 1) {
|
||||
this->SetIndex(this->m_selectedIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x007C97C0
|
||||
// FUNCTION: fn_09434
|
||||
void UICashEmotionMiniWnd::SetIndex(int index) {
|
||||
if (index == this->m_selectedIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->m_selectedIndex = index;
|
||||
if (this->m_selected) {
|
||||
bool enable = index > 0 && this->m_selected->Count() > 1;
|
||||
if (this->m_previous) {
|
||||
this->m_previous->Enable(enable);
|
||||
}
|
||||
|
||||
enable = this->m_selectedIndex + 1 < this->m_selected->Count() && this->m_selected->Count() > 1;
|
||||
if (this->m_next) {
|
||||
this->m_next->Enable(enable);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_selectedIndex >= this->m_page + 3) {
|
||||
this->m_page = this->m_selectedIndex - 2;
|
||||
this->Refresh(this->m_page);
|
||||
} else if (this->m_selectedIndex < this->m_page) {
|
||||
this->m_page = this->m_selectedIndex;
|
||||
this->Refresh(this->m_page);
|
||||
}
|
||||
|
||||
this->Invalidate();
|
||||
}
|
||||
|
||||
// OFFSET: 0x007C98A0
|
||||
// FUNCTION: fn_09435
|
||||
int UICashEmotionMiniWnd::SendMsg(
|
||||
UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4
|
||||
) {
|
||||
std::pair<int, int> entry;
|
||||
|
||||
switch (message) {
|
||||
case 6:
|
||||
if (argument1 == 1) {
|
||||
this->Previous();
|
||||
} else if (argument1 == 2) {
|
||||
this->Next();
|
||||
}
|
||||
return 0;
|
||||
case 60:
|
||||
this->Invalidate();
|
||||
return 0;
|
||||
case 174:
|
||||
entry.first = static_cast<int>(argument1);
|
||||
entry.second = static_cast<int>(argument2);
|
||||
break;
|
||||
case 176:
|
||||
if (argument1 == 13) {
|
||||
if (!this->m_selected) {
|
||||
return 0;
|
||||
}
|
||||
entry = this->m_selected->Get(this->m_selectedIndex);
|
||||
break;
|
||||
}
|
||||
if (argument1 == 37) {
|
||||
this->Previous();
|
||||
} else if (argument1 == 39) {
|
||||
this->Next();
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return UIWindow::SendMsg(sender, message, argument1, argument2, argument3, argument4);
|
||||
}
|
||||
|
||||
CashEmotionData* data = g_cashEmotionMgr->GetEmotionData(entry.first, entry.second);
|
||||
if (!data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int packId = data->id;
|
||||
if (packId == g_cashEmotionMgr->BasePackId() || g_cashEmotionMgr->IsOwnedPack(packId)) {
|
||||
if (g_chatSuggestions) {
|
||||
if (g_chatSuggestions->input) {
|
||||
g_chatSuggestions->input->SetText(data->name.c_str());
|
||||
}
|
||||
g_chatSuggestions->Show(0);
|
||||
}
|
||||
} else if (this->m_action) {
|
||||
this->m_action->Execute(packId, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// OFFSET: 0x007C9D60
|
||||
// FUNCTION: fn_09439
|
||||
UICashEmotionPack::~UICashEmotionPack() {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ public:
|
|||
|
||||
void Add(int packId, int emotionId);
|
||||
std::pair<int, int> Get(int index) const;
|
||||
// INLINED
|
||||
int Count() const {
|
||||
return static_cast<int>(this->entries.size());
|
||||
}
|
||||
|
||||
/* 0000 */ std::string name;
|
||||
/* 0018 */ std::vector<std::pair<int, int>> entries;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ inline RagEffectState::RagEffectState()
|
|||
// INLINED
|
||||
inline RagEffectState::~RagEffectState() {
|
||||
for (EffectPrimitiveState* particle : this->related) {
|
||||
particle->parent = nullptr;
|
||||
particle->master = nullptr;
|
||||
}
|
||||
|
||||
this->related.clear();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "Contents/Effects/EffectParticle.h"
|
||||
#include "Contents/Effects/RagEffectState.h"
|
||||
#include "Contents/Effects/AttachedEffect.h"
|
||||
|
||||
// OFFSET: 0x00BAD940
|
||||
// FUNCTION: fn_19761
|
||||
|
|
@ -9,13 +9,13 @@ EffectParticle::EffectParticle(ResourceMgr& resources, JobNames& names) : CRende
|
|||
// OFFSET: 0x00C1DE70
|
||||
// FUNCTION: fn_20076
|
||||
EffectParticle* CreateEffectParticle(
|
||||
RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z, ResourceMgr& resources, JobNames& names,
|
||||
AttachedEffect& master, const RenderObjectState& masterRender, int type, float x, float y, float z, ResourceMgr& resources, JobNames& names,
|
||||
std::list<CRenderObject*>& worldObjects
|
||||
) {
|
||||
auto* particle = new EffectParticle(resources, names);
|
||||
|
||||
particle->state.Initialize(particle->render, parent, parentRender, type, x, y, z);
|
||||
parent.related.push_back(&particle->state);
|
||||
particle->state.Initialize(particle->render, master, masterRender, type, x, y, z);
|
||||
master.state.related.push_back(&particle->state);
|
||||
worldObjects.push_back(particle);
|
||||
|
||||
return particle;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
struct JobNames;
|
||||
class ResourceMgr;
|
||||
struct RagEffectState;
|
||||
struct AttachedEffect;
|
||||
|
||||
struct EffectParticle : CRenderObject {
|
||||
EffectParticle(ResourceMgr& resources, JobNames& names);
|
||||
|
|
@ -22,6 +22,9 @@ struct EffectParticle : CRenderObject {
|
|||
bool UpdateExit();
|
||||
bool UpdateWarp();
|
||||
void PrimBottom2();
|
||||
void PrimBottom();
|
||||
void PrimBottomOut();
|
||||
void PrimBubbleDrop();
|
||||
|
||||
bool AdvanceFrame();
|
||||
void UpdateRecords();
|
||||
|
|
@ -30,7 +33,7 @@ struct EffectParticle : CRenderObject {
|
|||
};
|
||||
|
||||
EffectParticle* CreateEffectParticle(
|
||||
RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z, ResourceMgr& resources, JobNames& names,
|
||||
AttachedEffect& master, const RenderObjectState& masterRender, int type, float x, float y, float z, ResourceMgr& resources, JobNames& names,
|
||||
std::list<CRenderObject*>& worldObjects
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "Contents/Effects/EffectPrimitiveState.h"
|
||||
#include "Contents/Effects/RagEffectState.h"
|
||||
#include "Contents/Effects/AttachedEffect.h"
|
||||
#include "Utility/Math/ScalarConversion.h"
|
||||
|
||||
// OFFSET: 0x00BC5E00
|
||||
|
|
@ -45,7 +45,7 @@ void EffectPrimitiveState::UpdateColor() {
|
|||
}
|
||||
|
||||
if (this->unknown_015C == 0) {
|
||||
const int parentRemaining = this->parent->lifetime - this->parent->unknown_0178;
|
||||
const int parentRemaining = this->master->state.lifetime - this->master->state.unknown_0178;
|
||||
const int remaining = this->lifetime - current;
|
||||
|
||||
if (remaining > parentRemaining + 1) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "Resource/Sprites/ActionResource.h"
|
||||
#include "Contents/Effects/EffectParticle.h"
|
||||
#include "Contents/Effects/EffectPrimitiveState.h"
|
||||
#include "Contents/Effects/AttachedEffect.h"
|
||||
#include "Contents/Effects/RagEffectState.h"
|
||||
#include "Contents/Sound/SoundMgr.h"
|
||||
#include "Resource/World/TerrainResource.h"
|
||||
|
|
@ -49,6 +50,33 @@ namespace {
|
|||
((matrix[5] * point.y + matrix[2] * point.x) + point.z * matrix[8]) + matrix[11]
|
||||
};
|
||||
}
|
||||
|
||||
// INLINED
|
||||
void FaceCamera(EffectPrimitiveSlot* slots) {
|
||||
const CView* view = static_cast<CGameMode*>(g_world.ActiveGameMode())->camera;
|
||||
slots[0].alphaT = static_cast<std::int16_t>(360 - static_cast<int>(view->camera.yaw));
|
||||
slots[1].alphaT = static_cast<std::int16_t>(360 - static_cast<int>(view->camera.pitch) + 90);
|
||||
|
||||
if (slots[1].alphaT >= 360) {
|
||||
slots[1].alphaT -= 360;
|
||||
}
|
||||
}
|
||||
|
||||
// INLINED
|
||||
__forceinline void FollowTrail(EffectPrimitiveSlot& trail, const EffectPrimitiveSlot& previous, int fade) {
|
||||
trail.fullDisplayAngle = previous.fullDisplayAngle;
|
||||
trail.distance = previous.distance;
|
||||
trail.height[8] = previous.height[8];
|
||||
trail.alphaB = previous.alphaB - fade;
|
||||
|
||||
if (trail.alphaB < 0) {
|
||||
trail.alphaB = 0;
|
||||
}
|
||||
|
||||
trail.vecBNow = previous.vecBNow;
|
||||
trail.fullDisplayAngle = previous.fullDisplayAngle;
|
||||
trail.flag1[0] = previous.flag1[0];
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00BB8C50
|
||||
|
|
@ -136,8 +164,8 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend
|
|||
}
|
||||
|
||||
if ((particle.flags & 0x400u) != 0) {
|
||||
const float x = particle.parent->offset[0] - render.position[0];
|
||||
const float z = particle.parent->offset[2] - render.position[2];
|
||||
const float x = particle.master->state.offset[0] - render.position[0];
|
||||
const float z = particle.master->state.offset[2] - render.position[2];
|
||||
const float distance = std::sqrt(z * z + x * x);
|
||||
|
||||
if (3.0f >= distance) {
|
||||
|
|
@ -188,16 +216,16 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend
|
|||
}
|
||||
|
||||
if ((particle.flags & 0x10u) != 0) {
|
||||
particle.parent->offset[0] = particle.velocity.x + particle.offset.x;
|
||||
particle.parent->offset[1] = particle.offset.y + particle.velocity.y;
|
||||
particle.parent->offset[2] = particle.offset.z + particle.velocity.z;
|
||||
particle.master->state.offset[0] = particle.velocity.x + particle.offset.x;
|
||||
particle.master->state.offset[1] = particle.offset.y + particle.velocity.y;
|
||||
particle.master->state.offset[2] = particle.offset.z + particle.velocity.z;
|
||||
}
|
||||
|
||||
if ((particle.flags & 4u) != 0 && render.position[1] > context.ground.Height(render.position[0], render.position[2])) {
|
||||
particle.flags &= ~4u;
|
||||
particle.unknown_01E0 = particle.lifetime - 25;
|
||||
particle.unknown_02BC = 0;
|
||||
particle.parent->unknown_0170 = 1;
|
||||
particle.master->state.unknown_0170 = 1;
|
||||
}
|
||||
|
||||
const int frame = particle.unknown_01E0;
|
||||
|
|
@ -257,7 +285,7 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend
|
|||
// OFFSET: 0x00BAE7D0
|
||||
// FUNCTION: fn_19769
|
||||
bool UpdateEffectPrimitive15(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context, int updateTick) {
|
||||
if (!particle.parent) {
|
||||
if (!particle.master) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -280,39 +308,39 @@ bool ShrinkEffectPrimitiveSlots(EffectPrimitiveState& particle, RenderObjectStat
|
|||
for (int index = 0; index < 4; ++index) {
|
||||
EffectPrimitiveSlot& slot = particle.slots[index];
|
||||
|
||||
if (slot.active != 1) {
|
||||
if (slot.life != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float height = slot.unknown_0080 - 0.05f;
|
||||
++slot.frame;
|
||||
slot.unknown_0080 = height;
|
||||
float height = slot.distance - 0.05f;
|
||||
++slot.process;
|
||||
slot.distance = height;
|
||||
|
||||
if (height <= 0.0f) {
|
||||
slot.unknown_0080 = 10.0f;
|
||||
slot.unknown_0002 = 0;
|
||||
slot.distance = 10.0f;
|
||||
slot.alphaB = 0;
|
||||
height = 10.0f;
|
||||
}
|
||||
|
||||
slot.unknown_0008 = height;
|
||||
slot.unknown_007E = static_cast<std::int16_t>(static_cast<int>(90.0f - height * 9.0f));
|
||||
slot.maxHeight = height;
|
||||
slot.riseAngle = static_cast<std::int16_t>(static_cast<int>(90.0f - height * 9.0f));
|
||||
|
||||
if (slot.frame >= particle.lifetime - 40) {
|
||||
slot.unknown_0002 -= 3;
|
||||
if (slot.process >= particle.lifetime - 40) {
|
||||
slot.alphaB -= 3;
|
||||
|
||||
if (slot.unknown_0002 < 0) {
|
||||
slot.unknown_0002 = 0;
|
||||
if (slot.alphaB < 0) {
|
||||
slot.alphaB = 0;
|
||||
}
|
||||
} else if (slot.unknown_0002 < 70) {
|
||||
++slot.unknown_0002;
|
||||
} else if (slot.alphaB < 70) {
|
||||
++slot.alphaB;
|
||||
}
|
||||
|
||||
for (int value = 0; value < 21; ++value) {
|
||||
if (slot.finished[value] == 0) {
|
||||
slot.values[value] = slot.unknown_0008;
|
||||
if (slot.flag1[value] == 0) {
|
||||
slot.height[value] = slot.maxHeight;
|
||||
|
||||
if (slot.values[value] < 0.0f) {
|
||||
slot.values[value] = 0;
|
||||
if (slot.height[value] < 0.0f) {
|
||||
slot.height[value] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -331,21 +359,21 @@ bool PulseEffectPrimitiveSlots(EffectPrimitiveState& particle, RenderObjectState
|
|||
for (int index = 0; index < 4; ++index) {
|
||||
EffectPrimitiveSlot& slot = particle.slots[index];
|
||||
|
||||
if (slot.active != 1) {
|
||||
if (slot.life != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float phase = slot.unknown_0080 + 0.1f;
|
||||
const int frame = ++slot.frame;
|
||||
slot.unknown_0080 = phase;
|
||||
float phase = slot.distance + 0.1f;
|
||||
const int frame = ++slot.process;
|
||||
slot.distance = phase;
|
||||
|
||||
if (phase >= 13.0f) {
|
||||
slot.unknown_0080 = 3.0f;
|
||||
slot.unknown_0002 = 0;
|
||||
slot.distance = 3.0f;
|
||||
slot.alphaB = 0;
|
||||
phase = 3.0f;
|
||||
|
||||
if (frame > 50) {
|
||||
slot.active = 0;
|
||||
slot.life = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -355,23 +383,23 @@ bool PulseEffectPrimitiveSlots(EffectPrimitiveState& particle, RenderObjectState
|
|||
if (phase > 5.0f) {
|
||||
height = 10.0f - phase;
|
||||
|
||||
if (slot.unknown_0002 > 0) {
|
||||
slot.unknown_0002 -= 2;
|
||||
if (slot.alphaB > 0) {
|
||||
slot.alphaB -= 2;
|
||||
}
|
||||
} else {
|
||||
slot.unknown_0002 += 2;
|
||||
slot.alphaB += 2;
|
||||
height = phase;
|
||||
}
|
||||
|
||||
slot.unknown_0008 = height * 2.0f;
|
||||
slot.unknown_007E = static_cast<std::int16_t>(static_cast<int>(90.0f - phase * 5.0f));
|
||||
slot.maxHeight = height * 2.0f;
|
||||
slot.riseAngle = static_cast<std::int16_t>(static_cast<int>(90.0f - phase * 5.0f));
|
||||
|
||||
for (int value = 0; value < 21; ++value) {
|
||||
if (slot.finished[value] == 0) {
|
||||
slot.values[value] = slot.unknown_0008;
|
||||
if (slot.flag1[value] == 0) {
|
||||
slot.height[value] = slot.maxHeight;
|
||||
|
||||
if (slot.values[value] < 0.0f) {
|
||||
slot.values[value] = 0;
|
||||
if (slot.height[value] < 0.0f) {
|
||||
slot.height[value] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -559,10 +587,10 @@ bool EffectParticle::AdvanceFrame() {
|
|||
// OFFSET: 0x00BB5E80
|
||||
// FUNCTION: fn_19772
|
||||
bool EffectParticle::UpdateFireWall() {
|
||||
const RagEffectState* parent = this->state.parent;
|
||||
this->render.position[0] = std::bit_cast<float>(parent->unknown_013C[3]);
|
||||
this->render.position[1] = std::bit_cast<float>(parent->unknown_013C[4]);
|
||||
this->render.position[2] = std::bit_cast<float>(parent->unknown_013C[5]);
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->render.position[0] = master->render.position[0];
|
||||
this->render.position[1] = master->render.position[1];
|
||||
this->render.position[2] = master->render.position[2];
|
||||
|
||||
for (int index = 0; index < 4; ++index) {
|
||||
if (this->state.scale == 3.0f && index < 3) {
|
||||
|
|
@ -571,38 +599,38 @@ bool EffectParticle::UpdateFireWall() {
|
|||
|
||||
EffectPrimitiveSlot& slot = this->state.slots[index];
|
||||
|
||||
if (slot.active != 1) {
|
||||
if (slot.life != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++slot.frame;
|
||||
++slot.process;
|
||||
|
||||
if (index < 3) {
|
||||
slot.angle = static_cast<std::int16_t>(slot.angle + index + 3);
|
||||
slot.rotStart = static_cast<std::int16_t>(slot.rotStart + index + 3);
|
||||
}
|
||||
|
||||
if (slot.angle >= 360) {
|
||||
slot.angle = static_cast<std::int16_t>(slot.angle - 360);
|
||||
if (slot.rotStart >= 360) {
|
||||
slot.rotStart = static_cast<std::int16_t>(slot.rotStart - 360);
|
||||
}
|
||||
|
||||
const int limit = this->state.lifetime - 40;
|
||||
bool grown = false;
|
||||
|
||||
if (slot.frame < limit) {
|
||||
if (slot.frame < 20) {
|
||||
if (slot.process < limit) {
|
||||
if (slot.process < 20) {
|
||||
if (index == 3) {
|
||||
this->state.slots[3].unknown_0002 = static_cast<std::int16_t>(this->state.slots[3].unknown_0002 + 8);
|
||||
this->state.slots[3].alphaB = static_cast<std::int16_t>(this->state.slots[3].alphaB + 8);
|
||||
|
||||
if (this->state.slots[3].unknown_0002 > 100) {
|
||||
this->state.slots[3].unknown_0002 = 100;
|
||||
if (this->state.slots[3].alphaB > 100) {
|
||||
this->state.slots[3].alphaB = 100;
|
||||
}
|
||||
|
||||
grown = true;
|
||||
} else {
|
||||
slot.unknown_0002 = static_cast<std::int16_t>(slot.unknown_0002 + 10);
|
||||
slot.alphaB = static_cast<std::int16_t>(slot.alphaB + 10);
|
||||
|
||||
if (slot.unknown_0002 > 180) {
|
||||
slot.unknown_0002 = 180;
|
||||
if (slot.alphaB > 180) {
|
||||
slot.alphaB = 180;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -612,16 +640,16 @@ bool EffectParticle::UpdateFireWall() {
|
|||
}
|
||||
} else {
|
||||
if (index < 3) {
|
||||
slot.unknown_0002 = static_cast<std::int16_t>(slot.unknown_0002 - 5);
|
||||
slot.alphaB = static_cast<std::int16_t>(slot.alphaB - 5);
|
||||
|
||||
if (slot.unknown_0002 < 0) {
|
||||
slot.unknown_0002 = 0;
|
||||
if (slot.alphaB < 0) {
|
||||
slot.alphaB = 0;
|
||||
}
|
||||
} else {
|
||||
slot.unknown_0002 = static_cast<std::int16_t>(slot.unknown_0002 - 3);
|
||||
slot.alphaB = static_cast<std::int16_t>(slot.alphaB - 3);
|
||||
|
||||
if (slot.unknown_0002 < 0) {
|
||||
slot.unknown_0002 = 0;
|
||||
if (slot.alphaB < 0) {
|
||||
slot.alphaB = 0;
|
||||
}
|
||||
|
||||
grown = true;
|
||||
|
|
@ -630,46 +658,46 @@ bool EffectParticle::UpdateFireWall() {
|
|||
|
||||
if (!grown) {
|
||||
for (int sample = 0; sample < 21; ++sample) {
|
||||
if (slot.finished[sample] == 0) {
|
||||
if (slot.frame <= 90) {
|
||||
slot.values[sample] = slot.unknown_0008 * ClientSine(sample * 9) * ClientSine(slot.frame);
|
||||
if (slot.flag1[sample] == 0) {
|
||||
if (slot.process <= 90) {
|
||||
slot.height[sample] = slot.maxHeight * ClientSine(sample * 9) * ClientSine(slot.process);
|
||||
}
|
||||
|
||||
const float maximum = slot.unknown_0008 * ClientSine(sample * 9);
|
||||
const float maximum = slot.maxHeight * ClientSine(sample * 9);
|
||||
|
||||
if (slot.values[sample] > maximum) {
|
||||
slot.values[sample] = maximum;
|
||||
slot.finished[sample] = 1;
|
||||
if (slot.height[sample] > maximum) {
|
||||
slot.height[sample] = maximum;
|
||||
slot.flag1[sample] = 1;
|
||||
}
|
||||
|
||||
if (slot.values[sample] < 0.0f) {
|
||||
slot.values[sample] = 0.0f;
|
||||
if (slot.height[sample] < 0.0f) {
|
||||
slot.height[sample] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int sample = 0; sample < 21; ++sample) {
|
||||
if (slot.finished[sample] != 0) {
|
||||
const float base = slot.unknown_0008 * ClientSine(sample * 9) * 0.55f;
|
||||
slot.values[sample] = base;
|
||||
slot.values[sample] = slot.unknown_0008 * ClientSine(sample * 9) * 0.45f * ClientSine(slot.frame % 360) + base;
|
||||
if (slot.flag1[sample] != 0) {
|
||||
const float base = slot.maxHeight * ClientSine(sample * 9) * 0.55f;
|
||||
slot.height[sample] = base;
|
||||
slot.height[sample] = slot.maxHeight * ClientSine(sample * 9) * 0.45f * ClientSine(slot.process % 360) + base;
|
||||
} else {
|
||||
float value;
|
||||
|
||||
if (slot.frame > 90) {
|
||||
slot.finished[sample] = 1;
|
||||
value = slot.values[sample];
|
||||
if (slot.process > 90) {
|
||||
slot.flag1[sample] = 1;
|
||||
value = slot.height[sample];
|
||||
} else {
|
||||
value = slot.unknown_0008 * ClientSine(sample * 9) * ClientSine(slot.frame);
|
||||
slot.values[sample] = value;
|
||||
value = slot.maxHeight * ClientSine(sample * 9) * ClientSine(slot.process);
|
||||
slot.height[sample] = value;
|
||||
}
|
||||
|
||||
if (value > slot.unknown_0008 * ClientSine(sample * 9)) {
|
||||
slot.finished[sample] = 1;
|
||||
if (value > slot.maxHeight * ClientSine(sample * 9)) {
|
||||
slot.flag1[sample] = 1;
|
||||
}
|
||||
|
||||
if (slot.values[sample] < 0.0f) {
|
||||
slot.values[sample] = 0.0f;
|
||||
if (slot.height[sample] < 0.0f) {
|
||||
slot.height[sample] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -682,10 +710,10 @@ bool EffectParticle::UpdateFireWall() {
|
|||
// OFFSET: 0x00BB63C0
|
||||
// FUNCTION: fn_19775
|
||||
bool EffectParticle::UpdateStoneCurse() {
|
||||
const RagEffectState* parent = this->state.parent;
|
||||
this->render.position[0] = std::bit_cast<float>(parent->unknown_013C[3]);
|
||||
this->render.position[1] = std::bit_cast<float>(parent->unknown_013C[4]);
|
||||
this->render.position[2] = std::bit_cast<float>(parent->unknown_013C[5]);
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->render.position[0] = master->render.position[0];
|
||||
this->render.position[1] = master->render.position[1];
|
||||
this->render.position[2] = master->render.position[2];
|
||||
|
||||
for (int index = 0; index < 4; ++index) {
|
||||
if (this->state.scale == 3.0f && index < 3) {
|
||||
|
|
@ -694,59 +722,59 @@ bool EffectParticle::UpdateStoneCurse() {
|
|||
|
||||
EffectPrimitiveSlot& slot = this->state.slots[index];
|
||||
|
||||
if (slot.active != 1) {
|
||||
if (slot.life != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++slot.frame;
|
||||
++slot.process;
|
||||
|
||||
if (index < 3) {
|
||||
slot.angle = static_cast<std::int16_t>(slot.angle + index + 3);
|
||||
slot.rotStart = static_cast<std::int16_t>(slot.rotStart + index + 3);
|
||||
}
|
||||
|
||||
if (slot.angle >= 360) {
|
||||
slot.angle = static_cast<std::int16_t>(slot.angle - 360);
|
||||
if (slot.rotStart >= 360) {
|
||||
slot.rotStart = static_cast<std::int16_t>(slot.rotStart - 360);
|
||||
}
|
||||
|
||||
if (slot.frame < this->state.lifetime - 40) {
|
||||
if (slot.frame < 20 && slot.unknown_0004 != 1) {
|
||||
if (slot.process < this->state.lifetime - 40) {
|
||||
if (slot.process < 20 && slot.alphaT != 1) {
|
||||
if (index == 3) {
|
||||
this->state.slots[3].unknown_0002 = static_cast<std::int16_t>(this->state.slots[3].unknown_0002 + 8);
|
||||
this->state.slots[3].alphaB = static_cast<std::int16_t>(this->state.slots[3].alphaB + 8);
|
||||
|
||||
if (this->state.slots[3].unknown_0002 > 60) {
|
||||
this->state.slots[3].unknown_0002 = 60;
|
||||
if (this->state.slots[3].alphaB > 60) {
|
||||
this->state.slots[3].alphaB = 60;
|
||||
}
|
||||
} else {
|
||||
slot.unknown_0002 = static_cast<std::int16_t>(slot.unknown_0002 + 10);
|
||||
slot.alphaB = static_cast<std::int16_t>(slot.alphaB + 10);
|
||||
|
||||
if (slot.unknown_0002 > 180) {
|
||||
slot.unknown_0002 = 180;
|
||||
if (slot.alphaB > 180) {
|
||||
slot.alphaB = 180;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
slot.unknown_0002 = static_cast<std::int16_t>(slot.unknown_0002 - (index >= 3 ? 2 : 5));
|
||||
slot.alphaB = static_cast<std::int16_t>(slot.alphaB - (index >= 3 ? 2 : 5));
|
||||
|
||||
if (slot.unknown_0002 < 0) {
|
||||
slot.unknown_0002 = 0;
|
||||
if (slot.alphaB < 0) {
|
||||
slot.alphaB = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (int sample = 0; sample < 21; ++sample) {
|
||||
if (slot.finished[sample] == 0) {
|
||||
if (slot.frame <= 90) {
|
||||
slot.values[sample] = slot.unknown_0008 * ClientSine(sample * 9) * ClientSine(slot.frame);
|
||||
if (slot.flag1[sample] == 0) {
|
||||
if (slot.process <= 90) {
|
||||
slot.height[sample] = slot.maxHeight * ClientSine(sample * 9) * ClientSine(slot.process);
|
||||
}
|
||||
|
||||
const float maximum = slot.unknown_0008 * ClientSine(sample * 9);
|
||||
const float maximum = slot.maxHeight * ClientSine(sample * 9);
|
||||
|
||||
if (slot.values[sample] > maximum) {
|
||||
slot.values[sample] = maximum;
|
||||
slot.finished[sample] = 1;
|
||||
if (slot.height[sample] > maximum) {
|
||||
slot.height[sample] = maximum;
|
||||
slot.flag1[sample] = 1;
|
||||
}
|
||||
|
||||
if (slot.values[sample] < 0.0f) {
|
||||
slot.values[sample] = 0.0f;
|
||||
if (slot.height[sample] < 0.0f) {
|
||||
slot.height[sample] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -758,10 +786,10 @@ bool EffectParticle::UpdateStoneCurse() {
|
|||
// OFFSET: 0x00BB65C0
|
||||
// FUNCTION: fn_19776
|
||||
void EffectParticle::UpdateBeginSpell() {
|
||||
const RagEffectState* parent = this->state.parent;
|
||||
this->state.origin.x = std::bit_cast<float>(parent->unknown_013C[3]) + this->state.velocity.x;
|
||||
this->state.origin.y = std::bit_cast<float>(parent->unknown_013C[4]) + this->state.velocity.y;
|
||||
this->state.origin.z = std::bit_cast<float>(parent->unknown_013C[5]) + this->state.velocity.z;
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->state.origin.x = master->render.position[0] + this->state.velocity.x;
|
||||
this->state.origin.y = master->render.position[1] + this->state.velocity.y;
|
||||
this->state.origin.z = master->render.position[2] + this->state.velocity.z;
|
||||
|
||||
float base;
|
||||
|
||||
|
|
@ -815,41 +843,218 @@ void EffectParticle::UpdateBeginSpell() {
|
|||
// OFFSET: 0x00BBAB10
|
||||
// FUNCTION: fn_19790
|
||||
void EffectParticle::PrimBottom2() {
|
||||
const RagEffectState* parent = this->state.parent;
|
||||
this->render.position[0] = std::bit_cast<float>(parent->unknown_013C[3]);
|
||||
this->render.position[1] = std::bit_cast<float>(parent->unknown_013C[4]);
|
||||
this->render.position[2] = std::bit_cast<float>(parent->unknown_013C[5]);
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->render.position[0] = master->render.position[0];
|
||||
this->render.position[1] = master->render.position[1];
|
||||
this->render.position[2] = master->render.position[2];
|
||||
|
||||
for (int index = 0; index < 4; ++index) {
|
||||
EffectPrimitiveSlot& slot = this->state.slots[index];
|
||||
|
||||
if (slot.active != 1) {
|
||||
if (slot.life != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++slot.frame;
|
||||
++slot.process;
|
||||
|
||||
if (slot.values[0] == 1.0f) {
|
||||
slot.displayAngle += 4;
|
||||
if (slot.height[0] == 1.0f) {
|
||||
slot.fullDisplayAngle += 4;
|
||||
} else {
|
||||
slot.displayAngle += 2;
|
||||
slot.fullDisplayAngle += 2;
|
||||
}
|
||||
|
||||
if (slot.displayAngle >= 360) {
|
||||
slot.displayAngle -= 360;
|
||||
if (slot.fullDisplayAngle >= 360) {
|
||||
slot.fullDisplayAngle -= 360;
|
||||
}
|
||||
|
||||
slot.unknown_0008 = 20.0f + 10.0f * ClientSine(slot.displayAngle);
|
||||
slot.maxHeight = 20.0f + 10.0f * ClientSine(slot.fullDisplayAngle);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00BBABC0
|
||||
// FUNCTION: fn_19791
|
||||
void EffectParticle::PrimBottom() {
|
||||
EffectPrimitiveSlot* slots = this->state.slots;
|
||||
FaceCamera(slots);
|
||||
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->render.position[0] = master->render.position[0];
|
||||
this->render.position[1] = master->render.position[1];
|
||||
this->render.position[2] = master->render.position[2];
|
||||
|
||||
EffectPrimitiveSlot& slot = slots[0];
|
||||
|
||||
if (slot.life != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
++slot.process;
|
||||
|
||||
if (slot.process % 6 == 0) {
|
||||
for (int index = 3; index > 0; --index) {
|
||||
EffectPrimitiveSlot& trail = slots[index];
|
||||
const EffectPrimitiveSlot& previous = slots[index - 1];
|
||||
|
||||
if (trail.life > 0) {
|
||||
trail.fullDisplayAngle = previous.fullDisplayAngle;
|
||||
trail.distance = previous.distance + 0.5f;
|
||||
trail.height[8] = previous.height[8];
|
||||
trail.alphaB = previous.alphaB - 50;
|
||||
|
||||
if (trail.alphaB < 0) {
|
||||
trail.alphaB = 0;
|
||||
}
|
||||
|
||||
trail.vecBNow = previous.vecBNow;
|
||||
trail.fullDisplayAngle = previous.fullDisplayAngle;
|
||||
trail.flag1[0] = previous.flag1[0];
|
||||
trail.flag1[2] = 2;
|
||||
trail.height[7] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slot.height[8] += 5.0f;
|
||||
|
||||
if (slot.height[8] >= 360.0f) {
|
||||
slot.height[8] -= 360.0f;
|
||||
}
|
||||
|
||||
++slot.rotStart;
|
||||
|
||||
if (slot.rotStart >= 360) {
|
||||
slot.rotStart -= 360;
|
||||
}
|
||||
|
||||
slot.vecBNow.x = this->render.position[0];
|
||||
slot.vecBNow.z = this->render.position[2];
|
||||
slot.vecBPre.y = this->render.position[1] - 6.0f;
|
||||
slot.vecBNow.y = slot.vecBPre.y + 3.0f * ClientSine(slot.rotStart);
|
||||
|
||||
if (slot.flag1[2] == 7) {
|
||||
slot.fullDisplayAngle += 10;
|
||||
|
||||
if (slot.fullDisplayAngle >= 360) {
|
||||
slot.fullDisplayAngle -= 360;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00BBAF30
|
||||
// FUNCTION: fn_19792
|
||||
void EffectParticle::PrimBottomOut() {
|
||||
FaceCamera(this->state.slots);
|
||||
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->render.position[0] = master->render.position[0];
|
||||
this->render.position[1] = master->render.position[1];
|
||||
this->render.position[2] = master->render.position[2];
|
||||
|
||||
for (int index = 0; index < 4; ++index) {
|
||||
EffectPrimitiveSlot& slot = this->state.slots[index];
|
||||
|
||||
if (slot.life != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++slot.process;
|
||||
|
||||
if (slot.process <= 10) {
|
||||
slot.alphaB += 25;
|
||||
} else {
|
||||
slot.alphaB -= 5;
|
||||
|
||||
if (slot.alphaB <= 0) {
|
||||
slot.alphaB = 0;
|
||||
slot.process = 0;
|
||||
slot.vecBNow.y = slot.flag1[1] == 0 ? this->render.position[1] : this->render.position[1] - 5.0f;
|
||||
}
|
||||
|
||||
slot.vecBNow.y -= 0.2f;
|
||||
}
|
||||
|
||||
slot.height[8] += 5.0f;
|
||||
|
||||
if (slot.height[8] >= 360.0f) {
|
||||
slot.height[8] -= 360.0f;
|
||||
}
|
||||
|
||||
if (slot.flag1[1] == 1) {
|
||||
slot.fullDisplayAngle += 5;
|
||||
|
||||
if (slot.fullDisplayAngle >= 360) {
|
||||
slot.fullDisplayAngle -= 360;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00BBB120
|
||||
// FUNCTION: fn_19793
|
||||
void EffectParticle::PrimBubbleDrop() {
|
||||
EffectPrimitiveSlot* slots = this->state.slots;
|
||||
FaceCamera(slots);
|
||||
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->render.position[0] = master->render.position[0];
|
||||
this->render.position[1] = master->render.position[1];
|
||||
this->render.position[2] = master->render.position[2];
|
||||
|
||||
EffectPrimitiveSlot& slot = slots[0];
|
||||
|
||||
if (slot.life != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
++slot.process;
|
||||
|
||||
if (slot.process <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (slot.process > 3) {
|
||||
FollowTrail(slots[3], slots[2], 25);
|
||||
}
|
||||
|
||||
if (slot.process > 2) {
|
||||
FollowTrail(slots[2], slots[1], 25);
|
||||
}
|
||||
|
||||
if (slot.process > 1) {
|
||||
FollowTrail(slots[1], slot, 100);
|
||||
}
|
||||
|
||||
if (slot.process <= 10) {
|
||||
slot.alphaB += 20;
|
||||
}
|
||||
|
||||
if (slot.process < slot.flag1[4]) {
|
||||
slot.fullDisplayAngle -= 15;
|
||||
|
||||
if (slot.fullDisplayAngle < 0) {
|
||||
slot.fullDisplayAngle += 360;
|
||||
}
|
||||
|
||||
slot.vecBPre.y += slot.height[1];
|
||||
slot.vecBNow = {
|
||||
this->render.position[0] + slot.vecBPre.x, this->render.position[1] + slot.vecBPre.y, this->render.position[2] + slot.vecBPre.z
|
||||
};
|
||||
} else {
|
||||
slot.alphaB -= 10;
|
||||
|
||||
if (slot.alphaB < 0) {
|
||||
slot.alphaB = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00BB6F30
|
||||
// FUNCTION: fn_19779
|
||||
bool EffectParticle::UpdateHit6() {
|
||||
const RagEffectState* parent = this->state.parent;
|
||||
this->state.origin.x = std::bit_cast<float>(parent->unknown_013C[3]) + this->state.velocity.x;
|
||||
this->state.origin.y = std::bit_cast<float>(parent->unknown_013C[4]) + this->state.velocity.y;
|
||||
this->state.origin.z = std::bit_cast<float>(parent->unknown_013C[5]) + this->state.velocity.z;
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->state.origin.x = master->render.position[0] + this->state.velocity.x;
|
||||
this->state.origin.y = master->render.position[1] + this->state.velocity.y;
|
||||
this->state.origin.z = master->render.position[2] + this->state.velocity.z;
|
||||
|
||||
const int frame = this->state.unknown_01E0;
|
||||
|
||||
|
|
@ -930,7 +1135,7 @@ bool EffectParticle::UpdateHit6() {
|
|||
this->render.position[2] = this->state.offset.z + this->state.origin.z;
|
||||
|
||||
if ((this->state.flags & 0x100u) != 0) {
|
||||
if (3.0f >= this->HorizontalDistance(this->state.parent->offset[0], this->state.parent->offset[2])) {
|
||||
if (3.0f >= this->HorizontalDistance(this->state.master->state.offset[0], this->state.master->state.offset[2])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -948,10 +1153,10 @@ bool EffectParticle::UpdateHit6() {
|
|||
// FUNCTION: fn_19780
|
||||
bool EffectParticle::UpdateCoin() {
|
||||
CGameMode* mode = static_cast<CGameMode*>(g_world.ActiveGameMode());
|
||||
const RagEffectState* parent = this->state.parent;
|
||||
this->state.origin.z = std::bit_cast<float>(parent->unknown_013C[5]) + this->state.velocity.z;
|
||||
this->state.origin.y = std::bit_cast<float>(parent->unknown_013C[4]) + this->state.velocity.y;
|
||||
this->state.origin.x = std::bit_cast<float>(parent->unknown_013C[3]) + this->state.velocity.x;
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->state.origin.z = master->render.position[2] + this->state.velocity.z;
|
||||
this->state.origin.y = master->render.position[1] + this->state.velocity.y;
|
||||
this->state.origin.x = master->render.position[0] + this->state.velocity.x;
|
||||
this->state.unknown_02EC = this->state.unknown_02F0 + this->state.unknown_02EC;
|
||||
|
||||
const float speed = this->state.unknown_02C0 + this->state.unknown_02BC;
|
||||
|
|
@ -1082,8 +1287,8 @@ bool EffectParticle::UpdateDetoxication() {
|
|||
// OFFSET: 0x00BB7EC0
|
||||
// FUNCTION: fn_19782
|
||||
bool EffectParticle::UpdateExit() {
|
||||
const RagEffectState* parent = this->state.parent;
|
||||
this->state.origin = {std::bit_cast<float>(parent->unknown_013C[3]), std::bit_cast<float>(parent->unknown_013C[4]), std::bit_cast<float>(parent->unknown_013C[5])};
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->state.origin = {master->render.position[0], master->render.position[1], master->render.position[2]};
|
||||
|
||||
const float lateral = this->state.unknown_033C + this->state.unknown_0330;
|
||||
float vertical = this->state.unknown_02EC + this->state.unknown_02F0;
|
||||
|
|
@ -1146,10 +1351,10 @@ bool EffectParticle::UpdateExit() {
|
|||
// OFFSET: 0x00BB8180
|
||||
// FUNCTION: fn_19783
|
||||
bool EffectParticle::UpdateWarp() {
|
||||
const RagEffectState* parent = this->state.parent;
|
||||
const AttachedEffect* master = this->state.master;
|
||||
this->state.origin = {
|
||||
std::bit_cast<float>(parent->unknown_013C[3]) + this->state.velocity.x, std::bit_cast<float>(parent->unknown_013C[4]) + this->state.velocity.y,
|
||||
std::bit_cast<float>(parent->unknown_013C[5]) + this->state.velocity.z
|
||||
master->render.position[0] + this->state.velocity.x, master->render.position[1] + this->state.velocity.y,
|
||||
master->render.position[2] + this->state.velocity.z
|
||||
};
|
||||
|
||||
const int angle = static_cast<int>(this->state.unknown_0314);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "Contents/Effects/EffectPrimitiveRendering.h"
|
||||
#include "Contents/Effects/AttachedEffect.h"
|
||||
#include "Contents/Effects/EffectPrimitiveState.h"
|
||||
#include "Contents/Effects/EffectVisibility.h"
|
||||
#include "Contents/Actors/RenderObjectState.h"
|
||||
|
|
@ -86,7 +87,7 @@ void DrawEffectPrimitive15(EffectPrimitiveState& particle, const RenderObjectSta
|
|||
void RenderEffectPrimitive15(
|
||||
EffectPrimitiveState& particle, const RenderObjectState& render, EffectPrimitiveRenderContext& context, const EffectVisibilityContext& visibility
|
||||
) {
|
||||
if (particle.parent && PartyEffectVisible(*particle.parent, visibility)) {
|
||||
if (particle.master && PartyEffectVisible(particle.master->state, visibility)) {
|
||||
DrawEffectPrimitive15(particle, render, context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "Contents/Effects/EffectPrimitiveState.h"
|
||||
#include "Contents/Effects/RagEffectState.h"
|
||||
#include "Contents/Effects/AttachedEffect.h"
|
||||
#include "Contents/Actors/RenderObjectState.h"
|
||||
#include "Utility/Math/AffineMatrix.h"
|
||||
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
// FUNCTION: fn_19762
|
||||
EffectPrimitiveSlot::EffectPrimitiveSlot() {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
this->unknown_0084[i] = {0.0f, 0.0f, 0.0f};
|
||||
this->vectors[i] = {0.0f, 0.0f, 0.0f};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ EffectPrimitiveState::EffectPrimitiveState(RenderObjectState& render) {
|
|||
this->unknown_0158 = 0;
|
||||
this->unknown_015C = 0;
|
||||
this->unknown_0138 = 0;
|
||||
this->parent = nullptr;
|
||||
this->master = nullptr;
|
||||
this->unknown_01D4 = 0;
|
||||
this->unknown_01D8 = 0;
|
||||
this->unknown_01E0 = 0;
|
||||
|
|
@ -146,8 +146,8 @@ EffectPrimitiveState::EffectPrimitiveState(RenderObjectState& render) {
|
|||
|
||||
// INLINED
|
||||
EffectPrimitiveState::~EffectPrimitiveState() {
|
||||
if (this->parent) {
|
||||
auto& related = this->parent->related;
|
||||
if (this->master) {
|
||||
auto& related = this->master->state.related;
|
||||
|
||||
for (auto entry = related.begin(); entry != related.end(); ++entry) {
|
||||
if (*entry == this) {
|
||||
|
|
@ -165,16 +165,16 @@ EffectPrimitiveState::~EffectPrimitiveState() {
|
|||
// OFFSET: 0x00BAE460
|
||||
// FUNCTION: fn_19765
|
||||
void EffectPrimitiveState::GetColorOverride(unsigned char* red, unsigned char* green, unsigned char* blue) {
|
||||
if (this->parent->unknown_11C88[0] != -1) {
|
||||
*red = static_cast<unsigned char>(this->parent->unknown_11C88[0]);
|
||||
if (this->master->state.unknown_11C88[0] != -1) {
|
||||
*red = static_cast<unsigned char>(this->master->state.unknown_11C88[0]);
|
||||
}
|
||||
|
||||
if (this->parent->unknown_11C88[1] != -1) {
|
||||
*green = static_cast<unsigned char>(this->parent->unknown_11C88[1]);
|
||||
if (this->master->state.unknown_11C88[1] != -1) {
|
||||
*green = static_cast<unsigned char>(this->master->state.unknown_11C88[1]);
|
||||
}
|
||||
|
||||
if (this->parent->unknown_11C88[2] != -1) {
|
||||
*blue = static_cast<unsigned char>(this->parent->unknown_11C88[2]);
|
||||
if (this->master->state.unknown_11C88[2] != -1) {
|
||||
*blue = static_cast<unsigned char>(this->master->state.unknown_11C88[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -198,15 +198,15 @@ void __stdcall CalculateVectorAngle(float x, float y, std::int16_t* angle) {
|
|||
// OFFSET: 0x00BAE5D0
|
||||
// FUNCTION: fn_19767
|
||||
void EffectPrimitiveState::Initialize(
|
||||
RenderObjectState& render, RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z
|
||||
RenderObjectState& render, AttachedEffect& master, const RenderObjectState& masterRender, int type, float x, float y, float z
|
||||
) {
|
||||
const float first = x + this->offset.x;
|
||||
this->parent = &parent;
|
||||
this->master = &master;
|
||||
this->type = type;
|
||||
this->offset.x = first;
|
||||
this->offset.y = y + this->offset.y;
|
||||
this->offset.z = z + this->offset.z;
|
||||
this->origin = {parentRender.position[0], parentRender.position[1], parentRender.position[2]};
|
||||
this->origin = {masterRender.position[0], masterRender.position[1], masterRender.position[2]};
|
||||
render.position[0] = this->origin.x;
|
||||
render.position[1] = this->origin.y;
|
||||
render.position[2] = this->origin.z;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "Contents/Actors/RenderObjectState.h"
|
||||
struct RagEffectState;
|
||||
struct AttachedEffect;
|
||||
class CTexture;
|
||||
|
||||
struct EffectVector3 {
|
||||
|
|
@ -33,34 +33,42 @@ struct EffectPrimitiveRecord {
|
|||
|
||||
struct EffectPrimitiveSlot {
|
||||
EffectPrimitiveSlot();
|
||||
/* 0000 */ unsigned char active;
|
||||
/* 0000 */ unsigned char life;
|
||||
/* 0001 */ unsigned char unknown_0001;
|
||||
/* 0002 */ std::int16_t unknown_0002;
|
||||
/* 0004 */ std::int16_t unknown_0004;
|
||||
/* 0006 */ std::int16_t displayAngle;
|
||||
/* 0008 */ float unknown_0008;
|
||||
/* 000C */ int frame;
|
||||
/* 0010 */ std::int16_t angle;
|
||||
/* 0002 */ std::int16_t alphaB;
|
||||
/* 0004 */ std::int16_t alphaT;
|
||||
/* 0006 */ std::int16_t fullDisplayAngle;
|
||||
/* 0008 */ float maxHeight;
|
||||
/* 000C */ int process;
|
||||
/* 0010 */ std::int16_t rotStart;
|
||||
/* 0012 */ unsigned char unknown_0012[2];
|
||||
/* 0014 */ float values[21];
|
||||
/* 0068 */ unsigned char finished[21];
|
||||
/* 0014 */ float height[21];
|
||||
/* 0068 */ unsigned char flag1[21];
|
||||
/* 007D */ unsigned char unknown_007D;
|
||||
/* 007E */ std::int16_t unknown_007E;
|
||||
/* 0080 */ float unknown_0080;
|
||||
/* 0084 */ EffectVector3 unknown_0084[4];
|
||||
/* 007E */ std::int16_t riseAngle;
|
||||
/* 0080 */ float distance;
|
||||
union {
|
||||
/* 0084 */ EffectVector3 vectors[4];
|
||||
struct {
|
||||
/* 0084 */ EffectVector3 vecBNow;
|
||||
/* 0090 */ EffectVector3 vecTNow;
|
||||
/* 009C */ EffectVector3 vecBPre;
|
||||
/* 00A8 */ EffectVector3 vecTPre;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct EffectPrimitiveState {
|
||||
explicit EffectPrimitiveState(RenderObjectState& render);
|
||||
~EffectPrimitiveState();
|
||||
void Initialize(RenderObjectState& render, RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z);
|
||||
void Initialize(RenderObjectState& render, AttachedEffect& master, const RenderObjectState& masterRender, int type, float x, float y, float z);
|
||||
void UpdateColor();
|
||||
void InitializeRecords(const RenderObjectState& render);
|
||||
void GetColorOverride(unsigned char* red, unsigned char* green, unsigned char* blue);
|
||||
|
||||
/* 0138 */ std::uint32_t unknown_0138;
|
||||
/* 013C */ std::uint32_t unknown_013C;
|
||||
/* 0140 */ RagEffectState* parent;
|
||||
/* 0140 */ AttachedEffect* master;
|
||||
/* 0144 */ CTexture** textures;
|
||||
/* 0148 */ std::uint32_t unknown_0148;
|
||||
/* 014C */ EffectVector3 unknown_014C;
|
||||
|
|
@ -185,9 +193,9 @@ static_assert(offsetof(EffectVector3, z) == 0x8);
|
|||
static_assert(offsetof(EffectPrimitiveRecord, corners) == 0xC);
|
||||
static_assert(offsetof(EffectPrimitiveRecord, matrix) == 0x48);
|
||||
static_assert(offsetof(EffectPrimitiveRecord, color) == 0x88);
|
||||
static_assert(offsetof(EffectPrimitiveSlot, values) == 0x14);
|
||||
static_assert(offsetof(EffectPrimitiveSlot, finished) == 0x68);
|
||||
static_assert(offsetof(EffectPrimitiveSlot, unknown_0084) == 0x84);
|
||||
static_assert(offsetof(EffectPrimitiveSlot, height) == 0x14);
|
||||
static_assert(offsetof(EffectPrimitiveSlot, flag1) == 0x68);
|
||||
static_assert(offsetof(EffectPrimitiveSlot, vecBNow) == 0x84);
|
||||
static_assert(sizeof(EffectPrimitiveState) == 0xF8E0);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "Contents/Effects/AttachedEffect.h"
|
||||
#include "Contents/Effects/EffectActor.h"
|
||||
#include "Contents/Effects/EffectParticle.h"
|
||||
#include "Contents/Effects/PartyEffect.h"
|
||||
#include "Contents/Effects/RagEffectState.h"
|
||||
#include "Contents/Ground/TerrainHeight.h"
|
||||
#include "Render/Textures/TextureCache.h"
|
||||
|
||||
|
|
@ -10,9 +10,12 @@
|
|||
// OFFSET: 0x00C2CF20
|
||||
// FUNCTION: fn_20088
|
||||
bool UpdatePartyEffect(
|
||||
RagEffectState& effect, RenderObjectState& render, ResourceMgr& resources, JobNames& names, std::list<CRenderObject*>& worldObjects, TextureCache& textures,
|
||||
const TerrainHeight& ground, int updateTick
|
||||
AttachedEffect& self, ResourceMgr& resources, JobNames& names, std::list<CRenderObject*>& worldObjects, TextureCache& textures, const TerrainHeight& ground,
|
||||
int updateTick
|
||||
) {
|
||||
RagEffectState& effect = self.state;
|
||||
RenderObjectState& render = self.render;
|
||||
|
||||
if (!effect.parent) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -36,7 +39,7 @@ bool UpdatePartyEffect(
|
|||
}
|
||||
|
||||
if (effect.unknown_0178 == 0) {
|
||||
EffectParticle* particle = CreateEffectParticle(effect, render, 15, 0, 0, 0, resources, names, worldObjects);
|
||||
EffectParticle* particle = CreateEffectParticle(self, render, 15, 0, 0, 0, resources, names, worldObjects);
|
||||
effect.unknown_11C84 = &particle->state;
|
||||
EffectPrimitiveState& state = *effect.unknown_11C84;
|
||||
state.lifetime = 9999;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
#include <list>
|
||||
|
||||
struct RagEffectState;
|
||||
struct RenderObjectState;
|
||||
struct AttachedEffect;
|
||||
struct EffectParticle;
|
||||
struct JobNames;
|
||||
struct TerrainHeight;
|
||||
|
|
@ -13,8 +12,8 @@ class TextureCache;
|
|||
class CRenderObject;
|
||||
|
||||
bool UpdatePartyEffect(
|
||||
RagEffectState& effect, RenderObjectState& render, ResourceMgr& resources, JobNames& names, std::list<CRenderObject*>& worldObjects, TextureCache& textures,
|
||||
const TerrainHeight& ground, int updateTick
|
||||
AttachedEffect& self, ResourceMgr& resources, JobNames& names, std::list<CRenderObject*>& worldObjects, TextureCache& textures, const TerrainHeight& ground,
|
||||
int updateTick
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ class GroundGeometry;
|
|||
struct NaviCell {
|
||||
/* 0000 */ int x;
|
||||
/* 0004 */ int y;
|
||||
|
||||
int GetY() const;
|
||||
};
|
||||
|
||||
struct NaviLink {
|
||||
|
|
@ -34,6 +36,12 @@ struct NaviDataEntry {
|
|||
};
|
||||
|
||||
struct NaviRouteLine {
|
||||
// OFFSET: 0x00B92F10
|
||||
// FUNCTION: fn_19558
|
||||
~NaviRouteLine() {
|
||||
this->text.clear();
|
||||
}
|
||||
|
||||
/* 0000 */ int kind;
|
||||
/* 0004 */ int x;
|
||||
/* 0008 */ int y;
|
||||
|
|
@ -79,6 +87,9 @@ public:
|
|||
virtual const char* GetTitle() const;
|
||||
virtual NaviCell* GetCell(NaviCell* out) const;
|
||||
virtual CNaviInfo* GetInfo() const;
|
||||
|
||||
bool HasId(const unsigned int& id) const;
|
||||
bool IsNamed(const char* name) const;
|
||||
};
|
||||
|
||||
// VTABLE: vt_01778
|
||||
|
|
@ -105,6 +116,17 @@ public:
|
|||
CNaviInfo* GetInfo() const override;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct NaviObjectRecord {
|
||||
/* 0000 */ int type;
|
||||
/* 0004 */ int index;
|
||||
/* 0008 */ int cellX;
|
||||
/* 000C */ int cellY;
|
||||
/* 0010 */ std::int16_t nameLength;
|
||||
/* 0012 */ char name[1];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
class CNaviInfo {
|
||||
public:
|
||||
~CNaviInfo();
|
||||
|
|
@ -118,10 +140,12 @@ public:
|
|||
std::vector<CNavi_Link*>::iterator LinksEnd();
|
||||
int GetCellY() const;
|
||||
int GetIndex() const;
|
||||
int GetCellX() const;
|
||||
CNavi_Link* FindLink(unsigned int key, bool byId);
|
||||
CNavi_Object* FindNpc(unsigned int key, bool byId);
|
||||
CNavi_Object* FindNpcAt(int cellX, int cellY);
|
||||
std::vector<CNavi_Object*>* Npcs();
|
||||
CNavi_Link* FindMatchingLink(CNavi_Link link);
|
||||
|
||||
/* 0000 */ int index;
|
||||
/* 0004 */ int type;
|
||||
|
|
@ -137,12 +161,22 @@ public:
|
|||
|
||||
struct NavigationTarget {
|
||||
NavigationTarget() : type(-1), object(nullptr), x(-1), y(-1) {}
|
||||
|
||||
// INLINED
|
||||
NavigationTarget(int type, void* object, int x, int y, std::string name) {
|
||||
this->type = type;
|
||||
this->object = object;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
~NavigationTarget();
|
||||
|
||||
/* 0000 */ int type;
|
||||
/* 0004 */ void* object;
|
||||
/* 0008 */ int x;
|
||||
/* 000C */ int y;
|
||||
/* 0008 */ int x = 0;
|
||||
/* 000C */ int y = 0;
|
||||
/* 0010 */ std::string name;
|
||||
};
|
||||
|
||||
|
|
@ -155,6 +189,8 @@ public:
|
|||
CNaviInfo* GetInfo();
|
||||
NaviCell* GetCell(NaviCell* out);
|
||||
void Clear();
|
||||
void ClearAll();
|
||||
CNavi_Link* FindLink(unsigned int key, bool byId);
|
||||
int FindRoute(std::vector<CNavi_Link*>* route, bool direct, bool allowGates, bool includeObjects, bool allowWarps, int side);
|
||||
void ResetLinkDepths();
|
||||
|
||||
|
|
@ -190,6 +226,9 @@ public:
|
|||
std::string DestinationTitle();
|
||||
float FitToSquare(int* offsetX, int* offsetY, int width, int height, float size) const;
|
||||
void LoadSettings();
|
||||
bool BuildRoute(int startX, int startY, int destX, int destY, bool collectCells);
|
||||
NaviCell* MapCellToView(NaviCell* out, const char* mapName, int cellX, int cellY, float size);
|
||||
std::string RouteText();
|
||||
void Reset(bool clearAll);
|
||||
void ClearRouteNodes();
|
||||
void ClearNodePaths();
|
||||
|
|
@ -197,6 +236,17 @@ public:
|
|||
bool UpdateGround();
|
||||
bool PlayerCell(int* column, int* row);
|
||||
bool LoadStates(std::vector<char> packet);
|
||||
bool AddState(const std::vector<std::string>& tokens);
|
||||
bool ParseFlags(const char* text, bool* first, bool* second, bool* third);
|
||||
NaviCell ParseCell(const char* text);
|
||||
std::vector<char> WriteTarget(NavigationTarget target);
|
||||
std::vector<char> WriteObject(CNavi_Object* object);
|
||||
void ClearSavedTarget();
|
||||
void ClearCurrentObject();
|
||||
void ClearStates();
|
||||
void ClearNodes();
|
||||
int FindNodePath(unsigned int index);
|
||||
void SelectNodePath(std::string name);
|
||||
|
||||
/* 0000 */ CNaviData data;
|
||||
/* 004C */ CPathFinder pathFinder;
|
||||
|
|
@ -254,6 +304,7 @@ static_assert(offsetof(CNaviInfo, visited) == 0x40);
|
|||
static_assert(offsetof(NaviDataEntry, cost) == 0x08);
|
||||
static_assert(offsetof(CNavi_Link, linkedLinks) == 0x8C);
|
||||
static_assert(sizeof(NaviCell) == 0x08);
|
||||
static_assert(offsetof(NaviObjectRecord, name) == 0x12);
|
||||
static_assert(sizeof(NaviDataEntry) == 0x0C);
|
||||
static_assert(sizeof(NaviRouteLine) == 0x2C);
|
||||
static_assert(offsetof(NaviRouteLine, text) == 0x0C);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include "Client/Mode/CGameMode.h"
|
||||
#include "Contents/World/WorldScene.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
// OFFSET: 0x00B8DF10
|
||||
// FUNCTION: fn_19461
|
||||
std::uint16_t CNavi_Object::GetFlag() const {
|
||||
|
|
@ -180,3 +182,18 @@ CNavi_Object* CNaviInfo::FindNpcAt(int cellX, int cellY) {
|
|||
std::vector<CNavi_Object*>* CNaviInfo::Npcs() {
|
||||
return &this->npcs;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B8E010
|
||||
// FUNCTION: fn_19465
|
||||
CNavi_Link* CNaviInfo::FindMatchingLink(CNavi_Link link) {
|
||||
const CNavi_Link target = link;
|
||||
for (CNavi_Link* candidate : this->links) {
|
||||
if (candidate->cellX == target.cellX && candidate->cellY == target.cellY && candidate->unknown_0080 == target.unknown_0080 &&
|
||||
candidate->unknown_0084 == target.unknown_0084 && candidate->info != nullptr &&
|
||||
std::strcmp(candidate->info->name.c_str(), target.info->name.c_str()) == 0 && candidate->linkedInfo != nullptr &&
|
||||
std::strcmp(candidate->linkedInfo->name.c_str(), target.linkedInfo->name.c_str()) == 0) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
#include "Contents/NavigationManager.h"
|
||||
|
||||
#include "Contents/MessageTable.h"
|
||||
#include "Utility/Text/FormatString.h"
|
||||
#include "Client/Registry.h"
|
||||
#include "Client/Session.h"
|
||||
#include "Resource/ResourceMgr.h"
|
||||
#include "UI/Window/UIWindow.h"
|
||||
#include "UI/Window/UIWindowMgr.h"
|
||||
#include "Utility/RegistryKey.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
|
@ -17,6 +23,170 @@ CNaviInfo* CNavigationManager::FindObject(const char* name) const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B88840
|
||||
// FUNCTION: fn_19377
|
||||
CNavi_Link* CNaviData::FindLink(unsigned int key, bool byId) {
|
||||
if (byId) {
|
||||
for (CNavi_Link* object : this->objects) {
|
||||
if (object->HasId(key)) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
if (this->objects.empty() || key >= this->objects.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return this->objects[key];
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B88910
|
||||
// FUNCTION: fn_19379
|
||||
int NaviCell::GetY() const {
|
||||
return this->y;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B88930
|
||||
// FUNCTION: fn_19381
|
||||
void CNaviData::ClearAll() {
|
||||
this->Clear();
|
||||
|
||||
for (CNavi_Link*& object : this->objects) {
|
||||
if (object != nullptr) {
|
||||
delete object;
|
||||
}
|
||||
object = nullptr;
|
||||
}
|
||||
this->objects.clear();
|
||||
|
||||
for (CNaviInfo*& info : this->destinations) {
|
||||
if (info != nullptr) {
|
||||
delete info;
|
||||
}
|
||||
info = nullptr;
|
||||
}
|
||||
this->destinations.clear();
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B8CF70
|
||||
// FUNCTION: fn_19432
|
||||
bool CNavi_Object::HasId(const unsigned int& id) const {
|
||||
return static_cast<unsigned int>(this->id) == id;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B8D0D0
|
||||
// FUNCTION: fn_19433
|
||||
bool CNavi_Object::IsNamed(const char* name) const {
|
||||
if (name == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return this->name == std::string(name);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B8E8E0
|
||||
// FUNCTION: fn_19496
|
||||
int CNaviInfo::GetCellX() const {
|
||||
return this->cellX;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B97750
|
||||
// FUNCTION: fn_19600
|
||||
bool CNavigationManager::BuildRoute(int startX, int startY, int destX, int destY, bool collectCells) {
|
||||
this->movementRoute.points.clear();
|
||||
const bool found = this->pathFinder.FindPath(0, startX, startY, 8, 8, destX, destY, 1, this->movementRoute, 15);
|
||||
this->pathFinder.Reset();
|
||||
if (!collectCells) {
|
||||
return found;
|
||||
}
|
||||
|
||||
this->cells.clear();
|
||||
if (!found) {
|
||||
return found;
|
||||
}
|
||||
|
||||
CNaviInfo* info = this->FindObject(g_session.m_navigationPlayerMap);
|
||||
if (info == nullptr) {
|
||||
const std::string resolved = ResourceMgr::Instance().aliases.ResolveMapName(g_session.m_navigationPlayerMap);
|
||||
info = this->FindObject(resolved.c_str());
|
||||
if (info == nullptr) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
const int height = info->GetCellY();
|
||||
const int width = info->GetCellX();
|
||||
int offsetX;
|
||||
int offsetY;
|
||||
const float scale = this->FitToSquare(&offsetX, &offsetY, width, height, 126.0f);
|
||||
for (const MovementRoutePoint& point : this->movementRoute.points) {
|
||||
NaviCell cell;
|
||||
cell.x = static_cast<int>(point.x * scale + offsetX);
|
||||
cell.y = static_cast<int>(126.0f - (point.y * scale + offsetY));
|
||||
|
||||
bool exists = false;
|
||||
for (const NaviCell& other : this->cells) {
|
||||
if (other.x == cell.x && other.y == cell.y) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!exists) {
|
||||
this->cells.push_back(cell);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_windowMgr.window_4F174 != nullptr) {
|
||||
g_windowMgr.window_4F174->Invalidate();
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B97E90
|
||||
// FUNCTION: fn_19603
|
||||
NaviCell* CNavigationManager::MapCellToView(NaviCell* out, const char* mapName, int cellX, int cellY, float size) {
|
||||
CNaviInfo* info = this->FindObject(mapName);
|
||||
if (info == nullptr) {
|
||||
const std::string resolved = ResourceMgr::Instance().aliases.ResolveMapName(mapName);
|
||||
info = this->FindObject(resolved.c_str());
|
||||
}
|
||||
|
||||
out->x = -1;
|
||||
out->y = -1;
|
||||
if (info != nullptr) {
|
||||
const int height = info->GetCellY();
|
||||
const int width = info->GetCellX();
|
||||
int offsetX;
|
||||
int offsetY;
|
||||
const float scale = this->FitToSquare(&offsetX, &offsetY, width, height, size);
|
||||
out->x = static_cast<int>(cellX * scale + offsetX);
|
||||
out->y = static_cast<int>(static_cast<int>(size) - (cellY * scale + offsetY));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B98630
|
||||
// FUNCTION: fn_19608
|
||||
std::string CNavigationManager::RouteText() {
|
||||
char buffer[0x32];
|
||||
std::memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
CNaviInfo* info = this->data.GetInfo();
|
||||
if (info != nullptr) {
|
||||
NaviCell cell;
|
||||
if (this->data.GetCell(&cell)->x > 0) {
|
||||
NaviCell cellY;
|
||||
NaviCell cellX;
|
||||
const int y = this->data.GetCell(&cellY)->y;
|
||||
const int x = this->data.GetCell(&cellX)->x;
|
||||
StringFormat(buffer, sizeof(buffer), static_cast<std::size_t>(-1), "[%s] -> %s %d %d", LookupMessage(3585), info->GetName(), x, y);
|
||||
} else {
|
||||
StringFormat(buffer, sizeof(buffer), static_cast<std::size_t>(-1), "[%s] %s", LookupMessage(3585), info->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
this->routeText.assign(buffer, std::strlen(buffer));
|
||||
return this->routeText;
|
||||
}
|
||||
// OFFSET: 0x00B8D270
|
||||
// FUNCTION: fn_19434
|
||||
bool CNaviInfo::HasName(const char* name) const {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
#include "Client/Session.h"
|
||||
#include "Resource/ResourceMgr.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
// GLOBAL: gl_24627
|
||||
|
|
@ -270,3 +272,282 @@ void CNavigationManager::Reset(bool clearAll) {
|
|||
this->unknown_12A4 = nullptr;
|
||||
this->ClearRouteNodes();
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B93110
|
||||
// FUNCTION: fn_19562
|
||||
bool CNavigationManager::AddState(const std::vector<std::string>& tokens) {
|
||||
if (tokens.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CNaviInfo* info = this->FindObject(tokens[0].c_str());
|
||||
if (info == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const NaviCell cell = this->ParseCell(tokens[1].c_str());
|
||||
if (cell.x == -1 || cell.y == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
for (std::size_t i = 2; i < tokens.size(); ++i) {
|
||||
name.append(" ", 1);
|
||||
name.append(tokens[i]);
|
||||
}
|
||||
|
||||
NavigationTarget target(0, info, cell.x, cell.y, name);
|
||||
this->states.push_back(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B93670
|
||||
// FUNCTION: fn_19563
|
||||
bool CNavigationManager::ParseFlags(const char* text, bool* first, bool* second, bool* third) {
|
||||
const char* firstSlash = std::strstr(text, "/");
|
||||
if (firstSlash == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* rest = firstSlash + 1;
|
||||
const char* secondSlash = std::strstr(rest, "/");
|
||||
if (secondSlash == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string firstText(text, firstSlash);
|
||||
if (firstText.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string secondText(rest, secondSlash);
|
||||
if (secondText.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string thirdText(secondSlash + 1, text + std::strlen(text));
|
||||
if (thirdText.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int firstValue = std::atoi(firstText.c_str());
|
||||
const int secondValue = std::atoi(secondText.c_str());
|
||||
const int thirdValue = std::atoi(thirdText.c_str());
|
||||
if ((firstValue != 0 && firstValue != 1) || (secondValue != 0 && secondValue != 1) || (thirdValue != 0 && thirdValue != 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*first = firstValue == 1;
|
||||
*second = secondValue == 1;
|
||||
*third = thirdValue == 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B938F0
|
||||
// FUNCTION: fn_19564
|
||||
NaviCell CNavigationManager::ParseCell(const char* text) {
|
||||
NaviCell cell;
|
||||
const char* slash;
|
||||
if (text == nullptr || (slash = std::strstr(text, "/")) == nullptr) {
|
||||
cell.x = -1;
|
||||
cell.y = -1;
|
||||
return cell;
|
||||
}
|
||||
|
||||
std::string xText(text, slash);
|
||||
if (xText.empty()) {
|
||||
cell.x = -1;
|
||||
cell.y = -1;
|
||||
return cell;
|
||||
}
|
||||
|
||||
std::string yText(slash + 1, text + std::strlen(text));
|
||||
if (yText.empty()) {
|
||||
cell.x = -1;
|
||||
cell.y = -1;
|
||||
return cell;
|
||||
}
|
||||
|
||||
const int x = std::atoi(xText.c_str());
|
||||
const int y = std::atoi(yText.c_str());
|
||||
if (x >= 0 && x <= 500 && y >= 0 && y <= 500) {
|
||||
cell.x = x;
|
||||
cell.y = y;
|
||||
} else {
|
||||
cell.x = -1;
|
||||
cell.y = -1;
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B94890
|
||||
// FUNCTION: fn_19568
|
||||
std::vector<char> CNavigationManager::WriteTarget(NavigationTarget target) {
|
||||
std::vector<char> buffer;
|
||||
if (target.object == nullptr) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
buffer.resize(sizeof(int), '\0');
|
||||
*reinterpret_cast<int*>(buffer.data()) = target.type;
|
||||
|
||||
if (target.type == 1 || target.type == 0) {
|
||||
std::string name = static_cast<CNaviInfo*>(target.object)->GetName();
|
||||
buffer.insert(buffer.end(), name.begin(), name.end());
|
||||
} else if (target.type == 3) {
|
||||
std::vector<char> object = this->WriteObject(static_cast<CNavi_Object*>(target.object));
|
||||
buffer.insert(buffer.end(), object.begin(), object.end());
|
||||
} else if (target.type == 2) {
|
||||
std::vector<char> object = this->WriteObject(static_cast<CNavi_Object*>(target.object));
|
||||
buffer.insert(buffer.end(), object.begin(), object.end());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B94B50
|
||||
// FUNCTION: fn_19569
|
||||
std::vector<char> CNavigationManager::WriteObject(CNavi_Object* object) {
|
||||
std::vector<char> buffer;
|
||||
if (object != nullptr) {
|
||||
const int type = object->GetType();
|
||||
const int index = object->GetIndex();
|
||||
NaviCell cell;
|
||||
object->GetCell(&cell);
|
||||
std::string name = object->GetName();
|
||||
std::string title = object->GetTitle();
|
||||
std::string map = object->GetInfo()->GetName();
|
||||
|
||||
buffer.resize(map.size() + 0x16 + title.size() + name.size(), '\0');
|
||||
|
||||
NaviObjectRecord* record = reinterpret_cast<NaviObjectRecord*>(buffer.data());
|
||||
record->type = type;
|
||||
record->index = index;
|
||||
record->cellX = cell.x;
|
||||
record->cellY = cell.y;
|
||||
|
||||
const std::size_t nameLength = static_cast<std::int16_t>(name.size());
|
||||
reinterpret_cast<NaviObjectRecord*>(buffer.data())->nameLength = static_cast<std::int16_t>(name.size());
|
||||
std::memcpy(buffer.data() + 0x12, name.c_str(), nameLength);
|
||||
|
||||
const std::size_t titleLength = static_cast<std::int16_t>(title.size());
|
||||
*reinterpret_cast<std::int16_t*>(buffer.data() + nameLength + 0x12) = static_cast<std::int16_t>(title.size());
|
||||
std::memcpy(buffer.data() + nameLength + 0x14, title.c_str(), titleLength);
|
||||
|
||||
const std::size_t offset = nameLength + 0x14 + titleLength;
|
||||
*reinterpret_cast<std::int16_t*>(buffer.data() + offset) = static_cast<std::int16_t>(map.size());
|
||||
std::memcpy(buffer.data() + offset + 2, map.c_str(), static_cast<std::int16_t>(map.size()));
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B950B0
|
||||
// FUNCTION: fn_19571
|
||||
void CNavigationManager::ClearSavedTarget() {
|
||||
this->savedTarget = NavigationTarget();
|
||||
this->unknown_115C = false;
|
||||
this->routeResult = 0;
|
||||
this->nodes.clear();
|
||||
this->selectedNode = -1;
|
||||
this->movementRoute.segment = 0;
|
||||
this->unknown_117C = false;
|
||||
this->ground = nullptr;
|
||||
this->cells.clear();
|
||||
this->unknown_1258 = 1;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B95260
|
||||
// FUNCTION: fn_19572
|
||||
void CNavigationManager::ClearCurrentObject() {
|
||||
this->currentTarget.type = 0;
|
||||
this->currentTarget.object = nullptr;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B95AD0
|
||||
// FUNCTION: fn_19576
|
||||
void CNavigationManager::ClearStates() {
|
||||
this->states.clear();
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B95AF0
|
||||
// FUNCTION: fn_19577
|
||||
void CNavigationManager::ClearNodes() {
|
||||
this->nodes.clear();
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B95DC0
|
||||
// FUNCTION: fn_19579
|
||||
int CNavigationManager::FindNodePath(unsigned int index) {
|
||||
if (this->states[index].type == 1 || this->states[index].type == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < this->nodePaths.size(); ++i) {
|
||||
if (this->nodePaths[i].empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const unsigned int first = this->nodePaths[i][0];
|
||||
if (first >= this->states.size()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
NavigationTarget& target = this->states[index];
|
||||
if (target.type == 3 && target.x == -1000 && target.y == -1000) {
|
||||
if (this->states[first].type != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CNaviInfo* info = static_cast<CNaviInfo*>(this->states[first].object);
|
||||
if (info == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
CNavi_Object* object = static_cast<CNavi_Object*>(target.object);
|
||||
if (object == nullptr || object->GetInfo() == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (std::strcmp(info->GetName(), object->GetInfo()->GetName()) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
NavigationTarget& other = this->states[first];
|
||||
if (other.type == this->states[index].type) {
|
||||
CNavi_Object* otherObject = static_cast<CNavi_Object*>(other.object);
|
||||
if (otherObject == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
CNavi_Object* object = static_cast<CNavi_Object*>(this->states[index].object);
|
||||
if (object == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (std::strcmp(otherObject->GetName(), object->GetName()) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00B95FB0
|
||||
// FUNCTION: fn_19580
|
||||
void CNavigationManager::SelectNodePath(std::string name) {
|
||||
if (name.empty() || this->nodePaths.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> first = this->nodePaths[0];
|
||||
for (unsigned int i = 0; i < this->nodePaths.size(); ++i) {
|
||||
if (this->states[this->nodePaths[i][0]].name == name) {
|
||||
this->nodePaths[0] = this->nodePaths[i];
|
||||
this->nodePaths[i] = first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,82 @@
|
|||
#include "Client/Mode/ActiveGameMode.h"
|
||||
#include "Client/Mode/CGameMode.h"
|
||||
#include "Contents/Actors/GameActor.h"
|
||||
#include "Contents/Configuration/ServiceOptions.h"
|
||||
#include "Contents/Effects/EffectActor.h"
|
||||
#include "Contents/Effects/EffectLists.h"
|
||||
#include "Contents/Effects/EffectPrimitiveState.h"
|
||||
#include "Contents/MessageTable.h"
|
||||
#include "Contents/Skills/SkillId.h"
|
||||
#include "Contents/Skills/SkillInfo.h"
|
||||
#include "Contents/Sound/SoundMgr.h"
|
||||
#include "Contents/UserData/NormalItemSlots.h"
|
||||
#include "Contents/World/WorldScene.h"
|
||||
#include "Resource/World/TerrainResource.h"
|
||||
#include "Script/LuaScript.h"
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
class CEfstAction_ChangeSize : public CEfstAction {
|
||||
public:
|
||||
void Slot01(int efstId, int argument2, int argument3, int argument4, CRenderObject* actor) override;
|
||||
void Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) override;
|
||||
};
|
||||
|
||||
class CEfstAction_GenderChange : public CEfstAction {
|
||||
public:
|
||||
void Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) override;
|
||||
};
|
||||
|
||||
class CEfstAction_ShowEffect : public CEfstAction {
|
||||
public:
|
||||
void Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) override;
|
||||
};
|
||||
|
||||
class CSkillAction_RA_UNLIMIT : public CSkillAction {
|
||||
public:
|
||||
void Slot08(int level, CGameActor* source) override;
|
||||
};
|
||||
|
||||
class CEfstAction_UNLIMIT : public CEfstAction {
|
||||
public:
|
||||
void Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) override;
|
||||
};
|
||||
|
||||
class CEfstAction_SHADOW_WEAPON : public CEfstAction {
|
||||
public:
|
||||
EfstActionMessage Slot03() override;
|
||||
EfstActionMessage Slot04() override;
|
||||
};
|
||||
|
||||
class CEfstAction_DANCING_KNIFE : public CEfstAction {
|
||||
public:
|
||||
void Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) override;
|
||||
};
|
||||
|
||||
class CEfstAction_SHADOW_EXCEED : public CEfstAction {
|
||||
public:
|
||||
void Slot01(int efstId, int argument2, int argument3, int argument4, CRenderObject* actor) override;
|
||||
void Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) override;
|
||||
EfstActionMessage Slot03() override;
|
||||
EfstActionMessage Slot04() override;
|
||||
};
|
||||
|
||||
class CSkillAction_ABC_CHASING_BREAK : public CSkillAction {
|
||||
public:
|
||||
bool Slot07() override;
|
||||
};
|
||||
|
||||
class CSkillAction_ABC_CHASING_SHOT : public CSkillAction {
|
||||
public:
|
||||
bool Slot07() override;
|
||||
};
|
||||
|
||||
class CSkillAction_ABC_ABYSS_FLAME_ATK : public CSkillAction {
|
||||
public:
|
||||
bool Slot03(int argument) override;
|
||||
};
|
||||
|
||||
// GLOBAL: gl_24640
|
||||
CSkillActionMgr* g_skillActionMgr;
|
||||
|
||||
|
|
@ -404,3 +476,202 @@ bool ShowsCastEffect(int skillId) {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x007747B0
|
||||
// FUNCTION: fn_08327
|
||||
void CEfstAction_ChangeSize::Slot01(int efstId, int argument2, int argument3, int argument4, CRenderObject* actor) {
|
||||
if (actor) {
|
||||
g_effectMgr->Retire(actor->render.accountId, 2374);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x007747E0
|
||||
// FUNCTION: fn_08328
|
||||
void CEfstAction_ChangeSize::Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) {
|
||||
this->Slot00(efstId, value, 0, 0, actor, false);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00774E20
|
||||
// FUNCTION: fn_08331
|
||||
void CEfstAction_GenderChange::Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) {
|
||||
this->Slot00(efstId, value, 0, 0, actor, false);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00774F30
|
||||
// FUNCTION: fn_08334
|
||||
void CEfstAction_ShowEffect::Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) {
|
||||
this->Slot00(efstId, value, 0, 0, actor, false);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00774FB0
|
||||
// FUNCTION: fn_08335
|
||||
void CSkillAction_RA_UNLIMIT::Slot08(int level, CGameActor* source) {
|
||||
g_soundMgr->PlayWave("effect\\EF_BeginSpell.wav", 0.0f, 0.0f, 0.0f, 250, 40, 1.0f, 0);
|
||||
}
|
||||
|
||||
// OFFSET: 0x007756D0
|
||||
// FUNCTION: fn_08339
|
||||
void CEfstAction_UNLIMIT::Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) {
|
||||
this->Slot00(efstId, value, 0, 0, actor, false);
|
||||
}
|
||||
|
||||
// OFFSET: 0x007764E0
|
||||
// FUNCTION: fn_08346
|
||||
EfstActionMessage CEfstAction_SHADOW_WEAPON::Slot03() {
|
||||
return {LookupMessage(3766), 0xFFFF00};
|
||||
}
|
||||
|
||||
// OFFSET: 0x00776510
|
||||
// FUNCTION: fn_08347
|
||||
EfstActionMessage CEfstAction_SHADOW_WEAPON::Slot04() {
|
||||
return {LookupMessage(3767), 0xFF};
|
||||
}
|
||||
|
||||
// OFFSET: 0x00777910
|
||||
// FUNCTION: fn_08359
|
||||
void CEfstAction_DANCING_KNIFE::Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) {
|
||||
this->Slot00(efstId, value, 0, 0, actor, false);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00777E80
|
||||
// FUNCTION: fn_08366
|
||||
void CEfstAction_SHADOW_EXCEED::Slot01(int efstId, int argument2, int argument3, int argument4, CRenderObject* actor) {
|
||||
if (!actor) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* effectActor = static_cast<EffectActor*>(actor);
|
||||
while (effectActor->state.Attachments().HasId(1004)) {
|
||||
actor->SendObjectMessage(nullptr, 109, 0, 1004, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00777EE0
|
||||
// FUNCTION: fn_08367
|
||||
void CEfstAction_SHADOW_EXCEED::Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) {
|
||||
this->Slot00(efstId, value, 0, 0, actor, true);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00777F00
|
||||
// FUNCTION: fn_08368
|
||||
EfstActionMessage CEfstAction_SHADOW_EXCEED::Slot03() {
|
||||
return {LookupMessage(3762), 0xFFFF00};
|
||||
}
|
||||
|
||||
// OFFSET: 0x00777F30
|
||||
// FUNCTION: fn_08369
|
||||
EfstActionMessage CEfstAction_SHADOW_EXCEED::Slot04() {
|
||||
return {LookupMessage(3763), 0xFF};
|
||||
}
|
||||
|
||||
// OFFSET: 0x00778140
|
||||
// FUNCTION: fn_08371
|
||||
bool CSkillAction_ABC_CHASING_BREAK::Slot07() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00778580
|
||||
// FUNCTION: fn_08375
|
||||
bool CSkillAction_ABC_CHASING_SHOT::Slot07() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x007794D0
|
||||
// FUNCTION: fn_08385
|
||||
bool CSkillAction_ABC_ABYSS_FLAME_ATK::Slot03(int argument) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0077ACC0
|
||||
// FUNCTION: fn_08404
|
||||
std::pair<bool, int> CSkillActionMgr::ActionSlot01(int skillId) {
|
||||
const auto found = this->m_skillActions.find(skillId);
|
||||
std::unique_ptr<CSkillAction> action(found != this->m_skillActions.end() ? found->second() : nullptr);
|
||||
if (!action) {
|
||||
return {false, 8};
|
||||
}
|
||||
|
||||
return {true, action->Slot01()};
|
||||
}
|
||||
|
||||
// OFFSET: 0x0077AD90
|
||||
// FUNCTION: fn_08405
|
||||
EffectVector3 CellWorldPosition(int column, int row) {
|
||||
if (!g_world.ActiveGameMode() || !static_cast<CGameMode*>(g_world.ActiveGameMode())->scene ||
|
||||
!static_cast<CGameMode*>(g_world.ActiveGameMode())->scene->terrain) {
|
||||
return EffectVector3{0.0f, 0.0f, 0.0f};
|
||||
}
|
||||
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float z = 0.0f;
|
||||
static_cast<CGameMode*>(g_world.ActiveGameMode())->scene->terrain->Grid().CellOrigin(column, row, x, z);
|
||||
y = static_cast<CGameMode*>(g_world.ActiveGameMode())->scene->terrain->Grid().Height(x, z);
|
||||
return EffectVector3{x + 2.5f, y + 0.0f, z + 2.5f};
|
||||
}
|
||||
|
||||
// OFFSET: 0x0077AEA0
|
||||
// FUNCTION: fn_08406
|
||||
EfstActionMessage CSkillActionMgr::EfstSlot03(int efstId) {
|
||||
const auto found = this->m_efstActions.find(efstId);
|
||||
std::unique_ptr<CEfstAction> action(found != this->m_efstActions.end() ? found->second() : nullptr);
|
||||
if (!action) {
|
||||
return {nullptr, 0xFFFF00};
|
||||
}
|
||||
|
||||
return action->Slot03();
|
||||
}
|
||||
|
||||
// OFFSET: 0x0077AF80
|
||||
// FUNCTION: fn_08407
|
||||
EfstActionMessage CSkillActionMgr::EfstSlot04(int efstId) {
|
||||
const auto found = this->m_efstActions.find(efstId);
|
||||
std::unique_ptr<CEfstAction> action(found != this->m_efstActions.end() ? found->second() : nullptr);
|
||||
if (!action) {
|
||||
return {nullptr, 0xFF};
|
||||
}
|
||||
|
||||
return action->Slot04();
|
||||
}
|
||||
|
||||
// OFFSET: 0x0077B060
|
||||
// FUNCTION: fn_08408
|
||||
int CSkillActionMgr::ActionSlot14(int skillId) {
|
||||
const auto found = this->m_skillActions.find(skillId);
|
||||
std::unique_ptr<CSkillAction> action(found != this->m_skillActions.end() ? found->second() : nullptr);
|
||||
return action ? action->Slot14() : 0;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0077B210
|
||||
// FUNCTION: fn_08409
|
||||
std::pair<bool, int> CSkillActionMgr::ActionSlot02(int skillId) {
|
||||
const auto found = this->m_skillActions.find(skillId);
|
||||
std::unique_ptr<CSkillAction> action(found != this->m_skillActions.end() ? found->second() : nullptr);
|
||||
if (!action) {
|
||||
return {false, 7};
|
||||
}
|
||||
|
||||
return {true, action->Slot02()};
|
||||
}
|
||||
|
||||
// OFFSET: 0x0077B2E0
|
||||
// FUNCTION: fn_08410
|
||||
bool CSkillActionMgr::ActionSlot03(int skillId, int argument) {
|
||||
const auto found = this->m_skillActions.find(skillId);
|
||||
std::unique_ptr<CSkillAction> action(found != this->m_skillActions.end() ? found->second() : nullptr);
|
||||
return action ? action->Slot03(argument) : false;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0077B3A0
|
||||
// FUNCTION: fn_08411
|
||||
bool CSkillActionMgr::ActionSlot04(int skillId) {
|
||||
const auto found = this->m_skillActions.find(skillId);
|
||||
std::unique_ptr<CSkillAction> action(found != this->m_skillActions.end() ? found->second() : nullptr);
|
||||
return action ? action->Slot04() : false;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0077B460
|
||||
// FUNCTION: fn_08412
|
||||
bool CSkillActionMgr::HasEfstAction(int efstId) {
|
||||
return this->m_efstActions.find(efstId) != this->m_efstActions.end();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,16 +6,83 @@
|
|||
#include <functional>
|
||||
#include <map>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class CEfstAction;
|
||||
class CGameActor;
|
||||
class CRenderObject;
|
||||
class CSkillObjectAction;
|
||||
class LuaScript;
|
||||
struct EffectVector3;
|
||||
struct NormalItemSlot;
|
||||
|
||||
struct EfstActionMessage {
|
||||
/* 0000 */ const char* text;
|
||||
/* 0004 */ std::uint32_t color;
|
||||
};
|
||||
|
||||
class CSkillAction {
|
||||
public:
|
||||
virtual bool Slot00() = 0;
|
||||
virtual bool Slot00() {
|
||||
return false;
|
||||
}
|
||||
virtual int Slot01() {
|
||||
return 8;
|
||||
}
|
||||
virtual int Slot02() {
|
||||
return 7;
|
||||
}
|
||||
virtual bool Slot03(int argument) {
|
||||
return false;
|
||||
}
|
||||
virtual bool Slot04() {
|
||||
return false;
|
||||
}
|
||||
virtual bool Slot05() {
|
||||
return false;
|
||||
}
|
||||
virtual bool Slot06() {
|
||||
return false;
|
||||
}
|
||||
virtual bool Slot07() {
|
||||
return false;
|
||||
}
|
||||
virtual void Slot08(int level, CGameActor* source) {
|
||||
}
|
||||
virtual void Slot09(int argument1, int argument2, int argument3) {
|
||||
}
|
||||
virtual void Slot10(int argument1, int argument2, int argument3, int argument4, int argument5) {
|
||||
}
|
||||
virtual void Slot11(int level, CGameActor* source, CGameActor* target) {
|
||||
}
|
||||
virtual void Slot12(int argument1, int argument2, int argument3, int argument4, int argument5) {
|
||||
}
|
||||
virtual bool Slot13() {
|
||||
return false;
|
||||
}
|
||||
virtual int Slot14() {
|
||||
return 0;
|
||||
}
|
||||
virtual void Slot15(int level, CGameActor* source, CGameActor* target) {
|
||||
}
|
||||
virtual void Slot16(int level, CGameActor* source, CGameActor* target) {
|
||||
}
|
||||
};
|
||||
|
||||
class CEfstAction {
|
||||
public:
|
||||
virtual void Slot00(int efstId, int value, int argument3, int argument4, CRenderObject* actor, bool argument6) {
|
||||
}
|
||||
virtual void Slot01(int efstId, int argument2, int argument3, int argument4, CRenderObject* actor) {
|
||||
}
|
||||
virtual void Slot02(int efstId, int value, int argument3, int argument4, CRenderObject* actor) {
|
||||
}
|
||||
virtual EfstActionMessage Slot03() {
|
||||
return {nullptr, 0xFFFF00};
|
||||
}
|
||||
virtual EfstActionMessage Slot04() {
|
||||
return {nullptr, 0xFF};
|
||||
}
|
||||
};
|
||||
|
||||
struct SkillInfoEntry {
|
||||
|
|
@ -68,6 +135,14 @@ public:
|
|||
static CSkillActionMgr* GetInstance();
|
||||
|
||||
bool IsSupportAction(int skillId);
|
||||
std::pair<bool, int> ActionSlot01(int skillId);
|
||||
std::pair<bool, int> ActionSlot02(int skillId);
|
||||
int ActionSlot14(int skillId);
|
||||
bool ActionSlot03(int skillId, int argument);
|
||||
bool ActionSlot04(int skillId);
|
||||
EfstActionMessage EfstSlot03(int efstId);
|
||||
EfstActionMessage EfstSlot04(int efstId);
|
||||
bool HasEfstAction(int efstId);
|
||||
};
|
||||
|
||||
extern CSkillActionMgr* g_skillActionMgr;
|
||||
|
|
@ -85,6 +160,7 @@ bool IsOptionalSelfTargetSkill(int skillId);
|
|||
bool HidesUseFailureMessage(int skillId);
|
||||
bool IsSupportSkill(int skillId);
|
||||
bool ShowsCastEffect(int skillId);
|
||||
EffectVector3 CellWorldPosition(int column, int row);
|
||||
static_assert(sizeof(SkillInfoEntry) == 8);
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
static_assert(offsetof(SkillInfoEntry, unknown_0004) == 0x4);
|
||||
|
|
@ -93,6 +169,8 @@ static_assert(offsetof(CSkillActionMgr, m_efstActions) == 0x0C);
|
|||
static_assert(offsetof(CSkillActionMgr, m_skillObjectActions) == 0x14);
|
||||
static_assert(sizeof(CSkillActionMgr) == 0x1C);
|
||||
static_assert(sizeof(CSkillAction) == 4);
|
||||
static_assert(sizeof(CEfstAction) == 4);
|
||||
static_assert(sizeof(EfstActionMessage) == 8);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
33
Source/UI/Buttons/UIBmpRadioBtn.h
Normal file
33
Source/UI/Buttons/UIBmpRadioBtn.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_BUTTONS_UIBMPRADIOBTN_H
|
||||
#define RAGNAROK_SOURCE_UI_BUTTONS_UIBMPRADIOBTN_H
|
||||
|
||||
#include "UI/Window/UIWindow.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct UIButtonContext;
|
||||
|
||||
class UIBmpRadioBtn : public UIWindow {
|
||||
public:
|
||||
void Slot28(int x, int y) override;
|
||||
|
||||
protected:
|
||||
/* 007C */ unsigned char unknown_007C[0x64];
|
||||
/* 00E0 */ std::string m_tooltip;
|
||||
UIButtonContext* m_controls;
|
||||
};
|
||||
|
||||
class UIBmpRadioBtn2 : public UIBmpRadioBtn {
|
||||
};
|
||||
|
||||
class UICaptchaImage : public UIWindow {
|
||||
public:
|
||||
void Slot28(int x, int y) override;
|
||||
|
||||
protected:
|
||||
/* 007C */ unsigned char unknown_007C[0x124];
|
||||
/* 01A0 */ std::string m_tooltip;
|
||||
UIButtonContext* m_controls;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
#include "Render/DeviceContext/DeviceContext.h"
|
||||
#include "UI/UIBarGraph.h"
|
||||
#include "UI/Buttons/UIBmpRadioBtn.h"
|
||||
#include "Render/Text/TextContext.h"
|
||||
#include "UI/Window/UIWindowMgr.h"
|
||||
#include "UI/Buttons/UIItemTagButton.h"
|
||||
|
|
@ -6,6 +8,7 @@
|
|||
#include "UI/Lists/UITreeView.h"
|
||||
#include "UI/UIStaticItem.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -200,3 +203,76 @@ void UIItemTagButton::Slot28(int x, int y) {
|
|||
// FUNCTION: fn_11459
|
||||
void UIStaticItem_Illust::Slot28(int, int) {
|
||||
}
|
||||
|
||||
// OFFSET: 0x00891810
|
||||
// FUNCTION: fn_11450
|
||||
void UIBmpRadioBtn::Slot28(int, int) {
|
||||
if (!this->m_tooltip.empty()) {
|
||||
int screenX = 0, screenY = -20;
|
||||
|
||||
for (const UIWindow* window = this; window; window = window->parent) {
|
||||
screenX = (screenX + window->geometry.x);
|
||||
screenY = (screenY + window->geometry.y);
|
||||
}
|
||||
|
||||
this->m_controls->services.Tooltip(this->m_tooltip.c_str(), screenX, screenY, -1, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00891870
|
||||
// FUNCTION: fn_11451
|
||||
void UICaptchaImage::Slot28(int, int) {
|
||||
if (!this->m_tooltip.empty()) {
|
||||
int screenX = 0, screenY = -20;
|
||||
|
||||
for (const UIWindow* window = this; window; window = window->parent) {
|
||||
screenX = (screenX + window->geometry.x);
|
||||
screenY = (screenY + window->geometry.y);
|
||||
}
|
||||
|
||||
this->m_controls->services.Tooltip(this->m_tooltip.c_str(), screenX, screenY, -1, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00891240
|
||||
// FUNCTION: fn_11447
|
||||
void UIBarGraph4::Slot28(int, int) {
|
||||
if (!this->m_current || !this->m_maximum || *this->m_maximum < *this->m_current || *this->m_maximum == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int screenX = 0, screenY = -16;
|
||||
|
||||
for (const UIWindow* window = this; window; window = window->parent) {
|
||||
screenX = (screenX + window->geometry.x);
|
||||
screenY = (screenY + window->geometry.y);
|
||||
}
|
||||
|
||||
char text[260];
|
||||
std::memset(text, 0, sizeof(text));
|
||||
const int permille = static_cast<int>(static_cast<float>(*this->m_current) / static_cast<float>(*this->m_maximum) * 1000.0f);
|
||||
std::sprintf(text, "%.1f %%", static_cast<float>(permille) * 0.1f);
|
||||
this->m_controls->services.Tooltip(text, screenX, screenY, -1, false, true);
|
||||
}
|
||||
|
||||
// OFFSET: 0x008918D0
|
||||
// FUNCTION: fn_11452
|
||||
void UIINT64BarGraph::Slot28(int, int) {
|
||||
if (this->m_maximum < this->m_current || this->m_maximum == 0 || this->m_maximum == 99999999) {
|
||||
return;
|
||||
}
|
||||
|
||||
int screenX = 0, screenY = -16;
|
||||
|
||||
for (const UIWindow* window = this; window; window = window->parent) {
|
||||
screenX = (screenX + window->geometry.x);
|
||||
screenY = (screenY + window->geometry.y);
|
||||
}
|
||||
|
||||
char text[260];
|
||||
std::memset(text, 0, sizeof(text));
|
||||
const int permille = static_cast<int>(static_cast<double>(this->m_current) / static_cast<double>(this->m_maximum) * 1000.0);
|
||||
std::sprintf(text, "%.1f %%", static_cast<float>(permille) * 0.1f);
|
||||
this->m_controls->services.Tooltip(text, screenX, screenY, -1, false, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ struct ItemTagRetirement;
|
|||
struct ChatSuggestions {
|
||||
UIWindow& chat;
|
||||
UIWindow* const& window;
|
||||
UIEditCtrl* const& input;
|
||||
|
||||
bool Visible() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,16 +3,21 @@
|
|||
|
||||
#include "UI/Window/UIFrameWnd.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class UINewChatWnd : public UIFrameWnd {
|
||||
public:
|
||||
void Move(int x, int y) override;
|
||||
void Show(int visible) override;
|
||||
|
||||
private:
|
||||
/* 00BC */ int unknown_00BC;
|
||||
/* 00C0 */ int unknown_00C0;
|
||||
/* 00C4 */ int m_inputX;
|
||||
/* 00C8 */ int m_inputY;
|
||||
/* 00CC */ unsigned char unknown_00CC[0x50];
|
||||
/* 00CC */ unsigned char unknown_00CC[0x28];
|
||||
/* 00F4 */ std::vector<UIWindow*> m_tabs;
|
||||
/* 0100 */ unsigned char unknown_0100[0x1C];
|
||||
/* 011C */ int m_inputOffsetY;
|
||||
};
|
||||
|
||||
|
|
|
|||
16
Source/UI/Chat/UISubChatMiniWnd.h
Normal file
16
Source/UI/Chat/UISubChatMiniWnd.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_CHAT_UISUBCHATMINIWND_H
|
||||
#define RAGNAROK_SOURCE_UI_CHAT_UISUBCHATMINIWND_H
|
||||
|
||||
#include "UI/Window/UIFrameWnd.h"
|
||||
|
||||
class UISubChatMiniWnd : public UIFrameWnd {
|
||||
public:
|
||||
int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override;
|
||||
|
||||
private:
|
||||
/* 00B4 */ int unknown_00B4;
|
||||
/* 00B8 */ int m_rowHeight;
|
||||
/* 00BC */ int m_offsetY;
|
||||
};
|
||||
|
||||
#endif
|
||||
14
Source/UI/Dialogs/UIMemorialDunWnd.h
Normal file
14
Source/UI/Dialogs/UIMemorialDunWnd.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_DIALOGS_UIMEMORIALDUNWND_H
|
||||
#define RAGNAROK_SOURCE_UI_DIALOGS_UIMEMORIALDUNWND_H
|
||||
|
||||
#include "UI/Window/UIFrameWnd.h"
|
||||
|
||||
extern int g_memorialDunWndX;
|
||||
extern int g_memorialDunWndY;
|
||||
|
||||
class UIMemorialDunWnd : public UIFrameWnd {
|
||||
public:
|
||||
void Move(int x, int y) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
17
Source/UI/Lists/UIChatHisBox.h
Normal file
17
Source/UI/Lists/UIChatHisBox.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_LISTS_UICHATHISBOX_H
|
||||
#define RAGNAROK_SOURCE_UI_LISTS_UICHATHISBOX_H
|
||||
|
||||
#include "UI/Lists/UIListBox.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class UIChatHisBox : public UIListBox {
|
||||
public:
|
||||
const char* HistoryText(unsigned int index);
|
||||
|
||||
/* 00DC */ unsigned char unknown_00DC[0x18];
|
||||
/* 00F4 */ std::vector<std::string> history;
|
||||
};
|
||||
|
||||
#endif
|
||||
16
Source/UI/Lists/UIImgMenu.h
Normal file
16
Source/UI/Lists/UIImgMenu.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_LISTS_UIIMGMENU_H
|
||||
#define RAGNAROK_SOURCE_UI_LISTS_UIIMGMENU_H
|
||||
|
||||
#include "UI/Window/UIWindow.h"
|
||||
|
||||
class UIImgMenu : public UIWindow {
|
||||
public:
|
||||
int ItemAt(int x, int y);
|
||||
|
||||
/* 0080 */ int count;
|
||||
/* 0084 */ int itemWidth;
|
||||
/* 0088 */ int itemHeight;
|
||||
/* 008C */ int horizontal;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -29,6 +29,7 @@ public:
|
|||
virtual void AddLine(const char* text, std::uint32_t color);
|
||||
virtual void Clear();
|
||||
virtual void Refresh();
|
||||
int FindLine(const std::string& text);
|
||||
|
||||
/* 007C */ int backgroundRed;
|
||||
/* 0080 */ int backgroundGreen;
|
||||
|
|
|
|||
144
Source/UI/Lists/UIListBoxTemplate.h
Normal file
144
Source/UI/Lists/UIListBoxTemplate.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_LISTS_UILISTBOXTEMPLATE_H
|
||||
#define RAGNAROK_SOURCE_UI_LISTS_UILISTBOXTEMPLATE_H
|
||||
|
||||
#include "UI/Lists/UIVScrollBar.h"
|
||||
#include "UI/Window/UIControl.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
class CUIListItem : public CUIControl {
|
||||
public:
|
||||
virtual void SetSelected(bool selected);
|
||||
|
||||
/* 0084 */ unsigned char unknown_0084[0x04];
|
||||
/* 0088 */ int selected;
|
||||
/* 008C */ unsigned char unknown_008C[0x04];
|
||||
/* 0090 */ unsigned char frozen;
|
||||
/* 0094 */ int index;
|
||||
};
|
||||
|
||||
namespace AdventureGuide {
|
||||
class CUISubTab : public CUIListItem {};
|
||||
class CUITab : public CUIListItem {};
|
||||
class CUIItemInfo : public CUIListItem {};
|
||||
class CUIMonsterInfo : public CUIListItem {};
|
||||
class CUIQuestInfo : public CUIListItem {};
|
||||
class CUITabInfo : public CUIListItem {};
|
||||
class CItemData {};
|
||||
class CMonsterData {};
|
||||
class CQuestInfo {};
|
||||
}
|
||||
|
||||
namespace Guide_Intro {
|
||||
struct Contents {};
|
||||
}
|
||||
|
||||
template <class T> class CUIListBox : public CUIControl {
|
||||
public:
|
||||
// OFFSET: 0x009D3FD0
|
||||
// OFFSET: 0x009D4040
|
||||
// FUNCTION: fn_14037
|
||||
// FUNCTION: fn_14038
|
||||
void Resize(int width, int height) override {
|
||||
UIWindow::Resize(width, height);
|
||||
this->scrollBar->Resize(this->scrollBar->geometry.width, height);
|
||||
int total = 0;
|
||||
for (T* item : this->items) {
|
||||
total += item->geometry.height;
|
||||
}
|
||||
this->scrollBar->SetTotal(total);
|
||||
this->scrollBar->SetVisible(this->geometry.height);
|
||||
this->scrollBar->SetPosition(this->scrollBar->position);
|
||||
}
|
||||
|
||||
/* 0084 */ unsigned char unknown_0084[0x2C];
|
||||
/* 00B0 */ CUIVScrollBar* scrollBar;
|
||||
/* 00B4 */ unsigned char unknown_00B4[0x10];
|
||||
/* 00C4 */ std::list<T*> items;
|
||||
};
|
||||
|
||||
template <class T, class D> class CUIListBoxEx : public CUIControl {
|
||||
public:
|
||||
// OFFSET: 0x009D43D0
|
||||
// OFFSET: 0x009D45D0
|
||||
// OFFSET: 0x009D47D0
|
||||
// OFFSET: 0x009D49D0
|
||||
// FUNCTION: fn_14043
|
||||
// FUNCTION: fn_14044
|
||||
// FUNCTION: fn_14045
|
||||
// FUNCTION: fn_14046
|
||||
void OnScroll(int position) {
|
||||
auto it = this->items.begin();
|
||||
if (it == this->items.end()) {
|
||||
return;
|
||||
}
|
||||
if (this->data.size() == 0) {
|
||||
for (; it != this->items.end(); ++it) {
|
||||
(*it)->index = -1;
|
||||
(*it)->Show(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const int first = (*it)->index;
|
||||
unsigned int row = position / this->rowHeight;
|
||||
if (first != -1) {
|
||||
if (first < static_cast<int>(row)) {
|
||||
if (row - first < static_cast<unsigned int>(this->items.size())) {
|
||||
std::rotate(this->items.begin(), this->items.begin() + (row - first), this->items.end());
|
||||
}
|
||||
} else if (first > static_cast<int>(row)) {
|
||||
if (first - row < static_cast<unsigned int>(this->items.size())) {
|
||||
std::rotate(this->items.begin(), this->items.end() - (first - row), this->items.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it = this->items.begin();
|
||||
for (int y = this->itemY - position % this->rowHeight; y < this->geometry.height; y += this->rowHeight, ++it, ++row) {
|
||||
if (it == this->items.end() || row >= this->data.size()) {
|
||||
break;
|
||||
}
|
||||
T* item = *it;
|
||||
if (item) {
|
||||
if (this->rebind || row != static_cast<unsigned int>(item->index)) {
|
||||
item->index = row;
|
||||
if (this->binder) {
|
||||
auto node = this->data.begin();
|
||||
std::advance(node, static_cast<int>(row));
|
||||
this->binder(item, *node);
|
||||
}
|
||||
}
|
||||
item->SetSelected(row == this->selected);
|
||||
item->Move(this->itemX, y);
|
||||
item->Show(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (; it != this->items.end(); ++it) {
|
||||
(*it)->index = -1;
|
||||
(*it)->Show(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 0084 */ unsigned char unknown_0084[0x2C];
|
||||
/* 00B0 */ CUIVScrollBar* scrollBar;
|
||||
/* 00B4 */ int itemWidth;
|
||||
/* 00B8 */ int rowHeight;
|
||||
/* 00BC */ int itemX;
|
||||
/* 00C0 */ int itemY;
|
||||
/* 00C4 */ int unknown_00C4;
|
||||
/* 00C8 */ std::vector<T*> items;
|
||||
/* 00D4 */ std::list<D> data;
|
||||
/* 00DC */ unsigned int selected;
|
||||
/* 00E0 */ unsigned char unknown_00E0;
|
||||
/* 00E1 */ unsigned char rebind;
|
||||
/* 00E2 */ unsigned char unknown_00E2[0x2E];
|
||||
/* 0110 */ std::function<void(T*, const D&)> binder;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -4,6 +4,10 @@
|
|||
#include "Resource/ResourceMgr.h"
|
||||
#include "UI/Window/UIWindowMgr.h"
|
||||
#include "UI/Lists/UIScrollBar.h"
|
||||
#include "UI/Lists/UIChatHisBox.h"
|
||||
#include "UI/Lists/UIImgMenu.h"
|
||||
#include "UI/Lists/UIListBoxEx.h"
|
||||
#include "UI/Lists/UITabControl.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -315,3 +319,74 @@ void UIScrollBar::Configure(int x, int y, unsigned char vertical, int length) {
|
|||
this->Slot15(width, height);
|
||||
this->Slot22(width, height);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00880800
|
||||
// FUNCTION: fn_11279
|
||||
int UIListBoxEx::FindLine(const std::string& text) {
|
||||
const std::string key = text;
|
||||
auto it = this->lines.begin();
|
||||
for (; it != this->lines.end(); ++it) {
|
||||
if (key == it->second.text) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return it == this->lines.end() ? -1 : it->first;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00880920
|
||||
// FUNCTION: fn_11280
|
||||
int UIImgMenu::ItemAt(int x, int y) {
|
||||
const int width = this->geometry.width - 3;
|
||||
if (x < 1 || x >= width || y < 1) {
|
||||
return -1;
|
||||
}
|
||||
const int height = this->geometry.height - 3;
|
||||
if (y >= height) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int size;
|
||||
int offset;
|
||||
if (this->horizontal != 0) {
|
||||
size = width / this->count;
|
||||
this->itemWidth = size;
|
||||
offset = x;
|
||||
} else {
|
||||
size = height / this->count;
|
||||
this->itemHeight = size;
|
||||
offset = y;
|
||||
}
|
||||
return std::min(offset / size, this->count - 1);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00880B20
|
||||
// FUNCTION: fn_11283
|
||||
int UITabControl::TabCount() {
|
||||
return static_cast<int>(this->labels.size());
|
||||
}
|
||||
|
||||
// OFFSET: 0x00880B40
|
||||
// FUNCTION: fn_11284
|
||||
int UITabControl::TabAt(int x, int y) {
|
||||
int offset = x;
|
||||
if (this->layout == 0 || this->layout == 2) {
|
||||
offset = y;
|
||||
}
|
||||
const int count = this->TabCount();
|
||||
for (int index = 0; index < count; ++index) {
|
||||
offset -= this->widths[index];
|
||||
if (offset < 0) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00880BB0
|
||||
// FUNCTION: fn_11285
|
||||
const char* UIChatHisBox::HistoryText(unsigned int index) {
|
||||
if (index < this->history.size() && !this->history[index].empty()) {
|
||||
return this->history[index].c_str();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
21
Source/UI/Lists/UITabControl.h
Normal file
21
Source/UI/Lists/UITabControl.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_LISTS_UITABCONTROL_H
|
||||
#define RAGNAROK_SOURCE_UI_LISTS_UITABCONTROL_H
|
||||
|
||||
#include "UI/Window/UIWindow.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class UITabControl : public UIWindow {
|
||||
public:
|
||||
int TabCount();
|
||||
int TabAt(int x, int y);
|
||||
|
||||
/* 0080 */ int layout;
|
||||
/* 0084 */ unsigned char unknown_0084[0x30];
|
||||
/* 00B4 */ std::vector<std::string> labels;
|
||||
/* 00C0 */ unsigned char unknown_00C0[0xC];
|
||||
/* 00CC */ std::vector<int> widths;
|
||||
};
|
||||
|
||||
#endif
|
||||
37
Source/UI/Lists/UIVScrollBar.h
Normal file
37
Source/UI/Lists/UIVScrollBar.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_LISTS_UIVSCROLLBAR_H
|
||||
#define RAGNAROK_SOURCE_UI_LISTS_UIVSCROLLBAR_H
|
||||
|
||||
#include "UI/Window/UIControl.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
class CUIVScrollBar : public CUIControl {
|
||||
public:
|
||||
virtual void Slot54();
|
||||
|
||||
void SetTotal(int value);
|
||||
void SetVisible(int value);
|
||||
void SetPosition(int value);
|
||||
|
||||
/* 0084 */ UIWindow* upButton;
|
||||
/* 0088 */ CUIControl* thumb;
|
||||
/* 008C */ int unknown_008C;
|
||||
/* 0090 */ int total;
|
||||
/* 0094 */ int visible;
|
||||
/* 0098 */ int unknown_0098;
|
||||
/* 009C */ int position;
|
||||
/* 00A0 */ int maximum;
|
||||
/* 00A4 */ int trackLength;
|
||||
/* 00A8 */ unsigned char dragging;
|
||||
/* 00A9 */ unsigned char unknown_00A9[0x1F];
|
||||
/* 00C8 */ std::function<void(int)> onChange;
|
||||
};
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
static_assert(offsetof(CUIVScrollBar, total) == 0x90);
|
||||
static_assert(offsetof(CUIVScrollBar, dragging) == 0xA8);
|
||||
static_assert(offsetof(CUIVScrollBar, onChange) == 0xC8);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,4 +1,11 @@
|
|||
#include "Client/Session.h"
|
||||
#include "Resource/Bitmap/BitmapResource.h"
|
||||
#include "Resource/ResourceMgr.h"
|
||||
#include "Resource/SkinPalette.h"
|
||||
#include "Resource/TextureNames.h"
|
||||
#include "UI/Buttons/UIButton.h"
|
||||
#include "UI/Window/UIRebirthWnd.h"
|
||||
#include "UI/Window/UISeekPartyMBWnd.h"
|
||||
#include "UI/Shortcuts/ShortcutCooldowns.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
|
@ -204,3 +211,32 @@ void ShortcutCooldowns::Paint(
|
|||
++entry;
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x0092DDE0
|
||||
// FUNCTION: fn_12673
|
||||
void UIRebirthWnd::Paint() {
|
||||
auto* background = static_cast<CBitmapRes*>(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\win_msgbox1.bmp")));
|
||||
this->DrawBitmap(0, 0, &background->image, false);
|
||||
}
|
||||
|
||||
// OFFSET: 0x0092E230
|
||||
// FUNCTION: fn_12676
|
||||
void UISeekPartyMBWnd::Paint() {
|
||||
auto& controls = *this->m_controls;
|
||||
this->DrawTitleBar(controls.fonts, controls.locale, true, "", 0);
|
||||
if (this->m_minimized) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned red;
|
||||
unsigned green;
|
||||
unsigned blue;
|
||||
SkinPaletteChannels(ResourceMgr::Instance(), 2, 2, red, green, blue);
|
||||
this->FillRegion(0, 17, this->geometry.width, this->geometry.height - 38, RGB(red, green, blue));
|
||||
|
||||
const RECT outer = {50, 95, 310, 293};
|
||||
const RECT inner = {51, 96, 309, 292};
|
||||
this->FillSurface(0, &outer);
|
||||
this->FillSurface(0xF0F0F0, &inner);
|
||||
this->DrawButtonBar(2, 0, 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,18 +15,29 @@
|
|||
#include "UI/Shortcuts/ShortcutVisibility.h"
|
||||
#include "UI/Shortcuts/UIShortCutWnd.h"
|
||||
#include "UI/Chat/UINewChatWnd.h"
|
||||
#include "UI/Chat/UISubChatMiniWnd.h"
|
||||
#include "UI/Dialogs/UIMemorialDunWnd.h"
|
||||
#include "UI/Buttons/UIBitmapButton.h"
|
||||
#include "UI/Buttons/UIButton.h"
|
||||
#include "UI/Buttons/UICheckBox.h"
|
||||
#include "UI/Layout/WindowSnapping.h"
|
||||
#include "UI/Window/UIWindow.h"
|
||||
#include "UI/Window/UIWindowMgr.h"
|
||||
#include "UI/Window/UIWindowCallBtnWnd.h"
|
||||
#include "UI/Window/WindowManagerWindows.h"
|
||||
#include "Render/Renderer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace {}
|
||||
|
||||
// GLOBAL: gl_24737
|
||||
int g_memorialDunWndX;
|
||||
|
||||
// GLOBAL: gl_24738
|
||||
int g_memorialDunWndY;
|
||||
|
||||
// OFFSET: 0x009122B0
|
||||
// FUNCTION: fn_12528
|
||||
UIShortCutWnd::UIShortCutWnd(UIWindowContext& windows, UIFrameContext& frames, ShortcutWindowContext& shortcuts)
|
||||
|
|
@ -429,3 +440,62 @@ void UINewChatWnd::Move(int x, int y) {
|
|||
window->SendMsg(this, 6, 197, this->geometry.x + x, this->geometry.y + y, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x0093D090
|
||||
// FUNCTION: fn_12765
|
||||
void UINewChatWnd::Show(int visible) {
|
||||
this->geometry.visible = visible;
|
||||
|
||||
if (visible != 0) {
|
||||
this->Invalidate();
|
||||
this->m_frameContext->snapping.Store(this);
|
||||
} else if (this->m_frameContext->snapping.enabled) {
|
||||
this->m_frameContext->snapping.rectangles.erase(this);
|
||||
}
|
||||
|
||||
for (UIWindow* tab : this->m_tabs) {
|
||||
tab->Show(this->geometry.visible);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < g_windowMgr.retainedWindows.size(); ++i) {
|
||||
g_windowMgr.retainedWindows[i]->Show(this->geometry.visible);
|
||||
}
|
||||
}
|
||||
// OFFSET: 0x0091E960
|
||||
// FUNCTION: fn_12630
|
||||
void UIMemorialDunWnd::Move(int x, int y) {
|
||||
const int left = x <= g_renderer->viewport.width - this->geometry.width ? x : 0;
|
||||
const int top = y <= g_renderer->viewport.height - this->geometry.height ? y : 310;
|
||||
this->UIFrameWnd::Move(left, top);
|
||||
|
||||
if (g_memorialDunWndX != left) {
|
||||
g_memorialDunWndX = left;
|
||||
}
|
||||
if (g_memorialDunWndY != top) {
|
||||
g_memorialDunWndY = top;
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x0093CA50
|
||||
// FUNCTION: fn_12762
|
||||
int UISubChatMiniWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) {
|
||||
if (message != 6) {
|
||||
return this->UIFrameWnd::SendMsg(sender, message, a, b, c, d);
|
||||
}
|
||||
|
||||
if (a == 197) {
|
||||
this->Move(b, c - this->m_offsetY);
|
||||
} else if (a == 202) {
|
||||
this->Slot25(this->m_rowHeight * b + 1, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0093CAB0
|
||||
// FUNCTION: fn_12763
|
||||
int UIWindowCallBtnWnd::SendMsg(UIWindow*, int message, std::intptr_t a, std::intptr_t, std::intptr_t, std::intptr_t) {
|
||||
if (message == 6) {
|
||||
this->m_frameContext->windows.EnsureWindow(a);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
34
Source/UI/UIBarGraph.h
Normal file
34
Source/UI/UIBarGraph.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_UIBARGRAPH_H
|
||||
#define RAGNAROK_SOURCE_UI_UIBARGRAPH_H
|
||||
|
||||
#include "UI/Window/UIWindow.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct UIButtonContext;
|
||||
|
||||
class UIBarGraph3 : public UIWindow {
|
||||
};
|
||||
|
||||
class UIBarGraph4 : public UIBarGraph3 {
|
||||
public:
|
||||
void Slot28(int x, int y) override;
|
||||
|
||||
protected:
|
||||
/* 007C */ const int* m_current;
|
||||
/* 0080 */ const int* m_maximum;
|
||||
UIButtonContext* m_controls;
|
||||
};
|
||||
|
||||
class UIINT64BarGraph : public UIWindow {
|
||||
public:
|
||||
void Slot28(int x, int y) override;
|
||||
|
||||
protected:
|
||||
/* 007C */ int unknown_007C;
|
||||
/* 0080 */ std::int64_t m_current;
|
||||
/* 0088 */ std::int64_t m_maximum;
|
||||
UIButtonContext* m_controls;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -81,3 +81,9 @@ void UILapineScrollBar::Paint() {
|
|||
this->minimumThumb = 0;
|
||||
this->parent->Invalidate();
|
||||
}
|
||||
|
||||
// OFFSET: 0x00600260
|
||||
// FUNCTION: fn_04157
|
||||
void UILapineBox_IngredientListWnd::Paint() {
|
||||
this->ClearSurface(0xFFF7F7);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,4 +8,12 @@ public:
|
|||
void Paint() override;
|
||||
};
|
||||
|
||||
class UIScrollWnd : public UIWindow {
|
||||
};
|
||||
|
||||
class UILapineBox_IngredientListWnd : public UIScrollWnd {
|
||||
public:
|
||||
void Paint() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "UI/Window/UIControl.h"
|
||||
#include "UI/Lists/UIListBoxTemplate.h"
|
||||
#include "Resource/Bitmap/BitmapResource.h"
|
||||
#include "Resource/ResourceMgr.h"
|
||||
#include "Resource/TextureNames.h"
|
||||
|
|
@ -150,3 +151,80 @@ void CUIControl::Slot52(int value) {
|
|||
// FUNCTION: fn_14036
|
||||
void CUIControl::Slot53(int) {
|
||||
}
|
||||
|
||||
// OFFSET: 0x009F2B70
|
||||
// FUNCTION: fn_14726
|
||||
void CUIVScrollBar::SetTotal(int value) {
|
||||
const int count = value > 1 ? value : 1;
|
||||
this->total = count;
|
||||
const int shown = this->visible <= count ? this->visible : count;
|
||||
this->visible = shown;
|
||||
this->maximum = count - shown;
|
||||
this->Invalidate();
|
||||
}
|
||||
|
||||
// OFFSET: 0x009F2E80
|
||||
// FUNCTION: fn_14732
|
||||
void CUIVScrollBar::SetVisible(int value) {
|
||||
const int count = this->total;
|
||||
const int shown = count < value ? count : value;
|
||||
this->visible = shown;
|
||||
this->maximum = count - shown;
|
||||
this->Invalidate();
|
||||
}
|
||||
|
||||
// OFFSET: 0x009F2530
|
||||
// FUNCTION: fn_14716
|
||||
void CUIVScrollBar::SetPosition(int value) {
|
||||
int zero = 0;
|
||||
const int* clamped = &this->maximum;
|
||||
if (value <= this->maximum) {
|
||||
clamped = value >= 0 ? &value : &zero;
|
||||
}
|
||||
if (!this->dragging) {
|
||||
this->position = *clamped;
|
||||
}
|
||||
this->Show(this->total > this->visible);
|
||||
this->Slot54();
|
||||
if (this->onChange) {
|
||||
this->onChange(this->position);
|
||||
}
|
||||
this->Invalidate();
|
||||
}
|
||||
|
||||
// OFFSET: 0x009F25C0
|
||||
// FUNCTION: fn_14717
|
||||
void CUIVScrollBar::Slot54() {
|
||||
CUIControl* bar = this->thumb;
|
||||
float offset;
|
||||
if (bar->hitEnabled) {
|
||||
const int length = static_cast<int>((static_cast<float>(this->visible) / static_cast<float>(this->total)) * static_cast<float>(this->trackLength));
|
||||
bar->Resize(this->geometry.width, length > 1 ? length : 1);
|
||||
offset = (static_cast<float>(this->trackLength) / static_cast<float>(this->total)) * static_cast<float>(this->position);
|
||||
} else {
|
||||
if (this->total - this->visible <= 0) {
|
||||
bar->Move(0, this->upButton->geometry.height);
|
||||
return;
|
||||
}
|
||||
offset = static_cast<float>(this->position * (this->trackLength - bar->geometry.height)) / static_cast<float>(this->total - this->visible);
|
||||
}
|
||||
this->thumb->Move(0, static_cast<int>(offset + static_cast<float>(this->upButton->geometry.height)));
|
||||
}
|
||||
|
||||
// OFFSET: 0x009F0290
|
||||
// FUNCTION: fn_14661
|
||||
void CUIListItem::SetSelected(bool selected) {
|
||||
if (this->selected != selected) {
|
||||
this->selected = selected;
|
||||
if (!this->frozen) {
|
||||
this->Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void CUIListBox<AdventureGuide::CUITab>::Resize(int, int);
|
||||
template void CUIListBox<AdventureGuide::CUISubTab>::Resize(int, int);
|
||||
template void CUIListBoxEx<AdventureGuide::CUITabInfo, Guide_Intro::Contents>::OnScroll(int);
|
||||
template void CUIListBoxEx<AdventureGuide::CUIQuestInfo, AdventureGuide::CQuestInfo>::OnScroll(int);
|
||||
template void CUIListBoxEx<AdventureGuide::CUIMonsterInfo, AdventureGuide::CMonsterData>::OnScroll(int);
|
||||
template void CUIListBoxEx<AdventureGuide::CUIItemInfo, AdventureGuide::CItemData>::OnScroll(int);
|
||||
|
|
|
|||
11
Source/UI/Window/UIRebirthWnd.h
Normal file
11
Source/UI/Window/UIRebirthWnd.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_WINDOW_UIREBIRTHWND_H
|
||||
#define RAGNAROK_SOURCE_UI_WINDOW_UIREBIRTHWND_H
|
||||
|
||||
#include "UI/Window/UIFrameWnd.h"
|
||||
|
||||
class UIRebirthWnd : public UIFrameWnd {
|
||||
public:
|
||||
void Paint() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
18
Source/UI/Window/UISeekPartyMBWnd.h
Normal file
18
Source/UI/Window/UISeekPartyMBWnd.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_WINDOW_UISEEKPARTYMBWND_H
|
||||
#define RAGNAROK_SOURCE_UI_WINDOW_UISEEKPARTYMBWND_H
|
||||
|
||||
#include "UI/Window/UIFrameWnd.h"
|
||||
|
||||
struct UIButtonContext;
|
||||
|
||||
class UISeekPartyMBWnd : public UIFrameWnd {
|
||||
public:
|
||||
void Paint() override;
|
||||
|
||||
protected:
|
||||
/* 00BC */ unsigned char unknown_00BC[0xAC];
|
||||
/* 0168 */ unsigned char m_minimized;
|
||||
UIButtonContext* m_controls;
|
||||
};
|
||||
|
||||
#endif
|
||||
11
Source/UI/Window/UIWindowCallBtnWnd.h
Normal file
11
Source/UI/Window/UIWindowCallBtnWnd.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef RAGNAROK_SOURCE_UI_WINDOW_UIWINDOWCALLBTNWND_H
|
||||
#define RAGNAROK_SOURCE_UI_WINDOW_UIWINDOWCALLBTNWND_H
|
||||
|
||||
#include "UI/Window/UIFrameWnd.h"
|
||||
|
||||
class UIWindowCallBtnWnd : public UIFrameWnd {
|
||||
public:
|
||||
int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -7,7 +7,9 @@
|
|||
|
||||
class Timestamp {
|
||||
public:
|
||||
Timestamp(__time32_t value);
|
||||
~Timestamp();
|
||||
void Set(__time32_t value);
|
||||
TIMESTAMP_STRUCT ToSqlTimestamp();
|
||||
int IsBefore(__time32_t other) const;
|
||||
int IsBeforeNow() const;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue