Support for achievement types (#1052)

This commit is contained in:
Jamiras
2024-01-24 09:21:29 -07:00
committed by GitHub
parent b54bfc5268
commit 1adb9f71bf
32 changed files with 501 additions and 8 deletions
+27
View File
@@ -0,0 +1,27 @@
#ifndef MISSABLE_H
#define MISSABLE_H
const uint8_t MISSABLE_PIXELS[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xae,0xa7,0x00,0x0a,0xe1,0xab,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x27,0x00,0x14,0xfe,0xf4,0x05,0x3a,0xff,0xce,0x00,0x03,0x4c,0x00,0x00,0x00,0x00,
0x00,0x00,0x02,0x96,0xf8,0x38,0x00,0x56,0x6e,0x80,0x80,0x6d,0x35,0x00,0x87,0xff,0x88,0x00,0x00,0x00,
0x00,0x00,0x00,0x90,0xf7,0x55,0x00,0x00,0xab,0xff,0xff,0xab,0x00,0x00,0x5d,0xf0,0x3d,0x00,0x00,0x00,
0x00,0x0c,0x00,0x04,0x2b,0x00,0x00,0x00,0xab,0xff,0xff,0xab,0x00,0x00,0x00,0x11,0x00,0x0d,0x34,0x00,
0x07,0xe2,0xaa,0x0f,0x00,0x00,0x00,0x00,0xab,0xff,0xff,0xab,0x00,0x00,0x00,0x00,0x21,0xeb,0xe6,0x09,
0x3c,0xf7,0xcf,0x01,0x00,0x00,0x00,0x00,0xab,0xff,0xff,0xab,0x00,0x00,0x00,0x00,0x01,0xcb,0xc1,0x1f,
0x00,0x18,0x31,0x00,0x00,0x00,0x00,0x00,0xab,0xff,0xff,0xab,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0xff,0xff,0xab,0x00,0x00,0x00,0x00,0x00,0x02,0x40,0x46,
0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0xff,0xff,0xab,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0xfd,
0xff,0xff,0x04,0x00,0x00,0x00,0x00,0x00,0xab,0xff,0xff,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0xb8,
0x8d,0x89,0x08,0x00,0x00,0x00,0x00,0x00,0x72,0xab,0xab,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x5a,0x06,
0x04,0x6a,0xb5,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff,0x61,
0x0a,0xe4,0xff,0x49,0x00,0x00,0x00,0x00,0x8e,0xd5,0xd5,0x8e,0x00,0x00,0x00,0x00,0x02,0x62,0xbf,0x0a,
0x00,0x51,0x51,0x01,0x01,0x00,0x00,0x00,0xab,0xff,0xff,0xab,0x00,0x00,0x00,0x35,0x27,0x00,0x00,0x00,
0x00,0x00,0x00,0x08,0xc6,0x62,0x00,0x00,0xab,0xff,0xff,0xab,0x00,0x00,0x3a,0xf5,0xdc,0x14,0x00,0x00,
0x00,0x00,0x00,0x60,0xff,0xd8,0x08,0x19,0x6b,0x80,0x80,0x68,0x62,0x17,0x0a,0xca,0x9d,0x05,0x00,0x00,
0x00,0x00,0x00,0x00,0x5d,0x33,0x00,0x83,0xff,0x81,0x00,0xaf,0xff,0x61,0x00,0x0c,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xe6,0x57,0x00,0x60,0xb2,0x47,0x00,0x00,0x00,0x00,0x00,0x00,
};
#endif MISSABLE_H
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/python3
import PIL.Image as Image
def convert(source, output, name):
bytes = []
with Image.open(source, mode='r') as img:
bytes = img.tobytes()
with open(output, mode='w') as f:
f.write("#ifndef {0}_H\n".format(name));
f.write("#define {0}_H\n\n".format(name));
f.write("const uint8_t {0}_PIXELS[] = {{\n".format(name));
i = 0
num_bytes = len(bytes)
while i < num_bytes:
f.write(" ")
for j in range(0,20):
if i < num_bytes:
# just write the alpha value. if it's non-zero the RGB will be constant
f.write("0x{0:02x},".format(bytes[i+3]))
i += 4
f.write("\n")
f.write("};\n\n");
f.write("#endif {0}_H\n".format(name));
convert('missable.png', 'missable.h', 'MISSABLE')
convert('progression.png', 'progression.h', 'PROGRESSION')
convert('win-condition.png', 'win-condition.h', 'WIN_CONDITION')
+27
View File
@@ -0,0 +1,27 @@
#ifndef PROGRESSION_H
#define PROGRESSION_H
const uint8_t PROGRESSION_PIXELS[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x00,0x00,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x11,0x89,0xe7,0xfa,0x17,0x17,0xfa,0xe8,0x89,0x13,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x06,0xe7,0xff,0xd6,0x7a,0x02,0x02,0x7a,0xd6,0xff,0xe8,0x41,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x84,0x58,0x01,0x00,0x00,0x00,0x00,0x01,0x5a,0xf0,0xf7,0x41,0x00,0x00,0x00,
0x00,0x00,0x11,0x7e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0xef,0xe7,0x13,0x00,0x00,
0x00,0x00,0x8a,0xff,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5a,0xff,0x87,0x00,0x00,
0x00,0x02,0xeb,0xd5,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x6d,0x0c,0x00,0x01,0xd6,0xea,0x02,0x00,
0x00,0x2b,0xff,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xc9,0xff,0x3e,0x00,0x00,0x87,0xff,0x2c,0x00,
0x00,0x08,0x7e,0x1d,0x00,0x00,0x25,0xc2,0x3b,0x0f,0xc8,0xff,0x83,0x00,0x00,0x00,0x60,0xff,0x4a,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x25,0xf2,0xf2,0xd0,0xff,0x83,0x00,0x00,0x00,0x00,0x61,0xff,0x49,0x00,
0x00,0x00,0x9b,0x50,0x00,0x00,0x00,0x3b,0xf2,0xff,0x83,0x00,0x00,0x00,0x00,0x00,0x87,0xff,0x2c,0x00,
0x00,0x01,0xe9,0xd5,0x01,0x00,0x00,0x00,0x32,0x5a,0x00,0x00,0x00,0x00,0x00,0x01,0xd7,0xea,0x02,0x00,
0x00,0x00,0x8a,0xff,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0xff,0x86,0x00,0x00,
0x00,0x00,0x12,0xe6,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xef,0xe6,0x12,0x00,0x00,
0x00,0x00,0x00,0x07,0x01,0x0f,0x3e,0x01,0x00,0x00,0x00,0x00,0x01,0x5c,0xf1,0xf7,0x40,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x7f,0xff,0xd5,0x7a,0x02,0x02,0x7a,0xd7,0xff,0xe7,0x3f,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x12,0x8a,0xea,0xfa,0x17,0x17,0xfa,0xe7,0x87,0x12,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x15,0x00,0x00,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
#endif PROGRESSION_H
Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

+27
View File
@@ -0,0 +1,27 @@
#ifndef WIN_CONDITION_H
#define WIN_CONDITION_H
const uint8_t WIN_CONDITION_PIXELS[] = {
0x00,0x00,0x00,0x00,0x00,0x12,0x06,0x00,0x00,0x0c,0x0c,0x00,0x00,0x06,0x12,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xeb,0x96,0x00,0x00,0xc1,0xc1,0x00,0x00,0x96,0xeb,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xff,0xa9,0x00,0x00,0xd4,0xd4,0x00,0x00,0xa9,0xff,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xff,0xa9,0x00,0x00,0xd4,0xd4,0x00,0x00,0xa9,0xff,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xff,0xa9,0x00,0x00,0xd3,0xd3,0x00,0x00,0xa9,0xff,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xff,0xa9,0x00,0x00,0x5c,0x5c,0x00,0x00,0xa9,0xff,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xff,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0xa9,0xff,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xff,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0xa9,0xff,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x95,0x56,0x00,0x00,0x96,0x96,0x00,0x00,0x56,0x95,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xfe,0xfe,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb3,0xfd,0xfd,0xb3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x05,0x43,0x6f,0x9d,0xfe,0xa8,0xa8,0xfe,0x9d,0x6f,0x43,0x05,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x71,0xff,0xff,0xff,0xe4,0x28,0x28,0xe4,0xff,0xff,0xff,0x71,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x1b,0xdc,0xff,0x78,0x00,0x00,0x00,0x00,0x78,0xff,0xdc,0x1b,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x1c,0xdc,0xfd,0x25,0x00,0x00,0x25,0xfd,0xdc,0x1c,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x8f,0xff,0x1e,0x07,0x07,0x1e,0xff,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0xfa,0x6c,0xe2,0xe2,0x6c,0xfa,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xd8,0xff,0xff,0xe8,0xe8,0xff,0xff,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xdd,0xe8,0x73,0x0a,0x0a,0x73,0xe8,0xdd,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x09,0x00,0x00,0x00,0x00,0x09,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
};
#endif WIN_CONDITION_H
Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

+2
View File
@@ -145,6 +145,8 @@
#define IDC_RA_MEMVIEWER_4 1240
#define IDC_RA_DISPLAY_PROGRESS_INDICATOR 1241
#define IDC_RA_MEMVIEW_32BITBE 1242
#define IDC_RA_LBL_TYPE 1243
#define IDC_RA_TYPE 1244
#define IDD_RA_MEMORY 1501
+4 -2
View File
@@ -122,9 +122,11 @@ BEGIN
EDITTEXT IDC_RA_TITLE,50,4,214,13,ES_AUTOHSCROLL
LTEXT "ID:",IDC_RA_LBL_ID,282,7,11,8
EDITTEXT IDC_RA_ID,293,5,44,13,ES_AUTOHSCROLL | WS_DISABLED,WS_EX_RIGHT
CONTROL "Active",IDC_RA_CHK_ACTIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,345,6,40,10
CONTROL "Active",IDC_RA_CHK_ACTIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,340,6,40,10
LTEXT "Description:",IDC_STATIC,4,23,42,8
EDITTEXT IDC_RA_DESCRIPTION,50,21,333,13,ES_AUTOHSCROLL
EDITTEXT IDC_RA_DESCRIPTION,50,21,287,13,ES_AUTOHSCROLL
LTEXT "Type:",IDC_RA_LBL_TYPE,328,23,23,8
COMBOBOX IDC_RA_TYPE,348,21,22,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Points:",IDC_RA_LBL_POINTS,4,40,23,8
COMBOBOX IDC_RA_POINTS,50,38,42,13,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Format:",IDC_RA_LBL_FORMAT,4,40,23,8
+1
View File
@@ -27,6 +27,7 @@ public:
unsigned int Points{ 0U };
unsigned int Category{ 0U };
std::string Badge;
unsigned int Type { 0U };
using Callback = std::function<void(const Response& response)>;
+1
View File
@@ -688,6 +688,7 @@ UpdateAchievement::Response ConnectedServer::UpdateAchievement(const UpdateAchie
api_params.points = request.Points;
api_params.category = request.Category;
api_params.badge = request.Badge.c_str();
api_params.type = request.Type;
rc_api_request_t api_request;
if (rc_api_init_update_achievement_request(&api_request, &api_params) == RC_OK)
+87 -4
View File
@@ -1,5 +1,7 @@
#include "AchievementModel.hh"
#include "RA_Log.h"
#include "data\context\GameContext.hh"
#include "data\models\LocalBadgesModel.hh"
@@ -17,6 +19,7 @@ namespace data {
namespace models {
const IntModelProperty AchievementModel::PointsProperty("AchievementModel", "Points", 5);
const IntModelProperty AchievementModel::AchievementTypeProperty("AchievementModel", "Type", ra::etoi(ra::data::models::AchievementType::None));
const StringModelProperty AchievementModel::BadgeProperty("AchievementModel", "Badge", L"00000");
const BoolModelProperty AchievementModel::PauseOnResetProperty("AchievementModel", "PauseOnReset", false);
const BoolModelProperty AchievementModel::PauseOnTriggerProperty("AchievementModel", "PauseOnTrigger", false);
@@ -30,6 +33,7 @@ AchievementModel::AchievementModel() noexcept
GSL_SUPPRESS_F6 SetValue(TypeProperty, ra::etoi(AssetType::Achievement));
SetTransactional(PointsProperty);
SetTransactional(AchievementTypeProperty);
SetTransactional(BadgeProperty);
GSL_SUPPRESS_F6 AddAssetDefinition(m_pTrigger, TriggerProperty);
@@ -65,6 +69,11 @@ void AchievementModel::OnValueChanged(const IntModelProperty::ChangeArgs& args)
if (m_pAchievement)
SyncPoints();
}
else if (args.Property == AchievementTypeProperty)
{
if (m_pAchievement)
SyncAchievementType();
}
else if (args.Property == IDProperty)
{
if (m_pAchievement)
@@ -319,6 +328,28 @@ void AchievementModel::SyncPoints()
m_pAchievement->public_.points = GetPoints();
}
void AchievementModel::SyncAchievementType()
{
switch (GetAchievementType())
{
case ra::data::models::AchievementType::None:
m_pAchievement->public_.type = RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD;
break;
case ra::data::models::AchievementType::Missable:
m_pAchievement->public_.type = RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE;
break;
case ra::data::models::AchievementType::Progression:
m_pAchievement->public_.type = RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION;
break;
case ra::data::models::AchievementType::Win:
m_pAchievement->public_.type = RC_CLIENT_ACHIEVEMENT_TYPE_WIN;
break;
default:
m_pAchievement->public_.type = gsl::narrow_cast<uint8_t>(GetValue(AchievementTypeProperty));
break;
}
}
void AchievementModel::SyncCategory()
{
switch (GetCategory())
@@ -421,6 +452,26 @@ void AchievementModel::Attach(struct rc_client_achievement_info_t& pAchievement,
SetUpdatedTime(pAchievement.updated_time);
SetTrigger(sTrigger);
switch (pAchievement.public_.type)
{
case RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD:
SetAchievementType(ra::data::models::AchievementType::None);
break;
case RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE:
SetAchievementType(ra::data::models::AchievementType::Missable);
break;
case RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION:
SetAchievementType(ra::data::models::AchievementType::Progression);
break;
case RC_CLIENT_ACHIEVEMENT_TYPE_WIN:
SetAchievementType(ra::data::models::AchievementType::Win);
break;
default:
RA_LOG_ERR("Unsupported achievement type: %d", pAchievement.public_.type);
SetValue(AchievementTypeProperty, pAchievement.public_.type);
break;
}
CreateServerCheckpoint();
CreateLocalCheckpoint();
@@ -446,6 +497,7 @@ void AchievementModel::AttachAndInitialize(struct rc_client_achievement_info_t&
SyncCategory();
SyncTrigger();
SyncState();
SyncAchievementType();
}
void AchievementModel::Serialize(ra::services::TextWriter& pWriter) const
@@ -453,7 +505,27 @@ void AchievementModel::Serialize(ra::services::TextWriter& pWriter) const
WriteQuoted(pWriter, GetLocalAssetDefinition(m_pTrigger));
WritePossiblyQuoted(pWriter, GetLocalValue(NameProperty));
WritePossiblyQuoted(pWriter, GetLocalValue(DescriptionProperty));
pWriter.Write(":::"); // progress/max/format/author
pWriter.Write("::"); // progress/max
switch (GetAchievementType())
{
case ra::data::models::AchievementType::None:
WritePossiblyQuoted(pWriter, "");
break;
case ra::data::models::AchievementType::Missable:
WritePossiblyQuoted(pWriter, "missable");
break;
case ra::data::models::AchievementType::Progression:
WritePossiblyQuoted(pWriter, "progression");
break;
case ra::data::models::AchievementType::Win:
WritePossiblyQuoted(pWriter, "win_condition");
break;
default:
WriteNumber(pWriter, GetValue(TypeProperty));
break;
}
WritePossiblyQuoted(pWriter, GetLocalValue(AuthorProperty));
WriteNumber(pWriter, GetLocalValue(PointsProperty));
pWriter.Write("::::"); // created/modified/upvotes/downvotes
@@ -504,9 +576,9 @@ bool AchievementModel::Deserialize(ra::Tokenizer& pTokenizer)
if (!pTokenizer.Consume(':'))
return false;
// field 7: progress format (unused)
pTokenizer.AdvanceTo(':');
if (!pTokenizer.Consume(':'))
// field 7: achievement type
std::string sType;
if (!ReadPossiblyQuoted(pTokenizer, sType))
return false;
// field 8: author (unused)
@@ -555,6 +627,17 @@ bool AchievementModel::Deserialize(ra::Tokenizer& pTokenizer)
SetBadge(ra::Widen(sBadge));
SetTrigger(sTrigger);
if (sType.empty())
SetAchievementType(ra::data::models::AchievementType::None);
else if (sType == "missable")
SetAchievementType(ra::data::models::AchievementType::Missable);
else if (sType == "progression")
SetAchievementType(ra::data::models::AchievementType::Progression);
else if (sType == "win_condition")
SetAchievementType(ra::data::models::AchievementType::Win);
else
SetValue(AchievementTypeProperty, atoi(sType.c_str()));
return true;
}
+24
View File
@@ -12,6 +12,14 @@ namespace ra {
namespace data {
namespace models {
enum AchievementType
{
None = 0,
Missable,
Progression,
Win,
};
class AchievementModel : public AssetModelBase
{
public:
@@ -32,6 +40,21 @@ public:
/// </summary>
void SetPoints(int nValue) { SetValue(PointsProperty, nValue); }
/// <summary>
/// The <see cref="ModelProperty" /> for the achievement type.
/// </summary>
static const IntModelProperty AchievementTypeProperty;
/// <summary>
/// Gets the type of the achievement.
/// </summary>
AchievementType GetAchievementType() const { return ra::itoe<AchievementType>(GetValue(AchievementTypeProperty)); }
/// <summary>
/// Sets the type for the achievement.
/// </summary>
void SetAchievementType(AchievementType nValue) { SetValue(AchievementTypeProperty, ra::etoi(nValue)); }
/// <summary>
/// The <see cref="ModelProperty" /> for the badge.
/// </summary>
@@ -166,6 +189,7 @@ private:
void SyncDescription();
void SyncBadge();
void SyncPoints();
void SyncAchievementType();
void SyncCategory();
void SyncState();
void SyncTrigger();
+2
View File
@@ -114,6 +114,8 @@ public:
/// <param name="nAlpha">The new opacity (0.0-1.0).</param>
virtual void SetOpacity(double fAlpha) = 0;
virtual void SetPixels(int nX, int nY, int nWidth, int nHeight, uint32_t* pARGB) = 0;
protected:
ISurface() noexcept = default;
};
+12
View File
@@ -76,6 +76,18 @@ static constexpr uint8_t BlendPixel(std::uint8_t nTarget, std::uint8_t nBlend, s
return gsl::narrow_cast<std::uint8_t>(((nBlend * nAlpha) + (nTarget * (256 - nAlpha))) / 256);
}
void GDIBitmapSurface::SetPixels(int nX, int nY, int nWidth, int nHeight, uint32_t* pARGB) noexcept
{
const auto nStride = ra::to_signed(GetWidth());
std::uint32_t* pBits = m_pBits + gsl::narrow_cast<size_t>(nY) * nStride + nX;
while (nHeight--)
{
memcpy(pBits + gsl::narrow_cast<size_t>(nHeight) * nStride, pARGB, nWidth * sizeof(uint32_t));
pARGB += nWidth;
}
}
void GDIBitmapSurface::WriteText(int nX, int nY, int nFont, Color nColor, const std::wstring& sText)
{
if (sText.empty())
+2
View File
@@ -45,6 +45,8 @@ public:
HBITMAP GetHBitmap() const noexcept { return m_hBitmap; }
void SetPixels(int nX, int nY, int nWidth, int nHeight, uint32_t* pARGB) noexcept override;
protected:
std::uint32_t* m_pBits; // see note below about initializing this
+4
View File
@@ -39,6 +39,10 @@ public:
void DrawSurface(int nX, int nY, const ISurface& pSurface, int nSurfaceX, int nSurfaceY, int nWidth, int nHeight) noexcept override;
GSL_SUPPRESS_F6 void SetOpacity(_UNUSED double) override { assert("This surface does not support opacity"); }
GSL_SUPPRESS_F6 void SetPixels(_UNUSED int, _UNUSED int, _UNUSED int, _UNUSED int, _UNUSED uint32_t*) override
{
assert("This surface does not support setting pixels");
}
HDC GetHDC() const noexcept { return m_hDC; }
@@ -46,6 +46,7 @@ const StringModelProperty AssetEditorViewModel::AssetValidationWarningProperty("
const BoolModelProperty AssetEditorViewModel::HasMeasuredProperty("AssetEditorViewModel", "HasMeasured", false);
const StringModelProperty AssetEditorViewModel::MeasuredValueProperty("AssetEditorViewModel", "MeasuredValue", L"[Not Active]");
const StringModelProperty AssetEditorViewModel::WaitingLabelProperty("AssetEditorViewModel", "WaitingLabel", L"Active");
const IntModelProperty AssetEditorViewModel::AchievementTypeProperty("AssetEditorViewModel", "AchievementType", ra::etoi(ra::data::models::AchievementType::None));
const IntModelProperty AssetEditorViewModel::LeaderboardPartViewModel::ColorProperty("LeaderboardPartViewModel", "Color", 0);
AssetEditorViewModel::AssetEditorViewModel() noexcept
@@ -54,6 +55,11 @@ AssetEditorViewModel::AssetEditorViewModel() noexcept
m_vmTrigger.AddNotifyTarget(*this);
m_vAchievementTypes.Add(ra::etoi(ra::data::models::AchievementType::None), L"");
m_vAchievementTypes.Add(ra::etoi(ra::data::models::AchievementType::Missable), L"Missable");
m_vAchievementTypes.Add(ra::etoi(ra::data::models::AchievementType::Progression), L"Progression");
m_vAchievementTypes.Add(ra::etoi(ra::data::models::AchievementType::Win), L"Win");
m_vFormats.Add(ra::etoi(ra::data::ValueFormat::Value), L"Value");
m_vFormats.Add(ra::etoi(ra::data::ValueFormat::Score), L"Score");
m_vFormats.Add(ra::etoi(ra::data::ValueFormat::Frames), L"Frames");
@@ -204,6 +210,7 @@ void AssetEditorViewModel::LoadAsset(ra::data::models::AssetModelBase* pAsset, b
{
SetPoints(pAchievement->GetPoints());
SetBadge(pAchievement->GetBadge());
SetAchievementType(pAchievement->GetAchievementType());
SetPauseOnReset(pAchievement->IsPauseOnReset());
SetPauseOnTrigger(pAchievement->IsPauseOnTrigger());
@@ -251,6 +258,7 @@ void AssetEditorViewModel::LoadAsset(ra::data::models::AssetModelBase* pAsset, b
SetCategory(ra::itoe<ra::data::models::AssetCategory>(CategoryProperty.GetDefaultValue()));
SetPoints(PointsProperty.GetDefaultValue());
SetBadge(BadgeProperty.GetDefaultValue());
SetAchievementType(ra::itoe<ra::data::models::AchievementType>(AchievementTypeProperty.GetDefaultValue()));
SetPauseOnReset(PauseOnResetProperty.GetDefaultValue());
SetPauseOnTrigger(PauseOnTriggerProperty.GetDefaultValue());
SetWindowTitle(L"Achievement Editor");
@@ -412,6 +420,8 @@ void AssetEditorViewModel::OnDataModelIntValueChanged(const IntModelProperty::Ch
SetCategory(ra::itoe<ra::data::models::AssetCategory>(args.tNewValue));
else if (args.Property == ra::data::models::AchievementModel::PointsProperty)
SetPoints(args.tNewValue);
else if (args.Property == ra::data::models::AchievementModel::TypeProperty)
SetAchievementType(ra::itoe<ra::data::models::AchievementType>(args.tNewValue));
else if (args.Property == ra::data::models::LeaderboardModel::ValueFormatProperty)
SetValueFormat(ra::itoe<ra::data::ValueFormat>(args.tNewValue));
else if (args.Property == ra::data::models::AssetModelBase::IDProperty)
@@ -557,6 +567,8 @@ void AssetEditorViewModel::OnValueChanged(const IntModelProperty::ChangeArgs& ar
{
if (args.Property == PointsProperty)
pAchievement->SetPoints(args.tNewValue);
else if (args.Property == AchievementTypeProperty)
pAchievement->SetAchievementType(ra::itoe<ra::data::models::AchievementType>(args.tNewValue));
}
else
{
+25
View File
@@ -5,6 +5,7 @@
#include "TriggerViewModel.hh"
#include "data\Types.hh"
#include "data\models\AchievementModel.hh"
#include "data\models\AssetModelBase.hh"
#include "ui\WindowViewModelBase.hh"
@@ -202,6 +203,29 @@ public:
/// </summary>
void SelectBadgeFile();
/// <summary>
/// The <see cref="ModelProperty" /> for the achievement type.
/// </summary>
static const IntModelProperty AchievementTypeProperty;
/// <summary>
/// Gets the achievement type.
/// </summary>
ra::data::models::AchievementType GetAchievementType() const
{
return ra::itoe<ra::data::models::AchievementType>(GetValue(AchievementTypeProperty));
}
/// <summary>
/// Sets the achievement type.
/// </summary>
void SetAchievementType(ra::data::models::AchievementType nValue) { SetValue(AchievementTypeProperty, ra::etoi(nValue)); }
/// <summary>
/// Gets the list of achievement types.
/// </summary>
const LookupItemViewModelCollection& AchievementTypes() const noexcept { return m_vAchievementTypes; }
// ===== Leaderboard Specific =====
/// <summary>
@@ -452,6 +476,7 @@ protected:
ra::data::models::AssetModelBase* m_pAsset = nullptr;
bool m_bIgnoreTriggerUpdate = false;
LookupItemViewModelCollection m_vAchievementTypes;
LookupItemViewModelCollection m_vFormats;
ViewModelCollection<LeaderboardPartViewModel> m_vLeaderboardParts;
};
@@ -15,6 +15,8 @@
#include "RA_Defs.h"
#include "RA_Log.h"
#include <rcheevos/include/rc_api_runtime.h>
namespace ra {
namespace ui {
namespace viewmodels {
@@ -233,6 +235,25 @@ void AssetUploadViewModel::UploadAchievement(ra::data::models::AchievementModel&
request.Points = pAchievement.GetPoints();
request.Badge = ra::Narrow(pAchievement.GetBadge());
switch (pAchievement.GetAchievementType())
{
case ra::data::models::AchievementType::None:
request.Type = RC_ACHIEVEMENT_TYPE_STANDARD;
break;
case ra::data::models::AchievementType::Missable:
request.Type = RC_ACHIEVEMENT_TYPE_MISSABLE;
break;
case ra::data::models::AchievementType::Progression:
request.Type = RC_ACHIEVEMENT_TYPE_PROGRESSION;
break;
case ra::data::models::AchievementType::Win:
request.Type = RC_ACHIEVEMENT_TYPE_WIN;
break;
default:
request.Type = ra::etoi(pAchievement.GetAchievementType());
break;
}
if (pAchievement.GetCategory() == ra::data::models::AssetCategory::Local)
{
request.Category = ra::to_unsigned(ra::etoi(ra::data::models::AssetCategory::Unofficial));
@@ -89,6 +89,18 @@ void OverlayAchievementsPageViewModel::Refresh()
{
OverlayListPageViewModel::Refresh();
if (m_pMissableSurface == nullptr)
{
#include "..\data\missable.h"
m_pMissableSurface = LoadDecorator(MISSABLE_PIXELS, 20, 20);
#include "..\data\progression.h"
m_pProgressionSurface = LoadDecorator(PROGRESSION_PIXELS, 20, 20);
#include "..\data\win-condition.h"
m_pWinConditionSurface = LoadDecorator(WIN_CONDITION_PIXELS, 20, 20);
}
// title
const auto& pGameContext = ra::services::ServiceLocator::Get<ra::data::context::GameContext>();
const auto& sTitle = pGameContext.GameTitle();
@@ -177,6 +189,22 @@ void OverlayAchievementsPageViewModel::Refresh()
{
auto& pvmAchievement = GetNextItem(&nIndex);
SetAchievement(pvmAchievement, **pAchievement);
switch ((*pAchievement)->type)
{
case RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE:
pvmAchievement.SetDecorator(m_pMissableSurface.get());
break;
case RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION:
pvmAchievement.SetDecorator(m_pProgressionSurface.get());
break;
case RC_CLIENT_ACHIEVEMENT_TYPE_WIN:
pvmAchievement.SetDecorator(m_pWinConditionSurface.get());
break;
default:
pvmAchievement.SetDecorator(nullptr);
break;
}
}
}
@@ -278,7 +306,7 @@ const wchar_t* OverlayAchievementsPageViewModel::GetNextButtonText() const noexc
return L"Leaderboards";
}
void OverlayAchievementsPageViewModel::RenderDetail(ra::ui::drawing::ISurface& pSurface, int nX, int nY, _UNUSED int nWidth, int nHeight) const
void OverlayAchievementsPageViewModel::RenderDetail(ra::ui::drawing::ISurface& pSurface, int nX, int nY, int nWidth, int nHeight) const
{
const auto* pAchievement = m_vItems.GetItemAt(GetSelectedItemIndex());
if (pAchievement == nullptr)
@@ -294,12 +322,17 @@ void OverlayAchievementsPageViewModel::RenderDetail(ra::ui::drawing::ISurface& p
pSurface.WriteText(nX + nAchievementSize + 12, nY + 4, nFont, pTheme.ColorOverlayText(), pAchievement->GetLabel());
pSurface.WriteText(nX + nAchievementSize + 12, nY + 4 + 26, nSubFont, pTheme.ColorOverlaySubText(), pAchievement->GetDetail());
nY += nAchievementSize + 8;
const auto* pDecorator = pAchievement->GetDecorator();
if (pDecorator != nullptr)
pSurface.DrawSurface(nWidth - 5 - pDecorator->GetWidth(), nY + 6, *pDecorator);
const auto pDetail = m_vAchievementDetails.find(pAchievement->GetId());
if (pDetail == m_vAchievementDetails.end())
return;
nY += nAchievementSize + 8;
const auto szDetail = pSurface.MeasureText(nDetailFont, L"M");
pSurface.WriteText(nX, nY, nDetailFont, pTheme.ColorOverlaySubText(), L"Created: " + pDetail->second.GetCreatedDate());
nY += szDetail.Height;
@@ -95,6 +95,10 @@ private:
std::wstring m_sSummary;
std::map<gsl::index, uint32_t> m_mHeaderKeys;
std::unique_ptr<ra::ui::drawing::ISurface> m_pMissableSurface;
std::unique_ptr<ra::ui::drawing::ISurface> m_pProgressionSurface;
std::unique_ptr<ra::ui::drawing::ISurface> m_pWinConditionSurface;
};
} // namespace viewmodels
@@ -117,6 +117,39 @@ bool OverlayListPageViewModel::Update(double fElapsed)
return bUpdated;
}
std::unique_ptr<ra::ui::drawing::ISurface> OverlayListPageViewModel::LoadDecorator(
const uint8_t* pixels, int nWidth, int nHeight)
{
uint32_t* argb_pixels = static_cast<uint32_t*>(malloc(gsl::narrow_cast<size_t>(nWidth) * nHeight * sizeof(uint32_t)));
if (argb_pixels == nullptr)
return nullptr;
const auto& pTheme = ra::services::ServiceLocator::Get<ra::ui::OverlayTheme>();
ra::ui::Color nTextColor = pTheme.ColorOverlayDisabledText();
auto& pSurfaceFactory = ra::services::ServiceLocator::GetMutable<ra::ui::drawing::ISurfaceFactory>();
auto pDecorator = pSurfaceFactory.CreateTransparentSurface(nWidth, nHeight);
GSL_SUPPRESS_F23 uint32_t* dst = argb_pixels;
GSL_SUPPRESS_F23 const uint8_t* src = pixels;
const uint8_t* stop = pixels + gsl::narrow_cast<size_t>(nWidth) * nHeight;
while (src < stop)
{
nTextColor.Channel.A = *src++;
if (nTextColor.Channel.A == 0)
*dst++ = 0;
else
*dst++ = nTextColor.ARGB;
}
pDecorator->SetPixels(0, 0, nWidth, nHeight, argb_pixels);
free(argb_pixels);
return pDecorator;
}
void OverlayListPageViewModel::Render(ra::ui::drawing::ISurface& pSurface, int nX, int nY, int nWidth, int nHeight) const
{
if (m_bDetail)
@@ -222,6 +255,10 @@ void OverlayListPageViewModel::RenderList(ra::ui::drawing::ISurface& pSurface, i
const auto szProgress = pSurface.MeasureText(nProgressFont, sProgress);
pSurface.WriteText(nTextX + 12 + nProgressBarWidth + 6, nY + 1 + 26 + 25 + 4 - (szProgress.Height / 2) - 1, nProgressFont, nSubTextColor, sProgress);
}
const auto* pDecorator = pItem->GetDecorator();
if (pDecorator != nullptr)
pSurface.DrawSurface(nWidth - 5 - pDecorator->GetWidth(), nY + 6, *pDecorator);
}
nIndex++;
@@ -138,6 +138,12 @@ public:
/// Gets whether the current item is a header item.
/// </summary>
bool IsHeader() const { return GetId() == 0; }
ra::ui::drawing::ISurface* GetDecorator() const noexcept { return m_pDecorator; }
void SetDecorator(ra::ui::drawing::ISurface* pDecorator) noexcept { m_pDecorator = pDecorator; }
private:
ra::ui::drawing::ISurface* m_pDecorator = nullptr;
};
protected:
@@ -157,6 +163,8 @@ protected:
static void SetHeader(OverlayListPageViewModel::ItemViewModel& vmItem, const std::wstring& sHeader);
static bool AssetAppearsInFilter(const ra::data::models::AssetModelBase& pAsset);
std::unique_ptr<ra::ui::drawing::ISurface> LoadDecorator(const uint8_t* pixels, int nWidth, int nHeight);
ra::ui::ViewModelCollection<ItemViewModel> m_vItems;
private:
+8
View File
@@ -711,6 +711,7 @@ AssetEditorDialog::AssetEditorDialog(AssetEditorViewModel& vmAssetEditor)
m_bindBadgeImage(vmAssetEditor),
m_bindPoints(vmAssetEditor),
m_bindFormats(vmAssetEditor),
m_bindAchievementTypes(vmAssetEditor),
m_bindLeaderboardParts(vmAssetEditor),
m_bindLowerIsBetter(vmAssetEditor),
m_bindErrorIcon(vmAssetEditor),
@@ -771,6 +772,10 @@ AssetEditorDialog::AssetEditorDialog(AssetEditorViewModel& vmAssetEditor)
m_bindWindow.BindVisible(IDC_RA_BADGE_SPIN, AssetEditorViewModel::IsAchievementProperty);
m_bindWindow.BindVisible(IDC_RA_UPLOAD_BADGE, AssetEditorViewModel::IsAchievementProperty);
m_bindWindow.BindVisible(IDC_RA_BADGEPIC, AssetEditorViewModel::IsAchievementProperty);
m_bindAchievementTypes.BindItems(vmAssetEditor.AchievementTypes());
m_bindAchievementTypes.BindSelectedItem(AssetEditorViewModel::AchievementTypeProperty);
m_bindWindow.BindVisible(IDC_RA_LBL_TYPE, AssetEditorViewModel::IsAchievementProperty);
m_bindWindow.BindVisible(IDC_RA_TYPE, AssetEditorViewModel::IsAchievementProperty);
// leaderboard only fields
m_bindFormats.BindItems(vmAssetEditor.Formats());
@@ -940,6 +945,7 @@ BOOL AssetEditorDialog::OnInitDialog()
m_bindPoints.SetControl(*this, IDC_RA_POINTS);
m_bindFormats.SetControl(*this, IDC_RA_FORMAT);
m_bindLeaderboardParts.SetControl(*this, IDC_RA_LBX_LBOARD_PARTS);
m_bindAchievementTypes.SetControl(*this, IDC_RA_TYPE);
m_bindGroups.SetControl(*this, IDC_RA_LBX_GROUPS);
m_bindConditions.SetControl(*this, IDC_RA_LBX_CONDITIONS);
@@ -975,6 +981,8 @@ BOOL AssetEditorDialog::OnInitDialog()
SendMessage(m_hTooltip, TTM_ACTIVATE, TRUE, 0);
}
SendMessage(::GetDlgItem(GetHWND(), IDC_RA_TYPE), CB_SETDROPPEDWIDTH, 70, 0);
return DialogBase::OnInitDialog();
}
+1
View File
@@ -143,6 +143,7 @@ private:
ra::ui::win32::bindings::ImageBinding m_bindBadgeImage;
PointBinding m_bindPoints;
ra::ui::win32::bindings::ComboBoxBinding m_bindFormats;
ra::ui::win32::bindings::ComboBoxBinding m_bindAchievementTypes;
ra::ui::win32::bindings::GridBinding m_bindLeaderboardParts;
ra::ui::win32::bindings::CheckBoxBinding m_bindLowerIsBetter;
+18
View File
@@ -152,6 +152,24 @@ std::wstring ToString<ra::data::models::LeaderboardModel::LeaderboardParts>(cons
}
}
template<>
std::wstring ToString<ra::data::models::AchievementType>(const ra::data::models::AchievementType& nAchievementType)
{
switch (nAchievementType)
{
case ra::data::models::AchievementType::None:
return L"None";
case ra::data::models::AchievementType::Missable:
return L"Missable";
case ra::data::models::AchievementType::Progression:
return L"Progression";
case ra::data::models::AchievementType::Win:
return L"Win";
default:
return std::to_wstring(static_cast<int>(nAchievementType));
}
}
#pragma warning(pop)
} // namespace CppUnitTestFramework
@@ -62,6 +62,7 @@ public:
Assert::AreEqual(AssetState::Inactive, achievement.GetState());
Assert::AreEqual(AssetChanges::None, achievement.GetChanges());
Assert::AreEqual(5, achievement.GetPoints());
Assert::AreEqual(AchievementType::None, achievement.GetAchievementType());
Assert::AreEqual(std::wstring(L"00000"), achievement.GetBadge());
Assert::IsFalse(achievement.IsPauseOnReset());
Assert::IsFalse(achievement.IsPauseOnTrigger());
+1
View File
@@ -36,6 +36,7 @@ public:
void DrawSurface(int, int, const ISurface&) noexcept override {}
void DrawSurface(int, int, const ISurface&, int, int, int, int) noexcept override {}
void SetOpacity(double) noexcept override {}
void SetPixels(int, int, int, int, uint32_t*) noexcept override {}
private:
unsigned int m_nWidth;
@@ -131,6 +131,16 @@ public:
Assert::AreEqual((int)AssetEditorViewModel::LeaderboardPart::Start, (int)editor.GetSelectedLeaderboardPart());
Assert::AreEqual(ra::data::ValueFormat::Value, editor.GetValueFormat());
Assert::AreEqual({ 4U }, editor.AchievementTypes().Count());
Assert::AreEqual((int)ra::data::models::AchievementType::None, editor.AchievementTypes().GetItemAt(0)->GetId());
Assert::AreEqual(std::wstring(L""), editor.AchievementTypes().GetItemAt(0)->GetLabel());
Assert::AreEqual((int)ra::data::models::AchievementType::Missable, editor.AchievementTypes().GetItemAt(1)->GetId());
Assert::AreEqual(std::wstring(L"Missable"), editor.AchievementTypes().GetItemAt(1)->GetLabel());
Assert::AreEqual((int)ra::data::models::AchievementType::Progression, editor.AchievementTypes().GetItemAt(2)->GetId());
Assert::AreEqual(std::wstring(L"Progression"), editor.AchievementTypes().GetItemAt(2)->GetLabel());
Assert::AreEqual((int)ra::data::models::AchievementType::Win, editor.AchievementTypes().GetItemAt(3)->GetId());
Assert::AreEqual(std::wstring(L"Win"), editor.AchievementTypes().GetItemAt(3)->GetLabel());
Assert::AreEqual({ 6U }, editor.Formats().Count());
Assert::AreEqual((int)ra::data::ValueFormat::Value, editor.Formats().GetItemAt(0)->GetId());
Assert::AreEqual(std::wstring(L"Value"), editor.Formats().GetItemAt(0)->GetLabel());
@@ -966,6 +976,31 @@ public:
Assert::AreEqual(50, achievement.GetPoints());
}
TEST_METHOD(TestSyncAchievementType)
{
AssetEditorViewModelHarness editor;
AchievementModel achievement;
achievement.SetAchievementType(ra::data::models::AchievementType::Progression);
achievement.CreateServerCheckpoint();
achievement.CreateLocalCheckpoint();
editor.LoadAsset(&achievement);
Assert::AreEqual(ra::data::models::AchievementType::Progression, editor.GetAchievementType());
Assert::AreEqual(ra::data::models::AchievementType::Progression, achievement.GetAchievementType());
editor.SetAchievementType(ra::data::models::AchievementType::None);
Assert::AreEqual(ra::data::models::AchievementType::None, editor.GetAchievementType());
Assert::AreEqual(ra::data::models::AchievementType::None, achievement.GetAchievementType());
editor.SetAchievementType(ra::data::models::AchievementType::Win);
Assert::AreEqual(ra::data::models::AchievementType::Win, editor.GetAchievementType());
Assert::AreEqual(ra::data::models::AchievementType::Win, achievement.GetAchievementType());
editor.SetAchievementType(ra::data::models::AchievementType::Missable);
Assert::AreEqual(ra::data::models::AchievementType::Missable, editor.GetAchievementType());
Assert::AreEqual(ra::data::models::AchievementType::Missable, achievement.GetAchievementType());
}
TEST_METHOD(TestSyncBadge)
{
AssetEditorViewModelHarness editor;
@@ -283,6 +283,46 @@ public:
Assert::AreEqual(std::string("12345"), pRequest.Badge);
Assert::AreEqual(3U, pRequest.Category);
Assert::AreEqual(1U, pRequest.AchievementId);
Assert::AreEqual(0U, pRequest.Type);
pResponse.AchievementId = pRequest.AchievementId;
pResponse.Result = ra::api::ApiResult::Success;
return true;
});
vmUpload.DoUpload();
Assert::IsTrue(bApiCalled);
Assert::AreEqual(AssetChanges::None, pAchievement.GetChanges());
vmUpload.AssertSuccess(1);
}
TEST_METHOD(TestSingleCoreAchievementMissable)
{
AssetUploadViewModelHarness vmUpload;
auto& pAchievement = vmUpload.AddAchievement(AssetCategory::Core, 5, L"Title1", L"Desc1", L"12345", "0xH1234=1");
pAchievement.SetAchievementType(ra::data::models::AchievementType::Missable);
pAchievement.UpdateLocalCheckpoint();
Assert::AreEqual(AssetChanges::Unpublished, pAchievement.GetChanges());
vmUpload.QueueAsset(pAchievement);
Assert::AreEqual({ 1U }, vmUpload.TaskCount());
bool bApiCalled = false;
vmUpload.mockServer.HandleRequest<ra::api::UpdateAchievement>([&bApiCalled]
(const ra::api::UpdateAchievement::Request& pRequest, ra::api::UpdateAchievement::Response& pResponse)
{
bApiCalled = true;
Assert::AreEqual(AssetUploadViewModelHarness::GameId, pRequest.GameId);
Assert::AreEqual(std::wstring(L"Title1"), pRequest.Title);
Assert::AreEqual(std::wstring(L"Desc1"), pRequest.Description);
Assert::AreEqual(std::string("0xH1234=1"), pRequest.Trigger);
Assert::AreEqual(5U, pRequest.Points);
Assert::AreEqual(std::string("12345"), pRequest.Badge);
Assert::AreEqual(3U, pRequest.Category);
Assert::AreEqual(1U, pRequest.AchievementId);
Assert::AreEqual(1U, pRequest.Type);
pResponse.AchievementId = pRequest.AchievementId;
pResponse.Result = ra::api::ApiResult::Success;
@@ -7,8 +7,10 @@
#include "tests\mocks\MockGameContext.hh"
#include "tests\mocks\MockImageRepository.hh"
#include "tests\mocks\MockOverlayManager.hh"
#include "tests\mocks\MockOverlayTheme.hh"
#include "tests\mocks\MockServer.hh"
#include "tests\mocks\MockSessionTracker.hh"
#include "tests\mocks\MockSurface.hh"
#include "tests\mocks\MockThreadPool.hh"
#include "tests\mocks\MockUserContext.hh"
#include "tests\mocks\MockWindowManager.hh"
@@ -38,6 +40,8 @@ private:
ra::services::mocks::MockClock mockClock;
ra::services::mocks::MockThreadPool mockThreadPool;
ra::ui::mocks::MockImageRepository mockImageRepository;
ra::ui::mocks::MockOverlayTheme mockOverlayTheme;
ra::ui::drawing::mocks::MockSurfaceFactory mockSurfaceFactory;
ra::ui::viewmodels::mocks::MockOverlayManager mockOverlayManager;
ra::ui::viewmodels::mocks::MockWindowManager mockWindowManager;