356 lines
12 KiB
C++
356 lines
12 KiB
C++
#include "Client/Input/TextInputBuffer.h"
|
|
#include "Contents/Party/AdventurerAgencyMgr.h"
|
|
#include "Contents/Party/AgencyRequestContext.h"
|
|
#include "Contents/ForbiddenWords.h"
|
|
#include "Contents/Party/RegisterPartyAsyncWork.h"
|
|
#include "Render/DeviceContext/DeviceContext.h"
|
|
#include "Render/Text/TextContext.h"
|
|
#include "Resource/Bitmap/BitmapResource.h"
|
|
#include "Resource/ResourceFailures.h"
|
|
#include "Resource/ResourceMgr.h"
|
|
#include "UI/Window/InputFocus.h"
|
|
#include "UI/Text/TextFitting.h"
|
|
#include "UI/Text/TextWrapping.h"
|
|
#include "UI/Buttons/UIBasicButton.h"
|
|
#include "UI/Buttons/UIBitmapButton.h"
|
|
#include "UI/Lists/UIComboBoxDefWnd.h"
|
|
#include "UI/Edit/UIEditCtrl.h"
|
|
#include "UI/Buttons/UIJobSlotButton.h"
|
|
#include "UI/Party/UIRegisterPartyWnd.h"
|
|
#include "UI/Text/UIStaticText.h"
|
|
#include "UI/Window/WindowManagerWindows.h"
|
|
|
|
#include <algorithm>
|
|
#include <cctype>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
|
|
namespace {
|
|
constexpr char prefix[] = "유저인터페이스\\";
|
|
|
|
// OFFSET: 0x007BBFC0
|
|
// FUNCTION: fn_09295
|
|
bool Digits(std::string text) {
|
|
if (text.empty()) {
|
|
return false;
|
|
}
|
|
|
|
for (char value : text) {
|
|
if (!std::isdigit(value)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x007BAF30
|
|
// FUNCTION: fn_09278
|
|
UIRegisterPartyWnd::UIRegisterPartyWnd(UIWindowContext& windows, UIFrameContext& frames, UIRegisterPartyContext& registration)
|
|
: UIFrameWnd(windows, frames, 0), selectedType(0), m_registration(®istration) {
|
|
}
|
|
|
|
// OFFSET: 0x007BB810
|
|
UIRegisterPartyWnd::~UIRegisterPartyWnd() = default;
|
|
|
|
// OFFSET: 0x007C2440
|
|
// FUNCTION: fn_09326
|
|
void UIRegisterPartyWnd::Slot11() {
|
|
if (this->saved) {
|
|
this->saved->width = this->geometry.width;
|
|
this->saved->height = this->geometry.height;
|
|
this->saved->x = this->geometry.x;
|
|
this->saved->y = this->geometry.y;
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x007BDD10
|
|
// FUNCTION: fn_09300
|
|
void UIRegisterPartyWnd::Slot15(int, int) {
|
|
auto& owner = *this->m_registration;
|
|
auto& controls = owner.buttons;
|
|
|
|
const auto label = [&](const char* text, int x, int y, int width) {
|
|
auto* value = new UIStaticText(*this->m_context, controls);
|
|
value->SetSize(width, 15);
|
|
value->Move(x, y);
|
|
value->SetText(text, 0);
|
|
value->red = 0;
|
|
value->green = 0;
|
|
value->blue = 0;
|
|
this->AddChild(value);
|
|
|
|
return value;
|
|
};
|
|
label(controls.services.MessageText(3415), 10, 23, 40);
|
|
this->character = label(owner.characterName.c_str(), 60, 23, 119);
|
|
this->character->text = FitText(*this->character->geometry.surface, controls.fonts, controls.locale, owner.characterName, 119);
|
|
this->character->tooltipEnabled = this->character->text != owner.characterName;
|
|
label(controls.services.MessageText(408), 10, 49, 40);
|
|
const int level = owner.playerLevel;
|
|
|
|
const auto edit = [&](int x, int value) {
|
|
auto* control = new UIEditCtrl(*this->m_context, owner.edits);
|
|
control->SetSize(25, 16);
|
|
control->Move(x, 47);
|
|
control->invalidatesParent = 1;
|
|
control->maximum = 3;
|
|
control->Background(232, 232, 232);
|
|
char number[10] = {};
|
|
_snprintf_s(number, sizeof(number), _TRUNCATE, "%d", value);
|
|
control->SetText(number);
|
|
this->AddChild(control);
|
|
|
|
return control;
|
|
};
|
|
this->minimum = edit(60, std::max((level - 5), 1));
|
|
this->maximum = edit(96, (level + 5));
|
|
label(controls.services.MessageText(3369), 10, 73, this->geometry.width);
|
|
auto* roleLabel = label(controls.services.MessageText(504), 10, 97, this->geometry.width);
|
|
roleLabel->outline = 1;
|
|
const char* roles[] = {"def", "heal", "atk", "buf"};
|
|
const int tooltips[] = {3420, 3491, 3444, 3508};
|
|
|
|
for (int index = 0; index < 4; ++index) {
|
|
auto* job = new UIJobSlotButton(*this->m_context, controls);
|
|
this->jobs[index] = job;
|
|
job->SetSize(16, 16);
|
|
job->Move(60 + index * 18, 95);
|
|
job->selectedImage = std::string(prefix) + "UIadventurerAgency\\btn_job_" + roles[index] + "_on.bmp";
|
|
job->unselectedImage = std::string(prefix) + "UIadventurerAgency\\btn_job_" + roles[index] + "_off.bmp";
|
|
job->SetSelected(1);
|
|
job->SetTooltip(controls.services.MessageText(tooltips[index]));
|
|
this->AddChild(job);
|
|
}
|
|
|
|
label(controls.services.MessageText(3359), 10, 121, this->geometry.width - 32);
|
|
this->memo = new UIEditCtrl(*this->m_context, owner.edits);
|
|
this->memo->SetSize(139, 14);
|
|
this->memo->maximum = 24;
|
|
this->memo->TextColor(0, 0xFFFFFFFFu);
|
|
this->memo->Move(60, 119);
|
|
this->memo->Background(232, 232, 232);
|
|
this->AddChild(this->memo);
|
|
|
|
auto* submit = new UIBasicButton(*this->m_context, controls);
|
|
const bool registered = g_adventurerAgencyMgr->registered;
|
|
const char* title = controls.services.MessageText(registered ? 3376 : 3371);
|
|
submit->Configure(this->TextWidth(controls.fonts, controls.locale, title, 0, 0, 12, 0, 0) + 10, title);
|
|
submit->Move(108, 165);
|
|
submit->SetId(registered ? 564 : 565);
|
|
|
|
if (registered) {
|
|
this->change = submit;
|
|
} else {
|
|
this->recruit = submit;
|
|
}
|
|
|
|
this->m_message0 = registered ? 564 : 565;
|
|
this->AddChild(submit);
|
|
std::vector<std::string> lines;
|
|
WrapPlainText(controls.services.MessageText(3370), lines, 40, owner.codePage, controls.locale.inlineCharset);
|
|
int y = 136;
|
|
|
|
for (const auto& line : lines) {
|
|
auto* value = label(line.c_str(), 9, y, this->geometry.width - 18);
|
|
value->fontHeight = 11;
|
|
value->red = 255;
|
|
y += 12;
|
|
}
|
|
|
|
auto* close = new UIBitmapButton(*this->m_context, controls);
|
|
const char* suffixes[] = {"", "_a", "_b"};
|
|
|
|
for (int state = 0; state < 3; ++state) {
|
|
const std::string path = std::string(prefix) + "basic_interface\\btn_close" + suffixes[state] + ".bmp";
|
|
close->SetBitmap(path.c_str(), state, 0);
|
|
}
|
|
|
|
close->SetSize(close->BitmapWidth(), close->BitmapHeight());
|
|
close->Move(173, 165);
|
|
close->SetId(201);
|
|
this->AddChild(close);
|
|
|
|
this->types = new UIComboBoxDef2Wnd(*this->m_context, owner.combos);
|
|
this->types->dropdownHeight = 126;
|
|
this->types->SetSize(63, 18);
|
|
this->types->Move(60, 70);
|
|
this->AddChild(this->types);
|
|
this->types->AddOption(controls.services.MessageText(3377), 0);
|
|
|
|
for (int id = 3360; id <= 3365; ++id) {
|
|
this->types->AddOption(controls.services.MessageText(id), 0);
|
|
}
|
|
|
|
this->types->Select(0);
|
|
auto* titleClose = new UIBitmapButton(*this->m_context, controls);
|
|
const std::string off = std::string(prefix) + "basic_interface\\big_sys_close_off.bmp";
|
|
const std::string on = std::string(prefix) + "basic_interface\\big_sys_close_on.bmp";
|
|
titleClose->SetBitmap(off.c_str(), 0, 0);
|
|
titleClose->SetBitmap(on.c_str(), 1, 0);
|
|
titleClose->SetBitmap(on.c_str(), 2, 0);
|
|
titleClose->SetSize(titleClose->BitmapWidth(), titleClose->BitmapHeight());
|
|
titleClose->Move(this->geometry.width - titleClose->BitmapWidth(), 0);
|
|
titleClose->SetId(201);
|
|
titleClose->SetTooltip("");
|
|
this->AddChild(titleClose);
|
|
}
|
|
|
|
// OFFSET: 0x007C1FB0
|
|
// FUNCTION: fn_09321
|
|
void UIRegisterPartyWnd::SetInfo(CAdvenPartyInfo value) {
|
|
this->jobs[0]->SetSelected(value.tanker);
|
|
this->jobs[1]->SetSelected(value.healer);
|
|
this->jobs[2]->SetSelected(value.dealer);
|
|
this->jobs[3]->SetSelected(value.assist);
|
|
char number[10] = {};
|
|
_snprintf_s(number, sizeof(number), _TRUNCATE, "%d", value.minimumLevel);
|
|
this->minimum->SetText(number);
|
|
_snprintf_s(number, sizeof(number), _TRUNCATE, "%d", value.maximumLevel);
|
|
this->maximum->SetText(number);
|
|
this->selectedType = value.type;
|
|
this->types->Select(value.type);
|
|
this->memo->SetText(value.memo.c_str());
|
|
this->character->SetText(value.characterName.c_str(), 0);
|
|
this->Invalidate();
|
|
}
|
|
|
|
// INLINED
|
|
const char* UIRegisterPartyWnd::Text(UIEditCtrl& control) const {
|
|
const auto& edit = this->m_registration->edits;
|
|
return edit.focus.window == &control ? edit.input.text.c_str() : control.text.c_str();
|
|
}
|
|
|
|
// OFFSET: 0x007BBA80
|
|
// FUNCTION: fn_09290
|
|
void UIRegisterPartyWnd::NormalizeLevels() {
|
|
const int level = this->m_registration->playerLevel;
|
|
char number[10] = {};
|
|
|
|
if (!Digits(this->Text(*this->minimum))) {
|
|
_snprintf_s(number, sizeof(number), _TRUNCATE, "%d", std::max((level - 5), 1));
|
|
this->minimum->SetText(number);
|
|
}
|
|
|
|
if (!Digits(this->Text(*this->maximum))) {
|
|
_snprintf_s(number, sizeof(number), _TRUNCATE, "%d", (level + 5));
|
|
this->maximum->SetText(number);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x007BFBB0
|
|
// FUNCTION: fn_09305
|
|
void UIRegisterPartyWnd::Paint() {
|
|
auto& controls = this->m_registration->buttons;
|
|
this->geometry.surface->Fill(nullptr, 0xFFFF00FFu);
|
|
const auto load = [&](const char* name) { return static_cast<CBitmapRes*>(controls.resources.Load((std::string(prefix) + name).c_str())); };
|
|
const auto* background = load("UIadventurerAgency\\bg_agency_register.bmp");
|
|
this->DrawBitmap(0, 0, background ? &background->image : nullptr, false);
|
|
this->DrawTextAt(controls.fonts, controls.locale, 86, 50, "~", 0, 0, 12, 0, 0, 0);
|
|
int leftWidth = 0;
|
|
int rightWidth = 0;
|
|
int titleHeight = 0;
|
|
|
|
if (const auto* left = load("basic_interface\\titlebar_left.bmp")) {
|
|
this->DrawBitmap(0, 0, &left->image, false);
|
|
leftWidth = left->image.width;
|
|
}
|
|
|
|
if (const auto* right = load("basic_interface\\titlebar_right.bmp")) {
|
|
rightWidth = right->image.width;
|
|
this->DrawBitmap(this->geometry.width - rightWidth, 0, &right->image, false);
|
|
}
|
|
|
|
if (const auto* middle = load("basic_interface\\titlebar_mid.bmp")) {
|
|
titleHeight = middle->image.height;
|
|
const int extent = this->geometry.width - rightWidth - leftWidth;
|
|
const int tiles = extent / middle->image.width + (extent % middle->image.width != 0);
|
|
|
|
for (int index = 0; index < tiles; ++index) {
|
|
this->DrawBitmap(leftWidth, 0, &middle->image, false);
|
|
leftWidth += middle->image.width;
|
|
}
|
|
}
|
|
|
|
const char* caption = controls.services.MessageText(3356);
|
|
this->DrawTextAt(controls.fonts, controls.locale, 19, titleHeight - 13, caption, 0, 0, 12, 0xFFFFFF, 0, 0);
|
|
this->DrawTextAt(controls.fonts, controls.locale, 18, titleHeight - 14, caption, 0, 0, 12, 0, 0, 0);
|
|
const auto* base = load("basic_interface\\sys_base_off.bmp");
|
|
this->DrawBitmap(3, 3, base ? &base->image : nullptr, true);
|
|
}
|
|
|
|
// OFFSET: 0x007C1410
|
|
// FUNCTION: fn_09314
|
|
int UIRegisterPartyWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) {
|
|
auto& owner = *this->m_registration;
|
|
|
|
if (message == 6) {
|
|
const int value = static_cast<int>(a);
|
|
|
|
if (value != 201) {
|
|
if (value != 564 && value != 565) {
|
|
return 0;
|
|
}
|
|
|
|
const auto notify = [&](int id) {
|
|
char text[256] = {};
|
|
_snprintf_s(text, sizeof(text), _TRUNCATE, owner.buttons.services.MessageText(id));
|
|
owner.completion.messages.Message(text, 0xFF);
|
|
};
|
|
|
|
if (owner.partyMember != 0) {
|
|
if (owner.forbidden.Contains(this->Text(*this->memo))) {
|
|
notify(3372);
|
|
return 0;
|
|
}
|
|
|
|
this->NormalizeLevels();
|
|
|
|
if (std::atoi(this->Text(*this->minimum)) > std::atoi(this->Text(*this->maximum))) {
|
|
notify(3516);
|
|
return 0;
|
|
}
|
|
|
|
CAdvenPartyInfo info;
|
|
info.tanker = this->jobs[0]->selected;
|
|
info.healer = this->jobs[1]->selected;
|
|
info.dealer = this->jobs[2]->selected;
|
|
info.assist = this->jobs[3]->selected;
|
|
info.minimumLevel = std::atoi(this->Text(*this->minimum));
|
|
info.maximumLevel = std::atoi(this->Text(*this->maximum));
|
|
info.type = this->selectedType;
|
|
info.memo = this->Text(*this->memo);
|
|
info.characterName = owner.characterName;
|
|
g_adventurerAgencyMgr->RequestRegistration(info, owner.requests, owner.completion);
|
|
} else {
|
|
notify(3506);
|
|
}
|
|
}
|
|
|
|
owner.requests.windows.CloseWindow(323);
|
|
return 0;
|
|
}
|
|
|
|
if (message == 34) {
|
|
this->saved = reinterpret_cast<PartyBoardPlacement*>(a);
|
|
|
|
if (this->saved->width <= 0 || this->saved->height <= 0 || this->saved->x < 0 || this->saved->x > owner.screenWidth - this->saved->width ||
|
|
this->saved->y < 0 || this->saved->y > owner.screenHeight - this->saved->height) {
|
|
*this->saved = {200, 200, 220, 197};
|
|
}
|
|
|
|
this->Move(this->saved->x, this->saved->y);
|
|
return 0;
|
|
}
|
|
|
|
if (message == 39) {
|
|
if (sender == this->types) {
|
|
this->selectedType = static_cast<int>(a);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return this->UIFrameWnd::SendMsg(sender, message, a, b, c, d);
|
|
}
|