Skip to content

Commit

Permalink
Added "pc at any <buildingType>" as an extension to "pc at <place>". …
Browse files Browse the repository at this point in the history
…Instead of taking the symbol of a place as a parameter, it takes a building type (p1=0 in Quests-Places), and the trigger condition is true when the player is inside any building of this type.
  • Loading branch information
KABoissonneault committed May 18, 2021
1 parent 57ccc98 commit 0f83e63
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 27 deletions.
69 changes: 60 additions & 9 deletions Assets/Scripts/Game/Questing/Actions/PcAt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
using DaggerfallConnect;
using FullSerializer;

using DaggerfallWorkshop.Utility;

namespace DaggerfallWorkshop.Game.Questing.Actions
{
/// <summary>
Expand All @@ -27,6 +29,9 @@ public class PcAt : ActionTemplate
Symbol taskSymbol;
int textId;
bool textShown;
// Place type parameters
int p2; // Parameter 2
int p3; // Parameter 3

public override string Pattern
{
Expand All @@ -36,10 +41,16 @@ public override string Pattern
// Probably a change between writing of docs and Template v1.11.
// Supporting both variants as quest authors are working from docs
// Docs also missing "pc at aPlace set aTask saying nnnn"
// DFU extension: also adding "pc at any <placeType>" so quests can check for any place of a certain type
get { return @"pc at (?<aPlace>\w+) set (?<aTask>[a-zA-Z0-9_.]+) saying (?<id>\d+)|" +
@"pc at (?<aPlace>\w+) set (?<aTask>[a-zA-Z0-9_.]+)|" +
@"pc at (?<aPlace>\w+) do (?<aTask>[a-zA-Z0-9_.]+) saying (?<id>\d+)|" +
@"pc at (?<aPlace>\w+) do (?<aTask>[a-zA-Z0-9_.]+)"; }
@"pc at (?<aPlace>\w+) do (?<aTask>[a-zA-Z0-9_.]+)|" +
@"pc at any (?<placeType>\w+) set (?<aTask>[a-zA-Z0-9_.]+) saying (?<id>\d+)|" +
@"pc at any (?<placeType>\w+) set (?<aTask>[a-zA-Z0-9_.]+)|" +
@"pc at any (?<placeType>\w+) do (?<aTask>[a-zA-Z0-9_.]+) saying (?<id>\d+)|" +
@"pc at any (?<placeType>\w+) do (?<aTask>[a-zA-Z0-9_.]+)";
}
}

public PcAt(Quest parentQuest)
Expand All @@ -56,7 +67,33 @@ public override IQuestAction CreateNew(string source, Quest parentQuest)

// Factory new pcat
PcAt pcat = new PcAt(parentQuest);
pcat.placeSymbol = new Symbol(match.Groups["aPlace"].Value);

// If this is a classic "pc at" action, use a declared location
if (string.IsNullOrEmpty(match.Groups["placeType"].Value))
{
pcat.placeSymbol = new Symbol(match.Groups["aPlace"].Value);
}
else
{
string name = match.Groups["placeType"].Value;
Table placesTable = QuestMachine.Instance.PlacesTable;
if (placesTable.HasValue(name))
{
// Store values
int p1 = Place.CustomParseInt(placesTable.GetValue("p1", name));
if(p1 != 0 && p1 != 1)
{
throw new Exception("PcAt: This trigger condition can only be used with building types (p1=0) in Quests-Places table.");
}
pcat.p2 = Place.CustomParseInt(placesTable.GetValue("p2", name));
pcat.p3 = Place.CustomParseInt(placesTable.GetValue("p3", name));
}
else
{
throw new Exception(string.Format("PcAt: Could not find place type name in data table: '{0}'", name));
}
}

pcat.taskSymbol = new Symbol(match.Groups["aTask"].Value);
pcat.textId = Parser.ParseInt(match.Groups["id"].Value);

