public (ISmartScriptLine[], IConditionLine[]) ToDatabaseCompatibleSmartScript(SmartScript script) { if (script.Events.Count == 0) { return(new ISmartScriptLine[0], null); } var eventId = 0; var lines = new List <ISmartScriptLine>(); var conditions = new List <IConditionLine>(); var previousWasWait = false; long nextTriggerId = script.Events.Where(e => e.Id == SmartConstants.EventTriggerTimed) .Select(e => e.GetParameter(0).Value) .DefaultIfEmpty(0) .Max() + 1; foreach (var gv in script.GlobalVariables) { lines.Add(gv.ToMetaSmartScriptLine(script.EntryOrGuid, script.SourceType, eventId++)); } if (script.SourceType == SmartScriptType.TimedActionList) { foreach (SmartEvent e in script.Events) { for (var index = 0; index < e.Actions.Count; ++index) { SmartEvent eventToSerialize = index == 0 ? e.ShallowCopy() : smartFactory.EventFactory(SmartConstants.EventUpdateInCombat); SmartAction actualAction = e.Actions[index].Copy(); AdjustCoreCompatibleAction(actualAction); eventToSerialize.Parent = script; eventToSerialize.Actions.Add(actualAction); var serialized = eventToSerialize.ToSmartScriptLines(script.EntryOrGuid, script.SourceType, eventId++, false, 0); if (serialized.Length != 1) { throw new InvalidOperationException(); } lines.Add(serialized[0]); } } } else { foreach (SmartEvent e in script.Events) { if (e.Actions.Count == 0) { continue; } SmartEvent originalEvent = e.ShallowCopy(); originalEvent.Parent = script; List <SmartEvent> delayedWaits = new(); SmartEvent lastEvent = originalEvent; long accumulatedWaits = 0; for (var index = 0; index < e.Actions.Count; ++index) { if (previousWasWait) { var eventTimed = smartFactory.EventFactory(SmartConstants.EventTriggerTimed); eventTimed.Parent = script; eventTimed.GetParameter(0).Value = nextTriggerId++; delayedWaits.Add(eventTimed); lastEvent = eventTimed; } if (e.Actions[index].Id == SmartConstants.ActionWait) { accumulatedWaits += e.Actions[index].GetParameter(0).Value; if (index == e.Actions.Count - 1 || e.Actions[index + 1].Id == SmartConstants.ActionWait) { continue; } SmartAction createTimedAction = smartFactory.ActionFactory(SmartConstants.ActionCreateTimed, smartFactory.SourceFactory(SmartConstants.SourceNone), smartFactory.TargetFactory(SmartConstants.TargetNone)); createTimedAction.GetParameter(0).Value = nextTriggerId; createTimedAction.GetParameter(1).Value = accumulatedWaits; createTimedAction.GetParameter(2).Value = accumulatedWaits; createTimedAction.Comment = SmartConstants.CommentWait; previousWasWait = true; originalEvent.AddAction(createTimedAction); } else { previousWasWait = false; SmartAction actualAction = e.Actions[index].Copy(); AdjustCoreCompatibleAction(actualAction); lastEvent.AddAction(actualAction); } } if (originalEvent.Actions.Count == 0) { continue; } var serializedConditions = e.ToConditionLines(SmartConstants.ConditionSourceSmartScript, script.EntryOrGuid, script.SourceType, eventId); if (serializedConditions != null) { conditions.AddRange(serializedConditions); } foreach (var toSerialize in new SmartEvent[] { originalEvent }.Concat(delayedWaits)) { var serialized = toSerialize.ToSmartScriptLines(script.EntryOrGuid, script.SourceType, eventId, true); eventId += serialized.Length; lines.AddRange(serialized); } } } return(lines.ToArray(), conditions.ToArray()); }
public (ISmartScriptLine[], IConditionLine[]) ToDatabaseCompatibleSmartScript(SmartScript script) { if (script.Events.Count == 0) { return(new ISmartScriptLine[0], null); } var eventId = 0; var lines = new List <ISmartScriptLine>(); var conditions = new List <IConditionLine>(); var previousWasWait = false; long nextTriggerId = script.Events.Where(e => e.Id == SmartConstants.EventTriggerTimed) .Select(e => e.GetParameter(0).Value) .DefaultIfEmpty(0) .Max() + 1; var usedTimedActionLists = script.Events .SelectMany(e => e.Actions) .Where(a => a.Id == SmartConstants.ActionCallTimedActionList || a.Id == SmartConstants.ActionCallRandomTimedActionList || a.Id == SmartConstants.ActionCallRandomRangeTimedActionList) .SelectMany(a => { if (a.Id == SmartConstants.ActionCallRandomTimedActionList) { return new int[] { (int)a.GetParameter(0).Value, (int)a.GetParameter(1).Value, (int)a.GetParameter(2).Value, (int)a.GetParameter(3).Value, (int)a.GetParameter(4).Value, (int)a.GetParameter(5).Value, } } ; if (a.Id == SmartConstants.ActionCallRandomRangeTimedActionList && a.GetParameter(1).Value - a.GetParameter(0).Value < 20) { return(Enumerable.Range((int)a.GetParameter(0).Value, (int)(a.GetParameter(1).Value - a.GetParameter(0).Value + 1))); } return(new int[] { (int)a.GetParameter(0).Value }); }) .Where(id => id != 0) .ToHashSet(); int firstUnusedActionList = Math.Abs(script.EntryOrGuid) * 100 - 1; int GetNextUnusedTimedActionList() { do { firstUnusedActionList++; } while (usedTimedActionLists.Contains(firstUnusedActionList)); usedTimedActionLists.Add(firstUnusedActionList); return(firstUnusedActionList); } foreach (var gv in script.GlobalVariables) { lines.Add(gv.ToMetaSmartScriptLine(script.EntryOrGuid, script.SourceType, eventId++)); } if (script.SourceType == SmartScriptType.TimedActionList) { foreach (SmartEvent e in script.Events) { for (var index = 0; index < e.Actions.Count; ++index) { SmartEvent eventToSerialize = index == 0 ? e.ShallowCopy() : smartFactory.EventFactory(SmartConstants.EventUpdateInCombat); SmartAction actualAction = e.Actions[index].Copy(); AdjustCoreCompatibleAction(actualAction); eventToSerialize.Parent = script; eventToSerialize.Actions.Add(actualAction); var serialized = eventToSerialize.ToSmartScriptLines(script.EntryOrGuid, script.SourceType, eventId++, false, 0); if (serialized.Length != 1) { throw new InvalidOperationException(); } lines.Add(serialized[0]); } } } else { SmartEvent originalEvent; List <SmartEvent> additionalEvents = new(); void FlushLines(SmartEvent?eventForConditions) { if (eventForConditions != null) { var serializedConditions = eventForConditions.ToConditionLines(SmartConstants.ConditionSourceSmartScript, script.EntryOrGuid, script.SourceType, eventId); if (serializedConditions != null) { conditions.AddRange(serializedConditions); } } foreach (var toSerialize in new SmartEvent[] { originalEvent }.Concat(additionalEvents)) { if (toSerialize.Actions.Count == 0) { continue; } var serialized = toSerialize.ToSmartScriptLines(script.EntryOrGuid, script.SourceType, eventId, true); eventId += serialized.Length; lines.AddRange(serialized); } additionalEvents.ForEach(d => d.Actions.Clear()); originalEvent.Actions.Clear(); } foreach (SmartEvent e in script.Events) { if (e.Actions.Count == 0) { continue; } originalEvent = e.ShallowCopy(); originalEvent.Parent = script; additionalEvents.Clear(); SmartEvent lastEvent = originalEvent; long accumulatedWaits = 0; for (var index = 0; index < e.Actions.Count; ++index) { if (previousWasWait) { var eventTimed = smartFactory.EventFactory(SmartConstants.EventTriggerTimed); eventTimed.Parent = script; eventTimed.GetParameter(0).Value = nextTriggerId++; additionalEvents.Add(eventTimed); lastEvent = eventTimed; } if (e.Actions[index].Id == SmartConstants.ActionBeginInlineActionList || e.Actions[index].Id == SmartConstants.ActionAfter) { var timedActionListId = GetNextUnusedTimedActionList(); SmartAction callTimedActionList = smartFactory.ActionFactory(SmartConstants.ActionCallTimedActionList, smartFactory.SourceFactory(SmartConstants.SourceSelf), smartFactory.TargetFactory(SmartConstants.TargetSelf)); callTimedActionList.GetParameter(0).Value = timedActionListId; if (e.Actions[index].Id == SmartConstants.ActionBeginInlineActionList) { callTimedActionList.GetParameter(1).Value = e.Actions[index].GetParameter(0).Value; callTimedActionList.GetParameter(2).Value = e.Actions[index].GetParameter(1).Value; index++; } callTimedActionList.Comment = SmartConstants.CommentInlineActionList; lastEvent.AddAction(callTimedActionList); FlushLines(e); long afterTimeMin = 0; long afterTimeMax = 0; int timedEventId = 0; for (; index < e.Actions.Count; ++index) { if (e.Actions[index].Id == SmartConstants.ActionAfter || e.Actions[index].Id == SmartConstants.ActionWait) { afterTimeMin += e.Actions[index].GetParameter(0).Value; afterTimeMax += e.Actions[index].GetParameter(1).Value; if (e.Actions[index].GetParameter(1).Value == 0) { afterTimeMax += e.Actions[index].GetParameter(0).Value; } } else if (e.Actions[index].Id == SmartConstants.ActionAfterMovement && index > 0) { afterTimeMin = 0; afterTimeMax = 0; var pathId = e.Actions[index - 1].GetParameter(1).Value; timedActionListId = GetNextUnusedTimedActionList(); var eventFinishedMovement = smartFactory.EventFactory(SmartConstants.EventWaypointsEnded); eventFinishedMovement.Parent = script; eventFinishedMovement.GetParameter(1).Value = pathId; var callAnotherTimedActionList = smartFactory.ActionFactory(SmartConstants.ActionCallTimedActionList, smartFactory.SourceFactory(SmartConstants.SourceSelf), smartFactory.TargetFactory(SmartConstants.TargetSelf)); callAnotherTimedActionList.GetParameter(0).Value = timedActionListId; callAnotherTimedActionList.Comment = SmartConstants.CommentInlineMovementActionList; eventFinishedMovement.AddAction(callAnotherTimedActionList); additionalEvents.Add(eventFinishedMovement); FlushLines(null); } else { SmartEvent after = smartFactory.EventFactory(SmartConstants.EventUpdateInCombat); after.GetParameter(0).Value = afterTimeMin; after.GetParameter(1).Value = afterTimeMax; SmartAction actualAction = e.Actions[index].Copy(); AdjustCoreCompatibleAction(actualAction); after.Parent = new SmartScript(new SmartScriptSolutionItem(timedActionListId, SmartScriptType.TimedActionList), smartFactory, smartDataManager, messageBoxService); after.AddAction(actualAction); var serialized = after.ToSmartScriptLines(timedActionListId, SmartScriptType.TimedActionList, timedEventId++, false, 0); if (serialized.Length != 1) { throw new InvalidOperationException(); } lines.Add(serialized[0]); afterTimeMin = 0; afterTimeMax = 0; } } } else if (e.Actions[index].Id == SmartConstants.ActionWait) { accumulatedWaits += e.Actions[index].GetParameter(0).Value; if (index == e.Actions.Count - 1 || e.Actions[index + 1].Id == SmartConstants.ActionWait) { continue; } SmartAction createTimedAction = smartFactory.ActionFactory(SmartConstants.ActionCreateTimed, smartFactory.SourceFactory(SmartConstants.SourceNone), smartFactory.TargetFactory(SmartConstants.TargetNone)); createTimedAction.GetParameter(0).Value = nextTriggerId; createTimedAction.GetParameter(1).Value = accumulatedWaits; createTimedAction.GetParameter(2).Value = accumulatedWaits; createTimedAction.Comment = SmartConstants.CommentWait; previousWasWait = true; originalEvent.AddAction(createTimedAction); } else { previousWasWait = false; SmartAction actualAction = e.Actions[index].Copy(); AdjustCoreCompatibleAction(actualAction); lastEvent.AddAction(actualAction); } } if (originalEvent.Actions.Count == 0) { continue; } FlushLines(e); } } return(lines.ToArray(), conditions.ToArray()); }
public SmartScriptEditorViewModel(IHistoryManager history, IDatabaseProvider database, IEventAggregator eventAggregator, ISmartDataManager smartDataManager, ISmartFactory smartFactory, IItemFromListProvider itemFromListProvider, ISmartTypeListProvider smartTypeListProvider, IStatusBar statusbar, ISolutionItemNameRegistry itemNameRegistry) { this.history = history; this.database = database; this.smartDataManager = smartDataManager; this.smartFactory = smartFactory; this.itemFromListProvider = itemFromListProvider; this.smartTypeListProvider = smartTypeListProvider; this.statusbar = statusbar; this.itemNameRegistry = itemNameRegistry; EditEvent = new DelegateCommand(EditEventCommand); DeselectActions = new DelegateCommand(() => { foreach (var e in Events) { if (!e.IsSelected) { foreach (var a in e.Actions) { a.IsSelected = false; } } } }); DeselectAll = new DelegateCommand(() => { foreach (var e in Events) { foreach (var a in e.Actions) { a.IsSelected = false; } e.IsSelected = false; } }); DeselectAllEvents = new DelegateCommand(() => { foreach (var e in Events) { e.IsSelected = false; } }); OnDropItems = new DelegateCommand <int?>(destIndex => { using (script.BulkEdit("Reorder events")) { var selected = new List <SmartEvent>(); int d = destIndex.Value; for (int i = Events.Count - 1; i >= 0; --i) { if (Events[i].IsSelected) { if (i <= destIndex) { d--; } selected.Add(Events[i]); script.Events.RemoveAt(i); } } if (d == -1) { d = 0; } selected.Reverse(); foreach (var s in selected) { script.Events.Insert(d++, s); } } }); OnDropActions = new DelegateCommand <DropActionsArgs>(data => { using (script.BulkEdit("Reorder actions")) { var selected = new List <SmartAction>(); var d = data.ActionIndex; for (var eventIndex = 0; eventIndex < Events.Count; eventIndex++) { var e = Events[eventIndex]; for (int i = e.Actions.Count - 1; i >= 0; --i) { if (e.Actions[i].IsSelected) { if (eventIndex == data.EventIndex && i < data.ActionIndex) { d--; } selected.Add(e.Actions[i]); e.Actions.RemoveAt(i); } } } selected.Reverse(); foreach (var s in selected) { Events[data.EventIndex].Actions.Insert(d++, s); } } }); EditAction = new DelegateCommand <SmartAction>(action => EditActionCommand(action)); AddEvent = new DelegateCommand(AddEventCommand); AddAction = new DelegateCommand <NewActionViewModel>(AddActionCommand); SaveCommand = new AsyncAutoCommand(SaveAllToDb, null, e => { statusbar.PublishNotification(new PlainNotification(NotificationType.Error, "Error while saving script to the database: " + e.Message)); }); DeleteAction = new DelegateCommand <SmartAction>(DeleteActionCommand); DeleteSelected = new DelegateCommand(() => { if (anyEventSelected) { using (script.BulkEdit("Delete events")) { int?nextSelect = firstSelectedIndex; if (multipleEventsSelected) { nextSelect = null; } for (int i = Events.Count - 1; i >= 0; --i) { if (Events[i].IsSelected) { Events.RemoveAt(i); } } if (nextSelect.HasValue) { if (nextSelect.Value < Events.Count) { Events[nextSelect.Value].IsSelected = true; } else if (nextSelect.Value - 1 >= 0 && nextSelect.Value - 1 < Events.Count) { Events[nextSelect.Value - 1].IsSelected = true; } } } } else if (anyActionSelected) { using (script.BulkEdit("Delete actions")) { (int eventIndex, int actionIndex)? nextSelect = firstSelectedActionIndex; if (multipleActionsSelected) { nextSelect = null; } for (int i = 0; i < Events.Count; ++i) { var e = Events[i]; for (int j = e.Actions.Count - 1; j >= 0; --j) { if (e.Actions[j].IsSelected) { e.Actions.RemoveAt(j); } } } if (nextSelect.HasValue && nextSelect.Value.actionIndex < Events[nextSelect.Value.eventIndex].Actions.Count) { Events[nextSelect.Value.eventIndex].Actions[nextSelect.Value.actionIndex].IsSelected = true; } } } }); UndoCommand = new DelegateCommand(history.Undo, () => history.CanUndo); RedoCommand = new DelegateCommand(history.Redo, () => history.CanRedo); EditSelected = new DelegateCommand(() => { if (anyEventSelected) { if (!multipleEventsSelected) { EditEventCommand(); } } else if (anyActionSelected && !multipleActionsSelected) { EditActionCommand(Events[firstSelectedActionIndex.eventIndex] .Actions[firstSelectedActionIndex.actionIndex]); } }); CopyCommand = new DelegateCommand(() => { var selectedEvents = Events.Where(e => e.IsSelected).ToList(); if (selectedEvents.Count > 0) { var lines = string.Join("\n", selectedEvents.SelectMany((e, index) => e.ToSmartScriptLines(script.EntryOrGuid, script.SourceType, index)).Select(s => s.ToSqlString())); Clipboard.SetText(lines); } else { var selectedActions = Events.SelectMany(e => e.Actions).Where(e => e.IsSelected).ToList(); if (selectedActions.Count > 0) { var fakeEvent = new SmartEvent(-1) { ReadableHint = "" }; foreach (var a in selectedActions) { fakeEvent.AddAction(a.Copy()); } var lines = string.Join("\n", fakeEvent.ToSmartScriptLines(script.EntryOrGuid, script.SourceType, 0).Select(s => s.ToSqlString())); Clipboard.SetText(lines); } } }); CutCommand = new DelegateCommand(() => { CopyCommand.Execute(); DeleteSelected.Execute(); }); PasteCommand = new DelegateCommand(() => { var lines = (Clipboard.GetText() ?? "").Split('\n').Select(line => { if (line.TryToISmartScriptLine(out var s)) { return(s); } return(null); }).Where(l => l != null).ToList(); if (lines.Count > 0) { if (lines[0].EventType == -1) // actions { int?eventIndex = null; int?actionIndex = null; using (script.BulkEdit("Paste actions")) { for (int i = 0; i < Events.Count - 1; ++i) { if (Events[i].IsSelected) { eventIndex = i; } for (int j = Events[i].Actions.Count - 1; j >= 0; j--) { if (Events[i].Actions[j].IsSelected) { eventIndex = i; if (!actionIndex.HasValue) { actionIndex = j; } else { actionIndex--; } //Events[i].Actions.RemoveAt(j); } } } if (!eventIndex.HasValue) { eventIndex = Events.Count - 1; } if (eventIndex < 0) { return; } if (!actionIndex.HasValue) { actionIndex = Events[eventIndex.Value].Actions.Count - 1; } if (actionIndex < 0) { actionIndex = 0; } DeselectAll.Execute(); foreach (var smartAction in lines.Select(line => script.SafeActionFactory(line))) { Events[eventIndex.Value].Actions.Insert(actionIndex.Value, smartAction); smartAction.IsSelected = true; actionIndex++; } } } else { int?index = null; using (script.BulkEdit("Paste events")) { for (int i = Events.Count - 1; i >= 0; --i) { if (Events[i].IsSelected) { if (!index.HasValue) { index = i; } else { index--; } //Events.RemoveAt(i); } } if (!index.HasValue) { index = Events.Count; } script.InsertFromClipboard(index.Value, lines); } } } }); Action <bool, int> selectionUpDown = (addToSelection, diff) => { if (anyEventSelected) { var selectedEventIndex = Math.Clamp(firstSelectedIndex + diff, 0, Events.Count - 1); if (!addToSelection) { DeselectAll.Execute(); } Events[selectedEventIndex].IsSelected = true; } else if (anyActionSelected) { var nextActionIndex = firstSelectedActionIndex.actionIndex + diff; var nextEventIndex = firstSelectedActionIndex.eventIndex; while (nextActionIndex == -1 || nextActionIndex >= Events[nextEventIndex].Actions.Count) { nextEventIndex += diff; if (nextEventIndex >= 0 && nextEventIndex < Events.Count) { nextActionIndex = diff > 0 ? (Events[nextEventIndex].Actions.Count > 0 ? 0 : -1) : Events[nextEventIndex].Actions.Count - 1; } else { break; } } if (nextActionIndex != -1 && nextEventIndex >= 0 && nextEventIndex < Events.Count) { DeselectAll.Execute(); Events[nextEventIndex].Actions[nextActionIndex].IsSelected = true; } } else { if (Events.Count > 0) { Events[diff > 0 ? 0 : Events.Count - 1].IsSelected = true; } } }; SelectionUp = new DelegateCommand <bool?>(addToSelection => selectionUpDown(addToSelection ?? false, -1)); SelectionDown = new DelegateCommand <bool?>(addToSelection => selectionUpDown(addToSelection ?? false, 1)); SelectionLeft = new DelegateCommand(() => { if (!anyEventSelected && anyActionSelected) { var actionEventIndex = firstSelectedActionIndex; DeselectAll.Execute(); Events[actionEventIndex.eventIndex].IsSelected = true; } else if (!anyEventSelected && !anyActionSelected) { selectionUpDown(false, -1); } }); SelectionRight = new DelegateCommand(() => { if (!anyEventSelected) { selectionUpDown(false, -1); } if (anyEventSelected) { var eventIndex = firstSelectedIndex; if (Events[eventIndex].Actions.Count > 0) { DeselectAll.Execute(); Events[eventIndex].Actions[0].IsSelected = true; } } }); SelectAll = new DelegateCommand(() => { foreach (var e in Events) { e.IsSelected = true; } }); this.history.PropertyChanged += (sender, args) => { UndoCommand.RaiseCanExecuteChanged(); RedoCommand.RaiseCanExecuteChanged(); }; token = eventAggregator.GetEvent <EventRequestGenerateSql>().Subscribe((args) => { if (args.Item is SmartScriptSolutionItem) { var itemm = args.Item as SmartScriptSolutionItem; if (itemm.Entry == _item.Entry && itemm.SmartType == _item.SmartType) { args.Sql = new SmartScriptExporter(script, smartFactory).GetSql(); } } }); }