-
Notifications
You must be signed in to change notification settings - Fork 324
/
PcAt.cs
189 lines (167 loc) · 6.39 KB
/
PcAt.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Project: Daggerfall Unity
// Copyright: Copyright (C) 2009-2023 Daggerfall Workshop
// Web Site: http://www.dfworkshop.net
// License: MIT License (http://www.opensource.org/licenses/mit-license.php)
// Source Code: https://github.com/Interkarma/daggerfall-unity
// Original Author: Gavin Clayton (interkarma@dfworkshop.net)
// Contributors:
//
// Notes:
//
using UnityEngine;
using System.Collections;
using System.Text.RegularExpressions;
using System;
using DaggerfallConnect;
using FullSerializer;
using DaggerfallWorkshop.Utility;
namespace DaggerfallWorkshop.Game.Questing.Actions
{
/// <summary>
/// Condition which checks if player character at a specific place.
/// </summary>
public class PcAt : ActionTemplate
{
Symbol placeSymbol;
Symbol taskSymbol;
int textId;
bool textShown;
// Place type parameters
int p2; // Parameter 2
int p3; // Parameter 3
public override string Pattern
{
// Notes:
// Docs use form "pc at aPlace do aTask"
// But observed quests actually seem to use "pc at aPlace set aTask"
// 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 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)
: base(parentQuest)
{
}
public override IQuestAction CreateNew(string source, Quest parentQuest)
{
// Source must match pattern
Match match = Test(source);
if (!match.Success)
return null;
// Factory new pcat
PcAt pcat = new PcAt(parentQuest);
// 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);
return pcat;
}
/// <summary>
/// Continuously checks where player is and sets target true/false based on site properties.
/// </summary>
public override void Update(Task caller)
{
bool result;
if (placeSymbol != null)
{
// Get place resource
Place place = ParentQuest.GetPlace(placeSymbol);
if (place == null)
return;
// Check if player at this place
result = place.IsPlayerHere();
}
else
{
result = Place.IsPlayerAtBuildingType(p2, p3);
}
// Handle positive check
if (result)
{
// "saying" popup
// Only display this once or player can get a popup loop
if (textId != 0 && !textShown)
{
ParentQuest.ShowMessagePopup(textId);
textShown = true;
}
// Start target task
ParentQuest.StartTask(taskSymbol);
}
else
{
// Clear target task
ParentQuest.ClearTask(taskSymbol);
}
}
#region Serialization
[fsObject("v1")]
public struct SaveData_v1
{
public Symbol placeSymbol;
public Symbol taskSymbol;
public int textId;
public bool textShown;
// Place type parameters
public int p2;
public int p3;
}
public override object GetSaveData()
{
SaveData_v1 data = new SaveData_v1();
data.placeSymbol = placeSymbol;
data.taskSymbol = taskSymbol;
data.textId = textId;
data.textShown = textShown;
data.p2 = p2;
data.p3 = p3;
return data;
}
public override void RestoreSaveData(object dataIn)
{
if (dataIn == null)
return;
SaveData_v1 data = (SaveData_v1)dataIn;
placeSymbol = data.placeSymbol;
taskSymbol = data.taskSymbol;
textId = data.textId;
textShown = data.textShown;
p2 = data.p2;
p3 = data.p3;
}
#endregion
}
}