Skip to content

Commit

Permalink
Fix pickup issues (#592)
Browse files Browse the repository at this point in the history
Resolves #591.
  • Loading branch information
lahm86 authored Jan 13, 2024
1 parent a65b5ec commit 2c436d7
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 53 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
## [Unreleased](https://github.com/LostArtefacts/TR-Rando/compare/V1.8.1...master) - xxxx-xx-xx
- fixed some pickups appearing in unreachable locations in TR2 (#591)
- fixed inaccurate pickup statistics in TR1 when playing one-item mode (#591)
- fixed additional secret rewards being placed in non-existent rooms when not randomizing secrets in TR1 (#591)
- fixed a secret becoming invisible after blowing up the final area in Bartoli's Hideout (#591)

## [V1.8.1](https://github.com/LostArtefacts/TR-Rando/compare/V1.8.0...V1.8.1) - 2023-12-15
- fixed floor data issues in mirrored levels in TRUB (#583)
Expand Down
2 changes: 2 additions & 0 deletions TRRandomizerCore/Randomizers/TR1/TR1ItemRandomizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ public void EnforceOneLimit(TR1CombinedLevel level)
}

// Look for extra utility/ammo items and hide them
level.Script.UnobtainablePickups ??= 0;
for (int i = 0; i < level.Data.Entities.Count; i++)
{
TR1Entity entity = level.Data.Entities[i];
Expand All @@ -299,6 +300,7 @@ public void EnforceOneLimit(TR1CombinedLevel level)
{
ItemUtilities.HideEntity(entity);
ItemFactory.FreeItem(level.Name, i);
level.Script.UnobtainablePickups++;
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions TRRandomizerCore/Randomizers/TR1/TR1SecretRewardRandomizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ private void RandomizeRewards(TR1CombinedLevel level)
stdItemTypes.Remove(TR1Type.PistolAmmo_S_P); // Sprite/model not available
stdItemTypes.Remove(TR1Type.Pistols_S_P); // A bit cruel as a reward?

int secretRoom = RoomWaterUtilities.DefaultRoomCountDictionary[level.Name];
List<Location> rewardPositions = secretMapping.Rooms.First().RewardPositions;
List<int> rewardIndices = new(secretMapping.RewardEntities);

// Pile extra pickups on top of existing ones, either in their default spots
// or in the generated reward rooms.
List<Location> rewardPositions = new(rewardIndices.Select(i => level.Data.Entities[i].GetLocation()));

// Give at least one item per secret, never less than the original reward item count,
// and potentially some extra bonus items.
int rewardCount = Math.Max(rewardIndices.Count, level.Script.NumSecrets);
Expand All @@ -68,9 +70,10 @@ private void RandomizeRewards(TR1CombinedLevel level)

while (rewardIndices.Count < rewardCount)
{
TR1Entity item = ItemFactory.CreateItem(level.Name, level.Data.Entities, rewardPositions[_generator.Next(0, rewardPositions.Count)], true);
Location location = rewardPositions[_generator.Next(0, rewardPositions.Count)];
TR1Entity item = ItemFactory.CreateItem(level.Name, level.Data.Entities, location, true);
rewardIndices.Add(level.Data.Entities.IndexOf(item));
item.Room = (short)secretRoom;
item.Room = (short)location.Room;
}

foreach (int rewardIndex in rewardIndices)
Expand Down
90 changes: 41 additions & 49 deletions TRRandomizerCore/Randomizers/TR2/TR2EnemyRandomizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -837,64 +837,56 @@ private void LimitSkidooEntities(TR2CombinedLevel level)
}
}

if (skidooRemovalCount > 0)
if (skidooRemovalCount == 0)
{
FDControl floorData = new();
floorData.ParseFromLevel(level.Data);
TR2LocationGenerator locationGenerator = new();
List<TR2Type> replacementPool;
if (!Settings.RandomizeItems || Settings.RandoItemDifficulty == ItemDifficulty.Default)
{
// The user is not specifically attempting one-item rando, so we can add anything as replacements
replacementPool = TR2TypeUtilities.GetAmmoTypes();
}
else
{
// Camera targets don't take up any savegame space, so in one-item mode use these as replacements
replacementPool = new List<TR2Type> { TR2Type.CameraTarget_N };
}
return;
}

List<TR2Entity> skidMen;
for (int i = 0; i < skidooRemovalCount; i++)
{
skidMen = level.Data.Entities.FindAll(e => e.TypeID == TR2Type.MercSnowmobDriver);
if (skidMen.Count == 0)
{
break;
}
FDControl floorData = new();
floorData.ParseFromLevel(level.Data);
List<Location> pickupLocations = level.Data.Entities
.Where(e => TR2TypeUtilities.IsAnyPickupType(e.TypeID) && !TR2TypeUtilities.IsSecretType(e.TypeID))
.Select(e => e.GetLocation())
.ToList();

// Select a random Skidoo driver and convert him into something else
TR2Entity skidMan = skidMen[_generator.Next(0, skidMen.Count)];
TR2Type newType = replacementPool[_generator.Next(0, replacementPool.Count)];
skidMan.TypeID = newType;
List<TR2Type> replacementPool;
if (!Settings.RandomizeItems || Settings.RandoItemDifficulty == ItemDifficulty.Default)
{
// The user is not specifically attempting one-item rando, so we can add anything as replacements
replacementPool = TR2TypeUtilities.GetAmmoTypes();
}
else
{
// Camera targets don't take up any savegame space, so in one-item mode use these as replacements
replacementPool = new() { TR2Type.CameraTarget_N };
}

if (TR2TypeUtilities.IsAnyPickupType(newType))
{
// Make sure the pickup is pickupable
TRRoomSector sector = FDUtilities.GetRoomSector(skidMan.X, skidMan.Y, skidMan.Z, skidMan.Room, level.Data, floorData);
skidMan.Y = sector.Floor * TRConsts.Step1;
skidMan.Invisible = false;
List<TR2Entity> skidMen;
for (int i = 0; i < skidooRemovalCount; i++)
{
skidMen = level.Data.Entities.FindAll(e => e.TypeID == TR2Type.MercSnowmobDriver);
if (skidMen.Count == 0)
{
break;
}

if (sector.FDIndex != 0)
{
FDEntry entry = floorData.Entries[sector.FDIndex].Find(e => e is FDSlantEntry s && s.Type == FDSlantEntryType.FloorSlant);
if (entry is FDSlantEntry slant)
{
Vector4? bestMidpoint = locationGenerator.GetBestSlantMidpoint(slant);
if (bestMidpoint.HasValue)
{
skidMan.Y += (int)bestMidpoint.Value.Y;
}
}
}
}
// Select a random Skidoo driver and convert him into something else
TR2Entity skidMan = skidMen[_generator.Next(0, skidMen.Count)];
TR2Type newType = replacementPool[_generator.Next(0, replacementPool.Count)];
skidMan.TypeID = newType;
skidMan.Invisible = false;

// Get rid of the old enemy's triggers
FDUtilities.RemoveEntityTriggers(level.Data, level.Data.Entities.IndexOf(skidMan), floorData);
if (TR2TypeUtilities.IsAnyPickupType(newType))
{
// Move the pickup to another pickup location
skidMan.SetLocation(pickupLocations[_generator.Next(0, pickupLocations.Count)]);
}

floorData.WriteToLevel(level.Data);
// Get rid of the old enemy's triggers
FDUtilities.RemoveEntityTriggers(level.Data, level.Data.Entities.IndexOf(skidMan), floorData);
}

floorData.WriteToLevel(level.Data);
}

private void LimitFriendlyEnemies(TR2CombinedLevel level, List<TR2Type> pool, List<TR2Type> friends)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2096,6 +2096,32 @@
}
}
]
},
{
"Condition": {
"ConditionType": 0,
"EntityIndex": 125,
"X": 36352,
"Y": -256,
"Z": 35328,
"Room": 131
},
"OnFalse": [
{
"EMType": 71,
"Locations": [
{
"X": 37376,
"Y": 3840,
"Z": 18944,
"Room": 73
}
],
"ActionItem": {
"Parameter": 125
}
}
]
}
],
"ConditionalOneOf": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,30 @@
}
],
[
{
"Comments": "Move any pickups before making new walls.",
"EMType": 43,
"SectorLocations": [
{
"X": 53834,
"Y": -9216,
"Z": 61058,
"Room": 2
},
{
"X": 51702,
"Y": -9216,
"Z": 60953,
"Room": 2
}
],
"TargetLocation": {
"X": 52736,
"Y": -9216,
"Z": 62976,
"Room": 2
}
},
{
"Comments": "Make some blocks before the arena.",
"EMType": 1,
Expand Down

0 comments on commit 2c436d7

Please sign in to comment.