Skip to content

Commit fcc1e3e

Browse files
committed
CourseEditor: add code copy/paste, hopefully fix goal-bunki issue
1 parent af6a9e8 commit fcc1e3e

File tree

1 file changed

+85
-32
lines changed

1 file changed

+85
-32
lines changed

src/overlay/course_editor.cpp

Lines changed: 85 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -145,41 +145,30 @@ CourseReplacement CourseReplacement::instance;
145145

146146
void sharecode_generate();
147147

148-
bool update_stage(StageTable_mb* tableEntry, GameStage newStage, bool isGoalColumn)
148+
bool update_stage(StageTable_mb* tableEntry, GameStage newStage, int stageTableId)
149149
{
150150
tableEntry->StageUniqueName_0 = newStage;
151-
tableEntry->CsInfoId_1C = tableEntry->BrInfoId_20 = newStage;
151+
tableEntry->CsInfoId_1C = newStage;
152+
153+
tableEntry->BrInfoId_20 = 0; // 0 allows highway to always spawn
152154

153155
TAG_model_info** cs_info_tbl = Module::exe_ptr<TAG_model_info*>(0x2A54E0);
154156
TAG_model_info** br_info_tbl = Module::exe_ptr<TAG_model_info*>(0x2A55E8);
155157

156-
if (newStage == STAGE_PALM_BEACH_T || newStage == STAGE_PALM_BEACH_BT)
157-
tableEntry->BrInfoId_20 = STAGE_PALM_BEACH;
158-
else if (newStage == STAGE_BEACH_T || newStage == STAGE_BEACH_BT)
159-
tableEntry->BrInfoId_20 = STAGE_BEACH;
160-
else if (newStage == STAGE_PALM_BEACH_BR)
161-
tableEntry->BrInfoId_20 = STAGE_PALM_BEACH_R;
162-
else if (newStage == STAGE_BEACH_BR)
163-
tableEntry->BrInfoId_20 = STAGE_BEACH_R;
164-
165-
if (isGoalColumn)
158+
if (stageTableId > 9) // goal stage
166159
{
167-
// If stage is set to one of the existing goal-stages, use the goal bunki for it
168-
// (otherwise will default to normal bunki, sadly goal bunki can't be shared between maps)
169-
170-
if (tableEntry->BrInfoId_20 == STAGE_TULIP_GARDEN)
171-
tableEntry->BrInfoId_20 = STAGE_EASTER_ISLAND_R + 1; // ENDA
172-
else if (tableEntry->BrInfoId_20 == STAGE_METROPOLIS)
173-
tableEntry->BrInfoId_20 = STAGE_EASTER_ISLAND_R + 2; // ENDB
174-
else if (tableEntry->BrInfoId_20 == STAGE_ANCIENT_RUINS)
175-
tableEntry->BrInfoId_20 = STAGE_EASTER_ISLAND_R + 3; // ENDC
176-
else if (tableEntry->BrInfoId_20 == STAGE_CAPE_WAY)
177-
tableEntry->BrInfoId_20 = STAGE_EASTER_ISLAND_R + 4; // ENDD
178-
else if (tableEntry->BrInfoId_20 == STAGE_IMPERIAL_AVENUE)
179-
tableEntry->BrInfoId_20 = STAGE_EASTER_ISLAND_R + 5; // ENDE
180-
181-
else if (tableEntry->BrInfoId_20 == STAGE_PALM_BEACH)
182-
tableEntry->BrInfoId_20 = STAGE_EASTER_ISLAND_R + 5; // ANDA (todo: what are ANDB - ANDJ for?)
160+
// TODO: allow swapping to 2SP goal-bunkis somehow?
161+
// TODO2: is there a generic goal-bunki we can use? I guess c2c missions probably use one for the non-goal stages?
162+
if (stageTableId == 10)
163+
tableEntry->BrInfoId_20 = STAGE_TULIP_GARDEN; // goal A
164+
else if (stageTableId == 11)
165+
tableEntry->BrInfoId_20 = STAGE_METROPOLIS; // goal B
166+
else if (stageTableId == 12)
167+
tableEntry->BrInfoId_20 = STAGE_ANCIENT_RUINS; // goal C
168+
else if (stageTableId == 13)
169+
tableEntry->BrInfoId_20 = STAGE_CAPE_WAY; // goal D
170+
else if (stageTableId == 14)
171+
tableEntry->BrInfoId_20 = STAGE_IMPERIAL_AVENUE; // goal E
183172
}
184173

185174
tableEntry->CsInfoPtr_14 = cs_info_tbl[tableEntry->CsInfoId_1C];
@@ -233,7 +222,7 @@ void sharecode_apply()
233222
if (stageNum < 0 || stageNum >= 0x42)
234223
stageNum = 0;
235224

236-
update_stage(&CustomStageTable[num], GameStage(stageNum), num > 9);
225+
update_stage(&CustomStageTable[num], GameStage(stageNum), num);
237226

238227
num++;
239228

@@ -334,7 +323,7 @@ void Overlay_CourseEditor()
334323

335324
std::string name = std::format("{}.{}", (col + 1), (row + 1));
336325
if (ImGui::Combo(name.c_str(), &selected, stageNames, 0x42))
337-
has_updated |= update_stage(curStage, GameStage(selected), col == 4);
326+
has_updated |= update_stage(curStage, GameStage(selected), num);
338327

339328
curStage++;
340329

@@ -361,11 +350,75 @@ void Overlay_CourseEditor()
361350

362351
ImGui::Text("Share Code: ");
363352
ImGui::SameLine();
364-
ImGui::SetNextItemWidth(400.f);
353+
ImGui::SetNextItemWidth(500.f);
365354
ImGui::InputText("##ShareCode", ShareCode, 256);
366355
ImGui::SameLine();
367356
if (ImGui::Button("Apply Code"))
368357
sharecode_apply();
358+
ImGui::SameLine();
359+
if (ImGui::Button("Copy Code"))
360+
{
361+
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, strlen(ShareCode) + 1);
362+
if (hMem)
363+
{
364+
memcpy(GlobalLock(hMem), ShareCode, strlen(ShareCode) + 1);
365+
GlobalUnlock(hMem);
366+
OpenClipboard(0);
367+
EmptyClipboard();
368+
SetClipboardData(CF_TEXT, hMem);
369+
CloseClipboard();
370+
}
371+
}
372+
ImGui::SameLine();
373+
if (ImGui::Button("Paste Code"))
374+
{
375+
if (OpenClipboard(0))
376+
{
377+
HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT);
378+
if (hClipboardData == nullptr)
379+
hClipboardData = GetClipboardData(CF_TEXT);
380+
381+
if (hClipboardData != nullptr)
382+
{
383+
void* clipboardData = GlobalLock(hClipboardData);
384+
if (clipboardData)
385+
{
386+
if (hClipboardData == GetClipboardData(CF_UNICODETEXT))
387+
{
388+
wchar_t* wideText = static_cast<wchar_t*>(clipboardData);
389+
390+
// Convert unicode to char
391+
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, wideText, -1, nullptr, 0, nullptr, nullptr);
392+
if (bufferSize > 0 && bufferSize < sizeof(ShareCode))
393+
WideCharToMultiByte(CP_UTF8, 0, wideText, -1, ShareCode, bufferSize, nullptr, nullptr);
394+
else
395+
{
396+
// Handle the case where the buffer is too small, truncate if necessary
397+
WideCharToMultiByte(CP_UTF8, 0, wideText, -1, ShareCode, sizeof(ShareCode) - 1, nullptr, nullptr);
398+
ShareCode[sizeof(ShareCode) - 1] = '\0'; // Null-terminate
399+
}
400+
}
401+
else if (hClipboardData == GetClipboardData(CF_TEXT))
402+
{
403+
char* asciiText = static_cast<char*>(clipboardData);
404+
405+
if (strlen(asciiText) < sizeof(ShareCode))
406+
strcpy(ShareCode, asciiText);
407+
else
408+
{
409+
// If the clipboard text is too large, truncate
410+
strncpy(ShareCode, asciiText, sizeof(ShareCode) - 1);
411+
ShareCode[sizeof(ShareCode) - 1] = '\0'; // Null-terminate
412+
}
413+
}
414+
sharecode_apply();
415+
416+
GlobalUnlock(hClipboardData);
417+
}
418+
}
419+
CloseClipboard();
420+
}
421+
}
369422

370423
if (ImGui::TreeNode("Randomizer"))
371424
{
@@ -421,7 +474,7 @@ void Overlay_CourseEditor()
421474
}
422475
}
423476

424-
update_stage(&CustomStageTable[i], random_stage, i > 9);
477+
update_stage(&CustomStageTable[i], random_stage, i);
425478
seen.push_back(random_stage);
426479
}
427480
}

0 commit comments

Comments
 (0)