#include "miscextensions.hpp" #include #include #include #include #include #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 (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 (runtime.getContext()); MWWorld::Ptr ptr = context.getReference(); context.executeActivation(); } }; template 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 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 (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 (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 (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 (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 (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 OpGetLocked : public Interpreter::Opcode0 { public: virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); runtime.push (ptr.getCellRef ().mLockLevel > 0); } }; template 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 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().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 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 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 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 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 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 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 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 OpFall : public Interpreter::Opcode0 { public: virtual void execute (Interpreter::Runtime& runtime) { } }; template 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 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()); } }; 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; 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); } 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); interpreter.installSegment3 (opcodeLockExplicit, new OpLock); interpreter.installSegment5 (opcodeUnlock, new OpUnlock); interpreter.installSegment5 (opcodeUnlockExplicit, new OpUnlock); 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); interpreter.installSegment5 (opcodeGetLockedExplicit, new OpGetLocked); interpreter.installSegment5 (opcodeGetEffect, new OpGetEffect); interpreter.installSegment5 (opcodeGetEffectExplicit, new OpGetEffect); interpreter.installSegment5 (opcodeAddSoulGem, new OpAddSoulGem); interpreter.installSegment5 (opcodeAddSoulGemExplicit, new OpAddSoulGem); interpreter.installSegment5 (opcodeRemoveSoulGem, new OpRemoveSoulGem); interpreter.installSegment5 (opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem); interpreter.installSegment5 (opcodeDrop, new OpDrop); interpreter.installSegment5 (opcodeDropExplicit, new OpDrop); interpreter.installSegment5 (opcodeDropSoulGem, new OpDropSoulGem); interpreter.installSegment5 (opcodeDropSoulGemExplicit, new OpDropSoulGem); interpreter.installSegment5 (opcodeGetAttacked, new OpGetAttacked); interpreter.installSegment5 (opcodeGetAttackedExplicit, new OpGetAttacked); interpreter.installSegment5 (opcodeGetWeaponDrawn, new OpGetWeaponDrawn); interpreter.installSegment5 (opcodeGetWeaponDrawnExplicit, new OpGetWeaponDrawn); interpreter.installSegment5 (opcodeGetSpellEffects, new OpGetSpellEffects); interpreter.installSegment5 (opcodeGetSpellEffectsExplicit, new OpGetSpellEffects); interpreter.installSegment5 (opcodeGetCurrentTime, new OpGetCurrentTime); interpreter.installSegment5 (opcodeSetDelete, new OpSetDelete); interpreter.installSegment5 (opcodeSetDeleteExplicit, new OpSetDelete); interpreter.installSegment5 (opcodeGetSquareRoot, new OpGetSquareRoot); interpreter.installSegment5 (opcodeFall, new OpFall); interpreter.installSegment5 (opcodeFallExplicit, new OpFall); interpreter.installSegment5 (opcodeGetStandingPc, new OpGetStandingPc); interpreter.installSegment5 (opcodeGetStandingPcExplicit, new OpGetStandingPc); interpreter.installSegment5 (opcodeGetStandingActor, new OpGetStandingActor); interpreter.installSegment5 (opcodeGetStandingActorExplicit, new OpGetStandingActor); interpreter.installSegment5 (opcodeGetWindSpeed, new OpGetWindSpeed); } } }