// 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
        });
    }
Exemple #2
0
    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);
    }
Exemple #3
0
    // 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
        });
    }
Exemple #4
0
    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
        });
    }