/// <summary> /// Creates the on complete function from an oncomplete string. /// </summary> /// <returns>The on complete function in the form of an Action.</returns> /// <param name="oc">OnComplete function in string form.</param> public static Action <InteractionEvent> CreateOnCompleteFunction(string oc) { // Just return a no-op if the user didn't provide an OnComplete string if (string.IsNullOrEmpty(oc)) { return((InteractionEvent evt) => { }); } ParsingResult pR = ParseString(oc); Action <InteractionEvent> ac = (InteractionEvent evt) => { IGameEvent outEvt; switch (pR.interactionKind) { case InteractionKind.Become: if (pR.obj1 == "TargetItem") { outEvt = new ReplaceObjectEvent(evt.targetObject, pR.obj2); } else { outEvt = new ReplaceObjectEvent(pR.obj1, pR.obj2); } break; case InteractionKind.Show: Debug.Log("Show InteractionKind"); Debug.Log(string.Format("{0}, {1}", pR.obj1, pR.obj2)); outEvt = new ShowObjectEvent(pR.obj1); break; case InteractionKind.Hide: outEvt = new HideObjectEvent(pR.obj1); break; case InteractionKind.Delete: Debug.Log("Delete InteractionKind"); Debug.Log(string.Format("{0} {1}", pR.obj1, pR.obj2)); outEvt = new DeleteObjectEvent(pR.obj1); break; case InteractionKind.Play: switch (pR.uiEventKind) { case UIActionKind.Dialog: outEvt = new ShowTextEvent(pR.obj1); break; case UIActionKind.Sound: outEvt = new PlaySoundEvent(pR.obj1); break; default: throw new ArgumentException("Play must be followed by Dialog or Sound"); } break; case InteractionKind.Get: outEvt = new PlayerRecieveObjectEvent(pR.obj1); break; default: throw new ArgumentException(string.Format("Invalid interaction kind in OnComplete: {0} (OnComplete string: {1})", pR.interactionKind, oc)); } EventManager.FireEvent(outEvt); }; return(ac); }
/// <summary> /// Parses function strings according to the function grammar. /// At the moment, these include Trigger functions and OnComplete functions. /// /// </summary> /// <returns>The parsed result.</returns> /// <param name="s">Function string to be parsed</param> internal static ParsingResult ParseString(string s) { // Better documentation is in a text file // EXAMPLES OF LANGUAGE // target WITH source ex: Cut Tree With Axe // source ON target ex: Drop Water On ActiveFire // ENTER location ex: Enter Winter // the source object is the tool // this is also object 1 // the target object is the interacted object // this is object 2 // types of actions: Get, Enter, Drop, Cut, Hit, Dig, Merge, Open, None // Declares variables: string[] toParse = s.Split(' '); int length = toParse.Length; string obj1 = String.Empty; // tool or source string obj2 = String.Empty; int tempQuantity = 1; int obj1Quantity = 0; int obj2Quantity = 0; int amountOfTime = 0; string location = String.Empty; string objToObjIntrcType = String.Empty; InteractionKind action = InteractionKind.None; UIActionKind uiEventKind = UIActionKind.None; ParsingResult parsingResult = new ParsingResult(); // Goes through string word by word for (int i = 0; i < length; i++) { if (toParse[i].Equals("Player") || toParse[i].Equals("Object")) // ignores these for now { } else if (toParse[i].Equals("Item") && i + 1 < length) { i++; // next expected word might be a quantity if (Int32.TryParse(toParse[i], out tempQuantity)) { i++; } // if next expected word is an item, get the item if (!String.IsNullOrEmpty(objToObjIntrcType)) { // figure out which item is being referred to if (objToObjIntrcType.Equals("With") || objToObjIntrcType.Equals("Become")) { obj2 = obj1; // target item obj2Quantity = obj1Quantity; obj1 = toParse[i]; // source item = this current item obj1Quantity = tempQuantity; } else if (objToObjIntrcType.Equals("On") || objToObjIntrcType.Equals("And")) { obj2 = toParse[i]; // target item = this current item obj2Quantity = tempQuantity; } } else if (action == InteractionKind.Become) { //i++; // in the case of an OnComplete being parsed: obj2 = toParse[i]; obj2Quantity = tempQuantity; } else { // if this is the first reference to an item: obj1 = toParse[i]; obj1Quantity = tempQuantity; } } else if (toParse[i] == "TargetItem") { obj1 = toParse[i]; } else if (toParse[i].Equals("With") || toParse[i].Equals("On") || toParse[i].Equals("And")) { objToObjIntrcType = toParse[i]; //if objects interact, set the interaction type } else if (toParse[i].Equals("For") && action == InteractionKind.Leave) { //Trigger = "Player Leave Item ItemName For 2 Seasons" Int32.TryParse(toParse[++i], out amountOfTime); i++; } else if (toParse[i].Equals("Location") && i + 1 < length) { i++; location = toParse[i]; } else if (Enum.TryParse <InteractionKind>(toParse[i], out action)) { if (action == InteractionKind.Play) { Enum.TryParse <UIActionKind>(toParse[++i], out uiEventKind); obj1 = toParse[++i]; } } } parsingResult.interactionKind = action; parsingResult.uiEventKind = uiEventKind; parsingResult.obj1 = obj1; // tool parsingResult.obj2 = obj2; // other parsingResult.obj1Quantity = obj1Quantity; parsingResult.obj2Quantity = obj2Quantity; parsingResult.amountOfTime = amountOfTime; parsingResult.location = location; parsingResult.objToObjInteractionType = objToObjIntrcType; return(parsingResult); }
/// <summary> /// Creates the trigger function from a trigger string /// </summary> /// <returns>Trigger function in the form of a Predicate</returns> /// <param name="tr">Trigger function in string form</param> public static Predicate <InteractionEvent> CreateTriggerFunction(string tr) { if (String.IsNullOrEmpty(tr)) { return((InteractionEvent evt) => true); } ParsingResult pR = ParseString(tr); Predicate <InteractionEvent> pred; // TODO: implement InteractionKind.Leave // Don't worry about checking for the kind inside these predicates, we'll add that before we return switch (pR.interactionKind) { case InteractionKind.Enter: pred = (InteractionEvent evt) => pR.location == evt.location; break; // For this group, we just check that the object names match. case InteractionKind.Store: case InteractionKind.Retrieve: case InteractionKind.Get: case InteractionKind.PickUp: pred = (InteractionEvent evt) => pR.obj1 == evt.sourceObject.name; break; case InteractionKind.Drop: Predicate <InteractionEvent> tempPred; if (pR.obj1 == string.Empty) { tempPred = (InteractionEvent evt) => pR.obj2 == evt.targetObject.name; } else { tempPred = (InteractionEvent evt) => pR.obj1 == evt.sourceObject.name && pR.obj2 == evt.targetObject.name; } pred = (InteractionEvent evt) => { Debug.Log(string.Format("{0},{1},{2},{3}", pR.obj1, pR.obj2, evt.sourceObject.name, evt.targetObject.name)); return(tempPred(evt)); }; break; // TODO: Hack to work around current lack of activity recognition case InteractionKind.Cut: case InteractionKind.Dig: case InteractionKind.Hit: case InteractionKind.Grind: pred = (InteractionEvent evt) => { Debug.Log(string.Format("Hit event: {0} {1} {2} {3}", evt.sourceObject.name, evt.targetObject.name, pR.obj1, pR.obj2)); return(pR.obj2 == evt.targetObject.name); }; break; // check that the two objects are the ones we're looking for case InteractionKind.Merge: pred = (InteractionEvent evt) => { return((evt.sourceObject.name == pR.obj1 && evt.targetObject.name == pR.obj2) || (evt.targetObject.name == pR.obj1 && evt.sourceObject.name == pR.obj2)); }; break; // Check that the object is the one we're looking for, and check that it has waited long enough. case InteractionKind.Leave: pred = (InteractionEvent evt) => evt.targetObject.name == pR.obj1 && evt.waitedDuration >= pR.amountOfTime; break; // For this group we don't need any extra logic. case InteractionKind.Open: pred = (InteractionEvent evt) => true; break; default: throw new NotImplementedException(string.Format("Support for this interaction kind is not yet implemented: {0}", pR.interactionKind)); } Predicate <InteractionEvent> finalPred; // Add the check for event kind switch (pR.interactionKind) { // TODO: Hack to work around current lack of activity recognition case InteractionKind.Cut: case InteractionKind.Dig: case InteractionKind.Hit: case InteractionKind.Grind: finalPred = (InteractionEvent evt) => { Debug.Log(string.Format("kind inside hit: {0},{1},{2}", pR.interactionKind, evt.kind, pR.obj1)); if (evt.kind == InteractionKind.Hit) { return(pred(evt)); } else { return(false); } }; break; default: finalPred = (InteractionEvent evt) => { Debug.Log(string.Format("kind: {0},{1},{2}", pR.interactionKind, evt.kind, pR.obj1)); if (evt.kind == pR.interactionKind) { return(pred(evt)); } else { return(false); } }; break; } return(finalPred); }