Rework script handling to use smart pointers properly
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2022-05-14 16:07:32 +02:00
parent 0117cb9d64
commit de6d39376f
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
17 changed files with 85 additions and 77 deletions

View File

@ -7,10 +7,14 @@ export_func u8 CreatureLib_ExecutingAttack_Construct(ExecutingAttack*& out, Crea
LearnedAttack* attack,
CreatureLib::Library::AttackData* attackData,
BattleScript* script) {
Try(auto ls = ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>(targetCount);
for (size_t i = 0; i < targetCount; i++) { ls.Append(targets[i]); } auto s =
std::unique_ptr<BattleScript>(script);
out = new ExecutingAttack(ls, numberHits, user, attack, attackData, s);)
Try({
auto ls = ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>(targetCount);
for (size_t i = 0; i < targetCount; i++) {
ls.Append(targets[i]);
}
auto s = ArbUt::OptionalUniquePtr<BattleScript>(script);
out = new ExecutingAttack(ls, numberHits, user, attack, attackData, s);
})
}
export_func void CreatureLib_ExecutingAttack_Destruct(ExecutingAttack* p) { delete p; }

View File

@ -11,7 +11,7 @@ export_func u8 CreatureLib_ScriptResolver_Initialize(ScriptResolver* p, BattleLi
};
export_func u8 CreatureLib_ScriptResolver_LoadScript(BattleScript*& out, ScriptResolver* p, void* owner,
ScriptCategory category, const char* scriptName) {
Try(out = p->LoadScript(owner, category, ArbUt::StringView(scriptName));)
Try(out = p->LoadScript(owner, category, ArbUt::StringView(scriptName)).TakeOwnership();)
};
export_func u8 CreatureLib_ScriptResolver_LoadItemScript(ItemUseScript*& out, ScriptResolver* p,

View File

@ -39,7 +39,7 @@ SIMPLE_GET_FUNC(AttackTurnChoice, GetKind, TurnChoiceKind)
export_func u8 CreatureLib_AttackTurnChoice_GetPriority(i8& out, AttackTurnChoice* p) { Try(out = p->GetPriority()); }
SMART_GET_FUNC(AttackTurnChoice, GetAttackScript, BattleScript*)
OPTIONAL_GET_FUNC(AttackTurnChoice, GetAttackScript, BattleScript*)
export_func u8 CreatureLib_AttackTurnChoice_GetTargetSideIndex(const AttackTurnChoice* p) {
return p->GetTarget().GetSideIndex();
}

View File

@ -51,7 +51,7 @@ public:
#define BORROWED_GET_FUNC(type, name, returnType) \
export_func returnType CreatureLib_##type##_##name(const type* p) { return p->name().GetRaw(); }
#define OPTIONAL_GET_FUNC(type, name, returnType) \
export_func returnType CreatureLib_##type##_##name(const type* p) { \
export_func returnType CreatureLib_##type##_##name(type* p) { \
if (p->name().HasValue()) \
return p->name().GetValue(); \
return nullptr; \

View File

@ -115,8 +115,9 @@ void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>
return;
}
auto attackScoped = ArbUt::ScopedPtr<ExecutingAttack>(new ExecutingAttack(
targets, numberHits, choice->GetUser(), choice->GetAttack(), attackData, choice->GetAttackScript()));
auto attackScoped = ArbUt::ScopedPtr<ExecutingAttack>(
new ExecutingAttack(targets, numberHits, choice->GetUser(), choice->GetAttack(), attackData,
choice->GetAttackScript().TakeOwnership()));
bool prevented = false;
HOOK(PreventAttack, attackScoped, attackScoped, &prevented);
if (prevented) {

View File

@ -44,7 +44,8 @@ const std::unique_ptr<const DamageLibrary>& BattleLibrary::GetDamageLibrary() co
const std::unique_ptr<const MiscLibrary>& BattleLibrary::GetMiscLibrary() const noexcept { return _miscLibrary; }
BattleScript* nullable BattleLibrary::LoadScript(const ArbUt::OptionalBorrowedPtr<void>& owner, ScriptCategory category,
const ArbUt::StringView& scriptName) const {
return _scriptResolver->LoadScript(owner, category, scriptName);
ArbUt::OptionalUniquePtr<BattleScript> BattleLibrary::LoadScript(const ArbUt::OptionalBorrowedPtr<void>& owner,
ScriptCategory category,
const ArbUt::StringView& scriptName) const {
return _scriptResolver->LoadScript(owner, category, scriptName).TakeOwnership();
}

View File

@ -44,9 +44,9 @@ namespace CreatureLib::Battling {
return _scriptResolver;
}
[[nodiscard]] BattleScript* nullable LoadScript(const ArbUt::OptionalBorrowedPtr<void>& owner,
ScriptCategory category,
const ArbUt::StringView& scriptName) const;
[[nodiscard]] ArbUt::OptionalUniquePtr<BattleScript> LoadScript(const ArbUt::OptionalBorrowedPtr<void>& owner,
ScriptCategory category,
const ArbUt::StringView& scriptName) const;
};
}

