added missing sound script functionality; various script-related bug-fixes

actorid
Marc Zinnschlag 15 years ago
parent eeeb9b09f8
commit 5d46fc869c

@ -57,7 +57,8 @@ void OMW::Engine::processCommands()
} }
OMW::Engine::Engine() OMW::Engine::Engine()
: mWorld(NULL), mDebug (false), mSoundManager (0), mScriptManager (0), mScriptContext (0) : mWorld(NULL), mDebug (false), mVerboseScripts (false), mSoundManager (0), mScriptManager (0),
mScriptContext (0)
{ {
mspCommandServer.reset( mspCommandServer.reset(
new OMW::CommandServer::Server(&mCommandQueue, kCommandServerPort)); new OMW::CommandServer::Server(&mCommandQueue, kCommandServerPort));

@ -17,6 +17,8 @@
#include "../mwsound/extensions.hpp" #include "../mwsound/extensions.hpp"
#include "cellextensions.hpp"
namespace MWScript namespace MWScript
{ {
ScriptManager::ScriptManager (const ESMS::ESMStore& store, bool verbose, ScriptManager::ScriptManager (const ESMS::ESMStore& store, bool verbose,
@ -104,9 +106,13 @@ namespace MWScript
installOpcodes (interpreter); installOpcodes (interpreter);
interpreter.run (&iter->second[0], iter->second.size()); interpreter.run (&iter->second[0], iter->second.size());
} }
catch (...) catch (const std::exception& e)
{ {
std::cerr << "exeution of script " << name << " failed." << std::endl; std::cerr << "exeution of script " << name << " failed." << std::endl;
if (mVerbose)
std::cerr << "(" << e.what() << ")" << std::endl;
iter->second.clear(); // don't execute again. iter->second.clear(); // don't execute again.
} }
} }
@ -114,6 +120,7 @@ namespace MWScript
void ScriptManager::installOpcodes (Interpreter::Interpreter& interpreter) void ScriptManager::installOpcodes (Interpreter::Interpreter& interpreter)
{ {
Interpreter::installOpcodes (interpreter); Interpreter::installOpcodes (interpreter);
Cell::installOpcodes (interpreter);
MWSound::installOpcodes (interpreter); MWSound::installOpcodes (interpreter);
} }
} }

