-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathChestLootHelper.cs
149 lines (146 loc) · 4.49 KB
/
ChestLootHelper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
using System;
using System.Collections;
using System.Collections.Generic;
using Terraria;
using Terraria.ID;
using Terraria.Utilities;
using static Tyfyter.Utils.ChestLootCache.LootQueueAction;
using static Tyfyter.Utils.ChestLootCache.LootQueueMode;
namespace Tyfyter.Utils {
public class ChestLootCache : IEnumerable<KeyValuePair<int, List<int>>> {
public static int[] vanillaGenChests => [0, 2, 4, 11, 12, 13, 15, 16, 17, 50, 51];
public Dictionary<int, List<int>> ChestLoots = new Dictionary<int, List<int>>();
public ChestLootCache() {
ChestLoots = new Dictionary<int, List<int>>();
}
public ChestLootCache(IEnumerable<KeyValuePair<int, List<int>>> enumerable) {
ChestLoots = new Dictionary<int, List<int>>(enumerable);
}
public List<int> this[int lootType] {
get {
if (ChestLoots.ContainsKey(lootType)) {
return ChestLoots[lootType];
} else {
return null;
}
}
}
public void AddLoot(int lootType, int chestIndex) {
if (ChestLoots.ContainsKey(lootType)) {
ChestLoots[lootType].Add(chestIndex);
} else {
ChestLoots.Add(lootType, new List<int> { chestIndex });
}
}
public int CountLoot(int lootType) {
if (ChestLoots.ContainsKey(lootType)) {
return ChestLoots[lootType].Count;
} else {
return 0;
}
}
public WeightedRandom<int> GetWeightedRandom(bool cullUnique = true, UnifiedRandom random = null) {
bool cull = false;
WeightedRandom<int> rand = new WeightedRandom<int>(random ?? WorldGen.genRand);
foreach (KeyValuePair<int, List<int>> kvp in ChestLoots) {
if (kvp.Value.Count > 1) {
cull = cullUnique;
}
rand.Add(kvp.Key, kvp.Value.Count);
}
if (cull) rand.elements.RemoveAll((e) => e.Item2 <= 1);
return rand;
}
public static ChestLootCache[] BuildCaches(int[] chestTypes = null) {
if (chestTypes is null) {
chestTypes = vanillaGenChests;
}
ChestLootCache[] chestLoots = Origins.OriginExtensions.BuildArray<ChestLootCache>(56, chestTypes);
Chest chest;
int lootType;
ChestLootCache cache;
for (int i = 0; i < Main.chest.Length; i++) {
chest = Main.chest[i];
if (chest != null && Main.tile[chest.x, chest.y].TileType == TileID.Containers) {
cache = chestLoots[Main.tile[chest.x, chest.y].TileFrameX / 36];
if (cache is null) continue;
lootType = chest.item[0].type;
cache.AddLoot(lootType, i);
}
}
return chestLoots;
}
public IEnumerator<KeyValuePair<int, List<int>>> GetEnumerator() {
return ChestLoots.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return ChestLoots.GetEnumerator();
}
public enum LootQueueAction {
ENQUEUE,
CHANGE_QUEUE,
SWITCH_MODE,
SET_COUNT_RANGE
}
public static class LootQueueMode {
public const int MODE_REPLACE = 0;
public const int MODE_ADD = 1;
}
[Obsolete]
public static void ApplyLootQueue(ChestLootCache[] lootCaches, params (LootQueueAction action, int param)[] actions) {
int lootType;
ChestLootCache cache = null;
Chest chest;
int chestIndex = -1;
Queue<int> items = new Queue<int>();
WeightedRandom<int> random;
int newLootType;
int queueMode = MODE_REPLACE;
switch (actions[0].action) {
case CHANGE_QUEUE:
cache = lootCaches[actions[0].param];
break;
case SWITCH_MODE:
queueMode = actions[0].param;
break;
case ENQUEUE:
throw new ArgumentException("the first action in ApplyLootQueue must not be ENQUEUE", "actions");
}
int actionIndex = 1;
cont:
if (actionIndex < actions.Length && actions[actionIndex].action == ENQUEUE) {
items.Enqueue(actions[actionIndex].param);
actionIndex++;
goto cont;
}
int i = actions.Length;
if (cache is null) {
return;
}
while (items.Count > 0) {
random = cache.GetWeightedRandom();
lootType = random.Get();
chestIndex = WorldGen.genRand.Next(cache[lootType]);
chest = Main.chest[chestIndex];
newLootType = items.Dequeue();
int targetIndex = 0;
switch (queueMode) {
case MODE_ADD:
for (targetIndex = 0; targetIndex < Chest.maxItems; targetIndex++) if (chest.item[targetIndex].IsAir) break;
break;
}
if (targetIndex >= Chest.maxItems) {
if (--i > 0) items.Enqueue(newLootType);
}
chest.item[targetIndex].SetDefaults(newLootType);
chest.item[targetIndex].Prefix(-2);
cache[lootType].Remove(chestIndex);
}
if (actionIndex < actions.Length && actions[actionIndex].action == CHANGE_QUEUE) {
cache = lootCaches[actions[actionIndex].param];
actionIndex++;
goto cont;
}
}
}
}