Skip to content

Commit 7b63dc1

Browse files
authored
Merge pull request #137 from kgiesing/fix-objective-random-tagged-poi-goto-sdx-localization
Custom quest objective fixes
2 parents 8df27ef + 73bda2f commit 7b63dc1

7 files changed

Lines changed: 137 additions & 61 deletions

File tree

Mods/0-SCore/Config/Localization.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ xuiPersonalSettings,"Personal Settings","","Persönliche Einstellungen","Лич
118118
xuiSCoreUtilsAutoRedeemChallenges,"Auto Redeem Challenges","","Herausforderungen automatisch einlösen","Автоматически выполнять испытания"
119119
xuiSCoreUtilsAutoRedeemChallengesToolTip,"Auto Redeem Challenges as they complete.","","Löst Herausforderungen automatisch ein, sobald sie abgeschlossen sind.","Автоматически выполнять испытания по мере их завершения."
120120
ObjectiveBuffSDX_keyword,"Get","","Erhalten","Получить"
121+
ObjectiveGotoPOISDX,"Head to Rally Point:","Se rendre au point de ralliement :","Begib dich zum Sammelpunkt:","Направиться к точке сбора:"
122+
ObjectiveRandomGotoSDX,"Head to Rally Point:","Se rendre au point de ralliement :","Begib dich zum Sammelpunkt:","Направиться к точке сбора:"
123+
ObjectiveRandomPOIGotoSDX,"Head to Rally Point:","Se rendre au point de ralliement :","Begib dich zum Sammelpunkt:","Направиться к точке сбора:"
124+
ObjectiveRandomTaggedPOIGotoSDX,"Head to Rally Point:","Se rendre au point de ralliement :","Begib dich zum Sammelpunkt:","Направиться к точке сбора:"
121125
ItemCannotBePlaced,"This item cannot go into this slot.","","Dieser Gegenstand kann nicht in diesen Slot gelegt werden.","Этот предмет нельзя поместить в этот слот."
122126
npcNoStorage,"NPCs Cannot Be Placed In Storage.","","NSCs können nicht im Lager platziert werden.","NPC нельзя поместить в хранилище."
123127
buffFreshnessSCoreName,"Fresh Food","","Frisches Essen","Свежая еда"

Mods/0-SCore/Scripts/NetPackage/NetPackageRandomTaggedPOIGotoSDX.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public override void ProcessPackage(World _world, GameManager _callbacks)
8787
includeTags,
8888
excludeTags,
8989
// The values used in vanilla are the square of the distance; adjusted here
90-
minSearchDistance >= 0 ? minSearchDistance : 50,
90+
minSearchDistance >= 0 ? minSearchDistance : 32,
9191
maxSearchDistance >= 0 ? maxSearchDistance : 2000,
9292
usedPoiLocations,
9393
entityId,

Mods/0-SCore/Scripts/Quests/ObjectiveGotoPOISDX.cs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,18 @@ internal class ObjectiveGotoPOISDX : ObjectiveRandomPOIGoto
1414

1515
public override bool useUpdateLoop => true;
1616

17+
public override void SetupObjective()
18+
{
19+
keyword = Localization.Get("ObjectiveGotoPOISDX");
20+
}
21+
1722
public override BaseObjective Clone()
1823
{
1924
var objectiveGotoPOI = new ObjectiveGotoPOISDX();
2025
CopyValues(objectiveGotoPOI);
2126
objectiveGotoPOI.strPOIname = strPOIname;
2227
return objectiveGotoPOI;
2328
}
24-
25-
26-
private void SetDistanceOffset(Vector3 POISize)
27-
{
28-
if (POISize.x > POISize.z)
29-
distanceOffset = POISize.x;
30-
else
31-
distanceOffset = POISize.z;
32-
}
33-
3429