@ -17,6 +17,26 @@ namespace MWSound
{ {
namespace Script namespace Script
{ {
class OpSay : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string file = runtime.getStringLiteral (runtime[0]);
runtime.pop();
std::string text = runtime.getStringLiteral (runtime[0]);
runtime.pop();
context.getSoundManager().say (context.getReference(), file, text,
context);
}
};
class OpSayDone : public Interpreter::Opcode0 class OpSayDone : public Interpreter::Opcode0
{ {
public: public:
@ -31,6 +51,125 @@ namespace MWSound
} }
}; };
class OpStreamMusic : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string sound = runtime.getStringLiteral (runtime[0]);
runtime.pop();
context.getSoundManager().streamMusic (sound, context);
}
};
class OpPlaySound : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string sound = runtime.getStringLiteral (runtime[0]);
runtime.pop();
context.getSoundManager().playSound (sound, 1.0, 1.0, context);
}
};
class OpPlaySoundVP : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string sound = runtime.getStringLiteral (runtime[0]);
runtime.pop();
float volume = *reinterpret_cast<float *> (&runtime[0]);
runtime.pop();
float pitch = *reinterpret_cast<float *> (&runtime[0]);
runtime.pop();
context.getSoundManager().playSound (sound, volume, pitch, context);
}
};
class OpPlaySound3D : public Interpreter::Opcode0
{
bool mLoop;
public:
OpPlaySound3D (bool loop) : mLoop (loop) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string sound = runtime.getStringLiteral (runtime[0]);
runtime.pop();
context.getSoundManager().playSound3D (context.getReference(), sound,
1.0, 1.0, mLoop, context);
}
};
class OpPlaySoundVP3D : public Interpreter::Opcode0
{
bool mLoop;
public:
OpPlaySoundVP3D (bool loop) : mLoop (loop) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string sound = runtime.getStringLiteral (runtime[0]);
runtime.pop();
float volume = *reinterpret_cast<float *> (&runtime[0]);
runtime.pop();
float pitch = *reinterpret_cast<float *> (&runtime[0]);
runtime.pop();
context.getSoundManager().playSound3D (context.getReference(), sound, volume,
pitch, mLoop, context);
}
};
class OpStopSound : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
std::string sound = runtime.getStringLiteral (runtime[0]);
runtime.pop();
context.getSoundManager().stopSound3D (context.getReference(), sound, context);
}
};
class OpGetSoundPlaying : public Interpreter::Opcode0 class OpGetSoundPlaying : public Interpreter::Opcode0
{ {
public: public:
@ -55,25 +194,43 @@ namespace MWSound
const int opcodePlaySoundVP = 0x2000005; const int opcodePlaySoundVP = 0x2000005;
const int opcodePlaySound3D = 0x2000006; const int opcodePlaySound3D = 0x2000006;
const int opcodePlaySound3DVP = 0x2000007; const int opcodePlaySound3DVP = 0x2000007;
const int opcodeStopSound = 0x2000008; const int opcodePlayLoopSound3D = 0x2000008;
const int opcodeGetSoundPlaying = 0x2000009; const int opcodePlayLoopSound3DVP = 0x2000009;
const int opcodeStopSound = 0x200000a;
const int opcodeGetSoundPlaying = 0x200000b;
} }
// TODO opcodeSay, opcodeStreamMusic, opcodePlaySound, opcodePlaySoundVP,
// opcodePlaySound, opcodePlaySound, opcodeStopSound
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
extensions.registerInstruction ("say", "SS", Script::opcodeSay);
extensions.registerFunction ("saydone", 'l', "", Script::opcodeSayDone); extensions.registerFunction ("saydone", 'l', "", Script::opcodeSayDone);
extensions.registerInstruction ("streammusic", "S", Script::opcodeStreamMusic);
extensions.registerFunction ("getsoundplaying", 'l', "S", Script::opcodeGetSoundPlaying); extensions.registerInstruction ("playsound", "S", Script::opcodePlaySound);
extensions.registerInstruction ("playsoundvp", "Sll", Script::opcodePlaySoundVP);
extensions.registerInstruction ("playsound3d", "S", Script::opcodePlaySound3D);
extensions.registerInstruction ("playsound3dvp", "Sll", Script::opcodePlaySound3DVP);
extensions.registerInstruction ("playloopsound3d", "S", Script::opcodePlayLoopSound3D);
extensions.registerInstruction ("playloopsound3dvp", "Sll",
Script::opcodePlayLoopSound3DVP);
extensions.registerInstruction ("stopsound", "S", Script::opcodeStopSound);
extensions.registerFunction ("getsoundplaying", 'l', "S", Script::opcodeGetSoundPlaying);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
{ {
interpreter.installSegment5 (Script::opcodeSay, new Script::OpSay);
interpreter.installSegment5 (Script::opcodeSayDone, new Script::OpSayDone); interpreter.installSegment5 (Script::opcodeSayDone, new Script::OpSayDone);
interpreter.installSegment5 (Script::opcodeStreamMusic, new Script::OpStreamMusic);
interpreter.installSegment5 (Script::opcodePlaySound, new Script::OpPlaySound);
interpreter.installSegment5 (Script::opcodePlaySoundVP, new Script::OpPlaySoundVP);
interpreter.installSegment5 (Script::opcodePlaySound3D, new Script::OpPlaySound3D (false));
interpreter.installSegment5 (Script::opcodePlaySound3DVP,
new Script::OpPlaySoundVP3D (false));
interpreter.installSegment5 (Script::opcodePlayLoopSound3D,
new Script::OpPlaySound3D (true));
interpreter.installSegment5 (Script::opcodePlayLoopSound3DVP,
new Script::OpPlaySoundVP3D (true));
interpreter.installSegment5 (Script::opcodeStopSound, new Script::OpStopSound);
interpreter.installSegment5 (Script::opcodeGetSoundPlaying, new Script::OpGetSoundPlaying); interpreter.installSegment5 (Script::opcodeGetSoundPlaying, new Script::OpGetSoundPlaying);
} }
} }

