2using System.Collections.Generic;
5using System.Reflection;
6using System.Runtime.CompilerServices;
7using System.Text.RegularExpressions;
12 private static readonly Dictionary<string, DramaActionParser>
_actionParsers =
new Dictionary<string, DramaActionParser>(StringComparer.OrdinalIgnoreCase);
14 private static readonly Dictionary<string, DramaInvokeDetail>
_invokes =
new Dictionary<string, DramaInvokeDetail>(StringComparer.OrdinalIgnoreCase);
16 internal static readonly Regex
_expressionRegex =
new Regex(
"^\\s*(?<f>\\w+)\\s*(?:\\(\\s*(?<p>.*)\\s*\\))?\\s*$", RegexOptions.Compiled);
18 public static bool ParseAction(
string action,
DramaManager dm, Dictionary<string, string> line)
22 return value(dm, line);
30 Debug.Log(
"#drama added new action parser '" + action +
"' from '" + parser.Method.TryToString() +
"'");
31 bool SafeInvoke(
DramaManager dm, Dictionary<string, string> line)
35 return parser(dm, line);
39 ModUtil.LogModError(
"exception while parsing drama action '" + action +
"'\n" + ex.Message, parser.Method.DeclaringType);
40 Debug.LogException(ex);
46 public static void AddDramaInvokeMethod(
string name, MethodInfo method,
string contract =
null)
51 public static void AddDramaInvokeMethod(
string name,
DramaInvokeFunc func,
string contract =
null)
53 AddDramaInvokeMethod(name, func.Method, contract);
56 internal static (
DramaInvokeDetail invoke,
string[] parameters) BuildInvokeExpression(
string expression)
58 (string,
string[]) tuple = ParseInvokeExpression(expression);
59 if (!tuple.Item1.IsEmpty() &&
_invokes.TryGetValue(tuple.Item1, out var value))
61 return (invoke: value, parameters: tuple.Item2);
63 if (expression.Length <= 1)
67 return expression[0]
switch
69 '!' => BuildInvokeExpression(
"not(" + expression[1..] +
")"),
70 '&' => BuildInvokeExpression(
"and(" + expression[1..] +
")"),
71 '?' => BuildInvokeExpression(
"or(" + expression[1..] +
")"),
76 internal static (
string funcName,
string[] parameters) ParseInvokeExpression(
string expression)
78 if (expression.IsEmpty())
80 return (funcName:
"", parameters: Array.Empty<
string>());
83 return (funcName: match.Groups[
"f"].Value, parameters:
SplitParams(match.Groups[
"p"].Value));
88 return Array.Empty<
string>();
90 List<string> list =
new List<string>();
94 for (
int i = 0; i < args.Length; i++)
121 string s2 = args[num2..i].Trim();
130 if (num2 < args.Length)
132 string text = args[num2..].Trim();
138 return list.ToArray();
140 static string Unquote(
string s)
142 if (s.Length >= 2 && ((s[0] ==
'"' && s[^1] ==
'"') || (s[0] ==
'\'' && s[^1] ==
'\'')))
150 [ElinDramaActionParser(
"i*")]
151 [ElinDramaActionParser(
"invoke*")]
154 string text = line[
"param"].Trim().RemoveNewline();
155 if (text.StartsWith(
"//"))
159 var (invoke, parameters) = BuildInvokeExpression(text);
160 if (invoke.
Method ==
null)
162 ModUtil.LogModError(
"invalid drama invoke* expression '" + text +
"'",
new FileInfo(dm.
path));
165 string jump = line[
"jump"];
170 jumpFunc = () => (!invoke.
SafeInvoke(dm, line, parameters)) ?
"" : jump
181 [ElinDramaActionParser(
"eval")]
184 string expr = line[
"param"];
189 EScriptSubmission submission = EScriptSubmission.Create(dm.
setup.
book);
195 string jump = line[
"jump"];
196 bool flag = !jump.IsEmpty();
197 bool flag2 = !line[
"id"].IsEmpty();
200 Dictionary<string, string>
item =
new Dictionary<string, string>(line)
206 dm.lastTalk.activeCondition = delegate
208 object obj2 = DeferredCompileAndRun();
209 return obj2 is
bool && (bool)obj2;
219 object obj = DeferredCompileAndRun();
220 if (obj is
string result)
224 return (obj is
bool && !(
bool)obj) ?
"" : jump;
231 DeferredCompileAndRun();
234 object DeferredCompileAndRun()
236 if (expr.StartsWith(
"<<<"))
238 string text = expr[3..].Trim();
239 string path = Path.Combine(Path.GetDirectoryName(dm.
path), text);
240 if (!File.Exists(path))
242 throw new FileNotFoundException(text);
244 expr = File.ReadAllText(path);
250 [MethodImpl(MethodImplOptions.AggressiveInlining)]
251 [ElinDramaActionInvoke(
"nodiscard,passthrough")]
252 public static bool eval(
DramaManager dm, Dictionary<string, string> line, params
string[] parameters)
254 string text =
string.Join(
',', parameters);
259 EScriptSubmission eScriptSubmission = EScriptSubmission.Create(dm.
setup.
book);
265 if (text.StartsWith(
"<<<"))
267 string text2 = text[3..].Trim();
268 string path = Path.Combine(Path.GetDirectoryName(dm.
path), text2);
269 if (!File.Exists(path))
271 throw new FileNotFoundException(text2);
273 text = File.ReadAllText(path);
283 [MethodImpl(MethodImplOptions.AggressiveInlining)]
284 [ElinDramaActionInvoke(
"nodiscard")]
285 public static bool and(
DramaManager dm, Dictionary<string, string> line, params
string[] parameters)
287 return parameters.All(delegate(
string expr)
289 var (dramaInvokeDetail, parameters2) = BuildInvokeExpression(expr);
290 return dramaInvokeDetail.SafeInvoke(dm, line, parameters2);
294 [MethodImpl(MethodImplOptions.AggressiveInlining)]
295 [ElinDramaActionInvoke(
"nodiscard")]
296 public static bool or(
DramaManager dm, Dictionary<string, string> line, params
string[] parameters)
298 return parameters.Any(delegate(
string expr)
300 var (dramaInvokeDetail, parameters2) = BuildInvokeExpression(expr);
301 return dramaInvokeDetail.SafeInvoke(dm, line, parameters2);
305 [MethodImpl(MethodImplOptions.AggressiveInlining)]
306 [ElinDramaActionInvoke(
"nodiscard")]
307 public static bool not(
DramaManager dm, Dictionary<string, string> line, params
string[] parameters)
309 return parameters.All(delegate(
string expr)
311 var (dramaInvokeDetail, parameters2) = BuildInvokeExpression(expr);
312 return !dramaInvokeDetail.SafeInvoke(dm, line, parameters2);
316 [MethodImpl(MethodImplOptions.AggressiveInlining)]
317 [ElinDramaActionInvoke(
null)]
320 string.Join(
' ', parameters).EvaluateAsCommand();
324 [ElinDramaActionInvoke(
null)]
325 public static bool add_item(
DramaManager dm, Dictionary<string, string> line,
string itemId,
string materialAlias =
"wood",
int lv = -1,
int count = 1)
334 [ElinDramaActionInvoke(
null)]
341 [ElinDramaActionInvoke(
null)]
348 [ElinDramaActionInvoke(
null)]
361 count = Math.Max(count, 0);
362 foreach (
Thing item2
in list)
368 if (item2.
Num >= count)
380 [ElinDramaActionInvoke(
null)]
385 if (
item.source.alias == conditionAlias)
393 [ElinDramaActionInvoke(
null)]
397 if (religionId.IsEmpty())
408 [ElinDramaActionInvoke(
null)]
417 [ElinDramaActionInvoke(
"nodiscard")]
424 [ElinDramaActionInvoke(
"nodiscard")]
433 if (condition.
source.alias == conditionAlias)
435 return expr.Compare(condition.
value);
441 [ElinDramaActionInvoke(
"nodiscard")]
445 return expr.Compare(chara.
GetCurrency(currencyId));
448 [ElinDramaActionInvoke(
"nodiscard")]
454 return expr.Compare(chara.
Evalue(elementAlias));
459 [ElinDramaActionInvoke(
"nodiscard")]
467 if (
faith.id == religionId)
469 return expr.Compare(
faith.giftRank);
474 [ElinDramaActionInvoke(
"nodiscard")]
480 [ElinDramaActionInvoke(
"nodiscard")]
488 return expr.Compare(chara.
GetInt(flagKey));
491 [ElinDramaActionInvoke(
"nodiscard")]
502 [ElinDramaActionInvoke(
"nodiscard")]
506 Match match = Regex.Match(expression,
"^(?<op>>=|<=|>|<|=|!=|==)?(?<h>.+)$");
509 throw new ArgumentException(
"invalid expression " + expression);
511 string value = match.Groups[
"op"].Value;
512 if (!Enum.TryParse<
Hostility>(match.Groups[
"h"].Value, ignoreCase:
true, out var result))
514 throw new ArgumentException(
"invalid hostility " + match.Groups[
"h"].Value);
519 [ElinDramaActionInvoke(
"nodiscard")]
525 [ElinDramaActionInvoke(
"nodiscard")]
534 return expr.Compare(value2);
539 [ElinDramaActionInvoke(
"nodiscard")]
543 return expr.Compare(chara.
LV);
546 [ElinDramaActionInvoke(
"nodiscard")]
547 public static bool if_race(
DramaManager dm, Dictionary<string, string> line,
string raceId)
552 [ElinDramaActionInvoke(
"nodiscard")]
553 public static bool if_tag(
DramaManager dm, Dictionary<string, string> line,
string tag)
558 [ElinDramaActionInvoke(
"nodiscard")]
559 public static bool if_zone(
DramaManager dm, Dictionary<string, string> line,
string zoneId,
int zoneLv = 99999)
562 if (currentZone ==
null)
566 if (currentZone.
id == zoneId)
570 return currentZone.lv == zoneLv;
577 [ElinDramaActionInvoke(
"nodiscard")]
581 Zone zone = ModUtil.FindZoneByFullName(zoneFullName);
582 return currentZone == zone;
585 [ElinDramaActionInvoke(
null)]
593 [ElinDramaActionInvoke(
null)]
602 [ElinDramaActionInvoke(
null)]
603 public static bool mod_element(
DramaManager dm, Dictionary<string, string> line,
string elementAlias,
int value = 1,
int potential = 100)
607 if (orCreateElement !=
null)
609 if (orCreateElement is
Feat)
621 [ElinDramaActionInvoke(
null)]
626 if (orCreateElement ==
null)
630 chara.
ModExp(orCreateElement.
id, expr.Diff(orCreateElement.
vExp));
634 [ElinDramaActionInvoke(
null)]
641 [ElinDramaActionInvoke(
null)]
649 chara.
SetInt(flagKey, expr.ModOrSet(chara.
GetInt(flagKey)));
653 [ElinDramaActionInvoke(
"nodiscard")]
665 keyItems.TryAdd(value.id, 0);
666 int num = keyItems[value.id];
667 int num2 = expr.ModOrSet(keyItems[value.id]);
671 Msg.
Say(
"get_keyItem", value.GetName());
675 SE.Play(
"keyitem_lose");
676 Msg.
Say(
"lose_keyItem", value.GetName());
678 keyItems[value.id] = num2;
682 [ElinDramaActionInvoke(
null)]
691 Point nearestPoint = chara2.
pos.
GetNearestPoint(allowBlock:
false, allowChara:
false, allowInstalled:
true, ignoreCenter:
true);
692 chara.
TryMove(nearestPoint, allowDestroyPath:
false);
696 [ElinDramaActionInvoke(
null)]
697 public static bool move_tile(
DramaManager dm, Dictionary<string, string> line,
int xOffset,
int yOffset)
701 chara.
TryMove(newPoint, allowDestroyPath:
false);
705 [ElinDramaActionInvoke(
null)]
710 chara.
TryMove(newPoint, allowDestroyPath:
false);
714 [ElinDramaActionInvoke(
"nodiscard")]
715 public static bool move_zone(
DramaManager dm, Dictionary<string, string> line,
string zoneId,
int zoneLv = 99999)
722 Zone zone = ModUtil.FindZoneByFullName(
$"{zoneId}@{zoneLv}");
729 state = ZoneTransition.EnterState.RandomVisit
734 [ElinDramaActionInvoke(
"nodiscard")]
738 Zone zone = ModUtil.FindZoneByFullName(zoneFullName);
745 state = ZoneTransition.EnterState.RandomVisit
750 [ElinDramaActionInvoke(
null)]
757 [ElinDramaActionInvoke(
null)]
764 [ElinDramaActionInvoke(
null)]
771 [ElinDramaActionInvoke(
null)]
778 [ElinDramaActionInvoke(
null)]
785 [ElinDramaActionInvoke(
null)]
792 [ElinDramaActionInvoke(
null)]
801 if (!portraitId.IsEmpty())
803 string text2 = person.
id.IsEmpty(person.
chara?.
id);
804 HashSet<string> hashSet =
new HashSet<string>(StringComparer.Ordinal);
805 hashSet.Add(
"UN_" + text2 +
"_" + text +
".png");
806 hashSet.Add(text +
".png");
807 hashSet.Add(text2 +
"_" + text +
".png");
814 person.idPortrait = text;
818 [ElinDramaActionInvoke(
null)]
821 dm.
GetChara(line[
"actor"]).SetPortraitOverride(portraitId);
825 [ElinDramaActionInvoke(
null)]
828 dm.
GetChara(line[
"actor"]).SetSpriteOverride(spriteId);
832 [ElinDramaActionInvoke(
"nodiscard")]
839 string[] array = bookEntry.Split(
'/');
840 string text = array[0];
841 string text2 = array[1];
842 if (text2.EndsWith(
".txt"))
846 if (!
BookList.
dict.TryGetValue(text, out var value) || !value.TryGetValue(text2, out var value2))
850 bool flag = text ==
"Scroll";
851 EClass.
ui.AddLayer<
LayerHelp>(flag ?
"LayerParchment" :
"LayerBook").
book.Show((flag ?
"Scroll/" :
"Book/") + value2.id,
null, value2.title, value2);
static bool equip_item(DramaManager dm, Dictionary< string, string > line, string itemId)
static bool mod_affinity(DramaManager dm, Dictionary< string, string > line, DramaValueExpression expr)
static bool show_book(DramaManager dm, Dictionary< string, string > line, string bookEntry)
static bool join_faith(DramaManager dm, Dictionary< string, string > line, string religionId="")
static bool if_currency(DramaManager dm, Dictionary< string, string > line, string currencyId, DramaValueExpression expr)
static bool eval(DramaManager dm, Dictionary< string, string > line, params string[] parameters)
static bool mod_flag(DramaManager dm, Dictionary< string, string > line, string flagKey, DramaValueExpression expr=null)
static bool and(DramaManager dm, Dictionary< string, string > line, params string[] parameters)
static bool mod_fame(DramaManager dm, Dictionary< string, string > line, DramaValueExpression expr)
static bool play_emote(DramaManager dm, Dictionary< string, string > line, Emo emote, float duration=1f)
static bool if_condition(DramaManager dm, Dictionary< string, string > line, string conditionAlias, DramaValueExpression expr=null)
static bool console_cmd(DramaManager dm, Dictionary< string, string > line, params string[] parameters)
static bool set_portrait_override(DramaManager dm, Dictionary< string, string > line, string portraitId=null)
static bool mod_currency(DramaManager dm, Dictionary< string, string > line, string currencyId, DramaValueExpression expr)
static bool remove_condition(DramaManager dm, Dictionary< string, string > line, string conditionAlias)
static bool set_sprite(DramaManager dm, Dictionary< string, string > line, string spriteId=null)
static bool if_element(DramaManager dm, Dictionary< string, string > line, string elementAlias, DramaValueExpression expr)
static bool if_in_party(DramaManager dm, Dictionary< string, string > line, bool isInParty=true)
static bool mod_element(DramaManager dm, Dictionary< string, string > line, string elementAlias, int value=1, int potential=100)
static bool add_item(DramaManager dm, Dictionary< string, string > line, string itemId, string materialAlias="wood", int lv=-1, int count=1)
static bool play_effect(DramaManager dm, Dictionary< string, string > line, string effectId)
static bool if_has_item(DramaManager dm, Dictionary< string, string > line, string itemId, DramaValueExpression expr=null)
static bool destroy_item(DramaManager dm, Dictionary< string, string > line, string itemId, int count=-1)
static bool DefaultDramaInvokeExtActionParser(DramaManager dm, Dictionary< string, string > line)
static bool if_tag(DramaManager dm, Dictionary< string, string > line, string tag)
static bool move_zone_2(DramaManager dm, Dictionary< string, string > line, string zoneFullName)
static bool if_lv(DramaManager dm, Dictionary< string, string > line, DramaValueExpression expr)
static bool if_race(DramaManager dm, Dictionary< string, string > line, string raceId)
static bool if_flag(DramaManager dm, Dictionary< string, string > line, string flagKey, DramaValueExpression expr=null)
static bool mod_keyitem(DramaManager dm, Dictionary< string, string > line, string keyitemId, DramaValueExpression expr=null)
static bool move_zone(DramaManager dm, Dictionary< string, string > line, string zoneId, int zoneLv=99999)
static bool set_portrait(DramaManager dm, Dictionary< string, string > line, string portraitId=null)
static bool apply_condition(DramaManager dm, Dictionary< string, string > line, string conditionAlias, int power=100)
static bool if_keyitem(DramaManager dm, Dictionary< string, string > line, string keyitemId, DramaValueExpression expr=null)
static bool if_fame(DramaManager dm, Dictionary< string, string > line, DramaValueExpression expr)
static bool DefaultDramaEvalActionParser(DramaManager dm, Dictionary< string, string > line)
static bool if_zone_2(DramaManager dm, Dictionary< string, string > line, string zoneFullName)
static bool not(DramaManager dm, Dictionary< string, string > line, params string[] parameters)
static bool play_effect_at(DramaManager dm, Dictionary< string, string > line, string effectId, int x, int y)
static bool pop_text(DramaManager dm, Dictionary< string, string > line, string langText)
static bool move_next_to(DramaManager dm, Dictionary< string, string > line, string charaId)
static bool if_zone(DramaManager dm, Dictionary< string, string > line, string zoneId, int zoneLv=99999)
static bool move_to(DramaManager dm, Dictionary< string, string > line, int x, int y)
static bool play_screen_effect(DramaManager dm, Dictionary< string, string > line, string effectId)
static bool move_tile(DramaManager dm, Dictionary< string, string > line, int xOffset, int yOffset)
static bool mod_element_exp(DramaManager dm, Dictionary< string, string > line, string elementAlias, DramaValueExpression expr)
static bool or(DramaManager dm, Dictionary< string, string > line, params string[] parameters)
static bool play_anime(DramaManager dm, Dictionary< string, string > line, AnimeID animeId)
static bool join_party(DramaManager dm, Dictionary< string, string > line)
static bool if_affinity(DramaManager dm, Dictionary< string, string > line, DramaValueExpression expr)
static bool if_hostility(DramaManager dm, Dictionary< string, string > line, string expression)
static bool if_faith(DramaManager dm, Dictionary< string, string > line, string religionId, DramaValueExpression expr=null)
delegate bool DramaActionParser(DramaManager dm, Dictionary< string, string > line)
delegate bool DramaInvokeFunc(DramaManager dm, Dictionary< string, string > line, params string[] parameters)
static Dictionary< string, Dictionary< string, Item > > dict
void Say(string text, Color c=default(Color), float duration=0f)
ElementContainerCard elements
CardRenderer HostRenderer
void SetInt(string id, int value=0)
int GetCurrency(string id="money")
Effect PlayEffect(string id, bool useRenderPos=true, float range=0f, Vector3 fix=default(Vector3))
void ShowEmo(Emo _emo=Emo.none, float duration=0f, bool skipSame=true)
void ModCurrency(int a, string id="money")
void ModExp(string alias, int a)
void PlayAnime(AnimeID id, bool force=false)
void ModNum(int a, bool notify=true)
int GetInt(string id, int? defaultInt=null)
bool HasElement(int ele, bool includeNagative=false)
bool Equip(Thing thing, BodySlot slot=null, bool msg=true)
Condition AddCondition(string id, int p=100, bool force=false)
void ModAffinity(Chara c, int a, bool show=true, bool showOnlyEmo=false)
void SetFeat(int id, int value=1, bool msg=false)
override MoveResult TryMove(Point newPoint, bool allowDestroyPath=true)
List< Condition > conditions
void MakeAlly(bool msg=true)
Thing Pick(Thing t, bool msg=true, bool tryStack=true)
void MoveZone(string alias)
static string[] SplitParams(string args)
static readonly Regex _expressionRegex
static readonly Dictionary< string, DramaInvokeDetail > _invokes
static readonly Dictionary< string, DramaActionParser > _actionParsers
static string Unquote(string s)
bool SafeInvoke(DramaManager dm, Dictionary< string, string > line, params string[] parameters)
Chara GetChara(string id)
Person GetPerson(string id)
void ParseLine(Dictionary< string, string > item)
DramaEvent AddEvent(DramaEvent e)
static SourceManager sources
static SoundManager Sound
static Effect Get(Effect original)
void Play(float delay, Point from, float fixY=0f, Point to=null, Sprite sprite=null)
Element SetBase(string alias, int v, int potential=0)
Element GetOrCreateElement(Element ele)
ReligionManager religions
static string Say(string idLang, string ref1, string ref2=null, string ref3=null, string ref4=null)
Dictionary< int, int > keyItems
Point GetNearestPoint(bool allowBlock=false, bool allowChara=true, bool allowInstalled=true, bool ignoreCenter=false, int minRadius=0)
static HashSet< string > allIds
virtual void JoinFaith(Chara c, ConvertType type=ConvertType.Default)
virtual void LeaveFaith(Chara c, Religion newFaith, ConvertType type)
static void Play(string id)
List< Thing > List(Func< Thing, bool > func, bool onlyAccessible=false)
static Thing Create(string id, int idMat=-1, int lv=-1)