
#include "miscextensions.hpp"

#include <libs/openengine/ogre/fader.hpp>

#include <components/compiler/extensions.hpp>

#include <components/interpreter/interpreter.hpp>
#include <components/interpreter/runtime.hpp>
#include <components/interpreter/opcodes.hpp>

#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"

#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwworld/containerstore.hpp"

#include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/creaturestats.hpp"

#include "interpretercontext.hpp"
#include "ref.hpp"

namespace MWScript
{
    namespace Misc
    {
        class OpPlayBink : public Interpreter::Opcode0
        {
        public:

            virtual void execute (Interpreter::Runtime& runtime)
            {
                std::string name = runtime.getStringLiteral (runtime[0].mInteger);
                runtime.pop();

                bool allowSkipping = runtime[0].mInteger;
                runtime.pop();

                MWBase::Environment::get().getWorld ()->playVideo (name, allowSkipping);
            }
        };

        class OpGetPcSleep : public Interpreter::Opcode0
        {
        public:

            virtual void execute (Interpreter::Runtime& runtime)
            {
                runtime.push (MWBase::Environment::get().getWindowManager ()->getPlayerSleeping());
            }
        };

        class OpWakeUpPc : public Interpreter::Opcode0
        {
        public:

            virtual void execute (Interpreter::Runtime& runtime)
            {
                MWBase::Environment::get().getWindowManager ()->wakeUpPlayer();
            }
        };

