Skip to content

Commit e91982f

Browse files
committed
Add support for traps. Add 7 visual traps.
1 parent 7d772bf commit e91982f

16 files changed

+924
-0
lines changed

ArchipelagoMuseDash/Archipelago/ItemHandler.cs

+3
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ private IMuseDashItem GetItemFromNetworkItem(NetworkItem item, bool otherPlayers
146146
return new ExternalItem(name, playerName) { Item = item };
147147
}
148148

149+
if (ArchipelagoStatic.SessionHandler.TrapHandler.EnqueueIfTrap(item))
150+
return null;
151+
149152
if (name == music_sheet_item_name)
150153
return new MusicSheetItem() { Item = item };
151154

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using Archipelago.MultiClient.Net.Helpers;
2+
using Archipelago.MultiClient.Net.Models;
3+
using ArchipelagoMuseDash.Archipelago.Traps;
4+
using Il2CppAssets.Scripts.UI.Controls;
5+
using Il2CppGameLogic;
6+
7+
namespace ArchipelagoMuseDash.Archipelago;
8+
9+
public class TrapHandler {
10+
private readonly DataStorageHelper _dataStorageHelper;
11+
12+
private int _lastHandledTrap;
13+
private ITrap _activatedTrap;
14+
15+
private readonly List<ITrap> _knownTraps = new();
16+
17+
public TrapHandler(DataStorageHelper dataStorageHelper) {
18+
_dataStorageHelper = dataStorageHelper;
19+
_lastHandledTrap = dataStorageHelper["lastTrap"];
20+
_knownTraps.Clear();
21+
}
22+
23+
public bool EnqueueIfTrap(NetworkItem item) {
24+
foreach (var trap in _knownTraps) {
25+
if (trap.NetworkItem.Item == item.Item && trap.NetworkItem.Location == item.Location)
26+
return true; //Already known
27+
}
28+
29+
switch (item.Item) {
30+
case 2900001: {
31+
_knownTraps.Add(new BadAppleTrap() { NetworkItem = item });
32+
return true;
33+
}
34+
case 2900002: {
35+
_knownTraps.Add(new PixelateTrap() { NetworkItem = item });
36+
return true;
37+
}
38+
case 2900003: {
39+
_knownTraps.Add(new RandomWaveTrap() { NetworkItem = item });
40+
return true;
41+
}
42+
case 2900004: {
43+
_knownTraps.Add(new ShadowEdgeTrap() { NetworkItem = item });
44+
return true;
45+
}
46+
case 2900005: {
47+
_knownTraps.Add(new ChromaticAberrationTrap() { NetworkItem = item });
48+
return true;
49+
}
50+
case 2900006: {
51+
_knownTraps.Add(new BGFreezeTrap() { NetworkItem = item });
52+
return true;
53+
}
54+
case 2900007: {
55+
_knownTraps.Add(new GrayScaleTrap() { NetworkItem = item });
56+
return true;
57+
}
58+
default:
59+
return false;
60+
}
61+
}
62+
63+
public void ActivateNextTrap() {
64+
if (_lastHandledTrap >= _knownTraps.Count || _activatedTrap != null) {
65+
ShowText.ShowInfo(_activatedTrap.TrapMessage);
66+
return;
67+
}
68+
69+
_activatedTrap = _knownTraps[_lastHandledTrap];
70+
_lastHandledTrap++;
71+
ShowText.ShowInfo(_activatedTrap.TrapMessage);
72+
ArchipelagoStatic.ArchLogger.Log("TrapHandler", $"Activated trap {_activatedTrap}");
73+
}
74+
75+
public void SetTrapFinished() {
76+
if (_activatedTrap == null)
77+
return;
78+
79+
//This will cause issues if multiple people are running the same game and don't go through all traps. But I'm fine with that.
80+
_dataStorageHelper["lastTrap"] = _lastHandledTrap;
81+
_activatedTrap = null;
82+
}
83+
84+
public void PreGameSceneLoad() => _activatedTrap?.PreGameSceneLoad();
85+
public void LoadMusicDataByFilenameHook() => _activatedTrap?.LoadMusicDataByFilenameHook();
86+
87+
public void SetRuntimeMusicDataHook(Il2CppSystem.Collections.Generic.List<MusicData> result) {
88+
if (_activatedTrap == null)
89+
return;
90+
91+
var list = new List<MusicData>(result.Count);
92+
foreach (var value in result)
93+
list.Add(value);
94+
95+
_activatedTrap.SetRuntimeMusicDataHook(list);
96+
97+
result.Clear();
98+
foreach (var value in list)
99+
result.Add(value);
100+
}
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using Archipelago.MultiClient.Net.Models;
2+
using Il2CppGameLogic;
3+
using Il2CppPeroPeroGames.GlobalDefines;
4+
5+
namespace ArchipelagoMuseDash.Archipelago.Traps;
6+
7+
public class BGFreezeTrap : ITrap {
8+
public string TrapMessage => "★★ Trap Activated ★★\nBackground Frozen!";
9+
public NetworkItem NetworkItem { get; set; }
10+
11+
public void PreGameSceneLoad() { }
12+
13+
public void LoadMusicDataByFilenameHook() { }
14+
15+
public void SetRuntimeMusicDataHook(List<MusicData> data) {
16+
ArchipelagoStatic.ArchLogger.Log("DBStageInfo", $"SetRuntimeMusicData {data.Count}");
17+
18+
var backgroundFreezeNoteData = CreateBackgroundFreezeNoteData();
19+
TrapHelper.InsertAtStart(data, TrapHelper.CreateDefaultMusicData(backgroundFreezeNoteData.uid, backgroundFreezeNoteData));
20+
21+
for (int i = data.Count - 1; i > 1; i--) {
22+
var bmsUid = data[i].noteData.bmsUid;
23+
if (bmsUid != BmsNodeUid.BgFreeze && bmsUid != BmsNodeUid.BgUnfreeze)
24+
continue;
25+
TrapHelper.RemoveIndex(data, i);
26+
}
27+
28+
//ChangeToBadApple(data);
29+
TrapHelper.FixIndexes(data);
30+
}
31+
32+
private NoteConfigData CreateBackgroundFreezeNoteData() => new NoteConfigData() {
33+
id = "112",
34+
ibms_id = "2N",
35+
uid = "000903",
36+
mirror_uid = "000903",
37+
scene = "0",
38+
des = "黑白滤镜开始",
39+
prefab_name = "000903",
40+
type = 32,
41+
effect = "0",
42+
key_audio = "0",
43+
boss_action = "0",
44+
left_perfect_range = 0,
45+
left_great_range = 0,
46+
right_perfect_range = 0,
47+
right_great_range = 0,
48+
damage = 0,
49+
pathway = 0,
50+
speed = 1,
51+
score = 0,
52+
fever = 0,
53+
missCombo = false,
54+
addCombo = false,
55+
jumpNote = false,
56+
isShowPlayEffect = false,
57+
m_BmsUid = BmsNodeUid.BgFreeze,
58+
sceneChangeNames = null
59+
};
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using Archipelago.MultiClient.Net.Models;
2+
using Il2CppAssets.Scripts.Database;
3+
using Il2CppAssets.Scripts.TouhouLogic;
4+
using Il2CppGameLogic;
5+
using Il2CppPeroPeroGames.GlobalDefines;
6+
7+
namespace ArchipelagoMuseDash.Archipelago.Traps;
8+
9+
public class BadAppleTrap : ITrap {
10+
public string TrapMessage => "★★ Trap Activated ★★\nBad Apple!";
11+
public NetworkItem NetworkItem { get; set; }
12+
13+
public void PreGameSceneLoad() {
14+
GlobalDataBase.dbTouhou.isBadApple = true;
15+
GlobalDataBase.s_DbOther.m_HpFx = TouhouLogic.ReplaceBadAppleString("fx_hp_ground");
16+
GlobalDataBase.s_DbOther.m_MusicFx = TouhouLogic.ReplaceBadAppleString("fx_score_ground");
17+
GlobalDataBase.s_DbOther.m_DustFx = TouhouLogic.ReplaceBadAppleString("dust_fx");
18+
}
19+
20+
public void LoadMusicDataByFilenameHook() {
21+
//This is used to force the scene into the Touhou scene. The Touhou scene is the only one that can handle the bad apple look.
22+
GlobalDataBase.dbBattleStage.m_BeganScene = "scene_08";
23+
GlobalDataBase.dbBattleStage.m_BeganSceneIdx = 8;
24+
}
25+
26+
public void SetRuntimeMusicDataHook(List<MusicData> data) {
27+
ArchipelagoStatic.ArchLogger.Log("DBStageInfo", $"SetRuntimeMusicData {data.Count}");
28+
ChangeToBadApple(data);
29+
TrapHelper.FixIndexes(data);
30+
}
31+
32+
private void ChangeToBadApple(List<MusicData> data) {
33+
for (int i = data.Count - 1; i >= 0; i--) {
34+
var md = data[i];
35+
36+
var noteData = md.noteData;
37+
38+
switch (noteData.bmsUid) {
39+
case BmsNodeUid.ToggleScene1:
40+
case BmsNodeUid.ToggleScene2:
41+
case BmsNodeUid.ToggleScene3:
42+
case BmsNodeUid.ToggleScene4:
43+
case BmsNodeUid.ToggleScene5:
44+
case BmsNodeUid.ToggleScene6:
45+
case BmsNodeUid.ToggleScene7:
46+
case BmsNodeUid.ToggleScene8:
47+
case BmsNodeUid.ToggleScene9:
48+
case BmsNodeUid.ToggleScene10: {
49+
TrapHelper.RemoveIndex(data, i);
50+
continue;
51+
}
52+
}
53+
54+
//BmsNodeUid.Hp and BmsNodeUid.Music do not have stage specific versions, except for touhou. So these require special logic.
55+
if (noteData.m_BmsUid is BmsNodeUid.Hp or BmsNodeUid.Music) {
56+
ArchipelagoStatic.ArchLogger.Log("BadAppleTrap", "Note is HP or Music");
57+
if (noteData.scene == "scene_08")
58+
continue;
59+
60+
noteData.scene = "scene_08";
61+
noteData.prefab_name = string.Concat("08", md.noteData.prefab_name);
62+
md.noteData = noteData;
63+
data[i] = md;
64+
continue;
65+
}
66+
67+
if (noteData.scene is not { Length: > 2 })
68+
continue;
69+
70+
noteData.scene = "scene_08";
71+
if (int.TryParse(md.noteData.prefab_name.AsSpan(0, 2), out var value) && value != 8) {
72+
switch (noteData.m_BmsUid) {
73+
case BmsNodeUid.Music:
74+
case BmsNodeUid.Hp:
75+
break;
76+
default:
77+
noteData.prefab_name = string.Concat("08", md.noteData.prefab_name.AsSpan(2));
78+
break;
79+
}
80+
}
81+
82+
md.noteData = noteData;
83+
data[i] = md;
84+
}
85+
}
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using Archipelago.MultiClient.Net.Models;
2+
using Il2CppGameLogic;
3+
using Il2CppPeroPeroGames.GlobalDefines;
4+
5+
namespace ArchipelagoMuseDash.Archipelago.Traps;
6+
7+
/// <summary>
8+
/// This trap only partially works. (Probably a value somewhere.) but it is also too visually noisy to be a good trap.
9+
/// </summary>
10+
public class CanvasScrollTrap : ITrap {
11+
public string TrapMessage => "★★ Trap Activated ★★\nCanvas Scroll!";
12+
public NetworkItem NetworkItem { get; set; }
13+
14+
public void PreGameSceneLoad() { }
15+
16+
public void LoadMusicDataByFilenameHook() { }
17+
18+
public void SetRuntimeMusicDataHook(List<MusicData> data) {
19+
ArchipelagoStatic.ArchLogger.Log("DBStageInfo", $"SetRuntimeMusicData {data.Count}");
20+
21+
var scrollNoteData = UnityEngine.Random.Range(0, 2) == 0 ? CreateUpScrollNoteData() : CreateDownScrollNoteData();
22+
TrapHelper.InsertAtStart(data, TrapHelper.CreateDefaultMusicData(scrollNoteData.uid, scrollNoteData));
23+
24+
for (int i = data.Count - 1; i > 1; i--) {
25+
var bmsUid = data[i].noteData.bmsUid;
26+
if (bmsUid != BmsNodeUid.CanvasUpScroll && bmsUid != BmsNodeUid.CanvasDownScroll && bmsUid != BmsNodeUid.CanvasScrollOver)
27+
continue;
28+
TrapHelper.RemoveIndex(data, i);
29+
}
30+
31+
//ChangeToBadApple(data);
32+
TrapHelper.FixIndexes(data);
33+
}
34+
35+
private NoteConfigData CreateUpScrollNoteData() => new NoteConfigData() {
36+
id = "64",
37+
ibms_id = "27",
38+
uid = "000800",
39+
mirror_uid = "000800",
40+
scene = "0",
41+
des = "画面向上滚动",
42+
prefab_name = "000800",
43+
type = 18,
44+
effect = "0",
45+
key_audio = "0",
46+
boss_action = "0",
47+
left_perfect_range = 0,
48+
left_great_range = 0,
49+
right_perfect_range = 0,
50+
right_great_range = 0,
51+
damage = 0,
52+
pathway = 0,
53+
speed = 1,
54+
score = 0,
55+
fever = 0,
56+
missCombo = false,
57+
addCombo = false,
58+
jumpNote = false,
59+
isShowPlayEffect = false,
60+
m_BmsUid = BmsNodeUid.CanvasUpScroll,
61+
sceneChangeNames = null
62+
};
63+
64+
private NoteConfigData CreateDownScrollNoteData() => new NoteConfigData() {
65+
id = "67",
66+
ibms_id = "28",
67+
uid = "000801",
68+
mirror_uid = "000801",
69+
scene = "0",
70+
des = "画面向下滚动",
71+
prefab_name = "000801",
72+
type = 19,
73+
effect = "0",
74+
key_audio = "0",
75+
boss_action = "0",
76+
left_perfect_range = 0,
77+
left_great_range = 0,
78+
right_perfect_range = 0,
79+
right_great_range = 0,
80+
damage = 0,
81+
pathway = 0,
82+
speed = 1,
83+
score = 0,
84+
fever = 0,
85+
missCombo = false,
86+
addCombo = false,
87+
jumpNote = false,
88+
isShowPlayEffect = false,
89+
m_BmsUid = BmsNodeUid.CanvasDownScroll,
90+
sceneChangeNames = null
91+
};
92+
}

0 commit comments

Comments
 (0)