mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-25 16:04:28 -04:00
Merge pull request #599 from TwilitRealm/50_achievements
More Achievements
This commit is contained in:
@@ -1845,6 +1845,12 @@ inline void dComIfGs_addDeathCount() {
|
||||
g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().addDeathCount();
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
inline u16 dComIfGs_getDeathCount() {
|
||||
return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getDeathCount();
|
||||
}
|
||||
#endif
|
||||
|
||||
inline char* dComIfGs_getPlayerName() {
|
||||
return g_dComIfG_gameInfo.info.getPlayer().getPlayerInfo().getPlayerName();
|
||||
}
|
||||
|
||||
@@ -486,6 +486,9 @@ public:
|
||||
mDeathCount++;
|
||||
}
|
||||
}
|
||||
#if TARGET_PC
|
||||
u16 getDeathCount() const { return mDeathCount; }
|
||||
#endif
|
||||
char* getPlayerName() const { return const_cast<char*>(mPlayerName); }
|
||||
void setPlayerName(const char* i_name) {
|
||||
#if AVOID_UB
|
||||
|
||||
@@ -12,9 +12,8 @@
|
||||
namespace dusk {
|
||||
|
||||
enum class AchievementCategory : uint8_t {
|
||||
Story,
|
||||
Collection,
|
||||
Challenge,
|
||||
Collection,
|
||||
Minigame,
|
||||
Misc,
|
||||
Glitched
|
||||
|
||||
@@ -17,6 +17,7 @@ body {
|
||||
window {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
max-width: 1088dp;
|
||||
@@ -291,6 +292,19 @@ icon.question-mark {
|
||||
decorator: text("" center center);
|
||||
}
|
||||
|
||||
.achievement-total {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 64dp;
|
||||
height: 64dp;
|
||||
line-height: 64dp;
|
||||
font-family: "Fira Sans Condensed";
|
||||
font-weight: bold;
|
||||
font-size: 16dp;
|
||||
color: rgba(224, 219, 200, 55%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.achievement-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
@@ -205,6 +205,9 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm
|
||||
dComIfGp_setItemLifeCount(-i_dmgAmount, 0);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
dusk::AchievementSystem::get().signal("player_damaged");
|
||||
#endif
|
||||
onResetFlg1(RFLG1_DAMAGE_IMPACT);
|
||||
mSwordUpTimer = 0;
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
#include "d/actor/d_a_e_pz.h"
|
||||
#include "d/actor/d_a_horse.h"
|
||||
#include "d/actor/d_a_hozelda.h"
|
||||
#if TARGET_PC
|
||||
#include "dusk/achievements.h"
|
||||
#endif
|
||||
|
||||
int daArrow_c::createHeap() {
|
||||
J3DModelData* model_data;
|
||||
@@ -92,7 +95,12 @@ void daArrow_c::atHitCallBack(dCcD_GObjInf* i_atObjInf, fopAc_ac_c* i_tgActor, d
|
||||
if (dist_to_hitpos < field_0x998) {
|
||||
field_0x998 = dist_to_hitpos;
|
||||
mHitAcID = fopAcM_GetID(i_tgActor);
|
||||
|
||||
#if TARGET_PC
|
||||
if (fopAcM_GetGroup(i_tgActor) == fopAc_ENEMY_e &&
|
||||
current.pos.abs(mStartPos) > 10000.0f) {
|
||||
dusk::AchievementSystem::get().signal("arrow_hit_100m");
|
||||
}
|
||||
#endif
|
||||
if (mArrowType == 1) {
|
||||
field_0x9a8 = *hit_pos_p;
|
||||
} else if (i_tgObjInf->ChkTgShield()) {
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/settings.h"
|
||||
#if TARGET_PC
|
||||
#include "dusk/achievements.h"
|
||||
#endif
|
||||
|
||||
class daB_GND_HIO_c : public JORReflexible {
|
||||
public:
|
||||
@@ -1289,6 +1292,9 @@ static void b_gnd_g_wait(b_gnd_class* i_this) {
|
||||
if (i_this->mMoveMode < 5 && i_this->mPlayerDistXZ < 600.0f) {
|
||||
i_this->mMoveMode = 5;
|
||||
i_this->field_0xc44[0] = 10;
|
||||
#if TARGET_PC
|
||||
dusk::AchievementSystem::get().signal("ganondorf_fishing_rod");
|
||||
#endif
|
||||
}
|
||||
} else if (i_this->mMoveMode == 5) {
|
||||
i_this->mMoveMode = 6;
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#include "c/c_damagereaction.h"
|
||||
#include "f_op/f_op_actor_enemy.h"
|
||||
#include "f_op/f_op_camera_mng.h"
|
||||
#if TARGET_PC
|
||||
#include "dusk/achievements.h"
|
||||
#endif
|
||||
|
||||
class daE_TH_HIO_c : public JORReflexible {
|
||||
public:
|
||||
@@ -542,6 +545,7 @@ static void damage_check(e_th_class* i_this) {
|
||||
if (i_this->field_0x6a4 == 0 && i_this->mAction != ACTION_SPIN) {
|
||||
daPy_py_c* player = (daPy_py_c*)dComIfGp_getPlayer(0);
|
||||
OS_REPORT("E_th HP1 %d\n", i_this->health);
|
||||
s16 prevHealth = i_this->health;
|
||||
cc_at_check(i_this, &i_this->mAtInfo);
|
||||
OS_REPORT("E_th HP2 %d\n", i_this->health);
|
||||
|
||||
@@ -554,6 +558,11 @@ static void damage_check(e_th_class* i_this) {
|
||||
dComIfGs_onOneZoneSwitch(3, -1);
|
||||
|
||||
if (i_this->health <= 0) {
|
||||
#if TARGET_PC
|
||||
if (prevHealth == i_this->field_0x560) {
|
||||
dusk::AchievementSystem::get().signal("dark_hammer_one_hit");
|
||||
}
|
||||
#endif
|
||||
i_this->mAction = ACTION_END;
|
||||
i_this->mMode = 0;
|
||||
i_this->field_0x68a |= 4;
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include "d/d_s_play.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "f_op/f_op_actor_mng.h"
|
||||
#if TARGET_PC
|
||||
#include "dusk/achievements.h"
|
||||
#endif
|
||||
|
||||
static int plCutLRC[58] = {
|
||||
0, //
|
||||
@@ -434,6 +437,11 @@ fopAc_ac_c* cc_at_check(fopAc_ac_c* i_enemy, dCcU_AtInfo* i_AtInfo) {
|
||||
if (i_AtInfo->mAttackPower != 0 && i_enemy->health <= 0) {
|
||||
i_AtInfo->mHitStatus = 2;
|
||||
i_enemy->health = 0;
|
||||
#if TARGET_PC
|
||||
if (fopAcM_GetGroup(i_enemy) == fopAc_ENEMY_e) {
|
||||
dusk::AchievementSystem::get().signal("enemy_killed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int uvar8;
|
||||
|
||||
+694
-135
@@ -1,13 +1,21 @@
|
||||
#include "dusk/achievements.h"
|
||||
#include "d/actor/d_a_alink.h"
|
||||
#include "d/actor/d_a_npc4.h"
|
||||
#include "d/actor/d_a_player.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "d/d_demo.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "dusk/io.hpp"
|
||||
#include "dusk/main.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "d/d_item_data.h"
|
||||
#include "d/d_map_path_fmap.h"
|
||||
#include "d/d_stage.h"
|
||||
#include "d/d_menu_fmap.h"
|
||||
#include "JSystem/JKernel/JKRArchive.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "d/actor/d_a_alink.h"
|
||||
#include "d/actor/d_a_ni.h"
|
||||
#include "d/actor/d_a_npc4.h"
|
||||
#include "d/actor/d_a_b_ob.h"
|
||||
#include "d/actor/d_a_player.h"
|
||||
#include "d/d_demo.h"
|
||||
#include "dusk/ui/ui.hpp"
|
||||
#include "f_pc/f_pc_name.h"
|
||||
#include "f_op/f_op_actor_mng.h"
|
||||
#include "f_pc/f_pc_name.h"
|
||||
|
||||
@@ -18,6 +26,14 @@ namespace dusk {
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
static void* s_cucco_play_search(void* i_actor, void*) {
|
||||
if (!fopAcM_IsActor(i_actor) || fopAcM_GetName((fopAc_ac_c*)i_actor) != fpcNm_NI_e) {
|
||||
return nullptr;
|
||||
}
|
||||
auto* ni = static_cast<ni_class*>(i_actor);
|
||||
return ni->mAction == ACTION_PLAY_e ? i_actor : nullptr;
|
||||
}
|
||||
|
||||
static void checkGoatHerding(Achievement& a, int32_t threshMs) {
|
||||
if (dMeter2Info_getMaxCount() != 20 || dMeter2Info_getNowCount() != 20) {
|
||||
return;
|
||||
@@ -32,12 +48,13 @@ static constexpr auto ACHIEVEMENTS_FILENAME = "achievements.json";
|
||||
|
||||
std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
return {
|
||||
// Challenge
|
||||
{
|
||||
{
|
||||
"hero_of_twilight",
|
||||
"Hero of Twilight",
|
||||
"Deliver the finishing blow to Ganondorf.",
|
||||
AchievementCategory::Story,
|
||||
AchievementCategory::Challenge,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
@@ -48,6 +65,445 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"completionist",
|
||||
"Completionist",
|
||||
"Complete the game after collecting all equipment, heart containers, portals, bugs, poes, and hidden skills.",
|
||||
AchievementCategory::Challenge,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link == nullptr || link->mProcID != daAlink_c::PROC_GANON_FINISH) {
|
||||
return;
|
||||
}
|
||||
if (dComIfGs_getMaxLife() < 100) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (!dComIfGs_isCollectMirror(i)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (!dComIfGs_isCollectCrystal(i)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
static const u16 skillBits[] = {
|
||||
dSv_event_flag_c::F_0338, dSv_event_flag_c::F_0339,
|
||||
dSv_event_flag_c::F_0340, dSv_event_flag_c::F_0341,
|
||||
dSv_event_flag_c::F_0342, dSv_event_flag_c::F_0343,
|
||||
dSv_event_flag_c::F_0344
|
||||
};
|
||||
for (u16 bit : skillBits) {
|
||||
if (!dComIfGs_isEventBit(bit)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dComIfGs_checkGetInsectNum() < 24) {
|
||||
return;
|
||||
}
|
||||
if (dComIfGs_getPohSpiritNum() < 60) {
|
||||
return;
|
||||
}
|
||||
if (dComIfGs_getWalletSize() < 2) {
|
||||
return;
|
||||
}
|
||||
if (dComIfGs_getArrowMax() < 100) {
|
||||
return;
|
||||
}
|
||||
if (!dComIfGs_isCollectSword(COLLECT_MASTER_SWORD)) {
|
||||
return;
|
||||
}
|
||||
if (!dComIfGs_isCollectShield(COLLECT_HYLIAN_SHIELD)) {
|
||||
return;
|
||||
}
|
||||
if (!dComIfGs_isCollectClothes(KOKIRI_CLOTHES_FLAG)) {
|
||||
return;
|
||||
}
|
||||
if (!dComIfGs_isItemFirstBit(dItemNo_WEAR_ZORA_e)) {
|
||||
return;
|
||||
}
|
||||
if (!dComIfGs_isItemFirstBit(dItemNo_ARMOR_e)) {
|
||||
return;
|
||||
}
|
||||
static const struct { int stage; int sw; } warpPortals[] = {
|
||||
{ dStage_SaveTbl_ORDON, 52 }, // Ordon Spring
|
||||
{ dStage_SaveTbl_FARON, 71 }, // South Faron Woods
|
||||
{ dStage_SaveTbl_FARON, 2 }, // North Faron Woods
|
||||
{ dStage_SaveTbl_GROVE, 100 }, // Sacred Grove
|
||||
{ dStage_SaveTbl_FIELD, 21 }, // Gorge
|
||||
{ dStage_SaveTbl_ELDIN, 31 }, // Kakariko Village
|
||||
{ dStage_SaveTbl_ELDIN, 21 }, // Death Mountain
|
||||
{ dStage_SaveTbl_FIELD, 99 }, // Bridge of Eldin
|
||||
{ dStage_SaveTbl_FIELD, 3 }, // Castle Town
|
||||
{ dStage_SaveTbl_LANAYRU, 10 }, // Lake Hylia
|
||||
{ dStage_SaveTbl_LANAYRU, 2 }, // Zora's Domain
|
||||
{ dStage_SaveTbl_LANAYRU, 21 }, // Upper Zora's River
|
||||
{ dStage_SaveTbl_SNOWPEAK, 21 }, // Snowpeak
|
||||
{ dStage_SaveTbl_DESERT, 21 }, // Gerudo Mesa
|
||||
{ dStage_SaveTbl_DESERT, 40 }, // Mirror Chamber
|
||||
};
|
||||
for (const auto& p : warpPortals) {
|
||||
if (!g_dComIfG_gameInfo.info.getSavedata().getSave(p.stage).getBit().isSwitch(p.sw)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dComIfGs_getCollectSmell() == dItemNo_NONE_e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dMeter2Info_getRecieveLetterNum() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasJournal = false;
|
||||
for (int fi = 0; fi < 6; ++fi) {
|
||||
if (dComIfGs_getFishNum(fi) != 0) {
|
||||
hasJournal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasJournal) {
|
||||
return;
|
||||
}
|
||||
|
||||
int bottleCount = 0;
|
||||
for (int i = 0; i < dSv_player_item_c::BOTTLE_MAX; ++i) {
|
||||
if (dComIfGs_getItem(SLOT_11 + i, false) != dItemNo_NONE_e) {
|
||||
bottleCount++;
|
||||
}
|
||||
}
|
||||
if (bottleCount < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
int bombBagCount = 0;
|
||||
for (int i = 0; i < dSv_player_item_c::BOMB_BAG_MAX; ++i) {
|
||||
if (dComIfGs_getItem(SLOT_15 + i, false) != dItemNo_NONE_e) {
|
||||
bombBagCount++;
|
||||
}
|
||||
}
|
||||
if (bombBagCount < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasJewelRod = false;
|
||||
for (int slot = 0; slot < 24 && !hasJewelRod; ++slot) {
|
||||
const u8 item = dComIfGs_getItem(slot, false);
|
||||
if (item == dItemNo_JEWEL_ROD_e || item == dItemNo_JEWEL_BEE_ROD_e || item == dItemNo_JEWEL_WORM_ROD_e) {
|
||||
hasJewelRod = true;
|
||||
}
|
||||
}
|
||||
if (!hasJewelRod) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const u8 requiredWheelItems[] = {
|
||||
dItemNo_BOOMERANG_e,
|
||||
dItemNo_BOW_e,
|
||||
dItemNo_W_HOOKSHOT_e,
|
||||
dItemNo_SPINNER_e,
|
||||
dItemNo_IRONBALL_e,
|
||||
dItemNo_COPY_ROD_e,
|
||||
dItemNo_HVY_BOOTS_e,
|
||||
dItemNo_KANTERA_e,
|
||||
dItemNo_PACHINKO_e,
|
||||
dItemNo_HAWK_EYE_e,
|
||||
dItemNo_ANCIENT_DOCUMENT_e,
|
||||
dItemNo_HORSE_FLUTE_e,
|
||||
};
|
||||
for (u8 required : requiredWheelItems) {
|
||||
bool found = false;
|
||||
for (int slot = 0; slot < 24; ++slot) {
|
||||
if (dComIfGs_getItem(slot, false) == required) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
a.progress = 1;
|
||||
},
|
||||
{}
|
||||
},
|
||||
// Collection
|
||||
{
|
||||
{
|
||||
"princess_of_bugs",
|
||||
"The Princess of Bugs",
|
||||
"Deliver all 24 golden bugs to Agitha.",
|
||||
AchievementCategory::Collection,
|
||||
true, 24, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dComIfGs_checkGetInsectNum();
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"all_poes",
|
||||
"Poe Collector",
|
||||
"Collect all 60 Poe Souls.",
|
||||
AchievementCategory::Collection,
|
||||
true, 60, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dComIfGs_getPohSpiritNum();
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"hylian_loach",
|
||||
"Legendary Catch",
|
||||
"Catch a Hylian Loach.",
|
||||
AchievementCategory::Collection,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (dComIfGs_getFishNum(1) > 0) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"all_fish",
|
||||
"Gone Fishin'",
|
||||
"Catch all 6 species of fish.",
|
||||
AchievementCategory::Collection,
|
||||
true, 6, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
int nUniqueFish = 0;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
if (dComIfGs_getFishNum(i) != 0) {
|
||||
nUniqueFish++;
|
||||
}
|
||||
}
|
||||
a.progress = nUniqueFish;
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"a_big_heart",
|
||||
"A Big Heart",
|
||||
"Reach maximum health with all 20 heart containers.",
|
||||
AchievementCategory::Collection,
|
||||
true, 20, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dComIfGs_getMaxLife() / 5;
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"all_bottles",
|
||||
"Glassware Guardian",
|
||||
"Obtain all 4 bottles.",
|
||||
AchievementCategory::Collection,
|
||||
true, 4, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (daPy_getPlayerActorClass() == nullptr) {
|
||||
return;
|
||||
}
|
||||
int count = 0;
|
||||
for (int i = 0; i < dSv_player_item_c::BOTTLE_MAX; ++i) {
|
||||
if (dComIfGs_getItem(SLOT_11 + i, false) != dItemNo_NONE_e) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
a.progress = count;
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"all_hidden_skills",
|
||||
"Master of Secrets",
|
||||
"Learn all 7 Hidden Skills.",
|
||||
AchievementCategory::Collection,
|
||||
true, 7, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
static const u16 skillBits[] = {
|
||||
dSv_event_flag_c::F_0338, dSv_event_flag_c::F_0339,
|
||||
dSv_event_flag_c::F_0340, dSv_event_flag_c::F_0341,
|
||||
dSv_event_flag_c::F_0342, dSv_event_flag_c::F_0343,
|
||||
dSv_event_flag_c::F_0344
|
||||
};
|
||||
int count = 0;
|
||||
for (u16 bit : skillBits) {
|
||||
if (dComIfGs_isEventBit(bit)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
a.progress = count;
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"all_letters",
|
||||
"We Deliver!",
|
||||
"Collect all 16 postman letters.",
|
||||
AchievementCategory::Collection,
|
||||
true, 16, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dMeter2Info_getRecieveLetterNum();
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"cave_of_ordeals",
|
||||
"Conqueror of Ordeals",
|
||||
"Clear all 50 floors of the Cave of Ordeals.",
|
||||
AchievementCategory::Challenge,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (daNpcF_chkEvtBit(0x1F9)) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"cave_of_ordeals_heartless",
|
||||
"Indomitable",
|
||||
"Clear all 50 floors of the Cave of Ordeals with only 3 heart containers.",
|
||||
AchievementCategory::Challenge,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (daNpcF_chkEvtBit(0x1F9) && dComIfGs_getMaxLife() <= 15) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"speedrun_12h",
|
||||
"Been There Done That",
|
||||
"Defeat Ganondorf with a total save file play time under 12 hours.",
|
||||
AchievementCategory::Challenge,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link == nullptr || link->mProcID != daAlink_c::PROC_GANON_FINISH) {
|
||||
return;
|
||||
}
|
||||
const int64_t ticks = (static_cast<int64_t>(OSGetTime()) - dComIfGs_getSaveStartTime()) + dComIfGs_getSaveTotalTime();
|
||||
if (ticks / OS_TIMER_CLOCK < 12 * 3600) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"speedrun_8h",
|
||||
"Swift Blade",
|
||||
"Defeat Ganondorf with a total save file play time under 6 hours.",
|
||||
AchievementCategory::Challenge,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link == nullptr || link->mProcID != daAlink_c::PROC_GANON_FINISH) {
|
||||
return;
|
||||
}
|
||||
const int64_t ticks = (static_cast<int64_t>(OSGetTime()) - dComIfGs_getSaveStartTime()) + dComIfGs_getSaveTotalTime();
|
||||
if (ticks / OS_TIMER_CLOCK < 8 * 3600) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"dark_hammer_one_hit",
|
||||
"Mortal Edge",
|
||||
"Defeat Dark Hammer in a single hit.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (AchievementSystem::get().hasSignal("dark_hammer_one_hit")) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"no_deaths_clear",
|
||||
"Deathless",
|
||||
"Defeat Ganondorf with 0 deaths on your save file.",
|
||||
AchievementCategory::Challenge,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link == nullptr || link->mProcID != daAlink_c::PROC_GANON_FINISH) {
|
||||
return;
|
||||
}
|
||||
if (dComIfGs_getDeathCount() == 0) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"untouchable",
|
||||
"Untouchable",
|
||||
"Kill 25 enemies in a row without taking damage.",
|
||||
AchievementCategory::Challenge,
|
||||
true, 25, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
auto& sys = AchievementSystem::get();
|
||||
if (sys.hasSignal("player_damaged")) {
|
||||
a.progress = 0;
|
||||
}
|
||||
if (sys.hasSignal("enemy_killed")) {
|
||||
a.progress++;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"bow_100m_hit",
|
||||
"Long Shot",
|
||||
"Hit an enemy from over 100 meters away with the bow.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (AchievementSystem::get().hasSignal("arrow_hit_100m")) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
// Minigame
|
||||
{
|
||||
{
|
||||
"plumm_max",
|
||||
@@ -134,14 +590,16 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
},
|
||||
{
|
||||
{
|
||||
"cave_of_ordeals",
|
||||
"Conqueror of Ordeals",
|
||||
"Clear all 50 floors of the Cave of Ordeals.",
|
||||
AchievementCategory::Challenge,
|
||||
"snowboard_70s",
|
||||
"Downhill Dash",
|
||||
"Finish the snowboarding minigame in under 70 seconds.",
|
||||
AchievementCategory::Minigame,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (daNpcF_chkEvtBit(0x1F9)) {
|
||||
const int32_t bestMs = dComIfGs_getRaceGameTime();
|
||||
if (dComIfGs_isEventBit(dSv_event_flag_c::F_0481) &&
|
||||
bestMs > 0 && bestMs <= 70000) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
@@ -149,54 +607,37 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
},
|
||||
{
|
||||
{
|
||||
"cave_of_ordeals_heartless",
|
||||
"Indomitable",
|
||||
"Clear all 50 floors of the Cave of Ordeals with only 3 heart containers.",
|
||||
AchievementCategory::Challenge,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (daNpcF_chkEvtBit(0x1F9) && dComIfGs_getMaxLife() <= 15) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"speedrun_12h",
|
||||
"Been There Done That",
|
||||
"Defeat Ganondorf with a total save file play time under 12 hours.",
|
||||
AchievementCategory::Challenge,
|
||||
"canoe_perfect",
|
||||
"River Raider",
|
||||
"Achieve a perfect score in the canoe minigame.",
|
||||
AchievementCategory::Minigame,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link == nullptr || link->mProcID != daAlink_c::PROC_GANON_FINISH) {
|
||||
if (link == nullptr) {
|
||||
return;
|
||||
}
|
||||
const int64_t ticks = (static_cast<int64_t>(OSGetTime()) - dComIfGs_getSaveStartTime()) + dComIfGs_getSaveTotalTime();
|
||||
if (ticks / OS_TIMER_CLOCK < 12 * 3600) {
|
||||
static bool wasInCanoe = false;
|
||||
bool inCanoe = link->mProcID >= daAlink_c::PROC_CANOE_RIDE &&
|
||||
link->mProcID <= daAlink_c::PROC_CANOE_KANDELAAR_POUR;
|
||||
if (wasInCanoe && !inCanoe && dMeter2Info_getNowCount() >= 30) {
|
||||
a.progress = 1;
|
||||
}
|
||||
wasInCanoe = inCanoe;
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"speedrun_8h",
|
||||
"Swift Blade",
|
||||
"Defeat Ganondorf with a total save file play time under 6 hours.",
|
||||
AchievementCategory::Challenge,
|
||||
"star_2_under_40s",
|
||||
"Rising Star",
|
||||
"Complete the STAR Prize 2 minigame in under 40 seconds.",
|
||||
AchievementCategory::Minigame,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link == nullptr || link->mProcID != daAlink_c::PROC_GANON_FINISH) {
|
||||
return;
|
||||
}
|
||||
const int64_t ticks = (static_cast<int64_t>(OSGetTime()) - dComIfGs_getSaveStartTime()) + dComIfGs_getSaveTotalTime();
|
||||
if (ticks / OS_TIMER_CLOCK < 8 * 3600) {
|
||||
if(dComIfGs_getHookGameTime() > 0 && dComIfGs_getHookGameTime() <= 40000) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
@@ -204,77 +645,20 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
},
|
||||
{
|
||||
{
|
||||
"princess_of_bugs",
|
||||
"The Princess of Bugs",
|
||||
"Deliver all 24 golden bugs to Agitha.",
|
||||
AchievementCategory::Collection,
|
||||
true, 24, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dComIfGs_checkGetInsectNum();
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"all_poes",
|
||||
"Poe Collector",
|
||||
"Collect all 60 Poe Souls.",
|
||||
AchievementCategory::Collection,
|
||||
true, 60, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dComIfGs_getPohSpiritNum();
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"hylian_loach",
|
||||
"Legendary Catch",
|
||||
"Catch a Hylian Loach.",
|
||||
AchievementCategory::Collection,
|
||||
"star_2_under_30s",
|
||||
"Shooting Star",
|
||||
"Complete the STAR Prize 2 minigame in under 30 seconds.",
|
||||
AchievementCategory::Minigame,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (dComIfGs_getFishNum(1) > 0) {
|
||||
if(dComIfGs_getHookGameTime() > 0 && dComIfGs_getHookGameTime() <= 30000) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"all_fish",
|
||||
"Gone Fishin'",
|
||||
"Catch all 6 species of fish.",
|
||||
AchievementCategory::Collection,
|
||||
true, 6, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
int nUniqueFish = 0;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
if (dComIfGs_getFishNum(i) != 0) {
|
||||
nUniqueFish++;
|
||||
}
|
||||
}
|
||||
a.progress = nUniqueFish;
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"a_big_heart",
|
||||
"A Big Heart",
|
||||
"Reach maximum health with all 20 heart containers.",
|
||||
AchievementCategory::Collection,
|
||||
true, 20, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dComIfGs_getMaxLife() / 5;
|
||||
},
|
||||
{}
|
||||
},
|
||||
// Misc
|
||||
{
|
||||
{
|
||||
"friendly_fire",
|
||||
@@ -327,6 +711,87 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"email_me",
|
||||
"Email Me",
|
||||
"Read a letter during the Dark Beast Ganon fight.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
void* dbgExists = fopAcM_SearchByName(fpcNm_B_MGN_e);
|
||||
if (dbgExists && AchievementSystem::get().hasSignal("open_letter")) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"heavy_hitter",
|
||||
"Heavy Hitter",
|
||||
"Wear the Iron Boots during the end credits.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link == nullptr || link->mProcID != daAlink_c::PROC_GANON_FINISH) {
|
||||
return;
|
||||
}
|
||||
if (daPy_getPlayerActorClass()->checkEquipHeavyBoots()) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"fishing_rod_ganondorf",
|
||||
"Here Fishy Fishy",
|
||||
"Confuse Ganondorf with the fishing rod.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (AchievementSystem::get().hasSignal("ganondorf_fishing_rod")) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"steal_from_trill",
|
||||
"Petty Theft",
|
||||
"Steal from Trill.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (dComIfGs_isEventBit(dSv_event_flag_c::F_0758)) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"cucco_control",
|
||||
"Cucco Whisperer",
|
||||
"Take control of a cucco.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (fopAcM_Search(s_cucco_play_search, nullptr) != nullptr) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
// Glitched
|
||||
{
|
||||
{
|
||||
"back_in_time",
|
||||
@@ -377,19 +842,6 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"ultimate_delivery",
|
||||
"The Ultimate Delivery",
|
||||
"Have all 16 postman letters at the same time.",
|
||||
AchievementCategory::Glitched,
|
||||
true, 16, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dMeter2Info_getRecieveLetterNum();
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"speedrun_4h",
|
||||
@@ -412,15 +864,85 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
},
|
||||
{
|
||||
{
|
||||
"email_me",
|
||||
"Email Me",
|
||||
"Read a letter during the Dark Beast Ganon fight.",
|
||||
AchievementCategory::Misc,
|
||||
"no_fish_suit",
|
||||
"No Fish Suit No Problem",
|
||||
"Defeat Morpheel without equipping Zora Armor.",
|
||||
AchievementCategory::Glitched,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
void* dbgExists = fopAcM_SearchByName(fpcNm_B_MGN_e);
|
||||
if (dbgExists && AchievementSystem::get().hasSignal("open_letter")) {
|
||||
static bool prevMorpheelAlive = false;
|
||||
static bool inArena = false;
|
||||
static bool zoraWorn = false;
|
||||
const auto* morpheel = static_cast<const b_ob_class*>(fopAcM_SearchByName(fpcNm_B_OB_e));
|
||||
const bool morpheelAlive = morpheel != nullptr && morpheel->mAnmID != 0x14;
|
||||
const bool morpheelDead = morpheel != nullptr && morpheel->mAnmID == 0x14;
|
||||
const bool lakebedCleared = dComIfGs_isEventBit(dSv_event_flag_c::M_045);
|
||||
|
||||
if (inArena && morpheel == nullptr) {
|
||||
zoraWorn = false;
|
||||
}
|
||||
|
||||
if (morpheelAlive && !lakebedCleared) {
|
||||
inArena = true;
|
||||
if (daPy_py_c::checkZoraWearFlg()) {
|
||||
zoraWorn = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (prevMorpheelAlive && morpheelDead && inArena && !zoraWorn) {
|
||||
a.progress = 1;
|
||||
}
|
||||
|
||||
prevMorpheelAlive = morpheelAlive;
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"null_item",
|
||||
"Null Item",
|
||||
"Obtain the mysterious black rupee in the item wheel.",
|
||||
AchievementCategory::Glitched,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (daPy_getPlayerActorClass() == nullptr) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 24; ++i) {
|
||||
if (dComIfGs_getItem(i, false) == 0x00) {
|
||||
a.progress = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"stallord_skip",
|
||||
"Stallord Skip",
|
||||
"Leave Stallord's arena through the exit without defeating Stallord.",
|
||||
AchievementCategory::Glitched,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
static bool seenStallord = false;
|
||||
if (strcmp(dComIfGp_getStartStageName(), "D_MN10A") != 0) {
|
||||
seenStallord = false;
|
||||
return;
|
||||
}
|
||||
if (dComIfGs_isEventBit(dSv_event_flag_c::F_0265)) {
|
||||
seenStallord = false;
|
||||
return;
|
||||
}
|
||||
if (fopAcM_SearchByName(fpcNm_B_DS_e) != nullptr) {
|
||||
seenStallord = true;
|
||||
}
|
||||
if (seenStallord &&
|
||||
dComIfGp_isEnableNextStage() &&
|
||||
strcmp(dComIfGp_getNextStageName(), "F_SP125") == 0) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
@@ -428,22 +950,59 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
},
|
||||
{
|
||||
{
|
||||
"heavy-hitter",
|
||||
"Heavy Hitter",
|
||||
"Wear the Iron Boots during the end credits.",
|
||||
AchievementCategory::Misc,
|
||||
"lakebed_before_lanayru",
|
||||
"White Midna Glitch",
|
||||
"Clear the Lakebed Temple before clearing Lanayru's Twilight.",
|
||||
AchievementCategory::Glitched,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link == nullptr || link->mProcID != daAlink_c::PROC_GANON_FINISH) {
|
||||
return;
|
||||
}
|
||||
if (daPy_getPlayerActorClass()->checkEquipHeavyBoots()) {
|
||||
if (dComIfGs_isEventBit(dSv_event_flag_c::M_045) &&
|
||||
!dComIfGs_isDarkClearLV(2)) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"early_hidden_village",
|
||||
"Quick Detour",
|
||||
"Rescue the Hidden Village before clearing Goron Mines.",
|
||||
AchievementCategory::Glitched,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (dComIfGs_isEventBit(dSv_event_flag_c::F_0278) &&
|
||||
!dComIfGs_isEventBit(dSv_event_flag_c::M_031)) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"forest_temple_no_boomerang",
|
||||
"Must Have Been The Wind",
|
||||
"Complete the Forest Temple without obtaining the Gale Boomerang.",
|
||||
AchievementCategory::Glitched,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (!dComIfGs_isEventBit(dSv_event_flag_c::M_022)) {
|
||||
return;
|
||||
}
|
||||
if (daPy_getPlayerActorClass() == nullptr) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 24; ++i) {
|
||||
if (dComIfGs_getItem(i, false) == dItemNo_BOOMERANG_e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
a.progress = 1;
|
||||
},
|
||||
{}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,9 +16,8 @@ struct CategoryInfo {
|
||||
};
|
||||
|
||||
constexpr CategoryInfo kCategories[] = {
|
||||
{AchievementCategory::Story, "Story"},
|
||||
{AchievementCategory::Collection, "Collection"},
|
||||
{AchievementCategory::Challenge, "Challenge"},
|
||||
{AchievementCategory::Collection, "Collection"},
|
||||
{AchievementCategory::Minigame, "Minigame"},
|
||||
{AchievementCategory::Misc, "Misc"},
|
||||
{AchievementCategory::Glitched, "Glitched"},
|
||||
@@ -114,6 +113,13 @@ private:
|
||||
AchievementsWindow::AchievementsWindow() {
|
||||
const auto all = AchievementSystem::get().getAchievements();
|
||||
|
||||
{
|
||||
auto elem = mDocument->CreateElement("div");
|
||||
elem->SetClass("achievement-total", true);
|
||||
mTotalEl = mRoot->AppendChild(std::move(elem));
|
||||
updateTotal();
|
||||
}
|
||||
|
||||
for (const auto& catInfo : kCategories) {
|
||||
int catTotal = 0;
|
||||
for (const auto& a : all) {
|
||||
@@ -201,8 +207,25 @@ void AchievementsWindow::update() {
|
||||
if (dirty) {
|
||||
mSnapshot = current;
|
||||
refresh_active_tab();
|
||||
updateTotal();
|
||||
}
|
||||
Window::update();
|
||||
}
|
||||
|
||||
void AchievementsWindow::updateTotal() {
|
||||
if (mTotalEl == nullptr) {
|
||||
return;
|
||||
}
|
||||
const auto all = AchievementSystem::get().getAchievements();
|
||||
int total = static_cast<int>(all.size());
|
||||
int unlocked = 0;
|
||||
for (const auto& a : all) {
|
||||
if (a.unlocked) {
|
||||
++unlocked;
|
||||
}
|
||||
}
|
||||
const int pct = total > 0 ? (unlocked * 100 / total) : 0;
|
||||
mTotalEl->SetInnerRML(fmt::format("{}%", pct));
|
||||
}
|
||||
|
||||
} // namespace dusk::ui
|
||||
|
||||
@@ -13,7 +13,9 @@ public:
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
void updateTotal();
|
||||
std::vector<Achievement> mSnapshot;
|
||||
Rml::Element* mTotalEl = nullptr;
|
||||
};
|
||||
|
||||
} // namespace dusk::ui
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "d/actor/d_a_midna.h"
|
||||
#include "d/d_model.h"
|
||||
#include "d/d_tresure.h"
|
||||
#include "dusk/achievements.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/livesplit.h"
|
||||
#include "dusk/logging.h"
|
||||
@@ -828,6 +829,7 @@ void fapGm_Execute() {
|
||||
cCt_Counter(0);
|
||||
#ifdef TARGET_PC
|
||||
dusk::speedrun::onGameFrame();
|
||||
dusk::AchievementSystem::get().tick();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
#include <system_error>
|
||||
#include <thread>
|
||||
#include "SSystem/SComponent/c_API.h"
|
||||
#include "dusk/achievements.h"
|
||||
#include "dusk/app_info.hpp"
|
||||
#include "dusk/crash_reporting.h"
|
||||
#include "dusk/dusk.h"
|
||||
@@ -283,7 +282,6 @@ void main01(void) {
|
||||
dusk::gyro::read(pacing.sim_pace);
|
||||
fapGm_Execute();
|
||||
mDoAud_Execute();
|
||||
dusk::AchievementSystem::get().tick();
|
||||
dusk::game_clock::commit_sim_tick();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user