1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
4+ using Serilog ;
5+ using UndertaleModLib . Models ;
6+ using Newtonsoft . Json ;
7+ using System . IO ;
8+ using Microsoft . Win32 ;
9+
10+ namespace ModShardLauncher
11+ {
12+ public class RandomLootTable
13+ {
14+ public int [ ] TableLootWeight { get ; }
15+ public string [ ] TableLootItems { get ; }
16+ public int [ ] TableLootRarity { get ; }
17+ public int [ ] TableLootDurability { get ; }
18+
19+ public RandomLootTable ( int [ ] tableLootWeight , string [ ] tableLootItems , int [ ] tableLootRarity , int [ ] tableLootDurability )
20+ {
21+ TableLootWeight = tableLootWeight ;
22+ TableLootItems = tableLootItems ;
23+ TableLootRarity = tableLootRarity ;
24+ TableLootDurability = tableLootDurability ;
25+ }
26+ }
27+ public class ReferenceTable
28+ {
29+ public int [ ] Ids { get ; }
30+ public string [ ] Refs { get ; }
31+ public ReferenceTable ( string [ ] refs , int [ ] ids )
32+ {
33+ Ids = ids ;
34+ Refs = refs ;
35+ }
36+ }
37+ public class LootTable
38+ {
39+ public string [ ] GuaranteedItems { get ; }
40+ public int RandomLootMin { get ; }
41+ public int RandomLootMax { get ; }
42+ public int EmptyWeight { get ; }
43+ public RandomLootTable RandomLootTable { get ; }
44+ public LootTable ( string [ ] guaranteedItems , int randomLootMin , int randomLootMax , int emptyWeight , RandomLootTable randomLootTable )
45+ {
46+ GuaranteedItems = guaranteedItems ;
47+ RandomLootMin = randomLootMin ;
48+ RandomLootMax = randomLootMax ;
49+ EmptyWeight = emptyWeight ;
50+ RandomLootTable = randomLootTable ;
51+ }
52+ }
53+ public static class LootUtils
54+ {
55+ public static Dictionary < string , ReferenceTable > ReferenceTables = new ( ) ;
56+ public static Dictionary < string , LootTable > LootTables = new ( ) ;
57+ public static void ResetLootTables ( )
58+ {
59+ ReferenceTables . Clear ( ) ;
60+ LootTables . Clear ( ) ;
61+ }
62+ public static void SaveLootTables ( string DirPath )
63+ {
64+ if ( LootTables . Count > 0 )
65+ {
66+ File . WriteAllText ( Path . Combine ( DirPath , "loot_table.json" ) , JsonConvert . SerializeObject ( LootTables ) ) ;
67+ Log . Information ( "Successfully saving the loot table json." ) ;
68+ }
69+ if ( ReferenceTables . Count > 0 )
70+ {
71+ File . WriteAllText ( Path . Combine ( DirPath , "reference_table.json" ) , JsonConvert . SerializeObject ( ReferenceTables ) ) ;
72+ Log . Information ( "Successfully saving the reference table json." ) ;
73+ }
74+ }
75+ public static void InjectLootScripts ( )
76+ {
77+ if ( LootTables . Count == 0 && ReferenceTables . Count == 0 ) return ;
78+
79+ string lootFunction = @"function scr_resolve_loot_table(argument0)
80+ {
81+ var objectName = object_get_name(argument0.object_index);
82+ scr_actionsLogUpdate(""instance: "" + string(argument0.id) + "" of "" + objectName);
83+
84+ var refFile = file_text_open_read(""reference_table.json"");
85+ var refJson = file_text_read_string(refFile);
86+ var refData = json_parse(refJson);
87+
88+ var min_lvl = scr_globaltile_dungeon_get(""mob_lvl_min"");
89+ var max_lvl = scr_globaltile_dungeon_get(""mob_lvl_max"");
90+ var tier = floor(((max_lvl + min_lvl) / 2));
91+
92+ if (!variable_struct_exists(refData, objectName))
93+ {
94+ scr_actionsLogUpdate(""cant find object "" + objectName);
95+ return 0;
96+ }
97+ var refStruct = variable_struct_get(refData, objectName);
98+ var referenceLootTableIndex = -1;
99+
100+ if (!variable_struct_exists(refStruct, ""Ids""))
101+ {
102+ scr_actionsLogUpdate(""cant find Ids"");
103+ return 0;
104+ }
105+ var idsArray = variable_struct_get(refStruct, ""Ids"");
106+
107+ for (var i = 0; i < array_length(idsArray); i += 1)
108+ {
109+ if (idsArray[i] == argument0.id)
110+ {
111+ referenceLootTableIndex = i;
112+ break;
113+ }
114+ }
115+ scr_actionsLogUpdate(""id ref: "" + string(referenceLootTableIndex));
116+
117+ if (!variable_struct_exists(refStruct, ""Refs""))
118+ {
119+ scr_actionsLogUpdate(""cant find Refs"");
120+ return 0;
121+ }
122+ var refsTable = variable_struct_get(refStruct, ""Refs"");
123+ var referenceLootTable = refsTable[referenceLootTableIndex + 1];
124+
125+ scr_actionsLogUpdate(""ref: "" + referenceLootTable);
126+
127+ if (!variable_struct_exists(refStruct, ""Refs""))
128+ {
129+ scr_actionsLogUpdate(""cant find Refs"");
130+ return 0;
131+ }
132+ var refsTable = variable_struct_get(refStruct, ""Refs"");
133+ var referenceLootTable = refsTable[referenceLootTableIndex + 1];
134+
135+ var file = file_text_open_read(""loot_table.json"");
136+ var json = file_text_read_string(file);
137+ var data = json_parse(json);
138+
139+ if (!variable_struct_exists(data, referenceLootTable))
140+ {
141+ scr_actionsLogUpdate(""cant find ref "" + referenceLootTable);
142+ return 0;
143+ }
144+ var lootStruct = variable_struct_get(data, referenceLootTable);
145+
146+ var objectName = """";
147+ var obj = -1;
148+
149+ if (!variable_struct_exists(lootStruct, ""GuaranteedItems""))
150+ {
151+ scr_actionsLogUpdate(""no guaranteedItems"");
152+ return 0;
153+ }
154+ var guaranteedItems = variable_struct_get(lootStruct, ""GuaranteedItems"");
155+ var sizeGuaranteedItems = array_length(guaranteedItems);
156+
157+ for (var i = 0; i < sizeGuaranteedItems; i += 1)
158+ {
159+ objectName = guaranteedItems[i];
160+ obj = asset_get_index(objectName)
161+ if (obj > -1)
162+ {
163+ scr_inventory_add_item(obj);
164+ }
165+ else
166+ {
167+ scr_actionsLogUpdate(""invalid object "" + string(objectName));
168+ }
169+ }
170+
171+ if (!variable_struct_exists(lootStruct, ""RandomLootMin"") || !variable_struct_exists(lootStruct, ""RandomLootMax"") || !variable_struct_exists(lootStruct, ""EmptyWeight""))
172+ {
173+ scr_actionsLogUpdate(""no int"");
174+ return 0;
175+ }
176+
177+ var randomLootMin = variable_struct_get(lootStruct, ""RandomLootMin"");
178+ var randomLootMax = variable_struct_get(lootStruct, ""RandomLootMax"");
179+ var emptyWeight = variable_struct_get(lootStruct, ""EmptyWeight"");
180+
181+ var iteration = randomLootMin + irandom(randomLootMax - randomLootMin);
182+ scr_actionsLogUpdate(""iteration "" + string(iteration));
183+
184+ if (!variable_struct_exists(lootStruct, ""RandomLootTable""))
185+ {
186+ scr_actionsLogUpdate(""no RandomLootTable"");
187+ return 0;
188+ }
189+
190+ var randomLootTable = variable_struct_get(lootStruct, ""RandomLootTable"");
191+
192+ if (!variable_struct_exists(randomLootTable, ""TableLootWeight"")
193+ || !variable_struct_exists(randomLootTable, ""TableLootItems"")
194+ || !variable_struct_exists(randomLootTable, ""TableLootRarity"")
195+ || !variable_struct_exists(randomLootTable, ""TableLootDurability""))
196+ {
197+ scr_actionsLogUpdate(""no tableLoot data"");
198+ return 0;
199+ }
200+
201+ var tableLootWeight = variable_struct_get(randomLootTable, ""TableLootWeight"");
202+ var tableLootItems = variable_struct_get(randomLootTable, ""TableLootItems"");
203+ var tableLootRarity = variable_struct_get(randomLootTable, ""TableLootRarity"");
204+ var tableLootDurability = variable_struct_get(randomLootTable, ""TableLootDurability"");
205+
206+ var sizeTableLoot = array_length(tableLootWeight);
207+ var tableLootSpecialLootAlready = array_create(sizeTableLoot, 0);
208+
209+ for (var j = 0; j < iteration; j += 1)
210+ {
211+ var totalWeight = emptyWeight;
212+ for (var i = 0; i < sizeTableLoot; i += 1)
213+ {
214+ if (ds_list_find_index(scr_atr(""specialItemsPool""), tableLootItems[i]) != -1)
215+ {
216+ tableLootSpecialLootAlready[i] = 1;
217+ }
218+ else
219+ {
220+ totalWeight += tableLootWeight[i];
221+ }
222+ }
223+
224+ scr_actionsLogUpdate(""totalWeight "" + string(totalWeight));
225+
226+ var randomWeight = irandom(totalWeight - 1);
227+ scr_actionsLogUpdate(""randomWeight "" + string(randomWeight));
228+ var cumulativeWeight = 0;
229+ var index = -1;
230+
231+ for (var i = 0; i < sizeTableLoot; i += 1)
232+ {
233+ if (tableLootSpecialLootAlready[i] == 1)
234+ {
235+ continue;
236+ }
237+ cumulativeWeight += tableLootWeight[i]
238+ if (randomWeight < cumulativeWeight)
239+ {
240+ index = i;
241+ break;
242+ }
243+ }
244+
245+ if (index != -1)
246+ {
247+ scr_actionsLogUpdate(""found "" + string(index));
248+
249+ if (tableLootRarity[index] == -1)
250+ {
251+ objectName = tableLootItems[index];
252+ obj = asset_get_index(objectName)
253+ if (obj > -1)
254+ {
255+ scr_inventory_add_item(obj);
256+ }
257+ else
258+ {
259+ scr_actionsLogUpdate(""invalid object "" + string(objectName));
260+ }
261+ }
262+ else
263+ {
264+ with (scr_inventory_add_weapon(tableLootItems[index], (tableLootRarity[index] << 0)))
265+ {
266+ scr_inv_atr_set(""Duration"", tableLootDurability[index]);
267+ }
268+ }
269+
270+ }
271+ else
272+ {
273+ scr_actionsLogUpdate(""found empty"");
274+ }
275+ }
276+ }" ;
277+
278+ Msl . AddFunction ( lootFunction , "scr_resolve_loot_table" ) ;
279+
280+ Msl . LoadGML ( "gml_Object_o_chest_p_Alarm_1" )
281+ . MatchFrom ( "script_execute" )
282+ . InsertBelow ( "scr_resolve_loot_table(other)" )
283+ . Save ( ) ;
284+
285+ Msl . LoadGML ( "gml_Object_c_container_Other_10" )
286+ . MatchFrom ( "script_execute" )
287+ . InsertBelow ( "scr_resolve_loot_table(other)" )
288+ . Save ( ) ;
289+ }
290+ }
291+ public static partial class Msl
292+ {
293+ public static void AddLootTable ( string lootTableID , string [ ] guaranteedItems , int randomLootMin , int randomLootMax , int emptyWeight , RandomLootTable randomLootTable )
294+ {
295+ LootTable lootTable = new ( guaranteedItems , randomLootMin , randomLootMax , emptyWeight , randomLootTable ) ;
296+ LootUtils . LootTables . Add ( lootTableID , lootTable ) ;
297+ }
298+ public static void AddReferenceTable ( string nameObject , string [ ] refs , int [ ] ? ids = null )
299+ {
300+ ids ??= Array . Empty < int > ( ) ;
301+ ReferenceTable referenceTable = new ( refs , ids ) ;
302+ LootUtils . ReferenceTables . Add ( nameObject , referenceTable ) ;
303+ }
304+ }
305+ }
0 commit comments