        class OpXBox : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    runtime.push (0);
                }
        };

        class OpOnActivate : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    InterpreterContext& context =
                        static_cast<InterpreterContext&> (runtime.getContext());

                    MWWorld::Ptr ptr = context.getReference();

                    runtime.push (context.hasBeenActivated (ptr));
                }
        };

        class OpActivate : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    InterpreterContext& context =
                        static_cast<InterpreterContext&> (runtime.getContext());

                    MWWorld::Ptr ptr = context.getReference();

                    context.executeActivation();
                }
        };

        template<class R>
        class OpLock : public Interpreter::Opcode1
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    Interpreter::Type_Integer lockLevel = 100;

                    if (arg0==1)
                    {
                        lockLevel = runtime[0].mInteger;
                        runtime.pop();
                    }

                    MWWorld::Class::get (ptr).lock (ptr, lockLevel);
                }
        };

        template<class R>
        class OpUnlock : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    MWWorld::Class::get (ptr).unlock (ptr);
                }
        };

        class OpToggleCollisionDebug : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    InterpreterContext& context =
                        static_cast<InterpreterContext&> (runtime.getContext());

                    bool enabled =
                        MWBase::Environment::get().getWorld()->toggleRenderMode (MWBase::World::Render_CollisionDebug);

                    context.report (enabled ?
                        "Collision Mesh Rendering -> On" : "Collision Mesh Rendering -> Off");
                }
        };


        class OpToggleCollisionBoxes : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    InterpreterContext& context =
                        static_cast<InterpreterContext&> (runtime.getContext());

                    bool enabled =
                        MWBase::Environment::get().getWorld()->toggleRenderMode (MWBase::World::Render_BoundingBoxes);

                    context.report (enabled ?
                        "Bounding Box Rendering -> On" : "Bounding Box Rendering -> Off");
                }
        };

        class OpToggleWireframe : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    InterpreterContext& context =
                        static_cast<InterpreterContext&> (runtime.getContext());

                    bool enabled =
                        MWBase::Environment::get().getWorld()->toggleRenderMode (MWBase::World::Render_Wireframe);

                    context.report (enabled ?
                        "Wireframe Rendering -> On" : "Wireframe Rendering -> Off");
                }
        };

        class OpTogglePathgrid : public Interpreter::Opcode0
        {
        public:
            virtual void execute (Interpreter::Runtime& runtime)
            {
                InterpreterContext& context =
                    static_cast<InterpreterContext&> (runtime.getContext());

                bool enabled =
                    MWBase::Environment::get().getWorld()->toggleRenderMode (MWBase::World::Render_Pathgrid);

                context.report (enabled ?
                    "Path Grid rendering -> On" : "Path Grid Rendering -> Off");
            }
        };

        class OpFadeIn : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    Interpreter::Type_Float time = runtime[0].mFloat;
                    runtime.pop();

                    MWBase::Environment::get().getWorld()->getFader()->fadeIn(time);
                }
        };

        class OpFadeOut : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    Interpreter::Type_Float time = runtime[0].mFloat;
                    runtime.pop();

                    MWBase::Environment::get().getWorld()->getFader()->fadeOut(time);
                }
        };

        class OpFadeTo : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    Interpreter::Type_Float alpha = runtime[0].mFloat;
                    runtime.pop();

                    Interpreter::Type_Float time = runtime[0].mFloat;
                    runtime.pop();

                    MWBase::Environment::get().getWorld()->getFader()->fadeTo(alpha, time);
                }
        };

        class OpToggleWater : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWBase::Environment::get().getWorld()->toggleWater();
                }
        };

        class OpDontSaveObject : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    // We are ignoring the DontSaveObject statement for now. Probably not worth
                    /// bothering with. The incompatibility we are creating should be marginal at most.
                }
        };

        class OpToggleVanityMode : public Interpreter::Opcode0
        {
            static bool sActivate;

        public:

            virtual void execute(Interpreter::Runtime &runtime)
            {
                InterpreterContext& context =
                    static_cast<InterpreterContext&> (runtime.getContext());

                MWBase::World *world =
                    MWBase::Environment::get().getWorld();

                if (world->toggleVanityMode(sActivate)) {
                    context.report(sActivate ? "Vanity Mode -> On" : "Vanity Mode -> Off");
                    sActivate = !sActivate;
                } else {
                    context.report("Vanity Mode -> No");
                }
            }
        };
        bool OpToggleVanityMode::sActivate = true;

        template <class R>
        class OpGetLocked : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    runtime.push (ptr.getCellRef ().mLockLevel > 0);
                }
        };

        template <class R>
        class OpGetEffect : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    int key = runtime[0].mInteger;
                    runtime.pop();

                    runtime.push (MWWorld::Class::get(ptr).getCreatureStats (ptr).getMagicEffects ().get (
                                      MWMechanics::EffectKey(key)).mMagnitude > 0);
                }
        };

        template<class R>
        class OpAddSoulGem : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    std::string creature = runtime.getStringLiteral (runtime[0].mInteger);
                    runtime.pop();

                    std::string gem = runtime.getStringLiteral (runtime[0].mInteger);
                    runtime.pop();

                    const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
                    store.get<ESM::Creature>().find(creature); // This line throws an exception if it can't find the creature

                    MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), gem);

                    ref.getPtr().getRefData().setCount (1);

                    ref.getPtr().getCellRef().mSoul = creature;

                    MWWorld::Class::get (ptr).getContainerStore (ptr).add (ref.getPtr());

                }
        };

        template<class R>
        class OpRemoveSoulGem : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {

                    MWWorld::Ptr ptr = R()(runtime);

                    std::string soul = runtime.getStringLiteral (runtime[0].mInteger);
                    runtime.pop();

                    MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);


                    for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
                    {
                        if (::Misc::StringUtils::ciEqual(iter->getCellRef().mSoul, soul))
                        {
                            if (iter->getRefData().getCount() <= 1)
                                iter->getRefData().setCount (0);
                            else
                                iter->getRefData().setCount (iter->getRefData().getCount() - 1);
                            break;
                        }
                    }
                }
        };

        template<class R>
        class OpDrop : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {

                    MWWorld::Ptr ptr = R()(runtime);

                    std::string item = runtime.getStringLiteral (runtime[0].mInteger);
                    runtime.pop();

                    Interpreter::Type_Integer amount = runtime[0].mInteger;
                    runtime.pop();

                    if (amount<0)
                        throw std::runtime_error ("amount must be non-negative");

                    // no-op
                    if (amount == 0)
                        return;

                    MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);


                    for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
                    {
                        if (::Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, item))
                        {
                            if(iter->getRefData().getCount() <= amount)
                            {
                                MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
                                iter->getRefData().setCount(0);
                            }
                            else
                            {
                                int original = iter->getRefData().getCount();
                                iter->getRefData().setCount(amount);
                                MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
                                iter->getRefData().setCount(original - amount);
                            }

                            break;
                        }
                    }
                }
        };

        template<class R>
        class OpDropSoulGem : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {

                    MWWorld::Ptr ptr = R()(runtime);

                    std::string soul = runtime.getStringLiteral (runtime[0].mInteger);
                    runtime.pop();

                    MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);


                    for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
                    {
                        if (::Misc::StringUtils::ciEqual(iter->getCellRef().mSoul, soul))
                        {

                            if(iter->getRefData().getCount() <= 1)
                            {
                                MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
                                iter->getRefData().setCount(0);
                            }
                            else
                            {
                                int original = iter->getRefData().getCount();
                                iter->getRefData().setCount(1);
                                MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
                                iter->getRefData().setCount(original - 1);
                            }

                            break;
                        }
                    }
                }
        };

        template <class R>
        class OpGetAttacked : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    runtime.push(MWWorld::Class::get(ptr).getCreatureStats (ptr).getAttacked ());
                }
        };

        template <class R>
        class OpGetWeaponDrawn : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    runtime.push(MWWorld::Class::get(ptr).getNpcStats (ptr).getDrawState () == MWMechanics::DrawState_Weapon);
                }
        };

        template <class R>
        class OpGetSpellEffects : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);
                    std::string id = runtime.getStringLiteral(runtime[0].mInteger);
                    runtime.pop();

                    runtime.push(MWWorld::Class::get(ptr).getCreatureStats(ptr).getActiveSpells().isSpellActive(id));
                }
        };

        class OpGetCurrentTime : public Interpreter::Opcode0
        {
        public:

            virtual void execute (Interpreter::Runtime& runtime)
            {
                runtime.push(MWBase::Environment::get().getWorld()->getTimeStamp().getHour());
            }
        };

        template <class R>
        class OpSetDelete : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);
                    int parameter = runtime[0].mInteger;
                    runtime.pop();

                    if (parameter == 1)
                    {
                        if (ptr.isInCell())
                            MWBase::Environment::get().getWorld()->deleteObject (ptr);
                        else
                            ptr.getRefData().setCount(0);
                    }
                }
        };

        class OpGetSquareRoot : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    float param = runtime[0].mFloat;
                    runtime.pop();

                    runtime.push(std::sqrt (param));
                }
        };

        template <class R>
        class OpFall : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                }
        };

        template <class R>
        class OpGetStandingPc : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);
                    runtime.push (MWBase::Environment::get().getWorld()->getPlayerStandingOn(ptr));
                }
        };

        template <class R>
        class OpGetStandingActor : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);
                    runtime.push (MWBase::Environment::get().getWorld()->getActorStandingOn(ptr));
                }
        };

        class OpGetWindSpeed : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    runtime.push(MWBase::Environment::get().getWorld()->getWindSpeed());
                }
        };

        template <class R>
        class OpHitOnMe : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    std::string objectID = runtime.getStringLiteral (runtime[0].mInteger);
                    runtime.pop();

                    MWMechanics::CreatureStats &stats = MWWorld::Class::get(ptr).getCreatureStats(ptr);
                    runtime.push(::Misc::StringUtils::ciEqual(objectID, stats.getLastHitObject()));
                }
        };

        template <bool Enable>
        class OpEnableTeleporting : public Interpreter::Opcode0
        {
            public:

                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWBase::World *world = MWBase::Environment::get().getWorld();
                    world->enableTeleporting(Enable);
                }
        };

        const int opcodeXBox = 0x200000c;
        const int opcodeOnActivate = 0x200000d;
        const int opcodeActivate = 0x2000075;
        const int opcodeLock = 0x20004;
        const int opcodeLockExplicit = 0x20005;
        const int opcodeUnlock = 0x200008c;
        const int opcodeUnlockExplicit = 0x200008d;
        const int opcodeToggleCollisionDebug = 0x2000132;
        const int opcodeToggleCollisionBoxes = 0x20001ac;
        const int opcodeToggleWireframe = 0x200013b;
        const int opcodeFadeIn = 0x200013c;
        const int opcodeFadeOut = 0x200013d;
        const int opcodeFadeTo = 0x200013e;
        const int opcodeToggleWater = 0x2000144;
        const int opcodeTogglePathgrid = 0x2000146;
        const int opcodeDontSaveObject = 0x2000153;
        const int opcodeToggleVanityMode = 0x2000174;
        const int opcodeGetPcSleep = 0x200019f;
        const int opcodeWakeUpPc = 0x20001a2;
        const int opcodeGetLocked = 0x20001c7;
        const int opcodeGetLockedExplicit = 0x20001c8;
        const int opcodeGetEffect = 0x20001cf;
        const int opcodeGetEffectExplicit = 0x20001d0;
        const int opcodeAddSoulGem = 0x20001f3;
        const int opcodeAddSoulGemExplicit = 0x20001f4;
        const int opcodeRemoveSoulGem = 0x20001f5;
        const int opcodeRemoveSoulGemExplicit = 0x20001f6;
        const int opcodeDrop = 0x20001f8;
        const int opcodeDropExplicit = 0x20001f9;
        const int opcodeDropSoulGem = 0x20001fa;
        const int opcodeDropSoulGemExplicit = 0x20001fb;
        const int opcodeGetAttacked = 0x20001d3;
        const int opcodeGetAttackedExplicit = 0x20001d4;
        const int opcodeGetWeaponDrawn = 0x20001d7;
        const int opcodeGetWeaponDrawnExplicit = 0x20001d8;
        const int opcodeGetSpellEffects = 0x20001db;
        const int opcodeGetSpellEffectsExplicit = 0x20001dc;
        const int opcodeGetCurrentTime = 0x20001dd;
        const int opcodeSetDelete = 0x20001e5;
        const int opcodeSetDeleteExplicit = 0x20001e6;
        const int opcodeGetSquareRoot = 0x20001e7;
        const int opcodeFall = 0x200020a;
        const int opcodeFallExplicit = 0x200020b;
        const int opcodeGetStandingPc = 0x200020c;
        const int opcodeGetStandingPcExplicit = 0x200020d;
        const int opcodeGetStandingActor = 0x200020e;
        const int opcodeGetStandingActorExplicit = 0x200020f;
        const int opcodeGetWindSpeed = 0x2000212;

        const int opcodePlayBink = 0x20001f7;

        const int opcodeHitOnMe = 0x2000213;
        const int opcodeHitOnMeExplicit = 0x2000214;

        const int opcodeDisableTeleporting = 0x2000215;
        const int opcodeEnableTeleporting = 0x2000216;

        void registerExtensions (Compiler::Extensions& extensions)
        {
            extensions.registerFunction ("xbox", 'l', "", opcodeXBox);
            extensions.registerFunction ("onactivate", 'l', "", opcodeOnActivate);
            extensions.registerInstruction ("activate", "", opcodeActivate);
            extensions.registerInstruction ("lock", "/l", opcodeLock, opcodeLockExplicit);
            extensions.registerInstruction ("unlock", "", opcodeUnlock, opcodeUnlockExplicit);
            extensions.registerInstruction ("togglecollisionboxes", "", opcodeToggleCollisionBoxes);
            extensions.registerInstruction ("togglecollisiongrid", "", opcodeToggleCollisionDebug);
            extensions.registerInstruction ("tcb", "", opcodeToggleCollisionBoxes);
            extensions.registerInstruction ("tcg", "", opcodeToggleCollisionDebug);
            extensions.registerInstruction ("twf", "", opcodeToggleWireframe);
            extensions.registerInstruction ("togglewireframe", "", opcodeToggleWireframe);
            extensions.registerInstruction ("fadein", "f", opcodeFadeIn);
            extensions.registerInstruction ("fadeout", "f", opcodeFadeOut);
            extensions.registerInstruction ("fadeto", "ff", opcodeFadeTo);
            extensions.registerInstruction ("togglewater", "", opcodeToggleWater);
            extensions.registerInstruction ("twa", "", opcodeToggleWater);
            extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid);
            extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid);
            extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject);
            extensions.registerInstruction ("togglevanitymode", "", opcodeToggleVanityMode);
            extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode);
            extensions.registerFunction ("getpcsleep", 'l', "", opcodeGetPcSleep);
            extensions.registerInstruction ("wakeuppc", "", opcodeWakeUpPc);
            extensions.registerInstruction ("playbink", "Sl", opcodePlayBink);
            extensions.registerFunction ("getlocked", 'l', "", opcodeGetLocked, opcodeGetLockedExplicit);
            extensions.registerFunction ("geteffect", 'l', "l", opcodeGetEffect, opcodeGetEffectExplicit);
            extensions.registerInstruction ("addsoulgem", "cc", opcodeAddSoulGem, opcodeAddSoulGemExplicit);
            extensions.registerInstruction ("removesoulgem", "c", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit);
            extensions.registerInstruction ("drop", "cl", opcodeDrop, opcodeDropExplicit);
            extensions.registerInstruction ("dropsoulgem", "c", opcodeDropSoulGem, opcodeDropSoulGemExplicit);
            extensions.registerFunction ("getattacked", 'l', "", opcodeGetAttacked, opcodeGetAttackedExplicit);
            extensions.registerFunction ("getweapondrawn", 'l', "", opcodeGetWeaponDrawn, opcodeGetWeaponDrawnExplicit);
            extensions.registerFunction ("getspelleffects", 'l', "c", opcodeGetSpellEffects, opcodeGetSpellEffectsExplicit);
            extensions.registerFunction ("getcurrenttime", 'f', "", opcodeGetCurrentTime);
            extensions.registerInstruction ("setdelete", "l", opcodeSetDelete, opcodeSetDeleteExplicit);
            extensions.registerFunction ("getsquareroot", 'f', "f", opcodeGetSquareRoot);
            extensions.registerInstruction ("fall", "", opcodeFall, opcodeFallExplicit);
            extensions.registerFunction ("getstandingpc", 'l', "", opcodeGetStandingPc, opcodeGetStandingPcExplicit);
            extensions.registerFunction ("getstandingactor", 'l', "", opcodeGetStandingActor, opcodeGetStandingActorExplicit);
            extensions.registerFunction ("getwindspeed", 'f', "", opcodeGetWindSpeed);
            extensions.registerFunction ("hitonme", 'l', "S", opcodeHitOnMe, opcodeHitOnMeExplicit);
            extensions.registerInstruction ("disableteleporting", "", opcodeDisableTeleporting);
            extensions.registerInstruction ("enableteleporting", "", opcodeEnableTeleporting);
        }

        void installOpcodes (Interpreter::Interpreter& interpreter)
        {
            interpreter.installSegment5 (opcodeXBox, new OpXBox);
            interpreter.installSegment5 (opcodeOnActivate, new OpOnActivate);
            interpreter.installSegment5 (opcodeActivate, new OpActivate);
            interpreter.installSegment3 (opcodeLock, new OpLock<ImplicitRef>);
            interpreter.installSegment3 (opcodeLockExplicit, new OpLock<ExplicitRef>);
            interpreter.installSegment5 (opcodeUnlock, new OpUnlock<ImplicitRef>);
            interpreter.installSegment5 (opcodeUnlockExplicit, new OpUnlock<ExplicitRef>);
            interpreter.installSegment5 (opcodeToggleCollisionDebug, new OpToggleCollisionDebug);
            interpreter.installSegment5 (opcodeToggleCollisionBoxes, new OpToggleCollisionBoxes);
            interpreter.installSegment5 (opcodeToggleWireframe, new OpToggleWireframe);
            interpreter.installSegment5 (opcodeFadeIn, new OpFadeIn);
            interpreter.installSegment5 (opcodeFadeOut, new OpFadeOut);
            interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo);
            interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid);
            interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater);
            interpreter.installSegment5 (opcodeDontSaveObject, new OpDontSaveObject);
            interpreter.installSegment5 (opcodeToggleVanityMode, new OpToggleVanityMode);
            interpreter.installSegment5 (opcodeGetPcSleep, new OpGetPcSleep);
            interpreter.installSegment5 (opcodeWakeUpPc, new OpWakeUpPc);
            interpreter.installSegment5 (opcodePlayBink, new OpPlayBink);
            interpreter.installSegment5 (opcodeGetLocked, new OpGetLocked<ImplicitRef>);
            interpreter.installSegment5 (opcodeGetLockedExplicit, new OpGetLocked<ExplicitRef>);
            interpreter.installSegment5 (opcodeGetEffect, new OpGetEffect<ImplicitRef>);
            interpreter.installSegment5 (opcodeGetEffectExplicit, new OpGetEffect<ExplicitRef>);
            interpreter.installSegment5 (opcodeAddSoulGem, new OpAddSoulGem<ImplicitRef>);
            interpreter.installSegment5 (opcodeAddSoulGemExplicit, new OpAddSoulGem<ExplicitRef>);
            interpreter.installSegment5 (opcodeRemoveSoulGem, new OpRemoveSoulGem<ImplicitRef>);
            interpreter.installSegment5 (opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem<ExplicitRef>);
            interpreter.installSegment5 (opcodeDrop, new OpDrop<ImplicitRef>);
            interpreter.installSegment5 (opcodeDropExplicit, new OpDrop<ExplicitRef>);
            interpreter.installSegment5 (opcodeDropSoulGem, new OpDropSoulGem<ImplicitRef>);
            interpreter.installSegment5 (opcodeDropSoulGemExplicit, new OpDropSoulGem<ExplicitRef>);
            interpreter.installSegment5 (opcodeGetAttacked, new OpGetAttacked<ImplicitRef>);
            interpreter.installSegment5 (opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>);
            interpreter.installSegment5 (opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>);
            interpreter.installSegment5 (opcodeGetWeaponDrawnExplicit, new OpGetWeaponDrawn<ExplicitRef>);
            interpreter.installSegment5 (opcodeGetSpellEffects, new OpGetSpellEffects<ImplicitRef>);
            interpreter.installSegment5 (opcodeGetSpellEffectsExplicit, new OpGetSpellEffects<ExplicitRef>);
            interpreter.installSegment5 (opcodeGetCurrentTime, new OpGetCurrentTime);
            interpreter.installSegment5 (opcodeSetDelete, new OpSetDelete<ImplicitRef>);
            interpreter.installSegment5 (opcodeSetDeleteExplicit, new OpSetDelete<ExplicitRef>);
            interpreter.installSegment5 (opcodeGetSquareRoot, new OpGetSquareRoot);
            interpreter.installSegment5 (opcodeFall, new OpFall<ImplicitRef>);
            interpreter.installSegment5 (opcodeFallExplicit, new OpFall<ExplicitRef>);
            interpreter.installSegment5 (opcodeGetStandingPc, new OpGetStandingPc<ImplicitRef>);
            interpreter.installSegment5 (opcodeGetStandingPcExplicit, new OpGetStandingPc<ExplicitRef>);
            interpreter.installSegment5 (opcodeGetStandingActor, new OpGetStandingActor<ImplicitRef>);
            interpreter.installSegment5 (opcodeGetStandingActorExplicit, new OpGetStandingActor<ExplicitRef>);
            interpreter.installSegment5 (opcodeGetWindSpeed, new OpGetWindSpeed);
            interpreter.installSegment5 (opcodeHitOnMe, new OpHitOnMe<ImplicitRef>);
            interpreter.installSegment5 (opcodeHitOnMeExplicit, new OpHitOnMe<ExplicitRef>);
            interpreter.installSegment5 (opcodeDisableTeleporting, new OpEnableTeleporting<false>);
            interpreter.installSegment5 (opcodeEnableTeleporting, new OpEnableTeleporting<true>);
        }
    }
}
