From ac007cfe2c6276bb6b9e841a66b6d2b6ed630d05 Mon Sep 17 00:00:00 2001 From: Sebastian Lenz Date: Mon, 20 Aug 2018 23:05:02 +0200 Subject: [PATCH] Initial commit --- .editorconfig | 10 + .gitignore | 10 + .vscodeignore | 30 + CHANGELOG.md | 3 + LICENSE | 15 + README.md | 157 + package-lock.json | 2211 ++ package.json | 274 + resources/assets/api.css | 204 + resources/assets/api.js | 42 + resources/extension.png | Bin 0 -> 2880 bytes resources/extension.svg | 25 + resources/features/api-explorer.gif | Bin 0 -> 60840 bytes resources/features/code-analysis.gif | Bin 0 -> 51159 bytes resources/features/completion.gif | Bin 0 -> 278525 bytes resources/features/document-structure.gif | Bin 0 -> 43574 bytes resources/features/find-references.gif | Bin 0 -> 122177 bytes resources/features/hover.gif | Bin 0 -> 45558 bytes resources/features/rename.gif | Bin 0 -> 125002 bytes resources/features/story-outline.gif | Bin 0 -> 93038 bytes resources/icons/call-dark.svg | 1 + resources/icons/call-light.svg | 1 + resources/icons/category-dark.svg | 1 + resources/icons/category-light.svg | 1 + resources/icons/event-dark.svg | 1 + resources/icons/event-light.svg | 1 + resources/icons/goal-custom-dark.svg | 3 + resources/icons/goal-custom-light.svg | 3 + resources/icons/goal-shared-dark.svg | 3 + resources/icons/goal-shared-light.svg | 3 + resources/icons/query-dark.svg | 1 + resources/icons/query-light.svg | 1 + resources/templates/pages/category.hbs | 19 + resources/templates/pages/definition.hbs | 39 + resources/templates/pages/layout.hbs | 17 + resources/templates/partials/breadcrumbs.hbs | 11 + resources/templates/partials/definitions.hbs | 13 + src/client/Client.ts | 116 + src/client/features/Feature.ts | 21 + .../features/activityIndicator/index.ts | 89 + src/client/features/apiExplorer/index.ts | 163 + src/client/features/divProvider/index.ts | 58 + src/client/features/index.ts | 18 + src/client/features/storyOutline/index.ts | 359 + src/client/features/taskProvider/index.ts | 226 + src/client/index.ts | 21 + src/server/Server.ts | 253 + src/server/documentation/Documentation.ts | 83 + src/server/documentation/commands/compile.ts | 13 + src/server/documentation/commands/update.ts | 15 + src/server/documentation/raw/Category.ts | 97 + src/server/documentation/raw/Definition.ts | 115 + src/server/documentation/raw/Repository.ts | 129 + src/server/documentation/raw/WikiReader.ts | 254 + src/server/features/Feature.ts | 107 + .../features/activityIndicator/index.ts | 59 + .../features/apiExplorer/CategoryHandler.ts | 40 + .../features/apiExplorer/DefinitionHandler.ts | 96 + src/server/features/apiExplorer/Handler.ts | 112 + src/server/features/apiExplorer/index.ts | 106 + src/server/features/completion/index.ts | 335 + src/server/features/definition/index.ts | 75 + src/server/features/diagnostics/index.ts | 89 + src/server/features/divProvider/index.ts | 34 + src/server/features/documentSymbols/index.ts | 101 + src/server/features/hover/ConstantProvider.ts | 43 + src/server/features/hover/GuidProvider.ts | 35 + src/server/features/hover/Provider.ts | 32 + .../features/hover/SignatureProvider.ts | 83 + src/server/features/hover/VariableProvider.ts | 49 + src/server/features/hover/index.ts | 75 + src/server/features/index.ts | 32 + src/server/features/references/index.ts | 60 + src/server/features/rename/index.ts | 222 + src/server/features/signatureHelp/index.ts | 176 + src/server/features/storyOutline/index.ts | 189 + src/server/index.ts | 3 + src/server/parsers/lsf/BufferReader.ts | 101 + src/server/parsers/lsf/LICENSE | 25 + src/server/parsers/lsf/Parser.ts | 443 + src/server/parsers/lsf/models/Matrix.ts | 32 + src/server/parsers/lsf/models/Node.ts | 40 + .../parsers/lsf/models/NodeAttribute.ts | 152 + src/server/parsers/lsf/models/Region.ts | 3 + src/server/parsers/lsf/models/Resource.ts | 43 + .../lsf/structs/LSFAttributeEntryV2.ts | 64 + .../lsf/structs/LSFAttributeEntryV3.ts | 65 + src/server/parsers/lsf/structs/LSFHeader.ts | 122 + .../parsers/lsf/structs/LSFNodeEntryV2.ts | 44 + .../parsers/lsf/structs/LSFNodeEntryV3.ts | 51 + .../parsers/lsf/utils/compressionMethod.ts | 21 + src/server/parsers/lsf/utils/readAttribute.ts | 111 + src/server/parsers/story/GoalParser.ts | 202 + src/server/parsers/story/HeaderParser.ts | 271 + src/server/parsers/story/Lexer.ts | 526 + src/server/parsers/story/Parser.ts | 721 + .../story/messages/msgEmptyRuleBody.ts | 14 + .../story/messages/msgInvalidGoalSection.ts | 19 + .../messages/msgInvalidOptionLocation.ts | 23 + .../story/messages/msgInvalidOptionName.ts | 19 + .../story/messages/msgInvalidOptionValue.ts | 23 + .../story/messages/msgNewLineInString.ts | 13 + .../story/messages/msgPrematureRealEnd.ts | 13 + .../story/messages/msgUnexpectedToken.ts | 51 + .../parsers/story/models/diagnostics.ts | 136 + src/server/parsers/story/models/nodes.ts | 187 + .../parsers/story/utils/copyTokenRange.ts | 10 + src/server/parsers/story/utils/eachCaller.ts | 56 + src/server/parsers/story/utils/eachNode.ts | 72 + .../parsers/story/utils/eachNodeRecursive.ts | 17 + .../parsers/story/utils/eachRuleNode.ts | 84 + .../parsers/story/utils/isActionNode.ts | 16 + .../parsers/story/utils/isArgumentNode.ts | 24 + .../parsers/story/utils/isCallerNode.ts | 17 + .../parsers/story/utils/isConditionNode.ts | 16 + src/server/parsers/story/utils/isRuleToken.ts | 19 + .../parsers/story/utils/isStoryToken.ts | 25 + .../parsers/story/utils/packPosition.ts | 8 + src/server/parsers/story/utils/printNode.ts | 59 + src/server/parsers/story/utils/printToken.ts | 22 + .../parsers/story/utils/printTokenType.ts | 80 + .../parsers/story/utils/unpackPosition.ts | 9 + src/server/parsers/story/utils/unpackRange.ts | 11 + src/server/projects/FileWatcher.ts | 171 + src/server/projects/Project.ts | 36 + src/server/projects/index.ts | 120 + src/server/projects/levels/index.ts | 166 + src/server/projects/story/Goal.ts | 66 + src/server/projects/story/Symbol.ts | 336 + src/server/projects/story/Symbols.ts | 163 + .../projects/story/analyzers/Analyzer.ts | 56 + .../story/analyzers/GuidLiteralAnalyzer.ts | 0 .../projects/story/analyzers/Parameter.ts | 386 + .../story/analyzers/SymbolLocations.ts | 112 + .../projects/story/analyzers/SymbolTypes.ts | 86 + src/server/projects/story/analyzers/index.ts | 67 + src/server/projects/story/index.ts | 276 + .../messages/msgCanOnlyDeleteFromDatabase.ts | 23 + .../messages/msgComparisonTypeMismatch.ts | 27 + .../story/messages/msgDangerousCast.ts | 25 + .../story/messages/msgDatabaseNoRead.ts | 22 + .../story/messages/msgDatabaseNoWrite.ts | 22 + .../messages/msgInvalidDatabasePrefix.ts | 22 + .../story/messages/msgInvalidPlaceholder.ts | 22 + .../messages/msgInvalidSymbolInCondition.ts | 23 + .../story/messages/msgInvalidSymbolInFact.ts | 23 + .../msgInvalidSymbolInInitialCondition.ts | 48 + .../messages/msgInvalidSymbolInStatement.ts | 23 + .../story/messages/msgInvalidTypeCast.ts | 36 + .../story/messages/msgInvalidVariableName.ts | 20 + .../messages/msgParamaterCountMismatch.ts | 34 + .../messages/msgParameterTypeMismatch.ts | 33 + .../story/messages/msgSigantureTypo.ts | 38 + .../story/messages/msgStringLtGtComparison.ts | 20 + .../story/messages/msgUnresolvedSignature.ts | 59 + .../story/messages/msgUnresolvedSymbol.ts | 20 + .../story/messages/msgVariableNotAllowed.ts | 19 + .../story/messages/msgVariableNotBound.ts | 29 + src/server/projects/story/models/parameter.ts | 30 + src/server/projects/story/models/symbol.ts | 35 + .../projects/story/resources/FileResource.ts | 32 + .../projects/story/resources/GoalResource.ts | 79 + .../story/resources/HeaderGoalResource.ts | 80 + .../story/resources/HeaderResource.ts | 117 + .../projects/story/resources/Resource.ts | 137 + .../projects/story/utils/getAnnotatedType.ts | 14 + .../story/utils/getCallerSymbolType.ts | 21 + .../story/utils/getConstantParameterType.ts | 22 + .../story/utils/getDefinitionSymbolType.ts | 17 + .../story/utils/getExplicitParameterType.ts | 14 + .../story/utils/getParameterNameScore.ts | 7 + .../projects/story/utils/parseDocComment.ts | 226 + .../story/utils/printParameterFlow.ts | 12 + .../story/utils/printParameterType.ts | 28 + .../projects/story/utils/printSymbol.ts | 26 + .../projects/story/utils/printSymbolType.ts | 23 + .../projects/story/utils/resolveParameters.ts | 70 + src/server/projects/story/utils/sortGoals.ts | 5 + .../projects/story/utils/toParameterType.ts | 28 + .../projects/story/utils/toParameters.ts | 75 + .../story/utils/toSymbolTypeFromString.ts | 20 + src/server/utils/debounce.ts | 13 + src/server/utils/fetch.ts | 30 + src/server/utils/parseUri.ts | 34 + src/server/utils/readProjectMetaInfo.ts | 21 + src/server/utils/readXmlFile.ts | 17 + src/server/utils/runSafe.ts | 55 + src/server/utils/runSafeAsync.ts | 40 + src/server/utils/sleep.ts | 5 + src/server/utils/toLocation.ts | 13 + src/server/utils/ucfirst.ts | 3 + src/shared/fs.ts | 11 + src/shared/getPackagePath.ts | 5 + src/shared/goalTemplate.ts | 35 + src/shared/notifications.ts | 66 + src/shared/requests.ts | 38 + ...nity-story-div.language-configuration.json | 16 + syntaxes/divinity-story-div.tmLanguage.json | 96 + ...ity-story-goal.language-configuration.json | 16 + syntaxes/divinity-story-goal.snippets.json | 22 + syntaxes/divinity-story-goal.tmLanguage.json | 90 + test/fixtures/analyzer.txt | 242 + test/fixtures/headers.div | 19785 ++++++++++++++++ test/fixtures/object.lsf | Bin 0 -> 2126 bytes test/fixtures/simple.txt | 40 + test/lsf-parser.js | 12 + test/story-parser.js | 38 + tsconfig.json | 13 + tsconfig.publish.json | 6 + 209 files changed, 35872 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .vscodeignore create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 resources/assets/api.css create mode 100644 resources/assets/api.js create mode 100644 resources/extension.png create mode 100644 resources/extension.svg create mode 100644 resources/features/api-explorer.gif create mode 100644 resources/features/code-analysis.gif create mode 100644 resources/features/completion.gif create mode 100644 resources/features/document-structure.gif create mode 100644 resources/features/find-references.gif create mode 100644 resources/features/hover.gif create mode 100644 resources/features/rename.gif create mode 100644 resources/features/story-outline.gif create mode 100644 resources/icons/call-dark.svg create mode 100644 resources/icons/call-light.svg create mode 100644 resources/icons/category-dark.svg create mode 100644 resources/icons/category-light.svg create mode 100644 resources/icons/event-dark.svg create mode 100644 resources/icons/event-light.svg create mode 100644 resources/icons/goal-custom-dark.svg create mode 100644 resources/icons/goal-custom-light.svg create mode 100644 resources/icons/goal-shared-dark.svg create mode 100644 resources/icons/goal-shared-light.svg create mode 100644 resources/icons/query-dark.svg create mode 100644 resources/icons/query-light.svg create mode 100644 resources/templates/pages/category.hbs create mode 100644 resources/templates/pages/definition.hbs create mode 100644 resources/templates/pages/layout.hbs create mode 100644 resources/templates/partials/breadcrumbs.hbs create mode 100644 resources/templates/partials/definitions.hbs create mode 100644 src/client/Client.ts create mode 100644 src/client/features/Feature.ts create mode 100644 src/client/features/activityIndicator/index.ts create mode 100644 src/client/features/apiExplorer/index.ts create mode 100644 src/client/features/divProvider/index.ts create mode 100644 src/client/features/index.ts create mode 100644 src/client/features/storyOutline/index.ts create mode 100644 src/client/features/taskProvider/index.ts create mode 100644 src/client/index.ts create mode 100644 src/server/Server.ts create mode 100644 src/server/documentation/Documentation.ts create mode 100644 src/server/documentation/commands/compile.ts create mode 100644 src/server/documentation/commands/update.ts create mode 100644 src/server/documentation/raw/Category.ts create mode 100644 src/server/documentation/raw/Definition.ts create mode 100644 src/server/documentation/raw/Repository.ts create mode 100644 src/server/documentation/raw/WikiReader.ts create mode 100644 src/server/features/Feature.ts create mode 100644 src/server/features/activityIndicator/index.ts create mode 100644 src/server/features/apiExplorer/CategoryHandler.ts create mode 100644 src/server/features/apiExplorer/DefinitionHandler.ts create mode 100644 src/server/features/apiExplorer/Handler.ts create mode 100644 src/server/features/apiExplorer/index.ts create mode 100644 src/server/features/completion/index.ts create mode 100644 src/server/features/definition/index.ts create mode 100644 src/server/features/diagnostics/index.ts create mode 100644 src/server/features/divProvider/index.ts create mode 100644 src/server/features/documentSymbols/index.ts create mode 100644 src/server/features/hover/ConstantProvider.ts create mode 100644 src/server/features/hover/GuidProvider.ts create mode 100644 src/server/features/hover/Provider.ts create mode 100644 src/server/features/hover/SignatureProvider.ts create mode 100644 src/server/features/hover/VariableProvider.ts create mode 100644 src/server/features/hover/index.ts create mode 100644 src/server/features/index.ts create mode 100644 src/server/features/references/index.ts create mode 100644 src/server/features/rename/index.ts create mode 100644 src/server/features/signatureHelp/index.ts create mode 100644 src/server/features/storyOutline/index.ts create mode 100644 src/server/index.ts create mode 100644 src/server/parsers/lsf/BufferReader.ts create mode 100644 src/server/parsers/lsf/LICENSE create mode 100644 src/server/parsers/lsf/Parser.ts create mode 100644 src/server/parsers/lsf/models/Matrix.ts create mode 100644 src/server/parsers/lsf/models/Node.ts create mode 100644 src/server/parsers/lsf/models/NodeAttribute.ts create mode 100644 src/server/parsers/lsf/models/Region.ts create mode 100644 src/server/parsers/lsf/models/Resource.ts create mode 100644 src/server/parsers/lsf/structs/LSFAttributeEntryV2.ts create mode 100644 src/server/parsers/lsf/structs/LSFAttributeEntryV3.ts create mode 100644 src/server/parsers/lsf/structs/LSFHeader.ts create mode 100644 src/server/parsers/lsf/structs/LSFNodeEntryV2.ts create mode 100644 src/server/parsers/lsf/structs/LSFNodeEntryV3.ts create mode 100644 src/server/parsers/lsf/utils/compressionMethod.ts create mode 100644 src/server/parsers/lsf/utils/readAttribute.ts create mode 100644 src/server/parsers/story/GoalParser.ts create mode 100644 src/server/parsers/story/HeaderParser.ts create mode 100644 src/server/parsers/story/Lexer.ts create mode 100644 src/server/parsers/story/Parser.ts create mode 100644 src/server/parsers/story/messages/msgEmptyRuleBody.ts create mode 100644 src/server/parsers/story/messages/msgInvalidGoalSection.ts create mode 100644 src/server/parsers/story/messages/msgInvalidOptionLocation.ts create mode 100644 src/server/parsers/story/messages/msgInvalidOptionName.ts create mode 100644 src/server/parsers/story/messages/msgInvalidOptionValue.ts create mode 100644 src/server/parsers/story/messages/msgNewLineInString.ts create mode 100644 src/server/parsers/story/messages/msgPrematureRealEnd.ts create mode 100644 src/server/parsers/story/messages/msgUnexpectedToken.ts create mode 100644 src/server/parsers/story/models/diagnostics.ts create mode 100644 src/server/parsers/story/models/nodes.ts create mode 100644 src/server/parsers/story/utils/copyTokenRange.ts create mode 100644 src/server/parsers/story/utils/eachCaller.ts create mode 100644 src/server/parsers/story/utils/eachNode.ts create mode 100644 src/server/parsers/story/utils/eachNodeRecursive.ts create mode 100644 src/server/parsers/story/utils/eachRuleNode.ts create mode 100644 src/server/parsers/story/utils/isActionNode.ts create mode 100644 src/server/parsers/story/utils/isArgumentNode.ts create mode 100644 src/server/parsers/story/utils/isCallerNode.ts create mode 100644 src/server/parsers/story/utils/isConditionNode.ts create mode 100644 src/server/parsers/story/utils/isRuleToken.ts create mode 100644 src/server/parsers/story/utils/isStoryToken.ts create mode 100644 src/server/parsers/story/utils/packPosition.ts create mode 100644 src/server/parsers/story/utils/printNode.ts create mode 100644 src/server/parsers/story/utils/printToken.ts create mode 100644 src/server/parsers/story/utils/printTokenType.ts create mode 100644 src/server/parsers/story/utils/unpackPosition.ts create mode 100644 src/server/parsers/story/utils/unpackRange.ts create mode 100644 src/server/projects/FileWatcher.ts create mode 100644 src/server/projects/Project.ts create mode 100644 src/server/projects/index.ts create mode 100644 src/server/projects/levels/index.ts create mode 100644 src/server/projects/story/Goal.ts create mode 100644 src/server/projects/story/Symbol.ts create mode 100644 src/server/projects/story/Symbols.ts create mode 100644 src/server/projects/story/analyzers/Analyzer.ts create mode 100644 src/server/projects/story/analyzers/GuidLiteralAnalyzer.ts create mode 100644 src/server/projects/story/analyzers/Parameter.ts create mode 100644 src/server/projects/story/analyzers/SymbolLocations.ts create mode 100644 src/server/projects/story/analyzers/SymbolTypes.ts create mode 100644 src/server/projects/story/analyzers/index.ts create mode 100644 src/server/projects/story/index.ts create mode 100644 src/server/projects/story/messages/msgCanOnlyDeleteFromDatabase.ts create mode 100644 src/server/projects/story/messages/msgComparisonTypeMismatch.ts create mode 100644 src/server/projects/story/messages/msgDangerousCast.ts create mode 100644 src/server/projects/story/messages/msgDatabaseNoRead.ts create mode 100644 src/server/projects/story/messages/msgDatabaseNoWrite.ts create mode 100644 src/server/projects/story/messages/msgInvalidDatabasePrefix.ts create mode 100644 src/server/projects/story/messages/msgInvalidPlaceholder.ts create mode 100644 src/server/projects/story/messages/msgInvalidSymbolInCondition.ts create mode 100644 src/server/projects/story/messages/msgInvalidSymbolInFact.ts create mode 100644 src/server/projects/story/messages/msgInvalidSymbolInInitialCondition.ts create mode 100644 src/server/projects/story/messages/msgInvalidSymbolInStatement.ts create mode 100644 src/server/projects/story/messages/msgInvalidTypeCast.ts create mode 100644 src/server/projects/story/messages/msgInvalidVariableName.ts create mode 100644 src/server/projects/story/messages/msgParamaterCountMismatch.ts create mode 100644 src/server/projects/story/messages/msgParameterTypeMismatch.ts create mode 100644 src/server/projects/story/messages/msgSigantureTypo.ts create mode 100644 src/server/projects/story/messages/msgStringLtGtComparison.ts create mode 100644 src/server/projects/story/messages/msgUnresolvedSignature.ts create mode 100644 src/server/projects/story/messages/msgUnresolvedSymbol.ts create mode 100644 src/server/projects/story/messages/msgVariableNotAllowed.ts create mode 100644 src/server/projects/story/messages/msgVariableNotBound.ts create mode 100644 src/server/projects/story/models/parameter.ts create mode 100644 src/server/projects/story/models/symbol.ts create mode 100644 src/server/projects/story/resources/FileResource.ts create mode 100644 src/server/projects/story/resources/GoalResource.ts create mode 100644 src/server/projects/story/resources/HeaderGoalResource.ts create mode 100644 src/server/projects/story/resources/HeaderResource.ts create mode 100644 src/server/projects/story/resources/Resource.ts create mode 100644 src/server/projects/story/utils/getAnnotatedType.ts create mode 100644 src/server/projects/story/utils/getCallerSymbolType.ts create mode 100644 src/server/projects/story/utils/getConstantParameterType.ts create mode 100644 src/server/projects/story/utils/getDefinitionSymbolType.ts create mode 100644 src/server/projects/story/utils/getExplicitParameterType.ts create mode 100644 src/server/projects/story/utils/getParameterNameScore.ts create mode 100644 src/server/projects/story/utils/parseDocComment.ts create mode 100644 src/server/projects/story/utils/printParameterFlow.ts create mode 100644 src/server/projects/story/utils/printParameterType.ts create mode 100644 src/server/projects/story/utils/printSymbol.ts create mode 100644 src/server/projects/story/utils/printSymbolType.ts create mode 100644 src/server/projects/story/utils/resolveParameters.ts create mode 100644 src/server/projects/story/utils/sortGoals.ts create mode 100644 src/server/projects/story/utils/toParameterType.ts create mode 100644 src/server/projects/story/utils/toParameters.ts create mode 100644 src/server/projects/story/utils/toSymbolTypeFromString.ts create mode 100644 src/server/utils/debounce.ts create mode 100644 src/server/utils/fetch.ts create mode 100644 src/server/utils/parseUri.ts create mode 100644 src/server/utils/readProjectMetaInfo.ts create mode 100644 src/server/utils/readXmlFile.ts create mode 100644 src/server/utils/runSafe.ts create mode 100644 src/server/utils/runSafeAsync.ts create mode 100644 src/server/utils/sleep.ts create mode 100644 src/server/utils/toLocation.ts create mode 100644 src/server/utils/ucfirst.ts create mode 100644 src/shared/fs.ts create mode 100644 src/shared/getPackagePath.ts create mode 100644 src/shared/goalTemplate.ts create mode 100644 src/shared/notifications.ts create mode 100644 src/shared/requests.ts create mode 100644 syntaxes/divinity-story-div.language-configuration.json create mode 100644 syntaxes/divinity-story-div.tmLanguage.json create mode 100644 syntaxes/divinity-story-goal.language-configuration.json create mode 100644 syntaxes/divinity-story-goal.snippets.json create mode 100644 syntaxes/divinity-story-goal.tmLanguage.json create mode 100644 test/fixtures/analyzer.txt create mode 100644 test/fixtures/headers.div create mode 100644 test/fixtures/object.lsf create mode 100644 test/fixtures/simple.txt create mode 100644 test/lsf-parser.js create mode 100644 test/story-parser.js create mode 100644 tsconfig.json create mode 100644 tsconfig.publish.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1bb8032 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 + +[*.txt] +end_of_line = crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0707290 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.vscode +bin +etc +lib +node_modules + +docs +!docs/compile.bat +!docs/LICENSE +!docs/update.bat diff --git a/.vscodeignore b/.vscodeignore new file mode 100644 index 0000000..5b93824 --- /dev/null +++ b/.vscodeignore @@ -0,0 +1,30 @@ +.vscode/** +.gitignore +.travis.yml +tsconfig.json +contributing.md +package-lock.json + +bin +etc +src +test + +docs/** +!docs/cache +!docs/LICENSE + +node_modules/** +!node_modules/fast-levenshtein +!node_modules/handlebars +!node_modules/long +!node_modules/promise-queue +!node_modules/sax +!node_modules/semver +!node_modules/vscode-languageclient +!node_modules/vscode-languageserver +!node_modules/vscode-languageserver-protocol/** +!node_modules/vscode-languageserver-types/** +!node_modules/vscode-jsonrpc/** +!node_modules/xml2js +!node_modules/xmlbuilder diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9287bcc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +# Version 1.0.0 + +Initial release diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..83be731 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +MIT License + +Copyright (c) 2018 Sebastian Lenz + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..98b0351 --- /dev/null +++ b/README.md @@ -0,0 +1,157 @@ +# Divinity Engine Script Support for VS Code + +This extensions enables language features for the scripting language Osiris found in The Divinity Engine 2 based games. + +## Getting started + +### Installation + +- Open the extensions tab (usually the last button in the action bar. You can lso use the shortcut Ctrl+Shift+X) +- Search for "divinity-vscode" +- On the plugin page, click the "Install", then the "Enable" button + +### Open project + +- Before editing a project for the first time in VS Code, make sure you have a fresh built of the project. + - Start the Glasses editor and switch to your project. + - Open the story editor and choose "File" > "Build". +- In VS Code, select "File" > "Open Folder..." and select the data folder of your project. The path usually looks something like this: `../Divinity Original Sin 2/Data/Mods/MyModeName_########-####-####-####-############` +- After a moment the story outline panel should show up beneath your files and you are ready to go. + +## Features + +### Story outline + +The story outline brings you the familiar tree view from the native editor to VS Code. You can add, delete, move and rename goals using it. + +![Story outline](resources/features/story-outline.gif) + +### Code analysis + +The extension analyzes your code while you type and immediately shows you errors and problems. + +![Code analysis](resources/features/code-analysis.gif) + +### Completion + +Code completion shows you matching symbols for your current input, it will show up automatically when typing or by pressing Shift+Space. The suggestions are context sensitive and only show you the symbols that are currently available. + +![Code completion](resources/features/completion.gif) + +### Find all references and go to definition + +Bring up a list of all usages of a procedure, query or database by pressing Shift+F12 or selecting the command `Find All References` from the context menu. You can also jump to the definition by pressing F12 or using the command `Go to Definition`. + +![Goto definition and find all references](resources/features/find-references.gif) + +### Document structure + +Use the outline panel to get a broad overview over your current goal or jump to individial rules using the the shortcut Ctrl+Shift+O. + +![Document structure](resources/features/document-structure.gif) + +### Hover and signature help + +Quickly gain information about the symbols on screen, move your mouse over them and the extension will show you a short info. The signature help shows up everytime you start writing a function call (when pressing `(` or with the shortcut Ctrl+Shift+Space) and shows you a preview of the parameters. + +![Hover and signature help](resources/features/hover.gif) + +### Rename + +You can rename custom procedures, databases and queries as well as variables and GUID references. Press F2 while the cursor is above the symbol you want to rename or use the rename command from the context menu. + +![Rename](resources/features/rename.gif) + +### API Explorer + +Built in browser for the complete API with contents fetched from the Divinity Wiki when available. Open the command palette (e.g. press Ctrl+Shift+P) and search for the command `Show API explorer` to open the API explorer. + +![API explorer](resources/features/api-explorer.gif) + +### Custom documentation support + +The code completion, hovers and the signature help will show you short snippet from the Wiki to assist you. You can add documentation to your own procedures and queries by placing a JSDoc comment above them. + +## Differences to the built in editor + +Unlike the built in editor VS Code will not display three different regions when editing story goals. Instead you'll see the complete source file of each goal. The basic file structure looks like this: + +```javascript +Version 1 +SubGoalCombiner SGC_AND +INITSECTION + +// Init section contents go here + +KBSECTION + +// KB section contents go here + +EXITSECTION + +// Exit section contents go here + +ENDEXITSECTION +ParentTargetEdge "NameOfParentGoal" +``` + +You can safely ignore the header section, it will be the same for all your goals. The three main sections are self explonary and are the equvalent of the three panels you see in the built in editor. Beneath the exit section you'll notice the command `ParentTargetEdge`, this command tells the game the name of the parent goal. You may use the story outline to move goals around or you can directly edit the structure here. + +## Feedback + +All feedback is welcome. Please head over to the GitHub page of this project and start a new issue if you find any problems: +https://github.com/sebastian-lenz/divinity-vscode + +## License + +This extension is released under the MIT License. + +### Packaged software + +This extension uses several external dependencies, the following modules +are part of the installed extension: + +- **djsdoc** + Copyright (c) 2016-present Zeit, Inc. + GPL v3.0 License + https://github.com/EYHN/djsdoc +- **fast-levenshtein** + Copyright (c) 2013 Ramesh Nair + MIT License + https://github.com/hiddentao/fast-levenshtein +- **Handlebars.js** + Copyright (C) 2011-2017 by Yehuda Katz + MIT License + https://github.com/wycats/handlebars.js +- **long.js** + Copyright (C) Daniel Wirtz + Apache License Version 2.0 + https://github.com/dcodeIO/long.js +- **lslib** + Copyright (c) 2015 Norbyte + MIT License + https://github.com/Norbyte/lslib +- **promise-queue** + Copyright (c) 2013 Mikhail Davydov and other contributors + MIT License + https://github.com/promise-queue/promise-queue +- **sax** + Copyright (c) Isaac Z. Schlueter and Contributors + ISC License + https://github.com/isaacs/sax-js/blob/master/LICENSE +- **semver** + Copyright (c) Isaac Z. Schlueter and Contributors + ISC License + https://github.com/npm/node-semver +- **vscode** + Copyright (c) Microsoft Corporation + MIT License + https://github.com/Microsoft/vscode +- **node-xml2js** + Copyright 2010, 2011, 2012, 2013. All rights reserved. + MIT License + https://github.com/Leonidas-from-XIV/node-xml2js +- **xmlbuilder-js** + Copyright (c) 2013 Ozgur Ozcitak + MIT License + https://github.com/oozcitak/xmlbuilder-js diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f9a9abf --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2211 @@ +{ + "name": "divinity-vscode", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/events": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", + "dev": true + }, + "@types/fast-levenshtein": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@types/fast-levenshtein/-/fast-levenshtein-0.0.1.tgz", + "integrity": "sha1-OjYVzxc2Rcj8pY0FHk4ygk5L0oY=", + "dev": true + }, + "@types/glob": { + "version": "5.0.35", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz", + "integrity": "sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/handlebars": { + "version": "4.0.39", + "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.39.tgz", + "integrity": "sha512-vjaS7Q0dVqFp85QhyPSZqDKnTTCemcSHNHFvDdalO1s0Ifz5KuE64jQD5xoUkfdWwF4WpqdJEl7LsWH8rzhKJA==", + "dev": true + }, + "@types/js-yaml": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.11.2.tgz", + "integrity": "sha512-JRDtMPEqXrzfuYAdqbxLot1GvAr/QvicIZAnOAigZaj8xVMhuSJTg/xsv9E1TvyL+wujYhRLx9ZsQ0oFOSmwyA==", + "dev": true + }, + "@types/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", + "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==", + "dev": true + }, + "@types/marked": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.4.0.tgz", + "integrity": "sha512-xkURX55US18wHme+O2UlqJf3Fo7FqT5VAL+OJ/zK+jP2NX57naryDHoiqt/pMIwZjDc62sRvXUWuQQxQiBdheQ==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "8.10.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.26.tgz", + "integrity": "sha512-opk6bLLErLSwyVVJeSH5Ek7ZWOBSsN0JrvXTNVGLXLAXKB9xlTYajrplR44xVyMrmbut94H6uJ9jqzM/12jxkA==", + "dev": true + }, + "@types/promise-queue": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/promise-queue/-/promise-queue-2.2.0.tgz", + "integrity": "sha512-9QLtid6GxEWqpF+QImxBRG6bSVOHtpAm2kXuIyEvZBbSOupLvqhhJv8uaHbS8kUL8FDjzH3RWcSyC/52WOVtGw==", + "dev": true + }, + "@types/rimraf": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-2.0.2.tgz", + "integrity": "sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ==", + "dev": true, + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "@types/xml2js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.3.tgz", + "integrity": "sha512-Pv2HGRE4gWLs31In7nsyXEH4uVVsd0HNV9i2dyASvtDIlOtSTr1eczPLDpdEuyv5LWH5LT20GIXwPjkshKWI1g==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/node": "*" + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=" + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "~2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "optional": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "optional": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "optional": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "optional": true + } + } + }, + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "optional": true + }, + "deep-assign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", + "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=", + "requires": { + "is-obj": "^1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, + "duplexify": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "event-stream": { + "version": "3.3.4", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "^2.1.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "requires": { + "kind-of": "^1.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "^1.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + } + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "requires": { + "extend": "^3.0.0", + "glob": "^5.0.3", + "glob-parent": "^3.0.0", + "micromatch": "^2.3.7", + "ordered-read-streams": "^0.3.0", + "through2": "^0.6.0", + "to-absolute-glob": "^0.1.1", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "gulp-chmod": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz", + "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=", + "requires": { + "deep-assign": "^1.0.0", + "stat-mode": "^0.2.0", + "through2": "^2.0.0" + } + }, + "gulp-filter": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.1.0.tgz", + "integrity": "sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM=", + "requires": { + "multimatch": "^2.0.0", + "plugin-error": "^0.1.2", + "streamfilter": "^1.0.5" + } + }, + "gulp-gunzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz", + "integrity": "sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak=", + "requires": { + "through2": "~0.6.5", + "vinyl": "~0.4.6" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "gulp-remote-src-vscode": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/gulp-remote-src-vscode/-/gulp-remote-src-vscode-0.5.0.tgz", + "integrity": "sha512-/9vtSk9eI9DEWCqzGieglPqmx0WUQ9pwPHyHFpKmfxqdgqGJC2l0vFMdYs54hLdDsMDEZFLDL2J4ikjc4hQ5HQ==", + "requires": { + "event-stream": "^3.3.4", + "node.extend": "^1.1.2", + "request": "^2.79.0", + "through2": "^2.0.3", + "vinyl": "^2.0.1" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "gulp-sourcemaps": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "requires": { + "convert-source-map": "^1.1.1", + "graceful-fs": "^4.1.2", + "strip-bom": "^2.0.0", + "through2": "^2.0.0", + "vinyl": "^1.0.0" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-symdest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-symdest/-/gulp-symdest-1.1.0.tgz", + "integrity": "sha1-wWUyBzLRks5W/ZQnH/oSMjS/KuA=", + "requires": { + "event-stream": "^3.3.1", + "mkdirp": "^0.5.1", + "queue": "^3.1.0", + "vinyl-fs": "^2.4.3" + } + }, + "gulp-untar": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.7.tgz", + "integrity": "sha512-0QfbCH2a1k2qkTLWPqTX+QO4qNsHn3kC546YhAP3/n0h+nvtyGITDuDrYBMDZeW4WnFijmkOvBWa5HshTic1tw==", + "requires": { + "event-stream": "~3.3.4", + "streamifier": "~0.1.1", + "tar": "^2.2.1", + "through2": "~2.0.3", + "vinyl": "^1.2.0" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-vinyl-zip": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz", + "integrity": "sha1-JOQGhdwFtxSZlSRQmeBZAmO+ja0=", + "requires": { + "event-stream": "^3.3.1", + "queue": "^4.2.1", + "through2": "^2.0.3", + "vinyl": "^2.0.2", + "vinyl-fs": "^2.0.0", + "yauzl": "^2.2.1", + "yazl": "^2.2.1" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + }, + "queue": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", + "integrity": "sha512-fSMRXbwhMwipcDZ08enW2vl+YDmAmhcNcr43sCJL8DIg+CFOsoRLG23ctxA+fwNk1w55SePSiS7oqQQSgQoVJQ==", + "requires": { + "inherits": "~2.0.0" + } + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "requires": { + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "is": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", + "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=" + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "optional": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "requires": { + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "mime-db": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" + }, + "mime-types": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", + "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "requires": { + "mime-db": "~1.35.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "requires": { + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" + } + }, + "node.extend": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", + "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", + "requires": { + "is": "^3.1.0" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "requires": { + "is-stream": "^1.0.1", + "readable-stream": "^2.0.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "~2.3" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + } + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "promise-queue": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/promise-queue/-/promise-queue-2.2.5.tgz", + "integrity": "sha1-L29ffA9tCBCelnZZx5uIqe1ek7Q=" + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", + "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==" + }, + "queue": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/queue/-/queue-3.1.0.tgz", + "integrity": "sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU=", + "requires": { + "inherits": "~2.0.0" + } + }, + "randomatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "optional": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.8.tgz", + "integrity": "sha512-WqAEWPdb78u25RfKzOF0swBpY0dKrNdjc4GvLwm7ScX/o9bj8Eh/YL8mcMhBHYDGl87UkkSXDOFnW4G7GhWhGg==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "requires": { + "through": "2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=" + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "requires": { + "duplexer": "~0.1.1" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "streamfilter": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.7.tgz", + "integrity": "sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ==", + "requires": { + "readable-stream": "^2.0.2" + } + }, + "streamifier": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz", + "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "requires": { + "first-chunk-stream": "^1.0.0", + "strip-bom": "^2.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "to-absolute-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "requires": { + "extend-shallow": "^2.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "typescript": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.3.tgz", + "integrity": "sha512-K7g15Bb6Ra4lKf7Iq2l/I5/En+hLIHmxWZGq3D4DIRNFxMNV6j2SHSvDOqs2tGd4UvD/fJvrwopzQXjLrT7Itw==", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "optional": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "requires": { + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" + } + }, + "url-parse": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", + "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "requires": { + "duplexify": "^3.2.0", + "glob-stream": "^5.3.2", + "graceful-fs": "^4.0.0", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "^0.3.0", + "lazystream": "^1.0.0", + "lodash.isequal": "^4.0.0", + "merge-stream": "^1.0.0", + "mkdirp": "^0.5.0", + "object-assign": "^4.0.0", + "readable-stream": "^2.0.4", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^1.0.0", + "through2": "^2.0.0", + "through2-filter": "^2.0.0", + "vali-date": "^1.0.0", + "vinyl": "^1.0.0" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "vinyl-source-stream": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz", + "integrity": "sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A=", + "requires": { + "through2": "^2.0.3", + "vinyl": "^0.4.3" + } + }, + "vscode": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.21.tgz", + "integrity": "sha512-tJl9eL15ZMm6vzCYYeQ26sSYRuXGMGPsaeIAmG2rOOYRn01jdaDg6I4b9G5Ed6FISdmn6egpKThk4o4om8Ax/A==", + "requires": { + "glob": "^7.1.2", + "gulp-chmod": "^2.0.0", + "gulp-filter": "^5.0.1", + "gulp-gunzip": "1.0.0", + "gulp-remote-src-vscode": "^0.5.0", + "gulp-symdest": "^1.1.0", + "gulp-untar": "^0.0.7", + "gulp-vinyl-zip": "^2.1.0", + "mocha": "^4.0.1", + "request": "^2.83.0", + "semver": "^5.4.1", + "source-map-support": "^0.5.0", + "url-parse": "^1.4.3", + "vinyl-source-stream": "^1.1.0" + }, + "dependencies": { + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "mocha": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + } + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, + "vscode-jsonrpc": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.6.2.tgz", + "integrity": "sha512-T24Jb5V48e4VgYliUXMnZ379ItbrXgOimweKaJshD84z+8q7ZOZjJan0MeDe+Ugb+uqERDVV8SBmemaGMSMugA==" + }, + "vscode-languageclient": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.0.0.tgz", + "integrity": "sha512-zotks0PzR/ByGIYyM8SBobXHXsrdb6JqZ7m+qBpZLZP6HIUpF2oyYjQomVc4nFxjNdn0b2PfwkJZJKqRnV/UoQ==", + "requires": { + "semver": "^5.5.0", + "vscode-languageserver-protocol": "^3.10.3" + } + }, + "vscode-languageserver": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-5.0.1.tgz", + "integrity": "sha512-162KNZtWXBABfBWvDFZ0OwwzQkJ/sCed40MJiNZ763RZlAGCP6WW7vFtTkDgPB4MhsNEBnYIWQdwDkyx5XNDEg==", + "requires": { + "vscode-languageserver-protocol": "^3.10.3", + "vscode-uri": "^1.0.5" + } + }, + "vscode-languageserver-protocol": { + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.10.3.tgz", + "integrity": "sha512-R9hKsmXmpIXBLpy6I0eztfAcWU0KHr1lADJiJq+VCmdiHGVUJugMIvU6qVCzLP9wRtZ02AF98j09NAKq10hWeQ==", + "requires": { + "vscode-jsonrpc": "^3.6.2", + "vscode-languageserver-types": "^3.10.1" + } + }, + "vscode-languageserver-types": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.10.1.tgz", + "integrity": "sha512-HeQ1BPYJDly4HfKs0h2TUAZyHfzTAhgQsCwsa1tW9PhuvGGsd2r3Q53FFVugwP7/2bUv3GWPoTgAuIAkIdBc4w==" + }, + "vscode-uri": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.6.tgz", + "integrity": "sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww==" + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "optional": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yazl": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.4.3.tgz", + "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=", + "requires": { + "buffer-crc32": "~0.2.3" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9cb88a8 --- /dev/null +++ b/package.json @@ -0,0 +1,274 @@ +{ + "name": "divinity-vscode", + "displayName": "Divinity Engine Script Support", + "description": "VS Code language support for Divinity Engine story scripts", + "author": "Sebastian Lenz", + "license": "MIT", + "version": "1.0.0", + "publisher": "sebastian-lenz", + "categories": [ + "Programming Languages" + ], + "icon": "resources/extension.png", + "keywords": [ + "Larian", + "Divinity Engine", + "Osiris", + "Story Script" + ], + "engines": { + "vscode": "^1.25.0" + }, + "activationEvents": [ + "workspaceContains:**/Story/story.div", + "workspaceContains:**/RawFiles/story_header.div", + "onLanguage:divinity-story-goal", + "onLanguage:divinity-story-div", + "onWebviewPanel:divinity.apiExplorer" + ], + "homepage": "https://github.com/sebastian-lenz/divinity-vscode", + "repository": { + "type": "git", + "url": "https://github.com/sebastian-lenz/divinity-vscode.git" + }, + "bugs": { + "url": "https://github.com/sebastian-lenz/divinity-vscode/issues" + }, + "main": "./lib/client", + "contributes": { + "configuration": { + "type": "object", + "title": "Divinity Engine configuration", + "properties": { + "divinityScript.autoStart": { + "scope": "window", + "type": "boolean", + "default": false, + "description": "When enabled, the language support will start automatically. Otherwise it will start when opening an Osiris script file." + } + } + }, + "commands": [ + { + "command": "divinity.showApiExplorer", + "title": "Show API explorer", + "category": "Divinity" + }, + { + "command": "divinity.storyOutline.openGoal", + "title": "Open Goal", + "category": "Divinity" + }, + { + "command": "divinity.storyOutline.addGoal", + "title": "Add new Goal", + "category": "Divinity" + }, + { + "command": "divinity.storyOutline.renameGoal", + "title": "Rename Goal", + "category": "Divinity" + }, + { + "command": "divinity.storyOutline.deleteGoal", + "title": "Delete Goal", + "category": "Divinity" + }, + { + "command": "divinity.storyOutline.moveGoal", + "title": "Move Goal", + "category": "Divinity" + } + ], + "languages": [ + { + "id": "divinity-story-goal", + "aliases": [ + "Divinity story goal", + "divinity-story-goal" + ], + "extensions": [ + ".divGoal" + ], + "filenamePatterns": [ + "**/Story/RawFiles/Goals/*.txt" + ], + "configuration": "./syntaxes/divinity-story-goal.language-configuration.json" + }, + { + "id": "divinity-story-div", + "aliases": [ + "Divinity story div", + "divinity-story-div" + ], + "extensions": [ + ".div" + ], + "configuration": "./syntaxes/divinity-story-div.language-configuration.json" + } + ], + "menus": { + "view/item/context": [ + { + "command": "divinity.storyOutline.openGoal", + "when": "view == divinity.storyOutline", + "group": "navigation" + }, + { + "command": "divinity.storyOutline.addGoal", + "when": "view == divinity.storyOutline", + "group": "navigation" + }, + { + "command": "divinity.storyOutline.renameGoal", + "when": "view == divinity.storyOutline && viewItem != sharedGoal", + "group": "1_modification" + }, + { + "command": "divinity.storyOutline.deleteGoal", + "when": "view == divinity.storyOutline && viewItem != sharedGoal", + "group": "1_modification" + }, + { + "command": "divinity.storyOutline.moveGoal", + "when": "view == divinity.storyOutline && viewItem != sharedGoal", + "group": "1_modification" + } + ] + }, + "grammars": [ + { + "language": "divinity-story-div", + "scopeName": "text.divinity.storydiv", + "path": "./syntaxes/divinity-story-div.tmLanguage.json" + }, + { + "language": "divinity-story-goal", + "scopeName": "text.divinity.storygoal", + "path": "./syntaxes/divinity-story-goal.tmLanguage.json" + } + ], + "problemMatchers": [ + { + "name": "divinity.problemMatcher", + "owner": "divinity-vscode", + "fileLocation": "absolute", + "pattern": { + "regexp": "^(WARN|ERR!) ((?:[^:]+:\\\\)?[^:]*):(\\d+):(\\d+): \\[(\\d+)\\] (.*)$", + "severity": 1, + "file": 2, + "line": 3, + "column": 4, + "code": 5, + "message": 6 + } + } + ], + "snippets": [ + { + "language": "divinity-story-goal", + "path": "./syntaxes/divinity-story-goal.snippets.json" + } + ], + "taskDefinitions": [ + { + "type": "divinity.task.compiler", + "required": [ + "gameDataPath", + "output", + "mod" + ], + "properties": { + "gameDataPath": { + "type": "string", + "description": "Location of the game Data folder" + }, + "output": { + "type": "string", + "description": "Compiled story output path" + }, + "mod": { + "type": "array", + "description": "Check and compile all goals from the specified mod" + }, + "noWarn": { + "type": "array", + "description": "Suppress warnings with diagnostic code ", + "enum": [ + "alias-mismatch", + "db-naming", + "guid-prefix", + "rule-naming", + "string-lt", + "unused-db" + ] + }, + "checkOnly": { + "type": "boolean", + "description": "Only check scripts for errors, don't generate compiled story file" + }, + "checkNames": { + "type": "boolean", + "description": "Verify game object names (slow!)" + }, + "reload": { + "type": "string", + "description": "Turns on editor level reloading.", + "enum": [ + "reloadStory", + "reloadLevelAndStory" + ] + } + } + }, + { + "type": "divinity.task.reload" + } + ], + "views": { + "explorer": [ + { + "id": "divinity.storyOutline", + "name": "Story Outline", + "when": "divinity.storyOutline.enabled" + } + ] + } + }, + "scripts": { + "compile": "rimraf ./lib/** && tsc -p ./tsconfig.json", + "compile:publish": "rimraf ./lib/** && tsc -p ./tsconfig.publish.json", + "package": "vsce package", + "postinstall": "node ./node_modules/vscode/bin/install", + "test": "mocha", + "tidyup": "rimraf ./node_modules/handlebars/.idea && rimraf ./node_modules/handlebars/dist/amd && rimraf ./node_modules/handlebars/lib/handlebars && rimraf ./node_modules/handlebars/package-lock.json", + "update-vscode": "node ./node_modules/vscode/bin/install", + "vscode:prepublish": "npm run update-vscode && npm run tidyup && npm run compile:publish", + "watch": "tsc -w -p ./tsconfig.json" + }, + "devDependencies": { + "@types/fast-levenshtein": "0.0.1", + "@types/handlebars": "^4.0.39", + "@types/js-yaml": "^3.11.2", + "@types/long": "^4.0.0", + "@types/marked": "^0.4.0", + "@types/node": "^8.10.26", + "@types/promise-queue": "^2.2.0", + "@types/rimraf": "^2.0.2", + "@types/xml2js": "^0.4.3", + "js-yaml": "^3.12.0", + "mocha": "^5.2.0", + "rimraf": "^2.6.2", + "typescript": "2.8.3" + }, + "dependencies": { + "fast-levenshtein": "^2.0.6", + "handlebars": "^4.0.11", + "long": "^4.0.0", + "promise-queue": "^2.2.5", + "vscode": "^1.1.21", + "vscode-languageclient": "^5.0.0", + "vscode-languageserver": "^5.0.0", + "xml2js": "^0.4.19" + } +} diff --git a/resources/assets/api.css b/resources/assets/api.css new file mode 100644 index 0000000..9570042 --- /dev/null +++ b/resources/assets/api.css @@ -0,0 +1,204 @@ +body { + padding-top: 20px; + padding-bottom: 20px; +} + +h1 { + font-weight: normal; +} + +h2, +h3, +h4, +h5, +h6 { + margin: 1em 0 0.5em 0; + + padding-bottom: 4px; + border-bottom: 1px solid var(--vscode-panel-border); + + font-size: 1.5em; + font-weight: normal; +} + +a { + color: var(--color); +} + +p, +li { + line-height: 1.5em; +} + +ul { + padding-left: 20px; +} + +.divinitySection { + padding-bottom: 4px; + border-bottom: 1px solid var(--vscode-panel-border); +} + +.divinityIcon { + display: inline-block; + height: 14px; + width: 16px; + margin-top: -1px; + + background-image: url("../icons/category-light.svg"); + background-repeat: no-repeat; + + vertical-align: middle; +} + +.divinityIcon.large { + height: 21px; + width: 24px; + margin-top: -6px; +} + +.vscode-dark .divinityIcon { + background-image: url("../icons/category-dark.svg"); +} + +.divinityIcon.call { + background-image: url("../icons/call-light.svg"); +} + +.vscode-dark .divinityIcon.call { + background-image: url("../icons/call-dark.svg"); +} + +.divinityIcon.event { + background-image: url("../icons/event-light.svg"); +} + +.vscode-dark .divinityIcon.event { + background-image: url("../icons/event-dark.svg"); +} + +.divinityIcon.query { + background-image: url("../icons/query-light.svg"); +} + +.vscode-dark .divinityIcon.query { + background-image: url("../icons/query-dark.svg"); +} + +.divinityLink { + cursor: pointer; +} + +.divinityLink:hover { + text-decoration: underline; +} + +.divinityBreadcrumb { + display: flex; + flex-flow: row wrap; +} + +.divinityBreadcrumb--item:after { + content: "⮞"; + margin: -1px 8px 0; + + font-size: 75%; +} + +.divinityBreadcrumb + h1 { + margin-top: 2px; +} + +@media (min-width: 500px) { + .divinityCompactList { + columns: 2; + } +} + +@media (min-width: 750px) { + .divinityCompactList { + columns: 3; + } +} + +.divinityCompactList--item { + overflow: hidden; + box-sizing: border-box; + + padding: 3px 20px 3px 0; + white-space: nowrap; + text-overflow: ellipsis; + break-inside: avoid-column; +} + +pre, +.divinitySignatutes { + padding: 10px; + overflow: auto; + + border-radius: 3px; + background: var(--vscode-editorSuggestWidget-background); + + font-family: Consolas, "Courier New", monospace; +} + +.divinitySignatutes--item:not(:first-child) { + margin-top: 0.5em; +} + +.mtk12 { + color: var(--vscode-gitDecoration-conflictingResourceForeground); +} + +.mtk11 { + color: var(--vscode-list-warningForeground); +} + +.mtk13 { + color: var(--vscode-list-highlightForeground); +} + +.divinityProgress { + position: fixed; + top: 0; + right: 0; + left: 0; + height: 2px; + overflow: hidden; +} + +.divinityProgress--line { + position: absolute; + height: 100%; + + background: var(--vscode-activityBarBadge-background); +} + +.divinityProgress--line.inc { + animation: increase 2s infinite; +} + +.divinityProgress--line.dec { + animation: decrease 2s 0.5s infinite; +} + +@keyframes increase { + from { + left: -5%; + width: 5%; + } + to { + left: 130%; + width: 100%; + } +} +@keyframes decrease { + from { + left: -80%; + width: 80%; + } + to { + left: 110%; + width: 10%; + } +} diff --git a/resources/assets/api.js b/resources/assets/api.js new file mode 100644 index 0000000..8c9c568 --- /dev/null +++ b/resources/assets/api.js @@ -0,0 +1,42 @@ +(function() { + const vscode = acquireVsCodeApi(); + const location = document.body.getAttribute("data-location"); + let hasProgress = false; + + // Send state to vscode + vscode.setState({ location: location }); + + // Execute a command + function executeCommand(command, args) { + vscode.postMessage({ + command: command, + args: args + }); + + if (!hasProgress) { + const el = document.createElement("div"); + el.className = "divinityProgress"; + el.innerHTML = [ + '
', + '
' + ].join(""); + + document.body.appendChild(el); + hasProgress = true; + } + } + + document.addEventListener("click", function(event) { + var target = event.target; + while (target && target.getAttribute) { + var goto = target.getAttribute("data-goto"); + if (goto) { + executeCommand("goto", [goto]); + event.preventDefault(); + break; + } + + target = target.parentNode; + } + }); +})(); diff --git a/resources/extension.png b/resources/extension.png new file mode 100644 index 0000000000000000000000000000000000000000..c7d5dcb776bfaa7ba14df9c7b5eb57fe4042de41 GIT binary patch literal 2880 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 + + +]> + + + + + + + diff --git a/resources/features/api-explorer.gif b/resources/features/api-explorer.gif new file mode 100644 index 0000000000000000000000000000000000000000..181ccfd922e61446759483d47c81948fba1fded4 GIT binary patch literal 60840 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 Zt|X{=FEA!GCO0D^I5;>S9zq=* zULGD|9v*idHAy5ML@XX(H8@`wQ5Y3y6+KQJI#eDsS~NO+9yw?^9!y&uTzVd2crsi> zKTuyaQfW>e9$6h7TplttKs9y4|^FkCfBVIE?79(R8=NkLH{P+T}@ zRt{%l9&=z5M@L6oOj}e`RbO9VNM&AJU}|(qLTYMie_(2Qd3hclf*u~G9W#<1IG`sU zgEk(gH8_JTIH4U!p&n1L9#FC#V4og+k3Ud@EKsvKU8N;vvp;5_K5e!&dZ8X;#3W_O zEPBZ+dDS&!$4?%EPadawGm%4GrCD0GNoa;idV^JYf=OneMtitcdZ2n*wqbmNe}8~y zW2bs*wt8y7I+c8Th#pCnNlmkH9fpb?gRvx)qCcFoE3L2{huJlZ$~24BKb*=wo7Fa> z@H)w`MVXsaiJeJ|p-G&xR*Rrjo3n3&hGCPvVWOOAuBS+w%1E2lSDVRIo7GRa{bz{8 zaIff2$&X9PtY^*Id)(S)%>8@Y{e>PLmopxZG&H;w6}mh;h8{wO9%6uA9)W8Sk97~9 zU>>MR9;9L(jZ{gSX>qw)R;5RGq+w8{V`9QSKFDb_!*W~2YIn?ZV(Lalm0F>dTDFyW zw!2!9yLpkfa;lYiz{PoylYktniwd@f9hri5r z!-HGPmR!q`bZiGZ1#mxFDls;{rGx3{;9qr`x((SownnZC@WhQPaqz?06Ki^!;@&5Nhb zo3+k~wa%Nj+>5u|ou$pGwa%!w+^USt#Ejh9o6N(X#?+kL+Kk-$o7?-b)YQd>p~Z%_ z)UtxbhQQOtp4{Av+S{DW*r(dtsngT2$H&LX)XB-z)YR0;)z#JJ=H~qT{0RO469^ng zu%N+%2oow?$grWqhY%x5oJg^v#fum-YTU@NfFh*r_Y~2g9;r=w5ZXeNRx7W$+W4{r%xjsXw$wV%eJlCw{YXiolCc_-Me@xs@==Cui3nS0}CEZxUk{Fh!ZQm=(n-s z$0rv{o=my2<;$2eYgP=ovuD4XLyI0wy0q!js84@h&01>e*RW&Do=v;9?V7D~>u!0w zx9{J;g9{%Xc(?K6B#A3u&b+zv=g>2XbhG&(CB4DBaU?4c_{ht&p+9X zl+QoYq-5rqXX?jPijNt?p?@%aspp=U*@z>DQi9chGF=YDqcI8as2~qI7Fh$6P71`M zl*$ars6aO~Ic1;;7=!4PL-HwV0%4j&=1D&I!{$ggsM_X9{%gJ(fHEr1S!+nspm|cO za;~%afHTri>3y=2%b-oO(5Ap#x>gVxu}f3+X^D5~S#+k`l@-L7ob9ZLwdL zx?iv*ndy%|H;6RNy0Vg#E4ok7>8`FO@fzcwqzX&!zW~Q|Y_gm(Yf+HOL^^1~;#L=_ zOwSr5q^93mOYyeget0RU4Sb93r`ZNPqq!u~JCd2z_@j(S{p91%G|K$5GDx{9<4>>q z!FlVOXQpW{Nd3V1Pc{F@8FSEZ;%rh4f5Pam$WTY!)xZR4Sa7ot@xb3S0+qp^j&>?L z6OT!Lx@0wGZ!Ba3<3>!-rBq5uWi?K2>7&_FUr4h4nkI{6<}~@-YO^sf>kD*0G0$95 z(Al-hZUEKH+|T1b(~R%D`Wmhh(>OXES>B+Bo)pysS-mXQ4{0s7>N!>EkpeuF(QyLs%P)`uW!OKqw{HU(^2P%hSEmBCEwxdr zAmK`Yi_kY9;)TR`=~`9G0suYcQBY;vtDel%#4hKB#DW1>6P&bnE6W8dW*ZEE_}p}( zzKw)|FpQy0)TcnP1rT*xiQU;0RKS8!>}>wkf*Fy5xF}8~kV(*zVSF425(tvyZ?o#4 ziamEqnG_w_^By17F)6qRj_q$*c=5IEYfVXTbhR}|^QlQ}Y1wE`ipZq=$#g71;KYL$wt z_a+i^(diD<@* z*{hHiE6X7>PK~LiJQ-M>163m*)&4k8$mYpUqD<#H0KHDT%<{_+)zm=ssvxPV zR=3L4%3$@XT@9;P$C{U~LY1s&O{-ePV%Ddw^{sG?Yf{>ZRJq!9JPpXJUiZq^zWVjA zfDNo*2TRz(8uqY=O{`)U%h<*`_OXzStYjxkS-sNrvY5@RW;e^(&U*HP*SXBiu6DP}-R^p~t=QG=b;nEI@|yR&=(VhDn^6oBeAg)+ zu*WQ*(uRAqH#ZN+hA*BXhj#ea8Sf2nQ;tvw1PE9+K^O!EDoWr&6haRKkV<$%(%=V2 zH~{I*u!c9x;SNjIF)TusND|-!Pl>oO4j{)pRy^MTu-Cn$Aa`N~+fgPPwQXG6?+ zBwb!}NbG#)Jgdadjs^*%z3iDV|5+q+2G@S#GWj+VM&tg8bNX$HH zPK(3}cdoLcK?3Pji#Z0HCIqN4?BQPf`q#kDFlc;Wpc4mx#3l-WfpWVS9?uvg%n&kr zQIH!M(>Ta4nf8w5E0RDIgW4Z01U?|45-5WN2#-id0YYN#6J>eURWPuU+ic)kd%6!7 zwt}g5Gi4|YLf))-cSx+@hbx#m%NaN|9q^r!B&b>>N!Yhate|KrNIcMrM!3Qm9snT_ z0t|MTbpZYxK5CXE0ne{~c%?Zmk}Qj1;Uy1=#}kecD=_@zG^aI{A5L(C1ANMnX0st! z9snv3oz0OxIi*2j^9Uya5HMKv(X9~d-#+T*h%Qg z?F~*$;(_iZ#os20wqs0=XVVwkE}6SyK5&l~gT&k5HmDNz;dd-MBFX{i?+n;|c!Ne9 z;3^RUAFl9aA$Y+GK}R&lr+oC*2w@NvphM;>eP}AI+2W9g_{B#;a*{mWDOn!9r&SJ; z*Z-gn2oQKkTJMr9cR}B09y6I5;bqMI7%C$V|) zU;f?s=+oKv!0-6KLlOp-LqGUmfb6f%lULPwr~&TpPXq3m4<6*zPSxNm{rQvs{qx5M z?Z+RC(ji7Ne-V;@dF3bn7l7~QS77&m5Ey|H_$Xvofnw(vBxY+WAs37AOQj9U}G(oV!%*icozVHU}JGNf-8n?eD`B4W`jHUcg4^GD|ipU01|Bw zgCWrd^k4}=ID{&wgF?uIeHRkm281g%gdmZF_7!+O#)92egFZ-wPZ$6-b`N%Ug*teG z0nmg%CS+o0V|Isxm7ro|C=!K$WGm5b0WbyZpazVGc<1&AO~!{yrfwl|2kS5b{vgp` zP6iTpkPbuui0!ZpPJweRA$dly2LxaR89;Hm$8`9%eO$(8md0@ur*x*~ad)O_uvTR` zXLLg#XiHagpU80t7iK&sW;s`MV%B~4HfpG65|qegyLe%|2XTJziYTXZVm5l6xDucU zafXnK%~*^qA$$}Ne%NOctGI7U7mHvvj9kWx$tM!1#)>HMdR(Szu}6*8_jBP#5;OOV z0dRgK5qqoV2iKTq=okP|z;m7VR|!*CXp~0q*CECbf9zp^IdXsaq<1zCRz z$bUt`Aq7~G^|yWt>3|dXksvvN7C4f>hJk69RX#9KYqxeEcos#-h9lAb3|RXzcozsmS$9zRgi3j8>JSesfrpCMhb_kl zh!_BO&<=~2m!#$hlIWL*IG9oPm+ioZg834D#)~5%c@!`QMF0nxczWt+2MPC#l$Zp0 zrhBl4Z{z53c}8#%Hf4&&e7YEoBj;w==X@ZMW}-<4YlfQ3M+h|MnXwsim57^&wtDSY zd!NahBiCrVX9#YFj`3D|tQnbvAbTaDn!gEo(`cNLhnv}$Wla76isz4C@I4vZ1O0n@*?E)A~xD2?=qt`kSfzaPW@mELemdjN0Lg~ zVJ69TDXDBG!jgQ!l`&a^Zi#{-p_DZFcW79p)HanRVU|SLr7retU>X2QIfg6tY+N~) zT^V>{NTwwCcX$_qE*KIYAeCL}rZVV-Y{`ahDyCf7l>T$6lq%?VNJwt=)nY1Wg+Jg9 zBB*4Imxt`&hj>U5ddP?97G-&fZhV-ChxwO_N2#CM6k!IOyEkW45C&c_k84Jn=@?<0 z*__-LVdp1&PRD1jSBw-Fit@&MuxXE^Mx67AZ@emU0|%MADQhHApU#P_$y#zAr)cPy zjV)&fK{sW?SC6m=tsO@Q$l8n|F|89fn|bDO-wAWU>73A6t|fPJkv5L8dYkLXW*KJ( zhsJ#L37q;SZ?7kh^hl1hS*zJeoIl_P{upxy+A;|mSYh*_s&kMJx}qMMq4?C07HY8= zI-vfc@?4{dQTFWfcQim3%MRV5H=zT{#aXQr2c@USSO=2>JLn^E;E{=Kbmzx zW3xi~C_`EUkaTr4n<_RNc1xPH>D8qD(soa(LdKRBR4Nj4ccpR3g<={KTXVf$laOQtCpgg-W4a|)JS2&ZIA5@O1CXz7*aV5Vq@g=^@P zFews)7pW$(WKFi1Pd2F`p@@OVh=+LyQKpB9>tBm!h<$k$X;!bsNB|lKeNC5*oavfW z29CFyug~d;vKnhcC#%DUtExM!nP+L>SdOjR5~jIo7nfxZXS+P^6IMonVWYuYiVX^(?eu4H>c|Te0^Pp&Md<8mgfg%drHhp&Y9W z6+5!*r#dbBuoWqh@z=6_)pbETv(i(uOfor0nxiQLq&WIA{-C2WJG4XlC^X9=H>!0? z`@-hMv>~ywp0jLx!KWi=rD#}RR;Z<5ixB#&G_p8)4%sYV+Exv}e1>X<)+Yyd>erv3r-;s=KLIYVN3t zznh$VW}D>7zQxa4&|L9j)QUfm&SSzYm9Qv^vLTn{sfW}}Rk<-5jEPo2@ zzzi&*A`8KKg?}hZklDPk7tD1TOtc$Z12sCNMmh~Ss?06i!OBcGKT0?{dQK}Wv`yl| zF#ONfCBxq1q;97cTk54;N^WH9!)5rkR;ad6T*N=j#3T{XW89``Ta{xhgGrpVPF#bF zTDM4yr6VDxVp+CYJpRQbvC$7umuBpTi|dDTOsXLvxpIJb=vJ5`G1F*K$C~Gh3n z;Ao&IaElDO90$Ad2)`u(yW@(=?7PUjC(4fYzVnug>N{oocGR5*eduV9Uk%E-=*gc< zb6Ty-%^R&Jfr_k~1J?Sl!&l3JR@Fxb%D~ipR-Lad!u@T$ABFmvAJEBHnHQ;Qq2zbt0 zm(D7@&h3n(AzZ>L{0~Pvv^6TEH7c}p)7m0zMMw+Kz#UxzeQd-A5;oiy^<{U_rnVfd zs5rQT9(|ND{>is-N0fn=mLx5dB%RPJ{gi^+#D5CJT5Qo_C=wxEV`1s15iQYWXwlxC zm65v90U&PMeYj^F(;|_Vlv}EbSgL-hxI2BAB~b|dV3)R>bB5j2Lgz7S!R%bbMBxD1qX)`)d2vy`5=}E3wI}m%gjl<1q)YbuG({{Eq%f z2F&)p3!4v+?NOCmyHuliJzNQpS5`(v2<#ykUSh;`+5{J-aX7C85I*98g5{kKqJUtR_&=35e z2`jORiJTJh=+w? zqey4}&c|XF0>C%ORfej?xs1mdYk(YUZdULvG0c`0ucfb@t5sgrD&H}+`qT%?<%Bhm@@Ls*{xxVGB>d-)2gsqo zGLauDvJU)^H!z|U+#fza+If!7dp^P+jOZB*vpo9eK611|i=???=!w4Di$0@9di7Wb z>1_X72ln=8p?BDQw`b}U^c`@7X%;O#ZULv6eL;`O3-^LQ_$Yz%;?-9HSy<}_v0@(d z3%Si4isuT+e@Gu8jL+swzu7`>vLzcf3P|-;zuIcg!e=70=}a_R0w*?$=s+tyMtgPS zRKh}I_Ws=Vw%=NWpZhLx&@_qNBdEm}uMT|w8HYfKQt|D~{uy?i7V_%Ty8i$CZ*TZ1 zar=%HlGcCyNlN|Nk6O^*{U_1Ib7+;q?x#-C()+dTm23P`fo|=f{!j6!{b0Dg+1J2{ zir$JA41fQ}!SMX){r+zp0MQ^p0D=V#7Hp7E;X;ND9X^B@QQ}036)i5Tkx}DDjvYOI z1Q}9f$BQLRo`=Wn^*5% zzJ2}v1+2I3V8VqBA4Z&5@nXh}9nZXLGw@`}l`UV!oY~}K&YeAf{stXd^k~wh2}Z7| zS@mkxtzEy~Y+Ckg+O=)p#+}Is=& z$DUpLcJAGEI+s~p{CM)^0eeTEUj2IZ?GuBKXd zK&NUj#s>fkO27wW8h{E7c}yuN0&U=lgdhty2|z-5KBUk;5l1AkMD^f1s6Z80WHCCX z8sxzT1r3UkhX@dVLwQ;jaIp?JQv(CAmM2Jc~_vDkfrm|eH zpf4eGipVy7`~(dS*)+5uG?272Qb{MJR4F`9>oZeLH@)vq83WxCOs3crb4_hN38EDe z7>$z)3@e2-R#|5a57g&4#Wh!58*&QJmyT+NVHXPucmeHG@`7>L82cwvYjMi*Rt8M4;jgeFF~A&~JUx7~(A z9@yK426i~!flXdFeZfOpe<#NwuNaKPVK-*)EZw?sg z2U*^CUb};i*Jo~3rd#Kku_Zj+cONF#=7^D|mu#a2FZu9tbBZ--c_p9PyR= zy@Br=K2Mr$f+1I#ZNfj_SM7Yf^?T^eP1n1;rL{B&*ip6lFnAuVKJytehl~?ysl#Tz zdFPoMTi$%krf6HCtq;6#kBupqUzIUtXxxs0#@Sw>7qa%jhI!y&8j=GZSLXB?Qn(sx zRrUel`E9p@{5b$BHUA7w_xc=-GH*96BWtIz=y{6%?gqZJ34_t@^Ef_z+ z#i(WCE8K(jC$IqSEPeb+&<809F_|gEdgQYf$|grLe~AxbKDeO<9mazbrmukJ*`2L? zx0EBiiXg+<1o1iqiZUJQh}#I#^Q1UMDmuwl;gMHArdK@-VoxFYI-m*thrlqRaE9{( zVMF!@vAJj zfal`i1|MlOdx>z2Bn%n&V#vXBSx|c4tJwql7{@tU5QUuV*5qRNL*03bcY<+-@IB#N_Uk|aNc5B zz~)u3^dYl?XCxRhEqFi8YL>l`_R=^vokzm$3WZ>X7M;cymfF#`4Ao<2f@TJTl z*<>TXl)*uajq9BE^qJ7c=|6~_Q=1eNAI)%BvqVa?W&%xTE0yvk?sc>V)aqzQyQGv? z#HmALIu${TB#$8lkEOwcX-s7*mtk^@2Q~1A`y_%)we{?CDr+VnzxYN97Or2?>s}1M znY3&g6?7PDXVE~(uBgsWsr0+qM7gETtriemi94J!_!ZBkwri2e{9{67$F9zm4xN;& zoFngrwt>Ett>m)XxaMa5Rl5#Obvr~`3QI=Uj4ExWhed2+XH`@56>}my-J?SI<*}gt z5Ou1=Syb(axxGcsjq*#{Qn{tSKmN6^`r;DBFsqCowpNfvlN;J*hs;EN({41I;J)(J zGu)~$V5gj9HF!8cdp#7Q)@;CJ(}zmkPI7?kycy#LsMLJr7J>cqR&PDmF(0PYu!;q5 zc*UzE#sW=?#yn;h_oyuzigBt3Tr1Az_f>bQuVXiuCnKp@O}t+4d`?BJX)o#C5V{tj z-~(3+FFV@@(rj*L{ogbr{8xK%fjORGN%?C7@I)ZC#CVRdZs{Ql}e)B^ZH86~rK#}i{Z*V)d? znK9>TY-4#gPIYsuEV-s})j3`^$U<(H+lmZYeSuMo#t7^n#h9V7 zc67WQGbqR*Y@Ut+*hJzsZ-*LeqVtaP{2+I*I9dvU4@lVL2ad4$#|`pysZZqr>JWL! zwQi@AtK92fKZ%umfF+mz3gSkgInD#X@nsO?5Js1H)opSIqu=E1J%4)A3xf2EgPb3l zxCzw>BJsKhK=5YyfjfM$b;ir7>tKg`~@44OUPIIB} z{$1}=N&Mmi?}(~%T1j^!x=UOQ)~|T<-N1C596kV~FNpaEKXHl+{pp4G z{MtL-`gLFd>K;GH)irK={)-6rx(C3ow`VH`vFGiJL|(a4}7}nOS;43xOQke z3M`01D8c^Y!Tk8Y00hE>8$c*YklzD71S|*zBsz+dySYog__IK`dxR%Ey@S~Pz|Bj# z4UEBpz&r(XJEOZg)iXitQ^DAq3H0;A2=qP(Ou7tQzvnB6*#o>Dq{H_3!63v#e;dNn zD8i-)z5v)j&da;#tBD6(KZ<+3&9gZ;tUxZTIqJhcp_79wWIvnJz(-)j^i#Z?n7)oH zz4S9f2n4#)^Sncly6pqH7eqmski$B3#S<|?Ov%GpjJ!Sc6+cA6Nc=!uya_`D#rFHc z(31%$q&ca(Lcu$P=et5H#6+10Lrx6Em{32q<3-YwIJLt;gYdwa7{8`_#c$+}JEX;N z^tK_qMO=KnLrA&_%ta>@#)CM#;v2@(^T1`C#4KopzEi&>Y(|+N!IA!}iG7^9XpBD` zG(|b6x@FYHRg4K81W0g%NIZ*0Y9YspL^-D5sF3=oj1;M*2tJ)FJwbGY9vd z$Cx0->;uG!gTtSbJ8ERcOpHU?8^f8HM$Oy4PprXDG`^sViEWGt{fo$=gr13HiHcDM z0YewnX&2ckvYyE=5qnAuTCV8IFYJLBAM30(v&gSp2-!fzb|}0h#6O>_L|{}zNDRi9 z7)y$)zK;6?M_@!3Jct_PJ`n6jX>^DEbGm5Eyi|0%jx&Qt_{8^n$Df=(f)L7sXhoxh z%;PY)n|cVSWJZxbCoV&@; z_Y9o)6wx1Y&bv|u6a^R+wMZ9L(k0D}Jd@EGm5BSA{vtorNumhOH%gC7yiUns?9wRq@we!q}Fr zB8}zPn5_(t<-?D13Xv6(TEf?ql2{&5l$9k{mlayDfmxX~+P|*rCPRu$dOBNQeaR+OPFmf=GbX%vwn~$Aj>_o1NE@)!B$$mf?YhNVwXv zrCVp&+NsD0u+`fJ$OxOrpMe70z#S-?g^L;xT-K^vw>VpaXb=Nzil%+olI7XA?GY~c zgt<-J%%zlR5rEG1+|LEw&=uX$1>ODx7>NWR-PBdx)n(n*b=}v6-Po1g*`?juwcXpr z-Q3mP-DO>x72B~>TZe6;ZZ%ngnA!kHl`&vh&1K$5nHIf;-sqLy>80N4wchK+-t5)h z?d9I?_1^CV-|!XR@g?8#HQ)2SUf*5Zq=4Mvh1lZtS4cSnS6JTWwO_}ZNc7d;{pH{O z_22&m-~blj0VZJU#mJE2o{w@k?s44UWn1C}p5OsjNI3#|sNeg=;M>dJ0_NZj_TUc& z;Sd(#5f0xBHen@wUJ_Q}6=vZUcHtL>;fXxq8UDr;j^P`|;T+cC9p>S%rQsi@O&jjv zAtvG?HsT`|Um#XuqZDE!cK+fghT4#sHg;nvPUARkyfp^kka*)e#^XFrUpeMulA~k)nNUzXtkM7HEhX5mHF5W~~G$ z(n7x88lWRghUHi;VM+P9@Oz8t^U0ui#-G5;CWMLw-Q=z7WbMTPe~@JA4P;T~fl^-P z?^Tyd*4tIiURPEIS+?eD#@++z!-J?+!cB^|Ovjx|P=m0((v!FHSH9?|#^!@v+?l~I zZ@#>Cw9DdCX$iE3eB3-lKnFsUz|mvLMwAMc<_VV$043OmSt!3y+{T*zW$eW1eADUb zebSzW-WnL_X1)O&5Z@cPmTCA}Y1Ui9cIZ>~T56W+$ChP}jgfD`>ZAC>2IOjzJcwjG z1T~m~bGQQj1hh+CY`(oTzAEg*kN(Nmqd-*bKEnh*y)((w22k)r!~yNN({sqUt~wmt z$65wT#B9V~W<&d9!u(SQzf>u8uE(fbAn_9C zYrXyJc0rf&b!^0*ph{Nk1c2zTb?oxCaXmIic)gO2=EsjSOMD*4WdMRkNQ4={JaxP{ zl$8ELDkN)ud_E*^$+p`ALm5EO! zLqGJJ#J)32npEkxd_G90L;}4;_{Q=?tYrXoX}9+B)w4u+1WdeC%TheWM_fMn15h@f zLpOIfI3Mi4X68}`-_rS7g>h(mDdie(YCZ?s84vVgH{$_p+~2Kiv};H7%Ws;P^7V7S z*h|Ko(`>XZ#y4biA6G`xcJg7oc2}3i`};(fPP|c%X=sl|nQZOsyT&bF$X7RrZvK?@ zccb<2P4SOmW$)GQ1`=e7BcpO=i&ieU<6+Fq4+~6XGeLL_LDsGwOa># zj6UroXL`Iod%SqCPC=PaNDdt50}pw4UvA|NNWi@3jqf{ybOwa{_Ml|QgV^wTXSaI? z-(~)Y#ujRX2l}AbTlH0MrT9pA7RhjLNuON9mORV0oQajZMAdfsn56odKe})?`DF}g zgIGFmOn01Icb%*`o>WWa%Vlw&i3R6yb?66l$9ZN$kpZxPx+maeh6umL_31sRoAGy{ z2YgsQV20=BqW@-AFH3u-iKf?fIN(0+{Yt2bGU|Vw?L5(ES2Fo!M;7q;Br{o%L%>nC6lG5Mm{ez~|hn9fe6*9m?0$2OP# zJEQ&!!2b1TfBxN10_}X6_)n&o|HOF4(^qGrKv1FpW}EK^@CS$h0tXT-Xz(DygbEij zZ0PVI#E23nQmkn4BF2mwH*)Og@#Dk>2@(#tU@`&9lqy%UZ0YhP%$PD~(yVFoCeEBX zck=A%^C!@tLWiaVY4j-4q)L}EZR+$X)TmOYQmtzBYE_XWOh&wwuwuuOEo=5H zTA5fsjtr1s4cxYG;|iR+MlRgDb@Sq->z40czjpiT{VN!-;lhIhD@MFHG2zIJB}1NU zxiaR*njLdq>-jV2(4t3^E*-M%!ICG_vTp7AHSE~3XZJK+am|7SYd8epfLk|j-??}9 z{!Lss@Z!UR8)v>;d2-~(n?s-eT)Ok<)Uj93Ze9EJ?c&3e2XFp6dhhCOvv2SIJ^c9b zwIWpAl{WtT`uFqi?;o{%3TXhB1_KSaMu7qym|y@48c5)S2u8@Dg9<`up@bMxcwvJa zR@h;NAZ{4qhb4M=B8e!DxZ;E@YUrYfFa|gyjWybMBaZ$G(U;l)J^uG2kUEkdz5!c_x}^s#)cjZMyj; zoN>xI=SO8Cv?iW;>bWOtbo%)xpn(cH=#h3F#3!POD!M36VYYEkF(~BNMm?M?giSmH z>F^6F68ypo2_FeS%P*UNv}vcGhANsH^Q=lJtg*_dGjuz4}@cQZ*Rk z18NEQU<|Uu0?1Jy_c;6PJ-`g~Xrv!OV9qR1QEF*Ih2R6pKpm7SfGwZ~;3+8s`A}*? z*xLT>P* z2|@Uho9?;4$QyvWrZVIM(M<_$OVbkx0uC|-4S|bIVlD+TMIn+G__rE-gfNz>6oQc0dX(N-xCpQ$mMcQ63L-4X{97)9yew5BD4P z*5IIk``H25PLR()zkNLN6lY9Oe+|@4{&xa3q|DO|`BW1!O4F2#cuF-?qj&<b% zfAcUn_d}gLJ>%_Pi4^3;PG0lowLdG&K-b!0&ONg<6YW6$=PaECAP~i90sjD4Hf$Z_ zTF=ti2l^+FYe~xi5yhx)Rjl1-vLh=tkAF4jfHgQ47~EZYU5`d8!vGfLZ{= zB}^Zf%Uz(-r4g+b070Cs4dD30zpN>#e$k>EwQwT9aA%9$6{HZc6iCFp7{+z7lS^Z) z3xCe&F_G{9dpgmh8%dUu>KTJ2_*}^}#&^ej1TG(Ttlr+Xr%#mVF>iY7X9E7o$B6<7 zelUxhTP})}LSm8}h+H84nz6w^Y!HMT3_vpw>B>k-@RAAfq$d{$%8xdqS}QFG&jJwB zh+Bt{(lmwoN1TklY-T0;)0sB^PM&S z;JdPQBNk4i#S^oN#S*GBt=|1^q1LLg{lrzCDZ2pE6lY+O&PM(i=nYSM^o^inT)X9HU!q4}n1h04nsC&7`M(;tCq1P)g z9P3)Rz2&2>2v#thU&CO82&(}QHspjsT;Y;lb|4uh2x$e9VGrvpwVBkdvr3FHzB(d1zVnUfu;VOk*UZ@4U5$gvDWv%gzJB8M5y>*m{807}ZN*2v1n=CtL`?8<)ASb%b z*;85&T9X`i{t}3Efe5f3qS)}G?op3WTrkA!7D&^z&aIrrGyrLew=V23`3a1z#heNAXy+j9#|D0KCta_*LVaeINCWb`N@OC z!X**|CW@`{7>?88HKR)tL(-2#~HP`h73h4J1^EK-&=Iy;X9ogK*mhYF%YRubx z^ILs}M%(u0|4QH)U^0$HwFLkV7y~N` zi!@fFKJH^XUE^7}l{`fcJko^drG)lyS;~c;^%H818Kg2uq(rs^Mc#x< z;sov41ot>wN20|%hU7pPrAa2GQqBrWmPIxm4oB7m?WNC7LR-pYnK2faP?{r5P-OMQ zT=gge8?{%;6jt=z-06K!KZ&1vu_elI4>~T?VC@Y=aSuKf{**w?h#nK%S8Rsuy6g#9cvT_mxbRp&T4tk1^&XOY9`#{1@o8QGWfO z%6(<`4G!p;59`ey_#n>ekso6%Bph|4J_Q^2!QNlVW*i|KN)%gdqF`VW;z!DlVfq}= zB_?tvXPYdhSd`ZpomYDCL`}}-UfxyB?Uj8+B%764VWAvn?v)5a6kX}j>FpCi%@Jk_ zSb27)d*Rb(M&^Mn)Rs}-_>kO|0hY}XRyFkH_55UD_T0}!qvQyZ3@WFA9%zy3M$WMv|V92B(~kDyhZ_opQyLy%kIL1m~IOi{2OLajHOJrG=uYt3qj4 zN@@9&C+PJPIpRubwpsW2>gxe&pSmVELL2^Ta_Xy+U&-8NM2=65x>rn|On*WYX6|UI zZY#Ia$*HbJ|23cUL}f*OPdb{Q^=)T38qRtG*!4K+0LJA*CF|;?rQVEBVa4U&7~`7d zjd=1+P784Y;UHct!`QL)lq-$O{j`$w??eQhRL_yNB{lbEMiYwIaW{Z=pIch z$cF5bRIIJ#U-t<_%bRnTdV3;@-3t%6}K*oJM#6=L$uOGS4$6#pn`*1nE@lNj&W=sL30QMrU_MVCI)|pZ`FW(9;^^R{6W()~T0{Y%c#^TEMwlD9x z%u;}F0L(7=)^8A+FZxcx#=I4|&c@Qt)x%b(o3`&QvW4dg1U|+u@IJ5j+OGq%ApWNB z+%zBbnX7*N#Q(koH^OHC{(~q1qe<(k;_s3!?LM#xr(Xo?FMl-V^9UrXChKe-YD<3T zOrRXfrRGdz@CW}0fCeb#BydvPt>5nL{5J3jAMr1W*ZE3ts+!l~45UnirIPl94)>-& zW$UNLL>2FFe;~0JhinQ@usqRI|H?$Rdazz%Uwc8+S=Q5GiC;OkS6!Xu^<*oB7OZTV zr3D`!pYA9Au7WDCB32w1q;`W zp7z8}>XAWLrK=iaFu&xpLUhWBW?ii_dMD4mCRl z^eGc0n`!>^rE2H+oh7j{^sE}rl-98bhF{FV@kZt=o5@x5?dMw>Y*`C3S||2Cs`XF! z-}?5~0H&aS9`;Wwwq;KvWBbGgo-7A`pvtZ+n{~9x6e?wV6+iJ&Uy14~ca|);-I2uXcnjgljiMY)8aw4+QZM(5SeWy{t>z4TPr{ zS8f}GzN`wWC`5h3OKuOGQV0=3__jl68oeOXy382y8TWC6m-S+A3UIMoM)q`@wnw;( z=l(J-0#_Cxu{KhqH&cN4L#(&isSQEAHwhFKRT0go9F6rl0fKQgEyHWS2&WV@`b0O=Mv^B-dR(KxKc=YLy-8Roj5Ik z%5U|SZrKZf7lZ`(f+wVl1dxKHfqC1l-GSG*QSdlM_;?KUTR~iTksG-Z=WmkdxmOIP zF%TVP<>N|t?!F`x7|;b zfc`DK3yZTleh+&Q(a_z6%C9ebL$r6D+j&APu?p+Cwg1FCVt426Vn+x%*yR~{Gm;~H z+l0jwB?-^XP;%pW_gkYRm*x4dD=xyQN4Jo^S3Xk04+#D zEu;YJ$T_H)%B`#UkGndHXL+b7ynr9oi!)#{#kiXrgu=I2;QBa2@Km%r_?K`iGG?iHkVdxjW6{Pfo43t2soB{kw6+ zxI*xr4wM3rlR0nWdeJD&rZnJ}Yl@3cy`1wNrop%{x!=YYM8`vwZ!tYY(D}%t{?(DA zyxSk(Z~_vsP!_jygtx!Eo-LhcnHHoZ8r0Q}hl?A}7n(U_I*ErJ2?c$&YiB@puXMZ8{7T1LPY-B zvs2r@z3s=uJc6#|FmIr-(1Hub480xewj?v0FdWD}49&66$Mx@1=gL16TSBM12c6$TNfj&OY0he6`;` z{<}m`Mh^V8Jf3|NKtM1DEI_kjC<4)g)TSP%01qJsNC+w7Lxv73LYxTx@x#4Y4+Rp0 z7&0S7gD3)AeAw}$%8DBUbQBrD4L?mKOZp%MQNpjCJvTwriSwZjUL+zKMJj+6DIGf> z0wpTI7SsStt?KZV;vv?j5Ig*eR8lL~id2K*EQ?d>!?0tCmVBVjS6sVy@#fXLmv3Lc ze*p&;JeY7{!-o+kRve%~0-_`)MNTl8a%IbxF=y7inR92)pFxKfJ(_fB)2C6VR=t{a zYuA()LrmbqhvSDejNQ0xtVZmW4Kq3*Cv4=vf(IuGSC|oIM3*I-vjl0p_{@sJiKhe} z(_;YT6eG&yesAUvcXja&4bb!G`d?|ord8V>qSB(j#PWPUwQBxEAMJJcWvlw|gX=0< z2CQhUvuu$sqXjd1OFygfQevNve9KV74LR)4!w*3WQN+L+dn~d^UQ1EM6QEtRMeae_=T8bhnW z)mLF zYq8C?25PzO*4uBv&DGg)$t}r^et!KFD`A@|7a|MObywbb>8;mZz@W`Y+He!d*57Lz zL+yrq2qxH=$#^K(;L2*KM&TPSn?~V-`K{REi!rY3-i>#4gU!PtrL)qK=A;m@lIg`J zUXEFA+2xmY&9|a`!ENAQe-o$yV$%ku*qD3{PMC+ue)c&ZWhheyXvz{snrNppj#}!e zXNB47tFg{n>#e!&x>T7XqWN2EZ@v~{9(FFRXUe9Trr&&qo@^SV2ZoyHd>~$%>b?2y z+eNPd4_xrU2`}96dBKKAY;ViPwlN;I<$3AJ{*#jZ@r|%A6lGSn;Reca)BpLpzXKgRvO~nBcA5-(uptLc*|T*UisyjZ{B%c zVGlrdYA$F;hnPYA8P5{PX*MUj6miZ{Pj*af*I=T*)qbTgY*L z7-6_U=U;cXgEu_%4Um8rgWmxWm_P+CFl+KV5x8o{g9g|vV3I2z)BFd#&@rqUNCRF0 zK^Q`AF_45MG~o$RC@Kf8s#~;cTmr0>8ogBpb8kD?4DSZ9pT$jtJ@g@sQW!)b4v~mO z%*zU=)vfy7>}+YX;ALvqKOG(|X}MGWTKSA&w;yhii>fi=7r_`tF&+?!--_S_@s~X) z`VWTr0N}t1W;x4ruV7B>;vMlAnhfElHW8T(j{2A(G|0mg5Q%^`-~pFI24#@)aAYCJ z7)eP^l89ww+zntAtDNyLkDc_S=wdS)9?-@%jNwfHW)sN8L;xD8c!yaI>55N0WRU?t z10)~tidRySm%a4m`z+Zlv`vth#k`yyF{3bL77T!&bmlW-w3yj!i%hx`N@f>O?O+H#lebm;y=A=g$2|wCF`KikW>@6O}&T!9N44m|Aj^oZ9$A z5L!V3g+_!6iHzt=VH#7!O>|}z&FD>W3eAnG@nf`_n?9Dct)1FkGr|L7_;fK`Ff1+6$=M*d;TOROT;U#;v92}lasInyqa67tn>hNYZ(gxbhI(_fxs(SZ`Fh>qZkM}LEiQ7w8(vm* zm%QaQFUP(sUiGebMdx+zd*Q3B^s<+}^+ip5@ta@$j%dEN%48<(8{jVPm%s%!Fk<>k zt0n%cbLUIg1y{7g1pEw{0?z7zF`Quy-zCAbI-}Z@`8$Ql5p;4)7>O$*G43f-iLt59t z%goOJh`AHH%3+pk7yyAM;m~neVn&-HpPLrxXZw1>t#*vhQ4?pl1exGCFz5}q*L*u1mP(U^*IBeAL3$hlzu`vxEU_UOhP zaf!dQ+%GD#w))lJ&J6|w=IBCS28dKPafepi zMQ5a7XmFVF8oqgG#&DZ5=yr0>Z1Bc>j&u!OjyHL0oZFGEIiJ&vb8l~&=RG%IY-HP2 zKl%WWsV&SD*dcVG&j2EaP<%VmQ2@IfT@4QbI??0ec*RG)B6q-isP4e|k{mthc=>@N zN?(#fe5@iKSi}Y@5{E_1e(C{;0~;c8d#GOt53kSt>}g+-H!Ok;yNAdUfM0wE$R7B> z&p-f%-+bIdU-}h6{_LL){o+I94cTXY@&n-d=06`IuCM)F5dZkfM+E3s{}8;i&QAWW zv&h!}f??m;jpCH+j>+)09r@PH3sMFlW;Vc8u{4Q#2 zq>pf8NBk)OM#=C71MwIy0OX(@-0u)L59m@4CrIxhM)31+!UQGn^jt6iJg?|LPxJ)i z^inV)j3px=01wWO_qGrEVDI*FZwQxw4U7;XmJs>QZ~4+-5yDgZwliA@z!qy-OutKp$yCOe+DoT8E(lUM;Y8~=C;KF|Nc#miss)a zh6gqWVkoczF=j(Hkg^_PHiGIfKoBC1j`3jdA!;!5tf3K#?hp_G9c=IgMNbYRq84vZ z@&-c(OTt%5Licj73y<&!cklL`&iIya`LNLSKtSq_&-ZXb3ylx@n34O2P#NDaBe;?K zm~joqPzt$E9hq(1${Cita9jz4h17Z9yPBW2s8AE zAn2$vA}j<$@G&1f(2p+Zzg#7A@NXnV^IK5SqdF>}yh;@l;}z{N>1MGd?cxxYK@ObZ z4weA~50eHtPaffs7H9AfLU05tFE^ud1VeBZfetB+F#zN-7;&&7a+4(o^B7UDBeg^AiNYV8lxvv3RNG9A@$FMqH* z%M<;kGahj;I;Wr+9^&*kPZ*Ul0G1OTtFH2lGa}|3S5fS?f)VFq6D5HRmBk@FFrQy4Qs zM|1QJ5!4at@D&-;KMPu6K{G;0A>u(xLOuC1FqyFVW^enJus*-<9Mv&C zz2h#c)E%P__-gM=+0ie5a7){BJ+<>br!YUclRYa!K_RnA>G3Cv4mJz3=;Xi!525sk zvNs>%IwMq)CR8@YhMpYNo7-Z)$u}582*iO3V6{sK@}FmwIY`8T@`gR8I@k4wyt~w zH}LhR0?9-bV?}W^7Xx-BfAkS}^*}{%9kKuy5%yL)&jq10Hv_e7ZLnkK@mu@zV!w7z z&$d^0@K8AgJNJ?brS)Wsl>l0HE|<_R0kd0?k676C_vg5%;u}Own;$neZF; zQ*L?HXX{W&g)v5L^GVymYmxS79h5GZHj?5Mm7=zFu_`vQscJ3txjJw$Skv*=&r=;C zVI>x9n{@q>GX6UYGLQ1zbBlIw2uk|m9Z};Ay2#u8u zCIB0=k$WFv`JN6u$5;1M)(X4R{z@BnTB$Hh@t_Nh5Lpu!dvR9wu=H>>mnfoh7LU#a zt8OJfm3U3}T`nYb;niv7)pZ&8rlg7RmP?!d$Qb%HB{wf7T{LffHf(8?D3LTHvT|c- zQ1SjiRAF&+YxRP~bx)I1@m6vwg|75mR53?b@pjND^K?Mnf$4%(T2(gq05>f~U^|5n za1*y>sgL~5)J)A(OQ+8*{qlW*4=mes_NMUr+*JIwls%D{X9cz~V-;2*j}8p;5pLKK zw31zM!d(&gi&nRR;TWS1=y?-^j>n~XyH$a*^Fzc|Fz~pIjp&Wzc#!W2exP(Q4q0BX z!6x`tKHDdXKLl?50{#I0IgA9EkTKblPG^Q~m?$)lbPwZ`?`3JR^KaP)d>c<)W7uC4 zPlNp;>nhoj6_|B1xt9GbmT@_kS?7{%xtDziX8LIjggKapc@>3u4Tu?;jk%an>6nxG znU`6ao0*vtz?q{Nnx|QstC^auIh(P0o3*){!TFoTxtzKAoWmKN$yuGRxt+b)oyQrT z%{iUvd7bN7p4s`G^*NsR*^zabfq2=M1-gJ>W(^i#0oH&60)PVy8le@Mp$|Ht7rLP( z8loL~q9gjDDO#g58lx}TqAPl%JvyX28l*Y;qea@JNBX2m8l_7*rD6J|W!j}_x}|NJ zrEz+tby}r)I;Q?>I;VSjrf+(ueR`;a`lpGyqyHI&0(zjG+I(O}1B6)vAVR9wfT|zD zsN0O>AJ1$damzUuJu~1 z`8uupIu|8S({}*8&^JzG(6PZ+ASYQ?9KFV)fQ4D!zboq>@;fo zAu9v5Q@dhX`?!&Nrtl(M>JMjhMl_C0ZVWMV3d=gKOl5jCR}SA^}tn`+8?zxn%XW;t96jkN7-5ix@k z8ExIDyK=Pq*a&gBGtJU4jmB;SBv1Y}V+(Y5*#jGWc1U$bt z!#4siH!9+fXsfoei?2SRmT+s94k^1_iVFy-ser4$eSEvln^u}TTW}3DIPQOVt>DOR z;pC0Y7QDc{``?lc)10l@n2jLy4dimhVJ6be_$<3^Xw~RuazOlYYmGl6&}Z$xzvbMR2!^o7$PqkZ^hXgx z{%-E%hTeAD!XqZ%{%zkRGRqn6y|)}{FuWQzGM;j$0h?*ystj&S`^ee+GfMNhtR++D zTtn*o&OfWh_dFxkN)<*c&Y0N()lTta=>S z@%^oW+{6Cy>p&yyG*S{FJ<`k$bkgq0F9W|RgW4xC?rsFU2Y%ZDuF;!)UC{Hr<)dofgDisXZ#2pr%Gsv>LT=0cc*xI|}Ib%fEUEN>YH`*PyVq6|fKD%~l zty16!3dz@9zU*J#(3Plm0EYXdD#vLAFwz{6Y21e4?cU)nk#f=|)S)KF zBqnbx{1ZbGX|fH55Z`}9F#)CCGbokCLB8r^BkS}0-SwQaP(B4%DH6!u>_MO6(4Jeo z&d{LyLp$!m;pQOgULoIxAv0sP`A6^Jjw1QYA`33!k)GOEt>0LU!0D*kgTKfg|1#{= z7-ZM#Mc&pi-{kqcslNUbK0oxSznx&7M$qQ6K~ueo&AyA@i(-RnCyV~_7sK-L9NwQ_ zt#%2e#^Bzo|NVRE`U%ZKFLZ*ANki?8Rb+qJFGk_*{`&zUfxv+T3mQBqFo42^3>!Lp z*sy^y9uNcEFxH@=#*GhyM2oaAg0@W|wS5X8@?=9U?@}l{;|dlDjx=l9yoocX&Ye7a z`uqtrsL-KAiyA$OG^x_1Oq(KYkbow_sZ^_4HFzVd)~#8gUi}I-tk|(+zfR*J&{#fW zX_X1Qk#AbrxpeE=y^A-mUaChE_%H@IaE$;G0|Ta*)FViRB1tkfiBg-q$@1WVWa%=% z5qUD5dj1SLwCK^KOPfB8I<@N6IiX733p=*#*|ZHR%ZGdIK>i-NY<;Knbge-A&t{Q30x zs=tpvzyAIF`}_Y-SX9;3M__>l9*AIq_5sLXgAP6jVT2Mw$euWb7Dz3<)iY2}XV~jG+NTYfuLeyf8I_}6LcQyV9WROA*NhDD>KGb89 zN-oJ{T}3_#Wt37*S>llnHHl@GT4qUQmtKAeW|-hv+0d3|o{46PVy?+%n{K{&6qyVW zSVNt5-kD~edM*iPpML%cXrFQ}RNoCe9Exb7HRx4C{xxn*)##&EMY?CDmR?1p1LWLu zPd%KJhfO>@$GOo8so>vMxDR9~XP9_rOt zaP{UErI0%Mm9kS!lg|y8PJ3ojJOp+FLp22EgMdjjbB{1Uwc#m85SYU$r?ae92tJT( z^n)X%n%Ypjr!tpEIk+_B0XgO9+Y_v$1VHPnwD3ZL4z(`yfI7MM3US27{Tcv$4Gb%6 z0yRh*)@^JF#DiSU9yBslB^Sh-ZdR$qF|{slh|~?;2C(g5g!zz>Ux*;^R7?i ze!9`Q>jv;axT(3pk0u=1s}K;6q*K5`P%GE|uPxo|yHLNe1OUO-JPAy&tO^NmaKf%K z^n*LTNDOz}(|K#*e1>9tsI)w^d=<+iGrO#$Rh>+bGSeti&7xKL{c__NGNtoFGSgjD z8}wLW&e1&$ZEofZwQ-N;q_zF_(~jI50I4%reY$cGaC1r6TnFHQ*b21~&LumMt%KPC zpp9?`Ycs^O({dk={Cbq*I3M1KLdApPR}ro;;Em??aiq85#&OE|BwoGX1vP5S4b`Ak z{l^I)UIVnbNqa1A=wB~?0`W(iz%+6RM5*`tI}Si6EyXW0Ysf`1f|O>6OMwefAm}

E}C2|08?Ox8d!(As6Ap{Ka3aE7IKGmj6flzq8Ag_fdzTBBZxYY-3PnzHH8SG z9JTmN!$g(5Fp4oK6r0b*oQIYgpzkZZS>yPa1(*HtCRx?U$D^PnEoDfnQ6dA}LHwpa z{#8SL>`MUS=9m`U1af_7Q3m>^kvPV&tc}(CUjQ#D7RdQvXAI#%0gd88%LNTwKnp-K zO8LNbflhQ66k!E1=t2)FL{lzwfH#7cK~B(c7J-g`QgDlc-4|tAc(4|S2nD4%v4AZgSbP7gfjqAyO%SiCeG9;F?H<_r_{7LPTRFK zcVUY~?bg|p;>B~VY=y`?<8wE>Eh>8X%!eD-hfud@bT|8Sma^RUy*ee7Am&5gMH_n1 zMKN@c1TjV=xmUQ}{^U_Eg{7ZlJ&M_?Eaf8Eiij~jX_TS9P*WiktwLm^4b)$=)QEOYj+t#s(qMU2CrCe<&RU6aP&a{LJ6sG4+ zYmN$n?v*@+X#i{siJ@t#ltq2v134Ab)iz|Q!aeRoqDm^TPL+o~l-lZeoK@sbHz?H& z8#rDFw(Wxc28Tfduan;?UiX~QdG@>ORREgUe}XT|erzK^>nlD%3QjH2^CKh`i@*F? zGNSfdizM+!zP++p!E`Q2QnuybiuoYIm9rsBSNnl-T`;K(0cuMxCyt=ul(#6}AZ<;I z;-R57rL`o-D;v`2hbU85@UpQ(qRLID`fwr5l>_R&`jBe^rMhSRT<$>APEJ30*2s&p zcjAgMz45JCb!-`!+bl=jT#qe{daT|8OE^jnx|i_Oyo*?US3g-iewQkP^ZScph^pELlCb}ghx~1D>;|6M~f@co{Ft+E1lsF znuGqR4e@TLsmL}@JM+0&ZDNqA8Du67*&#~UM-FRJ-IkW)YZA`01OCUKZSR z?#o{cV~oLE1nPMXiisJbQgEf~(l5RTQ70_J4D(jroMLfGYbc7$)%LdK%6GWXeNq{+ z80-+VnmfRF@P|+nx<5X|yv*>3tQxUu4B5LARb4N4^nHrcq<@f%KNs(sz}+d6RyR#B-;`_yr4aoPT~TOn`=JC^^ZvZ= z73aCLH}eXA_-fqsLGWwW>uj&(q;GzFOiyssZAUP{s~ef^qXqiLTx#1VheHg^^! z{IVWO!^GeF^b4xwWs(n9-hTu1I)DBOhJL!GZxe8(zA0TtsZByPP0%$j-}e(z(+&jK z6WGuXcxMy}$bdzGE9Iwt6WAudM}HTHf!#rY8_0njI3pIAfgvb@!r_5&!vMg73aCH{ zCs=|l2qhpmf-xwAd*Ol+g9<0W0HYuY0U!xC$bvNpgf#+#Gf0F*NEZ5Ggh{A`OUQ)T zAw5k9g;AJE`5}c>XoXjZh2xWjTX=;?$bLZxhG95sL&$|?2yR{|hH0pV{$u!sgkpwo zNPlR!hI2@VP}YXP0*856dPo6S%CHcYH4RBo9Cb*Dg(xv(sE3K@I7opw8Q}x@-~$f9 zM@TVbGxPGsph?^L0OVI!__YmyU7k7w>rD%#zf{0G|d7#IMtvDP^@rl(SQVY?D zqj-w9h>KE^ir0Z_!}5e^!cllZX0FH~OfiWK!5fiii@C^*&G;j`XdNh57WZRE7-bNa zm1YUxJ&@H{Dg!dfR~5?#jtCKqcQK5_s3A-NEjvR$fk=s@=#23wj}8Kj!!c!eqcO%8 zj@}qD*4T}b;xXU&NIF++mZWUYvSp4$73GMIda@L^;fD`#X3IGKj}>W=6heyh(Tl>O zYhl5V{`eNv*p0`AKJUd>=ctY2co2mJ79ZJ=XrdIi;f@axDHM5;H;I$`QIEnQjVd=i z_B9Y}hGk-wlIX)xhSOfVp^{i3l8v=x7e!`9_l*ITKe@3+%Xb@S@n$rKQOnmoxuJ6} zNrFi6h%-r()u4<;QHeRpmTg%cI|&^3h%up8SE2`!YIYETbZy=Um1%a6wQtys>2qm3&9nX36I_St(KY11)q!S;9tbVo4lGF<%-Hi?cWsYw4DuDVoj!m%mX@ zcymwrv~7(!U~INm1%Z^?sB?a!UVn)Y$MQe_6_RX$lI;G&8{M{=k)mEjNnpcyQD>G& zhO(5HIhH2UbG;FXk7#s)2#=#_o!2=UrCA#rsVLg`i&bHph2)x+6qItIZ0Gozi)5Qq zfo+B~n7o;dlLU?|hb$&3kOXF*5~WwUDVc%EoXvS3poyIWN}!^lowR{+=M@&inOJz~ zP+=K9#2KO6Xq6KBlWw7#Z3dq$BcDbIq4`NkleC)p>7WEANdEbswIPQE%Azgm6bC9B zaycwjHWouEo|eR*CaP>&COvR*n9E5OfpkcOnT>i0j<)%mN~e_;#g~f2pM2wzDN2J> zSe-6vrB{j*Fd7@&i6|W@7T4oz;4^1x0gx(lp8j@KGQJ6<1SKg+>Z3ykpZuj8J6a71 zDJ^)^m`j>R;E0?NHA#;WrBa#~D~hFsYN$J*rLd8pJ}DOTSwB_DeD|Ys6e=w!`Hd5S zU*yS}k6KZ6 zYD9nQ`Kt8cg}*AS!%D1o@tp_~e8We4dt(*IXP4SRp-pKWLs_iPN2S$@t=X!rTBsrL z#})FYU}wQ?+iI<~YOd${AGgYh;%HFh>K*6`uknf>>gulb8XNM8ulYJ2^lGpDiWm9{ zumRf~{OYd-I~M|runD^w1Z%Jj8y41r{w?GdbxDB+lrb5mpb(p3v7Mo?9czjV>#!la zU`8=HG&8XbF?BYR7$3n9M_?Hq3$wQfvLZ{f2BAruBoQ*BvPhvAE&H-D3$&Lwvo%Y! zRmu|tI=basEH?s zM$ogr*Eql>idVnbKl7Q5Nco!iyI#@*SdXNt6{XHMr)KV>4D|CT(3TsJbVoXjyAf=}9m~F7alDB_mtc{<7r*GFKOD5aB7NYsSh(YLt9hs=;=} z4~k~^wV$1eEb-+?Bbtp8>-3t98vsiNM`{)%A#J!xj)&w&S*-?Z6-MW3x)dOgF48ALA`@Lh=Zdr(Mi24 z6@8n5%&cG9Yr?F-Eqq_1+RJ4oK59zRg;Z<+cBg%0r^8k~-~-0U$x#u7r;JphFl|12 zh0{ZP%{Og5IlZJGbH{oVp>L=kE0BUas1SUO3Vs~`fGyZcZP;(Z)CaMswmcP%%BT2+ z7LqDGsB5VyiK)H8$_+YnFYJ$`T1h>pbE&Fyr_0%pnshJi(FBp!&f+}*iOq98(kr|c z%+iN>{&?88&7z5Y%kZVE{6o@d;?uwpzz&Ps#f_c1jWY44tio4(%?jBkhkTJc7Qwxp zsa>u3|QQ;iH z;2VM94^A2zeiXZ>5znPu41sFWF(`oGgC8aYraI0G%>{t zpQ7MS0pe9Oa7Y#ix#tiOPH>r45iA87K@JiAb}rE;8cuG0>hORNv12)A;*X%;&~Y{X zQiFgj?rC<%ct$MaGcKiB%eG9>Q%5f4Kz?;S@#7nT7xEA zZYM*azA2odQw+}JZufPW6GLX_b{Y0!F~;e2hwSO1?8M$cvqfUM#W3nn<`uDH)3jAW z)a6`NDqB@m3~}g&UgFb~4n#0S?Xd3PXJb1?;@^i=dzbD!=0p-V@TE2{t3&?c#1&*A zC+QhU=@0*~1GKgT4j2X=6n+jamDcRHL`7DG%tBc7Gg(f9}R^=mK!Eb#L`nO8%Dd zDA49c-w-`6TSxP5*{5MduMiby zKyfus#rFE$L#y-dhE6r(zvT_bT;CUJZ2#zxe%}#1>4}eyeLLWumE)U}`NAJG{kJYo z-r+(85XDdgAXqSf19HL)1_*S|;X{E8=|Ni9rXHt)5X{XA(Cpzug#?>LEEtHSM2ZA8 z0$cdu9!G-~F^Uw}EF{4;6Em7)S#ab)lmrppEZD~3NrWF^YW(PsQ<#PDrHmSN3cGf3*Ns>R>cp0^q@g4<}yS_;KXPl`m)B-1&3p(WOtPUfue2?Af(%55Bwc4P!hS zH!ya?d&`$?e-hkE(P+=IL!%<(x_%)QYPPNxUbd4;u;#zzP>~W3AUVYYa1k z^a_nMg5&^g3UvCqW3i})?CZROOp6M~CGT>J9nLiVgR-r^3LwZxf|O)zMz)aj@=Gwo z6mv{6Z|m(h?$T6qO*Y$f^G!J8lylDH#H=Aa$L?$ZOoUGI=|qb9i!VP96|^uY{D=xb zCjKTAicpO>LU5r189H#n5LFzJ(XLoRu)s|3!;nx7(@XJDMPUTd&_ZMU^FkC!UDQFS zB2APrCH5JyF&i0UG5{@k1a`1HGV^iAg|GxO*d!e}t;x&^`c+ydqpI>sBAH#Nka>*PVFir zk0R12A_s06aI7xr>ykZ3aas|;r_AxQBnSQt91y`w6I7H_h^4xC(f?F^m14F^W{gpT zQFfI={{CwNriOM6xMfGnVv41ZEuJ}m2h@qD#wmTRmY{15BeJl#kQMCdf|QM_kbaJ~ zP1_#ZiFUH34Kj=~IXD~J+R>~&gzAEd*1BA{&z5DRTXx3BeNhqm$0+cy@<$s{B#X6MV?Qm{Epkpr9>wh$t7AKNQi?PiN?%TFB|i zDBOX<{-^;9QO&hp^Qvqy%GybXj{c|ZdbZifusu@7e!j1b>#h;Aa$19YjB9kP zVGV09Q3^n6R#P_wCQyM3)XkaDRk*%IaBsbNjxzFb!F*KXZwZ(N1~a%p;26V$${-F8 zJgC9r)SwzD1da)LARHGaz=R&m#|?rLL*S^;gElN&4}JK<>o8D=LsTHAh>DKf*AOI81;ANhrfWCP0LTEMz{60YpefQj*8%VkIq! z8zWwlfkvSUCtZ`Pw|$F#{Axg+|iF+wZ$;#9L*Npu*z@dQ=ba_qGKRf%L&R5gv&8z0_gZi zWkT}?2jyc88Ood+RAXzOV+*Bq$4e=|+R*gM@^%C=W!KOXTd*qdbivPdVtun-(XbA!TY)<3v&h5F`Pp zKm{eD8i1)*^{QF^wW?I9+EuK6b*p0as#ePiR<4fKtYKYiTFzbA_hHx_ls10v`g9@UMjyUZg26@N>iVi2DKILd~JZem$UUWFg)F?8G!&|2YSGZ~- zDJo9DfKf;y0Fp2+a+S;6<0f~x&6O^6ojcv=K9{=M%`SGYYu)N@*Sq2EE_k{7UGbWC zyyqn^ddr($_`X-Z?xk;g?aN;Lu2;Y6S;q8lJQyfJM`%YkuC}6r^rB!;yRMg96 zHvVx|{cLDQTiVm6HcMOWQo+%(mbV0|E^7;%gif=J)i5y~S!nJJ<`JmM4h};t_(u~y zlEreY=put-L3uY@-^;Fczy1AhfCpUQtiBuI3Vmn}L#NZ==5-_gXh96-+m0U|&aPpM z!aiP*nKQ&7H3>;a41RmxBbV{OO@4Ber(ETv7W6^}hs$=ktBkWIdChH3@|EXY=R4U-yVaKm&1tq0&vjUxzo{;W=> z2tXqh??^$}wc(0SIR5NtVEY4J!T7jmUh|vh{CVas)xL*b^rLT6nGlyR#2ubYM|g(| zv~l(Tgq;=7XuR3c&i2@A1NWWheeZq$`_E&Q^us59@uOpU9|XPzf&UieZ}0d|pyBMc zcYZ<8fcf8NU;EqddGL+@eej20ILOZz;K8Ff!h^~7tgpQ`J`sdgkbwHT=fc>ze}DYv z|KHvhfB*e2`ZDpU$nhzw8@w=KzW@k=ZJ0jydw^Alg!waw`Xf92t3V69K$hD&4EsM0 z>_D3%6Yw}Z9$>!H3llVe1#hvuuM4}#;{sENz=Gfc?887BtU((bDgN{RKpot{P#Y8Q z$QObb!B`T)F9|!fJ3_`|!Pt8S*PFcEJ3()`K`ER6LsP(ri=h1Yw>es9t3o)8LpemCE7U?eyhBL3moB6`A1FU#h#W8B0u%&0 z-9y75aD_FjJ_Q`aIc!8ne8e%SLp+>BN(3A*L7c^59I3)O=KGRY*gdpsJ@+FB%ae!6 zJ3>>0L{(fxRwTFwszg|f#dv8&TC7D|>^Di2MP1y*HMvD!{6$~{v|I$7n2R}HJVw3? zMrB+^X2d}a9JIpGwlS(T>0q}ti7{l%MyYE?ZtO;HkZfE-ASEDjsPvo~|Hh5Sg647i4jmvKxuhzho3bEJr?CJWLa9l9WS zn@ENO4v@=-Hfp$x%t?(5NuKOUpKOhhd>4BhqnUdS5yD9k!Zm9;N}9AuKq4WTv^8;S zB%IVqs|1dp%u22N$)HRZ(%LqILapZjIbIW?KVm4e1dc`9rKt3!MZ3tW#K^6jOS(+R zuB4NPjGzsp#^nGx8)7%KG%?@$rG=6x5aS?fg3GuR$o{%)Ovhx#yPT7QL$vA0D8NKE zb{otV0;aZfBh9q6#f;0x98J=!#mJ14p_Cw5s}5hf%tvCkwbY=8vbcRrw`!=$(3HzC zp}O)Y2;N*AAOx3lii>)Z8vx>yZYYOXSO`HVhjIvqONa^QEQeYsP3yeH(}a_}?3;*m zjvHX4css|Odd+fkN<@;k+N4TEDkk&HO`ZHZ!-Bi9tqoWdYxs>x((w2o6u_e4hW zYYV`8Mlk`P@QIuKe2txAxe!fKyg|NB+{F5{&(UBK$cUOO84Uda4fbh=r|}H)v629ggLTM)M~Dl&D4)al zn#RZ#d}<9DT~30?g8?N71@%!6_yz-YfaG-3Al=g{9MU$yrJ@Veqf-v0LsBI@)a)41 zg#Zsg3>Org5+*qo0a}b}v5Uk20zv4S9k~|$2@S(QmK9}`@e`(@TH=S*2BTr9oTeRdu~N5bVu`&=X-j z(}EaI{~4Bc;ueQCIzgS0z_HJy(d$zjR$! zirqIK+`~-_PH_p3s z&a+vq{adHHM6An1!s}U|C0qV#IgHR4rSf^2EA7&K-H{X>PBd+d7G(``olfVBQ#^If zS7q7hlv%zV-FXCC&;wl5WmnQ&UDi!CzfE1(out;CUD~a%*Nt7=)uxex3v@!3+Wp

E;>+RKjVz37@Fzr3a?QJj!>t69a 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%0Aw5#Zlg;qX=I{^S=y}POsyu^k=_%o8(`qK_2wdbL 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

adxSx9ojkJj9YnG?eIipj;HjE3%xD=oSKa69H zj*PgELqD1fiJ?4||KPZvOu9T2D2GcyzWS~oini&Zwn{53whJ#r#0N}cM7f%vM^wZH z3^z)IOGN`bbbG6vz{E|wH)EtXP5eO1i?_ymHOt$A6ih`6B*t|NM$ThFRU*z(mw!i2A#~h|3X~e8~w&65Z&? z;^;xun?jV}m#qs49(jo4`$*~Ah&q9jtuct9?2GH%y73bTRUuEV!-#rWNtbY!>|BZP zG?=w{h?J{69LbBJEC`q6J=}|l`W%uwIJuSNPos-LfGLK%Dn=46-{>v%NGxSO~3M@@qT+PG`#}Uj- za4=0&guLGzh}Yar7F0(~#Ka0*w-QXn*c=GSOGap9L1K8fHO*4d%+oRrPL)v3UYtyZ zBU4eNw`KIVag5VL-8W6dJj0v3GhK<-{7gb6O*g$aI4#c6WQaU?!K-x9`^1zPU;{8P zLj?)X!Eg~8sgvSR!l6_`8DYvU92WIdm3u4_SZzsw$<_0VNKOgQlyHcuTsfQji0mU# zG*OA`Ylt1>P?h7=jhxS!+tsF22*j8R=O6-OZM|Qui7=E_en1w}lJj~YIM1~{TVANT|Y{!e(*Tb;7 z0j(C4kk_cAjA#*wsEImOWx4QNKaJ~=WvNO4eF!GJ8is5Lt!2l>kt)c|r%h3vu~Jm`S~sgn~0QRAqH^4v%)9M=9RJU!*e+|7*((#6-m$kCK|S|7cyuoSdw!!++o zfw!cXy2}_$lhOr5Sh|8zh9%xDb6BT=*qNQ!i?CSX?0}3FQ;Nmel=xYBv^x58!(c$CZtZlt$72zNuKWjx?$57k@)llQe;9Mn0b*j%uW7-5v!i3}X^;k$oWIf(zH{M=AtzXg%-~FxFOCD&2 z!@$2xiRoouP2N&Ij$h?`~W(K1RS$N#%W6Z>W)>xaJ z&0(BPXPn3W$pdZ6G-&VLS%$OT#02f8&ED&6HKGk)U@XDxUCn~d4jdoC1@`bTzq2Pjk=+U20Rxp3uSswB-DsmM8hG$>~ zC0}wUck?%ouUks(fXm)E9*Q~_=x#YUI}Zw7qvHXsx(Nq#xXuZ2CiKnd<^wPDDd7-i zQweE+^GKKU@mlmsxAZ=Nv`N?WO{c3%_w-NKkWA{ z^;owKQFrxPXKY!=^<3W!TDSFHA7fny_Fy*(UibB4r&3`@_GAYSRX=fKclKLX_Gp*( zT48pseD-UH@oCrgZFeh}_%L^NEo>L}3EPZwyHajP_ZcJh*&W0yCNYYM=ke;@asC%K zo!SNDP4|4KF}l%!MDTYEtK#vJoNH4V=lZ3$M7zC%_xGB2dN(z|!*_j`_!HxIe@}!9 z^VdqdwC_U10({a#TlgrQncMAncb}^SR7+9|`SNObhnLI2I`@f}c?YZbf44B&4K&;J zE`>F$mG`u>d^-nxu4X`ZwJdn^YI&DOw9H@&mTIY)hx-4j`HQ!(fG11tO8PJcz=EZ# zthYOlH+ool%PcPVm7jOOVL-1}`ZUXo7P$9;Seglp`nmV3skg9<7qtKTuHk*ImG^n0 zk9WB;%fmLniorCLr*^hjnpZqGV{B*PY%?JLvf2)4C zc?!dMIvY!q&n~_f{DbxTqu2WB0^X1ZH&JWzUD&kS_k{tRphV1l!ry%~Q<`-#tKc{P zw(5KetKw54((6jg=C8Yz=lYY^ed+2p>K`@h?|M)pdi_Uz@COJ3yYQtjVDKQqgbEij zZ0PVI#E23nQmkn4BF2mw9Rld+@gvBPB1eWa@S;V>6uT0TZ0YhP%$PD~(yVFoCeEBX zck=A%^C!@tLWdG9YV;`5q)Le3y3aV zuKU)2+1dlWx;<{N8E*r=wh~@#{W|vS+OL=H?)^LX@Z!glFK_-l`jMwcLY2BbqHC=Q ztg@xL8z26>$no>n?~8v}4nfCXZN=&4oLT(ImKI$H4Tz6^)x9?%g%w)3U3wX6xFLrf zdiWuTA&S`1dLp%_+Jy_nb^?nnvRGGcDatq_jWybMBSZcp>bN71J^J_~kU@r5VoNy2 zHXo8no)8;E06N*)Mr>7tcddMT!v zYPx4-E=~F=sG*9Q;-;mVdMc`^a@lA}qq_Pktg&jODy_BJdMmD^u?mu`z54pAuel04 zEV0EJd(*BT0lO@-%|3c8w9!gCEv?By<}9|^YKtSa-Fo{ixOQ6G(YEE9d#-ktwICV0 zyPzc00%bhWQM`E+000qs=&Oet19$|(8T#5wZ~htk>N|l)@$QQ-4hHW#?+kYsJa9+( z9^6sHaQF+r40hZbF32H^EZ(>PpnEdPDNnVTNhu5!@4NsAK`{~i0swH#5wAcm82-X6 zQp7O>FvQ0W-Eq+)TYWXwnU$+8ck=^xI{q9TLE3f28zBLa^PD-UCGZ!y5iloi*Ww8$Q(5SGu@(eP28Ncw?Hi zOccy;r@gTdHqTr&!AoO&Hc54hgm>p3Q5`V`WZXOW;jO#=I;SvQ*;;%pG|shMh?yl8 z@-DLJVQ(I>n7%w`vArp5 zUju6%=RN{GkdV%3)H9m(&IW@p_-%XM`ydDj2fiCwMSNR1f&VT7mft*QD+V%7bXHg& z`Rz`9_{oj@8X_2s;7=nG%7}rQ!NUKADl;blUhtkUyt~;fUIzT!z?SDU=h5wGqm$kl zE_l7`;cEq~3n3W82(A&@h<5RTO$sa0!-Tw0I?*vsZF1NQDj8soIjp1o7_!5QtPvwW z#E5}f02m?y@G=543e0fE#Eo(O5hRL~Vk4ht#porhY#xCi7iX{r8+cHRp8Vvo$XFv2 zwxB7t^WhuWn7%z8gfQ~!VG5pcl|eoyj|*WXSo8xHU)aTbyusgn^f#Pm1n5Cxc@RMi zM86yIB`o~moq?*eKHt=5Ak!3!TX-j(-%Qh%gv8Kgj(7q@mQ7~|RNEK-b%uFKF?v#K};_5)>v?%P;pI-fH zrT{9VC5bOED%i*zar(@P9z>97jHN{Zq)q%ew3ZK9CVqH_7s3qZAY{p1UDL9bzD_hi zC8f(9_p+Sclm$S)*`r_<%ayR)RIo=(Wltv*&RvX?oI=YN!Vs9eO74q+1v41h0Jbm* z#?x#Q`K?E8qEwXtx(4 z<$OxHk-##Rt^WN@h%4>q$|vbZqR!P{TZqZK9@-^$)?Fxer3)RG8kW0f@vcC?8^Zt@ z$S&o5&UrV?S@q(Sh4gdpd#yv?6|=a-}6)R%@+6A%|md#%!JVYI*7``t4GMK}>85mQjw^~6X zRcPZ^9Oq^?Sf-|350sZ53dX==8L~hwjNAhS2!0!dP)D)p93HcIx%(L@b*3Cmy1?`~ z+?+CyX(}1Zb~!s@zBHyY&6G|R=|=daPho-y=>61>L2Gr8`v|L-wIDOcy>XJ74?Rr$ z{04t`{$clnbZ7BD{nc@4{n*s0YIEJ|2fcqbn~1Oo!gcG#Dm9&wy5laGGI?%AIWU>yBMf}Ba8HACh(pr1$}4(1?GP@w9WkXfM>iuuBvH3(V2m4nbAys27F z5f`Jeko?`0L@gN#E+JaTMRD0+py;3$ZXvQfUZ3Cy_Fctq)gVO}n3M$@|G3-w2#0hj z+YsH9_}xyO+0TOvR&~*lTlGcb3|Mnv;SF*jAO>Pf@Zd&#nto}7{7sj!G1iAAg!!aE z54mCEz@ZavnR4xgS@?$?-US{4h90(3bnHeS`k|W$qA8vtiFl!-kPs=+*i=vyVW5}W z;n|&y7?n_ATQy;Q@E4EeMH~Va|7jRn02wF-A1Ss8DkdW!5+ZB(ApUX~qwsMbgYb?l z)=_j!#|hBjWZ7bgv4u>@8L&~>e$e3%qR%Ey)&L3`4EB#mh2t^)p)$rJ4l*MknNWU_ zp^Z7#9!{Axx?3;_+AXrsgHXwC0HBlLP=V1J=Ghv6pv8TtS2CsEJHm-PR%8Uy<3(5- z{n11|phbox^!MF)!0wUrfLd{VsfTy5{hTCi`a~&P)KH7R_1EvrmeK*Yxd@0u*?g{9BEc2W$LDJ z?q+6Qi*GJxoNNZ-$z^FyrePi@b)E`uGADLkgl4P@XcmQS0zh$Ar+9A4b!Mk|N`z%p zon#CUQ4}RpCM9@I=XlO%rIaW02_8P4=S0#ce}!8{ij2m-dDg{ zN6A%!N#t`l=zy-BfmSG{A!t>!A_{554q20bd1#*g-6DdW6knj&grbavrf8U9=q))T zx?#i~VPg8E)h=~kV9?@;evOLmXp6C^LcE`V3fX$CMTaFBvjJm}=IF`rD3i{Yk0OKx zY6S*zD1ynTR{)tABB6;YDc3Zqm*UowYMwKuz*$i#?=%|!P|1TKgb-pFm+I(7Y4B{%+ThPxEIzz|M+lL&`UK7*t<`#l(k|`!H7&t*YtNOeP*m;Jj;+=l ztJa?FvF60c8mzkl0KA5+(UPs)V*W1IUh^17S}cfN;IFF<2J+H| zZ(yqnd6a@o(}Fz6l?r5m{^5m3#o}4~uJ6*}sWq+upYWVCEU03|luCs6%1@1Q8E!mS zUkFkKTjdd&@2Hs+H5DX_?AfF)R$WyGbWkIz_RpcQRbLG;sh%qeKXIqVZjF#t?fl?G zG-CTGNHa6n zVV;)mL%eWaJgW@rSy=#v5$124L9m~8Z-Yn^K}-|-1Qz)r@JzkYavb3KBnS@I@f~ln zvF35I&aR_U#B;@&fz&T`_##{s@&h|!10I$cFQTz^F`KfG02U)G=b0ciah|QRCa3FU zJYHn@txyytd;&oJ15kru9y25WfO{e(C(o^?uJBceY8f`59A&TWo{)MCk}7BNel)Qw ze`s`A;R6R&Er+9o>;+5;>Yx&Z0Er!^wZKUrQBgENGI#+ zUKa&fZ}wjkrBgD^DJ11Fr{)rD!fAWN63F#xJ9b^ec8>D(P{y<{`@}JyWF(ZRb z2Xs(h!EFyWaeK0Hb18CrA!iRocz$+hLpL*5!cD)mc>6PUcP!y<_r`U%UoUr0EWvgE zvu_i2N5}vvoHu-ec73n+!nU`2PaILSUAv5vdbSID{zPtrL|ognKNEC31T<4FGk|CJ zOa2TvcV9S%gNJ}?_`i0zh$n4vgLrn1IEstLhnslkrnrlbS&6gwa_R^IkP9bpf+Ezo z$=rC3+c=KvxB&n~K)S!&_=^+kip#jsjR+@j00LkFA^?CPB>9pz`I9R-lRG(-SNV{? zYLOdxrRfL=+_)il#FukIn0LgOmpK5Od6pA-jL(SXa(RlaxtuGmcF(H#7Mh=S(hui@@4YH#NCZW{h-@ct-{PDHCQ6DV4=`u@44J6@gFh%}!NwL0RA zKC}teZ&Rdhi_vfBAj13tN+BuD)fuS1@g}CAk}ZN306fv1Ur{c0~-0U#K0h+ z1O7UgLk47qG`s^&jDfJDLorwe7tF&`w)*Q3us!Oj0W-u%*Y5)BZ>~Fp>PoO*D6%i9 zgce7rq*L0gNyatmny=-Db1ahrvm*iGd2brU5$)X(31!;aL=c?AvZI3uc*Gw3J2?=5 zO91=7qXQPW#K13m!Gi=E5Ibh%!95UyOTd62{Cl%YkRWXQQY=6@K)bZNjtXlirRSnm z!mu=&G7Za8w>N~H4a5LeupRa=5X(=h*46SYB9PHf1?v^}?GWaf1^Hr=HnwwS%k$VJ zzzeX1;t55+2Rr~MdoXmw9y~m-d%R1a!Nb4A)f+s(~?3U(}I|C7Z;f-hjHJVsAN&~83S8+MPdO87(wjO zIV++NqWtL^@`eXROV4&$CwEUo{n!IM0DOH%kUdOry}^5Z*Z2FvkGu*0c zOZbI*Sk$k|SXL5RJJE1;Kgb%q?5D zSmDa0x(i>5wRHVLC2Y8E;azd91~zcwSzg73TRdYtw*}?1P$}naW?5?DsFd-k9lM%! zYuB$~$Cf>t_Uokp47_;Z6lROvNgbLnNRidR4Hwq2Ak@gqk|3renLRl(Z~ldp1%H|@7MbyDI|21a|oh? z@@Vh21sQD6!3QCXP{Ii*tk6QEntH0X4XX;vE3fqW%e7`8qbjYaNR&&m#5~hXFTOa- zimlJ4TI{gC=xU6y#Z040ve2U9(X1fbqD(ct@X1TE(sGo_Mh>BjQpzc*tg@=xa{KM2 z6Lv{Kso;hiq&SgA!YMrKJbI}-ikbs2O_;nRFU>d=`i?r`h|BIcmTI}FK8I8aP$mP- z6B8u;C^~SzG`TA%&V#t%=aCC3t<=&>G0jxdO*v&S!QOZ(k#| zE3i6~%@=%NP7Nwo-)d{c9Bq9SMz&(cr$nmC>e(${5z8@HW>JHgGy{$$?a5_fChRZ5 zqDFSEm~TBSW>it`+Uu`T2G`tz$Q}DAbg6@=ytHkC_aKEXBCpMt0Oa=^k{*R`kMACx zh~Ss_^i!gk9Nv#WyAL#wBIpQx31gT9B8cS4{wc5A^2;%|+~k?S9_!Q-Ko1>s&~WYC zbd-BM&Fa%xZ{77!#TFO0aBo9NXs@zWq%i5bO#M^WKBlbFZf4 z-yYme>>8)Hm@!o9`=G~PO3?Yt!4F^j@yRdWr_E)0eX3KzYTx}6P93Xfm`nFI=$?;M zKeC^rN?rf|0T{q5EhS6hD&T_9Rj&iFOAvFD3GWW_sNd1eU4%N1oz4@ekSwoI94v^& z5*Dc5Nl$qCQq+JLmLG;4YF-FoiA&5ELmAGHhBfpU`eGu$6zq_PJ=|ea1Q^8CuX}R$e16C z#KAw-(a-kCbR6xyO&u_#3G@J)8ibmlWDnae%~?2EsYmrJP-R!L@HZ325AxAa|z9WiDnd3*hNWx4P{3gl0io zTJSEI!3{o&c-3cDv9ydexD9L4hQwFAY)xxElgoNNlQX{3C@@finPK$$7Yw^augW?S zkTSW+`w}*GFd^3zZ?oLyZZ^Qt9Wa6qvIKT0K@{%Uu7i=BWF_AO!me|z$|h4ktoToL zc`1u(rp4DJ&5T*a;%jZ+dl?tAm&A}E8n%YyDqpx|%`=P3(MClVBh5ItHQwh7uE-!A z0~oqI{&9gl{&0oM9(l=yHuRF4+&cJ`S1&4XO=cK#zqkNtNlcscGmcc2-dY-TVK#uP zY~-1!NaktzOUrr}qv@HcWi-j6b7AfL65sTW*J^rqiXnG`_oH~1jWH_+%A@Zy2)vb^8Ox> z-v5p6y$PJ}AoCgkG7!ZS6nt~FuN|g22V1g9WnS2*YSawB@?p+`n!G>b&CFuU(bv}` z4Ks~dgprlCw%nM`G(#?$PE62t#P=O#_*z&us}rpV#VK+riu2B~*X{jsv5%JQ0I|C+(W@>SPR4QqpM7X8>uBAAs3YM2K6)93rL6eLZ)f`OW;%&q09)l6xF zy*rUOY%kv>g1X*opL?oc;3s|cXI=d5cmMm5LjL}) zvCn<)i(gjQEoE+5Txjd}KULu`00nRWb3*>Q#)l9v1rYB47|^B&@Btw(0s+7P8?XW` zFg7GG12s_mDDVP3@B^=614VEIZ>|GD@B~kg1XXYa56uKo@C7Z91!Zss8O#M?@CN;l z26b=;Ps;{z@CUJu2ZeA5tI7v~@Cav&2$gUNcghHn@Cjk9rOpE#^2I{nW`%qraC%}u z$^=5hiMyCE47G~ZmI(^YumaPnTxN=`R_<)HNF?TCn!w484um4AFgoIBkn-pbZ$p&& zLtt*AdS0S=?nq%$VuY&cHiQWb#jp`K#R<T5%!h8>>?-ngVGN6J_t!T_`{U;@FVJDKnlbu z4MHPVf+aWRCGB!4Vsc6hPB!!^@vct!$gRTylSq1t%6z2%a;4okBqw#UnPLsGRBj%F z(om-96C1`qVjvLuzy!eLc0NLaU3q)C@)8tj=eCAN%Rjz zh~+w)t}!Q3>n`y(h)Xg{lYvIDKa?Xp2&G@%WSTfA8PO>IAvw}tPSawh5_nvbBB!v0 zvT++{^A#Zm5fOq5<7O?b$8IbJEh+LPf^#?-G%4~jN@mh4fE@pUdG@>t)=Bq@7%R2#p^D=K2hEXVN z2X|bwg(3)$67@ierx`o(M%{%!h{qg^2YE=SH0l24J`wdYRU#Wzaw7|dgzBbxCI)*j zH9&(DLB^>{Syd<=ltYdaMAEM{K=jj0O~!0BMiegUwzF0*W0S<~RfdFWkgrc|wn)FP8S%+(amSA{i+>LN{twMhbFMmm%+LSt7GBh@mDSEo}*w6j_P5Gkt2 ziZW3}&*cr#!;C7ECU)~w1=2>($Y$a5BL3H?jX<%51T-{%l$r`fY3YTG2GSzjWgAmz zCh%yRuBmA);*SEUf%I^j3~5t8s3i?T8u|e&3-)Yd;#D^!Lc3zwYI4d1kJEA$MR4^* z!t^i5)KxV0Ldh*yc{N*D_A=&Y%{Vkhc%*O}Zf=`yS#Z^5y~d#OF(@L}Qsz~19wbJ6 zq849b8_gDNJ-1{IR-x+3t`5#McD36gHh;bp#&U#p^RG--14#T!qj4R#TMEiwhr)O>g(c|KL4b)T77-?TsV+ZvdM7Y+F{-sBtml-Ie^5%s9k&Fn+SL(zOZ}xVR@-{dexRT*p@3M)HUc1brttANMkw6ROxgpWaE}Bi0&*f zRPP$Y+s-0<`A#srY*|nY_iSWN-7IyJrSi7ZeqXkMaX5!377)0I zs4+I}j{$j*Avu!MHjW+snKk$?Wh=RoBzcoLS*D6JlR^2NI(d{KxsXHolud_}Rr!rg z8I@i6ix+7N>_HbgKzz2K9wLDzvdJJ=z!oyW0c>Fw7%?aUU=?hk&y1p%e>s?kxl$5% zl_jv1UwNAEcPZ4$fbcAeQZ6Xwz#hE$o9*Ei3__M^87UY590s;QZaJ4_qH+zQ0*+Y# zU_qDx0GKnuAYR~@WkQ~9p`ZP^7P1QfidmnL0-hm3p6S^q7~mSV!4VLG4!+?V8u}o% zAfms46%N7zydk1vAtlRURiSwRrJ0&Zno1}!v9LK?li~t!8A8rEof%}EWg<8YTAuH@ zo^1i30f3*8StkBo;HDp>reOi7d4dkKffpv)Am~6AK0*zWdJ866qcIu)G&&UkV4*v@ zNT)WW1#qNG`l~sl7k@FOAB3gZ*+E`fLS(vN4hA6%x|nae0%lvf;3=;Tuw6p{=?gAeylO0AT->E-xGW zGJCTTyfr#oo2?fpKpP=|d$fBS9B`Q!=0UiNJHiWMw`X&>yHTdo8p5$ba^|3=Iefx@ z+Z*g*w9i?>fxEZ?KmlT*mSwr6OZ=<}5xQq#16rX3cHFPw`ki$epZ~fb;Q70K8JKC| z1BMy^j=UgVfS&nTn1dWC-rK*kdJD864jNj^Yk8qp;Tl-Mz8xB|VIi^QbyZoyvI|`8 z4m`o(94p*$v9@_A9{eCQe8NYY7>auiihB!Syda1{!f$-Tc{{{q;>1t9wo_cfkGq@; z{v9FKdeOD8Ccs+*UceHj+phtjmp`k@i5w=LydXT?o^2Y`f%&tt8_E;fD6TxR8=I*O z+p#-<%op3R`5V?NTYB4^11VX6(s6X++>z&;Yy|Z-?%W{qoY5b>1N@v2h8vtAJ~%*$7w?70bsj~O)L(+=S-|M&ebbA4r;~o)lX|j~ z8rByZ>LDA=3w!hnLN2>L{3L!XVzn!h(={|$E1DBn`B;NZV>rnN0-xm5S*CaU&`Z9yS3CakzZ@LOS;lF+ z@%wW@_4=>3d!Sn#^WQz*Jz(Cm8=i}N>2HE;x0)vS9kBsIRt5lSwmAYo&>#Q{-dG{r z@+}nr2G?RCytts;yNd`j_EW_%q{xvZOPV~1GNsCuEL*yK2{We5nKWzKyoocX&X@@d zq%;6DsL-KAiyA$O6ljVTOq)7QVW0)nq(XP$n@Y4{ z$P4u%ahzi>bm-0uz}*5sOjn0F^aue^;7znWkN{Y_4p~}uXa0o5MqdI)d&_7`-cG~L zbuo1Zgs?|@2C!u}fD5xP!ceyn<%>)qU(C{gu!1c}Be!!D0Lzwo_1sz1^59@RdhP(k zum28UzRNuQ?%g)Y&^H1KXwhre2&m0+7pXCzL>ECMphF>X!OtTiNz+eunr+BohaP?i zVu&J+NMeaB_4E^CDi-Bbi%j*@!d!L{b`)Sh#U*1*kqSV8%+RWpV0_!f?T;e#Yw zHa3H#TZH-2Bvw`-DHl*yLD?jddtr%>Uj}H!q%VE__>7M?qV-HO&vf}^lU{QbxjRrCWdjww9cEUImw1 zZ9-*LtTdiE*I0fr>1D03)=HS1b?&uRn|@8Xty@Go3sjhJRT&wn=AMi0VxX?e?n%;A zC{ujowF>}$v>BQaq$9nXD82sv3vj>!4?L5oC#8#+s;4pqRSGHucGgr~Q90MELKX#N zR9RNpYr|}6yed*gMhp~dnjkuBGs1%7wlm@#kOEVvkLB*=C1mut`qy zwJ=l7=J-~w%qmUyU$Yt;^TpxDD)&)FPMPIbbphU_FU!h|a=2faxvZU82FdcoQJRGo zTw5Kkv71LPyCYe7@!7etYmZL4pJ$(rdg`jL&U)*vzm8JcC6%63+b^2h6JH;bSuxAw z!d-N$p=ar>=pvKLu~362k91*#CI02`!{R(1y^t&U~pRo3B5mL;^ZNeAzFnc5dN zWyrLz&puVKzYl->^3P9y{q~b2J4x*mWvcBht6wDM8R=EoGk}kTm$Y5A%qvEt%E*kj zw+5asC_H-Et){oE0xC^|25iPz=92!wkA<&!B;*m%7FZbS?QexF1j_wh2*Vi4aE3Ij z;ZE{5k`^k(c4D#KjMjve0s78>47}0DS{1DE@vd)1F;ZSQCMI4zQAT2tlV7G-EG3a^ zdP-x`RD4ku8*z|kdgI*qptZU2b*?N{c@qPph&dg~k#sh!qaE*v$2{usbT|}=9BtQv z1egkVcOjgy^wcEqZ7fHQLlUwe=&VNKV~9f8m7M03#=@mcO%(f4lUQb^%nj>K5wsPb zhT=sMwna;98k!oDhD0|d4Us9Fqb;4b$6V@im%QwyFLTnzko++PCn%;di&-)N-g0zt zq}{8Q3C(CW=9kp0rZumL&Hfq&lOw|vq&L5*Djybwco1x#B#X$HW|EGB(rl+Yk&?}L z%5$FdtmnYCd67A$V4wW#=RR}y&ZenzbP5cpK@aLedn$CH3~i`GZ|IXzA#|eY8feq( zBuc5>(hyLdrF^ZA0vxHP0Rt*K3KO0SUuAf-I* zsZW2pG|d>`1ub~NOfO=Y6yS8JOl_)DMWj=pN_DDKt?FAGGt{{l^`%2q>Qlc8*0758 zL@!mFRnLmnwDOcgLp>@0PTq}Gc0?0&$GIcGiVGpa& zyY6+djBPCK*t*q={UOuh0h`Ju9lhWq*1U)C!u_coM{o=B^{~W2&>4x6t1v^2{zvS^{;KI%BbI} zghf|^7>Kq?UMf@73=b1gbaGqps-U!&SQZ9Krv+eS%5eM2yRaSxW>-YA z5y_xry=4{tG$}$dvhiG8mEtL~mZ7|{m1oQ2ENgko9P%;y^c$7)Hj!f^?3f0_!p@-8 z3}r2rvQXCeyP;V0%5+XBm+y?{Jio-twA=8)Ql-q}$*9P&>dIG`$fGLjN-m9ivYVB6 zw=hz&ZgsA-o%M|AOluk;d@h~Bg50u)4Y^8Pi4}mS0zIYFY!}Q!iju3;=CbrHV?`#g znZQ~l2{OYUNo3QD6B zA|?KNNH%mOVQstzDze6kj<=QT4e^NU_TEhc@~MRUZ9fTDN1wZ*afr zp1ISXF4meaO)AnwCZL&)b;m+|>s-gF)Db3?Z;CyfR3T@e0R>{mZc{d9QAW_5PTD zz3hJve3j7N_Qc0E?nA=e4)OjXnQwjYpAUVcs$Q7IufFY%pIr|vfA4*d2PL8p{@)MZ z`s9}|_7TF;?o!_Jy?1{2-|zYHmw*1&J^yJxw0!_HAO8H0|Ma;@e*x%l=Vw{?$9~M` zd;OejG#DsVXG}H-gmk2XLr8=k!h?TeaV{ceg3)k) zLTy1ffJG>UQ-~8s=qF&tZ&|`d%N8h42!+)~g<&X$Fkyu&l5Z~3VS#}&{x`CPDz+kC z_=UzdhI2@VCQ*hel7uaSac@C00Mvwj0*7(fbahCGg;*K?mrwa+J20|@Lt$`W(Iq~2 zB?0ze(NZ(lvp{zeh=OQshUkf7c!!H|hNz+{OgKr9_;19LEVjZo4Ah6$^N3I~X`DES zpJbJVX%`o2hA}aqWGpaaEDD4puNXlJw28EMW4FkRM3{?-k%vwpY=<#1kK}RP zG8KA5Is0^p5u}Zjri^vgjN^!d&xjZ|w|Id;BW5Cu*@$##VT`=;jma2}^0px?6<6>z zSSBJIsxcy^Ass0J8pweX(eWHEQ5vT)Az_mru<#x)Fdm>{HSD4ODd=Gf?$;9WF$){8 z3Kw}1(m*NXm|Es&7^CPE`=%I!Gd=A%H_SpULbrySRFAp#ctzz_T?K+7h!db88=;|) z&|we$s1w2=8$vk|;1G}~F_0-?kT8*uAz>-^5&*049ab|h5V;=o0RZu_9ua90=z$*q zU^QAf5?r|+Sc4Gy5hCb;mgkWk7)cW1;ePr7k*#MbAt{oXMUsLMjZLwKc98-@azWQf zL>||QZ<304vn8iEla@w$re|D7g_9e?83*|xO*tZ%iIAqj5tG6ZQ(2WB2>|8+08_~* z@`4an1D6+Jk(W1>wm_C5ftvLJn{FAK9m1A2A(tURmyG^$5r~qPdWnc6r9(H@h(w`u zc(am&i9K4_oLT}HjsqmK*qG)=TW*zpoECx{Qkf#6nIZC>Eb){d=`{!eni{a1qp6kp zF`H^h5)M!clfWGgkO`#uo?bbcVcC$k$sxH}6Y0sCu+Sd9NuGcgoQ1WQ5JOB=mrT{^ zpg8t;HyKlq$(>0_l=eW7M+pnyFdMz`lf4ld_c8~%FajKE4+ae3GVV|S<9_jYpi)Yk>cJ>d>K&1SmH5d58<`%p*^o+Vk^Z(oprzT7>VY3$dLIT_5>a`eG&h_( zRh)_^cHTsGNnv&m8jj~DSh`13B)iDw_qE`fe_R|8$1aTO_`z>VH+(P zqCmN$7OHEtQYaCA_1T(kr8+~r*xH|fsuIr zl#YH1u0nBqeq|Y_mlNF?5~O;R$UzLPVH;b(qP#(nqWT<=3Y4<(lL&FCok|;=dX)K^ zqL^u~@cJLbfE<{~sd-SIC&8*0X_o4-{+buDC?3E9n!p|A5g+tntjmg@`&kkjOQyy; zvC^usqKTT%DiYDEru<2p5nB?{u&~)WR@)k`HG3|{mwF_XT!U(vg?gx*sT{T;qoU!D z`}(Pb`Wf+Bs{P8D7vZnX;i=Fe9ril3p`jWhsvw*Svv67xta_wgDIP2v9`BKxzuKkA ziVzPAt61u$zInE*P_kWV3;3b30ji`IQMdM?pWz{zEU~pRtF3ivvx7@f$9G#hwX>Rm zt{kDRPZ_lCszj4{i?^^^rXS0@TuGqSsuEKJxPgmbgp0iHbbKsTS=-68 zBGI@&d$p}msiFH2m8-9pYoq?Uxg4P!p3AS`8xs3U9Y3k6+M$&hE4w6X5@Bkf?z^%q zkiH$un*w?fXq%e8nXK|Fv3<)Cy4$-X0l;aCpTdh0*IK-DMYGAvz=^?La_77(^??=I zv#(*OPAk2u(HgK3x!F6p*IU7s`yZIgy-f?f7c9Q^%E2F8zNI>&2;rHls;qMh99&5!+mR-M7+C5e5}5!#QocP>dO*xn!qzFxD9N@9Mw9D zTN^z|8X0`4P@Ac>(ZT-W%MsMklczz#P5YxO>Ka3vp#p28U~HpANe_!q92_AH49T!v zi8T-FztF0~zA2?YEUj|8rDHk^C~&3r`H{DS1{&e&$owX=wV5tAANIzmS(>&(u0_0IjwYw>&(CfO8eXcwU* zi_PhB0;NRz?EX{!?9iD8&_;pIQV|ty=!hTlMAP$!O9O8Vtx*pR(s&lpEHckH_d|uI z7l*VJN(U7-@;vzP0&BvUMnp>F12~5Ubbv#h9{o-s?bBK|(nBH8OmTIiHW#c$Ghaa? zU=%KLfh%NTCyHch#4<&p^GMw@KD1(MJRMMOmya>^b{%4OCI|oxKn=cU*5pBgdH2(8 z4Ld>oW<1o35aTObfg^nr7N2t?cf%*;#$x4z(_RvA^)+V?Bry$vG?b)gW*Vq$mVI~-aF(whSEByr(8Kc*^l4!~EIdE1q zW`s_L{ykBT+1LQU6iDT~j&TF*KmwSJ5M~_;$e^of4FFd_)@DuCpY7aa6WV66h~D;X zG3_zCU~C_EKxpwn67y9uI-%UjZGvV^30FWK$o<|I zaRr_I-1{9h(LL1Qb9P9PEG)xG*w``QvJ1WtW1@4{e;p&@%@*WM6#a(Y>3yBZMR$|A z6UhDB$4w2CAOoVH0ruV8OMrs>jpF|j-4p$ne6c3z17YH((a+G07^N}80u?|b+sgth zUP9p&4ox_V8IM6(n$h6^AOqD<-ygmJpil@T&JiZ=vMEmGoD$u}i5TBwbS%RqNXCl( zM%U%aqeIylE?%F^LSdJug0!bd(Wi|8cAngoAl&!u>XxnPx1K4{-7?+EPv3ejm}Bavo>!?pS?Z?~ zOCaaNO$~Ye;RqoEq%i9ynB>Wh>(#!4oc>w|t!@D>>}vJEaz`1K5gByn7^l$O$qn4i zKIf+p4{F_aIBf0l{vo>F?NBK1_wH2mUhhDN@BQv|*uL+G?(YLnQ~Dn8E=d0H3GYz` zfAAZq@DJZm4Bzk%2=NtfPZB@z0%-9YFHabs@$|>>A%9IC|MBG~@+bdG`feEt&hjnq z>m|>0C@=H7r0>u04>ynVIiJu4&4p5>&oF-&GcWXdMDGcZ^GAR4#q{!?q)CNMJH*x} zKM(YR;ZZR#2~_LXu$a)f(D>35^10LDbe^}PZFHW5nkX21OC9cV(eTmx zf8Ip_5GS7bGEmUqL4*kv3M8n|;X{ZKB~GMR(c(pn88vR?*wFw0kRe5mBw2D~iWeVG z>^cF`z>5|jTck8u)8@z^=S+YcgDx1zJ>&=gh%u3^c zS+!afy7gvGEGF~ZBSccip9vx@{LvCp%mfB$D1?lgC8QTE{$lKcj5`;A7_@ZLbn!Dl zuolAry!Ztvrfo{ecU*+=Fb4urmg&EFUYf`Z}!{?AZgf;ti8_8 zI<_or+_`n{=H1)(Z{Wd&4<}wcc!G~vJuY|X@85Ii(OaDOm(t-bd?^%S$Bqx*u7WAN zd)IED*?D{feT{EuKs@{L=?gX+-(o&`U)akdJWrqCdwiZbp`aGV6R<$`7&2%*@0uxy zA^HLwkU0t~wD3X2;Y7aifanYm| z0RYP?tT-eIjjnv#k)#~x7Kw6729sG#E$;Jw+i87Fu zoa`|%IZI3=FwMLxw9)Pg%q=EOk_~{Vmf|TzA8T5moOkl{^G`qn6?9NS3;h#0tu*Y2 zy677HCxKlaedxUFBs5?>?R>G%JOR!7F1&^c1h2q`G*$4vg0QoXKJd(QP$5>s`;^lG zebG)J2TwhfzFVIWP@qr6Yfn*Pi#7IGWF`9ZC7N3J5P+3vBF@B+a{4JpAcuM}m_4uv zLYyLWO6tTNb1dqokXjUJDstCyaV< z!V5RtqGe$MU__8m3b8n9K`QE~6|KE#kDrS{BN!9UO}DEYhh(uwm|MF!XLMb&dFB<1 zLPw}NSqze-mt_VxUYtYPvrm#t7Adud8IyR*D4U!sGKQq*-Di$^O$2fdltk_+eI1!-Tukx96z?IJTIT!s$!;7ogp6XI31YiqY_`+iSsRg@8z~Wv&B4>d}TEmH4&L~$f@|DDAF$hE-OhBzYv`=S1 z=}J*%=Ni(9#C=J8isyV5ubrfii9_L6NouDql87!OFrXhviuXH}3FZ%LWTRcq=)1VE z@p;Re*j$J{k-CAI{v2Rsa+ zAVN-M!dIfIAh8UlFx{4r0=78^q2n62L*ew$ zb1Rxk6xSt)pJZ!CI~oI494WBWrHgd*f+tAWslWR5cHMp6@_&rixh%d>(aK!Jb&YF$%(@L-AbX z-U&qY1#u*u9A!;ydQ+S-t&}yfW-C?c5A*yZBBI(3Eg86r1>*8m%+w&=EJz@H+zoDY zBWgl&DNABX^8`%(ty@(67F88y^_pWPYgr4DCv83p05fcfOu!kO9+oReV(b?>r8tPN z#13;IkzYT1l#`{nPp{}(B1!nk6>a@9lK#ROUFTQ7?~UY+3Kgkh^teX5RLOf5yKG@3 zW|A~TucCkP(#SZPy^|eMHO>2&7XdnwmzC2+If@Dz?9|to+GJ0)$Z2nV`&-~1CprJC zW;0az4+r_fsg-I^3mmjS@$8~+@6pZ%l_?)m4RcjX_0@!I1;JT1*Fg!)u6qa~wgPp^ zY`dZ*;KDjhv&L7xh4ax$)T%=f-LOPD;cNWn%3qV*>#neAXA)$@*OT(-Mswn4fe)Np z!xpxm35NcpNh+x$d69&s(mNCMNNT(%iPmHa1!QSfTRqZt7>|%?t;Sa7;m&Y0F=zZ} z$|B0Jkb%#&k&MkF`5C%%P(ctU+GI*)x~?(?SIJ9ea+CWvTvJxlIjT$nb*vK+33?T} zpK>6kz{|h}MH4}mLJ&cK<(-Cb5X|-Ya#z{xsQ|@oKxJ0p2T2&s6&7>8d*(B-I0UKt z+VDd&fpRzj>`2&7j-f640D#pR0(4xUK2>)1Q^C}FWKSa zasGutQb|V!iCwdEBB&v3lA#sN$=l|3w>`O2lUVZ~>G4Im&Fza?NvhB5W_P>YO(EmF z1gZ08iA!F9)VCVCW{G`iq-`SLQA-$J2(~tc^Z71;#lf!WdM(iE#Zn2=45qGwDa;DS zX?pgkNW2}%W)qqQHqNEhX~+UXS4LSe_~8K`OSxep)5aBt?6Q6V(^>oyM?WTJEje$} z%qJ#C6)%#JqNcdOmO@X>&F*w}E!a*jtYJQRTk2D%`q98$5^MS+swv=l*Hh2}UyS?R zV<&sr&3=%o`^cZgS^NG@Jra|rokMX4R6B3Po43nd?|bLFZmv!eYo6eP@iCB|{?C4R z#3%lgeGg9Uh~xPE?TIYCOEu$tvlboy$+5ZNLO&pDdC-TR@qh1-;!S^g)TbWaqVIRb zOY+WU{|5G>+-=81?;E`^J)imvPQG%tn>~I0_QNNBw@EJ&)hA#1%V)kpivN7*M_>BW zr@qvWACl&0U;Eo1d-c8leej20{Nwl2^y%tUwFAKn%=4ka)le z>_873Kn)B*5gb7h{5}r+Kom^D?JGeRY(W=%L8?1J6`VmDL_HY1K^)BfK^+7o8LUAc z{6Vtwkr_fNZo~L~KM?d_`Eax<|yiYf7c#+A20w2foJ}hm1i19N<@fWB#`Bz z2w@~fcZ?cMJPA)!#yn(3QUt_Oghmgz0x7J%Y(jQ0#8mWv8|XrR6iAg^Nq{8C7MijF znvUuS$MkpxsX7mb?3+}HDm;Uw@t_+CDvyb*NTS4$Y}zK0K*l?)M?Y-FKnz5EY=C4a zgp_1StGvoabjibE6jg#0b<@S~m>a*bNr$YnX3$AkX|L|Oln_#{ge*$9v=FqCu98s7 zPh?6_bjnhMN|7kZEu@61#7e;&%pBB8!%-l?3a;Cj$6$hfFq5Mqc#E3r=&C$%r(!@(XL`}Z*!qo%-D;NdXoK5cR z&J3*0!LdbEVkK8%%uh+1mB8?t;%79u9J zw40pHL#JLXWKIUQ6#yHi6wR2I$C zV-Y;UBRu%hhy@~4Nd-+rtyD{uO+`Js_t?xy?NsKtR8S37mdsR7EmZ>)Ra8yYYa~@u zZB_hJRalKxMPyZ1t=06CRb0*08>CfR?bYnlRbUNP5#&{0E!O0#J_Yawd$5Okh=kvg z2HwdHhdVO4a{ybIg$-B*ThK!RfQ4HA@PHSvg=XY}gb`MAB@SXWR&_N!A)L1&gqC^B zH{u`$d&q^~*n(!w3I+g&WnEU`OPaj1FqJa8x}w(mQG;)Y14vbNQH%;NL`TF-`k+#|2<&W1&ILG-~8p^*M+QP-QAH$-7)Tf2JYf2CSzhC zWBn!LIdJ1-9pKv2ib?{kb23;%AXE{)V1w@ZLdTWJhk~Abtp6u;hqH07{-@6pBcMsHzm;WKEt=c;dU-po~7Sk`4?u;5x2;J&qo0XAcAuvcCtgqcm&{C#8I<=kc6VppE2 za)8^oMP8D4x=pjE3`^dkXpPOQX5F~vywwKYO1ruqUf#xx=6G3)1edgOlR@=WN6dj&vN3Lmwz#4qOX@$^f zB1Vq>=^$sLI*2jr6bQM@2?3D)kY@+l4-D#*_1F|I8)_A7PNRN-dx8gL?*MF65^QHdAx=G;aTLy8QO{tJ z4`H!V^iDHcs_gkN(XJYA%$~sg?9Y1BCIB^#+pc1mrPqEP;DiQdRmSBlzG|9H?PZLAX{C2=(Bz8dj0HJ{@sb*XW>n7GK$uYKC*miI-n33D{!=DTQqA6aeqT;GV1;Z zjy4JIZP*j9Qmwq;NaB&|2XONJFe(-SY4p!|(2(?K7<&p?i5^U{A0Tqx41{v>V zdIq{7rZ^31p!|;a+|2@c0imvM58S(q7U%@`3JVVuu)bie;PF3EVc*Du>*f$QZ`b4-wibJR_#9L7+`8M@^|rxG5D&@$wV|bKMqm z+E8OZ!C3*<^sSHv-Ubxh$_+9CVd5C|vks0uA@z{(bZxtH0Fgj$zadBJ^D`E|_HM)m z?*u?+T1N=|NG7d%FTop@pl%O_a7+Zcph%bW52SR^w)Cx_SJVa+i;i8dfL4Opy-EI~ z4cEE$Y5#E_@o_sB4stzpH&<>~2i80{h?|}WbOvwtpl^q;8?lP=_CWNuaW6cxn=C&n z_jm>_pJ!yxzj6y0?42Z&xBT!v1*+(7Ye~ zP~CgJultf!iF)f0#UXsh7gfVQ{I>7flj!Wnzx*+ce915S$@SWh$9&LlQO)1{si%DN zUHs5beLP)y(r!icm03=WRsZR+V6eQXMNlc{^hV|p3*PhKmG?b z{GeA~;dkGnHl-JsL*$=+Oa=a^@$+;JbQqE|!%^bqzb4Iwe#@tR@^4A&PZp9t_;;5N zvRO-Ca{u+ups~q_Ec5sGxBu@i#^R8-{%nbra94l;AaEeTf(8#FOsH@n!-ftYLX0SJ zBE^apFJjE7aU;i$9zTK%DRLyqk|s?iFwoEd%a$%*!i*_1W`Y(r{%_)JVcC&c8qgLy8HS5-{U&D?qdp7ObwkrZ=nA&n-oGDvu4!cVznP;Mzri?Zw#2#Tf4h7s;#c3%O zhEigQRFsK1c~zDMEJ-3u8&>wDR8DF(TyR`9wqccAh8d}(lcuPqrI%uwsivE9dJ&rl zv8SU=3DlHQSX6FjRHLbeHz=$46zYBqP9S)oMAP!tHVIW3TRL{0~MT~*P4svc8OtZ zr&8Nt<|sbiIVvK^@sb?1)ReAVwbfT+oi%JN7xZ!p34#qaOF2$mw%KQ+O_tVcv)#7a zZ)?OgL0*$ux7|4w?2^($i-x38P^TTZ;Dc)=QVY8vo`TCS>~exgLg*2B}yZ$kN>XNrEI_aMm000rBQ!Y^FdbBRk?U?(X zJKVz)U;K=659DSF%QN463Z@bsz4X&d8d3@`sB}W(1*L$v;~@zFhwB9qVY=wz6GVjY z1PRgmKt!NlIq*1`ZczEP1297q?7L6U40hm8AoQ!9=z2#4Jgi}S>N6e#8|Xm!AWtCF zn;-=%XhE5j!~id70YMV5i|c(4B;gw$L11tO%2{p#uAS2z9orH+#?_RXe=mlP$1e% z$rT?LKl|z7knaPd8pB9C8M;v*q61?K(WpB%o=%ZI9DolYK!)1U5s#uAB`GnYM?a!6 zm8vXJNe-6)32sn{g#;hzVpusnfH9Q(Bcbl@5V;txPI8o+q(T~b$pC7xlALUv5HP39 zQbIGD(lp2^S82^_Vv{W->7L>Qay^x35Q`p3W&#&b zHQBmN&Y%sPq~tXF>CZY=Gn)b(C_!g3lI{gkmfZ}eA$j?}JV>AniWK5OjLAOJnK6Cq zR3;8FSvfZnbCb54z%&2;Y0{HAFrWopDNC^_673}v0NO(wO}!_=iRN!}IkhE4)40*o zVf3B1M5j+3nm>>3u$L+nDGr`cQj|h9s%=wgORH+tJ%+@CFxLN>qW7e5xAt z$3riEG=KvUUH#0;(Sp#kh2|^69DBC_Fc^WKQr#Lh#u@cEo;w)+SkH1 zw);};dBSE}pS3o(y8Vi5d+XcZW{S3{5m;|)!X?#=54VmVb5<-k$`;xGm}K zdID7$5Uqu|+_G7EYBnXneFa=ZT5qM`>);1NSTFJ|4RH%Yu(2G6F*D(>dK|PT(g;|= z>!DLx6f9r{rzgTHUNMVHGGWqS7eo5xE^%U|G^#|&JK$1UV;HlYT^;RE+o=qyB9j#Z zO9wm|+gOqu#f;^O?!75duQ5sT= zyj>KFrp0oeGo5i0t^KTrzP$mEcuB;do(U}l?-B~dSW*<76y-zc!ZC%cq!T7ds7UIi zO1w7Y75?WQ?9fkY^V6QR+}Rl6Do>iFb1?qFNM(?<59O1lw>&kG&#}{k9;H+API^=ok4cIz@_N{i+E7p>5P$-dmW}3jYA(6^?o@7 z8d*E6F-RWJm6l!ZZy~2aS$VdWnmi~wfkwpOGI6r;WFA24I?lh|H@{gNY{67GCvlqb zOh|m8UKtu)kGT_{Qe_o|>1x|!(+;aruyA!lOe)Gv*sCNxG!Oj=)JQQ8!a2jClAD`V z>t3?A)?BE_NE}dJp?AeP4yg0y8!i3bInUqwZ?<5!RD*fds_kU*o+ye=8;a1XGZt|? z{!N^~GS^$qc3hc+8Qo!0=?umm7H)EloJ1%;xzU#m^==m|Tgtt8%ok2`LuY+ZIM2CR zdT#f-`}XH*(Q{#}HI{~T>`GZa&I=YZ;IBixD$%~VhTy%em)!g6+WwQmxZV{FFRWVx zBDvsC-udNuJ>dn5j&gM+?+LvpsxgNA;|=glH}&P2+D4v!^*- zo?#s<`_E^5>(^p9ns!r`HI-uQ>u>*i%^od5pBY$?ocT*r++t+R@sZ1xJ)G12b&HbK z9N!4d(s)?K$sO9+%HOoxmQ5e>eckmPNY@Eqh+v1pD2-$&jFPF>%_)s%C|RK>g;iYJ z1dbo;wV%C!#5c**_Q+CK-CqvsAgAQtSs=!3CCJ!ZOAN{ce{tCD!5|TK2_V4|4({L+ zLgAV8pjjY>-B=;s7|g5O7i-~O1g1q7Dq)yFkrXjh6q?}~lF1aBh4ZlC^Ms*G3}0dh zUo*(zpOgg{zM+>eq5L5Z{h{F>0%CorVIHQ&-Xu+`4B;InAtAC7Nx0JD_+cPQ;v~|> zATr`5GT1hK5JGs66H?+Qf}(`o*^OXgDVE|v?ZQ@d&?bgrE4m_HSfc(Z%A#PsR4OXO zAiZKP>LOgk;w<`NRb`beCWKb)Vlf({Nc7?_DkDJ=7ULL}<9HBFz0xsKV>M<(GA?5_ zUXwL)V>iwQHfm!yqLMd~V>$W-IErIBI*~cDV>{LbI;vwlT97-^V?Cn8D7J}-0HN5( zV?P#)JpyDvb_6_XMZn<%!HovH^%;WsqbUmHLqa4)5ad(DSXmGtw%DP7giJ&FVnll6 zM=r!f&II4(gnf|(P-NYZ7$M6w*G6)rEP`ZA%A`Puq)Zs(P1xS42%ycVBugHhSe)2P zUgAs=rAOA}f{4m*AY@D=U8_+XcRZ!%SzM|Jns_+HcmT!34E~u=4rNh#Wk4R~OOPZ^ z@EK70nc!txVpt59S*1=OnWd?ob8+Pxeq~+OV_3pr?J7bA7oKp)e7CZeC0OY3Uh|h5Lrte5j5NS^Q z#1&&YXIwaDlO(0koeI%4MrHowVE&9|P8??%-e)qR^+=KSgpdctUqhAC8PoyrtY%N0 zkL$z}LAZi;Llf$QGJe&5D*nv{`F5h)sW`YfpU7(b28{X21a^} z<$n;y-z}MQVdq-PVYUIs<8g~u;30Un-yUkvd7@{2LO~d~PJ4zD8Nm}>9fao8W+dI` z3K2v`u@6qck5MgBMfDFkjgaR2Kmr|=S~X~qW)(hyihA7Sj$p_Zu3l0I<^Vc{$6O`q zH5ul?W$`g2h@#jSW{+ut&qTox5vY)gu1}7}XF&)-9`wK+@YIZ^Q;jxOMTzMd@Dz;} z65mBtnmH+#?$#b&PxlsB3PPnogAd<`5Nr<|%#JlB>FEQvs@=;_6=@DZr@5 z4+5bOT57PGMl0>YG#*YjktZ#A4(7nn0(?@a%GIcPP9#CjoucX+si|c7=CbD0tKzAe zx=&L5=LEPa44`Op=4!h7%dWaiuRf0z)(sZ=#NL#eu-dCZp&8YzbTUU9Hcxil>&Vuf zNFWqJ?CTVPsYU>-oeF0d(7+ii)tSZ)sTRcf#4H*u>{EeN@3icl#%Zjk=>SFSr`o`R za%|G(2fKC+$vUlTg#=6$#0k(}zlQ#4r@E}|bkWRaj+?e<8Cg~hot3vTtU(lz>-eYb z;8d!DYi1o1KHY%|IcpCft{&7HA?@t?2P{dYF6x8kAita#oEZ>^0`+Y=VJtHjjVcued zZMIWV$qs8Kr>epxTLsYN!Y&#;lV?5B>HKDkN)Auyl5x%{eQImB{-;ol?&y~8=|XSG zHt+QA-1A27^~xaiYVWUEFZOzGTWoLm@>=(PZ~4B2_@eKek+1o(Z~D6LimfmEmhb!0 z?}Np!{CaQw>aTmmB^Cv-z@SMz8SEXBya`4 z*7H^*S&*Pt_>GixORhnTWYFvAWn_t^O5CAG1f%c-KZOOmuxXWUgxZ8jR;PFzS)^Kp zg5eBIP=yF5VRS5>Sy08UEFF6sAq$ViuSvr^Xh28gz&^}F2$TaqJVI?eaTHH+6~FKW zFR&81iC!W`SP0mk&D;mO+m!5#7cxckg`P!*-nyK}5hHQ-euQYUA^_MiP5Em^EI>K* z!yos10VzPJrKf4EO8UBl^-K=Asa*^cLWTmgCI)-6<0(b1F|Fw1Q%#B zMo_XLV{#~O@oANA{)|2FQ*hYkk%$gQMy(9T!F=e?pji%Yhg47p#eL9^sd47*Li#;k zbNHC5c#AQc990MfkD1)jG>XJ1S*6OacxI0ck|v36L>~*XaH<0np9CQzgfwjPTa2;ROv@)E_d_iVL>|lo5*%`3FE%0v zvN`{;CR?&(LpEF+1Q#H(Hv@oR|M50+azB_dNpQAH3&dVawr6v8Ue~oc+_h_8wqz@| zP%AK@qK5-VW>^d~L?Z<(bB4xwg+gn^RIduFY-ngGn66B8SKM1Ld*=ZrM#R0!$~D}% zO}AM~%x0#wOO*6L2<}^_^e1a_4!DCkd-G*8@l3-tICHWf!*g7>bU33k0Lb$v_k$$= zbs_$*bRJmtC6AFh)OJtH^mrG9e`_%%BX~Xs_<)zTNN}=e6GTtP^?AcnIi&X?ueX8M zv~91wobAet9vSyF6Tu(BS^N@fyc_@SPC@Z*U z_i=4Uxg%3HApbX+Q!FgJ-f913Z@}{If$lY(=M`mPL9k1%pTk z9UAmh{Fex`%Aga-3O1l$K6;El43fl3mX%+R>+n`0=8X}(c0WjUgc_)?{z%jcKKDd|a?SdE2vQ zm;Bq8dCK?J%74wT26R6LWq126z(i4~Z*sqPe47LIlbifu6Fk=kxRw_-I)n3N-}>Vt zet@HVm)CvfvweiOy_Q?@=95GoBzt~e{5}Z0f-iovAH;&|{fGOryTWU{hVi^=VTq8} zmQGOMr*$(LmJKHBNTfYC|M5J$0oFJEVV^qW%eSg`e0>Y{E4aPc7euWyyYW}HJ*T>2 zk2YUx|6O}C_Cx<{leRsNM5;gd#%K8PCqLuk{jx)L?Dun@?*_>JhAc<={v4ZB*5CO^ z00azmwEz?p_^x0=g$o%rbodZrM2QnARM0sW672^dlqfljVoI=b^8`>T)A`U*0p;V?@_gT`8MRz4=`X=QvU|-H#np~ z!-n%M4vesGWXY2$SGIf^vq-iQ^LF<98FXmTqe;ijd>VCX)vH;zcKsT*>dg^L*S38d zcW&LgZN~Qf8+dTx!-*F+ZgMt6-piRccm5pu&EwOlSGWFt9eZ}|Ad^3g{vCXH@#9Tz zH-8>|diCqslkM)1e0=%y>C10_AAf%R`}t>o->|*_1sssT(fT_O!2}gtkioG2W2nFg zC7h5#y&Aj_!wfatkiiERsu08wMGTR{5=}f2#T13}P$AGxcoD`JN1Tzy8hcU^#~gLs zkw>vuOz5)|S{RbZB2SQT7kpZk-N*rJRz=hJGyQvm&(|a;2Yq!3RuyifSQD zFn4h&1$@plpcyq~BC{En+AK4LnaC`2Ntu$&)5$*ltP;>b1s(LlD*^B#%{7~OCQ_KbjI^0fYpT?xFaG)T6V+5*B9zruU47L*mN@H7NJWRN zvjsRAHT#+G?#$%}~#5C32+}j?^hh zU14gLR|AG+Gt^#P+J#e4m$ma(Wrx~S&2SC46Q5_k{SwSbd7V?=Xa#=m+JX%}7-6uo z%`4GumptKAoI+(b-Y@GsH`ErMadfC%d~p{ia)}x$-f)LKp_wDwtaB)RNyb#nfn{DU z;hJr}8Rv@@#tY(YFIIu4U?~n$U5rzHW=)Mx_?Xx*-<34pmFIma+-9NXv(l+c4S43R zZ_63%u*I%<=eugP^+<1ne)`^DO-0j9{&WpsSLLFZmis1r^F6ZMb@8dQ%}(ilspGy4 z@P%uy6*q9~#vOlr(6a4vxP=4~?NTSizm2KciOr3B;-PZg_;8T(j+gLf{pR=?eBvD3 zrNUJ|Jn_YC_YCsfb>AIF$?0l%TXQ20Id0D5B@<>%Bi$v~UhnqYCaYtg-CnBywmR$C zHNTzv&UpVG{O}d@eXg?=#Z_EzW0sUs)Gam|O=KN?p6zi_pI+Und$o6EXX7+{d)*UY zUBp*F10E1P$ag^g6 z=~zcQ-Vu*^)Z-rc*hfG9agAdX!C!dfwBW`t$`q^YzaRva_He73oOTm{60Rv_}g~KT5MtN3Fr)rvMO>wFw zn_9J<`)u7-6W~*I0(Gci73(*TT2`|*D5-a9Y8t-;(*zt#Oj8xpRqa{Tx<)mhYO1GK z%LLZ3{uQvlJnLWyyPve4z#q+EV_Sg;*ImeUqjse$MzyM@uQC>(VDf8VIosJ+78bOj zO;1|Ev{p1eHRh|2b!SZPn$w(0^rCI;=vPzVS=-*0m7>+{ZmpBlrJ5FvFRkjv;JVQ} zft0nA&1zmF8YX|z7PrxrZYOzLUF)uhn+{PUOW#;gGflLwwUumDoeNOra&)#Cyz6w? z+ulE37ryarjY@q1+%;x)pFreSzQjA;n3i{^b%pD5)$3jZA2^TlRq%o@qf!Jv7{UZ) z@PsM67Y9ce!x^S#g*n_|A7$4{8W!=0r|Dr6pExBKCh>|{{8<#g7{(t_af@kO<4?vI z$2m5nN^IO?AA?fIK^C%hLClaJ9~sG!9P*NvY^Z<$03rDV03QGV04xXs^Z)_?7XY9r zC@25`00<5M0SFvOu%N+%2onMb2mm4Z1OW#C1OO}v0`ve102ctFEFK<7W?wF9%T{`W zGR-npoU>M()~>Iu2u%P92plNzzyX2;4I&(&w~zox(o;aA^8LW2mm?&EC>RJ z0Qdry0j3u(KN&7PCm3VzH1f6`udgC2nv0sFpP!(Wp{kvzud;%Gp`oIur>L&3ucfcG zthBkbw6wIkzq-1+zrVn{z{ADG#lpqN$I8pf%F55r&(6=#)YQ}f000000000000000 z000000000000000000000000000000000R70Cfl)NU)&6g9sBUT*$DY!-o(fN}Ncs zqQ#3CGiuz(v7^V2AVZ2ANwTELhZ>HkJjt@9%a<@?%A85Frp=o;bLwQ6a^=pSK!XY$ zO0=laqezo>?0H0~)2C3QN}Wozs@0ZEuWH@OwX4^!V8d?ADz>cIvuM+*U3-!&+qZDz z%AHHMs@uAF^XlEpw{OO~egg|0Ot|n_z=jhmUd*^LPQ;EQOP)-*GD?+AEo@PgvuocT6+8Fu;KTmw^e(=<`ST^oqhHUyJw^5IdNnTh6_@~O$@o9np==bYlnN#~v0 z*@@?#)al9RpUwFR=%B<2O6Z}z8H(tlwkgW!qpmp$>7=GfO6jGYS&HeVm1)Z9r;d3F z>Zpl{O6sYCnTqPF(XGhptNyyF3hS(J$x7?3Y1xYFu43uR>#tq;3hb~}2}|s;-MNbF zvWywa?6XBV3+=Q(NlWduk131owsl#{?YA#^3+}k&mTT_0=%%agy6m>=?z`~DEAPDY z)@$#*_~xtczWny<@4o;CEbzbt7i{ps2q&!Y!VEX;@WT)bS6YEg%#Tg3_ z@xe`Suz(Up=rBacBbR)#$Vz-{@COzLF%Zm6$Se@eHoL6z&OG<*^UpvBE%eYt7j5*> zNGGlI(o8q)^wUsBE%nq?S8esxSZA&E)?9b(_19pt!~n$>V;uImO?a@u5=Q7iMA~PU z3xdT$3^aG#?UtbT{@#4|?f2h+2QK*Fgcol3;fN=$_~MK=?)c-7M=tr~lvi%~<&580 z0s;8Pi!`s%E=?)vMn$1eNqwAXI??YQTzJLnYj?)&e(m!LW4 zyBBZ#@yI8y{PN5<@BH)7hYtMo6bNtQ=Fw-b{r22<@BR1Shc7+#zgs^e_Ts0n{`%~< z@BaI{lVASuoeyBZ{rKY#0sQ>;@BjY*3}Ef#=R5Ps2z>~kf)^IZKrbMG0QtjT=xE@B z3RZ9j63BoX;*f*RX%GkwFoPUMC)Ik+MhM@h<3M$e1Y1EUzP zz(yFLQH?Q(Wh~w3ISS4Il5Qx&8UpDC5Mt7Uiu9o-Mc2d`egTSv?4{^_2}5Lp&XGO5 z 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

Bk7S zL&4M6y7ISKPPnRBH!Gszp>Au%ZXrdkSE%6 z&3UoXP%f8I(M97;ch*oQikDg>b+r|_Skns!w2u0r+%G4w=|4HO@Krhz#jF0Oq_O84+3zwJh*{IGv+_|Ie0PGri`U8A z-&YUFc#OZxA(6E3tHw2I2c|T_V>fh_F0)>q<)TAg2Nf}e8lDi@h+rF!wnLpNy5YIrl%zm5_mRr#!3 z1ZC6_KIJb228rJ%)a`|l#yh=_W9(cO{hiZ^!f2NE-s)ccWC=I>TnQ<%o95L3G#A<$ z3{MV%3c)&C2WV(qlgG>HDfLuzUKD;Cs?k(?w@Rd|(IR#j7hxZn_H>o~~eQ>2GuCaMU?_1a!%AZ@REqKc&O5o1} z)y7x-KW}XReEYNxL9sdZ!@dwqAeA?Oo~Wu9W32lnT%ZAE;5i$5gMEu(2qF$Id+9CB z7!+~(u7bCi!*$;rSjv}%T<1mwx)F4ZU{eN8mY zIFz(#x!n8YsuhM6)g{qte>5uYvKmRx#TO+m}?JQhw{{?lbBi``( zEO7EzyUFxy%*|~XO}VxybJbH}Y#lt%8BSH+K~4My$Fe3*1{!!;AcxFJa3Ecs6l)T2 z+~`Xc_9IYdTLtAHX5aNWm9fMhJf{or9RKY@VG2W1lm_5`;365oU!ycLE0H3YmB@ag9-=J6UIVx)YD0f zNY{}O31%!EO`l~f!(Ag51d>wb7*&2Ix==``ivJ->Ni?kMhvjX!Sh{51lCObG9qZC4Z952(~f5s1^ie zol8uCJ!J3{sc4)ef4z`l_N#s!$GqAk>Qie^UZ$L1cY$7sOB>M@;^juaDW6wQQ^L^r za&56LSzyhjze`%B53)2XXQ>!1O*>y{`ib{(4o5R#Px0E&p?q5l!P@9q>oC=yNLIuk zPozZp58i|vLOzb)G>}3u!KR4ks_U(OF~+%}J!aH#GSSa-Bu=AX;ySPHV8fo;BSe&V zBIz)k4!$vLguUD;tp`>P)krosnBiNyD*`!)X0+zBMtuJ6AS>p21}YUNkI2N5wHpY{T@!R!DbK zoK|VUJqVzX%kFoebBU`Xo$C>*E7?`C|LryX{euui*={Y3Dj53n{yYH@T$+OHU_P*y zLz!aR6i3>wkgK&S!|@HaAn;tEE$tIEDs@0_txE%jfj>$nmeuO(I%0GppVfQtxS8}{ zC_IbBaMijnM2jiX+L|%4=*cn2T5DU1TS=9CFg;Xt1gS9DEcTks?8gxWkyeHP$*Bbu zpj2`D)54MEgjj4wiF8Vz??=e0MhQD?c}Ti4{`w3eeY~o0VGe zd45C<7G5qUePGgkhhhy13mq3O`uoGEYbm-+#>c zOv^~Sku@}7Fa^taUBMKVdqF)T=D|f2M=s<|SCz#`sK?R3^4j;iYGzPuK&%V>{dskl zdDVkb<;qFMaZip(+EU`9%8~r_^h8iYQ3?wvr{ofU6`4qU)0$SzYO$<m9#$Hp?b2z>+l`129 zYgo^Y{}RSNIwMWkJKm)s>nt?;>DCReCr?FCmE0F-=2TA8NWI}0pEplqeKgiSaH2t( zhpr>~(XeI(qCzkNm6LHSskG8JGATFlFo`5y9k$HvL88Z|u4~ur%3NFKD~(%zcJ4O^|>`efnumv-qk<|D(;|DCuo-g&m_H$j_@L{6z7$bj`@9}PxMA* z)dQhj8}1%v*~22q$RPc3;DTz9@E9HEU7WI5p=Y)5#Av}?lJ?Hq zA0tdW5v-(@EhZ@keUg7KI`^un^6UKsBUgK%TAP^{IPR60Q3@i5vEjG;SoMoZL)gom zBhK%=%LAYN-oM+}hN<^I415Xu^Ku`F>nZ8Vv?WSh>=3`@X`JuHwf9c&5gpf$Y3;%L zNUo3&j+P&D-h&UtlftKy-+wG+41TRX3pr2n{<->g@Ui)Q@MZM<&&}n*Z(U~r+bl!L zLAQf1zB-I+=*d2`V(f%W|qtW~{DIsA;biQrIU`kf)`V5^pIKTO|}Pj@PAbOXa~-i~FB4 zb*8gy6jAR@zx3pdp_jVW#eln}dc((YtxTvm%bbMEg3!m1l`Iu+Gf?N#K6_e>c!CfD zK(&C6(KqQUKFSxVlqjaF4P#2{C>WjmhO%{#hmb_sxSWbMOB+&*_My4zQM9dg+8u~BB>>cZEu zKPd8B0;MllA<-HbFJD>D{>AEB$R@f{^Q3qI+^EOrRVYYMXBb8sM|uNh|rv zZC&8WES7rSz-NZkq`4G{Ri(9bPBS2DyADjh$6};*tKq$;^^RG|K?TgY$Vn4<0@0FQM^t?#2{kFc;jhDxoU6DG9HSuX3>TQRYe)}nXP64 z{DSb>7!)NDp)?a>`-BON)3>S`8 zO$S};vy{!e8An0g#qqb?oJ!q7-@_gjj#mAx0%3sI242vI5z0K%d{K~vk~#$eO68Lk zO!t;E9C6HsHi$Lzl(08_N8(y!N%;rqTMsW_q{9r;ty8#K3vW#I)EY^25v^38Rf4b? z%G=Mp=2`3J&91TPDp?VVdE~25nK@sn*kx`#f0zmis2`;_%5KwYU1a<8WNq$KV61CI z+GNDh<`h%BT2n+fWJ~^Dvp`A5w3pOECg9^AN~hnXjo&s26?Db`Kl59LkwrpMD|^R0 zw@Ou87kzJ0BiQ#d3$;wa*M3?kMjxHT!Sxd^-i2sP*k}8b;zq@2=HJ653%1A(7sy1qCD*9#6VY`} ztq4O;IupL(lv9$yYn&%*P1fuP4y>8>C*yt}Z1l~P$Y{Sv^~djO0X2eDLXcgW^ zqCB8NAFL?mv|5h4OlfzdIfkTPA4~IbyCxsINuiv(x|v=XIbmia!}zC(1WJFxOnzM= zKY&!G=eT~0Hvj(Y&I6F3J(lKy0SIg@T0WC;doM+o)XuKB&HV2+IMYA%ziY?Gw9hbW^C;-0nSSjWu zUyFUNac?o!LQK{C`*4&4fFi7d^aB$ah}KG)PnEp8UJF zBLLvHZLJAd^PM^I2_@XUx#r~Sm{cZ^+r{x(KNOH3L0 zl{jIH-Pad=PV#3D@=DbmL=f>eG^UD-6J-3|v|owYd{~eG!aGQ8Vm@Ht8s4?ki#YGd zT;N)@tfIJ*s5YvrlpadxS9!b?1#2Ru)!L3^$C}Ve)p!;`#s@J)I~Dn(2|HBewGQtL8?@_wx9Tuni}E0oam<`?q>UB{2Uh z?0jnAUTGe84IC^1D?d2pDis6)s#-2haQmFtM|~drJpCJyBv0vmXB^+HfGxw@jsM&* zfAO(DmB&AS{NOlIRH`zP|Ioe>zvCiMSJhBzdiWyh7%|m|Qk{P`(n>*P(lA-tl{Dj1Vn}L_Z{wxz*44>c)AQDfsx&tVSqgQfTpl zKbUyT<$ZU^S$CLy;Ugn5-~RV7w4U%-`CUdCe85vUQ%@wFsd~?Dq_{8y-~A9(7NXx1 zEsacoX44bn93TPscl0$Lz)lC}{n-DGzW(>z>tD{FgPV<8fR*>>L~&o&U}F z|Ea~oF~52Q9P=aV#3LKPgBX92elkM{iD@Dn@W1%qEm=6@C$UI{OMWD~IwZ#?M7K^v z&t63DK^(76Y~Mb7$4Xq+1~}%&^=JWmwEf%j`;Q{}kN->ckAgyH5yF=KDbNa9j|K6i z!8^2n^L}`W7S8*FjJp0M{JZ|MN&7G7zk>QN+YgLfegWM=h&@1n9wNk_{M+^?o**S( zAf|o>q(A(P`Tw(9``=Xm-vQg(zZ$mCvEZKD;GM1imoeLaoIgBi3rGI{Mfe+a!F#q< zPVi&d-!a?2sXyHL|Bd|Ny#GIYws6@059v?Lul(Ed|C6zWd;WiAY`gxg`kR}oS~?p$ zdOJEg;G{pXV(g!QZQ|Tm;?CCpl(GG{@c*0l|C6zW3;z!vKFlvHuB@!Uc|R732AuZ~ zdmjBi^8TU!uhCcD|A@Z&{u6y|EN=$=pXe*u|Bk-Cc#Nw55*zjM0rWzp=T;klBZ@@} z9bYl;i=k64RuTD3qJaqdX^7d|ezs65Erh)IzZkpAwze8*UDN>rB*EP&1gB8kp|}Kh zD=tL}6n9#j5Zv9}THFd0E$;5_T53p}Zq|DDde1sru5*6D{5G#S#~9E3RD5*MEkN}o zeJXu@(^tw9fb+Yv^>Y0+O00;yh2Yh8Z8Q15}e@9!eo6vCk zHj0&k#kziNhhi_;_Tt@5YU77P1fNP@t#?bG2CSARyHN)8^m}kd_YrzRy7J0mHNxhn zJU_6HZaGu1jsYTS{f&`m&%Z!#C$rNz|9UlNR+3nI!M(u8!U~H ze#yp=BoB3ClIG%OILds%A6_OCe#fBfWyijNBPn3NP%6FoTSq-@!*tau-Pql)Btw#P zP?bNNusR$X0%Z?j{mU;pjg2VnI8t_|WJE}YtA0O3PjlU?s&K;Rx09x*b&Eo$v%KHW zaVuXvkwm&G^Rr8PZAIH@nX|hq33c6yB60&>0ObYM;MtW>248~VMzh$&nsmMg2WX*3 zk7i{N0@Z<|_|QTbpZ-9u`gKAdyQf2WBX1R`q9D}KsRP}iZCR2`M6l!9&8g*O7a5<#X?N{gg8jE-7y60&x@4Q}5u@iA#Kb7*ob0iN{N=^I-w8aB>Z0(V2TA)OJEpkz-Ufd;C@Mec&*@@RY6JU#sb%GjxfB`K87- zjdVvd>Da`}*@lX}OpymFU-r#}aOvf(2yBS87+*^lDoz|oqbTY9h7Pz3d?^#S474|S zM(DEh@>$=t@vLto7GPBrVC9hBI8I;u`v*G~0z0(YN>^-|U*+`jMxF%eWQRNhDQ2Vr z6p#};jL%P@kR56FTmU`$^yrv3yOvh%9M$LFPwBZcKIf=~<@|6^TOI*p`n8+^SC9i& z;VPfEUMk>QKJ2+Aax80RFp{?eq~ORN=WrY&D_BO#1aPgDcL7!itNCl2UTNh4QOIe1 zGF#B!y)pR_&Y-jCJsxq>M2Gr^B^{MgQ+cY!3{lxji(ftCw^D7hKb9`RP~AlN5Ei1s zNhU_cBueL&nofJU@!T&Y9K(q$3lvL#UdK3=l&Ljb#q7 zjFEW>h)WI;NKPz?;E79-(4FI%pHflw}_MTDu4*-CvD-NHw8Ce@J28Ucfe) zJnyv{pL(l?#GfjeY-v`vDGe?EAL(2DX;p0<`Yxn4?6Hg|)v!evu@qqh+I*@?J{Z4U zHZTb)Q3lr>^-fOuO?)U<2p-KV%H?_FiiJ~EbUpzOSgLm05UBLg!*zPYx&CJpvbhRn zpUx+<^aD1=$74NN;uTg>=}fYr!Pom)?6w@z$#z4}<1Av`SU=9s`7k?|`{*m%zs;&g ze4*$;IGx0%;A$AeyClZt+t;q2%k|+U^C-J?P;DYt=vpeh_qh9B7<02wZj21v6KN3{ zZX8%Jhv4s^c;t89$b4n$GT4Nndi>e&(2F|pb8_|uCS4nmK#u?~gj}uGbv!L&>*X#H z0iOvMNt-gnj(&_~a^u{pcC2(?ZzgmJml-awKH3yEEO#?H6Qw7|^hUXN^5W>o%|Qhl zDvU0=G^#n`gGp^oj@Je~(F{?_{+v%&#?Xzr8#m<-%~$i3QcV3kZ#h1z+|m;h=~HK@ z6Z(SB6#lqz^HaSuZ{o^#{ng8FSKb*{lh;2E0yZD7+Iok-z5TuvumfttMJ1iOi6mkK z<0rHarqvZOF#X;ecWD1YaN`;skh`bd-~O})XmX2s-oO7$<9fsZH#eEDYo9f$J+Af! z;WL;7!i#lGnP5U7fd`(5=!;ym^h6V?DO#UUdjPJB zCP3*!d~g|G2>4Gs>->GZSD0MTnO@t|KsElh&gaiLCD#c47qg#FY{A7*p_p`eB7R#_ z=`}DbV3W!HS6ADc>%3oq(weB`N)XCy`bpT_g)e3#|0NRj=4p)*@Q!!o+B$jlSB{^pDHN%~FL_7v?|oBhn; zB3`xLPHf5PI+<6(l+Io)ZQu#C#HF^w^_~|5zyb0s zf`Cd8ToGq?hE+8RKwSu0t8nwJz+|@o$9bS4q%c5bLAJ{%F2N#+iKx_MUc0WIf9d>f ze|h7Af})2*)P`NVmwhSPLxfg56DmNSzuZ92&K6Jv81B1uz1lZ!C{)dF;S6K zLS9&H0aBTf)OPT*3|wuvH*CaBrQO#HGom;u7;^>htx}M4Mzp*zoUAee))!%F@Asv` zgW3-ND;bWhePnzEV(89&Hp=(6oqMiQP-0X_t9@iSS=7)|sjQ)op<>v&aLgYIL@wOt zGC34s5ua3u!jTB3hXb}N0C5Hwx!jnym8dz1m|%RbCwf3l(d+$)XS6UP#sI-p5r=30 ze)BG_`py-nBb-b)Zr3$L>o}3DJ)q|?XE`#_%p2Uuuc(0%bw-O(K^9^S0Zq-!+^rfBz2Tnn$>p}O0hUT zu`=?>LZkRvFfR!h{=slGN{2sJTU3diCmRe$Xf+N)D;<)Qv5^_1K#`h`9~#^76fwhx z6k@8~r{cgoLt*drV2K7D;i~p=Zw-^NS>U#q5r22W`R>_Oh2!ipvm8f>ovOTCL}Hcd z-9)*8ovT>6@)^sDae!#AY2P@+XvShitoTSut6^qPN36SV=CVD${HbdaMHYw-EhiXE zi?qOZ?FGMe4Y12dpQ*|=Y)dmVN;IU%K4Qy@^b2mk%f<;wnxe>2d4@r_nD964?~9d!-Whsok|RirV@g(CkJ^<24Du2j zQZMh=I95=z=tOK1ql^5!sgyEhf2FCk$CL@@o2=%Ncj8C4hyrfc^L!R5P4s`OV4S@O$|W8P zBde~`>#H&&FU8))E*X1k;ggLK5@x!_Iz3#izgrCp27V7A`jzwyYexrL8rU>eGln4P zK>(Y%u|;|Ty%t!2n_3YIxAE*ci`iPh4%!_(7Uf>uN_E|VKgou_>tXhXy3QoiyBhY2 z4>u3Q$CR#LjXx^$e0*>9@u9l%f-?5H^CRGqXoC{;lMb7b5H#Y7wqNa98RaW%NL5J| zgf|rxr`%QQ~M8y|`50oTp>{-QkUn%VziyI+Bn2mWe%p!d_vm%Yz((uF@ zaMtnos0i8CgFh1HzODc{(}}1@Cqs$=7Wm+GvUg0!-U$^N!b%Meb`8eD_1~qidxD9m zW1uO&us_wem^@-l7siT_d)2pR`H>e68MZnPKcn7l)HI6GCG$5rDKQlCbXbiPJ8qJC z3>k?IdWLAqSFD=;Rr<)@60C{6;n~t)=RNBRkn3%ctM`+69;J31FhCLaIr^z`wiVAP zKZmVBmZ!>)r65wVLGmed^(!a#v~3;KjzQm!GLC;a_AW#UPa+Z20RX_o{9@LzB$u%g z-$c6KAyl6rAH$5_E76SxNiSg`e}c;%pI%-wT~(`op^opFk)N8DMv7-E$_%RmJdG=w zmEPG_bS)}{sk8QU7L^H=fbw1B3noz-cBb)*O1)y67q*dXsEq?}i6{oR@SOyOi8wP!%Y;qt^ zH>^m+_y1D2GC)e5XHJnr>BK-yjk1G}1g5SW^U@;kiFJ_SoC z5v4LpDBzt>?5F0KPd%4 zoiU25I%#W==K3j4wPwP4HHE9qvp@(wxiY#S9;fo?U5GV4dEza|mTha$87=mOSNKb( zc%I>MUW!uc&)QNk5qSB^#D`Dsi@SOra*@?tBaIYUlhoJ%15ND6#QL^-cUjk|V`?0U ziom4x*j(0z4;?)k%aORd9qfp{V!t5w3xwqF!MO{+4$99(CNq68GZXMMQAo)A`ixL^ z7)Na~A?N3}#O*Pc7Su2!xX8jMI5P1j=4Jw;v^NHLp4txVh8tpr z*RcU`3v7OzWLYU7eE>j|2G}VAOv>&L8+$J`S<(W@CEtw>a!%%cp69$i#%$^XI!mOe z9#aZjwi}LiFdD-`8S`^qD{S*7;G7}ebhQgw0@b6W-=VMHq37;k_>afkc9g_sB#yjk zE2%6goAiYn&qYj0)Lg+v3XO^3B#}Q_;i5(b@xS>uZ zH%?ffn=OHYXYGzr`~mhX{_7q)<@GH4A}fOY$Z#{t?x9z6KP5cL*!@*vx*bP%rO$R{ z0DI6ElsIu!e=q5Ay62FGQ460jkKfO^j#&VgoHu9js|vKLJ?eUAtB&7`O`h(IXj1w4 zP}c&uYx|7nsh0s`_>C_!VoBY+mIL+X^FR|AxIM!i3 zcD7#;tzOg(06qxQf9RmSkVZL~hhBWyA{u-L9qzf{Pr4B9znH-#nlf{nHM`{Cxumzd zTzf&ddI7#o^tii+Tw9=J#|KIrpTc`C&)!A8#{q01s{nN1TkfmFd{25mn=8p@d{rI^9$tV2G%U93jnkF@rH0! z{jb@U*XcC?4@rso8K=4)6xfUV9)KsWd5z(AJ$lmUUyV=13B|Bm(Z#Aea;`MW-XJ9m)l=ueGUj5ekc@B z`sVeIS+A*b^F|Qy1E5%NR#;8tX+@ynD`!dm5cgMC< zo_hm=Bey-H;Kg%zLsnV$Q`jl0zn9E#)|5HY8=`_eUbR|1CcKDmt&$|I`HVv)r_$HjWyYt{SI(Hhu^M^62CCsF z5Ns?}ws>L@-#lXzjb{4f3Jb8?XBA3^JD)Tn zM+RZvPejNbi%QpTZ=QU5%r=wJ`LC+-HRjn9_S_~TsR%f)u0NmM9Ggl&y!?NbzWztN z|0U_=cSgt6o``X87e^Y|u3!D1+8o~Yg$(1-;_(Zh4#m!kL~>*`9!;QO(W;&h-=56o z$00Y>7>n%1J~E^`D$68oB6J3&Zi)L&xy$??oy&Lddtod?u~_V)c#=RKx&Mgwv!Bg0 zeyD3(T6_HoQ^;L`t7nR#p6i>FlXDS7$ML%P3vG;3`a(Fi@iZjXgi!wT}VS5i3Ps60`?A3 zlF-Y1sW2n1mhK}JpJpmJIpfKF_KQl5fS0}LqmsO!tW>0$LW*h<_ual+3hC6sDO;}Z zIZj2ItG1j9P>7d>dEQ-hVv$m(pH(wCl~v~! zC0I`y^j>DZxtw{SlI@MrpNh5jN?xaeYu=ZdhEHIu@ZK?8?L5bNa}BrpWma1IKD((7 z{zM$;N4rgmh605MqUIC%zJ%q0u&w2@i#k0NDq^G8c|J!XhiOU3UR#tl$P-3e_$?Lz z&kXqKC9wvz;gl|~DDQL>d0%duNlgy;LJDY{LIKwdGk?V}3*O$-6`aS5|9qcB+Km4& z&#Rj6WE7kKPaJo0UcjGUZKjuP?X!x2lwICCHY*=rdh>fE#IvV-WtzP<1`o4PyEkrx zON7e`j`np}64%?+&@n6mZ2<+Rt(NW?+CqxXpic&nJ@Exo5lJ&dpX$w5cw{_mOaS)_ zk%2t7z#h9S#f!2iT-H!%u671CZC|w7K_A+$^JsNkX1ZklAr^g;xb(<5qR%^AmKHK; zP#Xb43|v)njBncEgClfY{RgjU!}mvvqX3M(p#;BzhyE&Ma#T>)`w*2DXu2>eah5Ym z-OepZ&e2B%U073Iqa^DHhoHhF%J>xzG|IJIt7gTE;ZQBcbpAPV+_(w70ftxyTmhn3 z)<%wNibN}WkLO7@axCWT>KTRb~J!_Z%fifJeu+OXILxw~z5nD&%7% z9jYp^DSIn(>S@1Gi#%JE+5^uQ_ClFCltYGRMJ5xvi17Gf(8*Agw$ z%YD@myP2VaxeFzs#h6KQnr8XctZ0QsMuyD9P?h!Z!)^j+{@WJOf>+Z(OX|=N>;6Inz~!nn@TyNkO+iCjYt7n z4zw(!JFNiZK%)+ze(Dhh%^E}h;Vxtv84(b#M zU?!=J#N~|bY{;&dCPOHRtUF23$SuSS*jRfbm;A9}r#|EF#i5mi*rpHx-&;0M^2<8ZF{%y9mhT&{cZV0uWBnSdt&15iw%W}mwbpJT?h zVHWax{S@I}?!pjc6k8oLc=tROrMK0xeUj64z&&$lgP#-2Wx`IuBXL}{gTHNca_Z~N z(U!QKXbjU-NsUMTkK8n|eV6I?82of`Wc!8Q1_b4@o2Tg^o?ady_5ZwtUyu^_IQ zyz_4+IL=aA_fs>GN%&!!erYEybAlrKkaL-z3VI1%epAI~k8~$p_abqu;3l;m=q8?u z`Gb3w!cuwEgJNP99=l@@9h_>g_hY4~RA^R1&GK;1cjjpUu9P!FZbO|4r^RIqbU_sJ z?=z(DoI-|Q*ndrx7FNs^UrlV+V?zQyF*@MGW69CyAVo5JYB z_@u8%oIVix)zz5DR!N!P{bSaG95o^rCCea*~Bb`&rGH!d7r1K#T~6 z?gp11EOo&tmSYwrK-^Wwjr98}hteFS|K4+~EltEd&l^>?F2)HiLr=@tnB$(2AnKvr ze4F|wCqeD&e($6+LpQ0mP}e=d57N~UMSr$z&wB#Yg?&Pg8%7%T9=5kmq?NLBuc>+O z;n5Mv8tKRL(uqloOhZhgD(>v2DXWa{#ZPnAe8W@!u4;a0ch>qa6+X-!gb42MH#SnOw(Lx zcKobaX?|EIp8la_arIWwWb0{raXp{4mB|Mss)9S9mJ_0*dkWw4Lk>CLSOwu#UWwh0 zXwQ9~=6(&AQl8~*)Of~IBbMsp;}yg|zVD@J-7Ep=lz{UwrYeU5o;LNJ6@O>MAB^G( z_CN7e(H6L}N7iFcuqO8vzl;Rn3_NH1>rbD1_Oc%&Ss2sCQ=B9lS{&>rXsj*vg13bh zE$x0j>w&2H@mtF8oXS7nDo6u4SB$X%;icH31qrY4&@R9whE+JcjM{#r)RfW&3<$~l z)U+J%dOxx^Ag9{#9M9zu>+v-1PqsK=GnB|P&S!v-h6-%LSHc?m;wV`AZ5C)L5bPS7BMB>J?O(rg7;< z<*1!GahU}$rV)#DGk1Y~S%Gy!QeplZ%MOj*)E|T#8+)Y#vVg7ZkK}cM3;Ny)MzbbM5T@$qyh`1uXKqmM8%pJME&oD zOOb~4NjcG|CG>pCyEbq+p>Pswxz1P4^y$p8vi6d-Z@C#b)b^BpwfLh-kVF)N<7g&NUhJ2 zC#TcAjM6X>KtbzYQmxgpyU$n4KM^LQx_R1cK!sNc#vKlajHtFsWHH~uI|iN$A}cfj z-0*M>Y232kFbWv~=@>|if_g; z$IH(a5ZR7r9wTFt4XSH$ZD$itm+%uWDW8Q7DDQrUl(^F%G-=NRvkslqonwS=r67g1 zh;uB=(m zq;d6oyk;F<>p}lcBsD@4d*B8?=Y@DzHMsCbRhAe2e7Bx-tIfQX3Ot4Qgf&Xjw z{*2_U;e2i(&f6xYz3n5(%`PaFHJibcEe*}Hjmv%X1T(>&@HNvaL3gWFjni1y3PH^@MA|$JYUdC;Wy{RHF9csSs<&htu#@Opb1uPn zLCm8)<@g|>M7mnUM9{4oMt?aee~s4VG@I1QH+SsEReWNb6#Y2Eo>TP-*P&v^X{pN$ zyPPVux~wJcVJXYB9Zl^bL;UU74#fjNV9T=mC>qvfFw-7h#N7fL0oMZk z4wR0na=xcuQ0xx^OHYj^5<8`e(!n^HVfMP9pj8RvE6$N6sX6)1uxYndhj($A4`@Usc z*kSu|aT|Yh`_B*alauYgBs+)X%D_wvXQ>_FQe=dE`T|^lVJ}=|1`uYCra?aN`=F@#T%V7m*4_1qMfT=kg*7pVW!!4;!Le*5^x%eaSCPm84Sn5P@1jX zpcOdl&Mu8v0_IC7Z=nSi?$Z{q=WtYPq424_fSr-xD0TMF#8Fx6Yif$yZ#ZWrJPF@2 z;Am6txXV286ZNVr*S>NC2^GM3fIYf&8UOP*2LJHU${kX2m`sPhM-v53 zNi;PKTy?vW1TU;0U!b5G^)og}KdIOxkJ9AX=fj|Brz|2Ar4KHNL({haDol$;4hpV> zGijqR$XIFVG+^dFwU@PU77@r!C7 zd=C)B>c!DOI8TI3IY7Idy##TBbbGBEA0oaIPPAfuv<{8iX`l*4tcD+cE_|s*Y#m_= z4>V(QUplM|o6H2^JI;W7-q}&bA4iOp^a_BS?HT3mOOv*um^6XHOBi#xy;&>!L@Pic z*Dyy6Lw(Yj_ZF>T@db(5Wv-rO#x5^7Lr?*3WpjfVX+6+yIG$E9?07#Nj@^u)*~|;%G(m+DrUZ0t){f&MlzL4V7djLw;yf# z;&OVCa|Y)i(6>Mu>N`mK53P`~H-{$Btk>(FulHEu*QB@lvPOD2BM$(KtyeFwWE(jTSm_c#=hV?6aZ{;aa z)e9H8wMyr=`Nb$GCme$0vazH>Boqy3277|Jzw;WBT(5mz4*`urAHQ7xei?dS{&rsg z?$Eodp})hrb8UsYgX(jQrsz7Ze}is*hT(IAR4|u}aRo-*KqU9EhHp@&R6k2K%c*SP z7;NJXcTOH`ollHsRPpzaxIN^#s)ZF;G8Fs(U(?E0=Qo{x-QW-KtPkV^k-&k9UMtNH zuf24>k~x2kqDPj~(k;6^P8poXQE~~!M?e=M#%4KM^^$N1Rs{oFxVat5o@=<5)0Z3C z-%=6?`;N;T*i6(jCw?a|{$aG0`3Bcvy_Idf$w% zSTm^LQ1*sOKMvv`>4ILc8#x69(oNN(Sfo;pJG?V*K&)4DW*u!F>neuKGxm^rH$e&W zP2rS>FXMu%5~rW1sUs85nmF}e4=GFwa%*>)_YkoN!C72!rQOuI-m5%>=8Agp=QGD69Y}dedn_ zt*QuE*=K()jt$^PNRIV?o4`@j=ZOl$#zeO&|-VnC>@KK&^2ldZCz&Ih>O5hbNjT9@x6yMy>7LdL-pP}WD$Y(JSfRO zR2elz6pwbk_(R^^S5|QF2Y*qPc{Hry-23GZcK2j>f)LTQ1)!Z0$5Zq_9@jzABKc$! zzXzGWbN>bbo~aL4`Z1|DTc+_xCP}LyNQNm(-r#@_4!m0vD#Sh>D}-1g>LB-8U0H56 zf%tvX7mc!kOZ{&f`W^nV2%yeUe`GcyoSUwYFwk03^h z7%&rA9V+}`fFg_BiGu>O^krXe$olrR+c25Xc947!7c#o5*8!6|5Y`c&3)RGgzyDK- zqnbQL9qRfg6F)bU4uxDbm)Ur)kkzD<5rnULN~TVL%KV4;50NlBqkuf(K~3eC7Sn_) zxd2oNc5AL6Pon~{X>{Ai5Xxb0mA1g$)hH1e_{xvzVXa&W@{A9^zb=!`|LfF$fjs;1 zeC40g*Pk3~&5p~B&gVZlH`>io=H!EcfUPe7B&XlXjB8DF?wCXhkKbxWG9t+MTrTc- z4n~q$bl$xZIyLRiz7O>xZRfQg2C4S%C9)C2Q-jew9`{Aj!*JWGu-5;s#2k^?gCh$I#Xol?S4=Q+!? z(r51QEDg_bx8JPJ9&&W-)r2sm$Bks5VzJa|SM2=Cfpf z!^@FWKTMNOGd?PZLV^jRODt*h$zp9k$WfUR8NR?5YD04HQDe~tm$0VSl2UI(ij6nnIzhORo za_i?pXQ`zIo8_F1p#qtblsHs-8aV20Ajo~Bns?{y>Ouw5j6{xz6 z#WHN^^;?sCieudNZNzyda{b$Q8uR;{Etf3AOJ=1bj?(YRCIWdZ0zo4 zvW;i;AEl(JY!$xKl$5UJtyV?-YuQN=n6Ou>GDgTDvP+qR8AvoFpoJ%{*ZhmIJS)LR zK(ogx+d8FhMi%EfTk^17=iDLc;|ZBN_F*I{RDEn-k&uf^udai)Aw{pXG08{`oncQ? zPPBYBAxY}cA7LNDd?!G_TPcU)N)BP}O$-(+t74?k%3AatU?^!(_Ga3Je597)buv9O zI9;EWG-TposFTyA$)!>v#uP}6xH0^* zfr=1P_%!2R7Rd06raYOgNowTgI(xd}+3ot5KXs8OSL;s5-H7hXlk#T!Ny`W8g>Akp zb;Wfo4FgZq%+}zxw5P;6zL~^&6)T!7$yJRUw|za4sa{^318ZPq@vSCLb#y1G%yqCb zF10XV4;2Kvhlb9)vPKTVVFiU+ZlDojQ*r&_1nwbf8dwz6i#HwxN*G#NT8R3cu8;d5 z(JEj(MaMTf^(ZSWEl5`TBjc!25(m06ZIkY}zbAvn*rk?eAOz3y3HM)Qk2jAsS%rEI zIsXi4c8AI-wpVKMk*N$y|*50cBFW@?bm3W~%8kPG)6!Vs+nD7bn=_uIXRB zL9eqznQy9N=C`osKqM*(rtbyHod_l81D+QtgB3YgG>!L#XCzN3v$EcO=V#~eYMZkt zefBjn@vjK5mH0xb%beIby{n#zsNPmHR8ijlC)BYYW^St2{-#CS;B(yqd6BoI+7I1I zP2E(g^5oW-`pQZXWkZoF(b`h#AulYHJt<)MD}7@DHdi{^65U8$d|dwbAI0G=qQ3nD zu}l8uCf3RiU-+E}H8hb*D$n|o{lM`Q#kWep>( zN~FVQ<(;gWwFwt*RLsM?^%DytqU}pya`WCmw%WY0m?$OF!!iaJ?$Z%v)t@PJt6bRx z0=qva*j8F#9vX@`b>GD?`AHu zWJe;@imdiI{c>c_LOqmhHY2!fOlT~uTv`6OxcS*@ zzfY15)eot}VhO_221Z-G48mU{;6WioF7+dpn#;$G%|>x!xsK^?CDy`@Tp+wmyu{0w z2IbgaKTKm(gbb}3a1?m-`M+*1;rxzpmZL;@T#zQIu|K7!`ygxG|JA{HPjh0)VWHB6 z=Fy34QeWUS+p|^2q3O5M>Ja79vc5shYZ)~;3HHS6#w+d6zyk$Zk-+P{+4SQ>gEahh zdvF7TfT%+$EYHC_CNw%_Gh;kYH+9)Yk6owHDb+2sbjWMs`m}#M$Jo|%7(9aZnRO+^ z^_z^J_zcoFwIlP4X5daAk*_IAurvAT!~o=m6WA%!i-o`*-8?s(MI>< z3Z1Rg@-kv?8hHvUuMPE_))>Df4Kjz^auNT+w#m_ajOk>7F;~o`I=!(mojfF4i0CBv z<)BUX2`kEIu`Q7W6+@$Jp}@p7iUf99D&1-?_1X1?z!%0V?xLc% z4jRl2qf+7HkDI_8a(Pt~WqfCi+EiSPSd%(K^8zXGm)ZD7KePOnQCQ_7{gCE;(Lyb? z$pNxK(Oq*3AJlhfyA`&h0LRJ86gR_~q8l#4dV7b9dx+_)2@YnA;3bzHlsDmbqQt3I zfS6*Shc4A;@f(UCX&7Qhb^gv{Ia0E#lrC@hBv!gut6 zh0!(SLvMemQ}#~;6&6uX(bE)zs8N+@j*4incHNbBU*FKvVHDG4M?Sk6qN9aEnfEM+ z_qDK{4g#?hUYHo0t(}YmohEZ^o5?rjVnweEjGGzQ`m6<#hs1xTDORI%^p9;jGxS8q zVoMa}a~4UV%J6Ie0IUo$$mnT6Tr&t~)@F8=adMtp4Z%H^SR}7dF7J29XwopW+iZRY zz`Z5Flq@baXk~zmXc~8w$~i+`96?`99jNaeyx4+j^sCa%$l@`|yZ|B(r9&;v?vcd}4y4yV#rGfXw+ad~oG=PfD!=5lHpVD5nJXhNE!I3c)KwxNF-o#Yn$OQuCZl=M=cZa* z_1iPa2Uko`evEBRMvGj8sd5Y|yns;DCg}oI=nmoYvn(=w(Jr}zXVD{_yR<(8i64Bk z1JsDoUN0!HE$X|3J0q0HU1bbTLQs3LWNy-H+hdg$El&LK+>o@`!*VQw;1ahFB$5z) z$?OBf7h3{!CQ}7~@L<2!Ss8po=jA1lg?hTATM|a-R$SsSJk7YBzkHTyi>7;4z)x#* z;uu(#tI<2xtu+L@Bi6hupp(!L9XZm$KJjlPtc9)PJS@@(#90AYXCsJF;Y_Oby-YST z*mS)Z{Qb-$QZ%Dx8Ci!T2iEQo-I(~wZKc#YVHO0bW6VQUjQXAl)SB)tR1>Nn`9qbT zpESaYN{yjr z#A!sq-`IRAZ<-Cwv{2~6uM_gv4XSX+ykT`X_Q^J~IJ2+i2e81+eoK|nZH=J-K^%j? zh{1J4be3^PQWi`VNDg0smEx}M$Bwuq*OEU9ShR!71KG0)LD2@0Z{U=4&-2|-ddUM8a{r} zrw`#3vk(s&urBWDa6@br`c#bby5jfq&oc8@v04`LrcLx0`CmsZGqDYPvAPJTb`0sL z%2IKv^%?XK&%IJr7hvJ+s8}|kOr?%_zDO0B(^EO9-SGY4o87qNP@Ebl*UNy?0d!Bw-bf2F6IuDcdT&xF++815pFqwlsb*aw= zPJ23Pwd8JA8t?mj{DE_alARod;g#}n%oZlZc&nNJg$Jtou~*S{egPH1=5d;tNVVLL zg(S?NbgOpq&($#}$sa!Mq%u~itCMr2vs+w>o0GLxQ|IX$04Sw`2mptf{EJ)8eFgWU z$*{E}4JjaVubg}(V#j$E^wL5C*WUYSj1~9>|TU@f?D8_48-pRQV3Xn4Hb( zd^;cA?@I)`8+_->jYF{2z#j{I{aO4oZj&`eqlKGStZM;xCO;uOFV&&He#(=)v?f&_ zCUq=y@v|)ca^T7wLC`d$eoz>w%fQFWV{^kzQNTkv97R#VL)G>a2XCMnZlD&!q@He| z*>-!oz(ae@^DHWo_7@Kw=51oFYbdCZ{u!@jZ4_E%*vk{NmnSj|&_+g$Mgu}#2Ju@b zy5q6r$~ZYYPMU_BLI$P;cP23&GZS9MHbs!oKA((rl)ZeJse|m#g})*CBK0q!RDdrFS)YGywcehiGH2Z6dl6V`(dUPhR(f??^T3xz0j~gF_v+xzT5{N?$xKuO|*hA8dYLRZth!Ep3i|4VA(K zp|eQIKxVd7#JB$#qF1K7iYa6`E@A|_y)sIVC z0uEvNXK#w+9$nJkQ#e#cQm#rz-#Y;_bkD)ixmfTu|)W%luYDdrR&|vGexfX|AeE7jzTi}3Gzh2g=V;I39VV*hB+{d0} zuw^MQv|2E`NMQ#I0t-}E53aKH8I|dbNtSQEPiiu()(qzll_9KzNdOEfG&n zqNkD&!jT)Ua-5#;YkY8`68kQiKYsaXxuJoykJWNA+M`MS@O@fG5AybxPsIsJ@HKH~ z5KqW^EbstFC|OactjC_VafT{&xdY`3Wrnwf>WKG3N+x%oJc*y(D^YkwWcjrVf1K6I zgO64UN54%;vVZC%V;wUg?Ef&xpNp0^c(;jtO|>xXvNAW%DrCgY^Zn;ta4jaVR+iyf zgkSa706IMuWMTgd26dx#=DGjDgD6SW7tIY@z1ken^?Sc=H=b#ZQbbObR^{Sk@UGfn z%aTvVAtf-(P;c}O%~r->rC=XL|+-_vazf^`JY4Lp|J-QZz1bW1iHc{V(u z`&|Qa#OCzjco<~m*MS>i#;NdFlCHjOOL`sgFC|}}*@+LwKv})TN6xtkW5q`^0{`U} z;sG3-Puv3O{|C3g!Nvc76BjVJlrgwfFnHAd6&Ems4ADhi{g=C71%0W)BC5xk4p%qO!-CI0UQgMH2aWEfokWf(pY+Z7Tyl>8$x{J$B7 z!6$|RHE0^!fAD{i7&K@r{=32O1TgSU@&>?ZY2h*d&D z6%ol15-JcA>l7D{q_rxuru~;;_}5@KQ&4Dw)BYnabjB+Gi!RKR$gGuWKhX=DrTJEZN!vKR<~_b{};M|%-y)j-9Uco9r)j^g|V@*>FMeJ z#x1zY)fe`K#ZTqQj?@jin4BBqZ4;qm5}`NK+vePau|Fh?8`PCZ>?Kzdp@i1U)%yJcWE^iyK!?l@c|U8z8V1bJ2IVUZ`iL0 zK*?}TeNBoomJX&BRsGfQAKb#QKm_X)ers>VLnXYI*e+VAZ>R7#}%de`f;u&x| zr)lro&HgwU8`<97{oS{7NyERpfBpb4?9JZe{$be(0SPKv$YL;`?1UAgXiD*p0tNum zMEbr(3>1Q(-6*=FA85Rvh38awWnvBYqS=x&4dL8hPKkRR zHl5$;>kR8J(Xv@~%2~`gzW)PTK%~FsY0;Z}N+9Q$bk<3wo`e?qP@ix9DQ2L84tXa- zH#j5dq&8?t(IWn|vfY*xiL*}+5^*|_IRB($XnBabsc4vtHj3s${?1q%;O+G;FaGyWCK+qp*N; zLmYcdt;pZHT=F6(6LdApEq~omBQVQc^}Jl#?6L$q-^t@#~4HN+iIgo6C^Ox zNqb39I=gmhGAs4`c`KxH z3o6%MbD69pU?}^E7ZSL^EVEq`w1FR`n4$?76F8DAAsEDA%I@+~5XL8_kTQn`Rbxt! z>?SXw<<;`0OpwH`f4+UfvHwH)+_>t>t0S$Pyicy;u6}(XeZKO*}u0R*Mv|)mStiW%2NW?1=fkAz7iD-ipRN<6{xWti70x27v z(=4UE&_PXJu#=bPREVpBXwMNlNJkH}Bo6YaPi_98D;W4VHAKeo%5$vSK?)_1tb@3L ziOMp_CN$u?-&i`mE4lu z3}!FC_3USUBLkcSXSAb1s)Qz7AqwkZDiiujhWnr#LW~H%fBXuLu5{Q8Qz?P9-4S)` zQ(fBTs3jv>3}ef3gBKk!2@as(6Ihf$*rv6mH<)4$7NCF_N&$!paBUM{(10dN(E<)^ zLKH2SKn5gH3KuMKjVp7+w$?Yf#;vk`Q~qmM5Ve#?e#X*<4)bL`1vyB?B~q1Zlwc$; z=?E$i#1#~DL?alf$VN2ue*_U=Bqe#XnPE^5d+QqpN4csH)~Rqy8Al`?iJCOewCHfkdL|Y&lbT*=`fjEC}tO7|m%Gqym7jqA8|mu|H5C zkuE5n71i*%EwOPCDf<-Zh8iwVwGvxK#bYeDgtnZftbPJ@7(ojhhl@AGuKpY|^6`4CzNnswk7532BE@sWn(yNK2V&2QJl;OmP`jP&tB@IK7qn zH0!W|PRy4C>E}W6m`JA9PN_)s{@PNd*|Co~!UBYlDpfa83NNVA3sNma}i`v@R!WN6PD_B-P zfdYfb!4z?@EkPojNECo#6D+vumj0WLZWRk_B?c8**;Qb>M%Tdlgr9Zgie0%e#BmUj zzyhh@ij7J%ymd7%Vbj~u1$Rn4&5E=tes-)*f|P1)+m$U0W~@1CIrcNP#G} z{|dWc6(lyve)Hg$;A^zP5hMyzJ|RL2M$;r}Ifw?nVLHU|Wln!KSDD&J5D%i@JMJ`f zJ53^k-^?sW$a$%LoeF z{P5VOTUq*ADPyc%H`5Uz*RDH#u7bECt&=f`|OSCeQiATVC;)4?N6kL66eY10Dl-azmEDjMlpz33;bT z7W$Em?dY8%<=}@D3bOZ!K!F|qsD0->^LfyRe(-0i1?mByg@Cb&t1k~pU;Aar(Fn$D)1q;!AAQ6EOA%5g%5a#C) z=yx&9vVIT&1Ew$t@OKdr7<&y-e-fw;0GJ&DIDiC5C#hh1^Uwr2aez6o1-JkXwuS)H zH!Dm)5E|$R*ynu(fq@@!gbu-h<>!P9fqtS;11uO3CWwOZcZCo*e=W#=1)&Zw7=zC- zgML?o0DuWOXe2zCfD34A4oHN&*LMV=4%)|e+{X{t0DO*64qn)Yr=xuYkq!KS1?*6M z{`Xf9*}#Q$IDhJ3Is_qz2rzrOB8ZM~f7wtDxx#-`XoY)+euE$b=@$wwfBoIDZHr1DNu8hyY1Af0;Oc_ZN>ycsktI4+H@P>L3MqR}R)FPsE6XiwJ=n*n15LjDmQ7 z|Db)p7mw(75Nm({A!rbsFaoD&MOBCZBTxxj6a$Wcew=Uz%+d)U;0S17MOt|NkIx8( zb;yqdA(0dbk49*Z$>@bJxO=nbhkclgj=&FHcz+2Ah5pBXcDQ}r_!HlFd1&Z^^st6Q zLVBhL4yJ?4o+8hrw77iD-mtnRgF)jQn_-jsSyD;D~ov4wi_G*T@c* z=z>q_6HytCfzo`X_Xs<-FKD=`FjQ-h_(L5jRv8O+p?Wz ziHAJNof0`zwTG0psCS)sg_dcB>#3M0n1YU=0D>S@oFD=rXa@?=g$SSn;l?a&fQhI{ zleKA+mxz|>8J!PV5XM-YL%Ek|S%+k0n>rbsLou9aNF>ci4#|mtj>46aB`eQqeYa6X6-hHJT<2!VZfiGfU5eo)Ao2>ORNiJ<(ck(`j21+kv*xtIm90E1wk_{j;S z@B(D{0>QNg0!k3TS(CzeqgM!NT2~(p<(Kc zV~U1YS$b!Rrpl?N2$6TtAfm7*r@rb46gY|JfTGsfoBa5QdzuB&iG%=ImjBm>NH~bX zSC*sNk9T={dHRXzcQFJ}2Z-vPn2G?0$tWngEmfJNH?emsp$ow|ik| zpbnvTrHY<7N}C69f0kGfVEU@CYKCNbb_~G;yy}i&8I}n-k+B zw8sypDuD{?os#IC4r{188iLj4t&5t9c_)g?l8TN%{sMv!Zt2RXc&Gqpkc-RmuGE-~ z{MVQ97<>AIo#ZPK-YdXc7{0tW zzrn}822lrA^sW!F0B3LsjjDphcM#o2jgo`02K=HSJACOoz3dx%)G!Pte8R>s4Rb1n zt;&B6YLFc)s@7xBVpqrx|VF&q;l%D@0So%XoE58=S>DgqFpt`>}=QaHX8 zYr7#_bt61~)^Gq!aKcQW1lF*^V;PrBsI?4{!yRG6C+ffbs<9PFd%}6Ps@kW<2&Jrg z5DuJ?Z9IjTy2M~v$4-2{lN-hBtE&F7SH;E941`<^TFk`~sCy8L#(W!lzjue=w|yMk z#{Bqqp0WN2Htp1D9|`XMg}TuxIE>5DSn8qhJc2a0dJ72z5|}F8~Uq zfCu~8pOjzFW>7D;;w3|q;V&})THpS9+07sAn_Iw0~ET=5o zr{hkq})mnRhZ0Dm60y}J7_R}4$KCjz$`N02r=-V zl`sMsO{{%-jiQ<>41JJd+_tqD$5{u@{_+H2Ifq7w1k@la&7j47yU$SC&;5`qz{-sQ z4T0r3mK6KSsT!Aa3d8f4!KsRudI^C6Thgj5jdWdmu*sB`*pz$cr!z^Adir;+%Gaf8 zwRC;02!M(HoTo<2EG=E6n;HVe3Pz(|zr%)t+8sC{jWc^8cMs(U%i*VKsDXnWYV zOnZwglyiKAMC#M2JqV6K*@DTk1ktX)lZp=P2`#C2<7!2FP@u8r#IX&>^cu;o`i}|e zrD&(ygu{YaJ>0`>4NK6RUfGUZU7OlBqpvx|UZ}Qwjls!He{bBW32KC5Y^sT!$^WR{ ze+aU@tapCB&v`8c=MBk@m@9~VqJ%n#UY(*k8sC37-;|Bym95{7um`Bvs1BS52`ba- zXW(sp;?SzU&`OXID8@$1omvt zX}$ysTgLl5dqtbv_c*{esSdY!j1kEXd$2ul^8Xoak_8>nDZlN}vQMJPf_wj$3Uy-sg*9oyWar@dmnk0n89R+uGs@vUk|3 zis=60FC+4Z!ytv={nJ<7(8`Zu){J$@M!N1$YpZpX7_p^F>ss0yz ztoOdmfcMIO`^>+5&G&rKr{No(7nU!9%^s*`zvm!b{dRHv2&jMz*boTNm9paa5!l@a z3E_>5z*G*H5m5tnkO%ww>r%Lu08#GWz<=r-9YlygAwq@?5ehWuP~t?26)j%Gm{H?K zjvYOI1Q}A~NRk&7oFri)&2P`KVMZ)rL=_mV@djOTVTi-M)nzSMFT8b?x4j zI#sX2mwll;`3bHjfK)tn8U}Flkx+?Cj2_L4U}@WfW+O|+XqA%)%ox3b{`EK(v(mC@ z(MEM-8SiS=tzEx{9b4qyy?$Rl(HYMNfWS3(_Wa3{u|uLoksjQekm*7x{02HASWYs6 zYy=}_B@9h6L!5=7#l)jA98n5v`( z$ri{XJx|V10JG{2`o}b=6f#RPDA+mZJA|4;=pPFO8c4d%sv9V+)YJjdLfKA4F+~+u z*&wjO#2RvXDbyxrHEnP^ohGkph7U)uFCIEcDR_ z8+M?ysv#HS>C!seiKFg^i{kd%Zp?IE*%*}Sp=9xh=x$cGzCmx*+3M5JaGONrH1YfMe;1D*7Eq#kqh!O zH9MI^G+zXUMhM=2Q49EBt+(cy(u5UW7&qQ>bi%l&}0%l+9L7_T`wD{fZ%A#{|nNP-xiL%`t->8nZmpMS$PRXsw!^b&1Az-;lY> zJYLnZ?z(i-PtWx0lNSDKFqvpNd*YfZZU~xHTNRRHy5|O2Uk@45d*77(9uJ}NV&*d0 z`H;ON1cXAUL=+elXh=L+5kS_CGL^zRT}h3OYS5>fB#T~w<@WugKM}I`>hV#BKYsbc zQk}1`U6(y=iYa2^_Q>*zm5>aDl0yCCRwxNxIsS&H6@;uIdB_{q;OK)Ut;h!rkE?;T z{)UnfR045M`ko^+=OEOmLs0xk5<*PYv#5D)AtnURgwirPN6pWMH^gD?RL458VPYow z10wB^V>?!nW@8Hx8A2=stLRLJLj!?Q0vE_YM>z0!E{mYd6o7`Ck!e0Lu*7?Uror(j zB?Nm&k5=j+ndbasPkK6yLe_F2ekk!!kIE3g)UmW0KCvk@JYNn4Impu0&wiYGLM`a= zLm=u;h>qxA+z440BO1{mq$`w(Cb>yYPSTK0x?dwj`ABF;vXgPCav!%6e1H${u#@X=%peP8rh_XxlCpbY?fhbz%hIQ0A3^m z2+^EoHLod6wKdb5-vnnk5mrAQCPNp4A;K-sS(9{{b9Ul{XFTP(%x5A}l%t$yKJ~dz z8`cv>V!Nj!`8iO67L;KAv<*N5YN|&X)S(ZBC?yR^%Y~+`p%KMsMm5@^iH5SG``c(p zMLJT7Ak;4k)n5eOp$v;wWC_fGX-skVN=sTqHP_1sGU-K9p2pIoeL-p3RLW9@PDCN8 zGLGEX*N>5D@}@^5U{$UHAFf!W26o5;{b=J5vw-M1P`rpvdpg!r{`5BY9BNA^aRSIR%8XNJk1&-0KnoJMtDa)@)3=iq_wCMLF#eb z>J+#>6{ndYUXUz8vyP-vvwcO4pZKxUz?Sx#gY8sd70Xgc+(Q@ua4bk2!q(#?2RTL( z?N>WA9j{&|JKO1wg;Yi!^PopP>=6@ud$`yG@t^R;y~1!4~Pzu7Jc38 zAhzNc)R5_j?~rDX4EjgBD)$`dL_}ne`tE2sc_RoZwTZOcKo?p|w?K z+6a{=5ov{zYuZ}+G{F8rNycQC3!igXd?ow#_`YDXCoJrdiAEo)&*Tio&%xWq*+b9oNOm`O1mmBU@? zl$S4j^B$p8V;Oc>j%wn=v5y6f7yRB&$V3*ZkssR-q&`MtOs1Pk68zrHN%6{=WeCf# z2s4>+))6+tna-}lGg=XPo4+t;9V&6+|7dB{a3 zs%#O$R!8Fw(nYG24roH-j^z9*WjcCj zuXVnooknIkul_Qv)(%doG;)#TX>h=pz)}! zJnWgGdC!a9^r}a^>t(Na{koS7QA}=zST1)rR<&l~C2}6aJJ<6@IVyqt&%)l@R4P@h zVqJSt+huH~vNG`82B;(hro_?_reYNzxM>OMfP!AUAbiF++>>+=ao*c8d_z7?kh6M7 zzH$hkOz!cNcYQW1Pv}P%EtUS+{8a=@VuirN#NE#4i3LG7wEOm+gIJN;oSx4XySQ91 ziZO#sU&tBLm{;^>Lr>jRiqzES9H-cry&{YXrMGjwcBduYUdKF0dd+gN>)Rnjy!l8y z>)H18{;M392Xy9Dukw1^v-90-NF+lq`g2EBR=ZN60cE^YuCLzrUvE9^}!2ECrOn3sgS}Of3sstC*50u9+)~XrsxSAHJf9%e$z!DrK4*F@!6NC_{%h!$1o^GP&<^gHLRm4ABY}=lR4{fhhX%ohesC0~*eMe^i3MAT@hTL_*rTQ4 zuJ?KnGD?Z^IFIyLkM_Ws<*JYS$Pa9bE&$0OM;HM+Kod)dfzjwiJ0TKO8%2J=0t!hD zeQ_hGVGhQFjwQ-Q=-?M%L=Es72sErj6}iMLM2J)&u*q_jRLn;xD-`kKu?7B_k}Bb` zj#&x5nVM#Ui0)vA?hqXkR0mc%M20wrJK7cAva^MFu?WeMOrtP{xUgg_lMQqrW$%$`99VhXnsL>` zi72Jnv(g`&h{<#)V{)=w)SPZDRR}fMu0hy<(msaG*pD5kjlCxV1lf`$D3Qe{lU3Pu z&D4{^#Fd5FheFv#BH5U=+0&v|EVS2~0^6}m3SvVFzKSE_n@XXK=-U3lrKz0FLyk47$jV#L`og2p+Kgb^AB z!s*z!;1w5c0=3>U@@}3M~RX>@l z^^#sv1gXVr_h5rAG6fkhlcNI=_NXy=xs?Q?3aDYt>R^X}gs?|> z5X*o9bvPedOEmB*@`Fl2;}5T2842?6ol z5=YS83_6K#8H8{dmvTWyPS^tl_?bHhGrA-*(!m=XK1lBhlu&e4s^l?{sY8a4V!=h? zvQpwr&CJ_5HwZQvyje~<<3*sPO?nYb-r-00xLt&h6EitsVv&q8W(ZSLx(srUZjlw< zgb&}GVjJ#YpHt5o z$7NFrOeTv>-V$j3WXrW%M{t}`M#enonG!CXRmK}!L?HFVkW&R@f1y-j)@5SiW&YdH z4z;<>G-eTr3WF%UDUIi-{;<&?pxS0jk5ERw7v(-wOoh@M^z!49UL2pIOJwg_VE*X=-fs4kbj3AtdDdh;#0U?6GZy?fdi(12zpoU>E z@*_8fX$bysLTQxfY_<|pDy68%CU@Wn&)iMK3~U9_`JnOwaWRDPw2fWgWebFu$dRB>iE#0|knt{7mJCNBtU+5Gmk1r-2p+f5 z{5q_}TCAD~a)ugmg|LPLV1grO0wu5pD_`Xr>mFfl!V#_0KE%f(l8VM1kgm-in=XEm0n4^bcs{^>;%68SsSh z-2>-A^@a#S6yGU$nXf?dD*9S>kIAq70)YNvt?Yhuk3OmcID#aQ`Xk8pkJ0FI5o&ow1lZsg4b?e4z9={ul4_ zJkxlRZa$~Ry^A1rY%@uRTY%Dwx1Uay&wmJ3V(OVhrV}f{|+rr(XH=CfkEl7r{p>^=JC1fvIq0ZDH(EP%6Z4~cDZ#v*QBt# zu|C%m@6n@(z$6Ygcw6@~(6M_KtUB_y5I{owEOW~)TY$?mi#Z-My95YF<@iZ)X7(I7>O3pF+*DG>@gbqv+9gJKY+N{k>YN~{UP z)Sv|mYlsTPsYVS@o7KBUkTK+_5gWJExL9Vnv{V^V{P%Gof}&hiGR7KO^uLyiznaBtyKl;xBTqXlYg8fH ze^w2ugZ)osNQ0`oHgxRppUBd%6(SVLeD}uQS${jazLh5@5e;uf(s?sy7Jk{g(gKCH4XcBZwGg*dTNxU&cny1Nb6`n zL^Fahahqcpb~PDs0oH~Yfr~kkn`fzYG}e=~1!t9&!x6{YVqIay7-}%mciWR;I$2YQ z+4x40mn&Mg=19iT*Bzbn5f|2j4N3P;iv$|v=5}!6>5_{DfhQhA5;`Jbid?l+p@*i_ zp=X8=s-|Cd3jTMclYI(`T}=oocvXY;iF%)-6p8{04GlR+(+icpw}xtlj<^~_gd#|i zI;UZo=w&d;I3rs%%7tT&c;VRNLO(LW47JQ0FeDO7Xp2N&wk26#IbA|l;%$p1_gP0( z$`m4*n9cj)#+Z7#D?7OCeMu3JeM~=VZSSa(u9W7o~d|Xk}Fgaekv7*s#GbbptYW;A zDB;PfDoySEgdxLs>Z+A*SayXVR!p}zmYK&Q>y@%M>ZRkeQabWu5J`BQ#I;N8J9cA_ zaTFkvC1;ssXxYGsc0yJP$8cCsVipo)6rC9+YX}915O?x(V311?5CcoVCw5w)3Olf1K->LkI2l|a%k0xaeqeze z7U7@>>x4vt!6u3X%*yhZ=RD~3iYooUh7}E>fHQakK0cG-7dZl(=w(}xq{EJF zge7>Q3D^13r#|)(5?TiNQ4-`gzacUHuaS<-;}Rb!$w^YOl9s$ACT(|}?tCtjp8O;z zLn+EplCqSPyp15KM#w@kWEoEQ+Sjas1XF4R)ET+X@+QcOXA@@yChEO!W9H%I&DVofo zGnmH|WHOcctaj3~p7y*aKJ%&1eTwp(>5Hd4>%vTa611QOJt#sGs!-kdb7}w$C;$e! z(1}vCq87akV_Lbb9wOWWP+ zrcbP7aM*bt{}B`|-W290nYXE6_Q|Y|oXR;%y4Ig{a)f}&%28GM(}+S90n|`r{ERUT zi74 z;DfqHjux_KZAfq~m&vxm&|jT>PGd(Y0#4YCBm%MF0(tcWZ@i~6)PyS!H#u^ zbF?Kw-Z)cxD@nHYKK{ZTZa;7rvu)DEcDF6&ZhI@cP(DaA9C@v74vet8PL;VfeeMB@ z5zS&$S79@G43k#nrvh`Ncn!HAcYh{Yqdks!2y$#ggww6AO4yT*A=FCpL|&SGlZ=z> z?_wicDt6?Sk|LH!jS!qdWiZN>qP@Uy93TEJ8&`-H&tjn zl^wS}q9F)y-8|XVwD2@OP8}QAFbbTEK#RvkfDR~Oic$!I1dPL@f1&JYk`-`)53FIN ziDR4qX;z%l{$UwE(AdERk#N8@*)5ZIJBSeA!4#o*LD6goYEhHg)S@C(dUT!5!jcTW z6NV90q)OFQG803#K>{@Z^CQK0OMqG_p+okBSFN?Ce`D zPo|uv$wIki6C*S&rp#(~9NgH9p$AcCP;rKwed*J-de=;RVcw3+E^d?n6{jV=)2}ID zkh)6kp)U?jSPVJ@pGtK4g!I18Z5{mGseDA{MBX5YWv25*6Yq%B>BrnyXl>m9d%=#_ zEhp{(pH6@PLCi_HhgiNTjRf!K-n@>KlbgGM-)7sa^ow8uLzp0Sx!f4iOhkH}-v5n> zGw??KbKD43wmI9cTlkiezBPm6FLmq1b;nQz%T;D35va_lLe!~Bq%<9~C@YnVlt}~@ zB8lnFN#8M@heUo8Q{Z6%X24jVy0U;vltKmwSU??2VFrZ#m*OL~%(|kOk<&aobGLo* zb-ohDf-$e?3)$@`I1vL8SfUg;aC%EdU;5Lh-VB>c(Q+t@^*OpZxm+)o*V)I+9|g%U zLn=~Wj+Can6C@&5sf-10<6yVP+im_15Jd`o?~df#Y&Q%|L!2~k^a6h10WY)MnT4Tj ziINZ&0zAla=$J|%4>$eXoS;mbyomvk&hzvPqeO@)lm`z*iovvpt;olDwcgHgAjAID zOK^b-qSRi@+#bzTjzFY}h7?$73|&L`otqNeJ9yw4Zhn#EhlilnffY)E{?Uk!}Ru->rm1 z@Qb_2ow-C3X$eolbk_{o&`OMs=2~vhrxiHrC`d-1(`RI zpr^>*3#MSsSr!Z4i3jvdTcMBKvoomRxvX#@NTncnrwspdCu%kmX6A z#NG)i#8`-r>ygSy@L2BM4A2x0IR4s_8C@sx+@ZK*$PD44Z48gq%+BpfpSc?n%Hljl zixR+({Ls%Ac4U%RiEN~ej1>-Mw9VT=i?VVBF{OT$bK%DAA~oE)#v4d=)qa$(%RFplUzTG>Ll5-fR*ED_Vu;L>9~6(u=YT?wdx>e6{l z5-fHdej0=`MUymX6LZ{>DFx_(Hc~J3(uHnlDYaLoRMLX}+J;~P6*0}H9i3V>m6C;C z5;tukONEn2`CFsuREx?MK4nl>f>($pVS{q0kNzl-Qq+#dVvh!?ksc|M*3*#k=w4Y> zl0GSvMrl7S>4@%ylwK*8W+^5uDFRe!b7?7kHja8uPMh1!JF7citt>`JO-6tt3NI5Eu=_sVC zD5FMdnxq$>jgy=bQZ3*q0BFH2#Dfp;1$Qk5_=R7dd0O2B9P>OD$gP&7Hqru|!6npy zx5>?2EnLnK6QZ7&m#s}EStzR}>e@}}{{X15Iv4)e`D&#KYKk@LuL3KxmTINqC|sjlG?gxxfu7;z*HdTG?!y(%dcowrTg0jk5n99b~+>ap67v|f_1 zrfN)K>Yys?vx3sUw(74Yt7kQv|gHS6(rFx<7K7HH`(jUrfb4d>%$)GttKnVg6PgVmcQPt zj#6rh^=!Ttt-%s4nFglEfP|0w=)0C78k}oc;juo0WF zg(3pTKpTz19)y6DIFKV0XwhEk&puYP;#o0HD_Ldg*xV~DI;LZynB`t=4A!%uQ&h1V6At zdYE7~f*cHFmW)MBq7Y8o+NIqd3c=|unLypjbs7|?17IePCnnv}fq)}mC4B5qQ9|yD zvZ}et?&(VI6xt1*l`b@g0nKCrnyG3D|v z6$5bn$}RxEZs+RnXKir+1FNG>an2qq0XysD+AQnpFYLZA()w(fe(EidgT`vG#&WAb zG3v+)1~qUC{)$S8s8b1tMM8u`1C}kLL}pkB;e0|w^~S*I4MND>Aj=L+=;F;{^q_~x z$8%U_?cksSU)?vgzhB z8HZQD_HP=iF#|iW6(cPEvDPjH#{(kRf)CUM)bhyMb#U12v9(SK#KlB_kub3gaz$7& z(LfKGz{#oH9b{Cm$eFVwt*ikl-_Yu^v;CqmI~S|N z_H#dHZ!ybq(t24e&+;vQF)wp2K#%c28*^WEq(2LD1B>y(w($pFUov?tJ;<>$+woo~ zRuE{*5)?yV>@gUdoNqWsl_bYjaC13~CeOT4yEsM`=!1LG#J!+1Iy-{Ls9pon3u!*C zWhkV`ATk(rgbgx=(AaA9gp0c2tUq5d?7HzVM{z2TaV)FxjyiNM>+Rt;8dTTzT6t0+7HUsN5PbhGvCrW*S7@ zsAp$4L_!#lyF$qtwb6U{3|a`p-XV8EOZTPnwpzn-|0?kRhINADFK!$6ZHulK4{H^V zE`uYmh5om0h10JBi?M|h?WSTv#d_3z=yi0%={`p;io4WVI~AMK>4=kfP5i})ulOpb zp^f8Ii#OG#CY5eLLyZf#>q05Nu5yv*IG{fGkl$2~r_@I=L69T4lu!9ZH916`DV1lr zmM6JfJNcG>IhYHnwl-;)m${h}l$Fc)nXfsUqf?sKRGY`SoD0*NSJj-~Ii3scj<#u@ z_qm_z>zMnvlnx{*4eT)=_d$suMNtF|QhA+oo5NyNpE3g*yuznxVi#uO~?cm<>+(FXeCLWaipko@dcJNo1gjXsDwcfFS6m-? ztXI;e2qE*FoQGc0ZT;t;W9}O_>99kWbj1&KSp%}O7&cQTy)Fc&U&^V2sPjOUKt3dK z^R}l0n5|p%jit7wS`yNpdy#27CAE8VzPlUWr@T|EBS4piK@*4JdzK{V#mx$rJn+9q zmH!GUQ z2-rb~Sb`&0U>z)g9hgETEZCuKPhaf(7x7J{Wk=ILebi&yXtV}%YNn%U5Q@6~D7u%R zWEO;mf<=1#Cc|`-tii^b{AbX|k#w{O2c1S?$suD&;tzReoCdm+4?C7=nb&Zc$k*S3 zWRAx5bB*X=md^^q*eA#ad@G|;l3#>#P0XS*3Hfl1)Wp?e(TeR z#2?J*8^!my=&jR^Lbx1$S^R9ezE|)Vmbl!>X`J|&1ap+e>r)no2D|pLTbW!2xQScY zSvq5%My~~T<(mRPa1!B23cqp)5M=9@#Zfkbjv%U2hd=};Q*NrdJ2Ng>EDrA(S8cOFEbE+^2FS^7C->4=S~JtAe4 z5~QGps8F10)BxoPgd>R%aY{k(k|soj42gwTYl$Ij{>!vVCb6VitZ3 z!}d+Ov|L$;FH=S|T=3t�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 literal 0 HcmV?d00001 diff --git a/resources/features/hover.gif b/resources/features/hover.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ffe419b6098ff24982a5d4543a3931c0598bea9 GIT binary patch literal 45558 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 a_sLI1#q*v34X8i|O3*4wi-k=I2mm`k60@uT literal 0 HcmV?d00001 diff --git a/resources/features/rename.gif b/resources/features/rename.gif new file mode 100644 index 0000000000000000000000000000000000000000..3c988ebfb67d1548865a390d2d4df3b19f1fc475 GIT binary patch literal 125002 zcmV(?K-a%VNk%w1VE_fZ0(bxbA^!_bMO0HmK~P09E-(WD0000X`2++g0000i00000 z00q1PryU&~9v&ba9W);x5hooTGaVf$EEX*~7Bn{=FEA=QH#avp9UVg*9bO$B zVjUfK6C+w4HAx;bS`jX17ASNTJ9H`?Rx~+4IY=8lQ64&d9v)0v9!F{!MtdGydLCnW zDn?8sKvybJT{}WZH&{tJQeG-bWG7g6HA-|cT4yp?cRpowRURH(9x_@p9!)(cY91bc z9y4$w0b?*SULIaq9(qtYKx`gse>F*IMjd!rGG}8RLPA1AT~}O8TToI$Q&Ut}TV_dR zUPxwbPj7f!U}{r!er`-ea8zk$VoPCYQgC%ZYinz1d3}FiYIS;Scy@Ol9)cborx`DX z7CM0)Gm;)SpeY`LHXf%mIg~Rwvl~T}9$S?iN1+~1upd>a9#FC#X_+2;rXg6GKTv}v zRJAowp)GNNEpeJTag-%yvp;5`HDjFkVWXXAt*A$yJ-xQnvbVl+Ajk#!ktPOv$Zp)7o#-{e&JKmopxlH8F-BLWUk< zfL$J+U>>MR9;IX+g>h1wX>q$+SEWaHr)Wy0X=uo4G{bUR#cFqzTC0_Lw!2!9yLpkd zajTViz{PoylYkzzh8}^GK#GKNsg_2okae@JW3|9{%aT{ik#*3cLff}u+|7A|gM)^S zlYo_%nVFi6r;L!esker-t)`BvtE;cCu(!9jgR;_rzVfDqz?06Ki^!<5&XljzshrT# zm)!fW($d9-s?xH9#fHGy*O%GatH{X6#KqLf)XB-z)YR0;)z#JI<>vhS{0RO469^ng zu%N+%2oow?$grWqhY%x5oJg^v#fum-YTU@N<3Io)Ly8fFh*r_Y~2g9;r=w5ZXeNRx7W$+W4{r%xjsXw$wV%eJlCw{YXiolCc_-Me@xs@==Cui3nS0}CEZxUk{Fh!ZQm=(n-s z$0rv{o=my2<;$2eYgP=ovuD4XLyI0wy0q!js84@h&01>e*RW&Do=v;9?V7D~>u!0w zx9{J;g9{%Xc(?K6B#A3u&b+zv=g>2<3=*!ob?Z@(YmXYeyZ7(l!~TmG%`ytUDCpCh z$LDRkd#2;#%b!obzWuD_@s-5Kzy16FD%~gGfb}(@-hl`r;Akz0BNgOsoVMzV-16dE=gyT&QEQKiJjIwFi;f?rwC>8_epyQ)C z40r>iKuw?%M3FuknLrQb^iWVZN$QvYl0GUpWs>M9=na-Z(CB4DBaU?4c_>Bk&p+9X zgwH?bq-5rqXX?jPijR52p?@%aspp=U*@z>DQi8=mI9(3Jqc;igs9+O17TE)nP71`M zl;I4?s6at9Ic1;;c!TJaL-HwV0%4j&=1Ecb!{$gqsM_X9{%gJpKsYMSS!+nafHT7ETmT=2%bgVxu}f3+X^D5~S#+k`l@-L7ob9ZLwdL zx?iv*ndy%|L5O6|y0Vg#E4ok7>8`FO@fzcwqzX&!zW~Q|Y_gm(Yf+HlL^^1~;#L=_ zOwSr5q^93mOYyeget0RU41A02r`ZNPqq!u~JCd2`_!Evu{ovz|IpO@XGDx|G<4>>q z!FlVOXQpW{Nd3V14?6$I8FSEZ;%rh6f5Pam$WTY!)xZR4Sa7otHNl@b0vW=ej&>?L z6OT!Lx+FSgZ!9DO<3>!-rBq5uB|1)S>7&_FUr4h4nkI{6raAcBYO^;l>kD*0G0$95 z(Al-hE&%Av+|T1b(~R%D`Wmhh(>OXES>B+Bo)pysS-mXQ4{0s7>N!>EkpfK^(s2Ut%P)`uhS)#0w{HU(^2P%hSEmBCEwxdr zAmK`Yi_kY9;)TR`=~`9G002GaQBY;vtDel%#4hKB#DV}=6P&bnE6W8dW*Y>6_}p}( zzKw)|FpQy0)TcnP1rT*xiQU;0RKS8!>}>wkf*Fy5xF}8~kV(*zVSF425(tvyZ?o#4 ziamEqnG_w_^By17F)6qRj_q$*c=5IEYfVXTbhR}|^QlQ}Y1wE`ipZq=$#g71;KYL$wt z_a+i^(diD<@* z*{hHiE6X7>PK~LiJQ-M>1EB*S=>9lR$mYpUqD<#H0KHDT%<{_+)zm=ssvxPV zR=3L4%3$@XT@9;P$C{U~LY1s&O{-ePV%Ddw^{sG?Yf{>ZRJq!9JPgRIUiZq^zWVjA zfDNo*2TRz(8uqY=O{`)U%h<*`_OXzStYjxkS-tKi03?9HVWAQCbhcO+b3fk@h$T9Q;jz5Z1LeNB?zlB9RN@=Zg36P#Kyuz(B$w(oQ&OyLS! z_`(QbB9vaD&qDLfSn z$XJ0Div|D$GBE@PTmk{Jt}_7QaDWFX`ABFasYP3319_L5MbZp&bY=m&T;9I z8zt)wxyb%UPV#dbN7XxU%oU^!5_%h33Y5TtCNv-tjFSWoqk#6b3l4xV@O&h4$hotH zK9ZHk+UK!$0Kx$f^!Um_12*rt)Td7Ms#B&Z`n=EfL3BrXSu9Lg~BnkQT&IM=zId5(0FgaH;bS2)o{^7fY3J0w?V1X47T-kwPD# z)92Mst$%&z{aW_k`~LU9e^lCsfA-x7AP~VguiIG;fVczT3WKP7NFG1!!C!&M&DVs$ z`~E%>rT_f;cpp6CnGb26D_!7>cfcg-aCgeP|NZcf|G29Qa=#|5uxL!9=R4$$&$Ea2 zIZ}G~gnApYdL0rD`!{;Hr+P)gA+xuDqnCLB$a}$8ffg8i#Fv31#~K~rDV~yYjRA15 zFoFS>ea0qVm;iXs*9s&E3qNOP;`etXc!E9Gg0L`na6p3Mmv=R1g9(>|BbacE2WcfJ ze@1wONH}$tS8jfFPdzYLs$+Yi*959VdiRtiu(wyK=X$0`fZm{m|HnJ9SA}^chORd# zxwjq&Xf+J59#Nnnv-gI7C3chJb%YZIkCHM>!X}TBDlbA#FS3VC@-BGT1F2#T{^ZmT z-XJvnAa)w~i0YPvk~oQ!Sc#Ts5=&TreT5D!^MrvFHl&w;{g;JsNQQcKg#*}yVEBcn z_Po6S> zV5ooa*oxr*i}&Pus>6$*xPS=wdA!(HVh4@FC_Ti;B$LyKewZ?a*oQCU4}Tbp(kP9O zGK?(3hhLYC8cAy3*pVLjksz62nJA7;*aSWBGJ%DTWeAV{cOLCXd){FF9+4xDtw@iq zsE%1Ei}{#<{Ai1~$BKECdO*on0~w6dXplXihlsd{=HQ1XiIE6-l5|6eg!6~zWRcO> zBpJDpTq$ND`ITT9mSXu+BZ-M6$sgwESD>hSqqrgZn3F;Ie{e{XaXFOr_=-6hi?gU# zaCnRNn0sJodjc7D1bLK&sFaP!kPums|6q;MsE3EBhtWtk6^WEtd5v9}nO!!PoY|S4 z`I)RymL)NcohVpQ7?*eimkAh(b(w&436ra+leUPDnums(w;o@}hJEQN0w|b7Nti}i znSqFyk8(4M$#wpKHbV0c5t*EiLXj+jlvRnDnpvG82AbHJo!b7noi8DpBr%TVNLcv? zdZws*op+aELE`Bi0y= zjhHLU`J9v)op`v2!P#}z8KEG?ofKN37K)wTId1lsmV%Xep;(@-`8BX9o9fAWM#6fd zr+c9oi#0ic^(lZkvLX4YpI^tHjCm%(SeQh!C2&%V&iRbeQ;l3lP7o14Q*Gb zkQ%9yx?$mHmWq0*m^ysAu>zj*sFV7spgO6CnyI8(sv?&g6L1Phz;>b9s;)YyqiU+M zI;*9Y8+;H97r?5ox~shUrLjt@z#6Px)*2l^4KJW-p4zL*x~$y!tHS!M(Ar_FaeS?Y ztjv0?*b17?8m-*gt=h#JEAVarV6E9&uI3t&LEwAdx~}Y6S*w9^q@}CpIfgbp;$y%=hJFxC|uVuHd2%E6u#i;U1unzmMkY})Dr?3=Tv8a|C?H+z6Zh7wq!G|720x>r$f4i~C@edk zFYACYyH~#glqjm6ZY!f9DwkkuqBZHXEE~B-8zd3pwdt68No%%B+mf|ue_1GjS%^lq zN4I@tx(jF|^7((`iMcy_i}SgRw`@CmLu)614j`bz-#Ee1KgWz2*Z{;lliGS`kTV8sG{Htm!`OuDJ;IESHgYSo3)65h5NNk40~+Y zzqkl{cJhViE5kvYqW4rCQ#^V-On}kbA8TvCv1xkOYry{7dRe%|(yMhJ{Kjxxb;XOM zsHZx}%U30wdAggmnOmD6s=WSp$$C{=z4oYAZfKh#%6hB_k0lJFp~%Q@d%ahj#efrl z?Rd#KxsNxyB`KQ6IjM@fxxt~VfIa)7WZ1Q!>mfWmi)>hh8dAv+Y{I=6i>gz}2uQtf zxQjeI%D9P>e9Xad9L&P}ZFB5(<7kp7*`aT%$Mh+mXUL);+PzZffK7OlTMVPDh4wTTQU ztqjG~T#JbNf7jfSQ81oaf}%0mAq^;_FA2=U9MKYeWyK7kXBnQ#EV*yHS7K;;&yCdJ%kB%opm?|{iym*A#5ugu_Y1r9 zyEQ%;fM`6$37w+s41f~sy&VmYX>25EoT8@Kl1WR`wt2q^D85`s)T(=h8XU`LH_>EW z))`jOTt}K1ozcs?(Z>?O@CnYWDY^vxf9f2Y9UTNs{Gx>1qVxI1>-pC$ooBkMON%MJ++?iJ%pBNXxZRAq z+IIWe@;%>I729`we}!e+X+*ny49*eKBQ7e*B~s15?2p53qA1MV3Qfeb2zqc0-tr6G z5`Nu(Ro!gMxa%yBoOjw;+|xMAc?0d>d==h7+u=ZYwJOcSUu%0}d*L*>h34tBCH|h8 zO5Zkq<1l64A-m)GdWjG44)y>HNc9N!&Z@)Nr0(j7R_iKA>6Q+6n$Uuq z?rgh`c%9yUjnV4Cj)J*f5>{>!l|Jj)m+Z(+&N-*9s-?v43C=!JzK!p7y2c z?vN4hA@KSqQ<|9s3>^PkQdN;d>h&l-Iv1(|>V^rrYI2>QIv@`~paR^JlbclC#-bQ&P@qt6sU z2lc7{89-0zIfwEmvFsyJ`&y4^iAQ&V7Y4Tv?U_FkT5kqZ4-&IK60;xsLjK45$v^wT zPXM^za-IMACyNT@fCR>@_TInt@7l0_;r1XA_y7R+yYS}sAn)^j=puplaXu1rFB0gl z{_@V}j~)_+zT}9m=yqQI0C7)Xw-^8bJa{K9l|XyA4kk1R;+`~v0LBTNSkWRzf!hE) z!pKeI!;mC7-t%Y>q(G4>?d^KU(jdZ=BOAmNNYP-bZa8qJ97k~GyP5z}HPm<$W6Gnz zDoWHTabUrR3K=>Cpmb_QDe`n0bbx6Tfsth^hBa{sL6|^cOkEI5)*u{H1g@|`Q1MEu zAqK<10$kUxDJ+@*_cbWRFko1(@&fn^I8a5ma3$--d-rkJA(0(Z{$@NGbYQt=&AKfO zK(XkuVaFz33`+y-*(2{_z;wAH9LBFlx=wAHvfz=cH3H|VskZR4do{rEEr)g4$gmI_ z+^d^8WX8l5FQ+bhWOZ1+%{r(2*`S4H5$^$BzHn;sFs>C zXdI-Dbjc};ghJ>Zf^HHCA&PE7ip+?T)Y2g?D^e3qA59DXimHl^awyIyi=?S6gjxa# z$&4O(vd%S|#8V@2yab7&K6es|P%jM)bIduvv{NHU`0-^tzzj4itmlT1Lj%;pP>(bJ z@Jep7EBpW}F77^q<1^y`sP!?r$O=oe$ol$EK2-q-3l_oHBWqV;^}`O}LBf48(4=7Qr2*J&&*BWQDEU7<l7hi@sW|?QExn`Sh#yRH>dE{9}0RsM^riGqoj8h^&lkC&btmgbvI1rw! zsL`Q{O7u{x<5csenx1y5=`0BfQznCralUV7^%y~b4SkzTP!Xp^-w?Yk>N$riO+QO!%UR?AWrbL?6H7xd3( zgLp8qN=A2Bg^|OxuF@g1Z@1V(tryw@tF1_m0re7nUBMWZ&MbvB(mg=oiY;%xuwrNZ zH%w-yj@E%SN%(hlO~!pkWqnVr!Wt&-4C}3kyHb z!!vL-lv75f93&#tSpWq%Kmr!ffCofiivEVSK+{a%6gptwcC?ZcxOquVR3k`{Ov5!O zLCq|8^IFvg$0wX{#8E`?6GXJ+rG=bCC?lNG(tflPv1vqUYdXo3B$dLVWNC(ka>(5( za*?H!MTk-fiqu{**vs7Sou=L}oITIiUzP(;yDqfiq2`xC+_?g?Gwe z3`fGjYMSP56ZBvUJF+$&rtpMUs?tcrxuhP=Flt-*TBbBOk{t%_nl}6)QiK>!;oQw= zAtnl?JKk%iqa<*#lIx41mjo zYh2|zSGv{}M$%+p2dMG>0=&`)Z5_1W5Zk6Ef|iAwUFv5#nP|@@rR}e7yC-CIf~9(D z zjrYaKEa!`itc}8WGscaI?yR`#BY~3>AIB(nE@9R(Cug+P)ZlS1xbxh%;ONEPZR?GU ze9fB|$Y%5j^{46Tu4!z^G1e^=0Qx#JB(oY;FwaiUSnXJHb2DC(VUd;iUC-{yT3oR5 zS?@Jt#(Cyb>O7(}OwQ@kxLp zY?Zi>D!dj`K~{WOi=?T9A2zm!Ir1bV-s8taB=R}|_3IczmLV40C*Fe15kcLf8j-be zu`vQB(Ec`&+vℑ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

>+={QqPas`DP3JPWf60(LNSKQrgJUp!J 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 RZusAif8w7{`?v9B{|7Jk>9_y@ literal 0 HcmV?d00001 diff --git a/resources/features/story-outline.gif b/resources/features/story-outline.gif new file mode 100644 index 0000000000000000000000000000000000000000..20c2ab94c30cda7723a0aa1a4021c6369d0431f8 GIT binary patch literal 93038 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�`Q>7N8vcY%#9fZbh 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 XuXp`f&VqpbOHcggWA6XsALRNUNW|K` literal 0 HcmV?d00001 diff --git a/resources/icons/call-dark.svg b/resources/icons/call-dark.svg new file mode 100644 index 0000000..64d7c37 --- /dev/null +++ b/resources/icons/call-dark.svg @@ -0,0 +1 @@ +Method_16x diff --git a/resources/icons/call-light.svg b/resources/icons/call-light.svg new file mode 100644 index 0000000..5ebc1f4 --- /dev/null +++ b/resources/icons/call-light.svg @@ -0,0 +1 @@ +Method_16x diff --git a/resources/icons/category-dark.svg b/resources/icons/category-dark.svg new file mode 100644 index 0000000..98e91b5 --- /dev/null +++ b/resources/icons/category-dark.svg @@ -0,0 +1 @@ + diff --git a/resources/icons/category-light.svg b/resources/icons/category-light.svg new file mode 100644 index 0000000..dbf0292 --- /dev/null +++ b/resources/icons/category-light.svg @@ -0,0 +1 @@ + diff --git a/resources/icons/event-dark.svg b/resources/icons/event-dark.svg new file mode 100644 index 0000000..466429b --- /dev/null +++ b/resources/icons/event-dark.svg @@ -0,0 +1 @@ + diff --git a/resources/icons/event-light.svg b/resources/icons/event-light.svg new file mode 100644 index 0000000..268938e --- /dev/null +++ b/resources/icons/event-light.svg @@ -0,0 +1 @@ + diff --git a/resources/icons/goal-custom-dark.svg b/resources/icons/goal-custom-dark.svg new file mode 100644 index 0000000..aab3ffd --- /dev/null +++ b/resources/icons/goal-custom-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/goal-custom-light.svg b/resources/icons/goal-custom-light.svg new file mode 100644 index 0000000..37db136 --- /dev/null +++ b/resources/icons/goal-custom-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/goal-shared-dark.svg b/resources/icons/goal-shared-dark.svg new file mode 100644 index 0000000..366b868 --- /dev/null +++ b/resources/icons/goal-shared-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/goal-shared-light.svg b/resources/icons/goal-shared-light.svg new file mode 100644 index 0000000..e0f2583 --- /dev/null +++ b/resources/icons/goal-shared-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/query-dark.svg b/resources/icons/query-dark.svg new file mode 100644 index 0000000..21ba9d9 --- /dev/null +++ b/resources/icons/query-dark.svg @@ -0,0 +1 @@ + diff --git a/resources/icons/query-light.svg b/resources/icons/query-light.svg new file mode 100644 index 0000000..db77e35 --- /dev/null +++ b/resources/icons/query-light.svg @@ -0,0 +1 @@ + diff --git a/resources/templates/pages/category.hbs b/resources/templates/pages/category.hbs new file mode 100644 index 0000000..01eee60 --- /dev/null +++ b/resources/templates/pages/category.hbs @@ -0,0 +1,19 @@ +{{> breadcrumbs}} +

{{ category.displayName }}

+ +{{#if category.children}} +

Child categories

+
+ {{#each category.children}} +
+ + + {{ displayName }} + +
+ {{/each}} +
+{{/if}} + +

Definitions

+{{> definitions}} diff --git a/resources/templates/pages/definition.hbs b/resources/templates/pages/definition.hbs new file mode 100644 index 0000000..51f8724 --- /dev/null +++ b/resources/templates/pages/definition.hbs @@ -0,0 +1,39 @@ +{{> breadcrumbs includeSelf=1 }} +

{{ title }}

+ +

Signatures

+
+ {{#each signatures}} +
+ {{~ name ~}}( + {{#if parameters}} + {{~#each parameters~}}
   + {{~#if flow}}[{{ flow }}]{{/if~}} + {{~#if type}}({{ type }}){{/if~}} + {{~ name ~}} + {{~#if @last}}{{else}}, {{/if~}} + {{~/each~}}
+ {{/if}}) +
+ {{/each}} +
+ +{{#if wiki}} + {{#if wiki.error}} +

Documentation

+

The Wiki could not be reached or returned an error.

+ {{/if}} + {{#if wiki.notFound}} +

Documentation

+

There is no documentation available for this definition.

+ {{/if}} + {{#if wiki.content}} + {{{ wiki.content }}} + {{/if}} + {{#if wiki.editLink}} +

Edit this page

+ {{/if}} +{{/if}} + +

See also

+{{> definitions}} diff --git a/resources/templates/pages/layout.hbs b/resources/templates/pages/layout.hbs new file mode 100644 index 0000000..847840e --- /dev/null +++ b/resources/templates/pages/layout.hbs @@ -0,0 +1,17 @@ + + + + + + + + API Explorer + + + + + {{{content}}} + + + + diff --git a/resources/templates/partials/breadcrumbs.hbs b/resources/templates/partials/breadcrumbs.hbs new file mode 100644 index 0000000..047639c --- /dev/null +++ b/resources/templates/partials/breadcrumbs.hbs @@ -0,0 +1,11 @@ +
+ {{#each category.parents}} +
{{ displayName + }} +
+ {{/each}}{{#if includeSelf}} +
{{ + category.displayName }} +
+ {{/if}} +
diff --git a/resources/templates/partials/definitions.hbs b/resources/templates/partials/definitions.hbs new file mode 100644 index 0000000..4c8db99 --- /dev/null +++ b/resources/templates/partials/definitions.hbs @@ -0,0 +1,13 @@ +{{#each symbols}} +

{{ title }}

+
+ {{#each symbols}} +
+ + + {{ name }} + +
+ {{/each}} +
+{{/each}} diff --git a/src/client/Client.ts b/src/client/Client.ts new file mode 100644 index 0000000..aa0376c --- /dev/null +++ b/src/client/Client.ts @@ -0,0 +1,116 @@ +import { EventEmitter } from "events"; +import * as path from "path"; + +import { ExtensionContext, OutputChannel, window } from "vscode"; +import { + LanguageClient, + LanguageClientOptions, + TransportKind, + ServerOptions +} from "vscode-languageclient"; + +import features, { Feature } from "./features"; +import { readyEvent } from "../shared/notifications"; + +export default class Client extends EventEmitter { + clientId = "osiris-language-server"; + clientName = "Osiris language server"; + connection: LanguageClient | null; + connectCallbacks: Array = []; + context: ExtensionContext; + features: Array = []; + isReady: boolean = false; + languages: Array = ["divinity-story-goal"]; + outputChannel: OutputChannel; + + constructor(context: ExtensionContext) { + super(); + + this.context = context; + this.outputChannel = window.createOutputChannel(this.clientName); + this.connection = this.createConnection(); + this.features = features.map(feature => new feature(this)); + } + + private createConnection() { + const { context, languages, outputChannel } = this; + const module = context.asAbsolutePath( + path.join("lib", "server", "index.js") + ); + + let serverOptions: ServerOptions = { + run: { + module, + transport: TransportKind.ipc + }, + debug: { + module, + transport: TransportKind.ipc, + options: { execArgv: ["--nolazy", "--inspect=6009"] } + } + }; + + let clientOptions: LanguageClientOptions = { + documentSelector: [ + ...languages.map(language => ({ + scheme: "file", + language + })), + { + scheme: "divinity" + } + ], + outputChannel + }; + + const client = new LanguageClient( + this.clientId, + this.clientName, + serverOptions, + clientOptions + ); + + client.start(); + client.onReady().then(() => { + client.onNotification(readyEvent, () => { + if (this.isReady) return; + this.isReady = true; + + for (const feature of this.features) { + feature.initialize(client); + } + + for (const callback of this.connectCallbacks) { + callback(client); + } + }); + }); + + return client; + } + + dispose(): Thenable { + const { connection, features } = this; + const promises: Thenable[] = features.map(feature => + feature.dispose() + ); + + if (connection) { + promises.push(connection.stop()); + } + + this.connection = null; + this.features.length = 0; + return Promise.all(promises).then(() => undefined); + } + + async getConnection(): Promise { + if (this.connection && this.isReady) { + return this.connection; + } else { + return new Promise(resolve => { + this.connectCallbacks.push(resolve); + }); + } + } +} diff --git a/src/client/features/Feature.ts b/src/client/features/Feature.ts new file mode 100644 index 0000000..ffcda9f --- /dev/null +++ b/src/client/features/Feature.ts @@ -0,0 +1,21 @@ +import { LanguageClient } from "vscode-languageclient/lib/main"; + +import Client from "../Client"; + +export interface FeatureFactory { + new (client: Client): Feature; +} + +export default class Feature { + readonly client: Client; + + constructor(client: Client) { + this.client = client; + } + + initialize(connection: LanguageClient) {} + + async dispose(): Promise { + return Promise.resolve(); + } +} diff --git a/src/client/features/activityIndicator/index.ts b/src/client/features/activityIndicator/index.ts new file mode 100644 index 0000000..0d06e90 --- /dev/null +++ b/src/client/features/activityIndicator/index.ts @@ -0,0 +1,89 @@ +import { EventEmitter } from "events"; +import { LanguageClient } from "vscode-languageclient/lib/main"; +import { Progress, ProgressLocation, window } from "vscode"; + +import Feature from "../Feature"; +import { + levelIndexReadyEvent, + levelIndexStartEvent, + projectAddedEvent, + ProjectEventArgs, + projectReadyEvent +} from "../../../shared/notifications"; + +type WindowProgress = Progress<{ message?: string; increment?: number }>; + +export default class ActivityIndicatorFeature extends Feature { + private events: EventEmitter = new EventEmitter(); + + initialize(connection: LanguageClient) { + const { events } = this; + + connection.onNotification(levelIndexStartEvent, this.handleLevelIndexStart); + + connection.onNotification(levelIndexReadyEvent, args => + events.emit(levelIndexReadyEvent, args) + ); + + connection.onNotification(projectAddedEvent, this.handleProjectAdded); + + connection.onNotification(projectReadyEvent, args => + events.emit(projectReadyEvent, args) + ); + } + + private handleLevelIndexStart = (args: ProjectEventArgs) => { + const { UUID } = args.project.meta; + + const createProgress = () => + new Promise(resolve => { + const { events } = this; + + function onReady({ project }: ProjectEventArgs) { + if (UUID !== project.meta.UUID) return; + events.removeListener(levelIndexReadyEvent, onReady); + resolve(); + } + + events.addListener(levelIndexReadyEvent, onReady); + }); + + window.withProgress( + { + cancellable: false, + location: ProgressLocation.Window, + title: `Indexing levels` + }, + createProgress + ); + }; + + private handleProjectAdded = (args: ProjectEventArgs) => { + const { Name, UUID } = args.project.meta; + + // Reemitt for task provider + this.client.emit(projectAddedEvent, args); + + const createProgress = () => + new Promise(resolve => { + const { events } = this; + + function onReady({ project }: ProjectEventArgs) { + if (UUID !== project.meta.UUID) return; + events.removeListener(projectReadyEvent, onReady); + resolve(); + } + + events.addListener(projectReadyEvent, onReady); + }); + + window.withProgress( + { + cancellable: false, + location: ProgressLocation.Notification, + title: `Loading project ${Name}` + }, + createProgress + ); + }; +} diff --git a/src/client/features/apiExplorer/index.ts b/src/client/features/apiExplorer/index.ts new file mode 100644 index 0000000..67847fa --- /dev/null +++ b/src/client/features/apiExplorer/index.ts @@ -0,0 +1,163 @@ +import { join } from "path"; +import { LanguageClient, Disposable } from "vscode-languageclient"; +import { + commands, + Uri, + ViewColumn, + WebviewPanel, + WebviewPanelSerializer, + window +} from "vscode"; + +import Client from "../../Client"; +import Feature from "../Feature"; +import { apiShowEvent } from "../../../shared/notifications"; +import { apiRequest, ApiResult } from "../../../shared/requests"; + +const viewType: string = "divinity.apiExplorer"; + +export default class ApiExplorerFeature extends Feature + implements WebviewPanelSerializer { + location: string = ""; + panel: WebviewPanel | null = null; + panelResources: Array = []; + + constructor(client: Client) { + super(client); + + commands.registerCommand("divinity.showApiExplorer", this.handleShowApi); + window.registerWebviewPanelSerializer(viewType, this); + } + + initialize(connection: LanguageClient) { + connection.onNotification(apiShowEvent, this.handleApiShow); + } + + async deserializeWebviewPanel(panel: WebviewPanel, state: any) { + let location: string; + try { + location = state.location; + } catch (e) { + location = "/"; + } + + this.setPanel(panel); + this.navigate(typeof location === "string" ? location : "/"); + } + + getPanel(): WebviewPanel { + let { panel } = this; + if (panel) { + if (!panel.visible) { + panel.reveal(); + } + + return panel; + } + + panel = window.createWebviewPanel( + viewType, + "API Explorer", + ViewColumn.Beside, + { + enableFindWidget: true, + enableScripts: true, + localResourceRoots: this.getResourceConfig().localResourceRoots + } + ); + + this.setPanel(panel); + return panel; + } + + getResourceConfig() { + const { extensionPath } = this.client.context; + const path = join(extensionPath, "resources"); + + const scriptUri = Uri.file(join(path, "assets", "api.js")) + .with({ scheme: "vscode-resource" }) + .toString(); + + const styleUri = Uri.file(join(path, "assets", "api.css")) + .with({ scheme: "vscode-resource" }) + .toString(); + + return { + localResourceRoots: [Uri.file(path)], + uris: [ + { + pattern: /%STYLE_URI%/g, + value: styleUri + }, + { + pattern: /%SCRIPT_URI%/g, + value: scriptUri + } + ] + }; + } + + handleApiShow = (location: string) => { + commands.executeCommand("divinity.showApiExplorer", location); + }; + + handleMessage = (message: any) => { + if (typeof message !== "object") return; + const { args, command } = message; + + switch (command) { + case "goto": + this.navigate(args[0]); + break; + case "reload": + this.navigate(this.location, true); + break; + } + }; + + handlePanelDispose = () => { + for (const resource of this.panelResources) { + resource.dispose(); + } + + this.location = ""; + this.panelResources.length = 0; + this.panel = null; + }; + + handleShowApi = (location: string = "/") => { + this.getPanel(); + this.navigate(location); + }; + + async navigate(location: string, force?: boolean) { + const { panel } = this; + if (!panel) return; + if (this.location === location && !force) return; + this.location = location; + + const connection = await this.client.getConnection(); + const result = await connection.sendRequest( + apiRequest, + location + ); + + if (!result) return; + const { uris } = this.getResourceConfig(); + let { content } = result; + + for (const { pattern, value } of uris) { + content = content.replace(pattern, value); + } + + panel.webview.html = content; + } + + setPanel(panel: WebviewPanel) { + this.panelResources.push(panel.onDidDispose(this.handlePanelDispose)); + this.panelResources.push( + panel.webview.onDidReceiveMessage(this.handleMessage) + ); + this.panel = panel; + } +} diff --git a/src/client/features/divProvider/index.ts b/src/client/features/divProvider/index.ts new file mode 100644 index 0000000..9f7d5fd --- /dev/null +++ b/src/client/features/divProvider/index.ts @@ -0,0 +1,58 @@ +import { EventEmitter } from "events"; +import { LanguageClient } from "vscode-languageclient/lib/main"; +import { + ProviderResult, + TextDocumentContentProvider, + Uri, + workspace, + TextDocument +} from "vscode"; + +import Client from "../../Client"; +import Feature from "../Feature"; +import { + divRequestEvent, + divRequestResultEvent, + DivRequestResult +} from "../../../shared/notifications"; + +const scheme = "divinity"; + +export default class DivProviderFeature extends Feature + implements TextDocumentContentProvider { + emitter: EventEmitter = new EventEmitter(); + + constructor(client: Client) { + super(client); + + client.context.subscriptions.push( + workspace.registerTextDocumentContentProvider(scheme, this) + ); + } + + initialize(connection: LanguageClient) { + connection.onNotification(divRequestResultEvent, this.handleDivResult); + } + + handleDivResult = (result: DivRequestResult) => { + this.emitter.emit("result", result); + }; + + async provideTextDocumentContent(uri: Uri): Promise { + const { emitter } = this; + const connection = await this.client.getConnection(); + const uriString = uri.toString(); + + return new Promise(resolve => { + function callback(result: DivRequestResult) { + if (result.uri === uriString) { + emitter.removeListener("result", callback); + resolve(result.content); + } + } + + emitter.addListener("result", callback); + connection.sendNotification(divRequestEvent, uriString); + }); + } +} diff --git a/src/client/features/index.ts b/src/client/features/index.ts new file mode 100644 index 0000000..2e08a47 --- /dev/null +++ b/src/client/features/index.ts @@ -0,0 +1,18 @@ +import Feature, { FeatureFactory } from "./Feature"; + +import ActivityIndicatorFeature from "./activityIndicator"; +import ApiExplorerFeature from "./apiExplorer"; +import DivProviderFeature from "./divProvider"; +import StoryOutlineFeature from "./storyOutline"; +import TaskProviderFeature from "./taskProvider"; + +const factories: Array = [ + ActivityIndicatorFeature, + ApiExplorerFeature, + DivProviderFeature, + StoryOutlineFeature, + TaskProviderFeature +]; + +export { Feature }; +export default factories; diff --git a/src/client/features/storyOutline/index.ts b/src/client/features/storyOutline/index.ts new file mode 100644 index 0000000..95abcb8 --- /dev/null +++ b/src/client/features/storyOutline/index.ts @@ -0,0 +1,359 @@ +import { join, dirname } from "path"; +import { LanguageClient, Event } from "vscode-languageclient"; +import { + commands, + EventEmitter, + ProviderResult, + TreeDataProvider, + TreeItem, + window, + TreeItemCollapsibleState, + Uri, + workspace +} from "vscode"; + +import Client from "../../Client"; +import goalTemplate from "../../../shared/goalTemplate"; +import { Feature } from ".."; +import { unlink, writeFile, rename } from "../../../shared/fs"; + +import { + goalsChangedEvent, + GoalsChanged, + GoalInfo, + ProjectInfo +} from "../../../shared/notifications"; + +import { + renameGoalRequest, + RenameGoalParams, + RenameGoalResult, + MoveGoalParams, + MoveGoalResult, + moveGoalRequest +} from "../../../shared/requests"; + +export default class StoryOutlineFeature extends Feature + implements TreeDataProvider { + emitter: EventEmitter; + iconCustom: { dark: string; light: string }; + iconShared: { dark: string; light: string }; + project: ProjectInfo | null = null; + onDidChangeTreeData: Event; + rootGoals: Array = []; + treeVersion: number = -1; + + constructor(client: Client) { + super(client); + this.emitter = new EventEmitter(); + this.iconCustom = this.createIcon("goal-custom"); + this.iconShared = this.createIcon("goal-shared"); + this.onDidChangeTreeData = this.emitter.event; + + window.registerTreeDataProvider("divinity.storyOutline", this); + + commands.registerCommand( + "divinity.storyOutline.addGoal", + this.handleAddGoal + ); + + commands.registerCommand( + "divinity.storyOutline.deleteGoal", + this.handleDeleteGoal + ); + + commands.registerCommand( + "divinity.storyOutline.moveGoal", + this.handleMoveGoal + ); + + commands.registerCommand( + "divinity.storyOutline.openGoal", + this.handleOpenGoal + ); + + commands.registerCommand( + "divinity.storyOutline.renameGoal", + this.handleRenameGoal + ); + } + + initialize(connection: LanguageClient) { + connection.onNotification(goalsChangedEvent, this.handleGoalsChanged); + } + + collectChildren( + goal: GoalInfo, + result: Array = [] + ): Array { + result.push(...goal.children); + for (const child of goal.children) { + this.collectChildren(child, result); + } + + return result; + } + + createIcon(name: string) { + const { context } = this.client; + return { + dark: context.asAbsolutePath( + join("resources", "icons", `${name}-dark.svg`) + ), + light: context.asAbsolutePath( + join("resources", "icons", `${name}-light.svg`) + ) + }; + } + + findGoal(name: string, scope?: GoalInfo): GoalInfo | null { + const children = scope ? scope.children : this.rootGoals; + for (const child of children) { + if (child.name.toLowerCase() === name.toLowerCase()) { + return child; + } + + const childGoal = this.findGoal(name, child); + if (childGoal) { + return childGoal; + } + } + + return null; + } + + getGoalFileName(name: string): string | undefined { + const { project } = this; + if (!project) return undefined; + return join(project.path, "Story", "RawFiles", "Goals", `${name}.txt`); + } + + getTreeItem(element: GoalInfo): TreeItem { + let state = TreeItemCollapsibleState.None; + if (element.children.length) { + state = TreeItemCollapsibleState.Collapsed; + } + + const { iconCustom, iconShared } = this; + const item = new TreeItem(element.name, state); + item.resourceUri = Uri.parse(element.uri); + item.contextValue = element.isShared ? "sharedGoal" : "customGoal"; + item.iconPath = element.isShared ? iconShared : iconCustom; + item.command = { + command: "divinity.storyOutline.openGoal", + title: "Open Goal", + arguments: [element] + }; + + return item; + } + + getChildren(element?: GoalInfo | undefined): ProviderResult> { + return element ? element.children : this.rootGoals; + } + + getMoveTargets( + goal: GoalInfo, + scope?: GoalInfo, + depth: string = "", + result: Array = [] + ): Array { + const children = scope ? scope.children : this.rootGoals; + for (const child of children) { + if (child !== goal) { + result.push(`${depth}${child.name}`); + this.getMoveTargets(goal, child, `${depth}\t`, result); + } + } + + return result; + } + + handleAddGoal = async (goal?: GoalInfo) => { + let name = await window.showInputBox({ + prompt: "Enter the name of the new goal:" + }); + + name = this.validateNewGoalName(name); + if (!name) return; + + const fileName = this.getGoalFileName(name); + if (!fileName) { + window.showErrorMessage("Cannot create goal: No project opened."); + return; + } + + try { + await writeFile( + fileName, + goalTemplate({ + parents: goal ? [goal.name] : undefined + }) + ); + } catch (error) { + window.showErrorMessage(`Cannot create goal: ${error.message}`); + return; + } + + window.showTextDocument(Uri.file(fileName)); + }; + + handleDeleteGoal = async (goal?: GoalInfo | null) => { + if (!goal) return; + + goal = this.findGoal(goal.name); + if (!goal || goal.isShared) { + window.showErrorMessage("This goal cannot be deleted."); + return; + } + + const goalsToDelete = this.collectChildren(goal).filter( + goal => !goal.isShared + ); + goalsToDelete.push(goal); + + if (goalsToDelete.length > 1) { + const result = await window.showQuickPick(["Yes", "No"], { + placeHolder: `This will delete ${ + goalsToDelete.length + } goals. Are you sure?` + }); + if (result === "No") return; + } + + for (const goalToDelete of goalsToDelete) { + try { + await unlink(Uri.parse(goalToDelete.uri).fsPath); + } catch (error) { + window.showErrorMessage( + `Could not delete "${goalToDelete.name}": ${error.message}` + ); + } + } + }; + + handleMoveGoal = async (goal?: GoalInfo) => { + const { project } = this; + if (!goal || !project) return; + + const targets = this.getMoveTargets(goal); + let newParent = await window.showQuickPick(targets, { + placeHolder: "Select the new parent" + }); + + if (!newParent) return; + const connection = await this.client.getConnection(); + const params: MoveGoalParams = { + goalName: goal.name, + newParent: newParent.trim(), + projectUid: project.meta.UUID + }; + + const result = await connection.sendRequest( + moveGoalRequest, + params + ); + + if (result.error) { + window.showErrorMessage(result.error); + return; + } + + const converter = connection.protocol2CodeConverter; + const workspaceEdit = converter.asWorkspaceEdit(result); + const didEdit = await workspace.applyEdit(workspaceEdit); + if (!didEdit) { + window.showErrorMessage("The move could not be performed."); + return; + } + }; + + handleOpenGoal = (goal?: GoalInfo) => { + if (goal) { + window.showTextDocument(Uri.parse(goal.uri)); + } + }; + + handleRenameGoal = async (goal?: GoalInfo) => { + const { project } = this; + if (!goal || !project) return; + + let newName = await window.showInputBox({ + prompt: "Enter the new name of the goal:", + value: goal.name + }); + + newName = this.validateNewGoalName(newName); + if (!newName) return; + + const connection = await this.client.getConnection(); + const params: RenameGoalParams = { + goalName: goal.name, + newName, + projectUid: project.meta.UUID + }; + + const result = await connection.sendRequest( + renameGoalRequest, + params + ); + + if (result.error) { + window.showErrorMessage(result.error); + return; + } + + const converter = connection.protocol2CodeConverter; + const workspaceEdit = converter.asWorkspaceEdit(result); + const didEdit = await workspace.applyEdit(workspaceEdit); + if (!didEdit) { + window.showErrorMessage("The rename could not be performed."); + return; + } + + const from = Uri.parse(goal.uri).fsPath; + const to = join(dirname(from), `${newName}.txt`); + await rename(from, to); + + window.showTextDocument(Uri.file(to)); + }; + + handleGoalsChanged = (event: GoalsChanged) => { + if (!this.project) { + this.project = event.project; + commands.executeCommand( + "setContext", + "divinity.storyOutline.enabled", + true + ); + } else { + if (event.project.path !== this.project.path) return; + } + + if (event.treeVersion > this.treeVersion) { + this.rootGoals = event.goals; + this.treeVersion = event.treeVersion; + this.emitter.fire(); + } + }; + + validateNewGoalName(name: string | undefined): string | undefined { + if (!name) return undefined; + if (name.endsWith(".txt")) { + name = name.substr(0, name.length - 4); + } + + if (!/^[A-Za-z0-9_-]+$/.test(name)) { + window.showErrorMessage(`The goal name "${name}" is invalid.`); + return undefined; + } + + const existingGoal = this.findGoal(name); + if (existingGoal) { + window.showErrorMessage(`The goal "${name}" already exists.`); + return undefined; + } + + return name; + } +} diff --git a/src/client/features/taskProvider/index.ts b/src/client/features/taskProvider/index.ts new file mode 100644 index 0000000..b994c7f --- /dev/null +++ b/src/client/features/taskProvider/index.ts @@ -0,0 +1,226 @@ +import { join, normalize } from "path"; +import { + ProgressLocation, + ShellExecution, + ShellQuotedString, + ShellQuoting, + Task, + tasks, + TaskDefinition, + TaskGroup, + TaskProcessEndEvent, + TaskProvider, + TaskRevealKind, + TaskStartEvent, + workspace, + window +} from "vscode"; + +import Client from "../../Client"; +import Feature from "../Feature"; +import getPackagePath from "../../../shared/getPackagePath"; +import { + projectAddedEvent, + ProjectInfo, + ProjectEventArgs +} from "../../../shared/notifications"; + +function quotedString(value: string): ShellQuotedString { + return { quoting: ShellQuoting.Strong, value }; +} + +const modes: Array<[string, ReloadMode]> = [ + ["Compile", ReloadMode.None], + ["Compile, reload story", ReloadMode.ReloadStory], + ["Compile, reload story and level", ReloadMode.ReloadLevelAndStory] +]; + +const taskTitle = "Divinity"; +const reloadTaskTitle = "Reload editor"; +const compilerTaskType = "divinity.task.compiler"; +const reloadTaskType = "divinity.task.reload"; +const problemMatcher = "divinity.problemMatcher"; + +export const enum ReloadMode { + None = "", + ReloadStory = "reloadStory", + ReloadLevelAndStory = "reloadLevelAndStory" +} + +export interface DivinityTaskDefinition extends TaskDefinition { + checkNames?: boolean; + checkOnly?: boolean; + gameDataPath: string; + mod: Array; + noWarn?: Array; + output: string; + reload?: ReloadMode; + type: "divinity.task.compiler"; +} + +export default class TaskProviderFeature extends Feature + implements TaskProvider { + projects: Array = []; + tasks: Array = []; + + constructor(client: Client) { + super(client); + + client.addListener(projectAddedEvent, this.handleProjectAdded); + tasks.onDidStartTask(this.handleDidStartTask); + tasks.onDidEndTaskProcess(this.handleDidEndTaskProcess); + workspace.registerTaskProvider(compilerTaskType, this); + } + + getCompilerPath(): string { + return join(getPackagePath(), "bin", "StoryCompiler.exe"); + } + + getRconPath(): string { + return join(getPackagePath(), "bin", "RconClient.exe"); + } + + handleProjectAdded = ({ project }: ProjectEventArgs) => { + const { projects } = this; + const tasks: Array = []; + projects.push(project); + + for (const project of projects) { + for (const [caption, mode] of modes) { + const definition: DivinityTaskDefinition = { + gameDataPath: normalize(join(project.path, "..", "..")), + mod: ["Shared", project.meta.Folder], + output: join(project.path, "Story", "story.div.osi"), + reload: mode, + type: compilerTaskType + }; + + const task = new Task(definition, caption, project.meta.Name); + task.group = TaskGroup.Build; + task.problemMatchers = [problemMatcher]; + task.presentationOptions = { + reveal: TaskRevealKind.Never + }; + + const resolved = this.resolveTask(task); + if (resolved) tasks.push(resolved); + } + } + + this.tasks = tasks; + }; + + handleDidEndTaskProcess = (event: TaskProcessEndEvent) => { + const { definition, scope } = event.execution.task; + if (definition.type !== compilerTaskType) return; + + if (event.exitCode === 0) { + window.showInformationMessage("Story successful compiled"); + } else { + window.showErrorMessage("Story compile failed"); + } + + const { reload } = definition as DivinityTaskDefinition; + if (reload && scope && event.exitCode === 0) { + const task = new Task( + { + type: reloadTaskType + }, + scope, + reloadTaskTitle, + taskTitle, + new ShellExecution(quotedString(this.getRconPath()), [ + "127.0.0.1:5384", + reload + ]) + ); + + task.presentationOptions = { + reveal: TaskRevealKind.Never + }; + + tasks.executeTask(task); + } + }; + + handleDidStartTask = (event: TaskStartEvent) => { + const { definition } = event.execution.task; + if (definition.type !== compilerTaskType) { + return; + } + + const createProgress = () => + new Promise(resolve => { + const listener = tasks.onDidEndTaskProcess(event => { + const { definition } = event.execution.task; + if (definition.type !== compilerTaskType) { + return; + } + + listener.dispose(); + resolve(); + }); + }); + + window.withProgress( + { + cancellable: false, + location: ProgressLocation.Notification, + title: `Compiling...` + }, + createProgress + ); + }; + + provideTasks(): Array { + return this.tasks; + } + + resolveTask(task: Task): Task | undefined { + const { definition } = task; + if (definition.type !== compilerTaskType) { + return undefined; + } + + const { + checkNames, + checkOnly, + gameDataPath, + mod, + noWarn, + output + } = definition as DivinityTaskDefinition; + + const args = [ + "--game-data-path", + quotedString(gameDataPath), + "--output", + quotedString(output) + ]; + + for (const modName of mod) { + args.push("--mod", quotedString(modName)); + } + + if (noWarn) { + for (const noWarnName of noWarn) { + args.push("--no-warn", quotedString(noWarnName)); + } + } + + if (checkOnly) { + args.push("--check-only"); + } + + if (checkNames) { + args.push("--check-names"); + } + + task.execution = new ShellExecution( + quotedString(this.getCompilerPath()), + args + ); + + return task; + } +} diff --git a/src/client/index.ts b/src/client/index.ts new file mode 100644 index 0000000..cafc182 --- /dev/null +++ b/src/client/index.ts @@ -0,0 +1,21 @@ +import { ExtensionContext } from "vscode"; + +import Client from "./Client"; + +let instance: Client | null = null; + +export function activate(context: ExtensionContext) { + if (!instance) { + instance = new Client(context); + } +} + +export function deactivate(): Thenable { + if (!instance) { + return Promise.resolve(); + } + + let result = instance.dispose(); + instance = null; + return result; +} diff --git a/src/server/Server.ts b/src/server/Server.ts new file mode 100644 index 0000000..9d60859 --- /dev/null +++ b/src/server/Server.ts @@ -0,0 +1,253 @@ +import { + createConnection, + Connection, + DidChangeConfigurationNotification, + DidChangeConfigurationParams, + InitializeParams, + InitializeResult, + ProposedFeatures, + ServerCapabilities, + TextDocuments +} from "vscode-languageserver"; + +import Projects from "./projects"; +import features, { Feature } from "./features"; +import { readyEvent } from "../shared/notifications"; + +interface ExampleSettings { + maxNumberOfProblems: number; +} + +const defaultSettings: ExampleSettings = { maxNumberOfProblems: 1000 }; + +let globalSettings: ExampleSettings = defaultSettings; + +export default class Server { + connection: Connection; + documents: TextDocuments; + documentSettings: Map> = new Map(); + features: Array = []; + hasConfigurationCapability: boolean = false; + hasWorkspaceFolderCapability: boolean = false; + hasDiagnosticRelatedInformationCapability: boolean = false; + projects: Projects = new Projects(); + + constructor() { + // Create a connection for the server. The connection uses Node's IPC as a transport. + // Also include all preview / proposed LSP features. + const connection = createConnection(ProposedFeatures.all); + connection.onInitialize(this.handleInitialize); + connection.onInitialized(this.handleInitialized); + connection.onDidChangeConfiguration(this.handleDidChangeConfiguration); + + connection.onExit(() => { + this.projects.dispose(); + this.features.forEach(feature => feature.dispose()); + }); + + // Create a simple text document manager. The text document manager + // supports full document sync only + const documents = new TextDocuments(); + + documents.listen(connection); + connection.listen(); + + this.connection = connection; + this.documents = documents; + } + + getDocumentSettings(resource: string): Thenable { + const { connection, documentSettings, hasConfigurationCapability } = this; + + if (!hasConfigurationCapability) { + return Promise.resolve(globalSettings); + } + + let result = documentSettings.get(resource); + if (!result) { + result = connection.workspace.getConfiguration({ + scopeUri: resource, + section: "osiris" + }); + documentSettings.set(resource, result); + } + + return result; + } + + handleDidChangeConfiguration = (change: DidChangeConfigurationParams) => { + const { documents, documentSettings, hasConfigurationCapability } = this; + + if (hasConfigurationCapability) { + // Reset all cached document settings + documentSettings.clear(); + } else { + globalSettings = ( + (change.settings.languageServerExample || defaultSettings) + ); + } + + // Revalidate all open text documents + // documents.all().forEach(document => this.project.analyze(document)); + }; + + handleInitialize = (params: InitializeParams): InitializeResult => { + const { capabilities } = params; + const { textDocument, workspace } = capabilities; + + this.features = features.map(factory => new factory(this)); + + // Does the client support the `workspace/configuration` request? + // If not, we will fall back using global settings + this.hasConfigurationCapability = !!( + workspace && !!workspace.configuration + ); + + this.hasWorkspaceFolderCapability = !!( + workspace && !!workspace.workspaceFolders + ); + + this.hasDiagnosticRelatedInformationCapability = !!( + textDocument && + textDocument.publishDiagnostics && + textDocument.publishDiagnostics.relatedInformation + ); + + return { + capabilities: this.features.reduce( + (capabilities, feature) => ({ + ...capabilities, + ...feature.getCapabilities() + }), + { + textDocumentSync: this.documents.syncKind + } as ServerCapabilities + ) + }; + }; + + handleInitialized = () => { + const { connection, features, hasConfigurationCapability } = this; + features.forEach(feature => feature.initialize(connection)); + + connection.sendNotification(readyEvent); + + if (hasConfigurationCapability) { + // Register for all configuration changes. + connection.client.register( + DidChangeConfigurationNotification.type, + undefined + ); + } + }; +} + +/* + +async function validateTextDocument(textDocument: TextDocument): Promise { + // In this simple example we get the settings for every validate run. + let settings = await getDocumentSettings(textDocument.uri); + + // The validator creates diagnostics for all uppercase words length 2 and more + let text = textDocument.getText(); + let pattern = /\b[A-Z]{2,}\b/g; + let m: RegExpExecArray; + + let problems = 0; + let diagnostics: Diagnostic[] = []; + while ((m = pattern.exec(text)) && problems < settings.maxNumberOfProblems) { + problems++; + let diagnosic: Diagnostic = { + severity: DiagnosticSeverity.Warning, + range: { + start: textDocument.positionAt(m.index), + end: textDocument.positionAt(m.index + m[0].length) + }, + message: `${m[0]} is all uppercase.`, + source: 'ex' + }; + if (hasDiagnosticRelatedInformationCapability) { + diagnosic.relatedInformation = [ + { + location: { + uri: textDocument.uri, + range: Object.assign({}, diagnosic.range) + }, + message: 'Spelling matters' + }, + { + location: { + uri: textDocument.uri, + range: Object.assign({}, diagnosic.range) + }, + message: 'Particularly for names' + } + ]; + } + diagnostics.push(diagnosic); + } + + // Send the computed diagnostics to VSCode. + connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }); +} + +connection.onDidChangeWatchedFiles(_change => { + // Monitored files have change in VSCode + connection.console.log('We received an file change event'); +}); + +// This handler provides the initial list of the completion items. +connection.onCompletion( + (_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => { + // The pass parameter contains the position of the text document in + // which code complete got requested. For the example we ignore this + // info and always provide the same completion items. + return [ + { + label: 'TypeScript', + kind: CompletionItemKind.Text, + data: 1 + }, + { + label: 'JavaScript', + kind: CompletionItemKind.Text, + data: 2 + } + ]; + } +); + +// This handler resolves additional information for the item selected in +// the completion list. +connection.onCompletionResolve( + (item: CompletionItem): CompletionItem => { + if (item.data === 1) { + item.detail = 'TypeScript details'; + item.documentation = 'TypeScript documentation'; + } else if (item.data === 2) { + item.detail = 'JavaScript details'; + item.documentation = 'JavaScript documentation'; + } + return item; + } +); + + +connection.onDidOpenTextDocument((params) => { + // A text document got opened in VSCode. + // params.uri uniquely identifies the document. For documents store on disk this is a file URI. + // params.text the initial full content of the document. + connection.console.log(`${params.textDocument.uri} opened.`); +}); +connection.onDidChangeTextDocument((params) => { + // The content of a text document did change in VSCode. + // params.uri uniquely identifies the document. + // params.contentChanges describe the content changes to the document. + connection.console.log(`${params.textDocument.uri} changed: ${JSON.stringify(params.contentChanges)}`); +}); +connection.onDidCloseTextDocument((params) => { + // A text document got closed in VSCode. + // params.uri uniquely identifies the document. + connection.console.log(`${params.textDocument.uri} closed.`); +}); +*/ diff --git a/src/server/documentation/Documentation.ts b/src/server/documentation/Documentation.ts new file mode 100644 index 0000000..456d808 --- /dev/null +++ b/src/server/documentation/Documentation.ts @@ -0,0 +1,83 @@ +import { join } from "path"; + +import getPackagePath from "../../shared/getPackagePath"; +import Repository from "./raw/Repository"; +import { CategoryData } from "./raw/Category"; +import { DefinitionDoc } from "./raw/Definition"; +import { readFile } from "../../shared/fs"; + +export interface SymbolCategoryMap { + [symbol: string]: string; +} + +export default class Documentation { + cachePath: string; + repository: Repository | null = null; + useRepository: boolean = false; + + constructor() { + this.cachePath = join(getPackagePath(), "docs", "cache"); + } + + async getCategory(name: string): Promise { + if (this.useRepository) { + const repository = this.getRepository(); + const category = repository.getCategory(name); + + return category ? category.getCategoryData() : null; + } + + const cacheFile = join(this.cachePath, `category.${name}.json`); + return this.readCache(cacheFile); + } + + async getDocumentation(name: string): Promise { + if (this.useRepository) { + const repository = this.getRepository(); + const definition = repository.getDefinition(name); + + return definition ? definition.getDocumentation() : null; + } + + const cacheFile = join( + this.cachePath, + `definition.${name.toLowerCase()}.json` + ); + + return this.readCache(cacheFile); + } + + getRepository() { + if (!this.repository) { + this.repository = new Repository(); + } + + return this.repository; + } + + async getSymbolCategories(): Promise { + if (this.useRepository) { + const result: SymbolCategoryMap = {}; + const repository = this.getRepository(); + + for (const definition of repository.definitions) { + const searchName = definition.name.toLowerCase(); + result[searchName] = definition.category.qualifiedName; + } + + return result; + } + + const cacheFile = join(this.cachePath, `index.json`); + return this.readCache(cacheFile); + } + + async readCache(path: string): Promise { + try { + const data = await readFile(path, { encoding: "utf-8" }); + return JSON.parse(data) as T; + } catch (error) { + return null; + } + } +} diff --git a/src/server/documentation/commands/compile.ts b/src/server/documentation/commands/compile.ts new file mode 100644 index 0000000..15ef02a --- /dev/null +++ b/src/server/documentation/commands/compile.ts @@ -0,0 +1,13 @@ +import { normalize, join } from "path"; + +import Repository from "../raw/Repository"; + +const repositoryPath = normalize(join(process.cwd(), process.argv[2])); +const repository = new Repository(repositoryPath); + +console.log(""); +repository.compile().then(() => { + console.log("Done!"); + console.log(""); + process.exit(); +}); diff --git a/src/server/documentation/commands/update.ts b/src/server/documentation/commands/update.ts new file mode 100644 index 0000000..f75455e --- /dev/null +++ b/src/server/documentation/commands/update.ts @@ -0,0 +1,15 @@ +import { normalize, join } from "path"; + +import Repository from "../raw/Repository"; + +const repositoryPath = normalize(join(process.cwd(), process.argv[2])); +const projectPath = normalize(join(process.cwd(), process.argv[3])); + +const repository = new Repository(repositoryPath); + +console.log(""); +repository.update(projectPath).then(() => { + console.log("Done!"); + console.log(""); + process.exit(); +}); diff --git a/src/server/documentation/raw/Category.ts b/src/server/documentation/raw/Category.ts new file mode 100644 index 0000000..7874ef2 --- /dev/null +++ b/src/server/documentation/raw/Category.ts @@ -0,0 +1,97 @@ +import { readdirSync, statSync } from "fs"; +import { join, extname, basename } from "path"; + +import Definition from "./Definition"; +import ucfirst from "../../utils/ucfirst"; + +export interface CategoryInfoData { + displayName: string; + name: string; + qualifiedName: string; +} + +export interface CategoryData extends CategoryInfoData { + children: Array; + parents: Array; +} + +export default class Category { + definitions: Array; + displayName: string; + name: string; + children: Array; + parent: Category | undefined; + path: string; + qualifiedName: string; + + constructor(path: string, parent?: Category) { + const definitions: Array = []; + const names = readdirSync(path); + const namespaces: Array = []; + + this.name = parent ? basename(path) : "root"; + this.qualifiedName = parent + ? `${parent.qualifiedName}.${this.name}` + : this.name; + + for (const name of names) { + const fileName = join(path, name); + const stats = statSync(fileName); + + if (stats.isDirectory()) { + namespaces.push(new Category(fileName, this)); + } else if (extname(fileName) === ".yml") { + definitions.push(new Definition(fileName, this)); + } + } + + let displayName = ucfirst(this.name); + if (!parent) { + displayName = "Divinity API"; + } + + this.definitions = definitions; + this.displayName = displayName; + this.children = namespaces; + this.parent = parent; + this.path = path; + } + + getAllCategories(): Array { + return this.children.reduce( + (result, category) => { + return [...result, ...category.getAllCategories()]; + }, + [this] as Array + ); + } + + getAllDefinitions(): Array { + return this.children.reduce((result, category) => { + return [...result, ...category.getAllDefinitions()]; + }, this.definitions); + } + + getCategoryInfoData(): CategoryInfoData { + return { + displayName: this.displayName, + name: this.name, + qualifiedName: this.qualifiedName + }; + } + + getCategoryData(): CategoryData { + return { + ...this.getCategoryInfoData(), + children: this.children.map(child => child.getCategoryInfoData()), + parents: this.getParents().map(parent => parent.getCategoryInfoData()) + }; + } + + getParents(): Array { + const { parent } = this; + const result: Array = parent ? parent.getParents() : []; + if (parent) result.push(parent); + return result; + } +} diff --git a/src/server/documentation/raw/Definition.ts b/src/server/documentation/raw/Definition.ts new file mode 100644 index 0000000..ac2cd7b --- /dev/null +++ b/src/server/documentation/raw/Definition.ts @@ -0,0 +1,115 @@ +import { basename } from "path"; +import { existsSync, readFileSync, writeFileSync } from "fs"; + +import Category from "./Category"; +import printSymbol from "../../projects/story/utils/printSymbol"; +import printSymbolType from "../../projects/story/utils/printSymbolType"; +import sleep from "../../utils/sleep"; +import Symbol from "../../projects/story/Symbol"; +import WikiParser from "./WikiReader"; +import { + SymbolDoc, + SymbolParameterDoc +} from "../../projects/story/models/symbol"; + +export interface DefinitionParameterDoc extends SymbolParameterDoc { + customDescription?: string; +} + +export interface DefinitionDoc extends SymbolDoc { + customDescription?: string; + overloads?: Array; + signature?: string; + type?: string; +} + +export default class Definition { + category: Category; + data: DefinitionDoc; + name: string; + path: string; + + constructor(path: string, category: Category) { + const { safeLoad } = require("js-yaml"); + + if (existsSync(path)) { + try { + this.data = safeLoad(readFileSync(path, "utf-8")); + } catch (error) { + throw new Error(`Could not load "${path}": ${error.message}`); + } + } else { + this.data = {}; + } + + this.category = category; + this.name = basename(path, ".yml"); + this.path = path; + } + + addOverload(symbol: Symbol) { + const { data } = this; + const overloads = data.overloads || (data.overloads = []); + overloads.push(printSymbol(symbol)); + } + + async apply(symbol: Symbol) { + console.log(`Fetching ${symbol.name}...`); + const wiki = new WikiParser(); + await sleep(); + await wiki.load(symbol.name); + + const { data } = this; + data.signature = printSymbol(symbol); + data.type = printSymbolType(symbol.type); + + if (data.overloads) { + data.overloads.length = 0; + } + + data.description = wiki.getDescription(); + + for (let index = 0; index < symbol.parameters.length; index++) { + const target = data.parameters || (data.parameters = []); + while (target.length <= index) { + target.push({}); + } + + const name = symbol.parameters[index].name; + target[index].name = name; + target[index].description = wiki.getParameter(name); + } + } + + getDocumentation(): DefinitionDoc { + const result = { ...this.data }; + if (result.customDescription) { + result.description = result.customDescription; + delete result.customDescription; + } + + if (result.parameters) { + result.parameters = result.parameters.map(parameter => { + const result = { ...parameter }; + if (result.customDescription) { + result.description = result.customDescription; + delete result.customDescription; + } + + return result; + }); + } + + return result; + } + + save() { + const { safeDump } = require("js-yaml"); + const { data } = this; + if (data.overloads && data.overloads.length === 0) { + delete data.overloads; + } + + writeFileSync(this.path, safeDump(this.data, { lineWidth: 200 }), "utf-8"); + } +} diff --git a/src/server/documentation/raw/Repository.ts b/src/server/documentation/raw/Repository.ts new file mode 100644 index 0000000..2df4210 --- /dev/null +++ b/src/server/documentation/raw/Repository.ts @@ -0,0 +1,129 @@ +import { join } from "path"; + +import Category from "./Category"; +import Definition from "./Definition"; +import getPackagePath from "../../../shared/getPackagePath"; +import Project from "../../projects/Project"; +import Projects from "../../projects"; +import Symbol from "../../projects/story/Symbol"; +import Documentation from "../Documentation"; +import { mkdirSync } from "fs"; +import { writeFile } from "../../../shared/fs"; + +export default class Repository { + categories: Array; + definitions: Array; + path: string; + rootCategory: Category; + + constructor(path: string = join(getPackagePath(), "docs")) { + const root = new Category(join(path, "definitions")); + + this.categories = root.getAllCategories(); + this.definitions = root.getAllDefinitions(); + this.path = path; + this.rootCategory = root; + } + + async compile() { + const rimraf = require("rimraf"); + const cachePath = join(this.path, "cache"); + rimraf.sync(cachePath); + mkdirSync(cachePath); + + const docs = new Documentation(); + docs.repository = this; + docs.useRepository = true; + + let data: any = await docs.getSymbolCategories(); + await writeFile(join(cachePath, "index.json"), JSON.stringify(data)); + + for (const category of this.categories) { + data = category.getCategoryData(); + await writeFile( + join(cachePath, `category.${category.qualifiedName}.json`), + JSON.stringify(data) + ); + } + + for (const definition of this.definitions) { + data = definition.getDocumentation(); + await writeFile( + join(cachePath, `definition.${definition.name.toLowerCase()}.json`), + JSON.stringify(data) + ); + } + } + + createDefinition(name: string): Definition { + let definition = this.getDefinition(name); + if (definition) return definition; + + const fileName = join(this.rootCategory.path, `${name}.yml`); + definition = new Definition(fileName, this.rootCategory); + + this.rootCategory.definitions.push(definition); + this.definitions.push(definition); + return definition; + } + + getCategory(name: string): Category | undefined { + return this.categories.find(category => category.qualifiedName === name); + } + + getDefinition(name: string): Definition | undefined { + name = name.toLowerCase(); + return this.definitions.find( + definition => definition.name.toLowerCase() === name + ); + } + + async update(path: string) { + const projects = new Projects(); + const project = new Project(projects, { + path, + meta: { + Folder: "", + Name: "Divinity Engine", + UUID: "00000000-0000-0000-0000-000000000000" + } + }); + + console.log("Loading project..."); + project.initialize(); + await project.story.whenReady(); + + console.log("Collecting symbols..."); + await this.updateDefinitions(project.story.symbols.symbols); + + projects.dispose(); + } + + async updateDefinitions(symbols: Array) { + const definitions: Array = []; + let definition: Definition | undefined; + + for (const symbol of symbols) { + if (symbol.isSystem) { + const definition = this.createDefinition(symbol.name); + await definition.apply(symbol); + definitions.push(definition); + } else { + definition = this.getDefinition(symbol.name); + if (definition) { + definition.addOverload(symbol); + } + } + } + + for (const definition of definitions) { + definition.save(); + } + + for (const oldDefinition of this.definitions) { + if (!definitions.some(def => def.name === oldDefinition.name)) { + console.log(`Deprecated definition: ${oldDefinition.name}`); + } + } + } +} diff --git a/src/server/documentation/raw/WikiReader.ts b/src/server/documentation/raw/WikiReader.ts new file mode 100644 index 0000000..315abc0 --- /dev/null +++ b/src/server/documentation/raw/WikiReader.ts @@ -0,0 +1,254 @@ +import fetch from "../../utils/fetch"; +import { SymbolData } from "../../features/apiExplorer/Handler"; +import Project from "../../projects/Project"; +import printSymbolType from "../../projects/story/utils/printSymbolType"; + +const wikiUrl = "https://docs.larian.game"; +const wikiApiPath = "Osiris/API/"; + +function extractContent(value: string): string { + const titleTag = /^<(h[1-6])/.exec(value); + if (titleTag) { + const end = value.indexOf(``); + if (end !== -1) { + value = value.substr(end); + } + } + + return sanitize(value).trim(); +} + +function extractParameters(value: string): Array { + const matcher = /]*>(.*?)<\/li>/g; + const result: Array = []; + let match: RegExpExecArray | null; + + while ((match = matcher.exec(value))) { + const chunk = sanitize(match[1]).trim(); + const splitAt = /[: ]/.exec(chunk); + if (splitAt) { + result.push({ + content: chunk.substr(splitAt.index + 1).trim(), + name: chunk.substr(0, splitAt.index).trim() + }); + } + } + + return result; +} + +function sanitize(value: string): string { + return value.replace(/<[^>]*>/g, ""); +} + +function symbolFromPath(path?: string): string | null { + if (!path) return null; + if (path.startsWith("/")) path = path.substr(1); + + const params = /index\.php\?title=([^&]+)/.exec(path); + if (params) path = params[1]; + + if (!path.startsWith(wikiApiPath)) return null; + + path = path.substr(wikiApiPath.length); + if (path.indexOf("#") !== -1) path = path.substr(0, path.indexOf("#")); + if (path.indexOf("?") !== -1) path = path.substr(0, path.indexOf("?")); + return path; +} + +function transformLink(string: string, url: string): string { + const symbolName = symbolFromPath(url); + if (symbolName) { + return `href="#" data-goto="/definition/${symbolName}"`; + } else { + return `href="${wikiUrl}${url}"`; + } +} + +function transformLinks(string: string): string { + return string.replace(/href="([^"]*)"/g, transformLink); +} + +export interface WikiData { + links: Array<{ + "*": string; + }>; + sections: Array<{ + anchor: string; + line: string; + }>; + text: { + "*": string; + }; +} + +export interface WikiSection { + content: string; + title: string; +} + +export interface WikiParameter { + content: string; + name: string; +} + +export default class WikiParser { + code: number = -1; + data: WikiData | undefined; + title: string = ""; + private parameters: Array | undefined; + private sections: Array | undefined; + private text: string = ""; + + async load(title: string): Promise { + const { code, data } = await this.fetch(title); + this.code = code; + this.data = data; + this.sections = undefined; + this.text = data ? data.text["*"] : ""; + this.title = title; + + return code; + } + + appendLinkedSymbols( + project: Project, + symbols: Array + ): Array { + const { data } = this; + if (!data) return symbols; + + for (const link of data.links) { + const name = symbolFromPath(link["*"]); + if (!name) continue; + + const compare = name.toLowerCase(); + if (symbols.some(({ name }) => name.toLowerCase() === compare)) { + continue; + } + + const storySymbols = project.story.symbols.findSymbols(name); + if (storySymbols.length) { + symbols.push({ + name, + type: printSymbolType(storySymbols[0].type) + }); + } + } + + return symbols; + } + + getApiContent(): string { + return this.getSections() + .filter( + section => + section.title.indexOf("Definition") === -1 && + section.title.indexOf("See") === -1 + ) + .map(section => section.content) + .join(""); + } + + getDescription(): string { + const description = this.getSections().find( + section => section.title.indexOf("Description") !== -1 + ); + + return description ? extractContent(description.content) : ""; + } + + getEditLink(): string { + const params = [ + "action=edit", + `title=${encodeURIComponent(`${wikiApiPath}${this.title}`)}` + ]; + + return `${wikiUrl}/index.php?${params.join("&")}`; + } + + getParameter(name: string): string { + name = name.toLowerCase(); + const parameter = this.getParameters().find( + paramater => paramater.name.toLowerCase() === name + ); + + return parameter ? parameter.content : ""; + } + + getParameters() { + if (!this.parameters) { + const parameters = this.getSections().find( + section => section.title.indexOf("Parameters") !== -1 + ); + + this.parameters = parameters ? extractParameters(parameters.content) : []; + } + + return this.parameters; + } + + getSections(): Array { + if (!this.sections) { + const { text } = this; + const splitter = /; + variables: Array; +} + +export default class Feature { + readonly server: Server; + + constructor(server: Server) { + this.server = server; + } + + dispose(): void {} + + getCapabilities(): Partial { + return {}; + } + + async getNodesAt({ + position, + textDocument + }: LocationOptions): Promise<{ + nodes?: Array; + resource?: Resource; + }> { + const { projects } = this.server; + const resource = await projects.findResource(textDocument.uri); + if (!resource) return {}; + + const nodes = await resource.getNodesAt(position); + if (!nodes) return {}; + + nodes.reverse(); + return { resource, nodes }; + } + + async getSymbolAt( + options: LocationOptions + ): Promise<{ + nodes?: Array; + resource?: Resource; + symbol?: Symbol; + }> { + const { nodes, resource } = await this.getNodesAt(options); + if (!nodes || !resource) return { nodes, resource }; + + for (const node of nodes) { + if (isCallerNode(node) && node.symbol) { + return { nodes, resource, symbol: node.symbol }; + } + } + + return { nodes, resource }; + } + + getVariablesAt(nodes?: Array): VariablesAt | undefined { + if (!nodes) { + return undefined; + } + + const ruleIndex = nodes.findIndex(node => node.type === NodeType.Rule); + if (ruleIndex === -1) { + return undefined; + } + + const rule = nodes[ruleIndex] as RuleNode; + let result: VariablesAt = { rule, variablesBefore: [], variables: [] }; + + for (const { node, variablesBefore, variables } of eachRuleNode(rule)) { + result = { rule, variablesBefore, variables }; + + const index = nodes.indexOf(node); + if (index !== -1 && index < ruleIndex) { + break; + } + } + + return result; + } + + initialize(connection: Connection): void {} +} diff --git a/src/server/features/activityIndicator/index.ts b/src/server/features/activityIndicator/index.ts new file mode 100644 index 0000000..4ab7098 --- /dev/null +++ b/src/server/features/activityIndicator/index.ts @@ -0,0 +1,59 @@ +import Feature from "../Feature"; +import Project from "../../projects/Project"; +import Server from "../../Server"; + +import { + levelIndexReadyEvent, + levelIndexStartEvent, + projectAddedEvent, + ProjectEventArgs, + projectReadyEvent, + ShowErrorArgs, + showErrorEvent +} from "../../../shared/notifications"; + +export default class ActivityIndicatorFeature extends Feature { + treeVersion: number = 0; + + constructor(server: Server) { + super(server); + + server.projects.on("levelInitStart", this.handleLevelInitStart); + server.projects.on("levelInitReady", this.handleLevelInitReady); + + server.projects.on("projectAdded", this.handleProjectAdded); + server.projects.on("projectReady", this.handleProjectReady); + + server.projects.on("showError", this.handleShowError); + } + + handleLevelInitStart = (project: Project) => { + this.server.connection.sendNotification(levelIndexStartEvent, { + project: project.getInfo() + } as ProjectEventArgs); + }; + + handleLevelInitReady = (project: Project) => { + this.server.connection.sendNotification(levelIndexReadyEvent, { + project: project.getInfo() + } as ProjectEventArgs); + }; + + handleProjectAdded = (project: Project) => { + this.server.connection.sendNotification(projectAddedEvent, { + project: project.getInfo() + } as ProjectEventArgs); + }; + + handleProjectReady = (project: Project) => { + this.server.connection.sendNotification(projectReadyEvent, { + project: project.getInfo() + } as ProjectEventArgs); + }; + + handleShowError = (message: string) => { + this.server.connection.sendNotification(showErrorEvent, { + message + } as ShowErrorArgs); + }; +} diff --git a/src/server/features/apiExplorer/CategoryHandler.ts b/src/server/features/apiExplorer/CategoryHandler.ts new file mode 100644 index 0000000..0d293eb --- /dev/null +++ b/src/server/features/apiExplorer/CategoryHandler.ts @@ -0,0 +1,40 @@ +import Handler, { groupSymbols } from "./Handler"; +import { CategoryData } from "../../documentation/raw/Category"; + +export interface Parameters { + category: CategoryData; + location: string; +} + +export default class CategoryHandler extends Handler { + async canHandle(location: string): Promise { + const documentation = this.getDocumentation(); + let category: CategoryData | null = null; + + if (location === "/") { + category = await documentation.getCategory("root"); + } + + const match = /^\/category\/(.*)/.exec(location); + if (match) { + category = await documentation.getCategory(match[1]); + } + + return category ? { category, location } : undefined; + } + + async getResponse({ category, location }: Parameters): Promise { + await this.feature.loadPartial("breadcrumbs"); + await this.feature.loadPartial("definitions"); + const symbols = await this.getSymbols(category.qualifiedName); + + return this.render({ + location, + template: "category", + context: { + category, + symbols: groupSymbols(symbols) + } + }); + } +} diff --git a/src/server/features/apiExplorer/DefinitionHandler.ts b/src/server/features/apiExplorer/DefinitionHandler.ts new file mode 100644 index 0000000..443e293 --- /dev/null +++ b/src/server/features/apiExplorer/DefinitionHandler.ts @@ -0,0 +1,96 @@ +import Handler, { SymbolData, groupSymbols } from "./Handler"; +import printParameterType from "../../projects/story/utils/printParameterType"; +import printParameterFlow from "../../projects/story/utils/printParameterFlow"; +import printSymbolType from "../../projects/story/utils/printSymbolType"; +import Symbol from "../../projects/story/Symbol"; +import ucfirst from "../../utils/ucfirst"; +import WikiParser from "../../documentation/raw/WikiReader"; +import { CategoryData } from "../../documentation/raw/Category"; +import { SymbolType } from "../../projects/story/models/symbol"; + +export interface Parameters { + category: CategoryData; + location: string; + signatures: Array; +} + +export default class DefinitionHandler extends Handler { + async canHandle(location: string): Promise { + const match = /^\/definition\/(.*)/.exec(location); + if (!match) return undefined; + + const project = await this.feature.getProject(); + const signatures = project.story.symbols + .findSymbols(match[1]) + .filter(symbol => symbol.type !== SymbolType.Unknown); + if (!signatures.length) return undefined; + + const categoryName = signatures[0].category; + if (!categoryName) return undefined; + + const category = await this.getDocumentation().getCategory(categoryName); + if (!category) return undefined; + + return { category, location, signatures }; + } + + async loadWiki(name: string, symbols: Array) { + const parser = new WikiParser(); + const statusCode = await parser.load(name); + const editLink = parser.getEditLink(); + + if (statusCode === -1) { + return { editLink, error: true }; + } else if (statusCode !== 200) { + return { editLink, notFound: true }; + } + + const project = await this.feature.getProject(); + parser.appendLinkedSymbols(project, symbols); + + return { + content: parser.getApiContent(), + editLink + }; + } + + async getResponse({ + category, + location, + signatures + }: Parameters): Promise { + await this.feature.loadPartial("breadcrumbs"); + await this.feature.loadPartial("definitions"); + + const signature = signatures[0]; + const type = printSymbolType(signature.type); + + const allSymbols = await this.getSymbols(category.qualifiedName); + const symbols = allSymbols.filter(symbol => symbol.name !== signature.name); + const wiki = await this.loadWiki(signature.name, symbols); + + return this.render({ + location, + template: "definition", + context: { + category, + signatures: signatures.map(signature => ({ + name: signature.name, + parameters: signature.parameters.map(parameter => ({ + flow: parameter.flow + ? printParameterFlow(parameter.flow) + : undefined, + name: parameter.name, + type: parameter.type + ? printParameterType(parameter.type) + : undefined + })) + })), + symbols: groupSymbols(symbols), + title: `${ucfirst(type)} ${signature.name}`, + type, + wiki + } + }); + } +} diff --git a/src/server/features/apiExplorer/Handler.ts b/src/server/features/apiExplorer/Handler.ts new file mode 100644 index 0000000..3ddeb11 --- /dev/null +++ b/src/server/features/apiExplorer/Handler.ts @@ -0,0 +1,112 @@ +import ApiExplorerFeature from "./index"; +import Documentation from "../../documentation/Documentation"; +import printSymbol from "../../projects/story/utils/printSymbol"; +import { SymbolType } from "../../projects/story/models/symbol"; +import printSymbolType from "../../projects/story/utils/printSymbolType"; +import ucfirst from "../../utils/ucfirst"; + +export interface SymbolData { + name: string; + type: string; +} + +export interface SymbolGroup { + symbols: Array; + title: string; +} + +export function sortSymbols(a: SymbolData, b: SymbolData) { + return a.name.localeCompare(b.name); +} + +export function groupSymbols(symbols: Array): Array { + const groups: { [type: string]: SymbolGroup } = {}; + for (const symbol of symbols) { + if (!(symbol.type in groups)) { + let title = `${ucfirst(symbol.type)}s`; + if (title === "Querys") title = "Queries"; + groups[symbol.type] = { symbols: [], title }; + } + + groups[symbol.type].symbols.push(symbol); + } + + return Object.keys(groups) + .sort() + .map(key => { + groups[key].symbols.sort(sortSymbols); + return groups[key]; + }); +} + +export default abstract class Handler { + feature: ApiExplorerFeature; + + constructor(feature: ApiExplorerFeature) { + this.feature = feature; + } + + abstract async canHandle(location: string): Promise; + + abstract async getResponse(params: T): Promise; + + getDocumentation(): Documentation { + return this.feature.server.projects.docProvider; + } + + getNonce() { + let text = ""; + const possible = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for (let i = 0; i < 32; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + + return text; + } + + async getSymbols(categoryName: string): Promise> { + const result: Array = []; + const nameMap: { [name: string]: SymbolData } = {}; + const project = await this.feature.getProject(); + const { symbols } = project.story.symbols; + + for (const symbol of symbols) { + const { category, name } = symbol; + if (name in nameMap || !category || !category.startsWith(categoryName)) { + continue; + } + + const data: SymbolData = { + name: symbol.name, + type: printSymbolType(symbol.type) + }; + + nameMap[name] = data; + result.push(data); + } + + return result; + } + + async render({ + context, + location, + template + }: { + context: any; + location: string; + template: string; + }) { + const { feature } = this; + const page = await feature.getTemplate(template); + const content = page(context); + + const layout = await feature.getTemplate("layout"); + return layout({ + content, + location, + nonce: this.getNonce() + }); + } +} diff --git a/src/server/features/apiExplorer/index.ts b/src/server/features/apiExplorer/index.ts new file mode 100644 index 0000000..b2dc700 --- /dev/null +++ b/src/server/features/apiExplorer/index.ts @@ -0,0 +1,106 @@ +import { compile, registerPartial, registerHelper } from "handlebars"; +import { join } from "path"; + +import CategoryHandler from "./CategoryHandler"; +import DefinitionHandler from "./DefinitionHandler"; +import getPackagePath from "../../../shared/getPackagePath"; +import Handler from "./Handler"; +import Project from "../../projects/Project"; +import runSafeAsync from "../../utils/runSafeAsync"; +import Server from "../../Server"; +import { apiRequest, ApiResult } from "../../../shared/requests"; +import { Feature } from ".."; +import { readFile } from "../../../shared/fs"; + +export default class ApiExplorerFeature extends Feature { + handlers: Array | undefined; + partials: { [name: string]: boolean } = {}; + templates: { [name: string]: HandlebarsTemplateDelegate } = {}; + + constructor(server: Server) { + super(server); + + const { connection } = server; + connection.onRequest(apiRequest, (location, token) => + runSafeAsync( + () => this.handleApiRequest(location), + null, + `Error while fetching api ${location}`, + token + ) + ); + } + + getHandlers(): Array { + let { handlers } = this; + if (!handlers) { + this.handlers = handlers = [ + new CategoryHandler(this), + new DefinitionHandler(this) + ]; + } + + return handlers; + } + + async getProject(): Promise { + const { projects } = this.server; + if (projects.projects.length) { + const project = projects.projects[0]; + if (!project.story.isInitializing) { + return project; + } + } + + return new Promise(resolve => { + function onProjectReady(project: Project) { + projects.removeListener("projectReady", onProjectReady); + resolve(project); + } + + projects.addListener("projectReady", onProjectReady); + }); + } + + async getTemplate(name: string) { + const { templates } = this; + if (!(name in this.templates)) { + templates[name] = await this.loadTemplate("pages", name); + } + + return templates[name]; + } + + async handleApiRequest(location: string): Promise { + const handlers = this.getHandlers(); + for (const handler of handlers) { + const params = await handler.canHandle(location); + if (params) { + const content = await handler.getResponse(params); + return { content, location }; + } + } + + return null; + } + + async loadPartial(name: string) { + if (!this.partials[name]) { + registerPartial(name, await this.loadTemplate("partials", name)); + this.partials[name] = true; + } + } + + private async loadTemplate(group: string, name: string) { + const fileName = join( + getPackagePath(), + "resources", + "templates", + group, + `${name}.hbs` + ); + + const input = await readFile(fileName, { encoding: "utf-8" }); + return compile(input); + } +} diff --git a/src/server/features/completion/index.ts b/src/server/features/completion/index.ts new file mode 100644 index 0000000..49fab2b --- /dev/null +++ b/src/server/features/completion/index.ts @@ -0,0 +1,335 @@ +import { + ServerCapabilities, + CompletionParams, + CompletionItem, + CompletionItemKind +} from "vscode-languageserver"; + +import printSymbol from "../../projects/story/utils/printSymbol"; +import printSymbolType from "../../projects/story/utils/printSymbolType"; +import Project from "../../projects/Project"; +import Resource from "../../projects/story/resources/Resource"; +import runSafeAsync from "../../utils/runSafeAsync"; +import Server from "../../Server"; +import Symbol from "../../projects/story/Symbol"; +import ucfirst from "../../utils/ucfirst"; +import unpackPosition from "../../parsers/story/utils/unpackPosition"; +import { Feature } from ".."; +import { NodeType, AnyNode } from "../../parsers/story/models/nodes"; +import { SymbolType } from "../../projects/story/models/symbol"; +import printParameterType from "../../projects/story/utils/printParameterType"; + +const SYMBOL_DATA = "divinity.symbol:"; + +const KEYWORDS: Array = [ + // Better handeled by snippets + // "IF", + // "PROC", + // "QRY", + // "AND", + + "THEN", + "NOT", + "INITSECTION", + "KBSECTION", + "EXITSECTION", + "ENDEXITSECTION", + "GoalCompleted" +].map(keyword => ({ + label: keyword, + kind: 14 as any // CompletionItemKind.Keyword +})); + +export enum CompletionType { + Condition, + Events, + Global, + Parameter, + Procedures, + Queries, + Rule, + Type +} + +function fromRuleType(ruleType: string, type: CompletionType): CompletionType { + if (ruleType === "IF") { + return CompletionType.Events; + } else if (ruleType === "PROC") { + return CompletionType.Procedures; + } else if (ruleType === "QRY") { + return CompletionType.Queries; + } + + return type; +} + +export default class CompletionFeature extends Feature { + constructor(server: Server) { + super(server); + + const { connection } = server; + connection.onCompletion((params, token) => + runSafeAsync( + () => this.handleCompletion(params), + null, + `Error while computing completions for ${params.textDocument.uri}`, + token + ) + ); + + connection.onCompletionResolve((params, token) => + this.handleResolveCompletion(params) + ); + } + + getCapabilities(): Partial { + return { + completionProvider: { + resolveProvider: true + } + }; + } + + getConditionCompletions(resource: Resource): Array { + const { symbols } = resource.story.symbols; + return this.getSymbolCompletions( + resource.story.project, + symbols.filter( + symbol => + symbol.type === SymbolType.Database || + symbol.type === SymbolType.Query + ) + ); + } + + getEventCompletions(resource: Resource): Array { + const { symbols } = resource.story.symbols; + return this.getSymbolCompletions( + resource.story.project, + symbols.filter( + symbol => + symbol.type === SymbolType.Database || + symbol.type === SymbolType.Event + ) + ); + } + + getGlobalCompletions(resource: Resource): Array { + const { symbols } = resource.story.symbols; + return this.getSymbolCompletions( + resource.story.project, + symbols.filter( + symbol => + symbol.type === SymbolType.Call || symbol.type === SymbolType.Database + ) + ); + } + + getParameterCompletions( + resource: Resource, + nodes?: Array + ): Array { + const { instances } = resource.story.project.levels; + const result: Array = instances.map(instance => ({ + kind: CompletionItemKind.Reference, + label: `${instance.name}_${instance.guid}` + })); + + const variablesAt = this.getVariablesAt(nodes); + if (variablesAt) { + for (const variable of variablesAt.variablesBefore) { + result.push({ + detail: printParameterType(variable.type), + kind: CompletionItemKind.Variable, + label: variable.displayName + }); + } + } + + return result; + } + + getProceduresCompletions(resource: Resource): Array { + const { symbols } = resource.story.symbols; + return this.getSymbolCompletions( + resource.story.project, + symbols.filter(symbol => symbol.type === SymbolType.Call) + ); + } + + getQueriesCompletions(resource: Resource): Array { + const { symbols } = resource.story.symbols; + return this.getSymbolCompletions( + resource.story.project, + symbols.filter(symbol => symbol.type === SymbolType.Query) + ); + } + + getSymbolCompletions( + project: Project, + symbols: Array + ): Array { + const names: { [name: string]: boolean } = {}; + const result: Array = []; + + for (const symbol of symbols) { + if (symbol.name in names) continue; + names[symbol.name] = true; + + let kind: CompletionItemKind = CompletionItemKind.Struct; + switch (symbol.type) { + case SymbolType.Call: + kind = CompletionItemKind.Function; + break; + case SymbolType.Database: + kind = CompletionItemKind.Enum; + break; + case SymbolType.Event: + kind = CompletionItemKind.Event; + break; + case SymbolType.Query: + kind = CompletionItemKind.Interface; + break; + default: + continue; + } + + result.push({ + data: `${SYMBOL_DATA}${project.meta.UUID}`, + kind, + label: symbol.name + }); + } + + return result.concat(KEYWORDS); + } + + getTypeCompletions(resource: Resource): Array { + const { types } = resource.story; + return types.map(type => ({ + kind: CompletionItemKind.TypeParameter, + label: type + })); + } + + async handleCompletion( + params: CompletionParams + ): Promise | null> { + const { nodes, resource } = await this.getNodesAt(params); + if (!resource) { + return null; + } + + const document = resource.getDocument(); + let type: CompletionType = CompletionType.Global; + + if (document && nodes) { + const offset = document.offsetAt(params.position); + for (const node of nodes) { + if (node.type === NodeType.TypeAnnotation) { + type = CompletionType.Type; + break; + } + + if ( + node.type === NodeType.Signature && + node.identifier.endOffset < offset + ) { + const chunk = document.getText({ + start: unpackPosition(node.identifier.endPosition), + end: params.position + }); + + type = /\([^\)]*$/.test(chunk.substr(1)) + ? CompletionType.Type + : CompletionType.Parameter; + break; + } + + if (node.type === NodeType.ActionBlock) { + type = CompletionType.Global; + break; + } + + if (node.type === NodeType.ConditionBlock) { + type = CompletionType.Condition; + break; + } + + if (node.type === NodeType.Rule) { + if (offset > node.signature.endOffset) { + type = CompletionType.Condition; + } else { + type = fromRuleType(node.ruleType, type); + } + break; + } + } + } + + if (document && type === CompletionType.Global) { + const chunk = document.getText({ + start: document.positionAt( + Math.max(0, document.offsetAt(params.position) - 64) + ), + end: params.position + }); + + const match = /(AND|IF|PROC|QRY)[\n\r\s]+[A-Za-z0-9_-]*$/.exec(chunk); + if (match) { + if (match[1] === "AND") { + type = CompletionType.Condition; + } else { + type = fromRuleType(match[1], type); + } + } + } + + switch (type) { + case CompletionType.Condition: + return this.getConditionCompletions(resource); + case CompletionType.Events: + return this.getEventCompletions(resource); + case CompletionType.Parameter: + return this.getParameterCompletions(resource, nodes); + case CompletionType.Procedures: + return this.getProceduresCompletions(resource); + case CompletionType.Queries: + return this.getQueriesCompletions(resource); + case CompletionType.Type: + return this.getTypeCompletions(resource); + default: + return this.getGlobalCompletions(resource); + } + } + + async handleResolveCompletion(item: CompletionItem): Promise { + const { data } = item; + if (typeof data === "string" && data.startsWith(SYMBOL_DATA)) { + const uid = data.substr(SYMBOL_DATA.length); + const project = this.server.projects.findProjectByUid(uid); + if (!project) return item; + + const { symbols } = project.story; + const chunks: Array = []; + const matchingSymbols = symbols.findSymbols(item.label); + if (matchingSymbols.length === 0) return item; + + const symbol = matchingSymbols[0]; + item.detail = ucfirst(printSymbolType(symbol.type)); + chunks.push("```divinity-story-goal", printSymbol(symbol, true), "```"); + + const documentation = await symbols.getDocumentation(symbol); + if (documentation && documentation.description) { + chunks.push(documentation.description); + } + + item.documentation = { + kind: "markdown", + value: chunks.join("\n") + }; + } + + return item; + } +} diff --git a/src/server/features/definition/index.ts b/src/server/features/definition/index.ts new file mode 100644 index 0000000..ce3570d --- /dev/null +++ b/src/server/features/definition/index.ts @@ -0,0 +1,75 @@ +import { + Location, + ServerCapabilities, + TextDocumentPositionParams +} from "vscode-languageserver"; + +import Feature from "../Feature"; +import runSafeAsync from "../../utils/runSafeAsync"; +import Server from "../../Server"; +import Symbol from "../../projects/story/Symbol"; +import unpackRange from "../../parsers/story/utils/unpackRange"; +import { apiShowEvent } from "../../../shared/notifications"; + +export default class DefinitionFeature extends Feature { + constructor(server: Server) { + super(server); + + server.connection.onDefinition((params, token) => + runSafeAsync( + () => this.handleDefinition(params), + null, + `Error while computing definition for ${params.textDocument.uri}`, + token + ) + ); + } + + getCapabilities(): ServerCapabilities { + return { + definitionProvider: true + }; + } + + async handleDefinition( + params: TextDocumentPositionParams + ): Promise { + const { resource, symbol } = await this.getSymbolAt(params); + if (!symbol) { + return null; + } + + let systemSymbol: Symbol | undefined; + if (symbol.isSystem) { + systemSymbol = symbol; + } else if (resource) { + const symbols = resource.story.symbols.findSymbols(symbol.name); + systemSymbol = symbols.find(symbol => symbol.isSystem); + } + + if (systemSymbol) { + this.server.connection.sendNotification( + apiShowEvent, + `/definition/${symbol.name}` + ); + + return { + uri: params.textDocument.uri, + range: { + end: params.position, + start: params.position + } + }; + } + + if (symbol.resolvedDefinition) { + const definition = symbol.resolvedDefinition; + return { + uri: definition.goal.resource.getUri(), + range: unpackRange(definition) + }; + } + + return null; + } +} diff --git a/src/server/features/diagnostics/index.ts b/src/server/features/diagnostics/index.ts new file mode 100644 index 0000000..98bf1a1 --- /dev/null +++ b/src/server/features/diagnostics/index.ts @@ -0,0 +1,89 @@ +import { Connection } from "vscode-languageserver/lib/main"; +import { TextDocumentChangeEvent } from "vscode-languageserver/lib/main"; + +import Feature from "../Feature"; +import Resource from "../../projects/story/resources/Resource"; +import Server from "../../Server"; +import parseUri from "../../utils/parseUri"; + +export default class DiagnosticsFeature extends Feature { + constructor(server: Server) { + super(server); + + const { documents, projects } = server; + documents.onDidClose(this.handleDocumentDidClose); + documents.onDidChangeContent(this.handleDocumentChangeContent); + documents.onDidOpen(this.handleDocumentOpen); + projects.on("diagnostics", this.handleDiagnostics); + } + + private async findFile( + event: TextDocumentChangeEvent + ): Promise { + const { projects } = this.server; + return projects.findResource(event.document.uri); + } + + private handleDocumentDidClose = async (event: TextDocumentChangeEvent) => { + // this.documentSettings.delete(event.document.uri); + const goal = await this.findFile(event); + if (goal) { + goal.setDocument(null); + } + }; + + private handleDocumentChangeContent = async ( + event: TextDocumentChangeEvent + ) => { + const file = await this.findFile(event); + if (file) { + file.invalidate(); + } + }; + + private handleDocumentOpen = async (event: TextDocumentChangeEvent) => { + const file = await this.findFile(event); + if (file) { + file.setDocument(event.document); + this.handleDiagnostics(file); + } else { + this.server.connection.window.showErrorMessage( + "This document seems not be part of a Divinity modification." + ); + } + }; + + private handleDiagnostics = (file: Resource) => { + const { connection } = this.server; + + connection.sendDiagnostics({ + uri: file.getUri(), + diagnostics: file.getDiagnostics().map(d => ({ + severity: d.severity, + range: { + start: d.range.start, + end: d.range.end + }, + message: d.message + })) + }); + }; + + initialize(connection: Connection): void { + connection.workspace.getWorkspaceFolders().then(folders => { + if (!folders) { + return; + } + + const { projects } = this.server; + for (const folder of folders) { + const parsedUri = parseUri(folder.uri); + if (!parsedUri || parsedUri.type !== "path") { + continue; + } + + projects.tryCreateForFolder(parsedUri.path); + } + }); + } +} diff --git a/src/server/features/divProvider/index.ts b/src/server/features/divProvider/index.ts new file mode 100644 index 0000000..c028f9c --- /dev/null +++ b/src/server/features/divProvider/index.ts @@ -0,0 +1,34 @@ +import { Connection } from "vscode-languageserver/lib/main"; + +import Feature from "../Feature"; +import { + divRequestEvent, + divRequestResultEvent, + DivRequestResult +} from "../../../shared/notifications"; + +export default class DivProviderFeature extends Feature { + initialize(connection: Connection): void { + connection.onNotification(divRequestEvent, this.handleDivRequest); + } + + handleDivRequest = async (uri: string) => { + const { connection, projects } = this.server; + if (!connection) { + return; + } + + let content: string | null = null; + const resource = await projects.findResource(uri); + if (resource) { + content = await resource.getSource(); + } + + const result: DivRequestResult = { + content, + uri + }; + + connection.sendNotification(divRequestResultEvent, result); + }; +} diff --git a/src/server/features/documentSymbols/index.ts b/src/server/features/documentSymbols/index.ts new file mode 100644 index 0000000..84c12e7 --- /dev/null +++ b/src/server/features/documentSymbols/index.ts @@ -0,0 +1,101 @@ +import { + ServerCapabilities, + SymbolKind, + SymbolInformation, + TextDocument +} from "vscode-languageserver/lib/main"; + +import Feature from "../Feature"; +import GoalResource from "../../projects/story/resources/GoalResource"; +import HeaderGoalResource from "../../projects/story/resources/HeaderGoalResource"; +import printNode from "../../parsers/story/utils/printNode"; +import runSafeAsync from "../../utils/runSafeAsync"; +import Server from "../../Server"; +import toLocation from "../../utils/toLocation"; +import { AbstractGoalNode } from "../../parsers/story/models/nodes"; + +export default class DocumentSymbolsFeature extends Feature { + constructor(server: Server) { + super(server); + + server.connection.onDocumentSymbol((params, token) => + runSafeAsync( + () => this.getSymbols(params.textDocument.uri), + [], + `Error while computing document symbols for ${params.textDocument.uri}`, + token + ) + ); + } + + createGoalSymbolInfos(document: TextDocument, story: AbstractGoalNode) { + const result: Array = []; + if (story.init) { + result.push({ + containerName: "", + name: "Init section", + kind: 3, // SymbolKind.Namespace, + location: toLocation(document, story.init) + }); + } + + if (story.kb) { + result.push({ + containerName: "", + name: "KB section", + kind: 3, // SymbolKind.Namespace, + location: toLocation(document, story.kb) + }); + + for (const rule of story.kb.rules) { + let kind: SymbolKind = 12; // SymbolKind.Function; + if (rule.ruleType == "IF") { + kind = 24; // SymbolKind.Event; + } else if (rule.ruleType === "QRY") { + kind = 11; // SymbolKind.Interface; + } + + result.push({ + containerName: "KB section", + name: printNode(rule), + kind, + location: toLocation(document, rule) + }); + } + + if (story.exit) { + result.push({ + containerName: "", + name: "Exit section", + kind: 3, // SymbolKind.Namespace, + location: toLocation(document, story.exit) + }); + } + } + + return result; + } + + getCapabilities(): Partial { + return { + documentSymbolProvider: true + }; + } + + async getSymbols(uri: string) { + const { projects } = this.server; + const goal = await projects.findResource(uri); + if ( + !(goal instanceof GoalResource) && + !(goal instanceof HeaderGoalResource) + ) { + return null; + } + + await goal.story.whenReady(); + + const document = goal.getDocument(); + const node = await goal.getRootNode(); + return document && node ? this.createGoalSymbolInfos(document, node) : null; + } +} diff --git a/src/server/features/hover/ConstantProvider.ts b/src/server/features/hover/ConstantProvider.ts new file mode 100644 index 0000000..73313a2 --- /dev/null +++ b/src/server/features/hover/ConstantProvider.ts @@ -0,0 +1,43 @@ +import { Hover } from "vscode-languageserver"; + +import unpackRange from "../../parsers/story/utils/unpackRange"; +import { NodeType } from "../../parsers/story/models/nodes"; +import { SyncProvider, ProviderContext } from "./Provider"; + +export default class ConstantProvider extends SyncProvider { + invoke({ node }: ProviderContext): Hover | null { + let contents: Array | undefined; + + if (node.type === NodeType.RealLiteral) { + contents = [ + "**Constant real**", + "```divinity-story-goal", + `(REAL)${node.value}`, + "```" + ]; + } else if (node.type === NodeType.IntegerLiteral) { + contents = [ + "**Constant integer**", + "```divinity-story-goal", + `(INTEGER)${node.value}`, + "```" + ]; + } else if (node.type === NodeType.StringLiteral) { + contents = [ + "**Constant string**", + "```divinity-story-goal", + `(STRING)"${node.value}"`, + "```" + ]; + } + + if (contents) { + return { + contents: contents.join("\n"), + range: unpackRange(node) + }; + } + + return null; + } +} diff --git a/src/server/features/hover/GuidProvider.ts b/src/server/features/hover/GuidProvider.ts new file mode 100644 index 0000000..585f9b0 --- /dev/null +++ b/src/server/features/hover/GuidProvider.ts @@ -0,0 +1,35 @@ +import { Hover } from "vscode-languageserver"; + +import ucfirst from "../../utils/ucfirst"; +import unpackRange from "../../parsers/story/utils/unpackRange"; +import { NodeType } from "../../parsers/story/models/nodes"; +import { SyncProvider, ProviderContext } from "./Provider"; + +export default class GuidProvider extends SyncProvider { + invoke({ node, resource }: ProviderContext): Hover | null { + if (node.type !== NodeType.GuidLiteral) return null; + + const { levels } = resource.story.project; + const instance = levels.instances.find( + instance => instance.guid === node.guid + ); + + let instanceInfo = ""; + if (instance) { + instanceInfo = `${ucfirst(instance.type)} "${instance.name}" from level ${ + instance.level + }`; + } + + return { + contents: [ + "**GUID reference** ", + instanceInfo, + "```divinity-story-goal", + `(GUIDSTRING)${node.guid}`, + "```" + ].join("\n"), + range: unpackRange(node) + }; + } +} diff --git a/src/server/features/hover/Provider.ts b/src/server/features/hover/Provider.ts new file mode 100644 index 0000000..8278096 --- /dev/null +++ b/src/server/features/hover/Provider.ts @@ -0,0 +1,32 @@ +import { Hover } from "vscode-languageserver"; + +import HoverFeature from "./index"; +import Resource from "../../projects/story/resources/Resource"; +import { AnyNode } from "../../parsers/story/models/nodes"; + +export type AnyProvider = AsyncProvider | SyncProvider; + +export interface ProviderContext { + index: number; + node: AnyNode; + nodes: Array; + resource: Resource; +} + +export abstract class Provider { + feature: HoverFeature; + + constructor(feature: HoverFeature) { + this.feature = feature; + } +} + +export abstract class AsyncProvider extends Provider { + abstract canHandle(context: ProviderContext): T | null; + + abstract async invoke(data: T): Promise; +} + +export abstract class SyncProvider extends Provider { + abstract invoke(context: ProviderContext): Hover | null; +} diff --git a/src/server/features/hover/SignatureProvider.ts b/src/server/features/hover/SignatureProvider.ts new file mode 100644 index 0000000..eb4c3c5 --- /dev/null +++ b/src/server/features/hover/SignatureProvider.ts @@ -0,0 +1,83 @@ +import { Hover } from "vscode-languageserver"; + +import printSymbol from "../../projects/story/utils/printSymbol"; +import Resource from "../../projects/story/resources/Resource"; +import Symbol from "../../projects/story/Symbol"; +import unpackRange from "../../parsers/story/utils/unpackRange"; +import { AsyncProvider, ProviderContext } from "./Provider"; +import { NodeType, AnyNode } from "../../parsers/story/models/nodes"; +import { SymbolType } from "../../projects/story/models/symbol"; +import isCallerNode, { + CallerNode +} from "../../parsers/story/utils/isCallerNode"; + +export interface Params { + callerNode: CallerNode; + node: AnyNode; + resource: Resource; + symbol: Symbol; +} + +export default class SignatureProvider extends AsyncProvider { + canHandle({ index, node, nodes, resource }: ProviderContext): Params | null { + const callerNode = nodes[index + 2]; + if (!isCallerNode(callerNode) || node.type !== NodeType.Identifier) { + return null; + } + + const { symbol } = callerNode; + if (!symbol) return null; + + return { callerNode, node, resource, symbol }; + } + + getUsageDescription(node: CallerNode, symbolType: SymbolType): string { + switch (node.type) { + case NodeType.SignatureAction: + return symbolType === SymbolType.Database + ? "Database write" + : "Procedure call"; + case NodeType.SignatureCondition: + return symbolType === SymbolType.Database + ? "Database query" + : "Query condition"; + case NodeType.Rule: + switch (node.ruleType) { + case "IF": + return symbolType === SymbolType.Database + ? "Database event handler" + : "Event handler"; + case "PROC": + return "Procedure definition"; + case "QRY": + return "Query definition"; + } + } + + return "Unknown invocation"; + } + + async invoke({ + callerNode, + node, + resource, + symbol + }: Params): Promise { + const documentation = await resource.story.symbols.getDocumentation(symbol); + let description = ""; + if (documentation && documentation.description) { + description = documentation.description; + } + + return { + contents: [ + `**${this.getUsageDescription(callerNode, symbol.type)}** `, + description, + "```divinity-story-goal", + `${printSymbol(symbol, true)}`, + "```" + ].join("\n"), + range: unpackRange(node) + }; + } +} diff --git a/src/server/features/hover/VariableProvider.ts b/src/server/features/hover/VariableProvider.ts new file mode 100644 index 0000000..e33522b --- /dev/null +++ b/src/server/features/hover/VariableProvider.ts @@ -0,0 +1,49 @@ +import { Hover } from "vscode-languageserver"; + +import printParameterType from "../../projects/story/utils/printParameterType"; +import unpackRange from "../../parsers/story/utils/unpackRange"; +import { IdentifierType, NodeType } from "../../parsers/story/models/nodes"; +import { SyncProvider, ProviderContext } from "./Provider"; + +export default class VariableProvider extends SyncProvider { + invoke({ node, nodes }: ProviderContext): Hover | null { + if ( + node.type !== NodeType.Identifier || + node.identifierType !== IdentifierType.Variable + ) { + return null; + } + + const variablesAt = this.feature.getVariablesAt(nodes); + if (!variablesAt) return null; + + const { rule, variables } = variablesAt; + const variable = variables.find( + variable => variable.name === node.name.toLowerCase() + ); + + if (!variable) { + return null; + } + + let origin: string; + if (variable.fromSymbol === rule.symbol && rule.ruleType !== "IF") { + origin = `From parameter #${variable.fromIndex + 1} of definition`; + } else { + origin = `From parameter #${variable.fromIndex + 1} of \`${ + variable.fromSymbol.name + }\``; + } + + return { + contents: [ + "**Local variable** ", + origin, + "```divinity-story-goal", + `(${printParameterType(variable.type)})${node.name}`, + "```" + ].join("\n"), + range: unpackRange(node) + }; + } +} diff --git a/src/server/features/hover/index.ts b/src/server/features/hover/index.ts new file mode 100644 index 0000000..43dc9e3 --- /dev/null +++ b/src/server/features/hover/index.ts @@ -0,0 +1,75 @@ +import { + Hover, + ServerCapabilities, + TextDocumentPositionParams +} from "vscode-languageserver/lib/main"; + +import ConstantProvider from "./ConstantProvider"; +import GuidProvider from "./GuidProvider"; +import runSafeAsync from "../../utils/runSafeAsync"; +import Server from "../../Server"; +import SignatureProvider from "./SignatureProvider"; +import VariableProvider from "./VariableProvider"; +import { AnyProvider, ProviderContext, SyncProvider } from "./Provider"; +import { Feature } from ".."; + +export default class HoverFeature extends Feature { + providers: Array; + + constructor(server: Server) { + super(server); + + const { connection } = server; + connection.onHover((params, token) => + runSafeAsync( + () => this.handleHover(params), + null, + `Error while computing document hover for ${params.textDocument.uri}`, + token + ) + ); + + this.providers = [ + new ConstantProvider(this), + new GuidProvider(this), + new SignatureProvider(this), + new VariableProvider(this) + ]; + } + + getCapabilities(): Partial { + return { + hoverProvider: true + }; + } + + async handleHover(params: TextDocumentPositionParams): Promise { + const { nodes, resource } = await this.getNodesAt(params); + if (!nodes || !resource) return null; + + const { providers } = this; + let result: Hover | null = null; + let localContext: {} | null; + + for (let index = 0; index < nodes.length; index++) { + const context: ProviderContext = { + index, + node: nodes[index], + nodes, + resource + }; + + for (const provider of providers) { + if (provider instanceof SyncProvider) { + result = provider.invoke(context); + } else if ((localContext = provider.canHandle(context))) { + result = await provider.invoke(localContext); + } + + if (result) return result; + } + } + + return null; + } +} diff --git a/src/server/features/index.ts b/src/server/features/index.ts new file mode 100644 index 0000000..e90d6bd --- /dev/null +++ b/src/server/features/index.ts @@ -0,0 +1,32 @@ +import Feature, { FeatureFactory } from "./Feature"; + +import ActivityIndicatorFeature from "./activityIndicator"; +import ApiExplorerFeature from "./apiExplorer"; +import CompletionFeature from "./completion"; +import DefinitionFeature from "./definition"; +import DiagnosticsFeature from "./diagnostics"; +import DivProviderFeature from "./divProvider"; +import DocumentSymbolsFeature from "./documentSymbols"; +import HoverFeature from "./hover"; +import ReferencesFeature from "./references"; +import RenameFeature from "./rename"; +import SignatureHelpFeature from "./signatureHelp"; +import StoryOutlineFeature from "./storyOutline"; + +const factories: Array = [ + ActivityIndicatorFeature, + ApiExplorerFeature, + CompletionFeature, + DefinitionFeature, + DiagnosticsFeature, + DivProviderFeature, + DocumentSymbolsFeature, + HoverFeature, + ReferencesFeature, + RenameFeature, + SignatureHelpFeature, + StoryOutlineFeature +]; + +export { Feature }; +export default factories; diff --git a/src/server/features/references/index.ts b/src/server/features/references/index.ts new file mode 100644 index 0000000..ac4dca3 --- /dev/null +++ b/src/server/features/references/index.ts @@ -0,0 +1,60 @@ +import { + Location, + ReferenceParams, + ServerCapabilities +} from "vscode-languageserver"; + +import eachCaller from "../../parsers/story/utils/eachCaller"; +import Feature from "../Feature"; +import runSafeAsync from "../../utils/runSafeAsync"; +import Server from "../../Server"; +import Symbol from "../../projects/story/Symbol"; +import unpackRange from "../../parsers/story/utils/unpackRange"; + +export default class ReferencesFeature extends Feature { + constructor(server: Server) { + super(server); + + server.connection.onReferences((params, token) => + runSafeAsync( + () => this.handleReferences(params), + null, + `Error while computing document hover for ${params.textDocument.uri}`, + token + ) + ); + } + + getCapabilities(): Partial { + return { + referencesProvider: true + }; + } + + async getSymbolReferences(symbol: Symbol): Promise> { + const result: Array = []; + + for (const goal of symbol.usages) { + const rootNode = await goal.resource.getRootNode(true); + const uri = goal.resource.getUri(); + + for (const { node } of eachCaller(rootNode)) { + if (node.symbol === symbol) { + result.push({ + uri, + range: unpackRange(node) + }); + } + } + } + + return result; + } + + async handleReferences( + params: ReferenceParams + ): Promise | null> { + const { symbol } = await this.getSymbolAt(params); + return symbol ? this.getSymbolReferences(symbol) : null; + } +} diff --git a/src/server/features/rename/index.ts b/src/server/features/rename/index.ts new file mode 100644 index 0000000..c6ca228 --- /dev/null +++ b/src/server/features/rename/index.ts @@ -0,0 +1,222 @@ +import { + ServerCapabilities, + RenameParams, + WorkspaceEdit, + ResponseError, + TextDocumentEdit +} from "vscode-languageserver"; + +import GoalResource from "../../projects/story/resources/GoalResource"; +import eachNodeRecursive from "../../parsers/story/utils/eachNodeRecursive"; +import Feature from "../Feature"; +import Resource from "../../projects/story/resources/Resource"; +import runSafeAsync from "../../utils/runSafeAsync"; +import Server from "../../Server"; +import unpackRange from "../../parsers/story/utils/unpackRange"; + +import { + NodeType, + GuidLiteralNode, + IdentifierType, + IdentifierNode, + AnyNode +} from "../../parsers/story/models/nodes"; + +import isCallerNode, { + CallerNode +} from "../../parsers/story/utils/isCallerNode"; + +const GUID_VALIDATION = /^[A-Za-z0-9_-]*?[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$/; +const SIGNATURE_VALIDATION = /^[A-Za-z_][A-Za-z0-9_-]*$/; +const VARIABLE_VALIDATION = /^_[A-Za-z0-9_-]*$/; + +export interface Context { + newName: string; + nodes: Array; + resource: Resource; +} + +export default class RenameFeature extends Feature { + constructor(server: Server) { + super(server); + + server.connection.onRenameRequest((params, token) => + runSafeAsync( + () => this.handleRename(params), + null, + `Error while computing rename for ${params.textDocument.uri}`, + token + ) + ); + } + + getCapabilities(): Partial { + return { + renameProvider: true + }; + } + + async renameGuid( + identifier: GuidLiteralNode, + { newName, resource }: Context + ): Promise> { + const documentChanges: Array = []; + const { guid } = identifier; + + if (!GUID_VALIDATION.test(newName)) { + return new ResponseError(-1, "The entered guid is invalid."); + } + + for (const goal of resource.story.getGoals()) { + if (!(goal.resource instanceof GoalResource)) { + continue; + } + + const rootNode = await goal.resource.getRootNode(true); + let change: TextDocumentEdit | undefined; + + for (const { node } of eachNodeRecursive(rootNode)) { + if (node.type !== NodeType.GuidLiteral || node.guid !== guid) { + continue; + } + + if (!change) { + change = goal.resource.getTextEdit(); + documentChanges.push(change); + } + + change.edits.push({ + newText: newName, + range: unpackRange(node) + }); + } + } + + return { documentChanges }; + } + + async renameSignature( + origin: CallerNode, + { newName }: Context + ): Promise> { + const { symbol } = origin; + + if (!symbol) { + return new ResponseError(-1, "Cannot rename unresolved signatures."); + } + + if (symbol.isSystem) { + return new ResponseError(-1, "Cannot rename system signatures."); + } + + if (!SIGNATURE_VALIDATION.test(newName)) { + return new ResponseError(-1, "The entered name is invalid."); + } + + const documentChanges: Array = []; + + for (let index = 0; index < symbol.usages.length; index++) { + const resource: GoalResource = symbol.usages[index] + .resource as GoalResource; + if (!(resource instanceof GoalResource)) { + return new ResponseError( + -1, + "Cannot rename signatures from the shared mod." + ); + } + + const rootNode = await resource.getRootNode(true); + let change: TextDocumentEdit | undefined; + + for (const { node } of eachNodeRecursive(rootNode)) { + if (!isCallerNode(node) || node.symbol !== symbol) { + continue; + } + + if (!change) { + change = resource.getTextEdit(); + documentChanges.push(change); + } + + change.edits.push({ + newText: newName, + range: unpackRange(node.signature.identifier) + }); + } + } + + return { documentChanges }; + } + + async renameVariable( + origin: IdentifierNode, + { nodes, newName, resource }: Context + ): Promise> { + const rule = nodes.find(node => node.type === NodeType.Rule); + if (!rule) { + return new ResponseError( + -1, + "Only variables inside rules can be renamed." + ); + } + + if (!VARIABLE_VALIDATION.test(newName)) { + return new ResponseError(-1, "The entered variable name is invalid."); + } + + const changes = resource.getTextEdit(); + const name = origin.name.toLowerCase(); + + for (const { node } of eachNodeRecursive(rule)) { + if ( + node.type === NodeType.Identifier && + node.identifierType === IdentifierType.Variable && + node.name.toLowerCase() === name + ) { + changes.edits.push({ newText: newName, range: unpackRange(node) }); + } + } + + return { documentChanges: [changes] }; + } + + async handleRename( + params: RenameParams + ): Promise> { + const { nodes, resource } = await this.getNodesAt(params); + if (!nodes || !resource) { + return new ResponseError( + -1, + "Could not resolve an symbols at the given location." + ); + } + + const context = { + newName: params.newName, + nodes, + resource + }; + + for (let index = 0; index < nodes.length; index++) { + const origin = nodes[index]; + const caller = nodes[index + 2]; + + if (origin.type === NodeType.GuidLiteral) { + return await this.renameGuid(origin, context); + } else if ( + origin.type === NodeType.Identifier && + origin.identifierType === IdentifierType.Variable + ) { + return await this.renameVariable(origin, context); + } else if ( + caller && + isCallerNode(caller) && + origin === caller.signature.identifier + ) { + return await this.renameSignature(caller, context); + } + } + + return new ResponseError(-1, "This symbol cannot be renamed."); + } +} diff --git a/src/server/features/signatureHelp/index.ts b/src/server/features/signatureHelp/index.ts new file mode 100644 index 0000000..e28bba4 --- /dev/null +++ b/src/server/features/signatureHelp/index.ts @@ -0,0 +1,176 @@ +import { + ParameterInformation, + ServerCapabilities, + SignatureHelp, + SignatureInformation, + TextDocumentPositionParams +} from "vscode-languageserver"; + +import Feature from "../Feature"; +import printSymbol from "../../projects/story/utils/printSymbol"; +import Resource from "../../projects/story/resources/Resource"; +import runSafeAsync from "../../utils/runSafeAsync"; +import Server from "../../Server"; +import Symbol from "../../projects/story/Symbol"; +import ucfirst from "../../utils/ucfirst"; +import { DefinitionDoc } from "../../documentation/raw/Definition"; +import { SymbolType } from "../../projects/story/models/symbol"; + +import isCallerNode, { + CallerNode +} from "../../parsers/story/utils/isCallerNode"; + +function getParameters( + symbol: Symbol, + definition: DefinitionDoc | null +): Array { + return symbol.parameters.map(symbolParam => { + let documentation: string | undefined; + if (definition && definition.parameters) { + const paramDefinition = definition.parameters.find( + paramDefinition => paramDefinition.name === symbolParam.name + ); + + if (paramDefinition && paramDefinition.description) { + documentation = ucfirst(paramDefinition.description); + } + } + + return { + documentation, + label: symbolParam.name + }; + }); +} + +async function getSignatures( + node: CallerNode, + resource: Resource +): Promise> { + const { docProvider } = resource.story.project.projects; + const { name } = node.signature.identifier; + const doc = await docProvider.getDocumentation(name); + const signatures: Array = []; + const symbols = resource.story.symbols.findSymbols(name); + + for (const symbol of symbols) { + if (symbol.type === SymbolType.Unknown) { + continue; + } + + const localDoc = symbol.documentation ? symbol.documentation : doc; + let symbolDescription: string | undefined; + if (localDoc && localDoc.description) { + symbolDescription = ucfirst(localDoc.description); + } + + signatures.push({ + documentation: symbolDescription, + label: printSymbol(symbol), + parameters: getParameters(symbol, localDoc) + }); + } + + return signatures; +} + +function sortSignatures( + a: SignatureInformation, + b: SignatureInformation +): number { + return ( + (a.parameters ? a.parameters.length : 0) - + (b.parameters ? b.parameters.length : 0) + ); +} + +export default class SignatureHelpFeature extends Feature { + constructor(server: Server) { + super(server); + + const { connection } = server; + connection.onSignatureHelp((params, token) => + runSafeAsync( + () => this.handleSignatureHelp(params), + null, + `Error while creating signature help for "${params.textDocument.uri}".`, + token + ) + ); + } + + getCapabilities(): Partial { + return { + signatureHelpProvider: { + triggerCharacters: ["("] + } + }; + } + + async handleSignatureHelp( + params: TextDocumentPositionParams + ): Promise { + const { nodes, resource } = await this.getNodesAt(params); + if (!nodes || !resource) return null; + + const document = resource.getDocument(); + if (!document) return null; + + const offset = document.offsetAt(params.position); + + for (const node of nodes) { + if (!isCallerNode(node)) { + continue; + } + + const { signature } = node; + const { identifier, parameters } = signature; + if (offset < signature.startOffset || offset > signature.endOffset) { + return null; + } + + const signatures = await getSignatures(node, resource); + let activeSignature: number | null = null; + let activeParameter: number | null = null; + let numParams = parameters.length; + + for (let index = 0; index < parameters.length; index++) { + if (offset <= parameters[index].endOffset) { + activeParameter = index; + break; + } + } + + if (activeParameter == null) { + activeParameter = parameters.length; + numParams += 1; + } + + if (offset <= identifier.endOffset || offset >= signature.endOffset) { + activeParameter = -1; + } + + signatures.sort(sortSignatures); + for (let index = 0; index < signatures.length; index++) { + const signatureParams = signatures[index].parameters; + const numSignatureParams = signatureParams ? signatureParams.length : 0; + if (numParams <= numSignatureParams) { + activeSignature = index; + break; + } + } + + if (activeSignature === null) { + activeSignature = signatures.length - 1; + } + + return { + activeSignature, + activeParameter, + signatures + }; + } + + return null; + } +} diff --git a/src/server/features/storyOutline/index.ts b/src/server/features/storyOutline/index.ts new file mode 100644 index 0000000..e93b697 --- /dev/null +++ b/src/server/features/storyOutline/index.ts @@ -0,0 +1,189 @@ +import { TextDocumentEdit } from "vscode-languageserver"; + +import debounce from "../../utils/debounce"; +import Feature from "../Feature"; +import Goal from "../../projects/story/Goal"; +import HeaderGoalResource from "../../projects/story/resources/HeaderGoalResource"; +import Project from "../../projects/Project"; +import runSafeAsync from "../../utils/runSafeAsync"; +import Server from "../../Server"; +import unpackRange from "../../parsers/story/utils/unpackRange"; +import { NodeType } from "../../parsers/story/models/nodes"; + +import { + renameGoalRequest, + RenameGoalParams, + RenameGoalResult, + moveGoalRequest, + MoveGoalParams, + MoveGoalResult +} from "../../../shared/requests"; + +import { + goalsChangedEvent, + GoalsChanged, + GoalInfo +} from "../../../shared/notifications"; + +export default class StoryOutlineFeature extends Feature { + treeVersion: number = 0; + + constructor(server: Server) { + super(server); + + const { connection } = server; + connection.onRequest(moveGoalRequest, (params: MoveGoalParams, token) => + runSafeAsync( + () => this.handleMoveGoal(params), + null, + `Error while moving goal "${params.goalName}".`, + token + ) + ); + + connection.onRequest(renameGoalRequest, (params: RenameGoalParams, token) => + runSafeAsync( + () => this.handleRenameGoal(params), + null, + `Error while renaming goal "${params.goalName}".`, + token + ) + ); + + server.projects.on("goalsChanged", this.handleGoalsChanged); + } + + handleGoalsChanged = debounce((project: Project) => { + const goals = this.createTree(project.story.getSortedRootGoals()); + const payload: GoalsChanged = { + project: project.getInfo(), + goals, + treeVersion: this.treeVersion++ + }; + + this.server.connection.sendNotification(goalsChangedEvent, payload); + }, 50); + + async handleMoveGoal({ + goalName, + newParent, + projectUid + }: MoveGoalParams): Promise { + const project = this.server.projects.findProjectByUid(projectUid); + if (!project) { + return { error: `Could not find project with uid "${projectUid}".` }; + } + + const goal = project.story.findGoal(goalName); + if (!goal) { + return { error: `Could not find goal "${goalName}".` }; + } + + const rootNode = await goal.resource.getRootNode(); + if ( + !rootNode || + rootNode.type !== NodeType.StoryGoal || + !rootNode.parentTargetEdges + ) { + return { error: `Could not open goal "${goal.name}" for editing.` }; + } + + const documentChanges: Array = []; + const document = goal.resource.getDocument(); + documentChanges.push({ + textDocument: { + uri: goal.resource.getUri(), + version: document ? document.version : null + }, + edits: [ + { + newText: `"${newParent}"`, + range: unpackRange(rootNode.parentTargetEdges[0]) + } + ] + }); + + return { documentChanges }; + } + + async handleRenameGoal({ + goalName, + newName, + projectUid + }: RenameGoalParams): Promise { + const project = this.server.projects.findProjectByUid(projectUid); + if (!project) { + return { error: `Could not find project with uid "${projectUid}".` }; + } + + const goal = project.story.findGoal(goalName); + if (!goal) { + return { error: `Could not find goal "${goalName}".` }; + } + + const collision = project.story.findGoal(newName); + if (collision) { + return { error: `A goal with the name "${newName}" already exists.` }; + } + + const documentChanges: Array = []; + const children = goal.getChildren(); + + for (const child of children) { + if (child.resource instanceof HeaderGoalResource) { + return { + error: `A goal which contains subgoals from the shared mod cannot be renamed.` + }; + } + + const rootNode = await child.resource.getRootNode(); + if ( + !rootNode || + rootNode.type !== NodeType.StoryGoal || + !rootNode.parentTargetEdges + ) { + return { error: `Could not open subgoal "${child.name}" for editing.` }; + } + + const edge = rootNode.parentTargetEdges.find( + edge => edge.value === goalName + ); + + if (!edge) { + return { + error: `Could not locate parentTargetEdges pointing to "${goalName}" in "${ + child.name + }".` + }; + } + + const document = child.resource.getDocument(); + documentChanges.push({ + textDocument: { + uri: child.resource.getUri(), + version: document ? document.version : null + }, + edits: [ + { + newText: `"${newName}"`, + range: unpackRange(edge) + } + ] + }); + } + + return { documentChanges }; + } + + private createTree( + goals: Array, + stack: Array = [] + ): Array { + return goals.filter(goal => stack.indexOf(goal) === -1).map(goal => ({ + children: this.createTree(goal.getSortedChildren(), [...stack, goal]), + isShared: !goal.resource || goal.resource instanceof HeaderGoalResource, + name: goal.name, + uri: goal.resource.getUri() + })); + } +} diff --git a/src/server/index.ts b/src/server/index.ts new file mode 100644 index 0000000..8614599 --- /dev/null +++ b/src/server/index.ts @@ -0,0 +1,3 @@ +import Server from "./Server"; + +new Server(); diff --git a/src/server/parsers/lsf/BufferReader.ts b/src/server/parsers/lsf/BufferReader.ts new file mode 100644 index 0000000..b537822 --- /dev/null +++ b/src/server/parsers/lsf/BufferReader.ts @@ -0,0 +1,101 @@ +import { inflateSync } from "zlib"; + +import { CompressionMethod } from "./utils/compressionMethod"; + +export default class BufferReader { + buffer: Buffer; + length: number; + offset: number = 0; + + constructor(buffer: Buffer) { + this.buffer = buffer; + this.length = buffer.length; + } + + readBytes( + length: number, + compression: CompressionMethod = CompressionMethod.None, + compressedLength: number = 0 + ): Buffer { + const { offset } = this; + let result: Buffer; + + switch (compression) { + case CompressionMethod.Zlib: + result = inflateSync( + this.buffer.slice(offset, offset + compressedLength) + ); + this.offset += compressedLength; + break; + case CompressionMethod.None: + result = this.buffer.slice(offset, offset + length); + this.offset += length; + break; + default: + throw new Error("Unsupported compression"); + } + + return result; + } + + readByte() { + const result = this.buffer[this.offset]; + this.offset += 1; + return result; + } + + readString(length: number) { + const { offset } = this; + const result = this.buffer.toString("utf-8", offset, offset + length); + this.offset += length; + return result; + } + + readFloat() { + const result = this.buffer.readFloatLE(this.offset); + this.offset += 4; + return result; + } + + readDouble() { + const result = this.buffer.readDoubleLE(this.offset); + this.offset += 8; + return result; + } + + readInt8() { + const result = this.buffer.readInt8(this.offset); + this.offset += 1; + return result; + } + + readUInt8() { + const result = this.buffer.readUInt8(this.offset); + this.offset += 1; + return result; + } + + readInt16() { + const result = this.buffer.readInt16LE(this.offset); + this.offset += 2; + return result; + } + + readUInt16() { + const result = this.buffer.readUInt16LE(this.offset); + this.offset += 2; + return result; + } + + readInt32() { + const result = this.buffer.readInt32LE(this.offset); + this.offset += 4; + return result; + } + + readUInt32() { + const result = this.buffer.readUInt32LE(this.offset); + this.offset += 4; + return result; + } +} diff --git a/src/server/parsers/lsf/LICENSE b/src/server/parsers/lsf/LICENSE new file mode 100644 index 0000000..59715e6 --- /dev/null +++ b/src/server/parsers/lsf/LICENSE @@ -0,0 +1,25 @@ +The LSF parser is a port of the LSF parser found in lslib +https://github.com/Norbyte/lslib + + +The MIT License (MIT) + +Copyright (c) 2015 Norbyte + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/server/parsers/lsf/Parser.ts b/src/server/parsers/lsf/Parser.ts new file mode 100644 index 0000000..fbe529a --- /dev/null +++ b/src/server/parsers/lsf/Parser.ts @@ -0,0 +1,443 @@ +import BufferReader from "./BufferReader"; + +import Node from "./models/Node"; +import Region from "./models/Region"; +import Resource from "./models/Resource"; +import NodeAttribute, { + DataType, + TranslatedFSString, + TranslatedFSStringArgument, + TranslatedString +} from "./models/NodeAttribute"; + +import LSFAttributeEntryV2 from "./structs/LSFAttributeEntryV2"; +import LSFAttributeEntryV3 from "./structs/LSFAttributeEntryV3"; +import LSFHeader from "./structs/LSFHeader"; +import LSFNodeEntryV2 from "./structs/LSFNodeEntryV2"; +import LSFNodeEntryV3 from "./structs/LSFNodeEntryV3"; + +import { CompressionFlagsToMethod } from "./utils/compressionMethod"; +import { readAttribute } from "./utils/readAttribute"; + +export type NodeEntry = LSFNodeEntryV2 | LSFNodeEntryV3; +export type AttributeEntry = LSFAttributeEntryV2 | LSFAttributeEntryV3; + +export default class Parser { + /** + * Turns on some debug console output + */ + private debug: boolean = false; + + /** + * Static string hash map + */ + private names: Array> = []; + + /** + * Preprocessed list of nodes (structures) + */ + private nodes: Array = []; + + /** + * Preprocessed list of node attributes + */ + private attributes: Array = []; + + read(buffer: Buffer): Resource { + const reader = new BufferReader(buffer); + const header = new LSFHeader(reader); + if (!header.validate()) { + throw new Error("Invalid LSF signature"); + } + + if ( + header.version < LSFHeader.versionInitial || + header.version > LSFHeader.currentVersion + ) { + throw new Error(`LSF version ${header.version} is not supported`); + } + + const compression = CompressionFlagsToMethod(header.compressionFlags); + + if (header.stringsSizeOnDisk > 0 || header.stringsUncompressedSize > 0) { + const namesStream = reader.readBytes( + header.stringsUncompressedSize, + compression, + header.stringsSizeOnDisk + ); + this.readNames(namesStream); + } + + if (header.nodesSizeOnDisk > 0 || header.nodesUncompressedSize > 0) { + const nodesStream = reader.readBytes( + header.nodesUncompressedSize, + compression, + header.nodesSizeOnDisk + ); + const longNodes = + header.version >= LSFHeader.versionExtendedNodes && + header.extended == 1; + this.readNodes(nodesStream, longNodes); + } + + if ( + header.attributesSizeOnDisk > 0 || + header.attributesUncompressedSize > 0 + ) { + const attributesStream = reader.readBytes( + header.attributesUncompressedSize, + compression, + header.attributesSizeOnDisk + ); + var longAttributes = + header.version >= LSFHeader.versionExtendedNodes && + header.extended == 1; + if (longAttributes) { + this.readAttributesV3(attributesStream); + } else { + this.readAttributesV2(attributesStream); + } + } + + let values: Buffer; + if (header.valuesSizeOnDisk > 0 || header.valuesUncompressedSize > 0) { + var valueStream = reader.readBytes( + header.valuesUncompressedSize, + compression, + header.valuesSizeOnDisk + ); + values = valueStream; + } else { + values = new Buffer(0); + } + + const resource = new Resource(); + resource.metadata.majorVersion = (header.engineVersion & 0xff000000) >> 24; + resource.metadata.minorVersion = (header.engineVersion & 0xff0000) >> 16; + resource.metadata.revision = (header.engineVersion & 0xff00) >> 8; + resource.metadata.buildNumber = header.engineVersion & 0xff; + + this.readRegions(resource, values); + + return resource; + } + + /** + * Return the name of the given entry from the name table + * @param entry The entry whose name should be returned + */ + private getName(entry: AttributeEntry | NodeEntry) { + return this.names[entry.getNameIndex()][entry.getNameOffset()]; + } + + /** + * Reads the static string hash table from the specified stream. + * @param buffer Stream to read the hash table from + */ + private readNames(buffer: Buffer) { + // Format: + // 32-bit hash entry count (N) + // N x 16-bit chain length (L) + // L x 16-bit string length (S) + // [S bytes of UTF-8 string data] + + const names: Array> = []; + const reader = new BufferReader(buffer); + let numHashEntries = reader.readUInt32(); + + if (this.debug) { + console.log(" ----- DUMP OF NAME TABLE -----"); + } + + while (numHashEntries-- > 0) { + const hash: Array = []; + names.push(hash); + + let numStrings = reader.readUInt16(); + while (numStrings-- > 0) { + const nameLen = reader.readUInt16(); + const name = reader.readString(nameLen); + hash.push(name); + + if (this.debug) { + console.log(`${names.length - 1}/${hash.length - 1}: ${name}`); + } + } + } + + this.names = names; + } + + /** + * Reads the structure headers for the LSOF resource + * @param buffer Stream to read the node headers from + * @param longNodes Use the long (V3) on-disk node format + */ + private readNodes(buffer: Buffer, longNodes: boolean) { + const nodes: Array = []; + const reader = new BufferReader(buffer); + let index = 0; + + if (this.debug) { + console.log(" ----- DUMP OF NODE TABLE -----"); + } + + while (reader.offset < reader.length) { + const pos = reader.offset; + const resolved = longNodes + ? new LSFNodeEntryV3(reader) + : new LSFNodeEntryV2(reader); + + if (this.debug) { + console.log( + `${index}: ${this.getName(resolved)} @ ${pos} (parent ${ + resolved.parentIndex + }, firstAttribute ${resolved.firstAttributeIndex})` + ); + } + + nodes.push(resolved); + index++; + } + + this.nodes = nodes; + } + + /** + * Reads the V2 attribute headers for the LSOF resource + * @param buffer Stream to read the attribute headers from + */ + private readAttributesV2(buffer: Buffer) { + const attributes: Array = []; + const prevAttributeRefs: Array = []; + const reader = new BufferReader(buffer); + let dataOffset = 0; + let index = 0; + + while (reader.offset < reader.length) { + const attribute = new LSFAttributeEntryV2(reader, dataOffset); + const nodeIndex = attribute.nodeIndex + 1; + + if (prevAttributeRefs.length > nodeIndex) { + if (prevAttributeRefs[nodeIndex] != -1) { + attributes[prevAttributeRefs[nodeIndex]].nextAttributeIndex = index; + } + + prevAttributeRefs[nodeIndex] = index; + } else { + while (prevAttributeRefs.length < nodeIndex) { + prevAttributeRefs.push(-1); + } + + prevAttributeRefs.push(index); + } + + dataOffset += attribute.getLength(); + attributes.push(attribute); + index++; + } + + if (this.debug) { + console.log(" ----- DUMP OF ATTRIBUTE REFERENCES -----"); + for (let i = 0; i < prevAttributeRefs.length; i++) { + console.log(`Node ${i}: last attribute ${prevAttributeRefs[i]}`); + } + + console.log(" ----- DUMP OF V2 ATTRIBUTE TABLE -----"); + for (let i = 0; i < attributes.length; i++) { + var resolved = attributes[i]; + console.log( + `${i}: ${this.getName(resolved)} (offset ${ + resolved.dataOffset + }, typeId ${resolved.getTypeId()}, nextAttribute ${ + resolved.nextAttributeIndex + }), node ${resolved.nodeIndex}` + ); + } + } + + this.attributes = attributes; + } + + /** + * Reads the V3 attribute headers for the LSOF resource + * @param buffer Stream to read the attribute headers from + */ + private readAttributesV3(buffer: Buffer) { + const attributes: Array = []; + const reader = new BufferReader(buffer); + + while (reader.offset < reader.length) { + attributes.push(new LSFAttributeEntryV3(reader)); + } + + if (this.debug) { + console.log(" ----- DUMP OF V3 ATTRIBUTE TABLE -----"); + + for (let i = 0; i < attributes.length; i++) { + var attribute = attributes[i]; + console.log( + `${i}: ${this.getName(attribute)} (offset ${ + attribute.dataOffset + }, typeId ${attribute.getTypeId()}, nextAttribute ${ + attribute.nextAttributeIndex + })` + ); + } + } + + this.attributes = attributes; + } + + private readRegions(resource: Resource, values: Buffer) { + const { nodes } = this; + const reader = new BufferReader(values); + const instances: Array = []; + + for (let i = 0; i < nodes.length; i++) { + const entry = nodes[i]; + + if (entry.parentIndex == -1) { + const region = new Region(); + this.readNode(entry, region, reader); + + resource.regions[region.name] = region; + instances.push(region); + } else { + const node = new Node(); + this.readNode(entry, node, reader); + + node.parent = instances[entry.parentIndex]; + instances.push(node); + instances[entry.parentIndex].append(node); + } + } + } + + private readNode(entry: NodeEntry, node: Node, reader: BufferReader) { + const { attributes } = this; + node.name = this.getName(entry); + + if (entry.firstAttributeIndex != -1) { + let attribute = attributes[entry.firstAttributeIndex]; + + while (attribute) { + reader.offset = attribute.dataOffset; + const value = this.readAttribute( + attribute.getTypeId(), + reader, + attribute.getLength() + ); + + node.attributes[this.getName(attribute)] = value; + + if (attribute.nextAttributeIndex == -1) { + break; + } else { + attribute = attributes[attribute.nextAttributeIndex]; + } + } + } + } + + private readAttribute( + type: DataType, + reader: BufferReader, + length: number + ): NodeAttribute { + // LSF and LSB serialize the buffer types differently, so specialized + // code is added to the LSB and LSf serializers, and the common code is + // available in BinUtils.ReadAttribute() + switch (type) { + case DataType.DT_String: + case DataType.DT_Path: + case DataType.DT_FixedString: + case DataType.DT_LSString: + case DataType.DT_WString: + case DataType.DT_LSWString: { + const attribute = new NodeAttribute(type); + attribute.value = this.readString(reader, length); + return attribute; + } + + case DataType.DT_TranslatedString: { + const attribute = new NodeAttribute(type); + + const valueLength = reader.readInt32(); + const value = this.readString(reader, valueLength); + + const handleLength = reader.readInt32(); + const handle = this.readString(reader, handleLength); + + attribute.value = new TranslatedString(value, handle); + return attribute; + } + + case DataType.DT_TranslatedFSString: { + const attribute = new NodeAttribute(type); + attribute.value = this.readTranslatedFSString(reader); + return attribute; + } + + case DataType.DT_ScratchBuffer: { + const attribute = new NodeAttribute(type); + attribute.value = reader.readBytes(length); + return attribute; + } + + default: + return readAttribute(type, reader); + } + } + + private readTranslatedFSString(reader: BufferReader): TranslatedFSString { + const valueLength = reader.readInt32(); + const value = this.readString(reader, valueLength); + + const handleLength = reader.readInt32(); + const handle = this.readString(reader, handleLength); + + const translatedString = new TranslatedFSString(value, handle); + + const length = reader.readInt32(); + for (let index = 0; index < length; index++) { + const argKeyLength = reader.readInt32(); + const argKey = this.readString(reader, argKeyLength); + + const string = this.readTranslatedFSString(reader); + + const argValueLength = reader.readInt32(); + const argValue = this.readString(reader, argValueLength); + + translatedString.arguments.push( + new TranslatedFSStringArgument(argKey, string, argValue) + ); + } + + return translatedString; + } + + private readString(reader: BufferReader, length: number = -1): string { + if (length === -1) { + const bytes: Array = []; + while (true) { + const b = reader.readByte(); + if (b != 0) { + bytes.push(String.fromCharCode(b)); + } else { + break; + } + } + + return bytes.join(""); + } + + const string = reader.readString(length - 1); + const nullTerminator = reader.readByte(); + if (nullTerminator != 0) { + throw new Error("String is not null-terminated"); + } + + return string; + } +} diff --git a/src/server/parsers/lsf/models/Matrix.ts b/src/server/parsers/lsf/models/Matrix.ts new file mode 100644 index 0000000..7ea058a --- /dev/null +++ b/src/server/parsers/lsf/models/Matrix.ts @@ -0,0 +1,32 @@ +export default class Matrix { + numColumns: number; + numRows: number; + values: Array>; + + constructor(numRows: number, numColumns: number) { + const values: Array> = []; + + for (let y = 0; y < numRows; y++) { + const row = []; + for (let x = 0; x < numColumns; x++) { + row.push(0); + } + + values.push(row); + } + + this.numColumns = numColumns; + this.numRows = numRows; + this.values = values; + } + + each(callback: (value: number, row: number, column: number) => void) { + const { numColumns, numRows, values } = this; + + for (let row = 0; row < numRows; row++) { + for (let column = 0; column < numColumns; column++) { + callback(values[row][column], row, column); + } + } + } +} diff --git a/src/server/parsers/lsf/models/Node.ts b/src/server/parsers/lsf/models/Node.ts new file mode 100644 index 0000000..4b59544 --- /dev/null +++ b/src/server/parsers/lsf/models/Node.ts @@ -0,0 +1,40 @@ +import NodeAttribute from "./NodeAttribute"; + +export default class Node { + attributes: { [name: string]: NodeAttribute } = {}; + children: { [name: string]: Array } = {}; + name: string = ""; + parent: Node | null = null; + + append(child: Node) { + const { name } = child; + let children = this.children[name]; + if (!children) { + this.children[name] = children = []; + } + + children.push(child); + } + + findNode(name: string, ...path: string[]): Node | null { + if (name in this.children) { + const child = this.children[name][0]; + if (path.length) { + const [childName, ...childPath] = path; + return child.findNode(childName, ...childPath); + } else { + return child; + } + } + + return null; + } + + getStringAttribute(name: string): string | null { + const attribute = this.attributes[name]; + if (!attribute) return null; + + const value = attribute.value; + return typeof value === "string" ? value : null; + } +} diff --git a/src/server/parsers/lsf/models/NodeAttribute.ts b/src/server/parsers/lsf/models/NodeAttribute.ts new file mode 100644 index 0000000..a59d686 --- /dev/null +++ b/src/server/parsers/lsf/models/NodeAttribute.ts @@ -0,0 +1,152 @@ +import * as Long from "long"; + +import Matrix from "./Matrix"; + +export enum DataType { + DT_None = 0, + DT_Byte = 1, + DT_Short = 2, + DT_UShort = 3, + DT_Int = 4, + DT_UInt = 5, + DT_Float = 6, + DT_Double = 7, + DT_IVec2 = 8, + DT_IVec3 = 9, + DT_IVec4 = 10, + DT_Vec2 = 11, + DT_Vec3 = 12, + DT_Vec4 = 13, + DT_Mat2 = 14, + DT_Mat3 = 15, + DT_Mat3x4 = 16, + DT_Mat4x3 = 17, + DT_Mat4 = 18, + DT_Bool = 19, + DT_String = 20, + DT_Path = 21, + DT_FixedString = 22, + DT_LSString = 23, + DT_ULongLong = 24, + DT_ScratchBuffer = 25, + DT_Long = 26, + DT_Int8 = 27, + DT_TranslatedString = 28, + DT_WString = 29, + DT_LSWString = 30, + DT_UUID = 31, + DT_Unknown32 = 32, + DT_TranslatedFSString = 33, + // Last supported datatype, always keep this one at the end + DT_Max = DT_TranslatedFSString +} + +export type AttributeValueType = + | boolean + | number + | string + | undefined + | Array + | Buffer + | Long + | Matrix + | TranslatedString; + +export class TranslatedString { + handle: string; + value: string; + + constructor(value: string, handle: string) { + this.value = value; + this.handle = handle; + } +} + +export class TranslatedFSStringArgument { + key: string; + string: TranslatedFSString; + value: string; + + constructor(key: string, string: TranslatedFSString, value: string) { + this.key = key; + this.string = string; + this.value = value; + } +} + +export class TranslatedFSString extends TranslatedString { + arguments: Array = []; +} + +export default class NodeAttribute { + type: DataType; + value: AttributeValueType; + + constructor(type: DataType) { + this.type = type; + } + + getNumRows(): number { + switch (this.type) { + case DataType.DT_IVec2: + case DataType.DT_IVec3: + case DataType.DT_IVec4: + case DataType.DT_Vec2: + case DataType.DT_Vec3: + case DataType.DT_Vec4: + return 1; + + case DataType.DT_Mat2: + return 2; + + case DataType.DT_Mat3: + case DataType.DT_Mat3x4: + return 3; + + case DataType.DT_Mat4x3: + case DataType.DT_Mat4: + return 4; + + default: + return 0; + } + } + + getNumColumns(): number { + switch (this.type) { + case DataType.DT_IVec2: + case DataType.DT_Vec2: + case DataType.DT_Mat2: + return 2; + + case DataType.DT_IVec3: + case DataType.DT_Vec3: + case DataType.DT_Mat3: + case DataType.DT_Mat4x3: + return 3; + + case DataType.DT_IVec4: + case DataType.DT_Vec4: + case DataType.DT_Mat3x4: + case DataType.DT_Mat4: + return 4; + + default: + return 0; + } + } + + isNumeric() { + return ( + this.type == DataType.DT_Byte || + this.type == DataType.DT_Short || + this.type == DataType.DT_Int || + this.type == DataType.DT_UInt || + this.type == DataType.DT_Float || + this.type == DataType.DT_Double || + this.type == DataType.DT_ULongLong || + this.type == DataType.DT_Long || + this.type == DataType.DT_Int8 + ); + } +} diff --git a/src/server/parsers/lsf/models/Region.ts b/src/server/parsers/lsf/models/Region.ts new file mode 100644 index 0000000..745be05 --- /dev/null +++ b/src/server/parsers/lsf/models/Region.ts @@ -0,0 +1,3 @@ +import Node from "./Node"; + +export default class Region extends Node {} diff --git a/src/server/parsers/lsf/models/Resource.ts b/src/server/parsers/lsf/models/Resource.ts new file mode 100644 index 0000000..2da271f --- /dev/null +++ b/src/server/parsers/lsf/models/Resource.ts @@ -0,0 +1,43 @@ +import Node from "./Node"; +import Region from "./Region"; + +export class LSMetadata { + buildNumber: number = 0; + majorVersion: number = 0; + minorVersion: number = 0; + revision: number = 0; + timestamp: number = 0; + + static currentMajorVersion = 33; +} + +export class LSBHeader { + bigEndian: number = 0; + metadata: LSMetadata = new LSMetadata(); + signature: number = 0; + totalSize: number = 0; + unknown: number = 0; + + static signature = 0x40000000; + static currentMajorVersion = 1; + static currentMinorVersion = 3; +} + +export default class Resource { + metadata: LSMetadata = new LSMetadata(); + regions: { [name: string]: Region } = {}; + + findNode(name: string, ...path: string[]): Node | null { + if (name in this.regions) { + const child = this.regions[name]; + if (path.length) { + const [childName, ...childPath] = path; + return child.findNode(childName, ...childPath); + } else { + return child; + } + } + + return null; + } +} diff --git a/src/server/parsers/lsf/structs/LSFAttributeEntryV2.ts b/src/server/parsers/lsf/structs/LSFAttributeEntryV2.ts new file mode 100644 index 0000000..666818d --- /dev/null +++ b/src/server/parsers/lsf/structs/LSFAttributeEntryV2.ts @@ -0,0 +1,64 @@ +import BufferReader from "../BufferReader"; + +/** + * V2 attribute extension in the LSF file + */ +export default class LSFAttributeEntryV2 { + /** + * Name of this attribute + * (16-bit MSB: index into name hash table, 16-bit LSB: offset in hash chain) + */ + nameHashTableIndex: number; + + /** + * 6-bit LSB: Type of this attribute (see NodeAttribute.DataType) + * 26-bit MSB: Length of this attribute + */ + typeAndLength: number; + + /** + * Index of the node that this attribute belongs to + * Note: These indexes are assigned seemingly arbitrarily, and are not neccessarily + * indices into the node list + */ + nodeIndex: number; + + nextAttributeIndex: number = -1; + + dataOffset: number; + + constructor(reader: BufferReader, dataOffset: number) { + this.nameHashTableIndex = reader.readUInt32(); + this.typeAndLength = reader.readUInt32(); + this.nodeIndex = reader.readInt32(); + this.dataOffset = dataOffset; + } + + /** + * Index into name hash table + */ + getNameIndex() { + return this.nameHashTableIndex >> 16; + } + + /** + * Offset in hash chain + */ + getNameOffset() { + return this.nameHashTableIndex & 0xffff; + } + + /** + * Type of this attribute (see NodeAttribute.DataType) + */ + getTypeId() { + return this.typeAndLength & 0x3f; + } + + /** + * Length of this attribute + */ + getLength() { + return this.typeAndLength >> 6; + } +} diff --git a/src/server/parsers/lsf/structs/LSFAttributeEntryV3.ts b/src/server/parsers/lsf/structs/LSFAttributeEntryV3.ts new file mode 100644 index 0000000..726c951 --- /dev/null +++ b/src/server/parsers/lsf/structs/LSFAttributeEntryV3.ts @@ -0,0 +1,65 @@ +import BufferReader from "../BufferReader"; + +/** + * V3 attribute extension in the LSF file + */ +export default class LSFAttributeEntryV3 { + /** + * Name of this attribute + * (16-bit MSB: index into name hash table, 16-bit LSB: offset in hash chain) + */ + nameHashTableIndex: number; + + /** + * 6-bit LSB: Type of this attribute (see NodeAttribute.DataType) + * 26-bit MSB: Length of this attribute + */ + typeAndLength: number; + + /** + * Index of the node that this attribute belongs to + * Note: These indexes are assigned seemingly arbitrarily, and are not neccessarily + * indices into the node list + */ + nextAttributeIndex: number; + + /** + * Absolute position of attribute value in the value stream + */ + dataOffset: number; + + constructor(reader: BufferReader) { + this.nameHashTableIndex = reader.readUInt32(); + this.typeAndLength = reader.readUInt32(); + this.nextAttributeIndex = reader.readInt32(); + this.dataOffset = reader.readUInt32(); + } + + /** + * Index into name hash table + */ + getNameIndex() { + return this.nameHashTableIndex >> 16; + } + + /** + * Offset in hash chain + */ + getNameOffset() { + return this.nameHashTableIndex & 0xffff; + } + + /** + * Type of this attribute (see NodeAttribute.DataType) + */ + getTypeId() { + return this.typeAndLength & 0x3f; + } + + /** + * Length of this attribute + */ + getLength() { + return this.typeAndLength >> 6; + } +} diff --git a/src/server/parsers/lsf/structs/LSFHeader.ts b/src/server/parsers/lsf/structs/LSFHeader.ts new file mode 100644 index 0000000..284eb0c --- /dev/null +++ b/src/server/parsers/lsf/structs/LSFHeader.ts @@ -0,0 +1,122 @@ +import BufferReader from "../BufferReader"; + +export default class LSFHeader { + /** + * LSOF file signature; should be the same as LSFHeader.Signature + */ + magic: string; + + /** + * Version of the LSOF file; D:OS EE is version 1/2, D:OS 2 is version 3 + */ + version: number; + + /** + * Possibly version number? (major, minor, rev, build) + */ + engineVersion: number; + + /** + * Total uncompressed size of the string hash table + */ + stringsUncompressedSize: number; + + /** + * Compressed size of the string hash table + */ + stringsSizeOnDisk: number; + + /** + * Total uncompressed size of the node list + */ + nodesUncompressedSize: number; + + /** + * Compressed size of the node list + */ + nodesSizeOnDisk: number; + + /** + * Total uncompressed size of the attribute list + */ + attributesUncompressedSize: number; + + /** + * Compressed size of the attribute list + */ + attributesSizeOnDisk: number; + + /** + * Total uncompressed size of the raw value buffer + */ + valuesUncompressedSize: number; + + /** + * Compressed size of the raw value buffer + */ + valuesSizeOnDisk: number; + + /** + * Compression method and level used for the string, node, attribute and value buffers. + * Uses the same format as packages (see BinUtils.MakeCompressionFlags) + */ + compressionFlags: number; + + /** + * Possibly unused, always 0 + */ + unknown2: number; + unknown3: number; + + /** + * Extended node/attribute format indicator, 0 for V2, 0/1 for V3 + */ + extended: number; + + /** + * Required header signature. + */ + static headerSignature = "LSOF"; + + /** + * Initial version of the LSF format + */ + static versionInitial = 0x01; + + /** + * LSF version that added chunked compression for substreams + */ + static versionChunkedCompress = 0x02; + + /** + * LSF version that extended the node descriptors + */ + static versionExtendedNodes = 0x03; + + /** + * Latest version supported by this library + */ + static currentVersion = 0x03; + + constructor(reader: BufferReader) { + this.magic = reader.readString(4); + this.version = reader.readUInt32(); + this.engineVersion = reader.readUInt32(); + this.stringsUncompressedSize = reader.readUInt32(); + this.stringsSizeOnDisk = reader.readUInt32(); + this.nodesUncompressedSize = reader.readUInt32(); + this.nodesSizeOnDisk = reader.readUInt32(); + this.attributesUncompressedSize = reader.readUInt32(); + this.attributesSizeOnDisk = reader.readUInt32(); + this.valuesUncompressedSize = reader.readUInt32(); + this.valuesSizeOnDisk = reader.readUInt32(); + this.compressionFlags = reader.readUInt8(); + this.unknown2 = reader.readUInt8(); + this.unknown3 = reader.readUInt16(); + this.extended = reader.readUInt32(); + } + + validate(): boolean { + return this.magic === LSFHeader.headerSignature; + } +} diff --git a/src/server/parsers/lsf/structs/LSFNodeEntryV2.ts b/src/server/parsers/lsf/structs/LSFNodeEntryV2.ts new file mode 100644 index 0000000..b26f4da --- /dev/null +++ b/src/server/parsers/lsf/structs/LSFNodeEntryV2.ts @@ -0,0 +1,44 @@ +import BufferReader from "../BufferReader"; + +/** + * Node (structure) entry in the LSF file + */ +export default class LSFNodeEntryV2 { + /** + * Name of this node + * (16-bit MSB: index into name hash table, 16-bit LSB: offset in hash chain) + */ + nameHashTableIndex: number; + + /** + * Index of the first attribute of this node + * (-1: node has no attributes) + */ + firstAttributeIndex: number; + + /** + * Index of the parent node + * (-1: this node is a root region) + */ + parentIndex: number; + + constructor(reader: BufferReader) { + this.nameHashTableIndex = reader.readUInt32(); + this.firstAttributeIndex = reader.readInt32(); + this.parentIndex = reader.readInt32(); + } + + /** + * Index into name hash table + */ + getNameIndex() { + return this.nameHashTableIndex >> 16; + } + + /** + * Offset in hash chain + */ + getNameOffset() { + return this.nameHashTableIndex & 0xffff; + } +} diff --git a/src/server/parsers/lsf/structs/LSFNodeEntryV3.ts b/src/server/parsers/lsf/structs/LSFNodeEntryV3.ts new file mode 100644 index 0000000..e2e6aed --- /dev/null +++ b/src/server/parsers/lsf/structs/LSFNodeEntryV3.ts @@ -0,0 +1,51 @@ +import BufferReader from "../BufferReader"; + +/** + * Node (structure) entry in the LSF file + */ +export default class LSFNodeEntryV3 { + /** + * Name of this node + * (16-bit MSB: index into name hash table, 16-bit LSB: offset in hash chain) + */ + nameHashTableIndex: number; + + /** + * Index of the parent node + * (-1: this node is a root region) + */ + parentIndex: number; + + /** + * Index of the next sibling of this node + * (-1: this is the last node) + */ + nextSiblingIndex: number; + + /** + * Index of the first attribute of this node + * (-1: node has no attributes) + */ + firstAttributeIndex: number; + + constructor(reader: BufferReader) { + this.nameHashTableIndex = reader.readUInt32(); + this.parentIndex = reader.readInt32(); + this.nextSiblingIndex = reader.readInt32(); + this.firstAttributeIndex = reader.readInt32(); + } + + /** + * Index into name hash table + */ + getNameIndex() { + return this.nameHashTableIndex >> 16; + } + + /** + * Offset in hash chain + */ + getNameOffset() { + return this.nameHashTableIndex & 0xffff; + } +} diff --git a/src/server/parsers/lsf/utils/compressionMethod.ts b/src/server/parsers/lsf/utils/compressionMethod.ts new file mode 100644 index 0000000..07c29ba --- /dev/null +++ b/src/server/parsers/lsf/utils/compressionMethod.ts @@ -0,0 +1,21 @@ +export enum CompressionMethod { + None = 0, + Zlib = 1, + LZ4 = 2 +} + +export function CompressionFlagsToMethod(flags: number): CompressionMethod { + switch (flags & 0x0f) { + case 0: + return CompressionMethod.None; + + case 1: + return CompressionMethod.Zlib; + + case 2: + return CompressionMethod.LZ4; + + default: + throw new Error("Invalid compression method"); + } +} diff --git a/src/server/parsers/lsf/utils/readAttribute.ts b/src/server/parsers/lsf/utils/readAttribute.ts new file mode 100644 index 0000000..6c3697e --- /dev/null +++ b/src/server/parsers/lsf/utils/readAttribute.ts @@ -0,0 +1,111 @@ +import * as Long from "long"; + +import BufferReader from "../BufferReader"; +import Matrix from "../models/Matrix"; +import NodeAttribute, { DataType } from "../models/NodeAttribute"; + +export function readAttribute(type: DataType, reader: BufferReader) { + const attribute = new NodeAttribute(type); + + switch (type) { + case DataType.DT_None: + break; + + case DataType.DT_Byte: + attribute.value = reader.readByte(); + break; + + case DataType.DT_Short: + attribute.value = reader.readInt16(); + break; + + case DataType.DT_UShort: + attribute.value = reader.readUInt16(); + break; + + case DataType.DT_Int: + attribute.value = reader.readInt32(); + break; + + case DataType.DT_UInt: + attribute.value = reader.readUInt32(); + break; + + case DataType.DT_Float: + attribute.value = reader.readFloat(); + break; + + case DataType.DT_Double: + attribute.value = reader.readDouble(); + break; + + case DataType.DT_IVec2: + case DataType.DT_IVec3: + case DataType.DT_IVec4: { + const columns = attribute.getNumColumns(); + const vector: Array = []; + for (let index = 0; index < columns; index++) { + vector[index] = reader.readInt32(); + } + + attribute.value = vector; + break; + } + + case DataType.DT_Vec2: + case DataType.DT_Vec3: + case DataType.DT_Vec4: { + const columns = attribute.getNumColumns(); + const vector: Array = []; + for (let index = 0; index < columns; index++) { + vector[index] = reader.readFloat(); + } + + attribute.value = vector; + break; + } + + case DataType.DT_Mat2: + case DataType.DT_Mat3: + case DataType.DT_Mat3x4: + case DataType.DT_Mat4x3: + case DataType.DT_Mat4: { + const columns = attribute.getNumColumns(); + const rows = attribute.getNumRows(); + const matrix = new Matrix(rows, columns); + matrix.each((value, row, column) => { + matrix.values[row][column] = reader.readFloat(); + }); + + attribute.value = matrix; + break; + } + + case DataType.DT_Bool: + attribute.value = reader.readByte() != 0; + break; + + case DataType.DT_ULongLong: + attribute.value = new Long(reader.readInt32(), reader.readInt32(), true); + break; + + case DataType.DT_Long: + attribute.value = new Long(reader.readInt32(), reader.readInt32()); + break; + + case DataType.DT_Int8: + attribute.value = reader.readInt8(); + break; + + case DataType.DT_UUID: + attribute.value = reader.readString(16); + break; + + default: + // Strings are serialized differently for each file format and should be + // handled by the format-specific ReadAttribute() + throw new Error(`ReadAttribute() not implemented for type ${type}`); + } + + return attribute; +} diff --git a/src/server/parsers/story/GoalParser.ts b/src/server/parsers/story/GoalParser.ts new file mode 100644 index 0000000..420aec5 --- /dev/null +++ b/src/server/parsers/story/GoalParser.ts @@ -0,0 +1,202 @@ +import msgInvalidOptionLocation from "./messages/msgInvalidOptionLocation"; +import msgInvalidOptionName from "./messages/msgInvalidOptionName"; +import msgInvalidOptionValue from "./messages/msgInvalidOptionValue"; +import msgUnexpectedToken from "./messages/msgUnexpectedToken"; +import ParserBase from "./Parser"; +import { Diagnostic } from "./models/diagnostics"; +import { NodeType, StoryGoalNode, AnyNode } from "./models/nodes"; +import { TokenType, Token } from "./Lexer"; + +import isStoryToken, { + StoryToken, + storyTokenTypes +} from "./utils/isStoryToken"; + +export interface ParserResult { + diagnostics: Array; + goal: StoryGoalNode; +} + +export default class GoalParser extends ParserBase { + parse(): ParserResult { + let storyToken: StoryToken | undefined; + const goal: StoryGoalNode = { + endOffset: 0, + endPosition: 0, + startOffset: 0, + startPosition: 0, + type: NodeType.StoryGoal + }; + + this.withBailOutTypes(storyTokenTypes, () => { + do { + switch (storyToken ? storyToken.type : undefined) { + case TokenType.InitSectionKeyword: + storyToken = this.readStoryInit(goal); + break; + case TokenType.KBSectionKeyword: + storyToken = this.readStoryKB(goal); + break; + case TokenType.ExitSectionKeyword: + storyToken = this.readStoryExit(goal); + break; + case TokenType.EndExitSectionKeyword: + storyToken = this.readStoryOptions(goal, false); + break; + default: + storyToken = this.readStoryOptions(goal, true); + } + } while (storyToken); + }); + + return { + diagnostics: this.diagnostics, + goal + }; + } + + readStoryInit = this.withStoryBoundary(TokenType.KBSectionKeyword, goal => { + return (goal.init = this.readActionBlock()); + }); + + readStoryKB = this.withStoryBoundary(TokenType.ExitSectionKeyword, goal => { + return (goal.kb = this.readRuleBlock()); + }); + + readStoryExit = this.withStoryBoundary( + TokenType.EndExitSectionKeyword, + goal => { + return (goal.exit = this.readActionBlock()); + } + ); + + readStoryOptions( + goal: StoryGoalNode, + isHeader: boolean + ): StoryToken | undefined { + let token: Token | undefined; + + while ((token = this.next())) { + if (isStoryToken(token)) { + return token; + } else if (token.type === TokenType.Identifier) { + this.readStoryOption(goal, token, isHeader); + } else { + this.addDiagnostic( + token, + msgUnexpectedToken({ + actualToken: token + }) + ); + } + } + + return undefined; + } + + readStoryOption(goal: StoryGoalNode, token: Token, isHeader: boolean) { + let valueToken: Token | undefined; + const headerCheck = (target: boolean) => + target !== isHeader + ? this.addDiagnostic( + token, + msgInvalidOptionLocation({ + isHeader, + name: token.value + }) + ) + : null; + + switch (token.value) { + case "Version": + headerCheck(true); + valueToken = this.read(TokenType.IntegerLiteral, true); + if (valueToken) { + const version = parseInt(valueToken.value); + if (version !== 1) { + this.addDiagnostic( + token, + msgInvalidOptionValue({ + actualValue: valueToken.value, + expectedValue: "1", + name: "Version" + }) + ); + } + + goal.version = version; + } + break; + + case "SubGoalCombiner": + headerCheck(true); + valueToken = this.read(TokenType.Identifier, true); + if (valueToken) { + if (valueToken.value !== "SGC_AND") { + this.addDiagnostic( + valueToken, + msgInvalidOptionValue({ + actualValue: valueToken.value, + expectedValue: "SGC_AND", + name: "SubGoalCombiner" + }) + ); + } + + goal.subGoalCombiner = valueToken.value; + } + break; + + case "ParentTargetEdge": + headerCheck(false); + const parent = this.readStringLiteral(); + if (parent) { + if (!goal.parentTargetEdges) { + goal.parentTargetEdges = []; + } + goal.parentTargetEdges.push(parent); + } + break; + + default: + this.addDiagnostic(token, msgInvalidOptionName({ name: token.value })); + } + } + + withStoryBoundary( + boundaryType: TokenType, + callback: { + (goal: StoryGoalNode): AnyNode | undefined; + } + ) { + return (goal: StoryGoalNode): StoryToken | undefined => { + const last = this.last(); + let node: AnyNode | undefined; + if (last) { + const startOffset = last.startOffset; + const startPosition = last.startPosition; + + node = callback(goal); + if (node) { + node.startOffset = startOffset; + node.startPosition = startPosition; + } + } else { + node = callback(goal); + } + + const storyToken = this.readStoryBoundary(); + if (storyToken && storyToken.type !== boundaryType) { + this.addDiagnostic( + storyToken, + msgUnexpectedToken({ + actualToken: storyToken, + expectedToken: boundaryType + }) + ); + } + + return storyToken; + }; + } +} diff --git a/src/server/parsers/story/HeaderParser.ts b/src/server/parsers/story/HeaderParser.ts new file mode 100644 index 0000000..a64bed8 --- /dev/null +++ b/src/server/parsers/story/HeaderParser.ts @@ -0,0 +1,271 @@ +import ParserBase from "./Parser"; +import { Diagnostic } from "./models/diagnostics"; +import { Token, TokenType } from "./Lexer"; + +import { + HeaderGoalNode, + NodeType, + HeaderNode, + DefinitionNode +} from "./models/nodes"; +import msgUnexpectedToken from "./messages/msgUnexpectedToken"; +import msgInvalidOptionName from "./messages/msgInvalidOptionName"; +import msgInvalidGoalSection from "./messages/msgInvalidGoalSection"; + +function isAliasTypeToken(token: Token): boolean { + return token.type === TokenType.Identifier && token.value === "alias_type"; +} + +function isConfigToken(token: Token): boolean { + return ( + token.type === TokenType.Identifier && + (token.value === "option" || token.value === "version") + ); +} + +function isGoalToken(token: Token): boolean { + return token.type === TokenType.Identifier && token.value === "Goal"; +} + +function isDefinitionToken(token: Token): boolean { + return ( + token.type === TokenType.Identifier && + (token.value === "call" || + token.value === "event" || + token.value === "query" || + token.value === "syscall" || + token.value === "sysquery") + ); +} + +function range(source: string, start: number, end: number): string { + if (!range) { + return ""; + } + + const sourcePart = source.substring(start, end).trim(); + if (sourcePart === "") return ""; + + const lines = sourcePart.split("\r\n"); + lines.push(""); + lines.unshift(""); + + return lines + .map(line => (line.startsWith("\t\t") ? line.substr(2) : line)) + .join("\r\n"); +} + +export interface ParserResult { + diagnostics: Array; + header: HeaderNode; +} + +export default class HeaderParser extends ParserBase { + parse(): ParserResult { + let token: Token | undefined; + const header: HeaderNode = { + definitions: [], + endOffset: 0, + endPosition: 0, + goals: [], + startOffset: 0, + startPosition: 0, + type: NodeType.Div, + typeAliases: [] + }; + + while ((token = this.next())) { + if (isAliasTypeToken(token)) { + this.consumeAlias(header); + } else if (isConfigToken(token)) { + this.tryReadConstant(); + } else if (isDefinitionToken(token)) { + const definition = this.readDefinition(token); + if (definition) { + header.definitions.push(definition); + } + } else if (isGoalToken(token)) { + this.readGoal(header); + } + } + + return { + diagnostics: this.diagnostics, + header + }; + } + + consumeAlias(header: HeaderNode) { + if (!this.consume(TokenType.CurlyBracketOpen)) { + return; + } + + const type = this.read(TokenType.Identifier); + if (type) { + header.typeAliases.push(type.value); + } + + this.consumeIncluding(TokenType.CurlyBracketClose); + } + + readDefinition(token: Token): DefinitionNode | undefined { + const startOffset = token.startOffset; + const startPosition = token.startPosition; + const definitionType = token.value; + const signature = this.readSignature(); + + if (!signature) return undefined; + + if (this.consume(TokenType.BracketOpen)) { + this.consumeIncluding(TokenType.BracketClose); + } else { + this.addDiagnostic( + undefined, + msgUnexpectedToken({ + actualToken: this.last(), + expectedHint: "definitionMetaData" + }) + ); + } + + return { + definitionType, + endOffset: signature.endOffset, + endPosition: signature.endPosition, + signature, + startOffset, + startPosition, + type: NodeType.Definition + }; + } + + readGoal(header: HeaderNode): undefined { + if (!this.consume(TokenType.BracketOpen)) { + return undefined; + } + + const idToken = this.read(TokenType.IntegerLiteral); + if (!idToken) { + this.consumeIncluding(TokenType.BracketClose); + return undefined; + } + + const id = parseInt(idToken.value); + if (!this.consume(TokenType.BracketClose)) { + return undefined; + } + + let goal = header.goals.find(goal => goal.id === id); + if (!goal) { + goal = { + endOffset: 0, + endPosition: 0, + id, + startPosition: 0, + startOffset: 0, + subGoal: [], + type: NodeType.DivGoal + }; + header.goals.push(goal); + } + + const separator = this.next(); + if (separator && separator.type === TokenType.Dot) { + this.readGoalOption(goal); + } else if (separator && separator.type === TokenType.CurlyBracketOpen) { + this.readGoalContent(goal); + } + + return undefined; + } + + readGoalContent(goal: HeaderGoalNode) { + let token: Token | undefined; + + while ((token = this.next())) { + if (token.type === TokenType.CurlyBracketClose) { + break; + } else if (token.type === TokenType.Identifier) { + const sectionName = token.value; + + token = this.read(TokenType.CurlyBracketOpen); + if (!token) continue; + + const start = token.endOffset; + while ((token = this.next())) { + if (token.type === TokenType.CurlyBracketClose) { + break; + } + } + + if (!token) continue; + const data = range(this.source, start, token.startOffset); + + switch (sectionName) { + case "INIT": + goal.init = data; + break; + case "KB": + goal.kb = data; + break; + case "EXIT": + goal.exit = data; + break; + default: + this.addDiagnostic( + token, + msgInvalidGoalSection({ + name: sectionName + }) + ); + } + } else { + this.addDiagnostic( + token, + msgUnexpectedToken({ + actualToken: token + }) + ); + } + } + } + + readGoalOption(goal: HeaderGoalNode) { + const identifier = this.read(TokenType.Identifier); + if (!identifier) { + return this.consumeIncluding(TokenType.SemiColon); + } + + const option = identifier.value; + if (!this.consume(TokenType.BracketOpen)) { + return this.consumeIncluding(TokenType.SemiColon); + } + + if (option === "Title") { + const title = this.read(TokenType.StringLiteral); + if (title) { + goal.title = title.value.substr(1, title.value.length - 2); + } + } else if (option === "SubGoal") { + const subGoal = this.read(TokenType.IntegerLiteral); + if (subGoal) { + goal.subGoal.push(parseInt(subGoal.value)); + } + } else if (option === "SubGoals") { + this.next(); + } else { + this.addDiagnostic( + identifier, + msgInvalidOptionName({ + name: option + }) + ); + } + + if (!this.consume(TokenType.BracketClose)) { + return this.consumeIncluding(TokenType.SemiColon); + } + + this.ensureSemiColon(); + } +} diff --git a/src/server/parsers/story/Lexer.ts b/src/server/parsers/story/Lexer.ts new file mode 100644 index 0000000..4b90dd9 --- /dev/null +++ b/src/server/parsers/story/Lexer.ts @@ -0,0 +1,526 @@ +import msgNewLineInString from "./messages/msgNewLineInString"; +import msgPrematureRealEnd from "./messages/msgPrematureRealEnd"; +import packPosition from "./utils/packPosition"; +import unpackRange from "./utils/unpackRange"; + +import { + DiagnosticType, + Diagnostic, + DiagnosticMessage +} from "./models/diagnostics"; + +const CHAR_TAB = 9; +const CHAR_NEWLINE = 10; +const CHAR_CARRIAGE_RETURN = 13; +const CHAR_SPACE = 32; +const CHAR_EXCLAMATION = 33; +const CHAR_QUOTE = 34; +const CHAR_BRACKET_OPEN = 40; +const CHAR_BRACKET_CLOSE = 41; +const CHAR_ASTERISK = 42; +const CHAR_PLUS = 43; +const CHAR_COLON = 44; +const CHAR_MINUS = 45; +const CHAR_DOT = 46; +const CHAR_SLASH = 47; +const CHAR_SEMICOLON = 59; +const CHAR_LOWER_THAN = 60; +const CHAR_EQUALS = 61; +const CHAR_GREATER_THAN = 62; +const CHAR_SQUARE_OPEN = 91; +const CHAR_SQUARE_CLOSE = 93; +const CHAR_UNDERSCORE = 95; +const CHAR_CURLY_OPEN = 123; +const CHAR_CURLY_CLOSE = 125; + +const NUM_TOKENS = 5; + +const GUID_REGEXP = /[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$/; + +const VALUE_BUFFER: Buffer = Buffer.alloc(64 * 1024); + +function isIdentifierChar(char: number): boolean { + return ( + isIdentifierStartChar(char) || isNumericChar(char) || char === CHAR_MINUS + ); +} + +function isIdentifierStartChar(char: number): boolean { + return ( + (char >= 65 && char <= 90) || + (char >= 97 && char <= 122) || + char === CHAR_UNDERSCORE + ); +} + +function isNumericChar(char: number): boolean { + return char >= 48 && char <= 57; +} + +function isOperantChar(char: number): boolean { + return ( + char === CHAR_EXCLAMATION || + char === CHAR_LOWER_THAN || + char === CHAR_EQUALS || + char === CHAR_GREATER_THAN + ); +} + +function extractComment(value: string, type: TokenType): string { + while (value.startsWith("/")) { + value = value.substr(1); + } + + if (type === TokenType.LineComment) { + return value; + } + + while (value.endsWith("/") || value.endsWith("*")) { + value = value.substr(0, value.length - 1); + } + + const lines = value.split(/\r\n|\r|\n/); + for (let index = 0; index < lines.length; index++) { + lines[index] = lines[index].replace(/^\s*\*+\s*/, ""); + } + + return lines.join("\n"); +} + +export const enum TokenType { + Empty, + EndOfFile, + Invalid, + + // Common token types + Annotation, + BlockComment, + BracketOpen, + BracketClose, + Colon, + CurlyBracketOpen, + CurlyBracketClose, + Dot, + GuidLiteral, + FloatLiteral, + Identifier, + IntegerLiteral, + LineComment, + Operator, + SemiColon, + StringLiteral, + + // Keyword tokens + AndKeyword, + EndExitSectionKeyword, + ExitSectionKeyword, + GoalCompletedKeyword, + IfKeyword, + InitSectionKeyword, + KBSectionKeyword, + NotKeyword, + ProcKeyword, + ThenKeyword, + QueryKeyword +} + +export type PackedPosition = number; + +export interface TokenRange { + endOffset: number; + endPosition: PackedPosition; + startOffset: number; + startPosition: PackedPosition; +} + +export interface Token extends TokenRange { + comment: string | null; + type: TokenType; + value: string; +} + +export default class Lexer { + diagnostics: Array = []; + source: string; + character: number = -1; + lastComment: string | null = null; + line: number = 0; + offset: number = 0; + region: string | null = null; + private tokenBuffer: Array; + + constructor(source: string) { + const tokenBuffer: Array = []; + this.source = source; + this.tokenBuffer = tokenBuffer; + + for (let index = 0; index < NUM_TOKENS; index++) { + tokenBuffer.push({ + comment: null, + endOffset: 0, + endPosition: 0, + startOffset: 0, + startPosition: 0, + type: TokenType.Empty, + value: "" + }); + + if (index < NUM_TOKENS - 1) { + this.readNextToken(index); + } + } + } + + addDiagnostic( + range: TokenRange | undefined = undefined, + message: DiagnosticMessage + ) { + range = range || this.last() || this.peak(); + + if (range) { + this.diagnostics.push({ + ...message, + range: unpackRange(range), + type: DiagnosticType.Syntax + }); + } + } + + last(): Token | undefined { + const { tokenBuffer } = this; + const result = tokenBuffer[NUM_TOKENS - 1]; + + return result.type === TokenType.EndOfFile || + result.type === TokenType.Empty + ? undefined + : result; + } + + next(): Token | undefined { + const { tokenBuffer } = this; + const result = tokenBuffer[0]; + if (result.type === TokenType.EndOfFile) { + return undefined; + } + + for (let index = 1; index < NUM_TOKENS; index++) { + tokenBuffer[index - 1] = tokenBuffer[index]; + } + + tokenBuffer[NUM_TOKENS - 1] = result; + + do { + this.readNextToken(NUM_TOKENS - 2); + } while ( + tokenBuffer[NUM_TOKENS - 2].type === TokenType.LineComment || + tokenBuffer[NUM_TOKENS - 2].type === TokenType.BlockComment + ); + + return result; + } + + peak(offset: number = 0): Token | undefined { + if (offset > NUM_TOKENS - 2) { + throw new Error("Invalid peak offset."); + } + + const { tokenBuffer } = this; + for (let index = 0; index <= offset; index++) { + if (tokenBuffer[index].type === TokenType.EndOfFile) { + return undefined; + } + } + + return tokenBuffer[offset]; + } + + tokenize() { + const result: Array = []; + let token: Token | undefined; + while ((token = this.next())) { + result.push({ + ...token, + endOffset: token.endOffset, + endPosition: token.endPosition, + startOffset: token.startOffset, + startPosition: token.startPosition + }); + } + + return result; + } + + private readNextToken(bufferIndex: number) { + const { source } = this; + const { length } = source; + let { character, line, offset } = this; + const value = VALUE_BUFFER; + const token = this.tokenBuffer[bufferIndex]; + + let char: number | undefined; + let charLength: number | undefined; + let isNewLine = false; + let nextChar: number | undefined; + let previousCharacter = character; + let previousLine = line; + let previousOffset = offset; + let type: TokenType | undefined; + let valueOffset = 0; + + while (offset < length) { + previousCharacter = character; + previousLine = line; + previousOffset = offset; + + char = source.charCodeAt(offset); + charLength = 1; + + isNewLine = false; + offset += 1; + character += 1; + + // Track line numbers + if (char === CHAR_CARRIAGE_RETURN) { + isNewLine = true; + character = -1; + line += 1; + + if (offset < length - 1) { + nextChar = source.charCodeAt(offset); + if (nextChar === CHAR_NEWLINE) { + charLength += 1; + offset += 1; + } + } + } + + if (char === CHAR_NEWLINE) { + isNewLine = true; + character = -1; + line += 1; + } + + // Consume values of the current token + if (type) { + if (type === TokenType.Annotation) { + // Annotations consume till `]` + if (char === CHAR_SQUARE_CLOSE) { + value[valueOffset++] = char; + break; + } + } else if (type === TokenType.BlockComment) { + // Block comments consume till `*/` + if ( + char === CHAR_SLASH && + valueOffset > 1 && + value[valueOffset - 1] === CHAR_ASTERISK + ) { + value[valueOffset++] = char; + break; + } + } else if (type === TokenType.LineComment) { + // Line comments consume till new line + if (isNewLine) { + // YIELD LineComment + break; + } + } else if (type === TokenType.StringLiteral) { + // String literals consume till `"` + if (char === CHAR_QUOTE) { + value[valueOffset++] = char; + break; + } + } else if (type === TokenType.FloatLiteral) { + // Float literals consume till no more numbers are read + if (!isNumericChar(char)) { + character = previousCharacter; + line = previousLine; + offset = previousOffset; + break; + } + } else if (type === TokenType.IntegerLiteral) { + if (char === CHAR_DOT) { + // If a dot is found, switch to float literal + type = TokenType.FloatLiteral; + } else if (char === CHAR_MINUS) { + // A guid starting with only numbers + type = TokenType.Identifier; + } else if (!isNumericChar(char)) { + // Integer literals consume till no more numbers are read + character = previousCharacter; + line = previousLine; + offset = previousOffset; + break; + } + } else if (type === TokenType.Identifier) { + // Identifiers read all valid characters + if (!isIdentifierChar(char)) { + character = previousCharacter; + line = previousLine; + offset = previousOffset; + break; + } + } + + value[valueOffset++] = char; + continue; + } + + // Just skip whitespace + if (isNewLine || char === CHAR_SPACE || char === CHAR_TAB) { + continue; + } + + token.startOffset = offset - 1; + token.startPosition = packPosition(line, character); + + // Single character tokens + if (char === CHAR_BRACKET_OPEN) { + type = TokenType.BracketOpen; + break; + } else if (char === CHAR_BRACKET_CLOSE) { + type = TokenType.BracketClose; + break; + } else if (char === CHAR_CURLY_OPEN) { + type = TokenType.CurlyBracketOpen; + break; + } else if (char === CHAR_CURLY_CLOSE) { + type = TokenType.CurlyBracketClose; + break; + } else if (char === CHAR_COLON) { + type = TokenType.Colon; + break; + } else if (char === CHAR_SEMICOLON) { + type = TokenType.SemiColon; + break; + } else if (char === CHAR_DOT) { + // Maybe start of float + nextChar = source.charCodeAt(offset); + if (isNumericChar(nextChar)) { + value[valueOffset++] = char; + value[valueOffset++] = nextChar; + type = TokenType.FloatLiteral; + offset += 1; + character += 1; + } else { + type = TokenType.Dot; + break; + } + } else if (char === CHAR_QUOTE) { + value[valueOffset++] = char; + type = TokenType.StringLiteral; + } else if (char === CHAR_SQUARE_OPEN) { + value[valueOffset++] = char; + type = TokenType.Annotation; + } else if ( + isNumericChar(char) || + char === CHAR_PLUS || + char === CHAR_MINUS + ) { + value[valueOffset++] = char; + type = TokenType.IntegerLiteral; + } else if (char === CHAR_SLASH) { + nextChar = source.charCodeAt(offset); + if (nextChar === CHAR_ASTERISK) { + value[valueOffset++] = char; + value[valueOffset++] = nextChar; + type = TokenType.BlockComment; + offset += 1; + character += 1; + } else if (nextChar === CHAR_SLASH) { + value[valueOffset++] = char; + value[valueOffset++] = nextChar; + type = TokenType.LineComment; + offset += 1; + character += 1; + } + } else if (isOperantChar(char)) { + nextChar = source.charCodeAt(offset); + if (nextChar === CHAR_EQUALS) { + value[valueOffset++] = char; + value[valueOffset++] = nextChar; + type = TokenType.Operator; + offset += 1; + character += 1; + break; + } else if (char === CHAR_GREATER_THAN || char === CHAR_LOWER_THAN) { + value[valueOffset++] = char; + type = TokenType.Operator; + break; + } + } else if (isIdentifierStartChar(char)) { + value[valueOffset++] = char; + type = TokenType.Identifier; + } else { + type = TokenType.Invalid; + break; + } + } + + this.character = character; + this.line = line; + this.offset = offset; + + const stringValue = value.toString("utf-8", 0, valueOffset); + if (type === TokenType.Identifier) { + if (stringValue === "AND") { + type = TokenType.AndKeyword; + } else if (stringValue === "ENDEXITSECTION") { + type = TokenType.EndExitSectionKeyword; + } else if (stringValue === "EXITSECTION") { + type = TokenType.ExitSectionKeyword; + } else if (stringValue === "GoalCompleted") { + type = TokenType.GoalCompletedKeyword; + } else if (stringValue === "IF") { + type = TokenType.IfKeyword; + } else if (stringValue === "INITSECTION") { + type = TokenType.InitSectionKeyword; + } else if (stringValue === "KBSECTION") { + type = TokenType.KBSectionKeyword; + } else if (stringValue === "NOT") { + type = TokenType.NotKeyword; + } else if (stringValue === "PROC") { + type = TokenType.ProcKeyword; + } else if (stringValue === "THEN") { + type = TokenType.ThenKeyword; + } else if (stringValue === "QRY") { + type = TokenType.QueryKeyword; + } else if (GUID_REGEXP.test(stringValue)) { + type = TokenType.GuidLiteral; + } + } + + token.endOffset = offset; + token.endPosition = packPosition(line, character + 1); + token.type = type || TokenType.EndOfFile; + token.value = stringValue; + + if ( + token.type === TokenType.LineComment && + stringValue.startsWith("//REGION") + ) { + this.region = stringValue.substr(8).trim(); + } else if ( + token.type === TokenType.LineComment && + stringValue.startsWith("//END_REGION") + ) { + this.region = null; + } else if ( + token.type === TokenType.BlockComment || + token.type === TokenType.LineComment + ) { + this.lastComment = extractComment(stringValue, token.type); + } else { + token.comment = this.lastComment; + this.lastComment = null; + } + + if (token.type === TokenType.FloatLiteral && token.value.endsWith(".")) { + this.addDiagnostic(token, msgPrematureRealEnd()); + } + + if (token.type === TokenType.StringLiteral && /[\r\n]/.test(token.value)) { + this.addDiagnostic(token, msgNewLineInString()); + } + } +} diff --git a/src/server/parsers/story/Parser.ts b/src/server/parsers/story/Parser.ts new file mode 100644 index 0000000..e5a400f --- /dev/null +++ b/src/server/parsers/story/Parser.ts @@ -0,0 +1,721 @@ +import isRuleToken, { ruleTokenTypes } from "./utils/isRuleToken"; +import isStoryToken, { StoryToken } from "./utils/isStoryToken"; +import Lexer, { TokenType, Token, TokenRange } from "./Lexer"; +import msgEmptyRuleBody from "./messages/msgEmptyRuleBody"; +import { ActionNode } from "./utils/isActionNode"; +import { ArgumentNode } from "./utils/isArgumentNode"; +import { ConditionNode } from "./utils/isConditionNode"; + +import msgUnexpectedToken, { + UnexpectedTokenHint +} from "./messages/msgUnexpectedToken"; + +import { + ActionBlockNode, + ConditionBlockNode, + NodeType, + OperatorNode, + ParameterNode, + RuleNode, + SignatureNode, + TypeAnnotationNode, + RuleBlockNode, + SignatureCallNode, + AbstractNode, + ParameterFlow, + IdentifierNode, + StringLiteralNode, + NumericLiteralNode, + GuidLiteralNode, + IdentifierType, + GoalCompletedNode +} from "./models/nodes"; + +type Omit = Pick>; + +type WithoutRange = Omit< + T, + "endOffset" | "endPosition" | "startOffset" | "startPosition" +>; + +const GUID_REGEXP = /(.*?)([0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12})$/; + +export default class Parser extends Lexer { + bailOutTypes: Array = []; + + consume(type: TokenType): boolean { + const token = this.peak(); + if (token && token.type === type) { + this.next(); + return true; + } + + this.addDiagnostic( + token, + msgUnexpectedToken({ + actualToken: token, + expectedToken: type + }) + ); + + return false; + } + + consumeUntil(...types: Array): boolean { + const { bailOutTypes } = this; + + let token: Token | undefined; + while ((token = this.peak())) { + if (bailOutTypes.indexOf(token.type) !== -1) { + return false; + } + + if (types.indexOf(token.type) !== -1) { + return true; + } + + this.next(); + } + + return false; + } + + consumeIncluding(...types: Array): boolean { + const result = this.consumeUntil(...types); + if (result) { + this.next(); + } + + return result; + } + + ensureSemiColon(lastToken: Token | undefined = undefined) { + const nextToken = this.peak(); + + if (nextToken && nextToken.type === TokenType.SemiColon) { + this.next(); + } else { + this.addDiagnostic( + lastToken, + msgUnexpectedToken({ + actualToken: nextToken, + expectedToken: TokenType.SemiColon + }) + ); + } + } + + injectRange(callback: { + (): WithoutRange | undefined; + }): { (): T | undefined } { + return () => { + const first = this.peak(); + if (!first) { + return undefined; + } + + const startOffset = first.startOffset; + const startPosition = first.startPosition; + const result = callback() as T; + + if (result) { + const last = this.last(); + if (!last) { + return undefined; + } + + result.endOffset = last.endOffset; + result.endPosition = last.endPosition; + result.startOffset = startOffset; + result.startPosition = startPosition; + } + + return result; + }; + } + + isBailOutToken(token: Token): boolean { + return this.bailOutTypes.indexOf(token.type) !== -1; + } + + read( + type: TokenType | Array, + error?: boolean, + hint?: UnexpectedTokenHint + ): Token | undefined { + const token = this.peak(); + if ( + token && + (Array.isArray(type) + ? type.indexOf(token.type) !== -1 + : token.type === type) + ) { + this.next(); + return token; + } + + if (error) { + this.addDiagnostic( + token, + msgUnexpectedToken({ + actualToken: token, + expectedHint: hint, + expectedToken: type + }) + ); + } + + return undefined; + } + + readAction(): ActionNode | undefined { + const token = this.peak(); + if (!token) return undefined; + if (token.type == TokenType.GoalCompletedKeyword) { + const result: GoalCompletedNode = { + endOffset: token.endOffset, + endPosition: token.endPosition, + startOffset: token.startOffset, + startPosition: token.startPosition, + type: NodeType.GoalCompletedAction + }; + + this.next(); + this.ensureSemiColon(token); + return result; + } + + const startOffset = token.startOffset; + const startPosition = token.startPosition; + let isInverted: boolean = false; + + if (token.type === TokenType.NotKeyword) { + this.next(); + isInverted = true; + } + + const signature = this.readSignature(); + if (!signature) { + return undefined; + } + + this.ensureSemiColon(); + return { + endOffset: signature.endOffset, + endPosition: signature.endPosition, + isInverted, + signature, + startOffset, + startPosition, + type: NodeType.SignatureAction + }; + } + + readActionBlock = this.injectRange(() => { + const actions: Array = []; + let token: Token | undefined; + let action; + + while ((token = this.peak())) { + if (this.isBailOutToken(token)) { + break; + } + + action = this.readAction(); + if (action) { + actions.push(action); + } else if (this.consumeUntil(TokenType.SemiColon)) { + this.next(); + } else { + break; + } + } + + return { + actions, + type: NodeType.ActionBlock + }; + }); + + readCondition = this.injectRange(() => { + const isInverted = this.tryReadNotToken(); + const maybeBracket = this.peak(); + const maybeOperator = this.peak(1); + + if ( + (maybeBracket && maybeBracket.type === TokenType.BracketOpen) || + (maybeOperator && maybeOperator.type === TokenType.Operator) + ) { + return this.readOperatorCondition(isInverted); + } else { + return this.readSignatureCondition(isInverted); + } + }); + + readConditionBlock = this.injectRange(() => { + const conditions: Array = []; + let token: Token | undefined; + + while ((token = this.peak())) { + if (this.isBailOutToken(token) || token.type === TokenType.ThenKeyword) { + break; + } else if (token.type === TokenType.AndKeyword) { + this.next(); + const condition = this.readCondition(); + if (condition) { + conditions.push(condition); + } + } else { + this.addDiagnostic( + token, + msgUnexpectedToken({ + actualToken: token, + expectedToken: [TokenType.AndKeyword, TokenType.ThenKeyword] + }) + ); + + if (!this.consumeUntil(TokenType.AndKeyword, TokenType.ThenKeyword)) { + break; + } + } + } + + return { + conditions, + type: NodeType.ConditionBlock + }; + }); + + readFloatLiteral(): NumericLiteralNode | undefined { + const token = this.read(TokenType.FloatLiteral); + return token + ? { + endOffset: token.endOffset, + endPosition: token.endPosition, + startOffset: token.startOffset, + startPosition: token.startPosition, + type: NodeType.RealLiteral, + value: parseFloat(token.value) + } + : undefined; + } + + readGuidLiteral(): GuidLiteralNode | undefined { + const token = this.read(TokenType.GuidLiteral); + if (!token) { + return undefined; + } + + const match = GUID_REGEXP.exec(token.value); + if (!match) { + return undefined; + } + + return { + endOffset: token.endOffset, + endPosition: token.endPosition, + guid: match[2].toLowerCase(), + prefix: match[1], + startOffset: token.startOffset, + startPosition: token.startPosition, + type: NodeType.GuidLiteral + }; + } + + readIdentifier(hint?: UnexpectedTokenHint): IdentifierNode | undefined { + const token = this.read(TokenType.Identifier, true, hint); + if (!token) return undefined; + + let identifierType: IdentifierType = IdentifierType.Default; + if (token.value.startsWith("DB_")) { + identifierType = IdentifierType.Database; + } else if (token.value === "_") { + identifierType = IdentifierType.Empty; + } else if (token.value.startsWith("_")) { + identifierType = IdentifierType.Variable; + } + + return { + endOffset: token.endOffset, + endPosition: token.endPosition, + startOffset: token.startOffset, + startPosition: token.startPosition, + identifierType, + name: token.value, + type: NodeType.Identifier + }; + } + + readIntegerLiteral(): NumericLiteralNode | undefined { + const token = this.read(TokenType.IntegerLiteral); + return token + ? { + endOffset: token.endOffset, + endPosition: token.endPosition, + startOffset: token.startOffset, + startPosition: token.startPosition, + value: parseInt(token.value), + type: NodeType.IntegerLiteral + } + : undefined; + } + + readOperatorCondition( + isInverted: boolean + ): WithoutRange | undefined { + const leftType = this.tryReadTypeAnnoation(); + const leftOperant = this.tryReadArgument(); + if (!leftOperant) return undefined; + + const operatorToken = this.read(TokenType.Operator, true); + if (!operatorToken) return undefined; + const operator = operatorToken.value; + + const rightType = this.tryReadTypeAnnoation(); + const rightOperant = this.tryReadArgument(); + if (!rightOperant) return undefined; + + if (leftOperant && operatorToken && rightOperant) { + return { + isInverted, + leftOperant, + leftType, + operator, + rightOperant, + rightType, + type: NodeType.OperatorCondition + }; + } + + return undefined; + } + + readParameter = this.injectRange(() => { + const flow = this.tryReadParameterFlow(); + const valueType = this.tryReadTypeAnnoation(); + const argument = this.tryReadArgument(); + + if (argument) { + return { + argument, + flow, + type: NodeType.Parameter, + valueType + }; + } + + this.addDiagnostic( + argument, + msgUnexpectedToken({ + actualToken: argument, + expectedHint: "parameter" + }) + ); + return undefined; + }); + + readParameters(thisParameter?: IdentifierNode): Array { + const result: Array = []; + + if (thisParameter) { + result.push({ + endOffset: thisParameter.endOffset, + endPosition: thisParameter.endPosition, + startOffset: thisParameter.startOffset, + startPosition: thisParameter.startPosition, + argument: thisParameter, + type: NodeType.Parameter + }); + } + + if (!this.consume(TokenType.BracketOpen)) { + return result; + } + + let token = this.peak(); + if (!token) { + this.addDiagnostic( + undefined, + msgUnexpectedToken({ + expectedHint: "parameterBlockStart" + }) + ); + return result; + } else if (token.type === TokenType.BracketClose) { + this.next(); + return result; + } + + do { + const parameter = this.readParameter(); + if (parameter) { + result.push(parameter); + } else if (!this.consumeUntil(TokenType.Colon, TokenType.BracketClose)) { + return result; + } + + token = this.peak(); + if (token && token.type === TokenType.Colon) { + this.next(); + } else if (token && token.type === TokenType.BracketClose) { + this.next(); + return result; + } else { + this.addDiagnostic( + token, + msgUnexpectedToken({ + actualToken: token, + expectedHint: "parameterBlock" + }) + ); + if (this.consumeUntil(TokenType.Colon, TokenType.BracketClose)) { + continue; + } else { + return result; + } + } + } while (token && (token = this.peak())); + + return result; + } + + readRule = this.injectRange(() => { + const ruleTypeToken = this.read(ruleTokenTypes); + if (!ruleTypeToken) return undefined; + const comment = ruleTypeToken.comment; + const region = this.region; + const ruleType = ruleTypeToken.value as any; + + const signature = this.readSignature(); + if (!signature) return undefined; + + const conditions = this.readConditionBlock(); + if (!conditions) return undefined; + + this.read(TokenType.ThenKeyword, true); + + const body = this.readActionBlock(); + if (!body) return undefined; + if (body.actions.length === 0) { + this.addDiagnostic(undefined, msgEmptyRuleBody()); + } + + return { + body, + comment, + conditions, + ruleType, + region, + signature, + type: NodeType.Rule + }; + }); + + readRuleBlock = this.injectRange(() => { + const rules: Array = []; + let token: Token | undefined; + + while ((token = this.peak())) { + if (this.isBailOutToken(token)) { + break; + } + + let skip: boolean = false; + if (isRuleToken(token)) { + let rule; + this.withBailOutTypes( + [TokenType.IfKeyword, TokenType.ProcKeyword, TokenType.QueryKeyword], + () => { + rule = this.readRule(); + } + ); + + if (!rule) { + skip = true; + } else { + rules.push(rule); + } + } else { + skip = true; + this.addDiagnostic( + token, + msgUnexpectedToken({ + actualToken: token, + expectedToken: ruleTokenTypes + }) + ); + } + + if (skip && !this.consumeUntil(...ruleTokenTypes)) { + break; + } + } + + return { + rules, + type: NodeType.RuleBlock + }; + }); + + readSignature = this.injectRange(() => { + let thisParamater: IdentifierNode | undefined; + let identifier = this.readIdentifier("signature"); + if (!identifier) { + return undefined; + } + + const dotToken = this.peak(); + if (dotToken && dotToken.type === TokenType.Dot) { + this.next(); + thisParamater = identifier; + + identifier = this.readIdentifier("signature"); + if (!identifier) return undefined; + } + + const parameters = this.readParameters(thisParamater); + + return { + identifier, + parameters, + type: NodeType.Signature + }; + }); + + readSignatureCondition( + isInverted: boolean + ): WithoutRange | undefined { + const signature = this.readSignature(); + if (signature) { + return { + isInverted, + signature, + type: NodeType.SignatureCondition + }; + } + + return undefined; + } + + readStringLiteral(): StringLiteralNode | undefined { + const token = this.read(TokenType.StringLiteral); + return token + ? { + endOffset: token.endOffset, + endPosition: token.endPosition, + startOffset: token.startOffset, + startPosition: token.startPosition, + value: token.value.substr(1, token.value.length - 2), + type: NodeType.StringLiteral + } + : undefined; + } + + readStoryBoundary(): StoryToken | undefined { + let token = this.next(); + if (token && isStoryToken(token)) { + return token; + } + + this.addDiagnostic( + token, + msgUnexpectedToken({ + actualToken: token, + expectedHint: "storyBoundary" + }) + ); + + this.next(); + while ((token = this.next())) { + if (isStoryToken(token)) return token; + } + + return undefined; + } + + tryReadArgument(): ArgumentNode | undefined { + const token = this.peak(); + if (!token) return undefined; + + return token.type === TokenType.Identifier + ? this.readIdentifier() + : this.tryReadConstant(); + } + + tryReadConstant() { + const token = this.peak(); + if (!token) return undefined; + + if (token.type === TokenType.FloatLiteral) { + return this.readFloatLiteral(); + } else if (token.type === TokenType.GuidLiteral) { + return this.readGuidLiteral(); + } else if (token.type === TokenType.IntegerLiteral) { + return this.readIntegerLiteral(); + } else if (token.type === TokenType.StringLiteral) { + return this.readStringLiteral(); + } + } + + tryReadNotToken(): boolean { + const notToken = this.peak(); + if (notToken && notToken.type === TokenType.NotKeyword) { + this.next(); + return true; + } + + return false; + } + + tryReadTypeAnnoation = this.injectRange(() => { + if (!this.read(TokenType.BracketOpen)) { + return undefined; + } + + const identifier = this.read(TokenType.Identifier, true, "typeIdentifier"); + + if (!identifier) { + this.consumeIncluding(TokenType.BracketClose); + return { type: NodeType.TypeAnnotation }; + } + + const annotatedType = identifier.value; + if (!this.read(TokenType.BracketClose, true)) { + this.consumeIncluding(TokenType.BracketClose); + return { type: NodeType.TypeAnnotation }; + } + + return { + annotatedType, + type: NodeType.TypeAnnotation + }; + }); + + tryReadParameterFlow(): ParameterFlow | undefined { + const token = this.peak(); + if (token && token.type === TokenType.Annotation) { + this.next(); + return token.value === "[out]" ? ParameterFlow.Out : ParameterFlow.In; + } + + return undefined; + } + + withBailOutTypes( + token: TokenType | Array, + callback: { (): T } + ): T { + const { bailOutTypes } = this; + const { length } = bailOutTypes; + if (Array.isArray(token)) { + this.bailOutTypes.push(...token); + } else { + this.bailOutTypes.push(token); + } + + const result = callback(); + + this.bailOutTypes.length = length; + return result; + } +} diff --git a/src/server/parsers/story/messages/msgEmptyRuleBody.ts b/src/server/parsers/story/messages/msgEmptyRuleBody.ts new file mode 100644 index 0000000..3e8c6a7 --- /dev/null +++ b/src/server/parsers/story/messages/msgEmptyRuleBody.ts @@ -0,0 +1,14 @@ +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../models/diagnostics"; + +export default function msgEmptyRuleBody(): DiagnosticMessage { + return { + code: DiagnosticCode.EmptyRuleBody, + message: + "Expected at least one action, add `DB_NOOP(1);` if you don't want to perform any actions.", + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/parsers/story/messages/msgInvalidGoalSection.ts b/src/server/parsers/story/messages/msgInvalidGoalSection.ts new file mode 100644 index 0000000..189d5c1 --- /dev/null +++ b/src/server/parsers/story/messages/msgInvalidGoalSection.ts @@ -0,0 +1,19 @@ +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../models/diagnostics"; + +export type Params = { + name: string; +}; + +export default function msgInvalidGoalSection({ + name +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.InvalidGoalSection, + message: `Invalid goal section "${name}".`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/parsers/story/messages/msgInvalidOptionLocation.ts b/src/server/parsers/story/messages/msgInvalidOptionLocation.ts new file mode 100644 index 0000000..94417e4 --- /dev/null +++ b/src/server/parsers/story/messages/msgInvalidOptionLocation.ts @@ -0,0 +1,23 @@ +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../models/diagnostics"; + +export type Params = { + isHeader: boolean; + name: string; +}; + +export default function msgInvalidOptionLocation({ + name, + isHeader +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.InvalidOptionLocation, + message: `Invalid location of option "${name}": The option must be placed in the ${ + isHeader ? "header" : "footer" + } of the file.`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/parsers/story/messages/msgInvalidOptionName.ts b/src/server/parsers/story/messages/msgInvalidOptionName.ts new file mode 100644 index 0000000..9e1a8a0 --- /dev/null +++ b/src/server/parsers/story/messages/msgInvalidOptionName.ts @@ -0,0 +1,19 @@ +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../models/diagnostics"; + +export type Params = { + name: string; +}; + +export default function msgInvalidOptionName({ + name +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.InvalidOptionName, + message: `Invalid option name "${name}".`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/parsers/story/messages/msgInvalidOptionValue.ts b/src/server/parsers/story/messages/msgInvalidOptionValue.ts new file mode 100644 index 0000000..2b81e76 --- /dev/null +++ b/src/server/parsers/story/messages/msgInvalidOptionValue.ts @@ -0,0 +1,23 @@ +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../models/diagnostics"; + +export type Params = { + actualValue: string; + expectedValue: string; + name: string; +}; + +export default function msgInvalidOptionValue({ + actualValue, + expectedValue, + name +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.InvalidOptionValue, + message: `Invalid value "${actualValue}" for option "${name}", expected "${expectedValue}".`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/parsers/story/messages/msgNewLineInString.ts b/src/server/parsers/story/messages/msgNewLineInString.ts new file mode 100644 index 0000000..43c1e8e --- /dev/null +++ b/src/server/parsers/story/messages/msgNewLineInString.ts @@ -0,0 +1,13 @@ +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../models/diagnostics"; + +export default function msgNewLineInString(): DiagnosticMessage { + return { + code: DiagnosticCode.NewLineInString, + message: "String literals cannot contain line breaks.", + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/parsers/story/messages/msgPrematureRealEnd.ts b/src/server/parsers/story/messages/msgPrematureRealEnd.ts new file mode 100644 index 0000000..94eace7 --- /dev/null +++ b/src/server/parsers/story/messages/msgPrematureRealEnd.ts @@ -0,0 +1,13 @@ +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../models/diagnostics"; + +export default function msgPrematureRealEnd(): DiagnosticMessage { + return { + code: DiagnosticCode.PrematureRealEnd, + message: 'Real literals are not allowed to end with ".".', + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/parsers/story/messages/msgUnexpectedToken.ts b/src/server/parsers/story/messages/msgUnexpectedToken.ts new file mode 100644 index 0000000..e690cc7 --- /dev/null +++ b/src/server/parsers/story/messages/msgUnexpectedToken.ts @@ -0,0 +1,51 @@ +import printTokenType from "../utils/printTokenType"; +import { Token, TokenType } from "../Lexer"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../models/diagnostics"; + +const hints = { + definitionMetaData: "definition meta data.", + parameter: "a parameter name or constant", + parameterBlock: "a colon or closing bracket for parameters", + parameterBlockStart: `a parameter name, constant or closing bracket ")"`, + signature: "the name of a siganture", + signatureOrThis: "the name of a siganture or a this value", + storyBoundary: "a story boundary token", + typeIdentifier: " a type identifier" +}; + +export type UnexpectedTokenHint = keyof typeof hints; + +export type Params = { + actualToken?: Token | TokenType; + expectedHint?: UnexpectedTokenHint; + expectedToken?: TokenType | Array; +}; + +export default function msgUnexpectedToken({ + actualToken, + expectedHint, + expectedToken +}: Params): DiagnosticMessage { + let message = "Unexpected token"; + if (actualToken) message += `"${printTokenType(actualToken)}"`; + + if (expectedHint) { + message += `, expected ${hints[expectedHint]}`; + } else if (Array.isArray(expectedToken)) { + const args = expectedToken.map(token => `"${printTokenType(token)}"`); + const orArg = args.length > 1 ? ` or ${args.pop()}` : ""; + message += `, expected ${args.join(",")}${orArg}`; + } else if (expectedToken) { + message += `, expected "${printTokenType(expectedToken)}"`; + } + + return { + code: DiagnosticCode.UnexpectedToken, + message, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/parsers/story/models/diagnostics.ts b/src/server/parsers/story/models/diagnostics.ts new file mode 100644 index 0000000..b0ab686 --- /dev/null +++ b/src/server/parsers/story/models/diagnostics.ts @@ -0,0 +1,136 @@ +import { DiagnosticSeverity, Range } from "vscode-languageserver"; + +export { DiagnosticSeverity }; + +export interface DiagnosticMessage { + code: DiagnosticCode; + message: string; + severity: DiagnosticSeverity; +} + +export enum DiagnosticType { + Analyzer, + Syntax +} + +export interface Diagnostic extends DiagnosticMessage { + range: Range; + type: DiagnosticType; +} + +/** + * Keep in sync with + * https://github.com/Norbyte/lslib/blob/master/LSLib/LS/Story/Compiler/Compiler.cs#L159 + */ +export const enum DiagnosticCode { + // Miscellaenous internal error - should not happen. + InternalError = "E00", + + // A type ID was declared multiple times in the story definition file. + TypeIdAlreadyDefined = "E01", + + // A type name (alias) was declared multiple times in the story definition file. + TypeNameAlreadyDefined = "E02", + + // The type ID is either an intrinsic ID or is outside the allowed range. + TypeIdInvalid = "E03", + + // The alias type ID doesn't point to a valid intrinsic type ID + IntrinsicTypeIdInvalid = "E04", + + // A function with the same signature already exists. + SignatureAlreadyDefined = "E05", + + // The type of an argument could not be resolved in a builtin function. + // (This only occurs when parsing story headers, not in goal code) + UnresolvedTypeInSignature = "E06", + + // A goal with the same name was seen earlier. + GoalAlreadyDefined = "E07", + + // The parent goal specified in the goal script was not found. + UnresolvedGoal = "E08", + + // Failed to infer the type of a rule-local variable. + UnresolvedVariableType = "E09", + + // The function signature (full typed parameter list) of a function + // could not be determined. This is likely the result of a failed type inference. + UnresolvedSignature = "E10", + + // The intrinsic type of a function parameter does not match the expected type. + LocalTypeMismatch = "E11", + + // Constant value with unknown type encountered during IR generation. + UnresolvedType = "E12", + + // PROC/QRY declarations must start with a PROC/QRY name as the first condition. + InvalidProcDefinition = "E13", + + // Fact contains a function that is not callable + // (the function is not a call, database or proc). + InvalidSymbolInFact = "E14", + + // Rule action contains a function that is not callable + // (the function is not a call, database or proc). + InvalidSymbolInStatement = "E15", + + // "NOT" action contains a non-database function. + CanOnlyDeleteFromDatabase = "E16", + + // Initial PROC/QRY/IF function type differs from allowed type. + InvalidSymbolInInitialCondition = "E17", + + // Condition contains a function that is not a query or database. + InvalidFunctionTypeInCondition = "E18", + + // Function name could not be resolved. + UnresolvedSymbol = "E19", + + // Use of less/greater operators on strings or guidstrings. + StringLtGtComparison = "W20", + + // The alias type of a function parameter does not match the expected type. + GuidAliasMismatch = "W21", + + // Object name GUID is prefixed with a type that is not known. + GuidPrefixNotKnown = "W22", + + // PROC_/QRY_ naming style violation. + RuleNamingStyle = "W23", + + // A rule variable was used in a read context, but was not yet bound. + ParamNotBound = "E24", + + // The database is likely unused or unpopulated. + // (Written but not read, or vice versa) + UnusedDatabase = "W25", + + // Database "DB_" naming convention violation. + DbNamingStyle = "W26", + + // Object name GUID could not be resolved to a game object. + UnresolvedGameObjectName = "W27", + + // Type of name GUID differs from type of game object. + GameObjectTypeMismatch = "W28", + + // Name part of name GUID differs from name of game object. + GameObjectNameMismatch = "W29", + + // Multiple definitions seen for the same function with different signatures. + ProcTypeMismatch = "E30", + + // Custom + // --------------------------------- + PrematureRealEnd = "E1001", + NewLineInString = "E1002", + UnexpectedToken = "E1003", + EmptyRuleBody = "E1004", + InvalidOptionName = "E1005", + InvalidOptionValue = "E1006", + InvalidOptionLocation = "E1007", + InvalidGoalSection = "E1008", + InvalidVariableName = "E1009", + VariableNotAllowed = "E1010" +} diff --git a/src/server/parsers/story/models/nodes.ts b/src/server/parsers/story/models/nodes.ts new file mode 100644 index 0000000..023c4c2 --- /dev/null +++ b/src/server/parsers/story/models/nodes.ts @@ -0,0 +1,187 @@ +import Symbol from "../../../projects/story/Symbol"; +import { ArgumentNode } from "../utils/isArgumentNode"; +import { ActionNode } from "../utils/isActionNode"; +import { ConditionNode } from "../utils/isConditionNode"; +import { TokenRange } from "../Lexer"; + +export const enum NodeType { + ActionBlock, + ConditionBlock, + Definition, + Div, + DivGoal, + GoalCompletedAction, + GuidLiteral, + Identifier, + IntegerLiteral, + OperatorCondition, + Parameter, + RealLiteral, + Rule, + RuleBlock, + Signature, + SignatureAction, + SignatureCondition, + StoryGoal, + StringLiteral, + TypeAnnotation +} + +export const enum ParameterFlow { + In = 1, + Out = 2 +} + +export const enum IdentifierType { + Default, + Database, + Empty, + Variable +} + +export type AnyNode = + | ActionBlockNode + | ConditionBlockNode + | DefinitionNode + | HeaderNode + | HeaderGoalNode + | GoalCompletedNode + | GuidLiteralNode + | IdentifierNode + | NumericLiteralNode + | OperatorNode + | ParameterNode + | RuleBlockNode + | RuleNode + | SignatureCallNode + | SignatureNode + | StoryGoalNode + | StringLiteralNode + | TypeAnnotationNode; + +export interface AbstractNode extends TokenRange { + type: NodeType; +} + +export interface AbstractGoalNode extends AbstractNode { + exit?: ActionBlockNode; + init?: ActionBlockNode; + kb?: RuleBlockNode; +} + +export interface ActionBlockNode extends AbstractNode { + actions: Array; + type: NodeType.ActionBlock; +} + +export interface ConditionBlockNode extends AbstractNode { + conditions: Array; + type: NodeType.ConditionBlock; +} + +export interface HeaderNode extends AbstractNode { + definitions: Array; + goals: Array; + type: NodeType.Div; + typeAliases: Array; +} + +export interface HeaderGoalNode extends AbstractNode { + exit?: string; + id: number; + init?: string; + kb?: string; + subGoal: Array; + title?: string; + type: NodeType.DivGoal; +} + +export interface DefinitionNode extends AbstractNode { + definitionType: string; + signature: SignatureNode; + type: NodeType.Definition; +} + +export interface GoalCompletedNode extends AbstractNode { + type: NodeType.GoalCompletedAction; +} + +export interface GuidLiteralNode extends AbstractNode { + guid: string; + prefix: string; + type: NodeType.GuidLiteral; +} + +export interface IdentifierNode extends AbstractNode { + identifierType: IdentifierType; + name: string; + type: NodeType.Identifier; +} + +export interface NumericLiteralNode extends AbstractNode { + type: NodeType.IntegerLiteral | NodeType.RealLiteral; + value: number; +} + +export interface OperatorNode extends AbstractNode { + isInverted: boolean; + leftOperant: ArgumentNode; + leftType: TypeAnnotationNode | undefined; + operator: string; + rightOperant: ArgumentNode; + rightType: TypeAnnotationNode | undefined; + type: NodeType.OperatorCondition; +} + +export interface ParameterNode extends AbstractNode { + argument: ArgumentNode; + flow?: ParameterFlow; + type: NodeType.Parameter; + valueType?: TypeAnnotationNode; +} + +export interface RuleNode extends AbstractNode { + body?: ActionBlockNode; + comment: string | null; + conditions?: ConditionBlockNode; + region: string | null; + ruleType: "IF" | "PROC" | "QRY"; + signature: SignatureNode; + symbol?: Symbol; + type: NodeType.Rule; +} + +export interface RuleBlockNode extends AbstractNode { + rules: Array; + type: NodeType.RuleBlock; +} + +export interface SignatureCallNode extends AbstractNode { + isInverted: boolean; + signature: SignatureNode; + symbol?: Symbol; + type: NodeType.SignatureAction | NodeType.SignatureCondition; +} + +export interface SignatureNode extends AbstractNode { + identifier: IdentifierNode; + parameters: Array; + type: NodeType.Signature; +} + +export interface StoryGoalNode extends AbstractGoalNode { + parentTargetEdges?: Array; + subGoalCombiner?: string; + type: NodeType.StoryGoal; + version?: number; +} + +export interface StringLiteralNode extends AbstractNode { + type: NodeType.StringLiteral; + value: string; +} + +export interface TypeAnnotationNode extends AbstractNode { + annotatedType?: string; + type: NodeType.TypeAnnotation; +} diff --git a/src/server/parsers/story/utils/copyTokenRange.ts b/src/server/parsers/story/utils/copyTokenRange.ts new file mode 100644 index 0000000..00ba2d6 --- /dev/null +++ b/src/server/parsers/story/utils/copyTokenRange.ts @@ -0,0 +1,10 @@ +import { TokenRange } from "../Lexer"; + +export default function copyRange(range: TokenRange): TokenRange { + return { + endOffset: range.endOffset, + endPosition: range.endPosition, + startOffset: range.startOffset, + startPosition: range.startPosition + }; +} diff --git a/src/server/parsers/story/utils/eachCaller.ts b/src/server/parsers/story/utils/eachCaller.ts new file mode 100644 index 0000000..b015cc2 --- /dev/null +++ b/src/server/parsers/story/utils/eachCaller.ts @@ -0,0 +1,56 @@ +import eachNodeRecursive from "./eachNodeRecursive"; +import isCallerNode, { CallerNode } from "./isCallerNode"; +import { AnyNode, NodeType, RuleNode } from "../models/nodes"; +import { Variable } from "../../../projects/story/models/symbol"; + +export interface EachCaller { + node: CallerNode; + stack: Array; + type: EachCallerType; + variables?: Array; +} + +export const enum EachCallerType { + Condition, + Definition, + Event, + Fact +} + +export default function* eachCaller( + parent: AnyNode | null +): Iterable { + if (!parent) { + return; + } + + let rule: RuleNode | undefined; + let variables: Array | undefined; + + for (const { node, stack } of eachNodeRecursive(parent)) { + if (!isCallerNode(node)) continue; + + const depth = stack.length; + let type: EachCallerType; + if (node.type === NodeType.Rule) { + rule = node; + variables = []; + if (node.ruleType === "IF") { + type = EachCallerType.Event; + } else { + type = EachCallerType.Definition; + } + } else if (depth < 2 || stack[depth - 2] !== rule) { + rule = undefined; + variables = undefined; + type = EachCallerType.Fact; + } else { + type = + stack[depth - 1].type === NodeType.ConditionBlock + ? EachCallerType.Condition + : EachCallerType.Fact; + } + + yield { node, stack, type, variables }; + } +} diff --git a/src/server/parsers/story/utils/eachNode.ts b/src/server/parsers/story/utils/eachNode.ts new file mode 100644 index 0000000..a25e925 --- /dev/null +++ b/src/server/parsers/story/utils/eachNode.ts @@ -0,0 +1,72 @@ +import { AnyNode, NodeType } from "../models/nodes"; + +export default function* eachNode(parent?: AnyNode): Iterable { + if (!parent) { + return; + } + + switch (parent.type) { + case NodeType.ActionBlock: + for (let index = 0; index < parent.actions.length; index++) { + yield parent.actions[index]; + } + break; + + case NodeType.ConditionBlock: + for (let index = 0; index < parent.conditions.length; index++) { + yield parent.conditions[index]; + } + break; + + case NodeType.OperatorCondition: + yield parent.leftOperant; + yield parent.rightOperant; + break; + + case NodeType.Div: + for (let index = 0; index < parent.definitions.length; index++) { + yield parent.definitions[index]; + } + for (let index = 0; index < parent.goals.length; index++) { + yield parent.goals[index]; + } + break; + + case NodeType.StoryGoal: + if (parent.init) yield parent.init; + if (parent.kb) yield parent.kb; + if (parent.exit) yield parent.exit; + break; + + case NodeType.SignatureAction: + case NodeType.SignatureCondition: { + yield parent.signature; + break; + } + + case NodeType.Parameter: + if (parent.valueType) yield parent.valueType; + if (parent.argument) yield parent.argument; + break; + + case NodeType.Rule: { + yield parent.signature; + if (parent.conditions) yield parent.conditions; + if (parent.body) yield parent.body; + break; + } + + case NodeType.RuleBlock: + for (let index = 0; index < parent.rules.length; index++) { + yield parent.rules[index]; + } + break; + + case NodeType.Signature: + yield parent.identifier; + for (let index = 0; index < parent.parameters.length; index++) { + yield parent.parameters[index]; + } + break; + } +} diff --git a/src/server/parsers/story/utils/eachNodeRecursive.ts b/src/server/parsers/story/utils/eachNodeRecursive.ts new file mode 100644 index 0000000..d9711eb --- /dev/null +++ b/src/server/parsers/story/utils/eachNodeRecursive.ts @@ -0,0 +1,17 @@ +import eachNode from "./eachNode"; +import { AnyNode } from "../models/nodes"; + +export interface NodeWithStack { + node: AnyNode; + stack: Array; +} + +export default function* eachNodeRecursive( + parent?: AnyNode, + stack: Array = [] +): Iterable { + for (const node of eachNode(parent)) { + yield { node, stack }; + yield* eachNodeRecursive(node, [...stack, node]); + } +} diff --git a/src/server/parsers/story/utils/eachRuleNode.ts b/src/server/parsers/story/utils/eachRuleNode.ts new file mode 100644 index 0000000..ff57076 --- /dev/null +++ b/src/server/parsers/story/utils/eachRuleNode.ts @@ -0,0 +1,84 @@ +import { ActionNode } from "./isActionNode"; +import { ConditionNode } from "./isConditionNode"; +import { RuleNode, NodeType, AnyNode } from "../models/nodes"; +import { Variable } from "../../../projects/story/models/symbol"; +import { EachCallerType } from "./eachCaller"; + +export interface Scope { + origin: RuleNode; + variablesBefore: Array; + variables: Array; +} + +export interface EachRuleNode extends Scope { + node: ActionNode | ConditionNode | RuleNode; + type: EachCallerType; +} + +function getRuleCallerType(rule: RuleNode) { + return rule.ruleType === "IF" + ? EachCallerType.Event + : EachCallerType.Definition; +} + +export function isInScope(scope: Scope, stack: Array): boolean { + return stack.indexOf(scope.origin) !== -1; +} + +export function startScope(origin: RuleNode): Scope { + const variables: Array = []; + if (origin.symbol) { + origin.symbol.applyTo(origin, getRuleCallerType(origin), variables); + } + + return { + origin, + variablesBefore: [], + variables + }; +} + +export function tryStartScope(node: AnyNode): Scope | null { + return node.type === NodeType.Rule ? startScope(node) : null; +} + +export function updateScope(scope: Scope, node: AnyNode): Scope { + if (node.type === NodeType.SignatureCondition && node.symbol) { + scope.variablesBefore = [...scope.variables]; + node.symbol.applyTo(node, EachCallerType.Condition, scope.variables); + } else { + scope.variablesBefore = scope.variables; + } + + return scope; +} + +export default function* eachRuleNode(rule: RuleNode): Iterable { + let scope = startScope(rule); + yield { + ...scope, + node: rule, + type: getRuleCallerType(rule) + }; + + if (rule.conditions) { + for (const node of rule.conditions.conditions) { + updateScope(scope, node); + yield { + ...scope, + node, + type: EachCallerType.Condition + }; + } + } + + if (rule.body) { + for (const node of rule.body.actions) { + yield { + ...scope, + node, + type: EachCallerType.Fact + }; + } + } +} diff --git a/src/server/parsers/story/utils/isActionNode.ts b/src/server/parsers/story/utils/isActionNode.ts new file mode 100644 index 0000000..415d9e8 --- /dev/null +++ b/src/server/parsers/story/utils/isActionNode.ts @@ -0,0 +1,16 @@ +import { + AnyNode, + GoalCompletedNode, + NodeType, + SignatureCallNode +} from "../models/nodes"; + +export type ActionNode = GoalCompletedNode | SignatureCallNode; + +export default function isActionNode(node?: AnyNode): node is ActionNode { + return ( + !!node && + (node.type === NodeType.GoalCompletedAction || + node.type === NodeType.SignatureAction) + ); +} diff --git a/src/server/parsers/story/utils/isArgumentNode.ts b/src/server/parsers/story/utils/isArgumentNode.ts new file mode 100644 index 0000000..e0d2a28 --- /dev/null +++ b/src/server/parsers/story/utils/isArgumentNode.ts @@ -0,0 +1,24 @@ +import { + AnyNode, + GuidLiteralNode, + NumericLiteralNode, + StringLiteralNode, + IdentifierNode, + NodeType +} from "../models/nodes"; + +export type ArgumentNode = + | GuidLiteralNode + | IdentifierNode + | NumericLiteralNode + | StringLiteralNode; + +export default function isArgumentNode(node: AnyNode): node is ArgumentNode { + return ( + node.type === NodeType.GuidLiteral || + node.type === NodeType.Identifier || + node.type === NodeType.RealLiteral || + node.type === NodeType.IntegerLiteral || + node.type === NodeType.StringLiteral + ); +} diff --git a/src/server/parsers/story/utils/isCallerNode.ts b/src/server/parsers/story/utils/isCallerNode.ts new file mode 100644 index 0000000..0fd4ec0 --- /dev/null +++ b/src/server/parsers/story/utils/isCallerNode.ts @@ -0,0 +1,17 @@ +import { + RuleNode, + SignatureCallNode, + AnyNode, + NodeType +} from "../models/nodes"; + +export type CallerNode = RuleNode | SignatureCallNode; + +export default function isCallerNode(node?: AnyNode): node is CallerNode { + return ( + !!node && + (node.type === NodeType.Rule || + node.type === NodeType.SignatureAction || + node.type === NodeType.SignatureCondition) + ); +} diff --git a/src/server/parsers/story/utils/isConditionNode.ts b/src/server/parsers/story/utils/isConditionNode.ts new file mode 100644 index 0000000..3b70cde --- /dev/null +++ b/src/server/parsers/story/utils/isConditionNode.ts @@ -0,0 +1,16 @@ +import { + AnyNode, + NodeType, + OperatorNode, + SignatureCallNode +} from "../models/nodes"; + +export type ConditionNode = OperatorNode | SignatureCallNode; + +export default function isConditionNode(node?: AnyNode): node is ConditionNode { + return ( + !!node && + (node.type === NodeType.OperatorCondition || + node.type === NodeType.SignatureCondition) + ); +} diff --git a/src/server/parsers/story/utils/isRuleToken.ts b/src/server/parsers/story/utils/isRuleToken.ts new file mode 100644 index 0000000..4c76df5 --- /dev/null +++ b/src/server/parsers/story/utils/isRuleToken.ts @@ -0,0 +1,19 @@ +import { Token, TokenType } from "../Lexer"; + +export interface RuleToken extends Token { + type: TokenType.IfKeyword | TokenType.ProcKeyword | TokenType.QueryKeyword; +} + +export const ruleTokenTypes = [ + TokenType.IfKeyword, + TokenType.ProcKeyword, + TokenType.QueryKeyword +]; + +export default function isRuleToken(token: Token): token is RuleToken { + return ( + token.type === TokenType.IfKeyword || + token.type === TokenType.ProcKeyword || + token.type === TokenType.QueryKeyword + ); +} diff --git a/src/server/parsers/story/utils/isStoryToken.ts b/src/server/parsers/story/utils/isStoryToken.ts new file mode 100644 index 0000000..4789205 --- /dev/null +++ b/src/server/parsers/story/utils/isStoryToken.ts @@ -0,0 +1,25 @@ +import { Token, TokenType } from "../Lexer"; + +export const storyTokenTypes = [ + TokenType.InitSectionKeyword, + TokenType.KBSectionKeyword, + TokenType.ExitSectionKeyword, + TokenType.EndExitSectionKeyword +]; + +export interface StoryToken extends Token { + type: + | TokenType.InitSectionKeyword + | TokenType.KBSectionKeyword + | TokenType.ExitSectionKeyword + | TokenType.EndExitSectionKeyword; +} + +export default function isStoryToken(token: Token): token is StoryToken { + return ( + token.type === TokenType.InitSectionKeyword || + token.type === TokenType.KBSectionKeyword || + token.type === TokenType.ExitSectionKeyword || + token.type === TokenType.EndExitSectionKeyword + ); +} diff --git a/src/server/parsers/story/utils/packPosition.ts b/src/server/parsers/story/utils/packPosition.ts new file mode 100644 index 0000000..4f93a1e --- /dev/null +++ b/src/server/parsers/story/utils/packPosition.ts @@ -0,0 +1,8 @@ +import { PackedPosition } from "../Lexer"; + +export default function packPosition( + line: number, + character: number +): PackedPosition { + return (character & 0x3fffff) * 0x40000000 + (line & 0x3fffffff); +} diff --git a/src/server/parsers/story/utils/printNode.ts b/src/server/parsers/story/utils/printNode.ts new file mode 100644 index 0000000..1e16d04 --- /dev/null +++ b/src/server/parsers/story/utils/printNode.ts @@ -0,0 +1,59 @@ +import { AnyNode, NodeType, ParameterFlow } from "../models/nodes"; + +export default function printNode(node?: AnyNode | null): string { + if (!node) { + return ""; + } + + switch (node.type) { + case NodeType.SignatureAction: + case NodeType.SignatureCondition: + return printNode(node.signature); + + case NodeType.Parameter: + return [ + node.flow ? `[${node.flow === ParameterFlow.Out ? "out" : "in"}]` : "", + printNode(node.valueType), + printNode(node.argument) + ].join(""); + + case NodeType.Rule: + return `${node.ruleType} ${printNode(node.signature)}`; + + case NodeType.Signature: { + const name = printNode(node.identifier); + const parameters = node.parameters + .map(parameter => printNode(parameter)) + .join(", "); + + return `${name}(${parameters})`; + } + + case NodeType.TypeAnnotation: + return `(${node.annotatedType})`; + + case NodeType.RealLiteral: + case NodeType.IntegerLiteral: + return node.value.toString(); + + case NodeType.GuidLiteral: + return node.guid; + + case NodeType.StringLiteral: + return node.value; + + case NodeType.Identifier: + return node.name; + + case NodeType.GoalCompletedAction: + case NodeType.OperatorCondition: + case NodeType.ActionBlock: + case NodeType.ConditionBlock: + case NodeType.RuleBlock: + case NodeType.Div: + case NodeType.DivGoal: + case NodeType.StoryGoal: + case NodeType.Definition: + return ""; + } +} diff --git a/src/server/parsers/story/utils/printToken.ts b/src/server/parsers/story/utils/printToken.ts new file mode 100644 index 0000000..ebd99b6 --- /dev/null +++ b/src/server/parsers/story/utils/printToken.ts @@ -0,0 +1,22 @@ +import { Token, TokenType } from "../Lexer"; + +export default function printToken(token?: Token | undefined): string { + if (!token) { + return ""; + } + + switch (token.type) { + case TokenType.IfKeyword: + return "IF"; + case TokenType.ProcKeyword: + return "PROC"; + case TokenType.QueryKeyword: + return "QRY"; + case TokenType.StringLiteral: + return `"${token.value}"`; + case TokenType.Identifier: + return token.value; + default: + return ""; + } +} diff --git a/src/server/parsers/story/utils/printTokenType.ts b/src/server/parsers/story/utils/printTokenType.ts new file mode 100644 index 0000000..e3ea8b6 --- /dev/null +++ b/src/server/parsers/story/utils/printTokenType.ts @@ -0,0 +1,80 @@ +import { TokenType, Token } from "../Lexer"; + +export default function printTokenType( + type: Token | TokenType | undefined +): string { + if (!type) { + return ""; + } + + if (typeof type === "object") { + type = type.type; + } + + switch (type) { + case TokenType.Empty: + return ""; + case TokenType.EndOfFile: + return ""; + case TokenType.Invalid: + return ""; + + // Common token types + case TokenType.Annotation: + return "annotion, e.g. '[in]'"; + case TokenType.BlockComment: + return "block comment"; + case TokenType.BracketOpen: + return "opening bracket `(`"; + case TokenType.BracketClose: + return "closing bracket `)`"; + case TokenType.Colon: + return "colon `,`"; + case TokenType.CurlyBracketOpen: + return "opening curly bracket `{`"; + case TokenType.CurlyBracketClose: + return "closing curly bracket `}`"; + case TokenType.Dot: + return "dot `.`"; + case TokenType.GuidLiteral: + return "guid literal"; + case TokenType.FloatLiteral: + return "float literal"; + case TokenType.Identifier: + return "identifier"; + case TokenType.IntegerLiteral: + return "integer literal"; + case TokenType.LineComment: + return "line comment"; + case TokenType.Operator: + return "operator `==`, `!=`, `<=`, `>=`, `>` or `<`"; + case TokenType.SemiColon: + return "semicolon `;`"; + case TokenType.StringLiteral: + return "string literal"; + + // Keyword tokens + case TokenType.AndKeyword: + return "AND"; + case TokenType.EndExitSectionKeyword: + return "ENDEXITSECTION"; + case TokenType.ExitSectionKeyword: + return "EXITSECTION"; + case TokenType.GoalCompletedKeyword: + return "GoalCompleted"; + case TokenType.IfKeyword: + return "IF"; + case TokenType.InitSectionKeyword: + return "INITSECTION"; + case TokenType.KBSectionKeyword: + return "KBSECTION"; + case TokenType.NotKeyword: + return "NOT"; + case TokenType.ProcKeyword: + return "PROC"; + case TokenType.ThenKeyword: + return "THEN"; + case TokenType.QueryKeyword: + return "QRY"; + } +} diff --git a/src/server/parsers/story/utils/unpackPosition.ts b/src/server/parsers/story/utils/unpackPosition.ts new file mode 100644 index 0000000..dfe6896 --- /dev/null +++ b/src/server/parsers/story/utils/unpackPosition.ts @@ -0,0 +1,9 @@ +import { Position } from "vscode-languageserver"; + +import { PackedPosition } from "../Lexer"; + +export default function unpackPosition(value: PackedPosition): Position { + var line = value & 0x3fffffff; + var character = (value - line) / 0x40000000; + return { line, character }; +} diff --git a/src/server/parsers/story/utils/unpackRange.ts b/src/server/parsers/story/utils/unpackRange.ts new file mode 100644 index 0000000..875b8da --- /dev/null +++ b/src/server/parsers/story/utils/unpackRange.ts @@ -0,0 +1,11 @@ +import { Range } from "vscode-languageserver"; + +import unpackPosition from "./unpackPosition"; +import { TokenRange } from "../Lexer"; + +export default function unpackRange(range: TokenRange): Range { + return { + end: unpackPosition(range.endPosition), + start: unpackPosition(range.startPosition) + }; +} diff --git a/src/server/projects/FileWatcher.ts b/src/server/projects/FileWatcher.ts new file mode 100644 index 0000000..661764e --- /dev/null +++ b/src/server/projects/FileWatcher.ts @@ -0,0 +1,171 @@ +import { EventEmitter } from "events"; +import { FSWatcher, watch, existsSync, readdirSync, statSync } from "fs"; +import { join, normalize } from "path"; +import { readDir, stat } from "../../shared/fs"; + +interface PendingEvent { + created: number; + event: string; + path: string; +} + +export interface FileWatcherOptions { + pattern: RegExp; + path: string; + recursive?: boolean; +} + +export default class FileWatcher extends EventEmitter { + readonly path: string; + readonly pattern: RegExp; + readonly recursive: boolean; + + private interval: NodeJS.Timer | null = null; + private pending: Array = []; + private watcher: FSWatcher | null = null; + + constructor(options: FileWatcherOptions) { + super(); + + this.path = options.path; + this.pattern = options.pattern; + this.recursive = !!options.recursive; + } + + dispose() { + if (this.watcher) { + this.watcher.close(); + this.watcher = null; + } + } + + async scan(path: string = this.path) { + this.validate(); + + const { pattern, recursive } = this; + const files = await readDir(path); + + for (const file of files) { + const filePath = normalize(join(path, file)); + const stats = await stat(filePath); + + if (stats.isDirectory()) { + if (recursive) { + await this.scan(filePath); + } + } else if (pattern.test(filePath)) { + this.emit("update", filePath); + } + } + } + + scanSync(path: string = this.path) { + this.validate(); + + const { pattern, recursive } = this; + const files = readdirSync(path); + + for (const file of files) { + const filePath = normalize(join(path, file)); + const stats = statSync(filePath); + + if (stats.isDirectory()) { + if (recursive) { + this.scanSync(filePath); + } + } else if (pattern.test(filePath)) { + this.emit("update", filePath); + } + } + } + + async scanAndStart() { + await this.scan(); + this.start(); + } + + scanAndStartSync() { + this.scanSync(); + this.start(); + } + + start() { + if (this.watcher) return; + this.validate(); + + const { path, recursive } = this; + const watcher = watch(path, { recursive }); + + watcher.on("change", (type, file) => + this.handleFileEvent(type, file as string) + ); + + this.watcher = watcher; + } + + validate() { + if (!existsSync(this.path)) { + throw new Error(`The path ${this.path} does not exist.`); + } + } + + private handleFileEvent(type: string, file: string) { + const { pending } = this; + const path = normalize(join(this.path, file)); + if (!this.pattern.test(path)) { + return; + } + + let event; + if (type === "rename") { + event = existsSync(path) ? "update" : "remove"; + } else { + event = "update"; + } + + let index = 0; + while (index < pending.length) { + if (pending[index].path === path) { + pending.splice(index, 1); + } else { + index++; + } + } + + pending.push({ + created: Date.now(), + event, + path + }); + + this.pending = pending; + this.startInterval(); + } + + private startInterval() { + if (this.interval) return; + + const interval = setInterval(() => { + const { pending } = this; + const now = Date.now(); + let index = 0; + + while (index < pending.length) { + const item = pending[index]; + if (now - item.created > 100) { + pending.splice(index, 1); + this.emit(item.event, item.path); + } else { + index++; + } + } + + if (pending.length === 0) { + clearInterval(interval); + this.interval = null; + } + }, 50); + + this.interval = interval; + } +} diff --git a/src/server/projects/Project.ts b/src/server/projects/Project.ts new file mode 100644 index 0000000..a60945e --- /dev/null +++ b/src/server/projects/Project.ts @@ -0,0 +1,36 @@ +import Levels from "./levels/index"; +import Projects from "."; +import Story from "./story"; +import { ProjectInfo, ProjectMetaInfo } from "../../shared/notifications"; + +export default class Project implements ProjectInfo { + readonly levels: Levels; + readonly meta: ProjectMetaInfo; + readonly path: string; + readonly projects: Projects; + readonly story: Story; + + constructor(projects: Projects, info: ProjectInfo) { + this.levels = new Levels(this); + this.meta = info.meta; + this.path = info.path; + this.projects = projects; + this.story = new Story(this); + } + + dispose() { + this.story.dispose(); + this.levels.dispose(); + } + + getInfo(): ProjectInfo { + return { + meta: this.meta, + path: this.path + }; + } + + initialize() { + this.story.initialize(); + } +} diff --git a/src/server/projects/index.ts b/src/server/projects/index.ts new file mode 100644 index 0000000..e2c4fd6 --- /dev/null +++ b/src/server/projects/index.ts @@ -0,0 +1,120 @@ +import { EventEmitter } from "events"; +import { normalize, join, resolve } from "path"; + +import Documentation from "../documentation/Documentation"; +import parseUri, { ParsedUri } from "../utils/parseUri"; +import Project from "./Project"; +import readProjectMetaInfo from "../utils/readProjectMetaInfo"; +import readXmlFile from "../utils/readXmlFile"; +import Resource from "./story/resources/Resource"; +import { ProjectInfo } from "../../shared/notifications"; + +/** + * @event "diagnostics" (goal: AbstractGoal) + * @event "goalsChanged" (project: Project) + * @event "levelInitStart" (project: Project) + * @event "levelInitReady" (project: Project) + * @event "projectAdded" (project: Project) + * @event "projectReady" (project: Project) + * @event "showError" (string: message) + */ +export default class Projects extends EventEmitter { + readonly docProvider: Documentation = new Documentation(); + readonly projects: Array = []; + + dispose() { + const { projects } = this; + projects.forEach(project => project.dispose()); + projects.length = 0; + } + + findProjectByPath(path: string): Project | null { + path = normalize(path); + return this.projects.find(project => project.path === path) || null; + } + + findProjectByUid(uid: string) { + return this.projects.find(project => project.meta.UUID === uid) || null; + } + + async findResource(uri: string | ParsedUri | null): Promise { + if (typeof uri === "string") { + uri = parseUri(uri); + } + + if (!uri) { + return null; + } + + if (uri.type === "path") { + return this.findResourceByPath(uri.path); + } + + const project = this.findProjectByUid(uri.project); + if (!project) { + return null; + } + + const goal = project.story.findGoal(uri.goal); + return goal ? goal.resource : null; + } + + async findResourceByPath(path: string | null): Promise { + if (!path) { + return null; + } + + for (const project of this.projects) { + const file = project.story.findOrCreateResource(path); + if (file) { + return file; + } + } + + const project = await this.tryCreateForFolder(path); + if (project) { + return project.story.findResource(path); + } + + return null; + } + + async tryGetProjectInfo(path: string): Promise { + path = normalize(path); + try { + const data = await readXmlFile(join(path, "meta.lsx")); + return { + meta: readProjectMetaInfo(data), + path + }; + } catch (e) {} + + return null; + } + + async tryCreateForFolder(initialPath: string): Promise { + let path = resolve(initialPath); + let nextPath = path; + + do { + path = nextPath; + nextPath = resolve(path, ".."); + + const info = await this.tryGetProjectInfo(path); + if (info) { + let project = this.findProjectByPath(info.path); + if (!project) { + project = new Project(this, info); + this.projects.push(project); + this.emit("projectAdded", project); + + project.initialize(); + } + + return project; + } + } while (path !== nextPath); + + return null; + } +} diff --git a/src/server/projects/levels/index.ts b/src/server/projects/levels/index.ts new file mode 100644 index 0000000..c910076 --- /dev/null +++ b/src/server/projects/levels/index.ts @@ -0,0 +1,166 @@ +import LSFParser from "../../parsers/lsf/Parser"; +import Project from "../Project"; +import FileWatcher from "../../projects/FileWatcher"; +import { readFile } from "../../../shared/fs"; + +const allowedTypes = ["character", "item", "leveltemplate", "trigger"]; + +export type InstanceType = "character" | "item" | "leveltemplate" | "trigger"; + +export interface FileInfo { + path: string; + guid: string; + level: string; +} + +export interface InstanceInfo extends FileInfo { + name: string; + type: InstanceType; +} + +export const enum LevelsInitState { + Idle, + Scanning, + Loading, + Ready +} + +export default class Levels { + readonly project: Project; + initState: LevelsInitState = LevelsInitState.Idle; + instances: Array = []; + isProcessing: boolean = false; + lsfReader: LSFParser = new LSFParser(); + pending: Array = []; + watcher: FileWatcher | null = null; + + constructor(project: Project) { + this.project = project; + } + + dispose() { + if (this.watcher) { + this.watcher.dispose(); + this.watcher = null; + } + } + + getFileInfo(path: string): FileInfo | null { + const match = /([^\\\/]+)[\\\/][^\\\/]+[\\\/]([0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12})\.lsf$/.exec( + path + ); + + return match + ? { + path, + guid: match[2], + level: match[1] + } + : null; + } + + initialize() { + try { + const watcher = new FileWatcher({ + path: this.project.path, + pattern: /(Globals|Levels)[\\\/]([^\\\/]+)[\\\/](Characters|Items|LevelTemplates|Splines|Triggers)[\\\/](.*?).lsf$/, + recursive: true + }); + + this.initState = LevelsInitState.Scanning; + + watcher.on("update", this.handleFileUpdate); + watcher.on("remove", this.handleFileRemove); + watcher.scanAndStart().then(() => { + if (!this.isProcessing) { + this.initState = LevelsInitState.Ready; + this.project.projects.emit("levelInitReady", this.project); + } else { + this.initState = LevelsInitState.Loading; + } + }); + + this.project.projects.emit("levelInitStart", this.project); + this.watcher = watcher; + } catch (error) { + this.initState = LevelsInitState.Ready; + this.project.projects.emit("showError", error.message); + } + } + + async process() { + if (this.isProcessing) return; + this.isProcessing = true; + + const { instances, pending } = this; + let info: FileInfo | undefined; + + while ((info = pending.shift())) { + let instance: InstanceInfo | null | undefined; + try { + instance = await this.read(info); + } catch (e) {} + + if (instance) { + const guid = instance.guid; + const index = instances.findIndex(inst => inst.guid === guid); + + if (index === -1) { + instances.push(instance); + } else { + instances[index] = instance; + } + } + } + + this.isProcessing = false; + if (this.initState === LevelsInitState.Loading) { + this.initState = LevelsInitState.Ready; + this.project.projects.emit("levelInitReady", this.project); + } + } + + async read(info: FileInfo): Promise { + const buffer = await readFile(info.path); + const resource = this.lsfReader.read(buffer); + const node = resource.findNode("Templates", "GameObjects"); + let result: InstanceInfo | null = null; + + if (node) { + const name = node.getStringAttribute("Name"); + const type = node.getStringAttribute("Type"); + + if (name && !name.startsWith("S_")) { + return null; + } + + if (name && type && allowedTypes.indexOf(type) !== -1) { + result = { + ...info, + guid: info.guid.toLowerCase(), + name, + type: type as InstanceType + }; + } + } + + return result; + } + + handleFileUpdate = (path: string) => { + const info = this.getFileInfo(path); + if (info) { + this.pending.push(info); + this.process(); + } + }; + + handleFileRemove = (path: string) => { + const info = this.getFileInfo(path); + if (info) { + const { guid } = info; + this.instances = this.instances.filter(info => info.guid !== guid); + this.pending = this.pending.filter(info => info.guid !== guid); + } + }; +} diff --git a/src/server/projects/story/Goal.ts b/src/server/projects/story/Goal.ts new file mode 100644 index 0000000..c2c0037 --- /dev/null +++ b/src/server/projects/story/Goal.ts @@ -0,0 +1,66 @@ +import HeaderGoalResource from "./resources/HeaderGoalResource"; +import Resource from "./resources/Resource"; +import sortGoals from "./utils/sortGoals"; +import Story from "."; + +export default class Goal { + parents: Array = []; + weight: number = 0; + readonly name: string; + readonly resource: Resource; + readonly story: Story; + + constructor(story: Story, name: string, resource: Resource) { + this.resource = resource; + this.name = name; + this.story = story; + } + + getChildren(): Array { + return this.story.getGoalsByParent(this.name); + } + + getSortedChildren(): Array { + return this.story.getGoalsByParent(this.name).sort(sortGoals); + } + + isHeaderGoal(): boolean { + return this.resource instanceof HeaderGoalResource; + } + + setParents(parents: Array) { + const { parents: oldParents } = this; + parents.sort(); + + if ( + oldParents.length === parents.length && + parents.every((parent, index) => parent === oldParents[index]) + ) { + return; + } + + this.parents = parents; + this.story.updateTree(); + } + + setWeight(weight: number) { + if (this.weight === weight) return; + this.weight = weight; + this.story.symbols.notifyGoalChanged(this); + } + + static updateWeights(goals: Array, weight: number = 0): number { + for (const goal of goals) { + goal.setWeight(weight++); + } + + for (const goal of goals) { + const children = goal.getChildren(); + if (children.length) { + weight = this.updateWeights(children, weight); + } + } + + return weight; + } +} diff --git a/src/server/projects/story/Symbol.ts b/src/server/projects/story/Symbol.ts new file mode 100644 index 0000000..00197e9 --- /dev/null +++ b/src/server/projects/story/Symbol.ts @@ -0,0 +1,336 @@ +import getCallerSymbolType from "./utils/getCallerSymbolType"; +import getDefinitionSymbolType from "./utils/getDefinitionSymbolType"; +import getParameterNameScore from "./utils/getParameterNameScore"; +import Goal from "./Goal"; +import parseDocComments from "./utils/parseDocComment"; +import toParameters from "./utils/toParameters"; +import { CallerNode } from "../../parsers/story/utils/isCallerNode"; +import { EachCallerType } from "../../parsers/story/utils/eachCaller"; +import { SymbolType, SymbolDoc, Variable } from "./models/symbol"; +import { TokenRange } from "../../parsers/story/Lexer"; + +import resolveParameters, { + ResolvePrameterResult +} from "./utils/resolveParameters"; + +import { + Parameter, + ParameterType, + ScoredParameterName +} from "./models/parameter"; + +import { + NodeType, + IdentifierType, + DefinitionNode, + ParameterFlow +} from "../../parsers/story/models/nodes"; +import getAnnotatedType from "./utils/getAnnotatedType"; + +function compareDefinition(left: SymbolDefinition, right: SymbolDefinition) { + if (left.goal.weight === right.goal.weight) { + return left.startOffset - right.startOffset; + } + + return left.goal.weight - right.goal.weight; +} + +export interface SymbolDefinition extends TokenRange { + comment: string | null; + goal: Goal; + isInferred: boolean; + isPartial: boolean; + parameters: Array; + type: SymbolType; +} + +export default class Symbol { + category: string | null = null; + dbReads: Array | null = null; + dbWrites: Array | null = null; + definitions: Array = []; + documentation: SymbolDoc | null = null; + isDead: boolean = false; + isSystem: boolean = false; + name: string; + needsUpdate: boolean = false; + numParameters: number; + parameters: Array; + parameterNames: Array; + resolvedDefinition: SymbolDefinition | null = null; + searchName: string; + type: SymbolType = SymbolType.Unknown; + usages: Array = []; + + constructor(name: string, numParameters: number) { + const parameters: Array = []; + const parameterNames: Array = []; + + for (let index = 0; index < numParameters; index++) { + const name = `_Param${index + 1}`; + parameterNames.push({ name, score: 0 }); + parameters.push({ name, type: ParameterType.Unknown }); + } + + this.name = name; + this.numParameters = numParameters; + this.parameters = parameters; + this.parameterNames = parameterNames; + this.searchName = name.toLowerCase(); + } + + applyTo(node: CallerNode, type: EachCallerType, variables: Array) { + if (type === EachCallerType.Fact) { + return; + } + + const { parameters } = node.signature; + if (parameters.length !== this.numParameters) { + throw new Error("Invalid operation."); + } + + for (let index = 0; index < parameters.length; index++) { + const parameter = parameters[index]; + const { argument } = parameter; + if ( + argument.type !== NodeType.Identifier || + argument.identifierType !== IdentifierType.Variable + ) { + continue; + } + + const definition = this.parameters[index]; + if (definition && definition.flow === ParameterFlow.In) { + continue; + } + + const annotatedType = getAnnotatedType(parameter.valueType); + const name = argument.name.toLowerCase(); + const variable = { + displayName: argument.name, + fromIndex: index, + fromSymbol: this, + name, + type: annotatedType || this.parameters[index].type + }; + + const existingIndex = variables.findIndex( + variable => variable.name === name + ); + + if (existingIndex === -1) { + variables.push(variable); + } + } + } + + addReference( + goal: Goal, + node: CallerNode, + type: EachCallerType, + variables?: Array + ) { + const { definitions, parameterNames, usages, dbReads, dbWrites } = this; + const { identifierType } = node.signature.identifier; + const isDefinition = + !this.isSystem && + (identifierType === IdentifierType.Database || + type === EachCallerType.Definition); + + if (usages.indexOf(goal) === -1) { + usages.push(goal); + } + + if ( + identifierType === IdentifierType.Database && + (node.type === NodeType.Rule || + node.type === NodeType.SignatureCondition) && + (!dbReads || dbReads.indexOf(goal) === -1) + ) { + (dbReads || (this.dbReads = [])).push(goal); + } + + if ( + identifierType === IdentifierType.Database && + node.type === NodeType.SignatureAction && + !node.isInverted && + (!dbWrites || dbWrites.indexOf(goal) === -1) + ) { + (dbWrites || (this.dbWrites = [])).push(goal); + } + + const { parameters } = node.signature; + for (let index = 0; index < parameters.length; index++) { + const { argument } = parameters[index]; + if ( + argument.type === NodeType.Identifier && + argument.identifierType === IdentifierType.Variable + ) { + const score = getParameterNameScore(argument.name); + if (score > parameterNames[index].score) { + parameterNames[index].score = score; + parameterNames[index].name = argument.name; + } + } + } + + if (isDefinition && !this.hasCompleteDefinition(goal)) { + const parameters = toParameters(this, node.signature, variables); + definitions.push({ + ...parameters, + comment: node.type === NodeType.Rule ? node.comment : null, + endOffset: node.endOffset, + endPosition: node.endPosition, + goal, + startOffset: node.startOffset, + startPosition: node.startPosition, + type: getCallerSymbolType(node) + }); + + this.needsUpdate = true; + } + } + + hasCompleteDefinition(target: Goal): boolean { + return this.definitions.some( + ({ goal, isInferred, isPartial }) => + goal === target && !isInferred && !isPartial + ); + } + + isDefinedBy(goal: Goal): boolean { + return this.definitions.some(definition => definition.goal === goal); + } + + notifyGoalChanged(goal: Goal) { + if (this.isDefinedBy(goal)) { + this.needsUpdate = true; + } + } + + removeGoal(goal: Goal) { + const { usages, dbReads, dbWrites } = this; + let index = usages.indexOf(goal); + if (index !== -1) { + usages.splice(index, 1); + } + + if (dbWrites) { + index = dbWrites.indexOf(goal); + if (index !== -1) { + dbWrites.splice(index, 1); + } + } + + if (dbReads) { + index = dbReads.indexOf(goal); + if (index !== -1) { + dbReads.splice(index, 1); + } + } + + if (this.isDefinedBy(goal)) { + this.definitions = this.definitions.filter( + definition => definition.goal !== goal + ); + + this.needsUpdate = true; + } + } + + resetParameters() { + if (this.isSystem) { + console.error("Trying to reset system definition."); + return; + } + + const { numParameters, parameterNames } = this; + const parameters: Array = []; + + for (let index = 0; index < numParameters; index++) { + parameters.push({ + name: parameterNames[index].name, + type: ParameterType.Unknown + }); + } + + this.parameters = parameters; + this.resolvedDefinition = null; + } + + toSystemSymbol(definition: DefinitionNode) { + const { parameters } = toParameters(this, definition.signature); + + this.isSystem = true; + this.parameters = parameters; + } + + update() { + const { definitions, isSystem, dbWrites } = this; + if (isSystem) { + console.error("Trying to rebuild system definition."); + this.needsUpdate = false; + return; + } + + definitions.sort(compareDefinition); + let deadCounter = 0; + this.type = SymbolType.Unknown; + + for (const definition of definitions) { + const parameters = resolveParameters(this, definition); + if (Array.isArray(parameters)) { + this.isDead = false; + this.needsUpdate = false; + this.parameters = parameters; + this.resolvedDefinition = definition; + this.type = definition.type; + this.documentation = definition.comment + ? parseDocComments(definition.comment) + : null; + + return; + } + + if (this.type === SymbolType.Unknown) { + this.type = definition.type; + } + + if (parameters === ResolvePrameterResult.Dead) { + deadCounter += 1; + } + } + + if ( + this.type === SymbolType.Database && + (!dbWrites || dbWrites.length === 0 || deadCounter === definitions.length) + ) { + this.isDead = true; + this.needsUpdate = false; + } + + this.resetParameters(); + } + + static fromCaller(caller: CallerNode): Symbol { + const { signature } = caller; + const symbol = new Symbol( + signature.identifier.name, + signature.parameters.length + ); + + return symbol; + } + + static fromDefinition(definition: DefinitionNode): Symbol { + const { signature } = definition; + const symbol = new Symbol( + signature.identifier.name, + signature.parameters.length + ); + + symbol.type = getDefinitionSymbolType(definition); + symbol.toSystemSymbol(definition); + return symbol; + } +} diff --git a/src/server/projects/story/Symbols.ts b/src/server/projects/story/Symbols.ts new file mode 100644 index 0000000..b867879 --- /dev/null +++ b/src/server/projects/story/Symbols.ts @@ -0,0 +1,163 @@ +import { get as levenshtein } from "fast-levenshtein"; + +import eachCaller from "../../parsers/story/utils/eachCaller"; +import Goal from "./Goal"; +import Story from "./index"; +import Symbol from "./Symbol"; +import { SymbolDoc } from "./models/symbol"; + +import { + SignatureNode, + DefinitionNode, + HeaderGoalNode, + StoryGoalNode +} from "../../parsers/story/models/nodes"; + +export default class Symbols { + readonly story: Story; + readonly symbols: Array = []; + + constructor(story: Story) { + this.story = story; + } + + addSystemSymbol(definition: DefinitionNode) { + let symbol = this.findSymbolForSignature(definition.signature); + if (!symbol) { + symbol = Symbol.fromDefinition(definition); + this.symbols.push(symbol); + } else { + symbol.toSystemSymbol(definition); + } + } + + assignSymbols(rootNode: HeaderGoalNode | StoryGoalNode) { + for (const { node } of eachCaller(rootNode)) { + if (node.symbol) { + continue; + } + + let symbol = this.findSymbolForSignature(node.signature); + if (symbol) { + node.symbol = symbol; + } + } + } + + findSimiliarSymbols(name: string): Array { + name = name.toLowerCase(); + return this.symbols.filter( + symbol => levenshtein(symbol.searchName, name) < 4 + ); + } + + findSymbol(name: string, numParameters: number): Symbol | null { + name = name.toLowerCase(); + return ( + this.symbols.find( + symbol => + symbol.searchName === name && symbol.numParameters === numParameters + ) || null + ); + } + + findSymbols(name: string): Array { + name = name.toLowerCase(); + return this.symbols.filter(symbol => symbol.searchName === name); + } + + findSymbolForSignature(signature: SignatureNode): Symbol | null { + return this.findSymbol( + signature.identifier.name, + signature.parameters.length + ); + } + + async getDocumentation(symbol: Symbol): Promise { + if (symbol.documentation) { + return symbol.documentation; + } + + const { docProvider } = this.story.project.projects; + return await docProvider.getDocumentation(symbol.name); + } + + async loadMetaData() { + const { docProvider } = this.story.project.projects; + const categories = await docProvider.getSymbolCategories(); + if (!categories) return; + + for (const symbol of this.symbols) { + if (symbol.searchName in categories) { + symbol.category = categories[symbol.searchName]; + } + } + } + + notifyGoalChanged(goal: Goal) { + for (const symbol of this.symbols) { + symbol.notifyGoalChanged(goal); + } + } + + updateGoal(goal: Goal, rootNode: HeaderGoalNode | StoryGoalNode) { + this.removeByGoal(goal); + + for (const { node, type, variables } of eachCaller(rootNode)) { + let symbol = this.findSymbolForSignature(node.signature); + if (!symbol) { + symbol = Symbol.fromCaller(node); + this.symbols.push(symbol); + } + + symbol.addReference(goal, node, type, variables); + if (variables) { + symbol.applyTo(node, type, variables); + } + + node.symbol = symbol; + } + } + + removeByGoal(goal: Goal) { + const { symbols } = this; + for (const symbol of symbols) { + symbol.removeGoal(goal); + } + } + + update() { + if (this.story.isInitializing) { + return; + } + + const revisit: Array = []; + const { symbols } = this; + let index = 0; + while (index < symbols.length) { + const symbol = symbols[index]; + if ( + !symbol.definitions.length && + !symbol.usages.length && + !symbol.isSystem + ) { + symbols.splice(index, 1); + continue; + } else { + index += 1; + } + + if (symbol.needsUpdate) { + symbol.update(); + } + + if (symbol.needsUpdate) { + revisit.push(symbol); + } + } + + for (const symbol of revisit) { + symbol.update(); + } + } +} diff --git a/src/server/projects/story/analyzers/Analyzer.ts b/src/server/projects/story/analyzers/Analyzer.ts new file mode 100644 index 0000000..9c4b447 --- /dev/null +++ b/src/server/projects/story/analyzers/Analyzer.ts @@ -0,0 +1,56 @@ +import { Range } from "vscode-languageserver"; + +import Analyzers from "./index"; +import isCallerNode from "../../../parsers/story/utils/isCallerNode"; +import Resource from "../resources/Resource"; +import unpackRange from "../../../parsers/story/utils/unpackRange"; +import { Scope } from "../../../parsers/story/utils/eachRuleNode"; +import { StoryGoalNode, AnyNode } from "../../../parsers/story/models/nodes"; + +import { + DiagnosticType, + DiagnosticMessage +} from "../../../parsers/story/models/diagnostics"; + +function resolveRange(node: AnyNode): Range { + if (isCallerNode(node)) { + node = node.signature.identifier; + } + + return unpackRange(node); +} + +export type AnyAnalyzer = SyncAnalyzer | AsyncAnalyzer; + +export interface AnalyzerContext { + node: AnyNode; + resource: Resource; + rootNode: StoryGoalNode; + scope: Scope | null; + stack: Array; +} + +export abstract class Analyzer { + readonly analyzers: Analyzers; + + constructor(analyzers: Analyzers) { + this.analyzers = analyzers; + } + + addDiagnostic(range: AnyNode, message: DiagnosticMessage) { + this.analyzers.diagnostics.push({ + ...message, + range: unpackRange(range), + type: DiagnosticType.Syntax + }); + } +} + +export abstract class SyncAnalyzer extends Analyzer { + abstract analyze(context: AnalyzerContext): void; +} + +export abstract class AsyncAnalyzer extends Analyzer { + abstract async analyze(context: AnalyzerContext): Promise; + abstract canAnalyze(context: AnalyzerContext): boolean; +} diff --git a/src/server/projects/story/analyzers/GuidLiteralAnalyzer.ts b/src/server/projects/story/analyzers/GuidLiteralAnalyzer.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/server/projects/story/analyzers/Parameter.ts b/src/server/projects/story/analyzers/Parameter.ts new file mode 100644 index 0000000..e72aa26 --- /dev/null +++ b/src/server/projects/story/analyzers/Parameter.ts @@ -0,0 +1,386 @@ +import msgComparisonTypeMismatch from "../messages/msgComparisonTypeMismatch"; +import msgInvalidPlaceholder from "../messages/msgInvalidPlaceholder"; +import msgInvalidTypeCast from "../messages/msgInvalidTypeCast"; +import msgInvalidVariableName from "../messages/msgInvalidVariableName"; +import msgParameterTypeMismatch from "../messages/msgParameterTypeMismatch"; +import msgStringLtGtComparison from "../messages/msgStringLtGtComparison"; +import msgVariableNotAllowed from "../messages/msgVariableNotAllowed"; +import msgVariableNotBound from "../messages/msgVariableNotBound"; +import Symbol from "../Symbol"; +import { AnalyzerContext, SyncAnalyzer } from "./Analyzer"; +import { ArgumentNode } from "../../../parsers/story/utils/isArgumentNode"; +import { ParameterType, Parameter } from "../models/parameter"; +import { Scope } from "../../../parsers/story/utils/eachRuleNode"; +import { SymbolType, Variable } from "../models/symbol"; + +import isCallerNode, { + CallerNode +} from "../../../parsers/story/utils/isCallerNode"; + +import { + NodeType, + TypeAnnotationNode, + ParameterFlow, + IdentifierType, + ParameterNode, + OperatorNode +} from "../../../parsers/story/models/nodes"; +import msgDangerousCast from "../messages/msgDangerousCast"; +import getAnnotatedType from "../utils/getAnnotatedType"; + +const enum ArgumentMode { + Constant, + Placeholder, + Variable +} + +function isDangerousCast(from: ParameterType, to: ParameterType): boolean { + return from !== to && isGuidSubtype(from) && isGuidSubtype(to); +} + +function isGuidType(type: ParameterType): boolean { + return type === ParameterType.Guid || isGuidSubtype(type); +} + +function isGuidSubtype(type: ParameterType): boolean { + return ( + type === ParameterType.CharacterGuid || + type === ParameterType.ItemGuid || + type === ParameterType.LevelTemplateGuid || + type === ParameterType.SplineGuid || + type === ParameterType.TriggerGuid + ); +} + +function isIntegerType(type: ParameterType): boolean { + return type === ParameterType.Integer || type === ParameterType.Integer64; +} + +function isNumericType(type: ParameterType): boolean { + return ( + type === ParameterType.Integer || + type === ParameterType.Integer64 || + type === ParameterType.Real + ); +} + +function isNumericOperator(operator: string) { + return ( + operator === ">" || + operator === ">=" || + operator === "<" || + operator === "<=" + ); +} + +function castType( + from: ParameterType, + to: ParameterType, + allowNumericCast?: boolean +): ParameterType { + if (from === to) return from; + if (isGuidType(from) && isGuidType(to)) return to; + if (isIntegerType(from) && isIntegerType(to)) return to; + if (isNumericType(from) && isNumericType(to)) return to; + + return ParameterType.Invalid; +} + +function getArgumentType( + node: ArgumentNode, + scopeOrType: Scope | ParameterType | null +): ParameterType { + switch (node.type) { + case NodeType.RealLiteral: + return ParameterType.Real; + case NodeType.GuidLiteral: + return ParameterType.Guid; + case NodeType.IntegerLiteral: + return ParameterType.Integer; + case NodeType.StringLiteral: + return ParameterType.String; + case NodeType.Identifier: + if (scopeOrType && typeof scopeOrType === "object") { + const variable = scopeOrType.variablesBefore.find( + variable => variable.name === node.name.toLowerCase() + ); + + if (variable && variable.type) { + return variable.type; + } + } else if (typeof scopeOrType === "number") { + return scopeOrType; + } + + return ParameterType.Unknown; + } +} + +export default class ParameterAnalyzer extends SyncAnalyzer { + analyze({ node, scope }: AnalyzerContext) { + if (node.type === NodeType.OperatorCondition) { + this.analyzeOperator(scope, node); + } else if (isCallerNode(node) && node.symbol) { + const { symbol } = node; + const { parameters } = node.signature; + const definitions = symbol.parameters; + + if (definitions.length !== parameters.length) { + return; + } + + for (let index = 0; index < definitions.length; index++) { + this.analyzeParameter( + scope, + node, + symbol, + definitions[index], + parameters[index], + index + ); + } + } + } + + analyzeOperator(scope: Scope | null, operator: OperatorNode) { + const isLeftValid = this.isValidArgument(scope, operator.leftOperant); + const isRightValid = this.isValidArgument(scope, operator.rightOperant); + if (!isLeftValid || !isRightValid) { + return; + } + + const leftType = this.resolveArgumentType( + scope, + operator.leftOperant, + operator.leftType + ); + + const rightType = this.resolveArgumentType( + scope, + operator.rightOperant, + operator.rightType + ); + + if ( + leftType === ParameterType.Invalid || + rightType === ParameterType.Invalid + ) { + return; + } + + if (castType(leftType, rightType, true) === ParameterType.Invalid) { + return this.addDiagnostic( + operator, + msgComparisonTypeMismatch({ leftType, rightType }) + ); + } + + if (isDangerousCast(leftType, rightType)) { + this.addDiagnostic( + operator, + msgDangerousCast({ + sourceType: leftType, + targetType: rightType + }) + ); + } + + if ( + (!isNumericType(leftType) || !isNumericType(rightType)) && + isNumericOperator(operator.operator) + ) { + this.addDiagnostic( + operator, + msgStringLtGtComparison({ + operator: operator.operator + }) + ); + } + } + + analyzeParameter( + scope: Scope | null, + node: CallerNode, + symbol: Symbol, + definition: Parameter, + parameter: ParameterNode, + index: number + ) { + // Fetch inbound variable + let mode: ArgumentMode; + let variableName: string | undefined; + let variable: Variable | undefined; + + if (parameter.argument.type === NodeType.Identifier) { + if (parameter.argument.identifierType === IdentifierType.Empty) { + mode = ArgumentMode.Placeholder; + } else if ( + parameter.argument.identifierType !== IdentifierType.Variable + ) { + return this.addDiagnostic( + parameter, + msgInvalidVariableName({ name: parameter.argument.name }) + ); + } else if (scope) { + const searchName = parameter.argument.name.toLowerCase(); + variableName = parameter.argument.name; + mode = ArgumentMode.Variable; + variable = scope.variablesBefore.find( + variable => variable.name === searchName + ); + } else { + return this.addDiagnostic( + parameter, + msgVariableNotAllowed({ name: parameter.argument.name }) + ); + } + } else { + mode = ArgumentMode.Constant; + } + + // Determine the value flow + let allowPlaceholders = true; + let flow = definition.flow; + if (!flow) { + if (symbol.type === SymbolType.Call || symbol.type === SymbolType.Query) { + if (node.type === NodeType.Rule) { + flow = + mode === ArgumentMode.Variable + ? ParameterFlow.Out + : ParameterFlow.In; + } else { + allowPlaceholders = false; + flow = ParameterFlow.In; + } + } else if (symbol.type === SymbolType.Database) { + if ( + node.type === NodeType.SignatureAction || + (node.type === NodeType.SignatureCondition && node.isInverted) + ) { + flow = ParameterFlow.In; + } else { + flow = variable ? ParameterFlow.In : ParameterFlow.Out; + } + } else { + flow = variable ? ParameterFlow.In : ParameterFlow.Out; + } + } + + // Bail out for placeholders + if (mode === ArgumentMode.Placeholder) { + if (!allowPlaceholders) { + this.addDiagnostic( + parameter, + msgInvalidPlaceholder({ + requiredByIndex: index, + requiredByName: symbol.name + }) + ); + } + + return; + } + + // If the flow is inbound, bail out if no value is given + if ( + flow === ParameterFlow.In && + mode === ArgumentMode.Variable && + !variable + ) { + return this.addDiagnostic( + parameter, + msgVariableNotBound({ + name: `${variableName}`, + requiredByIndex: index, + requiredByName: symbol.name + }) + ); + } + + // Check the type cast + const parameterType = this.resolveArgumentType( + flow === ParameterFlow.Out ? definition.type : scope, + parameter.argument, + parameter.valueType + ); + + // Bail out if the flow is outbound + if (flow === ParameterFlow.Out) { + return; + } + + // Check the type required by the definition + if (castType(parameterType, definition.type) === ParameterType.Invalid) { + this.addDiagnostic( + parameter, + msgParameterTypeMismatch({ + sourceType: parameterType, + symbol, + targetIndex: index, + targetType: definition.type + }) + ); + } else if (isDangerousCast(parameterType, definition.type)) { + this.addDiagnostic( + parameter, + msgDangerousCast({ + sourceType: parameterType, + targetType: definition.type + }) + ); + } + } + + resolveArgumentType( + scope: Scope | ParameterType | null, + argument: ArgumentNode, + typeAnnotation?: TypeAnnotationNode + ): ParameterType { + const argumentType = getArgumentType(argument, scope); + let result = argumentType; + + const annotatedType = getAnnotatedType(typeAnnotation); + if (!typeAnnotation || annotatedType === null) { + return result; + } + + result = castType(result, annotatedType); + if (result === ParameterType.Invalid) { + result = annotatedType; + + this.addDiagnostic( + typeAnnotation, + msgInvalidTypeCast({ + name: + argument.type === NodeType.Identifier ? argument.name : undefined, + sourceType: argumentType, + targetType: annotatedType + }) + ); + } + + return result; + } + + isValidArgument(scope: Scope | null, argument: ArgumentNode): boolean { + if (argument.type === NodeType.Identifier) { + const { name } = argument; + + if (!scope) { + this.addDiagnostic(argument, msgVariableNotAllowed({ name })); + return false; + } + + const variable = scope.variables.find( + variable => variable.name === argument.name.toLowerCase() + ); + + if (!variable) { + this.addDiagnostic(argument, msgVariableNotBound({ name })); + return false; + } + } + + return true; + } +} diff --git a/src/server/projects/story/analyzers/SymbolLocations.ts b/src/server/projects/story/analyzers/SymbolLocations.ts new file mode 100644 index 0000000..b969a9d --- /dev/null +++ b/src/server/projects/story/analyzers/SymbolLocations.ts @@ -0,0 +1,112 @@ +import msgCanOnlyDeleteFromDatabase from "../messages/msgCanOnlyDeleteFromDatabase"; +import msgInvalidSymbolInCondition from "../messages/msgInvalidSymbolInCondition"; +import msgInvalidSymbolInFact from "../messages/msgInvalidSymbolInFact"; +import msgInvalidSymbolInInitialCondition from "../messages/msgInvalidSymbolInInitialCondition"; +import msgInvalidSymbolInStatement from "../messages/msgInvalidSymbolInStatement"; +import Symbol from "../Symbol"; +import { AnalyzerContext, SyncAnalyzer } from "./Analyzer"; +import { SymbolType } from "../models/symbol"; +import { + NodeType, + RuleNode, + SignatureCallNode +} from "../../../parsers/story/models/nodes"; + +import isCallerNode, { + CallerNode +} from "../../../parsers/story/utils/isCallerNode"; + +export default class SymbolLocationsAnalyzer extends SyncAnalyzer { + analyze({ node, stack }: AnalyzerContext) { + if (!isCallerNode(node) || !node.symbol) return; + const { symbol } = node; + const block = stack[stack.length - 1]; + const rule = stack[stack.length - 2]; + + if (node.type === NodeType.Rule) { + return this.analyzeRule(node, symbol); + } + + switch (block ? block.type : undefined) { + case NodeType.ActionBlock: + if (rule && rule.type === NodeType.Rule) { + return this.analyzeRuleAction(node, symbol); + } else { + return this.analyzeFact(node, symbol); + } + case NodeType.ConditionBlock: + return this.analyzeRuleCondition(node, symbol); + } + + // Should never happen + console.error("Caller outside of block"); + } + + analyzeFact(node: SignatureCallNode, symbol: Symbol) { + this.ensureNotOnDatabase(node, symbol); + + if ( + symbol.type !== SymbolType.Database && + symbol.type !== SymbolType.Call + ) { + this.addDiagnostic(node, msgInvalidSymbolInFact({ symbol })); + } + } + + analyzeRule(node: RuleNode, symbol: Symbol) { + const { ruleType } = node; + let isValid: boolean = false; + + switch (ruleType) { + case "PROC": + isValid = symbol.type === SymbolType.Call && !symbol.isSystem; + break; + + case "QRY": + isValid = symbol.type === SymbolType.Query && !symbol.isSystem; + break; + + case "IF": + isValid = + symbol.type === SymbolType.Event || + symbol.type === SymbolType.Database; + break; + } + + if (!isValid) { + this.addDiagnostic( + node, + msgInvalidSymbolInInitialCondition({ ruleType, symbol }) + ); + } + } + + analyzeRuleAction(node: SignatureCallNode, symbol: Symbol) { + this.ensureNotOnDatabase(node, symbol); + + if ( + symbol.type !== SymbolType.Database && + symbol.type !== SymbolType.Call + ) { + this.addDiagnostic(node, msgInvalidSymbolInStatement({ symbol })); + } + } + + analyzeRuleCondition(node: CallerNode, symbol: Symbol) { + if ( + symbol.type !== SymbolType.Database && + symbol.type !== SymbolType.Query + ) { + this.addDiagnostic(node, msgInvalidSymbolInCondition({ symbol })); + } + } + + ensureNotOnDatabase(node: SignatureCallNode, symbol: Symbol) { + if ( + node.isInverted && + !(symbol.type === SymbolType.Database || symbol.type === SymbolType.Query) + ) { + this.addDiagnostic(node, msgCanOnlyDeleteFromDatabase({ symbol })); + } + } +} diff --git a/src/server/projects/story/analyzers/SymbolTypes.ts b/src/server/projects/story/analyzers/SymbolTypes.ts new file mode 100644 index 0000000..63e2a89 --- /dev/null +++ b/src/server/projects/story/analyzers/SymbolTypes.ts @@ -0,0 +1,86 @@ +import isCallerNode from "../../../parsers/story/utils/isCallerNode"; +import msgDatabaseNoWrite from "../messages/msgDatabaseNoWrite"; +import msgDatabaseNoRead from "../messages/msgDatabaseNoRead"; +import msgInvalidDatabasePrefix from "../messages/msgInvalidDatabasePrefix"; +import msgParamaterCountMismatch from "../messages/msgParamaterCountMismatch"; +import msgSigantureTypo from "../messages/msgSigantureTypo"; +import msgUnresolvedSignature from "../messages/msgUnresolvedSignature"; +import msgUnresolvedSymbol from "../messages/msgUnresolvedSymbol"; +import Symbol from "../Symbol"; +import { AnalyzerContext, SyncAnalyzer } from "./Analyzer"; +import { SymbolType } from "../models/symbol"; +import { NodeType } from "../../../parsers/story/models/nodes"; + +export default class SymbolTypesAnalyzer extends SyncAnalyzer { + analyze({ node, resource }: AnalyzerContext) { + if (!isCallerNode(node)) return; + const { symbol } = node; + + // This should actually not happen right now + if (!symbol) { + return this.addDiagnostic(node, msgUnresolvedSymbol({ node })); + } + + // Helper: Filter out invalid symbols + const filterSymbol = (existingSymbol: Symbol) => + existingSymbol !== symbol && existingSymbol.type !== SymbolType.Unknown; + + // Symbol type is unknown + if (symbol.type === SymbolType.Unknown) { + // Check for symbol with different parameter count + const { symbols } = resource.story; + const existingSymbols = symbols + .findSymbols(symbol.name) + .filter(filterSymbol); + + if (existingSymbols.length) { + return this.addDiagnostic( + node, + msgParamaterCountMismatch({ + actualSymbol: symbol, + existingSymbols + }) + ); + } + + // Check for symbols with a similiar name + const similiarSymbols = symbols + .findSimiliarSymbols(symbol.name) + .filter(filterSymbol); + + if (similiarSymbols.length) { + return this.addDiagnostic( + node, + msgSigantureTypo({ + actualSymbol: symbol, + similiarSymbols + }) + ); + } + + // Still no luck - create database error + return this.addDiagnostic(node, msgInvalidDatabasePrefix({ symbol })); + } + + // Procedure / Query definition with undefined parameters + if ( + node.type === NodeType.Rule && + !symbol.resolvedDefinition && + !symbol.isSystem + ) { + return this.addDiagnostic( + node, + msgUnresolvedSignature({ symbol, rule: node }) + ); + } + + // Database warnings + if (symbol.type === SymbolType.Database) { + if (symbol.isDead || !symbol.dbWrites) { + return this.addDiagnostic(node, msgDatabaseNoWrite({ symbol })); + } else if (!symbol.dbReads && symbol.searchName !== "db_noop") { + return this.addDiagnostic(node, msgDatabaseNoRead({ symbol })); + } + } + } +} diff --git a/src/server/projects/story/analyzers/index.ts b/src/server/projects/story/analyzers/index.ts new file mode 100644 index 0000000..94442cc --- /dev/null +++ b/src/server/projects/story/analyzers/index.ts @@ -0,0 +1,67 @@ +import eachNodeRecursive from "../../../parsers/story/utils/eachNodeRecursive"; +import Resource from "../resources/Resource"; +import Story from ".."; +import SymbolLocationsAnalyzer from "./SymbolLocations"; +import SymbolTypesAnalyzer from "./SymbolTypes"; +import { AnyAnalyzer, AnalyzerContext, SyncAnalyzer } from "./Analyzer"; +import { Diagnostic } from "../../../parsers/story/models/diagnostics"; +import { StoryGoalNode } from "../../../parsers/story/models/nodes"; +import { + isInScope, + Scope, + tryStartScope, + updateScope +} from "../../../parsers/story/utils/eachRuleNode"; +import ParameterAnalyzer from "./Parameter"; + +export default class Analyzers { + readonly diagnostics: Array = []; + readonly story: Story; + readonly workers: Array; + + constructor(story: Story) { + this.story = story; + this.workers = [ + new SymbolTypesAnalyzer(this), + new SymbolLocationsAnalyzer(this), + new ParameterAnalyzer(this) + ]; + } + + async apply( + resource: Resource, + rootNode: StoryGoalNode + ): Promise> { + const { workers } = this; + let scope: Scope | null = null; + + const context: AnalyzerContext = { + node: rootNode, + resource, + rootNode, + scope: null, + stack: [] + }; + + this.diagnostics.length = 0; + + for (const { node, stack } of eachNodeRecursive(rootNode)) { + if (scope && !isInScope(scope, stack)) scope = null; + scope = scope ? updateScope(scope, node) : tryStartScope(node); + + context.node = node; + context.scope = scope; + context.stack = stack; + + for (const worker of workers) { + if (worker instanceof SyncAnalyzer) { + worker.analyze(context); + } else if (worker.canAnalyze(context)) { + await worker.analyze(context); + } + } + } + + return this.diagnostics.slice(); + } +} diff --git a/src/server/projects/story/index.ts b/src/server/projects/story/index.ts new file mode 100644 index 0000000..026f4f9 --- /dev/null +++ b/src/server/projects/story/index.ts @@ -0,0 +1,276 @@ +import * as Queue from "promise-queue"; +import { join, normalize } from "path"; + +import Analyzers from "./analyzers"; +import FileResource from "./resources/FileResource"; +import FileWatcher from "../FileWatcher"; +import Goal from "./Goal"; +import GoalResource from "./resources/GoalResource"; +import HeaderResource from "./resources/HeaderResource"; +import HeaderGoalResource from "./resources/HeaderGoalResource"; +import Project from "../Project"; +import Resource from "./resources/Resource"; +import sortGoals from "./utils/sortGoals"; +import Symbols from "./Symbols"; +import { existsSync } from "fs"; + +export default class Story { + isInitializing: boolean = true; + + readonly analyzers: Analyzers = new Analyzers(this); + readonly project: Project; + readonly symbols: Symbols = new Symbols(this); + readonly queue: Queue; + readonly types: Array = [ + "INTEGER", + "INTEGER64", + "REAL", + "STRING", + "GUIDSTRING" + ]; + + private headerResource: HeaderResource | null = null; + private goals: Array = []; + private ignoreHeaderChange: NodeJS.Timer | null = null; + private resources: Array = []; + private watchers: Array = []; + + constructor(project: Project) { + this.project = project; + this.queue = new Queue(1, Number.POSITIVE_INFINITY, { + onEmpty: this.handleQueueEmpty + }); + } + + addGoal(goal: Goal) { + this.removeGoalByName(goal.name); + this.goals.push(goal); + + this.updateTree(); + } + + addIgnoredGoal(name: string) { + if (this.headerResource) { + this.headerResource.addIgnoredGoal(name); + } + } + + addResource(resource: HeaderGoalResource) { + this.resources.push(resource); + } + + async analyzeGoals() { + for (const resource of this.resources) { + if (resource instanceof GoalResource && resource.getDocument()) { + await resource.analyze(); + } + } + } + + dispose() { + this.watchers.forEach(watcher => watcher.dispose()); + this.watchers.length = 0; + } + + findGoal(name: string): Goal | null { + return this.goals.find(goal => goal.name === name) || null; + } + + findOrCreateResource(path: string): FileResource | null { + let resource = this.findResource(path); + if (resource) return resource; + + const rawPath = this.getGoalsPath(); + if (existsSync(rawPath) && path.startsWith(rawPath)) { + resource = new GoalResource({ story: this, path }); + this.resources.push(resource); + return resource; + } + + return null; + } + + findResource(path: string): FileResource | null { + return ( + (this.resources.find( + file => file instanceof FileResource && file.path === path + ) as FileResource) || null + ); + } + + getHeaderGoalResources(): Array { + return this.resources.filter( + file => file instanceof HeaderGoalResource + ) as Array; + } + + getGoal(name: string): Goal | null { + return this.goals.find(goal => goal.name === name) || null; + } + + getGoals(): Array { + return this.goals.slice(); + } + + getGoalsByParent(parent: string): Array { + return this.goals.filter(goal => goal.parents.indexOf(parent) !== -1); + } + + getGoalsPath(): string { + return normalize(join(this.project.path, "Story", "RawFiles", "Goals")); + } + + getRootGoals(): Array { + return this.goals.filter(goal => goal.parents.length === 0); + } + + getSortedRootGoals(): Array { + return this.getRootGoals().sort(sortGoals); + } + + ignoreHeaderFileEvents() { + if (this.ignoreHeaderChange) { + clearTimeout(this.ignoreHeaderChange); + } + + this.ignoreHeaderChange = setTimeout(() => { + this.ignoreHeaderChange = null; + }, 500); + } + + initialize() { + this.watchers = this.createWatchers(); + } + + removeGoal(goal: Goal) { + this.goals = this.goals.filter(existingGoal => existingGoal !== goal); + this.symbols.removeByGoal(goal); + this.updateTree(); + } + + removeGoalByName(name: string) { + this.goals + .filter(goal => goal.name === name) + .forEach(goal => this.removeGoal(goal)); + } + + removeResource(resource: Resource) { + this.resources = this.resources.filter(existing => existing !== resource); + resource.dispose(); + } + + updateTree() { + if (this.isInitializing) { + return; + } + + const { project } = this; + Goal.updateWeights(this.getRootGoals()); + project.projects.emit("goalsChanged", project); + } + + async whenReady(): Promise { + if (this.isInitializing) { + return new Promise(resolve => { + const { projects } = this.project; + const onReady = (project: Project) => { + if (project !== this.project) return; + projects.removeListener("projectReady", onReady); + resolve(); + }; + projects.addListener("projectReady", onReady); + }); + } else { + return Promise.resolve(); + } + } + + private createHeaderWatcher(): FileWatcher { + const watcher = new FileWatcher({ + path: normalize(join(this.project.path, "Story")), + pattern: /story\.div$/ + }); + + let resource: HeaderResource | null = null; + watcher.on("update", path => { + if (!resource) { + resource = new HeaderResource({ story: this, path }); + this.headerResource = resource; + this.resources.push(resource); + } + + if (!this.ignoreHeaderChange) { + resource.loadSync(); + } + }); + + watcher.scanAndStartSync(); + return watcher; + } + + private createGoalWatcher(): FileWatcher { + const watcher = new FileWatcher({ + path: this.getGoalsPath(), + pattern: /\.txt$/ + }); + + watcher.on("update", path => { + let resource = this.findResource(path); + if (!resource) { + resource = new GoalResource({ story: this, path }); + this.resources.push(resource); + } + + this.queue.add(resource.load); + }); + + watcher.on("remove", path => { + const resource = this.findResource(path); + if (resource) { + this.removeResource(resource); + } + }); + + watcher.scanAndStartSync(); + return watcher; + } + + private createWatchers(): Array { + const watchers: Array = []; + + try { + watchers.push(this.createHeaderWatcher()); + } catch (error) { + this.project.projects.emit("showError", error.message); + } + + try { + watchers.push(this.createGoalWatcher()); + } catch (error) { + this.project.projects.emit("showError", error.message); + } + + if (this.queue.getPendingLength() === 0) { + this.handleQueueEmpty(); + } + + return watchers; + } + + private handleQueueEmpty = async () => { + if (this.isInitializing) { + const { project, symbols } = this; + + this.isInitializing = false; + this.updateTree(); + + await symbols.loadMetaData(); + symbols.update(); + + await this.analyzeGoals(); + + project.projects.emit("projectReady", this.project); + project.levels.initialize(); + } + }; +} diff --git a/src/server/projects/story/messages/msgCanOnlyDeleteFromDatabase.ts b/src/server/projects/story/messages/msgCanOnlyDeleteFromDatabase.ts new file mode 100644 index 0000000..6e1215c --- /dev/null +++ b/src/server/projects/story/messages/msgCanOnlyDeleteFromDatabase.ts @@ -0,0 +1,23 @@ +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; +import printSymbolType from "../utils/printSymbolType"; + +export type Params = { + symbol: Symbol; +}; + +export default function msgCanOnlyDeleteFromDatabase({ + symbol +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.CanOnlyDeleteFromDatabase, + message: `NOT actions can only reference databases; "${ + symbol.name + }" is a ${printSymbolType(symbol)}`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgComparisonTypeMismatch.ts b/src/server/projects/story/messages/msgComparisonTypeMismatch.ts new file mode 100644 index 0000000..5039a41 --- /dev/null +++ b/src/server/projects/story/messages/msgComparisonTypeMismatch.ts @@ -0,0 +1,27 @@ +import { ParameterType } from "../models/parameter"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; +import printParameterType from "../utils/printParameterType"; + +export type Params = { + leftType: ParameterType; + rightType: ParameterType; +}; + +export default function msgComparisonTypeMismatch({ + leftType, + rightType +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.LocalTypeMismatch, + message: `Type of left expression (${printParameterType( + leftType + )}) differs from type of right expression (${printParameterType( + rightType + )})`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgDangerousCast.ts b/src/server/projects/story/messages/msgDangerousCast.ts new file mode 100644 index 0000000..839a3e6 --- /dev/null +++ b/src/server/projects/story/messages/msgDangerousCast.ts @@ -0,0 +1,25 @@ +import printParameterType from "../utils/printParameterType"; +import { ParameterType } from "../models/parameter"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + sourceType: ParameterType; + targetType: ParameterType; +}; + +export default function msgDangerousCast({ + sourceType, + targetType +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.GuidAliasMismatch, + message: `GUID alias cast: Type ${printParameterType( + sourceType + )} converted to ${printParameterType(targetType)}`, + severity: DiagnosticSeverity.Warning + }; +} diff --git a/src/server/projects/story/messages/msgDatabaseNoRead.ts b/src/server/projects/story/messages/msgDatabaseNoRead.ts new file mode 100644 index 0000000..070437c --- /dev/null +++ b/src/server/projects/story/messages/msgDatabaseNoRead.ts @@ -0,0 +1,22 @@ +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + symbol: Symbol; +}; + +export default function msgDatabaseNoRead({ + symbol +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.UnusedDatabase, + message: `Database "${ + symbol.name + }" is written to, but is never used in a rule`, + severity: DiagnosticSeverity.Warning + }; +} diff --git a/src/server/projects/story/messages/msgDatabaseNoWrite.ts b/src/server/projects/story/messages/msgDatabaseNoWrite.ts new file mode 100644 index 0000000..c0c72a9 --- /dev/null +++ b/src/server/projects/story/messages/msgDatabaseNoWrite.ts @@ -0,0 +1,22 @@ +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + symbol: Symbol; +}; + +export default function msgDatabaseNoWrite({ + symbol +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.UnusedDatabase, + message: `Database "${ + symbol.name + }" is used in a rule, but is never written to`, + severity: DiagnosticSeverity.Warning + }; +} diff --git a/src/server/projects/story/messages/msgInvalidDatabasePrefix.ts b/src/server/projects/story/messages/msgInvalidDatabasePrefix.ts new file mode 100644 index 0000000..0b6dd3d --- /dev/null +++ b/src/server/projects/story/messages/msgInvalidDatabasePrefix.ts @@ -0,0 +1,22 @@ +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + symbol: Symbol; +}; + +export default function msgInvalidDatabasePrefix({ + symbol +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.DbNamingStyle, + message: `Name of database "${ + symbol.name + }" should start with the prefix "DB"`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgInvalidPlaceholder.ts b/src/server/projects/story/messages/msgInvalidPlaceholder.ts new file mode 100644 index 0000000..97e0eac --- /dev/null +++ b/src/server/projects/story/messages/msgInvalidPlaceholder.ts @@ -0,0 +1,22 @@ +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + requiredByIndex: number; + requiredByName: string; +}; + +export default function msgInvalidPlaceholder({ + requiredByIndex, + requiredByName +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.ParamNotBound, + message: `Placeholder used but parameter ${requiredByIndex + + 1} of ${requiredByName} is required`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgInvalidSymbolInCondition.ts b/src/server/projects/story/messages/msgInvalidSymbolInCondition.ts new file mode 100644 index 0000000..e2a1d35 --- /dev/null +++ b/src/server/projects/story/messages/msgInvalidSymbolInCondition.ts @@ -0,0 +1,23 @@ +import printSymbolType from "../utils/printSymbolType"; +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + symbol: Symbol; +}; + +export default function msgInvalidSymbolInCondition({ + symbol +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.InvalidFunctionTypeInCondition, + message: `Subsequent rule conditions can only be queries or DBs; "${ + symbol.name + }" is a ${printSymbolType(symbol)}`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgInvalidSymbolInFact.ts b/src/server/projects/story/messages/msgInvalidSymbolInFact.ts new file mode 100644 index 0000000..08f6d68 --- /dev/null +++ b/src/server/projects/story/messages/msgInvalidSymbolInFact.ts @@ -0,0 +1,23 @@ +import printSymbolType from "../utils/printSymbolType"; +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + symbol: Symbol; +}; + +export default function msgInvalidSymbolInFact({ + symbol +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.InvalidSymbolInFact, + message: `Init/Exit actions can only reference databases, calls and PROCs; "${ + symbol.name + }" is a ${printSymbolType(symbol)}`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgInvalidSymbolInInitialCondition.ts b/src/server/projects/story/messages/msgInvalidSymbolInInitialCondition.ts new file mode 100644 index 0000000..81b362f --- /dev/null +++ b/src/server/projects/story/messages/msgInvalidSymbolInInitialCondition.ts @@ -0,0 +1,48 @@ +import printSymbolType from "../utils/printSymbolType"; +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + ruleType: "IF" | "PROC" | "QRY"; + symbol: Symbol; +}; + +export default function msgInvalidSymbolInInitialCondition({ + ruleType, + symbol +}: Params): DiagnosticMessage { + let message: string; + switch (ruleType) { + case "IF": + message = `Initial rule condition can only be an event or a DB; "${ + symbol.name + }" is a ${printSymbolType(symbol)}`; + break; + + case "PROC": + message = `Initial proc condition can only be a PROC name; "${ + symbol.name + }" is a ${printSymbolType(symbol)}`; + break; + + case "QRY": + message = `Initial query condition can only be a user-defined QRY name; "${ + symbol.name + }" is a ${printSymbolType(symbol)}`; + break; + + default: + message = `Invalid initial condition`; + break; + } + + return { + code: DiagnosticCode.InvalidSymbolInInitialCondition, + message, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgInvalidSymbolInStatement.ts b/src/server/projects/story/messages/msgInvalidSymbolInStatement.ts new file mode 100644 index 0000000..75ed357 --- /dev/null +++ b/src/server/projects/story/messages/msgInvalidSymbolInStatement.ts @@ -0,0 +1,23 @@ +import printSymbolType from "../utils/printSymbolType"; +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + symbol: Symbol; +}; + +export default function msgInvalidSymbolInStatement({ + symbol +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.InvalidSymbolInFact, + message: `KB rule actions can only reference databases, calls and PROCs; "${ + symbol.name + }" is a ${printSymbolType(symbol)}`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgInvalidTypeCast.ts b/src/server/projects/story/messages/msgInvalidTypeCast.ts new file mode 100644 index 0000000..7c962aa --- /dev/null +++ b/src/server/projects/story/messages/msgInvalidTypeCast.ts @@ -0,0 +1,36 @@ +import { ParameterType } from "../models/parameter"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; +import printParameterType from "../utils/printParameterType"; + +export type Params = { + name?: string; + sourceType: ParameterType; + targetType: ParameterType; +}; + +export default function msgInvalidTypeCast({ + name, + sourceType, + targetType +}: Params): DiagnosticMessage { + let message: string; + if (name) { + message = `Rule variable "${name}" of type ${printParameterType( + sourceType + )} cannot be converted to ${printParameterType(targetType)}`; + } else { + message = `Type ${printParameterType( + sourceType + )} cannot be converted to ${printParameterType(targetType)}`; + } + + return { + code: DiagnosticCode.LocalTypeMismatch, + message, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgInvalidVariableName.ts b/src/server/projects/story/messages/msgInvalidVariableName.ts new file mode 100644 index 0000000..81a116d --- /dev/null +++ b/src/server/projects/story/messages/msgInvalidVariableName.ts @@ -0,0 +1,20 @@ +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + name: string; +}; + +export default function msgInvalidVariableName({ + name +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.InvalidVariableName, + message: `Variable name "${name}" must start with an underscore.`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgParamaterCountMismatch.ts b/src/server/projects/story/messages/msgParamaterCountMismatch.ts new file mode 100644 index 0000000..0c9bd29 --- /dev/null +++ b/src/server/projects/story/messages/msgParamaterCountMismatch.ts @@ -0,0 +1,34 @@ +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +function printNumParameters(symbols: Array) { + const nums = symbols.map(symbol => symbol.numParameters).sort(); + if (nums.length === 1 && nums[0] === 1) { + return `1 parameter`; + } + + const orNum = nums.length > 1 ? nums.pop() : undefined; + return `${nums.join(", ")}${orNum ? ` or ${orNum}` : ""} parameters`; +} + +export type Params = { + actualSymbol: Symbol; + existingSymbols: Array; +}; + +export default function msgParamaterCountMismatch({ + actualSymbol, + existingSymbols +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.UnresolvedSymbol, + message: `Symbol "${actualSymbol.name}" could not be resolved: "${ + actualSymbol.name + }" requires ${printNumParameters(existingSymbols)}.`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgParameterTypeMismatch.ts b/src/server/projects/story/messages/msgParameterTypeMismatch.ts new file mode 100644 index 0000000..a6ba3c1 --- /dev/null +++ b/src/server/projects/story/messages/msgParameterTypeMismatch.ts @@ -0,0 +1,33 @@ +import printParameterType from "../utils/printParameterType"; +import printSymbolType from "../utils/printSymbolType"; +import Symbol from "../Symbol"; +import { ParameterType } from "../models/parameter"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + sourceType: ParameterType; + symbol: Symbol; + targetIndex: number; + targetType: ParameterType; +}; + +export default function msgParameterTypeMismatch({ + sourceType, + symbol, + targetIndex, + targetType +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.LocalTypeMismatch, + message: `Parameter ${targetIndex + 1} of ${printSymbolType(symbol)} "${ + symbol.name + }" expects ${printParameterType(targetType)}; ${printParameterType( + sourceType + )} specified`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgSigantureTypo.ts b/src/server/projects/story/messages/msgSigantureTypo.ts new file mode 100644 index 0000000..3087bc8 --- /dev/null +++ b/src/server/projects/story/messages/msgSigantureTypo.ts @@ -0,0 +1,38 @@ +import Symbol from "../Symbol"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +function printSimiliars(symbols: Array): string { + const names = symbols + .map(symbol => `"${symbol.name}"`) + .reduce( + (result, name) => + result.indexOf(name) === -1 ? [...result, name] : result, + [] as Array + ) + .sort(); + + const orName = names.length > 1 ? names.pop() : undefined; + return `${names.join(", ")}${orName ? ` or ${orName}` : ""}`; +} + +export type Params = { + actualSymbol: Symbol; + similiarSymbols: Array; +}; + +export default function msgSigantureTypo({ + actualSymbol, + similiarSymbols +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.UnresolvedSymbol, + message: `Symbol "${ + actualSymbol.name + }" could not be resolved: did you mean ${printSimiliars(similiarSymbols)}?`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgStringLtGtComparison.ts b/src/server/projects/story/messages/msgStringLtGtComparison.ts new file mode 100644 index 0000000..a7fa05c --- /dev/null +++ b/src/server/projects/story/messages/msgStringLtGtComparison.ts @@ -0,0 +1,20 @@ +import { CallerNode } from "../../../parsers/story/utils/isCallerNode"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + operator: string; +}; + +export default function msgStringLtGtComparison({ + operator +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.StringLtGtComparison, + message: `String comparison using operator ${operator} - probably a mistake?`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgUnresolvedSignature.ts b/src/server/projects/story/messages/msgUnresolvedSignature.ts new file mode 100644 index 0000000..04a67cf --- /dev/null +++ b/src/server/projects/story/messages/msgUnresolvedSignature.ts @@ -0,0 +1,59 @@ +import Symbol from "../Symbol"; +import toParameters from "../utils/toParameters"; +import { ParameterType } from "../models/parameter"; +import { RuleNode } from "../../../parsers/story/models/nodes"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +function printDefinitionError(rule: RuleNode, symbol: Symbol): string { + const { parameters } = toParameters(symbol, rule.signature); + + const unknowns: Array = []; + for (let index = 0; index < parameters.length; index++) { + const parameter = parameters[index]; + if ( + parameter.type === ParameterType.Unknown || + parameter.type === ParameterType.Invalid + ) { + unknowns.push(`#${index + 1} "${parameter.name}"`); + } + } + + if (unknowns.length) { + let parameters: string; + + if (unknowns.length === 1) { + parameters = `parameter ${unknowns[0]}`; + } else { + const andUnknown = unknowns.length > 1 ? unknowns.pop() : undefined; + parameters = `parameters ${unknowns.join(", ")}${ + andUnknown ? ` and ${andUnknown}` : "" + }`; + } + + return `: the type of ${parameters} could not be resolved`; + } + + return `.`; +} + +export type Params = { + rule: RuleNode; + symbol: Symbol; +}; + +export default function msgUnresolvedSignature({ + rule, + symbol +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.UnresolvedSignature, + message: `Signature of "${ + symbol.name + }" could not be determined${printDefinitionError(rule, symbol)}`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgUnresolvedSymbol.ts b/src/server/projects/story/messages/msgUnresolvedSymbol.ts new file mode 100644 index 0000000..77d793b --- /dev/null +++ b/src/server/projects/story/messages/msgUnresolvedSymbol.ts @@ -0,0 +1,20 @@ +import { CallerNode } from "../../../parsers/story/utils/isCallerNode"; +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + node: CallerNode; +}; + +export default function msgUnresolvedSymbol({ + node +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.UnresolvedSymbol, + message: `Symbol "${node.signature.identifier.name}" could not be resolved`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgVariableNotAllowed.ts b/src/server/projects/story/messages/msgVariableNotAllowed.ts new file mode 100644 index 0000000..8f24e2a --- /dev/null +++ b/src/server/projects/story/messages/msgVariableNotAllowed.ts @@ -0,0 +1,19 @@ +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + name: string; +}; + +export default function msgVariableNotAllowed({ + name +}: Params): DiagnosticMessage { + return { + code: DiagnosticCode.VariableNotAllowed, + message: `Variable "${name}" is not allowed in this context.`, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/messages/msgVariableNotBound.ts b/src/server/projects/story/messages/msgVariableNotBound.ts new file mode 100644 index 0000000..b4bdd03 --- /dev/null +++ b/src/server/projects/story/messages/msgVariableNotBound.ts @@ -0,0 +1,29 @@ +import { + DiagnosticCode, + DiagnosticMessage, + DiagnosticSeverity +} from "../../../parsers/story/models/diagnostics"; + +export type Params = { + name: string; + requiredByIndex?: number; + requiredByName?: string; +}; + +export default function msgVariableNotBound({ + name, + requiredByIndex, + requiredByName +}: Params): DiagnosticMessage { + let message = `Variable ${name} is not bound`; + if (requiredByIndex && requiredByName) { + message += ` but parameter ${requiredByIndex + + 1} of ${requiredByName} is required`; + } + + return { + code: DiagnosticCode.ParamNotBound, + message, + severity: DiagnosticSeverity.Error + }; +} diff --git a/src/server/projects/story/models/parameter.ts b/src/server/projects/story/models/parameter.ts new file mode 100644 index 0000000..6674161 --- /dev/null +++ b/src/server/projects/story/models/parameter.ts @@ -0,0 +1,30 @@ +import Symbol from "../Symbol"; +import { ParameterFlow } from "../../../parsers/story/models/nodes"; + +export enum ParameterType { + Unknown, + Invalid, + Integer, + Integer64, + Real, + String, + Guid, + CharacterGuid, + ItemGuid, + TriggerGuid, + SplineGuid, + LevelTemplateGuid +} + +export interface Parameter { + flow?: ParameterFlow; + fromIndex?: number; + fromSymbol?: Symbol; + name: string; + type: ParameterType; +} + +export interface ScoredParameterName { + name: string; + score: number; +} diff --git a/src/server/projects/story/models/symbol.ts b/src/server/projects/story/models/symbol.ts new file mode 100644 index 0000000..902e251 --- /dev/null +++ b/src/server/projects/story/models/symbol.ts @@ -0,0 +1,35 @@ +import Goal from "../Goal"; +import Symbol from "../Symbol"; +import { AnyNode } from "../../../parsers/story/models/nodes"; +import { ParameterType } from "./parameter"; + +export interface SymbolParameterDoc { + description?: string; + name?: string; +} + +export interface SymbolDoc { + description?: string; + parameters?: Array; +} + +export const enum SymbolType { + Unknown, + Call, + Database, + Event, + Query +} + +export interface SymbolLocation { + goal: Goal; + node: AnyNode; +} + +export interface Variable { + displayName: string; + fromIndex: number; + fromSymbol: Symbol; + name: string; + type?: ParameterType; +} diff --git a/src/server/projects/story/resources/FileResource.ts b/src/server/projects/story/resources/FileResource.ts new file mode 100644 index 0000000..83133ce --- /dev/null +++ b/src/server/projects/story/resources/FileResource.ts @@ -0,0 +1,32 @@ +import { normalize } from "path"; +import { readFileSync } from "fs"; + +import Resource, { ResourceOptions } from "./Resource"; +import { AnyNode } from "../../../parsers/story/models/nodes"; +import { readFile } from "../../../../shared/fs"; + +export interface FileResourceOptions extends ResourceOptions { + path: string; +} + +export default abstract class FileResource< + T extends AnyNode = AnyNode +> extends Resource { + readonly path: string; + constructor(options: FileResourceOptions) { + super(options); + this.path = normalize(options.path); + } + + async getSource(): Promise { + return readFile(this.path, { encoding: "utf-8" }); + } + + getSourceSync(): string { + return readFileSync(this.path, { encoding: "utf-8" }); + } + + getUri(): string { + return `file:///${encodeURIComponent(this.path.replace(/\\/g, "/"))}`; + } +} diff --git a/src/server/projects/story/resources/GoalResource.ts b/src/server/projects/story/resources/GoalResource.ts new file mode 100644 index 0000000..b16d870 --- /dev/null +++ b/src/server/projects/story/resources/GoalResource.ts @@ -0,0 +1,79 @@ +import { basename } from "path"; + +import GoalParser from "../../../parsers/story/GoalParser"; +import { DiagnosticType } from "../../../parsers/story/models/diagnostics"; +import { StoryGoalNode } from "../../../parsers/story/models/nodes"; + +import FileResource, { FileResourceOptions } from "./FileResource"; +import Goal from "../Goal"; +import Story from ".."; + +export default class GoalResource extends FileResource { + readonly goal: Goal; + readonly story: Story; + + constructor(options: FileResourceOptions) { + super(options); + + const { path, story } = options; + const goal = new Goal(story, basename(path, ".txt"), this); + story.addIgnoredGoal(goal.name); + story.addGoal(goal); + + this.goal = goal; + this.story = story; + } + + async analyze() { + const node = await this.getRootNode(true); + + this.setDiagnostics( + DiagnosticType.Analyzer, + await this.story.analyzers.apply(this, node) + ); + } + + dispose() { + super.dispose(); + this.story.removeGoal(this.goal); + } + + async getSource(): Promise { + const { document } = this; + if (document) { + return Promise.resolve(document.getText()); + } + + return super.getSource(); + } + + protected async parse( + source: string, + noAnalysis?: boolean + ): Promise { + const { goal, story } = this; + const parser = new GoalParser(source); + const { diagnostics, goal: node } = parser.parse(); + + if (noAnalysis) { + story.symbols.assignSymbols(node); + return node; + } + + this.setDiagnostics(DiagnosticType.Syntax, diagnostics); + story.symbols.updateGoal(goal, node); + + const parents = node.parentTargetEdges; + goal.setParents(parents ? parents.map(parentEdge => parentEdge.value) : []); + story.symbols.update(); + + if (!story.isInitializing) { + this.setDiagnostics( + DiagnosticType.Analyzer, + await story.analyzers.apply(this, node) + ); + } + + return node; + } +} diff --git a/src/server/projects/story/resources/HeaderGoalResource.ts b/src/server/projects/story/resources/HeaderGoalResource.ts new file mode 100644 index 0000000..1625c64 --- /dev/null +++ b/src/server/projects/story/resources/HeaderGoalResource.ts @@ -0,0 +1,80 @@ +import Goal from "../Goal"; +import goalTemplate from "../../../../shared/goalTemplate"; +import GoalParser from "../../../parsers/story/GoalParser"; +import Resource, { ResourceOptions } from "./Resource"; +import { + HeaderGoalNode, + StoryGoalNode +} from "../../../parsers/story/models/nodes"; + +export interface HeaderGoalResourceOptions extends ResourceOptions { + name: string; +} + +export default class HeaderGoalResource extends Resource { + readonly goal: Goal; + private source: string = ""; + + constructor(options: HeaderGoalResourceOptions) { + super(options); + + const { name, story } = options; + const goal = new Goal(story, name, this); + story.addGoal(goal); + + this.goal = goal; + } + + dispose() { + super.dispose(); + this.source = ""; + this.story.removeGoal(this.goal); + } + + async getSource(): Promise { + return Promise.resolve(this.source); + } + + getUri(): string { + const { goal, story } = this; + const { UUID } = story.project.meta; + return `divinity:///${UUID}/${goal.name}.divGoal`; + } + + update(allNodes: Array, rootNode: HeaderGoalNode) { + const id = rootNode.id; + const parents: Array = []; + + for (const { title, subGoal } of allNodes) { + if (title && subGoal.some(subGoal => subGoal === id)) { + parents.push(title); + } + } + + this.source = goalTemplate({ + exit: rootNode.exit, + init: rootNode.init, + kb: rootNode.kb, + parents + }); + + const parser = new GoalParser(this.source); + const { goal: node } = parser.parse(); + const { goal, story } = this; + + story.symbols.updateGoal(goal, node); + goal.setParents(parents); + } + + protected async parse( + source: string, + noAnalysis?: boolean + ): Promise { + const parser = new GoalParser(source); + const { goal: node } = parser.parse(); + + this.story.symbols.assignSymbols(node); + + return node; + } +} diff --git a/src/server/projects/story/resources/HeaderResource.ts b/src/server/projects/story/resources/HeaderResource.ts new file mode 100644 index 0000000..ad12ce0 --- /dev/null +++ b/src/server/projects/story/resources/HeaderResource.ts @@ -0,0 +1,117 @@ +import { join } from "path"; +import { readFileSync, writeFileSync } from "fs"; + +import FileResource, { FileResourceOptions } from "./FileResource"; +import HeaderGoalResource from "./HeaderGoalResource"; +import HeaderParser from "../../../parsers/story/HeaderParser"; + +import { + HeaderNode, + HeaderGoalNode, + DefinitionNode +} from "../../../parsers/story/models/nodes"; + +export default class HeaderResource extends FileResource { + ignoredGoals: Array; + ignoredPath: string; + + constructor(options: FileResourceOptions) { + super(options); + + const ignoredPath = join( + options.story.project.path, + "Story", + "story_custom_goals.txt" + ); + + let ignoredGoals: Array; + try { + const data = readFileSync(ignoredPath, "utf-8"); + ignoredGoals = JSON.parse(data); + } catch (error) { + ignoredGoals = []; + } + + this.ignoredGoals = ignoredGoals; + this.ignoredPath = ignoredPath; + } + + addIgnoredGoal(name: string) { + const { ignoredGoals, ignoredPath } = this; + if (ignoredGoals.indexOf(name) !== -1) return; + ignoredGoals.push(name); + + try { + writeFileSync(ignoredPath, JSON.stringify(ignoredGoals)); + } catch (error) {} + } + + loadSync(noAnalysis?: boolean) { + const source = this.getSourceSync(); + this.parse(source, noAnalysis); + } + + protected async parse( + source: string, + noAnalysis?: boolean + ): Promise { + const parser: HeaderParser = new HeaderParser(source); + const { header } = parser.parse(); + + this.syncDefinitions(header.definitions); + this.syncGoals(header.goals); + this.syncTypeAliases(header.typeAliases); + + this.story.symbols.update(); + return header; + } + + private syncDefinitions(definitions: Array) { + const { symbols } = this.story; + + for (const definition of definitions) { + symbols.addSystemSymbol(definition); + } + } + + private syncGoals(nodes: Array) { + const { story } = this; + const existingResources = story.getHeaderGoalResources(); + const resources: Array = []; + + for (const node of nodes) { + if (!node.title || this.ignoredGoals.indexOf(node.title) !== -1) continue; + const name = node.title; + let resource = existingResources.find( + resource => resource.goal.name === name + ); + + if (!resource) { + if (story.getGoal(name) !== null) { + continue; + } + + resource = new HeaderGoalResource({ name, story }); + story.addResource(resource); + } + + if (resource) { + resource.update(nodes, node); + resources.push(resource); + } + } + + existingResources + .filter(resource => resources.indexOf(resource) === -1) + .forEach(resource => story.removeResource(resource)); + } + + private syncTypeAliases(aliases: Array) { + const { types } = this.story; + for (const alias of aliases) { + if (types.indexOf(alias) === -1) { + types.push(alias); + } + } + } +} diff --git a/src/server/projects/story/resources/Resource.ts b/src/server/projects/story/resources/Resource.ts new file mode 100644 index 0000000..9e87075 --- /dev/null +++ b/src/server/projects/story/resources/Resource.ts @@ -0,0 +1,137 @@ +import { + Position, + TextDocument, + TextDocumentEdit +} from "vscode-languageserver"; + +import eachNode from "../../../parsers/story/utils/eachNode"; +import Projects from "../.."; +import Story from ".."; +import { AnyNode } from "../../../parsers/story/models/nodes"; + +import { + Diagnostic, + DiagnosticType +} from "../../../parsers/story/models/diagnostics"; + +export interface ResourceOptions { + story: Story; +} + +export default abstract class Resource { + readonly story: Story; + + protected diagnostics: Array = []; + protected document: TextDocument | null = null; + protected rootNode: T | null = null; + + constructor(options: ResourceOptions) { + this.load = this.load.bind(this); + this.story = options.story; + } + + abstract async getSource(): Promise; + + abstract getUri(): string; + + protected abstract async parse( + source: string, + noAnalysis?: boolean + ): Promise; + + dispose() { + if (this.document) this.document = null; + if (this.rootNode) this.rootNode = null; + this.diagnostics.length = 0; + } + + async load(noAnalysis?: boolean): Promise { + const buffer = await this.getSource(); + + const rootNode = await this.parse(buffer, noAnalysis); + if (this.document) { + this.rootNode = rootNode; + } + + return rootNode; + } + + getDocument(): TextDocument | null { + return this.document; + } + + getDiagnostics(): Array { + return this.diagnostics; + } + + async getNodesAt(position: Position) { + const { document } = this; + const rootNode = await this.getRootNode(); + + if (!rootNode || !document) { + return null; + } + + function findIn(parent: AnyNode) { + for (const node of eachNode(parent)) { + if (node.endOffset <= offset) continue; + if (node.startOffset > offset) break; + nodes.push(node); + findIn(node); + break; + } + } + + const offset = document.offsetAt(position); + const nodes: Array = []; + findIn(rootNode); + + return nodes; + } + + getProjects(): Projects { + return this.story.project.projects; + } + + async getRootNode(noAnalysis?: boolean): Promise { + if (this.rootNode) { + return Promise.resolve(this.rootNode); + } + + return this.load(noAnalysis); + } + + getTextEdit(): TextDocumentEdit { + return { + edits: [], + textDocument: { + uri: this.getUri(), + version: this.document ? this.document.version : null + } + }; + } + + invalidate() { + this.story.queue.add(this.load); + } + + setDocument(document: TextDocument | null) { + this.document = document; + + if (document == null) { + this.rootNode = null; + } + } + + protected setDiagnostics( + type: DiagnosticType, + diagnostics: Array + ) { + this.diagnostics = [ + ...this.diagnostics.filter(diagnostics => diagnostics.type !== type), + ...diagnostics + ]; + + this.getProjects().emit("diagnostics", this); + } +} diff --git a/src/server/projects/story/utils/getAnnotatedType.ts b/src/server/projects/story/utils/getAnnotatedType.ts new file mode 100644 index 0000000..8baaf3b --- /dev/null +++ b/src/server/projects/story/utils/getAnnotatedType.ts @@ -0,0 +1,14 @@ +import { TypeAnnotationNode } from "../../../parsers/story/models/nodes"; +import { ParameterType } from "../models/parameter"; +import toParameterType from "./toParameterType"; + +export default function getAnnotatedType( + node?: TypeAnnotationNode +): ParameterType | null { + if (!node || !node.annotatedType) { + return null; + } + + const result = toParameterType(node.annotatedType); + return result === ParameterType.Unknown ? null : result; +} diff --git a/src/server/projects/story/utils/getCallerSymbolType.ts b/src/server/projects/story/utils/getCallerSymbolType.ts new file mode 100644 index 0000000..eef6acf --- /dev/null +++ b/src/server/projects/story/utils/getCallerSymbolType.ts @@ -0,0 +1,21 @@ +import { CallerNode } from "../../../parsers/story/utils/isCallerNode"; +import { NodeType, IdentifierType } from "../../../parsers/story/models/nodes"; +import { SymbolType } from "../models/symbol"; + +export default function getCallerSymbolType(caller: CallerNode): SymbolType { + if (caller.type === NodeType.Rule) { + const { ruleType } = caller; + if (ruleType === "PROC") { + return SymbolType.Call; + } else if (ruleType === "QRY") { + return SymbolType.Query; + } + } + + const { identifierType } = caller.signature.identifier; + if (identifierType === IdentifierType.Database) { + return SymbolType.Database; + } + + return SymbolType.Unknown; +} diff --git a/src/server/projects/story/utils/getConstantParameterType.ts b/src/server/projects/story/utils/getConstantParameterType.ts new file mode 100644 index 0000000..402d972 --- /dev/null +++ b/src/server/projects/story/utils/getConstantParameterType.ts @@ -0,0 +1,22 @@ +import { ParameterNode, NodeType } from "../../../parsers/story/models/nodes"; +import { ParameterType } from "../models/parameter"; + +export default function getConstantParameterType( + node: ParameterNode +): ParameterType | null { + switch (node.argument.type) { + case NodeType.RealLiteral: + return ParameterType.Real; + + case NodeType.GuidLiteral: + return ParameterType.Guid; + + case NodeType.IntegerLiteral: + return ParameterType.Integer; + + case NodeType.StringLiteral: + return ParameterType.String; + } + + return null; +} diff --git a/src/server/projects/story/utils/getDefinitionSymbolType.ts b/src/server/projects/story/utils/getDefinitionSymbolType.ts new file mode 100644 index 0000000..d9aead7 --- /dev/null +++ b/src/server/projects/story/utils/getDefinitionSymbolType.ts @@ -0,0 +1,17 @@ +import { DefinitionNode } from "../../../parsers/story/models/nodes"; +import { SymbolType } from "../models/symbol"; + +export default function getDefinitionSymbolType( + definition: DefinitionNode +): SymbolType { + switch (definition.definitionType.toLowerCase()) { + case "event": + return SymbolType.Event; + case "sysquery": + case "query": + case "qry": + return SymbolType.Query; + } + + return SymbolType.Call; +} diff --git a/src/server/projects/story/utils/getExplicitParameterType.ts b/src/server/projects/story/utils/getExplicitParameterType.ts new file mode 100644 index 0000000..deefda2 --- /dev/null +++ b/src/server/projects/story/utils/getExplicitParameterType.ts @@ -0,0 +1,14 @@ +import toParameterType from "./toParameterType"; +import { ParameterNode } from "../../../parsers/story/models/nodes"; +import { ParameterType } from "../models/parameter"; +import getConstantParameterType from "./getConstantParameterType"; + +export default function getExplicitParameterType( + node: ParameterNode +): ParameterType | null { + if (node.valueType) { + return toParameterType(node.valueType.annotatedType); + } + + return getConstantParameterType(node); +} diff --git a/src/server/projects/story/utils/getParameterNameScore.ts b/src/server/projects/story/utils/getParameterNameScore.ts new file mode 100644 index 0000000..6a836a6 --- /dev/null +++ b/src/server/projects/story/utils/getParameterNameScore.ts @@ -0,0 +1,7 @@ +export default function getParameterNameScoe(value: string): number { + if (value.startsWith("_Param")) { + return 0; + } + + return Math.abs(value.length); +} diff --git a/src/server/projects/story/utils/parseDocComment.ts b/src/server/projects/story/utils/parseDocComment.ts new file mode 100644 index 0000000..5ee167f --- /dev/null +++ b/src/server/projects/story/utils/parseDocComment.ts @@ -0,0 +1,226 @@ +import { SymbolDoc, SymbolParameterDoc } from "../models/symbol"; + +/** + * The doc parser is an adaption of the module djsdoc + * https://github.com/EYHN/djsdoc + * + * + * The MIT License (MIT) + * + * Copyright (c) 2016-present Zeit, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +const NON_ASCII_WHITESPACES = [ + 0x1680, + 0x2000, + 0x2001, + 0x2002, + 0x2003, + 0x2004, + 0x2005, + 0x2006, + 0x2007, + 0x2008, + 0x2009, + 0x200a, + 0x202f, + 0x205f, + 0x3000, + 0xfeff +]; + +/** + * Return true if provided code is line terminator. Line terminator characters are formally defined in ECMA262. + * @param {number} ch + */ +function isLineTerminator(ch: number): boolean { + return ch === 0x0a || ch === 0x0d || ch === 0x2028 || ch === 0x2029; +} + +/** + * Return true if provided code is white space. White space characters are formally defined in ECMA262. + * @param {number} ch + */ +function isWhiteSpace(ch: number): boolean { + return ( + ch === 0x20 || + ch === 0x09 || + ch === 0x0b || + ch === 0x0c || + ch === 0xa0 || + (ch >= 0x1680 && NON_ASCII_WHITESPACES.indexOf(ch) >= 0) + ); +} + +export interface DocCommentTag { + title: string; + content: string; +} + +export class DocComment { + readonly description: string; + readonly source: string; + readonly tags: Array; + private index: number; + + constructor(source: string) { + this.source = source; + this.index = 0; + + const description = this.readDescription(); + const tags = []; + + while (true) { + const tag = this.readTag(); + if (!tag) break; + tags.push(tag); + } + + this.description = description; + this.tags = tags; + } + + private advance(): string { + return String.fromCharCode(this.source.charCodeAt(this.index++)); + } + + private readContent() { + const { source } = this; + let content = ""; + let waiting = false; + + while (this.index < source.length) { + const ch = source.charCodeAt(this.index); + if ( + isLineTerminator(ch) && + !( + ch === 0x0d /* '\r' */ && source.charCodeAt(this.index + 1) === 0x0a + ) /* '\n' */ + ) { + waiting = true; + } else if (waiting) { + if (ch === 0x40 /* '@' */) { + break; + } + + if (!isWhiteSpace(ch)) { + waiting = false; + } + } + + content += this.advance(); + } + + return content.trim(); + } + + private readDescription(): string { + const { source } = this; + let description = ""; + let atAllowed = true; + + while (this.index < source.length) { + let ch = source.charCodeAt(this.index); + if (atAllowed && ch === 0x40 /* '@' */) { + break; + } + + if (isLineTerminator(ch)) { + atAllowed = true; + } else if (atAllowed && !isWhiteSpace(ch)) { + atAllowed = false; + } + + description += this.advance(); + } + + return description.trim(); + } + + private readTag(): DocCommentTag | null { + if (!this.skipToTag()) { + return null; + } + + const title = this.readTitle(); + const content = this.readContent(); + return { content, title }; + } + + private readTitle(): string { + const { source } = this; + let title = ""; + + // waste '@' + this.advance(); + + while ( + this.index < source.length && + !isWhiteSpace(source.charCodeAt(this.index)) && + !isLineTerminator(source.charCodeAt(this.index)) + ) { + title += this.advance(); + } + + return title; + } + + private skipToTag(): boolean { + const { source } = this; + + while ( + this.index < source.length && + source.charCodeAt(this.index) !== 0x40 /* '@' */ + ) { + this.advance(); + } + + if (this.index >= source.length) { + return false; + } + + return true; + } +} + +export default function parseDocComments(source: string): SymbolDoc { + const comment = new DocComment(source); + + let description: string | undefined = comment.description.trim(); + if (description === "") description = undefined; + + const parameters: Array = []; + for (const tag of comment.tags) { + if (tag.title.toLowerCase() !== "param") continue; + + const firstSpace = tag.content.indexOf(" "); + if (firstSpace === -1) continue; + + const name = tag.content.substr(0, firstSpace).trim(); + const description = tag.content.substr(firstSpace).trim(); + parameters.push({ description, name }); + } + + return { + description, + parameters + }; +} diff --git a/src/server/projects/story/utils/printParameterFlow.ts b/src/server/projects/story/utils/printParameterFlow.ts new file mode 100644 index 0000000..23625dd --- /dev/null +++ b/src/server/projects/story/utils/printParameterFlow.ts @@ -0,0 +1,12 @@ +import { ParameterFlow } from "../../../parsers/story/models/nodes"; + +export default function printParameterFlow(value?: ParameterFlow): string { + switch (value) { + case ParameterFlow.In: + return "IN"; + case ParameterFlow.Out: + return "OUT"; + default: + return ""; + } +} diff --git a/src/server/projects/story/utils/printParameterType.ts b/src/server/projects/story/utils/printParameterType.ts new file mode 100644 index 0000000..11e3e60 --- /dev/null +++ b/src/server/projects/story/utils/printParameterType.ts @@ -0,0 +1,28 @@ +import { ParameterType } from "../models/parameter"; + +export default function printParameterType(value?: ParameterType): string { + switch (value) { + case ParameterType.Integer: + return "INTEGER"; + case ParameterType.Integer64: + return "INTEGER64"; + case ParameterType.Real: + return "REAL"; + case ParameterType.String: + return "STRING"; + case ParameterType.Guid: + return "GUIDSTRING"; + case ParameterType.CharacterGuid: + return "CHARACTERGUID"; + case ParameterType.ItemGuid: + return "ITEMGUID"; + case ParameterType.TriggerGuid: + return "TRIGGERGUID"; + case ParameterType.SplineGuid: + return "SPLINEGUID"; + case ParameterType.LevelTemplateGuid: + return "LEVELTEMPLATEGUID"; + default: + return "Unknown"; + } +} diff --git a/src/server/projects/story/utils/printSymbol.ts b/src/server/projects/story/utils/printSymbol.ts new file mode 100644 index 0000000..07d6bb9 --- /dev/null +++ b/src/server/projects/story/utils/printSymbol.ts @@ -0,0 +1,26 @@ +import printParameterType from "./printParameterType"; +import Symbol from "../Symbol"; +import { ParameterFlow } from "../../../parsers/story/models/nodes"; + +export default function printSymbol( + symbol: Symbol, + useLineBreaks?: boolean +): string { + let parameters = symbol.parameters + .map(({ flow, name, type }) => { + const parts: Array = []; + if (useLineBreaks) parts.push(" "); + if (flow) parts.push(`[${flow === ParameterFlow.In ? "in" : "out"}]`); + if (type) parts.push(`(${printParameterType(type)})`); + parts.push(name); + + return parts.join(""); + }) + .join(useLineBreaks ? ",\n" : ", "); + + if (useLineBreaks && parameters.length) { + parameters = `\n${parameters}\n`; + } + + return `${symbol.name}(${parameters})`; +} diff --git a/src/server/projects/story/utils/printSymbolType.ts b/src/server/projects/story/utils/printSymbolType.ts new file mode 100644 index 0000000..da88e04 --- /dev/null +++ b/src/server/projects/story/utils/printSymbolType.ts @@ -0,0 +1,23 @@ +import Symbol from "../Symbol"; +import { SymbolType } from "../models/symbol"; + +export default function printSymbolType(type: Symbol | SymbolType): string { + let prefix = ""; + if (type instanceof Symbol) { + if (type.isSystem) prefix = "system "; + type = type.type; + } + + switch (type) { + case SymbolType.Call: + return prefix + "call"; + case SymbolType.Database: + return "database"; + case SymbolType.Event: + return "event"; + case SymbolType.Query: + return prefix + "query"; + default: + return ""; + } +} diff --git a/src/server/projects/story/utils/resolveParameters.ts b/src/server/projects/story/utils/resolveParameters.ts new file mode 100644 index 0000000..3ec85ec --- /dev/null +++ b/src/server/projects/story/utils/resolveParameters.ts @@ -0,0 +1,70 @@ +import Symbol, { SymbolDefinition } from "../Symbol"; +import { Parameter, ParameterType } from "../models/parameter"; + +export const enum ResolvePrameterResult { + Dead, + Partial, + Unresolved +} + +export default function resolveParameters( + symbol: Symbol, + definition: SymbolDefinition, + unresolved?: Array +): Array | ResolvePrameterResult { + const { isPartial, parameters } = definition; + const { parameterNames: names } = symbol; + const resolved: Array = []; + + if (isPartial) { + return ResolvePrameterResult.Partial; + } + + for (let index = 0; index < parameters.length; index++) { + const { flow, fromIndex, fromSymbol, type } = parameters[index]; + const name = names[index].name; + + if (type !== ParameterType.Unknown) { + resolved.push({ flow, name, type }); + continue; + } + + if (fromSymbol && fromIndex !== undefined) { + if (fromSymbol.isDead) { + return ResolvePrameterResult.Dead; + } else if (fromSymbol.needsUpdate) { + // Check for loops - If the other symbol is only waiting for + // definitions from us, it's a deadlock + if ( + fromSymbol.definitions.every(otherDefinition => + otherDefinition.parameters.some( + otherParameter => otherParameter.fromSymbol === symbol + ) + ) + ) { + return ResolvePrameterResult.Dead; + } + } + + const type = fromSymbol.parameters[fromIndex].type; + if (type === ParameterType.Unknown) { + if (unresolved) { + unresolved.push(index); + } else { + return ResolvePrameterResult.Unresolved; + } + } + + resolved.push({ flow, name, type }); + continue; + } + + if (unresolved) { + unresolved.push(index); + } else { + return ResolvePrameterResult.Unresolved; + } + } + + return resolved; +} diff --git a/src/server/projects/story/utils/sortGoals.ts b/src/server/projects/story/utils/sortGoals.ts new file mode 100644 index 0000000..2023ca1 --- /dev/null +++ b/src/server/projects/story/utils/sortGoals.ts @@ -0,0 +1,5 @@ +import Goal from "../Goal"; + +export default function sortGoals(left: Goal, right: Goal): number { + return left.name.localeCompare(right.name); +} diff --git a/src/server/projects/story/utils/toParameterType.ts b/src/server/projects/story/utils/toParameterType.ts new file mode 100644 index 0000000..8a8238d --- /dev/null +++ b/src/server/projects/story/utils/toParameterType.ts @@ -0,0 +1,28 @@ +import { ParameterType } from "../models/parameter"; + +export default function toParameterType(value?: string): ParameterType { + switch (value ? value.toUpperCase() : undefined) { + case "INTEGER": + return ParameterType.Integer; + case "INTEGER64": + return ParameterType.Integer64; + case "REAL": + return ParameterType.Real; + case "STRING": + return ParameterType.String; + case "GUIDSTRING": + return ParameterType.Guid; + case "CHARACTERGUID": + return ParameterType.CharacterGuid; + case "ITEMGUID": + return ParameterType.ItemGuid; + case "TRIGGERGUID": + return ParameterType.TriggerGuid; + case "SPLINEGUID": + return ParameterType.SplineGuid; + case "LEVELTEMPLATEGUID": + return ParameterType.LevelTemplateGuid; + default: + return ParameterType.Unknown; + } +} diff --git a/src/server/projects/story/utils/toParameters.ts b/src/server/projects/story/utils/toParameters.ts new file mode 100644 index 0000000..b679b68 --- /dev/null +++ b/src/server/projects/story/utils/toParameters.ts @@ -0,0 +1,75 @@ +import getExplicitParameterType from "./getExplicitParameterType"; +import Symbol from "../Symbol"; +import { Parameter, ParameterType } from "../models/parameter"; +import { Variable } from "../models/symbol"; + +import { + SignatureNode, + NodeType, + IdentifierType +} from "../../../parsers/story/models/nodes"; + +export default function toParameters( + symbol: Symbol, + signature: SignatureNode, + variables?: Array +) { + const positions = signature.parameters; + const parameters: Array = []; + let isInferred: boolean = false; + let isPartial: boolean = false; + + for (let index = 0; index < positions.length; index++) { + const position = positions[index]; + const { argument, flow } = position; + + let type = getExplicitParameterType(position); + let name: string; + if (argument.type === NodeType.Identifier) { + name = argument.name; + } else { + name = `_Param${index + 1}`; + } + + if ( + !type && + variables && + argument.type === NodeType.Identifier && + argument.identifierType === IdentifierType.Variable + ) { + const variable = variables.find( + variable => variable.name === name.toLowerCase() + ); + + // Make sure we don't wait for variables from ourself + if (variable && variable.fromSymbol !== symbol) { + isInferred = true; + parameters.push({ + flow, + fromIndex: variable.fromIndex, + fromSymbol: variable.fromSymbol, + name, + type: variable.type || ParameterType.Unknown + }); + continue; + } + } + + if (!type) { + isPartial = true; + type = ParameterType.Invalid; + } + + parameters.push({ + flow, + name, + type + }); + } + + return { + isInferred, + isPartial, + parameters + }; +} diff --git a/src/server/projects/story/utils/toSymbolTypeFromString.ts b/src/server/projects/story/utils/toSymbolTypeFromString.ts new file mode 100644 index 0000000..e702764 --- /dev/null +++ b/src/server/projects/story/utils/toSymbolTypeFromString.ts @@ -0,0 +1,20 @@ +import { SymbolType } from "../models/symbol"; + +export default function toSymbolTypeFromString( + value: string +): SymbolType | null { + switch (value.toLowerCase()) { + case "call": + case "proc": + case "syscall": + return SymbolType.Call; + case "event": + return SymbolType.Event; + case "sysquery": + case "query": + case "qry": + return SymbolType.Query; + } + + return null; +} diff --git a/src/server/utils/debounce.ts b/src/server/utils/debounce.ts new file mode 100644 index 0000000..2cadfd8 --- /dev/null +++ b/src/server/utils/debounce.ts @@ -0,0 +1,13 @@ +export default function debounce( + callback: T, + time: number +) { + let interval: NodeJS.Timer | undefined; + return (...args: Array) => { + if (interval) clearTimeout(interval); + interval = setTimeout(() => { + interval = undefined; + callback(...args); + }, time); + }; +} diff --git a/src/server/utils/fetch.ts b/src/server/utils/fetch.ts new file mode 100644 index 0000000..e4b00bf --- /dev/null +++ b/src/server/utils/fetch.ts @@ -0,0 +1,30 @@ +import * as https from "https"; + +export interface FetchResult { + code: number; + content: string; + error?: Error; +} + +export default function fetch(url: string): Promise { + return new Promise(resolve => { + https + .get(url, resp => { + let content = ""; + + resp.on("data", chunk => { + content += chunk; + }); + + resp.on("end", () => { + resolve({ + code: resp.statusCode || -1, + content + }); + }); + }) + .on("error", error => { + resolve({ code: -1, content: "", error }); + }); + }); +} diff --git a/src/server/utils/parseUri.ts b/src/server/utils/parseUri.ts new file mode 100644 index 0000000..63dd2a1 --- /dev/null +++ b/src/server/utils/parseUri.ts @@ -0,0 +1,34 @@ +import { normalize } from "path"; + +export type ParsedUri = + | { + type: "path"; + path: string; + } + | { + goal: string; + project: string; + type: "header"; + } + | null; + +export default function parseUri(uri: string): ParsedUri { + uri = decodeURIComponent(uri); + if (uri.startsWith("file:///")) { + return { + type: "path", + path: normalize(uri.substr(8)) + }; + } + + const match = /divinity:\/([^/]+)\/(.*?)\.divGoal/.exec(uri); + if (match) { + return { + goal: match[2], + project: match[1], + type: "header" + }; + } + + return null; +} diff --git a/src/server/utils/readProjectMetaInfo.ts b/src/server/utils/readProjectMetaInfo.ts new file mode 100644 index 0000000..222c480 --- /dev/null +++ b/src/server/utils/readProjectMetaInfo.ts @@ -0,0 +1,21 @@ +import { ProjectMetaInfo } from "../../shared/notifications"; + +export default function readProjectMetaInfo(data: any): ProjectMetaInfo { + const params = data.save.region[0].node[0].children[0].node; + const result: any = {}; + + for (const param of params) { + if (param.$.id === "ModuleInfo") { + for (const { $ } of param.attribute) { + const { id, value } = $; + result[id] = value; + } + } + } + + if (!("UUID" in result) || !("Name" in result)) { + throw new Error("Missing project metadata."); + } + + return result as ProjectMetaInfo; +} diff --git a/src/server/utils/readXmlFile.ts b/src/server/utils/readXmlFile.ts new file mode 100644 index 0000000..dcde18f --- /dev/null +++ b/src/server/utils/readXmlFile.ts @@ -0,0 +1,17 @@ +import { parseString } from "xml2js"; +import { readFile } from "../../shared/fs"; + +export default async function readXmlFile(path: string): Promise { + return readFile(path, { encoding: "utf-8" }).then( + source => + new Promise((resolve, reject) => { + parseString(source, (error, data) => { + if (error) { + reject(error); + } else { + resolve(data); + } + }); + }) + ); +} diff --git a/src/server/utils/runSafe.ts b/src/server/utils/runSafe.ts new file mode 100644 index 0000000..eb1fc61 --- /dev/null +++ b/src/server/utils/runSafe.ts @@ -0,0 +1,55 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { + CancellationToken, + ResponseError, + ErrorCodes +} from "vscode-languageserver/lib/main"; + +export function formatError(message: string, err: any): string { + if (err instanceof Error) { + let error = err; + return `${message}: ${error.message}\n${error.stack}`; + } else if (typeof err === "string") { + return `${message}: ${err}`; + } else if (err) { + return `${message}: ${err.toString()}`; + } + return message; +} + +export function cancelValue() { + console.log("cancelled"); + return new ResponseError(ErrorCodes.RequestCancelled, "Request cancelled"); +} + +export default function runSafe( + func: () => T, + errorVal: T, + errorMessage: string, + token: CancellationToken +): Thenable> { + return new Promise>((resolve, reject) => { + setImmediate(() => { + if (token.isCancellationRequested) { + resolve(cancelValue()); + } else { + try { + let result = func(); + if (token.isCancellationRequested) { + resolve(cancelValue()); + return; + } else { + resolve(result); + } + } catch (e) { + console.error(formatError(errorMessage, e)); + resolve(errorVal); + } + } + }); + }); +} diff --git a/src/server/utils/runSafeAsync.ts b/src/server/utils/runSafeAsync.ts new file mode 100644 index 0000000..456e836 --- /dev/null +++ b/src/server/utils/runSafeAsync.ts @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { + CancellationToken, + ResponseError +} from "vscode-languageserver/lib/main"; + +import { cancelValue, formatError } from "./runSafe"; + +export default function runSafeAsync( + func: () => Thenable, + errorVal: T, + errorMessage: string, + token: CancellationToken +): Thenable> { + return new Promise>((resolve, reject) => { + setImmediate(() => { + if (token.isCancellationRequested) { + resolve(cancelValue()); + } + return func().then( + result => { + if (token.isCancellationRequested) { + resolve(cancelValue()); + return; + } else { + resolve(result); + } + }, + e => { + console.error(formatError(errorMessage, e)); + resolve(errorVal); + } + ); + }); + }); +} diff --git a/src/server/utils/sleep.ts b/src/server/utils/sleep.ts new file mode 100644 index 0000000..13150a9 --- /dev/null +++ b/src/server/utils/sleep.ts @@ -0,0 +1,5 @@ +export default async function sleep(duration: number = 500): Promise { + return new Promise(resolve => { + setTimeout(() => resolve(), duration); + }); +} diff --git a/src/server/utils/toLocation.ts b/src/server/utils/toLocation.ts new file mode 100644 index 0000000..8a3a250 --- /dev/null +++ b/src/server/utils/toLocation.ts @@ -0,0 +1,13 @@ +import { Location, TextDocument } from "vscode-languageserver/lib/main"; +import { TokenRange } from "../parsers/story/Lexer"; +import unpackRange from "../parsers/story/utils/unpackRange"; + +export default function toLocation( + document: TextDocument, + range: TokenRange +): Location { + return { + uri: document.uri, + range: unpackRange(range) + }; +} diff --git a/src/server/utils/ucfirst.ts b/src/server/utils/ucfirst.ts new file mode 100644 index 0000000..7bf7d5a --- /dev/null +++ b/src/server/utils/ucfirst.ts @@ -0,0 +1,3 @@ +export default function ucfirst(value: string): string { + return value.substr(0, 1).toUpperCase() + value.substr(1); +} diff --git a/src/shared/fs.ts b/src/shared/fs.ts new file mode 100644 index 0000000..cde6d84 --- /dev/null +++ b/src/shared/fs.ts @@ -0,0 +1,11 @@ +import * as fs from "fs"; +import { promisify } from "util"; + +const readDir = promisify(fs.readdir); +const readFile = promisify(fs.readFile); +const rename = promisify(fs.rename); +const stat = promisify(fs.stat); +const unlink = promisify(fs.unlink); +const writeFile = promisify(fs.writeFile); + +export { readDir, readFile, rename, stat, unlink, writeFile }; diff --git a/src/shared/getPackagePath.ts b/src/shared/getPackagePath.ts new file mode 100644 index 0000000..666d84f --- /dev/null +++ b/src/shared/getPackagePath.ts @@ -0,0 +1,5 @@ +import { join, normalize } from "path"; + +export default function getPackagePath() { + return normalize(join(__dirname, "..", "..")); +} diff --git a/src/shared/goalTemplate.ts b/src/shared/goalTemplate.ts new file mode 100644 index 0000000..4482a8d --- /dev/null +++ b/src/shared/goalTemplate.ts @@ -0,0 +1,35 @@ +export interface TemplateOptions { + exit?: string; + init?: string; + kb?: string; + parents?: Array; + subGoalCombiner?: string; + version?: number; +} + +export default function goalTemplate({ + exit = "", + init = "", + kb = "", + parents = [], + subGoalCombiner = "SGC_AND", + version = 1 +}: TemplateOptions): string { + const lines = [ + `Version ${version}`, + `SubGoalCombiner ${subGoalCombiner}`, + "INITSECTION", + init, + "KBSECTION", + kb, + "EXITSECTION", + exit, + "ENDEXITSECTION" + ]; + + for (const parent of parents) { + lines.push(`ParentTargetEdge "${parent}"`); + } + + return lines.join("\r\n"); +} diff --git a/src/shared/notifications.ts b/src/shared/notifications.ts new file mode 100644 index 0000000..2107f9f --- /dev/null +++ b/src/shared/notifications.ts @@ -0,0 +1,66 @@ +export const apiShowEvent = "divinity/apiShow"; +export const divRequestEvent = "divinity/divRequest"; +export const divRequestResultEvent = "divinity/divRequestResult"; +export const goalsChangedEvent = "divinity/goalsChanged"; +export const readyEvent = "divinity/ready"; + +export interface DivRequestResult { + content: string | null; + uri: string; +} + +export interface GoalsChanged { + goals: Array; + project: ProjectInfo; + treeVersion: number; +} + +export interface ProjectInfo { + meta: ProjectMetaInfo; + path: string; +} + +export interface ProjectMetaInfo { + Author?: string; + CharacterCreationLevelName?: string; + Description?: string; + Folder: string; + GMTemplate?: string; + LobbyLevelName?: string; + MD5?: string; + MenuLevelName?: string; + Name: string; + NumPlayers?: string; + PhotoBooth?: string; + StartupLevelName?: string; + Tags?: string; + Type?: string; + UUID: string; + Version?: string; +} + +export interface GoalInfo { + children: Array; + isShared: boolean; + name: string; + uri: string; +} + +// Error event + +export const showErrorEvent = "divinity/showError"; + +export interface ShowErrorArgs { + message: string; +} + +// Project events + +export const projectAddedEvent = "divinity/projectAdded"; +export const projectReadyEvent = "divinity/projectReady"; +export const levelIndexStartEvent = "divinity/levelIndexStart"; +export const levelIndexReadyEvent = "divinity/levelIndexReady"; + +export interface ProjectEventArgs { + project: ProjectInfo; +} diff --git a/src/shared/requests.ts b/src/shared/requests.ts new file mode 100644 index 0000000..58255b6 --- /dev/null +++ b/src/shared/requests.ts @@ -0,0 +1,38 @@ +import { WorkspaceEdit } from "vscode-languageclient"; + +// API request + +export const apiRequest = "divinity/api"; + +export interface ApiResult { + content: string; + location: string; +} + +// Rename goal + +export const renameGoalRequest = "divinity/renameGoal"; + +export interface RenameGoalParams { + goalName: string; + newName: string; + projectUid: string; +} + +export interface RenameGoalResult extends WorkspaceEdit { + error?: string; +} + +// Move goal + +export const moveGoalRequest = "divinity/moveGoal"; + +export interface MoveGoalParams { + goalName: string; + newParent: string; + projectUid: string; +} + +export interface MoveGoalResult extends WorkspaceEdit { + error?: string; +} diff --git a/syntaxes/divinity-story-div.language-configuration.json b/syntaxes/divinity-story-div.language-configuration.json new file mode 100644 index 0000000..b6b70e0 --- /dev/null +++ b/syntaxes/divinity-story-div.language-configuration.json @@ -0,0 +1,16 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": ["/*", "*/"] + }, + "brackets": [["{", "}"], ["[", "]"], ["(", ")"]], + "autoClosingPairs": [["{", "}"], ["[", "]"], ["(", ")"], ["\"", "\""]], + "surroundingPairs": [["{", "}"], ["[", "]"], ["(", ")"], ["\"", "\""]], + "folding": { + "offSide": true, + "markers": { + "start": "^\\s*//REGION", + "end": "^\\s*//END_REGION" + } + } +} diff --git a/syntaxes/divinity-story-div.tmLanguage.json b/syntaxes/divinity-story-div.tmLanguage.json new file mode 100644 index 0000000..8588d98 --- /dev/null +++ b/syntaxes/divinity-story-div.tmLanguage.json @@ -0,0 +1,96 @@ +{ + "$schema": + "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "Divinity story div", + "scopeName": "text.divinity.storydiv", + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#keywords" + }, + { + "include": "#strings" + } + ], + "repository": { + "comments": { + "patterns": [ + { + "name": "markup.bold.osiris", + "match": "^\\s*//(REGION|END_REGION).*" + }, + { + "name": "comment.line.double-slash.osiris", + "match": "//.*" + }, + { + "name": "comment.block.osiris", + "begin": "/\\*", + "end": "\\*/" + } + ] + }, + "keywords": { + "patterns": [ + { + "name": "support.other.osiris", + "match": "^(Version|SubGoalCombiner|ParentTargetEdge).*$" + }, + { + "name": "support.type.osiris", + "match": "\\([A-Z]+\\)" + }, + { + "name": "keyword.control.osiris", + "match": "\\b(AND|IF|NOT|PROC|THEN|QRY)\\b" + }, + { + "name": "keyword.control.osiris", + "match": "\\bNOT\\b" + }, + { + "name": "keyword.other.osiris", + "match": "^(ENDEXITSECTION|EXITSECTION|INITSECTION|KBSECTION)$" + }, + { + "name": "constant.numeric.osiris", + "match": "\\b([+-]?[0-9]*\\.[0-9]*)|([+-]?[0-9]+)\\b" + }, + { + "name": "constant.character.osiris", + "match": + "\\b(CHARACTERGUID|GUIDSTRING|ITEMGUID|SPLINEGUID|TRIGGERGUID)_[A-Za-z0-9_-]+\\b" + }, + { + "name": "variable.parameter.osiris", + "match": "\\b_[A-Za-z0-9_]*\\b" + }, + { + "name": "variable.other.db.osiris", + "match": "\\bDB_[A-Za-z0-9_-]+\\b" + }, + { + "match": "\\b([A-Za-z_][A-Za-z0-9_]*)\\(", + "captures": { + "1": { + "name": "entity.name.function.osiris" + } + } + } + ] + }, + "strings": { + "name": "string.quoted.double.osiris", + "begin": "\"", + "end": "\"", + "patterns": [ + { + "name": "constant.character.escape.osiris", + "match": "\\\\." + } + ] + } + } +} diff --git a/syntaxes/divinity-story-goal.language-configuration.json b/syntaxes/divinity-story-goal.language-configuration.json new file mode 100644 index 0000000..b6b70e0 --- /dev/null +++ b/syntaxes/divinity-story-goal.language-configuration.json @@ -0,0 +1,16 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": ["/*", "*/"] + }, + "brackets": [["{", "}"], ["[", "]"], ["(", ")"]], + "autoClosingPairs": [["{", "}"], ["[", "]"], ["(", ")"], ["\"", "\""]], + "surroundingPairs": [["{", "}"], ["[", "]"], ["(", ")"], ["\"", "\""]], + "folding": { + "offSide": true, + "markers": { + "start": "^\\s*//REGION", + "end": "^\\s*//END_REGION" + } + } +} diff --git a/syntaxes/divinity-story-goal.snippets.json b/syntaxes/divinity-story-goal.snippets.json new file mode 100644 index 0000000..bbcf0be --- /dev/null +++ b/syntaxes/divinity-story-goal.snippets.json @@ -0,0 +1,22 @@ +{ + "AND": { + "prefix": "AND", + "body": ["AND", "$0"], + "description": "And condition" + }, + "IF": { + "prefix": "IF", + "body": ["IF", "$0", "THEN"], + "description": "Rule definition" + }, + "PROC": { + "prefix": "PROC", + "body": ["PROC", "$0", "THEN"], + "description": "Procedure definition" + }, + "QRY": { + "prefix": "QRY", + "body": ["QRY", "$0", "THEN", "DB_NOOP(1);"], + "description": "Query definition" + } +} diff --git a/syntaxes/divinity-story-goal.tmLanguage.json b/syntaxes/divinity-story-goal.tmLanguage.json new file mode 100644 index 0000000..732246c --- /dev/null +++ b/syntaxes/divinity-story-goal.tmLanguage.json @@ -0,0 +1,90 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "Divinity story goal", + "scopeName": "text.divinity.storygoal", + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#keywords" + }, + { + "include": "#strings" + } + ], + "repository": { + "comments": { + "patterns": [ + { + "name": "markup.bold.osiris", + "match": "^\\s*//(REGION|END_REGION).*" + }, + { + "name": "comment.line.double-slash.osiris", + "match": "//.*" + }, + { + "name": "comment.block.osiris", + "begin": "/\\*", + "end": "\\*/" + } + ] + }, + "keywords": { + "patterns": [ + { + "name": "support.other.osiris", + "match": "^(Version|SubGoalCombiner|ParentTargetEdge).*$" + }, + { + "name": "support.type.osiris", + "match": "\\([A-Z]+\\)" + }, + { + "name": "keyword.control.osiris", + "match": "\\b(AND|IF|NOT|PROC|THEN|QRY)\\b" + }, + { + "name": "keyword.other.osiris", + "match": "^(ENDEXITSECTION|EXITSECTION|INITSECTION|KBSECTION)$" + }, + { + "name": "constant.numeric.osiris", + "match": "\\b([+-]?[0-9]*\\.[0-9]*)|([+-]?[0-9]+)\\b" + }, + { + "name": "variable.parameter.osiris", + "match": "\\b_[A-Za-z0-9_]*\\b" + }, + { + "name": "variable.other.db.osiris", + "match": "\\bDB_[A-Za-z0-9_-]+\\b" + }, + { + "match": "\\b([A-Za-z_][A-Za-z0-9_]*)\\(", + "captures": { + "1": { + "name": "entity.name.function.osiris" + } + } + }, + { + "name": "constant.character.osiris", + "match": "\\b[A-Za-z0-9][A-Za-z0-9_-]*\\b" + } + ] + }, + "strings": { + "name": "string.quoted.double.osiris", + "begin": "\"", + "end": "\"", + "patterns": [ + { + "name": "constant.character.escape.osiris", + "match": "\\\\." + } + ] + } + } +} diff --git a/test/fixtures/analyzer.txt b/test/fixtures/analyzer.txt new file mode 100644 index 0000000..051a081 --- /dev/null +++ b/test/fixtures/analyzer.txt @@ -0,0 +1,242 @@ +Version 1 +SubGoalCombiner SGC_AND + +INITSECTION + +DB_String("IAmAGUID_12345678-1234-1234-1234-12345678abcd"); +// DB_StringGuid(IAmAGUIDToo_55555555-5555-5555-5555-555555555555); +DB_Int(1234); +// DB_Float(123.456); + +// ERR! [11] Intrinsic type of column 1 of DB_BadInference differs: Integer vs Integer64 +DB_BadInference(444); +DB_BadInference((INTEGER64)444); + +// WARN [23] Name of database "BaaadDB" should start with the prefix "DB" +BaaadDB(123); + +// ERR! [11] Intrinsic type of column 1 of Call "CharacterFreeze" differs: GuidString vs String +CharacterFreeze("hahah"); + +// WARN [25] Database "DB_Unused1(1)" is written to, but is never used in a rule +DB_Unused1(1); + +DB_CharacterGuid((CHARACTERGUID)55555555-5555-5555-5555-555555555555); +DB_ItemGuid((ITEMGUID)55555555-5555-5555-5555-555555555555); + +KBSECTION + +IF +DB_String(_Str) +AND +// ERR! [11] Rule variable _Str of type String cannot be casted to Integer +DB_Int(_Str) +THEN +DB_NOOP(1); + +// Call rule test +// ERR! [17] Initial rule condition can only be an event or a DB; "CharacterFreeze(1)" is a Call +IF +CharacterFreeze(_) +THEN +// OK +DB_NOOP(1); +// OK +NOT DB_NOOP(1); +// OK +CharacterFreeze(55555555-5555-5555-5555-555555555555); +// ERR! [16] KB rule NOT actions can only reference databases; "CharacterFreeze(1)" is a Call +NOT CharacterFreeze(55555555-5555-5555-5555-555555555555); +// ERR! [15] KB rule actions can only reference databases, calls and PROCs; "RealMin(3)" is a Query +RealMin(1.0, 1.0, 1.0); + +// OK +IF +TradeEnds(_CharA, _CharB) +THEN +DB_NOOP(1); + +// Event in 2nd condition check +IF +TradeEnds(_CharA, _CharB) +// ERR! [18] Subsequent rule conditions can only be queries or DBs; "TradeEnds(2)" is a Event +AND +TradeEnds(_CharA, _CharB) +THEN +DB_NOOP(1); + +// OK +PROC +ProcName((STRING)_Asd) +THEN +DB_NOOP(1); + +// ERR! [17] Initial proc condition can only be a PROC name; "CharacterFreeze(1)" is a Call +PROC +CharacterFreeze((STRING)_Asd) +THEN +DB_NOOP(1); + +// OK +QRY +QryName((STRING)_Asd) +THEN +DB_NOOP(1); + +// BAD, incompatible with first declaration +QRY +// ERR! [11] Intrinsic type of parameter 1 of UserQuery "QryName" differs: String vs Integer +QryName((INTEGER)_Asd) +THEN +DB_NOOP(1); + +// ERR! [17] Initial query condition can only be a user-defined QRY name; "RealMin(3)" is a Query +QRY +RealMin(_Arg1, _Arg2, _Arg3) +THEN +DB_NOOP(1); + +// Alias type cast warning check +IF +DB_CharacterGuid(_CG) +AND +DB_ItemGuid(_IG) +AND +// WARN [11] GUID alias cast - LHS/RHS differs: 6 vs 7 +_CG == _IG +THEN +DB_NOOP(1); + +// Alias type cast warning check 2 +IF +DB_CharacterGuid(_CG) +AND +// WARN [11] GUID alias cast: Rule variable _CG of type 6 casted to 7 +DB_ItemGuid(_CG) +THEN +DB_NOOP(1); + +// Alias type cast warning check 3 +IF +DB_CharacterGuid(_CG) +THEN +// WARN [11] GUID alias cast: Rule variable _CG of type 6 casted to 7 +NOT DB_ItemGuid(_CG); + +// Illogical string comparison warning +IF +DB_String(_CG) +AND +// WARN [20] String comparison using operator Greater - probably a mistake? +_CG > "asdf" +THEN +DB_NOOP(1); + +// Bad constant type +IF +// WARN [21] GUID constant "ITEMGUID_12341234-1234-1234-1234-123412341234" has inferred type CHARACTERGUID +DB_CharacterGuid((CHARACTERGUID)ITEMGUID_12341234-1234-1234-1234-123412341234) +THEN +DB_NOOP(1); + +// OK +PROC +ProcGoodName(_ASD) +THEN +DB_NOOP(_ASD); + +// Bad PROC naming convention +PROC +// WARN [23] Name of PROC "BadProcName(1)" should start with the prefix "PROC" +BadProcName(_ASD) +THEN +DB_NOOP(_ASD); + +// OK +QRY +QryGoodName((INTEGER)_ASD) +THEN +DB_NOOP(1); + +// Bad QUERY naming convention +QRY +// WARN [23] Name of Query "BadQryName(1)" should start with the prefix "QRY" +BadQryName((INTEGER)_ASD) +THEN +DB_NOOP(1); + +// Bad DB naming convention +IF +// WARN [23] Name of database "BaaadDB" should start with the prefix "DB" +BaaadDB((INTEGER)_Arg) +THEN +DB_NOOP(1); + +// Using unbound names 1 +IF +DB_CharacterGuid(_Asd) +AND +// ERR! [24] Variable _Undef11 was never bound, but was used as parameter _A in Query "IntegerSum(3)" +// ERR! [24] Variable _Undef12 was never bound, but was used as parameter _B in Query "IntegerSum(3)" +IntegerSum(_Undef11, _Undef12, _C) +THEN +DB_NOOP(1); + +// Using unbound names 2 +IF +DB_CharacterGuid(_Asd) +AND +// ERR! [24] Variable _Undef2 was unbound when used in a binary expression +_Asd != (CHARACTERGUID)_Undef2 +THEN +DB_NOOP(1); + +// Using unbound names 3 +IF +DB_CharacterGuid(_Asd) +THEN +// ERR! [24] Variable _Undef3 was never bound, but was used as parameter 0 in Database "DB_NOOP(1)" +DB_NOOP((INTEGER)_Undef3); + +// Using late-bound names 1 +IF +DB_CharacterGuid(_Asd) +AND +// ERR! [24] Variable _LateBound11 was not bound when used as parameter _A in Query "IntegerSum(3)" +// ERR! [24] Variable _LateBound12 was not bound when used as parameter _B in Query "IntegerSum(3)" +IntegerSum(_LateBound11, _LateBound12, _C) +AND +DB_Int(_LateBound11) +AND +DB_Int(_LateBound12) +THEN +DB_NOOP(1); + +// Using late-bound names 2 +IF +DB_CharacterGuid(_Asd) +AND +// ERR! [24] Variable _LateBound2 was unbound when used in a binary expression +_Asd != (CHARACTERGUID)_LateBound2 +AND +DB_CharacterGuid(_LateBound2) +THEN +DB_NOOP(1); + +// Check write-only/read-only DBs +IF +// WARN [25] Database "DB_Unused3(1)" is used in a rule, but is never written to +DB_Unused3((STRING)_Unused) +THEN +// WARN [25] Database "DB_Unused4(1)" is written to, but is never used in a rule +DB_Unused4(1); + + +EXITSECTION + +// WARN [25] Database "DB_Unused2(1)" is written to, but is never used in a rule +DB_Unused2(1); + +ENDEXITSECTION +// ERR! [08] Parent goal of "testbench" could not be resolved: "Nonexistent" +ParentTargetEdge "Nonexistent" diff --git a/test/fixtures/headers.div b/test/fixtures/headers.div new file mode 100644 index 0000000..7d9a88a --- /dev/null +++ b/test/fixtures/headers.div @@ -0,0 +1,19785 @@ +//Story header automatically generated. Do not modify! +option compile_trace +option debug_trace + +//Registered types: +// type {INTEGER, 1} // osiris predefined type +// type {INTEGER64, 2} // osiris predefined type +// type {REAL, 3} // osiris predefined type +// type {STRING, 4} // osiris predefined type +// type {GUIDSTRING, 5} // osiris predefined type +alias_type {CHARACTERGUID, 6, 5} +alias_type {ITEMGUID, 7, 5} +alias_type {TRIGGERGUID, 8, 5} +alias_type {SPLINEGUID, 9, 5} +alias_type {LEVELTEMPLATEGUID, 10, 5} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////Built-in calls and queries///////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +syscall SysCompleteGoal((STRING)_GoalTitle) (1,0,0,0) +syscall SysActivateGoal((STRING)_GoalTitle) (2,0,0,0) +syscall SysSetGoalSleeping((STRING)_GoalTitle) (3,0,0,0) +syscall SysClear((STRING)_Predicate,(INTEGER)_Arity) (5,0,0,0) +syscall SysLog((STRING)_Predicate,(INTEGER)_Arity) (4,0,0,0) + + +// _Status can have these values: +// INTERNAL_QUERY_GoalStatus_Sleeping 1 // goal is not yet active, but can become so +// INTERNAL_QUERY_GoalStatus_Active 2 // goal is active +// INTERNAL_QUERY_GoalStatus_Completed 3 // goal is completed (hence, not active) +sysquery SysStatus([in](STRING)_GoalTitle,[out](INTEGER)_Status) (100,0,0,0) +sysquery SysIsCompleted([in](STRING)_GoalTitle) (101,0,0,0) +sysquery SysIsActive([in](STRING)_GoalTitle) (102,0,0,0) +sysquery SysIsSleeping([in](STRING)_GoalTitle) (103,0,0,0) +// Was... functions are only valid if WasDefined() is true. +sysquery SysWasCompleted([in](STRING)_GoalTitle) (104,0,0,0) +sysquery SysWasActive([in](STRING)_GoalTitle) (105,0,0,0) +sysquery SysWasSleeping([in](STRING)_GoalTitle) (106,0,0,0) +sysquery SysWasDefined([in](STRING)_GoalTitle) (107,0,0,0) +sysquery SysCount([in](STRING)_Predicate,[in](INTEGER)_Arity,[out](INTEGER)_Count) (108,0,0,0) +sysquery SysStoryVersion([out](INTEGER)_Major,[out](INTEGER)_Minor,[out](INTEGER)_V3,[out](INTEGER)_V4) (109,0,0,0) + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +query IntegerSum([in](INTEGER)_A, [in](INTEGER)_B, [out](INTEGER)_Sum) (2,0,0,1) +query IntegerSubtract([in](INTEGER)_A, [in](INTEGER)_B, [out](INTEGER)_Result) (2,0,1,1) +query IntegerProduct([in](INTEGER)_A, [in](INTEGER)_B, [out](INTEGER)_Product) (2,0,2,1) +query IntegerDivide([in](INTEGER)_A, [in](INTEGER)_B, [out](INTEGER)_Quotient) (2,0,3,1) +query IntegerMin([in](INTEGER)_A, [in](INTEGER)_B, [out](INTEGER)_Minimum) (2,0,4,1) +query IntegerMax([in](INTEGER)_A, [in](INTEGER)_B, [out](INTEGER)_Maximum) (2,0,5,1) +query IntegerModulo([in](INTEGER)_Num, [in](INTEGER)_Mod, [out](INTEGER)_Return) (2,0,6,1) +query RealSum([in](REAL)_A, [in](REAL)_B, [out](REAL)_Sum) (2,0,7,1) +query RealSubtract([in](REAL)_A, [in](REAL)_B, [out](REAL)_Result) (2,0,8,1) +query RealProduct([in](REAL)_A, [in](REAL)_B, [out](REAL)_Product) (2,0,9,1) +query RealDivide([in](REAL)_A, [in](REAL)_B, [out](REAL)_Quotient) (2,0,10,1) +query RealMin([in](REAL)_A, [in](REAL)_B, [out](REAL)_Minimum) (2,0,11,1) +query RealMax([in](REAL)_A, [in](REAL)_B, [out](REAL)_Maximum) (2,0,12,1) +query Integer([in](REAL)_R, [out](INTEGER)_I) (2,0,13,1) +query Real([in](INTEGER)_I, [out](REAL)_R) (2,0,14,1) +query Random([in](INTEGER)_Modulo, [out](INTEGER)_Random) (2,0,15,1) +query CharacterHasTalent([in](CHARACTERGUID)_Character, [in](STRING)_Talent, [out](INTEGER)_Bool) (2,0,16,1) +call CharacterAddTalent((CHARACTERGUID)_Character, (STRING)_Talent) (1,0,17,1) +call CharacterRemoveTalent((CHARACTERGUID)_Character, (STRING)_Talent) (1,0,18,1) +query CharacterGetLevel([in](CHARACTERGUID)_Character, [out](INTEGER)_Level) (2,0,19,1) +query CharacterCanFight([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,20,1) +call CharacterFreeze((CHARACTERGUID)_Character) (1,0,21,1) +call CharacterUnfreeze((CHARACTERGUID)_Character) (1,0,22,1) +call CharacterCreateAtTrigger((TRIGGERGUID)_Trigger, (STRING)_TemplateId, (INTEGER)_PlaySpawn) (1,0,23,1) +call TemporaryCharacterCreateAtTrigger((TRIGGERGUID)_Trigger, (STRING)_TemplateId, (INTEGER)_PlaySpawn) (1,0,24,1) +query CharacterCreateAtPosition([in](REAL)_X, [in](REAL)_Y, [in](REAL)_Z, [in](STRING)_TemplateId, [in](INTEGER)_PlaySpawn, [out](CHARACTERGUID)_Created) (2,0,25,1) +query TemporaryCharacterCreateAtPosition([in](REAL)_X, [in](REAL)_Y, [in](REAL)_Z, [in](STRING)_TemplateId, [in](INTEGER)_PlaySpawn, [out](CHARACTERGUID)_Created) (2,0,26,1) +query CharacterCreateAtPositionOutOfSightTo([in](REAL)_X, [in](REAL)_Y, [in](REAL)_Z, [in](STRING)_TemplateId, [in](INTEGER)_Angle, [in](INTEGER)_PlaySpawn, [in](STRING)_Event, [out](CHARACTERGUID)_Created) (2,0,27,1) +query TemporaryCharacterCreateAtPositionOutOfSightTo([in](REAL)_X, [in](REAL)_Y, [in](REAL)_Z, [in](STRING)_TemplateId, [in](INTEGER)_Angle, [in](INTEGER)_PlaySpawn, [in](STRING)_Event, [out](CHARACTERGUID)_Created) (2,0,28,1) +query CharacterCreateOutOfSightToObject([in](STRING)_TemplateId, [in](CHARACTERGUID)_ToTarget, [in](GUIDSTRING)_FromObject, [in](INTEGER)_PlaySpawn, [in](STRING)_Event, [out](CHARACTERGUID)_Created) (2,0,29,1) +query TemporaryCharacterCreateOutOfSightToObject([in](STRING)_TemplateId, [in](CHARACTERGUID)_ToTarget, [in](GUIDSTRING)_FromObject, [in](INTEGER)_PlaySpawn, [in](STRING)_Event, [out](CHARACTERGUID)_Created) (2,0,30,1) +call OpenMessageBox((CHARACTERGUID)_Character, (STRING)_Message) (1,0,31,1) +call ShowCredits((CHARACTERGUID)_Character) (1,0,32,1) +call TeleportToPosition((GUIDSTRING)_SourceObject, (REAL)_X, (REAL)_Y, (REAL)_Z, (STRING)_Event, (INTEGER)_TeleportLinkedCharacters, (INTEGER)_ExcludePartyFollowers) (1,0,33,1) +call TeleportTo((GUIDSTRING)_SourceObject, (GUIDSTRING)_TargetObject, (STRING)_Event, (INTEGER)_TeleportLinkedCharacters, (INTEGER)_ExcludePartyFollowers) (1,0,34,1) +call CharacterMoveToPosition((CHARACTERGUID)_Character, (REAL)_X, (REAL)_Y, (REAL)_Z, (INTEGER)_Running, (STRING)_Event) (1,0,35,1) +call CharacterMoveTo((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (INTEGER)_Running, (STRING)_Event, (INTEGER)_IncreaseSpeed) (1,0,36,1) +call CharacterLookFromTrigger((CHARACTERGUID)_Character, (TRIGGERGUID)_Trigger, (INTEGER)_SnapToTarget) (1,0,37,1) +call CharacterEquipItem((CHARACTERGUID)_Character, (ITEMGUID)_Item) (1,0,38,1) +call TransferItemsToCharacter((CHARACTERGUID)_Character, (CHARACTERGUID)_ToCharacter) (1,0,39,1) +call TransferItemsToParty((CHARACTERGUID)_Character) (1,0,40,1) +call TransferItemsToUser((CHARACTERGUID)_Character) (1,0,41,1) +call CharacterUnequipItem((CHARACTERGUID)_Character, (ITEMGUID)_Item) (1,0,42,1) +call CharacterFollowCharacter((CHARACTERGUID)_Character, (CHARACTERGUID)_ToCharacter) (1,0,43,1) +call CharacterStopFollow((CHARACTERGUID)_Character) (1,0,44,1) +call CharacterTeleportPartiesToTriggerWithMovie((TRIGGERGUID)_Trigger, (STRING)_Event, (STRING)_Movie) (1,0,45,1) +call CharacterTeleportPartiesToTriggerWithMovieRequestCallback((TRIGGERGUID)_Trigger, (STRING)_Event) (1,0,46,1) +call CharacterSetTeleportMovie((INTEGER)_UserId, (STRING)_Movie) (1,0,47,1) +call CharacterTeleportPartiesToTrigger((TRIGGERGUID)_Trigger, (STRING)_Event) (1,0,48,1) +call CharacterClearTradeGeneratedItems((CHARACTERGUID)_Character) (1,0,49,1) +call CharacterSetCustomTradeTreasure((CHARACTERGUID)_Character, (STRING)_Treasure) (1,0,50,1) +call GenerateItems((CHARACTERGUID)_Player, (CHARACTERGUID)_Trader) (1,0,51,1) +call CharacterGiveReward((CHARACTERGUID)_Player, (STRING)_Treasure, (INTEGER)_Identified) (1,0,52,1) +call CharacterGiveQuestReward((CHARACTERGUID)_Player, (STRING)_Quest, (STRING)_RewardState) (1,0,53,1) +call CharacterDie((CHARACTERGUID)_Character, (INTEGER)_GenerateTreasure, (STRING)_DeathType, (GUIDSTRING)_Source) (1,0,54,1) +call CharacterDieImmediate((CHARACTERGUID)_Character, (INTEGER)_GenerateTreasure, (STRING)_DeathType, (GUIDSTRING)_Source) (1,0,55,1) +call CharacterAddSkill((CHARACTERGUID)_Character, (STRING)_Skill, (INTEGER)_ShowNotification) (1,0,56,1) +call CharacterRemoveSkill((CHARACTERGUID)_Character, (STRING)_Skill) (1,0,57,1) +query CharacterHasSkill([in](CHARACTERGUID)_Character, [in](STRING)_Skill, [out](INTEGER)_Bool) (2,0,58,1) +call CharacterAddAttributePoint((CHARACTERGUID)_Character, (INTEGER)_Amount) (1,0,59,1) +query CharacterGetAttributePoints([in](CHARACTERGUID)_Character, [out](INTEGER)_Amount) (2,0,60,1) +call CharacterAddAbilityPoint((CHARACTERGUID)_Character, (INTEGER)_Amount) (1,0,61,1) +call CharacterAddCivilAbilityPoint((CHARACTERGUID)_Character, (INTEGER)_Amount) (1,0,62,1) +call CharacterAddActionPoints((CHARACTERGUID)_Character, (INTEGER)_Amount) (1,0,63,1) +query CharacterGetAbilityPoints([in](CHARACTERGUID)_Character, [out](INTEGER)_Amount) (2,0,64,1) +query CharacterGetCivilAbilityPoints([in](CHARACTERGUID)_Character, [out](INTEGER)_Amount) (2,0,65,1) +call CharacterAddTalentPoint((CHARACTERGUID)_Character, (INTEGER)_Amount) (1,0,66,1) +query CharacterGetTalentPoints([in](CHARACTERGUID)_Character, [out](INTEGER)_Amount) (2,0,67,1) +query CharacterGetBaseSourcePoints([in](CHARACTERGUID)_Character, [out](INTEGER)_Amount) (2,0,68,1) +query CharacterGetSourcePoints([in](CHARACTERGUID)_Character, [out](INTEGER)_Amount) (2,0,69,1) +query CharacterGetMaxSourcePoints([in](CHARACTERGUID)_Character, [out](INTEGER)_Amount) (2,0,70,1) +call CharacterResurrect((CHARACTERGUID)_Character) (1,0,71,1) +call CharacterResurrectAndResetXPReward((CHARACTERGUID)_Character) (1,0,72,1) +call CharacterResurrectCustom((CHARACTERGUID)_Character, (STRING)_ResurrectAnimation) (1,0,73,1) +query CharacterGetReservedUserID([in](CHARACTERGUID)_Character, [out](INTEGER)_User) (2,0,74,1) +query GetCurrentCharacter([in](INTEGER)_User, [out](CHARACTERGUID)_Character) (2,0,75,1) +query CharacterIsControlled([in](CHARACTERGUID)_Character, [out](INTEGER)_IsControlled) (2,0,76,1) +query CharacterGetGold([in](CHARACTERGUID)_Character, [out](INTEGER)_Count) (2,0,77,1) +call CharacterAddGold((CHARACTERGUID)_Character, (INTEGER)_Count) (1,0,78,1) +call PartyAddGold((CHARACTERGUID)_Character, (INTEGER)_Count) (1,0,79,1) +query PartyGetGold([in](CHARACTERGUID)_Character, [out](INTEGER)_Gold) (2,0,80,1) +call UserAddGold((CHARACTERGUID)_Character, (INTEGER)_Count) (1,0,81,1) +query UserGetGold([in](CHARACTERGUID)_Character, [out](INTEGER)_Gold) (2,0,82,1) +call CharacterIncreaseSocialStat((CHARACTERGUID)_Character, (STRING)_Id) (1,0,83,1) +call CharacterDecreaseSocialStat((CHARACTERGUID)_Character, (STRING)_Id) (1,0,84,1) +call CharacterSetSpectating((CHARACTERGUID)_Character, (INTEGER)_Spectating) (1,0,85,1) +query CharacterIsSpectating([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,86,1) +query CharacterCanSee([in](CHARACTERGUID)_Character, [in](GUIDSTRING)_Target, [out](INTEGER)_Bool) (2,0,87,1) +call CharacterSetCustomName((CHARACTERGUID)_Character, (STRING)_Text) (1,0,88,1) +call CharacterAppear((CHARACTERGUID)_Character, (INTEGER)_PlaySpawn, (STRING)_Event) (1,0,89,1) +call CharacterAppearCustom((CHARACTERGUID)_Character, (STRING)_Animation, (STRING)_Event) (1,0,90,1) +call CharacterAppearAt((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (INTEGER)_PlaySpawn, (STRING)_Event) (1,0,91,1) +call CharacterAppearAtCustom((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (STRING)_Animation, (STRING)_Event) (1,0,92,1) +call CharacterAppearAtPosition((CHARACTERGUID)_Character, (REAL)_X, (REAL)_Y, (REAL)_Z, (INTEGER)_PlaySpawn, (STRING)_Event) (1,0,93,1) +call CharacterAppearAtPositionCustom((CHARACTERGUID)_Character, (REAL)_X, (REAL)_Y, (REAL)_Z, (STRING)_Animation, (STRING)_Event) (1,0,94,1) +call CharacterAppearOutOfSightTo((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (INTEGER)_Angle, (INTEGER)_PlaySpawn, (STRING)_Event) (1,0,95,1) +call CharacterAppearOutOfSightToCustom((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (INTEGER)_Angle, (STRING)_Animation, (STRING)_Event) (1,0,96,1) +call CharacterAppearOutOfSightToObject((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (GUIDSTRING)_Object, (INTEGER)_PlaySpawn, (STRING)_Event) (1,0,97,1) +call CharacterAppearOutOfSightToObjectCustom((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (GUIDSTRING)_Object, (STRING)_Animation, (STRING)_Event) (1,0,98,1) +call CharacterAppearOnTrailOutOfSightTo((CHARACTERGUID)_Character, (CHARACTERGUID)_Target, (INTEGER)_Angle, (INTEGER)_PlaySpawn, (STRING)_Event) (1,0,99,1) +call CharacterAppearOnTrailOutOfSightToCustom((CHARACTERGUID)_Character, (CHARACTERGUID)_Target, (INTEGER)_Angle, (STRING)_Animation, (STRING)_Event) (1,0,100,1) +call CharacterAppearOnTrailOutOfSightToObject((CHARACTERGUID)_Character, (CHARACTERGUID)_Target, (GUIDSTRING)_Object, (INTEGER)_PlaySpawn, (STRING)_Event) (1,0,101,1) +call CharacterAppearOnTrailOutOfSightToObjectCustom((CHARACTERGUID)_Character, (CHARACTERGUID)_Target, (GUIDSTRING)_Object, (STRING)_Animation, (STRING)_Event) (1,0,102,1) +call CharacterAppearAtPositionOutOfSightTo((CHARACTERGUID)_Character, (REAL)_X, (REAL)_Y, (REAL)_Z, (INTEGER)_Angle, (INTEGER)_PlaySpawn, (STRING)_Event) (1,0,103,1) +call CharacterAppearAtPositionOutOfSightToCustom((CHARACTERGUID)_Character, (REAL)_X, (REAL)_Y, (REAL)_Z, (INTEGER)_Angle, (STRING)_Animation, (STRING)_Event) (1,0,104,1) +call CharacterAppearAtPositionOutOfSightToObject((CHARACTERGUID)_Character, (REAL)_X, (REAL)_Y, (REAL)_Z, (GUIDSTRING)_Object, (INTEGER)_PlaySpawn, (STRING)_Event) (1,0,105,1) +call CharacterAppearAtPositionOutOfSightToObjectCustom((CHARACTERGUID)_Character, (REAL)_X, (REAL)_Y, (REAL)_Z, (GUIDSTRING)_Object, (STRING)_Animation, (STRING)_Event) (1,0,106,1) +call CharacterDisappearOutOfSight((CHARACTERGUID)_Character, (INTEGER)_Angle, (INTEGER)_Running, (STRING)_Event, (INTEGER)_IncreaseSpeed) (1,0,107,1) +call CharacterDisappearOutOfSightToObject((CHARACTERGUID)_Character, (GUIDSTRING)_Object, (INTEGER)_Running, (STRING)_Event, (INTEGER)_IncreaseSpeed) (1,0,108,1) +call CharacterFleeOutOfSight((CHARACTERGUID)_Character, (STRING)_Event) (1,0,109,1) +call CharacterAttack((CHARACTERGUID)_Character, (GUIDSTRING)_Target) (1,0,110,1) +query CharacterAddToCharacterCreation([in](CHARACTERGUID)_Character, [in](INTEGER)_Respec, [out](INTEGER)_Success) (2,0,111,1) +query GameMasterAddToCharacterCreation([in](CHARACTERGUID)_Character, [in](INTEGER)_Respec, [out](INTEGER)_Success) (2,0,112,1) +call CharacterMakePlayer((CHARACTERGUID)_TargetCharacter, (CHARACTERGUID)_OwnerCharacter) (1,0,113,1) +call CharacterRecruitCharacter((CHARACTERGUID)_Character, (CHARACTERGUID)_Character) (1,0,114,1) +call CharacterAssign((INTEGER)_UserID) (1,0,115,1) +call CharacterAssignToUser((INTEGER)_UserID, (CHARACTERGUID)_Character) (1,0,116,1) +call CharacterMakeCompanion((CHARACTERGUID)_Character, (CHARACTERGUID)_Character) (1,0,117,1) +call CharacterMakeNPC((CHARACTERGUID)_Character) (1,0,118,1) +call CharacterAddToParty((CHARACTERGUID)_Character, (CHARACTERGUID)_Character) (1,0,119,1) +call CharacterRemoveFromParty((CHARACTERGUID)_Character) (1,0,120,1) +call CharacterAddToPlayerCharacter((CHARACTERGUID)_Character, (CHARACTERGUID)_Owner) (1,0,121,1) +call CharacterRemoveFromPlayerCharacter((CHARACTERGUID)_Character, (CHARACTERGUID)_Owner) (1,0,122,1) +call CharacterRemoveAllPartyFollowers((CHARACTERGUID)_Character) (1,0,123,1) +query CharacterIsPartyMember([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,124,1) +query CharacterIsInPartyWith([in](CHARACTERGUID)_Character, [in](CHARACTERGUID)_Target, [out](INTEGER)_Bool) (2,0,125,1) +query CharacterGetRelationToCharacter([in](CHARACTERGUID)_Character, [in](CHARACTERGUID)_OtherCharacter, [out](INTEGER)_Relation) (2,0,126,1) +call CharacterSetRelationIndivFactionToIndivFaction((CHARACTERGUID)_Character, (CHARACTERGUID)_OtherCharacter, (INTEGER)_Relation) (1,0,127,1) +call CharacterSetRelationIndivFactionToFaction((CHARACTERGUID)_Character, (STRING)_OtherFaction, (INTEGER)_Relation) (1,0,128,1) +call CharacterSetRelationFactionToIndivFaction((STRING)_Faction, (CHARACTERGUID)_OtherCharacter, (INTEGER)_Relation) (1,0,129,1) +call CharacterSetRelationFactionToFaction((STRING)_Faction, (STRING)_otherFaction, (INTEGER)_Relation) (1,0,130,1) +call CharacterSetTemporaryHostileRelation((CHARACTERGUID)_Character, (CHARACTERGUID)_OtherCharacter) (1,0,131,1) +call CharacterSetReactionPriority((CHARACTERGUID)_Character, (STRING)_Reaction, (INTEGER)_Priority) (1,0,132,1) +query CharacterGetAttitudeTowardsPlayer([in](CHARACTERGUID)_Character, [in](CHARACTERGUID)_Player, [out](INTEGER)_Attitude) (2,0,133,1) +query CharacterGetHitpointsPercentage([in](CHARACTERGUID)_Character, [out](INTEGER)_Percentage) (2,0,134,1) +call CharacterSetHitpointsPercentage((CHARACTERGUID)_Character, (INTEGER)_Percentage) (1,0,135,1) +query CharacterGetArmorPercentage([in](CHARACTERGUID)_Character, [out](INTEGER)_Percentage) (2,0,136,1) +call CharacterSetArmorPercentage((CHARACTERGUID)_Character, (INTEGER)_Percentage) (1,0,137,1) +query CharacterGetMagicArmorPercentage([in](CHARACTERGUID)_Character, [out](INTEGER)_Percentage) (2,0,138,1) +call CharacterSetMagicArmorPercentage((CHARACTERGUID)_Character, (INTEGER)_Percentage) (1,0,139,1) +call CharacterLookAt((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (INTEGER)_SnapToTarget) (1,0,140,1) +call CharacterLevelUp((CHARACTERGUID)_Character) (1,0,141,1) +call CharacterLevelUpTo((CHARACTERGUID)_Character, (INTEGER)_Level) (1,0,142,1) +call PartyAddActualExperience((CHARACTERGUID)_Character, (INTEGER)_XP) (1,0,143,1) +call PartyAddExperience((CHARACTERGUID)_Character, (INTEGER)_Act, (INTEGER)_ActPart, (INTEGER)_Gain) (1,0,144,1) +call PartyAddExplorationExperience((CHARACTERGUID)_Character, (INTEGER)_Act, (INTEGER)_ActPart, (INTEGER)_Gain) (1,0,145,1) +call CharacterAddExplorationExperience((CHARACTERGUID)_Character, (INTEGER)_Act, (INTEGER)_ActPart, (INTEGER)_Gain) (1,0,146,1) +call PartyAddCharismaExperience((CHARACTERGUID)_Character, (INTEGER)_Act, (INTEGER)_ActPart, (INTEGER)_Gain) (1,0,147,1) +call CharacterStatusText((CHARACTERGUID)_Character, (STRING)_Text) (1,0,148,1) +call CharacterEnteredSubRegion((CHARACTERGUID)_Character, (STRING)_Text) (1,0,149,1) +call CharacterDisplayTextWithParam((CHARACTERGUID)_Character, (STRING)_Text, (INTEGER)_Parameter) (1,0,150,1) +call CharacterSetImmortal((CHARACTERGUID)_Character, (INTEGER)_Bool) (1,0,151,1) +query CharacterGetHostCharacter([out](CHARACTERGUID)_Character) (2,0,152,1) +query CharacterGetDisplayName([in](CHARACTERGUID)_Character, [out](STRING)_stringHandle, [out](STRING)_referenceString) (2,0,153,1) +call CharacterFlushQueue((CHARACTERGUID)_Character) (1,0,154,1) +call CharacterPurgeQueue((CHARACTERGUID)_Character) (1,0,155,1) +call CharacterLaunchIterator((STRING)_Event) (1,0,156,1) +call CharacterLaunchIteratorAroundCharacter((CHARACTERGUID)_Character, (REAL)_Radius, (STRING)_Event) (1,0,157,1) +call CharacterSetCanTrade((CHARACTERGUID)_Trader, (INTEGER)_Bool) (1,0,158,1) +query CharacterCanTrade([in](CHARACTERGUID)_Trader, [out](INTEGER)_Bool) (2,0,159,1) +call CharacterSetStill((CHARACTERGUID)_Character) (1,0,160,1) +query CharacterIsInCombat([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,161,1) +query CharacterIsMoving([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,162,1) +query CharacterIsInFightMode([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,163,1) +call CharacterSetFightMode((CHARACTERGUID)_Character, (INTEGER)_Enabled, (INTEGER)_Immediately) (1,0,164,1) +call CharacterMakeStoryNpc((CHARACTERGUID)_Character, (INTEGER)_Bool) (1,0,165,1) +call CharacterStopAllEffectsWithName((CHARACTERGUID)_Character, (STRING)_FxName) (1,0,166,1) +call CharacterPickupItem((CHARACTERGUID)_Character, (ITEMGUID)_Item, (STRING)_Event) (1,0,167,1) +call CharacterItemSetEvent((CHARACTERGUID)_Character, (ITEMGUID)_Item, (STRING)_Event) (1,0,168,1) +call CharacterCharacterSetEvent((CHARACTERGUID)_Character, (CHARACTERGUID)_Character, (STRING)_Event) (1,0,169,1) +call CharacterUseItem((CHARACTERGUID)_Character, (ITEMGUID)_Item, (STRING)_Event) (1,0,170,1) +call CharacterMoveItemToTrigger((CHARACTERGUID)_Character, (ITEMGUID)_Item, (TRIGGERGUID)_Trigger, (INTEGER)_Amount, (STRING)_Event) (1,0,171,1) +query CharacterConsume([in](CHARACTERGUID)_Character, [in](STRING)_Potion, [out](INTEGER64)_ConsumeHandle) (2,0,172,1) +call CharacterUnconsume((CHARACTERGUID)_Character, (INTEGER64)_ConsumeHandle) (1,0,173,1) +call CharacterAddAttribute((CHARACTERGUID)_Character, (STRING)_Attribute, (INTEGER)_Value) (1,0,174,1) +call CharacterRemoveAttribute((CHARACTERGUID)_Character, (STRING)_Attribute, (INTEGER)_Value) (1,0,175,1) +query CharacterGetBaseAttribute([in](CHARACTERGUID)_Character, [in](STRING)_Attribute, [out](INTEGER)_Value) (2,0,176,1) +query CharacterGetAttribute([in](CHARACTERGUID)_Character, [in](STRING)_Attribute, [out](INTEGER)_Value) (2,0,177,1) +call CharacterAddAbility((CHARACTERGUID)_Character, (STRING)_Ability, (INTEGER)_Value) (1,0,178,1) +call CharacterRemoveAbility((CHARACTERGUID)_Character, (STRING)_Ability, (INTEGER)_Value) (1,0,179,1) +query CharacterIsIncapacitated([in](CHARACTERGUID)_Character, [out](INTEGER)_Incapacitated) (2,0,180,1) +query CharacterGetAbility([in](CHARACTERGUID)_Character, [in](STRING)_Ability, [out](INTEGER)_Value) (2,0,181,1) +query CharacterGetBaseAbility([in](CHARACTERGUID)_Character, [in](STRING)_Ability, [out](INTEGER)_Value) (2,0,182,1) +query CharacterGetOwner([in](CHARACTERGUID)_Character, [out](CHARACTERGUID)_Owner) (2,0,183,1) +call ActivateTrade((CHARACTERGUID)_Player, (CHARACTERGUID)_Trader, (INTEGER)_CanRepair, (INTEGER)_CanIdentify, (INTEGER)_CanSell) (1,0,184,1) +call StartPickpocket((CHARACTERGUID)_Player, (CHARACTERGUID)_NPC, (INTEGER)_Success) (1,0,185,1) +call ExecuteDeal((CHARACTERGUID)_Character, (INTEGER)_Deal, (INTEGER)_AttitudeDiff) (1,0,186,1) +query CharacterGetEquippedWeapon([in](CHARACTERGUID)_Character, [out](GUIDSTRING)_ItemGUID) (2,0,187,1) +query CharacterGetEquippedShield([in](CHARACTERGUID)_Character, [out](GUIDSTRING)_ItemGUID) (2,0,188,1) +query CharacterGetEquippedItem([in](CHARACTERGUID)_Character, [in](STRING)_Slotname, [out](GUIDSTRING)_ItemGUID) (2,0,189,1) +call CharacterSetFollowCharacter((CHARACTERGUID)_Character, (CHARACTERGUID)_CharacterToFollow) (1,0,190,1) +call CharacterAttachToGroup((CHARACTERGUID)_Src, (CHARACTERGUID)_Target) (1,0,191,1) +call CharacterDetachFromGroup((CHARACTERGUID)_Character) (1,0,192,1) +query CharactersAreGrouped([in](CHARACTERGUID)_Character1, [in](CHARACTERGUID)_Character2, [out](INTEGER)_Bool) (2,0,193,1) +query CharacterGetInventoryGoldValue([in](CHARACTERGUID)_Character, [out](INTEGER)_Value) (2,0,194,1) +query CharacterGetItemTemplateCount([in](CHARACTERGUID)_Character, [in](STRING)_ItemTemplate, [out](INTEGER)_Value) (2,0,195,1) +call CharacterAddAttitudeTowardsPlayer((CHARACTERGUID)_Character, (CHARACTERGUID)_Player, (INTEGER)_Delta) (1,0,196,1) +query CharacterIsFemale([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,197,1) +call CharacterSetCanSpotSneakers((CHARACTERGUID)_Character, (INTEGER)_CanSpotSneakers) (1,0,198,1) +query CharacterCanSpotSneakers([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,199,1) +call CharacterMoveWeaponsToContainer((CHARACTERGUID)_Character, (ITEMGUID)_Container) (1,0,200,1) +call CharacterLockAbility((CHARACTERGUID)_Character, (STRING)_Ability) (1,0,201,1) +call CharacterUnlockAbility((CHARACTERGUID)_Character, (STRING)_Ability) (1,0,202,1) +call CharacterUnlockRecipe((CHARACTERGUID)_Character, (STRING)_RecipeID, (INTEGER)_ShowNotification) (1,0,203,1) +query CharacterIsDead([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,204,1) +query CharacterIsDeadOrFeign([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,205,1) +call CharacterSetAnimationOverride((CHARACTERGUID)_Character, (STRING)_Animation) (1,0,206,1) +call CharacterSetAnimationSetOverride((CHARACTERGUID)_Character, (STRING)_AnimationSetResource) (1,0,207,1) +call PartySetIdentifyPriceModifier((CHARACTERGUID)_Character, (CHARACTERGUID)_PartyMember, (INTEGER)_Modifier) (1,0,208,1) +call PartySetRepairPriceModifier((CHARACTERGUID)_Character, (CHARACTERGUID)_PartyMember, (INTEGER)_Modifier) (1,0,209,1) +call PartySetShopPriceModifier((CHARACTERGUID)_Character, (CHARACTERGUID)_PartyMember, (INTEGER)_Modifier) (1,0,210,1) +call SetTagPriceModifier((CHARACTERGUID)_Character, (STRING)_Tag, (INTEGER)_Modifier) (1,0,211,1) +call CharacterResetCooldowns((CHARACTERGUID)_Character) (1,0,212,1) +call CharacterShowStoryElementUI((CHARACTERGUID)_Character, (INTEGER)_Type, (STRING)_UIInstance) (1,0,213,1) +call CharacterCloseStoryElementUI((CHARACTERGUID)_Character, (INTEGER)_Type, (STRING)_UIInstance) (1,0,214,1) +call CharacterSendGlobalCombatCounter((CHARACTERGUID)_Character, (INTEGER)_Turn) (1,0,215,1) +call CharacterPlayHUDSound((CHARACTERGUID)_Character, (STRING)_Sound) (1,0,216,1) +call CharacterRegisterCrime((CHARACTERGUID)_Player, (STRING)_CrimeType, (GUIDSTRING)_Evidence, (CHARACTERGUID)_Witness, (INTEGER)_CrimeID) (1,0,217,1) +call CharacterRegisterCrimeWithPosition((CHARACTERGUID)_Player, (STRING)_CrimeType, (GUIDSTRING)_Evidence, (CHARACTERGUID)_Witness, (REAL)_X, (REAL)_Y, (REAL)_Z, (INTEGER)_CrimeID) (1,0,218,1) +call CharacterStopCrime((CHARACTERGUID)_Player, (STRING)_CrimeType, (GUIDSTRING)_Evidence) (1,0,219,1) +call CharacterStopCrimeWithID((CHARACTERGUID)_Player, (INTEGER)_Crime) (1,0,220,1) +call CharacterIgnoreCharacterActiveCrimes((CHARACTERGUID)_Character, (CHARACTERGUID)_Player, (REAL)_Timer) (1,0,221,1) +call CharacterRemoveSummons((CHARACTERGUID)_Character, (INTEGER)_Die) (1,0,222,1) +call CharacterLinkGhost((CHARACTERGUID)_Character, (CHARACTERGUID)_Ghost) (1,0,223,1) +call CharacterUnlinkGhost((CHARACTERGUID)_Character, (CHARACTERGUID)_Ghost) (1,0,224,1) +call DestroyGhost((CHARACTERGUID)_Ghost) (1,0,225,1) +call CharacterUseSkill((CHARACTERGUID)_Character, (STRING)_SkillID, (GUIDSTRING)_Target, (INTEGER)_ForceResetCooldown, (INTEGER)_IgnoreHasSkill, (INTEGER)_IgnoreChecks) (1,0,226,1) +call CharacterUseSkillAtPosition((CHARACTERGUID)_Character, (STRING)_SkillID, (REAL)_X, (REAL)_Y, (REAL)_Z, (INTEGER)_ForceResetCooldown, (INTEGER)_IgnoreHasSkill) (1,0,227,1) +call CharacterDisableCrime((CHARACTERGUID)_Character, (STRING)_Crime) (1,0,228,1) +query CharacterIsCrimeEnabled([in](CHARACTERGUID)_Character, [in](STRING)_Crime, [out](INTEGER)_Bool) (2,0,229,1) +query CharacterGetCrimeRegion([in](CHARACTERGUID)_Character, [out](STRING)_Region) (2,0,230,1) +call CharacterEnableCrime((CHARACTERGUID)_Character, (STRING)_Crime) (1,0,231,1) +call CharacterDisableAllCrimes((CHARACTERGUID)_Character) (1,0,232,1) +call CharacterEnableAllCrimes((CHARACTERGUID)_Character) (1,0,233,1) +call CharacterEnableCrimeWarnings((CHARACTERGUID)_Character, (INTEGER)_Enable) (1,0,234,1) +query CharacterGetCrimeDialog([in](CHARACTERGUID)_Character, [out](INTEGER)_InstanceID) (2,0,235,1) +call CharacterRemoveTension((CHARACTERGUID)_Player) (1,0,236,1) +query CharacterIsEnemy([in](CHARACTERGUID)_Character, [in](CHARACTERGUID)_OtherCharacter, [out](INTEGER)_Bool) (2,0,237,1) +query CharacterIsAlly([in](CHARACTERGUID)_Character, [in](CHARACTERGUID)_OtherCharacter, [out](INTEGER)_Bool) (2,0,238,1) +query CharacterIsNeutral([in](CHARACTERGUID)_Character, [in](CHARACTERGUID)_OtherCharacter, [out](INTEGER)_Bool) (2,0,239,1) +call CharacterAddSourcePoints((CHARACTERGUID)_Character, (INTEGER)_Amount) (1,0,240,1) +call CharacterOverrideMaxSourcePoints((CHARACTERGUID)_Character, (INTEGER)_Amount) (1,0,241,1) +call CharacterRemoveMaxSourcePointsOverride((CHARACTERGUID)_Character) (1,0,242,1) +call CharacterApplyPreset((CHARACTERGUID)_Character, (STRING)_Preset) (1,0,243,1) +call CharacterApplyHenchmanPreset((CHARACTERGUID)_Character, (STRING)_Preset) (1,0,244,1) +call CharacterApplyRacePreset((CHARACTERGUID)_Character, (STRING)_Preset) (1,0,245,1) +call CharacterMoveToAndTalk((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (STRING)_DialogID, (INTEGER)_IsAutomated, (STRING)_MoveID, (INTEGER)_Running, (REAL)_Timeout) (1,0,246,1) +call CharacterMoveToAndTalkRequestDialogFailed((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (STRING)_MoveId) (1,0,247,1) +call CharacterEnableWaypointUsage((CHARACTERGUID)_Character, (INTEGER)_Bool) (1,0,248,1) +query CharacterCanUseWaypoints([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,249,1) +query CharacterCanSeeGhost([in](CHARACTERGUID)_Character, [in](GUIDSTRING)_Ghost, [out](INTEGER)_Bool) (2,0,250,1) +query CharacterIsSummon([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,251,1) +query CharacterIsPartyFollower([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,252,1) +query CharacterIsPolymorphedInto([in](CHARACTERGUID)_Character, [in](STRING)_TargetRace, [out](INTEGER)_Bool) (2,0,253,1) +query CharacterIsPolymorphInteractionDisabled([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,254,1) +query CharacterGameMaster([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,255,1) +query CharacterIsPlayer([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,256,1) +query CharacterHasLinkedGhost([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,257,1) +call CharacterReservePolymorphShape((CHARACTERGUID)_Character, (STRING)_Race) (1,0,258,1) +call CharacterSetForceSynch((CHARACTERGUID)_Character, (INTEGER)_Bool) (1,0,259,1) +call CharacterSetForceUpdate((CHARACTERGUID)_Character, (INTEGER)_Bool) (1,0,260,1) +call CharacterTransform((CHARACTERGUID)_Character, (STRING)_ObjectTemplate, (INTEGER)_ReplaceScripts, (INTEGER)_ReplaceScale, (INTEGER)_ReplaceStats, (INTEGER)_ReplaceEquipment, (INTEGER)_ReplaceSkills, (INTEGER)_UseCustomLooks, (INTEGER)_ReleasePlayerData) (1,0,261,1) +call CharacterTransformAppearanceTo((CHARACTERGUID)_Character, (CHARACTERGUID)_Target, (INTEGER)_CopyEquipment, (INTEGER)_CopyDisplayNameAndIcon) (1,0,262,1) +call CharacterTransformAppearanceToWithEquipmentSet((CHARACTERGUID)_Character, (CHARACTERGUID)_Target, (STRING)_EquipmentSet, (INTEGER)_CopyDisplayNameAndIcon) (1,0,263,1) +query CharacterCanSpotCrimes([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,264,1) +call CharacterReceivedTag((CHARACTERGUID)_Character, (STRING)_Tag) (1,0,265,1) +call CharacterAddPreferredAiTargetTag((CHARACTERGUID)_Character, (STRING)_Tag) (1,0,266,1) +call CharacterRemovePreferredAiTargetTag((CHARACTERGUID)_Character, (STRING)_Tag) (1,0,267,1) +query CharacterGetRace([in](CHARACTERGUID)_Player, [in](INTEGER)_CanPolymorphOverride, [out](STRING)_Race) (2,0,268,1) +query CharacterGetOrigin([in](CHARACTERGUID)_Player, [in](INTEGER)_CanPolymorphOverride, [out](STRING)_Origin) (2,0,269,1) +query CharacterGetInstrument([in](CHARACTERGUID)_Player, [out](STRING)_Instrument) (2,0,270,1) +query CharacterGetHenchmanPresetPrice([in](CHARACTERGUID)_Owner, [in](STRING)_Preset, [out](INTEGER)_Price) (2,0,271,1) +call CharacterOriginIntroStopped((CHARACTERGUID)_Character) (1,0,272,1) +call CharacterSetDoNotFaceFlag((CHARACTERGUID)_Character, (INTEGER)_Value) (1,0,273,1) +call CharacterSetReadyCheckBlocked((CHARACTERGUID)_Character, (INTEGER)_Value) (1,0,274,1) +call CharacterSetCorpseLootable((CHARACTERGUID)_Character, (INTEGER)_Value) (1,0,275,1) +call CharacterSetDetached((CHARACTERGUID)_Character, (INTEGER)_Value) (1,0,276,1) +event CharacterDied((CHARACTERGUID)_Character) (3,0,277,1) +event CharacterResurrected((CHARACTERGUID)_Character) (3,0,278,1) +event CharacterDying((CHARACTERGUID)_Character) (3,0,279,1) +event CharacterTemplateDied((STRING)_TemplateName) (3,0,280,1) +event CharacterStatusAttempt((CHARACTERGUID)_Character, (STRING)_Status, (GUIDSTRING)_Causee) (3,0,281,1) +event CharacterStatusApplied((CHARACTERGUID)_Character, (STRING)_Status, (GUIDSTRING)_Causee) (3,0,282,1) +event CharacterStatusRemoved((CHARACTERGUID)_Character, (STRING)_Status, (GUIDSTRING)_Causee) (3,0,283,1) +event CharacterUsedItem((CHARACTERGUID)_Character, (ITEMGUID)_Item) (3,0,284,1) +event CharacterUsedItemTemplate((CHARACTERGUID)_Character, (STRING)_Template, (ITEMGUID)_Item) (3,0,285,1) +event CharacterUsedItemFailed((CHARACTERGUID)_Character, (ITEMGUID)_Item) (3,0,286,1) +event CharacterPreMovedItem((CHARACTERGUID)_Character, (ITEMGUID)_Item) (3,0,287,1) +event CharacterMovedItem((CHARACTERGUID)_Character, (ITEMGUID)_Item) (3,0,288,1) +event CharacterMovedItemTemplate((CHARACTERGUID)_Character, (STRING)_Template) (3,0,289,1) +event CharacterEnteredRegion((CHARACTERGUID)_Character, (STRING)_Region) (3,0,290,1) +event CharacterLeftRegion((CHARACTERGUID)_Character, (STRING)_Region) (3,0,291,1) +event CharacterSawCharacter((CHARACTERGUID)_Character, (CHARACTERGUID)_OtherCharacter) (3,0,292,1) +event CharacterSawSneakingCharacter((CHARACTERGUID)_Character, (CHARACTERGUID)_OtherCharacter) (3,0,293,1) +event CharacterLostSightOfCharacter((CHARACTERGUID)_Character, (CHARACTERGUID)_OtherCharacter) (3,0,294,1) +event CharacterBlockedBy((CHARACTERGUID)_Defender, (CHARACTERGUID)_AttackOwner, (CHARACTERGUID)_Attacker) (3,0,295,1) +event CharacterMissedBy((CHARACTERGUID)_Defender, (CHARACTERGUID)_AttackOwner, (CHARACTERGUID)_Attacker) (3,0,296,1) +event CharacterCriticalHitBy((CHARACTERGUID)_Defender, (CHARACTERGUID)_AttackOwner, (CHARACTERGUID)_Attacker) (3,0,297,1) +event CharacterKilledBy((CHARACTERGUID)_Defender, (CHARACTERGUID)_AttackOwner, (CHARACTERGUID)_Attacker) (3,0,298,1) +event CharacterTemplateKilledByCharacter((STRING)_CharacterTemplate, (CHARACTERGUID)_Killer) (3,0,299,1) +event CharacterStartAttackObject((GUIDSTRING)_Defender, (CHARACTERGUID)_AttackOwner, (CHARACTERGUID)_Attacker) (3,0,300,1) +event CharacterStartAttackPosition((REAL)_x, (REAL)_y, (REAL)_z, (CHARACTERGUID)_AttackOwner, (CHARACTERGUID)_Attacker) (3,0,301,1) +event CharacterChangedAlginmentToCharacter((CHARACTERGUID)_Character, (CHARACTERGUID)_OtherCharacter, (INTEGER)_NewRelation) (3,0,302,1) +event CharacterEnteredTrigger((CHARACTERGUID)_Character, (TRIGGERGUID)_Trigger) (3,0,303,1) +event CharacterReceivedDamage((CHARACTERGUID)_Character, (INTEGER)_Percentage, (GUIDSTRING)_Source) (3,0,304,1) +event CharacterVitalityChanged((CHARACTERGUID)_Character, (INTEGER)_Percentage) (3,0,305,1) +event CharacterLeftTrigger((CHARACTERGUID)_Character, (TRIGGERGUID)_Trigger) (3,0,306,1) +event CharacterPickpocketSuccess((CHARACTERGUID)_Player, (CHARACTERGUID)_NPC, (ITEMGUID)_Item, (INTEGER)_Amount) (3,0,307,1) +event CharacterAttitudeTowardsPlayerChanged((CHARACTERGUID)_Character, (CHARACTERGUID)_Player, (INTEGER)_NewAttitude) (3,0,308,1) +event ItemSendToHomesteadEvent((CHARACTERGUID)_Player, (ITEMGUID)_Item) (3,0,309,1) +event CharacterItemEvent((CHARACTERGUID)_Character, (ITEMGUID)_Item, (STRING)_Event) (3,0,310,1) +event CharacterUsedSkill((CHARACTERGUID)_Character, (STRING)_Skill, (STRING)_SkillType) (3,0,311,1) +event CharacterUsedSkillAtPosition((CHARACTERGUID)_Character, (REAL)_X, (REAL)_Y, (REAL)_Z, (STRING)_Skill, (STRING)_SkillType) (3,0,312,1) +event CharacterUsedSkillOnTarget((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (STRING)_Skill, (STRING)_SkillType) (3,0,313,1) +event CharacterUsedSkillOnZoneWithTarget((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (STRING)_Skill, (STRING)_SkillType) (3,0,314,1) +event CharacterUsedSkillInTrigger((CHARACTERGUID)_Character, (STRING)_Skill, (STRING)_SkillElement, (TRIGGERGUID)_Trigger) (3,0,315,1) +event CharacterLearnedSkill((CHARACTERGUID)_Character, (STRING)_Skill) (3,0,316,1) +event SkillCast((CHARACTERGUID)_Character, (STRING)_Skill, (STRING)_SkillElement) (3,0,317,1) +event RequestPickpocket((CHARACTERGUID)_Player, (CHARACTERGUID)_NPC) (3,0,318,1) +event CharacterPickpocketFailed((CHARACTERGUID)_Player, (CHARACTERGUID)_NPC) (3,0,319,1) +event CharacterLootedCharacterCorpse((CHARACTERGUID)_Player, (CHARACTERGUID)_Corpse) (3,0,320,1) +event RequestTrade((CHARACTERGUID)_Character, (CHARACTERGUID)_Trader) (3,0,321,1) +event HappyWithDeal((CHARACTERGUID)_Character, (CHARACTERGUID)_Trader, (INTEGER)_CharacterValue, (INTEGER)_TraderValue) (3,0,322,1) +event TradeEnds((CHARACTERGUID)_Character, (CHARACTERGUID)_Trader) (3,0,323,1) +event CharacterScriptFrameFinished((CHARACTERGUID)_Character, (STRING)_FrameID) (3,0,324,1) +event CharacterCharacterEvent((CHARACTERGUID)_Character1, (CHARACTERGUID)_Character2, (STRING)_Event) (3,0,325,1) +event CharacterRelationChangedTo((CHARACTERGUID)_Character, (CHARACTERGUID)_OtherCharacter, (INTEGER)_Attitude) (3,0,326,1) +event CharacterDestroyedItem((CHARACTERGUID)_Character, (ITEMGUID)_Item) (3,0,327,1) +event CharacterDestroyedItemTemplate((CHARACTERGUID)_Character, (STRING)_ItemTemplate) (3,0,328,1) +event CharacterDisplayTextEnded((CHARACTERGUID)_Character, (STRING)_DisplayText) (3,0,329,1) +event CharacterSetTemporaryRelationsFailed((CHARACTERGUID)_Character1, (CHARACTERGUID)_Character2) (3,0,330,1) +event CharacterMadePlayer((CHARACTERGUID)_Character) (3,0,331,1) +event CharacterLeveledUp((CHARACTERGUID)_Character) (3,0,332,1) +event CharacterUnlockedTalent((CHARACTERGUID)_Character, (STRING)_Talent) (3,0,333,1) +event CharacterLockedTalent((CHARACTERGUID)_Character, (STRING)_Talent) (3,0,334,1) +event MessageBoxClosed((CHARACTERGUID)_Character, (STRING)_Message) (3,0,335,1) +event TutorialBoxClosed((CHARACTERGUID)_Character, (STRING)_Message) (3,0,336,1) +event CharacterTraitChanged((CHARACTERGUID)_Character, (STRING)_Trait) (3,0,337,1) +event CharacterGuarded((CHARACTERGUID)_Character) (3,0,338,1) +event CharacterWentOnStage((CHARACTERGUID)_Character, (INTEGER)_Bool) (3,0,339,1) +event CharacterReservedUserIDChanged((CHARACTERGUID)_Character, (INTEGER)_UserID) (3,0,340,1) +event CharacterAddedToGroup((CHARACTERGUID)_Character) (3,0,341,1) +event CharacterDetachedFromGroup((CHARACTERGUID)_Character) (3,0,342,1) +event CharacterStartLockpickingItem((CHARACTERGUID)_Character, (ITEMGUID)_Item) (3,0,343,1) +event CharacterStoppedUsingItem((CHARACTERGUID)_Character, (ITEMGUID)_Item) (3,0,344,1) +event CharacterStoppedCombiningItems((CHARACTERGUID)_Character, (ITEMGUID)_ItemA, (ITEMGUID)_ItemB, (ITEMGUID)_ItemC, (ITEMGUID)_ItemD, (ITEMGUID)_ItemE) (3,0,345,1) +event CharacterTurnedToGhost((CHARACTERGUID)_Character, (CHARACTERGUID)_Ghost) (3,0,346,1) +event CharacterGhostDestroyed((CHARACTERGUID)_Character, (CHARACTERGUID)_Ghost) (3,0,347,1) +event CharacterGhostRevealed((CHARACTERGUID)_Character, (CHARACTERGUID)_Ghost) (3,0,348,1) +event CharacterOnCrimeSensibleActionNotification((CHARACTERGUID)_Character, (STRING)_CrimeRegion, (INTEGER)_CrimeID, (STRING)_PriortiyName, (STRING)_PrimaryDialog, (CHARACTERGUID)_Criminal1, (CHARACTERGUID)_Criminal2, (CHARACTERGUID)_Criminal3, (CHARACTERGUID)_Criminal4, (INTEGER)_IsPrimary) (3,0,349,1) +event CharacterSelectedAsBestUnavailableFallbackLead((CHARACTERGUID)_Character, (STRING)_CrimeRegion, (INTEGER)_UnavailableForCrimeID, (INTEGER)_BusyCrimeID, (CHARACTERGUID)_Criminal1, (CHARACTERGUID)_Criminal2, (CHARACTERGUID)_Criminal3, (CHARACTERGUID)_Criminal4) (3,0,350,1) +event CrimeIsRegistered((CHARACTERGUID)_Victim, (STRING)_CrimeType, (INTEGER)_CrimeID, (GUIDSTRING)_Evidence, (CHARACTERGUID)_Criminal1, (CHARACTERGUID)_Criminal2, (CHARACTERGUID)_Criminal3, (CHARACTERGUID)_Criminal4) (3,0,351,1) +event CharacterSelectedInCharCreation((CHARACTERGUID)_Character, (INTEGER)_UserID) (3,0,352,1) +event CharacterStartOriginIntroduction((CHARACTERGUID)_Character, (INTEGER)_UserID, (STRING)_Origin) (3,0,353,1) +event CharacterStopOriginIntroduction((CHARACTERGUID)_Character, (INTEGER)_UserID) (3,0,354,1) +event CharacterCreatedInArena((CHARACTERGUID)_Character, (INTEGER)_Team) (3,0,355,1) +event CharacterUsedSourcePoint((CHARACTERGUID)_Character) (3,0,356,1) +event SkillAdded((CHARACTERGUID)_Character, (STRING)_Skill, (INTEGER)_Learned) (3,0,357,1) +event SkillActivated((CHARACTERGUID)_Character, (STRING)_Skill) (3,0,358,1) +event SkillDeactivated((CHARACTERGUID)_Character, (STRING)_Skill) (3,0,359,1) +event CharacterTeleported((CHARACTERGUID)_Target, (CHARACTERGUID)_Cause, (REAL)_OldX, (REAL)_OldY, (REAL)_OldZ, (REAL)_NewX, (REAL)_NewY, (REAL)_NewZ, (STRING)_Skill) (3,0,360,1) +event CharacterMoveToAndTalkFailed((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (STRING)_MoveID) (3,0,361,1) +event CharacterMoveToAndTalkRequestDialog((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (STRING)_DialogID, (INTEGER)_IsAutomated, (STRING)_MoveID) (3,0,362,1) +event CharacterMoveToAndTalkRequestDialogFailedEvent((CHARACTERGUID)_Character, (GUIDSTRING)_Target, (STRING)_MoveId) (3,0,363,1) +event CharacterJoinedParty((CHARACTERGUID)_Character) (3,0,364,1) +event CharacterLeftParty((CHARACTERGUID)_Character) (3,0,365,1) +event CharacterLoadedInPreset((CHARACTERGUID)_Character) (3,0,366,1) +event CharacterPolymorphedInto((CHARACTERGUID)_Character, (STRING)_Race) (3,0,367,1) +event CharacterStoppedPolymorph((CHARACTERGUID)_Character) (3,0,368,1) +event CharacterTeleportToPyramid((CHARACTERGUID)_Character, (ITEMGUID)_Pyramid) (3,0,369,1) +event CharacterTeleportToWaypoint((CHARACTERGUID)_Character, (TRIGGERGUID)_Trigger) (3,0,370,1) +event CharacterTeleportToFleeWaypoint((CHARACTERGUID)_Character, (TRIGGERGUID)_Trigger) (3,0,371,1) +event CharacterStoleItem((CHARACTERGUID)_Character, (ITEMGUID)_Item, (REAL)_X, (REAL)_Y, (REAL)_Z, (CHARACTERGUID)_OldOwner, (ITEMGUID)_SrcContainer, (INTEGER)_Amount) (3,0,372,1) +event CharacterRequestsHomestead((CHARACTERGUID)_Character) (3,0,373,1) +call ItemDragToTrigger((ITEMGUID)_Item, (TRIGGERGUID)_Trigger) (1,0,374,1) +call ItemDragToPosition((ITEMGUID)_Item, (REAL)_X, (REAL)_Y, (REAL)_Z) (1,0,375,1) +call ItemMoveToTrigger((ITEMGUID)_Item, (TRIGGERGUID)_Trigger, (REAL)_Speed, (REAL)_Acceleration, (INTEGER)_UseRotation, (STRING)_Event, (INTEGER)_DoHits) (1,0,376,1) +call ItemMoveToPosition((ITEMGUID)_Item, (REAL)_X, (REAL)_Y, (REAL)_Z, (REAL)_Speed, (REAL)_Acceleration, (STRING)_Event, (INTEGER)_DoHits) (1,0,377,1) +call ItemToTransform((GUIDSTRING)_UUID, (REAL)_X, (REAL)_Y, (REAL)_Z, (REAL)_Pitch, (REAL)_Yaw, (REAL)_Roll, (INTEGER)_Amount, (CHARACTERGUID)_OwnerCharacter) (1,0,378,1) +call ItemToInventory((ITEMGUID)_Item, (GUIDSTRING)_TargetObject, (INTEGER)_Amount, (INTEGER)_ShowNotification, (INTEGER)_ClearOriginalOwner) (1,0,379,1) +call ItemTemplateDropFromCharacter((STRING)_ItemTemplate, (CHARACTERGUID)_Character, (INTEGER)_Count) (1,0,380,1) +call ItemScatterAt((ITEMGUID)_Item, (REAL)_X, (REAL)_Y, (REAL)_Z) (1,0,381,1) +call ItemTemplateRemoveFrom((STRING)_ItemTemplate, (GUIDSTRING)_Object, (INTEGER)_Count) (1,0,382,1) +call ItemTemplateRemoveFromParty((STRING)_ItemTemplate, (CHARACTERGUID)_Character, (INTEGER)_Count) (1,0,383,1) +call ItemTemplateRemoveFromUser((STRING)_ItemTemplate, (CHARACTERGUID)_Character, (INTEGER)_Count) (1,0,384,1) +call ItemTemplateAddTo((STRING)_ItemTemplate, (GUIDSTRING)_Object, (INTEGER)_Count, (INTEGER)_ShowNotification) (1,0,385,1) +query CreateItemTemplateAtPosition([in](STRING)_ItemTemplate, [in](REAL)_X, [in](REAL)_Y, [in](REAL)_Z, [out](ITEMGUID)_Item) (2,0,386,1) +query GetDebugItem([in](INTEGER)_Index, [out](STRING)_Template) (2,0,387,1) +call ItemDrop((ITEMGUID)_Item) (1,0,388,1) +call ItemRemove((ITEMGUID)_Item) (1,0,389,1) +call MoveAllItemsTo((GUIDSTRING)_FromObject, (GUIDSTRING)_ToObject, (INTEGER)_MoveEquippedArmor, (INTEGER)_MoveEquippedWeapons, (INTEGER)_ClearOriginalOwner) (1,0,390,1) +call ContainerIdentifyAll((ITEMGUID)_FromContainer) (1,0,391,1) +query ItemIsInCharacterInventory([in](ITEMGUID)_Item, [in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,392,1) +query ItemIsInPartyInventory([in](ITEMGUID)_Item, [in](CHARACTERGUID)_Character, [in](INTEGER)_MoveAndReport, [out](INTEGER)_Bool) (2,0,393,1) +query ItemIsInUserInventory([in](ITEMGUID)_Item, [in](CHARACTERGUID)_Character, [in](INTEGER)_MoveAndReport, [out](INTEGER)_Bool) (2,0,394,1) +query ItemIsInInventory([in](ITEMGUID)_Item, [out](INTEGER)_Bool) (2,0,395,1) +query ItemTemplateIsInCharacterInventory([in](CHARACTERGUID)_Character, [in](STRING)_Template, [out](INTEGER)_Count) (2,0,396,1) +query ItemTagIsInCharacterInventory([in](CHARACTERGUID)_Character, [in](STRING)_Tag, [out](INTEGER)_Count) (2,0,397,1) +query ItemTemplateTagIsInCharacterInventory([in](CHARACTERGUID)_Character, [in](STRING)_Template, [in](STRING)_Tag, [out](INTEGER)_Count) (2,0,398,1) +query ItemTemplateIsInPartyInventory([in](CHARACTERGUID)_Character, [in](STRING)_Template, [in](INTEGER)_MoveAndReport, [out](INTEGER)_Count) (2,0,399,1) +query ItemTemplateIsInUserInventory([in](CHARACTERGUID)_Character, [in](STRING)_Template, [in](INTEGER)_MoveAndReport, [out](INTEGER)_Count) (2,0,400,1) +query ItemTemplateGetDisplayString([in](GUIDSTRING)_Template, [out](STRING)_stringHandle, [out](STRING)_referenceString) (2,0,401,1) +query ItemTemplateIsInContainer([in](ITEMGUID)_Item, [in](STRING)_Template, [out](INTEGER)_Count) (2,0,402,1) +call ItemLock((ITEMGUID)_Item, (STRING)_Key) (1,0,403,1) +call ItemUnLock((ITEMGUID)_Item) (1,0,404,1) +query ItemIsOpened([in](ITEMGUID)_Item, [out](INTEGER)_Opened) (2,0,405,1) +query DoorIsOpening([in](ITEMGUID)_Door, [out](INTEGER)_Opening) (2,0,406,1) +query ItemIsClosed([in](ITEMGUID)_Item, [out](INTEGER)_Closed) (2,0,407,1) +query DoorIsClosing([in](ITEMGUID)_Door, [out](INTEGER)_Closing) (2,0,408,1) +query ItemIsLocked([in](ITEMGUID)_Item, [out](INTEGER)_Locked) (2,0,409,1) +query ItemIsContainer([in](ITEMGUID)_Item, [out](INTEGER)_IsContainer) (2,0,410,1) +query ItemHasOnUse([in](ITEMGUID)_Item, [in](STRING)_OnUse, [out](INTEGER)_Bool) (2,0,411,1) +call ItemLockUnEquip((ITEMGUID)_Item, (INTEGER)_lock) (1,0,412,1) +call ItemIsPoisoned((CHARACTERGUID)_Item, (INTEGER)_IsPoisoned) (1,0,413,1) +query ItemIsTorch([in](ITEMGUID)_Item, [out](INTEGER)_Bool) (2,0,414,1) +query ItemIsEquipable([in](ITEMGUID)_Item, [out](INTEGER)_Bool) (2,0,415,1) +call ItemOpen((ITEMGUID)_Item) (1,0,416,1) +call ItemClose((ITEMGUID)_Item) (1,0,417,1) +call ItemDestroy((ITEMGUID)_Item) (1,0,418,1) +query ItemIsDestroyed([in](ITEMGUID)_Item, [out](INTEGER)_Destroyed) (2,0,419,1) +call ItemClearOwner((ITEMGUID)_Item) (1,0,420,1) +query ItemGetOwner([in](ITEMGUID)_Item, [out](CHARACTERGUID)_Character) (2,0,421,1) +query ItemGetOriginalOwner([in](ITEMGUID)_Item, [out](CHARACTERGUID)_Character) (2,0,422,1) +query GetInventoryOwner([in](ITEMGUID)_Item, [out](GUIDSTRING)_Owner) (2,0,423,1) +call ItemSetCanInteract((ITEMGUID)_Item, (INTEGER)_bool) (1,0,424,1) +call ItemSetCanPickUp((ITEMGUID)_Item, (INTEGER)_bool) (1,0,425,1) +call ItemSetCanMove((ITEMGUID)_Item, (INTEGER)_bool) (1,0,426,1) +call ItemSetOwner((ITEMGUID)_Item, (CHARACTERGUID)_NewOwner) (1,0,427,1) +call ItemSetOriginalOwner((ITEMGUID)_Item, (CHARACTERGUID)_NewOwner) (1,0,428,1) +call ItemSetOnlyOwnerCanUse((ITEMGUID)_Item, (INTEGER)_bool) (1,0,429,1) +call ItemSetStoryItem((ITEMGUID)_Item, (INTEGER)_bool) (1,0,430,1) +call ItemLaunchIterator((STRING)_Event) (1,0,431,1) +query ItemIsStoryItem([in](ITEMGUID)_Item, [out](INTEGER)_Bool) (2,0,432,1) +call ItemCreateAtTrigger((TRIGGERGUID)_Trigger, (STRING)_TemplateId) (1,0,433,1) +call CreateKickstarterMessageInABottleItemAtTrigger((TRIGGERGUID)_Trigger, (STRING)_TemplateId) (1,0,434,1) +call ItemRotateY((ITEMGUID)_Item, (REAL)_Angle, (REAL)_Speed) (1,0,435,1) +call ItemRotateToAngleY((ITEMGUID)_Item, (REAL)_Angle, (REAL)_Speed) (1,0,436,1) +call ItemAddCharges((ITEMGUID)_Item, (INTEGER)_Charges) (1,0,437,1) +query ItemGetCharges([in](ITEMGUID)_Item, [out](INTEGER)_Charges) (2,0,438,1) +call ItemResetChargesToMax((ITEMGUID)_Item) (1,0,439,1) +query ItemGetMaxCharges([in](ITEMGUID)_Item, [out](INTEGER)_InitialCharges) (2,0,440,1) +call ItemSetDurability((ITEMGUID)_Item, (INTEGER)_Durability) (1,0,441,1) +query ItemGetDurability([in](ITEMGUID)_Item, [out](INTEGER)_Durability) (2,0,442,1) +query ItemGetAmount([in](ITEMGUID)_Item, [out](INTEGER)_Amount) (2,0,443,1) +query ItemGetHealthPoints([in](ITEMGUID)_Item, [out](INTEGER)_HP) (2,0,444,1) +query ItemCanSitOn([in](ITEMGUID)_Item, [out](INTEGER)_Bool) (2,0,445,1) +query ItemIsLadder([in](ITEMGUID)_Item, [out](INTEGER)_Bool) (2,0,446,1) +query ItemTemplateCanSitOn([in](STRING)_Template, [out](INTEGER)_Bool) (2,0,447,1) +query ContainerGetGoldValue([in](ITEMGUID)_Container, [out](INTEGER)_Value) (2,0,448,1) +query ItemGetGoldValue([in](ITEMGUID)_Item, [out](INTEGER)_Value) (2,0,449,1) +call ItemSetForceSynch((ITEMGUID)_Item, (INTEGER)_Bool) (1,0,450,1) +call ItemSetKnown((ITEMGUID)_Item, (INTEGER)_Bool) (1,0,451,1) +query GetItemForItemTemplateInInventory([in](CHARACTERGUID)_Character, [in](STRING)_Template, [out](ITEMGUID)_Item) (2,0,452,1) +query GetItemForItemTemplateInPartyInventory([in](CHARACTERGUID)_Character, [in](STRING)_Template, [out](ITEMGUID)_Item) (2,0,453,1) +query CharacterFindTaggedItem([in](CHARACTERGUID)_Character, [in](STRING)_Tag, [out](ITEMGUID)_Item) (2,0,454,1) +query PartyFindTaggedItem([in](CHARACTERGUID)_Character, [in](STRING)_Tag, [in](INTEGER)_MoveAndReport, [out](ITEMGUID)_Item) (2,0,455,1) +query UserFindTaggedItem([in](CHARACTERGUID)_Character, [in](STRING)_Tag, [in](INTEGER)_MoveAndReport, [out](ITEMGUID)_Item) (2,0,456,1) +query CharacterRemoveTaggedLocalItems([in](CHARACTERGUID)_Character, [in](STRING)_Tag, [in](INTEGER)_Amount, [out](INTEGER)_AmountRemoved) (2,0,457,1) +query PartyRemoveTaggedLocalItems([in](CHARACTERGUID)_Character, [in](STRING)_Tag, [in](INTEGER)_Amount, [out](INTEGER)_AmountRemoved) (2,0,458,1) +query UserRemoveTaggedLocalItems([in](CHARACTERGUID)_Character, [in](STRING)_Tag, [in](INTEGER)_Amount, [out](INTEGER)_AmountRemoved) (2,0,459,1) +query UserTransferTaggedLocalItems([in](CHARACTERGUID)_Character, [in](GUIDSTRING)_ToObject, [in](STRING)_Tag, [in](INTEGER)_Amount, [out](INTEGER)_AmountTransfered) (2,0,460,1) +query ItemIsPublicDomain([in](ITEMGUID)_Item, [out](INTEGER)_Bool) (2,0,461,1) +event ItemAddedToCharacter((ITEMGUID)_Item, (CHARACTERGUID)_Character) (3,0,462,1) +event ItemOpened((ITEMGUID)_Item) (3,0,463,1) +event ItemTemplateOpening((STRING)_ItemTemplate, (ITEMGUID)_Item, (CHARACTERGUID)_Character) (3,0,464,1) +event ItemDestroying((ITEMGUID)_Item) (3,0,465,1) +event ItemDestroyed((ITEMGUID)_Item) (3,0,466,1) +event ItemTemplateDestroyed((STRING)_TemplateID, (ITEMGUID)_Item) (3,0,467,1) +event ItemCreatedAtTrigger((TRIGGERGUID)_Trigger, (STRING)_TemplateID, (ITEMGUID)_Item) (3,0,468,1) +event ItemClosed((ITEMGUID)_Item) (3,0,469,1) +event ItemDropped((ITEMGUID)_Item) (3,0,470,1) +event ItemEnteredTrigger((ITEMGUID)_Item, (TRIGGERGUID)_Trigger, (CHARACTERGUID)_Mover) (3,0,471,1) +event ItemTemplateEnteredTrigger((STRING)_ItemTemplate, (ITEMGUID)_Item, (TRIGGERGUID)_Trigger, (CHARACTERGUID)_Owner, (CHARACTERGUID)_Mover) (3,0,472,1) +event ItemLeftTrigger((ITEMGUID)_Item, (TRIGGERGUID)_Trigger, (CHARACTERGUID)_Mover) (3,0,473,1) +event ItemTemplateLeftTrigger((STRING)_ItemTemplate, (ITEMGUID)_Item, (TRIGGERGUID)_Trigger, (CHARACTERGUID)_Owner, (CHARACTERGUID)_Mover) (3,0,474,1) +event ItemAddedToContainer((ITEMGUID)_Item, (ITEMGUID)_Container) (3,0,475,1) +event ItemTemplateAddedToCharacter((GUIDSTRING)_ItemTemplate, (ITEMGUID)_Item, (CHARACTERGUID)_Character) (3,0,476,1) +event ItemTemplateAddedToContainer((STRING)_ItemTemplate, (ITEMGUID)_Item, (ITEMGUID)_Container) (3,0,477,1) +event ItemRemovedFromCharacter((ITEMGUID)_Item, (CHARACTERGUID)_Character) (3,0,478,1) +event ItemTemplateRemovedFromCharacter((STRING)_ItemTemplate, (ITEMGUID)_Item, (CHARACTERGUID)_Character) (3,0,479,1) +event ItemRemovedFromContainer((ITEMGUID)_Item, (ITEMGUID)_Container) (3,0,480,1) +event ItemTemplateRemovedFromContainer((STRING)_ItemTemplate, (ITEMGUID)_Item, (ITEMGUID)_Container) (3,0,481,1) +event ItemEquipped((ITEMGUID)_Item, (CHARACTERGUID)_Character) (3,0,482,1) +event ItemUnEquipped((ITEMGUID)_Item, (CHARACTERGUID)_Character) (3,0,483,1) +event ItemTemplateEquipped((STRING)_ItemTemplate, (CHARACTERGUID)_Character) (3,0,484,1) +event ItemTemplateUnEquipped((STRING)_ItemTemplate, (CHARACTERGUID)_Character) (3,0,485,1) +event ItemTransformed((ITEMGUID)_Item, (STRING)_ItemTemplate) (3,0,486,1) +event ItemMoved((ITEMGUID)_Item) (3,0,487,1) +event ItemTemplateMoved((STRING)_ItemTemplate, (ITEMGUID)_Item) (3,0,488,1) +event ItemDisplayTextEnded((ITEMGUID)_Item, (STRING)_DisplayText) (3,0,489,1) +event ItemTemplateCombinedWithItemTemplate((STRING)_FirstItemTemplate, (STRING)_SecondItemTemplate, (STRING)_ThirdItemTemplate, (STRING)_ForthItemTemplate, (STRING)_FifthItemTemplate, (CHARACTERGUID)_Character, (ITEMGUID)_NewItem) (3,0,490,1) +event ItemStatusAttempt((ITEMGUID)_Item, (STRING)_Status, (GUIDSTRING)_Causee) (3,0,491,1) +event ItemStatusChange((ITEMGUID)_Item, (STRING)_Status, (GUIDSTRING)_Causee) (3,0,492,1) +event ItemStatusRemoved((ITEMGUID)_Item, (STRING)_Status, (GUIDSTRING)_Causee) (3,0,493,1) +event ItemStackedWith((ITEMGUID)_Item, (ITEMGUID)_StackedWithItem) (3,0,494,1) +event ItemMovedFromTo((ITEMGUID)_Item, (GUIDSTRING)_FromObject, (GUIDSTRING)_ToObject, (INTEGER)_IsTrade) (3,0,495,1) +event ItemsScatteredAt((REAL)_X, (REAL)_Y, (REAL)_Z) (3,0,496,1) +event TradeGenerationStarted((CHARACTERGUID)_Trader) (3,0,497,1) +event TradeGenerationEnded((CHARACTERGUID)_Trader) (3,0,498,1) +event ItemUnlocked((ITEMGUID)_Item, (CHARACTERGUID)_Character, (ITEMGUID)_Key) (3,0,499,1) +event ItemUnEquipFailed((ITEMGUID)_Item, (CHARACTERGUID)_Character) (3,0,500,1) +event ItemReceivedDamage((ITEMGUID)_Item) (3,0,501,1) +event ItemWentOnStage((GUIDSTRING)_Item, (INTEGER)_Bool) (3,0,502,1) +event ItemGhostRevealed((ITEMGUID)_Item) (3,0,503,1) +event ItemEnteredRegion((ITEMGUID)_Item, (STRING)_Region) (3,0,504,1) +event ItemLeftRegion((ITEMGUID)_Item, (STRING)_Region) (3,0,505,1) +call ItemLevelUp((ITEMGUID)_Item) (1,0,506,1) +call ItemLevelUpTo((ITEMGUID)_Item, (INTEGER)_Level) (1,0,507,1) +event RuneInserted((CHARACTERGUID)_Character, (ITEMGUID)_Item, (STRING)_RuneItemTemplate, (INTEGER)_Slot) (3,0,508,1) +event RuneRemoved((CHARACTERGUID)_Character, (ITEMGUID)_Item, (ITEMGUID)_Rune, (INTEGER)_Slot) (3,0,509,1) +query ItemGetRuneItemTemplate([in](ITEMGUID)_Item, [in](INTEGER)_Slot, [out](STRING)_Template) (2,0,510,1) +call ItemInsertRune((CHARACTERGUID)_Character, (ITEMGUID)_Item, (STRING)_RuneTemplate, (INTEGER)_Slot) (1,0,511,1) +query ItemRemoveRune([in](CHARACTERGUID)_Character, [in](ITEMGUID)_Item, [in](INTEGER)_Slot, [out](ITEMGUID)_Rune) (2,0,512,1) +call ItemAddDeltaModifier((ITEMGUID)_Item, (STRING)_Boost) (1,0,513,1) +query ItemHasDeltaModifier([in](ITEMGUID)_Item, [in](STRING)_Boost, [out](INTEGER)_Count) (2,0,514,1) +call DialogRequestStopForDialog((STRING)_Dialog, (GUIDSTRING)_Speaker) (1,0,515,1) +call DialogRequestStop((GUIDSTRING)_Speaker) (1,0,516,1) +query DialogGetNumberOfInvolvedPlayers([in](INTEGER)_InstanceID, [out](INTEGER)_Count) (2,0,517,1) +query DialogGetInvolvedPlayer([in](INTEGER)_InstanceID, [in](INTEGER)_Index, [out](GUIDSTRING)_Player) (2,0,518,1) +query DialogGetCategory([in](INTEGER)_InstanceID, [out](STRING)_Category) (2,0,519,1) +query DialogGetNumberOfInvolvedNPCs([in](INTEGER)_InstanceID, [out](INTEGER)_NumberOfNPCs) (2,0,520,1) +query DialogGetInvolvedNPC([in](INTEGER)_InstanceID, [in](INTEGER)_Index, [out](GUIDSTRING)_NPC) (2,0,521,1) +call GlobalSetFlag((STRING)_Flag) (1,0,522,1) +call GlobalClearFlag((STRING)_Flag) (1,0,523,1) +query GlobalGetFlag([in](STRING)_Flag, [out](INTEGER)_FlagState) (2,0,524,1) +call ObjectSetFlag((GUIDSTRING)_Target, (STRING)_Flag, (INTEGER)_DialogInstance) (1,0,525,1) +call ObjectShareFlag((GUIDSTRING)_Target, (STRING)_Flag) (1,0,526,1) +call GlobalShareFlag((STRING)_Flag) (1,0,527,1) +call ObjectClearFlag((GUIDSTRING)_Target, (STRING)_Flag, (INTEGER)_DialogInstance) (1,0,528,1) +query ObjectGetFlag([in](GUIDSTRING)_Target, [in](STRING)_Flag, [out](INTEGER)_FlagState) (2,0,529,1) +call ObjectSetDialogFlag((GUIDSTRING)_Target, (STRING)_Flag, (INTEGER)_DialogInstance) (1,0,530,1) +call ObjectClearDialogFlag((GUIDSTRING)_Target, (STRING)_Flag, (INTEGER)_DialogInstance) (1,0,531,1) +query ObjectGetDialogFlag([in](GUIDSTRING)_Target, [in](STRING)_Flag, [out](INTEGER)_FlagState) (2,0,532,1) +call UserSetFlag((CHARACTERGUID)_Character, (STRING)_Flag, (INTEGER)_DialogInstance) (1,0,533,1) +call UserClearFlag((CHARACTERGUID)_Character, (STRING)_Flag, (INTEGER)_DialogInstance) (1,0,534,1) +query UserGetFlag([in](CHARACTERGUID)_Character, [in](STRING)_Flag, [out](INTEGER)_FlagState) (2,0,535,1) +call PartySetFlag((CHARACTERGUID)_Character, (STRING)_Flag, (INTEGER)_DialogInstance) (1,0,536,1) +call PartyClearFlag((CHARACTERGUID)_Character, (STRING)_Flag, (INTEGER)_DialogInstance) (1,0,537,1) +query PartyGetFlag([in](CHARACTERGUID)_Character, [in](STRING)_Flag, [out](INTEGER)_FlagState) (2,0,538,1) +query DialogGetLocalFlag([in](INTEGER)_DialogInstance, [in](STRING)_LocalEvent, [out](INTEGER)_Value) (2,0,539,1) +event DialogStarted((STRING)_Dialog, (INTEGER)_InstanceID) (3,0,540,1) +event AutomatedDialogStarted((STRING)_Dialog, (INTEGER)_InstanceID) (3,0,541,1) +event DualDialogStart((STRING)_Dialog, (INTEGER)_InstanceID) (3,0,542,1) +event AutomatedDialogEnded((STRING)_Dialog, (INTEGER)_InstanceID) (3,0,543,1) +event DialogEnded((STRING)_Dialog, (INTEGER)_InstanceID) (3,0,544,1) +event DialogRequestFailed((STRING)_Dialog, (INTEGER)_InstanceID) (3,0,545,1) +event DialogActorJoined((STRING)_Dialog, (INTEGER)_InstanceID, (GUIDSTRING)_Actor) (3,0,546,1) +event DialogActorLeft((STRING)_Dialog, (INTEGER)_InstanceID, (GUIDSTRING)_Actor) (3,0,547,1) +event AutomatedDialogRequestFailed((STRING)_Dialog, (INTEGER)_InstanceID) (3,0,548,1) +event DialogStartRequested((GUIDSTRING)_Target, (GUIDSTRING)_Player) (3,0,549,1) +event GlobalFlagSet((STRING)_FlagName) (3,0,550,1) +event GlobalFlagCleared((STRING)_FlagName) (3,0,551,1) +event ObjectFlagSet((STRING)_FlagName, (GUIDSTRING)_Speaker, (INTEGER)_DialogInstance) (3,0,552,1) +event ObjectFlagShared((STRING)_FlagName, (GUIDSTRING)_Speaker, (INTEGER)_NewValue) (3,0,553,1) +event ObjectFlagCleared((STRING)_FlagName, (GUIDSTRING)_Speaker, (INTEGER)_DialogInstance) (3,0,554,1) +event PersuasionResult((CHARACTERGUID)_Character, (INTEGER)_Success, (STRING)_Dialog) (3,0,555,1) +query ObjectIsCharacter([in](GUIDSTRING)_Object, [out](INTEGER)_Bool) (2,0,556,1) +query GetStatString([in](GUIDSTRING)_Object, [out](STRING)_Statname) (2,0,557,1) +query ObjectExists([in](GUIDSTRING)_Object, [out](INTEGER)_Exists) (2,0,558,1) +query ObjectIsGlobal([in](GUIDSTRING)_Object, [out](INTEGER)_IsGlobal) (2,0,559,1) +query ObjectIsItem([in](GUIDSTRING)_Object, [out](INTEGER)_Bool) (2,0,560,1) +query ObjectIsInTrigger([in](GUIDSTRING)_Object, [in](TRIGGERGUID)_Trigger, [out](INTEGER)_Bool) (2,0,561,1) +query PositionIsInTrigger([in](REAL)_x, [in](REAL)_Y, [in](REAL)_Z, [in](TRIGGERGUID)_Trigger, [out](INTEGER)_Bool) (2,0,562,1) +query ObjectIsOnStage([in](GUIDSTRING)_Object, [out](INTEGER)_Bool) (2,0,563,1) +call PlayEffect((GUIDSTRING)_Object, (STRING)_FxName, (STRING)_Bone) (1,0,564,1) +query PlayLoopEffect([in](GUIDSTRING)_Object, [in](STRING)_FxName, [in](STRING)_BoneName, [out](INTEGER64)_FxHandle) (2,0,565,1) +call PlayBeamEffect((GUIDSTRING)_Object, (GUIDSTRING)_Target, (STRING)_FxName, (STRING)_SourceBone, (STRING)_TargetBone) (1,0,566,1) +query PlayLoopBeamEffect([in](GUIDSTRING)_Object, [in](GUIDSTRING)_Target, [in](STRING)_FxName, [in](STRING)_SourceBone, [in](STRING)_TargetBone, [out](INTEGER64)_FxHandle) (2,0,567,1) +call PlaySound((GUIDSTRING)_Object, (STRING)_SoundEvent) (1,0,568,1) +call DebugText((GUIDSTRING)_Object, (STRING)_Text) (1,0,569,1) +call DisplayText((GUIDSTRING)_Object, (STRING)_Text) (1,0,570,1) +call SetOnStage((GUIDSTRING)_Object, (INTEGER)_Bool) (1,0,571,1) +call SetVisible((GUIDSTRING)_Object, (INTEGER)_Bool) (1,0,572,1) +call ShowMapMarker((CHARACTERGUID)_Character, (STRING)_MarkerID, (INTEGER)_Show) (1,0,573,1) +call SetCameraDistanceOverride((REAL)_Distance) (1,0,574,1) +query GetMaxCameraDistance([out](REAL)_Distance) (2,0,575,1) +call TimerLaunch((STRING)_Timer, (INTEGER)_Time) (1,0,576,1) +call TimerCancel((STRING)_Timer) (1,0,577,1) +call TimerPause((STRING)_Timer) (1,0,578,1) +call TimerUnpause((STRING)_Timer) (1,0,579,1) +call MusicPlayForPeer((CHARACTERGUID)_Character, (STRING)_EventName) (1,0,580,1) +call MusicPlayForPeerWithInstrument((CHARACTERGUID)_Character, (CHARACTERGUID)_Character, (STRING)_EventName) (1,0,581,1) +call MusicPlayOnCharacter((CHARACTERGUID)_Character, (STRING)_EventName) (1,0,582,1) +call MusicPlayGeneral((STRING)_EventName) (1,0,583,1) +call MoviePlay((CHARACTERGUID)_Character, (STRING)_Event) (1,0,584,1) +call PlayMovieForDialog((CHARACTERGUID)_Character, (STRING)_DialogName, (STRING)_NodePrefix) (1,0,585,1) +call CameraActivate((CHARACTERGUID)_Character, (STRING)_Name, (REAL)_Time, (INTEGER)_HideUI, (INTEGER)_Smooth, (INTEGER)_HideShroud) (1,0,586,1) +call QuestUpdate((CHARACTERGUID)_Character, (STRING)_Quest, (STRING)_Status) (1,0,587,1) +call QuestReceiveSharedUpdate((CHARACTERGUID)_SrcCharacter, (CHARACTERGUID)_Character, (STRING)_Quest, (STRING)_Status) (1,0,588,1) +query QuestUpdateExists([in](STRING)_Quest, [in](STRING)_Status, [out](INTEGER)_Result) (2,0,589,1) +call QuestAdd((CHARACTERGUID)_Character, (STRING)_Quest) (1,0,590,1) +query QuestAccepted([in](CHARACTERGUID)_Character, [in](STRING)_Quest, [out](INTEGER)_Bool) (2,0,591,1) +call QuestClose((CHARACTERGUID)_Character, (STRING)_Quest) (1,0,592,1) +call QuestCloseAll((STRING)_Quest) (1,0,593,1) +query QuestIsShared([in](CHARACTERGUID)_Character, [in](STRING)_Quest, [out](INTEGER)_Bool) (2,0,594,1) +call SetInArena((GUIDSTRING)_Target, (INTEGER)_InArena) (1,0,595,1) +query IsInArena([in](GUIDSTRING)_Target, [out](INTEGER)_Bool) (2,0,596,1) +query QuestIsClosed([in](CHARACTERGUID)_Character, [in](STRING)_Quest, [out](INTEGER)_Bool) (2,0,597,1) +query QuestGetBroadcastLevel([in](STRING)_Quest, [out](STRING)_Level) (2,0,598,1) +call QuestSetCategory((STRING)_Quest, (STRING)_CategoryID) (1,0,599,1) +call QuestArchive((CHARACTERGUID)_Character, (STRING)_Quest, (INTEGER)_DoArchive) (1,0,600,1) +query QuestHasUpdate([in](CHARACTERGUID)_Character, [in](STRING)_Quest, [in](STRING)_Update, [out](INTEGER)_Bool) (2,0,601,1) +call QuestArchiveCategory((CHARACTERGUID)_Character, (STRING)_CategoryID, (INTEGER)_DoArchive) (1,0,602,1) +call AddSecret((CHARACTERGUID)_Character, (STRING)_Secret) (1,0,603,1) +call UnlockJournalRecipe((STRING)_RecipeID) (1,0,604,1) +call GameEnd() (1,0,605,1) +call GameEndWithMovie((STRING)_Movie) (1,0,606,1) +call GameEndWithMovieRequestCallback((STRING)_CallbackID) (1,0,607,1) +call EnqueueGameEndMovie((INTEGER)_UserID, (STRING)_Movie, (STRING)_Music) (1,0,608,1) +call EnqueueGameEndDialogMovie((CHARACTERGUID)_Character, (STRING)_DialogName, (STRING)_PlaylistId, (STRING)_Music) (1,0,609,1) +call FinalizeGameEndMovieQueue((INTEGER)_UserID) (1,0,610,1) +call SetGameEndMovie((INTEGER)_UserID, (STRING)_Movie) (1,0,611,1) +call ShroudRender((INTEGER)_Enable) (1,0,612,1) +call DebugBreak((STRING)_Message) (1,0,613,1) +call FadeToBlack((CHARACTERGUID)_Character, (REAL)_Seconds, (INTEGER)_ToBlack, (STRING)_FadeID) (1,0,614,1) +call FadeToWhite((CHARACTERGUID)_Character, (REAL)_Seconds, (INTEGER)_ToWhite, (STRING)_FadeID) (1,0,615,1) +call FadeOutBlack((CHARACTERGUID)_Character, (REAL)_Seconds, (STRING)_FadeID) (1,0,616,1) +call FadeOutWhite((CHARACTERGUID)_Character, (REAL)_Seconds, (STRING)_FadeID) (1,0,617,1) +call FadeIn((CHARACTERGUID)_Character, (REAL)_Seconds, (STRING)_FadeID) (1,0,618,1) +call OpenCustomBookUI((CHARACTERGUID)_Character, (STRING)_Bookname) (1,0,619,1) +call AddEntryToCustomBook((STRING)_Bookname, (STRING)_Entryname) (1,0,620,1) +call RemoveEntryFromCustomBook((STRING)_Bookname, (STRING)_Entryname) (1,0,621,1) +call OpenWaypointUI((CHARACTERGUID)_Character, (STRING)_CurrentWaypoint, (ITEMGUID)_Item, (INTEGER)_IsFleeing) (1,0,622,1) +call CloseUI((CHARACTERGUID)_Character, (STRING)_UIName) (1,0,623,1) +call OpenCraftUI((CHARACTERGUID)_Character, (ITEMGUID)_Item) (1,0,624,1) +call UnlockWaypoint((STRING)_WaypointName, (TRIGGERGUID)_Trigger, (CHARACTERGUID)_Character) (1,0,625,1) +call LockWaypoint((STRING)_WaypointName, (CHARACTERGUID)_Character) (1,0,626,1) +call RegisterWaypoint((STRING)_WaypointName, (ITEMGUID)_Item) (1,0,627,1) +call UnlockSecretRegion((TRIGGERGUID)_SecretRegionTrigger) (1,0,628,1) +call LockSecretRegion((TRIGGERGUID)_SecretRegionTrigger) (1,0,629,1) +call CreateSurface((GUIDSTRING)_Source, (STRING)_SurfaceType, (REAL)_Radius, (REAL)_Lifetime) (1,0,630,1) +call CreateSurfaceAtPosition((REAL)_x, (REAL)_Y, (REAL)_Z, (STRING)_SurfaceType, (REAL)_Radius, (REAL)_Lifetime) (1,0,631,1) +call CreatePuddle((GUIDSTRING)_Source, (STRING)_SurfaceType, (INTEGER)_CellAmountMin, (INTEGER)_CellAmountMax, (INTEGER)_GrowAmountMin, (INTEGER)_GrowAmountMax, (REAL)_GrowTime) (1,0,632,1) +call TransformSurface((GUIDSTRING)_Source, (STRING)_TransformType, (STRING)_TransformLayer, (REAL)_Radius, (REAL)_Lifetime, (GUIDSTRING)_Owner) (1,0,633,1) +call TransformSurfaceAtPosition((REAL)_X, (REAL)_Y, (REAL)_Z, (STRING)_TransformType, (STRING)_TransformLayer, (REAL)_Radius, (REAL)_Lifetime, (GUIDSTRING)_Owner) (1,0,634,1) +query GetSurfaceGroundAt([in](GUIDSTRING)_Target, [out](STRING)_Surface) (2,0,635,1) +query GetSurfaceCloudAt([in](GUIDSTRING)_Target, [out](STRING)_Surface) (2,0,636,1) +query GetSurfaceGroundOwnerAt([in](GUIDSTRING)_Target, [out](CHARACTERGUID)_OwnerCharacter, [out](ITEMGUID)_OwnerItem) (2,0,637,1) +query GetSurfaceCloudOwnerAt([in](GUIDSTRING)_Target, [out](GUIDSTRING)_OwnerCharacter, [out](GUIDSTRING)_OwnerItem) (2,0,638,1) +query GetSurfaceTypeIndex([in](STRING)_Surface, [out](INTEGER)_Index) (2,0,639,1) +query GetSurfaceNameByTypeIndex([in](INTEGER)_SurfaceIndex, [out](STRING)_SurfaceName) (2,0,640,1) +query DrawSurfaceOnPath([in](GUIDSTRING)_OwnerObject, [in](GUIDSTRING)_FollowObject, [in](STRING)_SurfaceType, [in](REAL)_Radius, [in](REAL)_LifeTime, [out](INTEGER64)_SurfaceActionHandle) (2,0,641,1) +call StopDrawSurfaceOnPath((INTEGER64)_SurfaceActionHandle) (1,0,642,1) +query GetSurfaceSize([in](GUIDSTRING)_Target, [in](INTEGER)_SurfaceLayer, [out](INTEGER)_SurfaceSize) (2,0,643,1) +query GetSurfaceTurns([in](GUIDSTRING)_Target, [in](INTEGER)_SurfaceLayer, [out](INTEGER)_SurfaceTurns) (2,0,644,1) +call PlayEffectAtPosition((STRING)_FxName, (REAL)_X, (REAL)_Y, (REAL)_Z) (1,0,645,1) +call PlayEffectAtPositionAndRotation((STRING)_FxName, (REAL)_X, (REAL)_Y, (REAL)_Z, (REAL)_Yangle) (1,0,646,1) +call PlayScaledEffectAtPosition((STRING)_FxName, (REAL)_Scale, (REAL)_X, (REAL)_Y, (REAL)_Z) (1,0,647,1) +call EndCombat((INTEGER)_CombatID) (1,0,648,1) +call StopLoopEffect((INTEGER64)_FxHandle) (1,0,649,1) +call MakePlayerActive((CHARACTERGUID)_Target) (1,0,650,1) +query CombatGetNumberOfInvolvedPlayers([in](INTEGER)_CombatID, [out](INTEGER)_NumPlayers) (2,0,651,1) +query CombatGetNumberOfInvolvedPartyMembers([in](INTEGER)_CombatID, [out](INTEGER)_NumPartyMembers) (2,0,652,1) +query CombatGetInvolvedPlayer([in](INTEGER)_CombatID, [in](INTEGER)_PlayerIndex, [out](CHARACTERGUID)_Player) (2,0,653,1) +query CombatGetInvolvedPartyMember([in](INTEGER)_CombatID, [in](INTEGER)_PartyMemberIndex, [out](CHARACTERGUID)_PartyMember) (2,0,654,1) +query CombatGetIDForCharacter([in](CHARACTERGUID)_Player, [out](INTEGER)_CombatID) (2,0,655,1) +query IsCombatActive([in](INTEGER)_CombatID, [out](INTEGER)_Active) (2,0,656,1) +query CombatGetActiveEntity([in](INTEGER)_CombatID, [out](GUIDSTRING)_CurrentEntity) (2,0,657,1) +call CreateExplosion((GUIDSTRING)_Target, (STRING)_SkillID, (INTEGER)_CasterLevel) (1,0,658,1) +call CreateExplosionAtPosition((REAL)_X, (REAL)_Y, (REAL)_Z, (STRING)_SkillID, (INTEGER)_CasterLevel) (1,0,659,1) +query GetMultiplayerCharacter([in](CHARACTERGUID)_Character, [out](CHARACTERGUID)_MultiplayerCharacter) (2,0,660,1) +call AutoSave() (1,0,661,1) +call ShowGameOverMenu() (1,0,662,1) +call OnCompanionDismissed((CHARACTERGUID)_Character) (1,0,663,1) +call NotifyGameProgress((REAL)_Progress) (1,0,664,1) +call ShowNotification((STRING)_Text) (1,0,665,1) +call ShowError((CHARACTERGUID)_Character, (STRING)_Error) (1,0,666,1) +call ShowTutorial((CHARACTERGUID)_Character, (STRING)_Text, (STRING)_Category, (STRING)_Title, (INTEGER)_ControllerType, (INTEGER)_ModalType, (INTEGER)_Duration, (INTEGER)_Priority, (INTEGER)_Flags, (INTEGER)_MinimumPlaytimeInMinutes) (1,0,667,1) +call CompleteTutorial((CHARACTERGUID)_Character, (STRING)_Text) (1,0,668,1) +call UnlockAchievement((STRING)_AchievementID, (CHARACTERGUID)_Character) (1,0,669,1) +call ProgressAchievement((STRING)_AchievementID, (CHARACTERGUID)_Character, (INTEGER)_Progress) (1,0,670,1) +call SetAchievementProgress((STRING)_AchievementID, (INTEGER)_Value) (1,0,671,1) +call SetHomesteadKeyState((INTEGER)_State, (CHARACTERGUID)_Character) (1,0,672,1) +call EnableSendToHomestead((INTEGER)_Bool) (1,0,673,1) +call KillCombatFor((CHARACTERGUID)_Character) (1,0,674,1) +query HasKickstarterDialogReward([out](INTEGER)_Bool) (2,0,675,1) +query IsHardcoreMode([out](INTEGER)_Bool) (2,0,676,1) +query CharacterHasDLC([in](CHARACTERGUID)_Character, [in](INTEGER)_DLCId, [out](INTEGER)_HasDLC) (2,0,677,1) +query GetUserCount([out](INTEGER)_UserCount) (2,0,678,1) +call GenerateTreasure((ITEMGUID)_Item, (STRING)_TreasureID, (INTEGER)_Level, (CHARACTERGUID)_Character) (1,0,679,1) +call PlayAnimation((GUIDSTRING)_SourceObject, (STRING)_Animation, (STRING)_Event) (1,0,680,1) +query GetVarObject([in](GUIDSTRING)_Source, [in](STRING)_VarName, [out](GUIDSTRING)_UUID) (2,0,681,1) +call SetVarObject((GUIDSTRING)_Source, (STRING)_VarName, (GUIDSTRING)_Object) (1,0,682,1) +call ClearVarObject((GUIDSTRING)_Source, (STRING)_VarName) (1,0,683,1) +call SetScriptframe((GUIDSTRING)_Target, (STRING)_Scriptframe) (1,0,684,1) +call ClearScriptframe((GUIDSTRING)_Target) (1,0,685,1) +call SetTag((GUIDSTRING)_Source, (STRING)_Tag) (1,0,686,1) +call ClearTag((GUIDSTRING)_Source, (STRING)_Tag) (1,0,687,1) +query GetVarInteger([in](GUIDSTRING)_Source, [in](STRING)_VarName, [out](INTEGER)_VarValue) (2,0,688,1) +query GetVarFloat([in](GUIDSTRING)_Source, [in](STRING)_VarName, [out](REAL)_VarValue) (2,0,689,1) +query GetVarString([in](GUIDSTRING)_Source, [in](STRING)_VarName, [out](STRING)_VarValue) (2,0,690,1) +query GetVarFixedString([in](GUIDSTRING)_Source, [in](STRING)_VarName, [out](STRING)_VarValue) (2,0,691,1) +call SetVarInteger((GUIDSTRING)_Target, (STRING)_VarName, (INTEGER)_VarValue) (1,0,692,1) +call SetVarFloat((GUIDSTRING)_Target, (STRING)_VarName, (REAL)_VarValue) (1,0,693,1) +call SetVarString((GUIDSTRING)_Target, (STRING)_VarName, (STRING)_VarValue) (1,0,694,1) +call SetVarFixedString((GUIDSTRING)_Target, (STRING)_VarName, (STRING)_VarValue) (1,0,695,1) +call SetVarFloat3((GUIDSTRING)_Target, (STRING)_VarName, (REAL)_X, (REAL)_Y, (REAL)_Z) (1,0,696,1) +query GetVarFloat3([in](GUIDSTRING)_Target, [in](STRING)_VarName, [out](REAL)_X, [out](REAL)_Y, [out](REAL)_Z) (2,0,697,1) +query IsTagged([in](GUIDSTRING)_Target, [in](STRING)_Tag, [out](INTEGER)_Bool) (2,0,698,1) +call RemoveStatus((GUIDSTRING)_Target, (STRING)_Status) (1,0,699,1) +call RemoveHarmfulStatuses((GUIDSTRING)_Target) (1,0,700,1) +query HasActiveStatus([in](GUIDSTRING)_Target, [in](STRING)_Status, [out](INTEGER)_Bool) (2,0,701,1) +query HasAppliedStatus([in](GUIDSTRING)_Target, [in](STRING)_Status, [out](INTEGER)_Bool) (2,0,702,1) +query GetUUID([in](GUIDSTRING)_Target, [out](STRING)_UUID) (2,0,703,1) +query GetPosition([in](GUIDSTRING)_Target, [out](REAL)_X, [out](REAL)_Y, [out](REAL)_Z) (2,0,704,1) +query GetRotation([in](GUIDSTRING)_Target, [out](REAL)_X, [out](REAL)_Y, [out](REAL)_Z) (2,0,705,1) +query GetClosestPlayer([in](GUIDSTRING)_Target, [out](CHARACTERGUID)_Player, [out](REAL)_Distance) (2,0,706,1) +query GetClosestPlayerWithTalent([in](GUIDSTRING)_Target, [in](STRING)_Talent, [out](CHARACTERGUID)_Player, [out](REAL)_Distance) (2,0,707,1) +query GetClosestAlivePlayer([in](GUIDSTRING)_Target, [out](CHARACTERGUID)_Player, [out](REAL)_Distance) (2,0,708,1) +query GetClosestAliveUserPlayer([in](GUIDSTRING)_Target, [in](INTEGER)_UserID, [out](CHARACTERGUID)_Player, [out](REAL)_Distance) (2,0,709,1) +query GetClosestPlayerToPosition([in](REAL)_X, [in](REAL)_Y, [in](REAL)_Z, [out](CHARACTERGUID)_Player, [out](REAL)_Distance) (2,0,710,1) +call Transform((GUIDSTRING)_Object, (STRING)_ObjectTemplate, (INTEGER)_ReplaceScripts, (INTEGER)_ReplaceScale, (INTEGER)_ReplaceStats) (1,0,711,1) +call ApplyStatus((GUIDSTRING)_Object, (STRING)_Status, (REAL)_Duration, (INTEGER)_Force, (GUIDSTRING)_Source) (1,0,712,1) +query GetRegion([in](GUIDSTRING)_Object, [out](STRING)_Region) (2,0,713,1) +call SetStoryEvent((GUIDSTRING)_Object, (STRING)_Event) (1,0,714,1) +call RequestProcessed((CHARACTERGUID)_Character, (INTEGER)_RequestId, (INTEGER)_RequestAccepted) (1,0,715,1) +call IterateParty((CHARACTERGUID)_Character, (STRING)_Event) (1,0,716,1) +call IterateParties((STRING)_Event) (1,0,717,1) +call IterateUsers((STRING)_Event) (1,0,718,1) +query GetUserName([in](INTEGER)_UserId, [out](STRING)_UserName) (2,0,719,1) +query GetUserProfileID([in](INTEGER)_UserId, [out](STRING)_UserProfileID) (2,0,720,1) +call LoadGame((STRING)_Savegame) (1,0,721,1) +call LeaveParty((INTEGER)_UserId) (1,0,722,1) +call AddToParty((INTEGER)_Source, (INTEGER)_Target) (1,0,723,1) +call LoadPartyPreset((STRING)_Preset, (GUIDSTRING)_TeleportToTarget) (1,0,724,1) +query CrimeGetType([in](INTEGER)_CrimeID, [out](STRING)_Type) (2,0,725,1) +query CrimeGetDetectionRange([in](INTEGER)_CrimeID, [out](REAL)_Range) (2,0,726,1) +query CrimeGetTension([in](INTEGER)_CrimeID, [out](INTEGER)_Tension) (2,0,727,1) +query CrimeGetNewID([out](INTEGER)_CrimeID) (2,0,728,1) +query CrimeIsTensionOverWarningTreshold([in](CHARACTERGUID)_Character, [out](INTEGER)_Bool) (2,0,729,1) +call CrimeClearAll() (1,0,730,1) +query CrimeFindEvidence([in](INTEGER)_CrimeID, [in](CHARACTERGUID)_Searcher, [in](CHARACTERGUID)_Criminal1, [in](CHARACTERGUID)_Criminal2, [in](CHARACTERGUID)_Criminal3, [in](CHARACTERGUID)_Criminal4, [out](INTEGER)_EvidenceFoundForCurrentCrime, [out](INTEGER)_EvidenceFound, [out](INTEGER)_GuiltyFound) (2,0,731,1) +call CrimeInterrogationDone((INTEGER)_CrimeID, (CHARACTERGUID)_Interrogator, (INTEGER)_FoundEvidence, (CHARACTERGUID)_Criminal1, (CHARACTERGUID)_Criminal2, (CHARACTERGUID)_Criminal3, (CHARACTERGUID)_Criminal4) (1,0,732,1) +call CrimeConfrontationDone((INTEGER)_CrimeID, (CHARACTERGUID)_Interrogator) (1,0,733,1) +query CrimeGetLeadInvestigator([in](INTEGER)_CrimeID, [out](CHARACTERGUID)_LeadInvestigator) (2,0,734,1) +call SetCanFight((GUIDSTRING)_Target, (INTEGER)_Enabled) (1,0,735,1) +call SetCanJoinCombat((GUIDSTRING)_Target, (INTEGER)_Enabled) (1,0,736,1) +call InventoryLaunchIterator((GUIDSTRING)_InventoryHolder, (STRING)_Event, (STRING)_CompletionEvent) (1,0,737,1) +call InventoryLaunchTagIterator((GUIDSTRING)_InventoryHolder, (STRING)_TagA, (STRING)_OptionalTagB, (STRING)_Event, (STRING)_CompletionEvent) (1,0,738,1) +call InventoryLaunchTemplateIterator((GUIDSTRING)_InventoryHolder, (STRING)_Template, (STRING)_Event, (STRING)_CompletionEvent) (1,0,739,1) +call SetIsBoss((GUIDSTRING)_Target, (INTEGER)_Enabled) (1,0,740,1) +query IsBoss([in](GUIDSTRING)_Target, [out](INTEGER)_Bool) (2,0,741,1) +query GetDistanceTo([in](GUIDSTRING)_object1, [in](GUIDSTRING)_object2, [out](REAL)_Dist) (2,0,742,1) +query GetDistanceToPosition([in](GUIDSTRING)_Object, [in](REAL)_X, [in](REAL)_Y, [in](REAL)_Z, [out](REAL)_Dist) (2,0,743,1) +query GetAngleTo([in](REAL)_x0, [in](REAL)_z0, [in](REAL)_x1, [in](REAL)_z1, [out](INTEGER)_Angle) (2,0,744,1) +call SetCombatGroupID((GUIDSTRING)_Target, (STRING)_GroupID) (1,0,745,1) +call EndTurn((GUIDSTRING)_Target) (1,0,746,1) +call CrimeAreaSetTensionModifier((TRIGGERGUID)_CrimeArea, (INTEGER)_Modifier) (1,0,747,1) +query CrimeAreaGetTensionModifier([in](TRIGGERGUID)_CrimeArea, [out](INTEGER)_Modifier) (2,0,748,1) +call CrimeAreaResetTensionModifier((TRIGGERGUID)_CrimeArea) (1,0,749,1) +query CrimeGetVictim([in](INTEGER)_CrimeID, [out](CHARACTERGUID)_CrimeVictim) (2,0,750,1) +call CrimeTransferEvidenceTo((INTEGER)_CrimeID, (GUIDSTRING)_Target) (1,0,751,1) +query CrimeGetEvidence([in](INTEGER)_CrimeID, [in](INTEGER)_Index, [out](GUIDSTRING)_Evidence) (2,0,752,1) +query CrimeGetNumberOfEvidence([in](INTEGER)_CrimeID, [out](INTEGER)_NumEvidence) (2,0,753,1) +query CrimeIsContinuous([in](INTEGER)_CrimeID, [out](INTEGER)_Bool) (2,0,754,1) +call ShutdownCrimeSystem() (1,0,755,1) +query CrimeGetCriminals([in](INTEGER)_CrimeID, [out](CHARACTERGUID)_Criminal1, [out](CHARACTERGUID)_Criminal2, [out](CHARACTERGUID)_Criminal3, [out](CHARACTERGUID)_Criminal4) (2,0,756,1) +query CrimeIsAnyNPCGoingToReact([in](GUIDSTRING)_Criminal, [in](STRING)_CrimeType, [in](REAL)_X, [in](REAL)_Y, [in](REAL)_Z, [out](INTEGER)_Bool) (2,0,757,1) +query CrimeTransferLeadershipTo([in](GUIDSTRING)_OldLead, [in](INTEGER)_CrimeID, [in](GUIDSTRING)_NewLead, [out](INTEGER)_Bool) (2,0,758,1) +call CrimeEnableInterrogation((GUIDSTRING)_NPC, (INTEGER)_Bool) (1,0,759,1) +call CrimeIgnoreAllCrimesForCriminal((GUIDSTRING)_Criminal, (GUIDSTRING)_NPC, (INTEGER)_IgnoreDuration) (1,0,760,1) +call CrimeResetInterrogationForCriminals((INTEGER)_CrimeID, (GUIDSTRING)_Criminal1, (GUIDSTRING)_Criminal2, (GUIDSTRING)_Criminal3, (GUIDSTRING)_Criminal4) (1,0,761,1) +call JumpToTurn((GUIDSTRING)_Target) (1,0,762,1) +call CrimeIgnoreCrime((INTEGER)_CrimeID, (GUIDSTRING)_NPC) (1,0,763,1) +query CrimeAddCriminal([in](INTEGER)_CrimeID, [in](GUIDSTRING)_Criminal, [out](INTEGER)_Bool) (2,0,764,1) +call NotifyCharacterCreationFinished() (1,0,765,1) +call SetHasDialog((GUIDSTRING)_Speaker, (INTEGER)_Dialog) (1,0,766,1) +call ShowArenaResult((INTEGER)_WinnerTeamId) (1,0,767,1) +call EnterCombat((GUIDSTRING)_Source, (GUIDSTRING)_Target) (1,0,768,1) +call LeaveCombat((GUIDSTRING)_Target) (1,0,769,1) +call SetFaction((GUIDSTRING)_Target, (STRING)_Faction) (1,0,770,1) +query GetFaction([in](GUIDSTRING)_Target, [out](STRING)_Faction) (2,0,771,1) +query GetTemplate([in](GUIDSTRING)_Target, [out](STRING)_Template) (2,0,772,1) +call SetInvulnerable_UseProcSetInvulnerable((GUIDSTRING)_Target, (INTEGER)_Bool) (1,0,773,1) +call UserRest((CHARACTERGUID)_Character, (STRING)_Restconsumable, (REAL)_PartyRadius, (REAL)_MinSafeDistance) (1,0,774,1) +call FireOsirisEvents() (1,0,775,1) +query IsSkillActive([in](GUIDSTRING)_Character, [in](STRING)_SkillID, [out](INTEGER)_Bool) (2,0,776,1) +call StartCameraSpline((SPLINEGUID)_Spline, (CHARACTERGUID)_Character, (REAL)_FadeTime, (INTEGER)_HideUI, (INTEGER)_Freeze, (INTEGER)_StartIndex) (1,0,777,1) +call StopCameraSpline((SPLINEGUID)_Spline, (CHARACTERGUID)_Character) (1,0,778,1) +call ApplyDamage((GUIDSTRING)_Object, (INTEGER)_Damage, (STRING)_DamageType, (GUIDSTRING)_Source) (1,0,779,1) +query IsSourceSkill([in](STRING)_SkillID, [out](INTEGER)_Bool) (2,0,780,1) +call MakePeace((CHARACTERGUID)_Source, (CHARACTERGUID)_Target, (INTEGER)_IgnoreVote) (1,0,781,1) +call MakeWar((CHARACTERGUID)_Source, (CHARACTERGUID)_Target, (INTEGER)_IgnoreVote) (1,0,782,1) +call ActivatePersistentLevelTemplateWithCombat((LEVELTEMPLATEGUID)_LevelTemplate) (1,0,783,1) +call ActivatePersistentLevelTemplate((LEVELTEMPLATEGUID)_LevelTemplate) (1,0,784,1) +query GetStatusType([in](STRING)_StatusID, [out](STRING)_StatusType) (2,0,785,1) +query GetStatusTurns([in](GUIDSTRING)_Source, [in](STRING)_StatusID, [out](INTEGER)_Turns) (2,0,786,1) +query GetHealStat([in](STRING)_StatusID, [out](STRING)_HealStat) (2,0,787,1) +call ReadyCheckStart((GUIDSTRING)_Player, (STRING)_Id) (1,0,788,1) +query IsGameLevel([in](STRING)_LevelName, [out](INTEGER)_Bool) (2,0,789,1) +query IsCharacterCreationLevel([in](STRING)_LevelName, [out](INTEGER)_Bool) (2,0,790,1) +query HasRecipeUnlockedWithIngredient([in](CHARACTERGUID)_Player, [in](GUIDSTRING)_ItemTemplate, [out](INTEGER)_Bool) (2,0,791,1) +query GetGlobalPriceModifier([out](INTEGER)_Modifier) (2,0,792,1) +call SetGlobalPriceModifier((INTEGER)_Modifier) (1,0,793,1) +event TimerFinished((STRING)_Timer) (3,0,794,1) +event RegionStarted((STRING)_NewRegion) (3,0,795,1) +event GameStarted((STRING)_LevelName, (INTEGER)_IsEditorMode) (3,0,796,1) +event RegionEnded((STRING)_Region) (3,0,797,1) +event CreditsEnded() (3,0,798,1) +event DLCUnlocked((INTEGER)_DLCId) (3,0,799,1) +event CharacterCreationStarted((STRING)_Level) (3,0,800,1) +event CharacterCreationFinished((CHARACTERGUID)_Character) (3,0,801,1) +event GameBookInterfaceClosed((ITEMGUID)_Item, (CHARACTERGUID)_Character) (3,0,802,1) +event SavegameLoaded((INTEGER)_Major, (INTEGER)_Minor, (INTEGER)_Revision, (INTEGER)_Build) (3,0,803,1) +event MovieFinished((STRING)_MovieName) (3,0,804,1) +event MoviePlaylistFinished((STRING)_MovieName) (3,0,805,1) +event DifficultyChanged((INTEGER)_DifficultyLevel) (3,0,806,1) +event GameModeStarted((STRING)_GameMode, (INTEGER)_IsEditorMode) (3,0,807,1) +event StoryEvent((GUIDSTRING)_Object, (STRING)_Event) (3,0,808,1) +event CanMoveItem((CHARACTERGUID)_Character, (ITEMGUID)_Item, (INTEGER)_RequestID) (3,0,809,1) +event CanPickupItem((CHARACTERGUID)_Character, (ITEMGUID)_Item, (INTEGER)_RequestID) (3,0,810,1) +event CanUseItem((CHARACTERGUID)_Character, (ITEMGUID)_Item, (INTEGER)_RequestID) (3,0,811,1) +event CanLockpickItem((CHARACTERGUID)_Character, (ITEMGUID)_Item, (INTEGER)_RequestID) (3,0,812,1) +event CanCombineItem((CHARACTERGUID)_Character, (ITEMGUID)_ItemA, (ITEMGUID)_ItemB, (ITEMGUID)_ItemC, (ITEMGUID)_ItemD, (ITEMGUID)_ItemE, (INTEGER)_RequestID) (3,0,813,1) +event UserConnected((INTEGER)_UserID, (STRING)_UserName, (STRING)_UserProfileID) (3,0,814,1) +event FadeOutDone((INTEGER)_UserID, (STRING)_FadeID) (3,0,815,1) +event FadeInDone((INTEGER)_UserID, (STRING)_FadeID) (3,0,816,1) +event FadeDone((INTEGER)_UserID, (STRING)_FadeID) (3,0,817,1) +event ClearFadeDone((INTEGER)_UserID, (STRING)_FadeID) (3,0,818,1) +event UserDisconnected((INTEGER)_UserID, (STRING)_UserName, (STRING)_UserProfileID) (3,0,819,1) +event UserEvent((INTEGER)_UserID, (STRING)_UserEvent) (3,0,820,1) +event UserMakeWar((INTEGER)_SourceUserID, (INTEGER)_TargetUserID, (INTEGER)_War) (3,0,821,1) +event AttackedByObject((GUIDSTRING)_Defender, (GUIDSTRING)_AttackerOwner, (GUIDSTRING)_Attacker, (STRING)_DamageType, (STRING)_DamageSource) (3,0,822,1) +event FleeCombat((CHARACTERGUID)_Character) (3,0,823,1) +event CrimeInterrogationRequest((STRING)_CrimeRegion, (INTEGER)_CrimeID, (CHARACTERGUID)_Interrogator, (CHARACTERGUID)_Criminal1, (CHARACTERGUID)_Criminal2, (CHARACTERGUID)_Criminal3, (CHARACTERGUID)_Criminal4, (STRING)_InterrogateDialog) (3,0,824,1) +event OnCrimeResolved((INTEGER)_CrimeID, (CHARACTERGUID)_Victim, (CHARACTERGUID)_Criminal1, (CHARACTERGUID)_Criminal2, (CHARACTERGUID)_Criminal3, (CHARACTERGUID)_Criminal4) (3,0,825,1) +event OnCrimeRemoved((INTEGER)_CrimeID, (CHARACTERGUID)_Victim, (CHARACTERGUID)_Criminal1, (CHARACTERGUID)_Criminal2, (CHARACTERGUID)_Criminal3, (CHARACTERGUID)_Criminal4) (3,0,826,1) +event OnCrimeConfrontationDone((INTEGER)_CrimeID, (CHARACTERGUID)_Investigator, (INTEGER)_WasLead, (CHARACTERGUID)_Criminal1, (CHARACTERGUID)_Criminal2, (CHARACTERGUID)_Criminal3, (CHARACTERGUID)_Criminal4) (3,0,827,1) +event OnCriminalMergedWithCrime((INTEGER)_CrimeID, (CHARACTERGUID)_Criminal) (3,0,828,1) +event OnCrimeMergedWith((INTEGER)_OldCrimeID, (INTEGER)_NewCrimeID) (3,0,829,1) +event OnCrimeSawCriminalInCombat((INTEGER)_CrimeID, (CHARACTERGUID)_Character, (CHARACTERGUID)_Criminal1) (3,0,830,1) +event OnArenaRoundStarted((STRING)_ArenaMode) (3,0,831,1) +event OnArenaRoundForceEnded() (3,0,832,1) +event ObjectWasTagged((GUIDSTRING)_Object, (STRING)_Tag) (3,0,833,1) +event ObjectLostTag((GUIDSTRING)_Object, (STRING)_Tag) (3,0,834,1) +event ObjectEnteredCombat((GUIDSTRING)_Object, (INTEGER)_CombatID) (3,0,835,1) +event CombatStarted((INTEGER)_CombatID) (3,0,836,1) +event CombatRoundStarted((INTEGER)_CombatID, (INTEGER)_Round) (3,0,837,1) +event CombatEnded((INTEGER)_CombatID) (3,0,838,1) +event ObjectSwitchedCombat((GUIDSTRING)_Object, (INTEGER)_OldCombatID, (INTEGER)_NewCombatID) (3,0,839,1) +event ObjectLeftCombat((GUIDSTRING)_Object, (INTEGER)_CombatID) (3,0,840,1) +event ObjectReadyInCombat((GUIDSTRING)_Object, (INTEGER)_CombatID) (3,0,841,1) +event ObjectTurnStarted((GUIDSTRING)_Object) (3,0,842,1) +event ObjectTurnEnded((GUIDSTRING)_Object) (3,0,843,1) +event CrimeDisabled((CHARACTERGUID)_Character, (STRING)_Crime) (3,0,844,1) +event CrimeEnabled((CHARACTERGUID)_Character, (STRING)_Crime) (3,0,845,1) +event GMCampaignModeStarted((STRING)_CampaignMode) (3,0,846,1) +event PartyPresetLoaded((STRING)_PartyPreset) (3,0,847,1) +event QuestShared((CHARACTERGUID)_Character, (STRING)_Quest, (INTEGER)_IsShared) (3,0,848,1) +event QuestCategoryChanged((STRING)_Quest, (STRING)_NewCategory) (3,0,849,1) +event ReadyCheckPassed((STRING)_Id) (3,0,850,1) +event ReadyCheckFailed((STRING)_Id) (3,0,851,1) +event ObjectSourcePointAddRequest((GUIDSTRING)_Target, (INTEGER)_AddSP, (INTEGER)_WasSP) (3,0,852,1) +event TeleportRequestMovie((INTEGER)_UserId, (STRING)_EventId) (3,0,853,1) +event EndGameRequestMovie((INTEGER)_UserId, (STRING)_EventId) (3,0,854,1) +event CustomBookUIClosed((CHARACTERGUID)_Character, (STRING)_BookName) (3,0,855,1) +event PuzzleUIUsed((CHARACTERGUID)_Character, (STRING)_UIInstance, (INTEGER)_Type, (STRING)_Command, (INTEGER)_ElementId) (3,0,856,1) +event PuzzleUIClosed((CHARACTERGUID)_Character, (STRING)_UIInstance, (INTEGER)_Type) (3,0,857,1) +event CameraReachedNode((SPLINEGUID)_Spline, (CHARACTERGUID)_Character, (STRING)_event, (INTEGER)_index, (INTEGER)_last) (3,0,858,1) +call TriggerLaunchIterator((TRIGGERGUID)_Trigger, (STRING)_Event) (1,0,859,1) +call TriggerRemoveAllItemTemplates((TRIGGERGUID)_Trigger, (STRING)_ItemTemplate) (1,0,860,1) +call TriggerRegisterForCharacter((TRIGGERGUID)_Trigger, (CHARACTERGUID)_Character) (1,0,861,1) +call TriggerUnregisterForCharacter((TRIGGERGUID)_Trigger, (CHARACTERGUID)_Character) (1,0,862,1) +call TriggerRegisterForPlayers((TRIGGERGUID)_Trigger) (1,0,863,1) +call TriggerUnregisterForPlayers((TRIGGERGUID)_Trigger) (1,0,864,1) +call TriggerRegisterForItems((TRIGGERGUID)_Trigger) (1,0,865,1) +call TriggerUnregisterForItems((TRIGGERGUID)_Trigger) (1,0,866,1) +query CharacterTemplatesInTrigger([in](STRING)_Template, [in](TRIGGERGUID)_Trigger, [out](INTEGER)_Count) (2,0,867,1) +call TriggerSetAtmosphere((TRIGGERGUID)_Trigger, (STRING)_AtmosphereUUID) (1,0,868,1) +call TriggerResetAtmosphere((TRIGGERGUID)_Trigger) (1,0,869,1) +call TriggerSetSoundState((TRIGGERGUID)_Trigger, (STRING)_StateGroup, (STRING)_State, (INTEGER)_Recursive) (1,0,870,1) +call TriggerSetSoundRTPC((TRIGGERGUID)_Trigger, (STRING)_Name, (REAL)_Value, (INTEGER)_Recursive) (1,0,871,1) +call TriggerSetItemOwner((TRIGGERGUID)_AreaTrigger, (CHARACTERGUID)_Owner) (1,0,872,1) +call TriggerClearItemOwner((TRIGGERGUID)_AreaTrigger) (1,0,873,1) +call TriggerClearItemTemplateOwners((TRIGGERGUID)_Trigger, (STRING)_ItemTemplate) (1,0,874,1) +query GetRandomPositionInTrigger([in](TRIGGERGUID)_Trigger, [out](REAL)_X, [out](REAL)_Y, [out](REAL)_Z) (2,0,875,1) +query StringConcatenate([in](STRING)_StringA, [in](STRING)_StringB, [out](STRING)_Result) (2,0,876,1) +query StringContains([in](STRING)_StringA, [in](STRING)_StringB, [out](INTEGER)_Bool) (2,0,877,1) +query StringSub([in](STRING)_String, [in](INTEGER)_Start, [in](INTEGER)_Count, [out](STRING)_Result) (2,0,878,1) +query IntegertoString([in](INTEGER)_Integer, [out](STRING)_Result) (2,0,879,1) +query String([in](GUIDSTRING)_GUIDstring, [out](STRING)_Result) (2,0,880,1) +query StartDialog_Internal([in](STRING)_Dialog, [in](INTEGER)_MarkForInteractiveDialog, [in](GUIDSTRING)_Speaker1, [in](GUIDSTRING)_Speaker2, [in](GUIDSTRING)_Speaker3, [in](GUIDSTRING)_Speaker4, [in](GUIDSTRING)_Speaker5, [in](GUIDSTRING)_Speaker6, [out](INTEGER)_Success) (2,0,881,1) +query StartDialog_Internal_NoDeadCheck([in](STRING)_Dialog, [in](INTEGER)_MarkForInteractiveDialog, [in](GUIDSTRING)_Speaker1, [in](GUIDSTRING)_Speaker2, [in](GUIDSTRING)_Speaker3, [in](GUIDSTRING)_Speaker4, [in](GUIDSTRING)_Speaker5, [in](GUIDSTRING)_Speaker6, [out](INTEGER)_Success) (2,0,882,1) +query DialogStartCrimeDialog([in](INTEGER)_CrimeID, [in](STRING)_Dialog, [in](INTEGER)_MarkForInteractiveDialog, [in](GUIDSTRING)_NPC, [in](GUIDSTRING)_Criminal1, [in](GUIDSTRING)_Criminal2, [in](GUIDSTRING)_Criminal3, [in](GUIDSTRING)_Criminal4, [out](INTEGER)_success) (2,0,883,1) +call DialogAddCharacter((INTEGER)_InstanceID, (CHARACTERGUID)_Player) (1,0,884,1) +call DialogAddCharacterAt((INTEGER)_InstanceID, (CHARACTERGUID)_Player, (INTEGER)_Index) (1,0,885,1) +query DialogRemoveCharacter([in](INTEGER)_InstanceID, [in](CHARACTERGUID)_Player, [out](INTEGER)_success) (2,0,886,1) +query DialogStartPartyDialog([in](STRING)_Dialog, [in](INTEGER)_ParentInstanceID, [in](INTEGER)_NewInstanceID, [in](CHARACTERGUID)_Player1, [in](CHARACTERGUID)_Player2, [in](CHARACTERGUID)_Player3, [in](CHARACTERGUID)_Player4, [out](INTEGER)_success) (2,0,887,1) +query DialogStartChildDialog([in](STRING)_Dialog, [in](INTEGER)_ParentInstanceID, [in](INTEGER)_NewInstanceID, [in](CHARACTERGUID)_Player1, [in](CHARACTERGUID)_Player2, [in](CHARACTERGUID)_Player3, [in](CHARACTERGUID)_Player4, [out](INTEGER)_success) (2,0,888,1) +call DialogResume((INTEGER)_InstanceID) (1,0,889,1) +query IsSpeakerReserved([in](GUIDSTRING)_Speaker, [out](INTEGER)_success) (2,0,890,1) +call StartVoiceBark((STRING)_Bark, (CHARACTERGUID)_Source) (1,0,891,1) +event VoiceBarkStarted((STRING)_Bark, (INTEGER)_InstanceID) (3,0,892,1) +event VoiceBarkFailed((STRING)_Bark) (3,0,893,1) +event VoiceBarkEnded((STRING)_Bark, (INTEGER)_InstanceID) (3,0,894,1) +event DualDialogRequested((STRING)_Dialog, (INTEGER)_InstanceID, (INTEGER)_TargetInstanceID) (3,0,895,1) +event ChildDialogRequested((STRING)_Dialog, (INTEGER)_InstanceID, (INTEGER)_TargetInstanceID) (3,0,896,1) +call DialogSetVariableString((STRING)_Dialog, (STRING)_Variable, (STRING)_Value) (1,0,897,1) +call DialogSetVariableInt((STRING)_Dialog, (STRING)_Variable, (INTEGER)_Value) (1,0,898,1) +call DialogSetVariableFloat((STRING)_Dialog, (STRING)_Variable, (REAL)_Value) (1,0,899,1) +call DialogSetVariableFixedString((STRING)_Dialog, (STRING)_Variable, (STRING)_Value) (1,0,900,1) +call DialogSetVariableTranslatedString((STRING)_Dialog, (STRING)_Variable, (STRING)_StringHandleValue, (STRING)_ReferenceStringValue) (1,0,901,1) +call DialogSetVariableStringForInstance((INTEGER)_InstanceID, (STRING)_Variable, (STRING)_Value) (1,0,902,1) +call DialogSetVariableIntForInstance((INTEGER)_InstanceID, (STRING)_Variable, (INTEGER)_Value) (1,0,903,1) +call DialogSetVariableFloatForInstance((INTEGER)_InstanceID, (STRING)_Variable, (REAL)_Value) (1,0,904,1) +call DialogSetVariableFixedStringForInstance((INTEGER)_InstanceID, (STRING)_Variable, (STRING)_Value) (1,0,905,1) +call DialogSetVariableTranslatedStringForInstance((INTEGER)_InstanceID, (STRING)_Variable, (STRING)_StringHandleValue, (STRING)_ReferenceStringValue) (1,0,906,1) +query HasDefaultDialog([in](CHARACTERGUID)_Character, [out](INTEGER)_HasDefaultDialog) (2,0,907,1) +query StartDefaultDialog([in](CHARACTERGUID)_Character, [in](CHARACTERGUID)_Player, [out](STRING)_Dialog, [out](INTEGER)_Automated) (2,0,908,1) +event GameEventSet((STRING)_Event) (3,0,909,1) +event GameEventCleared((STRING)_Event) (3,0,910,1) +event TextEventSet((STRING)_Event) (3,0,911,1) +query GetTextEventParamString([in](INTEGER)_Number, [out](STRING)_Value) (2,0,912,1) +query GetTextEventParamInteger([in](INTEGER)_Number, [out](INTEGER)_Value) (2,0,913,1) +query GetTextEventParamReal([in](INTEGER)_Number, [out](REAL)_Value) (2,0,914,1) +query GetTextEventParamUUID([in](INTEGER)_Number, [out](GUIDSTRING)_Value) (2,0,915,1) + + +version "0.0.6.1" +Goal(1).Title("__Combat"); +Goal(1) +{ + INIT + { + + } + KB + { + PROC + ProcClearPreviousCombat((GUIDSTRING)_Char) + AND + DB_WasInCombat(_Char,(INTEGER)_Combat) + THEN + NOT DB_WasInCombat(_Char,_Combat); + + PROC + ProcAddToCharacterCombatList((GUIDSTRING)_Char,(INTEGER)_Combat) + AND + DB_CombatCharacters((CHARACTERGUID)_Char,(INTEGER)_Old) + THEN + NOT DB_CombatCharacters((CHARACTERGUID)_Char,_Old); + + PROC + ProcAddToCharacterCombatList((GUIDSTRING)_Char,(INTEGER)_Combat) + AND + ObjectIsCharacter(_Char,1) + THEN + DB_CombatCharacters((CHARACTERGUID)_Char,_Combat); + + IF + ObjectEnteredCombat(_Character,_Combat) + THEN + ProcClearPreviousCombat((GUIDSTRING)_Character); + DB_CombatObjects(_Character,_Combat); + ProcAddToCharacterCombatList(_Character,_Combat); + + IF + ObjectSwitchedCombat(_Character,_Old,_New) + THEN + NOT DB_CombatObjects(_Character,_Old); + DB_CombatObjects(_Character,_New); + ProcAddToCharacterCombatList(_Character,_New); + + PROC + Proc_ObjectLeftCombat((GUIDSTRING)_Char,(INTEGER)_Combat) + THEN + DB_NOOP(1); + + IF + ObjectLeftCombat(_Character,_Combat) + THEN + DB_WasInCombat(_Character,_Combat); + NOT DB_CombatObjects(_Character,_Combat); + NOT DB_CombatCharacters((CHARACTERGUID)_Character,_Combat); + Proc_ObjectLeftCombat(_Character,_Combat); + + IF + FleeCombat(_Player) + AND + DB_IsPlayer(_Player) + AND + NOT DB_BlockWaypointUsage(_Player) + THEN + OpenWaypointUI(_Player,"",NULL_00000000-0000-0000-0000-000000000000,1); + + } + EXIT + { + + } +} +Goal(2).Title("__GLO_Shovel"); +Goal(2) +{ + INIT + { + DB_LizardFirstShovelUses(0); + + } + KB + { + //REGION CHECK FOR TREASURE + IF + DB_ShovelArea((TRIGGERGUID)_Trigger,(STRING)_,(ITEMGUID)_) + THEN + ProcTriggerRegisterForPlayers(_Trigger); + + IF + DB_ShovelRewardItemAppear(_,_Item,_) + THEN + SetOnStage(_Item,0); + + IF + DB_ShovelRewardItemScatter(_,_Item) + THEN + SetOnStage(_Item,0); + + IF + DB_ShovelRewardItemSpawn(_,_Item) + THEN + SetOnStage(_Item,0); + + IF + DB_ShovelRewardCharacterAppear(_,_Character) + THEN + SetOnStage(_Character,0); + + //Dig while in a trigger + IF + CharacterUsedItem(_Player, _Shovel) + AND + ObjectExists(_Shovel,1) //ignore consumables that were destroyed + AND + IsTagged(_Shovel, "SHOVEL", 1) + AND + DB_ShovelArea(_Trigger,_,_DirtPile) + AND + DB_InRegion(_Player,_Trigger) + AND + NOT DB_Shovelling_Mound(_,_DirtPile) + AND + CharacterIsInFightMode(_Player,_WasInFightMode) + THEN + DB_Shovelling_Mound(_Player,_DirtPile); + CharacterSetFightMode(_Player,0,1); + PlayAnimation(_Player,"use_dig","digmound"); + DB_Shovel_PlayerHadWeaponDrawn(_Player,_WasInFightMode); + + //Dig outside a trigger + IF + CharacterUsedItem(_Player, _Shovel) + AND + ObjectExists(_Shovel,1) //ignore consumables that were destroyed + AND + IsTagged(_Shovel, "SHOVEL", 1) + AND + NOT DB_Shovelling_Mound(_Player,_) + AND + CharacterIsInFightMode(_Player,_WasInFightMode) + THEN + CharacterSetFightMode(_Player,0,1); + PlayAnimation(_Player,"use_dig","digmound"); + DB_Shovel_PlayerHadWeaponDrawn(_Player,_WasInFightMode); + + //Dig by interacting with pile without a shovel + + IF + CharacterUsedItem(_Player,_DirtPile) + AND + DB_ShovelArea(_,_,_DirtPile) + AND + NOT PartyFindTaggedItem(_Player, "SHOVEL", 0, _) + AND + IsTagged(_Player,"LIZARD",0) + THEN + Proc_StartDialog(1,"GLO_AD_ShovelRequired", _Player); + + IF + CharacterUsedItem(_Player,_DirtPile) + AND + DB_ShovelArea(_,_,_DirtPile) + AND + NOT DB_Shovelling_Mound(_,_DirtPile) + AND + IsTagged(_Player,"LIZARD",1) + AND + CharacterIsInFightMode(_Player,_WasInFightMode) + THEN + DB_Shovelling_Mound(_Player,_DirtPile); + CharacterSetFightMode(_Player,0,1); + PlayAnimation(_Player,"use_dig","digmound"); + DB_Shovel_PlayerHadWeaponDrawn(_Player,_WasInFightMode); + proc_LizardFirstShovelUse((CHARACTERGUID)_Player); + + //Dig by interacting with pile with a shovel + IF + CharacterUsedItem(_Player,_DirtPile) + AND + DB_ShovelArea(_,_,_DirtPile) + AND + NOT DB_Shovelling_Mound(_,_DirtPile) + AND + PartyFindTaggedItem(_Player, "SHOVEL", 1, _) + AND + CharacterIsInFightMode(_Player,_WasInFightMode) + THEN + DB_Shovelling_Mound(_Player,_DirtPile); + CharacterSetFightMode(_Player,0,1); + PlayAnimation(_Player,"use_dig","digmound"); + DB_Shovel_PlayerHadWeaponDrawn(_Player,_WasInFightMode); + + //After Dig + IF + StoryEvent(_Player,"digmound") + AND + NOT DB_Shovelling_Mound((CHARACTERGUID)_Player,_) + THEN + Proc_StartDialog(1,"GLO_AD_ShovelFailed", _Player); + + IF + StoryEvent(_Player,"digmound") + AND + DB_Shovelling_Mound((CHARACTERGUID)_Player,_DirtMound) + AND + DB_ShovelArea(_Trigger,_Reward,_DirtMound) + THEN + NOT DB_ShovelArea(_Trigger,_Reward,_DirtMound); + NOT DB_Shovelling_Mound(_Player,_DirtMound); + SetOnStage(_DirtMound,0); + ProcShovelRewards(_Player,_Reward); + CharacterItemSetEvent(_Player,_DirtMound,"clearedMound"); + + IF + StoryEvent(_Player,"digmound") + AND + DB_Shovel_PlayerHadWeaponDrawn((CHARACTERGUID)_Player,1) + THEN + CharacterSetFightMode(_Player,1,0); + + IF + StoryEvent(_Player,"digmound") + AND + DB_Shovel_PlayerHadWeaponDrawn((CHARACTERGUID)_Player,_Value) + THEN + NOT DB_Shovel_PlayerHadWeaponDrawn(_Player,_Value); + + //END_REGION + + //REGION Lizard Dig AD + + PROC + proc_LizardFirstShovelUse((CHARACTERGUID)_Lizrd) + AND + IsTagged(_Lizrd,"LIZARD",1) + AND + DB_LizardFirstShovelUses(_Int) + AND + _Int < 3 + AND + IntegerSum(_Int,1,_NewInt) + THEN + DB_LizardFirstShovelUses(_NewInt); + NOT DB_LizardFirstShovelUses(_Int); + Proc_StartDialog(1,"GEN_AD_Lizrd_Dig",_Lizrd); + + + + //END_REGION + + //REGION SHOVEL REWARDS + PROC + ProcShovelRewards((CHARACTERGUID)_Player,(STRING)_Reward) + AND + DB_ShovelRewardItemAdd(_Reward,(ITEMGUID)_Item) + THEN + ItemToInventory(_Item,_Player,-1); + + PROC + ProcShovelRewards((CHARACTERGUID)_Player,(STRING)_Reward) + AND + DB_ShovelRewardItemAppear(_Reward,(ITEMGUID)_Item,(TRIGGERGUID)_Trigger) + THEN + SetOnStage(_Item,1); + ItemDragToTrigger(_Item,_Trigger); + + PROC + ProcShovelRewards((CHARACTERGUID)_Player,(STRING)_Reward) + AND + DB_ShovelRewardCharacterAppear(_Reward,(CHARACTERGUID)_Character) + THEN + CharacterAppear(_Character,1,""); + + PROC + ProcShovelRewards((CHARACTERGUID)_Player,(STRING)_Reward) + AND + DB_ShovelRewardItemSpawn(_Reward,(ITEMGUID)_Item) + THEN + SetOnStage(_Item,1); + + PROC + ProcShovelRewards((CHARACTERGUID)_Player,(STRING)_Reward) + AND + DB_ShovelRewardItemTemplate(_Reward,(STRING)_ItemTemplate,(INTEGER)_Amount) + THEN + ItemTemplateAddTo(_ItemTemplate,_Player,_Amount); + + PROC + ProcShovelRewards((CHARACTERGUID)_Player,(STRING)_Reward) + AND + DB_ShovelRewardEvent(_Reward,(STRING)_Event) + THEN + GlobalSetFlag(_Event); + + PROC + ProcShovelRewards((CHARACTERGUID)_Player,(STRING)_Reward) + AND + DB_ShovelRewardVoiceBark(_Reward, (STRING)_VoiceBark) + THEN + StartVoiceBark(_VoiceBark, _Player); + + PROC + ProcShovelRewards((CHARACTERGUID)_Player,(STRING)_Reward) + AND + DB_ShovelRewardSurface(_Reward,(TRIGGERGUID)_Trigger, (STRING)_Type, (REAL)_Radius, (REAL)_Lifetime) + THEN + CreateSurface(_Trigger, _Type, _Radius, _Lifetime); + + PROC + ProcShovelRewards((CHARACTERGUID)_Player,(STRING)_Reward) + AND + DB_ShovelRewardItemScatter(_Reward,(ITEMGUID)_Item) + AND + GetPosition(_Item, _X, _Y, _Z) + THEN + SetOnStage(_Item, 1); + ItemScatterAt(_Item, _X, _Y, _Z); + + //END_REGION + + //REGION Tombstone AD + + IF + CharacterItemEvent(_Player,_Tombstone,"GEN_UsedTombstone") + AND + GetVarFixedString(_Tombstone,"Dialog",_Dialog) + AND + _Dialog != "" + THEN + Proc_StartDialog(1,_Dialog,_Tombstone,_Player); + + //END_REGION + + } + EXIT + { + + } +} +Goal(3).Title("__GLOBAL_Dialogs"); +Goal(3) +{ + INIT + { + // To intercept a dialog request, define one of these: + // PROC_GLOBAL_DialogStartRequested((GUIDSTRING)_Target,(GUIDSTRING)_Source) + // PROC_GLOBAL_DialogStartRequested_AfterGenerics((GUIDSTRING)_Target,(GUIDSTRING)_Source) + // The former is called before any generics (low attitude etc) are checked, but still after + // speaker availability checks are confirmed (not dead, not in combat). + // Start your own dialog in one of those PROCs if the conditions are right, and set + // DB_FoundDialog(_Target,_Source) if you want to prevent the default dialog to be searched/started + // + + DB_AnimalFoodVars("FoodTemplate1"); + DB_AnimalFoodVars("FoodTemplate2"); + DB_AnimalFoodVars("FoodTemplate3"); + DB_AnimalFoodVars("FoodTemplate4"); + DB_AnimalFoodVars("FoodTemplate5"); + DB_AnimalFoodVars("FoodTemplate6"); + + } + KB + { + //REGION HasMet + IF + DB_HasMetCharactersToCheck(_NPC,_PC) + THEN + ProcSetHasMetTag(_Npc,_PC); + + IF + DB_HasMetCharactersToCheck(_NPC,_PC) + THEN + NOT DB_HasMetCharactersToCheck(_NPC,_PC); + + PROC + Proc_Dialogs_CharactersHaveMetInThisShape((GUIDSTRING)_Npc,(CHARACTERGUID)_Player) + THEN + SetTag(_NPC,"HasMet"); + + PROC + ProcSetHasMetTag((GUIDSTRING)_Npc,(CHARACTERGUID)_Player) + AND + DB_CharacterPolymorphedInto(_Player,(STRING)_Race) + AND + DB_HasMet(_Npc,_Player,(STRING)_Race) + THEN + Proc_Dialogs_CharactersHaveMetInThisShape(_Npc,_Player); + + PROC + ProcSetHasMetTag((GUIDSTRING)_Npc,(CHARACTERGUID)_Player) + AND + NOT DB_CharacterPolymorphedInto(_Player,_) + AND + DB_HasMet(_Npc,_Player,"") + THEN + Proc_Dialogs_CharactersHaveMetInThisShape(_Npc,_Player); + + IF + DialogEnded(_Diag,_Inst) + AND + DB_DialogNPCs(_Inst,_Npc,_) + AND + DB_DialogPlayers(_Inst,_Player,_) + THEN + ProcSetHasMetDBEntry(_Diag,(GUIDSTRING)_Npc,(CHARACTERGUID)_Player); + + PROC + ProcSetHasMetDBEntry((STRING)_Diag,(GUIDSTRING)_Npc,(CHARACTERGUID)_Player) + AND + DB_CharacterPolymorphedInto(_Player,_Race) + THEN + DB_HasMet(_Npc,_Player,_Race); + + PROC + ProcSetHasMetDBEntry((STRING)_Diag,(GUIDSTRING)_Npc,(CHARACTERGUID)_Player) + AND + NOT DB_CharacterPolymorphedInto(_Player,_) + THEN + DB_HasMet(_Npc,_Player,""); + + + IF + DialogEnded(_Diag,_Inst) + AND + DB_DialogNPCs(_Inst,_Npc,_) + THEN + ClearTag(_Npc,"HasMet"); + //END_REGION + + //REGION Tag Priority Dialogs + PROC + PROC_GLOBAL_DialogStartRequested((GUIDSTRING)_NPC,(GUIDSTRING)_Player) + THEN + PROC_GLO_Origins_CheckTagPriorityDialogs(_NPC,_Player); + + PROC + PROC_GLO_Origins_CheckTagPriorityDialogs((GUIDSTRING)_NPC,(GUIDSTRING)_Player) + AND + DB_TagPriorityDialog(_NPC, (STRING)_Dialog, (STRING)_PriorityTag) + AND + NOT DB_GLO_OriginsFoundTagPriorityPlayer(1) + AND + IsTagged(_Player,_PriorityTag,0) + AND + DB_IsPlayer(_OtherPlayer) + AND + QRY_SpeakerIsAvailableAndInDialogRange(_OtherPlayer, _Player) + AND + _OtherPlayer != _Player + AND + CharacterGetReservedUserID((CHARACTERGUID)_Player,_ID) + AND + CharacterGetReservedUserID((CHARACTERGUID)_OtherPlayer,_ID) + AND + IsTagged(_OtherPlayer,_PriorityTag,1) + THEN + DB_GLO_OriginsFoundTagPriorityPlayer(1); + ProcForceStopDialog(_NPC); + Proc_StartDialog(0,_Dialog,_NPC,_OtherPlayer); + PROC_GLO_Origins_ClearTaggedPrioritiesForDialog(_Dialog); + + PROC + PROC_GLO_Origins_ClearTaggedPrioritiesForDialog((STRING)_Dialog) + AND + DB_TagPriorityDialog(_NPC,_Dialog,_PriorityTag) + THEN + NOT DB_TagPriorityDialog(_NPC,_Dialog,_PriorityTag); + + PROC + PROC_GLO_Origins_CheckTagPriorityDialogs((GUIDSTRING)_NPC,(GUIDSTRING)_Player) + THEN + NOT DB_GLO_OriginsFoundTagPriorityPlayer(1); + + //END_REGION + + + //REGION The Only Allowed Dialog Starting + PROC + Proc_StartDialog((INTEGER)_Automated,(STRING)_Dialog,(GUIDSTRING)_Speaker1) + AND + QRY_StartDialog(_Automated,_Dialog,_Speaker1) + THEN + DB_NOOP(1); + + PROC + Proc_StartDialog((INTEGER)_Automated,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2) + AND + NOT DB_OriginMomentTag(_Dialog,(STRING)_,(STRING)_) + AND + NOT DB_OriginMomentTag_HighPriority(_Dialog,(STRING)_,(STRING)_) + AND + NOT DB_OriginRecruitmentDialog((CHARACTERGUID)_,_Dialog) + AND + QRY_StartDialog(_Automated,_Dialog,_Speaker1,_Speaker2) + THEN + DB_NOOP(1); + + PROC + Proc_StartDialog((INTEGER)_Automated,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3) + AND + NOT DB_OriginMomentTag_3SP(_Dialog,(STRING)_,(STRING)_) + AND + NOT DB_OriginMomentTag_HighPriority_3SP(_Dialog,(STRING)_,(STRING)_) + AND + QRY_StartDialog(_Automated,_Dialog,_Speaker1,_Speaker2,_Speaker3) + THEN + DB_NOOP(1); + + PROC + Proc_StartDialog((INTEGER)_Automated,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4) + AND + QRY_StartDialog(_Automated,_Dialog,_Speaker1,_Speaker2,_Speaker3,_Speaker4) + THEN + DB_NOOP(1); + + PROC + Proc_StartDialog((INTEGER)_Automated,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4,(GUIDSTRING)_Speaker5) + AND + QRY_StartDialog(_Automated,_Dialog,_Speaker1,_Speaker2,_Speaker3,_Speaker4,_Speaker5) + THEN + DB_NOOP(1); + + PROC + Proc_StartDialog((INTEGER)_Automated,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4,(GUIDSTRING)_Speaker5,(GUIDSTRING)_Speaker6) + AND + QRY_StartDialog(_Automated,_Dialog,_Speaker1,_Speaker2,_Speaker3,_Speaker4,_Speaker5,_Speaker6) + THEN + DB_NOOP(1); + + QRY + QRY_StartDialog(1,(STRING)_Dialog,(GUIDSTRING)_Speaker1) + AND + QRY_SpeakerIsAvailable(_Speaker1,1) + AND + StartDialog_Internal(_Dialog,0,_Speaker1,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1); + + QRY + QRY_StartDialog(1,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2) + AND + QRY_SpeakerIsAvailable(_Speaker1,1) + AND + QRY_SpeakerIsAvailable(_Speaker2,1) + AND + StartDialog_Internal(_Dialog,0,_Speaker1,_Speaker2,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2); + + QRY + QRY_StartDialog(1,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3) + AND + QRY_SpeakerIsAvailable(_Speaker1,1) + AND + QRY_SpeakerIsAvailable(_Speaker2,1) + AND + QRY_SpeakerIsAvailable(_Speaker3,1) + AND + StartDialog_Internal(_Dialog,0,_Speaker1,_Speaker2,_Speaker3,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2, (GUIDSTRING)_Speaker3); + + QRY + QRY_StartDialog(1,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4) + AND + QRY_SpeakerIsAvailable(_Speaker1,1) + AND + QRY_SpeakerIsAvailable(_Speaker2,1) + AND + QRY_SpeakerIsAvailable(_Speaker3,1) + AND + QRY_SpeakerIsAvailable(_Speaker4,1) + AND + StartDialog_Internal(_Dialog,0,_Speaker1,_Speaker2,_Speaker3,_Speaker4,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2, (GUIDSTRING)_Speaker3, (GUIDSTRING)_Speaker4); + + QRY + QRY_StartDialog(1,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4,(GUIDSTRING)_Speaker5) + AND + QRY_SpeakerIsAvailable(_Speaker1,1) + AND + QRY_SpeakerIsAvailable(_Speaker2,1) + AND + QRY_SpeakerIsAvailable(_Speaker3,1) + AND + QRY_SpeakerIsAvailable(_Speaker4,1) + AND + QRY_SpeakerIsAvailable(_Speaker5,1) + AND + StartDialog_Internal(_Dialog,0,_Speaker1,_Speaker2,_Speaker3,_Speaker4,_Speaker5,NULL_00000000-0000-0000-0000-000000000000,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2, (GUIDSTRING)_Speaker3, (GUIDSTRING)_Speaker4, (GUIDSTRING)_Speaker5,NULL_00000000-0000-0000-0000-000000000000); + + QRY + QRY_StartDialog(1,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4,(GUIDSTRING)_Speaker5,(GUIDSTRING)_Speaker6) + AND + QRY_SpeakerIsAvailable(_Speaker1,1) + AND + QRY_SpeakerIsAvailable(_Speaker2,1) + AND + QRY_SpeakerIsAvailable(_Speaker3,1) + AND + QRY_SpeakerIsAvailable(_Speaker4,1) + AND + QRY_SpeakerIsAvailable(_Speaker5,1) + AND + QRY_SpeakerIsAvailable(_Speaker6,1) + AND + StartDialog_Internal(_Dialog,0,_Speaker1,_Speaker2,_Speaker3,_Speaker4,_Speaker5,_Speaker6,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2, (GUIDSTRING)_Speaker3, (GUIDSTRING)_Speaker4, (GUIDSTRING)_Speaker5, (GUIDSTRING)_Speaker6); + + QRY + QRY_StartDialog(0,(STRING)_Dialog,(GUIDSTRING)_Speaker1) + AND + QRY_SpeakerIsAvailable(_Speaker1) + AND + QRY_PrepForInteractiveDialog(_Speaker1) + AND + StartDialog_Internal(_Dialog,1,_Speaker1,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker1,1); + ProcItemSetInvulnerableForDialog(_Speaker1); + + QRY + QRY_StartDialog(0,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2) + AND + QRY_SpeakerIsAvailable(_Speaker1) + AND + QRY_SpeakerIsAvailable(_Speaker2) + AND + QRY_PrepForInteractiveDialog(_Speaker1) + AND + QRY_PrepForInteractiveDialog(_Speaker2) + AND + StartDialog_Internal(_Dialog,1,_Speaker1,_Speaker2,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2); + ProcFaceCharacter(_Speaker1,_Speaker2); + ProcFaceCharacter(_Speaker2,_Speaker1); + ProcItemSetInvulnerableForDialog(_Speaker1); + ProcItemSetInvulnerableForDialog(_Speaker2); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker1,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker2,1); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker2); + + QRY + QRY_StartDialog(0,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3) + AND + QRY_SpeakerIsAvailable(_Speaker1) + AND + QRY_SpeakerIsAvailable(_Speaker2) + AND + QRY_SpeakerIsAvailable(_Speaker3) + AND + QRY_PrepForInteractiveDialog(_Speaker1) + AND + QRY_PrepForInteractiveDialog(_Speaker2) + AND + QRY_PrepForInteractiveDialog(_Speaker3) + AND + StartDialog_Internal(_Dialog,1,_Speaker1,_Speaker2,_Speaker3,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2, (GUIDSTRING)_Speaker3); + ProcFaceCharacter(_Speaker1,_Speaker3); + ProcFaceCharacter(_Speaker2,_Speaker3); + ProcFaceCharacter(_Speaker3,_Speaker1); + ProcItemSetInvulnerableForDialog(_Speaker1); + ProcItemSetInvulnerableForDialog(_Speaker2); + ProcItemSetInvulnerableForDialog(_Speaker3); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker1,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker2,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker3,1); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker2); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker3); + + + QRY + QRY_StartDialog(0,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4) + AND + QRY_SpeakerIsAvailable(_Speaker1) + AND + QRY_SpeakerIsAvailable(_Speaker2) + AND + QRY_SpeakerIsAvailable(_Speaker3) + AND + QRY_SpeakerIsAvailable(_Speaker4) + AND + QRY_PrepForInteractiveDialog(_Speaker1) + AND + QRY_PrepForInteractiveDialog(_Speaker2) + AND + QRY_PrepForInteractiveDialog(_Speaker3) + AND + QRY_PrepForInteractiveDialog(_Speaker4) + AND + StartDialog_Internal(_Dialog,1,_Speaker1,_Speaker2,_Speaker3,_Speaker4,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2, (GUIDSTRING)_Speaker3, (GUIDSTRING)_Speaker4); + ProcFaceCharacter(_Speaker1,_Speaker4); + ProcFaceCharacter(_Speaker2,_Speaker4); + ProcFaceCharacter(_Speaker3,_Speaker4); + ProcFaceCharacter(_Speaker4,_Speaker1); + ProcItemSetInvulnerableForDialog(_Speaker1); + ProcItemSetInvulnerableForDialog(_Speaker2); + ProcItemSetInvulnerableForDialog(_Speaker3); + ProcItemSetInvulnerableForDialog(_Speaker4); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker1,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker2,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker3,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker4,1); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker2); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker3); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker4); + + + QRY + QRY_StartDialog(0,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4,(GUIDSTRING)_Speaker5) + AND + QRY_SpeakerIsAvailable(_Speaker1) + AND + QRY_SpeakerIsAvailable(_Speaker2) + AND + QRY_SpeakerIsAvailable(_Speaker3) + AND + QRY_SpeakerIsAvailable(_Speaker4) + AND + QRY_SpeakerIsAvailable(_Speaker5) + AND + QRY_PrepForInteractiveDialog(_Speaker1) + AND + QRY_PrepForInteractiveDialog(_Speaker2) + AND + QRY_PrepForInteractiveDialog(_Speaker3) + AND + QRY_PrepForInteractiveDialog(_Speaker4) + AND + QRY_PrepForInteractiveDialog(_Speaker5) + AND + StartDialog_Internal(_Dialog,1,_Speaker1,_Speaker2,_Speaker3,_Speaker4,_Speaker5,NULL_00000000-0000-0000-0000-000000000000,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2, (GUIDSTRING)_Speaker3, (GUIDSTRING)_Speaker4, (GUIDSTRING)_Speaker5); + ProcFaceCharacter(_Speaker1,_Speaker5); + ProcFaceCharacter(_Speaker2,_Speaker5); + ProcFaceCharacter(_Speaker3,_Speaker5); + ProcFaceCharacter(_Speaker4,_Speaker5); + ProcFaceCharacter(_Speaker5,_Speaker1); + ProcItemSetInvulnerableForDialog(_Speaker1); + ProcItemSetInvulnerableForDialog(_Speaker2); + ProcItemSetInvulnerableForDialog(_Speaker3); + ProcItemSetInvulnerableForDialog(_Speaker4); + ProcItemSetInvulnerableForDialog(_Speaker5); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker1,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker2,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker3,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker4,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker5,1); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker2); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker3); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker4); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker5); + + QRY + QRY_StartDialog(0,(STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4,(GUIDSTRING)_Speaker5,(GUIDSTRING)_Speaker6) + AND + QRY_SpeakerIsAvailable(_Speaker1) + AND + QRY_SpeakerIsAvailable(_Speaker2) + AND + QRY_SpeakerIsAvailable(_Speaker3) + AND + QRY_SpeakerIsAvailable(_Speaker4) + AND + QRY_SpeakerIsAvailable(_Speaker5) + AND + QRY_SpeakerIsAvailable(_Speaker6) + AND + QRY_PrepForInteractiveDialog(_Speaker1) + AND + QRY_PrepForInteractiveDialog(_Speaker2) + AND + QRY_PrepForInteractiveDialog(_Speaker3) + AND + QRY_PrepForInteractiveDialog(_Speaker4) + AND + QRY_PrepForInteractiveDialog(_Speaker5) + AND + QRY_PrepForInteractiveDialog(_Speaker6) + AND + StartDialog_Internal(_Dialog,1,_Speaker1,_Speaker2,_Speaker3,_Speaker4,_Speaker5,_Speaker6,1) + THEN + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2, (GUIDSTRING)_Speaker3, (GUIDSTRING)_Speaker4, (GUIDSTRING)_Speaker5, (GUIDSTRING)_Speaker6); + ProcFaceCharacter(_Speaker1,_Speaker6); + ProcFaceCharacter(_Speaker2,_Speaker6); + ProcFaceCharacter(_Speaker3,_Speaker6); + ProcFaceCharacter(_Speaker4,_Speaker6); + ProcFaceCharacter(_Speaker5,_Speaker6); + ProcFaceCharacter(_Speaker6,_Speaker1); + ProcItemSetInvulnerableForDialog(_Speaker1); + ProcItemSetInvulnerableForDialog(_Speaker2); + ProcItemSetInvulnerableForDialog(_Speaker3); + ProcItemSetInvulnerableForDialog(_Speaker4); + ProcItemSetInvulnerableForDialog(_Speaker5); + ProcItemSetInvulnerableForDialog(_Speaker6); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker1,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker2,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker3,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker4,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker5,1); + CharacterMakeStoryNpc((CHARACTERGUID)_Speaker6,1); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker2); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker3); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker4); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker5); + DB_HasMetCharactersToCheck(_Speaker1,_Speaker6); + + QRY + QRY_PrepForInteractiveDialog((GUIDSTRING)_Speaker) + THEN + DialogRequestStop(_Speaker); + //END_REGION + + //REGION Setting Items in Dialog Invulnerable + PROC + ProcItemSetInvulnerableForDialog((GUIDSTRING)_Speaker) + AND + ObjectIsItem(_Speaker,1) + THEN + SetInvulnerable_UseProcSetInvulnerable(_Speaker,1); + //END_REGION + + //REGION Flags Set Up The Start Of Dialog + PROC + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1) + THEN + DB_NOOP(1); + + PROC + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2) + THEN + DB_NOOP(1); + + PROC + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3) + THEN + DB_NOOP(1); + + PROC + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4) + THEN + DB_NOOP(1); + + PROC + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4,(GUIDSTRING)_Speaker5) + THEN + DB_NOOP(1); + + PROC + Proc_DialogFlagSetup((STRING)_Dialog,(GUIDSTRING)_Speaker1,(GUIDSTRING)_Speaker2,(GUIDSTRING)_Speaker3,(GUIDSTRING)_Speaker4,(GUIDSTRING)_Speaker5,(GUIDSTRING)_Speaker6) + THEN + DB_NOOP(1); + //END_REGION + + IF + DialogEnded(_,_Inst) + THEN + DB_MarkedForDelete(_Inst); + ProcClearDialogFlagsForPlayers(_Inst); + ProcClearDialogFlagsForNPCs(_Inst); + + //REGION Animal Food Dialogs + PROC + ProcSetAnimalFoodEvents((CHARACTERGUID)_Player,_) + THEN + SetVarInteger(_Player,"GEN_HasAnimalFood",0); + + PROC + ProcSetAnimalFoodEvents((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_AnimalFoodVars(_Var) + AND + GetVarFixedString(_Npc,_Var,_TempVal) + AND + _TempVal!="DONTEAT" + AND + QryItemTemplateInMagicPockets(_Player,_tempVal) + THEN + SetVarInteger(_Player,"GEN_HasAnimalFood",1); + + PROC + ProcGiveAnimalFood((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_AnimalFoodVars(_Var) + AND + GetVarFixedString(_Npc,_Var,_TempVal) + AND + _TempVal!="DONTEAT" + AND + NOT DB_FoodGiven(_Player) + AND + QryRemoveItemTemplateFromMagicPockets(_Player,_TempVal,1) + THEN + DB_FoodGiven(_Player); + CharacterAddAttitudeTowardsPlayer(_Npc,_Player,5); + + PROC + ProcGiveAnimalFood(_Player,_Npc) + THEN + NOT DB_FoodGiven(_Player); + + IF + ObjectFlagSet("GEN_PlayerGivesFood",_Player,_Inst) + AND + DB_DialogNPCs(_Inst,_Npc,1) + THEN + ProcGiveAnimalFood((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc); + //END_REGION + + //REGION Dialogs that must not be interceptable by custom scripts + //END_REGION + + //REGION Custom global overrides + PROC + PROC_GLOBAL_DialogCustomOverride((GUIDSTRING)_Npc,(GUIDSTRING)_Player) + THEN + DB_NOOP(1); + + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_Npc) + THEN + PROC_GLOBAL_DialogCustomOverride(_Npc,_Player); + + //END_REGION + + //REGION Custom script dialog Intercepts + PROC + PROC_GLOBAL_DialogStartRequested((GUIDSTRING)_Npc,(GUIDSTRING)_Player) + THEN + DB_NOOP(1); + + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_Npc) + AND + NOT DB_FoundDialog(_Npc,_Player) + THEN + // Reverse order of parameters to be consisted with DialogStartRequested() + PROC_GLOBAL_DialogStartRequested(_Npc,_Player); + //END_REGION + + //REGION Hostile Dialog + PROC + StartHostileDialog((GUIDSTRING)_Player,(GUIDSTRING)_Npc) + AND + IsTagged(_Npc,"ANIMAL",1) + THEN + DB_FoundDialog(_Npc,_Player); + ProcSetAnimalFoodEvents((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc); + Proc_StartDialog(0,"GEB_Default_AnimalHostile",_Npc,_Player); //TODO Change this Dialog to a new Style Dialog + + PROC + StartHostileDialog((GUIDSTRING)_Player,(GUIDSTRING)_Npc) + AND + IsTagged(_Npc,"ANIMAL",0) + THEN + StartHostileDialog_1(_Player,_Npc); + + PROC + StartHostileDialog_1((GUIDSTRING)_Player,(GUIDSTRING)_Npc) + AND + DB_HostileDialog(_Npc,(STRING)_Dialog) + THEN + DB_FoundDialog(_Npc,_Player); + Proc_StartDialog(0,_Dialog,_Npc,_Player); + + PROC + StartHostileDialog_1((GUIDSTRING)_Player,(GUIDSTRING)_Npc) + AND + NOT DB_FoundDialog(_Npc,_Player) + THEN + DB_FoundDialog(_Npc,_Player); + Proc_StartDialog(0,"GEB_Default_Hostile",_Npc,_Player); + //END_REGION + + //REGION Companion Redirects & ADs + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_OtherPlayer) + AND + NOT DB_FoundDialog(_OtherPlayer,_Player) + AND + DB_IsPlayer((CHARACTERGUID)_Player) + AND + DB_IsPlayer((CHARACTERGUID)_OtherPlayer) + AND + CharacterGetReservedUserID(_Player,_PID) + AND + CharacterGetReservedUserID(_OtherPlayer,_OPID) + AND + _PID != _OPID + THEN + Proc_StartDialog(1,"GLO_AD_CompanionCantTalk",_OtherPlayer); + DB_FoundDialog(_OtherPlayer,_Player); + + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_OtherPlayer) + AND + NOT DB_FoundDialog(_OtherPlayer,_Player) + AND + DB_IsPlayer((CHARACTERGUID)_Player) + AND + DB_IsPlayer((CHARACTERGUID)_OtherPlayer) + AND + IsTagged(_Player,"AVATAR",0) + AND + IsTagged(_OtherPlayer,"AVATAR",0) + AND + DB_CompanionAvatarBond(_OtherPlayer,_Avatar) + AND + IsTagged(_Avatar,"AVATAR",1) + AND + CharacterGetReservedUserID(_Avatar,_PID) + AND + CharacterGetReservedUserID(_OtherPlayer,_PID) + AND + QRY_SpeakerIsAvailableAndInDialogRange(_Avatar,_OtherPlayer) + THEN + SelectAndStartDialog(_Avatar,_OtherPlayer); + MakePlayerActive(_Avatar); + DB_FoundDialog(_OtherPlayer,_Player); + + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_OtherPlayer) + AND + NOT DB_FoundDialog(_OtherPlayer,_Player) + AND + DB_IsPlayer((CHARACTERGUID)_Player) + AND + DB_IsPlayer((CHARACTERGUID)_OtherPlayer) + AND + IsTagged(_Player,"AVATAR",0) + AND + IsTagged(_OtherPlayer,"AVATAR",0) + THEN + Proc_StartDialog(1,"GLO_AD_CompanionCantTalk",_OtherPlayer); + DB_FoundDialog(_OtherPlayer,_Player); + + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_OtherPlayer) + AND + NOT DB_FoundDialog(_OtherPlayer,_Player) + AND + DB_IsPlayer((CHARACTERGUID)_Player) + AND + DB_IsPlayer((CHARACTERGUID)_OtherPlayer) + AND + ObjectGetFlag(_OtherPlayer,"GLO_Polymorphed",1) + THEN + Proc_StartDialog(1,"GLO_AD_CompanionCantTalk",_OtherPlayer); + DB_FoundDialog(_OtherPlayer,_Player); + + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_Companion) + AND + NOT DB_FoundDialog(_Companion,_Player) + AND + DB_GLO_PartyMembers_RecruiteeAvatarBond((CHARACTERGUID)_Companion,(CHARACTERGUID)_Player2) + AND + _Player != _Player2 + THEN + Proc_StartDialog(0,"GLO_NonBondedCompanionDialog",_Companion,_Player); + DB_FoundDialog(_Companion,_Player); + + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_Companion) + AND + NOT DB_FoundDialog(_Companion,_Player) + AND + DB_RelationshipDialogs((CHARACTERGUID)_Companion,_Dialog) + AND + DB_CompanionAvatarBond((CHARACTERGUID)_Companion,(CHARACTERGUID)_Player) + AND + QRY_StartDialog(0,_Dialog,_Companion,_Player) + THEN + NOT DB_RelationshipDialogs(_Companion,_Dialog); + DB_FoundDialog(_Companion,_Player); + + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_Npc) + AND + IsTagged(_NPC,"ANIMAL",0) + AND + NOT DB_FoundDialog(_Npc,_Player) + AND + CharacterGetAttitudeTowardsPlayer((CHARACTERGUID)_Npc,(CHARACTERGUID)_Player,_Att) + AND + _Att <= -45 + AND + NOT _Npc.DB_IsPlayer() + AND + NOT DB_NoLowAttitudeDialog(_Npc) + THEN + StartHostileDialog(_Player,_Npc); + DB_FoundDialog(_Npc,_Player); + //END_REGION + + //REGION Threatened Dialog + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_NPC) + AND + NOT DB_FoundDialog(_NPC,_Player) + AND + CharacterIsInFightMode((CHARACTERGUID)_Player,1) + AND + NOT DB_IsPlayer((CHARACTERGUID)_NPC) + AND + NOT DB_BlockThreatenedDialog(_NPC) + AND + IsTagged(_NPC,"ANIMAL",0) + AND + NOT DB_CombatCharacters(_Player,_) + THEN + StartThreatenedDialog(_NPC,_Player); + + PROC + StartThreatenedDialog((GUIDSTRING)_NPC,(GUIDSTRING)_Player) + AND + CharacterCanTrade((CHARACTERGUID)_NPC,_CanTrade) + THEN + DB_FoundDialog(_NPC,_Player); + Proc_StartDialog(0,"GEB_Warning_Weapons_StartDialog",_NPC,_Player); + CharacterSetCanTrade(_NPC,0); + DB_CouldTrade(_NPC,_CanTrade); + + IF + DialogEnded("GEB_Warning_Weapons_StartDialog",_Inst) + AND + DB_DialogNPCs(_Inst,_NPC,1) + AND + DB_CouldTrade((CHARACTERGUID)_NPC,_CanTrade) + THEN + NOT DB_CouldTrade(_NPC,_CanTrade); + CharacterSetCanTrade((CHARACTERGUID)_NPC,_CanTrade); + + //END_REGION + + //REGION Script intercept after generics + PROC + PROC_GLOBAL_DialogStartRequested_AfterGenerics((GUIDSTRING)_Npc,(GUIDSTRING)_Player) + THEN + DB_NOOP(1); + + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_Npc) + AND + NOT DB_FoundDialog(_Npc,_Player) + THEN + PROC_GLOBAL_DialogStartRequested_AfterGenerics(_Npc,_Player); + //END_REGION + + //REGION Dialog Start by clicking on NPC + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_Npc) + AND + NOT DB_FoundDialog(_Npc,_Player) + THEN + DB_FoundDialog(_Npc,_Player); + NPCDialogStartRequested(_Npc,_Player);// start the default dialog + + PROC + SelectAndStartDialog((GUIDSTRING)_Player,(GUIDSTRING)_Npc) + THEN + NOT DB_FoundDialog(_Npc,_Player); + + IF + DialogStartRequested(_Npc2,_Npc1) + AND + QRY_SpeakerIsAvailable(_Npc1) + AND + QRY_SpeakerIsAvailable(_Npc2) + THEN + SelectAndStartDialog(_Npc1,_Npc2); + + //END_REGION + + IF + CharacterDying(_Char) + THEN + DialogRequestStop(_Char); + + IF + CharacterUnlockedTalent(_Char,"AnimalEmpathy") + THEN + SetTag(_char,"PETPAL"); + + IF + CharacterLockedTalent(_Char,"AnimalEmpathy") + THEN + ClearTag(_char,"PETPAL"); + + IF + DB_IsPlayer(_Char) + AND + CharacterHasTalent(_Char,"AnimalEmpathy",1) + THEN + SetTag(_char,"PETPAL"); + + IF + CharacterCreationFinished(_Char) + AND + _Char != NULL_00000000-0000-0000-0000-000000000000 + AND + CharacterHasTalent(_Char,"AnimalEmpathy",0) + THEN + ClearTag(_char,"PETPAL"); + + //REGION Child dialogs + IF + ChildDialogRequested(_ChildDialog,_ParentInstance,_TargetInstance) + AND + DB_DialogPlayers(_ParentInstance,_Player,1) + THEN + ProcStartChildDialog(_ChildDialog,_ParentInstance,_TargetInstance); + + PROC + ProcStartChildDialog((STRING)_ChildDialog,(INTEGER)_ParentInstance,(INTEGER)_TargetInstance) + THEN + DB_TargetInstancespeakers(_TargetInstance,1,(CHARACTERGUID)NULL_00000000-0000-0000-0000-000000000000); + DB_TargetInstancespeakers(_TargetInstance,2,(CHARACTERGUID)NULL_00000000-0000-0000-0000-000000000000); + DB_TargetInstancespeakers(_TargetInstance,3,(CHARACTERGUID)NULL_00000000-0000-0000-0000-000000000000); + DB_TargetInstancespeakers(_TargetInstance,4,(CHARACTERGUID)NULL_00000000-0000-0000-0000-000000000000); + + PROC + ProcStartChildDialog((STRING)_ChildDialog,(INTEGER)_ParentInstance,(INTEGER)_TargetInstance) + AND + DB_DialogNumPlayers(_ParentInstance,_NumPlayers) + AND + DB_DialogNumNPCs(_ParentInstance,_NumNPCs) + AND + IntegerSum(_NumPlayers,_NumNPCs,_Total) + AND + _Total > 4 + THEN + DebugBreak("too many speakers to fit in the child dialog! Need custom scripting and/or extension on speaker limit"); + + PROC + ProcStartChildDialog(_,(INTEGER)_ParentInstance,(INTEGER)_TargetInstance) + AND + DB_DialogNPCs(_ParentInstance,_NPC,_Index) + THEN + NOT DB_TargetInstancespeakers(_TargetInstance,_Index,NULL_00000000-0000-0000-0000-000000000000); + DB_TargetInstancespeakers(_TargetInstance,_Index,(CHARACTERGUID)_NPC); + + PROC + ProcStartChildDialog(_,(INTEGER)_ParentInstance,(INTEGER)_TargetInstance) + AND + DB_DialogPlayers(_ParentInstance,_Player,_Index) + AND + DB_DialogNumNPCs(_ParentInstance,_NumNPCs) + AND + IntegerSum(_NumNPCs,_Index,_PlayerIndex) + THEN + NOT DB_TargetInstancespeakers(_TargetInstance,_PlayerIndex,NULL_00000000-0000-0000-0000-000000000000); + DB_TargetInstancespeakers(_TargetInstance,_PlayerIndex,(CHARACTERGUID)_Player); + + PROC + ProcStartChildDialog(_ChildDialog,(INTEGER)_ParentInstance,(INTEGER)_TargetInstance) + AND + DB_TargetInstancespeakers(_TargetInstance,1,_Speaker1) + AND + DB_TargetInstancespeakers(_TargetInstance,2,_Speaker2) + AND + DB_TargetInstancespeakers(_TargetInstance,3,_Speaker3) + AND + DB_TargetInstancespeakers(_TargetInstance,4,_Speaker4) + AND + DialogStartChildDialog(_ChildDialog,_ParentInstance,_TargetInstance,_Speaker1,_Speaker2,_Speaker3,_Speaker4,_) + THEN + DB_NOOP(1); + + PROC + ProcStartChildDialog(_ChildDialog,(INTEGER)_ParentInstance,(INTEGER)_TargetInstance) + AND + DB_TargetInstancespeakers(_TargetInstance,_Index,_Speaker) + THEN + NOT DB_TargetInstancespeakers(_TargetInstance,_Index,_Speaker); + //END_REGION + + } + EXIT + { + + } +} +Goal(4).Title("__GLOBAL_ExplorationBonus"); +Goal(4) +{ + INIT + { + + } + KB + { + IF + DB_ExplorationZones((TRIGGERGUID)_Trigger,(INTEGER)_Act,(INTEGER)_ActPArt,(INTEGER)_Gain) + AND + NOT DB_Subregion(_Trigger,_,_) //Subregions can give XP without being Oneshot + THEN + ProcTriggerRegisterForPlayers(_Trigger); + + IF + CharacterEnteredTrigger((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_ExplorationZones(_Trigger,(INTEGER)_Act,(INTEGER)_ActPart,(INTEGER)_Gain) + THEN + ProcAddXPToParty(_Player,_Trigger); + ProcCheckRemoveExplorationZone(_Trigger); + + + PROC + ProcAddXPToParty((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_ExplorationZones(_Trigger,_Act,_ActPart,_Gain) + AND + DB_IsPlayer(_OtherPlayer) + AND + NOT DB_ExplorationXPGiven(_OtherPlayer,_Trigger) + AND + CharacterIsInPartyWith(_OtherPlayer,_Player,1) + THEN + DB_ExplorationXPGiven(_OtherPlayer,_Trigger); + CharacterAddExplorationExperience(_OtherPlayer,_Act,_ActPart,_Gain); + + //Dont unregister if also a Subregion + IF + DB_ExplorationXPGiven(_OtherPlayer,_Trigger) + AND + NOT DB_Subregion(_Trigger,_,_) + THEN + TriggerUnregisterForCharacter(_Trigger,_OtherPlayer); + + PROC + ProcCheckRemoveExplorationZone((TRIGGERGUID)_Trigger) + AND + DB_IsPlayer(_Player) + AND + NOT DB_ExplorationXPGiven(_Player,_Trigger) + THEN + DB_ExplorationZoneStillOpen(1); + + PROC + ProcCheckRemoveExplorationZone(_Trigger) + AND + NOT DB_ExplorationZoneStillOpen(1) + AND + DB_ExplorationZones(_Trigger,_Act,_ActPart,_Gain) + THEN + NOT DB_ExplorationZones(_Trigger,_Act,_ActPart,_Gain); + + PROC + ProcCheckRemoveExplorationZone(_Trigger) + THEN + NOT DB_ExplorationZoneStillOpen(1); + + IF + CharacterJoinedParty(_Char) + AND + DB_ExplorationZones(_Trigger,_Act,_ActPart,_Gain) + AND + DB_ExplorationXPGiven(_Player,_Trigger) + AND + CharacterIsInPartyWith(_Player,_Char,1) + THEN + DB_ExplorationXPGiven(_Char,_Trigger); + ProcCheckRemoveExplorationZone(_Trigger); + + } + EXIT + { + + } +} +Goal(5).Title("__GLOBAL_HiddenWalls"); +Goal(5) +{ + INIT + { + DB_HiddenWallCount(0); + + } + KB + { + //REGION Use event to open hidden wall + + IF + GlobalFlagSet(_flag) + AND + DB_HiddenWallEvent((STRING)_flag, (INTEGER)_wallIndex) + THEN + PROC_OpenWall(_WallIndex); + + //END_REGION + + //REGION Action When Player Uses Item To Open Wall + + IF + CharacterUsedItem(_Player, _Item) + AND + _Player.DB_IsPlayer() + AND + DB_HiddenWallItem((ITEMGUID)_Item, (INTEGER)_WallIndex) + THEN + PROC_CommentHiddenEffect(_Player); + PROC_OpenWall(_WallIndex); + + //END_REGION + + //REGION Action When Player Uses Trigger To Open Wall + + IF + DB_HiddenWallTrigger(_trigger, _) + THEN + DB_HW_CharCountInTrigger(_trigger, 0); + + IF + CharacterEnteredTrigger(_, _trigger) + AND + DB_HiddenWallTrigger((TRIGGERGUID)_trigger, (INTEGER)_wallIndex) + AND + DB_HW_CharCountInTrigger(_trigger, _current) + AND + IntegerSum(_current, 1, _new) + THEN + NOT DB_HW_CharCountInTrigger(_trigger, _current); + DB_HW_CharCountInTrigger(_trigger, _new); + + IF + CharacterLeftTrigger(_, _trigger) + AND + DB_HiddenWallTrigger((TRIGGERGUID)_trigger, (INTEGER)_wallIndex) + AND + DB_HW_CharCountInTrigger(_trigger, _current) + AND + IntegerSubtract(_current, 1, _new) + THEN + NOT DB_HW_CharCountInTrigger(_trigger, _current); + DB_HW_CharCountInTrigger(_trigger, _new); + + IF + DB_HW_CharCountInTrigger(_trigger, _current) + AND + _current < 0 + THEN + NOT DB_HW_CharCountInTrigger(_trigger, _current); + DB_HW_CharCountInTrigger(_trigger, 0); + + IF + DB_HW_CharCountInTrigger(_trigger, _current) + AND + _current > 0 + AND + DB_HiddenWallTrigger(_trigger, _wallIndex) + THEN + PROC_OpenWall(_wallIndex); + + IF + DB_HW_CharCountInTrigger(_trigger, _current) + AND + _current == 0 + AND + DB_HiddenWallTrigger(_trigger, _wallIndex) + THEN + PROC_CloseWall(_wallIndex); + + + //END_REGION + + //REGION Action When Player Uses Skills To Open Wall + + IF + StoryEvent(_Wall, "Open") + AND + DB_HiddenWall(_WallIndex, (ITEMGUID)_Wall) + THEN + PROC_OpenWall(_WallIndex); + + //END_REGION + + //REGION Registering all the hidden walls + + PROC + PROC_Register_HiddenWall((ITEMGUID)_Wall) + AND + NOT DB_HiddenWall(_, (ITEMGUID)_Wall) + AND + DB_HiddenWallCount(_Current) + AND + IntegerSum(_Current, 1, _New) + THEN + NOT DB_HiddenWallCount(_Current); + DB_HiddenWallCount(_New); + DB_HiddenWall((INTEGER)_New, (ITEMGUID)_Wall); + DB_HW_ClosedWalls(_New); + + //END_REGION + + //REGION Open/Close Hidden walls + + PROC + PROC_OpenWall((INTEGER)_WallIndex) + AND + DB_HW_ClosedWalls(_WallIndex) + AND + DB_HiddenWall(_WallIndex, _Wall) + THEN + NOT DB_HW_ClosedWalls(_WallIndex); + PlayEffect(_Wall, "RS3_FX_GP_ScriptedEvent_Teleport_GenericSmoke_01"); + SetOnStage(_Wall, 0); + + PROC + PROC_CloseWall((INTEGER)_WallIndex) + AND + NOT DB_HW_ClosedWalls(_WallIndex) + AND + DB_HiddenWall(_WallIndex, _Wall) + THEN + DB_HW_ClosedWalls(_WallIndex); + PlayEffect(_Wall, "RS3_FX_GP_ScriptedEvent_Teleport_GenericSmoke_01"); + SetOnStage(_Wall, 1); + + //END_REGION + + } + EXIT + { + + } +} +Goal(6).Title("__GLOBAL_ItemInteraction"); +Goal(6) +{ + INIT + { + + } + KB + { + IF + CharacterUsedItemTemplate(_Player, _Template, _) + AND + _Player.DB_IsPlayer() + AND + DB_RecipeBook(_Template, (STRING)_ID) + THEN + UnlockJournalRecipe(_ID); + NOT DB_RecipeBook(_Template, _ID); + + PROC + Proc_ItemRotateYduration((ITEMGUID)_Item,(REAL)_Angle,(INTEGER)_DurationMS) + AND + RealProduct(_Angle,1000.0,_AngleProd) + AND + Real(_DurationMS,_DurationReal) + AND + RealDivide(_AngleProd,_DurationReal,_Speed) + THEN + ItemRotateY(_Item,_Angle,_Speed); + + PROC + Proc_ItemRotateToAngleYduration((ITEMGUID)_Item,(REAL)_Angle,(INTEGER)_DurationMS) + AND + RealProduct(_Angle,1000.0,_AngleProd) + AND + Real(_DurationMS,_DurationReal) + AND + RealDivide(_AngleProd,_DurationReal,_Speed) + THEN + ItemRotateY(_Item,_Angle,_Speed); + + } + EXIT + { + + } +} +Goal(7).Title("__GLOBAL_ItemRotationPuzzles"); +Goal(7) +{ + INIT + { + DB_IRP_Internal_IndexCount(0); + + } + KB + { + //REGION Initialization of databases + + PROC + PROC_Puzzle_RegisterRotatingItem((STRING)_puzzleName, (ITEMGUID)_item, (INTEGER)_solution) + AND + DB_IRP_Internal_IndexCount(_index) + THEN + DB_IRP_IncreaseInternalCount(); + DB_IRP_Internal_Items((INTEGER)_index, (ITEMGUID)_item, 0); + DB_IRP_Internal_Solutions((INTEGER)_index, (INTEGER)_solution); + DB_IRP_Internal_Puzzles((STRING)_puzzleName, (INTEGER)_index, 0); + PROC_IRP_Internal_IncreasePuzzleItemcount(_puzzleName); + + PROC + DB_IRP_IncreaseInternalCount() + AND + DB_IRP_Internal_IndexCount(_indexCount) + AND + IntegerSum(_indexCount, 1, _newIndex) + THEN + NOT DB_IRP_Internal_IndexCount(_indexCount); + DB_IRP_Internal_IndexCount(_newIndex); + + PROC + PROC_ItemRotatePuzzle_AddItemToHandle((ITEMGUID)_handle, (ITEMGUID)_item) + AND + DB_IRP_Internal_Items(_index, _item, _) + THEN + DB_IRP_Internal_Handles(_handle, _index); + + PROC + PROC_IRP_Internal_IncreasePuzzleItemcount((STRING)_puzzleName) + AND + NOT DB_IRP_Internal_PuzzlesTotalItemCount(_puzzleName, _) + THEN + DB_IRP_Internal_PuzzlesTotalItemCount(_puzzleName, 0); + DB_IRP_Internal_PuzzlesItemsSolved(_puzzleName, 0); + + PROC + PROC_IRP_Internal_IncreasePuzzleItemcount((STRING)_puzzleName) + AND + DB_IRP_Internal_PuzzlesTotalItemCount(_puzzleName, _count) + AND + IntegerSum(_count, 1, _newTotal) + THEN + NOT DB_IRP_Internal_PuzzlesTotalItemCount(_puzzleName, _count); + DB_IRP_Internal_PuzzlesTotalItemCount(_puzzleName, _newTotal); + + //END_REGION + + + //REGION Rotate items + + IF + CharacterUsedItem(_player, _handle) + AND + _player.DB_IsPlayer() + AND + DB_IRP_Internal_Handles(_handle, _index) + AND + DB_IRP_Internal_Items(_index, _item, _) + THEN + PROC_IRP_RotateItem(_item); + + IF + CharacterUsedItem(_player, _item) + AND + _player.DB_IsPlayer() + AND + DB_IRP_Internal_Items(_index, _item, _) + THEN + PROC_IRP_RotateItem(_item); + + PROC + PROC_IRP_RotateItem((ITEMGUID)_item) + AND + DB_IRP_Internal_Items(_index, _item, _turnCount) + AND + DB_IRP_Internal_Puzzles(_puzzleName, _index, _) + AND + IntegerSum(_turnCount, 1, _newTurnCount) + THEN + NOT DB_IRP_Internal_Items(_index, _item, _turnCount); + DB_IRP_Internal_Items(_index, _item, _newTurnCount); + ItemRotateY(_item, 90.0, 135.0); + PROC_IRP_CheckItemState(_item); + PROC_IRP_CheckPuzzleState(_puzzleName); + + IF + DB_IRP_Internal_Items(_index, _item, 4) + THEN + NOT DB_IRP_Internal_Items(_index, _item, 4); + DB_IRP_Internal_Items(_index, _item, 0); + + //END_REGION + + //REGION Check for item solution + + PROC + PROC_IRP_CheckItemState((ITEMGUID)_item) + AND + DB_IRP_Internal_Items(_index, _item, _turnCount) + AND + DB_IRP_Internal_Puzzles(_puzzleName, _index, 0) + AND + DB_IRP_Internal_Solutions(_index, _solution) + AND + _turnCount == _solution + THEN + NOT DB_IRP_Internal_Puzzles(_puzzleName, _index, 0); + DB_IRP_Internal_Puzzles(_puzzleName, _index, 1); + + PROC + PROC_IRP_CheckItemState((ITEMGUID)_item) + AND + DB_IRP_Internal_Items(_index, _item, _turnCount) + AND + DB_IRP_Internal_Puzzles(_puzzleName, _index, 1) + AND + DB_IRP_Internal_Solutions(_index, _solution) + AND + NOT _turnCount == _solution + THEN + NOT DB_IRP_Internal_Puzzles(_puzzleName, _index, 1); + DB_IRP_Internal_Puzzles(_puzzleName, _index, 0); + + //END_REGION + + //REGION Check for puzzle solution + + PROC + PROC_IRP_CheckPuzzleState((STRING)_puzzleName) + AND + DB_IRP_Internal_Puzzles(_puzzleName, _, 1) + AND + DB_IRP_Internal_PuzzlesItemsSolved(_puzzleName, _count) + AND + IntegerSum(_count, 1, _new) + THEN + NOT DB_IRP_Internal_PuzzlesItemsSolved(_puzzleName, _count); + DB_IRP_Internal_PuzzlesItemsSolved(_puzzleName, _new); + + PROC + PROC_IRP_CheckPuzzleState((STRING)_puzzleName) + AND + DB_IRP_Internal_PuzzlesItemsSolved(_puzzleName, _itemsSolved) + AND + NOT DB_IRP_Internal_PuzzlesTotalItemCount(_puzzleName, _itemsSolved) + THEN + NOT DB_IRP_Internal_PuzzlesItemsSolved(_puzzleName, _itemsSolved); + DB_IRP_Internal_PuzzlesItemsSolved(_puzzleName, 0); + GlobalClearFlag(_puzzleName); + + PROC + PROC_IRP_CheckPuzzleState((STRING)_puzzleName) + AND + DB_IRP_Internal_PuzzlesItemsSolved(_puzzleName, _itemsSolved) + AND + DB_IRP_Internal_PuzzlesTotalItemCount(_puzzleName, _itemsSolved) + THEN + NOT DB_IRP_Internal_PuzzlesItemsSolved(_puzzleName, _itemsSolved); + DB_IRP_Internal_PuzzlesItemsSolved(_puzzleName, 0); + GlobalSetFlag(_puzzleName); + + //END_REGION + + + } + EXIT + { + + } +} +Goal(8).Title("__OneshotDialogs"); +Goal(8) +{ + INIT + { + + } + KB + { + //REGION One Shot Normal Dialogs + IF + DB_OneShot_PlayerOnlyDialogTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC) + THEN + DB_OneShotPlayerOnlyTrigger(_Trigger); + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,1); + DB_OneShot_DialogSpeakers(_Trigger,_Npc,1); + + IF + DB_OneShot_DialogTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC) + THEN + DB_OneShotPlayerTrigger(_Trigger); + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,1); + DB_OneShot_DialogSpeakers(_Trigger,_Npc,1); + + IF + DB_OneShot_DialogTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC,(CHARACTERGUID)_NPC2) + THEN + DB_OneShotPlayerTrigger(_Trigger); + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,2); + DB_OneShot_DialogSpeakers(_Trigger,_Npc,1); + DB_OneShot_DialogSpeakers(_Trigger,_Npc2,2); + + IF + DB_OneShot_DialogTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC,(CHARACTERGUID)_NPC2,(CHARACTERGUID)_NPC3) + THEN + DB_OneShotPlayerTrigger(_Trigger); + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,3); + DB_OneShot_DialogSpeakers(_Trigger,_Npc,1); + DB_OneShot_DialogSpeakers(_Trigger,_Npc2,2); + DB_OneShot_DialogSpeakers(_Trigger,_Npc3,3); + + IF + DB_OneShot_DialogTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC,(CHARACTERGUID)_NPC2,(CHARACTERGUID)_NPC3,(CHARACTERGUID)_NPC4) + THEN + DB_OneShotPlayerTrigger(_Trigger); + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,4); + DB_OneShot_DialogSpeakers(_Trigger,_Npc,1); + DB_OneShot_DialogSpeakers(_Trigger,_Npc2,2); + DB_OneShot_DialogSpeakers(_Trigger,_Npc3,3); + DB_OneShot_DialogSpeakers(_Trigger,_Npc4,4); + + PROC + ProcCheckIfNPCsBusy((TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakers(_Trigger,_Npc,_) + AND + NOT QRY_SpeakerIsAvailable(_Npc,1) + THEN + DB_OneShot_BusyNPC(_Trigger); + + PROC + ProcDoStartOneShotDialog((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,1) + AND + DB_OneShot_DialogSpeakers(_Trigger,_Npc,1) + THEN + Proc_StartDialog(0,_Dialog,_Npc,_Player); + + PROC + ProcDoStartOneShotDialog((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,2) + AND + DB_OneShot_DialogSpeakers(_Trigger,_Npc,1) + AND + DB_OneShot_DialogSpeakers(_Trigger,_Npc2,2) + THEN + Proc_StartDialog(0,_Dialog,_Npc,_Npc2,_Player); + + PROC + ProcDoStartOneShotDialog((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,3) + AND + DB_OneShot_DialogSpeakers(_Trigger,_Npc,1) + AND + DB_OneShot_DialogSpeakers(_Trigger,_Npc2,2) + AND + DB_OneShot_DialogSpeakers(_Trigger,_Npc3,3) + THEN + Proc_StartDialog(0,_Dialog,_Npc,_Npc2,_Npc3,_Player); + + PROC + ProcStartOneShotDialog((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + NOT DB_OneShot_BusyNPC(_Trigger) + THEN + ProcDoStartOneShotDialog(_Player,_Trigger); + + PROC + ProcClearOneShotCount((TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,1) + AND + DB_OneShot_DialogTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC) + THEN + NOT DB_OneShot_DialogTrigger(_Trigger,_Dialog,_NPC); + + PROC + ProcClearOneShotCount((TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,2) + AND + DB_OneShot_DialogTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC,(CHARACTERGUID)_NPC2) + THEN + NOT DB_OneShot_DialogTrigger(_Trigger,_Dialog,_NPC,_NPC2); + + PROC + ProcClearOneShotCount((TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,3) + AND + DB_OneShot_DialogTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC,(CHARACTERGUID)_NPC2,(CHARACTERGUID)_NPC3) + THEN + NOT DB_OneShot_DialogTrigger(_Trigger,_Dialog,_NPC,_NPC2,_NPC3); + + + PROC + ProcClearOneShotCount((TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,4) + AND + DB_OneShot_DialogTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC,(CHARACTERGUID)_NPC2,(CHARACTERGUID)_NPC3,(CHARACTERGUID)_NPC4) + THEN + NOT DB_OneShot_DialogTrigger(_Trigger,_Dialog,_NPC,_NPC2,_NPC3,_NPC4); + + PROC + ProcClearOneShotCount((TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,_Count) + THEN + NOT DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,_Count); + + PROC + ProcClearOneShotSpeakers((TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakers(_Trigger,_Npc,_Count) + THEN + NOT DB_OneShot_DialogSpeakers(_Trigger,_Npc,_Count); + + PROC + ProcOneShotDialogCleanup((TRIGGERGUID)_Trigger) + THEN + ProcClearOneShotCount(_Trigger); + ProcClearOneShotSpeakers(_Trigger); + + PROC + RemoveOneShotDialog((TRIGGERGUID)_Trigger) + THEN + ProcOneShotDialogCleanup(_Trigger); + ProcTriggerUnregisterForPlayers(_Trigger); + NOT DB_OneShotPlayerTrigger(_Trigger); + + IF + DB_Dead(_Npc) + AND + DB_OneShot_DialogSpeakers(_Trigger,_Npc,_) + THEN + RemoveOneShotDialog(_Trigger); + + PROC + ProcOneShotTriggerEntered((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogSpeakerCount(_Trigger,_,_) + AND + QRY_SpeakerIsAvailable(_Player) + THEN + ProcCheckIfNPCsBusy(_Trigger); //TODO: do this busy check? Dialogs won't ever start if one of these NPCs is busy + ProcStartOneShotDialog(_Player,_Trigger); + + PROC + ProcStartOneShotDialog(_,(TRIGGERGUID)_Trigger) + THEN + NOT DB_OneShot_BusyNPC(_Trigger); + + PROC + ProcStartOneShotDialog(_,(TRIGGERGUID)_Trigger) + THEN + ProcOneShotDialogCleanup(_Trigger); + + //if the dialog is started (manually), cleanup so this doesn't get started again + IF + DialogStarted(_Dialog,_) + AND + DB_OneShot_DialogSpeakerCount(_Trigger,_Dialog,_Count) + THEN + ProcOneShotDialogCleanup(_Trigger); + ProcTriggerUnregisterForPlayers(_Trigger); + NOT DB_OneShotPlayerTrigger(_Trigger); //because this might not have triggerd yet and we don't want to leave these around + + //END_REGION + + //REGION One Shot Automated Dialogs + + IF + DB_OneShot_ADTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC) + THEN + DB_OneShotPlayerTrigger(_Trigger); + DB_OneShot_ADSpeakerCount(_Trigger,_Dialog,1); + DB_OneShot_ADSpeakers(_Trigger,_Npc,1); + + IF + DB_OneShot_ADTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC,(CHARACTERGUID)_NPC2) + THEN + DB_OneShotPlayerTrigger(_Trigger); + DB_OneShot_ADSpeakerCount(_Trigger,_Dialog,2); + DB_OneShot_ADSpeakers(_Trigger,_Npc,1); + DB_OneShot_ADSpeakers(_Trigger,_Npc2,2); + + PROC + ProcDoStartOneShotAD((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_OneShot_ADSpeakerCount(_Trigger,_Dialog,1) + AND + DB_OneShot_ADSpeakers(_Trigger,_Npc,1) + THEN + Proc_StartDialog(1,_Dialog,_Npc); + + PROC + ProcDoStartOneShotAD((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_OneShot_ADSpeakerCount(_Trigger,_Dialog,2) + AND + DB_OneShot_ADSpeakers(_Trigger,_Npc,1) + AND + DB_OneShot_ADSpeakers(_Trigger,_Npc2,2) + THEN + Proc_StartDialog(1,_Dialog,_Npc,_Npc2); + + PROC + ProcClearOneShotADCount((TRIGGERGUID)_Trigger) + AND + DB_OneShot_ADSpeakerCount(_Trigger,_Dialog,1) + AND + DB_OneShot_ADTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC) + THEN + NOT DB_OneShot_ADTrigger(_Trigger,_Dialog,_NPC); + + PROC + ProcClearOneShotADCount((TRIGGERGUID)_Trigger) + AND + DB_OneShot_ADSpeakerCount(_Trigger,_Dialog,2) + AND + DB_OneShot_ADTrigger((TRIGGERGUID)_Trigger,(STRING)_Dialog,(CHARACTERGUID)_NPC,(CHARACTERGUID)_NPC2) + THEN + NOT DB_OneShot_ADTrigger(_Trigger,_Dialog,_NPC,_NPC2); + + PROC + ProcClearOneShotADSpeakers((TRIGGERGUID)_Trigger) + AND + DB_OneShot_ADSpeakers(_Trigger,_Npc,_Count) + THEN + NOT DB_OneShot_ADSpeakers(_Trigger,_Npc,_Count); + + PROC + ProcOneShotADCleanup((TRIGGERGUID)_Trigger) + THEN + ProcClearOneShotADCount(_Trigger); + ProcClearOneShotADSpeakers(_Trigger); + + PROC + RemoveOneShotAD((TRIGGERGUID)_Trigger) + THEN + ProcOneShotADCleanup(_Trigger); + ProcTriggerUnregisterForPlayers(_Trigger); + NOT DB_OneShotPlayerTrigger(_Trigger); + + IF + DB_Dead(_Npc) + AND + DB_OneShot_ADSpeakers(_Trigger,_Npc,_) + THEN + RemoveOneShotAD(_Trigger); + + PROC + ProcOneShotTriggerEntered((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_OneShot_ADSpeakerCount(_Trigger,_,_) + AND + DB_OneShot_ADSpeakers(_Trigger,_Npc,1) + AND + QRY_SpeakerIsAvailable(_Player) + AND + QRY_SpeakerIsAvailable(_Npc) + THEN + ProcDoStartOneShotAD(_Player,_Trigger); + ProcOneShotADCleanup(_Trigger); + + //if the dialog is started (manually), cleanup so this doesn't get started again + IF + AutomatedDialogStarted(_Dialog,_) + AND + DB_OneShot_ADSpeakerCount(_Trigger,_Dialog,_Count) + THEN + ProcOneShotADCleanup(_Trigger); + ProcTriggerUnregisterForPlayers(_Trigger); + + //END_REGION + + //REGION One Shot Voice Bark + + IF + DB_OneShot_VoiceBarkTrigger((TRIGGERGUID)_Trigger,(STRING)_VoiceBark) + THEN + DB_OneShotPlayerTrigger(_Trigger); + + PROC + ProcOneShotTriggerEntered(_Player,_Trigger) + AND + DB_OneShot_VoiceBarkTrigger(_Trigger,_VoiceBark) + AND + QRY_SpeakerIsAvailable(_Player) + THEN + StartVoiceBark(_VoiceBark,_Player); + + IF + VoiceBarkStarted(_VoiceBark,_) + AND + DB_OneShot_VoiceBarkTrigger(_Trigger,_VoiceBark) + THEN + NOT DB_OneShot_VoiceBarkTrigger(_Trigger,_VoiceBark); + + IF + VoiceBarkFailed(_VoiceBark) + AND + DB_OneShot_VoiceBarkTrigger(_Trigger,_VoiceBark) + THEN + NOT DB_OneShot_VoiceBarkTrigger(_Trigger,_VoiceBark); + + //END_REGION + + } + EXIT + { + + } +} +Goal(9).Title("__PROC"); +Goal(9) +{ + INIT + { + DB_InternalGroup_Count(0); + + + } + KB + { + PROC + CharacterGiveReward((CHARACTERGUID)_Player,(STRING)_Reward) + THEN + CharacterGiveReward(_Player,_Reward,1); + + //REGION Defaults for item adding + PROC + ItemTemplateAddTo((STRING)_ItemTemplate, (GUIDSTRING)_Object, (INTEGER)_Count) + THEN + ItemTemplateAddTo(_ItemTemplate,_Object,_Count,1); + + PROC + ItemToInventory((ITEMGUID)_Item,(GUIDSTRING)_Container) + THEN + ItemToInventory(_Item,_Container,1,1,1); + + PROC + ItemToInventory((ITEMGUID)_Item, (GUIDSTRING)_TargetObject, (INTEGER)_Amount) + THEN + ItemToInventory(_Item, _TargetObject, _Amount, 1, 1); + + PROC + ItemToInventory((ITEMGUID)_Item, (GUIDSTRING)_TargetObject, (INTEGER)_Amount, (INTEGER)_ShowNotification) + THEN + ItemToInventory(_Item, _TargetObject, _Amount, _ShowNotification, 1); + + //END_REGION + + //REGION Follow logic + PROC + ProcCharacterFollowCharacter((CHARACTERGUID)_Char,(CHARACTERGUID)_Target) + THEN + ProcCharacterStopFollow(_Char); + DB_Following(_Char,_Target); + CharacterFollowCharacter(_Char,_Target); + + PROC + ProcCharacterStopFollow((CHARACTERGUID)_Char) + AND + CharacterIsDead(_Char,0) + THEN + CharacterStopFollow(_Char); + + PROC + ProcCharacterStopFollow((CHARACTERGUID)_Char) + AND + DB_Following(_Char,_Target) + THEN + NOT DB_Following(_Char,_Target); + + IF + CharacterDying(_Char) + THEN + ProcCharacterStopFollow(_Char); + + IF + ObjectEnteredCombat((CHARACTERGUID)_Obj,_) + AND + DB_Following(_Obj,_) + THEN + CharacterStopFollow(_Obj); + + IF + ObjectLeftCombat((CHARACTERGUID)_Obj,_) + AND + DB_Following(_Obj,_Target) + THEN + CharacterFollowCharacter(_Obj,_Target); + + //END_REGION + + IF + DB_DoNotFace((GUIDSTRING)_Char) + THEN + CharacterSetDoNotFaceFlag((CHARACTERGUID)_Char,1); + DB_CheckDoNotFace(_Char); + + IF + DB_CheckDoNotFace(_Char) + AND + NOT DB_DoNotFace(_Char) + THEN + CharacterSetDoNotFaceFlag((CHARACTERGUID)_Char,0); + NOT DB_CheckDoNotFace(_Char); + + PROC + ProcFaceCharacter((GUIDSTRING)_Char,(GUIDSTRING)_Target) + AND + NOT DB_DoNotFace(_Char) + AND + ObjectIsCharacter(_Char,1) + AND + CharacterIsIncapacitated((CHARACTERGUID)_Char,0) + THEN + CharacterLookAt((CHARACTERGUID)_Char,_Target,0); + + PROC + ProcFaceEachother((GUIDSTRING)_Char,(GUIDSTRING)_Target) + AND + NOT DB_DoNotFace(_Char) + AND + ObjectIsCharacter(_Char,1) + AND + CharacterIsIncapacitated((CHARACTERGUID)_Char,0) + THEN + CharacterLookAt((CHARACTERGUID)_Char,_Target,0); + + PROC + ProcFaceEachother((GUIDSTRING)_Char,(GUIDSTRING)_Target) + AND + NOT DB_DoNotFace(_Target) + AND + ObjectIsCharacter(_Target,1) + AND + CharacterIsIncapacitated((CHARACTERGUID)_Target,0) + THEN + CharacterLookAt((CHARACTERGUID)_Target,_Char,0); + + //REGION Internal Dialog Logic (Starting dialog by clicking on NPC) + PROC + ProcIncreaseInternalCount() + AND + DB_InternalGroup_Count(_Nr) + AND + IntegerSum(_Nr,1,_New) + THEN + NOT DB_InternalGroup_Count(_Nr); + DB_InternalGroup_Count(_New); + + IF + DB_Dialogs((GUIDSTRING)_Npc,(STRING)_Dialog) + THEN + SetHasDialog(_Npc,1); + ProcIncreaseInternalCount(); + ProcInteralCounterEntry(_Npc,_Dialog); + + PROC + ProcInteralCounterEntry((GUIDSTRING)_Npc,(STRING)_Dialog) + AND + DB_InternalGroup_Count(_New) + THEN + DB_InternalCounter(_New,_Dialog,1); + DB_Internal_Dialogs(_Npc,_Dialog,_New,1); + + IF + DB_Dialogs((GUIDSTRING)_Npc,(GUIDSTRING)_Npc2,(STRING)_Dialog) + THEN + SetHasDialog(_Npc,1); + SetHasDialog(_Npc2,1); + ProcIncreaseInternalCount(); + ProcInteralCounterEntry(_Npc,_Npc2,_Dialog); + + PROC + ProcInteralCounterEntry((GUIDSTRING)_Npc,(GUIDSTRING)_Npc2,(STRING)_Dialog) + AND + DB_InternalGroup_Count(_Group) + THEN + DB_InternalCounter(_Group,_Dialog,2); + DB_Internal_Dialogs(_Npc,_Dialog,_Group,1); + DB_Internal_Dialogs(_Npc2,_Dialog,_Group,2); + + IF + DB_Dialogs((GUIDSTRING)_Npc,(GUIDSTRING)_Npc2,(GUIDSTRING)_Npc3,(STRING)_Dialog) + THEN + SetHasDialog(_Npc,1); + SetHasDialog(_Npc2,1); + SetHasDialog(_Npc3,1); + ProcIncreaseInternalCount(); + ProcInteralCounterEntry(_Npc,_Npc2,_Npc3,_Dialog); + + PROC + ProcInteralCounterEntry((GUIDSTRING)_Npc,(GUIDSTRING)_Npc2,(GUIDSTRING)_Npc3,(STRING)_Dialog) + AND + DB_InternalGroup_Count(_Group) + THEN + DB_InternalCounter(_Group,_Dialog,3); + DB_Internal_Dialogs(_Npc,_Dialog,_Group,1); + DB_Internal_Dialogs(_Npc2,_Dialog,_Group,2); + DB_Internal_Dialogs(_Npc3,_Dialog,_Group,3); + + IF + DB_Dialogs((GUIDSTRING)_Npc,(GUIDSTRING)_Npc2,(GUIDSTRING)_Npc3,(GUIDSTRING)_Npc4,(STRING)_Dialog) + THEN + SetHasDialog(_Npc,1); + SetHasDialog(_Npc2,1); + SetHasDialog(_Npc3,1); + SetHasDialog(_Npc4,1); + ProcIncreaseInternalCount(); + ProcInteralCounterEntry(_Npc,_Npc2,_Npc3,_Npc4,_Dialog); + + PROC + ProcInteralCounterEntry((GUIDSTRING)_Npc,(GUIDSTRING)_Npc2,(GUIDSTRING)_Npc3,(GUIDSTRING)_Npc4,(STRING)_Dialog) + AND + DB_InternalGroup_Count(_Group) + THEN + DB_InternalCounter(_Group,_Dialog,4); + DB_Internal_Dialogs(_Npc,_Dialog,_Group,1); + DB_Internal_Dialogs(_Npc2,_Dialog,_Group,2); + DB_Internal_Dialogs(_Npc3,_Dialog,_Group,3); + DB_Internal_Dialogs(_Npc4,_Dialog,_Group,4); + + PROC + ProcStartNPCDialog((GUIDSTRING)_Player,(STRING)_Dialog,(INTEGER)_Group) + AND + DB_InternalCounter(_Group,_Dialog,1) + AND + DB_Internal_Dialogs(_Npc,_Dialog,_Group,1) + THEN + Proc_StartDialog(0,_Dialog,_Npc,_Player); + + PROC + ProcStartNPCDialog((GUIDSTRING)_Player,(STRING)_Dialog,(INTEGER)_Group) + AND + DB_InternalCounter(_Group,_Dialog,2) + AND + DB_Internal_Dialogs(_Npc,_Dialog,_Group,1) + AND + DB_Internal_Dialogs(_Npc2,_Dialog,_Group,2) + THEN + Proc_StartDialog(0,_Dialog,_Npc,_Npc2,_Player); + + PROC + ProcStartNPCDialog((GUIDSTRING)_Player,(STRING)_Dialog,(INTEGER)_Group) + AND + DB_InternalCounter(_Group,_Dialog,3) + AND + DB_Internal_Dialogs(_Npc,_Dialog,_Group,1) + AND + DB_Internal_Dialogs(_Npc2,_Dialog,_Group,2) + AND + DB_Internal_Dialogs(_Npc3,_Dialog,_Group,3) + THEN + Proc_StartDialog(0,_Dialog,_Npc,_Npc2,_Npc3,_Player); + + PROC + ProcStartNPCDialog((GUIDSTRING)_Player,(STRING)_Dialog,(INTEGER)_Group) + AND + DB_InternalCounter(_Group,_Dialog,4) + AND + DB_Internal_Dialogs(_Npc,_Dialog,_Group,1) + AND + DB_Internal_Dialogs(_Npc2,_Dialog,_Group,2) + AND + DB_Internal_Dialogs(_Npc3,_Dialog,_Group,3) + AND + DB_Internal_Dialogs(_Npc4,_Dialog,_Group,4) + THEN + Proc_StartDialog(0,_Dialog,_Npc,_Npc2,_Npc3,_Npc4,_Player); + + + PROC + NPCDialogStartRequested((GUIDSTRING)_Npc,(GUIDSTRING)_Player) + AND + DB_Internal_Dialogs(_Npc,_Dialog,_Group,1) + AND + NOT DB_TempRequested(_NPC,_,_) + THEN + DB_TempRequested(_NPC,_Dialog,_Group); + + PROC + NPCDialogStartRequested((GUIDSTRING)_Npc,(GUIDSTRING)_Player) + AND + DB_Internal_Dialogs(_Npc,_Dialog,_Group,_) + AND + NOT DB_TempRequested(_NPC,_,_) + THEN + DB_TempRequested(_NPC,_Dialog,_Group); + + PROC + NPCDialogStartRequested((GUIDSTRING)_Npc,(GUIDSTRING)_Player) + AND + NOT DB_TempRequested(_NPC,_,_) + AND + QRY_SpeakerIsAvailable(_Npc) + AND + QRY_SpeakerIsAvailable(_Player) + AND + ObjectIsCharacter(_Npc,1) + AND + HasDefaultDialog((CHARACTERGUID)_Npc,1) + THEN + DialogRequestStop(_Npc); + DialogRequestStop(_Player); + ProcTryStartDefaultDialog(_Npc,(CHARACTERGUID)_Player); + + PROC + NPCDialogStartRequested((GUIDSTRING)_Npc,(GUIDSTRING)_Player) + AND + DB_TempRequested(_NPC,_Dialog,_Group) + THEN + NOT DB_TempRequested(_NPC,_Dialog,_Group); + ProcStartNPCDialog(_Player,_Dialog,_Group); + + PROC + ProcTryStartDefaultDialog((CHARACTERGUID)_Npc,(CHARACTERGUID)_Player) + AND + StartDefaultDialog(_Npc,_Player,_Dialog,_Automated) + THEN + ProcHandleDefaultDialogSetting(_Npc,_Player,_Dialog,_Automated); + + PROC + ProcHandleDefaultDialogSetting((CHARACTERGUID)_Npc,(CHARACTERGUID)_Player,(STRING)_Dialog,1) + THEN + ProcFaceCharacter(_Npc,_Player); + Proc_DialogFlagSetup(_Dialog,_Npc,_Player); + + PROC + ProcHandleDefaultDialogSetting((CHARACTERGUID)_Npc,(CHARACTERGUID)_Player,(STRING)_Dialog,0) + THEN + Proc_DialogFlagSetup(_Dialog,_Npc,_Player); + ProcFaceCharacter(_Npc,_Player); + ProcFaceCharacter(_Player,_Npc); + ProcItemSetInvulnerableForDialog(_Npc); + ProcItemSetInvulnerableForDialog(_Player); + CharacterMakeStoryNpc(_Npc,1); + CharacterMakeStoryNpc(_Player,1); + DB_HasMetCharactersToCheck(_Npc,_Player); + + //END_REGION + + //REGION Internal Dialog Cleanup + PROC + ProcRemoveAllDialogEntriesForSpeaker((GUIDSTRING)_NPC) + AND + DB_Internal_Dialogs(_Npc,_Dialog,_Group,1) + THEN + ProcRemoveInternalDialogEntries(_Dialog,_Group); + ProcRemoveExternalDialogEntry(_Npc,_Dialog,_Group); + + PROC + ProcRemoveDialogEntryForSpeaker((GUIDSTRING)_NPC,(STRING)_Dialog) + AND + DB_Internal_Dialogs(_Npc,_Dialog,_Group,1) + THEN + ProcRemoveInternalDialogEntries(_Dialog,_Group); + ProcRemoveExternalDialogEntry(_Npc,_Dialog,_Group); + + //remove dialogs when an NPC dies. + IF + DB_Dead((CHARACTERGUID)_Npc) + AND + NOT DB_KeepDialogsOnDeath(_Npc) + AND + DB_Internal_Dialogs(_Npc,_Dialog,_Group,_Nr) + AND + DB_Internal_Dialogs(_FirstSpeaker,_Dialog,_Group,1) + THEN + ProcRemoveDialogEntryForSpeaker(_FirstSpeaker,_Dialog); + + PROC + ProcRemoveExternalDialogEntry((GUIDSTRING)_Npc,(STRING)_Dialog,(INTEGER)_Group) + AND + DB_InternalCounter(_Group,_Dialog,1) + AND + DB_Dialogs(_Npc,_Dialog) + THEN + NOT DB_Dialogs(_Npc,_Dialog); + NOT DB_InternalCounter(_Group,_Dialog,1); + + PROC + ProcRemoveExternalDialogEntry((GUIDSTRING)_Npc,(STRING)_Dialog,(INTEGER)_Group) + AND + DB_InternalCounter(_Group,_Dialog,2) + AND + DB_Dialogs(_Npc,_Npc2,_Dialog) + THEN + NOT DB_Dialogs(_Npc,_Npc2,_Dialog); + NOT DB_InternalCounter(_Group,_Dialog,2); + + PROC + ProcRemoveExternalDialogEntry((GUIDSTRING)_Npc,(STRING)_Dialog,(INTEGER)_Group) + AND + DB_InternalCounter(_Group,_Dialog,3) + AND + DB_Dialogs(_Npc,_Npc2,_Npc3,_Dialog) + THEN + NOT DB_Dialogs(_Npc,_Npc2,_Npc3,_Dialog); + NOT DB_InternalCounter(_Group,_Dialog,3); + + PROC + ProcRemoveExternalDialogEntry((GUIDSTRING)_Npc,(STRING)_Dialog,(INTEGER)_Group) + AND + DB_InternalCounter(_Group,_Dialog,4) + AND + DB_Dialogs(_Npc,_Npc2,_Npc3,_Npc4,_Dialog) + THEN + NOT DB_Dialogs(_Npc,_Npc2,_Npc3,_Npc4,_Dialog); + NOT DB_InternalCounter(_Group,_Dialog,4); + + PROC + ProcRemoveInternalDialogEntries((STRING)_Dialog,(INTEGER)_Group) + AND + DB_Internal_Dialogs(_Npc,_Dialog,_Group,_Nr) + THEN + NOT DB_Internal_Dialogs(_Npc,_Dialog,_Group,_Nr); + //END_REGION + + //REGION Start Dialog with 1 Item + IF + CharacterUsedItem(_Player,_Item) + AND + DB_Dialogs(_Item,_Dialog) + AND + DB_CombatCharacters(_Player, _) + AND + NOT DB_IgnoreCombatItems((ITEMGUID) _Item) + THEN + Proc_StartDialog(1,"GLO_AD_CannotUseNow", _Player); + + IF + CharacterUsedItem(_Player,_Item) + AND + DB_Dialogs(_Item,_Dialog) + AND + NOT DB_CombatCharacters(_Player, _) + THEN + Proc_StartDialog(0,_Dialog,_Item,_Player); + + IF + CharacterUsedItem(_Player,_Item) + AND + DB_Dialogs(_Item,_Dialog) + AND + DB_CombatCharacters(_Player, _) + AND + DB_IgnoreCombatItems((ITEMGUID) _Item) + THEN + Proc_StartDialog(0,_Dialog,_Item,_Player); + + // From item's GEN_ItemDialog behavior script we can start interactive dialogs (used for modders to start item dialogs without Osiris support) + IF + CharacterItemEvent(_Player,_Item,"GEN_StartItemDialog") + AND + NOT DB_Dialogs(_Item,_) + AND + DB_IsPlayer(_Player) + AND + NOT DB_CombatCharacters(_Player,_) + AND + GetVarString(_Item,"ItemDialog",_Dialog) + THEN + Proc_StartDialog(0,_Dialog,_Item,_Player); + + IF + CharacterItemEvent(_Player,_Item,"GEN_StartItemDialog") + AND + NOT DB_Dialogs(_Item,_) + AND + DB_IsPlayer(_Player) + AND + DB_CombatCharacters(_Player,_) + AND + DB_IgnoreCombatItems((ITEMGUID)_Item) + AND + GetVarString(_Item,"ItemDialog",_Dialog) + THEN + Proc_StartDialog(0,_Dialog,_Item,_Player); + //END_REGION + + + //REGION Start Automated Dialog with 1 Item + IF + CharacterUsedItem(_Char,_Item) + AND + DB_AD_Dialog(_Item,_Dialog) + THEN + Proc_StartDialog(1,_Dialog, _Item); + //END_REGION + + //REGION Track Object Invulnerable (mainly used by itemdialogs setting items temporarily invulnerable) + PROC + ProcSetInvulnerable((GUIDSTRING)_Object,1) + THEN + DB_ObjectStoryInvulnerable(_Object); + SetInvulnerable_UseProcSetInvulnerable(_Object,1); + + PROC + ProcSetInvulnerable((GUIDSTRING)_Object,0) + THEN + NOT DB_ObjectStoryInvulnerable(_Object); + SetInvulnerable_UseProcSetInvulnerable(_Object,0); + //END_REGION + + //REGION Clear Involved NPCs in Dialog + PROC + ProcClearDialogFlagsForPlayers((INTEGER)_Instance) + AND + DB_DialogPlayers(_Instance,_Player,_Index) + THEN + ProcClearPlayerIfNotInOtherDialog(_Instance,_Player); + + PROC + ProcClearPlayerIfNotInOtherDialog((INTEGER)_Inst,(GUIDSTRING)_Player) + AND + DB_DialogPlayers(_OtherInstance,_Player,_) + AND + _OtherInstance!=_Inst + AND + NOT DB_AutomatedDialog(_OtherInstance) + AND + NOT DB_MarkedForDelete(_OtherInstance) + THEN + DB_TempIsInOtherDialog(_Player,1); + + PROC + ProcClearPlayerIfNotInOtherDialog((INTEGER)_Inst,(GUIDSTRING)_Player) + AND + NOT DB_TempIsInOtherDialog(_Player,1) + THEN + SetStoryNpcStatus((CHARACTERGUID)_Player); + + PROC + ProcClearPlayerIfNotInOtherDialog((INTEGER)_Inst,(GUIDSTRING)_Player) + THEN + NOT DB_TempIsInOtherDialog(_Player,1); + + PROC + ProcClearDialogFlagsForNPCs((INTEGER)_Instance) + AND + DB_DialogNPCs(_Instance,_Npc,_Index) + THEN + ProcClearNPCIfNotInOtherDialog(_Instance,_Npc); + + PROC + ProcClearNPCIfNotInOtherDialog((INTEGER)_Inst,(GUIDSTRING)_Npc) + AND + DB_DialogNPCs(_OtherInstance,_Npc,_) + AND + _OtherInstance!=_Inst + AND + NOT DB_AutomatedDialog(_OtherInstance) + AND + NOT DB_MarkedForDelete(_OtherInstance) + THEN + DB_TempIsInOtherDialog(_Npc,1); + + PROC + ProcClearNPCIfNotInOtherDialog((INTEGER)_Inst,(GUIDSTRING)_Npc) + AND + NOT DB_TempIsInOtherDialog(_Npc,1) + THEN + SetStoryNpcStatus((CHARACTERGUID)_Npc); + + PROC + ProcClearNPCIfNotInOtherDialog((INTEGER)_Inst,(GUIDSTRING)_Npc) + AND + NOT DB_TempIsInOtherDialog(_Npc,1) + AND + NOT DB_ObjectStoryInvulnerable(_Npc) + AND + ObjectIsItem(_Npc,1) + THEN + SetInvulnerable_UseProcSetInvulnerable(_Npc,0); + + PROC + ProcClearNPCIfNotInOtherDialog((INTEGER)_Inst,(GUIDSTRING)_Npc) + THEN + NOT DB_TempIsInOtherDialog(_Npc,1); + + //END_REGION + + //REGION Set Relation to Players + PROC + SetRelationFactionToPlayers((STRING)_Faction,(INTEGER)_Relation) + THEN + CharacterSetRelationFactionToFaction(_Faction,"Hero",_Relation); + CharacterSetRelationFactionToFaction("Hero",_Faction,_Relation); + CharacterSetRelationFactionToFaction(_Faction,"Companion",_Relation); + CharacterSetRelationFactionToFaction("Companion",_Faction,_Relation); + + PROC + SetRelationIndivFactionToPlayers((CHARACTERGUID)_Char,(INTEGER)_Relation) + THEN + CharacterSetRelationIndivFactionToFaction(_Char,"Hero",_Relation); + CharacterSetRelationFactionToIndivFaction("Hero",_Char,_Relation); + CharacterSetRelationIndivFactionToFaction(_Char,"Companion",_Relation); + CharacterSetRelationFactionToIndivFaction("Companion",_Char,_Relation); + + PROC + ProcSetRelationToPlayers((CHARACTERGUID)_Character,(INTEGER)_Relation) + AND + _Relation == 0 + AND + GetFaction(_Character,_Faction) + THEN + SetFaction(_Character,"Evil NPC"); + DB_PreviousAlignment(_Character,_Faction); + + PROC + ProcSetRelationToPlayers((CHARACTERGUID)_Character,(INTEGER)_Relation) + AND + _Relation == 100 + AND + NOT DB_PreviousAlignment(_Character,_) + AND + GetFaction(_Character,_Faction) + THEN + CharacterSetRelationFactionToFaction(_Faction,"Hero",100); + CharacterSetRelationFactionToFaction("Hero",_Faction,100); + + PROC + ProcSetRelationToPlayers((CHARACTERGUID)_Character,(INTEGER)_Relation) + AND + DB_IsPlayer(_Player) + AND + _Relation == 100 + AND + DB_PreviousAlignment(_Character,_Faction) + THEN + SetFaction(_Character,_Faction); + CharacterSetRelationFactionToFaction(_Faction,"Hero",100); + CharacterSetRelationFactionToFaction("Hero",_Faction,100); + NOT DB_PreviousAlignment(_Character,_Faction); + + PROC + ProcSetHostileToIndivPlayer((CHARACTERGUID)_Character,(CHARACTERGUID)_Player) + THEN + CharacterSetRelationIndivFactionToIndivFaction(_Character,_Player,0); + CharacterSetRelationIndivFactionToIndivFaction(_Player,_Character,0); + + PROC + ProcSetFactionHostileToIndivPlayer((STRING)_Faction,(CHARACTERGUID)_Player) + THEN + CharacterSetRelationFactionToIndivFaction(_Faction,_Player,0); + CharacterSetRelationIndivFactionToFaction(_Player,_Faction,0); + //END_REGION + + //REGION Change Attitude + IF + ObjectFlagSet("ChangeAttitude",_Player,_Instance) + AND + GetVarInteger(_Player,"ChangeAttitude",_Value) + AND + DB_DialogNPCs(_Instance,_Npc,1) + THEN + ObjectClearFlag(_Player,"ChangeAttitude",_Instance); + CharacterAddAttitudeTowardsPlayer((CHARACTERGUID)_Npc,(CHARACTERGUID)_Player,_Value); + + PROC + ChangeAttitude((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(INTEGER)_Value) + THEN + CharacterAddAttitudeTowardsPlayer(_Npc,_Player,_Value); + //END_REGION + + //REGION Peace Timer + PROC + PROC_PeaceTimerLaunch((STRING)_TimerName,(INTEGER)_TimerLength) + AND + DB_CombatCharacters(_Player,_) + AND + DB_IsPlayer(_Player) + AND + NOT DB_PeaceTimer(_TimerName) + THEN + DB_PeaceTimer(_TimerName); + DB_PeaceTimerStillToStart(_TimerName,_TimerLength); + + PROC + PROC_PeaceTimerLaunch((STRING)_TimerName,(INTEGER)_TimerLength) + AND + NOT DB_PeaceTimer(_TimerName) + THEN + DB_PeaceTimer(_TimerName); + TimerLaunch(_TimerName,_TimerLength); + + IF + ObjectEnteredCombat((CHARACTERGUID)_Player,_) + AND + _Player.DB_IsPlayer() + AND + DB_PeaceTimer(_TimerName) + THEN + TimerPause(_TimerName); + + IF + ObjectLeftCombat((CHARACTERGUID)_Player,_) + AND + _Player.DB_IsPlayer() + AND + DB_PeaceTimer(_TimerName) + THEN + ProcUnPausePeaceTimerIfNoPlayerInCombat(_TimerName); + + PROC + ProcUnPausePeaceTimerIfNoPlayerInCombat((STRING)_TimerName) + AND + _Player.DB_IsPlayer() + AND + DB_CombatCharacters(_Player,_) + THEN + DB_PlayerInCombat(1); + + PROC + ProcUnPausePeaceTimerIfNoPlayerInCombat((STRING)_TimerName) + AND + NOT DB_PlayerInCombat(1) + AND + NOT DB_PeaceTimerStillToStart(_TimerName,_) + THEN + TimerUnpause(_TimerName); + + PROC + ProcUnPausePeaceTimerIfNoPlayerInCombat((STRING)_TimerName) + AND + NOT DB_PlayerInCombat(1) + AND + DB_PeaceTimerStillToStart(_TimerName,_TimerLength) + THEN + TimerLaunch(_TimerName,_TimerLength); + NOT DB_PeaceTimerStillToStart(_TimerName,_TimerLength); + + PROC + ProcUnPausePeaceTimerIfNoPlayerInCombat((STRING)_TimerName) + THEN + NOT DB_PlayerInCombat(1); + IF + TimerFinished(_TimerName) + AND + DB_PeaceTimer(_TimerName) + THEN + NOT DB_PeaceTimer(_TimerName); + //END_REGION + + //REGION Doors + PROC + ItemCloseAndLock((ITEMGUID)_Item,(STRING)_Key) + THEN + ItemClose(_Item); + ItemLock(_Item,_Key); + + PROC + ItemUnlockAndOpen((ITEMGUID)_Item) + THEN + ItemUnLock(_Item); + ItemOpen(_Item); + //END_REGION + + //REGION Automated dialogs + IF + DB_AD_Dialog((GUIDSTRING)_Char,(STRING)_) + THEN + SetHasDialog(_Char,1); + + IF + DB_AD_Dialog((GUIDSTRING)_Char1,(GUIDSTRING)_Char2,(STRING)_) + THEN + SetHasDialog(_Char1,1); + SetHasDialog(_Char2,1); + + PROC + PROC_GLOBAL_DialogStartRequested((GUIDSTRING)_Char,(GUIDSTRING)_Player) + AND + DB_AD_Dialog(_Char,(STRING)_Dialog) + AND + NOT DB_ADRequested(_Char) + AND + QRY_StartDialog(1,_Dialog,_Char) + THEN + DB_ADRequested(_Char); + DB_FoundDialog(_Char,_Player); + + PROC + PROC_GLOBAL_DialogStartRequested((GUIDSTRING)_Char1,(GUIDSTRING)_Player) + AND + DB_AD_Dialog(_Char1,_Char2,(STRING)_Dialog) + AND + NOT DB_ADRequested(_Char1) + AND + NOT DB_ADRequested(_Char2) + AND + QRY_StartDialog(1,_Dialog,_Char1,_Char2) + THEN + DB_ADRequested(_Char1); + DB_ADRequested(_Char2); + DB_FoundDialog(_Char1,_Player); + + PROC + PROC_GLOBAL_DialogStartRequested((GUIDSTRING)_Char2,(GUIDSTRING)_Player) + AND + DB_AD_Dialog(_Char1,_Char2,(STRING)_Dialog) + AND + NOT DB_ADRequested(_Char1) + AND + NOT DB_ADRequested(_Char2) + AND + QRY_StartDialog(1,_Dialog,_Char1,_Char2) + THEN + DB_ADRequested(_Char1); + DB_ADRequested(_Char2); + DB_FoundDialog(_Char2,_Player); + + IF + AutomatedDialogEnded(_Dialog,_Inst) + THEN + ProcClearADRequests(_Dialog,_Inst); + + IF + AutomatedDialogRequestFailed(_Dialog,_Inst) + THEN + ProcClearADRequests(_Dialog,_Inst); + + PROC + ProcClearADRequests((STRING)_Dialog,(INTEGER)_Inst) + AND + DB_DialogNPCs(_Inst,_Npc,1) + AND + DB_AD_Dialog(_Npc,_Dialog) + THEN + NOT DB_ADRequested(_Npc); + + PROC + ProcClearADRequests((STRING)_Dialog,(INTEGER)_Inst) + AND + DB_DialogPlayers(_Inst,_Player,1) + AND + DB_AD_Dialog(_Player,_Dialog) + THEN + NOT DB_ADRequested(_Player); + + PROC + ProcClearADRequests((STRING)_Dialog,(INTEGER)_Inst) + AND + DB_DialogNPCs(_Inst,_Npc,_) + AND + DB_AD_Dialog(_,_,_Dialog) + THEN + NOT DB_ADRequested(_Npc); + + PROC + ProcClearADRequests((STRING)_Dialog,(INTEGER)_Inst) + AND + DB_DialogPlayers(_Inst,_Player,1) + AND + DB_AD_Dialog(_,_,_Dialog) + THEN + NOT DB_ADRequested(_Player); + + PROC + ProcRemoveNPCADs((GUIDSTRING)_Npc) + AND + DB_AD_Dialog(_Npc,_Dialog) + THEN + NOT DB_AD_Dialog(_Npc,_Dialog); + NOT DB_ADRequested(_Npc); + + PROC + ProcRemoveNPCADs((GUIDSTRING)_Npc) + AND + DB_AD_Dialog(_Npc,_Npc2,_Dialog) + THEN + NOT DB_AD_Dialog(_Npc,_Npc2,_Dialog); + NOT DB_ADRequested(_Npc); + NOT DB_ADRequested(_Npc2); + + PROC + ProcRemoveNPCADs((GUIDSTRING)_Npc2) + AND + DB_AD_Dialog(_Npc,_Npc2,_Dialog) + THEN + NOT DB_AD_Dialog(_Npc,_Npc2,_Dialog); + NOT DB_ADRequested(_Npc); + NOT DB_ADRequested(_Npc2); + + PROC + PROC_GLOBAL_DialogStartRequested((GUIDSTRING)_NPC,(GUIDSTRING)_Player) + AND + DB_AD_Dialog(_NPC,_) + THEN + ProcFaceEachother(_NPC,_Player); + + //END_REGION + + //REGION Object timer + PROC + ProcObjectTimer((GUIDSTRING)_Object,(STRING)_TimerName,(INTEGER)_Time) + AND + GetUUID(_Object,_UUID) + AND + StringConcatenate(_UUID,_TimerName,_ObjectTimerName) + THEN + DB_ObjectTimer(_Object,_ObjectTimerName,_TimerName); + TimerLaunch(_ObjectTimerName,_Time); + + PROC + ProcObjectTimerCancel((GUIDSTRING)_Object,(STRING)_TimerName) + AND + DB_ObjectTimer(_Object,_ObjectTimerName,_TimerName) + THEN + NOT DB_ObjectTimer(_Object,_ObjectTimerName,_TimerName); + TimerCancel(_ObjectTimerName); + + IF + TimerFinished(_ObjectTimerName) + AND + DB_ObjectTimer(_Object,_ObjectTimerName,_TimerName) + THEN + NOT DB_ObjectTimer(_Object,_ObjectTimerName,_TimerName); + ProcObjectTimerFinished(_Object,_TimerName); + + PROC + ProcObjectTimerFinished((GUIDSTRING)_Object,(STRING)_TimerName) + THEN + DB_NOOP(1); + //END_REGION + + //REGION Tutorial Messages + PROC + PROC_CheckPlayTut((STRING)_Message) + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTut(_Player,_Message); + + PROC + PROC_CheckPlayTut((CHARACTERGUID)_Player,(STRING)_Message) + AND + DB_StartTutMessages(1) + THEN + ProcPlayTut(_Player,_Message); + + PROC + PROC_CheckPlayTutWithDelay((STRING)_Message,(INTEGER)_Delay) + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTutWithDelay(_Player,_Message,_Delay); + + PROC + PROC_CheckPlayTutWithDelay((CHARACTERGUID)_Player,(STRING)_Message,(INTEGER)_Delay) + AND + NOT DB_TutorialMessage(_Player,_Message,_) + AND + GetUUID(_Player,_Timer) + AND + StringConcatenate(_Timer,"_Tut",_TimerMsg) + THEN + TimerLaunch(_TimerMsg,_Delay); + DB_TutorialMessage(_Player,_Message,_TimerMsg); + + IF + TimerFinished(_TimerMsg) + AND + DB_StartTutMessages(1) + AND + DB_TutorialMessage(_Player,_Message,_TimerMsg) + THEN + NOT DB_TutorialMessage(_Player,_Message,_TimerMsg); + ProcPlayTut(_Player,_Message); + //END_REGION + + //REGION Move to changes + PROC + ProcSaveGenericBehaviourState((CHARACTERGUID)_Char) + AND + NOT DB_StoryMoving(_Char,1) + AND + DB_Internal_Dialogs(_Char,_,_,_) + THEN + DB_NPCHadDialog(_Char,1); + + PROC + ProcSaveGenericBehaviourState((CHARACTERGUID)_Char) + AND + NOT DB_StoryMoving(_Char,1) + AND + DB_AD_Dialog(_Char,_) + THEN + DB_NPCHadDialog(_Char,1); + + PROC + ProcInternalMoveDisableGenericBehaviours((CHARACTERGUID)_Char) + AND + NOT DB_AD_Dialog(_Char,_) + THEN + SetHasDialog(_Char,0); + + PROC + ProcInternalMoveDisableGenericBehaviours((CHARACTERGUID)_Char) + THEN + CharacterDisableAllCrimes(_Char); + + PROC + ProcRestoreGenericBehaviour((CHARACTERGUID)_Char) + AND + NOT DB_CharacterAllCrimesDisabled(_Char) + THEN + CharacterEnableAllCrimes(_Char); + + PROC + ProcRestoreGenericBehaviour((CHARACTERGUID)_Char) + AND + DB_CharacterCrimeDisabled(_Char,_Crime) + THEN + CharacterDisableCrime(_Char,_Crime); + + PROC + ProcRestoreGenericBehaviour((CHARACTERGUID)_Char) + AND + DB_CharacterCrimeEnabled(_Char,_Crime) + THEN + CharacterEnableCrime(_Char,_Crime); + + PROC + ProcRestoreGenericBehaviour((CHARACTERGUID)_Char) + AND + DB_NPCHadDialog(_Char,1) + THEN + NOT DB_NPCHadDialog(_Char,1); + SetHasDialog(_Char,1); + + PROC + ProcSetMoveEvent((STRING)_Event) + AND + _Event!="" + THEN + DB_MoveEvent(_Event); + + PROC + ProcSetMoveEvent("") + THEN + DB_MoveEvent("_ResetGenericBehaviours_"); + + PROC + ProcExecuteMove((CHARACTERGUID)_Char,(GUIDSTRING)_Point,(INTEGER)_Running) + AND + DB_MoveEvent(_Event) + AND + DB_CharMovementCommandID(_Char,_ID) + THEN + NOT DB_MoveEvent(_Event); + CharacterMoveTo(_Char,_Point,_Running,_Event,0); + DB_CharacterMovement(_Char,_Event,_ID); + + PROC + ProcBumpOsirisMoveCommandID((CHARACTERGUID)_Char) + AND + NOT DB_CharMovementCommandID(_Char,_) + THEN + DB_CharMovementCommandID(_Char,0); + + PROC + ProcBumpOsirisMoveCommandID((CHARACTERGUID)_Char) + AND + DB_CharMovementCommandID(_Char,_ID) + AND + IntegerSum(1,_ID,_New) + THEN + NOT DB_CharMovementCommandID(_Char,_ID); + DB_CharMovementCommandID(_Char,_New); + + PROC + ProcCharacterMoveTo((CHARACTERGUID)_Char,_,_,_) + THEN + SetStoryEvent(_Char,"ClearCrimeReturnPos"); + ProcBumpOsirisMoveCommandID(_Char); + + PROC + ProcCharacterMoveTo((CHARACTERGUID)_Char,(GUIDSTRING)_Point,(INTEGER)_Running,(STRING)_Event) + AND + DB_CharMovementCommandID(_Char,_ID) + THEN + ProcSaveGenericBehaviourState(_Char); + ProcInternalMoveDisableGenericBehaviours(_Char); + ProcSetMoveEvent(_Event); + ProcExecuteMove(_Char,_Point,_Running); + DB_StoryMoving(_Char,1); + DB_MovingTo(_Char,_Point,_Running,_ID); + + PROC + ProcCharacterMoveTo((CHARACTERGUID)_Char,_,_,_) + THEN + ProcBumpOsirisMoveCommandID(_Char); + + PROC + ProcResumeStoryMoving((CHARACTERGUID)_Char) + AND + DB_CharacterMovement(_Char,_Event,_ID) + AND + NOT DB_SelectedMove(_Char) + THEN + ProcSelectMove(_Char,_ID); + + PROC + ProcSelectMove((CHARACTERGUID)_Char,(INTEGER)_ID) + AND + DB_MovingTo(_Char,_Point,_Running,_ID) + AND + DB_CharacterMovement(_Char,_Event,_ID) + THEN + DB_SelectedMove(_Char); + CharacterMoveTo(_Char,_Point,_Running,_Event,0); + + PROC + ProcResumeStoryMoving((CHARACTERGUID)_Char) + THEN + NOT DB_SelectedMove(_Char); + + PROC + ProcClearMovingFacts((CHARACTERGUID)_Char) + AND + DB_CharacterMovement(_Char,_Event,_ID) + THEN + NOT DB_CharacterMovement(_Char,_Event,_ID); + + PROC + ProcClearMovingFacts((CHARACTERGUID)_Char) + AND + DB_MovingTo(_Char,_Point,_Running,_ID) + THEN + NOT DB_MovingTo(_Char,_Point,_Running,_ID); + + PROC + ProcClearMovingFacts((CHARACTERGUID)_Char) + THEN + ProcRestoreGenericBehaviour(_Char); + + IF + StoryEvent((CHARACTERGUID)_Char,_Event) + AND + DB_CharacterMovement(_Char,_Event,_ID) + THEN + NOT DB_ClearedMoveEvent(_Char); + + IF + StoryEvent((CHARACTERGUID)_Char,_Event) + AND + DB_CharacterMovement(_Char,_Event,_ID) + AND + DB_MovingTo(_Char,_Point,_Running,_ID) + AND + NOT DB_ClearedMoveEvent(_Char) + THEN + DB_ClearedMoveEvent(_Char); + NOT DB_MovingTo(_Char,_Point,_Running,_ID); + + IF + StoryEvent((CHARACTERGUID)_Char,_Event) + AND + DB_CharacterMovement(_Char,_Event,_ID) + THEN + NOT DB_HandledMoveEvent(_Char); + + IF + StoryEvent((CHARACTERGUID)_Char,_Event) + AND + DB_CharacterMovement(_Char,_Event,_ID) + AND + NOT DB_HandledMoveEvent(_Char) + THEN + DB_HandledMoveEvent(_Char); + NOT DB_CharacterMovement(_Char,_Event,_ID); + SetStoryEvent(_Char,"ClearCrimeReturnPos"); + ProcCheckRestoreGenericBehaviours(_Char); + + + PROC + ProcCheckRestoreGenericBehaviours((CHARACTERGUID)_Char) + AND + NOT DB_CharacterMovement(_Char,_,_) + THEN + NOT DB_StoryMoving(_Char,1); + ProcRestoreGenericBehaviour(_Char); + + IF + AttackedByObject((CHARACTERGUID)_Char,(CHARACTERGUID)_Source,_,_,_DamageSource) + AND + DB_StoryMoving(_Char,1) + AND + NOT DB_CombatCharacters(_Char,_) + AND + NOT QryIgnoreDamageSource(_DamageSource) + AND + CharacterIsPlayer(_Source,1) + THEN + ProcMakeNPCHostile(_Source,_Char); + + IF + DB_Dead(_Char) + AND + DB_StoryMoving(_Char,1) + THEN + NOT DB_StoryMoving(_Char,1); + ProcRestoreGenericBehaviour(_Char); + ProcClearMovingFacts(_Char); + + IF + ObjectEnteredCombat((CHARACTERGUID)_Char,_) + AND + DB_StoryMoving(_Char,1) + THEN + CharacterPurgeQueue(_Char); + + IF + ObjectLeftCombat((CHARACTERGUID)_Char,_) + AND + NOT DB_Dead(_Char) + AND + DB_StoryMoving(_Char,1) + THEN + ProcResumeStoryMoving(_Char); + + PROC + ProcClearStoryMove((CHARACTERGUID)_Char) + THEN + NOT DB_StoryMoving(_Char,1); + ProcRestoreGenericBehaviour(_Char); + ProcClearMovingFacts(_Char); + //END_REGION + + //REGION Movement via State_Manager_GoTo + // The parameters are roughly the same as with ProcCharacterMoveTo. Additional parameters: + // - _MinDist: the minimal distance to which the character must have neared its destination before the event is triggered + // - _AfterArrivalState: the State_Manager state to go to once the character reaches its destination + PROC + ProcStateManagerCharacterMoveTo((CHARACTERGUID)_Char,(GUIDSTRING)_Destination,(INTEGER)_Running,(REAL)_MinDist,(STRING)_Event,(STRING)_AfterArrivalState) + AND + ObjectIsCharacter(_Destination,1) + THEN + DB_ProcStateManagerCharacterMoveTo_Handled(1); + SetVarObject(_Char,"DestinationCharacter",_Destination); + SetVarFixedString(_Char,"currentState","State_Manager_Go_To_Character"); + + PROC + ProcStateManagerCharacterMoveTo((CHARACTERGUID)_Char,(GUIDSTRING)_Destination,(INTEGER)_Running,(REAL)_MinDist,(STRING)_Event,(STRING)_AfterArrivalState) + AND + NOT DB_ProcStateManagerCharacterMoveTo_Handled(1) + AND + ObjectIsItem(_Destination,1) + THEN + DB_ProcStateManagerCharacterMoveTo_Handled(1); + SetVarObject(_Char,"DestinationItem",_Destination); + SetVarFixedString(_Char,"currentState","State_Manager_Go_To_Item"); + + PROC + ProcStateManagerCharacterMoveTo((CHARACTERGUID)_Char,(GUIDSTRING)_Destination,(INTEGER)_Running,(REAL)_MinDist,(STRING)_Event,(STRING)_AfterArrivalState) + AND + NOT DB_ProcStateManagerCharacterMoveTo_Handled(1) + THEN + SetVarObject(_Char,"Destination",_Destination); + SetVarFixedString(_Char,"currentState","State_Manager_Go_To_Trigger"); + + PROC + ProcStateManagerCharacterMoveTo((CHARACTERGUID)_Char,(GUIDSTRING)_Destination,(INTEGER)_Running,(REAL)_MinDist,(STRING)_Event,(STRING)_AfterArrivalState) + THEN + NOT DB_ProcStateManagerCharacterMoveTo_Handled(1); + SetVarInteger(_Char,"Running",_Running); + SetVarFloat(_Char,"Distance",_MinDist); + SetVarString(_Char,"ArriveEvent",_Event); + SetVarFixedString(_Char,"AfterArriveState",_AfterArrivalState); + //END_REGION + + PROC + ReactOnKillCounter((STRING)_Counter) + THEN + DB_NOOP(1); + + PROC + ProcStartMovie((STRING)_Movie) + AND + _Char.DB_IsPlayer() + AND + CharacterGetReservedUserID(_Char,_ID) + AND + GetUserProfileID(_ID,_UserProfile) + AND + NOT DB_MoviePlayed(_UserProfile,_Movie) + THEN + DB_MoviePlayed(_UserProfile,_Movie); + MoviePlay(_Char,_Movie); + + + //REGION check closest available character to object + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,(INTEGER)_SightCheck) + THEN + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,(INTEGER)_SightCheck,0,NULL_00000000-0000-0000-0000-000000000000); + + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,(INTEGER)_SightCheck,(INTEGER)_PartyCheck,(CHARACTERGUID)_Player) + THEN + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,(INTEGER)_SightCheck,(INTEGER)_PartyCheck,(CHARACTERGUID)_Player,(CHARACTERGUID)NULL_00000000-0000-0000-0000-000000000000); + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,(INTEGER)_SightCheck,(INTEGER)_PartyCheck,(CHARACTERGUID)_Player,(CHARACTERGUID)_ExceptPlayer) + AND + DB_ProcGetClosestAvailableCharacterTo_Dist(_Char,_Obj,_Dist) + THEN + NOT DB_ProcGetClosestAvailableCharacterTo_Dist(_Char,_Obj,_Dist); + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,(INTEGER)_SightCheck,(INTEGER)_PartyCheck,(CHARACTERGUID)_Player,(CHARACTERGUID)_ExceptPlayer) + AND + DB_ClosestAvailablePlayer(_Char,_Obj) + THEN + NOT DB_ClosestAvailablePlayer(_Char,_Obj); + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,(INTEGER)_SightCheck,(INTEGER)_PartyCheck,(CHARACTERGUID)_Player,(CHARACTERGUID)_ExceptPlayer) + AND + DB_ClosestAvailablePlayer_NoAvailablePlayer(_Obj) + THEN + NOT DB_ClosestAvailablePlayer_NoAvailablePlayer(_Obj); + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,1,1,(CHARACTERGUID)_Player,(CHARACTERGUID)_ExceptPlayer) + AND + DB_IsPlayer(_Char) + AND + _Char != _ExceptPlayer + AND + CharacterCanSee(_Obj,(CHARACTERGUID)_Char,1) + AND + QRY_SpeakerIsAvailable(_Char) + AND + CharacterIsInPartyWith(_Char,_Player,1) + AND + GetDistanceTo(_Char,_Obj,_Dist) + THEN + DB_ProcGetClosestAvailableCharacterTo_Dist(_Char,_Obj,_Dist); + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,0,1,(CHARACTERGUID)_Player,(CHARACTERGUID)_ExceptPlayer) + AND + DB_IsPlayer(_Char) + AND + _Char != _ExceptPlayer + AND + QRY_SpeakerIsAvailable(_Char) + AND + CharacterIsInPartyWith(_Char,_Player,1) + AND + GetDistanceTo(_Char,_Obj,_Dist) + THEN + DB_ProcGetClosestAvailableCharacterTo_Dist(_Char,_Obj,_Dist); + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,1,0,(CHARACTERGUID)_Player,(CHARACTERGUID)_ExceptPlayer) + AND + DB_IsPlayer(_Char) + AND + _Char != _ExceptPlayer + AND + CharacterCanSee(_Obj,(CHARACTERGUID)_Char,1) + AND + QRY_SpeakerIsAvailable(_Char) + AND + GetDistanceTo(_Char,_Obj,_Dist) + THEN + DB_ProcGetClosestAvailableCharacterTo_Dist(_Char,_Obj,_Dist); + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,0,0,(CHARACTERGUID)_Player,(CHARACTERGUID)_ExceptPlayer) + AND + DB_IsPlayer(_Char) + AND + _Char != _ExceptPlayer + AND + QRY_SpeakerIsAvailable(_Char) + AND + GetDistanceTo(_Char,_Obj,_Dist) + THEN + DB_ProcGetClosestAvailableCharacterTo_Dist(_Char,_Obj,_Dist); + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,(INTEGER)_SightCheck,(INTEGER)_PartyCheck,(CHARACTERGUID)_Player,(CHARACTERGUID)_ExceptPlayer) + AND + DB_ProcGetClosestAvailableCharacterTo_Dist(_Char1,_Obj,_Dist1) + AND + DB_ProcGetClosestAvailableCharacterTo_Dist(_Char2,_Obj,_Dist2) + AND + _Dist1 < _Dist2 + THEN + NOT DB_ProcGetClosestAvailableCharacterTo_Dist(_Char2,_Obj,_Dist2); + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,(INTEGER)_SightCheck,(INTEGER)_PartyCheck,(CHARACTERGUID)_Player,(CHARACTERGUID)_ExceptPlayer) + AND + NOT DB_ProcGetClosestAvailableCharacterTo_Dist(_,_Obj,_) + THEN + DB_ClosestAvailablePlayer_NoAvailablePlayer(_Obj); + + PROC + ProcGetClosestAvailableCharacterTo((CHARACTERGUID)_Obj,(INTEGER)_SightCheck,(INTEGER)_PartyCheck,(CHARACTERGUID)_Player,(CHARACTERGUID)_ExceptPlayer) + AND + DB_ProcGetClosestAvailableCharacterTo_Dist(_Char,_Obj,_Dist) + THEN + DB_ClosestAvailablePlayer(_Char,_Obj); + NOT DB_ProcGetClosestAvailableCharacterTo_Dist(_Char,_Obj,_Dist); + + //END_REGION + + + //REGION Disappear out of sight + + PROC + ProcCharacterDisappearOutOfSight((CHARACTERGUID)_Character,(INTEGER)_Angle,(INTEGER)_Running,(STRING)_Event,(INTEGER)_IncreaseSpeed) + THEN + CharacterDisableAllCrimes(_Character); + DB_CharacterDisappearedOutOfSight(_Character,_Event,1); + CharacterDisappearOutOfSight(_Character,_Angle,_Running,_Event,_IncreaseSpeed); + + PROC + ProcCharacterDisappearOutOfSightToObject((CHARACTERGUID)_Character,(GUIDSTRING)_Object,(INTEGER)_Running,(STRING)_Event,(INTEGER)_IncreaseSpeed) + THEN + CharacterDisableAllCrimes(_Character); + DB_CharacterDisappearedOutOfSight(_Character,_Event,1); + CharacterDisappearOutOfSightToObject(_Character,_Object,_Running,_Event,_IncreaseSpeed); + + QRY + QryCanSeeAttackers((CHARACTERGUID)_Char,(CHARACTERGUID)_Src,(CHARACTERGUID)_SrcSummon) + AND + _SrcSummon != NULL_00000000-0000-0000-0000-000000000000 + AND + _SrcSummon != _Src + AND + CharacterCanSee(_Char,_SrcSummon,1) + THEN + DB_SawAttacker(_SrcSummon); + + QRY + QryCanSeeAttackers((CHARACTERGUID)_Char,(CHARACTERGUID)_Src,(CHARACTERGUID)_SrcSummon) + AND + NOT DB_SawAttacker(_) + AND + CharacterCanSee(_Char,_Src,1) + THEN + DB_SawAttacker(_Src); + + IF + AttackedByObject((CHARACTERGUID)_Char,(CHARACTERGUID)_Src,_SrcSummon,_,_) + AND + _Src != _Char + AND + ObjectIsOnStage(_Char,1) + AND + DB_CharacterDisappearedOutOfSight(_Char,_,1) + AND + IsTagged(_Char,"ANIMAL",0) + AND + CharacterCanFight(_Char,1) + AND + ObjectIsCharacter(_Src,1) + AND + QryCanSeeAttackers(_Char,_Src,_SrcSummon) + AND + DB_SawAttacker(_Target) + THEN + DB_StoppedOutOfSight(_Char); + CharacterPurgeQueue(_Char); + CharacterSetTemporaryHostileRelation(_Char,_Target); + NOT DB_SawAttacker(_Target); + + IF + CharacterSetTemporaryRelationsFailed(_Char,_Target) + AND + DB_StoppedOutOfSight(_Char) + THEN + ProcResumeDisappearOutOfSight(_Char); + + IF + ObjectLeftCombat((CHARACTERGUID)_Char,_) + AND + DB_StoppedOutOfSight(_Char) + THEN + ProcResumeDisappearOutOfSight(_Char); + + PROC + ProcResumeDisappearOutOfSight((CHARACTERGUID)_Char) + AND + NOT DB_Dead(_Char) + AND + DB_CharacterDisappearedOutOfSight(_Char,_Event,1) + THEN + NOT DB_StoppedOutOfSight(_Char); + CharacterDisappearOutOfSight(_Char,0,1,_Event,1); + + IF + CharacterWentOnStage(_Character,1) + AND + DB_CharacterDisappearedOutOfSight(_Character,_Event,_ReactToCombat) + THEN + NOT DB_CharacterDisappearedOutOfSight(_Character,_Event,_ReactToCombat); + ProcRestoreGenericBehaviour(_Character); + + IF + StoryEvent((CHARACTERGUID)_Character,"GEN_CharacterDisableAllCrimesBeforeDisappear") + THEN + CharacterDisableAllCrimes(_Character); + DB_CharacterDisappearedOutOfSight(_Character,"",0); + + PROC + ProcClearDisappearData((CHARACTERGUID)_Character) + AND + DB_CharacterDisappearedOutOfSight(_Character,_Event,_ReactToCombat) + THEN + NOT DB_CharacterDisappearedOutOfSight(_Character,_Event,_ReactToCombat); + + //END_REGION + + //REGION TemporaryHostileRelation + PROC + Proc_CharacterSetTemporaryHostileRelation((CHARACTERGUID)_Char1,(CHARACTERGUID)_Char2) + AND + _Char2!= NULL_00000000-0000-0000-0000-000000000000 + AND + _Char1!= NULL_00000000-0000-0000-0000-000000000000 + THEN + CharacterSetTemporaryHostileRelation(_Char1,_Char2); + //END_REGION + + IF + RegionEnded(_Region) + THEN + ProcRegionEnded(_Region); + + PROC + ProcRegionEnded((STRING)_Region) + THEN + DB_NOOP(1); + + //REGION Healing status query + QRY + QRY_IsHealingStatus((STRING)_Status) + AND + _Status != "HEAL" //DOSTWO-24618 The actual HEAL status is a tick that is set from different statusses (that possibly doesn't heal because it has its parameters overwritten). It's never set on its own. + AND + GetStatusType(_Status,"HEAL") + AND + GetHealStat(_Status,"Vitality") + THEN + DB_NOOP(1); + + QRY + QRY_IsHealingStatus((STRING)_Status) + AND + GetStatusType(_Status,"HEALING") + AND + GetHealStat(_Status,"Vitality") + THEN + DB_NOOP(1); + //END_REGION + + //REGION item moving defaults + PROC + ItemMoveToTrigger((ITEMGUID)_Item,(TRIGGERGUID)_Trigger, (REAL)_Speed, (REAL)_Acceleration, (INTEGER)_UseRotation, (STRING)_Event) + THEN + ItemMoveToTrigger(_Item,_Trigger,_Speed,_Acceleration,_UseRotation,_Event,1); + + PROC + ItemMoveToTrigger((ITEMGUID)_Item,(TRIGGERGUID)_Trigger, (REAL)_Speed, (REAL)_Acceleration, (INTEGER)_UseRotation) + THEN + ItemMoveToTrigger(_Item,_Trigger,_Speed,_Acceleration,_UseRotation,"",1); + + PROC + ItemMoveToPosition((ITEMGUID)_Item, (REAL)_X, (REAL)_Y, (REAL)_Z, (REAL)_Speed, (REAL)_Acceleration, (STRING)_Event) + THEN + ItemMoveToPosition(_Item, _X, _Y, _Z, _Speed, _Acceleration,_Event,1); + + PROC + ItemMoveToPosition((ITEMGUID)_Item, (REAL)_X, (REAL)_Y, (REAL)_Z, (REAL)_Speed, (REAL)_Acceleration) + THEN + ItemMoveToPosition(_Item, _X, _Y, _Z, _Speed, _Acceleration,"",1); + + //END_REGION + + //REGION transform overloads + PROC + Transform((ITEMGUID)_Object, (STRING)_Template) + THEN + Transform(_Object,_Template,0,0,0); + + PROC + Transform((GUIDSTRING)_Object, (STRING)_Template, (INTEGER)_ReplaceScripts) + THEN + Transform(_Object,_Template,_ReplaceScripts,0,0); + + PROC + Transform((GUIDSTRING)_Object, (STRING)_Template, (INTEGER)_ReplaceScripts, (INTEGER)_ReplaceScale) + THEN + Transform(_Object,_Template,_ReplaceScripts,_ReplaceScale,0); + + //END_REGION + + //REGION Perception + PROC + ProcSetPerceptionDifficulty((ITEMGUID)_Item,(STRING)_Difficulty) + THEN + SetVarFixedString(_Item,"Difficulty",_Difficulty); + SetStoryEvent(_Item,"GLO_OverrideWitsCheck"); + //END_REGION + + PROC + PlayEffect((GUIDSTRING)_Object,(STRING)_FxName) + THEN + PlayEffect(_Object,_FxName,""); + + PROC + ApplyDamage((GUIDSTRING)_Object, (INTEGER)_Damage, (STRING)_DamageType) + THEN + ApplyDamage(_Object, _Damage, _DamageType, NULL_00000000-0000-0000-0000-000000000000); + + PROC + ApplyStatus((GUIDSTRING)_Object, (STRING)_Status, (REAL)_Duration, (INTEGER)_Force) + THEN + ApplyStatus(_Object, _Status, _Duration, _Force, NULL_00000000-0000-0000-0000-000000000000); + + PROC + CharacterDie((CHARACTERGUID)_Character, (INTEGER)_GenerateTreasure, (STRING)_DeathType) + THEN + CharacterDie(_Character, _GenerateTreasure, _DeathType, NULL_00000000-0000-0000-0000-000000000000); + + PROC + CharacterDieImmediate((CHARACTERGUID)_Character, (INTEGER)_GenerateTreasure, (STRING)_DeathType) + THEN + CharacterDieImmediate(_Character, _GenerateTreasure, _DeathType, NULL_00000000-0000-0000-0000-000000000000); + + } + EXIT + { + + } +} +Goal(10).Title("__Start"); +Goal(10) +{ + INIT + { + Proc_ExclamationMarkCleanup(); + + + } + KB + { + IF + GameEventSet("GAMEEVENT_GameStarted") + THEN + InitStory(); + GoalCompleted; + + + PROC + Proc_ExclamationMarkCleanup() + AND + _Player.DB_IsPlayer() + THEN + CharacterStopAllEffectsWithName(_Player,"RS3_FX_UI_Exclamation_Mark_01"); + SetHasDialog(_Player,0); + + } + EXIT + { + + } +} +Goal(11).Title("_AAA_FirstGoal"); +Goal(11) +{ + INIT + { + // Time(_Day,_Hour,_TotalHours) + // Current time (updated last time event NewHour was generated) + // _TotalHours = (_Day - 1)*24 + _Hour + // _TotalHours is suitable for calculating time differences + //SetTime(ENGINE_GAME,10); TODO + DB_Time(1,10,10); + // CurrentHalfHour and total HalfHours + DB_HalfHour(20,20); + + //TODO: for now we use these timers to simulate time passing. This should come from the game engine if we're going to support different time of day settings + DB_GameHour(300000); + StartTimeOfDayTimerLoop(); + + // Money dialog variables + DB_FirstGoal_MoneyDialogVar(1,"GEN_CheckMagicPocketGold_6057ad05-9492-4630-9f0a-be548b134c54"); + DB_FirstGoal_MoneyDialogVar(2,"GEN_CheckMagicPocketGold_2_463b0f43-5410-412d-aba3-875cf81c38ca"); + DB_FirstGoal_MoneyDialogVar(3,"GEN_CheckMagicPocketGold_3_01f129ea-b4dc-44b6-8154-9a948f876a82"); + DB_FirstGoal_MoneyDialogVar(4,"GEN_CheckMagicPocketGold_4_5dac5eea-faeb-459c-b675-46c51519b784"); + DB_FirstGoal_MoneyDialogVar(5,"GEN_CheckMagicPocketGold_5_8860ed48-ba5f-4b7b-82bf-f1220f967d41"); + + DB_FirstGoal_CheckPocketGoldSpeakerVar(1,"GEN_CheckPocketGold_SpeakerIndex_8504b4e0-886e-4912-9525-fbe559c5f8ff"); + DB_FirstGoal_CheckPocketGoldSpeakerVar(2,"GEN_CheckPocketGold_2_SpeakerIndex_a9c4d456-3ef5-491d-a1eb-49f09b91e8b4"); + DB_FirstGoal_CheckPocketGoldSpeakerVar(3,"GEN_CheckPocketGold_3_SpeakerIndex_d7fa1537-77d4-4d7d-a955-7ffda90e6207"); + DB_FirstGoal_CheckPocketGoldSpeakerVar(4,"GEN_CheckPocketGold_4_SpeakerIndex_5c499066-448b-4d0c-8dc9-d1553d04c6d4"); + DB_FirstGoal_CheckPocketGoldSpeakerVar(5,"GEN_CheckPocketGold_5_SpeakerIndex_65757687-b815-43fe-be9c-1cefe82efb60"); + + } + KB + { + //REGION Game Mode handling + PROC + Proc_GameModeStarted((STRING)_Mode,(INTEGER)_) + THEN + ProcSetCurrentGameMode(_Mode); + + PROC + ProcSetCurrentGameMode((STRING)_Mode) + AND + DB_CurrentGameMode(_Old) + THEN + NOT DB_CurrentGameMode(_Old); + + PROC + ProcSetCurrentGameMode((STRING)_Mode) + THEN + DB_CurrentGameMode(_Mode); + + //END_REGION + + //REGION Dialog book keeping + IF + DialogRequestFailed(_,_Inst) + THEN + DB_MarkedForDelete(_Inst); + ProcGetInvolvedPlayers(_Inst); + ProcGetInvolvedNPCs(_Inst); + ProcSaveNumActors(_Inst); + ProcClearDialogFlagsForPlayers(_Inst); + ProcClearDialogFlagsForNPCs(_Inst); + + IF + AutomatedDialogRequestFailed(_,_Inst) + THEN + ProcGetInvolvedPlayers(_Inst); + ProcGetInvolvedNPCs(_Inst); + ProcSaveNumActors(_Inst); + DB_AutomatedDialog(_Inst); + + IF + DialogStarted(_Dialog,_Inst) + THEN + ProcGetInvolvedPlayers(_Inst); + ProcGetInvolvedNPCs(_Inst); + ProcSaveNumActors(_Inst); + ProcSetDialogGoldCheckAmount(_Dialog); + DB_DialogName(_Dialog,_Inst); + + IF + DialogActorJoined(_Dialog,_Inst,_Actor) + THEN + ProcAddActorToDialogList(_Inst,_Actor); + ProcSetStoryNPC(_Inst,_Actor); + ProcSetNumberOfInvolvedActors(_Inst); + + IF + VoiceBarkStarted(_,_Inst) + THEN + DB_AutomatedDialogIsVB(_Inst); + + IF + AutomatedDialogStarted(_Dialog,_Inst) + THEN + ProcGetInvolvedPlayers(_Inst); + ProcGetInvolvedNPCs(_Inst); + ProcSaveNumActors(_Inst); + DB_AutomatedDialog(_Inst); + DB_DialogName(_Dialog,_Inst); + + PROC + ProcSetStoryNPC((INTEGER)_Inst,(GUIDSTRING)_Actor) + AND + NOT DB_AutomatedDialog(_Inst) + AND + ObjectIsCharacter((CHARACTERGUID)_Actor,1) + AND + NOT DB_CombatCharacters(_Actor,_) + THEN + CharacterMakeStoryNpc(_Actor,1); + + PROC + ProcSetStoryNPC((INTEGER)_Inst,(GUIDSTRING)_Actor) + AND + NOT DB_AutomatedDialog(_Inst) + THEN + ProcItemSetInvulnerableForDialog(_Actor); + + //add these in the back so we don't disrupt the original flow + PROC + ProcAddActorToDialogList((INTEGER)_Inst,(GUIDSTRING)_Actor) + AND + DB_IsPlayer((CHARACTERGUID)_Actor) + AND + DB_DialogNumPlayers(_Inst,_NumPlayers) + AND + IntegerSum(_NumPlayers,1,_NewSlot) + THEN + DB_DialogPlayers(_Inst,(GUIDSTRING)_Actor,_NewSlot); + + PROC + ProcAddActorToDialogList((INTEGER)_Inst,(GUIDSTRING)_Actor) + AND + NOT DB_IsPlayer((CHARACTERGUID)_Actor) + AND + DB_DialogNumNPCs(_Inst,_NumNPCs) + AND + IntegerSum(_NumNPCs,1,_NewSlot) + THEN + DB_DialogNPCs(_Inst,(GUIDSTRING)_Actor,_NewSlot); + + + PROC + ProcSetNumberOfInvolvedActors((INTEGER)_Inst) + AND + DB_DialogNumPlayers(_Inst,_NumPlayers) + AND + DB_DialogNumNPCs(_Inst,_NumNPCs) + THEN + NOT DB_DialogNumPlayers(_Inst,_NumPlayers); + NOT DB_DialogNumNPCs(_Inst,_NumNPCs); + ProcSaveNumActors(_Inst); + + PROC + ProcSaveNumActors((INTEGER)_Inst) + AND + DialogGetNumberOfInvolvedNPCs(_Inst,_NumNPCs) + AND + DialogGetNumberOfInvolvedPlayers(_Inst,_NumPlayers) + THEN + DB_DialogNumPlayers(_Inst,_NumPlayers); + DB_DialogNumNPCs(_Inst,_NumNPCs); + + PROC + ProcGetInvolvedNPCs((INTEGER)_Inst) + THEN + ProcGetInvolveNPC(_Inst,1); + + PROC + ProcGetInvolveNPC((INTEGER)_Inst,(INTEGER)_Index) + AND + DialogGetInvolvedNPC(_Inst,_Index,_NPC) + AND + IntegerSum(_Index,1,_New) + THEN + DB_DialogNPCs(_Inst,_NPC,_Index); + ProcGetInvolveNPC(_Inst,_New); + + PROC + ProcGetInvolvedPlayers((INTEGER)_Inst) + THEN + ProcGetInvolvePlayer(_Inst,1); + + PROC + ProcGetInvolvePlayer((INTEGER)_Inst,(INTEGER)_Index) + AND + DialogGetInvolvedPlayer(_Inst,_Index,_Player) + AND + IntegerSum(_Index,1,_New) + THEN + DB_DialogPlayers(_Inst,_Player,_Index); + ProcGetInvolvePlayer(_Inst,_New); + + PROC + ProcSetDialogGoldCheckAmount((STRING)_Dialog) + AND + DB_DialogMoneyTransfer((INTEGER)_Index,(STRING)_Dialog,(INTEGER)_Amount,(INTEGER)_CheckSpeakerIndex,(INTEGER)_) + AND + DB_FirstGoal_MoneyDialogVar(_Index,_MoneyVarName) + AND + DB_FirstGoal_CheckPocketGoldSpeakerVar(_Index,_SpeakerVarName) + THEN + DialogSetVariableInt(_Dialog,_MoneyVarName,_Amount); + DialogSetVariableInt(_Dialog,_SpeakerVarName,_CheckSpeakerIndex); + + //END_REGION + + //REGION Player NPC seeing + + PROC + ProcCheckIfOtherPlayersCanSeeNPC((CHARACTERGUID)_,(CHARACTERGUID)_) + AND + DB_OtherPlayersSee(_Npc) + THEN + NOT DB_OtherPlayersSee(_Npc); + + PROC + ProcCheckIfOtherPlayersCanSeeNPC((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + _Other.DB_IsPlayer() + AND + _Other!=_Player + AND + DB_Sees(_OtherPlayer,_Npc) + THEN + DB_OtherPlayersSee(_Npc); + + + //END_REGION + + //REGION Player trigger checking + + QRY + QryCheckOtherPlayersInTrigger((CHARACTERGUID)_Player,(TRIGGERGUID)_CheckTrigger) + AND + _Other.DB_IsPlayer() + AND + _Other!=_Player + AND + DB_InRegion(_Other, _CheckTrigger) + THEN + DB_NOOP(1); + + //END_REGION + + //REGION Player triggers + PROC + ProcTriggerRegisterForPlayers((TRIGGERGUID)_Trig) + AND + GetRegion(_Trig,_Level) + THEN + DB_PlayerTriggers(_Level,_Trig); + ProcDoTriggerRegisterForPlayers(_Level,_Trig); + + PROC + ProcDoTriggerRegisterForPlayers((STRING)_Level,(TRIGGERGUID)_Trig) + AND + ObjectExists(_Trig,0) + THEN + DB_PlayerTriggerToRegister(_Level,_Trig); + + PROC + ProcDoTriggerRegisterForPlayers((STRING)_Level,(TRIGGERGUID)_Trig) + AND + NOT DB_PlayerTriggerToRegister(_Level,_Trig) + THEN + TriggerRegisterForPlayers(_Trig); + + PROC + ProcTriggerUnregisterForPlayers((TRIGGERGUID)_Trig) + AND + DB_PlayerTriggers(_Level,_Trig) + AND + ObjectExists(_Trig,0) + THEN + DB_PlayerTriggerToUnregister(_Level,_Trig); + + PROC + ProcTriggerUnregisterForPlayers((TRIGGERGUID)_Trig) + AND + DB_PlayerTriggers(_Level,_Trig) + AND + NOT DB_PlayerTriggerToUnregister(_Level,_Trig) + THEN + TriggerUnregisterForPlayers(_Trig); + + PROC + ProcTriggerUnregisterForPlayers((TRIGGERGUID)_Trig) + AND + DB_PlayerTriggers(_Level,_Trig) + THEN + NOT DB_PlayerTriggers(_Level,_Trig); + + PROC + ProcRegisterPlayerTriggers((CHARACTERGUID)_Char) + AND + DB_PlayerTriggers(_Level,_Trig) + AND + ObjectExists(_Trig,0) + THEN + DB_PlayerTriggerToRegisterForCharacter(_Char,_Level,_Trig); + + PROC + ProcRegisterPlayerTriggers((CHARACTERGUID)_Char) + AND + DB_PlayerTriggers(_Level,_Trig) + AND + NOT DB_PlayerTriggerToRegisterForCharacter(_Char,_Level,_Trig) + THEN + TriggerRegisterForCharacter(_Trig,_Char); + + PROC + ProcUnRegisterPlayerTriggers((CHARACTERGUID)_Char) + AND + DB_PlayerTriggers(_Level,_Trig) + AND + ObjectExists(_Trig,0) + THEN + DB_PlayerTriggerToUnregisterForCharacter(_Char,_Level,_Trig); + + PROC + ProcUnRegisterPlayerTriggers((CHARACTERGUID)_Char) + AND + DB_PlayerTriggers(_Level,_Trig) + AND + NOT DB_PlayerTriggerToUnregisterForCharacter(_Char,_Level,_Trig) + THEN + TriggerUnregisterForCharacter(_Trig,_Char); + + IF + DB_PlayerTriggerToUnregisterForCharacter(_Char,_Level,_Trig) + THEN + NOT DB_PlayerTriggerToRegisterForCharacter(_Char,_Level,_Trig); + + IF + DB_PlayerTriggerToRegisterForCharacter(_Char,_Level,_Trig) + THEN + NOT DB_PlayerTriggerToUnregisterForCharacter(_Char,_Level,_Trig); + + IF + DB_PlayerTriggerToUnregister(_Level,_Trig) + THEN + NOT DB_PlayerTriggerToRegister(_Level,_Trig); + + IF + DB_PlayerTriggerToRegister(_Level,_Trig) + THEN + NOT DB_PlayerTriggerToUnregister(_Level,_Trig); + + IF + RegionStarted(_Level) + THEN + ProcRegisterTriggersForRegion(_Level); + ProcUnregisterTriggersForRegion(_Level); + ProcRegisterTriggersForCharacters(_Level); + ProcUnregisterTriggersForCharacters(_Level); + + PROC + ProcRegisterTriggersForRegion((STRING)_Level) + AND + DB_PlayerTriggerToRegister(_Level,_Trig) + THEN + TriggerRegisterForPlayers(_Trig); + NOT DB_PlayerTriggerToRegister(_Level,_Trig); + + PROC + ProcUnregisterTriggersForRegion((STRING)_Level) + AND + DB_PlayerTriggerToUnregister(_Level,_Trig) + THEN + TriggerUnregisterForPlayers(_Trig); + NOT DB_PlayerTriggerToUnregister(_Level,_Trig); + + PROC + ProcRegisterTriggersForCharacters((STRING)_Level) + AND + DB_PlayerTriggerToRegisterForCharacter(_Char,_Level,_Trig) + THEN + TriggerRegisterForCharacter(_Trig,_Char); + NOT DB_PlayerTriggerToRegisterForCharacter(_Char,_Level,_Trig); + + PROC + ProcUnregisterTriggersForCharacters((STRING)_Level) + AND + DB_PlayerTriggerToUnregisterForCharacter(_Char,_Level,_Trig) + THEN + TriggerUnregisterForCharacter(_Trig,_Char); + NOT DB_PlayerTriggerToUnregisterForCharacter(_Char,_Level,_Trig); + + PROC + ProcSetupGenericTimers((CHARACTERGUID)_Char) + AND + GetUUID(_Char,_UUID) + AND + StringConcatenate(_UUID,"_genTim",_Timer) + THEN + DB_GenericDialogTimers(_Char,_Timer); + + PROC + ProcRemoveGenericTimer((CHARACTERGUID)_Char) + AND + DB_GenericDialogTimers(_Char,_Timer) + THEN + NOT DB_GenericDialogTimers(_Char,_Timer); + //END_REGION + + // Since storyeditor orders goals alphabetically, this is the only way to make sure this goal comes first in story.div + // This is important because Osiris uses rule order to execute alternatives. + + /////////////////////////////////////////////////////////////////////// + // buffer time + + PROC + StartTimeOfDayTimerLoop() + AND + DB_GameHour(_Msec) + THEN + TimerLaunch("TimeOfDay",_Msec); + + IF + TimerFinished("TimeOfDay") + AND + DB_GameHour(_Msec) + AND + DB_Time(_,_Hour,_) + AND + IntegerSum(_Hour,1,_NewHour) + AND + IntegerModulo(_NewHour,24,_Mod) + THEN + TimerLaunch("TimeOfDay",_Msec); + NewHour(_Mod); + + PROC + NewHour(0) + AND // Day shifts to tomorrow + DB_Time((INTEGER)_Day,(INTEGER)_,(INTEGER)_) + AND + IntegerSum(_Day,1,_DayP1) + THEN + UpdateTime(_DayP1,0); + + PROC + NewHour((INTEGER)_Hour) + AND + _Hour != 0 + AND // Day stays today + DB_Time(_Day,_,_) + THEN + UpdateTime(_Day,_Hour); + + // Asserts Time(_Day,_Hour,...) with ... = the corresponding total hours = 24*(_Day - 1) + _Hour + PROC + UpdateTime((INTEGER)_Day,(INTEGER)_Hour) + AND + DB_Time(_D,_H,_TH) + AND + // calc new total hours: + IntegerSubtract(_Day,1,_DM1) + AND + IntegerProduct(_DM1,24,_T1) + AND + IntegerSum(_T1,_Hour,_NewTH) + THEN + NOT DB_Time(_D,_H,_TH); + DB_Time(_Day,_Hour,_NewTH); + + //TODO: commented stuff + /* + // + IF NewHalfHour(ENGINE_GAME,0) + THEN SetNewHalfHour(24); + IF NewHalfHour(ENGINE_GAME,_HH) AND _HH != 0 + THEN SetNewHalfHour(_HH); + + PROC SetNewHalfHour((INTEGER)_HH) AND + HalfHour((INTEGER)_CurrentHH,(INTEGER)_TotalHH) AND + IntegerSubtract(FUNCTION_Math,_HH,_CurrentHH,_Delta) AND + // Normally, Delta == 1 + IntegerSum(FUNCTION_Math,_CurrentHH,_Delta,_CurrentHHPDelta) AND + IntegerSum(FUNCTION_Math,_TotalHH,_Delta,_TotalHHPDelta) + THEN NOT HalfHour(_CurrentHH,_TotalHH); + HalfHour(_CurrentHHPDelta,_TotalHHPDelta); + + + /////////////////////////////////////////////////////////////////////// + // Buffer player invisibility + IF PlayerTurnsInvisible(NPC_Hero,1) + THEN PlayerIsInvisible(1); + + IF PlayerTurnsInvisible(NPC_Hero,0) + THEN NOT PlayerIsInvisible(1); + */ + /////////////////////////////////////////////////////////////////////// + // Buffer seeing events + // Note: "Sees" is asserted as soon as the "NpcSees" is generated. So you can use + // "Sees" as event as well. Major difference: NpcSees ignores player invisibility. + + // Buffer effects of player movement: + // (NpcSees actually means: "player starts seeing", NpcDoesNotSee means "players ends seeing") + IF + CharacterSawCharacter(_Player,_Npc) + AND + _Player.DB_IsPlayer() + THEN + DB_Sees(_Player, _Npc); + + //DB_Dead NPCs are blind + IF + CharacterDying(_Npc) + AND + DB_Sees(_Npc,_Player) + THEN + NOT DB_Sees(_Npc,_Player); + + IF + CharacterLostSightOfCharacter(_Player,_Npc) + AND + _Player.DB_IsPlayer() + THEN + NOT DB_Sees(_Player, _Npc); + NOT DB_Sees(_Npc, _Player); + + // Bring player invisibility into account (neglect for story npcs): + IF + DB_Sees(_Npc, _Player) + AND + _Player.DB_IsPlayer() + AND + DB_PlayerIsInvisible(_Player,1) + AND + NOT DB_IsStoryNpc(_Npc) + THEN + NOT DB_Sees(_Npc, _Player); + + IF + DB_Sees(_Player, _Npc) + AND + _Player.DB_IsPlayer() + AND + NOT DB_PlayerIsInvisible(_Player,1) + THEN + DB_Sees(_Npc, _Player); + + IF + DB_Sees(_Player, _Npc) + AND + _Player.DB_IsPlayer() + AND + DB_IsStoryNpc(_Npc) + THEN + DB_Sees(_Npc, _Player); + + /* + /////////////////////////////////////////////////////////////////////// + // Buffer dialog distance (analogous to seeing events) + + // Buffer effects of player movement: + IF NpcEntersDialogDistance(NPC_Hero, _Npc) + THEN InDialogDistance(NPC_Hero, _Npc); + + IF NpcLeavesDialogDistance(NPC_Hero, _Npc) + THEN NOT InDialogDistance(NPC_Hero, _Npc); + NOT InDialogDistance(_Npc, NPC_Hero); + + // Bring player invisibility into account (neglect for story npcs): + IF InDialogDistance(_Npc, NPC_Hero) AND PlayerIsInvisible(1) AND NOT DB_IsStoryNpc(_Npc) + THEN NOT InDialogDistance(_Npc, NPC_Hero); + + IF InDialogDistance(NPC_Hero, _Npc) AND NOT PlayerIsInvisible(1) + THEN InDialogDistance(_Npc, NPC_Hero); + + IF InDialogDistance(NPC_Hero, _Npc) AND DB_IsStoryNpc(_Npc) + THEN InDialogDistance(_Npc, NPC_Hero); + */ + + /////////////////////////////////////////////////////////////////////// + // Buffer region events + IF + CharacterEnteredTrigger(_Npc,_Region) + THEN + DB_InRegion(_Npc, _Region); + + IF + CharacterLeftTrigger(_Npc,_Region) + THEN + NOT DB_InRegion(_Npc, _Region); + DB_WasInRegion(_Npc,_Region); + + /////////////////////////////////////////////////////////////////////// + // Buffer killed + IF + CharacterDying(_Npc) + THEN + DB_Dead(_Npc); + + IF + CharacterDied(_Npc) + AND + NOT DB_Dead(_Npc) + THEN + DB_Dead(_Npc); + + IF + CharacterResurrected(_Npc) + THEN + NOT DB_Dead(_Npc); + + //TODO: comments + /* + // Engine does not generate NpcDoesNotSee for dead npcs anymore, so we have to clean up ourself: + IF NpcKilled(_Npc) AND Sees(_Npc,_OtherNpc) + THEN NOT Sees(_Npc,_OtherNpc); + IF NpcKilled(_Npc) AND Sees(_OtherNpc,_Npc) + THEN NOT Sees(_OtherNpc,_Npc); + // Cleanup InDialogDistance + IF NpcKilled(_Npc) AND InDialogDistance(_Npc,_OtherNpc) + THEN NOT InDialogDistance(_Npc,_OtherNpc); + IF NpcKilled(_Npc) AND InDialogDistance(_OtherNpc,_Npc) + THEN NOT InDialogDistance(_OtherNpc,_Npc); + */ + + /* ///This Breaks a lot of things especially Arrest in Generics + IF + CharacterDied(_Npc) + AND + DB_InRegion(_Npc,_Region) + THEN + NOT DB_InRegion(_Npc,_Region); + */ + + //TODO: comments + /* + IF NpcResurrected((NPC)_Npc) + THEN NOT DB_Dead(_Npc); + + IF NpcKilledBy(_Npc,NPC_Hero) + THEN HeroKilled(_Npc); + */ + /////////////////////////////////////////////////////////////////////// + // Cleanup DB_InRegion of npc (not the hero) if they are killed + // test for _Npc != NPC_Hero explicitely added because debug cheat key "F1" does not + // resurrect NPC_Hero, hence he remains "dead" although he can play on, enter regions, etc... + IF + DB_Dead(_Npc) + AND + NOT _Npc.DB_IsPlayer() + AND + DB_InRegion(_Npc,_Region) + THEN + NOT DB_InRegion(_Npc,_Region); + + IF + DB_Dead(_Npc) + AND + DB_DeadEvent(_Npc,(STRING)_Event) + AND + GlobalGetFlag(_Event,0) + THEN + GlobalSetFlag(_Event); + + IF + RegionStarted((STRING)_NewRegion) + THEN + DB_CurrentLevel(_NewRegion); + + IF + RegionEnded((STRING)_Region) + THEN + NOT DB_CurrentLevel(_Region); + + + //REGION OneshotTriggers + IF + DB_OneShotPlayerTrigger(_Trigger) + THEN + ProcTriggerRegisterForPlayers(_Trigger); + + IF + DB_OneShotPlayerOnlyTrigger(_Trigger) + THEN + TriggerRegisterForPlayers(_Trigger); + + IF + CharacterEnteredTrigger(_Player,_Trigger) + AND + DB_OneShotPlayerOnlyTrigger(_Trigger) + THEN + TriggerUnregisterForPlayers(_Trigger); + NOT DB_OneShotPlayerOnlyTrigger(_Trigger); + ProcOneShotTriggerEntered(_Player,_Trigger); + + PROC + RemoveOneShotTrigger((TRIGGERGUID)_Trigger) + AND + DB_OneShotPlayerTrigger(_Trigger) + THEN + ProcTriggerUnregisterForPlayers(_Trigger); + NOT DB_OneShotPlayerTrigger(_Trigger); + + IF + CharacterEnteredTrigger(_Player,_Trigger) + AND + DB_OneShotPlayerTrigger(_Trigger) + AND + _Player.DB_IsPlayer() + THEN + RemoveOneShotTrigger(_Trigger); + ProcOneShotTriggerEntered(_Player,_Trigger); + + PROC + ProcOneShotTriggerEntered((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + THEN + DB_NOOP(1); + //END_REGION + + //REGION _Global_CharacterAnimations + // Flush player character animations that may be ongoing at the end of a dialog + IF + DialogEnded(_,_Dialog) + AND + DB_GLO_CharacterAnimationForDialog(_Character,_Dialog) + AND + DB_IsPlayer(_Character) + THEN + CharacterFlushQueue(_Character); + + IF + DialogEnded(_,_Dialog) + AND + DB_GLO_CharacterAnimationForDialog(_Character,_Dialog) + THEN + // The animation may be purged by other code and hence never finish -> this DB would never be unset + NOT DB_GLO_CharacterAnimationForDialog(_Character,_Dialog); + //END_REGION + + } + EXIT + { + + } +} +Goal(12).Title("_AdvancedSneakTriggerSpotter"); +Goal(12) +{ + INIT + { + //REGION AdvancedSneakTriggerSupport + DB_SneakTriggerVars(1,"SpottedTrigger"); + DB_SneakTriggerVars(2,"SpottedTrigger1"); + DB_SneakTriggerVars(3,"SpottedTrigger2"); + DB_SneakTriggerVars(4,"SpottedTrigger3"); + //END_REGION + + } + KB + { + //REGION AdvancedSneakTrigger + IF + DB_AdvancedSneakTriggerSpotter((TRIGGERGUID)_Trigger,(CHARACTERGUID)_Char) + THEN + ProcSetSneakyTriggerVar(_Char,_Trigger); + PROC + ProcSetSneakyTriggerVar((CHARACTERGUID)_Char,(TRIGGERGUID)_Trigger) + AND + NOT DB_SneakyTriggersCounter(_Char,_) + THEN + DB_SneakyTriggersCounter(_Char,0); + PROC + ProcSetSneakyTriggerVar((CHARACTERGUID)_Char,(TRIGGERGUID)_Trigger) + AND + DB_SneakyTriggersCounter(_Char,_Count) + AND + IntegerSum(_Count,1,_New) + AND + DB_SneakTriggerVars(_New,_Var) + THEN + DB_SneakyTriggersCounter(_Char,_New); + NOT DB_SneakyTriggersCounter(_Char,_Count); + SetVarObject(_Char,_Var,_Trigger); + ProcTriggerRegisterForPlayers(_Trigger); + + IF + StoryEvent((CHARACTERGUID)_Char, "GLO_AdvancedSpotterSneaker") + AND + GetVarObject(_Char, "SpottedDude", _Player) + THEN + ProcCharSpottedByChar((CHARACTERGUID)_Player,_Char); + ProcReceiveActivatedTriggers(_Char,_Player); + ProcLockSpotting(_Char); + + PROC + ProcReceiveActivatedTriggers((CHARACTERGUID)_Char,(CHARACTERGUID)_Player) + AND + DB_AdvancedSneakTriggerSpotter((TRIGGERGUID)_Trigger, (CHARACTERGUID)_Char) + AND + DB_InRegion(_Player,_Trigger) + THEN + ProcCharInTriggerSpotted(_Player,_Trigger); + ProcCharInTriggerSpottedByChar(_Player,_Trigger,_Char); + + PROC + ProcCharSpottedByChar((CHARACTERGUID)_Player,(CHARACTERGUID)_Spotter) + THEN + DB_NOOP(1); + + PROC + ProcLockSpotting((CHARACTERGUID)_Char) + THEN + SetVarInteger(_Char, "SpottedCounter", 1); + + PROC + ProcCleanUpAdvancedSneakTriggers((CHARACTERGUID)_Char) + AND + DB_AdvancedSneakTriggerSpotter((TRIGGERGUID)_Trigger, (CHARACTERGUID)_Char) + THEN + NOT DB_AdvancedSneakTriggerSpotter(_Trigger, _Char); + SetVarInteger(_Char, "SpottedCounter", 1); + + PROC + ProcTriggerUnregisterForPlayers((TRIGGERGUID)_Trigger) + AND + DB_AdvancedSneakTriggerSpotter((TRIGGERGUID)_Trigger, (CHARACTERGUID)_Char) + THEN + NOT DB_AdvancedSneakTriggerSpotter((TRIGGERGUID)_Trigger, (CHARACTERGUID)_Char); + IF + DB_SpotterGroup((CHARACTERGUID)_Char,(STRING)_Name) + AND + _Player.DB_isPlayer() + THEN + SetVarInteger(_Player,_Name,0); + SetVarFixedString(_Char,"SpotterGroup",_Name); + //END_REGION + + } + EXIT + { + + } +} +Goal(13).Title("_Attitude"); +Goal(13) +{ + INIT + { + + } + KB + { + PROC + ProcMakeNPCHostile((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + CharacterIsDead(_Npc,0) + AND + CharacterIsPlayer(_Player,1) + AND + CharacterIsPlayer(_Npc,0) + THEN + CharacterSetTemporaryHostileRelation(_Npc,_Player); + + PROC + ProcMakeNPCHostile((CHARACTERGUID)_Npc,(CHARACTERGUID)_Player) + AND + CharacterIsDead(_Npc,0) + AND + CharacterIsPlayer(_Player,1) + THEN + CharacterSetTemporaryHostileRelation(_Npc,_Player); + + PROC + ProcMakeNPCHostile((CHARACTERGUID)_Npc,(CHARACTERGUID)_OtherNpc) + AND + CharacterIsDead(_Npc,0) + AND + CharacterIsDead(_OtherNpc,0) + AND + CharacterIsPlayer(_Npc,0) + AND + CharacterIsPlayer(_OtherNpc,0) + THEN + CharacterSetTemporaryHostileRelation(_Npc,_OtherNpc); + + } + EXIT + { + + } +} +Goal(14).Title("_CRIME_CrimeBribes"); +Goal(14) +{ + INIT + { + // small (0) or big (1) bribe, max player level, min amount, max-min amount + DB_CrimeBribes_BaseAmountUntilLevel(0,50,10,1); + DB_CrimeBribes_BaseAmountUntilLevel(0,70,20,5); + DB_CrimeBribes_BaseAmountUntilLevel(0,150,50,9); + DB_CrimeBribes_BaseAmountUntilLevel(0,245,65,13); + DB_CrimeBribes_BaseAmountUntilLevel(0,410,110,16); + DB_CrimeBribes_BaseAmountUntilLevel(0,600,200,18); + DB_CrimeBribes_BaseAmountUntilLevel(0,800,250,20); + + DB_CrimeBribes_BaseAmountUntilLevel(1,125,25,1); + DB_CrimeBribes_BaseAmountUntilLevel(1,175,30,5); + DB_CrimeBribes_BaseAmountUntilLevel(1,400,60,9); + DB_CrimeBribes_BaseAmountUntilLevel(1,625,100,13); + DB_CrimeBribes_BaseAmountUntilLevel(1,1100,200,16); + DB_CrimeBribes_BaseAmountUntilLevel(1,1600,400,18); + DB_CrimeBribes_BaseAmountUntilLevel(1,2200,500,20); + + DB_CrimeBribes_SevereCrimes("Murder"); + DB_CrimeBribes_SevereCrimes("SneakMurder"); + DB_CrimeBribes_SevereCrimes("Assault"); + + } + KB + { + //REGION Polymorph statuses are handled in the DivinityOrigins mod, so add a dummy proxy and a fallback + // Actual implemetation in GLOBAL_ShapeShifting in DivinityOrigins + QRY + QRY_GLOBAL_Shapeshifting_GetPolymorphStatus((CHARACTERGUID)_Player) + THEN + DB_NOOP(1); + + // If we're not using DivinityOrigins, ensure we still define a + // generic DB_GLOBAL_Shapeshifting_PolymorphStatus() as fallback + QRY + QRY_GLOBAL_Shapeshifting_GetPolymorphStatus_Fallback((CHARACTERGUID)_Player) + AND + NOT DB_GLOBAL_Shapeshifting_PolymorphStatus(_) + THEN + DB_GLOBAL_Shapeshifting_PolymorphStatus(""); + + // Ensure fallback query always succeeds + QRY + QRY_GLOBAL_Shapeshifting_GetPolymorphStatus_Fallback((CHARACTERGUID)_Player) + THEN + DB_NOOP(1); + + //END_REGION + + //REGION Determine whether we select from the high or low bribes + // Possible selectors: + // * Tension + // * Severity of the crime + // * Number of times this person has been bribed + + // Determine severity + // Return value: + // Severe crime: DB_CrimeBribes_CrimeSeverity(1) + // Non-sever crime: DB_CrimeBribes_CrimeSeverity(0) + QRY + QRY_CrimeBribes_CrimeGetSeverity((STRING)_CrimeType) + AND + DB_CrimeBribes_CrimeSeverity(_Severity) + THEN + NOT DB_CrimeBribes_CrimeSeverity(_Severity); + + QRY + QRY_CrimeBribes_CrimeGetSeverity((STRING)_CrimeType) + AND + DB_CrimeBribes_SevereCrimes(_CrimeType) + THEN + DB_CrimeBribes_CrimeSeverity(1); + + QRY + QRY_CrimeBribes_CrimeGetSeverity((STRING)_CrimeType) + AND + NOT DB_CrimeBribes_CrimeSeverity(1) + THEN + DB_CrimeBribes_CrimeSeverity(0); + + // Keep track of number of times this criminal has bribed this interrogator + IF + ObjectFlagSet(_Flag,_Speaker,_ID) + AND + DB_ItemEvents_TransferFlagToMoneyVarIndex(_Flag,_MoneyVarIndex) + AND + DB_DialogName(_Dialog,_ID) + AND + DB_CrimeTriggers_GeneralBribeDialog(_MoneyVarIndex,_Dialog) + AND + DB_DialogMoneyTransfer(_MoneyVarIndex,_Dialog,_,_,_TargetDBIndex) + AND + DB_DialogPlayers(_ID,_Player,1) + AND + DB_DialogNPCs(_ID,_NPC,_TargetDBIndex) + AND + QRY_GLOBAL_Shapeshifting_GetPolymorphStatus(_Player) + AND + QRY_GLOBAL_Shapeshifting_GetPolymorphStatus_Fallback(_Player) + AND + DB_GLOBAL_Shapeshifting_PolymorphStatus(_Race) + THEN + PROC_CrimeBribes_RecordBribe((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,_Race); + + PROC + PROC_CrimeBribes_RecordBribe((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(STRING)_Race) + AND + DB_CrimeBribes_PairBribes(_NPC,_Player,_Race,_Bribes) + AND + IntegerSum(_Bribes,1,_NewBribes) + THEN + NOT DB_CrimeBribes_PairBribes(_NPC,_Player,_Race,_Bribes); + DB_CrimeBribes_PairBribes(_NPC,_Player,_Race,_NewBribes); + + PROC + PROC_CrimeBribes_RecordBribe((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(STRING)_Race) + AND + NOT DB_CrimeBribes_PairBribes(_NPC,_Player,_Race,_) + THEN + DB_CrimeBribes_PairBribes(_NPC,_Player,_Race,1); + + // Return value: + // Bribed too many times: DB_CrimeBribes_BribedTooManyTimes(1) + // Not yet bribed or a few times: DB_CrimeBribes_BribedTooManyTimes(0) + QRY + QRY_CrimeBribes_BribedTooManyTimes((CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal,(STRING)_Race) + AND + DB_CrimeBribes_BribedTooManyTimes(_Result) + THEN + NOT DB_CrimeBribes_BribedTooManyTimes(_Result); + + QRY + QRY_CrimeBribes_BribedTooManyTimes((CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal,(STRING)_Race) + AND + DB_CrimeBribes_PairBribes(_Interrogator,_Criminal,_Race,_Bribes) + AND + // This is the number of times the NPC has already been bribed before. So starting at the second time, + // it's too much + _Bribes >= 1 + THEN + DB_CrimeBribes_BribedTooManyTimes(1); + + QRY + QRY_CrimeBribes_BribedTooManyTimes((CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal,(STRING)_Race) + AND + NOT DB_CrimeBribes_BribedTooManyTimes(1) + THEN + DB_CrimeBribes_BribedTooManyTimes(0); + + // Get bribe base & variation from table + PROC + PROC_CrimeBribes_GetBribeBounds((INTEGER)_HighBase,(INTEGER)_InterrogatorLevel) + AND + DB_CrimeBribes_GetBribeBounds(_Base,_Rand) + THEN + NOT DB_CrimeBribes_GetBribeBounds(_Base,_Rand); + + PROC + PROC_CrimeBribes_GetBribeBounds((INTEGER)_HighBase,(INTEGER)_InterrogatorLevel) + AND + DB_CrimeBribes_BaseAmountUntilLevel(_HighBase,_Base,_Rand,1) + THEN + DB_CrimeBribes_GetBribeBounds(_Base,_Rand); + + PROC + PROC_CrimeBribes_GetBribeBounds((INTEGER)_HighBase,(INTEGER)_InterrogatorLevel) + AND + DB_CrimeBribes_BaseAmountUntilLevel(_HighBase,_Base,_Rand,_Level) + AND + DB_CrimeBribes_GetBribeBounds(_OldBase,_OldRand) + AND + _Level <= _InterrogatorLevel + AND + _Base > _OldBase + THEN + NOT DB_CrimeBribes_GetBribeBounds(_OldBase,_OldRand); + DB_CrimeBribes_GetBribeBounds(_Base,_Rand); + + // Get the bribe amount + // Once a bribe amount has been set for an NPC, it stays that way until it switches from low to high + // base, or if the level of the NPC changes (it doesn't make sense if the bribe changes randomly for + // the same NPC with every new encounter). + PROC + PROC_CrimeBribes_GetBribe((CHARACTERGUID)_NPC,(INTEGER)_NPCLevel,(INTEGER)_HighBase) + AND + NOT DB_CrimeBribes_GetBribe_NPC(_NPC,_NPCLevel,_HighBase,_) + THEN + PROC_CrimeBribes_GetBribeBounds((INTEGER)_HighBase,(INTEGER)_NPCLevel); + + PROC + PROC_CrimeBribes_GetBribe((CHARACTERGUID)_NPC,(INTEGER)_NPCLevel,(INTEGER)_HighBase) + AND + NOT DB_CrimeBribes_GetBribe_NPC(_NPC,_NPCLevel,_HighBase,_) + AND + DB_CrimeBribes_GetBribeBounds(_Base,_Rand) + AND + Random(_Rand,_Variation) + AND + IntegerSum(_Base,_Variation,_Bribe) + THEN + DB_CrimeBribes_GetBribe_NPC(_NPC,_NPCLevel,_HighBase,_Bribe); + + // return value + PROC + PROC_CrimeBribes_GetBribe((CHARACTERGUID)_NPC,(INTEGER)_NPCLevel,(INTEGER)_HighBase) + AND + DB_CrimeBribes_GetBribe(_Bribe) + THEN + NOT DB_CrimeBribes_GetBribe(_Bribe); + + PROC + PROC_CrimeBribes_GetBribe((CHARACTERGUID)_NPC,(INTEGER)_NPCLevel,(INTEGER)_HighBase) + AND + DB_CrimeBribes_GetBribe_NPC(_NPC,_NPCLevel,_HighBase,_Bribe) + THEN + DB_CrimeBribes_GetBribe(_Bribe); + + // Set the bribe amount + IF + CrimeInterrogationRequest(_RegionID,_ID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog) + THEN + PROC_CrimeBribes_SetCrimeBribe(_ID,_Interrogator,_Criminal1,_Dialog); + + PROC + ProcStartCrimeDialog((INTEGER)_CrimeID,(STRING)_CrimeDialog,1,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + THEN + PROC_CrimeBribes_SetCrimeBribe(_CrimeID,_NPC,_Criminal,_CrimeDialog); + + //REGION Generic callback to disable bribing by certain (classes of) characters + PROC + PROC_CrimeBribes_SetCrimeBribe((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal,(STRING)_Dialog) + AND + QRY_CrimeBribes_DisableBribe(_CrimeID,_Interrogator,_Criminal,_Dialog) + THEN + DB_CrimeBribesDisabledBribe(_Interrogator,_Criminal,_Dialog); + ObjectSetFlag(_Interrogator,"GEB_BribeDisabled"); + //END_REGION + + //REGION Only allow bribing a few times + QRY + QRY_CrimeBribes_DisableBribe((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal,(STRING)_Dialog) + AND + QRY_GLOBAL_Shapeshifting_GetPolymorphStatus(_Criminal) + AND + DB_GLOBAL_Shapeshifting_PolymorphStatus(_Race) + AND + QRY_CrimeBribes_BribedTooManyTimes(_Interrogator,_Criminal,_Race) + AND + DB_CrimeBribes_BribedTooManyTimes(1) + THEN + DB_NOOP(1); + + IF + DialogEnded(_Dialog,_ID) + AND + DB_CrimeBribesDisabledBribe(_Interrogator,_Criminal,_Dialog) + AND + DB_DialogNPCs(_ID,_Interrogator,_) + AND + DB_DialogPlayers(_ID,_Criminal,_) + THEN + NOT DB_CrimeBribesDisabledBribe(_Interrogator,_Criminal,_Dialog); + ObjectClearFlag(_Interrogator,"GEB_BribeDisabled"); + //END_REGION + + // Low bribe if this NPC has not yet been bribed too many time by this player, + // AND it's not a severe crime, AND tension is below warning threshold. + // Otherwise higher bribe. + PROC + PROC_CrimeBribes_SetCrimeBribe((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal,(STRING)_Dialog) + AND + DB_CrimeTriggers_GeneralBribeDialog(_MoneyVarIndex,_Dialog) + AND + CrimeGetType(_CrimeID,_CrimeType) + AND + QRY_CrimeBribes_CrimeGetSeverity(_CrimeType) + AND + QRY_GLOBAL_Shapeshifting_GetPolymorphStatus(_Criminal) + AND + DB_GLOBAL_Shapeshifting_PolymorphStatus(_Race) + AND + QRY_CrimeBribes_BribedTooManyTimes(_Interrogator,_Criminal,_Race) + AND + DB_CrimeBribes_CrimeSeverity(_Severity) + AND + DB_CrimeBribes_BribedTooManyTimes(_TooManyTimes) + AND + IntegerMax(_Severity,_TooManyTimes,_HighBase1) + AND + CrimeIsTensionOverWarningTreshold(_Criminal,_TensionOverWarning) + AND + IntegerMax(_HighBase1,_TensionOverWarning,_HighBaseFinal) + AND + CharacterGetLevel(_Interrogator,_InterrogatorLevel) + THEN + PROC_CrimeBribes_GetBribe(_Interrogator,_InterrogatorLevel,_HighBaseFinal); + + PROC + PROC_CrimeBribes_SetCrimeBribe((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal,(STRING)_Dialog) + AND + DB_CrimeTriggers_GeneralBribeDialog(_MoneyVarIndex,_Dialog) + AND + DB_CrimeBribes_GetBribe(_Bribe) + THEN + // Will clear previous entries, if any + DB_DialogMoneyTransfer(_MoneyVarIndex,_Dialog,_Bribe); + + } + EXIT + { + + } +} +Goal(15).Title("_CRIME_CrimeTriggers"); +Goal(15) +{ + INIT + { + //Warning As AD + // TODO: what if a custom warning is an AD? Does it get added in there? + DB_CrimeWarningIsAD("GEB_AD_Noticed_EscapedPrisonerHelpful"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_Vandalise"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_Sneaking"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_Smelly"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_Weapons"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_AttackedAnimal"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_KilledAnimal"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_AnimalAttackedAnimal"); + DB_CrimeWarningIsAD("GEB_AD_Help_Thief"); + DB_CrimeWarningIsAD("GEB_AD_FTJ_Noticed_NoCollar"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_SummonAssault"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_SummonVandalise"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_Summon"); + DB_CrimeWarningIsAD("GEB_AD_Noticed_Polymorphed"); + DB_CrimeWarningIsAD("GEB_Lohse_AD_Warning_SummonAssault"); + DB_CrimeWarningIsAD("GEB_Ifan_AD_Warning_SummonAssault"); + DB_CrimeWarningIsAD("GEB_Sebille_AD_Warning_SummonAssault"); + DB_CrimeWarningIsAD("GEB_RedPrince_AD_Warning_SummonAssault"); + DB_CrimeWarningIsAD("GEB_AD_NoticedDeadSilentMonk"); + + // Trespassing + DB_TrespassingCrimes("Trespassing"); + + // Murder + + // Killing -> Murder type mapping : Sneak or not, Killed animal or not, killer is Summon or not + DB_CRIME_MurderType(0,0,0,"Murder"); + DB_CRIME_MurderType(1,0,0,"SneakMurder"); + DB_CRIME_MurderType(0,1,0,"KilledAnimal"); + DB_CRIME_MurderType(1,1,0,"SneakKilledAnimal"); + DB_CRIME_MurderType(0,0,1,"SummonMurder"); + DB_CRIME_MurderType(1,0,1,"SummonMurder"); + DB_CRIME_MurderType(0,1,1,"SummonKilledAnimal"); + DB_CRIME_MurderType(1,1,1,"SummonKilledAnimal"); + + DB_CRIME_ForbiddenStatus("LYING"); + + //For Status Reactions + DB_StatusReaction("SMELLY","Smelly"); + DB_StatusReaction("UNSHEATHED","WeaponsDrawn"); + + //Ingnore Vandalise Tags + DB_IgnoreVandaliseTag("JUNK"); + DB_IgnoreVandaliseTag("IGNOREVANDALISE"); + + //Bribe + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Arrest"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Arrest_EscapedPrison"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Arrest_Theft"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Arrest_Trespassing"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Arrest_UseForbiddenItem"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Arrest_Vandalise"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Interrogation"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Interrogation_Assault"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Interrogation_Murder"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Interrogation_PickPocketNoticed"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Interrogation_Steal"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Interrogation_UsedSource"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Interrogation_Vandalise"); + DB_CrimeTriggers_GeneralBribeDialog(1,"GEB_Warning_PickPocketFailed_EvidenceCheck"); + + //Pickpocket + DB_CannotPickpocketTags("ANIMAL"); + DB_CannotPickpocketTags("ELEMENTAL"); + DB_CannotPickpocketTags("GHOST"); + DB_CannotPickpocketTags("VOIDLING"); + DB_CannotPickpocketTags("VOIDSECT"); + DB_CannotPickpocketTags("VOID_SOLDIER"); + DB_CannotPickpocketTags("ALANBIRD"); + DB_CannotPickpocketTags("MOLESPITTER"); + DB_CannotPickpocketTags("NIGHTFANG"); + DB_CannotPickpocketTags("VOIDWOLF"); + DB_CannotPickpocketTags("FLESH_GOLEM"); + DB_CannotPickpocketTags("BLOCK_PICKPOCKET"); + + //Attitude Change + DB_CrimeAttitudeChange("SourceMagic",-5); + DB_CrimeAttitudeChange("Murder",-30); + DB_CrimeAttitudeChange("SpiritTalk",-1); + DB_CrimeAttitudeChange("Assault",-20); + DB_CrimeAttitudeChange("Steal",-5); + DB_CrimeAttitudeChange("PickPocketFailed",-5); + DB_CrimeAttitudeChange("PickPocket",-10); + DB_CrimeAttitudeChange("ItemDestroy",-15); + DB_CrimeAttitudeChange("Vandalise",-10); + DB_CrimeAttitudeChange("VandaliseNoOwner",-5); + DB_CrimeAttitudeChange("Trespassing",-5); + DB_CrimeAttitudeChange("UseForbiddenItem",-5); + DB_CrimeAttitudeChange("MoveForbiddenItem",-5); + DB_CrimeAttitudeChange("AttackAnimal",-5); + + //Evidence check + DB_EvidenceCheckInWarning("GEB_Warning_PickPocketFailed_EvidenceCheck"); + DB_EvidenceCheckInWarning("RC_WH_DijinnItem_Interrogation"); + + DB_NeutralTagIgnore("GHOST"); + + DB_Negate(0,1); + DB_Negate(1,0); + + DB_IgnoreDamageSources("SurfaceMove"); + DB_IgnoreDamageSources("StatusTick"); + DB_IgnoreDamageSources("SurfaceStatus"); + DB_IgnoreDamageSources("Offhand"); + + //crime tpyes that should be kept in sync when the parent crime is enabled/disabled + DB_LinkedCrimes("Assault","SummonAssault"); + DB_LinkedCrimes("Assault","IncapacitatedAssault"); + + DB_LinkedCrimes("Murder","KilledAnimal"); + DB_LinkedCrimes("Murder","SneakKilledAnimal"); + DB_LinkedCrimes("Murder","SneakMurder"); + DB_LinkedCrimes("Murder","SummonMurder"); + DB_LinkedCrimes("Murder","SummonKilledAnimal"); + + //crime warning to hostile dialogs + DB_CrimeWarningHostileADs("GEB_Warning_Theft","GEB_AD_Help_Thief"); + DB_CrimeWarningHostileADs("GEB_Warning_UseForbiddenItem","GEB_AD_Help_UseForbiddenItem"); + + // Apply item effect to user + DB_ItemStatusAffectCharacterOnUse("BURNING"); + DB_ItemStatusAffectCharacterOnUse("SHOCKED"); + + // Score increase based on invisible/sneaking. At 9 or more, NPC will realise where attack + // comes from and go to location of that attacker. Script will actually increase by one more + // for implementation reasons (taken into account in values of table below) + // sneaking invisible base increase random increase (mod, 1 -> 0) + DB_CRIME_CrimeLocationScoreIncrease(0, 0, 3, 1); + DB_CRIME_CrimeLocationScoreIncrease(1, 0, 2, 1); + DB_CRIME_CrimeLocationScoreIncrease(0, 1, 1, 1); + DB_CRIME_CrimeLocationScoreIncrease(1, 1, 2, 1); + + // score >= threshold -> perform action + DB_CRIME_CrimeLocationScore_GoToAttackerThreshold(9); + DB_CRIME_CrimeLocationScore_StartAttackingThreshold(13); + // health < threshold -> perform action + DB_CRIME_Assault_HealthStartAttackingThreshold(80); + + // Flee crime reactions + DB_CRIME_FleeReaction("CRIME_Flee"); + DB_CRIME_FleeReaction("CRIME_FleeWithAD"); + + } + KB + { + PROC + Proc_GameModeStarted("GameMaster",_) + THEN + GoalCompleted; + + //REGION Register crime wrapper to handle ignoring crimes + QRY + QRY_CRIME_CrimeTriggers_IsCrimeFamilyMember((STRING)_Crime,(STRING)_CrimeOrFamily) + AND + _Crime == _CrimeOrFamily + THEN + DB_NOOP(1); + + QRY + QRY_CRIME_CrimeTriggers_IsCrimeFamilyMember((STRING)_Crime,(STRING)_CrimeOrFamily) + AND + DB_LinkedCrimes(_CrimeOrFamily,_Crime) + THEN + DB_NOOP(1); + + // Built-in: + // * DB_AssaultIgnoreFor(_Witness, _Victim): _Witness ignores all Assault crimes against victim + // * DB_AssaultFamilyIgnoreFor((CHARACTERGUID)_AnyWitness,(CHARACTERGUID)_Victim): _Witness ignores all Assault-like crimes against victim + PROC + PROC_CRIME_CrimeTriggers_GetSilentWitnessesForCrime((INTEGER)_CrimeID,(CHARACTERGUID)_Perpetrator,"Assault",(GUIDSTRING)_Evidence,(CHARACTERGUID)_Victim) + AND + DB_AssaultIgnoreFor((CHARACTERGUID)_AnyWitness,(CHARACTERGUID)_Victim) + THEN + DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_AnyWitness); + + PROC + PROC_CRIME_CrimeTriggers_GetSilentWitnessesForCrime((INTEGER)_CrimeID,(CHARACTERGUID)_Perpetrator,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_Victim) + AND + DB_AssaultFamilyIgnoreFor((CHARACTERGUID)_AnyWitness,(CHARACTERGUID)_Victim) + AND + QRY_CRIME_CrimeTriggers_IsCrimeFamilyMember(_CrimeType,"Assault") + THEN + DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_AnyWitness); + + PROC + ProcCharacterRegisterCrime((CHARACTERGUID)_Char,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_CrimeWitness,(INTEGER)_CrimeID,(CHARACTERGUID)_Victim) + THEN + ProcCharacterRegisterCrimeHandleIgnoresBefore(_Char,_CrimeType,_Evidence,_CrimeWitness,_CrimeID,_Victim); + + PROC + ProcCharacterRegisterCrimeWithPosition((CHARACTERGUID)_Char,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_CrimeWitness,(REAL)_X,(REAL)_Y,(REAL)_Z,(INTEGER)_CrimeID,(CHARACTERGUID)_Victim) + THEN + ProcCharacterRegisterCrimeHandleIgnoresBefore(_Char,_CrimeType,_Evidence,_CrimeWitness,_CrimeID,_Victim); + + PROC + ProcCharacterRegisterCrimeHandleIgnoresBefore((CHARACTERGUID)_Char,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_CrimeWitness,(INTEGER)_CrimeID,(CHARACTERGUID)_Victim) + THEN + PROC_CRIME_CrimeTriggers_GetSilentWitnessesForCrime(_CrimeID,_Char,_CrimeType,_Evidence,_Victim); + + // If this crime is specifically already disabled for the witness, don't do anything special + // except for ignoring the crime + PROC + ProcCharacterRegisterCrimeHandleIgnoresBefore((CHARACTERGUID)_Char,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_CrimeWitness,(INTEGER)_CrimeID,(CHARACTERGUID)_Victim) + AND + DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_AnyWitness) + AND + DB_CharacterCrimeDisabled(_AnyWitness,_CrimeType) + THEN + // Undefine here instead of directly checking in QRY_CRIME_CrimeTriggers_GetSilentWitnessesForCrime(), as + // QRY_CRIME_CrimeTriggers_GetSilentWitnessesForCrime() may be overloaded in user goals and may miss such checks + NOT DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_AnyWitness); + DB_CRIME_CrimeTriggers_SilentWitnessIgnoreOnly(_AnyWitness); + + // If all crimes are disabled for the witness and this one is not enabled, don't do anything special either + // except for ignoring the crime + PROC + ProcCharacterRegisterCrimeHandleIgnoresBefore((CHARACTERGUID)_Char,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_CrimeWitness,(INTEGER)_CrimeID,(CHARACTERGUID)_Victim) + AND + DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_AnyWitness) + AND + DB_CharacterAllCrimesDisabled(_AnyWitness) + AND + NOT DB_CharacterCrimeEnabled(_AnyWitness,_CrimeType) + THEN + NOT DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_AnyWitness); + DB_CRIME_CrimeTriggers_SilentWitnessIgnoreOnly(_AnyWitness); + + // The remaining witnesses that need to temporarily ignore this crime + PROC + ProcCharacterRegisterCrimeHandleIgnoresBefore((CHARACTERGUID)_Char,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_CrimeWitness,(INTEGER)_CrimeID,(CHARACTERGUID)_Victim) + AND + DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_AnyWitness) + THEN + CharacterDisableCrime(_AnyWitness,_CrimeType); + + // Register the crime + PROC + ProcCharacterRegisterCrime((CHARACTERGUID)_Char,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_CrimeWitness,(INTEGER)_CrimeID,(CHARACTERGUID)_Victim) + THEN + CharacterRegisterCrime(_Char,_CrimeType,_Evidence,_CrimeWitness,_CrimeID); + + PROC + ProcCharacterRegisterCrimeWithPosition((CHARACTERGUID)_Char,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_CrimeWitness,(REAL)_X,(REAL)_Y,(REAL)_Z,(INTEGER)_CrimeID,(CHARACTERGUID)_Victim) + THEN + CharacterRegisterCrimeWithPosition(_Char,_CrimeType,_Evidence,_CrimeWitness,_X,_Y,_Z,_CrimeID); + + PROC + ProcCharacterRegisterCrime((CHARACTERGUID)_Char,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_CrimeWitness,(INTEGER)_CrimeID,(CHARACTERGUID)_Victim) + THEN + ProcCharacterRegisterCrimeHandleIgnoresAfter(_CrimeType,_CrimeID); + + PROC + ProcCharacterRegisterCrimeWithPosition((CHARACTERGUID)_Char,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_CrimeWitness,(REAL)_X,(REAL)_Y,(REAL)_Z,(INTEGER)_CrimeID,(CHARACTERGUID)_Victim) + THEN + ProcCharacterRegisterCrimeHandleIgnoresAfter(_CrimeType,_CrimeID); + + // Ignore the crime for the silent witnesses (they will also ignore it in case they were not a witness + // and discover the crime scene later on) and then re-enable the crime for them + PROC + ProcCharacterRegisterCrimeHandleIgnoresAfter((STRING)_CrimeType,(INTEGER)_CrimeID) + AND + DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_AnyWitness) + THEN + CrimeIgnoreCrime(_CrimeID,_AnyWitness); + CharacterEnableCrime(_AnyWitness,_CrimeType); + NOT DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_AnyWitness); + + PROC + ProcCharacterRegisterCrimeHandleIgnoresAfter((STRING)_CrimeType,(INTEGER)_CrimeID) + AND + DB_CRIME_CrimeTriggers_SilentWitnessIgnoreOnly(_AnyWitness) + THEN + NOT DB_CRIME_CrimeTriggers_SilentWitnessIgnoreOnly(_AnyWitness); + CrimeIgnoreCrime(_CrimeID,_AnyWitness); + //END_REGION + + //REGION Stopping Dialog + IF + CharacterOnCrimeSensibleActionNotification(_NPC,_Region,_CrimeID,_PriorityName,_Dialog,_Criminal,_Criminal2,_Criminal3,_Criminal4,_) + THEN + ProcForceStopDialog(_NPC); //This will only stop ADs Code stops interactive ones and SensibleAction will fail if he can't react to it + //END_REGION + + //REGION Behaviour scripts disabling + IF + CrimeDisabled(_Char,"") + THEN + ProcCharacterDisableAllCrimes((CHARACTERGUID)_Char); + + IF + CrimeDisabled(_Char,_Crime) + AND + _Crime != "" + THEN + ProcCharacterDisableCrime(_Char,_Crime); + + IF + CrimeEnabled(_Char,"") + THEN + ProcCharacterEnableAllCrimes((CHARACTERGUID)_Char); + + IF + CrimeEnabled(_Char,_Crime) + AND + _Crime != "" + THEN + ProcCharacterEnableCrime(_Char,_Crime); + //END_REGION + + //REGION Crime Enabling/Disabling + PROC + ProcCharacterDisableAllCrimes((CHARACTERGUID)_Char) + THEN + DB_CharacterAllCrimesDisabled(_Char); + CharacterDisableAllCrimes(_Char); + + PROC + ProcCharacterEnableAllCrimes((CHARACTERGUID)_Char) + THEN + NOT DB_CharacterAllCrimesDisabled(_Char); + CharacterEnableAllCrimes(_Char); + + PROC + ProcCharacterEnableCrime((CHARACTERGUID)_Char,(STRING)_Crime) + THEN + DB_CharacterCrimeEnabled(_Char,_Crime); + CharacterEnableCrime(_Char,_Crime); + + PROC + ProcCharacterDisableCrime((CHARACTERGUID)_Char,(STRING)_Crime) + THEN + DB_CharacterCrimeDisabled(_Char,_Crime); + CharacterDisableCrime(_Char,_Crime); + + IF + DB_CharacterCrimeEnabled(_Char,_Crime) + THEN + NOT DB_CharacterCrimeDisabled(_Char,_Crime); + + IF + DB_CharacterCrimeDisabled(_Char,_Crime) + THEN + NOT DB_CharacterCrimeEnabled(_Char,_Crime); + + //END_REGION + + //REGION Warning + IF + DB_CrimeReaction_DoNotWarn((CHARACTERGUID)_Char) + THEN + DB_CrimeReaction_DoNotWarn2(_Char); + CharacterEnableCrimeWarnings(_Char,0); + + IF + DB_CrimeReaction_DoNotWarn2((CHARACTERGUID)_Char) + AND + NOT DB_CrimeReaction_DoNotWarn(_Char) + THEN + NOT DB_CrimeReaction_DoNotWarn2(_Char); + CharacterEnableCrimeWarnings(_Char,1); + + + // Crime Warning Request events + //--- Generic Warning: + IF + CharacterOnCrimeSensibleActionNotification(_Warner,_CrimeRegion,_CrimeID,"CRIME_OsirisReaction",_WarningDialog,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_) + AND + NOT DB_CrimeReaction_DoNotWarn(_Warner) + AND + CrimeGetType(_CrimeID,_CrimeName) + AND + NOT DB_CrimeReaction_CustomWarning((CHARACTERGUID)_Warner,_CrimeName,(STRING)_) + THEN + ProcCrimeCheckCrimeTypeForFlags(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_CrimeName,_WarningDialog); + ProcCrimeSetupWarning(_CrimeRegion,_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_WarningDialog); + ProcCrimeWarningTryStopDialogs(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_WarningDialog); + ProcCrimeCheckStartedWarning(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_WarningDialog); + + + //--- Custom Warning: + IF + CharacterOnCrimeSensibleActionNotification(_Warner,_CrimeRegion,_CrimeID,"CRIME_OsirisReaction",_WarningDialog,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_) + AND + NOT DB_CrimeReaction_DoNotWarn(_Warner) + //AND + //NOT QryCrimeOnlyHasSummonCriminal(_CrimeID,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + CrimeGetType(_CrimeID,_CrimeName) + AND + DB_CrimeReaction_CustomWarning(_Warner,_CrimeName,_CustomDialog) + THEN + ProcCrimeCheckCrimeTypeForFlags(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_CrimeName,_CustomDialog); + ProcCrimeSetupWarning(_CrimeRegion,_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_CustomDialog); + ProcCrimeWarningTryStopDialogs(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_CustomDialog); + ProcCrimeCheckStartedWarning(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_CustomDialog); + + //--- No Warning + IF + CharacterOnCrimeSensibleActionNotification(_Warner,_CrimeRegion,_CrimeID,"CRIME_OsirisReaction",_Dialog,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_) + AND + DB_CrimeReaction_DoNotWarn(_Warner) + THEN + CrimeConfrontationDone(_CrimeID,_Warner); + + + //--- 1) Prepare a DB and set flag + PROC + ProcCrimeCheckCrimeTypeForFlags((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_CrimeType,(STRING)_WarningDialog) + AND + QryCrimeIsVandalismWithTension(_CrimeType) + THEN + ProcCrimeSetupCountFlag(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,"Vandalise",_WarningDialog); + + PROC + ProcCrimeCheckCrimeTypeForFlags((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_CrimeType,(STRING)_WarningDialog) + AND + NOT QryCrimeIsVandalismWithTension(_CrimeType) + THEN + ProcCrimeSetupCountFlag(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_CrimeType,_WarningDialog); + + QRY + QryCrimeIsVandalismWithTension((STRING)_CrimeType) + AND + _CrimeType == "Vandalise" + THEN + DB_NOOP(1); + + QRY + QryCrimeIsVandalismWithTension((STRING)_CrimeType) + AND + _CrimeType == "ItemDestroy" + THEN + DB_NOOP(1); + + PROC + ProcCrimeSetupCountFlag((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_CrimeType,(STRING)_WarningDialog) + AND + CrimeGetTension(_CrimeID,_Tension) + AND + _Tension > 0 + THEN + DB_Crime_RequestedDialogWithTension(_CrimeType,_WarningDialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeSetupCountFlag((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_CrimeType,(STRING)_WarningDialog) + AND + NOT DB_Crime_WarningCount(_,_CrimeType,_Criminal1,_Warner) // DB doesn't exist yet, meaning the player has never been warned by that NPC with that dialog (i.e. for that crime) + THEN + DB_Crime_WarningCount(1,_CrimeType,_Criminal1,_Warner); + + PROC + ProcCrimeSetupCountFlag((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_CrimeType,(STRING)_WarningDialog) + AND + DB_Crime_RequestedDialogWithTension(_CrimeType,_WarningDialog,_Warner,_,_,_,_) + AND + DB_Crime_WarningCount(_Pos,_CrimeType,_Player,_Warner) + AND + IntegertoString(_Pos,_StrPos) + AND + StringConcatenate("GEB_CrimeWarning_",_StrPos,_Flag) + THEN + ObjectSetFlag(_Player,_Flag); + + IF + DialogEnded(_Dialog,_ID) + AND + DB_TemporaryHostilityAfterDialog(_,_ID) + AND + DB_CrimeWarningHostileADs(_Dialog,_AD) + AND + DB_DialogNPCs(_ID,_NPC,1) + THEN + Proc_StartDialog(1,_AD,_NPC); + + //--- 2) Set variables in the Warner's script + PROC + ProcCrimeSetupWarning((STRING)_CrimeRegion,(INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + THEN + ObjectClearFlag(_Criminal1,"GEB_CrimeHasEvidenceInInventory"); + + PROC + ProcCrimeSetupWarning((STRING)_CrimeRegion,(INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + AND + CrimeGetType(_CrimeID,"Steal") + AND + CrimeFindEvidence(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,1,_,_) + THEN + DB_Interrogation(_Warner,_CrimeID); + ObjectSetFlag(_Criminal1,"GEB_CrimeHasEvidenceInInventory"); + + PROC + ProcCrimeSetupWarning((STRING)_CrimeRegion,(INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + THEN + SetVarInteger(_Warner,"CrimeID",_CrimeID); + SetVarFixedString(_Warner,"RegionID",_CrimeRegion); + DB_Crime_SetupCriminalIndex(_CrimeID,1); + ProcCrimeSetupValidWarningCriminals(_CrimeID,_Warner,_Criminal1); + ProcCrimeSetupValidWarningCriminals(_CrimeID,_Warner,_Criminal2); + ProcCrimeSetupValidWarningCriminals(_CrimeID,_Warner,_Criminal3); + ProcCrimeSetupValidWarningCriminals(_CrimeID,_Warner,_Criminal4); + ProcCrimeSetupNullWarningCriminals(_CrimeID,_Warner); + + PROC + ProcCrimeSetupValidWarningCriminals((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal) + AND + NOT QryCrimeCharacterIsSummonOrNull(_Criminal) + AND + DB_Crime_SetupCriminalIndex(_CrimeID,_Index) + AND + IntegertoString(_Index,_StrIndex) + AND + StringConcatenate("Criminal",_StrIndex,_Param) + AND + IntegerSum(_Index,1,_NewIndex) + THEN + SetVarObject(_Warner,_Param,_Criminal); + NOT DB_Crime_SetupCriminalIndex(_CrimeID,_Index); + DB_Crime_SetupCriminalIndex(_CrimeID,_NewIndex); + + PROC + ProcCrimeSetupNullWarningCriminals((INTEGER)_CrimeID,(CHARACTERGUID)_Warner) + AND + DB_Crime_SetupCriminalIndex(_CrimeID,_Index) + AND + _Index < 5 //goes from 1 to 4 + AND + IntegertoString(_Index,_StrIndex) + AND + StringConcatenate("Criminal",_StrIndex,_Param) + AND + IntegerSum(_Index,1,_NewIndex) + THEN + ClearVarObject(_Warner,_Param); + NOT DB_Crime_SetupCriminalIndex(_CrimeID,_Index); + DB_Crime_SetupCriminalIndex(_CrimeID,_NewIndex); + ProcCrimeSetupNullWarningCriminals(_CrimeID,_Warner); + + PROC + ProcCrimeSetupWarning((STRING)_CrimeRegion,(INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + AND + DB_Crime_SetupCriminalIndex(_CrimeID,_Index) + THEN + NOT DB_Crime_SetupCriminalIndex(_CrimeID,_Index); + + PROC + ProcCrimeSetupWarning((STRING)_CrimeRegion,(INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + AND + GetPosition(_Warner,_x,_y,_z) + THEN + SetVarFloat3(_Warner,"NPCOrgPos",_x,_y,_z); + + PROC + ProcCrimeSetupWarning((STRING)_CrimeRegion,(INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + AND + DB_EvidenceCheckInWarning(_WarningDialog) //Sets up Interrogation DB for evidence check in warning Dialog + THEN + DB_Crime_Interrogation(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_WarningDialog); + + + //--- 3) Try to stop the warner's dialog + PROC + ProcCrimeWarningTryStopDialogs((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + AND + DB_CrimeWarningIsAD(_WarningDialog) + THEN + ProcCrimeInterruptStoryDialogs(_CrimeID,_WarningDialog,0,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeWarningTryStopDialogs((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + AND + NOT DB_CrimeWarningIsAD(_WarningDialog) + THEN + ProcCrimeInterruptStoryDialogs(_CrimeID,_WarningDialog,1,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + + //--- 4) Verify if the crime dialog succeeded to start and clean up + PROC + ProcCrimeCheckStartedWarning((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + AND + DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_WarningDialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + DB_Crime_RequestedDialogWithTension(_CrimeType,_WarningDialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + DB_Crime_WarningCount(_Pos,_Dialog,_Player,_Warner) + AND + IntegertoString(_Pos,_StrPos) + AND + StringConcatenate("GEB_CrimeWarning_",_StrPos,_Flag) + THEN + NOT DB_Crime_RequestedDialogWithTension(_CrimeType,_WarningDialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + ObjectClearFlag(_Player,_Flag,0); + + PROC + ProcCrimeCheckStartedWarning((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + AND + DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_WarningDialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + THEN + ProcCrimeFailedToInterruptStoryDialog(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_WarningDialog); + NOT DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_WarningDialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + CrimeConfrontationDone(_CrimeID,_Warner); + + PROC + ProcCrimeCheckStartedWarning((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + AND + DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_WarningDialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + CrimeIsContinuous(_CrimeID,1) + THEN + ProcCrimeFailedToInterruptStoryDialog(_CrimeID,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_WarningDialog); + NOT DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_WarningDialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + PROC // Useful for custom scripting + ProcCrimeFailedToInterruptStoryDialog((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + THEN + DB_NOOP(1); + + PROC + ProcCrimeCheckStartedWarning((INTEGER)_CrimeID,(CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog) + AND + DB_Crime_FailedToInterruptStoryDialogs(_AnyCrimeID,_AnyWarningDialog,_AnyWarner,_AnyCriminal1,_AnyCriminal2,_AnyCriminal3,_AnyCriminal4) // Clean up anything that could have failed previously + THEN + NOT DB_Crime_FailedToInterruptStoryDialogs(_AnyCrimeID,_AnyWarningDialog,_AnyWarner,_AnyCriminal1,_AnyCriminal2,_AnyCriminal3,_AnyCriminal4); + + + //--- Count the warnings done: + IF + DialogEnded(_Dialog,_Inst) + AND + DB_Crime_RequestedDialogWithTension(_CrimeType,_Dialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + DB_DialogNPCs(_Inst,_Warner,_) + AND + DB_DialogPlayers(_Inst,_Player,_) + AND + DB_Crime_WarningCount(_Pos,_CrimeType,(CHARACTERGUID)_Player,_Warner) + AND + IntegertoString(_Pos,_StrPos) + AND + StringConcatenate("GEB_CrimeWarning_",_StrPos,_Flag) + AND + ObjectGetFlag(_Player,_Flag,1) + AND + IntegerSum(_Pos,1,_NewPos) + THEN + NOT DB_Crime_RequestedDialogWithTension(_CrimeType,_Dialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + ObjectClearFlag(_Player,_Flag,0); + NOT DB_Crime_WarningCount(_Pos,_CrimeType,_Player,_Warner); + DB_Crime_WarningCount(_NewPos,_CrimeType,_Player,_Warner); + + IF + DB_Crime_WarningCount(_NewPos,_CrimeType,_Player,_Warner) + AND + _NewPos > 3 + THEN + NOT DB_Crime_WarningCount(_NewPos,_CrimeType,_Player,_Warner); + DB_Crime_WarningCount(3,_CrimeType,_Player,_Warner); + + IF + DialogEnded(_Dialog,_Inst) + AND + DB_CrimeWarner(_CrimeID,_Warner,_Dialog) + AND + DB_DialogNPCs(_Inst,_Warner,_) + THEN + CrimeConfrontationDone(_CrimeID,_Warner); + NOT DB_CrimeWarner(_CrimeID,_Warner,_Dialog); + + IF + AutomatedDialogEnded(_Dialog,_Inst) + AND + DB_Crime_RequestedDialogWithTension(_CrimeType,_Dialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + DB_DialogNPCs(_Inst,_Warner,_) + AND + DB_Crime_WarningAD_Target(_CrimeType,_Warner,_Criminal1) + AND + DB_Crime_WarningCount(_Pos,_CrimeType,(CHARACTERGUID)_Player,_Warner) + AND + IntegertoString(_Pos,_StrPos) + AND + StringConcatenate("GEB_CrimeWarning_",_StrPos,_Flag) + AND + ObjectGetFlag(_Player,_Flag,1) + AND + IntegerSum(_Pos,1,_NewPos) + THEN + NOT DB_Crime_RequestedDialogWithTension(_CrimeType,_Dialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + ObjectClearFlag(_Player,_Flag,0); + NOT DB_Crime_WarningCount(_Pos,_CrimeType,_Player,_Warner); + DB_Crime_WarningCount(_NewPos,_CrimeType,_Player,_Warner); + + IF + AutomatedDialogEnded(_Dialog,_Inst) + AND + DB_DialogNPCs(_Inst,_Warner,_) + AND + DB_Crime_WarningAD_Target(_CrimeType,(CHARACTERGUID)_Warner,(CHARACTERGUID)_TargetPlayer) + THEN + NOT DB_Crime_WarningAD_Target(_CrimeType,_Warner,_TargetPlayer); + + PROC + ProcHandleCrimeDialog((CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog,0,(INTEGER)_MarkForInteractive) + THEN + DB_CrimeDialogStartFailed(_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog); + + IF + OnCrimeResolved(_CrimeID,_Victim,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + DB_CrimeDialogStartFailed(_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog) + AND + DB_Crime_RequestedDialogWithTension(_CrimeType,_Dialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + DB_Crime_WarningCount(_Pos,_CrimeType,(CHARACTERGUID)_Player,_Warner) + AND + IntegertoString(_Pos,_StrPos) + AND + StringConcatenate("GEB_CrimeWarning_",_StrPos,_Flag) + AND + ObjectGetFlag(_Player,_Flag,1) + AND + IntegerSum(_Pos,1,_NewPos) + THEN + NOT DB_CrimeDialogStartFailed(_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog); + NOT DB_Crime_RequestedDialogWithTension(_CrimeType,_Dialog,_Warner,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + ObjectClearFlag(_Player,_Flag,0); + NOT DB_Crime_WarningAD_Target(_CrimeType,_Warner,_Player); + NOT DB_Crime_WarningCount(_Pos,_CrimeType,_Player,_Warner); + DB_Crime_WarningCount(_NewPos,_CrimeType,_Player,_Warner); + + + //REGION Prepare the characters for the dialog + PROC + ProcHandleCrimeDialog((CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog,1,(INTEGER)_MarkForInteractive) + AND + GetPosition(_Warner,_x,_y,_z) + THEN + SetVarFloat3(_Warner,"NPCOrgPos",_x,_y,_z); + + PROC + ProcHandleCrimeDialog((CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog,1,1) + THEN + CharacterLookAt(_Warner,_Criminal1,0); + CharacterLookAt(_Criminal1,_Warner,0); + CharacterMakeStoryNpc(_Warner,1); + CharacterMakeStoryNpc(_Criminal1,1); + CharacterMakeStoryNpc(_Criminal2,1); + CharacterMakeStoryNpc(_Criminal3,1); + CharacterMakeStoryNpc(_Criminal4,1); + + PROC + ProcHandleCrimeDialog((CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog,1,0) + THEN + CharacterLookAt(_Warner,_Criminal1,0); + + PROC + ProcHandleCrimeDialog((CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_WarningDialog,1,_) + AND + DB_CRIME_ForbiddenStatus(_Status) + AND + HasActiveStatus(_Warner,_Status,1) + THEN + RemoveStatus(_Warner,_Status); + + IF + CharacterLeftParty(_Summon) + AND + ObjectExists(_Summon,1) + AND + IsTagged(_Summon,"SUMMON",1) + AND + DB_Crime_WarningCount(_Pos,_CrimeType,_Summon,_Warner) + THEN + NOT DB_Crime_WarningCount(_Pos,_CrimeType,_Summon,_Warner); + + //END_REGION + + //REGION Check Prison Cell in Warning + + IF + CharacterOnCrimeSensibleActionNotification(_Warner,_CrimeRegion,_CrimeID,"CRIME_OsirisReaction",_Dialog,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_) + THEN + ObjectClearFlag(_Warner,"GEB_Arrest_HavePrison",0); + + IF + CharacterOnCrimeSensibleActionNotification(_Warner,_CrimeRegion,_CrimeID,"CRIME_OsirisReaction",_Dialog,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_) + AND + DB_RegionPrison(_CrimeRegion,_) + THEN + ObjectSetFlag(_Warner,"GEB_Arrest_HavePrison"); + + //END_REGION + //END_REGION + + //REGION Summon check + + //--- Only summon (or null) in criminals + QRY + QryCrimeOnlyHasSummonCriminal((CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + QryCrimeCharacterIsSummonOrNull(_Criminal1) + AND + QryCrimeCharacterIsSummonOrNull(_Criminal2) + AND + QryCrimeCharacterIsSummonOrNull(_Criminal3) + AND + QryCrimeCharacterIsSummonOrNull(_Criminal4) + THEN + DB_NOOP(1); + + QRY + QryCrimeCharacterIsSummonOrNull((CHARACTERGUID)_Char) + AND + QRY_CharacterIsNull(_Char) + THEN + DB_NOOP(1); + + QRY + QryCrimeCharacterIsSummonOrNull((CHARACTERGUID)_Char) + AND + NOT QRY_CharacterIsNull(_Char) + AND + IsTagged(_Char,"SUMMON",1) + THEN + DB_NOOP(1); + + + QRY + QryCrimeAssailantIsNotSummon((CHARACTERGUID)_Char,(CHARACTERGUID)_Summon) + AND + _Char == _Summon + THEN + DB_NOOP(1); + + QRY + QryCrimeAssailantIsNotSummon((CHARACTERGUID)_Char,(CHARACTERGUID)_Summon) + AND + QRY_CharacterIsNull(_Summon) + THEN + DB_NOOP(1); + + + //--- Continuous summon crime + IF + CharacterJoinedParty(_Char) + AND + IsTagged(_Char,"SUMMON",1) + THEN + CharacterRegisterCrime(_Char,"ActiveSummon",NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,0); + + IF + CharacterLeftParty(_Char) + AND + IsTagged(_Char,"SUMMON",1) + THEN + CharacterStopCrime(_Char,"ActiveSummon",NULL_00000000-0000-0000-0000-000000000000); + + //END_REGION + + //REGION Investigation + // Override crime scene location (needs to be exact to ensure that e.g. in case of assault, + // we don't have a crime scene too far for the victim to see or hear) with a separate investigation + // location if appropriate + IF + StoryEvent((CHARACTERGUID)_Investigator,"CRIME_SetCrimeInvestigationPos") + AND + GetVarInteger(_Investigator,"CrimeID",_CrimeID) + AND + DB_CRIME_CrimeInvestigationPos(_CrimeID,_X,_Y,_Z) + THEN + // In case it's an alternate position, run rather than walk, because it means + // that we probably cannot find anything in the default location + SetVarInteger(_Investigator,"bool_RunToInvestigationScene",1); + SetVarFloat3(_Investigator,"CrimePos",_X,_Y,_Z); + + IF + StoryEvent((CHARACTERGUID)_Investigator,"CRIME_SetCrimeInvestigationPos") + THEN + CharacterSetReactionPriority(_Investigator,"WalkToCrimeScene",30000); + //END_REGION + + //REGION Interrogation + + IF + CrimeInterrogationRequest(_RegionID,_ID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog) + THEN + ObjectClearFlag(_Interrogator,"GEB_Arrest_HavePrison",0); + + IF + CrimeInterrogationRequest(_RegionID,_ID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog) + AND + DB_RegionPrison((STRING)_RegionID,(TRIGGERGUID)_) + THEN + ObjectSetFlag(_Interrogator,"GEB_Arrest_HavePrison"); + + PROC + ProcCrimeCheckInterrogationDialog((STRING)_RegionID,(INTEGER)_ID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + AND + IsTagged(_Interrogator,"NOT_MESSING_AROUND",0) + AND + IsTagged(_Interrogator,"ANIMAL",0) + AND + IsTagged(_Interrogator,"KID",0) + THEN + DB_Crime_InterrogationStarted(_ID,_Interrogator); + ProcStartInterrogationDialog(_ID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog); + + PROC + ProcCrimeCheckInterrogationDialog((STRING)_RegionID,(INTEGER)_ID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + AND + NOT DB_Crime_InterrogationStarted(_ID,_Interrogator) + AND + IsTagged(_Interrogator,"NOT_MESSING_AROUND",1) + THEN + DB_Crime_InterrogationStarted(_ID,_Interrogator); + //TODO: should not just interrupt the dialog here + DialogRequestStop(_Criminal1); + ProcMakeNPCHostile(_Criminal1,_Interrogator); + CrimeInterrogationDone(_ID,_Interrogator,1,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + ProcTryStartAttackAD(_Interrogator); + + PROC + ProcCrimeCheckInterrogationDialog((STRING)_RegionID,(INTEGER)_ID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + AND + NOT DB_Crime_InterrogationStarted(_ID,_Interrogator) + AND + IsTagged(_Interrogator,"ANIMAL",1) + THEN + DB_Crime_InterrogationStarted(_ID,_Interrogator); + CrimeInterrogationDone(_ID,_Interrogator,1,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeCheckInterrogationDialog((STRING)_RegionID,(INTEGER)_ID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + AND + NOT DB_Crime_InterrogationStarted(_ID,_Interrogator) + AND + IsTagged(_Interrogator,"AGGRESSIVEANIMAL",1) + THEN + DB_Crime_InterrogationStarted(_ID,_Interrogator); + Proc_StartDialog(1,"GEB_AD_Noticed_AnimalAttackedAnimal",_Interrogator); + ProcMakeNPCHostile(_Interrogator,_Criminal1); + ProcMakeNPCHostile(_Interrogator,_Criminal2); + ProcMakeNPCHostile(_Interrogator,_Criminal3); + ProcMakeNPCHostile(_Interrogator,_Criminal4); + + PROC + ProcCrimeCheckInterrogationDialog((STRING)_RegionID,(INTEGER)_ID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + AND + NOT DB_Crime_InterrogationStarted(_ID,_Interrogator) + AND + IsTagged(_Interrogator,"KID",1) + THEN + DB_Crime_InterrogationStarted(_ID,_Interrogator); + CrimeInterrogationDone(_ID,_Interrogator,1,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeCheckInterrogationDialog((STRING)_RegionID,(INTEGER)_ID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + THEN + NOT DB_Crime_InterrogationStarted(_ID,_Interrogator); + + + //--- Interrogation requested: + IF + CrimeInterrogationRequest(_RegionID,_ID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog) + THEN + DB_InterrogationRequested(_RegionID,_ID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog); + CharacterDisableAllCrimes(_Interrogator); + SetHasDialog(_Interrogator,0); //TODO: this is not great, we assume these guys have dialogs + CharacterMoveToAndTalk(_Interrogator,_Criminal1,"",0,"GEB_InterrogationMove",1,6.0); + + IF + CharacterMoveToAndTalkRequestDialog(_Arrester,(CHARACTERGUID)_Criminal,_,_,"GEB_InterrogationMove") + AND + DB_InterrogationRequested(_RegionID,_ID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4,_Dialog) + THEN + ProcCrimeCheckInterrogationDialog(_RegionID,_ID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4,_Dialog); + + IF + CharacterMoveToAndTalkFailed(_Arrester,_,"GEB_InterrogationMove") + AND + DB_InterrogationRequested(_RegionID,_ID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4,_Dialog) + THEN + CrimeInterrogationDone(_ID,_Arrester,0,_Criminal,_Criminal2,_Criminal3,_Criminal4); + ProcCleanUpInterrogation(_Arrester); + NOT DB_IgnoreInterrogation(_Arrester,NULL_00000000-0000-0000-0000-000000000000); + ProcObjectTimer(_Arrester,"GEB_RestoreInterrogation",4500); + CrimeEnableInterrogation(_Arrester,0); + //allow others to interrogate them + CrimeResetInterrogationForCriminals(_ID,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcObjectTimerFinished((CHARACTERGUID)_Arrester,"GEB_RestoreInterrogation") + AND + NOT DB_CrimeReaction_DoNotInterrogate(_Arrester) + THEN + CrimeEnableInterrogation(_Arrester,1); + + PROC + ProcCleanUpInterrogation((CHARACTERGUID)_Arrester) + AND + DB_InterrogationRequested(_RegionID,_ID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4,_Dialog) + THEN + ProcRestoreGenericBehaviour(_Arrester); + SetHasDialog(_Arrester,1); + NOT DB_InterrogationRequested(_RegionID,_ID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4,_Dialog); + + IF + CharacterMoveToAndTalkRequestDialog(_Arrester,(CHARACTERGUID)_Criminal,_,_,"GEB_InterrogationMove") + AND + NOT DB_InterrogationRequested(_,_,_Arrester,_Criminal,_,_,_,_) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Arrester,_Criminal,"GEB_InterrogationMove"); + + IF + DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_ArrestDialog,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4) + AND + DB_InterrogationRequested(_RegionID,_CrimeID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4,_ArrestDialog) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Arrester,_Criminal,"GEB_InterrogationMove"); + + IF + DB_Crime_InterrogationStarted(_CrimeID,_Arrester) + AND + DB_InterrogationRequested(_RegionID,_CrimeID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4,_ArrestDialog) + THEN + ProcCleanUpInterrogation(_Arrester); + + IF + OnCrimeResolved(_CrimeID,_,_,_,_,_) + AND + DB_InterrogationRequested(_,_CrimeID,_Arrester,_,_,_,_,_) + THEN + ProcCleanUpInterrogation(_Arrester); + + //--- Start dialog: + PROC + ProcStartInterrogationDialog((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + AND + _Dialog == "" + THEN + ProcDoStartInterrogationDialog(_CrimeID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,"GEB_Interrogation"); + + PROC + ProcStartInterrogationDialog((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + AND + _Dialog != "" + THEN + ProcDoStartInterrogationDialog(_CrimeID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog); + + PROC + ProcDoStartInterrogationDialog((INTEGER)_,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + AND + DB_Interrogation(_Interrogator,_CrimeID) + THEN + NOT DB_Interrogation(_Interrogator,_CrimeID); // This Database is set on CRIME_Allow_Search + + PROC + ProcDoStartInterrogationDialog((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + THEN + ProcCrimeInterruptStoryDialogs(_CrimeID,_Dialog,1,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + ProcCrimeCheckInterrogationDialogSucceeded(_CrimeID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog); + + PROC + ProcCrimeCheckInterrogationDialogSucceeded((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + AND + NOT DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_Dialog,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + THEN + DB_Crime_Interrogation(_CrimeID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog); + DB_Interrogation(_Interrogator,_CrimeID); + + PROC + ProcCrimeCheckInterrogationDialogSucceeded((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_Dialog) + AND + DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_Dialog,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + THEN + CrimeInterrogationDone(_CrimeID,_Interrogator,1,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + IF + ObjectFlagSet("CRIME_Allow_Search",(CHARACTERGUID)_Interrogator,_ID) + THEN + ObjectClearFlag(_Interrogator,"CRIME_Allow_Search",_ID); + ObjectClearFlag(_Interrogator,"CRIME_EvidenceFound",_ID); + ObjectClearFlag(_Interrogator,"CRIME_GuiltFound",_ID); + ObjectClearFlag(_Interrogator,"CRIME_FoundEvidenceCurrentCrime",_ID); + ObjectClearFlag(_Interrogator,"CRIME_FoundGuiltyPlayer",_ID); + + IF + ObjectFlagSet("CRIME_Allow_Search",(CHARACTERGUID)_Interrogator,_ID) + AND + DB_Crime_Interrogation(_CrimeID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_) + AND + CrimeFindEvidence(_CrimeID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_FoundEvidenceCurrentCrime,_FoundEvidence,_FoundGuilty) + AND + QRY_GetCriminalGuilty(_CrimeID,_Interrogator,_FoundEvidenceCurrentCrime,_FoundEvidence,_FoundGuilty) + THEN + DB_Interrogation(_Interrogator,_CrimeID); + + IF + ObjectFlagSet("CRIME_Resist_Search",(CHARACTERGUID)_Character,_ID) + THEN + ObjectClearFlag(_Character,"CRIME_Resist_Search",_ID); + DB_Crime_CombatAfterDialog(_ID); + + QRY + QRY_GetCriminalGuilty((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(INTEGER)_FoundEvidenceCurrentCrime,(INTEGER)_FoundEvidence,(INTEGER)_FoundGuilty) + AND + _FoundEvidence == 1 + THEN + ObjectSetFlag(_Interrogator,"CRIME_EvidenceFound",0); + + QRY + QRY_GetCriminalGuilty((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(INTEGER)_FoundEvidenceCurrentCrime,(INTEGER)_FoundEvidence,(INTEGER)_FoundGuilty) + AND + _FoundGuilty == 1 + THEN + ObjectSetFlag(_Interrogator,"CRIME_GuiltFound",0); + + QRY + QRY_GetCriminalGuilty((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(INTEGER)_FoundEvidenceCurrentCrime,(INTEGER)_FoundEvidence,(INTEGER)_FoundGuilty) + AND + _FoundEvidenceCurrentCrime == 1 + THEN + ObjectSetFlag(_Interrogator,"CRIME_FoundEvidenceCurrentCrime",0); + + //Resolve Crime + IF + ObjectFlagSet("CRIME_FoundGuiltyPlayer",(CHARACTERGUID)_Interrogator,_ID) + AND + DB_Interrogation(_Interrogator,_CrimeID) + THEN + DB_EvidenceFound(_CrimeID,_Interrogator); + //DebugText(_Interrogator,"Evidence Found"); + + //Give Evidance Back to investigator + IF + ObjectFlagSet("CRIME_ReturnGoodsToOnwer",(CHARACTERGUID)_Interrogator,_ID) + AND + DB_Interrogation(_Interrogator,_CrimeID) + THEN + ObjectClearFlag(_Interrogator,"CRIME_ReturnGoodsToOnwer",_ID); + CrimeTransferEvidenceTo(_CrimeID,_Interrogator); + + IF + ObjectFlagSet("CRIME_CallGuardsFromDialog",(CHARACTERGUID)_Interrogator,_ID) // When A Civilian finds a Thief in Interrogation + AND + DB_DialogPlayers(_ID,_Criminal,1) + THEN + ObjectClearFlag(_Interrogator,"CRIME_CallGuardsFromDialog"); + DB_Crime_CallingGuards(_Interrogator,_Criminal,_ID); + + IF + DialogEnded(_Dialog,_ID) + AND + DB_DialogNPCs(_ID,_Interrogator,1) + AND + DB_Crime_Interrogation(_CrimeID,(CHARACTERGUID)_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog) + AND + NOT DB_Crime_CallingGuards(_Interrogator,_,_ID) + THEN + ProcCheckInterrogationDone(_Interrogator,_Dialog); + + PROC + ProcCheckInterrogationDone((CHARACTERGUID)_Interrogator,(STRING)_Dialog) + AND + NOT DB_EvidenceCheckInWarning(_Dialog) + AND + DB_Crime_Interrogation(_CrimeID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog) + THEN + NOT DB_Crime_Interrogation(_CrimeID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog); + ProcStopInterrogation(_CrimeID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + + IF + DialogEnded(_Dialog,_ID) + AND + DB_Crime_CallingGuards(_Interrogator,_Criminal,_ID) + AND + DB_Interrogation(_Interrogator,_CrimeID) + THEN + SetVarObject(_Interrogator,"Criminal1",(CHARACTERGUID)_Criminal); // TODO REMOVE THIS HACK! + SetVarString(_Interrogator,"ArrestDialog","GEB_Arrest"); + SetVarInteger(_Interrogator,"CrimeID",_CrimeID); + SetStoryEvent(_Interrogator,"CRIME_CallGuardsFromDialog"); + NOT DB_Crime_CallingGuards(_Interrogator,_Criminal,_ID); + + IF + ObjectFlagSet("CRIME_FleeHelpFromDialog",(CHARACTERGUID)_Interrogator,_ID) // When A Kid finds a Criminal in Interrogation + AND + DB_DialogPlayers(_ID,_Criminal,1) + THEN + DB_Crime_FleeCallforHelp(_Interrogator,_Criminal,_ID); + + IF + DialogEnded(_Dialog,_ID) + AND + DB_Crime_FleeCallforHelp(_Interrogator,_Criminal,_ID) + AND + DB_Interrogation(_Interrogator,_CrimeID) + THEN + SetVarObject(_Interrogator,"Criminal1",(CHARACTERGUID)_Criminal); // TODO REMOVE THIS HACK! + SetVarString(_Interrogator,"ArrestDialog","GEB_Arrest"); + SetVarInteger(_Interrogator,"CrimeID",_CrimeID); + SetStoryEvent(_Interrogator,"CRIME_FleeHelpFromDialog"); + //CrimeInterrogationDone(_CrimeID,_Interrogator,1); + NOT DB_Crime_FleeCallforHelp(_Interrogator,_Criminal,_ID); + + IF + DialogEnded(_Dialog,_ID) + AND + DB_DialogPlayers(_ID,_Player,1) + AND + ObjectGetFlag(_Player,"CRIME_PersuasionFailed",1) + THEN + ObjectClearFlag(_Player,"CRIME_PersuasionFailed",0); + + // Stop Investigation when join combat + + + //REGION Dialog Ended + IF + DialogEnded(_Dialog,_ID) + AND + DB_Crime_CombatAfterDialog(_ID) + AND + DB_DialogNPCs(_ID,_Interrogator,1) + AND + DB_DialogPlayers(_ID,_Player,_) + THEN + ProcMakeNPCHostile((CHARACTERGUID)_Player,(CHARACTERGUID)_Interrogator); + NOT DB_Crime_CombatAfterDialog(_ID); + + IF + DialogEnded(_Dialog,_ID) + AND + DB_DialogNPCs(_ID,_Interrogator,1) + AND + DB_Crime_Interrogation(_CrimeID,(CHARACTERGUID)_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog) + THEN + NOT DB_Crime_Interrogation(_CrimeID,(CHARACTERGUID)_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog); + + PROC + ProcStopInterrogation((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + DB_EvidenceFound(_CrimeID,_Interrogator) + THEN + CrimeInterrogationDone(_CrimeID,_Interrogator,1,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcStopInterrogation((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + NOT DB_EvidenceFound(_CrimeID,_Interrogator) + THEN + CrimeInterrogationDone(_CrimeID,_Interrogator,0,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcStopInterrogation((INTEGER)_CrimeID,(CHARACTERGUID)_Interrogator,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + THEN + NOT DB_EvidenceFound(_CrimeID,_Interrogator); + //END_REGION + + //REGION Saw Criminal In Combat While Invesigating + IF + OnCrimeSawCriminalInCombat(_CrimeID,_Witness,_Criminal) + AND + IsTagged(_Witness,"CIVILIAN",0) + AND + IsTagged(_Witness,"ANIMAL",0) //Animals should not investigate should be disabled in excel + THEN + ProcMakeNPCHostile(_Witness,_Criminal); + //END_REGION + //END_REGION + + //REGION Trespassing + + //--- Registering DB + IF + DB_TrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger) + THEN + DB_TrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,"Trespassing",(CHARACTERGUID)NULL_00000000-0000-0000-0000-000000000000); + + IF + DB_TrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(STRING)_CrimeName) + THEN + DB_TrespassingCrimes((STRING)_CrimeName); + DB_TrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(STRING)_CrimeName,(CHARACTERGUID)NULL_00000000-0000-0000-0000-000000000000); + + IF + DB_TrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(STRING)_CrimeName,(CHARACTERGUID)_Victim) + THEN + DB_TrespassingCrimes((STRING)_CrimeName); + DB_TrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(STRING)_CrimeName,(CHARACTERGUID)_Victim); + + IF + DB_TrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_,_,_) + THEN + ProcTriggerRegisterForPlayers(_Trigger); + + + //--- Removing: + PROC + ProcRemoveDBTrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger) + THEN + ProcRemoveDBTrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(CHARACTERGUID)NULL_00000000-0000-0000-0000-000000000000); + + PROC + ProcRemoveDBTrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(CHARACTERGUID)_Victim) + AND + DB_TrespassTrigger(_Trigger,_OutTrigger,_CrimeName,_Victim) + AND + DB_IsPlayer(_Player) + THEN + CharacterStopCrime(_Player, _CrimeName, _Trigger); + + PROC + ProcRemoveDBTrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(CHARACTERGUID)_Victim) + AND + DB_TrespassTrigger(_Trigger,_OutTrigger,_CrimeName) + AND + DB_IsPlayer(_Player) + THEN + CharacterStopCrime(_Player, _CrimeName, _Trigger); + + PROC + ProcRemoveDBTrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(CHARACTERGUID)_Victim) + AND + DB_TrespassTrigger(_Trigger,_OutTrigger) + AND + DB_IsPlayer(_Player) + THEN + CharacterStopCrime(_Player, "Trespassing", _Trigger); + + PROC + ProcRemoveDBTrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(CHARACTERGUID)_Victim) + AND + DB_TrespassTrigger(_Trigger,_OutTrigger,_CrimeName,_Victim) + THEN + NOT DB_TrespassTrigger(_Trigger,_OutTrigger,_CrimeName,_Victim); + + PROC + ProcRemoveDBTrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(CHARACTERGUID)_Victim) + AND + DB_TrespassTrigger(_Trigger,_OutTrigger) + THEN + NOT DB_TrespassTrigger(_Trigger,_OutTrigger); + + PROC + ProcRemoveDBTrespassTrigger((TRIGGERGUID)_Trigger,(TRIGGERGUID)_OutTrigger,(CHARACTERGUID)_Victim) + AND + DB_TrespassTrigger(_Trigger,_OutTrigger,_CrimeName) + THEN + NOT DB_TrespassTrigger(_Trigger,_OutTrigger,_CrimeName); + + //--- Register/stop crime + IF + CharacterEnteredTrigger(_Player,_Trigger) + AND + DB_TrespassTrigger(_Trigger,_,_CrimeName,_Victim) + AND + DB_IsPlayer(_Player) + THEN + DB_PlayerTrespassing(_Player,_Trigger); + CharacterRegisterCrime(_Player,_CrimeName,_Trigger,_Victim,0); + + IF + CharacterLeftTrigger(_Player,_Trigger) + AND + DB_TrespassTrigger(_Trigger,_,_CrimeName,_Victim) + THEN + CharacterStopCrime(_Player,_CrimeName,_Trigger); + NOT DB_PlayerTrespassing(_Player,_Trigger); + + IF + ObjectFlagSet("TeleportOutOfTrespass",_Player,_Inst) + THEN + DB_CrimeTeleportOutOfTrespass(_Player,_Inst); + + IF + DialogEnded(_,_ID) + AND + DB_DialogPlayers(_ID,_FirstPlayer,1) + AND + DB_PlayerTrespassing((CHARACTERGUID)_FirstPlayer,_Trigger) + AND + DB_CrimeTeleportOutOfTrespass(_FirstPlayer,_ID) + AND + DB_TrespassTrigger(_Trigger,_Outside,_,_) + AND + DB_DialogPlayers(_ID,_Player,_) + THEN + TeleportTo(_Player,_Outside,"",1); + NOT DB_PlayerTrespassing(_FirstPlayer,_Trigger); + NOT DB_CrimeTeleportOutOfTrespass(_Player,_ID); + ObjectClearFlag(_Player,"TeleportOutOfTrespass",0); + CharacterFlushQueue((CHARACTERGUID)_Player); + FireOsirisEvents(); + + IF + DialogEnded(_,_ID) + AND + DB_CrimeTeleportOutOfTrespass(_Player,_ID) + THEN + NOT DB_CrimeTeleportOutOfTrespass(_Player,_ID); + ObjectClearFlag(_Player,"TeleportOutOfTrespass",0); + + ////////////////////////////// + // Unavailable Fallback lead + IF + CharacterSelectedAsBestUnavailableFallbackLead(_NPC,_RegionID,_CrimeID,_BusyCrimeID,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + NOT QryCrimeOnlyHasSummonCriminal(_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + CrimeGetType(_CrimeID,_CrimeName) + AND + DB_TrespassingCrimes(_CrimeName) + THEN + ProcCrimeTrespassingCheckDetection(_CrimeID,_NPC,_Criminal1); + ProcCrimeTrespassingCheckDetection(_CrimeID,_NPC,_Criminal2); + ProcCrimeTrespassingCheckDetection(_CrimeID,_NPC,_Criminal3); + ProcCrimeTrespassingCheckDetection(_CrimeID,_NPC,_Criminal4); + ProcCrimeTrespassingCheckValidLead(_CrimeID,_NPC); + ProcCrimeTrespassingStopNPCsDialogAndMakeHostileTo(_CrimeID,_BusyCrimeID,_NPC); + + PROC + ProcCrimeTrespassingCheckDetection((INTEGER)_CrimeID,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Player) + AND + _Player != NULL_00000000-0000-0000-0000-000000000000 + AND + GetDistanceTo(_NPC,_Player,_Dist) + AND + CrimeGetDetectionRange(_CrimeID,_Range) + AND + _Dist <= _Range + THEN + DB_Crime_TrespassUnavailableLeadDetected((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player); + + PROC + ProcCrimeTrespassingCheckValidLead((INTEGER)_CrimeID,(CHARACTERGUID)_NPC) + AND + QryCrimeTrespassUnavailableLeadDetected(_NPC) + THEN + ProcCrimeTrespassingBlockHostileFallback(_CrimeID,_NPC); + + QRY + QryCrimeTrespassUnavailableLeadDetected((CHARACTERGUID)_NPC) + AND + DB_Crime_TrespassUnavailableLeadDetected((CHARACTERGUID)_NPC,_) + THEN + DB_NOOP(1); + + PROC + ProcCrimeTrespassingBlockHostileFallback((INTEGER)_CrimeID,(CHARACTERGUID)_NPC) + THEN + DB_NOOP(1); + + PROC + ProcCrimeTrespassingStopNPCsDialogAndMakeHostileTo((INTEGER)_CrimeID,(INTEGER)_BusyCrimeID,(CHARACTERGUID)_NPC) + AND + DB_Crime_TrespassUnavailableLeadDetected(_NPC,_Player) + AND + NOT DB_CrimeTrespassingBlockHostile(_CrimeID,_NPC) + THEN + ProcTryMergingCrimes(_CrimeID,_BusyCrimeID,_NPC,_Player); + + PROC + ProcTryMergingCrimes((INTEGER)_NewCrime,(INTEGER)_OldCrime,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Player) + THEN + NOT DB_CanMergeCrimes(1); + + PROC + ProcTryMergingCrimes((INTEGER)_NewCrime,(INTEGER)_OldCrime,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Player) + AND + QryCanMergeCrimes(_NewCrime,_OldCrime,_Player) + THEN + DB_CanMergeCrimes(1); + + IF + OnCriminalMergedWithCrime(_Crime,_Criminal) + AND + CrimeGetLeadInvestigator(_Crime,_Lead) + AND + CrimeGetType(_Crime,_Type) + AND + DB_CrimeAttitudeChange(_Type,_Adjust) + THEN + ProcCrimeCheckIfAttitudeCauseCombat(_Lead,_Criminal,_Adjust); + + PROC + ProcTryMergingCrimes((INTEGER)_NewCrime,(INTEGER)_OldCrime,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Player) + AND + NOT DB_CanMergeCrimes(1) + AND + QueryOnlyOnce("CRIME_Trespassing_NPCForceStopDialog") + THEN + ProcForceStopDialog(_NPC); + + PROC + ProcTryMergingCrimes((INTEGER)_NewCrime,(INTEGER)_OldCrime,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Player) + AND + NOT DB_CanMergeCrimes(1) + THEN + //ignore these 2 crimes, since we're dealing with them in our own way + CrimeIgnoreCrime(_OldCrime,_NPC); + CrimeIgnoreCrime(_NewCrime,_NPC); + DB_CrimeTresPassCombatFallback(_NPC); + ProcTryStartAttackAD(_NPC); + CharacterSetTemporaryHostileRelation(_NPC,_Player); + + PROC + ProcTryMergingCrimes((INTEGER)_NewCrime,(INTEGER)_OldCrime,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Player) + AND + DB_CanMergeCrimes(1) + AND + DB_DialogNPCs(_ID,_NPC,_) + THEN + CharacterStopCrimeWithID(_Player,_NewCrime); + DialogAddCharacter(_ID,_Player); + + QRY + QryCanMergeCrimes((INTEGER)_NewCrime,(INTEGER)_OldCrime,(CHARACTERGUID)_Player) + AND + CrimeGetType(_NewCrime,_Type) + AND + CrimeGetType(_OldCrime,_Type) + AND + CrimeAddCriminal(_OldCrime,_Player,1) + THEN + DB_Noop(1); + + PROC + ProcTryStartAttackAD((CHARACTERGUID)_NPC) + AND + IsTagged(_NPC,"ANIMAL",0) + AND + HasAppliedStatus(_NPC, "UNCONSCIOUS", 0) + AND + HasAppliedStatus(_NPC, "LIE_DYING", 0) + AND + HasAppliedStatus(_NPC, "MUTED", 0) + THEN + Proc_StartDialog(1,"GEB_AD_AttackHelp",_NPC); + + //Clearing + PROC + ProcCrimeTrespassingStopNPCsDialogAndMakeHostileTo((INTEGER)_CrimeID,(INTEGER)_BusyCrimeID,(CHARACTERGUID)_NPC) + AND + DB_Crime_TrespassUnavailableLeadDetected(_NPC,_Player) + THEN + NOT DB_OnlyOnce("CRIME_Trespassing_NPCForceStopDialog"); + NOT DB_Crime_TrespassUnavailableLeadDetected(_NPC,_Player); + + PROC + ProcCrimeTrespassingStopNPCsDialogAndMakeHostileTo((INTEGER)_CrimeID,(INTEGER)_BusyCrimeID,(CHARACTERGUID)_NPC) + THEN + DB_CrimeTrespassingBlockHostile(_CrimeID,_NPC); + + IF + ObjectEnteredCombat((CHARACTERGUID)_NPC,_) + AND + DB_CrimeTresPassCombatFallback(_NPC) + AND + DB_CrimeTrespassingBlockHostile(_CrimeID,_NPC) + THEN + NOT DB_CrimeTrespassingBlockHostile(_CrimeID,_NPC); + + IF + OnCrimeResolved(_CrimeID,_,_,_,_,_) + AND + DB_CrimeTrespassingBlockHostile(_CrimeID,_NPC) + THEN + NOT DB_CrimeTrespassingBlockHostile(_CrimeID,_NPC); + + //END_REGION + + //REGION Crimes against a character that can't react because it's in a dialog + IF + CharacterSelectedAsBestUnavailableFallbackLead(_Char,_Region,_NewCrime,_OldCrime,_NewCriminal1,_NewCriminal2,_NewCriminal3,_NewCriminal4) + AND + CrimeGetTension(_NewCrime,_Tension) + AND + _Tension > 0 + AND + CrimeGetType(_NewCrime,_CrimeName) + AND + NOT DB_TrespassingCrimes(_CrimeName) + AND + DB_DialogNPCs(_OldCrimeDialog,_Char,_) + THEN + CrimeConfrontationDone(_NewCrime,_Char); + ProcForceStopDialog(_Char); + Proc_CharacterSetTemporaryHostileRelation(_Char,_NewCriminal1); + Proc_CharacterSetTemporaryHostileRelation(_Char,_NewCriminal2); + Proc_CharacterSetTemporaryHostileRelation(_Char,_NewCriminal3); + Proc_CharacterSetTemporaryHostileRelation(_Char,_NewCriminal4); + //END_REGION + //----------------------------------- ASSAULT ----------------------------------- + //REGION Chicken touch + + IF + CharacterStatusAttempt((CHARACTERGUID)_NPC,"CHICKEN",(CHARACTERGUID)_Player) + AND + DB_IsPlayer(_Player) + AND + NOT DB_IsPlayer(_NPC) + AND + NOT DB_IgnoreAssault(_NPC) + AND + NOT DB_CombatCharacters(_NPC,_) + AND + NOT DB_IgnoreAssaultFor(_Player,_NPC) + AND + ObjectIsCharacter(_NPC,1) + AND + IsTagged(_NPC,"GHOST",0) + AND + IsTagged(_NPC,"SUMMON",0) + AND + HasAppliedStatus(_NPC,"CHICKEN",1) + AND + CharacterIsEnemy(_NPC,_Player,0) + THEN + DB_Crime_PolymorphedIgnoreAssault(_NPC,_Player); //keep this first, the register forces a flush! + + //END_REGION + + //REGION Assault + + QRY + QryHasNeutralBlockTag((CHARACTERGUID)_NPC) + AND + DB_NeutralTagIgnore((STRING)_Tag) + AND + IsTagged(_NPC,_Tag,1) + THEN + DB_NOOP(1); + + //--- Checks if the NPC and/or the player/summon are in combat while being neutral to each other, then makes them hostile + IF + AttackedByObject((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon,_,_DamageSource) + AND + NOT DB_Crime_Assault(_,_,_NPC) + AND + NOT DB_Crime_Assault(_,_Player,_) + AND + NOT DB_Crime_PolymorphedIgnoreAssault(_NPC,_Player) + AND + NOT QryIgnoreDamageSource(_DamageSource) + AND + ObjectIsCharacter(_NPC,1) + AND + CharacterIsPlayer(_Player,1) + AND + CharacterIsDeadOrFeign(_Player,0) + AND + CharacterIsPlayer(_NPC,0) + AND + Qry_AreInCombat(_Player,_NPC) + AND + CharacterCanFight(_NPC,1) + AND + CharacterIsDead(_NPC,0) + AND + CharacterIsNeutral(_NPC,_Player,1) + AND + NOT QryHasNeutralBlockTag(_NPC) + AND + IsTagged(_NPC,"ANIMAL",0) + AND + DB_CombatCharacters(_NPC,_ID) + THEN + ProcWarnPlayerOfAttack(_NPC,_Player,_ID); + + //REGION Combat warnings + IF + ObjectLeftCombat((CHARACTERGUID)_NPC,_) + AND + DB_CombatWarnings(_NPC,_Cnt) + THEN + NOT DB_CombatWarnings(_NPC,_Cnt); + + PROC + ProcWarnPlayerOfAttack((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(INTEGER)_ID) + AND + NOT DB_CombatWarnings(_NPC,_) + THEN + DB_CombatWarnings(_NPC,0); + + PROC + ProcWarnPlayerOfAttack((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(INTEGER)_ID) + AND + NOT DB_CombatCharacters(_Player,_) + AND + DB_CombatWarnings(_NPC,_Count) + THEN + NOT DB_CombatWarnings(_NPC,_Count); + DB_CombatWarnings(_NPC,3); + + PROC + ProcWarnPlayerOfAttack((CHARACTERGUID)_NPC,_,_) + THEN + ObjectClearFlag(_NPC,"GEB_Crime_LastNeutralWarning"); + ObjectClearFlag(_NPC,"GEB_Crime_AttackNeutralWarning"); + + PROC + ProcWarnPlayerOfAttack((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(INTEGER)_ID) + AND + DB_CombatWarnings(_NPC,_Old) + AND + IntegerSum(_Old,1,_Count) + THEN + NOT DB_CombatWarnings(_NPC,_Old); + DB_CombatWarnings(_NPC,_Count); + + PROC + ProcWarnPlayerOfAttack((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(INTEGER)_ID) + AND + DB_CombatWarnings(_NPC,_Count) + AND + _Count > 3 + THEN + ObjectSetFlag(_NPC,"GEB_Crime_AttackNeutralWarning"); + ProcMakeNPCHostile(_NPC,_Player); + + PROC + ProcWarnPlayerOfAttack((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(INTEGER)_ID) + AND + DB_CombatWarnings(_NPC,3) + THEN + ObjectSetFlag(_NPC,"GEB_Crime_LastNeutralWarning"); + + PROC + ProcWarnPlayerOfAttack((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(INTEGER)_ID) + AND + DB_CombatWarnings(_NPC,_Count) + AND + QryDoNeutralAttackWarning(_Count) + THEN + Proc_StartDialog(1,"GEB_AD_WarnFriendlyFire",_NPC); + + QRY + QryDoNeutralAttackWarning((INTEGER)_Count) + AND + _Count < 3 + AND + Random(100,_Rnd) + AND + _Rnd <= 40 + THEN + DB_Noop(1); + + QRY + QryDoNeutralAttackWarning(3) + THEN + DB_Noop(1); + + //END_REGION + QRY + Qry_AreInCombat((CHARACTERGUID)_Player,(CHARACTERGUID)_NPC) + AND + DB_CombatCharacters(_NPC,_) + THEN + DB_NOOP(1); + + QRY + Qry_AreInCombat((CHARACTERGUID)_Player,(CHARACTERGUID)_NPC) + AND + DB_CombatCharacters(_Player,_) + THEN + DB_NOOP(1); + + PROC + ProcClearAssaultDBForCrime((INTEGER)_CrimeID) + AND + DB_Crime_Assault(_CrimeID,_Criminal,_Victim) + THEN + NOT DB_Crime_Assault(_CrimeID,_Criminal,_Victim); + + IF + OnCrimeRemoved(_CrimeID,_Victim,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + THEN + ProcClearAssaultDBForCrime(_CrimeID); + + IF + OnCrimeResolved(_CrimeID,_Victim,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + _Victim != NULL_00000000-0000-0000-0000-000000000000 + AND + DB_Crime_Assault(_CrimeID,_,_) + AND + IntegertoString(_CrimeID,_CrimeSuffix) + AND + StringConcatenate("Timer_ClearAttackDB",_CrimeSuffix,_TimerName) + THEN + DB_Crime_PlayerAttacked(_CrimeID,_Criminal1,_Victim); // This is For Murder crime + DB_Crime_PlayerAttacked(_CrimeID,_Criminal2,_Victim); + DB_Crime_PlayerAttacked(_CrimeID,_Criminal3,_Victim); + DB_Crime_PlayerAttacked(_CrimeID,_Criminal4,_Victim); + DB_AttackTimer(_CrimeID,_TimerName); + ProcObjectTimer(_Victim,_TimerName,1500); + NOT DB_Crime_PlayerAttacked(_CrimeID,NULL_00000000-0000-0000-0000-000000000000,_Victim); //Future Feature if needed Generate Murder for every on in combat with the OG DB_Crime_PlayerAttacked _Victim + + IF + OnCrimeResolved(_CrimeID,_Victim,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + THEN + ProcClearAssaultDBForCrime(_CrimeID); + + PROC + ProcObjectTimerFinished((CHARACTERGUID)_Victim,_TimerName) + AND + DB_AttackTimer(_CrimeID,_TimerName) + AND + DB_Crime_PlayerAttacked(_CrimeID,_Player,_Victim) + AND + NOT DB_CombatCharacters(_Victim, _) + THEN + NOT DB_Crime_PlayerAttacked(_CrimeID,_Player,_Victim); + + PROC + ProcObjectTimerFinished(_Victim,_TimerName) + AND + DB_AttackTimer(_CrimeID,_TimerName) + THEN + NOT DB_AttackTimer(_CrimeID,_TimerName); + + IF + CrimeInterrogationRequest(_RegionID,_CrimeID,_Interrogator,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_Dialog) + THEN + ProcClearAssaultDBForCrime(_CrimeID); + + IF + OnCrimeMergedWith(_Old,_New) + AND + DB_Crime_Assault(_Old,_Criminal1,_Victim) + THEN + NOT DB_Crime_Assault(_Old,_Criminal1,_Victim); + DB_Crime_Assault(_New,_Criminal1,_Victim); + + //if our vicitim is not selected as lead (incapacitated), don't track this DB because that will mean he won't be able to react anymore + //update it with the new lead + IF + CharacterOnCrimeSensibleActionNotification(_NPC,_,_CrimeID,_,_,_Criminal1,_,_,_,1) + AND + DB_Crime_Assault(_CrimeID,_Criminal1,_Victim) + THEN + NOT DB_Crime_Assault(_CrimeID,_Criminal1,_Victim); + DB_Crime_Assault(_CrimeID,_Criminal1,_NPC); + + //END_REGION + + //REGION General Assault crime -- verifies if the assailant is a summon or not and registers the Assault or AttackAnimal crime + + QRY + QryIgnoreDamageSource((STRING)_Dmg) + AND + DB_IgnoreDamageSources(_Dmg) + THEN + DB_NOOP(1); + + IF + AttackedByObject((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon,_,_DamageSource) + AND + NOT DB_IgnoreAssault(_NPC) + AND + NOT DB_Crime_PolymorphedIgnoreAssault(_NPC,_Player) + AND + NOT DB_CombatCharacters(_NPC,_) + AND + NOT DB_Crime_Assault(_,_,_NPC) + AND + CharacterIsPlayer(_Player,1) + AND + NOT QryIgnoreDamageSource(_DamageSource) + AND + CharacterIsDeadOrFeign(_Player,0) + AND + ObjectIsCharacter(_NPC,1) + AND + CharacterIsPlayer(_NPC,0) + AND + CharacterIsDead(_NPC,0) + AND + IsTagged(_NPC,"GHOST",0) + AND + IsTagged(_NPC,"SUMMON",0) + THEN + ProcCrimeCheckAssailant(_NPC,_Player,_Summon); + + + //--- Assailant is not a summon + PROC + ProcCrimeCheckAssailant((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon) + AND + NOT QRY_CharacterIsNull(_Summon) + AND + IsTagged(_Summon,"SUMMON",1) + AND + NOT DB_IgnoreAssaultFor(_Summon,_NPC) + AND + NOT DB_Crime_Assault(_,_Summon,_) + AND + CharacterIsEnemy(_NPC,_Summon,0) + THEN + ProcCrimeRegisterAssault(_Summon,_NPC,1); + + //--- Assailant is a summon + PROC + ProcCrimeCheckAssailant((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon) + AND + QryCrimeAssailantIsNotSummon(_Player,_Summon) + AND + NOT DB_IgnoreAssaultFor(_Player,_NPC) + AND + NOT DB_Crime_Assault(_,_Player,_) + AND + CharacterIsEnemy(_NPC,_Player,0) + THEN + ProcCrimeRegisterAssault(_Player,_NPC,0); + + //--- Split the type of assault + // Normal + PROC + ProcCrimeRegisterAssault((CHARACTERGUID)_Assailant,(CHARACTERGUID)_NPC,0) //_AssailantIsSummon + AND + IsTagged(_NPC,"ANIMAL",0) + THEN + ProcCrimeRegisterAssaultType(_Assailant,_NPC,"Assault"); + + PROC + ProcCrimeRegisterAssault((CHARACTERGUID)_Assailant,(CHARACTERGUID)_NPC,0) + AND + IsTagged(_NPC,"ANIMAL",1) + THEN + ProcCrimeRegisterAssaultType(_Assailant,_NPC,"AttackAnimal"); + + // Summon + PROC + ProcCrimeRegisterAssault((CHARACTERGUID)_Assailant,(CHARACTERGUID)_NPC,1) + AND + IsTagged(_NPC,"ANIMAL",0) + THEN + ProcCrimeRegisterAssaultType(_Assailant,_NPC,"SummonAssault"); + + PROC + ProcCrimeRegisterAssault((CHARACTERGUID)_Assailant,(CHARACTERGUID)_NPC,1) + AND + IsTagged(_NPC,"ANIMAL",1) + THEN + ProcCrimeRegisterAssaultType(_Assailant,_NPC,"SummonAttackAnimal"); + + //REGION Assault investigation location determination + // Default: victim location + // Problem: if attacked from out of sight range, they won't be able to find the attacker + // Solution: after a while, report the assailant's rather than the victim's location as investigation location + // If assaulted even more: force combat + // + // Reasoning: the more an NPC has been attacked, the more they'll pay attention + // regarding where the attack came from. Factors influencing them homing in on + // the source: sneaking, invisibility, wits difference between victim and assailant + + QRY + QRY_CRIMES_AssaultCrimeGetCrimeLocationScoreIncrease((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim) + AND + DB_CRIME_AssaultCrimeGetCrimeLocationScoreIncrease(_Total) + THEN + NOT DB_CRIME_AssaultCrimeGetCrimeLocationScoreIncrease(_Total); + + QRY + QRY_CRIMES_AssaultCrimeGetCrimeLocationScoreIncrease((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim) + AND + HasActiveStatus(_Assailant,"SNEAKING",_IsSneaking) + AND + HasActiveStatus(_Assailant,"INVISIBLE",_IsInvisible) + AND + CharacterGetAttribute(_Assailant,"WITS",_AssailantWits) + AND + CharacterGetAttribute(_Assailant,"WITS",_VictimWits) + AND + IntegerSubtract(_VictimWits,_AssailantWits,_WitsRes) + AND + QRY_IntegerSign(_WitsRes) + AND + DB_IntegerSign(_WitsBonus) + AND + DB_CRIME_CrimeLocationScoreIncrease(_IsSneaking,_IsInvisible,_Base,_Rand) + AND + Random(_Rand,_Extra) + AND + IntegerSum(_Base,_Extra,_BaseTotal) + AND + IntegerSum(_BaseTotal,_WitsBonus,_Total) + THEN + DB_CRIME_AssaultCrimeGetCrimeLocationScoreIncrease(_Total); + + QRY + QRY_CRIME_AssaultCrimeGetInvestigationPos((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim) + AND + DB_CRIME_AssaultCrimeInvestigationPos(_x,_yUp,_z) + THEN + NOT DB_CRIME_AssaultCrimeInvestigationPos(_x,_yUp,_z); + + QRY + QRY_CRIME_AssaultCrimeGetInvestigationPos((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim) + THEN + Proc_CharCountHelper(_Victim,"CRIME_CrimeTriggers_AssaultCrimeLocation"); + + // Update assault score + QRY + QRY_CRIME_AssaultCrimeGetInvestigationPos((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim) + AND + QRY_CRIMES_AssaultCrimeGetCrimeLocationScoreIncrease(_Assailant,_Victim) + AND + DB_CRIME_AssaultCrimeGetCrimeLocationScoreIncrease(_Increase) + THEN + Proc_CharCountHelper(_Victim,"CRIME_CrimeTriggers_AssaultCrimeLocation",_Increase); + + // Assaulted many times -> investigate location of assailant + QRY + QRY_CRIME_AssaultCrimeGetInvestigationPos((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim) + AND + DB_CharCountHelper(_Victim,"CRIME_CrimeTriggers_AssaultCrimeLocation",_Count) + AND + DB_CRIME_CrimeLocationScore_GoToAttackerThreshold(_Threshold) + AND + _Count >= _Threshold + AND + GetPosition(_Assailant,_x,_y,_z) + AND + RealSum(_y,1.0,_yUp) + THEN + DB_CRIME_AssaultCrimeInvestigationPos(_x,_yUp,_z); + + // Fallback if not yet assaulted many times + QRY + QRY_CRIME_AssaultCrimeGetInvestigationPos((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim) + AND + NOT DB_CRIME_AssaultCrimeInvestigationPos(_,_,_) + AND + GetPosition(_Victim,_x,_y,_z) + AND + RealSum(_y,1.0,_yUp) + THEN + DB_CRIME_AssaultCrimeInvestigationPos(_x,_yUp,_z); + + // Clean up when dying + IF + CharacterDied(_Victim) + AND + DB_CharCountHelper(_Victim,"CRIME_CrimeTriggers_AssaultCrimeLocation",_Count) + THEN + NOT DB_CharCountHelper(_Victim,"CRIME_CrimeTriggers_AssaultCrimeLocation",_Count); + + //END_REGION + + //REGION Assaulted really a lot or down on health -> start combat + // Allows for at least three assaults -> don't cut off warning system + PROC + ProcCrimeRegisterAssaultType((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim,(STRING)_AssaultType) + AND + CharacterIsCrimeEnabled(_Victim,_AssaultType,1) + AND + QRY_CRIME_AssaultCrimeGetInvestigationPos(_Assailant,_Victim) + AND + DB_CharCountHelper(_Victim,"CRIME_CrimeTriggers_AssaultCrimeLocation",_Count) + AND + DB_CRIME_CrimeLocationScore_StartAttackingThreshold(_Threshold) + AND + _Count >= _Threshold + AND + CharacterCanFight(_Victim,1) + THEN + DB_CrimeRegisterAssaultType_Handled(1); + ProcTryStartAttackAD(_Victim); + Proc_CharacterSetTemporaryHostileRelation(_Victim,_Assailant); + EnterCombat(_Victim,_Assailant); + + PROC + ProcCrimeRegisterAssaultType((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim,(STRING)_AssaultType) + AND + CharacterIsCrimeEnabled(_Victim,_AssaultType,1) + AND + CharacterGetHitpointsPercentage(_Victim,_Percentage) + AND + DB_CRIME_Assault_HealthStartAttackingThreshold(_Threshold) + AND + _Percentage < _Threshold + AND + CharacterCanFight(_Victim,1) + AND + CharacterIsDead(_Victim,0) + THEN + DB_CrimeRegisterAssaultType_Handled(1); + ProcTryStartAttackAD(_Victim); + Proc_CharacterSetTemporaryHostileRelation(_Victim,_Assailant); + EnterCombat(_Victim,_Assailant); + //END_REGION + + PROC + ProcCrimeRegisterAssaultType((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim,(STRING)_AssaultType) + AND + NOT DB_CrimeRegisterAssaultType_Handled(1) + AND + GetPosition(_Victim,_x,_y,_z) + AND + RealSum(_y,1.0,_yUp) + AND + CrimeIsAnyNPCGoingToReact(_Assailant,_AssaultType,_x,_yUp,_z,_WillReact) + AND + CrimeGetNewID(_CrimeID) + AND + DB_CRIME_AssaultCrimeInvestigationPos(_XInv,_YInv,_ZInv) + THEN + NOT DB_CRIME_AssaultCrimeInvestigationPos(_XInv,_YInv,_ZInv); + DB_CRIME_CrimeInvestigationPos(_CrimeID,_XInv,_YInv,_ZInv); + DB_Crime_Assault(_CrimeID,_Assailant,_Victim); + ProcCheckRegisterAssault(_Assailant,_Victim,_AssaultType,_x,_yUp,_z,_CrimeID,_WillReact); + + PROC + ProcCrimeRegisterAssaultType((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim,(STRING)_AssaultType) + AND + DB_CrimeRegisterAssaultType_Handled(1) + THEN + NOT DB_CrimeRegisterAssaultType_Handled(1); + + PROC + ProcClearAssaultDBForCrime((INTEGER)_CrimeID) + AND + DB_CRIME_CrimeInvestigationPos(_CrimeID,_XInv,_YInv,_ZInv) + THEN + NOT DB_CRIME_CrimeInvestigationPos(_CrimeID,_XInv,_YInv,_ZInv); + + PROC + ProcCheckRegisterAssault((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim,(STRING)_AssaultType,(REAL)_X,(REAL)_Y,(REAL)_Z,(INTEGER)_CrimeID,1) + THEN + ProcCharacterRegisterCrimeWithPosition(_Assailant,_AssaultType,NULL_00000000-0000-0000-0000-000000000000,_Victim,_X,_Y,_Z,_CrimeID,_Victim); + + //noone reacted to this one, so assume the victim was incapacitated + PROC + ProcCheckRegisterAssault((CHARACTERGUID)_Assailant,(CHARACTERGUID)_Victim,(STRING)_AssaultType,(REAL)_X,(REAL)_Y,(REAL)_Z,(INTEGER)_CrimeID,0) + THEN + ProcCharacterRegisterCrimeWithPosition(_Assailant,"IncapacitatedAssault",NULL_00000000-0000-0000-0000-000000000000,_Victim,_X,_Y,_Z,_CrimeID,_Victim); + + //END_REGION + + //REGION Clear PolymorphedIgnoreAssault fact + + IF + AttackedByObject((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon,_,_) + AND + DB_Crime_PolymorphedIgnoreAssault(_NPC,_Player) + AND + GetPosition(_NPC,_x,_y,_z) + AND + RealSum(_y,1.0,_yUp) + AND + CrimeGetNewID(_CrimeID) + THEN + NOT DB_Crime_PolymorphedIgnoreAssault(_NPC,_Player); + CharacterRegisterCrimeWithPosition(_Player,"Polymorphed",NULL_00000000-0000-0000-0000-000000000000,_NPC,_x,_yUp,_z,_CrimeID); + + //END_REGION + + //REGION Teleportation Netherswap + IF + CharacterUsedSkillOnTarget(_Player,(CHARACTERGUID)_Npc,"Teleportation_Netherswap",_) + AND + NOT Qry_AreInCombat(_Player,_NPC) + AND + CharacterIsPlayer(_Player,1) + AND + ObjectIsCharacter(_Npc,1) + AND + CharacterIsDeadOrFeign(_Player,0) + AND + CharacterIsPlayer(_NPC,0) + AND + CharacterIsDead(_NPC,0) + THEN + ProcDoCrimeCheckAssailant(_Player,_NPC); + + PROC + ProcDoCrimeCheckAssailant((CHARACTERGUID)_Summon,(CHARACTERGUID)_NPC) + AND + CharacterIsSummon(_Summon,1) + AND + CharacterGetOwner(_Summon,_Player) + THEN + ProcCrimeCheckAssailant(_NPC,_Player,_Summon); + + PROC + ProcDoCrimeCheckAssailant((CHARACTERGUID)_Player,(CHARACTERGUID)_NPC) + AND + CharacterIsSummon(_Player,0) + THEN + ProcCrimeCheckAssailant(_NPC,_Player,_Player); + + //END_REGION + + //----------------------------------- /ASSAULT ----------------------------------- + + //REGION GEB_FleeOutOfSight + IF + AutomatedDialogEnded("GEB_AD_CallForHelp",_ID) // For kids looking for help + AND + DB_DialogNPCs(_ID,_NPC,1) + AND + IsTagged(_NPC,"KID",1) + AND + ObjectGetFlag(_NPC,"GEB_FleeOutOfSight",0) + THEN + ObjectSetFlag(_NPC,"GEB_FleeOutOfSight"); + + IF + ObjectFlagSet("GEB_FleeOutOfSight",(CHARACTERGUID)_NPC,_) + THEN + SetHasDialog(_NPC,0); + ProcCharacterDisappearOutOfSight((CHARACTERGUID)_NPC,0,1,"GEB_NPCFledOutOfSight",1); + Proc_StartDialog(1,"GEB_AD_CallForHelp",_NPC); + ProcForceStopDialog(_NPC); + + IF + ObjectFlagSet("GEB_FleeOutOfSight",_NPC,_) + AND + NOT DB_GEB_FledOutOfSight(_NPC,_,_,_) + AND + GetPosition(_NPC,_X,_Y,_Z) + THEN + DB_GEB_FledOutOfSight(_NPC,_X,_Y,_Z); + + IF + ObjectFlagSet("GEB_FleeOutOfSight",(CHARACTERGUID)_NPC,_) + AND + DB_Crime_Assault(_CrimeID,_Player,_NPC) + THEN + NOT DB_Crime_Assault(_CrimeID,_Player,_NPC); + + IF + StoryEvent(_NPC,"GEB_NPCFledOutOfSight") + AND + ObjectGetFlag(_NPC,"GEB_DontAppearAfter",0) + THEN + ProcObjectTimer(_NPC,"GEB_AppearNPCOutOfSight",15000); + + IF + ObjectFlagSet("GEB_DontAppearAfter",_Char,_) + THEN + ProcObjectTimerCancel(_Char,"GEB_AppearNPCOutOfSight"); + + IF + ObjectFlagSet("GEB_DontAppearAfter",(CHARACTERGUID)_Char,_) + AND + DB_GEB_NPCAppearAfterCombat(_Char,_CombatID) + THEN + NOT DB_GEB_NPCAppearAfterCombat(_Char,_CombatID); + + //--- Start trying to reappear + PROC + ProcObjectTimerCancel((CHARACTERGUID)_NPC,"GEB_AppearNPCOutOfSight") + AND + DB_GEB_FledOutOfSight(_NPC,_X,_Y,_Z) + THEN + NOT DB_GEB_FledOutOfSight(_NPC,_X,_Y,_Z); + + PROC + ProcObjectTimerFinished((CHARACTERGUID)_NPC,"GEB_AppearNPCOutOfSight") + AND + DB_GEB_FledOutOfSight(_NPC,_X,_Y,_Z) + AND + GetClosestPlayerToPosition(_X,_Y,_Z,_Player,_Dist) + THEN + ProcCrimeAppearOutOfSightChecks(_NPC,_Player,_Dist); + + //--- Check the distance and if the player is dead, in dialog or in combat + PROC + ProcCrimeAppearOutOfSightChecks((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(REAL)_Dist) + AND + _Dist > 20.0 + THEN + ProcAppearOutOfSightAfterFleeing(_NPC); + + PROC + ProcCrimeAppearOutOfSightChecks((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(REAL)_Dist) + AND + _Dist <= 20.0 + AND + Query_CharacterIsAliveAndNotInCombat(_Player) + AND + IsSpeakerReserved(_Player,0) + THEN + ProcAppearOutOfSightAfterFleeing(_NPC); + + PROC + ProcCrimeAppearOutOfSightChecks((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(REAL)_Dist) + AND + _Dist <= 20.0 + AND + DB_CombatCharacters(_Player,_CombatID) + THEN + DB_GEB_NPCAppearAfterCombat(_NPC,_CombatID); + + PROC + ProcCrimeAppearOutOfSightChecks((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(REAL)_Dist) + AND + _Dist <= 20.0 + AND + CharacterIsDeadOrFeign(_Player,1) + THEN + ProcAppearOutOfSight_DeadClosestPlayer(_NPC,_Player); + + PROC + ProcCrimeAppearOutOfSightChecks((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(REAL)_Dist) + AND + NOT DB_GEB_NPCAppearAfterCombat(_NPC,_) + AND + _Dist <= 20.0 + AND + IsSpeakerReserved(_Player,1) + AND + DB_DialogPlayers(_Inst,_Player,1) + THEN + DB_GEB_NPCAppearAfterDialog(_NPC,_Inst); + + // Try to find a live player + PROC + ProcAppearOutOfSight_DeadClosestPlayer((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player) + AND + GetClosestAlivePlayer(_Player,_AlivePlayer,_) + THEN + DB_GEB_AppearOutOfSight_AlivePlayerFound(_NPC,_AlivePlayer); + + PROC + ProcAppearOutOfSight_DeadClosestPlayer((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player) + AND + NOT DB_GEB_AppearOutOfSight_AlivePlayerFound(_NPC,_) + THEN + ProcAppearOutOfSightAfterFleeing(_NPC); + + PROC + ProcAppearOutOfSight_DeadClosestPlayer((CHARACTERGUID)_NPC,(CHARACTERGUID)_) + AND + DB_GEB_AppearOutOfSight_AlivePlayerFound(_NPC,_AlivePlayer) + AND + DB_GEB_FledOutOfSight(_NPC,_X,_Y,_Z) + AND + GetDistanceToPosition(_AlivePlayer,_X,_Y,_Z,_Dist) + THEN + NOT DB_GEB_AppearOutOfSight_AlivePlayerFound(_NPC,_AlivePlayer); + ProcCrimeAppearOutOfSightChecks(_NPC,(CHARACTERGUID)_AlivePlayer,_Dist); + + //--- Recheck after dialog & combat + IF + DialogEnded(_,_Inst) + AND + DB_GEB_NPCAppearAfterDialog(_NPC,_Inst) + THEN + NOT DB_GEB_NPCAppearAfterDialog(_NPC,_Inst); + ProcObjectTimer(_NPC,"GEB_AppearNPCOutOfSight",3000); // restart from the beginning (delay in case combat starts after the dialog) + + IF + CombatEnded(_CombatID) + AND + DB_GEB_NPCAppearAfterCombat(_NPC,_CombatID) + THEN + NOT DB_GEB_NPCAppearAfterCombat(_NPC,_CombatID); + ProcObjectTimer(_NPC,"GEB_AppearNPCOutOfSight",3000); // restart the checks from the beginning + + //--- Appear + PROC + ProcAppearOutOfSightAfterFleeing((CHARACTERGUID)_NPC) + AND + DB_GEB_FledOutOfSight(_NPC,_X,_Y,_Z) + THEN + NOT DB_GEB_FledOutOfSight(_NPC,_X,_Y,_Z); + SetHasDialog(_NPC,1); + CharacterAppearAtPositionOutOfSightTo((CHARACTERGUID)_NPC,_X,_Y,_Z,0,0,"GEB_NPCAppeared"); + ObjectClearFlag(_NPC,"GEB_FleeOutOfSight",0); + CharacterSetHitpointsPercentage(_NPC,100); + + //END_REGION + + //REGION Source Magic + + IF + CharacterUsedSkill(_Character,_Skill,_) + AND + DB_IsPlayer(_Character) + AND + IsSourceSkill(_Skill,1) + THEN + CharacterRegisterCrime(_Character,"SourceMagic",NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,0); + + //END_REGION + + //REGION Stealing + IF + CharacterStoleItem(_Character,_Item,_X,_Y,_Z,_Victim,_SrcContainer,_) + AND + CharacterIsPlayer(_Character,1) + AND + _SrcContainer==NULL_00000000-0000-0000-0000-000000000000 + THEN + //TODO: do not register Steal for stelaing from a container? IE: the problem with doing this is, that NPCs will detect missign items from a barrel without looking into it + CharacterRegisterCrimeWithPosition(_Character,"Steal",_Item,_Victim,_X,_Y,_Z,0); + + //END_REGION + + //REGION Murder (animals and non-animals) + + //REGION Helpers + // A killed character may get removed from a combat before the CharacterKilledByCharacter event gets triggered + // -> also check DB_WasInCombat for the _Victim + QRY + QryCrimeKillerVictimWereInSameCombat((CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim) + AND + DB_CombatCharacters(_Killer,_ID) + AND + DB_WasInCombat(_Victim,_ID) + THEN + DB_NOOP(1); + + QRY + QryCrimeKillerVictimWereInSameCombat((CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim) + AND + DB_CombatCharacters(_Killer,_ID) + AND + DB_CombatCharacters(_Victim,_ID) + THEN + DB_NOOP(1); + + // Killing a totem or a summon is not murder + QRY + QryCrimeCharacterCanCreateMurder((CHARACTERGUID)_Char) + AND + IsTagged(_Char,"SUMMON",0) + AND + IsTagged(_Char,"TOTEM",0) + THEN + DB_NOOP(1); + //END_REGION + + //REGION Determine crime type + // By default, murdering an animal results in "KilledAnimal" and murdering anyone + // else in "Murder". Can override QryCrimeMurderGetCrimeTypeCustom() to return custom results. + // + // Note: QryCrimeMurderGetCrimeTypeCustom() can be called multiple times for the same murder + // (-> should not keep state, e.g. don't assume second call is for second murder) + + // Define signature for custom query + QRY + QryCrimeMurderGetCrimeTypeCustom((CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim) + AND + DB_CrimeNeverEverSet__INVALID(1) + THEN + DB_NOOP(1); + + // Reset previous result, if any + QRY + QryCrimeMurderGetCrimeType((CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim) + AND + DB_CrimeMurderCrimeType(_Type) + THEN + NOT DB_CrimeMurderCrimeType(_Type); + + // Query custom overrides + QRY + QryCrimeMurderGetCrimeType((CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim) + AND + QryCrimeMurderGetCrimeTypeCustom(_Killer,_Victim) + THEN + DB_NOOP(1); + + // Default fallbacks + QRY + QryCrimeMurderGetCrimeType((CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim) + AND + NOT DB_CrimeMurderCrimeType(_) + AND + IsTagged(_Victim,"ANIMAL",_Animal) + AND + HasActiveStatus(_Killer,"SNEAKING",_Sneaking) + AND + CharacterIsSummon(_Killer,_Summon) + AND + DB_CRIME_MurderType(_Sneaking,_Animal,_Summon,_MurderType) + THEN + DB_CrimeMurderCrimeType(_MurderType); + //END_REGION + + //REGION Witnesses that should ignore this murder crime + // Only have to do something before registering the crime if + // the witness does not ignore crimes like this in general + PROC + ProcCrimeMurderDefineSilentWitness((INTEGER)_CrimeID,(CHARACTERGUID)_Witness,(CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim) + AND + QryCrimeMurderGetCrimeType(_Killer,_Victim) + AND + DB_CrimeMurderCrimeType(_CrimeType) + AND + NOT DB_CharacterCrimeDisabled(_Witness,_CrimeType) + THEN + DB_CrimeSilentWitness(_CrimeID,_CrimeType,_Witness); + // Don't set it to ignore this crime yet, as another crime (murder) + // could occur between now and when this murder is registered due to + // the use of an iterator) -- that will be done by ProcCrimeCreateMurder) + + // Convert DB_CrimeSilentWitness() to DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(), as used by ProcCharacterRegisterCrimeWithPosition() + PROC + PROC_CRIME_CrimeTriggers_GetSilentWitnessesForCrime((INTEGER)_CrimeID,(CHARACTERGUID)_Perpetrator,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_Victim) + AND + DB_CrimeSilentWitness(_CrimeID,_CrimeType,_Witness) + THEN + NOT DB_CrimeSilentWitness(_CrimeID,_CrimeType,_Witness); + DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_Witness); + + // NPCs that should ignore the murder of this victim should be treated as silent witnesses + PROC + PROC_CRIME_CrimeTriggers_GetSilentWitnessesForCrime((INTEGER)_CrimeID,(CHARACTERGUID)_Perpetrator,(STRING)_CrimeType,(GUIDSTRING)_Evidence,(CHARACTERGUID)_Victim) + AND + DB_MurderIgnoreFor((CHARACTERGUID)_Witness,(CHARACTERGUID)_Victim) + THEN + DB_CRIME_CrimeTriggers_SilentWitnessesForCrime(_Witness); + //END_REGION + + //REGION Register the murder crime + PROC + ProcCrimeCreateMurder((CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim,(INTEGER)_CrimeID) + AND + QryCrimeMurderGetCrimeType(_Killer,_Victim) + AND + DB_CrimeMurderCrimeType(_CrimeType) + AND + GetPosition(_Victim,_x,_y,_z) + AND + RealSum(_y,1.0,_yUp) + THEN + ProcCharacterRegisterCrimeWithPosition(_Killer,_CrimeType,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,_x,_yUp,_z,_CrimeID,_Victim); + //END_REGION + + //REGION 1) Killed a non-enemy NPC outside of combat (one-shot, so combat did not have a chance to start) + IF + CharacterKilledBy(_Defender,_AttackerOwner,_Attacker) + AND + NOT DB_IsPlayer(_Defender) + AND + CharacterIsPlayer(_Attacker,1) + AND + CharacterIsPartyFollower(_Attacker,0) + AND + CharacterIsEnemy(_Defender,_Attacker,0) + AND + NOT DB_DontCreateMurder(_Defender) + AND + NOT QryCrimeKillerVictimWereInSameCombat(_Attacker,_Defender) + AND + QryCrimeCharacterCanCreateMurder(_Defender) + AND + CrimeGetNewID(_CrimeID) + THEN + DebugText(_Defender,"OneShot Murder Crime Scene"); + DB_CrimeMurderCreated(_Defender,_Attacker); + ProcCrimeCreateMurder(_Attacker,_Defender,_CrimeID); + //END_REGION + + //REGION 2) Killed an NPC while it was investigating + IF + CharacterKilledBy(_Defender,_AttackerOwner,_Attacker) + AND + NOT DB_CrimeMurderCreated(_Defender,_Attacker) + AND + NOT DB_IsPlayer(_Defender) + AND + NOT DB_DontCreateMurder(_Defender) + AND + DB_Crime_Assault(_,_,_Defender) // This DB Will be filled in if the character is still investigating + AND + QryCrimeCharacterCanCreateMurder(_Defender) + AND + CharacterIsPlayer(_Attacker,1) + AND + CharacterIsPartyFollower(_Attacker,0) + AND + CrimeGetNewID(_CrimeID) + THEN + DebugText(_Defender,"Mid Investigate Murder Crime Scene"); + ProcCrimeCreateMurder(_Attacker,_Defender,_CrimeID); + //END_REGION + + //REGION 3) Killed an NPC in a combat following an assault crime + // Current logic: + // - Create a murder for any NPC that you kill in this combat + // - This murder is, however, ignored by anyone within a 25 metre range that was not in combat + // Reasoning: the characters that joined in the combat due to the assault, presumably would + // have done the same for murder. The ones that did not, might not join for murder either. They also + // might, but we don't have a good way to determine this. Creating a murder in this case can easily + // lead to an avalache where a whole city starts fighting a player, which is not good -> be very + // restrictive about who will care about such a murder + // + // Don't check for CharacterIsEnemy(_NPC,0), because when someone attacks you after you assaulted them, + // they will obviously be an enemty to you. + IF + CharacterKilledBy(_Defender,_AttackerOwner,_Attacker) + AND + NOT DB_CrimeMurderCreated(_Defender,_Attacker) + AND + // This DB is set after an assault crime, and also for other + // characters that join a combat in which an assault victim is involved + DB_Crime_PlayerAttacked(_,_,_Defender) + AND + DB_CombatCharacters(_Defender,_ID) + AND + NOT DB_IsPlayer(_Defender) + AND + NOT DB_DontCreateMurder(_Defender) + AND + CharacterIsPlayer(_Attacker,1) + AND + CharacterIsPartyFollower(_Attacker,0) + AND + QryCrimeCharacterCanCreateMurder(_Defender) + AND + CrimeGetNewID(_CrimeID) + AND + IntegertoString(_CrimeID,_Iterator) + AND + StringConcatenate(_Iterator,"GEB_IgnoreCrime",_IteratorID) + THEN + DebugText(_Defender,"Assault murder scene"); + DB_CrimeMurderSilentWitnessCollectionContext(_CrimeID,_Defender,_IteratorID,_Attacker); + CharacterLaunchIteratorAroundCharacter(_Defender,25.0,_IteratorID); + + PROC + ProcCrimeMurderMaybeMakeSilentWitness((INTEGER)_CrimeID,(CHARACTERGUID)_Witness,(CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim) + AND + NOT DB_CombatCharacters(_Witness,_) + THEN + ProcCrimeMurderDefineSilentWitness(_CrimeID,_Witness,_Killer,_Victim); + + // Allies let allies commit murders! That's what real friendship is all about. + PROC + ProcCrimeMurderMaybeMakeSilentWitness((INTEGER)_CrimeID,(CHARACTERGUID)_Witness,(CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim) + AND + DB_CombatCharacters(_Witness,_) + AND + CharacterIsAlly(_Witness,_Killer,1) + THEN + ProcCrimeMurderDefineSilentWitness(_CrimeID,_Witness,_Killer,_Victim); + + // An ally of my ally is my friend (e.g. Butter in Fort Joy is only allied to the player that charmed her). + PROC + ProcCrimeMurderMaybeMakeSilentWitness((INTEGER)_CrimeID,(CHARACTERGUID)_Witness,(CHARACTERGUID)_Killer,(CHARACTERGUID)_Victim) + AND + DB_CombatCharacters(_Witness,_) + AND + DB_IsPlayer(_Player) + AND + CharacterIsAlly(_Witness,_Player,1) + AND + CharacterIsAlly(_Player,_Killer,1) + THEN + ProcCrimeMurderDefineSilentWitness(_CrimeID,_Witness,_Killer,_Victim); + + // Ignore murder seen in combat + IF + StoryEvent((CHARACTERGUID)_NPC,_IteratorID) + AND + DB_CrimeMurderSilentWitnessCollectionContext(_CrimeID,_DeadMan,_IteratorID,_Killer) + AND + _NPC != NULL_00000000-0000-0000-0000-000000000000 + AND + NOT DB_dead((CHARACTERGUID)_NPC) + THEN + ProcCrimeMurderMaybeMakeSilentWitness(_CrimeID,_NPC,_Killer,_DeadMan); + ProcCrimeMurderMaybeMakeSilentWitness(_CrimeID,_NPC,_Killer,_DeadMan); + + // Create Murder (Last NPC in the Iterator is NULL_00000000-0000-0000-0000-000000000000) + IF + StoryEvent(_NPC,_IteratorID) + AND + DB_CrimeMurderSilentWitnessCollectionContext(_CrimeID,_DeadMan,_IteratorID,_Killer) + AND + _NPC == NULL_00000000-0000-0000-0000-000000000000 + THEN + NOT DB_CrimeMurderSilentWitnessCollectionContext(_CrimeID,_DeadMan,_IteratorID,_Killer); + DebugText(_DeadMan,"Normal Murder Crime Scene"); + ProcCrimeCreateMurder(_Killer,_DeadMan,_CrimeID); + + QRY + Qry_HasDontCreateMurderInCombat((INTEGER)_ID) + AND + DB_CombatCharacters(_NPCS,_ID) + AND + DB_DontCreateMurder((CHARACTERGUID)_NPCS) + THEN + DB_NOOP(1); + + // One DB_DontCreateMurder() NPC in a combat -> killing others that join the combat should not create murders either + // (TODO: check that they're allies of one of the DB_DontCreateMurder() NPCs -- especially now that neutrals don't + // join random combats anymore) + IF + ObjectEnteredCombat(_Obj,_ID) + AND + ObjectIsCharacter(_Obj,1) + AND + Qry_HasDontCreateMurderInCombat(_ID) + AND + DB_CombatCharacters(_NPC,_ID) + AND + NOT DB_IsPlayer(_NPC) + AND + NOT DB_DontCreateMurder(_NPC) + THEN + DB_DontCreateMurder(_NPC); + DB_CrimeCreateMurderAfterCombat(_NPC,_ID); + DebugText(_NPC," Killing me won't create a murder in this combat, because I joined a combat with others whose murder gets ignored"); + + IF + ObjectSwitchedCombat((CHARACTERGUID)_NPC,_OldCombatID,_NewCombatID) + AND + DB_CrimeCreateMurderAfterCombat(_NPC,_OldCombatID) + THEN + NOT DB_CrimeCreateMurderAfterCombat(_NPC,_OldCombatID); + DB_CrimeCreateMurderAfterCombat(_NPC,_NewCombatID); + + IF + CombatEnded(_CombatID) + AND + DB_CrimeCreateMurderAfterCombat(_NPC,_CombatID) + THEN + NOT DB_CrimeCreateMurderAfterCombat(_NPC,_CombatID); + NOT DB_DontCreateMurder(_NPC); + + IF + ObjectEnteredCombat(_NPC,_) + AND + ObjectIsCharacter(_NPC,1) + THEN + ProcCrimeAddToAttackedDBIfAssaultCombat((CHARACTERGUID)_NPC); + + IF + ObjectSwitchedCombat(_NPC,_,_) + AND + ObjectIsCharacter(_NPC,1) + THEN + ProcCrimeAddToAttackedDBIfAssaultCombat((CHARACTERGUID)_NPC); + + IF + DB_Crime_PlayerAttacked(_CrimeID,_Player,_NPC) + THEN + ProcCrimeAddToAttackedDBIfAssaultCombat((CHARACTERGUID)_NPC); + + PROC + ProcCrimeAddToAttackedDBIfAssaultCombat((CHARACTERGUID)_NPC) + AND + DB_CombatCharacters(_NPC,_ID) + AND + DB_Crime_PlayerAttacked(_CrimeID,_Player,_OrigVic) + AND + DB_CombatCharacters(_Player,_ID) + AND + DB_CombatCharacters(_NPC2,_ID) + AND + NOT DB_Crime_PlayerAttacked(_CrimeID,_Player,_NPC2) + AND + CharacterIsPlayer(_NPC2,0) + AND + CharacterIsAlly(_OrigVic,_NPC2,1) + THEN + DB_Crime_PlayerAttacked(_CrimeID,_Player,_NPC2); + DebugText(_NPC2," Killing me will create a murder scene (probably joined combat to help assaulted NPC), although it will be ignored by anyone within a 25m radius of this combat"); + + IF + ObjectLeftCombat((CHARACTERGUID)_NPC,_) + AND + DB_Crime_PlayerAttacked(_CrimeID,_Player,_NPC) + THEN + NOT DB_Crime_PlayerAttacked(_CrimeID,_Player,_NPC); + + IF + OnCrimeMergedWith(_Old,_New) + AND + DB_CrimeMurderSilentWitnessCollectionContext(_Old,_DeadMan,_IteratorID,_Killer) + THEN + NOT DB_CrimeMurderSilentWitnessCollectionContext(_Old,_DeadMan,_IteratorID,_Killer); + DB_CrimeMurderSilentWitnessCollectionContext(_New,_DeadMan,_IteratorID,_Killer); + + IF + OnCrimeMergedWith(_Old,_New) + AND + DB_CrimeSilentWitness(_Old,_CrimeType,_NPC) + THEN + NOT DB_CrimeSilentWitness(_Old,_CrimeType,_NPC); + DB_CrimeSilentWitness(_New,_CrimeType,_NPC); + //END_REGION + + //REGION Reset DB_CrimeMurderCreated + IF + CharacterKilledBy(_Defender,_AttackerOwner,_Attacker) + AND + DB_CrimeMurderCreated(_Defender,_Attacker) + THEN + NOT DB_CrimeMurderCreated(_Defender,_Attacker); + //END_REGION + + //END_REGION + + //REGION Pickpocket + + IF + RequestPickpocket(_Player,_Npc) + AND + DB_CannotPickpocketTags(_Tag) + AND + IsTagged(_Npc, _Tag, 1) + AND + CharacterIsPartyMember(_Npc, 0) + THEN + DB_PickpocketingBlocked(1); + Proc_StartDialog(1,"GEB_AD_CannotPickpocket",_Player); + + IF + RequestPickpocket(_Player,_Npc) + AND + NOT DB_PickpocketingBlocked(1) + THEN + RemoveStatus(_Player,"INVISIBLE"); + + IF + CharacterPickpocketFailed(_Player,_) + THEN + RemoveStatus(_Player,"INVISIBLE"); + + + IF + RequestPickpocket(_Player,_Npc) + AND + DB_PickpocketingBlocked(1) + THEN + StartPickpocket(_Player,_Npc,0); + + IF + RequestPickpocket(_Player,_Npc) + AND + NOT DB_PickpocketingBlocked(1) + AND + CharacterIsPartyMember(_Npc, 0) + THEN + GenTradeItems(_Player,_Npc); + StartPickpocket(_Player,_Npc,1); + + IF + RequestPickpocket(_Player,_Npc) + THEN + NOT DB_PickpocketingBlocked(1); + + IF + RequestPickpocket(_Player,_OtherPlayer) + AND + CharacterIsPartyMember(_OtherPlayer, 1) + THEN + StartPickpocket(_Player,_OtherPlayer,1); + + + //--- PICKPOCKET SUCCESS + IF + CharacterPickpocketSuccess(_Thief,_Victim,_Item,_Amount) //TODO: Only trigger on HighValueItems + AND + CharacterIsCrimeEnabled(_Victim,"EmptyPocketNoticed",1) + AND + CharacterCanSpotCrimes(_Victim,1) + AND + Random(10000,_Rand) + AND + IntegerSum(_Rand,5000,_Time) + THEN + DB_Pickpocketed(_Thief,_Victim,_Item); + ProcObjectTimerCancel(_Victim,"CRIME_Pickpocket_CheckPockets"); + ProcObjectTimer(_Victim,"CRIME_Pickpocket_CheckPockets",_Time); + + + PROC + ProcObjectTimerFinished((CHARACTERGUID)_Victim,"CRIME_Pickpocket_CheckPockets") + AND + CharacterIsDead(_Victim,0) + AND + IsSpeakerReserved(_Victim,1) // Victim is in dialog, restart timer to delay reaction + AND + Random(10000,_Rand) + AND + IntegerSum(_Rand,5000,_Time) + THEN + ProcObjectTimerCancel(_Victim,"CRIME_Pickpocket_CheckPockets"); + ProcObjectTimer(_Victim,"CRIME_Pickpocket_CheckPockets",_Time); + + PROC + ProcObjectTimerFinished((CHARACTERGUID)_Victim,"CRIME_Pickpocket_CheckPockets") + AND + QRY_SpeakerIsAvailable(_Victim) + AND + DB_Pickpocketed(_Thief,_Victim,_) + AND + QueryOnlyOnce("CRIME_Pickpocket_PlayAnimation") + THEN + RemoveStatus(_Victim,"SITTING"); + RemoveStatus(_Victim,"LYING"); + PlayAnimation(_Victim,"PickPocket_01"); + + PROC + ProcObjectTimerFinished((CHARACTERGUID)_Victim,"CRIME_Pickpocket_CheckPockets") + AND + QRY_SpeakerIsAvailable(_Victim) + AND + DB_Pickpocketed(_Thief,_Victim,_Item) + AND + GetPosition(_Victim,_x,_y,_z) + THEN + NOT DB_OnlyOnce("CRIME_Pickpocket_PlayAnimation"); + NOT DB_Pickpocketed(_Thief,_Victim,_Item); + CharacterRegisterCrimeWithPosition(_Thief,"EmptyPocketNoticed",_Item,_Victim,_x,_y,_z,0); + + + //--- PICKPOCKET FAIL + //--- Don't create a crime if it failed because of a tag + IF + CharacterPickpocketFailed(_Player,_Npc) + AND + CharacterIsPartyMember(_Npc, 0) + AND + DB_CannotPickpocketTags(_Tag) + AND + IsTagged(_Npc, _Tag, 1) + THEN + DB_PickpocketingBlocked(1); + + //--- Check if player already stole items on that NPC + //--- Pass the item as evidence if it's the case. + IF + CharacterPickpocketFailed(_Player,_Npc) + AND + NOT DB_PickpocketingBlocked(1) + AND + CharacterIsPartyMember(_Npc, 0) + THEN + ProcCrimePickpocketFailedFlow(_Player,_Npc); + + PROC + ProcCrimePickpocketFailedFlow((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + THEN + ProcObjectTimerCancel(_Npc,"CRIME_Pickpocket_CheckPockets"); + + PROC + ProcCrimePickpocketFailedFlow((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + CharacterIsCrimeEnabled(_Npc,"PickPocketFailed",1) + THEN + RemoveStatus(_Player,"SNEAKING"); + RemoveStatus(_Npc,"SLEEPING"); + RemoveStatus(_Npc,"LYING"); + + PROC + ProcCrimePickpocketFailedFlow((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + NOT DB_Pickpocketed(_Player,_Npc,_) + THEN + ProcRegisterPickPocketFailed(_Player,_Npc,NULL_00000000-0000-0000-0000-000000000000); + + PROC + ProcCrimePickpocketFailedFlow((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_Pickpocketed(_Player,_Npc,_) + AND + QryCrimeWarningPickPocketFailed_NpcDoesNOTCheckEvidence(_Npc) + THEN + ProcRegisterPickPocketFailed(_Player,_Npc,NULL_00000000-0000-0000-0000-000000000000); + + // pass item as evidence if NPC must perform a search + PROC + ProcCrimePickpocketFailedFlow((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_Pickpocketed(_Player,_Npc,_Item) + AND + NOT QryCrimeWarningPickPocketFailed_NpcDoesNOTCheckEvidence(_Npc) + THEN + ProcRegisterPickPocketFailed(_Player,_Npc,_Item); + NOT DB_Pickpocketed(_Player,_Npc,_Item); + + PROC + ProcRegisterPickPocketFailed((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc,(GUIDSTRING)_Evidence) + AND + GetPosition(_Npc,_X,_Y,_Z) + AND + RealSum(_Y,1.0,_YUp) + THEN + CharacterRegisterCrimeWithPosition(_Player,"PickPocketFailed",_Evidence,_Npc,_X,_YUp,_Z,0); + + QRY + QryCrimeWarningPickPocketFailed_NpcDoesNOTCheckEvidence((CHARACTERGUID)_Npc) + AND + CharacterIsPartyMember(_Npc, 0) + AND + NOT QryNPCIsGuard(_Npc) + THEN + DB_NOOP(1); + + PROC + ProcCrimePickpocketFailedFlow((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + THEN + NOT DB_PickpocketingBlocked(1); + + + //END_REGION + + //REGION NPC Draw Weapons + // -------------------------- CRIME_Draw Reaction -----------------------------> + IF + CharacterOnCrimeSensibleActionNotification(_NPC,_,_CrimeID,"CRIME_Draw",_,_Criminal,_Criminal2,_Criminal3,_Criminal4,_) + AND + NOT DB_CombatCharacters(_Criminal,_) + AND + NOT DB_CombatCharacters(_NPC,_) + AND + NOT DB_NPCDrawForCrimial(_NPC,_CrimeID,_Criminal) + AND + CharacterCanSee(_NPC,_Criminal,_) + THEN + DB_NPCDrawForCrimial(_NPC,_CrimeID,_Criminal); + + IF + CharacterLostSightOfCharacter(_NPC,_Criminal) + AND + NOT DB_CombatCharacters(_NPC,_) + AND + DB_NPCDrawForCrimial(_NPC,_CrimeID,_Criminal) + THEN + CharacterSetFightMode(_NPC,0,0); + NOT DB_NPCDrawForCrimial(_NPC,_CrimeID,_Criminal); + + // -------------------------- WeaponsDrawn Crime -----------------------------> + PROC + ProcStoreFightMode((CHARACTERGUID)_Npc) + AND + NOT DB_FightModeState(_Npc,_) + AND + CharacterIsInFightMode(_Npc,_FightMode) + THEN + DB_FightModeState(_Npc,_FightMode); + + PROC + ProcRestoreFightMode((CHARACTERGUID)_Npc) + AND + DB_FightModeState(_Npc,_State) + AND + NOT DB_CombatCharacters(_NPC,_) + THEN + CharacterSetFightMode(_Npc,_State,0); + NOT DB_FightModeState(_Npc,_State); + + IF + StoryEvent(_Npc,"CRIME_RestoreUnsheath") + AND + ObjectExists(_Npc,1) + THEN + ProcRestoreFightMode((CHARACTERGUID)_Npc); + + IF + CharacterOnCrimeSensibleActionNotification(_NPC,_,_CrimeID,_,_,_Criminal,_Criminal2,_Criminal3,_Criminal4,_) + AND + NOT DB_CombatCharacters(_NPC,_) + AND + CrimeGetType(_CrimeID,"WeaponsDrawn") + AND + NOT DB_NPCSheathWeapon(_NPC,_Criminal) + THEN + DB_NPCSheathWeapon(_NPC,_Criminal); + DB_NPCSheathWeapon(_NPC,_Criminal2); + DB_NPCSheathWeapon(_NPC,_Criminal3); + DB_NPCSheathWeapon(_NPC,_Criminal4); + NOT DB_NPCSheathWeapon(_NPC,NULL_00000000-0000-0000-0000-000000000000); + ProcStoreFightMode(_Npc); + CharacterSetFightMode(_NPC,1,0); + + IF + CharacterStatusRemoved(_Player,"UNSHEATHED",_) + AND + DB_IsPlayer(_Player) + AND + DB_NPCSheathWeapon(_NPC,_Player) + AND + NOT DB_CombatCharacters(_NPC,_) + THEN + NOT DB_NPCSheathWeapon(_NPC,_Player); + ProcCrimeCheckIfPlayersWeaponsOut((CHARACTERGUID)_NPC); + + PROC + ProcCrimeCheckIfPlayersWeaponsOut((CHARACTERGUID)_NPC) + AND + NOT DB_NPCSheathWeapon(_NPC,_) + AND + NOT DB_CombatCharacters(_NPC,_) + THEN + ProcRestoreFightMode(_NPC); + SetStoryEvent(_NPC,"NPCReturnToOrginalPos"); + + IF + ObjectLeftCombat((CHARACTERGUID)_NPC,_) + AND + DB_NPCSheathWeapon(_NPC,_) + AND + ObjectExists(_NPC,1) + AND + CharacterIsDead(_NPC,0) + THEN + ProcRestoreFightMode(_NPC); + + IF + CharacterLostSightOfCharacter(_NPC,_Player) + AND + DB_NPCSheathWeapon(_NPC,_Player) + THEN + NOT DB_NPCSheathWeapon(_NPC,_Player); + ProcCrimeCheckIfPlayersWeaponsOut(_NPC); + + IF + DB_BlockThreatenedDialog((CHARACTERGUID)_Char) + THEN + CharacterDisableCrime(_Char,"WeaponsDrawn"); + DB_CheckWeaponsDrawnCrime(_Char); + + IF + DB_CheckWeaponsDrawnCrime((CHARACTERGUID)_Char) + AND + NOT DB_BlockThreatenedDialog(_Char) + AND + NOT DB_CharacterCrimeDisabled(_Char,"WeaponsDrawn") + THEN + CharacterEnableCrime(_Char,"WeaponsDrawn"); + + //END_REGION + + //REGION Sneaking Spotted + IF + CharacterSawSneakingCharacter(_NPC,_Player) + AND + CharacterIsPlayer(_NPC,0) + THEN + CharacterRegisterCrime(_Player,"Sneaking",NULL_00000000-0000-0000-0000-000000000000,_NPC,0); + //END_REGION + + //REGION Vandalise - AttackItem + + //--- 1) Item attacked + IF + AttackedByObject((ITEMGUID)_Item,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon,_,_DamageSource) + AND + NOT QryIgnoreDamageSource(_DamageSource) + AND + ObjectIsItem(_Item,1) + AND + CharacterIsPlayer(_Player,1) + AND + ItemGetHealthPoints(_Item,_INT) + AND + _INT > 0 + THEN + ProcCrimeVandaliseCheckOwner(_Item,_Player,_Summon); + + + //--- 2) Check if the item has an owner + PROC + ProcCrimeVandaliseCheckOwner((ITEMGUID)_Item,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon) + AND + ItemGetOwner(_Item,_Owner) + AND + _Owner != NULL_00000000-0000-0000-0000-000000000000 + AND + CharacterIsPlayer(_Owner,0) + THEN + ProcCrimeVandaliseCheckVandal(_Item,_Owner,_Player,_Summon,""); + + PROC + ProcCrimeVandaliseCheckOwner((ITEMGUID)_Item,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon) + AND + ItemGetOwner(_Item,_Owner) + AND + _Owner == NULL_00000000-0000-0000-0000-000000000000 + AND + NOT QryCheckforVandaliseTags(_Item) + THEN + ProcCrimeVandaliseCheckVandal(_Item,NULL_00000000-0000-0000-0000-000000000000,_Player,_Summon,"NoOwner"); + + + //--- 3) Check if the vandal is a summon + PROC + ProcCrimeVandaliseCheckVandal((ITEMGUID)_Item,(CHARACTERGUID)_Owner,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon,(STRING)_Postfix) + AND + NOT QRY_CharacterIsNull(_Summon) + AND + CharacterIsSummon(_Summon,1) + AND + QryShouldTriggerVandaliseCrime(_Item,_Summon) + AND + NOT DB_Crime_Vandalise((CHARACTERGUID)_Summon,(ITEMGUID)_Item,(INTEGER)_) + THEN + ProcCrimeRegisterVandalise(_Item,_Owner,_Summon,"Summon",_Postfix); + + PROC + ProcCrimeVandaliseCheckVandal((ITEMGUID)_Item,(CHARACTERGUID)_Owner,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon,(STRING)_Postfix) + AND + _Player == _Summon + AND + QryShouldTriggerVandaliseCrime(_Item,_Player) + AND + NOT DB_Crime_Vandalise(_Player,_Item,_) + THEN + ProcCrimeRegisterVandalise(_Item,_Owner,_Player,"",_Postfix); + + + //--- 4) Concatenate the crime's name & register it + PROC + ProcCrimeRegisterVandalise((ITEMGUID)_Item,(CHARACTERGUID)_Owner,(CHARACTERGUID)_Vandal) + THEN + ProcCrimeRegisterVandalise(_Item,_Owner,_Vandal,"",""); + + PROC + ProcCrimeRegisterVandalise((ITEMGUID)_Item,(CHARACTERGUID)_Owner,(CHARACTERGUID)_Vandal,(STRING)_Prefix,(STRING)_Postfix) + AND + StringConcatenate(_Prefix,"Vandalise",_Part1) + AND + StringConcatenate(_Part1,_Postfix,_CrimeName) + AND + GetPosition(_Item,_x,_y,_z) + AND + RealSum(_y,1.0,_yUp) + AND + CrimeGetNewID(_CrimeID) + THEN + DB_Crime_Vandalise(_Vandal,_Item,_CrimeID); + CharacterRegisterCrimeWithPosition(_Vandal,_CrimeName,_Item,_Owner,_x,_yUp,_z,_CrimeID); + + + QRY + QryCheckforVandaliseTags((ITEMGUID)_Item) + AND + DB_IgnoreVandaliseTag((STRING)_Tag) + AND + IsTagged(_Item,_Tag,1) + THEN + DB_NOOP(1); + + QRY + QryShouldTriggerVandaliseCrime((ITEMGUID)_Item,(CHARACTERGUID)_Player) + AND + NOT DB_CombatCharacters(_Player,_) + THEN + DB_NOOP(1); + + QRY + QryShouldTriggerVandaliseCrime((ITEMGUID)_Item,(CHARACTERGUID)_Player) + AND + DB_TriggerVandaliseInCombat(_Item) + THEN + DB_NOOP(1); + + IF + OnCrimeMergedWith(_Old,_New) + AND + DB_Crime_Vandalise(_Player,_Item,_Old) + THEN + NOT DB_Crime_Vandalise(_Player,_Item,_Old); + DB_Crime_Vandalise(_Player,_Item,_New); + + QRY + QryCheckforVandaliseTags((ITEMGUID)_Item) + AND + DB_IgnoreVandaliseTag((STRING)_Tag) + AND + IsTagged(_Item,_Tag,1) + THEN + DB_NOOP(1); + + //REGION Resolve Vandalise + IF + OnCrimeRemoved(_CrimeID,_Victim,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + THEN + ProcCrimeClearVandaliseDB(_Criminal1,_CrimeID); + ProcCrimeClearVandaliseDB(_Criminal2,_CrimeID); + ProcCrimeClearVandaliseDB(_Criminal3,_CrimeID); + ProcCrimeClearVandaliseDB(_Criminal4,_CrimeID); + + IF + OnCrimeResolved(_CrimeID,_Victim,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + CrimeGetType(_CrimeID,"Vandalise") + THEN + ProcCrimeClearVandaliseDB(_Criminal1,_CrimeID); + ProcCrimeClearVandaliseDB(_Criminal2,_CrimeID); + ProcCrimeClearVandaliseDB(_Criminal3,_CrimeID); + ProcCrimeClearVandaliseDB(_Criminal4,_CrimeID); + + IF + OnCrimeResolved(_CrimeID,_Victim,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + CrimeGetType(_CrimeID,"VandaliseNoOwner") + THEN + ProcCrimeClearVandaliseDB(_Criminal1,_CrimeID); + ProcCrimeClearVandaliseDB(_Criminal2,_CrimeID); + ProcCrimeClearVandaliseDB(_Criminal3,_CrimeID); + ProcCrimeClearVandaliseDB(_Criminal4,_CrimeID); + + PROC + ProcCrimeClearVandaliseDB((CHARACTERGUID)_Player,(INTEGER)_CrimeID) + AND + DB_Crime_Vandalise(_Player,_Item,_CrimeID) + THEN + NOT DB_Crime_Vandalise(_Player,_Item,_CrimeID); + //END_REGION + //END_REGION + + //REGION Vandalise - Destroy Item + + IF + AttackedByObject((ITEMGUID)_Item,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon,_,_DamageSource) + AND + NOT QryIgnoreDamageSource(_DamageSource) + AND + ObjectIsItem(_Item,1) + AND + CharacterIsPlayer(_Player,1) + AND + NOT DB_CombatCharacters(_Player,_) + AND + ItemGetHealthPoints(_Item,_INT) + AND + _INT < 1 + AND + NOT DB_Crime_ItemDestroyed(_Item,_Player) + AND + ItemGetOwner(_Item,_Owner) + AND + _Owner != NULL_00000000-0000-0000-0000-000000000000 + AND + CharacterIsPlayer(_Owner,0) + THEN + ProcCrimeItemDestroyCheckVandal(_Item,_Owner,_Player,_Summon); + + //2. check the criminal + PROC + ProcCrimeItemDestroyCheckVandal((ITEMGUID)_Item,(CHARACTERGUID)_Owner,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon) + AND + NOT QRY_CharacterIsNull(_Summon) + AND + CharacterIsSummon(_Summon,1) + AND + QryShouldTriggerVandaliseCrime(_Item,_Summon) + AND + NOT DB_Crime_Vandalise((CHARACTERGUID)_Summon,(ITEMGUID)_Item,(INTEGER)_) + THEN + ProcCrimeRegisterItemDestroy(_Item,_Owner,_Summon,"Summon"); + + PROC + ProcCrimeItemDestroyCheckVandal((ITEMGUID)_Item,(CHARACTERGUID)_Owner,(CHARACTERGUID)_Player,(CHARACTERGUID)_Summon) + AND + _Player == _Summon + AND + QryShouldTriggerVandaliseCrime(_Item,_Player) + AND + NOT DB_Crime_Vandalise(_Player,_Item,_) + THEN + ProcCrimeRegisterItemDestroy(_Item,_Owner,_Player,""); + + //3. register the crime + PROC + ProcCrimeRegisterItemDestroy((ITEMGUID)_Item,(CHARACTERGUID)_Owner,(CHARACTERGUID)_Vandal,(STRING)_Prefix) + AND + StringConcatenate(_Prefix,"ItemDestroy",_CrimeName) + AND + GetPosition(_Item,_x,_y,_z) + AND + RealSum(_y,1.0,_yUp) + THEN + DB_Crime_ItemDestroyed(_Item,_Vandal); + CharacterRegisterCrimeWithPosition(_Vandal,_CrimeName,_Item,_Owner,_x,_yUp,_z,0); + + //END_REGION + + //REGION Status Reaction + IF + CharacterStatusApplied(_Player,_Status,_) + AND + _Status != "UNSHEATHED" + AND + DB_IsPlayer(_Player) + AND + DB_StatusReaction(_Status,_Crime) + AND + HasActiveStatus(_Player,_Status,1) + THEN + DB_StatusReactingToPlayer(_Player,_Status); + CharacterRegisterCrime(_Player,_Crime,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,0); + + IF + CharacterStatusApplied(_Player,_Status,_) + AND + _Status == "UNSHEATHED" + AND + DB_IsPlayer(_Player) + AND + NOT DB_CombatCharacters(_Player,_) + AND + DB_StatusReaction(_Status,_Crime) + AND + HasActiveStatus(_Player,_Status,1) + THEN + DB_StatusReactingToPlayer(_Player,_Status); + CharacterRegisterCrime(_Player,_Crime,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,0); + + + IF + CharacterStatusRemoved(_Player, _Status, _) + AND + DB_IsPlayer(_Player) + AND + DB_StatusReaction(_Status,_Crime) + THEN + CharacterStopCrime(_Player,_Crime,NULL_00000000-0000-0000-0000-000000000000); + NOT DB_StatusReactingToPlayer(_Player,_Status); + + //END_REGION + + //REGION Is Not Messing Around + IF + DB_IsNotMessingAround((CHARACTERGUID)_Char) + THEN + DB_AttackOnAssault(_Char); + SetTag(_Char,"NOT_MESSING_AROUND"); + ProcCharacterEnableCrime(_Char,"Assault"); + + IF + DB_RemoveIsNotMessingAround((CHARACTERGUID)_Char) + THEN + NOT DB_IsNotMessingAround(_Char); + NOT DB_RemoveIsNotMessingAround(_Char); + ClearTag(_Char,"NOT_MESSING_AROUND"); + + IF + DB_AttackOnAssault(_Char) + AND + NOT DB_IsNotMessingAround(_Char) + THEN + NOT DB_AttackOnAssault(_Char); + ClearTag(_Char,"NOT_MESSING_AROUND"); + //END_REGION + + //REGION Attitude Change + QRY + QryNPCCaresAboutVictim((CHARACTERGUID)_NPC,(CHARACTERGUID)_Victim,(INTEGER)_) + AND + IsTagged(_NPC,"ANIMAL",1) + AND + IsTagged(_Victim,"ANIMAL",1) + THEN + DB_NOOP(1); + + QRY + QryNPCCaresAboutVictim((CHARACTERGUID)_NPC,(CHARACTERGUID)_Victim,_Primary) + AND + IsTagged(_NPC,"ANIMAL",0) + AND + QryNonAnimalNPCCaresAboutVictim(_NPC,_Victim,_Primary) + THEN + DB_NOOP(1); + + + QRY + QryNonAnimalNPCCaresAboutVictim((CHARACTERGUID)_NPC,(CHARACTERGUID)_Victim,0) + AND + ObjectIsCharacter(_Victim,0) + THEN + DB_NOOP(1); + + QRY + QryNonAnimalNPCCaresAboutVictim((CHARACTERGUID)_NPC,(CHARACTERGUID)_Victim,0) + AND + ObjectIsCharacter(_Victim,1) + AND + CharacterIsAlly(_NPC,_Victim,1) + THEN + DB_NOOP(1); + + QRY + QryNonAnimalNPCCaresAboutVictim((CHARACTERGUID)_NPC,(CHARACTERGUID)_Victim,1) + THEN + DB_NOOP(1); + + IF + CharacterOnCrimeSensibleActionNotification(_NPC,_Region,_CrimeID,_PriorityName,_Dialog,_Criminal,_Criminal2,_Criminal3,_Criminal4,_Primary) + AND + CrimeGetType(_CrimeID,_CrimeName) + AND + NOT DB_NPC_CrimeAttitude_DoNotChange(_NPC,_CrimeName) + AND + DB_CrimeAttitudeChange(_CrimeName,_AttitudeAmountToSub) + AND + CrimeGetVictim(_CrimeID,_Victim) + THEN + ProcCheckAdjustAttitude(_NPC,_Victim,_Criminal,_Criminal2,_Criminal3,_Criminal4,_AttitudeAmountToSub,_Primary); + + PROC + ProcCheckAdjustAttitude((CHARACTERGUID)_NPC,(CHARACTERGUID)_Victim,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(INTEGER)_AttitudeAmountToSub, (INTEGER)_Primary) + AND + QryNPCCaresAboutVictim(_NPC,_Victim,_Primary) + THEN + ProcCrimeCheckIfAttitudeCauseCombat(_NPC,_Criminal,_AttitudeAmountToSub); + ProcCrimeCheckIfAttitudeCauseCombat(_NPC,_Criminal2,_AttitudeAmountToSub); + ProcCrimeCheckIfAttitudeCauseCombat(_NPC,_Criminal3,_AttitudeAmountToSub); + ProcCrimeCheckIfAttitudeCauseCombat(_NPC,_Criminal4,_AttitudeAmountToSub); + + PROC + ProcCrimeCheckIfAttitudeCauseCombat((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(INTEGER)_AttitudeAmountToSub) + AND + CharacterGetAttitudeTowardsPlayer(_NPC,_Criminal,_NPCCurrentAttitude) + AND + IntegerSum(_NPCCurrentAttitude,_AttitudeAmountToSub,_NewNPCAttitude) + AND + _NewNPCAttitude > -75 //We Doin't want Lowering Attitude To Start Combat + THEN + CharacterAddAttitudeTowardsPlayer(_NPC,_Criminal,_AttitudeAmountToSub); + + PROC + ProcCrimeCheckIfAttitudeCauseCombat((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(INTEGER)_AttitudeAmountToSub) + AND + CharacterGetAttitudeTowardsPlayer(_NPC,_Criminal,_NPCCurrentAttitude) + AND + IntegerSum(_NPCCurrentAttitude,_AttitudeAmountToSub,_NewNPCAttitude) + AND + _NewNPCAttitude <= -75 //We Doin't want Lowering Attitude To Start Combat + AND + IntegerSubtract(-74,_NPCCurrentAttitude,_NewAttitudeToAdd) + THEN + CharacterAddAttitudeTowardsPlayer(_NPC,_Criminal,_NewAttitudeToAdd); + + //END_REGION + + //REGION Dialog interrupting + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + IsSpeakerReserved(_NPC,1) + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + _Criminal != NULL_00000000-0000-0000-0000-000000000000 + AND + IsSpeakerReserved(_Criminal,1) + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + _Criminal2 != NULL_00000000-0000-0000-0000-000000000000 + AND + IsSpeakerReserved(_Criminal2,1) + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + _Criminal3 != NULL_00000000-0000-0000-0000-000000000000 + AND + IsSpeakerReserved(_Criminal3,1) + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + _Criminal4 != NULL_00000000-0000-0000-0000-000000000000 + AND + IsSpeakerReserved(_Criminal4,1) + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + CharacterIsDead(_NPC,1) + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + GetRegion(_NPC,_Region) + AND + NOT DB_CurrentLevel(_Region) + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + CombatGetIDForCharacter(_NPC,_ID) + AND + _ID!=0 + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + CharacterIsEnemy(_NPC,_Criminal,1) + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + _Criminal2 != NULL_00000000-0000-0000-0000-000000000000 + AND + CharacterIsEnemy(_NPC,_Criminal2,1) + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + _Criminal3 != NULL_00000000-0000-0000-0000-000000000000 + AND + CharacterIsEnemy(_NPC,_Criminal3,1) + THEN + DB_NOOP(1); + + QRY + QRY_CrimeNPCUnAvailableForDialog((CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + _Criminal4 != NULL_00000000-0000-0000-0000-000000000000 + AND + CharacterIsEnemy(_NPC,_Criminal4,1) + THEN + DB_NOOP(1); + + PROC + ProcTryStopDialogFor((CHARACTERGUID)_Char) + AND + _Char != NULL_00000000-0000-0000-0000-000000000000 + AND + CharacterIsPlayer(_Char,1) + AND + DB_DialogPlayers(_Inst,_Char,_) + AND + DB_DialogName(_CurrentDialog,_Inst) + AND + NOT DB_Crime_DoNotStopDialog((STRING)_CurrentDialog) + THEN + DialogRequestStop(_Char); + DB_StoppedDialog(1); + + PROC + ProcTryStopDialogFor((CHARACTERGUID)_Char) + AND + _Char != NULL_00000000-0000-0000-0000-000000000000 + AND + CharacterIsPlayer(_Char,0) + AND + DB_DialogNPCs(_Inst,_Char,_) + AND + DB_DialogName(_CurrentDialog,_Inst) + AND + NOT DB_Crime_DoNotStopDialog(_CurrentDialog) + THEN + DialogRequestStop(_Char); + DB_StoppedDialog(1); + + PROC + ProcCrimeInterruptStoryDialogs((INTEGER)_CrimeID,(STRING)_CrimeDialog,1,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + THEN + ProcTryStopDialogFor(_NPC); + ProcTryStopDialogFor(_Criminal); + ProcTryStopDialogFor(_Criminal2); + ProcTryStopDialogFor(_Criminal3); + ProcTryStopDialogFor(_Criminal4); + + PROC + ProcCrimeInterruptStoryDialogs(_,_,1,_,_,_,_,_) + AND + DB_StoppedDialog(1) + THEN + NOT DB_StoppedDialog(1); + FireOsirisEvents(); + + PROC + ProcCrimeInterruptStoryDialogs((INTEGER)_CrimeID,(STRING)_CrimeDialog,0,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + DB_DialogNPCs(_Inst,_NPC,_) + AND + DB_DialogName(_CurrentDialog,_Inst) + AND + NOT DB_Crime_DoNotStopDialog(_CurrentDialog) + THEN + DialogRequestStop(_NPC); + FireOsirisEvents(); + + PROC + ProcCrimeInterruptStoryDialogs((INTEGER)_CrimeID,(STRING)_CrimeDialog,0,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + NOT QRY_CrimeNPCUnAvailableForDialog(_NPC,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000) + THEN + ProcStartCrimeDialog(_CrimeID,_CrimeDialog,0,_NPC,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeInterruptStoryDialogs((INTEGER)_CrimeID,(STRING)_CrimeDialog,1,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + NOT QRY_CrimeNPCUnAvailableForDialog(_NPC,_Criminal,_Criminal2,_Criminal3,_Criminal4) + THEN + ProcStartCrimeDialog(_CrimeID,_CrimeDialog,1,_NPC,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcHandleCrimeDialog((CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_CrimeDialog,1,_) + AND + DB_CheckInterrupt(_CrimeID,_Warner) + THEN + DB_Interrupted(_CrimeID,_Warner,1); + + PROC + ProcHandleCrimeDialog((CHARACTERGUID)_Warner,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_CrimeDialog,1,_) + AND + DB_CheckInterrupt(_CrimeID,_Warner) + THEN + NOT DB_CheckInterrupt(_CrimeID,_Warner); + + PROC + ProcStartCrimeDialog((INTEGER)_CrimeID,(STRING)_CrimeDialog,(INTEGER)_IsInteractive,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + THEN + DB_NOOP(1); + + PROC + ProcStartCrimeDialog((INTEGER)_CrimeID,(STRING)_CrimeDialog,1,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + DialogStartCrimeDialog(_CrimeID,_CrimeDialog,1,_NPC,_Criminal,_Criminal2,_Criminal3,_Criminal4,_Success) + THEN + DB_CheckInterrupt(_CrimeID,_NPC); + DB_CrimeWarner(_CrimeID,_NPC,_CrimeDialog); + ProcHandleCrimeDialog(_NPC,_Criminal,_Criminal2,_Criminal3,_Criminal4,_CrimeDialog,_Success,1); + + PROC + ProcStartCrimeDialog((INTEGER)_CrimeID,(STRING)_CrimeDialog,0,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + DialogStartCrimeDialog(_CrimeID,_CrimeDialog,0,_NPC,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,_Success) + AND + CrimeGetType(_CrimeID,_CrimeType) + THEN + DB_Crime_WarningAD_Target(_CrimeType,_NPC,_Criminal); // in AD we don't have player, so to clear Warning flags, store target player in this DB + DB_CheckInterrupt(_CrimeID,_NPC); + CrimeConfrontationDone(_CrimeID,_NPC); // confrontation done for ADs + ProcHandleCrimeDialog(_NPC,_Criminal,_Criminal2,_Criminal3,_Criminal4,_CrimeDialog,_Success,0); + DB_Interrupted(_CrimeID,_NPC,1); + + PROC + ProcCrimeInterruptStoryDialogs((INTEGER)_CrimeID,(STRING)_CrimeDialog,(INTEGER)_MarkForInteractive,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + NOT DB_Interrupted(_CrimeID,_NPC,1) + THEN + //NPC not available for dialog anymore + DB_Crime_FailedToInterruptStoryDialogs((INTEGER)_CrimeId,(STRING)_CrimeDialog,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4); + + PROC + ProcCrimeInterruptStoryDialogs((INTEGER)_CrimeID,(STRING)_CrimeDialog,(INTEGER)_MarkForInteractive,(CHARACTERGUID)_NPC,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + THEN + NOT DB_Interrupted(_CrimeID,_NPC,1); + //END_REGION + + //REGION -ForbiddenItem crime. Action Requests handling. + + /***************************************/ + //--- Crime reactions & Move crime + /***************************************/ + IF + DialogStarted("GEB_Warning_UseForbiddenItem",_Inst) + AND + DB_DialogPlayers(_Inst,_Player,1) + AND + DB_CRIME_ForbiddenStatus(_Status) + AND + HasActiveStatus(_Player,_Status,1) + THEN + RemoveStatus(_Player,_Status); + + IF + CharacterUsedSkillOnTarget(_Player,_Item,_,"teleportation") + AND + CharacterIsPlayer(_Player,1) + AND + ObjectIsItem(_Item,1) + AND + ItemCanSitOn((ITEMGUID)_Item,0) + AND + ItemGetOwner(_Item,_Owner) + AND + NOT QRY_CharacterIsNull(_Owner) + AND + CharacterIsPlayer(_Owner,0) + THEN + CharacterRegisterCrime(_Player,"MoveForbiddenItem",_Item,(CHARACTERGUID)_Owner,0); + + PROC + ProcCrimeTryRegisteringMoveForbiddenItem((CHARACTERGUID)_Player,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + CharacterIsPlayer(_Player,1) + AND + ItemCanSitOn(_Item,0) + AND + ItemGetOwner(_Item,_Owner) + AND + NOT QRY_CharacterIsNull(_Owner) + AND + CharacterIsPlayer(_Owner,0) + THEN + ProcSendMoveRequestResult(_Player,_Item,_RequestID); + CharacterRegisterCrime(_Player,"MoveForbiddenItem",_Item,(CHARACTERGUID)_Owner,0); + DB_MoveCrimeRegistered(1); + + PROC + ProcSendMoveRequestResult((CHARACTERGUID)_Player,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + GetPosition(_Item,_X,_Y,_Z) + AND + CrimeIsAnyNPCGoingToReact(_Player,"MoveForbiddenItem",_X,_Y,_Z,_Result) + AND + DB_Negate(_Result,_Inverse) + THEN + RequestProcessed(_Player,_RequestID,_Inverse); + + PROC + ProcCrimeTryRegisteringMoveForbiddenItem((CHARACTERGUID)_Player,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_MoveCrimeRegistered(1) + THEN + RequestProcessed(_Player,_RequestID,1); + + PROC + ProcCrimeTryRegisteringMoveForbiddenItem((CHARACTERGUID)_Player,(ITEMGUID)_Item,(INTEGER)_RequestID) + THEN + NOT DB_MoveCrimeRegistered(1); + + /***************************************/ + //--- REQUESTS + /***************************************/ + IF + CanUseItem(_Char,_Item,_RequestID) + THEN + ProcBlockUseOfItem(_Char,_Item); + ProcProcessUseOfItemWithStatus(_Char,_Item); + ProcProcessUseOfItem(_Char,_Item,_RequestID); + + IF + CanMoveItem(_Char,_Item,_RequestID) + THEN + ProcBlockMoveOfItem(_Char,_Item); + ProcProcessMoveOfItem(_Char,_Item,_RequestID); + + IF + CanPickupItem(_Char,_Item,_RequestID) + THEN + ProcBlockPickupOfItem(_Char,_Item); + ProcProcessPickupOfItem(_Char,_Item,_RequestID); + + IF + CanLockpickItem(_Char,_Item,_RequestID) + THEN + ProcBlockLockpickItem(_Char,_Item); + ProcProcessLockpickItem(_Char,_Item,_RequestID); + + IF + CanCombineItem(_Char,_ItemA,_ItemB,_ItemC,_ItemD,_ItemE,_RequestID) + THEN + ProcBlockCombineItem(_Char,_ItemA); + ProcBlockCombineItem(_Char,_ItemB); + ProcBlockCombineItem(_Char,_ItemC); + ProcBlockCombineItem(_Char,_ItemD); + ProcBlockCombineItem(_Char,_ItemE); + ProcProcessCombineItem(_Char,_ItemA,_ItemB,_ItemC,_ItemD,_ItemE,_RequestID); + + + /***************************************/ + //--- BLOCK ACTIONS + /***************************************/ + /* Catch one of the following PROCs to set the appropriate DB: + DB_CustomUseItemResponse((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_Result) + DB_CustomMoveItemResponse((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_Result) + DB_CustomPickupItemResponse((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_Result) + DB_CustomLockpickItemResponse((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_Result) + DB_CustomCombineItemResponse((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_Result) + */ + + PROC + ProcBlockUseOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item) + THEN + DB_NOOP(1); + + PROC + ProcBlockMoveOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item) + THEN + DB_NOOP(1); + + PROC + ProcBlockPickupOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item) + THEN + DB_NOOP(1); + + PROC + ProcBlockLockpickItem((CHARACTERGUID)_Char,(ITEMGUID)_Item) + THEN + DB_NOOP(1); + + PROC + ProcBlockCombineItem((CHARACTERGUID)_Char,(ITEMGUID)_Item) + THEN + DB_NOOP(1); + + + /***************************************/ + //--- BURNING AND ELECTRIFIED items apply status + /***************************************/ + PROC + ProcProcessUseOfItemWithStatus((CHARACTERGUID)_Char,(ITEMGUID)_Item) + AND + DB_IsPlayer(_Char) // apply only on player not to break story events with NPCs using items + AND + NOT DB_CustomUseItemResponse(_Char,_Item,0) // if handled in story, don't apply effect + AND + DB_ItemStatusAffectCharacterOnUse(_Status) + AND + HasActiveStatus(_Item,_Status,1) + AND + NOT QRYItemStatusIsNotAppliedToUser(_Item,_Status) + THEN + ApplyStatus(_Char,_Status,12.0); + + QRY + QRYItemStatusIsNotAppliedToUser((ITEMGUID)_Item,(STRING)_Status) + AND + _Status == "BURNING" + AND + ItemIsTorch(_Item,1) + THEN + DB_NOOP(1); + + /***************************************/ + //--- PROCESS + /***************************************/ + // Use + PROC + ProcProcessUseOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_CustomUseItemResponse(_Char,_Item,(INTEGER)_Result) + THEN + RequestProcessed(_Char,_RequestID,_Result); + + PROC + ProcProcessUseOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_CustomUseItemResponse(_Char,_Item,_) + AND + ItemCanSitOn(_Item,0) + AND + ItemIsLadder(_Item,0) + AND + ItemIsPublicDomain(_Item,0) + THEN + DB_HandledRequest(_Char,_Item,_RequestID); + ProcCrimeTryRegisteringUseForbiddenItem(_Char,_Item,_RequestID); + + PROC + ProcProcessUseOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_CustomUseItemResponse(_Char,_Item,_) + AND + NOT DB_HandledRequest(_Char,_Item,_RequestID) + THEN + RequestProcessed(_Char,_RequestID,1); + + PROC + ProcProcessUseOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_HandledRequest(_Char,_Item,_RequestID) + THEN + NOT DB_HandledRequest(_Char,_Item,_RequestID); + + // Move (registers MoveForbiddenItem instead of UseForbiddenItem) + PROC + ProcProcessMoveOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_CustomMoveItemResponse(_Char,_Item,(INTEGER)_Result) + THEN + RequestProcessed(_Char,_RequestID,_Result); + + PROC + ProcProcessMoveOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_CustomMoveItemResponse(_Char,_Item,_) + THEN + ProcCrimeTryRegisteringMoveForbiddenItem(_Char,_Item,_RequestID); + + // Pickup + PROC + ProcProcessPickupOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_CustomPickupItemResponse(_Char,_Item,(INTEGER)_Result) + THEN + RequestProcessed(_Char,_RequestID,_Result); + + PROC + ProcProcessPickupOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_CustomPickupItemResponse(_Char,_Item,_) + THEN + ProcCrimeTryRegisteringStealItem(_Char,_Item,_RequestID); + + // Lockpick + PROC + ProcProcessLockpickItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_CustomLockpickItemResponse(_Char,_Item,(INTEGER)_Result) + THEN + RequestProcessed(_Char,_RequestID,_Result); + + PROC + ProcProcessLockpickItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_CustomLockpickItemResponse(_Char,_Item,_) + THEN + ProcCrimeTryRegisteringUseForbiddenItem(_Char,_Item,_RequestID); + + // Combine + PROC + ProcProcessCombineItem(_Player,_ItemA,_ItemB,_ItemC,_ItemD,_ItemE,_RequestID) + AND + NOT QryCombineItemHasCustomResult(_Player,_ItemA,_ItemB,_ItemC,_ItemD,_ItemE) + AND + CharacterIsPlayer(_Player,1) + THEN + ProcCrimeCheckRegisterUseForbiddenItem(_Player,_ItemA,_RequestID); + ProcCrimeCheckRegisterUseForbiddenItem(_Player,_ItemB,_RequestID); + ProcCrimeCheckRegisterUseForbiddenItem(_Player,_ItemC,_RequestID); + ProcCrimeCheckRegisterUseForbiddenItem(_Player,_ItemD,_RequestID); + ProcCrimeCheckRegisterUseForbiddenItem(_Player,_ItemE,_RequestID); + + PROC + ProcProcessCombineItem((CHARACTERGUID)_Char,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE,(INTEGER)_RequestID) + AND + QryCombineItemHasCustomResult(_Char,_ItemA,_ItemB,_ItemC,_ItemD,_ItemE) + THEN + ProcProcessCustomCombineResponse(_Char,_ItemA,_ItemB,_ItemC,_ItemD,_ItemE,_RequestID); + + PROC + ProcProcessCustomCombineResponse((CHARACTERGUID)_Char,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE,(INTEGER)_RequestID) + AND + QryCombineItemIsBlocked(_Char,_ItemA,_ItemB,_ItemC,_ItemD,_ItemE) + THEN + RequestProcessed(_Char,_RequestID,0); + + PROC + ProcProcessCustomCombineResponse((CHARACTERGUID)_Char,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE,(INTEGER)_RequestID) + AND + NOT QryCombineItemIsBlocked(_Char,_ItemA,_ItemB,_ItemC,_ItemD,_ItemE) + THEN + RequestProcessed(_Char,_RequestID,1); + + + //--- General proc: + PROC + ProcCrimeTryRegisteringUseForbiddenItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + CharacterIsPlayer(_Char,1) + THEN + ProcCrimeCheckRegisterUseForbiddenItem(_Char,_Item,_RequestID); + + PROC + ProcCrimeTryRegisteringUseForbiddenItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + CharacterIsPlayer(_Char,0) + THEN + RequestProcessed(_Char,_RequestID,1); + + PROC + ProcCrimeTryRegisteringStealItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + CharacterIsPlayer(_Char,0) + THEN + DB_StealRequestHandled(1); + RequestProcessed(_Char,_RequestID,1); + + PROC + ProcCrimeTryRegisteringStealItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_StealRequestHandled(1) + AND + NOT QryCrimeItemHasNPCOwner(_Item) + THEN + DB_StealRequestHandled(1); + RequestProcessed(_Char,_RequestID,1); + + //we only register a crime here if they're going ot react, sicne we then block the pickup + //in the case they won't the reaction to the steal event will register the crime + PROC + ProcCrimeTryRegisteringStealItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_StealRequestHandled(1) + AND + ItemGetOwner(_Item,_Victim) + AND + CharacterIsPlayer(_Victim,0) + AND + GetPosition(_Item,_X,_Y,_Z) + AND + CrimeIsAnyNPCGoingToReact(_Char,"Steal",_X,_Y,_Z,1) + THEN + DB_StealRequestHandled(1); + RequestProcessed(_Char,_RequestID,0); + CharacterRegisterCrimeWithPosition(_Char,"Steal",_Item,_Victim,_X,_Y,_Z,0); + + PROC + ProcCrimeTryRegisteringStealItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_StealRequestHandled(1) + THEN + RequestProcessed(_Char,_RequestID,1); + + PROC + ProcCrimeTryRegisteringStealItem(_,_,_) + THEN + NOT DB_StealRequestHandled(1); + + /***************************************/ + //--- CLEAR custom response facts + /***************************************/ + PROC + ProcProcessUseOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_CustomUseItemResponse(_Char,_Item,_Result) + THEN + NOT DB_CustomUseItemResponse(_Char,_Item,_Result); + + PROC + ProcProcessMoveOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_CustomMoveItemResponse(_Char,_Item,_Result) + THEN + NOT DB_CustomMoveItemResponse(_Char,_Item,_Result); + + PROC + ProcProcessPickupOfItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_CustomPickupItemResponse(_Char,_Item,_Result) + THEN + NOT DB_CustomPickupItemResponse(_Char,_Item,_Result); + + PROC + ProcProcessLockpickItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_CustomLockpickItemResponse(_Char,_Item,_Result) + THEN + NOT DB_CustomLockpickItemResponse(_Char,_Item,_Result); + + PROC + ProcProcessCombineItem((CHARACTERGUID)_Char,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_CustomCombineItemResponse(_Char,_Item,_Result) + THEN + NOT DB_CustomCombineItemResponse(_Char,_Item,_Result); + + + /***************************************/ + //--- REGISTERING CRIMES and responding to the requests + /***************************************/ + PROC + ProcCrimeCheckRegisterUseForbiddenItem((CHARACTERGUID)_Player,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT QryCrimeItemHasNPCOwner(_Item) + AND + NOT DB_DontCreateUseForbiddenItem(_Item) + THEN + RequestProcessed(_Player,_RequestID,1); + + PROC + ProcCrimeCheckRegisterUseForbiddenItem((CHARACTERGUID)_Player,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + DB_DontCreateUseForbiddenItem(_Item) + THEN + RequestProcessed(_Player,_RequestID,1); + + PROC + ProcCrimeCheckRegisterUseForbiddenItem((CHARACTERGUID)_Player,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_DontCreateUseForbiddenItem(_Item) + AND + QryCrimeItemHasNPCOwner(_Item) + AND + HasActiveStatus(_Player,"SNEAKING",1) + THEN + DB_Crime_UseForbiddenItem(_Player,"SneakUseForbiddenItem",_Item); + RequestProcessed(_Player,_RequestID,1); + CharacterRegisterCrime(_Player,"SneakUseForbiddenItem",_Item,NULL_00000000-0000-0000-0000-000000000000,0); + + PROC + ProcCrimeCheckRegisterUseForbiddenItem((CHARACTERGUID)_Player,(ITEMGUID)_Item,(INTEGER)_RequestID) + AND + NOT DB_DontCreateUseForbiddenItem(_Item) + AND + QryCrimeItemHasNPCOwner(_Item) + AND + HasActiveStatus(_Player,"SNEAKING",0) + AND + GetPosition(_Item,_X,_Y,_Z) + AND + CrimeIsAnyNPCGoingToReact(_Player,"UseForbiddenItem",_X,_Y,_Z,_NPCWillReact) + THEN + ProcCrimeRegisterUseForbiddenItem(_Player,_Item,_RequestID,_NPCWillReact); + + PROC + ProcCrimeRegisterUseForbiddenItem((CHARACTERGUID)_Player,(ITEMGUID)_Item,(INTEGER)_RequestID,(INTEGER)_NPCWillReact) + AND + DB_Negate(_NPCWillReact,_Result) + THEN + DB_Crime_UseForbiddenItem(_Player,"UseForbiddenItem",_Item); + RequestProcessed(_Player,_RequestID,_Result); + CharacterRegisterCrime(_Player,"UseForbiddenItem",_Item,NULL_00000000-0000-0000-0000-000000000000,0); + + /***************************************/ + //--- CHECK CRIME REACTIONS + /***************************************/ + /* + IF + CharacterOnCrimeSensibleActionNotification(_,_,_CrimeID,_,_,_,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + CrimeGetType(_CrimeID,"UseForbiddenItem") + THEN + ProcCrimeForbiddenItemGetEvidence(_CrimeID,_Criminal1,"UseForbiddenItem"); + + IF + CharacterOnCrimeSensibleActionNotification(_,_,_CrimeID,_,_,_,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + CrimeGetType(_CrimeID,"SneakUseForbiddenItem") + THEN + ProcCrimeForbiddenItemGetEvidence(_CrimeID,_Criminal1,"SneakUseForbiddenItem"); + */ + + IF + OnCrimeConfrontationDone(_CrimeID,_Investigator,1,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + CrimeGetType(_CrimeID,"UseForbiddenItem") + THEN + ProcCrimeForbiddenItemGetEvidence(_CrimeID,_Criminal1,"UseForbiddenItem"); + + IF + OnCrimeConfrontationDone(_CrimeID,_Investigator,1,_Criminal1,_Criminal2,_Criminal3,_Criminal4) + AND + CrimeGetType(_CrimeID,"SneakUseForbiddenItem") + THEN + ProcCrimeForbiddenItemGetEvidence(_CrimeID,_Criminal1,"SneakUseForbiddenItem"); + + PROC + ProcCrimeForbiddenItemGetEvidence((INTEGER)_CrimeID,(CHARACTERGUID)_Criminal,(STRING)_CrimeType) + AND + NOT QRY_CharacterIsNull(_Criminal) + AND + CrimeGetNumberOfEvidence(_CrimeID,_NumEvidence) + AND + _NumEvidence > 0 + AND + CrimeGetEvidence(_CrimeID,1,(ITEMGUID)_Item) + THEN + ProcCrimeStopForbiddenItem(_Criminal,_CrimeType,_Item); + + PROC + ProcCrimeForbiddenItemGetEvidence((INTEGER)_CrimeID,(CHARACTERGUID)_Criminal,(STRING)_CrimeType) + AND + NOT QRY_CharacterIsNull(_Criminal) + AND + CrimeGetNumberOfEvidence(_CrimeID,_NumEvidence) + AND + _NumEvidence < 1 + THEN + ProcCrimeStopForbiddenItem(_Criminal,_CrimeType,NULL_00000000-0000-0000-0000-000000000000); + + PROC + ProcCrimeStopForbiddenItem((CHARACTERGUID)_Criminal,(STRING)_CrimeType,(ITEMGUID)_Evidence) + THEN + CharacterStopCrime(_Criminal,_CrimeType,_Evidence); + + PROC + ProcCrimeStopForbiddenItem((CHARACTERGUID)_Criminal,(STRING)_CrimeType,(ITEMGUID)_Evidence) + AND + DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Evidence) + THEN + NOT DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Evidence); + + + /***************************************/ + //--- STOPPING CRIMES + /***************************************/ + IF + CharacterStoppedUsingItem(_Player,_Item) + AND + DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item) + THEN + NOT DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item); + CharacterStopCrime(_Player,_CrimeType,_Item); + + /* + IF + CharacterMovedItem(_Player,_Item) + CharacterStoppedMovingItem(_Player,_Item) + AND + DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item) + THEN + NOT DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item); + CharacterStopCrime(_Player,_CrimeType,_Item); + + IF + CharacterStoppedPickingUpItem(_Player,_Item) + AND + DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item) + THEN + NOT DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item); + CharacterStopCrime(_Player,_CrimeType,_Item); + + IF + CharacterStoppedLockpickingItem(_Player,_Item) + AND + DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item) + THEN + NOT DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item); + CharacterStopCrime(_Player,_CrimeType,_Item); + */ + + IF + CharacterStoppedCombiningItems(_Player,_ItemA,_ItemB,_ItemC,_ItemD,_ItemE) + THEN + ProcCrimeStopCombineItemCrime(_Player,_ItemA); + ProcCrimeStopCombineItemCrime(_Player,_ItemB); + ProcCrimeStopCombineItemCrime(_Player,_ItemC); + ProcCrimeStopCombineItemCrime(_Player,_ItemD); + ProcCrimeStopCombineItemCrime(_Player,_ItemE); + + PROC + ProcCrimeStopCombineItemCrime((CHARACTERGUID)_Player,(ITEMGUID)_Item) + AND + DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item) + THEN + CharacterStopCrime(_Player,_CrimeType,_Item); + + QRY + QryCrimeClearCombineItemBD((CHARACTERGUID)_Player,(STRING)_CrimeType) + AND + DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item) + THEN + NOT DB_Crime_UseForbiddenItem(_Player,_CrimeType,_Item); + + + /***************************************/ + //--- QUERIES + /***************************************/ + + QRY + QryCrimeIsValidItemRequest((CHARACTERGUID)_Char,(ITEMGUID)_Item) + AND + CharacterIsPlayer(_Char,0) + THEN + DB_NOOP(1); + + QRY + QryCrimeIsValidItemRequest((CHARACTERGUID)_Char,(ITEMGUID)_Item) + AND + CharacterIsPlayer(_Char,1) + AND + NOT QryCrimeItemHasNPCOwner((ITEMGUID)_Item) + THEN + DB_NOOP(1); + + QRY + QryCrimeCombinedItemsAreValid((ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + NOT QryCrimeItemHasNPCOwner(_ItemA) + AND + NOT QryCrimeItemHasNPCOwner(_ItemB) + AND + NOT QryCrimeItemHasNPCOwner(_ItemC) + AND + NOT QryCrimeItemHasNPCOwner(_ItemD) + AND + NOT QryCrimeItemHasNPCOwner(_ItemE) + THEN + DB_NOOP(1); + + QRY + QryCrimeItemHasNPCOwner((ITEMGUID)_Item) + AND + ItemGetOwner(_Item,_Char) + AND + NOT QRY_CharacterIsNull(_Char) + AND + CharacterIsPlayer(_Char,0) + THEN + DB_NOOP(1); + + /**** Combine item custom result ****/ + QRY + QryCombineItemHasCustomResult((CHARACTERGUID)_Player,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + DB_CustomCombineItemResponse(_Player,_ItemA,_) + THEN + DB_NOOP(1); + + QRY + QryCombineItemHasCustomResult((CHARACTERGUID)_Player,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + DB_CustomCombineItemResponse(_Player,_ItemB,_) + THEN + DB_NOOP(1); + + QRY + QryCombineItemHasCustomResult((CHARACTERGUID)_Player,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + DB_CustomCombineItemResponse(_Player,_ItemC,_) + THEN + DB_NOOP(1); + + QRY + QryCombineItemHasCustomResult((CHARACTERGUID)_Player,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + DB_CustomCombineItemResponse(_Player,_ItemD,_) + THEN + DB_NOOP(1); + + QRY + QryCombineItemHasCustomResult((CHARACTERGUID)_Player,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + DB_CustomCombineItemResponse(_Player,_ItemE,_) + THEN + DB_NOOP(1); + + + /**** Combine item is blocked ****/ + QRY + QryCombineItemIsBlocked((CHARACTERGUID)_Player,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + DB_CustomCombineItemResponse(_Player,_ItemA,1) + THEN + DB_NOOP(1); + + QRY + QryCombineItemIsBlocked((CHARACTERGUID)_Player,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + DB_CustomCombineItemResponse(_Player,_ItemB,1) + THEN + DB_NOOP(1); + + QRY + QryCombineItemIsBlocked((CHARACTERGUID)_Player,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + DB_CustomCombineItemResponse(_Player,_ItemC,1) + THEN + DB_NOOP(1); + + QRY + QryCombineItemIsBlocked((CHARACTERGUID)_Player,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + DB_CustomCombineItemResponse(_Player,_ItemD,1) + THEN + DB_NOOP(1); + + QRY + QryCombineItemIsBlocked((CHARACTERGUID)_Player,(ITEMGUID)_ItemA,(ITEMGUID)_ItemB,(ITEMGUID)_ItemC,(ITEMGUID)_ItemD,(ITEMGUID)_ItemE) + AND + DB_CustomCombineItemResponse(_Player,_ItemE,1) + THEN + DB_NOOP(1); + + //END_REGION + + //----------------------------------- CUSTOM ----------------------------------- + //REGION Override Sensible Action + + // ------ Setting + PROC + ProcCrimeSetAllCustomSensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName,(STRING)_CustomReactionName) + THEN + ProcCrimeSetCustomPrimarySensibleAction(_Character,_CrimeName,_CustomReactionName); + ProcCrimeSetCustomSecondarySensibleAction(_Character,_CrimeName,_CustomReactionName); + + + // Primary + PROC + ProcCrimeSetCustomPrimarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName,(STRING)_CustomReactionName) + AND + DB_CrimeReaction_CustomSensibleAction(_Character,_CrimeName,1) + AND + StringConcatenate("Setting a custom primary sensible action [",_CustomReactionName,_Part1) + AND + StringConcatenate(_Part1,"] on a character that already have one for crime: ",_Part2) + AND + StringConcatenate(_Part2,_CrimeName,_Message) + THEN + DebugBreak(_Message); + + PROC + ProcCrimeSetCustomPrimarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName,(STRING)_) + THEN + DB_CrimeReaction_CustomSensibleAction(_Character,_CrimeName,1); + + PROC + ProcCrimeSetCustomPrimarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName,(STRING)_CustomReactionName) + AND + _CustomReactionName == "" + THEN + ProcCrimeSetCustomSensibleActionVariable(_Character,_CrimeName,"CRIME_UndefinedSensibleAction","Primary_"); + + PROC + ProcCrimeSetCustomPrimarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName,(STRING)_CustomReactionName) + AND + _CustomReactionName != "" + THEN + ProcCrimeSetCustomSensibleActionVariable(_Character,_CrimeName,_CustomReactionName,"Primary_"); + + + // Secondary + PROC + ProcCrimeSetCustomSecondarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName,(STRING)_CustomReactionName) + AND + DB_CrimeReaction_CustomSensibleAction(_Character,_CrimeName,0) + AND + StringConcatenate("Setting a custom secondary sensible action [",_CustomReactionName,_Part1) + AND + StringConcatenate(_Part1,"] on a character that already have one for crime: ",_Part2) + AND + StringConcatenate(_Part2,_CrimeName,_Message) + THEN + DebugBreak(_Message); + + PROC + ProcCrimeSetCustomSecondarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName,(STRING)_) + THEN + DB_CrimeReaction_CustomSensibleAction(_Character,_CrimeName,0); + + PROC + ProcCrimeSetCustomSecondarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName,(STRING)_CustomReactionName) + AND + _CustomReactionName == "" + THEN + ProcCrimeSetCustomSensibleActionVariable(_Character,_CrimeName,"CRIME_UndefinedSensibleAction","Secondary_"); + + PROC + ProcCrimeSetCustomSecondarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName,(STRING)_CustomReactionName) + AND + _CustomReactionName != "" + THEN + ProcCrimeSetCustomSensibleActionVariable(_Character,_CrimeName,_CustomReactionName,"Secondary_"); + + PROC + ProcCrimeSetCustomSensibleActionVariable((CHARACTERGUID)_Character,(STRING)_CrimeName,(STRING)_CustomReactionName,(STRING)_Type) + AND + StringConcatenate("Custom",_Type,_Prefix) + AND + StringConcatenate(_Prefix,_CrimeName,_VarName) + THEN + SetVarFixedString(_Character,_VarName,_CustomReactionName); + + + // --- Clearing + PROC + ProcCrimeClearCustomPrimarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName) + AND + StringConcatenate("CustomPrimary_",_CrimeName,_VarName) + THEN + SetVarFixedString(_Character,_VarName,""); + + PROC + ProcCrimeClearCustomPrimarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName) + AND + DB_CrimeReaction_CustomSensibleAction(_Character,_CrimeName,1) + THEN + NOT DB_CrimeReaction_CustomSensibleAction(_Character,_CrimeName,1); + + PROC + ProcCrimeClearCustomSecondarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName) + AND + StringConcatenate("CustomSecondary_",_CrimeName,_VarName) + THEN + SetVarFixedString(_Character,_VarName,""); + + PROC + ProcCrimeClearCustomSecondarySensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName) + AND + DB_CrimeReaction_CustomSensibleAction(_Character,_CrimeName,0) + THEN + NOT DB_CrimeReaction_CustomSensibleAction(_Character,_CrimeName,0); + + PROC + ProcCrimeClearAllCustomSensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName) + AND + StringConcatenate("CustomPrimary_",_CrimeName,_PrimaryVarName) + AND + StringConcatenate("CustomSecondary_",_CrimeName,_SecondaryVarName) + THEN + SetVarFixedString(_Character,_PrimaryVarName,""); + SetVarFixedString(_Character,_SecondaryVarName,""); + + PROC + ProcCrimeClearAllCustomSensibleAction((CHARACTERGUID)_Character,(STRING)_CrimeName) + AND + DB_CrimeReaction_CustomSensibleAction(_Character,_CrimeName,_Type) + THEN + NOT DB_CrimeReaction_CustomSensibleAction(_Character,_CrimeName,_Type); + + + // --- Throwing a proc to allow reacting in story + IF + CharacterOnCrimeSensibleActionNotification(_NPC,_Region,_CrimeID,_PriorityName,_Dialog,_Criminal,_Criminal2,_Criminal3,_Criminal4,_IsPrimary) + AND + CrimeGetType(_CrimeID,_CrimeName) + AND + DB_CrimeReaction_CustomSensibleAction(_NPC,_CrimeName,_IsPrimary) + THEN + ProcCrimeOnCustomSensibleAction(_NPC,_Region,_CrimeID,_PriorityName,_Dialog,_Criminal,_Criminal2,_Criminal3,_Criminal4,_IsPrimary); + + PROC + ProcCrimeOnCustomSensibleAction((CHARACTERGUID)_NPC, (STRING)_RegionID, (INTEGER)_CrimeID, (STRING)_PriorityName, (STRING)_PrimaryDialog, (CHARACTERGUID)_Criminal1, (CHARACTERGUID)_Criminal2, (CHARACTERGUID)_Criminal3, (CHARACTERGUID)_Criminal4, (INTEGER)_IsPrimary) + THEN + DB_NOOP(1); + + /** + * IMPORTANT! Call this event on the NPC who's reacting to the crime: + + SetStoryEvent(_NPC,"Crime_CustomSensibleActionDone"); + + */ + //END_REGION + + //REGION Override investigation + + /* Put your character in this fact to disable the interractive interrogation dialog: + DB_CrimeReaction_DoNotInterrogate(_Interrogator) + */ + + IF + DB_CrimeReaction_DoNotInterrogate((CHARACTERGUID)_Char) + THEN + DB_Crime_CheckInterrogate(_Char); + CrimeEnableInterrogation(_Char,0); + + IF + DB_Crime_CheckInterrogate(_Char) + AND + NOT DB_CrimeReaction_DoNotInterrogate(_Char) + THEN + NOT DB_Crime_CheckInterrogate(_Char); + CrimeEnableInterrogation(_Char,1); + + PROC + ProcCrimeSetCustomInvestigationAD((CHARACTERGUID)_Character,(STRING)_Dialog) + THEN + SetVarString(_Character,"CRIME_InvestigateAD",_Dialog); + + + //END_REGION + + //REGION Linked crimes + PROC + ProcCharacterDisableCrime((CHARACTERGUID)_Char,_Crime) + AND + DB_LinkedCrimes(_Crime,_LinkedCrime) + THEN + DB_CharacterCrimeDisabled(_Char,_LinkedCrime); + CharacterDisableCrime(_Char,_LinkedCrime); + + PROC + ProcCharacterEnableCrime((CHARACTERGUID)_Char,_Crime) + AND + DB_LinkedCrimes(_Crime,_LinkedCrime) + THEN + DB_CharacterCrimeEnabled(_Char,_LinkedCrime); + CharacterEnableCrime(_Char,_LinkedCrime); + + IF + DB_CrimeAttitudeChange("Assault",_Amount) + THEN + DB_CrimeAttitudeChange("IncapacitatedAssault",_Amount); + + //END_REGION + + + //REGION Zero-tension crimes without fleeing + // Zero-tension crimes that don't cause people to flee explicitly should not cause people to + // return to their starting position at the end (DOSTWO-24283) + IF + CharacterOnCrimeSensibleActionNotification(_Char,_,_ID,_Reaction,_,_,_,_,_,_) + AND + DB_CRIME_FleeReaction(_Rection) + AND + CrimeGetTension(_ID,0) + THEN + DB_CRIME_ZeroTensionFlee(_ID,_Char); + + IF + OnCrimeConfrontationDone(_ID,_Investigator,_,_,_,_,_) + AND + CrimeGetTension(_ID,0) + AND + NOT DB_CRIME_ZeroTensionFlee(_ID,_Investigator) + THEN + SetStoryEvent(_Investigator,"ClearCrimeReturnPos"); + + IF + OnCrimeConfrontationDone(_ID,_Investigator,_,_,_,_,_) + THEN + NOT DB_CRIME_ZeroTensionFlee(_ID,_Investigator); + //END_REGION + + } + EXIT + { + + + } +} +Goal(16).Title("_CRIME_ItemOwnership"); +Goal(16) +{ + INIT + { + DB_ItemOwnerShipIgnoreTemplates("LTS_Campfire_A_6fee7bbb-4adc-4222-a5b1-82fcfb8d1230"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Campfire_B_130692f2-a065-4168-be66-27cf4df2fff0"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Campfire_C_1086cce2-9164-4746-b3c3-2f8c943cb8fc"); + DB_ItemOwnerShipIgnoreTemplates("FUR_Humans_Camping_Sleepingbag_A_d76d0118-23cd-42af-b693-449c96c71d6d"); + DB_ItemOwnerShipIgnoreTemplates("FUR_Humans_Citz_Mattress_A_DarkBrown_eae64571-4e99-4036-b3e2-1dcc6da78c89"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_A_f21393ff-31bc-46ff-a024-985e72cd83f5"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_B_d5e83188-69f5-428f-8bca-64f00b441aef"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_C_b98b4f53-5cf3-46b1-8ecd-278f178a9816"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_D_511c5c17-2ed0-4b2e-a4b5-425621cb61ac"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_E_f497d3af-8837-4183-9bf4-aef2ef1145d1"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_F_0121d78b-8831-4607-9c2f-db63edcdfbb6"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_G_83e373a2-ca7b-4c35-8761-d04605aaabca"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_H_49acf8f4-946e-4f62-a12e-e85d332f3d96"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_I_728b84a6-3929-48eb-9368-631a0614e38d"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_J_b8b63ed1-7c28-4c68-90b2-e83db433467b"); + DB_ItemOwnerShipIgnoreTemplates("LTS_Candle_K_ef4d1dd9-8d2a-4677-98c3-bb9dd52c0865"); + DB_ItemOwnerShipIgnoreTemplates("BOOK_ARX_Letter_B_ShadyTraderAd_cb5bd6ad-ae01-4ba9-bd95-752f9d659316"); + + } + KB + { + PROC + PROC_Init_SetItemOwners((STRING)_Region) + AND + DB_ItemOwnerShipTriggers(_Region,_Trigger,_Owner) + THEN + TriggerSetItemOwner(_Trigger,_Owner); + ProcTriggerRegisterForPlayers(_Trigger); + NOT DB_ItemOwnerShipTriggers(_Region,_Trigger,_Owner); + DB_TempItemOwnerShipTrigger(_Region,_Trigger); + DB_OwnershipTrigger(_Trigger); + + PROC + PROC_Init_ClearItemOwners((STRING)_Region) + AND + DB_ItemOwnerShipClearItem(_Region,_Item) + THEN + ItemClearOwner(_Item); + NOT DB_ItemOwnerShipClearItem(_Region,_Item); + + PROC + PROC_Init_ClearItemOwners((STRING)_Region) + AND + DB_TempItemOwnerShipTrigger((STRING)_Region,(TRIGGERGUID)_Trigger) + AND + DB_ItemOwnerShipIgnoreTemplates(_Temp) + THEN + NOT DB_TempItemOwnerShipTrigger(_Region,_Trigger); + TriggerClearItemTemplateOwners(_Trigger,_Temp); + + IF + DB_ItemOwnerShipTriggers(_Region,_Trigger,_Owner) + AND + DB_CurrentLevel(_Region) + THEN + PROC_Init_SetItemOwners(_Region); + PROC_Init_ClearItemOwners(_Region); + + IF + RegionStarted(_Region) + THEN + PROC_Init_SetItemOwners(_Region); + PROC_Init_ClearItemOwners(_Region); + + } + EXIT + { + + } +} +Goal(17).Title("_CRIME_Prison"); +Goal(17) +{ + INIT + { + //Setting up Flags for the Arrest Dialogs + DB_ArrestDialogFlags("Assault","GEB_Arrest_Assault"); + DB_ArrestDialogFlags("SpiritTalk","GEB_Arrest_Source"); + DB_ArrestDialogFlags("SourceMagic","GEB_Arrest_Source"); + DB_ArrestDialogFlags("Steal","GEB_Arrest_Theft"); + DB_ArrestDialogFlags("PickPocketFailed","GEB_Arrest_Theft"); + DB_ArrestDialogFlags("PickPocket","GEB_Arrest_Theft"); + DB_ArrestDialogFlags("ItemDestroy","GEB_Arrest_Vandalise"); + DB_ArrestDialogFlags("Vandalise","GEB_Arrest_Vandalise"); + DB_ArrestDialogFlags("VandaliseNoOwner","GEB_Arrest_Vandalise"); + DB_ArrestDialogFlags("Trespassing","GEB_Arrest_Trespassing"); + DB_ArrestDialogFlags("UseForbiddenItem","GEB_Arrest_UseForbiddenItem"); + DB_ArrestDialogFlags("SneakUseForbiddenItem","GEB_Arrest_UseForbiddenItem"); + + DB_ReactOutOfRegion("RED PRINCE"); + DB_ReactOutOfRegion("IFAN"); + DB_ReactOutOfRegion("LOHSE"); + DB_ReactOutOfRegion("SEBILLE"); + DB_ReactOutOfRegion("BEAST"); + DB_ReactOutOfRegion("FANE"); + DB_ReactOutOfRegion("AGGRESSIVEANIMAL"); + + } + KB + { + IF + DB_RegionPrison(_RegionName,(TRIGGERGUID)_PrisonTrigger) + THEN + ProcTriggerRegisterForPlayers(_PrisonTrigger); + + QRY + QryNPCIsGuard((GUIDSTRING)_NPC) + AND + IsTagged(_Npc,"GUARD",1) + THEN + DB_Noop(1); + + QRY + QryNPCIsGuard((GUIDSTRING)_NPC) + AND + IsTagged(_Npc,"PALADIN",1) + THEN + DB_Noop(1); + + QRY + QryNPCIsGuard((GUIDSTRING)_NPC) + AND + IsTagged(_Npc,"MAGISTER",1) + THEN + DB_Noop(1); + + //REGION Start Arrest + //Wait for dialog to end to arrest Player // Needs to be removed + IF + ObjectFlagSet("Start_Arrest_AfterDialog",(CHARACTERGUID)_Character,_ID) + THEN + ObjectClearFlag(_Character,"Start_Arrest_AfterDialog",0); + DB_ArrestAfterDialog(_Character,_ID); + + + ///////// Handle Evidence //////////// + IF + ObjectFlagSet("Allow_Arrest",(CHARACTERGUID)_Player,_ID) + THEN + DB_ArrestDialog(_Player,_ID); + + IF + DialogEnded(_,_ID) + AND + DB_ArrestDialog(_Player,_ID) + AND + DB_DialogNPCs(_ID,_NPC,1) + AND + ObjectGetFlag((CHARACTERGUID)_NPC,"CRIME_FoundEvidenceCurrentCrime",1) + AND + DB_Interrogation(_NPC,_CrimeID) + THEN + ProcCrimeHandleEvidence(_Player,_NPC,_CrimeID); + + PROC + ProcCrimeHandleEvidence((CHARACTERGUID)_Player,(CHARACTERGUID)_Arrester,(INTEGER)_CrimeID) + AND + CharacterGetCrimeRegion(_Player,_CrimeRegionID) + AND + DB_RegionPrison(_CrimeRegionID,_PrisonTrigger) + AND + DB_PrisonEvidenceChest((TRIGGERGUID)_PrisonTrigger,(ITEMGUID)_EvidenceChest) + THEN + CrimeTransferEvidenceTo(_CrimeID,_EvidenceChest); + + PROC + ProcCrimeHandleEvidence((CHARACTERGUID)_Player,(CHARACTERGUID)_Arrester,(INTEGER)_CrimeID) + AND + CharacterGetCrimeRegion(_Player,_CrimeRegionID) + AND + DB_RegionPrison(_CrimeRegionID,_PrisonTrigger) + AND + NOT DB_PrisonEvidenceChest((TRIGGERGUID)_PrisonTrigger,_) + THEN + CrimeTransferEvidenceTo(_CrimeID,_Arrester); + + + ///////// Start Arrest //////////// + IF + DialogEnded(_,_ID) + AND + DB_ArrestAfterDialog(_Character,_ID) + THEN + NOT DB_ArrestAfterDialog(_Character,_ID); + ProcCrimeStartArrest((CHARACTERGUID)_Character,_ID); + + PROC + ProcCrimeStartArrest((CHARACTERGUID)_Character,(INTEGER)_ID) + AND + CharacterGetCrimeRegion(_Character,_CrimeRegion) + THEN + ProcCrimeDoPerformArrest(_ID,_CrimeRegion); + + PROC + ProcCrimeDoPerformArrest((INTEGER)_Inst,(STRING)_Region) + AND + DB_DialogNPCs(_Inst,_Player,_) + AND + CharacterIsPlayer((CHARACTERGUID)_Player,1) + THEN + ProcCrimePerformArrest(_Player,_Region); + + PROC + ProcCrimeDoPerformArrest((INTEGER)_Inst,(STRING)_Region) + AND + DB_DialogPlayers(_Inst,_Player,_) + AND + CharacterIsPlayer((CHARACTERGUID)_Player,1) + THEN + ProcCrimePerformArrest(_Player,_Region); + + PROC + ProcCrimePerformArrest((CHARACTERGUID)_Character,(STRING)_CrimeRegionID) + AND + DB_RegionPrison(_CrimeRegionID,_PrisonTrigger) + THEN + ProcCrimeTeleportCharacterToPrison(_Character,_PrisonTrigger); + + PROC //--- can be used outside of the Crime System + ProcCrimeTeleportCharacterToPrison((CHARACTERGUID)_Character,(TRIGGERGUID)_PrisonTrigger) + THEN + ObjectSetFlag(_Character,"IsInPrison"); + RemoveStatus(_Character,"FUGITIVE"); + CharacterDetachFromGroup(_Character); + Proc_TeleportSmoke(_Character); + TeleportTo(_Character,_PrisonTrigger,"",0); + Proc_TeleportSmoke(_Character); + DB_IsArrested(_Character); + CharacterFlushQueue(_Character); + LeaveCombat(_Character); + CharacterRemoveTension(_Character); + + PROC + ProcCrimeTeleportCharacterToPrison((CHARACTERGUID)_Character,(TRIGGERGUID)_PrisonTrigger) + AND + DB_PrisonChest((TRIGGERGUID)_PrisonTrigger,(ITEMGUID)_PrisonChest) + THEN + MoveAllItemsTo(_Character,_PrisonChest,0,1,1); + + //END_REGION + + //REGION Arrest dialog starting + + IF + CharacterOnCrimeSensibleActionNotification(_Arrester,_,_CrimeID,"CRIME_Arrest",_,_,_,_,_,_) + AND + CrimeGetType(_CrimeID,_CrimeName) + AND + NOT DB_CrimeReaction_CustomSensibleAction(_Arrester,_CrimeName) + THEN + Proc_StartArrestDialog(_Arrester); + + IF + StoryEvent(_Arrester,"ArrestOnRequest") + AND + GetVarInteger(_Arrester,"CrimeID",_CrimeID) + THEN + SetVarString(_Arrester,"ArrestDialog","GEB_Arrest"); + ProcStartArrest((CHARACTERGUID)_Arrester,(INTEGER)_CrimeID); + + IF + StoryEvent((CHARACTERGUID)_Arrester,"ArrestOnRequest") + AND + DB_Arresting(_Arrester,_CrimeID,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,_ArrestDialog) + THEN + CharacterMoveToAndTalk(_Arrester,_Criminal1,"",0,"GEB_ArrestMove",1,10.0); + + IF + StoryEvent((CHARACTERGUID)_Arrester, "CRIME_Perform_Arrest") + AND + GetVarInteger(_Arrester,"CrimeID",_CrimeID) + THEN + ProcStartArrest(_Arrester,_CrimeID); + + PROC + ProcStartArrest((CHARACTERGUID)_Arrester,(INTEGER)_CrimeID) + AND + GetVarObject(_Arrester,"Criminal1",_Criminal1) + AND + GetVarObject(_Arrester,"Criminal2",_Criminal2) + AND + GetVarObject(_Arrester,"Criminal3",_Criminal3) + AND + GetVarObject(_Arrester,"Criminal4",_Criminal4) + AND + GetVarString(_Arrester,"ArrestDialog",_ArrestDialog) + THEN + DB_Arresting(_Arrester,_CrimeID,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,_ArrestDialog); + SetHasDialog(_Arrester,0); + CharacterDisableAllCrimes(_Arrester); + DialogRequestStop(_Arrester); + + IF + DialogEnded(_,_Instance) + AND + DB_DialogPlayers(_Instance,_Criminal,1) + AND + DB_Arresting(_Arrester,_CrimeID,(CHARACTERGUID)_Criminal,_,_,_,_ArrestDialog) + THEN + CharacterMoveToAndTalk(_Arrester,_Criminal,"",0,"GEB_ArrestMove",1,10.0); + + PROC + ProcStartArrest((CHARACTERGUID)_Arrester,(INTEGER)_CrimeID) + AND + NOT DB_Arresting(_Arrester,_CrimeID,_,_,_,_,_) + THEN + CrimeConfrontationDone(_CrimeID,_Arrester); + + PROC + ProcCleanupArrest((CHARACTERGUID)_Arrester) + AND + DB_Arresting(_Arrester,_CrimeID,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_ArrestDialog) + THEN + ProcRestoreFightMode(_Arrester); + ProcRestoreGenericBehaviour(_Arrester); + SetHasDialog(_Arrester,1); + NOT DB_Arresting(_Arrester,_CrimeID,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_ArrestDialog); + SetStoryEvent(_Arrester,"CRIME_StartArrest"); + + IF + CharacterMoveToAndTalkRequestDialog(_Arrester,(CHARACTERGUID)_Criminal,_,_,"GEB_ArrestMove") + AND + DB_Arresting(_Arrester,_CrimeID,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_ArrestDialog) + THEN + SetStoryEvent(_Arrester,"CRIME_StartArrest"); + Proc_StartArrestDialog(_Arrester,_CrimeID,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_ArrestDialog); + + IF + CharacterMoveToAndTalkFailed(_Arrester,_,"GEB_ArrestMove") + AND + DB_Arresting(_Arrester,_CrimeID,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_ArrestDialog) + THEN + CrimeConfrontationDone(_CrimeID,_Arrester); + ProcCleanupArrest(_Arrester); + + IF + DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_ArrestDialog,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4) + AND + DB_Arresting(_Arrester,_CrimeID,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_ArrestDialog) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Arrester,_Criminal,"GEB_ArrestMove"); + + IF + ObjectFlagSet(_ActiveFlag,(CHARACTERGUID)_Arrester,_) + AND + DB_ArrestDialogFlags(_CrimeName,_ActiveFlag) + AND + DB_Arresting(_Arrester,_CrimeID,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_ArrestDialog) + THEN + ProcCleanupArrest(_Arrester); + + IF + ObjectEnteredCombat((CHARACTERGUID)_Arrester,_) + AND + DB_Arresting(_Arrester,_,_,_,_,_,_) + THEN + ProcCleanupArrest(_Arrester); + + PROC + Proc_StartArrestDialog((CHARACTERGUID)_Arrester) + AND + GetVarObject(_Arrester,"Criminal1",(CHARACTERGUID)_Criminal1) + AND + GetVarObject(_Arrester,"Criminal2",(CHARACTERGUID)_Criminal2) + AND + GetVarObject(_Arrester,"Criminal3",(CHARACTERGUID)_Criminal3) + AND + GetVarObject(_Arrester,"Criminal4",(CHARACTERGUID)_Criminal4) + AND + GetVarInteger(_Arrester,"CrimeID",_CrimeID) + AND + GetVarString(_Arrester,"ArrestDialog",_ArrestDialog) + THEN + Proc_StartArrestDialog(_Arrester,_CrimeID,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_ArrestDialog); + + PROC + Proc_StartArrestDialog((CHARACTERGUID)_Arrester,(INTEGER)_CrimeID,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_ArrestDialog) + THEN + ObjectClearFlag(_Arrester,"GEB_Arrest_HavePrison",0); + + PROC + Proc_StartArrestDialog((CHARACTERGUID)_Arrester,(INTEGER)_CrimeID,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_ArrestDialog) + AND + DB_ArrestDialogFlags(_CrimeName,_ActiveFlag) + AND + ObjectGetFlag(_Arrester,_ActiveFlag,1) + THEN + ObjectClearFlag(_Arrester,_ActiveFlag,0); + + PROC + Proc_StartArrestDialog((CHARACTERGUID)_Arrester,(INTEGER)_CrimeID,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_ArrestDialog) + AND + CrimeGetType(_CrimeID,_CrimeName) + AND + DB_ArrestDialogFlags(_CrimeName,_ActiveFlag) + THEN + ObjectSetFlag(_Arrester,_ActiveFlag); + + + //--- Setup the Arrester's script + PROC + Proc_StartArrestDialog((CHARACTERGUID)_Arrester,(INTEGER)_CrimeID,(CHARACTERGUID)_Criminal1,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,(STRING)_ArrestDialog) + AND + GetVarFixedString(_Arrester,"RegionID",_RegionID) + AND + CrimeGetType(_CrimeID,_CrimeType) + THEN + ProcCrimeSetupCountFlag(_CrimeID,_Arrester,_Criminal1,_Criminal2,_Criminal3,_Criminal4,_CrimeType,_ArrestDialog); + ProcCrimeStartRegionArrestInterrogation(_RegionID,_CrimeID,_ArrestDialog,_Arrester,_Criminal1,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCheckStartArrestInterrogation((INTEGER)_CrimeID,(STRING)_ArrestDialog,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + NOT DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_ArrestDialog,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4) + THEN + ProcCrimeStartArrestInterrogation(_CrimeID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4,1); + + PROC + ProcCheckStartArrestInterrogation((INTEGER)_CrimeID,(STRING)_ArrestDialog,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_ArrestDialog,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4) + THEN + ProcCrimeStartArrestInterrogation(_CrimeID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4,0); + NOT DB_Crime_FailedToInterruptStoryDialogs(_CrimeID,_ArrestDialog,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeStartRegionArrestInterrogation((STRING)_RegionID,(INTEGER)_CrimeID,(STRING)_ArrestDialog,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + DB_RegionPrison(_RegionID,_) + THEN + ObjectSetFlag(_Arrester,"GEB_Arrest_HavePrison"); + + PROC + ProcCrimeStartRegionArrestInterrogation((STRING)_RegionID,(INTEGER)_CrimeID,(STRING)_ArrestDialog,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + _RegionID != "" + THEN + ProcCrimeInterruptStoryDialogs(_CrimeID,_ArrestDialog,1,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + ProcCheckStartArrestInterrogation(_CrimeID,_ArrestDialog,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeStartRegionArrestInterrogation((STRING)_RegionID,(INTEGER)_CrimeID,(STRING)_ArrestDialog,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + _RegionID == "" + AND + DB_ReactOutOfRegion(_Tag) + AND + IsTagged(_Arrester,_Tag,1) + AND + NOT DB_ReactingCharOutOfRegion(_Arrester,_) + THEN + ProcCrimeInterruptStoryDialogs(_CrimeID,_ArrestDialog,1,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + ProcCheckStartArrestInterrogation(_CrimeID,_ArrestDialog,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + DB_ReactingCharOutOfRegion(_Arrester,_Tag); + + + // We change crime dialog in the next section, so replace it in the DB which is used to clean some stuff on crime end + PROC + ProcCrimeStartRegionArrestInterrogation((STRING)_RegionID,(INTEGER)_CrimeID,(STRING)_ArrestDialog,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + _RegionID == "" + AND + NOT DB_ReactingCharOutOfRegion(_Arrester,_) + THEN + ProcCrimeStartRegionArrestInterrogation_SubActions(_RegionID,_CrimeID,_ArrestDialog,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeStartRegionArrestInterrogation_SubActions((STRING)_RegionID,(INTEGER)_CrimeID,(STRING)_ArrestDialog,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + DB_Crime_RequestedDialogWithTension(_CrimeName,_ArrestDialog,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4) + THEN + NOT DB_Crime_RequestedDialogWithTension(_CrimeName,_ArrestDialog,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + DB_Crime_RequestedDialogWithTension(_CrimeName,"GEB_Attack",_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeStartRegionArrestInterrogation_SubActions((STRING)_RegionID,(INTEGER)_CrimeID,(STRING)_ArrestDialog,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + THEN + ProcCrimeInterruptStoryDialogs(_CrimeID,"GEB_Attack",1,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + ProcCheckStartArrestInterrogation(_CrimeID,"GEB_Attack",_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeStartRegionArrestInterrogation((STRING)_RegionID,(INTEGER)_CrimeID,(STRING)_ArrestDialog,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4) + AND + DB_ReactingCharOutOfRegion(_Arrester,_Tag) + THEN + NOT DB_ReactingCharOutOfRegion(_Arrester,_Tag); + + PROC + ProcCrimeStartArrestInterrogation((INTEGER)_CrimeID,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,_) + AND + DB_EvidenceFound(_CrimeID,_Interrogator) + AND + DB_Crime_CallingGuards(_Interrogator,_Criminal,_ID) + THEN + NOT DB_Crime_CallingGuards(_Interrogator,_Criminal,_ID); + NOT DB_EvidenceFound(_CrimeID,_Interrogator); + DB_EvidenceFound(_CrimeID,_Arrester); + + PROC + ProcCrimeStartArrestInterrogation((INTEGER)_CrimeID,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,1) + AND + DB_EvidenceFound(_CrimeID,_Interrogator) + AND + DB_Crime_CallingGuards(_Interrogator,_Criminal,_ID) + THEN + DB_StopInterrogationAfterDialog(_CrimeID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + PROC + ProcCrimeStartArrestInterrogation((INTEGER)_CrimeID,(CHARACTERGUID)_Arrester,(CHARACTERGUID)_Criminal,(CHARACTERGUID)_Criminal2,(CHARACTERGUID)_Criminal3,(CHARACTERGUID)_Criminal4,0) + AND + DB_Crime_Interrogation(_CrimeID,_,_,_,_,_,_) + THEN + ProcStopInterrogation(_CrimeID,_Arrester,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + IF + DialogEnded(_,_Instance) + AND + DB_DialogPlayers(_Instance,_Player,1) + AND + DB_DialogNPCs(_Instance,_NPC,1) + AND + ObjectGetFlag(_Player,"Resist_Arrest",1) + AND + DB_DialogPlayers(_Instance,_Players,_) + THEN + ObjectClearFlag(_Player,"Resist_Arrest",0); + proc_CriminalMakeHostileAfterDialog((CHARACTERGUID)_Players,(CHARACTERGUID)_NPC); + + PROC + proc_CriminalMakeHostileAfterDialog((CHARACTERGUID)_Player,(CHARACTERGUID)_NPC) + AND + _Player != NULL_00000000-0000-0000-0000-000000000000 + THEN + ProcMakeNPCHostile((CHARACTERGUID)_Player,(CHARACTERGUID)_NPC); + + IF + DialogEnded(_,_Instance) + AND + DB_ArrestDialog(_Player,_Instance) + THEN + ObjectClearFlag(_Player,"Allow_Arrest",0); + NOT DB_ArrestDialog(_Player,_Instance); + ProcCrimeStartArrest((CHARACTERGUID)_Player,_Instance); + + IF + DialogEnded(_,_Instance) + AND + DB_DialogNPCs(_Instance,_NPC,1) + AND + DB_StopInterrogationAfterDialog(_CrimeID,(CHARACTERGUID)_NPC,_Criminal,_Criminal2,_Criminal3,_Criminal4) + THEN + ProcStopInterrogation(_CrimeID,_NPC,_Criminal,_Criminal2,_Criminal3,_Criminal4); + NOT DB_StopInterrogationAfterDialog(_CrimeID,_NPC,_Criminal,_Criminal2,_Criminal3,_Criminal4); + + // TODO Remove the DB_ReactingCharOutOfRegion(_Arrester,_Tag) On Tag Removed + //END_REGION + + //REGION Arrest Play As AD + IF + StoryEvent((CHARACTERGUID)_Arrester,"GLO_PlayArrestAsAD") + AND + GetVarString(_Arrester,"ArrestDialog",_ArrestDialog) + THEN + Proc_StartDialog(1,_ArrestDialog,_Arrester); + //END_REGION + + //REGION Escape Prison + IF + CharacterEnteredTrigger(_Player,_PrisonTrigger) + AND + DB_IsArrested(_Player) + AND + DB_IsPlayer(_Player) + AND + DB_PlayerPrison_Door(_PrisonTrigger,(ITEMGUID)_CellDoor,(STRING)_KeyName) + THEN + ItemCloseAndLock(_CellDoor,_KeyName); + + IF + CharacterLeftTrigger(_Player,_PrisonTrigger) + AND + DB_IsArrested(_Player) + AND + DB_IsPlayer(_Player) + AND + DB_PlayerPrison((TRIGGERGUID)_PrisonTrigger,(TRIGGERGUID)_CellDoorTrigger,(STRING)_PrisonCrimeName,(STRING)_PrisonCrimeNameAD) + AND + GetPosition(_CellDoorTrigger,_x,_y,_z) + THEN + //ProcRestoreGenericBehaviourAfterScene(_Player); + DB_PlayerEscapedPrison(_Player,_PrisonCrimeName,_PrisonCrimeNameAD); + ApplyStatus(_Player,"FUGITIVE",100.0,1); + ObjectClearFlag(_Player,"IsInPrison",0); + CharacterRegisterCrimeWithPosition(_Player,"EscapedPrison",NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,_x,_y,_z,0); + NOT DB_IsArrested(_Player); + + IF + CharacterStatusApplied(_Player,"FUGITIVE",_) + AND + DB_IsPlayer(_Player) + AND + DB_PlayerEscapedPrison(_Player,_PrisonCrimeName,_PrisonCrimeNameAD) + THEN + ObjectSetFlag(_Player,"IsFugitive"); // This is for Arrest_EscapedPrison Dialog + CharacterRegisterCrime(_Player,_PrisonCrimeName,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,0); + + IF + CharacterStatusApplied(_Player,"FUGITIVE",_) + AND + DB_IsPlayer(_Player) + AND + DB_PlayerEscapedPrison(_Player,_PrisonCrimeName,_PrisonCrimeNameAD) + AND + _PrisonCrimeNameAD != "" + THEN + CharacterRegisterCrime(_Player,_PrisonCrimeNameAD,NULL_00000000-0000-0000-0000-000000000000,NULL_00000000-0000-0000-0000-000000000000,0); + + IF + CharacterStatusRemoved(_Player,"FUGITIVE",_) + AND + DB_IsPlayer(_Player) + AND + DB_PlayerEscapedPrison(_Player,_PrisonCrimeName,_PrisonCrimeNameAD) + THEN + NOT DB_PlayerEscapedPrison(_Player,_PrisonCrimeName,_PrisonCrimeNameAD); + CharacterStopCrime(_Player,_PrisonCrimeName,NULL_00000000-0000-0000-0000-000000000000); + CharacterStopCrime(_Player,_PrisonCrimeNameAD,NULL_00000000-0000-0000-0000-000000000000); + ObjectClearFlag(_Player,"IsFugitive",0); + + IF + ObjectFlagSet("GEB_ClearTag_FUGITIVE",_Player,_) //set in GEB_Arrest_EscapedPrison + AND + HasActiveStatus(_Player,"FUGITIVE",1) + THEN + RemoveStatus(_Player,"FUGITIVE"); + + IF + ObjectFlagSet("GEB_ClearTag_FUGITIVE",_Player,_ID) //set in GEB_Arrest_EscapedPrison + AND + DB_DialogNPCs(_ID,_NPC,1) + THEN + ProcCrimeBribedGuards(_NPC,_Player); + + PROC + ProcCrimeBribedGuards((GUIDSTRING)_NPC,(GUIDSTRING)_Player) + THEN + CrimeIgnoreAllCrimesForCriminal(_Player,_NPC,300000); + DB_CrimeBribeSource(_Player); + CharacterLaunchIteratorAroundCharacter((CHARACTERGUID)_Player,20.0,"GEB_CrimeBribeGuards"); + FireOsirisEvents(); + NOT DB_CrimeBribeSource(_Player); + + IF + StoryEvent((CHARACTERGUID)_NPC,"GEB_CrimeBribeGuards") + AND + NOT DB_CombatCharacters(_NPC,_) + AND + DB_CrimeBribeSource(_Player) + AND + NOT DB_Dead(_NPC) + AND + CharacterIsPlayer(_NPC,0) + AND + QryNPCIsGuard(_NPC) + THEN + CrimeIgnoreAllCrimesForCriminal(_Player,_NPC,300000); + + IF + ObjectFlagSet("GEB_ClearTag_FUGITIVE",_Player,_) //set in GEB_Arrest_EscapedPrison + THEN + ObjectClearFlag(_Player,"GEB_ClearTag_FUGITIVE",0); + + //END_REGION + + //REGION GUARD CALLING + IF + ObjectFlagSet("GEB_Arrest_Player",_NPC,_Inst) + AND + DB_DialogNPCs(_Inst,_OldLead,1) + THEN + DB_CrimeArrestCallingGuards((CHARACTERGUID)_OldLead,_Inst); + + IF + ObjectFlagSet("GEB_Arrest_Player",_NPC,_Inst) + AND + DB_DialogNPCs(_Inst,_OldLead,1) + AND + NOT DB_CombatCharacters((CHARACTERGUID)_NPC,_) + AND + NOT DB_PickedLeadToHelp(_,_Inst) + AND + GetVarInteger(_OldLead,"CrimeID",_CrimeID) + AND + CrimeTransferLeadershipTo((CHARACTERGUID)_OldLead,_CrimeID,_NPC,1) + AND + GetVarObject(_OldLead,"Criminal1",_Criminal1) + AND + GetVarObject(_OldLead,"Criminal2",_Criminal2) + AND + GetVarObject(_OldLead,"Criminal3",_Criminal3) + AND + GetVarObject(_OldLead,"Criminal4",_Criminal4) + AND + GetVarFixedString(_OldLead,"RegionID",_RegionID) + THEN + SetHasDialog(_OldLead,0); + CharacterDisableAllCrimes(_OldLead); + CharacterEnableCrime(_OldLead,"Assault"); + CharacterEnableCrime(_OldLead,"SummonAssault"); + CharacterEnableCrime(_OldLead,"IncapacitatedAssault"); + DB_GuardCaller(_CrimeID,_OldLead,_NPC); + CharacterSetReactionPriority(_OldLead,"CRIME_Flee",2800); + DB_PickedLeadToHelp(_NPC,_Inst); + ProcStoreFightMode(_Npc); + CharacterSetFightMode(_NPC,1,0); + SetVarObject(_NPC,"Criminal1",_Criminal1); + SetVarObject(_NPC,"Criminal2",_Criminal2); + SetVarObject(_NPC,"Criminal3",_Criminal3); + SetVarObject(_NPC,"Criminal4",_Criminal4); + SetVarString(_NPC,"ArrestDialog","GEB_Arrest"); + SetVarFixedString(_NPC,"RegionID",_RegionID); + SetVarInteger(_NPC,"CrimeID",_CrimeID); + SetStoryEvent(_NPC,"CRIME_Perform_Arrest"); + + IF + DialogEnded(_Dialog,_Inst) + AND + DB_CrimeArrestCallingGuards(_OldLead,_Inst) + AND + NOT DB_PickedLeadToHelp(_,_Inst) + AND + DB_DialogPlayers(_Inst,_Player,1) + THEN + NOT DB_CrimeArrestCallingGuards(_OldLead,_Inst); + //failed to transfer leadership, start combat as fallback + Proc_StartDialog(1,"GEB_AD_DealWithCrime",_OldLead); + CharacterSetTemporaryHostileRelation((CHARACTERGUID)_Player,_OldLead); + + IF + DialogEnded(_Dialog,_Inst) + AND + DB_PickedLeadToHelp(_NPC,_Inst) + AND + DB_DialogNPCs(_Inst,_OldLead,1) + THEN + NOT DB_PickedLeadToHelp(_NPC,_Inst); + NOT DB_CrimeArrestCallingGuards((CHARACTERGUID)_OldLead,_Inst); + + IF + OnCrimeConfrontationDone(_CrimeID,_OldLead,_,_,_,_,_) + AND + DB_GuardCaller(_CrimeID,_OldLead,_NPC) + THEN + SetHasDialog(_OldLead,1); + ProcRestoreGenericBehaviour(_OldLead); + NOT DB_GuardCaller(_CrimeID,_OldLead,_NPC); + + + + //END_REGION + + + //REGION Debug + + IF + TextEventSet("LookatPrison") + THEN + CharacterLookAt(S_FTJ_PrisonGuardTest_0ad9aa6c-c8df-4591-be1a-d4f0a94d89ac,S_FortJoy_PlayerPrisonDoor_2dd80040-28aa-4445-8438-1e2424d7228f); + + IF + TextEventSet("Lookatme") + THEN + CharacterLookAt(S_FTJ_PrisonGuardTest_0ad9aa6c-c8df-4591-be1a-d4f0a94d89ac,CHARACTERGUID_Player_Ifan_ad9a3327-4456-42a7-9bf4-7ad60cc9e54f); + + //END_REGION + + } + EXIT + { + + } +} +Goal(18).Title("_Global"); +Goal(18) +{ + INIT + { + + } + KB + { + /////////////////////////////////////////////////////////////////////// + // Story call to forward the clock to _NewHour. + // The clock will be advanced with max 24 hours. This happens when you call SetGameClock(_H) AND Time(_,_H,_). + // + // DO NOT USE THE ENGINE CALL SetTime DIRECTLY! + // + PROC + SetGameClock((INTEGER)_NewHour) + AND + DB_Time(_Day,_H,_) + AND + _NewHour > _H + // day stays today + THEN + UpdateTime(_Day,_NewHour); + + PROC + SetGameClock((INTEGER)_NewHour) + AND + DB_Time(_Day,_H,_) + AND + _NewHour <= _H + AND + // day forwards +1 + IntegerSum(_Day,1,_DayP1) + THEN + UpdateTime(_DayP1,_NewHour); + + PROC + ProcDisableFollow((CHARACTERGUID)_Char) + THEN + CharacterDetachFromGroup(_Char); + //CharacterLockGroup(_Char,1); + + IF + CharacterUsedItemFailed(_Player,_Item) + AND + _Player.DB_IsPlayer() + THEN + ProcShowForbiddenItemText(_Player,_Item); + + PROC + ProcShowForbiddenItemText((CHARACTERGUID)_Player,(ITEMGUID)_Item) + AND + ItemIsLocked(_Item, 0) + AND + NOT DB_NoForbiddenText(_Item) + THEN + Proc_StartDialog(1,"GLO_AD_ForbiddenItem",_Player); + + PROC + ProcShowForbiddenItemText((CHARACTERGUID)_Player,(ITEMGUID)_Item) + AND + ItemIsLocked(_Item, 1) + THEN + CharacterItemSetEvent(_Player, _Item, "GLO_UsedLockedItem"); + + PROC + ProcShowMarker((CHARACTERGUID)_Player,(STRING)_Marker) + AND + NOT DB_ActivePlayerMarker(_Player,_Marker) + THEN + DB_ActivePlayerMarker(_Player,_Marker); + ShowMapMarker(_Player,_Marker,1); + + PROC + ProcHideMarker((CHARACTERGUID)_Player,(STRING)_Marker) + AND + DB_ActivePlayerMarker(_Player,_Marker) + THEN + ShowMapMarker(_Player,_Marker,0); + + PROC + ProcFreezePlayers() + AND + _Player.DB_IsPlayer() + THEN + CharacterFreeze(_Player); + + PROC + ProcUnfreezePlayers() + AND + _Player.DB_IsPlayer() + THEN + CharacterUnfreeze(_Player); + + //REGION moving items default functions + PROC + MoveAllItemsTo((GUIDSTRING)_Source,(GUIDSTRING)_Target) + THEN + MoveAllItemsTo(_Source,_Target,1,1,1); + //END_REGION + + } + EXIT + { + + } +} +Goal(19).Title("_Global_Autosave"); +Goal(19) +{ + INIT + { + + } + KB + { + IF + DB_AutoSaveTrigger((TRIGGERGUID)_Trigger) + AND + NOT DB_Subregion(_Trigger,_,_) //Subregions can function as autosaves the first time they are entered + THEN + DB_OneShotPlayerTrigger(_Trigger); + + //retro-active check, if a trigger is a sub-region, it should not be oneshot + IF + DB_Subregion(_Trigger,_,_) + AND + DB_OneShotPlayerTrigger(_Trigger) + THEN + NOT DB_OneShotPlayerTrigger(_Trigger); + + PROC + ProcOneShotTriggerEntered(_,_Trigger) + AND + DB_AutoSaveTrigger(_Trigger) + AND + DB_AutosaveGroup(_Trigger,_Group) + AND + DB_AutosaveGroup(_AnotherTrigger,_Group) + AND + _AnotherTrigger != _Trigger + THEN + NOT DB_AutoSaveTrigger(_AnotherTrigger); + NOT DB_OneShotPlayerTrigger(_AnotherTrigger); + ProcTriggerUnregisterForPlayers(_AnotherTrigger); + + PROC + ProcOneShotTriggerEntered(_,_Trigger) + AND + DB_AutoSaveTrigger(_Trigger) + THEN + NOT DB_AutoSaveTrigger(_Trigger); + AutoSave(); + + //For use of Autosave triggers that are attached to non-oneshots such as Subregions + IF + CharacterEnteredTrigger((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_AutoSaveTrigger(_Trigger) + AND + NOT DB_OneShotPlayerTrigger(_Trigger) + THEN + NOT DB_AutoSaveTrigger(_Trigger); + AutoSave(); + + IF + DB_AutosaveGroup((TRIGGERGUID)_Trigger,(STRING)_ID) + THEN + DB_AutoSaveTrigger(_Trigger); + + + + } + EXIT + { + + } +} +Goal(20).Title("_Global_CharacterAnimations"); +Goal(20) +{ + INIT + { + // Standard animations + DB_GLO_CharacterAnimation("PlayAnim_attack1","attack1",0); + DB_GLO_CharacterAnimation("PlayAnim_attack2","attack2",0); + DB_GLO_CharacterAnimation("PlayAnim_attack3","attack3",0); + DB_GLO_CharacterAnimation("PlayAnim_attack_ground","attack_ground",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_thrown_loop","thrown_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_thrown_land","thrown_land",0); + DB_GLO_CharacterAnimation("PlayAnim_knockdown_fall","knockdown_fall",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_knockdown_loop","knockdown_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_knockdown_getup","knockdown_getup",0); + DB_GLO_CharacterAnimation("PlayAnim_barf","barf",0); + DB_GLO_CharacterAnimation("PlayAnim_die_melee","die_melee",0); + DB_GLO_CharacterAnimation("PlayAnim_die_slash","die_slash",0); + DB_GLO_CharacterAnimation("PlayAnim_die_crush","die_crush",0); + DB_GLO_CharacterAnimation("PlayAnim_die_pierce","die_pierce",0); + DB_GLO_CharacterAnimation("PlayAnim_die_arrow","die_arrow",0); + DB_GLO_CharacterAnimation("PlayAnim_die_dot","die_dot",0); + DB_GLO_CharacterAnimation("PlayAnim_die_incinerate","die_incinerate",0); + DB_GLO_CharacterAnimation("PlayAnim_die_acid","die_acid",0); + DB_GLO_CharacterAnimation("PlayAnim_die_electrocution","die_electrocution",0); + DB_GLO_CharacterAnimation("PlayAnim_die_frozenshatter","die_frozenshatter",0); + DB_GLO_CharacterAnimation("PlayAnim_die_hang","die_hang",0); + DB_GLO_CharacterAnimation("PlayAnim_hit","hit",0); + DB_GLO_CharacterAnimation("PlayAnim_hit_backstab","hit_backstab",0); + DB_GLO_CharacterAnimation("PlayAnim_hit_magic","hit_magic",0); + DB_GLO_CharacterAnimation("PlayAnim_block","block",0); + DB_GLO_CharacterAnimation("PlayAnim_dodge","dodge",0); + DB_GLO_CharacterAnimation("PlayAnim_dodge_backstab","dodge_backstab",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_idle1","idle1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_idle2","idle2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_idle3","idle3",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_walk","walk",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_sneak","sneak",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_run","run",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_still","still",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_stillsneaking","stillsneaking",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_stilldiseased","stilldiseased",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_stillchilled","stillchilled",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_stillcrippled","stillcrippled",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_stillblind","stillblind",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_stilldrunk","stilldrunk",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_stillelectrified","stillelectrified",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_walk_wings","walk_wings",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_run_wings","run_wings",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_still_wings","still_wings",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_stillmental","stillmental",1); + + DB_GLO_CharacterAnimation("PlayAnim_Loop_cower","cower",1); + DB_GLO_CharacterAnimation("PlayAnim_spawn","spawn",0); + DB_GLO_CharacterAnimation("PlayAnim_polymorphed","polymorphed",0); + DB_GLO_CharacterAnimation("PlayAnim_resurrect","resurrect",0); + DB_GLO_CharacterAnimation("PlayAnim_use_inspect","use_inspect",0); + DB_GLO_CharacterAnimation("PlayAnim_use_activate","use_activate",0); + DB_GLO_CharacterAnimation("PlayAnim_use_loot","use_loot",0); + DB_GLO_CharacterAnimation("PlayAnim_use_eat","use_eat",0); + DB_GLO_CharacterAnimation("PlayAnim_use_drink","use_drink",0); + DB_GLO_CharacterAnimation("PlayAnim_use_craft","use_craft",0); + DB_GLO_CharacterAnimation("PlayAnim_use_dig","use_dig",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_stance_start","skill_stance_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_stance_loop","skill_stance_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_stance_cast","skill_stance_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_prepare_weapon_01_start","skill_prepare_weapon_01_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_prepare_weapon_01_loop","skill_prepare_weapon_01_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_flurry_01_cast","skill_attack_flurry_01_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_precision_01_cast","skill_attack_precision_01_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_power_01_cast","skill_attack_power_01_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_round_01_cast","skill_attack_round_01_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_multi_01_cast","skill_attack_multi_01_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_multi_02_cast","skill_attack_multi_02_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_aoe_01_cast","skill_attack_aoe_01_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_offhand_01_cast","skill_attack_offhand_01_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_stance_01_cast","skill_attack_stance_01_cast",0); + + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_projectile_01_cast","skill_attack_projectile_01_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_attack_projectile_02_cast","skill_attack_projectile_02_cast",0); + ////////////////////////////////////////////////////////////////////////// + // Ranger tricks: + ////////////////////////////////////////////////////////////////////////// + DB_GLO_CharacterAnimation("PlayAnim_skill_arrow_start","skill_arrow_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_arrow_loop","skill_arrow_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_arrow_cast","skill_arrow_cast",0); + + DB_GLO_CharacterAnimation("PlayAnim_skill_rainofarrows_start","skill_rainofarrows_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_rainofarrows_loop","skill_rainofarrows_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_rainofarrows_cast","skill_rainofarrows_cast",0); + + DB_GLO_CharacterAnimation("PlayAnim_skill_splittingarrows_start","skill_splittingarrows_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_splittingarrows_loop","skill_splittingarrows_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_splittingarrows_cast","skill_splittingarrows_cast",0); + + DB_GLO_CharacterAnimation("PlayAnim_skill_multishot_lvl1_cast","skill_multishot_lvl1_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_multishot_lvl2_cast","skill_multishot_lvl2_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_multishot_lvl3_cast","skill_multishot_lvl3_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_multishot_lvl4_cast","skill_multishot_lvl4_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_multishot_lvl5_cast","skill_multishot_lvl5_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_multishot_lvl6_cast","skill_multishot_lvl6_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_multishot_lvl7_cast","skill_multishot_lvl7_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_multishot_lvl8_cast","skill_multishot_lvl8_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_multishot_lvl9_cast","skill_multishot_lvl9_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_skill_multishot_lvl10_cast","skill_multishot_lvl10_cast",0); + ////////////////////////////////////////////////////////////////////////// + // Warrior tricks: + ////////////////////////////////////////////////////////////////////////// + DB_GLO_CharacterAnimation("PlayAnim_skill_flurry_start","skill_flurry_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_flurry_loop","skill_flurry_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_flurry_cast","skill_flurry_cast",0); + + DB_GLO_CharacterAnimation("PlayAnim_skill_powerattack_start","skill_powerattack_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_powerattack_loop","skill_powerattack_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_powerattack_cast","skill_powerattack_cast",0); + + DB_GLO_CharacterAnimation("PlayAnim_skill_whirlwind_start","skill_whirlwind_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_whirlwind_loop","skill_whirlwind_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_whirlwind_cast","skill_whirlwind_cast",0); + + DB_GLO_CharacterAnimation("PlayAnim_skill_fatality_start","skill_fatality_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_fatality_loop","skill_fatality_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_fatality_cast","skill_fatality_cast",0); + ////////////////////////////////////////////////////////////////////////// + // Scoundrel tricks: + ////////////////////////////////////////////////////////////////////////// + DB_GLO_CharacterAnimation("PlayAnim_skill_shadowstrike_start","skill_shadowstrike_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_shadowstrike_loop","skill_shadowstrike_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_shadowstrike_cast","skill_shadowstrike_cast",0); + + DB_GLO_CharacterAnimation("PlayAnim_skill_lacerate_start","skill_lacerate_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_skill_lacerate_loop","skill_lacerate_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_skill_lacerate_cast","skill_lacerate_cast",0); + ////////////////////////////////////////////////////////////////////////// + // Emotions: + ////////////////////////////////////////////////////////////////////////// + DB_GLO_CharacterAnimation("PlayAnim_emotion_normal","emotion_normal",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_normal_looping1","emotion_normal_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_normal_looping2","emotion_normal_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_normal_looping3","emotion_normal_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_angry","emotion_angry",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_angry_looping1","emotion_angry_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_angry_looping2","emotion_angry_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_angry_looping3","emotion_angry_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_boasting_bragging","emotion_boasting_bragging",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_boasting_bragging_looping1","emotion_boasting_bragging_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_boasting_bragging_looping2","emotion_boasting_bragging_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_boasting_bragging_looping3","emotion_boasting_bragging_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_clueless","emotion_clueless",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_clueless_looping1","emotion_clueless_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_clueless_looping2","emotion_clueless_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_clueless_looping3","emotion_clueless_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_cower_scared","emotion_cower_scared",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_cower_scared_looping1","emotion_cower_scared_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_cower_scared_looping2","emotion_cower_scared_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_cower_scared_looping3","emotion_cower_scared_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_greeting","emotion_greeting",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_greeting_looping1","emotion_greeting_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_greeting_looping2","emotion_greeting_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_greeting_looping3","emotion_greeting_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_happy_cheerful","emotion_happy_cheerful",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_happy_cheerful_looping1","emotion_happy_cheerful_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_happy_cheerful_looping2","emotion_happy_cheerful_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_happy_cheerful_looping3","emotion_happy_cheerful_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_ignore_dismiss","emotion_ignore_dismiss",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_ignore_dismiss_looping1","emotion_ignore_dismiss_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_ignore_dismiss_looping2","emotion_ignore_dismiss_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_ignore_dismiss_looping3","emotion_ignore_dismiss_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_panic_distress","emotion_panic_distress",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_panic_distress_looping1","emotion_panic_distress_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_panic_distress_looping2","emotion_panic_distress_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_panic_distress_looping3","emotion_panic_distress_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_insulting","emotion_insulting",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_insulting_looping1","emotion_insulting_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_insulting_looping2","emotion_insulting_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_insulting_looping3","emotion_insulting_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_sad","emotion_sad",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_sad_looping1","emotion_sad_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_sad_looping2","emotion_sad_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_sad_looping3","emotion_sad_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_thankful","emotion_thankful",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_thankful_looping1","emotion_thankful_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_thankful_looping2","emotion_thankful_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_thankful_looping3","emotion_thankful_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_sly_scheming","emotion_sly_scheming",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_sly_scheming_looping1","emotion_sly_scheming_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_sly_scheming_looping2","emotion_sly_scheming_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_sly_scheming_looping3","emotion_sly_scheming_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_sarcasm_haughty","emotion_sarcasm_haughty",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_sarcasm_haughty_looping1","emotion_sarcasm_haughty_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_sarcasm_haughty_looping2","emotion_sarcasm_haughty_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_sarcasm_haughty_looping3","emotion_sarcasm_haughty_looping3",1); + DB_GLO_CharacterAnimation("PlayAnim_emotion_flirt","emotion_flirt",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_flirt_looping1","emotion_flirt_looping1",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_flirt_looping2","emotion_flirt_looping2",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_emotion_flirt_looping3","emotion_flirt_looping3",1); + ////////////////////////////////////////////////////////////////////////// + // Climbing + ////////////////////////////////////////////////////////////////////////// + DB_GLO_CharacterAnimation("PlayAnim_climb_UpAttach","climb_UpAttach",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_climb_Up","climb_Up",1); + DB_GLO_CharacterAnimation("PlayAnim_climb_UpDetach","climb_UpDetach",0); + DB_GLO_CharacterAnimation("PlayAnim_climb_DownAttach","climb_DownAttach",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_climb_Down","climb_Down",1); + DB_GLO_CharacterAnimation("PlayAnim_climb_DownDetach","climb_DownDetach",0); + DB_GLO_CharacterAnimation("PlayAnim_cast_target_start","cast_target_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_cast_target_loop","cast_target_loop",1); + DB_GLO_CharacterAnimation("PlayAnim_cast_target_cast","cast_target_cast",0); + DB_GLO_CharacterAnimation("PlayAnim_cast_shout_start","cast_shout_start",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_cast_shout_loop","cast_shout_loop",1); + + // Custom animations + DB_GLO_CharacterAnimation("PlayAnim_Activate_01","Activate_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Annoyed_01","Annoyed_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Attention_01","Attention_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Attention_02","Attention_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Attention_03","Attention_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Attentive_01","Attentive_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Beg_01","Beg_01",0); + DB_GLO_CharacterAnimation("PlayAnim_BehindBars_01","BehindBars_01",0); + DB_GLO_CharacterAnimation("PlayAnim_BehindBars_02","BehindBars_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Bellringer_01","Bellringer_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Blacksmith_01","Blacksmith_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Blacksmith_02","Blacksmith_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Bored_01","Bored_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Bored_02","Bored_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Bored_03","Bored_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Bow_01","Bow_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Bow_02","Bow_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Bow_03","Bow_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Bow_04","Bow_04",0); + DB_GLO_CharacterAnimation("PlayAnim_Bow_05","Bow_05",0); + DB_GLO_CharacterAnimation("PlayAnim_Cast_Ritual_01","Cast_Ritual_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Check_Neck_01","Check_Neck_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Cheer_01","Cheer_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Cheer_02","Cheer_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Cheer_03","Cheer_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Chicken_01","Chicken_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Chicken_02","Chicken_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Chicken_03","Chicken_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Chicken_Idle_01","Chicken_Idle_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Chuckle_01","Chuckle_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Chuckle_02","Chuckle_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Clap_01","Clap_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Clap_02","Clap_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Clap_03","Clap_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Clap_04","Clap_04",0); + DB_GLO_CharacterAnimation("PlayAnim_Clean_Floor_01","Clean_Floor_01",0); // With mop & water + DB_GLO_CharacterAnimation("PlayAnim_Clean_Floor_02","Clean_Floor_02",0); // With broom + DB_GLO_CharacterAnimation("PlayAnim_Cooking_01","Cooking_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Cower_01","Cower_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Cower_02","Cower_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Crying_01","Crying_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Curtsey_01","Curtsey_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Dance_01","Dance_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Depressed_01","Depressed_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Dust_Off_01","Dust_Off_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Fidget_Book_01","Fidget_Book_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Fidget_Forward_01","Fidget_Forward_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Fidget_Forward_02","Fidget_Forward_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Fidget_High_01","Fidget_High_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Fidget_High_02","Fidget_High_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Fidget_Low_01","Fidget_Low_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Fidget_Low_02","Fidget_Low_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Fidget_Low_03","Fidget_Low_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Flex_01","Flex_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Flirt_01","Flirt_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Fumble_01","Fumble_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Halt_01","Halt_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Ignore_01","Ignore_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Intimidate_01","Intimidate_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Intimidate_02","Intimidate_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Kneel_01","Kneel_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Kneel_02","Kneel_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Laugh_01","Laugh_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Laugh_02","Laugh_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Listen_01","Listen_01",0); + DB_GLO_CharacterAnimation("PlayAnim_LoadingCart_01","LoadingCart_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Look_Down_Long_01","Look_Down_Long_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Look_Down_Short_01","Look_Down_Short_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Look_Left_Long_01","Look_Left_Long_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Look_Left_Short_01","Look_Left_Short_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Look_Right_Long_01","Look_Right_Long_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Look_Right_Short_01","Look_Right_Short_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Look_Up_Long_01","Look_Up_Long_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Look_Up_Short_01","Look_Up_Short_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Look_Up_Short_02","Look_Up_Short_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Mindcontrol_01","Mindcontrol_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Mine_01","Mine_01",0); + DB_GLO_CharacterAnimation("PlayAnim_No_01","No_01",0); + DB_GLO_CharacterAnimation("PlayAnim_No_02","No_02",0); + DB_GLO_CharacterAnimation("PlayAnim_No_03","No_03",0); + DB_GLO_CharacterAnimation("PlayAnim_No_04","No_04",0); + DB_GLO_CharacterAnimation("PlayAnim_No_05","No_05",0); + DB_GLO_CharacterAnimation("PlayAnim_No_06","No_06",0); + DB_GLO_CharacterAnimation("PlayAnim_Perform_01","Perform_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Perform_02","Perform_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Perform_03","Perform_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Pickpocket_01","Pickpocket_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Point_01","Point_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Potion_Rub_01","Potion_Rub_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Pray_01","Pray_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Pst_01","Pst_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Pst_02","Pst_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Pst_03","Pst_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Pst_04","Pst_04",0); + DB_GLO_CharacterAnimation("PlayAnim_Repair_01","Repair_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Revolt_01","Revolt_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Revolt_02","Revolt_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Salute_01","Salute_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Salute_02","Salute_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Salute_03","Salute_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Salute_04","Salute_04",0); + DB_GLO_CharacterAnimation("PlayAnim_Salute_05","Salute_05",0); + DB_GLO_CharacterAnimation("PlayAnim_Salute_06","Salute_06",0); + DB_GLO_CharacterAnimation("PlayAnim_Salute_07","Salute_07",0); + DB_GLO_CharacterAnimation("PlayAnim_Shout_01","Shout_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Shrug_01","Shrug_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sigh_01","Sigh_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sooth_01","Sooth_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sow_02","Sow_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Stand_Read_01","Stand_Read_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Surprise_01","Surprise_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Surprise_02","Surprise_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Tapping_Beer_01","Tapping_Beer_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Tapping_Beer_02","Tapping_Beer_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Taunt_01","Taunt_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Taunt_02","Taunt_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Teleport_01","Teleport_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Think_01","Think_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Think_02","Think_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Throw_Away_01","Throw_Away_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Throw_Up_01","Throw_Up_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Throw_Water_01","Throw_Water_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Tired_01","Tired_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Trader_01","Trader_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Trader_02","Trader_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Trader_03","Trader_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Use_01","Use_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Use_02","Use_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Victory_01","Victory_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Victory_02","Victory_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Warm_Hands_01","Warm_Hands_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Wave_01","Wave_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Wave_02","Wave_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Wave_03","Wave_03",0); + DB_GLO_CharacterAnimation("PlayAnim_WipeTable_01","WipeTable_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Worship_01","Worship_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Yawn_01","Yawn_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Yes_01","Yes_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Yes_02","Yes_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Yes_03","Yes_03",0); + DB_GLO_CharacterAnimation("PlayAnim_Yes_04","Yes_04",0); + DB_GLO_CharacterAnimation("PlayAnim_Yes_05","Yes_05",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Angry_01","Sit_Angry_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Annoyed_01","Sit_Annoyed_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Bored_01","Sit_Bored_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Bored_02","Sit_Bored_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Chuckle_01","Sit_Chuckle_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Drink_01","Sit_Drink_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Laugh_01","Sit_Laugh_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Laugh_02","Sit_Laugh_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Look_Left_01","Sit_Look_Left_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Look_Right_01","Sit_Look_Right_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_No_01","Sit_No_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_No_02","Sit_No_02",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Praise_01","Sit_Praise_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Pray_01","Sit_Pray_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Read_01","Sit_Read_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Reject_01","Sit_Reject_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Salute_01","Sit_Salute_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Sigh_01","Sit_Sigh_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Surprise_01","Sit_Surprise_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Tired_01","Sit_Tired_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Sit_Yes_01","Sit_Yes_01",0); + DB_GLO_CharacterAnimation("PlayAnim_Loop_BarStand_01_Loop","BarStand_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Relax_01_Loop","Lie_Relax_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Suffer_01_Loop","Lie_Suffer_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Suffer_02_Loop","Lie_Suffer_02_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Suffer_03_Loop","Lie_Suffer_03_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Chained_01_Loop","Chained_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Cower_03_Loop","Cower_03_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Crucified_01_Loop","Crucified_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Dig_01_Loop","Dig_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Dead_01_Loop","Lie_Dead_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Relax_02_Loop","Lie_Relax_02_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Wounded_01_Loop","Lie_Wounded_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Wounded_02_Loop","Lie_Wounded_02_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Wounded_03_Loop","Lie_Wounded_03_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Guard_01_Loop","Guard_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Hung_01_Loop","Hung_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Hung_02_Loop","Hung_02_Loop",1); // dead + DB_GLO_CharacterAnimation("PlayAnim_Loop_Hung_03_Loop","Hung_03_Loop",1); // alive & kicking by the neck + DB_GLO_CharacterAnimation("PlayAnim_Loop_Injured_01_Loop","Injured_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Insane_01_Loop","Insane_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Kneel_01_Loop","Kneel_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Tied_Up_01_Loop","Lie_Tied_Up_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Lie_Tied_Up_01_End","Lie_Tied_Up_01_End",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Rake_01_Loop","Rake_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Sing_01_Loop","Sing_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Sad_01_Loop","Sad_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Search_Book_01_Loop","Search_Book_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Sit_Sick_01_Loop","Sit_Sick_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Sit_Sleep_01_Loop","Sit_Sleep_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Sit_Sleep_02_Loop","Sit_Sleep_02_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Sit_Write_01_Loop","Sit_Write_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Sow_01_Loop","Sow_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Stand_Drink_01_Loop","Stand_Drink_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Stand_Drink_02_Loop","Stand_Drink_02_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Stand_Read_01_Loop","Stand_Read_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Stare_01_Loop","Stare_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Tied_Up_01_Loop","Tied_Up_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Training_2HS_01_Loop","Training_2HS_01_Loop",1); + DB_GLO_CharacterAnimation("PlayAnim_Loop_Training_Bow_01_Loop","Training_Bow_01_Loop",1); + + DB_GLO_CharacterAnimation("PlayAnim_skill_cast_throw_arc_02_cast","skill_cast_throw_arc_02_cast"); + + } + KB + { + //REGION Play animation when flag is set + IF + ObjectFlagSet(_Flag,(CHARACTERGUID)_Character,_Dialog) + AND + DB_GLO_CharacterAnimation(_Flag,_Animation,_Looping) + THEN + ObjectClearFlag(_Character,_Flag); + PROC_GLO_CharacterAnimationStart(_Character,_Animation,_Dialog,_Looping); + + PROC + PROC_GLO_CharacterAnimationStart((CHARACTERGUID)_Character,(STRING)_Animation,(INTEGER)_Dialog,0) + AND + NOT DB_GLO_CharacterAnimationForDialog(_Character,_) + THEN + DB_GLO_CharacterAnimationForDialog(_Character,_Dialog); + PlayAnimation(_Character,_Animation,"GLO_CharacterAnimationFinished"); + + IF + StoryEvent((CHARACTERGUID)_Character,"GLO_CharacterAnimationFinished") + AND + DB_GLO_CharacterAnimationForDialog(_Character,_Dialog) + THEN + NOT DB_GLO_CharacterAnimationForDialog(_Character,_Dialog); + + PROC + PROC_GLO_CharacterAnimationStart((CHARACTERGUID)_Character,(STRING)_Animation,(INTEGER)_Dialog,1) + THEN + CharacterSetAnimationOverride(_Character,_Animation); + + IF + ObjectFlagSet("PlayAnim_StopLoop",(CHARACTERGUID)_Character,_) + THEN + ObjectClearFlag(_Character,"PlayAnim_StopLoop"); + CharacterSetAnimationOverride(_Character,""); + + IF + ObjectFlagSet("PlayAnim_DrawWeapons",(CHARACTERGUID)_Character,_) + AND + HasActiveStatus(_Character,"SITTING",1) + THEN + RemoveStatus(_Character,"SITTING"); + + IF + ObjectFlagSet("PlayAnim_DrawWeapons",(CHARACTERGUID)_Character,_) + THEN + ObjectClearFlag(_Character,"PlayAnim_DrawWeapons"); + CharacterSetFightMode(_Character,1,0); + + IF + ObjectFlagSet("PlayAnim_SheathWeapons",(CHARACTERGUID)_Character,_) + THEN + ObjectClearFlag(_Character,"PlayAnim_SheathWeapons"); + CharacterSetFightMode(_Character,0,0); + //END_REGION + + } + EXIT + { + + } +} +Goal(21).Title("_Global_Counter"); +Goal(21) +{ + INIT + { + + } + KB + { + PROC + ProcRemoveCounter((STRING)_Name) + AND + DB_GlobalCounter(_Name,_Count) + THEN + NOT DB_GlobalCounter(_Name,_Count); + + PROC + ProcDeclareCounter((STRING)_Name) + THEN + ProcRemoveCounter(_Name); + DB_GlobalCounter(_Name,0); + + PROC + ProcIncreaseCounter((STRING)_Name) + THEN + ProcIncreaseCounter(_Name,1); + + PROC + ProcIncreaseCounter((STRING)_Name,(INTEGER)_Amount) + AND + DB_GlobalCounter(_Name,_Count) + AND + IntegerSum(_Count,_Amount,_NewCount) + THEN + NOT DB_GlobalCounter(_Name,_Count); + DB_GlobalCounter(_Name,_NewCount); + + PROC + ProcDecreaseCounter((STRING)_Name) + THEN + ProcDecreaseCounter(_Name,1); + + PROC + ProcDecreaseCounter((STRING)_Name,(INTEGER)_Amount) + AND + DB_GlobalCounter(_Name,_Count) + AND + IntegerSubtract(_Count,_Amount,_NewCount) + THEN + NOT DB_GlobalCounter(_Name,_Count); + DB_GlobalCounter(_Name,_NewCount); + + } + EXIT + { + + } +} +Goal(22).Title("_GLOBAL_Effects"); +Goal(22) +{ + INIT + { + PROC_CleanUpEffects(); + + } + KB + { + //REGION Savegame handle fixes + + IF + DB_CurrentLevel(_) + THEN + PROC_InvalidateLoopEffects(); + PROC_InvalidateLoopBeamEffects(); + + PROC + PROC_InvalidateLoopEffects() + AND + DB_LoopEffect((GUIDSTRING)_object, (INTEGER64) _fxHandle,(STRING)_ID,(STRING)_Region,(STRING)_effect,(STRING)_BoneName) + THEN + NOT DB_LoopEffect(_object, _fxHandle,_ID,_Region,_effect,_BoneName); + DB_LoopEffect(_object, (INTEGER64)-1,_ID,_Region,_effect,_BoneName); + + PROC + PROC_InvalidateLoopBeamEffects() + AND + DB_LoopBeamEffect((GUIDSTRING)_Source,(GUIDSTRING)_Target,(INTEGER64)_EffectHandle,(STRING)_ID,(STRING)_Region,(STRING)_effect,(STRING)_SrcBone,(STRING)_TargetBone) + THEN + NOT DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,_Region,_effect,_SrcBone,_TargetBone); + DB_LoopBeamEffect(_Source,_Target,(INTEGER64)-1,_ID,_Region,_effect,_SrcBone,_TargetBone); + //END_REGION + + /***************************/ + /*** EFFECT REGISTRATION ***/ + /***************************/ + + PROC + PROC_LoopEffect((STRING)_effect, (GUIDSTRING)_Source,(STRING)_ID,(STRING)_Region,(STRING)_BoneName) + AND + DB_CurrentLevel(_Region) + AND + PlayLoopEffect(_Source, _effect, _BoneName, _fxHandle) + THEN + DB_LoopEffect(_Source, _fxHandle,_ID,_Region,_effect, _BoneName); + + PROC + PROC_LoopEffect((STRING)_effect, (GUIDSTRING)_Source,(STRING)_ID,(STRING)_Region,(STRING)_BoneName) + AND + _Region!="__ANY__" + AND + NOT DB_CurrentLevel(_Region) + THEN + DB_LoopEffect(_Source, (INTEGER64)-1,_ID,_Region,_effect, _BoneName); + + PROC + PROC_LoopEffect((STRING)_effect, (GUIDSTRING)_Source,(STRING)_ID,"__ANY__",(STRING)_BoneName) + AND + DB_CurrentLevel(_) + AND + NOT QryBlockEffectInCombat(_effect,_Source) + AND + PlayLoopEffect(_Source, _effect, _BoneName, _fxHandle) + THEN + DB_LoopEffect(_Source, _fxHandle,_ID,"__ANY__",_effect, _BoneName); + + PROC + PROC_LoopEffect((STRING)_effect, (GUIDSTRING)_Source,(STRING)_ID,"__ANY__",(STRING)_BoneName) + AND + DB_CurrentLevel(_) + AND + QryBlockEffectInCombat(_effect,_Source) + THEN + DB_LoopEffect(_Source, (INTEGER64)-1,_ID,"__ANY__",_effect, _BoneName); + + PROC + PROC_LoopEffect((STRING)_effect, (GUIDSTRING)_Source,(STRING)_ID,"__ANY__",(STRING)_BoneName) + AND + NOT DB_CurrentLevel(_) + THEN + DB_LoopEffect(_Source, (INTEGER64)-1,_ID,"__ANY__",_effect, _BoneName); + + PROC + PROC_LoopBeamEffect((STRING)_effect, (GUIDSTRING)_Source,(GUIDSTRING)_Target,(STRING)_SrcBone,(STRING)_TargetBone,(STRING)_ID,(STRING)_Region) + AND + _Region!="__ANY__" + AND + NOT DB_CurrentLevel(_Region) + THEN + DB_LoopBeamEffect(_Source,_Target,(INTEGER64)-1,_ID,_Region,_effect,_SrcBone,_TargetBone); + + PROC + PROC_LoopBeamEffect((STRING)_effect, (GUIDSTRING)_Source,(GUIDSTRING)_Target,(STRING)_SrcBone,(STRING)_TargetBone,(STRING)_ID,(STRING)_Region) + AND + DB_CurrentLevel(_Region) + AND + PlayLoopBeamEffect(_Source,_Target,_effect,_SrcBone,_TargetBone,_EffectHandle) + THEN + DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,_Region,_effect,_SrcBone,_TargetBone); + + PROC + PROC_LoopBeamEffect((STRING)_effect, (GUIDSTRING)_Source,(GUIDSTRING)_Target,(STRING)_SrcBone,(STRING)_TargetBone,(STRING)_ID,"__ANY__") + AND + PlayLoopBeamEffect(_Source,_Target,_effect,_SrcBone,_TargetBone,_EffectHandle) + THEN + DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,"__ANY__",_effect,_SrcBone,_TargetBone); + + /***********************/ + /*** EFFECT DELETION ***/ + /***********************/ + + PROC + ProcStopLoopEffect((INTEGER64)_fxHandle) + AND + _fxHandle!=-1 + THEN + StopLoopEffect(_fxHandle); + + PROC + PROC_StopLoopEffect((GUIDSTRING)_Source,(STRING)_ID) + AND + DB_LoopEffect(_Source, _fxHandle,_ID,_Region,_effect, _BoneName) + THEN + ProcStopLoopEffect(_fxHandle); + NOT DB_LoopEffect(_Source, _fxHandle,_ID,_Region,_effect, _BoneName); + + PROC + PROC_StopLoopBeamEffect((GUIDSTRING)_Source,(STRING)_ID) + AND + DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,_Region,_effect,_SrcBone,_TargetBone) + THEN + ProcStopLoopEffect(_EffectHandle); + NOT DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,_Region,_effect,_SrcBone,_TargetBone); + + /************************/ + /*** EFFECTS CLEAN-UP ***/ + /************************/ + + PROC + PROC_CleanUpEffects() + THEN + PROC_CleanUpLoopEffects(); + PROC_CleanUpLoopBeamEffects(); + + PROC + PROC_CleanUpLoopEffects() + AND + DB_LoopEffect(_Object, _,_ID,_,_,_) + THEN + PROC_StopLoopEffect(_Object,_ID); + + PROC + PROC_CleanUpLoopBeamEffects() + AND + DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,_Region,_effect,_SrcBone,_TargetBone) + THEN + PROC_StopLoopBeamEffect(_Source,_ID); + + + + /************************/ + + //REGION stopping effects for a region + + PROC + ProcStopEffectsForRegion((STRING)_Region) + THEN + ProcStopLoopEffectsForRegion(_Region); + ProcStopLoopBeamEffectsForRegion(_Region); + + PROC + ProcStopLoopEffectsForRegion((STRING)_Region) + AND + DB_LoopEffect(_Source, _fxHandle,_ID,_Region,_effect, _BoneName) + THEN + ProcStopLoopEffect(_fxHandle); + NOT DB_LoopEffect(_Source, _fxHandle,_ID,_Region,_effect, _BoneName); + DB_LoopEffect(_Source,(INTEGER64)-1,_ID,_Region,_effect, _BoneName); + + PROC + ProcStopLoopBeamEffectsForRegion((STRING)_Region) + AND + DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,_Region,_effect,_SrcBone,_TargetBone) + THEN + ProcStopLoopEffect(_EffectHandle); + NOT DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,_Region,_effect,_SrcBone,_TargetBone); + DB_LoopBeamEffect(_Source,_Target,(INTEGER64)-1,_ID,_Region,_effect,_SrcBone,_TargetBone); + + PROC + ProcStopLoopEffectsForRegion((STRING)_) + AND + DB_LoopEffect(_Source, _fxHandle,_ID,"__ANY__",_effect, _BoneName) + THEN + ProcStopLoopEffect(_fxHandle); + NOT DB_LoopEffect(_Source, _fxHandle,_ID,"__ANY__",_effect, _BoneName); + DB_LoopEffect(_Source, (INTEGER64)-1,_ID,"__ANY__",_effect, _BoneName); + + PROC + ProcStopLoopBeamEffectsForRegion((STRING)_) + AND + DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,"__ANY__",_effect,_SrcBone,_TargetBone) + THEN + ProcStopLoopEffect(_EffectHandle); + NOT DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,"__ANY__",_effect,_SrcBone,_TargetBone); + DB_LoopBeamEffect(_Source,_Target,(INTEGER64)-1,_ID,"__ANY__",_effect,_SrcBone,_TargetBone); + //END_REGION + + //REGION starting effects for a region + + PROC + ProcStartEffectsForRegion((STRING)_Region) + THEN + ProcStartLoopEffectsForRegion(_Region); + ProcStartLoopBeamEffectsForRegion(_Region); + + PROC + ProcStartLoopEffectsForRegion((STRING)_Region) + AND + DB_LoopEffect(_Source, _fxHandle,_ID,_Region,_effect, _BoneName) + AND + NOT QryBlockEffectInCombat(_effect,_Source) + AND + PlayLoopEffect(_Source, _effect, _BoneName, _NewfxHandle) + THEN + ProcStopLoopEffect(_fxHandle); + NOT DB_LoopEffect(_Source, _fxHandle,_ID,_Region,_effect, _BoneName); + DB_LoopEffect(_Source, _NewfxHandle,_ID,_Region,_effect, _BoneName); + + PROC + ProcStartLoopBeamEffectsForRegion((STRING)_Region) + AND + DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,_Region,_effect,_SrcBone,_TargetBone) + AND + PlayLoopBeamEffect(_Source,_Target,_effect,_SrcBone,_TargetBone,_NewEffectHandle) + THEN + ProcStopLoopEffect(_EffectHandle); + NOT DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,_Region,_effect,_SrcBone,_TargetBone); + DB_LoopBeamEffect(_Source,_Target,_NewEffectHandle,_ID,_Region,_effect,_SrcBone,_TargetBone); + + /////// + + PROC + ProcStartLoopEffectsForRegion((STRING)_) + AND + DB_LoopEffect(_Source, _fxHandle,_ID,"__ANY__",_effect, _BoneName) + AND + NOT QryBlockEffectInCombat(_effect,_Source) + AND + PlayLoopEffect(_Source, _effect, _BoneName, _NewfxHandle) + THEN + ProcStopLoopEffect(_fxHandle); + NOT DB_LoopEffect(_Source, _fxHandle,_ID,"__ANY__",_effect, _BoneName); + DB_LoopEffect(_Source, _NewfxHandle,_ID,"__ANY__",_effect, _BoneName); + + PROC + ProcStartLoopBeamEffectsForRegion((STRING)_Region) + AND + DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,"__ANY__",_effect,_SrcBone,_TargetBone) + AND + PlayLoopBeamEffect(_Source,_Target,_effect,_SrcBone,_TargetBone,_NewEffectHandle) + THEN + ProcStopLoopEffect(_EffectHandle); + NOT DB_LoopBeamEffect(_Source,_Target,_EffectHandle,_ID,"__ANY__",_effect,_SrcBone,_TargetBone); + DB_LoopBeamEffect(_Source,_Target,_NewEffectHandle,_ID,"__ANY__",_effect,_SrcBone,_TargetBone); + + //END_REGION + + IF + RegionEnded(_Region) + THEN + ProcStopEffectsForRegion(_Region); + + // At GameStarted instead of RegionStarted, because sometimes characters are teleported to the current region + // only during RegionStarted, and this RegionStarted handled may be exectuted before the one doing that + // (which results in playing the effect on the character while they are still in the previous level, and that + // triggers an assert) + IF + GameStarted(_Region,_) + THEN + ProcStartEffectsForRegion(_Region); + + //REGION Special case: Some effects should stop during combat + IF + ObjectEnteredCombat(_Character,_) + AND + DB_LoopEffect(_Character, _fxHandle,_ID,_Region,_EffectName,_BoneName) + AND + DB_LoopEffectDisabledInCombat(_EffectName) + THEN + ProcStopLoopEffect(_fxHandle); + NOT DB_LoopEffect(_Character, _fxHandle,_ID,_Region,_EffectName,_BoneName); + DB_LoopEffect(_Character, (INTEGER64)-1, _ID,_Region,_EffectName,_BoneName); + + IF + ObjectLeftCombat((CHARACTERGUID)_Character,_) + AND + NOT DB_Dead(_Character) + AND + DB_LoopEffect(_Character, (INTEGER64)-1, _ID,_Region,_EffectName,_BoneName) + AND + DB_LoopEffectDisabledInCombat(_EffectName) + AND + PlayLoopEffect(_Character, _EffectName, _BoneName,_NewfxHandle) + THEN + NOT DB_LoopEffect(_Character, (INTEGER64)-1, _ID,_Region,_EffectName,_BoneName); + DB_LoopEffect(_Character,_NewfxHandle,_ID,_Region,_EffectName,_BoneName); + + QRY + QryBlockEffectInCombat((STRING)_EffectName,(GUIDSTRING)_Object) + AND + DB_LoopEffectDisabledInCombat(_EffectName) + AND + DB_CombatObjects(_Object,_) + THEN + DB_NOOP(1); + + //END_REGION + + } + EXIT + { + + } +} +Goal(23).Title("_Global_Homestead"); +Goal(23) +{ + INIT + { + + } + KB + { + //REGION Character creation mirror (respec) + IF + CharacterItemEvent(_Player,_Mirror,"GEN_Homestead_CharCreationMirror") + AND + CharacterAddToCharacterCreation(_Player,2,1) + THEN + DB_Illusionist(_Player,_Mirror); + + IF + CharacterItemEvent(_Player,_Mirror,"GEN_Homestead_CharCreationMirror") + AND + HasActiveStatus(_Player,"PLAY_DEAD",1) + THEN + RemoveStatus(_Player,"PLAY_DEAD"); + + //REGION Save while using the mirror -> re-add to character creation after loading (DOSTWO-9410) + IF + SavegameLoaded(_,_,_,_) + AND + DB_Illusionist(_Player,_Mirror) + AND + CharacterAddToCharacterCreation(_Player,2,0) + THEN + DebugBreak("Failed to re-add player to character creation after reload"); + //END_REGION + + //REGION Handle teleportation pyramids + // Avoid other players teleporting into the character creation "level" + IF + DB_Illusionist(_Player,_) + AND + DB_TeleporterPyramid(_Pyramid) + AND + ItemIsInCharacterInventory(_Pyramid,_Player,1) + THEN + Proc_PyramidCustomBlockAdd(_Pyramid,"LV_Mirror"); + + IF + ItemAddedToCharacter(_Pyramid,_Player) + AND + DB_TeleporterPyramid(_Pyramid) + AND + DB_Illusionist(_Player,_Mirror) + THEN + Proc_PyramidCustomBlockAdd(_Pyramid,"LV_Mirror"); + + IF + ItemRemovedFromCharacter(_Pyramid,_Player) + AND + DB_TeleporterPyramid(_Pyramid) + AND + DB_Illusionist(_Player,_Mirror) + THEN + Proc_PyramidCustomBlockRemove(_Pyramid,"LV_Mirror"); + + IF + CharacterCreationFinished(_Player) + AND + DB_Illusionist(_Player,_Mirror) + AND + DB_TeleporterPyramid(_Pyramid) + AND + ItemIsInCharacterInventory(_Pyramid,_Player,1) + THEN + Proc_PyramidCustomBlockRemove(_Pyramid,"LV_Mirror"); + //END_REGION + + //REGION Finished respec + PROC + Proc_HomesteadTeleportAfterMirror((CHARACTERGUID)_Player,(ITEMGUID)_Mirror,(TRIGGERGUID)_Trigger) + AND + _Trigger!=NULL_00000000-0000-0000-0000-000000000000 + THEN + TeleportTo(_Player,_Trigger,"",0); + + PROC + Proc_HomesteadTeleportAfterMirror((CHARACTERGUID)_Player,(ITEMGUID)_Mirror,(TRIGGERGUID)_Trigger) + AND + _Trigger==NULL_00000000-0000-0000-0000-000000000000 + THEN + TeleportTo(_Player,_Mirror,"",0); + + IF + CharacterCreationFinished(_Player) + AND + DB_Illusionist(_Player,_Mirror) + AND + GetVarObject(_Mirror,"PlayerPositionAfterCreation",_Trigger) + THEN + NOT DB_Illusionist(_Player,_Mirror); + Proc_HomesteadTeleportAfterMirror(_Player,_Mirror,(TRIGGERGUID)_Trigger); + //END_REGION + + //END_REGION + + } + EXIT + { + + } +} +Goal(24).Title("_GLOBAL_ItemEvents"); +Goal(24) +{ + INIT + { + /* + Databases used for this events + DB_HasStoryEvent((ITEMGUID)_Item,_HasItemEvent); + DB_GiveItemToEvent(_Item,_GiveItemToStoryEvent); + */ + ///Please Add any Item tags that you want to be tracked HERE!! + //when declaredo n the fly only players will be checked + DB_TaggedItemInitialSetup(1); + DB_TaggedItemTracker("HEALING_POTION"); + DB_TaggedItemTracker("BODYPART"); + DB_TaggedItemTracker("MEAT"); + DB_TaggedItemTracker("FISH"); + DB_TaggedItemTracker("BOOK"); + DB_TaggedItemTracker("QUEST_ANCESTOR_TREE_BRANCH"); + DB_TaggedItemTracker("FOOD"); + DB_TaggedItemTracker("BONE"); + DB_TaggedItemTracker("TOY"); + DB_TaggedItemTracker("ALCOHOL"); + DB_TaggedItemTracker("CHEESE"); + DB_TaggedItemTracker("VEGETABLE"); + DB_TaggedItemTracker("DRUDANAE"); + NOT DB_TaggedItemInitialSetup(1); + + DB_ItemEvents_TransferFlagToMoneyVarIndex("GEN_TransferNPCPayment",1); + DB_ItemEvents_TransferFlagToMoneyVarIndex("GEN_TransferNPCPayment_2",2); + DB_ItemEvents_TransferFlagToMoneyVarIndex("GEN_TransferNPCPayment_3",3); + DB_ItemEvents_TransferFlagToMoneyVarIndex("GEN_TransferNPCPayment_4",4); + DB_ItemEvents_TransferFlagToMoneyVarIndex("GEN_TransferNPCPayment_5",5); + + } + KB + { + //REGION Event Recheck triggers + //see also ZZZ_ItemEvents for a trigger + IF + CharacterMadePlayer(_Player) + THEN + DB_IgnoreReservedChanged(_Player); + + IF + DB_CharacterCreationDummy((CHARACTERGUID)_Char) + THEN + DB_IgnoreReservedChanged(_Char); + + IF + CharacterReservedUserIDChanged(_Char,_) + AND + DB_IsPlayer(_Char) + AND + NOT DB_IgnoreReservedChanged(_Char) + THEN + Proc_ItemEventCheck(); + + IF + CharacterReservedUserIDChanged(_Char,_) + THEN + NOT DB_IgnoreReservedChanged(_Char); + + IF + SavegameLoaded(_,_,_,_) + THEN + Proc_ItemEventCheck(); + + PROC + PROC_GLO_PartyMembers_Add((CHARACTERGUID)_Origin,(CHARACTERGUID)_) + THEN + Proc_ItemEventCheck(); + + //END_REGION + + //REGION Private + PROC + ProcSetMagicPocketsItemTemplatecount((CHARACTERGUID)_Player,(STRING)_Template,(INTEGER)_) + AND + DB_MagicPocketsItemTemplateCount(_Player,_Template,_Count) + THEN + NOT DB_MagicPocketsItemTemplateCount(_Player,_Template,_Count); + + PROC + ProcSetMagicPocketsItemTemplatecount((CHARACTERGUID)_Player,(STRING)_Template,(INTEGER)_Count) + THEN + DB_MagicPocketsItemTemplateCount(_Player,_Template,_Count); + //END_REGION + + //REGION Eating a bodypart + IF + StoryEvent(_Player,"GEN_CloseInventory") + THEN + CloseUI((CHARACTERGUID)_Player,"Inventory"); + + IF + CharacterItemEvent(_Char,_BodyPart,_Dialog) + AND + DB_AwaitingBodypartDialog(_Char,_BodyPart) + THEN + NOT DB_AwaitingBodypartDialog(_Char,_BodyPart); + ProcCheckBodyPartDialog(_Char,_Dialog); + + IF + CharacterItemEvent(_Char,_BodyPart,"GLO_AteBodyPart") + THEN + DB_AwaitingBodypartDialog(_Char,_BodyPart); + + PROC + ProcCheckBodyPartDialog((CHARACTERGUID)_Char,(STRING)_Dialog) + AND + _Dialog!="" + THEN + ProcTriggerLimbEatingDialog(_Char,_Dialog); + + PROC + ProcTriggerLimbEatingDialog((CHARACTERGUID)_Char,(STRING)_Dialog) + AND + CharacterIsInCombat(_Char,0) + THEN + Proc_StartDialog(0,_Dialog,_Char); + + PROC + ProcTriggerLimbEatingDialog((CHARACTERGUID)_Char,(STRING)_Dialog) + AND + CharacterIsInCombat(_Char,1) + THEN + CloseUI(_Char,"Inventory"); + + IF + DialogEnded("GEN_Limb_RottenLimb", _ID) + AND + DB_DialogPlayers(_ID, _Player, _) + AND + CharacterConsume((CHARACTERGUID)_Player, "CON_BodyPart_Harm", _) + THEN + DB_NOOP(0); + //END_REGION + + //REGION Magic Pockets procedures + QRY + QryItemInMagicPockets((CHARACTERGUID)_Char,(ITEMGUID)_Item) + AND + ItemIsInUserInventory(_Item,_Char,0,1) + THEN + DB_NOOP(1); + + QRY + QryItemTemplateInMagicPockets((CHARACTERGUID)_Char,(STRING)_ItemTemplate) + AND + ItemTemplateIsInUserInventory(_Char,_ItemTemplate,0,_Count) + AND + _Count > 0 + THEN + DB_NOOP(1); + + QRY + QryTaggedItemInMagicPockets((CHARACTERGUID)_Character,(STRING)_Tag) + AND + UserFindTaggedItem(_Character,_Tag,0,_Item) + THEN + DB_NOOP(1); + + QRY + QryItemTemplateInMagicPocketsCount((CHARACTERGUID)_Player,(STRING)_Template) + AND + ItemTemplateIsInUserInventory(_Player,_Template,0,_Count) + AND + _Count > 0 + THEN + ProcSetMagicPocketsItemTemplatecount(_Player,_Template,_Count); + + QRY + QryRemoveTaggedLocalItemsFromMagicPockets((CHARACTERGUID)_Player,(STRING)_Tag,(INTEGER)_Amount) + AND + UserRemoveTaggedLocalItems(_Player,_Tag,_Amount,_Count) + AND + _Count == _Amount + THEN + DB_NOOP(1); + + QRY + QryTakeItemFromMagicPockets((CHARACTERGUID)_Player,(ITEMGUID)_Item,(CHARACTERGUID)_TargetCharacter) + AND + ItemIsInUserInventory(_Item,_Player, 1, 1) + THEN + ItemToInventory(_Item,_TargetCharacter); + + QRY + QryTakeItemTemplateFromMagicPockets((CHARACTERGUID)_Character,(STRING)_ItemTemplate,(INTEGER)_Amount,(CHARACTERGUID)_TargetCharacter) + AND + ItemTemplateIsInUserInventory(_Character,_ItemTemplate,1,_Amount) + THEN + ItemTemplateRemoveFromUser(_ItemTemplate,_Character,_Amount); + ItemTemplateAddTo(_ItemTemplate,_TargetCharacter,_Amount); + + QRY + QryRemoveItemTemplateFromMagicPockets((CHARACTERGUID)_Character,(STRING)_ItemTemplate,(INTEGER)_Amount) + AND + ItemTemplateIsInUserInventory(_Character,_ItemTemplate,1,_HaveAmount) + AND + _HaveAmount >= _Amount + THEN + ItemTemplateRemoveFromUser(_ItemTemplate,_Character,_Amount); + + //TODO: take amount into account + QRY + QryRemoveTaggedItemFromMagicPockets((CHARACTERGUID)_Character,(STRING)_Tag, (INTEGER)_Amount) + AND + UserFindTaggedItem(_Character,_Tag,1,_Item) + THEN + ItemRemove(_Item); + + QRY + QryEvaluateMagicPocketGold((CHARACTERGUID)_Character,"<",(INTEGER)_Amount) + AND + UserGetGold(_Character,_Gold) + AND + _Gold < _Amount + THEN + DB_NOOP(1); + + QRY + QryEvaluateMagicPocketGold((CHARACTERGUID)_Character,"<=",(INTEGER)_Amount) + AND + UserGetGold(_Character,_Gold) + AND + _Gold <= _Amount + THEN + DB_NOOP(1); + + QRY + QryEvaluateMagicPocketGold((CHARACTERGUID)_Character,">",(INTEGER)_Amount) + AND + UserGetGold(_Character,_Gold) + AND + _Gold > _Amount + THEN + DB_NOOP(1); + + QRY + QryEvaluateMagicPocketGold((CHARACTERGUID)_Character,">=",(INTEGER)_Amount) + AND + UserGetGold(_Character,_Gold) + AND + _Gold >= _Amount + THEN + DB_NOOP(1); + + QRY + QryEvaluateMagicPocketGold((CHARACTERGUID)_Character,"==",(INTEGER)_Amount) + AND + UserGetGold(_Character,_Gold) + AND + _Gold == _Amount + THEN + DB_NOOP(1); + + PROC + ProcEvaluateMagicPocketGold((CHARACTERGUID)_Character,"<",(INTEGER)_Amount,(STRING)_ObjectFlag) + AND + UserGetGold(_Character,_Gold) + AND + _Gold < _Amount + THEN + ObjectSetFlag(_Character,_ObjectFlag); + + PROC + ProcEvaluateMagicPocketGold((CHARACTERGUID)_Character,"<=",(INTEGER)_Amount,(STRING)_ObjectFlag) + AND + UserGetGold(_Character,_Gold) + AND + _Gold <= _Amount + THEN + ObjectSetFlag(_Character,_ObjectFlag); + + PROC + ProcEvaluateMagicPocketGold((CHARACTERGUID)_Character,"==",(INTEGER)_Amount,(STRING)_ObjectFlag) + AND + UserGetGold(_Character,_Gold) + AND + _Gold == _Amount + THEN + ObjectSetFlag(_Character,_ObjectFlag); + + PROC + ProcEvaluateMagicPocketGold((CHARACTERGUID)_Character,">",(INTEGER)_Amount,(STRING)_ObjectFlag) + AND + UserGetGold(_Character,_Gold) + AND + _Gold > _Amount + THEN + ObjectSetFlag(_Character,_ObjectFlag); + + PROC + ProcEvaluateMagicPocketGold((CHARACTERGUID)_Character,">=",(INTEGER)_Amount,(STRING)_ObjectFlag) + AND + UserGetGold(_Character,_Gold) + AND + _Gold >= _Amount + THEN + ObjectSetFlag(_Character,_ObjectFlag); + + PROC + ProcAddGoldToMagicPockets((CHARACTERGUID)_Char,(INTEGER)_Gold) + THEN + UserAddGold(_Char,_Gold); + + PROC + ProcLaunchMagicPocketIterator((CHARACTERGUID)_Character,(STRING)_Event, (STRING)_CompletionEvent) + AND + CharacterGetReservedUserID(_Character,_OwnerUser) + AND + DB_IsPlayer(_Player) + AND + CharacterGetReservedUserID(_Player,_OwnerUser) + THEN + InventoryLaunchIterator(_Player, _Event, ""); + + PROC + ProcLaunchMagicPocketIterator((CHARACTERGUID)_Character,(STRING)_Event, (STRING)_CompletionEvent) + AND + _CompletionEvent != "" + THEN + GlobalSetFlag(_CompletionEvent); + + PROC + ProcLaunchMagicPocketTagIterator((CHARACTERGUID)_Character,(STRING)_TagA,(STRING)_TagB,(STRING)_Event,(STRING)_CompletionEvent) + AND + CharacterGetReservedUserID(_Character,_OwnerUser) + AND + DB_IsPlayer(_Player) + AND + CharacterGetReservedUserID(_Player,_OwnerUser) + THEN + InventoryLaunchTagIterator(_Player,_TagA,_TagB,_Event,""); + + PROC + ProcLaunchMagicPocketTagIterator((CHARACTERGUID)_Character,(STRING)_TagA,(STRING)_TagB,(STRING)_Event,(STRING)_CompletionEvent) + AND + _CompletionEvent != "" + THEN + GlobalSetFlag(_CompletionEvent); + + PROC + ProcSetMagicPocketsOwnershipFlag((CHARACTERGUID)_Char,(STRING)_Flag) + AND + DB_IsPlayer(_Char) + THEN + UserSetFlag(_Char,_Flag,0); + + PROC + ProcSetMagicPocketsOwnershipFlag((CHARACTERGUID)_Char,(STRING)_Flag) + AND + NOT DB_IsPlayer(_Char) + THEN + ObjectSetFlag(_Char,_Flag); + + PROC + ProcClearMagicPocketsOwnershipFlag((CHARACTERGUID)_Char,(STRING)_Flag) + AND + DB_IsPlayer(_Char) + THEN + UserClearFlag(_Char,_Flag,0); + + PROC + ProcClearMagicPocketsOwnershipFlag((CHARACTERGUID)_Char,(STRING)_Flag) + AND + NOT DB_IsPlayer(_Char) + THEN + ObjectClearFlag(_Char,_Flag,0); + + //REGION General Give - Take Gold in dialogs + + // Usage: + // DB_DialogMoneyTransfer(_MoneyVarIndex,_Dialog,_Amount) + // DB_DialogMoneyTransfer(_MoneyVarIndex,_Dialog,_Amount,_CheckSpeakerIndex) + // DB_DialogMoneyTransfer(_MoneyVarIndex,_Dialog,_Amount,_CheckSpeakerIndex,_TargetDBIndex) + // + // Paramters: + // - _MoneyVarIndex: 1 - 5 (use different GEN_CheckMagicPocketGold variables) + // - _Dialog: name of the dialog + // - _Amount: amount of money transfer + // - _CheckSpeakerIndex: the speaker index on which the money should be checked by the + // GEN_CheckPocketGold* script flags. If not specified, defaults to 2 (player in most cases). + // ** NOTE: this Speaker index is a dialog speaker index, as assigned in the dialog + // - _TargetDBIndex: when the GEN_TransferNPCPayment/GEN_TransferNPCPayment_2/../GEN_TransferNPCPayment_5 flag + // is set on a player in a dialog, transfer the money from that player to DB_DialogNPCs(_ID,_NPC,_TargetDBIndex). + // When set on an NPC in a dialog, transfer from that NPC to DB_DialogPlayers(_ID,_Player,_TargetDBIndex). + // If not specified, defaults to 1 (first NPC/player in dialog) + // ** NOTE: this index is an index in DB_DialogNPCs resp. DB_DialogPlayers, and hence is unrelated to the + // the speaker indices in the dialog editor! + // + // If someone does not have enough gold and a transfer is requested, all of their gold will be transferred instead. + + //REGION Default speaker to check and target Player/NPC for the money transfer if unspecified + PROC + Proc_ItemEvents_DialogMoneyTransfer_New((INTEGER)_MoneyVarIndex,(STRING)_Dialog,(INTEGER)_Amount,(INTEGER)_CheckSpeakerIndex,(INTEGER)_TargetDBIndex) + AND + DB_DialogMoneyTransfer(_MoneyVarIndex,_Dialog,_AnyAmount,_AnyCheckSpeakerIndex,_AnyTargetDBIndex) + THEN + NOT DB_DialogMoneyTransfer(_MoneyVarIndex,_Dialog,_AnyAmount,_AnyCheckSpeakerIndex,_AnyTargetDBIndex); + + PROC + Proc_ItemEvents_DialogMoneyTransfer_New((INTEGER)_MoneyVarIndex,(STRING)_Dialog,(INTEGER)_Amount,(INTEGER)_CheckSpeakerIndex,(INTEGER)_TargetDBIndex) + THEN + DB_DialogMoneyTransfer(_MoneyVarIndex,_Dialog,_Amount,_CheckSpeakerIndex,_TargetDBIndex); + + // Default to most common player speaker index (2) and transfer to the first NPC or Player in the dialog (1) + IF + DB_DialogMoneyTransfer((INTEGER)_MoneyVarIndex,(STRING)_Dialog,(INTEGER)_Amount) + THEN + Proc_ItemEvents_DialogMoneyTransfer_New(_MoneyVarIndex,_Dialog,_Amount,2,1); + + IF + DB_DialogMoneyTransfer((INTEGER)_MoneyVarIndex,(STRING)_Dialog,(INTEGER)_Amount,(INTEGER)_CheckSpeakerIndex) + THEN + Proc_ItemEvents_DialogMoneyTransfer_New(_MoneyVarIndex,_Dialog,_Amount,_CheckSpeakerIndex,1); + //END_REGION + + //REGION Transfer gold between player and NPC + // If the transfer flag is set on a player, transfer from player to NPC. Otherwise vice versa. + + PROC + Proc_GiveNPCGold((CHARACTERGUID)_Player,(CHARACTERGUID)_NPC,(INTEGER)_Amount) + AND + IntegerSubtract(0,_Amount,_RemoveGold) + THEN + ProcAddGoldToMagicPockets(_Player,_RemoveGold); + CharacterAddGold(_NPC,_Amount); + + PROC + Proc_TakeNPCGold((CHARACTERGUID)_Player,(CHARACTERGUID)_NPC,(INTEGER)_Amount) + AND + IntegerSubtract(0,_Amount,_RemoveGold) + THEN + ProcAddGoldToMagicPockets(_Player,_Amount); + CharacterAddGold(_NPC,_RemoveGold); + + PROC + Proc_ItemEventsTransferMoney((INTEGER)_ID,(INTEGER)_Amount,(CHARACTERGUID)_Source,(INTEGER)_TargetIndex) + AND + DB_DialogPlayers(_ID,_Source,_) + AND + DB_DialogNPCs(_ID,_NPC,_TargetIndex) + THEN + Proc_GiveNPCGold(_Source,(CHARACTERGUID)_NPC,_Amount); + + PROC + Proc_ItemEventsTransferMoney(_ID,_Amount,_Source,_TargetIndex) + AND + DB_DialogNPCs(_ID,_Source,_) + AND + DB_DialogPlayers(_ID,_Player,_TargetIndex) + AND + CharacterGetGold(_Source,_NPCGold) + AND + IntegerMin(_NPCGold,_Amount,_TransferAmount) + THEN + Proc_TakeNPCGold((CHARACTERGUID)_Player,_Source,_TransferAmount); + + IF + ObjectFlagSet(_TransferFlag,_Source,_ID) + AND + DB_ItemEvents_TransferFlagToMoneyVarIndex(_TransferFlag,_MoneyVarIndex) + AND + DB_DialogName(_Dialog,_ID) + AND + DB_DialogMoneyTransfer(_MoneyVarIndex,_Dialog,_Amount,_CheckSpeakerIndex,_TargetDBIndex) + THEN + Proc_ItemEventsTransferMoney(_ID,_Amount,(CHARACTERGUID)_Source,_TargetDBIndex); + + //END_REGION + + //REGION Reset transfer flag + IF + ObjectFlagSet(_TransferFlag,_Char,_ID) + AND + DB_ItemEvents_TransferFlagToMoneyVarIndex(_TransferFlag,_) + THEN + ObjectClearFlag(_Char,_TransferFlag); + //END_REGION + + //END_REGION + + //REGION Has, lose and give items + IF + ItemAddedToCharacter(_Item,_Char) + AND + DB_HasStoryEvent((ITEMGUID)_Item,_Event) + THEN + SetOnStage(_Item,1); + ProcSetMagicPocketsOwnershipFlag(_Char,_Event); + + IF + ItemRemovedFromCharacter(_Item,_Char) + AND + DB_HasStoryEvent((ITEMGUID)_Item,_Event) + THEN + ProcClearMagicPocketsOwnershipFlag(_Char,_Event); + + IF + DB_HasStoryEvent((ITEMGUID)_Item,(STRING)_Event) + AND + ItemGetOwner(_Item,_Owner) + AND + _Owner != NULL_00000000-0000-0000-0000-000000000000 + AND + ItemIsInCharacterInventory(_Item,_Owner,1) + THEN + ProcSetMagicPocketsOwnershipFlag(_Owner,_Event); + + IF + ObjectFlagSet(_Event,_Char,_) + AND + DB_GiveItemToEvent((ITEMGUID)_Item,_Event) + THEN + ItemToInventory(_Item,_Char,1); + + //For giving the same item multiple times + IF + ObjectFlagSet(_Event,_Char,_) + AND + DB_GiveItemToEventWithClear((ITEMGUID)_Item,_Event) + THEN + ItemToInventory(_Item,_Char,1); + ObjectClearFlag(_Char,_Event,0); + + PROC + Proc_ItemEventCheck() + AND + DB_IsPlayer(_Char) + AND + DB_HasStoryEvent(_,_Event) + THEN + ProcClearMagicPocketsOwnershipFlag(_Char,_Event); + + PROC + Proc_ItemEventCheck() + AND + DB_HasStoryEvent((ITEMGUID)_Item,_Event) + AND + ObjectExists(_Item,1) + AND + ItemIsInInventory(_Item,1) + AND + ItemGetOwner(_Item,_Char) + AND + DB_IsPlayer(_Char) + THEN + ProcSetMagicPocketsOwnershipFlag(_Char,_Event); + + //END_REGION + + //REGION Check for Tagged Items in Characters Inventory + //If You want to Keep track of a specific Item tag going in and out of the inventory, add that tag to DB_TaggedItemTracker(_String) + + IF + ItemAddedToCharacter(_Item,_Char) + AND + ObjectExists(_Item,1) //prevent stacked items from asserting all over the place + AND + DB_TaggedItemTracker((STRING)_Tag) + AND + IsTagged(_Item,_Tag,1) + AND + StringConcatenate("Has_TaggedItem_",_Tag,_Flag) + THEN + ProcSetMagicPocketsOwnershipFlag(_Char,_Flag); + DB_HasTaggedItem(_Char,_Item,_Tag,_Flag); + + IF + DB_TaggedItemInitialSetup(1) + THEN + DB_TaggedItemRecheck(1); + + IF + DB_TaggedItemRecheck(1) + AND + NOT DB_TaggedItemInitialSetup(1) + THEN + NOT DB_TaggedItemRecheck(1); + ProcCheckItemTags(); + + PROC + ProcCheckItemTags() + AND + DB_IsPlayer(_Player) + AND + DB_TaggedItemTracker(_Tag) + THEN + DB_ItemTagCheckingPlayer((CHARACTERGUID)_Player,_Tag); + InventoryLaunchTagIterator(_Player,_Tag,"","_Check_Item_Tags_",""); + FireOsirisEvents(); + NOT DB_ItemTagCheckingPlayer(_Player,_Tag); + + IF + StoryEvent((ITEMGUID)_Item,"_Check_Item_Tags_") + AND + DB_ItemTagCheckingPlayer(_Player,_Tag) + AND + StringConcatenate("Has_TaggedItem_",_Tag,_Flag) + THEN + ProcSetMagicPocketsOwnershipFlag(_Player,_Flag); + DB_HasTaggedItem(_Player,_Item,_Tag,_Flag); + + IF + DB_TaggedItemTracker(_Tag) + AND + NOT DB_TaggedItemInitialSetup(1) + THEN + ProcCheckInventoriesForTag(_Tag); + + PROC + ProcCheckInventoriesForTag((STRING)_Tag) + AND + DB_IsPlayer(_Player) + THEN + DB_ItemTagCheckingPlayer(_Player,_Tag); + InventoryLaunchTagIterator(_Player,_Tag,"","_Check_Item_Tag_",""); + FireOsirisEvents(); + NOT DB_ItemTagCheckingPlayer(_Player,_Tag); + + IF + StoryEvent((ITEMGUID)_Item, "_Check_Item_Tag_") + AND + DB_ItemTagCheckingPlayer(_Char,_Tag) + AND + StringConcatenate("Has_TaggedItem_",_Tag,_Flag) + THEN + ProcSetMagicPocketsOwnershipFlag(_Char,_Flag); + DB_HasTaggedItem(_Char,_Item,_Tag,_Flag); + + + IF + ItemStackedWith(_Item,_) + AND + DB_HasTaggedItem(_Char,_Item,_String,_Flag) + THEN + NOT DB_HasTaggedItem(_Char,_Item,_String,_Flag); + + IF + ItemRemovedFromCharacter(_Item,_Char) + AND + DB_HasTaggedItem((CHARACTERGUID)_Char,_Item,_String,_Flag) + THEN + NOT DB_HasTaggedItem(_Char,_Item,_String,_Flag); + Proc_CheckForItemTagInMagicPockets(_Char,_String); + + PROC + Proc_CheckForItemTagInMagicPockets((CHARACTERGUID)_Char,(STRING)_Tag) + AND + NOT QryTaggedItemInMagicPockets(_Char,_Tag) + AND + StringConcatenate("Has_TaggedItem_",_Tag,_Flag) + THEN + ProcClearMagicPocketsOwnershipFlag(_Char,_Flag); + + PROC + Proc_ItemEventCheck() + AND + DB_HasTaggedItem(_,_,_Tag,_Flag) + AND + DB_IsPlayer(_Char) + THEN + ProcClearMagicPocketsOwnershipFlag(_Char,_Flag); + + IF + RegionStarted(_) + AND + DB_HasTaggedItem(_Char,_Item,_Tag,_Flag) + AND + ObjectExists(_Char,0) + THEN + NOT DB_HasTaggedItem(_Char,_Item,_Tag,_Flag); + + PROC + Proc_ItemEventCheck() + AND + DB_HasTaggedItem(_Char,_Item,_Tag,_Flag) + THEN + ProcSetMagicPocketsOwnershipFlag(_Char,_Flag); + + //END_REGION + + + //REGION On item template on gain and lose + //DB_HasTemplateItem((STRING)_template,(STRING)_HasItemFlag) + //If item is added to inventory + IF + ItemTemplateAddedToCharacter(_templateGUID,_item,_char) + AND + String(_templateGUID,_template) + AND + DB_HasTemplateItem((STRING)_template,(STRING)_flag) + THEN + Proc_OnAddItemTemplateToChar(_char,_template,_flag); + + //If item is removed from inventory + IF + ItemTemplateRemovedFromCharacter(_template,_item,_char) + AND + DB_HasTemplateItem((STRING)_template,(STRING)_flag) + THEN + Proc_OnRemoveItemTemplateFromChar(_char,_template,_flag); + + IF + DB_HasTemplateItem((STRING)_template,(STRING)_flag) + AND + DB_IsPlayer(_Player) + THEN + Proc_OnAddItemTemplateToChar(_Player,_template,_flag); + + PROC + Proc_ItemEventCheck() + AND + DB_HasTemplateItem((STRING)_template,(STRING)_flag) + AND + DB_IsPlayer(_Player) + THEN + ProcClearMagicPocketsOwnershipFlag(_Player,_flag); + Proc_OnAddItemTemplateToChar(_Player,_template,_flag); + + //Proc on template add + PROC + Proc_OnAddItemTemplateToChar((CHARACTERGUID)_char,(STRING)_template,(STRING)_flag) + AND + ItemTemplateIsInUserInventory(_char,_template,0,_amount) + AND + _amount > 0 + THEN + ProcSetMagicPocketsOwnershipFlag(_char,_flag); + + //Proc on template remove + PROC + Proc_OnRemoveItemTemplateFromChar((CHARACTERGUID)_char,(STRING)_template,(STRING)_flag) + AND + ItemTemplateIsInUserInventory(_char,_template,0,_amount) + AND + _amount < 1 + THEN + ProcClearMagicPocketsOwnershipFlag(_char,_flag); + + //END_REGION + + //REGION Give/remove Item template + //Gives item when flag is set + IF + ObjectFlagSet(_event,(CHARACTERGUID)_target,_inst) + AND + DB_GiveTemplateFromPlayerDialogEvent((STRING)_template,(STRING)_event,(STRING)_success) + AND + DialogGetInvolvedPlayer(_inst, 1, (CHARACTERGUID)_player) + THEN + ObjectClearFlag(_target,_event,0); //Flag is cleared again + Proc_PlayerGivesItemFromTemplate(_player,_target,_template,_success); + + + //Gives item when flag is set + IF + ObjectFlagSet(_event,(CHARACTERGUID)_target,_inst) + AND + DB_GiveTemplateFromNpcToPlayerDialogEvent((STRING)_template,(STRING)_event,(STRING)_success) + AND + DialogGetInvolvedPlayer(_inst, 1, (CHARACTERGUID)_player) + THEN + ObjectClearFlag(_target,_event,0); //Flag is cleared again + Proc_NPCGivesItemFromTemplate(_target,_player,_template,_success); + + + //Gives item when flag is set + IF + ObjectFlagSet(_event,_char,_) + AND + DB_GiveNewItemFromTemplateEvent((STRING)_template,(STRING)_event) + THEN + ObjectClearFlag((CHARACTERGUID)_char,(STRING)_event,0); //Flag is cleared again + ItemTemplateAddTo(_template,_char,1); + + + //Remove item when flag set + IF + ObjectFlagSet(_event,(CHARACTERGUID)_char,_) + AND + DB_RemoveItemFromTemplateEvent((STRING)_template,(STRING)_event,(STRING)_success) + THEN + ObjectClearFlag(_char,_event,0); //Flag is cleared again + Proc_RemoveItemFromTemplate(_char,_template,_success); + + //END_REGION + + //REGION Give/Remove Template Proc + //Giving Item + PROC + Proc_PlayerGivesItemFromTemplate((CHARACTERGUID)_Player,(CHARACTERGUID)_target,(STRING)_template,(STRING)_success) + AND + QryRemoveItemTemplateFromMagicPockets(_Player,_Template,1) + THEN + ItemTemplateAddTo(_template,_target,1); + ObjectSetFlag(_target,_success); + + //Mirrored Give to set _success on NPC instead of player + PROC + Proc_NPCGivesItemFromTemplate((CHARACTERGUID)_giver,(CHARACTERGUID)_target,(STRING)_template,(STRING)_success) + AND + ItemTemplateIsInCharacterInventory(_giver,_template,_amount) + AND + _amount > 0 + THEN + ItemTemplateRemoveFrom(_template,_giver,1); + ItemTemplateAddTo(_template,_target,1); + ObjectSetFlag(_giver,_success); + + //Remove Item + PROC + Proc_RemoveItemFromTemplate((CHARACTERGUID)_char,(STRING)_template,(STRING)_success) + AND + DB_IsPlayer(_Char) + AND + QryRemoveItemTemplateFromMagicPockets(_char,_template,1) + THEN + ObjectSetFlag(_char,_success); + + PROC + Proc_RemoveItemFromTemplate((CHARACTERGUID)_char,(STRING)_template,(STRING)_success) + AND + NOT DB_IsPlayer(_Char) + AND + ItemTemplateIsInCharacterInventory(_char,_template,_amount) + AND + _amount > 0 + THEN + ItemTemplateRemoveFrom(_template,_char,1); + ObjectSetFlag(_char,_success); + //END_REGION + + IF + DialogEnded(_,_ID) + AND + DialogGetInvolvedNPC(_ID,1,(ITEMGUID)_Item) + AND + ObjectIsItem(_Item,1) + AND + ObjectGetFlag(_Item,"ItemPickup",1) + AND + DialogGetInvolvedPlayer(_ID,1,(CHARACTERGUID)_Player) + THEN + CharacterPickupItem(_Player,_Item,""); + ObjectClearFlag(_Item,"ItemPickup",0); + + //REGION Play Activate animation from Script + + IF + StoryEvent((CHARACTERGUID)_Player,"GEN_Animation_Activate") + THEN + PlayAnimation(_Player,"use_activate"); + + //END_REGION + + + + } + EXIT + { + + } +} +Goal(25).Title("_Global_JournalHelper"); +Goal(25) +{ + INIT + { + + } + KB + { + //REGION Init + + PROC + ProcCheckDefaultQuestAdd((STRING)_QuestName) + AND + NOT DB_QuestDef_AddEvent(_QuestName,_) + AND + StringConcatenate("QuestAdd_",_QuestName,_AddEvent) + THEN + DB_QuestDef_AddEvent(_QuestName,_AddEvent); + + PROC + ProcCheckDefaultQuestClose((STRING)_QuestName) + AND + NOT DB_QuestDef_CloseEvent(_QuestName,_) + AND + StringConcatenate("QuestClose_",_QuestName,_CloseEvent) + THEN + DB_QuestDef_CloseEvent(_QuestName,_CloseEvent); + + IF + DB_QuestDef_State((STRING)_QuestName,(STRING)_QuestState, 1) //Indices allow you to define multiple start and end events for every quest. + AND + StringConcatenate("QuestUpdate_",_QuestName,_String1) + AND + StringConcatenate(_String1,"_",_String2) + AND + StringConcatenate(_String2,_QuestState,_AddEvent) + THEN + DB_QuestDef_AddEvent(_QuestName,_AddEvent); + DB_QuestDef_State((STRING)_QuestName,(STRING)_QuestState); + + IF + DB_QuestDef_State((STRING)_QuestName,(STRING)_QuestState, -1) + AND + StringConcatenate("QuestUpdate_",_QuestName,_String1) + AND + StringConcatenate(_String1,"_",_String2) + AND + StringConcatenate(_String2,_QuestState,_CloseEvent) + THEN + DB_QuestDef_CloseEvent(_QuestName,_CloseEvent); + DB_QuestDef_State((STRING)_QuestName,(STRING)_QuestState); + + IF + DB_QuestDef_State((STRING)_QuestName,(STRING)_QuestState) + AND + NOT DB_QuestDef_UpdateEvent(_QuestName,_QuestState, _) + AND + StringConcatenate("QuestUpdate_",_QuestName,_String1) + AND + StringConcatenate(_String1,"_",_String2) + AND + StringConcatenate(_String2,_QuestState,_UpdateEvent) + THEN + ProcCheckDefaultQuestAdd(_QuestName); + ProcCheckDefaultQuestClose(_QuestName); + DB_QuestDef_UpdateEvent(_QuestName,_QuestState,_UpdateEvent); + //END_REGION + + //REGION Unlocking quests + IF + ObjectFlagSet(_QuestAddEvent,(CHARACTERGUID)_Player, _) + AND + DB_QuestDef_AddEvent(_QuestName,_QuestAddEvent) + AND + DB_IsPlayer(_Player) + THEN + QuestAdd(_Player,_QuestName); + DB_ActivatedQuests(_QuestName); + ProcSetQuestNPCFlag(_QuestName,_QuestAddEvent); + ProcCheckMigrateQuestAddFlag(_Player,_QuestName,_QuestAddEvent); + + //don't migrate quest add flags that also trigger an update, since we'll be trying ot share the update already before the original player + //had a chance to get the update + PROC + ProcCheckMigrateQuestAddFlag((CHARACTERGUID)_Player,(STRING)_QuestName,(STRING)_QuestAddEvent) + AND + NOT DB_QuestDef_UpdateEvent(_QuestName,_,_QuestAddEvent) + THEN + ProcMigrateQuestFlag(_Player,_QuestName,_QuestAddEvent); + + IF + ObjectFlagSet(_QuestUpdateEvent,(CHARACTERGUID)_Player, _) + AND + DB_QuestDef_UpdateEvent(_QuestName,_QuestState,_QuestUpdateEvent) + AND + DB_IsPlayer(_Player) + AND + QuestIsClosed(_Player,_QuestName,0) + THEN + QuestUpdate(_Player,_QuestName,_QuestState); + ProcMigrateQuestFlag(_Player,_QuestName,_QuestUpdateEvent); + ProcSetQuestNPCFlag(_QuestName,_QuestUpdateEvent); + + IF + ObjectFlagSet(_QuestCloseEvent,(CHARACTERGUID)_Player, _) + AND + DB_QuestDef_CloseEvent(_QuestName,_QuestCloseEvent) + AND + DB_IsPlayer(_Player) + THEN + QuestClose(_Player,_QuestName); + ProcMigrateQuestFlag(_Player,_QuestName,_QuestCloseEvent); + ProcSetQuestNPCFlag(_QuestName,_QuestCloseEvent); + + PROC + ProcSetQuestNPCFlag((STRING)_QuestName,(STRING)_QuestEvent) + AND + DB_QuestNPC(_QuestName,(CHARACTERGUID)_NPC) + THEN + ObjectSetFlag(_NPC,_QuestEvent,0); + + + //END_REGION + + //REGION Merging quests + + IF + CharacterMadePlayer(_Player) + THEN + DB_JournalIgnoreReservedChanged(_Player); + + IF + CharacterReservedUserIDChanged(_Char,_NewUser) + AND + DB_IsPlayer(_Char) + AND + NOT DB_JournalIgnoreReservedChanged(_Char) + THEN + ProcMigrateQuestsForUser(_NewUser,_Char); + + IF + CharacterReservedUserIDChanged(_Char,_) + THEN + NOT DB_JournalIgnoreReservedChanged(_Char); + + IF + CharacterJoinedParty(_Joiner) + AND + DB_IsPlayer(_Joiner) + AND + DB_ActivatedQuests(_Quest) + THEN + ProcMigrateQuest(_Joiner,_Quest); + + IF + CharacterJoinedParty(_Joiner) + AND + DB_IsPlayer(_Joiner) + THEN + ProcShareQuestsWithParty(_Joiner); + + PROC + ProcShareQuestsWithParty((CHARACTERGUID)_Joiner) + AND + DB_IsPlayer(_Player) + AND + NOT DB_MigratedNewPartyFlags(1) + AND + _Player != _Joiner + AND + CharacterIsInPartyWith(_Player,_Joiner,1) + AND + DB_ActivatedQuests(_Quest) + AND + DB_SharedQuestFlag(_Player,_Quest,_QuestFlag) + THEN + DB_MigratedNewPartyFlags(1); + ProcShareQuestflagWith(_Player,_Quest,_QuestFlag,_Joiner); + + PROC + ProcShareQuestsWithParty((CHARACTERGUID)_Joiner) + THEN + NOT DB_MigratedNewPartyFlags(1); + + //always share quests with the owning user + IF + CharacterJoinedParty(_Joiner) + AND + DB_IsPlayer(_Joiner) + AND + CharacterGetReservedUserID(_Joiner,_User) + THEN + ProcMigrateQuestsForUser(_User,_Joiner); + + //handle the case where an MP savegame is loaded in SP + IF + SavegameLoaded(_,_,_,_) + AND + DB_IsPlayer(_Joiner) + AND + CharacterGetReservedUserID(_Joiner,_User) + THEN + ProcMigrateQuestsForUser(_User,_Joiner); + ProcShareQuestsWithParty(_Joiner); + + PROC + ProcMigrateQuestsForUser((INTEGER)_User,(CHARACTERGUID)_Joiner) + AND + DB_IsPlayer(_Other) + AND + CharacterGetReservedUserID(_Other,_User) + AND + DB_ActivatedQuests(_Quest) + AND + QuestGetBroadcastLevel(_Quest,_Level) + AND + _Level != "Character" + AND + DB_PrivateQuestFlag(_Other,_Quest,_QuestFlag) + THEN + ProcShareQuestflagWith(_Other,_Quest,_QuestFlag,_Joiner); + + IF + QuestShared(_SrcCharacter,"",1) + AND + DB_IsPlayer(_SrcCharacter) + AND + DB_ActivatedQuests(_Quest) + THEN + ProcMigrateQuest(_SrcCharacter,_Quest); + + IF + QuestShared(_SrcCharacter,_Quest,1) + AND + _Quest != "" + THEN + ProcMigrateQuestFlagsFor(_SrcCharacter,_Quest); + + PROC + ProcMigrateQuest((CHARACTERGUID)_SrcPlayer,(STRING)_Quest) + AND + QuestAccepted(_SrcPlayer,_Quest,1) + AND + QuestIsShared(_SrcPlayer,_Quest,1) + THEN + ProcMigrateQuestFlagsFor(_SrcPlayer,_Quest); + + PROC + ProcMigrateQuestFlagsFor((CHARACTERGUID)_SrcPlayer,(STRING)_Quest) + AND + DB_PrivateQuestFlag(_SrcPlayer,_Quest,_QuestFlag) + THEN + DB_SharedQuestFlag(_SrcPlayer,_Quest,_QuestFlag); + NOT DB_PrivateQuestFlag(_SrcPlayer,_Quest,_QuestFlag); + + PROC + ProcMigrateQuestFlagsFor((CHARACTERGUID)_SrcChar,(STRING)_Quest) + AND + DB_SharedQuestFlag(_SrcChar,_Quest,_QuestFlag) + THEN + ProcShareQuestFlag(_SrcChar,_Quest,_QuestFlag); + + PROC + ProcShareQuestFlag((CHARACTERGUID)_SrcPlayer,(STRING)_Quest,(STRING)_QuestFlag) + AND + DB_IsPlayer(_Player) + AND + _Player!=_SrcPlayer + AND + CharacterIsInPartyWith(_Player,_SrcPlayer,1) + AND + ObjectGetFlag(_Player,_QuestFlag,0) //checked for when story gives the flag to several players in a row. Otherwise you won't have a chance to give the update in case someone shares the quest + THEN + ProcShareQuestflagWith(_SrcPlayer,_Quest,_QuestFlag,_Player); + + PROC + ProcShareQuestflagWith((CHARACTERGUID)_SrcPlayer,(STRING)_Quest,(STRING)_QuestFlag,(CHARACTERGUID)_Player) + THEN + ProcStoreFlagState(_Player,_QuestFlag); + ProcShareQuestUpdate(_SrcPlayer,_Quest,_QuestFlag,_Player); + ObjectShareFlag(_Player,_QuestFlag); + ProcStoreSharedQuestFlag(_SrcPlayer,_Quest,_QuestFlag,_Player); + ProcVerifyFlagState(_SrcPlayer,_Player,_QuestFlag); + + PROC + ProcStoreSharedQuestFlag((CHARACTERGUID)_SrcPlayer,(STRING)_Quest,(STRING)_QuestFlag,(CHARACTERGUID)_Player) + AND + DB_SharedQuestFlag(_SrcPlayer,_Quest,_QuestFlag) + THEN + DB_SharedQuestFlag(_Player,_Quest,_QuestFlag); + + PROC + ProcStoreSharedQuestFlag((CHARACTERGUID)_SrcPlayer,(STRING)_Quest,(STRING)_QuestFlag,(CHARACTERGUID)_Player) + AND + DB_PrivateQuestFlag(_SrcPlayer,_Quest,_QuestFlag) + THEN + DB_PrivateQuestFlag(_Player,_Quest,_QuestFlag); + + PROC + ProcShareQuestUpdate((CHARACTERGUID)_SrcPlayer,(STRING)_Quest,(STRING)_QuestFlag,(CHARACTERGUID)_Player) + AND + QuestAccepted(_SrcPlayer,_Quest,1) + AND + QuestAccepted(_Player,_Quest,0) + THEN + QuestAdd(_Player,_Quest); + ProcMigrateQuestFlagsFor(_Player,_Quest); + + PROC + ProcShareQuestUpdate((CHARACTERGUID)_SrcPlayer,(STRING)_Quest,(STRING)_QuestFlag,(CHARACTERGUID)_Player) + AND + DB_QuestDef_UpdateEvent(_Quest,_QuestState,_QuestFlag) + AND + QuestHasUpdate(_SrcPlayer,_Quest,_QuestState,1) + THEN + QuestReceiveSharedUpdate(_SrcPlayer,_Player,_Quest,_QuestState); + + PROC + ProcShareQuestUpdate((CHARACTERGUID)_SrcPlayer,(STRING)_Quest,(STRING)_QuestFlag,(CHARACTERGUID)_Player) + AND + DB_QuestDef_CloseEvent(_Quest,_QuestFlag) + THEN + QuestClose(_Player,_Quest); + + PROC + ProcMigrateQuestFlag((CHARACTERGUID)_SrcPlayer,(STRING)_Quest,(STRING)_QuestFlag) + AND + QuestIsShared(_SrcPlayer,_Quest,0) + THEN + DB_PrivateQuestFlag(_SrcPlayer,_Quest,_QuestFlag); + ProcSharePrivateFlags(_SrcPlayer,_Quest,_QuestFlag); + + PROC + ProcMigrateQuestFlag((CHARACTERGUID)_SrcPlayer,(STRING)_Quest,(STRING)_QuestFlag) + AND + QuestIsShared(_SrcPlayer,_Quest,1) + THEN + DB_SharedQuestFlag(_SrcPlayer,_Quest,_QuestFlag); + ProcShareQuestFlag(_SrcPlayer,_Quest,_QuestFlag); + + PROC + ProcSharePrivateFlags((CHARACTERGUID)_SrcPlayer,(STRING)_Quest,(STRING)_QuestFlag) + AND + QuestGetBroadcastLevel(_Quest,"User") + AND + CharacterGetReservedUserID(_SrcPlayer,_User) + AND + DB_IsPlayer(_Char) + AND + _Char != _SrcPlayer + AND + CharacterGetReservedUserID(_Char,_User) + THEN + DB_PrivateQuestFlag(_SrcPlayer,_Quest,_QuestFlag); + ObjectShareFlag(_Char,_QuestFlag); + + PROC + ProcStoreFlagState((CHARACTERGUID)_Player,(STRING)_QuestFlag) + AND + ObjectGetFlag(_Player,_Questflag,_State) + THEN + DB_TargetQuestFlagState(_Player,_QuestFlag,_State); + + //if a quest flag was cleared and we didn't have it set before sharing clear it as well + //this will make flags couple to inventory events work correctly + PROC + ProcVerifyFlagState((CHARACTERGUID)_SrcPlayer,(CHARACTERGUID)_Player,(STRING)_QuestFlag) + AND + ObjectGetFlag(_SrcPlayer,_Questflag,0) + AND + DB_TargetQuestFlagState(_Player,_QuestFlag,0) + THEN + ObjectClearFlag(_Player,_QuestFlag,0); + + PROC + ProcVerifyFlagState((CHARACTERGUID)_SrcPlayer,(CHARACTERGUID)_Player,(STRING)_QuestFlag) + AND + ObjectGetFlag(_SrcPlayer,_Questflag,1) + AND + DB_HasStoryEvent((ITEMGUID)_Item,_Questflag) + AND + NOT QryItemInMagicPockets(_Player,_Item) + THEN + ObjectClearFlag(_Player,_QuestFlag,0); + + PROC + ProcVerifyFlagState((CHARACTERGUID)_SrcPlayer,(CHARACTERGUID)_Player,(STRING)_QuestFlag) + AND + ObjectGetFlag(_SrcPlayer,_Questflag,1) + AND + DB_HasTemplateItem(_Template,_Questflag) + AND + NOT QryItemTemplateInMagicPockets(_Player,_Template) + THEN + ObjectClearFlag(_Player,_QuestFlag,0); + + //TODO: this does not handle events outside of the DB_HasStoryEvent or the TaggedItemTracker + + PROC + ProcVerifyFlagState(_,_Player,_QuestFlag) + AND + DB_TargetQuestFlagState(_Player,_QuestFlag,_State) + THEN + NOT DB_TargetQuestFlagState(_Player,_QuestFlag,_State); + //END_REGION + + PROC + ProcSetFlagOnAll((STRING)_Flag) + AND + DB_IsPlayer(_Player) + THEN + ObjectSetFlag(_Player,_Flag); + + //REGION end of region + + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded((STRING)_Quest,(STRING)_Flag,(STRING)_Region) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + THEN + ObjectSetFlag(_Char,_Flag); + QuestArchive(_Char,_Quest,1); + + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded_Conditions_FalseGlobalFlag_TrueObjFlag((STRING)_Quest,(STRING)_SetFlag,_Region,(STRING)_GloFlag,(STRING)_ObjFlag) + AND + GlobalGetFlag(_GloFlag,0) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + AND + UserGetFlag(_Char,_ObjFlag,1) + AND + ObjectGetFlag(_Char,_SetFlag,0) + THEN + ObjectSetFlag(_Char,_SetFlag); + QuestArchive(_Char,_Quest,1); + + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded_Conditions_FalseGlobalFlag_FalseObjFlag((STRING)_Quest,(STRING)_SetFlag,_Region,(STRING)_GloFlag,(STRING)_ObjFlag) + AND + GlobalGetFlag(_GloFlag,0) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + AND + UserGetFlag(_Char,_ObjFlag,0) + AND + ObjectGetFlag(_Char,_SetFlag,0) + THEN + ObjectSetFlag(_Char,_SetFlag); + QuestArchive(_Char,_Quest,1); + + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded_Condition_FalseGlobalFlag_OrClose((STRING)_Quest,(STRING)_SetFlag,_Region,(STRING)_GlobalFlag) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + AND + GlobalGetFlag(_GlobalFlag,0) + THEN + ObjectSetFlag(_Char,_SetFlag); + QuestArchive(_Char,_Quest,1); + + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded_Condition_FalseGlobalFlag_OrClose((STRING)_Quest,(STRING)_SetFlag,_Region,(STRING)_GlobalFlag) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + AND + GlobalGetFlag(_GlobalFlag,1) + THEN + QuestClose(_Char,_Quest); + QuestArchive(_Char,_Quest,1); + + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded_Condition_FalseGlobalFlag((STRING)_Quest,(STRING)_SetFlag,_Region,(STRING)_GlobalFlag) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + AND + GlobalGetFlag(_GlobalFlag,0) + THEN + ObjectSetFlag(_Char,_SetFlag); + QuestArchive(_Char,_Quest,1); + + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded_Condition_TrueGlobalFlag((STRING)_Quest,(STRING)_SetFlag,_Region,(STRING)_GlobalFlag) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + AND + GlobalGetFlag(_GlobalFlag,1) + THEN + ObjectSetFlag(_Char,_SetFlag); + QuestArchive(_Char,_Quest,1); + + + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded_Conditions_FalseObjFlag((STRING)_Quest,(STRING)_SetFlag,_Region,(STRING)_ObjFlag) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + AND + UserGetFlag(_Char,_ObjFlag,0) + AND + ObjectGetFlag(_Char,_SetFlag,0) + THEN + ObjectSetFlag(_Char,_SetFlag); + QuestArchive(_Char,_Quest,1); + + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded_Conditions_TrueObjFlag((STRING)_Quest,(STRING)_SetFlag,_Region,(STRING)_ObjFlag) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + AND + UserGetFlag(_Char,_ObjFlag,1) + AND + ObjectGetFlag(_Char,_SetFlag,0) + THEN + ObjectSetFlag(_Char,_SetFlag); + QuestArchive(_Char,_Quest,1); + + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded_Conditions_FalseObjFlag_TrueObjFlag((STRING)_Quest,(STRING)_SetFlag,_Region,(STRING)_FalseObjFlag,(STRING)_TrueObjFlag) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + AND + UserGetFlag(_Char,_FalseObjFlag,0) + AND + UserGetFlag(_Char,_TrueObjFlag,1) + AND + ObjectGetFlag(_Char,_SetFlag,0) + THEN + ObjectSetFlag(_Char,_SetFlag); + QuestArchive(_Char,_Quest,1); + + /* + PROC + ProcRegionEnded(_Region) + AND + DB_QuestDef_CloseAtRegionEnded_Conditions_FalseObjFlag_FalseObjFlag(_Quest,_SetFlag,_Region,_FalseObjFlag1,_FalseObjFlag2) + AND + DB_IsPlayer(_Char) + AND + QuestAccepted(_Char,_Quest,1) + AND + UserGetFlag(_Char,_FalseObjFlag1,0) + AND + UserGetFlag(_Char,_FalseObjFlag2,0) + AND + ObjectGetFlag(_Char,_SetFlag,0) + THEN + ObjectSetFlag(_Char,_SetFlag); + QuestArchive(_Char,_Quest,1); + */ + + //END_REGION + + //REGION set category on region started + + PROC + ProcRegionStarted((STRING)_Region) + AND + DB_RegionQuestCategory(_Region,(STRING)_Category) + AND + DB_RegionQuestCategory_Swapped((STRING)_Quest) + THEN + ProcQuestSetCategory(_Quest,_Category); + + + PROC + ProcQuestSetCategory((STRING)_Quest,(STRING)_Category) + AND + DB_IsPlayer(_Char) + AND + QuestIsClosed(_Char,_Quest,0) + THEN + QuestSetCategory(_Quest,_Category); + ProcQuestCategorySet(_Quest,_Category,_Char); + + + PROC + ProcQuestCategorySet((STRING)_Quest,(STRING)_Category,(CHARACTERGUID)_Char) + THEN + DB_NOOP(1); + + //END_REGION + + //REGION QuestReward + + IF + ObjectFlagSet(_Flag,(CHARACTERGUID)_Player,_Inst) + AND + DB_IsPlayer(_Player) + AND + DB_QuestDef_QuestReward((STRING)_Quest,(STRING)_RewardState,_Flag) + AND + QuestAccepted(_Player,_Quest,1) + AND + _Inst != 0 + THEN + DB_GiveQuestRewardAfterDialog(_Player,_Quest,_RewardState,_Inst); + + IF + DialogEnded(_,_Inst) + AND + DB_GiveQuestRewardAfterDialog(_Player,_Quest,_RewardState,_Inst) + THEN + ProcGiveQuestReward(_Player,_Quest,_RewardState); + NOT DB_GiveQuestRewardAfterDialog(_Player,_Quest,_RewardState,_Inst); + + PROC + ProcGiveQuestReward((CHARACTERGUID)_Player,(STRING)_Quest,(STRING)_RewardState) + AND + NOT DB_QuestRewardGiven(_Player,_Quest,_RewardState) + THEN + CharacterGiveQuestReward(_Player,_Quest,_RewardState); + ProcMarkPartyAsGivenReward(_Player,_Quest,_RewardState); + + PROC + ProcMarkPartyAsGivenReward((CHARACTERGUID)_Player,(STRING)_Quest,(STRING)_RewardState) + AND + DB_IsPlayer(_OtherPlayer) + AND + CharacterIsInPartyWith(_Player,_OtherPlayer,1) + THEN + DB_QuestRewardGiven(_OtherPlayer,_Quest,_RewardState); + + //END_REGION + + } + EXIT + { + + } +} +Goal(26).Title("_Global_Procedure"); +Goal(26) +{ + INIT + { + + } + KB + { + //REGION Character DB_KillCounter + PROC + ProcCheckCounter((INTEGER)_Count,(STRING)_CounterDB) + AND + DB_KillCounterCounts(_CounterDB,_OldCount) + THEN + NOT DB_KillCounterCounts(_CounterDB,_OldCount); + DB_KillCounterCounts(_CounterDB,_Count); + + PROC + ProcClearCounterDB((STRING)_CounterDB) + AND + DB_KillCounter_Internal(_Character,_CounterDB) + THEN + NOT DB_KillCounter_Internal(_Character,_CounterDB); + + PROC + ProcClearCounterDB((STRING)_CounterDB) + AND + DB_KillCounterDied(_Char,_CounterDB) + THEN + NOT DB_KillCounterDied(_Char,_CounterDB); + + PROC + ProcCheckCounter(_Count,_CounterDB) + AND + DB_KillCounter((STRING)_CounterDB,(INTEGER)_TargetCount) + AND + _Count == _TargetCount + THEN + //NOT DB_KillCounter(_CounterDB,_TargetCount); + ProcClearCounterDB(_CounterDB); + ProcKillCounterReached(_CounterDB); + NOT DB_KillCounterCounterDefined(_CounterDB); + //NOT DB_KillCounterCounts(_CounterDB,_TargetCount); + + PROC + ProcCheckCounter(_Count, _CounterDB) + AND + DB_KillCounter((STRING)_CounterDB,(INTEGER)_TargetCount) + AND + IntegerSubtract(_TargetCount, 1, _New) + AND + _Count == _New + AND + DB_KillCounter_Internal(_LastCharacter, _CounterDB) + THEN + DB_LastManStanding((CHARACTERGUID)_LastCharacter, (STRING)_CounterDB); + + IF + CharacterDying(_Character) + AND + DB_KillCounter_Internal(_Character,_CounterDB) + AND + DB_CombatCharacters(_Character,_ID) + THEN + ProcSetCounterCombatID(_CounterDB,_ID); + + PROC + ProcClearCounterCombatID((STRING)_Counter) + AND + DB_CounterCombatID(_Counter,_OldID) + THEN + NOT DB_CounterCombatID(_Counter,_OldID); + + PROC + ProcSetCounterCombatID((STRING)_Counter,(INTEGER)_ID) + THEN + ProcClearCounterCombatID(_Counter); + DB_CounterCombatID(_Counter,_ID); + + IF + ObjectEnteredCombat((CHARACTERGUID)_Char, _ID) + AND + DB_KillCounter_Internal(_Char, _Counter) + THEN + ProcClearCounterCombatID(_Counter); + + IF + ObjectEnteredCombat((CHARACTERGUID)_LastMan, _ID) + AND + DB_KillCounter_Internal(_LastMan, _Counter) + AND + DB_KillCounter(_Counter,1) + THEN + DB_LastManStanding((CHARACTERGUID)_LastMan, (STRING)_Counter); + + IF + CharacterKilledBy(_Defender, _AttackerOwner, _Attacker) + AND + DB_LastManStanding(_Defender, _CounterDB) + THEN + NOT DB_LastManStanding(_Defender, _CounterDB); + DB_LastManInCombatKilledBy(_AttackerOwner, (STRING)_CounterDB); + + IF + CharacterDied(_Character) + AND + DB_KillCounter_Internal(_Character,_CounterDB) + AND + DB_KillCounterCounts(_CounterDB,_Count) + AND + IntegerSum(_Count,1,_NewCount) + THEN + NOT DB_KillCounter_Internal(_Character,_CounterDB); + DB_KillCounterDied(_Character,_CounterDB); + ProcCheckCounter(_NewCount,_CounterDB); + + IF + CharacterResurrected(_Character) + AND + DB_KillCounterDied(_Character,_CounterDB) + AND + DB_KillCounterCounts(_CounterDB,_Count) + AND + IntegerSubtract(_Count,1,_NewCount) + THEN + DB_KillCounter_Internal(_Character,_CounterDB); + NOT DB_KillCounterDied(_Character,_CounterDB); + ProcCheckCounter(_NewCount,_CounterDB); + + IF + DB_KillCounter_Internal(_Character,_CounterDB) + AND + NOT DB_KillCounterCounterDefined(_CounterDB) + THEN + DB_KillCounterCounts(_CounterDB,0); + DB_KillCounterCounterDefined(_CounterDB); + + IF + CombatEnded(_CombatID) + AND + DB_CounterCombatID(_CounterDB,_CombatID) + AND + DB_KillCounterCounts(_CounterDB,_Count) + THEN + ProcCheckCounterCombatOver(_CounterDB,_CombatID); + ProcCheckCounter(_Count,_CounterDB); + + IF + DB_CombatCharacters(_Char, _CombatID) + AND + DB_KillCounter_Internal(_Char,_CounterDB) + THEN + ProcClearCombatOverDB(_CounterDB); + + PROC + ProcClearCombatOverDB((STRING)_CounterDB) + AND + DB_KillCounterCombatOver(_OldCombatID, _CounterDB) + THEN + NOT DB_KillCounterCombatOver(_OldCombatID, _CounterDB); + + //killed people outside of combat + PROC + ProcKillCounterReached((STRING)_CounterDB) + AND + NOT DB_CounterCombatID(_CounterDB,_) + THEN + ReactOnKillCounter(_CounterDB); + + PROC + ProcKillCounterReached((STRING)_CounterDB) + AND + DB_KillCounterCombatOver(_CombatID, _CounterDB) + THEN + ReactOnKillCounter(_CounterDB); + NOT DB_KillCounterCombatOver(_CombatID, _CounterDB); + + //Wasn't involved in combat + PROC + ProcCheckCounterCombatOver((STRING)_CounterDB,(INTEGER)_CombatID) + THEN + NOT DB_KillCounterCombatOver(_CombatID, _CounterDB); + + PROC + ProcCheckCounterCombatOver((STRING)_CounterDB,(INTEGER)_CombatID) + AND + CombatGetNumberOfInvolvedPartyMembers(_CombatID, 0) + THEN + DB_KillCounterCombatOver(_CombatID, _CounterDB); + + + PROC + ReactOnKillCounter((STRING)_CounterDB) + AND + DB_KillCounterCounts(_CounterDB,_Count) + AND + DB_KillCounter(_CounterDB,_TargetCount) + THEN + NOT DB_KillCounterCounts(_CounterDB,_Count); + NOT DB_KillCounter(_CounterDB,_TargetCount); + + //END_REGION + + //REGION Item Destroy Counter + PROC + CheckItemCounter((INTEGER)_Count,(STRING)_CounterDB) + AND + DB_ItemDestroyCounterCounts(_CounterDB,_OldCount) + THEN + NOT DB_ItemDestroyCounterCounts(_CounterDB,_OldCount); + DB_ItemDestroyCounterCounts(_CounterDB,_Count); + + PROC + ClearDB_ItemDestroyCounter_Internal((STRING)_CounterDB) + AND + DB_ItemDestroyCounter_Internal(_Item,_CounterDB) + THEN + NOT DB_ItemDestroyCounter_Internal(_Item,_CounterDB); + + PROC + CheckItemCounter(_Count,_CounterDB) + AND + DB_ItemDestroyCounter((STRING)_CounterDB,(INTEGER)_TargetCount) + AND + _Count == _TargetCount + THEN + NOT DB_ItemDestroyCounter(_CounterDB,_TargetCount); + ClearDB_ItemDestroyCounter_Internal(_CounterDB); + NOT DB_ItemDestroyCounterCounterDefined(_CounterDB); + NOT DB_ItemDestroyCounter(_CounterDB,_TargetCount); + + IF + ItemDestroyed(_Item) + AND + DB_ItemDestroyCounter_Internal(_Item,_CounterDB) + AND + DB_ItemDestroyCounterCounts(_CounterDB,_Count) + AND + IntegerSum(_Count,1,_NewCount) + THEN + NOT DB_ItemDestroyCounter_Internal(_Item,_CounterDB); + CheckItemCounter(_NewCount,_CounterDB); + + IF + DB_ItemDestroyCounter_Internal(_Item,_CounterDB) + AND + NOT DB_ItemDestroyCounterCounterDefined(_CounterDB) + THEN + DB_ItemDestroyCounterCounts(_CounterDB,0); + DB_ItemDestroyCounterCounterDefined(_CounterDB); + //END_REGION + + //REGION Comment for hidden effect + PROC + PROC_CommentHiddenEffect((CHARACTERGUID)_Player) + THEN + Proc_StartDialog(1,"GLO_AD_ActivatedSwitch", _Player); + //END_REGION + + //REGION SneakTrigger + IF + DB_SneakTriggerSpotter((TRIGGERGUID)_Trigger, (CHARACTERGUID)_Char) + THEN + SetVarObject(_Char, "SpottedTrigger", _Trigger); + ProcTriggerRegisterForPlayers(_Trigger); + + PROC + ProcHandleSneakSpotted((CHARACTERGUID)_Char) + THEN + DB_NOOP(1); + + IF + StoryEvent((CHARACTERGUID)_Char, "GLO_SpotterSneaker") + AND + DB_SneakTriggerSpotter(_Trigger, _Char) + AND + GetVarObject(_Char, "SpottedDude", _Player) + THEN + ProcCharInTriggerSpotted((CHARACTERGUID)_Player,_Trigger); + ProcCharInTriggerSpottedByChar((CHARACTERGUID)_Player,_Trigger,_Char); + ProcHandleSneakSpotted(_Char); + ProcCleanUpSneakTrigger(_Trigger); + + PROC + ProcCharInTriggerSpottedByChar((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger,(CHARACTERGUID)_Spotter) + THEN + DB_NOOP(1); + + PROC + ProcCleanUpSneakTrigger((TRIGGERGUID)_Trigger) + AND + DB_SneakTriggerSpotter((TRIGGERGUID)_Trigger, (CHARACTERGUID)_Char) + THEN + SetVarInteger(_Char, "SpottedCounter", 1); + NOT DB_SneakTriggerSpotter(_Trigger, _Char); + + PROC + ProcTriggerUnregisterForPlayers((TRIGGERGUID)_Trigger) + AND + DB_SneakTriggerSpotter(_Trigger, _Char) + THEN + NOT DB_SneakTriggerSpotter(_Trigger, _Char); + //END_REGION + + //REGION DB_AmbushTrigger + IF + DB_AmbushTrigger((TRIGGERGUID)_Trigger, (ITEMGUID)_Helper) + THEN + ProcTriggerRegisterForPlayers(_Trigger); + SetOnStage(_Helper, 1); + + IF + CharacterEnteredTrigger(_Player,_Trigger) + AND + DB_AmbushTrigger(_Trigger, _) + AND + HasActiveStatus(_Player, "INVISIBLE", 0) + AND + HasActiveStatus(_Player, "SNEAKING", 0) + THEN + ProcLaunchAmbush(_Trigger, _Player); + + IF + CharacterStatusRemoved(_Player, "INVISIBLE",_) + AND + DB_InRegion(_Player, _Trigger) + AND + DB_AmbushTrigger(_Trigger, _) + THEN + ProcLaunchAmbush(_Trigger, _Player); + + IF + CharacterStatusRemoved(_Player, "SNEAKING",_) + AND + DB_InRegion(_Player, _Trigger) + AND + DB_AmbushTrigger(_Trigger, _Helper) + THEN + ProcLaunchAmbush(_Trigger, _Player); + + PROC + ProcLaunchAmbush((TRIGGERGUID)_Trigger, (CHARACTERGUID)_Player) + AND + DB_AmbushTrigger(_Trigger, _Helper) + THEN + ProcTriggerUnregisterForPlayers(_Trigger); + NOT DB_AmbushTrigger(_Trigger, _Helper); + SetOnStage(_Helper, 0); + //END_REGION + + //REGION Queuing Dialog + //1 Speaker + PROC + PROC_MandatoryOneSpeakerDialog((STRING)_Dialog,(CHARACTERGUID)_Player) + AND + NOT QRY_SpeakerIsAvailable(_Player) + THEN + DB_QueuedOneSpeakerDialog(_Player,_Dialog); + + PROC + PROC_MandatoryOneSpeakerDialog((STRING)_Dialog,(CHARACTERGUID)_Player) + AND + QRY_SpeakerIsAvailable(_Player) + THEN + MakePlayerActive(_Player); + Proc_StartDialog(0,_Dialog,_Player); + + IF + DialogEnded(_,_) + AND + DB_QueuedOneSpeakerDialog(_Player,_Dialog) + AND + DB_IsPlayer(_Player) + AND + QRY_SpeakerIsAvailable(_Player) + THEN + NOT DB_QueuedOneSpeakerDialog(_Player,_Dialog); + MakePlayerActive(_Player); + Proc_StartDialog(0,_Dialog,_Player); + + IF + ObjectLeftCombat((CHARACTERGUID)_Player,_) + AND + DB_QueuedOneSpeakerDialog(_Player,_Dialog) + AND + DB_IsPlayer(_Player) + AND + QRY_SpeakerIsAvailable(_Player) + THEN + NOT DB_QueuedOneSpeakerDialog(_Player,_Dialog); + MakePlayerActive(_Player); + Proc_StartDialog(0,_Dialog,_Player); + + //END_REGION + + //REGION Quest Reward + PROC + ProcRewardQuestMedium((TRIGGERGUID)_Trigger) + THEN + ItemCreateAtTrigger(_Trigger, "Quest_Reward_Small_94e12298-5e59-405a-9e93-95833e648ce2"); + PlayEffect(_Trigger,"RS3_FX_GP_ScriptedEvent_Teleport_GenericSmoke_01"); + + PROC + ProcRewardQuestBig((TRIGGERGUID)_Trigger) + THEN + ItemCreateAtTrigger(_Trigger, "Quest_Reward_Big_b67596ec-18ca-4790-9273-8af23d8a7a43"); + PlayEffect(_Trigger,"RS3_FX_GP_ScriptedEvent_Teleport_GenericSmoke_01"); + //END_REGION + + + //REGION secret regions + IF + DB_SecretRegions_OnOpenedDoor(_Trig,_) + THEN + LockSecretRegion(_Trig); + + IF + DB_SecretRegions_OnEnteredTrig(_Trig,_OtherTrig) + THEN + ProcTriggerRegisterForPlayers(_OtherTrig); + LockSecretRegion(_Trig); + + IF + CharacterUsedItem(_,_Door) + AND + DB_SecretRegions_OnOpenedDoor(_Trig,_Door) + AND + DoorIsOpening(_Door,1) + THEN + UnlockSecretRegion(_Trig); + NOT DB_SecretRegions_OnOpenedDoor(_Trig,_Door); + + IF + ItemOpened(_Door) + AND + DB_SecretRegions_OnOpenedDoor(_Trig,_Door) + THEN + UnlockSecretRegion(_Trig); + NOT DB_SecretRegions_OnOpenedDoor(_Trig,_Door); + + IF + ItemDestroyed(_Door) + AND + DB_SecretRegions_OnOpenedDoor(_Trig,_Door) + THEN + UnlockSecretRegion(_Trig); + NOT DB_SecretRegions_OnOpenedDoor(_Trig,_Door); + + + IF + CharacterEnteredTrigger(_Char,_EnteredTrig) + AND + DB_SecretRegions_OnEnteredTrig(_Trig,(TRIGGERGUID)_EnteredTrig) + AND + DB_IsPlayer(_Char) + THEN + UnlockSecretRegion(_Trig); + NOT DB_SecretRegions_OnEnteredTrig(_Trig,_EnteredTrig); + + IF + StoryEvent(_,_Event) + AND + DB_SecretRegions_OnStoryEvent(_Trig,_Event) + THEN + UnlockSecretRegion(_Trig); + NOT DB_SecretRegions_OnStoryEvent(_Trig,_Event); + + + //END_REGION + + } + EXIT + { + + } +} +Goal(27).Title("_Global_RunUpAndChat"); +Goal(27) +{ + INIT + { + + } + KB + { + //REGION MoveToAndTalk + + //Start Walking + PROC + ProcCharacterMoveToAndTalk((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent,(INTEGER)_Running,(REAL)_TimeOut) + THEN + ProcCharacterMoveToAndTalk((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent,(INTEGER)_Running,(REAL)_TimeOut,0,0); + + PROC + ProcCharacterMoveToAndTalk((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent,(INTEGER)_Running,(REAL)_TimeOut,(INTEGER)_CheckForFallBackPlayers,(INTEGER)_ForcePartyCheck) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving(_Character,_Target,_Dialog,_MoveEvent) + THEN + NOT DB_CharacterMoveToAndTalk_CharacerIsMoving(_Character,_Target,_Dialog,_MoveEvent); + + PROC + ProcCharacterMoveToAndTalk((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent,(INTEGER)_Running,(REAL)_TimeOut,(INTEGER)_CheckForFallBackPlayers,(INTEGER)_ForcePartyCheck) + AND + DB_CharacterMoveToAndTalk_CheckForFallBackCharacters(_Character,_Target,_Dialog,_CheckForFallBackPlayers,_ForcePartCheck) + THEN + NOT DB_CharacterMoveToAndTalk_CheckForFallBackCharacters(_Character,_Target,_Dialog,_CheckForFallBackPlayers,_ForcePartCheck); + + PROC + ProcCharacterMoveToAndTalk((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent,(INTEGER)_Running,(REAL)_TimeOut,(INTEGER)_CheckForFallBackPlayers,(INTEGER)_ForcePartyCheck) + THEN + CharacterMoveToAndTalk(_Character,_Target,_Dialog,_IsAutomated,_MoveEvent,_Running,_TimeOut); + DB_CharacterMoveToAndTalk_CharacerIsMoving(_Character,_Target,_Dialog,_MoveEvent); + DB_CharacterMoveToAndTalk_CheckForFallBackCharacters(_Character,_Target,_Dialog,_CheckForFallBackPlayers,_ForcePartyCheck); + + //Movement Failed + IF + CharacterMoveToAndTalkFailed((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_MoveEvent) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving(_Character,_Target,_Dialog,_MoveEvent) + THEN + NOT DB_CharacterMoveToAndTalk_CharacerIsMoving(_Character,_Target,_Dialog,_MoveEvent); + + IF + AttackedByObject(_Character,_Source,_Summon,_DamageType,_) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving((CHARACTERGUID)_Character,_Target,_Dialog,_MoveEvent) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Character,_Target,_MoveEvent); + + IF + RegionEnded(_) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving((CHARACTERGUID)_Character,_Target,_Dialog,_MoveEvent) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Character,_Target,_MoveEvent); + + IF + CharacterLeftRegion(_Characrer,_Region) + AND + DB_CurrentLevel(_Region) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving((CHARACTERGUID)_Character,_Target,_Dialog,_MoveEvent) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Character,_Target,_MoveEvent); + + IF + CharacterLeftRegion(_Target,_Region) + AND + DB_CurrentLevel(_Region) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving((CHARACTERGUID)_Character,_Target,_Dialog,_MoveEvent) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Character,_Target,_MoveEvent); + + IF + CharacterDied(_Target) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving((CHARACTERGUID)_Character,_Target,_Dialog,_MoveEvent) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Character,_Target,_MoveEvent); + + IF + CharacterDied(_Character) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving((CHARACTERGUID)_Character,_Target,_Dialog,_MoveEvent) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Character,_Target,_MoveEvent); + + IF + DialogStarted(_,_ID) + AND + DB_DialogNPCS(_ID,_Character,_) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving((CHARACTERGUID)_Character,_Target,_Dialog,_MoveEvent) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Character,_Target,_MoveEvent); + + IF + CombatStarted(_ID) + AND + DB_CombatCharacters(_Character, _ID) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving((CHARACTERGUID)_Character,_Target,_Dialog,_MoveEvent) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Character,_Target,_MoveEvent); + + + // Movement Finished + IF + CharacterMoveToAndTalkRequestDialog((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent) + AND + DB_CharacterMoveToAndTalk_CharacerIsMoving(_Character,_Target,_Dialog,_MoveEvent) + THEN + NOT DB_CharacterMoveToAndTalk_CharacerIsMoving(_Character,_Target,_Dialog,_MoveEvent); + + IF + CharacterMoveToAndTalkRequestDialog((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent) + THEN + SetStoryEvent(_Character,_MoveEvent); + + // Dialog Failed + IF + CharacterMoveToAndTalkRequestDialog((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent) + AND + NOT QRY_SpeakerIsAvailable(_Target) + AND + DB_CharacterMoveToAndTalk_CheckForFallBackCharacters(_Character,_Target,_Dialog,0,_ForcePartyCheck) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Character,_Target,_MoveEvent); + + IF + CharacterMoveToAndTalkRequestDialog((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent) + AND + NOT QRY_SpeakerIsAvailable(_Target) + AND + DB_CharacterMoveToAndTalk_CheckForFallBackCharacters(_Character,(CHARACTERGUID)_Target,_Dialog,1,0) + AND + DB_IsPlayer(_Target) + THEN + ProcGetClosestAvailableCharacterTo(_Target,1); + PROC_CharacterMoveToAndTalkRequestDialog_Closest(_Character,_Target,_Dialog,_IsAutomated,_MoveEvent); + + IF + CharacterMoveToAndTalkRequestDialog((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent) + AND + NOT QRY_SpeakerIsAvailable(_Target) + AND + DB_CharacterMoveToAndTalk_CheckForFallBackCharacters(_Character,(CHARACTERGUID)_Target,_Dialog,1,1) + AND + DB_IsPlayer(_Target) + THEN + ProcGetClosestAvailableCharacterTo(_Target,1,1,_Target); + PROC_CharacterMoveToAndTalkRequestDialog_Closest(_Character,_Target,_Dialog,_IsAutomated,_MoveEvent); + + // Dialog Success + + IF + CharacterMoveToAndTalkRequestDialog((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent) + AND + _Dialog!="" + AND + QRY_SpeakerIsAvailable(_Target) + THEN + Proc_StartDialog(_IsAutomated,_Dialog,_Character,_Target); + + PROC + PROC_CharacterMoveToAndTalkRequestDialog_Closest((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent) + AND + NOT QRY_SpeakerIsAvailable(_Target) + AND + DB_ClosestAvailablePlayer(_Player,(CHARACTERGUID)_Target) + THEN + Proc_StartDialog(_IsAutomated,_Dialog,_Character,_Player); + + PROC + PROC_CharacterMoveToAndTalkRequestDialog_Closest((CHARACTERGUID)_Character,(GUIDSTRING)_Target,(STRING)_Dialog,(INTEGER)_IsAutomated,(STRING)_MoveEvent) + AND + NOT QRY_SpeakerIsAvailable(_Target) + AND + NOT DB_ClosestAvailablePlayer(_,(CHARACTERGUID)_Target) + THEN + CharacterMoveToAndTalkRequestDialogFailed(_Character,_Target,_MoveEvent); + + //END_REGION + + + } + EXIT + { + + } +} +Goal(28).Title("_Global_SavegamePatching"); +Goal(28) +{ + INIT + { + + } + KB + { + //REGION Remove destroyed items that came back + IF + SavegameLoaded(_Major,_Minor,_Rev,_Build) + AND + QRY_VersionIsOlderThan(_Major,_Minor,_Rev,_Build,3,1,5,1) + AND + DB_DestroyedItems((GUIDSTRING)_Item) + AND + ObjectExists((ITEMGUID)_Item,1) + AND + ItemIsDestroyed(_Item,0) + THEN + ItemRemove(_Item); + //END_REGION + + } + EXIT + { + + } +} +Goal(29).Title("_GLOBAL_Subregions"); +Goal(29) +{ + INIT + { + + } + KB + { + IF + DB_Subregion((TRIGGERGUID)_Trigger,(STRING)_,(INTEGER)_) + THEN + ProcTriggerRegisterForPlayers(_Trigger); + + IF + CharacterEnteredTrigger(_Character,_Trigger) + AND + DB_Subregion(_Trigger,_Message,_ShowMarker) + THEN + CharacterEnteredSubRegion(_Character,_Message); + ProcCheckSetRegionMarker(_Message,_ShowMarker); + + PROC + ProcCheckSetRegionMarker((STRING)_Message,1) + AND + DB_IsPlayer(_Player) + THEN + ProcShowMarker(_Player,_Message); + + + + + + } + EXIT + { + + } +} +Goal(30).Title("_GLOBAL_TeleporterPyramids"); +Goal(30) +{ + INIT + { + // PUBLIC PROCs: + // Proc_PyramidBlockerTriggerAdd - add trigger that blocks pyramid usage + // Proc_PyramidBlockerTriggerRemove - remove trigger from blocking list + // Proc_PyramidGlobalBlockerOn - global pyramids blocker turn on + // Proc_PyramidGlobalBlockerOff - global pyramids blocker turn off + // Proc_PyramidCustomBlockAdd - add custom blocker of a pyramid (used for Tenebrium chests) + // Proc_PyramidCustomBlockRemove - remove custom blocker of a pyramid (used for Tenebrium chests) + + + // Inner DBs: + // DB_TeleporterPyramidUnlocked((ITENGUID)_Pyramid) - the ones found by players + // DB_PyramidBlockerTrigger((TRIGGERGUID)_Trigger) - trigger blockers of pyramid usage + // DB_PyramidUsageBlocked(1) - global pyramid blocker + // DB_PyramidInBlockerTrigger((ITEMGUID)_Pyramid,(TRIGGERGUID)_Trigger) - used to store which pyramids are in blocking triggers + // DB_PyramidCustomBlock((ITEMGUID)_Pyramid,(STRING)_Reason) - used to store which pyramids are customly blocked + + } + KB + { + //REGION Debug + //END_REGION + + IF + DB_TeleporterPyramid(_Pyramid) + THEN + ItemSetForceSynch(_Pyramid,1); + + //REGION Unlock pyramids that were found by player + IF + ItemAddedToCharacter(_Pyramid,_Player) + AND + DB_TeleporterPyramid(_Pyramid) + AND + NOT DB_TeleporterPyramidUnlocked(_Pyramid) + AND + _Player.DB_IsPlayer() + THEN + DB_TeleporterPyramidUnlocked(_Pyramid); + + IF + CharacterUsedItem(_Player,_Pyramid) + AND + DB_TeleporterPyramid(_Pyramid) + AND + NOT DB_TeleporterPyramidUnlocked(_Pyramid) + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTut(_Player,"TUT_PyramidsPickup"); + //END_REGION + + + //REGION Pyramid blockers + PROC + Proc_PyramidGlobalBlockerOn() + THEN + DB_PyramidUsageBlocked(1); + + PROC + Proc_PyramidGlobalBlockerOn() + AND + DB_TeleporterPyramid(_Pyramid) + THEN + DisablePyramid(_Pyramid); + + PROC + Proc_PyramidGlobalBlockerOff() + THEN + NOT DB_PyramidUsageBlocked(1); + + PROC + Proc_PyramidGlobalBlockerOff() + AND + DB_TeleporterPyramid(_Pyramid) + THEN + Proc_PyramidCheckEnabled(_Pyramid); + + + PROC + Proc_PyramidBlockerTriggerAdd((TRIGGERGUID)_Trigger) + THEN + DB_PyramidBlockerTrigger(_Trigger); + TriggerRegisterForItems(_Trigger); + ProcTriggerRegisterForPlayers(_Trigger); + + PROC + Proc_PyramidBlockerTriggerRemove((TRIGGERGUID)_Trigger) + THEN + NOT DB_PyramidBlockerTrigger(_Trigger); + TriggerUnregisterForItems(_Trigger); + ProcTriggerUnregisterForPlayers(_Trigger); + + PROC + Proc_PyramidCustomBlockAdd((ITEMGUID)_Pyramid,(STRING)_Reason) + THEN + DisablePyramid(_Pyramid); + DB_PyramidCustomBlock(_Pyramid,_Reason); + + PROC + Proc_PyramidCustomBlockRemove((ITEMGUID)_Pyramid,(STRING)_Reason) + THEN + NOT DB_PyramidCustomBlock(_Pyramid,_Reason); + Proc_PyramidCheckEnabled(_Pyramid); + + + // Pyramid entered/left blocking trigger inside of character's inventory + IF + CharacterEnteredTrigger(_Char,_Trigger) + AND + DB_PyramidBlockerTrigger(_Trigger) + AND + DB_TeleporterPyramid(_Pyramid) + AND + ItemIsInCharacterInventory(_Pyramid,_Char,1) + THEN + Proc_PyramidEnterBlockerTrigger(_Pyramid,_Trigger); + + IF + CharacterLeftTrigger(_Char,_Trigger) + AND + DB_PyramidBlockerTrigger(_Trigger) + AND + DB_TeleporterPyramid(_Pyramid) + AND + ItemIsInCharacterInventory(_Pyramid,_Char,1) + AND + DB_PyramidInBlockerTrigger(_Pyramid,_Trigger) + THEN + Proc_PyramidLeaveBlockerTrigger(_Pyramid,_Trigger); + + + // Pyramid entered/left blocking trigger + IF + ItemEnteredTrigger(_Pyramid,_Trigger,_) + AND + DB_TeleporterPyramid(_Pyramid) + AND + DB_PyramidBlockerTrigger(_Trigger) + THEN + Proc_PyramidEnterBlockerTrigger(_Pyramid,_Trigger); + + IF + ItemLeftTrigger(_Pyramid,_Trigger,_) + AND + DB_PyramidInBlockerTrigger(_Pyramid,_Trigger) + THEN + Proc_PyramidLeaveBlockerTrigger(_Pyramid,_Trigger); + + + // Pyramid entered/left blocking trigger inside of another container + IF + ItemEnteredTrigger(_Container,_Trigger,_) + AND + DB_PyramidBlockerTrigger(_Trigger) + AND + DB_TeleporterPyramid(_Pyramid) + AND + GetInventoryOwner(_Pyramid,_Container) + THEN + Proc_PyramidEnterBlockerTrigger(_Pyramid,_Trigger); + + IF + ItemLeftTrigger(_Container,_Trigger,_) + AND + DB_PyramidInBlockerTrigger(_Pyramid,_Trigger) + AND + GetInventoryOwner(_Pyramid,_Container) + THEN + Proc_PyramidLeaveBlockerTrigger(_Pyramid,_Trigger); + + + // Added to container - remove old triggers that this container is not inside + IF + ItemAddedToContainer(_Pyramid,_) + AND + DB_TeleporterPyramid(_Pyramid) + AND + GetInventoryOwner(_Pyramid,_TopCont) + AND + DB_PyramidInBlockerTrigger(_Pyramid,_Trigger) + AND + ObjectIsInTrigger(_TopCont,_Trigger,0) + THEN + Proc_PyramidLeaveBlockerTrigger(_Pyramid,_Trigger); + + IF + ItemAddedToContainer(_Pyramid,_) + AND + DB_TeleporterPyramid(_Pyramid) + AND + GetInventoryOwner(_Pyramid,_TopCont) + AND + DB_PyramidBlockerTrigger(_Trigger) + AND + ObjectIsInTrigger(_TopCont,_Trigger,1) + THEN + Proc_PyramidEnterBlockerTrigger(_Pyramid,_Trigger); + + IF + ItemRemovedFromContainer(_Pyramid,_Container) + AND + DB_TeleporterPyramid(_Pyramid) + AND + DB_PyramidInBlockerTrigger(_Pyramid,_Trigger) + AND + ObjectIsInTrigger(_Container,_Trigger,1) + THEN + Proc_PyramidLeaveBlockerTrigger(_Pyramid,_Trigger); + + IF + ItemRemovedFromContainer(_Pyramid,_Container) + AND + DB_TeleporterPyramid(_Pyramid) + AND + DB_PyramidInBlockerTrigger(_Pyramid,_Trigger) + AND + GetInventoryOwner(_Container,_TopCont) + AND + ObjectIsInTrigger(_TopCont,_Trigger,1) + THEN + Proc_PyramidLeaveBlockerTrigger(_Pyramid,_Trigger); + + IF + ItemAddedToCharacter(_Pyramid,_Character) + AND + DB_TeleporterPyramid(_Pyramid) + AND + DB_PyramidBlockerTrigger(_Trigger) + AND + ObjectIsInTrigger(_Character,_Trigger,1) + THEN + Proc_PyramidEnterBlockerTrigger(_Pyramid,_Trigger); + + IF + ItemRemovedFromCharacter(_Pyramid,_Character) + AND + DB_TeleporterPyramid(_Pyramid) + AND + DB_PyramidBlockerTrigger(_Trigger) + AND + ObjectIsInTrigger(_Character,_Trigger,1) + THEN + Proc_PyramidLeaveBlockerTrigger(_Pyramid,_Trigger); + + + PROC + Proc_PyramidEnterBlockerTrigger((ITEMGUID)_Pyramid,(TRIGGERGUID)_Trigger) + THEN + DisablePyramid(_Pyramid); + DB_PyramidInBlockerTrigger(_Pyramid,_Trigger); + + PROC + Proc_PyramidLeaveBlockerTrigger((ITEMGUID)_Pyramid,(TRIGGERGUID)_Trigger) + THEN + NOT DB_PyramidInBlockerTrigger(_Pyramid,_Trigger); + Proc_PyramidCheckEnabled(_Pyramid); + + + PROC + Proc_PyramidCheckEnabled((ITEMGUID)_Pyramid) + AND + NOT DB_PyramidUsageBlocked(1) + AND + DB_TeleporterPyramid(_Pyramid) + AND + NOT DB_PyramidInBlockerTrigger(_Pyramid,_) + AND + NOT DB_PyramidCustomBlock(_Pyramid,_) + THEN + EnablePyramid(_Pyramid); + //END_REGION + + + //REGION Level transitions + IF + RegionEnded(_Region) + AND + DB_TeleporterPyramidUnlocked(_Pyramid) + AND + GetRegion(_Pyramid,_Region) + AND + GetInventoryOwner(_Pyramid,_TopContainer) + AND + NOT DB_IsPlayer((CHARACTERGUID)_TopContainer) + AND + ItemGetOriginalOwner(_Pyramid,_Owner) + THEN + ItemToInventory(_Pyramid,_Owner,-1); + + IF + RegionEnded(_Region) + AND + DB_TeleporterPyramidUnlocked(_Pyramid) + AND + GetRegion(_Pyramid,_Region) + AND + NOT GetInventoryOwner(_Pyramid,_) + AND + ItemGetOriginalOwner(_Pyramid,_Owner) + THEN + ItemToInventory(_Pyramid,_Owner,-1); + + /* + IF + ItemWentOnStage(_Container,0) + AND + DB_TeleporterPyramidUnlocked(_Pyramid) + AND + //TODO: implement this: ItemIsInItemInventory(_Pyramid,_Container,1) + AND + GetPosition(_Container,_X,_Y,_Z) + THEN + TeleportToPosition(_Pyramid,_X,_Y,_Z,"",0); + ItemClearOwner(_Pyramid); + */ + + // Prevent NPCs leaving with Pyramids in their inventory + IF + CharacterWentOnStage(_NPC,0) + AND + // Players can be set off-stage temporarily by story in some cases + NOT DB_IsPlayer(_NPC) + AND + DB_TeleporterPyramid(_Pyramid) + AND + ItemIsInCharacterInventory(_Pyramid,_NPC,1) + AND + GetPosition(_NPC,_X,_Y,_Z) + THEN + TeleportToPosition(_Pyramid,_X,_Y,_Z,"",0); + ItemClearOwner(_Pyramid); + + PROC + Proc_CompanionLeftParty((CHARACTERGUID)_Companion,(CHARACTERGUID)_Player) + AND + DB_TeleporterPyramid(_Pyramid) + AND + ItemIsInCharacterInventory(_Pyramid,_Companion,1) + THEN + ItemToInventory(_Pyramid,_Player,-1); + //END_REGION + + + //REGION Pyramids using (teleportation) + IF + CharacterTeleportToPyramid(_Char,_Pyramid) + AND + PyramidEnabled(_Pyramid) + AND + GetPosition(_Pyramid,_X,_Y,_Z) + THEN + TeleportToPosition(_Char,_X,_Y,_Z,"",1,1); + + IF + CharacterTeleportToPyramid(_Char,_Pyramid) + AND + NOT PyramidEnabled(_Pyramid) + THEN + Proc_StartDialog(1,"GEN_AD_TeleporterPyramidDisabled",_Char); + // TODO: check if this is needed ---> DB_CustomUseItemResponse(_Char,_Pyramid,0); + + PROC + ProcBlockUseOfItem(_Player,_Pyramid) + AND + DB_TeleporterPyramid(_Pyramid) + AND + DB_IsPlayer(_Player) + AND + NOT PyramidEnabled(_Pyramid) + THEN + CloseUI(_Player,"Inventory"); + ObjectSetFlag(_Player,"SourcePyramidBlocked"); + Proc_StartDialog(1,"GEN_AD_TeleporterPyramidDisabled",_Player); + DB_CustomUseItemResponse(_Player,_Pyramid,0); + + PROC + ProcBlockUseOfItem(_Player,_Pyramid) + AND + DB_TeleporterPyramid(_Pyramid) + AND + DB_IsPlayer(_Player) + AND + DB_PyramidBlockerTrigger(_Trigger) + AND + ObjectIsInTrigger(_Player,_Trigger,1) + THEN + CloseUI(_Player,"Inventory"); + ObjectSetFlag(_Player,"SourcePyramidBlocked"); + Proc_StartDialog(1,"GEN_AD_TeleporterPyramidDisabled",_Player); + DB_CustomUseItemResponse(_Player,_Pyramid,0); + //END_REGION + + + IF + ItemAddedToCharacter(_Pyramid,_Player) + AND + DB_TeleporterPyramid(_Pyramid) + AND + DB_IsPlayer(_Player) + THEN + PROC_CheckPlayTutWithDelay(_Player,"TUT_Pyramid",2000); + + + //REGION Enable/disable + //TEMP: needs to be a game calls + PROC + DisablePyramid((ITEMGUID)_Item) + THEN + SetTag(_Item,"PYRAMID_DISABLED"); + + PROC + EnablePyramid((ITEMGUID)_Item) + THEN + ClearTag(_Item,"PYRAMID_DISABLED"); + + QRY + PyramidEnabled((ITEMGUID)_Item) + AND + IsTagged(_Item,"PYRAMID_DISABLED",0) + THEN + DB_NOOP(1); + //END_REGION + + } + EXIT + { + + } +} +Goal(31).Title("_GLOBAL_TutorialMessages"); +Goal(31) +{ + INIT + { + DB_ItemOpened(0); + + /*********************** + * Flags field: a bit field + * 0 : no checks + * 1 : no combat : don't show the tutorial if the character is active in combat + * 2 : no UI : don't show the tutorial if the character has a UI open + * 4 : cancel on condition fail : the tutorial is removed from the queue if the conditions don't match, it can be sent again after that + * 8 : force enqueue (wait at least one frame) + * 16 : newfeature : this tutorial is specific for DOS2 + ***********************/ + DB_TutorialInfo("TUT_Book","TUT_CAT_Inventory","TUT_Book_Title",0,0,-1,1,3,0); + DB_TutorialInfo("TUT_Camera","TUT_CAT_Exploring","TUT_Camera_Title",0,0,6000,1,2,0); + DB_TutorialInfo("TUT_Combat","TUT_CAT_Combat","TUT_Combat_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_Combat_Examine","TUT_CAT_Combat","TUT_Combat_Examine_Title",0,0,20000,2,0,0); + DB_TutorialInfo("TUT_Combat_Guard","TUT_CAT_Combat","TUT_Combat_Guard_Title",0,2,-1,2,0,0); + DB_TutorialInfo("TUT_Combat_TacticalView","TUT_CAT_Combat","TUT_Combat_TacticalView_Title",0,0,20000,2,0,0); + DB_TutorialInfo("TUT_Combat_TargetCycle","TUT_CAT_Combat","TUT_Combat_TargetCycle_Controller_Title",2,0,-1,1,0,0); + DB_TutorialInfo("TUT_Combat_TurnOrder","TUT_CAT_Combat","TUT_Combat_TurnOrder_Title",0,3,-1,1,0,0); + DB_TutorialInfo("TUT_Died","TUT_CAT_Combat","TUT_Died_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_Disarm","TUT_CAT_Exploring","TUT_Disarm_Title",0,0,-1,3,0,0); + DB_TutorialInfo("TUT_DragIcon","TUT_CAT_Exploring","TUT_DragIcon_Title",1,0,-1,1,0,0); + DB_TutorialInfo("TUT_Equipment","TUT_CAT_Inventory","TUT_Equipment_Title",0,0,20000,1,2,0); + DB_TutorialInfo("TUT_Flee","TUT_CAT_Combat","TUT_Flee_Title",0,0,-1,3,4,0); + DB_TutorialInfo("TUT_GasPit","TUT_CAT_Exploring","TUT_GasPit_Title",0,1,-1,3,0,0); + DB_TutorialInfo("TUT_GenericBehaviors","TUT_CAT_Exploring","TUT_GenericBehaviors_Title",0,0,-1,3,0,0); + DB_TutorialInfo("TUT_Hammer","TUT_CAT_Inventory","TUT_Hammer_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_HotbarAssignment","TUT_CAT_Inventory","TUT_HotbarAssignment_Title",0,0,15000,2,6,0); + DB_TutorialInfo("TUT_IdentifyingGlass","TUT_CAT_Inventory","TUT_IdentifyingGlass_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_Inventory","TUT_CAT_Inventory","TUT_Inventory_Title",0,2,20000,1,2,0); + DB_TutorialInfo("TUT_LevelUp","TUT_CAT_Inventory","TUT_LevelUp_Title",0,2,20000,2,3,0); + DB_TutorialInfo("TUT_Locked","TUT_CAT_Exploring","TUT_Locked_Title",0,0,-1,3,0,0); + DB_TutorialInfo("TUT_WoodenDoor","TUT_CAT_Exploring","TUT_WoodenDoor_Title",0,0,-1,3,0,0); + DB_TutorialInfo("TUT_Lockpick","TUT_CAT_Inventory","TUT_Lockpick_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_Mound","TUT_CAT_Exploring","TUT_Mound_Title",0,0,-1,3,0,0); + DB_TutorialInfo("TUT_Movement","TUT_CAT_Exploring","TUT_Movement_Title",0,0,6000,1,0,0); + DB_TutorialInfo("TUT_NoPetPal","TUT_CAT_Social","TUT_PetPal_Title",0,0,-1,2,0,0); + DB_TutorialInfo("TUT_Perception","TUT_CAT_Inventory","TUT_Perception_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_PetPal","TUT_CAT_Social","TUT_PetPal_Title",0,0,-1,2,0,0); + DB_TutorialInfo("TUT_Potion","TUT_CAT_Combat","TUT_Potion_Title",0,1,-1,2,0,0); + DB_TutorialInfo("TUT_Pyramid","TUT_CAT_Exploring","TUT_Pyramid_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_Pyramid_2","TUT_CAT_Exploring","TUT_Pyramid_2_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_PyramidsPickup","TUT_CAT_Exploring","TUT_PyramidsPickup_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_ReflectionDialog","TUT_CAT_Social","TUT_ReflectionDialog_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_SaveLoad","TUT_CAT_General","TUT_SaveLoad_Title",0,0,-1,1,0,0); + DB_TutorialInfo("TUT_Scroll","TUT_CAT_Combat","TUT_Scroll_Title",0,0,-1,2,2,0); + DB_TutorialInfo("TUT_Shovel","TUT_CAT_Exploring","TUT_Shovel_Title",0,0,-1,2,0,0); + DB_TutorialInfo("TUT_Skill","TUT_CAT_Inventory","TUT_Skill_Title",0,0,-1,2,2,0); + DB_TutorialInfo("TUT_SkillUnlock","TUT_CAT_Combat","TUT_SkillUnlock_Title",0,0,-1,2,0,0); + DB_TutorialInfo("TUT_Stealing","TUT_CAT_Exploring","TUT_Stealing_Title",0,0,-1,3,0,0); + DB_TutorialInfo("TUT_Waypoint","TUT_CAT_Exploring","TUT_Waypoint_Title",0,0,-1,2,0,0); + DB_TutorialInfo("TUT_BondedAvatar","TUT_CAT_Social","TUT_BondedAvatar_Title",0,0,-1,1,16,0); + DB_TutorialInfo("TUT_HotbarLocked","TUT_CAT_Combat","TUT_HotbarLocked_Title",0,3,-1,1,0,10); + DB_TutorialInfo("TUT_Tooltips","TUT_CAT_Exploring","TUT_Tooltips_Title",1,0,-1,2,0,0); + DB_TutorialInfo("TUT_Tooltips_Controller","TUT_CAT_Exploring","TUT_Tooltips_Title",2,0,-1,2,0,0); + DB_TutorialInfo("TUT_TagVillain","TUT_CAT_Social","TUT_TagVillain_Title",0,0,-1,2,0,0); + DB_TutorialInfo("TUT_TagHero","TUT_CAT_Social","TUT_TagHero_Title",0,0,-1,2,0,0); + DB_TutorialInfo("TUT_Waypoint","TUT_CAT_Exploring","TUT_Waypoint_Title",0,2,3,1,0,0); + + } + KB + { + //REGION Tutorial Message + PROC + ProcPlayTut((CHARACTERGUID)_Char,(STRING)_Message) + AND + DB_TutorialInfo(_Message,(STRING)_Cat,(STRING)_Title,(INTEGER)_ControllerType,(INTEGER)_ModalType,(INTEGER)_Duration,(INTEGER)_Priority,(INTEGER)_Flags,(INTEGER)_MinimumPlaytime) + THEN + ShowTutorial(_Char,_Message,_Cat,_Title,_ControllerType,_ModalType,_Duration,_Priority,_Flags,_MinimumPlaytime); + + PROC + ProcPlayTut((CHARACTERGUID)_Char,(STRING)_Message) + AND + DB_TutorialInfo_MsgBox(_Message,(STRING)_Cat,(STRING)_Title,(INTEGER)_ControllerType,(INTEGER)_ModalType,(INTEGER)_Duration,(INTEGER)_Priority,(INTEGER)_Flags,(INTEGER)_MinimumPlaytime) + THEN + OpenMessageBox(_Char,_Message); + + PROC + ProcPlayTut((CHARACTERGUID)_Char,(STRING)_Message) + AND + NOT DB_TutorialInfo(_Message,_,_,_,_,_,_,_,_) + AND + NOT DB_TutorialInfo_MsgBox(_Message,_,_,_,_,_,_,_,_) + AND + StringConcatenate("Tutorial Message without info: ",_Message,_ErrorMessage) + THEN + DebugBreak(_ErrorMessage); + ShowTutorial(_Char,_Message,"","",0,0,-1,3,0,0); + //END_REGION + + //REGION Tutorial From ProximityTutorial.itemscript + IF + CharacterItemEvent(_Character,_Item,"LaunchTutorialMessage") + AND + GetVarString(_Item,"TutorialMessage",_TutorialName) + THEN + PROC_CheckPlayTut(_Character,_TutorialName); + //END_REGION + + //REGION Movement Popup + + // See also _GLOBAL_TutorialMessages_MovementDetection + IF + DB_GLO_Tutorial_StartMovementTutorial(1) + THEN + TimerLaunch("TUT_Movement",5000); + + IF + TimerFinished("TUT_Movement") + AND + DB_IsPlayer(_Player) + AND + NOT DB_GLOBAL_TutorialMessages_MovementTutFinishedFor(_Player) + THEN + PROC_CheckPlayTut(_Player,"TUT_Movement"); + + IF + TimerFinished("TUT_Camera") + THEN + PROC_CheckPlayTut("TUT_Camera"); + DB_InitialTutorialsShown(1); + //END_REGION + + //REGION Inventory Popup + IF + ItemTemplateAddedToCharacter(_,_,_Player) + AND + _Player.DB_IsPlayer() + AND + DB_InitialTutorialsShown(1) + THEN + ProcCheckInventoryTutorial(_Player); + + PROC + ProcCheckInventoryTutorial((GUIDSTRING)_Player) + AND + IsSpeakerReserved(_Player,0) + THEN + PROC_CheckPlayTut((CHARACTERGUID)_Player,"TUT_Inventory"); + + PROC + ProcCheckInventoryTutorial((GUIDSTRING)_Player) + AND + IsSpeakerReserved(_Player,1) + THEN + DB_InventoryMessageQueued(_Player); + + IF + DialogEnded(_,_ID) + AND + DB_DialogPlayers(_ID,_Player,_) + AND + DB_InventoryMessageQueued(_Player) + THEN + NOT DB_InventoryMessageQueued(_Player); + //force a frame delay to give Osiris a chance to run other logic, in case this dialog causes combat or another dialog + SetStoryEvent(_Player,"GLO_CheckInventoryTutorial"); + + IF + StoryEvent(_Player,"GLO_CheckInventoryTutorial") + AND + QRY_SpeakerIsAvailable(_Player) + THEN + PROC_CheckPlayTut((CHARACTERGUID)_Player,"TUT_Inventory"); + + + //END_REGION + + //REGION Combat Popup + IF + ObjectTurnStarted((CHARACTERGUID)_Player) + AND + _Player.DB_IsPlayer() + AND + CharacterGetAbility(_Player, "Loremaster", _Val) + AND + _Val > 0 + AND + DB_CharCountHelper(_Player,"CombatTurnCounter",_Turn) + AND + _Turn >= 6 + THEN + PROC_CheckPlayTut(_Player,"TUT_Combat_Examine"); + //END_REGION + + //REGION Tool Popups + IF + ItemTemplateAddedToCharacter(TOOL_LockPick_A_06d0eecb-4271-42a7-bd8c-4cbf24927197,_,_Player) + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTut(_Player, "TUT_Lockpick"); + + IF + ItemTemplateAddedToCharacter(TOOL_Hammer_Repair_A_be7226da-7211-4250-be95-ca780bcdb3df,_,_Player) + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTut(_Player, "TUT_Hammer"); + + IF + ItemTemplateAddedToCharacter(TOOL_IdentifyingGlass_A_32288ce4-3d8d-46b3-a655-598350a96201,_,_Player) + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTut(_Player, "TUT_IdentifyingGlass"); + + IF + ItemTemplateAddedToCharacter(TOOL_Trap_DisarmToolkit_9fda335e-2220-4ae9-a4c2-2424d5ef5165,_,_Player) + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTut(_Player, "TUT_Disarm"); + + IF + ItemTemplateAddedToCharacter(TOOL_Shovel_A_41486dd2-3fd5-464e-870e-844120cf0517,_,_Player) + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTut(_Player,"TUT_Shovel"); + //END_REGION + + IF + ObjectTurnStarted((CHARACTERGUID)_Player) + AND + _Player.DB_IsPlayer() + AND + CharacterGetHitpointsPercentage(_Player,_Percentage) + AND + _Percentage < 25 + AND + _Percentage > 0 + AND + DB_PotionDone(1) + THEN + PROC_CheckPlayTut(_Player,"TUT_Flee"); + + IF + ObjectTurnStarted((CHARACTERGUID)_Player) + AND + _Player.DB_IsPlayer() + AND + CharacterGetHitpointsPercentage(_Player,_Percentage) + AND + _Percentage < 25 + AND + _Percentage > 0 + THEN + PROC_CheckPlayTut(_Player,"TUT_Potion"); + DB_PotionDone(1); + + IF + CharacterItemEvent(_, _Item, "WaypointDiscovered") + AND + DB_WaypointInfo((ITEMGUID)_Item,(TRIGGERGUID)_,(STRING)_) + THEN + DB_WaypointTuto(1); + + IF + CharacterDied(_Player) + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTutWithDelay(_Player,"TUT_Died",2000); + + IF + StoryEvent((CHARACTERGUID)_Player,_Event) + AND + DB_Event2DisplayText(_Event,_Text) //See the goal TrapReactions for context about that DB + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTutWithDelay(_Player,"TUT_Perception",2000); + + IF + CharacterUsedItem(_Player,_Mound) + AND + DB_ShovelArea(_,_,_Mound) + THEN + PROC_CheckPlayTut(_Player,"TUT_Mound"); + + IF + TextEventSet("axeltuto") + THEN + DB_StartTutMessages(1); + + IF + CharacterLeveledUp(_Player) + AND + _Player.DB_IsPlayer() + THEN + PROC_CheckPlayTut(_Player, "TUT_LevelUp"); + + IF + ItemAddedToCharacter(_Item, _Player) + AND + DB_InitialTutorialsShown(1) + AND + DB_IsPlayer(_Player) + AND + ItemHasOnUse(_Item,"skillbook",1) + THEN + PROC_CheckPlayTut(_Player,"TUT_Skill"); + + IF + ItemAddedToCharacter(_Item, _Player) + AND + DB_InitialTutorialsShown(1) + AND + DB_IsPlayer(_Player) + AND + ItemHasOnUse(_Item,"scrollarrow",1) + AND + IsTagged(_Item,"GRENADES",0) + THEN + PROC_CheckPlayTut(_Player, "TUT_Scroll"); + + IF + ItemAddedToCharacter(_Item, _Player) + AND + DB_InitialTutorialsShown(1) + AND + DB_IsPlayer(_Player) + AND + ItemHasOnUse(_Item,"book",1) + THEN + PROC_CheckPlayTut(_Player, "TUT_Book"); + + IF + DifficultyChanged(0) + THEN + DB_TUT_PlayOnEasy(1); + + IF + DifficultyChanged(_Int) + AND + _Int != 0 + THEN + NOT DB_TUT_PlayOnEasy(1); + + IF + SkillAdded(_Player,_,1) + AND + DB_IsPlayer(_Player) + AND + CharacterIsControlled(_Player,1) + AND + DB_InitialTutorialsShown(1) + AND + NOT DB_TutorialMessages_SkillUnlockDone(_Player) + THEN + ProcObjectTimer(_Player,"TUT_SkillUnlock",500); + + PROC + ProcObjectTimerFinished(_Player,"TUT_SkillUnlock") + THEN + PROC_TutorialMessage_SkillUnlockAfterDialog((CHARACTERGUID)_Player); + + PROC + PROC_TutorialMessage_SkillUnlockAfterDialog((CHARACTERGUID)_Player) + AND + NOT DB_DialogPlayers(_,_Player,_) + THEN + DB_TutorialMessages_SkillUnlockDone(_Player); + PROC_CheckPlayTut(_Player, "TUT_SkillUnlock"); + + PROC + PROC_TutorialMessage_SkillUnlockAfterDialog((CHARACTERGUID)_Player) + AND + NOT DB_TutorialMessages_SkillUnlockDone(_Player) + AND + DB_DialogPlayers(_Inst,_Player,_) + AND + NOT DB_AutomatedDialog(_Inst) + THEN + DB_TutorialMessage_CheckEndDialog_SkillTut(_Inst,_Player); + + PROC + PROC_TutorialMessage_SkillUnlockAfterDialog((CHARACTERGUID)_Player) + AND + NOT DB_TutorialMessages_SkillUnlockDone(_Player) + AND + DB_DialogPlayers(_Inst,_Player,_) + AND + DB_AutomatedDialog(_Inst) + THEN + DB_TutorialMessage_CheckEndAutomatedDialog_SkillTut(_Inst,_Player); + + IF + DialogEnded(_,_Inst) + AND + DB_TutorialMessage_CheckEndDialog_SkillTut(_Inst,_Player) + THEN + NOT DB_TutorialMessage_CheckEndDialog_SkillTut(_Inst,_Player); + DB_TutorialMessages_SkillUnlockDone(_Player); + PROC_CheckPlayTut(_Player, "TUT_SkillUnlock"); + + IF + AutomatedDialogEnded(_,_Inst) + AND + DB_TutorialMessage_CheckEndAutomatedDialog_SkillTut(_Inst,_Player) + THEN + NOT DB_TutorialMessage_CheckEndAutomatedDialog_SkillTut(_Inst,_Player); + DB_TutorialMessages_SkillUnlockDone(_Player); + PROC_CheckPlayTut(_Player, "TUT_SkillUnlock"); + + IF + ItemTemplateOpening(_,_Item, _Player) + AND + DB_IsPlayer(_Player) + AND + ItemIsContainer(_Item, 1) + AND + DB_ItemOpened(_Nb) + AND + _Nb == 10 + THEN + PROC_CheckPlayTut(_Player, "TUT_DragIcon"); + + IF + ItemTemplateOpening(_,_Item, _Player) + AND + DB_IsPlayer(_Player) + AND + ItemIsContainer(_Item, 1) + AND + DB_ItemOpened(_Nb) + AND + IntegerSum(_Nb,1,_NewNb) + THEN + NOT DB_ItemOpened(_Nb); + DB_ItemOpened(_NewNb); + + IF + DialogStarted(_,_Instance) + AND + DB_DialogNPCs(_Instance,_Animal,1) + AND + DB_DialogPlayers(_Instance,_Player,1) + AND + CharacterHasTalent((CHARACTERGUID)_Player,"AnimalEmpathy",0) + AND + IsTagged(_Animal,"ANIMAL",1) + THEN + PROC_CheckPlayTut(_Player,"TUT_NoPetPal"); + + IF + DialogStarted(_,_Instance) + AND + DB_DialogNPCs(_Instance,_Animal,1) + AND + DB_DialogPlayers(_Instance,_Player,1) + AND + CharacterHasTalent((CHARACTERGUID)_Player,"AnimalEmpathy",1) + AND + IsTagged(_Animal,"ANIMAL",1) + THEN + PROC_CheckPlayTut(_Player,"TUT_PetPal"); + + IF + ItemAddedToCharacter(_Item,_Player) + AND + DB_IsPlayer(_Player) + AND + DB_CharCountHelper(_Player,"CombatTurnCounter",_Turn) + AND + _Turn >= 3 + AND + ItemHasOnUse(_Item,"scrollarrow",1) + AND + ItemIsEquipable(_Item,0) + THEN + PROC_CheckPlayTut(_Player,"TUT_HotbarAssignment"); + + IF + ItemAddedToCharacter(_Item,_Player) + AND + DB_InitialTutorialsShown(1) + AND + DB_IsPlayer(_Player) + AND + ItemIsEquipable(_Item,1) + THEN + PROC_CheckPlayTut(_Player,"TUT_Equipment"); + + IF + CharacterUsedItem(_Player,_Item) + AND + DB_IsPlayer(_Player) + AND + ObjectIsItem(_Item,1) + AND + ItemIsLocked(_Item,1) + THEN + PROC_CheckPlayTut(_Player,"TUT_Locked"); + DB_TUT_ShowedTutLocked(1); + + IF + CharacterItemEvent(_Character, _,"WaypointDiscovered") + THEN + PROC_CheckPlayTut(_Character, "TUT_Waypoint"); + + } + EXIT + { + + } +} +Goal(32).Title("_GLOBAL_TutorialMessages_MovementDetection"); +Goal(32) +{ + INIT + { + // Don't show the movement tutorial for players that move before the tutorial is shown + + // Trigger the camera tutorial 10 seconds after all players have moved, or + // 10 seconds after the first player closed the movement tutorial box + + } + KB + { + // Triggers to detect that someone moved from their initial position + IF + DB_Tutorial_PlayerMovementDetectionTrigger((TRIGGERGUID)_Trigger) + THEN + TriggerRegisterForPlayers(_Trigger); + + // Player entered detection trigger -> won't get movement tutorial + // + check whether everyone has moved (if so, complete this goal + // and schedule the camera tutorial) + IF + CharacterEnteredTrigger(_Player,_Trigger) + AND + DB_Tutorial_PlayerMovementDetectionTrigger(_Trigger) + THEN + PROC_GLOBAL_TutorialMessages_PlayerMoved(_Player); + + // Player got the movement tutorial -> record so we know + // we should only schedule the camera tutorial after a + // a movement tutorial box has been closed + PROC + PROC_CheckPlayTut(_Char,"TUT_Movement") + THEN + DB_GlobalTutorialMessages_TUT_Movement_Shown(1); + PROC_GLOBAL_TutorialMessages_PlayerMoved(_Char); + + //REGION Handle a player moving or getting the movement tutorial + // This player has moved or got the tutorial + PROC + PROC_GLOBAL_TutorialMessages_PlayerMoved((CHARACTERGUID)_Player) + THEN + DB_GLOBAL_TutorialMessages_MovementTutFinishedFor(_Player); + + // Anyone left that didn't move or didn't get the tutorial? + PROC + PROC_GLOBAL_TutorialMessages_PlayerMoved((CHARACTERGUID)_Player) + AND + DB_IsPlayer(_AnyPlayer) + AND + NOT DB_GLOBAL_TutorialMessages_MovementTutFinishedFor(_AnyPlayer) + THEN + DB_GLOBAL_TutorialMessages_MovementTutUnfinished(1); + + // No one left -> unregister movement detection triggers + PROC + PROC_GLOBAL_TutorialMessages_PlayerMoved((CHARACTERGUID)_Player) + AND + NOT DB_GLOBAL_TutorialMessages_MovementTutUnfinished(1) + AND + DB_Tutorial_PlayerMovementDetectionTrigger(_Trigger) + THEN + ProcTriggerUnregisterForPlayers(_Trigger); + NOT DB_Tutorial_PlayerMovementDetectionTrigger(_Trigger); + + // No one left -> schedule camera tutorial right away if everyone + // skipped the movement tutorial and complete goal + PROC + PROC_GLOBAL_TutorialMessages_PlayerMoved((CHARACTERGUID)_Player) + AND + NOT DB_GLOBAL_TutorialMessages_MovementTutUnfinished(1) + AND + NOT DB_GlobalTutorialMessages_TUT_Movement_Shown(1) + THEN + TimerLaunch("TUT_Camera",10000); + GoalCompleted; + + // Clean up + PROC + PROC_GLOBAL_TutorialMessages_PlayerMoved((CHARACTERGUID)_Player) + THEN + NOT DB_GLOBAL_TutorialMessages_MovementTutUnfinished(1); + //END_REGION + + // At least one player got the movement tutorial and dismissed it + // -> schedule the camera tutorial + IF + TutorialBoxClosed(_,_Message) + AND + StringContains(_Message,"TUT_Movement",1) + AND + NOT DB_Tutorial_PlayerCameraTutorialTimerLaunched(1) + THEN + // Only launch once, multiple players could have gotten this dialog + DB_Tutorial_PlayerCameraTutorialTimerLaunched(1); + TimerLaunch("TUT_Camera",10000); + GoalCompleted; + + } + EXIT + { + NOT DB_GlobalTutorialMessages_TUT_Movement_Shown(1); + NOT DB_Tutorial_PlayerCameraTutorialTimerLaunched(1); + + } +} +Goal(33).Title("_Greevers_Little_Helpers"); +Goal(33) +{ + INIT + { + DB_Singleton("InitData",0); + + DB_GLO_AttributeCheck_Var(1,"Name","Attribute_Check_1_Name_080aa25a-eb82-4060-a20f-93f3f0a3ec85"); + DB_GLO_AttributeCheck_Var(1,"Difficulty","Attribute_Check_1_Difficulty_6645b5b8-4c17-4678-98b2-d5d718c36829"); + DB_GLO_AttributeCheck_Var(1,"LevelOverride","Attribute_Check_1_LevelOverride_08b97107-2d16-4ff5-a2e5-a01ed50e7135"); + DB_GLO_AttributeCheck_Var(1,"Source","Attribute_Check_1_Source_dd323f37-f472-4a67-9a44-5ca9f15646bb"); + DB_GLO_AttributeCheck_Var(1,"Target","Attribute_Check_1_Target_c46387f7-f39b-46c5-b6ec-baeccc34291a"); + + DB_GLO_AttributeCheck_Var(2,"Difficulty","Attribute_Check_2_Difficulty_eab60140-a9e3-4579-b5fa-3cb5515c2282"); + DB_GLO_AttributeCheck_Var(2,"LevelOverride","Attribute_Check_2_LevelOverride_1dc16030-ece6-4677-ae14-62e7e9d1ac0e"); + DB_GLO_AttributeCheck_Var(2,"Name","Attribute_Check_2_Name_151dfe0f-6575-4ce2-bedc-6f157abdb36e"); + DB_GLO_AttributeCheck_Var(2,"Source","Attribute_Check_2_Source_c40af148-2c37-444b-a462-4387a4c6cede"); + DB_GLO_AttributeCheck_Var(2,"Target","Attribute_Check_2_Target_b8df81e7-d122-452b-bfaa-f9bbe87fd387"); + + DB_GLO_AttributeCheck_Var(3,"Difficulty","Attribute_Check_3_Difficulty_ff545cea-32e3-4a9a-b005-f3a6e0f0cabd"); + DB_GLO_AttributeCheck_Var(3,"LevelOverride","Attribute_Check_3_LevelOverride_6e3f0bc5-636f-48ad-ad0a-642c3146302b"); + DB_GLO_AttributeCheck_Var(3,"Name","Attribute_Check_3_Name_8281a807-0ae5-4ada-8dc5-3b859310c1f5"); + DB_GLO_AttributeCheck_Var(3,"Source","Attribute_Check_3_Source_32f31478-7329-4902-bb66-a9043819102c"); + DB_GLO_AttributeCheck_Var(3,"Target","Attribute_Check_3_Target_65312317-50da-4cce-a6e9-725a85e7fd46"); + + } + KB + { + //REGION Stacks + + //Stacks are a useful tool to mimic a FILO stack structure. + //Add items using the Stack((STRING)_ID,_Value) command. + //At any time you can query for DB_TopOfStackCharacter((STRING)_ID,_Value), DB_TopOfStackItem((STRING)_ID,_Value) or DB_TopOfStackTrigger((STRING)_ID,_Value) + //If you wish to pop the top member of the stack, just call PopStack((STRING)_ID); + PROC + Stack_Internal((STRING)_ID,(STRING)_Value) + AND + NOT DB_StackInternalCounter(_,_ID) + THEN + DB_StackInternalCounter(0,_ID); + DB_TopOfStack(_ID,_Value); + + PROC + Stack_Internal((STRING)_ID,(STRING)_Value) + AND + DB_StackInternalCounter(_Amount,_ID) + AND + IntegerSum(_Amount,1,_NewAmount) + AND + DB_TopOfStack(_ID,_TopValue) + THEN + NOT DB_StackInternalCounter(_Amount,_ID); + DB_StackInternalCounter(_NewAmount,_ID); + DB_StackInternalMember(_NewAmount,_ID,_Value); + NOT DB_TopOfStack(_ID,_TopValue); + DB_TopOfStack(_ID,_Value); + + PROC + PopStack((STRING)_ID) + AND + DB_StackInternalCounter(1,_ID) + AND + DB_TopOfStack(_ID,_Value) + THEN + NOT DB_TopOfStack(_ID,_Value); + NOT DB_StackInternalCounter(1,_ID); + NOT DB_StackInternalMember(1,_ID,_Value); + ProcClearOldTopOfStack(_ID); + + PROC + PopStack((STRING)_ID) + AND + DB_StackInternalCounter(_Amount,_ID) + AND + IntegerSubtract(_Amount,1,_NewAmount) + AND + DB_StackInternalMember(_Amount,_ID,_OldTopValue) + AND + DB_StackInternalMember(_NewAmount,_ID,_NewTopValue) + THEN + NOT DB_StackInternalCounter(_Amount,_ID); + DB_StackInternalCounter(_NewAmount,_ID); + NOT DB_StackInternalMember(_Amount,_ID,_OldTopValue); + NOT DB_TopOfStack(_ID,_OldTopValue); + DB_TopOfStack(_ID,_NewTopValue); + + PROC + Stack((STRING)_ID,(GUIDSTRING)_Object) + AND + GetUUID(_Object,_UUID) + THEN + DB_Stack_UUID(_Object,_UUID); + Stack_Internal(_ID,_UUID); + + IF + DB_TopOfStack(_ID,_UUID) + AND + DB_Stack_UUID(_Value,_UUID) + THEN + ProcClearOldTopOfStack(_ID); + DB_TopOfStackObject(_ID,_Value); + + PROC + ProcClearOldTopOfStack((STRING)_ID) + AND + DB_TopOfStackObject(_ID,_Value) + THEN + NOT DB_TopOfStackObject(_ID,_Value); + + //END_REGION + + //REGION Default Parameters + PROC + CharacterLookAt((CHARACTERGUID)_Character1,(GUIDSTRING)_Target) + THEN + CharacterLookAt(_Character1,_Target,0); + + PROC + PlayAnimation((GUIDSTRING)_Object,(STRING)_String) + THEN + PlayAnimation(_Object,_String,""); + + PROC + TeleportTo((GUIDSTRING)_Object,(GUIDSTRING)_Target) + THEN + TeleportTo(_Object,_Target,"",1,0); + + PROC + TeleportTo((GUIDSTRING)_Object,(GUIDSTRING)_Target,(STRING)_Event,(INTEGER)_TeleportLinkedCharacters) + THEN + TeleportTo(_Object,_Target,_Event,_TeleportLinkedCharacters,0); + + PROC + TeleportToPosition((GUIDSTRING)_Object,(REAL)_X,(REAL)_Y,(REAL)_Z,(STRING)_Event,(INTEGER)_TeleportLinkedCharacters) + THEN + TeleportToPosition(_Object,_X,_Y,_Z,_Event,_TeleportLinkedCharacters,0); + + PROC + ApplyStatus((GUIDSTRING)_Target,(STRING)_Status,(REAL)_Duration) + THEN + ApplyStatus(_Target,_Status,_Duration,0); + + PROC + PartySetFlag((CHARACTERGUID)_Character,(STRING)_Event) + THEN + PartySetFlag(_Character,_Event,0); + + PROC + ObjectSetFlag((GUIDSTRING)_Object,(STRING)_Event) + THEN + ObjectSetFlag(_Object,_Event,0); + + PROC + ObjectClearFlag((GUIDSTRING)_Object,(STRING)_Event) + THEN + ObjectClearFlag(_Object,_Event,0); + + PROC + UserSetFlag((CHARACTERGUID)_Character,(STRING)_Event) + THEN + UserSetFlag(_Character,_Event,0); + + PROC + CharacterUseSkill((CHARACTERGUID)_Character,(STRING)_Skill,(GUIDSTRING)_Target) + THEN + CharacterUseSkill(_Character,_Skill,_Target,0,0,0); + + PROC + CharacterUseSkill((CHARACTERGUID)_Character,(STRING)_Skill,(GUIDSTRING)_Target,(INTEGER)_ForceResetCooldown) + THEN + CharacterUseSkill(_Character,_Skill,_Target,_ForceResetCooldown,0,0); + + PROC + CharacterUseSkill((CHARACTERGUID)_Character,(STRING)_Skill,(GUIDSTRING)_Target,(INTEGER)_ForceResetCooldown, (INTEGER)_IgnoreHasSkill) + THEN + CharacterUseSkill(_Character,_Skill,_Target,_ForceResetCooldown,_IgnoreHasSkill,0); + + PROC + CharacterAddSkill((CHARACTERGUID)_Character, (STRING)_Skill) + THEN + CharacterAddSkill((CHARACTERGUID)_Character, (STRING)_Skill, 1); + + PROC + CharacterMakePlayer((CHARACTERGUID)_Character) + THEN + CharacterMakePlayer((CHARACTERGUID)_Character,NULL_00000000-0000-0000-0000-000000000000); + //END_REGION + + //REGION Trigger Spotter + QRY + Query_IsPlayerHiding((CHARACTERGUID)_Char) + AND + HasActiveStatus(_Char,"SNEAKING",1) + THEN + DB_NOOP(1); + + QRY + Query_IsPlayerHiding((CHARACTERGUID)_Char) + AND + HasActiveStatus(_Char,"INVISIBLE",1) + THEN + DB_NOOP(1); + + IF + DB_OneShot_DialogTrigger_NewSystem((TRIGGERGUID)_Trigger,(STRING)_,(CHARACTERGUID)_Spotter) + THEN + SetVarInteger(_Spotter,"IgnoreDialogChecks",0); + DB_SneakTriggerSpotter(_Trigger,_Spotter); + + IF + DB_OneShot_DialogTrigger_NewSystem((TRIGGERGUID)_Trigger,(STRING)_,(CHARACTERGUID)_Spotter1,(CHARACTERGUID)_Spotter2) + THEN + SetVarInteger(_Spotter1,"IgnoreDialogChecks",0); + SetVarInteger(_Spotter2,"IgnoreDialogChecks",0); + DB_SneakTriggerSpotter(_Trigger,_Spotter1); + DB_SneakTriggerSpotter(_Trigger,_Spotter2); + + IF + DB_OneShot_DialogTrigger_NewSystem((TRIGGERGUID)_Trigger,(STRING)_,(CHARACTERGUID)_Spotter1,(CHARACTERGUID)_Spotter2,(CHARACTERGUID)_Spotter3) + THEN + SetVarInteger(_Spotter1,"IgnoreDialogChecks",0); + SetVarInteger(_Spotter2,"IgnoreDialogChecks",0); + SetVarInteger(_Spotter3,"IgnoreDialogChecks",0); + DB_SneakTriggerSpotter(_Trigger,_Spotter1); + DB_SneakTriggerSpotter(_Trigger,_Spotter2); + DB_SneakTriggerSpotter(_Trigger,_Spotter3); + + PROC + ProcCharInTriggerSpotted((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogTrigger_NewSystem(_Trigger,_Dialog,_Spotter) + THEN + Proc_StartDialog(0,_Dialog,_Spotter,_Player); + NOT DB_OneShot_DialogTrigger_NewSystem(_Trigger,_Dialog,_Spotter); + + PROC + ProcCharInTriggerSpotted((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogTrigger_NewSystem(_Trigger,_Dialog,_Spotter1,_Spotter2) + THEN + Proc_StartDialog(0,_Dialog,_Spotter1,_Spotter2,_Player); + NOT DB_OneShot_DialogTrigger_NewSystem(_Trigger,_Dialog,_Spotter1,_Spotter2); + + PROC + ProcCharInTriggerSpotted((CHARACTERGUID)_Player,(TRIGGERGUID)_Trigger) + AND + DB_OneShot_DialogTrigger_NewSystem(_Trigger,_Dialog,_Spotter1,_Spotter2,_Spotter3) + THEN + Proc_StartDialog(0,_Dialog,_Spotter1,_Spotter2,_Spotter3,_Player); + NOT DB_OneShot_DialogTrigger_NewSystem(_Trigger,_Dialog,_Spotter1,_Spotter2,_Spotter3); + + IF + CharacterStatusRemoved(_Player,"SNEAKING",_) + AND + DB_IsPlayer(_Player) + AND + NOT Query_IsPlayerHiding(_Player) + THEN + SetStoryEvent(_Player,"BecameVisible"); + + IF + CharacterStatusRemoved(_Player,"INVISIBLE",_) + AND + DB_IsPlayer(_Player) + AND + NOT Query_IsPlayerHiding(_Player) + THEN + SetStoryEvent(_Player,"BecameVisible"); + + IF + CharacterStatusApplied(_Player,"SNEAKING",_) + AND + DB_IsPlayer(_Player) + AND + Query_IsPlayerHiding(_Player) + THEN + SetStoryEvent(_Player,"BecameInvisible"); + + IF + CharacterStatusApplied(_Player,"INVISIBLE",_) + AND + DB_IsPlayer(_Player) + AND + NOT Query_IsPlayerHiding(_Player) + THEN + SetStoryEvent(_Player,"BecameInvisible"); + + IF + DB_TriggerSendsSpotEvents(_Trigger) + THEN + ProcTriggerRegisterForPlayers(_Trigger); + + IF + CharacterEnteredTrigger(_Player,_SpotTrigger) + AND + NOT Query_IsPlayerHiding(_Player) + AND + DB_TriggerSendsSpotEvents(_SpotTrigger) + THEN + DB_Event_CharacterAppearedInSpotTrigger(_Player,_SpotTrigger); + NOT DB_Event_CharacterAppearedInSpotTrigger(_Player,_SpotTrigger); + + IF + CharacterLeftTrigger(_Player,_SpotTrigger) + AND + NOT Query_IsPlayerHiding(_Player) + AND + DB_TriggerSendsSpotEvents(_SpotTrigger) + THEN + DB_Event_CharacterDisappearedInSpotTrigger(_Player,_SpotTrigger); + NOT DB_Event_CharacterDisappearedInSpotTrigger(_Player,_SpotTrigger); + + IF + StoryEvent((CHARACTERGUID)_Player,"BecameVisible") + AND + DB_InRegion(_Player,_SpotTrigger) + AND + DB_TriggerSendsSpotEvents(_SpotTrigger) + THEN + DB_Event_CharacterAppearedInSpotTrigger(_Player,_SpotTrigger); + NOT DB_Event_CharacterAppearedInSpotTrigger(_Player,_SpotTrigger); + + IF + StoryEvent((CHARACTERGUID)_Player,"BecameInvisible") + AND + DB_InRegion(_Player,_SpotTrigger) + AND + DB_TriggerSendsSpotEvents(_SpotTrigger) + THEN + DB_Event_CharacterDisappearedInSpotTrigger(_Player,_SpotTrigger); + NOT DB_Event_CharacterDisappearedInSpotTrigger(_Player,_SpotTrigger); + + //END_REGION + + //REGION Global Event Memory + IF + GlobalFlagSet(_String) + THEN + DB_GlobalFlag(_String); + + IF + GlobalFlagCleared(_String) + THEN + NOT DB_GlobalFlag(_String); + //END_REGION + + //REGION Poof / Foop + PROC + Poof((GUIDSTRING)_Character) + THEN + Poof((GUIDSTRING)_Character,"RS3_FX_GP_ScriptedEvent_Teleport_GenericSmoke_01"); + + PROC + Poof((GUIDSTRING)_Character,(STRING)_Effect) + AND + GetRegion(_Character,_Region) + AND + DB_CurrentLevel(_Region) + AND + GetPosition(_Character,_X,_Y,_Z) + THEN + PlayEffectAtPosition(_Effect,_X,_Y,_Z); + + PROC + Poof((GUIDSTRING)_Character,(STRING)_Effect) + THEN + SetOnStage(_Character,0); + + PROC + Foop((GUIDSTRING)_Character) + THEN + Foop(_Character,"RS3_FX_GP_ScriptedEvent_Teleport_GenericSmoke_01"); + + PROC + Foop((GUIDSTRING)_Character,(STRING)_Effect) + AND + GetRegion(_Character,_Region) + AND + DB_CurrentLevel(_Region) + AND + GetPosition(_Character,_X,_Y,_Z) + THEN + PlayEffectAtPosition(_Effect,_X,_Y,_Z); + + PROC + Foop((GUIDSTRING)_Character,(STRING)_Effect) + THEN + SetOnStage(_Character,1); + + IF + StoryEvent(_Character,"GEN_GoOffStage") + THEN + SetOnStage(_Character,0); + + PROC + Proc_PoofOnce((GUIDSTRING)_Character,(STRING)_OnlyOnce) + AND + NOT DB_OnlyOnce(_OnlyOnce) + THEN + Poof(_Character); + DB_OnlyOnce(_OnlyOnce); + //END_REGION + + //REGION Uniformly distributed Randoms (Fair random with memory) + //Fair rand requires a UUID and a maxamount. The function will return [0,Maxamount-1] + //When no previous data found, all possible numbers are added into an array. + //Every FairRand query returns one random number from the array and removes it. + //Only when the array is empty, is it reseeded. + //Output: DB_FairRand_ReturnVal(INTEGER) + + //Clear return value + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_Amount) + AND + DB_FairRand_ReturnVal((INTEGER)_Number) + THEN + NOT DB_FairRand_ReturnVal(_Number); + + //If first time or all numbers used: reseed. + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_Amount) + AND + NOT DB_FairRand_Available(_UUID,_Amount,_) + THEN + Proc_SeedFairRand(_UUID,_Amount,_Amount); + + //Pick a random number from the available array (Put in new array with indeces, pick random index, return number) + //Special case: Make sure that the first pick of a list is not the same as the last pick of the previous list + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_Amount) + THEN + DB_FairRandAmount(0); + + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_Amount) + AND + _Amount > 1 + AND + DB_FairRand_Last_Of_Previous_Seeding(_PreviousNumber) + AND + DB_FairRand_Available(_UUID,_Amount,_AvailableNumber) + AND + _PreviousNumber != _AvailableNumber + AND + DB_FairRandAmount(_Count) + AND + IntegerSum(_Count,1,_NewCount) + THEN + DB_FairRand_Array(_Count,_AvailableNumber); + NOT DB_FairRandAmount(_Count); + DB_FairRandAmount(_NewCount); + DB_FairAmount_ListFilled(1); + + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_Amount) + AND + DB_FairRand_Last_Of_Previous_Seeding(_Number) + THEN + NOT DB_FairRand_Last_Of_Previous_Seeding(_Number); + + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_Amount) + AND + NOT DB_FairAmount_ListFilled(1) + AND + DB_FairRand_Available(_UUID,_Amount,_AvailableNumber) + AND + DB_FairRandAmount(_Count) + AND + IntegerSum(_Count,1,_NewCount) + THEN + DB_FairRand_Array(_Count,_AvailableNumber); + NOT DB_FairRandAmount(_Count); + DB_FairRandAmount(_NewCount); + + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_Amount) + AND + DB_FairAmount_ListFilled(1) + THEN + NOT DB_FairAmount_ListFilled(1); + + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_Amount) + AND + DB_FairRandAmount(_Count) + AND + _Count > 0 + AND + Random(_Count,_Index) + AND + DB_FairRand_Array(_Index,_Number) + THEN + NOT DB_FairRand_Available(_UUID,_Amount,_Number); + DB_FairRand_ReturnVal(_Number); + + //If this was the last value in the available list, remember it, so we don't pick it first in the next list. + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_Amount) + AND + NOT DB_FairRand_Available(_UUID,_Amount,_) + AND + DB_FairRand_ReturnVal(_Number) + THEN + DB_FairRand_Last_Of_Previous_Seeding(_Number); + + //Clean up temp vars + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_MaxAmount) + AND + DB_FairRandAmount(_Amount) + THEN + NOT DB_FairRandAmount(_Amount); + + QRY + QRY_GetFairRand((STRING)_UUID,(INTEGER)_Amount) + AND + DB_FairRand_Array(_Index,_Number) + THEN + NOT DB_FairRand_Array(_Index,_Number); + + PROC + Proc_SeedFairRand((STRING)_UUID,(INTEGER)_MaxAmount,(INTEGER)_Amount) + AND + _Amount > 0 + AND + IntegerSubtract(_Amount,1,_NewAmount) + THEN + DB_FairRand_Available(_UUID,_MaxAmount,_NewAmount); + Proc_SeedFairRand(_UUID,_MaxAmount,_NewAmount); + //END_REGION + + //REGION Get Random position in coordinate-based area ignoring AI grid + // Pass in two objects. Returns point within cube defined by their coordinates + // Returns result in DB_Helper_GetAnyRandomPositionInArea_Result(_X,_Y,_Z) + // NOTE: only tested currently with all coordinates of FirstPoint <= coordinates of _SecondPoint + // I don't know whether our random can handle a negative module. + QRY + QRY_Helper_GetAnyRandomPositionInArea((GUIDSTRING)_FirstPoint,(GUIDSTRING)_SecondPoint) + AND + DB_Helper_GetAnyRandomPositionInArea_Result(_X,_Y,_Z) + THEN + NOT DB_Helper_GetAnyRandomPositionInArea_Result(_X,_Y,_Z); + + QRY + QRY_Helper_GetAnyRandomPositionInArea((GUIDSTRING)_BottomLeftBack,(GUIDSTRING)_TopRightFront) + AND + GetPosition(_BottomLeftBack,_X1,_Y1,_Z1) + AND + GetPosition(_TopRightFront,_X2,_Y2,_Z2) + AND + RealSubtract(_X2,_X1,_XDeltaReal) + AND + RealSubtract(_Y2,_Y1,_YDeltaReal) + AND + RealSubtract(_Z2,_Z1,_ZDeltaReal) + AND + RealProduct(_XDeltaReal,100.0,_XScaledDeltaReal) + AND + RealProduct(_YDeltaReal,100.0,_YScaledDeltaReal) + AND + RealProduct(_ZDeltaReal,100.0,_ZScaledDeltaReal) + AND + Integer(_XScaledDeltaReal,_XScaledDeltaInt) + AND + Integer(_YScaledDeltaReal,_YScaledDeltaInt) + AND + Integer(_ZScaledDeltaReal,_ZScaledDeltaInt) + AND + Random(_XScaledDeltaInt,_XRandScaledDeltaInt) + AND + Random(_YScaledDeltaInt,_YRandScaledDeltaInt) + AND + Random(_ZScaledDeltaInt,_ZRandScaledDeltaInt) + AND + Real(_XRandScaledDeltaInt,_XRandScaledDeltaReal) + AND + Real(_YRandScaledDeltaInt,_YRandScaledDeltaReal) + AND + Real(_ZRandScaledDeltaInt,_ZRandScaledDeltaReal) + AND + RealDivide(_XRandScaledDeltaReal,100.0,_XRandDeltaReal) + AND + RealDivide(_YRandScaledDeltaReal,100.0,_YRandDeltaReal) + AND + RealDivide(_ZRandScaledDeltaReal,100.0,_ZRandDeltaReal) + AND + RealSum(_X1,_XRandDeltaReal,_NewX) + AND + RealSum(_Y1,_YRandDeltaReal,_NewY) + AND + RealSum(_Z1,_ZRandDeltaReal,_NewZ) + THEN + DB_Helper_GetAnyRandomPositionInArea_Result(_NewX,_NewY,_NewZ); + //END_REGION + + //REGION Singleton Variables //A variable which can only hold one value. All old value get overwritten. + IF + DB_Singleton(_VariableNam,_NewValue) + AND + DB_Singleton(_VariableNam,_OldValue) + AND + _NewValue != _OldValue + THEN + NOT DB_Singleton(_VariableNam,_OldValue); + //END_REGION + + //REGION Only Once Rule Query + QRY + QueryOnlyOnce((STRING)_OnlyOnceUUID) + AND + NOT DB_OnlyOnce(_OnlyOnceUUID) + THEN + DB_OnlyOnce(_OnlyOnceUUID); + //END_REGION + + //REGION Only once per user, but also mark users of nearby players + // NOTE: this is intended as replacement for triggering ADs guarded by a + // QueryOnlyOnce(). It does not check for all corner cases, such as + // character reassignment to another user. It's just meant to increase + // the chances that every user will see an AD rather than only the first + // one. + + // Use for atmospheric ADs that don't influence progression, and which are + // nice for a player to see/hear at least once. It avoids playing the same + // AD for multiple users in case they already heard another user's player + // say it, and at the same time allows different users to have the same AD + // if they arrive at a spot/perform the same action at different times. + QRY + QRY_OncePerUserAndNearbyPlayers((CHARACTERGUID)_Player, (STRING)_Flag) + AND + QRY_OncePerUserAndNearbyPlayers(_Player, _Flag, 10.0) + THEN + DB_NOOP(1); + + QRY + QRY_OncePerUserAndNearbyPlayers((CHARACTERGUID)_Player, (STRING)_Flag, (REAL)_Range) + AND + UserGetFlag(_Player, _Flag, 0) + THEN + PROC_OncePerUserAndNearbyPlayers_SetFlag(_Player, _Flag, _Range); + + PROC + PROC_OncePerUserAndNearbyPlayers_SetFlag((CHARACTERGUID)_Player, (STRING)_Flag, (REAL)_Range) + AND + DB_IsPlayer(_OtherPlayer) + AND + GetDistanceTo(_Player, _OtherPlayer, _Dist) + AND + _Dist < _Range + THEN + // Will also catch _Player himself + UserSetFlag(_OtherPlayer, _Flag); + //END_REGION + + //REGION Only once per user, but also mark users of nearby players + // NOTE: this is intended as replacement for triggering ADs guarded by a + // QueryOnlyOnce(). It does not check for all corner cases, such as + // character reassignment to another user. It's just meant to increase + // the chances that every user will see an AD rather than only the first + // one. + + // Use for atmospheric ADs that don't influence progression, and which are + // nice for a player to see/hear at least once. It avoids playing the same + // AD for multiple users in case they already heard another user's player + // say it, and at the same time allows different users to have the same AD + // if they arrive at a spot/perform the same action at different times. + QRY + QRY_OncePerUserAndNearbyPlayers((CHARACTERGUID)_Player, (STRING)_Flag) + AND + QRY_OncePerUserAndNearbyPlayers(_Player, _Flag, 10.0) + THEN + DB_NOOP(1); + + QRY + QRY_OncePerUserAndNearbyPlayers((CHARACTERGUID)_Player, (STRING)_Flag, (REAL)_Range) + AND + UserGetFlag(_Player, _Flag, 0) + THEN + PROC_OncePerUserAndNearbyPlayers_SetFlag(_Player, _Flag, _Range); + + PROC + PROC_OncePerUserAndNearbyPlayers_SetFlag((CHARACTERGUID)_Player, (STRING)_Flag, (REAL)_Range) + AND + DB_IsPlayer(_OtherPlayer) + AND + GetDistanceTo(_Player, _OtherPlayer, _Dist) + AND + _Dist < _Range + THEN + // Will also catch _Player himself + UserSetFlag(_OtherPlayer, _Flag); + //END_REGION + + //REGION Small macros + PROC + PROC_RemoveDialogFromCharacter((CHARACTERGUID)_NPC) + THEN + DialogRequestStop(_NPC); + ProcRemoveAllDialogEntriesForSpeaker(_NPC); + SetHasDialog(_Npc,0); + //END_REGION + + //REGION Counter Helper + PROC + Proc_CountHelper((STRING)_ID) + AND + NOT DB_CountHelper(_ID,_) + THEN + DB_CountHelper(_ID,0); + + PROC + Proc_CountHelper((STRING)_ID) + AND + DB_CountHelper(_ID,_OldValue) + AND + IntegerSum(_OldValue,1,_Value) + THEN + NOT DB_CountHelper(_ID,_OldValue); + DB_CountHelper(_ID,_Value); + + PROC + Proc_CharCountHelper((CHARACTERGUID)_Char,(STRING)_ID) + THEN + Proc_CharCountHelper(_Char,_ID,1); + + PROC + Proc_CharCountHelper((CHARACTERGUID)_Char,(STRING)_ID,_) + AND + NOT DB_CharCountHelper(_Char,_ID,_) + THEN + DB_CharCountHelper(_Char,_ID,0); + + PROC + Proc_CharCountHelper((CHARACTERGUID)_Char,(STRING)_ID,(INTEGER)_Count) + AND + DB_CharCountHelper(_Char,_ID,_OldValue) + AND + IntegerSum(_OldValue,_Count,_Value) + THEN + NOT DB_CharCountHelper(_Char,_ID,_OldValue); + DB_CharCountHelper(_Char,_ID,_Value); + + PROC + Proc_CharCountHelperReset((CHARACTERGUID)_Char,(STRING)_ID) + AND + DB_CharCountHelper(_Char,_ID,_Counter) + THEN + NOT DB_CharCountHelper(_Char,_ID,_Counter); + //END_REGION + + //REGION Unregister a Trigger For a User + // Note: this routines errs on the side of keeping the trigger unregistered. + // E.g., if a character is assigned to a user without other characters, triggers + // will kept be kept unregistered for that character if they had been unregistered + // before. + PROC + ProcUnregisterForUser((TRIGGERGUID)_Trigger,(CHARACTERGUID)_Player) + AND + CharacterGetReservedUserID(_Player,_UserID) + AND + DB_IsPlayer(_OtherPlayer) + AND + CharacterGetReservedUserID(_OtherPlayer,_UserID) + THEN + DB_TriggerUnregisteredForUserChar(_Trigger,_OtherPlayer); + TriggerUnregisterForCharacter(_Trigger,_OtherPlayer); + + IF + CharacterReservedUserIDChanged(_Player,_UserID) + AND + DB_IsPlayer(_Player) + AND + DB_IsPlayer(_OtherPlayer) + AND + NOT DB_UnregisterForUserIDChanged(1) + AND + _OtherPlayer != _Player + AND + CharacterGetReservedUserID(_OtherPlayer,_UserID) + THEN + DB_UnregisterForUserIDChanged(1); + // Only have to call this for one character, because this logic keeps it the + // same for all of the characters assigned to a single user + ProcUnregisterForUserIDChanged(_OtherPlayer,_Player); + + PROC + ProcUnregisterForUserIDChanged((CHARACTERGUID)_ExistingPlayer,(CHARACTERGUID)_NewPlayer) + AND + DB_TriggerUnregisteredForUserChar(_Trigger,_ExistingPlayer) + AND + NOT DB_TriggerUnregisteredForUserChar(_Trigger,_NewPlayer) + THEN + DB_TriggerUnregisteredForUserChar(_Trigger,_NewPlayer); + TriggerUnregisterForCharacter(_Trigger,_NewPlayer); + + PROC + ProcUnregisterForUserIDChanged((CHARACTERGUID)_ExistingPlayer,(CHARACTERGUID)_NewPlayer) + AND + DB_TriggerUnregisteredForUserChar(_Trigger,_NewPlayer) + AND + NOT DB_TriggerUnregisteredForUserChar(_Trigger,_ExistingPlayer) + THEN + NOT DB_TriggerUnregisteredForUserChar(_Trigger,_NewPlayer); + TriggerRegisterForCharacter(_Trigger,_NewPlayer); + + IF + CharacterReservedUserIDChanged(_Player,_UserID) + THEN + NOT DB_UnregisterForUserIDChanged(1); + + //END_REGION + + //REGION Turn Skipping + //While in DB_CharacterSkipTurn(_Char), skip turn + // + IF + ObjectFlagSet("GEN_EndTurn",_Char,_) + THEN + EndTurn(_Char); + ObjectClearFlag(_Char,"GEN_EndTurn",0); + + IF + ObjectFlagSet("GEN_SkipToTurn",_Char,_) + AND + DB_CombatObjects(_Char,_) + THEN + DB_CharacterSkipTurn(_Char); + ObjectClearFlag(_Char,"GEN_SkipToTurn",0); + + IF + ObjectTurnStarted(_Char) + AND + DB_CharacterSkipTurn(_Char) + THEN + EndTurn(_Char); + + PROC + Proc_PurgeSkipTurnDB() + AND + DB_CharacterSkipTurn(_Char) + THEN + NOT DB_CharacterSkipTurn(_Char); + + IF + ObjectTurnStarted(_Char) + AND + DB_SkipToCharactersTurn(_CharsTurn) + AND + DB_CombatObjects(_Char,_ID) + AND + DB_CombatObjects(_CharsTurn,_ID) + AND + _Char != _CharsTurn + THEN + EndTurn(_Char); + + IF + ObjectTurnStarted(_Char) + AND + DB_SkipToCharactersTurn(_Char) + THEN + NOT DB_SkipToCharactersTurn(_Char); + + IF + ObjectFlagSet("GEN_DisappearOutOfSight",(CHARACTERGUID)_Char,_) + THEN + ProcCharacterDisappearOutOfSight(_Char,0,1,"",0); + ObjectClearFlag(_Char,"GEN_DisappearOutOfSight",0); + + IF + ObjectLeftCombat((CHARACTERGUID)_Char,_) + AND + ObjectGetFlag(_Char,"GEN_DisappearOutOfSightWhenAvailable",1) + AND + QRY_SpeakerIsAvailable(_Char) + THEN + ProcCharacterDisappearOutOfSight(_Char,0,1,"",0); + ObjectClearFlag(_Char,"GEN_DisappearOutOfSightWhenAvailable",0); + + IF + DialogEnded(_,_ID) + AND + DialogGetInvolvedNPC(_ID,1,(CHARACTERGUID)_Char) + AND + ObjectGetFlag(_Char,"GEN_DisappearOutOfSightWhenAvailable",1) + AND + QRY_SpeakerIsAvailable(_Char) + THEN + ProcCharacterDisappearOutOfSight(_Char,0,1,"",0); + ObjectClearFlag(_Char,"GEN_DisappearOutOfSightWhenAvailable",0); + + + //END_REGION + + //REGION Move an item locally + //Add to an items X, Y and Z values + // + PROC + ProcItemLocalMove((ITEMGUID)_Item,(REAL)_PlusX,(REAL)_PlusY,(REAL)_PlusZ,(REAL)_Speed,(REAL)_Acceleration) + AND + GetPosition(_Item,_X,_Y,_Z) + AND + RealSum(_X,_PlusX,_TargetX) + AND + RealSum(_Y,_PlusY,_TargetY) + AND + RealSum(_Z,_PlusZ,_TargetZ) + THEN + Proc_ItemMoveToPosition(_Item,_TargetX,_TargetY,_TargetZ,_Speed,_Acceleration); + + + //END_REGION + + //REGION Force End a Dialog + //for use in behaviour scripts + IF + StoryEvent((GUIDSTRING)_Object,"ForceStopDialog") + THEN + ProcForceStopDialog(_Object); + + PROC + ProcForceStopDialog((GUIDSTRING)_Object) + THEN + DialogRequestStop(_Object); + + //END_REGION + + //REGION Generic hostile after dialog + //NPC in the dialogue will go hostile to the Player that this event is set on at the end of the dialog + IF + ObjectFlagSet("FactionHostileToIndivPlayerAfterDialog",(CHARACTERGUID)_Player,_Id) + THEN + DB_HostileToIndivPlayerAfterDialog(_Player,_Id); + + IF + DialogEnded(_,_Id) + AND + DB_HostileToIndivPlayerAfterDialog(_Player,_Id) + AND + DB_DialogNPCs(_Id,_Char,_) + THEN + ProcSetHostileToIndivPlayer((CHARACTERGUID)_Char,_Player); + ObjectClearFlag(_Player,"FactionHostileToIndivPlayerAfterDialog",_Id); + NOT DB_HostileToIndivPlayerAfterDialog(_Player,_Id); + + + //Temp Hostility + IF + ObjectFlagSet("TemporaryHostilityAfterDialog",(CHARACTERGUID)_Player,_Id) + THEN + DB_TemporaryHostilityAfterDialog(_Player,_Id); + + IF + DialogEnded(_,_Id) + AND + DB_TemporaryHostilityAfterDialog(_Player,_Id) + AND + DB_DialogNPCs(_Id,_Char,_) + THEN + ProcMakeNPCHostile((CHARACTERGUID)_Char,_Player); + ObjectClearFlag(_Player,"TemporaryHostilityAfterDialog",_Id); + NOT DB_TemporaryHostilityAfterDialog(_Player,_Id); + + //Set Attitude to -100 after dialog + IF + ObjectFlagSet("HostileAttitudeAfterDialog",(CHARACTERGUID)_Player,_Id) + THEN + DB_HostileAttitudeAfterDialog(_Player,_Id); + + IF + DialogEnded(_,_Id) + AND + DB_HostileAttitudeAfterDialog(_Player,_Id) + AND + DB_DialogNPCs(_Id,_Char,_) + THEN + CharacterAddAttitudeTowardsPlayer((CHARACTERGUID)_Char,_Player,-100); + ObjectClearFlag(_Player,"HostileAttitudeAfterDialog",_Id); + NOT DB_HostileAttitudeAfterDialog(_Player,_Id); + + + //Set Evil NPC after Dialog + IF + ObjectFlagSet("HostileAlignmentAfterDialog",(CHARACTERGUID)_Player,_Id) + THEN + DB_HostileAlignmentAfterDialog(_Player,_Id); + + IF + DialogEnded(_,_Id) + AND + DB_HostileAlignmentAfterDialog(_Player,_Id) + AND + DialogGetInvolvedNPC(_Id,1,(CHARACTERGUID)_Char) + THEN + ProcSetRelationToPlayers(_Char,0); + ObjectClearFlag(_Player,"HostileAlignmentAfterDialog",_Id); + NOT DB_HostileAlignmentAfterDialog(_Player,_Id); + + + //END_REGION + + //REGION Character Dies After Dialog Ends + + IF + ObjectFlagSet("CharacterDieAfterDialog",(CHARACTERGUID)_Player,_Id) + THEN + DB_CharacterDieAfterDialog(_Player,_Id); + + IF + DialogEnded(_,_Id) + AND + DB_CharacterDieAfterDialog(_Player,_Id) + THEN + CharacterDie(_Player,0,"DoT"); + ObjectClearFlag(_Player,"CharacterDieAfterDialog",_Id); + NOT DB_CharacterDieAfterDialog(_Player,_Id); + + + + //END_REGION + + //REGION Res, Heal, and remove statuses from a player + + PROC + Proc_CharacterFullRestore((CHARACTERGUID)_Char) + THEN + CharacterResurrect(_Char); + RemoveHarmfulStatuses(_Char); + CharacterSetHitpointsPercentage(_Char,100); + CharacterSetArmorPercentage(_Char,100); + CharacterSetMagicArmorPercentage(_Char,100); + CharacterResetCooldowns(_Char); + + + //END_REGION + + //REGION Camera Shake around Player + + PROC + Proc_ShakeCameraForTime((CHARACTERGUID)_Char,(INTEGER)_Time) + AND + GetUUID(_Char,_UUID) + AND + StringConcatenate("CameraShake_",_UUID,_ID) + THEN + PROC_LoopEffect("RS3_FX_GP_ScriptedEvent_CameraShake_Loop_00-50",_Char,_ID,"__ANY__",""); + ProcObjectTimer(_Char,"Timer_LoopCameraShakeHelper",_Time); + + PROC + ProcObjectTimerFinished(_Char,"Timer_LoopCameraShakeHelper") + AND + GetUUID(_Char,_UUID) + AND + StringConcatenate("CameraShake_",_UUID,_ID) + THEN + PROC_StopLoopEffect(_Char,_ID); + + PROC + Proc_CameraShakeAroundCharacter((GUIDSTRING)_Object,(INTEGER)_Duration,(REAL)_Radius) + AND + DB_IsPlayer(_Player) + AND + GetDistanceTo(_Player,_Object,_Dist) + AND + _Dist <= _Radius + THEN + PlayEffect(_Player,"RS3_FX_GP_Combat_CameraShake_A"); + ProcObjectTimer(_Player,"ShakeCameraOn_",200); + DB_CameraShakeAroundCharacter(_Object,_Duration,_Radius); + + + PROC + ProcObjectTimerFinished((CHARACTERGUID)_Player,"ShakeCameraOn_") + AND + DB_CameraShakeAroundCharacter(_Object,_Duration,_Radius) + AND + IntegerSubtract(_Duration,200,_Dif) + AND + _Dif >= 0 + THEN + NOT DB_CameraShakeAroundCharacter(_Object,_Duration,_Radius); + Proc_CameraShakeAroundCharacter(_Object,_Dif,_Radius); + + PROC + ProcObjectTimerFinished((CHARACTERGUID)_Player,"ShakeCameraOn_") + AND + DB_CameraShakeAroundCharacter(_Object,_Duration,_Radius) + AND + IntegerSubtract(_Duration,200,_Dif) + AND + _Dif < 0.0 + THEN + NOT DB_CameraShakeAroundCharacter(_Object,_Duration,_Radius); + + //END_REGION + + //REGION Add/Remove Source Points + IF + ObjectFlagSet("RemoveSourcePoints",(CHARACTERGUID)_Char,_) + THEN + ObjectClearFlag(_Char,"RemoveSourcePoints",0); + Proc_RemoveSourcePoints(_Char); + + IF + ObjectFlagSet("RemoveOneSourcePoint",(CHARACTERGUID)_Char,_) + THEN + ObjectClearFlag(_Char,"RemoveOneSourcePoint",0); + CharacterAddSourcePoints(_Char, -1); + + + IF + ObjectFlagSet("AddSourcePoint",(CHARACTERGUID)_Char,_) + THEN + ObjectClearFlag(_Char,"AddSourcePoint",0); + Proc_AddSourcePoint(_Char); + + IF + ObjectFlagSet("AddTwoSourcePoints",(CHARACTERGUID)_Char,_) + THEN + ObjectClearFlag(_Char,"AddTwoSourcePoints",0); + Proc_AddSourcePoint(_Char); + Proc_AddSourcePoint(_Char); + + PROC + Proc_AddSourcePoint((CHARACTERGUID)_Char) + THEN + CharacterAddSourcePoints(_Char,1); + + PROC + Proc_RemoveSourcePoints((CHARACTERGUID)_Char) + THEN + CharacterAddSourcePoints(_Char,-100); + + //END_REGION + + QRY + QRY_GLO_IsVisibleUndead((CHARACTERGUID)_Char) + AND + IsTagged(_Char, "UNDEAD", 1) + AND + IsTagged(_Char, "VEILED_UNDEAD", 0) + AND + IsTagged(_Char, "MASKED_UNDEAD", 0) + THEN + DB_NOOP(0); + + IF + StoryEvent((CHARACTERGUID)_Char,"GEN_PurgeQueue") + THEN + CharacterPurgeQueue(_Char); + ProcClearMovingFacts(_Char); + + //REGION Do Knockdown fall / getup Animation + IF + StoryEvent((CHARACTERGUID)_Char,"GEN_FallAndGetUp") + THEN + PlayAnimation(_Char,"knockdown_fall","Play_Anim_knockdown_getup"); + + IF + StoryEvent((CHARACTERGUID)_Char,"Play_Anim_knockdown_getup") + THEN + PlayAnimation(_Char,"knockdown_getup"); + + //END_REGION + + //REGION Do Knockdown fall / knockdown loop Animation + IF + StoryEvent((CHARACTERGUID)_Char,"GEN_FallAndLie") + THEN + PlayAnimation(_Char,"knockdown_fall","Play_Anim_knockdown_loop"); + + IF + StoryEvent((CHARACTERGUID)_Char,"Play_Anim_knockdown_loop") + THEN + CharacterSetAnimationOverride(_Char,"knockdown_loop"); + + //END_REGION + + //REGION Is Available to + + QRY + QRY_IsAvailableTo((CHARACTERGUID)_Char,(CHARACTERGUID)_Target) + AND + QRY_SpeakerIsAvailable(_Char) + AND + QRY_SpeakerIsAvailable(_Target) + AND + CharacterCanSee(_Char,_Target,1) + THEN + DB_NOOP(1); + + //END_REGION + + //REGION Lookat in Dialog + + IF + ObjectFlagSet("LookAtPlayer",(CHARACTERGUID)_Char,_ID) + AND + DialogGetInvolvedPlayer(_ID,1,(CHARACTERGUID)_Player) + THEN + CharacterLookAt(_Char,_Player); + ObjectClearFlag(_Char,"LookAtPlayer",0); + + //END_REGION + + //REGION MoveTo in Dialog + + IF + ObjectFlagSet("Speaker1MoveTo",(CHARACTERGUID)_Char,_ID) + AND + DialogGetInvolvedNPC(_ID,1,(CHARACTERGUID)_Speaker1) + THEN + CharacterMoveTo(_Speaker1,_Char,0,"",0); + ObjectClearFlag(_Char,"Speaker1MoveTo",0); + + IF + ObjectFlagSet("Speaker2MoveTo",(CHARACTERGUID)_Char,_ID) + AND + DialogGetInvolvedNPC(_ID,2,(CHARACTERGUID)_Speaker2) + THEN + CharacterMoveTo(_Speaker2,_Char,0,"",0); + ObjectClearFlag(_Char,"Speaker2MoveTo",0); + + IF + ObjectFlagSet("Player1MoveTo",(CHARACTERGUID)_Char,_ID) + AND + DialogGetInvolvedPlayer(_ID,1,(CHARACTERGUID)_Player) + THEN + CharacterMoveTo(_Player,_Char,0,"",0); + ObjectClearFlag(_Char,"Player1MoveTo",0); + + IF + ObjectFlagSet("Player2MoveTo",(CHARACTERGUID)_Char,_ID) + AND + DialogGetInvolvedPlayer(_ID,2,(CHARACTERGUID)_Player) + THEN + CharacterMoveTo(_Player,_Char,0,"",0); + ObjectClearFlag(_Char,"Player2MoveTo",0); + + IF + ObjectFlagSet("Speaker1RunTo",(CHARACTERGUID)_Char,_ID) + AND + DialogGetInvolvedNPC(_ID,1,(CHARACTERGUID)_Speaker1) + THEN + CharacterMoveTo(_Speaker1,_Char,1,"",0); + ObjectClearFlag(_Char,"Speaker1MoveTo",0); + + IF + ObjectFlagSet("Speaker2RunTo",(CHARACTERGUID)_Char,_ID) + AND + DialogGetInvolvedNPC(_ID,2,(CHARACTERGUID)_Speaker2) + THEN + CharacterMoveTo(_Speaker2,_Char,1,"",0); + ObjectClearFlag(_Char,"Speaker2MoveTo",0); + + IF + ObjectFlagSet("Player1RunTo",(CHARACTERGUID)_Char,_ID) + AND + DialogGetInvolvedPlayer(_ID,1,(CHARACTERGUID)_Player) + THEN + CharacterMoveTo(_Player,_Char,1,"",0); + ObjectClearFlag(_Char,"Player1MoveTo",0); + + IF + ObjectFlagSet("Player2RunTo",(CHARACTERGUID)_Char,_ID) + AND + DialogGetInvolvedPlayer(_ID,2,(CHARACTERGUID)_Player) + THEN + CharacterMoveTo(_Player,_Char,1,"",0); + ObjectClearFlag(_Char,"Player2MoveTo",0); + + //END_REGION + + //REGION Animation testing + IF + TextEventSet("AnimTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamInteger(1,0) + THEN + CharacterPurgeQueue(_Player); + + IF + TextEventSet("AnimTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamInteger(1,0) + AND + DB_AnimTestLoopingAnimation(_Player,_AnimName) + THEN + NOT DB_AnimTestLoopingAnimation(_Player,_AnimName); + + // oe animtest animation_name + IF + TextEventSet("AnimTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamString(1,_AnimName) + AND + NOT GetTextEventParamInteger(2,_) + THEN + PlayAnimation(_Player,_AnimName); + + IF + TextEventSet("AnimTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamString(1,_AnimName) + AND + GetTextEventParamInteger(2,1) + THEN + PlayAnimation(_Player,_AnimName); + + + IF + TextEventSet("AnimTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamString(1,_AnimName) + AND + GetTextEventParamInteger(2,-1) + THEN + PlayAnimation(_Player,_AnimName,"AnimTest_PlayLoopingAnim"); + DB_AnimTestLoopingAnimation(_Player,_AnimName); + + IF + StoryEvent((CHARACTERGUID)_Player,"AnimTest_PlayLoopingAnim") + AND + DB_AnimTestLoopingAnimation(_Player,_AnimName) + THEN + PlayAnimation(_Player,_AnimName,"AnimTest_PlayLoopingAnim"); + + + IF + TextEventSet("AnimTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamString(1,_AnimName) + AND + GetTextEventParamInteger(2,0) + THEN + CharacterPurgeQueue(_Player); + + + + IF + TextEventSet("AnimTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamString(1,_AnimName) + AND + GetTextEventParamInteger(2,0) + AND + DB_AnimTestLoopingAnimation(_Player,_AnimName) + THEN + NOT DB_AnimTestLoopingAnimation(_Player,_AnimName); + + + //END_REGION + + //REGION FX testing + + // oe animtest animation_name + //REGION OneShot + + IF + TextEventSet("FxTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamString(1,_FxName) + AND + GetTextEventParamInteger(2,1) + THEN + PlayEffect(_Player,_FxName); + //END_REGION + + //REGION Looping FX + IF + TextEventSet("FxTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamString(1,_FxName) + AND + GetTextEventParamInteger(2,-1) + THEN + PROC_LoopEffect(_FxName,_Player,"FxTest","__ANY__","Dummy_FX"); + + IF + TextEventSet("FxTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamString(1,_FxName) + AND + GetTextEventParamString(2,_BoneName) + AND + GetTextEventParamInteger(3,-1) + THEN + PROC_LoopEffect(_FxName,_Player,"FxTest","__ANY__",_BoneName); + + /////// 0 or STOP to stop looping + + IF + TextEventSet("FxTest") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamString(1,"Stop") + THEN + PROC_StopLoopEffect(_Player,"FxTest"); + + IF + TextEventSet("FxTestStop") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + THEN + PROC_StopLoopEffect(_Player,"FxTest"); + + //END_REGION + + //END_REGION + + //REGION AddTag OE + + IF + TextEventSet("AddTag") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + AND + GetTextEventParamString(1,_TagName) + THEN + SetTag(_Player,_TagName); + DebugText(_Player,_TagName); + + //END_REGION + + //REGION DrawWeaponforXTime + PROC + proc_DrawWeaponforXTime((CHARACTERGUID)_NPC,(INTEGER)_Time) + THEN + CharacterSetFightMode(_NPC,1,0); + ProcObjectTimer(_NPC,"GLO_DrawWeaponsForXTime",_Time); + + PROC + ProcObjectTimerFinished(_NPC,"GLO_DrawWeaponsForXTime") + AND + CharacterIsInCombat((CHARACTERGUID)_NPC,0) + THEN + CharacterSetFightMode(_NPC,0,0); + //END_REGION + + //REGION Conditional Object Flag Setter + PROC + Proc_SetConditionalObjectFlag((GUIDSTRING)_Object,(STRING)_Flag,(INTEGER)_Condition) + AND + _Condition == 0 + THEN + ObjectClearFlag(_Object,_Flag,0); + + PROC + Proc_SetConditionalObjectFlag((GUIDSTRING)_Object,(STRING)_Flag,(INTEGER)_Condition) + AND + _Condition != 0 + THEN + ObjectSetFlag(_Object,_Flag,0); + + QRY + QRY_IsEmptyDB((STRING)_DB,(INTEGER)_Size) + AND + SysCount(_DB,_Size,0) + THEN + DB_NOOP(1); + + QRY + QRY_IsInRange((GUIDSTRING)_Source,(GUIDSTRING)_Target,(REAL)_Range) + AND + GetDistanceTo(_Source,_Target,_Dist) + AND + _Dist <= _Range + THEN + DB_NOOP(1); + + QRY + Query_CharacterIsAliveAndNotInCombat((CHARACTERGUID)_Char) + AND + CharacterIsDead(_Char,0) + AND + CharacterIsInCombat(_Char,0) + THEN + DB_NOOP(1); + + //END_REGION + + //REGION Attribute checks + QRY + QRY_CheckPlayerStat((CHARACTERGUID)_Player,(STRING)_Stat,(INTEGER)_Value) + AND + CharacterGetAttribute(_Player,_Stat,_PlayerStat) + AND + _PlayerStat >= _Value + THEN + DB_NOOP(1); + + IF + DB_GLO_Attribute_Check_AgainstSpeaker((STRING)_Dialog,(INTEGER)_Index,(STRING)_Attribute,(STRING)_Difficulty,(INTEGER)_Source,(INTEGER)_Target) + THEN + PROC_Define_GLO_Attribute_Check_Internal(_Dialog,_Index,_Attribute,_Difficulty,_Source,_Target,0); + + IF + DB_GLO_Attribute_Check_AgainstLevel((STRING)_Dialog,(INTEGER)_Index,(STRING)_Attribute,(STRING)_Difficulty,(INTEGER)_Source,(INTEGER)_Level) + THEN + PROC_Define_GLO_Attribute_Check_Internal(_Dialog,_Index,_Attribute,_Difficulty,_Source,1,_Level); + + PROC + PROC_Define_GLO_Attribute_Check_Internal((STRING)_Dialog,(INTEGER)_Index,(STRING)_Attribute,(STRING)_Difficulty,(INTEGER)_Source,(INTEGER)_Target,(INTEGER)_Level) + AND + DB_GLO_Attribute_Check_Internal(_Dialog,_Index,_AnyAttribute,_AnyDifficulty,_AnySource,_AnyTarget,_AnyLevel) + THEN + NOT DB_GLO_Attribute_Check_Internal(_Dialog,_Index,_AnyAttribute,_AnyDifficulty,_AnySource,_AnyTarget,_AnyLevel); + + PROC + PROC_Define_GLO_Attribute_Check_Internal((STRING)_Dialog,(INTEGER)_Index,(STRING)_Attribute,(STRING)_Difficulty,(INTEGER)_Source,(INTEGER)_Target,(INTEGER)_Level) + THEN + DB_GLO_Attribute_Check_Internal(_Dialog,_Index,_Attribute,_Difficulty,_Source,_Target,_Level); + + PROC + Proc_DialogFlagSetup(_Dialog,_Speaker1) + AND + DB_GLO_Attribute_Check_Internal(_Dialog,_,_,_,_,_,_) + THEN + PROC_GLO_Attribute_Check_Setup(_Dialog); + + PROC + Proc_DialogFlagSetup(_Dialog,_Speaker1,_Speaker2) + AND + DB_GLO_Attribute_Check_Internal(_Dialog,_,_,_,_,_,_) + THEN + PROC_GLO_Attribute_Check_Setup(_Dialog); + + PROC + Proc_DialogFlagSetup(_Dialog,_Speaker1,_Speaker2,_Speaker3) + AND + DB_GLO_Attribute_Check_Internal(_Dialog,_,_,_,_,_,_) + THEN + PROC_GLO_Attribute_Check_Setup(_Dialog); + + PROC + Proc_DialogFlagSetup(_Dialog,_Speaker1,_Speaker2,_Speaker3,_Speaker4) + AND + DB_GLO_Attribute_Check_Internal(_Dialog,_,_,_,_,_,_) + THEN + PROC_GLO_Attribute_Check_Setup(_Dialog); + + PROC + Proc_DialogFlagSetup(_Dialog,_Speaker1,_Speaker2,_Speaker3,_Speaker4,_Speaker5) + AND + DB_GLO_Attribute_Check_Internal(_Dialog,_,_,_,_,_,_) + THEN + PROC_GLO_Attribute_Check_Setup(_Dialog); + + PROC + Proc_DialogFlagSetup(_Dialog,_Speaker1,_Speaker2,_Speaker3,_Speaker4,_Speaker5,_Speaker6) + AND + DB_GLO_Attribute_Check_Internal(_Dialog,_,_,_,_,_,_) + THEN + PROC_GLO_Attribute_Check_Setup(_Dialog); + + PROC + PROC_GLO_Attribute_Check_Setup((STRING)_Dialog) + AND + DB_GLO_Attribute_Check_Internal(_Dialog,_Index,_Attribute,_Difficulty,_Source,_Target,_Level) + AND + DB_GLO_AttributeCheck_Var(_Index,"Difficulty",_DifficultyVar) + AND + DB_GLO_AttributeCheck_Var(_Index,"LevelOverride",_LevelOverrideVar) + AND + DB_GLO_AttributeCheck_Var(_Index,"Name",_NameVar) + AND + DB_GLO_AttributeCheck_Var(_Index,"Source",_SourceVar) + AND + DB_GLO_AttributeCheck_Var(_Index,"Target",_TargetVar) + THEN + DialogSetVariableString(_Dialog,_DifficultyVar,_Difficulty); + DialogSetVariableInt(_Dialog,_LevelOverrideVar,_Level); + DialogSetVariableString(_Dialog,_NameVar,_Attribute); + DialogSetVariableInt(_Dialog,_SourceVar,_Source); + DialogSetVariableInt(_Dialog,_TargetVar,_Target); + + //END_REGION + + //REGION User Based Voice Bark + + IF + DB_OneShotUser_VoicebarkTrigger((TRIGGERGUID)_Trigger,_) + THEN + ProcTriggerRegisterForPlayers(_Trigger); + + IF + CharacterEnteredTrigger(_Player,_Trigger) + AND + DB_OneShotUser_VoicebarkTrigger((TRIGGERGUID)_Trigger,(STRING)_Bark) + AND + StringConcatenate("Commented_",_Bark,_Flag) + AND + UserGetFlag(_Player,_Flag,0) + THEN + UserSetFlag(_Player,_Flag); + StartVoiceBark(_Bark,_Player); + + //END_REGION + + PROC + Proc_TeleportSmoke((GUIDSTRING)_Object) + AND + GetPosition(_Object,_X,_Y,_Z) + THEN + PlayEffectAtPosition("RS3_FX_GP_ScriptedEvent_Teleport_GenericSmoke_01",_X,_Y,_Z); + + + //REGION + IF + DB_HideEquippedWeapon((CHARACTERGUID)_Char) + AND + CharacterGetEquippedItem(_Char,"Weapon",(ITEMGUID)_Weapon) + THEN + CharacterUnequipItem(_Char,_Weapon); + DB_HiddenEquippedWeapon(_Char,_Weapon); + + IF + DB_HideEquippedShield((CHARACTERGUID)_Char) + AND + CharacterGetEquippedItem(_Char,"Shield",(ITEMGUID)_Shield) + THEN + CharacterUnequipItem(_Char,_Shield); + DB_HideEquippedShield(_Char,_Shield); + + PROC + Proc_EquipHiddenWeapon((CHARACTERGUID)_Char) + AND + DB_HiddenEquippedWeapon(_Char,_Weapon) + THEN + CharacterEquipItem(_Char,_Weapon); + NOT DB_HiddenEquippedWeapon(_Char,_Weapon); + + PROC + Proc_EquipHiddenShield((CHARACTERGUID)_Char) + AND + DB_HideEquippedShield(_Char,_Shield) + THEN + CharacterEquipItem(_Char,_Shield); + NOT DB_HideEquippedShield(_Char,_Shield); + + //END_REGION + + //REGION Combat Cutscene - control whos turn it is + + IF + DB_CombatCutscene_PrioritizedObject(_PrioritiedObject) + THEN + JumpToTurn(_PrioritiedObject); + + PROC + Proc_CombatCutscene_PrioritizedObject_Purge() + AND + DB_CombatCutscene_PrioritizedObject(_PrioritiedObject) + THEN + NOT DB_CombatCutscene_PrioritizedObject(_PrioritiedObject); + + IF + DB_CombatCutscene_PrioritizedObject(_PrioritiedObject) + AND + DB_CombatCutscene_PrioritizedObject(_OtherObject) + AND + _OtherObject != _PrioritiedObject + THEN + NOT DB_CombatCutscene_PrioritizedObject(_OtherObject); + + IF + ObjectTurnStarted((CHARACTERGUID)_Combatant) + AND + DB_CombatCutscene_PrioritizedObject(_PrioritiedObject) + AND + ObjectIsCharacter(_PrioritiedObject,1) + AND + DB_CombatCharacters(_Combatant,_Id) + AND + _Combatant != _PrioritiedObject + AND + DB_CombatCharacters(_PrioritiedObject,_PId) + AND + _Id == _PId + THEN + JumpToTurn(_PrioritiedObject); + + IF + CharacterWentOnStage(_PrioritiedObject,0) + AND + ObjectIsCharacter(_PrioritiedObject,1) + AND + DB_CombatCutscene_PrioritizedObject(_PrioritiedObject) + THEN + NOT DB_CombatCutscene_PrioritizedObject(_PrioritiedObject); + + //END_REGION + + //REGION Remove Weapons + + PROC + Proc_RemoveWeapons((CHARACTERGUID)_Char) + AND + CharacterGetEquippedItem(_Char,"Weapon",(ITEMGUID)_Weapon) + THEN + ItemRemove(_Weapon); + + PROC + Proc_RemoveWeapons((CHARACTERGUID)_Char) + AND + CharacterGetEquippedItem(_Char,"Shield",(ITEMGUID)_Shield) + THEN + ItemRemove(_Shield); + + + + //END_REGION + + + //REGION + IF + CharacterKilledBy(_Defender,_AttackerOwner,_Attacker) + AND + DB_IsPlayer(_AttackerOwner) + AND + DB_KilledEvent(_Defender, (STRING)_Event) + THEN + UserSetFlag(_AttackerOwner,_Event,0); + + IF + CharacterDying(_Killed) + AND + DB_KilledEvent(_Killed, _Event) + AND + DB_CombatCharacters(_Killed, _ID) + AND + DB_IsPlayer(_Killer) + AND + DB_CombatCharacters(_Killer, _ID) + AND + QRY_GLO_KilledEvent_WasEnemy((CHARACTERGUID)_Killed,(CHARACTERGUID)_Killer, _ID) + THEN + UserSetFlag(_Killer, _Event, 0); + + QRY + QRY_GLO_KilledEvent_WasEnemy((CHARACTERGUID)_Killed, (CHARACTERGUID)_Killer, (INTEGER)_ID) + AND + DB_KilledEvent_HostileToTarget(_Killer, _Killed, _ID) + THEN + DB_NOOP(0); + + QRY + QRY_GLO_KilledEvent_WasEnemy((CHARACTERGUID)_Killed, (CHARACTERGUID)_Killer, (INTEGER)_ID) + AND + CharacterIsEnemy(_Killed, _Killer, 1) + THEN + DB_NOOP(0); + + IF + ObjectEnteredCombat((CHARACTERGUID)_NPC, _ID) + AND + DB_KilledEvent(_NPC, _) + AND + DB_IsPlayer(_Player) + AND + DB_CombatCharacters(_Player, _ID) + AND + CharacterIsEnemy(_Player, _NPC, 1) + THEN + DB_KilledEvent_HostileToTarget((CHARACTERGUID)_Player, (CHARACTERGUID)_NPC, _ID); + + IF + ObjectEnteredCombat((CHARACTERGUID)_Player, _ID) + AND + DB_IsPlayer(_Player) + AND + DB_KilledEvent(_NPC, _) + AND + DB_CombatCharacters(_Player, _ID) + AND + CharacterIsEnemy(_Player,(CHARACTERGUID)_NPC,1) + THEN + DB_KilledEvent_HostileToTarget((CHARACTERGUID)_Player, (CHARACTERGUID)_NPC, _ID); + + IF + CombatEnded(_ID) + AND + DB_KilledEvent_HostileToTarget(_Player, _NPC, _ID) + THEN + NOT DB_KilledEvent_HostileToTarget(_Player, _NPC, _ID); + //END_REGION + + + //REGION + //This will add characters within a trigger to the dialog + //first int, if 1, will also add character when the enter the trigger after the dialog started + + IF + DialogStarted(_Dialog,_Id) + AND + DB_AddCharactersInTriggerToDialog((STRING)_Dialog,(TRIGGERGUID)_Trigger,(INTEGER)_) + THEN + DB_AddCharactersInTriggerToDialog_ID(_Dialog,_Id); + + IF + DialogStarted(_Dialog,_Id) + AND + DB_AddCharactersInTriggerToDialog(_Dialog,_Trigger,_) + AND + DB_InRegion(_Char,_Trigger) + AND + DB_IsPlayer(_Char) + AND + QRY_SpeakerIsAvailable(_Char) + AND + DB_AddCharactersInTriggerToDialog_ID(_Dialog,_Id) + THEN + DialogAddCharacter(_Id,_Char); + + IF + CharacterEnteredTrigger(_Char,_Trigger) + AND + DB_AddCharactersInTriggerToDialog(_Dialog,_Trigger,1) + AND + DB_IsPlayer(_Char) + AND + DB_AddCharactersInTriggerToDialog_ID(_Dialog,_Id) + THEN + DialogAddCharacter(_Id,_Char); + + IF + DialogEnded(_Dialog,_Id) + AND + DB_AddCharactersInTriggerToDialog_ID(_Dialog,_Id) + THEN + NOT DB_AddCharactersInTriggerToDialog_ID(_Dialog,_Id); + //END_REGION + + //REGION Replace one-time use dialog flag into a proc call (for flags used to trigger actions) + PROC + Proc_OneTimeEventFlag((STRING)_Flag) + THEN + DB_NOOP(1); + + PROC + Proc_OneTimeEventFlag((GUIDSTRING)_Object,(STRING)_Flag) + THEN + DB_NOOP(1); + + PROC + Proc_OneTimeEventFlag((GUIDSTRING)_Object,(STRING)_Flag,(INTEGER)_DialogInst) + THEN + DB_NOOP(1); + + IF + ObjectFlagSet(_Flag,_Object,_DlgInst) + AND + DB_OneTimeEventFlag(_Flag) + THEN + ObjectClearFlag(_Object,_Flag); + Proc_OneTimeEventFlag(_Object,_Flag); + Proc_OneTimeEventFlag(_Object,_Flag,_DlgInst); + + IF + GlobalFlagSet(_Flag) + AND + DB_OneTimeEventFlag(_Flag) + THEN + GlobalClearFlag(_Flag); + Proc_OneTimeEventFlag(_Flag); + //END_REGION + + //REGION Generic Leave Through Portal (_Poof Variation) + + PROC + Proc_CreatePortalAndLeave((CHARACTERGUID)_Char,(STRING)_Event) + AND + GetPosition(_Char,_X,_Y,_Z) + AND + RealSum(_Y,1.25,_Y2) + AND + RealSum(_X,2.0,_X2) + AND + CreateItemTemplateAtPosition("Helper_Invisible_A_835c266c-2619-41a6-9591-50fc937bf97d",_X2,_Y2,_Z,(ITEMGUID)_Portal) + THEN + DB_GEN_CreatePortalAndLeave(_Char,_Portal,_Event); + CharacterLookAt(_Char,_Portal); + PlayAnimation(_Char,"cast_target_cast","GEN_CreatePortalAndLeave_CreatePortal"); + PROC_LoopEffect("RS3_FX_Skills_Voodoo_Cast_Hand_01",_Char,"GEN_CreatePortalAndLeave_Fx","__ANY__","Dummy_R_HandFX"); + PROC_LoopEffect("RS3_FX_GP_ScriptedEvent_DarkOrb_Summoning_01",_Char,"GEN_CreatePortalAndLeave_Fx","__ANY__",""); + ProcObjectTimer(_Char,"GEN_CreatePortalAndLeave_CreatePortal_Timer",1800); + + PROC + ProcObjectTimerFinished((CHARACTERGUID)_Char,"GEN_CreatePortalAndLeave_CreatePortal_Timer") + AND + GetRotation(_Char,_,_Yr,_) + AND + DB_GEN_CreatePortalAndLeave(_Char,(ITEMGUID)_Portal,_Event) + THEN + ItemRotateToAngleY(_Portal,_Yr,1000.0); + PROC_LoopEffect("RS3_FX_GP_ScriptedEvent_Portal_01",_Portal,"GEN_CreatePortalAndLeave","__ANY__",""); + + + IF + StoryEvent((CHARACTERGUID)_Char,"GEN_CreatePortalAndLeave_CreatePortal") + AND + DB_GEN_CreatePortalAndLeave(_Char,_Portal,_Event) + THEN + PROC_StopLoopEffect(_Char,"GEN_CreatePortalAndLeave_Fx"); + ProcObjectTimer(_Char,"GEN_CreatePortalAndLeave_MoveToDelay",800); + + PROC + ProcObjectTimerFinished((CHARACTERGUID)_Char,"GEN_CreatePortalAndLeave_MoveToDelay") + AND + DB_GEN_CreatePortalAndLeave(_Char,(ITEMGUID)_Portal,_Event) + THEN + CharacterMoveTo(_Char,_Portal,0,"GEN_CreatePortalAndLeave_Offstage",0); + + IF + StoryEvent((CHARACTERGUID)_Char,"GEN_CreatePortalAndLeave_Offstage") + AND + DB_GEN_CreatePortalAndLeave(_Char,(ITEMGUID)_Portal,_Event) + THEN + ProcObjectTimer(_Portal,"GEN_CreatePortalAndLeave_Offstage_PortalRemove",3500); + PROC_StopLoopEffect(_Portal,"GEN_CreatePortalAndLeave"); + SetStoryEvent(_Char,_Event); + NOT DB_GEN_CreatePortalAndLeave(_Char,_Portal,_Event); + + PROC + ProcObjectTimerFinished((ITEMGUID)_Portal,"GEN_CreatePortalAndLeave_Offstage_PortalRemove") + THEN + ItemRemove(_Portal); + + + IF + TextEventSet("GEN_CreatePortalAndLeave_Offstage") + AND + CharacterGetHostCharacter((CHARACTERGUID)_Player) + THEN + Proc_CreatePortalAndLeave(_Player,""); + + //END_REGION + + //REGION StartDialog With Visible Tagged Player + + PROC + PROC_StartDialog_WithVisibleTag((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(STRING)_Dialog,(STRING)_MainTag,(STRING)_FallBackTag,(INTEGER)_AddOtherPlayersToDialog) + AND + NOT DB_PROC_StartDialogWithVisibleTag(1) + AND + IsTagged(_Player,_MainTag,1) + AND + QRY_SpeakerIsAvailableAndInDialogRange(_NPC,_Player) + THEN + Proc_StartDialog(0,_Dialog,_NPC,_Player); + DB_PROC_StartDialogWithVisibleTag(1); + + PROC + PROC_StartDialog_WithVisibleTag((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(STRING)_Dialog,(STRING)_MainTag,(STRING)_FallBackTag,(INTEGER)_AddOtherPlayersToDialog) + AND + NOT DB_PROC_StartDialogWithVisibleTag(1) + AND + IsTagged(_Player,_MainTag,0) + AND + DB_IsPlayer(_OtherPlayers) + AND + IsTagged(_OtherPlayers,_MainTag,1) + AND + QRY_SpeakerIsAvailableAndInDialogRange(_NPC,_OtherPlayers) + THEN + Proc_StartDialog(0,_Dialog,_NPC,_OtherPlayers); + DB_PROC_StartDialogWithVisibleTag(1); + + PROC + PROC_StartDialog_WithVisibleTag((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(STRING)_Dialog,(STRING)_MainTag,(STRING)_FallBackTag,(INTEGER)_AddOtherPlayersToDialog) + AND + NOT DB_PROC_StartDialogWithVisibleTag(1) + AND + IsTagged(_Player,_FallBackTag,1) + AND + QRY_SpeakerIsAvailableAndInDialogRange(_NPC,_Player) + THEN + Proc_StartDialog(0,_Dialog,_NPC,_Player); + DB_PROC_StartDialogWithVisibleTag(1); + + PROC + PROC_StartDialog_WithVisibleTag((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(STRING)_Dialog,(STRING)_MainTag,(STRING)_FallBackTag,(INTEGER)_AddOtherPlayersToDialog) + AND + NOT DB_PROC_StartDialogWithVisibleTag(1) + AND + IsTagged(_Player,_FallBackTag,0) + AND + DB_IsPlayer(_OtherPlayers) + AND + IsTagged(_OtherPlayers,_FallBackTag,1) + AND + QRY_SpeakerIsAvailableAndInDialogRange(_NPC,_OtherPlayers) + THEN + Proc_StartDialog(0,_Dialog,_NPC,_OtherPlayers); + DB_PROC_StartDialogWithVisibleTag(1); + + PROC + PROC_StartDialog_WithVisibleTag((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(STRING)_Dialog,(STRING)_MainTag,(STRING)_FallBackTag,(INTEGER)_AddOtherPlayersToDialog) + AND + NOT DB_PROC_StartDialogWithVisibleTag(1) + AND + QRY_SpeakerIsAvailableAndInDialogRange(_NPC,_Player) + THEN + Proc_StartDialog(0,_Dialog,_NPC,_Player); + DB_PROC_StartDialogWithVisibleTag(1); + + PROC + PROC_StartDialog_WithVisibleTag((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(STRING)_Dialog,(STRING)_MainTag,(STRING)_FallBackTag,1) + AND + DB_PROC_StartDialogWithVisibleTag(1) + THEN + DB_PROC_StartDialog_WithVisibleTag_AddPlayers(_NPC,_Player,_Dialog); + + PROC + PROC_StartDialog_WithVisibleTag((CHARACTERGUID)_NPC,(CHARACTERGUID)_Player,(STRING)_Dialog,(STRING)_MainTag,(STRING)_FallBackTag,(INTEGER)_AddOtherPlayersToDialog) + AND + DB_PROC_StartDialogWithVisibleTag(1) + THEN + NOT DB_PROC_StartDialogWithVisibleTag(1); + + IF + DialogStarted(_Dialog,_ID) + AND + DB_PROC_StartDialog_WithVisibleTag_AddPlayers(_NPC,_Player,_Dialog) + AND + DB_IsPlayer(_Players) + AND + NOT DB_DialogPlayers(_ID,_Players,_) + AND + CharacterCanSee(_NPC,_Players,1) + AND + QRY_SpeakerIsAvailable(_Players) + THEN + DialogAddCharacter(_ID,_Players); + + + IF + DialogStarted(_Dialog,_ID) + AND + DB_PROC_StartDialog_WithVisibleTag_AddPlayers(_NPC,_Player,_Dialog) + THEN + NOT DB_PROC_StartDialog_WithVisibleTag_AddPlayers(_NPC,_Player,_Dialog); + + //END_REGION + + //REGION Repair / Loremaster traders + + IF + DB_LoremasterTrader((CHARACTERGUID)_Trader,(INTEGER)_Level) + THEN + CharacterAddAbility(_Trader,"Loremaster",_Level); + + IF + DB_RepairTrader((CHARACTERGUID)_Trader,(INTEGER)_Level) + THEN + CharacterAddAbility(_Trader,"Repair",_Level); + + //END_REGION + + //REGION Safe teleport for characters: teleport and flush/stop existing commands + PROC + PROC_Helper_SafeTeleportTo((CHARACTERGUID)_Char,(GUIDSTRING)_Dest) + THEN + PROC_Helper_SafeTeleportTo(_Char,_Dest,"",1); + + PROC + PROC_Helper_SafeTeleportTo((CHARACTERGUID)_Char,(GUIDSTRING)_Dest,(STRING)_Event,(INTEGER)_TeleportLinkedCharacters) + THEN + TeleportTo(_Char,_Dest,_Event,_TeleportLinkedCharacters); + CharacterFlushQueue(_Char); + LeaveCombat(_Char); + SetStoryEvent(_Char,"ClearPeaceReturn"); + // Clear ongoing animations + PlayAnimation(_Char,""); + + //END_REGION + + //REGION Teleport In/Out script helpers + + IF + StoryEvent((CHARACTERGUID)_Char,"GEN_Teleport_In") + THEN + SetOnStage(_Char,1); + PlayAnimation(_Char,"Teleport_In_01"); + + + IF + StoryEvent((CHARACTERGUID)_Char,"GEN_Teleport_Out") + THEN + PlayAnimation(_Char,"Teleport_Out_01","GEN_GoOffStage"); + + + //END_REGION + + + + //REGION Sign function + QRY + QRY_IntegerSign((INTEGER)_Value) + AND + DB_IntegerSign(_Result) + THEN + NOT DB_IntegerSign(_Result); + + QRY + QRY_IntegerSign((INTEGER)_Value) + AND + _Value < 0 + THEN + DB_IntegerSign(-1); + + QRY + QRY_IntegerSign((INTEGER)_Value) + AND + _Value == 0 + THEN + DB_IntegerSign(0); + + QRY + QRY_IntegerSign((INTEGER)_Value) + AND + _Value > 0 + THEN + DB_IntegerSign(0); + //END_REGION + + //REGION Waypoint + PROC + OpenWaypointUI((CHARACTERGUID)_Player,(STRING)_WaypointCurrent,(ITEMGUID)_Item) + THEN + OpenWaypointUI((CHARACTERGUID)_Player,_WaypointCurrent,_Item,0); + + PROC + OpenWaypointUIForFlee((CHARACTERGUID)_Player,(STRING)_WaypointCurrent,(ITEMGUID)_Item) + THEN + OpenWaypointUI((CHARACTERGUID)_Player,_WaypointCurrent,_Item,1); + //END_REGION Waypoint + + } + EXIT + { + + } +} +Goal(34).Title("_InitGoal"); +Goal(34) +{ + INIT + { + + } + KB + { + PROC + InitStory() + THEN + DB_StoryStarted(1); + GoalCompleted; + + } + EXIT + { + + } +} +Goal(35).Title("_NPC_Stats"); +Goal(35) +{ + INIT + { + + } + KB + { + + } + EXIT + { + + } +} +Goal(36).Title("_PlayerAlignments"); +Goal(36) +{ + INIT + { + + } + KB + { + PROC + ProcFixPlayerAlignments() + AND + DB_IsPlayer(_Player) + AND + NOT DB_PlayerAlignments_BlockFix(_Player) + AND + IsInArena(_Player,0) + AND + CharacterIsPlayer(_Player,1) + AND + DB_IsPlayer(_OtherPlayer) + AND + NOT DB_PlayerAlignments_BlockFix(_OtherPlayer) + AND + _Player!=_OtherPlayer + AND + IsInArena(_OtherPlayer,0) + AND + CharacterIsPlayer(_OtherPlayer,1) + AND + CharacterGetReservedUserID(_Player,_User) + AND + CharacterGetReservedUserID(_OtherPlayer,_OtherUser) + AND + GetUserProfileID(_User,_UserProfileID) + AND + GetUserProfileID(_OtherUser,_OtherUserProfileID) + THEN + ProcSetPlayerAlignment(_Player,_OtherPlayer,_UserProfileID,_OtherUserProfileID); + + PROC + ProcFixPlayerAlignments() + AND + DB_IsPlayer((CHARACTERGUID)_Player) + AND + NOT DB_PlayerAlignments_BlockFix(_Player) + AND + IsInArena(_Player,0) + AND + DB_IsPlayer((CHARACTERGUID)_OtherPlayer) + AND + NOT DB_PlayerAlignments_BlockFix(_OtherPlayer) + AND + _Player != _OtherPlayer + AND + IsInArena(_OtherPlayer,0) + AND + CharacterGetRelationToCharacter(_Player,_OtherPlayer,_Relation) + THEN + ProcLeavePartyIfRelationLow(_Player,_OtherPlayer,_Relation); + + PROC + ProcSetPlayerAlignment((CHARACTERGUID)_Player,(CHARACTERGUID)_OtherPlayer,(STRING)_User,(STRING)_OtherUser) + AND + DB_UserAlign(_User,_OtherUser,_Result) + THEN + CharacterSetRelationIndivFactionToIndivFaction(_Player,_OtherPlayer,_Result); + + PROC + ProcSetPlayerAlignment((CHARACTERGUID)_Player,(CHARACTERGUID)_OtherPlayer,(STRING)_User,(STRING)_OtherUser) + AND + NOT DB_UserAlign(_User,_OtherUser,_) + AND + CharacterIsInPartyWith(_Player,_OtherPlayer,1) + THEN + CharacterSetRelationIndivFactionToIndivFaction(_Player,_OtherPlayer,100); + + PROC + ProcSetPlayerAlignment((CHARACTERGUID)_Player,(CHARACTERGUID)_OtherPlayer,(STRING)_User,(STRING)_OtherUser) + AND + NOT DB_UserAlign(_User,_OtherUser,_) + AND + CharacterIsInPartyWith(_Player,_OtherPlayer,0) + THEN + CharacterSetRelationIndivFactionToIndivFaction(_Player,_OtherPlayer,50); + + PROC + ProcLeavePartyIfRelationLow((CHARACTERGUID)_Player,(CHARACTERGUID)_OtherPlayer,(INTEGER)_Relation) + AND + _Relation < 25 + AND + CharacterIsInPartyWith(_Player,_OtherPlayer,1) + AND + CharacterGetReservedUserID(_Player,_UserID) + AND + CharacterGetReservedUserID(_OtherPlayer,_OtherUserID) + AND + _UserID != _OtherUserID + THEN + LeaveParty(_OtherUserID); + + /*************************************************************************************** + Fix alignments when swapping characters between users or creating new players. + ****************************************************************************************/ + + IF + CharacterReservedUserIDChanged(_,_) + THEN + ProcFixPlayerAlignments(); + + IF + DB_IsPlayer(_) + THEN + ProcFixPlayerAlignments(); + + IF + GlobalFlagSet("SetupUserAlignments") + THEN + ProcFixPlayerAlignments(); + GlobalClearFlag("SetupUserAlignments"); + + IF + CharacterJoinedParty(_) + THEN + ProcFixPlayerAlignments(); + + /*************************************************************************************** + DB_UserAlign logic + ****************************************************************************************/ + + IF + GameStarted(_,_) + THEN + GlobalSetFlag("SetupUserAlignments"); + + IF + UserDisconnected(_User,_,_UserProfileID) + AND + DB_UserAlign(_UserProfileID,_OtherUser,_Result) + THEN + NOT DB_UserAlign(_UserProfileID,_OtherUser,_Result); + + IF + UserDisconnected(_User,_,_UserProfileID) + AND + DB_UserAlign(_OtherUser,_UserProfileID,_Result) + THEN + NOT DB_UserAlign(_OtherUser,_UserProfileID,_Result); + + IF + UserMakeWar(_Source,_Target,1) + AND + GetUserProfileID(_Source,_SourceProfileID) + AND + GetUserProfileID(_Target,_TargetProfileID) + THEN + ProcSetUserAlign(_SourceProfileID,_TargetProfileID,0); + ProcSetUserAlign(_TargetProfileID,_SourceProfileID,0); + ProcFixPlayerAlignments(); + + IF + UserMakeWar(_Source,_Target,0) + AND + GetUserProfileID(_Source,_SourceProfileID) + AND + GetUserProfileID(_Target,_TargetProfileID) + THEN + NOT DB_UserAlign(_SourceProfileID,_TargetProfileID,0); + NOT DB_UserAlign(_TargetProfileID,_SourceProfileID,0); + ProcFixPlayerAlignments(); + + PROC + ProcSetUserAlign((STRING)_SourceProfileID,(STRING)_TargetProfileID,(INTEGER)_NewResult) + AND + DB_UserAlign(_SourceProfileID,_TargetProfileID,_Result) + THEN + NOT DB_UserAlign(_SourceProfileID,_TargetProfileID,_Result); + + PROC + ProcSetUserAlign((STRING)_SourceProfileID,(STRING)_TargetProfileID,(INTEGER)_NewResult) + THEN + DB_UserAlign(_SourceProfileID,_TargetProfileID,_NewResult); + + /*************************************************************************************** + DB_UserAlign Debugging + ****************************************************************************************/ + + IF + TextEventSet("useralign") + AND + DB_UserAlign(_User,_OtherUser,_Result) + AND + DB_IsPlayer(_Player) + AND + StringConcatenate(_User," vs ",_Res) + AND + StringConcatenate(_Res,_OtherUser,_Res2) + AND + StringConcatenate(_Res2,": ",_Res3) + AND + IntegertoString(_Result,_IntStr) + AND + StringConcatenate(_Res3,_IntStr,_FinalResult) + THEN + DebugText(_Player,_FinalResult); + + } + EXIT + { + + } +} +Goal(37).Title("_PROC_AUDIO"); +Goal(37) +{ + INIT + { + //MoveToTrigger Audio Events + DB_MoveToTrigger_Materials("STONE"); + DB_MoveToTrigger_Materials("WOOD"); + DB_MoveToTrigger_Materials("METAL"); + + DB_CameraShakeAudioEventTrigger(800,5001); + + DB_DebugCameraShakerParser("500",500); + DB_DebugCameraShakerParser("1000",1000); + DB_DebugCameraShakerParser("3000",3000); + DB_DebugCameraShakerParser("5000",5000); + DB_DebugCameraShakerParser("8000",8000); + DB_DebugCameraShakerParser("13000",13000); + + + DB_DebugCameraShakerParser("2",2); + DB_DebugCameraShakerParser("5",5); + DB_DebugCameraShakerParser("1",1); + DB_DebugCameraShakerParser("25",25); + DB_DebugCameraShakerParser("60",60); + + } + KB + { + //REGION MoveToTrigger //Audio Play Sounds according to Material + + PROC + proc_ItemMoveToTrigger((ITEMGUID)_Item,(TRIGGERGUID)_Trigger,(REAL)_Speed,(REAL)_Acceleration,(INTEGER)_UseRotation) + THEN + ItemMoveToTrigger(_Item,_Trigger,_Speed,_Acceleration,_UseRotation); + + PROC + Proc_ItemMoveToPosition((ITEMGUID)_Item,(REAL)_X,(REAL)_Y,(REAL)_Z,(REAL)_Speed,(REAL)_Acceleration) + THEN + ItemMoveToPosition(_Item,_X,_Y,_Z,_Speed,_Acceleration); + + PROC + Proc_ItemMoveToPosition((ITEMGUID)_Item,(REAL)_PlusX,(REAL)_PlusY,(REAL)_PlusZ,(REAL)_Speed,(REAL)_Acceleration) + AND + NOT DB_MovingItem(_Item,_) + AND + DB_MoveToTrigger_Materials(_Tag) + AND + IsTagged(_Item,_Tag,1) + AND + StringConcatenate("Items_Puzzles_MovingObjects_",_Tag,_SoundEventPre) + AND + StringConcatenate(_SoundEventPre,"_Start",_SoundEvent) + THEN + DB_MovingItem(_Item,_Tag); + PlaySound(_Item,_SoundEvent); + DebugText(_Item,"PlayEvent_Move_Start"); + + + PROC + proc_ItemMoveToTrigger((ITEMGUID)_Item,(TRIGGERGUID)_Trigger,(REAL)_Speed,(REAL)_Acceleration,(INTEGER)_UseRotation) + AND + NOT DB_MovingItem(_Item,_) + AND + DB_MoveToTrigger_Materials(_Tag) + AND + IsTagged(_Item,_Tag,1) + AND + StringConcatenate("Items_Puzzles_MovingObjects_",_Tag,_SoundEventPre) + AND + StringConcatenate(_SoundEventPre,"_Start",_SoundEvent) + THEN + DB_MovingItem(_Item,_Tag); + PlaySound(_Item,_SoundEvent); + DebugText(_Item,"PlayEvent_Move_Start"); + + + IF + StoryEvent(_Item,"GEN_ItemMoved") + AND + NOT DB_MovingItem((ITEMGUID)_Item,_) + AND + DB_MoveToTrigger_Materials(_Tag) + AND + IsTagged(_Item,_Tag,1) + AND + StringConcatenate("Items_Puzzles_MovingObjects_",_Tag,_SoundEventPre) + AND + StringConcatenate(_SoundEventPre,"_Start",_SoundEvent) + THEN + DB_MovingItem(_Item,_Tag); + PlaySound(_Item,_SoundEvent); + DebugText(_Item,"PlayEvent_Move_Start"); + + + IF + ItemMoved(_Item) + AND + DB_MovingItem(_Item,_Tag) + AND + StringConcatenate("Items_Puzzles_MovingObjects_",_Tag,_SoundEventPre) + AND + StringConcatenate(_SoundEventPre,"_Stop",_SoundEvent) + THEN + NOT DB_MovingItem(_Item,_Tag); + PlaySound(_Item,_SoundEvent); + DebugText(_Item,"PlayEvent_Move_END"); + //END_REGION + + //REGION ScreenShake Audio Logic + + PROC + ProcObjectTimer(_Char,"Timer_LoopCameraShakeHelper",_Time) + AND + DB_CameraShakeAudioEventTrigger(_MinDuration,_) + AND + _Time > _MinDuration + THEN + PlaySound(_Char,"SE_GP_ScriptedEvent_CameraShake_Earth"); + + PROC + ProcObjectTimer(_Char,"Timer_LoopCameraShakeHelper",_Time) + AND + DB_CameraShakeAudioEventTrigger(_MinDuration,_MaxDurationToCallStop) + AND + _Time > _MinDuration + AND + _Time < _MaxDurationToCallStop + THEN + DB_Timer_LoopCameraShakeHelper_StopSound(_Char); + + PROC + ProcObjectTimerFinished(_Char,"Timer_LoopCameraShakeHelper") + AND + DB_Timer_LoopCameraShakeHelper_StopSound(_Char) + THEN + NOT DB_Timer_LoopCameraShakeHelper_StopSound(_Char); + PlaySound(_Char,"SE_GP_ScriptedEvent_CameraShake_Earth_Stop"); + + + IF + TextEventSet("TestCameraShakeAudio") + AND + GetTextEventParamString(1,_TimeString) + AND + DB_DebugCameraShakerParser(_TimeString,_TimerInt) + AND + DB_IsPlayer(_Player) + THEN + Proc_ShakeCameraForTime((CHARACTERGUID)_Player,_TimerInt); + + + IF + TextEventSet("TestCameraShake_AroundChar_Audio") + AND + GetTextEventParamString(1,_TimeString) + AND + DB_DebugCameraShakerParser(_TimeString,_TimerInt) + AND + DB_IsPlayer(_Player) + THEN + Proc_CameraShakeAroundCharacter(_Player,_TimerInt,6.0); + //END_REGION + + } + EXIT + { + + } +} +Goal(38).Title("_Sandbox"); +Goal(38) +{ + INIT + { + DB_Dialogs(CHARACTERGUID_Sandbox_Ship_Captain_dc36935c-4452-47af-8bab-f34c48754e13, CHARACTERGUID_Sandbox_Ship_Elisabeth_Fendrish_a7b94f10-865f-4ffd-8770-fce3973366ff, "Sandbox_Quest"); + + DB_QuestDef_State("SandboxQuest","Accept", 1); + DB_QuestDef_State("SandboxQuest","GoBack"); + DB_QuestDef_State("SandboxQuest","Finish", -1); + + ProcTriggerRegisterForPlayers(TRIGGERGUID_CaveQuestTrigger_fb308de8-145b-4749-8b92-db51ea2bc019); + + DB_QuestDef_QuestReward("SandboxQuest","Finish","QuestUpdate_SandboxQuest_Finish"); + + } + KB + { + IF + CharacterEnteredTrigger(_Player, TRIGGERGUID_CaveQuestTrigger_fb308de8-145b-4749-8b92-db51ea2bc019) + THEN + ObjectSetFlag(_Player, "QuestUpdate_SandboxQuest_GoBack"); + + } + EXIT + { + + } +} +Goal(39).Title("_Shroud"); +Goal(39) +{ + INIT + { + + } + KB + { + PROC + ProcDisableShroud() + AND + NOT DB_ShroudDisabled(1) + THEN + DB_ShroudDisabled(1); + ShroudRender(0); + + PROC + ProcEnableShroud() + AND + DB_ShroudDisabled(1) + THEN + NOT DB_ShroudDisabled(1); + ShroudRender(1); + + } + EXIT + { + + } +} +Goal(40).Title("_Story Npcs"); +Goal(40) +{ + INIT + { + + } + KB + { + PROC + SetStoryNpc((CHARACTERGUID)_Npc,(INTEGER)_State) + THEN + CharacterMakeStoryNpc(_Npc,_State); + + PROC + SetStoryNpc((CHARACTERGUID)_Npc,0) + THEN + NOT DB_IsStoryNpc(_Npc); + + PROC + SetStoryNpc((CHARACTERGUID)_Npc,1) + THEN + DB_IsStoryNpc(_Npc); + + PROC + MakeAttackable((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + THEN + SetStoryNpc(_Npc,0); + CharacterSetTemporaryHostileRelation(_Npc,_Player); + CharacterAddAttitudeTowardsPlayer(_Npc,_Player,-100); + + // Default arg: + PROC + SetStoryNpc((CHARACTERGUID)_Npc) + THEN + SetStoryNpc(_Npc,1); + + PROC + SetStoryNpcStatus((CHARACTERGUID)_Npc) + AND + DB_IsStoryNpc(_Npc) + THEN + CharacterMakeStoryNpc(_Npc,1); + + PROC + SetStoryNpcStatus((CHARACTERGUID)_Npc) + AND + NOT DB_IsStoryNpc(_Npc) + THEN + CharacterMakeStoryNpc(_Npc,0); + + } + EXIT + { + + } +} +Goal(41).Title("_Trade"); +Goal(41) +{ + INIT + { + DB_DoubleAttitudePrice(1, 2); + DB_DoubleAttitudePrice(2, 2); + DB_DoubleAttitudePrice(3, 3); + DB_DoubleAttitudePrice(4, 3); + DB_DoubleAttitudePrice(5, 4); + DB_DoubleAttitudePrice(6, 5); + DB_DoubleAttitudePrice(7, 6); + DB_DoubleAttitudePrice(8, 7); + DB_DoubleAttitudePrice(9, 12); + DB_DoubleAttitudePrice(10, 15); + DB_DoubleAttitudePrice(11, 20); + DB_DoubleAttitudePrice(12, 25); + DB_DoubleAttitudePrice(13, 30); + DB_DoubleAttitudePrice(14, 35); + DB_DoubleAttitudePrice(15, 40); + DB_DoubleAttitudePrice(16, 60); + DB_DoubleAttitudePrice(17, 65); + DB_DoubleAttitudePrice(18, 75); + DB_DoubleAttitudePrice(19, 85); + DB_DoubleAttitudePrice(20, 95); + DB_DoubleAttitudePriceOverTwenty(100); + + } + KB + { + //REGION Creating and resetting TraderTreasure + PROC + GenTradeItems((CHARACTERGUID)_Player,(CHARACTERGUID)_Trader) + AND + NOT DB_TraderGeneratedTreasureForLevel(_Trader,_) + THEN + DB_TraderGeneratedTreasureForLevel(_Trader,0); + + PROC + GenTradeItems((CHARACTERGUID)_Player,(CHARACTERGUID)_Trader) + AND + DB_TraderGeneratedTreasureForLevel(_Trader,_OldLevel) + AND + CharacterGetLevel(_Player,_NewLevel) + AND + _NewLevel > _OldLevel + THEN + NOT DB_TraderGeneratedTreasureForLevel(_Trader,_OldLevel); + DB_TraderGeneratedTreasureForLevel(_Trader,_NewLevel); + DoGenTradeItems(_Player,_Trader); + + PROC + ProcClearTradeFacts((CHARACTERGUID)_Trader) + AND + DB_TraderGeneratedTreasureForLevel(_Trader,_OldLevel) + THEN + NOT DB_TraderGeneratedTreasureForLevel(_Trader,_OldLevel); + + PROC + GenTradeItems((CHARACTERGUID)_Player,(CHARACTERGUID)_Trader) + AND + DB_LastTradeItemGeneration(_Trader,(INTEGER)_THLastGen) + AND + _THLastGen != 0 + AND // check if last generation was long enough ago: + DB_Time(_,_,_TH) + AND + IntegerSubtract(_TH,_THLastGen,_Delta) + AND + _Delta >= 12 + THEN + DoGenTradeItems(_Player,_Trader); + + // If not yet an inventory generated for this npc, do it: + PROC + GenTradeItems((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_LastTradeItemGeneration(_Npc,0) // not yet generated + THEN + DoGenTradeItems(_Player,_Npc); + + // + PROC + DoGenTradeItems((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_LastTradeItemGeneration(_Npc,_THLastGen) + THEN + NOT DB_LastTradeItemGeneration(_Npc,_THLastGen); + + // + PROC + DoGenTradeItems((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_Time(_,_,_TH) + THEN + ProcGenerateTradeTreasure(_Player,_Npc); + DB_LastTradeItemGeneration(_Npc,_TH); + + PROC + ProcClearGeneratedItems((CHARACTERGUID)_Npc) + AND + NOT DB_ItemsCleared(_Npc) + THEN + DB_ItemsCleared(_Npc); + CharacterClearTradeGeneratedItems(_Npc); + + IF + DB_CustomTradeTreasure(_Npc,_Treasure) + THEN + ProcClearLastTradeTime(_Npc); + + PROC + ProcClearLastTradeTime((CHARACTERGUID)_Trader) + AND + DB_LastTradeItemGeneration(_Trader,(INTEGER)_THLastGen) + THEN + NOT DB_LastTradeItemGeneration(_Trader,_THLastGen); + DB_LastTradeItemGeneration(_Trader,0); + + PROC + ProcGenerateTradeTreasure((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_CustomTradeTreasure((CHARACTERGUID)_Npc,(STRING)_Treasure) + THEN + ProcClearGeneratedItems(_Npc); + DB_CharacterGenerateCustomTradeTreasure(_Player,_Npc,_Treasure); + DB_TreasureGenerated(1); + + PROC + ProcGenerateTradeTreasure((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + NOT DB_TreasureGenerated(1) + THEN + GenerateItems(_Player,_Npc); + + PROC + ProcGenerateTradeTreasure((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + THEN + NOT DB_TreasureGenerated(1); + NOT DB_ItemsCleared(_Npc); + //END_REGION + + //REGION Start Trade + // + // StartTrade: set all facts and startup the trade window: + // + PROC + StartTrade((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + THEN + GenTradeItems(_Player,_Npc); // regenerate items (clear if _Npc.DB_IsHostile()) + ResetInsults(_Player,_Npc); + + PROC + StartTrade((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + THEN + DoStartTrade_1(_Player,_Npc); + + PROC + DoStartTrade_1((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_NoRepair(_Npc) + AND + DB_NoIdentify(_Npc) + THEN + ActivateTrade(_Player,_Npc,0,0,1); + + PROC + DoStartTrade_1((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + NOT DB_NoRepair(_Npc) + AND + DB_NoIdentify(_Npc) + THEN + ActivateTrade(_Player,_Npc,1,0,1); + + PROC + DoStartTrade_1((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_NoRepair(_Npc) + AND + NOT DB_NoIdentify(_Npc) + THEN + ActivateTrade(_Player,_Npc,0,1,1); + + PROC + DoStartTrade_1((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + NOT DB_NoRepair(_Npc) + AND + NOT DB_NoIdentify(_Npc) + THEN + ActivateTrade(_Player,_Npc,1,1,1); + + IF + RequestTrade(_Player,_Npc) + THEN + StartTrade(_Player,_Npc); + + PROC + ResetInsults((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + DB_InsultCounter(_Player, _Npc, _Counter) + THEN + NOT DB_InsultCounter(_Player, _Npc, _Counter); + DB_InsultCounter(_Player, _Npc, 0); + + PROC + ResetInsults((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc) + AND + NOT DB_InsultCounter(_Player, _Npc, _) + THEN + DB_InsultCounter(_Player, _Npc, 0); + + //END_REGION + + //REGION Finish trade and adjust attitude if necessary + IF + HappyWithDeal(_Player,_Npc,_ValuePlayer,_ValueNpc) + AND + QRY_GetAttitudeChangeForTrade(_Player,_Npc,_ValuePlayer,_ValueNpc) + AND + DB_AttitudeAdjustMent(_Player,_Npc,_Att) + AND + _Att != 0 + THEN + CharacterAddAttitudeTowardsPlayer(_Npc,_Player,_Att); + + IF + HappyWithDeal(_Player,_Npc,_ValuePlayer,_ValueNpc) + AND + _ValuePlayer >= _ValueNpc + AND + DB_AttitudeAdjustMent(_Player,_Npc,_Att) + THEN + ExecuteDeal(_Player,1,_Att); + + IF + HappyWithDeal(_Player,_Npc,_ValuePlayer,_ValueNpc) + AND + _ValuePlayer < _ValueNpc + AND + DB_AttitudeAdjustMent(_Player,_Npc,_Att) + AND + DB_InsultCounter(_Player,_Npc,_Counter) + AND + IntegerSum(_Counter,1,_NewCounter) + THEN + ExecuteDeal(_Player,0,_Att); + NOT DB_InsultCounter(_Player,_Npc,_Counter); + DB_InsultCounter(_Player,_Npc,_NewCounter); + + QRY + QRY_GetAttitudeChangeForTrade((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc,(INTEGER)_ValuePlayer,(INTEGER)_ValueNpc) + AND + NOT DB_TempTradeBalance(_Player,_Npc,_) + THEN + DB_TempTradeBalance(_Player,_Npc,0); + + QRY + QRY_GetAttitudeChangeForTrade((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc,(INTEGER)_ValuePlayer,(INTEGER)_ValueNpc) + AND + DB_AttitudeAdjustMent(_Player,_Npc,_Att) + THEN + NOT DB_AttitudeAdjustMent(_Player,_Npc,_Att); + + QRY + QRY_GetAttitudeChangeForTrade((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc,(INTEGER)_ValuePlayer,(INTEGER)_ValueNpc) + AND + IntegerSubtract(_ValuePlayer,_ValueNPC,_Delta) + AND + DB_TempTradeBalance(_Player,_Npc,_OldBalance) + AND + IntegerSum(_Delta,_OldBalance,_NewBalance) + AND + CharacterGetLevel(_Npc,_NpcLevel) + AND + _NpcLevel <= 20 + AND + DB_DoubleAttitudePrice(_NpcLevel,_DoublePrice)// Working with doubles to allow us to work with halves in integer envirnoment + AND + IntegerSum(_NewBalance,_NewBalance,_DoubleBalance) + AND + IntegerDivide(_DoubleBalance,_DoublePrice,_Q) // 1 Attitude point costs (L+1)/2 + AND + IntegerProduct(_Q,_DoublePrice,_DoubleSubtracted) + AND + IntegerSum(_DoubleSubtracted,1,_DoubleSubtractedIncremented) + AND + IntegerDivide(_DoubleSubtractedIncremented,2,_TotalSubtracted) + AND + IntegerSubtract(_NewBalance,_TotalSubtracted,_Remainder) + THEN + NOT DB_TempTradeBalance(_Player,_Npc,_OldBalance); + DB_TempTradeBalance(_Player,_Npc,_Remainder); + DB_AttitudeAdjustMent(_Player,_Npc,_Q); + + QRY + QRY_GetAttitudeChangeForTrade((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc,(INTEGER)_ValuePlayer,(INTEGER)_ValueNpc) + AND + IntegerSubtract(_ValuePlayer,_ValueNPC,_Delta) + AND + DB_TempTradeBalance(_Player,_Npc,_OldBalance) + AND + IntegerSum(_Delta,_OldBalance,_NewBalance) + AND + CharacterGetLevel(_Npc,_NpcLevel) + AND + _NpcLevel > 20 + AND + DB_DoubleAttitudePriceOverTwenty(_DoublePrice)// Working with doubles to allow us to work with halves in integer envirnoment + AND + IntegerSum(_NewBalance,_NewBalance,_DoubleBalance) + AND + IntegerDivide(_DoubleBalance,_DoublePrice,_Q) // 1 Attitude point costs (L+1)/2 + AND + IntegerProduct(_Q,_DoublePrice,_DoubleSubtracted) + AND + IntegerSum(_DoubleSubtracted,1,_DoubleSubtractedIncremented) + AND + IntegerDivide(_DoubleSubtractedIncremented,2,_TotalSubtracted) + AND + IntegerSubtract(_NewBalance,_TotalSubtracted,_Remainder) + THEN + NOT DB_TempTradeBalance(_Player,_Npc,_OldBalance); + DB_TempTradeBalance(_Player,_Npc,_Remainder); + DB_AttitudeAdjustMent(_Player,_Npc,_Q); + + + IF + DB_AttitudeAdjustMent(_Player,_Npc,_Q) + AND + _Q < 0 + AND + DB_InsultCounter(_Player, _Npc, _InsultCount) + AND + _InsultCount < 2 // Player can insult trader with the offer 2 times before Attitude reduction kicks in + AND + IntegerSum(_InsultCount, 1, _NewInsultCount) + THEN + NOT DB_AttitudeAdjustMent(_Player,_Npc,_Q); + DB_AttitudeAdjustMent(_Player,_Npc,0); + + IF + DB_AttitudeAdjustMent(_Player,_Npc,_Q) + AND + _Q < 0 + AND + DB_InsultCounter(_Player, _Npc, _InsultCount) + AND + _InsultCount >= 2 + AND + _Q != -15 + AND + CharacterGetAttitudeTowardsPlayer(_Npc,_Player,_OldAtt) + AND + IntegerSum(_OldAtt,_Q,_NewAtt) + AND + _NewAtt != -45 + THEN + NOT DB_AttitudeAdjustMent(_Player,_Npc,_Q); + DB_AttitudeAdjustMent(_Player,_Npc,-15); + + QRY + QRY_GetAttitudeChangeForTrade((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc,(INTEGER)_ValuePlayer,(INTEGER)_ValueNpc) + AND + CharacterGetAttitudeTowardsPlayer(_Npc,_Player,_OldAtt) + AND + DB_AttitudeAdjustMent(_Player,_Npc,_OldDelta) + AND + IntegerSum(_OldAtt,_OldDelta,_NewAtt) + AND + _NewAtt < -45 + AND + IntegerSubtract(-45,_OldAtt,_NewDelta) + THEN + NOT DB_AttitudeAdjustMent(_Player,_Npc,_OldDelta); + DB_AttitudeAdjustMent(_Player,_Npc,_NewDelta); + //END_REGION + + //Start Trade via Event (instead of button click in dialog) + IF + ObjectFlagSet("StartTrade",(CHARACTERGUID)_Player,_Instance) + AND + DB_DialogNPCs(_Instance,_Npc,1) + THEN + StartTrade((CHARACTERGUID)_Player,(CHARACTERGUID)_Npc); + ObjectClearFlag(_Player,"StartTrade",_Instance); + + //REGION Manual Trade Toggling Per Player + + PROC + Proc_DialogFlagSetup(_,(GUIDSTRING)_NPC,(GUIDSTRING)_Player) + AND + DB_ManualTradeNPC(_NPC) + AND + DB_PreventTradeBetween(_NPC,_Player) + THEN + CharacterSetCanTrade((CHARACTERGUID)_NPC,0); + + PROC + Proc_DialogFlagSetup(_,(GUIDSTRING)_NPC,(GUIDSTRING)_Player) + AND + IsTagged(_NPC,"GHOST",1) + THEN + CharacterSetCanTrade((CHARACTERGUID)_NPC,0); + + IF + ObjectFlagSet("PreventTradeWithPlayer",(GUIDSTRING)_NPC,_ID) + AND + DialogGetInvolvedPlayer(_ID,1,(CHARACTERGUID)_Player) + THEN + DB_ManualTradeNPC(_NPC); + DB_PreventTradeBetween(_NPC,_Player); + ObjectClearFlag(_NPC,"PreventTradeWithPlayer",_ID); + + PROC + Proc_DialogFlagSetup(_,(GUIDSTRING)_NPC,(GUIDSTRING)_Player) + AND + DB_ManualTradeNPC(_NPC) + AND + NOT DB_PreventTradeBetween(_NPC,_Player) + THEN + CharacterSetCanTrade((CHARACTERGUID)_NPC,1); + //END_REGION + + } + EXIT + { + + } +} +Goal(42).Title("_TrapReactions"); +Goal(42) +{ + INIT + { + DB_Event2DisplayText("HiddenPerceptionReveal","GEN_AD_HiddenPerceptionReveal"); + DB_Event2DisplayText("HiddenTrapReveal","GEN_AD_HiddenTrapReveal"); + DB_Event2DisplayText("FakePerceptionReveal","GEN_AD_FakePerceptionReveal"); + DB_Event2DisplayText("AmbushReveal","GLO_AD_AmbushDetected"); + + } + KB + { + IF + StoryEvent((CHARACTERGUID)_Player,_Event) + AND + NOT DB_BlockTextSpam(_Player) + AND + _Player.DB_IsPlayer() + AND + DB_CustomEvent2DisplayText((CHARACTERGUID)_Player,(STRING)_Event,(STRING)_Text) + AND + QRY_SpeakerIsAvailable(_Player) + THEN + Proc_StartDialog(1,_Text, _Player); + DB_BlockTextSpam(_Player); + ProcObjectTimer(_Player,"BlockTextSpam",5000); + + IF + StoryEvent((CHARACTERGUID)_Player,_Event) + AND + NOT DB_BlockTextSpam(_Player) + AND + _Player.DB_IsPlayer() + AND + DB_Event2DisplayText(_Event,_Text) + AND + QRY_SpeakerIsAvailable(_Player) + THEN + Proc_StartDialog(1,_Text, _Player); + DB_BlockTextSpam(_Player); + ProcObjectTimer(_Player,"BlockTextSpam",5000); + + PROC + ProcObjectTimerFinished(_Player,"BlockTextSpam") + THEN + NOT DB_BlockTextSpam((CHARACTERGUID)_Player); + + + + } + EXIT + { + + } +} +Goal(43).Title("_Waypoints"); +Goal(43) +{ + INIT + { + + } + KB + { + IF + CharacterTeleportToWaypoint(_Char,_Trigger) + AND + GetPosition(_Trigger,_X,_Y,_Z) + THEN + TeleportToPosition(_Char,_X,_Y,_Z,"",1,1); + + IF + CharacterTeleportToFleeWaypoint(_Char,_Trigger) + AND + GetPosition(_Trigger,_X,_Y,_Z) + THEN + TeleportToPosition(_Char,_X,_Y,_Z,"",0,1); + + IF + DB_WaypointInfo(_Item,_Trigger,_CurrentWP) + THEN + RegisterWaypoint(_CurrentWP,_Item); + + IF + CharacterItemEvent(_Player,(ITEMGUID)_Item,"WaypointDiscovered") + AND + DB_WaypointInfo(_Item,_,_) + THEN + ProcDoWaypointUnlock(_Item, _Player); + + IF + CharacterItemEvent(_, (ITEMGUID)_Item,"WaypointDiscovered") + THEN + ShowNotification("GLO_WaypointDiscovered"); + + IF + CharacterUsedItem(_Player,_Item) + AND + DB_WaypointInfo(_Item,_Trigger,_CurrentWP) + AND + NOT DB_BlockWaypointUsage(_Player) + THEN + ProcDoWaypointUnlock(_Item,_Player); + + //Check for UI blocker + IF + CharacterUsedItem(_Player,_Item) + AND + DB_WaypointInfo(_Item,_Trigger,_CurrentWP) + AND + NOT DB_BlockWaypointUsage(_Player) + AND + NOT DB_WaypointBlockUI(_Item) + AND + NOT DB_Dialogs(_Item,_) + AND + NOT DB_IsSign(_Item,(STRING)_,(STRING)_) + THEN + OpenWaypointUI(_Player,_CurrentWP,_Item); + + IF + TextEventSet("wp") + THEN + PROC_UnlockAllWP(); + ProcTestOpenWaypointUI(); + + PROC + ProcTestOpenWaypointUI() + AND + _Player.DB_IsPlayer() + AND + NOT DB_OnlyOnce("openedWPUI") + THEN + DB_OnlyOnce("openedWPUI"); + OpenWaypointUI(_Player,"",NULL_00000000-0000-0000-0000-000000000000); + + + PROC + ProcTestOpenWaypointUI() + THEN + NOT DB_OnlyOnce("openedWPUI"); + + PROC + PROC_UnlockAllWP() + AND + DB_WaypointInfo(_,_Trigger,_CurrentWP) + THEN + UnlockWaypoint(_CurrentWP,_Trigger,NULL_00000000-0000-0000-0000-000000000000); + + PROC + ProcDoWaypointUnlock((ITEMGUID)_Item,(CHARACTERGUID)_Player) + AND + DB_WaypointInfo(_Item,_Trigger,_CurrentWP) + THEN + UnlockWaypoint(_CurrentWP,_Trigger,_Player); + + PROC + ProcDoWaypointUnlock(_,_) + AND + DB_IsPlayer(_OtherPlayer) + AND + NOT DB_NumUnlockedWaypoints(_OtherPlayer,_) + THEN + DB_NumUnlockedWaypoints(_OtherPlayer,0); + + PROC + ProcDoWaypointUnlock((ITEMGUID)_Item,(CHARACTERGUID)_Player) + AND + DB_IsPlayer(_OtherPlayer) + AND + NOT DB_UnlockedWaypoint(_Item,_OtherPlayer) + AND + CharacterIsInPartyWith(_OtherPlayer,_Player,1) + AND + DB_NumUnlockedWaypoints(_OtherPlayer,_OldCount) + AND + IntegerSum(_OldCount,1,_NewCount) + THEN + DB_UnlockedWaypoint(_Item,_OtherPlayer); + NOT DB_NumUnlockedWaypoints(_OtherPlayer,_OldCount); + DB_NumUnlockedWaypoints(_OtherPlayer,_NewCount); + + + IF + ObjectFlagSet("OpenWaypointUI",_Player,_ID) + AND + DB_DialogNPCs(_ID,_Item,1) + AND + DB_WaypointInfo((ITEMGUID)_Item,_Trigger,_CurrentWP) + THEN + OpenWaypointUI((CHARACTERGUID)_Player,_CurrentWP,_Item); + ObjectClearFlag(_Player,"OpenWaypointUI",_ID); + PROC_CheckPlayTut(_Player,"TUT_Waypoint"); + + } + EXIT + { + + } +} +Goal(44).Title("GLO_BidirShovelTunnel"); +Goal(44) +{ + INIT + { + // Support for a bidirectional tunnel that can be opened up from either side by shovelling + // Usage: + // DB_BidirShovelPileTunnel(IDString,Side1ShovelTrigger,Side1ShovelPileObject,Side1TunnelEntranceObject,Side2ShovelTrigger,Side2ShovelPileObject,Side2TunnelEntranceObject); + // + // As soon as one side is opened up, so is the other side. Can't easily use simply two shovel + // piles with the same ID, because then the dirt pile on the other side won't be removed. Also + // avoids conflicts in case people shovel on both sides at the same time. + // + // When the tunnel is opened on side 1/2, ProcBidirShovelTunnelOpenedOnSide(1/2) is called + // (only one of these will be called per tunnel) + + } + KB + { + //REGION Convert tunnel into two shovel areas + IF + DB_BidirShovelPileTunnel((STRING)_IDString,(TRIGGERGUID)_Side1ShovelTrigger,(ITEMGUID)_Side1ShovelPileObject,(ITEMGUID)_Side1TunnelEntranceObject,(TRIGGERGUID)_Side2ShovelTrigger,(ITEMGUID)_Side2ShovelPileObject,(ITEMGUID)_Side2TunnelEntranceObject) + AND + StringConcatenate(_IDString,"___side1",_Side1IDString) + AND + StringConcatenate(_IDString,"___side2",_Side2IDString) + THEN + DB_BidirShovelTunnelExit(_IDString,_Side1IDString); + DB_BidirShovelTunnelExit(_IDString,_Side2IDString); + DB_ShovelArea((TRIGGERGUID)_Side1ShovelTrigger,(STRING)_Side1IDString,(ITEMGUID)_Side1ShovelPileObject); + DB_ShovelArea((TRIGGERGUID)_Side2ShovelTrigger,(STRING)_Side2IDString,(ITEMGUID)_Side2ShovelPileObject); + DB_ShovelRewardItemSpawn((STRING)_Side1IDString,(ITEMGUID)_Side1TunnelEntranceObject); + DB_ShovelRewardItemSpawn((STRING)_Side2IDString,(ITEMGUID)_Side2TunnelEntranceObject); + //END_REGION + + //REGION User hooks + PROC + ProcBidirShovelTunnelOpenedOnSide((CHARACTERGUID)_,(STRING)_,(INTEGER)_) + THEN + DB_NOOP(1); + + PROC + ProcShovelRewards(_Player,_ThisSideIDString) + AND + DB_BidirShovelTunnelExit(_IDString,_ThisSideIDString) + AND + StringContains(_ThisSideIDString,"__side1",1) + THEN + ProcBidirShovelTunnelOpenedOnSide(_Player,_IDString,1); + + PROC + ProcShovelRewards(_Player,_ThisSideIDString) + AND + DB_BidirShovelTunnelExit(_IDString,_ThisSideIDString) + AND + StringContains(_ThisSideIDString,"__side2",1) + THEN + ProcBidirShovelTunnelOpenedOnSide(_Player,_IDString,2); + //END_REGION + + //REGION If one side is opened up, open the other one too + PROC + PROC_ShovelTunnelOpenUpOtherSide((CHARACTERGUID)_Player, (STRING)_IDString) + AND + DB_BidirShovelTunnelExit(_IDString,_OtherSideIDString) + AND + DB_ShovelArea(_OtherTrigger,_OtherSideIDString,_OtherPileObject) + AND + // avoid issues if someone is digging up the other side at the same time + NOT DB_Shovelling_Mound(_,_OtherPileObject) + THEN + NOT DB_BidirShovelTunnelExit(_IDString,_OtherSideIDString); + SetOnStage(_OtherPileObject,0); + NOT DB_ShovelArea(_OtherTrigger,_OtherSideIDString,_OtherPileObject); + // Won't trigger code below again, because all DB_BidirShovelTunnelExit() for this _IDString have been cleared + ProcShovelRewards(_Player,_OtherSideIDString); + + PROC + ProcShovelRewards(_Player,_ThisSideIDString) + AND + DB_BidirShovelTunnelExit(_IDString,_ThisSideIDString) + AND + DB_BidirShovelPileTunnel(_IDString,_Side1ShovelTrigger,_Side1ShovelPileObject,_Side1TunnelEntranceObject,_Side2ShovelTrigger,_Side2ShovelPileObject,_Side2TunnelEntranceObject) + THEN + NOT DB_BidirShovelTunnelExit(_IDString,_ThisSideIDString); + // Only DB_BidirShovelTunnelExit(_IDString,_) definition left now is for the other side + PROC_ShovelTunnelOpenUpOtherSide(_Player,_IDString); + NOT DB_BidirShovelPileTunnel(_IDString,_Side1ShovelTrigger,_Side1ShovelPileObject,_Side1TunnelEntranceObject,_Side2ShovelTrigger,_Side2ShovelPileObject,_Side2TunnelEntranceObject); + + //END_REGION + + } + EXIT + { + + } +} +Goal(45).Title("GLO_Resting"); +Goal(45) +{ + INIT + { + DB_RestTemplates("FUR_Humans_Camping_Sleepingbag_B_4d7216c9-c21e-4ab0-b98e-97d744798912","STORY_PartyRest",10.0,17.0); + + } + KB + { + IF + CharacterUsedItemTemplate(_Character,_Temp,_) + AND + DB_RestTemplates(_Temp,_Consume,_PartyRadius,_SafeRadius) + THEN + UserRest(_Character,_Consume,_PartyRadius,_SafeRadius); + + } + EXIT + { + + } +} +Goal(46).Title("GLO_SavegamePatchHelpers"); +Goal(46) +{ + INIT + { + + } + KB + { + QRY + QRY_VersionIsOlderThan((INTEGER)_Major,(INTEGER)_Minor,(INTEGER)_Rev,(INTEGER)_Build,(INTEGER)_CompMajor,(INTEGER)_CompMinor,(INTEGER)_CompRev,(INTEGER)_CompBuild) + AND + _Major < _CompMajor + THEN + DB_Noop(1); + + QRY + QRY_VersionIsOlderThan((INTEGER)_Major,(INTEGER)_Minor,(INTEGER)_Rev,(INTEGER)_Build,(INTEGER)_CompMajor,(INTEGER)_CompMinor,(INTEGER)_CompRev,(INTEGER)_CompBuild) + AND + _Major == _CompMajor + AND + _Minor < _CompMinor + THEN + DB_Noop(1); + + QRY + QRY_VersionIsOlderThan((INTEGER)_Major,(INTEGER)_Minor,(INTEGER)_Rev,(INTEGER)_Build,(INTEGER)_CompMajor,(INTEGER)_CompMinor,(INTEGER)_CompRev,(INTEGER)_CompBuild) + AND + _Major == _CompMajor + AND + _Minor == _CompMinor + AND + _Rev < _CompRev + THEN + DB_Noop(1); + + QRY + QRY_VersionIsOlderThan((INTEGER)_Major,(INTEGER)_Minor,(INTEGER)_Rev,(INTEGER)_Build,(INTEGER)_CompMajor,(INTEGER)_CompMinor,(INTEGER)_CompRev,(INTEGER)_CompBuild) + AND + _Major == _CompMajor + AND + _Minor == _CompMinor + AND + _Rev == _CompRev + AND + _Build < _CompBuild + THEN + DB_Noop(1); + + } + EXIT + { + + } +} +Goal(47).Title("QRY_Characters"); +Goal(47) +{ + INIT + { + + } + KB + { + QRY + QRY_SpeakerBlockedBycombat((GUIDSTRING)_Char,(INTEGER)_Ignore) + AND + ObjectIsCharacter(_Char,1) + AND + _Ignore == 0 + AND + CharacterIsInCombat((CHARACTERGUID)_Char,1) + THEN + DB_NOOP(1); + + QRY + QRY_SpeakerIsAvailable((GUIDSTRING)_Item) + AND + ObjectExists(_Item,1) + AND + ObjectIsItem(_Item,1) + AND + QRY_SpeakerIsAvailable(_Item,0) + THEN + DB_NOOP(1); + + QRY + QRY_SpeakerIsAvailable((GUIDSTRING)_Char) + AND + ObjectIsCharacter(_Char,1) + AND + QRY_SpeakerIsAvailable((GUIDSTRING)_Char, 0) + THEN + DB_NOOP(1); + + QRY + QRY_SpeakerIsDead((GUIDSTRING)_Char) + AND + ObjectIsCharacter(_Char,1) + AND + CharacterIsDeadOrFeign((CHARACTERGUID)_Char,1) + THEN + DB_NOOP(1); + + QRY + QRY_SpeakerIsDead((GUIDSTRING)_Item) + AND + ObjectIsItem(_Item,1) + AND + ItemIsDestroyed((ITEMGUID)_Item,1) + THEN + DB_NOOP(1); + + QRY + QRY_HasInteractionDisabled((GUIDSTRING)_Char) + AND + ObjectIsCharacter(_Char,1) + AND + CharacterIsPolymorphInteractionDisabled((CHARACTERGUID)_Char,1) + THEN + DB_NOOP(1); + + QRY + QRY_SpeakerIsAvailable((GUIDSTRING)_Char, (INTEGER)_IgnoreCombat) + AND + NOT QRY_SpeakerIsDead(_Char) + AND + IsSpeakerReserved(_Char,0) + AND + NOT QRY_HasInteractionDisabled(_Char) + AND + NOT QRY_SpeakerBlockedBycombat(_Char,_IgnoreCombat) + THEN + DB_NOOP(1); + + QRY + QRY_SpeakerIsAvailable(NULL_00000000-0000-0000-0000-000000000000) + THEN + DB_NOOP(1); + + QRY + QRY_CharacterIsNotDisabled((CHARACTERGUID)_Character) + AND + HasActiveStatus(_Character,"FROZEN",0) + AND + HasActiveStatus(_Character,"STUNNED",0) + AND + HasActiveStatus(_Character,"FEAR",0) + AND + HasActiveStatus(_Character,"PETRIFIED",0) + AND + HasActiveStatus(_Character,"KNOCKED_DOWN",0) + THEN + DB_NOOP(1); + + QRY + QRY_SpeakerIsAvailableForCombat((CHARACTERGUID)_Char) + AND + CharacterIsDeadOrFeign(_Char,0) + AND + IsSpeakerReserved(_Char,0) + THEN + DB_NOOP(1); + + + QRY + QRY_SpeakerIsAvailableAndInDialogRange((CHARACTERGUID)_Char,(CHARACTERGUID)_SourceCharacter) + AND + CharacterIsDeadOrFeign(_Char,0) + AND + IsSpeakerReserved(_Char,0) + AND + CharacterIsInCombat(_Char,0) + AND + GetDistanceTo(_Char,_SourceCharacter,_Distance) + AND + _Distance < 10.0 + THEN + DB_NOOP(1); + + QRY + Query_IsPlayerHiding((CHARACTERGUID)_Char) + AND + HasActiveStatus(_Char,"SNEAKING",1) + THEN + DB_NOOP(1); + + QRY + Query_IsPlayerHiding((CHARACTERGUID)_Char) + AND + HasActiveStatus(_Char,"INVISIBLE",1) + THEN + DB_NOOP(1); + + QRY + QRY_CharacterIsNull((CHARACTERGUID)_Char) + AND + _Char == NULL_00000000-0000-0000-0000-000000000000 + THEN + DB_NOOP(1); + + } + EXIT + { + + } +} +Goal(48).Title("Sandbox"); +Goal(48) +{ + INIT + { + DB_CheckLevelStart("_TMPL_Sandbox"); + + } + KB + { + IF + RegionStarted("_TMPL_Sandbox") + THEN + GoalCompleted; + + IF + DB_CheckLevelStart("_TMPL_Sandbox") + AND + DB_CurrentLevel("_TMPL_Sandbox") + THEN + GoalCompleted; + + } + EXIT + { + NOT DB_CheckLevelStart("_TMPL_Sandbox"); + + } +} +Goal(49).Title("ZZZ_LastGoal"); +Goal(49) +{ + INIT + { + + } + KB + { + PROC + ProcClearAutomatedDialog((INTEGER)_Inst) + THEN + ProcClearDialogPlayers(_Inst); + ProcClearDialogNPCs(_Inst); + ProcClearDialogCounts(_Inst); + NOT DB_AutomatedDialog(_Inst); + + IF + VoiceBarkEnded(_,_Inst) + THEN + NOT DB_AutomatedDialogIsVB(_Inst); + ProcClearAutomatedDialog(_Inst); + + IF + AutomatedDialogEnded(_,_Inst) + AND + NOT DB_AutomatedDialogIsVB(_Inst) + THEN + ProcClearAutomatedDialog(_Inst); + + IF + AutomatedDialogEnded(_Dialog,_Inst) + THEN + NOT DB_DialogName(_Dialog,_Inst); + + IF + DialogEnded(_Dialog,_Inst) + THEN + ProcClearDialogPlayers(_Inst); + ProcClearDialogNPCs(_Inst); + ProcClearDialogCounts(_Inst); + NOT DB_DialogName(_Dialog,_Inst); + NOT DB_MarkedForDelete(_Inst); + + IF + DialogActorLeft(_Dialog,_Inst,_Actor) + AND + DB_DialogPlayers(_Inst,_Actor,_Index) + THEN + NOT DB_DialogPlayers(_Inst,_Actor,_Index); + ProcClearPlayerIfNotInOtherDialog(_Inst,_Actor); + + IF + DialogActorLeft(_Dialog,_Inst,_Actor) + AND + DB_DialogNPCs(_Inst,_Actor,_Index) + THEN + NOT DB_DialogNPCs(_Inst,_Actor,_Index); + ProcClearNPCIfNotInOtherDialog(_Inst,_Actor); + + IF + DialogActorLeft(_Dialog,_Inst,_Actor) + THEN + ProcSetNumberOfInvolvedActors(_Inst); + + PROC + ProcClearDialogPlayers((INTEGER)_Inst) + AND + DB_DialogPlayers(_Inst,_Player,_Index) + THEN + NOT DB_DialogPlayers(_Inst,_Player,_Index); + + PROC + ProcClearDialogNPCs((INTEGER)_Inst) + AND + DB_DialogNPCs(_Inst,_Player,_Index) + THEN + NOT DB_DialogNPCs(_Inst,_Player,_Index); + + PROC + ProcClearDialogCounts((INTEGER)_Inst) + AND + DB_DialogNumPlayers(_Inst,_NumPlayers) + AND + DB_DialogNumNPCs(_Inst,_NumNPCs) + THEN + NOT DB_DialogNumPlayers(_Inst,_NumPlayers); + NOT DB_DialogNumNPCs(_Inst,_NumNPCs); + + IF + CharacterCreationFinished(_) + THEN + NOT DB_InCharacterCreation(1); + NotifyCharacterCreationFinished(); + + } + EXIT + { + + } +} +Goal(10).SubGoal(2); +Goal(10).SubGoal(4); +Goal(10).SubGoal(8); +Goal(10).SubGoal(9); +Goal(10).SubGoal(14); +Goal(10).SubGoal(15); +Goal(10).SubGoal(19); +Goal(10).SubGoal(29); +Goal(10).SubGoal(30); +Goal(10).SubGoal(37); +Goal(10).SubGoal(39); +Goal(10).SubGoal(43); +Goal(10).SubGoal(48); +Goal(2).SubGoals(AND); +Goal(4).SubGoals(AND); +Goal(8).SubGoals(AND); +Goal(9).SubGoals(AND); +Goal(14).SubGoals(AND); +Goal(15).SubGoals(AND); +Goal(19).SubGoals(AND); +Goal(29).SubGoals(AND); +Goal(30).SubGoals(AND); +Goal(37).SubGoals(AND); +Goal(39).SubGoals(AND); +Goal(43).SubGoals(AND); +Goal(48).SubGoals(AND); +Goal(48).SubGoal(38); +Goal(38).SubGoals(AND); + diff --git a/test/fixtures/object.lsf b/test/fixtures/object.lsf new file mode 100644 index 0000000000000000000000000000000000000000..f6cbede6823dd164daf54e32a5c0166d756a9e86 GIT binary patch literal 2126 zcmdT_%}*0i5TB<|z7;PL4}NgqxXCWvZnqbZZ_x?`+Jam*kM^x8wB2TRA?d{!<5f=> zJsHEri~b2F-b_4s@(&=!goFAg=*(=31PW>-CT;?6elx%My_vVOuj!@v>9asjhw-_M z4fqf(a7{$UWMd`7=9vcJghfC%WTY=EDpY=Om?)qVZp&I;mN!*1CZG-GkWZN6880Y> zC9m3y|II3(1C|PYsTLk7rIoCJE=a2_Rc_YPibOsEG3w)%sz(d~y|CzolImXAlp*z$ zt=IN@JWl7&{Q}ytBUwIHno65rTUUkfs5q6GRh3#9?ky$JOcV*yzF_!rA^%ld&?r#EzHz+;UeY<+^1z!Id^1zBHK1K0B_t=a#|OCy}i%}$=Q zpMV~i!B01ux8M52PLiV-pFm?oPem}2z~DhdxZE{U0-SS)cH8#yfDe5r572nV|Y8{-()Ced=eI@dmUZ?n8Tz z@st?A#)$ugG4_Z1pGSKLc>oc=AFW}=Q{pMw#J3n<78j9E*hZ|Yq#LKrN*EX zstQ<%HR&dGL$ln3u9*p$(xi!&Z7VyehEoN*5XZXSjsn=@XyEf=ELxlY?~fi5e)Mg( z{nPedYI}L?-NW4Ah_3XwOcvsrk&uRFDjoN5m8-caWfu+HAz{T~%5~}IfL`$8Qrwwd zab~f;z*$zZ=2Zh{QdZ<$z8sy5R|>qUGry($vaCD0;iR|9x&b$&Uo3dOny;4YJV`n< K?$kN2s^AB0)Fs{k literal 0 HcmV?d00001 diff --git a/test/fixtures/simple.txt b/test/fixtures/simple.txt new file mode 100644 index 0000000..87e6826 --- /dev/null +++ b/test/fixtures/simple.txt @@ -0,0 +1,40 @@ +Version 1 +SubGoalCombiner SGC_AND +INITSECTION + DB_MY_Test((TRIGGERGUID)TRIGGERGUID_S_MY_TriggerName_000_f2b9bdc9-0369-4cc3-81ed-ad85e2c423b2, "Test"); +KBSECTION + IF + RegionStarted("MyRegion") + THEN + GoalCompleted; + + PROC + Proc_My_TestProc((INTEGER)_Value) + AND + DB_MY_TestValue((INTEGER)_OldValue) + AND + _OldValue < _Value + THEN + NOT DB_MY_TestValue(_OldValue); + + PROC + Proc_My_TestProc((INTEGER)_Value) + THEN + DB_MY_TestValue(_Value); + + QRY + Qry_My_HasTestValue() + AND + DB_MY_TestValue((INTEGER)_Value) + THEN + DB_NOOP(1); + + QRY + Qry_My_IsTestValue((INTEGER)_Value) + AND + DB_MY_TestValue(_Value) + THEN + DB_NOOP(1); +EXITSECTION +ENDEXITSECTION +ParentTargetEdge "__Start" diff --git a/test/lsf-parser.js b/test/lsf-parser.js new file mode 100644 index 0000000..51db59c --- /dev/null +++ b/test/lsf-parser.js @@ -0,0 +1,12 @@ +const assert = require("assert"); +const fs = require("fs"); + +const { default: LSFReader } = require("../lib/server/parsers/lsf/Parser"); + +describe("LSF parser", function() { + it("reads a lsf file", function() { + const buffer = fs.readFileSync("test/fixtures/object.lsf"); + const parser = new LSFReader(); + parser.read(buffer); + }); +}); diff --git a/test/story-parser.js b/test/story-parser.js new file mode 100644 index 0000000..a073dd6 --- /dev/null +++ b/test/story-parser.js @@ -0,0 +1,38 @@ +const assert = require("assert"); +const fs = require("fs"); + +const { + default: HeaderParser +} = require("../lib/server/parsers/story/HeaderParser"); + +const { + default: GoalParser +} = require("../lib/server/parsers/story/GoalParser"); + +function load(filename) { + return fs.readFileSync("test/fixtures/" + filename, "utf-8"); +} + +function saveJson(filename, data) { + fs.writeFileSync("test/fixtures/" + filename, JSON.stringify(data, null, 2), { + encoding: "utf-8" + }); +} + +describe("Story parser", function() { + it("creates tokens from script files", function() { + const parser = new GoalParser(load("simple.txt")); + const nodes = parser.tokenize(); + // saveJson("simple-tokens.json", nodes); + }); + it("parses simple sory script", function() { + const parser = new GoalParser(load("simple.txt")); + const nodes = parser.parse(); + // saveJson("simple-nodes.json", nodes); + }); + it("parses stroy div", function() { + const parser = new HeaderParser(load("headers.div")); + const nodes = parser.parse(); + // saveJson("headers.json", nodes); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..688584c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "lib": ["es6"], + "module": "commonjs", + "outDir": "lib", + "rootDir": "src", + "sourceMap": true, + "strict": true, + "target": "es6" + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/tsconfig.publish.json b/tsconfig.publish.json new file mode 100644 index 0000000..55590b1 --- /dev/null +++ b/tsconfig.publish.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "sourceMap": false + } +}

SFtlZ4yD#?^cHEO9QoRSu>-!mxrlr<&OYeGpjmYwF(YXz4qRASeb z8%dJu{A~ke#dGFri z-D`Nf4qK(%2W(Ga$e<6I)YPOD!Q^25xr>6L(A;H@ z)`!`3gMRwtg{F1U{>ZT&F|XOVS$O&VQoNaA(;%+7BN3kECk^$+J^OLTWpLEb4S}uu zMV!t@rtiK3?ORt5DeWH<4*r#&g;;FdHdqITfTZ^AJ?_*NR1}9GAAy|>E!<|DD*F(N z_MIj7)J75|`!Gd;-I-+E2AWH|2(I?sv8L2ImT0>uB7wbuMci5*X1i$U_Py?h)M}AQ z+t>^K{Z?$eDrpDX_=UFpdhWCeWfa@QPX2>RExdB==<4L=@dIYB=P?tM`qUwXL-zFN z@o!4?;6F>_hurPY6OPgK8Al37{ASRL^&%}w6*UMZEN@Iz%;;CBt%Y2DaW105EsaE^TLQQmI zg_Yu&-rCDz%VcAf$HbY@>&sFPN>fd!;`vvC*X3cQrn;1gb4!8OmFeiFhGNAF8~xYS z<;kX|=7|djuh+G0l;)Np#Y^Y(*Y#ti=C-AYOZWEIjqB*kxsr9kiI1ej25J5&CbtxKk~IJd^*Tz25dnQCo+> z(n>e+>2LeA%B`c?lQ+rjZwIU~t>acow|~~&4tb|qCp{)_vtHkhL{ZzOLzV9G2;Prn zl-p)gChv*_-cM9w+UARu?#uMwPj#l+7MmyUtGwRNOipz{hdfiylV0H49MsNZY2}yMbnsn?a_1=8mx zI~UEHcDGD-%gH(9QP(lRX8FyX;mjddVImVSms6 z>>-A|e2?<`K!_v(xKQ>$Y?k=Ln9qHn%hW-$Uz?+N=Zuom_9m;=1hBS~!dMmcBCl2i z5|87-NetJ2iNCg@7R;SiE9uLttqGR#B11}{{)@+78NwZfkK!WJNOa?<4TgIo%l4)P z=|R_qA@Y->LrC^h)yah`QKDhy%al;7#c8N_?E2P~NP={0BQti%aZe})+1MleEP+~h zbIVy=b!v$(oMef}N*uxC`OtuCpgBaz-%R$goH z#;v&H;BmTSZ1tcnb;itGpT(WAw6*PCtrON1?_1PiM zG@{!5Q@^Cja$p89#4+^9ez7OAp!k#+lGCeNF*W3&2!q57iv)s%PljNbm!y}8tXKv9em2a z_tP)I4>VRih%p%b{%>1)eQ(^R^>tTOVwrzmoFa5>U4!kKymzZ^^cig1C|#+OVytxY zB%jX4X}O|l#;0eUDk@W&_jk>8GwoZKTDEQBv((MH>~`zwwN=3L7ytESCI2?Kamg%v z+g{z&wAIl~AGU30`l(ycdOP~jt7|*9yXxgmm5zS4>)OuMt$JBYqoZDRUE4MPs9yTk z*^%#}uI--8s-JT7cEl&GYkS&V^%Jj3M|}Hrb#Ha6e%#aO@L#8{?#n-_AN_T9*uPm< z_b0O&M6lioWy-#KAl%g;R8%IE&HCy=?^c5#)tC@2?yHCFj~e)!&I#tbedVw*tD%qU zogksrSB|K=8hVDx1c@?=R>Snl_a;|_eACbauJQIh_7 z!ozRVr0Hj#s9FC!8PK=JlGjD6p?WB&WV4YBufKhFUh zV$1#izOt74bq&-I6FmR-9sf3^dyt0Mi)P^U&7e^*MU=*rrKP2nl@)LZ%+b-&#l;2K zr1J6c0gitG+f&swpvF`~WBtTQ6DCcbG-b+^*>h%(Hl{{LwT8{8)@WmDv@tc>m>O+N PjW(tRcvNdhHm0lrKd{JD literal 0 HcmV?d00001 diff --git a/resources/features/document-structure.gif b/resources/features/document-structure.gif new file mode 100644 index 0000000000000000000000000000000000000000..7223a511237c6f24ee1551c1b6de42d848c3e70e GIT binary patch literal 43574 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 SjoZavyiH>qxXmgc0028kTH!MQ literal 0 HcmV?d00001 diff --git a/resources/features/find-references.gif b/resources/features/find-references.gif new file mode 100644 index 0000000000000000000000000000000000000000..b0b88c033b3c1ba4adbf8a1c0ac73100ba37960f GIT binary patch literal 122177 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