3530
public override Vector3 GetPosition(EntityNPC ownerNPC = null, EntityPlayer entityPlayer = null, List<Vector2> usedPOILocations = null, int entityIDforQuests = -1)
3631
{

Mods/0-SCore/Scripts/Quests/ObjectiveRandomGotoSDX.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public override BaseObjective.ObjectiveValueTypes ObjectiveValueType
1818
// Token: 0x06003857 RID: 14423 RVA: 0x001839B8 File Offset: 0x00181BB8
1919
public override void SetupObjective()
2020
{
21-
this.keyword = Localization.Get("ObjectiveRallyPointHeadTo");
21+
this.keyword = Localization.Get("ObjectiveRandomGotoSDX");
2222
this.SetupIcon();
2323
}
2424

Mods/0-SCore/Scripts/Quests/ObjectiveRandomPOIGotoSDX.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public class ObjectiveRandomPOIGotoSDX : ObjectiveGoto
99
public override void SetupObjective()
1010
{
1111
//Log.Out("ObjectiveRandomPOIGotoSDX-SetupObjective");
12-
this.keyword = Localization.Get("ObjectiveRallyPointHeadTo");
12+
this.keyword = Localization.Get("ObjectiveRandomPOIGotoSDX");
1313
}
1414

1515
// Token: 0x0600386E RID: 14446 RVA: 0x00184429 File Offset: 0x00182629

Mods/0-SCore/Scripts/Quests/ObjectiveRandomTaggedPOIGotoSDX.cs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ public class ObjectiveRandomTaggedPOIGotoSDX : ObjectiveRandomPOIGoto
5252
/// </summary>
5353
public float MaxSearchDistance { get; internal set; } = -1;
5454

55+
/// <summary>
56+
/// Sets up the quest objective.
57+
/// </summary>
58+
public override void SetupObjective()
59+
{
60+
base.SetupObjective();
61+
keyword = Localization.Get("ObjectiveRandomTaggedPOIGotoSDX");
62+
}
63+
5564
/// <summary>
5665
/// Parses additional properties from the dynamic properties.
5766
/// </summary>
@@ -155,7 +164,7 @@ public override Vector3 GetPosition(
155164
IncludeTags,
156165
ExcludeTags,
157166
// The values used in vanilla are the square of the distance; adjusted here
158-
MinSearchDistance >= 0 ? MinSearchDistance : 50,
167+
MinSearchDistance >= 0 ? MinSearchDistance : 32,
159168
MaxSearchDistance >= 0 ? MaxSearchDistance : 2000,
160169
usedPoiLocations,
161170
entityIdForQuests,
@@ -195,7 +204,7 @@ public override Vector3 GetPosition(
195204

196205
OwnerQuest.QuestPrefab = prefabInstance;
197206

198-
OwnerQuest.DataVariables.Add("POIName", OwnerQuest.QuestPrefab.location.Name);
207+
OwnerQuest.DataVariables.Add("POIName", Localization.Get(OwnerQuest.QuestPrefab.location.Name));
199208

200209
if (usedPoiLocations != null)
201210
{
@@ -230,6 +239,11 @@ public override Vector3 GetPosition(
230239
return Vector3.zero;
231240
}
232241

242+
/// <summary>
243+
/// Converts a 2D location representing the center of a prefab to a 3D position in the world.
244+
/// </summary>
245+
/// <param name="prefabCenter"></param>
246+
/// <returns></returns>
233247
public static Vector3 PrefabCenterToPosition(Vector2 prefabCenter)
234248
{
235249
// Since the center is a 2D vector, its "y" is actually the z-axis position
@@ -245,9 +259,9 @@ public static Vector3 PrefabCenterToPosition(Vector2 prefabCenter)
245259
/// <returns></returns>
246260
public override BaseObjective Clone()
247261
{
248-
var objectiveRandomPOIGoto = new ObjectiveRandomTaggedPOIGotoSDX();
249-
CopyValues(objectiveRandomPOIGoto);
250-
return objectiveRandomPOIGoto;
262+
var objective = new ObjectiveRandomTaggedPOIGotoSDX();
263+
CopyValues(objective);
264+
return objective;
251265
}
252266

253267
/// <summary>
@@ -262,20 +276,12 @@ public override void CopyValues(BaseObjective objective)
262276
obj.ExcludeTags = ExcludeTags;
263277
obj.MinSearchDistance = MinSearchDistance;
264278
obj.MaxSearchDistance = MaxSearchDistance;
265-
}
266-
267-
/// <summary>
268-
/// Copied verbatim from ObjectiveRandomPOIGoto, made protected so any future subclasses won't
269-
/// have to do the same thing.
270-
/// </summary>
271-
/// <param name="poiSize"></param>
272-
protected void SetDistanceOffset(Vector3 poiSize)
273-
{
274-
if (poiSize.x > poiSize.z)
275-
{
276-
distanceOffset = poiSize.x;
277-
return;
278-
}
279-
distanceOffset = poiSize.z;
279+
// These values are copied in ObjectiveRandomPOIGoto.Clone, and this class can't call that
280+
// base class method because it creates the wrong object type. So, copy the values here.
281+
obj.poiTier = poiTier;
282+
obj.distance = distance;
283+
obj.biomeFilterType = biomeFilterType;
284+
obj.biomeFilter = biomeFilter;
285+
obj.locationName = locationName;
280286
}
281287
}

Mods/0-SCore/Scripts/Quests/QuestUtils.cs

Lines changed: 99 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -129,26 +129,27 @@ public static PrefabInstance GetRandomPOINearTrader(
129129
BiomeFilterTypes biomeFilterType = BiomeFilterTypes.AnyBiome,
130130
string biomeFilter = "")
131131
{
132-
var world = GameManager.Instance.World;
132+
var current = QuestEventManager.Current;
133+
var gameRandom = GameManager.Instance.World.GetGameRandom();
134+
var distanceIndex = trader.PreferredDistanceIndex;
135+
var distanceIndexes = GetDistanceIndexes(minSearchDistance, maxSearchDistance);
136+
for (var i = 0; i < 3; i++)
137+
{
138+
distanceIndex %= 3;
133139

134-
var minDistanceTier = minSearchDistance < 0 ? 0 : GetTraderPrefabListTier(minSearchDistance);
135-
var maxDistanceTier = maxSearchDistance < 0 ? 2 : GetTraderPrefabListTier(maxSearchDistance);
140+
if (!distanceIndexes.Contains(distanceIndex))
141+
{
142+
distanceIndex++;
143+
continue;
144+
}
136145

137-
for (var distanceTier = minDistanceTier; distanceTier <= maxDistanceTier; distanceTier++)
138-
{
139-
var prefabsForTrader = QuestEventManager.Current.GetPrefabsForTrader(
140-
trader.traderArea,
141-
difficulty,
142-
distanceTier,
143-
world.GetGameRandom());
144-
145-
if (prefabsForTrader == null) continue;
146-
// GetPrefabsForTrader shuffles the prefabs before returning them, so we can just
147-
// iterate through the list and still send players to "random" POIs
148-
for (var j = 0; j < prefabsForTrader.Count; j++)
146+
var prefabsForTrader = current.GetPrefabsForTrader(trader.traderArea, difficulty, distanceIndex, gameRandom);
147+
if (prefabsForTrader != null)
149148
{
150-
var prefabInstance = prefabsForTrader[j];
151-
if (ValidPrefabForQuest(
149+
for (var j = 0; j < prefabsForTrader.Count; j++)
150+
{
151+
PrefabInstance prefabInstance = prefabsForTrader[j];
152+
if (ValidPrefabForQuest(
152153
trader,
153154
prefabInstance,
154155
questTag,
@@ -160,15 +161,85 @@ public static PrefabInstance GetRandomPOINearTrader(
160161
biomeFilter,
161162
minSearchDistance,
162163
maxSearchDistance))
163-
{
164-
return prefabInstance;
164+
{
165+
return prefabInstance;
166+
}
165167
}
166168
}
169+
170+
distanceIndex++;
167171
}
168172

169173
return null;
170174
}
171175

176+
/// <summary>
177+
/// <para>
178+
/// Takes the minumum and maximum search distances, and returns the vanilla distance indexes
179+
/// that are compatible with those search distances. It is meant to avoid searching through
180+
/// lists of POIs by distance index, if none of those POIs can be within range.
181+
/// </para>
182+
/// <para>
183+
/// <list type="table">
184+
/// <listheader>
185+
/// <term>index</term>
186+
/// <description>distance range</description>
187+
/// </listheader>
188+
/// <item>
189+
/// <term>0</term>
190+
/// <description>0 - 500</description>
191+
/// </item>
192+
/// <item>
193+
/// <term>1</term>
194+
/// <description>501 - 1500</description>
195+
/// </item>
196+
/// <item>
197+
/// <term>2</term>
198+
/// <description>1501+</description>
199+
/// </item>
200+
/// </list>
201+
/// Taken from <see cref="QuestEventManager.SetupTraderPrefabList"/>
202+
/// </para>
203+
/// </summary>
204+
/// <param name="minSearchDistance">Minimum search distance, in blocks/meters</param>
205+
/// <param name="maxSearchDistance">Maximum search distance, in blocks/meters</param>
206+
/// <returns></returns>
207+
public static List<int> GetDistanceIndexes(float minSearchDistance, float maxSearchDistance)
208+
{
209+
var allIndexes = new List<int> { 0, 1, 2 };
210+
211+
if (minSearchDistance > maxSearchDistance)
212+
{
213+
// Invalid entries. Just use the vanilla indexes.
214+
return allIndexes;
215+
}
216+
217+
if (minSearchDistance < 0 && maxSearchDistance < 0)
218+
{
219+
// No min or max specified. Use the vanilla indexes.
220+
return allIndexes;
221+
}
222+
223+
if (minSearchDistance <= 500f && maxSearchDistance > 1500f)
224+
{
225+
// This is within the entire range of vanilla indexes.
226+
return allIndexes;
227+
}
228+
229+
// Remove the indexes according to the min and max distance.
230+
if (minSearchDistance > 500f)
231+
allIndexes.Remove(0);
232+
if (minSearchDistance > 1500f)
233+
allIndexes.Remove(1);
234+
235+
if (maxSearchDistance >= 0 && maxSearchDistance <= 1500f)
236+
allIndexes.Remove(2);
237+
if (maxSearchDistance >= 0 && maxSearchDistance <= 500f)
238+
allIndexes.Remove(1);
239+
240+
return allIndexes;
241+
}
242+
172243
/// <summary>
173244
/// Gets a random POI near an entity's position. This is meant to be a replacement for
174245
/// <see cref="DynamicPrefabDecorator.GetRandomPOINearWorldPos"/>
@@ -290,14 +361,14 @@ public static bool ValidPrefabForQuest(
290361
return false;
291362
}
292363

293-
//if (!prefab.prefab.GetQuestTag(questTag))
294-
//{
295-
// if (LoggingEnabled)
296-
// {
297-
// Log.Out($"Quest {questTag}: Prefab {prefab.name} does not have quest tag {questTag}");
298-
// }
299-
// return false;
300-
//}
364+
if (!questTag.IsEmpty && !prefab.prefab.GetQuestTag(questTag))
365+
{
366+
if (LoggingEnabled)
367+
{
368+
Log.Out($"Quest {questTag}: Prefab {prefab.name} does not have quest tag {questTag}");
369+
}
370+
return false;
371+
}
301372

302373
Vector2 poiLocation = new Vector2(prefab.boundingBoxPosition.x, prefab.boundingBoxPosition.z);
303374

@@ -310,7 +381,7 @@ public static bool ValidPrefabForQuest(
310381
return false;
311382
}
312383

313-
QuestEventManager.POILockoutReasonTypes lockoutReason = QuestEventManager.Current.CheckForPOILockouts(entityIdForQuests, poiLocation, out var num);
384+
QuestEventManager.POILockoutReasonTypes lockoutReason = QuestEventManager.Current.CheckForPOILockouts(entityIdForQuests, poiLocation, out _);
314385

315386
if (lockoutReason != QuestEventManager.POILockoutReasonTypes.None)
316387
{

0 commit comments

Comments
 (0)