@ -35,7 +35,7 @@ namespace MWSound
} }
void SoundManager::playSound3D (MWWorld::Ptr reference, const std::string& soundId, void SoundManager::playSound3D (MWWorld::Ptr reference, const std::string& soundId,
float volume, float pitch, Interpreter::Context& context) float volume, float pitch, bool loop, Interpreter::Context& context)
{ {
std::cout std::cout
<< "sound effect: playing sound " << soundId << "sound effect: playing sound " << soundId

@ -50,7 +50,7 @@ namespace MWSound
///< Play a sound, independently of 3D-position ///< Play a sound, independently of 3D-position
void playSound3D (MWWorld::Ptr reference, const std::string& soundId, void playSound3D (MWWorld::Ptr reference, const std::string& soundId,
float volume, float pitch, Interpreter::Context& context); float volume, float pitch, bool loop, Interpreter::Context& context);
///< Play a sound from an object ///< Play a sound from an object
void stopSound3D (MWWorld::Ptr reference, const std::string& soundId, void stopSound3D (MWWorld::Ptr reference, const std::string& soundId,

@ -31,7 +31,18 @@ namespace Compiler
argumentType = iter->second.mArguments; argumentType = iter->second.mArguments;
return true; return true;
} }
bool Extensions::isInstruction (int keyword, std::string& argumentType) const
{
std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword);
if (iter==mInstructions.end())
return false;
argumentType = iter->second.mArguments;
return true;
}
void Extensions::registerFunction (const std::string& keyword, char returnType, void Extensions::registerFunction (const std::string& keyword, char returnType,
const std::string& argumentType, int segment5code) const std::string& argumentType, int segment5code)
{ {
@ -48,7 +59,23 @@ namespace Compiler
mFunctions.insert (std::make_pair (code, function)); mFunctions.insert (std::make_pair (code, function));
} }
void Extensions::registerInstruction (const std::string& keyword,
const std::string& argumentType, int segment5code)
{
assert (segment5code>=33554432 && segment5code<=67108863);
int code = mNextKeywordIndex--;
mKeywords.insert (std::make_pair (keyword, code));
Instruction instruction;
instruction.mArguments = argumentType;
instruction.mCode = segment5code;
mInstructions.insert (std::make_pair (code, instruction));
}
void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code) void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code)
const const
{ {
@ -57,6 +84,18 @@ namespace Compiler
if (iter==mFunctions.end()) if (iter==mFunctions.end())
throw std::logic_error ("unknown custom function keyword"); throw std::logic_error ("unknown custom function keyword");
Generator::segment5 (iter->second.mCode); code.push_back (Generator::segment5 (iter->second.mCode));
} }
void Extensions::generateInstructionCode (int keyword,
std::vector<Interpreter::Type_Code>& code)
const
{
std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword);
if (iter==mInstructions.end())
throw std::logic_error ("unknown custom instruction keyword");
code.push_back (Generator::segment5 (iter->second.mCode));
}
} }

@ -19,10 +19,17 @@ namespace Compiler
std::string mArguments; std::string mArguments;
int mCode; int mCode;
}; };
struct Instruction
{
std::string mArguments;
int mCode;
};
int mNextKeywordIndex; int mNextKeywordIndex;
std::map<std::string, int> mKeywords; std::map<std::string, int> mKeywords;
std::map<int, Function> mFunctions; std::map<int, Function> mFunctions;
std::map<int, Instruction> mInstructions;
public: public:
@ -36,6 +43,9 @@ namespace Compiler
bool isFunction (int keyword, char& returnType, std::string& argumentType) const; bool isFunction (int keyword, char& returnType, std::string& argumentType) const;
///< Is this keyword registered with a function? If yes, return return and argument ///< Is this keyword registered with a function? If yes, return return and argument
/// types. /// types.
bool isInstruction (int keyword, std::string& argumentType) const;
///< Is this keyword registered with a function? If yes, return argument types.
void registerFunction (const std::string& keyword, char returnType, void registerFunction (const std::string& keyword, char returnType,
const std::string& argumentType, int segment5code); const std::string& argumentType, int segment5code);
@ -44,9 +54,20 @@ namespace Compiler
/// - keyword must be unique /// - keyword must be unique
/// \note Currently only segment 5 opcodes are supported. /// \note Currently only segment 5 opcodes are supported.
void registerInstruction (const std::string& keyword,
const std::string& argumentType, int segment5code);
///< Register a custom instruction
/// - keyword must be all lower case.
/// - keyword must be unique
/// \note Currently only segment 5 opcodes are supported.
void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code) void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code)
const; const;
///< Append code for function to \a code. ///< Append code for function to \a code.
void generateInstructionCode (int keyword, std::vector<Interpreter::Type_Code>& code)
const;
///< Append code for function to \a code.
}; };
} }

@ -7,6 +7,7 @@
#include "skipparser.hpp" #include "skipparser.hpp"
#include "locals.hpp" #include "locals.hpp"
#include "generator.hpp" #include "generator.hpp"
#include "extensions.hpp"
namespace Compiler namespace Compiler
{ {
@ -135,6 +136,21 @@ namespace Compiler
mState = EndState; mState = EndState;
return true; return true;
} }
// check for custom extensions
if (const Extensions *extensions = getContext().getExtensions())
{
std::string argumentType;
if (extensions->isInstruction (keyword, argumentType))
{
mExprParser.parseArguments (argumentType, scanner, mCode, true);
extensions->generateInstructionCode (keyword, mCode);
mState = EndState;
return true;
}
}
} }
else if (mState==SetLocalVarState && keyword==Scanner::K_to) else if (mState==SetLocalVarState && keyword==Scanner::K_to)
{ {

@ -76,7 +76,7 @@ namespace Interpreter
if (iter==mSegment3.end()) if (iter==mSegment3.end())
abortUnknownCode (3, opcode); abortUnknownCode (3, opcode);
iter->second->execute (mRuntime, arg0); iter->second->execute (mRuntime, arg0);
return; return;
@ -106,7 +106,7 @@ namespace Interpreter
if (iter==mSegment5.end()) if (iter==mSegment5.end())
abortUnknownCode (5, opcode); abortUnknownCode (5, opcode);
iter->second->execute (mRuntime); iter->second->execute (mRuntime);
return; return;

Loading…
Cancel
Save