-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement in game command list #222
base: master
Are you sure you want to change the base?
Conversation
src/engine/N3Base/N3UIList.h
Outdated
@@ -28,6 +28,7 @@ class CN3UIList : public CN3UIBase { | |||
D3DCOLOR FontColor() { return m_crFont; } | |||
BOOL FontIsBold() { return m_bFontBold; } | |||
BOOL FontIsItalic() { return m_bFontItalic; } | |||
CN3UIString * GetChildStrFromList(std::string str); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should ideally be a const reference, since we have no reason to copy or change the string, i.e.:
const std::string & str
@@ -231,6 +233,8 @@ class CGameProcMain : public CGameProcedure { | |||
bool CommandToggleMoveContinous(); | |||
bool CommandToggleWalkRun(); | |||
bool CommandToggleUISkillTree(); | |||
bool CommandToggleCmdList(); | |||
bool OpenCmdEdit(std::string msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also ideally be a const reference, i.e.:
const std::string & msg
src/game/UICmdEdit.h
Outdated
|
||
////////////////////////////////////////////////////////////////////// | ||
|
||
class CUICmdEditDlg : public CN3UIBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Officially the class name is simply named CUICmdEdit
, I assume based on the leftover comments in the source file, you originally created it with the 'Dlg' suffix and then renamed it without renaming the class itself.
I don't know if this project intends to keep official class names for things like this, but if so, this should be renamed CUICmdEdit
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we keep the same official names. 100% with you @twostars.
src/game/UICmdList.h
Outdated
|
||
////////////////////////////////////////////////////////////////////// | ||
|
||
class CUICmdListDlg : public CN3UIBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As with the other UI class, officially the class name is simply named CUICmdList
.
I don't know if this project intends to keep official class names for things like this, but if so, this should be renamed CUICmdList
.
|
||
class CUICmdListDlg : public CN3UIBase { | ||
bool m_bDestoyDlgAlive; | ||
class CUICmdEdit * m_pUICmdEdit; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In its current state this forward declaration is wrong. You named it CUICmdEditDlg
(which is unofficial), so if that's the name you're sticking with, it should be forward declared as such as well.
If that gets changed though, of course it's fine to leave.
src/game/UICmdList.cpp
Outdated
std::string command; | ||
m_pList_Cmds->GetString(cmdSel, command); | ||
|
||
if (command == "PM") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a couple of issues with doing this like this.
For one, you have the command names defined in the TBL, but then you're explicitly checking (and case-sensitive at that) it against "PM" here.
For another, it's not the only command which officially shows this prompt.
It would be saner to translate this back to either the command type from the enum, or alternatively the resource ID. Officially they do the former.
src/engine/N3Base/N3UIList.cpp
Outdated
@@ -195,6 +195,17 @@ bool CN3UIList::SetString(int iIndex, const std::string & szString) { | |||
return false; | |||
} | |||
|
|||
CN3UIString * CN3UIList::GetChildStrFromList(std::string str) { | |||
for (std::list<CN3UIString *>::iterator it = m_ListString.begin(); it != m_ListString.end(); ++it) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is fine, and this is just a nitpick really, but this is a perfect use of auto
, to not have to deal with the tedious templated type names, e.g.:
for (auto it = m_ListString.begin(); it != m_ListString.end(); ++it) {
I should also note that the preferable modern way to handle a loop like this is with their new for each loop syntax, e.g.:
for (CN3UIString* pString : m_ListString) {
Although in this particular case I don't know what this project is intending to support, since this is a newer language feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with @twostars here. The existing instances ideally we won't refactor in the same PR, just to make the PR with isolated changes, but when adding stuff, let's try and stick to modern C++.
src/game/UICmdList.cpp
Outdated
for (int i = 0; i < 8; i++) { | ||
::_LoadStringFromResource(i + 7800, szCategory); //load command categories | ||
|
||
if (CGameBase::s_pPlayer->m_InfoBase.iAuthority == 0 && szCategory == "GM") { // if not gm hide this category |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is another case of relying on the content of the TBLs. Ideally it should be using an enum or some other language-agnostic indicator, that isn't explicitly relying on the contents of the TBL.
src/game/UICmdList.h
Outdated
std::map<uint16_t, std::string> m_mapCmds; | ||
|
||
public: | ||
void SetVisible(bool bVisible); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is virtual but doesn't indicate it as such. Ideally it should be using override
(rather than redefining it as virtual
to enforce the overridden virtual method (that way it can error if it's defined incorrectly).
i.e.
void SetVisible(bool bVisible) override;
src/game/UICmdList.h
Outdated
public: | ||
void SetVisible(bool bVisible); | ||
|
||
bool OnKeyPress(int iKey); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is virtual but doesn't indicate it as such. Ideally it should be using override
(rather than redefining it as virtual
to enforce the overridden virtual method (that way it can error if it's defined incorrectly).
i.e.
bool OnKeyPress(int iKey) override;
src/game/UICmdList.h
Outdated
void SetVisible(bool bVisible); | ||
|
||
bool OnKeyPress(int iKey); | ||
virtual void Release(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally this should be using override
(rather than redefining it as virtual
to enforce the overridden virtual method (that way it can error if it's defined incorrectly).
i.e.
void Release() override;
src/game/UICmdList.h
Outdated
|
||
bool OnKeyPress(int iKey); | ||
virtual void Release(); | ||
virtual void Tick(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally this should be using override
(rather than redefining it as virtual
to enforce the overridden virtual method (that way it can error if it's defined incorrectly).
i.e.
void Tick() override;
src/game/UICmdList.h
Outdated
bool OnKeyPress(int iKey); | ||
virtual void Release(); | ||
virtual void Tick(); | ||
virtual bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally this should be using override
(rather than redefining it as virtual
to enforce the overridden virtual method (that way it can error if it's defined incorrectly).
i.e.
bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) override;
src/game/UICmdList.h
Outdated
virtual void Release(); | ||
virtual void Tick(); | ||
virtual bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); | ||
void Render(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is virtual but doesn't indicate it as such. Ideally it should be using override
(rather than redefining it as virtual
to enforce the overridden virtual method (that way it can error if it's defined incorrectly).
i.e.
void Render() override;
src/game/UICmdList.h
Outdated
void Render(); | ||
void Open(); | ||
void Close(bool bByKey = false); | ||
bool Load(HANDLE hFile); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is virtual but doesn't indicate it as such. Ideally it should be using override
(rather than redefining it as virtual
to enforce the overridden virtual method (that way it can error if it's defined incorrectly).
i.e.
bool Load(HANDLE hFile) override;
src/game/UICmdList.h
Outdated
bool ExecuteCommand(uint8_t cmdSel); | ||
|
||
CUICmdListDlg(); | ||
virtual ~CUICmdListDlg(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't really need to redefine itself as virtual; to insist that it is overridden virtually, you'd use override
instead, like:
~CUICmdListDlg() override;
But this is more of a preference thing in this case and I don't really know where @stevewgr stands on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with you @twostars, with the caveat mentioned in this comment: #222 (comment)
src/game/UICmdEdit.h
Outdated
std::string m_szArg1; | ||
|
||
public: | ||
void SetVisible(bool bVisible); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is virtual but doesn't indicate it as such. Ideally it should be using override
(rather than redefining it as virtual
to enforce the overridden virtual method (that way it can error if it's defined incorrectly).
i.e.
void SetVisible(bool bVisible) override;
|
||
public: | ||
void SetVisible(bool bVisible); | ||
void Open(std::string msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there's no need to copy or modify, this should be passed by const reference, i.e.:
void Open(const std::string & msg);
void SetVisible(bool bVisible); | ||
void Open(std::string msg); | ||
|
||
bool Load(HANDLE hFile); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is virtual but doesn't indicate it as such. Ideally it should be using override
(rather than redefining it as virtual
to enforce the overridden virtual method (that way it can error if it's defined incorrectly).
i.e.
bool Load(HANDLE hFile) override;
void Open(std::string msg); | ||
|
||
bool Load(HANDLE hFile); | ||
bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is virtual but doesn't indicate it as such. Ideally it should be using override
(rather than redefining it as virtual
to enforce the overridden virtual method (that way it can error if it's defined incorrectly).
i.e.
bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) override;
src/game/UICmdEdit.h
Outdated
bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); | ||
|
||
CUICmdEditDlg(); | ||
virtual ~CUICmdEditDlg(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't really need to redefine itself as virtual; to insist that it is overridden virtually, you'd use override
instead, like:
~CUICmdEditrDlg() override;
But this is more of a preference thing in this case and I don't really know where @stevewgr stands on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
bool CUICmdEditDlg::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { | ||
if (dwMsg == UIMSG_BUTTON_CLICK) { | ||
if (pSender->m_szID == "btn_ok") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have the pointer to this button to check against; can just check it directly instead, i.e.:
if (pSender == m_pBtn_Ok)
return true; | ||
} | ||
|
||
if (pSender->m_szID == "btn_cancel") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have the pointer to this button to check against; can just check it directly instead, i.e.:
if (pSender == m_pBtn_Cancel)
src/game/UICmdList.cpp
Outdated
|
||
return true; | ||
} | ||
bool CUICmdListDlg::UpdateCommandList(uint8_t cmdCat) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should probably be a newline before this line, separating the 2 methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! That's weird that the code formatter didn't fix that. I'll keep that in mind to check for later.
src/game/UICmdList.cpp
Outdated
|
||
return true; | ||
} | ||
bool CUICmdListDlg::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should probably be a newline before this line, separating the 2 methods.
src/game/UICmdList.cpp
Outdated
return true; | ||
} | ||
bool CUICmdListDlg::UpdateCommandList(uint8_t cmdCat) { | ||
if (m_pList_Cmds == NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, I don't know what we're working with, but I assume we should be moving away from the old NULL
definitions and explicitly using C++11's nullptr
instead. But @stevewgr can confirm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely: #222 (comment)
} | ||
|
||
void CUICmdListDlg::Render() { | ||
if (!m_bVisible) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method doesn't really do anything in your implementation.
Officially, it's responsible for rendering the (yellow) selection border of the appropriate list.
If we're keeping it to official behaviour, it should handle this -- but if not, this implementation is pointless and can go.
|
||
//this_ui_add_start | ||
bool CUICmdListDlg::OnKeyPress(int iKey) { | ||
return CN3UIBase::OnKeyPress(iKey); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation is also pointless in your implementation.
Officially, it's responsible for handling DIK_ESCAPE
to close the UI, the various navigation key input (DIK_TAB
, DIK_UP
, DIK_DOWN
) and also for handling selection behaviour (DIK_RETURN
, DIK_NUMPADENTER
).
} | ||
|
||
void CUICmdListDlg::SetVisible(bool bVisible) { | ||
CN3UIBase::SetVisible(bVisible); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Officially this also resets the selection when opening (while not already visible).
As an aside, it also syncs up the button in CUICmd
.
class CUICmdListDlg : public CN3UIBase { | ||
bool m_bDestoyDlgAlive; | ||
class CUICmdEdit * m_pUICmdEdit; | ||
CN3UIButton * m_pBtn_cancel; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the naming scheme of the others, this should probably be m_pBtn_Cancel
src/game/UICmdList.h
Outdated
int m_iRBtnDownOffs; | ||
bool m_bRBtnProcessing; | ||
|
||
enum iCmd { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like the naming of this enum leaves something to be desired, and will more than likely unintentionally clash with variable names used within this class implementation. Probably something like CmdListCategory
or something would avoid any chance of a clash (I don't really know the intended naming scheme for enums here though -- personally I'd match them to the client's e_<name> scheme).
Great majority of my comments were rather nitpicky, and largely dependent on the intentions of the codebase, so take from that what you will. I don't know if it's at all useful, but I will explain how this behaviour is handled officially, for reference. Officially, on The thing with this, is it loads commands into an array for each and every category (not a singular array like it used to): void __stdcall CUICmdList::InitCommands()
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v0 = IDS_CMD_WHISPER;
v1 = CUICmdList::szCommandsPrivate; // Private (12)
do
CGameBase::GetText(v0++, v1++);
while ( (int)v1 < (int)CUICmdList::ParseChattingCommand::szCmds );
v2 = IDS_CMD_TRADE;
v3 = CUICmdList::szCommandsTrade; // Trade (4)
do
CGameBase::GetText(v2++, v3++);
while ( (int)v3 < (int)CUICmdList::szCommandsKing );
v4 = IDS_CMD_PARTY;
v5 = CUICmdList::szCommandsParty; // Party (5)
do
CGameBase::GetText(v4++, v5++);
while ( (int)v5 < (int)CUICmdList::szCommandsClan );
v6 = IDS_CMD_JOINCLAN;
v7 = CUICmdList::szCommandsClan; // Clan (9)
do
CGameBase::GetText(v6++, v7++);
while ( (int)v7 < (int)&stru_815C10 );
v8 = IDS_CMD_CONFEDERACY;
v9 = CUICmdList::szCommandsKnights; // Knights (3)
do
CGameBase::GetText(v8++, v9++);
while ( (int)v9 < (int)CUICmdList::szCommandsParty );
v10 = IDS_CMD_VISIBLE;
v11 = CUICmdList::szCommandsGM; // GM (21)
do
CGameBase::GetText(v10++, v11++);
while ( (int)v11 < (int)&byte_815A48 );
v12 = IDS_CMD_GUARD_HIDE;
v13 = CUICmdList::szCommandsGuardianMonster; // Guardian Monster (7)
do
CGameBase::GetText(v12++, v13++);
while ( (int)v13 < (int)CUICmdList::szCommandsPrivate );
v14 = IDS_CMD_KING_ROYALORDER;
v15 = CUICmdList::szCommandsKing; // King (7)
do
CGameBase::GetText(v14++, v15++);
while ( (int)v15 < (int)CUICmdList::szCommandsKnights );
} With these loaded, in what I call If none of those match, it then scans the various arrays in a particular order, with each category handled by its own method, which I've loosely named like This then scans if they match, and based on the matching index in the array (which they'd have an enum coupled to), they handle the command appropriately, for example: switch ( eCmd )
{
case CMD_PRIVATE_WHISPER:
szID._allocator._byte = v30;
std::string::_Tidy(&szID, 0);
std::string::assign(&szID, arg2, strlen(arg2));
LOBYTE(v38) = 1;
CGameProcMain::MsgSend_ChatSelectTarget(*(CGameProcMain **)v31, &szID, CHAT_TARGET_SELECT_PRIVATE);
LOBYTE(v38) = 0;
std::string::_Tidy(&szID, 1);
goto LABEL_74;
case CMD_PRIVATE_TOWN:
if ( CGameBase::s_pPlayer->_.m_bStun )
goto LABEL_16;
if ( 2 * CGameBase::s_pPlayer->_.m_InfoBase.iHP >= CGameBase::s_pPlayer->_.m_InfoBase.iHPMax
|| CGameBase::s_pPlayer->_.m_InfoExt.iZoneCur == 55 )
{
strcpy((char *)&data, "H");
CAPISocket::Send(CGameProcedure::s_pSocket, (BYTE *)&data._allocator, 2);
}
else
{
data._allocator._byte = v30;
std::string::_Tidy(&data, 0);
LOBYTE(v38) = 2;
CGameBase::GetText(IDS_ERR_GOTO_TOWN_OUT_OF_HP, &data);
CGameProcMain::MsgOutput(*(CGameProcMain **)v31, &data, 0xFFFF00FF);
LOBYTE(v38) = 0;
std::string::_Tidy(&data, 1);
}
goto LABEL_74;
case CMD_PRIVATE_EXIT:
CGameProcMain::RequestExit(*(CGameProcMain **)v31);
goto LABEL_74; Getting back to the list itself, when it's opened it'll reset the selected list to the category list, and toggle the "option" button on case CMD_GROUP_PRIVATE:
v3 = 0;
p_data_long = &CUICmdList::szCommandsPrivate[0]._data_long;
do
{
CGameBase::GetText((e_TextResourceID)(v3 + 8100), &szMsg);
v5 = *p_data_long;
if ( !*p_data_long )
v5 = NewFilename;
data_long = szMsg._data_long;
if ( !szMsg._data_long )
data_long = NewFilename;
sprintf(Buffer, data_long, v5);
v7 = *p_data_long;
if ( !*p_data_long )
v7 = NewFilename;
a2._allocator._byte = v56;
std::string::_Tidy(&a2, 0);
std::string::assign(&a2, v7, strlen(v7));
v54 = 0xFF80FF80;
v57 = (char **)&v53;
LOBYTE(v75) = 1;
sub_4A64F0(&v53, Buffer, &v56);
v8 = v61->_.m_pList_Content;
LOBYTE(v75) = 1;
CN3UIList::AddString(v8, &a2, 0xFFC6C6FB, v53, v54);
LOBYTE(v75) = 0;
std::string::_Tidy(&a2, 1);
p_data_long += 4;
++v3;
}
while ( (int)p_data_long < (int)&CUICmdList::ParseChattingCommand::szCmds[0][4] );
break; What they're (predominantly) doing here is they're just using the various command group enums (e.g. private's containing /PM, /TOWN, etc) and looping until they reach the end of this enum. For each of the categories. Selecting a command predominantly just passes it through, but based on the selected category ID (and then consequently the appropriately selected command, by index in the array -- which is mapped to the previously mentioned enum), it'll determine whether or not it needs to show If it doesn't, it just passes it through to
I think that's about the general gist of how it works. |
src/game/GameProcMain.cpp
Outdated
} else if (11 == iState) { | ||
pBPC->AnimationAdd(ANI_WAR_CRY1, true); // ���� | ||
pBPC->AnimationAdd(ANI_WAR_CRY0, true); // ???? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realise it's not logical, but officially 11 = ANI_WAR_CRY1
, 12 = ANI_WAR_CRY0
and 13 = ANI_WAR_CRY2
. I made the exact same mistake.
case STATE_CHANGE_ACTION:
switch ( iState )
{
case 1u:
CPlayerBase::AnimationAdd((CPlayerBase *)pBPC, ANI_GREETING0, 1);
break;
case 2u:
CPlayerBase::AnimationAdd((CPlayerBase *)pBPC, ANI_GREETING1, 1);
break;
case 3u:
CPlayerBase::AnimationAdd((CPlayerBase *)pBPC, ANI_GREETING2, 1);
break;
case 11u:
CPlayerBase::AnimationAdd((CPlayerBase *)pBPC, ANI_WAR_CRY1, 1);
break;
case 12u:
CPlayerBase::AnimationAdd((CPlayerBase *)pBPC, ANI_WAR_CRY0, 1);
break;
case 13u:
CPlayerBase::AnimationAdd((CPlayerBase *)pBPC, ANI_WAR_CRY2, 1);
break;
}
return;
Thank you, @twostars, for the ASM code. I think I understand how it works now. Do you know how the tooltips is set for the commands in the official version? I tried using SetTooltipText perhaps I am missing some code for rendering it or something else. |
They include the tooltip and the colour in |
Oh i see AddString function has more parameters instead of one "szString" CN3UIList::AddString(v8, &a2, 0xFFC6C6FB, v53, v54); a2 = szString? so i will need also ASM for AddString function too |
Yes, this is correct. Does this help you @xGuTeK?: int CN3UIList::AddString(const CN3UIString & szString, D3DCOLOR crColor, std::string szToolTip, D3DCOLOR crToolTipColor)
{
D3DCOLOR crFont;
CN3UIString *v7; // eax
CN3UIString *pString; // eax
if ( crColor == 0xEFFFFFFF )
crFont = this->CN3UIList.m_crFont;
v7 = (CN3UIString *)operator new(0xECu);
if ( v7 )
pString = CN3UIString::ctor(v7);
else
pString = NULL;
pString->vft->Init(pString, this);
pString->vft->SetFont(
pString,
&this->CN3UIList.m_szFontName,
this->CN3UIList.m_dwFontHeight,
this->CN3UIList.m_bFontBold,
this->CN3UIList.m_bFontItalic);
pString->CN3UIString.m_Color = crFont;
pString->vft->SetString(pString, szString);
pString->CN3UIBase.m_szToolTip = szToolTip;
pString->CN3UIBase.m_crToolTipColor = crToolTipColor;
this->CN3UIList.m_ListString.push_back(pString);
CN3UIList::UpdateChildRegions(this);
return this->CN3UIList.m_ListString._Size - 1;
} |
…missing functions ![Screenshot](https://iili.io/d3T5Xn4.jpg) Thanks to @twostars and @stevewgr for asm code :)
ca0939e
to
98c901d
Compare
7810241
to
e254822
Compare
e254822
to
526ec8e
Compare
Screenshots
Thanks to @twostars and @stevewgr for asm code :)