#include "EventHandlerSetScopeSequences.h" #include #include #include #include "Generic/GenericStringPropertySequence.h" #include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h" #include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.h" #include "Parsing/Menu/Matcher/MenuExpressionMatchers.h" #include "Parsing/Menu/Matcher/MenuMatcherFactory.h" #include "Parsing/Menu/Matcher/MenuMatcherScriptInt.h" #include "Parsing/Menu/Matcher/MenuMatcherScriptNumeric.h" using namespace menu; namespace menu { enum class ExpectedScriptToken { NUMERIC, INT, TEXT }; class ScriptMatcherFactory final : public MenuMatcherFactory { public: explicit ScriptMatcherFactory(const IMatcherForLabelSupplier* labelSupplier) : MenuMatcherFactory(labelSupplier) { } _NODISCARD MatcherFactoryWrapper ScriptStrictNumeric() const { return And({ MatcherFactoryWrapper(std::make_unique()).Transform([](const token_list_t& tokens)-> SimpleParserValue { const auto& firstToken = tokens[0].get(); if (firstToken.m_type == SimpleParserValueType::INTEGER) return SimpleParserValue::String(firstToken.GetPos(), new std::string(std::to_string(firstToken.IntegerValue()))); if (firstToken.m_type == SimpleParserValueType::FLOATING_POINT) { std::ostringstream ss; ss << std::noshowpoint << firstToken.FloatingPointValue(); return SimpleParserValue::String(firstToken.GetPos(), new std::string(ss.str())); } return SimpleParserValue::String(firstToken.GetPos(), new std::string(firstToken.StringValue())); }) }); } _NODISCARD MatcherFactoryWrapper ScriptNumeric() const { return Or({ ScriptStrictNumeric(), Or({ Type(SimpleParserValueType::CHARACTER), Type(SimpleParserValueType::STRING), Type(SimpleParserValueType::IDENTIFIER), }).Transform([](const token_list_t& tokens) -> SimpleParserValue { return SimpleParserValue::Integer(tokens[0].get().GetPos(), static_cast(ExpectedScriptToken::NUMERIC)); }) }); } _NODISCARD MatcherFactoryWrapper ScriptStrictInt() const { return And({ MatcherFactoryWrapper(std::make_unique()).Transform([](const token_list_t& tokens)-> SimpleParserValue { const auto& firstToken = tokens[0].get(); if (firstToken.m_type == SimpleParserValueType::INTEGER) return SimpleParserValue::String(firstToken.GetPos(), new std::string(std::to_string(firstToken.IntegerValue()))); return SimpleParserValue::String(firstToken.GetPos(), new std::string(firstToken.StringValue())); }) }); } _NODISCARD MatcherFactoryWrapper ScriptChar(const char c) const { return Or({ Char(c), Or({ Type(SimpleParserValueType::INTEGER), Type(SimpleParserValueType::FLOATING_POINT), Type(SimpleParserValueType::STRING), Type(SimpleParserValueType::IDENTIFIER), }).Transform([](const token_list_t& tokens) -> SimpleParserValue { return SimpleParserValue::Integer(tokens[0].get().GetPos(), static_cast(ExpectedScriptToken::INT)); }) }); } _NODISCARD MatcherFactoryWrapper ScriptInt() const { return Or({ ScriptStrictInt(), Or({ Type(SimpleParserValueType::CHARACTER), Type(SimpleParserValueType::FLOATING_POINT), Type(SimpleParserValueType::STRING), Type(SimpleParserValueType::IDENTIFIER), }).Transform([](const token_list_t& tokens) -> SimpleParserValue { return SimpleParserValue::Integer(tokens[0].get().GetPos(), static_cast(ExpectedScriptToken::INT)); }) }); } _NODISCARD MatcherFactoryWrapper ScriptText() const { return Or({ Type(SimpleParserValueType::STRING), Type(SimpleParserValueType::IDENTIFIER), Or({ Type(SimpleParserValueType::CHARACTER), Type(SimpleParserValueType::FLOATING_POINT), Type(SimpleParserValueType::INTEGER), }).Transform([](const token_list_t& tokens) -> SimpleParserValue { return SimpleParserValue::Integer(tokens[0].get().GetPos(), static_cast(ExpectedScriptToken::TEXT)); }) }); } _NODISCARD MatcherFactoryWrapper ScriptKeyword(std::string keyword) const { return KeywordIgnoreCase(std::move(keyword)); } _NODISCARD MatcherFactoryWrapper ScriptColor() const { return And({ ScriptStrictNumeric(), Optional(ScriptStrictNumeric()), Optional(ScriptStrictNumeric()), Optional(ScriptStrictNumeric()) }); } }; } namespace menu::event_handler_set_scope_sequences { class SequenceCloseBlock final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_TOKEN = 1; public: SequenceCloseBlock() { const MenuMatcherFactory create(this); AddMatchers({ create.Char('}') }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { auto remainingScript = state->m_current_script.str(); if (!remainingScript.empty()) state->m_current_nested_event_handler_set->m_elements.emplace_back(std::make_unique(std::move(remainingScript))); state->m_current_script.str(std::string()); bool conditionWasAutoSkip; do { conditionWasAutoSkip = false; if (!state->m_condition_stack.empty()) { conditionWasAutoSkip = state->m_condition_stack.top().m_auto_skip; state->m_condition_stack.pop(); if (!state->m_condition_stack.empty()) { const auto& newConditionState = state->m_condition_stack.top(); if (newConditionState.m_in_condition_elements) state->m_current_nested_event_handler_set = newConditionState.m_condition->m_condition_elements.get(); else state->m_current_nested_event_handler_set = newConditionState.m_condition->m_else_elements.get(); } else state->m_current_nested_event_handler_set = state->m_current_event_handler_set; } else { state->m_current_event_handler_set = nullptr; state->m_current_nested_event_handler_set = nullptr; } } while (conditionWasAutoSkip); } }; class SequenceSkipEmptyStatements final : public MenuFileParser::sequence_t { public: SequenceSkipEmptyStatements() { const MenuMatcherFactory create(this); AddMatchers({ create.Char(';') }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { if (!state->m_current_script_statement_terminated) { state->m_current_script << "; "; state->m_current_script_statement_terminated = true; } } }; class SequenceSkipScriptToken final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_SCRIPT_TOKEN = 1; public: SequenceSkipScriptToken() { const ScriptMatcherFactory create(this); AddMatchers({ create.Or({ create.Text(), create.Numeric() }).Capture(CAPTURE_SCRIPT_TOKEN) }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { const auto& capture = result.NextCapture(CAPTURE_SCRIPT_TOKEN); switch (capture.m_type) { case SimpleParserValueType::STRING: state->m_current_script << "\"" << capture.StringValue() << "\" "; break; case SimpleParserValueType::IDENTIFIER: state->m_current_script << "\"" << capture.IdentifierValue() << "\" "; break; case SimpleParserValueType::INTEGER: state->m_current_script << "\"" << capture.IntegerValue() << "\" "; break; case SimpleParserValueType::FLOATING_POINT: state->m_current_script << "\"" << capture.FloatingPointValue() << "\" "; break; default: throw ParsingException(capture.GetPos(), "Invalid script token type for skipping"); } state->m_current_script_statement_terminated = false; } }; class SequenceGenericScriptStatement : public MenuFileParser::sequence_t { protected: static constexpr auto CAPTURE_SCRIPT_TOKEN = 1; SequenceGenericScriptStatement() = default; public: explicit SequenceGenericScriptStatement(std::initializer_list>>> matchers) { const MenuMatcherFactory create(this); AddMatchers({ create.And(matchers).Capture(CAPTURE_SCRIPT_TOKEN), create.Optional(create.Char(';')) }); } static std::unique_ptr Create(std::initializer_list>>> matchers) { return std::make_unique(matchers); } private: static std::string ScriptTokenTypeToString(int tokenType) { switch (static_cast(tokenType)) { case ExpectedScriptToken::INT: return "INT"; case ExpectedScriptToken::NUMERIC: return "NUMERIC"; case ExpectedScriptToken::TEXT: return "TEXT"; default: return "UNKNOWN"; } } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { while (result.HasNextCapture(CAPTURE_SCRIPT_TOKEN)) { const auto& capture = result.NextCapture(CAPTURE_SCRIPT_TOKEN); if (capture.m_type == SimpleParserValueType::IDENTIFIER) { state->m_current_script << "\"" << capture.IdentifierValue() << "\" "; } else if (capture.m_type == SimpleParserValueType::STRING) { state->m_current_script << "\"" << capture.StringValue() << "\" "; } else if (capture.m_type == SimpleParserValueType::CHARACTER) { state->m_current_script << capture.CharacterValue() << " "; } else if (capture.m_type == SimpleParserValueType::INTEGER) { std::ostringstream ss; ss << "Invalid script token. Expected " << ScriptTokenTypeToString(capture.IntegerValue()) << "."; throw ParsingException(capture.GetPos(), ss.str()); } else throw ParsingException(capture.GetPos(), "Invalid script capture"); } state->m_current_script << "; "; } }; class SequenceUiScriptStatement final : public SequenceGenericScriptStatement { public: explicit SequenceUiScriptStatement(std::initializer_list>>> matchers) : SequenceGenericScriptStatement() { const ScriptMatcherFactory create(this); AddMatchers({ create.And({ create.ScriptKeyword("uiScript"), create.And(matchers) }).Capture(CAPTURE_SCRIPT_TOKEN), create.Optional(create.Char(';')) }); } static std::unique_ptr Create(std::initializer_list>>> matchers) { return std::make_unique(matchers); } }; class AbstractSequenceWithPlayerData : public SequenceGenericScriptStatement { protected: static constexpr auto LABEL_PLAYER_DATA_PATH_ELEMENT = 1; static std::unique_ptr PlayerDataPathMatchers(const ScriptMatcherFactory& create) { return create.Or({ create.ScriptKeyword("false"), create.ScriptKeyword("true"), create.And({ create.Or({ create.ScriptKeyword("localvarstring"), create.ScriptKeyword("localvarint"), create.ScriptKeyword("localvarbool"), }), create.ScriptChar('('), create.ScriptText(), create.ScriptChar(')'), }), create.ScriptStrictInt(), create.ScriptText() }); } }; class SequenceSetPlayerData final : public AbstractSequenceWithPlayerData { public: explicit SequenceSetPlayerData() { const ScriptMatcherFactory create(this); AddLabeledMatchers(PlayerDataPathMatchers(create), LABEL_PLAYER_DATA_PATH_ELEMENT); AddMatchers({ create.And({ create.ScriptKeyword("setPlayerData"), create.ScriptChar('('), create.Label(LABEL_PLAYER_DATA_PATH_ELEMENT), create.Loop(create.And({ create.ScriptChar(','), create.Label(LABEL_PLAYER_DATA_PATH_ELEMENT) })), create.ScriptChar(')'), }).Capture(CAPTURE_SCRIPT_TOKEN), create.Optional(create.Char(';')) }); } }; class SequenceSetPlayerDataSplitscreen final : public AbstractSequenceWithPlayerData { public: explicit SequenceSetPlayerDataSplitscreen() { const ScriptMatcherFactory create(this); AddLabeledMatchers(PlayerDataPathMatchers(create), LABEL_PLAYER_DATA_PATH_ELEMENT); AddMatchers({ create.And({ create.ScriptKeyword("setPlayerDataSplitscreen"), create.ScriptChar('('), create.ScriptInt(), create.ScriptChar(','), create.Label(LABEL_PLAYER_DATA_PATH_ELEMENT), create.Loop(create.And({ create.ScriptChar(','), create.Label(LABEL_PLAYER_DATA_PATH_ELEMENT) })), create.ScriptChar(')'), }).Capture(CAPTURE_SCRIPT_TOKEN), create.Optional(create.Char(';')) }); } }; class SequenceLerp final : public SequenceGenericScriptStatement { public: explicit SequenceLerp() { const ScriptMatcherFactory create(this); AddMatchers({ create.And({ create.ScriptKeyword("lerp"), create.Or({ create.ScriptKeyword("scale"), create.ScriptKeyword("alpha"), create.ScriptKeyword("x"), create.ScriptKeyword("y"), }), create.ScriptKeyword("from"), create.ScriptNumeric(), create.ScriptKeyword("to"), create.ScriptNumeric(), create.ScriptKeyword("over"), create.ScriptNumeric() }).Capture(CAPTURE_SCRIPT_TOKEN), create.Optional(create.Char(';')) }); } }; class SequenceSetLocalVar final : public MenuFileParser::sequence_t { static constexpr auto TAG_BOOL = static_cast(SetLocalVarType::BOOL); static constexpr auto TAG_INT = static_cast(SetLocalVarType::INT); static constexpr auto TAG_FLOAT = static_cast(SetLocalVarType::FLOAT); static constexpr auto TAG_STRING = static_cast(SetLocalVarType::STRING); static constexpr auto CAPTURE_VAR_NAME = 1; public: SequenceSetLocalVar() { const ScriptMatcherFactory create(this); const MenuExpressionMatchers expressionMatchers; AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION); AddMatchers({ create.Or({ create.ScriptKeyword("setLocalVarBool").Tag(TAG_BOOL), create.ScriptKeyword("setLocalVarInt").Tag(TAG_INT), create.ScriptKeyword("setLocalVarFloat").Tag(TAG_FLOAT), create.ScriptKeyword("setLocalVarString").Tag(TAG_STRING) }), create.ScriptText().Capture(CAPTURE_VAR_NAME), create.Label(MenuExpressionMatchers::LABEL_EXPRESSION), create.Optional(create.Char(';')) }); } private: static std::string ScriptKeywordForType(const SetLocalVarType type) { switch (type) { case SetLocalVarType::BOOL: return "setLocalVarBool"; case SetLocalVarType::INT: return "setLocalVarInt"; case SetLocalVarType::FLOAT: return "setLocalVarFloat"; case SetLocalVarType::STRING: return "setLocalVarString"; default: return "unknown"; } } static void EmitStaticValue(MenuFileParserState* state, const SimpleExpressionValue& value) { switch (value.m_type) { case SimpleExpressionValue::Type::DOUBLE: state->m_current_script << value.m_double_value; break; case SimpleExpressionValue::Type::INT: state->m_current_script << value.m_int_value; break; case SimpleExpressionValue::Type::STRING: state->m_current_script << *value.m_string_value; break; } } static void CheckStaticValueType(const TokenPos& pos, const SetLocalVarType type, const SimpleExpressionValue& staticValue) { switch (type) { case SetLocalVarType::BOOL: if (staticValue.m_type != SimpleExpressionValue::Type::INT) throw ParsingException(pos, "Static value must be BOOL"); break; case SetLocalVarType::INT: if (staticValue.m_type != SimpleExpressionValue::Type::INT) throw ParsingException(pos, "Static value must be INT"); break; case SetLocalVarType::FLOAT: if (staticValue.m_type != SimpleExpressionValue::Type::DOUBLE && staticValue.m_type != SimpleExpressionValue::Type::INT) throw ParsingException(pos, "Static value must be FLOAT"); break; case SetLocalVarType::STRING: default: break; } } static void EmitStaticSetLocalVar(MenuFileParserState* state, const TokenPos& pos, const SetLocalVarType type, const std::string& varName, std::unique_ptr expression) { state->m_current_script << "\"" << ScriptKeywordForType(type) << "\" \"" << varName << "\" \""; const auto staticValue = expression->Evaluate(); CheckStaticValueType(pos, type, staticValue); EmitStaticValue(state, staticValue); state->m_current_script << "\" ; "; } static void EmitDynamicSetLocalVar(const MenuFileParserState* state, const SetLocalVarType type, const std::string& varName, std::unique_ptr expression) { state->m_current_nested_event_handler_set->m_elements.emplace_back(std::make_unique(type, varName, std::move(expression))); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { const MenuExpressionMatchers expressionMatchers(state); const auto typeTag = static_cast(result.NextTag()); const auto& varNameToken = result.NextCapture(CAPTURE_VAR_NAME); const auto& varName = MenuMatcherFactory::TokenTextValue(varNameToken); auto expression = expressionMatchers.ProcessExpression(result); if (!expression) throw ParsingException(varNameToken.GetPos(), "No expression"); if (expression && expression->IsStatic()) EmitStaticSetLocalVar(state, varNameToken.GetPos(), typeTag, varName, std::move(expression)); else EmitDynamicSetLocalVar(state, typeTag, varName, std::move(expression)); } }; class SequenceIf final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_KEYWORD = 1; public: SequenceIf() { const ScriptMatcherFactory create(this); const MenuExpressionMatchers expressionMatchers; AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION); AddMatchers({ create.Keyword("if").Capture(CAPTURE_KEYWORD), create.Char('('), create.Label(MenuExpressionMatchers::LABEL_EXPRESSION), create.Char(')'), create.Char('{') }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { const MenuExpressionMatchers expressionMatchers(state); auto expression = expressionMatchers.ProcessExpression(result); if (!expression) throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Could not parse expression"); auto remainingScript = state->m_current_script.str(); if (!remainingScript.empty()) state->m_current_nested_event_handler_set->m_elements.emplace_back(std::make_unique(std::move(remainingScript))); state->m_current_script.str(std::string()); auto newCondition = std::make_unique(std::move(expression), std::make_unique(), nullptr); auto* newConditionPtr = newCondition.get(); state->m_current_nested_event_handler_set->m_elements.emplace_back(std::move(newCondition)); state->m_condition_stack.emplace(newConditionPtr); state->m_current_nested_event_handler_set = newConditionPtr->m_condition_elements.get(); } }; class SequenceElseIf final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_KEYWORD = 1; public: SequenceElseIf() { const ScriptMatcherFactory create(this); const MenuExpressionMatchers expressionMatchers; AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION); AddMatchers({ create.Char('}'), create.Keyword("elseif").Capture(CAPTURE_KEYWORD), create.Char('('), create.Label(MenuExpressionMatchers::LABEL_EXPRESSION), create.Char(')'), create.Char('{') }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { const MenuExpressionMatchers expressionMatchers(state); auto expression = expressionMatchers.ProcessExpression(result); if (!expression) throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Could not parse expression"); if (state->m_condition_stack.empty()) throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Not in an if statement"); auto remainingScript = state->m_current_script.str(); if (!remainingScript.empty()) state->m_current_nested_event_handler_set->m_elements.emplace_back(std::make_unique(std::move(remainingScript))); state->m_current_script.str(std::string()); auto& currentCondition = state->m_condition_stack.top(); assert(currentCondition.m_in_condition_elements == (currentCondition.m_condition->m_else_elements == nullptr)); if (!currentCondition.m_in_condition_elements) throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Cannot specify elseif after else"); currentCondition.m_in_condition_elements = false; auto newCondition = std::make_unique(std::move(expression), std::make_unique(), nullptr); auto* newConditionPtr = newCondition.get(); currentCondition.m_condition->m_else_elements = std::make_unique(); currentCondition.m_condition->m_else_elements->m_elements.emplace_back(std::move(newCondition)); state->m_condition_stack.emplace(newConditionPtr, true); state->m_current_nested_event_handler_set = newConditionPtr->m_condition_elements.get(); } }; class SequenceElse final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_KEYWORD = 1; public: SequenceElse() { const ScriptMatcherFactory create(this); const MenuExpressionMatchers expressionMatchers; AddMatchers({ create.Char('}'), create.Keyword("else").Capture(CAPTURE_KEYWORD), create.Char('{') }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { if (state->m_condition_stack.empty()) throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Not in an if statement"); auto& currentCondition = state->m_condition_stack.top(); assert(currentCondition.m_in_condition_elements == (currentCondition.m_condition->m_else_elements == nullptr)); if (!currentCondition.m_in_condition_elements) throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Cannot specify second else block"); auto remainingScript = state->m_current_script.str(); if (!remainingScript.empty()) state->m_current_nested_event_handler_set->m_elements.emplace_back(std::make_unique(std::move(remainingScript))); state->m_current_script.str(std::string()); currentCondition.m_in_condition_elements = false; currentCondition.m_condition->m_else_elements = std::make_unique(); state->m_current_nested_event_handler_set = currentCondition.m_condition->m_else_elements.get(); } }; } using namespace event_handler_set_scope_sequences; EventHandlerSetScopeSequences::EventHandlerSetScopeSequences(std::vector>& allSequences, std::vector& scopeSequences) : AbstractScopeSequenceHolder(allSequences, scopeSequences) { } void EventHandlerSetScopeSequences::AddSequences(FeatureLevel featureLevel, bool permissive) { AddSequence(std::make_unique()); // If else and stuff // Creating factory with no label supplier. Cannot use labels with it. const ScriptMatcherFactory create(nullptr); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("fadeIn"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("fadeOut"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("show"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("hide"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("showMenu"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("hideMenu"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("setColor"), create.ScriptColor()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("open"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("close"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("escape"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("closeForAllPlayers"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("ingameOpen"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("ingameClose"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("setBackground"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("setItemColor"), create.ScriptText(), create.ScriptText(), create.ScriptColor()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("focusFirst")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("setFocus"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("setFocusByDvar"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("setDvar"), create.ScriptText(), create.Or({create.ScriptStrictNumeric(), create.ScriptText()})})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("exec"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("execNow"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("execOnDvarStringValue"), create.ScriptText(), create.ScriptText(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("execOnDvarIntValue"), create.ScriptText(), create.ScriptInt(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("execOnDvarFloatValue"), create.ScriptText(), create.ScriptNumeric(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("execNowOnDvarStringValue"), create.ScriptText(), create.ScriptText(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("execNowOnDvarIntValue"), create.ScriptText(), create.ScriptInt(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("execNowOnDvarFloatValue"), create.ScriptText(), create.ScriptNumeric(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("play"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("scriptMenuResponse"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("respondOnDvarStringValue"), create.ScriptText(), create.ScriptText(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("respondOnDvarIntValue"), create.ScriptText(), create.ScriptInt(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("respondOnDvarFloatValue"), create.ScriptText(), create.ScriptNumeric(), create.ScriptText()})); AddSequence(std::make_unique()); AddSequence(std::make_unique()); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("setPlayerDataSp")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("updateMail")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("openMail")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("deleteMail")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("doMailLottery")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("resetStatsConfirm")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("resetStatsCancel")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("setGameMode"), create.ScriptText()})); AddSequence(std::make_unique()); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("feederTop")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("feederBottom")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("showGamerCard")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("openForGameType"), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("closeForGameType"), create.ScriptText()})); // statClearPerkNew // TODO // statSetUsingTable // TODO // statClearBitMask // TODO AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("kickPlayer")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("getKickPlayerQuestion")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("partyUpdateMissingMapPackDvar")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("togglePlayerMute")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("resolveError")})); AddSequence(std::make_unique()); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("StartServer")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("loadArenas")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("loadGameInfo")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("clearError")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("Quit")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("Controls")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("Leave")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("closeingame")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("update"), create.ScriptText()})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("startSingleplayer")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("getLanguage")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("verifyLanguage")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("updateLanguage")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("mutePlayer")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("openMenuOnDvar"), create.ScriptText(), create.Or({create.ScriptStrictNumeric(), create.ScriptText()}), create.ScriptText()})); AddSequence( SequenceUiScriptStatement::Create({create.ScriptKeyword("openMenuOnDvarNot"), create.ScriptText(), create.Or({create.ScriptStrictNumeric(), create.ScriptText()}), create.ScriptText()})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("closeMenuOnDvar"), create.ScriptText(), create.Or({create.ScriptStrictNumeric(), create.ScriptText()}), create.ScriptText()})); AddSequence(SequenceUiScriptStatement::Create( {create.ScriptKeyword("closeMenuOnDvarNot"), create.ScriptText(), create.Or({create.ScriptStrictNumeric(), create.ScriptText()}), create.ScriptText()})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("setRecommended")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("clearLoadErrorsSummary")})); AddSequence(SequenceUiScriptStatement::Create({create.ScriptKeyword("clearClientMatchData")})); if(featureLevel == FeatureLevel::IW4) { // IW4x UiScripts AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("LoadMods") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("RunMod") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("ClearMods") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("security_increase_cancel") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("mod_download_cancel") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("LoadFriends") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("JoinFriend") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("downloadDLC"), create.ScriptInt() })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("checkFirstLaunch") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("visitWebsite") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("visitWiki") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("visitDiscord") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("updateui_mousePitch") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("ServerStatus") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("UpdateFilter") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("RefreshFilter") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("RefreshServers") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("JoinServer") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("ServerSort"), create.ScriptInt() })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("CreateListFavorite") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("CreateFavorite") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("CreateCurrentServerFavorite") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("DeleteFavorite") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("nextStartupMessage") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("UpdateClasses") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("loadDemos") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("launchDemo") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("deleteDemo") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("ApplyMap") })); AddSequence(SequenceUiScriptStatement::Create({ create.ScriptKeyword("ApplyInitialMap") })); } AddSequence(std::make_unique()); AddSequence(std::make_unique()); AddSequence(std::make_unique()); AddSequence(std::make_unique()); if (permissive) { AddSequence(std::make_unique()); } }