Expand All @@ -68,15 +105,22 @@ public override IQuestAction CreateNew(string source, Quest parentQuest)
/// </summary>
public override void Update(Task caller)
{
bool result = false;
bool result;

// Get place resource
Place place = ParentQuest.GetPlace(placeSymbol);
if (place == null)
return;
if (placeSymbol != null)
{
// Get place resource
Place place = ParentQuest.GetPlace(placeSymbol);
if (place == null)
return;

// Check if player at this place
result = place.IsPlayerHere();
// Check if player at this place
result = place.IsPlayerHere();
}
else
{
result = Place.IsPlayerAtBuildingType(p2, p3);
}

// Handle positive check
if (result)
Expand Down Expand Up @@ -108,6 +152,9 @@ public struct SaveData_v1
public Symbol taskSymbol;
public int textId;
public bool textShown;
// Place type parameters
public int p2;
public int p3;
}

public override object GetSaveData()
Expand All @@ -117,6 +164,8 @@ public override object GetSaveData()
data.taskSymbol = taskSymbol;
data.textId = textId;
data.textShown = textShown;
data.p2 = p2;
data.p3 = p3;

return data;
}
Expand All @@ -131,6 +180,8 @@ public override void RestoreSaveData(object dataIn)
taskSymbol = data.taskSymbol;
textId = data.textId;
textShown = data.textShown;
p2 = data.p2;
p3 = data.p3;
}

#endregion
Expand Down
76 changes: 58 additions & 18 deletions Assets/Scripts/Game/Questing/Place.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Globalization;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;
using DaggerfallWorkshop;
using DaggerfallWorkshop.Utility;
using DaggerfallConnect;
Expand Down Expand Up @@ -569,9 +570,66 @@ public void ReassignSiteDetailsLegacyMarkers()
}
}

/// <summary>
/// Custom parser to handle hex or decimal values from places data table.
/// </summary>
public static int CustomParseInt(string value)
{
int result;
if (value.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
{
result = int.Parse(value.Replace("0x", ""), NumberStyles.HexNumber);
}
else
{
result = int.Parse(value);
}

return result;
}

static readonly int[] validBuildingTypes = { 0, 2, 3, 5, 6, 8, 9, 11, 12, 13, 14, 15, 17, 18, 19, 20 };
static readonly int[] validHouseTypes = { 17, 18, 19, 20 };
static readonly int[] validShopTypes = { 0, 2, 5, 6, 7, 8, 9, 12, 13 }; // not including bank and library

public static bool IsPlayerAtPlaceType(int p1, int p2, int p3)
{
// Get component handling player world status and transitions
PlayerEnterExit playerEnterExit = GameManager.Instance.PlayerEnterExit;
if (!playerEnterExit)
return false;

// Only support building types for now
if (p1 != 0)
return false;

if (!playerEnterExit.IsPlayerInsideBuilding)
return false;

int buildingType = (int)playerEnterExit.Interior.BuildingData.BuildingType;

// DFU extensions
if (p2 == -1)
{
switch(p3)
{
case 0: // random
return validBuildingTypes.Contains(buildingType);
case 1: // house
return validHouseTypes.Contains(buildingType);
case 2: // shop
return validShopTypes.Contains(buildingType);
default: // unhandled
Debug.LogWarning($"Unhandled building type: p1={p1}, p2={p2}, p3={p3}");
return false;
}
}
else
{
return buildingType == p2;
}
}

#endregion

#region Local Site Methods
Expand Down Expand Up @@ -986,24 +1044,6 @@ void SetupFixedLocation()

#region Private Methods

/// <summary>
/// Custom parser to handle hex or decimal values from places data table.
/// </summary>
int CustomParseInt(string value)
{
int result = -1;
if (value.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
{
result = int.Parse(value.Replace("0x", ""), NumberStyles.HexNumber);
}
else
{
result = int.Parse(value);
}

return result;
}

/// <summary>
/// Checks if location is one of the dungeon types.
/// </summary>
Expand Down

0 comments on commit 0f83e63

Please sign in to comment.