// Handle puzzle-specific function calls if ProgramController.ExecuteNode set the handover flag public override ExecutionStatus ExecuteNode(NodeBase node) { ExecutionStatus baseStatus = base.ExecuteNode(node); if (!baseStatus.handover) { return(baseStatus); } if (CheckNodeType(node) == NodeType.FunctionCallBase) { FunctionCallBase funcCall = node.GetComponent <FunctionCallBase>(); if (functions.ContainsKey(funcCall.functionName)) { functions[funcCall.functionName].DynamicInvoke(); return(new ExecutionStatus { success = true, handover = false }); } } return(new ExecutionStatus { success = true, handover = true }); }
public override bool ExecuteFrame() { // Check if ProgramController.ExecuteFrame moved to next node already, in which case this child implementation does not need to be called. if (!base.ExecuteFrame()) { return(false); } // Is the node still being processed? if (!processingDone) { // Is it a function? if (CheckNodeType(currentNode) == NodeType.FunctionCallBase) { FunctionCallBase functionCall = currentNode.GetComponent <FunctionCallBase>(); // Is it not a base function? if (ControllerFunctions().ContainsKey(functionCall.functionName)) { // Platform index int index = -1; string val = (string)functionCall.GetRawParameters(symbolTable)[0]; // Get the platform index from command node in the user program if (int.TryParse(val, out index) || int.TryParse(symbolTable[val].Value, out index)) { // If the index value is valid, call raisePlatform/lowerPlatform with the platform index as a parameter. if (index >= 0) { //Logger.Log($"Calling {functionCall.functionName}({index})"); functions[functionCall.functionName].DynamicInvoke(index.ToString()); // Increment the raising timer so that we know when we can set the processingDone flag currentRaiseTime += Time.deltaTime; } else { Logger.LogWarning("Invalid platform index"); } } else { Logger.LogWarning($"Can't convert platform index to integer ({gameObject.name})."); } } else { Logger.Log($"Unknown function {functionCall.functionName}."); } } // Finally, check if the timer overran raisingTime - if yes, mark processingDone as true. // Then, the execution can move to next node. if (currentRaiseTime >= raisingTime) { Logger.Log("Platform raised!"); processingDone = true; } } return(true); }
// Puzzle-specific ExecuteNode implementation. This should only execute if ProgramController.ExecuteNode set the handover flag. public override ExecutionStatus ExecuteNode(NodeBase node) { // Check if node can be handled by ProgramController first. // If not, it will return .handover as true ExecutionStatus baseStatus = base.ExecuteNode(node); if (!baseStatus.handover) { return(baseStatus); } Logger.Log(CheckNodeType(node).ToString()); switch (CheckNodeType(node)) { // Handlers for different commands case NodeType.FunctionCallBase: Logger.Log($"Handling function {node.GetComponent<FunctionCallBase>().functionName}."); // If this node is going to alter the platform positions (e.g. by raising them), // it's going to need their positions before calling this function node as a reference point, // to be able to interpolate over time. // // Also, set a timer to mark processing as done after raisingTime passes. // Lastly, set processingDone to false, indicating that we may need an irregular tick time for this (the computer won't continue until processingDone is true) // TODO: replace the Action type value in the functions dictionary with a FunctionCall class that contains an "irregularTick" flag // TODO: GetPlatformPositions() should be in a virtual override (IrregularTickInit, IrregularTickFrame, IrregularTickFinished) FunctionCallBase functionCall = node.GetComponent <FunctionCallBase>(); if (functionCall.functionName == "raisePlatform" || functionCall.functionName == "lowerPlatform") { Platform platform = GetChildProgrammable(PlatformContainer, int.Parse((string)functionCall.GetRawParameters(symbolTable)[0])).GetComponent <Platform>(); // Check elevation boundaries (e.g. to prevent platforms going under ground) bool allowElevation = functionCall.functionName == "raisePlatform" && initPositions[platform.index].y + platform.MaxElevation < platform.transform.localPosition.y + stepHeight; bool allowDown = functionCall.functionName == "lowerPlatform" && initPositions[platform.index].y + platform.MinElevation > platform.transform.localPosition.y - stepHeight; bool allowMove = allowElevation || allowDown; if (allowMove) { // If outside limits, prevent moving processingDone = true; return(new ExecutionStatus { success = true, handover = false }); } // Otherwise continue with raising/lowering the platform GetPlatformPositions(); currentRaiseTime = 0.0f; processingDone = false; return(new ExecutionStatus { success = true, handover = false }); } break; default: Logger.Log("Unidentified node."); break; } return(new ExecutionStatus { success = true, handover = false }); }
public override ExecutionStatus ExecuteNode(NodeBase node) { ExecutionStatus baseStatus = base.ExecuteNode(node); if (!baseStatus.handover) { return(baseStatus); } switch (CheckNodeType(node)) { case NodeType.FunctionCallBase: FunctionCallBase functionCall = currentNode.GetComponent <FunctionCallBase>(); // TODO: rewrite so we have a Dictionary of function names and function delegates, along with an array of types describing each parameter's type Delegate func = null; try { func = functions[functionCall.functionName]; } catch (Exception) { Logger.Log($"Unknown function {functionCall.functionName}."); return(new ExecutionStatus { success = false, handover = false }); } if (func != null) { if (lockType != UnlockableDoorWithLock.LockType.FizzBuzz) { bool state = false; string val = (string)functionCall.GetRawParameters(symbolTable)[0]; Logger.Log($"Calling door function with {val}"); // Check literal & symbol table // TODO: make symbol lookup more robust/universal? A template function maybe? if (bool.TryParse(val, out state) || bool.TryParse(symbolTable[val].Value, out state)) { // we need a custom amount of time for processing this node processingDone = false; func.DynamicInvoke(state.ToString()); return(new ExecutionStatus { success = true, handover = false }); } else { Logger.LogWarning($"Can't convert function parameter for function {functionCall.functionName}. ({gameObject.name})."); return(new ExecutionStatus { success = false, handover = false }); } } else { processingDone = true; func.DynamicInvoke(); return(new ExecutionStatus { success = true, handover = false }); } } break; } return(new ExecutionStatus { success = true, handover = false }); }