protected void Deactivate(QuestPin pin) { QuestObjectState state = GetState(pin); if (state.Locked || state.Active == QuestObjectState.ActivationState.Inactive) { return; } state.Active = QuestObjectState.ActivationState.Inactive; GameDebugger.Log(LogLevel.Debug, "QS: {0} '0x{1:X16}' deactivated", pin.GetType().Name, pin.Id); if (pin.Type == GraphPin.PinType.Input) { if (m_ActivelyChecked.ContainsKey(pin.Id)) { GameDebugger.Log(LogLevel.Debug, "QS: Removing {0} '0x{1:X16}' from the list of actively checked objects", pin.GetType().Name, pin.Id); m_ActivelyChecked.Remove(pin.Id); } } foreach (QuestConnection connection in pin.Connections) { if (connection.Source != pin) { continue; } Deactivate(connection); } if (pin.Type == GraphPin.PinType.Input) { Deactivate((BaseQuestObject)pin.Node); } }
protected void CheckInputsOnActivation(BaseQuestObject obj) { // all objects except quests get activated when all their input pins are active bool allActive = true; GameDebugger.Log(LogLevel.Debug, "QS: Checking inputs of {0} '0x{1:X16}'", obj.GetType().Name, obj.Id); foreach (QuestPin pin in obj.Inputs) { QuestObjectState state = GetState(pin); if (state.Active != QuestObjectState.ActivationState.Active) { allActive = false; break; } } if (allActive) { GameDebugger.Log(LogLevel.Debug, "QS: SUCCESS"); Activate((BaseQuestObject)obj); } else { GameDebugger.Log(LogLevel.Debug, "QS: FAIL"); } }
protected void Activate(BaseQuestObject obj) { QuestObjectState state = GetState(obj); if (state.Locked || state.Active != QuestObjectState.ActivationState.Inactive) { return; } state.Active = QuestObjectState.ActivationState.Active; GameDebugger.Log(LogLevel.Debug, "QS: Activated {0} '0x{1:X16}'", obj.GetType().Name, obj.Id); if (obj is QuestCondition) { // conditions must be actively checked every quest system tick GameDebugger.Log(LogLevel.Debug, "QS: Adding {0} '0x{1:X16}' to the list of actively checked objects", obj.GetType().Name, obj.Id); m_ActivelyChecked.Add(obj.Id, obj); } else if (obj is QuestObjective) { // quest objectives must be actively checked every quest system tick, but only when there is at least one output that has a script assigned bool hasScriptsOnOutputs = false; foreach (QuestPin pin in obj.Outputs) { if (pin.Script != null) { hasScriptsOnOutputs = true; break; } } if (hasScriptsOnOutputs) { GameDebugger.Log(LogLevel.Debug, "QS: Adding {0} '0x{1:X16}' to the list of actively checked objects due to existing scripts on one or more outputs", obj.GetType().Name, obj.Id); m_ActivelyChecked.Add(obj.Id, obj); } GameDebugger.Log(LogLevel.Debug, "QS: event: OnQuestObjectiveActivated"); if (OnQuestObjectiveActivated != null) { OnQuestObjectiveActivated.Invoke(new QuestObjectiveActivatedEventArgs((QuestObjective)obj)); } } else if (obj is Quest) { GameDebugger.Log(LogLevel.Debug, "QS: event: OnQuestActivated"); if (OnQuestActivated != null) { OnQuestActivated.Invoke(new QuestActivatedEventArgs((Quest)obj)); } } else { if (obj is QuestInstruction) { ExecuteScript((QuestInstruction)obj); } foreach (QuestPin pin in obj.Outputs) { Activate(pin); } } // when quest gets activated it does nothing since objectives actually get activated by quest's active input pins }
protected void Deactivate(BaseQuestObject obj) { QuestObjectState state = GetState(obj); if (state.Locked || state.Active == QuestObjectState.ActivationState.Inactive) { return; } state.Active = QuestObjectState.ActivationState.Inactive; GameDebugger.Log(LogLevel.Debug, "QS: {0} '0x{1:X16}' deactivated", obj.GetType().Name, obj.Id); if (m_ActivelyChecked.ContainsKey(obj.Id)) { GameDebugger.Log(LogLevel.Debug, "QS: Removing {0} '0x{1:X16}' from the list of actively checked objects", obj.GetType().Name, obj.Id); m_ActivelyChecked.Remove(obj.Id); } if (obj is Quest) { GameDebugger.Log(LogLevel.Debug, "QS: event: OnQuestDeactivated"); if (OnQuestDeactivated != null) { OnQuestDeactivated.Invoke(new QuestDeactivatedEventArgs((Quest)obj)); } if (state.Completion != QuestObjectState.CompletionState.Incomplete) { state.Completion = QuestObjectState.CompletionState.Incomplete; // NOTE: This most probably will never happen since quests are locked right after getting complete, // but might need to invoke OnQuestIncomplete event in case this happens after all. } } else if (obj is QuestObjective) { GameDebugger.Log(LogLevel.Debug, "QS: event: OnQuestObjectiveDeactivated"); if (OnQuestObjectiveDeactivated != null) { OnQuestObjectiveDeactivated.Invoke(new QuestObjectiveDeactivatedEventArgs((QuestObjective)obj)); } if (state.Completion != QuestObjectState.CompletionState.Incomplete) { state.Completion = QuestObjectState.CompletionState.Incomplete; GameDebugger.Log(LogLevel.Debug, "QS: event: OnQuestObjectiveIncomplete"); if (OnQuestObjectiveIncomplete != null) { OnQuestObjectiveIncomplete.Invoke(new QuestObjectiveIncompleteEventArgs((QuestObjective)obj)); } } } foreach (QuestPin pin in obj.Outputs) { Deactivate(pin); } }
public QuestObjectState GetState(IQuestSystemObject obj) { QuestObjectState state; if (m_States.TryGetValue(obj.Id, out state)) { return(state); } state = new QuestObjectState(); m_States.Add(obj.Id, state); return(state); }
protected void Activate(QuestConnection connection) { QuestObjectState state = GetState(connection); if (state.Locked || state.Active != QuestObjectState.ActivationState.Inactive) { return; } state.Active = QuestObjectState.ActivationState.Active; GameDebugger.Log(LogLevel.Debug, "QS: Activated connection '0x{0:X16}'", connection.Id); Activate((QuestPin)connection.Target); }
protected void Deactivate(QuestConnection connection) { QuestObjectState state = GetState(connection); if (state.Locked || state.Active == QuestObjectState.ActivationState.Inactive) { return; } state.Active = QuestObjectState.ActivationState.Inactive; GameDebugger.Log(LogLevel.Debug, "QS: {0} '0x{1:X16}' deactivated", connection.GetType().Name, connection.Id); Deactivate((QuestPin)connection.Target); }
protected void Lock(QuestConnection connection, bool propagate) { QuestObjectState state = GetState(connection); if (state.Locked) { return; } state.Locked = true; GameDebugger.Log(LogLevel.Debug, "QS: {0} '0x{1:X16}' locked", connection.GetType().Name, connection.Id); if (propagate) { Lock((QuestPin)connection.Source); } }
public void QuestObjectiveIncomplete(QuestObjective objective) { QuestObjectState state = GetState(objective); if (state.Locked || state.Completion == QuestObjectState.CompletionState.Incomplete) { return; } state.Completion = QuestObjectState.CompletionState.Incomplete; GameDebugger.Log(LogLevel.Debug, "QS: event: OnQuestObjectiveIncomplete"); if (OnQuestObjectiveIncomplete != null) { OnQuestObjectiveIncomplete.Invoke(new QuestObjectiveIncompleteEventArgs(objective)); } Deactivate((QuestPin)objective.Outputs[state.CompletionOutput]); }
protected void Lock(BaseQuestObject obj) { QuestObjectState state = GetState(obj); if (state.Locked) { return; } state.Locked = true; GameDebugger.Log(LogLevel.Debug, "QS: {0} '0x{1:X16}' locked", obj.GetType().Name, obj.Id); if (m_ActivelyChecked.ContainsKey(obj.Id)) { GameDebugger.Log(LogLevel.Debug, "QS: Removing {0} '0x{1:X16}' from the list of actively checked objects", obj.GetType().Name, obj.Id); m_ActivelyChecked.Remove(obj.Id); } foreach (QuestPin pin in obj.Inputs) { Lock(pin, true); } }
protected void Lock(QuestPin pin, bool propagate) { QuestObjectState state = GetState(pin); if (state.Locked) { return; } state.Locked = true; GameDebugger.Log(LogLevel.Debug, "QS: {0} '0x{1:X16}' locked", pin.GetType().Name, pin.Id); if (pin.Type == GraphPin.PinType.Input) { if (m_ActivelyChecked.ContainsKey(pin.Id)) { GameDebugger.Log(LogLevel.Debug, "QS: Removing {0} '0x{1:X16}' from the list of actively checked objects", pin.GetType().Name, pin.Id); m_ActivelyChecked.Remove(pin.Id); } } foreach (QuestConnection connection in pin.Connections) { Lock(connection, (connection.Target == pin)); // propagate locking only on incoming connections } if (propagate && pin.Type == GraphPin.PinType.Output) { foreach (QuestPin otherPin in pin.Node.Outputs) { if (otherPin == pin) { continue; } Lock(otherPin, false); } Lock((BaseQuestObject)pin.Node); } }
protected void Activate(QuestPin pin) { QuestObjectState state = GetState(pin); if (state.Locked || state.Active != QuestObjectState.ActivationState.Inactive) { return; } bool lockPin = false; if (pin.Type == GraphPin.PinType.Input) { if (pin.Script != null) { GameDebugger.Log(LogLevel.Debug, "QS: Partially activated pin '0x{0:X16}'", pin.Id); GameDebugger.Log(LogLevel.Debug, "QS: Adding pin '0x{0:X16}' to the list of actively checked objects", pin.Id); state.Active = QuestObjectState.ActivationState.PartiallyActive; m_ActivelyChecked.Add(pin.Id, pin); } else { state.Active = QuestObjectState.ActivationState.Active; GameDebugger.Log(LogLevel.Debug, "QS: Activated pin '0x{0:X16}'", pin.Id); if (pin.Node is Quest) { Activate((BaseQuestObject)pin.Node); } else { CheckInputsOnActivation((BaseQuestObject)pin.Node); } } } else { state.Active = QuestObjectState.ActivationState.Active; GameDebugger.Log(LogLevel.Debug, "QS: Activated pin '0x{0:X16}'", pin.Id); if (pin.Node is Quest || pin.Node is QuestObjective) { QuestObjectState nodeState = GetState((IQuestSystemObject)pin.Node); int pinIndex = 0; foreach (QuestPin testPin in pin.Node.Outputs) { if (testPin == pin) { GameDebugger.Log(LogLevel.Debug, "QS: Detected pin index: {0}", pinIndex); break; } pinIndex++; } if (nodeState.Completion == QuestObjectState.CompletionState.Incomplete || nodeState.CompletionOutput != pinIndex) { if (nodeState.Completion != QuestObjectState.CompletionState.Incomplete) { Deactivate((QuestPin)pin.Node.Outputs[nodeState.CompletionOutput]); GameDebugger.Log(LogLevel.Debug, "QS: Switching {0} '0x{1:X16}' completion state from {2} to {3}", pin.Node.GetType().Name, ((IQuestSystemObject)pin.Node).Id, nodeState.CompletionOutput, pinIndex); } else { GameDebugger.Log(LogLevel.Debug, "QS: Setting {0} '0x{1:X16}' completion state to {2}", pin.Node.GetType().Name, ((IQuestSystemObject)pin.Node).Id, pinIndex); } nodeState.CompletionOutput = (byte)pinIndex; nodeState.Completion = pin.IsFailureOutput ? QuestObjectState.CompletionState.Failed : QuestObjectState.CompletionState.Successful; if (pin.Node is Quest) { lockPin = true; GameDebugger.Log(LogLevel.Debug, "QS: event: OnQuestComplete"); if (OnQuestComplete != null) { OnQuestComplete.Invoke(new QuestCompleteEventArgs((Quest)pin.Node, pinIndex, pin.IsFailureOutput)); } } else { GameDebugger.Log(LogLevel.Debug, "QS: event: OnQuestObjectiveComplete"); if (OnQuestObjectiveComplete != null) { OnQuestObjectiveComplete.Invoke(new QuestObjectiveCompleteEventArgs((QuestObjective)pin.Node, pinIndex, pin.IsFailureOutput)); } } } } if (!(pin.Node is QuestObjective)) // quest objectives have conditions instead of instructions on outputs { ExecuteScript(pin); } } // activate all outgoing connections if (state.Active == QuestObjectState.ActivationState.Active) { foreach (QuestConnection connection in pin.Connections) { if (connection.Source == pin) { Activate(connection); } } } // locking the pin must be done in the end otherwise it will not activate connections (they will be already locked) if (lockPin) { Lock(pin); } }