View File

@ -167,11 +167,11 @@ BattleScript* Battle::AddVolatileScript(const ArbUt::StringView& key) {
script.GetValue()->Stack();
return script.GetValue();
}
script = _library->LoadScript(this, ScriptCategory::Battle, key);
script = _library->LoadScript(this, ScriptCategory::Battle, key).TakeOwnership();
if (!script.HasValue()) {
THROW("Invalid volatile script requested for battle: '", key.c_str(), "'.");
}
return _volatile.Add(script.GetValue());
return _volatile.Add(script);
}
BattleScript* Battle::AddVolatileScript(BattleScript* script) { return _volatile.Add(script); }
void Battle::RemoveVolatileScript(BattleScript* script) { _volatile.Remove(script->GetName()); }

View File

@ -145,7 +145,7 @@ BattleScript* BattleSide::AddVolatileScript(const ArbUt::StringView& key) {
script.GetValue()->Stack();
return script.GetValue();
}
script = _battle->GetLibrary()->LoadScript(this, ScriptCategory::Side, key);
script = _battle->GetLibrary()->LoadScript(this, ScriptCategory::Side, key).TakeOwnership();
if (!script.HasValue()) {
THROW("Invalid volatile script requested for battleside: '", key.c_str(), "'.");
}

View File

@ -21,15 +21,17 @@ namespace CreatureLib::Battling {
_height(variant->GetHeight()), _nickname(std::move(nickname)), _talentIndex(talent),
_hasOverridenTalent(false), _attacks(attacks), _allowedExperienceGain(allowedExperienceGain),
_heldItem(heldItem) {
_activeTalent = std::unique_ptr<BattleScript>(
_library->LoadScript(this, ScriptCategory::Talent, GetActiveTalent()->GetEffect()));
if (_activeTalent != nullptr) {
_activeTalent->OnInitialize(_library.GetRaw(), GetActiveTalent()->GetParameters());
_activeTalent =
_library->LoadScript(this, ScriptCategory::Talent, GetActiveTalent()->GetEffect()).TakeOwnership();
if (_activeTalent.HasValue()) {
_activeTalent.GetValue()->OnInitialize(_library.GetRaw(), GetActiveTalent()->GetParameters());
}
if (_heldItem.HasValue() && _heldItem.GetValue()->GetBattleTriggerEffect().HasValue()) {
_heldItemTriggerScript = std::unique_ptr<BattleScript>(
_library->LoadScript(this, ScriptCategory::ItemBattleTrigger,
_heldItem.GetValue()->GetBattleTriggerEffect().GetValue()->GetEffectName()));
_heldItemTriggerScript =
_library
->LoadScript(this, ScriptCategory::ItemBattleTrigger,
_heldItem.GetValue()->GetBattleTriggerEffect().GetValue()->GetEffectName())
.TakeOwnership();
}
for (auto t : _variant->GetTypes()) {
_types.push_back(t);
@ -82,10 +84,10 @@ namespace CreatureLib::Battling {
_height = variant->GetHeight();
// Grab the new active talent.
_activeTalent = std::unique_ptr<BattleScript>(
_library->LoadScript(this, ScriptCategory::Talent, GetActiveTalent()->GetEffect()));
if (_activeTalent != nullptr) {
_activeTalent->OnInitialize(_library.GetRaw(), GetActiveTalent()->GetParameters());
_activeTalent =
_library->LoadScript(this, ScriptCategory::Talent, GetActiveTalent()->GetEffect()).TakeOwnership();
if (_activeTalent.HasValue()) {
_activeTalent.GetValue()->OnInitialize(_library.GetRaw(), GetActiveTalent()->GetParameters());
}
// We modify the health of the creature by the change in its max health.
@ -264,9 +266,9 @@ namespace CreatureLib::Battling {
void Creature::OverrideActiveTalent(const ArbUt::StringView& talent) {
_hasOverridenTalent = true;
if (_activeTalent != nullptr) {
_activeTalent->OnRemove();
_activeTalent.reset(this->_library->LoadScript(this, ScriptCategory::Talent, talent));
if (_activeTalent.HasValue()) {
_activeTalent.GetValue()->OnRemove();
_activeTalent = this->_library->LoadScript(this, ScriptCategory::Talent, talent).TakeOwnership();
}
_overridenTalent = _library->GetStaticLib()->GetTalentLibrary()->Get(talent);
}
@ -395,7 +397,7 @@ namespace CreatureLib::Battling {
script.GetValue()->Stack();
return script.GetValue();
}
script = this->_library->LoadScript(this, ScriptCategory::Creature, name);
script = this->_library->LoadScript(this, ScriptCategory::Creature, name).TakeOwnership();
if (!script.HasValue()) {
THROW("Invalid volatile script requested for creature: '", name.c_str(), "'.");
}
@ -463,13 +465,13 @@ namespace CreatureLib::Battling {
c->_battleData.Side = _battleData.Side;
c->_battleData.OnBattleField = _battleData.OnBattleField;
c->_battleData.Index = _battleData.Index;
if (_activeTalent != nullptr) {
c->_activeTalent = std::unique_ptr<BattleScript>(_activeTalent->Clone(c));
if (_activeTalent.HasValue()) {
c->_activeTalent = _activeTalent.GetValue()->Clone(c);
}
c->_hasOverridenTalent = _hasOverridenTalent;
c->_overridenTalent = _overridenTalent;
if (_status != nullptr) {
c->_status = std::unique_ptr<BattleScript>(_status->Clone(c));
if (_status.HasValue()) {
c->_status = _status.GetValue()->Clone(c);
}
_volatile.Clone(c, c->_volatile);
c->_types = std::vector<u8>(_types);
@ -479,19 +481,19 @@ namespace CreatureLib::Battling {
}
void Creature::SetStatus(const ArbUt::StringView& name) {
if (_status != nullptr) {
_status->OnRemove();
if (_status.HasValue()) {
_status.GetValue()->OnRemove();
}
_status = std::unique_ptr<BattleScript>(_library->LoadScript(this, ScriptCategory::Status, name));
_status = _library->LoadScript(this, ScriptCategory::Status, name).TakeOwnership();
if (_battleData.Battle.HasValue()) {
_battleData.Battle.GetValue()->TriggerEventListener<StatusChangeEvent>(this, name);
}
}
void Creature::ClearStatus() {
if (_status == nullptr) {
if (!_status.HasValue()) {
return;
}
_status->OnRemove();
_status.GetValue()->OnRemove();
_status = nullptr;
if (_battleData.Battle.HasValue()) {
_battleData.Battle.GetValue()->TriggerEventListener<StatusChangeEvent>(this, ""_cnc);

View File

@ -53,7 +53,7 @@ namespace CreatureLib::Battling {
std::optional<std::string> _nickname = {};
CreatureLib::Library::TalentIndex _talentIndex = {};
std::unique_ptr<BattleScript> _activeTalent = {};
ArbUt::OptionalUniquePtr<BattleScript> _activeTalent = {};
bool _hasOverridenTalent = false;
ArbUt::OptionalBorrowedPtr<const Library::Talent> _overridenTalent = {};
@ -61,13 +61,13 @@ namespace CreatureLib::Battling {
ArbUt::OptionalUniquePtrList<LearnedAttack> _attacks = {};
bool _allowedExperienceGain = {};
std::unique_ptr<BattleScript> _status = nullptr;
ArbUt::OptionalUniquePtr<BattleScript> _status = nullptr;
ScriptSet _volatile = {};
std::vector<u8> _types = {};
ArbUt::OptionalBorrowedPtr<const Library::Item> _heldItem;
std::unique_ptr<BattleScript> _heldItemTriggerScript = nullptr;
ArbUt::OptionalUniquePtr<BattleScript> _heldItemTriggerScript = nullptr;
private:
void OnFaint(DamageSource damageSource);
@ -212,9 +212,9 @@ namespace CreatureLib::Battling {
void SetStatus(const ArbUt::StringView& name);
void ClearStatus();
const ArbUt::StringView& GetStatusName() const noexcept {
if (_status == nullptr)
if (!_status.HasValue())
return ArbUt::StringView::EmptyString();
return _status->GetName();
return _status.GetValue()->GetName();
}
// region Stat APIs

View File

@ -38,18 +38,17 @@ namespace CreatureLib::Battling {
ArbUt::BorrowedPtr<Creature> _user;
ArbUt::BorrowedPtr<LearnedAttack> _attack;
ArbUt::BorrowedPtr<const Library::AttackData> _useAttack;
std::unique_ptr<BattleScript> _script = nullptr;
ArbUt::OptionalUniquePtr<BattleScript> _script = nullptr;
ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>> _targets;
public:
ExecutingAttack(const ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>& targets, u8 numberHits,
ArbUt::BorrowedPtr<Creature> user, const ArbUt::BorrowedPtr<LearnedAttack>& attack,
const ArbUt::BorrowedPtr<const Library::AttackData>& useAttack,
const std::unique_ptr<BattleScript>& script)
const ArbUt::BorrowedPtr<const Library::AttackData>& useAttack, BattleScript* nullable script)
: _numberHits(numberHits), _hits(std::make_unique<HitData[]>(targets.Count() * numberHits)), _user(user),
_attack(attack), _useAttack(useAttack), _targets(targets) {
// Take ownership of the script of the attack choice, and give attack choice our initial nullptr.
_script.swap(const_cast<std::unique_ptr<BattleScript>&>(script));
_script = script;
}
ExecutingAttack(const ExecutingAttack&) = delete;
ExecutingAttack& operator=(const ExecutingAttack&) = delete;
@ -103,7 +102,7 @@ namespace CreatureLib::Battling {
inline const ArbUt::BorrowedPtr<const Library::AttackData>& GetUseAttack() noexcept { return _useAttack; }
size_t ScriptCount() const override { return _user->ScriptCount() + 1; }
inline ArbUt::BorrowedPtr<BattleScript> GetScript() const noexcept { return _script; }
inline ArbUt::BorrowedPtr<BattleScript> GetScript() const noexcept { return _script.GetValue(); }
void GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) override {
GetOwnScripts(scripts);

View File

@ -32,10 +32,10 @@
scriptIterator->hookName(__VA_ARGS__); \
} \
} else { \
if (scriptWrapper.GetScript()->get()->IsSuppressed()) { \
if (scriptWrapper.GetScript()->GetValue()->IsSuppressed()) { \
continue; \
} \
scriptWrapper.GetScript()->get()->hookName(__VA_ARGS__); \
scriptWrapper.GetScript()->GetValue()->hookName(__VA_ARGS__); \
} \
} \
} catch (const ArbUt::Exception& e) { \

View File

@ -9,22 +9,22 @@ namespace CreatureLib::Battling {
bool _isSet;
union {
std::unique_ptr<BattleScript> const* nullable _script;
ArbUt::OptionalUniquePtr<BattleScript> const* nullable _script;
const ScriptSet* nullable _scriptSet;
};
ScriptWrapper(std::unique_ptr<BattleScript>* nullable s, bool isSet) : _isSet(isSet), _script(s){};
ScriptWrapper(ArbUt::OptionalUniquePtr<BattleScript>* nullable s, bool isSet) : _isSet(isSet), _script(s){};
ScriptWrapper(ScriptSet* nullable s, bool isSet) : _isSet(isSet), _scriptSet(s){};
public:
static inline ScriptWrapper FromScript(std::unique_ptr<BattleScript>* nullable s) {
static inline ScriptWrapper FromScript(ArbUt::OptionalUniquePtr<BattleScript>* nullable s) {
return ScriptWrapper(s, false);
}
static inline ScriptWrapper FromSet(ScriptSet* nullable s) { return ScriptWrapper(s, true); }
inline bool IsSet() const noexcept { return _isSet; }
inline const std::unique_ptr<BattleScript>* nullable GetScript() const noexcept { return _script; }
inline const ArbUt::OptionalUniquePtr<BattleScript>* nullable GetScript() const noexcept { return _script; }
inline const ScriptSet* nullable GetScriptSet() const noexcept { return _scriptSet; }
inline bool HasValue() const noexcept {

View File

@ -12,7 +12,7 @@ namespace CreatureLib::Battling {
class AttackTurnChoice : public BaseTurnChoice {
ArbUt::BorrowedPtr<LearnedAttack> _attack;
CreatureIndex _target;
std::unique_ptr<BattleScript> _attackScript = nullptr;
ArbUt::OptionalUniquePtr<BattleScript> _attackScript = nullptr;
i8 _priority = 0;
bool _hasFailed = false;
@ -25,10 +25,11 @@ namespace CreatureLib::Battling {
if (attack->HasSecondaryEffect()) {
auto library = battle.GetValue()->GetLibrary();
auto& effect = attack->GetSecondaryEffect();
_attackScript = std::unique_ptr<BattleScript>(
library->LoadScript(this, ScriptCategory::Attack, effect->GetEffectName()));
if (_attackScript != nullptr) {
_attackScript->OnInitialize(battle.GetValue()->GetLibrary().GetRaw(), effect->GetParameters());
_attackScript =
library->LoadScript(this, ScriptCategory::Attack, effect->GetEffectName()).TakeOwnership();
if (_attackScript.HasValue()) {
_attackScript.GetValue()->OnInitialize(battle.GetValue()->GetLibrary().GetRaw(),
effect->GetParameters());
}
}
}
@ -64,7 +65,7 @@ namespace CreatureLib::Battling {
const CreatureIndex& GetTarget() const noexcept { return _target; }
const std::unique_ptr<BattleScript>& GetAttackScript() const noexcept { return _attackScript; }
ArbUt::OptionalUniquePtr<BattleScript>& GetAttackScript() noexcept { return _attackScript; }
size_t ScriptCount() const override { return 1 + GetUser()->ScriptCount(); }
void GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) override {

View File

@ -24,7 +24,7 @@ TEST_CASE("Script Aggregator properly iterates containing script.") {
auto script = std::make_unique<TestScript>("test");
auto ran = 0;
auto vec = ArbUt::List<ScriptWrapper>{
ScriptWrapper::FromScript(reinterpret_cast<std::unique_ptr<BattleScript>*>(&script))};
ScriptWrapper::FromScript(reinterpret_cast<ArbUt::OptionalUniquePtr<BattleScript>*>(&script))};
auto aggr = ScriptAggregator(vec);
ArbUt::BorrowedPtr<CreatureLib::Battling::BattleScript> next = (CreatureLib::Battling::BattleScript*)1;
while (aggr.GetNext(next)) {
@ -39,9 +39,9 @@ TEST_CASE("Script Aggregator properly iterates multiple scripts.") {
auto script3 = std::make_unique<TestScript>("test3");
auto ran = 0;
auto vec = ArbUt::List<ScriptWrapper>{
ScriptWrapper::FromScript(reinterpret_cast<std::unique_ptr<BattleScript>*>(&script)),
ScriptWrapper::FromScript(reinterpret_cast<std::unique_ptr<BattleScript>*>(&script2)),
ScriptWrapper::FromScript(reinterpret_cast<std::unique_ptr<BattleScript>*>(&script3))};
ScriptWrapper::FromScript(reinterpret_cast<ArbUt::OptionalUniquePtr<BattleScript>*>(&script)),
ScriptWrapper::FromScript(reinterpret_cast<ArbUt::OptionalUniquePtr<BattleScript>*>(&script2)),
ScriptWrapper::FromScript(reinterpret_cast<ArbUt::OptionalUniquePtr<BattleScript>*>(&script3))};
auto aggr = ScriptAggregator(vec);
ArbUt::BorrowedPtr<CreatureLib::Battling::BattleScript> next = (CreatureLib::Battling::BattleScript*)1;
while (aggr.GetNext(next)) {
@ -98,7 +98,7 @@ TEST_CASE("Script Aggregator properly iterates data of Script Set and Script.")
set.Add(script3);
auto vec = ArbUt::List<ScriptWrapper>{
ScriptWrapper::FromSet(&set),
ScriptWrapper::FromScript(reinterpret_cast<std::unique_ptr<BattleScript>*>(&script))};
ScriptWrapper::FromScript(reinterpret_cast<ArbUt::OptionalUniquePtr<BattleScript>*>(&script))};
auto aggr = ScriptAggregator(vec);
ArbUt::BorrowedPtr<CreatureLib::Battling::BattleScript> next = (CreatureLib::Battling::BattleScript*)1;
while (aggr.GetNext(next)) {
@ -115,9 +115,9 @@ TEST_CASE("Script Aggregator properly iterates data of Script and Script Set.")
auto set = ScriptSet();
set.Add(script2);
set.Add(script3);
auto vec =
ArbUt::List<ScriptWrapper>{ScriptWrapper::FromScript(reinterpret_cast<std::unique_ptr<BattleScript>*>(&script)),
ScriptWrapper::FromSet(&set)};
auto vec = ArbUt::List<ScriptWrapper>{
ScriptWrapper::FromScript(reinterpret_cast<ArbUt::OptionalUniquePtr<BattleScript>*>(&script)),
ScriptWrapper::FromSet(&set)};
auto aggr = ScriptAggregator(vec);
ArbUt::BorrowedPtr<CreatureLib::Battling::BattleScript> next = (CreatureLib::Battling::BattleScript*)1;
while (aggr.GetNext(next)) {
@ -136,9 +136,9 @@ TEST_CASE("Script Aggregator properly iterates data of Script, Script Set and Sc
set.Add(script2);
set.Add(script3);
auto vec = ArbUt::List<ScriptWrapper>{
ScriptWrapper::FromScript(reinterpret_cast<std::unique_ptr<BattleScript>*>(&script)),
ScriptWrapper::FromScript(reinterpret_cast<ArbUt::OptionalUniquePtr<BattleScript>*>(&script)),
ScriptWrapper::FromSet(&set),
ScriptWrapper::FromScript(reinterpret_cast<std::unique_ptr<BattleScript>*>(&script4))};
ScriptWrapper::FromScript(reinterpret_cast<ArbUt::OptionalUniquePtr<BattleScript>*>(&script4))};
auto aggr = ScriptAggregator(vec);
ArbUt::BorrowedPtr<CreatureLib::Battling::BattleScript> next = (CreatureLib::Battling::BattleScript*)1;
while (aggr.GetNext(next)) {

View File

@ -20,7 +20,7 @@ public:
class ScriptSourceWithScriptPtr : public ScriptSource {
public:
std::unique_ptr<BattleScript> ScriptPtr = nullptr;
ArbUt::OptionalUniquePtr<BattleScript> ScriptPtr = nullptr;
protected:
size_t ScriptCount() const override { return 1; }
@ -49,7 +49,7 @@ TEST_CASE("Script source with unset script ptr.") {
TEST_CASE("Script source with script ptr being set.") {
auto source = ScriptSourceWithScriptPtr();
source.ScriptPtr = std::make_unique<TestScript>("foobar");
source.ScriptPtr = new TestScript("foobar");
auto scripts = source.GetScriptIterator();
ArbUt::BorrowedPtr<CreatureLib::Battling::BattleScript> next = (CreatureLib::Battling::BattleScript*)1;
REQUIRE(scripts.GetNext(next));
@ -60,7 +60,7 @@ TEST_CASE("Script source with script ptr being set after first iteration.") {
auto scripts = source.GetScriptIterator();
ArbUt::BorrowedPtr<CreatureLib::Battling::BattleScript> next = (CreatureLib::Battling::BattleScript*)1;
REQUIRE_FALSE(scripts.GetNext(next));
source.ScriptPtr = std::make_unique<TestScript>("foobar");
source.ScriptPtr = new TestScript("foobar");
scripts = source.GetScriptIterator();
REQUIRE(scripts.GetNext(next));
}