diff --git a/src/script/api/script_text.cpp b/src/script/api/script_text.cpp --- a/src/script/api/script_text.cpp +++ b/src/script/api/script_text.cpp @@ -160,25 +160,30 @@ SQInteger ScriptText::_set(HSQUIRRELVM v std::string ScriptText::GetEncodedText() { - StringIDList seen_ids; + ScriptTextList seen_texts; ParamList params; int param_count = 0; std::string result; auto output = std::back_inserter(result); - this->_FillParamList(params); - this->_GetEncodedText(output, param_count, seen_ids, params); + this->_FillParamList(params, seen_texts); + this->_GetEncodedText(output, param_count, params); if (param_count > SCRIPT_TEXT_MAX_PARAMETERS) throw Script_FatalError(fmt::format("{}: Too many parameters", GetGameStringName(this->string))); return result; } -void ScriptText::_FillParamList(ParamList ¶ms) +void ScriptText::_FillParamList(ParamList ¶ms, ScriptTextList &seen_texts) { + if (std::find(seen_texts.begin(), seen_texts.end(), this) != seen_texts.end()) throw Script_FatalError(fmt::format("{}: Circular reference detected", GetGameStringName(this->string))); + seen_texts.push_back(this); + for (int i = 0; i < this->paramc; i++) { Param *p = &this->param[i]; params.emplace_back(this->string, i, p); if (!std::holds_alternative(*p)) continue; - std::get(*p)->_FillParamList(params); + std::get(*p)->_FillParamList(params, seen_texts); } + + seen_texts.pop_back(); } void ScriptText::ParamCheck::Encode(std::back_insert_iterator &output) @@ -190,13 +195,10 @@ void ScriptText::ParamCheck::Encode(std: this->used = true; } -void ScriptText::_GetEncodedText(std::back_insert_iterator &output, int ¶m_count, StringIDList &seen_ids, ParamSpan args) +void ScriptText::_GetEncodedText(std::back_insert_iterator &output, int ¶m_count, ParamSpan args) { const std::string &name = GetGameStringName(this->string); - if (std::find(seen_ids.begin(), seen_ids.end(), this->string) != seen_ids.end()) throw Script_FatalError(fmt::format("{}: Circular reference detected", name)); - seen_ids.push_back(this->string); - Utf8Encode(output, SCC_ENCODED); fmt::format_to(output, "{:X}", this->string); @@ -234,7 +236,7 @@ void ScriptText::_GetEncodedText(std::ba int count = 0; fmt::format_to(output, ":"); ScriptTextRef &ref = std::get(*p.param); - ref->_GetEncodedText(output, count, seen_ids, args.subspan(idx)); + ref->_GetEncodedText(output, count, args.subspan(idx)); p.used = true; if (++count != cur_param.consumes) { ScriptLog::Error(fmt::format("{}({}): {{{}}} expects {} to be consumed, but {} consumes {}", name, param_count + 1, cur_param.cmd, cur_param.consumes - 1, GetGameStringName(ref->string), count - 1)); @@ -255,8 +257,6 @@ void ScriptText::_GetEncodedText(std::ba param_count += cur_param.consumes; } - - seen_ids.pop_back(); } const std::string Text::GetDecodedText()