diff --git a/src/d/d_stage.cpp b/src/d/d_stage.cpp index 0b933bdb34..6055d8a9ae 100644 --- a/src/d/d_stage.cpp +++ b/src/d/d_stage.cpp @@ -1614,17 +1614,15 @@ DUSK_GAME_DATA dStage_roomControl_c::roomDzs_c dStage_roomControl_c::m_roomDzs; u8 dStage_roomControl_c::mNoArcBank; #endif +static void dStage_actorCreate(stage_actor_data_class* i_actorData, fopAcM_prm_class* i_actorPrm + IF_DUSK_ARG(size_t recordSize = sizeof(stage_actor_data_class))) { #if TARGET_PC -static void dStage_actorCreate(stage_actor_data_class* i_actorData, fopAcM_prm_class* i_actorPrm, - size_t recordSize = sizeof(stage_actor_data_class)) { if (!dusk::mods::svc::stage_apply_actor_edits(i_actorData, i_actorPrm, recordSize, i_actorPrm->room_no)) { JKRFree(i_actorPrm); return; } -#else -static void dStage_actorCreate(stage_actor_data_class* i_actorData, fopAcM_prm_class* i_actorPrm) { #endif dStage_objectNameInf* actorInf = dStage_searchName(i_actorData->name); @@ -1687,6 +1685,8 @@ static int dStage_playerInit(dStage_dt_c* i_stage, void* i_data, int num, void* fopAcM_prm_class* appen = fopAcM_CreateAppend(); JUT_ASSERT(1586, appen != NULL); + IF_DUSK(stage_actor_data_class newPoint{};) // data stored on the stack for any newly registered spawn points + int point = dComIfGp_getStartStagePoint(); u32 roomParam = dComIfGs_getRestartRoomParam(); if (point == -2 || point == -3) { @@ -1707,6 +1707,13 @@ static int dStage_playerInit(dStage_dt_c* i_stage, void* i_data, int num, void* int i; for (i = 0; i < num; i++) { +#ifdef TARGET_PC + // If, for whatever reason, we want to patch the point ID, we need to do it here. + if (!dusk::mods::svc::stage_apply_actor_edits(player_data, nullptr, sizeof(*player_data), i_stage->getRoomNo())) { + player_data++; + continue; // If the spawn is deleted, check the next one + } +#endif if ((u8)player_data->base.angle.z == unk) { break; } @@ -1714,16 +1721,43 @@ static int dStage_playerInit(dStage_dt_c* i_stage, void* i_data, int num, void* } if (i == num) { #if TARGET_PC - std::vector valid_points; - valid_points.reserve(num); - player_data = player->m_entries; - for (i = 0; i < num; i++) { - valid_points.push_back(player_data->base.angle.z); - player_data++; + // Search through all new actor edits and return the point data via userdata + struct newActors_userData { + stage_actor_data_class* out_point; + bool out_pointSet; + int16_t pointNo; + }; + newActors_userData params = { + &newPoint, false, (int16_t)unk + }; + dusk::mods::svc::stage_create_new_actors(i_stage->getRoomNo(), + [](void* user, const void* record, size_t size) { + const stage_actor_data_class* i_record = static_cast(record); + auto* params = static_cast(user); + + // We don't cast i_record->base.angle.z to a u8 here so we can register any spawn point within the s16 range + if (i_record->base.angle.z == params->pointNo && size == sizeof(stage_actor_data_class) && strncmp(i_record->name,"Link",7) == 0) { + std::memcpy(params->out_point, i_record, size); + params->out_pointSet = true; + } + }, + ¶ms); + + if (params.out_pointSet) { + player_data = &newPoint; + } else { + // If the requested spawn point isn't found, print all valid points within the log + std::vector valid_points; + valid_points.reserve(num); + player_data = player->m_entries; + for (i = 0; i < num; i++) { + valid_points.push_back(player_data->base.angle.z); + player_data++; + } + std::ranges::sort(valid_points); + DuskLog.fatal("Failed to find player start point for next stage! Requested point: {}, Valid points: [{}]", + point, fmt::join(valid_points, ", ")); } - std::ranges::sort(valid_points); - DuskLog.fatal("Failed to find player start point for next stage! Requested point: {}, Valid points: [{}]", - point, fmt::join(valid_points, ", ")); #else OS_REPORT_ERROR("プレイヤーが発見できません。[No.%d]\n切り替えの情報や処理の確認をお願いします。\n", point); #endif @@ -2129,12 +2163,8 @@ static int dStage_doorInfoInit(dStage_dt_c* i_stage, void* i_data, int entryNum, appen->base = actor_data->base; appen->room_no = (int)i_stage->getRoomNo(); appen->scale = tgsc_data->scale; -#if TARGET_PC - dStage_actorCreate(actor_data, appen, - sizeof(stage_actor_data_class) + sizeof(fopAcM_prmScale_class)); -#else - dStage_actorCreate(actor_data, appen); -#endif + dStage_actorCreate(actor_data, appen IF_DUSK_ARG( + sizeof(stage_actor_data_class) + sizeof(fopAcM_prmScale_class))); } tgsc_data++; } @@ -2567,6 +2597,11 @@ static void dusk_stage_svc_new_actor_create(dStage_dt_c* i_stage) { stage_tgsc_data_class object{}; std::memcpy(&object, record, size); + if (strncmp(object.name,"Link",7) == 0) { + // We create new spawns for Link during dStage_playerInit. Ignore them here so we don't get duplicates. + return; + } + fopAcM_prm_class* appen = fopAcM_CreateAppend(); if (appen != nullptr) { appen->base = object.base; @@ -2778,9 +2813,7 @@ void dStage_dt_c_roomReLoader(void* i_data, dStage_dt_c* i_stage, int param_2) { }; dStage_dt_c_decode(i_data, i_stage, l_funcTable, ARRAY_SIZEU(l_funcTable)); -#if TARGET_PC - dusk_stage_svc_new_actor_create(i_stage); -#endif + IF_DUSK(dusk_stage_svc_new_actor_create(i_stage)); layerActorLoader(i_data, i_stage, param_2); } diff --git a/src/dusk/mods/svc/stage.cpp b/src/dusk/mods/svc/stage.cpp index 10af84a238..431591ae66 100644 --- a/src/dusk/mods/svc/stage.cpp +++ b/src/dusk/mods/svc/stage.cpp @@ -130,7 +130,9 @@ bool stage_apply_actor_edits(void* actorData, void* actorPrm, size_t recordSize, } std::memcpy(actorData, winner->record.data(), winner->record.size()); - std::memcpy(actorPrm, winner->record.data() + 8, winner->record.size() - 8); + if (actorPrm) { + std::memcpy(actorPrm, winner->record.data() + 8, winner->record.size() - 8); + } return true; }