Give mission achievements at game start
This commit is contained in:
parent
e45324ad32
commit
8a56923a7d
@ -188,6 +188,127 @@ namespace achievements
|
||||
{
|
||||
give_achievement(game::Scr_GetString(0));
|
||||
}
|
||||
|
||||
void give_mission_achievements()
|
||||
{
|
||||
game::GamerProfileData data{};
|
||||
game::GamerProfile_GetDataByName(&data, 0, "missionhighestdifficulty", 0xFFFFFFFF);
|
||||
|
||||
if (data.type != game::TYPE_STRING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
achievement_file_t file{};
|
||||
achievements::get_achievements(&file);
|
||||
|
||||
const auto completed_mission = [&](const game::level_number level, const std::string& achievement)
|
||||
{
|
||||
const auto id = get_achievement_id(achievement);
|
||||
if (!id.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto id_value = id.value();
|
||||
const auto highest_difficulty = data.u.stringVal[level] - '0';
|
||||
if (highest_difficulty)
|
||||
{
|
||||
file.achievements[id_value] = true;
|
||||
}
|
||||
};
|
||||
|
||||
std::unordered_map<achievement_id, std::vector<game::level_number>> veteran_achievements;
|
||||
|
||||
const auto add_veteran_achievement = [&](const game::level_number level, const std::string& achievement)
|
||||
{
|
||||
const auto id = get_achievement_id(achievement);
|
||||
if (!id.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto id_value = static_cast<achievement_id>(id.value());
|
||||
veteran_achievements[id_value].push_back(level);
|
||||
};
|
||||
|
||||
const auto give_veteran_achievements = [&]()
|
||||
{
|
||||
for (const auto& achievement : veteran_achievements)
|
||||
{
|
||||
auto has_veteran = true;
|
||||
for (const auto& mission : achievement.second)
|
||||
{
|
||||
if (data.u.stringVal[mission] != '3')
|
||||
{
|
||||
has_veteran = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_veteran)
|
||||
{
|
||||
file.achievements[achievement.first] = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const auto give_completed_campaign_achievement = [&](const std::string& achievement)
|
||||
{
|
||||
const auto id = get_achievement_id(achievement);
|
||||
if (!id.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto id_value = static_cast<achievement_id>(id.value());
|
||||
for (auto i = 0; i < game::LEVEL_COUNT; i++)
|
||||
{
|
||||
if (data.u.stringVal[i] - '0' < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
file.achievements[id_value] = true;
|
||||
};
|
||||
|
||||
completed_mission(game::LEVEL_TRAINER, "BACK_IN_THE_SADDLE");
|
||||
completed_mission(game::LEVEL_ROADKILL, "DANGER_CLOSE");
|
||||
completed_mission(game::LEVEL_CLIFFHANGER, "COLD_SHOULDER");
|
||||
completed_mission(game::LEVEL_FAVELA, "TAGEM_AND_BAGEM");
|
||||
completed_mission(game::LEVEL_INVASION, "ROYAL_WITH_CHEESE");
|
||||
completed_mission(game::LEVEL_GULAG, "SOAP_ON_A_ROPE");
|
||||
completed_mission(game::LEVEL_CONTINGENCY, "DESPERATE_TIMES");
|
||||
completed_mission(game::LEVEL_DC_WHITEHOUSE, "HOUSTON_WE_HAVE_A_PROBLEM");
|
||||
completed_mission(game::LEVEL_ESTATE, "THE_PAWN");
|
||||
completed_mission(game::LEVEL_BONEYARD, "OUT_OF_THE_FRYING_PAN");
|
||||
completed_mission(game::LEVEL_ENDING, "FOR_THE_RECORD");
|
||||
|
||||
add_veteran_achievement(game::LEVEL_TRAINER, "FIRST_DAY_OF_SCHOOL");
|
||||
add_veteran_achievement(game::LEVEL_ROADKILL, "FIRST_DAY_OF_SCHOOL");
|
||||
add_veteran_achievement(game::LEVEL_CLIFFHANGER, "BLACK_DIAMOND");
|
||||
add_veteran_achievement(game::LEVEL_FAVELA, "TURISTAS");
|
||||
add_veteran_achievement(game::LEVEL_INVASION, "RED_DAWN");
|
||||
add_veteran_achievement(game::LEVEL_FAVELA_ESCAPE, "TURISTAS");
|
||||
add_veteran_achievement(game::LEVEL_ARCADIA, "RED_DAWN");
|
||||
add_veteran_achievement(game::LEVEL_OILRIG, "PRISONER_627");
|
||||
add_veteran_achievement(game::LEVEL_GULAG, "PRISONER_627");
|
||||
add_veteran_achievement(game::LEVEL_DCBURNING, "HOME_COMING");
|
||||
add_veteran_achievement(game::LEVEL_CONTINGENCY, "ENDS_JUSTIFY_THE_MEANS");
|
||||
add_veteran_achievement(game::LEVEL_DCEMP, "HOME_COMING");
|
||||
add_veteran_achievement(game::LEVEL_DC_WHITEHOUSE, "HOME_COMING");
|
||||
add_veteran_achievement(game::LEVEL_ESTATE, "QUEEN_TAKES_ROOK");
|
||||
add_veteran_achievement(game::LEVEL_BONEYARD, "QUEEN_TAKES_ROOK");
|
||||
add_veteran_achievement(game::LEVEL_AF_CAVES, "OFF_THE_GRID");
|
||||
add_veteran_achievement(game::LEVEL_AF_CHASE, "OFF_THE_GRID");
|
||||
add_veteran_achievement(game::LEVEL_ENDING, "OFF_THE_GRID");
|
||||
|
||||
give_veteran_achievements();
|
||||
give_completed_campaign_achievement("THE_PRICE_OF_WAR");
|
||||
|
||||
write_achievements(&file);
|
||||
}
|
||||
}
|
||||
|
||||
void get_achievements(achievement_file_t* file)
|
||||
@ -252,6 +373,8 @@ namespace achievements
|
||||
{
|
||||
utils::hook::jump(0x1404B6240, scr_give_achievement_stub);
|
||||
|
||||
scheduler::once(give_mission_achievements, scheduler::main);
|
||||
|
||||
command::add("reset_achievements", []
|
||||
{
|
||||
achievement_file_t file{};
|
||||
|
@ -1728,6 +1728,63 @@ namespace game
|
||||
|
||||
static_assert(sizeof(physical_memory) == 0x530);
|
||||
|
||||
union GamerProfileDataUnion
|
||||
{
|
||||
unsigned __int8 byteVal;
|
||||
bool boolVal;
|
||||
__int16 shortVal;
|
||||
int intVal;
|
||||
float floatVal;
|
||||
const char* stringVal;
|
||||
};
|
||||
|
||||
enum level_number
|
||||
{
|
||||
LEVEL_TRAINER,
|
||||
LEVEL_ROADKILL,
|
||||
LEVEL_CLIFFHANGER,
|
||||
LEVEL_AIRPORT,
|
||||
LEVEL_FAVELA,
|
||||
|
||||
LEVEL_INVASION,
|
||||
LEVEL_FAVELA_ESCAPE,
|
||||
LEVEL_ARCADIA,
|
||||
LEVEL_OILRIG,
|
||||
LEVEL_GULAG,
|
||||
LEVEL_DCBURNING,
|
||||
|
||||
LEVEL_CONTINGENCY,
|
||||
LEVEL_DCEMP,
|
||||
LEVEL_DC_WHITEHOUSE,
|
||||
LEVEL_ESTATE,
|
||||
LEVEL_BONEYARD,
|
||||
LEVEL_AF_CAVES,
|
||||
LEVEL_AF_CHASE,
|
||||
|
||||
LEVEL_ENDING,
|
||||
|
||||
LEVEL_COUNT,
|
||||
};
|
||||
|
||||
enum GamerProfileDataType : __int32
|
||||
{
|
||||
TYPE_INVALID = 0x0,
|
||||
TYPE_BYTE = 0x1,
|
||||
TYPE_BOOL = 0x2,
|
||||
TYPE_SHORT = 0x3,
|
||||
TYPE_INT = 0x4,
|
||||
TYPE_FLOAT = 0x5,
|
||||
TYPE_STRING = 0x6,
|
||||
TYPE_BUFFER = 0x7,
|
||||
TYPE_FLAG = 0x8,
|
||||
};
|
||||
|
||||
struct GamerProfileData
|
||||
{
|
||||
GamerProfileDataType type;
|
||||
GamerProfileDataUnion u;
|
||||
};
|
||||
|
||||
namespace hks
|
||||
{
|
||||
struct lua_State;
|
||||
|
Loading…
Reference in New Issue
Block a user