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()
: mWorld(NULL), mDebug (false), mSoundManager (0), mScriptManager (0), mScriptContext (0)
: mWorld(NULL), mDebug (false), mVerboseScripts (false), mSoundManager (0), mScriptManager (0),
mScriptContext (0)
{
mspCommandServer.reset(
new OMW::CommandServer::Server(&mCommandQueue, kCommandServerPort));

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

@ -17,6 +17,26 @@ namespace MWSound
{
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
{
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
{
public:
@ -55,25 +194,43 @@ namespace MWSound
const int opcodePlaySoundVP = 0x2000005;
const int opcodePlaySound3D = 0x2000006;
const int opcodePlaySound3DVP = 0x2000007;
const int opcodeStopSound = 0x2000008;
const int opcodeGetSoundPlaying = 0x2000009;
const int opcodePlayLoopSound3D = 0x2000008;
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)
{
extensions.registerInstruction ("say", "SS", Script::opcodeSay);
extensions.registerFunction ("saydone", 'l', "", Script::opcodeSayDone);
extensions.registerFunction ("getsoundplaying", 'l', "S", Script::opcodeGetSoundPlaying);
extensions.registerInstruction ("streammusic", "S", Script::opcodeStreamMusic);
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)
{
interpreter.installSegment5 (Script::opcodeSay, new Script::OpSay);
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);
}
}

@ -35,7 +35,7 @@ namespace MWSound
}
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
<< "sound effect: playing sound " << soundId

@ -50,7 +50,7 @@ namespace MWSound
///< Play a sound, independently of 3D-position
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
void stopSound3D (MWWorld::Ptr reference, const std::string& soundId,

@ -31,7 +31,18 @@ namespace Compiler
argumentType = iter->second.mArguments;
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,
const std::string& argumentType, int segment5code)
{
@ -48,7 +59,23 @@ namespace Compiler
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)
const
{
@ -57,6 +84,18 @@ namespace Compiler
if (iter==mFunctions.end())
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;
int mCode;
};
struct Instruction
{
std::string mArguments;
int mCode;
};
int mNextKeywordIndex;
std::map<std::string, int> mKeywords;
std::map<int, Function> mFunctions;
std::map<int, Instruction> mInstructions;
public:
@ -36,6 +43,9 @@ namespace Compiler
bool isFunction (int keyword, char& returnType, std::string& argumentType) const;
///< Is this keyword registered with a function? If yes, return return and argument
/// 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,
const std::string& argumentType, int segment5code);
@ -44,9 +54,20 @@ namespace Compiler
/// - keyword must be unique
/// \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)
const;
///< 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 "locals.hpp"
#include "generator.hpp"
#include "extensions.hpp"
namespace Compiler
{
@ -135,6 +136,21 @@ namespace Compiler
mState = EndState;
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)
{

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

Loading…
Cancel
Save